From 35902c2803796c95a588e2cc2824f795b9ca918d Mon Sep 17 00:00:00 2001 From: Shylie Date: Thu, 30 May 2024 10:57:36 -0400 Subject: [PATCH] Add key callbacks, fix buffering issue --- examples/atlas.cpp | 2 +- examples/basic.cpp | 2 +- examples/rogue.cpp | 2 +- examples/towers.cpp | 2 +- include/glerminal.h | 5 ++++- source/glerminal-main.cpp | 37 ++++++++++++++++++++++++++++++++++++- source/glerminal-private.h | 5 ++++- source/glerminal.cpp | 33 ++++++++++++++++++++++++++++----- tests/basic.cpp | 2 +- 9 files changed, 77 insertions(+), 13 deletions(-) diff --git a/examples/atlas.cpp b/examples/atlas.cpp index 71031bb..055212d 100644 --- a/examples/atlas.cpp +++ b/examples/atlas.cpp @@ -42,5 +42,5 @@ namespace int main(int argc, char** argv) { - glerminal_run(init, mainloop); + glerminal_run(init, mainloop, nullptr, nullptr); } \ No newline at end of file diff --git a/examples/basic.cpp b/examples/basic.cpp index 28f4581..0885d57 100644 --- a/examples/basic.cpp +++ b/examples/basic.cpp @@ -39,5 +39,5 @@ namespace int main(int argc, char** argv) { - glerminal_run(init, mainloop); + glerminal_run(init, mainloop, nullptr, nullptr); } \ No newline at end of file diff --git a/examples/rogue.cpp b/examples/rogue.cpp index 7c77451..8d430e5 100644 --- a/examples/rogue.cpp +++ b/examples/rogue.cpp @@ -83,5 +83,5 @@ namespace int main(int argc, char** argv) { - glerminal_run(init, mainloop); + glerminal_run(init, mainloop, nullptr, nullptr); } \ No newline at end of file diff --git a/examples/towers.cpp b/examples/towers.cpp index cf67e66..f346be8 100644 --- a/examples/towers.cpp +++ b/examples/towers.cpp @@ -63,5 +63,5 @@ namespace int main(int argc, char** argv) { - glerminal_run(init, mainloop); + glerminal_run(init, mainloop, nullptr, nullptr); } \ No newline at end of file diff --git a/include/glerminal.h b/include/glerminal.h index 0df93c0..97c9a1e 100644 --- a/include/glerminal.h +++ b/include/glerminal.h @@ -10,13 +10,16 @@ extern "C" typedef void (*glerminal_init_cb)(); typedef void (*glerminal_main_cb)(float dt); +typedef void (*glerminal_keys_cb)(int key); /** * @brief Call init once, then run the application's mainloop * @param init initialization callback * @param main main calllback + * @param pressed key pressed callback (can be null) + * @param released key released callback (can be null) */ -void glerminal_run(glerminal_init_cb init, glerminal_main_cb main); +void glerminal_run(glerminal_init_cb init, glerminal_main_cb main, glerminal_keys_cb pressed, glerminal_keys_cb released); void glerminal_quit(); diff --git a/source/glerminal-main.cpp b/source/glerminal-main.cpp index 6708668..337f4c8 100644 --- a/source/glerminal-main.cpp +++ b/source/glerminal-main.cpp @@ -1,4 +1,5 @@ #include +#include extern "C" { @@ -131,6 +132,40 @@ namespace lua_remove(L, -1); } } + + void pressed(int key) + { + const char* const name = glfwGetKeyName(key, 0); + if (name) + { + lua_getglobal(L, "glerminal"); + lua_getfield(L, -1, "pressed"); + lua_remove(L, -2); + lua_pushstring(L, name); + if (lua_pcall(L, 1, 0, 0) != LUA_OK) + { + // ignore error for now + lua_remove(L, -1); + } + } + } + + void released(int key) + { + const char* const name = glfwGetKeyName(key, 0); + if (name) + { + lua_getglobal(L, "glerminal"); + lua_getfield(L, -1, "released"); + lua_remove(L, -2); + lua_pushstring(L, name); + if (lua_pcall(L, 1, 0, 0) != LUA_OK) + { + // ignore error for now + lua_remove(L, -1); + } + } + } } int main(int argc, char** argv) @@ -155,7 +190,7 @@ int main(int argc, char** argv) luaL_dofile(L, "main.lua"); - glerminal_run(init, mainloop); + glerminal_run(init, mainloop, pressed, released); lua_close(L); diff --git a/source/glerminal-private.h b/source/glerminal-private.h index 535ee5f..ae29ac8 100644 --- a/source/glerminal-private.h +++ b/source/glerminal-private.h @@ -25,7 +25,7 @@ namespace glerminal class glerminal { public: - glerminal(glerminal_init_cb init, glerminal_main_cb main); + glerminal(glerminal_init_cb init, glerminal_main_cb main, glerminal_keys_cb pressed, glerminal_keys_cb released); ~glerminal(); glerminal(const glerminal&) = delete; @@ -84,6 +84,7 @@ namespace glerminal unsigned int m_sprites[CELL_SIZE * CELL_SIZE * (1 << (8 * sizeof(*m_cells)))]; glerminal_main_cb m_main; + glerminal_keys_cb m_pressed, m_released; #ifdef GLERMINAL_OPENGL_DEBUG_CONTEXT mutable std::ofstream m_log; @@ -99,6 +100,8 @@ namespace glerminal void update_sprites(); void update_layer_colors(); void update_layer_scales(); + + static void glfw_key_handler(GLFWwindow* window, int key, int scancode, int action, int mods); }; } diff --git a/source/glerminal.cpp b/source/glerminal.cpp index 2055f7f..a07e170 100644 --- a/source/glerminal.cpp +++ b/source/glerminal.cpp @@ -198,8 +198,10 @@ namespace namespace glerminal { - glerminal::glerminal(glerminal_init_cb init, glerminal_main_cb main) : + glerminal::glerminal(glerminal_init_cb init, glerminal_main_cb main, glerminal_keys_cb pressed, glerminal_keys_cb released) : m_main(main), + m_pressed(pressed), + m_released(released), m_cells{ }, m_offsets{ }, m_sprites{ }, @@ -237,8 +239,6 @@ namespace glerminal GLERMINAL_G = this; init(); - - glerminal_flush(); } glerminal::~glerminal() @@ -261,6 +261,8 @@ namespace glerminal m_main(current - last); last = current; + + glfwSwapBuffers(m_window); } } @@ -292,6 +294,8 @@ namespace glerminal glBlitNamedFramebuffer(m_screen_framebuffer, 0, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); glfwSwapBuffers(m_window); + + glBlitNamedFramebuffer(m_screen_framebuffer, 0, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); } void glerminal::set(unsigned char x, unsigned char y, unsigned char layer, unsigned char sprite) @@ -362,6 +366,7 @@ namespace glerminal { glfwInit(); + glfwWindowHint(GLFW_DOUBLEBUFFER, GLFW_TRUE); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); @@ -381,6 +386,9 @@ namespace glerminal { throw std::runtime_error("Failed to create glerminal window."); } + + glfwSetWindowUserPointer(m_window, this); + glfwSetKeyCallback(m_window, glerminal::glfw_key_handler); } void glerminal::log(GLenum type, GLuint id, GLenum severity, const char* message) const @@ -767,13 +775,28 @@ namespace glerminal { glNamedBufferData(m_layer_scales_buffer, sizeof(m_layer_scales), m_layer_scales, GL_DYNAMIC_READ); } + + void glerminal::glfw_key_handler(GLFWwindow* window, int key, int scancode, int action, int mods) + { + glerminal* const self = static_cast(glfwGetWindowUserPointer(window)); + + if (self->m_pressed && action == GLFW_PRESS) + { + self->m_pressed(key); + } + + if (self->m_released && action == GLFW_RELEASE) + { + self->m_released(key); + } + } } -void glerminal_run(glerminal_init_cb init, glerminal_main_cb main) +void glerminal_run(glerminal_init_cb init, glerminal_main_cb main, glerminal_keys_cb pressed, glerminal_keys_cb released) { try { - glerminal::glerminal* g = new glerminal::glerminal(init, main); + glerminal::glerminal* g = new glerminal::glerminal(init, main, pressed, released); g->run(); delete g; } diff --git a/tests/basic.cpp b/tests/basic.cpp index 9322eee..70ab010 100644 --- a/tests/basic.cpp +++ b/tests/basic.cpp @@ -30,7 +30,7 @@ namespace int main() { - glerminal_run(init, mainloop); + glerminal_run(init, mainloop, nullptr, nullptr); return 0; } \ No newline at end of file