feat: Animación elástica tipo pegatina para AppLogo
Implementación de deformación elástica con vértices para el logo: FADE IN (0.5s): - Scale: 120% → 100% con easing elástico (bounce) - Squash Y: 0.6 → 1.0 con easing back (aplastamiento) - Stretch X: compensación automática - Efecto: logo se "pega" aplastándose y rebotando FADE OUT (0.5s): - Scale: 100% → 120% (aceleración cuadrática) - Squash Y: 1.0 → 1.3 (estiramiento vertical) - Stretch X: 1.0 → 0.8 (compresión horizontal) - Rotación: 0° → ~5.7° (torsión sutil) - Efecto: logo se "despega" estirándose y girando Características técnicas: - Enum AppLogoAnimationType (ZOOM_ONLY / ELASTIC_STICK) - Renderizado con SDL_RenderGeometry para deformaciones - Funciones de easing: easeOutElastic() y easeOutBack() - Transformación de vértices con rotación y escala 2D - Actualmente fijo en ELASTIC_STICK para testing Limpieza adicional: - Eliminado dbgtxt.h (no utilizado) - Removidos SDL_Log de debug en HelpOverlay - Comentada variable no usada en ShapeManager 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
#include "app_logo.h"
|
||||
|
||||
#include <SDL3/SDL_render.h> // for SDL_SCALEMODE_LINEAR
|
||||
#include <SDL3/SDL_render.h> // for SDL_SCALEMODE_LINEAR, SDL_RenderGeometry
|
||||
#include <cmath> // for powf, sinf, cosf
|
||||
|
||||
#include "external/sprite.h" // for Sprite
|
||||
#include "external/texture.h" // for Texture
|
||||
|
||||
bool AppLogo::initialize(SDL_Renderer* renderer, int screen_width, int screen_height) {
|
||||
renderer_ = renderer;
|
||||
screen_width_ = screen_width;
|
||||
screen_height_ = screen_height;
|
||||
|
||||
@@ -39,10 +41,12 @@ bool AppLogo::initialize(SDL_Renderer* renderer, int screen_width, int screen_he
|
||||
float scale_y = quadrant_height / logo_height;
|
||||
float scale = (scale_x < scale_y) ? scale_x : scale_y;
|
||||
|
||||
// Aplicar escala
|
||||
float scaled_width = logo_width * scale;
|
||||
float scaled_height = logo_height * scale;
|
||||
logo_sprite_->setSize(scaled_width, scaled_height);
|
||||
// Calcular tamaño base (guardarlo para animaciones de zoom)
|
||||
base_width_ = logo_width * scale;
|
||||
base_height_ = logo_height * scale;
|
||||
|
||||
// Aplicar escala inicial
|
||||
logo_sprite_->setSize(base_width_, base_height_);
|
||||
|
||||
// Posicionar logo en el centro del cuadrante inferior derecho
|
||||
updateLogoPosition();
|
||||
@@ -73,7 +77,7 @@ void AppLogo::update(float delta_time, AppMode current_mode) {
|
||||
break;
|
||||
|
||||
case AppLogoState::FADE_IN:
|
||||
// Fade in: alpha de 0 a 255
|
||||
// Fade in: alpha de 0 a 255, scale de 120% a 100%
|
||||
{
|
||||
float fade_progress = timer_ / APPLOGO_FADE_DURATION;
|
||||
if (fade_progress >= 1.0f) {
|
||||
@@ -81,9 +85,37 @@ void AppLogo::update(float delta_time, AppMode current_mode) {
|
||||
state_ = AppLogoState::VISIBLE;
|
||||
timer_ = 0.0f;
|
||||
current_alpha_ = 255;
|
||||
current_scale_ = 1.0f;
|
||||
squash_y_ = 1.0f;
|
||||
stretch_x_ = 1.0f;
|
||||
rotation_ = 0.0f;
|
||||
} else {
|
||||
// Interpolar alpha linealmente
|
||||
// Interpolar alpha linealmente (0 → 255)
|
||||
current_alpha_ = static_cast<int>(fade_progress * 255.0f);
|
||||
|
||||
if (animation_type_ == AppLogoAnimationType::ELASTIC_STICK) {
|
||||
// Animación elástica tipo "pegatina"
|
||||
// Usar easing elástico para el scale (bounce al final)
|
||||
float elastic_t = easeOutElastic(fade_progress);
|
||||
current_scale_ = 1.2f - (elastic_t * 0.2f);
|
||||
|
||||
// Squash vertical al principio, luego se normaliza con overshoot
|
||||
// Empieza aplastado (0.6), termina normal (1.0) con bounce
|
||||
float squash_t = easeOutBack(fade_progress);
|
||||
squash_y_ = 0.6f + (squash_t * 0.4f);
|
||||
|
||||
// Compensar squash con stretch horizontal (conservación de área)
|
||||
stretch_x_ = 1.0f + (1.0f - squash_y_) * 0.5f;
|
||||
|
||||
// Sin rotación en fade in
|
||||
rotation_ = 0.0f;
|
||||
} else {
|
||||
// Animación simple (solo zoom)
|
||||
current_scale_ = 1.2f - (fade_progress * 0.2f);
|
||||
squash_y_ = 1.0f;
|
||||
stretch_x_ = 1.0f;
|
||||
rotation_ = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -98,7 +130,7 @@ void AppLogo::update(float delta_time, AppMode current_mode) {
|
||||
break;
|
||||
|
||||
case AppLogoState::FADE_OUT:
|
||||
// Fade out: alpha de 255 a 0
|
||||
// Fade out: alpha de 255 a 0, scale de 100% a 120%
|
||||
{
|
||||
float fade_progress = timer_ / APPLOGO_FADE_DURATION;
|
||||
if (fade_progress >= 1.0f) {
|
||||
@@ -106,32 +138,73 @@ void AppLogo::update(float delta_time, AppMode current_mode) {
|
||||
state_ = AppLogoState::HIDDEN;
|
||||
timer_ = 0.0f;
|
||||
current_alpha_ = 0;
|
||||
current_scale_ = 1.0f;
|
||||
squash_y_ = 1.0f;
|
||||
stretch_x_ = 1.0f;
|
||||
rotation_ = 0.0f;
|
||||
} else {
|
||||
// Interpolar alpha linealmente (inverso)
|
||||
// Interpolar alpha linealmente (255 → 0)
|
||||
current_alpha_ = static_cast<int>((1.0f - fade_progress) * 255.0f);
|
||||
|
||||
if (animation_type_ == AppLogoAnimationType::ELASTIC_STICK) {
|
||||
// Animación elástica tipo "despegar pegatina"
|
||||
// Scale crece con easing out (más rápido al principio)
|
||||
current_scale_ = 1.0f + (fade_progress * fade_progress * 0.2f);
|
||||
|
||||
// Stretch vertical (estiramiento al despegarse)
|
||||
squash_y_ = 1.0f + (fade_progress * 0.3f);
|
||||
|
||||
// Squash horizontal (se comprime al estirarse verticalmente)
|
||||
stretch_x_ = 1.0f - (fade_progress * 0.2f);
|
||||
|
||||
// Rotación sutil al despegarse (parece que se tuerce)
|
||||
rotation_ = fade_progress * 0.1f; // ~5.7 grados máximo
|
||||
} else {
|
||||
// Animación simple (solo zoom)
|
||||
current_scale_ = 1.0f + (fade_progress * 0.2f);
|
||||
squash_y_ = 1.0f;
|
||||
stretch_x_ = 1.0f;
|
||||
rotation_ = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Aplicar alpha a la textura
|
||||
// Aplicar alpha y scale al logo
|
||||
if (logo_texture_) {
|
||||
logo_texture_->setAlpha(current_alpha_);
|
||||
}
|
||||
|
||||
if (logo_sprite_) {
|
||||
// Aplicar escala animada al tamaño
|
||||
float scaled_width = base_width_ * current_scale_;
|
||||
float scaled_height = base_height_ * current_scale_;
|
||||
logo_sprite_->setSize(scaled_width, scaled_height);
|
||||
|
||||
// Recentrar con el nuevo tamaño (importante para que el zoom sea desde el centro)
|
||||
updateLogoPosition();
|
||||
}
|
||||
}
|
||||
|
||||
void AppLogo::render() {
|
||||
// Renderizar si NO está en estado HIDDEN (incluye FADE_IN, VISIBLE, FADE_OUT)
|
||||
if (state_ != AppLogoState::HIDDEN && logo_sprite_) {
|
||||
if (state_ != AppLogoState::HIDDEN) {
|
||||
if (animation_type_ == AppLogoAnimationType::ELASTIC_STICK) {
|
||||
// Usar renderizado con geometría para deformaciones
|
||||
renderWithGeometry();
|
||||
} else if (logo_sprite_) {
|
||||
// Usar renderizado simple con Sprite
|
||||
logo_sprite_->render();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AppLogo::updateScreenSize(int screen_width, int screen_height) {
|
||||
screen_width_ = screen_width;
|
||||
screen_height_ = screen_height;
|
||||
|
||||
// Recalcular escala y posición del logo
|
||||
// Recalcular tamaño base del logo para la nueva resolución
|
||||
if (logo_sprite_ && logo_texture_) {
|
||||
float logo_width = static_cast<float>(logo_texture_->getWidth());
|
||||
float logo_height = static_cast<float>(logo_texture_->getHeight());
|
||||
@@ -144,32 +217,26 @@ void AppLogo::updateScreenSize(int screen_width, int screen_height) {
|
||||
float scale_y = quadrant_height / logo_height;
|
||||
float scale = (scale_x < scale_y) ? scale_x : scale_y;
|
||||
|
||||
// Aplicar escala
|
||||
float scaled_width = logo_width * scale;
|
||||
float scaled_height = logo_height * scale;
|
||||
// Recalcular tamaño base
|
||||
base_width_ = logo_width * scale;
|
||||
base_height_ = logo_height * scale;
|
||||
|
||||
// Aplicar escala actual (respeta la animación en curso)
|
||||
float scaled_width = base_width_ * current_scale_;
|
||||
float scaled_height = base_height_ * current_scale_;
|
||||
logo_sprite_->setSize(scaled_width, scaled_height);
|
||||
|
||||
// Posicionar logo
|
||||
// Reposicionar logo
|
||||
updateLogoPosition();
|
||||
}
|
||||
}
|
||||
|
||||
void AppLogo::updateLogoPosition() {
|
||||
if (!logo_sprite_ || !logo_texture_) return;
|
||||
if (!logo_sprite_) return;
|
||||
|
||||
// Calcular tamaño escalado del logo (ya configurado en setSize)
|
||||
float logo_width = static_cast<float>(logo_texture_->getWidth());
|
||||
float logo_height = static_cast<float>(logo_texture_->getHeight());
|
||||
|
||||
float quadrant_width = screen_width_ / 2.0f;
|
||||
float quadrant_height = screen_height_ / 2.0f;
|
||||
|
||||
float scale_x = quadrant_width / logo_width;
|
||||
float scale_y = quadrant_height / logo_height;
|
||||
float scale = (scale_x < scale_y) ? scale_x : scale_y;
|
||||
|
||||
float scaled_width = logo_width * scale;
|
||||
float scaled_height = logo_height * scale;
|
||||
// Usar el tamaño actual del logo (base_width/height * current_scale_)
|
||||
float current_width = base_width_ * current_scale_;
|
||||
float current_height = base_height_ * current_scale_;
|
||||
|
||||
// Centro del cuadrante inferior derecho
|
||||
// Cuadrante inferior derecho va de (width/2, height/2) a (width, height)
|
||||
@@ -178,8 +245,111 @@ void AppLogo::updateLogoPosition() {
|
||||
float quadrant_center_y = screen_height_ * 0.75f;
|
||||
|
||||
// Centrar el logo en ese punto (sprite se posiciona por esquina superior izquierda)
|
||||
float pos_x = quadrant_center_x - (scaled_width / 2.0f);
|
||||
float pos_y = quadrant_center_y - (scaled_height / 2.0f);
|
||||
float pos_x = quadrant_center_x - (current_width / 2.0f);
|
||||
float pos_y = quadrant_center_y - (current_height / 2.0f);
|
||||
|
||||
logo_sprite_->setPos({pos_x, pos_y});
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Funciones de easing para animaciones elásticas
|
||||
// ============================================================================
|
||||
|
||||
float AppLogo::easeOutElastic(float t) {
|
||||
// Elastic easing out: bounce elástico al final
|
||||
const float c4 = (2.0f * 3.14159f) / 3.0f;
|
||||
|
||||
if (t == 0.0f) return 0.0f;
|
||||
if (t == 1.0f) return 1.0f;
|
||||
|
||||
return powf(2.0f, -10.0f * t) * sinf((t * 10.0f - 0.75f) * c4) + 1.0f;
|
||||
}
|
||||
|
||||
float AppLogo::easeOutBack(float t) {
|
||||
// Back easing out: overshoot suave al final
|
||||
const float c1 = 1.70158f;
|
||||
const float c3 = c1 + 1.0f;
|
||||
|
||||
return 1.0f + c3 * powf(t - 1.0f, 3.0f) + c1 * powf(t - 1.0f, 2.0f);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Renderizado con geometría deformada (para animación ELASTIC_STICK)
|
||||
// ============================================================================
|
||||
|
||||
void AppLogo::renderWithGeometry() {
|
||||
if (!logo_texture_ || !renderer_) return;
|
||||
|
||||
// Calcular tamaño con escala y deformaciones aplicadas
|
||||
float width = base_width_ * current_scale_ * stretch_x_;
|
||||
float height = base_height_ * current_scale_ * squash_y_;
|
||||
|
||||
// Centro del cuadrante inferior derecho (mismo que updateLogoPosition)
|
||||
float quadrant_center_x = screen_width_ * 0.75f;
|
||||
float quadrant_center_y = screen_height_ * 0.75f;
|
||||
|
||||
// Calcular posición centrada
|
||||
float center_x = quadrant_center_x;
|
||||
float center_y = quadrant_center_y;
|
||||
|
||||
// Pre-calcular seno y coseno de rotación
|
||||
float cos_rot = cosf(rotation_);
|
||||
float sin_rot = sinf(rotation_);
|
||||
|
||||
// Crear 4 vértices del quad (centrado en center_x, center_y)
|
||||
SDL_Vertex vertices[4];
|
||||
|
||||
// Offset desde el centro
|
||||
float half_w = width / 2.0f;
|
||||
float half_h = height / 2.0f;
|
||||
|
||||
// Vértice superior izquierdo (rotado)
|
||||
{
|
||||
float local_x = -half_w;
|
||||
float local_y = -half_h;
|
||||
float rotated_x = local_x * cos_rot - local_y * sin_rot;
|
||||
float rotated_y = local_x * sin_rot + local_y * cos_rot;
|
||||
vertices[0].position = {center_x + rotated_x, center_y + rotated_y};
|
||||
vertices[0].tex_coord = {0.0f, 0.0f};
|
||||
vertices[0].color = {1.0f, 1.0f, 1.0f, 1.0f}; // Color blanco (textura se modula con alpha)
|
||||
}
|
||||
|
||||
// Vértice superior derecho (rotado)
|
||||
{
|
||||
float local_x = half_w;
|
||||
float local_y = -half_h;
|
||||
float rotated_x = local_x * cos_rot - local_y * sin_rot;
|
||||
float rotated_y = local_x * sin_rot + local_y * cos_rot;
|
||||
vertices[1].position = {center_x + rotated_x, center_y + rotated_y};
|
||||
vertices[1].tex_coord = {1.0f, 0.0f};
|
||||
vertices[1].color = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
}
|
||||
|
||||
// Vértice inferior derecho (rotado)
|
||||
{
|
||||
float local_x = half_w;
|
||||
float local_y = half_h;
|
||||
float rotated_x = local_x * cos_rot - local_y * sin_rot;
|
||||
float rotated_y = local_x * sin_rot + local_y * cos_rot;
|
||||
vertices[2].position = {center_x + rotated_x, center_y + rotated_y};
|
||||
vertices[2].tex_coord = {1.0f, 1.0f};
|
||||
vertices[2].color = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
}
|
||||
|
||||
// Vértice inferior izquierdo (rotado)
|
||||
{
|
||||
float local_x = -half_w;
|
||||
float local_y = half_h;
|
||||
float rotated_x = local_x * cos_rot - local_y * sin_rot;
|
||||
float rotated_y = local_x * sin_rot + local_y * cos_rot;
|
||||
vertices[3].position = {center_x + rotated_x, center_y + rotated_y};
|
||||
vertices[3].tex_coord = {0.0f, 1.0f};
|
||||
vertices[3].color = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
}
|
||||
|
||||
// Índices para 2 triángulos
|
||||
int indices[6] = {0, 1, 2, 2, 3, 0};
|
||||
|
||||
// Renderizar con la textura del logo
|
||||
SDL_RenderGeometry(renderer_, logo_texture_->getSDLTexture(), vertices, 4, indices, 6);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,12 @@ enum class AppLogoState {
|
||||
FADE_OUT // Desapareciendo (alpha 255 → 0)
|
||||
};
|
||||
|
||||
// Tipo de animación de entrada/salida
|
||||
enum class AppLogoAnimationType {
|
||||
ZOOM_ONLY, // Solo zoom simple (120% → 100% → 120%)
|
||||
ELASTIC_STICK // Zoom + deformación elástica tipo "pegatina"
|
||||
};
|
||||
|
||||
class AppLogo {
|
||||
public:
|
||||
AppLogo() = default;
|
||||
@@ -41,10 +47,31 @@ class AppLogo {
|
||||
AppLogoState state_ = AppLogoState::HIDDEN; // Estado actual de la máquina de estados
|
||||
float timer_ = 0.0f; // Contador de tiempo para estado actual
|
||||
int current_alpha_ = 0; // Alpha actual (0-255)
|
||||
float current_scale_ = 1.0f; // Escala actual (1.0 = 100%)
|
||||
|
||||
// Tipo de animación (FIJO para testing: ELASTIC_STICK)
|
||||
AppLogoAnimationType animation_type_ = AppLogoAnimationType::ELASTIC_STICK;
|
||||
|
||||
// Variables de deformación elástica (para ELASTIC_STICK)
|
||||
float squash_y_ = 1.0f; // Factor de aplastamiento vertical (1.0 = normal)
|
||||
float stretch_x_ = 1.0f; // Factor de estiramiento horizontal (1.0 = normal)
|
||||
float rotation_ = 0.0f; // Rotación en radianes (para efecto despegar)
|
||||
|
||||
int screen_width_ = 0; // Ancho de pantalla (para centrar)
|
||||
int screen_height_ = 0; // Alto de pantalla (para centrar)
|
||||
|
||||
// Tamaño base del logo (calculado una vez)
|
||||
float base_width_ = 0.0f;
|
||||
float base_height_ = 0.0f;
|
||||
|
||||
// SDL renderer (necesario para renderizado con geometría)
|
||||
SDL_Renderer* renderer_ = nullptr;
|
||||
|
||||
// Métodos privados auxiliares
|
||||
void updateLogoPosition(); // Centrar logo en pantalla
|
||||
void renderWithGeometry(); // Renderizar con vértices deformados
|
||||
|
||||
// Funciones de easing
|
||||
float easeOutElastic(float t); // Elastic bounce out
|
||||
float easeOutBack(float t); // Overshoot out
|
||||
};
|
||||
|
||||
78
source/external/dbgtxt.h
vendored
78
source/external/dbgtxt.h
vendored
@@ -1,78 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
namespace {
|
||||
SDL_Texture* dbg_tex = nullptr;
|
||||
SDL_Renderer* dbg_ren = nullptr;
|
||||
} // namespace
|
||||
|
||||
inline void dbg_init(SDL_Renderer* renderer) {
|
||||
dbg_ren = renderer;
|
||||
Uint8 font[448] = {0x42, 0x4D, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x01, 0x00, 0x00, 0x12, 0x0B, 0x00, 0x00, 0x12, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x18, 0xF3, 0x83, 0x83, 0xCF, 0x83, 0x87, 0x00, 0x00, 0xF3, 0x39, 0x39, 0xCF, 0x79, 0xF3, 0x00, 0x00, 0x01, 0xF9, 0x39, 0xCF, 0x61, 0xF9, 0x00, 0x00, 0x33, 0xF9, 0x03, 0xE7, 0x87, 0x81, 0x00, 0x00, 0x93, 0x03, 0x3F, 0xF3, 0x1B, 0x39, 0x00, 0x00, 0xC3, 0x3F, 0x9F, 0x39, 0x3B, 0x39, 0x00, 0x41, 0xE3, 0x03, 0xC3, 0x01, 0x87, 0x83, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xE7, 0x01, 0xC7, 0x81, 0x01, 0x83, 0x00, 0x00, 0xE7, 0x1F, 0x9B, 0xE7, 0x1F, 0x39, 0x00, 0x00, 0xE7, 0x8F, 0x39, 0xE7, 0x87, 0xF9, 0x00, 0x00, 0xC3, 0xC7, 0x39, 0xE7, 0xC3, 0xC3, 0x00, 0x00, 0x99, 0xE3, 0x39, 0xE7, 0xF1, 0xE7, 0x00, 0x00, 0x99, 0xF1, 0xB3, 0xC7, 0x39, 0xF3, 0x00, 0x00, 0x99, 0x01, 0xC7, 0xE7, 0x83, 0x81, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x83, 0xE7, 0x83, 0xEF, 0x39, 0x39, 0x00, 0x00, 0x39, 0xE7, 0x39, 0xC7, 0x11, 0x11, 0x00, 0x00, 0xF9, 0xE7, 0x39, 0x83, 0x01, 0x83, 0x00, 0x00, 0x83, 0xE7, 0x39, 0x11, 0x01, 0xC7, 0x00, 0x00, 0x3F, 0xE7, 0x39, 0x39, 0x29, 0x83, 0x00, 0x00, 0x33, 0xE7, 0x39, 0x39, 0x39, 0x11, 0x00, 0x00, 0x87, 0x81, 0x39, 0x39, 0x39, 0x39, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x39, 0x39, 0x83, 0x3F, 0x85, 0x31, 0x00, 0x00, 0x39, 0x31, 0x39, 0x3F, 0x33, 0x23, 0x00, 0x00, 0x29, 0x21, 0x39, 0x03, 0x21, 0x07, 0x00, 0x00, 0x01, 0x01, 0x39, 0x39, 0x39, 0x31, 0x00, 0x00, 0x01, 0x09, 0x39, 0x39, 0x39, 0x39, 0x00, 0x00, 0x11, 0x19, 0x39, 0x39, 0x39, 0x39, 0x00, 0x00, 0x39, 0x39, 0x83, 0x03, 0x83, 0x03, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xC1, 0x39, 0x81, 0x83, 0x31, 0x01, 0x00, 0x00, 0x99, 0x39, 0xE7, 0x39, 0x23, 0x3F, 0x00, 0x00, 0x39, 0x39, 0xE7, 0xF9, 0x07, 0x3F, 0x00, 0x00, 0x31, 0x01, 0xE7, 0xF9, 0x0F, 0x3F, 0x00, 0x00, 0x3F, 0x39, 0xE7, 0xF9, 0x27, 0x3F, 0x00, 0x00, 0x9F, 0x39, 0xE7, 0xF9, 0x33, 0x3F, 0x00, 0x00, 0xC1, 0x39, 0x81, 0xF9, 0x39, 0x3F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x39, 0x03, 0xC3, 0x07, 0x01, 0x3F, 0x00, 0x00, 0x39, 0x39, 0x99, 0x33, 0x3F, 0x3F, 0x00, 0x00, 0x01, 0x39, 0x3F, 0x39, 0x3F, 0x3F, 0x00, 0x00, 0x39, 0x03, 0x3F, 0x39, 0x03, 0x03, 0x00, 0x00, 0x39, 0x39, 0x3F, 0x39, 0x3F, 0x3F, 0x00, 0x00, 0x93, 0x39, 0x99, 0x33, 0x3F, 0x3F, 0x00, 0x00, 0xC7, 0x03, 0xC3, 0x07, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
// Cargar surface del bitmap font
|
||||
SDL_Surface* font_surface = SDL_LoadBMP_IO(SDL_IOFromMem(font, 448), 1);
|
||||
if (font_surface != nullptr) {
|
||||
// Crear una nueva surface de 32 bits con canal alpha
|
||||
SDL_Surface* rgba_surface = SDL_CreateSurface(font_surface->w, font_surface->h, SDL_PIXELFORMAT_RGBA8888);
|
||||
if (rgba_surface != nullptr) {
|
||||
// Obtener píxeles de ambas surfaces
|
||||
Uint8* src_pixels = (Uint8*)font_surface->pixels;
|
||||
Uint32* dst_pixels = (Uint32*)rgba_surface->pixels;
|
||||
|
||||
int width = font_surface->w;
|
||||
int height = font_surface->h;
|
||||
|
||||
// Procesar cada píxel
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
int byte_index = y * font_surface->pitch + (x / 8);
|
||||
int bit_index = 7 - (x % 8);
|
||||
|
||||
// Extraer bit del bitmap monocromo
|
||||
bool is_white = (src_pixels[byte_index] >> bit_index) & 1;
|
||||
|
||||
if (is_white) // Fondo blanco original -> transparente
|
||||
{
|
||||
dst_pixels[y * width + x] = 0x00000000; // Transparente
|
||||
} else // Texto negro original -> blanco opaco
|
||||
{
|
||||
dst_pixels[y * width + x] = 0xFFFFFFFF; // Blanco opaco
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dbg_tex = SDL_CreateTextureFromSurface(dbg_ren, rgba_surface);
|
||||
SDL_DestroySurface(rgba_surface);
|
||||
}
|
||||
SDL_DestroySurface(font_surface);
|
||||
}
|
||||
|
||||
// Configurar filtro nearest neighbor para píxel perfect del texto
|
||||
if (dbg_tex != nullptr) {
|
||||
SDL_SetTextureScaleMode(dbg_tex, SDL_SCALEMODE_NEAREST);
|
||||
// Configurar blend mode para transparencia normal
|
||||
SDL_SetTextureBlendMode(dbg_tex, SDL_BLENDMODE_BLEND);
|
||||
}
|
||||
}
|
||||
|
||||
inline void dbg_print(int x, int y, const char* text, Uint8 r, Uint8 g, Uint8 b) {
|
||||
int cc = 0;
|
||||
SDL_SetTextureColorMod(dbg_tex, r, g, b);
|
||||
SDL_FRect src = {0, 0, 8, 8};
|
||||
SDL_FRect dst = {static_cast<float>(x), static_cast<float>(y), 8, 8};
|
||||
while (text[cc] != 0) {
|
||||
if (text[cc] != 32) {
|
||||
if (text[cc] >= 65) {
|
||||
src.x = ((text[cc] - 65) % 6) * 8;
|
||||
src.y = ((text[cc] - 65) / 6) * 8;
|
||||
} else {
|
||||
src.x = ((text[cc] - 22) % 6) * 8;
|
||||
src.y = ((text[cc] - 22) / 6) * 8;
|
||||
}
|
||||
|
||||
SDL_RenderTexture(dbg_ren, dbg_tex, &src, &dst);
|
||||
}
|
||||
cc++;
|
||||
dst.x += 8;
|
||||
}
|
||||
}
|
||||
@@ -76,8 +76,10 @@ void ShapeManager::toggleShapeMode(bool force_gravity_on_exit) {
|
||||
|
||||
// Si estamos en LOGO MODE, generar threshold aleatorio de convergencia (75-100%)
|
||||
if (state_mgr_ && state_mgr_->getCurrentMode() == AppMode::LOGO) {
|
||||
/*
|
||||
float logo_convergence_threshold = LOGO_CONVERGENCE_MIN +
|
||||
(rand() % 1000) / 1000.0f * (LOGO_CONVERGENCE_MAX - LOGO_CONVERGENCE_MIN);
|
||||
*/
|
||||
shape_convergence_ = 0.0f; // Reset convergencia al entrar
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -88,9 +88,6 @@ HelpOverlay::~HelpOverlay() {
|
||||
|
||||
void HelpOverlay::toggle() {
|
||||
visible_ = !visible_;
|
||||
SDL_Log("HelpOverlay::toggle() - visible=%s, box_pos=(%d,%d), box_size=%dx%d, physical=%dx%d",
|
||||
visible_ ? "TRUE" : "FALSE", box_x_, box_y_, box_width_, box_height_,
|
||||
physical_width_, physical_height_);
|
||||
}
|
||||
|
||||
void HelpOverlay::initialize(SDL_Renderer* renderer, ThemeManager* theme_mgr, int physical_width, int physical_height, int font_size) {
|
||||
@@ -103,12 +100,7 @@ void HelpOverlay::initialize(SDL_Renderer* renderer, ThemeManager* theme_mgr, in
|
||||
text_renderer_ = new TextRenderer();
|
||||
text_renderer_->init(renderer, "data/fonts/FunnelSans-Regular.ttf", font_size, true);
|
||||
|
||||
SDL_Log("HelpOverlay::initialize() - physical=%dx%d, font_size=%d", physical_width, physical_height, font_size);
|
||||
|
||||
calculateBoxDimensions();
|
||||
|
||||
SDL_Log("HelpOverlay::initialize() - AFTER calculateBoxDimensions: box_pos=(%d,%d), box_size=%dx%d",
|
||||
box_x_, box_y_, box_width_, box_height_);
|
||||
}
|
||||
|
||||
void HelpOverlay::updatePhysicalWindowSize(int physical_width, int physical_height) {
|
||||
@@ -135,11 +127,6 @@ void HelpOverlay::reinitializeFontSize(int new_font_size) {
|
||||
}
|
||||
|
||||
void HelpOverlay::updateAll(int font_size, int physical_width, int physical_height) {
|
||||
SDL_Log("HelpOverlay::updateAll() - INPUT: font_size=%d, physical=%dx%d",
|
||||
font_size, physical_width, physical_height);
|
||||
SDL_Log("HelpOverlay::updateAll() - BEFORE: box_pos=(%d,%d), box_size=%dx%d",
|
||||
box_x_, box_y_, box_width_, box_height_);
|
||||
|
||||
// Actualizar dimensiones físicas PRIMERO
|
||||
physical_width_ = physical_width;
|
||||
physical_height_ = physical_height;
|
||||
@@ -154,9 +141,6 @@ void HelpOverlay::updateAll(int font_size, int physical_width, int physical_heig
|
||||
|
||||
// Marcar textura para regeneración completa
|
||||
texture_needs_rebuild_ = true;
|
||||
|
||||
SDL_Log("HelpOverlay::updateAll() - AFTER: box_pos=(%d,%d), box_size=%dx%d",
|
||||
box_x_, box_y_, box_width_, box_height_);
|
||||
}
|
||||
|
||||
void HelpOverlay::calculateTextDimensions(int& max_width, int& total_height) {
|
||||
@@ -246,15 +230,10 @@ void HelpOverlay::calculateTextDimensions(int& max_width, int& total_height) {
|
||||
}
|
||||
|
||||
void HelpOverlay::calculateBoxDimensions() {
|
||||
SDL_Log("HelpOverlay::calculateBoxDimensions() START - physical=%dx%d", physical_width_, physical_height_);
|
||||
|
||||
// Calcular dimensiones necesarias según el texto
|
||||
int text_width, text_height;
|
||||
calculateTextDimensions(text_width, text_height);
|
||||
|
||||
SDL_Log("HelpOverlay::calculateBoxDimensions() - text_width=%d, text_height=%d, col1_width=%d, col2_width=%d",
|
||||
text_width, text_height, column1_width_, column2_width_);
|
||||
|
||||
// Usar directamente el ancho y altura calculados según el contenido
|
||||
box_width_ = text_width;
|
||||
|
||||
@@ -265,17 +244,11 @@ void HelpOverlay::calculateBoxDimensions() {
|
||||
// Centrar en pantalla
|
||||
box_x_ = (physical_width_ - box_width_) / 2;
|
||||
box_y_ = (physical_height_ - box_height_) / 2;
|
||||
|
||||
SDL_Log("HelpOverlay::calculateBoxDimensions() END - box_pos=(%d,%d), box_size=%dx%d, max_height=%d",
|
||||
box_x_, box_y_, box_width_, box_height_, max_height);
|
||||
}
|
||||
|
||||
void HelpOverlay::rebuildCachedTexture() {
|
||||
if (!renderer_ || !theme_mgr_ || !text_renderer_) return;
|
||||
|
||||
SDL_Log("HelpOverlay::rebuildCachedTexture() - Regenerando textura: box_size=%dx%d, box_pos=(%d,%d)",
|
||||
box_width_, box_height_, box_x_, box_y_);
|
||||
|
||||
// Destruir textura anterior si existe
|
||||
if (cached_texture_) {
|
||||
SDL_DestroyTexture(cached_texture_);
|
||||
@@ -471,9 +444,6 @@ void HelpOverlay::render(SDL_Renderer* renderer) {
|
||||
int centered_x = viewport.x + (viewport.w - box_width_) / 2;
|
||||
int centered_y = viewport.y + (viewport.h - box_height_) / 2;
|
||||
|
||||
SDL_Log("HelpOverlay::render() - viewport=(%d,%d,%dx%d), centered_pos=(%d,%d), box_size=%dx%d",
|
||||
viewport.x, viewport.y, viewport.w, viewport.h, centered_x, centered_y, box_width_, box_height_);
|
||||
|
||||
// Renderizar la textura cacheada centrada en el viewport
|
||||
SDL_FRect dest_rect;
|
||||
dest_rect.x = static_cast<float>(centered_x);
|
||||
|
||||
Reference in New Issue
Block a user