diff --git a/source/service_menu.cpp b/source/service_menu.cpp index 3f7b616..249ea87 100644 --- a/source/service_menu.cpp +++ b/source/service_menu.cpp @@ -8,6 +8,7 @@ #include "options.h" #include "section.h" // Para Name, name, Options, options, AttractMode #include "audio.h" +#include // Singleton ServiceMenu *ServiceMenu::instance_ = nullptr; @@ -15,13 +16,13 @@ ServiceMenu *ServiceMenu::instance_ = nullptr; // Inicializa la instancia única del singleton void ServiceMenu::init() { ServiceMenu::instance_ = new ServiceMenu(); } -// Libera la instancia +// Libera la instancia única del singleton void ServiceMenu::destroy() { delete ServiceMenu::instance_; } -// Obtiene la instancia +// Devuelve la instancia única del singleton ServiceMenu *ServiceMenu::get() { return ServiceMenu::instance_; } -// Constructor +// Constructor de ServiceMenu ServiceMenu::ServiceMenu() : element_text_(Resource::get()->getText("04b_25_flat")), title_text_(Resource::get()->getText("04b_25_flat_2x")), @@ -33,12 +34,14 @@ ServiceMenu::ServiceMenu() updateMenu(current_settings_group_); } +// Alterna la visibilidad del menú de servicio void ServiceMenu::toggle() { enabled_ = !enabled_; reset(); } +// Dibuja el menú de servicio en pantalla void ServiceMenu::render() { if (enabled_) @@ -62,7 +65,7 @@ void ServiceMenu::render() SDL_SetRenderDrawColor(Screen::get()->getRenderer(), title_color_.r, title_color_.g, title_color_.b, 255); SDL_RenderRect(Screen::get()->getRenderer(), &rect_); - // SERVICE MENU + // TITULO y += line_height_; title_text_->writeDX(TEXT_COLOR | TEXT_CENTER, param.game.game_area.center_x, y, "SERVICE MENU", -4, title_color_); @@ -71,7 +74,7 @@ void ServiceMenu::render() SDL_SetRenderDrawColor(Screen::get()->getRenderer(), title_color_.r, title_color_.g, title_color_.b, 255); SDL_RenderLine(Screen::get()->getRenderer(), rect_.x + OPTIONS_HORIZONTAL_PADDING_, y, rect_.x + rect_.w - OPTIONS_HORIZONTAL_PADDING_, y); - // LIST + // OPCIONES for (size_t i = 0; i < option_pairs_.size(); ++i) { y += line_height_; @@ -99,6 +102,7 @@ void ServiceMenu::render() } } +// Actualiza el estado del menú de servicio (colores, animaciones, etc.) void ServiceMenu::update() { if (enabled_) @@ -108,6 +112,7 @@ void ServiceMenu::update() } } +// Calcula y establece los anclajes y dimensiones del menú void ServiceMenu::setAnchors() { line_height_ = element_text_->getCharacterSize() + 5; @@ -120,6 +125,7 @@ void ServiceMenu::setAnchors() static_cast(height_)}; } +// Actualiza el contador interno para animaciones o efectos visuales void ServiceMenu::updateCounter() { static Uint64 lastUpdate = SDL_GetTicks(); @@ -131,7 +137,8 @@ void ServiceMenu::updateCounter() } } -Color ServiceMenu::getSelectedColor() +// Devuelve el color actual del elemento seleccionado (animado) +Color ServiceMenu::getSelectedColor() const { static std::array colors = { Color(0xFF, 0xFB, 0x8A), // Amarillo suave @@ -153,31 +160,51 @@ Color ServiceMenu::getSelectedColor() return colors.at(index); } +// Método privado para reproducir el sonido del menú +void ServiceMenu::playMenuSound() +{ + Audio::get()->playSound(MENU_SOUND_); +} + +// Mueve el selector hacia arriba en la lista de opciones void ServiceMenu::setSelectorUp() { + if (display_options_.empty()) + return; selected_ = (selected_ > 0) ? --selected_ : display_options_.size() - 1; - Audio::get()->playSound(MENU_SOUND_); + playMenuSound(); } +// Mueve el selector hacia abajo en la lista de opciones void ServiceMenu::setSelectorDown() { + if (display_options_.empty()) + return; selected_ = (selected_ + 1) % display_options_.size(); - Audio::get()->playSound(MENU_SOUND_); + playMenuSound(); } +// Ajusta el valor de la opción seleccionada (si es ajustable) void ServiceMenu::adjustOption(bool adjust_up) { + if (display_options_.empty() || selected_ >= display_options_.size()) + return; + if (display_options_.at(selected_).behavior == OptionBehavior::ADJUST) { display_options_.at(selected_).adjustValue(adjust_up); option_pairs_ = getOptionPairs(current_settings_group_); applySettings(current_settings_group_); - Audio::get()->playSound(MENU_SOUND_); + playMenuSound(); } } +// Ejecuta la acción de la opción seleccionada o navega a un submenú void ServiceMenu::selectOption() { + if (display_options_.empty() || selected_ >= display_options_.size()) + return; + // Carpeta if (display_options_.at(selected_).type == ValueType::FOLDER) { @@ -185,7 +212,7 @@ void ServiceMenu::selectOption() current_settings_group_ = display_options_.at(selected_).target_group; updateMenu(current_settings_group_); selected_ = 0; - Audio::get()->playSound(MENU_SOUND_); + playMenuSound(); return; } @@ -214,6 +241,7 @@ void ServiceMenu::selectOption() } } +// Vuelve al grupo de opciones anterior o cierra el menú si está en el principal void ServiceMenu::moveBack() { if (current_settings_group_ == SettingsGroup::MAIN) @@ -226,10 +254,11 @@ void ServiceMenu::moveBack() selected_ = 0; current_settings_group_ = previous_settings_group_; updateMenu(current_settings_group_); - Audio::get()->playSound(MENU_SOUND_); + playMenuSound(); } } +// Inicializa todas las opciones del menú de servicio void ServiceMenu::initializeOptions() { // Video @@ -261,6 +290,7 @@ void ServiceMenu::initializeOptions() options_.emplace_back("SYSTEM", SettingsGroup::MAIN, OptionBehavior::SELECT, SettingsGroup::SYSTEM); } +// Devuelve las opciones del grupo como pares (nombre, valor) ServiceMenu::OptionPairs ServiceMenu::getOptionPairs(ServiceMenu::SettingsGroup group) const { OptionPairs optionPairs; @@ -276,6 +306,7 @@ ServiceMenu::OptionPairs ServiceMenu::getOptionPairs(ServiceMenu::SettingsGroup return optionPairs; } +// Devuelve las opciones del grupo como un vector de OptionEntry std::vector ServiceMenu::getOptionsByGroup(SettingsGroup group) const { std::vector filteredOptions; @@ -291,6 +322,7 @@ std::vector ServiceMenu::getOptionsByGroup(SettingsGro return filteredOptions; } +// Aplica la configuración correspondiente al grupo seleccionado void ServiceMenu::applySettings(ServiceMenu::SettingsGroup group) { switch (group) @@ -308,12 +340,14 @@ void ServiceMenu::applySettings(ServiceMenu::SettingsGroup group) } } +// Actualiza las opciones mostradas según el grupo seleccionado void ServiceMenu::updateMenu(SettingsGroup group) { option_pairs_ = getOptionPairs(group); display_options_ = getOptionsByGroup(group); } +// Reinicia el menú al estado inicial (grupo principal y opción seleccionada) void ServiceMenu::reset() { selected_ = 0; @@ -321,30 +355,28 @@ void ServiceMenu::reset() updateMenu(current_settings_group_); } -int ServiceMenu::calculateMenuHeight() +// Calcula la altura total del menú en píxeles +int ServiceMenu::calculateMenuHeight() const { return ((4 + findLargestGroupSize() + 1) * line_height_) - 5; } -int ServiceMenu::findLargestGroupSize() +// Devuelve el tamaño (número de opciones) del grupo más grande +int ServiceMenu::findLargestGroupSize() const { + std::unordered_map group_counts; + for (const auto &option : options_) + ++group_counts[option.group]; + int max_size = 0; - // Recorremos todos los posibles grupos - for (int group = static_cast(SettingsGroup::VIDEO); group <= static_cast(SettingsGroup::MAIN); ++group) - { - int count = 0; - for (const auto &option : options_) - { - if (static_cast(option.group) == group) - ++count; - } - if (count > max_size) - max_size = count; - } + for (const auto &pair : group_counts) + if (pair.second > max_size) + max_size = pair.second; return max_size; } -ServiceMenu::GroupAlignment ServiceMenu::getGroupAlignment(SettingsGroup group) +// Devuelve la alineación de las opciones para el grupo dado +ServiceMenu::GroupAlignment ServiceMenu::getGroupAlignment(SettingsGroup group) const { switch (group) { diff --git a/source/service_menu.h b/source/service_menu.h index 774e979..a4380c4 100644 --- a/source/service_menu.h +++ b/source/service_menu.h @@ -12,45 +12,48 @@ class Text; class ServiceMenu { public: - // --- Métodos de singleton --- - static void init(); // Inicializa el objeto ServiceMenu - static void destroy(); // Libera el objeto ServiceMenu - static ServiceMenu *get(); // Obtiene el puntero al objeto ServiceMenu + // --- Métodos de Singleton --- + static void init(); // Inicializa la instancia única de ServiceMenu + static void destroy(); // Libera la instancia única de ServiceMenu + static ServiceMenu *get(); // Devuelve el puntero a la instancia única - // -- Métodos --- - void toggle(); - void render(); - void update(); + // --- Métodos principales --- + void toggle(); // Muestra u oculta el menú de servicio + void render(); // Dibuja el menú de servicio en pantalla + void update(); // Actualiza el estado del menú de servicio - // --- Métodos de control --- - void setSelectorUp(); - void setSelectorDown(); - void adjustOption(bool adjust_up); - void selectOption(); - void moveBack(); + // --- Métodos de control de navegación --- + void setSelectorUp(); // Mueve el selector hacia arriba + void setSelectorDown(); // Mueve el selector hacia abajo + void adjustOption(bool adjust_up); // Ajusta el valor de la opción seleccionada + void selectOption(); // Selecciona la opción actual + void moveBack(); // Vuelve al grupo de opciones anterior // --- Getters --- - bool isEnabled() const { return enabled_; } + bool isEnabled() const { return enabled_; } // Indica si el menú de servicio está activo private: + // --- Tipos internos --- using OptionPairs = std::vector>; - static constexpr const char *MENU_SOUND_ = "clock.wav"; - static constexpr int OPTIONS_HORIZONTAL_PADDING_ = 20; + // --- Constantes --- + static constexpr const char *MENU_SOUND_ = "clock.wav"; // Sonido al navegar por el menú + static constexpr int OPTIONS_HORIZONTAL_PADDING_ = 20; // Relleno horizontal de las opciones + // --- Enumeraciones internas --- enum class Aspect { ASPECT1, // Fondo opaco y proyecta sombra - ASPECT2 // Fondo translucido + ASPECT2 // Fondo translúcido }; enum class SettingsGroup { - VIDEO, // Configuraciones relacionadas con la calidad y resolución de imagen - AUDIO, // Opciones de sonido y volumen - GAME, // Ajustes de jugabilidad y mecánicas - SYSTEM, // Preferencias generales y configuraciones del sistema - MAIN // Raíz + VIDEO, // Configuraciones de vídeo + AUDIO, // Opciones de audio + GAME, // Opciones de juego + SYSTEM, // Opciones del sistema + MAIN // Menú principal }; enum class OptionBehavior @@ -61,18 +64,19 @@ private: enum class ValueType { - BOOL, - INT, - FOLDER, - NONE + BOOL, // Valor booleano + INT, // Valor entero + FOLDER, // Referencia a otro grupo + NONE // Sin valor asociado }; enum class GroupAlignment { - CENTERED, - LEFT + CENTERED, // Opciones centradas + LEFT // Opciones alineadas a la izquierda }; + // --- Estructura de opción del menú --- struct OptionEntry { std::string caption; // Texto visible en el menú @@ -102,7 +106,7 @@ private: : caption(cap), group(grp), behavior(beh), linked_variable(nullptr), type(ValueType::FOLDER), min_value(0), max_value(0), step_value(0), target_group(tgtGrp) {} - // Método para modificar el valor + // Método para modificar el valor de la opción void adjustValue(bool adjust_up) { if (linked_variable) @@ -111,14 +115,12 @@ private: { int &value = *(static_cast(linked_variable)); int newValue = adjust_up ? value + step_value : value - step_value; - - // Asegurar que el nuevo valor se mantenga dentro de los límites value = std::clamp(newValue, min_value, max_value); } else if (type == ValueType::BOOL) { bool &value = *(static_cast(linked_variable)); - value = !value; // Invierte el valor booleano + value = !value; } } } @@ -138,49 +140,58 @@ private: } }; - // -- Variables internas --- + // --- Variables internas --- bool enabled_ = false; // Indica si el menú de servicio está activo - SDL_FRect rect_; // Rectangulo para definir el area del menú de servicio - std::shared_ptr element_text_; // Objeto para escribir texto; - std::shared_ptr title_text_; // Objeto para escribir texto; - size_t selected_ = 0; // Elemento del menú seleccionado + SDL_FRect rect_; // Rectángulo que define el área del menú de servicio + std::shared_ptr element_text_; // Objeto para escribir el texto de los elementos + std::shared_ptr title_text_; // Objeto para escribir el texto del título + size_t selected_ = 0; // Índice del elemento del menú seleccionado Uint32 counter_ = 0; // Contador interno std::vector options_; // Listado con todas las opciones del menú de servicio - std::vector display_options_; // Listado con todas las opciones del menú de servicio que se estan mostrando - OptionPairs option_pairs_; // Listado con las opciones de menu actuales (filtradas por grupo) - SettingsGroup current_settings_group_; // Grupo actual - SettingsGroup previous_settings_group_; // Grupo anterior - Aspect aspect_ = Aspect::ASPECT2; + std::vector display_options_; // Opciones actualmente mostradas en pantalla + OptionPairs option_pairs_; // Opciones actuales del menú (filtradas por grupo) + SettingsGroup current_settings_group_; // Grupo de opciones actualmente activo + SettingsGroup previous_settings_group_; // Grupo de opciones anterior + Aspect aspect_ = Aspect::ASPECT2; // Estilo visual del menú - // -- Aspecto -- + // --- Variables de aspecto --- Color bg_color_ = SERV_MENU_BG_COLOR; // Color de fondo - Color title_color_ = SERV_MENU_TITLE_COLOR; // Color del título del menu - Color text_color_ = SERV_MENU_TEXT_COLOR; // Color para el texto de los elementos - Color selected_color_ = SERV_MENU_SELECTED_COLOR; // Color para el elemento seleccionado + Color title_color_ = SERV_MENU_TITLE_COLOR; // Color del título del menú + Color text_color_ = SERV_MENU_TEXT_COLOR; // Color del texto de los elementos + Color selected_color_ = SERV_MENU_SELECTED_COLOR; // Color del elemento seleccionado int width_; // Ancho del menú - int height_; // Alto del menu - int line_height_; // Espacio entre elementos del menu + int height_; // Alto del menú + int line_height_; // Espacio entre elementos del menú - // -- Métodos internos --- - void setAnchors(); // Establece el valor de las variables de anclaje - void updateCounter(); // Actualiza el contador interno - Color getSelectedColor(); // Devuelve el color del elemento seleccionado - void initializeOptions(); // Crea todas las opciones del menú de servicio - OptionPairs getOptionPairs(SettingsGroup group) const; - std::vector getOptionsByGroup(SettingsGroup group) const; - void applySettings(SettingsGroup group); - void updateMenu(SettingsGroup group); - void reset(); - int calculateMenuHeight(); - int findLargestGroupSize(); - GroupAlignment getGroupAlignment(SettingsGroup group); + // --- Métodos internos: Anclaje y aspecto --- + void setAnchors(); // Establece el valor de las variables de anclaje + Color getSelectedColor() const; // Devuelve el color del elemento seleccionado + + // --- Métodos internos: Gestión de opciones --- + void initializeOptions(); // Crea todas las opciones del menú de servicio + OptionPairs getOptionPairs(SettingsGroup group) const; // Devuelve las opciones como pares de strings para un grupo + std::vector getOptionsByGroup(SettingsGroup group) const; // Devuelve las opciones de un grupo + + // --- Métodos internos: Lógica de menú --- + void applySettings(SettingsGroup group); // Aplica la configuración de un grupo + void updateMenu(SettingsGroup group); // Actualiza las opciones mostradas según el grupo + void reset(); // Reinicia el menú al estado inicial + + // --- Métodos internos: Utilidades --- + void updateCounter(); // Actualiza el contador interno + int calculateMenuHeight() const; // Calcula la altura del menú + int findLargestGroupSize() const; // Devuelve el tamaño del grupo más grande + GroupAlignment getGroupAlignment(SettingsGroup group) const; // Devuelve la alineación del grupo // --- Patrón Singleton --- ServiceMenu(); // Constructor privado ~ServiceMenu() = default; // Destructor privado - ServiceMenu(const ServiceMenu &) = delete; // Evitar copia - ServiceMenu &operator=(const ServiceMenu &) = delete; // Evitar asignación + ServiceMenu(const ServiceMenu &) = delete; // Evita la copia + ServiceMenu &operator=(const ServiceMenu &) = delete; // Evita la asignación - // --- Singleton --- - static ServiceMenu *instance_; + // --- Instancia Singleton --- + static ServiceMenu *instance_; // Instancia única del menú de servicio + + // --- Método para reproducir el sonido del menú --- + void playMenuSound(); // Reproduce el sonido del menú }; \ No newline at end of file