ArtifactEngine/Client/Platform/Window.cpp
2026-03-11 18:05:19 -04:00

163 lines
4.8 KiB
C++

#include <stdexcept>
#include "Window.h"
#include "glfw3webgpu/glfw3webgpu.h"
namespace Artifact {
static std::array<Key, GLFW_KEY_LAST + 1> GLFWToArtifact {};
namespace {
// Ensure that GLFW is transparently initialized prior to window creation.
static struct _glfwInit {
_glfwInit() {
if(!glfwInit()) throw std::runtime_error("Failed to initialize GLFW.");
// Populate the global GLFW-to-Artifact keycode mapping.
GLFWToArtifact.fill(Key::Unknown);
#define X(glfw, artifact) GLFWToArtifact[glfw] = Key::artifact
X(GLFW_KEY_A, A);
X(GLFW_KEY_B, B);
X(GLFW_KEY_C, C);
X(GLFW_KEY_D, D);
X(GLFW_KEY_E, E);
X(GLFW_KEY_F, F);
X(GLFW_KEY_G, G);
X(GLFW_KEY_H, H);
X(GLFW_KEY_I, I);
X(GLFW_KEY_J, J);
X(GLFW_KEY_K, K);
X(GLFW_KEY_L, L);
X(GLFW_KEY_M, M);
X(GLFW_KEY_N, N);
X(GLFW_KEY_O, O);
X(GLFW_KEY_P, P);
X(GLFW_KEY_Q, Q);
X(GLFW_KEY_R, R);
X(GLFW_KEY_S, S);
X(GLFW_KEY_T, T);
X(GLFW_KEY_U, U);
X(GLFW_KEY_V, V);
X(GLFW_KEY_W, W);
X(GLFW_KEY_X, X);
X(GLFW_KEY_Y, Y);
X(GLFW_KEY_Z, Z);
X(GLFW_KEY_0, Zero);
X(GLFW_KEY_1, One);
X(GLFW_KEY_2, Two);
X(GLFW_KEY_3, Three);
X(GLFW_KEY_4, Four);
X(GLFW_KEY_5, Five);
X(GLFW_KEY_6, Six);
X(GLFW_KEY_7, Seven);
X(GLFW_KEY_8, Eight);
X(GLFW_KEY_9, Nine);
X(GLFW_KEY_ENTER, Enter);
X(GLFW_KEY_LEFT_SHIFT, ShiftLeft);
X(GLFW_KEY_RIGHT_SHIFT, ShiftRight);
X(GLFW_KEY_LEFT_CONTROL, ControlLeft);
X(GLFW_KEY_RIGHT_CONTROL, ControlRight);
X(GLFW_KEY_LEFT_ALT, OptionLeft);
X(GLFW_KEY_RIGHT_ALT, OptionRight);
X(GLFW_KEY_LEFT_SUPER, CommandLeft);
X(GLFW_KEY_RIGHT_SUPER, CommandRight);
X(GLFW_KEY_BACKSPACE, DeleteBackward);
X(GLFW_KEY_DELETE, DeleteForward);
X(GLFW_KEY_LEFT, ArrowLeft);
X(GLFW_KEY_RIGHT, ArrowRight);
X(GLFW_KEY_UP, ArrowUp);
X(GLFW_KEY_DOWN, ArrowDown);
X(GLFW_KEY_TAB, Tab);
#undef X
}
~_glfwInit() {
glfwTerminate();
}
} __glfwInit;
}
Window::Window(uint32_t width, uint32_t height, std::string title) {
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
window = glfwCreateWindow(width, height, "", nullptr, nullptr);
glfwSetWindowUserPointer(window, this);
glfwSetCursorPosCallback(window, [](auto window, auto x, auto y) {
static_cast<Window *>(glfwGetWindowUserPointer(window))->dispatch(Events::CursorPosEvent {
.x = x,
.y = y
});
});
glfwSetMouseButtonCallback(window, [](auto window, auto button, auto action, auto mods) {
Events::MouseButton myButton = Events::MOUSE_BUTTON_LEFT;
if (button == GLFW_MOUSE_BUTTON_2) {
myButton = Events::MOUSE_BUTTON_RIGHT;
} else if (button == GLFW_MOUSE_BUTTON_3) {
myButton = Events::MOUSE_BUTTON_MIDDLE;
}
double x, y;
glfwGetCursorPos(window, &x, &y);
static_cast<Window *>(glfwGetWindowUserPointer(window))->dispatch(Events::MouseEvent {
.button = myButton,
.state = action == GLFW_PRESS,
.x = x,
.y = y
});
});
glfwSetScrollCallback(window, [](auto window, auto dx, auto dy) {
static_cast<Window *>(glfwGetWindowUserPointer(window))->dispatch(Events::ScrollEvent {
.dx = dx,
.dy = dy
});
});
glfwSetKeyCallback(window, [](auto window, auto key, auto scancode, auto action, auto mods) {
if (action == GLFW_PRESS) {
static_cast<Window *>(glfwGetWindowUserPointer(window))->dispatch(Events::KeyDownEvent {
.key = GLFWToArtifact[key]
});
} else if (action == GLFW_RELEASE) {
static_cast<Window *>(glfwGetWindowUserPointer(window))->dispatch(Events::KeyUpEvent {
.key = GLFWToArtifact[key]
});
}
});
glfwSetCharCallback(window, [](auto window, auto codepoint) {
static_cast<Window *>(glfwGetWindowUserPointer(window))->dispatch(Events::CharInputEvent {
.codepoint = codepoint
});
});
}
void Window::render() {
dispatch(Events::InputBegin {});
glfwPollEvents();
dispatch(Events::InputEnd {});
}
WGPUSurface Window::createWGPUSurface(WGPUInstance instance) {
return glfwCreateWindowWGPUSurface(instance, window);
}
void Window::setTitle(std::string title) {
glfwSetWindowTitle(window, title.c_str());
}
bool Window::shouldClose() {
return glfwWindowShouldClose(window);
}
}