feature: add support for firing triggers on state transitions (#10329) cc34f96631 * feature: add support for fiiring triggers on state transitions Co-authored-by: hernan <hernan@rive.app>
diff --git a/.rive_head b/.rive_head index 76045c1..4216257 100644 --- a/.rive_head +++ b/.rive_head
@@ -1 +1 @@ -64f828c9a278586f61b7636da99d68404c906176 +cc34f96631a6279e94227c10862cdde8ebf6b478
diff --git a/dev/defs/animation/state_machine_fire_action.json b/dev/defs/animation/state_machine_fire_action.json new file mode 100644 index 0000000..4dc81dc --- /dev/null +++ b/dev/defs/animation/state_machine_fire_action.json
@@ -0,0 +1,39 @@ +{ + "name": "StateMachineFireAction", + "key": { + "int": 615, + "string": "statemachinefireaction" + }, + "abstract": true, + "properties": { + "layerComponentId": { + "type": "Id", + "initialValue": "Core.missingId", + "key": { + "int": 391, + "string": "layercomponentid" + }, + "description": "Id of the transition or layer this belongs to.", + "runtime": false + }, + "occursValue": { + "type": "uint", + "initialValue": "0", + "key": { + "int": 393, + "string": "occursvalue" + }, + "description": "When the event fires." + }, + "fireOrder": { + "type": "FractionalIndex", + "initialValue": "FractionalIndex.invalid", + "key": { + "int": 394, + "string": "fireorder" + }, + "description": "Order value for sorting transitions in states.", + "runtime": false + } + } +} \ No newline at end of file
diff --git a/dev/defs/animation/state_machine_fire_event.json b/dev/defs/animation/state_machine_fire_event.json index 41db898..e713cba 100644 --- a/dev/defs/animation/state_machine_fire_event.json +++ b/dev/defs/animation/state_machine_fire_event.json
@@ -4,17 +4,8 @@ "int": 169, "string": "statemachinefireevent" }, + "extends": "animation/state_machine_fire_action.json", "properties": { - "layerComponentId": { - "type": "Id", - "initialValue": "Core.missingId", - "key": { - "int": 391, - "string": "layercomponentid" - }, - "description": "Id of the transition or layer this belongs to.", - "runtime": false - }, "eventId": { "type": "Id", "typeRuntime": "uint", @@ -25,25 +16,6 @@ "string": "eventid" }, "description": "Id of the Event referenced." - }, - "occursValue": { - "type": "uint", - "initialValue": "0", - "key": { - "int": 393, - "string": "occursvalue" - }, - "description": "When the event fires." - }, - "fireOrder": { - "type": "FractionalIndex", - "initialValue": "FractionalIndex.invalid", - "key": { - "int": 394, - "string": "fireorder" - }, - "description": "Order value for sorting transitions in states.", - "runtime": false } } } \ No newline at end of file
diff --git a/dev/defs/animation/state_machine_fire_trigger.json b/dev/defs/animation/state_machine_fire_trigger.json new file mode 100644 index 0000000..67c31e0 --- /dev/null +++ b/dev/defs/animation/state_machine_fire_trigger.json
@@ -0,0 +1,21 @@ +{ + "name": "StateMachineFireTrigger", + "key": { + "int": 614, + "string": "statemachinefiretrigger" + }, + "extends": "animation/state_machine_fire_action.json", + "properties": { + "viewModelPathIds": { + "type": "List<Id>", + "typeRuntime": "Bytes", + "encoded": true, + "initialValue": "[]", + "key": { + "int": 871, + "string": "viewmodelpathids" + }, + "description": "Path to the selected view model trigger property." + } + } +} \ No newline at end of file
diff --git a/include/rive/animation/state_machine_fire_action.hpp b/include/rive/animation/state_machine_fire_action.hpp new file mode 100644 index 0000000..35fb477 --- /dev/null +++ b/include/rive/animation/state_machine_fire_action.hpp
@@ -0,0 +1,25 @@ +#ifndef _RIVE_STATE_MACHINE_FIRE_ACTION_HPP_ +#define _RIVE_STATE_MACHINE_FIRE_ACTION_HPP_ +#include "rive/generated/animation/state_machine_fire_action_base.hpp" +#include <stdio.h> +namespace rive +{ +class StateMachineInstance; +enum class StateMachineFireOccurance : int +{ + atStart = 0, + atEnd = 1 +}; +class StateMachineFireAction : public StateMachineFireActionBase +{ +public: + StateMachineFireOccurance occurs() const + { + return (StateMachineFireOccurance)occursValue(); + } + StatusCode import(ImportStack& importStack) override; + virtual void perform(StateMachineInstance* stateMachineInstance) const = 0; +}; +} // namespace rive + +#endif \ No newline at end of file
diff --git a/include/rive/animation/state_machine_fire_event.hpp b/include/rive/animation/state_machine_fire_event.hpp index 9927cfd..86173ed 100644 --- a/include/rive/animation/state_machine_fire_event.hpp +++ b/include/rive/animation/state_machine_fire_event.hpp
@@ -4,22 +4,11 @@ namespace rive { -class StateMachineInstance; -enum class StateMachineFireOccurance : int -{ - atStart = 0, - atEnd = 1 -}; class StateMachineFireEvent : public StateMachineFireEventBase { public: - StatusCode import(ImportStack& importStack) override; - StateMachineFireOccurance occurs() const - { - return (StateMachineFireOccurance)occursValue(); - } - void perform(StateMachineInstance* stateMachineInstance) const; + void perform(StateMachineInstance* stateMachineInstance) const override; }; } // namespace rive
diff --git a/include/rive/animation/state_machine_fire_trigger.hpp b/include/rive/animation/state_machine_fire_trigger.hpp new file mode 100644 index 0000000..0758890 --- /dev/null +++ b/include/rive/animation/state_machine_fire_trigger.hpp
@@ -0,0 +1,20 @@ +#ifndef _RIVE_STATE_MACHINE_FIRE_TRIGGER_HPP_ +#define _RIVE_STATE_MACHINE_FIRE_TRIGGER_HPP_ +#include "rive/generated/animation/state_machine_fire_trigger_base.hpp" +#include <stdio.h> +namespace rive +{ +class StateMachineFireTrigger : public StateMachineFireTriggerBase +{ +public: + void perform(StateMachineInstance* stateMachineInstance) const override; + void decodeViewModelPathIds(Span<const uint8_t> value) override; + void copyViewModelPathIds( + const StateMachineFireTriggerBase& object) override; + +protected: + std::vector<uint32_t> m_viewModelPathIdsBuffer; +}; +} // namespace rive + +#endif \ No newline at end of file
diff --git a/include/rive/animation/state_machine_layer_component.hpp b/include/rive/animation/state_machine_layer_component.hpp index d94266d..4ff309e 100644 --- a/include/rive/animation/state_machine_layer_component.hpp +++ b/include/rive/animation/state_machine_layer_component.hpp
@@ -5,20 +5,20 @@ namespace rive { -class StateMachineFireEvent; +class StateMachineFireAction; class StateMachineLayerComponent : public StateMachineLayerComponentBase { friend class StateMachineLayerComponentImporter; public: - const std::vector<StateMachineFireEvent*>& events() const + const std::vector<StateMachineFireAction*>& events() const { return m_events; } ~StateMachineLayerComponent() override; private: - std::vector<StateMachineFireEvent*> m_events; + std::vector<StateMachineFireAction*> m_events; }; } // namespace rive
diff --git a/include/rive/generated/animation/state_machine_fire_action_base.hpp b/include/rive/generated/animation/state_machine_fire_action_base.hpp new file mode 100644 index 0000000..a991072 --- /dev/null +++ b/include/rive/generated/animation/state_machine_fire_action_base.hpp
@@ -0,0 +1,68 @@ +#ifndef _RIVE_STATE_MACHINE_FIRE_ACTION_BASE_HPP_ +#define _RIVE_STATE_MACHINE_FIRE_ACTION_BASE_HPP_ +#include "rive/core.hpp" +#include "rive/core/field_types/core_uint_type.hpp" +namespace rive +{ +class StateMachineFireActionBase : public Core +{ +protected: + typedef Core Super; + +public: + static const uint16_t typeKey = 615; + + /// Helper to quickly determine if a core object extends another without + /// RTTI at runtime. + bool isTypeOf(uint16_t typeKey) const override + { + switch (typeKey) + { + case StateMachineFireActionBase::typeKey: + return true; + default: + return false; + } + } + + uint16_t coreType() const override { return typeKey; } + + static const uint16_t occursValuePropertyKey = 393; + +protected: + uint32_t m_OccursValue = 0; + +public: + inline uint32_t occursValue() const { return m_OccursValue; } + void occursValue(uint32_t value) + { + if (m_OccursValue == value) + { + return; + } + m_OccursValue = value; + occursValueChanged(); + } + + void copy(const StateMachineFireActionBase& object) + { + m_OccursValue = object.m_OccursValue; + } + + bool deserialize(uint16_t propertyKey, BinaryReader& reader) override + { + switch (propertyKey) + { + case occursValuePropertyKey: + m_OccursValue = CoreUintType::deserialize(reader); + return true; + } + return false; + } + +protected: + virtual void occursValueChanged() {} +}; +} // namespace rive + +#endif \ No newline at end of file
diff --git a/include/rive/generated/animation/state_machine_fire_event_base.hpp b/include/rive/generated/animation/state_machine_fire_event_base.hpp index 34138da..6da429a 100644 --- a/include/rive/generated/animation/state_machine_fire_event_base.hpp +++ b/include/rive/generated/animation/state_machine_fire_event_base.hpp
@@ -1,13 +1,13 @@ #ifndef _RIVE_STATE_MACHINE_FIRE_EVENT_BASE_HPP_ #define _RIVE_STATE_MACHINE_FIRE_EVENT_BASE_HPP_ -#include "rive/core.hpp" +#include "rive/animation/state_machine_fire_action.hpp" #include "rive/core/field_types/core_uint_type.hpp" namespace rive { -class StateMachineFireEventBase : public Core +class StateMachineFireEventBase : public StateMachineFireAction { protected: - typedef Core Super; + typedef StateMachineFireAction Super; public: static const uint16_t typeKey = 169; @@ -19,6 +19,7 @@ switch (typeKey) { case StateMachineFireEventBase::typeKey: + case StateMachineFireActionBase::typeKey: return true; default: return false; @@ -28,11 +29,9 @@ uint16_t coreType() const override { return typeKey; } static const uint16_t eventIdPropertyKey = 392; - static const uint16_t occursValuePropertyKey = 393; protected: uint32_t m_EventId = -1; - uint32_t m_OccursValue = 0; public: inline uint32_t eventId() const { return m_EventId; } @@ -46,22 +45,11 @@ eventIdChanged(); } - inline uint32_t occursValue() const { return m_OccursValue; } - void occursValue(uint32_t value) - { - if (m_OccursValue == value) - { - return; - } - m_OccursValue = value; - occursValueChanged(); - } - Core* clone() const override; void copy(const StateMachineFireEventBase& object) { m_EventId = object.m_EventId; - m_OccursValue = object.m_OccursValue; + StateMachineFireAction::copy(object); } bool deserialize(uint16_t propertyKey, BinaryReader& reader) override @@ -71,16 +59,12 @@ case eventIdPropertyKey: m_EventId = CoreUintType::deserialize(reader); return true; - case occursValuePropertyKey: - m_OccursValue = CoreUintType::deserialize(reader); - return true; } - return false; + return StateMachineFireAction::deserialize(propertyKey, reader); } protected: virtual void eventIdChanged() {} - virtual void occursValueChanged() {} }; } // namespace rive
diff --git a/include/rive/generated/animation/state_machine_fire_trigger_base.hpp b/include/rive/generated/animation/state_machine_fire_trigger_base.hpp new file mode 100644 index 0000000..311bee3 --- /dev/null +++ b/include/rive/generated/animation/state_machine_fire_trigger_base.hpp
@@ -0,0 +1,62 @@ +#ifndef _RIVE_STATE_MACHINE_FIRE_TRIGGER_BASE_HPP_ +#define _RIVE_STATE_MACHINE_FIRE_TRIGGER_BASE_HPP_ +#include "rive/animation/state_machine_fire_action.hpp" +#include "rive/core/field_types/core_bytes_type.hpp" +#include "rive/span.hpp" +namespace rive +{ +class StateMachineFireTriggerBase : public StateMachineFireAction +{ +protected: + typedef StateMachineFireAction Super; + +public: + static const uint16_t typeKey = 614; + + /// Helper to quickly determine if a core object extends another without + /// RTTI at runtime. + bool isTypeOf(uint16_t typeKey) const override + { + switch (typeKey) + { + case StateMachineFireTriggerBase::typeKey: + case StateMachineFireActionBase::typeKey: + return true; + default: + return false; + } + } + + uint16_t coreType() const override { return typeKey; } + + static const uint16_t viewModelPathIdsPropertyKey = 871; + +public: + virtual void decodeViewModelPathIds(Span<const uint8_t> value) = 0; + virtual void copyViewModelPathIds( + const StateMachineFireTriggerBase& object) = 0; + + Core* clone() const override; + void copy(const StateMachineFireTriggerBase& object) + { + copyViewModelPathIds(object); + StateMachineFireAction::copy(object); + } + + bool deserialize(uint16_t propertyKey, BinaryReader& reader) override + { + switch (propertyKey) + { + case viewModelPathIdsPropertyKey: + decodeViewModelPathIds(CoreBytesType::deserialize(reader)); + return true; + } + return StateMachineFireAction::deserialize(propertyKey, reader); + } + +protected: + virtual void viewModelPathIdsChanged() {} +}; +} // namespace rive + +#endif \ No newline at end of file
diff --git a/include/rive/generated/core_registry.hpp b/include/rive/generated/core_registry.hpp index c880aef..18728c2 100644 --- a/include/rive/generated/core_registry.hpp +++ b/include/rive/generated/core_registry.hpp
@@ -53,7 +53,9 @@ #include "rive/animation/state_machine.hpp" #include "rive/animation/state_machine_bool.hpp" #include "rive/animation/state_machine_component.hpp" +#include "rive/animation/state_machine_fire_action.hpp" #include "rive/animation/state_machine_fire_event.hpp" +#include "rive/animation/state_machine_fire_trigger.hpp" #include "rive/animation/state_machine_input.hpp" #include "rive/animation/state_machine_layer.hpp" #include "rive/animation/state_machine_layer_component.hpp" @@ -423,6 +425,8 @@ return new ListenerFireEvent(); case TransitionSelfComparatorBase::typeKey: return new TransitionSelfComparator(); + case StateMachineFireTriggerBase::typeKey: + return new StateMachineFireTrigger(); case TransitionValueTriggerComparatorBase::typeKey: return new TransitionValueTriggerComparator(); case KeyFrameUintBase::typeKey: @@ -1079,6 +1083,9 @@ case LayerStateBase::flagsPropertyKey: object->as<LayerStateBase>()->flags(value); break; + case StateMachineFireActionBase::occursValuePropertyKey: + object->as<StateMachineFireActionBase>()->occursValue(value); + break; case TransitionValueTriggerComparatorBase::valuePropertyKey: object->as<TransitionValueTriggerComparatorBase>()->value( value); @@ -1186,9 +1193,6 @@ case StateMachineFireEventBase::eventIdPropertyKey: object->as<StateMachineFireEventBase>()->eventId(value); break; - case StateMachineFireEventBase::occursValuePropertyKey: - object->as<StateMachineFireEventBase>()->occursValue(value); - break; case LinearAnimationBase::fpsPropertyKey: object->as<LinearAnimationBase>()->fps(value); break; @@ -2572,6 +2576,8 @@ return object->as<ListenerFireEventBase>()->eventId(); case LayerStateBase::flagsPropertyKey: return object->as<LayerStateBase>()->flags(); + case StateMachineFireActionBase::occursValuePropertyKey: + return object->as<StateMachineFireActionBase>()->occursValue(); case TransitionValueTriggerComparatorBase::valuePropertyKey: return object->as<TransitionValueTriggerComparatorBase>() ->value(); @@ -2647,8 +2653,6 @@ return object->as<StateTransitionBase>()->randomWeight(); case StateMachineFireEventBase::eventIdPropertyKey: return object->as<StateMachineFireEventBase>()->eventId(); - case StateMachineFireEventBase::occursValuePropertyKey: - return object->as<StateMachineFireEventBase>()->occursValue(); case LinearAnimationBase::fpsPropertyKey: return object->as<LinearAnimationBase>()->fps(); case LinearAnimationBase::durationPropertyKey: @@ -3533,6 +3537,7 @@ instanceHeightScaleTypePropertyKey: case ListenerFireEventBase::eventIdPropertyKey: case LayerStateBase::flagsPropertyKey: + case StateMachineFireActionBase::occursValuePropertyKey: case TransitionValueTriggerComparatorBase::valuePropertyKey: case KeyFrameBase::framePropertyKey: case InterpolatingKeyFrameBase::interpolationTypePropertyKey: @@ -3568,7 +3573,6 @@ case StateTransitionBase::interpolatorIdPropertyKey: case StateTransitionBase::randomWeightPropertyKey: case StateMachineFireEventBase::eventIdPropertyKey: - case StateMachineFireEventBase::occursValuePropertyKey: case LinearAnimationBase::fpsPropertyKey: case LinearAnimationBase::durationPropertyKey: case LinearAnimationBase::loopValuePropertyKey: @@ -3937,6 +3941,7 @@ case ExportAudioBase::volumePropertyKey: return CoreDoubleType::id; case NestedArtboardBase::dataBindPathIdsPropertyKey: + case StateMachineFireTriggerBase::viewModelPathIdsPropertyKey: case StateMachineListenerBase::viewModelPathIdsPropertyKey: case MeshBase::triangleIndexBytesPropertyKey: case DataConverterOperationViewModelBase::sourcePathIdsPropertyKey: @@ -4145,6 +4150,8 @@ return object->is<ListenerFireEventBase>(); case LayerStateBase::flagsPropertyKey: return object->is<LayerStateBase>(); + case StateMachineFireActionBase::occursValuePropertyKey: + return object->is<StateMachineFireActionBase>(); case TransitionValueTriggerComparatorBase::valuePropertyKey: return object->is<TransitionValueTriggerComparatorBase>(); case KeyFrameBase::framePropertyKey: @@ -4214,8 +4221,6 @@ return object->is<StateTransitionBase>(); case StateMachineFireEventBase::eventIdPropertyKey: return object->is<StateMachineFireEventBase>(); - case StateMachineFireEventBase::occursValuePropertyKey: - return object->is<StateMachineFireEventBase>(); case LinearAnimationBase::fpsPropertyKey: return object->is<LinearAnimationBase>(); case LinearAnimationBase::durationPropertyKey:
diff --git a/include/rive/importers/state_machine_layer_component_importer.hpp b/include/rive/importers/state_machine_layer_component_importer.hpp index b9132a2..621bf79 100644 --- a/include/rive/importers/state_machine_layer_component_importer.hpp +++ b/include/rive/importers/state_machine_layer_component_importer.hpp
@@ -6,14 +6,14 @@ namespace rive { class StateMachineLayerComponent; -class StateMachineFireEvent; +class StateMachineFireAction; class StateMachineLayerComponentImporter : public ImportStackObject { public: StateMachineLayerComponentImporter(StateMachineLayerComponent* component); - void addFireEvent(StateMachineFireEvent* fireEvent); + void addFireEvent(StateMachineFireAction* fireEvent); private: StateMachineLayerComponent* m_stateMachineLayerComponent;
diff --git a/src/animation/state_machine_fire_action.cpp b/src/animation/state_machine_fire_action.cpp new file mode 100644 index 0000000..f6b8089 --- /dev/null +++ b/src/animation/state_machine_fire_action.cpp
@@ -0,0 +1,20 @@ +#include "rive/generated/animation/state_machine_fire_action_base.hpp" +#include "rive/animation/state_machine_fire_event.hpp" +#include "rive/animation/state_machine_layer_component.hpp" +#include "rive/animation/state_machine_instance.hpp" +#include "rive/event.hpp" +#include "rive/importers/state_machine_layer_component_importer.hpp" + +using namespace rive; + +StatusCode StateMachineFireAction::import(ImportStack& importStack) +{ + auto stateImporter = importStack.latest<StateMachineLayerComponentImporter>( + StateMachineLayerComponent::typeKey); + if (stateImporter == nullptr) + { + return StatusCode::MissingObject; + } + stateImporter->addFireEvent(this); + return Super::import(importStack); +} \ No newline at end of file
diff --git a/src/animation/state_machine_fire_trigger.cpp b/src/animation/state_machine_fire_trigger.cpp new file mode 100644 index 0000000..7b23348 --- /dev/null +++ b/src/animation/state_machine_fire_trigger.cpp
@@ -0,0 +1,37 @@ +#include "rive/animation/state_machine_fire_trigger.hpp" +#include "rive/animation/state_machine_instance.hpp" +#include "rive/viewmodel/viewmodel_instance_trigger.hpp" + +using namespace rive; + +void StateMachineFireTrigger::perform( + StateMachineInstance* stateMachineInstance) const +{ + auto dataContext = stateMachineInstance->dataContext(); + if (dataContext != nullptr) + { + auto vmProp = + dataContext->getViewModelProperty(m_viewModelPathIdsBuffer); + if (vmProp && vmProp->is<ViewModelInstanceTrigger>()) + { + vmProp->as<ViewModelInstanceTrigger>()->trigger(); + } + } +} + +void StateMachineFireTrigger::decodeViewModelPathIds(Span<const uint8_t> value) +{ + BinaryReader reader(value); + while (!reader.reachedEnd()) + { + auto val = reader.readVarUintAs<uint32_t>(); + m_viewModelPathIdsBuffer.push_back(val); + } +} + +void StateMachineFireTrigger::copyViewModelPathIds( + const StateMachineFireTriggerBase& object) +{ + m_viewModelPathIdsBuffer = + object.as<StateMachineFireTrigger>()->m_viewModelPathIdsBuffer; +} \ No newline at end of file
diff --git a/src/animation/state_machine_instance.cpp b/src/animation/state_machine_instance.cpp index e0f70fc..fe3050f 100644 --- a/src/animation/state_machine_instance.cpp +++ b/src/animation/state_machine_instance.cpp
@@ -187,7 +187,7 @@ } void fireEvents(StateMachineFireOccurance occurs, - const std::vector<StateMachineFireEvent*>& fireEvents) + const std::vector<StateMachineFireAction*>& fireEvents) { for (auto event : fireEvents) {
diff --git a/src/generated/animation/state_machine_fire_action_base.cpp b/src/generated/animation/state_machine_fire_action_base.cpp new file mode 100644 index 0000000..cd8eec4 --- /dev/null +++ b/src/generated/animation/state_machine_fire_action_base.cpp
@@ -0,0 +1,4 @@ +#include "rive/generated/animation/state_machine_fire_action_base.hpp" +#include "rive/animation/state_machine_fire_action.hpp" + +using namespace rive;
diff --git a/src/generated/animation/state_machine_fire_event.cpp b/src/generated/animation/state_machine_fire_event.cpp index 568d11b..5b2a2c2 100644 --- a/src/generated/animation/state_machine_fire_event.cpp +++ b/src/generated/animation/state_machine_fire_event.cpp
@@ -7,18 +7,6 @@ using namespace rive; -StatusCode StateMachineFireEvent::import(ImportStack& importStack) -{ - auto stateImporter = importStack.latest<StateMachineLayerComponentImporter>( - StateMachineLayerComponent::typeKey); - if (stateImporter == nullptr) - { - return StatusCode::MissingObject; - } - stateImporter->addFireEvent(this); - return Super::import(importStack); -} - void StateMachineFireEvent::perform( StateMachineInstance* stateMachineInstance) const {
diff --git a/src/generated/animation/state_machine_fire_trigger_base.cpp b/src/generated/animation/state_machine_fire_trigger_base.cpp new file mode 100644 index 0000000..734398d --- /dev/null +++ b/src/generated/animation/state_machine_fire_trigger_base.cpp
@@ -0,0 +1,11 @@ +#include "rive/generated/animation/state_machine_fire_trigger_base.hpp" +#include "rive/animation/state_machine_fire_trigger.hpp" + +using namespace rive; + +Core* StateMachineFireTriggerBase::clone() const +{ + auto cloned = new StateMachineFireTrigger(); + cloned->copy(*this); + return cloned; +}
diff --git a/src/importers/state_machine_layer_component_importer.cpp b/src/importers/state_machine_layer_component_importer.cpp index 4ea47ca..12ab08b 100644 --- a/src/importers/state_machine_layer_component_importer.cpp +++ b/src/importers/state_machine_layer_component_importer.cpp
@@ -1,6 +1,6 @@ #include "rive/importers/state_machine_layer_component_importer.hpp" #include "rive/animation/state_machine_layer_component.hpp" -#include "rive/animation/state_machine_fire_event.hpp" +#include "rive/animation/state_machine_fire_action.hpp" using namespace rive; @@ -18,7 +18,7 @@ {} void StateMachineLayerComponentImporter::addFireEvent( - StateMachineFireEvent* fireEvent) + StateMachineFireAction* fireEvent) { m_stateMachineLayerComponent->m_events.push_back(fireEvent); } \ No newline at end of file
diff --git a/tests/unit_tests/assets/state_transition_fire_trigger.riv b/tests/unit_tests/assets/state_transition_fire_trigger.riv new file mode 100644 index 0000000..33f86b0 --- /dev/null +++ b/tests/unit_tests/assets/state_transition_fire_trigger.riv Binary files differ
diff --git a/tests/unit_tests/runtime/data_binding_test.cpp b/tests/unit_tests/runtime/data_binding_test.cpp index 11a5935..4b6138f 100644 --- a/tests/unit_tests/runtime/data_binding_test.cpp +++ b/tests/unit_tests/runtime/data_binding_test.cpp
@@ -1295,3 +1295,46 @@ CHECK(silver.matches("data_bind_solo-solos-to-values")); } + +TEST_CASE("State machine fire triggers", "[data binding]") +{ + + rive::SerializingFactory silver; + auto file = + ReadRiveFile("assets/state_transition_fire_trigger.riv", &silver); + + auto artboard = file->artboardNamed("main"); + + silver.frameSize(artboard->width(), artboard->height()); + + REQUIRE(artboard != nullptr); + auto stateMachine = artboard->stateMachineAt(0); + int viewModelId = artboard.get()->viewModelId(); + + auto vmi = viewModelId == -1 + ? file->createViewModelInstance(artboard.get()) + : file->createViewModelInstance(viewModelId, 0); + + stateMachine->bindViewModelInstance(vmi); + stateMachine->advanceAndApply(0.0f); + stateMachine->advanceAndApply(0.016f); + + auto renderer = silver.makeRenderer(); + artboard->draw(renderer.get()); + // Advance and apply twice to take the transition and apply the next state. + stateMachine->advanceAndApply(0.1f); + stateMachine->advanceAndApply(1.0f); + + silver.addFrame(); + stateMachine->advanceAndApply(0.1f); + stateMachine->advanceAndApply(1.0f); + artboard->draw(renderer.get()); + + silver.addFrame(); + // Advance and apply twice to take the transition and apply the next state. + stateMachine->advanceAndApply(0.1f); + stateMachine->advanceAndApply(1.0f); + artboard->draw(renderer.get()); + + CHECK(silver.matches("state_transition_fire_trigger")); +}
diff --git a/tests/unit_tests/silvers/state_transition_fire_trigger.sriv b/tests/unit_tests/silvers/state_transition_fire_trigger.sriv new file mode 100644 index 0000000..b6b5d1d --- /dev/null +++ b/tests/unit_tests/silvers/state_transition_fire_trigger.sriv Binary files differ