#include "core/input/global_inputs.hpp" #include #include // Para allocator, operator+, char_traits, string #include // Para vector #include "core/input/input.hpp" // Para Input, InputAction, Input::DO_NOT_ALLOW_REPEAT #include "core/locale/locale.hpp" // Para Locale #include "core/rendering/render_info.hpp" // Para RenderInfo #include "core/rendering/screen.hpp" // Para Screen #include "game/options.hpp" // Para Options, options, OptionsVideo, Section #include "game/scene_manager.hpp" // Para SceneManager #include "game/ui/console.hpp" // Para Console #include "game/ui/notifier.hpp" // Para Notifier, NotificationText #include "utils/utils.hpp" // Para stringInVector namespace GlobalInputs { // Funciones internas namespace { void handleQuit() { // En la escena GAME el comportamiento es siempre el mismo (con o sin modo kiosko) if (SceneManager::current == SceneManager::Scene::GAME) { const std::string CODE = "PRESS AGAIN TO RETURN TO MENU"; if (stringInVector(Notifier::get()->getCodes(), CODE)) { SceneManager::current = SceneManager::Scene::TITLE; } else { Notifier::get()->show({Locale::get()->get("ui.press_again_menu")}, Notifier::Style::DEFAULT, -1, true, CODE); // NOLINT(readability-static-accessed-through-instance) } return; } // En modo kiosko, fuera de GAME: mostrar el texto del kiosko y no salir nunca if (Options::kiosk.enabled) { const std::string KIOSK_CODE = "KIOSK_EXIT"; if (!stringInVector(Notifier::get()->getCodes(), KIOSK_CODE)) { Notifier::get()->show({Options::kiosk.text}, Notifier::Style::DEFAULT, -1, true, KIOSK_CODE); } // Segunda pulsación: notificación ya activa → no hacer nada return; } // Comportamiento normal fuera del modo kiosko const std::string CODE = "PRESS AGAIN TO EXIT"; if (stringInVector(Notifier::get()->getCodes(), CODE)) { SceneManager::current = SceneManager::Scene::QUIT; } else { Notifier::get()->show({Locale::get()->get("ui.press_again_exit")}, Notifier::Style::DEFAULT, -1, true, CODE); // NOLINT(readability-static-accessed-through-instance) } } void handleSkipSection() { switch (SceneManager::current) { case SceneManager::Scene::LOGO: SceneManager::current = SceneManager::Scene::TITLE; SceneManager::options = SceneManager::Options::NONE; break; default: break; } } void handleToggleBorder() { Screen::get()->toggleBorder(); Notifier::get()->show({Locale::get()->get(Options::video.border.enabled ? "ui.border_enabled" : "ui.border_disabled")}); // NOLINT(readability-static-accessed-through-instance) } void handleToggleVideoMode() { Screen::get()->toggleVideoMode(); Notifier::get()->show({Locale::get()->get(static_cast(Options::video.fullscreen) == 0 ? "ui.fullscreen_disabled" : "ui.fullscreen_enabled")}); // NOLINT(readability-static-accessed-through-instance) } void handleDecWindowZoom() { if (Screen::get()->decWindowZoom()) { Notifier::get()->show({Locale::get()->get("ui.window_zoom") + std::to_string(Options::window.zoom)}); // NOLINT(readability-static-accessed-through-instance) } } void handleIncWindowZoom() { if (Screen::get()->incWindowZoom()) { Notifier::get()->show({Locale::get()->get("ui.window_zoom") + std::to_string(Options::window.zoom)}); // NOLINT(readability-static-accessed-through-instance) } } void handleToggleShaders() { Screen::get()->toggleShaders(); Notifier::get()->show({Locale::get()->get(Options::video.shader.enabled ? "ui.shaders_enabled" : "ui.shaders_disabled")}); // NOLINT(readability-static-accessed-through-instance) } void handleNextShaderPreset() { if (Options::video.shader.current_shader == Rendering::ShaderType::CRTPI) { if (!Options::crtpi_presets.empty()) { Options::video.shader.current_crtpi_preset = (Options::video.shader.current_crtpi_preset + 1) % static_cast(Options::crtpi_presets.size()); Screen::get()->reloadCrtPi(); Notifier::get()->show({Locale::get()->get("ui.crtpi") + " " + prettyName(Options::crtpi_presets[static_cast(Options::video.shader.current_crtpi_preset)].name)}); // NOLINT(readability-static-accessed-through-instance) } } else { if (!Options::postfx_presets.empty()) { Options::video.shader.current_postfx_preset = (Options::video.shader.current_postfx_preset + 1) % static_cast(Options::postfx_presets.size()); Screen::get()->reloadPostFX(); Notifier::get()->show({Locale::get()->get("ui.postfx") + " " + prettyName(Options::postfx_presets[static_cast(Options::video.shader.current_postfx_preset)].name)}); // NOLINT(readability-static-accessed-through-instance) } } } void handleNextShader() { Screen::get()->nextShader(); Notifier::get()->show({Locale::get()->get("ui.shader") + " " + // NOLINT(readability-static-accessed-through-instance) (Options::video.shader.current_shader == Rendering::ShaderType::CRTPI ? "CRTPI" : "POSTFX")}); } void handleNextPalette() { Screen::get()->nextPalette(); Notifier::get()->show({Locale::get()->get("ui.palette") + " " + toUpper(Screen::get()->getPalettePrettyName())}); // NOLINT(readability-static-accessed-through-instance) } void handlePreviousPalette() { Screen::get()->previousPalette(); Notifier::get()->show({Locale::get()->get("ui.palette") + " " + toUpper(Screen::get()->getPalettePrettyName())}); // NOLINT(readability-static-accessed-through-instance) } void handleNextPaletteSortMode() { Screen::get()->nextPaletteSortMode(); Notifier::get()->show({Locale::get()->get("ui.palette_sort") + " " + toUpper(Screen::get()->getPaletteSortModeName())}); // NOLINT(readability-static-accessed-through-instance) } void handleToggleIntegerScale() { Screen::get()->toggleIntegerScale(); Screen::get()->setVideoMode(Options::video.fullscreen); Notifier::get()->show({Locale::get()->get(Options::video.integer_scale ? "ui.integer_scale_enabled" : "ui.integer_scale_disabled")}); // NOLINT(readability-static-accessed-through-instance) } void handleToggleVSync() { Screen::get()->toggleVSync(); Notifier::get()->show({Locale::get()->get(Options::video.vertical_sync ? "ui.vsync_enabled" : "ui.vsync_disabled")}); // NOLINT(readability-static-accessed-through-instance) } // Detecta qué acción global ha sido presionada (si alguna) auto getPressedAction() -> InputAction { // NOLINT(readability-function-cognitive-complexity) if (Input::get()->checkAction(InputAction::EXIT, Input::DO_NOT_ALLOW_REPEAT)) { return InputAction::EXIT; } if (Input::get()->checkAction(InputAction::ACCEPT, Input::DO_NOT_ALLOW_REPEAT)) { return InputAction::ACCEPT; } if (Input::get()->checkAction(InputAction::TOGGLE_BORDER, Input::DO_NOT_ALLOW_REPEAT)) { return InputAction::TOGGLE_BORDER; } if (!Options::kiosk.enabled) { if (Input::get()->checkAction(InputAction::TOGGLE_FULLSCREEN, Input::DO_NOT_ALLOW_REPEAT)) { return InputAction::TOGGLE_FULLSCREEN; } if (Input::get()->checkAction(InputAction::WINDOW_DEC_ZOOM, Input::DO_NOT_ALLOW_REPEAT)) { return InputAction::WINDOW_DEC_ZOOM; } if (Input::get()->checkAction(InputAction::WINDOW_INC_ZOOM, Input::DO_NOT_ALLOW_REPEAT)) { return InputAction::WINDOW_INC_ZOOM; } } if (Screen::get()->isHardwareAccelerated()) { if (Input::get()->checkAction(InputAction::TOGGLE_SHADER, Input::DO_NOT_ALLOW_REPEAT)) { if ((SDL_GetModState() & SDL_KMOD_CTRL) != 0U) { return InputAction::TOGGLE_SUPERSAMPLING; // Ctrl+F4 } if (Options::video.shader.enabled && ((SDL_GetModState() & SDL_KMOD_SHIFT) != 0U)) { return InputAction::NEXT_SHADER_PRESET; // Shift+F4 } return InputAction::TOGGLE_SHADER; // F4 } } if (Input::get()->checkAction(InputAction::NEXT_PALETTE, Input::DO_NOT_ALLOW_REPEAT)) { if ((SDL_GetModState() & SDL_KMOD_CTRL) != 0U) { return InputAction::PREVIOUS_PALETTE; // Ctrl+F5 } return InputAction::NEXT_PALETTE; // F5 } if (Input::get()->checkAction(InputAction::NEXT_PALETTE_SORT, Input::DO_NOT_ALLOW_REPEAT)) { return InputAction::NEXT_PALETTE_SORT; // F6 } if (Input::get()->checkAction(InputAction::TOGGLE_INTEGER_SCALE, Input::DO_NOT_ALLOW_REPEAT)) { return InputAction::TOGGLE_INTEGER_SCALE; } if (Input::get()->checkAction(InputAction::TOGGLE_VSYNC, Input::DO_NOT_ALLOW_REPEAT)) { return InputAction::TOGGLE_VSYNC; } if (Input::get()->checkAction(InputAction::TOGGLE_INFO, Input::DO_NOT_ALLOW_REPEAT)) { return InputAction::TOGGLE_INFO; } if (Input::get()->checkAction(InputAction::TOGGLE_CONSOLE, Input::DO_NOT_ALLOW_REPEAT)) { return InputAction::TOGGLE_CONSOLE; } return InputAction::NONE; } } // namespace // Funciones públicas // Comprueba los inputs que se pueden introducir en cualquier sección del juego void handle() { const bool CONSOLE_ACTIVE = Console::get() != nullptr && Console::get()->isActive(); if (CONSOLE_ACTIVE) { // TAB/ESC cierran la consola en lugar de ejecutar sus acciones normales if (Input::get()->checkAction(InputAction::TOGGLE_CONSOLE, Input::DO_NOT_ALLOW_REPEAT) || Input::get()->checkAction(InputAction::EXIT, Input::DO_NOT_ALLOW_REPEAT)) { Console::get()->toggle(); return; } } else { // Salida de administrador en modo kiosko (Ctrl+Shift+Alt+Q) if (Options::kiosk.enabled) { SDL_Keymod mod = SDL_GetModState(); const bool* ks = SDL_GetKeyboardState(nullptr); if (((mod & SDL_KMOD_CTRL) != 0U) && ((mod & SDL_KMOD_SHIFT) != 0U) && ((mod & SDL_KMOD_ALT) != 0U) && ks[SDL_SCANCODE_Q]) { SceneManager::current = SceneManager::Scene::QUIT; return; } } } // Detectar qué acción global está siendo presionada InputAction action = getPressedAction(); // Con consola activa, ACCEPT (saltar sección) y EXIT están bloqueados if (CONSOLE_ACTIVE && (action == InputAction::ACCEPT || action == InputAction::EXIT)) { return; } // Ejecutar el handler correspondiente usando switch statement switch (action) { case InputAction::EXIT: handleQuit(); break; case InputAction::ACCEPT: handleSkipSection(); break; case InputAction::TOGGLE_BORDER: handleToggleBorder(); break; case InputAction::TOGGLE_FULLSCREEN: handleToggleVideoMode(); break; case InputAction::WINDOW_DEC_ZOOM: handleDecWindowZoom(); break; case InputAction::WINDOW_INC_ZOOM: handleIncWindowZoom(); break; case InputAction::TOGGLE_SHADER: handleToggleShaders(); break; case InputAction::NEXT_SHADER_PRESET: handleNextShaderPreset(); break; case InputAction::TOGGLE_SUPERSAMPLING: handleNextShader(); break; case InputAction::NEXT_PALETTE: handleNextPalette(); break; case InputAction::PREVIOUS_PALETTE: handlePreviousPalette(); break; case InputAction::NEXT_PALETTE_SORT: handleNextPaletteSortMode(); break; case InputAction::TOGGLE_INTEGER_SCALE: handleToggleIntegerScale(); break; case InputAction::TOGGLE_VSYNC: handleToggleVSync(); break; case InputAction::TOGGLE_CONSOLE: if (Console::get() != nullptr) { Console::get()->toggle(); } break; case InputAction::TOGGLE_INFO: if (RenderInfo::get() != nullptr) { RenderInfo::get()->toggle(); } break; case InputAction::NONE: default: // No se presionó ninguna acción global break; } } } // namespace GlobalInputs