#pragma once namespace Transitions { // Fade-out estil "mosaic dissolve": al llarg del temps els píxels del // canvas es reagrupen en blocs cada cop més grans (1×1 → max_block_size× // max_block_size). Cada bloc es pinta amb el píxel central del què // tenia abans, donant aquell aspecte chunky d'arcade. Al damunt // s'aplica un fade-to-black quadràtic (alpha = p² × 255) perquè el // resultat acabi en negre opac. // // La classe NO sap res del Screen abans de `render()`. El caller hi // crida després de pintar la seva escena: l'efecte llegeix els // píxels actuals del canvas, els rebina i escriu pixels modificats // al mateix canvas. És, per tant, un post-procés in-place. class Mosaic { public: struct Params { int max_block_size; }; explicit Mosaic(Params params); // Arrenca un fade nou. Si ja n'hi havia un actiu, el reemplaça. // `duration_ms <= 0` deixa l'efecte inactiu. void begin(int duration_ms); void tick(int delta_ms); [[nodiscard]] auto isActive() const -> bool { return duration_ms_ > 0 && elapsed_ms_ < duration_ms_; } [[nodiscard]] auto isFinished() const -> bool { return duration_ms_ > 0 && elapsed_ms_ >= duration_ms_; } [[nodiscard]] auto progress() const -> float; // Aplica el mosaic + alpha negre sobre el canvas actual de Screen. // Cridar després del render normal de l'escena, abans de // `Screen::present()`. void render() const; private: Params params_; int duration_ms_{0}; int elapsed_ms_{0}; }; } // namespace Transitions