diff --git a/assets/scene/initial.lua b/assets/scene/initial.lua index 87ca123..b1a6f4c 100644 --- a/assets/scene/initial.lua +++ b/assets/scene/initial.lua @@ -1,11 +1,12 @@ module('spritebatch') module('camera') module('color') -module('ui') +-- module('ui') +module('text') +module('screen') +module('time') -camera = cameraCreate(CAMERA_PROJECTION_TYPE_PERSPECTIVE) - -uiPush('ui/test.dsf') +camera = cameraCreate(CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC) function sceneDispose() end @@ -13,16 +14,22 @@ end function sceneUpdate() end +text = "Hello World" + function sceneRender() cameraPushMatrix(camera) - spriteBatchPush( - nil, - 0, 0, - 1, 2, - colorBlue() - ) - spriteBatchFlush() + camera.bottom = screenGetHeight() + camera.right = screenGetWidth() + + width, height = textMeasure(text) + x = (screenGetWidth() - width) + x = math.sin(TIME.time * 2) * (x / 2) + (x / 2) + + y = (screenGetHeight() - height) / 2 + y = math.cos(TIME.time * 3) * (y) + (y) + + textDraw(x, y, text) cameraPopMatrix() end \ No newline at end of file diff --git a/assets/ui/CMakeLists.txt b/assets/ui/CMakeLists.txt index d9c9a0f..22dbf0a 100644 --- a/assets/ui/CMakeLists.txt +++ b/assets/ui/CMakeLists.txt @@ -3,5 +3,4 @@ # This software is released under the MIT License. # https://opensource.org/licenses/MIT -add_asset(TILESET minogram.png type=PALETTIZED tileWidth=6 tileHeight=10 columns=16 rows=6)# Fixes PSP rendering -add_asset(SCRIPT test.lua) \ No newline at end of file +add_asset(TILESET minogram.png type=PALETTIZED tileWidth=6 tileHeight=10 columns=16 rows=6)# Fixes PSP rendering \ No newline at end of file diff --git a/assets/ui/test.lua b/assets/ui/test.lua deleted file mode 100644 index cb91065..0000000 --- a/assets/ui/test.lua +++ /dev/null @@ -1,9 +0,0 @@ -module('spritebatch') - -function uiElementRender(x, y, w, h) - spriteBatchPush( - nil, - x, y, - w, h - ) -end \ No newline at end of file diff --git a/src/display/CMakeLists.txt b/src/display/CMakeLists.txt index 9410ae1..de9d945 100644 --- a/src/display/CMakeLists.txt +++ b/src/display/CMakeLists.txt @@ -11,6 +11,7 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME} screen.c texture.c spritebatch.c + text.c ) # Subdirectories diff --git a/src/display/camera/camera.c b/src/display/camera/camera.c index 15cb8be..087f169 100644 --- a/src/display/camera/camera.c +++ b/src/display/camera/camera.c @@ -34,9 +34,9 @@ void cameraInitOrthographic(camera_t *camera) { camera->projType = CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC; camera->orthographic.left = 0.0f; - camera->orthographic.right = (float_t)frameBufferGetWidth(FRAMEBUFFER_BOUND); - camera->orthographic.bottom = 0.0f; - camera->orthographic.top = (float_t)frameBufferGetHeight(FRAMEBUFFER_BOUND); + camera->orthographic.right = SCREEN.width; + camera->orthographic.top = 0.0f; + camera->orthographic.bottom = SCREEN.height; camera->nearClip = -1.0f; camera->farClip = 1.0f; diff --git a/src/display/color3.h b/src/display/color3.h deleted file mode 100644 index 380c182..0000000 --- a/src/display/color3.h +++ /dev/null @@ -1,113 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -typedef float_t colorchannelf_t; -typedef uint8_t colorchannelb_t; - -typedef struct { - colorchannelf_t r; - colorchannelf_t g; - colorchannelf_t b; -} color3f_t; - -typedef struct { - colorchannelf_t r; - colorchannelf_t g; - colorchannelf_t b; - colorchannelf_t a; -} color4f_t; - -typedef struct { - colorchannelb_t r; - colorchannelb_t g; - colorchannelb_t b; -} color3b_t; - -typedef struct { - colorchannelb_t r; - colorchannelb_t g; - colorchannelb_t b; - colorchannelb_t a; -} color4b_t; - -typedef color4b_t color_t; - -#define color3f(r, g, b) ((color3f_t){r, g, b}) -#define color4f(r, g, b, a) ((color4f_t){r, g, b, a}) -#define color3b(r, g, b) ((color3b_t){r, g, b}) -#define color4b(r, g, b, a) ((color4b_t){r, g, b, a}) -#define color(r, g, b, a) ((color_t){r, g, b, a}) - -#define colorHex(hex) color( \ - ((hex >> 24) & 0xFF), \ - ((hex >> 16) & 0xFF), \ - ((hex >> 8) & 0xFF), \ - (hex & 0xFF) \ -) - -#define COLOR_WHITE_3F color3f(1.0f, 1.0f, 1.0f) -#define COLOR_WHITE_4F color4f(1.0f, 1.0f, 1.0f, 1.0f) -#define COLOR_WHITE_3B color3b(255, 255, 255) -#define COLOR_WHITE_4B color4b(255, 255, 255, 255) -#define COLOR_WHITE color(255, 255, 255, 255) - -#define COLOR_BLACK_3F color3f(0.0f, 0.0f, 0.0f) -#define COLOR_BLACK_4F color4f(0.0f, 0.0f, 0.0f, 1.0f) -#define COLOR_BLACK_3B color3b(0, 0, 0) -#define COLOR_BLACK_4B color4b(0, 0, 0, 255) -#define COLOR_BLACK color(0, 0, 0, 255) - -#define COLOR_RED_3F color3f(1.0f, 0.0f, 0.0f) -#define COLOR_RED_4F color4f(1.0f, 0.0f, 0.0f, 1.0f) -#define COLOR_RED_3B color3b(255, 0, 0) -#define COLOR_RED_4B color4b(255, 0, 0, 255) -#define COLOR_RED color(255, 0, 0, 255) - -#define COLOR_GREEN_3F color3f(0.0f, 1.0f, 0.0f) -#define COLOR_GREEN_4F color4f(0.0f, 1.0f, 0.0f, 1.0f) -#define COLOR_GREEN_3B color3b(0, 255, 0) -#define COLOR_GREEN_4B color4b(0, 255, 0, 255) -#define COLOR_GREEN color(0, 255, 0, 255) - -#define COLOR_BLUE_3F color3f(0.0f, 0.0f, 1.0f) -#define COLOR_BLUE_4F color4f(0.0f, 0.0f, 1.0f, 1.0f) -#define COLOR_BLUE_3B color3b(0, 0, 255) -#define COLOR_BLUE_4B color4b(0, 0, 255, 255) -#define COLOR_BLUE color(0, 0, 255, 255) - -#define COLOR_YELLOW_3F color3f(1.0f, 1.0f, 0.0f) -#define COLOR_YELLOW_4F color4f(1.0f, 1.0f, 0.0f, 1.0f) -#define COLOR_YELLOW_3B color3b(255, 255, 0) -#define COLOR_YELLOW_4B color4b(255, 255, 0, 255) -#define COLOR_YELLOW color(255, 255, 0, 255) - -#define COLOR_CYAN_3F color3f(0.0f, 1.0f, 1.0f) -#define COLOR_CYAN_4F color4f(0.0f, 1.0f, 1.0f, 1.0f) -#define COLOR_CYAN_3B color3b(0, 255, 255) -#define COLOR_CYAN_4B color4b(0, 255, 255, 255) -#define COLOR_CYAN color(0, 255, 255, 255) - -#define COLOR_MAGENTA_3F color3f(1.0f, 0.0f, 1.0f) -#define COLOR_MAGENTA_4F color4f(1.0f, 0.0f, 1.0f, 1.0f) -#define COLOR_MAGENTA_3B color3b(255, 0, 255) -#define COLOR_MAGENTA_4B color4b(255, 0, 255, 255) -#define COLOR_MAGENTA color(255, 0, 255, 255) - -#define COLOR_TRANSPARENT_3F color3f(0.0f, 0.0f, 0.0f) -#define COLOR_TRANSPARENT_4F color4f(0.0f, 0.0f, 0.0f, 0.0f) -#define COLOR_TRANSPARENT_3B color3b(0, 0, 0) -#define COLOR_TRANSPARENT_4B color4b(0, 0, 0, 0) -#define COLOR_TRANSPARENT color(0, 0, 0, 0) - -#define COLOR_CORNFLOWER_BLUE_3F color3f(0.39f, 0.58f, 0.93f) -#define COLOR_CORNFLOWER_BLUE_4F color4f(0.39f, 0.58f, 0.93f, 1.0f) -#define COLOR_CORNFLOWER_BLUE_3B color3b(100, 149, 237) -#define COLOR_CORNFLOWER_BLUE_4B color4b(100, 149, 237, 255) -#define COLOR_CORNFLOWER_BLUE color(100, 149, 237, 255) \ No newline at end of file diff --git a/src/display/display.c b/src/display/display.c index 1e38697..1fb197e 100644 --- a/src/display/display.c +++ b/src/display/display.c @@ -14,6 +14,7 @@ #include "display/screen.h" #include "ui/ui.h" #include "debug/debug.h" +#include "display/text.h" display_t DISPLAY; @@ -73,6 +74,7 @@ errorret_t displayInit(void) { quadInit(); frameBufferInitBackbuffer(); spriteBatchInit(); + errorChain(textInit()); screenInit(); errorOk(); @@ -145,6 +147,7 @@ errorret_t displayUpdate(void) { errorret_t displayDispose(void) { spriteBatchDispose(); screenDispose(); + textDispose(); #if DISPLAY_SDL2 if(DISPLAY.glContext) { diff --git a/src/display/text.c b/src/display/text.c new file mode 100644 index 0000000..d1a0f5a --- /dev/null +++ b/src/display/text.c @@ -0,0 +1,124 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "text.h" +#include "assert/assert.h" +#include "util/memory.h" +#include "display/spritebatch.h" +#include "asset/asset.h" + +texture_t DEFAULT_FONT_TEXTURE; + +errorret_t textInit(void) { + errorChain(assetLoad(DEFAULT_FONT_TILESET.image, &DEFAULT_FONT_TEXTURE)); + errorOk(); +} + +void textDispose(void) { + textureDispose(&DEFAULT_FONT_TEXTURE); +} + +void textDrawChar( + const float_t x, + const float_t y, + const char_t c, + const color_t color, + const tileset_t *tileset, + texture_t *texture +) { + int32_t tileIndex = (int32_t)(c) - TEXT_CHAR_START; + if(tileIndex < 0 || tileIndex >= tileset->tileCount) { + tileIndex = ((int32_t)'@') - TEXT_CHAR_START; + } + + assertTrue( + tileIndex >= 0 && tileIndex <= tileset->tileCount, + "Character is out of bounds for font tiles" + ); + + vec4 uv; + tilesetTileGetUV(tileset, tileIndex, uv); + + spriteBatchPush( + texture, + x, y, + x + tileset->tileWidth, + y + tileset->tileHeight, + color, + uv[0], uv[1], uv[2], uv[3] + ); +} + + +void textDraw( + const float_t x, + const float_t y, + const char_t *text, + const color_t color, + const tileset_t *tileset, + texture_t *texture +) { + assertNotNull(text, "Text cannot be NULL"); + + float_t posX = x; + float_t posY = y; + + char_t c; + int32_t i = 0; + while((c = text[i++]) != '\0') { + if(c == '\n') { + posX = x; + posY += tileset->tileHeight; + continue; + } + + if(c == ' ') { + posX += tileset->tileWidth; + continue; + } + + textDrawChar(posX, posY, c, color, tileset, texture); + posX += tileset->tileWidth; + } +} + +void textMeasure( + const char_t *text, + const tileset_t *tileset, + int32_t *outWidth, + int32_t *outHeight +) { + assertNotNull(text, "Text cannot be NULL"); + assertNotNull(outWidth, "Output width pointer cannot be NULL"); + assertNotNull(outHeight, "Output height pointer cannot be NULL"); + + int32_t width = 0; + int32_t height = tileset->tileHeight; + int32_t lineWidth = 0; + + char_t c; + int32_t i = 0; + while((c = text[i++]) != '\0') { + if(c == '\n') { + if(lineWidth > width) { + width = lineWidth; + } + lineWidth = 0; + height += tileset->tileHeight; + continue; + } + + lineWidth += tileset->tileWidth; + } + + if(lineWidth > width) { + width = lineWidth; + } + + *outWidth = width; + *outHeight = height; +} \ No newline at end of file diff --git a/src/display/text.h b/src/display/text.h new file mode 100644 index 0000000..cfdddc8 --- /dev/null +++ b/src/display/text.h @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "asset/asset.h" +#include "display/texture.h" +#include "display/tileset/tileset.h" +#include "display/tileset/tileset_minogram.h" + +#define TEXT_CHAR_START '!' + +extern texture_t DEFAULT_FONT_TEXTURE; +#define DEFAULT_FONT_TILESET TILESET_MINOGRAM + +/** + * Initializes the text system. + */ +errorret_t textInit(void); + +/** + * Disposes of the text system. + */ +void textDispose(void); + +/** + * Draws a single character at the specified position. + * + * @param x The x-coordinate to draw the character at. + * @param y The y-coordinate to draw the character at. + * @param c The character to draw. + * @param color The color to draw the character in. + * @param tileset Font tileset to use for rendering. + * @param texture Texture containing the font tileset image. + */ +void textDrawChar( + const float_t x, + const float_t y, + const char_t c, + const color_t color, + const tileset_t *tileset, + texture_t *texture +); + +/** + * Draws a string of text at the specified position. + * + * @param x The x-coordinate to draw the text at. + * @param y The y-coordinate to draw the text at. + * @param text The null-terminated string of text to draw. + * @param color The color to draw the text in. + * @param tileset Font tileset to use for rendering. + * @param texture Texture containing the font tileset image. + */ +void textDraw( + const float_t x, + const float_t y, + const char_t *text, + const color_t color, + const tileset_t *tileset, + texture_t *texture +); + +/** + * Measures the width and height of the given text string when rendered. + * + * @param text The null-terminated string of text to measure. + * @param tileset Font tileset to use for measurement. + * @param outWidth Pointer to store the measured width in pixels. + * @param outHeight Pointer to store the measured height in pixels. + */ +void textMeasure( + const char_t *text, + const tileset_t *tileset, + int32_t *outWidth, + int32_t *outHeight +); \ No newline at end of file diff --git a/src/script/module/display/CMakeLists.txt b/src/script/module/display/CMakeLists.txt index aba882e..45f8362 100644 --- a/src/script/module/display/CMakeLists.txt +++ b/src/script/module/display/CMakeLists.txt @@ -11,4 +11,6 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME} modulespritebatch.c moduleglm.c modulecolor.c + moduletext.c + modulescreen.c ) \ No newline at end of file diff --git a/src/script/module/display/modulescreen.c b/src/script/module/display/modulescreen.c new file mode 100644 index 0000000..6bda4c5 --- /dev/null +++ b/src/script/module/display/modulescreen.c @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "modulescreen.h" +#include "assert/assert.h" +#include "display/screen.h" + +void moduleScreen(scriptcontext_t *context) { + assertNotNull(context, "Context cannot be NULL."); + + lua_register(context->luaState, "screenGetWidth", moduleScreenGetWidth); + lua_register(context->luaState, "screenGetHeight", moduleScreenGetHeight); +} + +int moduleScreenGetWidth(lua_State *L) { + assertNotNull(L, "Lua state is null"); + lua_pushinteger(L, SCREEN.width); + return 1; +} + +int moduleScreenGetHeight(lua_State *L) { + assertNotNull(L, "Lua state is null"); + lua_pushinteger(L, SCREEN.height); + return 1; +} \ No newline at end of file diff --git a/src/script/module/display/modulescreen.h b/src/script/module/display/modulescreen.h new file mode 100644 index 0000000..3375679 --- /dev/null +++ b/src/script/module/display/modulescreen.h @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "script/scriptcontext.h" + +/** + * Registers the Screen module with the given script context. + * + * @param context The script context to register the module with. + */ +void moduleScreen(scriptcontext_t *context); + +/** + * Gets the current screen width. + * + * @param L The Lua state. + * @return Count of return values. + */ +int moduleScreenGetWidth(lua_State *L); + +/** + * Gets the current screen height. + * + * @param L The Lua state. + * @return Count of return values. + */ +int moduleScreenGetHeight(lua_State *L); \ No newline at end of file diff --git a/src/script/module/display/modulespritebatch.c b/src/script/module/display/modulespritebatch.c index c123e98..00c95b5 100644 --- a/src/script/module/display/modulespritebatch.c +++ b/src/script/module/display/modulespritebatch.c @@ -55,7 +55,6 @@ int moduleSpriteBatchPush(lua_State *L) { return luaL_error(L, "Sprite color must be a color struct or nil"); } - // Optional UV min and maxes, defaults to 0,0 -> 1,1 float_t u0 = 0.0f; float_t v0 = 0.0f; diff --git a/src/script/module/display/moduletext.c b/src/script/module/display/moduletext.c new file mode 100644 index 0000000..1596dcf --- /dev/null +++ b/src/script/module/display/moduletext.c @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "moduletext.h" +#include "assert/assert.h" +#include "display/text.h" +#include "display/spritebatch.h" + +void moduleText(scriptcontext_t *context) { + assertNotNull(context, "Script context is null"); + + lua_register(context->luaState, "textDraw", moduleTextDraw); + lua_register(context->luaState, "textMeasure", moduleTextMeasure); +} + +int moduleTextDraw(lua_State *L) { + assertNotNull(L, "Lua state is null"); + + // Position. + if(!lua_isnumber(L, 1)) { + return luaL_error(L, "X position must be a number"); + } + if(!lua_isnumber(L, 2)) { + return luaL_error(L, "Y position must be a number"); + } + + const float_t x = (float_t)lua_tonumber(L, 1); + const float_t y = (float_t)lua_tonumber(L, 2); + + // String + if(!lua_isstring(L, 3)) { + return luaL_error(L, "Text to draw must be a string"); + } + const char_t *text = (const char_t*)lua_tostring(L, 3); + + // Optional color + color_t *color = NULL; + if(lua_gettop(L) < 6 || lua_isnil(L, 6)) { + // Allow NULL + } else if(lua_isuserdata(L, 6)) { + color = (color_t*)luaL_checkudata(L, 6, "color_mt"); + } else { + return luaL_error(L, "Sprite color must be a color struct or nil"); + } + + // For now, use the default font tileset and texture. + textDraw( + x, + y, + text, + color == NULL ? COLOR_WHITE : *color, + &DEFAULT_FONT_TILESET, + &DEFAULT_FONT_TEXTURE + ); + spriteBatchFlush(); +} + +int moduleTextMeasure(lua_State *L) { + assertNotNull(L, "Lua state is null"); + + // String + if(!lua_isstring(L, 1)) { + return luaL_error(L, "Text to measure must be a string"); + } + const char_t *text = (const char_t*)lua_tostring(L, 1); + + int32_t width = 0; + int32_t height = 0; + textMeasure( + text, + &DEFAULT_FONT_TILESET, + &width, + &height + ); + + lua_pushinteger(L, width); + lua_pushinteger(L, height); + return 2; +} \ No newline at end of file diff --git a/src/script/module/display/moduletext.h b/src/script/module/display/moduletext.h new file mode 100644 index 0000000..680e9b3 --- /dev/null +++ b/src/script/module/display/moduletext.h @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "script/scriptcontext.h" + +/** + * Register text rendering functions to the given script context. + * + * @param context The script context to register text functions to. + */ +void moduleText(scriptcontext_t *context); + +/** + * Script binding for drawing text. + * + * @param L The Lua state. + * @return Number of return values on the Lua stack. + */ +int moduleTextDraw(lua_State *L); + +/** + * Script binding for measuring text dimensions. + * + * @param L The Lua state. + * @return Number of return values on the Lua stack. + */ +int moduleTextMeasure(lua_State *L); \ No newline at end of file diff --git a/src/script/module/time/moduletime.c b/src/script/module/time/moduletime.c index ae68fb8..a813a73 100644 --- a/src/script/module/time/moduletime.c +++ b/src/script/module/time/moduletime.c @@ -18,6 +18,11 @@ void moduleTime(scriptcontext_t *ctx) { lua_pushcfunction(ctx->luaState, moduleTimeIndex); lua_settable(ctx->luaState, -3); } + + // Global time struct + lua_pushlightuserdata(ctx->luaState, &TIME); + luaL_setmetatable(ctx->luaState, "time_mt"); + lua_setglobal(ctx->luaState, "TIME"); } int moduleTimeIndex(lua_State *L) { diff --git a/src/script/module/ui/moduleui.c b/src/script/module/ui/moduleui.c index 3de230c..f71ad19 100644 --- a/src/script/module/ui/moduleui.c +++ b/src/script/module/ui/moduleui.c @@ -12,25 +12,4 @@ void moduleUi(scriptcontext_t *ctx) { assertNotNull(ctx, "Script context cannot be NULL"); - lua_register(ctx->luaState, "uiPush", moduleUiPush); -} - -int moduleUiPush(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - // Expect path string. TODO Support non scripted ui elements. - if(!lua_isstring(L, 1)) { - return luaL_error(L, "uiPush expects a string path as the first argument"); - } - - const char_t *path = lua_tostring(L, 1); - - printf("Pushing UI from script: %s\n", path); - errorret_t err = uiPushScript(path); - if(err.code != ERROR_OK) { - errorCatch(errorPrint(err)); - return luaL_error(L, "uiPush failed for path: %s", path); - } - - return 0; } \ No newline at end of file diff --git a/src/script/module/ui/moduleui.h b/src/script/module/ui/moduleui.h index dbdf789..3e65ea4 100644 --- a/src/script/module/ui/moduleui.h +++ b/src/script/module/ui/moduleui.h @@ -7,20 +7,11 @@ #pragma once #include "script/scriptcontext.h" +#include "error/error.h" /** * Registers the ui module within the given script context. * * @param ctx The script context to register the module in. */ -void moduleUi(scriptcontext_t *ctx); - -/** - * Lua binding for uiPush function. - * - * Expects a string path to the UI script as the first argument. - * - * @param L The Lua state. - * @return Number of return values on the Lua stack. - */ -int moduleUiPush(lua_State *L); \ No newline at end of file +void moduleUi(scriptcontext_t *ctx); \ No newline at end of file diff --git a/src/script/scriptmodule.c b/src/script/scriptmodule.c index 73015a1..5606555 100644 --- a/src/script/scriptmodule.c +++ b/src/script/scriptmodule.c @@ -19,6 +19,8 @@ #include "script/module/display/modulecamera.h" #include "script/module/display/moduleglm.h" #include "script/module/ui/moduleui.h" +#include "script/module/display/moduletext.h" +#include "script/module/display/modulescreen.h" #include "util/string.h" const scriptmodule_t SCRIPT_MODULE_LIST[] = { @@ -35,6 +37,8 @@ const scriptmodule_t SCRIPT_MODULE_LIST[] = { { .name = "camera", .callback = moduleCamera }, { .name = "glm", .callback = moduleGLM }, { .name = "ui", .callback = moduleUi }, + { .name = "text", .callback = moduleText }, + { .name = "screen", .callback = moduleScreen }, }; #define SCRIPT_MODULE_COUNT ( \ diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index e5fe231..17e8dd9 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -7,5 +7,4 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME} PUBLIC ui.c - uielement.c ) \ No newline at end of file diff --git a/src/ui/ui.c b/src/ui/ui.c index 1add719..1f9bf3b 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -24,11 +24,6 @@ errorret_t uiInit(void) { } void uiUpdate(void) { - uint_fast8_t i = 0; - while(i < UI.stackSize) { - errorCatch(errorPrint(uiElementUpdate(&UI.stack[i]))); - i++; - } } void uiRender(void) { @@ -38,34 +33,9 @@ void uiRender(void) { cameraPushMatrix(&UI.camera); spriteBatchClear(); - uint_fast8_t i = 0; - while(i < UI.stackSize) { - errorCatch(errorPrint(uiElementRender(&UI.stack[i]))); - i++; - } - spriteBatchFlush(); cameraPopMatrix(); } -errorret_t uiPushScript(const char_t *path) { - assertTrue(UI.stackSize < UI_STACK_SIZE, "UI stack overflow"); - uielement_t *element = &UI.stack[UI.stackSize]; - errorChain(uiElementInitScript(element, path)); - UI.stackSize++; - // Ret Id or something? - errorOk(); -} - -void uiPop(void) { - assertTrue(UI.stackSize > 0, "UI stack underflow"); - UI.stackSize--; - uielement_t *element = &UI.stack[UI.stackSize]; - uiElementDispose(element); -} - void uiDispose(void) { - while(UI.stackSize > 0) { - uiPop(); - } } \ No newline at end of file diff --git a/src/ui/ui.h b/src/ui/ui.h index 70da817..e60df1a 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -7,15 +7,10 @@ #pragma once #include "display/camera/camera.h" -#include "ui/uielement.h" - -#define UI_STACK_SIZE 64 +#include "error/error.h" typedef struct { camera_t camera; - - uielement_t stack[UI_STACK_SIZE]; - uint_fast8_t stackSize; } ui_t; extern ui_t UI; @@ -35,18 +30,6 @@ void uiUpdate(void); */ void uiRender(void); -/** - * Pushes a new UI element onto the UI stack from a script file. - * - * @param path Path to the UI script file. - */ -errorret_t uiPushScript(const char_t *path); - -/** - * Pops the top UI element from the UI stack. - */ -void uiPop(void); - /** * Disposes of the UI system. */ diff --git a/src/ui/uielement.c b/src/ui/uielement.c deleted file mode 100644 index c7dd8b3..0000000 --- a/src/ui/uielement.c +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "uielement.h" -#include "display/screen.h" -#include "debug/debug.h" - -errorret_t uiElementInitScript( - uielement_t *element, - const char_t *path -) { - errorChain(scriptContextInit(&element->ctx)); - errorChain(scriptContextExecFile(&element->ctx, path)); - errorOk(); -} - -errorret_t uiElementUpdate(uielement_t *element) { - lua_getglobal(element->ctx.luaState, "uiElementUpdate"); - if(lua_isfunction(element->ctx.luaState, -1)) { - if(lua_pcall(element->ctx.luaState, 0, 0, 0) != LUA_OK) { - const char_t *strErr = lua_tostring(element->ctx.luaState, -1); - lua_pop(element->ctx.luaState, 1); - errorThrow("Failed to call UI element uiElementUpdate: %s", strErr); - } - } else { - lua_pop(element->ctx.luaState, 1); - } - - errorOk(); -} - -errorret_t uiElementRender(uielement_t *element) { - lua_getglobal(element->ctx.luaState, "uiElementRender"); - if(lua_isfunction(element->ctx.luaState, -1)) { - - // Push parameters: x, y, w, h - lua_pushnumber(element->ctx.luaState, 0); - lua_pushnumber(element->ctx.luaState, 0); - lua_pushnumber(element->ctx.luaState, SCREEN.width); - lua_pushnumber(element->ctx.luaState, SCREEN.height); - - if(lua_pcall(element->ctx.luaState, 4, 0, 0) != LUA_OK) { - const char_t *strErr = lua_tostring(element->ctx.luaState, -1); - lua_pop(element->ctx.luaState, 1); - errorThrow("Failed to call UI element uiElementRender: %s", strErr); - } - } else { - lua_pop(element->ctx.luaState, 1); - } - - errorOk(); -} - -void uiElementDispose(uielement_t *element) { - lua_getglobal(element->ctx.luaState, "uiElementDispose"); - if(lua_isfunction(element->ctx.luaState, -1)) { - if(lua_pcall(element->ctx.luaState, 0, 0, 0) != LUA_OK) { - const char_t *strErr = lua_tostring(element->ctx.luaState, -1); - lua_pop(element->ctx.luaState, 1); - debugPrint("Failed to call UI element uiElementDispose: %s\n", strErr); - } - } else { - lua_pop(element->ctx.luaState, 1); - } - scriptContextDispose(&element->ctx); -} \ No newline at end of file diff --git a/src/ui/uielement.h b/src/ui/uielement.h deleted file mode 100644 index 1e2f928..0000000 --- a/src/ui/uielement.h +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "script/scriptcontext.h" - -// TODO: Support both scripted and native UI elements. -typedef struct { - scriptcontext_t ctx; -} uielement_t; - -/** - * Initializes a scripted UI Element. - * - * @param element The UI element to initialize. - * @param path Path to the UI script file. - */ -errorret_t uiElementInitScript( - uielement_t *element, - const char_t *path -); - -/** - * Updates/ticks a UI element's logic. - * - * @param element The UI element to tick. - */ -errorret_t uiElementUpdate(uielement_t *element); - -/** - * Renders a UI element. - * - * @param element The UI element to render. - */ -errorret_t uiElementRender(uielement_t *element); - -/** - * Disposes of a UI element. - * - * @param element The UI element to dispose of. - */ -void uiElementDispose(uielement_t *element); \ No newline at end of file