Макросы для разных конфигураций сборки или просто сборка другого файла? - PullRequest
0 голосов
/ 08 апреля 2020

Я работаю над игровым движком, настроенным со следующей структурой:

  • Engine (dll)
  • Engine Gui (. Exe) зависит от Engine.dll и Game.dll
  • Игра (dll / .exe) зависит от Engine.dll

Движок содержит точку входа (класс приложения), но создание точки входа происходит либо в Game или Engine Gui в зависимости от того, отлажена ли конфигурация сборки.

Поскольку точка входа одинакова как для Engine GUI, так и для Game, и мне нужны дополнительные функции для Engine Gui I использовал макросы, чтобы добавить эту функциональность, сохраняя чистоту сборки Game.

Пока не так много макросов, но я боюсь, что если я продолжу добавлять дополнительные функции для Engine GUI, это сделает класс грязный и нечитаемый.

Вот как это выглядит сейчас:

//Application.h
#ifndef CHEETAH_ENGINE_CORE_APPLICATION_H_
#define CHEETAH_ENGINE_CORE_APPLICATION_H_

#include "Core.h"

#include "Window.h"
#include "UpdateLayerQueue.h"
#include "../Events/ApplicationEvents.h"
#include "ImGUILayer.h"

namespace cheetah
{
    class CH_API Application
    {
    public:
        Application();
        virtual ~Application() = default;
        void run();

        void onEvent(Event& event);

        bool onWindowClose(WindowCloseEvent& event);
        bool onWindowResize(WindowResizeEvent& event);

        void pushLayer(UpdateLayer* layer);
        void pushOverlay(UpdateLayer* overlay);

        void exit();

        static Window& getWindow();
        static Application& getApplication();

    private:
        bool m_isRunning = true;
        UpdateLayerQueue m_updateLayerQueue;
        std::unique_ptr<Window> m_window;
        static Application* s_instance;

#ifdef DEBUG
    public:
        void setImGUILayer(ImGUILayer* layer);
        void test();
    private:
        ImGUILayer* m_imGUILayer = nullptr;
#endif // DEBUG
    };
}

#endif // !CHEETAH_ENGINE_CORE_APPLICATION_H_

//Application.cpp
#include "Application.h"

#include "Events/EventDispatcher.h"
#include "Events/ApplicationEvents.h"
#include "Core/Time.h"
#include "Input/Input.h"
#include "Renderer/Renderer.h"
#include "Metrics/MemoryMetrics.h"

#include <iostream>

namespace cheetah
{
    Application* Application::s_instance = nullptr;

    Application::Application()
    {
        s_instance = this;
        m_window = std::unique_ptr<Window>((Window::create()));
        m_window->setEventCallBack(std::bind(&Application::onEvent, this, std::placeholders::_1));
        Renderer::init();
    }

    void Application::run()
    {
        while (m_isRunning)
        {
            Time::getInstance()->setTime();
            Time::getInstance()->setDeltaTime();
            Time::getInstance()->setLastFrameTime();

            m_updateLayerQueue.onUpdate(Time::getDeltaTimeMsec());

#ifdef DEBUG
            if (m_imGUILayer != nullptr)
            {
                m_imGUILayer->begin();
                m_updateLayerQueue.onImGUIRender();
                m_imGUILayer->end();
            }

            MemoryMetrics::reset();
#endif // DEBUG

            m_window->onUpdate();
        }
    }

    // events
    void Application::onEvent(Event& event)
    {
        EventDispatcher dispatcher(event);

        dispatcher.dispatch<WindowCloseEvent>(EventTypes::WindowClose, std::bind(&Application::onWindowClose, this, std::placeholders::_1));
        dispatcher.dispatch<WindowResizeEvent>(EventTypes::WindowResize, std::bind(&Application::onWindowResize, this, std::placeholders::_1));

        m_updateLayerQueue.onEvent(event);
    }

    bool Application::onWindowResize(WindowResizeEvent& event)
    {
        Renderer::setViewPort(0, 0, event.m_width, event.m_height);
        return true;
    }

    bool Application::onWindowClose(WindowCloseEvent& event)
    {
        this->exit();
        return true;
    }

    void Application::exit()
    {
        m_isRunning = false;
        Renderer::shutDown();
    }

    // layers
    void Application::pushLayer(UpdateLayer* layer)
    {
        m_updateLayerQueue.pushLayer(layer);
    }

    void Application::pushOverlay(UpdateLayer* overlay)
    {
        m_updateLayerQueue.pushOverlay(overlay);
    }

    Application& Application::getApplication()
    {
        return *s_instance;
    }

    Window& Application::getWindow()
    {
        return *Application::getApplication().m_window;
    }

#ifdef DEBUG
    void Application::setImGUILayer(ImGUILayer* layer)
    {
        m_imGUILayer = layer;
        this->pushOverlay(m_imGUILayer);
    }
#endif // DEBUG

}

В настоящее время в качестве решения я думаю о создании отдельного файла "ApplicationDebug "и в зависимости от конфигурации сборки В сборку можно включить либо обычное приложение, либо файл ApplicationDebug (я использую CMake).

У этого есть свои недостатки, потому что мне по-прежнему нужны макросы для включения нужного файла, и потому что у меня теперь есть два файла, мне нужно было бы добавить функции и поддерживать их, и что, если мне нужна конфигурация отладки специально для Game или Engine, я бы добавил еще один дополнительный файл?

Каков будет лучший выбор в этом вопросе, или оба варианта неправильны, и есть ли лучшее решение?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...