Spatial & set/getUserData

Hi everyone, I am having trouble with Spatials, picking and get/setUserData methods. Sorry for my English, I hope you understand me :stuck_out_tongue:

First of all, I load a door model I made using Blender and exporting to mesh. I read the Hellopicking tutorial and I used what I learned here, so when I point to the door, and press E, the door is rotated 90 degrees and it looks like it is opened. If I Prees E again, the door is rotated 90 degrees again. This works well.

Now I want to control if the door is opened or closed. I use setUserData to control this, and here is my problem. This is part of my code:

This is the method I use to create the door:

[java]

private void initMyDoor(){

    Spatial door = assetManager.loadModel("Models/Door/MyDoor.j3o");

    door.setLocalTranslation(0, 0, 20);
    door.setUserData("Mode", false);

    //interactivo is the node I use for pickable objects
    interactivo.attachChild(door);        

}
[/java]

And this is the code I use for collisionResults:

[java]

if (bindeo.equals(“Accion”) && !isPressed) {
CollisionResults results = new CollisionResults();
Ray r = new Ray(cam.getLocation(), cam.getDirection());
interactivo.collideWith(r, results);

        if (results.size() > 0) {
            CollisionResult nearestC = results.getClosestCollision();
            if(nearestC.getDistance() <= 15){
                
                if(nearestC.getGeometry().getUserData("Mode")){                        
                    nearestC.getGeometry().rotate(0, (float)(90*Math.PI)/(180), 0);
                    nearestC.getGeometry().setUserData("Mode", false);                        
                }else{                        
                    nearestC.getGeometry().rotate(0, (float)(-90*Math.PI)/(180), 0);
                    nearestC.getGeometry().setUserData("Mode", true);
                }
            }else{
                System.out.println("Too far");
            }
        }else{
            // No collision.
            System.out.println("No collision");
        }
    }

[/java]

This doesn’t work because I get a NullPointerException because the “variable” Mode I set when load the door isn’t the same I get from the Collision’ed object.

After reading and searching at the forum, I got some answers, but any of them worked. Then I change the code and this worked:

[java]
private void initMyDoor2(){
Node door = (Node)assetManager.loadModel(“Models/Door/MyDoor.j3o”);
door.setLocalTranslation(0, 0, 20);
door.setUserData(“Estado”, false);
interactivo.attachChild(puerta);
}
[/java]

[java]

if (bindeo.equals(“Accion”) && !isPressed) {
CollisionResults results = new CollisionResults();
Ray r = new Ray(cam.getLocation(), cam.getDirection());
interactivo.collideWith(r, results);

        if (results.size() > 0) {
            CollisionResult nearestC = results.getClosestCollision();
            if(nearestC.getDistance() <= 15){
                
                if(nearestC.getGeometry().getParent().getParent().getParent().getParent().getUserData("Mode")){                        
                    nearestC.getGeometry().rotate(0, (float)(90*Math.PI)/(180), 0);
                    nearestC.getGeometry().getParent().getParent().getParent().getParent().setUserData("Mode", false);                        
                }else{                        
                    nearestC.getGeometry().rotate(0, (float)(-90*Math.PI)/(180), 0);
                    nearestC.getGeometry().getParent().getParent().getParent().getParent().setUserData("Mode", true);
                }
            }else{
                System.out.println("Too far");
            }
        }else{
            // No collision.
            System.out.println("No collision");
        }
    }

[/java]

I don’t think this is the best way to make this :S Can anyone help me?

Thank you.

This is covered at least twice a week in the forum. This may help:
https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:scenegraph_for_dummies

…then remember that when you load a model it’s probably a whole hierarchy of nodes and geometries. Picking ONLY happens on Geometries. So if you set something on the root node of a model then you will have to traverse up from the collision Geometry until you find it.

Since I’m avoiding work at the moment I’ll even rewrite a code snippet that I’ve posted a few times before:
[java]
for( Spatial s = nearest.getGeometry(); s.getParent() != null; s = s.getParent() ) {
// Check for your user data, break if you find it.
}
[/java]

I may be missunderstanding you, but why using UserData if you can just check the rotation values themselves?

Thank you for the answers.

@benkibitzer said: I may be missunderstanding you, but why using UserData if you can just check the rotation values themselves?

I use the userData to check if the door is opened or closed. Anyway, I would like to use userData to store data like health (I want player break the door), etc