diff --git a/engine/modules/engine/app/impl/app_impl.inl b/engine/modules/engine/app/impl/app_impl.inl index f1a4bcf..87e82f9 100644 --- a/engine/modules/engine/app/impl/app_impl.inl +++ b/engine/modules/engine/app/impl/app_impl.inl @@ -1,4 +1,6 @@ +#include "app.h" #include "data/global.h" namespace api { APP_API EngineConfig gEngineConfig{}; + IMPLEMENT_STATIC_MODULE(APP_API, AppModule, app) } \ No newline at end of file diff --git a/engine/modules/engine/app/impl/event_system_impl.inl b/engine/modules/engine/app/impl/event_system_impl.inl new file mode 100644 index 0000000..a017fd4 --- /dev/null +++ b/engine/modules/engine/app/impl/event_system_impl.inl @@ -0,0 +1,17 @@ +#include "event/event_system.h" +namespace api { + SINGLETON_DEFINE(EventSystem) + + inline EventSystem::EventSystem() + { + SINGLETON_PTR(); + } + inline void EventSystem::Initialize() + { + + } + inline void EventSystem::Finalize() + { + + } +} \ No newline at end of file diff --git a/engine/modules/engine/app/include/app.h b/engine/modules/engine/app/include/app.h index 8b5bf25..ff1281d 100644 --- a/engine/modules/engine/app/include/app.h +++ b/engine/modules/engine/app/include/app.h @@ -1,6 +1,14 @@ #pragma once +#include "module/module.h" #include "data/engine_config.h" namespace api{ + class APP_API AppModule : public IStaticModule + { + public: + void OnLoad(int argc, char** argv) override; + void OnUnload() override; + void InitMetaData(void) override {}; + }; template class AppImpl; class App { diff --git a/engine/modules/engine/app/include/data/global.h b/engine/modules/engine/app/include/data/global.h index 8eea15e..7a8a3a2 100644 --- a/engine/modules/engine/app/include/data/global.h +++ b/engine/modules/engine/app/include/data/global.h @@ -1,3 +1,4 @@ +#pragma once #include "engine_config.h" #include "project_config.h" namespace api { diff --git a/engine/modules/engine/app/include/event/engine_event.h b/engine/modules/engine/app/include/event/engine_event.h new file mode 100644 index 0000000..e69de29 diff --git a/engine/modules/engine/app/include/event/event.h b/engine/modules/engine/app/include/event/event.h new file mode 100644 index 0000000..ecc5062 --- /dev/null +++ b/engine/modules/engine/app/include/event/event.h @@ -0,0 +1,187 @@ +#pragma once +#include "pmr/name.h" +#include +#include +namespace api{ + using pmr::Name; + //* Utility functions to create std::functions without std::placeholder + template + class Event; + + /** + * @brief Event that can call all of its subscribers + * + * @tparam R Return type + * @tparam Args Function arguments + */ + template + class Event { + private: + using Delegate = std::function; + using FuncMap = std::unordered_map; + std::unordered_map listeners; + //std::unordered_map constListeners; + template + static consteval auto add_const(R(Type::* ptr)(Args...)) { + using MethodType = R(Type::*)(Args...)const; + return (MethodType)ptr; + } + template + static std::function EasyBind(R(Type::* func)(Args... args) const, const Type* invoker) { + return [=](auto&&... args) { + return (invoker->*func)(std::forward(args)...); + }; + } + public: + Event() = default; + + /** + * @brief Subscribes a member function to the event. + * + * @tparam Invoker The instance type to call the member function + * @tparam Type The type containing the member function + * @param id Unique identifier of the subscribing function + * @param func The function to call when the event is raised + * @param invoker The instance owning the member function + */ + template + void Subscribe(const Name& id, R(Type::*func)(Args... args),const Invoker* invoker) { + Subscribe(id, add_const(func), invoker); + } + + /** + * @brief Subscribes a const member function to the event. + * + * @tparam Invoker The instance type to call the member function + * @tparam Type The type containing the member function + * @param id Unique identifier of the subscribing function + * @param func The const function to call when the event is raised + * @param invoker The instance owning the member function + */ + template + void Subscribe(const Name& id, R (Type::*func)(Args... args) const, const Invoker* invoker) { + Delegate deleg{ std::move(EasyBind(func, invoker)) }; + auto found{ listeners.find(invoker) }; + if (found != listeners.end()) { + auto iter{ found->second.find(id) }; + if (iter != found->second.end()) { + iter->second = std::move(deleg); + } + else { + found->second.emplace(id, std::move(deleg)); + } + } + else { + listeners.emplace(invoker, FuncMap{ {id, {std::move(deleg)}} }); + } + } + /** + * @brief Subscribes a free function or a std::function reference to the event + * + * @param id Unique identifier of the subscribing function + * @param func The function to call when the event is raised + */ + void Subscribe(const Name& id,const std::function& func) { + auto found{listeners.find(nullptr)}; + + if (found != listeners.end()) { + auto iter{found->second.find(id)}; + if (iter != found->second.end()) { + iter->second = func; + } + else { + found->second.emplace(id, func); + } + } else { + listeners.emplace(nullptr, FuncMap{{id, {func}}}); + } + } + + /** + * @brief Unsubscribes a member function from an event + * + * @tparam Invoker + * @param id Unique identifier of the subscribed function + * @param invoker The instance owning the member function + */ + template + void Unsubscribe(const Name& id,const Invoker* invoker) { + auto found {listeners.find(invoker)}; + + if (found != listeners.end()) { + auto iter {found->second.find(id)}; + if (iter != found->second.end()) { + found->second.erase(iter); + } + if (found->second.empty()) { + listeners.erase(found); + } + } + } + /** + * @brief Unsubscribes a free function/lambda from an event + * + * @param id Unique identifier of the subscribed function/lambda + */ + void Unsubscribe(const Name& id) { + auto found{listeners.find(nullptr)}; + + if (found != listeners.end()) { + auto iter{found->second.find(id)}; + if (iter != found->second.end()) { + found->second.erase(iter); + } + if (found->second.empty()) { + listeners.erase(found); + } + } + } + + /** + * @brief Unsubscribes all functions owned by the invoker const instance from this event + * + * @param invoker Const instance subscribed to this event + */ + template + void RemoveListener(const Invoker* invoker) { + auto found{ listeners.find(invoker)}; + if (found != listeners.end()) { + listeners.erase(found); + } + } + + /** + * @brief Unsubscribes all free functions/lambdas from this event + */ + void RemoveFreeFunctions() { + auto found{listeners.find(nullptr)}; + if (found != listeners.end()) { + listeners.erase(found); + } + } + + // TODO: Check if args should be lvalues or not. + /** + * @brief Calls all subscribed functions + * + * @param args + */ + void Invoke(Args... args) { + for (auto& listener : listeners) { + for (auto& func : listener.second) { + func.second(std::forward(args)...); + } + } + } + + /** + * @brief Calls all subscribed functions (this is equivalent to Invoke()) + * + * @param args + */ + void operator()(Args... args) { + Invoke(std::forward(args)...); + } + + }; +} \ No newline at end of file diff --git a/engine/modules/engine/app/include/event/event_system.h b/engine/modules/engine/app/include/event/event_system.h new file mode 100644 index 0000000..e689e78 --- /dev/null +++ b/engine/modules/engine/app/include/event/event_system.h @@ -0,0 +1,13 @@ +#pragma once +#include "event.h" +#include "module/module.h" +namespace api { + class APP_API EventSystem : public ISystem{ + SINGLETON_IMPL(EventSystem) + public: + EventSystem(); + void Initialize() override; + void Finalize() override; + Event BeginRenderFrame; + }; +} \ No newline at end of file diff --git a/engine/modules/engine/app/src/app.cpp b/engine/modules/engine/app/src/app.cpp index 96369dc..89f8e39 100644 --- a/engine/modules/engine/app/src/app.cpp +++ b/engine/modules/engine/app/src/app.cpp @@ -1,4 +1,13 @@ #include "data/engine_config.h" +#include "event/event_system.h" +#include "app.h" namespace api { + void AppModule::OnLoad(int argc, char** argv) + { + AddSystem(); + } + void AppModule::OnUnload() + { + } } \ No newline at end of file diff --git a/engine/modules/engine/core/include/os/file_handle.h b/engine/modules/engine/core/include/os/file_handle.h index 9701624..68e392a 100644 --- a/engine/modules/engine/core/include/os/file_handle.h +++ b/engine/modules/engine/core/include/os/file_handle.h @@ -1,3 +1,4 @@ +#pragma once #include "package_path.h" #include #include diff --git a/engine/modules/render/vulkan/src/vulkan_api.cpp b/engine/modules/render/vulkan/src/vulkan_api.cpp index b96807d..80cd427 100644 --- a/engine/modules/render/vulkan/src/vulkan_api.cpp +++ b/engine/modules/render/vulkan/src/vulkan_api.cpp @@ -6,10 +6,12 @@ #include "vkn/thread/command_worker.h" #include "vkn/loader/vulkan_glsl_loader.h" #include "render/asset/mesh.h" +#include "event/event_system.h" #include "meta/enum.h" #include "tinyimageformat/tinyimageformat_apis.h" #include "zlog.h" namespace vkn { + using api::EventSystem; inline bool operator==(const FramebufferKey& k1, const FramebufferKey& k2) { if (k1.pass != k2.pass) return false; if (k1.attachmentCount != k2.attachmentCount) return false; @@ -344,6 +346,7 @@ namespace vkn { window.Aquire(ctx); ctx.BeginRecord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); graph.mSurface = ctx.surface; + EventSystem::Ptr()->BeginRenderFrame.Invoke(); } void VulkanAPI::EndFrame() { diff --git a/engine/src/engine/api.cpp b/engine/src/engine/api.cpp index 5619d66..ceb0c1a 100644 --- a/engine/src/engine/api.cpp +++ b/engine/src/engine/api.cpp @@ -1,5 +1,4 @@ #include "engine/api.h" -#include "app_impl.inl" #include "os/file_manager.h" #include "xmalloc_new_delete.h" class ENGINE_API EngineModule : public api::IDynamicModule @@ -14,6 +13,7 @@ public: }; void InitMetaData(void) override { mInfo.dependencies = { + {"app","1.0.1", "static"}, {"core", "1.0.1", "static" }, {"asset", "1.0.1", "static" }, {"render", "1.0.1", "static" }, diff --git a/engine/src/engine/asset.cpp b/engine/src/engine/asset.cpp deleted file mode 100644 index e41c50a..0000000 --- a/engine/src/engine/asset.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef ASSET_API_VAL -#define ASSET_API_VAL 1 -#include "resource_system_impl.inl" -#include "asset_visit_impl.inl" -#endif // !ASSET_API_VAL \ No newline at end of file diff --git a/engine/src/engine/core.cpp b/engine/src/engine/core.cpp deleted file mode 100644 index 46954b5..0000000 --- a/engine/src/engine/core.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef CORE_API_VAL -#define CORE_API_VAL 1 -#include "zlog.h" -#include "module_manager_impl.inl" -#include "file_manager_impl.inl" -#endif // !CORE_API_VAL \ No newline at end of file diff --git a/engine/src/engine/plugin.cpp b/engine/src/engine/plugin.cpp new file mode 100644 index 0000000..8e5127e --- /dev/null +++ b/engine/src/engine/plugin.cpp @@ -0,0 +1,30 @@ +#ifndef ZLIB_API_VAL +#define ZLIB_API_VAL 1 +#include "pmr/name.h" +#include "pmr/frame_allocator.h" +#endif // !ZLIB_API_VAL + +#ifndef CORE_API_VAL +#define CORE_API_VAL 1 +#include "zlog.h" +#include "module_manager_impl.inl" +#include "file_manager_impl.inl" +#endif // !CORE_API_VAL + +#ifndef ASSET_API_VAL +#define ASSET_API_VAL 1 +#include "resource_system_impl.inl" +#include "asset_visit_impl.inl" +#endif // !ASSET_API_VAL + +#ifndef RENDER_API_VAL +#define RENDER_API_VAL 1 +#include "renderapi_impl.inl" +#include "window_impl.inl" +#endif // !RENDER_API_VAL + +#ifndef APP_API_VAL +#define APP_API_VAL 1 +#include "app_impl.inl" +#include "event_system_impl.inl" +#endif // !APP_API_VAL \ No newline at end of file diff --git a/engine/src/engine/render.cpp b/engine/src/engine/render.cpp deleted file mode 100644 index 3361a9d..0000000 --- a/engine/src/engine/render.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef RENDER_API_VAL -#define RENDER_API_VAL 1 -#include "renderapi_impl.inl" -#include "window_impl.inl" -#endif // !RENDER_API_VAL \ No newline at end of file diff --git a/engine/src/engine/zlib.cpp b/engine/src/engine/zlib.cpp deleted file mode 100644 index 8c438a9..0000000 --- a/engine/src/engine/zlib.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef ZLIB_API_VAL -#define ZLIB_API_VAL 1 -#include "pmr/name.h" -#include "pmr/frame_allocator.h" -#include "refl/detail/uclass.inl" -#endif // !ZLIB_API_VAL \ No newline at end of file diff --git a/game/zworld/src/zworld.cpp b/game/zworld/src/zworld.cpp index 02aa9b3..ebfc9a1 100644 --- a/game/zworld/src/zworld.cpp +++ b/game/zworld/src/zworld.cpp @@ -1,6 +1,7 @@ #include "zlog.h" #include "zworld.h" #include "data/global.h" +#include "event/event_system.h" #include "vkn/vulkan_window.h" #include "vkn/vulkan_api.h" #ifdef WITH_EDITOR @@ -26,6 +27,9 @@ void ZWorldModule::OnLoad(int argc, char** argv) #ifdef WITH_EDITOR //绑定窗口交互 ImGui_ImplSDL2_InitForVulkan(window->GetPtr()); #endif + EventSystem::Ptr()->BeginRenderFrame.Subscribe("zworld", []() { + API->graph.AddRenderPass(); + }); } void ZWorldModule::Initialize() { @@ -46,7 +50,6 @@ void ZWorldModule::MainLoop() } } API->BeginFrame(); - API->graph.AddRenderPass(); API->Render(); API->EndFrame(); FramePool()->reset();