#include "rive/artboard.hpp"
#include "rive/artboard_clusters.hpp"
#include "rive/data_bind/host_data_context_consumer.hpp"
#include "rive/file.hpp"
#ifdef WITH_RIVE_SCRIPTING_WASM
#include "rive/wasm/wasm_scripting_vm.hpp"
#endif
#include "rive/animation/keyframe_interpolator.hpp"
#include "rive/artboard_component_list.hpp"
#include "rive/backboard.hpp"
#include "rive/component.hpp"
#include "rive/container_component.hpp"
#include "rive/focus_data.hpp"
#include "rive/input/focus_manager.hpp"
#include "rive/semantic/semantic_data.hpp"
#include "rive/semantic/semantic_manager.hpp"
#include "rive/semantic/semantic_node.hpp"
#include "rive/input/focusable.hpp"
#include "rive/animation/linear_animation_instance.hpp"
#include "rive/custom_property_color.hpp"
#include "rive/custom_property_number.hpp"
#include "rive/custom_property_trigger.hpp"
#include "rive/math/math_types.hpp"
#include "rive/shapes/paint/color.hpp"
#include "rive/dependency_sorter.hpp"
#include "rive/data_bind/data_bind.hpp"
#include "rive/data_bind/data_bind_context.hpp"
#include "rive/draw_rules.hpp"
#include "rive/draw_target.hpp"
#include "rive/audio_event.hpp"
#include "rive/draw_target_placement.hpp"
#include "rive/drawable.hpp"
#include "rive/animation/keyed_object.hpp"
#include "rive/animation/keyframe.hpp"
#include "rive/factory.hpp"
#include "rive/renderer.hpp"
#include "rive/artboard_host.hpp"
#include "rive/shapes/paint/shape_paint.hpp"
#include "rive/shapes/paint/paint_image.hpp"
#include "rive/watermark.hpp"
#include "rive/importers/import_stack.hpp"
#include "rive/importers/backboard_importer.hpp"
#include "rive/layout_component.hpp"
#include "rive/node.hpp"
#include "rive/foreground_layout_drawable.hpp"
#include "rive/nested_artboard.hpp"
#include "rive/nested_artboard_leaf.hpp"
#include "rive/nested_artboard_layout.hpp"
#include "rive/animation/nested_state_machine.hpp"
#include "rive/joystick.hpp"
#include "rive/data_bind/data_bind.hpp"
#include "rive/data_bind_flags.hpp"
#include "rive/animation/nested_bool.hpp"
#include "rive/animation/nested_number.hpp"
#include "rive/animation/nested_trigger.hpp"
#include "rive/viewmodel/viewmodel_instance.hpp"
#include "rive/viewmodel/viewmodel_instance_value.hpp"
#include "rive/viewmodel/viewmodel.hpp"
#include "rive/view_model_type.hpp"
#include "rive/data_bind/data_context.hpp"
#include "rive/animation/state_machine_input_instance.hpp"
#include "rive/animation/state_machine_instance.hpp"
#include "rive/shapes/shape.hpp"
#include "rive/shapes/path_composer.hpp"
#include "rive/text/text_style.hpp"
#include "rive/text/text_variation_helper.hpp"
#include "rive/shapes/clipping_shape.hpp"
#include "rive/text/text_value_run.hpp"
#include "rive/event.hpp"
#include "rive/assets/audio_asset.hpp"
#include "rive/layout/layout_data.hpp"
#include "rive/profiler/profiler_macros.h"
#include "rive/scripted/scripted_object.hpp"
#include "rive/scripted/scripted_interpolator.hpp"
#include "rive/scripted/scripted_data_converter.hpp"
#include "rive/data_bind/converters/data_converter_group.hpp"
#include "rive/data_bind/converters/data_converter_group_item.hpp"
#ifdef WITH_RIVE_SCRIPTING
#ifdef WITH_RIVE_SCRIPTING_LUAU
#include "rive/lua/rive_lua_libs.hpp"
#endif
#endif
#include "rive/async/work_pool.hpp"
#include "rive/bitmap_cache.hpp"
#include "rive/layer_mask.hpp"
#ifdef RIVE_CANVAS
#include "rive/offscreen_raster.hpp"
#include "rive/renderer/render_context.hpp"
#include "rive/renderer/render_canvas.hpp"
#include "rive/renderer/cmd/deferred_canvas_host.hpp"
#include "rive/shapes/paint/image_sampler.hpp"
#include <algorithm>
#include <array>
#include <cmath>
#endif

#include <set>
#include <unordered_map>

using namespace rive;

namespace rive
{
// The live scripted interpolators an ArtboardInstance's layouts run, keyed by
// the source artboard's interpolator they were cloned from. See
// Artboard::statefulInterpolator.
struct ArtboardScriptedInterpolators
{
  std::unordered_map<
      const ScriptedInterpolator*,
      std::unique_ptr<StatefulScriptedInterpolator>>
      bySource;
};
} // namespace rive

uint64_t Artboard::sm_frameId = 0;
#ifdef TESTING
uint64_t Artboard::sm_layoutPassCount = 0;
uint64_t Artboard::sm_dirtNotifications = 0;
uint64_t Artboard::sm_collapsedRunSkips = 0;
#endif

Artboard::Artboard()
{
  // Artboards need to override default clip value to true.
  m_Clip = true;
#ifdef WITH_RIVE_TOOLS
  callbackUserData = this;
#endif
}

#ifdef TESTING
Artboard::Artboard(Factory* factory) : m_Factory(factory) { m_Clip = true; }
#endif

Artboard::~Artboard()
{
  // The boundary node can outlive this artboard: a virtualized list row
  // destroyed from the pool never leaves the semantic tree. Flattening reads
  // this pointer to see whether the host is collapsed, so it must not dangle.
  if (m_semanticBoundaryNode != nullptr)
  {
    m_semanticBoundaryNode->boundaryArtboard(nullptr);
  }
#ifdef WITH_RIVE_EDITOR
  // Borrowed editor instances must retire their arena-owned children before
  // this destructor starts walking the graph. Owned arena entries have
  // already been detached and have no arena by this point.
  if (editorArena() != nullptr)
    editorArena()->ownerDestroyed(this);
#endif
  // Tear the focus tree down FIRST, while every component is still alive.
  // Detaching a focused node clears focus, and that runs blur callbacks
  // (FocusData::blurred walks parents and siblings) — which must not fire
  // once the m_Objects loop below has started deleting those siblings.
  //
  // Only when we own the manager: an adopted one belongs to a host artboard
  // or to Dart, either of which may already be gone by the time a finalizer
  // frees us, so m_activeFocusManager is not safe to touch. Those artboards
  // are cleaned up explicitly by whoever adopted them —
  // NestedArtboard::updateArtboard and ArtboardComponentList::removeArtboard
  // both call cleanupFocusTree() before teardown — and a host being torn
  // down has already run this same block against the shared manager, so
  // nothing in a nested subtree is still focused by the time we reach it.
  if (m_ownedFocusManager != nullptr &&
      m_activeFocusManager == m_ownedFocusManager.get())
  {
#ifdef WITH_RIVE_TOOLS
    m_ownedFocusManager->setFocusChangedCallback(nullptr);
    m_ownedFocusManager->setScrollIntoViewCallback(nullptr);
#endif
    cleanupFocusTree();
  }

#ifdef WITH_RIVE_AUDIO
#ifdef EXTERNAL_RIVE_AUDIO_ENGINE
  auto audioEngine = m_audioEngine != nullptr
                         ? m_audioEngine
                         : AudioEngine::RuntimeEngine(false);
#else
  auto audioEngine = AudioEngine::RuntimeEngine(false);
#endif
  if (audioEngine)
  {
    audioEngine->stop(this);
  }
#endif
  // Layouts here, and in the nested artboards and list items below them,
  // only borrow these clones, and none of them calls an interpolator while
  // tearing down. Each clone pulls the input binds it parked on this
  // artboard before it dies, so do it while the bind list is intact.
  m_scriptedInterpolators.reset();
  unbind();

  // ViewModelInstance and ViewModelInstanceValue inherit from RefCnt.
  //
  // ViewModelInstance (VMI) ownership: the artboard releases every VMI in
  // its m_Objects via unref(). NestedArtboard borrows its stateful child VMI
  // without bumping the refcount; dynamically-created bound VMIs are not in
  // m_Objects and are released by NestedArtboard itself.
  //
  // ViewModelInstanceValue (VMV) ownership: always owned by their parent
  // ViewModelInstance via rcp<> in m_PropertyValues. When VMI is deleted,
  // its destructor clears m_PropertyValues, which unrefs and deletes VMVs.
  //
  // Strategy:
  // 1) Identify VMI/VMV objects by pointer (safe is<>() check BEFORE any
  // deletions).
  // 2) Delete everything else immediately, deferring VMI unref until after
  // hierarchy components are gone.
  std::set<Core*> vmObjects;
  std::set<ViewModelInstance*> deferredVmiUnrefs;

  // First pass: identify ViewModelInstance and ViewModelInstanceValue
  // objects while memory is valid (before any deletions). Precompute which
  // VMIs should be released so we never dereference pointers after deletes.
  // Also detach FocusData from their nodes: with an adopted manager the
  // focus tree above wasn't torn down, and deleting a focused node blurs the
  // chain, which must not call into components already deleted.
  auto preDeletePass = [&](Core* object) {
    if (object == nullptr || object == this)
    {
      return;
    }
    if (object->is<FocusData>())
    {
      object->as<FocusData>()->detachFocusable();
      return;
    }
    if (object->is<ViewModelInstance>())
    {
      vmObjects.insert(object);
      deferredVmiUnrefs.insert(object->as<ViewModelInstance>());
      return;
    }
    if (object->is<ViewModelInstanceValue>())
    {
      vmObjects.insert(object);
    }
  };
  for (auto object : m_Objects)
  {
    preDeletePass(object);
  }
  for (auto object : ownInvalidObjects())
  {
    preDeletePass(object);
  }

  auto isVmObject = [&](Core* object) -> bool {
    return vmObjects.count(object) != 0;
  };

  // Second pass: delete non-VM objects.
  for (auto object : m_Objects)
  {
    if (object == nullptr || object == this)
    {
      continue;
    }
    if (isVmObject(object))
    {
      continue;
    }
    delete object;
  }
  for (auto object : ownInvalidObjects())
  {
    if (object == nullptr)
    {
      continue;
    }
    if (isVmObject(object))
    {
      continue;
    }
    delete object;
  }

  // Now release deferred ViewModelInstances after hierarchy components have
  // been destroyed. Releasing via unref() keeps RefCnt ownership semantics
  // intact and cascades to VMVs via m_PropertyValues rcps.
  for (auto* vmi : deferredVmiUnrefs)
  {
    vmi->unref();
  }

  deleteDataBinds();

  // Instances reference back to the original artboard's animations and state
  // machines, so don't delete them here, they'll get cleaned up when the
  // source is deleted.
  // TODO: move this logic into ArtboardInstance destructor???
  if (!m_IsInstance)
  {
    for (auto object : ownAnimations())
    {
      delete object;
    }
    for (auto object : ownStateMachines())
    {
      delete object;
    }
  }
  m_dirtyLayout.clear();
}

static bool canContinue(StatusCode code)
{
  // We currently only cease loading on invalid object.
  return code != StatusCode::InvalidObject;
}

bool Artboard::validateObjects()
{
  auto size = m_Objects.size();
  // Start every slot valid so an object that fails on the first cycle
  // registers as a change. Starting invalid meant an artboard whose objects
  // all fail never changed, so its orphans survived into initialize().
  std::vector<bool> valid(size, true);

  // Max iterations..
  for (int cycle = 0; cycle < 100; cycle++)
  {
    bool changed = false;
    for (size_t i = 1; i < size; i++)
    {
      auto object = m_Objects[i];
      if (object == nullptr)
      {
        // objects can be null if they were not understood by this
        // runtime.
        continue;
      }
      bool wasValid = valid[i];
      bool isValid = object->validate(this);
      if (wasValid != isValid)
      {
        changed = true;
        valid[i] = isValid;
      }
    }
    if (changed)
    {
      // Delete invalid objects.
      for (size_t i = 1; i < size; i++)
      {
        if (valid[i])
        {
          continue;
        }
        // Instead of immediately deleting invalid objects, we keep them
        // around in case other objects are referencing them. One
        // example is the backboard_importer keeping a reference on its
        // m_FileAssetReferencers. So the invalid objects are taken out
        // of the objects list but only deleted when the artboard is
        // destroyed.
        m_sourceState.ensureAllocated()->invalidObjects.push_back(m_Objects[i]);
        m_Objects[i] = nullptr;
      }
    }
    else
    {
      break;
    }
  }

  return true;
}

void Artboard::reinstanceNestedArtboards(Factory* factory)
{
  for (auto object : m_Objects)
  {
    if (object == nullptr || !object->is<NestedArtboard>())
    {
      continue;
    }
    auto nested = object->as<NestedArtboard>();
    Artboard* current = nested->sourceArtboard();
    if (current == nullptr || !current->isInstance() ||
        current->m_artboardSource == nullptr)
    {
      continue;
    }
    auto replacement = current->m_artboardSource->instance<ArtboardInstance>(
        factory);
    if (replacement != nullptr)
    {
      nested->referencedArtboard(replacement.release());
    }
  }
}

StatusCode Artboard::initialize()
{
  StatusCode code;

  // these will be re-built in update() -- are they needed here?
  m_layout = Layout(0.0f, 0.0f, width(), height());

#ifdef WITH_RIVE_LAYOUT
  markLayoutDirty(this);
#endif
  // onAddedDirty guarantees that all objects are now available so they can be
  // looked up by index/id. This is where nodes find their parents, but they
  // can't assume that their parent's parent will have resolved yet.
  for (auto object : m_Objects)
  {
    if (object == nullptr)
    {
      // objects can be null if they were not understood by this runtime.
      continue;
    }
    if (!canContinue(code = object->onAddedDirty(this)))
    {
      return code;
    }
  }

  // Animations and StateMachines initialize only once on the source/origin
  // Artboard. Instances will hold references to the original Animations and
  // StateMachines, so running this code for instances will effectively
  // initialize them twice. This can lead to unpredictable behaviour. One such
  // example was that resolved objects like listener inputs were being added
  // to lists twice.
  if (!isInstance())
  {
    for (auto object : ownAnimations())
    {
      if (!canContinue(code = object->onAddedDirty(this)))
      {
        return code;
      }
    }

    for (auto object : ownStateMachines())
    {
      if (!canContinue(code = object->onAddedDirty(this)))
      {
        return code;
      }
    }
    if (ownAnimations().empty() && ownStateMachines().empty())
    {
      auto sm = new StateMachine();
      sm->name("Auto Generated State Machine");
      m_sourceState.ensureAllocated()->stateMachines.push_back(sm);
    }
  }

  // Store a map of the drawRules to make it easier to lookup the matching
  // rule for a transform component.
  std::unordered_map<Core*, DrawRules*> componentDrawRules;

#ifdef WITH_RIVE_EDITOR
  // Editor builds move typed-child registration (paths on shapes,
  // nested animations on NestedArtboard, skins, constraints, ...) out
  // of onAdded* and into editorParentChanged, driven by the coop
  // hydration passes. initialize() only ever runs for .riv-imported
  // artboards, which never see those passes — run the registration
  // sweep here or the typed lists stay empty (frozen rigs, zero
  // bounds, unresolvable nested inputs). Must happen BEFORE the
  // onAddedClean walk below: consumers like NestedArtboard mount
  // their nested state machines from the typed lists inside
  // onAddedClean. Parent pointers and child lists are wired by the
  // onAddedDirty pass above. Registrations are contractually
  // idempotent on `to`, so the pump's hydrateRuntimeArtboard doing
  // this again is harmless.
  for (auto object : m_Objects)
  {
    if (object != nullptr && object->is<Component>())
    {
      auto* component = object->as<Component>();
      if (auto* componentParent = component->parent())
      {
        component->editorParentChanged(nullptr, componentParent);
      }
    }
  }
#endif

  // onAddedClean is called when all individually referenced components have
  // been found and so components can look at other components' references and
  // assume that they have resolved too. This is where the whole hierarchy is
  // linked up and we can traverse it to find other references (my parent's
  // parent should be type X can be checked now).
  for (auto object : m_Objects)
  {
    if (object == nullptr)
    {
      continue;
    }
    if (!canContinue(code = object->onAddedClean(this)))
    {
      return code;
    }
    switch (object->coreType())
    {
      case DrawRulesBase::typeKey:
      {
        DrawRules* rules = static_cast<DrawRules*>(object);
        Core* component = resolve(rules->parentId());
        if (component != nullptr)
        {
          componentDrawRules[component] = rules;
        }
        else
        {
          fprintf(
              stderr,
              "Artboard::initialize - Draw rule targets missing "
              "component width id %u\n",
              static_cast<uint32_t>(rules->parentId()));
        }
        break;
      }
      case NestedArtboardBase::typeKey:
      case NestedArtboardLeafBase::typeKey:
      case NestedArtboardLayoutBase::typeKey:
      {
        m_NestedArtboards.push_back(object->as<NestedArtboard>());
        m_ArtboardHosts.push_back(object->as<NestedArtboard>());
        break;
      }
      case ArtboardComponentListBase::typeKey:
        m_ComponentLists.push_back(object->as<ArtboardComponentList>());
        m_ArtboardHosts.push_back(object->as<ArtboardComponentList>());
        break;
      case PaintImageBase::typeKey:
        // Only a paint filled with an artboard hosts one (it passes
        // this artboard's data context to it). An image paint stays
        // out, so it keeps list rows free to go quiet.
        if (object->as<PaintImage>()->sourceArtboard() != nullptr)
        {
          m_ArtboardHosts.push_back(object->as<PaintImage>());
        }
        break;
      case JoystickBase::typeKey:
      {
        Joystick* joystick = object->as<Joystick>();
        if (!joystick->canApplyBeforeUpdate())
        {
          m_JoysticksApplyBeforeUpdate = false;
        }
        joystick->addDependents(this);
        m_Joysticks.push_back(joystick);
        break;
      }
      case BitmapCacheBase::typeKey:
        m_BitmapCache = object->as<BitmapCache>();
        break;
    }
    auto advancingComponent = AdvancingComponent::from(object);
    if (advancingComponent)
    {
      m_advancingComponents.push_back(advancingComponent);
    }
    auto hostDataContextConsumer = HostDataContextConsumer::from(object);
    if (hostDataContextConsumer)
    {
      m_hostDataContextConsumers.push_back(hostDataContextConsumer);
    }
  }

  if (!isInstance())
  {
    for (auto object : ownAnimations())
    {
      if (!canContinue(code = object->onAddedClean(this)))
      {
        return code;
      }
    }

    for (auto object : ownStateMachines())
    {
      if (!canContinue(code = object->onAddedClean(this)))
      {
        return code;
      }
    }
  }

  // Multi-level references have been built up, now we can
  // actually mark what's dependent on what.
  for (auto object : m_Objects)
  {
    if (object == nullptr)
    {
      continue;
    }
    if (object->is<Component>())
    {
      object->as<Component>()->buildDependencies();
    }
    if (object->is<Drawable>() && object != this)
    {
      Drawable* drawable = object->as<Drawable>();
      m_Drawables.push_back(drawable);
      // Move the foreground drawable before its parent. We traverse the
      // added list of drawables and swap their positions with the
      // foreground drawable until we find the parent
      if (drawable->is<ForegroundLayoutDrawable>())
      {
        auto parent = drawable->parent();
        auto index = m_Drawables.size() - 1;
        while (index >= 1)
        {
          auto swappingDrawable = m_Drawables[index - 1];
          std::swap(m_Drawables[index - 1], m_Drawables[index]);
          if (swappingDrawable == parent)
          {
            break;
          }
          index--;
        }
      }

      for (ContainerComponent* parent = drawable; parent != nullptr;
           parent = parent->parent())
      {
        auto itr = componentDrawRules.find(parent);
        if (itr != componentDrawRules.end())
        {
          drawable->flattenedDrawRules = itr->second;
          break;
        }
      }
    }
    else if (object->is<ClippingShape>())
    {
      m_clippingShapes.push_back(object->as<ClippingShape>());
    }
    else if (object->is<LayerMask>())
    {
      m_layerMasks.push_back(object->as<LayerMask>());
    }
  }
  insertLayoutProxies();

  sortDependencies();

  std::vector<DrawRules*> rulesList;
  // Build the rules in the right order. We use the map componentDrawRules
  // to make sure we traverse the objects in the right order from parent
  // to child, and add the rules accordingly.
  for (auto object : m_Objects)
  {
    if (object == nullptr)
    {
      continue;
    }
    auto itr = componentDrawRules.find(object);
    if (itr != componentDrawRules.end())
    {
      rulesList.emplace_back(componentDrawRules[object]);
    }
  }
  DrawTarget root;
  // Build up the draw order. Look for draw targets and build
  // their dependencies.
  for (auto rules : rulesList)
  {
    for (auto child : rules->children())
    {
      auto target = child->as<DrawTarget>();
      root.addDependent(target);
      auto dependentRules = target->drawable()->flattenedDrawRules;
      if (dependentRules != nullptr)
      {
        // Because we don't store targets on rules, we need
        // to find the targets that belong to this rule
        // here.
        for (auto object : m_Objects)
        {
          if (object != nullptr && object->is<DrawTarget>())
          {
            DrawTarget* dependentTarget = object->as<DrawTarget>();
            if (dependentTarget->parent() == dependentRules)
            {
              dependentTarget->addDependent(target);
            }
          }
        }
      }
    }
  }
  DependencySorter sorter;
  std::vector<Component*> drawTargetOrder;
  sorter.sort(&root, drawTargetOrder);
  if (drawTargetOrder.size() > 0)
  {
    auto itr = drawTargetOrder.begin();
    itr++;
    while (itr != drawTargetOrder.end())
    {
      m_DrawTargets.push_back(static_cast<DrawTarget*>(*itr++));
    }
  }

  initScriptedObjects();
  return StatusCode::Ok;
}

void Artboard::insertLayoutProxies()
{
  // A layout only needs a DrawableProxy if it paints, clips, can gain a clip
  // at runtime, or is an interaction/listener hit target. Those deferred
  // reasons are stamped as ForceDrawableProxy when their references resolve
  // (KeyedObject::onAddedDirty, DataBind::target, ScrollConstraint, and
  // StateMachineListener::onAddedClean; source-only ones are carried to
  // instances by LayoutComponent::clone) -- guaranteeing the proxy exists
  // before this first, one-time injection. See needsDrawableProxy.

  // Iterate over the drawables in order to inject proxies for layouts
  std::vector<LayoutComponent*> layouts;
  for (int i = 0; i < m_Drawables.size(); i++)
  {
    auto drawable = m_Drawables[i];
    LayoutComponent* currentLayout = nullptr;
    bool isInCurrentLayout = true;
    if (!layouts.empty())
    {
      currentLayout = layouts.back();
      isInCurrentLayout = drawable->isChildOfLayout(currentLayout);
    }
    // We inject a DrawableProxy after all of the children of a
    // LayoutComponent so that we can draw a stroke above and background
    // below the children This also allows us to clip the children. Layouts
    // that will never paint or clip skip the proxy entirely (it would draw
    // nothing) -- pure containers are the common case.
    if (currentLayout != nullptr && !isInCurrentLayout)
    {
      // This is the first item in the list of drawables that isn't a
      // child of the layout, so we insert a proxy before it
      do
      {
        if (currentLayout->needsDrawableProxy())
        {
          m_Drawables.insert(m_Drawables.begin() + i, currentLayout->proxy());
          i += 1;
        }
        layouts.pop_back();
        if (!layouts.empty())
        {
          currentLayout = layouts.back();
        }
      } while (!layouts.empty() && !drawable->isChildOfLayout(currentLayout));
    }
    if (drawable->is<LayoutComponent>())
    {
      layouts.push_back(drawable->as<LayoutComponent>());
    }
  }
  while (!layouts.empty())
  {
    auto layout = layouts.back();
    if (layout->needsDrawableProxy())
    {
      m_Drawables.push_back(layout->proxy());
    }
    layouts.pop_back();
  }
}

void Artboard::sortDrawOrder()
{
  m_drawOrderChangeCounter = m_drawOrderChangeCounter ==
                                     std::numeric_limits<uint8_t>::max()
                                 ? 0
                                 : m_drawOrderChangeCounter + 1;
  for (auto target : m_DrawTargets)
  {
    target->first = target->last = nullptr;
  }

  m_FirstDrawable = nullptr;
  Drawable* lastDrawable = nullptr;
  for (auto drawable : m_Drawables)
  {
    auto rules = drawable->flattenedDrawRules;
    if (rules != nullptr && rules->activeTarget() != nullptr)
    {

      auto target = rules->activeTarget();
      if (target->first == nullptr)
      {
        target->first = target->last = drawable;
        drawable->prev = drawable->next = nullptr;
      }
      else
      {
        target->last->next = drawable;
        drawable->prev = target->last;
        target->last = drawable;
        drawable->next = nullptr;
      }
    }
    else
    {
      drawable->prev = lastDrawable;
      drawable->next = nullptr;
      if (lastDrawable == nullptr)
      {
        lastDrawable = m_FirstDrawable = drawable;
      }
      else
      {
        lastDrawable->next = drawable;
        lastDrawable = drawable;
      }
    }
  }

  for (auto rule : m_DrawTargets)
  {
    if (rule->first == nullptr)
    {
      continue;
    }
    auto targetDrawable = rule->drawable();
    switch (rule->placement())
    {
      case DrawTargetPlacement::before:
      {
        if (targetDrawable->prev != nullptr)
        {
          targetDrawable->prev->next = rule->first;
          rule->first->prev = targetDrawable->prev;
        }
        if (targetDrawable == m_FirstDrawable)
        {
          m_FirstDrawable = rule->first;
        }
        targetDrawable->prev = rule->last;
        rule->last->next = targetDrawable;
        break;
      }
      case DrawTargetPlacement::after:
      {
        if (targetDrawable->next != nullptr)
        {
          targetDrawable->next->prev = rule->last;
          rule->last->next = targetDrawable->next;
        }
        if (targetDrawable == lastDrawable)
        {
          lastDrawable = rule->last;
        }
        targetDrawable->next = rule->first;
        rule->first->prev = targetDrawable;
        break;
      }
    }
  }

  m_FirstDrawable = lastDrawable;

  // Interleave clipping operations between drawables that share the same
  // common clippings. Each clipping operation has a start and an end.
  for (auto& clippingShape : m_clippingShapes)
  {
    clippingShape->resetDrawables();
  }
  Drawable* currentDrawable = m_FirstDrawable;
  Drawable* nextDrawable = nullptr;
  std::vector<ClippingShape*> _clippingStack;
  while (currentDrawable)
  {
    currentDrawable->needsSaveOperation(true);
    const auto& drawableClippingShapes = currentDrawable->clippingShapes();
    // Remove all clippings that are not part of the current drawable. Since
    // they are applied as a stack, if one clipping is removed, all
    // subsequent clippings from the stack need to be removed as well
    size_t removingIndex = _clippingStack.size();
    for (size_t i = 0; i < _clippingStack.size(); ++i)
    {
      auto& cl = _clippingStack[i];
      // Check if this clipping should stay (is in both stack and
      // drawable's clippings)
      bool shouldStay = std::find(
                            drawableClippingShapes.begin(),
                            drawableClippingShapes.end(),
                            cl) != drawableClippingShapes.end();
      if (!shouldStay)
      {
        removingIndex = i;
        break;
      }
    }

    // Remove all clippings from stack in the reverse order they were added
    if (_clippingStack.size() > 0 && removingIndex < _clippingStack.size())
    {

      size_t i = _clippingStack.size() - 1;
      while (i >= removingIndex)
      {
        auto& clippingShape = _clippingStack[i];
        // Insert in the drawing list a clipEnd for each clipping that
        // is removed
        auto proxyDrawable = clippingShape->createProxyDrawable(
            &clippingShape->clipEnd);
        if (nextDrawable)
        {
          proxyDrawable->next = nextDrawable;
          nextDrawable->prev = proxyDrawable;
        }
        else
        {
          fprintf(stderr, "Error - adding clip end as first operation\n");
        }
        proxyDrawable->prev = currentDrawable;
        currentDrawable->next = proxyDrawable;
        nextDrawable = proxyDrawable;
        if (i == 0)
        {
          break;
        }
        i--;
      }
      _clippingStack.erase(
          _clippingStack.begin() + removingIndex,
          _clippingStack.end());
    }
    // Find clippings that are applied to the drawable but are not on the
    // stack
    for (auto& clippingShape : drawableClippingShapes)
    {
      auto itr = std::find(
          _clippingStack.begin(),
          _clippingStack.end(),
          clippingShape);
      if (itr == _clippingStack.end())
      {
        auto proxyDrawable = clippingShape->createProxyDrawable(
            &clippingShape->clipStart);
        if (nextDrawable)
        {
          proxyDrawable->next = nextDrawable;
          nextDrawable->prev = proxyDrawable;
        }
        else
        {
          m_FirstDrawable = proxyDrawable;
        }
        proxyDrawable->prev = currentDrawable;
        currentDrawable->next = proxyDrawable;
        nextDrawable = proxyDrawable;
        _clippingStack.push_back(clippingShape);
      }
    }
    nextDrawable = currentDrawable;
    currentDrawable = currentDrawable->prev;
  }
  // Add closing calls to remaining clippings in the stack
  if (_clippingStack.size() > 0)
  {

    for (int i = (int)(_clippingStack.size() - 1); i >= 0; i--)
    {
      auto& clippingShape = _clippingStack[i];
      auto proxyDrawable = clippingShape->createProxyDrawable(
          &clippingShape->clipEnd);
      if (nextDrawable)
      {
        nextDrawable->prev = proxyDrawable;
        proxyDrawable->next = nextDrawable;
      }
      proxyDrawable->prev = nullptr; // End of list
      nextDrawable = proxyDrawable;
    }
  }
  interleaveLayerMasks();
  clearRedundantOperations();
}

// True when `d` belongs inside a bracket whose members are `members`. Pure
// bracket operations (clip and mask markers) are always allowed: they are
// nested structure, not content. A DrawableProxy is allowed when the component
// it stands in for is a member -- a LayoutComponent's proxy is injected by the
// artboard and so never appears in a subtree walk, but its save()+clipPath()
// has to sit inside the same bracket as the restore() in its draw().
static bool spansMember(
    Drawable* d,
    const std::unordered_set<Drawable*>& members)
{
  if (members.count(d) != 0)
  {
    return true;
  }
  if (!d->isProxy())
  {
    return false;
  }
  if (d->isClipStart() || d->isClipEnd() || d->isMaskStart() || d->isMaskEnd())
  {
    return true;
  }
  Drawable* stands = d->hittableComponent();
  return stands != nullptr && members.count(stands) != 0;
}

bool Artboard::spliceLayerMaskBracket(
    LayerMask* mask,
    const std::vector<Drawable*>& members,
    LayerMaskOp startOp,
    LayerMaskOp endOp,
    LayerMaskProxyDrawable** startOut)
{
  if (startOut != nullptr)
  {
    *startOut = nullptr;
  }
  if (members.empty())
  {
    return false;
  }
  std::unordered_set<Drawable*> memberSet(members.begin(), members.end());

  // `next` is earlier in draw order, `prev` later: the walk from
  // m_FirstDrawable follows prev, so first/last here are in draw order.
  Drawable* first = nullptr;
  Drawable* last = nullptr;
  for (auto d = m_FirstDrawable; d != nullptr; d = d->prev)
  {
    if (memberSet.count(d) != 0)
    {
      if (first == nullptr)
      {
        first = d;
      }
      last = d;
    }
  }
  if (first == nullptr)
  {
    // The members are not in this artboard's draw list at all (all hidden
    // behind a collapsed parent, say).
    return false;
  }

  // Our markers have to nest with every bracket already in the list, never
  // interleave: the draw walk is handed a [start, end) range and would run
  // off the list if an inner end marker escaped our outer one. The member
  // extremes are not necessarily balanced -- a mask processed before us may
  // have bracketed our first or last member -- so grow the range outward
  // until it is. Bracket markers are always allowed inside a span, so growing
  // can only make the contiguity check below easier.
  bool grew = true;
  while (grew)
  {
    grew = false;
    // Starts whose end is inside the range, and ends whose start is before
    // it.
    int clipDepth = 0, maskDepth = 0;
    int clipDeficit = 0, maskDeficit = 0;
    for (auto d = first;; d = d->prev)
    {
      if (d->isClipStart())
      {
        ++clipDepth;
      }
      else if (d->isClipEnd())
      {
        clipDepth > 0 ? --clipDepth : ++clipDeficit;
      }
      else if (d->isMaskStart())
      {
        ++maskDepth;
      }
      else if (d->isMaskEnd())
      {
        maskDepth > 0 ? --maskDepth : ++maskDeficit;
      }
      if (d == last)
      {
        break;
      }
    }
    // Pull the start back over the openers whose closers we contain.
    while (clipDeficit > 0 || maskDeficit > 0)
    {
      Drawable* before = first->next;
      if (before == nullptr)
      {
        break;
      }
      if (maskDeficit > 0 && before->isMaskStart())
      {
        --maskDeficit;
      }
      else if (clipDeficit > 0 && before->isClipStart())
      {
        --clipDeficit;
      }
      else
      {
        break;
      }
      first = before;
      grew = true;
    }
    // Push the end forward over the closers whose openers we contain.
    while (clipDepth > 0 || maskDepth > 0)
    {
      Drawable* after = last->prev;
      if (after == nullptr)
      {
        break;
      }
      if (maskDepth > 0 && after->isMaskEnd())
      {
        --maskDepth;
      }
      else if (clipDepth > 0 && after->isClipEnd())
      {
        --clipDepth;
      }
      else
      {
        break;
      }
      last = after;
      grew = true;
    }
    if (!grew &&
        (clipDeficit > 0 || maskDeficit > 0 || clipDepth > 0 || maskDepth > 0))
    {
      // Could not balance: some bracket genuinely half-overlaps this
      // range, and no placement of our markers avoids crossing it.
      return false;
    }
  }

  // Contiguity. A draw rule can lift an unrelated drawable into the middle of
  // a subtree's span; masking it too would be silently wrong, and splitting
  // into two brackets would composite the mask twice. Refuse instead, and let
  // the caller draw the content unmasked.
  for (auto d = first;; d = d->prev)
  {
    if (!spansMember(d, memberSet))
    {
      return false;
    }
    if (d == last)
    {
      break;
    }
  }

  auto* startMarker = mask->createProxyDrawable(startOp);
  auto* endMarker = mask->createProxyDrawable(endOp);

  // Insert startMarker immediately before `first` in draw order.
  Drawable* before = first->next;
  startMarker->next = before;
  startMarker->prev = first;
  if (before != nullptr)
  {
    before->prev = startMarker;
  }
  else
  {
    m_FirstDrawable = startMarker;
  }
  first->next = startMarker;

  // Insert endMarker immediately after `last` in draw order.
  Drawable* after = last->prev;
  endMarker->prev = after;
  endMarker->next = last;
  if (after != nullptr)
  {
    after->next = endMarker;
  }
  last->prev = endMarker;

  startMarker->pairedEnd(endMarker);
  if (startOut != nullptr)
  {
    *startOut = startMarker;
  }
  return true;
}

void Artboard::interleaveLayerMasks()
{
  if (m_layerMasks.empty())
  {
    return;
  }
  for (auto& mask : m_layerMasks)
  {
    mask->resetDrawables();
  }
  for (auto& mask : m_layerMasks)
  {
    // A self-referential mask is inert: its source sits inside the range it
    // would rasterize, so bracketing it would recurse forever.
    if (mask->isSelfReferential())
    {
      continue;
    }
    // Collect the drawables this mask applies to. Done per mask rather than
    // from one shared index because each splice shifts the list.
    std::vector<Drawable*> masked;
    for (auto d = m_FirstDrawable; d != nullptr; d = d->prev)
    {
      const auto& masks = d->layerMasks();
      if (std::find(masks.begin(), masks.end(), mask) != masks.end())
      {
        masked.push_back(d);
      }
    }
    LayerMaskProxyDrawable* start = nullptr;
    if (!spliceLayerMaskBracket(
            mask,
            masked,
            LayerMaskOp::maskStart,
            LayerMaskOp::maskEnd,
            &start))
    {
      continue;
    }
    // Only bracket the source once the masked range is genuinely bracketed:
    // suppressing the source while the content draws unmasked would just
    // make the mask art vanish for nothing.
    LayerMaskProxyDrawable* sourceStart = nullptr;
    if (spliceLayerMaskBracket(
            mask,
            mask->sourceDrawables(),
            LayerMaskOp::sourceStart,
            LayerMaskOp::sourceEnd,
            &sourceStart))
    {
      mask->sourceBracket(sourceStart, sourceStart->pairedEnd());
    }
  }
}

// Look for drawables that are preceeding and succeeding drawables that call
// save and restore. If found, the drawable does not need to call save and
// restore itself.
void Artboard::clearRedundantOperations()
{
  Drawable* currentDrawable = m_FirstDrawable;
  bool prevAppliedSave = false;
  // Keep a stack of clipStart operation results to apply the same operation
  // to its clipEnd
  std::vector<bool> appliedClippingSaveOperations;
  while (currentDrawable)
  {
    currentDrawable->needsSaveOperation(true);
    // If previous operation applied a save operation
    if (prevAppliedSave)
    {
      // With consecutive clippings, we can skip the save and restore
      // operation since the previous one has applied it
      if (currentDrawable->isClipStart())
      {
        appliedClippingSaveOperations.push_back(false);
        currentDrawable->needsSaveOperation(false);
      }
      else if (currentDrawable->isClipEnd())
      {
        // Apply or skip the clipEnd Restore operation matching its clip
        // start counterpart
        auto operationApplied = appliedClippingSaveOperations.back();
        appliedClippingSaveOperations.pop_back();
        currentDrawable->needsSaveOperation(operationApplied);
      }
      else
      {
        // Check if next is clip end, if it is, we can skip the drawable
        // save/restore because it is tightly wrapped in a clipping
        // operation
        auto nextDrawable = currentDrawable->prev;
        if (nextDrawable->isClipEnd())
        {
          currentDrawable->needsSaveOperation(false);
        }
      }
    }
    else if (currentDrawable->isClipStart())
    {
      appliedClippingSaveOperations.push_back(true);
    }
    else if (currentDrawable->isClipEnd())
    {
      // Apply or skip the clipEnd Restore operation matching its clip
      // start counterpart
      auto operationApplied = appliedClippingSaveOperations.back();
      currentDrawable->needsSaveOperation(operationApplied);
      appliedClippingSaveOperations.pop_back();
    }
    prevAppliedSave = currentDrawable->isClipStart() &&
                      (currentDrawable->willClip() || prevAppliedSave);
    currentDrawable = currentDrawable->prev;
  }
  assert(appliedClippingSaveOperations.size() == 0);
}

#ifdef WITH_RIVE_EDITOR
void Artboard::rebuildAdvancingForEditor(Span<Core*> objects)
{
  m_advancingComponents.clear();
  m_NestedArtboards.clear();
  m_ArtboardHosts.clear();
  m_ComponentLists.clear();
  for (auto* object : objects)
  {
    if (auto* advancing = AdvancingComponent::from(object))
      m_advancingComponents.push_back(advancing);
    if (object->is<NestedArtboard>())
    {
      m_NestedArtboards.push_back(object->as<NestedArtboard>());
      m_ArtboardHosts.push_back(object->as<NestedArtboard>());
    }
    else if (object->is<ArtboardComponentList>())
    {
      m_ComponentLists.push_back(object->as<ArtboardComponentList>());
      m_ArtboardHosts.push_back(object->as<ArtboardComponentList>());
    }
  }
}

void Artboard::initLayoutForEditor()
{
  m_layout = Layout(0.0f, 0.0f, width(), height());
  // NOTE: intentionally skipping `markLayoutDirty(this)` — the full
  // layout pipeline isn't wired for coop-loaded artboards yet (no
  // style / Yoga node setup), and running syncStyleChanges on a
  // partial state has been observed to crash. Phase 2.1 adds the
  // layout pipeline back behind the `#ifdef WITH_RIVE_LAYOUT` once
  // the missing setup is in place.
}
#endif

Component* Artboard::componentForOrderEntry(
    const DependencyOrderEntry& entry) const
{
  if (entry.objectIndex >= m_Objects.size())
  {
    return nullptr;
  }
  Core* object = m_Objects[entry.objectIndex];
  if (object == nullptr)
  {
    return nullptr;
  }
  if (entry.helperSlot == 0)
  {
    return object->is<Component>() ? object->as<Component>() : nullptr;
  }
  // Slot 1 is the single owned helper for the types that have one. Add
  // further slots here if another Component gains an owned graph node.
  if (entry.helperSlot == 1)
  {
    if (object->is<Shape>())
    {
      return object->as<Shape>()->pathComposer();
    }
    if (object->is<TextStyle>())
    {
      return object->as<TextStyle>()->variationHelper();
    }
  }
  return nullptr;
}

const std::vector<Artboard::DependencyOrderEntry>* Artboard::
    dependencyOrderRecipe() const
{
  switch (m_RecipeState)
  {
    case RecipeState::valid:
      return m_DependencyOrderRecipe.get();
    case RecipeState::unusable:
      return nullptr;
    case RecipeState::unbuilt:
      break;
  }

  // No reverse Component* -> index map is needed: sortDependencies() has
  // already stamped every component in m_DependencyOrder with its position
  // via m_GraphOrder, so one walk of m_Objects can scatter each entry
  // straight into its slot. That keeps recipe construction allocation-free
  // beyond the result vector, which matters because the source artboard is
  // re-decoded (and so re-builds this) on every editor regeneration.
  const size_t count = m_DependencyOrder.size();
  constexpr uint32_t unset = ~(uint32_t)0;
  auto& recipe = *m_DependencyOrderRecipe.ensureAllocated();
  recipe.assign(count, {unset, 0});
  size_t filled = 0;

  auto stamp = [&](const Component* component, uint32_t index, uint8_t slot) {
    if (component == nullptr)
    {
      return;
    }
    const unsigned int position = component->graphOrder();
    // A component the sort never placed keeps Component's sentinel, which
    // no order can hand out. One that a *previous, longer* order placed
    // keeps that order's position, which this one may well have handed to
    // somebody else -- so the stamp alone is not proof. Confirm the order
    // really holds this component where it claims to be, which is an exact
    // membership test no stale stamp can pass.
    if (position >= count || m_DependencyOrder[position] != component)
    {
      return;
    }
    DependencyOrderEntry& entry = recipe[position];
    if (entry.objectIndex != unset)
    {
      // One component reachable through two slots. Leave the first.
      return;
    }
    entry = {index, slot};
    filled++;
  };

  for (size_t i = 0; i < m_Objects.size(); i++)
  {
    Core* object = m_Objects[i];
    if (object == nullptr || !object->is<Component>())
    {
      continue;
    }
    const uint32_t index = (uint32_t)i;
    stamp(object->as<Component>(), index, 0);
    if (object->is<Shape>())
    {
      stamp(object->as<Shape>()->pathComposer(), index, 1);
    }
    else if (object->is<TextStyle>())
    {
      stamp(object->as<TextStyle>()->variationHelper(), index, 1);
    }
  }

  if (filled != count)
  {
    // Something in the order isn't addressable as index/slot (or the
    // graph-order stamps disagree). Don't emit a partial order.
    m_DependencyOrderRecipe.reset();
    m_RecipeState = RecipeState::unusable;
    return nullptr;
  }
  m_RecipeState = RecipeState::valid;
  return m_DependencyOrderRecipe.get();
}

bool Artboard::replaySourceDependencyOrder(const Artboard* source)
{
  if (source == nullptr || source == this ||
      source->m_Objects.size() != m_Objects.size())
  {
    return false;
  }
  const std::vector<DependencyOrderEntry>*
      recipe = source->dependencyOrderRecipe();
  if (recipe == nullptr)
  {
    return false;
  }
  std::vector<Component*> order;
  order.reserve(recipe->size());
  for (const DependencyOrderEntry& entry : *recipe)
  {
    Component* component = componentForOrderEntry(entry);
    if (component == nullptr)
    {
      // A helper the source had but this instance doesn't (they are
      // lazily created). Fall back rather than emit a short order.
      return false;
    }
    order.push_back(component);
  }
  m_DependencyOrder = std::move(order);
  return true;
}

void Artboard::sortDependencies()
{
  // An instance replays its source's order instead of re-walking the graph;
  // see DependencyOrderEntry. Falls back to sorting whenever anything about
  // the instance doesn't line up.
  bool replayed = replaySourceDependencyOrder(m_artboardSource);

  if (!replayed)
  {
    DependencySorter sorter;
    sorter.sort(this, m_DependencyOrder);
  }
  unsigned int graphOrder = 0;
  for (auto component : m_DependencyOrder)
  {
    component->m_GraphOrder = graphOrder++;
  }
  m_DependencyOrderRecipe.reset();
  m_RecipeState = RecipeState::unbuilt;
  m_collapsedRunsDirty = true;
  m_Dirt |= ComponentDirt::Components;
}

void Artboard::addObject(Core* object) { m_Objects.push_back(object); }

void Artboard::addAnimation(LinearAnimation* object)
{
  m_sourceState.ensureAllocated()->animations.push_back(object);
}

void Artboard::addStateMachine(StateMachine* object)
{
  m_sourceState.ensureAllocated()->stateMachines.push_back(object);
}

void Artboard::addScriptedObject(ScriptedObject* object)
{
  m_ScriptedObjects.push_back(object);
}

ScriptedInterpolator* Artboard::statefulInterpolator(
    const ScriptedInterpolator* source)
{
  // Only instances run layouts, and a clone parks its input binds on us.
  if (source == nullptr || !isInstance())
  {
    return nullptr;
  }
  if (m_scriptedInterpolators == nullptr)
  {
    m_scriptedInterpolators = std::unique_ptr<ArtboardScriptedInterpolators>(
        new ArtboardScriptedInterpolators());
  }
  auto& bySource = m_scriptedInterpolators->bySource;
  auto itr = bySource.find(source);
  if (itr != bySource.end())
  {
    return itr->second->get();
  }
  // Cache a failed clone too, so a runtime without scripting doesn't retry
  // every frame; get() stays null and callers fall back to the template.
  auto stateful = std::unique_ptr<StatefulScriptedInterpolator>(
      new StatefulScriptedInterpolator(source, this, dataContext()));
  auto* clone = stateful->get();
  bySource.emplace(source, std::move(stateful));
  return clone;
}

void Artboard::initScriptedObjects()
{
  if (isInstance())
  {
    for (auto obj : m_ScriptedObjects)
    {
      if (obj->scriptAsset() != nullptr)
      {
        if (!obj->userLuaInitDone())
        {
          obj->scriptAsset()->initScriptedObject(obj);
        }
        obj->hydrateScriptInputs();
      }
    }
  }
}

static bool converterRunsScript(DataConverter* converter)
{
  if (converter == nullptr)
  {
    return false;
  }
  if (converter->is<ScriptedDataConverter>())
  {
    return true;
  }
  if (converter->is<DataConverterGroup>())
  {
    for (auto* item : converter->as<DataConverterGroup>()->items())
    {
      if (converterRunsScript(item->converter()))
      {
        return true;
      }
    }
  }
  for (auto* dataBind : converter->dataBinds())
  {
    if (converterRunsScript(dataBind->converter()))
    {
      return true;
    }
  }
  return false;
}

bool Artboard::usesScripts() const
{
  for (auto* object : m_Objects)
  {
    if (object != nullptr && ScriptedObject::from(object) != nullptr)
    {
      return true;
    }
  }
  for (auto* machine : animationSource()->ownStateMachines())
  {
    if (machine->hasScriptedObjects())
    {
      return true;
    }
    for (size_t i = 0; i < machine->dataBindCount(); i++)
    {
      if (converterRunsScript(machine->dataBind(i)->converter()))
      {
        return true;
      }
    }
  }
  for (auto* dataBind : dataBinds())
  {
    if (converterRunsScript(dataBind->converter()))
    {
      return true;
    }
  }
  return false;
}

void Artboard::pollAsyncWork() { rive_pollAsyncWork(); }

#if defined(WITH_RIVE_SCRIPTING_LUAU) || defined(WITH_RIVE_SCRIPTING_WASM)
static bool fileHasPendingAsyncWork(const File* file)
{
#ifdef WITH_RIVE_SCRIPTING_LUAU
  if (auto vm = file->scriptingVM())
  {
    auto* context = vm->context();
    if (context != nullptr && context->hasPendingAsyncWork(vm->state()))
    {
      return true;
    }
  }
#endif
#ifdef WITH_RIVE_SCRIPTING_WASM
  for (auto& vm : file->wasmVMs())
  {
    if (vm->hasPendingAsyncWork())
    {
      return true;
    }
  }
#endif
  return false;
}
#endif

bool Artboard::hasPendingAsyncWork()
{
#if defined(WITH_RIVE_SCRIPTING_LUAU) || defined(WITH_RIVE_SCRIPTING_WASM)
  // Only roots carry their file, and nested artboards run on it unless they
  // were bound in from another one.
  auto file = artboardFile();
  if (file != nullptr && fileHasPendingAsyncWork(file.get()))
  {
    return true;
  }
  for (auto host : m_ArtboardHosts)
  {
    auto foreign = host->foreignFile();
    if (foreign != nullptr && fileHasPendingAsyncWork(foreign))
    {
      return true;
    }
    for (size_t i = 0; i < host->artboardCount(); i++)
    {
      auto instance = host->artboardInstance((int)i);
      if (instance != nullptr && instance->hasPendingAsyncWork())
      {
        return true;
      }
    }
  }
#endif
  return false;
}

Core* Artboard::resolve(Id id) const
{
#ifdef WITH_RIVE_EDITOR
  // Editor `Id` is `{client, object}` and objects come from two
  // sources that share the same namespace:
  //   • `.riv`-loaded objects — `CoreIdType::runtimeDeserialize`
  //     synthesizes `Id{0, runtime_index}` which indexes straight
  //     into `m_Objects` (same behavior as a runtime build).
  //   • Coop-delivered objects — stamped by the server with
  //     `client == 0` too, looked up via `m_editorResolver`'s
  //     CoopId map. Non-zero client always means a coop peer ID.
  // `m_Objects` first (runtime path) then fall through to the
  // resolver, so both sources resolve correctly without the caller
  // needing to know which. `kEmptyId == {0, 0}` is short-circuited
  // — `m_Objects[0]` is a legitimate object (the Artboard itself)
  // and would be a wrong answer for "no id set".
  if (id.empty())
    return nullptr;
  if (id.client == 0 && id.object < m_Objects.size())
  {
    if (auto* hit = m_Objects[id.object])
      return hit;
  }
  return m_editorResolver ? m_editorResolver->resolve(id) : nullptr;
#else
  // Runtime: single-source `Id` (a raw uint index) into `m_Objects`.
  return id < static_cast<int>(m_Objects.size()) ? m_Objects[id] : nullptr;
#endif
}

uint32_t Artboard::idOf(Core* object) const
{
  auto it = std::find(m_Objects.begin(), m_Objects.end(), object);

  if (it != m_Objects.end())
  {
    return castTo<uint32_t>(it - m_Objects.begin());
  }
  else
  {
    return 0;
  }
}

void Artboard::onComponentDirty(Component* component)
{
#ifdef TESTING
  sm_dirtNotifications++;
#endif
  wakeIfQuietRow();
  m_didChange = true;
  ++m_contentRevision;
  m_changeSerial++;
  m_Dirt |= ComponentDirt::Components;

  /// If the order of the component is less than the current dirt
  /// depth, update the dirt depth so that the update loop can break
  /// out early and re-run (something up the tree is dirty).
  if (component->graphOrder() < m_DirtDepth)
  {
    m_DirtDepth = component->graphOrder();
  }
}

// Not in the dependency graph: draw and hit test read selfTransform(). Redraw
// without content dirt (a cascade hides children's same-frame dirt behind
// addDirt's dedupe); semantics re-read their bounds through the boundary.
void Artboard::selfTransformChanged()
{
  // Rasters leave self rotation/scale out of m_contentRevision, but a state
  // machine holding a pose that keys them has to hear about it, even on a
  // quiet list row.
  m_changeSerial++;
  wakeIfQuietRow();
  // Hosts cache mesh bounds and visibility from the pose. Only an update
  // pass clears the flag, and none follows without dirt: re-arm it, or the
  // host hears only the first change.
  m_hostTransformMarkedDirty = false;
  markHostTransformDirty();
  markSemanticBoundaryTransformDirty();
  if (!m_didChange)
  {
    m_didChange = true;
    if (parentArtboard())
    {
      parentArtboard()->changed();
    }
  }
}

void Artboard::rotationChanged() { selfTransformChanged(); }
void Artboard::scaleXChanged() { selfTransformChanged(); }
void Artboard::scaleYChanged() { selfTransformChanged(); }

void Artboard::onDirty(ComponentDirt dirt)
{
#ifdef TESTING
  sm_dirtNotifications++;
#endif
  wakeIfQuietRow();
  m_Dirt |= ComponentDirt::Components;
}

#ifdef WITH_RIVE_LAYOUT
void Artboard::propagateSize()
{
  addDirt(ComponentDirt::Path);
  if (sharesLayoutWithHost())
  {
    m_host->markHostTransformDirty();
  }
#ifdef WITH_RIVE_TOOLS
  if (m_layoutChangedCallback != nullptr)
  {
    m_layoutChangedCallback(callbackUserData);
  }
#endif
}
#endif

bool Artboard::sharesLayoutWithHost() const
{
  return m_host != nullptr && m_host->isLayoutProvider();
}

void Artboard::cloneObjectDataBinds(
    const Core* object,
    Core* clone,
    Artboard* artboard) const
{

  for (auto dataBind : dataBinds())
  {
    if (dataBind->target() == object)
    {
      artboard->addDataBind(dataBind->cloneWithTarget(clone));
    }
  }
}

void Artboard::syncInstanceValueBinds()
{
  // Mid update the removes and adds would only queue, and a second change
  // in the same pass could not see them; coalesce until the pass drains.
  if (isProcessingDataBinds())
  {
    m_instanceValueBindsPending = true;
    return;
  }
  auto instance = dataBindContext() != nullptr
                      ? dataBindContext()->mainViewModelInstance()
                      : nullptr;
  if (instance == m_instanceValueBindsSource)
  {
    return;
  }
  // Snapshot: removing mutates the list we are walking.
  auto previous = dataBinds();
  for (auto dataBind : previous)
  {
    if (dataBind->isInstanceValueBind())
    {
      removeAndDeleteDataBind(dataBind);
    }
  }
  m_instanceValueBindsSource = instance;
  if (instance == nullptr)
  {
    return;
  }
  for (auto dataBind : instance->valueDataBinds())
  {
    auto dataBindClone = dataBind->cloneWithTarget(dataBind->target());
    dataBindClone->markInstanceValueBind();
    addDataBind(dataBindClone);
  }
}

void Artboard::mainViewModelInstanceChanged()
{
  wakeIfQuietRow();
  syncInstanceValueBinds();
}

void Artboard::dataContextChanged() { wakeIfQuietRow(); }

void Artboard::wakeQuietRow()
{
  auto row = m_quietHostRow;
  m_quietHostRow = kNoQuietRow;
  if (m_host != nullptr)
  {
    m_host->hostedRowWoke(this, row);
  }
}

AdvancingComponent::QuietState Artboard::rowQuietState()
{
  using QuietState = AdvancingComponent::QuietState;
  // Work this check can't see into: hosted artboards and lists, joysticks
  // and scripts.
  if (!m_ArtboardHosts.empty() || !m_Joysticks.empty() ||
      !m_ScriptedObjects.empty())
  {
    return QuietState::never;
  }
  // Cheapest first: a busy row is checked again every frame.
  if (hasDirt(ComponentDirt::Components) || !m_dirtyLayout.empty() ||
      m_hostTransformMarkedDirty || m_instanceValueBindsPending ||
      hasDataBindWork())
  {
    return QuietState::busy;
  }
  auto state = QuietState::quiet;
  for (auto advancing : m_advancingComponents)
  {
    switch (advancing->quietState())
    {
      case QuietState::never:
        return QuietState::never;
      case QuietState::busy:
        state = QuietState::busy;
        break;
      case QuietState::quiet:
        break;
    }
  }
  if (state == QuietState::quiet && mayAdvanceDataBinds())
  {
    // Converters that advance can't say whether they would.
    return QuietState::never;
  }
  return state;
}

void Artboard::dataBindsProcessed()
{
  if (m_instanceValueBindsPending)
  {
    m_instanceValueBindsPending = false;
    syncInstanceValueBinds();
  }
}

namespace
{
// One shared empty per element type, handed out whenever an artboard has no
// source state. Keeps every read branch-free at the call site.
template <typename T> const std::vector<T>& emptySourceList()
{
  static const std::vector<T> EMPTY;
  return EMPTY;
}
} // namespace

const std::vector<LinearAnimation*>& Artboard::ownAnimations() const
{
  const ArtboardSourceState* state = m_sourceState.get();
  return state != nullptr ? state->animations
                          : emptySourceList<LinearAnimation*>();
}

const std::vector<StateMachine*>& Artboard::ownStateMachines() const
{
  const ArtboardSourceState* state = m_sourceState.get();
  return state != nullptr ? state->stateMachines
                          : emptySourceList<StateMachine*>();
}

const std::vector<Core*>& Artboard::ownInvalidObjects() const
{
  const ArtboardSourceState* state = m_sourceState.get();
  return state != nullptr ? state->invalidObjects : emptySourceList<Core*>();
}

#ifdef WITH_RIVE_EDITOR
void Artboard::clearAnimations()
{
  if (ArtboardSourceState* state = m_sourceState.get())
  {
    state->animations.clear();
  }
}

void Artboard::clearStateMachines()
{
  if (ArtboardSourceState* state = m_sourceState.get())
  {
    state->stateMachines.clear();
  }
}
#endif

void Artboard::buildKeyFrameSourceBindsIndex() const
{
  ArtboardSourceState* state = m_sourceState.ensureAllocated();
  state->keyFrameBindsBuilt = true;
  for (auto dataBind : dataBinds())
  {
    auto target = dataBind->target();
    if (target == nullptr || !target->is<KeyFrame>())
    {
      continue;
    }
    // A keyframe holds a single value, so keep the first bind per target
    // (emplace does not overwrite an existing key).
    state->keyFrameBinds.emplace(target->as<KeyFrame>(), dataBind);
  }
}

bool Artboard::hasKeyFrameSourceBinds() const
{
  const ArtboardSourceState* state = m_sourceState.get();
  if (state == nullptr || !state->keyFrameBindsBuilt)
  {
    buildKeyFrameSourceBindsIndex();
    state = m_sourceState.get();
  }
  return !state->keyFrameBinds.empty();
}

DataBind* Artboard::keyFrameSourceBind(const KeyFrame* keyframe) const
{
  const ArtboardSourceState* state = m_sourceState.get();
  if (state == nullptr || !state->keyFrameBindsBuilt)
  {
    buildKeyFrameSourceBindsIndex();
    state = m_sourceState.get();
  }
  auto it = state->keyFrameBinds.find(keyframe);
  return it != state->keyFrameBinds.end() ? it->second : nullptr;
}

void Artboard::host(ArtboardHost* artboardHost)
{
  addedToHost();
  m_host = artboardHost;
#ifdef EXTERNAL_RIVE_AUDIO_ENGINE
  // audioEngine(engine) only reaches artboards hosted at the time, so list
  // items and swapped nested artboards pick up their host's engine here.
  if (artboardHost != nullptr)
  {
    Artboard* parent = artboardHost->parentArtboard();
    if (parent != nullptr && parent->audioEngine() != nullptr)
    {
      audioEngine(parent->audioEngine());
    }
  }
#endif
#ifdef WITH_RIVE_LAYOUT
  if (!sharesLayoutWithHost())
  {
    return;
  }
  Artboard* parent = parentArtboard();
  if (parent != nullptr)
  {
    parent->markLayoutDirty(this);
    parent->syncLayoutChildren();
  }
#endif
}

ArtboardHost* Artboard::host() const { return m_host; }

StatusCode Artboard::onAddedClean(CoreContext* context)
{
  auto code = Super::onAddedClean(context);
  if (code != StatusCode::Ok)
  {
    return code;
  }
  NodeBase::x(0);
  NodeBase::y(0);
  return StatusCode::Ok;
}

Artboard* Artboard::parentArtboard() const
{
  if (m_host == nullptr)
  {
    return nullptr;
  }
  return m_host->parentArtboard();
}

float Artboard::layoutWidth() const
{
#ifdef WITH_RIVE_LAYOUT
  return m_layout.width();
#else
  return width();
#endif
}

float Artboard::layoutHeight() const
{
#ifdef WITH_RIVE_LAYOUT
  return m_layout.height();
#else
  return height();
#endif
}

float Artboard::layoutX() const
{
#ifdef WITH_RIVE_LAYOUT
  return m_layout.left();
#else
  return 0.0f;
#endif
}

float Artboard::layoutY() const
{
#ifdef WITH_RIVE_LAYOUT
  return m_layout.top();
#else
  return 0.0f;
#endif
}

void Artboard::updateRenderPath()
{
  AABB bg = AABB::fromLTWH(
      -layoutWidth() * originX(),
      -layoutHeight() * originY(),
      layoutWidth(),
      layoutHeight());
  AABB clip;
  if (m_FrameOrigin)
  {
    clip = {0.0f, 0.0f, layoutWidth(), layoutHeight()};
  }
  else
  {
    clip = bg;
  }
  auto& renderPaths = mutableRenderPaths();
  renderPaths.local.rewind();
  renderPaths.local.addRect(bg);
  renderPaths.world.rewind();
  renderPaths.world.addRect(clip);
}

void Artboard::update(ComponentDirt value)
{
  Super::update(value);
  if (hasDirt(value, ComponentDirt::DrawOrder))
  {
    sortDrawOrder();
  }
  if (hasDirt(value, ComponentDirt::Clipping))
  {
    clearRedundantOperations();
  }
#ifdef WITH_RIVE_LAYOUT
  if (hasDirt(value, ComponentDirt::LayoutStyle))
  {
    bool cascadeChanged = cascadeLayoutStyle(
        interpolation(),
        interpolator(),
        interpolationTime(),
        actualDirection());
    // TODO: Explore whether we can remove the syncStyleChanges call in
    // updatePass. Since updatePass calls updateComponents, where the first
    // component is the artboard itself, hence calling update, we end up
    // calling this twice. Although it is safe, because syncStyleChanges
    // checks for the list of dirty layouts that would be empty at this
    // point, it seems redundant.
    syncStyleChangesWithUpdate(cascadeChanged);
  }
#endif
  m_hostTransformMarkedDirty = false;
}

void Artboard::addDirtyDataBind(DataBind* dataBind)
{
  wakeIfQuietRow();
  // Most artboard data binds target Components and need the component graph
  // marked dirty. Keyframe value binds instead target transient
  // BindableProperty holders (see
  // LinearAnimationInstance::keyFrameValueHolder) that aren't in the
  // component graph — they're read directly during animation apply — so only
  // propagate component dirt for Component targets.
  auto target = dataBind->target();
  if (target != nullptr && target->is<Component>())
  {
    onComponentDirty(target->as<Component>());
  }
  DataBindContainer::addDirtyDataBind(dataBind);
}

void Artboard::updateDataBinds(bool applyTargetToSource)
{
  for (auto artboardHost : m_ArtboardHosts)
  {
    artboardHost->updateDataBinds();
  }
  DataBindContainer::updateDataBinds(applyTargetToSource);
  // After this artboard's own binds: values they just wrote (a text style's
  // exposed inputs, data a style reads) reach the styles this same frame.
  for (auto consumer : m_hostDataContextConsumers)
  {
    consumer->updateHostedDataBinds();
  }
}

// How far the collapsed component at `index` jumps for a run ending at
// `runEnd` (see Component::m_collapsedRunSkip).
static uint16_t collapsedRunSkip(unsigned int runEnd, unsigned int index)
{
  return (uint16_t)std::min<unsigned int>(runEnd - index, UINT16_MAX);
}

void Artboard::markCollapsedRuns()
{
  m_collapsedRunsDirty = false;
  auto runEnd = (unsigned int)m_DependencyOrder.size();
  for (auto i = runEnd; i-- > 0;)
  {
    Component* component = m_DependencyOrder[i];
    // The dirt bit, as updateComponents reads it: isCollapsed() also
    // reports a display-hidden layout, which still updates.
    if ((component->m_Dirt & ComponentDirt::Collapsed) !=
        ComponentDirt::Collapsed)
    {
      runEnd = i;
      continue;
    }
    // Only stored when it moved, so an unchanged run leaves its
    // components' cache lines clean.
    uint16_t skip = collapsedRunSkip(runEnd, i);
    if (component->m_collapsedRunSkip != skip)
    {
      component->m_collapsedRunSkip = skip;
    }
  }
}

#ifdef TESTING
void Artboard::verifyCollapsedRuns() const
{
  auto runEnd = (unsigned int)m_DependencyOrder.size();
  for (auto i = runEnd; i-- > 0;)
  {
    Component* component = m_DependencyOrder[i];
    if ((component->m_Dirt & ComponentDirt::Collapsed) !=
        ComponentDirt::Collapsed)
    {
      runEnd = i;
    }
    else if (component->m_collapsedRunSkip != collapsedRunSkip(runEnd, i))
    {
      fprintf(
          stderr,
          "Collapsed '%s' at %u in artboard '%s' skips %u, not %u: "
          "a collapse change didn't reach collapseChanged()\n",
          component->name().c_str(),
          i,
          name().c_str(),
          (unsigned int)component->m_collapsedRunSkip,
          (unsigned int)collapsedRunSkip(runEnd, i));
      abort();
    }
  }
}
#endif

bool Artboard::updateComponents()
{
  if (!hasDirt(ComponentDirt::Components))
  {
    return false;
  }
  const int maxSteps = 100;
  int step = 0;
  auto count = m_DependencyOrder.size();
  while (hasDirt(ComponentDirt::Components) && step < maxSteps)
  {
    m_Dirt = m_Dirt & ~ComponentDirt::Components;
    if (m_collapsedRunsDirty)
    {
      markCollapsedRuns();
    }
#ifdef TESTING
    else
    {
      verifyCollapsedRuns();
    }
#endif

    // Track dirt depth here so that if something else marks
    // dirty, we restart.
    for (unsigned int i = 0; i < count; i++)
    {
      auto component = m_DependencyOrder[i];
      m_DirtDepth = i;
      auto d = component->m_Dirt;
      if ((d & ComponentDirt::Collapsed) == ComponentDirt::Collapsed)
      {
        // Collapsed components aren't updated, and they sit in long
        // runs (a Solo's inactive options): skip the whole run. If
        // anything collapsed or uncollapsed during this pass, the
        // skips are stale, so step one by one until the next pass
        // marks them again.
        if (!m_collapsedRunsDirty && component->m_collapsedRunSkip > 1)
        {
#ifdef TESTING
          sm_collapsedRunSkips++;
#endif
          i += component->m_collapsedRunSkip - 1;
        }
        continue;
      }
      if (d == ComponentDirt::None)
      {
        continue;
      }
      component->m_Dirt = ComponentDirt::None;
      component->update(d);

      // If the update changed the dirt depth by adding dirt
      // to something before us (in the DAG), early out and
      // re-run the update.
      if (m_DirtDepth < i)
      {
        break;
      }
    }
    step++;
  }
  return true;
}

LayoutData* Artboard::takeLayoutData()
{
#ifdef WITH_RIVE_LAYOUT
  m_updatesOwnLayout = false;
  return m_layoutData;
#else
  return nullptr;
#endif
}

void Artboard::cleanLayout(LayoutComponent* layoutComponent)
{
  assert(!m_isCleaningDirtyLayouts);
  if (m_isCleaningDirtyLayouts)
  {
    fprintf(
        stderr,
        "Artboard::cleanLayout - trying to remove a dirty layout "
        "during clean pass!\n");
    return;
  }

  if (!m_dirtyLayout.empty())
  {
    auto itr = m_dirtyLayout.find(layoutComponent);
    if (itr != m_dirtyLayout.end())
    {
      m_dirtyLayout.erase(itr);
    }
  }
  // If we called cleanLayout on ourselves, make sure to also
  // call it on our parent artboard in case we were dirtied
  if (layoutComponent == this)
  {
    Artboard* parent = parentArtboard();
    if (parent != nullptr)
    {
      parent->cleanLayout(layoutComponent);
    }
  }
}

void Artboard::markLayoutDirty(LayoutComponent* layoutComponent)
{
  wakeIfQuietRow();
  assert(!m_isCleaningDirtyLayouts);
  if (m_isCleaningDirtyLayouts)
  {
    fprintf(
        stderr,
        "Artboard::markLayoutDirty - trying to mark a layout dirty "
        "during clean pass!\n");
    return;
  }
#ifdef WITH_RIVE_TOOLS
  if (m_dirtyLayout.empty() && m_layoutDirtyCallback != nullptr)
  {
    m_layoutDirtyCallback(callbackUserData);
  }
#endif
  m_dirtyLayout.insert(layoutComponent);
  if (isInstance())
  {
    if (sharesLayoutWithHost())
    {
      m_host->markHostingLayoutDirty(this->as<ArtboardInstance>());
    }
    else
    {
      markHostTransformDirty();
    }
  }
  addDirt(ComponentDirt::Components);
}

void Artboard::markHostTransformDirty()
{
  wakeIfQuietRow();
#ifdef WITH_RIVE_TOOLS
  if (!m_hostTransformMarkedDirty && m_transformDirtyCallback != nullptr)
  {
    m_transformDirtyCallback(callbackUserData);
  }
#endif
  m_hostTransformMarkedDirty = true;
  if (host())
  {
    host()->markHostTransformDirty();
  }
}

void Artboard::syncStyleChangesWithUpdate(bool forceUpdate)
{
#ifdef WITH_RIVE_LAYOUT
  if (syncStyleChanges() && (m_updatesOwnLayout || forceUpdate))
  {
    calculateLayout();
    updateLayoutBounds(/*animation*/ true); // maybe use a static to allow
                                            // the editor to set this.
  }
#endif
}

bool Artboard::syncStyleChanges()
{
  bool updated = false;
  m_isCleaningDirtyLayouts = true;
#ifdef WITH_RIVE_LAYOUT
  if (!m_dirtyLayout.empty())
  {
    for (auto layout : m_dirtyLayout)
    {
      if (layout == nullptr)
      {
        continue;
      }
      switch (layout->coreType())
      {
        case ArtboardBase::typeKey:
        {
          auto artboard = layout->as<Artboard>();
          if (artboard == this)
          {
            artboard->syncStyle();
          }
          else
          {
            // This is a nested artboard, sync its changes too.
            if (!artboard->updatesOwnLayout())
            {
              artboard->syncStyleChanges();
            }
          }
          break;
        }

        default:
          layout->syncStyle();
          break;
      }
    }
    m_dirtyLayout.clear();
    updated = true;
  }
#endif
  m_isCleaningDirtyLayouts = false;
  return updated;
}

void Artboard::calculateLayout()
{
  // Always pass NAN and let calculateLayoutInternal decide whether to use
  // the intrinsic (hug) size or fall back to width()/height().
  //
  // This covers all cases:
  // - Runtime:
  //   - Top level artboards: intrinsically sized artboards get NAN so Yoga
  //     computes from children; fixed-size artboards fall back to
  //     width()/height() inside calculateLayoutInternal.
  //   - Nested node/leaf artboards (m_updatesOwnLayout == true): same as
  //     top-level, calculateLayoutInternal handles the distinction.
  //   - Nested layout-mode artboards (NestedArtboardLayout): their layout
  //     node is owned by the parent via takeLayoutData(), which sets
  //     m_updatesOwnLayout = false. syncStyleChangesWithUpdate() gates on
  //     that flag, so calculateLayout() is not reached for these.
  // - Editor:
  //   - Top level artboards: are handled on the Dart side so don't take
  //     this code path
  //   - Nested node/leaf artboards (m_updatesOwnLayout == true):
  //     same as runtime, calculateLayoutInternal handles the distinction.
  //   - Nested layout-mode artboards (NestedArtboardLayout): same
  //     as runtime, their layout node is owned by the Dart parent
  //     which sets m_updatesOwnLayout = false
#ifdef TESTING
  sm_layoutPassCount++;
#endif
  calculateLayoutInternal(NAN, NAN);
}

#ifdef WITH_RIVE_TOOLS
namespace
{
size_t s_settlePasses = 0;

void settlePass(Artboard* artboard)
{
  s_settlePasses++;
  artboard->updatePass(true);
}

template <typename Visit> void forEachHosted(Artboard* artboard, Visit visit)
{
  for (ArtboardHost* host : artboard->artboardHosts())
  {
    for (size_t i = 0; i < host->artboardCount(); i++)
    {
      if (ArtboardInstance* instance = host->artboardInstance((int)i))
      {
        visit(instance);
      }
    }
  }
}

void settleBottomUp(Artboard* artboard)
{
  forEachHosted(artboard, [](ArtboardInstance* hosted) {
    settleBottomUp(hosted);
  });
  settlePass(artboard);
}

void flushHostedTopDown(Artboard* artboard)
{
  forEachHosted(artboard, [](ArtboardInstance* hosted) {
    settlePass(hosted);
    flushHostedTopDown(hosted);
  });
}
} // namespace

void Artboard::settleAfterImageReveal()
{
  settleBottomUp(this);
  flushHostedTopDown(this);
}

size_t Artboard::settlePassesForTesting() { return s_settlePasses; }
void Artboard::resetSettlePassesForTesting() { s_settlePasses = 0; }

void Artboard::settleIfImagesRevealed()
{
  // Only an artboard that has been updated has layout to correct; one a
  // script never advanced draws as it would have without the reveal.
  uint32_t generation = RenderImage::revealGeneration();
  if (m_hasUpdated && m_seenImageRevealGeneration != generation)
  {
    m_seenImageRevealGeneration = generation;
    settleAfterImageReveal();
  }
}
#endif

bool Artboard::updatePass(bool isRoot)
{
#ifdef WITH_RIVE_TOOLS
  m_hasUpdated = true;
#endif
  RIVE_PROF_SCOPE()
  updateDataBinds();
  bool didUpdate = false;
  syncStyleChangesWithUpdate();
  m_hostTransformMarkedDirty = false;

  if (m_JoysticksApplyBeforeUpdate)
  {
    for (auto joystick : m_Joysticks)
    {
      joystick->apply(this);
    }
  }
  if (updateComponents())
  {
    didUpdate = true;
  }
  if (!m_JoysticksApplyBeforeUpdate)
  {
    for (auto joystick : m_Joysticks)
    {
      if (!joystick->canApplyBeforeUpdate())
      {
        updateDataBinds();
        if (updateComponents())
        {
          didUpdate = true;
        }
      }
      joystick->apply(this);
    }
    updateDataBinds();
    if (updateComponents())
    {
      didUpdate = true;
    }
  }
  if (didUpdate)
  {
    updateDataBinds();
  }
  return didUpdate;
}

bool Artboard::advanceInternal(float elapsedSeconds, AdvanceFlags flags)
{
  RIVE_PROF_SCOPE()
  bool didUpdate = false;

  for (auto adv : m_advancingComponents)
  {
    if (adv->advanceComponent(elapsedSeconds, flags))
    {
      didUpdate = true;
    }
  }
  if (advanceDataBinds(elapsedSeconds))
  {
    didUpdate = true;
  }

  return didUpdate;
}

void Artboard::reset() {}

bool Artboard::advance(float elapsedSeconds, AdvanceFlags flags)
{
  // Poll async work (image decodes, etc.) so promises resolve before
  // script advance() callbacks run.
  pollAsyncWork();

  AdvanceFlags advancingFlags = flags;
  advancingFlags |= AdvanceFlags::IsRoot;
  bool didUpdate = advanceInternal(elapsedSeconds, advancingFlags);
  if (updatePass(true))
  {
    didUpdate = true;
  }
  return didUpdate || hasDirt(ComponentDirt::Components);
}

Core* Artboard::hitTest(HitInfo* hinfo, const Mat2D& xform)
{
  if (clip())
  {
    // TODO: can we get the rawpath for the clip?
  }

  auto mx = xform;
  if (m_FrameOrigin)
  {
    mx *= Mat2D::fromTranslate(
        layoutWidth() * originX(),
        layoutHeight() * originY());
  }
  // Mirror drawInternal's own rotation/scale so hit-testing matches what is
  // drawn. This single spot also covers nested instances, since
  // NestedArtboard::hitTest re-enters Artboard::hitTest.
  if (hasSelfTransform())
  {
    mx *= selfTransform();
  }

  Drawable* last = m_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)
  {
    if (drawable->isHidden())
    {
      continue;
    }
    if (auto c = drawable->hitTest(hinfo, mx))
    {
      return c;
    }
  }

  // TODO: should we hit-test the background?

  return nullptr;
}

Vec2D Artboard::rootTransform(const Vec2D& point)
{
  // When this artboard is nested, its own rotation/scale (applied about the
  // origin at draw time) is part of how its contents land in the parent, so
  // fold it in before mapping through the host. Top-level artboards are the
  // root coordinate space, so their own transform is not applied here.
  if (host())
  {
    auto local = hasSelfTransform() ? selfTransform() * point : point;
    return host()->hostTransformPoint(local, this->as<ArtboardInstance>());
  }
#ifdef WITH_RIVE_TOOLS
  // Editor artboards don't have a host, so we expose a function that calls
  // the host in dart. The callback is only wired up for mounted (nested)
  // instances, so applying the self transform here matches the host() path.
  if (m_rootTransformCallback != nullptr)
  {
    auto local = hasSelfTransform() ? selfTransform() * point : point;
    auto x = m_rootTransformCallback(callbackUserData, local.x, local.y, true);
    auto y = m_rootTransformCallback(callbackUserData, local.x, local.y, false);
    return Vec2D(x, y);
  }
#endif
  return point;
}

bool Artboard::rootToLocal(const Vec2D& rootPosition, Vec2D* outLocal)
{
  // rootTransform is affine but only exposed as a point map (the editor
  // routes it through a callback), so rebuild its matrix from three points.
  Vec2D origin = rootTransform(Vec2D(0.0f, 0.0f));
  Vec2D xAxis = rootTransform(Vec2D(1.0f, 0.0f)) - origin;
  Vec2D yAxis = rootTransform(Vec2D(0.0f, 1.0f)) - origin;
  Mat2D toRoot(xAxis.x, xAxis.y, yAxis.x, yAxis.y, origin.x, origin.y);
  Mat2D toLocal;
  if (!toRoot.invert(&toLocal))
  {
    return false;
  }
  *outLocal = toLocal * rootPosition;
  return true;
}

bool Artboard::isRoot() const
{
  if (m_host != nullptr)
  {
    return false;
  }
#ifdef WITH_RIVE_TOOLS
  if (m_rootTransformCallback != nullptr)
  {
    return false;
  }
#endif
  return true;
}

bool Artboard::hitTestPoint(
    const Vec2D& position,
    bool skipOnUnclipped,
    bool isPrimaryHit)
{
  if (host() != nullptr && isInstance())
  {
    if (!host()->hitTestHost(
            position,
            skipOnUnclipped,
            this->as<ArtboardInstance>()))
    {
      return false;
    }
  }
#ifdef WITH_RIVE_TOOLS
  // Editor artboards don't have a host, so we expose a function that calls
  // the host in dart.
  if (m_testBoundsCallback != nullptr)
  {
    // Dart can't return booleans to cpp, so we use a uint_8 instead
    auto didHit = m_testBoundsCallback(
        callbackUserData,
        position.x,
        position.y,
        skipOnUnclipped);
    if (didHit == 0)
    {
      return false;
    }
  }
#endif
  return LayoutComponent::hitTestPoint(position, skipOnUnclipped, isPrimaryHit);
}

void Artboard::watermark(std::unique_ptr<Watermark> watermark)
{
  m_watermark = std::move(watermark);
}

bool Artboard::advanceWatermark(float elapsedSeconds)
{
  if (m_watermark == nullptr)
  {
    return false;
  }
  if (!m_watermark->advance(elapsedSeconds))
  {
    m_watermark = nullptr;
    return false;
  }
  return true;
}

void Artboard::draw(Renderer* renderer)
{
  sm_frameId++;
  // Nested artboards and component lists draw through drawInternal, so only a
  // top level draw can be diverted to the watermark. isPlaying() keeps an
  // artboard that is never advanced through a state machine (and so never
  // starts its watermark) drawing itself rather than freezing on a pre-roll
  // that would never end.
  if (m_watermark != nullptr && m_watermark->isPlaying())
  {
    m_watermark->draw(renderer, bounds());
    return;
  }
  // A standalone/root artboard is never cached as a bitmap: it is already the
  // top-level render target, and a host can skip drawing entirely via
  // didChange(). Only nested/instanced draws (which reach drawInternal
  // directly) participate in cache-as-bitmap.
  drawContent(renderer);
}

struct ModulatedDraw
{
  uint32_t propertyKey;
  // Alpha, red, green, blue of the tags above, multiplied in float so
  // depth does not round.
  std::array<float, 4> level = {1.0f, 1.0f, 1.0f, 1.0f};
};

static void modulatedDrawVisitor(
    void* context,
    Drawable* drawable,
    Renderer* renderer)
{
  auto modulated = static_cast<ModulatedDraw*>(context);
  auto property = drawable->customProperty(modulated->propertyKey);
  std::array<float, 4> own;
  if (property != nullptr && property->is<CustomPropertyNumber>())
  {
    float value = math::clamp(
        property->as<CustomPropertyNumber>()->propertyValue(),
        0.0f,
        1.0f);
    own = {1.0f, value, value, value};
  }
  else if (property != nullptr && property->is<CustomPropertyColor>())
  {
    ColorInt color = property->as<CustomPropertyColor>()->propertyValue();
    own = {
        colorOpacity(color),
        colorRed(color) / 255.0f,
        colorGreen(color) / 255.0f,
        colorBlue(color) / 255.0f};
  }
  else
  {
    // Tagged, but not with this key.
    drawable->draw(renderer);
    return;
  }
  std::array<float, 4> outer = modulated->level;
  unsigned int channels[4];
  for (size_t i = 0; i < own.size(); i++)
  {
    modulated->level[i] = outer[i] * own[i];
    channels[i] = (unsigned int)std::lround(modulated->level[i] * 255.0f);
  }
  renderer->modulateColor(
      colorARGB(channels[0], channels[1], channels[2], channels[3]),
      true);
  drawable->draw(renderer);
  modulated->level = outer;
}

void Artboard::drawModulated(
    Renderer* renderer,
    uint32_t propertyKey,
    const File* keysFile)
{
  ModulatedDraw modulated = {propertyKey};
  drawInternal(renderer, modulatedDrawVisitor, &modulated, keysFile);
}

const File* Artboard::drawVisitorFile() const
{
  return m_drawVisitorFile != nullptr ? m_drawVisitorFile
                                      : artboardFile().get();
}

void Artboard::drawHosted(
    Artboard* hosted,
    Renderer* renderer,
    bool bypassCache)
{
  DrawVisitor visitor = m_drawVisitor;
  if (visitor != nullptr)
  {
    // Name ids are per file, so a key means nothing in an artboard bound
    // in from another one.
    const File* file = drawVisitorFile();
    const File* hostedFile = hosted->artboardFile().get();
    if (hostedFile != nullptr && hostedFile != file)
    {
      visitor = nullptr;
    }
    hosted->m_drawVisitorFile = file;
  }
  if (bypassCache)
  {
    hosted->drawContent(renderer, visitor, m_drawVisitorContext);
    return;
  }
  hosted->drawInternal(renderer, visitor, m_drawVisitorContext);
}

void Artboard::drawInternal(
    Renderer* renderer,
    DrawVisitor visitor,
    void* visitorContext,
    const File* keysFile)
{
  if (keysFile != nullptr)
  {
    m_drawVisitorFile = keysFile;
  }
#ifdef RIVE_CANVAS
  // A cached bitmap has no drawables left to visit.
  if (visitor == nullptr && m_BitmapCache != nullptr &&
      drawCachedAsBitmap(renderer))
  {
    return;
  }
#endif
  drawContent(renderer, visitor, visitorContext);
}

void Artboard::drawContent(
    Renderer* renderer,
    DrawVisitor visitor,
    void* visitorContext)
{
  RIVE_PROF_SCOPE_L(1)
  m_didChange = false;
  if (childOpacity() == 0)
  {
    return;
  }
  // Hosted artboards read these while this draw runs. A draw started from
  // inside a visit hands them back, and none outlives its context.
  struct VisitorScope
  {
    Artboard* artboard;
    DrawVisitor visitor;
    void* context;
    ~VisitorScope()
    {
      artboard->m_drawVisitor = visitor;
      artboard->m_drawVisitorContext = context;
    }
  } visitorScope{this, m_drawVisitor, m_drawVisitorContext};
  m_drawVisitor = visitor;
  m_drawVisitorContext = visitorContext;
  bool hasSelf = hasSelfTransform() && !m_skipSelfTransform;
  bool save = clip() || m_FrameOrigin || hasSelf;
  if (save)
  {
    renderer->save();
  }

  if (m_FrameOrigin)
  {
    Mat2D artboardTransform;
    artboardTransform[4] = layoutWidth() * originX();
    artboardTransform[5] = layoutHeight() * originY();
    renderer->transform(artboardTransform);
  }

  // Apply the artboard's own rotation/scale, pivoted around its origin.
  // Content-local (0,0) is the origin anchor, so this is simply rotation *
  // scale with no extra pivot translation. Applied after the frame-origin
  // translation so the anchor stays put, and it covers both top-level and
  // nested (mounted) rendering since both funnel through drawInternal.
  // Hit-testing mirrors this via selfTransform() so interaction matches.
  if (hasSelf)
  {
    renderer->transform(selfTransform());
  }

  // Clip after the frame-origin and self transforms so the clip region tracks
  // the (possibly rotated/scaled) artboard. The local path is the
  // content-local bounds, so it is transformed along with the content.
  if (clip())
  {
    renderer->clipPath(mutableRenderPaths().local.renderPath(this));
  }

  for (auto shapePaint : m_ShapePaints)
  {
    if (!shapePaint->shouldDraw())
    {
      continue;
    }
    auto shapePaintPath = shapePaint->pickPath(this);
    if (shapePaintPath == nullptr)
    {
      continue;
    }
    shapePaint->draw(renderer, shapePaintPath, worldTransform());
  }
  drawDrawableRange(renderer, m_FirstDrawable, nullptr);
  if (save)
  {
    renderer->restore();
  }
}

Mat2D Artboard::compositeSelfTransform() const
{
  // The self transform pivots on the frame origin, which a raster drawn
  // without it has inside, so conjugate by it.
  if (!m_FrameOrigin)
  {
    return selfTransform();
  }
  const Mat2D toOrigin = Mat2D::fromTranslate(
      layoutWidth() * originX(),
      layoutHeight() * originY());
  const Mat2D fromOrigin = Mat2D::fromTranslate(
      -layoutWidth() * originX(),
      -layoutHeight() * originY());
  return toOrigin * selfTransform() * fromOrigin;
}

void Artboard::drawContentUntransformed(Renderer* renderer)
{
  const bool previous = m_skipSelfTransform;
  m_skipSelfTransform = true;
  drawContent(renderer);
  m_skipSelfTransform = previous;
}

void Artboard::drawDrawableRange(
    Renderer* renderer,
    Drawable* first,
    Drawable* stop)
{
  // Empty clips is a counter for clipping shapes that are empty, for
  // example because they are hidden in a solo. If emptyClips > 0, the
  // drawables should not be drawn. A layer mask's source bracket rides the
  // same counter to suppress the source in the normal pass.
  int emptyClips = 0;
  // We stack clip operations to avoid calling a save + clip + restore on
  // clipping that don't have any drawables in between. this is a common
  // case with drawables in solos where the drawables are not drawn.
  // Deliberately a local: this function recurses through drawMasked.
  std::vector<Drawable*> pendingClipOperations;
  for (auto drawable = first; drawable != stop; drawable = drawable->prev)
  {
    auto prevClips = emptyClips;
    emptyClips += drawable->emptyClipCount();
    if (!drawable->willDraw() || emptyClips != prevClips || emptyClips > 0)
    {
      continue;
    }
    if (drawable->isClipStart())
    {
      pendingClipOperations.push_back(drawable);
      continue;
    }
    else if (pendingClipOperations.size() > 0)
    {
      // If there are clip operations pending and the next drawable is
      // a clip end, the clipping operation does not clip anything and
      // both can be skipped.
      if (drawable->isClipEnd())
      {
        pendingClipOperations.pop_back();
        continue;
      }
      else
      {
        for (auto& pendingClip : pendingClipOperations)
        {
          pendingClip->draw(renderer);
        }
        pendingClipOperations.clear();
      }
    }
    if (drawable->isMaskStart())
    {
      // Pending clips have already been flushed above, so the ancestor
      // clips are live on `renderer` and will constrain the composite.
      auto* startMarker = static_cast<LayerMaskProxyDrawable*>(drawable);
      Drawable* end = startMarker->pairedEnd();
      if (drawMasked(renderer, startMarker, end))
      {
        // Consumed: skip to the closing marker. `continue` runs the
        // for-increment, so the next iteration starts at end->prev.
        drawable = end;
      }
      // Otherwise fall through and let the range draw inline; the marker
      // itself draws nothing either way.
      continue;
    }
    if (drawable->isMaskEnd())
    {
      continue;
    }
    if (m_drawVisitor != nullptr && drawable->hasCustomProperties())
    {
      // Whatever the visitor sets on the renderer ends with the visit.
      renderer->save();
      m_drawVisitor(m_drawVisitorContext, drawable, renderer);
      renderer->restore();
    }
    else
    {
      drawable->draw(renderer);
    }
  }
}

#ifdef RIVE_CANVAS
namespace
{
// How much to pad a drawable that reported `approximate` bounds. Generous on
// purpose: the mask box is intersected with the artboard's own bounds, so the
// worst case of an over-wide margin is a raster no bigger than the one this
// whole change replaces -- while the worst case of an under-wide one is a hard
// crop through the middle of someone's artwork.
constexpr float kApproximateSlopDevicePx = 8.0f;
constexpr float kApproximateSlopFraction = 0.25f;

AABB padApproximate(const AABB& box, float rasterScale)
{
  const float relative = kApproximateSlopFraction *
                         std::max(box.width(), box.height());
  const float absolute = rasterScale > 0.0f
                             ? kApproximateSlopDevicePx / rasterScale
                             : kApproximateSlopDevicePx;
  const float slop = std::max(relative, absolute);
  if (!std::isfinite(slop) || slop <= 0.0f)
  {
    return box;
  }
  return box.outset(slop, slop);
}

// Float AABB has no intersect helper, and AABB::overlaps is wrong (it compares
// maxX against b.minY), so this is written out. False for an empty result.
bool intersectBoxes(const AABB& a, const AABB& b, AABB* out)
{
  const AABB r(
      std::max(a.left(), b.left()),
      std::max(a.top(), b.top()),
      std::min(a.right(), b.right()),
      std::min(a.bottom(), b.bottom()));
  if (r.isEmptyOrNaN())
  {
    return false;
  }
  *out = r;
  return true;
}
} // namespace

BoundsFidelity Artboard::rangeDrawBounds(
    Drawable* first,
    Drawable* stop,
    float rasterScale,
    AABB* out,
    bool* anyDrawn) const
{
  // The skip rules mirror drawDrawableRange deliberately, which is what buys
  // the awkward cases for free: a drawable inside a nested empty clip is
  // excluded, and so is a nested mask's source range -- its markers push the
  // same empty-clip counter -- while a nested mask's own members are
  // included, which is correct because a mask only ever attenuates what is
  // already there.
  int emptyClips = 0;
  AABB accumulated = AABB::forExpansion();
  BoundsFidelity worst = BoundsFidelity::exact;
  bool drew = false;

  for (auto* d = first; d != stop; d = d->prevDrawable())
  {
    const int prevClips = emptyClips;
    emptyClips += d->emptyClipCount();
    if (!d->willDraw() || emptyClips != prevClips || emptyClips > 0)
    {
      continue;
    }
    // Bracket markers paint nothing of their own: a clip only constrains
    // what follows it, and a mask marker is consumed by drawMasked.
    if (d->isClipStart() || d->isClipEnd() || d->isMaskStart() ||
        d->isMaskEnd())
    {
      continue;
    }
    drew = true;

    AABB painted;
    const BoundsFidelity fidelity = d->paintedWorldBounds(&painted);
    if (fidelity == BoundsFidelity::none)
    {
      // Not "pad it harder": there is no measurement to pad. Give up on a
      // tight box for this range rather than inventing one.
      *anyDrawn = true;
      return BoundsFidelity::none;
    }
    if (fidelity == BoundsFidelity::approximate)
    {
      worst = BoundsFidelity::approximate;
      painted = padApproximate(painted, rasterScale);
    }
    // A drawable can legitimately paint nothing -- a shape whose paths all
    // collapsed reports an empty box. Filtering here also keeps
    // AABB::forExpansion()'s +/-FLT_MAX sentinel out of the union.
    if (!painted.isEmptyOrNaN())
    {
      accumulated.expand(painted);
    }
  }

  *anyDrawn = drew;
  if (!drew)
  {
    return BoundsFidelity::exact;
  }
  if (accumulated.isEmptyOrNaN())
  {
    // Something drew but nothing measurable came of it. Rare, and not worth
    // reasoning about further: fall back.
    return BoundsFidelity::none;
  }
  *out = accumulated;
  return worst;
}

bool Artboard::drawMasked(
    Renderer* renderer,
    Drawable* startMarker,
    Drawable* endMarker)
{
  LayerMask& mask = *static_cast<LayerMaskProxyDrawable*>(startMarker)->mask();
  if (!mask.isVisible())
  {
    return false;
  }

  // Re-entry guard, and defence in depth rather than a fix for anything
  // reachable today.
  //
  // onAddedClean rejects a mask whose source sits under its own parent, which
  // only catches a mask pointing at itself. Two masks naming each other's
  // subtrees pass that test, and the coverage pass draws a RANGE that
  // drawDrawableRange dispatches from, so in principle A could rasterize B
  // which rasterizes A without bound.
  //
  // In practice spliceLayerMaskBracket grows every range outward until it is
  // balanced with the brackets already in the list, so brackets nest and
  // never interleave: if B's members sit inside A's source bracket, B's range
  // grows to enclose the whole of A, which puts A's source range INSIDE B
  // rather than the other way round, and walking it never reaches B's start
  // marker. A mutual pair therefore terminates today -- there is a
  // [layer-mask] test pinning exactly that -- and this costs a bool and a
  // branch against the day the nesting invariant is relaxed, or a longer
  // cycle is reached some other way.
  //
  // Per mask, so legitimate nesting -- a different LayerMask inside a masked
  // subtree -- is unaffected.
  if (mask.m_isDrawing)
  {
    return false;
  }
  // Cleared however this returns, and there are many exits below.
  struct DrawingGuard
  {
    LayerMask& mask;
    DrawingGuard(LayerMask& m) : mask(m) { mask.m_isDrawing = true; }
    ~DrawingGuard() { mask.m_isDrawing = false; }
  } drawingGuard(mask);

  // canvasContentHost, not deferredCanvasHost: this only needs somewhere to
  // rasterize into. No host means nobody can give us an offscreen frame (a
  // plain non-GPU or test factory), so the content draws unmasked -- the
  // permanent fallback, and the reason a mask degrades rather than vanishing.
  Factory* f = factory();
  auto* host = f ? f->canvasContentHost() : nullptr;
  if (host == nullptr)
  {
    return false;
  }

  // The same fallback, one step earlier, for a host that can rasterize but
  // cannot apply the mask. Renderer::applyLayerMask already no-ops there, but
  // finding out that late is too late: the rasters below are sized to the
  // content-and-coverage intersection, so the layer would come back unmasked
  // and *cropped* to a box that only made sense if the mask had been applied.
  // Bailing here draws the range inline -- unmasked for real, and two
  // canvases and a composite cheaper.
  if (!host->supportsLayerMask())
  {
    return false;
  }

  // The raster scale before anything is measured: it depends only on the
  // renderer's transform, and it is the unit the slop margin for an
  // approximately-bounded drawable is expressed against.
  offscreen::RasterPlan plan;
  if (!offscreen::planRasterScale(renderer, mask.resolution(), &plan))
  {
    return false;
  }

  // mask.m_dirty alone. LayerMask sits on the dependency graph as a dependent
  // of everything in its own range and its own source, so its update() raises
  // this when -- and only when -- something it actually rasterizes changed.
  //
  // This used to also read the artboard-wide "something moved" flag, which
  // meant every mask re-rasterized both of its canvases whenever anything
  // anywhere in the artboard moved, however unrelated. That flag was captured
  // into a separate field just for this read, and both are now gone.
  const bool contentChanged = mask.m_contentCanvas == nullptr ||
                              mask.m_maskCanvas == nullptr || mask.m_dirty;

  AABB tight;
  if (contentChanged)
  {
    // Measuring both ranges also answers "would anything draw at all",
    // which is what the two cheap probes that used to live here did on
    // their own.
    bool contentDraws = false;
    AABB contentBox;
    const BoundsFidelity contentFidelity = rangeDrawBounds(
        startMarker->prevDrawable(),
        endMarker,
        plan.rasterScale,
        &contentBox,
        &contentDraws);
    if (!contentDraws)
    {
      // Nothing in the range would have drawn, so consume the bracket
      // rather than rasterizing two empty textures.
      return true;
    }

    bool coverageDraws = false;
    AABB sourceBox;
    BoundsFidelity sourceFidelity = BoundsFidelity::none;
    if (mask.sourceStart() == nullptr)
    {
      // No source bracket. Two very different situations arrive here and
      // the mode-switch below is only right for one of them.
      //
      // interleaveLayerMasks splices the masked range first and the
      // source second, and the second can fail on its own -- a draw rule
      // can scatter the source subtree so it is not contiguous. The
      // masked bracket is already in the list by then, so this mask is
      // live with no source bracket, and the source subtree is NOT
      // suppressed: it draws in its natural position. Treating coverage
      // as absent would erase the whole masked range in alpha/luminance
      // while the mask art itself stayed on screen -- the content gone
      // and the mask visible, which is the worst of both.
      //
      // So only take the empty-coverage path when the source genuinely
      // draws nothing. If anything in it would draw, the bracket is the
      // thing that is missing, and the mask goes inert: return false and
      // the range draws inline, unmasked.
      for (Drawable* d : mask.sourceDrawables())
      {
        if (d->willDraw())
        {
          return false;
        }
      }
    }
    else
    {
      // Over the source bracket rather than sourceDrawables(), matching
      // what the coverage pass below actually draws -- so a clipping
      // shape nested inside the source is accounted for the same way.
      sourceFidelity = rangeDrawBounds(
          mask.sourceStart()->prevDrawable(),
          mask.sourceEnd(),
          plan.rasterScale,
          &sourceBox,
          &coverageDraws);
    }
    if (!coverageDraws)
    {
      // Coverage is zero everywhere -- the mask source is hidden, or sits
      // in an inactive solo. Which way that falls depends on the mode,
      // and both answers avoid the GPU entirely.
      switch (mask.maskMode())
      {
        case MaskMode::alpha:
        case MaskMode::luminance:
          return true; // content fully masked out
        case MaskMode::invertedAlpha:
        case MaskMode::invertedLuminance:
          return false; // content fully visible; draw it inline
      }
    }

    // One box and one scale for both canvases, so a content texel and a
    // coverage texel at the same coordinate correspond with no resampling
    // and no second transform.
    bool authoredBox = false;
    const AABB authored = mask.customBounds();
    if (mask.useCustomBounds() && !authored.isEmptyOrNaN())
    {
      // The author drew this rectangle, in artboard space. Taken
      // verbatim: no slop margin, and deliberately no intersect with the
      // artboard box either, because cropping a mask to a region that
      // reaches outside the artboard is intent rather than an error.
      // kMaxDim still caps it.
      //
      // The ranges above were still walked, which is what keeps the
      // "nothing draws" and "no coverage" shortcuts working; only the box
      // comes from here. The mode-aware intersect is skipped on purpose
      // -- the author has already said which region matters.
      //
      // A degenerate rectangle -- zero or negative extent, which is what
      // a half-drawn one looks like -- falls through to measuring rather
      // than collapsing the raster and dropping the layer.
      tight = authored;
      authoredBox = true;
    }
    else if (contentFidelity == BoundsFidelity::none)
    {
      // Something in the range could not say where it paints. Fall back
      // to the box that is always big enough.
      tight = bounds();
    }
    else
    {
      tight = contentBox;
      // In the un-inverted modes the coverage texel is zero outside the
      // source, so content out there is erased anyway: intersecting costs
      // nothing and it is where the win lives, because a small mask over
      // a full-stage layer now rasterizes only the small mask. The
      // inverted modes are the opposite -- absent coverage means a factor
      // of 1, so the content box has to stand on its own.
      const bool intersectsSource = mask.maskMode() == MaskMode::alpha ||
                                    mask.maskMode() == MaskMode::luminance;
      if (sourceFidelity != BoundsFidelity::none)
      {
        // sourceBox is a superset of where coverage actually lands, so
        // "these do not overlap" is a claim that holds: no coverage
        // reaches the content at all.
        AABB overlap;
        const bool overlaps = intersectBoxes(tight, sourceBox, &overlap);
        if (intersectsSource)
        {
          if (!overlaps)
          {
            // Every content texel would be multiplied by zero
            // coverage. Consume the bracket and draw nothing at
            // all.
            return true;
          }
          tight = overlap;
        }
        else if (!overlaps)
        {
          // Inverted, so absent coverage means a factor of one: the
          // layer is fully visible. Decline the bracket and let it
          // draw inline, exactly as a source that draws nothing at
          // all does.
          return false;
        }
      }
    }

    // Clamped to the artboard only when the artboard actually clips.
    //
    // When it does, content reaching past the edge is cropped at composite
    // time anyway, so rasterizing it would be wasted texels -- and the
    // clamp keeps the raster no larger than the artboard-sized one this
    // replaced, which is what makes the common case monotone: kMaxDim's
    // coarsening can only bite less than before, never more.
    //
    // When it does not clip, that content is genuinely visible, and
    // clamping would crop it inside the mask while it draws fine everywhere
    // else. The artboard-sized rasters had that bug too; this is where it
    // is fixed.
    //
    // The cost is that the monotone guarantee does not hold for an
    // unclipped artboard whose content sprawls far past it: a bigger box
    // can hit kMaxDim and coarsen. Blurrier beats cropped.
    //
    // Skipped entirely for an authored box, where reaching outside the
    // artboard is a decision rather than an accident.
    if (!authoredBox && clip() && !intersectBoxes(tight, bounds(), &tight))
    {
      return false;
    }
  }
  else
  {
    // Nothing changed, so re-measuring would land in the same place. Re-fit
    // the box that was measured, never the box that was fitted -- feeding a
    // fitted box back through the guard band would grow the raster a few
    // texels on every frame.
    tight = mask.m_tightBox;
  }

  // A guard band of transparent texels on every side. Without it the content
  // reaches the raster edge, and the composite's LinearClamp then replicates
  // that edge texel outward under rotation: a one-texel smear along the seam.
  // It is added after the artboard clamp above, so the band can sit a couple
  // of texels outside the artboard -- where the composite is itself clipped
  // when the artboard clips, and where showing those texels is the more
  // correct answer when it does not.
  constexpr uint32_t kGuardTexels = 2;
  if (!offscreen::fitRasterToBox(
          tight,
          kGuardTexels,
          offscreen::RasterFit::stableGrid,
          &plan))
  {
    return false;
  }

  // Growth is immediate, shrinking waits. Anything rotating or scaling
  // changes the size of its own bounding box every frame, and re-allocating
  // two GPU textures that often costs far more than carrying one bucket of
  // slack.
  const offscreen::RasterResize resize = offscreen::decideRasterResize(
      plan.widthPx,
      plan.heightPx,
      mask.m_widthPx,
      mask.m_heightPx,
      &mask.m_shrinkStreak);
  // Hold whatever allocation was settled on, growing the box right and bottom
  // to span it so the composite's inverse still maps exactly onto the pixels.
  offscreen::holdRasterAllocation(resize.widthPx, resize.heightPx, &plan);

  // New textures hold nothing, and the cap inside fitRasterToBox can lower
  // the scale out from under a cached raster, so either forces a rebuild even
  // on a frame that had decided it could reuse what it had.
  const bool mustRaster = contentChanged || resize.reallocate ||
                          plan.rasterScale != mask.m_rasterScale;

  if (mustRaster)
  {
    if (resize.reallocate || mask.m_contentCanvas == nullptr ||
        mask.m_maskCanvas == nullptr)
    {
      mask.m_contentCanvas = host->makeContentCanvas(
          plan.widthPx,
          plan.heightPx);
      mask.m_maskCanvas = host->makeContentCanvas(plan.widthPx, plan.heightPx);
#ifdef TESTING
      mask.testAllocations++;
#endif
    }
    if (mask.m_contentCanvas == nullptr || mask.m_maskCanvas == nullptr)
    {
      mask.releaseCanvases();
      return false;
    }

    // Sequentially, never nested: DeferredSession::endCanvasContent routes
    // back to the screen rather than to an enclosing canvas, so an inner
    // bracket closing inside an outer one would misroute the rest of the
    // outer content. Finishing the coverage canvas before opening the
    // content one keeps the recorded stream two independent segments.
    bool opened = true;
    {
      offscreen::CanvasContentScope scope(
          host,
          mask.m_maskCanvas.get(),
          plan,
          0);
      if (Renderer* r = scope.renderer())
      {
        // Over the source bracket, not sourceDrawables() directly, so a
        // clipping shape nested inside the source still brackets its
        // own drawables. Starting past the opening marker keeps its
        // own +1 suppression from hiding the very range we want.
        drawDrawableRange(
            r,
            mask.sourceStart()->prevDrawable(),
            mask.sourceEnd());
      }
      else
      {
        opened = false;
      }
    }
    if (opened)
    {
      offscreen::CanvasContentScope scope(
          host,
          mask.m_contentCanvas.get(),
          plan,
          0);
      if (Renderer* r = scope.renderer())
      {
        drawDrawableRange(r, startMarker->prevDrawable(), endMarker);
        // The mask apply has to be the last draw into this canvas: it
        // multiplies everything already there, so anything drawn after
        // it would land unmasked. Issued in the canvas's own pixel
        // space (the scope's transform is still in effect, so undo it)
        // because the coverage texture is the same size as the target
        // and has to line up texel for texel.
        if (rcp<RenderImage> coverage = host->contentCanvasImage(
                mask.m_maskCanvas.get()))
        {
          r->save();
          const float inv = 1.0f / plan.rasterScale;
          r->translate(plan.box.left(), plan.box.top());
          r->transform(Mat2D::fromScale(inv, inv));
          r->applyLayerMask(
              coverage.get(),
              ImageSampler::LinearClamp(),
              static_cast<LayerMaskMode>(mask.maskMode()));
          r->restore();
        }
      }
      else
      {
        opened = false;
      }
    }
    if (!opened)
    {
      // The host could not open an offscreen frame. Nothing was drawn, so
      // drop the canvases and stay dirty: a later frame retries, and in
      // the meantime the content draws unmasked rather than as a hole.
      mask.releaseCanvases();
      mask.m_dirty = true;
      return false;
    }

    // Commit what the pixels now are. m_tightBox is what a later frame
    // re-fits from; m_box is where these pixels live, which is what the
    // composite has to place them at even after the plan moves on.
    mask.m_tightBox = tight;
    mask.m_box = plan.box;
    mask.m_widthPx = plan.widthPx;
    mask.m_heightPx = plan.heightPx;
    mask.m_rasterScale = plan.rasterScale;
    mask.m_dirty = false;
  }

  rcp<RenderImage> contentImage = host->contentCanvasImage(
      mask.m_contentCanvas.get());
  rcp<RenderImage> coverageImage = host->contentCanvasImage(
      mask.m_maskCanvas.get());
  if (contentImage == nullptr || coverageImage == nullptr)
  {
    return false;
  }

  // mask.m_box, not plan.box: on a frame that reused the cached rasters the
  // plan was re-fitted from scratch, and the pixels being composited belong
  // to whatever box they were rasterized for.
  auto placement = offscreen::beginComposite(
      renderer,
      host,
      plan,
      mask.m_rasterScale,
      mask.m_box);
  placement.renderer->drawImage(
      contentImage.get(),
      ImageSampler::LinearClamp(),
      BlendMode::srcOver,
      placement.opacity);
  offscreen::endComposite(placement);
  return true;
}
#else
bool Artboard::drawMasked(Renderer*, Drawable*, Drawable*) { return false; }
#endif

#ifdef RIVE_CANVAS
bool Artboard::drawCachedAsBitmap(Renderer* renderer)
{
  // Only reached when m_BitmapCache != nullptr (guarded in drawInternal).
  BitmapCache& cache = *m_BitmapCache;

  if (!cache.cacheEnabled())
  {
    // Authored off (or animated/bound off): behave as though the artboard
    // had no BitmapCache at all. The texture is released by
    // BitmapCache::cacheFlagsChanged when the bit clears.
    return false;
  }

  if (consumeInvisibleChange())
  {
    return true;
  }

  // The raster is untransformed; the self transform applies at composite, so
  // rotated or scaled art keeps its footprint. Set before planning: the pixel
  // snap reads the CTM.
  const bool hasSelf = hasSelfTransform();
  if (hasSelf)
  {
    renderer->save();
    renderer->transform(compositeSelfTransform());
  }
  struct SelfScope
  {
    Renderer* renderer;
    bool active;
    ~SelfScope()
    {
      if (active)
      {
        renderer->restore();
      }
    }
  } selfScope{renderer, hasSelf};

  offscreen::RasterPlan plan;
  cmd::DeferredCanvasHost* host = nullptr;
  rcp<RenderImage> image = rasterImage(
      renderer,
      cache.m_raster,
      cache.resolution(),
      /*fixedSize=*/false,
      &plan,
      &host);
  if (image == nullptr)
  {
    return false;
  }

  // Composite the cached texture in place of the vector content. The
  // artboard's own opacity is already baked into the raster (host/render
  // opacity propagate to children and invalidate the cache via
  // onComponentDirty), so the only opacity left to apply is an enclosing
  // modulateOpacity() scope -- and only on the fresh-renderer path, which
  // does not inherit it. m_raster's scale, not plan.rasterScale: the raster
  // being composited may have been built on an earlier frame, and the mapping
  // has to invert the scale it was actually drawn at.
  auto placement = offscreen::beginComposite(
      renderer,
      host,
      plan,
      cache.m_raster.rasterScale,
      cache.m_raster.box);
  placement.renderer->drawImage(
      image.get(),
      ImageSampler::LinearClamp(),
      BlendMode::srcOver,
      placement.opacity);
  offscreen::endComposite(placement);
  return true;
}

bool Artboard::consumeInvisibleChange()
{
  if (childOpacity() != 0.0f)
  {
    return false;
  }
  // Fully transparent: consume the change as drawContent() would, or a host
  // gating on didChange() (Unity) resubmits forever. Fold it into the raster
  // so moved content re-rasterizes once visible.
  m_didChange = false;
  return true;
}

rcp<RenderImage> Artboard::rasterImage(
    Renderer* renderer,
    offscreen::CachedRaster& raster,
    float resolution,
    bool fixedSize,
    offscreen::RasterPlan* planOut,
    cmd::DeferredCanvasHost** hostOut)
{
  Factory* f = factory();
  // canvasContentHost, not deferredCanvasHost: this only needs somewhere to
  // rasterize into, and an immediate renderer can provide that without
  // claiming its content is being recorded. No host means nobody can give
  // us an offscreen frame (a plain non-GPU or test factory).
  auto* host = f ? f->canvasContentHost() : nullptr;
  if (host == nullptr)
  {
    return nullptr;
  }

  // The artboard's own box, which is not [0,0,width,height] in general: with
  // frameOrigin off, bounds() is offset by the origin -- and every host turns
  // frameOrigin off on the artboards it nests. bounds() also tracks the
  // resolved layout size rather than the authored width/height.
  offscreen::RasterPlan plan;
  const bool planned = fixedSize ? offscreen::planFixedRaster(
                                       renderer,
                                       bounds(),
                                       resolution,
                                       &plan)
                                 : offscreen::planRaster(
                                       renderer,
                                       bounds(),
                                       resolution,
                                       &plan);
  if (!planned)
  {
    return nullptr;
  }

  const bool geomChanged = plan.widthPx != raster.widthPx ||
                           plan.heightPx != raster.heightPx ||
                           plan.rasterScale != raster.rasterScale;
  // Consumes a self-transform-only change. Cleared before the draw so a
  // change raised while drawing stays pending.
  m_didChange = false;
  if (raster.canvas == nullptr || raster.dirty || geomChanged ||
      raster.contentRevision != m_contentRevision)
  {
    renderIntoCanvas(host, plan, raster);
  }
  if (raster.canvas == nullptr)
  {
    return nullptr; // allocation failed
  }
  // Not necessarily the canvas's own image: some backends cannot sample
  // their canvas textures directly and stand in a companion for it.
  rcp<RenderImage> image = host->contentCanvasImage(raster.canvas.get());
  if (image == nullptr)
  {
    return nullptr;
  }
  *planOut = plan;
  *hostOut = host;
  return image;
}

void Artboard::renderIntoCanvas(
    cmd::DeferredCanvasHost* deferredHost,
    const offscreen::RasterPlan& plan,
    offscreen::CachedRaster& raster)
{
  // Reuse the texture whenever it is already the right size. This runs on
  // every frame the artboard changes, and on an immediate host each of these
  // is a real GPU allocation -- re-minting one per frame both defeats the
  // point of a cache and thrashes the driver.
  if (raster.canvas == nullptr || raster.widthPx != plan.widthPx ||
      raster.heightPx != plan.heightPx)
  {
    // The host decides whether this needs real pixels now or can defer
    // them to whoever replays.
    raster.canvas = deferredHost->makeContentCanvas(
        plan.widthPx,
        plan.heightPx);
  }
  if (raster.canvas == nullptr)
  {
    return;
  }

  // The scope opens the content bracket and applies the raster transform;
  // drawContent (not drawInternal) so we never re-enter the cache hook.
  // clearColor is transparent black.
  bool opened = false;
  uint64_t revision = 0;
  {
    offscreen::CanvasContentScope scope(
        deferredHost,
        raster.canvas.get(),
        plan,
        0);
    if (Renderer* r = scope.renderer())
    {
      opened = true;
      revision = m_contentRevision;
      drawContentUntransformed(r);
    }
  }
  if (!opened)
  {
    // The host could not open an offscreen frame (an unbacked canvas, or a
    // host that cannot nest one). Nothing was drawn, so the canvas holds
    // whatever it held before -- uninitialized on the first attempt. Drop
    // it rather than end a bracket that never began: the caller's null
    // check then takes the vector path, and leaving the raster dirty means
    // a later frame retries instead of compositing this hole forever.
    raster.release();
    return;
  }

  raster.widthPx = plan.widthPx;
  raster.heightPx = plan.heightPx;
  raster.rasterScale = plan.rasterScale;
  raster.box = plan.box;
  raster.contentRevision = revision;
  raster.dirty = false;
}
#endif

void Artboard::addToRenderPath(RenderPath* path, const Mat2D& transform)
{
  for (auto drawable = m_FirstDrawable; drawable != nullptr;
       drawable = drawable->prev)
  {
    if (drawable->isHidden() || !drawable->is<Shape>())
    {
      continue;
    }
    Shape* shape = drawable->as<Shape>();
    shape->addToRenderPath(path, transform);
  }
}

void Artboard::addToRawPath(RawPath& path, const Mat2D* transform)
{
  for (auto drawable = m_FirstDrawable; drawable != nullptr;
       drawable = drawable->prev)
  {
    if (drawable->isHidden() || !drawable->is<Shape>())
    {
      continue;
    }
    Shape* shape = drawable->as<Shape>();
    shape->addToRawPath(path, transform);
  }
}

Vec2D Artboard::origin() const
{
  return m_FrameOrigin
             ? Vec2D(0.0f, 0.0f)
             : Vec2D(-layoutWidth() * originX(), -layoutHeight() * originY());
}

void Artboard::xChanged()
{
  Super::xChanged();
  markHostTransformDirty();
}

void Artboard::yChanged()
{
  Super::yChanged();
  markHostTransformDirty();
}

// Origin has no dedicated animation/change plumbing, so a live change (e.g. a
// nested artboard origin override, or a keyframed artboard origin) would leave
// the cached render path and layout stale. Invalidate the background/clip path
// (updateRenderPath reads origin) and force the update pass to re-run so the
// content is repositioned. Components dirt is what a hosting NestedArtboard
// keys off (see NestedArtboard::advanceComponent) to re-run our updatePass;
// markHostTransformDirty notifies the host that our transform moved.
void Artboard::originXChanged()
{
  // Base originXChanged is a no-op; go straight to invalidation.
  addDirt(ComponentDirt::Path | ComponentDirt::Components);
  markHostTransformDirty();
}

void Artboard::originYChanged()
{
  addDirt(ComponentDirt::Path | ComponentDirt::Components);
  markHostTransformDirty();
}

AABB Artboard::bounds() const
{
  return m_FrameOrigin ? AABB(0.0f, 0.0f, layoutWidth(), layoutHeight())
                       : AABB::fromLTWH(
                             -layoutWidth() * originX(),
                             -layoutHeight() * originY(),
                             layoutWidth(),
                             layoutHeight());
}

AABB Artboard::worldBounds() const
{
  return AABB::fromLTWH(
      NodeBase::x(),
      NodeBase::y(),
      m_layout.width(),
      m_layout.height());
}

bool Artboard::isTranslucent() const
{
  for (const auto sp : m_ShapePaints)
  {
    if (!sp->isTranslucent())
    {
      return false; // one opaque fill is sufficient to be opaque
    }
  }
  return true;
}

bool Artboard::hasAudio() const
{
  for (auto object : m_Objects)
  {
    if (object != nullptr && object->coreType() == AudioEventBase::typeKey)
    {
      return true;
    }
  }
  for (auto artboardHost : m_ArtboardHosts)
  {
    for (int i = 0; i < artboardHost->artboardCount(); i++)
    {
      auto artboard = artboardHost->artboardInstance(i);
      if (artboard != nullptr && artboard->hasAudio())
      {
        return true;
      }
    }
  }
  return false;
}

bool Artboard::isTranslucent(const LinearAnimation* anim) const
{
  // For now we're conservative/lazy -- if we see that any of our paints are
  // animated we assume that might make it non-opaque, so we early out
  for (const auto& obj : anim->m_KeyedObjects)
  {
    const auto ptr = this->resolve(obj->objectId());
    for (const auto sp : m_ShapePaints)
    {
      if (ptr == sp)
      {
        return true;
      }
    }
  }

  // If we get here, we have no animations, so just check our paints for
  // opacity
  return this->isTranslucent();
}

bool Artboard::isTranslucent(const LinearAnimationInstance* inst) const
{
  return this->isTranslucent(inst->animation());
}

std::string Artboard::animationNameAt(size_t index) const
{
  auto la = this->animation(index);
  return la ? la->name() : "";
}

// Helper: check if a FocusData has a parent FocusData within the artboard
// by walking up the component hierarchy
static bool hasParentFocusData(const FocusData* focusData)
{
  // FocusData's parent is a ContainerComponent (likely a Node)
  // Walk up to find if any ancestor Node has a FocusData child
  auto* current = focusData->parent();
  while (current != nullptr)
  {
    if (current->is<Node>())
    {
      auto* node = current->as<Node>();
      for (auto child : node->children())
      {
        if (child->is<FocusData>() && child != focusData)
        {
          return true;
        }
      }
    }
    current = current->parent();
  }
  return false;
}

size_t Artboard::rootFocusDataCount() const
{
  size_t count = 0;
  for (auto* object : m_Objects)
  {
    if (object != nullptr && object->is<FocusData>())
    {
      if (!hasParentFocusData(object->as<FocusData>()))
      {
        count++;
      }
    }
  }
  return count;
}

FocusData* Artboard::rootFocusDataAt(size_t index) const
{
  size_t count = 0;
  for (auto* object : m_Objects)
  {
    if (object != nullptr && object->is<FocusData>())
    {
      if (!hasParentFocusData(object->as<FocusData>()))
      {
        if (count == index)
        {
          return object->as<FocusData>();
        }
        count++;
      }
    }
  }
  return nullptr;
}

namespace
{
// Depth-first in scene (Container child) order so FocusManager child order
// (tab) matches the hierarchy, not the flat m_Objects / grouped passes.
// At most one FocusData is allowed as a direct child of a container; it is
// registered in a first pass, then child traversal skips that FocusData.
void buildFocusTreeVisit(
    FocusManager* focusManager,
    Component* component,
    rcp<FocusNode> focusNode)
{
  if (component == nullptr)
  {
    return;
  }
  if (component->is<NestedArtboard>())
  {
    auto* nestedHost = component->as<NestedArtboard>();
    // Wire the nested state machines to this manager before placing the
    // scope: setExternalFocusManager rebuilds the nested focus tree at the
    // manager root, so it must run first. Track whether any was actually
    // re-wired — a re-wire leaves the tree at the root and requires
    // re-homing under the scope (forceRebuild); an already-wired tree is
    // left in place.
    bool rewired = false;
    for (auto* animation : nestedHost->nestedAnimations())
    {
      if (animation->is<NestedStateMachine>())
      {
        auto* nsm = animation->as<NestedStateMachine>();
        auto* smi = nsm->stateMachineInstance();
        if (smi != nullptr && smi->focusManager() != focusManager)
        {
          smi->setExternalFocusManager(focusManager);
          rewired = true;
        }
      }
    }
    // Scope placement must be the final write so it overrides the root
    // rebuild above. For data-bound hosts this parents the nested focus
    // tree under the host's persistent structural scope; static hosts
    // build directly under focusNode. placeScope=true: the build pass is
    // the ordering authority — the scope is re-appended at the walk's
    // position.
    nestedHost->syncNestedFocusTree(
        focusNode,
        /*placeScope=*/true,
        /*forceRebuild=*/rewired);
  }
  else if (component->is<ArtboardComponentList>())
  {
    auto* list = component->as<ArtboardComponentList>();
    list->ensureListScopeFocusNode(focusManager, focusNode);
  }
  if (component->is<ContainerComponent>())
  {
    auto* cc = component->as<ContainerComponent>();
    FocusData* directFd = nullptr;
    for (Component* ch : cc->children())
    {
      if (ch != nullptr && ch->is<FocusData>())
      {
        directFd = ch->as<FocusData>();
        break;
      }
    }
    rcp<FocusNode> recurseWith;
    if (directFd != nullptr)
    {
      focusManager->addChild(focusNode, directFd->focusNode());
      recurseWith = directFd->focusNode();
    }
    else
    {
      recurseWith = focusNode;
    }
    for (Component* ch : cc->children())
    {
      if (ch == nullptr || ch->is<FocusData>())
      {
        continue;
      }
      buildFocusTreeVisit(focusManager, ch, recurseWith);
    }
  }
}
} // namespace

FocusManager* Artboard::ensureFocusManager()
{
  if (m_activeFocusManager != nullptr)
  {
    return m_activeFocusManager;
  }
  if (m_ownedFocusManager == nullptr)
  {
    m_ownedFocusManager = std::make_unique<FocusManager>();
  }
  m_activeFocusManager = m_ownedFocusManager.get();
  return m_activeFocusManager;
}

void Artboard::adoptFocusManager(FocusManager* manager)
{
  // A null manager means "stop borrowing", which falls back to our own if we
  // have one — the same shape as clearing the old external-manager override.
  if (manager == nullptr)
  {
    manager = m_ownedFocusManager.get();
  }
  if (m_activeFocusManager == manager)
  {
    return;
  }

  if (m_activeFocusManager != nullptr)
  {
    cleanupFocusTree();
  }

  m_activeFocusManager = manager;

  if (manager != nullptr)
  {
    buildFocusTree(manager, nullptr);
  }
}

void Artboard::buildFocusTree(
    FocusManager* focusManager,
    rcp<FocusNode> parentFocusNode)
{
  if (focusManager == nullptr)
  {
    return;
  }

  // Store reference to the active focus manager
  setActiveFocusManager(focusManager);

#ifdef WITH_RIVE_TOOLS
  // Store the parent focus node if provided (for later retrieval by tools)
  if (parentFocusNode != nullptr)
  {
    m_externalParentFocusNode = parentFocusNode;
  }
  // Use explicit parent if provided, otherwise fall back to external parent
  rcp<FocusNode> effectiveParent = parentFocusNode != nullptr
                                       ? parentFocusNode
                                       : m_externalParentFocusNode;
#else
  rcp<FocusNode> effectiveParent = parentFocusNode;
#endif

  if (as<ContainerComponent>() != nullptr)
  {
    buildFocusTreeVisit(focusManager, this, std::move(effectiveParent));
  }
}

void Artboard::buildFocusTree(rcp<FocusNode> parentFocusNode)
{
  if (parentFocusNode == nullptr)
  {
    return;
  }
  auto* manager = parentFocusNode->manager();
  if (manager == nullptr)
  {
    return;
  }
  buildFocusTree(manager, parentFocusNode);
}

void Artboard::cleanupFocusTree()
{
  if (m_activeFocusManager == nullptr)
  {
    return;
  }

  // Remove all FocusData's FocusNodes from the FocusManager
  for (auto* obj : m_Objects)
  {
    if (obj != nullptr && obj->is<FocusData>())
    {
      auto* fd = obj->as<FocusData>();
      auto node = fd->focusNode();
      if (node == nullptr)
      {
        // FocusNode never lazily created — nothing to remove.
        continue;
      }
      // Remove the node when it belongs to this manager. Nodes owned by
      // a DIFFERENT live manager are left untouched.
      if (node->manager() == m_activeFocusManager)
      {
        m_activeFocusManager->removeChild(node);
      }
      else if (node->manager() == nullptr && node->parent() != nullptr)
      {
        // The node's manager was nulled while it is still attached —
        // either by an ancestor removal (removeChild clears m_manager
        // across a removed subtree) or by ~FocusManager, which nulls
        // m_manager tree-wide as it dies. Detach node-side only: in the
        // second case m_activeFocusManager is already dangling (it is
        // an unowned back-pointer, see setActiveFocusManager) and
        // touching it is a use-after-free. Nothing is lost by skipping
        // markFocusableContentDirty here — if the manager is alive, the
        // ancestor removal that nulled m_manager already marked it.
        node->removeFromParent();
      }
    }
  }

  // Propagate cleanup to nested artboards that share our FocusManager
  for (auto* nestedArtboardHost : m_NestedArtboards)
  {
    auto* nestedArtboard = nestedArtboardHost->artboardInstance(0);
    if (nestedArtboard != nullptr &&
        nestedArtboard->focusManager() == m_activeFocusManager)
    {
      nestedArtboard->cleanupFocusTree();
    }
  }

  // Propagate cleanup to ArtboardComponentList items
  for (auto* componentList : m_ComponentLists)
  {
    for (size_t i = 0; i < componentList->artboardCount(); i++)
    {
      auto* nestedArtboard = componentList->artboardInstance(
          static_cast<int>(i));
      if (nestedArtboard != nullptr &&
          nestedArtboard->focusManager() == m_activeFocusManager)
      {
        nestedArtboard->cleanupFocusTree();
      }
    }
  }

  for (auto* componentList : m_ComponentLists)
  {
    componentList->removeListScopeFocusNode();
  }

  // Fall back to our own manager rather than to "no manager"
  m_activeFocusManager = m_ownedFocusManager.get();
}

#ifdef WITH_RIVE_TOOLS
void Artboard::setExternalParentFocusNode(rcp<FocusNode> node)
{
  m_externalParentFocusNode = std::move(node);
}

rcp<FocusNode> Artboard::externalParentFocusNode() const
{
  return m_externalParentFocusNode;
}

void Artboard::collapseSingle(bool value) { Component::collapse(value); }
#endif

// Builds the semantic tree for this artboard. Iterates all objects,
// registers each SemanticData's SemanticNode with the manager, then
// propagates to nested artboards. Each nested boundary hangs under the
// closest SemanticData at or above its host in this artboard, or under this
// artboard's own boundary, so a host's subtree contains everything below it.
//
// For nested artboards (those with a host), a boundary SemanticNode is
// created and inserted as the parent of all semantic nodes within this
// artboard. Boundary nodes are structural-only — skipped during
// flattening — but enable better subtree collapse/uncollapse and
// targeted bounds dirtying when the host transform changes.
void Artboard::buildSemanticTree(
    SemanticManager* semanticManager,
    rcp<SemanticNode> parentSemanticNode)
{
  if (semanticManager == nullptr)
  {
    return;
  }

  // Store reference to the active semantic manager
  setActiveSemanticManager(semanticManager);

  // For nested artboards, create a boundary node that acts as the
  // structural root of this artboard's semantic subtree.
  rcp<SemanticNode> effectiveParent = parentSemanticNode;
  if (host() != nullptr)
  {
    if (m_semanticBoundaryNode == nullptr)
    {
      // Id is assigned by the SemanticManager on addChild() below.
      m_semanticBoundaryNode = rcp<SemanticNode>(new SemanticNode());
      m_semanticBoundaryNode->isBoundaryNode(true);
      m_semanticBoundaryNode->boundaryArtboard(this);
    }
    semanticManager->addChild(parentSemanticNode, m_semanticBoundaryNode);
    // Seed the boundary as dirty so the first drainDiff() resolves its
    // bounds from the artboard rect even when semantics are enabled on
    // an already-settled scene (no subsequent WorldTransform dirt to
    // trigger this via the normal update cycle).
    markSemanticBoundaryTransformDirty();
    effectiveParent = m_semanticBoundaryNode;
  }

  // Register all SemanticData in this artboard
  for (auto* obj : m_Objects)
  {
    if (obj != nullptr && obj->is<SemanticData>())
    {
      auto* sd = obj->as<SemanticData>();
      auto* localParent = sd->findParentSemanticData();

      rcp<SemanticNode> parentNode = localParent != nullptr
                                         ? localParent->semanticNode()
                                         : effectiveParent;

      semanticManager->addChild(parentNode, sd->semanticNode());
    }
  }

  // Propagate semantic registration to nested artboards that might have been
  // created before this artboard's semanticManager was available.
  //
  // We check if the nested artboard's semanticManager is DIFFERENT from ours.
  // If it is, that means it created its own internal semanticManager when it
  // should be sharing the parent's. We rebuild its semantic tree with the
  // correct shared semanticManager.

  // Handle NestedArtboard instances
  for (auto* nestedArtboardHost : m_NestedArtboards)
  {
    auto hostParentNode = SemanticData::findClosestSemanticNode(
        nestedArtboardHost);
    if (hostParentNode == nullptr)
    {
      hostParentNode = effectiveParent;
    }

    auto* nestedArtboard = nestedArtboardHost->artboardInstance(0);
    if (nestedArtboard != nullptr &&
        nestedArtboard->semanticManager() != semanticManager)
    {
      // Clean up old semantic tree if it exists (with wrong
      // semanticManager)
      nestedArtboard->cleanupSemanticTree();
      nestedArtboard->buildSemanticTree(semanticManager, hostParentNode);
    }
  }

  // Handle ArtboardComponentList instances
  for (auto* componentList : m_ComponentLists)
  {
    auto hostParentNode = SemanticData::findClosestSemanticNode(componentList);
    if (hostParentNode == nullptr)
    {
      hostParentNode = effectiveParent;
    }

    for (size_t i = 0; i < componentList->artboardCount(); i++)
    {
      auto* nestedArtboard = componentList->artboardInstance(
          static_cast<int>(i));
      if (nestedArtboard != nullptr &&
          nestedArtboard->semanticManager() != semanticManager)
      {
        // Clean up old semantic tree if it exists (with wrong
        // semanticManager)
        nestedArtboard->cleanupSemanticTree();
        nestedArtboard->buildSemanticTree(semanticManager, hostParentNode);
      }
    }
  }
}

void Artboard::cleanupSemanticTree()
{
  if (m_activeSemanticManager == nullptr)
  {
    return;
  }

  // Propagate cleanup to nested artboards that share our SemanticManager.
  // Done FIRST so their boundary nodes are removed before we remove ours.
  for (auto* nestedArtboardHost : m_NestedArtboards)
  {
    auto* nestedArtboard = nestedArtboardHost->artboardInstance(0);
    if (nestedArtboard != nullptr &&
        nestedArtboard->semanticManager() == m_activeSemanticManager)
    {
      nestedArtboard->cleanupSemanticTree();
    }
  }

  // Propagate cleanup to ArtboardComponentList items
  for (auto* componentList : m_ComponentLists)
  {
    for (size_t i = 0; i < componentList->artboardCount(); i++)
    {
      auto* nestedArtboard = componentList->artboardInstance(
          static_cast<int>(i));
      if (nestedArtboard != nullptr &&
          nestedArtboard->semanticManager() == m_activeSemanticManager)
      {
        nestedArtboard->cleanupSemanticTree();
      }
    }
  }

  // Remove all SemanticData's SemanticNodes from the SemanticManager.
  // Use hasSemanticNode() to avoid lazy-creating a node during cleanup.
  for (auto* obj : m_Objects)
  {
    if (obj != nullptr && obj->is<SemanticData>())
    {
      auto* sd = obj->as<SemanticData>();
      if (!sd->hasSemanticNode())
      {
        continue;
      }
      auto node = sd->semanticNode();
      if (node != nullptr && node->manager() == m_activeSemanticManager)
      {
        m_activeSemanticManager->removeChild(node);
      }
    }
  }

  // Remove the boundary node for this artboard (if any).
  if (m_semanticBoundaryNode != nullptr &&
      m_semanticBoundaryNode->manager() == m_activeSemanticManager)
  {
    m_activeSemanticManager->removeChild(m_semanticBoundaryNode);
  }
  m_semanticBoundaryNode = nullptr;

  // Clear the active semantic manager reference
  m_activeSemanticManager = nullptr;
}

bool Artboard::isHostCollapsed() const
{
  auto* artboardHost = host();
  auto* component = artboardHost != nullptr ? artboardHost->hostComponent()
                                            : nullptr;
  return component != nullptr && component->isCollapsed();
}

// Called when the host collapses or uncollapses. Whether this artboard's
// semantics are shown is read when the tree is flattened (a boundary whose
// host is collapsed hides everything below it, including artboards nested
// further down), so a change only needs a re-flatten. Coming back, bounds
// are refreshed: a collapsed host does not advance this artboard.
void Artboard::syncSemanticBoundary()
{
  if (m_activeSemanticManager == nullptr || m_semanticBoundaryNode == nullptr)
  {
    return;
  }
  // An empty boundary shows nothing either way, so its host can toggle
  // without a re-flatten.
  if (!m_semanticBoundaryNode->children().empty())
  {
    m_activeSemanticManager->markDirty(SemanticDirt::Structure);
  }
  if (!isHostCollapsed())
  {
    markSemanticBoundaryTransformDirty();
  }
}

// Recursively mark all semantic nodes under the boundary as bounds-dirty.
// Called when the host transform changes so bounds are recalculated in
// root artboard space.
void Artboard::markSemanticBoundaryTransformDirty()
{
  if (m_semanticBoundaryNode == nullptr || m_activeSemanticManager == nullptr)
  {
    return;
  }
  m_activeSemanticManager->markBoundaryDirty(m_semanticBoundaryNode->id());
}

std::string Artboard::stateMachineNameAt(size_t index) const
{
  auto sm = this->stateMachine(index);
  return sm ? sm->name() : "";
}

LinearAnimation* Artboard::animation(const std::string& name) const
{
  for (auto animation : animationSource()->ownAnimations())
  {
    if (animation->name() == name)
    {
      return animation;
    }
  }
  return nullptr;
}

LinearAnimation* Artboard::animation(size_t index) const
{
  const Artboard* source = animationSource();
  const std::vector<LinearAnimation*>& animations = source->ownAnimations();
  if (index >= animations.size())
  {
    return nullptr;
  }
  return animations[index];
}

StateMachine* Artboard::stateMachine(const std::string& name) const
{
  for (auto machine : animationSource()->ownStateMachines())
  {
    if (machine->name() == name)
    {
      return machine;
    }
  }
  return nullptr;
}

StateMachine* Artboard::stateMachine(size_t index) const
{
  const Artboard* source = animationSource();
  const std::vector<StateMachine*>& stateMachines = source->ownStateMachines();
  if (index >= stateMachines.size())
  {
    return nullptr;
  }
  return stateMachines[index];
}

int Artboard::defaultStateMachineIndex() const
{
  int index = defaultStateMachineId();
  if ((size_t)index >= animationSource()->ownStateMachines().size())
  {
    index = -1;
  }
  return index;
}

NestedArtboard* Artboard::nestedArtboard(const std::string& name) const
{
  for (auto nested : m_NestedArtboards)
  {
    if (nested->name() == name)
    {
      return nested;
    }
  }
  return nullptr;
}

NestedArtboard* Artboard::nestedArtboardAtPath(const std::string& path) const
{
  // name parameter can be a name or a path to recursively find a nested
  // artboard
  std::string delimiter = "/";
  size_t firstDelim = path.find(delimiter);
  std::string artboardName = firstDelim == std::string::npos
                                 ? path
                                 : path.substr(0, firstDelim);
  std::string restOfPath = firstDelim == std::string::npos
                               ? ""
                               : path.substr(firstDelim + 1, path.size());

  // Find the nested artboard at this level
  if (!artboardName.empty())
  {
    auto nested = nestedArtboard(artboardName);
    if (nested != nullptr)
    {
      if (restOfPath.empty())
      {
        return nested;
      }
      else
      {
        auto artboard = nested->artboardInstance();
        return artboard->nestedArtboardAtPath(restOfPath);
      }
    }
  }
  return nullptr;
}

// std::unique_ptr<ArtboardInstance> Artboard::instance() const
// {
//     std::unique_ptr<ArtboardInstance> artboardClone(new ArtboardInstance);
//     artboardClone->copy(*this);

//     artboardClone->m_Factory = m_Factory;
//     artboardClone->m_FrameOrigin = m_FrameOrigin;
//     artboardClone->m_IsInstance = true;

//     std::vector<Core*>& cloneObjects = artboardClone->m_Objects;
//     cloneObjects.push_back(artboardClone.get());

//     if (!m_Objects.empty())
//     {
//         // Skip first object (artboard).
//         auto itr = m_Objects.begin();
//         while (++itr != m_Objects.end())
//         {
//             auto object = *itr;
//             cloneObjects.push_back(object == nullptr ? nullptr :
//             object->clone());
//         }
//     }

//     for (auto animation : m_Animations)
//     {
//         artboardClone->m_Animations.push_back(animation);
//     }
//     for (auto stateMachine : m_StateMachines)
//     {
//         artboardClone->m_StateMachines.push_back(stateMachine);
//     }

//     if (artboardClone->initialize() != StatusCode::Ok)
//     {
//         artboardClone = nullptr;
//     }

//     assert(artboardClone->isInstance());
//     return artboardClone;
// }

void Artboard::frameOrigin(bool value)
{
  if (value == m_FrameOrigin)
  {
    return;
  }
  m_FrameOrigin = value;
  addDirt(ComponentDirt::Path);
}

StatusCode Artboard::import(ImportStack& importStack)
{
  auto backboardImporter = importStack.latest<BackboardImporter>(
      Backboard::typeKey);
  if (backboardImporter == nullptr)
  {
    return StatusCode::MissingObject;
  }

  StatusCode result = Super::import(importStack);
  if (result == StatusCode::Ok)
  {
    backboardImporter->addArtboard(this);
  }
  else
  {
    backboardImporter->addMissingArtboard();
  }
  return result;
}

void Artboard::buildDataContext(rcp<DataContext> value) {}

void Artboard::internalDataContext(rcp<DataContext> value)
{
  // Set the context before recursing into the artboard hosts; they read it
  // back off this artboard while they bind. The binds are walked after.
  dataBindContext(value);
  syncInstanceValueBinds();
  for (auto artboardHost : m_ArtboardHosts)
  {
    auto hostValue = value->getViewModelInstance(artboardHost->dataBindPath());
    if (hostValue != nullptr && hostValue->is<ViewModelInstance>())
    {
      artboardHost->bindViewModelInstance(hostValue, value);
    }
    else
    {
      artboardHost->internalDataContext(value);
    }
  }
  bindDataBindsFromContext();
  sortDataBinds();
  for (auto consumer : m_hostDataContextConsumers)
  {
    consumer->hostDataContext(value);
  }
  for (auto* scriptedObject : m_ScriptedObjects)
  {
    scriptedObject->dataContext(value);
  }
  initScriptedObjects();
  if (m_scriptedInterpolators != nullptr)
  {
    for (auto& pair : m_scriptedInterpolators->bySource)
    {
      pair.second->dataContext(value);
    }
  }
}

void Artboard::rebind() { internalDataContext(dataBindContext()); }

void Artboard::relinkDataContext()
{
  wakeIfQuietRow();
  if (dataBindContext() == nullptr)
  {
    return;
  }
  for (auto artboardHost : m_ArtboardHosts)
  {
    rcp<ViewModelInstance> value = dataBindContext()->getViewModelInstance(
        artboardHost->dataBindPath());
    if (value == nullptr)
    {
      value = dataBindContext()->mainViewModelInstance();
    }
    artboardHost->relinkDataContext(value);
  }
  for (auto consumer : m_hostDataContextConsumers)
  {
    consumer->relinkHostDataContext();
  }
}

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

void Artboard::unbind()
{
  clearDataContext();
  unbindDataBinds();
  for (auto artboardHost : m_ArtboardHosts)
  {
    artboardHost->unbind();
  }
}

void Artboard::clearDataContext()
{
  if (dataBindContext() != nullptr)
  {
    dataBindContext()->removeDependentContainer(this);
    dataBindContext(nullptr);
    syncInstanceValueBinds();
  }
  for (auto artboardHost : m_ArtboardHosts)
  {
    artboardHost->clearDataContext();
  }
  for (auto consumer : m_hostDataContextConsumers)
  {
    consumer->hostDataContext(nullptr);
  }
  for (auto* scriptedObject : m_ScriptedObjects)
  {
    scriptedObject->resetLuaInit();
  }
  if (m_scriptedInterpolators != nullptr)
  {
    for (auto& pair : m_scriptedInterpolators->bySource)
    {
      if (auto* clone = pair.second->get())
      {
        clone->resetLuaInit();
      }
    }
  }
}

float Artboard::volume() const { return m_volume; }
void Artboard::volume(float value)
{
  m_volume = value;
  for (auto artboardHost : m_ArtboardHosts)
  {
    for (int i = 0; i < artboardHost->artboardCount(); i++)
    {
      auto artboard = artboardHost->artboardInstance(i);
      if (artboard != nullptr)
      {
        artboard->volume(value);
      }
    }
  }
}

void Artboard::hostOpacity(float value)
{
  if (m_hostOpacity == value)
  {
    return;
  }
  m_hostOpacity = value;
  // Re-propagate opacity to our contents. The property itself is untouched,
  // so we dirty render opacity directly rather than through opacity(...).
  addDirt(ComponentDirt::RenderOpacity, true);
}

void Artboard::dataContext(rcp<DataContext> value)
{
  internalDataContext(value);
}

rcp<const File> Artboard::artboardFile() const { return nullptr; }

void Artboard::bindViewModelInstance(rcp<ViewModelInstance> viewModelInstance)
{
  bindViewModelInstance(viewModelInstance, nullptr);
}

void Artboard::bindViewModelInstance(
    rcp<ViewModelInstance> viewModelInstance,
    rcp<DataContext> parent)
{
  if (viewModelInstance == nullptr)
  {
    unbind();
    return;
  }
  setViewModelInstance(std::move(viewModelInstance));
  if (parent != nullptr && dataBindContext() != nullptr)
  {
    dataBindContext()->parent(parent);
  }
  bind();
}

void Artboard::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 artboard and
  // any state machines sharing the context) off the old main and onto the new
  // one.
  dataBindContext()->setMainViewModelInstance(viewModelInstance);
}

void Artboard::bindViewModelInstances(
    std::vector<rcp<ViewModelInstance>> viewModelInstances,
    rcp<DataContext> parent)
{
  if (viewModelInstances.empty())
  {
    unbind();
    return;
  }
  clearDataContext();
  auto dataContext = make_rcp<DataContext>(std::move(viewModelInstances));
  dataContext->addDependentContainer(this);
  dataContext->parent(parent);
  internalDataContext(dataContext);
}

void Artboard::bind()
{
  if (dataBindContext() != nullptr)
  {
    internalDataContext(dataBindContext());
  }
}

rcp<ViewModelInstance> Artboard::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 f = artboardFile();
  if (f == nullptr)
  {
    return nullptr;
  }
  return dataBindContext()->instanceForSlot(f->viewModelId(name));
}

bool Artboard::setGlobalViewModelInstance(
    const std::string& name,
    rcp<ViewModelInstance> viewModelInstance)
{
  // A null instance is allowed: it empties the named slot below.
  auto f = artboardFile();
  if (f == 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 = f->viewModelId(name);
  if (slotKey >= f->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 = f->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;
}

bool Artboard::isAncestor(const Artboard* artboard)
{
  if (artboard != nullptr && m_artboardSource == artboard->artboardSource())
  {
    return true;
  }
  if (parentArtboard() != nullptr)
  {
    return parentArtboard()->isAncestor(artboard);
  }
#ifdef WITH_RIVE_TOOLS
  // Editor artboards don't have a host, so we expose a function that calls
  // the host in dart.
  if (m_isAncestorCallback != nullptr)
  {
    // Dart can't return booleans to cpp, so we use a uint_8 instead
    auto isAncestor = m_isAncestorCallback(
        callbackUserData,
        artboard->artboardId());
    if (isAncestor == 1)
    {
      return true;
    }
  }
#endif
  return false;
}

void Artboard::changed()
{
  ++m_contentRevision;
  // Counted on every call: a change can land after m_didChange is already
  // set and still has to reach state machines holding a pose. Those may sit
  // on a quiet list row, which has to advance to hear it: changed() raises
  // no component dirt (SolidColor uses it for exactly that), so wake the row
  // here as onComponentDirty does.
  m_changeSerial++;
  wakeIfQuietRow();
  if (!m_didChange)
  {
    m_didChange = true;
    if (parentArtboard())
    {
      parentArtboard()->changed();
    }
  }
}

////////// ArtboardInstance

#include "rive/animation/linear_animation_instance.hpp"
#include "rive/animation/state_machine_instance.hpp"

ArtboardInstance::ArtboardInstance() {}

ArtboardInstance::~ArtboardInstance() {}

void ArtboardInstance::file(rcp<const File> file) { m_file = std::move(file); }

rcp<const File> ArtboardInstance::file() const { return m_file; }

rcp<const File> ArtboardInstance::artboardFile() const { return m_file; }

std::unique_ptr<LinearAnimationInstance> ArtboardInstance::animationAt(
    size_t index)
{
  auto la = this->animation(index);
  return la ? std::make_unique<LinearAnimationInstance>(la, this) : nullptr;
}

std::unique_ptr<LinearAnimationInstance> ArtboardInstance::animationNamed(
    const std::string& name)
{
  auto la = this->animation(name);
  return la ? std::make_unique<LinearAnimationInstance>(la, this) : nullptr;
}

std::unique_ptr<StateMachineInstance> ArtboardInstance::stateMachineAt(
    size_t index)
{
  auto sm = this->stateMachine(index);
  if (sm == nullptr)
  {
    return nullptr;
  }
  auto smInstance = std::make_unique<StateMachineInstance>(sm, this);
  if (auto dc = dataContext())
  {
    smInstance->inheritDataContext(dc);
  }
  return smInstance;
}

std::unique_ptr<StateMachineInstance> ArtboardInstance::stateMachineNamed(
    const std::string& name)
{
  auto sm = this->stateMachine(name);
  if (sm == nullptr)
  {
    return nullptr;
  }
  auto smInstance = std::make_unique<StateMachineInstance>(sm, this);
  if (auto dc = dataContext())
  {
    smInstance->inheritDataContext(dc);
  }
  return smInstance;
}

std::unique_ptr<StateMachineInstance> ArtboardInstance::defaultStateMachine()
{
  const int index = this->defaultStateMachineIndex();
  return index >= 0 ? this->stateMachineAt(index) : nullptr;
}

std::unique_ptr<Scene> ArtboardInstance::defaultScene()
{
  std::unique_ptr<Scene> scene = this->defaultStateMachine();
  if (!scene)
  {
    scene = this->stateMachineAt(0);
  }
  if (!scene)
  {
    scene = this->animationAt(0);
  }
  return scene;
}

SMIInput* ArtboardInstance::input(
    const std::string& name,
    const std::string& path)
{
  return getNamedInput<SMIInput>(name, path);
}

template <typename InstType>
InstType* ArtboardInstance::getNamedInput(
    const std::string& name,
    const std::string& path)
{
  if (!path.empty())
  {
    auto nestedArtboard = nestedArtboardAtPath(path);
    if (nestedArtboard != nullptr)
    {
      auto input = nestedArtboard->input(name);
      if (input != nullptr && input->input() != nullptr)
      {
        return static_cast<InstType*>(input->input());
      }
    }
  }
  return nullptr;
}

SMIBool* ArtboardInstance::getBool(
    const std::string& name,
    const std::string& path)
{
  return getNamedInput<SMIBool>(name, path);
}

SMINumber* ArtboardInstance::getNumber(
    const std::string& name,
    const std::string& path)
{
  return getNamedInput<SMINumber>(name, path);
}
SMITrigger* ArtboardInstance::getTrigger(
    const std::string& name,
    const std::string& path)
{
  return getNamedInput<SMITrigger>(name, path);
}

TextValueRun* ArtboardInstance::getTextRun(
    const std::string& name,
    const std::string& path)
{
  if (path.empty())
  {
    return nullptr;
  }

  auto nestedArtboard = nestedArtboardAtPath(path);
  if (nestedArtboard == nullptr)
  {
    return nullptr;
  }

  auto artboardInstance = nestedArtboard->artboardInstance();
  if (artboardInstance == nullptr)
  {
    return nullptr;
  }

  return artboardInstance->find<TextValueRun>(name);
}

#ifdef EXTERNAL_RIVE_AUDIO_ENGINE
rcp<AudioEngine> Artboard::audioEngine() const { return m_audioEngine; }
void Artboard::audioEngine(rcp<AudioEngine> audioEngine)
{
  m_audioEngine = audioEngine;
  for (auto artboardHost : m_ArtboardHosts)
  {
    for (int i = 0; i < artboardHost->artboardCount(); i++)
    {
      auto artboard = artboardHost->artboardInstance(i);
      if (artboard != nullptr)
      {
        artboard->audioEngine(audioEngine);
      }
    }
  }
}
#endif

#ifdef WITH_RIVE_EDITOR
void Artboard::editorPrepareForDestruction()
{
  if (m_ownedFocusManager != nullptr &&
      m_activeFocusManager == m_ownedFocusManager.get())
  {
#ifdef WITH_RIVE_TOOLS
    m_ownedFocusManager->setFocusChangedCallback(nullptr);
    m_ownedFocusManager->setScrollIntoViewCallback(nullptr);
#endif
  }
  cleanupFocusTree();
  cleanupSemanticTree();
  m_scriptedInterpolators.reset();
  unbind();
  clearEditorDataBinds();
  m_ArtboardHosts.clear();
  m_ScriptedObjects.clear();
  m_NestedArtboards.clear();
  m_ComponentLists.clear();
  // These lists borrow arena objects, unlike importer-populated lists.
  auto discardArenaEntries = [](auto& entries) {
    entries.erase(
        std::remove_if(
            entries.begin(),
            entries.end(),
            [](auto* c) {
              return c != nullptr && c->editorArena() != nullptr;
            }),
        entries.end());
  };
  discardArenaEntries(m_Objects);
  if (ArtboardSourceState* state = m_sourceState.get())
  {
    discardArenaEntries(state->animations);
    discardArenaEntries(state->stateMachines);
    discardArenaEntries(state->invalidObjects);
  }
  clearDrawables();
  m_FirstDrawable = nullptr;
  m_clippingShapes.clear();
  m_layerMasks.clear();
  m_DrawTargets.clear();
  m_Joysticks.clear();
  m_advancingComponents.clear();
  m_dirtyLayout.clear();
  m_host = nullptr;
  m_DependencyOrder.clear();
  m_editorResolver = nullptr;
  Component::editorPrepareForDestruction();
}

#endif
