removeChild method
Destroys child and everything under it.
Not a detach: the child goes away, its subtree goes with it, and its
rows are freed. Entity.destroy() is what runs, so the unmount events
fire and the rows are released in the order that method documents.
Child.detach is the operation that unlinks and keeps the entity alive,
and adopt the one that moves it somewhere else.
Throws if child isn't currently a child of this entity - which catches
both "never attached" and "attached to a different parent", and is the
whole reason this is not simply child.destroy(). Destroying somebody
else's child through this parent would report success for work it did
not do.
Implementation
void removeChild(Entity child) {
final childComponent = _requireChild(child);
assert(_sameScene(child));
// `readPending`, for the same reason the splice needs it: a chain edited
// earlier this tick is only visible in the write slot.
if (childComponent.parent.readPending(child) != entity) {
throw ArgumentError.value(
child,
'child',
'is not currently a child of $entity',
);
}
child.destroy();
}