Android: Add rumble for phone
This currently only supports using the internal vibrate on a phone for rumble.
This commit is contained in:
parent
3405c7d420
commit
126ff8dc5f
|
@ -18,6 +18,7 @@
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<uses-permission android:name="com.android.providers.tv.permission.READ_EPG_DATA"/>
|
<uses-permission android:name="com.android.providers.tv.permission.READ_EPG_DATA"/>
|
||||||
<uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA"/>
|
<uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA"/>
|
||||||
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".DolphinApplication"
|
android:name=".DolphinApplication"
|
||||||
|
|
|
@ -25,6 +25,7 @@ Triggers/R = `Axis 21`
|
||||||
Triggers/L-Analog = `Axis 20`
|
Triggers/L-Analog = `Axis 20`
|
||||||
Triggers/R-Analog = `Axis 21`
|
Triggers/R-Analog = `Axis 21`
|
||||||
Triggers/Threshold = 90,000000
|
Triggers/Threshold = 90,000000
|
||||||
|
Rumble/Motor = `Rumble 700`
|
||||||
[GCPad2]
|
[GCPad2]
|
||||||
Device = Android/1/Touchscreen
|
Device = Android/1/Touchscreen
|
||||||
Buttons/A = `Button 0`
|
Buttons/A = `Button 0`
|
||||||
|
@ -52,6 +53,7 @@ Triggers/R = `Axis 21`
|
||||||
Triggers/L-Analog = `Axis 20`
|
Triggers/L-Analog = `Axis 20`
|
||||||
Triggers/R-Analog = `Axis 21`
|
Triggers/R-Analog = `Axis 21`
|
||||||
Triggers/Threshold = 90,000000
|
Triggers/Threshold = 90,000000
|
||||||
|
Rumble/Motor = `Rumble 700`
|
||||||
[GCPad3]
|
[GCPad3]
|
||||||
Device = Android/2/Touchscreen
|
Device = Android/2/Touchscreen
|
||||||
Buttons/A = `Button 0`
|
Buttons/A = `Button 0`
|
||||||
|
@ -79,6 +81,7 @@ Triggers/R = `Axis 21`
|
||||||
Triggers/L-Analog = `Axis 20`
|
Triggers/L-Analog = `Axis 20`
|
||||||
Triggers/R-Analog = `Axis 21`
|
Triggers/R-Analog = `Axis 21`
|
||||||
Triggers/Threshold = 90,000000
|
Triggers/Threshold = 90,000000
|
||||||
|
Rumble/Motor = `Rumble 700`
|
||||||
[GCPad4]
|
[GCPad4]
|
||||||
Device = Android/3/Touchscreen
|
Device = Android/3/Touchscreen
|
||||||
Buttons/A = `Button 0`
|
Buttons/A = `Button 0`
|
||||||
|
@ -106,3 +109,4 @@ Triggers/R = `Axis 21`
|
||||||
Triggers/L-Analog = `Axis 20`
|
Triggers/L-Analog = `Axis 20`
|
||||||
Triggers/R-Analog = `Axis 21`
|
Triggers/R-Analog = `Axis 21`
|
||||||
Triggers/Threshold = 90,000000
|
Triggers/Threshold = 90,000000
|
||||||
|
Rumble/Motor = `Rumble 700`
|
||||||
|
|
|
@ -133,6 +133,7 @@ Turntable/Effect/Dial = `Axis 621`
|
||||||
Turntable/Crossfade/Left = `Axis 623`
|
Turntable/Crossfade/Left = `Axis 623`
|
||||||
Turntable/Crossfade/Right = `Axis 624`
|
Turntable/Crossfade/Right = `Axis 624`
|
||||||
Source = 1
|
Source = 1
|
||||||
|
Rumble/Motor = `Rumble 700`
|
||||||
[Wiimote2]
|
[Wiimote2]
|
||||||
Device = Android/5/Touchscreen
|
Device = Android/5/Touchscreen
|
||||||
Buttons/A = `Button 100`
|
Buttons/A = `Button 100`
|
||||||
|
@ -268,6 +269,7 @@ Turntable/Effect/Dial = `Axis 621`
|
||||||
Turntable/Crossfade/Left = `Axis 623`
|
Turntable/Crossfade/Left = `Axis 623`
|
||||||
Turntable/Crossfade/Right = `Axis 624`
|
Turntable/Crossfade/Right = `Axis 624`
|
||||||
Source = 0
|
Source = 0
|
||||||
|
Rumble/Motor = `Rumble 700`
|
||||||
[Wiimote3]
|
[Wiimote3]
|
||||||
Device = Android/6/Touchscreen
|
Device = Android/6/Touchscreen
|
||||||
Buttons/A = `Button 100`
|
Buttons/A = `Button 100`
|
||||||
|
@ -403,6 +405,7 @@ Turntable/Effect/Dial = `Axis 621`
|
||||||
Turntable/Crossfade/Left = `Axis 623`
|
Turntable/Crossfade/Left = `Axis 623`
|
||||||
Turntable/Crossfade/Right = `Axis 624`
|
Turntable/Crossfade/Right = `Axis 624`
|
||||||
Source = 0
|
Source = 0
|
||||||
|
Rumble/Motor = `Rumble 700`
|
||||||
[Wiimote4]
|
[Wiimote4]
|
||||||
Device = Android/7/Touchscreen
|
Device = Android/7/Touchscreen
|
||||||
Buttons/A = `Button 100`
|
Buttons/A = `Button 100`
|
||||||
|
@ -538,3 +541,4 @@ Turntable/Effect/Dial = `Axis 621`
|
||||||
Turntable/Crossfade/Left = `Axis 623`
|
Turntable/Crossfade/Left = `Axis 623`
|
||||||
Turntable/Crossfade/Right = `Axis 624`
|
Turntable/Crossfade/Right = `Axis 624`
|
||||||
Source = 0
|
Source = 0
|
||||||
|
Rumble/Motor = `Rumble 700`
|
||||||
|
|
|
@ -7,6 +7,11 @@
|
||||||
package org.dolphinemu.dolphinemu;
|
package org.dolphinemu.dolphinemu;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.VibrationEffect;
|
||||||
|
import android.os.Vibrator;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.activities.EmulationActivity;
|
import org.dolphinemu.dolphinemu.activities.EmulationActivity;
|
||||||
|
@ -225,6 +230,39 @@ public final class NativeLibrary
|
||||||
*/
|
*/
|
||||||
public static native void onGamePadMoveEvent(String Device, int Axis, float Value);
|
public static native void onGamePadMoveEvent(String Device, int Axis, float Value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rumble sent from native. Currently only supports phone rumble.
|
||||||
|
*
|
||||||
|
* @param padID Ignored for now. Future use would be to pass rumble to a connected controller
|
||||||
|
* @param state Ignored for now since phone rumble can't just be 'turned' on/off
|
||||||
|
*/
|
||||||
|
public static void rumble(int padID, double state)
|
||||||
|
{
|
||||||
|
final EmulationActivity emulationActivity = sEmulationActivity.get();
|
||||||
|
if (emulationActivity == null)
|
||||||
|
{
|
||||||
|
Log.warning("[NativeLibrary] EmulationActivity is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PreferenceManager.getDefaultSharedPreferences(emulationActivity)
|
||||||
|
.getBoolean("phoneRumble", true))
|
||||||
|
{
|
||||||
|
Vibrator vibrator = (Vibrator) emulationActivity.getSystemService(Context.VIBRATOR_SERVICE);
|
||||||
|
if (vibrator != null && vibrator.hasVibrator())
|
||||||
|
{
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
|
||||||
|
{
|
||||||
|
vibrator.vibrate(VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vibrator.vibrate(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static native String GetUserSetting(String gameID, String Section, String Key);
|
public static native String GetUserSetting(String gameID, String Section, String Key);
|
||||||
|
|
||||||
public static native void SetUserSetting(String gameID, String Section, String Key, String Value);
|
public static native void SetUserSetting(String gameID, String Section, String Key, String Value);
|
||||||
|
|
|
@ -124,6 +124,7 @@ public final class EmulationActivity extends AppCompatActivity
|
||||||
public static final int MENU_ACTION_EXIT = 22;
|
public static final int MENU_ACTION_EXIT = 22;
|
||||||
public static final int MENU_ACTION_CHANGE_DISC = 23;
|
public static final int MENU_ACTION_CHANGE_DISC = 23;
|
||||||
public static final int MENU_ACTION_JOYSTICK_REL_CENTER = 24;
|
public static final int MENU_ACTION_JOYSTICK_REL_CENTER = 24;
|
||||||
|
public static final int MENU_ACTION_RUMBLE = 25;
|
||||||
|
|
||||||
|
|
||||||
private static SparseIntArray buttonsActionsMap = new SparseIntArray();
|
private static SparseIntArray buttonsActionsMap = new SparseIntArray();
|
||||||
|
@ -163,6 +164,7 @@ public final class EmulationActivity extends AppCompatActivity
|
||||||
buttonsActionsMap.append(R.id.menu_exit, EmulationActivity.MENU_ACTION_EXIT);
|
buttonsActionsMap.append(R.id.menu_exit, EmulationActivity.MENU_ACTION_EXIT);
|
||||||
buttonsActionsMap.append(R.id.menu_emulation_joystick_rel_center,
|
buttonsActionsMap.append(R.id.menu_emulation_joystick_rel_center,
|
||||||
EmulationActivity.MENU_ACTION_JOYSTICK_REL_CENTER);
|
EmulationActivity.MENU_ACTION_JOYSTICK_REL_CENTER);
|
||||||
|
buttonsActionsMap.append(R.id.menu_emulation_rumble, EmulationActivity.MENU_ACTION_RUMBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void launch(FragmentActivity activity, GameFile gameFile, int position,
|
public static void launch(FragmentActivity activity, GameFile gameFile, int position,
|
||||||
|
@ -473,6 +475,8 @@ public final class EmulationActivity extends AppCompatActivity
|
||||||
// Populate the checkbox value for joystick center on touch
|
// Populate the checkbox value for joystick center on touch
|
||||||
menu.findItem(R.id.menu_emulation_joystick_rel_center)
|
menu.findItem(R.id.menu_emulation_joystick_rel_center)
|
||||||
.setChecked(mPreferences.getBoolean("joystickRelCenter", true));
|
.setChecked(mPreferences.getBoolean("joystickRelCenter", true));
|
||||||
|
menu.findItem(R.id.menu_emulation_rumble)
|
||||||
|
.setChecked(mPreferences.getBoolean("phoneRumble", true));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -504,7 +508,11 @@ public final class EmulationActivity extends AppCompatActivity
|
||||||
case MENU_ACTION_JOYSTICK_REL_CENTER:
|
case MENU_ACTION_JOYSTICK_REL_CENTER:
|
||||||
item.setChecked(!item.isChecked());
|
item.setChecked(!item.isChecked());
|
||||||
toggleJoystickRelCenter(item.isChecked());
|
toggleJoystickRelCenter(item.isChecked());
|
||||||
return;
|
break;
|
||||||
|
case MENU_ACTION_RUMBLE:
|
||||||
|
item.setChecked(!item.isChecked());
|
||||||
|
toggleRumble(item.isChecked());
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -636,6 +644,13 @@ public final class EmulationActivity extends AppCompatActivity
|
||||||
editor.commit();
|
editor.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void toggleRumble(boolean state)
|
||||||
|
{
|
||||||
|
final SharedPreferences.Editor editor = mPreferences.edit();
|
||||||
|
editor.putBoolean("phoneRumble", state);
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void editControlsPlacement()
|
private void editControlsPlacement()
|
||||||
{
|
{
|
||||||
|
|
|
@ -98,6 +98,10 @@
|
||||||
android:id="@+id/menu_emulation_joystick_rel_center"
|
android:id="@+id/menu_emulation_joystick_rel_center"
|
||||||
android:checkable="true"
|
android:checkable="true"
|
||||||
android:title="@string/emulation_control_joystick_rel_center"/>
|
android:title="@string/emulation_control_joystick_rel_center"/>
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_emulation_rumble"
|
||||||
|
android:checkable="true"
|
||||||
|
android:title="@string/emulation_control_rumble"/>
|
||||||
</menu>
|
</menu>
|
||||||
</item>
|
</item>
|
||||||
|
|
||||||
|
|
|
@ -98,11 +98,16 @@
|
||||||
android:id="@+id/menu_emulation_joystick_rel_center"
|
android:id="@+id/menu_emulation_joystick_rel_center"
|
||||||
android:checkable="true"
|
android:checkable="true"
|
||||||
android:title="@string/emulation_control_joystick_rel_center"/>
|
android:title="@string/emulation_control_joystick_rel_center"/>
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_emulation_rumble"
|
||||||
|
android:checkable="true"
|
||||||
|
android:title="@string/emulation_control_rumble"/>
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/menu_emulation_choose_controller"
|
android:id="@+id/menu_emulation_choose_controller"
|
||||||
android:title="@string/emulation_choose_controller"/>
|
android:title="@string/emulation_choose_controller"/>
|
||||||
|
|
||||||
</menu>
|
</menu>
|
||||||
</item>
|
</item>
|
||||||
|
|
||||||
|
|
|
@ -271,6 +271,7 @@
|
||||||
<string name="emulation_toggle_all">Toggle All</string>
|
<string name="emulation_toggle_all">Toggle All</string>
|
||||||
<string name="emulation_control_scale">Adjust Scale</string>
|
<string name="emulation_control_scale">Adjust Scale</string>
|
||||||
<string name="emulation_control_joystick_rel_center">Relative Stick Center</string>
|
<string name="emulation_control_joystick_rel_center">Relative Stick Center</string>
|
||||||
|
<string name="emulation_control_rumble">Rumble</string>
|
||||||
<string name="emulation_choose_controller">Choose Controller</string>
|
<string name="emulation_choose_controller">Choose Controller</string>
|
||||||
<string name="emulation_controller_changed">You may have to reload the game after changing extensions.</string>
|
<string name="emulation_controller_changed">You may have to reload the game after changing extensions.</string>
|
||||||
<string name="emulation_touch_button_help">To change the button layout, open the menu -> Configure Controls -> Edit Layout</string>
|
<string name="emulation_touch_button_help">To change the button layout, open the menu -> Configure Controls -> Edit Layout</string>
|
||||||
|
|
|
@ -52,6 +52,8 @@ std::vector<std::string> configStrings = {
|
||||||
"TurntableEuphoria", "TurntableLeftTLeft", "TurntableLeftTRight", "TurntableRightTLeft",
|
"TurntableEuphoria", "TurntableLeftTLeft", "TurntableLeftTRight", "TurntableRightTLeft",
|
||||||
"TurntableRightTRight", "TurntableUp", "TurntableDown", "TurntableLeft", "TurntableRight",
|
"TurntableRightTRight", "TurntableUp", "TurntableDown", "TurntableLeft", "TurntableRight",
|
||||||
"TurntableEffDial", "TurntableCrossLeft", "TurntableCrossRight",
|
"TurntableEffDial", "TurntableCrossLeft", "TurntableCrossRight",
|
||||||
|
// Rumble
|
||||||
|
"Rumble",
|
||||||
};
|
};
|
||||||
std::vector<ButtonType> configTypes = {
|
std::vector<ButtonType> configTypes = {
|
||||||
// GC
|
// GC
|
||||||
|
@ -95,6 +97,8 @@ std::vector<ButtonType> configTypes = {
|
||||||
TURNTABLE_TABLE_RIGHT_RIGHT, TURNTABLE_STICK_UP, TURNTABLE_STICK_DOWN, TURNTABLE_STICK_LEFT,
|
TURNTABLE_TABLE_RIGHT_RIGHT, TURNTABLE_STICK_UP, TURNTABLE_STICK_DOWN, TURNTABLE_STICK_LEFT,
|
||||||
TURNTABLE_STICK_RIGHT, TURNTABLE_EFFECT_DIAL, TURNTABLE_CROSSFADE_LEFT,
|
TURNTABLE_STICK_RIGHT, TURNTABLE_EFFECT_DIAL, TURNTABLE_CROSSFADE_LEFT,
|
||||||
TURNTABLE_CROSSFADE_RIGHT,
|
TURNTABLE_CROSSFADE_RIGHT,
|
||||||
|
// Rumble
|
||||||
|
RUMBLE,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void AddBind(const std::string& dev, sBind* bind)
|
static void AddBind(const std::string& dev, sBind* bind)
|
||||||
|
@ -462,4 +466,5 @@ float InputDevice::AxisValue(int padID, ButtonType axis)
|
||||||
else
|
else
|
||||||
return _buttons[binding->second->_buttontype] == BUTTON_PRESSED ? 1.0f : 0.0f;
|
return _buttons[binding->second->_buttontype] == BUTTON_PRESSED ? 1.0f : 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -176,6 +176,8 @@ enum ButtonType
|
||||||
TURNTABLE_CROSSFADE = 622, // To Be Used on Java Side
|
TURNTABLE_CROSSFADE = 622, // To Be Used on Java Side
|
||||||
TURNTABLE_CROSSFADE_LEFT = 623,
|
TURNTABLE_CROSSFADE_LEFT = 623,
|
||||||
TURNTABLE_CROSSFADE_RIGHT = 624,
|
TURNTABLE_CROSSFADE_RIGHT = 624,
|
||||||
|
// Rumble
|
||||||
|
RUMBLE = 700,
|
||||||
};
|
};
|
||||||
enum ButtonState
|
enum ButtonState
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include "InputCommon/ControllerInterface/Android/Android.h"
|
#include "InputCommon/ControllerInterface/Android/Android.h"
|
||||||
|
#include <jni/AndroidCommon/IDCache.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <thread>
|
||||||
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
||||||
|
|
||||||
namespace ciface
|
namespace ciface
|
||||||
|
@ -190,6 +192,8 @@ Touchscreen::Touchscreen(int padID) : _padID(padID)
|
||||||
new Axis(_padID, ButtonManager::TURNTABLE_CROSSFADE_RIGHT));
|
new Axis(_padID, ButtonManager::TURNTABLE_CROSSFADE_RIGHT));
|
||||||
AddAnalogInputs(new Axis(_padID, ButtonManager::TURNTABLE_EFFECT_DIAL),
|
AddAnalogInputs(new Axis(_padID, ButtonManager::TURNTABLE_EFFECT_DIAL),
|
||||||
new Axis(_padID, ButtonManager::TURNTABLE_EFFECT_DIAL));
|
new Axis(_padID, ButtonManager::TURNTABLE_EFFECT_DIAL));
|
||||||
|
// Rumble
|
||||||
|
AddOutput(new Motor(_padID, ButtonManager::RUMBLE));
|
||||||
}
|
}
|
||||||
// Buttons and stuff
|
// Buttons and stuff
|
||||||
|
|
||||||
|
@ -215,5 +219,34 @@ ControlState Touchscreen::Axis::GetState() const
|
||||||
{
|
{
|
||||||
return ButtonManager::GetAxisValue(_padID, _index) * _neg;
|
return ButtonManager::GetAxisValue(_padID, _index) * _neg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Touchscreen::Motor::~Motor()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Touchscreen::Motor::GetName() const
|
||||||
|
{
|
||||||
|
std::ostringstream ss;
|
||||||
|
ss << "Rumble " << (int)_index;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Touchscreen::Motor::SetState(ControlState state)
|
||||||
|
{
|
||||||
|
if (state > 0)
|
||||||
|
{
|
||||||
|
std::thread(Rumble, _padID, state).detach();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Touchscreen::Motor::Rumble(int padID, double state)
|
||||||
|
{
|
||||||
|
JNIEnv* env;
|
||||||
|
IDCache::GetJavaVM()->AttachCurrentThread(&env, nullptr);
|
||||||
|
jmethodID rumbleMethod =
|
||||||
|
env->GetStaticMethodID(IDCache::GetNativeLibraryClass(), "rumble", "(ID)V");
|
||||||
|
env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), rumbleMethod, padID, state);
|
||||||
|
IDCache::GetJavaVM()->DetachCurrentThread();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,19 @@ private:
|
||||||
const ButtonManager::ButtonType _index;
|
const ButtonManager::ButtonType _index;
|
||||||
const float _neg;
|
const float _neg;
|
||||||
};
|
};
|
||||||
|
class Motor : public Core::Device::Output
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Motor(int padID, ButtonManager::ButtonType index) : _padID(padID), _index(index) {}
|
||||||
|
~Motor();
|
||||||
|
std::string GetName() const override;
|
||||||
|
void SetState(ControlState state) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const int _padID;
|
||||||
|
const ButtonManager::ButtonType _index;
|
||||||
|
static void Rumble(int padID, double state);
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Touchscreen(int padID);
|
Touchscreen(int padID);
|
||||||
|
|
Loading…
Reference in New Issue