From ce2a615ced7eb6d5ae8904e95e7e7547b0880bf7 Mon Sep 17 00:00:00 2001 From: Benjamin Palko Date: Sun, 6 Oct 2024 22:29:42 -0400 Subject: [PATCH 01/10] create components dir --- meson.build | 2 ++ src/components/meson.build | 1 + src/components/shader.cpp | 11 +++++++++++ src/components/shader.hpp | 26 ++++++++++++++++++++++++++ src/meson.build | 4 +++- src/systems/shader-system.cpp | 10 ---------- src/systems/shader-system.hpp | 26 +------------------------- 7 files changed, 44 insertions(+), 36 deletions(-) create mode 100644 src/components/meson.build create mode 100644 src/components/shader.cpp create mode 100644 src/components/shader.hpp diff --git a/meson.build b/meson.build index e6a8aed..19160c9 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,7 @@ project('test', 'cpp') +sources = [] + deps = [] deps += dependency('fmt') deps += dependency('glfw3') diff --git a/src/components/meson.build b/src/components/meson.build new file mode 100644 index 0000000..32f0f06 --- /dev/null +++ b/src/components/meson.build @@ -0,0 +1 @@ +sources += files('shader.cpp', 'shader.hpp') diff --git a/src/components/shader.cpp b/src/components/shader.cpp new file mode 100644 index 0000000..779df45 --- /dev/null +++ b/src/components/shader.cpp @@ -0,0 +1,11 @@ +#include "shader.hpp" + +Shader::Shader(GLuint shader) { this->shader = shader; } +void Shader::SetSource(std::string source) { this->SetSource(source.c_str()); } +void Shader::SetSource(const char *source) { + glShaderSource(shader, 1, &source, NULL); +} +void Shader::Compile() { glCompileShader(shader); } +void Shader::Attach(GLuint program) { glAttachShader(program, shader); } +VertexShader::VertexShader() : Shader(glCreateShader(GL_VERTEX_SHADER)) {} +FragmentShader::FragmentShader() : Shader(glCreateShader(GL_FRAGMENT_SHADER)) {} diff --git a/src/components/shader.hpp b/src/components/shader.hpp new file mode 100644 index 0000000..9ac44e0 --- /dev/null +++ b/src/components/shader.hpp @@ -0,0 +1,26 @@ +#include +#include + +class Shader { +public: + Shader(GLuint shader); + +protected: + GLuint shader; + +public: + void SetSource(std::string source); + void SetSource(const char *source); + void Compile(); + void Attach(GLuint program); +}; + +class VertexShader : public Shader { +public: + VertexShader(); +}; + +class FragmentShader : public Shader { +public: + FragmentShader(); +}; diff --git a/src/meson.build b/src/meson.build index bb1cc6f..8a251b6 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,2 +1,4 @@ -sources = files('main.cpp') +sources += files('main.cpp') + +subdir('components') subdir('systems') diff --git a/src/systems/shader-system.cpp b/src/systems/shader-system.cpp index 3de31da..df3bb63 100644 --- a/src/systems/shader-system.cpp +++ b/src/systems/shader-system.cpp @@ -82,13 +82,3 @@ int ShaderSystem::Draw(int width, int height, float time) { glDrawArrays(GL_TRIANGLES, 0, 3); return 0; } - -Shader::Shader(GLuint shader) { this->shader = shader; } -void Shader::SetSource(std::string source) { this->SetSource(source.c_str()); } -void Shader::SetSource(const char *source) { - glShaderSource(shader, 1, &source, NULL); -} -void Shader::Compile() { glCompileShader(shader); } -void Shader::Attach(GLuint program) { glAttachShader(program, shader); } -VertexShader::VertexShader() : Shader(glCreateShader(GL_VERTEX_SHADER)) {} -FragmentShader::FragmentShader() : Shader(glCreateShader(GL_FRAGMENT_SHADER)) {} diff --git a/src/systems/shader-system.hpp b/src/systems/shader-system.hpp index 145ae75..6bc9345 100644 --- a/src/systems/shader-system.hpp +++ b/src/systems/shader-system.hpp @@ -1,6 +1,6 @@ #include #include -#include +#include "../components/shader.hpp" class ShaderSystem { GLuint vertex_buffer; @@ -15,27 +15,3 @@ public: int Draw(int width, int height, float time); GLuint *CreateBuffer(); }; - -class Shader { -public: - Shader(GLuint shader); - -protected: - GLuint shader; - -public: - void SetSource(std::string source); - void SetSource(const char *source); - void Compile(); - void Attach(GLuint program); -}; - -class VertexShader : public Shader { -public: - VertexShader(); -}; - -class FragmentShader : public Shader { -public: - FragmentShader(); -}; From bfcceba5023277c2e86e0f1ad0c81d498bbd5a0a Mon Sep 17 00:00:00 2001 From: Benjamin Palko Date: Sun, 6 Oct 2024 23:08:39 -0400 Subject: [PATCH 02/10] naming conventions! --- src/main.cpp | 2 +- src/systems/meson.build | 8 ++++---- src/systems/{shader-system.cpp => shadersystem.cpp} | 2 +- src/systems/{shader-system.hpp => shadersystem.hpp} | 0 src/systems/{window-system.cpp => windowsystem.cpp} | 2 +- src/systems/{window-system.hpp => windowsystem.hpp} | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) rename src/systems/{shader-system.cpp => shadersystem.cpp} (98%) rename src/systems/{shader-system.hpp => shadersystem.hpp} (100%) rename src/systems/{window-system.cpp => windowsystem.cpp} (93%) rename src/systems/{window-system.hpp => windowsystem.hpp} (88%) diff --git a/src/main.cpp b/src/main.cpp index b51934e..ddf1bfa 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,7 +2,7 @@ #include #include -#include "systems/window-system.hpp" +#include "systems/windowsystem.hpp" void error_callback(int error_code, const char *description) { fmt::print("[ERROR - {}] {}\n", error_code, description); diff --git a/src/systems/meson.build b/src/systems/meson.build index e42b237..db627d1 100644 --- a/src/systems/meson.build +++ b/src/systems/meson.build @@ -1,6 +1,6 @@ sources += files( - 'shader-system.cpp', - 'shader-system.hpp', - 'window-system.cpp', - 'window-system.hpp', + 'shadersystem.cpp', + 'shadersystem.hpp', + 'windowsystem.cpp', + 'windowsystem.hpp', ) diff --git a/src/systems/shader-system.cpp b/src/systems/shadersystem.cpp similarity index 98% rename from src/systems/shader-system.cpp rename to src/systems/shadersystem.cpp index df3bb63..49083c2 100644 --- a/src/systems/shader-system.cpp +++ b/src/systems/shadersystem.cpp @@ -1,4 +1,4 @@ -#include "shader-system.hpp" +#include "shadersystem.hpp" typedef struct Vertex { vec2 pos; diff --git a/src/systems/shader-system.hpp b/src/systems/shadersystem.hpp similarity index 100% rename from src/systems/shader-system.hpp rename to src/systems/shadersystem.hpp diff --git a/src/systems/window-system.cpp b/src/systems/windowsystem.cpp similarity index 93% rename from src/systems/window-system.cpp rename to src/systems/windowsystem.cpp index 626abc0..3d65a00 100644 --- a/src/systems/window-system.cpp +++ b/src/systems/windowsystem.cpp @@ -1,4 +1,4 @@ -#include "window-system.hpp" +#include "windowsystem.hpp" WindowSystem::WindowSystem(GLFWwindow *window, class ShaderSystem shaderSystem) { diff --git a/src/systems/window-system.hpp b/src/systems/windowsystem.hpp similarity index 88% rename from src/systems/window-system.hpp rename to src/systems/windowsystem.hpp index 9fd6f59..f7de070 100644 --- a/src/systems/window-system.hpp +++ b/src/systems/windowsystem.hpp @@ -1,6 +1,6 @@ #define GLFW_INCLUDE_NONE #include -#include "shader-system.hpp" +#include "shadersystem.hpp" class WindowSystem { GLFWwindow *window; From 38483b4b36065b04e68f90be6d8298bc4bb53f7b Mon Sep 17 00:00:00 2001 From: Benjamin Palko Date: Mon, 7 Oct 2024 12:31:03 -0400 Subject: [PATCH 03/10] hwaa??? --- src/systems/shadersystem.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/systems/shadersystem.hpp b/src/systems/shadersystem.hpp index 6bc9345..d211dee 100644 --- a/src/systems/shadersystem.hpp +++ b/src/systems/shadersystem.hpp @@ -1,6 +1,5 @@ #include #include -#include "../components/shader.hpp" class ShaderSystem { GLuint vertex_buffer; From 4591ad623ecfe9b68e959c40ff777c45ce095ff6 Mon Sep 17 00:00:00 2001 From: Benjamin Palko Date: Mon, 7 Oct 2024 13:21:15 -0400 Subject: [PATCH 04/10] include guard --- src/components/shader.hpp | 6 ++++++ src/systems/shadersystem.hpp | 5 +++++ src/systems/windowsystem.hpp | 5 +++++ 3 files changed, 16 insertions(+) diff --git a/src/components/shader.hpp b/src/components/shader.hpp index 9ac44e0..58c74c1 100644 --- a/src/components/shader.hpp +++ b/src/components/shader.hpp @@ -1,3 +1,7 @@ +#ifndef SHADER_HPP +#define SHADER_HPP + +#define SHADER_HPP #include #include @@ -24,3 +28,5 @@ class FragmentShader : public Shader { public: FragmentShader(); }; + +#endif // SHADER_HPP diff --git a/src/systems/shadersystem.hpp b/src/systems/shadersystem.hpp index d211dee..c8367fb 100644 --- a/src/systems/shadersystem.hpp +++ b/src/systems/shadersystem.hpp @@ -1,3 +1,6 @@ +#ifndef SHADERSYSTEM_HPP +#define SHADERSYSTEM_HPP + #include #include @@ -14,3 +17,5 @@ public: int Draw(int width, int height, float time); GLuint *CreateBuffer(); }; + +#endif // SHADERSYSTEM_HPP diff --git a/src/systems/windowsystem.hpp b/src/systems/windowsystem.hpp index f7de070..ac26f60 100644 --- a/src/systems/windowsystem.hpp +++ b/src/systems/windowsystem.hpp @@ -1,3 +1,6 @@ +#ifndef WINDOWSYSTEM_HPP +#define WINDOWSYSTEM_HPP + #define GLFW_INCLUDE_NONE #include #include "shadersystem.hpp" @@ -10,3 +13,5 @@ public: WindowSystem(GLFWwindow *window, class ShaderSystem shaderSystem); int Loop(); }; + +#endif // WINDOWSYSTEM_HPP From 5273b8017e7b412c6b889e32cef168ab7f402996 Mon Sep 17 00:00:00 2001 From: Benjamin Palko Date: Wed, 9 Oct 2024 11:26:03 -0400 Subject: [PATCH 05/10] implement ECS library --- libs/component.hpp | 13 ++++++++ libs/componentarray.cpp | 47 +++++++++++++++++++++++++++++ libs/componentarray.hpp | 37 +++++++++++++++++++++++ libs/componentmanager.cpp | 63 +++++++++++++++++++++++++++++++++++++++ libs/componentmanager.hpp | 35 ++++++++++++++++++++++ libs/coordinator.cpp | 63 +++++++++++++++++++++++++++++++++++++++ libs/coordinator.hpp | 30 +++++++++++++++++++ libs/entity.cpp | 42 ++++++++++++++++++++++++++ libs/entity.hpp | 31 +++++++++++++++++++ libs/system.cpp | 54 +++++++++++++++++++++++++++++++++ libs/system.hpp | 29 ++++++++++++++++++ 11 files changed, 444 insertions(+) create mode 100644 libs/component.hpp create mode 100644 libs/componentarray.cpp create mode 100644 libs/componentarray.hpp create mode 100644 libs/componentmanager.cpp create mode 100644 libs/componentmanager.hpp create mode 100644 libs/coordinator.cpp create mode 100644 libs/coordinator.hpp create mode 100644 libs/entity.cpp create mode 100644 libs/entity.hpp create mode 100644 libs/system.cpp create mode 100644 libs/system.hpp diff --git a/libs/component.hpp b/libs/component.hpp new file mode 100644 index 0000000..323866e --- /dev/null +++ b/libs/component.hpp @@ -0,0 +1,13 @@ +#ifndef COMPONENT_HPP +#define COMPONENT_HPP + +#include +#include + +using ComponentType = std::uint8_t; + +const ComponentType MAX_COMPONENTS = 32; + +using Signature = std::bitset; + +#endif // COMPONENT_HPP diff --git a/libs/componentarray.cpp b/libs/componentarray.cpp new file mode 100644 index 0000000..3b3b45b --- /dev/null +++ b/libs/componentarray.cpp @@ -0,0 +1,47 @@ +#include +#include "componentarray.hpp" + +template +void ComponentArray::InsertData(Entity entity, T component) { + assert(mEntityToIndexMap.find(entity) == mEntityToIndexMap.end() && + "Component added to same entity more than once."); + + // Put new entry at end and update the maps + size_t newIndex = mSize; + mEntityToIndexMap[entity] = newIndex; + mIndexToEntityMap[newIndex] = entity; + mComponentArray[newIndex] = component; + ++mSize; +}; +template void ComponentArray::RemoveData(Entity entity) { + assert(mEntityToIndexMap.find(entity) != mEntityToIndexMap.end() && + "Removing non-existent component."); + + // Copy element at end into deleted element's place to maintain density + size_t indexOfRemovedEntity = mEntityToIndexMap[entity]; + size_t indexOfLastElement = mSize - 1; + mComponentArray[indexOfRemovedEntity] = mComponentArray[indexOfLastElement]; + + // Update map to point to moved spot + Entity entityOfLastElement = mIndexToEntityMap[indexOfLastElement]; + mEntityToIndexMap[entityOfLastElement] = indexOfRemovedEntity; + mIndexToEntityMap[indexOfRemovedEntity] = entityOfLastElement; + + mEntityToIndexMap.erase(entity); + mIndexToEntityMap.erase(indexOfLastElement); + + --mSize; +}; +template T &ComponentArray::GetData(Entity entity) { + assert(mEntityToIndexMap.find(entity) != mEntityToIndexMap.end() && + "Retrieving non-existent component."); + + // Return a reference to the entity's component + return mComponentArray[mEntityToIndexMap[entity]]; +}; +template void ComponentArray::EntityDestroyed(Entity entity) { + if (mEntityToIndexMap.find(entity) != mEntityToIndexMap.end()) { + // Remove the entity's component if it existed + RemoveData(entity); + } +}; diff --git a/libs/componentarray.hpp b/libs/componentarray.hpp new file mode 100644 index 0000000..f8b10c4 --- /dev/null +++ b/libs/componentarray.hpp @@ -0,0 +1,37 @@ +#ifndef COMPONENTARRAY_HPP +#define COMPONENTARRAY_HPP + +#include +#include +#include "entity.hpp" + +class IComponentArray { +public: + virtual ~IComponentArray() = default; + virtual void EntityDestroyed(Entity entity) = 0; +}; + +template class ComponentArray : public IComponentArray { + // The packed array of components (of generic type T), + // set to a specified maximum amount, matching the maximum number + // of entities allowed to exist simultaneously, so that each entity + // has a unique spot. + std::array mComponentArray; + + // Map from an entity ID to an array index. + std::unordered_map mEntityToIndexMap; + + // Map from an array index to an entity ID. + std::unordered_map mIndexToEntityMap; + + // Total size of valid entries in the array. + size_t mSize; + +public: + void InsertData(Entity entity, T component); + void RemoveData(Entity entity); + T &GetData(Entity entity); + void EntityDestroyed(Entity entity) override; +}; + +#endif // COMPONENTARRAY_HPP diff --git a/libs/componentmanager.cpp b/libs/componentmanager.cpp new file mode 100644 index 0000000..24584db --- /dev/null +++ b/libs/componentmanager.cpp @@ -0,0 +1,63 @@ +#include "componentmanager.hpp" +#include "componentarray.hpp" +#include + +// Private functions +template +std::shared_ptr> ComponentManager::GetComponentArray() { + const char *typeName = typeid(T).name(); + + assert(mComponentTypes.find(typeName) != mComponentTypes.end() && + "Component not registered before use."); + + return std::static_pointer_cast>( + mComponentArrays[typeName]); +} + +// Public functions +template void ComponentManager::RegisterComponent() { + const char *typeName = typeid(T).name(); + + assert(mComponentTypes.find(typeName) == mComponentTypes.end() && + "Registering component type more than once."); + + // Add this component type to the component type map + mComponentTypes.insert({typeName, mNextComponentType}); + + // Create a ComponentArray pointer and add it to the component arrays map + mComponentArrays.insert({typeName, std::make_shared>()}); + + // Increment the value so that the next component registered will be different + ++mNextComponentType; +}; +template ComponentType ComponentManager::GetComponentType() { + const char *typeName = typeid(T).name(); + + assert(mComponentTypes.find(typeName) != mComponentTypes.end() && + "Component not registered before use."); + + // Return this component's type - used for creating signatures + return mComponentTypes[typeName]; +} +template +void ComponentManager::AddComponent(Entity entity, T component) { + // Add a component to the array for an entity + GetComponentArray()->InsertData(entity, component); +} +template void ComponentManager::RemoveComponent(Entity entity) { + // Remove a component from the array for an entity + GetComponentArray()->RemoveData(entity); +} +template T &ComponentManager::GetComponent(Entity entity) { + // Get a reference to a component from the array for an entity + return GetComponentArray()->GetData(entity); +} +void ComponentManager::EntityDestroyed(Entity entity) { + // Notify each component array that an entity has been destroyed + // If it has a component for that entity, it will remove it + for (auto const &pair : mComponentArrays) { + auto const &component = pair.second; + + component->EntityDestroyed(entity); + } +}; diff --git a/libs/componentmanager.hpp b/libs/componentmanager.hpp new file mode 100644 index 0000000..16ab368 --- /dev/null +++ b/libs/componentmanager.hpp @@ -0,0 +1,35 @@ +#ifndef COMPONENTMANAGER_HPP +#define COMPONENTMANAGER_HPP + +#include +#include +#include +#include "component.hpp" +#include "componentarray.hpp" + +class ComponentManager { + // Map from type string pointer to a component type + std::unordered_map mComponentTypes{}; + + // Map from type string pointer to a component array + std::unordered_map> + mComponentArrays{}; + + // The component type to be assigned to the next registered component - + // starting at 0 + ComponentType mNextComponentType{}; + + // Convenience function to get the statically casted pointer to the + // ComponentArray of type T. + template std::shared_ptr> GetComponentArray(); + +public: + template void RegisterComponent(); + template ComponentType GetComponentType(); + template void AddComponent(Entity entity, T component); + template void RemoveComponent(Entity entity); + template T &GetComponent(Entity entity); + void EntityDestroyed(Entity entity); +}; + +#endif // COMPONENTMANAGER_HPP diff --git a/libs/coordinator.cpp b/libs/coordinator.cpp new file mode 100644 index 0000000..af6f545 --- /dev/null +++ b/libs/coordinator.cpp @@ -0,0 +1,63 @@ +#include "coordinator.hpp" + +void Coordinator::Init() { + // Create pointers to each manager + mComponentManager = std::make_unique(); + mEntityManager = std::make_unique(); + mSystemManager = std::make_unique(); +} + +// Entity methods +Entity Coordinator::CreateEntity() { return mEntityManager->CreateEntity(); } + +void Coordinator::DestroyEntity(Entity entity) { + mEntityManager->DestroyEntity(entity); + + mComponentManager->EntityDestroyed(entity); + + mSystemManager->EntityDestroyed(entity); +} + +// Component methods +template void Coordinator::RegisterComponent() { + mComponentManager->RegisterComponent(); +} + +template +void Coordinator::AddComponent(Entity entity, T component) { + mComponentManager->AddComponent(entity, component); + + auto signature = mEntityManager->GetSignature(entity); + signature.set(mComponentManager->GetComponentType(), true); + mEntityManager->SetSignature(entity, signature); + + mSystemManager->EntitySignatureChanged(entity, signature); +} + +template void Coordinator::RemoveComponent(Entity entity) { + mComponentManager->RemoveComponent(entity); + + auto signature = mEntityManager->GetSignature(entity); + signature.set(mComponentManager->GetComponentType(), false); + mEntityManager->SetSignature(entity, signature); + + mSystemManager->EntitySignatureChanged(entity, signature); +} + +template T &Coordinator::GetComponent(Entity entity) { + return mComponentManager->GetComponent(entity); +} + +template ComponentType Coordinator::GetComponentType() { + return mComponentManager->GetComponentType(); +} + +// System methods +template std::shared_ptr Coordinator::RegisterSystem() { + return mSystemManager->RegisterSystem(); +} + +template +void Coordinator::SetSystemSignature(Signature signature) { + mSystemManager->SetSignature(signature); +} diff --git a/libs/coordinator.hpp b/libs/coordinator.hpp new file mode 100644 index 0000000..73f5a36 --- /dev/null +++ b/libs/coordinator.hpp @@ -0,0 +1,30 @@ +#ifndef COORDINATOR_HPP +#define COORDINATOR_HPP + +#include +#include "componentmanager.hpp" +#include "entity.hpp" +#include "system.hpp" + +class Coordinator { + std::unique_ptr mComponentManager; + std::unique_ptr mEntityManager; + std::unique_ptr mSystemManager; + +public: + void Init(); + // Entity methods + Entity CreateEntity(); + void DestroyEntity(Entity entity); + // Component methods + template void RegisterComponent(); + template void AddComponent(Entity entity, T component); + template void RemoveComponent(Entity entity); + template T &GetComponent(Entity entity); + template ComponentType GetComponentType(); + // System methods + template std::shared_ptr RegisterSystem(); + template void SetSystemSignature(Signature signature); +}; + +#endif // COORDINATOR_HPP diff --git a/libs/entity.cpp b/libs/entity.cpp new file mode 100644 index 0000000..83f7262 --- /dev/null +++ b/libs/entity.cpp @@ -0,0 +1,42 @@ +#include "entity.hpp" +#include + +EntityManager::EntityManager() { + // Initialize the queue with all possible entity IDs + for (Entity entity = 0; entity < MAX_ENTITIES; ++entity) { + mAvailableEntities.push(entity); + } +} +Entity EntityManager::CreateEntity() { + assert(mLivingEntityCount < MAX_ENTITIES && + "Too many entities in existence."); + + // Take an ID from the front of the queue + Entity id = mAvailableEntities.front(); + mAvailableEntities.pop(); + ++mLivingEntityCount; + + return id; +} +void EntityManager::DestroyEntity(Entity entity) { + assert(entity < MAX_ENTITIES && "Entity out of range."); + + // Invalidate the destroyed entity's signature + mSignatures[entity].reset(); + + // Put the destroyed ID at the back of the queue + mAvailableEntities.push(entity); + --mLivingEntityCount; +} +void EntityManager::SetSignature(Entity entity, Signature signature) { + assert(entity < MAX_ENTITIES && "Entity out of range."); + + // Put this entity's signature into the array + mSignatures[entity] = signature; +} +Signature EntityManager::GetSignature(Entity entity) { + assert(entity < MAX_ENTITIES && "Entity out of range."); + + // Get this entity's signature from the array + return mSignatures[entity]; +} diff --git a/libs/entity.hpp b/libs/entity.hpp new file mode 100644 index 0000000..e2f7a15 --- /dev/null +++ b/libs/entity.hpp @@ -0,0 +1,31 @@ +#ifndef ENTITY_HPP +#define ENTITY_HPP + +#include +#include +#include +#include "component.hpp" + +using Entity = std::uint32_t; + +const Entity MAX_ENTITIES = 5000; + +class EntityManager { + // Queue of unused entity IDs + std::queue mAvailableEntities{}; + + // Array of signatures where the index corresponds to the entity ID + std::array mSignatures{}; + + // Total living entities - used to keep limits on how many exist + uint32_t mLivingEntityCount{}; + +public: + EntityManager(); + Entity CreateEntity(); + void DestroyEntity(Entity entity); + void SetSignature(Entity entity, Signature signature); + Signature GetSignature(Entity entity); +}; + +#endif // ENTITY_HPP diff --git a/libs/system.cpp b/libs/system.cpp new file mode 100644 index 0000000..a7e4ef4 --- /dev/null +++ b/libs/system.cpp @@ -0,0 +1,54 @@ +#include "system.hpp" + +#include + +template std::shared_ptr SystemManager::RegisterSystem() { + const char *typeName = typeid(T).name(); + + assert(mSystems.find(typeName) == mSystems.end() && + "Registering system more than once."); + + // Create a pointer to the system and return it so it can be used externally + auto system = std::make_shared(); + mSystems.insert({typeName, system}); + return system; +} + +template void SystemManager::SetSignature(Signature signature) { + const char *typeName = typeid(T).name(); + + assert(mSystems.find(typeName) != mSystems.end() && + "System used before registered."); + + // Set the signature for this system + mSignatures.insert({typeName, signature}); +} + +void SystemManager::EntityDestroyed(Entity entity) { + // Erase a destroyed entity from all system lists + // mEntities is a set so no check needed + for (auto const &pair : mSystems) { + auto const &system = pair.second; + + system->mEntities.erase(entity); + } +} + +void SystemManager::EntitySignatureChanged(Entity entity, + Signature entitySignature) { + // Notify each system that an entity's signature changed + for (auto const &pair : mSystems) { + auto const &type = pair.first; + auto const &system = pair.second; + auto const &systemSignature = mSignatures[type]; + + // Entity signature matches system signature - insert into set + if ((entitySignature & systemSignature) == systemSignature) { + system->mEntities.insert(entity); + } + // Entity signature does not match system signature - erase from set + else { + system->mEntities.erase(entity); + } + } +} diff --git a/libs/system.hpp b/libs/system.hpp new file mode 100644 index 0000000..af7e831 --- /dev/null +++ b/libs/system.hpp @@ -0,0 +1,29 @@ +#ifndef SYSTEM_HPP +#define SYSTEM_HPP + +#include +#include +#include +#include "component.hpp" +#include "entity.hpp" + +class System { +public: + std::set mEntities; +}; + +class SystemManager { + // Map from system type string pointer to a signature + std::unordered_map mSignatures{}; + + // Map from system type string pointer to a system pointer + std::unordered_map> mSystems{}; + +public: + template std::shared_ptr RegisterSystem(); + template void SetSignature(Signature signature); + void EntityDestroyed(Entity entity); + void EntitySignatureChanged(Entity entity, Signature entitySignature); +}; + +#endif // !SYSTEM_HPP From 41d6c28be93ddd955bb9237b4485bbfb97172e0e Mon Sep 17 00:00:00 2001 From: Benjamin Palko Date: Wed, 9 Oct 2024 12:54:15 -0400 Subject: [PATCH 06/10] missing includes --- src/systems/shadersystem.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/systems/shadersystem.cpp b/src/systems/shadersystem.cpp index 49083c2..6cf2d01 100644 --- a/src/systems/shadersystem.cpp +++ b/src/systems/shadersystem.cpp @@ -1,4 +1,6 @@ #include "shadersystem.hpp" +#include +#include typedef struct Vertex { vec2 pos; From 888abc495b6ba8828530ad735175a02f880ae49d Mon Sep 17 00:00:00 2001 From: Benjamin Palko Date: Wed, 9 Oct 2024 13:34:54 -0400 Subject: [PATCH 07/10] move to subdir --- libs/{ => ecs}/component.hpp | 0 libs/{ => ecs}/componentarray.cpp | 0 libs/{ => ecs}/componentarray.hpp | 0 libs/{ => ecs}/componentmanager.cpp | 0 libs/{ => ecs}/componentmanager.hpp | 0 libs/{ => ecs}/coordinator.cpp | 0 libs/{ => ecs}/coordinator.hpp | 0 libs/{ => ecs}/entity.cpp | 0 libs/{ => ecs}/entity.hpp | 0 libs/{ => ecs}/system.cpp | 0 libs/{ => ecs}/system.hpp | 0 11 files changed, 0 insertions(+), 0 deletions(-) rename libs/{ => ecs}/component.hpp (100%) rename libs/{ => ecs}/componentarray.cpp (100%) rename libs/{ => ecs}/componentarray.hpp (100%) rename libs/{ => ecs}/componentmanager.cpp (100%) rename libs/{ => ecs}/componentmanager.hpp (100%) rename libs/{ => ecs}/coordinator.cpp (100%) rename libs/{ => ecs}/coordinator.hpp (100%) rename libs/{ => ecs}/entity.cpp (100%) rename libs/{ => ecs}/entity.hpp (100%) rename libs/{ => ecs}/system.cpp (100%) rename libs/{ => ecs}/system.hpp (100%) diff --git a/libs/component.hpp b/libs/ecs/component.hpp similarity index 100% rename from libs/component.hpp rename to libs/ecs/component.hpp diff --git a/libs/componentarray.cpp b/libs/ecs/componentarray.cpp similarity index 100% rename from libs/componentarray.cpp rename to libs/ecs/componentarray.cpp diff --git a/libs/componentarray.hpp b/libs/ecs/componentarray.hpp similarity index 100% rename from libs/componentarray.hpp rename to libs/ecs/componentarray.hpp diff --git a/libs/componentmanager.cpp b/libs/ecs/componentmanager.cpp similarity index 100% rename from libs/componentmanager.cpp rename to libs/ecs/componentmanager.cpp diff --git a/libs/componentmanager.hpp b/libs/ecs/componentmanager.hpp similarity index 100% rename from libs/componentmanager.hpp rename to libs/ecs/componentmanager.hpp diff --git a/libs/coordinator.cpp b/libs/ecs/coordinator.cpp similarity index 100% rename from libs/coordinator.cpp rename to libs/ecs/coordinator.cpp diff --git a/libs/coordinator.hpp b/libs/ecs/coordinator.hpp similarity index 100% rename from libs/coordinator.hpp rename to libs/ecs/coordinator.hpp diff --git a/libs/entity.cpp b/libs/ecs/entity.cpp similarity index 100% rename from libs/entity.cpp rename to libs/ecs/entity.cpp diff --git a/libs/entity.hpp b/libs/ecs/entity.hpp similarity index 100% rename from libs/entity.hpp rename to libs/ecs/entity.hpp diff --git a/libs/system.cpp b/libs/ecs/system.cpp similarity index 100% rename from libs/system.cpp rename to libs/ecs/system.cpp diff --git a/libs/system.hpp b/libs/ecs/system.hpp similarity index 100% rename from libs/system.hpp rename to libs/ecs/system.hpp From ab187a9fa91cc9c9b8063f6222ffe6d97dbfc5a8 Mon Sep 17 00:00:00 2001 From: Benjamin Palko Date: Thu, 10 Oct 2024 14:00:33 -0400 Subject: [PATCH 08/10] merge component array into manager --- libs/ecs/componentarray.cpp | 47 ----------------------------- libs/ecs/componentarray.hpp | 37 ----------------------- libs/ecs/componentmanager.cpp | 56 ++++++++++++++++++++++++++++++++++- libs/ecs/componentmanager.hpp | 33 +++++++++++++++++++-- 4 files changed, 86 insertions(+), 87 deletions(-) delete mode 100644 libs/ecs/componentarray.cpp delete mode 100644 libs/ecs/componentarray.hpp diff --git a/libs/ecs/componentarray.cpp b/libs/ecs/componentarray.cpp deleted file mode 100644 index 3b3b45b..0000000 --- a/libs/ecs/componentarray.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include -#include "componentarray.hpp" - -template -void ComponentArray::InsertData(Entity entity, T component) { - assert(mEntityToIndexMap.find(entity) == mEntityToIndexMap.end() && - "Component added to same entity more than once."); - - // Put new entry at end and update the maps - size_t newIndex = mSize; - mEntityToIndexMap[entity] = newIndex; - mIndexToEntityMap[newIndex] = entity; - mComponentArray[newIndex] = component; - ++mSize; -}; -template void ComponentArray::RemoveData(Entity entity) { - assert(mEntityToIndexMap.find(entity) != mEntityToIndexMap.end() && - "Removing non-existent component."); - - // Copy element at end into deleted element's place to maintain density - size_t indexOfRemovedEntity = mEntityToIndexMap[entity]; - size_t indexOfLastElement = mSize - 1; - mComponentArray[indexOfRemovedEntity] = mComponentArray[indexOfLastElement]; - - // Update map to point to moved spot - Entity entityOfLastElement = mIndexToEntityMap[indexOfLastElement]; - mEntityToIndexMap[entityOfLastElement] = indexOfRemovedEntity; - mIndexToEntityMap[indexOfRemovedEntity] = entityOfLastElement; - - mEntityToIndexMap.erase(entity); - mIndexToEntityMap.erase(indexOfLastElement); - - --mSize; -}; -template T &ComponentArray::GetData(Entity entity) { - assert(mEntityToIndexMap.find(entity) != mEntityToIndexMap.end() && - "Retrieving non-existent component."); - - // Return a reference to the entity's component - return mComponentArray[mEntityToIndexMap[entity]]; -}; -template void ComponentArray::EntityDestroyed(Entity entity) { - if (mEntityToIndexMap.find(entity) != mEntityToIndexMap.end()) { - // Remove the entity's component if it existed - RemoveData(entity); - } -}; diff --git a/libs/ecs/componentarray.hpp b/libs/ecs/componentarray.hpp deleted file mode 100644 index f8b10c4..0000000 --- a/libs/ecs/componentarray.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef COMPONENTARRAY_HPP -#define COMPONENTARRAY_HPP - -#include -#include -#include "entity.hpp" - -class IComponentArray { -public: - virtual ~IComponentArray() = default; - virtual void EntityDestroyed(Entity entity) = 0; -}; - -template class ComponentArray : public IComponentArray { - // The packed array of components (of generic type T), - // set to a specified maximum amount, matching the maximum number - // of entities allowed to exist simultaneously, so that each entity - // has a unique spot. - std::array mComponentArray; - - // Map from an entity ID to an array index. - std::unordered_map mEntityToIndexMap; - - // Map from an array index to an entity ID. - std::unordered_map mIndexToEntityMap; - - // Total size of valid entries in the array. - size_t mSize; - -public: - void InsertData(Entity entity, T component); - void RemoveData(Entity entity); - T &GetData(Entity entity); - void EntityDestroyed(Entity entity) override; -}; - -#endif // COMPONENTARRAY_HPP diff --git a/libs/ecs/componentmanager.cpp b/libs/ecs/componentmanager.cpp index 24584db..352c01f 100644 --- a/libs/ecs/componentmanager.cpp +++ b/libs/ecs/componentmanager.cpp @@ -1,7 +1,61 @@ #include "componentmanager.hpp" -#include "componentarray.hpp" + +#include #include +/** + * ComponentArray + **/ + +template +void ComponentArray::InsertData(Entity entity, T component) { + assert(mEntityToIndexMap.find(entity) == mEntityToIndexMap.end() && + "Component added to same entity more than once."); + + // Put new entry at end and update the maps + size_t newIndex = mSize; + mEntityToIndexMap[entity] = newIndex; + mIndexToEntityMap[newIndex] = entity; + mComponentArray[newIndex] = component; + ++mSize; +}; +template void ComponentArray::RemoveData(Entity entity) { + assert(mEntityToIndexMap.find(entity) != mEntityToIndexMap.end() && + "Removing non-existent component."); + + // Copy element at end into deleted element's place to maintain density + size_t indexOfRemovedEntity = mEntityToIndexMap[entity]; + size_t indexOfLastElement = mSize - 1; + mComponentArray[indexOfRemovedEntity] = mComponentArray[indexOfLastElement]; + + // Update map to point to moved spot + Entity entityOfLastElement = mIndexToEntityMap[indexOfLastElement]; + mEntityToIndexMap[entityOfLastElement] = indexOfRemovedEntity; + mIndexToEntityMap[indexOfRemovedEntity] = entityOfLastElement; + + mEntityToIndexMap.erase(entity); + mIndexToEntityMap.erase(indexOfLastElement); + + --mSize; +}; +template T &ComponentArray::GetData(Entity entity) { + assert(mEntityToIndexMap.find(entity) != mEntityToIndexMap.end() && + "Retrieving non-existent component."); + + // Return a reference to the entity's component + return mComponentArray[mEntityToIndexMap[entity]]; +}; +template void ComponentArray::EntityDestroyed(Entity entity) { + if (mEntityToIndexMap.find(entity) != mEntityToIndexMap.end()) { + // Remove the entity's component if it existed + RemoveData(entity); + } +}; + +/** + * ComponentManager + **/ + // Private functions template std::shared_ptr> ComponentManager::GetComponentArray() { diff --git a/libs/ecs/componentmanager.hpp b/libs/ecs/componentmanager.hpp index 16ab368..a61a95f 100644 --- a/libs/ecs/componentmanager.hpp +++ b/libs/ecs/componentmanager.hpp @@ -1,11 +1,40 @@ #ifndef COMPONENTMANAGER_HPP #define COMPONENTMANAGER_HPP +#include #include #include -#include +#include "entity.hpp" #include "component.hpp" -#include "componentarray.hpp" + +class IComponentArray { +public: + virtual ~IComponentArray() = default; + virtual void EntityDestroyed(Entity entity) = 0; +}; + +template class ComponentArray : public IComponentArray { + // The packed array of components (of generic type T), + // set to a specified maximum amount, matching the maximum number + // of entities allowed to exist simultaneously, so that each entity + // has a unique spot. + std::array mComponentArray; + + // Map from an entity ID to an array index. + std::unordered_map mEntityToIndexMap; + + // Map from an array index to an entity ID. + std::unordered_map mIndexToEntityMap; + + // Total size of valid entries in the array. + size_t mSize; + +public: + void InsertData(Entity entity, T component); + void RemoveData(Entity entity); + T &GetData(Entity entity); + void EntityDestroyed(Entity entity) override; +}; class ComponentManager { // Map from type string pointer to a component type From 27a3525f3f997910e485478b90d6b1d3fdb02bad Mon Sep 17 00:00:00 2001 From: Benjamin Palko Date: Thu, 10 Oct 2024 14:04:35 -0400 Subject: [PATCH 09/10] dont need import --- libs/ecs/componentmanager.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/ecs/componentmanager.hpp b/libs/ecs/componentmanager.hpp index a61a95f..a11f17e 100644 --- a/libs/ecs/componentmanager.hpp +++ b/libs/ecs/componentmanager.hpp @@ -5,7 +5,6 @@ #include #include #include "entity.hpp" -#include "component.hpp" class IComponentArray { public: From 273a03b99b4e603406be18ca29324d700a407fb8 Mon Sep 17 00:00:00 2001 From: Baobeld Date: Wed, 15 Jan 2025 16:43:50 -0500 Subject: [PATCH 10/10] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0bb0acb..ba9fde6 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Wayland Application +I'm messing around with GLFW to build an OpenGL app in wayland, theoretically this is the starting point for a game engine. ### Setup