window_message: animació d'entrada i eixida de la finestra
This commit is contained in:
@@ -28,13 +28,14 @@ DefineButtons::DefineButtons()
|
|||||||
config.border_color = Color{100, 150, 200, 255}; // Borde azul claro
|
config.border_color = Color{100, 150, 200, 255}; // Borde azul claro
|
||||||
config.title_color = Color{100, 150, 200, 255}; // Titulo azul claro
|
config.title_color = Color{100, 150, 200, 255}; // Titulo azul claro
|
||||||
config.text_color = Color{220, 220, 220, 255}; // Texto gris claro
|
config.text_color = Color{220, 220, 220, 255}; // Texto gris claro
|
||||||
config.padding = 15.0f;
|
config.padding = 15.0F;
|
||||||
config.line_spacing = 5.0f;
|
config.line_spacing = 5.0F;
|
||||||
config.title_separator_spacing = 15;
|
config.title_separator_spacing = 15;
|
||||||
config.min_width = 250.0f;
|
config.min_width = 250.0F;
|
||||||
config.text_safety_margin = 15.0f;
|
config.text_safety_margin = 15.0F;
|
||||||
config.min_width = 100;
|
config.min_width = 100;
|
||||||
config.min_height = 32;
|
config.min_height = 32;
|
||||||
|
config.animation_duration = 0.5F;
|
||||||
|
|
||||||
auto text_renderer = Resource::get()->getText("04b_25_flat");
|
auto text_renderer = Resource::get()->getText("04b_25_flat");
|
||||||
window_message_ = std::make_unique<WindowMessage>(
|
window_message_ = std::make_unique<WindowMessage>(
|
||||||
@@ -157,8 +158,6 @@ void DefineButtons::checkEnd() {
|
|||||||
if (window_message_) {
|
if (window_message_) {
|
||||||
window_message_->clearTexts();
|
window_message_->clearTexts();
|
||||||
window_message_->addText(Lang::getText("[DEFINE_BUTTONS] CONFIGURATION_COMPLETE"));
|
window_message_->addText(Lang::getText("[DEFINE_BUTTONS] CONFIGURATION_COMPLETE"));
|
||||||
//window_message_->autoSize();
|
|
||||||
//window_message_->centerOnScreen();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Se deshabilitará desde el ServiceMenu después de un breve delay
|
// Se deshabilitará desde el ServiceMenu después de un breve delay
|
||||||
|
|||||||
@@ -55,7 +55,6 @@ class ServiceMenu {
|
|||||||
void adjustOption(bool adjust_up);
|
void adjustOption(bool adjust_up);
|
||||||
void selectOption();
|
void selectOption();
|
||||||
void moveBack();
|
void moveBack();
|
||||||
void checkEvents(const SDL_Event &event); // Nuevo método para eventos
|
|
||||||
|
|
||||||
// --- Método para manejar eventos (llamado desde GlobalEvents) ---
|
// --- Método para manejar eventos (llamado desde GlobalEvents) ---
|
||||||
void handleEvent(const SDL_Event &event);
|
void handleEvent(const SDL_Event &event);
|
||||||
|
|||||||
@@ -35,48 +35,53 @@ void WindowMessage::render() {
|
|||||||
config_.border_color.b, config_.border_color.a);
|
config_.border_color.b, config_.border_color.a);
|
||||||
SDL_RenderRect(renderer, &rect_);
|
SDL_RenderRect(renderer, &rect_);
|
||||||
|
|
||||||
float current_y = rect_.y + config_.padding;
|
// Solo mostrar contenido si no estamos en animación de show/hide
|
||||||
float available_width = getAvailableTextWidth();
|
if (shouldShowContent()) {
|
||||||
|
float current_y = rect_.y + config_.padding;
|
||||||
|
float available_width = getAvailableTextWidth();
|
||||||
|
|
||||||
// Dibujar título si existe
|
// Dibujar título si existe
|
||||||
if (!title_.empty()) {
|
if (!title_.empty()) {
|
||||||
std::string visible_title = getTruncatedText(title_, available_width);
|
std::string visible_title = getTruncatedText(title_, available_width);
|
||||||
text_renderer_->writeStyle(
|
if (!visible_title.empty()) {
|
||||||
rect_.x + rect_.w / 2.0f,
|
text_renderer_->writeStyle(
|
||||||
current_y,
|
rect_.x + rect_.w / 2.0f,
|
||||||
visible_title,
|
current_y,
|
||||||
title_style_);
|
visible_title,
|
||||||
current_y += text_renderer_->getCharacterSize() + config_.title_separator_spacing;
|
title_style_);
|
||||||
|
}
|
||||||
|
current_y += text_renderer_->getCharacterSize() + config_.title_separator_spacing;
|
||||||
|
|
||||||
// Línea separadora debajo del título (solo si hay título visible)
|
// Línea separadora debajo del título (solo si hay título visible)
|
||||||
if (!visible_title.empty()) {
|
if (!visible_title.empty()) {
|
||||||
SDL_SetRenderDrawColor(renderer, config_.border_color.r, config_.border_color.g,
|
SDL_SetRenderDrawColor(renderer, config_.border_color.r, config_.border_color.g,
|
||||||
config_.border_color.b, config_.border_color.a);
|
config_.border_color.b, config_.border_color.a);
|
||||||
SDL_RenderLine(renderer,
|
SDL_RenderLine(renderer,
|
||||||
rect_.x + config_.padding,
|
rect_.x + config_.padding,
|
||||||
current_y - config_.title_separator_spacing / 2.0f,
|
current_y - config_.title_separator_spacing / 2.0f,
|
||||||
rect_.x + rect_.w - config_.padding,
|
rect_.x + rect_.w - config_.padding,
|
||||||
current_y - config_.title_separator_spacing / 2.0f);
|
current_y - config_.title_separator_spacing / 2.0f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Dibujar textos
|
// Dibujar textos
|
||||||
for (const auto& text : texts_) {
|
for (const auto& text : texts_) {
|
||||||
std::string visible_text = getTruncatedText(text, available_width);
|
std::string visible_text = getTruncatedText(text, available_width);
|
||||||
if (!visible_text.empty()) {
|
if (!visible_text.empty()) {
|
||||||
text_renderer_->writeStyle(
|
text_renderer_->writeStyle(
|
||||||
rect_.x + rect_.w / 2.0f,
|
rect_.x + rect_.w / 2.0f,
|
||||||
current_y,
|
current_y,
|
||||||
visible_text,
|
visible_text,
|
||||||
text_style_);
|
text_style_);
|
||||||
|
}
|
||||||
|
current_y += text_renderer_->getCharacterSize() + config_.line_spacing;
|
||||||
}
|
}
|
||||||
current_y += text_renderer_->getCharacterSize() + config_.line_spacing;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowMessage::update() {
|
void WindowMessage::update() {
|
||||||
// Actualizar animación de redimensionado
|
// Actualizar animaciones
|
||||||
if (resize_animation_.active) {
|
if (show_hide_animation_.active || resize_animation_.active) {
|
||||||
// Aquí necesitarías el delta_time del game loop
|
// Aquí necesitarías el delta_time del game loop
|
||||||
// Por ahora usamos un valor fijo, pero idealmente se pasaría como parámetro
|
// Por ahora usamos un valor fijo, pero idealmente se pasaría como parámetro
|
||||||
float delta_time = 1.0f / 60.0f; // Asumiendo 60 FPS
|
float delta_time = 1.0f / 60.0f; // Asumiendo 60 FPS
|
||||||
@@ -85,12 +90,37 @@ void WindowMessage::update() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WindowMessage::show() {
|
void WindowMessage::show() {
|
||||||
ensureTextFits();
|
if (visible_) {
|
||||||
|
return; // Ya visible
|
||||||
|
}
|
||||||
|
|
||||||
visible_ = true;
|
visible_ = true;
|
||||||
|
ensureTextFits();
|
||||||
|
|
||||||
|
// Detener cualquier animación anterior
|
||||||
|
resize_animation_.stop();
|
||||||
|
|
||||||
|
// Iniciar animación de mostrar desde tamaño 0
|
||||||
|
show_hide_animation_.startShow(rect_.w, rect_.h);
|
||||||
|
rect_.w = 0.0f;
|
||||||
|
rect_.h = 0.0f;
|
||||||
|
updatePosition(); // Reposicionar con tamaño 0
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowMessage::hide() {
|
void WindowMessage::hide() {
|
||||||
visible_ = false;
|
if (!visible_) {
|
||||||
|
return; // Ya oculto
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detener cualquier animación anterior
|
||||||
|
resize_animation_.stop();
|
||||||
|
|
||||||
|
// Guardar el tamaño actual para la animación
|
||||||
|
show_hide_animation_.target_width = rect_.w;
|
||||||
|
show_hide_animation_.target_height = rect_.h;
|
||||||
|
|
||||||
|
// Iniciar animación de ocultar hacia tamaño 0
|
||||||
|
show_hide_animation_.startHide();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowMessage::setTitle(const std::string& title) {
|
void WindowMessage::setTitle(const std::string& title) {
|
||||||
@@ -137,6 +167,10 @@ void WindowMessage::centerOnScreen() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WindowMessage::autoSize() {
|
void WindowMessage::autoSize() {
|
||||||
|
if (show_hide_animation_.active) {
|
||||||
|
return; // No redimensionar durante show/hide
|
||||||
|
}
|
||||||
|
|
||||||
if (resize_animation_.active) {
|
if (resize_animation_.active) {
|
||||||
resize_animation_.stop(); // Detener animación anterior
|
resize_animation_.stop(); // Detener animación anterior
|
||||||
}
|
}
|
||||||
@@ -263,13 +297,63 @@ void WindowMessage::triggerAutoResize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WindowMessage::updateAnimation(float delta_time) {
|
void WindowMessage::updateAnimation(float delta_time) {
|
||||||
|
if (show_hide_animation_.active) {
|
||||||
|
updateShowHideAnimation(delta_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resize_animation_.active) {
|
||||||
|
updateResizeAnimation(delta_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowMessage::updateShowHideAnimation(float delta_time) {
|
||||||
|
if (!show_hide_animation_.active) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
show_hide_animation_.elapsed += delta_time;
|
||||||
|
|
||||||
|
if (show_hide_animation_.isFinished(config_.animation_duration)) {
|
||||||
|
// Animación terminada
|
||||||
|
if (show_hide_animation_.type == ShowHideAnimation::Type::SHOWING) {
|
||||||
|
// Mostrar completado
|
||||||
|
rect_.w = show_hide_animation_.target_width;
|
||||||
|
rect_.h = show_hide_animation_.target_height;
|
||||||
|
} else if (show_hide_animation_.type == ShowHideAnimation::Type::HIDING) {
|
||||||
|
// Ocultar completado
|
||||||
|
rect_.w = 0.0f;
|
||||||
|
rect_.h = 0.0f;
|
||||||
|
visible_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
show_hide_animation_.stop();
|
||||||
|
updatePosition();
|
||||||
|
} else {
|
||||||
|
// Interpolar el tamaño
|
||||||
|
float progress = easeOut(show_hide_animation_.getProgress(config_.animation_duration));
|
||||||
|
|
||||||
|
if (show_hide_animation_.type == ShowHideAnimation::Type::SHOWING) {
|
||||||
|
// Crecer desde 0 hasta el tamaño objetivo
|
||||||
|
rect_.w = show_hide_animation_.target_width * progress;
|
||||||
|
rect_.h = show_hide_animation_.target_height * progress;
|
||||||
|
} else if (show_hide_animation_.type == ShowHideAnimation::Type::HIDING) {
|
||||||
|
// Decrecer desde el tamaño actual hasta 0
|
||||||
|
rect_.w = show_hide_animation_.target_width * (1.0f - progress);
|
||||||
|
rect_.h = show_hide_animation_.target_height * (1.0f - progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
updatePosition(); // Mantener la posición centrada durante la animación
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowMessage::updateResizeAnimation(float delta_time) {
|
||||||
if (!resize_animation_.active) {
|
if (!resize_animation_.active) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
resize_animation_.elapsed += delta_time;
|
resize_animation_.elapsed += delta_time;
|
||||||
|
|
||||||
if (resize_animation_.isFinished()) {
|
if (resize_animation_.isFinished(config_.animation_duration)) {
|
||||||
// Animación terminada
|
// Animación terminada
|
||||||
rect_.w = resize_animation_.target_width;
|
rect_.w = resize_animation_.target_width;
|
||||||
rect_.h = resize_animation_.target_height;
|
rect_.h = resize_animation_.target_height;
|
||||||
@@ -277,7 +361,7 @@ void WindowMessage::updateAnimation(float delta_time) {
|
|||||||
updatePosition();
|
updatePosition();
|
||||||
} else {
|
} else {
|
||||||
// Interpolar el tamaño
|
// Interpolar el tamaño
|
||||||
float progress = easeOut(resize_animation_.getProgress());
|
float progress = easeOut(resize_animation_.getProgress(config_.animation_duration));
|
||||||
|
|
||||||
rect_.w = resize_animation_.start_width +
|
rect_.w = resize_animation_.start_width +
|
||||||
(resize_animation_.target_width - resize_animation_.start_width) * progress;
|
(resize_animation_.target_width - resize_animation_.start_width) * progress;
|
||||||
@@ -288,6 +372,11 @@ void WindowMessage::updateAnimation(float delta_time) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto WindowMessage::shouldShowContent() const -> bool {
|
||||||
|
// No mostrar contenido durante animaciones de show/hide
|
||||||
|
return !show_hide_animation_.active;
|
||||||
|
}
|
||||||
|
|
||||||
auto WindowMessage::easeOut(float t) const -> float {
|
auto WindowMessage::easeOut(float t) const -> float {
|
||||||
// Función de suavizado ease-out cuadrática
|
// Función de suavizado ease-out cuadrática
|
||||||
return 1.0f - (1.0f - t) * (1.0f - t);
|
return 1.0f - (1.0f - t) * (1.0f - t);
|
||||||
|
|||||||
@@ -37,6 +37,9 @@ class WindowMessage {
|
|||||||
// Margen de seguridad para texto
|
// Margen de seguridad para texto
|
||||||
float text_safety_margin; // Margen extra para evitar texto cortado
|
float text_safety_margin; // Margen extra para evitar texto cortado
|
||||||
|
|
||||||
|
// Animaciones
|
||||||
|
float animation_duration; // Duración en segundos para todas las animaciones
|
||||||
|
|
||||||
// Constructor con valores por defecto
|
// Constructor con valores por defecto
|
||||||
Config()
|
Config()
|
||||||
: bg_color{40, 40, 60, 220}
|
: bg_color{40, 40, 60, 220}
|
||||||
@@ -51,6 +54,7 @@ class WindowMessage {
|
|||||||
, max_width_ratio{0.8f}
|
, max_width_ratio{0.8f}
|
||||||
, max_height_ratio{0.8f}
|
, max_height_ratio{0.8f}
|
||||||
, text_safety_margin{20.0f}
|
, text_safety_margin{20.0f}
|
||||||
|
, animation_duration{0.3f}
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -68,6 +72,8 @@ class WindowMessage {
|
|||||||
void show();
|
void show();
|
||||||
void hide();
|
void hide();
|
||||||
[[nodiscard]] auto isVisible() const -> bool { return visible_; }
|
[[nodiscard]] auto isVisible() const -> bool { return visible_; }
|
||||||
|
[[nodiscard]] auto isFullyVisible() const -> bool { return visible_ && !show_hide_animation_.active; }
|
||||||
|
[[nodiscard]] auto isAnimating() const -> bool { return resize_animation_.active || show_hide_animation_.active; }
|
||||||
|
|
||||||
// Configuración de contenido
|
// Configuración de contenido
|
||||||
void setTitle(const std::string& title);
|
void setTitle(const std::string& title);
|
||||||
@@ -128,7 +134,6 @@ class WindowMessage {
|
|||||||
bool active = false;
|
bool active = false;
|
||||||
float start_width, start_height;
|
float start_width, start_height;
|
||||||
float target_width, target_height;
|
float target_width, target_height;
|
||||||
float duration = 0.3f; // segundos
|
|
||||||
float elapsed = 0.0f;
|
float elapsed = 0.0f;
|
||||||
|
|
||||||
void start(float from_w, float from_h, float to_w, float to_h) {
|
void start(float from_w, float from_h, float to_w, float to_h) {
|
||||||
@@ -145,15 +150,53 @@ class WindowMessage {
|
|||||||
elapsed = 0.0f;
|
elapsed = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto isFinished() const -> bool {
|
[[nodiscard]] auto isFinished(float duration) const -> bool {
|
||||||
return elapsed >= duration;
|
return elapsed >= duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto getProgress() const -> float {
|
[[nodiscard]] auto getProgress(float duration) const -> float {
|
||||||
return std::min(elapsed / duration, 1.0f);
|
return std::min(elapsed / duration, 1.0f);
|
||||||
}
|
}
|
||||||
} resize_animation_;
|
} resize_animation_;
|
||||||
|
|
||||||
|
// Animación de mostrar/ocultar
|
||||||
|
struct ShowHideAnimation {
|
||||||
|
enum class Type { NONE, SHOWING, HIDING };
|
||||||
|
|
||||||
|
Type type = Type::NONE;
|
||||||
|
bool active = false;
|
||||||
|
float target_width, target_height; // Tamaño final al mostrar
|
||||||
|
float elapsed = 0.0f;
|
||||||
|
|
||||||
|
void startShow(float to_w, float to_h) {
|
||||||
|
type = Type::SHOWING;
|
||||||
|
target_width = to_w;
|
||||||
|
target_height = to_h;
|
||||||
|
elapsed = 0.0f;
|
||||||
|
active = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void startHide() {
|
||||||
|
type = Type::HIDING;
|
||||||
|
elapsed = 0.0f;
|
||||||
|
active = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void stop() {
|
||||||
|
type = Type::NONE;
|
||||||
|
active = false;
|
||||||
|
elapsed = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto isFinished(float duration) const -> bool {
|
||||||
|
return elapsed >= duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto getProgress(float duration) const -> float {
|
||||||
|
return std::min(elapsed / duration, 1.0f);
|
||||||
|
}
|
||||||
|
} show_hide_animation_;
|
||||||
|
|
||||||
// Estilos
|
// Estilos
|
||||||
Text::Style title_style_;
|
Text::Style title_style_;
|
||||||
Text::Style text_style_;
|
Text::Style text_style_;
|
||||||
@@ -165,6 +208,8 @@ class WindowMessage {
|
|||||||
void ensureTextFits(); // Verifica y ajusta para que todo el texto sea visible
|
void ensureTextFits(); // Verifica y ajusta para que todo el texto sea visible
|
||||||
void triggerAutoResize(); // Inicia redimensionado automático si está habilitado
|
void triggerAutoResize(); // Inicia redimensionado automático si está habilitado
|
||||||
void updateAnimation(float delta_time); // Actualiza la animación de redimensionado
|
void updateAnimation(float delta_time); // Actualiza la animación de redimensionado
|
||||||
|
void updateShowHideAnimation(float delta_time); // Actualiza la animación de mostrar/ocultar
|
||||||
|
void updateResizeAnimation(float delta_time); // Actualiza la animación de redimensionado
|
||||||
|
|
||||||
// Función de suavizado (ease-out)
|
// Función de suavizado (ease-out)
|
||||||
[[nodiscard]] auto easeOut(float t) const -> float;
|
[[nodiscard]] auto easeOut(float t) const -> float;
|
||||||
@@ -172,6 +217,7 @@ class WindowMessage {
|
|||||||
// Métodos para manejo de texto durante animación
|
// Métodos para manejo de texto durante animación
|
||||||
[[nodiscard]] auto getTruncatedText(const std::string& text, float available_width) const -> std::string;
|
[[nodiscard]] auto getTruncatedText(const std::string& text, float available_width) const -> std::string;
|
||||||
[[nodiscard]] auto getAvailableTextWidth() const -> float;
|
[[nodiscard]] auto getAvailableTextWidth() const -> float;
|
||||||
|
[[nodiscard]] auto shouldShowContent() const -> bool; // Si mostrar el contenido (texto, líneas, etc.)
|
||||||
|
|
||||||
[[nodiscard]] auto calculateContentHeight() const -> float;
|
[[nodiscard]] auto calculateContentHeight() const -> float;
|
||||||
[[nodiscard]] auto calculateContentWidth() const -> float;
|
[[nodiscard]] auto calculateContentWidth() const -> float;
|
||||||
|
|||||||
Reference in New Issue
Block a user