Scene methods
Some checks failed
Build Dusk / run-tests (push) Failing after 2m14s
Build Dusk / build-linux (push) Successful in 2m12s
Build Dusk / build-psp (push) Failing after 1m30s

This commit is contained in:
2026-01-28 10:31:31 -06:00
parent 25dc97e3cc
commit 6bdb4ae30d
20 changed files with 215 additions and 151 deletions

View File

@@ -39,5 +39,5 @@ else
end end
localeSet(DUSK_LOCALE_EN_US) localeSet(DUSK_LOCALE_EN_US)
-- sceneSet('map') sceneSet('scene/initial.dsf')
-- mapLoad('map/testmap/testmap.dmf') -- mapLoad('map/testmap/testmap.dmf')

View File

@@ -3,4 +3,4 @@
# This software is released under the MIT License. # This software is released under the MIT License.
# https://opensource.org/licenses/MIT # https://opensource.org/licenses/MIT
add_asset(SCRIPT map.lua) add_asset(SCRIPT initial.lua)

1
assets/scene/initial.lua Normal file
View File

@@ -0,0 +1 @@
print('Initial scene')

View File

@@ -1 +0,0 @@
-- Map Scene

View File

@@ -108,13 +108,15 @@ errorret_t errorChainImpl(
return retval; return retval;
} }
void errorCatch(const errorret_t retval) { void errorCatch(errorret_t retval) {
if(retval.code == ERROR_OK) return; if(retval.code == ERROR_OK) return;
assertNotNull(retval.state, "Error state cannot be NULL"); assertNotNull(retval.state, "Error state cannot be NULL");
assertNotNull(retval.state->message, "Message cannot be NULL"); assertNotNull(retval.state->message, "Message cannot be NULL");
// Clear the error state
memoryFree((void*)retval.state->message); memoryFree((void*)retval.state->message);
retval.state->code = ERROR_OK;
} }
errorret_t errorPrint(const errorret_t retval) { errorret_t errorPrint(const errorret_t retval) {

View File

@@ -78,7 +78,7 @@ errorret_t errorChainImpl(
* *
* @param retval The return value containing the error state. * @param retval The return value containing the error state.
*/ */
void errorCatch(const errorret_t retval); void errorCatch(errorret_t retval);
/** /**
* Prints the error state to the console. * Prints the error state to the console.

View File

@@ -5,80 +5,63 @@
#include "scene.h" #include "scene.h"
#include "assert/assert.h" #include "assert/assert.h"
#include "util/string.h" #include "util/memory.h"
const scene_t SCENES[] = { scene_t SCENE;
};
uint_fast8_t SCENE_CURRENT = 0xFF;
errorret_t sceneInit(void) { errorret_t sceneInit(void) {
// Initialize the scene subsystem here memoryZero(&SCENE, sizeof(scene_t));
errorChain(scriptContextInit(&SCENE.scriptContext));
errorOk(); errorOk();
} }
void sceneUpdate(void) { void sceneUpdate(void) {
const scene_t *current = sceneGetCurrent(); if(!scriptContextHasFunc(&SCENE.scriptContext, "sceneUpdate")) {
if(current && current->update) { return;
current->update();
} }
errorret_t err = scriptContextCallFunc(
&SCENE.scriptContext, "sceneUpdate", NULL, 0, NULL
);
errorCatch(errorPrint(err));
} }
void sceneRender(void) { void sceneRender(void) {
const scene_t *current = sceneGetCurrent(); if(!scriptContextHasFunc(&SCENE.scriptContext, "sceneRender")) {
return;
if(current && current->render) {
current->render();
}
} }
void sceneDispose(void) { errorret_t err = scriptContextCallFunc(
const scene_t *current = sceneGetCurrent(); &SCENE.scriptContext, "sceneRender", NULL, 0, NULL
if(current && current->dispose) {
current->dispose();
}
}
errorret_t sceneSet(const scene_t *scene) {
sceneDispose();
if(scene) {
SCENE_CURRENT = (uint_fast8_t)(scene - SCENES);
assertTrue(
SCENE_CURRENT < sizeof(SCENES) / sizeof(scene_t),
"Invalid scene index."
); );
errorCatch(errorPrint(err));
}
if(scene->init) { errorret_t sceneSet(const char_t *script) {
errorret_t err = scene->init(); // Cleanup old script context.
if(err.code != ERROR_OK) SCENE_CURRENT = 0xFF; if(scriptContextHasFunc(&SCENE.scriptContext, "sceneDispose")) {
errorChain(err); errorret_t err = scriptContextCallFunc(
} &SCENE.scriptContext, "sceneDispose", NULL, 0, NULL
} else { );
SCENE_CURRENT = 0xFF; errorCatch(errorPrint(err));
} }
scriptContextDispose(&SCENE.scriptContext);
// Create a new script context.
errorChain(scriptContextInit(&SCENE.scriptContext));
errorChain(scriptContextExecFile(&SCENE.scriptContext, script));
errorOk(); errorOk();
} }
const scene_t* sceneGetCurrent(void) { void sceneDispose(void) {
if(SCENE_CURRENT == 0xFF) return NULL; if(scriptContextHasFunc(&SCENE.scriptContext, "sceneDispose")) {
errorret_t err = scriptContextCallFunc(
assertTrue( &SCENE.scriptContext, "sceneDispose", NULL, 0, NULL
SCENE_CURRENT < sizeof(SCENES) / sizeof(scene_t),
"Invalid current scene index."
); );
errorCatch(errorPrint(err));
return &SCENES[SCENE_CURRENT];
} }
const scene_t* sceneGetByName(const char_t *name) { scriptContextDispose(&SCENE.scriptContext);
for(uint_fast8_t i = 0; i < sizeof(SCENES) / sizeof(scene_t); i++) {
if(stringCompare(SCENES[i].name, name) == 0) {
return &SCENES[i];
}
}
return NULL;
} }

View File

@@ -6,18 +6,13 @@
*/ */
#pragma once #pragma once
#include "error/error.h" #include "script/scriptcontext.h"
typedef struct { typedef struct {
const char_t *name; scriptcontext_t scriptContext;
errorret_t (*init)(void);
void (*update)(void);
void (*render)(void);
void (*dispose)(void);
} scene_t; } scene_t;
extern const scene_t SCENES[]; extern scene_t SCENE;
extern uint_fast8_t SCENE_CURRENT;
/** /**
* Initialize the scene subsystem. * Initialize the scene subsystem.
@@ -34,30 +29,14 @@ void sceneUpdate(void);
*/ */
void sceneRender(void); void sceneRender(void);
/**
* Set the current scene by script name.
*
* @param script The script name of the scene to set.
*/
errorret_t sceneSet(const char_t *script);
/** /**
* Dispose of the scene subsystem. * Dispose of the scene subsystem.
*/ */
void sceneDispose(void); void sceneDispose(void);
/**
* Set the current scene.
*
* @param sceneIndex The index of the scene to set.
* @return An error code indicating success or failure.
*/
errorret_t sceneSet(const scene_t *scene);
/**
* Get the current scene.
*
* @return The current scene.
*/
const scene_t* sceneGetCurrent(void);
/**
* Get a scene by its name.
*
* @param name The name of the scene.
* @return The scene with the given name, or NULL if not found.
*/
const scene_t* sceneGetByName(const char_t *name);

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2025 Dominic Masters # Copyright (c) 2026 Dominic Masters
# #
# This software is released under the MIT License. # This software is released under the MIT License.
# https://opensource.org/licenses/MIT # https://opensource.org/licenses/MIT
@@ -9,3 +9,5 @@ add_subdirectory(input)
add_subdirectory(item) add_subdirectory(item)
add_subdirectory(locale) add_subdirectory(locale)
add_subdirectory(system) add_subdirectory(system)
add_subdirectory(scene)
add_subdirectory(time)

View File

@@ -48,6 +48,7 @@ int moduleLocaleSet(lua_State *L) {
err = localeManagerSetLocale(locale); err = localeManagerSetLocale(locale);
if(err.code != ERROR_OK) { if(err.code != ERROR_OK) {
luaL_error(L, "localeSet: Failed to set locale"); luaL_error(L, "localeSet: Failed to set locale");
errorCatch(errorPrint(err));
return 0; return 0;
} }

View File

@@ -1,41 +0,0 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "script/scriptcontext.h"
#include "scene/scene.h"
int moduleSceneSetScene(lua_State *L) {
assertNotNull(L, "Lua state cannot be NULL");
assertTrue(lua_isstring(L, 1), "Expected string scene name");
const char *sceneName = luaL_checkstring(L, 1);
if(sceneName == NULL || sceneName[0] == '\0') {
luaL_error(L, "Scene name cannot be NULL");
return 0;
}
const scene_t *scene = sceneGetByName(sceneName);
if(scene == NULL) {
luaL_error(L, "Scene '%s' not found", sceneName);
return 0;
}
errorret_t err = sceneSet(scene);
if(err.code != ERROR_OK) {
luaL_error(L, "Failed to set scene '%s'", sceneName);
return 0;
}
return 0;
}
void moduleScene(scriptcontext_t *ctx) {
assertNotNull(ctx, "Script context cannot be NULL");
scriptContextRegFunc(ctx, "sceneSet", moduleSceneSetScene);
}

View File

@@ -0,0 +1,10 @@
# Copyright (c) 2026 Dominic Masters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Sources
target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
modulescene.c
)

View File

@@ -0,0 +1,37 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "modulescene.h"
#include "assert/assert.h"
#include "scene/scene.h"
void moduleScene(scriptcontext_t *ctx) {
assertNotNull(ctx, "Script context cannot be NULL");
scriptContextRegFunc(ctx, "sceneSet", moduleSceneSet);
}
int moduleSceneSet(lua_State *L) {
assertNotNull(L, "Lua state cannot be NULL");
// Need string
if (!lua_isstring(L, 1)) {
luaL_error(L, "sceneSet requires a string argument");
return 0;
}
const char_t *script = lua_tostring(L, 1);
errorret_t err = sceneSet(script);
if(err.code != ERROR_OK) {
luaL_error(L, "Failed to set scene");
errorCatch(errorPrint(err));
return 0;
}
return 0;
}

View File

@@ -0,0 +1,24 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "script/scriptcontext.h"
/**
* Register the scene module within the given script context.
*
* @param ctx The script context to register the module in.
*/
void moduleScene(scriptcontext_t *ctx);
/**
* Lua binding for sceneSet function.
*
* @param L The Lua state.
* @return int Number of return values on the Lua stack.
*/
int moduleSceneSet(lua_State *L);

View File

@@ -0,0 +1,10 @@
# Copyright (c) 2026 Dominic Masters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Sources
target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
moduletime.c
)

View File

@@ -5,10 +5,19 @@
* https://opensource.org/licenses/MIT * https://opensource.org/licenses/MIT
*/ */
#pragma once #include "moduletime.h"
#include "script/scriptcontext.h" #include "assert/assert.h"
#include "time/time.h" #include "script/scriptstruct.h"
#include "util/string.h"
void moduleTime(scriptcontext_t *ctx) {
assertNotNull(ctx, "Script context cannot be NULL");
// Script structure
scriptStructRegister(ctx, "time_mt", moduleTimeGetter, NULL);
// Register struct
scriptStructPush(ctx, "time_mt", "TIME", &TIME);
}
void moduleTimeGetter( void moduleTimeGetter(
const scriptcontext_t *context, const scriptcontext_t *context,
@@ -26,13 +35,3 @@ void moduleTimeGetter(
return; return;
} }
} }
void moduleTime(scriptcontext_t *ctx) {
assertNotNull(ctx, "Script context cannot be NULL");
// Script structure
scriptStructRegister(ctx, "time_mt", moduleTimeGetter, NULL);
// Register struct
scriptStructPush(ctx, "time_mt", "TIME", &TIME);
}

View File

@@ -0,0 +1,33 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "script/scriptcontext.h"
#include "time/time.h"
#include "util/string.h"
/**
* Registers the time module within the given script context.
*
* @param ctx The script context to register the module in.
*/
void moduleTime(scriptcontext_t *ctx);
/**
* Getter function for the TIME struct in scripts.
*
* @param context The script context.
* @param key The key being accessed.
* @param structPtr Pointer to the struct instance.
* @param outValue Output parameter to store the retrieved value.
*/
void moduleTimeGetter(
const scriptcontext_t *context,
const char_t *key,
const void *structPtr,
scriptvalue_t *outValue
);

View File

@@ -155,6 +155,19 @@ errorret_t scriptContextCallFunc(
errorOk(); 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

@@ -74,6 +74,18 @@ errorret_t scriptContextCallFunc(
scriptvalue_t *retValue 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

@@ -9,10 +9,10 @@
#include "script/module/system/modulesystem.h" #include "script/module/system/modulesystem.h"
#include "script/module/input/moduleinput.h" #include "script/module/input/moduleinput.h"
#include "script/module/moduleplatform.h" #include "script/module/moduleplatform.h"
#include "script/module/modulescene.h" #include "script/module/scene/modulescene.h"
#include "script/module/item/moduleitem.h" #include "script/module/item/moduleitem.h"
#include "script/module/locale/modulelocale.h" #include "script/module/locale/modulelocale.h"
#include "script/module/moduletime.h" #include "script/module/time/moduletime.h"
#include "script/module/event/moduleevent.h" #include "script/module/event/moduleevent.h"
#include "util/string.h" #include "util/string.h"