From 1c71e3fd788a495c47b8a8d176845e7dba104541 Mon Sep 17 00:00:00 2001 From: Ubpa <641614112@qq.com> Date: Thu, 30 Jul 2020 00:16:18 +0800 Subject: [PATCH] IListener --- CMakeLists.txt | 2 +- include/UECS/EntityMngr.h | 4 + include/UECS/IListener.h | 32 ++++++ include/UECS/SystemMngr.h | 3 + include/UECS/World.h | 4 + src/core/EntityMngr.cpp | 18 +++ src/core/SystemMngr.cpp | 14 +++ src/core/World.cpp | 9 ++ src/test/14_serialize/CMakeLists.txt | 6 + src/test/14_serialize/main.cpp | 162 +++++++++++++++++++++++++++ 10 files changed, 253 insertions(+), 1 deletion(-) create mode 100644 include/UECS/IListener.h create mode 100644 src/core/SystemMngr.cpp create mode 100644 src/test/14_serialize/CMakeLists.txt create mode 100644 src/test/14_serialize/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 967f8f7..9db9ebf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.14 FATAL_ERROR) -project(UECS VERSION 0.9.6) +project(UECS VERSION 0.9.7) message(STATUS "[Project] ${PROJECT_NAME}") include(cmake/InitUCMake.cmake) diff --git a/include/UECS/EntityMngr.h b/include/UECS/EntityMngr.h index 7b1dc85..f524317 100644 --- a/include/UECS/EntityMngr.h +++ b/include/UECS/EntityMngr.h @@ -12,6 +12,8 @@ namespace Ubpa { class World; + class IListener; + // Entity Manager of World // auto maintain Component's lifecycle ({default|copy|move} constructor, destructor) // [API] @@ -77,6 +79,8 @@ namespace Ubpa { void AddCommand(const std::function& command); + void Accept(IListener* listener) const; + private: friend class World; EntityMngr() = default; diff --git a/include/UECS/IListener.h b/include/UECS/IListener.h new file mode 100644 index 0000000..3c9598c --- /dev/null +++ b/include/UECS/IListener.h @@ -0,0 +1,32 @@ +#pragma once + +#include + +namespace Ubpa { + class World; + class SystemMngr; + class EntityMngr; + class Entity; + class CmptPtr; + + class IListener { + public: + virtual void EnterWorld(const World* w) = 0; + virtual void ExistWorld(const World* w) = 0; + + virtual void EnterSystemMngr(const SystemMngr* sm) = 0; + virtual void ExistSystemMngr(const SystemMngr* sm) = 0; + + virtual void EnterSystem(std::string_view s) = 0; + virtual void ExistSystem(std::string_view s) = 0; + + virtual void EnterEntityMngr(const EntityMngr* em) = 0; + virtual void ExistEntityMngr(const EntityMngr* em) = 0; + + virtual void EnterEntity(const Entity* e) = 0; + virtual void ExistEntity(const Entity* e) = 0; + + virtual void EnterCmptPtr(const CmptPtr* cmpt) = 0; + virtual void ExistCmptPtr(const CmptPtr* cmpt) = 0; + }; +} diff --git a/include/UECS/SystemMngr.h b/include/UECS/SystemMngr.h index 935d59b..4d2b2ce 100644 --- a/include/UECS/SystemMngr.h +++ b/include/UECS/SystemMngr.h @@ -5,6 +5,8 @@ #include namespace Ubpa{ + class IListener; + // System Manager // System is a struct with specific function // signature: static void OnUpdate(Schedule&) @@ -27,6 +29,7 @@ namespace Ubpa{ template void Deregister() noexcept; + void Accept(IListener* listener) const; private: template diff --git a/include/UECS/World.h b/include/UECS/World.h index 5e29e80..dc6c1a2 100644 --- a/include/UECS/World.h +++ b/include/UECS/World.h @@ -7,6 +7,8 @@ #include namespace Ubpa { + class IListener; + // SystemMngr + EntityMngr class World { public: @@ -29,6 +31,8 @@ namespace Ubpa { // use RTDCmptTraits' registered component name Graphviz::Graph GenUpdateFrameGraph() const; + void Accept(IListener* listener) const; + private: mutable JobExecutor executor; Schedule schedule; diff --git a/src/core/EntityMngr.cpp b/src/core/EntityMngr.cpp index bee5a31..aa2c750 100644 --- a/src/core/EntityMngr.cpp +++ b/src/core/EntityMngr.cpp @@ -1,5 +1,7 @@ #include +#include + using namespace Ubpa; using namespace std; @@ -283,3 +285,19 @@ void EntityMngr::RunCommands() { command(); commandBuffer.clear(); } + +void EntityMngr::Accept(IListener* listener) const { + listener->EnterEntityMngr(this); + for (const auto& [h, a] : h2a) { + for (size_t i = 0; i < a->EntityNum(); i++) { + auto e = a->At(i); + listener->EnterEntity(e); + for (const auto& cmpt : a->Components(i)) { + listener->EnterCmptPtr(&cmpt); + listener->ExistCmptPtr(&cmpt); + } + listener->ExistEntity(e); + } + } + listener->ExistEntityMngr(this); +} diff --git a/src/core/SystemMngr.cpp b/src/core/SystemMngr.cpp new file mode 100644 index 0000000..759ab01 --- /dev/null +++ b/src/core/SystemMngr.cpp @@ -0,0 +1,14 @@ +#include + +#include + +using namespace Ubpa; + +void SystemMngr::Accept(IListener* listener) const { + listener->EnterSystemMngr(this); + for (const auto& [n, f] : onUpdateMap) { + listener->EnterSystem(n); + listener->ExistSystem(n); + } + listener->ExistSystemMngr(this); +} diff --git a/src/core/World.cpp b/src/core/World.cpp index ee002ce..cec9f4f 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -1,5 +1,7 @@ #include +#include + using namespace Ubpa; using namespace std; @@ -159,3 +161,10 @@ Graphviz::Graph World::GenUpdateFrameGraph() const { return graph; } + +void World::Accept(IListener* listener) const { + listener->EnterWorld(this); + systemMngr.Accept(listener); + entityMngr.Accept(listener); + listener->ExistWorld(this); +} diff --git a/src/test/14_serialize/CMakeLists.txt b/src/test/14_serialize/CMakeLists.txt new file mode 100644 index 0000000..ec4a795 --- /dev/null +++ b/src/test/14_serialize/CMakeLists.txt @@ -0,0 +1,6 @@ +Ubpa_GetTargetName(core "${PROJECT_SOURCE_DIR}/src/core") +Ubpa_AddTarget( + TEST + MODE EXE + LIB ${core} +) diff --git a/src/test/14_serialize/main.cpp b/src/test/14_serialize/main.cpp new file mode 100644 index 0000000..d444c47 --- /dev/null +++ b/src/test/14_serialize/main.cpp @@ -0,0 +1,162 @@ +#include +#include + +#include + +using namespace Ubpa; +using namespace std; + +struct Position { float val; }; +struct Velocity { float val; }; + +class Dumper : public IListener { + size_t indent{ 0 }; + bool firstSystem{ true }; + bool firstEntity{ true }; + bool firstCmpt{ true }; + + void PrintIndent() { + for (size_t i = 0; i < indent; i++) + cout << " "; + } + + // new line + virtual void EnterWorld(const World* w) override { + cout << "{" << endl; + indent++; + PrintIndent(); + cout << "\"type\" : \"World\"," << endl; + } + + virtual void ExistWorld(const World* w) override { + indent--; + cout << "}"; + } + + virtual void EnterSystemMngr(const SystemMngr* sm) override { + PrintIndent(); + cout << "\"systemMngr\" : {" << endl; + indent++; + PrintIndent(); + cout << "\"type\" : \"SystemMngr\"," << endl; + PrintIndent(); + cout << "\"systems\" : ["; + indent++; + firstSystem = true; + } + + virtual void ExistSystemMngr(const SystemMngr* sm) override { + cout << endl; + indent--; + PrintIndent(); + cout << "]" << endl; + indent--; + PrintIndent(); + cout << "}," << endl; + } + + virtual void EnterSystem(std::string_view s) override { + if (!firstSystem) + cout << ","; + else + firstSystem = false; + cout << endl; + PrintIndent(); + cout << "\"" << s << "\""; + } + + virtual void ExistSystem(std::string_view s) override { + + } + + virtual void EnterEntityMngr(const EntityMngr* em) override { + PrintIndent(); + cout << "\"entityMngr\" : {" << endl; + indent++; + PrintIndent(); + cout << "\"type\" : \"EntityMngr\"," << endl; + PrintIndent(); + cout << "\"entities\" : ["; + indent++; + firstEntity = true; + } + + virtual void ExistEntityMngr(const EntityMngr* em) override { + cout << endl; + indent--; + PrintIndent(); + cout << "]" << endl; + indent--; + PrintIndent(); + cout << "}" << endl; + } + + virtual void EnterEntity(const Entity* e) override { + if (!firstEntity) + cout << ","; + else + firstEntity = false; + cout << endl; + PrintIndent(); + cout << "{" << endl; + indent++; + PrintIndent(); + cout << "\"type\" : \"Entity\"," << endl; + PrintIndent(); + cout << "\"components\" : [" << endl; + indent++; + firstCmpt = true; + } + + virtual void ExistEntity(const Entity* e) override { + cout << endl; + indent--; + PrintIndent(); + cout << "]" << endl; + indent--; + PrintIndent(); + cout << "}"; + } + + virtual void EnterCmptPtr(const CmptPtr* cmpt) override { + if (!firstCmpt) + cout << ","; + else + firstCmpt = false; + cout << endl; + PrintIndent(); + cout << "{" << endl; + indent++; + PrintIndent(); + cout << "\"type\" : \"" << RTDCmptTraits::Instance().Nameof(cmpt->Type()) << "\""; + } + + virtual void ExistCmptPtr(const CmptPtr* cmpt) override { + cout << endl; + indent--; + PrintIndent(); + cout << "}"; + } +}; + +struct MoverSystem { + static void OnUpdate(Schedule& schedule) { + schedule.Register( + [](const Velocity* v, Position* p) { + p->val += v->val; + }, "Mover"); + } +}; + +int main() { + World w; + RTDCmptTraits::Instance().Register(); + w.systemMngr.Register(); + w.entityMngr.Create(); + w.entityMngr.Create(); + w.entityMngr.Create(); + w.entityMngr.Create<>(); + w.Update(); + Dumper dumper; + w.Accept(&dumper); +}