animacions a renderinfo
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
#include "core/rendering/text.hpp"
|
||||
#include "core/system/director.hpp"
|
||||
#include "game/options.hpp"
|
||||
#include "utils/easing.hpp"
|
||||
|
||||
namespace Overlay {
|
||||
|
||||
@@ -50,7 +51,19 @@ namespace Overlay {
|
||||
static Uint32 last_ticks_ = 0;
|
||||
|
||||
// --- Render info ---
|
||||
static std::string render_info_text_;
|
||||
static Options::RenderInfoPosition info_visible_pos_ = Options::RenderInfoPosition::OFF;
|
||||
static float info_anim_ = 0.0F; // 0 = fora de pantalla, 1 = posició final
|
||||
static constexpr float INFO_SLIDE_SPEED = 5.0F;
|
||||
|
||||
// Segments del render info — cadascú amb la seva pròpia visibilitat animada
|
||||
static constexpr int INFO_SEGMENT_COUNT = 4;
|
||||
static constexpr float SEG_SPEED = 6.0F; // ~165 ms per aparèixer/desaparèixer
|
||||
struct InfoSegment {
|
||||
std::string text;
|
||||
float anim{0.0F};
|
||||
bool visible{false};
|
||||
};
|
||||
static InfoSegment info_segments_[INFO_SEGMENT_COUNT];
|
||||
|
||||
// --- Doble ESC per a eixir ---
|
||||
static bool esc_waiting_ = false;
|
||||
@@ -129,17 +142,79 @@ namespace Overlay {
|
||||
font_->draw(pixel_data, box_x + NOTIF_PADDING_H, box_y + NOTIF_PADDING_V, notif.message.c_str(), NOTIF_TEXT_COLOR);
|
||||
}
|
||||
|
||||
// Render info (FPS, driver, shader) — centrat, posició configurable
|
||||
if (Options::render_info.position != Options::RenderInfoPosition::OFF && !render_info_text_.empty()) {
|
||||
int info_w = font_->width(render_info_text_.c_str());
|
||||
int info_x = (SCREEN_W - info_w) / 2;
|
||||
int info_y = (Options::render_info.position == Options::RenderInfoPosition::TOP)
|
||||
? 1
|
||||
: SCREEN_H - font_->charHeight() - 1;
|
||||
// Ombra (1px desplaçat)
|
||||
font_->draw(pixel_data, info_x + 1, info_y + 1, render_info_text_.c_str(), Options::render_info.shadow_color);
|
||||
// Text
|
||||
font_->draw(pixel_data, info_x, info_y, render_info_text_.c_str(), Options::render_info.text_color);
|
||||
// Render info (FPS, driver, shader) — animat amb slide vertical
|
||||
// State machine: visible_pos s'actualitza cap a desired quan anim arriba a 0
|
||||
{
|
||||
const auto desired = Options::render_info.position;
|
||||
if (desired == info_visible_pos_) {
|
||||
// Mateix lloc: entra fins a 1
|
||||
if (info_anim_ < 1.0F) {
|
||||
info_anim_ += INFO_SLIDE_SPEED * dt;
|
||||
if (info_anim_ > 1.0F) info_anim_ = 1.0F;
|
||||
}
|
||||
} else {
|
||||
// Canvi: si visible_pos està OFF, commuta directament
|
||||
if (info_visible_pos_ == Options::RenderInfoPosition::OFF) {
|
||||
info_visible_pos_ = desired;
|
||||
info_anim_ = 0.0F;
|
||||
} else {
|
||||
// Ix del lloc actual
|
||||
info_anim_ -= INFO_SLIDE_SPEED * dt;
|
||||
if (info_anim_ <= 0.0F) {
|
||||
info_anim_ = 0.0F;
|
||||
info_visible_pos_ = desired;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Actualitza animacions individuals dels segments
|
||||
for (auto& seg : info_segments_) {
|
||||
float target = seg.visible ? 1.0F : 0.0F;
|
||||
if (seg.anim < target) {
|
||||
seg.anim += SEG_SPEED * dt;
|
||||
if (seg.anim > target) seg.anim = target;
|
||||
} else if (seg.anim > target) {
|
||||
seg.anim -= SEG_SPEED * dt;
|
||||
if (seg.anim < target) seg.anim = target;
|
||||
}
|
||||
}
|
||||
|
||||
// Render si hi ha alguna cosa visible
|
||||
if (info_visible_pos_ != Options::RenderInfoPosition::OFF && info_anim_ > 0.0F) {
|
||||
// Calcula amplada total interpolant cada segment per la seva anim
|
||||
float total_w = 0.0F;
|
||||
for (auto& seg : info_segments_) {
|
||||
if (seg.anim > 0.0F && !seg.text.empty()) {
|
||||
total_w += font_->width(seg.text.c_str()) * Easing::outQuad(seg.anim);
|
||||
}
|
||||
}
|
||||
if (total_w > 0.0F) {
|
||||
// Slide vertical (ease-out quadratic) — igual que abans
|
||||
float eased_y = Easing::outQuad(info_anim_);
|
||||
int ch = font_->charHeight();
|
||||
int final_y;
|
||||
int start_y;
|
||||
if (info_visible_pos_ == Options::RenderInfoPosition::TOP) {
|
||||
final_y = 1;
|
||||
start_y = -ch - 1;
|
||||
} else {
|
||||
final_y = SCREEN_H - ch - 1;
|
||||
start_y = SCREEN_H;
|
||||
}
|
||||
int info_y = start_y + static_cast<int>((final_y - start_y) * eased_y);
|
||||
|
||||
// Dibuixa cada segment en la seva posició x acumulada
|
||||
float cur_x = (SCREEN_W - total_w) / 2.0F;
|
||||
for (auto& seg : info_segments_) {
|
||||
if (seg.anim > 0.01F && !seg.text.empty()) {
|
||||
int xi = static_cast<int>(cur_x);
|
||||
font_->draw(pixel_data, xi + 1, info_y + 1, seg.text.c_str(), Options::render_info.shadow_color);
|
||||
font_->draw(pixel_data, xi, info_y, seg.text.c_str(), Options::render_info.text_color);
|
||||
cur_x += font_->width(seg.text.c_str()) * Easing::outQuad(seg.anim);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Elimina les acabades
|
||||
@@ -192,8 +267,16 @@ namespace Overlay {
|
||||
Options::render_info.position = static_cast<Options::RenderInfoPosition>(pos);
|
||||
}
|
||||
|
||||
void setRenderInfoText(const char* text) {
|
||||
render_info_text_ = text;
|
||||
void setRenderInfoSegments(const char* s0, const char* s1, const char* s2, const char* s3) {
|
||||
const char* segs[INFO_SEGMENT_COUNT] = {s0, s1, s2, s3};
|
||||
for (int i = 0; i < INFO_SEGMENT_COUNT; i++) {
|
||||
if (segs[i] != nullptr && *segs[i] != '\0') {
|
||||
info_segments_[i].text = segs[i];
|
||||
info_segments_[i].visible = true;
|
||||
} else {
|
||||
info_segments_[i].visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto isEscConsumed() -> bool {
|
||||
|
||||
Reference in New Issue
Block a user