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);
+}