diff --git a/Source/Android/app/src/main/AndroidManifest.xml b/Source/Android/app/src/main/AndroidManifest.xml index 975a493860..147b658ad3 100644 --- a/Source/Android/app/src/main/AndroidManifest.xml +++ b/Source/Android/app/src/main/AndroidManifest.xml @@ -18,6 +18,7 @@ + = 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); diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java index 221d3ee399..7eb8430935 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java @@ -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() { diff --git a/Source/Android/app/src/main/res/menu/menu_emulation.xml b/Source/Android/app/src/main/res/menu/menu_emulation.xml index bbb418018c..0a9ccfd25d 100644 --- a/Source/Android/app/src/main/res/menu/menu_emulation.xml +++ b/Source/Android/app/src/main/res/menu/menu_emulation.xml @@ -98,6 +98,10 @@ android:id="@+id/menu_emulation_joystick_rel_center" android:checkable="true" android:title="@string/emulation_control_joystick_rel_center"/> + diff --git a/Source/Android/app/src/main/res/menu/menu_emulation_wii.xml b/Source/Android/app/src/main/res/menu/menu_emulation_wii.xml index 87c61eefc0..f0cbc6024a 100644 --- a/Source/Android/app/src/main/res/menu/menu_emulation_wii.xml +++ b/Source/Android/app/src/main/res/menu/menu_emulation_wii.xml @@ -98,11 +98,16 @@ android:id="@+id/menu_emulation_joystick_rel_center" android:checkable="true" android:title="@string/emulation_control_joystick_rel_center"/> + + diff --git a/Source/Android/app/src/main/res/values/strings.xml b/Source/Android/app/src/main/res/values/strings.xml index 52627892cb..c1bf44b837 100644 --- a/Source/Android/app/src/main/res/values/strings.xml +++ b/Source/Android/app/src/main/res/values/strings.xml @@ -271,6 +271,7 @@ Toggle All Adjust Scale Relative Stick Center + Rumble Choose Controller You may have to reload the game after changing extensions. To change the button layout, open the menu -> Configure Controls -> Edit Layout diff --git a/Source/Android/jni/ButtonManager.cpp b/Source/Android/jni/ButtonManager.cpp index 6f6b812494..8490561c0f 100644 --- a/Source/Android/jni/ButtonManager.cpp +++ b/Source/Android/jni/ButtonManager.cpp @@ -52,6 +52,8 @@ std::vector configStrings = { "TurntableEuphoria", "TurntableLeftTLeft", "TurntableLeftTRight", "TurntableRightTLeft", "TurntableRightTRight", "TurntableUp", "TurntableDown", "TurntableLeft", "TurntableRight", "TurntableEffDial", "TurntableCrossLeft", "TurntableCrossRight", + // Rumble + "Rumble", }; std::vector configTypes = { // GC @@ -95,6 +97,8 @@ std::vector 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; } + } diff --git a/Source/Android/jni/ButtonManager.h b/Source/Android/jni/ButtonManager.h index c65d8180f0..b9744f516c 100644 --- a/Source/Android/jni/ButtonManager.h +++ b/Source/Android/jni/ButtonManager.h @@ -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 { diff --git a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp index 983108f356..b5faf422de 100644 --- a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp @@ -3,7 +3,9 @@ // Refer to the license.txt file included. #include "InputCommon/ControllerInterface/Android/Android.h" +#include #include +#include #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(); +} } } diff --git a/Source/Core/InputCommon/ControllerInterface/Android/Android.h b/Source/Core/InputCommon/ControllerInterface/Android/Android.h index bf588719c2..deb23539ce 100644 --- a/Source/Core/InputCommon/ControllerInterface/Android/Android.h +++ b/Source/Core/InputCommon/ControllerInterface/Android/Android.h @@ -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);