CCCPaste

50a8d325dee6a

// 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; }
};