#pragma once #include // for unique_ptr #include // for vector #include "ball.h" // for Ball class #include "defines.h" // for Color, ColorTheme #include "themes/theme.h" // for Theme interface #include "themes/theme_snapshot.h" // for ThemeSnapshot /** * ThemeManager: Gestiona el sistema de temas visuales (unificado, estáticos y dinámicos) * * PHASE 2 - Sistema Unificado: * - Vector unificado de 10 temas (7 estáticos + 3 dinámicos) * - Índices 0-9 mapeados a ColorTheme enum (SUNSET=0, OCEAN=1, ..., NEON_PULSE=9) * - API simplificada: switchToTheme(0-9) para cualquier tema * - Sin lógica dual (eliminados if(dynamic_theme_active_) scattered) * * PHASE 3 - LERP Universal: * - Transiciones suaves entre CUALQUIER par de temas (estático↔estático, estático↔dinámico, dinámico↔dinámico) * - Sistema de snapshots: Captura estado del tema origen antes de cambiar * - LERP durante transición: snapshot origen → tema destino * - Duración configurable (THEME_TRANSITION_DURATION = 0.5s por defecto) * * Responsabilidades: * - Mantener 10 temas polimórficos (StaticTheme / DynamicTheme) * - Actualizar animación de tema activo si es dinámico * - Gestionar transiciones LERP suaves entre temas * - Proporcionar colores interpolados para renderizado (con LERP si hay transición activa) * * Uso desde Engine: * - initialize() al inicio * - update(delta_time) cada frame (actualiza tema activo + transición LERP) * - switchToTheme(0-9) para cambiar tema con transición suave (Numpad 1-0, Tecla B) * - getInterpolatedColor(index) en render loop (retorna color con LERP si transitioning) */ class ThemeManager { public: // Constructor/Destructor ThemeManager() = default; ~ThemeManager() = default; // Inicialización void initialize(); // Inicializa 10 temas unificados (7 estáticos + 3 dinámicos) // Interfaz unificada (PHASE 2 + PHASE 3) void switchToTheme(int theme_index); // Cambia a tema 0-9 con transición LERP suave (PHASE 3) void update(float delta_time); // Actualiza transición LERP + tema activo si es dinámico void cycleTheme(); // Cicla al siguiente tema (0→1→...→9→0) - Tecla B void pauseDynamic(); // Toggle pausa de animación (Shift+D, solo dinámicos) // Queries de colores (usado en rendering) Color getInterpolatedColor(size_t ball_index) const; // Obtiene color interpolado para pelota void getBackgroundColors(float& top_r, float& top_g, float& top_b, float& bottom_r, float& bottom_g, float& bottom_b) const; // Obtiene colores de fondo degradado // Queries de estado (para debug display y lógica) int getCurrentThemeIndex() const { return current_theme_index_; } bool isCurrentThemeDynamic() const; bool isTransitioning() const { return transitioning_; } // ¿Hay transición LERP activa? (PHASE 3) // Obtener información de tema actual para debug display const char* getCurrentThemeNameEN() const; const char* getCurrentThemeNameES() const; void getCurrentThemeTextColor(int& r, int& g, int& b) const; // Obtener color inicial para nuevas pelotas (usado en initBalls) Color getInitialBallColor(int random_index) const; private: // ======================================== // DATOS UNIFICADOS (PHASE 2) // ======================================== // Vector unificado de 10 temas (índices 0-9) // 0-6: Estáticos (SUNSET, OCEAN, NEON, FOREST, RGB, MONOCHROME, LAVENDER) // 7-9: Dinámicos (SUNRISE, OCEAN_WAVES, NEON_PULSE) std::vector> themes_; // Índice de tema activo actual (0-9) int current_theme_index_ = 0; // Por defecto SUNSET // ======================================== // SISTEMA DE TRANSICIÓN LERP (PHASE 3) // ======================================== // Estado de transición bool transitioning_ = false; // ¿Hay transición LERP activa? float transition_progress_ = 0.0f; // Progreso 0.0-1.0 (0.0 = origen, 1.0 = destino) float transition_duration_ = THEME_TRANSITION_DURATION; // Duración en segundos (configurable en defines.h) // Índices de temas involucrados en transición int source_theme_index_ = 0; // Tema origen (del que venimos) int target_theme_index_ = 0; // Tema destino (al que vamos) // Snapshot del tema origen (capturado al iniciar transición) std::unique_ptr source_snapshot_; // nullptr si no hay transición // ======================================== // MÉTODOS PRIVADOS // ======================================== // Inicialización void initializeStaticThemes(); // Crea 7 temas estáticos (índices 0-6) void initializeDynamicThemes(); // Crea 3 temas dinámicos (índices 7-9) // Sistema de transición LERP (PHASE 3) std::unique_ptr captureCurrentSnapshot() const; // Captura snapshot del tema actual float lerp(float a, float b, float t) const { return a + (b - a) * t; } // Interpolación lineal };