diff --git a/Source/Android/app/src/main/AndroidManifest.xml b/Source/Android/app/src/main/AndroidManifest.xml index 0ba4bc2b51..f9554dbc73 100644 --- a/Source/Android/app/src/main/AndroidManifest.xml +++ b/Source/Android/app/src/main/AndroidManifest.xml @@ -4,6 +4,12 @@ + + diff --git a/Source/Android/app/src/main/assets/WiimoteNew.ini b/Source/Android/app/src/main/assets/WiimoteNew.ini index 2ebd9d61d9..933c63e3ed 100644 --- a/Source/Android/app/src/main/assets/WiimoteNew.ini +++ b/Source/Android/app/src/main/assets/WiimoteNew.ini @@ -99,7 +99,7 @@ Guitar/Stick/Down = `Axis 411` Guitar/Stick/Left = `Axis 412` Guitar/Stick/Right = `Axis 413` Guitar/Stick/Radius = 100,000000 -Guitar/Whammy/Bar = `Axis = 414` +Guitar/Whammy/Bar = `Axis 414` Drums/Buttons/- = `Button 500` Drums/Buttons/+ = `Button 501` Drums/Pads/Red = `Button 502` @@ -135,6 +135,18 @@ Turntable/Stick/Radius = 100,000000 Turntable/Effect/Dial = `Axis 621` Turntable/Crossfade/Left = `Axis 623` Turntable/Crossfade/Right = `Axis 624` +IMUAccelerometer/Left = `Axis 625` +IMUAccelerometer/Right = `Axis 626` +IMUAccelerometer/Forward = `Axis 627` +IMUAccelerometer/Backward = `Axis 628` +IMUAccelerometer/Up = `Axis 629` +IMUAccelerometer/Down = `Axis 630` +IMUGyroscope/Pitch Up = `Axis 631` +IMUGyroscope/Pitch Down = `Axis 632` +IMUGyroscope/Roll Left = `Axis 633` +IMUGyroscope/Roll Right = `Axis 634` +IMUGyroscope/Yaw Left = `Axis 635` +IMUGyroscope/Yaw Right = `Axis 636` Source = 1 Rumble/Motor = `Rumble 700` [Wiimote2] @@ -238,7 +250,7 @@ Guitar/Stick/Down = `Axis 411` Guitar/Stick/Left = `Axis 412` Guitar/Stick/Right = `Axis 413` Guitar/Stick/Radius = 100,000000 -Guitar/Whammy/Bar = `Axis = 414` +Guitar/Whammy/Bar = `Axis 414` Drums/Buttons/- = `Button 500` Drums/Buttons/+ = `Button 501` Drums/Pads/Red = `Button 502` @@ -274,6 +286,18 @@ Turntable/Stick/Radius = 100,000000 Turntable/Effect/Dial = `Axis 621` Turntable/Crossfade/Left = `Axis 623` Turntable/Crossfade/Right = `Axis 624` +IMUAccelerometer/Left = `Axis 625` +IMUAccelerometer/Right = `Axis 626` +IMUAccelerometer/Forward = `Axis 627` +IMUAccelerometer/Backward = `Axis 628` +IMUAccelerometer/Up = `Axis 629` +IMUAccelerometer/Down = `Axis 630` +IMUGyroscope/Pitch Up = `Axis 631` +IMUGyroscope/Pitch Down = `Axis 632` +IMUGyroscope/Roll Left = `Axis 633` +IMUGyroscope/Roll Right = `Axis 634` +IMUGyroscope/Yaw Left = `Axis 635` +IMUGyroscope/Yaw Right = `Axis 636` Source = 0 Rumble/Motor = `Rumble 700` [Wiimote3] @@ -377,7 +401,7 @@ Guitar/Stick/Down = `Axis 411` Guitar/Stick/Left = `Axis 412` Guitar/Stick/Right = `Axis 413` Guitar/Stick/Radius = 100,000000 -Guitar/Whammy/Bar = `Axis = 414` +Guitar/Whammy/Bar = `Axis 414` Drums/Buttons/- = `Button 500` Drums/Buttons/+ = `Button 501` Drums/Pads/Red = `Button 502` @@ -413,6 +437,18 @@ Turntable/Stick/Radius = 100,000000 Turntable/Effect/Dial = `Axis 621` Turntable/Crossfade/Left = `Axis 623` Turntable/Crossfade/Right = `Axis 624` +IMUAccelerometer/Left = `Axis 625` +IMUAccelerometer/Right = `Axis 626` +IMUAccelerometer/Forward = `Axis 627` +IMUAccelerometer/Backward = `Axis 628` +IMUAccelerometer/Up = `Axis 629` +IMUAccelerometer/Down = `Axis 630` +IMUGyroscope/Pitch Up = `Axis 631` +IMUGyroscope/Pitch Down = `Axis 632` +IMUGyroscope/Roll Left = `Axis 633` +IMUGyroscope/Roll Right = `Axis 634` +IMUGyroscope/Yaw Left = `Axis 635` +IMUGyroscope/Yaw Right = `Axis 636` Source = 0 Rumble/Motor = `Rumble 700` [Wiimote4] @@ -516,7 +552,7 @@ Guitar/Stick/Down = `Axis 411` Guitar/Stick/Left = `Axis 412` Guitar/Stick/Right = `Axis 413` Guitar/Stick/Radius = 100,000000 -Guitar/Whammy/Bar = `Axis = 414` +Guitar/Whammy/Bar = `Axis 414` Drums/Buttons/- = `Button 500` Drums/Buttons/+ = `Button 501` Drums/Pads/Red = `Button 502` @@ -552,5 +588,17 @@ Turntable/Stick/Radius = 100,000000 Turntable/Effect/Dial = `Axis 621` Turntable/Crossfade/Left = `Axis 623` Turntable/Crossfade/Right = `Axis 624` +IMUAccelerometer/Left = `Axis 625` +IMUAccelerometer/Right = `Axis 626` +IMUAccelerometer/Forward = `Axis 627` +IMUAccelerometer/Backward = `Axis 628` +IMUAccelerometer/Up = `Axis 629` +IMUAccelerometer/Down = `Axis 630` +IMUGyroscope/Pitch Up = `Axis 631` +IMUGyroscope/Pitch Down = `Axis 632` +IMUGyroscope/Roll Left = `Axis 633` +IMUGyroscope/Roll Right = `Axis 634` +IMUGyroscope/Yaw Left = `Axis 635` +IMUGyroscope/Yaw Right = `Axis 636` Source = 0 Rumble/Motor = `Rumble 700` diff --git a/Source/Android/app/src/main/assets/WiimoteProfile.ini b/Source/Android/app/src/main/assets/WiimoteProfile.ini index 2546736d13..33e51c94d6 100644 --- a/Source/Android/app/src/main/assets/WiimoteProfile.ini +++ b/Source/Android/app/src/main/assets/WiimoteProfile.ini @@ -99,7 +99,7 @@ Guitar/Stick/Down = `Axis 411` Guitar/Stick/Left = `Axis 412` Guitar/Stick/Right = `Axis 413` Guitar/Stick/Radius = 100,000000 -Guitar/Whammy/Bar = `Axis = 414` +Guitar/Whammy/Bar = `Axis 414` Drums/Buttons/- = `Button 500` Drums/Buttons/+ = `Button 501` Drums/Pads/Red = `Button 502` @@ -135,4 +135,16 @@ Turntable/Stick/Radius = 100,000000 Turntable/Effect/Dial = `Axis 621` Turntable/Crossfade/Left = `Axis 623` Turntable/Crossfade/Right = `Axis 624` +IMUAccelerometer/Left = `Axis 625` +IMUAccelerometer/Right = `Axis 626` +IMUAccelerometer/Forward = `Axis 627` +IMUAccelerometer/Backward = `Axis 628` +IMUAccelerometer/Up = `Axis 629` +IMUAccelerometer/Down = `Axis 630` +IMUGyroscope/Pitch Up = `Axis 631` +IMUGyroscope/Pitch Down = `Axis 632` +IMUGyroscope/Roll Left = `Axis 633` +IMUGyroscope/Roll Right = `Axis 634` +IMUGyroscope/Yaw Left = `Axis 635` +IMUGyroscope/Yaw Right = `Axis 636` Rumble/Motor = `Rumble 700` diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java index 1c748a5cea..171946a226 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java @@ -196,6 +196,18 @@ public final class NativeLibrary public static final int TURNTABLE_CROSSFADE = 622; public static final int TURNTABLE_CROSSFADE_LEFT = 623; public static final int TURNTABLE_CROSSFADE_RIGHT = 624; + public static final int WIIMOTE_ACCEL_LEFT = 625; + public static final int WIIMOTE_ACCEL_RIGHT = 626; + public static final int WIIMOTE_ACCEL_FORWARD = 627; + public static final int WIIMOTE_ACCEL_BACKWARD = 628; + public static final int WIIMOTE_ACCEL_UP = 629; + public static final int WIIMOTE_ACCEL_DOWN = 630; + public static final int WIIMOTE_GYRO_PITCH_UP = 631; + public static final int WIIMOTE_GYRO_PITCH_DOWN = 632; + public static final int WIIMOTE_GYRO_ROLL_LEFT = 633; + public static final int WIIMOTE_GYRO_ROLL_RIGHT = 634; + public static final int WIIMOTE_GYRO_YAW_LEFT = 635; + public static final int WIIMOTE_GYRO_YAW_RIGHT = 636; } /** @@ -254,6 +266,9 @@ public final class NativeLibrary Rumble.checkRumble(padID, state); } + public static native void SetMotionSensorsEnabled(boolean accelerometerEnabled, + boolean gyroscopeEnabled); + public static native void NewGameIniFile(); public static native void LoadGameIniFile(String gameId); 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 1b5661b9a0..68562e9969 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 @@ -26,6 +26,7 @@ import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; +import android.view.Surface; import android.view.View; import android.widget.SeekBar; import android.widget.TextView; @@ -49,6 +50,7 @@ import org.dolphinemu.dolphinemu.utils.ControllerMappingHelper; import org.dolphinemu.dolphinemu.utils.FileBrowserHelper; import org.dolphinemu.dolphinemu.utils.Java_GCAdapter; import org.dolphinemu.dolphinemu.utils.Java_WiimoteAdapter; +import org.dolphinemu.dolphinemu.utils.MotionListener; import org.dolphinemu.dolphinemu.utils.Rumble; import org.dolphinemu.dolphinemu.utils.TvUtil; @@ -67,6 +69,7 @@ public final class EmulationActivity extends AppCompatActivity private EmulationFragment mEmulationFragment; private SharedPreferences mPreferences; + private MotionListener mMotionListener; private ControllerMappingHelper mControllerMappingHelper; private Settings mSettings; @@ -97,7 +100,8 @@ public final class EmulationActivity extends AppCompatActivity MENU_ACTION_SAVE_SLOT6, MENU_ACTION_LOAD_SLOT1, MENU_ACTION_LOAD_SLOT2, MENU_ACTION_LOAD_SLOT3, MENU_ACTION_LOAD_SLOT4, MENU_ACTION_LOAD_SLOT5, MENU_ACTION_LOAD_SLOT6, MENU_ACTION_EXIT, MENU_ACTION_CHANGE_DISC, - MENU_ACTION_RESET_OVERLAY, MENU_SET_IR_SENSITIVITY, MENU_ACTION_CHOOSE_DOUBLETAP}) + MENU_ACTION_RESET_OVERLAY, MENU_SET_IR_SENSITIVITY, MENU_ACTION_CHOOSE_DOUBLETAP, + MENU_ACTION_SCREEN_ORIENTATION, MENU_ACTION_MOTION_CONTROLS}) public @interface MenuAction { } @@ -131,6 +135,8 @@ public final class EmulationActivity extends AppCompatActivity public static final int MENU_ACTION_RESET_OVERLAY = 26; public static final int MENU_SET_IR_SENSITIVITY = 27; public static final int MENU_ACTION_CHOOSE_DOUBLETAP = 28; + public static final int MENU_ACTION_SCREEN_ORIENTATION = 29; + public static final int MENU_ACTION_MOTION_CONTROLS = 30; private static SparseIntArray buttonsActionsMap = new SparseIntArray(); @@ -177,6 +183,10 @@ public final class EmulationActivity extends AppCompatActivity EmulationActivity.MENU_SET_IR_SENSITIVITY); buttonsActionsMap.append(R.id.menu_emulation_choose_doubletap, EmulationActivity.MENU_ACTION_CHOOSE_DOUBLETAP); + buttonsActionsMap.append(R.id.menu_screen_orientation, + EmulationActivity.MENU_ACTION_SCREEN_ORIENTATION); + buttonsActionsMap.append(R.id.menu_emulation_motion_controls, + EmulationActivity.MENU_ACTION_MOTION_CONTROLS); } private static String[] scanForSecondDisc(GameFile gameFile) @@ -252,13 +262,18 @@ public final class EmulationActivity extends AppCompatActivity restoreState(savedInstanceState); } + mPreferences = PreferenceManager.getDefaultSharedPreferences(this); + mSettings = new Settings(); mSettings.loadSettings(null); + updateOrientation(); + // TODO: The accurate way to find out which console we're emulating is to // first launch emulation and then ask the core which console we're emulating sIsGameCubeGame = Platform.fromNativeInt(mPlatform) == Platform.GAMECUBE; mDeviceHasTouchScreen = getPackageManager().hasSystemFeature("android.hardware.touchscreen"); + mMotionListener = new MotionListener(this); mControllerMappingHelper = new ControllerMappingHelper(); int themeId; @@ -295,17 +310,6 @@ public final class EmulationActivity extends AppCompatActivity setContentView(R.layout.activity_emulation); - - BooleanSetting lockLandscapeSetting = - (BooleanSetting) mSettings.getSection(Settings.SECTION_INI_CORE) - .getSetting(SettingsFile.KEY_LOCK_LANDSCAPE); - boolean lockLandscape = lockLandscapeSetting == null || lockLandscapeSetting.getValue(); - // Force landscape if set - if (mDeviceHasTouchScreen && lockLandscape) - { - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE); - } - // Find or create the EmulationFragment mEmulationFragment = (EmulationFragment) getSupportFragmentManager() .findFragmentById(R.id.frame_emulation_fragment); @@ -321,9 +325,6 @@ public final class EmulationActivity extends AppCompatActivity { setTitle(mSelectedTitle); } - - mPreferences = PreferenceManager.getDefaultSharedPreferences(this); - } @Override @@ -348,6 +349,21 @@ public final class EmulationActivity extends AppCompatActivity mPlatform = savedInstanceState.getInt(EXTRA_PLATFORM); } + @Override + protected void onResume() + { + super.onResume(); + if (!sIsGameCubeGame && mPreferences.getInt("motionControlsEnabled", 0) != 2) + mMotionListener.enable(); + } + + @Override + protected void onPause() + { + super.onPause(); + mMotionListener.disable(); + } + @Override protected void onStop() { @@ -414,6 +430,12 @@ public final class EmulationActivity extends AppCompatActivity View.SYSTEM_UI_FLAG_IMMERSIVE); } + private void updateOrientation() + { + setRequestedOrientation(mPreferences.getInt("emulationActivityOrientation", + ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)); + } + private void toggleMenu() { boolean result = getSupportFragmentManager().popBackStackImmediate( @@ -629,6 +651,14 @@ public final class EmulationActivity extends AppCompatActivity chooseDoubleTapButton(); return; + case MENU_ACTION_SCREEN_ORIENTATION: + chooseOrientation(); + return; + + case MENU_ACTION_MOTION_CONTROLS: + showMotionControlsOptions(); + return; + case MENU_ACTION_EXIT: // ATV menu is built using a fragment, this will pop that fragment before emulation ends. if (TvUtil.isLeanback(getApplicationContext())) @@ -852,6 +882,8 @@ public final class EmulationActivity extends AppCompatActivity editor.putInt("wiiController", indexSelected); NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote1", "Extension", getResources().getStringArray(R.array.controllersValues)[indexSelected]); + NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote1", + "Options/Sideways Wiimote", indexSelected == 2 ? "True" : "False"); NativeLibrary.ReloadWiimoteConfig(); }); builder.setPositiveButton(getString(R.string.ok), (dialogInterface, i) -> @@ -864,6 +896,63 @@ public final class EmulationActivity extends AppCompatActivity alertDialog.show(); } + private void showMotionControlsOptions() + { + final SharedPreferences.Editor editor = mPreferences.edit(); + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(R.string.emulation_motion_controls); + builder.setSingleChoiceItems(R.array.motionControlsEntries, + mPreferences.getInt("motionControlsEnabled", 0), + (dialog, indexSelected) -> + { + editor.putInt("motionControlsEnabled", indexSelected); + + if (indexSelected != 2) + mMotionListener.enable(); + else + mMotionListener.disable(); + + NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote1", "IMUIR/Enabled", + indexSelected != 1 ? "True" : "False"); + NativeLibrary.ReloadWiimoteConfig(); + }); + builder.setPositiveButton(getString(R.string.ok), (dialogInterface, i) -> editor.apply()); + + AlertDialog alertDialog = builder.create(); + alertDialog.show(); + } + + private void chooseOrientation() + { + final int[] orientationValues = getResources().getIntArray(R.array.orientationValues); + int initialChoice = mPreferences.getInt("emulationActivityOrientation", + ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + int initialIndex = -1; + for (int i = 0; i < orientationValues.length; i++) + { + if (orientationValues[i] == initialChoice) + initialIndex = i; + } + + final SharedPreferences.Editor editor = mPreferences.edit(); + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(R.string.emulation_screen_orientation); + builder.setSingleChoiceItems(R.array.orientationEntries, initialIndex, + (dialog, indexSelected) -> + { + int orientation = orientationValues[indexSelected]; + editor.putInt("emulationActivityOrientation", orientation); + }); + builder.setPositiveButton(getString(R.string.ok), (dialogInterface, i) -> + { + editor.apply(); + updateOrientation(); + }); + + AlertDialog alertDialog = builder.create(); + alertDialog.show(); + } + private void setIRSensitivity() { int ir_pitch = Integer.valueOf( diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java index 271d556a4b..3c3f2f294f 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java @@ -225,7 +225,6 @@ public final class SettingsFragmentPresenter Setting autoDiscChange = null; Setting analytics = null; Setting enableSaveState; - Setting lockToLandscape; SettingSection coreSection = mSettings.getSection(Settings.SECTION_INI_CORE); SettingSection dspSection = mSettings.getSection(Settings.SECTION_INI_DSP); @@ -241,7 +240,6 @@ public final class SettingsFragmentPresenter autoDiscChange = coreSection.getSetting(SettingsFile.KEY_AUTO_DISC_CHANGE); analytics = analyticsSection.getSetting(SettingsFile.KEY_ANALYTICS_ENABLED); enableSaveState = coreSection.getSetting(SettingsFile.KEY_ENABLE_SAVE_STATES); - lockToLandscape = coreSection.getSetting(SettingsFile.KEY_LOCK_LANDSCAPE); // TODO: Having different emuCoresEntries/emuCoresValues for each architecture is annoying. // The proper solution would be to have one emuCoresEntries and one emuCoresValues @@ -288,12 +286,6 @@ public final class SettingsFragmentPresenter sl.add(new CheckBoxSetting(SettingsFile.KEY_ENABLE_SAVE_STATES, Settings.SECTION_INI_CORE, R.string.enable_save_states, R.string.enable_save_states_description, false, enableSaveState)); - if (!TvUtil.isLeanback(DolphinApplication.getAppContext())) - { - sl.add(new CheckBoxSetting(SettingsFile.KEY_LOCK_LANDSCAPE, Settings.SECTION_INI_CORE, - R.string.lock_emulation_landscape, R.string.lock_emulation_landscape_desc, true, - lockToLandscape)); - } sl.add(new CheckBoxSetting(SettingsFile.KEY_ANALYTICS_ENABLED, Settings.SECTION_ANALYTICS, R.string.analytics, 0, false, analytics)); } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.java index 6f7bf15be8..8de9bf5281 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.java @@ -54,7 +54,6 @@ public final class SettingsFile public static final String KEY_SLOT_A_DEVICE = "SlotA"; public static final String KEY_SLOT_B_DEVICE = "SlotB"; public static final String KEY_ENABLE_SAVE_STATES = "EnableSaveStates"; - public static final String KEY_LOCK_LANDSCAPE = "LockLandscape"; public static final String KEY_ANALYTICS_ENABLED = "Enabled"; public static final String KEY_ANALYTICS_PERMISSION_ASKED = "PermissionAsked"; diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlay.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlay.java index 40e4a3d6ed..e2c6c1978c 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlay.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlay.java @@ -571,22 +571,11 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener } if (mPreferences.getBoolean("buttonToggleWii7", true)) { - if (mPreferences.getInt("wiiController", 3) == 2) - { - overlayDpads.add(initializeOverlayDpad(getContext(), R.drawable.gcwii_dpad, - R.drawable.gcwii_dpad_pressed_one_direction, - R.drawable.gcwii_dpad_pressed_two_directions, - ButtonType.WIIMOTE_RIGHT, ButtonType.WIIMOTE_LEFT, - ButtonType.WIIMOTE_UP, ButtonType.WIIMOTE_DOWN, orientation)); - } - else - { - overlayDpads.add(initializeOverlayDpad(getContext(), R.drawable.gcwii_dpad, - R.drawable.gcwii_dpad_pressed_one_direction, - R.drawable.gcwii_dpad_pressed_two_directions, - ButtonType.WIIMOTE_UP, ButtonType.WIIMOTE_DOWN, - ButtonType.WIIMOTE_LEFT, ButtonType.WIIMOTE_RIGHT, orientation)); - } + overlayDpads.add(initializeOverlayDpad(getContext(), R.drawable.gcwii_dpad, + R.drawable.gcwii_dpad_pressed_one_direction, + R.drawable.gcwii_dpad_pressed_two_directions, + ButtonType.WIIMOTE_UP, ButtonType.WIIMOTE_DOWN, + ButtonType.WIIMOTE_LEFT, ButtonType.WIIMOTE_RIGHT, orientation)); } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/DirectoryInitialization.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/DirectoryInitialization.java index eeb3a78855..7742ac90ae 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/DirectoryInitialization.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/DirectoryInitialization.java @@ -34,7 +34,7 @@ public final class DirectoryInitialization "org.dolphinemu.dolphinemu.DIRECTORY_INITIALIZATION"; public static final String EXTRA_STATE = "directoryState"; - private static final Integer WiimoteNewVersion = 2; + private static final int WiimoteNewVersion = 3; // Last changed in PR 8439 private static volatile DirectoryInitializationState directoryState = null; private static String userPath; private static String internalPath; diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/MotionListener.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/MotionListener.java new file mode 100644 index 0000000000..31d1641aba --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/MotionListener.java @@ -0,0 +1,126 @@ +package org.dolphinemu.dolphinemu.utils; + +import android.app.Activity; +import android.content.Context; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.view.Surface; + +import org.dolphinemu.dolphinemu.NativeLibrary; +import org.dolphinemu.dolphinemu.NativeLibrary.ButtonType; + +public class MotionListener implements SensorEventListener +{ + private final Activity mActivity; + private final SensorManager mSensorManager; + private final Sensor mAccelSensor; + private final Sensor mGyroSensor; + + private boolean mEnabled = false; + + // The same sampling period as for Wii Remotes + private static final int SAMPLING_PERIOD_US = 1000000 / 200; + + public MotionListener(Activity activity) + { + mActivity = activity; + mSensorManager = (SensorManager) activity.getSystemService(Context.SENSOR_SERVICE); + mAccelSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); + mGyroSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE); + } + + @Override + public void onSensorChanged(SensorEvent sensorEvent) + { + float x, y; + float z = sensorEvent.values[2]; + int orientation = mActivity.getWindowManager().getDefaultDisplay().getRotation(); + switch (orientation) + { + default: + case Surface.ROTATION_0: + x = -sensorEvent.values[0]; + y = -sensorEvent.values[1]; + break; + case Surface.ROTATION_90: + x = sensorEvent.values[1]; + y = -sensorEvent.values[0]; + break; + case Surface.ROTATION_180: + x = sensorEvent.values[0]; + y = sensorEvent.values[1]; + break; + case Surface.ROTATION_270: + x = -sensorEvent.values[1]; + y = sensorEvent.values[0]; + break; + } + + if (sensorEvent.sensor == mAccelSensor) + { + NativeLibrary.onGamePadMoveEvent(NativeLibrary.TouchScreenDevice, + ButtonType.WIIMOTE_ACCEL_LEFT, x); + NativeLibrary.onGamePadMoveEvent(NativeLibrary.TouchScreenDevice, + ButtonType.WIIMOTE_ACCEL_RIGHT, x); + NativeLibrary.onGamePadMoveEvent(NativeLibrary.TouchScreenDevice, + ButtonType.WIIMOTE_ACCEL_FORWARD, y); + NativeLibrary.onGamePadMoveEvent(NativeLibrary.TouchScreenDevice, + ButtonType.WIIMOTE_ACCEL_BACKWARD, y); + NativeLibrary.onGamePadMoveEvent(NativeLibrary.TouchScreenDevice, + ButtonType.WIIMOTE_ACCEL_UP, z); + NativeLibrary.onGamePadMoveEvent(NativeLibrary.TouchScreenDevice, + ButtonType.WIIMOTE_ACCEL_DOWN, z); + } + + if (sensorEvent.sensor == mGyroSensor) + { + NativeLibrary.onGamePadMoveEvent(NativeLibrary.TouchScreenDevice, + ButtonType.WIIMOTE_GYRO_PITCH_UP, x); + NativeLibrary.onGamePadMoveEvent(NativeLibrary.TouchScreenDevice, + ButtonType.WIIMOTE_GYRO_PITCH_DOWN, x); + NativeLibrary.onGamePadMoveEvent(NativeLibrary.TouchScreenDevice, + ButtonType.WIIMOTE_GYRO_ROLL_LEFT, y); + NativeLibrary.onGamePadMoveEvent(NativeLibrary.TouchScreenDevice, + ButtonType.WIIMOTE_GYRO_ROLL_RIGHT, y); + NativeLibrary.onGamePadMoveEvent(NativeLibrary.TouchScreenDevice, + ButtonType.WIIMOTE_GYRO_YAW_LEFT, z); + NativeLibrary.onGamePadMoveEvent(NativeLibrary.TouchScreenDevice, + ButtonType.WIIMOTE_GYRO_YAW_RIGHT, z); + } + } + + @Override + public void onAccuracyChanged(Sensor sensor, int i) + { + // We don't care about this + } + + public void enable() + { + if (mEnabled) + return; + + if (mAccelSensor != null) + mSensorManager.registerListener(this, mAccelSensor, SAMPLING_PERIOD_US); + if (mGyroSensor != null) + mSensorManager.registerListener(this, mGyroSensor, SAMPLING_PERIOD_US); + + NativeLibrary.SetMotionSensorsEnabled(mAccelSensor != null, mGyroSensor != null); + + mEnabled = true; + } + + public void disable() + { + if (!mEnabled) + return; + + mSensorManager.unregisterListener(this); + + NativeLibrary.SetMotionSensorsEnabled(false, false); + + mEnabled = false; + } +} 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 cfa126c4c9..6f0abbeae7 100644 --- a/Source/Android/app/src/main/res/menu/menu_emulation.xml +++ b/Source/Android/app/src/main/res/menu/menu_emulation.xml @@ -113,6 +113,11 @@ + + + + + + Wii Controller Settings Clear Game Settings + + + Landscape + Portrait + Auto + + + 0 + 1 + -1 + + + + Use Device Sensors (With Pointer Emulation) + Use Device Sensors (Without Pointer Emulation) + Don\'t Use Device Sensors + diff --git a/Source/Android/app/src/main/res/values/strings.xml b/Source/Android/app/src/main/res/values/strings.xml index f1346dfdde..1e7ef2114a 100644 --- a/Source/Android/app/src/main/res/values/strings.xml +++ b/Source/Android/app/src/main/res/values/strings.xml @@ -318,6 +318,8 @@ Touch IR Pointer IR Sensitivity Double tap button + Screen Orientation + Motion Controls Enable Vibration diff --git a/Source/Android/jni/ButtonManager.cpp b/Source/Android/jni/ButtonManager.cpp index 1ba6de758e..bd02525db4 100644 --- a/Source/Android/jni/ButtonManager.cpp +++ b/Source/Android/jni/ButtonManager.cpp @@ -18,7 +18,7 @@ namespace ButtonManager namespace { constexpr char touchScreenKey[] = "Touchscreen"; -constexpr std::array configStrings{{ +constexpr std::array configStrings{{ // GC "InputA", "InputB", @@ -168,11 +168,24 @@ constexpr std::array configStrings{{ "TurntableEffDial", "TurntableCrossLeft", "TurntableCrossRight", + // Wiimote IMU + "WiimoteAccelLeft", + "WiimoteAccelRight", + "WiimoteAccelForward", + "WiimoteAccelBackward", + "WiimoteAccelUp", + "WiimoteAccelDown", + "WiimoteGyroPitchUp", + "WiimoteGyroPitchDown", + "WiimoteGyroRollLeft", + "WiimoteGyroRollRight", + "WiimoteGyroYawLeft", + "WiimoteGyroYawRight", // Rumble "Rumble", }}; -constexpr std::array configTypes{{ +constexpr std::array configTypes{{ // GC BUTTON_A, BUTTON_B, @@ -322,6 +335,19 @@ constexpr std::array configTypes{{ TURNTABLE_EFFECT_DIAL, TURNTABLE_CROSSFADE_LEFT, TURNTABLE_CROSSFADE_RIGHT, + // Wiimote IMU + WIIMOTE_ACCEL_LEFT, + WIIMOTE_ACCEL_RIGHT, + WIIMOTE_ACCEL_FORWARD, + WIIMOTE_ACCEL_BACKWARD, + WIIMOTE_ACCEL_UP, + WIIMOTE_ACCEL_DOWN, + WIIMOTE_GYRO_PITCH_UP, + WIIMOTE_GYRO_PITCH_DOWN, + WIIMOTE_GYRO_ROLL_LEFT, + WIIMOTE_GYRO_ROLL_RIGHT, + WIIMOTE_GYRO_YAW_LEFT, + WIIMOTE_GYRO_YAW_RIGHT, // Rumble RUMBLE, }}; @@ -562,6 +588,29 @@ void Init(const std::string& gameId) new sBind(a, TURNTABLE_CROSSFADE_LEFT, BIND_AXIS, TURNTABLE_CROSSFADE_LEFT, -1.0f)); AddBind(touchScreenKey, new sBind(a, TURNTABLE_CROSSFADE_RIGHT, BIND_AXIS, TURNTABLE_CROSSFADE_RIGHT, 1.0f)); + + // Wiimote IMU + AddBind(touchScreenKey, new sBind(a, WIIMOTE_ACCEL_LEFT, BIND_AXIS, WIIMOTE_ACCEL_LEFT, 1.0f)); + AddBind(touchScreenKey, + new sBind(a, WIIMOTE_ACCEL_RIGHT, BIND_AXIS, WIIMOTE_ACCEL_RIGHT, -1.0f)); + AddBind(touchScreenKey, + new sBind(a, WIIMOTE_ACCEL_FORWARD, BIND_AXIS, WIIMOTE_ACCEL_FORWARD, -1.0f)); + AddBind(touchScreenKey, + new sBind(a, WIIMOTE_ACCEL_BACKWARD, BIND_AXIS, WIIMOTE_ACCEL_BACKWARD, 1.0f)); + AddBind(touchScreenKey, new sBind(a, WIIMOTE_ACCEL_UP, BIND_AXIS, WIIMOTE_ACCEL_UP, 1.0f)); + AddBind(touchScreenKey, new sBind(a, WIIMOTE_ACCEL_DOWN, BIND_AXIS, WIIMOTE_ACCEL_DOWN, -1.0f)); + AddBind(touchScreenKey, + new sBind(a, WIIMOTE_GYRO_PITCH_UP, BIND_AXIS, WIIMOTE_GYRO_PITCH_UP, -1.0f)); + AddBind(touchScreenKey, + new sBind(a, WIIMOTE_GYRO_PITCH_DOWN, BIND_AXIS, WIIMOTE_GYRO_PITCH_DOWN, 1.0f)); + AddBind(touchScreenKey, + new sBind(a, WIIMOTE_GYRO_ROLL_LEFT, BIND_AXIS, WIIMOTE_GYRO_ROLL_LEFT, 1.0f)); + AddBind(touchScreenKey, + new sBind(a, WIIMOTE_GYRO_ROLL_RIGHT, BIND_AXIS, WIIMOTE_GYRO_ROLL_RIGHT, -1.0f)); + AddBind(touchScreenKey, + new sBind(a, WIIMOTE_GYRO_YAW_LEFT, BIND_AXIS, WIIMOTE_GYRO_YAW_LEFT, 1.0f)); + AddBind(touchScreenKey, + new sBind(a, WIIMOTE_GYRO_YAW_RIGHT, BIND_AXIS, WIIMOTE_GYRO_YAW_RIGHT, -1.0f)); } // Init our controller bindings IniFile ini; diff --git a/Source/Android/jni/ButtonManager.h b/Source/Android/jni/ButtonManager.h index b7fd2f7647..71722c54d6 100644 --- a/Source/Android/jni/ButtonManager.h +++ b/Source/Android/jni/ButtonManager.h @@ -176,6 +176,19 @@ enum ButtonType TURNTABLE_CROSSFADE = 622, // To Be Used on Java Side TURNTABLE_CROSSFADE_LEFT = 623, TURNTABLE_CROSSFADE_RIGHT = 624, + // Wiimote IMU + WIIMOTE_ACCEL_LEFT = 625, + WIIMOTE_ACCEL_RIGHT = 626, + WIIMOTE_ACCEL_FORWARD = 627, + WIIMOTE_ACCEL_BACKWARD = 628, + WIIMOTE_ACCEL_UP = 629, + WIIMOTE_ACCEL_DOWN = 630, + WIIMOTE_GYRO_PITCH_UP = 631, + WIIMOTE_GYRO_PITCH_DOWN = 632, + WIIMOTE_GYRO_ROLL_LEFT = 633, + WIIMOTE_GYRO_ROLL_RIGHT = 634, + WIIMOTE_GYRO_YAW_LEFT = 635, + WIIMOTE_GYRO_YAW_RIGHT = 636, // Rumble RUMBLE = 700, }; diff --git a/Source/Android/jni/MainAndroid.cpp b/Source/Android/jni/MainAndroid.cpp index aa197f7e5e..d998097fee 100644 --- a/Source/Android/jni/MainAndroid.cpp +++ b/Source/Android/jni/MainAndroid.cpp @@ -47,6 +47,8 @@ #include "DiscIO/Enums.h" #include "DiscIO/Volume.h" +#include "InputCommon/ControllerInterface/Android/Android.h" + #include "UICommon/UICommon.h" #include "VideoCommon/OnScreenDisplay.h" @@ -200,6 +202,8 @@ JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_onGamePa JNIEnv* env, jobject obj, jstring jDevice, jint Button, jint Action); JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_onGamePadMoveEvent( JNIEnv* env, jobject obj, jstring jDevice, jint Axis, jfloat Value); +JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetMotionSensorsEnabled( + JNIEnv* env, jobject obj, jboolean accelerometer_enabled, jboolean gyroscope_enabled); JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetVersionString(JNIEnv* env, jobject obj); JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetGitRevision(JNIEnv* env, @@ -308,6 +312,12 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_onGamePadMov ButtonManager::GamepadAxisEvent(GetJString(env, jDevice), Axis, Value); } +JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetMotionSensorsEnabled( + JNIEnv* env, jobject obj, jboolean accelerometer_enabled, jboolean gyroscope_enabled) +{ + ciface::Android::SetMotionSensorsEnabled(accelerometer_enabled, gyroscope_enabled); +} + JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetVersionString(JNIEnv* env, jobject obj) { diff --git a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp index 910b7553c9..21537cba15 100644 --- a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp @@ -10,6 +10,21 @@ namespace ciface::Android { +static bool s_accelerometer_enabled = false; +static bool s_gyroscope_enabled = false; + +void SetMotionSensorsEnabled(bool accelerometer_enabled, bool gyroscope_enabled) +{ + const bool any_changes = + s_accelerometer_enabled != accelerometer_enabled || s_gyroscope_enabled != gyroscope_enabled; + + s_accelerometer_enabled = accelerometer_enabled; + s_gyroscope_enabled = gyroscope_enabled; + + if (any_changes) + g_controller_interface.RefreshDevices(); +} + void PopulateDevices() { for (int i = 0; i < 8; ++i) @@ -185,6 +200,28 @@ Touchscreen::Touchscreen(int padID) : _padID(padID) AddInput(new Axis(_padID, ButtonManager::TURNTABLE_CROSSFADE_RIGHT)); AddInput(new Axis(_padID, ButtonManager::TURNTABLE_EFFECT_DIAL)); + // Wiimote IMU + // Only add inputs if we actually can receive data from the relevant sensor. + // Whether inputs exist affects what WiimoteEmu gets when calling ControlReference::BoundCount. + if (s_accelerometer_enabled) + { + AddInput(new Axis(_padID, ButtonManager::WIIMOTE_ACCEL_LEFT)); + AddInput(new Axis(_padID, ButtonManager::WIIMOTE_ACCEL_RIGHT)); + AddInput(new Axis(_padID, ButtonManager::WIIMOTE_ACCEL_FORWARD)); + AddInput(new Axis(_padID, ButtonManager::WIIMOTE_ACCEL_BACKWARD)); + AddInput(new Axis(_padID, ButtonManager::WIIMOTE_ACCEL_UP)); + AddInput(new Axis(_padID, ButtonManager::WIIMOTE_ACCEL_DOWN)); + } + if (s_gyroscope_enabled) + { + AddInput(new Axis(_padID, ButtonManager::WIIMOTE_GYRO_PITCH_UP)); + AddInput(new Axis(_padID, ButtonManager::WIIMOTE_GYRO_PITCH_DOWN)); + AddInput(new Axis(_padID, ButtonManager::WIIMOTE_GYRO_ROLL_LEFT)); + AddInput(new Axis(_padID, ButtonManager::WIIMOTE_GYRO_ROLL_RIGHT)); + AddInput(new Axis(_padID, ButtonManager::WIIMOTE_GYRO_YAW_LEFT)); + AddInput(new Axis(_padID, ButtonManager::WIIMOTE_GYRO_YAW_RIGHT)); + } + // Rumble AddOutput(new Motor(_padID, ButtonManager::RUMBLE)); } diff --git a/Source/Core/InputCommon/ControllerInterface/Android/Android.h b/Source/Core/InputCommon/ControllerInterface/Android/Android.h index 82a1a47954..c9e7ddc0a9 100644 --- a/Source/Core/InputCommon/ControllerInterface/Android/Android.h +++ b/Source/Core/InputCommon/ControllerInterface/Android/Android.h @@ -9,6 +9,8 @@ namespace ciface::Android { +void SetMotionSensorsEnabled(bool accelerometer_enabled, bool gyroscope_enabled); + void PopulateDevices(); class Touchscreen : public Core::Device