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('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()

View File

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

View File

@@ -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();

View File

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

View File

@@ -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);

View File

@@ -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.

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;
}

View File

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

View File

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

View File

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

View File

@@ -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");

View File

@@ -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.
*

View File

@@ -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);
}