From c6f4518684d8a5cf2014e7ecdb3eb2d4e32bbee0 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Sun, 1 Feb 2026 21:54:33 -0600 Subject: [PATCH] More lua stuff, yay. --- assets/scene/initial.lua | 7 +- assets/ui/test.lua | 2 +- src/display/display.c | 3 +- src/engine/engine.c | 2 +- src/scene/scene.c | 68 ++++++++++----- src/scene/scene.h | 10 ++- src/script/module/display/modulecamera.c | 5 -- src/script/module/display/modulecolor.c | 19 +++- src/script/module/display/modulecolor.h | 10 ++- src/script/module/input/moduleinput.c | 7 +- src/script/module/time/moduletime.c | 3 + src/script/scriptcontext.c | 105 ----------------------- src/script/scriptcontext.h | 31 ------- src/ui/uielement.c | 61 +++++++------ 14 files changed, 131 insertions(+), 202 deletions(-) diff --git a/assets/scene/initial.lua b/assets/scene/initial.lua index 0abb998..87ca123 100644 --- a/assets/scene/initial.lua +++ b/assets/scene/initial.lua @@ -1,17 +1,16 @@ module('spritebatch') --- module('time') module('camera') --- module('glm') module('color') +module('ui') camera = cameraCreate(CAMERA_PROJECTION_TYPE_PERSPECTIVE) +uiPush('ui/test.dsf') + function sceneDispose() - -- print('Disposing initial scene') end function sceneUpdate() - end function sceneRender() diff --git a/assets/ui/test.lua b/assets/ui/test.lua index 67aa1ca..cb91065 100644 --- a/assets/ui/test.lua +++ b/assets/ui/test.lua @@ -1,6 +1,6 @@ module('spritebatch') -function render(x, y, w, h) +function uiElementRender(x, y, w, h) spriteBatchPush( nil, x, y, diff --git a/src/display/display.c b/src/display/display.c index 26f2024..1e38697 100644 --- a/src/display/display.c +++ b/src/display/display.c @@ -120,13 +120,12 @@ errorret_t displayUpdate(void) { FRAMEBUFFER_CLEAR_COLOR | FRAMEBUFFER_CLEAR_DEPTH, COLOR_CORNFLOWER_BLUE ); - sceneRender(); + errorChain(sceneRender()); // Render UI uiRender(); // Finish up - spriteBatchFlush(); screenUnbind(); screenRender(); diff --git a/src/engine/engine.c b/src/engine/engine.c index 0ab68fa..2640480 100644 --- a/src/engine/engine.c +++ b/src/engine/engine.c @@ -55,7 +55,7 @@ errorret_t engineUpdate(void) { // errorChain(rpgUpdate()); uiUpdate(); - sceneUpdate(); + errorChain(sceneUpdate()); errorChain(displayUpdate()); if(inputPressed(INPUT_ACTION_RAGEQUIT)) ENGINE.running = false; diff --git a/src/scene/scene.c b/src/scene/scene.c index 5003a15..434eeb3 100644 --- a/src/scene/scene.c +++ b/src/scene/scene.c @@ -6,6 +6,8 @@ #include "scene.h" #include "assert/assert.h" #include "util/memory.h" +#include "debug/debug.h" +#include "time/time.h" #include "display/camera/camera.h" #include "display/screen.h" @@ -19,31 +21,49 @@ errorret_t sceneInit(void) { errorOk(); } -void sceneUpdate(void) { - if(!scriptContextHasFunc(&SCENE.scriptContext, "sceneUpdate")) return; +errorret_t sceneUpdate(void) { + lua_getglobal(SCENE.scriptContext.luaState, "sceneUpdate"); + if(!lua_isfunction(SCENE.scriptContext.luaState, -1)) { + lua_pop(SCENE.scriptContext.luaState, 1); + errorOk(); + } - errorret_t err = scriptContextCallFunc( - &SCENE.scriptContext, "sceneUpdate", NULL, 0, NULL - ); - errorCatch(errorPrint(err)); + if(lua_pcall(SCENE.scriptContext.luaState, 0, 0, 0) != LUA_OK) { + const char_t *strErr = lua_tostring(SCENE.scriptContext.luaState, -1); + lua_pop(SCENE.scriptContext.luaState, 1); + errorThrow("Failed to call function '%s': %s", "sceneUpdate", strErr); + } + + errorOk(); } -void sceneRender(void) { - if(!scriptContextHasFunc(&SCENE.scriptContext, "sceneRender")) return; +errorret_t sceneRender(void) { + lua_getglobal(SCENE.scriptContext.luaState, "sceneRender"); + if(!lua_isfunction(SCENE.scriptContext.luaState, -1)) { + lua_pop(SCENE.scriptContext.luaState, 1); + errorOk(); + } - errorret_t err = scriptContextCallFunc( - &SCENE.scriptContext, "sceneRender", NULL, 0, NULL - ); - errorCatch(errorPrint(err)); + if(lua_pcall(SCENE.scriptContext.luaState, 0, 0, 0) != LUA_OK) { + const char_t *strErr = lua_tostring(SCENE.scriptContext.luaState, -1); + lua_pop(SCENE.scriptContext.luaState, 1); + errorThrow("Failed to call function '%s': %s", "sceneRender", strErr); + } + + errorOk(); } errorret_t sceneSet(const char_t *script) { // Cleanup old script context. - if(scriptContextHasFunc(&SCENE.scriptContext, "sceneDispose")) { - errorret_t err = scriptContextCallFunc( - &SCENE.scriptContext, "sceneDispose", NULL, 0, NULL - ); - errorCatch(errorPrint(err)); + lua_getglobal(SCENE.scriptContext.luaState, "sceneDispose"); + if(lua_isfunction(SCENE.scriptContext.luaState, -1)) { + if(lua_pcall(SCENE.scriptContext.luaState, 0, 0, 0) != LUA_OK) { + const char_t *strErr = lua_tostring(SCENE.scriptContext.luaState, -1); + lua_pop(SCENE.scriptContext.luaState, 1); + errorThrow("Failed to call function '%s': %s", "sceneDispose", strErr); + } + } else { + lua_pop(SCENE.scriptContext.luaState, 1); } scriptContextDispose(&SCENE.scriptContext); @@ -55,11 +75,15 @@ errorret_t sceneSet(const char_t *script) { } void sceneDispose(void) { - if(scriptContextHasFunc(&SCENE.scriptContext, "sceneDispose")) { - errorret_t err = scriptContextCallFunc( - &SCENE.scriptContext, "sceneDispose", NULL, 0, NULL - ); - errorCatch(errorPrint(err)); + lua_getglobal(SCENE.scriptContext.luaState, "sceneDispose"); + if(lua_isfunction(SCENE.scriptContext.luaState, -1)) { + if(lua_pcall(SCENE.scriptContext.luaState, 0, 0, 0) != LUA_OK) { + const char_t *strErr = lua_tostring(SCENE.scriptContext.luaState, -1); + lua_pop(SCENE.scriptContext.luaState, 1); + debugPrint("Failed to call function '%s': %s\n", "sceneDispose", strErr); + } + } else { + lua_pop(SCENE.scriptContext.luaState, 1); } scriptContextDispose(&SCENE.scriptContext); diff --git a/src/scene/scene.h b/src/scene/scene.h index d766f07..4f87063 100644 --- a/src/scene/scene.h +++ b/src/scene/scene.h @@ -16,18 +16,24 @@ extern scene_t SCENE; /** * Initialize the scene subsystem. + * + * @return The error return value. */ errorret_t sceneInit(void); /** * Update the current scene. + * + * @return The error return value. */ -void sceneUpdate(void); +errorret_t sceneUpdate(void); /** * Render the current scene. + * + * @return The error return value. */ -void sceneRender(void); +errorret_t sceneRender(void); /** * Set the current scene by script name. diff --git a/src/script/module/display/modulecamera.c b/src/script/module/display/modulecamera.c index 7df8ca5..7bf0748 100644 --- a/src/script/module/display/modulecamera.c +++ b/src/script/module/display/modulecamera.c @@ -267,10 +267,5 @@ int moduleCameraNewIndex(lua_State *l) { } } - luaL_error( - l, - "Attempted to set unknown or read-only camera field '%s'.", - key - ); return 0; } \ No newline at end of file diff --git a/src/script/module/display/modulecolor.c b/src/script/module/display/modulecolor.c index cb2ddf1..d5825cb 100644 --- a/src/script/module/display/modulecolor.c +++ b/src/script/module/display/modulecolor.c @@ -23,6 +23,10 @@ void moduleColor(scriptcontext_t *context) { lua_pushcfunction(context->luaState, moduleColorNewIndex); lua_settable(context->luaState, -3); + lua_pushstring(context->luaState, "__tostring"); + lua_pushcfunction(context->luaState, moduleColorToString); + lua_settable(context->luaState, -3); + lua_pop(context->luaState, 1); } @@ -129,6 +133,19 @@ int moduleColorNewIndex(lua_State *L) { return 0; } - luaL_error(L, "Invalid color channel key."); return 0; +} + +int moduleColorToString(lua_State *L) { + assertNotNull(L, "Lua state cannot be NULL."); + + const color_t *color = (const color_t*)luaL_checkudata(L, 1, "color_mt"); + assertNotNull(color, "Color struct cannot be NULL."); + + lua_pushfstring( + L, "color(r=%d, g=%d, b=%d, a=%d)", + color->r, color->g, color->b, color->a + ); + + return 1; } \ No newline at end of file diff --git a/src/script/module/display/modulecolor.h b/src/script/module/display/modulecolor.h index aa3b8eb..f2c5076 100644 --- a/src/script/module/display/modulecolor.h +++ b/src/script/module/display/modulecolor.h @@ -36,4 +36,12 @@ int moduleColorIndex(lua_State *L); * @param L The Lua state. * @return Number of return values. */ -int moduleColorNewIndex(lua_State *L); \ No newline at end of file +int moduleColorNewIndex(lua_State *L); + +/** + * Color to string method for script + * + * @param L The Lua state. + * @return Number of return values. + */ +int moduleColorToString(lua_State *L); \ No newline at end of file diff --git a/src/script/module/input/moduleinput.c b/src/script/module/input/moduleinput.c index a63eb8d..0fc29c7 100644 --- a/src/script/module/input/moduleinput.c +++ b/src/script/module/input/moduleinput.c @@ -35,11 +35,11 @@ void moduleInput(scriptcontext_t *context) { #endif ); - // Script structure + // Metatable if(luaL_newmetatable(context->luaState, "input_mt")) { - // Metatable methods lua_pushcfunction(context->luaState, moduleInputIndex); lua_setfield(context->luaState, -2, "__index"); + lua_pop(context->luaState, 1); } @@ -68,7 +68,8 @@ int moduleInputIndex(lua_State *l) { return 1; } - return 0; + lua_pushnil(l); + return 1; } int moduleInputBind(lua_State *L) { diff --git a/src/script/module/time/moduletime.c b/src/script/module/time/moduletime.c index 6217e4f..ae68fb8 100644 --- a/src/script/module/time/moduletime.c +++ b/src/script/module/time/moduletime.c @@ -33,4 +33,7 @@ int moduleTimeIndex(lua_State *L) { lua_pushnumber(L, TIME.time); return 1; } + + lua_pushnil(L); + return 1; } \ No newline at end of file diff --git a/src/script/scriptcontext.c b/src/script/scriptcontext.c index b0de54f..c95b8b1 100644 --- a/src/script/scriptcontext.c +++ b/src/script/scriptcontext.c @@ -38,111 +38,6 @@ errorret_t scriptContextInit(scriptcontext_t *context) { errorOk(); } -errorret_t scriptContextCallFunc( - scriptcontext_t *context, - const char_t *fnName, - const scriptvalue_t *args, - const int32_t argCount, - scriptvalue_t *retValue -) { - assertNotNull(context, "Script context cannot be NULL"); - assertNotNull(fnName, "Function name cannot be NULL"); - assertTrue(args == NULL || argCount >= 0, "Invalid arg count"); - - // Get func - lua_getglobal(context->luaState, fnName); - if(!lua_isfunction(context->luaState, -1)) { - errorThrow("Function '%s' not found in script context", fnName); - } - - // Push args - for(int32_t i = 0; i < argCount; i++) { - const scriptvalue_t *arg = &args[i]; - switch(arg->type) { - case SCRIPT_VALUE_TYPE_INT: - lua_pushinteger(context->luaState, arg->value.intValue); - break; - - case SCRIPT_VALUE_TYPE_FLOAT: - lua_pushnumber(context->luaState, arg->value.floatValue); - break; - - case SCRIPT_VALUE_TYPE_STRING: - lua_pushstring(context->luaState, arg->value.strValue); - break; - - default: - errorThrow("Unsupported argument type %d", arg->type); - } - } - - // Call func - if(lua_pcall( - context->luaState, - args ? argCount : 0, - retValue ? 1 : 0, - 0 - ) != LUA_OK) { - const char_t *strErr = lua_tostring(context->luaState, -1); - lua_pop(context->luaState, 1); - errorThrow("Failed to call function '%s': %s", fnName, strErr); - } - - // Was there a ret value? - if(retValue == NULL) { - errorOk(); - } - - // Get ret value - switch(retValue->type) { - case SCRIPT_VALUE_TYPE_INT: - if(!lua_isinteger(context->luaState, -1)) { - errorThrow("Expected integer return value from '%s'", fnName); - } - retValue->value.intValue = (int32_t)lua_tointeger(context->luaState, -1); - break; - - case SCRIPT_VALUE_TYPE_FLOAT: - if(!lua_isnumber(context->luaState, -1)) { - errorThrow("Expected float return value from '%s'", fnName); - } - retValue->value.floatValue = (float)lua_tonumber(context->luaState, -1); - break; - - case SCRIPT_VALUE_TYPE_BOOL: - if(!lua_isboolean(context->luaState, -1)) { - errorThrow("Expected boolean return value from '%s'", fnName); - } - retValue->value.boolValue = lua_toboolean(context->luaState, -1); - break; - - // case SCRIPT_VALUE_TYPE_STRING: - // if(!lua_isstring(context->luaState, -1)) { - // errorThrow("Expected string return value from '%s'", fnName); - // } - // retValue->value.strValue = lua_tostring(context->luaState, -1); - // break; - - default: - errorThrow("Unsupported return value type %d", retValue->type); - } - - errorOk(); -} - -bool_t scriptContextHasFunc( - scriptcontext_t *context, - const char_t *fnName -) { - assertNotNull(context, "Script context cannot be NULL"); - assertNotNull(fnName, "Function name cannot be NULL"); - - lua_getglobal(context->luaState, fnName); - bool_t isFunc = lua_isfunction(context->luaState, -1); - lua_pop(context->luaState, 1); - return isFunc; -} - errorret_t scriptContextExec(scriptcontext_t *context, const char_t *script) { assertNotNull(context, "Script context cannot be NULL"); assertNotNull(script, "Script cannot be NULL"); diff --git a/src/script/scriptcontext.h b/src/script/scriptcontext.h index 26945d3..7469f2a 100644 --- a/src/script/scriptcontext.h +++ b/src/script/scriptcontext.h @@ -29,37 +29,6 @@ typedef struct scriptcontext_s { */ errorret_t scriptContextInit(scriptcontext_t *context); -/** - * Call a Lua function within a script context. - * - * @param context The script context to use. - * @param fnName The name of the Lua function to call. - * @param args Array of args to pass to the function (or NULL for no args) - * @param argCount The number of arguments in the args array (omitable). - * @param retValue Output to store returned value (or NULL for no return value). - * @return The error return value. - */ - -errorret_t scriptContextCallFunc( - scriptcontext_t *context, - const char_t *fnName, - const scriptvalue_t *args, - const int32_t argCount, - scriptvalue_t *retValue -); - -/** - * Checks if a Lua function exists within a script context. - * - * @param context The script context to use. - * @param fnName The name of the Lua function to check. - * @return true if the function exists, false otherwise. - */ -bool_t scriptContextHasFunc( - scriptcontext_t *context, - const char_t *fnName -); - /** * Execute a script within a script context. * diff --git a/src/ui/uielement.c b/src/ui/uielement.c index afa65b2..c7dd8b3 100644 --- a/src/ui/uielement.c +++ b/src/ui/uielement.c @@ -7,6 +7,7 @@ #include "uielement.h" #include "display/screen.h" +#include "debug/debug.h" errorret_t uiElementInitScript( uielement_t *element, @@ -18,40 +19,52 @@ errorret_t uiElementInitScript( } errorret_t uiElementUpdate(uielement_t *element) { - if(!scriptContextHasFunc(&element->ctx, "update")) errorOk(); - - errorChain(scriptContextCallFunc( - &element->ctx, - "update", - NULL, - 0, - NULL - )); + 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) { - if(!scriptContextHasFunc(&element->ctx, "render")) errorOk(); + lua_getglobal(element->ctx.luaState, "uiElementRender"); + if(lua_isfunction(element->ctx.luaState, -1)) { - // scriptvalue_t args[4] = { - // { .type = SCRIPT_VALUE_TYPE_FLOAT, .value.floatValue = 0.0f }, - // { .type = SCRIPT_VALUE_TYPE_FLOAT, .value.floatValue = 0.0f }, - // { .type = SCRIPT_VALUE_TYPE_FLOAT, .value.floatValue = SCREEN.width }, - // { .type = SCRIPT_VALUE_TYPE_FLOAT, .value.floatValue = SCREEN.height }, - // }; - - // errorChain(scriptContextCallFunc( - // &element->ctx, - // "render", - // args, - // 4, - // NULL - // )); + // 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