Add cutsceneSystemLoad, a debug cutscene overlay, and NULL-safe fatal error
cutsceneSystemLoad(file) centralizes the lock/assetRequireLoaded/start sequence previously duplicated in sceneInitialInit, and falls back to the fatal error overlay instead of asserting when the asset fails to load. uiFatalErrorOpen now accepts a NULL message, showing a generic "contact support" message for callers with no specific error text. Also adds a ui/debug/uicutscene overlay showing the running cutscene's item count and current item type, and wires main_menu's post-save-picker flow through cutsceneSystemLoad. Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
@@ -58,13 +58,6 @@ errorret_t assetCutsceneParseItem(
|
|||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
// First pass over the parsed "items" array: sums the exact pool bytes
|
|
||||||
// ENTITY_WALK_TO/MAP_AREA_WAIT items will need, so the real parse pass can
|
|
||||||
// allocate the pool exactly once up front rather than growing/moving it
|
|
||||||
// (which would dangle pointers already written into earlier items). Any
|
|
||||||
// item with an invalid/missing type is silently skipped here - the real
|
|
||||||
// error for that gets thrown later during the actual per-item parse pass
|
|
||||||
// in assetCutsceneParseItem, this first pass is pool-sizing only.
|
|
||||||
size_t assetCutsceneComputePoolSize(yyjson_val *itemsArr) {
|
size_t assetCutsceneComputePoolSize(yyjson_val *itemsArr) {
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
yyjson_arr_iter iter = yyjson_arr_iter_with(itemsArr);
|
yyjson_arr_iter iter = yyjson_arr_iter_with(itemsArr);
|
||||||
|
|||||||
@@ -12,9 +12,6 @@
|
|||||||
#include "rpg/cutscene/item/json/cutscenejsonpool.h"
|
#include "rpg/cutscene/item/json/cutscenejsonpool.h"
|
||||||
#include "yyjson.h"
|
#include "yyjson.h"
|
||||||
|
|
||||||
// Above this, something is almost certainly wrong (or malicious) rather
|
|
||||||
// than a legitimately large cutscene - matches ASSET_JSON_FILE_SIZE_MAX's
|
|
||||||
// role in assetjsonloader.h.
|
|
||||||
#define ASSET_CUTSCENE_FILE_SIZE_MAX (1024 * 64)
|
#define ASSET_CUTSCENE_FILE_SIZE_MAX (1024 * 64)
|
||||||
|
|
||||||
typedef struct assetloading_s assetloading_t;
|
typedef struct assetloading_s assetloading_t;
|
||||||
@@ -37,18 +34,8 @@ typedef struct {
|
|||||||
size_t size;
|
size_t size;
|
||||||
} assetcutsceneloaderloading_t;
|
} assetcutsceneloaderloading_t;
|
||||||
|
|
||||||
// Runtime-loaded cutscene, parsed directly from the cutscene's authored
|
|
||||||
// JSONC (no separate compiled binary format/build step - see
|
|
||||||
// assetCutsceneLoaderSync). `doc` is kept alive for the entry's whole
|
|
||||||
// lifetime rather than freed after parsing: every pool-string-shaped
|
|
||||||
// field (item names, markers, modal option text, ...) points straight at
|
|
||||||
// yyjson's own internally-owned string storage instead of being copied
|
|
||||||
// out, so freeing doc early would dangle every one of those pointers.
|
|
||||||
// `pool` only exists for the handful of fields that need a packed native
|
|
||||||
// array yyjson can't hand back a pointer into directly - entityWalkTo's
|
|
||||||
// worldpos_t positions and mapAreaWait's uint8_t areaIds.
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
cutscene_t cutscene; // .items points at the items array below
|
cutscene_t cutscene;
|
||||||
cutsceneitem_t *items;
|
cutsceneitem_t *items;
|
||||||
uint8_t *pool;
|
uint8_t *pool;
|
||||||
yyjson_doc *doc;
|
yyjson_doc *doc;
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ console_t CONSOLE;
|
|||||||
|
|
||||||
void consoleInit(void) {
|
void consoleInit(void) {
|
||||||
memoryZero(&CONSOLE, sizeof(console_t));
|
memoryZero(&CONSOLE, sizeof(console_t));
|
||||||
// CONSOLE.visible = false;
|
CONSOLE.visible = false;
|
||||||
CONSOLE.visible = true;
|
// CONSOLE.visible = true;
|
||||||
threadMutexInit(&CONSOLE.printMutex);
|
threadMutexInit(&CONSOLE.printMutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
|
#include "asset/asset.h"
|
||||||
|
#include "ui/overlay/uifatalerror.h"
|
||||||
|
|
||||||
cutscenesystem_t CUTSCENE_SYSTEM;
|
cutscenesystem_t CUTSCENE_SYSTEM;
|
||||||
|
|
||||||
@@ -61,6 +63,21 @@ void cutsceneSystemStartCutsceneAndGoToMarker(
|
|||||||
cutsceneGoTo(marker);
|
cutsceneGoTo(marker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cutsceneSystemLoad(const char_t *file) {
|
||||||
|
char_t path[ASSET_FILE_NAME_MAX];
|
||||||
|
stringFormat(path, sizeof(path), "cutscenes/%s", file);
|
||||||
|
|
||||||
|
assetentry_t *entry = assetLock(path, ASSET_LOADER_TYPE_CUTSCENE, NULL);
|
||||||
|
errorret_t result = assetRequireLoaded(entry);
|
||||||
|
if(errorIsNotOk(result)) {
|
||||||
|
errorCatch(errorPrint(result));
|
||||||
|
uiFatalErrorOpen(NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cutsceneSystemStartCutscene(&entry->data.cutscene.cutscene);
|
||||||
|
}
|
||||||
|
|
||||||
void cutsceneRestart(void) {
|
void cutsceneRestart(void) {
|
||||||
assertNotNull(
|
assertNotNull(
|
||||||
CUTSCENE_SYSTEM.scene, "cutsceneRestart called with no cutscene running"
|
CUTSCENE_SYSTEM.scene, "cutsceneRestart called with no cutscene running"
|
||||||
|
|||||||
@@ -96,6 +96,22 @@ void cutsceneSystemStartCutsceneAndGoToMarker(
|
|||||||
const char_t *marker
|
const char_t *marker
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locks, loads and immediately starts a cutscene asset by file name,
|
||||||
|
* e.g. cutsceneSystemLoad("main_menu.jsonc") loads and starts
|
||||||
|
* assets/cutscenes/main_menu.jsonc - same lock/assetRequireLoaded/start
|
||||||
|
* sequence as sceneInitialInit's INITIAL_CUTSCENE_ENTRY. The entry is
|
||||||
|
* locked forever (never unlocked), same lifetime convention as
|
||||||
|
* LOCALE.entry - it's fine to call this again later for the same file,
|
||||||
|
* it'll just resolve to the same already-loaded entry. Opens the fatal
|
||||||
|
* error overlay (see uiFatalErrorOpen) instead of starting anything if
|
||||||
|
* the asset fails to load.
|
||||||
|
*
|
||||||
|
* @param file Cutscene file name (with .jsonc extension), relative to
|
||||||
|
* assets/cutscenes/.
|
||||||
|
*/
|
||||||
|
void cutsceneSystemLoad(const char_t *file);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restarts the currently running cutscene from its first item,
|
* Restarts the currently running cutscene from its first item,
|
||||||
* preserving whatever interact/interacted entities triggered it.
|
* preserving whatever interact/interacted entities triggered it.
|
||||||
|
|||||||
@@ -12,12 +12,6 @@
|
|||||||
#include "display/screen/screen.h"
|
#include "display/screen/screen.h"
|
||||||
#include "console/console.h"
|
#include "console/console.h"
|
||||||
#include "rpg/cutscene/cutscenesystem.h"
|
#include "rpg/cutscene/cutscenesystem.h"
|
||||||
#include "asset/asset.h"
|
|
||||||
|
|
||||||
// Loaded lazily and kept resident for the rest of the process - this scene
|
|
||||||
// only ever runs once at boot, but there's no reason to unlock it (same
|
|
||||||
// lifetime convention as e.g. LOCALE.entry).
|
|
||||||
static assetentry_t *INITIAL_CUTSCENE_ENTRY = NULL;
|
|
||||||
|
|
||||||
errorret_t sceneInitialInit(scenedata_t *sceneData) {
|
errorret_t sceneInitialInit(scenedata_t *sceneData) {
|
||||||
assertNotNull(sceneData, "Scene data cannot be null");
|
assertNotNull(sceneData, "Scene data cannot be null");
|
||||||
@@ -29,18 +23,7 @@ errorret_t sceneInitialInit(scenedata_t *sceneData) {
|
|||||||
// Runtime-loaded from assets/cutscenes/initial.jsonc, parsed directly at
|
// Runtime-loaded from assets/cutscenes/initial.jsonc, parsed directly at
|
||||||
// load time (no separate compile step) - checks for a save device,
|
// load time (no separate compile step) - checks for a save device,
|
||||||
// retrying on failure, then hands off to the main menu.
|
// retrying on failure, then hands off to the main menu.
|
||||||
if(INITIAL_CUTSCENE_ENTRY == NULL) {
|
cutsceneSystemLoad("initial.jsonc");
|
||||||
INITIAL_CUTSCENE_ENTRY = assetLock(
|
|
||||||
"cutscenes/initial.jsonc", ASSET_LOADER_TYPE_CUTSCENE, NULL
|
|
||||||
);
|
|
||||||
}
|
|
||||||
errorret_t result = assetRequireLoaded(INITIAL_CUTSCENE_ENTRY);
|
|
||||||
if(errorIsNotOk(result)) {
|
|
||||||
errorCatch(errorPrint(result));
|
|
||||||
assertTrue(false, "Failed to load initial scene cutscene asset");
|
|
||||||
}
|
|
||||||
|
|
||||||
cutsceneSystemStartCutscene(&INITIAL_CUTSCENE_ENTRY->data.cutscene.cutscene);
|
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||||
PUBLIC
|
PUBLIC
|
||||||
uiconsole.c
|
uiconsole.c
|
||||||
|
uicutscene.c
|
||||||
uifps.c
|
uifps.c
|
||||||
uiplayerpos.c
|
uiplayerpos.c
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uicutscene.h"
|
||||||
|
#include "util/string.h"
|
||||||
|
#include "display/screen/screen.h"
|
||||||
|
#include "display/text/text.h"
|
||||||
|
#include "display/spritebatch/spritebatch.h"
|
||||||
|
#include "display/color.h"
|
||||||
|
#include "rpg/cutscene/cutscenesystem.h"
|
||||||
|
#include "rpg/cutscene/item/cutsceneitem.h"
|
||||||
|
|
||||||
|
uicutscene_t UICUTSCENE;
|
||||||
|
|
||||||
|
errorret_t uiCutsceneInit() {
|
||||||
|
uiLabelInit(
|
||||||
|
&UICUTSCENE.countLabel,
|
||||||
|
UICUTSCENE.countText,
|
||||||
|
UICUTSCENE.countSprites, UI_CUTSCENE_SPRITES_MAX
|
||||||
|
);
|
||||||
|
uiLabelSetX(&UICUTSCENE.countLabel, (float_t)SCREEN.scanX);
|
||||||
|
uiLabelSetY(&UICUTSCENE.countLabel, (float_t)SCREEN.scanY +
|
||||||
|
(float_t)FONT_DEFAULT.tileset->tileHeight * 2
|
||||||
|
);
|
||||||
|
|
||||||
|
uiLabelInit(
|
||||||
|
&UICUTSCENE.itemLabel,
|
||||||
|
UICUTSCENE.itemText,
|
||||||
|
UICUTSCENE.itemSprites, UI_CUTSCENE_SPRITES_MAX
|
||||||
|
);
|
||||||
|
uiLabelSetX(&UICUTSCENE.itemLabel, (float_t)SCREEN.scanX);
|
||||||
|
uiLabelSetY(&UICUTSCENE.itemLabel, (float_t)SCREEN.scanY +
|
||||||
|
(float_t)FONT_DEFAULT.tileset->tileHeight * 3
|
||||||
|
);
|
||||||
|
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t uiCutsceneDraw() {
|
||||||
|
const cutsceneitem_t *item = cutsceneSystemGetCurrentItem();
|
||||||
|
if(!item || !CUTSCENE_SYSTEM.scene) {
|
||||||
|
stringCopy(
|
||||||
|
UICUTSCENE.countText, "Cutscene Inactive", UI_CUTSCENE_TEXT_MAX - 1
|
||||||
|
);
|
||||||
|
UICUTSCENE.itemText[0] = '\0';
|
||||||
|
} else {
|
||||||
|
const char_t *name = CUTSCENE_ITEM_CALLBACKS[item->type].jsonName;
|
||||||
|
if(!name) name = "???";
|
||||||
|
|
||||||
|
stringFormat(
|
||||||
|
UICUTSCENE.countText,
|
||||||
|
UI_CUTSCENE_TEXT_MAX - 1,
|
||||||
|
"Cutscene Item Count: %d",
|
||||||
|
(int_t)CUTSCENE_SYSTEM.scene->itemCount
|
||||||
|
);
|
||||||
|
stringFormat(
|
||||||
|
UICUTSCENE.itemText,
|
||||||
|
UI_CUTSCENE_TEXT_MAX - 1,
|
||||||
|
"Current Item: %s",
|
||||||
|
name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
UICUTSCENE.countLabel.dirty = true;
|
||||||
|
UICUTSCENE.itemLabel.dirty = true;
|
||||||
|
|
||||||
|
errorChain(uiLabelRender(&UICUTSCENE.countLabel, COLOR_GREEN));
|
||||||
|
errorChain(uiLabelRender(&UICUTSCENE.itemLabel, COLOR_GREEN));
|
||||||
|
return spriteBatchFlush();
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* 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 "ui/widget/uilabel.h"
|
||||||
|
|
||||||
|
#define UI_CUTSCENE_TEXT_MAX 64
|
||||||
|
#define UI_CUTSCENE_SPRITES_MAX UI_CUTSCENE_TEXT_MAX
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uilabel_t countLabel;
|
||||||
|
char_t countText[UI_CUTSCENE_TEXT_MAX];
|
||||||
|
spritebatchsprite_t countSprites[UI_CUTSCENE_SPRITES_MAX];
|
||||||
|
|
||||||
|
uilabel_t itemLabel;
|
||||||
|
char_t itemText[UI_CUTSCENE_TEXT_MAX];
|
||||||
|
spritebatchsprite_t itemSprites[UI_CUTSCENE_SPRITES_MAX];
|
||||||
|
} uicutscene_t;
|
||||||
|
|
||||||
|
extern uicutscene_t UICUTSCENE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the cutscene debug labels.
|
||||||
|
*
|
||||||
|
* @return Any error that occurs.
|
||||||
|
*/
|
||||||
|
errorret_t uiCutsceneInit();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws the currently running cutscene's item count and current item
|
||||||
|
* type as two lines ("Item Count: %d" / "Current Item: %s"), or a
|
||||||
|
* single "Cutscene Inactive" line if no cutscene is running. Renders
|
||||||
|
* below UIPLAYERPOS (see ui/debug/uiplayerpos.h).
|
||||||
|
*
|
||||||
|
* @return Any error that occurs.
|
||||||
|
*/
|
||||||
|
errorret_t uiCutsceneDraw();
|
||||||
@@ -9,7 +9,6 @@
|
|||||||
#include "ui/widget/uiframe.h"
|
#include "ui/widget/uiframe.h"
|
||||||
#include "ui/widget/uibutton.h"
|
#include "ui/widget/uibutton.h"
|
||||||
#include "engine/engine.h"
|
#include "engine/engine.h"
|
||||||
#include "assert/assert.h"
|
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
#include "util/math.h"
|
#include "util/math.h"
|
||||||
@@ -40,11 +39,11 @@ errorret_t uiFatalErrorInit(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void uiFatalErrorOpen(const char_t *message) {
|
void uiFatalErrorOpen(const char_t *message) {
|
||||||
assertNotNull(message, "Message cannot be NULL");
|
|
||||||
// This is the last line of defense - it must never itself fail, so a
|
// This is the last line of defense - it must never itself fail, so a
|
||||||
// second fatal error while one is already showing is silently dropped
|
// second fatal error while one is already showing is silently dropped
|
||||||
// rather than asserting.
|
// rather than asserting.
|
||||||
if(UI_FATAL_ERROR.open) return;
|
if(UI_FATAL_ERROR.open) return;
|
||||||
|
if(message == NULL) message = UI_FATAL_ERROR_GENERIC_MESSAGE;
|
||||||
|
|
||||||
stringCopy(
|
stringCopy(
|
||||||
UI_FATAL_ERROR.messageText, message, UI_FATAL_ERROR_MESSAGE_MAX - 1
|
UI_FATAL_ERROR.messageText, message, UI_FATAL_ERROR_MESSAGE_MAX - 1
|
||||||
|
|||||||
@@ -14,6 +14,9 @@
|
|||||||
#define UI_FATAL_ERROR_MESSAGE_SPRITES_MAX UI_FATAL_ERROR_MESSAGE_MAX
|
#define UI_FATAL_ERROR_MESSAGE_SPRITES_MAX UI_FATAL_ERROR_MESSAGE_MAX
|
||||||
#define UI_FATAL_ERROR_ITEM_COUNT 1
|
#define UI_FATAL_ERROR_ITEM_COUNT 1
|
||||||
#define UI_FATAL_ERROR_QUIT_LABEL "QUIT"
|
#define UI_FATAL_ERROR_QUIT_LABEL "QUIT"
|
||||||
|
#define UI_FATAL_ERROR_GENERIC_MESSAGE \
|
||||||
|
"An unexpected error occurred and the game must exit. " \
|
||||||
|
"Please contact support if this issue persists."
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool_t open;
|
bool_t open;
|
||||||
@@ -46,6 +49,10 @@ errorret_t uiFatalErrorInit(void);
|
|||||||
*
|
*
|
||||||
* @param message The error text to display; copied internally, safe to
|
* @param message The error text to display; copied internally, safe to
|
||||||
* be transient. Truncated to UI_FATAL_ERROR_MESSAGE_MAX - 1 characters.
|
* be transient. Truncated to UI_FATAL_ERROR_MESSAGE_MAX - 1 characters.
|
||||||
|
* May be NULL, in which case UI_FATAL_ERROR_GENERIC_MESSAGE is shown
|
||||||
|
* instead - useful for callers with no specific error text to report
|
||||||
|
* (or that don't want to risk formatting/locale-lookup failures of their
|
||||||
|
* own right before calling this, the last line of defense).
|
||||||
*/
|
*/
|
||||||
void uiFatalErrorOpen(const char_t *message);
|
void uiFatalErrorOpen(const char_t *message);
|
||||||
|
|
||||||
|
|||||||
@@ -26,17 +26,7 @@
|
|||||||
#define UI_MAIN_MENU_INDEX_QUIT 2
|
#define UI_MAIN_MENU_INDEX_QUIT 2
|
||||||
|
|
||||||
uimainmenu_t UI_MAIN_MENU;
|
uimainmenu_t UI_MAIN_MENU;
|
||||||
|
assetentry_t *MAIN_MENU_CUTSCENE_ENTRY = NULL;
|
||||||
// Loaded lazily on first activation and kept resident for the rest of the
|
|
||||||
// process - it's tiny and reused every time, so there's no benefit to
|
|
||||||
// unlocking/reloading it between attempts (same lifetime convention as
|
|
||||||
// e.g. LOCALE.entry). The persistent cutscene is normally already running
|
|
||||||
// by the time this screen is reachable at all (chained straight from the
|
|
||||||
// initial cutscene's own CUTSCENE item, see assets/cutscenes/initial.jsonc
|
|
||||||
// and CUTSCENE_ITEM_TYPE_CUTSCENE in asset/loader/cutscene/
|
|
||||||
// assetcutsceneloader.c) - this lock just gives uiMainMenuStartGame a
|
|
||||||
// stable pointer to restart it with if that run already completed.
|
|
||||||
static assetentry_t *MAIN_MENU_CUTSCENE_ENTRY = NULL;
|
|
||||||
|
|
||||||
void uiMainMenuQuitConfirmed(const bool_t result, void *user) {
|
void uiMainMenuQuitConfirmed(const bool_t result, void *user) {
|
||||||
if(result) ENGINE.running = false;
|
if(result) ENGINE.running = false;
|
||||||
@@ -59,7 +49,7 @@ cutscene_t *uiMainMenuLoadCutscene(void) {
|
|||||||
|
|
||||||
void uiMainMenuSelectSaveResult(const uint8_t slotIndex, void *user) {
|
void uiMainMenuSelectSaveResult(const uint8_t slotIndex, void *user) {
|
||||||
if(slotIndex == UI_SELECT_SAVE_RESULT_NONE) {
|
if(slotIndex == UI_SELECT_SAVE_RESULT_NONE) {
|
||||||
uiMainMenuOpen();
|
cutsceneSystemLoad("main_menu.jsonc");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,10 +65,6 @@ void uiMainMenuOpenSelectSave(void *userData) {
|
|||||||
|
|
||||||
void uiMainMenuStartGame(void) {
|
void uiMainMenuStartGame(void) {
|
||||||
if(CUTSCENE_SYSTEM.scene == NULL) {
|
if(CUTSCENE_SYSTEM.scene == NULL) {
|
||||||
// The menu cutscene already ran to completion once (e.g. the player
|
|
||||||
// backed out of the save picker back to this menu) - restart it
|
|
||||||
// landing straight on NEW_GAME rather than replaying the idle/BGM
|
|
||||||
// setup from the top.
|
|
||||||
cutsceneSystemStartCutsceneAndGoToMarker(
|
cutsceneSystemStartCutsceneAndGoToMarker(
|
||||||
uiMainMenuLoadCutscene(), "NEW_GAME"
|
uiMainMenuLoadCutscene(), "NEW_GAME"
|
||||||
);
|
);
|
||||||
@@ -86,11 +72,6 @@ void uiMainMenuStartGame(void) {
|
|||||||
cutsceneGoTo("NEW_GAME");
|
cutsceneGoTo("NEW_GAME");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Armed unconditionally, whether this just (re)started the cutscene or
|
|
||||||
// jumped one already running since boot (chained straight from the
|
|
||||||
// initial cutscene - see assets/cutscenes/initial.jsonc) - that first
|
|
||||||
// run is never otherwise armed by anything, so setting this only in the
|
|
||||||
// restart branch above would silently drop it on a fresh boot.
|
|
||||||
cutsceneSystemSetOnComplete(uiMainMenuOpenSelectSave);
|
cutsceneSystemSetOnComplete(uiMainMenuOpenSelectSave);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +88,6 @@ void uiMainMenuSelected(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case UI_MAIN_MENU_INDEX_OPTIONS:
|
case UI_MAIN_MENU_INDEX_OPTIONS:
|
||||||
// TODO: options.
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UI_MAIN_MENU_INDEX_QUIT:
|
case UI_MAIN_MENU_INDEX_QUIT:
|
||||||
@@ -151,9 +131,6 @@ errorret_t uiMainMenuInit(void) {
|
|||||||
MENU_BUTTON(UI_MAIN_MENU.optionsLabel);
|
MENU_BUTTON(UI_MAIN_MENU.optionsLabel);
|
||||||
MENU_BUTTON(UI_MAIN_MENU.quitLabel);
|
MENU_BUTTON(UI_MAIN_MENU.quitLabel);
|
||||||
MENU_END(UI_MAIN_MENU.items, 1);
|
MENU_END(UI_MAIN_MENU.items, 1);
|
||||||
|
|
||||||
// The main menu is the root screen once past the initial boot check -
|
|
||||||
// there's nothing to back out to, so back/cancel does nothing here.
|
|
||||||
uiMenuSetDisableBack(&UI_MAIN_MENU.menu, true);
|
uiMenuSetDisableBack(&UI_MAIN_MENU.menu, true);
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "ui/overlay/uiloading.h"
|
#include "ui/overlay/uiloading.h"
|
||||||
#include "ui/overlay/uifatalerror.h"
|
#include "ui/overlay/uifatalerror.h"
|
||||||
#include "ui/debug/uiplayerpos.h"
|
#include "ui/debug/uiplayerpos.h"
|
||||||
|
#include "ui/debug/uicutscene.h"
|
||||||
#include "ui/overlay/uicrop.h"
|
#include "ui/overlay/uicrop.h"
|
||||||
#include "ui/transition/uitransition.h"
|
#include "ui/transition/uitransition.h"
|
||||||
#include "ui/debug/uiconsole.h"
|
#include "ui/debug/uiconsole.h"
|
||||||
@@ -156,6 +157,7 @@ uielement_t UI_ELEMENTS[] = {
|
|||||||
{ .init = uiConsoleInit, .draw = uiConsoleDraw },
|
{ .init = uiConsoleInit, .draw = uiConsoleDraw },
|
||||||
{ .init = uiFPSInit, .draw = uiFPSDraw },
|
{ .init = uiFPSInit, .draw = uiFPSDraw },
|
||||||
{ .init = uiPlayerPosInit, .draw = uiPlayerPosDraw },
|
{ .init = uiPlayerPosInit, .draw = uiPlayerPosDraw },
|
||||||
|
{ .init = uiCutsceneInit, .draw = uiCutsceneDraw },
|
||||||
|
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
// Null terminator
|
// Null terminator
|
||||||
|
|||||||
Reference in New Issue
Block a user