ImGui Events
本节主要是为 ImGui 设置 Events ,让我们在用鼠标键盘输入的时候能够使 ImGui 渲染的窗口进行反馈,为此我们在
ImGuiLayer.h
中添加以下函数:
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);
ImGuiLayer.cpp
void ImGuiLayer::OnEvent(Event& event)
{
//Check the event type
EventDispatcher dispatcher(event);
dispatcher.Dispatch<MouseButtonPressedEvent>(HZ_BIND_EVENT_FN(ImGuiLayer::OnMouseButtonPressedEvent));
//Core.h 中添加如下定义#define HZ_BIND_EVENT_FN(fn) std::bind(&fn, this, std::placeholders::_1)
dispatcher.Dispatch<MouseButtonReleasedEvent>(HZ_BIND_EVENT_FN(ImGuiLayer::OnMouseButtonReleasedEvent));
dispatcher.Dispatch<MouseMovedEvent>(HZ_BIND_EVENT_FN(ImGuiLayer::OnMouseMovedEvent));
dispatcher.Dispatch<MouseScrolledEvent>(HZ_BIND_EVENT_FN(ImGuiLayer::OnMouseScrolledEvent));
dispatcher.Dispatch<KeyPressedEvent>(HZ_BIND_EVENT_FN(ImGuiLayer::OnKeyPressedEvent));
dispatcher.Dispatch<KeyReleasedEvent>(HZ_BIND_EVENT_FN(ImGuiLayer::OnKeyReleasedEvent));
dispatcher.Dispatch<KeyTypedEvent>(HZ_BIND_EVENT_FN(ImGuiLayer::OnKeyTypedEvent));
dispatcher.Dispatch<WindowResizeEvent>(HZ_BIND_EVENT_FN(ImGuiLayer::OnWindowResizedEvent));
}
//控制鼠标按下触发的事件
bool ImGuiLayer::OnMouseButtonPressedEvent(MouseButtonPressedEvent& e)
{
ImGuiIO& io = ImGui::GetIO();
io.MouseDown[e.GetMouseButton()] = true;
return false;
}
//控制鼠标释放的事件
bool ImGuiLayer::OnMouseButtonReleasedEvent(MouseButtonReleasedEvent& e)
{
ImGuiIO& io = ImGui::GetIO();
io.MouseDown[e.GetMouseButton()] = false;
return false;
}
//鼠标位置
bool ImGuiLayer::OnMouseMovedEvent(MouseMovedEvent& e)
{
ImGuiIO& io = ImGui::GetIO();
io.MousePos = ImVec2(e.GetX(), e.GetY());
return false;
}
//鼠标移动
bool ImGuiLayer::OnMouseScrolledEvent(MouseScrolledEvent& e)
{
ImGuiIO& io = ImGui::GetIO();
io.MouseWheelH += e.GetXOffset();
io.MouseWheel += e.GetYOffset();
return 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;
}
为了识别我们按下的按键,需要定义 KeyTypedEvent,在KeyEvent.h
中添加
class HAZEL_API KeyTypedEvent : public KeyEvent {
public:
KeyTypedEvent(int keycode) : KeyEvent(keycode) {}
std::string ToString() const override {
std::stringstream ss;
ss << "KeyTypedEvent: " << m_KeyCode ;
return ss.str();
}
EVENT_CLASS_TYPE(KeyTyped)
};
WindowsWindow.cpp
中需要对 glfw 添加初始化的部分:
void WindowsWindow::Init(const WindowProps& props)
{
...
glfwSetKeyCallback(m_Window, [](GLFWwindow* window, int key, int scancode, int action, int mods)
...
);
glfwSetCharCallback(m_Window, [](GLFWwindow* window, unsigned int charactor)
{
WindowData& data = *(WindowData*)glfwGetWindowUserPointer(window);
KeyTypedEvent event(charactor);
data.EventCallback(event);
}
);
...
}
之后运行程序:测试所有按键,由于我的 mac 按键映射原因,右 shift 会中断程序,但是在 windows 中测试没有问题