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="com.android.providers.tv.permission.READ_EPG_DATA"/>
|
||||
<uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA"/>
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
|
||||
<application
|
||||
android:name=".DolphinApplication"
|
||||
|
|
|
@ -25,6 +25,7 @@ Triggers/R = `Axis 21`
|
|||
Triggers/L-Analog = `Axis 20`
|
||||
Triggers/R-Analog = `Axis 21`
|
||||
Triggers/Threshold = 90,000000
|
||||
Rumble/Motor = `Rumble 700`
|
||||
[GCPad2]
|
||||
Device = Android/1/Touchscreen
|
||||
Buttons/A = `Button 0`
|
||||
|
@ -52,6 +53,7 @@ Triggers/R = `Axis 21`
|
|||
Triggers/L-Analog = `Axis 20`
|
||||
Triggers/R-Analog = `Axis 21`
|
||||
Triggers/Threshold = 90,000000
|
||||
Rumble/Motor = `Rumble 700`
|
||||
[GCPad3]
|
||||
Device = Android/2/Touchscreen
|
||||
Buttons/A = `Button 0`
|
||||
|
@ -79,6 +81,7 @@ Triggers/R = `Axis 21`
|
|||
Triggers/L-Analog = `Axis 20`
|
||||
Triggers/R-Analog = `Axis 21`
|
||||
Triggers/Threshold = 90,000000
|
||||
Rumble/Motor = `Rumble 700`
|
||||
[GCPad4]
|
||||
Device = Android/3/Touchscreen
|
||||
Buttons/A = `Button 0`
|
||||
|
@ -106,3 +109,4 @@ Triggers/R = `Axis 21`
|
|||
Triggers/L-Analog = `Axis 20`
|
||||
Triggers/R-Analog = `Axis 21`
|
||||
Triggers/Threshold = 90,000000
|
||||
Rumble/Motor = `Rumble 700`
|
||||
|
|
|
@ -133,6 +133,7 @@ Turntable/Effect/Dial = `Axis 621`
|
|||
Turntable/Crossfade/Left = `Axis 623`
|
||||
Turntable/Crossfade/Right = `Axis 624`
|
||||
Source = 1
|
||||
Rumble/Motor = `Rumble 700`
|
||||
[Wiimote2]
|
||||
Device = Android/5/Touchscreen
|
||||
Buttons/A = `Button 100`
|
||||
|
@ -268,6 +269,7 @@ Turntable/Effect/Dial = `Axis 621`
|
|||
Turntable/Crossfade/Left = `Axis 623`
|
||||
Turntable/Crossfade/Right = `Axis 624`
|
||||
Source = 0
|
||||
Rumble/Motor = `Rumble 700`
|
||||
[Wiimote3]
|
||||
Device = Android/6/Touchscreen
|
||||
Buttons/A = `Button 100`
|
||||
|
@ -403,6 +405,7 @@ Turntable/Effect/Dial = `Axis 621`
|
|||
Turntable/Crossfade/Left = `Axis 623`
|
||||
Turntable/Crossfade/Right = `Axis 624`
|
||||
Source = 0
|
||||
Rumble/Motor = `Rumble 700`
|
||||
[Wiimote4]
|
||||
Device = Android/7/Touchscreen
|
||||
Buttons/A = `Button 100`
|
||||
|
@ -538,3 +541,4 @@ Turntable/Effect/Dial = `Axis 621`
|
|||
Turntable/Crossfade/Left = `Axis 623`
|
||||
Turntable/Crossfade/Right = `Axis 624`
|
||||
Source = 0
|
||||
Rumble/Motor = `Rumble 700`
|
||||
|
|
|
@ -7,6 +7,11 @@
|
|||
package org.dolphinemu.dolphinemu;
|
||||
|
||||
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 org.dolphinemu.dolphinemu.activities.EmulationActivity;
|
||||
|
@ -225,6 +230,39 @@ public final class NativeLibrary
|
|||
*/
|
||||
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 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_CHANGE_DISC = 23;
|
||||
public static final int MENU_ACTION_JOYSTICK_REL_CENTER = 24;
|
||||
public static final int MENU_ACTION_RUMBLE = 25;
|
||||
|
||||
|
||||
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_emulation_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,
|
||||
|
@ -473,6 +475,8 @@ public final class EmulationActivity extends AppCompatActivity
|
|||
// Populate the checkbox value for joystick center on touch
|
||||
menu.findItem(R.id.menu_emulation_joystick_rel_center)
|
||||
.setChecked(mPreferences.getBoolean("joystickRelCenter", true));
|
||||
menu.findItem(R.id.menu_emulation_rumble)
|
||||
.setChecked(mPreferences.getBoolean("phoneRumble", true));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -504,7 +508,11 @@ public final class EmulationActivity extends AppCompatActivity
|
|||
case MENU_ACTION_JOYSTICK_REL_CENTER:
|
||||
item.setChecked(!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();
|
||||
}
|
||||
|
||||
private void toggleRumble(boolean state)
|
||||
{
|
||||
final SharedPreferences.Editor editor = mPreferences.edit();
|
||||
editor.putBoolean("phoneRumble", state);
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
|
||||
private void editControlsPlacement()
|
||||
{
|
||||
|
|
|
@ -98,6 +98,10 @@
|
|||
android:id="@+id/menu_emulation_joystick_rel_center"
|
||||
android:checkable="true"
|
||||
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>
|
||||
</item>
|
||||
|
||||
|
|
|
@ -98,11 +98,16 @@
|
|||
android:id="@+id/menu_emulation_joystick_rel_center"
|
||||
android:checkable="true"
|
||||
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>
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_emulation_choose_controller"
|
||||
android:title="@string/emulation_choose_controller"/>
|
||||
|
||||
</menu>
|
||||
</item>
|
||||
|
||||
|
|
|
@ -271,6 +271,7 @@
|
|||
<string name="emulation_toggle_all">Toggle All</string>
|
||||
<string name="emulation_control_scale">Adjust Scale</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_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>
|
||||
|
|
|
@ -52,6 +52,8 @@ std::vector<std::string> configStrings = {
|
|||
"TurntableEuphoria", "TurntableLeftTLeft", "TurntableLeftTRight", "TurntableRightTLeft",
|
||||
"TurntableRightTRight", "TurntableUp", "TurntableDown", "TurntableLeft", "TurntableRight",
|
||||
"TurntableEffDial", "TurntableCrossLeft", "TurntableCrossRight",
|
||||
// Rumble
|
||||
"Rumble",
|
||||
};
|
||||
std::vector<ButtonType> configTypes = {
|
||||
// GC
|
||||
|
@ -95,6 +97,8 @@ std::vector<ButtonType> configTypes = {
|
|||
TURNTABLE_TABLE_RIGHT_RIGHT, TURNTABLE_STICK_UP, TURNTABLE_STICK_DOWN, TURNTABLE_STICK_LEFT,
|
||||
TURNTABLE_STICK_RIGHT, TURNTABLE_EFFECT_DIAL, TURNTABLE_CROSSFADE_LEFT,
|
||||
TURNTABLE_CROSSFADE_RIGHT,
|
||||
// Rumble
|
||||
RUMBLE,
|
||||
};
|
||||
|
||||
static void AddBind(const std::string& dev, sBind* bind)
|
||||
|
@ -462,4 +466,5 @@ float InputDevice::AxisValue(int padID, ButtonType axis)
|
|||
else
|
||||
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_LEFT = 623,
|
||||
TURNTABLE_CROSSFADE_RIGHT = 624,
|
||||
// Rumble
|
||||
RUMBLE = 700,
|
||||
};
|
||||
enum ButtonState
|
||||
{
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
// Refer to the license.txt file included.
|
||||
|
||||
#include "InputCommon/ControllerInterface/Android/Android.h"
|
||||
#include <jni/AndroidCommon/IDCache.h>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
||||
|
||||
namespace ciface
|
||||
|
@ -190,6 +192,8 @@ Touchscreen::Touchscreen(int padID) : _padID(padID)
|
|||
new Axis(_padID, ButtonManager::TURNTABLE_CROSSFADE_RIGHT));
|
||||
AddAnalogInputs(new Axis(_padID, ButtonManager::TURNTABLE_EFFECT_DIAL),
|
||||
new Axis(_padID, ButtonManager::TURNTABLE_EFFECT_DIAL));
|
||||
// Rumble
|
||||
AddOutput(new Motor(_padID, ButtonManager::RUMBLE));
|
||||
}
|
||||
// Buttons and stuff
|
||||
|
||||
|
@ -215,5 +219,34 @@ ControlState Touchscreen::Axis::GetState() const
|
|||
{
|
||||
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 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:
|
||||
Touchscreen(int padID);
|
||||
|
|
Loading…
Reference in New Issue