[SOLVED] User data, Incorrect behavior

I’m all trying to create a FPS camera. I was visited by the idea, to save the mouse position setUserData (“saveMousePos”, xz)

package test;

import com.jme3.app.SimpleApplication;
import com.jme3.math.Vector2f;
import com.jme3.scene.CameraNode;
import com.jme3.scene.control.CameraControl.ControlDirection;

public class Main extends SimpleApplication {

	private static Main app;

	public static void main(String[] args) {

		app = new Main();
		app.start();
	}

	private CameraNode camNode;

	@Override
	public void simpleInitApp() {

		flyCam.setEnabled(false);

		camNode = new CameraNode("CameraNode", app.getCamera());
		camNode.setControlDir(ControlDirection.SpatialToCamera);

		Vector2f xz = inputManager.getCursorPosition();
		camNode.setUserData("saveMousePos", xz);

		rootNode.attachChild(camNode);

	}

	@Override
	public void simpleUpdate(float tpf) {

		Vector2f pos = camNode.getUserData("saveMousePos");

		System.out.println(pos);

	}

}

However, as it is supposed, not everything is so simple … This data is updated without my desire. How can this be?

In your simpleInitApp(), the xz is a referrence of the CursorPosition object.

If you only want to save the initial value of mouse position, it should be done in this way.

Vector2f xz = new Vector2f();
xz.set(inputManager.getCursorPosition());
camNode.setUserData("saveMousePos", xz);
1 Like

Edit: oh, somebody was faster.
Edit2: note, that JME widely uses references due to performance reasons, so every time you need a copy, make sure you’ve made it (via .clone() method, if it’s defined, or else).

Thank you. As that is not logical in Java.

That is, the = sign can be considered as ->

Assuming you mention C++, for your particular case, yes, it’s similar. You can reassign xz just like you could do with pointer (and you couldn’t with C++ reference). But generally, I’d recommend to treat Java like it’s your first language you learn, this will save you from constant considerations sort of “how fair this analogy is this time?”
Edit: still, there are differences. My point was that Java reference closer to cpp pointer than to cpp reference. But it is not completely same thing.

I would say that is not logical on whatever other language it is different. When I see ‘=’ it makes more sense to me to think that it I’m assigning the same thing than thinking that I’m assigning a copy of it. So, as already said Torsion to you, don’t try to see analogies with other languages or think that this “is not logical” only because it is done differently on another one. It will give you more headaches than help (Btw, if you think on OOP languages, you’ll find that c++ is the strange here as it wasn’t originally created thinking of OOP).

So, ‘=’ is to assign objects/instances. Every time you give an object as a parameter you are passing that object/instance. If you want otherwise (to create a new object/instance) you have to explicitly say it.

It’s not logical, because a Vector2f type, I requested the cursor data into a variable. But neither as an object.

Example:

Object xz = inputManager.getCursorPosition();
camNode.setUserData("saveMousePos", xz);

In general, JME tries to avoid unnecessary allocations.

Meaning:
-InputManager will keep a Vector2f around to store cursor position in because it queries this every frame and it would be dumb to “new” an object every time.
-it will return to you that raw result when you ask for getCursorPosition() because you might just be looking at the value and throw it away. It would be wasteful to create an object in that case.

Only your code knows the context of what you intend to do with the value you grabbed. Unless JME is calculating the value on the fly for you upon request, it will return its own reference because to do otherwise would be creating garbage in 99% of typical use cases.

As to the design of your approach, I think this is kind of the wrong direction. The screen is global. The data structures you use to track things done to it should be similarly global. It makes no sense to attach this kind of information to a node, really. It can only cause problems or limitations for you later.

Edit: global meaning something like an app state makes more sense for mouse related camera movement… since app states are global to the application. You might have 500 different “camera nodes” in your scene but only one of those will be attached to the screen at any given time and that’s the only place an initial drag position makes any sort of sense.

Yes, I did not need it, I struggled with updating the variable :slight_smile:

In general, you will probably be happier if you start with a proper game design now that separates your “visualization” from your “game objects”.

The player is a game object. The mouse/joystick/keys/whatever will move that game object.

The camera is part of the visualization. It may or may not be located exactly where the player game object’s head is. (For example, it might be a third person camera sometimes… or whatever.)

Proper separation of game objects from their visualization will save you tons of issues later.

1 Like

I have a design based on the skills of Panda3D. However, there are differences, the screen in the Rectangular coordinate system. There are mirror methods of setters for getters. I mean setP, setH and so on. It’s much easier to control the camera.

I did not read the whole post but its an inherent Design of java that you can only Pass by Reference. This is also the same (apart from structures) in C# as you dont want to create garbage (each method call would probably instantiate a Class and drop the old one).

Even in c++ its the same if you Work with pointers. Just always Keep in mind that Everything is a pointer