我们首先要理解顺序,如果我们以事件来说,先渲染谁,再渲染谁,那么他们有个顺序123456……大概这样。但是图层是后渲染的在先渲染的前面,所以实际上我们渲染的顺序应该是987654……

新增的代码

在Hazel文件夹下创建了四套代码,Layer.h,Layer.cpp,LayerStack.h,LayerStack.cpp。

layer.h

#pragma once

#include "Hazel/Core.h"
#include "Hazel/Events/Event.h"

namespace Hazel {

        class HAZEL_API Layer
        {
        public:
                Layer(const std::string& name = "Layer");
                virtual ~Layer();

                virtual void OnAttach() {}
                virtual void OnDetach() {}
                virtual void OnUpdate() {}
                virtual void OnEvent(Event& event) {}

                inline const std::string& GetName() const { return m_DebugName; }
        protected:
                std::string m_DebugName;
        };
}

Layer.cpp

#include "hzpch.h"
#include "Layer.h"

namespace Hazel {

        Layer::Layer(const std::string& debugName)
                : m_DebugName(debugName)
        {
        }

        Layer::~Layer()
        {
        }
}

LayerStack.h

#pragma once

#include "Hazel/Core.h"
#include "Layer.h"

#include <vector>

namespace Hazel {

        class HAZEL_API LayerStack
        {
        public:
                LayerStack();
                ~LayerStack();

                void PushLayer(Layer* layer);
                void PushOverlay(Layer* overlay);
                void PopLayer(Layer* layer);
                void PopOverlay(Layer* overlay);

                std::vector<Layer*>::iterator begin() { return m_Layers.begin(); }
                std::vector<Layer*>::iterator end() { return m_Layers.end(); }

        private:
                std::vector<Layer*> m_Layers;
                std::vector<Layer*>::iterator m_LayerInsert;
        };
}

分为两套层,一个普通Layer(给GamePlay),一个OverLay(给Debug,ImGui之类的)(总之最后画)。

std::vector<Layer*>::iterator begin() { return m_Layers.begin(); }

std::vector<Layer*>::iterator end() { return m_Layers.end(); }

是为了把LayerStack包装成一个可迭代容器,对外暴露的就是这个底层的vector<Layer*>的起止迭代器。

m_Layersm_LayerInsert分别是层指针数组和普通层与OverLay的分界层

layerStack.cpp

#include "hzpch.h"
#include "LayerStack.h"

namespace Hazel {
        
        LayerStack::LayerStack()
        {
                m_LayerInsert = m_Layers.begin();
        }

        LayerStack::~LayerStack()
        {
                for (Layer* layer : m_Layers)
                        delete layer;
        }

        void LayerStack::PushLayer(Layer* layer)
        {
                m_LayerInsert = m_Layers.emplace(m_LayerInsert, layer);
        }

        void LayerStack::PushOverlay(Layer* overlay)
        {
                m_Layers.emplace_back(overlay);
        }

        void LayerStack::PopLayer(Layer* layer)
        {
                auto it = std::find(m_Layers.begin(), m_Layers.end(), layer);
                if (it != m_Layers.end())
                {
                        m_Layers.erase(it);
                        m_LayerInsert--;
                }
        }

        void LayerStack::PopOverlay(Layer* overlay)
        {
                auto it = std::find(m_Layers.begin(), m_Layers.end(), overlay);
                if (it != m_Layers.end())
                        m_Layers.erase(it);
        }
}

普通Layer和OverLay分别从begin和end进入,m_LayerInsert永远指向第一个OverLay,遍历顺序即从游戏逻辑到调试UI。

其他的修改部分

Application.h

#pragma once

#include "Core.h"
#include "Window.h"
#include "Hazel/LayerStack.h"
#include "Hazel/Events/Event.h"
#include "Hazel/Events/ApplicationEvent.h"

namespace Hazel
{
    class HAZEL_API Application
    {
    public:
        Application();
        virtual ~Application();

        void Run();

        void OnEvent(Event& e);

        void PushLayer(Layer* layer);
        void PushOverlay(Layer* layer);
    private:
        bool OnWindowClose(WindowCloseEvent& e);

        std::unique_ptr<Window> m_Window;
        bool m_Running = true;
        LayerStack m_LayerStack;
    };

    //去定义在客户端中
    Application* CreateApplication();
}

Application.cpp

#include "hzpch.h"
#include "Application.h"


#include "Hazel/Log.h"

#include<GLFW/glfw3.h>

namespace Hazel
{
#define BIND_EVENT_FN(x) std::bind(&Application::x, this, std::placeholders::_1)

    Application::Application()
    {
        m_Window = std::unique_ptr<Window>(Window::Create());
        m_Window->SetEventCallback(BIND_EVENT_FN(OnEvent));
    }

    Application::~Application()
    {
    }

    void Application::PushLayer(Layer* layer)
    {
        m_LayerStack.PushLayer(layer);
    }

    void Application::PushOverlay(Layer* layer)
    {
        m_LayerStack.PushOverlay(layer);
    }

    void Application::OnEvent(Event& e)
    {
        EventDispatcher dispatcher(e);
        dispatcher.Dispatch<WindowCloseEvent>(BIND_EVENT_FN(OnWindowClose));

        HZ_CORE_TRACE("{0}", e.ToString());

        for (auto it = m_LayerStack.end(); it != m_LayerStack.begin();)
        {
            (*--it)->OnEvent(e);
            if (e.Handled)
                break;
        }
    }

    void Application::Run()
    {
        while (m_Running)
        {
            glClearColor(1, 0, 1, 1);
            glClear(GL_COLOR_BUFFER_BIT);

            for (Layer* layer : m_LayerStack)
                layer->OnUpdate();
            m_Window->OnUpdate();
        }
    }

    bool Application::OnWindowClose(WindowCloseEvent& e)
    {
        m_Running = false;
        return true;
    }
}

Hazel.h

#pragma once

//For use by Hazel application

#include "Hazel/Application.h"
#include "Hazel/Layer.h"
#include "Hazel/Log.h"

//------EntryPoint---------------------
#include "Hazel/EntryPoint.h"
//-------------------------------------

关于之前有关于本身构建的问题:(我们统一将两个项目Hazel和Sandbox都修改添加一行buildoptions。(这东西貌似也能填/utf-8,后面研究一下)

filter "configurations:Debug"
        defines "HZ_DEBUG"
        buildoptions "/MDd"
        symbols "On"

filter "configurations:Release"
        defines "HZ_RELEASE"
        buildoptions "/MD"
        symbols "On"

filter "configurations:Dist"
        defines "HZ_DIST"
        buildoptions "/MD"
        symbols "On"

sandbox的代码先不提,这里有个bug:

看了一下源码,似乎是偷偷把之前的m_Handled(在Event.h中)改成了Handled,同时将其protected的权限改为了公开的!这里要改一下!

Sandbox.cpp

#include "sandpch.h"
#include <Hazel.h>


class ExampleLayer : public Hazel::Layer
{
public:
    ExampleLayer()
        : Layer("Example")
    {
    }

    void OnUpdate() override
    {
        HZ_INFO("ExampleLayer::Update");
    }

    void OnEvent(Hazel::Event& event) override
    {
        HZ_TRACE("{0}", event.ToString());
    }
};

class Sandbox : public Hazel::Application
{
public:
    Sandbox()
    {
        PushLayer(new ExampleLayer());
    }

    ~Sandbox()
    {

    }
};

Hazel::Application* Hazel::CreateApplication()
{
    return new Sandbox();
}