mirror of
https://github.com/BlackMATov/ecs.hpp.git
synced 2025-12-15 03:05:25 +07:00
world: for_each_component
This commit is contained in:
64
ecs.hpp
64
ecs.hpp
@@ -98,16 +98,28 @@ namespace ecs_hpp
|
||||
template < typename T >
|
||||
class component_storage : public component_storage_base {
|
||||
public:
|
||||
component_storage(world& owner);
|
||||
|
||||
template < typename... Args >
|
||||
void assign(entity_id id, Args&&... args);
|
||||
bool remove(entity_id id) noexcept override;
|
||||
bool exists(entity_id id) const noexcept override;
|
||||
T* find(entity_id id) noexcept;
|
||||
const T* find(entity_id id) const noexcept;
|
||||
|
||||
template < typename F >
|
||||
void for_each_component(F&& f) noexcept;
|
||||
template < typename F >
|
||||
void for_each_component(F&& f) const noexcept;
|
||||
private:
|
||||
world& owner_;
|
||||
std::unordered_map<entity_id, T> components_;
|
||||
};
|
||||
|
||||
template < typename T >
|
||||
component_storage<T>::component_storage(world& owner)
|
||||
: owner_(owner) {}
|
||||
|
||||
template < typename T >
|
||||
template < typename... Args >
|
||||
void component_storage<T>::assign(entity_id id, Args&&... args) {
|
||||
@@ -139,6 +151,22 @@ namespace ecs_hpp
|
||||
? &iter->second
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
template < typename F >
|
||||
void component_storage<T>::for_each_component(F&& f) noexcept {
|
||||
for ( auto& component_pair : components_ ) {
|
||||
f(entity(owner_, component_pair.first), component_pair.second);
|
||||
}
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
template < typename F >
|
||||
void component_storage<T>::for_each_component(F&& f) const noexcept {
|
||||
for ( auto& component_pair : components_ ) {
|
||||
f(entity(owner_, component_pair.first), component_pair.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,6 +286,12 @@ namespace ecs_hpp
|
||||
|
||||
template < typename T >
|
||||
const T* find_component(const entity& ent) const noexcept;
|
||||
|
||||
template < typename T, typename F >
|
||||
void for_each_component(F&& f) noexcept;
|
||||
|
||||
template < typename T, typename F >
|
||||
void for_each_component(F&& f) const noexcept;
|
||||
private:
|
||||
template < typename T >
|
||||
detail::component_storage<T>* find_storage_() noexcept;
|
||||
@@ -436,7 +470,9 @@ namespace ecs_hpp
|
||||
|
||||
template < typename T >
|
||||
T& world::get_component(const entity& ent) {
|
||||
T* component = find_component<T>(ent);
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
detail::component_storage<T>* storage = find_storage_<T>();
|
||||
T* component = storage ? storage->find(ent.id()) : nullptr;
|
||||
if ( component ) {
|
||||
return *component;
|
||||
}
|
||||
@@ -445,7 +481,9 @@ namespace ecs_hpp
|
||||
|
||||
template < typename T >
|
||||
const T& world::get_component(const entity& ent) const {
|
||||
const T* component = find_component<T>(ent);
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
const detail::component_storage<T>* storage = find_storage_<T>();
|
||||
const T* component = storage ? storage->find(ent.id()) : nullptr;
|
||||
if ( component ) {
|
||||
return *component;
|
||||
}
|
||||
@@ -454,6 +492,7 @@ namespace ecs_hpp
|
||||
|
||||
template < typename T >
|
||||
T* world::find_component(const entity& ent) noexcept {
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
detail::component_storage<T>* storage = find_storage_<T>();
|
||||
return storage
|
||||
? storage->find(ent.id())
|
||||
@@ -462,12 +501,31 @@ namespace ecs_hpp
|
||||
|
||||
template < typename T >
|
||||
const T* world::find_component(const entity& ent) const noexcept {
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
const detail::component_storage<T>* storage = find_storage_<T>();
|
||||
return storage
|
||||
? storage->find(ent.id())
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
template < typename T, typename F >
|
||||
void world::for_each_component(F&& f) noexcept {
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
detail::component_storage<T>* storage = find_storage_<T>();
|
||||
if ( storage ) {
|
||||
storage->for_each_component(std::forward<F>(f));
|
||||
}
|
||||
}
|
||||
|
||||
template < typename T, typename F >
|
||||
void world::for_each_component(F&& f) const noexcept {
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
const detail::component_storage<T>* storage = find_storage_<T>();
|
||||
if ( storage ) {
|
||||
storage->for_each_component(std::forward<F>(f));
|
||||
}
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
detail::component_storage<T>* world::find_storage_() noexcept {
|
||||
const auto family = detail::type_family<T>::id();
|
||||
@@ -497,7 +555,7 @@ namespace ecs_hpp
|
||||
const auto family = detail::type_family<T>::id();
|
||||
const auto emplace_r = storages_.emplace(std::make_pair(
|
||||
family,
|
||||
std::make_unique<detail::component_storage<T>>()));
|
||||
std::make_unique<detail::component_storage<T>>(*this)));
|
||||
assert(emplace_r.second && "unexpected internal error");
|
||||
return *static_cast<detail::component_storage<T>*>(
|
||||
emplace_r.first->second.get());
|
||||
|
||||
@@ -181,6 +181,9 @@ TEST_CASE("world") {
|
||||
w.assign_component<position_c>(e1, 1, 2);
|
||||
w.assign_component<velocity_c>(e2, 3, 4);
|
||||
|
||||
REQUIRE(e1.find_component<position_c>()->y == 2);
|
||||
REQUIRE(e2.find_component<velocity_c>()->dy == 4);
|
||||
|
||||
{
|
||||
const ecs::world& ww = w;
|
||||
REQUIRE(ww.get_component<position_c>(e1).x == 1);
|
||||
@@ -191,6 +194,48 @@ TEST_CASE("world") {
|
||||
|
||||
REQUIRE_THROWS_AS(ww.get_component<velocity_c>(e1), ecs::basic_exception);
|
||||
REQUIRE_THROWS_AS(ww.get_component<position_c>(e2), ecs::basic_exception);
|
||||
|
||||
ww.remove_all_components(e1);
|
||||
ww.remove_all_components(e2);
|
||||
|
||||
REQUIRE_FALSE(ww.find_component<position_c>(e1));
|
||||
REQUIRE_FALSE(ww.find_component<velocity_c>(e2));
|
||||
}
|
||||
}
|
||||
}
|
||||
SECTION("for_each_component") {
|
||||
{
|
||||
ecs::world w;
|
||||
|
||||
auto e1 = w.create_entity();
|
||||
auto e2 = w.create_entity();
|
||||
|
||||
e1.assign_component<position_c>(1, 2);
|
||||
e1.assign_component<velocity_c>(3, 4);
|
||||
e2.assign_component<position_c>(5, 6);
|
||||
e2.assign_component<velocity_c>(7, 8);
|
||||
|
||||
{
|
||||
ecs::entity_id acc1 = 0;
|
||||
int acc2 = 0;
|
||||
w.for_each_component<position_c>([&acc1, &acc2](ecs::entity e, position_c& p){
|
||||
acc1 += e.id();
|
||||
acc2 += p.x;
|
||||
});
|
||||
REQUIRE(acc1 == e1.id() + e2.id());
|
||||
REQUIRE(acc2 == 6);
|
||||
}
|
||||
|
||||
{
|
||||
const ecs::world& ww = w;
|
||||
ecs::entity_id acc1 = 0;
|
||||
int acc2 = 0;
|
||||
ww.for_each_component<position_c>([&acc1, &acc2](ecs::entity e, const position_c& p){
|
||||
acc1 += e.id();
|
||||
acc2 += p.x;
|
||||
});
|
||||
REQUIRE(acc1 == e1.id() + e2.id());
|
||||
REQUIRE(acc2 == 6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user