Implementation
bool advance(double elapsedSeconds) {
var deltaSeconds = elapsedSeconds * animation.speed * _direction;
_lastTotalTime = _totalTime;
_totalTime += deltaSeconds;
_time += deltaSeconds;
double frames = _time * animation.fps;
var start = animation.enableWorkArea ? animation.workStart : 0;
var end = animation.enableWorkArea ? animation.workEnd : animation.duration;
var range = end - start;
bool keepGoing = true;
_didLoop = false;
_spilledTime = 0;
switch (animation.loop) {
case Loop.oneShot:
if (frames > end) {
keepGoing = false;
_spilledTime = (frames - end) / animation.fps;
frames = end.toDouble();
_time = frames / animation.fps;
_didLoop = true;
}
break;
case Loop.loop:
if (frames >= end) {
_spilledTime = (frames - end) / animation.fps;
frames = _time * animation.fps;
frames = start + (frames - start) % range;
_time = frames / animation.fps;
_didLoop = true;
}
break;
case Loop.pingPong:
// ignore: literal_only_boolean_expressions
while (true) {
if (_direction == 1 && frames >= end) {
_spilledTime = (frames - end) / animation.fps;
_direction = -1;
frames = end + (end - frames);
_time = frames / animation.fps;
_didLoop = true;
} else if (_direction == -1 && frames < start) {
_spilledTime = (start - frames) / animation.fps;
_direction = 1;
frames = start + (start - frames);
_time = frames / animation.fps;
_didLoop = true;
} else {
// we're within the range, we can stop fixing. We do this in a
// loop to fix conditions when time has advanced so far that we've
// ping-ponged back and forth a few times in a single frame. We
// want to accomodate for this in cases where animations are not
// advanced on regular intervals.
break;
}
}
break;
}
return keepGoing;
}