Scene script

This commit is contained in:
2026-04-20 15:34:24 -05:00
parent b89ae2391b
commit b640295be2
14 changed files with 143 additions and 27 deletions
+2 -2
View File
@@ -25,7 +25,7 @@ errorret_t assetInit(void) {
} }
bool_t assetFileExists(const char_t *filename) { bool_t assetFileExists(const char_t *filename) {
assertStrLenMax(filename, FILENAME_MAX, "Filename too long."); assertStrLenMax(filename, ASSET_FILE_PATH_MAX, "Filename too long.");
zip_int64_t idx = zip_name_locate(ASSET.zip, filename, 0); zip_int64_t idx = zip_name_locate(ASSET.zip, filename, 0);
if(idx < 0) return false; if(idx < 0) return false;
@@ -38,7 +38,7 @@ errorret_t assetLoad(
void *params, void *params,
void *output void *output
) { ) {
assertStrLenMax(filename, FILENAME_MAX, "Filename too long."); assertStrLenMax(filename, ASSET_FILE_PATH_MAX, "Filename too long.");
assertNotNull(output, "Output pointer cannot be NULL."); assertNotNull(output, "Output pointer cannot be NULL.");
assertNotNull(loader, "Asset file loader cannot be NULL."); assertNotNull(loader, "Asset file loader cannot be NULL.");
+2
View File
@@ -9,6 +9,8 @@
#include "error/error.h" #include "error/error.h"
#include <zip.h> #include <zip.h>
#define ASSET_FILE_PATH_MAX FILENAME_MAX
typedef struct assetfile_s assetfile_t; typedef struct assetfile_s assetfile_t;
typedef errorret_t (*assetfileloader_t)(assetfile_t *file); typedef errorret_t (*assetfileloader_t)(assetfile_t *file);
+1 -1
View File
@@ -31,7 +31,7 @@ void consoleInit() {
// Register vars // Register vars
#define REG(name, value) consoleRegVar(name, value, NULL) #define REG(name, value) consoleRegVar(name, value, NULL)
REG("console", "0"); REG("console", "1");
#undef REG #undef REG
// Register cmdss // Register cmdss
+7 -1
View File
@@ -55,22 +55,28 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) {
errorChain(scriptContextExecFile(&ctx, "init.lua")); errorChain(scriptContextExecFile(&ctx, "init.lua"));
scriptContextDispose(&ctx); scriptContextDispose(&ctx);
sceneSet("test/scene.lua");
errorOk(); errorOk();
} }
errorret_t engineUpdate(void) { errorret_t engineUpdate(void) {
// Order here is important.
errorChain(networkUpdate()); errorChain(networkUpdate());
timeUpdate(); timeUpdate();
inputUpdate(); inputUpdate();
consoleUpdate(); consoleUpdate();
uiUpdate(); uiUpdate();
errorChain(sceneUpdate());
physicsManagerUpdate(); physicsManagerUpdate();
errorChain(gameUpdate()); errorChain(gameUpdate());
errorChain(displayUpdate()); errorChain(displayUpdate());
if(inputPressed(INPUT_ACTION_RAGEQUIT)) ENGINE.running = false; if(inputPressed(INPUT_ACTION_RAGEQUIT)) ENGINE.running = false;
// Scene update occurs last because only after rendering would we want to do
// scene switching, refer to sceneSet() for information.
errorChain(sceneUpdate());
errorOk(); errorOk();
} }
+100 -4
View File
@@ -16,6 +16,7 @@
#include "display/text/text.h" #include "display/text/text.h"
#include "display/screen/screen.h" #include "display/screen/screen.h"
#include "console/console.h" #include "console/console.h"
#include "util/string.h"
scene_t SCENE; scene_t SCENE;
@@ -31,6 +32,27 @@ errorret_t sceneUpdate(void) {
} }
#endif #endif
// Is the scene changing?
if(stringCompare(SCENE.sceneNext, SCENE.sceneCurrent) != 0) {
errorChain(sceneSetImmediate(SCENE.sceneNext));
}
// Call scene update function if script loaded
if(!SCENE.scriptActive) {
errorOk();
}
assertNotNull(SCENE.script.luaState, "Script context null?");
lua_getglobal(SCENE.script.luaState, "sceneUpdate");
if(lua_isfunction(SCENE.script.luaState, -1)) {
if(lua_pcall(SCENE.script.luaState, 0, 0, 0) != LUA_OK) {
errorThrow(
"Failed to call sceneUpdate function in script: %s\n",
lua_tostring(SCENE.script.luaState, -1)
);
}
}
errorOk(); errorOk();
} }
@@ -42,7 +64,6 @@ errorret_t sceneRender(void) {
COMPONENT_TYPE_CAMERA, camEnts, camComps COMPONENT_TYPE_CAMERA, camEnts, camComps
); );
// Prep Matricies // Prep Matricies
mat4 view, proj, model; mat4 view, proj, model;
@@ -142,10 +163,85 @@ errorret_t sceneRender(void) {
errorOk(); errorOk();
} }
errorret_t sceneSet(const char_t *script) { errorret_t sceneSetImmediate(const char_t *script) {
// Update the next scene name (shouldn't really happen but its for safety).
if(script != SCENE.sceneNext) {
stringCopy(
SCENE.sceneNext,
script == NULL ? "" : script,
ASSET_FILE_PATH_MAX
);
}
// If there's currently a scene active, dispose of it first.
if(SCENE.scriptActive) {
assertNotNull(SCENE.script.luaState, "Script context null?");
// Call sceneDispose function
lua_getglobal(SCENE.script.luaState, "sceneDispose");
if(lua_isfunction(SCENE.script.luaState, -1)) {
if(lua_pcall(SCENE.script.luaState, 0, 0, 0) != LUA_OK) {
errorThrow(
"Failed to call sceneDispose function in script: %s\n",
lua_tostring(SCENE.script.luaState, -1)
);
}
}
// Scenes should ideally clean themselves up, this is just a warning because
// you can technically move entities between scenes, but it's messy.
for(entityid_t i = 0; i < ENTITY_COUNT_MAX; i++) {
if(ENTITY_MANAGER.entities[i].state & ENTITY_STATE_ACTIVE) {
consolePrint(
"Entity %d is active after scene dispose\n", i
);
}
}
// Unload script context.
scriptContextDispose(&SCENE.script);
SCENE.scriptActive = false;
}
// At this point the existing scene is unloaded, update the current scene.
stringCopy(
SCENE.sceneCurrent,
script == NULL ? "" : script,
ASSET_FILE_PATH_MAX
);
// If we have a new scene, execute it.
if(script != NULL) {
errorChain(scriptContextInit(&SCENE.script));
SCENE.scriptActive = true;
errorChain(scriptContextExecFile(&SCENE.script, script));
// Call the init function.
lua_getglobal(SCENE.script.luaState, "sceneInit");
if(lua_isfunction(SCENE.script.luaState, -1)) {
if(lua_pcall(SCENE.script.luaState, 0, 0, 0) != LUA_OK) {
errorThrow(
"Failed to call sceneInit function in script: %s\n",
lua_tostring(SCENE.script.luaState, -1)
);
}
}
}
errorOk(); errorOk();
} }
void sceneDispose(void) { void sceneSet(const char_t *script) {
// Tell the scene that next update it needs to change scenes. This will always
// occur on the NEXT frame.
stringCopy(
SCENE.sceneNext,
script == NULL ? "" : script,
ASSET_FILE_PATH_MAX
);
}
errorret_t sceneDispose(void) {
errorChain(sceneSetImmediate(NULL));
errorOk();
} }
+17 -4
View File
@@ -6,10 +6,14 @@
*/ */
#pragma once #pragma once
#include "error/error.h" #include "script/scriptcontext.h"
#include "asset/assetfile.h"
typedef struct { typedef struct {
void *nothing; scriptcontext_t script;
bool_t scriptActive;
char_t sceneCurrent[ASSET_FILE_PATH_MAX];
char_t sceneNext[ASSET_FILE_PATH_MAX];
} scene_t; } scene_t;
extern scene_t SCENE; extern scene_t SCENE;
@@ -35,14 +39,23 @@ errorret_t sceneUpdate(void);
*/ */
errorret_t sceneRender(void); errorret_t sceneRender(void);
/**
* Internal only method, immediately sets the scene. This will basically crash
* Lua if called from its tree.
*/
errorret_t sceneSetImmediate(const char_t *script);
/** /**
* Set the current scene by script name. * Set the current scene by script name.
* *
* @param script The script name of the scene to set. * @param script The script name of the scene to set.
* @return The error return value.
*/ */
errorret_t sceneSet(const char_t *script); void sceneSet(const char_t *script);
/** /**
* Dispose of the scene subsystem. * Dispose of the scene subsystem.
*
* @return The error return value.
*/ */
void sceneDispose(void); errorret_t sceneDispose(void);
+1 -6
View File
@@ -26,12 +26,7 @@ int moduleSceneSet(lua_State *L) {
const char_t *script = lua_tostring(L, 1); const char_t *script = lua_tostring(L, 1);
errorret_t err = sceneSet(script); sceneSet(script);
if(err.code != ERROR_OK) {
errorCatch(errorPrint(err));
luaL_error(L, "Failed to set scene");
return 0;
}
return 0; return 0;
} }
+1
View File
@@ -18,6 +18,7 @@ void stringCopy(char_t *dest, const char_t *src, const size_t destSize) {
assertNotNull(src, "src must not be NULL"); assertNotNull(src, "src must not be NULL");
assertTrue(destSize > 0, "destSize must be greater than 0"); assertTrue(destSize > 0, "destSize must be greater than 0");
assertStrLenMax(src, destSize, "src is too long"); assertStrLenMax(src, destSize, "src is too long");
assertTrue(dest != src, "Cannot copy string to itself.");
memoryCopy(dest, src, strlen(src) + 1); memoryCopy(dest, src, strlen(src) + 1);
} }
+2 -2
View File
@@ -21,7 +21,7 @@ errorret_t assetInitDolphin(void) {
if(!fatInitDefault()) errorThrow("Failed to initialize FAT filesystem."); if(!fatInitDefault()) errorThrow("Failed to initialize FAT filesystem.");
char_t **dolphinSearchPath = (char_t **)ASSET_DOLPHIN_PATHS; char_t **dolphinSearchPath = (char_t **)ASSET_DOLPHIN_PATHS;
char_t foundPath[FILENAME_MAX]; char_t foundPath[ASSET_FILE_PATH_MAX];
foundPath[0] = '\0'; foundPath[0] = '\0';
do { do {
// Try open dir // Try open dir
@@ -40,7 +40,7 @@ errorret_t assetInitDolphin(void) {
// Copy out filename // Copy out filename
snprintf( snprintf(
foundPath, foundPath,
FILENAME_MAX, ASSET_FILE_PATH_MAX,
"%s/%s", "%s/%s",
*dolphinSearchPath, *dolphinSearchPath,
ASSET_FILE_NAME ASSET_FILE_NAME
+1
View File
@@ -7,6 +7,7 @@
#pragma once #pragma once
#include "error/error.h" #include "error/error.h"
#include "asset/assetfile.h"
static const char_t *ASSET_DOLPHIN_PATHS[] = { static const char_t *ASSET_DOLPHIN_PATHS[] = {
"/", "/",
+6 -6
View File
@@ -14,12 +14,12 @@ errorret_t assetInitLinux(void) {
// Engine may have been provided the launch path // Engine may have been provided the launch path
if(ENGINE.argc > 0) { if(ENGINE.argc > 0) {
// Get the directory of the executable // Get the directory of the executable
char_t buffer[FILENAME_MAX]; char_t buffer[ASSET_FILE_PATH_MAX];
stringCopy(buffer, ENGINE.argv[0], FILENAME_MAX); stringCopy(buffer, ENGINE.argv[0], ASSET_FILE_PATH_MAX);
size_t len = strlen(buffer); size_t len = strlen(buffer);
// Normalize slashes // Normalize slashes
for(size_t i = 0; i < FILENAME_MAX; i++) { for(size_t i = 0; i < ASSET_FILE_PATH_MAX; i++) {
if(buffer[i] == '\0') break; if(buffer[i] == '\0') break;
if(buffer[i] == '\\') buffer[i] = '/'; if(buffer[i] == '\\') buffer[i] = '/';
} }
@@ -38,15 +38,15 @@ errorret_t assetInitLinux(void) {
// Did we find a slash? // Did we find a slash?
if(end != buffer) { if(end != buffer) {
// We found the directory, set as system path // We found the directory, set as system path
stringCopy(ASSET.platform.systemPath, buffer, FILENAME_MAX); stringCopy(ASSET.platform.systemPath, buffer, ASSET_FILE_PATH_MAX);
} }
} }
// Default system path, intended to be overridden by the platform // Default system path, intended to be overridden by the platform
stringCopy(ASSET.platform.systemPath, ".", FILENAME_MAX); stringCopy(ASSET.platform.systemPath, ".", ASSET_FILE_PATH_MAX);
// Open zip file // Open zip file
char_t searchPath[FILENAME_MAX]; char_t searchPath[ASSET_FILE_PATH_MAX];
const char_t **path = ASSET_LINUX_SEARCH_PATHS; const char_t **path = ASSET_LINUX_SEARCH_PATHS;
int32_t error; int32_t error;
do { do {
+2 -1
View File
@@ -7,6 +7,7 @@
#pragma once #pragma once
#include "error/error.h" #include "error/error.h"
#include "asset/assetfile.h"
static const char_t *ASSET_LINUX_SEARCH_PATHS[] = { static const char_t *ASSET_LINUX_SEARCH_PATHS[] = {
"%s/%s", "%s/%s",
@@ -19,7 +20,7 @@ static const char_t *ASSET_LINUX_SEARCH_PATHS[] = {
}; };
typedef struct { typedef struct {
char_t systemPath[FILENAME_MAX]; char_t systemPath[ASSET_FILE_PATH_MAX];
} assetlinux_t; } assetlinux_t;
/** /**
+1 -1
View File
@@ -12,7 +12,7 @@
errorret_t assetInitPBP(const char_t *pbpPath) { errorret_t assetInitPBP(const char_t *pbpPath) {
assertNotNull(pbpPath, "PBP path cannot be null."); assertNotNull(pbpPath, "PBP path cannot be null.");
assertStrLenMin(pbpPath, 1, "PBP path cannot be empty."); assertStrLenMin(pbpPath, 1, "PBP path cannot be empty.");
assertStrLenMax(pbpPath, FILENAME_MAX, "PBP path is too long."); assertStrLenMax(pbpPath, ASSET_FILE_PATH_MAX, "PBP path is too long.");
ASSET.platform.pbpFile = fopen(pbpPath, "rb"); ASSET.platform.pbpFile = fopen(pbpPath, "rb");
if(ASSET.platform.pbpFile == NULL) { if(ASSET.platform.pbpFile == NULL) {
+1
View File
@@ -7,6 +7,7 @@
#pragma once #pragma once
#include "error/error.h" #include "error/error.h"
#include "asset/assetfile.h"
#define ASSET_PBP_SIGNATURE_SIZE 4 #define ASSET_PBP_SIGNATURE_SIZE 4
#define ASSET_PBP_SIGNATURE "\0PBP" #define ASSET_PBP_SIGNATURE "\0PBP"