From f4824f5e7e6cee12bec602f3240770945a73d043 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Fri, 6 Dec 2024 17:13:59 +0100 Subject: add more fetching functions to ComponentManager --- src/crepe/api/Script.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/crepe/api/Script.h') diff --git a/src/crepe/api/Script.h b/src/crepe/api/Script.h index 1b339b0..5862bae 100644 --- a/src/crepe/api/Script.h +++ b/src/crepe/api/Script.h @@ -84,6 +84,13 @@ protected: template RefVector get_components() const; + /** + * \copydoc ComponentManager::get_components_by_id + * \see ComponentManager::get_components_by_id + */ + template + RefVector get_components_by_id(game_object_id_t id) const; + /** * \brief Log a message using Log::logf * -- cgit v1.2.3 From 90c6bf03e59fdec64f850310bcbff45ae86f69e3 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Sat, 7 Dec 2024 14:18:54 +0100 Subject: more script utilities --- src/crepe/api/Script.h | 12 ++++++++ src/crepe/api/Script.hpp | 27 +++++++++++++++--- src/crepe/manager/ComponentManager.h | 20 ++++++++++++++ src/crepe/manager/ComponentManager.hpp | 23 ++++++++++++++++ src/test/CMakeLists.txt | 1 + src/test/ECSTest.cpp | 50 ++++++++++++++++++++++++++++++++-- src/test/ScriptECSTest.cpp | 42 ++++++++++++++++++++++++++++ src/test/ScriptEventTest.cpp | 2 +- src/test/ScriptSceneTest.cpp | 3 +- src/test/ScriptTest.cpp | 3 +- src/test/ScriptTest.h | 2 ++ 11 files changed, 175 insertions(+), 10 deletions(-) create mode 100644 src/test/ScriptECSTest.cpp (limited to 'src/crepe/api/Script.h') diff --git a/src/crepe/api/Script.h b/src/crepe/api/Script.h index 5862bae..a040608 100644 --- a/src/crepe/api/Script.h +++ b/src/crepe/api/Script.h @@ -90,6 +90,18 @@ protected: */ template RefVector get_components_by_id(game_object_id_t id) const; + /** + * \copydoc ComponentManager::get_components_by_name + * \see ComponentManager::get_components_by_name + */ + template + RefVector get_components_by_name(const std::string & name) const; + /** + * \copydoc ComponentManager::get_components_by_tag + * \see ComponentManager::get_components_by_tag + */ + template + RefVector get_components_by_tag(const std::string & tag) const; /** * \brief Log a message using Log::logf diff --git a/src/crepe/api/Script.hpp b/src/crepe/api/Script.hpp index 45f1ff1..16e0dc5 100644 --- a/src/crepe/api/Script.hpp +++ b/src/crepe/api/Script.hpp @@ -20,10 +20,7 @@ T & Script::get_component() const { template RefVector Script::get_components() const { - Mediator & mediator = this->mediator; - ComponentManager & mgr = mediator.component_manager; - - return mgr.get_components_by_id(this->game_object_id); + return this->get_components_by_id(this->game_object_id); } template @@ -56,4 +53,26 @@ void Script::subscribe(const EventHandler & callback) { this->subscribe_internal(callback, EventManager::CHANNEL_ALL); } +template +RefVector Script::get_components_by_id(game_object_id_t id) const { + Mediator & mediator = this->mediator; + ComponentManager & mgr = mediator.component_manager; + + return mgr.get_components_by_id(id); +} +template +RefVector Script::get_components_by_name(const std::string & name) const { + Mediator & mediator = this->mediator; + ComponentManager & mgr = mediator.component_manager; + + return mgr.get_components_by_name(name); +} +template +RefVector Script::get_components_by_tag(const std::string & tag) const { + Mediator & mediator = this->mediator; + ComponentManager & mgr = mediator.component_manager; + + return mgr.get_components_by_tag(tag); +} + } // namespace crepe diff --git a/src/crepe/manager/ComponentManager.h b/src/crepe/manager/ComponentManager.h index 5f2cf3c..4e53954 100644 --- a/src/crepe/manager/ComponentManager.h +++ b/src/crepe/manager/ComponentManager.h @@ -135,10 +135,30 @@ public: */ template RefVector get_components_by_type() const; + /** + * \brief Get all components of a specific type on a GameObject with name \c name + * + * \tparam T The type of the component + * \param name Metadata::name for the same game_object_id as the returned components + * \return Components matching criteria + */ + template + RefVector get_components_by_name(const std::string & name) const; + /** + * \brief Get all components of a specific type on a GameObject with tag \c tag + * + * \tparam T The type of the component + * \param name Metadata::tag for the same game_object_id as the returned components + * \return Components matching criteria + */ + template + RefVector get_components_by_tag(const std::string & tag) const; private: template std::set get_objects_by_predicate(const std::function & pred) const; + template + RefVector get_components_by_ids(const std::set & ids) const; std::set get_objects_by_name(const std::string & name) const; std::set get_objects_by_tag(const std::string & tag) const; diff --git a/src/crepe/manager/ComponentManager.hpp b/src/crepe/manager/ComponentManager.hpp index 25c2747..52df368 100644 --- a/src/crepe/manager/ComponentManager.hpp +++ b/src/crepe/manager/ComponentManager.hpp @@ -167,4 +167,27 @@ std::set ComponentManager::get_objects_by_predicate(const std: return objects; } +template +RefVector ComponentManager::get_components_by_ids(const std::set & ids) const { + using namespace std; + + RefVector out = {}; + for (game_object_id_t id : ids) { + RefVector components = get_components_by_id(id); + out.insert(out.end(), components.begin(), components.end()); + } + + return out; +} + +template +RefVector ComponentManager::get_components_by_name(const std::string & name) const { + return this->get_components_by_ids(this->get_objects_by_name(name)); +} + +template +RefVector ComponentManager::get_components_by_tag(const std::string & tag) const { + return this->get_components_by_ids(this->get_objects_by_tag(tag)); +} + } // namespace crepe diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index e19d7de..43f564a 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -15,4 +15,5 @@ target_sources(test_main PUBLIC InputTest.cpp ScriptEventTest.cpp ScriptSceneTest.cpp + ScriptECSTest.cpp ) diff --git a/src/test/ECSTest.cpp b/src/test/ECSTest.cpp index a169b3b..ed5341e 100644 --- a/src/test/ECSTest.cpp +++ b/src/test/ECSTest.cpp @@ -17,6 +17,10 @@ class ECSTest : public ::testing::Test { public: ComponentManager mgr{m}; + + class TestComponent : public Component { + using Component::Component; + }; }; TEST_F(ECSTest, createGameObject) { @@ -389,7 +393,7 @@ TEST_F(ECSTest, resetPersistent) { EXPECT_EQ(transform.size(), 0); } -TEST_F(ECSTest, GetByName) { +TEST_F(ECSTest, IDByName) { GameObject foo = mgr.new_object("foo"); GameObject bar = mgr.new_object("bar"); @@ -405,7 +409,7 @@ TEST_F(ECSTest, GetByName) { } } -TEST_F(ECSTest, GetByTag) { +TEST_F(ECSTest, IDByTag) { GameObject foo = mgr.new_object("foo", "common tag"); GameObject bar = mgr.new_object("bar", "common tag"); @@ -421,3 +425,45 @@ TEST_F(ECSTest, GetByTag) { EXPECT_TRUE(objects.contains(bar.id)); } } + +TEST_F(ECSTest, ComponentsByName) { + GameObject foo = mgr.new_object("foo"); + foo.add_component(); + GameObject bar = mgr.new_object("bar"); + bar.add_component(); + bar.add_component(); + + { + auto objects = mgr.get_components_by_name(""); + EXPECT_EQ(objects.size(), 0); + } + + { + auto objects = mgr.get_components_by_name("foo"); + EXPECT_EQ(objects.size(), 1); + } + + { + auto objects = mgr.get_components_by_name("bar"); + EXPECT_EQ(objects.size(), 2); + } +} + +TEST_F(ECSTest, ComponentsByTag) { + GameObject foo = mgr.new_object("foo", "common tag"); + foo.add_component(); + GameObject bar = mgr.new_object("bar", "common tag"); + bar.add_component(); + bar.add_component(); + + { + auto objects = mgr.get_components_by_tag(""); + EXPECT_EQ(objects.size(), 0); + } + + { + auto objects = mgr.get_components_by_tag("common tag"); + EXPECT_EQ(objects.size(), 3); + } +} + diff --git a/src/test/ScriptECSTest.cpp b/src/test/ScriptECSTest.cpp new file mode 100644 index 0000000..4477e55 --- /dev/null +++ b/src/test/ScriptECSTest.cpp @@ -0,0 +1,42 @@ +#include + +#define protected public + +#include +#include +#include +#include +#include +#include + +#include "ScriptTest.h" + +using namespace std; +using namespace crepe; +using namespace testing; + +class ScriptECSTest : public ScriptTest { +public: + class TestComponent : public Component { + using Component::Component; + }; +}; + +TEST_F(ScriptECSTest, GetOwnComponent) { + MyScript & script = this->script; + Metadata & metadata = script.get_component(); + + EXPECT_EQ(metadata.name, OBJ_NAME); +} + +TEST_F(ScriptECSTest, GetOwnComponents) { + const unsigned COUNT = 4; + + for (unsigned i = 0; i < COUNT; i++) + entity.add_component(); + + MyScript & script = this->script; + RefVector components = script.get_components(); + + EXPECT_EQ(components.size(), COUNT); +} diff --git a/src/test/ScriptEventTest.cpp b/src/test/ScriptEventTest.cpp index 5da31e7..c1b4028 100644 --- a/src/test/ScriptEventTest.cpp +++ b/src/test/ScriptEventTest.cpp @@ -26,7 +26,7 @@ public: class MyEvent : public Event {}; }; -TEST_F(ScriptEventTest, Inactive) { +TEST_F(ScriptEventTest, Default) { BehaviorScript & behaviorscript = this->behaviorscript; MyScript & script = this->script; EventManager & evmgr = this->event_manager; diff --git a/src/test/ScriptSceneTest.cpp b/src/test/ScriptSceneTest.cpp index 9ee1e52..8e849c1 100644 --- a/src/test/ScriptSceneTest.cpp +++ b/src/test/ScriptSceneTest.cpp @@ -18,7 +18,7 @@ public: class MyScene : public Scene {}; }; -TEST_F(ScriptSceneTest, Inactive) { +TEST_F(ScriptSceneTest, Default) { BehaviorScript & behaviorscript = this->behaviorscript; MyScript & script = this->script; @@ -28,3 +28,4 @@ TEST_F(ScriptSceneTest, Inactive) { script.set_next_scene(non_default_value); EXPECT_EQ(non_default_value, scene_manager.next_scene); } + diff --git a/src/test/ScriptTest.cpp b/src/test/ScriptTest.cpp index 1d2d6dd..b0b2546 100644 --- a/src/test/ScriptTest.cpp +++ b/src/test/ScriptTest.cpp @@ -6,7 +6,6 @@ #define protected public #include "ScriptTest.h" -#include using namespace std; using namespace crepe; @@ -14,7 +13,6 @@ using namespace testing; void ScriptTest::SetUp() { auto & mgr = this->component_manager; - GameObject entity = mgr.new_object("name"); BehaviorScript & component = entity.add_component(); this->behaviorscript = component; @@ -75,3 +73,4 @@ TEST_F(ScriptTest, UpdateInactive) { system.update(); } } + diff --git a/src/test/ScriptTest.h b/src/test/ScriptTest.h index 1bbfdd3..309e016 100644 --- a/src/test/ScriptTest.h +++ b/src/test/ScriptTest.h @@ -11,10 +11,12 @@ class ScriptTest : public testing::Test { protected: crepe::Mediator mediator; + static constexpr const char * OBJ_NAME = "foo"; public: crepe::ComponentManager component_manager{mediator}; crepe::ScriptSystem system{mediator}; + crepe::GameObject entity = component_manager.new_object(OBJ_NAME); class MyScript : public crepe::Script { // NOTE: explicitly stating `public:` is not required on actual scripts -- cgit v1.2.3 From 2e6fcb1d048edd13a2ec69ddd226fc8ebabc2389 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Sat, 7 Dec 2024 16:01:19 +0100 Subject: add SaveManager to Script --- src/crepe/api/Script.cpp | 11 +++++++---- src/crepe/api/Script.h | 4 ++++ src/crepe/api/Script.hpp | 6 ++---- src/crepe/util/OptionalRef.h | 10 +++++++++- src/crepe/util/OptionalRef.hpp | 7 +++++++ src/test/CMakeLists.txt | 1 + src/test/ScriptSaveManagerTest.cpp | 36 ++++++++++++++++++++++++++++++++++++ 7 files changed, 66 insertions(+), 9 deletions(-) create mode 100644 src/test/ScriptSaveManagerTest.cpp (limited to 'src/crepe/api/Script.h') diff --git a/src/crepe/api/Script.cpp b/src/crepe/api/Script.cpp index 4091fd4..961e6e7 100644 --- a/src/crepe/api/Script.cpp +++ b/src/crepe/api/Script.cpp @@ -8,8 +8,7 @@ using namespace crepe; using namespace std; Script::~Script() { - Mediator & mediator = this->mediator; - EventManager & mgr = mediator.event_manager; + EventManager & mgr = this->mediator->event_manager; for (auto id : this->listeners) { mgr.unsubscribe(id); } @@ -21,7 +20,11 @@ void Script::subscribe(const EventHandler & callback) { } void Script::set_next_scene(const string & name) { - Mediator & mediator = this->mediator; - SceneManager & mgr = mediator.scene_manager; + SceneManager & mgr = this->mediator->scene_manager; mgr.set_next_scene(name); } + +SaveManager & Script::get_save_manager() const { + return this->mediator->save_manager; +} + diff --git a/src/crepe/api/Script.h b/src/crepe/api/Script.h index d99ab0e..024f1d7 100644 --- a/src/crepe/api/Script.h +++ b/src/crepe/api/Script.h @@ -7,6 +7,7 @@ #include "../system/CollisionSystem.h" #include "../types.h" #include "../util/OptionalRef.h" +#include "../ValueBroker.h" namespace crepe { @@ -113,6 +114,9 @@ protected: */ void set_next_scene(const std::string & name); + //! Retrieve SaveManager reference + SaveManager & get_save_manager() const; + //! \} private: diff --git a/src/crepe/api/Script.hpp b/src/crepe/api/Script.hpp index 45f1ff1..23d69d9 100644 --- a/src/crepe/api/Script.hpp +++ b/src/crepe/api/Script.hpp @@ -20,8 +20,7 @@ T & Script::get_component() const { template RefVector Script::get_components() const { - Mediator & mediator = this->mediator; - ComponentManager & mgr = mediator.component_manager; + ComponentManager & mgr = this->mediator->component_manager; return mgr.get_components_by_id(this->game_object_id); } @@ -34,8 +33,7 @@ void Script::logf(Args &&... args) { template void Script::subscribe_internal(const EventHandler & callback, event_channel_t channel) { - Mediator & mediator = this->mediator; - EventManager & mgr = mediator.event_manager; + EventManager & mgr = this->mediator->event_manager; subscription_t listener = mgr.subscribe( [this, callback](const EventType & data) -> bool { bool & active = this->active; diff --git a/src/crepe/util/OptionalRef.h b/src/crepe/util/OptionalRef.h index 3201667..1b2cb3f 100644 --- a/src/crepe/util/OptionalRef.h +++ b/src/crepe/util/OptionalRef.h @@ -25,13 +25,21 @@ public: */ OptionalRef & operator=(T & ref); /** - * \brief Retrieve this reference + * \brief Retrieve this reference (cast) * * \returns Internal reference if it is set * * \throws std::runtime_error if this function is called while the reference it not set */ operator T &() const; + /** + * \brief Retrieve this reference (member access) + * + * \returns Internal reference if it is set + * + * \throws std::runtime_error if this function is called while the reference it not set + */ + T * operator->() const; /** * \brief Check if this reference is not empty * diff --git a/src/crepe/util/OptionalRef.hpp b/src/crepe/util/OptionalRef.hpp index 4608c9e..5e36b3a 100644 --- a/src/crepe/util/OptionalRef.hpp +++ b/src/crepe/util/OptionalRef.hpp @@ -18,6 +18,13 @@ OptionalRef::operator T &() const { return *this->ref; } +template +T * OptionalRef::operator->() const { + if (this->ref == nullptr) + throw std::runtime_error("OptionalRef: attempt to dereference nullptr"); + return this->ref; +} + template OptionalRef & OptionalRef::operator=(T & ref) { this->ref = &ref; diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 734e3ee..2cb7c7a 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -18,4 +18,5 @@ target_sources(test_main PUBLIC ScriptSceneTest.cpp Profiling.cpp SaveManagerTest.cpp + ScriptSaveManagerTest.cpp ) diff --git a/src/test/ScriptSaveManagerTest.cpp b/src/test/ScriptSaveManagerTest.cpp new file mode 100644 index 0000000..098afa0 --- /dev/null +++ b/src/test/ScriptSaveManagerTest.cpp @@ -0,0 +1,36 @@ +#include + +// stupid hack to allow access to private/protected members under test +#define private public +#define protected public + +#include +#include + +#include "ScriptTest.h" + +using namespace std; +using namespace crepe; +using namespace testing; + +class ScriptSaveManagerTest : public ScriptTest { +public: + class TestSaveManager : public SaveManager { + using SaveManager::SaveManager; + + // in-memory database for testing + DB db{}; + virtual DB & get_db() override { return this->db; } + }; + + TestSaveManager save_mgr{mediator}; +}; + +TEST_F(ScriptSaveManagerTest, GetSaveManager) { + MyScript & script = this->script; + + SaveManager & mgr = script.get_save_manager(); + + EXPECT_EQ(&mgr, &save_mgr); +} + -- cgit v1.2.3 From dd8bbe2fde97786ab29490bc7ba9962deb08fb4c Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Sat, 7 Dec 2024 16:01:59 +0100 Subject: `make format` --- src/crepe/api/Script.cpp | 5 +---- src/crepe/api/Script.h | 2 +- src/test/SaveManagerTest.cpp | 5 ++--- src/test/ScriptSaveManagerTest.cpp | 3 +-- 4 files changed, 5 insertions(+), 10 deletions(-) (limited to 'src/crepe/api/Script.h') diff --git a/src/crepe/api/Script.cpp b/src/crepe/api/Script.cpp index 961e6e7..753a9e3 100644 --- a/src/crepe/api/Script.cpp +++ b/src/crepe/api/Script.cpp @@ -24,7 +24,4 @@ void Script::set_next_scene(const string & name) { mgr.set_next_scene(name); } -SaveManager & Script::get_save_manager() const { - return this->mediator->save_manager; -} - +SaveManager & Script::get_save_manager() const { return this->mediator->save_manager; } diff --git a/src/crepe/api/Script.h b/src/crepe/api/Script.h index 024f1d7..0d59ab6 100644 --- a/src/crepe/api/Script.h +++ b/src/crepe/api/Script.h @@ -2,12 +2,12 @@ #include +#include "../ValueBroker.h" #include "../manager/EventManager.h" #include "../manager/Mediator.h" #include "../system/CollisionSystem.h" #include "../types.h" #include "../util/OptionalRef.h" -#include "../ValueBroker.h" namespace crepe { diff --git a/src/test/SaveManagerTest.cpp b/src/test/SaveManagerTest.cpp index a1efc33..e9b0c29 100644 --- a/src/test/SaveManagerTest.cpp +++ b/src/test/SaveManagerTest.cpp @@ -1,8 +1,8 @@ #include -#include -#include #include +#include +#include using namespace std; using namespace crepe; @@ -38,4 +38,3 @@ TEST_F(SaveManagerTest, DefaultValue) { value.set(5); ASSERT_EQ(value.get(), 5); } - diff --git a/src/test/ScriptSaveManagerTest.cpp b/src/test/ScriptSaveManagerTest.cpp index 098afa0..64403c4 100644 --- a/src/test/ScriptSaveManagerTest.cpp +++ b/src/test/ScriptSaveManagerTest.cpp @@ -4,8 +4,8 @@ #define private public #define protected public -#include #include +#include #include "ScriptTest.h" @@ -33,4 +33,3 @@ TEST_F(ScriptSaveManagerTest, GetSaveManager) { EXPECT_EQ(&mgr, &save_mgr); } - -- cgit v1.2.3 From b5bf36aec3caa879d77457e3b2d1d29b6b625f27 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Sat, 7 Dec 2024 16:03:47 +0100 Subject: minor cleanup --- src/crepe/api/Script.h | 1 - src/crepe/manager/SaveManager.h | 7 ------- 2 files changed, 8 deletions(-) (limited to 'src/crepe/api/Script.h') diff --git a/src/crepe/api/Script.h b/src/crepe/api/Script.h index 0d59ab6..3417bb4 100644 --- a/src/crepe/api/Script.h +++ b/src/crepe/api/Script.h @@ -2,7 +2,6 @@ #include -#include "../ValueBroker.h" #include "../manager/EventManager.h" #include "../manager/Mediator.h" #include "../system/CollisionSystem.h" diff --git a/src/crepe/manager/SaveManager.h b/src/crepe/manager/SaveManager.h index d13a97a..1b55a22 100644 --- a/src/crepe/manager/SaveManager.h +++ b/src/crepe/manager/SaveManager.h @@ -91,16 +91,9 @@ private: template T deserialize(const std::string & value) const noexcept; -public: - SaveManager(const SaveManager &) = delete; - SaveManager(SaveManager &&) = delete; - SaveManager & operator=(const SaveManager &) = delete; - SaveManager & operator=(SaveManager &&) = delete; - protected: //! Create or return DB virtual DB & get_db(); - private: //! Database std::unique_ptr db = nullptr; -- cgit v1.2.3