Window Events
本节主要是将我们在 window 中的各种操作产生的 Events dispatch之后通过 log 显示出来
我们先观察一个窗口是如何被创建出来的:
int main(int argc, char** argv)
{
Hazel::Log::Init();
HZ_CORE_WARN("Initialized Log");
int a = 5;
HZ_INFO("Hello! Var={0}", a);
auto app = Hazel::CreateApplication(); //调用 CreateApplication 函数
app->Run();
delete app;
}
CreateAplication 做了什么呢?我们转到该函数,发现在函数中创建了 SandBox 的对象,并返回了Application 类型的指针,该对象继承自 Application 类,因此可以通过该指针调用类中的方法,然后观察 Application 的结构
namespace Hazel{
class HAZEL_API Application
{
public:
Application();
virtual ~Application();
void Run();
void OnEvent(Event& e); //用于各种事件
private:
bool OnWindowClose(WindowCloseEvent& e); //用于关闭窗口
std::unique_ptr<Window> m_Window; //显示的窗口
bool m_Running = true ; //运行状态的控制
};
//To be defined in Client
Application* CreateApplication();
}
构造函数中,我们初始化了 window 并且设置了事件的 callback
m_Window = std::unique_ptr<Window>(Window::Create());
m_Window->SetEventCallback(BIND_EVENT_FN(OnEvent));
window::Create 函数创建了一个 GLFW 窗口,并进行了一系列初始化,具体内容可以参照上一节 windowswindow 的内容,然后调用了EventCallback 来进行事件的 dispatch,这里 BIND 宏进行了如下定义:
#define BIND_EVENT_FN(x) std::bind(&Application::x, this, std::placeholders::_1) // Returns a function object based on fn(Application::x), but with its arguments bound to args(this,_1).
然后函数 OnEvent 定义如下:
void Application::OnEvent(Event& e)
{
EventDispatcher dispatcher(e);
dispatcher.Dispatch<WindowCloseEvent>(BIND_EVENT_FN(OnWindowClose)); //控制窗口关闭
HZ_CORE_INFO("{0}", e); //Get Core logger
}
这里的作用就是根据我们产生的事件 e,来进行 dispatch,从而通过 log 进行显示
在 main 函数中我们调用了 Run 函数,
void Application::Run()
{
while (m_Running)
{
glClearColor(1, 0, 1, 1);
glClear(GL_COLOR_BUFFER_BIT);
m_Window->OnUpdate();
}
}
利用 glfw 的函数对窗口进行初始化,并开始渲染窗口
这时候窗口能够正常显示了
之后我们需要将在窗口中进行操作产生的事件显示出来,在 windowsWindow 中添加各种 EventCallback
//Set GLFW callbacks
glfwSetWindowSizeCallback(m_Window, [](GLFWwindow* window, int width, int height)
{
WindowData& data = *(WindowData*)glfwGetWindowUserPointer(window);
data.Width = width; //shoud be initialized first
data.Height = height;
WindowResizeEvent event(width, height); //renturn a Event instance
data.EventCallback(event); //translate event instance to func pointer and dispatch 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:
{
KeyRelseasedEvent 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);
MouseMoveEvent event((float)xPos, (float)yPos);
data.EventCallback(event);
}
);
最后为了关闭窗口,我们必须在收到 WindowClose Event 之后修改 running 的状态
bool Application::OnWindowClose(WindowCloseEvent& e)
{
m_Running = false;
return true;
}
然后再次运行窗口,在我们进行操作的时候,就可以在控制台中显示当前的事件啦