new: treballant en Console 2.0

This commit is contained in:
2026-03-30 19:11:24 +02:00
parent 9e1b2b8960
commit 0a740a5be2
2 changed files with 116 additions and 25 deletions

View File

@@ -5,6 +5,7 @@
#include <cctype> // Para toupper #include <cctype> // Para toupper
#include <functional> // Para function #include <functional> // Para function
#include <iostream> // Para std::cout #include <iostream> // Para std::cout
#include <sstream> // Para std::istringstream
#include <string> // Para string #include <string> // Para string
#include <vector> // Para vector #include <vector> // Para vector
@@ -787,17 +788,50 @@ static const std::vector<ConsoleCommand> COMMANDS = {
return std::to_string(w) + "x" + std::to_string(h); return std::to_string(w) + "x" + std::to_string(h);
}}, }},
// HELP / ? — Muestra ayuda en la terminal del sistema // HELP / ? — Muestra ayuda en la terminal del sistema y lista de comandos en consola
{.keyword = "HELP", .execute = [](const std::vector<std::string>&) -> std::string { {.keyword = "HELP", .execute = [](const std::vector<std::string>&) -> std::string {
printHelp(); printHelp();
return "Help printed to terminal"; std::string result =
"Commands (see terminal):\n"
"fullscreen, zoom, intscale, vsync, driver\n"
"palette, audio, music, sound, set\n"
"restart, kiosk, exit, quit, show\n"
"hide, size, help\n";
#ifdef _DEBUG
result += "\n[debug] debug room scene";
result += "\ncheat";
#endif
return result;
}}, }},
{.keyword = "?", .execute = [](const std::vector<std::string>&) -> std::string { {.keyword = "?", .execute = [](const std::vector<std::string>&) -> std::string {
printHelp(); printHelp();
return "Help printed to terminal"; std::string result =
"Commands (see terminal):\n"
"[video] fullscreen zoom\n"
"intscale vsync driver\n"
"palette\n"
"[audio] audio music sound\n"
"[game] set restart kiosk\n"
"exit quit\n"
"[info] show hide size help";
#ifdef _DEBUG
result += "\n[debug] debug room scene";
result += "\ncheat";
#endif
return result;
}}, }},
}; };
// ── Helpers ───────────────────────────────────────────────────────────────────
// Calcula la altura total de la consola para N líneas de mensaje (+ 1 línea de input)
static auto calcTargetHeight(int num_msg_lines) -> float {
constexpr int TEXT_SIZE = 6;
constexpr int PADDING_IN_V = TEXT_SIZE / 2;
return static_cast<float>((TEXT_SIZE * (num_msg_lines + 1)) + (PADDING_IN_V * 2));
}
// ── Singleton ───────────────────────────────────────────────────────────────── // ── Singleton ─────────────────────────────────────────────────────────────────
// [SINGLETON] // [SINGLETON]
@@ -822,13 +856,11 @@ auto Console::get() -> Console* {
// Constructor // Constructor
Console::Console(const std::string& font_name) Console::Console(const std::string& font_name)
: text_(Resource::Cache::get()->getText(font_name)) { : text_(Resource::Cache::get()->getText(font_name)) {
const int TEXT_SIZE = 6; msg_lines_ = {std::string(CONSOLE_NAME) + " " + std::string(CONSOLE_VERSION)};
const int PADDING_IN_V = TEXT_SIZE / 2; height_ = calcTargetHeight(static_cast<int>(msg_lines_.size()));
height_ = static_cast<float>((TEXT_SIZE * 2) + (PADDING_IN_V * 2)); target_height_ = height_;
y_ = -height_; y_ = -height_;
msg_line_ = std::string(CONSOLE_NAME) + " " + std::string(CONSOLE_VERSION);
buildSurface(); buildSurface();
} }
@@ -849,9 +881,9 @@ void Console::buildSurface() {
// Redibuja el texto dinámico sobre la surface (fondo + borde + líneas) // Redibuja el texto dinámico sobre la surface (fondo + borde + líneas)
void Console::redrawText() { void Console::redrawText() {
const float WIDTH = Options::game.width; const float WIDTH = Options::game.width;
const int TEXT_SIZE = 6; constexpr int TEXT_SIZE = 6;
const int PADDING_IN_H = TEXT_SIZE; constexpr int PADDING_IN_H = TEXT_SIZE;
const int PADDING_IN_V = TEXT_SIZE / 2; constexpr int PADDING_IN_V = TEXT_SIZE / 2;
auto previous_renderer = Screen::get()->getRendererSurface(); auto previous_renderer = Screen::get()->getRendererSurface();
Screen::get()->setRendererSurface(surface_); Screen::get()->setRendererSurface(surface_);
@@ -861,13 +893,17 @@ void Console::redrawText() {
SDL_FRect rect = {.x = 0, .y = 0, .w = WIDTH, .h = height_}; SDL_FRect rect = {.x = 0, .y = 0, .w = WIDTH, .h = height_};
surface_->drawRectBorder(&rect, BORDER_COLOR); surface_->drawRectBorder(&rect, BORDER_COLOR);
// Línea 1: mensajes // Líneas de mensaje (una o más); las que no caben en la Surface no se dibujan
text_->writeColored(PADDING_IN_H, PADDING_IN_V, msg_line_, MSG_COLOR); int y_pos = PADDING_IN_V;
for (const auto& line : msg_lines_) {
text_->writeColored(PADDING_IN_H, y_pos, line, MSG_COLOR);
y_pos += TEXT_SIZE;
}
// Línea 2: prompt + input + cursor // Línea de input (siempre la última)
const bool SHOW_CURSOR = cursor_visible_ && (static_cast<int>(input_line_.size()) < MAX_LINE_CHARS); const bool SHOW_CURSOR = cursor_visible_ && (static_cast<int>(input_line_.size()) < MAX_LINE_CHARS);
const std::string INPUT_STR = "> " + input_line_ + (SHOW_CURSOR ? "_" : ""); const std::string INPUT_STR = "> " + input_line_ + (SHOW_CURSOR ? "_" : "");
text_->writeColored(PADDING_IN_H, PADDING_IN_V + TEXT_SIZE, INPUT_STR, BORDER_COLOR); text_->writeColored(PADDING_IN_H, y_pos, INPUT_STR, BORDER_COLOR);
Screen::get()->setRendererSurface(previous_renderer); Screen::get()->setRendererSurface(previous_renderer);
} }
@@ -888,6 +924,31 @@ void Console::update(float delta_time) {
} }
} }
// Animación de altura (resize cuando msg_lines_ cambia); solo en ACTIVE
if (status_ == Status::ACTIVE && height_ != target_height_) {
const float PREV_HEIGHT = height_;
if (height_ < target_height_) {
height_ = std::min(height_ + SLIDE_SPEED * delta_time, target_height_);
} else {
height_ = std::max(height_ - SLIDE_SPEED * delta_time, target_height_);
}
// Actualizar el Notifier incrementalmente con el delta de altura
if (Notifier::get() != nullptr) {
const int DELTA_PX = static_cast<int>(height_) - static_cast<int>(PREV_HEIGHT);
if (DELTA_PX > 0) {
Notifier::get()->addYOffset(DELTA_PX);
notifier_offset_applied_ += DELTA_PX;
} else if (DELTA_PX < 0) {
Notifier::get()->removeYOffset(-DELTA_PX);
notifier_offset_applied_ += DELTA_PX;
}
}
// Reconstruir la Surface al nuevo tamaño (pequeña: 256×~18-72px)
const float WIDTH = Options::game.width;
surface_ = std::make_shared<Surface>(WIDTH, height_);
sprite_->setSurface(surface_);
}
// Redibujar texto cada frame // Redibujar texto cada frame
redrawText(); redrawText();
@@ -914,6 +975,7 @@ void Console::update(float delta_time) {
SDL_FRect rect = {.x = 0, .y = y_, .w = Options::game.width, .h = height_}; SDL_FRect rect = {.x = 0, .y = y_, .w = Options::game.width, .h = height_};
sprite_->setPosition(rect); sprite_->setPosition(rect);
sprite_->setClip({.x = 0.0F, .y = 0.0F, .w = Options::game.width, .h = height_});
} }
// Renderiza la consola // Renderiza la consola
@@ -928,21 +990,34 @@ void Console::render() {
void Console::toggle() { void Console::toggle() {
switch (status_) { switch (status_) {
case Status::HIDDEN: case Status::HIDDEN:
// Al abrir: la consola siempre empieza con 1 línea de mensaje (altura base)
target_height_ = calcTargetHeight(static_cast<int>(msg_lines_.size()));
height_ = target_height_;
y_ = -height_;
status_ = Status::RISING; status_ = Status::RISING;
input_line_.clear(); input_line_.clear();
cursor_timer_ = 0.0F; cursor_timer_ = 0.0F;
cursor_visible_ = true; cursor_visible_ = true;
SDL_StartTextInput(SDL_GetKeyboardFocus()); SDL_StartTextInput(SDL_GetKeyboardFocus());
if (Notifier::get() != nullptr) { Notifier::get()->addYOffset(static_cast<int>(height_)); } if (Notifier::get() != nullptr) {
const int OFFSET = static_cast<int>(height_);
Notifier::get()->addYOffset(OFFSET);
notifier_offset_applied_ = OFFSET;
}
if (on_toggle) { on_toggle(true); } if (on_toggle) { on_toggle(true); }
break; break;
case Status::ACTIVE: case Status::ACTIVE:
// Al cerrar: resetear a 1 línea para el próximo ciclo; cerrar con la altura actual
status_ = Status::VANISHING; status_ = Status::VANISHING;
msg_line_ = std::string(CONSOLE_NAME) + " " + std::string(CONSOLE_VERSION); msg_lines_ = {std::string(CONSOLE_NAME) + " " + std::string(CONSOLE_VERSION)};
target_height_ = height_; // No animar durante VANISHING
history_index_ = -1; history_index_ = -1;
saved_input_.clear(); saved_input_.clear();
SDL_StopTextInput(SDL_GetKeyboardFocus()); SDL_StopTextInput(SDL_GetKeyboardFocus());
if (Notifier::get() != nullptr) { Notifier::get()->removeYOffset(static_cast<int>(height_)); } if (Notifier::get() != nullptr) {
Notifier::get()->removeYOffset(notifier_offset_applied_);
notifier_offset_applied_ = 0;
}
if (on_toggle) { on_toggle(false); } if (on_toggle) { on_toggle(false); }
break; break;
default: default:
@@ -1009,20 +1084,31 @@ void Console::processCommand() {
if (!TOKENS.empty()) { if (!TOKENS.empty()) {
const std::string& cmd = TOKENS[0]; const std::string& cmd = TOKENS[0];
const std::vector<std::string> ARGS(TOKENS.begin() + 1, TOKENS.end()); const std::vector<std::string> ARGS(TOKENS.begin() + 1, TOKENS.end());
std::string result;
bool found = false; bool found = false;
for (const auto& command : COMMANDS) { for (const auto& command : COMMANDS) {
if (command.keyword == cmd) { if (command.keyword == cmd) {
msg_line_ = command.execute(ARGS); result = command.execute(ARGS);
found = true; found = true;
break; break;
} }
} }
if (!found) { if (!found) { result = "Unknown: " + cmd; }
msg_line_ = "Unknown: " + cmd;
// Split en '\n' y truncar cada línea a MAX_LINE_CHARS
msg_lines_.clear();
std::istringstream stream(result);
std::string line;
while (std::getline(stream, line)) {
if (static_cast<int>(line.size()) > MAX_LINE_CHARS) {
line.resize(MAX_LINE_CHARS);
} }
if (static_cast<int>(msg_line_.size()) > MAX_LINE_CHARS) { msg_lines_.push_back(std::move(line));
msg_line_.resize(MAX_LINE_CHARS);
} }
if (msg_lines_.empty()) { msg_lines_.push_back({}); }
// Actualizar la altura objetivo para animar el resize
target_height_ = calcTargetHeight(static_cast<int>(msg_lines_.size()));
} }
} }
input_line_.clear(); input_line_.clear();

View File

@@ -6,6 +6,7 @@
#include <functional> // Para function #include <functional> // Para function
#include <memory> // Para shared_ptr #include <memory> // Para shared_ptr
#include <string> // Para string #include <string> // Para string
#include <vector> // Para vector
class Surface; class Surface;
class Sprite; class Sprite;
@@ -77,11 +78,15 @@ class Console {
float height_{0.0F}; // Altura del panel float height_{0.0F}; // Altura del panel
// Estado de la entrada de texto // Estado de la entrada de texto
std::string msg_line_; // inicializado en constructor con CONSOLE_NAME + CONSOLE_VERSION std::vector<std::string> msg_lines_; // Líneas de mensaje (1 o más)
std::string input_line_; std::string input_line_;
float cursor_timer_{0.0F}; float cursor_timer_{0.0F};
bool cursor_visible_{true}; bool cursor_visible_{true};
// Animación de altura dinámica
float target_height_{0.0F}; // Altura objetivo (según número de líneas de mensaje)
int notifier_offset_applied_{0}; // Acumulador del offset enviado al Notifier
// Historial de comandos (navegable con flechas arriba/abajo) // Historial de comandos (navegable con flechas arriba/abajo)
std::deque<std::string> history_; std::deque<std::string> history_;
int history_index_{-1}; // -1 = en la entrada actual (presente) int history_index_{-1}; // -1 = en la entrada actual (presente)