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:
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "../ball.h" // for Ball
|
||||
#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 "../shapes/shape.h" // for Shape
|
||||
#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,
|
||||
const Engine* engine,
|
||||
const SceneManager* scene_manager,
|
||||
SimulationMode current_mode,
|
||||
AppMode current_app_mode,
|
||||
@@ -115,7 +117,7 @@ void UIManager::render(SDL_Renderer* renderer,
|
||||
|
||||
// Renderizar debug HUD si está activo
|
||||
if (show_debug_) {
|
||||
renderDebugHUD(scene_manager, current_mode, current_app_mode,
|
||||
renderDebugHUD(engine, scene_manager, current_mode, current_app_mode,
|
||||
active_shape, shape_convergence);
|
||||
}
|
||||
|
||||
@@ -167,7 +169,8 @@ void UIManager::setTextObsolete(const std::string& text, int pos, int current_sc
|
||||
|
||||
// === Métodos privados ===
|
||||
|
||||
void UIManager::renderDebugHUD(const SceneManager* scene_manager,
|
||||
void UIManager::renderDebugHUD(const Engine* engine,
|
||||
const SceneManager* scene_manager,
|
||||
SimulationMode current_mode,
|
||||
AppMode current_app_mode,
|
||||
const Shape* active_shape,
|
||||
@@ -175,92 +178,171 @@ void UIManager::renderDebugHUD(const SceneManager* scene_manager,
|
||||
// Obtener altura de línea para espaciado dinámico
|
||||
int line_height = text_renderer_debug_->getTextHeight();
|
||||
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_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
|
||||
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)
|
||||
// Info de la primera pelota (si existe)
|
||||
const Ball* first_ball = scene_manager->getFirstBall();
|
||||
if (first_ball != nullptr) {
|
||||
// Línea 1: Gravedad
|
||||
int grav_int = static_cast<int>(first_ball->getGravityForce());
|
||||
std::string grav_text = "Gravedad: " + std::to_string(grav_int);
|
||||
text_renderer_debug_->printAbsolute(margin, current_y, grav_text.c_str(), {255, 0, 255, 255}); // Magenta
|
||||
current_y += line_height;
|
||||
// Posición X, Y
|
||||
SDL_FRect pos = first_ball->getPosition();
|
||||
std::string pos_text = "Pos: (" + std::to_string(static_cast<int>(pos.x)) + ", " + std::to_string(static_cast<int>(pos.y)) + ")";
|
||||
int pos_width = text_renderer_debug_->getTextWidthPhysical(pos_text.c_str());
|
||||
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());
|
||||
std::string vy_text = "Velocidad Y: " + std::to_string(vy_int);
|
||||
text_renderer_debug_->printAbsolute(margin, current_y, vy_text.c_str(), {255, 0, 255, 255}); // Magenta
|
||||
current_y += line_height;
|
||||
std::string vy_text = "VelY: " + std::to_string(vy_int);
|
||||
int vy_width = text_renderer_debug_->getTextWidthPhysical(vy_text.c_str());
|
||||
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
|
||||
std::string surface_text = first_ball->isOnSurface() ? "Superficie: Sí" : "Superficie: No";
|
||||
text_renderer_debug_->printAbsolute(margin, current_y, surface_text.c_str(), {255, 0, 255, 255}); // Magenta
|
||||
current_y += line_height;
|
||||
// Fuerza de gravedad
|
||||
int grav_int = static_cast<int>(first_ball->getGravityForce());
|
||||
std::string grav_text = "Gravity: " + std::to_string(grav_int);
|
||||
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();
|
||||
std::string loss_text = "Rebote: " + std::to_string(loss_val).substr(0, 4);
|
||||
text_renderer_debug_->printAbsolute(margin, current_y, loss_text.c_str(), {255, 0, 255, 255}); // Magenta
|
||||
current_y += line_height;
|
||||
std::string loss_text = "Loss: " + std::to_string(loss_val).substr(0, 4);
|
||||
int loss_width = text_renderer_debug_->getTextWidthPhysical(loss_text.c_str());
|
||||
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
|
||||
std::string gravity_dir_text = "Dirección: " + gravityDirectionToString(static_cast<int>(scene_manager->getCurrentGravity()));
|
||||
text_renderer_debug_->printAbsolute(margin, current_y, gravity_dir_text.c_str(), {255, 255, 0, 255}); // Amarillo
|
||||
current_y += line_height;
|
||||
// Dirección de gravedad
|
||||
std::string gravity_dir_text = "Dir: " + gravityDirectionToString(static_cast<int>(scene_manager->getCurrentGravity()));
|
||||
int dir_width = text_renderer_debug_->getTextWidthPhysical(gravity_dir_text.c_str());
|
||||
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)
|
||||
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)
|
||||
// Convergencia en modo LOGO (solo cuando está activo) - Parte inferior derecha
|
||||
if (current_app_mode == AppMode::LOGO && current_mode == SimulationMode::SHAPE) {
|
||||
int convergence_percent = static_cast<int>(shape_convergence * 100.0f);
|
||||
std::string convergence_text = "Convergencia: " + std::to_string(convergence_percent) + "%";
|
||||
text_renderer_debug_->printAbsolute(margin, current_y, convergence_text.c_str(), {255, 128, 0, 255}); // Naranja
|
||||
current_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
|
||||
std::string convergence_text = "Convergence: " + std::to_string(convergence_percent) + "%";
|
||||
int conv_width = text_renderer_debug_->getTextWidthPhysical(convergence_text.c_str());
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ class ThemeManager;
|
||||
class TextRenderer;
|
||||
class Notifier;
|
||||
class HelpOverlay;
|
||||
class Engine;
|
||||
enum class SimulationMode;
|
||||
enum class AppMode;
|
||||
|
||||
@@ -59,6 +60,7 @@ class UIManager {
|
||||
/**
|
||||
* @brief Renderiza todos los elementos UI
|
||||
* @param renderer Renderizador SDL3
|
||||
* @param engine Puntero a Engine (para info de sistema)
|
||||
* @param scene_manager SceneManager (para info de debug)
|
||||
* @param current_mode Modo de simulación actual (PHYSICS/SHAPE)
|
||||
* @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)
|
||||
*/
|
||||
void render(SDL_Renderer* renderer,
|
||||
const Engine* engine,
|
||||
const SceneManager* scene_manager,
|
||||
SimulationMode current_mode,
|
||||
AppMode current_app_mode,
|
||||
@@ -136,13 +139,15 @@ class UIManager {
|
||||
private:
|
||||
/**
|
||||
* @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 current_mode Modo de simulación (PHYSICS/SHAPE)
|
||||
* @param current_app_mode Modo de aplicación (SANDBOX/DEMO/LOGO)
|
||||
* @param active_shape Figura 3D activa (puede ser nullptr)
|
||||
* @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,
|
||||
AppMode current_app_mode,
|
||||
const Shape* active_shape,
|
||||
|
||||
Reference in New Issue
Block a user