#pragma once #include "theme.h" #include // Forward declaration (estructura definida en defines.h) struct DynamicThemeKeyframe; /** * DynamicTheme: Tema animado con N keyframes (2+) * * Características: * - Animación continua entre keyframes * - Progreso interno 0.0-1.0 entre keyframe actual y siguiente * - Loop automático (vuelve al primer keyframe al terminar) * - Pausable con Shift+D * - Compatible con LERP externo (PHASE 3) vía parámetro progress * * Uso: * - 3 temas dinámicos: SUNRISE, OCEAN_WAVES, NEON_PULSE * - Indices 7-9 en el array unificado de ThemeManager */ class DynamicTheme : public Theme { public: /** * Constructor * @param name_en: Nombre en inglés * @param name_es: Nombre en español * @param text_r, text_g, text_b: Color de texto UI * @param keyframes: Vector de keyframes (mínimo 2) * @param loop: ¿Volver al inicio al terminar? (siempre true en esta app) */ DynamicTheme(const char* name_en, const char* name_es, int text_r, int text_g, int text_b, std::vector keyframes, bool loop = true); ~DynamicTheme() override = default; // ======================================== // QUERIES BÁSICAS // ======================================== const char* getNameEN() const override { return name_en_.c_str(); } const char* getNameES() const override { return name_es_.c_str(); } void getTextColor(int& r, int& g, int& b) const override { r = text_r_; g = text_g_; b = text_b_; } void getNotificationBackgroundColor(int& r, int& g, int& b) const override; // ======================================== // CORE: OBTENER COLORES (interpolados) // ======================================== Color getBallColor(size_t ball_index, float progress) const override; void getBackgroundColors(float progress, float& tr, float& tg, float& tb, float& br, float& bg, float& bb) const override; // ======================================== // ANIMACIÓN (soporte completo) // ======================================== void update(float delta_time) override; bool needsUpdate() const override { return true; } float getProgress() const override { return transition_progress_; } void resetProgress() override; // ======================================== // PAUSA (tecla Shift+D) // ======================================== bool isPaused() const override { return paused_; } void togglePause() override { paused_ = !paused_; } private: // ======================================== // DATOS DEL TEMA // ======================================== std::string name_en_; std::string name_es_; int text_r_, text_g_, text_b_; std::vector keyframes_; bool loop_; // ======================================== // ESTADO DE ANIMACIÓN // ======================================== size_t current_keyframe_index_ = 0; // Keyframe actual size_t target_keyframe_index_ = 1; // Próximo keyframe float transition_progress_ = 0.0f; // Progreso 0.0-1.0 hacia target bool paused_ = false; // Pausa manual con Shift+D // ======================================== // UTILIDADES PRIVADAS // ======================================== float lerp(float a, float b, float t) const { return a + (b - a) * t; } void advanceToNextKeyframe(); // Avanza al siguiente keyframe (con loop) };