Files
HelloVulkan/Engine/src/Core/Window.cpp
T

210 lines
6.2 KiB
C++

//
// Created by atdunbg on 2026/9/20.
//
#include <Engine/Core/Window.h>
#include <Engine/Core/Log.h>
#include <GLFW/glfw3.h>
namespace Engine
{
void Window::FramebufferResizeCallback(GLFWwindow* window, int width, int height)
{
auto* self = static_cast<Window*>(glfwGetWindowUserPointer(window));
self->m_FramebufferResized = true;
if (self->m_EventCallback) {
Event e;
e.type = EventType::WindowResize;
e.width = width;
e.height = height;
self->m_EventCallback(e);
}
}
void Window::KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
auto* self = static_cast<Window*>(glfwGetWindowUserPointer(window));
if (!self->m_EventCallback || key == GLFW_KEY_UNKNOWN) return;
// UI 捕获键盘时,游戏侧不收键盘事件(ImGui 后端链式回调自行处理)
if (self->m_KeyboardCapture && self->m_KeyboardCapture()) return;
Event e;
e.key = key;
e.type = (action == GLFW_PRESS) ? EventType::KeyPress
: (action == GLFW_RELEASE) ? EventType::KeyRelease
: EventType::None; // GLFW_REPEAT 暂不透出
if (e.type != EventType::None) self->m_EventCallback(e);
}
void Window::MouseButtonCallback(GLFWwindow* window, int button, int action, int mods)
{
auto* self = static_cast<Window*>(glfwGetWindowUserPointer(window));
if (!self->m_EventCallback) return;
if (self->m_MouseCapture && self->m_MouseCapture()) return;
Event e;
e.button = button;
e.type = (action == GLFW_PRESS) ? EventType::MouseButtonPress
: EventType::MouseButtonRelease;
self->m_EventCallback(e);
}
void Window::CursorPosCallback(GLFWwindow* window, double xpos, double ypos)
{
auto* self = static_cast<Window*>(glfwGetWindowUserPointer(window));
if (!self->m_EventCallback) return;
if (self->m_MouseCapture && self->m_MouseCapture()) return;
Event e;
e.type = EventType::MouseMove;
e.x = static_cast<f32>(xpos);
e.y = static_cast<f32>(ypos);
self->m_EventCallback(e);
}
void Window::ScrollCallback(GLFWwindow* window, double xoffset, double yoffset)
{
auto* self = static_cast<Window*>(glfwGetWindowUserPointer(window));
if (!self->m_EventCallback) return;
if (self->m_MouseCapture && self->m_MouseCapture()) return;
Event e;
e.type = EventType::MouseScroll;
e.deltaX = static_cast<f32>(xoffset);
e.deltaY = static_cast<f32>(yoffset);
self->m_EventCallback(e);
}
void Window::WindowFocusCallback(GLFWwindow* window, int focused)
{
auto* self = static_cast<Window*>(glfwGetWindowUserPointer(window));
if (!self->m_EventCallback) return;
Event e;
e.type = focused ? EventType::WindowFocus : EventType::WindowLostFocus;
self->m_EventCallback(e);
}
Window::Window(const std::string& title, u32 width, u32 height)
: m_Width(width), m_Height(height), m_Title(title)
{
if (!glfwInit())
{
ENGINE_FATAL("glfwInit failed");
return;
}
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
// glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
m_Window = glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr);
if (!m_Window)
{
ENGINE_FATAL("glfwCreateWindow failed");
glfwTerminate();
return;
}
ENGINE_INFO("Window created: {} ({}x{})", title, width, height);
// callbacks
glfwSetWindowUserPointer(m_Window, this);
glfwSetFramebufferSizeCallback(m_Window, FramebufferResizeCallback);
glfwSetKeyCallback(m_Window, KeyCallback);
glfwSetMouseButtonCallback(m_Window, MouseButtonCallback);
glfwSetCursorPosCallback(m_Window, CursorPosCallback);
glfwSetScrollCallback(m_Window, ScrollCallback);
glfwSetWindowFocusCallback(m_Window, WindowFocusCallback);
}
Window::~Window()
{
if (m_Window)
{
glfwDestroyWindow(m_Window);
}
glfwTerminate();
}
bool Window::ShouldClose() const
{
return glfwWindowShouldClose(m_Window);
}
void Window::PollEvents()
{
glfwPollEvents();
}
vk::SurfaceKHR Window::CreateSurface(vk::Instance instance)
{
VkSurfaceKHR surface;
if (glfwCreateWindowSurface(instance, m_Window, nullptr, &surface) != VK_SUCCESS)
{
ENGINE_FATAL("glfwCreateWindowSurface failed");
return nullptr;
}
return surface;
}
void Window::DestroySurface(vk::Instance instance, vk::SurfaceKHR surface)
{
instance.destroySurfaceKHR(surface);
}
std::vector<const char*> Window::GetRequiredExtensions()
{
u32 count = 0;
const char** extensions = glfwGetRequiredInstanceExtensions(&count);
return std::vector<const char*>(extensions, extensions + count);
}
void Window::GetFramebufferSize(int& width, int& height) const
{
glfwGetFramebufferSize(m_Window, &width, &height);
}
bool Window::IsKeyPressed(int key) const
{
// UI 捕获键盘时,轮询接口同样静默(相机等轮询型消费方)
if (m_KeyboardCapture && m_KeyboardCapture()) return false;
return glfwGetKey(m_Window, key) == GLFW_PRESS;
}
void Window::GetMouseDelta(float& dx, float& dy)
{
double mx, my;
glfwGetCursorPos(m_Window, &mx, &my);
static double lastX = mx;
static double lastY = my;
static bool first = true;
if (first)
{
lastX = mx;
lastY = my;
first = false;
dx = dy = 0.0f;
return;
}
dx = static_cast<float>(mx - lastX);
dy = static_cast<float>(my - lastY);
lastX = mx;
lastY = my;
// UI 捕获鼠标时 delta 归零;lastX/Y 照常更新,避免释放后跳变
if (m_MouseCapture && m_MouseCapture())
{
dx = dy = 0.0f;
}
}
} // namespace Engine