Nested Inputs

This PR adds support for setting NestedInput values from a parent artboard. We should support NestedBool, NestedNumber and NestedTrigger. After discussion with @alxgibsn there are at least 4 editor UI updates required to work together with this feature.

- [x] Add a `public` boolean to StateMachineInput that allows you to specify whether the input should be available outside of its own artboard. This is presented in the motion inspector when a StateMachineInput is selected.
- [x] Surfacing Nested Inputs in the Inputs panel alongside the Inputs for the current artboard. We also need a way to differentiate Nested Inputs from regular Inputs (possibly a folder-like hierarchy).
- [x] Surfacing Nested Inputs in the Inputs list for a Listener.
- [x] Surfacing Nested Inputs in the NestedArtboard StateMachine flyout. Looks like this work has already been done!
- [x]  Get NestedTrigger working

Diffs=
45359b3e8 Nested Inputs  (#6007)

Co-authored-by: Philip Chung <philterdesign@gmail.com>
diff --git a/.rive_head b/.rive_head
index fe1cfcf..eb5f98f 100644
--- a/.rive_head
+++ b/.rive_head
@@ -1 +1 @@
-1a9dd7e97e623eb30dbec164ae0935b2ad848c1b
+45359b3e81085b85fa517ec8e26ac273eb40ad04
diff --git a/dev/defs/animation/listener_input_change.json b/dev/defs/animation/listener_input_change.json
index 445b3e4..006e50c 100644
--- a/dev/defs/animation/listener_input_change.json
+++ b/dev/defs/animation/listener_input_change.json
@@ -17,6 +17,17 @@
         "string": "inputid"
       },
       "description": "Id of the StateMachineInput referenced."
+    },
+    "nestedInputId": {
+      "type": "Id",
+      "typeRuntime": "uint",
+      "initialValue": "Core.missingId",
+      "initialValueRuntime": "-1",
+      "key": {
+        "int": 400,
+        "string": "nestedinputid"
+      },
+      "description": "Id of the NestedInput referenced if this is listening to a nested input."
     }
   }
 }
\ No newline at end of file
diff --git a/dev/defs/animation/nested_trigger.json b/dev/defs/animation/nested_trigger.json
index ea7f077..ab9255e 100644
--- a/dev/defs/animation/nested_trigger.json
+++ b/dev/defs/animation/nested_trigger.json
@@ -4,5 +4,15 @@
     "int": 122,
     "string": "nestedTrigger"
   },
-  "extends": "animation/nested_input.json"
+  "extends": "animation/nested_input.json",
+  "properties": {
+    "fire": {
+      "type": "callback",
+      "animates": true,
+      "key": {
+        "int": 401,
+        "string": "fire"
+      }
+    }
+  }
 }
\ No newline at end of file
diff --git a/dev/defs/animation/state_machine_input.json b/dev/defs/animation/state_machine_input.json
index 51d3b0f..93d6e60 100644
--- a/dev/defs/animation/state_machine_input.json
+++ b/dev/defs/animation/state_machine_input.json
@@ -5,5 +5,17 @@
     "string": "statemachineinput"
   },
   "abstract": true,
-  "extends": "animation/state_machine_component.json"
+  "extends": "animation/state_machine_component.json",
+  "properties": {
+    "public": {
+      "type": "bool",
+      "initialValue": "false",
+      "key": {
+        "int": 402,
+        "string": "public"
+      },
+      "description": "Determines whether this StateMachineInput will be exposed to parent artboards.",
+      "runtime": false
+    }
+  }
 }
\ No newline at end of file
diff --git a/include/rive/animation/nested_bool.hpp b/include/rive/animation/nested_bool.hpp
index 99f0dab..2900390 100644
--- a/include/rive/animation/nested_bool.hpp
+++ b/include/rive/animation/nested_bool.hpp
@@ -7,6 +7,8 @@
 class NestedBool : public NestedBoolBase
 {
 public:
+protected:
+    void nestedValueChanged() override;
 };
 } // namespace rive
 
diff --git a/include/rive/animation/nested_input.hpp b/include/rive/animation/nested_input.hpp
index 158cf05..9d4970c 100644
--- a/include/rive/animation/nested_input.hpp
+++ b/include/rive/animation/nested_input.hpp
@@ -1,5 +1,6 @@
 #ifndef _RIVE_NESTED_INPUT_HPP_
 #define _RIVE_NESTED_INPUT_HPP_
+#include "rive/animation/nested_state_machine.hpp"
 #include "rive/generated/animation/nested_input_base.hpp"
 #include <stdio.h>
 namespace rive
@@ -7,6 +8,17 @@
 class NestedInput : public NestedInputBase
 {
 public:
+protected:
+    SMIInput* input() {
+        auto parent = this->parent();
+        if (parent != nullptr && parent->is<NestedStateMachine>()) 
+        {
+            StateMachineInstance* smInstance = parent->as<NestedStateMachine>()->stateMachineInstance();
+            auto inputInstance = smInstance->input(this->inputId());
+            return inputInstance;
+        }
+        return nullptr;
+    }
 };
 } // namespace rive
 
diff --git a/include/rive/animation/nested_number.hpp b/include/rive/animation/nested_number.hpp
index 5ae1053..6b51594 100644
--- a/include/rive/animation/nested_number.hpp
+++ b/include/rive/animation/nested_number.hpp
@@ -7,6 +7,8 @@
 class NestedNumber : public NestedNumberBase
 {
 public:
+protected:
+    void nestedValueChanged() override;
 };
 } // namespace rive
 
diff --git a/include/rive/animation/nested_state_machine.hpp b/include/rive/animation/nested_state_machine.hpp
index 46790e7..da13c5a 100644
--- a/include/rive/animation/nested_state_machine.hpp
+++ b/include/rive/animation/nested_state_machine.hpp
@@ -1,5 +1,6 @@
 #ifndef _RIVE_NESTED_STATE_MACHINE_HPP_
 #define _RIVE_NESTED_STATE_MACHINE_HPP_
+#include "rive/animation/state_machine_instance.hpp"
 #include "rive/generated/animation/nested_state_machine_base.hpp"
 #include "rive/math/vec2d.hpp"
 #include <memory>
diff --git a/include/rive/animation/nested_trigger.hpp b/include/rive/animation/nested_trigger.hpp
index 7861dbd..5f1d67c 100644
--- a/include/rive/animation/nested_trigger.hpp
+++ b/include/rive/animation/nested_trigger.hpp
@@ -7,6 +7,7 @@
 class NestedTrigger : public NestedTriggerBase
 {
 public:
+    void fire(const CallbackData& value) override;
 };
 } // namespace rive
 
diff --git a/include/rive/generated/animation/listener_input_change_base.hpp b/include/rive/generated/animation/listener_input_change_base.hpp
index f0c982a..835bb76 100644
--- a/include/rive/generated/animation/listener_input_change_base.hpp
+++ b/include/rive/generated/animation/listener_input_change_base.hpp
@@ -29,9 +29,11 @@
     uint16_t coreType() const override { return typeKey; }
 
     static const uint16_t inputIdPropertyKey = 227;
+    static const uint16_t nestedInputIdPropertyKey = 400;
 
 private:
     uint32_t m_InputId = -1;
+    uint32_t m_NestedInputId = -1;
 
 public:
     inline uint32_t inputId() const { return m_InputId; }
@@ -45,9 +47,21 @@
         inputIdChanged();
     }
 
+    inline uint32_t nestedInputId() const { return m_NestedInputId; }
+    void nestedInputId(uint32_t value)
+    {
+        if (m_NestedInputId == value)
+        {
+            return;
+        }
+        m_NestedInputId = value;
+        nestedInputIdChanged();
+    }
+
     void copy(const ListenerInputChangeBase& object)
     {
         m_InputId = object.m_InputId;
+        m_NestedInputId = object.m_NestedInputId;
         ListenerAction::copy(object);
     }
 
@@ -58,12 +72,16 @@
             case inputIdPropertyKey:
                 m_InputId = CoreUintType::deserialize(reader);
                 return true;
+            case nestedInputIdPropertyKey:
+                m_NestedInputId = CoreUintType::deserialize(reader);
+                return true;
         }
         return ListenerAction::deserialize(propertyKey, reader);
     }
 
 protected:
     virtual void inputIdChanged() {}
+    virtual void nestedInputIdChanged() {}
 };
 } // namespace rive
 
diff --git a/include/rive/generated/animation/nested_trigger_base.hpp b/include/rive/generated/animation/nested_trigger_base.hpp
index c489415..6fd3a5d 100644
--- a/include/rive/generated/animation/nested_trigger_base.hpp
+++ b/include/rive/generated/animation/nested_trigger_base.hpp
@@ -1,6 +1,7 @@
 #ifndef _RIVE_NESTED_TRIGGER_BASE_HPP_
 #define _RIVE_NESTED_TRIGGER_BASE_HPP_
 #include "rive/animation/nested_input.hpp"
+#include "rive/core/field_types/core_callback_type.hpp"
 namespace rive
 {
 class NestedTriggerBase : public NestedInput
@@ -28,6 +29,11 @@
 
     uint16_t coreType() const override { return typeKey; }
 
+    static const uint16_t firePropertyKey = 401;
+
+public:
+    virtual void fire(const CallbackData& value) = 0;
+
     Core* clone() const override;
 
 protected:
diff --git a/include/rive/generated/core_registry.hpp b/include/rive/generated/core_registry.hpp
index 5ca3da9..1f8987f 100644
--- a/include/rive/generated/core_registry.hpp
+++ b/include/rive/generated/core_registry.hpp
@@ -452,6 +452,9 @@
             case ListenerInputChangeBase::inputIdPropertyKey:
                 object->as<ListenerInputChangeBase>()->inputId(value);
                 break;
+            case ListenerInputChangeBase::nestedInputIdPropertyKey:
+                object->as<ListenerInputChangeBase>()->nestedInputId(value);
+                break;
             case AnimationStateBase::animationIdPropertyKey:
                 object->as<AnimationStateBase>()->animationId(value);
                 break;
@@ -1141,6 +1144,18 @@
                 break;
         }
     }
+    static void setCallback(Core* object, int propertyKey, CallbackData value)
+    {
+        switch (propertyKey)
+        {
+            case NestedTriggerBase::firePropertyKey:
+                object->as<NestedTriggerBase>()->fire(value);
+                break;
+            case EventBase::triggerPropertyKey:
+                object->as<EventBase>()->trigger(value);
+                break;
+        }
+    }
     static void setColor(Core* object, int propertyKey, int value)
     {
         switch (propertyKey)
@@ -1156,15 +1171,6 @@
                 break;
         }
     }
-    static void setCallback(Core* object, int propertyKey, CallbackData value)
-    {
-        switch (propertyKey)
-        {
-            case EventBase::triggerPropertyKey:
-                object->as<EventBase>()->trigger(value);
-                break;
-        }
-    }
     static std::string getString(Core* object, int propertyKey)
     {
         switch (propertyKey)
@@ -1226,6 +1232,8 @@
                 return object->as<ListenerFireEventBase>()->eventId();
             case ListenerInputChangeBase::inputIdPropertyKey:
                 return object->as<ListenerInputChangeBase>()->inputId();
+            case ListenerInputChangeBase::nestedInputIdPropertyKey:
+                return object->as<ListenerInputChangeBase>()->nestedInputId();
             case AnimationStateBase::animationIdPropertyKey:
                 return object->as<AnimationStateBase>()->animationId();
             case NestedInputBase::inputIdPropertyKey:
@@ -1736,6 +1744,7 @@
             case SoloBase::activeComponentIdPropertyKey:
             case ListenerFireEventBase::eventIdPropertyKey:
             case ListenerInputChangeBase::inputIdPropertyKey:
+            case ListenerInputChangeBase::nestedInputIdPropertyKey:
             case AnimationStateBase::animationIdPropertyKey:
             case NestedInputBase::inputIdPropertyKey:
             case KeyedObjectBase::objectIdPropertyKey:
@@ -1980,6 +1989,7 @@
     {
         switch (propertyKey)
         {
+            case NestedTriggerBase::firePropertyKey:
             case EventBase::triggerPropertyKey:
                 return true;
             default:
diff --git a/src/animation/listener_bool_change.cpp b/src/animation/listener_bool_change.cpp
index e27c00c..ba9e2aa 100644
--- a/src/animation/listener_bool_change.cpp
+++ b/src/animation/listener_bool_change.cpp
@@ -1,4 +1,7 @@
 #include "rive/animation/listener_bool_change.hpp"
+#include "rive/animation/nested_bool.hpp"
+#include "rive/animation/nested_input.hpp"
+#include "rive/animation/nested_state_machine.hpp"
 #include "rive/animation/state_machine_instance.hpp"
 #include "rive/animation/state_machine_bool.hpp"
 #include "rive/animation/state_machine_input_instance.hpp"
@@ -14,23 +17,49 @@
 
 void ListenerBoolChange::perform(StateMachineInstance* stateMachineInstance, Vec2D position) const
 {
-    auto inputInstance = stateMachineInstance->input(inputId());
-    if (inputInstance == nullptr)
+    if (nestedInputId() != Core::emptyId) 
     {
-        return;
-    }
-    // If it's not null, it must be our correct type (why we validate at load time).
-    auto boolInput = static_cast<SMIBool*>(inputInstance);
-    switch (value())
-    {
-        case 0:
-            boolInput->value(false);
-            break;
-        case 1:
-            boolInput->value(true);
-            break;
-        default:
-            boolInput->value(!boolInput->value());
-            break;
+        auto nestedInputInstance = stateMachineInstance->artboard()->resolve(nestedInputId());
+        if (nestedInputInstance == nullptr) 
+        {
+            return;
+        }
+        auto nestedBoolInput = static_cast<NestedBool*>(nestedInputInstance);
+        if (nestedBoolInput != nullptr) {
+            switch (value())
+            {
+                case 0:
+                    nestedBoolInput->nestedValue(false);
+                    break;
+                case 1:
+                    nestedBoolInput->nestedValue(true);
+                    break;
+                default:
+                    nestedBoolInput->nestedValue(!nestedBoolInput->nestedValue());
+                    break;
+            }
+        }
+    } else {
+        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 = static_cast<SMIBool*>(inputInstance);
+        if (boolInput != nullptr) {
+            switch (value())
+            {
+                case 0:
+                    boolInput->value(false);
+                    break;
+                case 1:
+                    boolInput->value(true);
+                    break;
+                default:
+                    boolInput->value(!boolInput->value());
+                    break;
+            }
+        }
     }
 }
diff --git a/src/animation/listener_number_change.cpp b/src/animation/listener_number_change.cpp
index 3f8af9b..3b3ae43 100644
--- a/src/animation/listener_number_change.cpp
+++ b/src/animation/listener_number_change.cpp
@@ -1,4 +1,6 @@
 #include "rive/animation/listener_number_change.hpp"
+#include "rive/animation/nested_number.hpp"
+#include "rive/animation/nested_state_machine.hpp"
 #include "rive/animation/state_machine_instance.hpp"
 #include "rive/animation/state_machine_number.hpp"
 #include "rive/animation/state_machine_input_instance.hpp"
@@ -15,12 +17,27 @@
 
 void ListenerNumberChange::perform(StateMachineInstance* stateMachineInstance, Vec2D position) const
 {
-    auto inputInstance = stateMachineInstance->input(inputId());
-    if (inputInstance == nullptr)
+    if (nestedInputId() != Core::emptyId) 
     {
-        return;
+        auto nestedInputInstance = stateMachineInstance->artboard()->resolve(nestedInputId());
+        if (nestedInputInstance == nullptr) 
+        {
+            return;
+        }
+        auto nestedNumberInput = static_cast<NestedNumber*>(nestedInputInstance);
+        if (nestedNumberInput != nullptr) {
+            nestedNumberInput->nestedValue(value());
+        }
+    } else {
+        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 = static_cast<SMINumber*>(inputInstance);
+        if (numberInput != nullptr) {
+            numberInput->value(value());
+        }
     }
-    // If it's not null, it must be our correct type (why we validate at load time).
-    auto numberInput = static_cast<SMINumber*>(inputInstance);
-    numberInput->value(value());
 }
diff --git a/src/animation/listener_trigger_change.cpp b/src/animation/listener_trigger_change.cpp
index 3dff886..8b6ac21 100644
--- a/src/animation/listener_trigger_change.cpp
+++ b/src/animation/listener_trigger_change.cpp
@@ -1,7 +1,10 @@
 #include "rive/animation/listener_trigger_change.hpp"
+#include "rive/animation/nested_trigger.hpp"
+#include "rive/animation/nested_state_machine.hpp"
 #include "rive/animation/state_machine_instance.hpp"
 #include "rive/animation/state_machine_trigger.hpp"
 #include "rive/animation/state_machine_input_instance.hpp"
+#include "rive/core/field_types/core_callback_type.hpp"
 
 using namespace rive;
 
@@ -16,12 +19,27 @@
 void ListenerTriggerChange::perform(StateMachineInstance* stateMachineInstance,
                                     Vec2D position) const
 {
-    auto inputInstance = stateMachineInstance->input(inputId());
-    if (inputInstance == nullptr)
+    if (nestedInputId() != Core::emptyId) 
     {
-        return;
+        auto nestedInputInstance = stateMachineInstance->artboard()->resolve(nestedInputId());
+        if (nestedInputInstance == nullptr) 
+        {
+            return;
+        }
+        auto nestedTriggerInput = static_cast<NestedTrigger*>(nestedInputInstance);
+        if (nestedTriggerInput != nullptr) {
+            nestedTriggerInput->fire(CallbackData(stateMachineInstance, 0));
+        }
+    } else {
+        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 = static_cast<SMITrigger*>(inputInstance);
+        if (triggerInput != nullptr) {
+            triggerInput->fire();
+        }
     }
-    // If it's not null, it must be our correct type (why we validate at load time).
-    auto triggerInput = static_cast<SMITrigger*>(inputInstance);
-    triggerInput->fire();
 }
diff --git a/src/animation/nested_bool.cpp b/src/animation/nested_bool.cpp
new file mode 100644
index 0000000..cf4110d
--- /dev/null
+++ b/src/animation/nested_bool.cpp
@@ -0,0 +1,18 @@
+#include "rive/animation/nested_bool.hpp"
+#include "rive/animation/nested_state_machine.hpp"
+#include "rive/animation/state_machine_input_instance.hpp"
+#include "rive/container_component.hpp"
+
+using namespace rive;
+class StateMachineInstance;
+
+void NestedBool::nestedValueChanged() {
+    auto inputInstance = input();
+    if (inputInstance != nullptr) 
+    {
+        auto boolInput = static_cast<SMIBool*>(inputInstance);
+        if (boolInput != nullptr) {
+            boolInput->value(nestedValue());
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/animation/nested_number.cpp b/src/animation/nested_number.cpp
new file mode 100644
index 0000000..6628b91
--- /dev/null
+++ b/src/animation/nested_number.cpp
@@ -0,0 +1,18 @@
+#include "rive/animation/nested_number.hpp"
+#include "rive/animation/nested_state_machine.hpp"
+#include "rive/animation/state_machine_input_instance.hpp"
+#include "rive/container_component.hpp"
+
+using namespace rive;
+class StateMachineInstance;
+
+void NestedNumber::nestedValueChanged() {
+    auto inputInstance = input();
+    if (inputInstance != nullptr) 
+    {
+        auto numInput = static_cast<SMINumber*>(inputInstance);
+        if (numInput != nullptr) {
+            numInput->value(nestedValue());
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/animation/nested_trigger.cpp b/src/animation/nested_trigger.cpp
new file mode 100644
index 0000000..f590f94
--- /dev/null
+++ b/src/animation/nested_trigger.cpp
@@ -0,0 +1,19 @@
+#include "rive/animation/nested_trigger.hpp"
+#include "rive/animation/nested_state_machine.hpp"
+#include "rive/animation/state_machine_input_instance.hpp"
+#include "rive/container_component.hpp"
+
+using namespace rive;
+class StateMachineInstance;
+
+void NestedTrigger::fire(const CallbackData& value) {
+    auto inputInstance = input();
+    if (inputInstance != nullptr) 
+    {
+        auto numInput = static_cast<SMITrigger*>(inputInstance);
+        if (numInput != nullptr) {
+            numInput->fire();
+        }
+    }
+    
+}
\ No newline at end of file