Hello there!
I’ve made a little something I call MouseViewerPicker which handles toggling between normal “FPS mode” and “cursor mode”. I used jmetest.TutorialGuide.HelloMousePick as a starting point. I ran into something unexpected like I always do. I understand the game states to some extent, but I don’t get why this is happening. (Adding the ZBufferState to the AbsoluteMouse was my idea, obtained by sticking my index finger into the air, and it didn’t work.)
The cursor changes a bit now and then. When my transparent window is being rendered, the cursor turns into a transparent square with the exact same size.
package no.hig.nilspl;
import java.net.URL;
import java.util.logging.Logger;
import com.jme.image.Texture;
import com.jme.input.AbsoluteMouse;
import com.jme.input.FirstPersonHandler;
import com.jme.input.InputHandler;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.input.MouseInput;
import com.jme.intersection.PickResults;
import com.jme.intersection.TrianglePickResults;
import com.jme.math.Ray;
import com.jme.math.Triangle;
import com.jme.math.Vector2f;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.scene.Node;
import com.jme.scene.TriMesh;
import com.jme.scene.state.BlendState;
import com.jme.scene.state.TextureState;
import com.jme.scene.state.ZBufferState;
import com.jme.system.DisplaySystem;
import com.jme.util.TextureManager;
/**
* A class containing functionality for switches between a mouse pointer
* and traditional "FPS-mouselook".
* @author nils
*
*/
public class MouseViewerPicker {
private static final Logger logger = Logger.getLogger(FireController.class.getName());
private AbsoluteMouse am;
// The input handler this viewer/picker is registered on.
private InputHandler input;
// The node containing the geometry/triangles to check for
// mouse picks.
private Node node;
private boolean mouseLookEnabled = false;
private Camera cam;
private static final int toggleButton = KeyInput.KEY_SPACE;
/**
*
* @param input The input handler this picker will be registered on.
* @param node The node containing geometry to check for mouse picks.
* @param cam The camera to register this picker on.
*/
public MouseViewerPicker (InputHandler input, Node node, Camera cam) {
this.input = input;
this.node = node;
this.cam = cam;
DisplaySystem display = DisplaySystem.getDisplaySystem();
display.getRenderer().createBlendState();
am = new AbsoluteMouse("mouse", display.getWidth(), display.getHeight());
TextureState ts = display.getRenderer().createTextureState();
URL loc = VciigeGamePrototype.class.getClassLoader().getResource(
"no/hig/nilspl/cursor1.png" );
Texture t = TextureManager.loadTexture(loc, Texture.MinificationFilter.NearestNeighborNoMipMaps,
Texture.MagnificationFilter.Bilinear);
ts.setTexture(t);
am.setRenderState(ts);
BlendState as = display.getRenderer().createBlendState();
as.setBlendEnabled(true);
as.setSourceFunction(BlendState.SourceFunction.SourceAlpha);
as.setDestinationFunction(BlendState.DestinationFunction.OneMinusSourceAlpha);
as.setTestEnabled(true);
as.setTestFunction(BlendState.TestFunction.GreaterThan);
am.setRenderState(as);
ZBufferState buf = display.getRenderer().createZBufferState();
buf.setEnabled(true);
buf.setFunction(ZBufferState.TestFunction.LessThanOrEqualTo);
am.setRenderState(buf);
am.setLocalTranslation(new Vector3f(display.getWidth() / 2, display.getHeight() / 2, 0));
am.registerWithInputHandler(input);
(( FirstPersonHandler ) input ).getMouseLookHandler().setEnabled( mouseLookEnabled );
KeyBindingManager.getKeyBindingManager().add("toggle", toggleButton);
}
/**
* This method should be invoked once every game loop. It checks
* if the cursor is enabled and if the left mouse button has been
* pressed.
*/
public void update () {
DisplaySystem display = DisplaySystem.getDisplaySystem();
// Get the mouse input device from the jME mouse
// Is button 0 down? Button 0 is left click
if (MouseInput.get().isButtonDown(0) && !mouseLookEnabled) {
Vector2f screenPos = new Vector2f();
// Get the position that the mouse is pointing to
screenPos.set(am.getHotSpotPosition().x, am.getHotSpotPosition().y);
// Get the world location of that X,Y value
Vector3f worldCoords = display.getWorldCoordinates(screenPos, 0);
Vector3f worldCoords2 = display.getWorldCoordinates(screenPos, 1);
// Create a ray starting from the camera, and going in the direction
// of the mouse's location
Ray mouseRay = new Ray(worldCoords, worldCoords2
.subtractLocal(worldCoords).normalizeLocal());
PickResults pr = new TrianglePickResults();
pr.clear();
node.findPick(mouseRay, pr);
for (int i = 0; i < pr.getNumber(); i++) {
Triangle[] triangles = ((TriMesh) pr.getPickData(i).getTargetMesh()).getMeshAsTriangles(null);
System.out.println( "triangles.length " + triangles.length);
for (Triangle tri : triangles) {
Vector3f loc = new Vector3f();
Vector3f temp0 = new Vector3f();
Vector3f temp1 = new Vector3f();
Vector3f temp2 = new Vector3f();
pr.getPickData(i).getTargetMesh().localToWorld(tri.get(0), temp0);
pr.getPickData(i).getTargetMesh().localToWorld(tri.get(1), temp1);
pr.getPickData(i).getTargetMesh().localToWorld(tri.get(2), temp2);
Triangle tempTri = new Triangle(temp0, temp1, temp2);
tempTri.calculateCenter();
if ( mouseRay.intersectWhere(tempTri, loc) ) {
System.out.println( "ray intersects here " + loc.toString() );
System.out.println( "distance " + cam.getLocation().distance(loc) );
}
}
}
}
if (KeyBindingManager.getKeyBindingManager().isValidCommand("toggle", false)) {
mouseLookEnabled = !mouseLookEnabled;
(( FirstPersonHandler ) input ).getMouseLookHandler().setEnabled( mouseLookEnabled );
if (mouseLookEnabled) {
am.registerWithInputHandler(null);
am.removeFromParent();
} else {
am.registerWithInputHandler(input);
node.attachChild(am);
}
}
}
}