// ModuleManager.h #pragma once #include "Modules/ModuleInterface.h" #include "CorePCH.h" #include #include #include class CORE_API FModuleManager { public: /** * Gets the module manager. * * @return The module manager. */ static FModuleManager& Get(); /** * Loads a module by type and name. * * @tparam T The type of module to load. * @param InName The name of the module to load. * * @return The newly loaded module instance. */ template T& LoadModule(const std::string& InName); /** * Unloads a module by name. * * @param InName The name of the module to unload. */ void UnloadModule(const std::string& InName); public: /** * Gets the currently loaded game module. * * @return The currently loaded game module. */ IModuleInterface* GetGameModule() const; private: /** * Default constructor. */ FModuleManager() {} private: /** * The currently loaded modules. */ std::unordered_map LoadedModules; /** * The currently loaded game module. */ IModuleInterface* GameModule; }; // ModuleManager.cpp #include "Modules/ModuleManager.h" #include FModuleManager& FModuleManager::Get() { static FModuleManager Instance; return Instance; } template T& FModuleManager::LoadModule(const std::string &InName) { auto Module = LoadedModules.find(InName); if (Module != LoadedModules.end()) { throw std::runtime_error(InName + " module has already been loaded!"); } std::unique_ptr ModuleInstance = std::make_unique(); ModuleInstance->StartupModule(); IModuleInterface* ModuleInterface = static_cast(ModuleInstance.get()); LoadedModules[InName] = ModuleInterface; if (ModuleInterface->IsGameModule()) { GameModule = ModuleInstance.get(); } T& TypedModule = *ModuleInstance; return TypedModule; } void FModuleManager::UnloadModule(const std::string& InName) { auto Module = LoadedModules.find(InName); if (Module == LoadedModules.end()) { return; } IModuleInterface* ModuleInstance = Module->second; ModuleInstance->ShutdownModule(); HMODULE LoadedModule = GetModuleHandle(ModuleInstance->GetName()); FreeLibrary(LoadedModule); LoadedModules.erase(Module); } IModuleInterface* FModuleManager::GetGameModule() const { return GameModule; } // HierarchyModule.h #pragma once #include "HierarchyModuleDefinitions.h" #include "Modules/ModuleInterface.h" class HIERARCHY_API FHierarchyModule : public IModuleInterface { public: /** * Default constructor. */ FHierarchyModule() = default; public: /** * Called after the module has been loaded. */ void StartupModule() override; /** * Called before the module is unloaded. */ void ShutdownModule() override; public: /** * Renders the hierarchy panel. */ void RenderHierarchy(); public: /** * Gets the name of the module. * * @return The name of the module. */ const char* GetName() override { return "Hierarchy"; } /** * Checks to see if the module is a game module. * * @return Whether or not the module is a game module. */ bool IsGameModule() const override { return false; } }; // HierarchyModule.cpp #include "HierarchyModule.h" #include "Modules/ModuleManager.h" #include "Logging/LogMacros.h" #include "imgui.h" void FHierarchyModule::StartupModule() { FROST_LOG_INFO("Initializing hierarchy module..."); // TODO: Implement module initialization FROST_LOG_INFO("Initialized hierarchy module!"); } void FHierarchyModule::ShutdownModule() { FROST_LOG_INFO("Shutting down hierarchy module..."); // TODO: Implement module cleanup FROST_LOG_INFO("Shut down hierarchy module!"); } void FHierarchyModule::RenderHierarchy() { ImGui::Begin("Hierarchy"); // TODO: Implement the hierarchy content ImGui::End(); } // FrostEd.h #pragma once #include "FrostEdPCH.h" #include "ImGuiLayer.h" class FROSTED_API FFrostEd : public FImGuiLayer { public: /** * Virtual destructor. */ virtual ~FFrostEd() = default; public: /** * Initializes the editor. */ static void Initialize(); public: /** * Called upon the FrostEd layer being attached. */ void OnAttach() override; /** * Called upon the FrostEd layer rendering ImGui. */ void OnImGuiRender() override; /** * Called upon the FrostEd layer being detached. */ void OnDetach() override; }; // FrostEd.cpp #include "FrostEd.h" #include "Modules/ModuleManager.h" #include "Logging/LogMacros.h" #include "Windows/WindowsApplication.h" #include "HierarchyModule.h" #include "imgui.h" void FFrostEd::Initialize() { FROST_LOG_INFO("Initializing FrostEd..."); // Editor initialization // ... FModuleManager::Get().LoadModule("Hierarchy"); FHierarchyModule& HierarchyModule = FModuleManager::Get().LoadModule("Hierarchy"); HierarchyModule.RenderHierarchy(); FWindowsApplication::Get()->GetLayerStack()->PushOverlay(new FFrostEd()); FROST_LOG_INFO("Initialized FrostEd!"); } void FFrostEd::OnAttach() { // Setup the editor // ... } void FFrostEd::OnImGuiRender() { static bool OptFullscreen = true; static bool OptPadding = false; static ImGuiDockNodeFlags DockspaceFlags = ImGuiDockNodeFlags_None; ImGuiWindowFlags WindowFlags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking; if (OptFullscreen) { const ImGuiViewport* Viewport = ImGui::GetMainViewport(); ImGui::SetNextWindowPos(Viewport->WorkPos); ImGui::SetNextWindowSize(Viewport->WorkSize); ImGui::SetNextWindowViewport(Viewport->ID); ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); WindowFlags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove; WindowFlags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus; } else { DockspaceFlags &= ~ImGuiDockNodeFlags_PassthruCentralNode; } if (DockspaceFlags & ImGuiDockNodeFlags_PassthruCentralNode) { WindowFlags |= ImGuiWindowFlags_NoBackground; } if (!OptPadding) { ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); } ImGui::Begin("FrostEd", (bool*)true, WindowFlags); if (!OptPadding) { ImGui::PopStyleVar(); } if (OptFullscreen) { ImGui::PopStyleVar(2); } ImGuiIO& IO = ImGui::GetIO(); if (IO.ConfigFlags & ImGuiConfigFlags_DockingEnable) { ImGuiID DockspaceID = ImGui::GetID("FrostEd"); ImGui::DockSpace(DockspaceID, ImVec2(0.0f, 0.0f), DockspaceFlags); } // Render the editor // ... ImGui::End(); } void FFrostEd::OnDetach() { // Cleanup the editor // ... FModuleManager::Get().UnloadModule("Hierarchy"); } // ModuleInterface.h #pragma once class IModuleInterface { public: /** * Virtual destructor. */ virtual ~IModuleInterface() = default; public: /** * Called after the module has been loaded. */ virtual void StartupModule() = 0; /** * Called before the module is unloaded. */ virtual void ShutdownModule() = 0; public: /** * Gets the name of the module. * * @return The name of the module. */ virtual const char* GetName() = 0; public: /** * Checks to see if the module is a game module. * * @return Whether or not the module is a game module. */ virtual bool IsGameModule() const { return false; } };