fix: corregir padding asimétrico en HelpOverlay con getGlyphHeight()

Añade TextRenderer::getGlyphHeight() (ascent - descent, sin line_gap)
y lo usa en calculateTextDimensions() para descontar el gap sobrante
de la última línea, aproximando padding superior e inferior simétricos.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-20 19:29:35 +01:00
parent b9b5f0b29f
commit dcea4ebbab
3 changed files with 63 additions and 47 deletions

View File

@@ -30,7 +30,7 @@ HelpOverlay::HelpOverlay()
{"SIMULACIÓN", ""},
{"1-8", "Escenarios (10 a 50.000 pelotas)"},
{"F", "Cambia entre figura y física"},
{"B", "Modo Boids"},
{"B", "Cambia entre boids y física"},
{"ESPACIO", "Impulso contra gravedad"},
{"G", "Activar / Desactivar gravedad"},
{"CURSORES", "Dirección de gravedad"},
@@ -47,9 +47,9 @@ HelpOverlay::HelpOverlay()
// COLUMNA 2: MODOS
{"MODOS", ""},
{"D", "Modo demo"},
{"L", "Modo demo lite"},
{"K", "Modo logo"},
{"D", "Activar / Desactivar modo demo"},
{"L", "Activar / Desactivar modo demo lite"},
{"K", "Activar / Desactivar modo logo"},
{"", ""}, // Separador
// COLUMNA 2: VISUAL
@@ -202,14 +202,14 @@ void HelpOverlay::calculateTextDimensions(int& max_width, int& total_height) {
column2_width_ = max_col2_width;
column3_width_ = max_col3_width;
// Ancho total: 3 columnas + 4 paddings (izq, entre cols x2, der)
max_width = max_col1_width + max_col2_width + max_col3_width + padding * 4;
// Gap entre columnas: doble del padding para dar más respiro
int col_gap = padding * 2;
// Altura: contar unidades de altura por columna (en "medias líneas" para precisión)
// - línea normal = 2 unidades, encabezado = 2 unidades (+2px ignorados aquí), separador = 1 unidad
int col1_half_lines = 0;
int col2_half_lines = 0;
int col3_half_lines = 0;
// Ancho total: 3 columnas + padding izq/der + 2 gaps entre columnas
max_width = max_col1_width + max_col2_width + max_col3_width + padding * 2 + col_gap * 2;
// Calcular altura real simulando exactamente lo que hace el render
int col_heights[3] = {0, 0, 0};
current_column = 0;
for (const auto& binding : key_bindings_) {
@@ -218,23 +218,23 @@ void HelpOverlay::calculateTextDimensions(int& max_width, int& total_height) {
continue;
}
int units = (binding.key[0] == '\0') ? 1 : 2; // separador = 1, línea/encabezado = 2
if (current_column == 0) {
col1_half_lines += units;
} else if (current_column == 1) {
col2_half_lines += units;
if (binding.key[0] == '\0') {
col_heights[current_column] += line_height; // separador vacío
} else if (binding.description[0] == '\0') {
col_heights[current_column] += line_height; // encabezado
} else {
col3_half_lines += units;
col_heights[current_column] += line_height; // línea normal
}
}
// Convertir a altura real: unidades * (line_height / 2)
int max_half_lines = std::max({col1_half_lines, col2_half_lines, col3_half_lines});
int content_height = max_half_lines * line_height / 2;
int content_height = std::max({col_heights[0], col_heights[1], col_heights[2]});
// Altura: título (2 líneas) + contenido + padding superior e inferior
total_height = line_height * 2 + content_height + padding * 2;
// Eliminar el line_gap de la última línea: ese gap es espacio entre líneas,
// pero la última línea no tiene siguiente, así que queda como padding muerto.
int glyph_height = text_renderer_->getGlyphHeight();
int visual_content_height = content_height - (line_height - glyph_height);
total_height = visual_content_height + padding * 2;
}
void HelpOverlay::calculateBoxDimensions() {
@@ -341,31 +341,28 @@ void HelpOverlay::rebuildCachedTexture() {
// Configuración de espaciado
int line_height = text_renderer_->getTextHeight();
// Padding dinámico basado en altura física: 25px para >= 600px, escalado proporcionalmente para menores
int padding = (physical_height_ >= 600) ? 25 : std::max(10, physical_height_ / 24);
int col_gap = padding * 2;
// Posición X de inicio de cada columna
int col_start[3];
col_start[0] = padding;
col_start[1] = padding + column1_width_ + col_gap;
col_start[2] = padding + column1_width_ + col_gap + column2_width_ + col_gap;
// Ancho de cada columna (para centrado interno)
int col_width[3] = {column1_width_, column2_width_, column3_width_};
int current_x = padding; // Coordenadas relativas a la textura (0,0)
int current_y = padding;
int current_column = 0;
// Título principal
const char* title = "CONTROLES - ViBe3 Physics";
int title_width = text_renderer_->getTextWidthPhysical(title);
text_renderer_->printAbsolute(box_width_ / 2 - title_width / 2, current_y, title, category_color);
current_y += line_height * 2;
int content_start_y = current_y;
// Renderizar cada línea
for (const auto& binding : key_bindings_) {
if (strcmp(binding.key, "[new_col]") == 0 && binding.description[0] == '\0') {
if (current_column == 0) {
current_column = 1;
current_x = padding + column1_width_ + padding;
current_y = content_start_y;
} else if (current_column == 1) {
current_column = 2;
current_x = padding + column1_width_ + padding + column2_width_ + padding;
if (current_column < 2) {
current_column++;
current_y = content_start_y;
}
continue;
@@ -376,22 +373,30 @@ void HelpOverlay::rebuildCachedTexture() {
continue;
}
int cx = col_start[current_column];
int cw = col_width[current_column];
if (binding.description[0] == '\0') {
if (binding.key[0] == '\0') {
// Separador vacío: avanzar media línea
current_y += line_height / 2;
// Separador vacío: avanzar una línea completa
current_y += line_height;
} else {
// Encabezado de sección
text_renderer_->printAbsolute(current_x, current_y, binding.key, category_color);
current_y += line_height + 2;
// Encabezado de sección — centrado en la columna
int w = text_renderer_->getTextWidthPhysical(binding.key);
text_renderer_->printAbsolute(cx + (cw - w) / 2, current_y, binding.key, category_color);
current_y += line_height;
}
continue;
}
// Tecla en category_color, descripción en content_color
text_renderer_->printAbsolute(current_x, current_y, binding.key, category_color);
// Par tecla+descripción — centrado como bloque en la columna
int key_width = text_renderer_->getTextWidthPhysical(binding.key);
text_renderer_->printAbsolute(current_x + key_width + 10, current_y, binding.description, content_color);
int desc_width = text_renderer_->getTextWidthPhysical(binding.description);
int total_width = key_width + 10 + desc_width;
int line_x = cx + (cw - total_width) / 2;
text_renderer_->printAbsolute(line_x, current_y, binding.key, category_color);
text_renderer_->printAbsolute(line_x + key_width + 10, current_y, binding.description, content_color);
current_y += line_height;
}