mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-05-30 00:17:40 +00:00
Added support for gamepad rumble on Android
Tested with the DualSense controller over Bluetooth on Android 12 Fixes https://github.com/libsdl-org/SDL/issues/7847
This commit is contained in:
parent
0c3dcdf4a3
commit
f879411627
6 changed files with 116 additions and 70 deletions
|
@ -9,6 +9,7 @@ import android.content.Context;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.VibrationEffect;
|
import android.os.VibrationEffect;
|
||||||
import android.os.Vibrator;
|
import android.os.Vibrator;
|
||||||
|
import android.os.VibratorManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.InputDevice;
|
import android.view.InputDevice;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
|
@ -24,7 +25,7 @@ public class SDLControllerManager
|
||||||
public static native int nativeAddJoystick(int device_id, String name, String desc,
|
public static native int nativeAddJoystick(int device_id, String name, String desc,
|
||||||
int vendor_id, int product_id,
|
int vendor_id, int product_id,
|
||||||
int button_mask,
|
int button_mask,
|
||||||
int naxes, int axis_mask, int nhats);
|
int naxes, int axis_mask, int nhats, boolean can_rumble);
|
||||||
public static native int nativeRemoveJoystick(int device_id);
|
public static native int nativeRemoveJoystick(int device_id);
|
||||||
public static native int nativeAddHaptic(int device_id, String name);
|
public static native int nativeAddHaptic(int device_id, String name);
|
||||||
public static native int nativeRemoveHaptic(int device_id);
|
public static native int nativeRemoveHaptic(int device_id);
|
||||||
|
@ -50,7 +51,9 @@ public class SDLControllerManager
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mHapticHandler == null) {
|
if (mHapticHandler == null) {
|
||||||
if (Build.VERSION.SDK_INT >= 26 /* Android 8.0 (O) */) {
|
if (Build.VERSION.SDK_INT >= 31 /* Android 12.0 (S) */) {
|
||||||
|
mHapticHandler = new SDLHapticHandler_API31();
|
||||||
|
} else if (Build.VERSION.SDK_INT >= 26 /* Android 8.0 (O) */) {
|
||||||
mHapticHandler = new SDLHapticHandler_API26();
|
mHapticHandler = new SDLHapticHandler_API26();
|
||||||
} else {
|
} else {
|
||||||
mHapticHandler = new SDLHapticHandler();
|
mHapticHandler = new SDLHapticHandler();
|
||||||
|
@ -84,6 +87,13 @@ public class SDLControllerManager
|
||||||
mHapticHandler.run(device_id, intensity, length);
|
mHapticHandler.run(device_id, intensity, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called by SDL using JNI.
|
||||||
|
*/
|
||||||
|
public static void hapticRumble(int device_id, float low_frequency_intensity, float high_frequency_intensity, int length) {
|
||||||
|
mHapticHandler.rumble(device_id, low_frequency_intensity, high_frequency_intensity, length);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called by SDL using JNI.
|
* This method is called by SDL using JNI.
|
||||||
*/
|
*/
|
||||||
|
@ -233,10 +243,19 @@ class SDLJoystickHandler_API16 extends SDLJoystickHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean can_rumble = false;
|
||||||
|
if (Build.VERSION.SDK_INT >= 31 /* Android 12.0 (S) */) {
|
||||||
|
VibratorManager manager = joystickDevice.getVibratorManager();
|
||||||
|
int[] vibrators = manager.getVibratorIds();
|
||||||
|
if (vibrators.length > 0) {
|
||||||
|
can_rumble = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mJoysticks.add(joystick);
|
mJoysticks.add(joystick);
|
||||||
SDLControllerManager.nativeAddJoystick(joystick.device_id, joystick.name, joystick.desc,
|
SDLControllerManager.nativeAddJoystick(joystick.device_id, joystick.name, joystick.desc,
|
||||||
getVendorId(joystickDevice), getProductId(joystickDevice),
|
getVendorId(joystickDevice), getProductId(joystickDevice),
|
||||||
getButtonMask(joystickDevice), joystick.axes.size(), getAxisMask(joystick.axes), joystick.hats.size()/2);
|
getButtonMask(joystickDevice), joystick.axes.size(), getAxisMask(joystick.axes), joystick.hats.size()/2, can_rumble);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -470,12 +489,63 @@ class SDLJoystickHandler_API19 extends SDLJoystickHandler_API16 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SDLHapticHandler_API31 extends SDLHapticHandler {
|
||||||
|
@Override
|
||||||
|
public void run(int device_id, float intensity, int length) {
|
||||||
|
SDLHaptic haptic = getHaptic(device_id);
|
||||||
|
if (haptic != null) {
|
||||||
|
vibrate(haptic.vib, intensity, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void rumble(int device_id, float low_frequency_intensity, float high_frequency_intensity, int length) {
|
||||||
|
InputDevice device = InputDevice.getDevice(device_id);
|
||||||
|
if (device == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VibratorManager manager = device.getVibratorManager();
|
||||||
|
int[] vibrators = manager.getVibratorIds();
|
||||||
|
if (vibrators.length >= 2) {
|
||||||
|
vibrate(manager.getVibrator(vibrators[0]), low_frequency_intensity, length);
|
||||||
|
vibrate(manager.getVibrator(vibrators[1]), high_frequency_intensity, length);
|
||||||
|
} else if (vibrators.length == 1) {
|
||||||
|
float intensity = (low_frequency_intensity * 0.6f) + (high_frequency_intensity * 0.4f);
|
||||||
|
vibrate(manager.getVibrator(vibrators[0]), intensity, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void vibrate(Vibrator vibrator, float intensity, int length) {
|
||||||
|
if (intensity == 0.0f) {
|
||||||
|
vibrator.cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int value = Math.round(intensity * 255);
|
||||||
|
if (value > 255) {
|
||||||
|
value = 255;
|
||||||
|
}
|
||||||
|
if (value < 1) {
|
||||||
|
vibrator.cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
vibrator.vibrate(VibrationEffect.createOneShot(length, value));
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
// Fall back to the generic method, which uses DEFAULT_AMPLITUDE, but works even if
|
||||||
|
// something went horribly wrong with the Android 8.0 APIs.
|
||||||
|
vibrator.vibrate(length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class SDLHapticHandler_API26 extends SDLHapticHandler {
|
class SDLHapticHandler_API26 extends SDLHapticHandler {
|
||||||
@Override
|
@Override
|
||||||
public void run(int device_id, float intensity, int length) {
|
public void run(int device_id, float intensity, int length) {
|
||||||
SDLHaptic haptic = getHaptic(device_id);
|
SDLHaptic haptic = getHaptic(device_id);
|
||||||
if (haptic != null) {
|
if (haptic != null) {
|
||||||
Log.d("SDL", "Rtest: Vibe with intensity " + intensity + " for " + length);
|
|
||||||
if (intensity == 0.0f) {
|
if (intensity == 0.0f) {
|
||||||
stop(device_id);
|
stop(device_id);
|
||||||
return;
|
return;
|
||||||
|
@ -523,6 +593,10 @@ class SDLHapticHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void rumble(int device_id, float low_frequency_intensity, float high_frequency_intensity, int length) {
|
||||||
|
// Not supported in older APIs
|
||||||
|
}
|
||||||
|
|
||||||
public void stop(int device_id) {
|
public void stop(int device_id) {
|
||||||
SDLHaptic haptic = getHaptic(device_id);
|
SDLHaptic haptic = getHaptic(device_id);
|
||||||
if (haptic != null) {
|
if (haptic != null) {
|
||||||
|
@ -535,30 +609,6 @@ class SDLHapticHandler {
|
||||||
final int deviceId_VIBRATOR_SERVICE = 999999;
|
final int deviceId_VIBRATOR_SERVICE = 999999;
|
||||||
boolean hasVibratorService = false;
|
boolean hasVibratorService = false;
|
||||||
|
|
||||||
int[] deviceIds = InputDevice.getDeviceIds();
|
|
||||||
// It helps processing the device ids in reverse order
|
|
||||||
// For example, in the case of the XBox 360 wireless dongle,
|
|
||||||
// so the first controller seen by SDL matches what the receiver
|
|
||||||
// considers to be the first controller
|
|
||||||
|
|
||||||
for (int i = deviceIds.length - 1; i > -1; i--) {
|
|
||||||
SDLHaptic haptic = getHaptic(deviceIds[i]);
|
|
||||||
if (haptic == null) {
|
|
||||||
InputDevice device = InputDevice.getDevice(deviceIds[i]);
|
|
||||||
Vibrator vib = device.getVibrator();
|
|
||||||
if (vib != null) {
|
|
||||||
if (vib.hasVibrator()) {
|
|
||||||
haptic = new SDLHaptic();
|
|
||||||
haptic.device_id = deviceIds[i];
|
|
||||||
haptic.name = device.getName();
|
|
||||||
haptic.vib = vib;
|
|
||||||
mHaptics.add(haptic);
|
|
||||||
SDLControllerManager.nativeAddHaptic(haptic.device_id, haptic.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check VIBRATOR_SERVICE */
|
/* Check VIBRATOR_SERVICE */
|
||||||
Vibrator vib = (Vibrator) SDL.getContext().getSystemService(Context.VIBRATOR_SERVICE);
|
Vibrator vib = (Vibrator) SDL.getContext().getSystemService(Context.VIBRATOR_SERVICE);
|
||||||
if (vib != null) {
|
if (vib != null) {
|
||||||
|
@ -581,18 +631,11 @@ class SDLHapticHandler {
|
||||||
ArrayList<Integer> removedDevices = null;
|
ArrayList<Integer> removedDevices = null;
|
||||||
for (SDLHaptic haptic : mHaptics) {
|
for (SDLHaptic haptic : mHaptics) {
|
||||||
int device_id = haptic.device_id;
|
int device_id = haptic.device_id;
|
||||||
int i;
|
|
||||||
for (i = 0; i < deviceIds.length; i++) {
|
|
||||||
if (device_id == deviceIds[i]) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (device_id != deviceId_VIBRATOR_SERVICE || !hasVibratorService) {
|
if (device_id != deviceId_VIBRATOR_SERVICE || !hasVibratorService) {
|
||||||
if (i == deviceIds.length) {
|
|
||||||
if (removedDevices == null) {
|
if (removedDevices == null) {
|
||||||
removedDevices = new ArrayList<Integer>();
|
removedDevices = new ArrayList<Integer>();
|
||||||
}
|
}
|
||||||
removedDevices.add(device_id);
|
removedDevices.add(device_id);
|
||||||
}
|
|
||||||
} // else: don't remove the vibrator if it is still present
|
} // else: don't remove the vibrator if it is still present
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -274,7 +274,7 @@ JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativeHat)(
|
||||||
JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick)(
|
JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick)(
|
||||||
JNIEnv *env, jclass jcls,
|
JNIEnv *env, jclass jcls,
|
||||||
jint device_id, jstring device_name, jstring device_desc, jint vendor_id, jint product_id,
|
jint device_id, jstring device_name, jstring device_desc, jint vendor_id, jint product_id,
|
||||||
jint button_mask, jint naxes, jint axis_mask, jint nhats);
|
jint button_mask, jint naxes, jint axis_mask, jint nhats, jboolean can_rumble);
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveJoystick)(
|
JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveJoystick)(
|
||||||
JNIEnv *env, jclass jcls,
|
JNIEnv *env, jclass jcls,
|
||||||
|
@ -294,7 +294,7 @@ static JNINativeMethod SDLControllerManager_tab[] = {
|
||||||
{ "onNativePadUp", "(II)I", SDL_JAVA_CONTROLLER_INTERFACE(onNativePadUp) },
|
{ "onNativePadUp", "(II)I", SDL_JAVA_CONTROLLER_INTERFACE(onNativePadUp) },
|
||||||
{ "onNativeJoy", "(IIF)V", SDL_JAVA_CONTROLLER_INTERFACE(onNativeJoy) },
|
{ "onNativeJoy", "(IIF)V", SDL_JAVA_CONTROLLER_INTERFACE(onNativeJoy) },
|
||||||
{ "onNativeHat", "(IIII)V", SDL_JAVA_CONTROLLER_INTERFACE(onNativeHat) },
|
{ "onNativeHat", "(IIII)V", SDL_JAVA_CONTROLLER_INTERFACE(onNativeHat) },
|
||||||
{ "nativeAddJoystick", "(ILjava/lang/String;Ljava/lang/String;IIIIII)I", SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick) },
|
{ "nativeAddJoystick", "(ILjava/lang/String;Ljava/lang/String;IIIIIIZ)I", SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick) },
|
||||||
{ "nativeRemoveJoystick", "(I)I", SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveJoystick) },
|
{ "nativeRemoveJoystick", "(I)I", SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveJoystick) },
|
||||||
{ "nativeAddHaptic", "(ILjava/lang/String;)I", SDL_JAVA_CONTROLLER_INTERFACE(nativeAddHaptic) },
|
{ "nativeAddHaptic", "(ILjava/lang/String;)I", SDL_JAVA_CONTROLLER_INTERFACE(nativeAddHaptic) },
|
||||||
{ "nativeRemoveHaptic", "(I)I", SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveHaptic) }
|
{ "nativeRemoveHaptic", "(I)I", SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveHaptic) }
|
||||||
|
@ -378,6 +378,7 @@ static jclass mControllerManagerClass;
|
||||||
static jmethodID midPollInputDevices;
|
static jmethodID midPollInputDevices;
|
||||||
static jmethodID midPollHapticDevices;
|
static jmethodID midPollHapticDevices;
|
||||||
static jmethodID midHapticRun;
|
static jmethodID midHapticRun;
|
||||||
|
static jmethodID midHapticRumble;
|
||||||
static jmethodID midHapticStop;
|
static jmethodID midHapticStop;
|
||||||
|
|
||||||
/* Accelerometer data storage */
|
/* Accelerometer data storage */
|
||||||
|
@ -746,10 +747,12 @@ JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeSetupJNI)(JNIEnv *env
|
||||||
"pollHapticDevices", "()V");
|
"pollHapticDevices", "()V");
|
||||||
midHapticRun = (*env)->GetStaticMethodID(env, mControllerManagerClass,
|
midHapticRun = (*env)->GetStaticMethodID(env, mControllerManagerClass,
|
||||||
"hapticRun", "(IFI)V");
|
"hapticRun", "(IFI)V");
|
||||||
|
midHapticRumble = (*env)->GetStaticMethodID(env, mControllerManagerClass,
|
||||||
|
"hapticRumble", "(IFFI)V");
|
||||||
midHapticStop = (*env)->GetStaticMethodID(env, mControllerManagerClass,
|
midHapticStop = (*env)->GetStaticMethodID(env, mControllerManagerClass,
|
||||||
"hapticStop", "(I)V");
|
"hapticStop", "(I)V");
|
||||||
|
|
||||||
if (!midPollInputDevices || !midPollHapticDevices || !midHapticRun || !midHapticStop) {
|
if (!midPollInputDevices || !midPollHapticDevices || !midHapticRun || !midHapticRumble || !midHapticStop) {
|
||||||
__android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java callbacks, do you have the latest version of SDLControllerManager.java?");
|
__android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java callbacks, do you have the latest version of SDLControllerManager.java?");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1069,13 +1072,13 @@ JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick)(
|
||||||
JNIEnv *env, jclass jcls,
|
JNIEnv *env, jclass jcls,
|
||||||
jint device_id, jstring device_name, jstring device_desc,
|
jint device_id, jstring device_name, jstring device_desc,
|
||||||
jint vendor_id, jint product_id,
|
jint vendor_id, jint product_id,
|
||||||
jint button_mask, jint naxes, jint axis_mask, jint nhats)
|
jint button_mask, jint naxes, jint axis_mask, jint nhats, jboolean can_rumble)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
const char *name = (*env)->GetStringUTFChars(env, device_name, NULL);
|
const char *name = (*env)->GetStringUTFChars(env, device_name, NULL);
|
||||||
const char *desc = (*env)->GetStringUTFChars(env, device_desc, NULL);
|
const char *desc = (*env)->GetStringUTFChars(env, device_desc, NULL);
|
||||||
|
|
||||||
retval = Android_AddJoystick(device_id, name, desc, vendor_id, product_id, button_mask, naxes, axis_mask, nhats);
|
retval = Android_AddJoystick(device_id, name, desc, vendor_id, product_id, button_mask, naxes, axis_mask, nhats, can_rumble);
|
||||||
|
|
||||||
(*env)->ReleaseStringUTFChars(env, device_name, name);
|
(*env)->ReleaseStringUTFChars(env, device_name, name);
|
||||||
(*env)->ReleaseStringUTFChars(env, device_desc, desc);
|
(*env)->ReleaseStringUTFChars(env, device_desc, desc);
|
||||||
|
@ -2201,6 +2204,12 @@ void Android_JNI_HapticRun(int device_id, float intensity, int length)
|
||||||
(*env)->CallStaticVoidMethod(env, mControllerManagerClass, midHapticRun, device_id, intensity, length);
|
(*env)->CallStaticVoidMethod(env, mControllerManagerClass, midHapticRun, device_id, intensity, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Android_JNI_HapticRumble(int device_id, float low_frequency_intensity, float high_frequency_intensity, int length)
|
||||||
|
{
|
||||||
|
JNIEnv *env = Android_JNI_GetEnv();
|
||||||
|
(*env)->CallStaticVoidMethod(env, mControllerManagerClass, midHapticRumble, device_id, low_frequency_intensity, high_frequency_intensity, length);
|
||||||
|
}
|
||||||
|
|
||||||
void Android_JNI_HapticStop(int device_id)
|
void Android_JNI_HapticStop(int device_id)
|
||||||
{
|
{
|
||||||
JNIEnv *env = Android_JNI_GetEnv();
|
JNIEnv *env = Android_JNI_GetEnv();
|
||||||
|
|
|
@ -91,6 +91,7 @@ void Android_JNI_PollInputDevices(void);
|
||||||
/* Haptic support */
|
/* Haptic support */
|
||||||
void Android_JNI_PollHapticDevices(void);
|
void Android_JNI_PollHapticDevices(void);
|
||||||
void Android_JNI_HapticRun(int device_id, float intensity, int length);
|
void Android_JNI_HapticRun(int device_id, float intensity, int length);
|
||||||
|
void Android_JNI_HapticRumble(int device_id, float low_frequency_intensity, float high_frequency_intensity, int length);
|
||||||
void Android_JNI_HapticStop(int device_id);
|
void Android_JNI_HapticStop(int device_id);
|
||||||
|
|
||||||
/* Video */
|
/* Video */
|
||||||
|
|
|
@ -25,8 +25,6 @@
|
||||||
#include "SDL_syshaptic_c.h"
|
#include "SDL_syshaptic_c.h"
|
||||||
#include "../SDL_syshaptic.h"
|
#include "../SDL_syshaptic.h"
|
||||||
#include "../../core/android/SDL_android.h"
|
#include "../../core/android/SDL_android.h"
|
||||||
#include "../../joystick/SDL_sysjoystick.h" /* For the real SDL_Joystick */
|
|
||||||
#include "../../joystick/android/SDL_sysjoystick_c.h" /* For joystick hwdata */
|
|
||||||
|
|
||||||
typedef struct SDL_hapticlist_item
|
typedef struct SDL_hapticlist_item
|
||||||
{
|
{
|
||||||
|
@ -78,18 +76,6 @@ static SDL_hapticlist_item *HapticByInstanceID(SDL_HapticID instance_id)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_hapticlist_item *HapticByDevId(int device_id)
|
|
||||||
{
|
|
||||||
SDL_hapticlist_item *item;
|
|
||||||
for (item = SDL_hapticlist; item; item = item->next) {
|
|
||||||
if (device_id == item->device_id) {
|
|
||||||
/*SDL_Log("=+=+=+=+=+= HapticByDevId id [%d]", device_id);*/
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_HapticID SDL_SYS_HapticInstanceID(int index)
|
SDL_HapticID SDL_SYS_HapticInstanceID(int index)
|
||||||
{
|
{
|
||||||
SDL_hapticlist_item *item = HapticByOrder(index);
|
SDL_hapticlist_item *item = HapticByOrder(index);
|
||||||
|
@ -142,11 +128,6 @@ static SDL_hapticlist_item *OpenHapticByInstanceID(SDL_Haptic *haptic, SDL_Hapti
|
||||||
return OpenHaptic(haptic, HapticByInstanceID(instance_id));
|
return OpenHaptic(haptic, HapticByInstanceID(instance_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_hapticlist_item *OpenHapticByDevId(SDL_Haptic *haptic, int device_id)
|
|
||||||
{
|
|
||||||
return OpenHaptic(haptic, HapticByDevId(device_id));
|
|
||||||
}
|
|
||||||
|
|
||||||
int SDL_SYS_HapticOpen(SDL_Haptic *haptic)
|
int SDL_SYS_HapticOpen(SDL_Haptic *haptic)
|
||||||
{
|
{
|
||||||
return OpenHapticByInstanceID(haptic, haptic->instance_id) == NULL ? -1 : 0;
|
return OpenHapticByInstanceID(haptic, haptic->instance_id) == NULL ? -1 : 0;
|
||||||
|
@ -159,19 +140,17 @@ int SDL_SYS_HapticMouse(void)
|
||||||
|
|
||||||
int SDL_SYS_JoystickIsHaptic(SDL_Joystick *joystick)
|
int SDL_SYS_JoystickIsHaptic(SDL_Joystick *joystick)
|
||||||
{
|
{
|
||||||
SDL_hapticlist_item *item;
|
return 0;
|
||||||
item = HapticByDevId(((joystick_hwdata *)joystick->hwdata)->device_id);
|
|
||||||
return (item) ? 1 : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SDL_SYS_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick)
|
int SDL_SYS_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick)
|
||||||
{
|
{
|
||||||
return OpenHapticByDevId(haptic, ((joystick_hwdata *)joystick->hwdata)->device_id) == NULL ? -1 : 0;
|
return SDL_Unsupported();
|
||||||
}
|
}
|
||||||
|
|
||||||
int SDL_SYS_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick)
|
int SDL_SYS_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick)
|
||||||
{
|
{
|
||||||
return ((SDL_hapticlist_item *)haptic->hwdata)->device_id == ((joystick_hwdata *)joystick->hwdata)->device_id ? 1 : 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_SYS_HapticClose(SDL_Haptic *haptic)
|
void SDL_SYS_HapticClose(SDL_Haptic *haptic)
|
||||||
|
|
|
@ -301,7 +301,7 @@ int Android_OnHat(int device_id, int hat_id, int x, int y)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Android_AddJoystick(int device_id, const char *name, const char *desc, int vendor_id, int product_id, int button_mask, int naxes, int axis_mask, int nhats)
|
int Android_AddJoystick(int device_id, const char *name, const char *desc, int vendor_id, int product_id, int button_mask, int naxes, int axis_mask, int nhats, SDL_bool can_rumble)
|
||||||
{
|
{
|
||||||
SDL_joylist_item *item;
|
SDL_joylist_item *item;
|
||||||
SDL_JoystickGUID guid;
|
SDL_JoystickGUID guid;
|
||||||
|
@ -372,6 +372,7 @@ int Android_AddJoystick(int device_id, const char *name, const char *desc, int v
|
||||||
}
|
}
|
||||||
item->naxes = naxes;
|
item->naxes = naxes;
|
||||||
item->nhats = nhats;
|
item->nhats = nhats;
|
||||||
|
item->can_rumble = can_rumble;
|
||||||
item->device_instance = SDL_GetNextObjectID();
|
item->device_instance = SDL_GetNextObjectID();
|
||||||
if (!SDL_joylist_tail) {
|
if (!SDL_joylist_tail) {
|
||||||
SDL_joylist = SDL_joylist_tail = item;
|
SDL_joylist = SDL_joylist_tail = item;
|
||||||
|
@ -578,14 +579,26 @@ static int ANDROID_JoystickOpen(SDL_Joystick *joystick, int device_index)
|
||||||
joystick->nbuttons = item->nbuttons;
|
joystick->nbuttons = item->nbuttons;
|
||||||
joystick->naxes = item->naxes;
|
joystick->naxes = item->naxes;
|
||||||
|
|
||||||
|
if (item->can_rumble) {
|
||||||
|
SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, SDL_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ANDROID_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
|
static int ANDROID_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
|
||||||
{
|
{
|
||||||
|
SDL_joylist_item *item = (SDL_joylist_item *)joystick->hwdata;
|
||||||
|
if (!item->can_rumble) {
|
||||||
return SDL_Unsupported();
|
return SDL_Unsupported();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float low_frequency_intensity = (float)low_frequency_rumble / SDL_MAX_UINT16;
|
||||||
|
float high_frequency_intensity = (float)high_frequency_rumble / SDL_MAX_UINT16;
|
||||||
|
Android_JNI_HapticRumble(item->device_id, low_frequency_intensity, high_frequency_intensity, 5000);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int ANDROID_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
|
static int ANDROID_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
|
||||||
{
|
{
|
||||||
return SDL_Unsupported();
|
return SDL_Unsupported();
|
||||||
|
|
|
@ -32,7 +32,7 @@ extern int Android_OnPadDown(int device_id, int keycode);
|
||||||
extern int Android_OnPadUp(int device_id, int keycode);
|
extern int Android_OnPadUp(int device_id, int keycode);
|
||||||
extern int Android_OnJoy(int device_id, int axisnum, float value);
|
extern int Android_OnJoy(int device_id, int axisnum, float value);
|
||||||
extern int Android_OnHat(int device_id, int hat_id, int x, int y);
|
extern int Android_OnHat(int device_id, int hat_id, int x, int y);
|
||||||
extern int Android_AddJoystick(int device_id, const char *name, const char *desc, int vendor_id, int product_id, int button_mask, int naxes, int axis_mask, int nhats);
|
extern int Android_AddJoystick(int device_id, const char *name, const char *desc, int vendor_id, int product_id, int button_mask, int naxes, int axis_mask, int nhats, SDL_bool can_rumble);
|
||||||
extern int Android_RemoveJoystick(int device_id);
|
extern int Android_RemoveJoystick(int device_id);
|
||||||
|
|
||||||
/* A linked list of available joysticks */
|
/* A linked list of available joysticks */
|
||||||
|
@ -45,6 +45,7 @@ typedef struct SDL_joylist_item
|
||||||
SDL_Joystick *joystick;
|
SDL_Joystick *joystick;
|
||||||
int nbuttons, naxes, nhats;
|
int nbuttons, naxes, nhats;
|
||||||
int dpad_state;
|
int dpad_state;
|
||||||
|
SDL_bool can_rumble;
|
||||||
|
|
||||||
struct SDL_joylist_item *next;
|
struct SDL_joylist_item *next;
|
||||||
} SDL_joylist_item;
|
} SDL_joylist_item;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue