Node.hasChild(Spatial spat)

Created Classes: 0



Affected Classes: 1



Summary of additions: A method to determine whether a given child is attached to that node or not.



   /**
    *
    * <code>hasChild</code> returns a boolean value which
    * indiciates whether the spatial is present in this
    * node
    *
    * @param spat the spatial to check
    * @return Boolean, whether the spatial is attached or not
    */
   public boolean hasChild(Spatial spat) {
      boolean hasChild = false;
      for (int i = 0; i < children.size(); i++) {
         if (children.get(i) == spat) {
            hasChild = true;
            break;
         }
      }
      
      return hasChild;
   }



Useful for:


      if (KeyBindingManager.getKeyBindingManager()
            .isValidCommand("show stats", false)) {
         if (rootSceneNode.hasChild(fpsText)) {
            rootSceneNode.detachChild(fpsText);
         } else {
            rootSceneNode.attachChild(fpsText);
            fpsText.updateRenderState();
         }
      }

Sounds very usefull. What about implementing it like this?


   public boolean hasChild(Spatial spat) {
return children.contains(spat);

   }

OMG, theres a contains(Object o) in ArrayList 8-O



And ive been using loops for soooo long! :’(



DP

Ive modified the code so that the call propogates down to the children as well. So it returns true if it is there somewhere, not just within its leaf boundries:



   /**
    *
    * <code>hasChild</code> returns a boolean value which
    * indiciates whether the spatial is present in this
    * node
    *
    * @param spat the spatial to check
    * @return Boolean, whether the spatial is attached or not
    */
   public boolean hasChild(Spatial spat) {
      boolean hasChild = children.contains(spat);
      
      if (hasChild == false) {
         for (int i = 0; i < children.size(); i++) {
            Spatial pSpat = (Spatial)children.get(i);
            if (pSpat instanceof Node) {
               Node pNode = (Node)spat;
               if (pNode.hasChild(spat)) {
                  hasChild = true;
                  break;
               }
            }
         }
      }
      
      return hasChild;
   }



DP

Maybe early return can be added ? In case node is found early, there is no need to iterate through rest of children.

sorry, yeah, with the rush of adding it in, i forgot the break; under hasChild = false.



Ive edited my post to reflect the change



DP

Maybe the following is more compact?


   public boolean hasChild(Spatial spat) {

      if (children.contains(spat)) return true;

         for (int i = 0; i < children.size(); i++) {
            Spatial child = (Spatial)children.get(i);
            if (child instanceof Node &&
                 ((Node)child).hasChild(spat)) return true;
         }
      }
     
      return false;
   }

if that increases readability, then sure.



DP

One other small optimization…



You don’t really need to cast the child to a Spatial because you never use it as such… You just check if it’s a Node, then cast it to that.



Basically, you can just use it as an Object until you need it. Probably should also add a comment saying what it is, just for clarity:



public boolean hasChild(Spatial spat) {

      if (children.contains(spat)) return true;

         for (int i = 0; i < children.size(); i++) {
               // 'child' is a Spatial, but we just need to
               //   use it as a Node.
             Object child = children.get(i);
             if (child instanceof Node &&
                 ((Node)child).hasChild(spat)) return true;
         }
      }
     
      return false;
   }



Also.. anybody know if an Iterator is supposed to be faster than always doing the 'get(i)'? Looks like 'children' is an ArrayList, so probably not because you have the overhead of creating the Iterator... so I'm really just making sure that that's what it is. (For some collections (like LinkedList), I'm pretty sure it's faster to use the Iterator.)

Also.. maybe stupid question.. can the 'children' class variable of a Node ever be null?


--K

no, the child cannot be null.



In attachChild(…) that is checked if the to be attached spatial is null or not before attaching.



Sure, the Object thing is cool, never thought of it that way to be honest…



DP