Varios arreglos a tot lo de definir botons dins del service menu i lo de triar mando

This commit is contained in:
2025-08-07 21:11:05 +02:00
parent d8a37c555f
commit fdfc976749
11 changed files with 223 additions and 233 deletions

View File

@@ -59,11 +59,6 @@ void MenuRenderer::render(const ServiceMenu *menu_state) {
std::string truncated_value = getTruncatedValue(option_pairs.at(i).second, available_width);
// Si la opción tiene Behavior::BOTH, añadir indicador visual
if (i < display_options.size() && display_options[i]->getBehavior() == MenuOption::Behavior::BOTH) {
truncated_value = "-" + truncated_value + "-";
}
element_text_->writeColored(rect_.x + ServiceMenu::OPTIONS_HORIZONTAL_PADDING, y, option_pairs.at(i).first, current_color, -2);
const int X = rect_.x + rect_.w - ServiceMenu::OPTIONS_HORIZONTAL_PADDING - element_text_->length(truncated_value, -2);
element_text_->writeColored(X, y, truncated_value, current_color, -2);
@@ -72,11 +67,6 @@ void MenuRenderer::render(const ServiceMenu *menu_state) {
const int available_width = rect_.w - (ServiceMenu::OPTIONS_HORIZONTAL_PADDING * 2);
std::string truncated_caption = getTruncatedValue(option_pairs.at(i).first, available_width);
// Si la opción tiene Behavior::BOTH, añadir indicador visual
if (i < display_options.size() && display_options[i]->getBehavior() == MenuOption::Behavior::BOTH) {
truncated_caption = "-" + truncated_caption + "-";
}
element_text_->writeDX(Text::CENTER | Text::COLOR, rect_.x + rect_.w / 2, y, truncated_caption, -2, current_color);
}
y += options_height_ + options_padding_;

View File

@@ -2,21 +2,21 @@
#include <algorithm> // Para max
#include "audio.h" // Para Audio
#include "difficulty.h" // Para getCodeFromName, getNameFromCode
#include "input.h" // Para Input
#include "lang.h" // Para getText, getCodeFromName, getNameFromCode
#include "menu_option.h" // Para MenuOption, ListOption, ActionOption, BoolOption, FolderOption, IntOption
#include "menu_renderer.h" // Para MenuRenderer
#include "options.h" // Para PendingChanges, pending_changes, checkPendingChanges, GamepadManager, Video, gamepad_manager, video, Audio, Settings, audio, settings, Gamepad, Window, window, Music, Sound
#include "param.h" // Para Param, param, ParamGame, ParamServiceMenu
#include "player.h" // Para Player
#include "resource.h" // Para Resource
#include "screen.h" // Para Screen
#include "section.hpp" // Para Name, name, Options, options
#include "ui/ui_message.h" // Para UIMessage
#include "utils.h" // Para Zone
#include "define_buttons.h" // Para DefineButtons
#include "audio.h" // Para Audio
#include "define_buttons.h" // Para DefineButtons
#include "difficulty.h" // Para getCodeFromName, getNameFromCode
#include "input.h" // Para Input
#include "lang.h" // Para getText, getCodeFromName, getNameFromCode
#include "menu_option.h" // Para MenuOption, ListOption, ActionOption, BoolOption, FolderOption, IntOption
#include "menu_renderer.h" // Para MenuRenderer
#include "options.h" // Para PendingChanges, pending_changes, checkPendingChanges, GamepadManager, Video, gamepad_manager, video, Audio, Settings, audio, settings, Gamepad, Window, window, Music, Sound
#include "param.h" // Para Param, param, ParamGame, ParamServiceMenu
#include "player.h" // Para Player
#include "resource.h" // Para Resource
#include "screen.h" // Para Screen
#include "section.hpp" // Para Name, name, Options, options
#include "ui/ui_message.h" // Para UIMessage
#include "utils.h" // Para Zone
// Singleton
ServiceMenu *ServiceMenu::instance = nullptr;
@@ -39,6 +39,10 @@ ServiceMenu::ServiceMenu()
}
void ServiceMenu::toggle() {
if (define_buttons_ && define_buttons_->isEnabled()) {
return; // No se puede mostrar u ocultar el menu de servicio si se estan definiendo los botones
}
playBackSound();
enabled_ = !enabled_;
if (!enabled_) {
@@ -81,13 +85,13 @@ void ServiceMenu::update() {
// Actualizar DefineButtons
if (define_buttons_) {
define_buttons_->update();
// Si DefineButtons ha terminado, deshabilitarlo
if (define_buttons_->isEnabled() && define_buttons_->isFinished()) {
// Pequeño delay antes de cerrar
static int finish_delay = 0;
static size_t finish_delay = 0;
finish_delay++;
if (finish_delay > 60) { // 1 segundo a 60 FPS
if (finish_delay > DEFINE_BUTTONS_FINISH_DELAY_FRAMES) {
define_buttons_->disable();
finish_delay = 0;
}
@@ -283,7 +287,7 @@ void ServiceMenu::initializeOptions() {
},
[this]() {
// Acción: configurar botones del mando del jugador 1
auto* gamepad = &Options::gamepad_manager.getGamepad(Player::Id::PLAYER1);
auto *gamepad = &Options::gamepad_manager.getGamepad(Player::Id::PLAYER1);
if (gamepad && gamepad->instance) {
define_buttons_->enable(gamepad);
}
@@ -301,7 +305,7 @@ void ServiceMenu::initializeOptions() {
},
[this]() {
// Acción: configurar botones del mando del jugador 2
auto* gamepad = &Options::gamepad_manager.getGamepad(Player::Id::PLAYER2);
auto *gamepad = &Options::gamepad_manager.getGamepad(Player::Id::PLAYER2);
if (gamepad && gamepad->instance) {
define_buttons_->enable(gamepad);
}
@@ -550,66 +554,95 @@ void ServiceMenu::handleEvent(const SDL_Event &event) {
// Si DefineButtons está activo, que maneje todos los eventos
if (define_buttons_ && define_buttons_->isEnabled()) {
define_buttons_->checkEvents(event);
return; // No procesar otros eventos mientras DefineButtons está activo
return; // No procesar otros eventos mientras DefineButtons está activo
}
}
bool ServiceMenu::checkInput() {
if (!enabled_) {
return false;
}
// Procesar eventos normales del ServiceMenu
/*switch (event.type) {
case SDL_EVENT_KEY_DOWN:
switch (event.key.key) {
case SDLK_ESCAPE:
case SDLK_BACKSPACE:
moveBack();
break;
case SDLK_RETURN:
case SDLK_KP_ENTER:
selectOption();
break;
case SDLK_UP:
setSelectorUp();
break;
case SDLK_DOWN:
setSelectorDown();
break;
case SDLK_LEFT:
adjustOption(false);
break;
case SDLK_RIGHT:
adjustOption(true);
break;
default:
break;
}
break;
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
switch (event.gbutton.button) {
case SDL_GAMEPAD_BUTTON_SOUTH:
case SDL_GAMEPAD_BUTTON_BACK:
moveBack();
break;
case SDL_GAMEPAD_BUTTON_EAST:
case SDL_GAMEPAD_BUTTON_START:
selectOption();
break;
case SDL_GAMEPAD_BUTTON_DPAD_UP:
setSelectorUp();
break;
case SDL_GAMEPAD_BUTTON_DPAD_DOWN:
setSelectorDown();
break;
case SDL_GAMEPAD_BUTTON_DPAD_LEFT:
adjustOption(false);
break;
case SDL_GAMEPAD_BUTTON_DPAD_RIGHT:
adjustOption(true);
break;
default:
break;
}
break;
default:
break;
}*/
if (define_buttons_ && define_buttons_->isEnabled()) {
return true;
}
static auto input = Input::get();
// --- Teclado ---
// Arriba
if (input->checkAction(Input::Action::UP, Input::DO_NOT_ALLOW_REPEAT, Input::CHECK_KEYBOARD)) {
setSelectorUp();
return true;
}
// Abajo
if (input->checkAction(Input::Action::DOWN, Input::DO_NOT_ALLOW_REPEAT, Input::CHECK_KEYBOARD)) {
setSelectorDown();
return true;
}
// Derecha
if (input->checkAction(Input::Action::RIGHT, Input::DO_NOT_ALLOW_REPEAT, Input::CHECK_KEYBOARD)) {
adjustOption(true);
return true;
}
// Izquierda
if (input->checkAction(Input::Action::LEFT, Input::DO_NOT_ALLOW_REPEAT, Input::CHECK_KEYBOARD)) {
adjustOption(false);
return true;
}
// Aceptar
if (input->checkAction(Input::Action::SM_SELECT, Input::DO_NOT_ALLOW_REPEAT, Input::CHECK_KEYBOARD)) {
selectOption();
return true;
}
// Atras
if (input->checkAction(Input::Action::SM_BACK, Input::DO_NOT_ALLOW_REPEAT, Input::CHECK_KEYBOARD)) {
moveBack();
return true;
}
// --- Mandos ---
auto gamepads = input->getGamepads();
for (auto gamepad : gamepads) {
// Arriba
if (input->checkAction(Input::Action::UP, Input::DO_NOT_ALLOW_REPEAT, Input::DO_NOT_CHECK_KEYBOARD, gamepad)) {
setSelectorUp();
return true;
}
// Abajo
if (input->checkAction(Input::Action::DOWN, Input::DO_NOT_ALLOW_REPEAT, Input::DO_NOT_CHECK_KEYBOARD, gamepad)) {
setSelectorDown();
return true;
}
// Derecha
if (input->checkAction(Input::Action::RIGHT, Input::DO_NOT_ALLOW_REPEAT, Input::DO_NOT_CHECK_KEYBOARD, gamepad)) {
adjustOption(true);
return true;
}
// Izquierda
if (input->checkAction(Input::Action::LEFT, Input::DO_NOT_ALLOW_REPEAT, Input::DO_NOT_CHECK_KEYBOARD, gamepad)) {
adjustOption(false);
return true;
}
// Aceptar
if (input->checkAction(Input::Action::SM_SELECT, Input::DO_NOT_ALLOW_REPEAT, Input::DO_NOT_CHECK_KEYBOARD, gamepad)) {
selectOption();
return true;
}
// Atras
if (input->checkAction(Input::Action::SM_BACK, Input::DO_NOT_ALLOW_REPEAT, Input::DO_NOT_CHECK_KEYBOARD, gamepad)) {
moveBack();
return true;
}
}
return false;
}

View File

@@ -34,6 +34,7 @@ class ServiceMenu {
static constexpr size_t MIN_WIDTH = 240;
static constexpr size_t MIN_GAP_OPTION_VALUE = 30;
static constexpr size_t SETTINGS_GROUP_SIZE = 6;
static constexpr size_t DEFINE_BUTTONS_FINISH_DELAY_FRAMES = 60 * 3; // 3 segundo a 60 FPS
// --- Métodos de singleton ---
static void init();
@@ -56,8 +57,9 @@ class ServiceMenu {
void moveBack();
void checkEvents(const SDL_Event &event); // Nuevo método para eventos
// NUEVO: Método para manejar eventos (llamado desde GlobalEvents)
// --- Método para manejar eventos (llamado desde GlobalEvents) ---
void handleEvent(const SDL_Event &event);
bool checkInput();
// NUEVO: Getter para saber si DefineButtons está activo
[[nodiscard]] auto isDefiningButtons() const -> bool {

View File

@@ -36,33 +36,40 @@ void WindowMessage::render() {
SDL_RenderRect(renderer, &rect_);
float current_y = rect_.y + config_.padding;
float available_width = getAvailableTextWidth();
// Dibujar título si existe
if (!title_.empty()) {
std::string visible_title = getTruncatedText(title_, available_width);
text_renderer_->writeStyle(
rect_.x + rect_.w / 2.0f,
current_y,
title_,
visible_title,
title_style_);
current_y += text_renderer_->getCharacterSize() + config_.title_separator_spacing;
// Línea separadora debajo del título
SDL_SetRenderDrawColor(renderer, config_.border_color.r, config_.border_color.g,
config_.border_color.b, config_.border_color.a);
SDL_RenderLine(renderer,
rect_.x + config_.padding,
current_y - config_.title_separator_spacing / 2.0f,
rect_.x + rect_.w - config_.padding,
current_y - config_.title_separator_spacing / 2.0f);
// Línea separadora debajo del título (solo si hay título visible)
if (!visible_title.empty()) {
SDL_SetRenderDrawColor(renderer, config_.border_color.r, config_.border_color.g,
config_.border_color.b, config_.border_color.a);
SDL_RenderLine(renderer,
rect_.x + config_.padding,
current_y - config_.title_separator_spacing / 2.0f,
rect_.x + rect_.w - config_.padding,
current_y - config_.title_separator_spacing / 2.0f);
}
}
// Dibujar textos
for (const auto& text : texts_) {
text_renderer_->writeStyle(
rect_.x + rect_.w / 2.0f,
current_y,
text,
text_style_);
std::string visible_text = getTruncatedText(text, available_width);
if (!visible_text.empty()) {
text_renderer_->writeStyle(
rect_.x + rect_.w / 2.0f,
current_y,
visible_text,
text_style_);
}
current_y += text_renderer_->getCharacterSize() + config_.line_spacing;
}
}
@@ -284,4 +291,46 @@ void WindowMessage::updateAnimation(float delta_time) {
auto WindowMessage::easeOut(float t) const -> float {
// Función de suavizado ease-out cuadrática
return 1.0f - (1.0f - t) * (1.0f - t);
}
auto WindowMessage::getAvailableTextWidth() const -> float {
// Ancho disponible = ancho total - padding en ambos lados
return rect_.w - (config_.padding * 2.0f);
}
auto WindowMessage::getTruncatedText(const std::string& text, float available_width) const -> std::string {
if (text.empty()) {
return text;
}
// Si el texto completo cabe, devolverlo tal como está
int text_width = text_renderer_->length(text, -2);
if (text_width <= available_width) {
return text;
}
// Si no hay espacio suficiente, devolver string vacío
if (available_width < 10.0f) { // Mínimo espacio para al menos un carácter
return "";
}
// Buscar cuántos caracteres caben usando búsqueda binaria
int left = 0;
int right = text.length();
int best_length = 0;
while (left <= right) {
int mid = (left + right) / 2;
std::string partial = text.substr(0, mid);
int partial_width = text_renderer_->length(partial, -2);
if (partial_width <= available_width) {
best_length = mid;
left = mid + 1;
} else {
right = mid - 1;
}
}
return text.substr(0, best_length);
}

View File

@@ -169,6 +169,10 @@ class WindowMessage {
// Función de suavizado (ease-out)
[[nodiscard]] auto easeOut(float t) const -> float;
// Métodos para manejo de texto durante animación
[[nodiscard]] auto getTruncatedText(const std::string& text, float available_width) const -> std::string;
[[nodiscard]] auto getAvailableTextWidth() const -> float;
[[nodiscard]] auto calculateContentHeight() const -> float;
[[nodiscard]] auto calculateContentWidth() const -> float;
[[nodiscard]] auto getScreenWidth() const -> float;