mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-18 10:32:43 +00:00
Add device vibration and other fixes
This commit is contained in:
parent
2f7087d6d3
commit
50d45011a8
@ -55,6 +55,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
private final double stickDeadzone;
|
||||
private final InputDeviceContext defaultContext = new InputDeviceContext();
|
||||
private final GameGestures gestures;
|
||||
private final Vibrator deviceVibrator;
|
||||
private boolean hasGameController;
|
||||
|
||||
private final PreferenceConfiguration prefConfig;
|
||||
@ -65,6 +66,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
this.conn = conn;
|
||||
this.gestures = gestures;
|
||||
this.prefConfig = prefConfig;
|
||||
this.deviceVibrator = (Vibrator) activityContext.getSystemService(Context.VIBRATOR_SERVICE);
|
||||
|
||||
// HACK: For now we're hardcoding a 10% deadzone. Some deadzone
|
||||
// is required for controller batching support to work.
|
||||
@ -163,6 +165,8 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
deviceContext.vibrator.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
deviceVibrator.cancel();
|
||||
}
|
||||
|
||||
private static boolean hasJoystickAxes(InputDevice device) {
|
||||
@ -220,6 +224,11 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
}
|
||||
}
|
||||
|
||||
if (PreferenceConfiguration.readPreferences(context).onscreenController) {
|
||||
LimeLog.info("Counting OSC gamepad");
|
||||
mask |= 1;
|
||||
}
|
||||
|
||||
LimeLog.info("Enumerated "+count+" gamepads");
|
||||
return mask;
|
||||
}
|
||||
@ -633,7 +642,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
|
||||
private short getActiveControllerMask() {
|
||||
if (prefConfig.multiController) {
|
||||
return (short)(currentControllers | initialControllers);
|
||||
return (short)(currentControllers | initialControllers | (prefConfig.onscreenController ? 1 : 0));
|
||||
}
|
||||
else {
|
||||
// Only Player 1 is active with multi-controller disabled
|
||||
@ -1072,13 +1081,15 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
// Since we can only use a single amplitude value, compute the desired amplitude
|
||||
// by taking 75% of the big motor and 25% of the small motor.
|
||||
// NB: This value is now 0-255 as required by VibrationEffect.
|
||||
int simulatedAmplitude = (int)(((lowFreqMotor >> 8) * 0.75) + ((highFreqMotor >> 8) * 0.25));
|
||||
short lowFreqMotorMSB = (short)((lowFreqMotor >> 8) & 0xFF);
|
||||
short highFreqMotorMSB = (short)((lowFreqMotor >> 8) & 0xFF);
|
||||
int simulatedAmplitude = (int)((lowFreqMotorMSB * 0.75) + (highFreqMotorMSB * 0.25));
|
||||
|
||||
// Attempt to use amplitude-based control if we're on Oreo and the device
|
||||
// supports amplitude-based vibration control.
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
if (vibrator.hasAmplitudeControl()) {
|
||||
VibrationEffect effect = VibrationEffect.createOneShot(Long.MAX_VALUE, simulatedAmplitude);
|
||||
VibrationEffect effect = VibrationEffect.createOneShot(60000, simulatedAmplitude);
|
||||
AudioAttributes audioAttributes = new AudioAttributes.Builder()
|
||||
.setUsage(AudioAttributes.USAGE_GAME)
|
||||
.build();
|
||||
@ -1089,26 +1100,50 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
|
||||
// If we reach this point, we don't have amplitude controls available, so
|
||||
// we must emulate it by PWMing the vibration. Ick.
|
||||
long pwmPeriod = 50;
|
||||
long pwmPeriod = 20;
|
||||
long onTime = (long)((simulatedAmplitude / 255.0) * pwmPeriod);
|
||||
long offTime = pwmPeriod - onTime;
|
||||
vibrator.vibrate(new long[]{offTime, onTime}, 0);
|
||||
vibrator.vibrate(new long[]{0, onTime, offTime}, 0);
|
||||
}
|
||||
|
||||
public void handleRumble(short controllerNumber, short lowFreqMotor, short highFreqMotor) {
|
||||
boolean foundMatchingDevice = false;
|
||||
boolean vibrated = false;
|
||||
|
||||
for (int i = 0; i < inputDeviceContexts.size(); i++) {
|
||||
InputDeviceContext deviceContext = inputDeviceContexts.valueAt(i);
|
||||
|
||||
if (deviceContext.controllerNumber == controllerNumber && deviceContext.vibrator != null) {
|
||||
if (deviceContext.controllerNumber == controllerNumber) {
|
||||
foundMatchingDevice = true;
|
||||
|
||||
if (deviceContext.vibrator != null) {
|
||||
vibrated = true;
|
||||
rumbleVibrator(deviceContext.vibrator, lowFreqMotor, highFreqMotor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < usbDeviceContexts.size(); i++) {
|
||||
UsbDeviceContext deviceContext = usbDeviceContexts.valueAt(i);
|
||||
|
||||
if (deviceContext.controllerNumber == controllerNumber) {
|
||||
deviceContext.device.rumble(lowFreqMotor, highFreqMotor);
|
||||
foundMatchingDevice = vibrated = true;
|
||||
deviceContext.device.rumble((short)lowFreqMotor, (short)highFreqMotor);
|
||||
}
|
||||
}
|
||||
|
||||
// We may decide to rumble the device for player 1
|
||||
if (controllerNumber == 0) {
|
||||
// If we didn't find a matching device, it must be the on-screen
|
||||
// controls that triggered the rumble. Vibrate the device if
|
||||
// the user has requested that behavior.
|
||||
if (!foundMatchingDevice && prefConfig.onscreenController && !prefConfig.onlyL3R3 && prefConfig.vibrateOsc) {
|
||||
rumbleVibrator(deviceVibrator, lowFreqMotor, highFreqMotor);
|
||||
}
|
||||
else if (foundMatchingDevice && !vibrated && prefConfig.vibrateFallbackToDevice) {
|
||||
// We found a device to vibrate but it didn't have rumble support. The user
|
||||
// has requested us to vibrate the device in this case.
|
||||
rumbleVibrator(deviceVibrator, lowFreqMotor, highFreqMotor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,8 @@ public class PreferenceConfiguration {
|
||||
private static final String MOUSE_EMULATION_STRING = "checkbox_mouse_emulation";
|
||||
private static final String MOUSE_NAV_BUTTONS_STRING = "checkbox_mouse_nav_buttons";
|
||||
static final String UNLOCK_FPS_STRING = "checkbox_unlock_fps";
|
||||
private static final String VIBRATE_OSC_PREF_STRING = "checkbox_vibrate_osc";
|
||||
private static final String VIBRATE_FALLBACK_PREF_STRING = "checkbox_vibrate_fallback";
|
||||
|
||||
static final String DEFAULT_RESOLUTION = "720p";
|
||||
static final String DEFAULT_FPS = "60";
|
||||
@ -58,6 +60,8 @@ public class PreferenceConfiguration {
|
||||
private static final boolean DEFAULT_MOUSE_EMULATION = true;
|
||||
private static final boolean DEFAULT_MOUSE_NAV_BUTTONS = false;
|
||||
private static final boolean DEFAULT_UNLOCK_FPS = false;
|
||||
private static final boolean DEFAULT_VIBRATE_OSC = true;
|
||||
private static final boolean DEFAULT_VIBRATE_FALLBACK = false;
|
||||
|
||||
public static final int FORCE_H265_ON = -1;
|
||||
public static final int AUTOSELECT_H265 = 0;
|
||||
@ -79,6 +83,8 @@ public class PreferenceConfiguration {
|
||||
public boolean mouseEmulation;
|
||||
public boolean mouseNavButtons;
|
||||
public boolean unlockFps;
|
||||
public boolean vibrateOsc;
|
||||
public boolean vibrateFallbackToDevice;
|
||||
|
||||
private static int getHeightFromResolutionString(String resString) {
|
||||
if (resString.equalsIgnoreCase("360p")) {
|
||||
@ -329,6 +335,8 @@ public class PreferenceConfiguration {
|
||||
config.mouseEmulation = prefs.getBoolean(MOUSE_EMULATION_STRING, DEFAULT_MOUSE_EMULATION);
|
||||
config.mouseNavButtons = prefs.getBoolean(MOUSE_NAV_BUTTONS_STRING, DEFAULT_MOUSE_NAV_BUTTONS);
|
||||
config.unlockFps = prefs.getBoolean(UNLOCK_FPS_STRING, DEFAULT_UNLOCK_FPS);
|
||||
config.vibrateOsc = prefs.getBoolean(VIBRATE_OSC_PREF_STRING, DEFAULT_VIBRATE_OSC);
|
||||
config.vibrateFallbackToDevice = prefs.getBoolean(VIBRATE_FALLBACK_PREF_STRING, DEFAULT_VIBRATE_FALLBACK);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
@ -136,6 +136,8 @@
|
||||
<string name="category_input_settings">Input Settings</string>
|
||||
<string name="title_checkbox_multi_controller">Automatic gamepad presence detection</string>
|
||||
<string name="summary_checkbox_multi_controller">Unchecking this option forces a gamepad to always be present</string>
|
||||
<string name="title_checkbox_vibrate_fallback">Emulate rumble support with vibration</string>
|
||||
<string name="summary_checkbox_vibrate_fallback">Vibrates your device to emulate rumble if your gamepad does not support it</string>
|
||||
<string name="title_seekbar_deadzone">Adjust analog stick deadzone</string>
|
||||
<string name="suffix_seekbar_deadzone">%</string>
|
||||
<string name="title_checkbox_xb1_driver">Xbox 360/One controller driver</string>
|
||||
@ -150,6 +152,8 @@
|
||||
<string name="category_on_screen_controls_settings">On-screen Controls Settings</string>
|
||||
<string name="title_checkbox_show_onscreen_controls">Show on-screen controls</string>
|
||||
<string name="summary_checkbox_show_onscreen_controls">Show virtual controller overlay on touchscreen</string>
|
||||
<string name="title_checkbox_vibrate_osc">Enable vibration</string>
|
||||
<string name="summary_checkbox_vibrate_osc">Vibrates your device to emulate rumble for the on-screen controls</string>
|
||||
<string name="title_only_l3r3">Only show L3 and R3</string>
|
||||
<string name="summary_only_l3r3">Hide all virtual buttons except L3 and R3</string>
|
||||
<string name="title_reset_osc">Clear saved on-screen controls layout</string>
|
||||
|
@ -82,6 +82,11 @@
|
||||
android:title="@string/title_checkbox_mouse_emulation"
|
||||
android:summary="@string/summary_checkbox_mouse_emulation"
|
||||
android:defaultValue="true" />
|
||||
<CheckBoxPreference
|
||||
android:key="checkbox_vibrate_fallback"
|
||||
android:title="@string/title_checkbox_vibrate_fallback"
|
||||
android:summary="@string/summary_checkbox_vibrate_fallback"
|
||||
android:defaultValue="false" />
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="@string/category_on_screen_controls_settings"
|
||||
android:key="category_onscreen_controls">
|
||||
@ -90,6 +95,12 @@
|
||||
android:key="checkbox_show_onscreen_controls"
|
||||
android:summary="@string/summary_checkbox_show_onscreen_controls"
|
||||
android:title="@string/title_checkbox_show_onscreen_controls" />
|
||||
<CheckBoxPreference
|
||||
android:key="checkbox_vibrate_osc"
|
||||
android:dependency="checkbox_show_onscreen_controls"
|
||||
android:title="@string/title_checkbox_vibrate_osc"
|
||||
android:summary="@string/summary_checkbox_vibrate_osc"
|
||||
android:defaultValue="true" />
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:dependency="checkbox_show_onscreen_controls"
|
||||
|
Loading…
x
Reference in New Issue
Block a user