[nostalgia/core] Add key event handler

This commit is contained in:
Gary Talent 2022-03-20 01:42:08 -05:00
parent 2223fe7863
commit ea318bb6c8
5 changed files with 120 additions and 24 deletions

View File

@ -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<ox::FileSystem> rom;
ox::Vector<Drawer*, 5> 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<typename T>
[[nodiscard]]
constexpr T *windowerData() noexcept {
return static_cast<T*>(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<T*>(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;

View File

@ -74,8 +74,9 @@ uint64_t ticksMs(Context *ctx) noexcept {
return static_cast<uint64_t>(now - id->startTime);
}
bool buttonDown(Context*, Key) noexcept {
return false;
bool buttonDown(Context *ctx, Key key) noexcept {
const auto id = ctx->windowerData<GlfwImplData>();
return (id->keysDown >> static_cast<int>(key)) & 1;
}
ox::Error shutdown(Context *ctx) noexcept {

View File

@ -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;
};
}

View File

@ -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<int>(key);
} else {
id->keysDown &= ~(1llu << static_cast<int>(key));
}
}
static void handleKeyPress(Context *ctx, int key, bool down) noexcept {
const auto eventHandler = keyEventHandler(ctx);
const auto id = ctx->windowerData<GlfwImplData>();
if (eventHandler) {
if (key >= GLFW_KEY_A && key <= GLFW_KEY_Z) {
const auto k = static_cast<Key>(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>(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<Context*>(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);
}
}

View File

@ -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);
}