HelloPicking detachChild() issue

Hi friends,



I am working through the beginning tutorials and at the end of the HelloPicking tutorial, it suggests creating an “inventory” so that when you click on a spatial, it is removed from the root node and added to an inventory node which isn’t attached to the root node.



The problem is that I can’t successfully attach the child to the inventory without getting a null pointer exception and I can’t detach the spatial from the root node (in other words, detachChild(…) returns -1). It is supposed to attach and detach the closest spatial that is hit. Here is my code from the relevant section:



[java]if (results.size() > 0){

// The closest collision point is what was truly hit:

CollisionResult closest = results.getClosestCollision();

System.out.println("Closest is: " + closest.getGeometry().getName());



Spatial child = rootNode.getChild(closest.getGeometry().getName());

System.out.println("Attached at: " + inventory.attachChild(child));

System.out.println("Detach at: " + rootNode.detachChild(child));



// Let’s interact - we mark the hit with a red dot.

mark.setLocalTranslation(closest.getContactPoint());

rootNode.attachChild(mark);

} else {

// No hits? Then remove the red mark.

rootNode.detachChild(mark);

}

}[/java]



I have tried coding this about six different ways, but I keep getting the result of -1 when I detach the child from the root node and a null pointer exception when I try to attach the child to the inventory node. Any help would be greatly appreciated!

This should work:

[java]rootNode.detachChild(rootNode.getChild(closest.getGeometry().getName()));

inventory.attachChild(rootNode.getChild(closest.getGeometry().getName()));[/java]

The geometry returned in the collision result might be deep in the scene graph, in that case it won’t simply be a child of the rootNode. You need to find a top-level node for a given geometry that has the rootNode as its parent, and then you will be able to detach/attach it at will.

@Momoko_Fan Thanks, I have the detaching working now, by detaching from shootables rather than from rootNode.



As for the issues I was having with attaching a child to my inventory node… it is always good to initialize variables. The reason that I kept getting a null pointer exception was because I hadn’t initialized the inventory node. By simply changing:

[java]Node inventory;[/java]

to

[java]Node inventory = new Node(“Inventory”);[/java]

I removed my errors and the program runs correctly now. Thanks for the help everyone.



One more clarification though… I originally understood the detachChild() method to work by removing a specified child if it existed anywhere in the scene graph tree. However, it seems that when detaching a child you need to determine the Node that is a direct parent of the node you want to detach and then detach it from that node. Is this correct?

However, it seems that when detaching a child you need to determine the Node that is a direct parent of the node you want to detach and then detach it from that node. Is this correct?

Yeah

mhhhh if you look at the attachChild method in node you’ll notice that if the given child node already has a parent it’s detached from it.



so basically what you need to do is :



inventory.attachChild(child);



nothing more.



The thing going on in this code



Spatial child = rootNode.getChild(closest.getGeometry().getName());

System.out.println("Attached at: " + inventory.attachChild(child));

System.out.println("Detach at: " + rootNode.detachChild(child));



Is when you call rootNode.detachChild(child) the child has already been detached on the inventory.attachChild(child)) call.

thus the null pointer.

nehon said:
Is when you call rootNode.detachChild(child) the child has already been detached on the inventory.attachChild(child)) call.
thus the null pointer.

Actually, my null pointer was caused by my failure to initialize the inventory node that I was attempting to attach the child to. Also, when you try to use detachChild() when the child isn't attached to that node, then the value -1 is returned, but no null pointer exception is thrown.

nehon said:
mhhhh if you look at the attachChild method in node you'll notice that if the given child node already has a parent it's detached from it.

Thanks, that is a very useful thing to note. I am trying to figure out how you would best take advantage of this though. Here is my code from above:
[java]Spatial child = rootNode.getChild(closest.getGeometry().getName());
System.out.println("Attached at: " + inventory.attachChild(child));[/java]
This won't do the trick, because child is a new Spatial object that is not associated with rootNode, just a copy of one of the spatials in the scene graph.

However, something like this might work:
[java]inventory.attachChild(shootables.getChild(closest.getGeometry().getName()));[/java]
According to nehon, this should effectively attach the spatial to inventory while removing it from its current parent shootables. (I didn't actually code this and run it, but I am pretty sure it is right. Correct me if I am off)
Treebranch said:
[java]Spatial child = rootNode.getChild(closest.getGeometry().getName());
System.out.println("Attached at: " + inventory.attachChild(child));[/java]
This won't do the trick, because child is a new Spatial object that is not associated with rootNode, just a copy of one of the spatials in the scene graph.

Absolutely not, java does not copy objects, only primitive types, your "child" object IS the spatial attached to the root node so this code should work.
1 Like

Oops… so probably the easiest way to do it then is:

[java]inventory.attachChild(closest.getGeometry());[/java]

I just tested it using this line and it worked like a dream. Thanks for setting me straight, Nehon!