#include <atomic>
#include <cmath>
#include "rive/animation/animation_reset.hpp"
#include "rive/animation/animation_reset_factory.hpp"
#include "rive/animation/animation_state_instance.hpp"
#include "rive/animation/animation_state.hpp"
#include "rive/animation/any_state.hpp"
#include "rive/animation/keyframe_interpolator.hpp"
#include "rive/animation/keyed_object.hpp"
#ifdef TESTING
#include "rive/animation/keyframe_bool.hpp"
#include "rive/animation/keyframe_color.hpp"
#include "rive/animation/keyframe_double.hpp"
#include "rive/animation/keyframe_id.hpp"
#include "rive/animation/keyframe_int.hpp"
#include "rive/animation/keyframe_string.hpp"
#include "rive/animation/keyframe_uint.hpp"
#include "rive/generated/core_registry.hpp"
#endif
#include "rive/animation/keyed_property.hpp"
#include "rive/animation/linear_animation.hpp"
#include "rive/animation/linear_animation_instance.hpp"
#include "rive/data_bind/bindable_property_number.hpp"
#include "rive/data_bind/converters/data_converter.hpp"
#include "rive/animation/entry_state.hpp"
#include "rive/animation/exit_state.hpp"
#include "rive/animation/layer_state_flags.hpp"
#include "rive/animation/nested_linear_animation.hpp"
#include "rive/animation/nested_state_machine.hpp"
#include "rive/animation/scripted_transition_condition.hpp"
#include "rive/animation/state_instance.hpp"
#include "rive/animation/state_machine_bool.hpp"
#include "rive/animation/state_machine_input_instance.hpp"
#include "rive/animation/state_machine_input.hpp"
#include "rive/animation/state_machine_instance.hpp"
#include "rive/animation/state_machine_instance_clusters.hpp"
#include "rive/animation/state_machine_layer.hpp"
#include "rive/animation/listener_invocation.hpp"
#include "rive/animation/state_machine_listener.hpp"
#include "rive/animation/state_machine_listener_single.hpp"
#include "rive/animation/state_machine_number.hpp"
#include "rive/animation/state_machine_trigger.hpp"
#include "rive/animation/state_machine.hpp"
#include "rive/animation/state_transition.hpp"
#include "rive/animation/listener_action.hpp"
#include "rive/animation/listener_types/listener_input_type_viewmodel.hpp"
#include "rive/animation/scripted_listener_action.hpp"
#include "rive/animation/transition_condition.hpp"
#include "rive/animation/transition_comparator.hpp"
#include "rive/animation/transition_property_viewmodel_comparator.hpp"
#include "rive/animation/transition_viewmodel_condition.hpp"
#include "rive/animation/state_machine_fire_event.hpp"
#include "rive/viewmodel/viewmodel_instance_trigger.hpp"
#include "rive/artboard_component_list.hpp"
#include "rive/constraints/draggable_constraint.hpp"
#include "rive/data_bind/data_bind_context.hpp"
#include "rive/data_bind/data_bind.hpp"
#include "rive/data_bind/context/context_value.hpp"
#include "rive/data_bind/data_values/data_value_number.hpp"
#include "rive/data_bind_flags.hpp"
#include "rive/event_report.hpp"
#include "rive/hit_result.hpp"
#include "rive/listener_group.hpp"
#include "rive/math/aabb.hpp"
#include "rive/math/random.hpp"
#include "rive/math/hit_test.hpp"
#include "rive/nested_animation.hpp"
#include "rive/nested_artboard.hpp"
#include "rive/process_event_result.hpp"
#include "rive/scripted/scripted_drawable.hpp"
#include "rive/scripted/scripted_interpolator.hpp"
#include "rive/shapes/image.hpp"
#include "rive/shapes/shape.hpp"
#include "rive/text/text.hpp"
#include "rive/math/math_types.hpp"
#include "rive/audio_event.hpp"
#include "rive/dirtyable.hpp"
#include "rive/profiler/profiler_macros.h"
#include "rive/text/text_input.hpp"
#include "rive/refcnt.hpp"
#include "rive/animation/focus_listener_group.hpp"
#include "rive/animation/text_input_listener_group.hpp"
#include "rive/animation/listener_types/listener_input_type_event.hpp"
#include "rive/focus_data.hpp"
#include "rive/node.hpp"
#include "rive/semantic/semantic_data.hpp"
#include "rive/view_model_type.hpp"
#include "rive/viewmodel/viewmodel.hpp"
#include "rive/file.hpp"
#include "rive/data_bind/data_context.hpp"
#include "rive/viewmodel/write_attribution.hpp"
#include <algorithm>
#include <array>
#include <functional>
#include <limits>
#include <memory>
#include <unordered_map>
#include <vector>
#include <chrono>

using namespace rive;

// ArtboardComponentList builds one StateMachineInstance per row, so a 1000-row
// list pays sizeof(StateMachineInstance) a thousand times over before any
// content exists. The clusters in state_machine_instance_clusters.hpp exist to
// keep it small: 1080 B before that work, 368 B after, which the allocator
// rounds to 384 instead of 1280.
//
// Before adding an inline member, check whether it belongs in one of the
// SMI* sidecar clusters instead — anything that is only populated for a
// specific authored feature (events, bindables, focus/keyboard/gamepad/
// semantics, scripting) does. Note also that nothing inline here is a
// std::unordered_map any more, which is what makes this type the same size on
// libc++ and libstdc++; an inline hash container would give that up.

#ifdef RIVE_MICROPROFILE
#include "rive/profiler/rive_profile.hpp"
static std::string getStateName(const StateInstance* stateInstance)
{
  if (stateInstance == nullptr)
  {
    return "(null)";
  }
  auto state = stateInstance->state();
  if (state->is<AnimationState>())
  {
    auto anim = state->as<AnimationState>()->animation();
    return anim != nullptr ? anim->name() : "Animation";
  }
  if (state->is<EntryState>())
  {
    return "Entry";
  }
  if (state->is<ExitState>())
  {
    return "Exit";
  }
  if (state->is<AnyState>())
  {
    return "Any";
  }
  return "Blend";
}
#endif

namespace rive
{

class StateMachineLayerInstance
{
public:
  StateMachineLayerInstance()
      : m_transitionCompleted(false)
      , m_holdAnimationFrom(false)
      , m_stateMachineChangedOnAdvance(false)
      , m_waitingForExit(false)
      , m_settled(false)
  {}

  ~StateMachineLayerInstance()
  {
    delete m_anyStateInstance;
    delete m_currentState;
    delete m_stateFrom;
  }

  /// The artboard every layer of this instance applies to. This is
  /// identical for all layers of a given StateMachineInstance — as was the
  /// owning instance pointer — so holding either per layer stored the same
  /// value layerCount times over. Both are therefore derived from the `smi`
  /// threaded through the methods below rather than stored per layer.
  ///
  /// The layer *definition* is deliberately NOT derived this way. It is
  /// genuinely per-index data, and while `m_machine->layer(this - m_layers)`
  /// would recover it, that lookup is only stable in runtime builds. Under
  /// WITH_RIVE_EDITOR, StateMachine::layer() reads `m_editorLayers`, which
  /// EditorFile::finalizeBatch clears and rebuilds from arena order after
  /// every coop batch, while clearStalePlaybackScenes only rebuilds the
  /// StateMachineInstance when the StateMachine *pointer* changes. So adding
  /// or reparenting a layer can leave slot i resolving to a different
  /// definition — or, if a layer was deleted, to nullptr — while m_layers[i]
  /// still holds the old layer's runtime state. m_layer is captured once at
  /// init and pinned for the instance's lifetime instead.
  static ArtboardInstance* artboardOf(const StateMachineInstance* smi)
  {
    return smi->m_artboardInstance;
  }

  void init(StateMachineInstance* smi, const StateMachineLayer* layer)
  {
    assert(m_layer == nullptr);
    m_layer = layer;
    changeState(smi, m_layer->entryState());
  }

  void resetState(StateMachineInstance* smi)
  {
    // The current state goes away below even when changeState then finds
    // nothing to change to (no entry state).
    m_settled = false;
    if (m_stateFrom != m_anyStateInstance && m_stateFrom != m_currentState)
    {
      delete m_stateFrom;
    }
    m_stateFrom = nullptr;
    if (m_currentState != m_anyStateInstance)
    {
      delete m_currentState;
    }
    m_currentState = nullptr;
    changeState(smi, m_layer->entryState());
  }

  void updateMix(StateMachineInstance* smi, float seconds)
  {
    if (m_transition != nullptr && m_stateFrom != nullptr &&
        resolvedDuration() != 0)
    {
      auto mixTime = resolvedMixTime();
      if (mixTime == 0.0f)
      {
        m_mix = 1.0f;
      }
      else
      {
        m_mix = std::min(1.0f, std::max(0.0f, (m_mix + seconds / mixTime)));
      }
      if (m_mix == 1.0f && !m_transitionCompleted)
      {
        m_transitionCompleted = true;
        clearAnimationReset();
        fireEvents(
            smi,
            StateMachineFireOccurance::atEnd,
            m_transition->events());
        performListenerActions(
            smi,
            StateMachineFireOccurance::atEnd,
            m_transition->listenerActions());
      }
    }
    else
    {
      m_mix = 1.0f;
    }
  }

  // A settled layer that has finished mixing, in a state that keys nothing,
  // has stopped keeping itself going and has no exit time to wait on: its
  // advance would only move a clock nothing reads, apply nothing and skip a
  // search that can't pass, so it returns what that advance would have.
  // The same holds for a state whose animation holds its keyframe values and
  // has already applied them (see isPoseInPlace): a pose, or a finished
  // one-shot. poseSince is the artboard's change serial when the previous
  // advance started.
  bool isFrozen(const StateMachineInstance* smi, uint32_t poseSince) const
  {
    if (!m_settled || m_mix != 1.0f || m_animationReset != nullptr ||
        m_holdAnimation != nullptr ||
        (m_transition != nullptr && !m_transitionCompleted) ||
        m_currentState == nullptr || m_currentState->keepGoing())
    {
      return false;
    }
    auto state = m_currentState->state();
    if (!state->transitionsIgnoreTime())
    {
      return false;
    }
    // Checked on the instance rather than classified with the state: a
    // state's animation may not be resolved yet when that runs.
    switch (state->coreType())
    {
      case EntryStateBase::typeKey:
      case ExitStateBase::typeKey:
      case AnyStateBase::typeKey:
        return true;
      case AnimationStateBase::typeKey:
      {
        // An animation state without an animation plays an empty one.
        auto instance = static_cast<const AnimationStateInstance*>(
                            m_currentState)
                            ->animationInstance();
        return instance->animation()->numKeyedObjects() == 0 ||
               isPoseInPlace(
                   smi,
                   instance,
                   state->as<AnimationState>()->speed(),
                   poseSince);
      }
      default:
        return false;
    }
  }

  // A one-shot that has finished sits clamped to its end (its start, playing
  // backwards), crosses no more keyframes and so fires no more callbacks.
  // Where that time writes keyframe values as they are (a pose, or a time at
  // or outside every property's keyframes), applying it again changes
  // nothing once it has been applied at full mix -- until something else
  // writes to the artboard: another layer, a bind, a script, the host. Every
  // such write bumps the artboard's change serial, so the pose is still in
  // place while the serial hasn't moved since the previous advance started
  // (this advance's earlier layers included). Keyframe values bound to data
  // change without that, so their artboards keep re-applying, and so does a
  // transition whose interpolator doesn't end at exactly 1 (its "full" mix
  // still blends). Finished is the animation's own word for it: the state's
  // keepGoing() also reads false after an advance by zero, before the
  // animation has played at all. It is asked in the direction the state
  // plays it (stateSpeed): a state playing backwards starts at the
  // animation's end, where a forward one-shot would be done.
  bool isPoseInPlace(
      const StateMachineInstance* smi,
      const LinearAnimationInstance* instance,
      float stateSpeed,
      uint32_t poseSince) const
  {
    if (instance->keepGoing(stateSpeed) ||
        !instance->animation()->appliesKeyFrameValuesAt(instance->time()))
    {
      return false;
    }
    const ArtboardInstance* artboard = artboardOf(smi);
    if (artboard->changeSerial() != poseSince)
    {
      return false;
    }
    const Artboard* source = artboard->artboardSource();
    if ((source != nullptr ? source : artboard)->hasKeyFrameSourceBinds())
    {
      return false;
    }
    if (m_transition != nullptr && m_transition->interpolator() != nullptr &&
        m_transition->interpolator()->transform(1.0f) != 1.0f)
    {
      return false;
    }
    return true;
  }

#ifdef TESTING
  // Every value the skipped pose would have written is already there.
  void verifyFrozenPose(const StateMachineInstance* smi) const
  {
    if (m_currentState == nullptr ||
        m_currentState->state()->coreType() != AnimationStateBase::typeKey)
    {
      return;
    }
    auto instance = static_cast<const AnimationStateInstance*>(m_currentState)
                        ->animationInstance();
    auto animation = instance->animation();
    if (animation->numKeyedObjects() == 0)
    {
      return;
    }
    StateMachineInstance::sm_frozenPoseAdvances++;
    float seconds = instance->time();
    if (animation->quantize())
    {
      float ffps = (float)animation->fps();
      seconds = std::floor(seconds * ffps) / ffps;
    }
    ArtboardInstance* artboard = artboardOf(smi);
    for (size_t o = 0; o < animation->numKeyedObjects(); o++)
    {
      const KeyedObject* keyedObject = animation->getObject(o);
      Core* object = artboard->resolve(keyedObject->objectId());
      if (object == nullptr)
      {
        continue;
      }
      for (size_t p = 0; p < keyedObject->numKeyedProperties(); p++)
      {
        const KeyedProperty* property = keyedObject->getProperty(p);
        int key = property->propertyKey();
        size_t count = property->numKeyFrames();
        if (count == 0 || CoreRegistry::isCallback(key))
        {
          continue;
        }
        // At or before the first keyframe apply writes the first, at
        // or after the last it writes the last.
        const KeyFrame* keyFrame = count == 1 ||
                                           seconds <= property->getKeyFrame(0)
                                                          ->seconds()
                                       ? property->getKeyFrame(0)
                                       : property->getKeyFrame(count - 1);
        if (count > 1 && keyFrame == property->getKeyFrame(count - 1) &&
            seconds < keyFrame->seconds())
        {
          fprintf(
              stderr,
              "Frozen animation %s is between keyframes of "
              "property %d at %f\n",
              animation->name().c_str(),
              key,
              seconds);
          abort();
        }
        bool inPlace;
        if (keyFrame->is<KeyFrameDouble>())
        {
          inPlace = CoreRegistry::getDouble(object, key) ==
                    keyFrame->as<KeyFrameDouble>()->value();
        }
        else if (keyFrame->is<KeyFrameColor>())
        {
          inPlace = CoreRegistry::getColor(object, key) ==
                    keyFrame->as<KeyFrameColor>()->value();
        }
        else if (keyFrame->is<KeyFrameId>())
        {
          inPlace = CoreRegistry::getUint(object, key) ==
                    keyFrame->as<KeyFrameId>()->value();
        }
        else if (keyFrame->is<KeyFrameUint>())
        {
          inPlace = CoreRegistry::getUint(object, key) ==
                    keyFrame->as<KeyFrameUint>()->value();
        }
        else if (keyFrame->is<KeyFrameInt>())
        {
          inPlace = CoreRegistry::getInt(object, key) ==
                    keyFrame->as<KeyFrameInt>()->value();
        }
        else if (keyFrame->is<KeyFrameBool>())
        {
          inPlace = CoreRegistry::getBool(object, key) ==
                    keyFrame->as<KeyFrameBool>()->value();
        }
        else if (keyFrame->is<KeyFrameString>())
        {
          inPlace = CoreRegistry::getString(object, key) ==
                    keyFrame->as<KeyFrameString>()->value();
        }
        else
        {
          fprintf(
              stderr,
              "Frozen animation %s keys property %d with an "
              "unverifiable keyframe type %d\n",
              animation->name().c_str(),
              key,
              (int)keyFrame->coreType());
          abort();
        }
        if (!inPlace)
        {
          fprintf(
              stderr,
              "Frozen animation %s in layer %s on artboard %s would "
              "have changed property %d of object %u\n",
              animation->name().c_str(),
              m_layer->name().c_str(),
              artboard->name().c_str(),
              key,
              keyedObject->objectId());
          abort();
        }
      }
    }
  }
#endif

  bool advance(
      StateMachineInstance* smi,
      float seconds,
      bool newFrame,
      uint32_t poseSince)
  {
    RIVE_WRITE_SOURCE(layer, m_layer, smi);
    if (newFrame)
    {
      m_stateMachineChangedOnAdvance = false;
    }
    if (isFrozen(smi, poseSince))
    {
      // Skipped without a search, but it still has its frame, as a
      // settled layer's update does (see updateState).
      smi->markFrozenLayerSearched(this);
#ifdef TESTING
      StateMachineInstance::sm_frozenLayerAdvances++;
      verifyFrozenPose(smi);
#endif
      return false;
    }
    m_currentState->advance(seconds, smi);
    updateMix(smi, seconds);

    if (m_stateFrom != nullptr && m_mix < 1.0f && !m_holdAnimationFrom)
    {
      // This didn't advance during our updateState, but it should now
      // that we realize we need to mix it in.
      m_stateFrom->advance(seconds, smi);
    }

    apply(smi);

    bool changedState = false;

    for (int i = 0; updateState(smi); i++)
    {
      changedState = true;
      apply(smi);

      if (i == maxIterations)
      {
        auto stateMachineName = smi->stateMachine() == nullptr
                                    ? "[SM Not found]"
                                    : smi->stateMachine()->name().c_str();
        auto layerName = m_layer == nullptr ? "[LY Not found]"
                                            : m_layer->name().c_str();
        auto artboardName = smi->artboard() == nullptr
                                ? "[AB Not found]"
                                : smi->artboard()->name().c_str();
        fprintf(
            stderr,
            "%s StateMachine exceeded max iterations in layer %s "
            "on artboard %s\n",
            stateMachineName,
            layerName,
            artboardName);
        return false;
      }
    }

    m_currentState->clearSpilledTime();

    return changedState || m_mix != 1.0f || m_waitingForExit ||
           (m_currentState != nullptr && m_currentState->keepGoing());
  }

  /// Returns the per-instance transition duration, resolving any data
  /// binding override. Falls back to the shared definition value when
  /// no binding exists.
  uint32_t resolvedDuration() const
  {
    if (m_transitionDurationProperty != nullptr)
    {
      float val = m_transitionDurationProperty->propertyValue();
      return val < 0 ? 0 : static_cast<uint32_t>(std::round(val));
    }
    return m_transition->duration();
  }

  /// Computes the mix time using the per-instance resolved duration.
  float resolvedMixTime() const
  {
    auto dur = resolvedDuration();
    if (dur == 0)
    {
      return 0;
    }
    if (m_transition->durationIsPercentage())
    {
      float animationDuration = 0.0f;
      auto state = m_stateFrom->state();
      if (state->is<AnimationState>())
      {
        auto animation = state->as<AnimationState>()->animation();
        if (animation != nullptr)
        {
          animationDuration = animation->durationSeconds();
        }
      }
      return (float)dur / 100.0f * animationDuration;
    }
    return (float)dur / 1000.0f;
  }

  bool isTransitioning()
  {
    return m_transition != nullptr && m_stateFrom != nullptr &&
           resolvedDuration() != 0 && m_mix < 1.0f;
  }

  /// The any state's instance is only ever fed to tryChangeState, so a layer
  /// whose any state has no transitions never needs one. Most don't, so this
  /// is built on demand instead of at init: it saves a heap allocation per
  /// layer in the common case. Lazy rather than a one-shot check at init
  /// because LayerState::transitionCount() also reports the editor's
  /// live-edit list, which can grow after this instance was built.
  void ensureAnyStateInstance(StateMachineInstance* smi)
  {
    if (m_anyStateInstance != nullptr)
    {
      return;
    }
    // A layer without an any state is degenerate but not fatal: every
    // other use of m_anyStateInstance is either a delete guard or a
    // tryChangeState call, both of which handle null. Keeping this
    // tolerant is what lets StateMachineLayer stop requiring the state
    // to be present, so exports can eventually omit unused ones.
    auto anyState = m_layer == nullptr ? nullptr : m_layer->anyState();
    if (anyState == nullptr || anyState->transitionCount() == 0)
    {
      return;
    }
    m_anyStateInstance = anyState->makeInstance(artboardOf(smi)).release();
  }

  bool updateState(StateMachineInstance* smi)
  {
    // Don't allow changing state while a transition is taking place
    // (we're mixing one state onto another) if enableEarlyExit is not true.
    if (isTransitioning() && !m_transition->enableEarlyExit())
    {
      // A view model change pending while this layer can't change state
      // still expires with the frame, instead of waiting for a search
      // that can act on it.
      smi->markViewModelChangesSearched(this);
      return false;
    }

    m_waitingForExit = false;

    ensureAnyStateInstance(smi);
    if (m_settled)
    {
      // Marked anyway: a machine bound to another instance would
      // otherwise find that instance's past changes pending.
      smi->markViewModelChangesSearched(this);
#ifdef TESTING
      verifySettled(smi);
      StateMachineInstance::sm_settledLayerSkips++;
#endif
      return false;
    }
    smi->markViewModelChangesSearched(this);
    if (tryChangeState(smi, m_anyStateInstance))
    {
      return true;
    }
    if (tryChangeState(smi, m_currentState))
    {
      return true;
    }
#ifndef WITH_RIVE_EDITOR
    // Nothing to change to, and that holds until the current state changes
    // or a value these transitions read does, provided they read only
    // values whose changes reach this instance (transitionsSettleSafe),
    // none is waiting on an exit time, and no bind is waiting to be
    // applied (a condition may just have read a bindable's old value).
    // StateMachineInstance::unsettleLayers undoes it.
    if (!m_waitingForExit && !smi->m_bindsPending &&
        isSettleSafe(m_anyStateInstance) && isSettleSafe(m_currentState))
    {
      m_settled = true;
      smi->m_anySettled = true;
    }
#endif
    return false;
  }

  void unsettle() { m_settled = false; }

  static bool isSettleSafe(const StateInstance* stateInstance)
  {
    return stateInstance == nullptr ||
           stateInstance->state()->transitionsSettleSafe();
  }

#ifdef TESTING
  // A settled layer's search must still come up empty. Repeats it without
  // its side effects (random weights, used-layer marks, m_waitingForExit)
  // and stops loudly if the settled answer went stale.
  void verifySettled(StateMachineInstance* smi)
  {
    StateInstance* stateFromInstances[] = {m_anyStateInstance, m_currentState};
    for (StateInstance* stateFromInstance : stateFromInstances)
    {
      if (stateFromInstance == nullptr)
      {
        continue;
      }
      auto stateFrom = stateFromInstance->state();
      for (size_t i = 0, count = stateFrom->transitionCount(); i < count; i++)
      {
        auto transition = stateFrom->transition(i);
        if (canChangeState(transition->stateTo()) &&
            transition->allowed(stateFromInstance, smi, this) !=
                AllowTransition::no)
        {
          fprintf(
              stderr,
              "Settled layer %s on artboard %s would have taken "
              "a transition\n",
              m_layer->name().c_str(),
              smi->artboard()->name().c_str());
          abort();
        }
      }
    }
  }
#endif

  void fireEvents(
      StateMachineInstance* smi,
      StateMachineFireOccurance occurs,
      const std::vector<StateMachineFireAction*>& fireEvents)
  {
    for (auto event : fireEvents)
    {
      if (event->occurs() == occurs)
      {
        event->perform(smi);
      }
    }
  }

  void performListenerActions(
      StateMachineInstance* smi,
      StateMachineFireOccurance occurs,
      const std::vector<std::unique_ptr<ListenerAction>>& listenerActions)
  {
    bool performed = false;
    for (const auto& action : listenerActions)
    {
      if (action->matchesScheduledOccurrence(occurs))
      {
        action->perform(smi, ListenerInvocation::none());
        performed = true;
      }
    }
    if (performed)
    {
      smi->updateDataBinds(false);
    }
  }

  bool canChangeState(const LayerState* stateTo)
  {
    return !(
        (m_currentState == nullptr ? nullptr : m_currentState->state()) ==
        stateTo);
  }

  double randomValue() { return RandomProvider::generateRandomFloat(); }

  void changeState(StateMachineInstance* smi, const LayerState* stateTo)
  {
    if ((m_currentState == nullptr ? nullptr : m_currentState->state()) ==
        stateTo)
    {
      return;
    }
    // A different state has different transitions to search.
    m_settled = false;

    // Fire end events for the state we're changing from.
    if (m_currentState != nullptr)
    {
      fireEvents(
          smi,
          StateMachineFireOccurance::atEnd,
          m_currentState->state()->events());
      performListenerActions(
          smi,
          StateMachineFireOccurance::atEnd,
          m_currentState->state()->listenerActions());
    }

    m_currentState = stateTo == nullptr
                         ? nullptr
                         : stateTo->makeInstance(artboardOf(smi)).release();

    // Fire start events for the state we're changing to.
    if (m_currentState != nullptr)
    {
      fireEvents(
          smi,
          StateMachineFireOccurance::atStart,
          m_currentState->state()->events());
      performListenerActions(
          smi,
          StateMachineFireOccurance::atStart,
          m_currentState->state()->listenerActions());
    }
    return;
  }

  StateTransition* findRandomTransition(
      StateMachineInstance* smi,
      StateInstance* stateFromInstance)
  {
    uint32_t totalWeight = 0;
    auto stateFrom = stateFromInstance->state();
    for (size_t i = 0, length = stateFrom->transitionCount(); i < length; i++)
    {
      auto transition = stateFrom->transition(i);
      if (canChangeState(transition->stateTo()))
      {

        auto allowed = transition->allowed(stateFromInstance, smi, this);
        if (allowed == AllowTransition::yes)
        {
          transition->evaluatedRandomWeight(transition->randomWeight());
          totalWeight += transition->randomWeight();
        }
        else
        {
          transition->evaluatedRandomWeight(0);
          if (allowed == AllowTransition::waitingForExit)
          {
            m_waitingForExit = true;
          }
        }
      }
      else
      {
        transition->evaluatedRandomWeight(0);
      }
    }
    if (totalWeight > 0)
    {
      double randomWeight = randomValue() * totalWeight * 1.0;
      double currentWeight = 0;
      size_t index = 0;
      StateTransition* transition;
      while (index < stateFrom->transitionCount())
      {
        transition = stateFrom->transition(index);
        double transitionWeight = (double)transition->evaluatedRandomWeight();
        if (currentWeight + transitionWeight > randomWeight)
        {
          transition->useLayerInConditions(smi, this);
          return transition;
        }
        currentWeight += transitionWeight;
        index++;
      }
    }
    return nullptr;
  }

  StateTransition* findAllowedTransition(
      StateMachineInstance* smi,
      StateInstance* stateFromInstance)
  {
    auto stateFrom = stateFromInstance->state();
    // If it should randomize
    if ((static_cast<LayerStateFlags>(stateFrom->flags()) &
         LayerStateFlags::Random) == LayerStateFlags::Random)
    {
      return findRandomTransition(smi, stateFromInstance);
    }
    // Else search the first valid transition
    for (size_t i = 0, length = stateFrom->transitionCount(); i < length; i++)
    {
      auto transition = stateFrom->transition(i);
      if (canChangeState(transition->stateTo()))
      {

        auto allowed = transition->allowed(stateFromInstance, smi, this);
        if (allowed == AllowTransition::yes)
        {
          transition->evaluatedRandomWeight(transition->randomWeight());
          transition->useLayerInConditions(smi, this);
          return transition;
        }
        else
        {
          transition->evaluatedRandomWeight(0);
          if (allowed == AllowTransition::waitingForExit)
          {
            m_waitingForExit = true;
          }
        }
      }
    }
    return nullptr;
  }

  void buildAnimationResetForTransition(StateMachineInstance* smi)
  {
    m_animationReset = AnimationResetFactory::fromStates(
        m_stateFrom,
        m_currentState,
        artboardOf(smi));
  }

  void clearAnimationReset()
  {
    if (m_animationReset != nullptr)
    {
      AnimationResetFactory::release(std::move(m_animationReset));
      m_animationReset = nullptr;
    }
  }

  bool tryChangeState(
      StateMachineInstance* smi,
      StateInstance* stateFromInstance)
  {
    if (stateFromInstance == nullptr)
    {
      return false;
    }
    auto outState = m_currentState;
    auto transition = findAllowedTransition(smi, stateFromInstance);
    if (transition != nullptr)
    {
      clearAnimationReset();
      changeState(smi, transition->stateTo());
      m_stateMachineChangedOnAdvance = true;
#ifdef RIVE_MICROPROFILE
      RiveProfile::instance().recordTransition(
          smi->artboard()->name(),
          smi->name(),
          m_layer->name(),
          getStateName(outState),
          getStateName(m_currentState),
          smi->artboard());
#endif
      // state actually has changed
      m_transition = transition;
      m_transitionDurationProperty = smi->findTransitionPropertyInstance(
          transition,
          StateTransitionBase::durationPropertyKey);
      fireEvents(smi, StateMachineFireOccurance::atStart, transition->events());
      performListenerActions(
          smi,
          StateMachineFireOccurance::atStart,
          transition->listenerActions());
      if (resolvedDuration() == 0)
      {
        m_transitionCompleted = true;
        fireEvents(smi, StateMachineFireOccurance::atEnd, transition->events());
        performListenerActions(
            smi,
            StateMachineFireOccurance::atEnd,
            transition->listenerActions());
      }
      else
      {
        m_transitionCompleted = false;
      }

      if (m_stateFrom != m_anyStateInstance)
      {
        // Old state from is done.
        delete m_stateFrom;
      }
      m_stateFrom = outState;

      if (!m_transitionCompleted)
      {
        buildAnimationResetForTransition(smi);
      }

      // If we had an exit time and wanted to pause on exit, make
      // sure to hold the exit time. Delegate this to the
      // transition by telling it that it was completed.
      if (outState != nullptr && transition->applyExitCondition(outState))
      {
        // Make sure we apply this state. This only returns true
        // when it's an animation state instance.
        auto instance = static_cast<AnimationStateInstance*>(m_stateFrom)
                            ->animationInstance();

        m_holdAnimation = instance->animation();
        m_holdTime = instance->time();
      }
      m_mixFrom = m_mix;

      // Keep mixing last animation that was mixed in.
      if (m_mix != 0.0f)
      {
        m_holdAnimationFrom = transition->pauseOnExit();
      }
      if (m_currentState != nullptr)
      {
        auto advanceTime = 0.0f;
        if (m_stateFrom != nullptr)
        {
          if (m_stateFrom->state()->is<AnimationState>())
          {

            auto instance = static_cast<AnimationStateInstance*>(m_stateFrom)
                                ->animationInstance();

            advanceTime = instance->spilledTime();
          }
        }
        m_currentState->advance(advanceTime, smi);
      }
      m_mix = 0.0f;
      updateMix(smi, 0.0f);
      m_waitingForExit = false;
      return true;
    }
    return false;
  }

  void apply(StateMachineInstance* smi)
  {
    auto artboardInstance = artboardOf(smi);
    if (m_animationReset != nullptr)
    {
      m_animationReset->apply(artboardInstance);
    }
    if (m_holdAnimation != nullptr)
    {
      m_holdAnimation->apply(artboardInstance, m_holdTime, m_mixFrom);
      m_holdAnimation = nullptr;
    }

    KeyFrameInterpolator* interpolator = nullptr;
    if (m_transition != nullptr && m_transition->interpolator() != nullptr)
    {
      interpolator = m_transition->interpolator();
      // A scripted one runs as this instance's clone (StateMachine
      // registers it with its scripted objects).
      if (interpolator->is<ScriptedInterpolator>())
      {
        if (auto* stateful = smi->scriptedObject(
                interpolator->as<ScriptedInterpolator>()))
        {
          interpolator = static_cast<ScriptedInterpolator*>(stateful);
        }
      }
    }

    if (m_stateFrom != nullptr && m_mix < 1.0f)
    {
      auto fromMix = interpolator != nullptr
                         ? interpolator->transform(m_mixFrom)
                         : m_mixFrom;
      m_stateFrom->apply(artboardInstance, fromMix);
    }
    if (m_currentState != nullptr)
    {
      auto mix = interpolator != nullptr ? interpolator->transform(m_mix)
                                         : m_mix;
      m_currentState->apply(artboardInstance, mix);
    }
  }

  bool stateChangedOnAdvance() const { return m_stateMachineChangedOnAdvance; }

  const LayerState* currentState()
  {
    return m_currentState == nullptr ? nullptr : m_currentState->state();
  }

  const LinearAnimationInstance* currentAnimation() const
  {
    if (m_currentState == nullptr ||
        !m_currentState->state()->is<AnimationState>())
    {
      return nullptr;
    }
    return static_cast<AnimationStateInstance*>(m_currentState)
        ->animationInstance();
  }

private:
  static const int maxIterations = 100;

  // One of these exists per layer of every StateMachineInstance, which in an
  // ArtboardComponentList means per layer per row. Keep the pointers, then
  // the floats, then the bools: interleaving them costs 8 B of padding for
  // nothing. The owning instance and its artboard used to be stored here
  // too; both are the same for every layer of an instance, so they are now
  // derived from the `smi` argument threaded through the methods above. The
  // layer definition stays stored — see artboardOf() for why deriving it
  // from the array index is not safe in editor builds.
  const StateMachineLayer* m_layer = nullptr;
  StateInstance* m_anyStateInstance = nullptr;
  StateInstance* m_currentState = nullptr;
  StateInstance* m_stateFrom = nullptr;

  const StateTransition* m_transition = nullptr;
  BindablePropertyNumber* m_transitionDurationProperty = nullptr;
  std::unique_ptr<AnimationReset> m_animationReset = nullptr;
  /// Used to ensure a specific animation is applied on the next apply.
  const LinearAnimation* m_holdAnimation = nullptr;

  float m_mix = 1.0f;
  float m_mixFrom = 1.0f;
  float m_holdTime = 0.0f;

  // One bit each, so m_settled shares the byte the four flags before it
  // already take and sizeof stays 80. Bit-fields can't have default member
  // initializers before C++20, so the constructor sets them.
  bool m_transitionCompleted : 1;
  bool m_holdAnimationFrom : 1;
  bool m_stateMachineChangedOnAdvance : 1;
  bool m_waitingForExit : 1;
  // The last search found nothing and nothing it read has changed since,
  // so the next one would find nothing too. See updateState.
  bool m_settled : 1;
};

// Instances with a capture-phase pointer listener of their own. While there are
// none, no dispatch anywhere runs the capture phase, so files without capture
// listeners keep exactly the single pass they always had.
static std::atomic<uint32_t> s_liveCaptureMachines{0};
// Moves whenever the set of trees that hold a capture listener may have
// changed, see StateMachineInstance::captureTopologyChanged.
static std::atomic<uint32_t> s_captureEpoch{1};

static HitResult combineHitResults(HitResult a, HitResult b)
{
  if (a == HitResult::hitOpaque || b == HitResult::hitOpaque)
  {
    return HitResult::hitOpaque;
  }
  if (a == HitResult::hit || b == HitResult::hit)
  {
    return HitResult::hit;
  }
  return HitResult::none;
}

// Whether component is scope or sits under it in the artboard's hierarchy.
static bool componentWithin(const Component* component, const Component* scope)
{
  for (auto c = component; c != nullptr; c = c->parent())
  {
    if (c == scope)
    {
      return true;
    }
  }
  return false;
}

// The component a hit component stands for in the hierarchy: a layout's
// listeners hit through its proxy, which isn't part of the hierarchy itself.
static Component* hierarchyComponent(HitComponent* hitComponent)
{
  auto component = hitComponent->component();
  if (component != nullptr && component->is<Drawable>() &&
      component->as<Drawable>()->isProxy())
  {
    return component->as<Drawable>()->hittableComponent();
  }
  return component;
}

/// Marks a machine as receiving a pointer event from the machine hosting it,
/// which ran the capture phase over it already.
class HostDispatchScope
{
public:
  HostDispatchScope(StateMachineInstance* stateMachineInstance)
      : m_stateMachineInstance(stateMachineInstance)
  {
    if (m_stateMachineInstance != nullptr)
    {
      m_previous = m_stateMachineInstance->m_hostDispatching;
      m_stateMachineInstance->m_hostDispatching = true;
    }
  }
  ~HostDispatchScope()
  {
    if (m_stateMachineInstance != nullptr)
    {
      m_stateMachineInstance->m_hostDispatching = m_previous;
    }
  }

private:
  StateMachineInstance* m_stateMachineInstance;
  bool m_previous = false;
};

/// Representation of a Component from the Artboard Instance and all the
/// listeners it triggers. Allows tracking hover and performing hit detection
/// only once on components that trigger multiple listeners.
// A down, up or move a hosted machine gets while its host can't hit
// anything: past the edge of a mesh the host draws it through, or while the
// host is itself missing the pointer (see pointerMiss).
static bool isMissableEvent(ListenerType hitType)
{
  return hitType == ListenerType::down || hitType == ListenerType::up ||
         hitType == ListenerType::move;
}

// The passes a host's own drag sets off in what it hosts, to turn their
// pointers off and back on. Past a mesh's edge they miss like the above, so
// dragEnd's settling move can't reach anything undrawn.
static bool isDragPass(ListenerType hitType)
{
  return hitType == ListenerType::dragStart || hitType == ListenerType::dragEnd;
}

class HitDrawable : public HitComponent
{
public:
  HitDrawable(
      Drawable* drawable,
      Component* component,
      StateMachineInstance* stateMachineInstance,
      bool isOpaque)
      : HitComponent(component, stateMachineInstance)
  {
    this->m_drawable = drawable;
    this->isOpaque = isOpaque;
    if (drawable->isTargetOpaque())
    {
      canEarlyOut = false;
    }
  }
  float hitRadius = 2;
  bool isHovered = false;
  bool canEarlyOut = true;
  bool hasDownListener = false;
  bool hasUpListener = false;
  bool isOpaque = false;
  Drawable* m_drawable;
  std::vector<ListenerGroup*> listeners;

  bool hitTest(Vec2D position) const override { return false; }

  DraggableProxy* scrollProxyFor(const ScrollEvent& event)
  {
    // A live gesture keeps the view it started on, even once that view
    // can't move; only then does an idle proxy get a chance at the delta.
    for (auto listenerGroup : listeners)
    {
      auto proxy = listenerGroup->scrollProxy();
      if (proxy != nullptr && proxy->isScrollGestureActive())
      {
        return proxy;
      }
    }
    for (auto listenerGroup : listeners)
    {
      auto proxy = listenerGroup->scrollProxy();
      if (proxy != nullptr && proxy->wantsScroll(event))
      {
        return proxy;
      }
    }
    return nullptr;
  }

  bool wantsScroll(Vec2D position, const ScrollEvent& event) override
  {
    return hitTest(position) && scrollProxyFor(event) != nullptr;
  }

  bool hasScrollTarget(Vec2D position) override
  {
    if (!hitTest(position))
    {
      return false;
    }
    for (auto listenerGroup : listeners)
    {
      auto proxy = listenerGroup->scrollProxy();
      if (proxy != nullptr && proxy->acceptsScroll())
      {
        return true;
      }
    }
    return false;
  }

  bool listensToButtonAt(Vec2D position, PointerButton button) override
  {
    if (!hitTest(position))
    {
      return false;
    }
    for (auto listenerGroup : listeners)
    {
      auto listener = listenerGroup->listener();
      if (listener != nullptr && listener->listensToButton(button))
      {
        return true;
      }
    }
    return false;
  }

  bool occludesPointer(Vec2D position) override
  {
    return (isOpaque || m_drawable->isTargetOpaque()) && hitTest(position);
  }

  bool occludesScroll(Vec2D position) override
  {
    // A scroll view never occludes: at its edge it declines and the
    // gesture chains outward.
    for (auto listenerGroup : listeners)
    {
      if (listenerGroup->scrollProxy() != nullptr)
      {
        return false;
      }
    }
    // Same opacity test as processEvent's hitOpaque.
    return (isOpaque || m_drawable->isTargetOpaque()) && hitTest(position);
  }

  bool scrollGestureActive() override
  {
    for (auto listenerGroup : listeners)
    {
      auto proxy = listenerGroup->scrollProxy();
      if (proxy != nullptr && proxy->isScrollGestureActive())
      {
        return true;
      }
    }
    return false;
  }

  void cancelScroll() override
  {
    for (auto listenerGroup : listeners)
    {
      auto proxy = listenerGroup->scrollProxy();
      if (proxy != nullptr)
      {
        proxy->cancelScroll();
      }
    }
  }

  HitResult processScroll(
      Vec2D position,
      const ScrollEvent& event,
      float timeStamp,
      int pointerId) override
  {
    auto proxy = scrollProxyFor(event);
    if (proxy == nullptr || !proxy->scroll(event, timeStamp))
    {
      return HitResult::none;
    }
    return isOpaque ? HitResult::hitOpaque : HitResult::hit;
  }

  void prepareEvent(Vec2D position, ListenerType hitType, int pointerId)
      override
  {
    if (canEarlyOut && (hitType != ListenerType::down || !hasDownListener) &&
        (hitType != ListenerType::up || !hasUpListener))
    {
#ifdef TESTING
      earlyOutCount++;
#endif
      return;
    }
    isHovered = hitType != ListenerType::exit && hitTest(position);

    // // iterate all listeners associated with this hit shape
    if (isHovered)
    {
      for (auto listenerGroup : listeners)
      {

        listenerGroup->hover(pointerId);
      }
    }
  }

  HitResult processGamepadInvocation(
      const ListenerInvocation& invocation,
      ScriptedDrawable* alreadyDispatched) override
  {
    return HitResult::none;
  }

  HitResult processEvent(
      Vec2D position,
      ListenerType hitType,
      bool canHit,
      float timeStamp,
      int pointerId,
      PointerButton button) override
  {
    // If the shape doesn't have any ListenerType::move / enter / exit and
    // the event being processed is not of the type it needs to handle.
    // There is no need to perform a hitTest (which is relatively expensive
    // and would be happening on every pointer move) so we early out.
    if (canEarlyOut && (hitType != ListenerType::down || !hasDownListener) &&
        (hitType != ListenerType::up || !hasUpListener))
    {
      return HitResult::none;
    }
    bool isBlockingEvent = false;
    // // iterate all listeners associated with this hit shape
    for (auto listenerGroup : listeners)
    {
      // Disabled is per pointer (a drag, or a capture listener's claim);
      // consumed is shared, so another pointer's event clears it.
      if (listenerGroup->isConsumed() ||
          listenerGroup->isPointerDisabled(pointerId))
      {
        continue;
      }
      if (listenerGroup->processEvent(
              m_component,
              position,
              pointerId,
              hitType,
              button,
              canHit,
              timeStamp,
              m_stateMachineInstance) == ProcessEventResult::scroll)
      {
        isBlockingEvent = true;
      }
    }
    return (isHovered && canHit)
               ? (isOpaque || m_drawable->isTargetOpaque() || isBlockingEvent)
                     ? HitResult::hitOpaque
                     : HitResult::hit
               : HitResult::none;
  }

  void addListener(ListenerGroup* listenerGroup)
  {
    if (!listenerGroup->canEarlyOut(m_component))
    {
      canEarlyOut = false;
    }
    else
    {
      if (listenerGroup->needsDownListener(m_component))
      {
        hasDownListener = true;
      }
      if (listenerGroup->needsUpListener(m_component))
      {
        hasUpListener = true;
      }
    }
    listeners.push_back(listenerGroup);
  }

  void enablePointerEvents(int pointerId) override
  {
    for (auto listenerGroup : listeners)
    {
      listenerGroup->enable(pointerId);
    }
  }

  void disablePointerEvents(int pointerId) override
  {
    for (auto listenerGroup : listeners)
    {
      listenerGroup->disable(pointerId);
    }
  }
};

/// Representation of a HitDrawable with a Hittable component
class HitExpandable : public HitDrawable
{
public:
  HitExpandable(
      Drawable* drawable,
      Component* component,
      StateMachineInstance* stateMachineInstance,
      bool isOpaque = false)
      : HitDrawable(drawable, component, stateMachineInstance, isOpaque)
  {}

  bool hitTest(Vec2D position) const override
  {
    return m_component->hitTestPoint(position, true, true);
  }
};

class HitTextRun : public HitExpandable
{
public:
  HitTextRun(
      Drawable* drawable,
      TextValueRun* component,
      StateMachineInstance* stateMachineInstance,
      bool isOpaque = false)
      : HitExpandable(drawable, component, stateMachineInstance, isOpaque)
  {
    if (component)
    {
      component->isHitTarget(true);
    }
  }
};

class HitLayout : public HitDrawable
{
public:
  HitLayout(
      Drawable* layout,
      StateMachineInstance* stateMachineInstance,
      bool isOpaque = false)
      : HitDrawable(layout, layout, stateMachineInstance, isOpaque)
  {}

  bool hitTest(Vec2D position) const override
  {
    return m_component->hitTestPoint(position, false, true);
  }
};

// The pointers a host turned off (its capture claim, or a drag above it) for
// the machines a hit component hosts. Those machines can change while one is
// off -- a list realizes or adds a row, a nested artboard swaps its machine --
// so each is turned off as an event reaches it, not only when the host turned
// the pointer off.
class HostedPointersOff
{
public:
  void add(int pointerId) { m_ids.pushUnique(pointerId); }
  void remove(int pointerId) { m_ids.eraseAll(pointerId); }
  bool has(int pointerId) const
  {
    const auto& ids = m_ids.view();
    return std::find(ids.begin(), ids.end(), pointerId) != ids.end();
  }
  void keepOff(StateMachineInstance* machine, int pointerId) const
  {
    if (machine != nullptr && has(pointerId) &&
        !machine->isPointerDisabled(pointerId))
    {
      machine->disablePointerEvents(pointerId);
    }
  }

private:
  LazyVector<int> m_ids;
};

class HitNestedArtboard : public HitComponent
{
public:
  HitNestedArtboard(
      Component* nestedArtboard,
      StateMachineInstance* stateMachineInstance)
      : HitComponent(nestedArtboard, stateMachineInstance)
  {}
  ~HitNestedArtboard() override {}

  bool hitTest(Vec2D position) const override
  {
    auto nestedArtboard = m_component->as<NestedArtboard>();
    if (nestedArtboard->isCollapsed() || nestedArtboard->isHidden() ||
        nestedArtboard->isPaused())
    {
      return false;
    }
    Vec2D nestedPosition;
    if (!drawnPosition(nestedArtboard, position, &nestedPosition))
    {
      // Mounted artboard isn't ready, has a 0 scale transform, or isn't
      // drawn under the pointer.
      return false;
    }

    for (auto nestedAnimation : nestedArtboard->nestedAnimations())
    {
      if (nestedAnimation->is<NestedStateMachine>())
      {
        auto nestedStateMachine = nestedAnimation->as<NestedStateMachine>();
        if (nestedStateMachine->hitTest(nestedPosition))
        {
          return true;
        }
      }
    }
    return false;
  }
  bool hitTestBounded(Vec2D position) const override
  {
    auto nestedArtboard = m_component->as<NestedArtboard>();
    if (nestedArtboard->isCollapsed() || nestedArtboard->isHidden() ||
        nestedArtboard->isPaused())
    {
      return false;
    }
    Vec2D nestedPosition;
    if (!drawnPosition(nestedArtboard, position, &nestedPosition))
    {
      return false;
    }
    for (auto nestedAnimation : nestedArtboard->nestedAnimations())
    {
      if (nestedAnimation->is<NestedStateMachine>() &&
          nestedAnimation->as<NestedStateMachine>()->hitTestBounded(
              nestedPosition))
      {
        return true;
      }
    }
    return false;
  }
  /// Maps `position` into the nested artboard for a query only something
  /// drawn there can answer: false past the edge of a mesh the artboard is
  /// drawn through.
  static bool drawnPosition(
      NestedArtboard* nestedArtboard,
      Vec2D position,
      Vec2D* nestedPosition,
      Mat2D* toNested = nullptr)
  {
    bool offMesh;
    return nestedArtboard
               ->worldToLocal(position, nestedPosition, &offMesh, toNested) &&
           !offMesh;
  }
  /// Maps a parent-space delta into the nested artboard. A delta is a
  /// vector, so it takes only the linear part of the mapping at the pointer:
  /// through a mesh, that of the triangle under it, wherever the delta would
  /// end. Mapping the end point instead could land in another N-Slice tile.
  static Vec2D nestedDelta(const Mat2D& toNested, Vec2D delta)
  {
    return Vec2D::transformDir(delta, toNested);
  }

  bool wantsScroll(Vec2D position, const ScrollEvent& event) override
  {
    auto nestedArtboard = m_component->as<NestedArtboard>();
    if (nestedArtboard->isCollapsed() || nestedArtboard->isPaused())
    {
      return false;
    }
    Vec2D nestedPosition;
    Mat2D toNested;
    if (!drawnPosition(nestedArtboard, position, &nestedPosition, &toNested))
    {
      return false;
    }
    ScrollEvent mapped = event;
    mapped.delta = nestedDelta(toNested, event.delta);
    for (auto nestedAnimation : nestedArtboard->nestedAnimations())
    {
      if (nestedAnimation->is<NestedStateMachine>() &&
          nestedAnimation->as<NestedStateMachine>()->wantsScroll(
              nestedPosition,
              mapped))
      {
        return true;
      }
    }
    return false;
  }

  bool hasScrollTarget(Vec2D position) override
  {
    auto nestedArtboard = m_component->as<NestedArtboard>();
    if (nestedArtboard->isCollapsed() || nestedArtboard->isPaused())
    {
      return false;
    }
    Vec2D nestedPosition;
    if (!drawnPosition(nestedArtboard, position, &nestedPosition))
    {
      return false;
    }
    for (auto nestedAnimation : nestedArtboard->nestedAnimations())
    {
      if (nestedAnimation->is<NestedStateMachine>() &&
          nestedAnimation->as<NestedStateMachine>()->hasScrollTargetAt(
              nestedPosition))
      {
        return true;
      }
    }
    return false;
  }

  bool listensToButtonAt(Vec2D position, PointerButton button) override
  {
    auto nestedArtboard = m_component->as<NestedArtboard>();
    if (nestedArtboard->isCollapsed() || nestedArtboard->isHidden() ||
        nestedArtboard->isPaused())
    {
      return false;
    }
    Vec2D nestedPosition;
    if (!drawnPosition(nestedArtboard, position, &nestedPosition))
    {
      return false;
    }
    for (auto nestedAnimation : nestedArtboard->nestedAnimations())
    {
      if (nestedAnimation->is<NestedStateMachine>() &&
          nestedAnimation->as<NestedStateMachine>()->listensToButtonAt(
              nestedPosition,
              button))
      {
        return true;
      }
    }
    return false;
  }

  bool occludesScroll(Vec2D position) override
  {
    auto nestedArtboard = m_component->as<NestedArtboard>();
    if (nestedArtboard->isCollapsed() || nestedArtboard->isPaused())
    {
      return false;
    }
    Vec2D nestedPosition;
    if (!drawnPosition(nestedArtboard, position, &nestedPosition))
    {
      return false;
    }
    for (auto nestedAnimation : nestedArtboard->nestedAnimations())
    {
      if (nestedAnimation->is<NestedStateMachine>() &&
          nestedAnimation->as<NestedStateMachine>()->scrollOccludedAt(
              nestedPosition))
      {
        return true;
      }
    }
    return false;
  }

  bool scrollGestureActive() override
  {
    auto nestedArtboard = m_component->as<NestedArtboard>();
    if (nestedArtboard->isCollapsed() || nestedArtboard->isPaused())
    {
      // A paused machine never advances, so its idle timer can never
      // clear the latch. End it outright, or unpausing resurrects it.
      for (auto nestedAnimation : nestedArtboard->nestedAnimations())
      {
        if (nestedAnimation->is<NestedStateMachine>())
        {
          nestedAnimation->as<NestedStateMachine>()->cancelScroll();
        }
      }
      return false;
    }
    for (auto nestedAnimation : nestedArtboard->nestedAnimations())
    {
      if (nestedAnimation->is<NestedStateMachine>() &&
          nestedAnimation->as<NestedStateMachine>()->hasScrollLatch())
      {
        return true;
      }
    }
    return false;
  }

  HitResult processScroll(
      Vec2D position,
      const ScrollEvent& event,
      float timeStamp,
      int pointerId) override
  {
    auto nestedArtboard = m_component->as<NestedArtboard>();
    Vec2D nestedPosition;
    bool offMesh;
    Mat2D toNested;
    if (!nestedArtboard
             ->worldToLocal(position, &nestedPosition, &offMesh, &toNested))
    {
      return HitResult::none;
    }
    ScrollEvent mapped = event;
    mapped.delta = nestedDelta(toNested, event.delta);
    // A latched machine gets the event first; only then can another
    // take it.
    for (auto nestedAnimation : nestedArtboard->nestedAnimations())
    {
      if (nestedAnimation->is<NestedStateMachine>() &&
          nestedAnimation->as<NestedStateMachine>()->hasScrollLatch())
      {
        return nestedAnimation->as<NestedStateMachine>()
            ->pointerScroll(nestedPosition, mapped, timeStamp, pointerId);
      }
    }
    // Past the mesh's edge nothing is drawn to start a gesture on.
    if (offMesh)
    {
      return HitResult::none;
    }
    for (auto nestedAnimation : nestedArtboard->nestedAnimations())
    {
      if (!nestedAnimation->is<NestedStateMachine>())
      {
        continue;
      }
      auto result = nestedAnimation->as<NestedStateMachine>()->pointerScroll(
          nestedPosition,
          mapped,
          timeStamp,
          pointerId);
      if (result != HitResult::none)
      {
        return result;
      }
    }
    return HitResult::none;
  }

  HitResult processGamepadInvocation(
      const ListenerInvocation& invocation,
      ScriptedDrawable* alreadyDispatched) override
  {
    auto hitResult = HitResult::none;
    auto nestedArtboard = m_component->as<NestedArtboard>();
    for (auto nestedAnimation : nestedArtboard->nestedAnimations())
    {
      if (nestedAnimation->is<NestedStateMachine>())
      {
        auto nestedStateMachine = nestedAnimation->as<NestedStateMachine>();
        nestedStateMachine->stateMachineInstance()
            ->broadcastGamepadToScriptedDrawables(
                invocation,
                alreadyDispatched);
      }
    }
    return hitResult;
  }
  HitResult processEvent(
      Vec2D position,
      ListenerType hitType,
      bool canHit,
      float timeStamp,
      int pointerId,
      PointerButton button) override
  {
    auto nestedArtboard = m_component->as<NestedArtboard>();
    HitResult hitResult = HitResult::none;
    if (hitType == ListenerType::exit)
    {
      // The pointer left: the machines below forget it, and so does this.
      m_pointersOff.remove(pointerId);
    }
    if (nestedArtboard->isCollapsed() || nestedArtboard->isHidden() ||
        nestedArtboard->isPaused())
    {
      return hitResult;
    }
    Vec2D nestedPosition;
    bool offMesh;
    if (!nestedArtboard->worldToLocal(position, &nestedPosition, &offMesh))
    {
      // Mounted artboard isn't ready or has a 0 scale transform.
      return hitResult;
    }
    // Past the edge of the mesh it's drawn through, or while this machine
    // misses the pointer itself, nothing in the artboard can be hit, but a
    // drag in progress keeps following the pointer. Past the edge, this
    // machine's own drags (unless it's turned off, as below) still start and
    // end in there as misses too.
    const bool pastMesh = canHit && offMesh;
    const bool missesMesh = (isMissableEvent(hitType) &&
                             (pastMesh ||
                              m_stateMachineInstance->inPointerMiss())) ||
                            (isDragPass(hitType) && pastMesh &&
                             !m_pointersOff.has(pointerId));

    for (auto nestedAnimation : nestedArtboard->nestedAnimations())
    {
      if (nestedAnimation->is<NestedStateMachine>())
      {
        auto nestedStateMachine = nestedAnimation->as<NestedStateMachine>();
        m_pointersOff.keepOff(
            nestedStateMachine->stateMachineInstance(),
            pointerId);
        HostDispatchScope dispatch(nestedStateMachine->stateMachineInstance());
        if (missesMesh)
        {
          nestedStateMachine->pointerMiss(
              nestedPosition,
              hitType,
              timeStamp,
              pointerId,
              button);
        }
        else if (canHit)
        {
          switch (hitType)
          {
            case ListenerType::down:
              hitResult = nestedStateMachine->pointerDown(
                  nestedPosition,
                  pointerId,
                  button);
              break;
            case ListenerType::up:
              hitResult = nestedStateMachine->pointerUp(
                  nestedPosition,
                  pointerId,
                  button);
              break;
            case ListenerType::move:
              hitResult = nestedStateMachine->pointerMove(
                  nestedPosition,
                  timeStamp,
                  pointerId);
              break;
            // A machine this host turned off (its capture claim, or a drag
            // above) sits the host's drags out: their end would turn it
            // back on from below, inside the claim.
            case ListenerType::dragStart:
              if (!m_pointersOff.has(pointerId))
              {
                nestedStateMachine
                    ->dragStart(nestedPosition, timeStamp, pointerId, button);
              }
              break;
            case ListenerType::dragEnd:
              if (!m_pointersOff.has(pointerId))
              {
                nestedStateMachine
                    ->dragEnd(nestedPosition, timeStamp, pointerId, button);
              }
              break;
            case ListenerType::exit:
              hitResult = nestedStateMachine->pointerExit(
                  nestedPosition,
                  pointerId);
              break;
            case ListenerType::enter:
            case ListenerType::event:
            case ListenerType::click:
            case ListenerType::componentProvided:
            case ListenerType::textInput:
            case ListenerType::viewModel:
            case ListenerType::drag:
            case ListenerType::focus:
            case ListenerType::blur:
            case ListenerType::keyboard:
            case ListenerType::semanticAction:
            case ListenerType::gamepad:
              break;
          }
        }
        else
        {
          switch (hitType)
          {
            case ListenerType::down:
            case ListenerType::up:
            case ListenerType::move:
              // Something drawn above covers the pointer, which hasn't
              // left: a drag or claim here that turned it off still holds.
              if (auto smi = nestedStateMachine->stateMachineInstance())
              {
                smi->hoverExit(nestedPosition, pointerId);
              }
              break;
            case ListenerType::exit:
              nestedStateMachine->pointerExit(nestedPosition, pointerId);
              break;
            case ListenerType::dragStart:
            case ListenerType::dragEnd:
            case ListenerType::enter:
            case ListenerType::event:
            case ListenerType::click:
            case ListenerType::componentProvided:
            case ListenerType::textInput:
            case ListenerType::viewModel:
            case ListenerType::drag:
            case ListenerType::focus:
            case ListenerType::blur:
            case ListenerType::keyboard:
            case ListenerType::semanticAction:
            case ListenerType::gamepad:
              break;
          }
        }
      }
    }
    return hitResult;
  }
  void prepareEvent(Vec2D position, ListenerType hitType, int pointerId)
      override
  {}

  // A drag or a capture listener's claim turns off a pointer for the
  // nested machines too, not just for the host's own hit components.
  void enablePointerEvents(int pointerId) override
  {
    m_pointersOff.remove(pointerId);
    forEachStateMachine([pointerId](StateMachineInstance* smi) {
      smi->enablePointerEvents(pointerId);
    });
  }

  void disablePointerEvents(int pointerId) override
  {
    m_pointersOff.add(pointerId);
    forEachStateMachine([pointerId](StateMachineInstance* smi) {
      smi->disablePointerEvents(pointerId);
    });
  }

  bool hasCaptureListeners() override
  {
    bool has = false;
    forEachStateMachine([&](StateMachineInstance* smi) {
      if (!has && smi->hasCaptureListeners())
      {
        has = true;
      }
    });
    return has;
  }

  bool blocksCapture(Vec2D position) override
  {
    auto nestedArtboard = m_component->as<NestedArtboard>();
    if (nestedArtboard->isCollapsed() || nestedArtboard->isHidden() ||
        nestedArtboard->isPaused())
    {
      return false;
    }
    Vec2D nestedPosition;
    if (!drawnPosition(nestedArtboard, position, &nestedPosition))
    {
      return false;
    }
    bool blocks = false;
    forEachStateMachine([&](StateMachineInstance* smi) {
      if (!blocks && smi->pointerOccludedAt(nestedPosition))
      {
        blocks = true;
      }
    });
    return blocks;
  }

  HitResult capturePointer(
      Vec2D position,
      ListenerType hitType,
      int pointerId,
      float timeStamp,
      PointerButton button) override
  {
    auto nestedArtboard = m_component->as<NestedArtboard>();
    if (nestedArtboard->isCollapsed() || nestedArtboard->isHidden() ||
        nestedArtboard->isPaused())
    {
      return HitResult::none;
    }
    Vec2D nestedPosition;
    bool offMesh;
    if (!nestedArtboard->worldToLocal(position, &nestedPosition, &offMesh))
    {
      return HitResult::none;
    }
    // Past the edge of the mesh it's drawn through, its capture listeners
    // only see the pointer leave, as under an opaque hit drawn above.
    if (offMesh && isMissableEvent(hitType))
    {
      hitType = ListenerType::exit;
    }
    HitResult result = HitResult::none;
    forEachStateMachine([&](StateMachineInstance* smi) {
      m_pointersOff.keepOff(smi, pointerId);
      result = combineHitResults(
          result,
          smi->capturePointer(
              nestedPosition,
              hitType,
              pointerId,
              timeStamp,
              button));
    });
    return result;
  }

private:
  HostedPointersOff m_pointersOff;

  template <typename F> void forEachStateMachine(F&& visit)
  {
    auto nestedArtboard = m_component->as<NestedArtboard>();
    for (auto nestedAnimation : nestedArtboard->nestedAnimations())
    {
      if (!nestedAnimation->is<NestedStateMachine>())
      {
        continue;
      }
      if (auto smi = nestedAnimation->as<NestedStateMachine>()
                         ->stateMachineInstance())
      {
        visit(smi);
      }
    }
  }
};

class HitComponentList : public HitComponent
{
public:
  HitComponentList(
      Component* componentList,
      StateMachineInstance* stateMachineInstance)
      : HitComponent(componentList, stateMachineInstance)
  {}
  ~HitComponentList() override {}

  bool hitTest(Vec2D position) const override
  {
    auto componentList = m_component->as<ArtboardComponentList>();
    if (componentList->isCollapsed() || componentList->isHidden())
    {
      return false;
    }
    const auto& order = componentList->orderedListIndices();
    for (auto it = order.rbegin(); it != order.rend(); ++it)
    {
      const int i = *it;
      Vec2D listPosition;
      if (!componentList->worldToLocal(position, &listPosition, i))
      {
        // Mounted artboard isn't ready or has a 0 scale transform.
        continue;
      }
      auto stateMachine = componentList->stateMachineInstance(i);
      if (stateMachine != nullptr && stateMachine->hitTest(listPosition))
      {
        return true;
      }
    }
    return false;
  }
  bool hitTestBounded(Vec2D position) const override
  {
    auto componentList = m_component->as<ArtboardComponentList>();
    if (componentList->isCollapsed() || componentList->isHidden())
    {
      return false;
    }
    const auto& order = componentList->orderedListIndices();
    for (auto it = order.rbegin(); it != order.rend(); ++it)
    {
      const int i = *it;
      Vec2D listPosition;
      if (!componentList->worldToLocal(position, &listPosition, i))
      {
        continue;
      }
      auto stateMachine = componentList->stateMachineInstance(i);
      if (stateMachine != nullptr && stateMachine->hitTestBounded(listPosition))
      {
        return true;
      }
    }
    return false;
  }

  /// Maps a parent-space delta into item i. A delta is a vector, so it
  /// takes the mapping's linear part only.
  bool itemDelta(
      ArtboardComponentList* componentList,
      int i,
      Vec2D position,
      Vec2D listPosition,
      Vec2D delta,
      Vec2D& out)
  {
    Vec2D shifted;
    if (!componentList->worldToLocal(position + delta, &shifted, i))
    {
      return false;
    }
    out = shifted - listPosition;
    return true;
  }

  // Items walk top-most first, like processEvent, and an opaque item blocks
  // the items behind it the way hitOpaque clears runningCanHit there.
  bool wantsScroll(Vec2D position, const ScrollEvent& event) override
  {
    auto componentList = m_component->as<ArtboardComponentList>();
    if (componentList->isCollapsed())
    {
      return false;
    }
    const auto& order = componentList->orderedListIndices();
    for (auto it = order.rbegin(); it != order.rend(); ++it)
    {
      const int i = *it;
      Vec2D listPosition;
      if (!componentList->worldToLocal(position, &listPosition, i))
      {
        continue;
      }
      auto stateMachine = componentList->stateMachineInstance(i);
      if (stateMachine == nullptr)
      {
        continue;
      }
      ScrollEvent mapped = event;
      if (!itemDelta(
              componentList,
              i,
              position,
              listPosition,
              event.delta,
              mapped.delta))
      {
        continue;
      }
      if (stateMachine->wantsScroll(listPosition, mapped))
      {
        return true;
      }
      if (stateMachine->scrollOccludedAt(listPosition))
      {
        return false;
      }
    }
    return false;
  }

  bool hasScrollTarget(Vec2D position) override
  {
    auto componentList = m_component->as<ArtboardComponentList>();
    if (componentList->isCollapsed())
    {
      return false;
    }
    const auto& order = componentList->orderedListIndices();
    for (auto it = order.rbegin(); it != order.rend(); ++it)
    {
      const int i = *it;
      Vec2D listPosition;
      if (!componentList->worldToLocal(position, &listPosition, i))
      {
        continue;
      }
      auto stateMachine = componentList->stateMachineInstance(i);
      if (stateMachine == nullptr)
      {
        continue;
      }
      if (stateMachine->hasScrollTargetAt(listPosition))
      {
        return true;
      }
      if (stateMachine->scrollOccludedAt(listPosition))
      {
        return false;
      }
    }
    return false;
  }

  bool listensToButtonAt(Vec2D position, PointerButton button) override
  {
    auto componentList = m_component->as<ArtboardComponentList>();
    if (componentList->isCollapsed() || componentList->isHidden())
    {
      return false;
    }
    const auto& order = componentList->orderedListIndices();
    for (auto it = order.rbegin(); it != order.rend(); ++it)
    {
      const int i = *it;
      Vec2D listPosition;
      if (!componentList->worldToLocal(position, &listPosition, i))
      {
        continue;
      }
      auto stateMachine = componentList->stateMachineInstance(i);
      if (stateMachine != nullptr &&
          stateMachine->listensToButtonAt(listPosition, button))
      {
        return true;
      }
    }
    return false;
  }

  bool occludesScroll(Vec2D position) override
  {
    auto componentList = m_component->as<ArtboardComponentList>();
    if (componentList->isCollapsed())
    {
      return false;
    }
    const auto& order = componentList->orderedListIndices();
    for (auto it = order.rbegin(); it != order.rend(); ++it)
    {
      const int i = *it;
      Vec2D listPosition;
      if (!componentList->worldToLocal(position, &listPosition, i))
      {
        continue;
      }
      auto stateMachine = componentList->stateMachineInstance(i);
      if (stateMachine != nullptr &&
          stateMachine->scrollOccludedAt(listPosition))
      {
        return true;
      }
    }
    return false;
  }

  bool scrollGestureActive() override
  {
    auto componentList = m_component->as<ArtboardComponentList>();
    const auto& order = componentList->orderedListIndices();
    if (componentList->isCollapsed())
    {
      // A collapsed list never advances its items, so an idle timer
      // there can never clear the latch. End it outright.
      for (int i : order)
      {
        auto stateMachine = componentList->stateMachineInstance(i);
        if (stateMachine != nullptr)
        {
          stateMachine->cancelScroll();
        }
      }
      return false;
    }
    for (int i : order)
    {
      auto stateMachine = componentList->stateMachineInstance(i);
      if (stateMachine != nullptr && stateMachine->hasScrollLatch())
      {
        return true;
      }
    }
    return false;
  }

  void cancelScroll() override
  {
    auto componentList = m_component->as<ArtboardComponentList>();
    for (int i : componentList->orderedListIndices())
    {
      auto stateMachine = componentList->stateMachineInstance(i);
      if (stateMachine != nullptr)
      {
        stateMachine->cancelScroll();
      }
    }
  }

  HitResult processScroll(
      Vec2D position,
      const ScrollEvent& event,
      float timeStamp,
      int pointerId) override
  {
    auto componentList = m_component->as<ArtboardComponentList>();
    if (componentList->isCollapsed())
    {
      return HitResult::none;
    }
    const auto& order = componentList->orderedListIndices();
    // A latched item gets the event first; only then can another take it.
    for (int pass = 0; pass < 2; pass++)
    {
      for (auto it = order.rbegin(); it != order.rend(); ++it)
      {
        const int i = *it;
        auto stateMachine = componentList->stateMachineInstance(i);
        if (stateMachine == nullptr ||
            (pass == 0 && !stateMachine->hasScrollLatch()))
        {
          continue;
        }
        Vec2D listPosition;
        if (!componentList->worldToLocal(position, &listPosition, i))
        {
          continue;
        }
        ScrollEvent mapped = event;
        if (!itemDelta(
                componentList,
                i,
                position,
                listPosition,
                event.delta,
                mapped.delta))
        {
          continue;
        }
        auto result = stateMachine->pointerScroll(
            listPosition,
            mapped,
            timeStamp,
            pointerId);
        if (pass == 0 || result != HitResult::none)
        {
          return result;
        }
        if (stateMachine->scrollOccludedAt(listPosition))
        {
          return HitResult::none;
        }
      }
    }
    return HitResult::none;
  }

  HitResult processEvent(
      Vec2D position,
      ListenerType hitType,
      bool canHit,
      float timeStamp,
      int pointerId,
      PointerButton button) override
  {
    auto componentList = m_component->as<ArtboardComponentList>();
    HitResult hitResult = HitResult::none;
    bool runningCanHit = canHit;
    if (hitType == ListenerType::exit)
    {
      // See HitNestedArtboard::processEvent.
      m_pointersOff.remove(pointerId);
    }
    if (componentList->isCollapsed() || componentList->isHidden())
    {
      return hitResult;
    }
    const auto& order = componentList->orderedListIndices();
    for (auto it = order.rbegin(); it != order.rend(); ++it)
    {
      const int i = *it;
      Vec2D listPosition;
      bool hit = componentList->worldToLocal(position, &listPosition, i);
      if (!hit)
      {
        continue;
      }
      auto stateMachine = componentList->stateMachineInstance(i);
      if (stateMachine != nullptr)
      {
        m_pointersOff.keepOff(stateMachine, pointerId);
        HostDispatchScope dispatch(stateMachine);
        HitResult itemHitResult = HitResult::none;
        if (runningCanHit)
        {
          switch (hitType)
          {
            case ListenerType::down:
              itemHitResult = stateMachine->pointerDown(
                  listPosition,
                  pointerId,
                  button);
              break;
            case ListenerType::up:
              itemHitResult = stateMachine->pointerUp(
                  listPosition,
                  pointerId,
                  button);
              break;
            case ListenerType::move:
              itemHitResult = stateMachine->pointerMove(
                  listPosition,
                  timeStamp,
                  pointerId);
              break;
            case ListenerType::exit:
              itemHitResult = stateMachine->pointerExit(
                  listPosition,
                  pointerId);
              break;
            // See HitNestedArtboard::processEvent.
            case ListenerType::dragStart:
              if (!m_pointersOff.has(pointerId))
              {
                stateMachine
                    ->dragStart(listPosition, 0, true, pointerId, button);
              }
              break;
            case ListenerType::dragEnd:
              if (!m_pointersOff.has(pointerId))
              {
                stateMachine->dragEnd(listPosition, 0, pointerId, button);
              }
              break;
            case ListenerType::enter:
            case ListenerType::event:
            case ListenerType::click:
            case ListenerType::componentProvided:
            case ListenerType::textInput:
            case ListenerType::viewModel:
            case ListenerType::drag:
            case ListenerType::focus:
            case ListenerType::blur:
            case ListenerType::keyboard:
            case ListenerType::semanticAction:
            case ListenerType::gamepad:
              break;
          }
        }
        else if (
            isMissableEvent(hitType) && m_stateMachineInstance->inPointerMiss())
        {
          stateMachine->pointerMiss(
              listPosition,
              hitType,
              timeStamp,
              pointerId,
              button);
        }
        else
        {
          switch (hitType)
          {
            case ListenerType::down:
            case ListenerType::up:
            case ListenerType::move:
              // Covered by an item or something drawn above, not left: see
              // HitNestedArtboard::processEvent.
              stateMachine->hoverExit(listPosition, pointerId);
              break;
            case ListenerType::exit:
              stateMachine->pointerExit(listPosition, pointerId);
              break;
            case ListenerType::dragStart:
            case ListenerType::dragEnd:
            case ListenerType::enter:
            case ListenerType::event:
            case ListenerType::click:
            case ListenerType::componentProvided:
            case ListenerType::textInput:
            case ListenerType::viewModel:
            case ListenerType::drag:
            case ListenerType::focus:
            case ListenerType::blur:
            case ListenerType::keyboard:
            case ListenerType::semanticAction:
            case ListenerType::gamepad:
              break;
          }
        }
        if ((hitResult == HitResult::none &&
             (itemHitResult == HitResult::hit ||
              itemHitResult == HitResult::hitOpaque)) ||
            (hitResult == HitResult::hit &&
             itemHitResult == HitResult::hitOpaque))
        {
          hitResult = itemHitResult;
        }
        if (hitResult == HitResult::hitOpaque)
        {
          runningCanHit = false;
        }
      }
    }
    return hitResult;
  }
  HitResult processGamepadInvocation(
      const ListenerInvocation& invocation,
      ScriptedDrawable* alreadyDispatched) override
  {
    auto componentList = m_component->as<ArtboardComponentList>();
    HitResult hitResult = HitResult::none;
    bool runningCanHit = true;
    if (componentList->isCollapsed())
    {
      return hitResult;
    }
    const auto& order = componentList->orderedListIndices();
    for (auto it = order.rbegin(); it != order.rend(); ++it)
    {
      const int i = *it;
      auto stateMachine = componentList->stateMachineInstance(i);
      if (stateMachine != nullptr)
      {
        HitResult itemHitResult = HitResult::none;
        if (runningCanHit)
        {
          itemHitResult = stateMachine->broadcastGamepadToScriptedDrawables(
              invocation,
              alreadyDispatched);
        }

        if ((hitResult == HitResult::none &&
             (itemHitResult == HitResult::hit ||
              itemHitResult == HitResult::hitOpaque)) ||
            (hitResult == HitResult::hit &&
             itemHitResult == HitResult::hitOpaque))
        {
          hitResult = itemHitResult;
        }
        if (hitResult == HitResult::hitOpaque)
        {
          runningCanHit = false;
        }
      }
    }
    return hitResult;
  }
  void prepareEvent(Vec2D position, ListenerType hitType, int pointerId)
      override
  {}

  void enablePointerEvents(int pointerId) override
  {
    m_pointersOff.remove(pointerId);
    auto componentList = m_component->as<ArtboardComponentList>();
    for (int i : componentList->orderedListIndices())
    {
      if (auto stateMachine = componentList->stateMachineInstance(i))
      {
        stateMachine->enablePointerEvents(pointerId);
      }
    }
  }

  void disablePointerEvents(int pointerId) override
  {
    m_pointersOff.add(pointerId);
    auto componentList = m_component->as<ArtboardComponentList>();
    for (int i : componentList->orderedListIndices())
    {
      if (auto stateMachine = componentList->stateMachineInstance(i))
      {
        stateMachine->disablePointerEvents(pointerId);
      }
    }
  }

  bool hasCaptureListeners() override
  {
    auto componentList = m_component->as<ArtboardComponentList>();
    for (int i : componentList->orderedListIndices())
    {
      auto stateMachine = componentList->stateMachineInstance(i);
      if (stateMachine != nullptr && stateMachine->hasCaptureListeners())
      {
        return true;
      }
    }
    return false;
  }

  bool blocksCapture(Vec2D position) override
  {
    auto componentList = m_component->as<ArtboardComponentList>();
    if (componentList->isCollapsed() || componentList->isHidden())
    {
      return false;
    }
    for (int i : componentList->orderedListIndices())
    {
      Vec2D listPosition;
      if (!componentList->worldToLocal(position, &listPosition, i))
      {
        continue;
      }
      auto stateMachine = componentList->stateMachineInstance(i);
      if (stateMachine != nullptr &&
          stateMachine->pointerOccludedAt(listPosition))
      {
        return true;
      }
    }
    return false;
  }

  // Items run top-most first, and an opaque item hides the items behind
  // it, which then only see the pointer leave -- as in processEvent. Only
  // items with a capture listener somewhere inside are visited, and the
  // items above them only tested as far as needed.
  HitResult capturePointer(
      Vec2D position,
      ListenerType hitType,
      int pointerId,
      float timeStamp,
      PointerButton button) override
  {
    auto componentList = m_component->as<ArtboardComponentList>();
    if (componentList->isCollapsed() || componentList->isHidden())
    {
      return HitResult::none;
    }
    HitResult result = HitResult::none;
    bool occluded = false;
    const auto& order = componentList->orderedListIndices();
    const size_t count = order.size();
    // Items are counted top-most first; this many have been tested.
    size_t tested = 0;
    for (size_t item = 0; item < count; item++)
    {
      const int i = order[count - 1 - item];
      auto stateMachine = componentList->stateMachineInstance(i);
      if (stateMachine == nullptr || !stateMachine->hasCaptureListeners())
      {
        continue;
      }
      Vec2D listPosition;
      if (!componentList->worldToLocal(position, &listPosition, i))
      {
        continue;
      }
      for (; !occluded && tested < item; tested++)
      {
        const int above = order[count - 1 - tested];
        auto aboveMachine = componentList->stateMachineInstance(above);
        Vec2D abovePosition;
        if (aboveMachine != nullptr &&
            componentList->worldToLocal(position, &abovePosition, above) &&
            aboveMachine->pointerOccludedAt(abovePosition))
        {
          occluded = true;
        }
      }
      m_pointersOff.keepOff(stateMachine, pointerId);
      result = combineHitResults(
          result,
          stateMachine->capturePointer(
              listPosition,
              occluded ? ListenerType::exit : hitType,
              pointerId,
              timeStamp,
              button));
    }
    return result;
  }

private:
  HostedPointersOff m_pointersOff;
};

#ifdef WITH_RIVE_TEXT
/// Forwards pointer events to the state machines of a Text's styles that
/// listen to the runs drawn with them (see
/// StateMachineInstance::serveTextStyle). Styles and their instances come and
/// go (list updates, style swaps), so they are looked up on every event,
/// never kept.
class HitTextStyleRuns : public HitComponent
{
public:
  HitTextStyleRuns(Text* text, StateMachineInstance* stateMachineInstance)
      : HitComponent(text, stateMachineInstance)
  {}

  Text* text() const { return m_component->as<Text>(); }

  bool hidden() const
  {
    auto text = this->text();
    return text->isCollapsed() || text->isHidden();
  }

  bool hitTest(Vec2D position) const override
  {
    if (hidden())
    {
      return false;
    }
    std::vector<StateMachineInstance*> stateMachines;
    text()->runStateMachines(stateMachines);
    for (auto stateMachine : stateMachines)
    {
      if (stateMachine->hitTest(position))
      {
        return true;
      }
    }
    return false;
  }

  bool listensToButtonAt(Vec2D position, PointerButton button) override
  {
    if (hidden())
    {
      return false;
    }
    m_stateMachines.clear();
    text()->runStateMachines(m_stateMachines);
    for (auto stateMachine : m_stateMachines)
    {
      if (stateMachine->listensToButtonAt(position, button))
      {
        return true;
      }
    }
    return false;
  }

  HitResult processEvent(
      Vec2D position,
      ListenerType hitType,
      bool canHit,
      float timeStamp,
      int pointerId,
      PointerButton button) override
  {
    HitResult hitResult = HitResult::none;
    bool runningCanHit = canHit && !hidden();
    // Collected first: a listener may change the styles while this walks
    // them.
    m_stateMachines.clear();
    text()->runStateMachines(m_stateMachines);
    for (auto stateMachine : m_stateMachines)
    {
      HitResult styleHitResult = HitResult::none;
      if (runningCanHit)
      {
        switch (hitType)
        {
          case ListenerType::down:
            styleHitResult = stateMachine->pointerDown(
                position,
                pointerId,
                button);
            break;
          case ListenerType::up:
            styleHitResult = stateMachine->pointerUp(
                position,
                pointerId,
                button);
            break;
          case ListenerType::move:
            styleHitResult = stateMachine->pointerMove(
                position,
                timeStamp,
                pointerId);
            break;
          case ListenerType::exit:
            styleHitResult = stateMachine->pointerExit(position, pointerId);
            break;
          case ListenerType::dragStart:
            stateMachine->dragStart(position, 0, true, pointerId, button);
            break;
          case ListenerType::dragEnd:
            stateMachine->dragEnd(position, 0, pointerId, button);
            break;
          default:
            break;
        }
      }
      else if (
          isMissableEvent(hitType) && m_stateMachineInstance->inPointerMiss())
      {
        stateMachine
            ->pointerMiss(position, hitType, timeStamp, pointerId, button);
      }
      else
      {
        switch (hitType)
        {
          case ListenerType::down:
          case ListenerType::up:
          case ListenerType::move:
          case ListenerType::exit:
            stateMachine->pointerExit(position, pointerId);
            break;
          default:
            break;
        }
      }
      if (stateMachine->needsAdvance())
      {
        m_stateMachineInstance->markNeedsAdvance();
      }
      if ((hitResult == HitResult::none &&
           (styleHitResult == HitResult::hit ||
            styleHitResult == HitResult::hitOpaque)) ||
          (hitResult == HitResult::hit &&
           styleHitResult == HitResult::hitOpaque))
      {
        hitResult = styleHitResult;
      }
      if (hitResult == HitResult::hitOpaque)
      {
        runningCanHit = false;
      }
    }
    return hitResult;
  }

  HitResult processGamepadInvocation(
      const ListenerInvocation& invocation,
      ScriptedDrawable* alreadyDispatched) override
  {
    return HitResult::none;
  }

  void prepareEvent(Vec2D position, ListenerType hitType, int pointerId)
      override
  {}

private:
  // Reused across events.
  std::vector<StateMachineInstance*> m_stateMachines;
};

/// The runs of a Text drawn with one style, which the pointer listeners with
/// no target in that style's state machine listen to as one target (see
/// StateMachineInstance::serveTextStyle). Runs come and go and change styles
/// (list updates, swaps), so they're found on every hit test, never kept; the
/// Text makes them hit targets.
class HitTextStyleTarget : public HitDrawable
{
public:
  HitTextStyleTarget(
      Text* text,
      const TextStyleReference* style,
      StateMachineInstance* stateMachineInstance)
      : HitDrawable(text, text, stateMachineInstance, false)
      , m_style(style)
  {}

  bool hitTest(Vec2D position) const override
  {
    for (auto run : m_drawable->as<Text>()->runs())
    {
      if (run->styleReference() == m_style &&
          run->hitTestPoint(position, true, true))
      {
        return true;
      }
    }
    return false;
  }

private:
  const TextStyleReference* m_style;
};
#endif

class ListenerViewModel;

// Helper that holds one view model property reference, listens to its dirt,
// and reports the parent ListenerViewModel when the property changes.
class ListenerViewModelPropertyBinding : public ViewModelValueDependent
{
public:
  ListenerViewModelPropertyBinding(
      ListenerViewModel* parent,
      ViewModelInstanceValue* vmProp);
  virtual ~ListenerViewModelPropertyBinding();
  void addDirt(ComponentDirt value, bool recurse) override;
  void relinkDataBind() override;
  ViewModelInstanceValue* value() { return m_viewModelInstanceValue.get(); }

protected:
  ListenerViewModel* m_parent = nullptr;
  rive::rcp<ViewModelInstanceValue> m_viewModelInstanceValue = nullptr;
  void clearDataContext();
};
class ListenerViewModelPropertyBindingListener
    : public ListenerViewModelPropertyBinding
{
public:
  ListenerViewModelPropertyBindingListener(
      ListenerViewModel* parent,
      ViewModelInstanceValue* vmProp,
      const StateMachineListenerSingle* listener);
  void relinkDataBind() override;

private:
  const StateMachineListenerSingle* m_listener;
};
class ListenerViewModelPropertyBindingInput
    : public ListenerViewModelPropertyBinding
{
public:
  ListenerViewModelPropertyBindingInput(
      ListenerViewModel* parent,
      ViewModelInstanceValue* vmProp,
      const ListenerInputTypeViewModel* listenerInput);
  void relinkDataBind() override;

private:
  const ListenerInputTypeViewModel* m_listenerInput;
};

class ListenerViewModel
{
public:
  virtual ~ListenerViewModel();
  ListenerViewModel(
      StateMachineInstance* smInstance,
      const StateMachineListener* listener)
      : m_stateMachineInstance(smInstance)
      , m_listener(listener)
  {}

  void clearDataContext() { m_propertyBindings.clear(); }
  void bindFromContext(rcp<DataContext> dataContext)
  {
    m_dataContext = dataContext;
    clearDataContext();
    if (m_listener->is<StateMachineListenerSingle>())
    {
      auto vmProp = dataContext->getViewModelProperty(
          m_listener->as<StateMachineListenerSingle>()->dataBindPath());
      if (vmProp != nullptr)
      {
        m_propertyBindings.push_back(
            std::make_unique<ListenerViewModelPropertyBindingListener>(
                this,
                vmProp,
                m_listener->as<StateMachineListenerSingle>()));
      }
    }
    else
    {
      size_t index = 0;
      while (index < m_listener->listenerInputTypeCount())
      {
        auto listenerInputType = m_listener->listenerInputType(index);
        if (listenerInputType->is<ListenerInputTypeViewModel>())
        {
          auto listenerInputTypeVM = listenerInputType
                                         ->as<ListenerInputTypeViewModel>();
          auto vmProp = dataContext->getViewModelProperty(
              listenerInputTypeVM->dataBindPath());
          if (vmProp != nullptr)
          {
            m_propertyBindings.push_back(
                std::make_unique<ListenerViewModelPropertyBindingInput>(
                    this,
                    vmProp,
                    listenerInputTypeVM));
          }
        }
        index++;
      }
    }
    for (auto& binding : m_propertyBindings)
    {
      reportIfPending(binding->value());
    }
  }
  void reportToStateMachine()
  {
    m_stateMachineInstance->reportListenerViewModel(this);
  }
  // A trigger fired before this listener was listening to it can still be
  // pending (fired by a script's init(), which runs as the artboard binds,
  // before this does, or by the host before binding): report it so it isn't
  // lost. A fire whose frame has passed isn't, so it isn't replayed.
  void reportIfPending(ViewModelInstanceValue* value)
  {
    if (value != nullptr && value->is<ViewModelInstanceTrigger>() &&
        m_stateMachineInstance->viewModelTriggerPendingForListeners(value))
    {
      reportToStateMachine();
    }
  }
  const StateMachineListener* listener() { return m_listener; }
  DataContext* dataContext()
  {
    if (m_dataContext)
    {

      return m_dataContext.get();
    }
    return nullptr;
  }

private:
  StateMachineInstance* m_stateMachineInstance = nullptr;
  const StateMachineListener* m_listener = nullptr;
  rcp<DataContext> m_dataContext = nullptr;
  std::vector<std::unique_ptr<ListenerViewModelPropertyBinding>>
      m_propertyBindings;
};

ListenerViewModelPropertyBinding::ListenerViewModelPropertyBinding(
    ListenerViewModel* parent,
    ViewModelInstanceValue* vmProp)
    : m_parent(parent)
    , m_viewModelInstanceValue(rive::ref_rcp(vmProp))
{
  vmProp->addDependent(this);
}

void ListenerViewModelPropertyBinding::relinkDataBind() {}

ListenerViewModelPropertyBinding::~ListenerViewModelPropertyBinding()
{
  clearDataContext();
}

void ListenerViewModelPropertyBinding::clearDataContext()
{

  if (m_viewModelInstanceValue != nullptr)
  {
    m_viewModelInstanceValue->removeDependent(this);
    m_viewModelInstanceValue = nullptr;
  }
}

ListenerViewModelPropertyBindingListener::
    ListenerViewModelPropertyBindingListener(
        ListenerViewModel* parent,
        ViewModelInstanceValue* vmProp,
        const StateMachineListenerSingle* listener)
    : ListenerViewModelPropertyBinding(parent, vmProp)
    , m_listener(listener)
{}

void ListenerViewModelPropertyBindingListener::relinkDataBind()
{
  auto dataContext = m_parent->dataContext();
  if (dataContext)
  {

    auto vmProp = dataContext->getViewModelProperty(m_listener->dataBindPath());
    if (vmProp != m_viewModelInstanceValue.get())
    {
      clearDataContext();
      if (vmProp != nullptr)
      {
        m_viewModelInstanceValue = ref_rcp(vmProp);
        vmProp->addDependent(this);
        m_parent->reportIfPending(vmProp);
      }
    }
  }
}

ListenerViewModelPropertyBindingInput::ListenerViewModelPropertyBindingInput(
    ListenerViewModel* parent,
    ViewModelInstanceValue* vmProp,
    const ListenerInputTypeViewModel* listenerInput)
    : ListenerViewModelPropertyBinding(parent, vmProp)
    , m_listenerInput(listenerInput)
{}

void ListenerViewModelPropertyBindingInput::relinkDataBind()
{
  auto dataContext = m_parent->dataContext();
  if (dataContext)
  {
    auto vmProp = dataContext->getViewModelProperty(
        m_listenerInput->dataBindPath());
    if (vmProp != m_viewModelInstanceValue.get())
    {
      clearDataContext();
      if (vmProp != nullptr)
      {
        m_viewModelInstanceValue = ref_rcp(vmProp);
        vmProp->addDependent(this);
        m_parent->reportIfPending(vmProp);
      }
    }
  }
}

void ListenerViewModelPropertyBinding::addDirt(
    ComponentDirt value,
    bool recurse)
{
  // Every change reports, a trigger's included: its count only changes
  // when it fires.
  if (m_parent != nullptr && m_viewModelInstanceValue != nullptr)
  {
    m_parent->reportToStateMachine();
  }
}

ListenerViewModel::~ListenerViewModel() { clearDataContext(); }

} // namespace rive

HitResult StateMachineInstance::updateListeners(
    Vec2D position,
    ListenerType hitType,
    int pointerId,
    float timeStamp,
    PointerButton button)
{
  const Vec2D hostPosition = position;
  // A primary press may take focus from the focused component when it lands
  // outside it (FocusManager::pressEnded). Only the root sees every press in
  // root space; a nested instance gets a press in its own space, and only
  // when it lands inside it. It begins ahead of the capture phase, whose
  // listeners can move focus too: focus a press moved is not blurred by it.
  FocusManager* pressFocusManager = nullptr;
  if (hitType == ListenerType::down && button == PointerButton::primary &&
      m_artboardInstance != nullptr && m_artboardInstance->isRoot())
  {
    pressFocusManager = focusManager();
  }
  if (pressFocusManager != nullptr)
  {
    pressFocusManager->pressBegan();
  }
  // The capture phase runs once per event, from the root of the dispatch,
  // over every machine in the tree; the machines it reaches through the
  // normal phase below must not run it again. Skipped outright while
  // nothing anywhere has a capture listener. A miss reaches capture
  // listeners as the pointer leaving, as off a nested mesh in a host's
  // capture pass.
  HitResult captureResult = HitResult::none;
  if (!m_hostDispatching && !m_captureRunByHost &&
      s_liveCaptureMachines.load(std::memory_order_relaxed) != 0 &&
      treeHasCaptureListeners())
  {
    captureResult = capturePointer(
        position,
        m_inPointerMiss && isMissableEvent(hitType) ? ListenerType::exit
                                                    : hitType,
        pointerId,
        timeStamp,
        button);
  }

  // Listener hit-testing runs in content space, so undo the frame origin and
  // the artboard's own rotation/scale first.
  //
  // A degenerate (0 scale) self transform has no inverse: the contents
  // collapse to nothing, so nothing in them can be hit. We still run the pass
  // with every group forced to miss rather than returning early, so hover
  // unwinds and pending exits fire, and we cancel any gesture in flight so a
  // press held across the collapse can't resume when the scale comes back.
  bool contentsCollapsed = !mapToContentSpace(position);

  // First reset all listener groups before processing the events
  for (const auto& listenerGroup : m_listenerGroups)
  {
    listenerGroup.get()->reset(pointerId);
  }
  // Drag ends owed by cancellation, dispatched once the pass below has had a
  // chance to emit its hover exits.
  std::vector<std::pair<int, PointerButton>> dragEnded;
  if (contentsCollapsed)
  {
    // canHit alone won't do this: it marks a target as occluded, and an
    // occluded target deliberately keeps its press so a drag survives the
    // pointer moving over other things (see ListenerGroup::processEvent,
    // where the phase only resets on down/up and the drag branch ignores
    // canHit). Collapsed content isn't occluded, it's gone.
    //
    // Every tracked pointer is cancelled, not just the one that delivered
    // this event: the contents are gone for all of them. The drag ends are
    // only collected here -- dispatching one re-enters updateListeners,
    // whose reset() overwrites isPrevHovered with the isHovered this pass
    // already cleared, so any exit still pending would be swallowed, and
    // whose enablePointerEvents() resets every group's phase, so groups not
    // yet cancelled would look like they had nothing in flight.
    for (const auto& listenerGroup : m_listenerGroups)
    {
      listenerGroup.get()->cancelPointers(position, timeStamp, dragEnded);
    }
  }
  else
  {
    // Next prepare the event to set the common hover status for each group.
    // Skipped when collapsed so every group stays unhovered.
    for (const auto& hitShape : m_hitComponents)
    {
      hitShape->prepareEvent(position, hitType, pointerId);
    }
  }
  bool hitSomething = false;
  bool hitOpaque = false;
  // Process the events
  for (const auto& hitShape : m_hitComponents)
  {
    HitResult hitResult = hitShape->processEvent(
        position,
        hitType,
        !m_inPointerMiss && !hitOpaque && !contentsCollapsed,
        timeStamp,
        pointerId,
        button);
    if (hitResult != HitResult::none)
    {
      hitSomething = true;
      if (hitResult == HitResult::hitOpaque)
      {
        hitOpaque = true;
      }
    }
  }
  // Hover exits have been emitted, so it's safe to let dragEnd re-enter now.
  for (auto& ended : dragEnded)
  {
    dragEnd(position, timeStamp, ended.first, ended.second);
  }
  if (pressFocusManager != nullptr)
  {
    pressFocusManager->pressEnded(position);
  }
  // Finally release events that are complete
  if (hitType == ListenerType::exit)
  {
    for (const auto& listenerGroup : m_listenerGroups)
    {
      listenerGroup.get()->releaseEvent(pointerId);
    }
    // A pointer that left is forgotten everywhere here: the capture groups
    // too, which a host's capture pass reached first, and whatever turned
    // it off from outside. hoverExit turns it back off for a pointer that
    // only passed under something drawn above.
    if (auto* extras = inputExtras())
    {
      for (const auto& group : extras->captureGroups)
      {
        group->releaseEvent(pointerId);
      }
    }
    m_disabledPointerIds.eraseAll(pointerId);
  }
  // A claimed gesture ends with its release, which the pass above has just
  // kept from the claimed targets. They come back on now, and a move puts
  // their hover back where the pointer is, as dragEnd does.
  if ((hitType == ListenerType::up || hitType == ListenerType::exit) &&
      releasePointerClaims(pointerId, button, hitType == ListenerType::exit) &&
      hitType == ListenerType::up)
  {
    pointerMove(hostPosition, timeStamp, pointerId);
  }

  return combineHitResults(
      captureResult,
      hitSomething ? hitOpaque ? HitResult::hitOpaque : HitResult::hit
                   : HitResult::none);
}

HitResult StateMachineInstance::capturePointer(
    Vec2D position,
    ListenerType hitType,
    int pointerId,
    float timeStamp,
    PointerButton button)
{
  if (s_liveCaptureMachines.load(std::memory_order_relaxed) == 0)
  {
    return HitResult::none;
  }
#ifdef TESTING
  sm_capturePassVisits++;
#endif
  auto* extras = inputExtras();
  const bool hasLocal = extras != nullptr && !extras->captureHits.empty();
  if (!hasLocal && m_artboardInstance->nestedArtboards().empty() &&
      m_artboardInstance->artboardComponentLists().empty())
  {
    return HitResult::none;
  }
  // Collapsed contents hit nothing; the pass still runs so hover unwinds.
  const bool collapsed = !mapToContentSpace(position);
  HitResult result = HitResult::none;
  if (hasLocal)
  {
    result = captureLocalPointer(
        position,
        hitType,
        pointerId,
        timeStamp,
        button,
        collapsed);
  }
  // Then the nested machines, which only come after every capture listener
  // here: a host's capture listener runs before any of its contents'. Only
  // hosts with a capture listener somewhere inside are visited, and what is
  // drawn above them only tested as far as the lowest of those. One under an
  // opaque hit drawn above it only sees the pointer leave, as in the normal
  // phase.
  bool occluded = collapsed;
  size_t tested = 0;
  for (size_t i = 0; i < m_hitComponents.size(); i++)
  {
    auto hitComponent = m_hitComponents[i].get();
    if (!hitComponent->hasCaptureListeners())
    {
      continue;
    }
    for (; !occluded && tested < i; tested++)
    {
      if (m_hitComponents[tested]->blocksCapture(position))
      {
        occluded = true;
      }
    }
    result = combineHitResults(
        result,
        hitComponent->capturePointer(
            position,
            occluded ? ListenerType::exit : hitType,
            pointerId,
            timeStamp,
            button));
  }
  return result;
}

HitResult StateMachineInstance::captureLocalPointer(
    Vec2D position,
    ListenerType hitType,
    int pointerId,
    float timeStamp,
    PointerButton button,
    bool collapsed)
{
  auto& extras = *inputExtras();
  // A claim lasts until its release. One still here at the next press of
  // its button lost its release on the way (the machine wasn't reached for
  // it), so it goes before this press can take a new one. A press of
  // another button says nothing about it: both can be held.
  if (hitType == ListenerType::down)
  {
    releasePointerClaims(pointerId, button, false);
  }
  for (const auto& group : extras.captureGroups)
  {
    group->reset(pointerId);
  }
  std::vector<std::pair<int, PointerButton>> dragEnded;
  if (collapsed)
  {
    // As in updateListeners: contents that are gone can't hold a press.
    for (const auto& group : extras.captureGroups)
    {
      group->cancelPointers(position, timeStamp, dragEnded);
    }
  }
  else if (hitType != ListenerType::exit)
  {
    for (const auto& captureHit : extras.captureHits)
    {
      if (!captureHit.group->isPointerDisabled(pointerId) &&
          captureHit.hit->hitTest(position))
      {
        captureHit.group->hover(pointerId);
      }
    }
  }

  // What is drawn above each capture target and opaque under the pointer.
  // A target's own contents don't count: a layout's children always draw
  // over it, and an opaque one among them is part of what it captures for.
  struct Occluder
  {
    size_t drawIndex;
    Component* component;
  };
  std::vector<Occluder> occluders;
  if (!collapsed && hitType != ListenerType::exit)
  {
    size_t lowest = 0;
    for (const auto& captureHit : extras.captureHits)
    {
      lowest = std::max(lowest, captureHit.drawIndex);
    }
    for (size_t i = 0; i < lowest && i < m_hitComponents.size(); i++)
    {
      auto hitComponent = m_hitComponents[i].get();
      if (hitComponent->blocksCapture(position))
      {
        occluders.push_back({i, hierarchyComponent(hitComponent)});
      }
    }
  }

  HitResult result = HitResult::none;
  for (size_t i = 0; i < extras.captureHits.size(); i++)
  {
    // By index: a listener's actions can claim, which only grows
    // pointerClaims, but nothing here may hold on to a reference across
    // them.
    auto captureHit = extras.captureHits[i];
    auto group = captureHit.group;
    if (group->isConsumed() || group->isPointerDisabled(pointerId))
    {
      continue;
    }
    bool canHit = !collapsed;
    for (const auto& occluder : occluders)
    {
      if (occluder.drawIndex < captureHit.drawIndex &&
          !componentWithin(occluder.component, captureHit.target))
      {
        canHit = false;
        break;
      }
    }
    group->processEvent(
        captureHit.hit->component(),
        position,
        pointerId,
        hitType,
        button,
        canHit,
        timeStamp,
        this);
    if (canHit && group->isPointerHovered(pointerId))
    {
      result = HitResult::hit;
      if (hitType == ListenerType::down &&
          group->listener()->claimsPress(button))
      {
        claimPointer(captureHit.target, pointerId, button);
      }
    }
  }
  for (auto& ended : dragEnded)
  {
    dragEnd(position, timeStamp, ended.first, ended.second);
  }
  if (hitType == ListenerType::exit)
  {
    for (const auto& group : extras.captureGroups)
    {
      group->releaseEvent(pointerId);
    }
  }
  return result;
}

void StateMachineInstance::claimPointer(
    Component* scope,
    int pointerId,
    PointerButton button)
{
  auto& extras = ensureInputExtras();
  const PointerClaim* otherButton = nullptr;
  for (const auto& claim : extras.pointerClaims)
  {
    if (claim.pointerId != pointerId || claim.scope != scope)
    {
      continue;
    }
    // Peers on one target, or one listener over several of its shapes.
    if (claim.button == button)
    {
      return;
    }
    otherButton = &claim;
  }
  PointerClaim claim;
  claim.pointerId = pointerId;
  claim.button = button;
  claim.scope = scope;
  if (otherButton != nullptr)
  {
    // The same scope, already off: it holds the same things, so that
    // whichever button lets go first leaves them off for the other.
    claim.hits = otherButton->hits;
    claim.captureGroups = otherButton->captureGroups;
    extras.pointerClaims.push_back(std::move(claim));
    return;
  }
  for (const auto& hitComponent : m_hitComponents)
  {
    if (componentWithin(hierarchyComponent(hitComponent.get()), scope))
    {
      hitComponent->disablePointerEvents(pointerId);
      claim.hits.push_back(hitComponent.get());
    }
  }
  // Capture listeners deeper inside it too: the outermost claim wins, as
  // it does for keys. Peers on the same target keep running. One already
  // off still counts: an inner claim for another button may hold it, and
  // when that one lets go, this one keeps it off.
  for (const auto& captureHit : extras.captureHits)
  {
    if (captureHit.target != scope &&
        componentWithin(captureHit.target, scope) &&
        std::find(
            claim.captureGroups.begin(),
            claim.captureGroups.end(),
            captureHit.group) == claim.captureGroups.end())
    {
      captureHit.group->disable(pointerId);
      claim.captureGroups.push_back(captureHit.group);
    }
  }
  extras.pointerClaims.push_back(std::move(claim));
}

bool StateMachineInstance::releasePointerClaims(
    int pointerId,
    PointerButton button,
    bool anyButton)
{
  auto* extras = inputExtras();
  if (extras == nullptr || extras->pointerClaims.empty())
  {
    return false;
  }
  bool released = false;
  auto& claims = extras->pointerClaims;
  for (size_t i = 0; i < claims.size();)
  {
    if (claims[i].pointerId != pointerId ||
        (!anyButton && claims[i].button != button))
    {
      i++;
      continue;
    }
    PointerClaim claim = std::move(claims[i]);
    claims.erase(claims.begin() + i);
    for (auto hitComponent : claim.hits)
    {
      hitComponent->enablePointerEvents(pointerId);
    }
    for (auto group : claim.captureGroups)
    {
      group->enable(pointerId);
    }
    released = true;
  }
  if (released)
  {
    // Another claim of the pointer's may hold some of the same things.
    applyPointerClaims(pointerId);
  }
  return released;
}

void StateMachineInstance::applyPointerClaims(int pointerId)
{
  auto* extras = inputExtras();
  if (isPointerDisabled(pointerId))
  {
    // Turned off from outside (a host's claim or drag), which still holds:
    // everything goes back off, not just what the claims here cover.
    for (const auto& hitShape : m_hitComponents)
    {
      hitShape->disablePointerEvents(pointerId);
    }
    if (extras != nullptr)
    {
      for (const auto& group : extras->captureGroups)
      {
        group->disable(pointerId);
      }
    }
    return;
  }
  if (extras == nullptr)
  {
    return;
  }
  for (const auto& claim : extras->pointerClaims)
  {
    if (claim.pointerId != pointerId)
    {
      continue;
    }
    for (auto hitComponent : claim.hits)
    {
      hitComponent->disablePointerEvents(pointerId);
    }
    for (auto group : claim.captureGroups)
    {
      group->disable(pointerId);
    }
  }
}

uint32_t StateMachineInstance::liveCaptureMachines()
{
  return s_liveCaptureMachines.load(std::memory_order_relaxed);
}

void StateMachineInstance::captureTopologyChanged()
{
  // Never 0, which marks a cache that was never filled.
  if (s_captureEpoch.fetch_add(1, std::memory_order_relaxed) + 1 == 0)
  {
    s_captureEpoch.fetch_add(1, std::memory_order_relaxed);
  }
}

bool StateMachineInstance::treeHasCaptureListeners()
{
  const uint32_t epoch = s_captureEpoch.load(std::memory_order_relaxed);
  auto& extras = ensureInputExtras();
  if (extras.captureTreeEpoch != epoch)
  {
    extras.captureTreeHas = hasCaptureListeners();
    extras.captureTreeEpoch = epoch;
  }
  return extras.captureTreeHas;
}

bool StateMachineInstance::hasCaptureListeners()
{
  auto* extras = inputExtras();
  if (extras != nullptr && !extras->captureHits.empty())
  {
    return true;
  }
  for (auto nestedArtboard : m_artboardInstance->nestedArtboards())
  {
    for (auto nestedAnimation : nestedArtboard->nestedAnimations())
    {
      if (!nestedAnimation->is<NestedStateMachine>())
      {
        continue;
      }
      auto smi = nestedAnimation->as<NestedStateMachine>()
                     ->stateMachineInstance();
      if (smi != nullptr && smi->hasCaptureListeners())
      {
        return true;
      }
    }
  }
  for (auto componentList : m_artboardInstance->artboardComponentLists())
  {
    for (int i : componentList->orderedListIndices())
    {
      auto smi = componentList->stateMachineInstance(i);
      if (smi != nullptr && smi->hasCaptureListeners())
      {
        return true;
      }
    }
  }
  return false;
}

bool StateMachineInstance::pointerOccludedAt(Vec2D position)
{
  if (!mapToContentSpace(position))
  {
    // Collapsed contents hit nothing, so they hide nothing either.
    return false;
  }
  for (const auto& hitComponent : m_hitComponents)
  {
    if (hitComponent->blocksCapture(position))
    {
      return true;
    }
  }
  return false;
}

bool StateMachineInstance::hitTest(Vec2D position) const
{
  return hitTestInternal(position, false);
}

bool StateMachineInstance::hitTestBounded(Vec2D position) const
{
  return hitTestInternal(position, true);
}

bool StateMachineInstance::hitTestInternal(Vec2D position, bool bounded) const
{
  if (m_artboardInstance->frameOrigin() && !m_hostSpacePointers)
  {
    position -= Vec2D(
        m_artboardInstance->originX() * m_artboardInstance->layoutWidth(),
        m_artboardInstance->originY() * m_artboardInstance->layoutHeight());
  }
  // Invert the artboard's own rotation/scale (applied in drawInternal after
  // the frame-origin translation) so the pointer maps into content space.
  // Covers nested state machines too, which funnel through here.
  if (m_artboardInstance->hasSelfTransform() && !m_hostSpacePointers)
  {
    Mat2D inverse;
    if (!m_artboardInstance->selfTransform().invert(&inverse))
    {
      // A degenerate (0 scale) self transform collapses the contents to
      // nothing, so there's nothing to hit.
      return false;
    }
    position = inverse * position;
  }

  for (const auto& hitShape : m_hitComponents)
  {
    // TODO: quick reject.

    if (bounded ? hitShape->hitTestBounded(position)
                : hitShape->hitTest(position))
    {
      return true;
    }
  }
  return false;
}

void StateMachineInstance::serveTextStyle(
    Text* text,
    const TextStyleReference* style)
{
#ifdef WITH_RIVE_TEXT
  if (text == nullptr || style == nullptr)
  {
    return;
  }
  // Pointer listeners with no target listen to the runs drawn with
  // [style]. Their groups exist already, inert, so they just get a hit
  // area now.
  std::unique_ptr<HitTextStyleTarget> hitRuns;
  for (const auto& listenerGroup : m_listenerGroups)
  {
    auto listener = listenerGroup->listener();
    if (listener == nullptr || !listener->hasPointerListeners() ||
        m_artboardInstance->resolve(listener->targetId()) != nullptr)
    {
      continue;
    }
    if (hitRuns == nullptr)
    {
      hitRuns = std::make_unique<HitTextStyleTarget>(text, style, this);
    }
    hitRuns->addListener(listenerGroup.get());
  }
  if (hitRuns != nullptr)
  {
    m_hitComponents.push_back(std::move(hitRuns));
  }
  m_hostSpacePointers = true;
#endif
}

HitResult StateMachineInstance::pointerMove(
    Vec2D position,
    float timeStamp,
    int id)
{
  return updateListeners(position, ListenerType::move, id, timeStamp);
}
HitResult StateMachineInstance::pointerDown(
    Vec2D position,
    int id,
    PointerButton button)
{
  return updateListeners(position, ListenerType::down, id, 0, button);
}
HitResult StateMachineInstance::pointerUp(
    Vec2D position,
    int id,
    PointerButton button)
{
  return updateListeners(position, ListenerType::up, id, 0, button);
}
HitResult StateMachineInstance::pointerExit(Vec2D position, int id)
{
  return updateListeners(position, ListenerType::exit, id);
}
HitResult StateMachineInstance::pointerMiss(
    Vec2D position,
    ListenerType hitType,
    float timeStamp,
    int id,
    PointerButton button)
{
  // Every target counts as occluded: ListenerGroup::processEvent then
  // unhovers it and fails presses, but keeps a drag's press alive. Scoped
  // rather than passed, so the dragStart/dragEnd passes a group sets off
  // (and dragEnd's pointerMove) miss as well.
  const bool wasInPointerMiss = m_inPointerMiss;
  m_inPointerMiss = true;
  HitResult result;
  switch (hitType)
  {
    // A host's drag still turns this machine's pointers off and back on.
    case ListenerType::dragStart:
      result = dragStart(position, timeStamp, true, id, button);
      break;
    case ListenerType::dragEnd:
      result = dragEnd(position, timeStamp, id, button);
      break;
    default:
      result = updateListeners(position, hitType, id, timeStamp, button);
      break;
  }
  m_inPointerMiss = wasInPointerMiss;
  return result;
}
HitResult StateMachineInstance::dragStart(
    Vec2D position,
    float timeStamp,
    bool disablePointer,
    int pointerId,
    PointerButton button)
{
  if (disablePointer)
  {
    disablePointerEvents(pointerId);
  }
  auto hit = updateListeners(
      position,
      ListenerType::dragStart,
      pointerId,
      0,
      button);
  return hit;
}
HitResult StateMachineInstance::dragEnd(
    Vec2D position,
    float timeStamp,
    int pointerId,
    PointerButton button)
{
  enablePointerEvents(pointerId);
  auto hit = updateListeners(
      position,
      ListenerType::dragEnd,
      pointerId,
      0,
      button);
  pointerMove(position, timeStamp, pointerId);
  return hit;
}
bool StateMachineInstance::mapToContentSpace(Vec2D& position, Vec2D* delta)
    const
{
  if (m_hostSpacePointers)
  {
    return true;
  }
  if (m_artboardInstance->frameOrigin())
  {
    position -= Vec2D(
        m_artboardInstance->originX() * m_artboardInstance->layoutWidth(),
        m_artboardInstance->originY() * m_artboardInstance->layoutHeight());
  }
  if (m_artboardInstance->hasSelfTransform())
  {
    Mat2D inverse;
    if (!m_artboardInstance->selfTransform().invert(&inverse))
    {
      return false;
    }
    position = inverse * position;
    if (delta != nullptr)
    {
      // A delta is a vector: linear part only, no translation.
      *delta = inverse * *delta - inverse * Vec2D();
    }
  }
  return true;
}

HitResult StateMachineInstance::pointerScroll(
    Vec2D position,
    const ScrollEvent& event,
    float timeStamp,
    int pointerId)
{
  ScrollEvent mapped = event;
  if (!mapToContentSpace(position, &mapped.delta))
  {
    // Nothing can map through a singular transform, so no later event
    // could close this gesture.
    cancelScroll();
    return HitResult::none;
  }
  if (m_scrollLatch != nullptr && !m_scrollLatch->scrollGestureActive())
  {
    m_scrollLatch = nullptr;
  }
  HitComponent* target = m_scrollLatch;
  HitResult result = HitResult::none;
  if (target != nullptr)
  {
    result = target->processScroll(position, mapped, timeStamp, pointerId);
  }
  else
  {
    // Sorted top-most first, so the innermost view that can move wins.
    // One that declines, like a script that never calls hit, passes the
    // event on. An opaque hit that cannot scroll ends the walk, as it
    // would for a pointer: nothing behind it may take the event.
    for (const auto& hitShape : m_hitComponents)
    {
      if (hitShape->wantsScroll(position, mapped))
      {
        result = hitShape
                     ->processScroll(position, mapped, timeStamp, pointerId);
        if (result != HitResult::none)
        {
          target = hitShape.get();
          break;
        }
      }
      if (hitShape->occludesScroll(position))
      {
        break;
      }
    }
  }
  m_scrollLatch = target != nullptr && target->scrollGestureActive() ? target
                                                                     : nullptr;
  return result;
}

bool StateMachineInstance::wantsScroll(Vec2D position, const ScrollEvent& event)
{
  if (hasScrollLatch())
  {
    return true;
  }
  ScrollEvent mapped = event;
  if (!mapToContentSpace(position, &mapped.delta))
  {
    return false;
  }
  for (const auto& hitShape : m_hitComponents)
  {
    if (hitShape->wantsScroll(position, mapped))
    {
      return true;
    }
    if (hitShape->occludesScroll(position))
    {
      return false;
    }
  }
  return false;
}

bool StateMachineInstance::hasScrollTargetAt(Vec2D position)
{
  if (hasScrollLatch())
  {
    return true;
  }
  if (!mapToContentSpace(position))
  {
    return false;
  }
  for (const auto& hitShape : m_hitComponents)
  {
    if (hitShape->hasScrollTarget(position))
    {
      return true;
    }
    if (hitShape->occludesScroll(position))
    {
      return false;
    }
  }
  return false;
}

bool StateMachineInstance::listensToButtonAt(
    Vec2D position,
    PointerButton button)
{
  if (!mapToContentSpace(position))
  {
    return false;
  }
  // Capture listeners hear the press before anything else does.
  if (auto* extras = inputExtras())
  {
    for (const auto& captureHit : extras->captureHits)
    {
      if (captureHit.group->listener()->listensToButton(button) &&
          captureHit.hit->hitTest(position))
      {
        return true;
      }
    }
  }
  for (const auto& hitShape : m_hitComponents)
  {
    if (hitShape->listensToButtonAt(position, button))
    {
      return true;
    }
    if (hitShape->occludesPointer(position))
    {
      return false;
    }
  }
  return false;
}

bool StateMachineInstance::scrollOccludedAt(Vec2D position)
{
  if (!mapToContentSpace(position))
  {
    // Collapsed contents hit nothing, so they hide nothing either.
    return false;
  }
  // Only asked once nothing here wanted the event, so the first opaque hit
  // decides.
  for (const auto& hitShape : m_hitComponents)
  {
    if (hitShape->occludesScroll(position))
    {
      return true;
    }
  }
  return false;
}

void StateMachineInstance::cancelScroll()
{
  if (m_scrollLatch != nullptr)
  {
    m_scrollLatch->cancelScroll();
    m_scrollLatch = nullptr;
  }
}

bool StateMachineInstance::hasScrollLatch()
{
  if (m_scrollLatch != nullptr && !m_scrollLatch->scrollGestureActive())
  {
    m_scrollLatch = nullptr;
  }
  return m_scrollLatch != nullptr;
}

#ifdef TESTING
uint64_t StateMachineInstance::sm_settledLayerSkips = 0;
uint64_t StateMachineInstance::sm_capturePassVisits = 0;
uint64_t StateMachineInstance::sm_frozenLayerAdvances = 0;
uint64_t StateMachineInstance::sm_frozenPoseAdvances = 0;

const LayerState* StateMachineInstance::layerState(size_t index)
{
  if (index < m_layerCount)
  {
    return m_layers[index].currentState();
  }
  return nullptr;
}

bool StateMachineInstance::isLayerFrozen(size_t index) const
{
  return index < m_layerCount &&
         m_layers[index].isFrozen(this, m_advanceChangeSerial);
}

bool StateMachineInstance::hasLayerChangeWindows() const
{
  auto* bindables = this->bindables();
  return bindables != nullptr && bindables->layerChanges != nullptr;
}
#endif

void StateMachineInstance::addToHitLookup(
    Component* target,
    bool isLayoutComponent,
    std::unordered_map<Component*, HitDrawable*>& hitLookup,
    ListenerGroup* listenerGroup,
    bool isOpaque,
    std::vector<HitDrawable*>* captureHits)
{
  // A capture listener's hit drawable is shared with the normal listeners
  // on the same target, but doesn't take the listener: the capture phase
  // drives it from the outside.
  auto addListener = [&](HitDrawable* hitDrawable) {
    if (captureHits != nullptr)
    {
      captureHits->push_back(hitDrawable);
    }
    else
    {
      hitDrawable->addListener(listenerGroup);
    }
  };
  // target could either be a LayoutComponent or a DrawableProxy
  if (isLayoutComponent)
  {
    HitLayout* hitLayout;
    auto itr = hitLookup.find(target);
    if (itr == hitLookup.end())
    {
      auto hs = std::make_unique<HitLayout>(
          target->as<Drawable>(),
          this,
          isOpaque);
      hitLookup[target] = hitLayout = hs.get();
      m_hitComponents.push_back(std::move(hs));
    }
    else
    {
      hitLayout = static_cast<HitLayout*>(itr->second);
    }
    addListener(hitLayout);
    if (isOpaque)
    {
      hitLayout->isOpaque = true;
    }
    return;
  }

  if (target->is<Shape>())
  {
    HitExpandable* hitShape;
    auto itr = hitLookup.find(target);
    if (itr == hitLookup.end())
    {
      Shape* shape = target->as<Shape>();
      shape->addFlags(PathFlags::neverDeferUpdate);
      shape->addDirt(ComponentDirt::Path, true);
      auto hs = std::make_unique<HitExpandable>(shape, shape, this);
      hitLookup[target] = hitShape = hs.get();
      m_hitComponents.push_back(std::move(hs));
    }
    else
    {
      hitShape = static_cast<HitExpandable*>(itr->second);
    }
    addListener(hitShape);
    return;
  }

  if (target->is<TextValueRun>())
  {
    HitTextRun* hitTextRun;
    auto itr = hitLookup.find(target);
    if (itr == hitLookup.end())
    {
      TextValueRun* run = target->as<TextValueRun>();
      run->textComponent()->addDirt(ComponentDirt::Path, true);
      auto hs = std::make_unique<HitTextRun>(run->textComponent(), run, this);
      hitLookup[target] = hitTextRun = hs.get();
      m_hitComponents.push_back(std::move(hs));
    }
    else
    {
      hitTextRun = static_cast<HitTextRun*>(itr->second);
    }
    addListener(hitTextRun);
    return;
  }

  // Older files ignore images: they fall through to the container walk, which
  // finds nothing to hit under one.
  if (target->is<Image>() && target->as<Image>()->isPointerTarget())
  {
    HitExpandable* hitImage;
    auto itr = hitLookup.find(target);
    if (itr == hitLookup.end())
    {
      Image* image = target->as<Image>();
      auto hs = std::make_unique<HitExpandable>(image, image, this);
      hitLookup[target] = hitImage = hs.get();
      m_hitComponents.push_back(std::move(hs));
    }
    else
    {
      hitImage = static_cast<HitExpandable*>(itr->second);
    }
    addListener(hitImage);
    return;
  }

  if (target->is<ContainerComponent>())
  {
    target->as<ContainerComponent>()->forEachChild([&](Component* child) {
      addToHitLookup(
          child,
          child->is<LayoutComponent>(),
          hitLookup,
          listenerGroup,
          isOpaque,
          captureHits);
      return false;
    });
    return;
  }
}

StateMachineInstance::StateMachineInstance(
    const StateMachine* machine,
    ArtboardInstance* instance)
    : Scene(instance)
    , m_machine(machine)
    , m_needsAdvance(false)
    , m_bindsPending(false)
    , m_anySettled(false)
    , m_destroying(false)
    , m_hostSpacePointers(false)
    , m_hostDispatching(false)
    , m_captureRunByHost(false)
    , m_inPointerMiss(false)
{
  const auto count = machine->inputCount();
  m_inputInstances.resize(count);
  for (size_t i = 0; i < count; i++)
  {
    auto input = machine->input(i);
    if (input == nullptr)
    {
      continue;
    }
    switch (input->coreType())
    {
      case StateMachineBool::typeKey:
        m_inputInstances[i] = new SMIBool(input->as<StateMachineBool>(), this);
        break;
      case StateMachineNumber::typeKey:
        m_inputInstances[i] = new SMINumber(
            input->as<StateMachineNumber>(),
            this);
        break;
      case StateMachineTrigger::typeKey:
        m_inputInstances[i] = new SMITrigger(
            input->as<StateMachineTrigger>(),
            this);
        break;
      default:
        // Sanity check.
        break;
    }
#ifdef WITH_RIVE_TOOLS
    auto instance = m_inputInstances[i];
    if (instance != nullptr)
    {
      instance->m_index = i;
    }
#endif
  }

  // Seeded once per state machine instance. This used to run inside the
  // per-layer init(), reseeding the global RNG (and, outside deterministic
  // mode, reading the clock) once for every layer of every instance.
  if (File::deterministicMode)
  {
    srand((unsigned int)1);
  }
  else
  {
    auto now = std::chrono::high_resolution_clock::now();
    auto nanos = std::chrono::duration_cast<std::chrono::nanoseconds>(
                     now.time_since_epoch())
                     .count();
    srand((unsigned int)nanos);
  }

  // Import refuses a machine with more (StateMachineImporter::resolve).
  assert(machine->layerCount() <= UINT16_MAX);
  m_layerCount = static_cast<uint16_t>(
      std::min<size_t>(machine->layerCount(), UINT16_MAX));
  m_layers = new StateMachineLayerInstance[m_layerCount];
  for (size_t i = 0; i < m_layerCount; i++)
  {
    m_layers[i].init(this, machine->layer(i));
  }

  // A condition comparing a component's trigger reads whether it fired
  // within the frame (changePending), which this instance's change tracking
  // answers. It has to start now, before anything fires.
  if (machine->readsComponentTriggers())
  {
    ensureBindables();
  }

  // Initialize dataBinds. All databinds are cloned for the state machine
  // instance. That enables binding each instance to its own context without
  // polluting the rest.
  auto dataBindCount = machine->dataBindCount();
  for (size_t i = 0; i < dataBindCount; i++)
  {
    auto dataBind = machine->dataBind(i);
    if (!dataBind->target())
    {
      continue;
    }
    auto dataBindClone = static_cast<DataBind*>(dataBind->clone());
    dataBindClone->file(dataBind->file());
    if (dataBind->converter() != nullptr)
    {
      dataBindClone->converter(
          dataBind->converter()->clone()->as<DataConverter>());
    }
    if (dataBind->target()->is<BindableProperty>())
    {
      auto& bindables = ensureBindables();
      auto bindableProperty = dataBind->target()->as<BindableProperty>();
      BindableProperty* bindablePropertyClone = bindables.propertyInstances
                                                    .find(bindableProperty);
      if (bindablePropertyClone == nullptr)
      {
        bindablePropertyClone = bindableProperty->clone()
                                    ->as<BindableProperty>();
        bindables.propertyInstances.insert(
            bindableProperty,
            bindablePropertyClone);
      }
      dataBindClone->target(bindablePropertyClone);
      // We are only storing in this unordered map data binds that are
      // targetting the source. For now, this is only the case for
      // listener actions.
      if ((static_cast<DataBindFlags>(dataBindClone->flags()) &
           DataBindFlags::ToSource) == DataBindFlags::ToSource)
      {
        bindables.dataBindsToSource[bindablePropertyClone] = dataBindClone;
      }
      else
      {
        bindables.dataBindsToTarget[bindablePropertyClone] = dataBindClone;
      }
    }
    else
    {
      auto* originalTarget = dataBind->target();
      dataBindClone->target(originalTarget);
      if (originalTarget->is<StateTransitionBase>())
      {
        // Create a per-instance BindablePropertyNumber to
        // receive the data-bound value instead of writing
        // to the shared StateTransition. Swap the target
        // and propertyKey so the normal apply() path writes
        // to our instance-local property.
        auto* prop = new BindablePropertyNumber();
        auto& transitionProps = ensureBindables().transitionPropertyInstances;
        transitionProps[originalTarget][dataBind->propertyKey()] = prop;
        dataBindClone->target(prop);
        dataBindClone->propertyKey(
            BindablePropertyNumberBase::propertyValuePropertyKey);
      }
    }
    // Added once its target is set: addDataBind decides from the target
    // whether a toSource bind hears about changes or has to poll for them,
    // and without one it would poll on every pass.
    addDataBind(dataBindClone);
  }

  // Initialize listeners. Store a lookup table of shape id to hit shape
  // representation (an object that stores all the listeners triggered by the
  // shape producing a listener).
  std::unordered_map<Component*, HitDrawable*> hitLookup;
  for (std::size_t i = 0; i < machine->listenerCount(); i++)
  {
    auto listener = machine->listener(i);
    if (listener->hasListener(ListenerType::event))
    {
      continue;
    }
    if (listener->hasListener(ListenerType::viewModel))
    {
      auto vmListener = new ListenerViewModel(this, listener);
      ensureReporting().listenerViewModels.push_back(vmListener);
      // Its triggers are checked against this instance's change
      // tracking when it binds (viewModelTriggerPendingForListeners),
      // which has to start now, before the first bind.
      ensureBindables();
      continue;
    }
    // Handle focus/blur listeners - they're driven by FocusManager,
    // not pointer events.
    if (listener->hasListener(ListenerType::focus) ||
        listener->hasListener(ListenerType::blur))
    {
      auto target = m_artboardInstance->resolve(listener->targetId());
      if (target != nullptr && target->is<Node>())
      {
        auto node = target->as<Node>();
        // Find FocusData child of the node
        FocusData* focusData = nullptr;
        for (auto child : node->children())
        {
          if (child->is<FocusData>())
          {
            focusData = child->as<FocusData>();
            break;
          }
        }
        if (focusData != nullptr)
        {
          auto focusGroup = std::make_unique<FocusListenerGroup>(
              focusData,
              listener,
              this);
          ensureInputExtras().focusListenerGroups.push_back(
              std::move(focusGroup));
        }
      }
    }
    if (listener->hasListener(ListenerType::keyboard) ||
        listener->hasListener(ListenerType::textInput))
    {
      auto target = m_artboardInstance->resolve(listener->targetId());
      if (target != nullptr && target->is<Node>())
      {
        auto node = target->as<Node>();
        // Find FocusData child of the node
        FocusData* focusData = nullptr;
        for (auto child : node->children())
        {
          if (child->is<FocusData>())
          {
            focusData = child->as<FocusData>();
            break;
          }
        }
        if (focusData != nullptr)
        {
          auto keyboardGroup = std::make_unique<KeyboardListenerGroup>(
              focusData,
              listener,
              this);
          ensureInputExtras().keyboardListenerGroups.push_back(
              std::move(keyboardGroup));
        }
      }
    }
    // Semantic listeners are driven by accessibility actions rather
    // than pointer events. The editor enforces that the listener's
    // target Node owns a SemanticData child directly; no ancestor
    // walk is performed here.
    if (listener->hasListener(ListenerType::semanticAction))
    {
      auto target = m_artboardInstance->resolve(listener->targetId());
      if (target != nullptr && target->is<Node>())
      {
        for (auto* child : target->as<Node>()->children())
        {
          if (child->is<SemanticData>())
          {
            ensureInputExtras().semanticListenerGroups.push_back(
                std::make_unique<SemanticListenerGroup>(
                    child->as<SemanticData>(),
                    listener,
                    this));
            break;
          }
        }
      }
    }

    if (listener->hasPointerListeners() && listener->isCapture())
    {
      auto listenerGroup = std::make_unique<ListenerGroup>(listener);
      auto target = m_artboardInstance->resolve(listener->targetId());
      if (target != nullptr && target->is<Component>())
      {
        auto scope = target->as<Component>();
        uint32_t depth = 0;
        for (auto p = scope->parent(); p != nullptr; p = p->parent())
        {
          depth++;
        }
        bool isLayoutComponent = false;
        Component* hitTarget = scope;
        if (scope->is<LayoutComponent>())
        {
          isLayoutComponent = true;
          hitTarget = scope->as<LayoutComponent>()->proxy();
        }
        std::vector<HitDrawable*> hits;
        addToHitLookup(
            hitTarget,
            isLayoutComponent,
            hitLookup,
            listenerGroup.get(),
            false,
            &hits);
        auto& extras = ensureInputExtras();
        for (auto hit : hits)
        {
          extras.captureHits.push_back(
              {hit, listenerGroup.get(), scope, depth, 0});
        }
      }
      ensureInputExtras().captureGroups.push_back(std::move(listenerGroup));
    }
    else if (listener->hasPointerListeners())
    {
      auto listenerGroup = std::make_unique<ListenerGroup>(listener);
      auto target = m_artboardInstance->resolve(listener->targetId());
      if (target != nullptr && target->is<Component>())
      {
        bool isLayoutComponent = false;
        if (target->is<LayoutComponent>())
        {
          isLayoutComponent = true;
          target = target->as<LayoutComponent>()->proxy();
        }
        addToHitLookup(
            target->as<Component>(),
            isLayoutComponent,
            hitLookup,
            listenerGroup.get(),
            false);
      }
      m_listenerGroups.push_back(std::move(listenerGroup));
    }
    if (listener->hasListener(ListenerType::gamepad))
    {
      auto target = m_artboardInstance->resolve(listener->targetId());
      if (target != nullptr && target->is<Node>())
      {
        auto node = target->as<Node>();
        FocusData* focusData = nullptr;
        for (auto child : node->children())
        {
          if (child->is<FocusData>())
          {
            focusData = child->as<FocusData>();
            break;
          }
        }
        if (focusData != nullptr)
        {
          auto gamepadGroup = std::make_unique<GamepadListenerGroup>(
              focusData,
              listener,
              this);
          ensureInputExtras().gamepadListenerGroups.push_back(
              std::move(gamepadGroup));
        }
      }
    }
  }

  // Native editor instances keep components in their dependency graph,
  // rather than the runtime importer's owning object array.
  const auto* listenerObjects = &instance->objects();
#ifdef WITH_RIVE_EDITOR
  std::vector<Core*> nativeListenerObjects;
  if (instance->editorResolver())
  {
    const auto& components = instance->dependencyOrder();
    nativeListenerObjects.assign(components.begin(), components.end());
    listenerObjects = &nativeListenerObjects;
  }
#endif
  std::vector<ListenerGroupProvider*> componentProvidedListenerGroups;
  for (auto core : *listenerObjects)
  {
    if (core == nullptr)
    {
      continue;
    }
    auto provider = ListenerGroupProvider::from(core);
    if (provider != nullptr)
    {
      componentProvidedListenerGroups.push_back(provider);
    }
  }
  for (auto component : componentProvidedListenerGroups)
  {
    auto groupsWithTargets = component->listenerGroups();
    for (auto groupWithTargets : groupsWithTargets)
    {
      auto group = groupWithTargets->group();
      auto targets = groupWithTargets->targets();
      for (auto target : targets)
      {
        auto component = target->component();
        bool isLayoutComponent = component->is<LayoutComponent>() ||
                                 (component->is<Drawable>() &&
                                  component->as<Drawable>()->isProxy());
        addToHitLookup(
            target->component(),
            isLayoutComponent,
            hitLookup,
            group,
            target->isOpaque());
      }
      m_listenerGroups.push_back(std::unique_ptr<ListenerGroup>(group));
      for (auto target : targets)
      {
        delete target;
      }
      delete groupWithTargets;
    }
    auto hitComponents = component->hitComponents(this);
    for (auto* hitComponent : hitComponents)
    {
      m_hitComponents.push_back(std::unique_ptr<HitComponent>(hitComponent));
    }
  }

  for (auto nestedArtboard : instance->nestedArtboards())
  {
    // TODO: @hernan as an optimization only create a HitNestedArtboard if
    // the nested artboard has state machines or if it is bound via data
    // binding
    auto hn = std::make_unique<HitNestedArtboard>(
        nestedArtboard->as<Component>(),
        this);
    m_hitComponents.push_back(std::move(hn));
    for (auto animation : nestedArtboard->nestedAnimations())
    {
      if (animation->is<NestedStateMachine>())
      {
        if (auto notifier = animation->as<NestedStateMachine>()
                                ->stateMachineInstance())
        {
          notifier->setNestedArtboard(nestedArtboard);
          notifier->addNestedEventListener(this);
        }
      }
      else if (animation->is<NestedLinearAnimation>())
      {
        if (auto notifier = animation->as<NestedLinearAnimation>()
                                ->animationInstance())
        {
          notifier->setNestedArtboard(nestedArtboard);
          notifier->addNestedEventListener(this);
        }
      }
    }
  }
  for (auto componentList : instance->artboardComponentLists())
  {
    auto hc = std::make_unique<HitComponentList>(
        componentList->as<Component>(),
        this);
    m_hitComponents.push_back(std::move(hc));
  }

#ifdef WITH_RIVE_TEXT
  // Texts whose runs may use a style that listens to them forward pointers
  // to those styles' state machines.
  for (auto text : instance->objects<Text>())
  {
    if (text->mayHaveListeningRuns())
    {
      m_hitComponents.push_back(std::make_unique<HitTextStyleRuns>(text, this));
    }
  }
  // Register TextInputs as hit targets for drag-to-select functionality
  for (auto object : *listenerObjects)
  {
    if (!object || !object->is<TextInput>())
      continue;
    auto* textInput = object->as<TextInput>();
    auto textInputGroup = std::make_unique<TextInputListenerGroup>(
        textInput,
        this);
    auto hitExpandable = std::make_unique<HitExpandable>(
        textInput->as<Drawable>(),
        textInput->as<Component>(),
        this,
        true); // isOpaque - TextInput blocks hits behind it
    hitExpandable->addListener(textInputGroup.get());
    m_hitComponents.push_back(std::move(hitExpandable));
    m_listenerGroups.push_back(std::move(textInputGroup));
  }
#endif

  // Initialize local instances of ScriptedObjects, in the state machine's
  // authored order so every downstream walk (dataContext, Lua init) is
  // deterministic.
  auto sharedScriptedObjects = machine->scriptedObjects();
  if (!sharedScriptedObjects.empty())
  {
    auto& scripting = ensureScripting();
    scripting.objects.reserve(sharedScriptedObjects.size());
    for (auto& scriptedOb : sharedScriptedObjects)
    {
      scripting.objects.emplace_back(
          scriptedOb,
          scriptedOb->cloneScriptedObject(this));
    }
    for (auto& scriptedPair : scripting.objects)
    {
      scriptedPair.second->dataContext(m_artboardInstance->dataContext());
    }
    initScriptedObjects();
  }
  // Register Scripted objects as keyboard and text targets when expected,
  // and collect every scripted drawable that wants gamepad events so we can
  // broadcast to it later regardless of focus.
  for (auto object : *listenerObjects)
  {
    if (!object || !object->is<ContainerComponent>())
      continue;
    auto scriptedObject = ScriptedObject::from(object);
    if (!scriptedObject)
    {
      continue;
    }
    if (scriptedObject->wantsKeyboardInput() ||
        scriptedObject->wantsTextInput())
    {
      for (auto& child : object->as<ContainerComponent>()->children())
      {
        if (child->is<FocusData>())
        {

          auto keyboardGroup = std::make_unique<KeyboardListenerGroup>(
              child->as<FocusData>(),
              nullptr,
              this);
          ensureInputExtras().keyboardListenerGroups.push_back(
              std::move(keyboardGroup));
          break;
        }
      }
    }
    if ((scriptedObject->wantsGamePadConnect() ||
         scriptedObject->wantsGamePadDisconnect() ||
         scriptedObject->wantsGamePadEvent()) &&
        object->is<ScriptedDrawable>())
    {
      ensureInputExtras().gamepadScriptedDrawables.push_back(
          object->as<ScriptedDrawable>());
    }
  }
  sortHitComponents();
  if (inputExtras() != nullptr && !inputExtras()->captureHits.empty())
  {
    s_liveCaptureMachines.fetch_add(1, std::memory_order_relaxed);
    captureTopologyChanged();
  }
}

FocusManager* StateMachineInstance::focusManager()
{
  return m_artboardInstance != nullptr ? m_artboardInstance->focusManager()
                                       : nullptr;
}

const FocusManager* StateMachineInstance::focusManager() const
{
  return m_artboardInstance != nullptr ? m_artboardInstance->focusManager()
                                       : nullptr;
}

SMIReporting& StateMachineInstance::ensureReporting()
{
  return *m_reporting.ensureAllocated();
}

SMIBindables& StateMachineInstance::ensureBindables()
{
  if (m_bindables.get() == nullptr)
  {
    m_bindables.ensureAllocated();
    // Changes from before this instance existed aren't pending for it,
    // beyond the frame it was made in (see forgetViewModelChanges).
    forgetViewModelChanges();
  }
  return *m_bindables.get();
}

SMIInputExtras& StateMachineInstance::ensureInputExtras()
{
  return *m_inputExtras.ensureAllocated();
}

SMIScripting& StateMachineInstance::ensureScripting()
{
  return *m_scripting.ensureAllocated();
}

SemanticManager* StateMachineInstance::semanticManager() const
{
  auto* extras = inputExtras();
  if (extras == nullptr)
  {
    return nullptr;
  }
  return extras->externalSemanticManager ? extras->externalSemanticManager
                                         : extras->semanticManager.get();
}

ScriptedObject* StateMachineInstance::scriptedObject(
    const ScriptedObject* source) const
{
  auto* scripting = this->scripting();
  return scripting != nullptr ? scripting->find(source) : nullptr;
}

StateMachineInstance::~StateMachineInstance()
{
  m_destroying = true;
  if (inputExtras() != nullptr && !inputExtras()->captureHits.empty())
  {
    s_liveCaptureMachines.fetch_sub(1, std::memory_order_relaxed);
    captureTopologyChanged();
  }

  // Clean up semantic tree BEFORE the internal SemanticManager is destroyed.
  // Only needed when we own the manager; if external, the parent cleans up.
  if (auto* extras = inputExtras())
  {
    if (extras->externalSemanticManager == nullptr &&
        extras->semanticManager != nullptr && m_artboardInstance != nullptr)
    {
      m_artboardInstance->cleanupSemanticTree();
    }
    extras->embedderGamepads.clear();
  }

  unbind();
  for (auto inst : m_inputInstances)
  {
    delete inst;
  }
  for (auto& listenerGroup : m_listenerGroups)
  {
    listenerGroup.reset();
  }
  deleteDataBinds();
  delete[] m_layers;
  // What's torn down below can still dirty a bind, which unsettles layers.
  m_layers = nullptr;
  m_anySettled = false;
  // The bindable clones and per-transition property instances are raw-owning,
  // so they are deleted here rather than by the cluster's destructor.
  if (auto* bindables = m_bindables.get())
  {
    bindables->propertyInstances.forEachInstance(
        [](BindableProperty* instance) { delete instance; });
    for (auto& outer : bindables->transitionPropertyInstances)
    {
      for (auto& inner : outer.second)
      {
        delete inner.second;
      }
    }
    bindables->transitionPropertyInstances.clear();
    bindables->propertyInstances.clear();
  }
  if (auto* reporting = this->reporting())
  {
    for (auto& listenerViewModel : reporting->listenerViewModels)
    {
      delete listenerViewModel;
    }
    reporting->listenerViewModels.clear();
  }
  if (auto* scripting = m_scripting.get())
  {
    for (auto& pair : scripting->objects)
    {
      delete pair.second;
    }
    scripting->objects.clear();
  }
}

// Stops the nested artboards' animations from reporting events to this
// machine. ~NestedEventListener does the same, so this only matters to a host
// that wants the machine detached before it is deleted.
void StateMachineInstance::dispose() { removeEventListeners(); }

void StateMachineInstance::removeEventListeners()
{
  removeFromNestedEventNotifiers();
}

#ifdef WITH_RIVE_TOOLS
void StateMachineInstance::onDataBindChanged(DataBindChanged callback)
{
  // dataBinds() is the DataBindContainer base's list — the one addDataBind()
  // actually fills. A same-named member used to shadow it here, and it was
  // never written, so this callback silently never got installed.
  for (auto databind : dataBinds())
  {
    databind->onChanged(callback);
  }
}
#endif

void StateMachineInstance::sortHitComponents()
{
  auto hitShapesCount = m_hitComponents.size();
  auto currentSortedIndex = 0;
  auto count = 0;
  // Since the Artboard is not a drawable, we move all hit components
  // pointing to the artboard to the front of the list
  for (auto& comp : m_hitComponents)
  {
    if (comp->component() != nullptr && comp->component()->is<Artboard>())
    {
      if (currentSortedIndex != count)
      {

        std::iter_swap(
            m_hitComponents.begin() + currentSortedIndex,
            m_hitComponents.begin() + count);
      }
      currentSortedIndex++;
    }
    count++;
  }
  Drawable* last = m_artboardInstance->firstDrawable();
  if (last)
  {
    // walk to the end, so we can visit in reverse-order
    while (last->prev)
    {
      last = last->prev;
    }
  }
  for (auto drawable = last; drawable; drawable = drawable->next)
  {
    for (size_t i = currentSortedIndex; i < hitShapesCount; i++)
    {
      if (m_hitComponents[i]->component() == drawable)
      {
        if (currentSortedIndex != i)
        {
          std::iter_swap(
              m_hitComponents.begin() + currentSortedIndex,
              m_hitComponents.begin() + i);
        }
        currentSortedIndex++;
      }
    }
    if (currentSortedIndex == hitShapesCount)
    {
      break;
    }
  }

  auto* extras = inputExtras();
  if (extras == nullptr || extras->captureHits.empty())
  {
    return;
  }
  for (auto& captureHit : extras->captureHits)
  {
    for (size_t i = 0; i < m_hitComponents.size(); i++)
    {
      if (m_hitComponents[i].get() == captureHit.hit)
      {
        captureHit.drawIndex = i;
        break;
      }
    }
  }
  // Ancestors before descendants, then topmost first.
  std::stable_sort(
      extras->captureHits.begin(),
      extras->captureHits.end(),
      [](const CaptureHit& a, const CaptureHit& b) {
        if (a.depth != b.depth)
        {
          return a.depth < b.depth;
        }
        return a.drawIndex < b.drawIndex;
      });
}

bool StateMachineInstance::tryChangeState()
{
  updateDataBinds(false);
  bool hasChangedState = false;
  for (size_t i = 0; i < m_layerCount; i++)
  {
    if (m_layers[i].updateState(this))
    {
      hasChangedState = true;
    }
  }
  return hasChangedState;
}

void StateMachineInstance::applyEvents()
{
  auto* reporting = this->reporting();
  if (reporting == nullptr)
  {
    // Nothing has ever reported on this instance, so there is provably
    // nothing to apply and nothing stale to clear.
    return;
  }
  reporting->eventsAppliedDuringLoop.clear();
  int maxIterations = 100;
  int currentIteration = 0;
  while ((reporting->reportedEvents.size() > 0 ||
          reporting->reportedListenerViewModels.size() > 0) &&
         currentIteration++ < maxIterations)
  {
    updateDataBinds(false);
    // The reported/reporting split is load-bearing: notifying below can
    // re-enter reportEvent(), and those events must queue for the next
    // pass rather than mutate the batch being delivered.
    reporting->reportingEvents = reporting->reportedEvents;
    reporting->reportingListenerViewModels = reporting
                                                 ->reportedListenerViewModels;
    reporting->reportedEvents.clear();
    reporting->reportedListenerViewModels.clear();
    if (currentIteration > 1)
    {
      // These were reported during the loop, so no host has seen them
      // yet; keep them visible until the next applyEvents.
      reporting->eventsAppliedDuringLoop.insert(
          reporting->eventsAppliedDuringLoop.end(),
          reporting->reportingEvents.begin(),
          reporting->reportingEvents.end());
    }
    this->notifyEventListeners(reporting->reportingEvents, nullptr);
    this->notifyListenerViewModels(reporting->reportingListenerViewModels);
  }
  if (currentIteration >= maxIterations)
  {
    fprintf(
        stderr,
        "%s StateMachine exceeded max event iterations"
        "on artboard %s\n",
        stateMachine()->name().c_str(),
        artboard()->name().c_str());
  }
}

void StateMachineInstance::setExternalFocusManager(FocusManager* manager)
{
  if (m_artboardInstance != nullptr)
  {
    m_artboardInstance->adoptFocusManager(manager);
  }
}

void StateMachineInstance::enableSemantics()
{
  if (semanticManager() != nullptr)
  {
    return;
  }
  ensureInputExtras().semanticManager = std::make_unique<SemanticManager>();
  if (m_artboardInstance != nullptr)
  {
    m_artboardInstance->buildSemanticTree(semanticManager(), nullptr);
  }
}

void StateMachineInstance::setExternalSemanticManager(
    SemanticManager* manager,
    rcp<SemanticNode> parentNode)
{
  // An unallocated cluster means no external manager is set, so clearing one
  // on such an instance is a no-op — check before allocating.
  auto* existing = inputExtras();
  if ((existing != nullptr ? existing->externalSemanticManager : nullptr) ==
      manager)
  {
    return;
  }
  auto& extras = ensureInputExtras();

  // Clean up the old semantic tree if one was built with a different manager.
  if (m_artboardInstance != nullptr &&
      m_artboardInstance->semanticManager() != nullptr)
  {
    m_artboardInstance->cleanupSemanticTree();
  }

  extras.externalSemanticManager = manager;

  // Rebuild with the new manager. semanticManager() now returns the external
  // manager if set, or the internal one if null.
  if (m_artboardInstance != nullptr)
  {
    m_artboardInstance->buildSemanticTree(semanticManager(), parentNode);
  }
}

void StateMachineInstance::queueFocusEvent(
    FocusListenerGroup* group,
    bool isFocus)
{
  ensureInputExtras().queuedFocusEvents.push_back({group, isFocus});
  markNeedsAdvance();
}

void StateMachineInstance::setFocus(FocusData* focusData)
{
  if (!focusManager())
  {
    return;
  }
  if (focusData != nullptr)
  {
    auto node = focusData->focusNode();
    auto* fm = focusManager();
    fm->setFocus(node);
  }
  else
  {
    focusManager()->clearFocus();
  }
}

StateMachineInstance::FocusState StateMachineInstance::focusState() const
{
  FocusState state;
  const FocusManager* fm = focusManager();
  if (fm == nullptr)
  {
    return state;
  }
  // primaryFocusPtr() avoids a refcount bump on this poll-friendly path.
  FocusNode* focus = fm->primaryFocusPtr();
  if (focus == nullptr)
  {
    return state;
  }
  state.hasFocus = true;
  if (Focusable* focusable = focus->focusable())
  {
    state.expectsKeyboardInput = focusable->acceptsKeyboardInput();
  }
  return state;
}

const Artboard* StateMachineInstance::rootArtboard() const
{
  const Artboard* artboard = m_artboardInstance;
  while (artboard != nullptr && artboard->host() != nullptr &&
         artboard->host()->parentArtboard() != nullptr)
  {
    artboard = artboard->host()->parentArtboard();
  }
  return artboard;
}

void StateMachineInstance::queueFocusTarget(FocusData* focusData)
{
  if (focusData == nullptr)
  {
    return;
  }
  if (!focusManager())
  {
    return;
  }
  focusManager()->requestFocus(focusData->focusNode(), rootArtboard());
  markNeedsAdvance();
}

void StateMachineInstance::queueClearFocus()
{
  if (!focusManager())
  {
    return;
  }
  focusManager()->requestClearFocus(rootArtboard());
  markNeedsAdvance();
}

void StateMachineInstance::queueFocusTraversal(uint32_t traversalKind)
{
  if (!focusManager())
  {
    return;
  }
  focusManager()->requestTraversal(traversalKind, rootArtboard());
  markNeedsAdvance();
}

void StateMachineInstance::processFocusEvents()
{
  auto* extras = inputExtras();
  if (extras == nullptr || extras->queuedFocusEvents.empty())
  {
    return;
  }

  // Moved out before dispatch: a listener action can queue further focus
  // events, and those belong to the next advance, not this drain.
  auto events = std::move(extras->queuedFocusEvents);
  extras->queuedFocusEvents.clear();

  for (const auto& event : events)
  {
    auto listener = event.group->listener();
    bool isFocusEvent = event.isFocus;

    // Match listener type to event type
    if ((isFocusEvent && listener->hasListener(ListenerType::focus)) ||
        (!isFocusEvent && listener->hasListener(ListenerType::blur)))
    {
      listener->performChanges(
          this,
          ListenerInvocation::focus(event.group, event.isFocus));
    }
  }
}

void StateMachineInstance::queueSemanticEvent(
    SemanticListenerGroup* group,
    SemanticActionType actionType)
{
  ensureInputExtras().queuedSemanticEvents.push_back({group, actionType});
  markNeedsAdvance();
}

void StateMachineInstance::processSemanticEvents()
{
  auto* extras = inputExtras();
  if (extras == nullptr || extras->queuedSemanticEvents.empty())
  {
    return;
  }

  auto events = std::move(extras->queuedSemanticEvents);
  extras->queuedSemanticEvents.clear();

  for (const auto& event : events)
  {
    if (event.group == nullptr)
    {
      continue;
    }
    auto* listener = event.group->listener();
    if (listener == nullptr)
    {
      continue;
    }
    listener->performChanges(
        this,
        ListenerInvocation::semantic(event.group, event.actionType));
  }
}

void StateMachineInstance::fireSemanticAction(
    uint32_t semanticNodeId,
    SemanticActionType actionType)
{
  // The unified SemanticManager indexes every SD in the tree — top-level,
  // nested-artboard, and data-bound list items — so this lookup handles
  // all dispatch targets uniformly. SemanticData::fire*() routes the
  // event to listeners, which queue on their own owning state machine.
  auto* mgr = semanticManager();
  if (mgr == nullptr)
  {
    return;
  }
  auto* node = mgr->nodeById(semanticNodeId);
  // A hidden node (collapsed, Hidden, or under a collapsed host) stays
  // registered; an action the platform sent before it saw the node leave
  // must not reach it.
  if (node == nullptr || !mgr->isInTree(node))
  {
    return;
  }
  auto* sd = node->semanticData();
  if (sd == nullptr)
  {
    // Boundary nodes have no owning SemanticData.
    return;
  }
  switch (actionType)
  {
    case SemanticActionType::tap:
      sd->fireSemanticTap();
      break;
    case SemanticActionType::increase:
      sd->fireSemanticIncrease();
      break;
    case SemanticActionType::decrease:
      sd->fireSemanticDecrease();
      break;
  }
}

namespace
{
// Where the change window of the innermost state machine advancing on this
// thread starts (its SMIBindables::changeBaseline), or kNotAdvancing outside
// any advance. A machine made or reset meanwhile starts in that window, see
// StateMachineInstance::forgetViewModelChanges.
constexpr uint64_t kNotAdvancing = std::numeric_limits<uint64_t>::max();
thread_local uint64_t s_advancingChangeBaseline = kNotAdvancing;

// Publishes a machine's change window while it advances. One that tracks no
// view model changes has no window, and leaves the enclosing machine's without
// touching the thread local, which most rows of a long list would otherwise
// pay for every advance.
class AdvancingChangeWindow
{
public:
  explicit AdvancingChangeWindow(const SMIBindables* bindables)
      : m_published(bindables != nullptr)
  {
    if (m_published)
    {
      m_outer = s_advancingChangeBaseline;
      s_advancingChangeBaseline = bindables->changeBaseline;
    }
  }
  // Restores rather than pops, so the next scope out undoes one a Luau
  // error longjmped past.
  ~AdvancingChangeWindow()
  {
    if (m_published)
    {
      s_advancingChangeBaseline = m_outer;
    }
  }
  AdvancingChangeWindow(const AdvancingChangeWindow&) = delete;
  AdvancingChangeWindow& operator=(const AdvancingChangeWindow&) = delete;

private:
  bool m_published;
  uint64_t m_outer = 0;
};
} // namespace

bool StateMachineInstance::advance(float seconds, bool newFrame)
{
  RIVE_PROF_SCOPE()
  if (m_drawOrderChangeCounter != m_artboardInstance->drawOrderChangeCounter())
  {
    m_drawOrderChangeCounter = m_artboardInstance->drawOrderChangeCounter();
    sortHitComponents();
  }
  // View model changes the last frame's transition searches could see have
  // had their frame. See viewModelValueChanged.
  auto* bindables = m_bindables.get();
  if (newFrame && bindables != nullptr)
  {
    // With a window per layer, each moves to where its own latest search
    // started, so a change a later layer made after an earlier one
    // searched is still pending for the earlier one.
    if (auto* windows = bindables->layerChanges.get())
    {
      uint64_t earliest = std::numeric_limits<uint64_t>::max();
      for (size_t i = 0; i < m_layerCount; i++)
      {
        windows[i].baseline = windows[i].searched;
        earliest = std::min(earliest, windows[i].baseline);
      }
      bindables->changeBaseline = earliest;
    }
    else
    {
      bindables->changeBaseline = bindables->changeSearched;
    }
    bindables->changesUsed.clear();
    // applyEvents below handles every listener report so far.
    bindables
        ->listenerBaseline = ViewModelInstanceValue::latestChangeSequence();
  }
  // Machines made or reset while this one advances, such as the ones a list
  // makes for its rows as its data binds apply, start in this frame.
  AdvancingChangeWindow changeWindow(bindables);
  if (newFrame)
  {
    processFocusEvents();
    processSemanticEvents();
    applyEvents();
    m_needsAdvance = false;
  }
  // Poses re-apply when anything reached the artboard since the previous
  // advance started (see StateMachineLayerInstance::isPoseInPlace).
  const uint32_t poseSince = m_advanceChangeSerial;
  m_advanceChangeSerial = m_artboardInstance->changeSerial();
  updateDataBinds(false);
  for (size_t i = 0; i < m_layerCount; i++)
  {
    if (m_layers[i].advance(this, seconds, newFrame, poseSince))
    {
      m_needsAdvance = true;
    }
  }

  if (advanceDataBinds(seconds))
  {
    m_needsAdvance = true;
  }

  if (m_inputInstances.size() > 0)
  {
    for (auto inst : m_inputInstances)
    {
      inst->advanced();
    }
  }
  return m_needsAdvance || hasPendingReports();
}

void StateMachineInstance::reset() {}

bool StateMachineInstance::advanceAndApply(float seconds)
{
  // This is the host's per-frame entry point, and it reaches the artboard
  // through advanceInternal, which skips the poll Artboard::advance does.
  // Deliver finished async work (script image decodes, fetches) here so
  // their promises resolve before script callbacks run.
  m_artboardInstance->pollAsyncWork();
  if (m_artboardInstance->advanceWatermark(seconds))
  {
    // The file's watermark is playing: settle the artboard at time zero so
    // its first frame is ready the instant the watermark ends, but don't
    // let it animate forward. Reporting "keep going" matters here, a false
    // would read as settled and stop the host's ticker mid pre-roll.
    advanceAndApply(0.0f, true);
    return true;
  }
  // Keep going while this artboard's scripts have async work outstanding,
  // even once settled: a host that stops ticking on false would never poll
  // the result in.
  return advanceAndApply(seconds, true) ||
         m_artboardInstance->hasPendingAsyncWork();
}

bool StateMachineInstance::advanceAndApply(
    float seconds,
    bool /*advanceViewModels*/)
{
  RIVE_PROF_SCOPE_L(1)
  // Advancing by 0 could return false, when it shouldn't. Force keepGoing
  // to true.
  bool keepGoing = this->advance(seconds, true) || seconds == 0.0f;
  // The artboard's advances and updates below make machines too, in the
  // frame advance just started.
  AdvancingChangeWindow changeWindow(m_bindables.get());
  if (focusManager())
  {
    focusManager()->dropFocusIfFocusTargetHidden();
  }
  if (m_artboardInstance->advanceInternal(
          seconds,
          AdvanceFlags::IsRoot | AdvanceFlags::Animate |
              AdvanceFlags::AdvanceNested | AdvanceFlags::NewFrame))
  {
    keepGoing = true;
  }

  for (int outerOptionC = 0; outerOptionC < 5; outerOptionC++)
  {
    if (m_artboardInstance->updatePass(true))
    {
      keepGoing = true;
    }

    // Authoritative drain: updatePass has recomputed renderOpacity and
    // propagated collapse, so target eligibility can be measured against
    // real values. Reaches nested artboards and artboard-component-list
    // items too, since they share this manager. A target can still need
    // several passes to settle, so a request that doesn't take here is
    // kept for the next iteration.
    if (focusManager())
    {
      focusManager()->processPendingFocusRequests(rootArtboard());
      focusManager()->dropFocusIfFocusTargetHidden(rootArtboard());
    }

    // Advance all animations.
    if (this->tryChangeState())
    {
      this->advance(0.0f, false);
      keepGoing = true;
    }

    if (m_artboardInstance->advanceInternal(
            0.0f,
            AdvanceFlags::IsRoot | AdvanceFlags::Animate |
                AdvanceFlags::AdvanceNested))
    {
      keepGoing = true;
    }

    if (!m_artboardInstance->hasDirt(ComponentDirt::Components) &&
        !m_artboardInstance->hasDirtyLayout())
    {
      break;
    }
  }
  // Last chance for this frame: picks up a request queued by the loop's
  // final tryChangeState, and drops anything that still can't take so an
  // unreachable target doesn't leave a request queued indefinitely.
  if (focusManager())
  {
    focusManager()->finishPendingFocusRequests(rootArtboard());
  }
  return keepGoing || hasPendingReports();
}

void StateMachineInstance::markNeedsAdvance()
{
  m_needsAdvance = true;
  wakeRow();
}
bool StateMachineInstance::needsAdvance() const { return m_needsAdvance; }

void StateMachineInstance::resetState()
{
  wakeRow();
  // Starting over, e.g. as a list reuses this instance for another item:
  // nothing pending from before carries into the new run.
  forgetViewModelChanges();
  // Focus and semantic events queued for the previous run (the blur a row
  // gets when it leaves its list) would act on the next one's data.
  if (auto* extras = inputExtras())
  {
    extras->queuedFocusEvents.clear();
    extras->queuedSemanticEvents.clear();
  }
  // So would a gesture still in flight: a press on the previous item would
  // complete as a click on the next one.
  for (auto& listenerGroup : m_listenerGroups)
  {
    listenerGroup->releaseAllPointers();
  }
  for (size_t i = 0; i < m_layerCount; i++)
  {
    m_layers[i].resetState(this);
  }
}

std::string StateMachineInstance::name() const { return m_machine->name(); }

SMIInput* StateMachineInstance::input(size_t index) const
{
  if (index < m_inputInstances.size())
  {
    return m_inputInstances[index];
  }
  return nullptr;
}

template <typename SMType, typename InstType>
InstType* StateMachineInstance::getNamedInput(const std::string& name) const
{
  for (const auto inst : m_inputInstances)
  {
    auto input = inst->input();
    if (input->is<SMType>() && input->name() == name)
    {
      return static_cast<InstType*>(inst);
    }
  }
  return nullptr;
}

SMIBool* StateMachineInstance::getBool(const std::string& name) const
{
  return getNamedInput<StateMachineBool, SMIBool>(name);
}
SMINumber* StateMachineInstance::getNumber(const std::string& name) const
{
  return getNamedInput<StateMachineNumber, SMINumber>(name);
}
SMITrigger* StateMachineInstance::getTrigger(const std::string& name) const
{
  return getNamedInput<StateMachineTrigger, SMITrigger>(name);
}

void StateMachineInstance::setViewModelInstance(
    rcp<ViewModelInstance> viewModelInstance)
{
  if (viewModelInstance == nullptr)
  {
    return;
  }
  if (dataBindContext() == nullptr)
  {
    dataBindContext(make_rcp<DataContext>(viewModelInstance));
    dataBindContext()->addDependentContainer(this);
    return;
  }
  // The data context re-points every attached container (this state machine,
  // the artboard, and any sibling state machines sharing the context) off the
  // old main and onto the new one.
  dataBindContext()->setMainViewModelInstance(viewModelInstance);
}

bool StateMachineInstance::setGlobalViewModelInstance(
    const std::string& name,
    rcp<ViewModelInstance> viewModelInstance)
{
  // A null instance is allowed: it empties the named slot below.
  auto file = m_artboardInstance->file();
  if (file == nullptr)
  {
    return false;
  }
  // The slot is addressed by the named view model (its file index), not by
  // the instance's own view model — so an override instance of a different
  // view model can be placed on the slot.
  uint32_t slotKey = file->viewModelId(name);
  if (slotKey >= file->viewModelCount())
  {
    return false;
  }
  // Only global view models get a slot; a non-global name is not a valid
  // global slot and must not be slotted.
  auto slotViewModel = file->viewModel(slotKey);
  if (slotViewModel == nullptr ||
      static_cast<ViewModelType>(slotViewModel->viewModelType()) !=
          ViewModelType::global)
  {
    return false;
  }
  if (dataBindContext() == nullptr)
  {
    // Nothing to clear when there is no context yet; only create one when
    // actually placing an instance.
    if (viewModelInstance == nullptr)
    {
      return true;
    }
    dataBindContext(make_rcp<DataContext>(rcp<ViewModelInstance>(nullptr)));
    dataBindContext()->addDependentContainer(this);
  }
  // The data context re-points every attached container off any previous
  // instance occupying this slot and onto the new one (or empties the slot
  // when the instance is null).
  dataBindContext()->setViewModelInstanceForSlot(slotKey, viewModelInstance);
  return true;
}

void StateMachineInstance::bind()
{
  if (dataBindContext() == nullptr)
  {
    // No data context yet: create an empty one so the view model
    // instances it needs can be completed on the fly below.
    dataBindContext(make_rcp<DataContext>(rcp<ViewModelInstance>(nullptr)));
    dataBindContext()->addDependentContainer(this);
  }
  // Make sure every view model instance the data context needs exists before
  // it is applied: the main instance plus one for each global view model.
  // Any that are missing are created (completed) on the fly.
  completeViewModelInstances();
  // Apply the current data context: rebind the artboard and state machine
  // data binds in a single pass.
  m_artboardInstance->internalDataContext(dataBindContext());
  internalDataContext(dataBindContext());
}

void StateMachineInstance::completeViewModelInstances()
{
  auto file = m_artboardInstance->file();
  if (file == nullptr)
  {
    return;
  }
  // Ensure a main instance is present. The main is the entry not on the slot
  // keys; if there is none, create the artboard's default and place it first.
  if (dataBindContext()->mainViewModelInstance() == nullptr)
  {
    auto main = file->createDefaultViewModelInstance(m_artboardInstance);
    if (main != nullptr)
    {
      // setMainViewModelInstance re-points every attached container onto
      // the new instance.
      dataBindContext()->setMainViewModelInstance(main);
    }
  }
  // Ensure an instance exists for each global view model slot, creating any
  // missing ones. Occupancy is checked by slot key, so a cross-view-model
  // override already sitting in a slot is not treated as empty.
  for (auto* viewModel : file->globalViewModels())
  {
    uint32_t slotKey = file->viewModelId(viewModel->name());
    if (dataBindContext()->instanceForSlot(slotKey) != nullptr)
    {
      continue;
    }
    auto instance = file->createDefaultViewModelInstance(viewModel);
    if (instance != nullptr)
    {
      // setViewModelInstanceForSlot re-points every attached container
      // onto the new instance.
      dataBindContext()->setViewModelInstanceForSlot(slotKey, instance);
    }
  }
}

void StateMachineInstance::bindViewModelInstance(
    rcp<ViewModelInstance> viewModelInstance)
{
  if (viewModelInstance == nullptr)
  {
    clearDataContext();
    m_artboardInstance->unbind();
    return;
  }
  setViewModelInstance(std::move(viewModelInstance));
  bind();
}

rcp<ViewModelInstance> StateMachineInstance::globalViewModelInstance(
    const std::string& name)
{
  // Pure read: returns the instance in the named slot only if one has been
  // set/bound; never creates.
  if (dataBindContext() == nullptr)
  {
    return nullptr;
  }
  auto file = m_artboardInstance->file();
  if (file == nullptr)
  {
    return nullptr;
  }
  return dataBindContext()->instanceForSlot(file->viewModelId(name));
}

void StateMachineInstance::bindDataContext(rcp<DataContext> dataContext)
{
  clearDataContext();
  dataContext->addDependentContainer(this);
  m_artboardInstance->clearDataContext();
  m_artboardInstance->internalDataContext(dataContext);
  internalDataContext(dataContext);
}

void StateMachineInstance::inheritDataContext(rcp<DataContext> dataContext)
{
  if (dataContext == nullptr)
  {
    return;
  }
  dataContext->addDependentContainer(this);
  internalDataContext(dataContext);
}

void StateMachineInstance::dataContext(rcp<DataContext> dataContext)
{
  clearDataContext();
  internalDataContext(dataContext);
}

void StateMachineInstance::initScriptedObjects()
{
  auto* scripting = m_scripting.get();
  if (scripting == nullptr)
  {
    return;
  }
  for (auto& obj : scripting->objects)
  {
    if (obj.second->scriptAsset() != nullptr)
    {
      if (!obj.second->userLuaInitDone())
      {
        obj.second->scriptAsset()->initScriptedObject(obj.second);
      }
      obj.second->hydrateScriptInputs();
    }
  }
}

void StateMachineInstance::internalDataContext(rcp<DataContext> dataContext)
{
  // A root machine whose artboard hosts others tracks view model changes
  // from its bind on, however it is bound, even if none of its own
  // conditions read them: the machines its lists and nested artboards make
  // while it advances start in its frame (see forgetViewModelChanges). A
  // hosted machine without a window of its own leaves them the enclosing
  // machine's. Checked at bind rather than at creation, since a nested
  // artboard makes its machines before it gets its host.
  if (m_artboardInstance->host() == nullptr &&
      m_artboardInstance->hostsArtboards())
  {
    ensureBindables();
  }
  bindDataBindsFromContext(dataContext);
  if (auto* reporting = this->reporting())
  {
    for (auto listenerViewModel : reporting->listenerViewModels)
    {
      listenerViewModel->bindFromContext(dataContext);
    }
  }
  if (auto* scripting = m_scripting.get())
  {
    for (auto& scriptedObjectItr : scripting->objects)
    {
      scriptedObjectItr.second->dataContext(dataContext);
    }
  }
  initScriptedObjects();
}

void StateMachineInstance::rebind()
{
  m_artboardInstance->clearDataContext();
  m_artboardInstance->internalDataContext(dataBindContext());
  internalDataContext(dataBindContext());
};

void StateMachineInstance::clearDataContext()
{
  if (dataBindContext() != nullptr)
  {
    dataBindContext()->removeDependentContainer(this);
    dataBindContext(nullptr);
  }
  if (auto* reporting = this->reporting())
  {
    for (auto& listenerViewModel : reporting->listenerViewModels)
    {
      listenerViewModel->clearDataContext();
    }
  }
}

void StateMachineInstance::mainViewModelInstanceChanged()
{
  unsettleLayers();
  if (m_artboardInstance != nullptr)
  {
    m_artboardInstance->mainViewModelInstanceChanged();
  }
}

void StateMachineInstance::unsettleLayers()
{
  // Whatever unsettles a layer can change a quiet row too.
  wakeRow();
  if (!m_anySettled)
  {
    return;
  }
  m_anySettled = false;
  for (uint32_t i = 0; i < m_layerCount; i++)
  {
    m_layers[i].unsettle();
  }
}

void StateMachineInstance::wakeRow()
{
  if (m_artboardInstance != nullptr && !m_destroying)
  {
    m_artboardInstance->wakeIfQuietRow();
  }
}

AdvancingComponent::QuietState StateMachineInstance::rowQuietState()
{
  using QuietState = AdvancingComponent::QuietState;
  // Scripts do work this can't see into.
  if (m_scripting.get() != nullptr)
  {
    return QuietState::never;
  }
  // Cheapest first: a busy row is checked again every frame.
  if (m_needsAdvance || m_bindsPending || hasDataBindWork() ||
      m_drawOrderChangeCounter != m_artboardInstance->drawOrderChangeCounter())
  {
    return QuietState::busy;
  }
  if (auto* reporting = this->reporting())
  {
    if (!reporting->reportedEvents.empty() ||
        !reporting->reportingEvents.empty() ||
        !reporting->eventsAppliedDuringLoop.empty() ||
        !reporting->reportedListenerViewModels.empty() ||
        !reporting->reportingListenerViewModels.empty())
    {
      return QuietState::busy;
    }
  }
  if (auto* extras = inputExtras())
  {
    if (!extras->queuedFocusEvents.empty() ||
        !extras->queuedSemanticEvents.empty())
    {
      return QuietState::busy;
    }
  }
  // Every layer frozen, and none changed state last frame (a new frame's
  // advance clears that).
  for (uint32_t i = 0; i < m_layerCount; i++)
  {
    if (!m_layers[i].isFrozen(this, m_advanceChangeSerial) ||
        m_layers[i].stateChangedOnAdvance())
    {
      return QuietState::busy;
    }
  }
  // Converters that advance can't say whether they would.
  return mayAdvanceDataBinds() ? QuietState::never : QuietState::quiet;
}

void StateMachineInstance::addDirtyDataBind(DataBind* dataBind)
{
  // A bound value is about to change. Layers that settled on the old one
  // must search again, and none may settle until it has been applied. Set
  // before the base, which skips binds already queued or polled.
  m_bindsPending = true;
  unsettleLayers();
  DataBindContainer::addDirtyDataBind(dataBind);
}

void StateMachineInstance::updateDataBinds(bool applyTargetToSource)
{
  // A nested call returns without applying anything, so only the outer pass
  // clears this; binds dirtied while it runs set it again.
  if (!isProcessingDataBinds())
  {
    m_bindsPending = false;
  }
  DataBindContainer::updateDataBinds(applyTargetToSource);
}

void StateMachineInstance::dataContextChanged()
{
  // View model conditions only evaluate with a data context.
  unsettleLayers();
}

void StateMachineInstance::dropInstanceValueBindsTargeting(Core* target)
{
  DataBindContainer::dropInstanceValueBindsTargeting(target);
  if (m_artboardInstance != nullptr)
  {
    m_artboardInstance->dropInstanceValueBindsTargeting(target);
  }
}

void StateMachineInstance::relinkDataContext()
{
  unsettleLayers();
  m_artboardInstance->relinkDataContext();
}

void StateMachineInstance::rebuildDataBind(DataBind* dataBind)
{
  if (dataBind->is<DataBindContext>())
  {
    dataBind->as<DataBindContext>()->bindFromContext(dataBindContext().get());
  }
};

void StateMachineInstance::unbind()
{
  clearDataContext();
  unbindDataBinds();
}

size_t StateMachineInstance::stateChangedCount() const
{
  size_t count = 0;
  for (size_t i = 0; i < m_layerCount; i++)
  {
    if (m_layers[i].stateChangedOnAdvance())
    {
      count++;
    }
  }
  return count;
}

const LayerState* StateMachineInstance::stateChangedByIndex(size_t index) const
{
  size_t count = 0;
  for (size_t i = 0; i < m_layerCount; i++)
  {
    if (m_layers[i].stateChangedOnAdvance())
    {
      if (count == index)
      {
        return m_layers[i].currentState();
      }
      count++;
    }
  }
  return nullptr;
}

size_t StateMachineInstance::currentAnimationCount() const
{
  size_t count = 0;
  for (size_t i = 0; i < m_layerCount; i++)
  {
    if (m_layers[i].currentAnimation() != nullptr)
    {
      count++;
    }
  }
  return count;
}

const LinearAnimationInstance* StateMachineInstance::currentAnimationByIndex(
    size_t index) const
{
  size_t count = 0;
  for (size_t i = 0; i < m_layerCount; i++)
  {
    if (m_layers[i].currentAnimation() != nullptr)
    {
      if (count == index)
      {
        return m_layers[i].currentAnimation();
      }
      count++;
    }
  }
  return nullptr;
}

bool StateMachineInstance::hasPendingReports() const
{
  auto* reporting = this->reporting();
  return reporting != nullptr &&
         (!reporting->reportedEvents.empty() ||
          !reporting->reportedListenerViewModels.empty());
}

void StateMachineInstance::reportEvent(Event* event, float delaySeconds)
{
  wakeRow();
  ensureReporting().reportedEvents.push_back(EventReport(event, delaySeconds));
}

void StateMachineInstance::reportListenerViewModel(
    ListenerViewModel* listenerViewModel)
{
  wakeRow();
  ensureReporting().reportedListenerViewModels.push_back(listenerViewModel);
}

std::size_t StateMachineInstance::reportedEventCount() const
{
  auto* reporting = this->reporting();
  if (reporting == nullptr)
  {
    return 0;
  }
  return reporting->eventsAppliedDuringLoop.size() +
         reporting->reportedEvents.size();
}

const EventReport StateMachineInstance::reportedEventAt(std::size_t index) const
{
  auto* reporting = this->reporting();
  if (reporting == nullptr)
  {
    return EventReport(nullptr, 0.0f);
  }
  if (index < reporting->eventsAppliedDuringLoop.size())
  {
    return reporting->eventsAppliedDuringLoop[index];
  }
  index -= reporting->eventsAppliedDuringLoop.size();
  if (index >= reporting->reportedEvents.size())
  {
    return EventReport(nullptr, 0.0f);
  }
  return reporting->reportedEvents[index];
}

void StateMachineInstance::notify(
    const std::vector<EventReport>& events,
    NestedArtboard* context)
{
  notifyEventListeners(events, context);
  updateDataBinds(false);
}

void StateMachineInstance::notifyListenerViewModels(
    const std::vector<ListenerViewModel*>& events)
{
  if (events.size() > 0)
  {
    for (auto& listenerViewModel : events)
    {
      listenerViewModel->listener()->performChanges(
          this,
          ListenerInvocation::viewModelChange(listenerViewModel));
    }
  }
}

void StateMachineInstance::notifyEventListeners(
    const std::vector<EventReport>& events,
    NestedArtboard* source)
{
  if (events.size() > 0)
  {
    // We trigger the listeners in order
    for (size_t i = 0; i < m_machine->listenerCount(); i++)
    {
      auto listener = m_machine->listener(i);
      auto target = artboard()->resolve(listener->targetId());
      if (listener != nullptr && listener->hasListener(ListenerType::event) &&
          (source == nullptr || source == target))
      {
        for (const auto event : events)
        {
          auto sourceArtboard = source == nullptr ? artboard()
                                                  : source->artboardInstance();

          // NOTE: this issue can't happen anymore because a new
          // fix in the editor prevents selecting other artboard
          // as target. But the fix is kept here to fix older
          // files. listener->eventId() can point to an id from an
          // event in the context of this artboard or the
          // context of a nested artboard. Because those ids
          // belong to different contexts, they can have the
          // same value. So when the eventId is resolved
          // within one context, but actually pointing to the
          // other, it can return the wrong event object. If,
          // by chance, that event exists in the other
          // context, and is being reported, it will trigger
          // the wrong set of actions. This validation makes
          // sure that a listener must be targetting the
          // current artboard to disambiguate between external
          // and internal events.
          if (source == nullptr)
          {
            auto target = sourceArtboard->resolve(listener->targetId());
            if (target && target != artboard() && !target->is<Event>())
            {
              continue;
            }
          }
          if (listener->is<StateMachineListenerSingle>())
          {
            auto listenerEvent = sourceArtboard->resolve(
                listener->as<StateMachineListenerSingle>()->eventId());
            if (listenerEvent == event.event())
            {
              listener->performChanges(
                  this,
                  ListenerInvocation::reportedEvent(
                      event.event(),
                      event.secondsDelay()));
              break;
            }
          }
          else
          {
            size_t index = 0;
            while (index < listener->listenerInputTypeCount())
            {
              auto listenerInputType = listener->listenerInputType(index);
              if (listenerInputType->is<ListenerInputTypeEvent>())
              {

                auto listenerInputTypeEvent = listenerInputType->as<
                    ListenerInputTypeEvent>();
                auto listenerEvent = sourceArtboard->resolve(
                    listenerInputTypeEvent->eventId());
                if (listenerEvent == event.event())
                {
                  listener->performChanges(
                      this,
                      ListenerInvocation::reportedEvent(
                          event.event(),
                          event.secondsDelay()));
                  break;
                }
              }
              index += 1;
            }
          }
        }
      }
    }
    // Bubble the event up to parent artboard state machines
    // immediately
    for (auto listener : nestedEventListeners())
    {
      listener->notify(events, nestedArtboard());
    }

    for (auto report : events)
    {
      auto event = report.event();
      if (event->is<AudioEvent>())
      {
        event->as<AudioEvent>()->play();
      }
    }
  }
}

void StateMachineInstance::enablePointerEvents(int pointerId)
{
  m_disabledPointerIds.eraseAll(pointerId);
  for (const auto& hitShape : m_hitComponents)
  {
    hitShape->enablePointerEvents(pointerId);
  }
  if (auto* extras = inputExtras())
  {
    for (const auto& group : extras->captureGroups)
    {
      group->enable(pointerId);
    }
  }
  // A drag ending turns everything back on, but a capture claim here still
  // holds until its own release.
  applyPointerClaims(pointerId);
}

void StateMachineInstance::disablePointerEvents(int pointerId)
{
  m_disabledPointerIds.pushUnique(pointerId);
  for (const auto& hitShape : m_hitComponents)
  {
    hitShape->disablePointerEvents(pointerId);
  }
  if (auto* extras = inputExtras())
  {
    for (const auto& group : extras->captureGroups)
    {
      group->disable(pointerId);
    }
  }
}

bool StateMachineInstance::isPointerDisabled(int pointerId) const
{
  const auto& ids = m_disabledPointerIds.view();
  return std::find(ids.begin(), ids.end(), pointerId) != ids.end();
}

HitResult StateMachineInstance::hoverExit(Vec2D position, int pointerId)
{
  const bool disabled = isPointerDisabled(pointerId);
  // The exit releases every group's state for the pointer, the disabled
  // phase among them, so what turned the pointer off has to again.
  HitResult result = pointerExit(position, pointerId);
  if (disabled)
  {
    disablePointerEvents(pointerId);
  }
  return result;
}

BindableProperty* StateMachineInstance::bindablePropertyInstance(
    BindableProperty* bindableProperty) const
{
  auto* bindables = this->bindables();
  if (bindables == nullptr)
  {
    return nullptr;
  }
  return bindables->propertyInstances.find(bindableProperty);
}

DataBind* StateMachineInstance::bindableDataBindToSource(
    BindableProperty* bindableProperty) const
{
  auto* bindables = this->bindables();
  if (bindables == nullptr)
  {
    return nullptr;
  }
  auto dataBind = bindables->dataBindsToSource.find(bindableProperty);
  if (dataBind == bindables->dataBindsToSource.end())
  {
    return nullptr;
  }
  return dataBind->second;
}

DataBind* StateMachineInstance::bindableDataBindToTarget(
    BindableProperty* bindableProperty) const
{
  auto* bindables = this->bindables();
  if (bindables == nullptr)
  {
    return nullptr;
  }
  auto dataBind = bindables->dataBindsToTarget.find(bindableProperty);
  if (dataBind == bindables->dataBindsToTarget.end())
  {
    return nullptr;
  }
  return dataBind->second;
}

size_t StateMachineInstance::layerIndex(
    const StateMachineLayerInstance* layer) const
{
  // The layers are one array, so a layer's index is its offset in it.
  // std::less orders pointers that aren't into the array too.
  std::less<const StateMachineLayerInstance*> before;
  if (layer == nullptr || before(layer, m_layers) ||
      !before(layer, m_layers + m_layerCount))
  {
    return m_layerCount;
  }
  return static_cast<size_t>(layer - m_layers);
}

uint64_t StateMachineInstance::changeBaselineFor(
    const StateMachineLayerInstance* layer) const
{
  auto* bindables = this->bindables();
  if (bindables == nullptr)
  {
    return 0;
  }
  auto* windows = bindables->layerChanges.get();
  size_t index = layerIndex(layer);
  return windows != nullptr && index < m_layerCount ? windows[index].baseline
                                                    : bindables->changeBaseline;
}

bool StateMachineInstance::changePending(
    uint64_t changeSequence,
    const StateMachineLayerInstance* layer) const
{
  return bindables() != nullptr && changeSequence > changeBaselineFor(layer);
}

bool StateMachineInstance::viewModelTriggerPendingForListeners(
    const ViewModelInstanceValue* trigger) const
{
  auto* bindables = this->bindables();
  return bindables != nullptr &&
         trigger->changeSequence() > bindables->listenerBaseline;
}

bool StateMachineInstance::viewModelValueChanged(
    const ViewModelInstanceValue* value,
    const StateMachineLayerInstance* layer) const
{
  auto* bindables = this->bindables();
  if (bindables == nullptr ||
      value->changeSequence() <= changeBaselineFor(layer))
  {
    return false;
  }
  for (const auto& used : bindables->changesUsed)
  {
    if (used.first == layer && used.second == value)
    {
      return false;
    }
  }
  return true;
}

void StateMachineInstance::useViewModelValue(
    const ViewModelInstanceValue* value,
    const StateMachineLayerInstance* layer) const
{
  auto* bindables = this->bindables();
  if (bindables == nullptr)
  {
    return;
  }
  for (const auto& used : bindables->changesUsed)
  {
    if (used.first == layer && used.second == value)
    {
      return;
    }
  }
  bindables->changesUsed.emplace_back(layer, value);
}

void StateMachineInstance::markViewModelChangesSearched(
    const StateMachineLayerInstance* layer)
{
  auto* bindables = m_bindables.get();
  if (bindables == nullptr)
  {
    return;
  }
  auto latest = ViewModelInstanceValue::latestChangeSequence();
  bindables->changeSearched = latest;
  SMILayerChangeWindow* window = nullptr;
  if (auto* windows = bindables->layerChanges.get())
  {
    size_t index = layerIndex(layer);
    if (index < m_layerCount)
    {
      window = &windows[index];
      window->searched = latest;
    }
  }
  // A host above that stopped advancing this instance (collapsed or paused)
  // marks the changes made meanwhile. They had their frame while this
  // instance couldn't run, so they aren't pending for it now that it does.
  uint64_t inactive = 0;
  for (const Artboard* artboard = m_artboardInstance;
       artboard != nullptr && artboard->host() != nullptr;
       artboard = artboard->host()->parentArtboard())
  {
    inactive = std::max(inactive, artboard->host()->inactiveChangeSequence());
  }
  if (inactive > bindables->changeBaseline)
  {
    bindables->changeBaseline = inactive;
  }
  if (window != nullptr && inactive > window->baseline)
  {
    window->baseline = inactive;
  }
}

void StateMachineInstance::markFrozenLayerSearched(
    const StateMachineLayerInstance* layer)
{
  // Only a layer's own window goes stale this way. The instance's moves with
  // every other layer's search, as it always has, and its next search
  // applies a collapsed host's mark (markViewModelChangesSearched).
  auto* bindables = m_bindables.get();
  auto* windows = bindables == nullptr ? nullptr
                                       : bindables->layerChanges.get();
  if (windows == nullptr)
  {
    return;
  }
  size_t index = layerIndex(layer);
  if (index < m_layerCount)
  {
    windows[index].searched = ViewModelInstanceValue::latestChangeSequence();
  }
}

void StateMachineInstance::forgetViewModelChanges()
{
  if (auto* bindables = m_bindables.get())
  {
    auto latest = ViewModelInstanceValue::latestChangeSequence();
    // Made or reset while another machine advances, as a list makes its
    // rows' machines, this instance starts in that machine's frame: what
    // is still pending there is pending here too, so a fire made just
    // before the frame that makes a row reaches it. Otherwise nothing made
    // so far is.
    uint64_t start = s_advancingChangeBaseline != kNotAdvancing
                         ? s_advancingChangeBaseline
                         : latest;
    bindables->changeBaseline = bindables->changeSearched = start;
    // Only a machine whose conditions read pending changes keeps a window
    // per layer; for the rest, the instance's is all anything reads.
    if (m_machine != nullptr && m_machine->readsPendingChanges() &&
        m_layerCount > 0)
    {
      if (bindables->layerChanges == nullptr)
      {
        bindables->layerChanges = std::make_unique<SMILayerChangeWindow[]>(
            m_layerCount);
      }
      std::fill_n(
          bindables->layerChanges.get(),
          m_layerCount,
          SMILayerChangeWindow{start, start});
    }
    bindables->listenerBaseline = latest;
    bindables->changesUsed.clear();
  }
}

BindablePropertyNumber* StateMachineInstance::findTransitionPropertyInstance(
    const StateTransition* transition,
    uint32_t propertyKey) const
{
  auto* bindables = this->bindables();
  if (bindables == nullptr)
  {
    return nullptr;
  }
  auto it = bindables->transitionPropertyInstances.find(transition);
  if (it != bindables->transitionPropertyInstances.end())
  {
    auto propIt = it->second.find(propertyKey);
    if (propIt != it->second.end())
    {
      return propIt->second;
    }
  }
  return nullptr;
}

bool StateMachineInstance::hasFocusNodes()
{
  if (!focusManager())
  {
    return false;
  }
  auto* fm = focusManager();
  return fm->hasFocusableContent();
}

bool StateMachineInstance::focusNext()
{
  if (!focusManager())
  {
    return false;
  }
  auto* fm = focusManager();
  return fm->focusNext();
}

bool StateMachineInstance::focusPrevious()
{
  if (!focusManager())
  {
    return false;
  }
  auto* fm = focusManager();
  return fm->focusPrevious();
}

bool StateMachineInstance::focusLeft()
{
  if (!focusManager())
  {
    return false;
  }
  auto* fm = focusManager();
  return fm->focusLeft();
}

bool StateMachineInstance::focusRight()
{
  if (!focusManager())
  {
    return false;
  }
  auto* fm = focusManager();
  return fm->focusRight();
}

bool StateMachineInstance::focusUp()
{
  if (!focusManager())
  {
    return false;
  }
  auto* fm = focusManager();
  return fm->focusUp();
}

bool StateMachineInstance::focusDown()
{
  if (!focusManager())
  {
    return false;
  }
  auto* fm = focusManager();
  return fm->focusDown();
}

void StateMachineInstance::clearFocus()
{
  if (!focusManager())
  {
    return;
  }
  auto* fm = focusManager();
  fm->clearFocus();
}

bool StateMachineInstance::keyInput(
    Key key,
    KeyModifiers modifiers,
    bool isPressed,
    bool isRepeat)
{
  if (!focusManager())
  {
    return false;
  }
  auto* fm = focusManager();
  return fm->keyInput(key, modifiers, isPressed, isRepeat);
}

bool StateMachineInstance::textInput(const std::string& text)
{
  if (!focusManager())
  {
    return false;
  }
  auto* fm = focusManager();
  return fm->textInput(text);
}

std::string StateMachineInstance::selectedText() const
{
  const auto* fm = focusManager();
  if (!fm)
  {
    return "";
  }
  return fm->selectedText();
}
