càrrega de recursos no bloquejant

This commit is contained in:
2026-04-14 18:10:28 +02:00
parent d493ebf4f0
commit 8706b2c7fb
15 changed files with 356 additions and 118 deletions
+60 -9
View File
@@ -32,6 +32,7 @@
#include "game/scenes/instructions.hpp" // Para Instructions
#include "game/scenes/intro.hpp" // Para Intro
#include "game/scenes/logo.hpp" // Para Logo
#include "game/scenes/preload.hpp" // Para Preload
#include "game/scenes/title.hpp" // Para Title
#include "game/ui/notifier.hpp" // Para Notifier
#include "game/ui/service_menu.hpp" // Para ServiceMenu
@@ -140,9 +141,40 @@ void Director::init() {
#else
Resource::init(Resource::LoadingMode::PRELOAD);
#endif
if (Resource::get()->getLoadingMode() == Resource::LoadingMode::PRELOAD) {
// Guarda la sección destino (la que fijó loadDebugConfig o el default)
// y redirige el arranque a la escena PRELOAD hasta que loadStep termine.
Section::post_preload = Section::name;
Section::name = Section::Name::PRELOAD;
Resource::get()->beginLoad();
} else {
// LAZY_LOAD: el constructor de Resource ya cargó lo esencial síncronamente;
// no hay fase de preload, pasamos directamente a post-boot.
finishBoot();
boot_loading_ = false;
}
// ServiceMenu/Notifier/getSingletons se mueven a finishBoot() — dependen
// de Resource y se inicializan al terminar la carga incremental.
}
// Inicializaciones que dependen del Resource cargado. Se llama desde iterate()
// cuando Resource::loadStep() devuelve true, con la ventana y el bucle vivos.
void Director::finishBoot() {
ServiceMenu::init(); // Inicializa el menú de servicio
Notifier::init(std::string(), Resource::get()->getText("8bithud")); // Inicialización del sistema de notificaciones
Screen::get()->getSingletons(); // Obtiene los punteros al resto de singletones
// Restaura el vsync a la preferencia del usuario (beginLoad lo había puesto a false)
Screen::get()->setVSync(Options::video.vsync);
// Si NO estamos en modo "wait for input", transiciona ya al destino.
// Si wait_for_input está activo (y la pantalla es visible), nos quedamos
// en PRELOAD hasta que el usuario pulse tecla/botón.
if (!(Options::loading.show && Options::loading.wait_for_input)) {
Section::name = Section::post_preload;
}
}
// Cierra todo y libera recursos del sistema y de los singletons
@@ -327,6 +359,7 @@ void Director::createSystemFolder(const std::string& folder) {
// Libera todos los unique_ptr de sección (solo uno tiene propiedad a la vez)
void Director::resetActiveSection() {
preload_.reset();
logo_.reset();
intro_.reset();
title_.reset();
@@ -353,6 +386,10 @@ void Director::handleSectionTransition() {
// Construye la nueva
switch (Section::name) {
case Section::Name::PRELOAD:
preload_ = std::make_unique<Preload>();
break;
case Section::Name::LOGO:
logo_ = std::make_unique<Logo>();
break;
@@ -435,20 +472,32 @@ auto Director::iterate() -> SDL_AppResult {
return SDL_APP_SUCCESS;
}
// En el primer frame, SDL ya ha drenado los SDL_EVENT_GAMEPAD_ADDED de los
// mandos conectados al iniciar. A partir de ahora los eventos sí son hotplug
// real y deben mostrar notificación.
static bool first_iterate = true;
if (first_iterate) {
first_iterate = false;
GlobalEvents::markStartupComplete();
// Fase de boot: carga incremental frame a frame con presupuesto de 50ms.
// Durante esta fase la escena activa es Preload (una barra de progreso).
if (boot_loading_) {
try {
if (Resource::get()->loadStep(50 /*ms*/)) {
finishBoot();
boot_loading_ = false;
// Los SDL_EVENT_GAMEPAD_ADDED iniciales ya los ha drenado la rama
// durante la carga: marcamos startup completo ahora para que los
// ADDED/REMOVED posteriores sí generen notificación.
GlobalEvents::markStartupComplete();
}
} catch (const std::exception& e) {
std::cerr << "Fatal error during resource load: " << e.what() << '\n';
Section::name = Section::Name::QUIT;
return SDL_APP_FAILURE;
}
}
// Gestiona las transiciones entre secciones (destruye la anterior y construye la nueva)
handleSectionTransition();
// Ejecuta un frame de la sección activa
if (logo_) {
if (preload_) {
preload_->iterate();
} else if (logo_) {
logo_->iterate();
} else if (intro_) {
intro_->iterate();
@@ -473,7 +522,9 @@ auto Director::handleEvent(SDL_Event& event) -> SDL_AppResult {
GlobalEvents::handle(event);
// Reenvía a la sección activa
if (logo_) {
if (preload_) {
preload_->handleEvent(event);
} else if (logo_) {
logo_->handleEvent(event);
} else if (intro_) {
intro_->handleEvent(event);