Scene loading example
This commit is contained in:
@@ -56,7 +56,7 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) {
|
|||||||
|
|
||||||
/* Run the init script. */
|
/* Run the init script. */
|
||||||
consolePrint("Engine initialized");
|
consolePrint("Engine initialized");
|
||||||
sceneSet(SCENE_TYPE_OVERWORLD);
|
sceneSet(SCENE_TYPE_INITIAL);
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,27 @@
|
|||||||
|
|
||||||
#include "initialscene.h"
|
#include "initialscene.h"
|
||||||
#include "console/console.h"
|
#include "console/console.h"
|
||||||
|
#include "scene/scene.h"
|
||||||
|
#include "time/time.h"
|
||||||
|
#include "ui/uiloading.h"
|
||||||
|
|
||||||
void initialSceneInit(void) {
|
void initialSceneInit(void) {
|
||||||
consolePrint("Initial scene initialized");
|
consolePrint("Initial scene initialized");
|
||||||
|
SCENE.data.initial.timer = 0.0f;
|
||||||
|
SCENE.data.initial.hiding = false;
|
||||||
|
uiLoadingShow(NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
errorret_t initialSceneUpdate(void) {
|
errorret_t initialSceneUpdate(void) {
|
||||||
|
initialscene_t *scene = &SCENE.data.initial;
|
||||||
|
if(scene->hiding) errorOk();
|
||||||
|
|
||||||
|
scene->timer += TIME.delta;
|
||||||
|
if(scene->timer >= INITIAL_SCENE_WAIT) {
|
||||||
|
scene->hiding = true;
|
||||||
|
uiLoadingHide(NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "error/error.h"
|
#include "error/error.h"
|
||||||
|
|
||||||
|
#define INITIAL_SCENE_WAIT 2.0f
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *nothing;
|
float_t timer;
|
||||||
|
bool_t hiding;
|
||||||
} initialscene_t;
|
} initialscene_t;
|
||||||
|
|
||||||
void initialSceneInit(void);
|
void initialSceneInit(void);
|
||||||
|
|||||||
@@ -11,5 +11,6 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
|||||||
uielement.c
|
uielement.c
|
||||||
uiframe.c
|
uiframe.c
|
||||||
uifullbox.c
|
uifullbox.c
|
||||||
|
uiloading.c
|
||||||
uitextbox.c
|
uitextbox.c
|
||||||
)
|
)
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "display/screen/screen.h"
|
#include "display/screen/screen.h"
|
||||||
#include "ui/uielement.h"
|
#include "ui/uielement.h"
|
||||||
#include "ui/uifullbox.h"
|
#include "ui/uifullbox.h"
|
||||||
|
#include "ui/uiloading.h"
|
||||||
#include "time/time.h"
|
#include "time/time.h"
|
||||||
#include "log/log.h"
|
#include "log/log.h"
|
||||||
|
|
||||||
@@ -19,6 +20,7 @@ ui_t UI;
|
|||||||
|
|
||||||
errorret_t uiInit(void) {
|
errorret_t uiInit(void) {
|
||||||
memoryZero(&UI, sizeof(ui_t));
|
memoryZero(&UI, sizeof(ui_t));
|
||||||
|
uiLoadingInit();
|
||||||
|
|
||||||
uielement_t *element = &UI_ELEMENTS[0];
|
uielement_t *element = &UI_ELEMENTS[0];
|
||||||
while(element->type != UI_ELEMENT_TYPE_NULL) {
|
while(element->type != UI_ELEMENT_TYPE_NULL) {
|
||||||
@@ -32,6 +34,7 @@ errorret_t uiInit(void) {
|
|||||||
void uiUpdate(void) {
|
void uiUpdate(void) {
|
||||||
uiFullboxUpdate(&UI_FULLBOX_UNDER, TIME.delta);
|
uiFullboxUpdate(&UI_FULLBOX_UNDER, TIME.delta);
|
||||||
uiFullboxUpdate(&UI_FULLBOX_OVER, TIME.delta);
|
uiFullboxUpdate(&UI_FULLBOX_OVER, TIME.delta);
|
||||||
|
uiLoadingUpdate(TIME.delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
errorret_t uiRender(void) {
|
errorret_t uiRender(void) {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "engine/engine.h"
|
#include "engine/engine.h"
|
||||||
#include "ui/uitextbox.h"
|
#include "ui/uitextbox.h"
|
||||||
#include "ui/uifullbox.h"
|
#include "ui/uifullbox.h"
|
||||||
|
#include "ui/uiloading.h"
|
||||||
|
|
||||||
uielement_t UI_ELEMENTS[] = {
|
uielement_t UI_ELEMENTS[] = {
|
||||||
// Fullbox under: above scene, below system UI.
|
// Fullbox under: above scene, below system UI.
|
||||||
@@ -20,10 +21,12 @@ uielement_t UI_ELEMENTS[] = {
|
|||||||
// { .type = UI_ELEMENT_TYPE_SCRIPT, .script = { .script = "ui/test.js" } },
|
// { .type = UI_ELEMENT_TYPE_SCRIPT, .script = { .script = "ui/test.js" } },
|
||||||
|
|
||||||
{ .type = UI_ELEMENT_TYPE_NATIVE, .draw = consoleDraw },
|
{ .type = UI_ELEMENT_TYPE_NATIVE, .draw = consoleDraw },
|
||||||
{ .type = UI_ELEMENT_TYPE_NATIVE, .draw = uiFPSDraw },
|
|
||||||
{ .type = UI_ELEMENT_TYPE_NATIVE, .draw = uiTextboxDraw },
|
{ .type = UI_ELEMENT_TYPE_NATIVE, .draw = uiTextboxDraw },
|
||||||
// Fullbox over: above absolutely everything.
|
// Fullbox over: above absolutely everything.
|
||||||
{ .type = UI_ELEMENT_TYPE_NATIVE, .draw = uiFullboxOverDraw },
|
{ .type = UI_ELEMENT_TYPE_NATIVE, .draw = uiFullboxOverDraw },
|
||||||
|
// These render above the fullbox overlay.
|
||||||
|
{ .type = UI_ELEMENT_TYPE_NATIVE, .draw = uiFPSDraw },
|
||||||
|
{ .type = UI_ELEMENT_TYPE_NATIVE, .draw = uiLoadingDraw },
|
||||||
|
|
||||||
{ .type = UI_ELEMENT_TYPE_NULL },
|
{ .type = UI_ELEMENT_TYPE_NULL },
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -52,20 +52,20 @@ errorret_t uiFullboxDraw(uifullbox_t *fullbox) {
|
|||||||
color_t color = uiFullboxGetColor(fullbox);
|
color_t color = uiFullboxGetColor(fullbox);
|
||||||
if(color.a == 0) errorOk();
|
if(color.a == 0) errorOk();
|
||||||
|
|
||||||
errorChain(shaderSetTexture(&SHADER_UNLIT, SHADER_UNLIT_TEXTURE, &TEXTURE_WHITE));
|
spritebatchsprite_t sprite = {
|
||||||
#if MESH_ENABLE_COLOR
|
.min = { 0.0f, 0.0f, 0.0f },
|
||||||
#else
|
.max = { (float_t)SCREEN.width, (float_t)SCREEN.height, 0.0f },
|
||||||
errorChain(shaderSetColor(&SHADER_UNLIT, SHADER_UNLIT_COLOR, color));
|
.uvMin = { 0.0f, 0.0f },
|
||||||
#endif
|
.uvMax = { 1.0f, 1.0f }
|
||||||
|
};
|
||||||
spritebatchsprite_t sprite;
|
|
||||||
shadermaterial_t material = {
|
shadermaterial_t material = {
|
||||||
.unlit = {
|
.unlit = {
|
||||||
.color = color,
|
.color = color,
|
||||||
.texture = &TEXTURE_WHITE
|
.texture = &TEXTURE_WHITE
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return spriteBatchBuffer(&sprite, 1, &SHADER_UNLIT, material);
|
errorChain(spriteBatchBuffer(&sprite, 1, &SHADER_UNLIT, material));
|
||||||
|
return spriteBatchFlush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void uiFullboxTransition(
|
void uiFullboxTransition(
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uiloading.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "util/memory.h"
|
||||||
|
#include "display/text/text.h"
|
||||||
|
#include "display/screen/screen.h"
|
||||||
|
#include "display/spritebatch/spritebatch.h"
|
||||||
|
#include "ui/uifullbox.h"
|
||||||
|
|
||||||
|
#define UI_LOADING_TEXT "loading"
|
||||||
|
|
||||||
|
uiloading_t UI_LOADING;
|
||||||
|
|
||||||
|
void uiLoadingInit(void) {
|
||||||
|
memoryZero(&UI_LOADING, sizeof(uiloading_t));
|
||||||
|
eventInit(&UI_LOADING.onTransitionEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uiLoadingUpdate(float_t delta) {
|
||||||
|
if(UI_LOADING.duration <= 0.0f || UI_LOADING.time >= UI_LOADING.duration) return;
|
||||||
|
UI_LOADING.time += delta;
|
||||||
|
if(UI_LOADING.time >= UI_LOADING.duration) {
|
||||||
|
UI_LOADING.time = UI_LOADING.duration;
|
||||||
|
eventInvoke(&UI_LOADING.onTransitionEnd, &UI_LOADING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t uiLoadingDraw(void) {
|
||||||
|
float_t alpha;
|
||||||
|
if(UI_LOADING.duration <= 0.0f || UI_LOADING.time >= UI_LOADING.duration) {
|
||||||
|
alpha = UI_LOADING.toAlpha;
|
||||||
|
} else {
|
||||||
|
float_t t = UI_LOADING.time / UI_LOADING.duration;
|
||||||
|
alpha = UI_LOADING.fromAlpha + (UI_LOADING.toAlpha - UI_LOADING.fromAlpha) * t;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(alpha <= 0.0f) errorOk();
|
||||||
|
|
||||||
|
int32_t textW, textH;
|
||||||
|
textMeasure(UI_LOADING_TEXT, &FONT_DEFAULT, &textW, &textH);
|
||||||
|
|
||||||
|
float_t x = (float_t)SCREEN.width - (float_t)textW - UI_LOADING_MARGIN;
|
||||||
|
float_t y = (float_t)SCREEN.height - (float_t)textH - UI_LOADING_MARGIN;
|
||||||
|
|
||||||
|
color_t color = COLOR_WHITE;
|
||||||
|
color.a = (uint8_t)(alpha * 255.0f);
|
||||||
|
|
||||||
|
errorChain(textDraw(x, y, UI_LOADING_TEXT, color, &FONT_DEFAULT));
|
||||||
|
return spriteBatchFlush();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void uiLoadingTransition(
|
||||||
|
const float_t from,
|
||||||
|
const float_t to,
|
||||||
|
const eventcallback_t callback,
|
||||||
|
void *user
|
||||||
|
) {
|
||||||
|
UI_LOADING.fromAlpha = from;
|
||||||
|
UI_LOADING.toAlpha = to;
|
||||||
|
UI_LOADING.duration = UI_LOADING_FADE_DURATION;
|
||||||
|
UI_LOADING.time = 0.0f;
|
||||||
|
eventInit(&UI_LOADING.onTransitionEnd);
|
||||||
|
if(callback) eventSubscribe(&UI_LOADING.onTransitionEnd, callback, user);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uiLoadingShow(eventcallback_t callback, void *user) {
|
||||||
|
uiLoadingTransition(0.0f, 1.0f, callback, user);
|
||||||
|
uiFullboxTransition(
|
||||||
|
&UI_FULLBOX_OVER,
|
||||||
|
COLOR_TRANSPARENT_BLACK,
|
||||||
|
COLOR_BLACK,
|
||||||
|
UI_LOADING_FADE_DURATION,
|
||||||
|
EASING_LINEAR
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uiLoadingHide(eventcallback_t callback, void *user) {
|
||||||
|
uiLoadingTransition(1.0f, 0.0f, callback, user);
|
||||||
|
uiFullboxTransition(
|
||||||
|
&UI_FULLBOX_OVER,
|
||||||
|
COLOR_BLACK,
|
||||||
|
COLOR_TRANSPARENT_BLACK,
|
||||||
|
UI_LOADING_FADE_DURATION,
|
||||||
|
EASING_LINEAR
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "error/error.h"
|
||||||
|
#include "event/event.h"
|
||||||
|
|
||||||
|
#define UI_LOADING_FADE_DURATION 0.5f
|
||||||
|
#define UI_LOADING_MARGIN 8.0f
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float_t fromAlpha;
|
||||||
|
float_t toAlpha;
|
||||||
|
float_t duration;
|
||||||
|
float_t time;
|
||||||
|
event_t onTransitionEnd;
|
||||||
|
} uiloading_t;
|
||||||
|
|
||||||
|
extern uiloading_t UI_LOADING;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the loading indicator.
|
||||||
|
*/
|
||||||
|
void uiLoadingInit(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Advances the loading indicator fade transition. Fires onTransitionEnd once
|
||||||
|
* when the transition completes.
|
||||||
|
*
|
||||||
|
* @param delta Seconds elapsed since last update.
|
||||||
|
*/
|
||||||
|
void uiLoadingUpdate(float_t delta);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws the loading indicator. No-op when fully transparent.
|
||||||
|
*
|
||||||
|
* @return Error state.
|
||||||
|
*/
|
||||||
|
errorret_t uiLoadingDraw(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fades the loading indicator in. Invokes callback when fully visible.
|
||||||
|
*
|
||||||
|
* @param callback Called when the fade-in completes. May be NULL.
|
||||||
|
* @param user Forwarded to the callback unchanged.
|
||||||
|
*/
|
||||||
|
void uiLoadingShow(eventcallback_t callback, void *user);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fades the loading indicator out. Invokes callback when fully hidden.
|
||||||
|
*
|
||||||
|
* @param callback Called when the fade-out completes. May be NULL.
|
||||||
|
* @param user Forwarded to the callback unchanged.
|
||||||
|
*/
|
||||||
|
void uiLoadingHide(eventcallback_t callback, void *user);
|
||||||
Reference in New Issue
Block a user