From a32897d5d4fff81bdbef86d5097a27511aba1bd4 Mon Sep 17 00:00:00 2001 From: Shylie Date: Tue, 14 May 2024 16:46:30 -0500 Subject: [PATCH] Initial public api version --- examples/basic.cpp | 27 +++++++++++++++++- include/glerminal.h | 21 ++++++++++++-- source/glerminal-private.h | 5 +++- source/glerminal.cpp | 56 ++++++++++++++++++++++++++++++++++---- 4 files changed, 99 insertions(+), 10 deletions(-) diff --git a/examples/basic.cpp b/examples/basic.cpp index 7711cbe..c1303e8 100644 --- a/examples/basic.cpp +++ b/examples/basic.cpp @@ -1,6 +1,31 @@ #include +namespace +{ + void init() + { + glerminal_update_palette(0, 0xFF0000FF); + glerminal_update_palette(1, 0x00FF00FF); + + glerminal_update_sprite(0, { + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0 + }); + } + + void mainloop(float dt) + { + glerminal_flush(); + } +} + int main(int argc, char** argv) { - glerminal_run(glerminal_flush); + glerminal_run(init, mainloop); } \ No newline at end of file diff --git a/include/glerminal.h b/include/glerminal.h index 94bb212..e104719 100644 --- a/include/glerminal.h +++ b/include/glerminal.h @@ -12,7 +12,8 @@ enum GLERMINAL_CELL_AREA = GLERMINAL_CELL_SIZE * GLERMINAL_CELL_SIZE }; -typedef void (*glerminal_main_cb)(); +typedef void (*glerminal_init_cb)(); +typedef void (*glerminal_main_cb)(float dt); typedef struct glerminal_sprite { @@ -20,10 +21,10 @@ typedef struct glerminal_sprite } glerminal_sprite; /** - * @brief Run the application's mainloop + * @brief Call init once, then run the application's mainloop * @param main main calllback */ -void glerminal_run(glerminal_main_cb main); +void glerminal_run(glerminal_init_cb init, glerminal_main_cb main); /** * @brief Update the displayed screen contents to the current state of the library @@ -47,6 +48,20 @@ void glerminal_set(unsigned char x, unsigned char y, unsigned char layer, unsign */ unsigned char glerminal_get(unsigned char x, unsigned char y, unsigned char layer); +/** + * @brief Upload sprite to the given sprite ID + * @param id The ID of the sprite to change + * @param sprite The new sprite + */ +void glerminal_update_sprite(unsigned char id, glerminal_sprite sprite); + +/** + * @brief Update palette color at index ID + * @param id Palette index to update + * @param color New color + */ +void glerminal_update_palette(unsigned char id, unsigned int color); + #ifdef __cplusplus } #endif diff --git a/source/glerminal-private.h b/source/glerminal-private.h index 184bbe1..56cd8ee 100644 --- a/source/glerminal-private.h +++ b/source/glerminal-private.h @@ -25,7 +25,7 @@ namespace glerminal class glerminal { public: - glerminal(glerminal_main_cb main); + glerminal(glerminal_init_cb init, glerminal_main_cb main); ~glerminal(); glerminal(const glerminal&) = delete; @@ -41,6 +41,9 @@ namespace glerminal void set(unsigned char x, unsigned char y, unsigned char layer, unsigned char sprite); unsigned char get(unsigned char x, unsigned char y, unsigned char layer) const; + void update_sprite(unsigned char id, glerminal_sprite sprite); + void update_palette_color(unsigned char id, unsigned int color); + private: GLFWwindow* m_window; diff --git a/source/glerminal.cpp b/source/glerminal.cpp index 7cc56bb..a416872 100644 --- a/source/glerminal.cpp +++ b/source/glerminal.cpp @@ -89,7 +89,7 @@ namespace "void main()\n" "{\n" " gl_Position = vec4(position * 2 + 1, 0, 1);\n" - " texcoord = -position;\n" + " texcoord = vec2(position.x + 1, -position.y);\n" "}"; constexpr char* SCREEN_FRAGMENT_SHADER_SOURCE = @@ -111,7 +111,7 @@ namespace namespace glerminal { - glerminal::glerminal(glerminal_main_cb main) : + glerminal::glerminal(glerminal_init_cb init, glerminal_main_cb main) : m_main(main), m_cells{ }, m_sprites{ }, @@ -126,6 +126,11 @@ namespace glerminal } // unsure if this should be an error + if (!init) + { + throw std::runtime_error("No init callback provided."); + } + if (!m_main) { throw std::runtime_error("No main callback provided."); @@ -135,6 +140,8 @@ namespace glerminal init_gl(); GLERMINAL_G = this; + + init(); } glerminal::~glerminal() @@ -147,17 +154,25 @@ namespace glerminal void glerminal::run() { + float last = glfwGetTime(); while (!glfwWindowShouldClose(m_window)) { glfwPollEvents(); - m_main(); + const float current = glfwGetTime(); + + m_main(current - last); + + last = current; } } void glerminal::flush() { + // use dirty flag later glNamedBufferData(m_instance_vbo, sizeof(m_cells), m_cells, GL_STREAM_DRAW); + update_sprites(); + update_palette(); glUseProgram(m_program); glBindTexture(GL_TEXTURE_2D_ARRAY, m_sprites_texture); @@ -196,6 +211,23 @@ namespace glerminal } } + void glerminal::update_sprite(unsigned char id, glerminal_sprite sprite) + { + // does this work? + reinterpret_cast(m_sprites)[id] = sprite; + } + + void glerminal::update_palette_color(unsigned char id, unsigned int color) + { + if (id < 16) + { + m_palette[4 * id + 0] = ((color >> 24) & 0xFF) / 255.0f; + m_palette[4 * id + 1] = ((color >> 16) & 0xFF) / 255.0f; + m_palette[4 * id + 2] = ((color >> 8) & 0xFF) / 255.0f; + m_palette[4 * id + 3] = ((color >> 0) & 0xFF) / 255.0f; + } + } + void glerminal::init_glfw() { glfwInit(); @@ -538,11 +570,11 @@ namespace glerminal } } -void glerminal_run(glerminal_main_cb main) +void glerminal_run(glerminal_init_cb init, glerminal_main_cb main) { try { - glerminal::glerminal(main).run(); + glerminal::glerminal(init, main).run(); } catch (const std::runtime_error& e) { @@ -568,4 +600,18 @@ unsigned char glerminal_get(unsigned char x, unsigned char y, unsigned char laye if (!GLERMINAL_G) { return 0; } return GLERMINAL_G->get(x, y, layer); +} + +void glerminal_update_sprite(unsigned char id, glerminal_sprite sprite) +{ + if (!GLERMINAL_G) { return; } + + GLERMINAL_G->update_sprite(id, sprite); +} + +void glerminal_update_palette(unsigned char id, unsigned int color) +{ + if (!GLERMINAL_G) { return; } + + GLERMINAL_G->update_palette_color(id, color); } \ No newline at end of file