diff --git a/Tween.h b/Tween.h index 4b2e2bb..d7f2a03 100644 --- a/Tween.h +++ b/Tween.h @@ -1,6 +1,30 @@ #pragma once #include "Easing.h" +#include "TimeWarp.h" +namespace EasingFunc { + + // typedef float (*eFunc)(float); // тип easing-функции, как у Вас + + // Статические данные для обёртки + static const TimeWarp* g_warp = nullptr; + static eFunc g_baseEasing = nullptr; + + // Обёртка с модификатором времени (вызывается Tween'ом) + inline float _easingWithWarp(float t) { + if (!g_warp || !g_baseEasing) return t; + float warpedT = g_warp->apply(t); + return g_baseEasing(warpedT); + } + + // Установить текущий модификатор времени + inline eFunc withTimeWarp(eFunc easing, const TimeWarp& warp) { + g_warp = &warp; + g_baseEasing = easing; + return _easingWithWarp; + } + +}; // namespace EasingFunc class Tween { private: @@ -10,7 +34,7 @@ private: Tween* next; public: - Tween(uint16_t fps) { + Tween(uint16_t fps = 30) { setFps(fps); if (Tween::head == nullptr) { Tween::head = this; @@ -42,7 +66,7 @@ private: EasingFunc::eFunc easing = nullptr; float progress; bool isPlayingF; - bool isLastPlay; + bool triggerLastTick = false; // Флаг последнего тика public: float current; @@ -55,38 +79,54 @@ public: void update() { if (millis() - frameRateTimer > frameTime) { - dtTick(); - if (!isPlayingF || easing == nullptr) return; - if(!isLastPlay){ - if (/* ((uint16_t)current) == ((uint16_t)to) || */ progress > duration) { - current = to; - isLastPlay = true; - return; + uint32_t now = millis(); + dt = (now - oldMillis) / 1000.0; + oldMillis = now; + + if (!isPlayingF && triggerLastTick) { + triggerLastTick = false; + current = to; + return; } - current = clamp(Tween::lerp(from, to, easing(progress / duration)), from, to); - progress = progress + Tween::dt; - } else { - stop(); - } - frameRateTimer = millis(); + + if (!isPlayingF || easing == nullptr) return; + + progress = constrain(progress + dt, 0, duration); + float normProgress = constrain(progress / duration, 0, 1); + + current = Tween::lerp(from, to, easing(normProgress)); + + if (progress >= duration) { + current = to; + triggerLastTick = true; + isPlayingF = false; + } + + frameRateTimer = millis(); } } float getProgress() { - return clamp(progress / duration, 0, 1); + return constrain(progress / duration, 0, 1); } void start(float from, float to, uint16_t duration, EasingFunc::eFunc easing) { current = from; - if (from == to) { return; } + if (from == to) { + current = to; + isPlayingF = false; + triggerLastTick = true; + return; + } + this->from = from; this->to = to; this->duration = duration / 1000.0; this->easing = easing; - - resetToStart(); - dtTick(); + progress = 0; + oldMillis = millis(); isPlayingF = true; + triggerLastTick = false; } void resetToStart() { @@ -94,11 +134,12 @@ public: } void stop() { isPlayingF = false; - isLastPlay = false; + current = to; + triggerLastTick = true; } bool isPlaying() const { - return isPlayingF; + return isPlayingF || triggerLastTick; // Учитываем последний тик } void setFps(uint16_t fps){ @@ -127,14 +168,14 @@ public: } private: - int clamp(int value, int a, int b) { - if (a > b) { - a ^= b; - b ^= a; - a ^= b; - } - if (value < a) return a; - else if (value > b) return b; - else return value; - } + // int clamp(int value, int a, int b) { + // if (a > b) { + // a ^= b; + // b ^= a; + // a ^= b; + // } + // if (value < a) return a; + // else if (value > b) return b; + // else return value; + // } }; \ No newline at end of file