#include #include "Window.h" #include "glfw3webgpu/glfw3webgpu.h" namespace Artifact { static std::array GLFWToArtifact {}; static std::array(Key::Last) + 1> ArtifactToGLFW {}; 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;\ ArtifactToGLFW[static_cast(Key::artifact)] = glfw 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(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(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(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(glfwGetWindowUserPointer(window))->dispatch(Events::KeyDownEvent { .key = GLFWToArtifact[key] }); } else if (action == GLFW_RELEASE) { static_cast(glfwGetWindowUserPointer(window))->dispatch(Events::KeyUpEvent { .key = GLFWToArtifact[key] }); } }); glfwSetCharCallback(window, [](auto window, auto codepoint) { static_cast(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); } void Window::setPointerLock() { glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); } void Window::releasePointerLock() { glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); } bool Window::isKeyDown(Key key) { return glfwGetKey(window, ArtifactToGLFW[static_cast(key)]) == GLFW_PRESS; } }