From 8d9e112e7af084974797f61c4eb0f3a273d46c5a Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Mon, 11 Mar 2019 20:50:13 +0700 Subject: [PATCH] system processing priority --- README.md | 6 +++--- ecs.hpp | 52 +++++++++++++++++++++++++++++++++++++------- ecs_tests.cpp | 60 ++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 102 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 650f93b..b31f76d 100644 --- a/README.md +++ b/README.md @@ -79,8 +79,8 @@ private: }; ecs_hpp::registry world; -world.add_system(); -world.add_system(9.8f); +world.add_system(0); +world.add_system(1, 9.8f); auto entity_one = world.create_entity(); world.assign_component(entity_one, 4.f, 2.f); @@ -90,7 +90,7 @@ auto entity_two = world.create_entity(); entity_two.assign_component(4.f, 2.f); entity_two.assign_component(10.f, 20.f); -world.process_systems(); +world.process_all_systems(); ``` ## API diff --git a/ecs.hpp b/ecs.hpp index 7acf1ef..313bdb8 100644 --- a/ecs.hpp +++ b/ecs.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -41,6 +42,7 @@ namespace ecs_hpp using family_id = std::uint16_t; using entity_id = std::uint32_t; + using priority_t = std::int32_t; constexpr std::size_t entity_id_index_bits = 22u; constexpr std::size_t entity_id_version_bits = 10u; @@ -1072,8 +1074,12 @@ namespace ecs_hpp void for_joined_components(F&& f) const; template < typename T, typename... Args > - void add_system(Args&&... args); - void process_systems(); + void add_system(priority_t priority, Args&&... args); + + void process_all_systems(); + void process_systems_above(priority_t min); + void process_systems_below(priority_t max); + void process_systems_in_range(priority_t min, priority_t max); private: template < typename T > detail::component_storage* find_storage_() noexcept; @@ -1146,7 +1152,7 @@ namespace ecs_hpp detail::sparse_map storages_; using system_uptr = std::unique_ptr; - std::vector systems_; + std::vector> systems_; }; } @@ -1831,14 +1837,44 @@ namespace ecs_hpp } template < typename T, typename... Args > - void registry::add_system(Args&&... args) { - systems_.emplace_back( + void registry::add_system(priority_t priority, Args&&... args) { + auto iter = std::upper_bound( + systems_.begin(), systems_.end(), priority, + [](priority_t pr, const auto& r){ + return pr < r.first; + }); + systems_.emplace( + iter, + priority, std::make_unique(std::forward(args)...)); } - inline void registry::process_systems() { - for ( auto& s : systems_ ) { - s->process(*this); + inline void registry::process_all_systems() { + process_systems_in_range( + std::numeric_limits::min(), + std::numeric_limits::max()); + } + + inline void registry::process_systems_above(priority_t min) { + process_systems_in_range( + min, + std::numeric_limits::max()); + } + + inline void registry::process_systems_below(priority_t max) { + process_systems_in_range( + std::numeric_limits::min(), + max); + } + + inline void registry::process_systems_in_range(priority_t min, priority_t max) { + const auto first = std::lower_bound( + systems_.begin(), systems_.end(), min, + [](const auto& p, priority_t pr) noexcept { + return p.first < pr; + }); + for ( auto iter = first; iter != systems_.end() && iter->first <= max; ++iter ) { + iter->second->process(*this); } } diff --git a/ecs_tests.cpp b/ecs_tests.cpp index 9c3d0e2..d4944e6 100644 --- a/ecs_tests.cpp +++ b/ecs_tests.cpp @@ -909,7 +909,7 @@ TEST_CASE("registry") { }; ecs::registry w; - w.add_system(); + w.add_system(0); auto e1 = w.create_entity(); auto e2 = w.create_entity(); @@ -919,7 +919,7 @@ TEST_CASE("registry") { e2.assign_component(5, 6); e2.assign_component(7, 8); - w.process_systems(); + w.process_all_systems(); REQUIRE(e1.get_component().x == 1 + 3); REQUIRE(e1.get_component().y == 2 + 4); @@ -927,6 +927,56 @@ TEST_CASE("registry") { REQUIRE(e2.get_component().x == 5 + 7); REQUIRE(e2.get_component().y == 6 + 8); } + { + class system_n : public ecs::system { + public: + system_n(int& i, int n) : i_(i), n_(n) {} + void process(ecs::registry&) override { + i_ += n_; + } + private: + int& i_; + int n_; + }; + + int i = 0; + ecs::registry w; + w.add_system(20, std::ref(i), 2); + w.add_system(10, std::ref(i), 1); + REQUIRE(i == 0); + w.process_all_systems(); + REQUIRE(i == 3); + w.process_systems_below(10); + REQUIRE(i == 4); + w.process_systems_above(20); + REQUIRE(i == 6); + w.process_systems_below(20); + REQUIRE(i == 9); + w.process_systems_above(10); + REQUIRE(i == 12); + + w.process_systems_below(9); + w.process_systems_above(21); + REQUIRE(i == 12); + + w.process_systems_in_range(0, 9); + w.process_systems_in_range(11, 19); + w.process_systems_in_range(21, 30); + REQUIRE(i == 12); + + w.process_systems_in_range(0, 10); + REQUIRE(i == 13); + w.process_systems_in_range(10, 19); + REQUIRE(i == 14); + w.process_systems_in_range(10, 20); + REQUIRE(i == 17); + w.process_systems_in_range(20, 30); + REQUIRE(i == 19); + w.process_systems_in_range(10, 20); + REQUIRE(i == 22); + w.process_systems_in_range(0, 30); + REQUIRE(i == 25); + } } } @@ -976,8 +1026,8 @@ TEST_CASE("example") { }; ecs_hpp::registry world; - world.add_system(); - world.add_system(9.8f); + world.add_system(0); + world.add_system(1, 9.8f); auto entity_one = world.create_entity(); world.assign_component(entity_one, 4.f, 2.f); @@ -987,5 +1037,5 @@ TEST_CASE("example") { entity_two.assign_component(4.f, 2.f); entity_two.assign_component(10.f, 20.f); - world.process_systems(); + world.process_all_systems(); }