#include "define_buttons.h" #include #include #include #include "input.h" #include "input_types.h" #include "lang.h" #include "options.h" #include "param.h" #include "resource.h" #include "text.h" #include "ui/window_message.h" DefineButtons::DefineButtons() : input_(Input::get()) { clearButtons(); auto gamepads = input_->getGamepads(); for (auto gamepad : gamepads) { controller_names_.emplace_back(Input::getControllerName(gamepad)); } // Crear la ventana de mensaje WindowMessage::Config config; config.bg_color = Color{20, 30, 50, 240}; // Fondo azul oscuro semi-transparente config.border_color = Color{100, 150, 200, 255}; // Borde 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.padding = 15.0F; config.line_spacing = 5.0F; config.title_separator_spacing = 15; config.min_width = 250.0F; config.text_safety_margin = 15.0F; config.min_width = 100; config.min_height = 32; config.animation_duration = 0.3F; auto text_renderer = Resource::get()->getText("04b_25_flat"); window_message_ = std::make_unique( text_renderer, Lang::getText("[DEFINE_BUTTONS] TITLE"), config); window_message_->setPosition(param.game.game_area.center_x, param.game.game_area.center_y, WindowMessage::PositionMode::CENTERED); } void DefineButtons::render() { if (enabled_ && window_message_) { window_message_->render(); } } void DefineButtons::update() { if (!enabled_) { return; } // Actualizar la ventana siempre if (window_message_) { window_message_->update(); } // Manejar la secuencia de cierre si ya terminamos if (finished_ && message_shown_) { message_timer_++; // Después del delay, iniciar animación de cierre (solo una vez) if (message_timer_ > MESSAGE_DISPLAY_FRAMES && !closing_) { if (window_message_) { window_message_->hide(); // Iniciar animación de cierre } closing_ = true; } } } void DefineButtons::handleEvents(const SDL_Event &event) { if (enabled_) { switch (event.type) { case SDL_EVENT_GAMEPAD_BUTTON_DOWN: doControllerButtonDown(event.gbutton); break; case SDL_EVENT_GAMEPAD_BUTTON_UP: checkEnd(); break; default: break; } } } auto DefineButtons::enable(Options::Gamepad *options_gamepad) -> bool { if (options_gamepad != nullptr) { options_gamepad_ = options_gamepad; enabled_ = true; finished_ = false; index_button_ = 0; message_shown_ = false; closing_ = false; clearButtons(); updateWindowMessage(); if (window_message_) { window_message_->autoSize(); window_message_->show(); } return true; } return false; } void DefineButtons::disable() { enabled_ = false; finished_ = false; message_shown_ = false; closing_ = false; if (window_message_) { window_message_->hide(); } } void DefineButtons::doControllerButtonDown(const SDL_GamepadButtonEvent &event) { auto gamepad = input_->getGamepad(event.which); if (!gamepad || gamepad != options_gamepad_->instance) { return; } const auto BUTTON = static_cast(event.button); if (checkButtonNotInUse(BUTTON)) { buttons_.at(index_button_).button = BUTTON; incIndexButton(); updateWindowMessage(); } } void DefineButtons::bindButtons(Options::Gamepad *options_gamepad) { for (const auto &button : buttons_) { Input::bindGameControllerButton(options_gamepad->instance, button.action, button.button); } Input::bindGameControllerButton(options_gamepad->instance, Input::Action::SM_SELECT, Input::Action::FIRE_LEFT); Input::bindGameControllerButton(options_gamepad->instance, Input::Action::SM_BACK, Input::Action::FIRE_CENTER); } void DefineButtons::incIndexButton() { if (index_button_ < buttons_.size() - 1) { ++index_button_; } else { finished_ = true; } } auto DefineButtons::checkButtonNotInUse(SDL_GamepadButton button) -> bool { return std::ranges::all_of(buttons_, [button](const auto &b) { return b.button != button; }); } void DefineButtons::clearButtons() { buttons_.clear(); buttons_.emplace_back(Lang::getText("[DEFINE_BUTTONS] FIRE_LEFT"), Input::Action::FIRE_LEFT, SDL_GAMEPAD_BUTTON_INVALID); buttons_.emplace_back(Lang::getText("[DEFINE_BUTTONS] FIRE_UP"), Input::Action::FIRE_CENTER, SDL_GAMEPAD_BUTTON_INVALID); buttons_.emplace_back(Lang::getText("[DEFINE_BUTTONS] FIRE_RIGHT"), Input::Action::FIRE_RIGHT, SDL_GAMEPAD_BUTTON_INVALID); buttons_.emplace_back(Lang::getText("[DEFINE_BUTTONS] START"), Input::Action::START, SDL_GAMEPAD_BUTTON_INVALID); buttons_.emplace_back(Lang::getText("[DEFINE_BUTTONS] SERVICE_MENU"), Input::Action::SERVICE, SDL_GAMEPAD_BUTTON_INVALID); } void DefineButtons::checkEnd() { if (finished_ && !message_shown_) { bindButtons(options_gamepad_); input_->saveGamepadConfigFromGamepad(options_gamepad_->instance); input_->resetInputStates(); // Mostrar mensaje de finalización if (window_message_) { window_message_->clearTexts(); window_message_->addText(Lang::getText("[DEFINE_BUTTONS] CONFIGURATION_COMPLETE")); } // Solo marcar que ya mostramos el mensaje message_shown_ = true; message_timer_ = 0; } } bool DefineButtons::isReadyToClose() const { // Solo está listo para cerrar si: // 1. Terminó // 2. Ya mostró el mensaje // 3. Está cerrando // 4. La ventana ya no está visible (animación terminada) return finished_ && message_shown_ && closing_ && (!window_message_ || !window_message_->isVisible()); } void DefineButtons::updateWindowMessage() { if (!window_message_ || !options_gamepad_) { return; } // Configurar título std::string title = Lang::getText("[DEFINE_BUTTONS] CONFIGURING") + ": " + options_gamepad_->name; window_message_->setTitle(title); // Limpiar textos anteriores window_message_->clearTexts(); if (index_button_ < buttons_.size()) { // Instrucción actual std::string instruction = Lang::getText("[DEFINE_BUTTONS] PRESS_BUTTON_FOR") + ":"; window_message_->addText(instruction); window_message_->addText(buttons_.at(index_button_).label); } }