Starting to process events in state machine instance.
diff --git a/include/rive/animation/event_bool_change.hpp b/include/rive/animation/event_bool_change.hpp
index 79d3933..61f79a2 100644
--- a/include/rive/animation/event_bool_change.hpp
+++ b/include/rive/animation/event_bool_change.hpp
@@ -1,10 +1,12 @@
#ifndef _RIVE_EVENT_BOOL_CHANGE_HPP_
#define _RIVE_EVENT_BOOL_CHANGE_HPP_
#include "rive/generated/animation/event_bool_change_base.hpp"
-#include <stdio.h>
+
namespace rive {
class EventBoolChange : public EventBoolChangeBase {
public:
+ bool validateInputType(const StateMachineInput* input) const override;
+ void perform(StateMachineInstance* stateMachineInstance) const override;
};
} // namespace rive
diff --git a/include/rive/animation/event_input_change.hpp b/include/rive/animation/event_input_change.hpp
index ee3e724..b3ae0ce 100644
--- a/include/rive/animation/event_input_change.hpp
+++ b/include/rive/animation/event_input_change.hpp
@@ -3,9 +3,13 @@
#include "rive/generated/animation/event_input_change_base.hpp"
namespace rive {
+ class StateMachineInstance;
+ class StateMachineInput;
class EventInputChange : public EventInputChangeBase {
public:
StatusCode import(ImportStack& importStack) override;
+ virtual void perform(StateMachineInstance* stateMachineInstance) const = 0;
+ virtual bool validateInputType(const StateMachineInput* input) const { return true; }
};
} // namespace rive
diff --git a/include/rive/animation/event_number_change.hpp b/include/rive/animation/event_number_change.hpp
index 27ac05f..6e123d0 100644
--- a/include/rive/animation/event_number_change.hpp
+++ b/include/rive/animation/event_number_change.hpp
@@ -1,10 +1,12 @@
#ifndef _RIVE_EVENT_NUMBER_CHANGE_HPP_
#define _RIVE_EVENT_NUMBER_CHANGE_HPP_
#include "rive/generated/animation/event_number_change_base.hpp"
-#include <stdio.h>
+
namespace rive {
class EventNumberChange : public EventNumberChangeBase {
public:
+ bool validateInputType(const StateMachineInput* input) const override;
+ void perform(StateMachineInstance* stateMachineInstance) const override;
};
} // namespace rive
diff --git a/include/rive/animation/event_trigger_change.hpp b/include/rive/animation/event_trigger_change.hpp
index b6245af..20200b5 100644
--- a/include/rive/animation/event_trigger_change.hpp
+++ b/include/rive/animation/event_trigger_change.hpp
@@ -1,10 +1,12 @@
#ifndef _RIVE_EVENT_TRIGGER_CHANGE_HPP_
#define _RIVE_EVENT_TRIGGER_CHANGE_HPP_
#include "rive/generated/animation/event_trigger_change_base.hpp"
-#include <stdio.h>
+
namespace rive {
class EventTriggerChange : public EventTriggerChangeBase {
public:
+ bool validateInputType(const StateMachineInput* input) const override;
+ void perform(StateMachineInstance* stateMachineInstance) const override;
};
} // namespace rive
diff --git a/include/rive/animation/state_machine_event.hpp b/include/rive/animation/state_machine_event.hpp
index b3d7606..ea6cb5a 100644
--- a/include/rive/animation/state_machine_event.hpp
+++ b/include/rive/animation/state_machine_event.hpp
@@ -1,21 +1,30 @@
#ifndef _RIVE_STATE_MACHINE_EVENT_HPP_
#define _RIVE_STATE_MACHINE_EVENT_HPP_
#include "rive/generated/animation/state_machine_event_base.hpp"
+#include "rive/event_type.hpp"
namespace rive {
+ class Shape;
class StateMachineEventImporter;
class EventInputChange;
+ class StateMachineInstance;
class StateMachineEvent : public StateMachineEventBase {
friend class StateMachineEventImporter;
private:
+ std::vector<uint32_t> m_HitShapesIds;
std::vector<EventInputChange*> m_InputChanges;
void addInputChange(EventInputChange* inputChange);
public:
+ EventType eventType() const { return (EventType)eventTypeValue(); }
size_t inputChangeCount() const { return m_InputChanges.size(); }
const EventInputChange* inputChange(size_t index) const;
StatusCode import(ImportStack& importStack) override;
+ StatusCode onAddedClean(CoreContext* context) override;
+
+ const std::vector<uint32_t>& hitShapeIds() const { return m_HitShapesIds; }
+ void performChanges(StateMachineInstance* stateMachineInstance) const;
};
} // namespace rive
diff --git a/include/rive/animation/state_machine_instance.hpp b/include/rive/animation/state_machine_instance.hpp
index 2226ef9..b995265 100644
--- a/include/rive/animation/state_machine_instance.hpp
+++ b/include/rive/animation/state_machine_instance.hpp
@@ -3,7 +3,9 @@
#include <string>
#include <stddef.h>
+#include <vector>
#include "rive/animation/linear_animation_instance.hpp"
+#include "rive/event_type.hpp"
namespace rive {
class StateMachine;
@@ -13,8 +15,9 @@
class SMIBool;
class SMINumber;
class SMITrigger;
-
+ class Shape;
class StateMachineLayerInstance;
+ class HitShape;
class StateMachineInstance {
friend class SMIInput;
@@ -31,6 +34,9 @@
void markNeedsAdvance();
+ std::vector<HitShape*> m_HitShapes;
+ void processEvent(Vec2D position, EventType hitEvent);
+
public:
StateMachineInstance(const StateMachine* machine, ArtboardInstance* instance);
~StateMachineInstance();
diff --git a/include/rive/artboard.hpp b/include/rive/artboard.hpp
index ad19de3..297cedb 100644
--- a/include/rive/artboard.hpp
+++ b/include/rive/artboard.hpp
@@ -67,6 +67,7 @@
StatusCode initialize();
Core* resolve(uint32_t id) const override;
+ uint32_t idOf(Core* object) const;
// EXPERIMENTAL -- for internal testing only for now.
// DO NOT RELY ON THIS as it may change/disappear in the future.
@@ -88,7 +89,7 @@
// Returns true iff calling popMessage() will return true.
bool hasMessages() const;
-
+
// If there are any queued messages...
// copies the first message into msg parameter
// removes that message from the queue
@@ -138,6 +139,16 @@
StateMachine* stateMachine(std::string name) const;
StateMachine* stateMachine(size_t index) const;
+ /// Make an instance of a state machine given the name of the source state machine in this
+ /// artboard. The StateMachineInstance must be explictly deleted when no longer needed.
+ StateMachineInstance* stateMachineInstance(std::string name);
+
+ /// Make an instance of a state machine given the index of the source state machine in this
+ /// artboard. The StateMachineInstance must be explictly deleted when no longer needed.
+ StateMachineInstance* stateMachineInstance(size_t index);
+
+ size_t stateMachineCount() const { return m_StateMachines.size(); }
+
/// Make an instance of this artboard, must be explictly deleted when no
/// longer needed.
// Deprecated...
diff --git a/include/rive/event_type.hpp b/include/rive/event_type.hpp
new file mode 100644
index 0000000..d50df00
--- /dev/null
+++ b/include/rive/event_type.hpp
@@ -0,0 +1,11 @@
+#ifndef _RIVE_EVENT_TYPE_HPP_
+#define _RIVE_EVENT_TYPE_HPP_
+namespace rive {
+ enum class EventType : unsigned int {
+ enter = 0,
+ exit = 1,
+ down = 2,
+ up = 3,
+ };
+}
+#endif
\ No newline at end of file
diff --git a/include/rive/generated/animation/event_input_change_base.hpp b/include/rive/generated/animation/event_input_change_base.hpp
index 61f30d1..7212efb 100644
--- a/include/rive/generated/animation/event_input_change_base.hpp
+++ b/include/rive/generated/animation/event_input_change_base.hpp
@@ -26,11 +26,11 @@
static const uint16_t inputIdPropertyKey = 227;
private:
- int m_InputId = -1;
+ uint32_t m_InputId = -1;
public:
- inline int inputId() const { return m_InputId; }
- void inputId(int value) {
+ inline uint32_t inputId() const { return m_InputId; }
+ void inputId(uint32_t value) {
if (m_InputId == value) {
return;
}
diff --git a/include/rive/generated/animation/state_machine_event_base.hpp b/include/rive/generated/animation/state_machine_event_base.hpp
index 2aa9f01..a67e39c 100644
--- a/include/rive/generated/animation/state_machine_event_base.hpp
+++ b/include/rive/generated/animation/state_machine_event_base.hpp
@@ -28,12 +28,12 @@
static const uint16_t eventTypeValuePropertyKey = 225;
private:
- int m_TargetId = 0;
- int m_EventTypeValue = 0;
+ uint32_t m_TargetId = 0;
+ uint32_t m_EventTypeValue = 0;
public:
- inline int targetId() const { return m_TargetId; }
- void targetId(int value) {
+ inline uint32_t targetId() const { return m_TargetId; }
+ void targetId(uint32_t value) {
if (m_TargetId == value) {
return;
}
@@ -41,8 +41,8 @@
targetIdChanged();
}
- inline int eventTypeValue() const { return m_EventTypeValue; }
- void eventTypeValue(int value) {
+ inline uint32_t eventTypeValue() const { return m_EventTypeValue; }
+ void eventTypeValue(uint32_t value) {
if (m_EventTypeValue == value) {
return;
}
diff --git a/src/animation/event_bool_change.cpp b/src/animation/event_bool_change.cpp
new file mode 100644
index 0000000..946f15a
--- /dev/null
+++ b/src/animation/event_bool_change.cpp
@@ -0,0 +1,22 @@
+#include "rive/animation/event_bool_change.hpp"
+#include "rive/animation/state_machine_instance.hpp"
+#include "rive/animation/state_machine_bool.hpp"
+#include "rive/animation/state_machine_input_instance.hpp"
+using namespace rive;
+
+bool EventBoolChange::validateInputType(const StateMachineInput* input) const {
+ // A null input is valid as the StateMachine can attempt to limp along if we
+ // introduce new input types that old conditions are expected to handle in
+ // newer runtimes. The older runtimes will just evaluate them to true.
+ return input == nullptr || input->is<StateMachineBool>();
+}
+
+void EventBoolChange::perform(StateMachineInstance* stateMachineInstance) const {
+ auto inputInstance = stateMachineInstance->input(inputId());
+ if (inputInstance == nullptr) {
+ return;
+ }
+ // If it's not null, it must be our correct type (why we validate at load time).
+ auto boolInput = reinterpret_cast<SMIBool*>(inputInstance);
+ boolInput->value(value());
+}
\ No newline at end of file
diff --git a/src/animation/event_input_change.cpp b/src/animation/event_input_change.cpp
index d319855..7914ae3 100644
--- a/src/animation/event_input_change.cpp
+++ b/src/animation/event_input_change.cpp
@@ -1,17 +1,27 @@
#include "rive/animation/state_machine_event.hpp"
#include "rive/importers/import_stack.hpp"
#include "rive/importers/state_machine_event_importer.hpp"
+#include "rive/importers/state_machine_importer.hpp"
#include "rive/animation/event_input_change.hpp"
-#include "rive/generated/animation/state_machine_base.hpp"
+#include "rive/animation/state_machine.hpp"
using namespace rive;
StatusCode EventInputChange::import(ImportStack& importStack) {
+ auto stateMachineImporter = importStack.latest<StateMachineImporter>(StateMachine::typeKey);
+ if (stateMachineImporter == nullptr) {
+ return StatusCode::MissingObject;
+ }
+
auto stateMachineEventImporter =
importStack.latest<StateMachineEventImporter>(StateMachineEventBase::typeKey);
if (stateMachineEventImporter == nullptr) {
return StatusCode::MissingObject;
}
+
+ if (!validateInputType(stateMachineImporter->stateMachine()->input((size_t)inputId()))) {
+ return StatusCode::InvalidObject;
+ }
stateMachineEventImporter->addInputChange(this);
return Super::import(importStack);
}
diff --git a/src/animation/event_number_change.cpp b/src/animation/event_number_change.cpp
new file mode 100644
index 0000000..a97d306
--- /dev/null
+++ b/src/animation/event_number_change.cpp
@@ -0,0 +1,23 @@
+#include "rive/animation/event_number_change.hpp"
+#include "rive/animation/state_machine_instance.hpp"
+#include "rive/animation/state_machine_number.hpp"
+#include "rive/animation/state_machine_input_instance.hpp"
+
+using namespace rive;
+
+bool EventNumberChange::validateInputType(const StateMachineInput* input) const {
+ // A null input is valid as the StateMachine can attempt to limp along if we
+ // introduce new input types that old conditions are expected to handle in
+ // newer runtimes. The older runtimes will just evaluate them to true.
+ return input == nullptr || input->is<StateMachineNumber>();
+}
+
+void EventNumberChange::perform(StateMachineInstance* stateMachineInstance) const {
+ auto inputInstance = stateMachineInstance->input(inputId());
+ if (inputInstance == nullptr) {
+ return;
+ }
+ // If it's not null, it must be our correct type (why we validate at load time).
+ auto numberInput = reinterpret_cast<SMINumber*>(inputInstance);
+ numberInput->value(value());
+}
diff --git a/src/animation/event_trigger_change.cpp b/src/animation/event_trigger_change.cpp
new file mode 100644
index 0000000..e2b8d9d
--- /dev/null
+++ b/src/animation/event_trigger_change.cpp
@@ -0,0 +1,23 @@
+#include "rive/animation/event_trigger_change.hpp"
+#include "rive/animation/state_machine_instance.hpp"
+#include "rive/animation/state_machine_trigger.hpp"
+#include "rive/animation/state_machine_input_instance.hpp"
+
+using namespace rive;
+
+bool EventTriggerChange::validateInputType(const StateMachineInput* input) const {
+ // A null input is valid as the StateMachine can attempt to limp along if we
+ // introduce new input types that old conditions are expected to handle in
+ // newer runtimes. The older runtimes will just evaluate them to true.
+ return input == nullptr || input->is<StateMachineTrigger>();
+}
+
+void EventTriggerChange::perform(StateMachineInstance* stateMachineInstance) const {
+ auto inputInstance = stateMachineInstance->input(inputId());
+ if (inputInstance == nullptr) {
+ return;
+ }
+ // If it's not null, it must be our correct type (why we validate at load time).
+ auto triggerInput = reinterpret_cast<SMITrigger*>(inputInstance);
+ triggerInput->fire();
+}
\ No newline at end of file
diff --git a/src/animation/state_machine_event.cpp b/src/animation/state_machine_event.cpp
index d6791b3..fd367ed 100644
--- a/src/animation/state_machine_event.cpp
+++ b/src/animation/state_machine_event.cpp
@@ -2,6 +2,10 @@
#include "rive/importers/import_stack.hpp"
#include "rive/importers/state_machine_importer.hpp"
#include "rive/generated/animation/state_machine_base.hpp"
+#include "rive/artboard.hpp"
+#include "rive/shapes/shape.hpp"
+#include "rive/animation/state_machine_instance.hpp"
+#include "rive/animation/event_input_change.hpp"
using namespace rive;
@@ -23,4 +27,34 @@
return m_InputChanges[index];
}
return nullptr;
+}
+
+StatusCode StateMachineEvent::onAddedClean(CoreContext* context) {
+ auto artboard = static_cast<Artboard*>(context);
+ for (auto core : artboard->objects()) {
+ if (core == nullptr) {
+ continue;
+ }
+ auto target = artboard->resolve(targetId());
+
+ // Iterate artboard to find Shapes that are parented to the target
+ if (core->is<Shape>()) {
+ auto shape = core->as<Shape>();
+ for (ContainerComponent* component = shape; component != nullptr;
+ component = component->parent()) {
+ if (component == target) {
+ m_HitShapesIds.push_back(artboard->idOf(shape));
+ break;
+ }
+ }
+ }
+ }
+
+ return Super::onAddedClean(context);
+}
+
+void StateMachineEvent::performChanges(StateMachineInstance* stateMachineInstance) const {
+ for (auto inputChange : m_InputChanges) {
+ inputChange->perform(stateMachineInstance);
+ }
}
\ No newline at end of file
diff --git a/src/animation/state_machine_instance.cpp b/src/animation/state_machine_instance.cpp
index b5bfa84..1129c4f 100644
--- a/src/animation/state_machine_instance.cpp
+++ b/src/animation/state_machine_instance.cpp
@@ -13,6 +13,10 @@
#include "rive/animation/animation_state.hpp"
#include "rive/animation/state_instance.hpp"
#include "rive/animation/animation_state_instance.hpp"
+#include "rive/animation/state_machine_event.hpp"
+#include "rive/shapes/shape.hpp"
+#include "rive/math/aabb.hpp"
+#include <unordered_map>
using namespace rive;
namespace rive {
@@ -69,7 +73,7 @@
}
}
- bool advance(/*Artboard* artboard, */float seconds, SMIInput** inputs, size_t inputCount) {
+ bool advance(/*Artboard* artboard, */ float seconds, SMIInput** inputs, size_t inputCount) {
m_StateChangedOnAdvance = false;
if (m_CurrentState != nullptr) {
@@ -124,7 +128,8 @@
if ((m_CurrentState == nullptr ? nullptr : m_CurrentState->state()) == stateTo) {
return false;
}
- m_CurrentState = stateTo == nullptr ? nullptr : stateTo->makeInstance(m_ArtboardInstance).release();
+ m_CurrentState =
+ stateTo == nullptr ? nullptr : stateTo->makeInstance(m_ArtboardInstance).release();
return true;
}
@@ -213,12 +218,62 @@
return static_cast<AnimationStateInstance*>(m_CurrentState)->animationInstance();
}
};
+
+ /// Representation of a Shape from the Artboard Instance and all the events it
+ /// triggers. Allows tracking hover and performing hit detection only once on
+ /// shapes that trigger multiple events.
+ class HitShape {
+ private:
+ Shape* m_Shape;
+
+ public:
+ Shape* shape() const { return m_Shape; }
+ HitShape(Shape* shape) : m_Shape(shape) {}
+ bool isHovered = false;
+ std::vector<const StateMachineEvent*> events;
+ };
} // namespace rive
-StateMachineInstance::StateMachineInstance(const StateMachine* machine, ArtboardInstance* instance)
- : m_Machine(machine)
- , m_ArtboardInstance(instance)
-{
+void StateMachineInstance::processEvent(Vec2D position, EventType hitEvent) {
+ const int hitRadius = 2;
+ auto hitArea = AABB(position.x() - hitRadius,
+ position.y() - hitRadius,
+ position.x() + hitRadius,
+ position.y() + hitRadius)
+ .round();
+ for (auto hitShape : m_HitShapes) {
+
+ // TODO: quick reject.
+
+ // TODO: hit test
+ bool isOver = false;
+
+ bool hoverChange = hitShape->isHovered != isOver;
+ hitShape->isHovered = isOver;
+ // iterate all events associated with this hit shape
+ for (auto event : hitShape->events) {
+ // Always update hover states regardless of which specific event type
+ // we're trying to trigger.
+ if (hoverChange) {
+ if (isOver && event->eventType() == EventType::enter) {
+ event->performChanges(this);
+ markNeedsAdvance();
+ } else if (!isOver && event->eventType() == EventType::exit) {
+ event->performChanges(this);
+ markNeedsAdvance();
+ }
+ }
+ if (isOver && hitEvent == event->eventType()) {
+ event->performChanges(this);
+ markNeedsAdvance();
+ }
+ }
+ }
+}
+
+StateMachineInstance::StateMachineInstance(const StateMachine* machine,
+ ArtboardInstance* instance) :
+ m_Machine(machine), m_ArtboardInstance(instance) {
assert(instance->isInstance());
m_InputCount = machine->inputCount();
m_InputInstances = new SMIInput*[m_InputCount];
@@ -250,9 +305,40 @@
for (size_t i = 0; i < m_LayerCount; i++) {
m_Layers[i].init(machine->layer(i), m_ArtboardInstance);
}
+
+ // Initialize events. Store a lookup table of shape id to hit shape
+ // representation (an object that stores all the events triggered by the
+ // shape producing an event).
+ std::unordered_map<uint32_t, HitShape*> hitShapeLookup;
+ for (std::size_t i = 0; i < machine->eventCount(); i++) {
+ auto event = machine->event(i);
+
+ // Iterate actual leaf hittable shapes tied to this event and resolve
+ // corresponding ones in the artboard instance.
+ for (auto id : event->hitShapeIds()) {
+ HitShape* hitShape;
+ auto itr = hitShapeLookup.find(id);
+ if (itr == hitShapeLookup.end()) {
+ auto shape = artboard->resolve(id);
+ if (shape != nullptr && shape->is<Shape>()) {
+ hitShapeLookup[id] = hitShape = new HitShape(shape->as<Shape>());
+ m_HitShapes.push_back(hitShape);
+ } else {
+ // No object or not a shape...
+ continue;
+ }
+ } else {
+ hitShape = itr->second;
+ }
+ hitShape->events.push_back(event);
+ }
+ }
}
StateMachineInstance::~StateMachineInstance() {
+ for (auto hitShape : m_HitShapes) {
+ delete hitShape;
+ }
// TODO: can this and others be rewritten as for (auto inst : m_InputInstances) ?
for (size_t i = 0; i < m_InputCount; i++) {
delete m_InputInstances[i];
@@ -279,9 +365,7 @@
void StateMachineInstance::markNeedsAdvance() { m_NeedsAdvance = true; }
bool StateMachineInstance::needsAdvance() const { return m_NeedsAdvance; }
-std::string StateMachineInstance::name() const {
- return m_Machine->name();
-}
+std::string StateMachineInstance::name() const { return m_Machine->name(); }
SMIInput* StateMachineInstance::input(size_t index) const {
if (index < m_InputCount) {
diff --git a/src/artboard.cpp b/src/artboard.cpp
index 940b835..b52587f 100644
--- a/src/artboard.cpp
+++ b/src/artboard.cpp
@@ -14,6 +14,7 @@
#include "rive/importers/import_stack.hpp"
#include "rive/importers/backboard_importer.hpp"
#include "rive/nested_artboard.hpp"
+#include "rive/animation/state_machine_instance.hpp"
#include <stack>
#include <unordered_map>
@@ -287,6 +288,8 @@
return m_Objects[id];
}
+uint32_t Artboard::idOf(Core* object) const { return 0; }
+
void Artboard::onComponentDirty(Component* component) {
m_Dirt |= ComponentDirt::Components;
@@ -506,6 +509,22 @@
return m_StateMachines[index];
}
+StateMachineInstance* Artboard::stateMachineInstance(std::string name) {
+ StateMachine* machine = stateMachine(name);
+ if (machine != nullptr) {
+ return new StateMachineInstance(machine, this);
+ }
+ return nullptr;
+}
+
+StateMachineInstance* Artboard::stateMachineInstance(size_t index) {
+ StateMachine* machine = stateMachine(index);
+ if (machine != nullptr) {
+ return new StateMachineInstance(machine, this);
+ }
+ return nullptr;
+}
+
std::unique_ptr<ArtboardInstance> Artboard::instance() const {
std::unique_ptr<ArtboardInstance> artboardClone(new ArtboardInstance);
artboardClone->copy(*this);
@@ -577,7 +596,8 @@
assert(gButtonIsDown);
gButtonIsDown = false;
break;
- default: break;
+ default:
+ break;
}
#if 0
@@ -603,13 +623,9 @@
#endif
}
-void Artboard::testing_only_enque_message(const Message& msg) {
- m_MessageQueue.push(msg);
-}
+void Artboard::testing_only_enque_message(const Message& msg) { m_MessageQueue.push(msg); }
-bool Artboard::hasMessages() const {
- return !m_MessageQueue.empty();
-}
+bool Artboard::hasMessages() const { return !m_MessageQueue.empty(); }
bool Artboard::nextMessage(Message* msg) {
if (m_MessageQueue.empty()) {
@@ -626,26 +642,22 @@
#include "rive/animation/linear_animation_instance.hpp"
#include "rive/animation/state_machine_instance.hpp"
-std::unique_ptr<LinearAnimationInstance>
-ArtboardInstance::animationAt(size_t index) {
+std::unique_ptr<LinearAnimationInstance> ArtboardInstance::animationAt(size_t index) {
auto la = this->animation(index);
return la ? std::make_unique<LinearAnimationInstance>(la, this) : nullptr;
}
-std::unique_ptr<LinearAnimationInstance>
-ArtboardInstance::animationNamed(std::string name) {
+std::unique_ptr<LinearAnimationInstance> ArtboardInstance::animationNamed(std::string name) {
auto la = this->animation(name);
return la ? std::make_unique<LinearAnimationInstance>(la, this) : nullptr;
}
-std::unique_ptr<StateMachineInstance>
-ArtboardInstance::stateMachineAt(size_t index) {
+std::unique_ptr<StateMachineInstance> ArtboardInstance::stateMachineAt(size_t index) {
auto sm = this->stateMachine(index);
return sm ? std::make_unique<StateMachineInstance>(sm, this) : nullptr;
}
-std::unique_ptr<StateMachineInstance>
-ArtboardInstance::stateMachineNamed(std::string name) {
+std::unique_ptr<StateMachineInstance> ArtboardInstance::stateMachineNamed(std::string name) {
auto sm = this->stateMachine(name);
return sm ? std::make_unique<StateMachineInstance>(sm, this) : nullptr;
}
diff --git a/test/state_machine_test.cpp b/test/state_machine_test.cpp
index b4b0f97..3424c5f 100644
--- a/test/state_machine_test.cpp
+++ b/test/state_machine_test.cpp
@@ -73,6 +73,7 @@
auto abi = artboard->instance();
rive::StateMachineInstance smi(artboard->stateMachine("Button"), abi.get());
+
REQUIRE(smi.getBool("Hover")->name() == "Hover");
REQUIRE(smi.getBool("Press")->name() == "Press");
REQUIRE(smi.getBool("Hover") != nullptr);