1 #include <rive/file.hpp>
2 #include <rive/animation/state_machine_bool.hpp>
3 #include <rive/animation/state_machine_layer.hpp>
4 #include <rive/animation/animation_state.hpp>
5 #include <rive/animation/entry_state.hpp>
6 #include <rive/animation/state_transition.hpp>
7 #include <rive/animation/state_machine_instance.hpp>
8 #include <rive/animation/state_machine_input_instance.hpp>
9 #include <rive/animation/blend_state_1d.hpp>
10 #include <rive/animation/blend_animation_1d.hpp>
11 #include <rive/animation/blend_state_direct.hpp>
12 #include <rive/animation/blend_state_transition.hpp>
14 #include "rive_file_reader.hpp"
17 TEST_CASE("file with state machine be read", "[file]") {
18 auto file = ReadRiveFile("../../test/assets/rocket.riv");
20 auto artboard = file->artboard();
21 REQUIRE(artboard != nullptr);
22 REQUIRE(artboard->animationCount() == 3);
23 REQUIRE(artboard->stateMachineCount() == 1);
25 auto stateMachine = artboard->stateMachine("Button");
26 REQUIRE(stateMachine != nullptr);
28 REQUIRE(stateMachine->layerCount() == 1);
29 REQUIRE(stateMachine->inputCount() == 2);
31 auto hover = stateMachine->input("Hover");
32 REQUIRE(hover != nullptr);
33 REQUIRE(hover->is<rive::StateMachineBool>());
35 auto press = stateMachine->input("Press");
36 REQUIRE(press != nullptr);
37 REQUIRE(press->is<rive::StateMachineBool>());
39 auto layer = stateMachine->layer(0);
40 REQUIRE(layer->stateCount() == 6);
42 REQUIRE(layer->anyState() != nullptr);
43 REQUIRE(layer->entryState() != nullptr);
44 REQUIRE(layer->exitState() != nullptr);
46 int foundAnimationStates = 0;
47 for (int i = 0; i < layer->stateCount(); i++) {
48 auto state = layer->state(i);
49 if (state->is<rive::AnimationState>()) {
50 foundAnimationStates++;
51 REQUIRE(state->as<rive::AnimationState>()->animation() != nullptr);
55 REQUIRE(foundAnimationStates == 3);
57 REQUIRE(layer->entryState()->transitionCount() == 1);
58 auto stateTo = layer->entryState()->transition(0)->stateTo();
59 REQUIRE(stateTo != nullptr);
60 REQUIRE(stateTo->is<rive::AnimationState>());
61 REQUIRE(stateTo->as<rive::AnimationState>()->animation() != nullptr);
62 REQUIRE(stateTo->as<rive::AnimationState>()->animation()->name() == "idle");
64 auto idleState = stateTo->as<rive::AnimationState>();
65 REQUIRE(idleState->transitionCount() == 2);
66 for (int i = 0; i < idleState->transitionCount(); i++) {
67 auto transition = idleState->transition(i);
68 if (transition->stateTo()->as<rive::AnimationState>()->animation()->name() == "Roll_over") {
69 // Check the condition
70 REQUIRE(transition->conditionCount() == 1);
74 auto abi = artboard->instance();
75 rive::StateMachineInstance smi(artboard->stateMachine("Button"), abi.get());
77 REQUIRE(smi.getBool("Hover")->name() == "Hover");
78 REQUIRE(smi.getBool("Press")->name() == "Press");
79 REQUIRE(smi.getBool("Hover") != nullptr);
80 REQUIRE(smi.getBool("Press") != nullptr);
81 REQUIRE(smi.stateChangedCount() == 0);
82 REQUIRE(smi.currentAnimationCount() == 0);
85 TEST_CASE("file with blend states loads correctly", "[file]") {
86 auto file = ReadRiveFile("../../test/assets/blend_test.riv");
88 auto artboard = file->artboard();
89 REQUIRE(artboard != nullptr);
90 REQUIRE(artboard->animationCount() == 4);
91 REQUIRE(artboard->stateMachineCount() == 2);
93 auto stateMachine = artboard->stateMachine("blend");
94 REQUIRE(stateMachine != nullptr);
96 REQUIRE(stateMachine->layerCount() == 1);
97 auto layer = stateMachine->layer(0);
98 REQUIRE(layer->stateCount() == 5);
100 REQUIRE(layer->anyState() != nullptr);
101 REQUIRE(layer->entryState() != nullptr);
102 REQUIRE(layer->exitState() != nullptr);
104 REQUIRE(layer->state(1)->is<rive::BlendState1D>());
105 REQUIRE(layer->state(2)->is<rive::BlendState1D>());
107 auto blendStateA = layer->state(1)->as<rive::BlendState1D>();
108 auto blendStateB = layer->state(2)->as<rive::BlendState1D>();
110 REQUIRE(blendStateA->animationCount() == 3);
111 REQUIRE(blendStateB->animationCount() == 3);
113 auto animation = blendStateA->animation(0);
114 REQUIRE(animation->is<rive::BlendAnimation1D>());
115 auto animation1D = animation->as<rive::BlendAnimation1D>();
116 REQUIRE(animation1D->animation() != nullptr);
117 REQUIRE(animation1D->animation()->name() == "horizontal");
118 REQUIRE(animation1D->value() == 0.0f);
120 animation = blendStateA->animation(1);
121 REQUIRE(animation->is<rive::BlendAnimation1D>());
122 animation1D = animation->as<rive::BlendAnimation1D>();
123 REQUIRE(animation1D->animation() != nullptr);
124 REQUIRE(animation1D->animation()->name() == "vertical");
125 REQUIRE(animation1D->value() == 100.0f);
127 animation = blendStateA->animation(2);
128 REQUIRE(animation->is<rive::BlendAnimation1D>());
129 animation1D = animation->as<rive::BlendAnimation1D>();
130 REQUIRE(animation1D->animation() != nullptr);
131 REQUIRE(animation1D->animation()->name() == "rotate");
132 REQUIRE(animation1D->value() == 0.0f);
134 REQUIRE(blendStateA->transitionCount() == 1);
135 REQUIRE(blendStateA->transition(0)->is<rive::BlendStateTransition>());
136 REQUIRE(blendStateA->transition(0)->as<rive::BlendStateTransition>()->exitBlendAnimation() !=
140 TEST_CASE("animation state with no animation doesn't crash", "[file]") {
141 auto file = ReadRiveFile("../../test/assets/multiple_state_machines.riv");
143 auto artboard = file->artboard();
144 REQUIRE(artboard != nullptr);
145 REQUIRE(artboard->animationCount() == 1);
146 REQUIRE(artboard->stateMachineCount() == 4);
148 auto stateMachine = artboard->stateMachine("two");
149 REQUIRE(stateMachine != nullptr);
151 REQUIRE(stateMachine->layerCount() == 1);
152 auto layer = stateMachine->layer(0);
153 REQUIRE(layer->stateCount() == 4);
155 REQUIRE(layer->anyState() != nullptr);
156 REQUIRE(layer->entryState() != nullptr);
157 REQUIRE(layer->exitState() != nullptr);
159 REQUIRE(layer->state(3)->is<rive::AnimationState>());
161 auto animationState = layer->state(3)->as<rive::AnimationState>();
162 REQUIRE(animationState->animation() == nullptr);
164 auto abi = artboard->instance();
165 rive::StateMachineInstance(stateMachine, abi.get()).advance(0.0f);