Skip to content

Commit d8559f2

Browse files
Improve gamepads rumble and add device rumble (#2790)
* improve rumble and add device rumble * cleanup * Update jme3-lwjgl/src/main/java/com/jme3/input/lwjgl/JInputJoyInput.java Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Update jme3-lwjgl/src/main/java/com/jme3/input/lwjgl/JInputJoyInput.java Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Update jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/SdlJoystickInput.java Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Update jme3-android/src/main/java/com/jme3/system/android/AndroidHapticFeedback.java Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * fix rumble for android API level < 26 * fixes * cleanup * cleanup * Update jme3-lwjgl/src/main/java/com/jme3/input/lwjgl/JInputJoyInput.java Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
1 parent da8102f commit d8559f2

17 files changed

Lines changed: 842 additions & 131 deletions

File tree

jme3-android/src/main/java/com/jme3/input/android/AndroidInputHandler.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ protected void addListeners(GLSurfaceView view) {
111111

112112
public void loadSettings(AppSettings settings) {
113113
touchInput.loadSettings(settings);
114+
joyInput.loadSettings(settings);
114115
}
115116

116117
public TouchInput getTouchInput() {

jme3-android/src/main/java/com/jme3/input/android/AndroidJoyInput.java

Lines changed: 21 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,7 @@
3131
*/
3232
package com.jme3.input.android;
3333

34-
import android.content.Context;
3534
import android.opengl.GLSurfaceView;
36-
import android.os.Vibrator;
3735
import com.jme3.input.InputManager;
3836
import com.jme3.input.JoyInput;
3937
import com.jme3.input.Joystick;
@@ -42,6 +40,7 @@
4240
import com.jme3.input.event.JoyAxisEvent;
4341
import com.jme3.input.event.JoyButtonEvent;
4442
import com.jme3.system.AppSettings;
43+
import com.jme3.system.JmeSystem;
4544
import java.util.ArrayList;
4645
import java.util.List;
4746
import java.util.concurrent.ConcurrentLinkedQueue;
@@ -55,9 +54,9 @@
5554
* This class manages all the joysticks and feeds the inputs from each back
5655
* to jME's InputManager.
5756
*
58-
* This handler also supports the joystick.rumble(rumbleAmount) method. In this
59-
* case, when joystick.rumble(rumbleAmount) is called, the Android device will vibrate
60-
* if the device has a built-in vibrate motor.
57+
* This handler also supports redirecting joystick.rumble(rumbleAmount) to the
58+
* Android device vibrator if AppSettings#setOnDeviceJoystickRumble(boolean) is
59+
* enabled and the device has a built-in vibrate motor.
6160
*
6261
* Because Android does not allow for the user to define the intensity of the
6362
* vibration, the rumble amount (ie strength) is converted into vibration pulses
@@ -92,33 +91,25 @@ public class AndroidJoyInput implements JoyInput {
9291
private RawInputListener listener = null;
9392
private ConcurrentLinkedQueue<InputEvent> eventQueue = new ConcurrentLinkedQueue<>();
9493
private AndroidSensorJoyInput sensorJoyInput;
95-
private Vibrator vibrator = null;
96-
private boolean vibratorActive = false;
97-
private long maxRumbleTime = 250; // 250ms
94+
private boolean onDeviceJoystickRumble = false;
9895

9996
public AndroidJoyInput(AndroidInputHandler inputHandler) {
10097
this.inputHandler = inputHandler;
10198
sensorJoyInput = new AndroidSensorJoyInput(this);
10299
}
103100

104101
public void setView(GLSurfaceView view) {
105-
if (view == null) {
106-
vibrator = null;
107-
} else {
108-
// Get instance of Vibrator from current Context
109-
vibrator = (Vibrator) view.getContext().getSystemService(Context.VIBRATOR_SERVICE);
110-
if (vibrator == null) {
111-
logger.log(Level.FINE, "Vibrator Service not found.");
112-
}
113-
}
114-
115102
if (sensorJoyInput != null) {
116103
sensorJoyInput.setView(view);
117104
}
118105
}
119106

120107
public void loadSettings(AppSettings settings) {
108+
onDeviceJoystickRumble = settings.isOnDeviceJoystickRumble();
109+
}
121110

111+
boolean isOnDeviceJoystickRumble() {
112+
return onDeviceJoystickRumble;
122113
}
123114

124115
public void addEvent(InputEvent event) {
@@ -133,8 +124,8 @@ public void pauseJoysticks() {
133124
if (sensorJoyInput != null) {
134125
sensorJoyInput.pauseSensors();
135126
}
136-
if (vibrator != null && vibratorActive) {
137-
vibrator.cancel();
127+
if (onDeviceJoystickRumble) {
128+
JmeSystem.stopRumble();
138129
}
139130

140131
}
@@ -182,28 +173,16 @@ public long getInputTimeNanos() {
182173
}
183174

184175
@Override
185-
public void setJoyRumble(int joyId, float amount) {
186-
// convert amount to pulses since Android doesn't allow intensity
187-
if (vibrator != null) {
188-
final long rumbleOnDur = (long)(amount * maxRumbleTime); // ms to pulse vibration on
189-
final long rumbleOffDur = maxRumbleTime - rumbleOnDur; // ms to delay between pulses
190-
final long[] rumblePattern = {
191-
0, // start immediately
192-
rumbleOnDur, // time to leave vibration on
193-
rumbleOffDur // time to delay between vibrations
194-
};
195-
final int rumbleRepeatFrom = 0; // index into rumble pattern to repeat from
196-
197-
// logger.log(Level.FINE, "Rumble amount: {0}, rumbleOnDur: {1}, rumbleOffDur: {2}",
198-
// new Object[]{amount, rumbleOnDur, rumbleOffDur});
199-
200-
if (rumbleOnDur > 0) {
201-
vibrator.vibrate(rumblePattern, rumbleRepeatFrom);
202-
vibratorActive = true;
203-
} else {
204-
vibrator.cancel();
205-
vibratorActive = false;
206-
}
176+
public void setJoyRumble(int joyId, float amountHigh, float amountLow, float duration) {
177+
if (onDeviceJoystickRumble && JmeSystem.isDeviceRumbleSupported()) {
178+
JmeSystem.rumble(amountHigh, amountLow, duration);
179+
}
180+
}
181+
182+
@Override
183+
public void stopJoyRumble(int joyId) {
184+
if (onDeviceJoystickRumble && JmeSystem.isDeviceRumbleSupported()) {
185+
JmeSystem.stopRumble();
207186
}
208187
}
209188

jme3-android/src/main/java/com/jme3/input/android/AndroidJoyInput14.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import android.view.MotionEvent;
3636
import com.jme3.input.InputManager;
3737
import com.jme3.input.Joystick;
38+
import com.jme3.system.JmeSystem;
3839
import java.util.logging.Logger;
3940

4041
/**
@@ -97,6 +98,24 @@ public Joystick[] loadJoysticks(InputManager inputManager) {
9798
return joystickList.toArray( new Joystick[joystickList.size()] );
9899
}
99100

101+
@Override
102+
public void setJoyRumble(int joyId, float amountHigh, float amountLow, float duration) {
103+
if (isOnDeviceJoystickRumble() && JmeSystem.isDeviceRumbleSupported()) {
104+
super.setJoyRumble(joyId, amountHigh, amountLow, duration);
105+
} else {
106+
joystickJoyInput.setJoyRumble(joyId, amountHigh, amountLow, duration);
107+
}
108+
}
109+
110+
@Override
111+
public void stopJoyRumble(int joyId) {
112+
if (isOnDeviceJoystickRumble() && JmeSystem.isDeviceRumbleSupported()) {
113+
super.stopJoyRumble(joyId);
114+
} else {
115+
joystickJoyInput.stopJoyRumble(joyId);
116+
}
117+
}
118+
100119
public boolean onGenericMotion(MotionEvent event) {
101120
return joystickJoyInput.onGenericMotion(event);
102121
}

jme3-android/src/main/java/com/jme3/input/android/AndroidJoystickJoyInput14.java

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import com.jme3.input.JoystickCompatibilityMappings;
4848
import com.jme3.input.event.JoyAxisEvent;
4949
import com.jme3.input.event.JoyButtonEvent;
50+
import com.jme3.system.android.AndroidHapticFeedback;
5051
import java.util.ArrayList;
5152
import java.util.HashMap;
5253
import java.util.List;
@@ -96,15 +97,15 @@ public AndroidJoystickJoyInput14(AndroidJoyInput joyInput) {
9697

9798

9899
public void pauseJoysticks() {
99-
100+
stopAllRumble();
100101
}
101102

102103
public void resumeJoysticks() {
103104

104105
}
105106

106107
public void destroy() {
107-
108+
stopAllRumble();
108109
}
109110

110111
public List<Joystick> loadJoysticks(int joyId, InputManager inputManager) {
@@ -245,6 +246,48 @@ public boolean onKey(KeyEvent event) {
245246
return consumed;
246247
}
247248

249+
boolean setJoyRumble(int joyId, float amount) {
250+
AndroidJoystick joystick = getJoystick(joyId);
251+
if (joystick == null || !joystick.isHapticFeedbackSupported()) {
252+
return false;
253+
}
254+
joystick.rumble(amount);
255+
return true;
256+
}
257+
258+
boolean setJoyRumble(int joyId, float amountHigh, float amountLow, float duration) {
259+
AndroidJoystick joystick = getJoystick(joyId);
260+
if (joystick == null || !joystick.isHapticFeedbackSupported()) {
261+
return false;
262+
}
263+
joystick.rumble(amountHigh, amountLow, duration);
264+
return true;
265+
}
266+
267+
boolean stopJoyRumble(int joyId) {
268+
AndroidJoystick joystick = getJoystick(joyId);
269+
if (joystick == null || !joystick.isHapticFeedbackSupported()) {
270+
return false;
271+
}
272+
joystick.stopRumble();
273+
return true;
274+
}
275+
276+
private AndroidJoystick getJoystick(int joyId) {
277+
for (AndroidJoystick joystick : joystickIndex.values()) {
278+
if (joystick.getJoyId() == joyId) {
279+
return joystick;
280+
}
281+
}
282+
return null;
283+
}
284+
285+
private void stopAllRumble() {
286+
for (AndroidJoystick joystick : joystickIndex.values()) {
287+
joystick.stopRumble();
288+
}
289+
}
290+
248291
protected class AndroidJoystick extends AbstractJoystick {
249292

250293
private JoystickAxis nullAxis;
@@ -278,6 +321,25 @@ protected Set<Integer> getAndroidAxes() {
278321
return axisIndex.keySet();
279322
}
280323

324+
@SuppressWarnings("deprecation")
325+
private android.os.Vibrator getVibrator() {
326+
return device.getVibrator();
327+
}
328+
329+
private boolean isHapticFeedbackSupported() {
330+
return AndroidHapticFeedback.isSupported(getVibrator());
331+
}
332+
333+
@Override
334+
public void rumble(float amountHigh, float amountLow, float duration) {
335+
AndroidHapticFeedback.rumble(getVibrator(), amountHigh, amountLow, duration);
336+
}
337+
338+
@Override
339+
public void stopRumble() {
340+
AndroidHapticFeedback.stop(getVibrator());
341+
}
342+
281343
protected JoystickButton getButton(int keyCode) {
282344
return buttonIndex.get(keyCode);
283345
}

0 commit comments

Comments
 (0)