|
@@ -1,13 +1,38 @@
|
|
|
package jme3test.input;
|
|
|
|
|
|
import com.jme3.app.SimpleApplication;
|
|
|
-import com.jme3.input.JoyInput;
|
|
|
+import com.jme3.font.BitmapText;
|
|
|
import com.jme3.input.Joystick;
|
|
|
-import com.jme3.input.controls.ActionListener;
|
|
|
-import com.jme3.input.controls.AnalogListener;
|
|
|
+import com.jme3.input.JoystickAxis;
|
|
|
+import com.jme3.input.JoystickButton;
|
|
|
+import com.jme3.input.RawInputListener;
|
|
|
+import com.jme3.input.event.JoyAxisEvent;
|
|
|
+import com.jme3.input.event.JoyButtonEvent;
|
|
|
+import com.jme3.input.event.KeyInputEvent;
|
|
|
+import com.jme3.input.event.MouseButtonEvent;
|
|
|
+import com.jme3.input.event.MouseMotionEvent;
|
|
|
+import com.jme3.input.event.TouchEvent;
|
|
|
+import com.jme3.material.Material;
|
|
|
+import com.jme3.material.RenderState.BlendMode;
|
|
|
+import com.jme3.math.ColorRGBA;
|
|
|
+import com.jme3.math.FastMath;
|
|
|
+import com.jme3.math.Vector2f;
|
|
|
+import com.jme3.scene.Geometry;
|
|
|
+import com.jme3.scene.Node;
|
|
|
+import com.jme3.scene.shape.Quad;
|
|
|
import com.jme3.system.AppSettings;
|
|
|
+import java.io.FileWriter;
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.PrintWriter;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.Map;
|
|
|
|
|
|
-public class TestJoystick extends SimpleApplication implements AnalogListener, ActionListener {
|
|
|
+public class TestJoystick extends SimpleApplication {
|
|
|
+
|
|
|
+ private Joystick viewedJoystick;
|
|
|
+ private GamepadView gamepad;
|
|
|
+ private Node joystickInfo;
|
|
|
+ private float yInfo = 0;
|
|
|
|
|
|
public static void main(String[] args){
|
|
|
TestJoystick app = new TestJoystick();
|
|
@@ -16,35 +41,348 @@ public class TestJoystick extends SimpleApplication implements AnalogListener, A
|
|
|
app.setSettings(settings);
|
|
|
app.start();
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
@Override
|
|
|
public void simpleInitApp() {
|
|
|
Joystick[] joysticks = inputManager.getJoysticks();
|
|
|
if (joysticks == null)
|
|
|
throw new IllegalStateException("Cannot find any joysticks!");
|
|
|
|
|
|
- for (int i = 0; i < joysticks.length; i++){
|
|
|
- Joystick joy = joysticks[i];
|
|
|
- System.out.println(joy.toString());
|
|
|
+ try {
|
|
|
+ PrintWriter out = new PrintWriter( new FileWriter( "joysticks-" + System.currentTimeMillis() + ".txt" ) );
|
|
|
+ dumpJoysticks( joysticks, out );
|
|
|
+ out.close();
|
|
|
+ } catch( IOException e ) {
|
|
|
+ throw new RuntimeException( "Error writing joystick dump", e );
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ int gamepadSize = cam.getHeight() / 2;
|
|
|
+ float scale = gamepadSize / 512.0f;
|
|
|
+ gamepad = new GamepadView();
|
|
|
+ gamepad.setLocalTranslation( cam.getWidth() - gamepadSize - (scale * 20), 0, 0 );
|
|
|
+ gamepad.setLocalScale( scale, scale, scale );
|
|
|
+ guiNode.attachChild(gamepad);
|
|
|
+
|
|
|
+ joystickInfo = new Node( "joystickInfo" );
|
|
|
+ joystickInfo.setLocalTranslation( 0, cam.getHeight(), 0 );
|
|
|
+ guiNode.attachChild( joystickInfo );
|
|
|
+
|
|
|
+ // Add a raw listener because it's eisier to get all joystick events
|
|
|
+ // this way.
|
|
|
+ inputManager.addRawInputListener( new JoystickEventListener() );
|
|
|
+ }
|
|
|
+
|
|
|
+ protected void dumpJoysticks( Joystick[] joysticks, PrintWriter out ) {
|
|
|
+ for( Joystick j : joysticks ) {
|
|
|
+ out.println( "Joystick[" + j.getJoyId() + "]:" + j.getName() );
|
|
|
+ out.println( " buttons:" + j.getButtonCount() );
|
|
|
|
|
|
- joy.assignAxis("Joy Right", "Joy Left", joy.getXAxisIndex());
|
|
|
- joy.assignAxis("Joy Down", "Joy Up", joy.getYAxisIndex());
|
|
|
- joy.assignAxis("DPAD Right", "DPAD Left", JoyInput.AXIS_POV_X);
|
|
|
- joy.assignAxis("DPAD Up", "DPAD Down", JoyInput.AXIS_POV_Y);
|
|
|
- joy.assignButton("Button", 0);
|
|
|
+ for( JoystickAxis axis : j.getAxes() ) {
|
|
|
+ out.println( " " + axis );
|
|
|
+ }
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- inputManager.addListener(this, "DPAD Left", "DPAD Right", "DPAD Down", "DPAD Up");
|
|
|
- inputManager.addListener(this, "Joy Left", "Joy Right", "Joy Down", "Joy Up");
|
|
|
- inputManager.addListener(this, "Button");
|
|
|
+ protected void addInfo( String info, int column ) {
|
|
|
+
|
|
|
+ BitmapText t = new BitmapText(guiFont);
|
|
|
+ t.setText( info );
|
|
|
+ t.setLocalTranslation( column * 200, yInfo, 0 );
|
|
|
+ joystickInfo.attachChild(t);
|
|
|
+ yInfo -= t.getHeight();
|
|
|
}
|
|
|
|
|
|
- public void onAnalog(String name, float isPressed, float tpf) {
|
|
|
- System.out.println(name + " = " + isPressed / tpf);
|
|
|
+ protected void setViewedJoystick( Joystick stick ) {
|
|
|
+ if( this.viewedJoystick == stick )
|
|
|
+ return;
|
|
|
+
|
|
|
+ if( this.viewedJoystick != null ) {
|
|
|
+ joystickInfo.detachAllChildren();
|
|
|
+ }
|
|
|
+
|
|
|
+ this.viewedJoystick = stick;
|
|
|
+
|
|
|
+ if( this.viewedJoystick != null ) {
|
|
|
+ // Draw the hud
|
|
|
+ yInfo = 0;
|
|
|
+
|
|
|
+ addInfo( "Joystick:\"" + stick.getName() + "\" id:" + stick.getJoyId(), 0 );
|
|
|
+
|
|
|
+ yInfo -= 5;
|
|
|
+
|
|
|
+ float ySave = yInfo;
|
|
|
+
|
|
|
+ // Column one for the buttons
|
|
|
+ addInfo( "Buttons:", 0 );
|
|
|
+ for( JoystickButton b : stick.getButtons() ) {
|
|
|
+ addInfo( " '" + b.getName() + "' id:'" + b.getLogicalId() + "'", 0 );
|
|
|
+ }
|
|
|
+ yInfo = ySave;
|
|
|
+
|
|
|
+ // Column two for the axes
|
|
|
+ addInfo( "Axes:", 1 );
|
|
|
+ for( JoystickAxis a : stick.getAxes() ) {
|
|
|
+ addInfo( " '" + a.getName() + "' id:'" + a.getLogicalId() + "' analog:" + a.isAnalog(), 1 );
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Easier to watch for all button and axis events with a raw input listener.
|
|
|
+ */
|
|
|
+ protected class JoystickEventListener implements RawInputListener {
|
|
|
|
|
|
- public void onAction(String name, boolean isPressed, float tpf) {
|
|
|
- System.out.println(name + " = " + isPressed);
|
|
|
+ public void onJoyAxisEvent(JoyAxisEvent evt) {
|
|
|
+ setViewedJoystick( evt.getAxis().getJoystick() );
|
|
|
+ gamepad.setAxisValue( evt.getAxis(), evt.getValue() );
|
|
|
+ }
|
|
|
+
|
|
|
+ public void onJoyButtonEvent(JoyButtonEvent evt) {
|
|
|
+ setViewedJoystick( evt.getButton().getJoystick() );
|
|
|
+ gamepad.setButtonValue( evt.getButton(), evt.isPressed() );
|
|
|
+ }
|
|
|
+
|
|
|
+ public void beginInput() {}
|
|
|
+ public void endInput() {}
|
|
|
+ public void onMouseMotionEvent(MouseMotionEvent evt) {}
|
|
|
+ public void onMouseButtonEvent(MouseButtonEvent evt) {}
|
|
|
+ public void onKeyEvent(KeyInputEvent evt) {}
|
|
|
+ public void onTouchEvent(TouchEvent evt) {}
|
|
|
}
|
|
|
|
|
|
+ protected class GamepadView extends Node {
|
|
|
+
|
|
|
+ float xAxis = 0;
|
|
|
+ float yAxis = 0;
|
|
|
+ float zAxis = 0;
|
|
|
+ float zRotation = 0;
|
|
|
+
|
|
|
+ float lastPovX = 0;
|
|
|
+ float lastPovY = 0;
|
|
|
+
|
|
|
+ Geometry leftStick;
|
|
|
+ Geometry rightStick;
|
|
|
+
|
|
|
+ Map<String, ButtonView> buttons = new HashMap<String, ButtonView>();
|
|
|
+
|
|
|
+ public GamepadView() {
|
|
|
+ super( "gamepad" );
|
|
|
+
|
|
|
+ // Sizes naturally for the texture size. All positions will
|
|
|
+ // be in that space because it's easier.
|
|
|
+ int size = 512;
|
|
|
+
|
|
|
+ Material m = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
|
|
|
+ m.setTexture( "ColorMap", assetManager.loadTexture( "Interface/Joystick/gamepad-buttons.png" ) );
|
|
|
+ m.getAdditionalRenderState().setBlendMode( BlendMode.Alpha );
|
|
|
+ Geometry buttonPanel = new Geometry( "buttons", new Quad(size, size) );
|
|
|
+ buttonPanel.setLocalTranslation( 0, 0, -1 );
|
|
|
+ buttonPanel.setMaterial(m);
|
|
|
+ attachChild(buttonPanel);
|
|
|
+
|
|
|
+ m = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
|
|
|
+ m.setTexture( "ColorMap", assetManager.loadTexture( "Interface/Joystick/gamepad-frame.png" ) );
|
|
|
+ m.getAdditionalRenderState().setBlendMode( BlendMode.Alpha );
|
|
|
+ Geometry frame = new Geometry( "frame", new Quad(size, size) );
|
|
|
+ frame.setMaterial(m);
|
|
|
+ attachChild(frame);
|
|
|
+
|
|
|
+ m = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
|
|
|
+ m.setTexture( "ColorMap", assetManager.loadTexture( "Interface/Joystick/gamepad-stick.png" ) );
|
|
|
+ m.getAdditionalRenderState().setBlendMode( BlendMode.Alpha );
|
|
|
+ leftStick = new Geometry( "leftStick", new Quad(64, 64) );
|
|
|
+ leftStick.setMaterial(m);
|
|
|
+ attachChild(leftStick);
|
|
|
+ rightStick = new Geometry( "leftStick", new Quad(64, 64) );
|
|
|
+ rightStick.setMaterial(m);
|
|
|
+ attachChild(rightStick);
|
|
|
+
|
|
|
+ // A "standard" mapping... fits a majority of my game pads
|
|
|
+ addButton( "Button 0", 371, 512 - 176, 42, 42 );
|
|
|
+ addButton( "Button 1", 407, 512 - 212, 42, 42 );
|
|
|
+ addButton( "Button 2", 371, 512 - 248, 42, 42 );
|
|
|
+ addButton( "Button 3", 334, 512 - 212, 42, 42 );
|
|
|
+
|
|
|
+ // Front buttons Some of these have the top ones and the bottoms ones flipped.
|
|
|
+ addButton( "Button 4", 67, 512 - 111, 95, 21 );
|
|
|
+ addButton( "Button 5", 348, 512 - 111, 95, 21 );
|
|
|
+ addButton( "Button 6", 67, 512 - 89, 95, 21 );
|
|
|
+ addButton( "Button 7", 348, 512 - 89, 95, 21 );
|
|
|
+
|
|
|
+ // Select and start buttons
|
|
|
+ addButton( "Button 8", 206, 512 - 198, 48, 30 );
|
|
|
+ addButton( "Button 9", 262, 512 - 198, 48, 30 );
|
|
|
+
|
|
|
+ // Joystick push buttons
|
|
|
+ addButton( "Button 10", 147, 512 - 300, 75, 70 );
|
|
|
+ addButton( "Button 11", 285, 512 - 300, 75, 70 );
|
|
|
+
|
|
|
+ // Fake button highlights for the POV axes
|
|
|
+ //
|
|
|
+ // +Y
|
|
|
+ // -X +X
|
|
|
+ // -Y
|
|
|
+ //
|
|
|
+ addButton( "POV +Y", 96, 512 - 174, 40, 38 );
|
|
|
+ addButton( "POV +X", 128, 512 - 208, 40, 38 );
|
|
|
+ addButton( "POV -Y", 96, 512 - 239, 40, 38 );
|
|
|
+ addButton( "POV -X", 65, 512 - 208, 40, 38 );
|
|
|
+
|
|
|
+ resetPositions();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void addButton( String name, float x, float y, float width, float height ) {
|
|
|
+ ButtonView b = new ButtonView(name, x, y, width, height);
|
|
|
+ attachChild(b);
|
|
|
+ buttons.put(name, b);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setAxisValue( JoystickAxis axis, float value ) {
|
|
|
+ System.out.println( "Axis:" + axis.getName() + "=" + value );
|
|
|
+ if( axis == axis.getJoystick().getXAxis() ) {
|
|
|
+ setXAxis(value);
|
|
|
+ } else if( axis == axis.getJoystick().getYAxis() ) {
|
|
|
+ setYAxis(-value);
|
|
|
+ } else if( axis == axis.getJoystick().getAxis("Z Axis") ) {
|
|
|
+ // Note: in the above condition, we could check the axis name but
|
|
|
+ // I have at least one joystick that reports 2 "Z Axis" axes.
|
|
|
+ // In this particular case, the first one is the right one so
|
|
|
+ // a name based lookup will find the proper one. It's a problem
|
|
|
+ // because the erroneous axis sends a constant stream of values.
|
|
|
+ setZAxis(value);
|
|
|
+ } else if( axis == axis.getJoystick().getAxis("Z Rotation") ) {
|
|
|
+ setZRotation(-value);
|
|
|
+ } else if( axis == axis.getJoystick().getPovXAxis() ) {
|
|
|
+ if( lastPovX < 0 ) {
|
|
|
+ setButtonValue( "POV -X", false );
|
|
|
+ } else if( lastPovX > 0 ) {
|
|
|
+ setButtonValue( "POV +X", false );
|
|
|
+ }
|
|
|
+ if( value < 0 ) {
|
|
|
+ setButtonValue( "POV -X", true );
|
|
|
+ } else if( value > 0 ) {
|
|
|
+ setButtonValue( "POV +X", true );
|
|
|
+ }
|
|
|
+ lastPovX = value;
|
|
|
+ } else if( axis == axis.getJoystick().getPovYAxis() ) {
|
|
|
+ if( lastPovY < 0 ) {
|
|
|
+ setButtonValue( "POV -Y", false );
|
|
|
+ } else if( lastPovY > 0 ) {
|
|
|
+ setButtonValue( "POV +Y", false );
|
|
|
+ }
|
|
|
+ if( value < 0 ) {
|
|
|
+ setButtonValue( "POV -Y", true );
|
|
|
+ } else if( value > 0 ) {
|
|
|
+ setButtonValue( "POV +Y", true );
|
|
|
+ }
|
|
|
+ lastPovY = value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setButtonValue( JoystickButton button, boolean isPressed ) {
|
|
|
+ System.out.println( "Button:" + button.getName() + "=" + (isPressed ? "Down" : "Up") );
|
|
|
+ setButtonValue( button.getName(), isPressed );
|
|
|
+ }
|
|
|
+
|
|
|
+ protected void setButtonValue( String name, boolean isPressed ) {
|
|
|
+ ButtonView view = buttons.get(name);
|
|
|
+ if( view != null ) {
|
|
|
+ if( isPressed ) {
|
|
|
+ view.down();
|
|
|
+ } else {
|
|
|
+ view.up();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setXAxis( float f ) {
|
|
|
+ xAxis = f;
|
|
|
+ resetPositions();
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setYAxis( float f ) {
|
|
|
+ yAxis = f;
|
|
|
+ resetPositions();
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setZAxis( float f ) {
|
|
|
+ zAxis = f;
|
|
|
+ resetPositions();
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setZRotation( float f ) {
|
|
|
+ zRotation = f;
|
|
|
+ resetPositions();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void resetPositions() {
|
|
|
+
|
|
|
+ float xBase = 155;
|
|
|
+ float yBase = 212;
|
|
|
+
|
|
|
+ Vector2f dir = new Vector2f(xAxis, yAxis);
|
|
|
+ float length = Math.min(1, dir.length());
|
|
|
+ dir.normalizeLocal();
|
|
|
+
|
|
|
+ float angle = dir.getAngle();
|
|
|
+ float x = FastMath.cos(angle) * length * 10;
|
|
|
+ float y = FastMath.sin(angle) * length * 10;
|
|
|
+ leftStick.setLocalTranslation( xBase + x, yBase + y, 0 );
|
|
|
+
|
|
|
+
|
|
|
+ xBase = 291;
|
|
|
+ dir = new Vector2f(zAxis, zRotation);
|
|
|
+ length = Math.min(1, dir.length());
|
|
|
+ dir.normalizeLocal();
|
|
|
+
|
|
|
+ angle = dir.getAngle();
|
|
|
+ x = FastMath.cos(angle) * length * 10;
|
|
|
+ y = FastMath.sin(angle) * length * 10;
|
|
|
+ rightStick.setLocalTranslation( xBase + x, yBase + y, 0 );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ protected class ButtonView extends Node {
|
|
|
+
|
|
|
+ private int state = 0;
|
|
|
+ private Material material;
|
|
|
+ private ColorRGBA hilite = new ColorRGBA( 0.0f, 0.75f, 0.75f, 0.5f );
|
|
|
+
|
|
|
+ public ButtonView( String name, float x, float y, float width, float height ) {
|
|
|
+ super(name);
|
|
|
+ setLocalTranslation( x, y, -0.5f );
|
|
|
+
|
|
|
+ material = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
|
|
|
+ material.setColor( "Color", hilite );
|
|
|
+ material.getAdditionalRenderState().setBlendMode( BlendMode.Alpha );
|
|
|
+
|
|
|
+ Geometry g = new Geometry( "highlight", new Quad(width, height) );
|
|
|
+ g.setMaterial(material);
|
|
|
+ attachChild(g);
|
|
|
+
|
|
|
+ resetState();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void resetState() {
|
|
|
+ if( state <= 0 ) {
|
|
|
+ setCullHint( CullHint.Always );
|
|
|
+ } else {
|
|
|
+ setCullHint( CullHint.Dynamic );
|
|
|
+ }
|
|
|
+
|
|
|
+ System.out.println( getName() + " state:" + state );
|
|
|
+ }
|
|
|
+
|
|
|
+ public void down() {
|
|
|
+ state++;
|
|
|
+ resetState();
|
|
|
+ }
|
|
|
+
|
|
|
+ public void up() {
|
|
|
+ state--;
|
|
|
+ resetState();
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|