Make traverse and the rest of the family respect special return values. The most important (in my opinion) would be the ability to ignore the children. For example:
// Somewhere in Three.js code. Could be replaced with an enum-style definition
const IGNORE_CHILDREN = new Symbol('ignore_children');
const HALT_TRAVERSE = new Symbol('halt_traverse');
// I didn't check this for mistakes, but the idea should become clear
traverse( callback ) {
const controlFlowResult = callback( this );
if (controlFlowResult === IGNORE_CHILDREN || controlFlowResult === HALT_TRAVERSE ) {
return controlFlowResult;
}
const children = this.children;
for ( let i = 0, l = children.length; i < l; i ++ ) {
const childFlowResult = children[ i ].traverse( callback );
if (childFlowResult === HALT_TRAVERSE) {
return HALT_TRAVERSE;
}
}
}
Examples how a user might use it:
Find a specific node with some property. Then stop.
//
let oneSpecimenB;
myModel.traverse(node => {
if (node.userData.isB) {
oneSpecimentB = node;
return HALT_TRAVERSE;
}
});
Run code for all nodes except for all the descendants (and the node itself) of the nodes we want to ignore
myModel.traverse(node => {
if (node.userData.ignoreChildren) {
// Optionally run operations here before returning
return IGNORE_CHILDREN;
}
// Do operations for others
});