Updating core defs, adding logic for toggle button, bug fix.
diff --git a/dev/defs/animation/event_bool_change.json b/dev/defs/animation/event_bool_change.json
index 5bf7a92..7a67cd7 100644
--- a/dev/defs/animation/event_bool_change.json
+++ b/dev/defs/animation/event_bool_change.json
@@ -7,8 +7,8 @@
"extends": "animation/event_input_change.json",
"properties": {
"value": {
- "type": "bool",
- "initialValue": "true",
+ "type": "uint",
+ "initialValue": "1",
"key": {
"int": 228,
"string": "value"
diff --git a/dev/defs/assets/layer_image_asset.json b/dev/defs/assets/layer_image_asset.json
new file mode 100644
index 0000000..0c42783
--- /dev/null
+++ b/dev/defs/assets/layer_image_asset.json
@@ -0,0 +1,38 @@
+{
+ "name": "LayerImageAsset",
+ "key": {
+ "int": 120,
+ "string": "layerimageasset"
+ },
+ "extends": "assets/image_asset.json",
+ "runtime": false,
+ "properties": {
+ "layer": {
+ "type": "uint",
+ "initialValue": "-1",
+ "key": {
+ "int": 233,
+ "string": "layer"
+ },
+ "description": "Layer ID as it is analysed by the backend"
+ },
+ "x": {
+ "type": "double",
+ "initialValue": "0",
+ "key": {
+ "int": 234,
+ "string": "x"
+ },
+ "description": "x offset for this layer"
+ },
+ "y": {
+ "type": "double",
+ "initialValue": "0",
+ "key": {
+ "int": 235,
+ "string": "y"
+ },
+ "description": "y offset for this layer"
+ }
+ }
+}
\ No newline at end of file
diff --git a/dev/defs/assets/layered_asset.json b/dev/defs/assets/layered_asset.json
new file mode 100644
index 0000000..042381f
--- /dev/null
+++ b/dev/defs/assets/layered_asset.json
@@ -0,0 +1,9 @@
+{
+ "name": "LayeredAsset",
+ "key": {
+ "int": 119,
+ "string": "layeredasset"
+ },
+ "runtime": false,
+ "extends": "assets/drawable_asset.json"
+}
\ No newline at end of file
diff --git a/include/rive/generated/animation/event_bool_change_base.hpp b/include/rive/generated/animation/event_bool_change_base.hpp
index 13d95ad..e0914b7 100644
--- a/include/rive/generated/animation/event_bool_change_base.hpp
+++ b/include/rive/generated/animation/event_bool_change_base.hpp
@@ -1,7 +1,7 @@
#ifndef _RIVE_EVENT_BOOL_CHANGE_BASE_HPP_
#define _RIVE_EVENT_BOOL_CHANGE_BASE_HPP_
#include "rive/animation/event_input_change.hpp"
-#include "rive/core/field_types/core_bool_type.hpp"
+#include "rive/core/field_types/core_uint_type.hpp"
namespace rive {
class EventBoolChangeBase : public EventInputChange {
protected:
@@ -27,11 +27,11 @@
static const uint16_t valuePropertyKey = 228;
private:
- bool m_Value = true;
+ uint32_t m_Value = 1;
public:
- inline bool value() const { return m_Value; }
- void value(bool value) {
+ inline uint32_t value() const { return m_Value; }
+ void value(uint32_t value) {
if (m_Value == value) {
return;
}
@@ -48,7 +48,7 @@
bool deserialize(uint16_t propertyKey, BinaryReader& reader) override {
switch (propertyKey) {
case valuePropertyKey:
- m_Value = CoreBoolType::deserialize(reader);
+ m_Value = CoreUintType::deserialize(reader);
return true;
}
return EventInputChange::deserialize(propertyKey, reader);
diff --git a/include/rive/generated/core_registry.hpp b/include/rive/generated/core_registry.hpp
index 54f9bc5..918498f 100644
--- a/include/rive/generated/core_registry.hpp
+++ b/include/rive/generated/core_registry.hpp
@@ -373,6 +373,9 @@
case TransitionValueConditionBase::opValuePropertyKey:
object->as<TransitionValueConditionBase>()->opValue(value);
break;
+ case EventBoolChangeBase::valuePropertyKey:
+ object->as<EventBoolChangeBase>()->value(value);
+ break;
case StateTransitionBase::stateToIdPropertyKey:
object->as<StateTransitionBase>()->stateToId(value);
break;
@@ -750,9 +753,6 @@
case KeyFrameBoolBase::valuePropertyKey:
object->as<KeyFrameBoolBase>()->value(value);
break;
- case EventBoolChangeBase::valuePropertyKey:
- object->as<EventBoolChangeBase>()->value(value);
- break;
case LinearAnimationBase::enableWorkAreaPropertyKey:
object->as<LinearAnimationBase>()->enableWorkArea(value);
break;
@@ -861,6 +861,8 @@
return object->as<KeyFrameIdBase>()->value();
case TransitionValueConditionBase::opValuePropertyKey:
return object->as<TransitionValueConditionBase>()->opValue();
+ case EventBoolChangeBase::valuePropertyKey:
+ return object->as<EventBoolChangeBase>()->value();
case StateTransitionBase::stateToIdPropertyKey:
return object->as<StateTransitionBase>()->stateToId();
case StateTransitionBase::flagsPropertyKey:
@@ -1117,8 +1119,6 @@
return object->as<NestedSimpleAnimationBase>()->isPlaying();
case KeyFrameBoolBase::valuePropertyKey:
return object->as<KeyFrameBoolBase>()->value();
- case EventBoolChangeBase::valuePropertyKey:
- return object->as<EventBoolChangeBase>()->value();
case LinearAnimationBase::enableWorkAreaPropertyKey:
return object->as<LinearAnimationBase>()->enableWorkArea();
case StateMachineBoolBase::valuePropertyKey:
@@ -1183,6 +1183,7 @@
case KeyFrameBase::interpolatorIdPropertyKey:
case KeyFrameIdBase::valuePropertyKey:
case TransitionValueConditionBase::opValuePropertyKey:
+ case EventBoolChangeBase::valuePropertyKey:
case StateTransitionBase::stateToIdPropertyKey:
case StateTransitionBase::flagsPropertyKey:
case StateTransitionBase::durationPropertyKey:
@@ -1308,7 +1309,6 @@
case IKConstraintBase::invertDirectionPropertyKey:
case NestedSimpleAnimationBase::isPlayingPropertyKey:
case KeyFrameBoolBase::valuePropertyKey:
- case EventBoolChangeBase::valuePropertyKey:
case LinearAnimationBase::enableWorkAreaPropertyKey:
case StateMachineBoolBase::valuePropertyKey:
case ShapePaintBase::isVisiblePropertyKey:
diff --git a/src/animation/event_bool_change.cpp b/src/animation/event_bool_change.cpp
index 946f15a..2d81753 100644
--- a/src/animation/event_bool_change.cpp
+++ b/src/animation/event_bool_change.cpp
@@ -18,5 +18,15 @@
}
// 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());
+ switch (value()) {
+ case 0:
+ boolInput->value(false);
+ break;
+ case 1:
+ boolInput->value(true);
+ break;
+ default:
+ boolInput->value(!boolInput->value());
+ break;
+ }
}
\ No newline at end of file
diff --git a/src/animation/state_machine_event.cpp b/src/animation/state_machine_event.cpp
index 9abce0c..bd17743 100644
--- a/src/animation/state_machine_event.cpp
+++ b/src/animation/state_machine_event.cpp
@@ -48,7 +48,7 @@
if (component == target) {
auto index = artboard->idOf(shape);
if (index != 0) {
- m_HitShapesIds.push_back(artboard->idOf(shape));
+ m_HitShapesIds.push_back(index);
}
break;
}
diff --git a/src/animation/state_machine_instance.cpp b/src/animation/state_machine_instance.cpp
index 0447d10..cf29882 100644
--- a/src/animation/state_machine_instance.cpp
+++ b/src/animation/state_machine_instance.cpp
@@ -74,7 +74,7 @@
}
}
- bool advance(/*Artboard* artboard, */float seconds, Span<SMIInput*> inputs) {
+ bool advance(/*Artboard* artboard, */ float seconds, Span<SMIInput*> inputs) {
m_StateChangedOnAdvance = false;
if (m_CurrentState != nullptr) {
@@ -134,8 +134,9 @@
return true;
}
- bool
- tryChangeState(StateInstance* stateFromInstance, Span<SMIInput*> inputs, bool ignoreTriggers) {
+ bool tryChangeState(StateInstance* stateFromInstance,
+ Span<SMIInput*> inputs,
+ bool ignoreTriggers) {
if (stateFromInstance == nullptr) {
return false;
}
@@ -276,18 +277,12 @@
void StateMachineInstance::pointerMove(Vec2D position) {
processEvent(position, EventType::updateHover);
}
-void StateMachineInstance::pointerDown(Vec2D position) {
- processEvent(position, EventType::down);
-}
-void StateMachineInstance::pointerUp(Vec2D position) {
- processEvent(position, EventType::up);
-}
+void StateMachineInstance::pointerDown(Vec2D position) { processEvent(position, EventType::down); }
+void StateMachineInstance::pointerUp(Vec2D position) { processEvent(position, EventType::up); }
StateMachineInstance::StateMachineInstance(const StateMachine* machine,
- ArtboardInstance* instance)
- : Scene(instance)
- , m_Machine(machine)
-{
+ ArtboardInstance* instance) :
+ Scene(instance), m_Machine(machine) {
const auto count = machine->inputCount();
m_InputInstances.resize(count);
for (size_t i = 0; i < count; i++) {
diff --git a/src/artboard.cpp b/src/artboard.cpp
index 6758548..56f1e6d 100644
--- a/src/artboard.cpp
+++ b/src/artboard.cpp
@@ -68,17 +68,25 @@
}
}
- for (auto object : m_Animations) {
- if (!canContinue(code = object->onAddedDirty(this))) {
- return code;
+ // Animations and StateMachines initialize only once on the source/origin
+ // Artboard. Instances will hold references to the original Animations and StateMachines, so
+ // running this code for instances will effectively initialize them twice. This can lead to
+ // unpredictable behaviour. One such example was that resolved objects like event inputs were
+ // being added to lists twice.
+ if (!isInstance()) {
+ for (auto object : m_Animations) {
+ if (!canContinue(code = object->onAddedDirty(this))) {
+ return code;
+ }
+ }
+
+ for (auto object : m_StateMachines) {
+ if (!canContinue(code = object->onAddedDirty(this))) {
+ return code;
+ }
}
}
- for (auto object : m_StateMachines) {
- if (!canContinue(code = object->onAddedDirty(this))) {
- return code;
- }
- }
// Store a map of the drawRules to make it easier to lookup the matching
// rule for a transform component.
std::unordered_map<Core*, DrawRules*> componentDrawRules;
@@ -115,15 +123,17 @@
}
}
- for (auto object : m_Animations) {
- if (!canContinue(code = object->onAddedClean(this))) {
- return code;
+ if (!isInstance()) {
+ for (auto object : m_Animations) {
+ if (!canContinue(code = object->onAddedClean(this))) {
+ return code;
+ }
}
- }
- for (auto object : m_StateMachines) {
- if (!canContinue(code = object->onAddedClean(this))) {
- return code;
+ for (auto object : m_StateMachines) {
+ if (!canContinue(code = object->onAddedClean(this))) {
+ return code;
+ }
}
}
@@ -523,6 +533,7 @@
artboardClone->m_Factory = m_Factory;
artboardClone->m_FrameOrigin = m_FrameOrigin;
+ artboardClone->m_IsInstance = true;
std::vector<Core*>& cloneObjects = artboardClone->m_Objects;
cloneObjects.push_back(artboardClone.get());
@@ -545,8 +556,6 @@
if (artboardClone->initialize() != StatusCode::Ok) {
artboardClone = nullptr;
- } else {
- artboardClone->m_IsInstance = true;
}
assert(artboardClone->isInstance());
diff --git a/test/assets/light_switch.riv b/test/assets/light_switch.riv
new file mode 100644
index 0000000..a779e6b
--- /dev/null
+++ b/test/assets/light_switch.riv
Binary files differ
diff --git a/test/state_machine_event_test.cpp b/test/state_machine_event_test.cpp
index ad9e4d3..9bc81cf 100644
--- a/test/state_machine_event_test.cpp
+++ b/test/state_machine_event_test.cpp
@@ -81,3 +81,31 @@
REQUIRE(trigger->didFire());
}
+
+TEST_CASE("hit a toggle boolean event", "[file]") {
+ auto file = ReadRiveFile("../../test/assets/light_switch.riv");
+
+ auto artboard = file->artboard()->instance();
+ REQUIRE(artboard != nullptr);
+ REQUIRE(artboard->stateMachineCount() == 1);
+
+ auto stateMachine = artboard->stateMachineAt(0);
+ REQUIRE(stateMachine != nullptr);
+
+ artboard->advance(0.0f);
+ stateMachine->advance(0.0f);
+
+ auto switchButton = stateMachine->getBool("On");
+ REQUIRE(switchButton != nullptr);
+ REQUIRE(switchButton->value() == true);
+
+ stateMachine->pointerDown(rive::Vec2D(150.0f, 258.0f));
+ stateMachine->pointerUp(rive::Vec2D(150.0f, 258.0f));
+ // Got toggled off after pressing
+ REQUIRE(switchButton->value() == false);
+
+ stateMachine->pointerDown(rive::Vec2D(150.0f, 258.0f));
+ stateMachine->pointerUp(rive::Vec2D(150.0f, 258.0f));
+ // Got toggled back on after pressing
+ REQUIRE(switchButton->value() == true);
+}