feat: rediseño HUD ayuda — 3 columnas, colores diferenciados, font -1pt
- Reorganizar key_bindings_ en 3 columnas (SIMULACIÓN+FIGURAS3D / VISUAL+PANTALLA / MODOS+DEBUG) - Añadir F6 (escalado entero) y corregir F5 (Toggle PostFX), X (ciclar presets) - Teclas usan category_color, descripciones usan content_color - Separadores vacíos avanzan media línea (fix secciones pegadas) - Font size del overlay reducido en 1pt respecto al resto de la UI - calculateTextDimensions y rebuildCachedTexture actualizados para 3 columnas Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -18,20 +18,21 @@ HelpOverlay::HelpOverlay()
|
||||
box_y_(0),
|
||||
column1_width_(0),
|
||||
column2_width_(0),
|
||||
column3_width_(0),
|
||||
cached_texture_(nullptr),
|
||||
last_category_color_({0, 0, 0, 255}),
|
||||
last_content_color_({0, 0, 0, 255}),
|
||||
last_bg_color_({0, 0, 0, 255}),
|
||||
texture_needs_rebuild_(true) {
|
||||
// Llenar lista de controles (organizados por categoría, equilibrado en 2 columnas)
|
||||
// Llenar lista de controles (organizados por categoría, equilibrado en 3 columnas)
|
||||
key_bindings_ = {
|
||||
// COLUMNA 1: SIMULACIÓN
|
||||
{"SIMULACIÓN", ""},
|
||||
{"1-8", "Escenarios (10 a 50,000 pelotas)"},
|
||||
{"F", "Toggle Física - Última Figura"},
|
||||
{"B", "Modo Boids (enjambre)"},
|
||||
{"1-8", "Escenarios (10 a 50.000 pelotas)"},
|
||||
{"F", "Cambia entre figura y física"},
|
||||
{"B", "Modo Boids"},
|
||||
{"ESPACIO", "Impulso contra gravedad"},
|
||||
{"G", "Toggle Gravedad ON/OFF"},
|
||||
{"G", "Activar / Desactivar gravedad"},
|
||||
{"CURSORES", "Dirección de gravedad"},
|
||||
{"", ""}, // Separador
|
||||
|
||||
@@ -39,40 +40,42 @@ HelpOverlay::HelpOverlay()
|
||||
{"FIGURAS 3D", ""},
|
||||
{"Q/W/E/R", "Esfera/Lissajous/Hélice/Toroide"},
|
||||
{"T/Y/U/I", "Cubo/Cilindro/Icosaedro/Átomo"},
|
||||
{"O", "Forma PNG"},
|
||||
{"Num+/-", "Escalar figura"},
|
||||
{"Num*", "Reset escala"},
|
||||
{"Num/", "Toggle profundidad"},
|
||||
{"Num/", "Activar / Desactivar profundidad"},
|
||||
{"[new_col]", ""}, // CAMBIO DE COLUMNA -> COLUMNA 2
|
||||
|
||||
// COLUMNA 2: MODOS
|
||||
{"MODOS", ""},
|
||||
{"D", "Modo demo"},
|
||||
{"L", "Modo demo lite"},
|
||||
{"K", "Modo logo"},
|
||||
{"", ""}, // Separador
|
||||
|
||||
// COLUMNA 1: VISUAL
|
||||
// COLUMNA 2: VISUAL
|
||||
{"VISUAL", ""},
|
||||
{"C", "Tema siguiente"},
|
||||
{"Shift+C", "Tema anterior"},
|
||||
{"NumEnter", "Página de temas"},
|
||||
{"N", "Cambiar sprite"},
|
||||
{"[new_col]", ""}, // Separador -> CAMBIO DE COLUMNA
|
||||
|
||||
// COLUMNA 2: PANTALLA
|
||||
{"PANTALLA", ""},
|
||||
{"F1/F2", "Zoom out/in (ventana)"},
|
||||
{"F3", "Fullscreen letterbox"},
|
||||
{"F4", "Fullscreen real"},
|
||||
{"F5", "Escalado (F3 activo)"},
|
||||
{"V", "Toggle V-Sync"},
|
||||
{"", ""}, // Separador
|
||||
|
||||
// COLUMNA 2: MODOS
|
||||
{"MODOS", ""},
|
||||
{"D", "Modo DEMO"},
|
||||
{"Shift+D", "Pausar tema dinámico"},
|
||||
{"L", "Modo DEMO LITE"},
|
||||
{"K", "Modo LOGO (easter egg)"},
|
||||
{"N", "Cambiar tamaño de pelota"},
|
||||
{"X", "Ciclar presets PostFX"},
|
||||
{"[new_col]", ""}, // CAMBIO DE COLUMNA -> COLUMNA 3
|
||||
|
||||
// COLUMNA 3: PANTALLA
|
||||
{"PANTALLA", ""},
|
||||
{"F1", "Disminuye ventana"},
|
||||
{"F2", "Aumenta ventana"},
|
||||
{"F3", "Pantalla completa"},
|
||||
{"F4", "Pantalla completa real"},
|
||||
{"F5", "Activar / Desactivar PostFX"},
|
||||
{"F6", "Cambia el escalado de pantalla"},
|
||||
{"V", "Activar / Desactivar V-Sync"},
|
||||
{"", ""}, // Separador
|
||||
|
||||
// COLUMNA 2: DEBUG/AYUDA
|
||||
// COLUMNA 3: DEBUG/AYUDA
|
||||
{"DEBUG/AYUDA", ""},
|
||||
{"F12", "Toggle info debug"},
|
||||
{"F12", "Activar / Desactivar info debug"},
|
||||
{"H", "Esta ayuda"},
|
||||
{"ESC", "Salir"}};
|
||||
}
|
||||
@@ -157,12 +160,13 @@ void HelpOverlay::calculateTextDimensions(int& max_width, int& total_height) {
|
||||
// Calcular ancho máximo por columna
|
||||
int max_col1_width = 0;
|
||||
int max_col2_width = 0;
|
||||
int max_col3_width = 0;
|
||||
int current_column = 0;
|
||||
|
||||
for (const auto& binding : key_bindings_) {
|
||||
// Cambio de columna
|
||||
if (strcmp(binding.key, "[new_col]") == 0) {
|
||||
current_column = 1;
|
||||
current_column++;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -186,48 +190,51 @@ void HelpOverlay::calculateTextDimensions(int& max_width, int& total_height) {
|
||||
// Actualizar máximo de columna correspondiente
|
||||
if (current_column == 0) {
|
||||
max_col1_width = std::max(max_col1_width, line_width);
|
||||
} else {
|
||||
} else if (current_column == 1) {
|
||||
max_col2_width = std::max(max_col2_width, line_width);
|
||||
} else {
|
||||
max_col3_width = std::max(max_col3_width, line_width);
|
||||
}
|
||||
}
|
||||
|
||||
// Almacenar anchos de columnas en miembros para uso posterior
|
||||
column1_width_ = max_col1_width;
|
||||
column2_width_ = max_col2_width;
|
||||
column3_width_ = max_col3_width;
|
||||
|
||||
// Ancho total: 2 columnas + 3 paddings (izq, medio, der)
|
||||
max_width = max_col1_width + max_col2_width + padding * 3;
|
||||
// Ancho total: 3 columnas + 4 paddings (izq, entre cols x2, der)
|
||||
max_width = max_col1_width + max_col2_width + max_col3_width + padding * 4;
|
||||
|
||||
// Altura: contar líneas REALES en cada columna
|
||||
int col1_lines = 0;
|
||||
int col2_lines = 0;
|
||||
// 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;
|
||||
current_column = 0;
|
||||
|
||||
for (const auto& binding : key_bindings_) {
|
||||
// Cambio de columna
|
||||
if (strcmp(binding.key, "[new_col]") == 0) {
|
||||
current_column = 1;
|
||||
current_column++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Separador vacío no cuenta como línea
|
||||
if (binding.key[0] == '\0') {
|
||||
continue;
|
||||
}
|
||||
int units = (binding.key[0] == '\0') ? 1 : 2; // separador = 1, línea/encabezado = 2
|
||||
|
||||
// Contar línea (ya sea encabezado o contenido)
|
||||
if (current_column == 0) {
|
||||
col1_lines++;
|
||||
col1_half_lines += units;
|
||||
} else if (current_column == 1) {
|
||||
col2_half_lines += units;
|
||||
} else {
|
||||
col2_lines++;
|
||||
col3_half_lines += units;
|
||||
}
|
||||
}
|
||||
|
||||
// Usar la columna más larga para calcular altura
|
||||
int max_column_lines = std::max(col1_lines, col2_lines);
|
||||
// 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;
|
||||
|
||||
// Altura: título (2 líneas) + contenido + padding superior e inferior
|
||||
total_height = line_height * 2 + max_column_lines * line_height + padding * 2;
|
||||
total_height = line_height * 2 + content_height + padding * 2;
|
||||
}
|
||||
|
||||
void HelpOverlay::calculateBoxDimensions() {
|
||||
@@ -354,34 +361,35 @@ void HelpOverlay::rebuildCachedTexture() {
|
||||
if (strcmp(binding.key, "[new_col]") == 0 && binding.description[0] == '\0') {
|
||||
if (current_column == 0) {
|
||||
current_column = 1;
|
||||
current_x = padding + column1_width_ + padding; // Usar ancho real de columna 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;
|
||||
current_y = content_start_y;
|
||||
}
|
||||
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
|
||||
// CHECK PADDING INFERIOR ANTES de escribir la línea
|
||||
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;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (binding.description[0] == '\0') {
|
||||
text_renderer_->printAbsolute(current_x, current_y, binding.key, category_color);
|
||||
current_y += line_height + 2;
|
||||
if (binding.key[0] == '\0') {
|
||||
// Separador vacío: avanzar media línea
|
||||
current_y += line_height / 2;
|
||||
} else {
|
||||
// Encabezado de sección
|
||||
text_renderer_->printAbsolute(current_x, current_y, binding.key, category_color);
|
||||
current_y += line_height + 2;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
text_renderer_->printAbsolute(current_x, current_y, binding.key, content_color);
|
||||
// Tecla en category_color, descripción en content_color
|
||||
text_renderer_->printAbsolute(current_x, current_y, binding.key, category_color);
|
||||
int key_width = text_renderer_->getTextWidthPhysical(binding.key);
|
||||
text_renderer_->printAbsolute(current_x + key_width + 10, current_y, binding.description, content_color);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user