diff --git a/source/core/input/input.cpp b/source/core/input/input.cpp index d44bc41..b350ff9 100644 --- a/source/core/input/input.cpp +++ b/source/core/input/input.cpp @@ -52,7 +52,7 @@ Input::Input(std::string game_controller_db_path) {Action::TOGGLE_VSYNC, KeyState{.scancode = SDL_SCANCODE_F10}}, {Action::PAUSE, KeyState{.scancode = SDL_SCANCODE_F11}}, {Action::TOGGLE_INFO, KeyState{.scancode = SDL_SCANCODE_F12}}, - {Action::TOGGLE_CONSOLE, KeyState{.scancode = SDL_SCANCODE_TAB}}}; + {Action::TOGGLE_CONSOLE, KeyState{.scancode = SDL_SCANCODE_GRAVE}}}; initSDLGamePad(); // Inicializa el subsistema SDL_INIT_GAMEPAD } diff --git a/source/game/ui/console.cpp b/source/game/ui/console.cpp index 5d9bc80..1fe7da1 100644 --- a/source/game/ui/console.cpp +++ b/source/game/ui/console.cpp @@ -32,6 +32,7 @@ struct ConsoleCommand { std::string_view keyword; std::function& args)> execute; bool instant{false}; // Si true, muestra la respuesta sin efecto typewriter + bool hidden{false}; // Si true, no aparece en el autocompletado (TAB) }; // Convierte la entrada a uppercase y la divide en tokens por espacios @@ -130,6 +131,13 @@ static void printHelp() { #endif } +// En Release, los comandos de truco (CHEAT) son ocultos en el autocompletado +#ifdef _DEBUG +static constexpr bool CHEAT_HIDDEN = false; +#else +static constexpr bool CHEAT_HIDDEN = true; +#endif + // Tabla de comandos disponibles static const std::vector COMMANDS = { // SS [ON|OFF|SIZE|UPSCALE [NEAREST|LINEAR]|DOWNSCALE [BILINEAR|LANCZOS2|LANCZOS3]] — Supersampling @@ -514,7 +522,8 @@ static const std::vector COMMANDS = { } return "usage: cheat [infinite lives|invincibility|open the jail|close the jail]"; - }}, + }, + .hidden = CHEAT_HIDDEN}, // SET PLAYER SKIN <1|2> — Cambia la skin del jugador (disponible en todos los builds, GAME) // SET INITIAL [ROOM|POS] — Guarda habitación/posición actual como inicio (solo _DEBUG, GAME) @@ -1085,15 +1094,19 @@ void Console::handleEvent(const SDL_Event& event) { if (status_ != Status::ACTIVE) { return; } if (event.type == SDL_EVENT_TEXT_INPUT) { + // Filtrar caracteres de control (tab, newline, etc.) + if (static_cast(event.text.text[0]) < 32) { return; } if (static_cast(input_line_.size()) < MAX_LINE_CHARS) { input_line_ += event.text.text; } + tab_matches_.clear(); return; } if (event.type == SDL_EVENT_KEY_DOWN) { switch (event.key.scancode) { case SDL_SCANCODE_BACKSPACE: + tab_matches_.clear(); if (!input_line_.empty()) { input_line_.pop_back(); } break; case SDL_SCANCODE_RETURN: @@ -1102,6 +1115,7 @@ void Console::handleEvent(const SDL_Event& event) { break; case SDL_SCANCODE_UP: // Navegar hacia atrás en el historial + tab_matches_.clear(); if (history_index_ < static_cast(history_.size()) - 1) { if (history_index_ == -1) { saved_input_ = input_line_; } ++history_index_; @@ -1110,6 +1124,7 @@ void Console::handleEvent(const SDL_Event& event) { break; case SDL_SCANCODE_DOWN: // Navegar hacia el presente en el historial + tab_matches_.clear(); if (history_index_ >= 0) { --history_index_; input_line_ = (history_index_ == -1) @@ -1117,6 +1132,29 @@ void Console::handleEvent(const SDL_Event& event) { : history_[static_cast(history_index_)]; } break; + case SDL_SCANCODE_TAB: { + // Calcular prefijo (input actual en mayúsculas) + std::string prefix; + for (unsigned char c : input_line_) { prefix += static_cast(std::toupper(c)); } + // Regenerar lista si el prefijo ha cambiado o la lista está vacía + if (tab_matches_.empty() || tab_prefix_ != prefix) { + tab_matches_.clear(); + tab_prefix_ = prefix; + for (const auto& cmd : COMMANDS) { + if (cmd.hidden) { continue; } + if (prefix.empty() || cmd.keyword.starts_with(prefix)) { + tab_matches_.push_back(std::string(cmd.keyword)); + } + } + tab_index_ = -1; + } + if (tab_matches_.empty()) { break; } + tab_index_ = (tab_index_ + 1) % static_cast(tab_matches_.size()); + std::string lower = tab_matches_[static_cast(tab_index_)]; + for (char& c : lower) { c = static_cast(std::tolower(static_cast(c))); } + input_line_ = lower; + break; + } default: break; } @@ -1171,6 +1209,7 @@ void Console::processCommand() { input_line_.clear(); history_index_ = -1; saved_input_.clear(); + tab_matches_.clear(); cursor_timer_ = 0.0F; cursor_visible_ = true; } diff --git a/source/game/ui/console.hpp b/source/game/ui/console.hpp index 259e9b6..a491781 100644 --- a/source/game/ui/console.hpp +++ b/source/game/ui/console.hpp @@ -97,4 +97,9 @@ class Console { std::deque history_; int history_index_{-1}; // -1 = en la entrada actual (presente) std::string saved_input_; // guarda input_line_ al empezar a navegar + + // Estado de autocompletado (TAB) + std::vector tab_matches_; // Comandos que coinciden con el prefijo actual + int tab_index_{-1}; // Índice actual en tab_matches_ + std::string tab_prefix_; // Prefijo usado en la última búsqueda TAB };