[committed] descendantMatch() proposal

I propose that I add an instance method


    List<Spatial> Spatial.descendantMatch(Class<? extends Spatial> spatialSubclass, String nameRegex>()



with convenience wrappers

    List<Spatial> Spatial.descendantMatch(Class<? extends Spatial>>()
    List<Spatial> Spatial.descendantMatch(String>()


Methods will alway return a list, possibly a 0-element list, so it will always be safe to use loops like:

    for (Spatial s : scene.descendantMatch(".+Bush") {...}



The purpose is to make it easy to perform operations on a subset of scene spatials based on Spatial type and/or based on game-specific naming conventions.  It's a Spatial method instead of a Node method just so it can be used as easily as possible by methods which work on Spatials, e.g. a custom boolean isTerrainColliding(Spatial).

Snippets to justify usefulness:


    for (Spatial s : scene.descendantMatch(CustomBush.class)) s.removeFromParent();
    // Removes all custom Bush Spatials from scene

    for (Spatial s : subScene.descendantMatch(Node.class, "avatar.+")) s.updateRenderState();
    // Updates render state for all Nodes in specified subgraph with name starting with "avatar"

    for (Spatial s : scene.descendantMatch(Bone.class)) {
        Bone skel = (Bone) s;
        if (skel.getControllerCount() < 1) continue;
        ...
        // Do some action to all animation controllers, e.g. stop all active animations

I think it would fit Node better than Spatial, but i can see also why you want to add it on Spatial.

Committed with rev. 4455.



To accommodate the justified scope concern of Core-Dump, I implemented descendantMatches() as advertised in Node, but also implemented boolean Spatial.matches().  This last is a direct and intuitive extension of String.matches().



All properly documented.



N.b. I changed the names from *match() to *matches(), to be consistent with the naming of String.matches().