diff --git a/data/console/commands.yaml b/data/console/commands.yaml index bf0e26e..e132ddd 100644 --- a/data/console/commands.yaml +++ b/data/console/commands.yaml @@ -88,6 +88,15 @@ categories: PALETTE SORT: [ORIGINAL, OPTIMAL, REFERENCE] dynamic_completions: true + - keyword: CONSOLE + handler: cmd_console + description: "Console appearance" + usage: "CONSOLE [TRANSPARENT [ON|OFF]|BG|MSG|PROMPT|COMMAND <0-255>]" + scope: global + completions: + CONSOLE: [TRANSPARENT, BG, MSG, PROMPT, COMMAND] + CONSOLE TRANSPARENT: [ON, OFF] + - name: AUDIO scope: game commands: diff --git a/source/game/defaults.hpp b/source/game/defaults.hpp index 667fb6c..b206cba 100644 --- a/source/game/defaults.hpp +++ b/source/game/defaults.hpp @@ -106,6 +106,14 @@ namespace Defaults::Notification { constexpr Uint8 CHEEVO_TEXT_COLOR = 9; // Color del texto (CHEEVO) — blanco } // namespace Defaults::Notification +namespace Defaults::Console { + constexpr bool TRANSPARENT = false; // Por defecto sólida + constexpr Uint8 BG_COLOR = 0; // Color de fondo (índice de paleta) + constexpr Uint8 MSG_COLOR = 8; // Color de los mensajes + constexpr Uint8 PROMPT_COLOR = 9; // Color del prompt y del borde + constexpr Uint8 COMMAND_COLOR = 9; // Color del texto que escribe el usuario +} // namespace Defaults::Console + namespace Defaults::Localization { constexpr const char* LANGUAGE = "ca"; // Idioma por defecto (en = inglés, ca = catalán) } // namespace Defaults::Localization diff --git a/source/game/options.cpp b/source/game/options.cpp index 921602c..5bc4a57 100644 --- a/source/game/options.cpp +++ b/source/game/options.cpp @@ -586,6 +586,28 @@ namespace Options { } } + // Carga configuración de la consola desde YAML + void loadConsoleConfigFromYaml(const fkyaml::node& yaml) { // NOLINT(readability-function-cognitive-complexity) + if (!yaml.contains("console")) { return; } + const auto& c = yaml["console"]; + + if (c.contains("transparent")) { + try { console.transparent = c["transparent"].get_value(); } catch (...) {} + } + if (c.contains("bg_color")) { + try { console.bg_color = std::clamp(c["bg_color"].get_value(), 0, 255); } catch (...) {} + } + if (c.contains("msg_color")) { + try { console.msg_color = std::clamp(c["msg_color"].get_value(), 0, 255); } catch (...) {} + } + if (c.contains("prompt_color")) { + try { console.prompt_color = std::clamp(c["prompt_color"].get_value(), 0, 255); } catch (...) {} + } + if (c.contains("command_color")) { + try { console.command_color = std::clamp(c["command_color"].get_value(), 0, 255); } catch (...) {} + } + } + // Carga configuración de idioma desde YAML void loadLocalizationFromYaml(const fkyaml::node& yaml) { if (yaml.contains("localization")) { @@ -650,6 +672,7 @@ namespace Options { loadGamepadControlsFromYaml(yaml); loadKioskConfigFromYaml(yaml); loadLocalizationFromYaml(yaml); + loadConsoleConfigFromYaml(yaml); std::cout << "Config file loaded successfully\n\n"; @@ -724,6 +747,16 @@ namespace Options { file << " volume: " << audio.sound.volume << "\n"; file << "\n"; + // CONSOLE + file << "# CONSOLE\n"; + file << "console:\n"; + file << " transparent: " << (console.transparent ? "true" : "false") << " # true = sin fondo, false = solida\n"; + file << " bg_color: " << console.bg_color << " # indice de paleta del fondo (solo si transparent: false)\n"; + file << " msg_color: " << console.msg_color << " # indice de paleta de los mensajes\n"; + file << " prompt_color: " << console.prompt_color << " # indice de paleta del prompt y del borde\n"; + file << " command_color: " << console.command_color << " # indice de paleta del texto escrito por el usuario\n"; + file << "\n"; + // VIDEO file << "# VIDEO \n"; file << "video:\n"; diff --git a/source/game/options.hpp b/source/game/options.hpp index e841650..4e6dff1 100644 --- a/source/game/options.hpp +++ b/source/game/options.hpp @@ -138,6 +138,15 @@ namespace Options { float height{Defaults::Canvas::HEIGHT}; // Alto de la resolucion del juego }; + // Estructura para las opciones visuales de la consola en pantalla + struct Console { + bool transparent{Defaults::Console::TRANSPARENT}; // true = sin fondo, false = sólida + int bg_color{Defaults::Console::BG_COLOR}; // Índice de paleta del fondo (sólo si !transparent) + int msg_color{Defaults::Console::MSG_COLOR}; // Índice de paleta de las líneas de mensaje + int prompt_color{Defaults::Console::PROMPT_COLOR}; // Índice de paleta del prompt y del borde + int command_color{Defaults::Console::COMMAND_COLOR};// Índice de paleta del texto escrito por el usuario + }; + // Estructura para un preset de PostFX struct PostFXPreset { std::string name; // Nombre del preset @@ -181,6 +190,7 @@ namespace Options { inline KeyboardControls keyboard_controls{}; // Teclas usadas para jugar inline GamepadControls gamepad_controls{}; // Botones del gamepad usados para jugar inline Kiosk kiosk{}; // Opciones del modo kiosko + inline Console console{}; // Opciones visuales de la consola en pantalla // Idioma del juego (establecido al inicio, sin cambio en caliente) inline std::string language{Defaults::Localization::LANGUAGE}; diff --git a/source/game/ui/console.cpp b/source/game/ui/console.cpp index ed0f008..3d75854 100644 --- a/source/game/ui/console.cpp +++ b/source/game/ui/console.cpp @@ -133,14 +133,23 @@ void Console::redrawText() { const float WIDTH = Options::game.width; constexpr int PADDING_IN_H = TEXT_SIZE; constexpr int PADDING_IN_V = TEXT_SIZE / 2; + constexpr Uint8 TRANSPARENT_SENTINEL = 255; // Coincide con Surface::transparent_color_ por defecto auto previous_renderer = Screen::get()->getRendererSurface(); Screen::get()->setRendererSurface(surface_); + // Colores leídos de Options (modificables en caliente con el comando CONSOLE) + const Uint8 BG_COLOR = Options::console.transparent + ? TRANSPARENT_SENTINEL + : static_cast(Options::console.bg_color); + const auto MSG_COLOR = static_cast(Options::console.msg_color); + const auto PROMPT_COLOR = static_cast(Options::console.prompt_color); + const auto COMMAND_COLOR = static_cast(Options::console.command_color); + // Fondo y borde surface_->clear(BG_COLOR); SDL_FRect rect = {.x = 0, .y = 0, .w = WIDTH, .h = height_}; - surface_->drawRectBorder(&rect, BORDER_COLOR); + surface_->drawRectBorder(&rect, PROMPT_COLOR); // La surface de la fuente tiene transparent_color_=255 por defecto, // pero sus píxeles de fondo son color 0. Cambiarlo temporalmente a 0 @@ -160,10 +169,12 @@ void Console::redrawText() { y_pos += TEXT_SIZE; } - // Línea de input (siempre la última) + // Línea de input (siempre la última): prompt en PROMPT_COLOR, comando + cursor en COMMAND_COLOR const bool SHOW_CURSOR = cursor_visible_ && (static_cast(input_line_.size()) < MAX_LINE_CHARS); - const std::string INPUT_STR = prompt_ + input_line_ + (SHOW_CURSOR ? "_" : ""); - text_->writeColored(PADDING_IN_H, y_pos, INPUT_STR, BORDER_COLOR); + text_->writeColored(PADDING_IN_H, y_pos, prompt_, PROMPT_COLOR); + const int PROMPT_PX = text_->length(prompt_); + const std::string CMD_STR = input_line_ + (SHOW_CURSOR ? "_" : ""); + text_->writeColored(PADDING_IN_H + PROMPT_PX, y_pos, CMD_STR, COMMAND_COLOR); // Restaurar transparent_color_ original de la fuente font_surface->setTransparentColor(PREV_TRANSPARENT); diff --git a/source/game/ui/console.hpp b/source/game/ui/console.hpp index 7d65731..7f8c298 100644 --- a/source/game/ui/console.hpp +++ b/source/game/ui/console.hpp @@ -54,9 +54,6 @@ class Console { }; // Constantes visuales - static constexpr Uint8 BG_COLOR = 255; // Transparente (sin fondo) - static constexpr Uint8 BORDER_COLOR = 9; // PaletteColor::BRIGHT_GREEN - static constexpr Uint8 MSG_COLOR = 8; // PaletteColor::GREEN static constexpr float SLIDE_SPEED = 180.0F; // Constantes de consola diff --git a/source/game/ui/console_commands.cpp b/source/game/ui/console_commands.cpp index 8554144..2823ea2 100644 --- a/source/game/ui/console_commands.cpp +++ b/source/game/ui/console_commands.cpp @@ -951,6 +951,54 @@ static auto cmdSize(const std::vector& /*unused*/) -> std::string { return std::to_string(w) + "x" + std::to_string(h); } +// CONSOLE [TRANSPARENT [ON|OFF]|BG|MSG|PROMPT|COMMAND <0-255>] +static auto cmdConsole(const std::vector& args) -> std::string { // NOLINT(readability-function-cognitive-complexity) + if (args.empty()) { + return std::string("Console ") + (Options::console.transparent ? "transparent" : "solid") + + " bg:" + std::to_string(Options::console.bg_color) + + " msg:" + std::to_string(Options::console.msg_color) + + " prompt:" + std::to_string(Options::console.prompt_color) + + " cmd:" + std::to_string(Options::console.command_color); + } + + if (args[0] == "TRANSPARENT") { + if (args.size() < 2) { + return std::string("Console ") + (Options::console.transparent ? "transparent" : "solid"); + } + if (args[1] == "ON") { + Options::console.transparent = true; + return "Console transparent"; + } + if (args[1] == "OFF") { + Options::console.transparent = false; + return "Console solid"; + } + return "usage: console transparent [on|off]"; + } + + // Helper para los cuatro comandos de color (BG, MSG, PROMPT, COMMAND) + const auto SET_COLOR = [&args](int& target, const char* label) -> std::string { + if (args.size() < 2) { + return std::string("Console ") + label + ":" + std::to_string(target); + } + try { + const int VAL = std::stoi(args[1]); + if (VAL < 0 || VAL > 255) { return std::string(label) + " must be 0-255"; } + target = VAL; + return std::string("Console ") + label + ":" + std::to_string(VAL); + } catch (...) { + return std::string("usage: console ") + label + " <0-255>"; + } + }; + + if (args[0] == "BG") { return SET_COLOR(Options::console.bg_color, "bg"); } + if (args[0] == "MSG") { return SET_COLOR(Options::console.msg_color, "msg"); } + if (args[0] == "PROMPT") { return SET_COLOR(Options::console.prompt_color, "prompt"); } + if (args[0] == "COMMAND") { return SET_COLOR(Options::console.command_color, "command"); } + + return "usage: console [transparent [on|off]|bg|msg|prompt|command <0-255>]"; +} + // ── CommandRegistry ────────────────────────────────────────────────────────── void CommandRegistry::registerHandlers() { // NOLINT(readability-function-cognitive-complexity) @@ -974,6 +1022,7 @@ void CommandRegistry::registerHandlers() { // NOLINT(readability-function-cogni handlers_["cmd_exit"] = cmdExit; handlers_["cmd_quit"] = cmdExit; // QUIT usa el mismo handler que EXIT handlers_["cmd_size"] = cmdSize; + handlers_["cmd_console"] = cmdConsole; #ifdef _DEBUG handlers_["cmd_debug"] = cmdDebug; handlers_["cmd_items"] = cmdItems;