càrrega de recursos no bloquejant
This commit is contained in:
@@ -217,4 +217,5 @@ namespace Defaults::Settings {
|
||||
namespace Defaults::Loading {
|
||||
constexpr bool SHOW = false;
|
||||
constexpr bool SHOW_RESOURCE_NAME = true;
|
||||
constexpr bool WAIT_FOR_INPUT = false;
|
||||
} // namespace Defaults::Loading
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace Lang {
|
||||
}
|
||||
|
||||
// Declaraciones adelantadas de las secciones
|
||||
class Preload;
|
||||
class Logo;
|
||||
class Intro;
|
||||
class Title;
|
||||
@@ -54,6 +55,7 @@ class Director {
|
||||
std::string system_folder_; // Carpeta del sistema para almacenar datos
|
||||
|
||||
// --- Sección activa (una y sólo una viva en cada momento) ---
|
||||
std::unique_ptr<Preload> preload_;
|
||||
std::unique_ptr<Logo> logo_;
|
||||
std::unique_ptr<Intro> intro_;
|
||||
std::unique_ptr<Title> title_;
|
||||
@@ -63,8 +65,12 @@ class Director {
|
||||
std::unique_ptr<Credits> credits_;
|
||||
Section::Name last_built_section_name_ = Section::Name::RESET;
|
||||
|
||||
// --- Fase de arranque no bloqueante ---
|
||||
bool boot_loading_ = true; // True mientras Resource::loadStep está cargando incremental
|
||||
|
||||
// --- Inicialización y cierre del sistema ---
|
||||
void init(); // Inicializa la aplicación
|
||||
void init(); // Inicializa la aplicación (pre-boot)
|
||||
void finishBoot(); // Post-boot: inicializa lo que depende de recursos cargados
|
||||
static void close(); // Cierra y libera recursos
|
||||
|
||||
// --- Configuración inicial ---
|
||||
|
||||
@@ -36,7 +36,11 @@ namespace GlobalEvents {
|
||||
// Reasignar siempre: tanto en arranque como en hotplug en caliente.
|
||||
Options::gamepad_manager.assignAndLinkGamepads();
|
||||
Options::gamepad_manager.resyncGamepadsWithPlayers();
|
||||
ServiceMenu::get()->refresh();
|
||||
|
||||
// Durante el preload ServiceMenu aún no existe: solo refresca si está vivo.
|
||||
if (ServiceMenu::get() != nullptr) {
|
||||
ServiceMenu::get()->refresh();
|
||||
}
|
||||
|
||||
if (startup_in_progress || message.empty()) {
|
||||
return;
|
||||
@@ -51,7 +55,11 @@ namespace GlobalEvents {
|
||||
message.replace(pos, std::string(" DISCONNECTED").length(), " " + Lang::getText("[NOTIFICATIONS] DISCONNECTED"));
|
||||
}
|
||||
|
||||
Notifier::get()->show({message});
|
||||
// Notifier también puede no existir todavía si la notificación se
|
||||
// disparase antes de finishBoot(). Protegido por si acaso.
|
||||
if (Notifier::get() != nullptr) {
|
||||
Notifier::get()->show({message});
|
||||
}
|
||||
}
|
||||
|
||||
void markStartupComplete() {
|
||||
@@ -79,7 +87,10 @@ namespace GlobalEvents {
|
||||
break;
|
||||
}
|
||||
|
||||
ServiceMenu::get()->handleEvent(event);
|
||||
// Durante el preload ServiceMenu aún no existe
|
||||
if (ServiceMenu::get() != nullptr) {
|
||||
ServiceMenu::get()->handleEvent(event);
|
||||
}
|
||||
Mouse::handleEvent(event);
|
||||
handleInputEvents(event);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace Section {
|
||||
// --- Enumeraciones de secciones del programa ---
|
||||
enum class Name {
|
||||
RESET, // Inicialización
|
||||
PRELOAD, // Carga incremental de recursos
|
||||
LOGO, // Pantalla de logo
|
||||
INTRO, // Introducción
|
||||
TITLE, // Pantalla de título/menú principal
|
||||
@@ -43,6 +44,7 @@ namespace Section {
|
||||
|
||||
// --- Variables globales de estado ---
|
||||
inline Name name = Name::RESET;
|
||||
inline Name post_preload = Name::LOGO; // Sección a la que transiciona PRELOAD al terminar
|
||||
inline Options options = Options::NONE;
|
||||
inline AttractMode attract_mode = AttractMode::TITLE_TO_DEMO;
|
||||
} // namespace Section
|
||||
Reference in New Issue
Block a user