deepCopyNode function
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;
}