当前位置: 首页 > news >正文

跟着cherno手搓游戏引擎【6】ImGui和ImGui事件

导入ImGui:

下载链接:

GitHub - TheCherno/imgui: Dear ImGui: Bloat-free Immediate Mode Graphical User interface for C++ with minimal dependencies

 新建文件夹,把下载好的文件放入对应路径:

 SRC下的premake5.lua文件:添加ImGui

workspace "YOTOEngine"		-- sln文件名architecture "x64"	configurations{"Debug","Release","Dist"}
-- https://github.com/premake/premake-core/wiki/Tokens#value-tokens
-- 组成输出目录:Debug-windows-x86_64
outputdir = "%{cfg.buildcfg}-%{cfg.system}-%{cfg.architecture}"
-- 包含相对解决方案的目录
IncludeDir={}
IncludeDir["GLFW"]="YOTOEngine/vendor/GLFW/include"
IncludeDir["Glad"]="YOTOEngine/vendor/Glad/include"
IncludeDir["ImGui"] ="YOTOEngine/vendor/imgui"
--项目中包含某包
include "YOTOEngine/vendor/GLFW"
include "YOTOEngine/vendor/Glad"
include "YOTOEngine/vendor/imgui"project "YOTOEngine"		--YOTOEngine项目location "YOTOEngine"--在sln所属文件夹下的YOTOEngine文件夹kind "SharedLib"--dll动态库language "C++"targetdir ("bin/" .. outputdir .. "/%{prj.name}") -- 输出目录objdir ("bin-int/" .. outputdir .. "/%{prj.name}")-- 中间目录pchheader "ytpch.h"pchsource "YOTOEngine/src/ytpch.cpp"-- 包含的所有h和cpp文件files{"%{prj.name}/src/**.h","%{prj.name}/src/**.cpp"}-- 包含目录includedirs{"%{prj.name}/src","%{prj.name}/vendor/spdlog-1.x/include","%{IncludeDir.GLFW}","%{IncludeDir.Glad}","%{IncludeDir.ImGui}"}links{"GLFW",-- GLFW.lib库链接到YOTOEngine项目中"Glad",-- Glad.lib库链接到YOTOEngine项目中"ImGui",-- ImGui.lib库链接到YOTOEngine项目中"opengl32.lib"}-- 如果是window系统filter "system:windows"cppdialect "C++17"-- On:代码生成的运行库选项是MTD,静态链接MSVCRT.lib库;-- Off:代码生成的运行库选项是MDD,动态链接MSVCRT.dll库;打包后的exe放到另一台电脑上若无这个dll会报错staticruntime "On"	systemversion "latest"	-- windowSDK版本-- 预处理器定义defines{"YT_PLATFORM_WINDOWS","YT_BUILD_DLL","YT_ENABLE_ASSERTS","GLFW_INCLUDE_NONE"-- 让GLFW不包含OpenGL}-- 编译好后移动Hazel.dll文件到Sandbox文件夹下postbuildcommands{("{COPY} %{cfg.buildtarget.relpath} ../bin/" .. outputdir .. "/Sandbox")}-- 不同配置下的预定义不同filter "configurations:Debug"defines "YT_DEBUG"buildoptions"/MDd"symbols "On"filter "configurations:Release"defines "YT_RELEASE"buildoptions"/MD"optimize "On"filter "configurations:Dist"defines "YT_DIST"buildoptions"/MD"optimize "On"project "Sandbox"location "Sandbox"kind "ConsoleApp"language "C++"targetdir ("bin/" .. outputdir .. "/%{prj.name}")objdir ("bin-int/" .. outputdir .. "/%{prj.name}")files{"%{prj.name}/src/**.h","%{prj.name}/src/**.cpp"}-- 同样包含spdlog头文件includedirs{"YOTOEngine/vendor/spdlog-1.x/include","YOTOEngine/src"}-- 引用YOTOEnginelinks{"YOTOEngine","GLFW","opengl32.lib"}filter "system:windows"cppdialect "C++17"staticruntime "On"systemversion "latest"defines{"YT_PLATFORM_WINDOWS"}filter "configurations:Debug"defines "YT_DEBUG"buildoptions"/MDd"symbols "On"filter "configurations:Release"defines "YT_RELEASE"buildoptions"/MD"optimize "On"filter "configurations:Dist"defines "YT_DIST"buildoptions"/MD"optimize "On"

在Platform下创建OpenGl,将imgui_impl_opengl3.cpp和.h加入到该文件夹。

并且更名:

150行改为:#include "backends/imgui_impl_opengl3_loader.h"

96行添加:#include"ytpch.h" 至此错误消除,导入成功。

创建ImGui层:

在YOTO下创建ImGui文件夹创建ImGuiLayer.cpp和.h:

ImGuiLayer.h:UI层的.h文件

#pragma once
#include"YOTO/Layer.h"
namespace YOTO {class YOTO_API ImGuiLayer:public Layer{public:ImGuiLayer();~ImGuiLayer();void OnAttach();void OnDetach();void OnUpdate();void OnEvent(Event& event);private:float m_Time = 0.0f;};}

ImGuiLayer.cpp:在层初始化的时候和刷新的时候对io的参数进行修改,达到修改UI的目的

#include"ytpch.h"
#include"ImGuiLayer.h"
#include"Platform/OpenGL/ImGuiOpenGLRenderer.h"
#include"GLFW/glfw3.h"
#include"YOTO/Application.h"
namespace YOTO {ImGuiLayer::ImGuiLayer():Layer("ImGuiLayer") {}ImGuiLayer::~ImGuiLayer() {}void ImGuiLayer::OnAttach(){//创建上下文ImGui::CreateContext();//设置颜色ImGui::StyleColorsDark();//配置类:ImGuiIOImGuiIO& io = ImGui::GetIO();io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;// 光标io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos;// imgui输入key对应glfw的key,临时的:最终会对应引擎自身的keyio.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 410");}void ImGuiLayer::OnDetach(){}void ImGuiLayer::OnUpdate() {//每帧刷新UI配置ImGuiIO& io = ImGui::GetIO();Application& app = Application::Get();//显示的size大小io.DisplaySize = ImVec2(app.GetWindow().GetWidth(), app.GetWindow().GetHeight());float time = (float)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 DemoImGui::ShowDemoWindow(&show);ImGui::Render();ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());}void ImGuiLayer::OnEvent(Event& event) {}
}

 Application.h:将Application变为单例,添加Get方法和GetWindow方法

#pragma once
#include"Core.h"
#include"Event/Event.h"
#include"Event/ApplicationEvent.h"
#include "YOTO/Window.h"
#include"YOTO/LayerStack.h"
namespace YOTO {class YOTO_API Application{public:Application();virtual ~Application();void Run();void OnEvent(Event &e);void PushLayer(Layer* layer);void PushOverlay(Layer* layer);inline static Application& Get() {return * s_Instance;}inline Window& GetWindow() { return *m_Window; }private:bool  OnWindowClosed(WindowCloseEvent& e);std::unique_ptr<Window>  m_Window;bool m_Running = true;LayerStack m_LayerStack;static Application* s_Instance;};//在客户端定义Application* CreateApplication();
}

  Application.cpp:构造时候令s_Instance = this

#include"ytpch.h"
#include "Application.h"#include"Log.h"
#include<glad/glad.h>
namespace YOTO {
#define BIND_EVENT_FN(x) std::bind(&x, this, std::placeholders::_1)Application* Application::s_Instance = nullptr;Application::Application() {YT_CORE_ASSERT(!s_Instance, "Application需要为空!")s_Instance = this;//智能指针m_Window = std::unique_ptr<Window>(Window::Creat());//设置回调函数m_Window->SetEventCallback(BIND_EVENT_FN(Application::OnEvent));unsigned int id;glGenBuffers(1, &id);}Application::~Application() {}/// <summary>/// 所有的Window事件都会在这触发,作为参数e/// </summary>/// <param name="e"></param>void Application::OnEvent(Event& e) {//根据事件类型绑定对应事件EventDispatcher dispatcher(e);dispatcher.Dispatch<WindowCloseEvent>(BIND_EVENT_FN(Application::OnWindowClosed));//输出事件信息YT_CORE_INFO("{0}",e);for (auto it = m_LayerStack.end(); it != m_LayerStack.begin();) {(*--it)->OnEvent(e);if (e.m_Handled)break;}}bool Application::OnWindowClosed(WindowCloseEvent& e) {m_Running = false;return true;}void Application::Run() {WindowResizeEvent e(1280, 720);if (e.IsInCategory(EventCategoryApplication)) {YT_CORE_TRACE(e);}if (e.IsInCategory(EventCategoryInput)) {YT_CORE_ERROR(e);}while (m_Running){glClearColor(1,0,1,1);glClear(GL_COLOR_BUFFER_BIT);for (Layer* layer : m_LayerStack) {layer->OnUpdate();}m_Window->OnUpdate();}}void Application::PushLayer(Layer* layer) {m_LayerStack.PushLayer(layer);layer->OnAttach();}void Application::PushOverlay(Layer* layer) {m_LayerStack.PushOverlay(layer);layer->OnDetach();}
}

YOTO.h:添加ImGuiLayer.h

#pragma once
#include "YOTO/Application.h"
#include"YOTO/Layer.h"
#include "YOTO/Log.h"
#include"YOTO/ImGui/ImGuiLayer.h"
//入口点
#include"YOTO/EntryPoint.h"

 SandboxApp.cpp:new且push这个层

#include<YOTO.h>
#include<stdio.h>class ExampleLayer:public YOTO::Layer
{
public:ExampleLayer():Layer("Example") {}void OnUpdate()override {//YT_CLIENT_INFO("测试update");}void	OnEvent(YOTO::Event& e)override {YT_CLIENT_TRACE("测试event{0}",e);}private:};class Sandbox:public YOTO::Application
{
public:Sandbox() {PushLayer(new ExampleLayer());PushLayer(new YOTO::ImGuiLayer());}~Sandbox() {}private:};YOTO::Application* YOTO::CreateApplication() {printf("helloworld");return new Sandbox();
}

 测试:

Bug:这里莫名爆红

注释掉:

 暂时解决(不知道这个bug会不会未来给我一脚)

运行成功但是什么都不能点,因为没添加事件。

 谢谢大家的支持,我会把每次可成改动的整个代码、类都粘上来,虽然有点儿多,但是防止迷路然后出现一些蜜汁bug。有问题欢迎评论区讨论(博主也是菜鸡,希望大佬指点)

ImGui事件:

ImGuiLayer.h:创建各种事件的函数声明

#pragma once
#include"YOTO/Layer.h"
#include"YOTO/Event/KeyEvent.h"
#include"YOTO/Event/MouseEvent.h"
#include"YOTO/Event/ApplicationEvent.h"
namespace YOTO {class YOTO_API ImGuiLayer:public Layer{public:ImGuiLayer();~ImGuiLayer();void OnAttach();void OnDetach();void OnUpdate();void OnEvent(Event& event);private:bool OnMouseButtonPressedEvent(MouseButtonPressedEvent& e);bool OnMouseButtonReleasedEvent(MouseButtonReleasedEvent& e);bool OnMouseMovedEvent(MouseMovedEvent& e);bool OnMouseScrolledEvent(MouseScrolledEvent& e);bool OnKeyPressedEvent(KeyPressedEvent& e);bool OnKeyReleasedEvent(KeyReleasedEvent& e);bool OnKeyTypedEvent(KeyTypedEvent& e);bool OnWindowResizedEvent(WindowResizeEvent& e);float m_Time = 0.0f;};}

 ImGuiLayer.h:绑定拦截器,实现方法

#include"ytpch.h"
#include"ImGuiLayer.h"
#include"Platform/OpenGL/ImGuiOpenGLRenderer.h"#include"YOTO/Application.h"#include<GLFW/glfw3.h>
#include<glad/glad.h>namespace YOTO {ImGuiLayer::ImGuiLayer():Layer("ImGuiLayer") {}ImGuiLayer::~ImGuiLayer() {}void ImGuiLayer::OnAttach(){//创建上下文ImGui::CreateContext();//设置颜色ImGui::StyleColorsDark();//配置类:ImGuiIOImGuiIO& io = ImGui::GetIO();io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;// 光标io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos;// imgui输入key对应glfw的key,临时的:最终会对应引擎自身的keyio.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 410");}void ImGuiLayer::OnDetach(){}void ImGuiLayer::OnUpdate() {//每帧刷新UI配置ImGuiIO& io = ImGui::GetIO();Application& app = Application::Get();//显示的size大小io.DisplaySize = ImVec2(app.GetWindow().GetWidth(), app.GetWindow().GetHeight());float time = (float)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 DemoImGui::ShowDemoWindow(&show);ImGui::Render();ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());}void ImGuiLayer::OnEvent(Event& event) {EventDispatcher dispatcher(event);dispatcher.Dispatch<MouseButtonPressedEvent>(YT_BIND_EVENT_FN(ImGuiLayer::OnMouseButtonPressedEvent));dispatcher.Dispatch<MouseButtonReleasedEvent>(YT_BIND_EVENT_FN(ImGuiLayer::OnMouseButtonReleasedEvent));dispatcher.Dispatch<MouseMovedEvent>(YT_BIND_EVENT_FN(ImGuiLayer::OnMouseMovedEvent));dispatcher.Dispatch<MouseScrolledEvent>(YT_BIND_EVENT_FN(ImGuiLayer::OnMouseScrolledEvent));dispatcher.Dispatch<KeyPressedEvent>(YT_BIND_EVENT_FN(ImGuiLayer::OnKeyPressedEvent));dispatcher.Dispatch<KeyReleasedEvent>(YT_BIND_EVENT_FN(ImGuiLayer::OnKeyReleasedEvent));dispatcher.Dispatch<KeyTypedEvent>(YT_BIND_EVENT_FN(ImGuiLayer::OnKeyTypedEvent));dispatcher.Dispatch<WindowResizeEvent>(YT_BIND_EVENT_FN(ImGuiLayer::OnWindowResizedEvent));}	bool ImGuiLayer::OnMouseButtonPressedEvent(MouseButtonPressedEvent& e){ImGuiIO& io = ImGui::GetIO();io.MouseDown[e.GetMouseButton()] = true;return false;//返回false是因为希望其他层也处理这个事件(事件穿透)}bool ImGuiLayer::OnMouseButtonReleasedEvent(MouseButtonReleasedEvent& e){ImGuiIO& io = ImGui::GetIO();io.MouseDown[e.GetMouseButton()] = false;return false;//返回false是因为希望其他层也处理这个事件(事件穿透)}bool ImGuiLayer::OnMouseMovedEvent(MouseMovedEvent& e){ImGuiIO &io = ImGui::GetIO();io.MousePos = ImVec2(e.GetX(), e.GetY());return false;//返回false是因为希望其他层也处理这个事件(事件穿透)}bool ImGuiLayer::OnMouseScrolledEvent(MouseScrolledEvent& e){ImGuiIO&io = ImGui::GetIO();io.MouseWheel += e.GetXOffset();io.MouseWheelH += e.GetYOffset();return false;//返回false是因为希望其他层也处理这个事件(事件穿透)}bool ImGuiLayer::OnKeyPressedEvent(KeyPressedEvent& e){ImGuiIO& io = ImGui::GetIO();io.KeysDown[e.GetKeyCode()] = true;io.KeyCtrl = io.KeysDown[GLFW_KEY_LEFT_CONTROL] || io.KeysDown[GLFW_KEY_RIGHT_CONTROL];io.KeyShift = io.KeysDown[GLFW_KEY_LEFT_SHIFT] || io.KeysDown[GLFW_KEY_RIGHT_SHIFT];io.KeyAlt = io.KeysDown[GLFW_KEY_LEFT_ALT] || io.KeysDown[GLFW_KEY_RIGHT_ALT];io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER];return false;}bool ImGuiLayer::OnKeyReleasedEvent(KeyReleasedEvent& e){ImGuiIO& io = ImGui::GetIO();io.KeysDown[e.GetKeyCode()] = false;return false;}bool ImGuiLayer::OnKeyTypedEvent(KeyTypedEvent& e){ImGuiIO& io = ImGui::GetIO();int keycode = e.GetKeyCode();if (keycode > 0 && keycode < 0x10000)io.AddInputCharacter((unsigned short)keycode);return false;}bool ImGuiLayer::OnWindowResizedEvent(WindowResizeEvent& e){ImGuiIO& io = ImGui::GetIO();io.DisplaySize = ImVec2(e.GetWidth(), e.GetHeight());io.DisplayFramebufferScale = ImVec2(1.0f, 1.0f);glViewport(0, 0, e.GetWidth(), e.GetHeight());return false;}
}

KeyEvent.h:添加KeyTypedEvent类

#pragma once
#include"Event.h"
#include "ytpch.h"namespace YOTO {/// <summary>/// 键盘事件基类/// </summary>class YOTO_API KeyEvent:public Event{public:inline int GetKeyCode() const { return m_KeyCode; }EVENT_CLASS_CATEGORY(EventCategoryKeyboard | EventCategoryInput)protected:KeyEvent(int keycode):m_KeyCode(keycode){}int m_KeyCode;};/// <summary>/// 键盘按下回调/// </summary>class YOTO_API KeyPressedEvent :public KeyEvent{public:KeyPressedEvent(int keycode, int repeatCount):KeyEvent(keycode),m_RepeatCount(repeatCount){}inline int GetRepeatCount() const { return m_RepeatCount; }std::string ToString() const override{std::stringstream ss;ss << "键盘按下事件:" << m_KeyCode << "(" << m_RepeatCount << "重复)";return ss.str();}//static EventType GetStaticType() { return EventType::KeyPressed; }//virtual EventType GetEventType()const override { return GetStaticType(); }//virtual const char* GetName()const override { return "KeyPressed"; }EVENT_CLASS_TYPE(KeyPressed)private:int m_RepeatCount;};/// <summary>/// 键盘释放回调/// </summary>class YOTO_API KeyReleasedEvent:public KeyEvent{public:KeyReleasedEvent(int keycode):KeyEvent(keycode){}std::string ToString()const override {std::stringstream ss;ss << "键盘释放事件:" << m_KeyCode;return ss.str(); }EVENT_CLASS_TYPE(KeyReleased)};/// <summary>/// 输入字符回调/// </summary>class YOTO_API KeyTypedEvent :public KeyEvent{public:KeyTypedEvent(int keycode):KeyEvent(keycode) { }std::string ToString()const override {std::stringstream ss;ss << "键盘类型事件:" << m_KeyCode;return ss.str();}EVENT_CLASS_TYPE(KeyTyped)};}

 WindowsWindow.cpp:Init里添加KeyTyped的回调:

#include "ytpch.h"
#include "WindowsWindow.h"
#include"YOTO/Event/ApplicationEvent.h"
#include"YOTO/Event/MouseEvent.h"
#include"YOTO/Event/KeyEvent.h"
#include<glad/glad.h>namespace YOTO {static bool s_GLFWInitialized = false;Window* Window::Creat(const WindowProps& props) {return new WindowsWindow(props);}WindowsWindow::WindowsWindow(const WindowProps& props) {Init(props);}WindowsWindow::~WindowsWindow() {ShutDown();}void WindowsWindow::Init(const WindowProps& props) {m_Data.Title = props.Title;m_Data.Width = props.Width;m_Data.Height = props.Height;YT_CORE_INFO("创建了{0},{1},{2}", props.Title, props.Width, props.Height);if (!s_GLFWInitialized) {int success = glfwInit();YT_CLIENT_ASSERT("不能创建新的glfw,{0}",success );glfwSetErrorCallback([](int error_code, const char* description) {YT_CORE_ERROR("GLFW错误:错误码({0}):{1} ", error_code, description);});s_GLFWInitialized = true;}m_Window = glfwCreateWindow((int)props.Width, (int)props.Height, m_Data.Title.c_str(), nullptr, nullptr);glfwMakeContextCurrent(m_Window); //在运行时获取OpenGL函数地址并将其保存在函数指针中供以后使用int status = gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);YT_CORE_ASSERT(status, "glad初始化错误");glfwSetWindowUserPointer(m_Window, &m_Data);SetVSync(true);//GLFW回调,每次改变调用lambda里的部分//窗口大小回调glfwSetWindowSizeCallback(m_Window, [](GLFWwindow* window, int width, int height) {WindowData& data=*(WindowData*)glfwGetWindowUserPointer(window);data.Width = width;data.Height = height;WindowResizeEvent event(width, height);//调用回调函数data.EventCallback(event);});//窗口关闭回调glfwSetWindowCloseCallback(m_Window, [](GLFWwindow* window) {WindowData& data = *(WindowData*)glfwGetWindowUserPointer(window);WindowCloseEvent event;data.EventCallback(event);});//键盘按键回调glfwSetKeyCallback(m_Window, [](GLFWwindow* window, int key, int scancode, int action, int mods) {WindowData& data = *(WindowData*)glfwGetWindowUserPointer(window);switch (action) {case GLFW_PRESS:{KeyPressedEvent event(key, 0);data.EventCallback(event);break;}case GLFW_RELEASE:{KeyReleasedEvent event(key);data.EventCallback(event);break;}case GLFW_REPEAT:{KeyPressedEvent event(key, 1);data.EventCallback(event);break;}}});//鼠标按键回调glfwSetMouseButtonCallback(m_Window, [](GLFWwindow* window, int button, int action, int mods) {WindowData& data = *(WindowData*)glfwGetWindowUserPointer(window);switch (action){case GLFW_PRESS:{MouseButtonPressedEvent event(button);data.EventCallback(event);break;}case GLFW_RELEASE:{MouseButtonReleasedEvent event(button);data.EventCallback(event);break;}}});//滚轮回调glfwSetScrollCallback(m_Window, [](GLFWwindow* window, double xoffset, double yoffset) {WindowData& data = *(WindowData*)glfwGetWindowUserPointer(window);MouseScrolledEvent event((float)xoffset, (float)yoffset);data.EventCallback(event);});//鼠标位置回调glfwSetCursorPosCallback(m_Window, [](GLFWwindow* window, double xpos, double ypos) {WindowData& data = *(WindowData*)glfwGetWindowUserPointer(window);MouseMovedEvent event((float)xpos, (float)ypos);data.EventCallback(event);});//字符回调glfwSetCharCallback(m_Window, [](GLFWwindow* window, unsigned int codepoint) {WindowData& data = *(WindowData*)glfwGetWindowUserPointer(window);KeyTypedEvent event(codepoint);data.EventCallback(event);});}void WindowsWindow::ShutDown() {glfwDestroyWindow(m_Window);}void WindowsWindow::OnUpdate(){//轮询事件glfwPollEvents();//交换缓冲区glfwSwapBuffers(m_Window);}void WindowsWindow::SetVSync(bool enable) {if (enable)glfwSwapInterval(1);elseglfwSwapInterval(0);m_Data.VSync = enable;}bool WindowsWindow::IsVSync() const {return m_Data.VSync;}
}

Core.h:添加绑定事件的定义

#pragma once
//用于dll的宏
#ifdef YT_PLATFORM_WINDOWS
#ifdef YT_BUILD_DLL
#define YOTO_API __declspec(dllexport) 
#else
#define YOTO_API __declspec(dllimport) #endif // DEBUG
#else
#error YOTO_ONLY_SUPPORT_WINDOWS
#endif // YOTO_PLATFORM_WINDOWS#ifdef YT_ENABLE_ASSERTS
#define YT_CLIENT_ASSERT(x,...) {if(!(x)){YT_CLIENT_ERROR("断言错误:{0}",__VA_ARGS__);__debugbreak();}}
#define YT_CORE_ASSERT(x,...) {if(!(x)){YT_CORE_ERROR("断言错误:{0}",__VA_ARGS__);__debugbreak();}}
#else
#define YT_CLIENT_ASSERT(x,...)
#define YT_CORE_ASSERT(x,...)#endif // YT_ENABLE_ASSERTS#define BIT(x)(1<<x)
//绑定事件定义
#define YT_BIND_EVENT_FN(fn) std::bind(&fn, this, std::placeholders::_1)

测试:

 cool现在ImGui就能接收到咱的事件了。

相关文章:

  • MyBatis 使用报错:org.xml.sax.SAXParseException 元素内容必须由格式正确的字符数据或标记组成
  • OpenHarmony 应用开发入门 (一、环境搭建及第一个Hello World)
  • 数据结构之二叉搜索树
  • 尚硅谷Nginx高级配置笔记
  • 集成开发环境(IDE)介绍
  • 【Vue3】3-2 : 组件的概念及组件的基本使用方式
  • 机器人持续学习基准LIBERO系列6——获取并显示实际深度图
  • 用Python优雅地写出数学表达式的LaTeX代码
  • c# 自定义 滑块TrackBar
  • 树莓派4B +Ubuntu20.04+ROS1的使用(2)
  • 4、python列表Lists
  • Python实现自动化办公(使用第三方库操作Excel)
  • openlayers [六] 地图交互 interaction 详解
  • macOS安装VMware Fusion 13试用版本
  • Spring-BeanPostProcessor PostConstruct init InitializingBean 执行顺序
  • 时间复杂度分析经典问题——最大子序列和
  • 【vuex入门系列02】mutation接收单个参数和多个参数
  • 2018一半小结一波
  • CentOS学习笔记 - 12. Nginx搭建Centos7.5远程repo
  • MQ框架的比较
  • Next.js之基础概念(二)
  • Python语法速览与机器学习开发环境搭建
  • React+TypeScript入门
  • Spring Security中异常上抛机制及对于转型处理的一些感悟
  • Sublime Text 2/3 绑定Eclipse快捷键
  • 半理解系列--Promise的进化史
  • 每个JavaScript开发人员应阅读的书【1】 - JavaScript: The Good Parts
  • 时间复杂度与空间复杂度分析
  • 世界上最简单的无等待算法(getAndIncrement)
  • 手写一个CommonJS打包工具(一)
  • 王永庆:技术创新改变教育未来
  • 物联网链路协议
  • 一文看透浏览器架构
  • 用element的upload组件实现多图片上传和压缩
  • 原生JS动态加载JS、CSS文件及代码脚本
  • 远离DoS攻击 Windows Server 2016发布DNS政策
  • 数据可视化之下发图实践
  • 数据库巡检项
  • !!java web学习笔记(一到五)
  • #define、const、typedef的差别
  • #Java第九次作业--输入输出流和文件操作
  • #Spring-boot高级
  • $emit传递多个参数_PPC和MIPS指令集下二进制代码中函数参数个数的识别方法
  • (02)Cartographer源码无死角解析-(03) 新数据运行与地图保存、加载地图启动仅定位模式
  • (13):Silverlight 2 数据与通信之WebRequest
  • (delphi11最新学习资料) Object Pascal 学习笔记---第8章第5节(封闭类和Final方法)
  • (Redis使用系列) Springboot 使用redis实现接口Api限流 十
  • (论文阅读23/100)Hierarchical Convolutional Features for Visual Tracking
  • (篇九)MySQL常用内置函数
  • (一) storm的集群安装与配置
  • (原)Matlab的svmtrain和svmclassify
  • (转)EXC_BREAKPOINT僵尸错误
  • **python多态
  • .bat批处理(七):PC端从手机内复制文件到本地
  • .desktop 桌面快捷_Linux桌面环境那么多,这几款优秀的任你选