Adds some documentation to the joystick state.

This commit is contained in:
Markil3
2020-12-13 18:34:42 -07:00
parent 058833ca5b
commit a8d76ed11d
3 changed files with 153 additions and 49 deletions

View File

@@ -58,7 +58,7 @@ dependencies {
implementation "${jme3.g}:jme3-core:${jme3.version}" implementation "${jme3.g}:jme3-core:${jme3.version}"
implementation "${jme3.g}:jme3-desktop:${jme3.version}" implementation "${jme3.g}:jme3-desktop:${jme3.version}"
implementation 'org.jmonkeyengine:jme3-testdata:3.3.2-stable' implementation "${jme3.g}:jme3-testdata:${jme3.version}"
implementation "${jme3.g}:jme3-lwjgl3:${jme3.version}" implementation "${jme3.g}:jme3-lwjgl3:${jme3.version}"
} }

View File

@@ -63,6 +63,15 @@ import static markil3.controller.Main.SELECT;
import static markil3.controller.Main.START; import static markil3.controller.Main.START;
/** /**
* Adding this app state will display a GUI screen showing the controllers
* connected and information on what buttons are pressed. It is primarily
* useful for debugging controllers.
* <p>Note that this class relies on three textures not found in the default
* JME core: "Interface/Joystick/gamepad-buttons.png",
* "Interface/Joystick/gamepad-frame.png," and
* "Interface/Joystick/gamepad-stick.png." These textures can be obtained
* from the org.jmonkeyengine:jme3-testdata library.</p>
*
* @author Markil 3 * @author Markil 3
* @author Normen Hansen * @author Normen Hansen
* @author Kirill Vainer * @author Kirill Vainer
@@ -76,6 +85,10 @@ public class JoystickPreviewScreen extends BaseAppState
private static final org.slf4j.Logger logger = private static final org.slf4j.Logger logger =
org.slf4j.LoggerFactory.getLogger(JoystickPreviewScreen.class); org.slf4j.LoggerFactory.getLogger(JoystickPreviewScreen.class);
/**
* This node serves as the center of logic for each gamepad connected to
* the computer.
*/
static class GamepadView extends Node static class GamepadView extends Node
{ {
@@ -179,9 +192,8 @@ public class JoystickPreviewScreen extends BaseAppState
private void addButton(String name, float x, float y, float width, private void addButton(String name, float x, float y, float width,
float height) float height)
{ {
ButtonView b = ButtonView b = new ButtonView(this.assetManager, name, x, y, width,
new ButtonView(this.prevScreen, this.assetManager, name, x, height);
y, width, height);
attachChild(b); attachChild(b);
buttons.put(name, b); buttons.put(name, b);
} }
@@ -431,41 +443,39 @@ public class JoystickPreviewScreen extends BaseAppState
} }
} }
/**
* Applied to the buttons to highlight which ones are being pressed.
*/
static class ButtonView extends Node static class ButtonView extends Node
{ {
private static final ColorRGBA hilite =
private final JoystickPreviewScreen prevScreen; new ColorRGBA(0.0f, 0.75f, 0.75f, 0.5f);
private int state = 0; private int state = 0;
private Material material; private Material material;
private ColorRGBA hilite = new ColorRGBA(0.0f, 0.75f, 0.75f, 0.5f);
ButtonView(AssetManager assetManager, String name, float x, float y, ButtonView(AssetManager assetManager, String name, float x, float y,
float width, float height) float width, float height)
{
this(null, assetManager, name, x, y, width, height);
}
ButtonView(JoystickPreviewScreen prevScreen, AssetManager assetManager,
String name, float x, float y, float width, float height)
{ {
super("Button:" + name); super("Button:" + name);
setLocalTranslation(x, y, -0.5f); setLocalTranslation(x, y, -0.5f);
this.prevScreen = prevScreen; this.material = new Material(assetManager,
material = new Material(assetManager,
"Common/MatDefs/Misc/Unshaded.j3md"); "Common/MatDefs/Misc/Unshaded.j3md");
material.setColor("Color", hilite); this.material.setColor("Color", hilite);
material.getAdditionalRenderState().setBlendMode(BlendMode.Alpha); this.material.getAdditionalRenderState()
.setBlendMode(BlendMode.Alpha);
Geometry g = new Geometry("highlight", new Quad(width, height)); Geometry g = new Geometry("highlight", new Quad(width, height));
g.setMaterial(material); g.setMaterial(this.material);
g.setUserData("view", this); g.setUserData("view", this);
attachChild(g); attachChild(g);
resetState(); resetState();
} }
/**
* Updates the visual of whether the button is pressed or not.
*/
private void resetState() private void resetState()
{ {
if (state <= 0) if (state <= 0)
@@ -480,17 +490,30 @@ public class JoystickPreviewScreen extends BaseAppState
// System.out.println(getName() + " state:" + state); // System.out.println(getName() + " state:" + state);
} }
/**
* Checks to see if the visual displays if the button is pressed.
* @return True if the visual displays that the button is pressed,
* false otherwise.
*/
public boolean isDown() public boolean isDown()
{ {
return this.state > 0; return this.state > 0;
} }
/**
* Updates the button to display that it is pressed.
* @see #up()
*/
public void down() public void down()
{ {
this.state++; this.state++;
this.resetState(); this.resetState();
} }
/**
* Updates the button to display that it is not pressed.
* @see #down()
*/
public void up() public void up()
{ {
this.state--; this.state--;
@@ -501,6 +524,7 @@ public class JoystickPreviewScreen extends BaseAppState
final ColorRGBA BUTTON_COLOR = new ColorRGBA(0F, 0.1F, 0F, 1F); final ColorRGBA BUTTON_COLOR = new ColorRGBA(0F, 0.1F, 0F, 1F);
final ColorRGBA HIGHLIGHTED_BUTTON_COLOR = final ColorRGBA HIGHLIGHTED_BUTTON_COLOR =
new ColorRGBA(0F, 0.75F, 0.25F, 1F); new ColorRGBA(0F, 0.75F, 0.25F, 1F);
protected Node gui; protected Node gui;
private BitmapFont guiFont; private BitmapFont guiFont;
@@ -515,21 +539,10 @@ public class JoystickPreviewScreen extends BaseAppState
private Map<JoystickAxis, Float> lastValues = new HashMap<>(); private Map<JoystickAxis, Float> lastValues = new HashMap<>();
/**
*
*/
public JoystickPreviewScreen()
{
this.gui = new Node();
// this.gui.setLayout(
// new CenterAlignLayout(HAlignment.Center, VAlignment.Center,
// FillMode.None, FillMode.None));
}
@Override @Override
public void initialize(Application app) public void initialize(Application app)
{ {
this.gui = new Node();
this.guiFont = this.guiFont =
app.getAssetManager().loadFont("Interface/Fonts/Default.fnt"); app.getAssetManager().loadFont("Interface/Fonts/Default.fnt");
this.refLabel = this.guiFont.createLabel("Axis X/Axis Y"); this.refLabel = this.guiFont.createLabel("Axis X/Axis Y");
@@ -537,8 +550,6 @@ public class JoystickPreviewScreen extends BaseAppState
this.updateGamepad(); this.updateGamepad();
// this.initNavState();
// this.setFocus(this.playButton);
this.setEnabled(true); this.setEnabled(true);
((SimpleApplication) this.getApplication()).getGuiNode() ((SimpleApplication) this.getApplication()).getGuiNode()
@@ -550,12 +561,18 @@ public class JoystickPreviewScreen extends BaseAppState
this.setEnabled(true); this.setEnabled(true);
} }
/**
* Adds all the GUI elements to the screen.
*/
private void updateGamepad() private void updateGamepad()
{ {
int mostButtons = 0; int mostButtons = 0;
Joystick joy; Joystick joy;
int l = this.getApplication().getInputManager().getJoysticks().length; int l = this.getApplication().getInputManager().getJoysticks().length;
/*
* Removes any existing gamepads.
*/
if (this.gamepadCont != null) if (this.gamepadCont != null)
{ {
for (Node cont : this.gamepadCont) for (Node cont : this.gamepadCont)
@@ -566,6 +583,11 @@ public class JoystickPreviewScreen extends BaseAppState
} }
} }
} }
/*
* Removes the labels, just in case something changed and the
* previous ones are incompatible.
*/
if (this.labels != null) if (this.labels != null)
{ {
for (BitmapText[] cont : this.labels) for (BitmapText[] cont : this.labels)
@@ -579,6 +601,9 @@ public class JoystickPreviewScreen extends BaseAppState
} }
} }
} }
/*
* Initialize the array of labels and gamepads.
*/
for (int i = 0; i < l; i++) for (int i = 0; i < l; i++)
{ {
joy = this.getApplication().getInputManager().getJoysticks()[i]; joy = this.getApplication().getInputManager().getJoysticks()[i];
@@ -591,6 +616,7 @@ public class JoystickPreviewScreen extends BaseAppState
this.gamepadView = this.gamepadView =
new GamepadView[this.getApplication().getInputManager() new GamepadView[this.getApplication().getInputManager()
.getJoysticks().length]; .getJoysticks().length];
for (int i = 0; i < l; i++) for (int i = 0; i < l; i++)
{ {
this.gamepadCont[i] = new Node(); this.gamepadCont[i] = new Node();
@@ -603,15 +629,24 @@ public class JoystickPreviewScreen extends BaseAppState
this.gui.attachChild(this.gamepadCont[i]); this.gui.attachChild(this.gamepadCont[i]);
} }
} }
this.addButtons(); this.addButtons();
} }
/**
* Adds the tab buttons used to switch between which gamepad is currently
* being viewed.
*/
private void addButtons() private void addButtons()
{ {
Node button; Node button;
BitmapText buttonText; BitmapText buttonText;
Geometry buttonBackground; Geometry buttonBackground;
int i, l; int i, l;
/*
* Clears out any old tab buttons.
*/
if (this.gamepadHeaders != null) if (this.gamepadHeaders != null)
{ {
for (i = 0, l = this.gamepadHeaders.length; i < l; i++) for (i = 0, l = this.gamepadHeaders.length; i < l; i++)
@@ -619,6 +654,7 @@ public class JoystickPreviewScreen extends BaseAppState
this.gamepadHeaders[i].removeFromParent(); this.gamepadHeaders[i].removeFromParent();
} }
} }
l = this.gamepadCont.length; l = this.gamepadCont.length;
this.gamepadHeaders = new Node[l]; this.gamepadHeaders = new Node[l];
for (i = 0, l = this.gamepadCont.length; i < l; i++) for (i = 0, l = this.gamepadCont.length; i < l; i++)
@@ -653,6 +689,11 @@ public class JoystickPreviewScreen extends BaseAppState
} }
} }
/**
* Obtain the size of the screen based on the game camera.
* @return The screen size in a two-dimensional float vector. Note that
* the numbers will always be integers.
*/
private Vector2f getScreenSize() private Vector2f getScreenSize()
{ {
return new Vector2f(this.getApplication().getCamera().getWidth(), return new Vector2f(this.getApplication().getCamera().getWidth(),
@@ -662,7 +703,7 @@ public class JoystickPreviewScreen extends BaseAppState
@Override @Override
protected void cleanup(Application app) protected void cleanup(Application app)
{ {
this.gui.removeFromParent();
} }
@Override @Override
@@ -681,8 +722,16 @@ public class JoystickPreviewScreen extends BaseAppState
.removeJoystickConnectionListener(this); .removeJoystickConnectionListener(this);
} }
/**
* Updates the values of the gamepad labels as buttons and axis are
* manipulated.
* @param joy - The gamepad to update.
*/
private void setLabels(Joystick joy) private void setLabels(Joystick joy)
{ {
/*
* Removes the old labels.
*/
if (labels != null) if (labels != null)
{ {
for (BitmapText label : this.labels[joy.getJoyId()]) for (BitmapText label : this.labels[joy.getJoyId()])
@@ -697,31 +746,50 @@ public class JoystickPreviewScreen extends BaseAppState
// joy.getButtonCount()) * 2 + 1]; // joy.getButtonCount()) * 2 + 1];
if (this.labels != null) if (this.labels != null)
{ {
/*
* The name of the gamepad.
*/
this.labels[joy.getJoyId()][0] = this.labels[joy.getJoyId()][0] =
this.guiFont.createLabel(joy.getName()); this.guiFont.createLabel(joy.getName());
this.labels[joy.getJoyId()][0].setLocalTranslation(20, -25, 0); this.labels[joy.getJoyId()][0].setLocalTranslation(20, -25, 0);
this.gamepadCont[joy.getJoyId()] this.gamepadCont[joy.getJoyId()]
.attachChild(this.labels[joy.getJoyId()][0]); .attachChild(this.labels[joy.getJoyId()][0]);
/*
* The key for the axis. Each of the axis rows will display the
* index of the axis, its given name, its logical ID after
* joystick remapping has occurred, and the axis index again.
*/
this.labels[joy.getJoyId()][1] = this.guiFont this.labels[joy.getJoyId()][1] = this.guiFont
.createLabel("Axis Index: Axis Name (logical ID, axis ID)"); .createLabel("Axis Index: Axis Name (logical ID, axis ID)");
this.labels[joy.getJoyId()][1].setLocalTranslation(20, -50, 0); this.labels[joy.getJoyId()][1].setLocalTranslation(20, -50, 0);
this.gamepadCont[joy.getJoyId()] this.gamepadCont[joy.getJoyId()]
.attachChild(this.labels[joy.getJoyId()][1]); .attachChild(this.labels[joy.getJoyId()][1]);
/*
* Loop through all the axes.
*/
for (int i = 0; i < joy.getAxisCount(); i++) for (int i = 0; i < joy.getAxisCount(); i++)
{ {
JoystickAxis axis = joy.getAxes().get(i); JoystickAxis axis = joy.getAxes().get(i);
try try
{ {
/*
* The name and information of the axis.
*/
BitmapText label = this.guiFont.createLabel( BitmapText label = this.guiFont.createLabel(
(i) + ": " + axis.getName() + " (" + (i) + ": " + axis.getName() + " (" +
axis.getLogicalId() + ", " + axis.getLogicalId() + ", " +
axis.getAxisId() + "): "); axis.getAxisId() + "): ");
label.setLocalTranslation(20, -25 * (i + 3), 0); label.setLocalTranslation(20, -25 * (i + 3), 0);
this.labels[joy.getJoyId()][i * 2 + 1] = label; this.labels[joy.getJoyId()][i * 2 + 1] = label;
/*
* The current value of the axis.
*/
BitmapText label2 = this.guiFont.createLabel("-1.0"); BitmapText label2 = this.guiFont.createLabel("-1.0");
label2.setLocalTranslation(label.getLocalTranslation() label2.setLocalTranslation(label.getLocalTranslation()
.add(label.getLineWidth(), 0, 0)); .add(label.getLineWidth(), 0, 0));
this.labels[joy.getJoyId()][i * 2 + 2] = label2; this.labels[joy.getJoyId()][i * 2 + 2] = label2;
this.gamepadCont[joy.getJoyId()].attachChild(label); this.gamepadCont[joy.getJoyId()].attachChild(label);
this.gamepadCont[joy.getJoyId()].attachChild(label2); this.gamepadCont[joy.getJoyId()].attachChild(label2);
} }
@@ -738,7 +806,14 @@ public class JoystickPreviewScreen extends BaseAppState
// axis.getAxisId() + ")", aie); // axis.getAxisId() + ")", aie);
} }
} }
int firstButtonIndex = 2 * joy.getAxisCount() + 1; int firstButtonIndex = 2 * joy.getAxisCount() + 1;
/*
* The key for the buttons. Each of the button rows will display the
* index of the button offset by the number of axes we had, its
* given name, its logical ID after
* joystick remapping has occurred, and the actual button index.
*/
this.labels[joy.getJoyId()][firstButtonIndex] = this.guiFont this.labels[joy.getJoyId()][firstButtonIndex] = this.guiFont
.createLabel( .createLabel(
"Button Index: Button Name (logical ID, button " + "Button Index: Button Name (logical ID, button " +
@@ -749,25 +824,40 @@ public class JoystickPreviewScreen extends BaseAppState
.getLineWidth(), -50, 0); .getLineWidth(), -50, 0);
this.gamepadCont[joy.getJoyId()] this.gamepadCont[joy.getJoyId()]
.attachChild(this.labels[joy.getJoyId()][firstButtonIndex]); .attachChild(this.labels[joy.getJoyId()][firstButtonIndex]);
/*
* Loop through all the buttons.
*/
for (int i = 0; i < joy.getButtonCount(); i++) for (int i = 0; i < joy.getButtonCount(); i++)
{ {
JoystickButton button = joy.getButtons().get(i); JoystickButton button = joy.getButtons().get(i);
try try
{ {
/*
* The current value of the button. We create this first
since the name will be placed in relation to this, due
to it being right-justified.
*/
BitmapText label2 = this.guiFont.createLabel("false"); BitmapText label2 = this.guiFont.createLabel("false");
label2.setLocalTranslation( label2.setLocalTranslation(
this.getScreenSize().x - label2.getLineWidth(), this.getScreenSize().x - label2.getLineWidth(),
-25 * (i + 3), 0); -25 * (i + 3), 0);
/*
* The name and information for the button.
*/
BitmapText label = this.guiFont.createLabel( BitmapText label = this.guiFont.createLabel(
(i + joy.getAxisCount()) + ": " + button.getName() + (i + joy.getAxisCount()) + ": " + button.getName() +
" (" + button.getLogicalId() + ", " + " (" + button.getLogicalId() + ", " +
button.getButtonId() + "): "); button.getButtonId() + "): ");
label.setLocalTranslation(label2.getLocalTranslation() label.setLocalTranslation(label2.getLocalTranslation()
.add(-label.getLineWidth(), 0, 0)); .add(-label.getLineWidth(), 0, 0));
this.labels[joy.getJoyId()][2 * (i + joy.getAxisCount()) + this.labels[joy.getJoyId()][2 * (i + joy.getAxisCount()) +
2] = label; 2] = label;
this.labels[joy.getJoyId()][2 * (i + joy.getAxisCount()) + this.labels[joy.getJoyId()][2 * (i + joy.getAxisCount()) +
3] = label2; 3] = label2;
this.gamepadCont[joy.getJoyId()].attachChild(label); this.gamepadCont[joy.getJoyId()].attachChild(label);
this.gamepadCont[joy.getJoyId()].attachChild(label2); this.gamepadCont[joy.getJoyId()].attachChild(label2);
} }
@@ -786,6 +876,11 @@ public class JoystickPreviewScreen extends BaseAppState
} }
} }
/**
* Repositions the screen elements.
* @param width - The width of the screen.
* @param height - The height of the screen.
*/
public void resize(int width, int height) public void resize(int width, int height)
{ {
this.gui.setLocalTranslation(0, this.getScreenSize().y, 0); this.gui.setLocalTranslation(0, this.getScreenSize().y, 0);
@@ -859,6 +954,12 @@ public class JoystickPreviewScreen extends BaseAppState
{ {
} }
/**
* A convenience method to discover what the mouse is currently over.
* @param x - The current X coordinate of the mouse.
* @param y - The current Y coordinate of the mouse.
* @return Collision results on the GUI.
*/
private CollisionResults checkMouse(int x, int y) private CollisionResults checkMouse(int x, int y)
{ {
CollisionResults results = new CollisionResults(); CollisionResults results = new CollisionResults();
@@ -867,6 +968,11 @@ public class JoystickPreviewScreen extends BaseAppState
return results; return results;
} }
/**
* Displays which button is which as the user hovers over the button.
* TODO - Doesn't trigger.
* @param evt - Input event data.
*/
@Override @Override
public void onMouseMotionEvent(MouseMotionEvent evt) public void onMouseMotionEvent(MouseMotionEvent evt)
{ {
@@ -890,10 +996,8 @@ public class JoystickPreviewScreen extends BaseAppState
if (button != null) if (button != null)
{ {
this.refLabel.setText(button.getName().substring(8)); this.refLabel.setText(button.getName().substring(8));
this.resize( Vector2f size = this.getScreenSize();
this.getApplication().getViewPort().getCamera().getWidth(), this.resize((int) size.x, (int) size.y);
this.getApplication().getViewPort().getCamera()
.getHeight());
} }
else else
{ {
@@ -904,6 +1008,10 @@ public class JoystickPreviewScreen extends BaseAppState
} }
} }
/**
* Triggers the gamepad tab buttons.
* @param evt - Input event data.
*/
@Override @Override
public void onMouseButtonEvent(MouseButtonEvent evt) public void onMouseButtonEvent(MouseButtonEvent evt)
{ {
@@ -955,26 +1063,22 @@ public class JoystickPreviewScreen extends BaseAppState
@Override @Override
public void onConnected(Joystick joystick) public void onConnected(Joystick joystick)
{ {
Vector2f size = this.getScreenSize();
this.updateGamepad(); this.updateGamepad();
this.resize(((SimpleApplication) this.getApplication()).getCamera() this.resize((int) size.x, (int) size.y);
.getWidth(),
((SimpleApplication) this.getApplication()).getCamera()
.getHeight());
} }
@Override @Override
public void onDisconnected(Joystick joystick) public void onDisconnected(Joystick joystick)
{ {
/** Vector2f size = this.getScreenSize();
/*
* TODO - This callback will fire before the joystick is actually * TODO - This callback will fire before the joystick is actually
* removed. This is helpful at times, but it does mean we will have a * removed. This is helpful at times, but it does mean we will have a
* blank slot because this code still thinks we have the one that was * blank slot because this code still thinks we have the one that was
* removed. * removed.
*/ */
this.updateGamepad(); this.updateGamepad();
this.resize(((SimpleApplication) this.getApplication()).getCamera() this.resize((int) size.x, (int) size.y);
.getWidth(),
((SimpleApplication) this.getApplication()).getCamera()
.getHeight());
} }
} }

View File

@@ -97,12 +97,12 @@ public class Main extends SimpleApplication
public Main() public Main()
{ {
super(new StatsAppState(), new DebugKeysAppState()); super(new StatsAppState(), new DebugKeysAppState(), new JoystickPreviewScreen());
} }
@Override @Override
public void simpleInitApp() public void simpleInitApp()
{ {
this.getStateManager().attach(new JoystickPreviewScreen());
} }
} }