deepCopyNode function

SceneNode deepCopyNode(
  1. SceneNode node, {
  2. String rename(
    1. String
    )?,
})

A deep copy of node's authored plane — every authored property, bindings and children; never fx, measured geometry or the document pointer. rename maps every name in the subtree (a duplicate needs fresh names — names are field identity, unique per scene); a snapshot passes nothing and keeps them.

Implementation

SceneNode deepCopyNode(SceneNode node, {String Function(String)? rename}) {
  var name = rename == null ? node.name : rename(node.name);
  var copy = switch (node) {
    FrameNode f =>
      FrameNode(name: name)
        // A renamed copy is one drawn ROW, not the rule that drew it —
        // carrying the repeat would make each copy repeat again.
        ..repeated = rename == null ? f.repeated : null
        ..children.addAll([
          for (var c in f.children) deepCopyNode(c, rename: rename),
        ]),
    TextNode() => TextNode('', name: name),
    ShapeNode() => ShapeNode(name: name),
    KindNode k =>
      KindNode(k.kind, name: name)
        ..children.addAll([
          for (var c in k.children) deepCopyNode(c, rename: rename),
        ]),
    ExternalNode e =>
      ExternalNode.read(e.entry, name: name, args: Map.of(e.args))
        ..declared = e.declared
        ..builder = e.builder,
    // The instance is copied too, so the copy draws at once; each copy owns
    // its own, because args are applied by mutating it.
    SceneRefNode r =>
      SceneRefNode.read(r.sceneClassName, name: name, args: Map.of(r.args))
        ..declared = r.declared
        ..tokensArg = r.tokensArg
        ..instance = r.instance == null
            ? null
            : instantiateScene(r.instance!, r.args),
  };
  for (var p in scenePropsOf(node)) {
    p.write(copy, p.read(node));
  }
  copy.bindings.addAll(node.bindings);
  return copy;
}