early out of advance if we are not going to keep goign

attached a file that is relevant to this issue.

this is a possible solution to the problem. basically early out of our advance, if we have already established that we are not going to keep going. this is to prevent accumulating more spilled time.

another approach might be to put the keep going check into the animationStateInstance, but then the animation state instance will have to track total time, maybe that makes more sense though than total time being tracked in the linear animation instance.

todo if this fix is acceptable:

- [x] add a golden test for this.
- [x] run generators for flutter runtime.
- [x] apply to cpp runtime.

[spilled_time.riv.zip](https://github.com/rive-app/rive/files/12381784/spilled_time.riv.zip)

https://github.com/rive-app/rive/assets/1216025/7afc5d4d-e9cf-4546-941c-947adf2d454b

Diffs=
2719b1463 early out of advance if we are not going to keep goign (#5849)

Co-authored-by: Maxwell Talbot <talbot.maxwell@gmail.com>
diff --git a/.rive_head b/.rive_head
index 06a46dd..373b6de 100644
--- a/.rive_head
+++ b/.rive_head
@@ -1 +1 @@
-a91b1b7647965149bd1b7894fa428f189e57f653
+2719b146328ddd2136232d0756ad59f3d0facc2d
diff --git a/include/rive/animation/linear_animation_instance.hpp b/include/rive/animation/linear_animation_instance.hpp
index 1b7c91d..36656d5 100644
--- a/include/rive/animation/linear_animation_instance.hpp
+++ b/include/rive/animation/linear_animation_instance.hpp
@@ -59,7 +59,9 @@
 
     bool keepGoing() const
     {
-        return m_loopValue != static_cast<int>(rive::Loop::oneShot) || !m_didLoop;
+        return this->loopValue() != static_cast<int>(rive::Loop::oneShot) ||
+               (m_direction > 0 && m_time < m_animation->durationSeconds()) ||
+               (m_direction < 0 && m_time > 0);
     }
 
     float totalTime() const { return m_totalTime; }
diff --git a/src/animation/linear_animation_instance.cpp b/src/animation/linear_animation_instance.cpp
index ac527f8..7be5d6a 100644
--- a/src/animation/linear_animation_instance.cpp
+++ b/src/animation/linear_animation_instance.cpp
@@ -52,30 +52,30 @@
 {
     const LinearAnimation& animation = *m_animation;
     float deltaSeconds = elapsedSeconds * animation.speed() * m_direction;
+    m_spilledTime = 0.0f;
     if (deltaSeconds == 0)
     {
-        // we say keep going, if you advance by 0.
-        // could argue that any further advances by 0 result in nothing so you should not keep going
-        // could argue its saying, we are not at the end of the animation yet, so keep going
-        // our runtimes currently expect the latter, so we say keep going!
         m_didLoop = false;
         return true;
     }
 
     m_lastTotalTime = m_totalTime;
     m_totalTime += std::abs(deltaSeconds);
+
+    // NOTE:
+    // do not track spilled time, if our one shot loop is already completed.
+    // stop gap before we move spilled tracking into state machine logic.
+    bool killSpilledTime = !this->keepGoing();
+
     m_time += deltaSeconds;
 
     int fps = animation.fps();
     float frames = m_time * fps;
-
     int start = animation.enableWorkArea() ? animation.workStart() : 0;
     int end = animation.enableWorkArea() ? animation.workEnd() : animation.duration();
     int range = end - start;
 
-    bool keepGoing = true;
     bool didLoop = false;
-    m_spilledTime = 0.0f;
 
     // this has some issues when deltaSeconds is 0,
     // right now we basically assume we default to going forwards in that case
@@ -86,7 +86,6 @@
         case Loop::oneShot:
             if (direction == 1 && frames > end)
             {
-                keepGoing = false;
                 m_spilledTime = (frames - end) / fps;
                 frames = (float)end;
                 m_time = frames / fps;
@@ -94,7 +93,6 @@
             }
             else if (direction == -1 && frames < start)
             {
-                keepGoing = false;
                 m_spilledTime = (start - frames) / fps;
                 frames = (float)start;
                 m_time = frames / fps;
@@ -107,7 +105,6 @@
                 m_spilledTime = (frames - end) / fps;
                 frames = m_time * fps;
                 frames = start + std::fmod(frames - start, (float)range);
-
                 m_time = frames / fps;
                 didLoop = true;
             }
@@ -150,8 +147,13 @@
             break;
     }
 
+    if (killSpilledTime)
+    {
+        m_spilledTime = 0;
+    }
+
     m_didLoop = didLoop;
-    return keepGoing;
+    return this->keepGoing();
 }
 
 void LinearAnimationInstance::time(float value)
diff --git a/src/animation/state_machine_instance.cpp b/src/animation/state_machine_instance.cpp
index 1993115..cc6c649 100644
--- a/src/animation/state_machine_instance.cpp
+++ b/src/animation/state_machine_instance.cpp
@@ -72,12 +72,7 @@
     bool advance(float seconds, Span<SMIInput*> inputs)
     {
         m_stateMachineChangedOnAdvance = false;
-
-        if (m_currentState != nullptr && m_currentState->keepGoing())
-        {
-            m_currentState->advance(seconds, inputs);
-        }
-
+        m_currentState->advance(seconds, inputs);
         updateMix(seconds);
 
         if (m_stateFrom != nullptr && m_mix < 1.0f && !m_holdAnimationFrom)