apply current state update before changing states

Once a transition completes, we update the state without applying the advance to the currentState of the transition.
This PR checks whether a transition is complete to invoke apply to the complete state before moving to the next state.
Note: It could happen that the next state is actually the same one completed in the transition, so apply would be called twice on the same state.
Conceptually it makes sense to treat it as two different things, since one is in the context of the transition and the other "apply" is in the context of the new state. But in terms of performance, this might not be the best solution.

Diffs=
da14cc814 apply current state update before changing states (#6538)

Co-authored-by: hernan <hernan@rive.app>
diff --git a/.rive_head b/.rive_head
index 55fcd07..f4de6df 100644
--- a/.rive_head
+++ b/.rive_head
@@ -1 +1 @@
-ac0d97c1243ea3c2e473a319f4eb100fed52e1d5
+da14cc81429ab78081030ec824f0796985af968d
diff --git a/src/animation/state_machine_instance.cpp b/src/animation/state_machine_instance.cpp
index 9c810cc..3ba76eb 100644
--- a/src/animation/state_machine_instance.cpp
+++ b/src/animation/state_machine_instance.cpp
@@ -82,6 +82,11 @@
             m_stateFrom->advance(seconds, m_stateMachineInstance);
         }
 
+        if (isTransitionEnded())
+        {
+            apply();
+        }
+
         for (int i = 0; updateState(i != 0); i++)
         {
             apply();
@@ -107,6 +112,12 @@
                m_mix < 1.0f;
     }
 
+    bool isTransitionEnded()
+    {
+        return m_transition != nullptr && m_stateFrom != nullptr && m_transition->duration() != 0 &&
+               m_mix == 1.0f;
+    }
+
     bool updateState(bool ignoreTriggers)
     {
         // Don't allow changing state while a transition is taking place
diff --git a/test/assets/state_machine_transition.riv b/test/assets/state_machine_transition.riv
new file mode 100644
index 0000000..58fbd62
--- /dev/null
+++ b/test/assets/state_machine_transition.riv
Binary files differ
diff --git a/test/state_machine_test.cpp b/test/state_machine_test.cpp
index 7ebd3a0..e3dd9cf 100644
--- a/test/state_machine_test.cpp
+++ b/test/state_machine_test.cpp
@@ -10,6 +10,9 @@
 #include <rive/animation/blend_animation_1d.hpp>
 #include <rive/animation/blend_state_direct.hpp>
 #include <rive/animation/blend_state_transition.hpp>
+#include <rive/shapes/paint/solid_color.hpp>
+#include <rive/shapes/paint/stroke.hpp>
+#include <rive/shapes/shape.hpp>
 #include "catch.hpp"
 #include "rive_file_reader.hpp"
 #include <cstdio>
@@ -197,3 +200,45 @@
 
     delete stateMachineInstance;
 }
+
+TEST_CASE("Transitions with duration completes the state correctly before changing states",
+          "[file]")
+{
+    auto file = ReadRiveFile("../../test/assets/state_machine_transition.riv");
+    auto black_color = 0xFF000000;
+    auto white_color = 0xFFFFFFFF;
+
+    auto artboard = file->artboard();
+    auto stateMachine = artboard->stateMachine("State-Machine-Test");
+
+    REQUIRE(artboard != nullptr);
+    REQUIRE(artboard->animationCount() == 3);
+    REQUIRE(artboard->stateMachineCount() == 1);
+
+    REQUIRE(stateMachine->layerCount() == 1);
+    auto layer = stateMachine->layer(0);
+    REQUIRE(layer->stateCount() == 6);
+
+    auto abi = artboard->instance();
+    REQUIRE(abi->children()[0]->is<rive::Shape>());
+    REQUIRE(abi->children()[0]->name() == "Star-Stroke");
+    auto shape = abi->children()[0]->as<rive::Shape>();
+    REQUIRE(shape->children()[1]->is<rive::Stroke>());
+    auto stroke = shape->children()[1]->as<rive::Stroke>();
+    REQUIRE(stroke->paint()->is<rive::SolidColor>());
+    auto solidColor = stroke->paint()->as<rive::SolidColor>();
+    // Before the transition, the color has to be full black
+    REQUIRE(solidColor->colorValue() == black_color);
+    rive::StateMachineInstance* stateMachineInstance =
+        new rive::StateMachineInstance(stateMachine, abi.get());
+    stateMachineInstance->advanceAndApply(0.1f);
+    abi->advance(0.1f);
+    REQUIRE(stateMachineInstance->currentAnimationByIndex(0)->name() == "State-2");
+    // After the transition has passed, the color has to be full white.
+    stateMachineInstance->advanceAndApply(2.0f);
+    abi->advance(2.0f);
+    REQUIRE(stateMachineInstance->currentAnimationByIndex(0)->name() == "State-3");
+    REQUIRE(solidColor->colorValue() == white_color);
+
+    delete stateMachineInstance;
+}