diff --git a/src/dusk/engine/engine.c b/src/dusk/engine/engine.c index b9988487..32649669 100644 --- a/src/dusk/engine/engine.c +++ b/src/dusk/engine/engine.c @@ -26,6 +26,8 @@ #include "item/backpack.h" #include "save/save.h" +#include "scene/initial/initialscene.h" + engine_t ENGINE; errorret_t engineInit(const int32_t argc, const char_t **argv) { @@ -55,7 +57,7 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) { /* Run the init script. */ consolePrint("Engine initialized"); - // errorChain(scriptManagerExecFile("init.js", NULL)); + sceneSet(SCENE_TYPE_INITIAL); errorOk(); } diff --git a/src/dusk/scene/initial/initialscene.c b/src/dusk/scene/initial/initialscene.c index 2d649bd7..2d027570 100644 --- a/src/dusk/scene/initial/initialscene.c +++ b/src/dusk/scene/initial/initialscene.c @@ -5,4 +5,21 @@ * https://opensource.org/licenses/MIT */ -#include "initialscene.h" \ No newline at end of file +#include "initialscene.h" +#include "console/console.h" + +void initialSceneInit(void) { + consolePrint("Initial scene initialized"); +} + +errorret_t initialSceneUpdate(void) { + errorOk(); +} + +errorret_t initialSceneDraw(void) { + errorOk(); +} + +void initialSceneDispose(void) { + +} \ No newline at end of file diff --git a/src/dusk/scene/initial/initialscene.h b/src/dusk/scene/initial/initialscene.h index 20902e35..af29ae9b 100644 --- a/src/dusk/scene/initial/initialscene.h +++ b/src/dusk/scene/initial/initialscene.h @@ -6,16 +6,32 @@ */ #pragma once -#include "scene/scene.h" +#include "error/error.h" +typedef struct { + void *nothing; +} initialscene_t; + +/** + * Initial scene initializer. + */ void initialSceneInit(void); -errorret_t initialSceneUpdate(void); -errorret_t initialSceneDraw(void); -void initialSceneDispose(void); -static const scene_t INITIAL_SCENE = { - .init = initialSceneInit, - .update = initialSceneUpdate, - .draw = initialSceneDraw, - .dispose = initialSceneDispose -}; \ No newline at end of file +/** + * Initial scene updater. + * + * @return Any error state that happened. + */ +errorret_t initialSceneUpdate(void); + +/** + * Initial scene drawer. + * + * @return Any error state that happened. + */ +errorret_t initialSceneDraw(void); + +/** + * Initial scene disposer. + */ +void initialSceneDispose(void); \ No newline at end of file diff --git a/src/dusk/scene/scene.c b/src/dusk/scene/scene.c index 3224c4b0..c6f2257c 100644 --- a/src/dusk/scene/scene.c +++ b/src/dusk/scene/scene.c @@ -18,15 +18,18 @@ #include "util/string.h" #include "ui/ui.h" -scene_t SCENE_CURRENT; -scene_t SCENE_NEXT; -bool_t SCENE_NEXT_SET; +scenefuncs_t SCENE_FUNCTIONS[SCENE_TYPE_COUNT] = { + { 0 }, + #define X(structName, varName, varNameUpper, initFunc, updateFunc, renderFunc, disposeFunc) \ + { initFunc, updateFunc, renderFunc, disposeFunc }, + #include "scene/scenelist.h" + #undef X +}; + +scene_t SCENE; errorret_t sceneInit(void) { - memoryZero(&SCENE_CURRENT, sizeof(scene_t)); - memoryZero(&SCENE_NEXT, sizeof(scene_t)); - SCENE_NEXT_SET = false; - + memoryZero(&SCENE, sizeof(scene_t)); errorOk(); } @@ -37,14 +40,22 @@ errorret_t sceneUpdate(void) { } #endif - if(SCENE_NEXT_SET) { - if(SCENE_CURRENT.dispose) SCENE_CURRENT.dispose(); - SCENE_CURRENT = SCENE_NEXT; - SCENE_NEXT_SET = false; - if(SCENE_CURRENT.init) SCENE_CURRENT.init(); + // Dispose current scene. + if(SCENE.type != SCENE_TYPE_NULL) { + if(SCENE_FUNCTIONS[SCENE.type].dispose) { + SCENE_FUNCTIONS[SCENE.type].dispose(); + } } - if(SCENE_CURRENT.update != NULL) errorChain(SCENE_CURRENT.update()); + // Init new scene + SCENE.type = SCENE.nextType; + SCENE.nextType = SCENE_TYPE_NULL; + + if(SCENE.type != SCENE_TYPE_NULL) { + if(SCENE_FUNCTIONS[SCENE.type].init) { + SCENE_FUNCTIONS[SCENE.type].init(); + } + } errorOk(); } @@ -52,131 +63,61 @@ errorret_t sceneUpdate(void) { dusktimeepoch_t LAST; errorret_t sceneRender(void) { - entityid_t camEnts[ENTITY_COUNT_MAX]; - componentid_t camComps[ENTITY_COUNT_MAX]; - entityid_t camCount = componentGetEntitiesWithComponent( - COMPONENT_TYPE_CAMERA, camEnts, camComps - ); - - shader_t *shaderCurrent = NULL; - mat4 view, proj, model; - - errorChain(displaySetState((displaystate_t){ - // .flags = DISPLAY_STATE_FLAG_CULL | DISPLAY_STATE_FLAG_DEPTH_TEST - .flags = 0 - })); - - // For each camera - for(entityid_t camIndex = 0; camIndex < camCount; camIndex++) { - entityid_t camEnt = camEnts[camIndex]; - componentid_t camComp = camComps[camIndex]; - componentid_t camPos = entityGetComponent(camEnt, COMPONENT_TYPE_POSITION); - if(camPos == COMPONENT_ID_INVALID) { - logError("Camera entity without entity position found\n"); - continue; - } - - entityCameraGetProjection(camEnt, camComp, proj); - entityPositionGetTransform(camEnt, camPos, view); - - for(entityid_t entityId = 0; entityId < ENTITY_COUNT_MAX; entityId++) { - componentid_t renderComp = entityGetComponent( - entityId, COMPONENT_TYPE_RENDERABLE - ); - if(renderComp == COMPONENT_ID_INVALID) continue; - - entityrenderable_t *r = componentGetData( - entityId, renderComp, COMPONENT_TYPE_RENDERABLE - ); - - componentid_t posComp = entityGetComponent( - entityId, COMPONENT_TYPE_POSITION - ); - if(posComp == COMPONENT_ID_INVALID) { - glm_mat4_identity(model); - } else { - entityPositionGetTransform(entityId, posComp, model); - } - - switch(r->type) { - case ENTITY_RENDERABLE_TYPE_CALLBACK: { - if(!r->callback) break; - errorChain(r->callback( - entityId, renderComp, view, proj, model, r->user - )); - break; - } - - case ENTITY_RENDERABLE_TYPE_MATERIAL: { - shader_t *shader = r->shader; - if(!shader) break; - if(!r->mesh) break; - if(shaderCurrent != shader) { - shaderCurrent = shader; - errorChain(shaderBind(shaderCurrent)); - errorChain(shaderSetMatrix(shader, SHADER_UNLIT_PROJECTION, proj)); - errorChain(shaderSetMatrix(shader, SHADER_UNLIT_VIEW, view)); - } - errorChain(shaderSetMatrix(shader, SHADER_UNLIT_MODEL, model)); - errorChain(shaderSetMaterial(shader, &r->material)); - errorChain(meshDraw(r->mesh, 0, -1)); - break; - } - - case ENTITY_RENDERABLE_TYPE_SPRITEBATCH: { - if(r->spritebatch.spriteCount == 0) break; - shader_t *shader = r->shader; - if(!shader) break; - if(shaderCurrent != shader) { - shaderCurrent = shader; - errorChain(shaderBind(shaderCurrent)); - errorChain(shaderSetMatrix(shader, SHADER_UNLIT_PROJECTION, proj)); - errorChain(shaderSetMatrix(shader, SHADER_UNLIT_VIEW, view)); - } - errorChain(shaderSetMatrix(shader, SHADER_UNLIT_MODEL, model)); - for(uint16_t si = 0; si < r->spritebatch.spriteCount; si++) { - errorChain(spriteBatchBufferSprite(&r->spritebatch.sprites[si])); - } - errorChain(spriteBatchFlush()); - break; - } - } - } - } - - // UI Rendering + mat4 view, proj; glm_ortho( 0.0f, SCREEN.width, SCREEN.height, 0.0f, 0.1f, 100.0f, proj ); - glm_lookat( - (vec3){ 0.0f, 0.0f, 1.0f }, - (vec3){ 0.0f, 0.0f, 0.0f }, - (vec3){ 0.0f, 1.0f, 0.0f }, - view - ); - glm_mat4_identity(model); errorChain(shaderBind(&SHADER_UNLIT)); errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_PROJECTION, proj)); - errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_VIEW, view)); - errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_MODEL, model)); - errorChain(displaySetState((displaystate_t){ - .flags = DISPLAY_STATE_FLAG_BLEND - })); - errorChain(uiRender()); + if(SCENE.type != SCENE_TYPE_NULL && SCENE_FUNCTIONS[SCENE.type].render) { + glm_mat4_identity(view); + errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_VIEW, view)); + errorChain(SCENE_FUNCTIONS[SCENE.type].render()); + } + + // UI Rendering + { + glm_lookat( + (vec3){ 0.0f, 0.0f, 1.0f }, + (vec3){ 0.0f, 0.0f, 0.0f }, + (vec3){ 0.0f, 1.0f, 0.0f }, + view + ); + errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_VIEW, view)); + + mat4 model; + glm_mat4_identity(model); + errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_MODEL, model)); + + errorChain(displaySetState((displaystate_t){ + .flags = DISPLAY_STATE_FLAG_BLEND + })); + errorChain(uiRender()); + } errorOk(); } -void sceneSet(const scene_t scene) { - SCENE_NEXT = scene; - SCENE_NEXT_SET = true; +void sceneSet(const scenetype_t type) { + assertTrue( + type > SCENE_TYPE_NULL && type < SCENE_TYPE_COUNT, + "Invalid scene type" + ); + SCENE.nextType = type; } errorret_t sceneDispose(void) { + if(SCENE.type != SCENE_TYPE_NULL) { + if(SCENE_FUNCTIONS[SCENE.type].dispose) { + SCENE_FUNCTIONS[SCENE.type].dispose(); + } + } + SCENE.type = SCENE_TYPE_NULL; + SCENE.nextType = SCENE_TYPE_NULL; errorOk(); } diff --git a/src/dusk/scene/scene.h b/src/dusk/scene/scene.h index f4118d02..fb47233d 100644 --- a/src/dusk/scene/scene.h +++ b/src/dusk/scene/scene.h @@ -7,18 +7,41 @@ #pragma once #include "asset/assetfile.h" +#include "scene/initial/initialscene.h" #define SCENE_EVENT_UPDATE_MAX 16 +typedef enum { + SCENE_TYPE_NULL, + #define X(structName, varName, varNameUpper, initFunc, updateFunc, renderFunc, disposeFunc) \ + SCENE_TYPE_##varNameUpper, + #include "scene/scenelist.h" + #undef X + SCENE_TYPE_COUNT +} scenetype_t; + +typedef union { + #define X(structName, varName, varNameUpper, initFunc, updateFunc, renderFunc, disposeFunc) \ + structName varName; + #include "scene/scenelist.h" + #undef X +} scenedata_t; + typedef struct { void (*init)(void); errorret_t (*update)(void); + errorret_t (*render)(void); void (*dispose)(void); +} scenefuncs_t; + +typedef struct { + scenedata_t data; + scenetype_t type; + scenetype_t nextType; } scene_t; -extern scene_t SCENE_CURRENT; -extern scene_t SCENE_NEXT; -extern bool_t SCENE_NEXT_SET; +extern scenefuncs_t SCENE_FUNCTIONS[SCENE_TYPE_COUNT]; +extern scene_t SCENE; /** * Initializes the scene manager. @@ -44,9 +67,9 @@ errorret_t sceneRender(void); /** * Requests a scene change on the next safe opportunity. * - * @param scene Which scene to set. + * @param type The type of scene to change to. */ -void sceneSet(const scene_t scene); +void sceneSet(const scenetype_t type); /** * Disposes of the current scene. diff --git a/src/dusk/scene/scenelist.h b/src/dusk/scene/scenelist.h new file mode 100644 index 00000000..5d47f3c9 --- /dev/null +++ b/src/dusk/scene/scenelist.h @@ -0,0 +1,13 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#ifndef X + #define X(structName, varName, varNameUpper, initFunc, updateFunc, renderFunc, disposeFunc) \ + ((void)) +#endif + +X(initialscene_t, initial, INITIAL, initialSceneInit, initialSceneUpdate, initialSceneDraw, initialSceneDispose) \ No newline at end of file diff --git a/src/dusk/ui/uitextbox.c b/src/dusk/ui/uitextbox.c index a7e88b85..94f29b92 100644 --- a/src/dusk/ui/uitextbox.c +++ b/src/dusk/ui/uitextbox.c @@ -207,6 +207,8 @@ void uiTextboxNextPage(void) { } errorret_t uiTextboxDraw(void) { + if(UI_TEXTBOX.lineCount == 0 || UI_TEXTBOX.text[0] == '\0') errorOk(); + errorChain(uiFrameDraw( &UI_TEXTBOX.frame, UI_TEXTBOX.x, UI_TEXTBOX.y, @@ -214,8 +216,6 @@ errorret_t uiTextboxDraw(void) { )); errorChain(spriteBatchFlush()); - if(UI_TEXTBOX.lineCount == 0 || UI_TEXTBOX.text[0] == '\0') errorOk(); - errorChain(shaderSetTexture( &SHADER_UNLIT, SHADER_UNLIT_TEXTURE, &UI_TEXTBOX.font->texture ));