fix: Preservar SimulationMode y mejorar Debug HUD
CAMBIOS: - Debug HUD reorganizado en layout de 2 columnas (LEFT/RIGHT, sin centro) - Añadidos getters públicos en Engine para info de sistema - changeScenario() ahora preserva el SimulationMode actual - Inicialización de pelotas según modo (PHYSICS/SHAPE/BOIDS) - Eliminada duplicación de logo_entered_manually_ (ahora en StateManager) ARCHIVOS MODIFICADOS: - engine.h: Añadidos 8 getters públicos para UIManager - engine.cpp: changeScenario() pasa current_mode_ a SceneManager - scene_manager.h: changeScenario() acepta parámetro SimulationMode - scene_manager.cpp: Inicialización según modo (RULES.md líneas 23-26) - ui_manager.h: render() acepta Engine* y renderDebugHUD() actualizado - ui_manager.cpp: Debug HUD con columnas LEFT (sistema) y RIGHT (física) REGLAS.md IMPLEMENTADO: ✅ Líneas 23-26: Inicialización diferenciada por modo - PHYSICS: Top, 75% distribución central en X, velocidades aleatorias - SHAPE: Centro de pantalla, sin velocidad inicial - BOIDS: Posiciones y velocidades aleatorias ✅ Líneas 88-96: Debug HUD con información de sistema completa BUGS CORREGIDOS: - Fix: Cambiar escenario (1-8) en FIGURE ya no resetea a PHYSICS ❌→✅ - Fix: Las pelotas se inicializan correctamente según el modo activo - Fix: AppMode movido de centro a izquierda en Debug HUD 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -340,10 +340,14 @@ void Engine::update() {
|
|||||||
|
|
||||||
// Gravedad y física
|
// Gravedad y física
|
||||||
void Engine::handleGravityToggle() {
|
void Engine::handleGravityToggle() {
|
||||||
// Si estamos en modo boids, salir a modo física primero
|
// Si estamos en modo boids, salir a modo física CON GRAVEDAD OFF
|
||||||
|
// Según RULES.md: "BOIDS a PHYSICS: Pulsando la tecla G: Gravedad OFF"
|
||||||
if (current_mode_ == SimulationMode::BOIDS) {
|
if (current_mode_ == SimulationMode::BOIDS) {
|
||||||
toggleBoidsMode(); // Esto cambia a PHYSICS y activa gravedad
|
toggleBoidsMode(); // Cambiar a PHYSICS (preserva inercia, gravedad ya está OFF desde activateBoids)
|
||||||
return; // La notificación ya se muestra en toggleBoidsMode
|
// NO llamar a forceBallsGravityOff() porque aplica impulsos que destruyen la inercia de BOIDS
|
||||||
|
// La gravedad ya está desactivada por BoidManager::activateBoids() y se mantiene al salir
|
||||||
|
showNotificationForAction("Modo Física - Gravedad Off");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si estamos en modo figura, salir a modo física SIN GRAVEDAD
|
// Si estamos en modo figura, salir a modo física SIN GRAVEDAD
|
||||||
@@ -504,13 +508,14 @@ void Engine::switchTexture() {
|
|||||||
|
|
||||||
// Escenarios (número de pelotas)
|
// Escenarios (número de pelotas)
|
||||||
void Engine::changeScenario(int scenario_id, const char* notification_text) {
|
void Engine::changeScenario(int scenario_id, const char* notification_text) {
|
||||||
// Resetear modo SHAPE si está activo
|
// Pasar el modo actual al SceneManager para inicialización correcta
|
||||||
|
scene_manager_->changeScenario(scenario_id, current_mode_);
|
||||||
|
|
||||||
|
// Si estamos en modo SHAPE, regenerar la figura con nuevo número de pelotas
|
||||||
if (current_mode_ == SimulationMode::SHAPE) {
|
if (current_mode_ == SimulationMode::SHAPE) {
|
||||||
current_mode_ = SimulationMode::PHYSICS;
|
generateShape();
|
||||||
active_shape_.reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scene_manager_->changeScenario(scenario_id);
|
|
||||||
showNotificationForAction(notification_text);
|
showNotificationForAction(notification_text);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -695,7 +700,7 @@ void Engine::render() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Renderizar UI (debug HUD, texto obsoleto, notificaciones) - delegado a UIManager
|
// Renderizar UI (debug HUD, texto obsoleto, notificaciones) - delegado a UIManager
|
||||||
ui_manager_->render(renderer_, scene_manager_.get(), current_mode_, state_manager_->getCurrentMode(),
|
ui_manager_->render(renderer_, this, scene_manager_.get(), current_mode_, state_manager_->getCurrentMode(),
|
||||||
active_shape_.get(), shape_convergence_,
|
active_shape_.get(), shape_convergence_,
|
||||||
physical_window_width_, physical_window_height_, current_screen_width_);
|
physical_window_width_, physical_window_height_, current_screen_width_);
|
||||||
|
|
||||||
@@ -769,7 +774,7 @@ void Engine::toggleRealFullscreen() {
|
|||||||
|
|
||||||
// Reinicar la escena con nueva resolución
|
// Reinicar la escena con nueva resolución
|
||||||
scene_manager_->updateScreenSize(current_screen_width_, current_screen_height_);
|
scene_manager_->updateScreenSize(current_screen_width_, current_screen_height_);
|
||||||
scene_manager_->changeScenario(scene_manager_->getCurrentScenario());
|
scene_manager_->changeScenario(scene_manager_->getCurrentScenario(), current_mode_);
|
||||||
|
|
||||||
// Actualizar tamaño de pantalla para boids (wrapping boundaries)
|
// Actualizar tamaño de pantalla para boids (wrapping boundaries)
|
||||||
boid_manager_->updateScreenSize(current_screen_width_, current_screen_height_);
|
boid_manager_->updateScreenSize(current_screen_width_, current_screen_height_);
|
||||||
@@ -794,7 +799,7 @@ void Engine::toggleRealFullscreen() {
|
|||||||
|
|
||||||
// Reinicar la escena con resolución original
|
// Reinicar la escena con resolución original
|
||||||
scene_manager_->updateScreenSize(current_screen_width_, current_screen_height_);
|
scene_manager_->updateScreenSize(current_screen_width_, current_screen_height_);
|
||||||
scene_manager_->changeScenario(scene_manager_->getCurrentScenario());
|
scene_manager_->changeScenario(scene_manager_->getCurrentScenario(), current_mode_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1154,7 +1159,7 @@ void Engine::performLogoAction(bool logo_waiting_for_flip) {
|
|||||||
// Solo salir automáticamente si la entrada a LOGO fue automática (desde DEMO)
|
// Solo salir automáticamente si la entrada a LOGO fue automática (desde DEMO)
|
||||||
// No salir si el usuario entró manualmente con tecla K
|
// No salir si el usuario entró manualmente con tecla K
|
||||||
// Probabilidad de salir: 60% en cada acción → sale rápido (relación DEMO:LOGO = 6:1)
|
// Probabilidad de salir: 60% en cada acción → sale rápido (relación DEMO:LOGO = 6:1)
|
||||||
if (!logo_entered_manually_ && rand() % 100 < 60) {
|
if (!state_manager_->getLogoEnteredManually() && rand() % 100 < 60) {
|
||||||
state_manager_->exitLogoMode(true); // Volver a DEMO/DEMO_LITE
|
state_manager_->exitLogoMode(true); // Volver a DEMO/DEMO_LITE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1313,7 +1318,7 @@ void Engine::executeDemoAction(bool is_lite) {
|
|||||||
// Escenarios válidos: índices 1, 2, 3, 4, 5 (10, 100, 500, 1000, 10000 pelotas)
|
// Escenarios válidos: índices 1, 2, 3, 4, 5 (10, 100, 500, 1000, 10000 pelotas)
|
||||||
int valid_scenarios[] = {1, 2, 3, 4, 5};
|
int valid_scenarios[] = {1, 2, 3, 4, 5};
|
||||||
int new_scenario = valid_scenarios[rand() % 5];
|
int new_scenario = valid_scenarios[rand() % 5];
|
||||||
scene_manager_->changeScenario(new_scenario);
|
scene_manager_->changeScenario(new_scenario, current_mode_);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1398,7 +1403,7 @@ void Engine::executeRandomizeOnDemoStart(bool is_lite) {
|
|||||||
// 1. Escenario (excluir índices 0, 6, 7)
|
// 1. Escenario (excluir índices 0, 6, 7)
|
||||||
int valid_scenarios[] = {1, 2, 3, 4, 5};
|
int valid_scenarios[] = {1, 2, 3, 4, 5};
|
||||||
int new_scenario = valid_scenarios[rand() % 5];
|
int new_scenario = valid_scenarios[rand() % 5];
|
||||||
scene_manager_->changeScenario(new_scenario);
|
scene_manager_->changeScenario(new_scenario, current_mode_);
|
||||||
|
|
||||||
// 2. Tema (elegir entre TODOS los 15 temas)
|
// 2. Tema (elegir entre TODOS los 15 temas)
|
||||||
int random_theme_index = rand() % 15;
|
int random_theme_index = rand() % 15;
|
||||||
@@ -1463,7 +1468,7 @@ void Engine::executeEnterLogoMode(size_t ball_count) {
|
|||||||
// Verificar mínimo de pelotas
|
// Verificar mínimo de pelotas
|
||||||
if (static_cast<int>(ball_count) < LOGO_MODE_MIN_BALLS) {
|
if (static_cast<int>(ball_count) < LOGO_MODE_MIN_BALLS) {
|
||||||
// Ajustar a 5000 pelotas automáticamente
|
// Ajustar a 5000 pelotas automáticamente
|
||||||
scene_manager_->changeScenario(5); // Escenario 5000 pelotas (índice 5 en BALL_COUNT_SCENARIOS)
|
scene_manager_->changeScenario(5, current_mode_); // Escenario 5000 pelotas (índice 5 en BALL_COUNT_SCENARIOS)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Guardar estado previo (para restaurar al salir)
|
// Guardar estado previo (para restaurar al salir)
|
||||||
|
|||||||
@@ -87,6 +87,16 @@ class Engine {
|
|||||||
void executeEnterLogoMode(size_t ball_count);
|
void executeEnterLogoMode(size_t ball_count);
|
||||||
void executeExitLogoMode();
|
void executeExitLogoMode();
|
||||||
|
|
||||||
|
// === Getters públicos para UIManager (Debug HUD) ===
|
||||||
|
bool getVSyncEnabled() const { return vsync_enabled_; }
|
||||||
|
bool getFullscreenEnabled() const { return fullscreen_enabled_; }
|
||||||
|
bool getRealFullscreenEnabled() const { return real_fullscreen_enabled_; }
|
||||||
|
ScalingMode getCurrentScalingMode() const { return current_scaling_mode_; }
|
||||||
|
int getCurrentScreenWidth() const { return current_screen_width_; }
|
||||||
|
int getCurrentScreenHeight() const { return current_screen_height_; }
|
||||||
|
int getBaseScreenWidth() const { return base_screen_width_; }
|
||||||
|
int getBaseScreenHeight() const { return base_screen_height_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// === Componentes del sistema (Composición) ===
|
// === Componentes del sistema (Composición) ===
|
||||||
std::unique_ptr<InputHandler> input_handler_; // Manejo de entradas SDL
|
std::unique_ptr<InputHandler> input_handler_; // Manejo de entradas SDL
|
||||||
@@ -168,9 +178,9 @@ class Engine {
|
|||||||
float logo_target_flip_percentage_ = 0.0f; // % de flip a esperar (0.2-0.8)
|
float logo_target_flip_percentage_ = 0.0f; // % de flip a esperar (0.2-0.8)
|
||||||
int logo_current_flip_count_ = 0; // Flips observados hasta ahora
|
int logo_current_flip_count_ = 0; // Flips observados hasta ahora
|
||||||
|
|
||||||
// Control de entrada manual vs automática a LOGO MODE
|
// NOTA: logo_entered_manually_ fue eliminado de Engine (duplicado)
|
||||||
// Determina si LOGO debe salir automáticamente o esperar input del usuario
|
// Ahora se obtiene de StateManager con state_manager_->getLogoEnteredManually()
|
||||||
bool logo_entered_manually_ = false; // true si se activó con tecla K, false si automático desde DEMO
|
// Esto evita desincronización entre Engine y StateManager
|
||||||
|
|
||||||
// Estado previo antes de entrar a Logo Mode (para restaurar al salir)
|
// Estado previo antes de entrar a Logo Mode (para restaurar al salir)
|
||||||
// Guardado por executeEnterLogoMode(), restaurado por executeExitLogoMode()
|
// Guardado por executeEnterLogoMode(), restaurado por executeExitLogoMode()
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ void SceneManager::initialize(int scenario, std::shared_ptr<Texture> texture, Th
|
|||||||
theme_manager_ = theme_manager;
|
theme_manager_ = theme_manager;
|
||||||
current_ball_size_ = texture_->getWidth();
|
current_ball_size_ = texture_->getWidth();
|
||||||
|
|
||||||
// Crear bolas iniciales
|
// Crear bolas iniciales (siempre en modo PHYSICS al inicio)
|
||||||
changeScenario(scenario_);
|
changeScenario(scenario_, SimulationMode::PHYSICS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneManager::update(float delta_time) {
|
void SceneManager::update(float delta_time) {
|
||||||
@@ -33,7 +33,7 @@ void SceneManager::update(float delta_time) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneManager::changeScenario(int scenario_id) {
|
void SceneManager::changeScenario(int scenario_id, SimulationMode mode) {
|
||||||
// Guardar escenario
|
// Guardar escenario
|
||||||
scenario_ = scenario_id;
|
scenario_ = scenario_id;
|
||||||
|
|
||||||
@@ -45,14 +45,49 @@ void SceneManager::changeScenario(int scenario_id) {
|
|||||||
|
|
||||||
// Crear las bolas según el escenario
|
// Crear las bolas según el escenario
|
||||||
for (int i = 0; i < BALL_COUNT_SCENARIOS[scenario_id]; ++i) {
|
for (int i = 0; i < BALL_COUNT_SCENARIOS[scenario_id]; ++i) {
|
||||||
const int SIGN = ((rand() % 2) * 2) - 1; // Genera un signo aleatorio (+ o -)
|
float X, VX, VY;
|
||||||
|
|
||||||
// Calcular spawn zone: margen a cada lado, zona central para spawn
|
// Inicialización según SimulationMode (RULES.md líneas 23-26)
|
||||||
|
switch (mode) {
|
||||||
|
case SimulationMode::PHYSICS: {
|
||||||
|
// PHYSICS: Parte superior, 75% distribución central en X
|
||||||
|
const int SIGN = ((rand() % 2) * 2) - 1;
|
||||||
const int margin = static_cast<int>(screen_width_ * BALL_SPAWN_MARGIN);
|
const int margin = static_cast<int>(screen_width_ * BALL_SPAWN_MARGIN);
|
||||||
const int spawn_zone_width = screen_width_ - (2 * margin);
|
const int spawn_zone_width = screen_width_ - (2 * margin);
|
||||||
const float X = (rand() % spawn_zone_width) + margin; // Posición inicial en X
|
X = (rand() % spawn_zone_width) + margin;
|
||||||
const float VX = (((rand() % 20) + 10) * 0.1f) * SIGN; // Velocidad en X
|
VX = (((rand() % 20) + 10) * 0.1f) * SIGN;
|
||||||
const float VY = ((rand() % 60) - 30) * 0.1f; // Velocidad en Y
|
VY = ((rand() % 60) - 30) * 0.1f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SimulationMode::SHAPE: {
|
||||||
|
// SHAPE: Centro de pantalla, sin velocidad inicial
|
||||||
|
X = screen_width_ / 2.0f;
|
||||||
|
VX = 0.0f;
|
||||||
|
VY = 0.0f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SimulationMode::BOIDS: {
|
||||||
|
// BOIDS: Posiciones aleatorias, velocidades aleatorias
|
||||||
|
const int SIGN_X = ((rand() % 2) * 2) - 1;
|
||||||
|
const int SIGN_Y = ((rand() % 2) * 2) - 1;
|
||||||
|
X = static_cast<float>(rand() % screen_width_);
|
||||||
|
VX = (((rand() % 40) + 10) * 0.1f) * SIGN_X; // 1.0 - 5.0 px/frame
|
||||||
|
VY = (((rand() % 40) + 10) * 0.1f) * SIGN_Y;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Fallback a PHYSICS por seguridad
|
||||||
|
const int SIGN = ((rand() % 2) * 2) - 1;
|
||||||
|
const int margin = static_cast<int>(screen_width_ * BALL_SPAWN_MARGIN);
|
||||||
|
const int spawn_zone_width = screen_width_ - (2 * margin);
|
||||||
|
X = (rand() % spawn_zone_width) + margin;
|
||||||
|
VX = (((rand() % 20) + 10) * 0.1f) * SIGN;
|
||||||
|
VY = ((rand() % 60) - 30) * 0.1f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Seleccionar color de la paleta del tema actual (delegado a ThemeManager)
|
// Seleccionar color de la paleta del tema actual (delegado a ThemeManager)
|
||||||
int random_index = rand();
|
int random_index = rand();
|
||||||
|
|||||||
@@ -51,8 +51,9 @@ class SceneManager {
|
|||||||
/**
|
/**
|
||||||
* @brief Cambia el número de bolas según escenario
|
* @brief Cambia el número de bolas según escenario
|
||||||
* @param scenario_id Índice del escenario (0-7 para 10 a 50,000 bolas)
|
* @param scenario_id Índice del escenario (0-7 para 10 a 50,000 bolas)
|
||||||
|
* @param mode Modo de simulación actual (afecta inicialización)
|
||||||
*/
|
*/
|
||||||
void changeScenario(int scenario_id);
|
void changeScenario(int scenario_id, SimulationMode mode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Actualiza textura y tamaño de todas las bolas
|
* @brief Actualiza textura y tamaño de todas las bolas
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "../ball.h" // for Ball
|
#include "../ball.h" // for Ball
|
||||||
#include "../defines.h" // for TEXT_DURATION, NOTIFICATION_DURATION, AppMode, SimulationMode
|
#include "../defines.h" // for TEXT_DURATION, NOTIFICATION_DURATION, AppMode, SimulationMode
|
||||||
|
#include "../engine.h" // for Engine (info de sistema)
|
||||||
#include "../scene/scene_manager.h" // for SceneManager
|
#include "../scene/scene_manager.h" // for SceneManager
|
||||||
#include "../shapes/shape.h" // for Shape
|
#include "../shapes/shape.h" // for Shape
|
||||||
#include "../text/textrenderer.h" // for TextRenderer
|
#include "../text/textrenderer.h" // for TextRenderer
|
||||||
@@ -96,6 +97,7 @@ void UIManager::update(Uint64 current_time, float delta_time) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void UIManager::render(SDL_Renderer* renderer,
|
void UIManager::render(SDL_Renderer* renderer,
|
||||||
|
const Engine* engine,
|
||||||
const SceneManager* scene_manager,
|
const SceneManager* scene_manager,
|
||||||
SimulationMode current_mode,
|
SimulationMode current_mode,
|
||||||
AppMode current_app_mode,
|
AppMode current_app_mode,
|
||||||
@@ -115,7 +117,7 @@ void UIManager::render(SDL_Renderer* renderer,
|
|||||||
|
|
||||||
// Renderizar debug HUD si está activo
|
// Renderizar debug HUD si está activo
|
||||||
if (show_debug_) {
|
if (show_debug_) {
|
||||||
renderDebugHUD(scene_manager, current_mode, current_app_mode,
|
renderDebugHUD(engine, scene_manager, current_mode, current_app_mode,
|
||||||
active_shape, shape_convergence);
|
active_shape, shape_convergence);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,7 +169,8 @@ void UIManager::setTextObsolete(const std::string& text, int pos, int current_sc
|
|||||||
|
|
||||||
// === Métodos privados ===
|
// === Métodos privados ===
|
||||||
|
|
||||||
void UIManager::renderDebugHUD(const SceneManager* scene_manager,
|
void UIManager::renderDebugHUD(const Engine* engine,
|
||||||
|
const SceneManager* scene_manager,
|
||||||
SimulationMode current_mode,
|
SimulationMode current_mode,
|
||||||
AppMode current_app_mode,
|
AppMode current_app_mode,
|
||||||
const Shape* active_shape,
|
const Shape* active_shape,
|
||||||
@@ -175,92 +178,171 @@ void UIManager::renderDebugHUD(const SceneManager* scene_manager,
|
|||||||
// Obtener altura de línea para espaciado dinámico
|
// Obtener altura de línea para espaciado dinámico
|
||||||
int line_height = text_renderer_debug_->getTextHeight();
|
int line_height = text_renderer_debug_->getTextHeight();
|
||||||
int margin = 8; // Margen constante en píxeles físicos
|
int margin = 8; // Margen constante en píxeles físicos
|
||||||
int current_y = margin; // Y inicial en píxeles físicos
|
|
||||||
|
|
||||||
// Mostrar contador de FPS en esquina superior derecha
|
// ===========================
|
||||||
|
// COLUMNA LEFT (Sistema)
|
||||||
|
// ===========================
|
||||||
|
int left_y = margin;
|
||||||
|
|
||||||
|
// AppMode (antes estaba centrado, ahora va a la izquierda)
|
||||||
|
std::string appmode_text;
|
||||||
|
SDL_Color appmode_color = {255, 255, 255, 255}; // Blanco por defecto
|
||||||
|
|
||||||
|
if (current_app_mode == AppMode::LOGO) {
|
||||||
|
appmode_text = "AppMode: LOGO";
|
||||||
|
appmode_color = {255, 128, 0, 255}; // Naranja
|
||||||
|
} else if (current_app_mode == AppMode::DEMO) {
|
||||||
|
appmode_text = "AppMode: DEMO";
|
||||||
|
appmode_color = {255, 165, 0, 255}; // Naranja
|
||||||
|
} else if (current_app_mode == AppMode::DEMO_LITE) {
|
||||||
|
appmode_text = "AppMode: DEMO LITE";
|
||||||
|
appmode_color = {255, 200, 0, 255}; // Amarillo-naranja
|
||||||
|
} else {
|
||||||
|
appmode_text = "AppMode: SANDBOX";
|
||||||
|
appmode_color = {0, 255, 128, 255}; // Verde claro
|
||||||
|
}
|
||||||
|
text_renderer_debug_->printAbsolute(margin, left_y, appmode_text.c_str(), appmode_color);
|
||||||
|
left_y += line_height;
|
||||||
|
|
||||||
|
// SimulationMode
|
||||||
|
std::string simmode_text;
|
||||||
|
if (current_mode == SimulationMode::PHYSICS) {
|
||||||
|
simmode_text = "SimMode: PHYSICS";
|
||||||
|
} else if (current_mode == SimulationMode::SHAPE) {
|
||||||
|
if (active_shape) {
|
||||||
|
simmode_text = std::string("SimMode: SHAPE (") + active_shape->getName() + ")";
|
||||||
|
} else {
|
||||||
|
simmode_text = "SimMode: SHAPE";
|
||||||
|
}
|
||||||
|
} else if (current_mode == SimulationMode::BOIDS) {
|
||||||
|
simmode_text = "SimMode: BOIDS";
|
||||||
|
}
|
||||||
|
text_renderer_debug_->printAbsolute(margin, left_y, simmode_text.c_str(), {0, 255, 255, 255}); // Cian
|
||||||
|
left_y += line_height;
|
||||||
|
|
||||||
|
// V-Sync
|
||||||
|
text_renderer_debug_->printAbsolute(margin, left_y, vsync_text_.c_str(), {0, 255, 255, 255}); // Cian
|
||||||
|
left_y += line_height;
|
||||||
|
|
||||||
|
// Modo de escalado (INTEGER/LETTERBOX/STRETCH o WINDOWED si no está en fullscreen)
|
||||||
|
std::string scaling_text;
|
||||||
|
if (engine->getFullscreenEnabled() || engine->getRealFullscreenEnabled()) {
|
||||||
|
ScalingMode scaling = engine->getCurrentScalingMode();
|
||||||
|
if (scaling == ScalingMode::INTEGER) {
|
||||||
|
scaling_text = "Scaling: INTEGER";
|
||||||
|
} else if (scaling == ScalingMode::LETTERBOX) {
|
||||||
|
scaling_text = "Scaling: LETTERBOX";
|
||||||
|
} else if (scaling == ScalingMode::STRETCH) {
|
||||||
|
scaling_text = "Scaling: STRETCH";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
scaling_text = "Scaling: WINDOWED";
|
||||||
|
}
|
||||||
|
text_renderer_debug_->printAbsolute(margin, left_y, scaling_text.c_str(), {255, 255, 0, 255}); // Amarillo
|
||||||
|
left_y += line_height;
|
||||||
|
|
||||||
|
// Resolución física (píxeles reales de la ventana)
|
||||||
|
std::string phys_res_text = "Physical: " + std::to_string(physical_window_width_) + "x" + std::to_string(physical_window_height_);
|
||||||
|
text_renderer_debug_->printAbsolute(margin, left_y, phys_res_text.c_str(), {255, 128, 255, 255}); // Magenta claro
|
||||||
|
left_y += line_height;
|
||||||
|
|
||||||
|
// Resolución lógica (resolución interna del renderizador)
|
||||||
|
std::string logic_res_text = "Logical: " + std::to_string(engine->getCurrentScreenWidth()) + "x" + std::to_string(engine->getCurrentScreenHeight());
|
||||||
|
text_renderer_debug_->printAbsolute(margin, left_y, logic_res_text.c_str(), {255, 128, 255, 255}); // Magenta claro
|
||||||
|
left_y += line_height;
|
||||||
|
|
||||||
|
// Display refresh rate (obtener de SDL)
|
||||||
|
std::string refresh_text;
|
||||||
|
int num_displays = 0;
|
||||||
|
SDL_DisplayID* displays = SDL_GetDisplays(&num_displays);
|
||||||
|
if (displays && num_displays > 0) {
|
||||||
|
const auto* dm = SDL_GetCurrentDisplayMode(displays[0]);
|
||||||
|
if (dm) {
|
||||||
|
refresh_text = "Refresh: " + std::to_string(static_cast<int>(dm->refresh_rate)) + " Hz";
|
||||||
|
} else {
|
||||||
|
refresh_text = "Refresh: N/A";
|
||||||
|
}
|
||||||
|
SDL_free(displays);
|
||||||
|
} else {
|
||||||
|
refresh_text = "Refresh: N/A";
|
||||||
|
}
|
||||||
|
text_renderer_debug_->printAbsolute(margin, left_y, refresh_text.c_str(), {255, 255, 128, 255}); // Amarillo claro
|
||||||
|
left_y += line_height;
|
||||||
|
|
||||||
|
// Tema actual (delegado a ThemeManager)
|
||||||
|
std::string theme_text = std::string("Theme: ") + theme_manager_->getCurrentThemeNameEN();
|
||||||
|
text_renderer_debug_->printAbsolute(margin, left_y, theme_text.c_str(), {128, 255, 255, 255}); // Cian claro
|
||||||
|
left_y += line_height;
|
||||||
|
|
||||||
|
// ===========================
|
||||||
|
// COLUMNA RIGHT (Primera pelota)
|
||||||
|
// ===========================
|
||||||
|
int right_y = margin;
|
||||||
|
|
||||||
|
// FPS counter (esquina superior derecha)
|
||||||
int fps_text_width = text_renderer_debug_->getTextWidthPhysical(fps_text_.c_str());
|
int fps_text_width = text_renderer_debug_->getTextWidthPhysical(fps_text_.c_str());
|
||||||
int fps_x = physical_window_width_ - fps_text_width - margin;
|
int fps_x = physical_window_width_ - fps_text_width - margin;
|
||||||
text_renderer_debug_->printAbsolute(fps_x, current_y, fps_text_.c_str(), {255, 255, 0, 255}); // Amarillo
|
text_renderer_debug_->printAbsolute(fps_x, right_y, fps_text_.c_str(), {255, 255, 0, 255}); // Amarillo
|
||||||
|
right_y += line_height;
|
||||||
|
|
||||||
// Mostrar estado V-Sync en esquina superior izquierda
|
// Info de la primera pelota (si existe)
|
||||||
text_renderer_debug_->printAbsolute(margin, current_y, vsync_text_.c_str(), {0, 255, 255, 255}); // Cian
|
|
||||||
current_y += line_height;
|
|
||||||
|
|
||||||
// Debug: Mostrar valores de la primera pelota (si existe)
|
|
||||||
const Ball* first_ball = scene_manager->getFirstBall();
|
const Ball* first_ball = scene_manager->getFirstBall();
|
||||||
if (first_ball != nullptr) {
|
if (first_ball != nullptr) {
|
||||||
// Línea 1: Gravedad
|
// Posición X, Y
|
||||||
int grav_int = static_cast<int>(first_ball->getGravityForce());
|
SDL_FRect pos = first_ball->getPosition();
|
||||||
std::string grav_text = "Gravedad: " + std::to_string(grav_int);
|
std::string pos_text = "Pos: (" + std::to_string(static_cast<int>(pos.x)) + ", " + std::to_string(static_cast<int>(pos.y)) + ")";
|
||||||
text_renderer_debug_->printAbsolute(margin, current_y, grav_text.c_str(), {255, 0, 255, 255}); // Magenta
|
int pos_width = text_renderer_debug_->getTextWidthPhysical(pos_text.c_str());
|
||||||
current_y += line_height;
|
text_renderer_debug_->printAbsolute(physical_window_width_ - pos_width - margin, right_y, pos_text.c_str(), {255, 128, 128, 255}); // Rojo claro
|
||||||
|
right_y += line_height;
|
||||||
|
|
||||||
// Línea 2: Velocidad Y
|
// Velocidad X
|
||||||
|
int vx_int = static_cast<int>(first_ball->getVelocityX());
|
||||||
|
std::string vx_text = "VelX: " + std::to_string(vx_int);
|
||||||
|
int vx_width = text_renderer_debug_->getTextWidthPhysical(vx_text.c_str());
|
||||||
|
text_renderer_debug_->printAbsolute(physical_window_width_ - vx_width - margin, right_y, vx_text.c_str(), {128, 255, 128, 255}); // Verde claro
|
||||||
|
right_y += line_height;
|
||||||
|
|
||||||
|
// Velocidad Y
|
||||||
int vy_int = static_cast<int>(first_ball->getVelocityY());
|
int vy_int = static_cast<int>(first_ball->getVelocityY());
|
||||||
std::string vy_text = "Velocidad Y: " + std::to_string(vy_int);
|
std::string vy_text = "VelY: " + std::to_string(vy_int);
|
||||||
text_renderer_debug_->printAbsolute(margin, current_y, vy_text.c_str(), {255, 0, 255, 255}); // Magenta
|
int vy_width = text_renderer_debug_->getTextWidthPhysical(vy_text.c_str());
|
||||||
current_y += line_height;
|
text_renderer_debug_->printAbsolute(physical_window_width_ - vy_width - margin, right_y, vy_text.c_str(), {128, 255, 128, 255}); // Verde claro
|
||||||
|
right_y += line_height;
|
||||||
|
|
||||||
// Línea 3: Estado superficie
|
// Fuerza de gravedad
|
||||||
std::string surface_text = first_ball->isOnSurface() ? "Superficie: Sí" : "Superficie: No";
|
int grav_int = static_cast<int>(first_ball->getGravityForce());
|
||||||
text_renderer_debug_->printAbsolute(margin, current_y, surface_text.c_str(), {255, 0, 255, 255}); // Magenta
|
std::string grav_text = "Gravity: " + std::to_string(grav_int);
|
||||||
current_y += line_height;
|
int grav_width = text_renderer_debug_->getTextWidthPhysical(grav_text.c_str());
|
||||||
|
text_renderer_debug_->printAbsolute(physical_window_width_ - grav_width - margin, right_y, grav_text.c_str(), {255, 255, 128, 255}); // Amarillo claro
|
||||||
|
right_y += line_height;
|
||||||
|
|
||||||
// Línea 4: Coeficiente de rebote (loss)
|
// Estado superficie
|
||||||
|
std::string surface_text = first_ball->isOnSurface() ? "Surface: YES" : "Surface: NO";
|
||||||
|
int surface_width = text_renderer_debug_->getTextWidthPhysical(surface_text.c_str());
|
||||||
|
text_renderer_debug_->printAbsolute(physical_window_width_ - surface_width - margin, right_y, surface_text.c_str(), {255, 200, 128, 255}); // Naranja claro
|
||||||
|
right_y += line_height;
|
||||||
|
|
||||||
|
// Coeficiente de rebote (loss)
|
||||||
float loss_val = first_ball->getLossCoefficient();
|
float loss_val = first_ball->getLossCoefficient();
|
||||||
std::string loss_text = "Rebote: " + std::to_string(loss_val).substr(0, 4);
|
std::string loss_text = "Loss: " + std::to_string(loss_val).substr(0, 4);
|
||||||
text_renderer_debug_->printAbsolute(margin, current_y, loss_text.c_str(), {255, 0, 255, 255}); // Magenta
|
int loss_width = text_renderer_debug_->getTextWidthPhysical(loss_text.c_str());
|
||||||
current_y += line_height;
|
text_renderer_debug_->printAbsolute(physical_window_width_ - loss_width - margin, right_y, loss_text.c_str(), {255, 128, 255, 255}); // Magenta
|
||||||
|
right_y += line_height;
|
||||||
|
|
||||||
// Línea 5: Dirección de gravedad
|
// Dirección de gravedad
|
||||||
std::string gravity_dir_text = "Dirección: " + gravityDirectionToString(static_cast<int>(scene_manager->getCurrentGravity()));
|
std::string gravity_dir_text = "Dir: " + gravityDirectionToString(static_cast<int>(scene_manager->getCurrentGravity()));
|
||||||
text_renderer_debug_->printAbsolute(margin, current_y, gravity_dir_text.c_str(), {255, 255, 0, 255}); // Amarillo
|
int dir_width = text_renderer_debug_->getTextWidthPhysical(gravity_dir_text.c_str());
|
||||||
current_y += line_height;
|
text_renderer_debug_->printAbsolute(physical_window_width_ - dir_width - margin, right_y, gravity_dir_text.c_str(), {128, 255, 255, 255}); // Cian claro
|
||||||
|
right_y += line_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug: Mostrar tema actual (delegado a ThemeManager)
|
// Convergencia en modo LOGO (solo cuando está activo) - Parte inferior derecha
|
||||||
std::string theme_text = std::string("Tema: ") + theme_manager_->getCurrentThemeNameEN();
|
|
||||||
text_renderer_debug_->printAbsolute(margin, current_y, theme_text.c_str(), {255, 255, 128, 255}); // Amarillo claro
|
|
||||||
current_y += line_height;
|
|
||||||
|
|
||||||
// Debug: Mostrar modo de simulación actual
|
|
||||||
std::string mode_text;
|
|
||||||
if (current_mode == SimulationMode::PHYSICS) {
|
|
||||||
mode_text = "Modo: Física";
|
|
||||||
} else if (active_shape) {
|
|
||||||
mode_text = std::string("Modo: ") + active_shape->getName();
|
|
||||||
} else {
|
|
||||||
mode_text = "Modo: Forma";
|
|
||||||
}
|
|
||||||
text_renderer_debug_->printAbsolute(margin, current_y, mode_text.c_str(), {0, 255, 128, 255}); // Verde claro
|
|
||||||
current_y += line_height;
|
|
||||||
|
|
||||||
// Debug: Mostrar convergencia en modo LOGO (solo cuando está activo)
|
|
||||||
if (current_app_mode == AppMode::LOGO && current_mode == SimulationMode::SHAPE) {
|
if (current_app_mode == AppMode::LOGO && current_mode == SimulationMode::SHAPE) {
|
||||||
int convergence_percent = static_cast<int>(shape_convergence * 100.0f);
|
int convergence_percent = static_cast<int>(shape_convergence * 100.0f);
|
||||||
std::string convergence_text = "Convergencia: " + std::to_string(convergence_percent) + "%";
|
std::string convergence_text = "Convergence: " + std::to_string(convergence_percent) + "%";
|
||||||
text_renderer_debug_->printAbsolute(margin, current_y, convergence_text.c_str(), {255, 128, 0, 255}); // Naranja
|
int conv_width = text_renderer_debug_->getTextWidthPhysical(convergence_text.c_str());
|
||||||
current_y += line_height;
|
text_renderer_debug_->printAbsolute(physical_window_width_ - conv_width - margin, right_y, convergence_text.c_str(), {255, 128, 0, 255}); // Naranja
|
||||||
}
|
right_y += line_height;
|
||||||
|
|
||||||
// Debug: Mostrar modo DEMO/LOGO activo (siempre visible cuando debug está ON)
|
|
||||||
// FIJO en tercera fila (no se mueve con otros elementos del HUD)
|
|
||||||
int fixed_y = margin + (line_height * 2); // Tercera fila fija
|
|
||||||
if (current_app_mode == AppMode::LOGO) {
|
|
||||||
const char* logo_text = "Modo Logo";
|
|
||||||
int logo_text_width = text_renderer_debug_->getTextWidthPhysical(logo_text);
|
|
||||||
int logo_x = (physical_window_width_ - logo_text_width) / 2;
|
|
||||||
text_renderer_debug_->printAbsolute(logo_x, fixed_y, logo_text, {255, 128, 0, 255}); // Naranja
|
|
||||||
} else if (current_app_mode == AppMode::DEMO) {
|
|
||||||
const char* demo_text = "Modo Demo";
|
|
||||||
int demo_text_width = text_renderer_debug_->getTextWidthPhysical(demo_text);
|
|
||||||
int demo_x = (physical_window_width_ - demo_text_width) / 2;
|
|
||||||
text_renderer_debug_->printAbsolute(demo_x, fixed_y, demo_text, {255, 165, 0, 255}); // Naranja
|
|
||||||
} else if (current_app_mode == AppMode::DEMO_LITE) {
|
|
||||||
const char* lite_text = "Modo Demo Lite";
|
|
||||||
int lite_text_width = text_renderer_debug_->getTextWidthPhysical(lite_text);
|
|
||||||
int lite_x = (physical_window_width_ - lite_text_width) / 2;
|
|
||||||
text_renderer_debug_->printAbsolute(lite_x, fixed_y, lite_text, {255, 200, 0, 255}); // Amarillo-naranja
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ class ThemeManager;
|
|||||||
class TextRenderer;
|
class TextRenderer;
|
||||||
class Notifier;
|
class Notifier;
|
||||||
class HelpOverlay;
|
class HelpOverlay;
|
||||||
|
class Engine;
|
||||||
enum class SimulationMode;
|
enum class SimulationMode;
|
||||||
enum class AppMode;
|
enum class AppMode;
|
||||||
|
|
||||||
@@ -59,6 +60,7 @@ class UIManager {
|
|||||||
/**
|
/**
|
||||||
* @brief Renderiza todos los elementos UI
|
* @brief Renderiza todos los elementos UI
|
||||||
* @param renderer Renderizador SDL3
|
* @param renderer Renderizador SDL3
|
||||||
|
* @param engine Puntero a Engine (para info de sistema)
|
||||||
* @param scene_manager SceneManager (para info de debug)
|
* @param scene_manager SceneManager (para info de debug)
|
||||||
* @param current_mode Modo de simulación actual (PHYSICS/SHAPE)
|
* @param current_mode Modo de simulación actual (PHYSICS/SHAPE)
|
||||||
* @param current_app_mode Modo de aplicación (SANDBOX/DEMO/LOGO)
|
* @param current_app_mode Modo de aplicación (SANDBOX/DEMO/LOGO)
|
||||||
@@ -69,6 +71,7 @@ class UIManager {
|
|||||||
* @param current_screen_width Ancho lógico de pantalla (para texto centrado)
|
* @param current_screen_width Ancho lógico de pantalla (para texto centrado)
|
||||||
*/
|
*/
|
||||||
void render(SDL_Renderer* renderer,
|
void render(SDL_Renderer* renderer,
|
||||||
|
const Engine* engine,
|
||||||
const SceneManager* scene_manager,
|
const SceneManager* scene_manager,
|
||||||
SimulationMode current_mode,
|
SimulationMode current_mode,
|
||||||
AppMode current_app_mode,
|
AppMode current_app_mode,
|
||||||
@@ -136,13 +139,15 @@ class UIManager {
|
|||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* @brief Renderiza HUD de debug (solo si show_debug_ == true)
|
* @brief Renderiza HUD de debug (solo si show_debug_ == true)
|
||||||
|
* @param engine Puntero a Engine (para info de sistema)
|
||||||
* @param scene_manager SceneManager (para info de pelotas)
|
* @param scene_manager SceneManager (para info de pelotas)
|
||||||
* @param current_mode Modo de simulación (PHYSICS/SHAPE)
|
* @param current_mode Modo de simulación (PHYSICS/SHAPE)
|
||||||
* @param current_app_mode Modo de aplicación (SANDBOX/DEMO/LOGO)
|
* @param current_app_mode Modo de aplicación (SANDBOX/DEMO/LOGO)
|
||||||
* @param active_shape Figura 3D activa (puede ser nullptr)
|
* @param active_shape Figura 3D activa (puede ser nullptr)
|
||||||
* @param shape_convergence % de convergencia en LOGO mode
|
* @param shape_convergence % de convergencia en LOGO mode
|
||||||
*/
|
*/
|
||||||
void renderDebugHUD(const SceneManager* scene_manager,
|
void renderDebugHUD(const Engine* engine,
|
||||||
|
const SceneManager* scene_manager,
|
||||||
SimulationMode current_mode,
|
SimulationMode current_mode,
|
||||||
AppMode current_app_mode,
|
AppMode current_app_mode,
|
||||||
const Shape* active_shape,
|
const Shape* active_shape,
|
||||||
|
|||||||
Reference in New Issue
Block a user