Compare commits
9 Commits
250b1a640d
...
boids_deve
| Author | SHA1 | Date | |
|---|---|---|---|
| a929346463 | |||
| c4075f68db | |||
| 399650f8da | |||
| 9b8afa1219 | |||
| 5b674c8ea6 | |||
| 7fac103c51 | |||
| bcceb94c9e | |||
| 1b3d32ba84 | |||
| 7c0a60f140 |
128
RULES.md
Normal file
128
RULES.md
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
Documento de especificaciones de ViBe3 Physics
|
||||||
|
|
||||||
|
# Codigo
|
||||||
|
* Se preferira el uso de #pragma once a #ifndef
|
||||||
|
* Se preferira el uso de C++ frente a C
|
||||||
|
* Se preferirá el uso de verisiones mas moderdas de C++ frente a las mas viejas, es decir, C++20 frente a C++17, por ejemplo
|
||||||
|
* Se preferirá el uso de smart pointers frente a new/delete y sobretodo antes que malloc/free
|
||||||
|
* Los archivos de cabecera que definan clases, colocaran primero la parte publica y luego la privada. Agruparan los metodos por categorias. Todas las variables, constantes, estructuras, enumeraciones, metodos, llevaran el comentario a la derecha
|
||||||
|
* Se respetarán las reglas definidas en los ficheros .clang-tidy y .clang-format que hay en la raíz o en las subcarpetas
|
||||||
|
|
||||||
|
# Funcionamiento
|
||||||
|
* El programa tiene modos de funcionamiento (AppMode). El funcionamiento de cada uno de ellos se describirá mas adelante. Son estados exclusivos que van automatizando cambios en el SimulationMode, Theme y Scene y serian:
|
||||||
|
* SANDBOX
|
||||||
|
* DEMO
|
||||||
|
* DEMO LITE
|
||||||
|
* LOGO
|
||||||
|
* LOGO LITE
|
||||||
|
* El progama tiene otros modos de funcionamiento (SimulationMode). El funcionamiento de cada uno de ellos se describirá mas adelante. Son estados exclusivos:
|
||||||
|
* PHYISICS
|
||||||
|
* FIGURE
|
||||||
|
* BOIDS
|
||||||
|
* El programa tiene un gestor de temas (Theme) que cambia los colores de lo que se ve en pantalla. Hay temas estáticos y dinamicos. El cambio de tema se realiza mediante LERP y no afecta en nada ni al AppMode ni al SimulationMode, es decir, no modifica sus estados.
|
||||||
|
* El programa tiene escenarios (Scene). Cada escena tiene un numero de pelotas. Cuando se cambia el escenario, se elimina el vector de pelotas y se crea uno nuevo. En funcion del SimulationMode actual se inicializan las pelotas de manera distinta:
|
||||||
|
* PHYSICS: Se crean todas las pelotas cerca de la parte superior de la pantalla distribuidas en el 75% central del eje X (es como está ahora)
|
||||||
|
* FIGURE: Se crean todas las pelotas en el punto central de la pantalla
|
||||||
|
* BOIDS: Se crean todas las pelotas en posiciones al azar de la pantalla con velocidades y direcciones aleatorias
|
||||||
|
* El cambio de SimulationMode ha de preservar la inercia (velocidad, aceleracion, direccion) de cada pelota. El cambio se produce tanto de forma manual (pulsacion de una tecla por el usuario) como de manera automatica (cualquier AppMode que no sea SANDBOX)
|
||||||
|
* PHYSICS a FIGURE:
|
||||||
|
* Pulsando la tecla de la figura correspondiente
|
||||||
|
* Pulsando la tecla F (ultima figura seleccionada)
|
||||||
|
* PHYSICS a BOIDS:
|
||||||
|
* Pulsando la tecla B
|
||||||
|
* FIGURE a PHYSICS:
|
||||||
|
* Pulsando los cursores: Gravedad ON en la direccion del cursor
|
||||||
|
* Pulsando la tecla G: Gravedad OFF
|
||||||
|
* Pulsando la tecla F: Ultima gravedad seleccionada (direccion o OFF)
|
||||||
|
* FIGURE a BOIDS:
|
||||||
|
* Pulsando la tecla B
|
||||||
|
* BOIDS a PHYSICS:
|
||||||
|
* Pulsando la tecla G: Gravedad OFF
|
||||||
|
* Pulsando los cursores: Gravedad ON en la direccion del cursor
|
||||||
|
* BOIDS a FIGURE:
|
||||||
|
* Pulsando la tecla de la figura
|
||||||
|
* Pulsando la tecla F (ultima figura)
|
||||||
|
|
||||||
|
# AppMode
|
||||||
|
* SANDBOX
|
||||||
|
* No hay ningun automatismo. El usuario va pulsando teclas para ejecutar acciones.
|
||||||
|
* Si pulsa una de estas teclas, cambia de modo:
|
||||||
|
* D: DEMO
|
||||||
|
* L: DEMO LITE
|
||||||
|
* K: LOGO
|
||||||
|
* DEMO
|
||||||
|
* En el modo DEMO el programa va cambiando el SimulationMode de manera automatica (como está ahora es correcto)
|
||||||
|
* Se inicializa con un Theme al azar, Scene al azar, SimulationMode al azar. Restringido FIGURE->PNG_SHAPE
|
||||||
|
* Va cambiando de Theme
|
||||||
|
* Va cambiando de Scene
|
||||||
|
* Cambia la escala de la Figure
|
||||||
|
* Cambia el Sprite de las pelotas
|
||||||
|
* NO PUEDE cambiar a la figura PNG_SHAPE
|
||||||
|
* Eventualmente puede cambiar de manera automatica a LOGO LITE, sin restricciones
|
||||||
|
* El usuario puede cambiar el SimulationMode, el Theme o el Scene. Esto no hace que se salga del modo DEMO
|
||||||
|
* El usuario puede cambiar de AppMode pulsando:
|
||||||
|
* D: SANDBOX
|
||||||
|
* L: DEMO LITE
|
||||||
|
* K: LOGO
|
||||||
|
* DEMO LITE
|
||||||
|
* En el modo DEMO el programa va cambiando el SimulationMode de manera automatica (como está ahora es correcto)
|
||||||
|
* Se inicializa con un Theme al azar, Scene al azar, SimulationMode al azar. Restringido FIGURE->PNG_SHAPE
|
||||||
|
* Este modo es exactamente igual a DEMO pero NO PUEDE:
|
||||||
|
* Cambiar de Scene
|
||||||
|
* Cambiar de Theme
|
||||||
|
* Cambiar el Sprite de las pelotas
|
||||||
|
* Eventualmente puede cambiar de manera automatica a LOGO LITE, sin restricciones
|
||||||
|
* NO PUEDE cambiar a la figura PNG_SHAPE
|
||||||
|
* El usuario puede cambiar el SimulationMode, el Theme o el Scene. Esto no hace que se salga del modo DEMO LITE
|
||||||
|
* El usuario puede cambiar de AppMode pulsando:
|
||||||
|
* D: DEMO
|
||||||
|
* L: SANDBOX
|
||||||
|
* K: LOGO
|
||||||
|
* LOGO
|
||||||
|
* Se inicializa con la Scene de 5.000 pelotas, con el tamaño de Sprite->Small, con SimulationMode en FIGURE->PNG_SHAPE, con un tema al azar de los permitidos
|
||||||
|
* No cambia de Scene
|
||||||
|
* No cambia el tamaño de Sprite
|
||||||
|
* No cambia la escala de FIGURE
|
||||||
|
* Los temas permitidos son MONOCROMO, LAVANDA, CARMESI, ESMERALDA o cualquiera de los temas dinamicos
|
||||||
|
* En este modo SOLO aparece la figura PNG_SHAPE
|
||||||
|
* Solo cambiara a los temas permitidos
|
||||||
|
* Cambia el SimulationMode de PHYSICS a FIGURE (como hace ahora) pero no a BOIDS. BOIDS prohibido
|
||||||
|
* El usuario puede cambiar el SimulationMode, el Theme o el Scene. Esto no hace que se salga del modo LOGO. Incluso puede poner un Theme no permitido o otro Scene.
|
||||||
|
* El automatismo no cambia nunca de Theme así que se mantiene el del usuario.
|
||||||
|
* El automatismo no cambia nunca de Scene asi que se mantiene el del usuario.
|
||||||
|
* El usuario puede cambiar de AppMode pulsando:
|
||||||
|
* D: DEMO
|
||||||
|
* L: DEMO LITE
|
||||||
|
* K: SANDBOX
|
||||||
|
* B: SANDBOX->BOIDS
|
||||||
|
* LOGO LITE
|
||||||
|
* Este modo es exactamente igual al modo LOGO pero con unas pequeñas diferencias:
|
||||||
|
* Solo se accede a el de manera automatica, el usuario no puede invocarlo. No hay tecla
|
||||||
|
* Como se accede de manera automatica solo se puede llegar a él desde DEMO o DEMO LITE. Hay que guardar el estado en el que se encontraba AppMode, EngindeMode, Scene, Theme, Sprite, Scale... etc
|
||||||
|
* Este modo tiene una muy alta probabilidad de terminar, volviendo al estado anterior desde donde se invocó.
|
||||||
|
* El usuario puede cambiar de AppMode pulsando:
|
||||||
|
* D: Si el modo anterior era DEMO -> SANDBOX, else -> DEMO)
|
||||||
|
* L: Si el modo anterior era DEMO LITE -> SANDBOX, else -> DEMO LITE)
|
||||||
|
* K: LOGO
|
||||||
|
* B: SANDBOX->BOIDS
|
||||||
|
|
||||||
|
|
||||||
|
# Debug Hud
|
||||||
|
* En el debug hud hay que añadir que se vea SIEMPRE el AppMode (actualmente aparece centrado, hay que ponerlo a la izquierda) y no solo cietos AppModes
|
||||||
|
* Tiene que aparecer tambien el SimulationMode
|
||||||
|
* El modo de Vsync
|
||||||
|
* El modo de escalado entero, stretched, ventana
|
||||||
|
* la resolucion fisica
|
||||||
|
* la resolucion logica
|
||||||
|
* el refresco del panel
|
||||||
|
* El resto de cosas que salen
|
||||||
|
|
||||||
|
# Ventana de ayuda
|
||||||
|
* La ventana de ayuda actualmente es cuadrada
|
||||||
|
* Esa es la anchura minima que ha de tener
|
||||||
|
* Hay que ver cual es la linea mas larga, multiplicarla por el numero de columnas, añadirle los paddings y que ese sea el nuevo ancho
|
||||||
|
* Actualmente se renderiza a cada frame. El rendimiento cae de los 1200 frames por segundo a 200 frames por segundo. Habria que renderizarla a una textura o algo. El problema es que el cambio de Theme con LERP afecta a los colores de la ventana. Hay que investigar qué se puede hacer.
|
||||||
|
|
||||||
|
# Bugs actuales
|
||||||
|
* En el modo LOGO, si se pulsa un cursor, se activa la gravedad y deja de funcionar los automatismos. Incluso he llegado a ver como sale solo del modo LOGO sin pulsar nada
|
||||||
|
* En el modo BOIDS, pulsar la G activa la gravedad. La G deberia pasar al modo PHYSICS con la gravedad en OFF y que las pelotas mantuvieran el momento/inercia
|
||||||
@@ -744,6 +744,12 @@ void Engine::toggleFullscreen() {
|
|||||||
fullscreen_enabled_ = !fullscreen_enabled_;
|
fullscreen_enabled_ = !fullscreen_enabled_;
|
||||||
SDL_SetWindowFullscreen(window_, fullscreen_enabled_);
|
SDL_SetWindowFullscreen(window_, fullscreen_enabled_);
|
||||||
|
|
||||||
|
// Si acabamos de salir de fullscreen, restaurar tamaño de ventana
|
||||||
|
if (!fullscreen_enabled_) {
|
||||||
|
SDL_SetWindowSize(window_, base_screen_width_ * current_window_zoom_, base_screen_height_ * current_window_zoom_);
|
||||||
|
SDL_SetWindowPosition(window_, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
|
||||||
|
}
|
||||||
|
|
||||||
// Actualizar dimensiones físicas después del cambio
|
// Actualizar dimensiones físicas después del cambio
|
||||||
updatePhysicalWindowSize();
|
updatePhysicalWindowSize();
|
||||||
}
|
}
|
||||||
@@ -784,6 +790,17 @@ void Engine::toggleRealFullscreen() {
|
|||||||
|
|
||||||
// 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_);
|
||||||
|
|
||||||
|
// Si estamos en modo SHAPE, regenerar la figura con nuevas dimensiones
|
||||||
|
if (current_mode_ == SimulationMode::SHAPE) {
|
||||||
|
generateShape(); // Regenerar figura con nuevas dimensiones de pantalla
|
||||||
|
|
||||||
|
// Activar atracción física en las bolas nuevas (crítico tras changeScenario)
|
||||||
|
auto& balls = scene_manager_->getBallsMutable();
|
||||||
|
for (auto& ball : balls) {
|
||||||
|
ball->enableShapeAttraction(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SDL_free(displays);
|
SDL_free(displays);
|
||||||
}
|
}
|
||||||
@@ -806,6 +823,17 @@ 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(), current_mode_);
|
scene_manager_->changeScenario(scene_manager_->getCurrentScenario(), current_mode_);
|
||||||
|
|
||||||
|
// Si estamos en modo SHAPE, regenerar la figura con nuevas dimensiones
|
||||||
|
if (current_mode_ == SimulationMode::SHAPE) {
|
||||||
|
generateShape(); // Regenerar figura con nuevas dimensiones de pantalla
|
||||||
|
|
||||||
|
// Activar atracción física en las bolas nuevas (crítico tras changeScenario)
|
||||||
|
auto& balls = scene_manager_->getBallsMutable();
|
||||||
|
for (auto& ball : balls) {
|
||||||
|
ball->enableShapeAttraction(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ HelpOverlay::HelpOverlay()
|
|||||||
box_height_(0),
|
box_height_(0),
|
||||||
box_x_(0),
|
box_x_(0),
|
||||||
box_y_(0),
|
box_y_(0),
|
||||||
|
column1_width_(0),
|
||||||
|
column2_width_(0),
|
||||||
cached_texture_(nullptr),
|
cached_texture_(nullptr),
|
||||||
last_category_color_({0, 0, 0, 255}),
|
last_category_color_({0, 0, 0, 255}),
|
||||||
last_content_color_({0, 0, 0, 255}),
|
last_content_color_({0, 0, 0, 255}),
|
||||||
@@ -84,6 +86,13 @@ HelpOverlay::~HelpOverlay() {
|
|||||||
delete text_renderer_;
|
delete text_renderer_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HelpOverlay::toggle() {
|
||||||
|
visible_ = !visible_;
|
||||||
|
SDL_Log("HelpOverlay::toggle() - visible=%s, box_pos=(%d,%d), box_size=%dx%d, physical=%dx%d",
|
||||||
|
visible_ ? "TRUE" : "FALSE", box_x_, box_y_, box_width_, box_height_,
|
||||||
|
physical_width_, physical_height_);
|
||||||
|
}
|
||||||
|
|
||||||
void HelpOverlay::initialize(SDL_Renderer* renderer, ThemeManager* theme_mgr, int physical_width, int physical_height, int font_size) {
|
void HelpOverlay::initialize(SDL_Renderer* renderer, ThemeManager* theme_mgr, int physical_width, int physical_height, int font_size) {
|
||||||
renderer_ = renderer;
|
renderer_ = renderer;
|
||||||
theme_mgr_ = theme_mgr;
|
theme_mgr_ = theme_mgr;
|
||||||
@@ -94,7 +103,12 @@ void HelpOverlay::initialize(SDL_Renderer* renderer, ThemeManager* theme_mgr, in
|
|||||||
text_renderer_ = new TextRenderer();
|
text_renderer_ = new TextRenderer();
|
||||||
text_renderer_->init(renderer, "data/fonts/FunnelSans-Regular.ttf", font_size, true);
|
text_renderer_->init(renderer, "data/fonts/FunnelSans-Regular.ttf", font_size, true);
|
||||||
|
|
||||||
|
SDL_Log("HelpOverlay::initialize() - physical=%dx%d, font_size=%d", physical_width, physical_height, font_size);
|
||||||
|
|
||||||
calculateBoxDimensions();
|
calculateBoxDimensions();
|
||||||
|
|
||||||
|
SDL_Log("HelpOverlay::initialize() - AFTER calculateBoxDimensions: box_pos=(%d,%d), box_size=%dx%d",
|
||||||
|
box_x_, box_y_, box_width_, box_height_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HelpOverlay::updatePhysicalWindowSize(int physical_width, int physical_height) {
|
void HelpOverlay::updatePhysicalWindowSize(int physical_width, int physical_height) {
|
||||||
@@ -112,11 +126,37 @@ void HelpOverlay::reinitializeFontSize(int new_font_size) {
|
|||||||
// Reinicializar text renderer con nuevo tamaño
|
// Reinicializar text renderer con nuevo tamaño
|
||||||
text_renderer_->reinitialize(new_font_size);
|
text_renderer_->reinitialize(new_font_size);
|
||||||
|
|
||||||
// Recalcular dimensiones del box (el texto ahora tiene distinto tamaño)
|
// NOTA: NO recalcular dimensiones aquí porque physical_width_ y physical_height_
|
||||||
|
// pueden tener valores antiguos. updatePhysicalWindowSize() se llamará después
|
||||||
|
// con las dimensiones correctas y recalculará todo apropiadamente.
|
||||||
|
|
||||||
|
// Marcar textura para regeneración completa
|
||||||
|
texture_needs_rebuild_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelpOverlay::updateAll(int font_size, int physical_width, int physical_height) {
|
||||||
|
SDL_Log("HelpOverlay::updateAll() - INPUT: font_size=%d, physical=%dx%d",
|
||||||
|
font_size, physical_width, physical_height);
|
||||||
|
SDL_Log("HelpOverlay::updateAll() - BEFORE: box_pos=(%d,%d), box_size=%dx%d",
|
||||||
|
box_x_, box_y_, box_width_, box_height_);
|
||||||
|
|
||||||
|
// Actualizar dimensiones físicas PRIMERO
|
||||||
|
physical_width_ = physical_width;
|
||||||
|
physical_height_ = physical_height;
|
||||||
|
|
||||||
|
// Reinicializar text renderer con nuevo tamaño (si cambió)
|
||||||
|
if (text_renderer_) {
|
||||||
|
text_renderer_->reinitialize(font_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recalcular dimensiones del box con nuevo font y nuevas dimensiones
|
||||||
calculateBoxDimensions();
|
calculateBoxDimensions();
|
||||||
|
|
||||||
// Marcar textura para regeneración completa
|
// Marcar textura para regeneración completa
|
||||||
texture_needs_rebuild_ = true;
|
texture_needs_rebuild_ = true;
|
||||||
|
|
||||||
|
SDL_Log("HelpOverlay::updateAll() - AFTER: box_pos=(%d,%d), box_size=%dx%d",
|
||||||
|
box_x_, box_y_, box_width_, box_height_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HelpOverlay::calculateTextDimensions(int& max_width, int& total_height) {
|
void HelpOverlay::calculateTextDimensions(int& max_width, int& total_height) {
|
||||||
@@ -141,15 +181,22 @@ void HelpOverlay::calculateTextDimensions(int& max_width, int& total_height) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Separador vacío o encabezado
|
// Separador vacío (no tiene key ni description)
|
||||||
if (binding.description[0] == '\0') {
|
if (binding.key[0] == '\0') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calcular ancho de esta línea: key + espacio + description
|
int line_width = 0;
|
||||||
|
|
||||||
|
if (binding.description[0] == '\0') {
|
||||||
|
// Es un encabezado (solo tiene key, sin description)
|
||||||
|
line_width = text_renderer_->getTextWidthPhysical(binding.key);
|
||||||
|
} else {
|
||||||
|
// Es una línea normal con key + description
|
||||||
int key_width = text_renderer_->getTextWidthPhysical(binding.key);
|
int key_width = text_renderer_->getTextWidthPhysical(binding.key);
|
||||||
int desc_width = text_renderer_->getTextWidthPhysical(binding.description);
|
int desc_width = text_renderer_->getTextWidthPhysical(binding.description);
|
||||||
int line_width = key_width + 10 + desc_width; // 10px de separación
|
line_width = key_width + 10 + desc_width; // 10px de separación
|
||||||
|
}
|
||||||
|
|
||||||
// Actualizar máximo de columna correspondiente
|
// Actualizar máximo de columna correspondiente
|
||||||
if (current_column == 0) {
|
if (current_column == 0) {
|
||||||
@@ -159,31 +206,57 @@ void HelpOverlay::calculateTextDimensions(int& max_width, int& total_height) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Almacenar anchos de columnas en miembros para uso posterior
|
||||||
|
column1_width_ = max_col1_width;
|
||||||
|
column2_width_ = max_col2_width;
|
||||||
|
|
||||||
// Ancho total: 2 columnas + 3 paddings (izq, medio, der)
|
// Ancho total: 2 columnas + 3 paddings (izq, medio, der)
|
||||||
max_width = max_col1_width + max_col2_width + padding * 3;
|
max_width = max_col1_width + max_col2_width + padding * 3;
|
||||||
|
|
||||||
// Altura: contar líneas y calcular
|
// Altura: contar líneas REALES en cada columna
|
||||||
int num_lines = 0;
|
int col1_lines = 0;
|
||||||
|
int col2_lines = 0;
|
||||||
|
current_column = 0;
|
||||||
|
|
||||||
for (const auto& binding : key_bindings_) {
|
for (const auto& binding : key_bindings_) {
|
||||||
if (strcmp(binding.key, "[new_col]") != 0) {
|
// Cambio de columna
|
||||||
num_lines++;
|
if (strcmp(binding.key, "[new_col]") == 0) {
|
||||||
|
current_column = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Separador vacío no cuenta como línea
|
||||||
|
if (binding.key[0] == '\0') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contar línea (ya sea encabezado o contenido)
|
||||||
|
if (current_column == 0) {
|
||||||
|
col1_lines++;
|
||||||
|
} else {
|
||||||
|
col2_lines++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Altura: título + espacio + líneas de contenido
|
|
||||||
total_height = line_height * 2 + (num_lines / 2 + 2) * line_height + padding * 2;
|
// Usar la columna más larga para calcular altura
|
||||||
|
int max_column_lines = std::max(col1_lines, col2_lines);
|
||||||
|
|
||||||
|
// Altura: título (2 líneas) + contenido + padding superior e inferior
|
||||||
|
total_height = line_height * 2 + max_column_lines * line_height + padding * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HelpOverlay::calculateBoxDimensions() {
|
void HelpOverlay::calculateBoxDimensions() {
|
||||||
|
SDL_Log("HelpOverlay::calculateBoxDimensions() START - physical=%dx%d", physical_width_, physical_height_);
|
||||||
|
|
||||||
// Calcular dimensiones necesarias según el texto
|
// Calcular dimensiones necesarias según el texto
|
||||||
int text_width, text_height;
|
int text_width, text_height;
|
||||||
calculateTextDimensions(text_width, text_height);
|
calculateTextDimensions(text_width, text_height);
|
||||||
|
|
||||||
// Ancho mínimo: 90% de dimensión menor (como antes, para compatibilidad)
|
SDL_Log("HelpOverlay::calculateBoxDimensions() - text_width=%d, text_height=%d, col1_width=%d, col2_width=%d",
|
||||||
int min_dimension = std::min(physical_width_, physical_height_);
|
text_width, text_height, column1_width_, column2_width_);
|
||||||
int min_width = static_cast<int>(min_dimension * 0.9f);
|
|
||||||
|
|
||||||
// Usar el mayor entre ancho calculado y ancho mínimo
|
// Usar directamente el ancho y altura calculados según el contenido
|
||||||
box_width_ = std::max(text_width, min_width);
|
box_width_ = text_width;
|
||||||
|
|
||||||
// Altura: 90% de altura física o altura calculada, el que sea menor
|
// Altura: 90% de altura física o altura calculada, el que sea menor
|
||||||
int max_height = static_cast<int>(physical_height_ * 0.9f);
|
int max_height = static_cast<int>(physical_height_ * 0.9f);
|
||||||
@@ -192,11 +265,17 @@ void HelpOverlay::calculateBoxDimensions() {
|
|||||||
// Centrar en pantalla
|
// Centrar en pantalla
|
||||||
box_x_ = (physical_width_ - box_width_) / 2;
|
box_x_ = (physical_width_ - box_width_) / 2;
|
||||||
box_y_ = (physical_height_ - box_height_) / 2;
|
box_y_ = (physical_height_ - box_height_) / 2;
|
||||||
|
|
||||||
|
SDL_Log("HelpOverlay::calculateBoxDimensions() END - box_pos=(%d,%d), box_size=%dx%d, max_height=%d",
|
||||||
|
box_x_, box_y_, box_width_, box_height_, max_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HelpOverlay::rebuildCachedTexture() {
|
void HelpOverlay::rebuildCachedTexture() {
|
||||||
if (!renderer_ || !theme_mgr_ || !text_renderer_) return;
|
if (!renderer_ || !theme_mgr_ || !text_renderer_) return;
|
||||||
|
|
||||||
|
SDL_Log("HelpOverlay::rebuildCachedTexture() - Regenerando textura: box_size=%dx%d, box_pos=(%d,%d)",
|
||||||
|
box_width_, box_height_, box_x_, box_y_);
|
||||||
|
|
||||||
// Destruir textura anterior si existe
|
// Destruir textura anterior si existe
|
||||||
if (cached_texture_) {
|
if (cached_texture_) {
|
||||||
SDL_DestroyTexture(cached_texture_);
|
SDL_DestroyTexture(cached_texture_);
|
||||||
@@ -279,10 +358,9 @@ void HelpOverlay::rebuildCachedTexture() {
|
|||||||
last_content_color_ = content_color;
|
last_content_color_ = content_color;
|
||||||
last_bg_color_ = {static_cast<Uint8>(notif_bg_r), static_cast<Uint8>(notif_bg_g), static_cast<Uint8>(notif_bg_b), 255};
|
last_bg_color_ = {static_cast<Uint8>(notif_bg_r), static_cast<Uint8>(notif_bg_g), static_cast<Uint8>(notif_bg_b), 255};
|
||||||
|
|
||||||
// Configuración de espaciado (misma que renderHelpText())
|
// Configuración de espaciado
|
||||||
int line_height = text_renderer_->getTextHeight();
|
int line_height = text_renderer_->getTextHeight();
|
||||||
int padding = 25;
|
int padding = 25;
|
||||||
int column_width = (box_width_ - padding * 3) / 2;
|
|
||||||
|
|
||||||
int current_x = padding; // Coordenadas relativas a la textura (0,0)
|
int current_x = padding; // Coordenadas relativas a la textura (0,0)
|
||||||
int current_y = padding;
|
int current_y = padding;
|
||||||
@@ -301,12 +379,27 @@ void HelpOverlay::rebuildCachedTexture() {
|
|||||||
if (strcmp(binding.key, "[new_col]") == 0 && binding.description[0] == '\0') {
|
if (strcmp(binding.key, "[new_col]") == 0 && binding.description[0] == '\0') {
|
||||||
if (current_column == 0) {
|
if (current_column == 0) {
|
||||||
current_column = 1;
|
current_column = 1;
|
||||||
current_x = padding + column_width + padding;
|
current_x = padding + column1_width_ + padding; // Usar ancho real de columna 1
|
||||||
current_y = content_start_y;
|
current_y = content_start_y;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CHECK PADDING INFERIOR ANTES de escribir la línea (AMBAS COLUMNAS)
|
||||||
|
// Verificar si la PRÓXIMA línea cabrá dentro del box con padding inferior
|
||||||
|
if (current_y + line_height >= box_height_ - padding) {
|
||||||
|
if (current_column == 0) {
|
||||||
|
// Columna 0 llena: cambiar a columna 1
|
||||||
|
current_column = 1;
|
||||||
|
current_x = padding + column1_width_ + padding;
|
||||||
|
current_y = content_start_y;
|
||||||
|
} else {
|
||||||
|
// Columna 1 llena: omitir resto de texto (no cabe)
|
||||||
|
// Preferible omitir que sobresalir del overlay
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (binding.description[0] == '\0') {
|
if (binding.description[0] == '\0') {
|
||||||
text_renderer_->printAbsolute(current_x, current_y, binding.key, category_color);
|
text_renderer_->printAbsolute(current_x, current_y, binding.key, category_color);
|
||||||
current_y += line_height + 2;
|
current_y += line_height + 2;
|
||||||
@@ -318,12 +411,6 @@ void HelpOverlay::rebuildCachedTexture() {
|
|||||||
text_renderer_->printAbsolute(current_x + key_width + 10, current_y, binding.description, content_color);
|
text_renderer_->printAbsolute(current_x + key_width + 10, current_y, binding.description, content_color);
|
||||||
|
|
||||||
current_y += line_height;
|
current_y += line_height;
|
||||||
|
|
||||||
if (current_y > box_height_ - padding && current_column == 0) {
|
|
||||||
current_column = 1;
|
|
||||||
current_x = padding + column_width + padding;
|
|
||||||
current_y = content_start_y;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restaurar render target original
|
// Restaurar render target original
|
||||||
@@ -374,10 +461,23 @@ void HelpOverlay::render(SDL_Renderer* renderer) {
|
|||||||
// CRÍTICO: Habilitar alpha blending para que la transparencia funcione
|
// CRÍTICO: Habilitar alpha blending para que la transparencia funcione
|
||||||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
|
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
|
||||||
|
|
||||||
// Renderizar la textura cacheada en la posición del overlay
|
// Obtener viewport actual (en modo letterbox F3 tiene offset para centrar imagen)
|
||||||
|
SDL_Rect viewport;
|
||||||
|
SDL_GetRenderViewport(renderer, &viewport);
|
||||||
|
|
||||||
|
// Calcular posición centrada dentro del VIEWPORT, no de la pantalla física
|
||||||
|
// viewport.w y viewport.h son las dimensiones del área visible
|
||||||
|
// viewport.x y viewport.y son el offset de las barras negras
|
||||||
|
int centered_x = viewport.x + (viewport.w - box_width_) / 2;
|
||||||
|
int centered_y = viewport.y + (viewport.h - box_height_) / 2;
|
||||||
|
|
||||||
|
SDL_Log("HelpOverlay::render() - viewport=(%d,%d,%dx%d), centered_pos=(%d,%d), box_size=%dx%d",
|
||||||
|
viewport.x, viewport.y, viewport.w, viewport.h, centered_x, centered_y, box_width_, box_height_);
|
||||||
|
|
||||||
|
// Renderizar la textura cacheada centrada en el viewport
|
||||||
SDL_FRect dest_rect;
|
SDL_FRect dest_rect;
|
||||||
dest_rect.x = static_cast<float>(box_x_);
|
dest_rect.x = static_cast<float>(centered_x);
|
||||||
dest_rect.y = static_cast<float>(box_y_);
|
dest_rect.y = static_cast<float>(centered_y);
|
||||||
dest_rect.w = static_cast<float>(box_width_);
|
dest_rect.w = static_cast<float>(box_width_);
|
||||||
dest_rect.h = static_cast<float>(box_height_);
|
dest_rect.h = static_cast<float>(box_height_);
|
||||||
|
|
||||||
|
|||||||
@@ -41,10 +41,18 @@ class HelpOverlay {
|
|||||||
*/
|
*/
|
||||||
void reinitializeFontSize(int new_font_size);
|
void reinitializeFontSize(int new_font_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Actualiza font size Y dimensiones físicas de forma atómica
|
||||||
|
* @param font_size Tamaño de fuente actual
|
||||||
|
* @param physical_width Nueva anchura física
|
||||||
|
* @param physical_height Nueva altura física
|
||||||
|
*/
|
||||||
|
void updateAll(int font_size, int physical_width, int physical_height);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Toggle visibilidad del overlay
|
* @brief Toggle visibilidad del overlay
|
||||||
*/
|
*/
|
||||||
void toggle() { visible_ = !visible_; }
|
void toggle();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Consulta si el overlay está visible
|
* @brief Consulta si el overlay está visible
|
||||||
@@ -65,6 +73,10 @@ class HelpOverlay {
|
|||||||
int box_x_;
|
int box_x_;
|
||||||
int box_y_;
|
int box_y_;
|
||||||
|
|
||||||
|
// Anchos individuales de cada columna (para evitar solapamiento)
|
||||||
|
int column1_width_;
|
||||||
|
int column2_width_;
|
||||||
|
|
||||||
// Sistema de caché para optimización de rendimiento
|
// Sistema de caché para optimización de rendimiento
|
||||||
SDL_Texture* cached_texture_; // Textura cacheada del overlay completo
|
SDL_Texture* cached_texture_; // Textura cacheada del overlay completo
|
||||||
SDL_Color last_category_color_; // Último color de categorías renderizado
|
SDL_Color last_category_color_; // Último color de categorías renderizado
|
||||||
|
|||||||
@@ -5,6 +5,31 @@
|
|||||||
#include "../utils/easing_functions.h"
|
#include "../utils/easing_functions.h"
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// HELPER: Obtener viewport en coordenadas físicas (no lógicas)
|
||||||
|
// ============================================================================
|
||||||
|
// SDL_GetRenderViewport() devuelve coordenadas LÓGICAS cuando hay presentación
|
||||||
|
// lógica activa. Para obtener coordenadas FÍSICAS, necesitamos deshabilitar
|
||||||
|
// temporalmente la presentación lógica.
|
||||||
|
static SDL_Rect getPhysicalViewport(SDL_Renderer* renderer) {
|
||||||
|
// Guardar estado actual de presentación lógica
|
||||||
|
int logical_w = 0, logical_h = 0;
|
||||||
|
SDL_RendererLogicalPresentation presentation_mode;
|
||||||
|
SDL_GetRenderLogicalPresentation(renderer, &logical_w, &logical_h, &presentation_mode);
|
||||||
|
|
||||||
|
// Deshabilitar presentación lógica temporalmente
|
||||||
|
SDL_SetRenderLogicalPresentation(renderer, 0, 0, SDL_LOGICAL_PRESENTATION_DISABLED);
|
||||||
|
|
||||||
|
// Obtener viewport en coordenadas físicas (píxeles reales)
|
||||||
|
SDL_Rect physical_viewport;
|
||||||
|
SDL_GetRenderViewport(renderer, &physical_viewport);
|
||||||
|
|
||||||
|
// Restaurar presentación lógica
|
||||||
|
SDL_SetRenderLogicalPresentation(renderer, logical_w, logical_h, presentation_mode);
|
||||||
|
|
||||||
|
return physical_viewport;
|
||||||
|
}
|
||||||
|
|
||||||
Notifier::Notifier()
|
Notifier::Notifier()
|
||||||
: renderer_(nullptr)
|
: renderer_(nullptr)
|
||||||
, text_renderer_(nullptr)
|
, text_renderer_(nullptr)
|
||||||
@@ -159,10 +184,14 @@ void Notifier::render() {
|
|||||||
int bg_width = text_width + (NOTIFICATION_PADDING * 2);
|
int bg_width = text_width + (NOTIFICATION_PADDING * 2);
|
||||||
int bg_height = text_height + (NOTIFICATION_PADDING * 2);
|
int bg_height = text_height + (NOTIFICATION_PADDING * 2);
|
||||||
|
|
||||||
// Centrar en la ventana FÍSICA (no usar viewport lógico)
|
// Obtener viewport FÍSICO (píxeles reales, no lógicos)
|
||||||
// CRÍTICO: Como renderizamos en píxeles físicos absolutos (bypass de presentación lógica),
|
// CRÍTICO: En F3, SDL_GetRenderViewport() devuelve coordenadas LÓGICAS,
|
||||||
// debemos centrar usando dimensiones físicas, no el viewport lógico de SDL
|
// pero printAbsolute() trabaja en píxeles FÍSICOS. Usar helper para obtener
|
||||||
int x = (window_width_ / 2) - (bg_width / 2);
|
// viewport en coordenadas físicas.
|
||||||
|
SDL_Rect physical_viewport = getPhysicalViewport(renderer_);
|
||||||
|
|
||||||
|
// Centrar en el viewport físico (coordenadas relativas al viewport)
|
||||||
|
int x = (physical_viewport.w / 2) - (bg_width / 2);
|
||||||
int y = NOTIFICATION_TOP_MARGIN + static_cast<int>(current_notification_->y_offset);
|
int y = NOTIFICATION_TOP_MARGIN + static_cast<int>(current_notification_->y_offset);
|
||||||
|
|
||||||
// Renderizar fondo semitransparente (con bypass de presentación lógica)
|
// Renderizar fondo semitransparente (con bypass de presentación lógica)
|
||||||
|
|||||||
@@ -13,6 +13,31 @@
|
|||||||
#include "notifier.h" // for Notifier
|
#include "notifier.h" // for Notifier
|
||||||
#include "help_overlay.h" // for HelpOverlay
|
#include "help_overlay.h" // for HelpOverlay
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// HELPER: Obtener viewport en coordenadas físicas (no lógicas)
|
||||||
|
// ============================================================================
|
||||||
|
// SDL_GetRenderViewport() devuelve coordenadas LÓGICAS cuando hay presentación
|
||||||
|
// lógica activa. Para obtener coordenadas FÍSICAS, necesitamos deshabilitar
|
||||||
|
// temporalmente la presentación lógica.
|
||||||
|
static SDL_Rect getPhysicalViewport(SDL_Renderer* renderer) {
|
||||||
|
// Guardar estado actual de presentación lógica
|
||||||
|
int logical_w = 0, logical_h = 0;
|
||||||
|
SDL_RendererLogicalPresentation presentation_mode;
|
||||||
|
SDL_GetRenderLogicalPresentation(renderer, &logical_w, &logical_h, &presentation_mode);
|
||||||
|
|
||||||
|
// Deshabilitar presentación lógica temporalmente
|
||||||
|
SDL_SetRenderLogicalPresentation(renderer, 0, 0, SDL_LOGICAL_PRESENTATION_DISABLED);
|
||||||
|
|
||||||
|
// Obtener viewport en coordenadas físicas (píxeles reales)
|
||||||
|
SDL_Rect physical_viewport;
|
||||||
|
SDL_GetRenderViewport(renderer, &physical_viewport);
|
||||||
|
|
||||||
|
// Restaurar presentación lógica
|
||||||
|
SDL_SetRenderLogicalPresentation(renderer, logical_w, logical_h, presentation_mode);
|
||||||
|
|
||||||
|
return physical_viewport;
|
||||||
|
}
|
||||||
|
|
||||||
UIManager::UIManager()
|
UIManager::UIManager()
|
||||||
: text_renderer_(nullptr)
|
: text_renderer_(nullptr)
|
||||||
, text_renderer_debug_(nullptr)
|
, text_renderer_debug_(nullptr)
|
||||||
@@ -175,18 +200,15 @@ void UIManager::updatePhysicalWindowSize(int width, int height) {
|
|||||||
if (text_renderer_notifier_) {
|
if (text_renderer_notifier_) {
|
||||||
text_renderer_notifier_->reinitialize(current_font_size_);
|
text_renderer_notifier_->reinitialize(current_font_size_);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Reinicializar help overlay con nuevo tamaño de fuente
|
// Actualizar help overlay con font size actual Y nuevas dimensiones (atómicamente)
|
||||||
if (help_overlay_) {
|
if (help_overlay_) {
|
||||||
help_overlay_->reinitializeFontSize(current_font_size_);
|
help_overlay_->updateAll(current_font_size_, width, height);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualizar componentes de UI con nuevas dimensiones
|
// Actualizar otros componentes de UI con nuevas dimensiones
|
||||||
notifier_->updateWindowSize(width, height);
|
notifier_->updateWindowSize(width, height);
|
||||||
if (help_overlay_) {
|
|
||||||
help_overlay_->updatePhysicalWindowSize(width, height);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UIManager::setTextObsolete(const std::string& text, int pos, int current_screen_width) {
|
void UIManager::setTextObsolete(const std::string& text, int pos, int current_screen_width) {
|
||||||
@@ -208,6 +230,12 @@ void UIManager::renderDebugHUD(const Engine* engine,
|
|||||||
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
|
||||||
|
|
||||||
|
// Obtener viewport FÍSICO (píxeles reales, no lógicos)
|
||||||
|
// CRÍTICO: En F3, SDL_GetRenderViewport() devuelve coordenadas LÓGICAS,
|
||||||
|
// pero printAbsolute() trabaja en píxeles FÍSICOS. Usar helper para obtener
|
||||||
|
// viewport en coordenadas físicas.
|
||||||
|
SDL_Rect physical_viewport = getPhysicalViewport(renderer_);
|
||||||
|
|
||||||
// ===========================
|
// ===========================
|
||||||
// COLUMNA LEFT (Sistema)
|
// COLUMNA LEFT (Sistema)
|
||||||
// ===========================
|
// ===========================
|
||||||
@@ -310,7 +338,7 @@ void UIManager::renderDebugHUD(const Engine* engine,
|
|||||||
|
|
||||||
// FPS counter (esquina superior derecha)
|
// 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_viewport.w - fps_text_width - margin;
|
||||||
text_renderer_debug_->printAbsolute(fps_x, right_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;
|
right_y += line_height;
|
||||||
|
|
||||||
@@ -321,47 +349,47 @@ void UIManager::renderDebugHUD(const Engine* engine,
|
|||||||
SDL_FRect pos = first_ball->getPosition();
|
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)) + ")";
|
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());
|
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
|
text_renderer_debug_->printAbsolute(physical_viewport.w - pos_width - margin, right_y, pos_text.c_str(), {255, 128, 128, 255}); // Rojo claro
|
||||||
right_y += line_height;
|
right_y += line_height;
|
||||||
|
|
||||||
// Velocidad X
|
// Velocidad X
|
||||||
int vx_int = static_cast<int>(first_ball->getVelocityX());
|
int vx_int = static_cast<int>(first_ball->getVelocityX());
|
||||||
std::string vx_text = "VelX: " + std::to_string(vx_int);
|
std::string vx_text = "VelX: " + std::to_string(vx_int);
|
||||||
int vx_width = text_renderer_debug_->getTextWidthPhysical(vx_text.c_str());
|
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
|
text_renderer_debug_->printAbsolute(physical_viewport.w - vx_width - margin, right_y, vx_text.c_str(), {128, 255, 128, 255}); // Verde claro
|
||||||
right_y += line_height;
|
right_y += line_height;
|
||||||
|
|
||||||
// Velocidad Y
|
// Velocidad Y
|
||||||
int vy_int = static_cast<int>(first_ball->getVelocityY());
|
int vy_int = static_cast<int>(first_ball->getVelocityY());
|
||||||
std::string vy_text = "VelY: " + std::to_string(vy_int);
|
std::string vy_text = "VelY: " + std::to_string(vy_int);
|
||||||
int vy_width = text_renderer_debug_->getTextWidthPhysical(vy_text.c_str());
|
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
|
text_renderer_debug_->printAbsolute(physical_viewport.w - vy_width - margin, right_y, vy_text.c_str(), {128, 255, 128, 255}); // Verde claro
|
||||||
right_y += line_height;
|
right_y += line_height;
|
||||||
|
|
||||||
// Fuerza de gravedad
|
// Fuerza de gravedad
|
||||||
int grav_int = static_cast<int>(first_ball->getGravityForce());
|
int grav_int = static_cast<int>(first_ball->getGravityForce());
|
||||||
std::string grav_text = "Gravity: " + std::to_string(grav_int);
|
std::string grav_text = "Gravity: " + std::to_string(grav_int);
|
||||||
int grav_width = text_renderer_debug_->getTextWidthPhysical(grav_text.c_str());
|
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
|
text_renderer_debug_->printAbsolute(physical_viewport.w - grav_width - margin, right_y, grav_text.c_str(), {255, 255, 128, 255}); // Amarillo claro
|
||||||
right_y += line_height;
|
right_y += line_height;
|
||||||
|
|
||||||
// Estado superficie
|
// Estado superficie
|
||||||
std::string surface_text = first_ball->isOnSurface() ? "Surface: YES" : "Surface: NO";
|
std::string surface_text = first_ball->isOnSurface() ? "Surface: YES" : "Surface: NO";
|
||||||
int surface_width = text_renderer_debug_->getTextWidthPhysical(surface_text.c_str());
|
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
|
text_renderer_debug_->printAbsolute(physical_viewport.w - surface_width - margin, right_y, surface_text.c_str(), {255, 200, 128, 255}); // Naranja claro
|
||||||
right_y += line_height;
|
right_y += line_height;
|
||||||
|
|
||||||
// Coeficiente de rebote (loss)
|
// Coeficiente de rebote (loss)
|
||||||
float loss_val = first_ball->getLossCoefficient();
|
float loss_val = first_ball->getLossCoefficient();
|
||||||
std::string loss_text = "Loss: " + std::to_string(loss_val).substr(0, 4);
|
std::string loss_text = "Loss: " + std::to_string(loss_val).substr(0, 4);
|
||||||
int loss_width = text_renderer_debug_->getTextWidthPhysical(loss_text.c_str());
|
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
|
text_renderer_debug_->printAbsolute(physical_viewport.w - loss_width - margin, right_y, loss_text.c_str(), {255, 128, 255, 255}); // Magenta
|
||||||
right_y += line_height;
|
right_y += line_height;
|
||||||
|
|
||||||
// Dirección de gravedad
|
// Dirección de gravedad
|
||||||
std::string gravity_dir_text = "Dir: " + gravityDirectionToString(static_cast<int>(scene_manager->getCurrentGravity()));
|
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());
|
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
|
text_renderer_debug_->printAbsolute(physical_viewport.w - dir_width - margin, right_y, gravity_dir_text.c_str(), {128, 255, 255, 255}); // Cian claro
|
||||||
right_y += line_height;
|
right_y += line_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -370,7 +398,7 @@ void UIManager::renderDebugHUD(const Engine* engine,
|
|||||||
int convergence_percent = static_cast<int>(shape_convergence * 100.0f);
|
int convergence_percent = static_cast<int>(shape_convergence * 100.0f);
|
||||||
std::string convergence_text = "Convergence: " + std::to_string(convergence_percent) + "%";
|
std::string convergence_text = "Convergence: " + std::to_string(convergence_percent) + "%";
|
||||||
int conv_width = text_renderer_debug_->getTextWidthPhysical(convergence_text.c_str());
|
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
|
text_renderer_debug_->printAbsolute(physical_viewport.w - conv_width - margin, right_y, convergence_text.c_str(), {255, 128, 0, 255}); // Naranja
|
||||||
right_y += line_height;
|
right_y += line_height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user