美文网首页
Dragon Engine:GUI

Dragon Engine:GUI

作者: Dragon_boy | 来源:发表于2020-08-15 16:09 被阅读0次

    这一节介绍GUI的实现。我们这里使用开源库ImGui

    首先我们将GUI分离为一个单独的层,创建ImGuiLayer:
    ImGuiLayer.h:

    #pragma once
    
    #include "Dragon/Core/Layer.h"
    
    #include "Dragon/Events/ApplicationEvent.h"
    #include "Dragon/Events/KeyEvents.h"
    #include "Dragon/Events/MouseEvent.h"
    
    namespace Dragon
    {
        class ImGuiLayer : public Layer
        {
        public:
            ImGuiLayer();
            ~ImGuiLayer() = default;
    
            virtual void OnAttach() override;
            virtual void OnDetach() override;
            virtual void OnImGuiRender() override;
            //virtual void OnEvent(Event& e) override;
    
            void Begin();
            void End();
        private:
            float m_Time = 0.0f;
        };
    }
    

    函数先不介绍,直接看实现:

    namespace Dragon
    {
        ImGuiLayer::ImGuiLayer()
            :Layer("ImGuiLayer")
        {
    
        }
    
        void ImGuiLayer::OnAttach()
        {
            // Setup Dear ImGui context
            IMGUI_CHECKVERSION();
            ImGui::CreateContext();
            ImGuiIO& io = ImGui::GetIO(); (void)io;
            io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;       // Enable Keyboard Controls
            //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad Controls
            io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;           // Enable Docking
            io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;         // Enable Multi-Viewport / Platform Windows
            //io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoTaskBarIcons;
            //io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoMerge;
    
            //// Setup Dear ImGui style
            ImGui::StyleColorsDark();
            ////ImGui::StyleColorsClassic();
    
            //// When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.
            ImGuiStyle& style = ImGui::GetStyle();
            if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
            {
                style.WindowRounding = 0.0f;
                style.Colors[ImGuiCol_WindowBg].w = 1.0f;
            }
    
            Application& app = Application::Get();
            GLFWwindow* window = static_cast<GLFWwindow*>(app.GetWindow().GetNativeWindow());
    
            // Setup Platform/Renderer bindings
            ImGui_ImplGlfw_InitForOpenGL(window, true);
            ImGui_ImplOpenGL3_Init("#version 410");
        }
    
        void ImGuiLayer::OnDetach()
        {
            ImGui_ImplOpenGL3_Shutdown();
            ImGui_ImplGlfw_Shutdown();
            ImGui::DestroyContext();
        }
    
        void ImGuiLayer::Begin()
        {
            ImGui_ImplOpenGL3_NewFrame();
            ImGui_ImplGlfw_NewFrame();
            ImGui::NewFrame();
        }
    
        void ImGuiLayer::End()
        {
            ImGuiIO& io = ImGui::GetIO();
            Application& app = Application::Get();
            io.DisplaySize = ImVec2((float)app.GetWindow().GetWidth(), (float)app.GetWindow().GetHeight());
    
            // Rendering
            ImGui::Render();
            ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
    
            if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
            {
                GLFWwindow* backup_current_context = glfwGetCurrentContext();
                ImGui::UpdatePlatformWindows();
                ImGui::RenderPlatformWindowsDefault();
                glfwMakeContextCurrent(backup_current_context);
            }
        }
    
        void ImGuiLayer::OnImGuiRender()
        {
            /*static bool show = true;
            ImGui::ShowDemoWindow(&show);*/
        }
    
    }
    

    OnAttach()函数初始化ImGui,创建上下文,然后获取输入输出io,并设置io的标识,设置按键标识,Docking标识(即GUI窗口可以相互内嵌),视口标识(和OpenGL视口配套)。ImGui::StyleColorsDark()设置样式,默认有三种可选。然后获取样式,设置GUI窗口的背景以及圆角。ImGui_ImplGlfw_InitForOpenGL是ImGui为GLFW提供的一个方法,可以传入一个GLFW窗口指针,然后配置好所需的参数,ImGui_ImplOpenGL3_Init是ImGui为OpenGL提供的一个方法,可以为某一版本的OpenGL配置好所需的参数。

    OnDetach()函数没什么好说的。

    Begin()函数调用了三个NewFrame方法,这是必须的,相当于新建窗口的意思。

    OnImGuiRender()函数是所绘制的GUI,大家可以把注释取消渲染一下ImGui自带的demo窗口看一下,里面提供了许多示例。

    End()函数主要是渲染GUI数据,并更新,这是示例中的代码。

    重点是OnImGuiRender()函数,它定义在Layer类中,这样我们可以在客户端类中定义同名函数来设置GUI,比如:

    virtual void OnImGuiRender() override
        {
            ImGui::Begin("Inspector");
            if(m_GameObjectsName.size()!=0)
                GameObjectGui(m_GameObjectsName[m_GameObjectsItem]);
            ImGui::NewLine();
            ImGui::Text("Shader List");
            
            const char** shaderList = StringToChar(m_ShaderList);
            ImGui::Combo("", &m_ShaderListItem, shaderList, m_ShaderList.size());
            ShaderGui(m_ShaderList[m_ShaderListItem]);
    
            ImGui::NewLine();
            ImGui::Text("Post Effect");
            ImGui::Checkbox("Opposition", &m_Opposition);
            if (m_Opposition)
            {
                ImGui::SameLine();
                ImGui::SliderFloat("Opposition Weight", &m_OppositionWeight, 0.0f, 1.0f);
            }
            ImGui::Checkbox("Gray", &m_Gray);
            if (m_Gray)
            {
                ImGui::SameLine();
                ImGui::SliderFloat("Gray Weight", &m_GrayWeight, 0.0f, 1.0f);
            }
            ImGui::Checkbox("Kernel", &m_Kernel);
            if (m_Kernel)
            {
                ImGui::SameLine();
                ImGui::SliderFloat("Kernel Weight", &m_KernelWeight, 0.0f, 1.0);
            }
            ImGui::Checkbox("Blur", &m_Blur);
            if (m_Blur)
            {
                ImGui::SameLine();
                ImGui::SliderFloat("Blur Weight", &m_BlurWeight, 0.0f, 1.0f);
            }
            ImGui::Checkbox("Edge Detection", &m_EdgeDetection);
            if (m_EdgeDetection)
            {
                ImGui::SameLine();
                ImGui::SliderFloat("Edge Detection Weight", &m_EdgeDetectionWeight, 0.0f, 1.0f);
            }
    
    
            ImGui::End();
    
            ImGui::Begin("Game Object");
            ImGui::Text("Geometry");
            m_CubeButtonClicked = ImGui::Button("Cube");
            ImGui::SameLine();
            ImGui::Button("Sphere");
            ImGui::SameLine();
            ImGui::Button("Quad");
            ImGui::Button("Import Model");
            ImGui::NewLine();
            ImGui::Text("Light Source");
            ImGui::Button("Point Light");
            ImGui::SameLine();
            ImGui::Button("Directional Light");
            ImGui::SameLine();
            ImGui::Button("Spot Light");
            ImGui::SameLine();
            ImGui::Button("Area Light");
            ImGui::Button("Sky Box");
            ImGui::NewLine();
            ImGui::Button("Orthographic Camera");
            ImGui::SameLine();
            ImGui::Button("Perspective Camera");
            ImGui::End();
    
            ImGui::Begin("Outline View");
            const char** GameObjectList = StringToChar(m_GameObjectsName);
            ImGui::ListBox("", &m_GameObjectsItem, GameObjectList, m_GameObjectsName.size(), m_GameObjectsName.size());
            ImGui::End();
        }
    

    这些组件函数可以从ImGui的文档里看到用法,都是GUI的那一套,这是我的GUI效果:


    目前可以点击创建一些内置几何体,并调整TRS以及赋予shader,调整相关参数。

    下一节介绍预编译模块(使用CMake或Premake),来方便整理外部模块,方便别人能够使用你的程序。

    项目github地址:https://github.com/Dragon-Baby/Dragon

    相关文章

      网友评论

          本文标题:Dragon Engine:GUI

          本文链接:https://www.haomeiwen.com/subject/pweadktx.html