#include "service_menu.h" #include "screen.h" #include #include #include #include "text.h" #include "resource.h" #include "options.h" #include "section.h" // Para Name, name, Options, options, AttractMode // Singleton ServiceMenu *ServiceMenu::instance_ = nullptr; // Inicializa la instancia única del singleton void ServiceMenu::init() { ServiceMenu::instance_ = new ServiceMenu(); } // Libera la instancia void ServiceMenu::destroy() { delete ServiceMenu::instance_; } // Obtiene la instancia ServiceMenu *ServiceMenu::get() { return ServiceMenu::instance_; } // Constructor ServiceMenu::ServiceMenu() : element_text_(Resource::get()->getText("04b_25_flat")), title_text_(Resource::get()->getText("04b_25_flat_2x")), current_settings_group_(SettingsGroup::MAIN), previous_settings_group_(current_settings_group_) { setAnchors(); initializeOptions(); updateMenu(current_settings_group_); } void ServiceMenu::toggle() { enabled_ = !enabled_; reset(); } void ServiceMenu::render() { if (enabled_) { int y = rect_.y; constexpr int H_PADDING = 20; // SOMBRA SDL_FRect shadowRect = {rect_.x + 5, rect_.y + 5, rect_.w, rect_.h}; SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 0, 0, 0, 64); SDL_RenderFillRect(Screen::get()->getRenderer(), &shadowRect); // FONDO SDL_SetRenderDrawColor(Screen::get()->getRenderer(), bg_color_.r, bg_color_.g, bg_color_.b, 255); SDL_RenderFillRect(Screen::get()->getRenderer(), &rect_); // BORDE SDL_SetRenderDrawColor(Screen::get()->getRenderer(), title_color_.r, title_color_.g, title_color_.b, 255); SDL_RenderRect(Screen::get()->getRenderer(), &rect_); // SERVICE MENU y += line_height_; title_text_->writeDX(TEXT_COLOR | TEXT_CENTER, param.game.game_area.center_x, y, "SERVICE MENU", -4, title_color_); // LINEA y += line_height_ * 2; SDL_SetRenderDrawColor(Screen::get()->getRenderer(), title_color_.r, title_color_.g, title_color_.b, 255); SDL_RenderLine(Screen::get()->getRenderer(), rect_.x + H_PADDING, y, rect_.x + rect_.w - H_PADDING, y); // LIST for (size_t i = 0; i < option_pairs_.size(); ++i) { y += line_height_; element_text_->writeColored(rect_.x + H_PADDING, y, option_pairs_.at(i).first, i == selected_ ? selected_color_ : text_color_, -2); element_text_->writeColored(rect_.x + H_PADDING + 100, y, "" + std::string(option_pairs_.at(i).second), i == selected_ ? selected_color_ : text_color_, -2); } } } void ServiceMenu::update() { if (enabled_) { updateCounter(); selected_color_ = getSelectedColor(); } } void ServiceMenu::setAnchors() { width_ = 220; height_ = 200; line_height_ = element_text_->getCharacterSize() + 5; rect_ = { (param.game.width - width_) / 2, (param.game.height - height_) / 2, static_cast(width_), static_cast(height_)}; } void ServiceMenu::updateCounter() { static Uint64 lastUpdate = SDL_GetTicks(); Uint64 currentTicks = SDL_GetTicks(); if (currentTicks - lastUpdate >= 50) { counter_++; lastUpdate = currentTicks; } } Color ServiceMenu::getSelectedColor() { static std::array colors = { Color(0xFF, 0xFB, 0x8A), // Amarillo suave Color(0xFF, 0xE4, 0x5D), // Dorado medio Color(0xFF, 0xD1, 0x3C), // Amarillo pastel intenso Color(0xFF, 0xBF, 0x23), // Amarillo anaranjado Color(0xFF, 0xAA, 0x12), // Amarillo cálido Color(0xE6, 0x9A, 0x08), // Mostaza oscuro Color(0xE6, 0x9A, 0x08), // Mostaza oscuro (regreso, cierre) Color(0xFF, 0xAA, 0x12), // Amarillo cálido (regreso) Color(0xFF, 0xBF, 0x23), // Amarillo anaranjado (regreso) Color(0xFF, 0xD1, 0x3C), // Amarillo pastel intenso (regreso) Color(0xFF, 0xE4, 0x5D), // Dorado medio (regreso) Color(0xFF, 0xFB, 0x8A) // Amarillo suave (regreso) }; const size_t index = counter_ % colors.size(); return colors.at(index); } void ServiceMenu::setSelectorUp() { if (selected_ > 0) { --selected_; } else { selected_ = option_pairs_.size() - 1; } } void ServiceMenu::setSelectorDown() { selected_ = (selected_ + 1) % option_pairs_.size(); } void ServiceMenu::setSelectorRight() { display_options_.at(selected_).adjustValue(true); option_pairs_ = getOptionPairs(current_settings_group_); applySettings(current_settings_group_); } void ServiceMenu::setSelectorLeft() { display_options_.at(selected_).adjustValue(false); option_pairs_ = getOptionPairs(current_settings_group_); applySettings(current_settings_group_); } void ServiceMenu::acceptSelection() { if (display_options_.at(selected_).type == ValueType::FOLDER) { previous_settings_group_ = current_settings_group_; current_settings_group_ = display_options_.at(selected_).target_group; updateMenu(current_settings_group_); selected_ = 0; } else if (display_options_.at(selected_).behavior == OptionBehavior::SELECT) { if (display_options_.at(selected_).caption == "RESET") { section::name = section::Name::INIT; toggle(); return; } else if (display_options_.at(selected_).caption == "QUIT") { section::name = section::Name::QUIT; section::options = section::Options::QUIT_WITH_KEYBOARD; return; } else if (display_options_.at(selected_).caption == "SHUTDOWN") { section::name = section::Name::QUIT; section::options = section::Options::QUIT_WITH_CONTROLLER; return; } } } void ServiceMenu::moveBack() { if (current_settings_group_ == SettingsGroup::MAIN) { enabled_ = false; return; } else { selected_ = 0; current_settings_group_ = previous_settings_group_; updateMenu(current_settings_group_); } } void ServiceMenu::initializeOptions() { // Video options_.emplace_back("FULLSCREEN", SettingsGroup::VIDEO, OptionBehavior::ADJUST, &options.video.fullscreen, ValueType::BOOL); options_.emplace_back("WINDOW SIZE", SettingsGroup::VIDEO, OptionBehavior::ADJUST, &options.window.size, ValueType::INT, 1, options.window.max_size, 1); options_.emplace_back("SHADERS", SettingsGroup::VIDEO, OptionBehavior::ADJUST, &options.video.shaders, ValueType::BOOL); options_.emplace_back("VSYNC", SettingsGroup::VIDEO, OptionBehavior::ADJUST, &options.video.v_sync, ValueType::BOOL); options_.emplace_back("INTEGER SCALE", SettingsGroup::VIDEO, OptionBehavior::ADJUST, &options.video.integer_scale, ValueType::BOOL); // Audio options_.emplace_back("AUDIO", SettingsGroup::AUDIO, OptionBehavior::ADJUST, &options.audio.enabled, ValueType::BOOL); options_.emplace_back("MAIN VOLUME", SettingsGroup::AUDIO, OptionBehavior::ADJUST, &options.audio.volume, ValueType::INT, 0, 100, 5); options_.emplace_back("MUSIC VOLUME", SettingsGroup::AUDIO, OptionBehavior::ADJUST, &options.audio.music.volume, ValueType::INT, 0, 100, 5); options_.emplace_back("SFX VOLUME", SettingsGroup::AUDIO, OptionBehavior::ADJUST, &options.audio.sound.volume, ValueType::INT, 0, 100, 5); // Game options_.emplace_back("AUTOFIRE", SettingsGroup::GAME, OptionBehavior::ADJUST, &options.game.autofire, ValueType::BOOL); // options_.emplace_back("LANG", SettingsGroup::GAME, OptionBehavior::ADJUST, &options.game.language, ValueType::BOOL); // System options_.emplace_back("RESET", SettingsGroup::SYSTEM, OptionBehavior::SELECT, nullptr, ValueType::NONE); options_.emplace_back("QUIT", SettingsGroup::SYSTEM, OptionBehavior::SELECT, nullptr, ValueType::NONE); options_.emplace_back("SHUTDOWN", SettingsGroup::SYSTEM, OptionBehavior::SELECT, nullptr, ValueType::NONE); // Menu principal options_.emplace_back("VIDEO", SettingsGroup::MAIN, OptionBehavior::SELECT, SettingsGroup::VIDEO); options_.emplace_back("AUDIO", SettingsGroup::MAIN, OptionBehavior::SELECT, SettingsGroup::AUDIO); options_.emplace_back("GAME", SettingsGroup::MAIN, OptionBehavior::SELECT, SettingsGroup::GAME); options_.emplace_back("SYSTEM", SettingsGroup::MAIN, OptionBehavior::SELECT, SettingsGroup::SYSTEM); } ServiceMenu::OptionPairs ServiceMenu::getOptionPairs(ServiceMenu::SettingsGroup group) const { OptionPairs optionPairs; for (const auto &option : options_) { if (option.group == group) { optionPairs.emplace_back(option.caption, option.getValueAsString()); } } return optionPairs; } std::vector ServiceMenu::getOptionsByGroup(SettingsGroup group) const { std::vector filteredOptions; for (const auto &option : options_) { if (option.group == group) { filteredOptions.push_back(option); } } return filteredOptions; } void ServiceMenu::applySettings(ServiceMenu::SettingsGroup group) { switch (group) { case SettingsGroup::VIDEO: Screen::get()->applySettings(); break; default: break; } } void ServiceMenu::updateMenu(SettingsGroup group) { option_pairs_ = getOptionPairs(group); display_options_ = getOptionsByGroup(group); } void ServiceMenu::reset() { selected_ = 0; previous_settings_group_ = current_settings_group_ = SettingsGroup::MAIN; updateMenu(current_settings_group_); }