From e0922bfbba791549c96e33a33e69f488bf5009fc Mon Sep 17 00:00:00 2001 From: Jonathan Bradley Date: Wed, 3 Dec 2025 16:33:52 -0500 Subject: pke: tear down levels + settle ECS before shutdown --- src/game.cpp | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/game.cpp b/src/game.cpp index 01aba10..f56e129 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -86,7 +86,7 @@ void Game_Tick(double delta) { } } - if (pkeSettings.rt.activeLevel->pke_cb_tick.func != nullptr) { + if (pkeSettings.rt.activeLevel && pkeSettings.rt.activeLevel->pke_cb_tick.func != nullptr) { reinterpret_cast(pkeSettings.rt.activeLevel->pke_cb_tick.func)(delta); } @@ -260,6 +260,47 @@ void pke_game_main_run() { void pke_game_main_teardown() { fprintf(stdout, "[%s] pke_game_main_teardown Entering.\n", __FILE__); + // tear down any loaded levels + if (pkeSettings.rt.nextLevel != nullptr) { + if (pkeSettings.rt.nextLevel->pke_cb_teardown.func != nullptr) { + pkeSettings.rt.nextLevel->pke_cb_teardown.func(); + } + pke_level_teardown(pkeSettings.rt.nextLevel); + pkeSettings.rt.nextLevel = nullptr; + } + if (pkeSettings.rt.activeLevel != nullptr) { + if (pkeSettings.rt.activeLevel->pke_cb_teardown.func != nullptr) { + pkeSettings.rt.activeLevel->pke_cb_teardown.func(); + } + pke_level_teardown(pkeSettings.rt.activeLevel); + pkeSettings.rt.activeLevel = nullptr; + } + if (pkeSettings.rt.previousLevel != nullptr) { + if (pkeSettings.rt.previousLevel->pke_cb_teardown.func != nullptr) { + pkeSettings.rt.previousLevel->pke_cb_teardown.func(); + } + pke_level_teardown(pkeSettings.rt.previousLevel); + pkeSettings.rt.previousLevel = nullptr; + } + + // Tick until entities have settled. + // This allows things like nested entities (static_ui) to flush out. + // Without this, plugins will have their OnTeardown called before the engine + // has had a chance to free anything active. + // Example: player input LIFO error if a loaded level had an active set. + pk_bkt_arr *bkt_arr_ents = ECS_GetEntities(); + pk_bkt_arr_handle settle_handle_l = pk_bkt_arr_handle_MAX; + pk_bkt_arr_handle settle_handle_r = pk_bkt_arr_handle_MAX; + pk_bkt_arr_handle settle_handle_ll = bkt_arr_ents->head_l; + pk_bkt_arr_handle settle_handle_rr = bkt_arr_ents->head_r; + while (settle_handle_ll != settle_handle_l && settle_handle_rr != settle_handle_r) { + Game_Tick(0.f); + settle_handle_l = settle_handle_ll; + settle_handle_r = settle_handle_rr; + settle_handle_ll = bkt_arr_ents->head_l; + settle_handle_rr = bkt_arr_ents->head_r; + } + fprintf(stdout, "Game_Main SHUTDOWN INITIATED\n"); #ifndef NDEBUG // TODO debug print buckets before shutdown -- cgit v1.2.3