From fac09bc7caa96ac1108da9697be15e15c061b782 Mon Sep 17 00:00:00 2001 From: Ricardo Antunes Date: Mon, 30 Oct 2023 10:34:36 +0000 Subject: [PATCH] feat(ecs): add negative tags --- .../cubos/core/ecs/system/dispatcher.hpp | 4 ++++ core/src/cubos/core/ecs/system/dispatcher.cpp | 17 ++++++++++++++ core/tests/ecs/dispatcher.cpp | 23 +++++++++++++++++++ engine/include/cubos/engine/cubos.hpp | 22 +++++++++++++----- engine/src/cubos/engine/cubos.cpp | 18 +++++++++++---- 5 files changed, 73 insertions(+), 11 deletions(-) diff --git a/core/include/cubos/core/ecs/system/dispatcher.hpp b/core/include/cubos/core/ecs/system/dispatcher.hpp index 96b01d113..ddc63904b 100644 --- a/core/include/cubos/core/ecs/system/dispatcher.hpp +++ b/core/include/cubos/core/ecs/system/dispatcher.hpp @@ -61,6 +61,10 @@ namespace cubos::core::ecs /// @param tag Tag to add. void addTag(const std::string& tag); + /// @brief Adds a tag, and sets it as the current negative tag for further settings. + /// @param tag Tag to add. + void addNegativeTag(const std::string& tag); + /// @brief Makes the current tag inherit the settings of another tag. /// @param tag Tag to inherit from. void tagInheritTag(const std::string& tag); diff --git a/core/src/cubos/core/ecs/system/dispatcher.cpp b/core/src/cubos/core/ecs/system/dispatcher.cpp index 61be65f90..569a89f38 100644 --- a/core/src/cubos/core/ecs/system/dispatcher.cpp +++ b/core/src/cubos/core/ecs/system/dispatcher.cpp @@ -23,10 +23,18 @@ Dispatcher::~Dispatcher() void Dispatcher::addTag(const std::string& tag) { + CUBOS_ASSERT(!tag.starts_with('!'), "Tags starting with '!' are reserved for internal use"); ENSURE_TAG_SETTINGS(tag); mCurrTag = tag; } +void Dispatcher::addNegativeTag(const std::string& tag) +{ + CUBOS_ASSERT(!tag.starts_with('!'), "Tags starting with '!' are reserved for internal use"); + ENSURE_TAG_SETTINGS('!' + tag); + mCurrTag = '!' + tag; +} + void Dispatcher::tagInheritTag(const std::string& tag) { ENSURE_CURR_TAG(); @@ -110,6 +118,15 @@ void Dispatcher::compileChain() // Implement system tag settings with custom settings for (System* system : mPendingSystems) { + // Add negative tags when the system doesn't have the respective positive tags + for (auto& [tag, settings] : mTagSettings) + { + if (tag.starts_with('!') && !system->tags.contains(tag.substr(1))) + { + system->tags.insert(tag); + } + } + for (const auto& tag : system->tags) { if (!system->settings) diff --git a/core/tests/ecs/dispatcher.cpp b/core/tests/ecs/dispatcher.cpp index abc0a7a65..b78c9403b 100644 --- a/core/tests/ecs/dispatcher.cpp +++ b/core/tests/ecs/dispatcher.cpp @@ -102,6 +102,21 @@ TEST_CASE("ecs::Dispatcher") dispatcher.tagSetBeforeTag("2"); // "3" runs before "2" } + SUBCASE("with constraints on negative tags") + { + dispatcher.addSystem(pushToOrder<1>); + dispatcher.systemAddTag("1"); + dispatcher.addSystem(pushToOrder<2>); + dispatcher.systemAddTag("2"); + dispatcher.addSystem(pushToOrder<3>); + dispatcher.systemAddTag("3"); + + dispatcher.addNegativeTag("1"); + dispatcher.tagSetBeforeTag("1"); // anything without "1" runs before "1" + dispatcher.addNegativeTag("3"); + dispatcher.tagSetAfterTag("3"); // anything without "3" runs after "3" + } + singleDispatch(dispatcher, world, cmdBuffer); assertOrder(world, {3, 2, 1}); } @@ -138,6 +153,14 @@ TEST_CASE("ecs::Dispatcher") dispatcher.tagSetAfterTag("1"); // Repeat dispatcher.tagSetBeforeTag("2"); // "3" runs before "2" - redundant dispatcher.tagSetBeforeTag("2"); // Repeat + + dispatcher.addNegativeTag("1"); + dispatcher.tagSetAfterTag("1"); // "2" and "3" run after "1" - redundant + dispatcher.tagSetAfterTag("1"); // Repeat + + dispatcher.addNegativeTag("2"); + dispatcher.tagSetBeforeTag("2"); // "1" and "3" run before "2" - redundant + dispatcher.tagSetBeforeTag("2"); // Repeat } singleDispatch(dispatcher, world, cmdBuffer); diff --git a/engine/include/cubos/engine/cubos.hpp b/engine/include/cubos/engine/cubos.hpp index 419083659..4b6082374 100644 --- a/engine/include/cubos/engine/cubos.hpp +++ b/engine/include/cubos/engine/cubos.hpp @@ -165,16 +165,26 @@ namespace cubos::engine template Cubos& addEvent(); - /// @brief Returns a @ref TagBuilder to configure the given tag. - /// @param tag Tag to configure. - /// @return @ref TagBuilder used to configure the tag. + /// @brief Returns a @ref TagBuilder to configure the systems with the given tag. + /// @param tag Tag. + /// @return @ref TagBuilder. TagBuilder tag(const std::string& tag); - /// @brief Returns a @ref TagBuilder to configure the given startup tag. - /// @param tag Tag to configure. - /// @return @ref TagBuilder used to configure the tag. + /// @brief Returns a @ref TagBuilder to configure the systems with the given startup tag. + /// @param tag Tag. + /// @return @ref TagBuilder. TagBuilder startupTag(const std::string& tag); + /// @brief Returns a @ref TagBuilder to configure the systems without the given tag. + /// @param tag Tag. + /// @return @ref TagBuilder. + TagBuilder noTag(const std::string& tag); + + /// @brief Returns a @ref TagBuilder to configure the systems without the given startup tag. + /// @param tag Tag. + /// @return @ref TagBuilder. + TagBuilder noStartupTag(const std::string& tag); + /// @brief Adds a new system to the engine, which will be executed at every iteration of /// the main loop. /// @tparam F Type of the system function. diff --git a/engine/src/cubos/engine/cubos.cpp b/engine/src/cubos/engine/cubos.cpp index f0f32b939..41e8d36b4 100644 --- a/engine/src/cubos/engine/cubos.cpp +++ b/engine/src/cubos/engine/cubos.cpp @@ -98,17 +98,25 @@ Cubos& Cubos::addPlugin(void (*func)(Cubos&)) TagBuilder Cubos::tag(const std::string& tag) { mMainDispatcher.addTag(tag); - TagBuilder builder(mMainDispatcher, mMainTags); - - return builder; + return TagBuilder{mMainDispatcher, mMainTags}; } TagBuilder Cubos::startupTag(const std::string& tag) { mStartupDispatcher.addTag(tag); - TagBuilder builder(mStartupDispatcher, mStartupTags); + return TagBuilder{mStartupDispatcher, mStartupTags}; +} + +TagBuilder Cubos::noTag(const std::string& tag) +{ + mMainDispatcher.addNegativeTag(tag); + return TagBuilder{mMainDispatcher, mMainTags}; +} - return builder; +TagBuilder Cubos::noStartupTag(const std::string& tag) +{ + mStartupDispatcher.addNegativeTag(tag); + return TagBuilder{mStartupDispatcher, mStartupTags}; } Cubos::Cubos()