Add support for listening to joystick connection/disconnection.
Fixes bug causing NullPointerException when removing joysticks. Allows adding joysticks after the application has started.
This commit is contained in:
parent
c4d2de1656
commit
318d6d0e89
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,7 @@
|
||||
package com.jme3.input;
|
||||
|
||||
public interface JoystickConnectionListener {
|
||||
|
||||
void connectionChanged(int joystickId, JoystickState action);
|
||||
|
||||
}
|
47
jme3-core/src/main/java/com/jme3/input/JoystickState.java
Normal file
47
jme3-core/src/main/java/com/jme3/input/JoystickState.java
Normal file
@ -0,0 +1,47 @@
|
||||
package com.jme3.input;
|
||||
|
||||
/**
|
||||
* Response for joystick callback events.
|
||||
* @author jayfella
|
||||
*/
|
||||
public enum JoystickState {
|
||||
|
||||
// a list of connected/disconnected codes from various contexts.
|
||||
|
||||
// using the JoystickState.fromCode(int) method, if the code matches
|
||||
// it will return the enum value.
|
||||
|
||||
CONNECTED(new int[] {
|
||||
0x40001 // GLFW.GLFW_CONNECTED / LWJGL3
|
||||
}),
|
||||
|
||||
DISCONNECTED(new int[] {
|
||||
0x40002 // GLFW.GLFW_DISCONNECTED / LWJGL3
|
||||
}),
|
||||
|
||||
UNKNOWN(new int[0]);
|
||||
|
||||
private int[] codes;
|
||||
|
||||
JoystickState(int[] codes) {
|
||||
this.codes = codes;
|
||||
}
|
||||
|
||||
private int[] getCodes() {
|
||||
return codes;
|
||||
}
|
||||
|
||||
public static JoystickState fromCode(int value) {
|
||||
|
||||
for (JoystickState state : values()) {
|
||||
for (int code : state.getCodes()) {
|
||||
if (value == code) {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
}
|
@ -57,6 +57,8 @@ public class GlfwJoystickInput implements JoyInput {
|
||||
|
||||
private final Map<JoystickButton, Boolean> joyButtonPressed = new HashMap<>();
|
||||
|
||||
private InputManager inputManager;
|
||||
|
||||
private boolean initialized = false;
|
||||
|
||||
@Override
|
||||
@ -66,8 +68,24 @@ public class GlfwJoystickInput implements JoyInput {
|
||||
}
|
||||
}
|
||||
|
||||
public void fireJoystickConnectionEvent(int jid, int event) {
|
||||
inputManager.fireJoystickConnectionEvent(jid, event);
|
||||
}
|
||||
|
||||
public void reloadJoysticks() {
|
||||
joysticks.clear();
|
||||
|
||||
if (inputManager != null) {
|
||||
Joystick[] joysticks = loadJoysticks(inputManager);
|
||||
inputManager.setJoysticks(joysticks);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Joystick[] loadJoysticks(final InputManager inputManager) {
|
||||
|
||||
this.inputManager = inputManager;
|
||||
|
||||
for (int i = 0; i < GLFW_JOYSTICK_LAST; i++) {
|
||||
if (glfwJoystickPresent(i)) {
|
||||
final String name = glfwGetJoystickName(i);
|
||||
@ -126,23 +144,33 @@ public class GlfwJoystickInput implements JoyInput {
|
||||
@Override
|
||||
public void update() {
|
||||
for (final Map.Entry<Integer, GlfwJoystick> entry : joysticks.entrySet()) {
|
||||
|
||||
// Axes
|
||||
final FloatBuffer axisValues = glfwGetJoystickAxes(entry.getKey());
|
||||
|
||||
for (final JoystickAxis axis : entry.getValue().getAxes()) {
|
||||
final float value = axisValues.get(axis.getAxisId());
|
||||
listener.onJoyAxisEvent(new JoyAxisEvent(axis, value));
|
||||
// if a joystick is added or removed, the callback reloads the joysticks.
|
||||
// when the callback is called and reloads the joystick, this iterator may already have started iterating.
|
||||
// To avoid a NullPointerException we null-check the axisValues and bytebuffer objects.
|
||||
// If the joystick it's iterating over no-longer exists it will return null.
|
||||
|
||||
if (axisValues != null) {
|
||||
for (final JoystickAxis axis : entry.getValue().getAxes()) {
|
||||
final float value = axisValues.get(axis.getAxisId());
|
||||
listener.onJoyAxisEvent(new JoyAxisEvent(axis, value));
|
||||
}
|
||||
}
|
||||
|
||||
// Buttons
|
||||
final ByteBuffer byteBuffer = glfwGetJoystickButtons(entry.getKey());
|
||||
|
||||
for (final JoystickButton button : entry.getValue().getButtons()) {
|
||||
final boolean pressed = byteBuffer.get(button.getButtonId()) == GLFW_PRESS;
|
||||
if (byteBuffer != null) {
|
||||
for (final JoystickButton button : entry.getValue().getButtons()) {
|
||||
final boolean pressed = byteBuffer.get(button.getButtonId()) == GLFW_PRESS;
|
||||
|
||||
if (joyButtonPressed.get(button) != pressed) {
|
||||
joyButtonPressed.put(button, pressed);
|
||||
listener.onJoyButtonEvent(new JoyButtonEvent(button, pressed));
|
||||
if (joyButtonPressed.get(button) != pressed) {
|
||||
joyButtonPressed.put(button, pressed);
|
||||
listener.onJoyButtonEvent(new JoyButtonEvent(button, pressed));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,6 +65,7 @@ import com.jme3.util.LWJGLBufferAllocator.ConcurrentLWJGLBufferAllocator;
|
||||
import org.lwjgl.PointerBuffer;
|
||||
import org.lwjgl.Version;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
import org.lwjgl.glfw.GLFWJoystickCallback;
|
||||
import org.lwjgl.opencl.APPLEGLSharing;
|
||||
import org.lwjgl.opencl.CL10;
|
||||
import org.lwjgl.opencl.KHRGLSharing;
|
||||
@ -233,6 +234,14 @@ public abstract class LwjglContext implements JmeContext {
|
||||
joyInput.initialize();
|
||||
}
|
||||
|
||||
GLFW.glfwSetJoystickCallback(new GLFWJoystickCallback() {
|
||||
@Override
|
||||
public void invoke(int jid, int event) {
|
||||
joyInput.reloadJoysticks();
|
||||
joyInput.fireJoystickConnectionEvent(jid, event);
|
||||
}
|
||||
});
|
||||
|
||||
renderable.set(true);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user