跟着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就能接收到咱的事件了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/410508.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

好消息,Linux Kernel 6.7正式发布!

据有关资料显示&#xff0c;该版本是有史以来合并数最多的版本之一&#xff0c;包含 17k 个非合并 commit&#xff0c;实际合并的超过1K个。 那么该版本主要有哪边变化呢&#xff1f;下面我来一一列举一下&#xff1a; Bcachefs文件系统已被合并到主线内核&#xff0c;这是一款…

23111 网络编程 day4

思维导图 #include<myhead.h> #define SER_PORT 69 #define SER_IP "192.168.125.180"int do_download(int cfd,struct sockaddr_in sin) {//向服务器发送下载请求char buf[516]"";char fileName[40]"";printf("请输入文件名&#xf…

Simulink|双机并联自适应虚拟阻抗下垂控制仿真模型

目录 主要内容 模型研究 结果一览 下载链接 主要内容 风电高渗透率下&#xff0c;电力系统对风电场频率调节能力提出了技术要求。考虑风机惯性控制和变桨距控制的频率响应能力&#xff0c;提出将储能与风电自身调频手段相结合&#xff0c;参与系统频率调节。模型…

Spring高手之路-Spring在业务中常见的使用方式

目录 通过IOC实现策略模式 通过AOP实现拦截增强 1.参数检验 2.缓存逻辑 3.日志记录 通过Event异步解耦 通过Spring管理事务 1.声明式事务 2.编程式事务 3.需要注意的问题 不能在事务中处理分布式缓存 不能在事务中执行 RPC 操作 不过度使用声明式事务 通过IOC实现…

C++初入(四)

1.万能头文件 #include <bits/stdc.h> 里面包含了大量我们日常所需的头文件&#xff0c;如果使用它&#xff0c;我们就可以减少大量时间去写头文件&#xff0c;但是其实在平常练习和实际运用中&#xff0c;该头文件几乎没有实际价值&#xff0c;原因&#xff1a;1.里面…

SpringBoot教程(七) | SpringBoot解决跨域问题

SpringBoot教程(七) | SpringBoot解决跨域问题 上篇文章我们介绍了SpringBoot的拦截器的写法&#xff0c;其中有一个比较重要的步骤&#xff0c;就是把我们写好的拦截器注册到Spring的一个配置类中&#xff0c;这个类是实现了WebMvcConfigurer 接口&#xff0c;这个类很重要&a…

翻译: Streamlit从入门到精通 高级用法缓存Cache和Session 五

Streamlit从入门到精通 系列&#xff1a; 翻译: Streamlit从入门到精通 基础控件 一翻译: Streamlit从入门到精通 显示图表Graphs 地图Map 主题Themes 二翻译: Streamlit从入门到精通 构建一个机器学习应用程序 三翻译: Streamlit从入门到精通 部署一个机器学习应用程序 四 …

Pytorch基础知识点复习

文章目录 并行计算单卡训练多卡训练单机多卡DP多机多卡DDPDP 与 DDP 的优缺点 PyTorch的主要组成模块Pytorch的主要组成模块包括那些呢&#xff1f;Dataset和DataLoader的作用是什么&#xff0c;我们如何构建自己的Dataset和DataLoader&#xff1f;神经网络的一般构造方法&…

.NET国产化改造探索(三)、银河麒麟安装.NET 8环境

随着时代的发展以及近年来信创工作和…废话就不多说了&#xff0c;这个系列就是为.NET遇到国产化需求的一个闭坑系列。接下来&#xff0c;看操作。 上一篇介绍了如何在银河麒麟操作系统上安装人大金仓数据库&#xff0c;这篇文章详细介绍下在银河麒麟操作系统上安装.NET8环境。…

Ubuntu 22.04 安装prometheus

服务器监控和报警软件有很多&#xff0c;为什么我们会选择Prometheus而不是其他软件呢&#xff1f; 因为它有以下优点&#xff1a; 自带简易web监控页面&#xff0c;用户可以很方便地查看监控数据和使用仪表盘。能实时收集数据并根据自定义警报规则推送告警&#xff1b;具有丰…

AI绘图制作红包封面教程

注意&#xff1a;有不懂的话可加入QQ群聊一起交流&#xff1a;901944946欢迎大家关注微信公众号【程序猿代码之路】&#xff0c;每天都会不定时的发送一些红包封面&#xff01;&#xff01; 2024的春节即将到来&#xff0c;而在这春节到来之前&#xff0c;就有一个非常爆火的小…

spring boot学习第八篇:通过spring boot、jedis实现秒单

参考&#xff1a;Redis实现分布式锁的7种方案 - 知乎 1、 准备数据库表&#xff0c;如下SQL表示库存表&#xff0c;有主键ID和库存数量字段 CREATE TABLE t_stock (id bigint(20) NOT NULL AUTO_INCREMENT,quantity bigint(20) NOT NULL,PRIMARY KEY (id) ) ENGINEInnoDB DEF…