From da9eb14ebe7e6968cdad6a10f4559aa056c496b8 Mon Sep 17 00:00:00 2001 From: SirLynix Date: Sat, 21 Jan 2023 12:03:02 +0100 Subject: [PATCH] Handle windows and EnTT with application components --- examples/Tut01/main.cpp | 34 ++++++------ .../Nazara/Core/AppEntitySystemComponent.hpp | 46 ++++++++++++++++ .../Nazara/Core/AppEntitySystemComponent.inl | 44 +++++++++++++++ include/Nazara/Core/Application.hpp | 2 +- include/Nazara/Core/Application.inl | 6 +++ include/Nazara/Core/ApplicationBase.hpp | 6 ++- include/Nazara/Core/ApplicationBase.inl | 54 ++++++++++++++----- include/Nazara/Core/ApplicationComponent.hpp | 10 +++- include/Nazara/Core/ApplicationComponent.inl | 14 +++++ .../Core/ApplicationComponentRegistry.hpp | 24 +++++++++ .../Core/ApplicationComponentRegistry.inl | 27 ++++++++++ .../Nazara/Platform/AppWindowingComponent.hpp | 14 ++++- .../Nazara/Platform/AppWindowingComponent.inl | 20 +++++++ src/Nazara/Core/AppEntitySystemComponent.cpp | 14 +++++ src/Nazara/Core/Application.cpp | 32 ----------- src/Nazara/Core/ApplicationBase.cpp | 5 ++ 16 files changed, 287 insertions(+), 65 deletions(-) create mode 100644 include/Nazara/Core/AppEntitySystemComponent.hpp create mode 100644 include/Nazara/Core/AppEntitySystemComponent.inl create mode 100644 include/Nazara/Core/ApplicationComponentRegistry.hpp create mode 100644 include/Nazara/Core/ApplicationComponentRegistry.inl create mode 100644 src/Nazara/Core/AppEntitySystemComponent.cpp delete mode 100644 src/Nazara/Core/Application.cpp diff --git a/examples/Tut01/main.cpp b/examples/Tut01/main.cpp index 10b91368f..5cd9fa069 100644 --- a/examples/Tut01/main.cpp +++ b/examples/Tut01/main.cpp @@ -1,10 +1,12 @@ // Sources pour https://github.com/NazaraEngine/NazaraEngine/wiki/(FR)-Tutoriel:-%5B01%5D-Hello-World #include +#include #include #include #include #include +#include #include #include #include @@ -17,15 +19,19 @@ int main() { Nz::Application app; - entt::registry registry; - Nz::SystemGraph systemGraph(registry); - Nz::RenderSystem& renderSystem = systemGraph.AddSystem(); - Nz::RenderWindow& mainWindow = renderSystem.CreateWindow(Nz::Graphics::Instance()->GetRenderDevice(), Nz::VideoMode(1280, 720), "Tut01 - Hello world"); + auto& windowing = app.AddComponent(); + Nz::Window& mainWindow = windowing.CreateWindow(Nz::VideoMode(1280, 720), "Hello world"); - entt::entity cameraEntity = registry.create(); + auto& ecs = app.AddComponent(); + + Nz::RenderSystem& renderSystem = ecs.AddSystem(); + auto& windowSwapchain = renderSystem.CreateSwapchain(mainWindow); + + entt::handle cameraEntity = ecs.CreateEntity(); { - registry.emplace(cameraEntity); - auto& cameraComponent = registry.emplace(cameraEntity, mainWindow.GetRenderTarget(), Nz::ProjectionType::Orthographic); + cameraEntity.emplace(); + + auto& cameraComponent = cameraEntity.emplace(&windowSwapchain.GetSwapchain(), Nz::ProjectionType::Orthographic); cameraComponent.UpdateClearColor(Nz::Color(0.46f, 0.48f, 0.84f, 1.f)); } @@ -37,10 +43,10 @@ int main() std::shared_ptr textSprite = std::make_shared(); textSprite->Update(textDrawer); - entt::entity textEntity = registry.create(); + entt::handle textEntity = ecs.CreateEntity(); { - auto& nodeComponent = registry.emplace(textEntity); - auto& gfxComponent = registry.emplace(textEntity); + auto& nodeComponent = textEntity.emplace(); + auto& gfxComponent = textEntity.emplace(); gfxComponent.AttachRenderable(textSprite, 0xFFFFFFFF); Nz::Boxf textBox = textSprite->GetAABB(); @@ -48,11 +54,5 @@ int main() nodeComponent.SetPosition(windowSize.x / 2 - textBox.width / 2, windowSize.y / 2 - textBox.height / 2); } - while (mainWindow.IsOpen()) - { - mainWindow.ProcessEvents(); - systemGraph.Update(); - } - - return EXIT_SUCCESS; + return app.Run(); } diff --git a/include/Nazara/Core/AppEntitySystemComponent.hpp b/include/Nazara/Core/AppEntitySystemComponent.hpp new file mode 100644 index 000000000..22d092803 --- /dev/null +++ b/include/Nazara/Core/AppEntitySystemComponent.hpp @@ -0,0 +1,46 @@ +// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Platform module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_CORE_APPENTITYSYSTEMCOMPONENT_HPP +#define NAZARA_CORE_APPENTITYSYSTEMCOMPONENT_HPP + +#include +#include +#include +#include + +namespace Nz +{ + class NAZARA_CORE_API AppEntitySystemComponent : public ApplicationComponent + { + public: + inline AppEntitySystemComponent(ApplicationBase& app); + AppEntitySystemComponent(const AppEntitySystemComponent&) = delete; + AppEntitySystemComponent(AppEntitySystemComponent&&) = delete; + ~AppEntitySystemComponent() = default; + + template T& AddSystem(Args&&... args); + + entt::handle CreateEntity(); + + entt::registry& GetRegistry(); + const entt::registry& GetRegistry() const; + template T& GetSystem() const; + + void Update(Time elapsedTime) override; + + AppEntitySystemComponent& operator=(const AppEntitySystemComponent&) = delete; + AppEntitySystemComponent& operator=(AppEntitySystemComponent&&) = delete; + + private: + entt::registry m_registry; + SystemGraph m_systemGraph; + }; +} + +#include + +#endif // NAZARA_CORE_APPENTITYSYSTEMCOMPONENT_HPP diff --git a/include/Nazara/Core/AppEntitySystemComponent.inl b/include/Nazara/Core/AppEntitySystemComponent.inl new file mode 100644 index 000000000..97de0c034 --- /dev/null +++ b/include/Nazara/Core/AppEntitySystemComponent.inl @@ -0,0 +1,44 @@ +// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Platform module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + inline AppEntitySystemComponent::AppEntitySystemComponent(ApplicationBase& app) : + ApplicationComponent(app), + m_systemGraph(m_registry) + { + } + + template + T& AppEntitySystemComponent::AddSystem(Args&&... args) + { + return m_systemGraph.AddSystem(std::forward(args)...); + } + + inline entt::handle AppEntitySystemComponent::CreateEntity() + { + return entt::handle(m_registry, m_registry.create()); + } + + inline entt::registry& AppEntitySystemComponent::GetRegistry() + { + return m_registry; + } + + inline const entt::registry& AppEntitySystemComponent::GetRegistry() const + { + return m_registry; + } + + template + T& AppEntitySystemComponent::GetSystem() const + { + return m_systemGraph.GetSystem(); + } +} + +#include diff --git a/include/Nazara/Core/Application.hpp b/include/Nazara/Core/Application.hpp index 8f701a74c..ffc81e50c 100644 --- a/include/Nazara/Core/Application.hpp +++ b/include/Nazara/Core/Application.hpp @@ -20,7 +20,7 @@ namespace Nz using ApplicationBase::ApplicationBase; Application(const Application&) = delete; Application(Application&&) = delete; - ~Application() = default; + ~Application(); Application& operator=(const Application&) = delete; Application& operator=(Application&&) = delete; diff --git a/include/Nazara/Core/Application.inl b/include/Nazara/Core/Application.inl index 7e797fad2..c51f72639 100644 --- a/include/Nazara/Core/Application.inl +++ b/include/Nazara/Core/Application.inl @@ -7,6 +7,12 @@ namespace Nz { + template + Application::~Application() + { + // Clear components before releasing modules + ClearComponents(); + } } #include diff --git a/include/Nazara/Core/ApplicationBase.hpp b/include/Nazara/Core/ApplicationBase.hpp index be750316f..9cc285016 100644 --- a/include/Nazara/Core/ApplicationBase.hpp +++ b/include/Nazara/Core/ApplicationBase.hpp @@ -26,7 +26,11 @@ namespace Nz ~ApplicationBase() = default; template T& AddComponent(Args&&... args); - inline void AddComponent(std::unique_ptr&& component); + + inline void ClearComponents(); + + template T* GetComponent(); + template const T* GetComponent() const; int Run(); diff --git a/include/Nazara/Core/ApplicationBase.inl b/include/Nazara/Core/ApplicationBase.inl index 3ae4485f1..1615256ba 100644 --- a/include/Nazara/Core/ApplicationBase.inl +++ b/include/Nazara/Core/ApplicationBase.inl @@ -3,20 +3,12 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include +#include #include namespace Nz { - template - T& Nz::ApplicationBase::AddComponent(Args&& ...args) - { - std::unique_ptr component = std::make_unique(std::forward(args)...); - T& componentRef = *component; - AddComponent(std::move(component)); - - return componentRef; - } - inline ApplicationBase::ApplicationBase() : ApplicationBase(0, static_cast(nullptr)) { @@ -27,9 +19,47 @@ namespace Nz { } - void ApplicationBase::AddComponent(std::unique_ptr&& component) + template + T& ApplicationBase::AddComponent(Args&&... args) { - m_components.emplace_back(std::move(component)); + std::size_t componentIndex = ApplicationComponentRegistry::GetComponentId(); + + std::unique_ptr component = std::make_unique(*this, std::forward(args)...); + T& componentRef = *component; + + if (componentIndex >= m_components.size()) + m_components.resize(componentIndex + 1); + else if (m_components[componentIndex] != nullptr) + throw std::runtime_error("component was added multiple times"); + + m_components[componentIndex] = std::move(component); + + return componentRef; + } + + inline void ApplicationBase::ClearComponents() + { + m_components.clear(); + } + + template + T* ApplicationBase::GetComponent() + { + std::size_t componentIndex = ApplicationComponentRegistry::GetComponentId(); + if (componentIndex >= m_components.size()) + return nullptr; + + return m_components[componentIndex].get(); + } + + template + const T* ApplicationBase::GetComponent() const + { + std::size_t componentIndex = ApplicationComponentRegistry::GetComponentId(); + if (componentIndex >= m_components.size()) + return nullptr; + + return m_components[componentIndex].get(); } inline void ApplicationBase::Quit() diff --git a/include/Nazara/Core/ApplicationComponent.hpp b/include/Nazara/Core/ApplicationComponent.hpp index 601aa6fbb..83a82654b 100644 --- a/include/Nazara/Core/ApplicationComponent.hpp +++ b/include/Nazara/Core/ApplicationComponent.hpp @@ -13,18 +13,26 @@ namespace Nz { + class ApplicationBase; + class NAZARA_CORE_API ApplicationComponent { public: - ApplicationComponent() = default; + inline ApplicationComponent(ApplicationBase& app); ApplicationComponent(const ApplicationComponent&) = delete; ApplicationComponent(ApplicationComponent&&) = delete; virtual ~ApplicationComponent(); + inline ApplicationBase& GetApp(); + inline const ApplicationBase& GetApp() const; + virtual void Update(Time elapsedTime); ApplicationComponent& operator=(const ApplicationComponent&) = delete; ApplicationComponent& operator=(ApplicationComponent&&) = delete; + + private: + ApplicationBase& m_app; }; } diff --git a/include/Nazara/Core/ApplicationComponent.inl b/include/Nazara/Core/ApplicationComponent.inl index 116de11f4..bcda1e259 100644 --- a/include/Nazara/Core/ApplicationComponent.inl +++ b/include/Nazara/Core/ApplicationComponent.inl @@ -7,6 +7,20 @@ namespace Nz { + inline ApplicationComponent::ApplicationComponent(ApplicationBase& app) : + m_app(app) + { + } + + inline ApplicationBase& ApplicationComponent::GetApp() + { + return m_app; + } + + inline const ApplicationBase& ApplicationComponent::GetApp() const + { + return m_app; + } } #include diff --git a/include/Nazara/Core/ApplicationComponentRegistry.hpp b/include/Nazara/Core/ApplicationComponentRegistry.hpp new file mode 100644 index 000000000..6e522b2c1 --- /dev/null +++ b/include/Nazara/Core/ApplicationComponentRegistry.hpp @@ -0,0 +1,24 @@ +// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_CORE_APPLICATIONCOMPONENTREGISTRY_HPP +#define NAZARA_CORE_APPLICATIONCOMPONENTREGISTRY_HPP + +#include +#include + +namespace Nz +{ + template + struct ApplicationComponentRegistry + { + static std::size_t GetComponentId(); + }; +} + +#include + +#endif // NAZARA_CORE_APPLICATIONCOMPONENTREGISTRY_HPP diff --git a/include/Nazara/Core/ApplicationComponentRegistry.inl b/include/Nazara/Core/ApplicationComponentRegistry.inl new file mode 100644 index 000000000..486eb7ccc --- /dev/null +++ b/include/Nazara/Core/ApplicationComponentRegistry.inl @@ -0,0 +1,27 @@ +// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + namespace Detail + { + std::size_t ComponentCounter() + { + static std::size_t counter = 0; + return counter++; + } + } + + template + std::size_t ApplicationComponentRegistry::GetComponentId() + { + static std::size_t typeId = Detail::ComponentCounter(); + return typeId; + } +} + +#include diff --git a/include/Nazara/Platform/AppWindowingComponent.hpp b/include/Nazara/Platform/AppWindowingComponent.hpp index f2e22fda6..3a55ea1a5 100644 --- a/include/Nazara/Platform/AppWindowingComponent.hpp +++ b/include/Nazara/Platform/AppWindowingComponent.hpp @@ -10,21 +10,33 @@ #include #include #include +#include namespace Nz { class NAZARA_PLATFORM_API AppWindowingComponent : public ApplicationComponent { public: - AppWindowingComponent() = default; + using ApplicationComponent::ApplicationComponent; AppWindowingComponent(const AppWindowingComponent&) = delete; AppWindowingComponent(AppWindowingComponent&&) = delete; ~AppWindowingComponent() = default; + template Window& CreateWindow(Args&&... args); + + inline void DisableQuitOnLastWindowClosed(); + inline void EnableQuitOnLastWindowClosed(bool enable = true); + + inline bool IsQuitOnLastWindowClosedEnabled() const; + void Update(Time elapsedTime) override; AppWindowingComponent& operator=(const AppWindowingComponent&) = delete; AppWindowingComponent& operator=(AppWindowingComponent&&) = delete; + + private: + std::vector> m_windows; + bool m_quitOnLastWindowClosed; }; } diff --git a/include/Nazara/Platform/AppWindowingComponent.inl b/include/Nazara/Platform/AppWindowingComponent.inl index 83a77dc5b..c55818d72 100644 --- a/include/Nazara/Platform/AppWindowingComponent.inl +++ b/include/Nazara/Platform/AppWindowingComponent.inl @@ -7,6 +7,26 @@ namespace Nz { + template + Window& AppWindowingComponent::CreateWindow(Args&&... args) + { + return *m_windows.emplace_back(std::make_unique(std::forward(args)...)); + } + + inline void AppWindowingComponent::DisableQuitOnLastWindowClosed() + { + return EnableQuitOnLastWindowClosed(false); + } + + inline void AppWindowingComponent::EnableQuitOnLastWindowClosed(bool enable) + { + m_quitOnLastWindowClosed = enable; + } + + inline bool AppWindowingComponent::IsQuitOnLastWindowClosedEnabled() const + { + return m_quitOnLastWindowClosed; + } } #include diff --git a/src/Nazara/Core/AppEntitySystemComponent.cpp b/src/Nazara/Core/AppEntitySystemComponent.cpp new file mode 100644 index 000000000..98c232705 --- /dev/null +++ b/src/Nazara/Core/AppEntitySystemComponent.cpp @@ -0,0 +1,14 @@ +// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Platform module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + void AppEntitySystemComponent::Update(Time elapsedTime) + { + m_systemGraph.Update(elapsedTime); + } +} diff --git a/src/Nazara/Core/Application.cpp b/src/Nazara/Core/Application.cpp deleted file mode 100644 index c5cd89208..000000000 --- a/src/Nazara/Core/Application.cpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com) -// This file is part of the "Nazara Engine - Core module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include - -namespace Nz -{ - Application::Application(int argc, const char** argv) : - m_running(true) - { - } - - int Application::Run() - { - // Ignore time between creation and Run() call - m_clock.Restart(); - - while (m_running) - { - Time elapsedTime = m_clock.Restart(); - Update(elapsedTime); - } - - return 0; - } - - void Application::Update(Time elapsedTime) - { - } -} diff --git a/src/Nazara/Core/ApplicationBase.cpp b/src/Nazara/Core/ApplicationBase.cpp index 34903b223..69878e092 100644 --- a/src/Nazara/Core/ApplicationBase.cpp +++ b/src/Nazara/Core/ApplicationBase.cpp @@ -28,5 +28,10 @@ namespace Nz void ApplicationBase::Update(Time elapsedTime) { + for (auto& componentPtr : m_components) + { + if (componentPtr) + componentPtr->Update(elapsedTime); + } } }