用了两年的Macbook开不了机了,耽搁了几天,积累了多年的材料都没了。伤心。
前语
完好的引擎都支撑修改的功用,提升开发功率,也让美术、交互等人物参加进来,通过点击拖拽就能完成一些原型作用。
虚幻5的修改器:
这节咱们引进一个非常知名的、轻量的GUI结构,完成修改的功用。
集成imGui
imGui轻量简练、功用很强壮,能完成非常丰富、艳丽的修改作用。
下载了最新的imGui代码到本地,代码结构简单,分烘托后端、Demo、辅助工具、控件。
clone imGui
根目录下,clone imgui代码到vendor目录下
git submodule add https://github.com/ocornut/imgui.git Sandbox/Hazel/vendor/imgui
更新CMake,添加需求参加编译的源码,include需求的头文件
后端咱们选用OpenGL,所以将backends/imgui_impl_opengl3.h、imgui_impl_opengl3.cpp、imgui_impl_opengl3_loader.h三个文件归入到编译列表中。如果你用的是Metal、或许vulkan等后端,则需求添加上对应的编译文件。
更好的做法是,根据编译条件,比如根据window、mac、linux等环境变量,添加对应的后端。此处图省事,只添加了OpenGL,不对平台做兼容。
Sandbox/Hazel/CMakeLists.txt
...
file (GLOB SRC_LIST_IMGUI
vendor/imgui/*.h
vendor/imgui/*.cpp
)
set(SRC_LIST_IMGUI_BACKENDS
vendor/imgui/backends/imgui_impl_opengl3.h
vendor/imgui/backends/imgui_impl_opengl3.cpp
vendor/imgui/backends/imgui_impl_opengl3_loader.h
vendor/imgui/backends/imgui_impl_glfw.h
vendor/imgui/backends/imgui_impl_glfw.cpp
)
set(SRC_LIST
...
src/Hazel/ImGui/ImGuiLayer.cpp
src/Hazel/ImGui/ImGuiLayer.h
)
add_library(hazel STATIC ${SRC_LIST} ${SRC_LIST_IMGUI} ${SRC_LIST_IMGUI_BACKENDS})
...
target_include_directories(${PROJECT_NAME} PUBLIC
...
vendor/imgui
vendor/imgui/backends
...
前置开发-完善Application
添加获取Application 和 window的接口,后边封装ImGui用的上。
Sandbox/Hazel/src/Hazel/Application.h
inline Window& GetWindow() {
return *m_Window;
}
inline static Application& Get() {
return *s_Instance;
}
完善PushLayer PushOverlayer,添加layer的OnAttach(). Sandbox/Hazel/src/Hazel/Application.cpp
namespace Hazel{
...
Application* Application::s_Instance = nullptr;
Application::Application() {
s_Instance = this;
}
void Application::PushLayer(Layer *layer) {
m_LayerStack.PushLayer(layer);
layer->OnAttach();
}
void Application::PushOverlay(Layer *layer) {
m_LayerStack.PushOverlay(layer);
layer->OnAttach();
}
完成ImGuiLayer
ImGui的操作封装到ImGuiLayer类中。ImGuiLayer承继Layer,烘托到整个界面的最上层。
创建文件夹ImGui及ImGuiLayer.h/.cpp文件
重写基类Layer的虚函数, Sandbox/Hazel/src/Hazel/ImGui/ImGuiLayer.h
#pragma once
#include "Layer.h"
namespace Hazel {
class ImGuiLayer : public Layer{
public:
ImGuiLayer();
~ImGuiLayer() override;
void OnAttach() override;
void OnDetach() override;
void OnUpdate() override;
void OnEvent(Event &event) override;
private:
float m_Time = 0.0f;
};
}
imGui的运用不是咱们的要点,参阅下面注释了解。
要点看两个函数。OnAttach()完成了初始化, OnUpdate()完成每帧的更新,这儿咱们ImGui::ShowDemoWindow显示一个简单的界面.
Sandbox/Hazel/src/Hazel/ImGui/ImGuiLayer.cpp
#include <imgui.h>
#include <GLFW/glfw3.h>
#include <backends/imgui_impl_opengl3.h>
#include "ImGuiLayer.h"
#include "Application.h"
namespace Hazel {
ImGuiLayer::~ImGuiLayer() {
}
// 初始化ImGui
void ImGuiLayer::OnAttach() {
ImGui::CreateContext();
ImGui::StyleColorsDark();
// ImGuiIO用于设置输入事情、窗口特点
ImGuiIO io = ImGui::GetIO();
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos;
// 装备需求监听的按键
io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB;
io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT;
io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT;
io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP;
io.KeyMap[ImGuiKey_DownArrow] = GLFW_KEY_DOWN;
io.KeyMap[ImGuiKey_PageUp] = GLFW_KEY_PAGE_UP;
io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN;
io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME;
io.KeyMap[ImGuiKey_End] = GLFW_KEY_END;
io.KeyMap[ImGuiKey_Insert] = GLFW_KEY_INSERT;
io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE;
io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE;
io.KeyMap[ImGuiKey_Space] = GLFW_KEY_SPACE;
io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER;
io.KeyMap[ImGuiKey_Escape] = GLFW_KEY_ESCAPE;
io.KeyMap[ImGuiKey_A] = GLFW_KEY_A;
io.KeyMap[ImGuiKey_C] = GLFW_KEY_C;
io.KeyMap[ImGuiKey_V] = GLFW_KEY_V;
io.KeyMap[ImGuiKey_X] = GLFW_KEY_X;
io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y;
io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z;
ImGui_ImplOpenGL3_Init("#version 330");
}
void ImGuiLayer::OnDetach() {
}
//
void ImGuiLayer::OnUpdate() {
ImGuiIO& io = ImGui::GetIO();
Application& app = Application::Get();
io.DisplaySize = ImVec2( app.GetWindow().GetWidth(), 2 * app.GetWindow().GetHeight());
float time = glfwGetTime();
io.DeltaTime = m_Time > 0.0f ? (time - m_Time) : (1.0f / 60.0f);
m_Time = time;
ImGui_ImplOpenGL3_NewFrame();
ImGui::NewFrame();
static bool show = true;
ImGui::ShowDemoWindow(&show);
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
}
void ImGuiLayer::OnEvent(Hazel::Event &event) {
Layer::OnEvent(event);
}
ImGuiLayer::ImGuiLayer() : Layer("ImGuiLayer"){}
}
更新Hazel.h文件
#include "Hazel/ImGui/ImGuiLayer.h"
添加ImGuiLayer
调用的逻辑只有一行. Sandbox/src/SandBoxApp.cpp
Sandbox(){
PushOverlay(new ExampleLayer());
PushOverlay(new Hazel::ImGuiLayer());
}
完成作用
不出意外的话, 界面上会出现一个imGui的列表
shit!暂时还有点丑陋,咱们后边继续完善。
本节完好代码参阅Integrated imGui