Skip to content

Commit dfa8acc

Browse files
committed
Add ECS
1 parent 5fc3b21 commit dfa8acc

9 files changed

Lines changed: 244 additions & 23 deletions

File tree

Core/CMakeLists.txt

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ find_package(OpenGL REQUIRED)
99
CPMAddPackage(
1010
URI "gh:glfw/glfw#3.4"
1111
OPTIONS
12-
GLFW_BUILD_DOCS OFF
13-
GLFW_BUILD_TESTS OFF
14-
GLFW_BUILD_EXAMPLES OFF
12+
"GLFW_BUILD_DOCS OFF"
13+
"GLFW_BUILD_TESTS OFF"
14+
"GLFW_BUILD_EXAMPLES OFF"
1515
)
1616

1717
CPMAddPackage(
@@ -24,10 +24,10 @@ CPMAddPackage(
2424
NAME fmt
2525
GITHUB_REPOSITORY "fmtlib/fmt"
2626
GIT_TAG 12.1.0
27-
FMT_DOC OFF
28-
FMT_TEST OFF
29-
FMT_INSTALL OFF
30-
FMT_HEADER_ONLY ON
27+
"FMT_DOC OFF"
28+
"FMT_TEST OFF"
29+
"FMT_INSTALL OFF"
30+
"FMT_HEADER_ONLY ON"
3131
)
3232

3333
if (WIN32)
@@ -50,6 +50,14 @@ CPMAddPackage(
5050
"ASSIMP_BUILD_TESTS OFF"
5151
)
5252

53+
CPMAddPackage(
54+
URI "gh:skypjack/entt#v3.16.0"
55+
OPTIONS
56+
"ENTT_BUILD_TESTING OFF"
57+
"ENTT_BUILD_TESTBED OFF"
58+
"ENTT_BUILD_DOCS OFF"
59+
)
60+
5361
add_library(stbi STATIC vendor/stbi/stbi.h vendor/stbi/stbi.c)
5462

5563
CPMAddPackage(
@@ -151,6 +159,12 @@ set(PROJECT_SOURCES
151159
src/Input/InputManager.cpp
152160
src/Gui/Gui.hpp
153161
src/Gui/Gui.cpp
162+
src/Entities/Registry.hpp
163+
src/Entities/Registry.cpp
164+
src/Entities/SystemRegistry.cpp
165+
src/Entities/SystemRegistry.hpp
166+
src/Entities/System.hpp
167+
src/Entities/System.cpp
154168
)
155169

156170
add_library(${PROJECT_NAME} SHARED ${PROJECT_SOURCES})
@@ -167,6 +181,7 @@ target_link_libraries(${PROJECT_NAME} PUBLIC
167181
assimp::assimp
168182
stbi
169183
imgui
184+
EnTT::EnTT
170185
)
171186

172187
# OS libs

Core/src/Application/State.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#define PIXF_STATE_HPP
33

44
#include "Common.hpp"
5+
#include "Entities/Registry.hpp"
6+
#include "Entities/SystemRegistry.hpp"
57
#include "Graphics/Gl/Window.hpp"
68
#include "Graphics/Renderer.hpp"
79
#include "Graphics/Resources.hpp"
@@ -13,6 +15,8 @@ namespace Pixf::Core::Application {
1315
Graphics::Resources resources{};
1416
Graphics::Renderer renderer{};
1517
Time::Clock clock{};
18+
Entities::Registry entityRegistry{};
19+
Entities::SystemRegistry systemRegistry{};
1620
};
1721
} // namespace Pixf::Core::Application
1822

Core/src/Entities/Registry.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#include "Registry.hpp"
2+
3+
namespace Pixf::Core::Entities {
4+
Entity Registry::CreateEntity() {
5+
return m_Registry.create();
6+
}
7+
8+
void Registry::DestroyEntity(const Entity entity) {
9+
m_Registry.destroy(entity);
10+
}
11+
}

Core/src/Entities/Registry.hpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#ifndef PIXF_REGISTRY_HPP
2+
#define PIXF_REGISTRY_HPP
3+
4+
#include <entt/entt.hpp>
5+
6+
#include "Common.hpp"
7+
8+
namespace Pixf::Core::Entities {
9+
using Entity = entt::entity;
10+
11+
class PIXF_API Registry {
12+
public:
13+
Entity CreateEntity();
14+
void DestroyEntity(Entity);
15+
16+
template<typename T>
17+
void AddComponent(const Entity entity, const T component = {}) {
18+
if (m_Registry.any_of<T>(entity)) {
19+
m_Registry.remove<T>(entity);
20+
}
21+
22+
m_Registry.emplace<T>(entity, component);
23+
}
24+
25+
template<typename T>
26+
bool HasComponent(const Entity entity) const {
27+
return m_Registry.all_of<T>(entity);
28+
}
29+
30+
template<typename... Args>
31+
bool HasComponents(const Entity entity) const {
32+
return m_Registry.all_of<Args...>(entity);
33+
}
34+
35+
template<typename... Args>
36+
bool HasAnyComponents(const Entity entity) const {
37+
return m_Registry.any_of<Args...>(entity);
38+
}
39+
40+
template<typename T>
41+
T GetComponent(const Entity entity) {
42+
return m_Registry.get<T>(entity);
43+
}
44+
45+
template<typename T>
46+
void RemoveComponent(const Entity entity) {
47+
m_Registry.remove<T>(entity);
48+
}
49+
50+
template<typename... Args, typename Func>
51+
void ForEach(Func func) {
52+
m_Registry.view<Args...>().each(func);
53+
}
54+
55+
template<typename... Args, typename Func>
56+
void ForEachEntity(Func func) {
57+
m_Registry.view<Args...>().each(func);
58+
}
59+
60+
private:
61+
entt::registry m_Registry;
62+
};
63+
} // namespace Pixf::Core::Entities
64+
65+
#endif // PIXF_REGISTRY_HPP

Core/src/Entities/System.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#include "System.hpp"
2+
3+
namespace Pixf::Core::Entities {
4+
void System::Awake(Registry &registry) {}
5+
void System::Start(Registry &registry) {}
6+
void System::Update(Registry &registry, double deltaTime) {}
7+
void System::Render(Registry &registry, double deltaTime) {}
8+
void System::RenderGui(Registry &registry, double deltaTime) {}
9+
void System::OnEvent(Registry &registry, Event::Event &event) {}
10+
} // namespace Pixf::Core::Entities

Core/src/Entities/System.hpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#ifndef PIXF_SYSTEM_HPP
2+
#define PIXF_SYSTEM_HPP
3+
4+
#include "Event/Event.hpp"
5+
#include "Registry.hpp"
6+
#include "Common.hpp"
7+
8+
namespace Pixf::Core::Entities {
9+
struct PIXF_API System {
10+
virtual ~System() = default;
11+
12+
virtual void Awake(Registry &registry);
13+
virtual void Start(Registry &registry);
14+
15+
virtual void Update(Registry &registry, double deltaTime);
16+
virtual void Render(Registry &registry, double deltaTime);
17+
virtual void RenderGui(Registry &registry, double deltaTime);
18+
19+
virtual void OnEvent(Registry &registry, Event::Event &event);
20+
};
21+
} // namespace Pixf::Core::Entities
22+
23+
#endif // PIXF_SYSTEM_HPP
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#include "SystemRegistry.hpp"
2+
3+
namespace Pixf::Core::Entities {
4+
void SystemRegistry::Awake(Registry &registry) {
5+
for (auto &[typeId, system]: m_Systems) {
6+
system->Awake(registry);
7+
}
8+
}
9+
10+
void SystemRegistry::Start(Registry &registry) {
11+
for (auto &[typeId, system]: m_Systems) {
12+
system->Start(registry);
13+
}
14+
}
15+
16+
void SystemRegistry::Update(Registry &registry, const double deltaTime) {
17+
for (auto &[typeId, system]: m_Systems) {
18+
system->Update(registry, deltaTime);
19+
}
20+
}
21+
22+
void SystemRegistry::Render(Registry &registry, const double deltaTime) {
23+
for (auto &[typeId, system]: m_Systems) {
24+
system->Render(registry, deltaTime);
25+
}
26+
}
27+
28+
void SystemRegistry::RenderGui(Registry &registry, const double deltaTime) {
29+
for (auto &[typeId, system]: m_Systems) {
30+
system->RenderGui(registry, deltaTime);
31+
}
32+
}
33+
34+
void SystemRegistry::OnEvent(Registry &registry, Event::Event &event) {
35+
for (auto &[typeId, system]: m_Systems) {
36+
system->OnEvent(registry, event);
37+
}
38+
}
39+
40+
void SystemRegistry::Clear() { m_Systems.clear(); }
41+
} // namespace Pixf::Core::Entities
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#ifndef PIXF_SYSTEMREGISTRY_HPP
2+
#define PIXF_SYSTEMREGISTRY_HPP
3+
4+
#include "System.hpp"
5+
#include "TypeId.hpp"
6+
#include "Common.hpp"
7+
8+
namespace Pixf::Core::Entities {
9+
class PIXF_API SystemRegistry {
10+
public:
11+
void Awake(Registry &registry);
12+
void Start(Registry &registry);
13+
14+
void Update(Registry &registry, double deltaTime);
15+
void Render(Registry &registry, double deltaTime);
16+
void RenderGui(Registry &registry, double deltaTime);
17+
18+
void OnEvent(Registry &registry, Event::Event &event);
19+
20+
void Clear();
21+
22+
template<typename T>
23+
void Register() {
24+
static_assert(std::is_base_of<System, T>());
25+
26+
m_Systems[GetTypeId<T>()] = std::move(std::make_unique<T>());
27+
}
28+
29+
private:
30+
std::unordered_map<TypeId, std::unique_ptr<System>> m_Systems;
31+
};
32+
} // namespace Pixf::Core::Entities
33+
34+
#endif // PIXF_SYSTEMREGISTRY_HPP

Example/src/App.cpp

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "Application/Application.hpp"
2+
#include "Entities/System.hpp"
23
#include "Files/Model.hpp"
34
#include "Graphics/Gl/Viewport.hpp"
45
#include "Graphics/Renderer.hpp"
@@ -10,17 +11,38 @@ using namespace Pixf::Core::Math;
1011
using namespace Pixf::Core::Graphics;
1112
using namespace Pixf::Core::Debug;
1213

14+
struct Backpack {
15+
Matrix4f transform{};
16+
Model backpack;
17+
float dist = 0.0F;
18+
float rot = 0.0F;
19+
};
20+
21+
struct BackpackSystem final : Entities::System {
22+
void Update(Entities::Registry &registry, const double deltaTime) override {
23+
registry.ForEach<Backpack>([deltaTime](Backpack &backpack) {
24+
backpack.dist += 5.0F * deltaTime;
25+
backpack.rot += 5.0F * deltaTime;
26+
27+
backpack.transform = Matrix4f::Identity();
28+
backpack.transform.ApplyRotation(backpack.rot, Vector3f::Up());
29+
backpack.transform.ApplyTranslation(Vector3f(0.0F, 0.0F, backpack.dist));
30+
});
31+
}
32+
};
33+
1334
class RenderStage final : public Application::Stage {
1435
public:
15-
void OnAttach(Application::State &state) override { backpack = Files::LoadModel("backpack.obj", state.resources); }
36+
void OnAttach(Application::State &state) override {
37+
const auto entity = state.entityRegistry.CreateEntity();
38+
const Backpack backpack{.backpack = Files::LoadModel("backpack.obj", state.resources)};
1639

17-
void Update(Application::State &state, const double deltaTime) override {
18-
dist += 5.0F * deltaTime;
19-
rot += 5.0F * deltaTime;
40+
state.entityRegistry.AddComponent(entity, backpack);
41+
state.systemRegistry.Register<BackpackSystem>();
42+
}
2043

21-
transform = Matrix4f::Identity();
22-
transform.ApplyRotation(rot, Vector3f::Up());
23-
transform.ApplyTranslation(Vector3f(0.0F, 0.0F, dist));
44+
void Update(Application::State &state, const double deltaTime) override {
45+
state.systemRegistry.Update(state.entityRegistry, deltaTime);
2446
}
2547

2648
void Render(Application::State &state, double deltaTime) override {
@@ -29,18 +51,14 @@ class RenderStage final : public Application::Stage {
2951
Renderer &renderer = state.renderer;
3052
renderer.BeginPass({.projectionMatrix = Matrix4f::Perspective(60.0F, 4.0F / 3.0F, 0.1F, 100.0F)});
3153

32-
for (auto &[mesh, material]: backpack.elements) {
33-
renderer.Submit({.mesh = mesh, .material = material, .modelMatrix = transform});
34-
}
54+
state.entityRegistry.ForEach<Backpack>([&renderer](Backpack &backpack) {
55+
for (auto &[mesh, material]: backpack.backpack.elements) {
56+
renderer.Submit({.mesh = mesh, .material = material, .modelMatrix = backpack.transform});
57+
}
58+
});
3559

3660
renderer.Render(viewport, state.resources);
3761
}
38-
39-
private:
40-
Matrix4f transform;
41-
Model backpack;
42-
float dist = 0.0F;
43-
float rot = 0.0F;
4462
};
4563

4664
class App final : public Application::Application {

0 commit comments

Comments
 (0)