fps: overlay debug a dalt-dreta del canvas (verd, F10 toggle, 8bithud, alineat amb notificacions i overscan-aware)
This commit is contained in:
@@ -127,6 +127,10 @@ namespace GlobalInputs {
|
|||||||
notifyPresentationMode();
|
notifyPresentationMode();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (Input::get()->checkInput(Input::Action::TOGGLE_FPS, Input::Repeat::OFF)) {
|
||||||
|
Screen::get()->toggleFps();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// F5/F6 només actuen quan el post-procesado està actiu.
|
// F5/F6 només actuen quan el post-procesado està actiu.
|
||||||
if (Screen::isShaderEnabled()) {
|
if (Screen::isShaderEnabled()) {
|
||||||
if (Input::get()->checkInput(Input::Action::TOGGLE_SHADER_TYPE, Input::Repeat::OFF)) {
|
if (Input::get()->checkInput(Input::Action::TOGGLE_SHADER_TYPE, Input::Repeat::OFF)) {
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ class Input {
|
|||||||
SHOW_VERSION,
|
SHOW_VERSION,
|
||||||
TOGGLE_VSYNC,
|
TOGGLE_VSYNC,
|
||||||
NEXT_PRESENTATION_MODE,
|
NEXT_PRESENTATION_MODE,
|
||||||
|
TOGGLE_FPS,
|
||||||
|
|
||||||
// Centinela final (usar para sizing)
|
// Centinela final (usar para sizing)
|
||||||
NUMBER_OF_INPUTS
|
NUMBER_OF_INPUTS
|
||||||
|
|||||||
@@ -169,9 +169,12 @@ void Screen::start() {
|
|||||||
|
|
||||||
// Vuelca el contenido del renderizador en pantalla
|
// Vuelca el contenido del renderizador en pantalla
|
||||||
void Screen::blit() {
|
void Screen::blit() {
|
||||||
// Dibuja la notificación activa sobre el gameCanvas antes de presentar
|
updateFps();
|
||||||
|
|
||||||
|
// Dibuja la notificación activa i, si toca, l'overlay de FPS sobre el gameCanvas
|
||||||
SDL_SetRenderTarget(renderer_, game_canvas_);
|
SDL_SetRenderTarget(renderer_, game_canvas_);
|
||||||
renderNotification();
|
renderNotification();
|
||||||
|
renderFps();
|
||||||
|
|
||||||
#ifndef NO_SHADERS
|
#ifndef NO_SHADERS
|
||||||
// Si el backend GPU està viu i accelerat, passem sempre per ell (tant amb
|
// Si el backend GPU està viu i accelerat, passem sempre per ell (tant amb
|
||||||
@@ -525,6 +528,55 @@ void Screen::renderNotification() {
|
|||||||
notification_outline_color_);
|
notification_outline_color_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Alterna la visibilitat de l'overlay de FPS. No persisteix a config.
|
||||||
|
void Screen::toggleFps() {
|
||||||
|
fps_visible_ = !fps_visible_;
|
||||||
|
if (fps_visible_) {
|
||||||
|
fps_window_start_ticks_ = SDL_GetTicks();
|
||||||
|
fps_frame_count_ = 0;
|
||||||
|
fps_value_ = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Screen::isFpsVisible() const -> bool {
|
||||||
|
return fps_visible_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Acumula frames i recalcula el FPS cada segon real (no afectat per dt del joc).
|
||||||
|
// Cridat des de blit() una vegada per frame.
|
||||||
|
void Screen::updateFps() {
|
||||||
|
if (!fps_visible_) { return; }
|
||||||
|
++fps_frame_count_;
|
||||||
|
const Uint32 NOW = SDL_GetTicks();
|
||||||
|
const Uint32 ELAPSED = NOW - fps_window_start_ticks_;
|
||||||
|
if (ELAPSED >= 1000) {
|
||||||
|
fps_value_ = static_cast<int>((static_cast<Uint64>(fps_frame_count_) * 1000) / ELAPSED);
|
||||||
|
fps_frame_count_ = 0;
|
||||||
|
fps_window_start_ticks_ = NOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dibuixa "NN FPS" a dalt a la dreta del canvas, mateixa Y que les notificacions
|
||||||
|
// (incloent l'ajust per overscan) i amb la mateixa font 8bithud.
|
||||||
|
void Screen::renderFps() {
|
||||||
|
if (!fps_visible_ || notification_text_ == nullptr) { return; }
|
||||||
|
constexpr int RIGHT_MARGIN = 2;
|
||||||
|
const Color FPS_COLOR{0x60, 0xD0, 0x70}; // verd (mateix to que SUCCESS de notificacions)
|
||||||
|
const Color FPS_OUTLINE{0x26, 0x53, 0x2C}; // ~40% darken del verd
|
||||||
|
const std::string MSG = std::to_string(fps_value_) + " FPS";
|
||||||
|
const int TEXT_W = notification_text_->lenght(MSG, 1);
|
||||||
|
const int X = game_canvas_width_ - TEXT_W - RIGHT_MARGIN;
|
||||||
|
const int Y = notification_y_ + safeNotificationY();
|
||||||
|
notification_text_->writeDX(Text::FLAG_COLOR | Text::FLAG_STROKE,
|
||||||
|
X,
|
||||||
|
Y,
|
||||||
|
MSG,
|
||||||
|
1,
|
||||||
|
FPS_COLOR,
|
||||||
|
1,
|
||||||
|
FPS_OUTLINE);
|
||||||
|
}
|
||||||
|
|
||||||
// Y minima del canvas visible. Solo no zero quan estem en overscan i l'aspect
|
// Y minima del canvas visible. Solo no zero quan estem en overscan i l'aspect
|
||||||
// de finestra obliga a escalar mes ample que alt (el canvas vertical desborda
|
// de finestra obliga a escalar mes ample que alt (el canvas vertical desborda
|
||||||
// i la franja superior es retalla). En cas contrari (qualsevol altre mode, o
|
// i la franja superior es retalla). En cas contrari (qualsevol altre mode, o
|
||||||
|
|||||||
@@ -73,6 +73,10 @@ class Screen {
|
|||||||
void notify(const std::string &text, Color text_color, Color outline_color, Uint32 duration_ms); // Muestra una notificación en la línea superior del canvas durante durationMs. Sobrescribe cualquier notificación activa (sin apilación).
|
void notify(const std::string &text, Color text_color, Color outline_color, Uint32 duration_ms); // Muestra una notificación en la línea superior del canvas durante durationMs. Sobrescribe cualquier notificación activa (sin apilación).
|
||||||
void clearNotification(); // Limpia la notificación actual
|
void clearNotification(); // Limpia la notificación actual
|
||||||
|
|
||||||
|
// FPS overlay (debug, no persistent)
|
||||||
|
void toggleFps(); // Alterna la visibilitat de l'overlay de FPS
|
||||||
|
[[nodiscard]] auto isFpsVisible() const -> bool; // Estat actual
|
||||||
|
|
||||||
// GPU / shaders (post-procesado). En builds con NO_SHADERS (Emscripten) son no-op.
|
// GPU / shaders (post-procesado). En builds con NO_SHADERS (Emscripten) son no-op.
|
||||||
void initShaders(); // Crea el backend GPU si no existe y lo inicializa
|
void initShaders(); // Crea el backend GPU si no existe y lo inicializa
|
||||||
void shutdownShaders(); // Libera el backend GPU
|
void shutdownShaders(); // Libera el backend GPU
|
||||||
@@ -115,6 +119,10 @@ class Screen {
|
|||||||
void renderNotification(); // Dibuja la notificación activa (si la hay) sobre el gameCanvas
|
void renderNotification(); // Dibuja la notificación activa (si la hay) sobre el gameCanvas
|
||||||
[[nodiscard]] auto safeNotificationY() const -> int; // Y minima dins del canvas que segueix sent visible en overscan (segons aspect ratio finestra/canvas)
|
[[nodiscard]] auto safeNotificationY() const -> int; // Y minima dins del canvas que segueix sent visible en overscan (segons aspect ratio finestra/canvas)
|
||||||
|
|
||||||
|
// FPS overlay
|
||||||
|
void updateFps(); // Acumula temps i recalcula fps cada segon (a cridar des de blit)
|
||||||
|
void renderFps(); // Dibuixa "NN FPS" a dalt a la dreta del canvas
|
||||||
|
|
||||||
#ifndef NO_SHADERS
|
#ifndef NO_SHADERS
|
||||||
// Aplica els paràmetres actuals del shader al backend segons options
|
// Aplica els paràmetres actuals del shader al backend segons options
|
||||||
// (pass-through si `videoShaderEnabled==false`, preset per defecte si true).
|
// (pass-through si `videoShaderEnabled==false`, preset per defecte si true).
|
||||||
@@ -142,6 +150,12 @@ class Screen {
|
|||||||
Uint32 notification_end_time_; // SDL_GetTicks() hasta el cual se muestra
|
Uint32 notification_end_time_; // SDL_GetTicks() hasta el cual se muestra
|
||||||
int notification_y_; // Fila vertical en el canvas virtual
|
int notification_y_; // Fila vertical en el canvas virtual
|
||||||
|
|
||||||
|
// FPS overlay (debug, no persistent)
|
||||||
|
bool fps_visible_{false}; // F10 toggle
|
||||||
|
int fps_value_{0}; // Ultim valor calculat (frames per segon)
|
||||||
|
int fps_frame_count_{0}; // Frames acumulats durant la finestra actual
|
||||||
|
Uint32 fps_window_start_ticks_{0}; // Inici de la finestra d'1s actual (SDL_GetTicks)
|
||||||
|
|
||||||
#ifndef NO_SHADERS
|
#ifndef NO_SHADERS
|
||||||
// GPU / shaders
|
// GPU / shaders
|
||||||
std::unique_ptr<Rendering::ShaderBackend> shader_backend_; // Backend GPU (nullptr si inactivo)
|
std::unique_ptr<Rendering::ShaderBackend> shader_backend_; // Backend GPU (nullptr si inactivo)
|
||||||
|
|||||||
@@ -234,6 +234,7 @@ void Director::initInput() {
|
|||||||
Input::get()->bindKey(Input::Action::NEXT_SHADER_PRESET, SDL_SCANCODE_F6);
|
Input::get()->bindKey(Input::Action::NEXT_SHADER_PRESET, SDL_SCANCODE_F6);
|
||||||
Input::get()->bindKey(Input::Action::TOGGLE_VSYNC, SDL_SCANCODE_F7);
|
Input::get()->bindKey(Input::Action::TOGGLE_VSYNC, SDL_SCANCODE_F7);
|
||||||
Input::get()->bindKey(Input::Action::NEXT_PRESENTATION_MODE, SDL_SCANCODE_F8);
|
Input::get()->bindKey(Input::Action::NEXT_PRESENTATION_MODE, SDL_SCANCODE_F8);
|
||||||
|
Input::get()->bindKey(Input::Action::TOGGLE_FPS, SDL_SCANCODE_F10);
|
||||||
Input::get()->bindKey(Input::Action::SHOW_VERSION, SDL_SCANCODE_F11);
|
Input::get()->bindKey(Input::Action::SHOW_VERSION, SDL_SCANCODE_F11);
|
||||||
|
|
||||||
// Mando - Movimiento del jugador
|
// Mando - Movimiento del jugador
|
||||||
|
|||||||
Reference in New Issue
Block a user