refactor(director): extreu iterate/handleEvent/advanceScene del runFrameLoop
run() ara delega a iterate() i handleEvent() per cada frame. runFrameLoop desapareix; la seva lògica es divideix entre els tres nous mètodes. La primera escena es construeix lazy via advanceScene() dins d'iterate(). Cap canvi de comportament visible.
This commit is contained in:
+107
-63
@@ -282,20 +282,28 @@ auto Director::run() -> int {
|
|||||||
// tant com el Notifier; el destruim explícitament abans de tornar.
|
// tant com el Notifier; el destruim explícitament abans de tornar.
|
||||||
System::Notifier::init(sdl_->getRenderer());
|
System::Notifier::init(sdl_->getRenderer());
|
||||||
|
|
||||||
// Bucle principal: construir escena → frame loop → destruir → siguiente.
|
// Comptador de delta time per al primer iterate().
|
||||||
while (context_->nextScene() != SceneType::EXIT) {
|
last_ticks_ms_ = SDL_GetTicks();
|
||||||
SceneManager::actual = context_->nextScene();
|
|
||||||
current_scene_ = buildScene(context_->nextScene(), *sdl_, *context_);
|
|
||||||
if (!current_scene_) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
runFrameLoop(*current_scene_, *sdl_, *context_, *debug_overlay_);
|
|
||||||
current_scene_.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
SceneManager::actual = SceneType::EXIT;
|
// Bucle principal: poll d'events + iterate() per frame. La primera escena
|
||||||
System::Notifier::destroy();
|
// es construeix lazy dins d'iterate() via advanceScene(). En migrar a
|
||||||
return 0;
|
// SDL_MAIN_USE_CALLBACKS, aquest while desapareixerà i SDL_AppEvent/
|
||||||
|
// SDL_AppIterate cridaran handleEvent()/iterate() directament.
|
||||||
|
while (true) {
|
||||||
|
SDL_Event event;
|
||||||
|
while (SDL_PollEvent(&event)) {
|
||||||
|
SDL_AppResult r = handleEvent(event);
|
||||||
|
if (r != SDL_APP_CONTINUE) {
|
||||||
|
System::Notifier::destroy();
|
||||||
|
return (r == SDL_APP_SUCCESS) ? 0 : 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SDL_AppResult r = iterate();
|
||||||
|
if (r != SDL_APP_CONTINUE) {
|
||||||
|
System::Notifier::destroy();
|
||||||
|
return (r == SDL_APP_SUCCESS) ? 0 : 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Director::buildScene(SceneType type, SDLManager& sdl, SceneContext& context)
|
auto Director::buildScene(SceneType type, SDLManager& sdl, SceneContext& context)
|
||||||
@@ -313,55 +321,91 @@ auto Director::buildScene(SceneType type, SDLManager& sdl, SceneContext& context
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Director::runFrameLoop(Scene& scene, SDLManager& sdl, SceneContext& context, System::DebugOverlay& debug_overlay) {
|
auto Director::advanceScene() -> SDL_AppResult {
|
||||||
SDL_Event event;
|
current_scene_.reset();
|
||||||
Uint64 last_time = SDL_GetTicks();
|
const SceneType NEXT = context_->nextScene();
|
||||||
|
if (NEXT == SceneType::EXIT) {
|
||||||
while (!scene.isFinished()) {
|
SceneManager::actual = SceneType::EXIT;
|
||||||
// Delta time real, capeado a 50ms para evitar grandes saltos.
|
return SDL_APP_SUCCESS;
|
||||||
const Uint64 NOW = SDL_GetTicks();
|
|
||||||
float delta_time = static_cast<float>(NOW - last_time) / 1000.0F;
|
|
||||||
last_time = NOW;
|
|
||||||
delta_time = std::min(delta_time, 0.05F);
|
|
||||||
|
|
||||||
Mouse::updateCursorVisibility();
|
|
||||||
Input::get()->update();
|
|
||||||
|
|
||||||
// Event loop: primero ventana, después globales, después F11
|
|
||||||
// (toggle del overlay), después escena.
|
|
||||||
while (SDL_PollEvent(&event)) {
|
|
||||||
if (sdl.handleWindowEvent(event)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (GlobalEvents::handle(event, sdl, context)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (event.type == SDL_EVENT_KEY_DOWN && event.key.scancode == SDL_SCANCODE_F11) {
|
|
||||||
debug_overlay.toggle();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
scene.handleEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
scene.update(delta_time);
|
|
||||||
debug_overlay.update(delta_time);
|
|
||||||
if (auto* notifier = System::Notifier::get(); notifier != nullptr) {
|
|
||||||
notifier->update(delta_time);
|
|
||||||
}
|
|
||||||
Audio::update();
|
|
||||||
|
|
||||||
// Si la swapchain no está disponible (ventana minimizada, etc.),
|
|
||||||
// saltarse draw+present ese frame: dibujar dejaría vértices
|
|
||||||
// colgando en el batch interno sin nadie que los presente.
|
|
||||||
if (!sdl.clear(0, 0, 0)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
sdl.updateRenderingContext();
|
|
||||||
scene.draw();
|
|
||||||
debug_overlay.draw(); // sempre per damunt de l'escena
|
|
||||||
if (const auto* notifier = System::Notifier::get(); notifier != nullptr) {
|
|
||||||
notifier->draw(); // toast: per damunt de tot
|
|
||||||
}
|
|
||||||
sdl.present();
|
|
||||||
}
|
}
|
||||||
|
SceneManager::actual = NEXT;
|
||||||
|
current_scene_ = buildScene(NEXT, *sdl_, *context_);
|
||||||
|
if (!current_scene_) {
|
||||||
|
SceneManager::actual = SceneType::EXIT;
|
||||||
|
return SDL_APP_SUCCESS;
|
||||||
|
}
|
||||||
|
return SDL_APP_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Director::handleEvent(const SDL_Event& event) -> SDL_AppResult {
|
||||||
|
// 1. Window events (resize, minimize, focus...)
|
||||||
|
if (sdl_->handleWindowEvent(event)) {
|
||||||
|
return SDL_APP_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Events globals (F1-F6, ESC, QUIT, gamepad hotplug).
|
||||||
|
// GlobalEvents marca context_->nextScene() = EXIT en ESC doble o QUIT;
|
||||||
|
// activem la bandera per fer-ho fluir cap a SDL_APP_SUCCESS al pròxim tick.
|
||||||
|
if (GlobalEvents::handle(event, *sdl_, *context_)) {
|
||||||
|
if (context_->nextScene() == SceneType::EXIT) {
|
||||||
|
wants_quit_ = true;
|
||||||
|
}
|
||||||
|
return SDL_APP_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. F11 → toggle del debug overlay (cas especial fora de GlobalEvents).
|
||||||
|
if (event.type == SDL_EVENT_KEY_DOWN && event.key.scancode == SDL_SCANCODE_F11) {
|
||||||
|
debug_overlay_->toggle();
|
||||||
|
return SDL_APP_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Esdeveniment específic de l'escena actual.
|
||||||
|
if (current_scene_) {
|
||||||
|
current_scene_->handleEvent(event);
|
||||||
|
}
|
||||||
|
return SDL_APP_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Director::iterate() -> SDL_AppResult {
|
||||||
|
if (wants_quit_) {
|
||||||
|
return SDL_APP_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pivotar a la següent escena si l'actual ha acabat (o és la primera).
|
||||||
|
if (!current_scene_ || current_scene_->isFinished()) {
|
||||||
|
SDL_AppResult pivot = advanceScene();
|
||||||
|
if (pivot != SDL_APP_CONTINUE) {
|
||||||
|
return pivot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delta time real, capeado a 50ms per evitar grans salts.
|
||||||
|
const Uint64 NOW = SDL_GetTicks();
|
||||||
|
float delta_time = static_cast<float>(NOW - last_ticks_ms_) / 1000.0F;
|
||||||
|
last_ticks_ms_ = NOW;
|
||||||
|
delta_time = std::min(delta_time, 0.05F);
|
||||||
|
|
||||||
|
Mouse::updateCursorVisibility();
|
||||||
|
Input::get()->update();
|
||||||
|
|
||||||
|
current_scene_->update(delta_time);
|
||||||
|
debug_overlay_->update(delta_time);
|
||||||
|
if (auto* notifier = System::Notifier::get(); notifier != nullptr) {
|
||||||
|
notifier->update(delta_time);
|
||||||
|
}
|
||||||
|
Audio::update();
|
||||||
|
|
||||||
|
// Si la swapchain no està disponible (finestra minimitzada, etc.),
|
||||||
|
// saltar-se draw+present aquest frame.
|
||||||
|
if (!sdl_->clear(0, 0, 0)) {
|
||||||
|
return SDL_APP_CONTINUE;
|
||||||
|
}
|
||||||
|
sdl_->updateRenderingContext();
|
||||||
|
current_scene_->draw();
|
||||||
|
debug_overlay_->draw(); // sempre per damunt de l'escena
|
||||||
|
if (const auto* notifier = System::Notifier::get(); notifier != nullptr) {
|
||||||
|
notifier->draw(); // toast: per damunt de tot
|
||||||
|
}
|
||||||
|
sdl_->present();
|
||||||
|
return SDL_APP_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -26,6 +28,16 @@ class Director {
|
|||||||
// Bucle principal del juego.
|
// Bucle principal del juego.
|
||||||
auto run() -> int;
|
auto run() -> int;
|
||||||
|
|
||||||
|
// Una iteració del bucle: pivot d'escena si cal, delta time, update i
|
||||||
|
// render. Retorna SDL_APP_CONTINUE per seguir, SDL_APP_SUCCESS si vol
|
||||||
|
// sortir net, SDL_APP_FAILURE si no es pot recuperar.
|
||||||
|
auto iterate() -> SDL_AppResult;
|
||||||
|
|
||||||
|
// Enruta un sol esdeveniment cap a la cadena finestra → globals → F11 →
|
||||||
|
// escena. Si detecta sortida (ESC doble, QUIT) marca wants_quit_ perquè
|
||||||
|
// el següent iterate() retorni SDL_APP_SUCCESS.
|
||||||
|
auto handleEvent(const SDL_Event& event) -> SDL_AppResult;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string executable_path_;
|
std::string executable_path_;
|
||||||
std::string system_folder_;
|
std::string system_folder_;
|
||||||
@@ -41,6 +53,9 @@ class Director {
|
|||||||
std::unique_ptr<System::DebugOverlay> debug_overlay_;
|
std::unique_ptr<System::DebugOverlay> debug_overlay_;
|
||||||
std::unique_ptr<Scene> current_scene_;
|
std::unique_ptr<Scene> current_scene_;
|
||||||
|
|
||||||
|
Uint64 last_ticks_ms_{0};
|
||||||
|
bool wants_quit_{false};
|
||||||
|
|
||||||
auto checkProgramArguments(std::vector<std::string> const& args)
|
auto checkProgramArguments(std::vector<std::string> const& args)
|
||||||
-> std::string;
|
-> std::string;
|
||||||
void createSystemFolder(const std::string& folder);
|
void createSystemFolder(const std::string& folder);
|
||||||
@@ -52,8 +67,8 @@ class Director {
|
|||||||
SceneManager::SceneContext& context)
|
SceneManager::SceneContext& context)
|
||||||
-> std::unique_ptr<Scene>;
|
-> std::unique_ptr<Scene>;
|
||||||
|
|
||||||
// Ejecuta el bucle de frames de UNA escena hasta que scene.isFinished()
|
// Pivota a la següent escena: destrueix l'actual, llegeix context_->nextScene()
|
||||||
// sea true. Maneja delta_time, eventos (globales + escena), update y draw.
|
// i construeix la nova. Retorna SDL_APP_SUCCESS si la nova és EXIT o no es pot
|
||||||
// El debug_overlay es global a todas las escenas; el Director lo posee.
|
// construir; SDL_APP_CONTINUE si tot OK.
|
||||||
static void runFrameLoop(Scene& scene, SDLManager& sdl, SceneManager::SceneContext& context, System::DebugOverlay& debug_overlay);
|
auto advanceScene() -> SDL_AppResult;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user