#include "GTweener.h" #include "EaseManager.h" #include "GObject.h" #include "GPath.h" NS_FGUI_BEGIN USING_NS_AX; GTweener::GTweener() : _target(nullptr), _refTarget(nullptr), _userData(nullptr), _onStart(nullptr), _onUpdate(nullptr), _onComplete(nullptr), _onComplete0(nullptr), _path(nullptr) { } GTweener::~GTweener() { } GTweener* GTweener::setDelay(float value) { _delay = value; return this; } GTweener* GTweener::setDuration(float value) { _duration = value; return this; } GTweener* GTweener::setBreakpoint(float value) { _breakpoint = value; return this; } GTweener* GTweener::setEase(EaseType value) { _easeType = value; return this; } GTweener* GTweener::setEasePeriod(float value) { _easePeriod = value; return this; } GTweener* GTweener::setEaseOvershootOrAmplitude(float value) { _easeOvershootOrAmplitude = value; return this; } GTweener* GTweener::setRepeat(int repeat, bool yoyo) { _repeat = repeat; _yoyo = yoyo; return this; } GTweener* GTweener::setTimeScale(float value) { _timeScale = value; return this; } GTweener* GTweener::setSnapping(bool value) { _snapping = value; return this; } GTweener* GTweener::setTargetAny(void* value) { CC_SAFE_RELEASE(_refTarget); _refTarget = nullptr; _target = value; return this; } GTweener* GTweener::setTarget(axis::Ref* value) { return setTarget(value, TweenPropType::None); } GTweener* GTweener::setTarget(axis::Ref* target, TweenPropType propType) { CC_SAFE_RELEASE(_refTarget); _target = _refTarget = target; _propType = propType; CC_SAFE_RETAIN(_refTarget); return this; } GTweener* GTweener::setUserData(const Value& value) { _userData = value; return this; } GTweener* GTweener::setPath(GPath* path) { _path = path; return this; } GTweener* GTweener::onUpdate(GTweenCallback callback) { _onUpdate = callback; return this; } GTweener* GTweener::onStart(GTweenCallback callback) { _onStart = callback; return this; } GTweener* GTweener::onComplete(GTweenCallback0 callback) { _onComplete0 = callback; return this; } GTweener* GTweener::onComplete1(GTweenCallback callback) { _onComplete = callback; return this; } GTweener* GTweener::setPaused(bool paused) { _paused = paused; return this; } void GTweener::seek(float time) { if (_killed) return; _elapsedTime = time; if (_elapsedTime < _delay) { if (_started) _elapsedTime = _delay; else return; } update(); } void GTweener::kill(bool complete) { if (_killed) return; if (complete) { if (_ended == 0) { if (_breakpoint >= 0) _elapsedTime = _delay + _breakpoint; else if (_repeat >= 0) _elapsedTime = _delay + _duration * (_repeat + 1); else _elapsedTime = _delay + _duration * 2; update(); } callCompleteCallback(); } _killed = true; } GTweener* GTweener::_to(float start, float end, float duration) { _valueSize = 1; startValue.x = start; endValue.x = end; value.x = start; _duration = duration; return this; } GTweener* GTweener::_to(const axis::Vec2& start, const axis::Vec2& end, float duration) { _valueSize = 2; startValue.setVec2(start); endValue.setVec2(end); value.setVec2(start); _duration = duration; return this; } GTweener* GTweener::_to(const axis::Vec3& start, const axis::Vec3& end, float duration) { _valueSize = 3; startValue.setVec3(start); endValue.setVec3(end); value.setVec3(start); _duration = duration; return this; } GTweener* GTweener::_to(const axis::Vec4& start, const axis::Vec4& end, float duration) { _valueSize = 4; startValue.setVec4(start); endValue.setVec4(end); value.setVec4(start); _duration = duration; return this; } GTweener* GTweener::_to(const axis::Color4B& start, const axis::Color4B& end, float duration) { _valueSize = 4; startValue.setColor(start); endValue.setColor(end); value.setColor(start); _duration = duration; return this; } GTweener* GTweener::_to(double start, double end, float duration) { _valueSize = 5; startValue.d = start; endValue.d = end; value.d = start; _duration = duration; return this; } GTweener* GTweener::_shake(const axis::Vec2& start, float amplitude, float duration) { _valueSize = 6; startValue.setVec2(start); startValue.w = amplitude; _duration = duration; _easeType = EaseType::Linear; return this; } void GTweener::_init() { _delay = 0; _duration = 0; _breakpoint = -1; _easeType = EaseType::QuadOut; _timeScale = 1; _easePeriod = 0; _easeOvershootOrAmplitude = 1.70158f; _snapping = false; _repeat = 0; _yoyo = false; _valueSize = 0; _started = false; _paused = false; _killed = false; _elapsedTime = 0; _normalizedTime = 0; _ended = 0; startValue.setZero(); endValue.setZero(); value.setZero(); deltaValue.setZero(); } void GTweener::_reset() { CC_SAFE_RELEASE(_refTarget); _target = nullptr; _refTarget = nullptr; _userData = nullptr; _path = nullptr; _onStart = _onUpdate = _onComplete = nullptr; _onComplete0 = nullptr; } void GTweener::_update(float dt) { if (_ended != 0) //Maybe completed by seek { callCompleteCallback(); _killed = true; return; } if (_timeScale != 1) dt *= _timeScale; if (dt == 0) return; _elapsedTime += dt; update(); if (_ended != 0) { if (!_killed) { callCompleteCallback(); _killed = true; } } } void GTweener::update() { _ended = 0; if (_valueSize == 0) //DelayedCall { if (_elapsedTime >= _delay + _duration) _ended = 1; return; } if (!_started) { if (_elapsedTime < _delay) return; _started = true; callStartCallback(); if (_killed) return; } bool reversed = false; float tt = _elapsedTime - _delay; if (_breakpoint >= 0 && tt >= _breakpoint) { tt = _breakpoint; _ended = 2; } if (_repeat != 0) { int round = (int)floor(tt / _duration); tt -= _duration * round; if (_yoyo) reversed = round % 2 == 1; if (_repeat > 0 && _repeat - round < 0) { if (_yoyo) reversed = _repeat % 2 == 1; tt = _duration; _ended = 1; } } else if (tt >= _duration) { tt = _duration; _ended = 1; } _normalizedTime = EaseManager::evaluate(_easeType, reversed ? (_duration - tt) : tt, _duration, _easeOvershootOrAmplitude, _easePeriod); value.setZero(); deltaValue.setZero(); if (_valueSize == 5) { double d = startValue.d + (endValue.d - startValue.d) * _normalizedTime; if (_snapping) d = round(d); deltaValue.d = d - value.d; value.d = d; value.x = (float)d; } else if (_valueSize == 6) { if (_ended == 0) { float r = startValue.w * (1 - _normalizedTime); float rx = (rand_0_1() * 2 - 1) * r; float ry = (rand_0_1() * 2 - 1) * r; rx = rx > 0 ? ceil(rx) : floor(rx); ry = ry > 0 ? ceil(ry) : floor(ry); deltaValue.x = rx; deltaValue.y = ry; value.x = startValue.x + rx; value.y = startValue.y + ry; } else value.setVec3(startValue.getVec3()); } else if (_path != nullptr) { Vec3 vec3 = _path->getPointAt(_normalizedTime); if (_snapping) { vec3.x = round(vec3.x); vec3.y = round(vec3.y); vec3.z = round(vec3.z); } deltaValue.setVec3(vec3 - value.getVec3()); value.setVec3(vec3); } else { for (int i = 0; i < _valueSize; i++) { float n1 = startValue[i]; float n2 = endValue[i]; float f = n1 + (n2 - n1) * _normalizedTime; if (_snapping) f = round(f); deltaValue[i] = f - value[i]; value[i] = f; } value.d = value.x; } if (_refTarget != nullptr && _propType != TweenPropType::None) { GObject* gobj = dynamic_cast(_refTarget); if (gobj != nullptr) TweenPropTypeUtils::setProps(gobj, _propType, value); else { Node* node = dynamic_cast(_refTarget); if (node != nullptr) TweenPropTypeUtils::setProps(node, _propType, value); } } callUpdateCallback(); } void GTweener::callStartCallback() { if (_onStart != nullptr) _onStart(this); } void GTweener::callUpdateCallback() { if (_onUpdate != nullptr) _onUpdate(this); } void GTweener::callCompleteCallback() { if (_onComplete != nullptr) _onComplete(this); if (_onComplete0 != nullptr) _onComplete0(); } NS_FGUI_END