From 250b1a640d479b404b7575d6f55ba015d64203f3 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Thu, 16 Oct 2025 17:41:19 +0200 Subject: [PATCH] feat: Dynamic text scaling based on physical window size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sistema de escalado dinámico de texto con 3 tamaños según área de ventana: 1. TextRenderer improvements: - Añadido reinitialize(int new_font_size) para cambiar tamaño en runtime - Almacena font_path_ para permitir recarga de fuente - Cierra fuente anterior y abre nueva con diferente tamaño - Verifica si tamaño es igual antes de reinicializar (optimización) 2. UIManager - Font size calculation: - Añadido calculateFontSize() con stepped scaling por área: * SMALL (< 800x600): 14px * MEDIUM (800x600 a 1920x1080): 18px * LARGE (> 1920x1080): 24px - Tracking de current_font_size_ para detectar cambios - Inicialización con tamaño dinámico en initialize() - Reinitialización automática en updatePhysicalWindowSize() 3. UIManager - Propagation: - Reinitializa 3 TextRenderer instances cuando cambia tamaño - Propaga nuevo tamaño a HelpOverlay - Detecta cambios solo cuando área cruza umbrales (eficiencia) 4. HelpOverlay integration: - Acepta font_size como parámetro en initialize() - Añadido reinitializeFontSize() para cambios dinámicos - Recalcula dimensiones del box cuando cambia fuente - Marca textura para rebuild completo tras cambio Resultado: - Ventanas pequeñas: texto 14px (más espacio para contenido) - Ventanas medianas: texto 18px (tamaño original, óptimo) - Ventanas grandes: texto 24px (mejor legibilidad) - Cambios automáticos al redimensionar ventana (F1/F2/F3/F4) - Sin impacto en performance (solo recalcula al cruzar umbrales) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- source/text/textrenderer.cpp | 33 +++++++++++++++++++ source/text/textrenderer.h | 4 +++ source/ui/help_overlay.cpp | 19 +++++++++-- source/ui/help_overlay.h | 7 ++++- source/ui/ui_manager.cpp | 61 +++++++++++++++++++++++++++++++----- source/ui/ui_manager.h | 11 +++++++ 6 files changed, 124 insertions(+), 11 deletions(-) diff --git a/source/text/textrenderer.cpp b/source/text/textrenderer.cpp index 24ec7f4..ac30b9c 100644 --- a/source/text/textrenderer.cpp +++ b/source/text/textrenderer.cpp @@ -13,6 +13,7 @@ bool TextRenderer::init(SDL_Renderer* renderer, const char* font_path, int font_ renderer_ = renderer; font_size_ = font_size; use_antialiasing_ = use_antialiasing; + font_path_ = font_path; // Guardar ruta para reinitialize() // Inicializar SDL_ttf si no está inicializado if (!TTF_WasInit()) { @@ -32,6 +33,38 @@ bool TextRenderer::init(SDL_Renderer* renderer, const char* font_path, int font_ return true; } +bool TextRenderer::reinitialize(int new_font_size) { + // Verificar que tenemos todo lo necesario + if (renderer_ == nullptr || font_path_.empty()) { + SDL_Log("Error: TextRenderer no inicializado correctamente para reinitialize()"); + return false; + } + + // Si el tamaño es el mismo, no hacer nada + if (new_font_size == font_size_) { + return true; + } + + // Cerrar fuente actual + if (font_ != nullptr) { + TTF_CloseFont(font_); + font_ = nullptr; + } + + // Cargar fuente con nuevo tamaño + font_ = TTF_OpenFont(font_path_.c_str(), new_font_size); + if (font_ == nullptr) { + SDL_Log("Error al recargar fuente '%s' con tamaño %d: %s", + font_path_.c_str(), new_font_size, SDL_GetError()); + return false; + } + + // Actualizar tamaño almacenado + font_size_ = new_font_size; + + return true; +} + void TextRenderer::cleanup() { if (font_ != nullptr) { TTF_CloseFont(font_); diff --git a/source/text/textrenderer.h b/source/text/textrenderer.h index 91002a1..b36639d 100644 --- a/source/text/textrenderer.h +++ b/source/text/textrenderer.h @@ -12,6 +12,9 @@ public: // Inicializa el renderizador de texto con una fuente bool init(SDL_Renderer* renderer, const char* font_path, int font_size, bool use_antialiasing = true); + // Reinicializa el renderizador con un nuevo tamaño de fuente + bool reinitialize(int new_font_size); + // Libera recursos void cleanup(); @@ -46,4 +49,5 @@ private: TTF_Font* font_; int font_size_; bool use_antialiasing_; + std::string font_path_; // Almacenar ruta para reinitialize() }; diff --git a/source/ui/help_overlay.cpp b/source/ui/help_overlay.cpp index bbbcbc4..7ad22cd 100644 --- a/source/ui/help_overlay.cpp +++ b/source/ui/help_overlay.cpp @@ -84,15 +84,15 @@ HelpOverlay::~HelpOverlay() { delete text_renderer_; } -void HelpOverlay::initialize(SDL_Renderer* renderer, ThemeManager* theme_mgr, int physical_width, int physical_height) { +void HelpOverlay::initialize(SDL_Renderer* renderer, ThemeManager* theme_mgr, int physical_width, int physical_height, int font_size) { renderer_ = renderer; theme_mgr_ = theme_mgr; physical_width_ = physical_width; physical_height_ = physical_height; - // Crear renderer de texto con tamaño reducido (18px en lugar de 24px) + // Crear renderer de texto con tamaño dinámico text_renderer_ = new TextRenderer(); - text_renderer_->init(renderer, "data/fonts/FunnelSans-Regular.ttf", 18, true); + text_renderer_->init(renderer, "data/fonts/FunnelSans-Regular.ttf", font_size, true); calculateBoxDimensions(); } @@ -106,6 +106,19 @@ void HelpOverlay::updatePhysicalWindowSize(int physical_width, int physical_heig texture_needs_rebuild_ = true; } +void HelpOverlay::reinitializeFontSize(int new_font_size) { + if (!text_renderer_) return; + + // Reinicializar text renderer con nuevo tamaño + text_renderer_->reinitialize(new_font_size); + + // Recalcular dimensiones del box (el texto ahora tiene distinto tamaño) + calculateBoxDimensions(); + + // Marcar textura para regeneración completa + texture_needs_rebuild_ = true; +} + void HelpOverlay::calculateTextDimensions(int& max_width, int& total_height) { if (!text_renderer_) { max_width = 0; diff --git a/source/ui/help_overlay.h b/source/ui/help_overlay.h index d775fc1..269ff9f 100644 --- a/source/ui/help_overlay.h +++ b/source/ui/help_overlay.h @@ -24,7 +24,7 @@ class HelpOverlay { /** * @brief Inicializa el overlay con renderer y theme manager */ - void initialize(SDL_Renderer* renderer, ThemeManager* theme_mgr, int physical_width, int physical_height); + void initialize(SDL_Renderer* renderer, ThemeManager* theme_mgr, int physical_width, int physical_height, int font_size); /** * @brief Renderiza el overlay si está visible @@ -36,6 +36,11 @@ class HelpOverlay { */ void updatePhysicalWindowSize(int physical_width, int physical_height); + /** + * @brief Reinitializa el tamaño de fuente (cuando cambia el tamaño de ventana) + */ + void reinitializeFontSize(int new_font_size); + /** * @brief Toggle visibilidad del overlay */ diff --git a/source/ui/ui_manager.cpp b/source/ui/ui_manager.cpp index b3c0b06..d09b84e 100644 --- a/source/ui/ui_manager.cpp +++ b/source/ui/ui_manager.cpp @@ -32,7 +32,8 @@ UIManager::UIManager() , renderer_(nullptr) , theme_manager_(nullptr) , physical_window_width_(0) - , physical_window_height_(0) { + , physical_window_height_(0) + , current_font_size_(18) { // Tamaño por defecto (medium) } UIManager::~UIManager() { @@ -51,16 +52,18 @@ void UIManager::initialize(SDL_Renderer* renderer, ThemeManager* theme_manager, physical_window_width_ = physical_width; physical_window_height_ = physical_height; + // Calcular tamaño de fuente apropiado según dimensiones físicas + current_font_size_ = calculateFontSize(physical_width, physical_height); + // Crear renderers de texto text_renderer_ = new TextRenderer(); text_renderer_debug_ = new TextRenderer(); text_renderer_notifier_ = new TextRenderer(); - // Inicializar renderers - // (el tamaño se configura dinámicamente en Engine según resolución) - text_renderer_->init(renderer, "data/fonts/FunnelSans-Regular.ttf", 18, true); - text_renderer_debug_->init(renderer, "data/fonts/FunnelSans-Regular.ttf", 18, true); - text_renderer_notifier_->init(renderer, "data/fonts/FunnelSans-Regular.ttf", 18, true); + // Inicializar renderers con tamaño dinámico + text_renderer_->init(renderer, "data/fonts/FunnelSans-Regular.ttf", current_font_size_, true); + text_renderer_debug_->init(renderer, "data/fonts/FunnelSans-Regular.ttf", current_font_size_, true); + text_renderer_notifier_->init(renderer, "data/fonts/FunnelSans-Regular.ttf", current_font_size_, true); // Crear y configurar sistema de notificaciones notifier_ = new Notifier(); @@ -69,7 +72,7 @@ void UIManager::initialize(SDL_Renderer* renderer, ThemeManager* theme_manager, // Crear y configurar sistema de ayuda (overlay) help_overlay_ = new HelpOverlay(); - help_overlay_->initialize(renderer, theme_manager_, physical_width, physical_height); + help_overlay_->initialize(renderer, theme_manager_, physical_width, physical_height, current_font_size_); // Inicializar FPS counter fps_last_time_ = SDL_GetTicks(); @@ -154,6 +157,32 @@ void UIManager::updateVSyncText(bool enabled) { void UIManager::updatePhysicalWindowSize(int width, int height) { physical_window_width_ = width; physical_window_height_ = height; + + // Calcular nuevo tamaño de fuente apropiado + int new_font_size = calculateFontSize(width, height); + + // Si el tamaño cambió, reinicializar todos los text renderers + if (new_font_size != current_font_size_) { + current_font_size_ = new_font_size; + + // Reinicializar text renderers con nuevo tamaño + if (text_renderer_) { + text_renderer_->reinitialize(current_font_size_); + } + if (text_renderer_debug_) { + text_renderer_debug_->reinitialize(current_font_size_); + } + if (text_renderer_notifier_) { + text_renderer_notifier_->reinitialize(current_font_size_); + } + + // Reinicializar help overlay con nuevo tamaño de fuente + if (help_overlay_) { + help_overlay_->reinitializeFontSize(current_font_size_); + } + } + + // Actualizar componentes de UI con nuevas dimensiones notifier_->updateWindowSize(width, height); if (help_overlay_) { help_overlay_->updatePhysicalWindowSize(width, height); @@ -376,3 +405,21 @@ std::string UIManager::gravityDirectionToString(int direction) const { default: return "Desconocida"; } } + +int UIManager::calculateFontSize(int physical_width, int physical_height) const { + // Calcular área física de la ventana + int area = physical_width * physical_height; + + // Stepped scaling con 3 tamaños: + // - SMALL: < 800x600 (480,000 pixels) → 14px + // - MEDIUM: 800x600 a 1920x1080 (2,073,600 pixels) → 18px + // - LARGE: > 1920x1080 → 24px + + if (area < 480000) { + return 14; // Ventanas pequeñas + } else if (area < 2073600) { + return 18; // Ventanas medianas (default) + } else { + return 24; // Ventanas grandes + } +} diff --git a/source/ui/ui_manager.h b/source/ui/ui_manager.h index 8fd044c..7eb25d8 100644 --- a/source/ui/ui_manager.h +++ b/source/ui/ui_manager.h @@ -166,6 +166,14 @@ class UIManager { */ std::string gravityDirectionToString(int direction) const; + /** + * @brief Calcula tamaño de fuente apropiado según dimensiones físicas + * @param physical_width Ancho físico de ventana + * @param physical_height Alto físico de ventana + * @return Tamaño de fuente (14px/18px/24px) + */ + int calculateFontSize(int physical_width, int physical_height) const; + // === Recursos de renderizado === TextRenderer* text_renderer_; // Texto obsoleto (DEPRECATED) TextRenderer* text_renderer_debug_; // HUD de debug @@ -194,4 +202,7 @@ class UIManager { ThemeManager* theme_manager_; // Gestor de temas (para colores) int physical_window_width_; // Ancho físico de ventana (píxeles reales) int physical_window_height_; // Alto físico de ventana (píxeles reales) + + // === Sistema de escalado dinámico de texto === + int current_font_size_; // Tamaño de fuente actual (14/18/24) };