loadSubtree method

Future<void> loadSubtree(
  1. Node node, {
  2. String? package,
  3. AssetBundle? bundle,
  4. FsceneComponentRegistry? registry,
})

Streams a lazy placeholder node's prefab content under it, resolving the referenced prefab (and its eager references) by source path against this registry.

The registry-aware counterpart of loadSubtree: the streamed content is also registered for hot reload, so an edit to any of the prefab assets re-streams the subtree in place while loaded. References the app holds into the streamed content go stale after such a reload; re-resolve them from node.

Implementation

Future<void> loadSubtree(
  Node node, {
  String? package,
  AssetBundle? bundle,
  FsceneComponentRegistry? registry,
}) async {
  final assetBundle = bundle ?? rootBundle;

  Future<Set<String>> streamIn(Node target) async {
    final seen = <String>{};
    await stream.loadSubtree(
      target,
      registry: registry,
      bundle: assetBundle,
      load: (ref) {
        final key = resolveKey(ref.key, package: package);
        seen.add(key);
        return _readDocument(key, assetBundle);
      },
    );
    return seen;
  }

  final seen = await streamIn(node);
  if (seen.isEmpty) return;

  // Register once per placeholder; later loads just refresh the tracked
  // dependency set (debug only; a no-op registration in release).
  final existing = _streamedDependencies[node];
  if (existing != null) {
    existing
      ..clear()
      ..addAll(seen);
    return;
  }
  final dependencies = {...seen};
  _streamedDependencies[node] = dependencies;
  final weakNode = WeakReference(node);
  HotReloadCoordinator.instance.registerScene(
    node,
    assetKey: seen.first,
    dependencies: dependencies,
    bundle: assetBundle,
    onReload: () async {
      // Re-stream in place only while loaded; an unloaded placeholder
      // streams the fresh content on its next load. Held weakly so a
      // discarded placeholder's registration can be pruned.
      final placeholder = weakNode.target;
      if (placeholder == null || !stream.isSubtreeLoaded(placeholder)) {
        return;
      }
      stream.unloadSubtree(placeholder);
      final refreshed = await streamIn(placeholder);
      dependencies
        ..clear()
        ..addAll(refreshed);
    },
  );
}