From ea318bb6c8b6054123f975429ce642d3a33da8dd Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Sun, 20 Mar 2022 01:42:08 -0500 Subject: [PATCH] [nostalgia/core] Add key event handler --- src/nostalgia/core/context.hpp | 14 ++++++- src/nostalgia/core/glfw/core.cpp | 5 ++- src/nostalgia/core/glfw/core.hpp | 2 + src/nostalgia/core/glfw/gfx.cpp | 58 ++++++++++++++++++++++------ src/nostalgia/core/input.hpp | 65 +++++++++++++++++++++++++++----- 5 files changed, 120 insertions(+), 24 deletions(-) diff --git a/src/nostalgia/core/context.hpp b/src/nostalgia/core/context.hpp index 1606279b..a5c6b747 100644 --- a/src/nostalgia/core/context.hpp +++ b/src/nostalgia/core/context.hpp @@ -68,6 +68,8 @@ class Context { friend void setBgStatus(Context *ctx, unsigned bg, bool status) noexcept; friend void setClipboardText(Context *ctx, const ox::String &text) noexcept; friend void setUpdateHandler(Context *ctx, UpdateHandler h) noexcept; + friend constexpr void setKeyEventHandler(Context *ctx, KeyEventHandler h) noexcept; + friend constexpr KeyEventHandler keyEventHandler(Context *ctx) noexcept; friend void setTile(Context *ctx, int layer, int column, int row, uint8_t tile) noexcept; friend void setWindowTitle(Context *ctx, const char *title) noexcept; @@ -75,6 +77,7 @@ class Context { ox::UniquePtr rom; ox::Vector drawers; const char *appName = "Nostalgia"; + #ifndef OX_BARE_METAL AssetManager assetManager; int uninterruptedRefreshes = 3; @@ -85,6 +88,7 @@ class Context { // sets screen refresh to constant instead of only on event bool constantRefresh = true; #endif + KeyEventHandler m_keyEventHandler = nullptr; void *m_customData = nullptr; private: @@ -98,13 +102,13 @@ class Context { Context(const Context &other) noexcept = delete; Context(const Context &&other) noexcept = delete; - protected: template [[nodiscard]] constexpr T *windowerData() noexcept { return static_cast(m_windowerData); } + protected: constexpr void setWindowerData(void *windowerData) noexcept { m_windowerData = windowerData; } @@ -131,6 +135,14 @@ constexpr T *applicationData(Context *ctx) noexcept { return static_cast(ctx->m_customData); } +constexpr void setKeyEventHandler(Context *ctx, KeyEventHandler h) noexcept { + ctx->m_keyEventHandler = h; +} + +constexpr KeyEventHandler keyEventHandler(Context *ctx) noexcept { + return ctx->m_keyEventHandler; +} + constexpr void setConstantRefresh([[maybe_unused]] Context *ctx, [[maybe_unused]] bool r) noexcept { #ifndef OX_BARE_METAL ctx->constantRefresh = r; diff --git a/src/nostalgia/core/glfw/core.cpp b/src/nostalgia/core/glfw/core.cpp index debfa8fb..276d8b9a 100644 --- a/src/nostalgia/core/glfw/core.cpp +++ b/src/nostalgia/core/glfw/core.cpp @@ -74,8 +74,9 @@ uint64_t ticksMs(Context *ctx) noexcept { return static_cast(now - id->startTime); } -bool buttonDown(Context*, Key) noexcept { - return false; +bool buttonDown(Context *ctx, Key key) noexcept { + const auto id = ctx->windowerData(); + return (id->keysDown >> static_cast(key)) & 1; } ox::Error shutdown(Context *ctx) noexcept { diff --git a/src/nostalgia/core/glfw/core.hpp b/src/nostalgia/core/glfw/core.hpp index 3305f703..6e66793a 100644 --- a/src/nostalgia/core/glfw/core.hpp +++ b/src/nostalgia/core/glfw/core.hpp @@ -12,7 +12,9 @@ struct GlfwImplData { struct GLFWwindow *window = nullptr; int64_t startTime = 0; UpdateHandler eventHandler = nullptr; + KeyEventHandler keyEventHandler = nullptr; uint64_t wakeupTime = 0; + uint64_t keysDown; }; } diff --git a/src/nostalgia/core/glfw/gfx.cpp b/src/nostalgia/core/glfw/gfx.cpp index fd7a8eec..2fa1e092 100644 --- a/src/nostalgia/core/glfw/gfx.cpp +++ b/src/nostalgia/core/glfw/gfx.cpp @@ -20,19 +20,53 @@ static void handleGlfwError(int err, const char *desc) noexcept { oxErrf("GLFW error ({}): {}\n", err, desc); } -static void handleKeyPress(Context *ctx, int key) noexcept { - switch (key) { - case GLFW_KEY_ESCAPE: - case GLFW_KEY_Q: - if constexpr(ox::defines::Debug) { - oxIgnoreError(shutdown(ctx)); - } - break; - default: - break; +static auto setKeyDownStatus(GlfwImplData *id, Key key, bool down) noexcept { + if (down) { + id->keysDown |= 1llu << static_cast(key); + } else { + id->keysDown &= ~(1llu << static_cast(key)); } } +static void handleKeyPress(Context *ctx, int key, bool down) noexcept { + const auto eventHandler = keyEventHandler(ctx); + const auto id = ctx->windowerData(); + if (eventHandler) { + if (key >= GLFW_KEY_A && key <= GLFW_KEY_Z) { + const auto k = static_cast(Key::Alpha_A + (key - GLFW_KEY_A)); + setKeyDownStatus(id, k, down); + eventHandler(ctx, k, down); + } else if (key >= GLFW_KEY_0 && key <= GLFW_KEY_9) { + const auto k = static_cast(Key::Num_0 + (key - GLFW_KEY_0)); + setKeyDownStatus(id, k, down); + eventHandler(ctx, k, down); + } else { + switch (key) { + case GLFW_KEY_LEFT_SHIFT: + case GLFW_KEY_RIGHT_SHIFT: + setKeyDownStatus(id, Key::Mod_Shift, down); + eventHandler(ctx, Key::Mod_Shift, down); + break; + case GLFW_KEY_LEFT_CONTROL: + case GLFW_KEY_RIGHT_CONTROL: + setKeyDownStatus(id, Key::Mod_Ctrl, down); + eventHandler(ctx, Key::Mod_Ctrl, down); + break; + } + } + } + //if constexpr(ox::defines::Debug) { + // switch (key) { + // case GLFW_KEY_ESCAPE: + // case GLFW_KEY_Q: + // oxIgnoreError(shutdown(ctx)); + // break; + // default: + // break; + // } + //} +} + static void handleGlfwCursorPosEvent(GLFWwindow*, double, double) noexcept { } @@ -48,7 +82,9 @@ static void handleGlfwKeyEvent(GLFWwindow *window, int key, int, int action, int const auto ctx = static_cast(glfwGetWindowUserPointer(window)); ctx->uninterruptedRefreshes = 2; if (action == GLFW_PRESS) { - handleKeyPress(ctx, key); + handleKeyPress(ctx, key, true); + } else if (action == GLFW_RELEASE) { + handleKeyPress(ctx, key, false); } } diff --git a/src/nostalgia/core/input.hpp b/src/nostalgia/core/input.hpp index e80afb56..e5489e32 100644 --- a/src/nostalgia/core/input.hpp +++ b/src/nostalgia/core/input.hpp @@ -8,16 +8,59 @@ namespace nostalgia::core { enum Key { // GBA implementation currently relies on GamePad entry order - GamePad_A = 1, - GamePad_B = 2, - GamePad_Select = 4, - GamePad_Start = 8, - GamePad_Right = 16, - GamePad_Left = 32, - GamePad_Up = 64, - GamePad_Down = 128, - GamePad_R = 256, - GamePad_L = 512, + GamePad_A = 1, + GamePad_B, + GamePad_Select, + GamePad_Start, + GamePad_Right, + GamePad_Left, + GamePad_Up, + GamePad_Down, + GamePad_R, + GamePad_L, + + Num_0, + Num_1, + Num_2, + Num_3, + Num_4, + Num_5, + Num_6, + Num_7, + Num_8, + Num_9, + + Alpha_A, + Alpha_B, + Alpha_C, + Alpha_D, + Alpha_E, + Alpha_F, + Alpha_G, + Alpha_H, + Alpha_I, + Alpha_J, + Alpha_K, + Alpha_L, + Alpha_M, + Alpha_N, + Alpha_O, + Alpha_P, + Alpha_Q, + Alpha_R, + Alpha_S, + Alpha_T, + Alpha_U, + Alpha_V, + Alpha_W, + Alpha_X, + Alpha_Y, + Alpha_Z, + + Mod_Ctrl, + Mod_Shift, + + End }; class Context; @@ -25,4 +68,6 @@ class Context; [[nodiscard]] bool buttonDown(Context *ctx, Key) noexcept; +using KeyEventHandler = void(*)(Context*, Key, bool); + }