210 lines
6.2 KiB
C++
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
|