More lua stuff, yay.
Some checks failed
Build Dusk / run-tests (push) Failing after 1m18s
Build Dusk / build-linux (push) Failing after 1m43s
Build Dusk / build-psp (push) Failing after 1m46s

This commit is contained in:
2026-02-01 21:54:33 -06:00
parent 053778a502
commit c6f4518684
14 changed files with 131 additions and 202 deletions

View File

@@ -1,17 +1,16 @@
module('spritebatch') module('spritebatch')
-- module('time')
module('camera') module('camera')
-- module('glm')
module('color') module('color')
module('ui')
camera = cameraCreate(CAMERA_PROJECTION_TYPE_PERSPECTIVE) camera = cameraCreate(CAMERA_PROJECTION_TYPE_PERSPECTIVE)
uiPush('ui/test.dsf')
function sceneDispose() function sceneDispose()
-- print('Disposing initial scene')
end end
function sceneUpdate() function sceneUpdate()
end end
function sceneRender() function sceneRender()

View File

@@ -1,6 +1,6 @@
module('spritebatch') module('spritebatch')
function render(x, y, w, h) function uiElementRender(x, y, w, h)
spriteBatchPush( spriteBatchPush(
nil, nil,
x, y, x, y,

View File

@@ -120,13 +120,12 @@ errorret_t displayUpdate(void) {
FRAMEBUFFER_CLEAR_COLOR | FRAMEBUFFER_CLEAR_DEPTH, FRAMEBUFFER_CLEAR_COLOR | FRAMEBUFFER_CLEAR_DEPTH,
COLOR_CORNFLOWER_BLUE COLOR_CORNFLOWER_BLUE
); );
sceneRender(); errorChain(sceneRender());
// Render UI // Render UI
uiRender(); uiRender();
// Finish up // Finish up
spriteBatchFlush();
screenUnbind(); screenUnbind();
screenRender(); screenRender();

View File

@@ -55,7 +55,7 @@ errorret_t engineUpdate(void) {
// errorChain(rpgUpdate()); // errorChain(rpgUpdate());
uiUpdate(); uiUpdate();
sceneUpdate(); errorChain(sceneUpdate());
errorChain(displayUpdate()); errorChain(displayUpdate());
if(inputPressed(INPUT_ACTION_RAGEQUIT)) ENGINE.running = false; if(inputPressed(INPUT_ACTION_RAGEQUIT)) ENGINE.running = false;

View File

@@ -6,6 +6,8 @@
#include "scene.h" #include "scene.h"
#include "assert/assert.h" #include "assert/assert.h"
#include "util/memory.h" #include "util/memory.h"
#include "debug/debug.h"
#include "time/time.h"
#include "display/camera/camera.h" #include "display/camera/camera.h"
#include "display/screen.h" #include "display/screen.h"
@@ -19,31 +21,49 @@ errorret_t sceneInit(void) {
errorOk(); errorOk();
} }
void sceneUpdate(void) { errorret_t sceneUpdate(void) {
if(!scriptContextHasFunc(&SCENE.scriptContext, "sceneUpdate")) return; lua_getglobal(SCENE.scriptContext.luaState, "sceneUpdate");
if(!lua_isfunction(SCENE.scriptContext.luaState, -1)) {
lua_pop(SCENE.scriptContext.luaState, 1);
errorOk();
}
errorret_t err = scriptContextCallFunc( if(lua_pcall(SCENE.scriptContext.luaState, 0, 0, 0) != LUA_OK) {
&SCENE.scriptContext, "sceneUpdate", NULL, 0, NULL const char_t *strErr = lua_tostring(SCENE.scriptContext.luaState, -1);
); lua_pop(SCENE.scriptContext.luaState, 1);
errorCatch(errorPrint(err)); errorThrow("Failed to call function '%s': %s", "sceneUpdate", strErr);
}
errorOk();
} }
void sceneRender(void) { errorret_t sceneRender(void) {
if(!scriptContextHasFunc(&SCENE.scriptContext, "sceneRender")) return; lua_getglobal(SCENE.scriptContext.luaState, "sceneRender");
if(!lua_isfunction(SCENE.scriptContext.luaState, -1)) {
lua_pop(SCENE.scriptContext.luaState, 1);
errorOk();
}
errorret_t err = scriptContextCallFunc( if(lua_pcall(SCENE.scriptContext.luaState, 0, 0, 0) != LUA_OK) {
&SCENE.scriptContext, "sceneRender", NULL, 0, NULL const char_t *strErr = lua_tostring(SCENE.scriptContext.luaState, -1);
); lua_pop(SCENE.scriptContext.luaState, 1);
errorCatch(errorPrint(err)); errorThrow("Failed to call function '%s': %s", "sceneRender", strErr);
}
errorOk();
} }
errorret_t sceneSet(const char_t *script) { errorret_t sceneSet(const char_t *script) {
// Cleanup old script context. // Cleanup old script context.
if(scriptContextHasFunc(&SCENE.scriptContext, "sceneDispose")) { lua_getglobal(SCENE.scriptContext.luaState, "sceneDispose");
errorret_t err = scriptContextCallFunc( if(lua_isfunction(SCENE.scriptContext.luaState, -1)) {
&SCENE.scriptContext, "sceneDispose", NULL, 0, NULL if(lua_pcall(SCENE.scriptContext.luaState, 0, 0, 0) != LUA_OK) {
); const char_t *strErr = lua_tostring(SCENE.scriptContext.luaState, -1);
errorCatch(errorPrint(err)); 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); scriptContextDispose(&SCENE.scriptContext);
@@ -55,11 +75,15 @@ errorret_t sceneSet(const char_t *script) {
} }
void sceneDispose(void) { void sceneDispose(void) {
if(scriptContextHasFunc(&SCENE.scriptContext, "sceneDispose")) { lua_getglobal(SCENE.scriptContext.luaState, "sceneDispose");
errorret_t err = scriptContextCallFunc( if(lua_isfunction(SCENE.scriptContext.luaState, -1)) {
&SCENE.scriptContext, "sceneDispose", NULL, 0, NULL if(lua_pcall(SCENE.scriptContext.luaState, 0, 0, 0) != LUA_OK) {
); const char_t *strErr = lua_tostring(SCENE.scriptContext.luaState, -1);
errorCatch(errorPrint(err)); 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); scriptContextDispose(&SCENE.scriptContext);

View File

@@ -16,18 +16,24 @@ extern scene_t SCENE;
/** /**
* Initialize the scene subsystem. * Initialize the scene subsystem.
*
* @return The error return value.
*/ */
errorret_t sceneInit(void); errorret_t sceneInit(void);
/** /**
* Update the current scene. * Update the current scene.
*
* @return The error return value.
*/ */
void sceneUpdate(void); errorret_t sceneUpdate(void);
/** /**
* Render the current scene. * Render the current scene.
*
* @return The error return value.
*/ */
void sceneRender(void); errorret_t sceneRender(void);
/** /**
* Set the current scene by script name. * Set the current scene by script name.

View File

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

View File

@@ -23,6 +23,10 @@ void moduleColor(scriptcontext_t *context) {
lua_pushcfunction(context->luaState, moduleColorNewIndex); lua_pushcfunction(context->luaState, moduleColorNewIndex);
lua_settable(context->luaState, -3); 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); lua_pop(context->luaState, 1);
} }
@@ -129,6 +133,19 @@ int moduleColorNewIndex(lua_State *L) {
return 0; return 0;
} }
luaL_error(L, "Invalid color channel key.");
return 0; 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;
} }

View File

@@ -36,4 +36,12 @@ int moduleColorIndex(lua_State *L);
* @param L The Lua state. * @param L The Lua state.
* @return Number of return values. * @return Number of return values.
*/ */
int moduleColorNewIndex(lua_State *L); 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);

View File

@@ -35,11 +35,11 @@ void moduleInput(scriptcontext_t *context) {
#endif #endif
); );
// Script structure // Metatable
if(luaL_newmetatable(context->luaState, "input_mt")) { if(luaL_newmetatable(context->luaState, "input_mt")) {
// Metatable methods
lua_pushcfunction(context->luaState, moduleInputIndex); lua_pushcfunction(context->luaState, moduleInputIndex);
lua_setfield(context->luaState, -2, "__index"); lua_setfield(context->luaState, -2, "__index");
lua_pop(context->luaState, 1);
} }
@@ -68,7 +68,8 @@ int moduleInputIndex(lua_State *l) {
return 1; return 1;
} }
return 0; lua_pushnil(l);
return 1;
} }
int moduleInputBind(lua_State *L) { int moduleInputBind(lua_State *L) {

View File

@@ -33,4 +33,7 @@ int moduleTimeIndex(lua_State *L) {
lua_pushnumber(L, TIME.time); lua_pushnumber(L, TIME.time);
return 1; return 1;
} }
lua_pushnil(L);
return 1;
} }

View File

@@ -38,111 +38,6 @@ errorret_t scriptContextInit(scriptcontext_t *context) {
errorOk(); 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) { errorret_t scriptContextExec(scriptcontext_t *context, const char_t *script) {
assertNotNull(context, "Script context cannot be NULL"); assertNotNull(context, "Script context cannot be NULL");
assertNotNull(script, "Script cannot be NULL"); assertNotNull(script, "Script cannot be NULL");

View File

@@ -29,37 +29,6 @@ typedef struct scriptcontext_s {
*/ */
errorret_t scriptContextInit(scriptcontext_t *context); 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. * Execute a script within a script context.
* *

View File

@@ -7,6 +7,7 @@
#include "uielement.h" #include "uielement.h"
#include "display/screen.h" #include "display/screen.h"
#include "debug/debug.h"
errorret_t uiElementInitScript( errorret_t uiElementInitScript(
uielement_t *element, uielement_t *element,
@@ -18,40 +19,52 @@ errorret_t uiElementInitScript(
} }
errorret_t uiElementUpdate(uielement_t *element) { errorret_t uiElementUpdate(uielement_t *element) {
if(!scriptContextHasFunc(&element->ctx, "update")) errorOk(); lua_getglobal(element->ctx.luaState, "uiElementUpdate");
if(lua_isfunction(element->ctx.luaState, -1)) {
errorChain(scriptContextCallFunc( if(lua_pcall(element->ctx.luaState, 0, 0, 0) != LUA_OK) {
&element->ctx, const char_t *strErr = lua_tostring(element->ctx.luaState, -1);
"update", lua_pop(element->ctx.luaState, 1);
NULL, errorThrow("Failed to call UI element uiElementUpdate: %s", strErr);
0, }
NULL } else {
)); lua_pop(element->ctx.luaState, 1);
}
errorOk(); errorOk();
} }
errorret_t uiElementRender(uielement_t *element) { 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] = { // Push parameters: x, y, w, h
// { .type = SCRIPT_VALUE_TYPE_FLOAT, .value.floatValue = 0.0f }, lua_pushnumber(element->ctx.luaState, 0);
// { .type = SCRIPT_VALUE_TYPE_FLOAT, .value.floatValue = 0.0f }, lua_pushnumber(element->ctx.luaState, 0);
// { .type = SCRIPT_VALUE_TYPE_FLOAT, .value.floatValue = SCREEN.width }, lua_pushnumber(element->ctx.luaState, SCREEN.width);
// { .type = SCRIPT_VALUE_TYPE_FLOAT, .value.floatValue = SCREEN.height }, lua_pushnumber(element->ctx.luaState, SCREEN.height);
// };
if(lua_pcall(element->ctx.luaState, 4, 0, 0) != LUA_OK) {
// errorChain(scriptContextCallFunc( const char_t *strErr = lua_tostring(element->ctx.luaState, -1);
// &element->ctx, lua_pop(element->ctx.luaState, 1);
// "render", errorThrow("Failed to call UI element uiElementRender: %s", strErr);
// args, }
// 4, } else {
// NULL lua_pop(element->ctx.luaState, 1);
// )); }
errorOk(); errorOk();
} }
void uiElementDispose(uielement_t *element) { 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); scriptContextDispose(&element->ctx);
} }