mirror of
https://github.com/badvision/lawless-legends.git
synced 2024-11-01 01:05:19 +00:00
Use auto-calibration to prevent unnecessary lag, add mapping for controllers
This commit is contained in:
parent
abc32325de
commit
bbb7a08ac6
@ -357,6 +357,10 @@ public class Utility {
|
|||||||
}
|
}
|
||||||
} else if (type.equals(Boolean.TYPE) || type == Boolean.class) {
|
} else if (type.equals(Boolean.TYPE) || type == Boolean.class) {
|
||||||
return Boolean.valueOf(value);
|
return Boolean.valueOf(value);
|
||||||
|
} else if (type.equals(Float.TYPE) || type == Float.class) {
|
||||||
|
return Float.parseFloat(value);
|
||||||
|
} else if (type.equals(Double.TYPE) || type == Double.class) {
|
||||||
|
return Double.parseDouble(value);
|
||||||
} else if (type == File.class) {
|
} else if (type == File.class) {
|
||||||
return new File(String.valueOf(value));
|
return new File(String.valueOf(value));
|
||||||
} else if (type.isEnum()) {
|
} else if (type.isEnum()) {
|
||||||
|
@ -33,7 +33,6 @@ import jace.core.Computer;
|
|||||||
import jace.core.Device;
|
import jace.core.Device;
|
||||||
import jace.core.RAMEvent;
|
import jace.core.RAMEvent;
|
||||||
import jace.core.RAMListener;
|
import jace.core.RAMListener;
|
||||||
import jace.core.TimedDevice;
|
|
||||||
import jace.state.Stateful;
|
import jace.state.Stateful;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.scene.input.MouseEvent;
|
import javafx.scene.input.MouseEvent;
|
||||||
@ -82,17 +81,19 @@ public class Joystick extends Device {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ConfigurableField(name = "X Axis", shortName = "xaxis", description = "Physical game controller X Axis")
|
@ConfigurableField(name = "X Axis", shortName = "xaxis", description = "Physical game controller X Axis")
|
||||||
public int xaxis = GLFW.GLFW_GAMEPAD_AXIS_LEFT_X;
|
public int xaxis = -1;
|
||||||
@ConfigurableField(name = "Y Axis", shortName = "yaxis", description = "Physical game controller Y Axis")
|
@ConfigurableField(name = "Y Axis", shortName = "yaxis", description = "Physical game controller Y Axis")
|
||||||
public int yaxis = GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y;
|
public int yaxis = -1;
|
||||||
@ConfigurableField(name = "Button 0", shortName = "buttonA", description = "Physical game controller A button")
|
@ConfigurableField(name = "Button 0", shortName = "buttonA", description = "Physical game controller A button")
|
||||||
public int button0 = GLFW.GLFW_GAMEPAD_BUTTON_A;
|
public int button0 = -1;
|
||||||
@ConfigurableField(name = "Button 1", shortName = "buttonB", description = "Physical game controller B button")
|
@ConfigurableField(name = "Button 1", shortName = "buttonB", description = "Physical game controller B button")
|
||||||
public int button1 = GLFW.GLFW_GAMEPAD_BUTTON_B;
|
public int button1 = -1;
|
||||||
@ConfigurableField(name = "Prefer D-PAD", shortName = "dpad", description = "Physical game controller enable D-PAD")
|
@ConfigurableField(name = "Use D-PAD", shortName = "dpad", description = "Physical game controller enable D-PAD")
|
||||||
public boolean useDPad = false;
|
public boolean useDPad = true;
|
||||||
@ConfigurableField(name = "Timer resolution", shortName = "timerres", description = "How many ticks until we poll the buttons again?")
|
ControllerMappings mapping = null;
|
||||||
public static long TIMER_RESOLUTION = TimedDevice.NTSC_1MHZ / 15; // 15FPS resolution reads when joystick is not used
|
@ConfigurableField(name = "Polling time", shortName = "pollTime", description = "How many milliseconds between joystick reads? -1=auto-calibrate.")
|
||||||
|
public static long POLLING_TIME = -1;
|
||||||
|
public static int CALIBRATION_ITERATIONS = 15;
|
||||||
@ConfigurableField(name = "Dead Zone", shortName = "deadZone", description = "Dead zone for joystick (0-1)")
|
@ConfigurableField(name = "Dead Zone", shortName = "deadZone", description = "Dead zone for joystick (0-1)")
|
||||||
public static float deadZone = 0.1f;
|
public static float deadZone = 0.1f;
|
||||||
|
|
||||||
@ -100,21 +101,16 @@ public class Joystick extends Device {
|
|||||||
|
|
||||||
public Integer getControllerNum() {
|
public Integer getControllerNum() {
|
||||||
if (controllerNumber != null) {
|
if (controllerNumber != null) {
|
||||||
return controllerNumber >= 0 && GLFW.glfwJoystickPresent(controllerNumber) ? controllerNumber : null;
|
return controllerNumber >= 0 ? controllerNumber : null;
|
||||||
}
|
}
|
||||||
String controllerName = glfwController.getValue();
|
String controllerName = glfwController.getValue();
|
||||||
if (controllerName == null || controllerName.isEmpty()) {
|
if (controllerName == null || controllerName.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
for (int i = GLFW.GLFW_JOYSTICK_1; i <= GLFW.GLFW_JOYSTICK_LAST; i++) {
|
for (int i = GLFW.GLFW_JOYSTICK_1; i <= GLFW.GLFW_JOYSTICK_LAST; i++) {
|
||||||
if (GLFW.glfwJoystickPresent(i) && controllerName.equals(GLFW.glfwGetJoystickName(i))) {
|
if (controllerName.equals(GLFW.glfwGetJoystickName(i)) && GLFW.glfwJoystickPresent(i)) {
|
||||||
controllerNumber = i;
|
controllerNumber = i;
|
||||||
// Let's list out all the buttons and axis data
|
applyControllerMapping();
|
||||||
Platform.runLater(()->{
|
|
||||||
FloatBuffer axes = GLFW.glfwGetJoystickAxes(controllerNumber);
|
|
||||||
ByteBuffer buttons = GLFW.glfwGetJoystickButtons(controllerNumber);
|
|
||||||
System.out.println("Controller " + controllerName + " has " + axes.capacity() + " axes and " + buttons.capacity() + " buttons");
|
|
||||||
});
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -133,6 +129,10 @@ public class Joystick extends Device {
|
|||||||
MemorySoftSwitch xSwitch;
|
MemorySoftSwitch xSwitch;
|
||||||
MemorySoftSwitch ySwitch;
|
MemorySoftSwitch ySwitch;
|
||||||
|
|
||||||
|
long lastPollTime = System.currentTimeMillis();
|
||||||
|
FloatBuffer axes;
|
||||||
|
ByteBuffer buttons;
|
||||||
|
|
||||||
public Joystick(int port, Computer computer) {
|
public Joystick(int port, Computer computer) {
|
||||||
super();
|
super();
|
||||||
if (LawlessLegends.getApplication() == null) {
|
if (LawlessLegends.getApplication() == null) {
|
||||||
@ -166,62 +166,82 @@ public class Joystick extends Device {
|
|||||||
if (useKeyboard) {
|
if (useKeyboard) {
|
||||||
joyX = (leftPressed ? -128 : 0) + (rightPressed ? 255 : 128);
|
joyX = (leftPressed ? -128 : 0) + (rightPressed ? 255 : 128);
|
||||||
joyY = (upPressed ? -128 : 0) + (downPressed ? 255 : 128);
|
joyY = (upPressed ? -128 : 0) + (downPressed ? 255 : 128);
|
||||||
} else if (selectedPhysicalController()) {
|
} else if (readGLFWJoystick()) {
|
||||||
Platform.runLater(()->{
|
float x = xaxis >= 0 && xaxis < axes.capacity() ? axes.get(xaxis) : -0.5f;
|
||||||
Integer controllerNum = getControllerNum();
|
float y = yaxis >= 0 && yaxis < axes.capacity() ? axes.get(yaxis) : 0.5f;
|
||||||
|
|
||||||
if (controllerNum != null) {
|
if (useDPad && mapping != null) {
|
||||||
FloatBuffer axes = GLFW.glfwGetJoystickAxes(controllerNumber);
|
// ByteBuffer buttons = GLFW.glfwGetJoystickButtons(controllerNum);
|
||||||
ByteBuffer buttons = GLFW.glfwGetJoystickButtons(controllerNumber);
|
if (buttons.get(mapping.dpadLeft) != 0) {
|
||||||
float x = xaxis >= 0 && xaxis < axes.capacity() ? axes.get(xaxis) : -0.5f;
|
x = -1;
|
||||||
float y = yaxis >= 0 && yaxis < axes.capacity() ? axes.get(yaxis) : 0.5f;
|
} else if (buttons.get(mapping.dpadRight) != 0) {
|
||||||
|
x = 1;
|
||||||
if (useDPad) {
|
|
||||||
// ByteBuffer buttons = GLFW.glfwGetJoystickButtons(controllerNum);
|
|
||||||
if (buttons.get(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_LEFT) != 0) {
|
|
||||||
x = -1;
|
|
||||||
} else if (buttons.get(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_RIGHT) != 0) {
|
|
||||||
x = 1;
|
|
||||||
} else {
|
|
||||||
x = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buttons.get(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP) != 0) {
|
|
||||||
y = -1;
|
|
||||||
} else if (buttons.get(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_DOWN) != 0) {
|
|
||||||
y = 1;
|
|
||||||
} else {
|
|
||||||
y = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (Math.abs(x) < deadZone) {
|
|
||||||
x = 0;
|
|
||||||
}
|
|
||||||
if (Math.abs(y) < deadZone) {
|
|
||||||
y = 0;
|
|
||||||
}
|
|
||||||
joyX = (int) (x * 128.0 + 128.0);
|
|
||||||
joyY = (int) (y * 128.0 + 128.0);
|
|
||||||
|
|
||||||
readButtons();
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
if (buttons.get(mapping.dpadUp) != 0) {
|
||||||
|
y = -1;
|
||||||
|
} else if (buttons.get(mapping.dpadDown) != 0) {
|
||||||
|
y = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Math.abs(x) < deadZone) {
|
||||||
|
x = 0;
|
||||||
|
}
|
||||||
|
if (Math.abs(y) < deadZone) {
|
||||||
|
y = 0;
|
||||||
|
}
|
||||||
|
joyX = (int) (x * 128.0 + 128.0);
|
||||||
|
joyY = (int) (y * 128.0 + 128.0);
|
||||||
|
|
||||||
|
readButtons();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readButtons() {
|
private void calibrateTiming() {
|
||||||
|
if (POLLING_TIME > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (selectedPhysicalController()) {
|
if (selectedPhysicalController()) {
|
||||||
Integer controllerNum = getControllerNum();
|
Integer controllerNum = getControllerNum();
|
||||||
if (controllerNum != null) {
|
if (controllerNum != null) {
|
||||||
ByteBuffer buttons = GLFW.glfwGetJoystickButtons(controllerNumber);
|
long start = System.currentTimeMillis();
|
||||||
byte b0 = button0 >=0 && button0 < buttons.capacity() ? buttons.get(button0) : 0;
|
|
||||||
byte b1 = button1 >=0 && button1 < buttons.capacity() ? buttons.get(button1) : 0;
|
for (int i = 0; i < CALIBRATION_ITERATIONS; i++) {
|
||||||
SoftSwitches.PB0.getSwitch().setState(b0 != 0);
|
buttons = GLFW.glfwGetJoystickButtons(controllerNumber);
|
||||||
SoftSwitches.PB1.getSwitch().setState(b1 != 0);
|
axes = GLFW.glfwGetJoystickAxes(controllerNumber);
|
||||||
|
}
|
||||||
|
long end = System.currentTimeMillis();
|
||||||
|
POLLING_TIME = (end - start) / CALIBRATION_ITERATIONS + 1;
|
||||||
|
System.out.println("Calibrated polling time to " + POLLING_TIME + "ms");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean readGLFWJoystick() {
|
||||||
|
if (System.currentTimeMillis() - lastPollTime >= POLLING_TIME) {
|
||||||
|
lastPollTime = System.currentTimeMillis();
|
||||||
|
if (selectedPhysicalController()) {
|
||||||
|
Integer controllerNum = getControllerNum();
|
||||||
|
if (controllerNum != null) {
|
||||||
|
Platform.runLater(()->{
|
||||||
|
buttons = GLFW.glfwGetJoystickButtons(controllerNumber);
|
||||||
|
axes = GLFW.glfwGetJoystickAxes(controllerNumber);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return axes != null && buttons != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readButtons() {
|
||||||
|
if (readGLFWJoystick()) {
|
||||||
|
byte b0 = button0 >=0 && button0 < buttons.capacity() ? buttons.get(button0) : 0;
|
||||||
|
byte b1 = button1 >=0 && button1 < buttons.capacity() ? buttons.get(button1) : 0;
|
||||||
|
SoftSwitches.PB0.getSwitch().setState(b0 != 0);
|
||||||
|
SoftSwitches.PB1.getSwitch().setState(b1 != 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getDeviceName() {
|
protected String getDeviceName() {
|
||||||
return "Joystick (port " + port + ")";
|
return "Joystick (port " + port + ")";
|
||||||
@ -255,12 +275,8 @@ public class Joystick extends Device {
|
|||||||
if (selectedPhysicalController()) {
|
if (selectedPhysicalController()) {
|
||||||
if (finished && ticksSinceLastRead >= 1000000) {
|
if (finished && ticksSinceLastRead >= 1000000) {
|
||||||
setRun(false);
|
setRun(false);
|
||||||
} else if (ticksSinceLastRead % TIMER_RESOLUTION == 0) {
|
} else if (ticksSinceLastRead > 1000 && ticksSinceLastRead % 1000 == 0) {
|
||||||
// Read joystick buttons ~60 times a second as long as joystick is actively in use
|
readButtons();
|
||||||
Integer controllerNum = getControllerNum();
|
|
||||||
if (controllerNum != null) {
|
|
||||||
Platform.runLater(this::readButtons);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (finished) {
|
} else if (finished) {
|
||||||
setRun(false);
|
setRun(false);
|
||||||
@ -283,8 +299,68 @@ public class Joystick extends Device {
|
|||||||
removeListeners();
|
removeListeners();
|
||||||
x = 0;
|
x = 0;
|
||||||
y = 0;
|
y = 0;
|
||||||
registerListeners();
|
|
||||||
controllerNumber = null;
|
controllerNumber = null;
|
||||||
|
Platform.runLater(this::calibrateTiming);
|
||||||
|
registerListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyControllerMapping() {
|
||||||
|
mapping = ControllerMappings.getMapping(glfwController.getValue());
|
||||||
|
if (mapping != null) {
|
||||||
|
System.out.println("Applying controller mapping " + mapping);
|
||||||
|
if (xaxis < 0) {
|
||||||
|
xaxis = mapping.xaxis;
|
||||||
|
}
|
||||||
|
if (yaxis < 0) {
|
||||||
|
yaxis = mapping.yaxis;
|
||||||
|
}
|
||||||
|
if (button0 < 0) {
|
||||||
|
button0 = mapping.button0;
|
||||||
|
}
|
||||||
|
if (button1 < 0) {
|
||||||
|
button1 = mapping.button1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static enum ControllerMappings{
|
||||||
|
mocute("MOCUTE-032.*", 1, 3, 3, 6),
|
||||||
|
ps3("PLAYSTATION\\(R\\)3.*", 0, 1, 7, 5, 4, 6, 14, 13),
|
||||||
|
generic("UNKNOWN", GLFW.GLFW_GAMEPAD_AXIS_LEFT_X, GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y, GLFW.GLFW_GAMEPAD_BUTTON_A, GLFW.GLFW_GAMEPAD_BUTTON_B);
|
||||||
|
public final String pattern;
|
||||||
|
public final int xaxis;
|
||||||
|
public final int yaxis;
|
||||||
|
public final int dpadLeft;
|
||||||
|
public final int dpadRight;
|
||||||
|
public final int dpadUp;
|
||||||
|
public final int dpadDown;
|
||||||
|
public final int button0;
|
||||||
|
public final int button1;
|
||||||
|
ControllerMappings(String pattern, int xaxis, int yaxis, int button0, int button1) {
|
||||||
|
this(pattern, xaxis, yaxis, GLFW.GLFW_GAMEPAD_BUTTON_DPAD_LEFT,GLFW. GLFW_GAMEPAD_BUTTON_DPAD_RIGHT, GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW.GLFW_GAMEPAD_BUTTON_DPAD_DOWN, button0, button1);
|
||||||
|
}
|
||||||
|
ControllerMappings(String pattern, int xaxis, int yaxis, int dpadLeft, int dpadRight, int dpadUp, int dpadDown, int button0, int button1) {
|
||||||
|
this.pattern = pattern;
|
||||||
|
this.xaxis = xaxis;
|
||||||
|
this.yaxis = yaxis;
|
||||||
|
this.dpadLeft = dpadLeft;
|
||||||
|
this.dpadRight = dpadRight;
|
||||||
|
this.dpadUp = dpadUp;
|
||||||
|
this.dpadDown = dpadDown;
|
||||||
|
this.button0 = button0;
|
||||||
|
this.button1 = button1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ControllerMappings getMapping(String name) {
|
||||||
|
if (name == null) return null;
|
||||||
|
for (ControllerMappings mapping : ControllerMappings.values()) {
|
||||||
|
if (name.matches(mapping.pattern)) {
|
||||||
|
return mapping;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println("No mapping found for " + name);
|
||||||
|
return ControllerMappings.generic;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@InvokableAction(name = "Left", category = "joystick", defaultKeyMapping = "left", notifyOnRelease = true)
|
@InvokableAction(name = "Left", category = "joystick", defaultKeyMapping = "left", notifyOnRelease = true)
|
||||||
|
Loading…
Reference in New Issue
Block a user