From 0150f521f740fc3b1a00d49b432edd0ed32e31d1 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sat, 14 Aug 2021 15:03:54 +0200 Subject: ControllerInterface/Android: Rip out ButtonManager ButtonManager is very different from how a normal input backend works, and is making it hard for us to improve controller support on Android. The following commits will add a new input backend in its place. --- .../ControllerInterface/Android/Android.cpp | 19 - .../ControllerInterface/Android/Android.h | 2 - .../ControllerInterface/Touch/ButtonManager.cpp | 788 --------------------- .../ControllerInterface/Touch/ButtonManager.h | 279 -------- .../ControllerInterface/Touch/Touchscreen.cpp | 264 ------- .../ControllerInterface/Touch/Touchscreen.h | 64 -- 6 files changed, 1416 deletions(-) delete mode 100644 Source/Core/InputCommon/ControllerInterface/Touch/ButtonManager.cpp delete mode 100644 Source/Core/InputCommon/ControllerInterface/Touch/ButtonManager.h delete mode 100644 Source/Core/InputCommon/ControllerInterface/Touch/Touchscreen.cpp delete mode 100644 Source/Core/InputCommon/ControllerInterface/Touch/Touchscreen.h (limited to 'Source/Core/InputCommon/ControllerInterface') diff --git a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp index 7a7c548cc6..d59dc03588 100644 --- a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp @@ -4,29 +4,10 @@ #include "InputCommon/ControllerInterface/Android/Android.h" #include "InputCommon/ControllerInterface/ControllerInterface.h" -#include "InputCommon/ControllerInterface/Touch/Touchscreen.h" 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) - g_controller_interface.AddDevice(std::make_shared( - i, s_accelerometer_enabled, s_gyroscope_enabled)); } } // namespace ciface::Android diff --git a/Source/Core/InputCommon/ControllerInterface/Android/Android.h b/Source/Core/InputCommon/ControllerInterface/Android/Android.h index 2cc3c5a22b..9f57f5ba2e 100644 --- a/Source/Core/InputCommon/ControllerInterface/Android/Android.h +++ b/Source/Core/InputCommon/ControllerInterface/Android/Android.h @@ -5,7 +5,5 @@ namespace ciface::Android { -void SetMotionSensorsEnabled(bool accelerometer_enabled, bool gyroscope_enabled); - void PopulateDevices(); } // namespace ciface::Android diff --git a/Source/Core/InputCommon/ControllerInterface/Touch/ButtonManager.cpp b/Source/Core/InputCommon/ControllerInterface/Touch/ButtonManager.cpp deleted file mode 100644 index 0111947608..0000000000 --- a/Source/Core/InputCommon/ControllerInterface/Touch/ButtonManager.cpp +++ /dev/null @@ -1,788 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "InputCommon/ControllerInterface/Touch/ButtonManager.h" - -#include -#include -#include -#include -#include - -#include "Common/FileUtil.h" -#include "Common/IniFile.h" -#include "Common/StringUtil.h" -#include "Common/Thread.h" - -namespace ButtonManager -{ -namespace -{ -constexpr char TOUCHSCREEN_KEY[] = "Touchscreen"; -constexpr std::array CONFIG_STRINGS{{ - // GC - "InputA", - "InputB", - "InputStart", - "InputX", - "InputY", - "InputZ", - "DPadUp", - "DPadDown", - "DPadLeft", - "DPadRight", - "MainUp", - "MainDown", - "MainLeft", - "MainRight", - "CStickUp", - "CStickDown", - "CStickLeft", - "CStickRight", - "InputL", - "InputR", - // Wiimote - "WiimoteA", - "WiimoteB", - "WiimoteMinus", - "WiimotePlus", - "WiimoteHome", - "Wiimote1", - "Wiimote2", - "WiimoteUp", - "WiimoteDown", - "WiimoteLeft", - "WiimoteRight", - "IRUp", - "IRDown", - "IRLeft", - "IRRight", - "IRForward", - "IRBackward", - "IRHide", - "SwingUp", - "SwingDown", - "SwingLeft", - "SwingRight", - "SwingForward", - "SwingBackward", - "TiltForward", - "TiltBackward", - "TiltLeft", - "TiltRight", - "TiltModifier", - "ShakeX", - "ShakeY", - "ShakeZ", - // Nunchuk - "NunchukC", - "NunchukZ", - "NunchukUp", - "NunchukDown", - "NunchukLeft", - "NunchukRight", - "NunchukSwingUp", - "NunchukSwingDown", - "NunchukSwingLeft", - "NunchukSwingRight", - "NunchukSwingForward", - "NunchukSwingBackward", - "NunchukTiltForward", - "NunchukTiltBackward", - "NunchukTiltLeft", - "NunchukTiltRight", - "NunchukTiltModifier", - "NunchukShakeX", - "NunchukShakeY", - "NunchukShakeZ", - // Classic - "ClassicA", - "ClassicB", - "ClassicX", - "ClassicY", - "ClassicMinus", - "ClassicPlus", - "ClassicHome", - "ClassicZL", - "ClassicZR", - "ClassicUp", - "ClassicDown", - "ClassicLeft", - "ClassicRight", - "ClassicLeftStickUp", - "ClassicLeftStickDown", - "ClassicLeftStickLeft", - "ClassicLeftStickRight", - "ClassicRightStickUp", - "ClassicRightStickDown", - "ClassicRightStickLeft", - "ClassicRightStickRight", - "ClassicTriggerL", - "ClassicTriggerR", - // Guitar - "GuitarMinus", - "GuitarPlus", - "GuitarGreen", - "GuitarRed", - "GuitarYellow", - "GuitarBlue", - "GuitarOrange", - "GuitarStrumUp", - "GuitarStrumDown", - "GuitarUp", - "GuitarDown", - "GuitarLeft", - "GuitarRight", - "GuitarWhammy", - // Drums - "DrumsMinus", - "DrumsPlus", - "DrumsRed", - "DrumsYellow", - "DrumsBlue", - "DrumsGreen", - "DrumsOrange", - "DrumsBass", - "DrumsUp", - "DrumsDown", - "DrumsLeft", - "DrumsRight", - // Turntable - "TurntableGreenLeft", - "TurntableRedLeft", - "TurntableBlueLeft", - "TurntableGreenRight", - "TurntableRedRight", - "TurntableBlueRight", - "TurntableMinus", - "TurntablePlus", - "TurntableHome", - "TurntableEuphoria", - "TurntableLeftTLeft", - "TurntableLeftTRight", - "TurntableRightTLeft", - "TurntableRightTRight", - "TurntableUp", - "TurntableDown", - "TurntableLeft", - "TurntableRight", - "TurntableEffDial", - "TurntableCrossLeft", - "TurntableCrossRight", - // Wiimote IMU - "WiimoteAccelLeft", - "WiimoteAccelRight", - "WiimoteAccelForward", - "WiimoteAccelBackward", - "WiimoteAccelUp", - "WiimoteAccelDown", - "WiimoteGyroPitchUp", - "WiimoteGyroPitchDown", - "WiimoteGyroRollLeft", - "WiimoteGyroRollRight", - "WiimoteGyroYawLeft", - "WiimoteGyroYawRight", - // Rumble - "Rumble", -}}; - -constexpr std::array CONFIG_TYPES{{ - // GC - BUTTON_A, - BUTTON_B, - BUTTON_START, - BUTTON_X, - BUTTON_Y, - BUTTON_Z, - BUTTON_UP, - BUTTON_DOWN, - BUTTON_LEFT, - BUTTON_RIGHT, - STICK_MAIN_UP, - STICK_MAIN_DOWN, - STICK_MAIN_LEFT, - STICK_MAIN_RIGHT, - STICK_C_UP, - STICK_C_DOWN, - STICK_C_LEFT, - STICK_C_RIGHT, - TRIGGER_L, - TRIGGER_R, - // Wiimote - WIIMOTE_BUTTON_A, - WIIMOTE_BUTTON_B, - WIIMOTE_BUTTON_MINUS, - WIIMOTE_BUTTON_PLUS, - WIIMOTE_BUTTON_HOME, - WIIMOTE_BUTTON_1, - WIIMOTE_BUTTON_2, - WIIMOTE_UP, - WIIMOTE_DOWN, - WIIMOTE_LEFT, - WIIMOTE_RIGHT, - WIIMOTE_IR_UP, - WIIMOTE_IR_DOWN, - WIIMOTE_IR_LEFT, - WIIMOTE_IR_RIGHT, - WIIMOTE_IR_FORWARD, - WIIMOTE_IR_BACKWARD, - WIIMOTE_IR_HIDE, - WIIMOTE_SWING_UP, - WIIMOTE_SWING_DOWN, - WIIMOTE_SWING_LEFT, - WIIMOTE_SWING_RIGHT, - WIIMOTE_SWING_FORWARD, - WIIMOTE_SWING_BACKWARD, - WIIMOTE_TILT_FORWARD, - WIIMOTE_TILT_BACKWARD, - WIIMOTE_TILT_LEFT, - WIIMOTE_TILT_RIGHT, - WIIMOTE_TILT_MODIFIER, - WIIMOTE_SHAKE_X, - WIIMOTE_SHAKE_Y, - WIIMOTE_SHAKE_Z, - // Nunchuk - NUNCHUK_BUTTON_C, - NUNCHUK_BUTTON_Z, - NUNCHUK_STICK_UP, - NUNCHUK_STICK_DOWN, - NUNCHUK_STICK_LEFT, - NUNCHUK_STICK_RIGHT, - NUNCHUK_SWING_UP, - NUNCHUK_SWING_DOWN, - NUNCHUK_SWING_LEFT, - NUNCHUK_SWING_RIGHT, - NUNCHUK_SWING_FORWARD, - NUNCHUK_SWING_BACKWARD, - NUNCHUK_TILT_FORWARD, - NUNCHUK_TILT_BACKWARD, - NUNCHUK_TILT_LEFT, - NUNCHUK_TILT_RIGHT, - NUNCHUK_TILT_MODIFIER, - NUNCHUK_SHAKE_X, - NUNCHUK_SHAKE_Y, - NUNCHUK_SHAKE_Z, - // Classic - CLASSIC_BUTTON_A, - CLASSIC_BUTTON_B, - CLASSIC_BUTTON_X, - CLASSIC_BUTTON_Y, - CLASSIC_BUTTON_MINUS, - CLASSIC_BUTTON_PLUS, - CLASSIC_BUTTON_HOME, - CLASSIC_BUTTON_ZL, - CLASSIC_BUTTON_ZR, - CLASSIC_DPAD_UP, - CLASSIC_DPAD_DOWN, - CLASSIC_DPAD_LEFT, - CLASSIC_DPAD_RIGHT, - CLASSIC_STICK_LEFT_UP, - CLASSIC_STICK_LEFT_DOWN, - CLASSIC_STICK_LEFT_LEFT, - CLASSIC_STICK_LEFT_RIGHT, - CLASSIC_STICK_RIGHT_UP, - CLASSIC_STICK_RIGHT_DOWN, - CLASSIC_STICK_RIGHT_LEFT, - CLASSIC_STICK_RIGHT_RIGHT, - CLASSIC_TRIGGER_L, - CLASSIC_TRIGGER_R, - // Guitar - GUITAR_BUTTON_MINUS, - GUITAR_BUTTON_PLUS, - GUITAR_FRET_GREEN, - GUITAR_FRET_RED, - GUITAR_FRET_YELLOW, - GUITAR_FRET_BLUE, - GUITAR_FRET_ORANGE, - GUITAR_STRUM_UP, - GUITAR_STRUM_DOWN, - GUITAR_STICK_UP, - GUITAR_STICK_DOWN, - GUITAR_STICK_LEFT, - GUITAR_STICK_RIGHT, - GUITAR_WHAMMY_BAR, - // Drums - DRUMS_BUTTON_MINUS, - DRUMS_BUTTON_PLUS, - DRUMS_PAD_RED, - DRUMS_PAD_YELLOW, - DRUMS_PAD_BLUE, - DRUMS_PAD_GREEN, - DRUMS_PAD_ORANGE, - DRUMS_PAD_BASS, - DRUMS_STICK_UP, - DRUMS_STICK_DOWN, - DRUMS_STICK_LEFT, - DRUMS_STICK_RIGHT, - // Turntable - TURNTABLE_BUTTON_GREEN_LEFT, - TURNTABLE_BUTTON_RED_LEFT, - TURNTABLE_BUTTON_BLUE_LEFT, - TURNTABLE_BUTTON_GREEN_RIGHT, - TURNTABLE_BUTTON_RED_RIGHT, - TURNTABLE_BUTTON_BLUE_RIGHT, - TURNTABLE_BUTTON_MINUS, - TURNTABLE_BUTTON_PLUS, - TURNTABLE_BUTTON_HOME, - TURNTABLE_BUTTON_EUPHORIA, - TURNTABLE_TABLE_LEFT_LEFT, - TURNTABLE_TABLE_LEFT_RIGHT, - TURNTABLE_TABLE_RIGHT_LEFT, - 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, - // 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, -}}; - -std::unordered_map m_controllers; - -void AddBind(const std::string& dev, sBind* bind) -{ - auto it = m_controllers.find(dev); - if (it != m_controllers.end()) - { - it->second->AddBind(bind); - return; - } - m_controllers[dev] = new InputDevice(dev); - m_controllers[dev]->AddBind(bind); -} -} // Anonymous namespace - -void Init(const std::string& game_id) -{ - // Initialize pad 0(gc 1) and pad 4(wii 1) as touch overlay controller - for (int a = 0; a < 5; a += 4) - { - // GC - AddBind(TOUCHSCREEN_KEY, new sBind(a, BUTTON_A, BIND_BUTTON, BUTTON_A, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, BUTTON_B, BIND_BUTTON, BUTTON_B, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, BUTTON_START, BIND_BUTTON, BUTTON_START, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, BUTTON_X, BIND_BUTTON, BUTTON_X, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, BUTTON_Y, BIND_BUTTON, BUTTON_Y, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, BUTTON_Z, BIND_BUTTON, BUTTON_Z, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, BUTTON_UP, BIND_BUTTON, BUTTON_UP, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, BUTTON_DOWN, BIND_BUTTON, BUTTON_DOWN, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, BUTTON_LEFT, BIND_BUTTON, BUTTON_LEFT, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, BUTTON_RIGHT, BIND_BUTTON, BUTTON_RIGHT, 1.0f)); - - AddBind(TOUCHSCREEN_KEY, new sBind(a, STICK_MAIN_UP, BIND_AXIS, STICK_MAIN_UP, -1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, STICK_MAIN_DOWN, BIND_AXIS, STICK_MAIN_DOWN, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, STICK_MAIN_LEFT, BIND_AXIS, STICK_MAIN_LEFT, -1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, STICK_MAIN_RIGHT, BIND_AXIS, STICK_MAIN_RIGHT, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, STICK_C_UP, BIND_AXIS, STICK_C_UP, -1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, STICK_C_DOWN, BIND_AXIS, STICK_C_DOWN, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, STICK_C_LEFT, BIND_AXIS, STICK_C_LEFT, -1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, STICK_C_RIGHT, BIND_AXIS, STICK_C_RIGHT, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, TRIGGER_L, BIND_AXIS, TRIGGER_L, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, TRIGGER_R, BIND_AXIS, TRIGGER_R, 1.0f)); - - // Wiimote - AddBind(TOUCHSCREEN_KEY, new sBind(a, WIIMOTE_BUTTON_A, BIND_BUTTON, WIIMOTE_BUTTON_A, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, WIIMOTE_BUTTON_B, BIND_BUTTON, WIIMOTE_BUTTON_B, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, WIIMOTE_BUTTON_MINUS, BIND_BUTTON, WIIMOTE_BUTTON_MINUS, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, WIIMOTE_BUTTON_PLUS, BIND_BUTTON, WIIMOTE_BUTTON_PLUS, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, WIIMOTE_BUTTON_HOME, BIND_BUTTON, WIIMOTE_BUTTON_HOME, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, WIIMOTE_BUTTON_1, BIND_BUTTON, WIIMOTE_BUTTON_1, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, WIIMOTE_BUTTON_2, BIND_BUTTON, WIIMOTE_BUTTON_2, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, WIIMOTE_UP, BIND_BUTTON, WIIMOTE_UP, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, WIIMOTE_DOWN, BIND_BUTTON, WIIMOTE_DOWN, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, WIIMOTE_LEFT, BIND_BUTTON, WIIMOTE_LEFT, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, WIIMOTE_RIGHT, BIND_BUTTON, WIIMOTE_RIGHT, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, WIIMOTE_IR_HIDE, BIND_BUTTON, WIIMOTE_IR_HIDE, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, WIIMOTE_TILT_MODIFIER, BIND_BUTTON, WIIMOTE_TILT_MODIFIER, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, WIIMOTE_SHAKE_X, BIND_BUTTON, WIIMOTE_SHAKE_X, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, WIIMOTE_SHAKE_Y, BIND_BUTTON, WIIMOTE_SHAKE_Y, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, WIIMOTE_SHAKE_Z, BIND_BUTTON, WIIMOTE_SHAKE_Z, 1.0f)); - - AddBind(TOUCHSCREEN_KEY, new sBind(a, WIIMOTE_IR_UP, BIND_AXIS, WIIMOTE_IR_UP, -1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, WIIMOTE_IR_DOWN, BIND_AXIS, WIIMOTE_IR_DOWN, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, WIIMOTE_IR_LEFT, BIND_AXIS, WIIMOTE_IR_LEFT, -1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, WIIMOTE_IR_RIGHT, BIND_AXIS, WIIMOTE_IR_RIGHT, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, WIIMOTE_IR_FORWARD, BIND_AXIS, WIIMOTE_IR_FORWARD, -1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, WIIMOTE_IR_BACKWARD, BIND_AXIS, WIIMOTE_IR_BACKWARD, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, WIIMOTE_SWING_UP, BIND_AXIS, WIIMOTE_SWING_UP, -1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, WIIMOTE_SWING_DOWN, BIND_AXIS, WIIMOTE_SWING_DOWN, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, WIIMOTE_SWING_LEFT, BIND_AXIS, WIIMOTE_SWING_LEFT, -1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, WIIMOTE_SWING_RIGHT, BIND_AXIS, WIIMOTE_SWING_RIGHT, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, WIIMOTE_SWING_FORWARD, BIND_AXIS, WIIMOTE_SWING_FORWARD, -1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, WIIMOTE_SWING_BACKWARD, BIND_AXIS, WIIMOTE_SWING_BACKWARD, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, WIIMOTE_TILT_FORWARD, BIND_AXIS, WIIMOTE_TILT_FORWARD, -1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, WIIMOTE_TILT_BACKWARD, BIND_AXIS, WIIMOTE_TILT_BACKWARD, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, WIIMOTE_TILT_LEFT, BIND_AXIS, WIIMOTE_TILT_LEFT, -1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, WIIMOTE_TILT_RIGHT, BIND_AXIS, WIIMOTE_TILT_RIGHT, 1.0f)); - - // Wii: Nunchuk - AddBind(TOUCHSCREEN_KEY, new sBind(a, NUNCHUK_BUTTON_C, BIND_BUTTON, NUNCHUK_BUTTON_C, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, NUNCHUK_BUTTON_Z, BIND_BUTTON, NUNCHUK_BUTTON_Z, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, NUNCHUK_TILT_MODIFIER, BIND_BUTTON, NUNCHUK_TILT_MODIFIER, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, NUNCHUK_SHAKE_X, BIND_BUTTON, NUNCHUK_SHAKE_X, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, NUNCHUK_SHAKE_Y, BIND_BUTTON, NUNCHUK_SHAKE_Y, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, NUNCHUK_SHAKE_Z, BIND_BUTTON, NUNCHUK_SHAKE_Z, 1.0f)); - - AddBind(TOUCHSCREEN_KEY, new sBind(a, NUNCHUK_SWING_UP, BIND_AXIS, NUNCHUK_SWING_UP, -1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, NUNCHUK_SWING_DOWN, BIND_AXIS, NUNCHUK_SWING_DOWN, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, NUNCHUK_SWING_LEFT, BIND_AXIS, NUNCHUK_SWING_LEFT, -1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, NUNCHUK_SWING_RIGHT, BIND_AXIS, NUNCHUK_SWING_RIGHT, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, NUNCHUK_SWING_FORWARD, BIND_AXIS, NUNCHUK_SWING_FORWARD, -1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, NUNCHUK_SWING_BACKWARD, BIND_BUTTON, NUNCHUK_SWING_BACKWARD, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, NUNCHUK_TILT_FORWARD, BIND_AXIS, NUNCHUK_TILT_FORWARD, -1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, NUNCHUK_TILT_BACKWARD, BIND_AXIS, NUNCHUK_TILT_BACKWARD, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, NUNCHUK_TILT_LEFT, BIND_AXIS, NUNCHUK_TILT_LEFT, -1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, NUNCHUK_TILT_RIGHT, BIND_AXIS, NUNCHUK_TILT_RIGHT, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, NUNCHUK_STICK_UP, BIND_AXIS, NUNCHUK_STICK_UP, -1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, NUNCHUK_STICK_DOWN, BIND_AXIS, NUNCHUK_STICK_DOWN, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, NUNCHUK_STICK_LEFT, BIND_AXIS, NUNCHUK_STICK_LEFT, -1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, NUNCHUK_STICK_RIGHT, BIND_AXIS, NUNCHUK_STICK_RIGHT, 1.0f)); - - // Wii: Classic - AddBind(TOUCHSCREEN_KEY, new sBind(a, CLASSIC_BUTTON_A, BIND_BUTTON, CLASSIC_BUTTON_A, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, CLASSIC_BUTTON_B, BIND_BUTTON, CLASSIC_BUTTON_B, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, CLASSIC_BUTTON_X, BIND_BUTTON, CLASSIC_BUTTON_X, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, CLASSIC_BUTTON_Y, BIND_BUTTON, CLASSIC_BUTTON_Y, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, CLASSIC_BUTTON_MINUS, BIND_BUTTON, CLASSIC_BUTTON_MINUS, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, CLASSIC_BUTTON_PLUS, BIND_BUTTON, CLASSIC_BUTTON_PLUS, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, CLASSIC_BUTTON_HOME, BIND_BUTTON, CLASSIC_BUTTON_HOME, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, CLASSIC_BUTTON_ZL, BIND_BUTTON, CLASSIC_BUTTON_ZL, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, CLASSIC_BUTTON_ZR, BIND_BUTTON, CLASSIC_BUTTON_ZR, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, CLASSIC_DPAD_UP, BIND_BUTTON, CLASSIC_DPAD_UP, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, CLASSIC_DPAD_DOWN, BIND_BUTTON, CLASSIC_DPAD_DOWN, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, CLASSIC_DPAD_LEFT, BIND_BUTTON, CLASSIC_DPAD_LEFT, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, CLASSIC_DPAD_RIGHT, BIND_BUTTON, CLASSIC_DPAD_RIGHT, 1.0f)); - - AddBind(TOUCHSCREEN_KEY, - new sBind(a, CLASSIC_STICK_LEFT_UP, BIND_AXIS, CLASSIC_STICK_LEFT_UP, -1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, CLASSIC_STICK_LEFT_DOWN, BIND_AXIS, CLASSIC_STICK_LEFT_DOWN, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, CLASSIC_STICK_LEFT_LEFT, BIND_AXIS, CLASSIC_STICK_LEFT_LEFT, -1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, CLASSIC_STICK_LEFT_RIGHT, BIND_AXIS, CLASSIC_STICK_LEFT_RIGHT, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, CLASSIC_STICK_RIGHT_UP, BIND_AXIS, CLASSIC_STICK_RIGHT_UP, -1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, CLASSIC_STICK_RIGHT_DOWN, BIND_AXIS, CLASSIC_STICK_RIGHT_DOWN, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, CLASSIC_STICK_RIGHT_LEFT, BIND_AXIS, CLASSIC_STICK_RIGHT_LEFT, -1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, CLASSIC_STICK_RIGHT_RIGHT, BIND_AXIS, CLASSIC_STICK_RIGHT_RIGHT, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, CLASSIC_TRIGGER_L, BIND_AXIS, CLASSIC_TRIGGER_L, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, CLASSIC_TRIGGER_R, BIND_AXIS, CLASSIC_TRIGGER_R, 1.0f)); - - // Wii: Guitar - AddBind(TOUCHSCREEN_KEY, - new sBind(a, GUITAR_BUTTON_MINUS, BIND_BUTTON, GUITAR_BUTTON_MINUS, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, GUITAR_BUTTON_PLUS, BIND_BUTTON, GUITAR_BUTTON_PLUS, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, GUITAR_FRET_GREEN, BIND_BUTTON, GUITAR_FRET_GREEN, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, GUITAR_FRET_RED, BIND_BUTTON, GUITAR_FRET_RED, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, GUITAR_FRET_YELLOW, BIND_BUTTON, GUITAR_FRET_YELLOW, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, GUITAR_FRET_BLUE, BIND_BUTTON, GUITAR_FRET_BLUE, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, GUITAR_FRET_ORANGE, BIND_BUTTON, GUITAR_FRET_ORANGE, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, GUITAR_STRUM_UP, BIND_BUTTON, GUITAR_STRUM_UP, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, GUITAR_STRUM_DOWN, BIND_BUTTON, GUITAR_STRUM_DOWN, 1.0f)); - - AddBind(TOUCHSCREEN_KEY, new sBind(a, GUITAR_STICK_UP, BIND_AXIS, GUITAR_STICK_UP, -1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, GUITAR_STICK_DOWN, BIND_AXIS, GUITAR_STICK_DOWN, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, GUITAR_STICK_LEFT, BIND_AXIS, GUITAR_STICK_LEFT, -1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, GUITAR_STICK_RIGHT, BIND_AXIS, GUITAR_STICK_RIGHT, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, GUITAR_WHAMMY_BAR, BIND_AXIS, GUITAR_WHAMMY_BAR, 1.0f)); - - // Wii: Drums - AddBind(TOUCHSCREEN_KEY, - new sBind(a, DRUMS_BUTTON_MINUS, BIND_BUTTON, DRUMS_BUTTON_MINUS, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, DRUMS_BUTTON_PLUS, BIND_BUTTON, DRUMS_BUTTON_PLUS, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, DRUMS_PAD_RED, BIND_BUTTON, DRUMS_PAD_RED, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, DRUMS_PAD_YELLOW, BIND_BUTTON, DRUMS_PAD_YELLOW, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, DRUMS_PAD_BLUE, BIND_BUTTON, DRUMS_PAD_BLUE, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, DRUMS_PAD_GREEN, BIND_BUTTON, DRUMS_PAD_GREEN, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, DRUMS_PAD_ORANGE, BIND_BUTTON, DRUMS_PAD_ORANGE, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, DRUMS_PAD_BASS, BIND_BUTTON, DRUMS_PAD_BASS, 1.0f)); - - AddBind(TOUCHSCREEN_KEY, new sBind(a, DRUMS_STICK_UP, BIND_AXIS, DRUMS_STICK_UP, -1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, DRUMS_STICK_DOWN, BIND_AXIS, DRUMS_STICK_DOWN, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, DRUMS_STICK_LEFT, BIND_AXIS, DRUMS_STICK_LEFT, -1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, DRUMS_STICK_RIGHT, BIND_AXIS, DRUMS_STICK_RIGHT, 1.0f)); - - // Wii: Turntable - AddBind(TOUCHSCREEN_KEY, new sBind(a, TURNTABLE_BUTTON_GREEN_LEFT, BIND_BUTTON, - TURNTABLE_BUTTON_GREEN_LEFT, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, TURNTABLE_BUTTON_RED_LEFT, BIND_BUTTON, TURNTABLE_BUTTON_RED_LEFT, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, TURNTABLE_BUTTON_BLUE_LEFT, BIND_BUTTON, - TURNTABLE_BUTTON_BLUE_LEFT, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, TURNTABLE_BUTTON_GREEN_RIGHT, BIND_BUTTON, - TURNTABLE_BUTTON_GREEN_RIGHT, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, TURNTABLE_BUTTON_RED_RIGHT, BIND_BUTTON, - TURNTABLE_BUTTON_RED_RIGHT, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, TURNTABLE_BUTTON_BLUE_RIGHT, BIND_BUTTON, - TURNTABLE_BUTTON_BLUE_RIGHT, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, TURNTABLE_BUTTON_MINUS, BIND_BUTTON, TURNTABLE_BUTTON_MINUS, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, TURNTABLE_BUTTON_PLUS, BIND_BUTTON, TURNTABLE_BUTTON_PLUS, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, TURNTABLE_BUTTON_HOME, BIND_BUTTON, TURNTABLE_BUTTON_HOME, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, TURNTABLE_BUTTON_EUPHORIA, BIND_BUTTON, TURNTABLE_BUTTON_EUPHORIA, 1.0f)); - - AddBind(TOUCHSCREEN_KEY, - new sBind(a, TURNTABLE_TABLE_LEFT_LEFT, BIND_AXIS, TURNTABLE_TABLE_LEFT_LEFT, -1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, TURNTABLE_TABLE_LEFT_RIGHT, BIND_AXIS, TURNTABLE_TABLE_LEFT_RIGHT, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, TURNTABLE_TABLE_RIGHT_LEFT, BIND_AXIS, TURNTABLE_TABLE_RIGHT_LEFT, -1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, TURNTABLE_TABLE_RIGHT_RIGHT, BIND_AXIS, - TURNTABLE_TABLE_RIGHT_RIGHT, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, TURNTABLE_STICK_UP, BIND_AXIS, TURNTABLE_STICK_UP, -1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, TURNTABLE_STICK_DOWN, BIND_AXIS, TURNTABLE_STICK_DOWN, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, TURNTABLE_STICK_LEFT, BIND_AXIS, TURNTABLE_STICK_LEFT, -1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, TURNTABLE_STICK_RIGHT, BIND_AXIS, TURNTABLE_STICK_RIGHT, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, TURNTABLE_EFFECT_DIAL, BIND_AXIS, TURNTABLE_EFFECT_DIAL, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, TURNTABLE_CROSSFADE_LEFT, BIND_AXIS, TURNTABLE_CROSSFADE_LEFT, -1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, TURNTABLE_CROSSFADE_RIGHT, BIND_AXIS, TURNTABLE_CROSSFADE_RIGHT, 1.0f)); - - // Wiimote IMU - AddBind(TOUCHSCREEN_KEY, new sBind(a, WIIMOTE_ACCEL_LEFT, BIND_AXIS, WIIMOTE_ACCEL_LEFT, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, WIIMOTE_ACCEL_RIGHT, BIND_AXIS, WIIMOTE_ACCEL_RIGHT, -1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, WIIMOTE_ACCEL_FORWARD, BIND_AXIS, WIIMOTE_ACCEL_FORWARD, -1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, WIIMOTE_ACCEL_BACKWARD, BIND_AXIS, WIIMOTE_ACCEL_BACKWARD, 1.0f)); - AddBind(TOUCHSCREEN_KEY, new sBind(a, WIIMOTE_ACCEL_UP, BIND_AXIS, WIIMOTE_ACCEL_UP, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, WIIMOTE_ACCEL_DOWN, BIND_AXIS, WIIMOTE_ACCEL_DOWN, -1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, WIIMOTE_GYRO_PITCH_UP, BIND_AXIS, WIIMOTE_GYRO_PITCH_UP, -1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, WIIMOTE_GYRO_PITCH_DOWN, BIND_AXIS, WIIMOTE_GYRO_PITCH_DOWN, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, WIIMOTE_GYRO_ROLL_LEFT, BIND_AXIS, WIIMOTE_GYRO_ROLL_LEFT, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, WIIMOTE_GYRO_ROLL_RIGHT, BIND_AXIS, WIIMOTE_GYRO_ROLL_RIGHT, -1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, WIIMOTE_GYRO_YAW_LEFT, BIND_AXIS, WIIMOTE_GYRO_YAW_LEFT, 1.0f)); - AddBind(TOUCHSCREEN_KEY, - new sBind(a, WIIMOTE_GYRO_YAW_RIGHT, BIND_AXIS, WIIMOTE_GYRO_YAW_RIGHT, -1.0f)); - } - // Init our controller bindings - IniFile ini; - ini.Load(File::GetUserPath(D_CONFIG_IDX) + std::string("Dolphin.ini"), true); - ini.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + std::string(game_id + ".ini"), true); - for (u32 a = 0; a < CONFIG_STRINGS.size(); ++a) - { - for (int pad_id = 0; pad_id < 8; ++pad_id) - { - std::ostringstream config; - config << CONFIG_STRINGS[a] << "_" << pad_id; - BindType type; - int bindnum; - char dev[128]{}; - bool hasbind = false; - char modifier = '+'; - std::string value; - ini.GetOrCreateSection("Android")->Get(config.str(), &value, "None"); - if (value == "None") - continue; - if (std::string::npos != value.find("Axis")) - { - hasbind = true; - type = BIND_AXIS; - if (value.starts_with("Device ''")) - sscanf(value.c_str(), "Device ''-Axis %d%c", &bindnum, &modifier); - else - sscanf(value.c_str(), "Device '%127[^\']'-Axis %d%c", dev, &bindnum, &modifier); - } - else if (std::string::npos != value.find("Button")) - { - hasbind = true; - type = BIND_BUTTON; - if (value.starts_with("Device ''")) - sscanf(value.c_str(), "Device ''-Button %d", &bindnum); - else - sscanf(value.c_str(), "Device '%127[^\']'-Button %d", dev, &bindnum); - } - if (hasbind) - AddBind(std::string(dev), - new sBind(pad_id, CONFIG_TYPES[a], type, bindnum, modifier == '-' ? -1.0f : 1.0f)); - } - } -} - -bool GetButtonPressed(int pad_id, ButtonType button) -{ - bool pressed = m_controllers[TOUCHSCREEN_KEY]->ButtonValue(pad_id, button); - - for (const auto& ctrl : m_controllers) - pressed |= ctrl.second->ButtonValue(pad_id, button); - - return pressed; -} - -float GetAxisValue(int pad_id, ButtonType axis) -{ - float value = m_controllers[TOUCHSCREEN_KEY]->AxisValue(pad_id, axis); - if (value == 0.0f) - { - for (const auto& ctrl : m_controllers) - { - value = ctrl.second->AxisValue(pad_id, axis); - if (value != 0.0f) - return value; - } - } - return value; -} - -bool GamepadEvent(const std::string& dev, int button, int action) -{ - auto it = m_controllers.find(dev); - if (it != m_controllers.end()) - return it->second->PressEvent(button, action); - return false; -} - -void GamepadAxisEvent(const std::string& dev, int axis, float value) -{ - auto it = m_controllers.find(dev); - if (it != m_controllers.end()) - it->second->AxisEvent(axis, value); -} - -void Shutdown() -{ - for (const auto& controller : m_controllers) - delete controller.second; - m_controllers.clear(); -} - -// InputDevice -bool InputDevice::PressEvent(int button, int action) -{ - bool handled = false; - for (const auto& binding : m_input_binds) - { - if (binding.second->m_bind == button) - { - if (binding.second->m_bind_type == BIND_BUTTON) - m_buttons[binding.second->m_button_type] = action == BUTTON_PRESSED ? true : false; - else - m_axes[binding.second->m_button_type] = action == BUTTON_PRESSED ? 1.0f : 0.0f; - handled = true; - } - } - return handled; -} - -void InputDevice::AxisEvent(int axis, float value) -{ - for (const auto& binding : m_input_binds) - { - if (binding.second->m_bind == axis) - { - if (binding.second->m_bind_type == BIND_AXIS) - m_axes[binding.second->m_button_type] = value; - else - m_buttons[binding.second->m_button_type] = value > 0.5f ? true : false; - } - } -} - -bool InputDevice::ButtonValue(int pad_id, ButtonType button) const -{ - const auto binding = m_input_binds.find(std::make_pair(pad_id, button)); - if (binding == m_input_binds.end()) - return false; - - if (binding->second->m_bind_type == BIND_BUTTON) - { - const auto button = m_buttons.find(binding->second->m_button_type); - if (button == m_buttons.end()) - return false; - return button->second; - } - else - { - const auto axis = m_axes.find(binding->second->m_button_type); - if (axis == m_axes.end()) - return false; - return (axis->second * binding->second->m_neg) > 0.5f; - } -} - -float InputDevice::AxisValue(int pad_id, ButtonType axis) const -{ - const auto binding = m_input_binds.find(std::make_pair(pad_id, axis)); - if (binding == m_input_binds.end()) - return 0.0f; - - if (binding->second->m_bind_type == BIND_AXIS) - { - const auto axis = m_axes.find(binding->second->m_button_type); - if (axis == m_axes.end()) - return 0.0f; - return axis->second * binding->second->m_neg; - } - else - { - const auto button = m_buttons.find(binding->second->m_button_type); - if (button == m_buttons.end()) - return 0.0f; - return button->second == BUTTON_PRESSED ? 1.0f : 0.0f; - } -} -} // namespace ButtonManager diff --git a/Source/Core/InputCommon/ControllerInterface/Touch/ButtonManager.h b/Source/Core/InputCommon/ControllerInterface/Touch/ButtonManager.h deleted file mode 100644 index 08c4349c84..0000000000 --- a/Source/Core/InputCommon/ControllerInterface/Touch/ButtonManager.h +++ /dev/null @@ -1,279 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include - -namespace ButtonManager -{ -enum ButtonType -{ - // GC - BUTTON_A = 0, - BUTTON_B = 1, - BUTTON_START = 2, - BUTTON_X = 3, - BUTTON_Y = 4, - BUTTON_Z = 5, - BUTTON_UP = 6, - BUTTON_DOWN = 7, - BUTTON_LEFT = 8, - BUTTON_RIGHT = 9, - STICK_MAIN = 10, // Used on Java Side - STICK_MAIN_UP = 11, - STICK_MAIN_DOWN = 12, - STICK_MAIN_LEFT = 13, - STICK_MAIN_RIGHT = 14, - STICK_C = 15, // Used on Java Side - STICK_C_UP = 16, - STICK_C_DOWN = 17, - STICK_C_LEFT = 18, - STICK_C_RIGHT = 19, - TRIGGER_L = 20, - TRIGGER_R = 21, - // Wiimote - WIIMOTE_BUTTON_A = 100, - WIIMOTE_BUTTON_B = 101, - WIIMOTE_BUTTON_MINUS = 102, - WIIMOTE_BUTTON_PLUS = 103, - WIIMOTE_BUTTON_HOME = 104, - WIIMOTE_BUTTON_1 = 105, - WIIMOTE_BUTTON_2 = 106, - WIIMOTE_UP = 107, - WIIMOTE_DOWN = 108, - WIIMOTE_LEFT = 109, - WIIMOTE_RIGHT = 110, - WIIMOTE_IR = 111, // To Be Used on Java Side - WIIMOTE_IR_UP = 112, - WIIMOTE_IR_DOWN = 113, - WIIMOTE_IR_LEFT = 114, - WIIMOTE_IR_RIGHT = 115, - WIIMOTE_IR_FORWARD = 116, - WIIMOTE_IR_BACKWARD = 117, - WIIMOTE_IR_HIDE = 118, - WIIMOTE_SWING = 119, // To Be Used on Java Side - WIIMOTE_SWING_UP = 120, - WIIMOTE_SWING_DOWN = 121, - WIIMOTE_SWING_LEFT = 122, - WIIMOTE_SWING_RIGHT = 123, - WIIMOTE_SWING_FORWARD = 124, - WIIMOTE_SWING_BACKWARD = 125, - WIIMOTE_TILT = 126, // To Be Used on Java Side - WIIMOTE_TILT_FORWARD = 127, - WIIMOTE_TILT_BACKWARD = 128, - WIIMOTE_TILT_LEFT = 129, - WIIMOTE_TILT_RIGHT = 130, - WIIMOTE_TILT_MODIFIER = 131, - WIIMOTE_SHAKE_X = 132, - WIIMOTE_SHAKE_Y = 133, - WIIMOTE_SHAKE_Z = 134, - // Nunchuk - NUNCHUK_BUTTON_C = 200, - NUNCHUK_BUTTON_Z = 201, - NUNCHUK_STICK = 202, // To Be Used on Java Side - NUNCHUK_STICK_UP = 203, - NUNCHUK_STICK_DOWN = 204, - NUNCHUK_STICK_LEFT = 205, - NUNCHUK_STICK_RIGHT = 206, - NUNCHUK_SWING = 207, // To Be Used on Java Side - NUNCHUK_SWING_UP = 208, - NUNCHUK_SWING_DOWN = 209, - NUNCHUK_SWING_LEFT = 210, - NUNCHUK_SWING_RIGHT = 211, - NUNCHUK_SWING_FORWARD = 212, - NUNCHUK_SWING_BACKWARD = 213, - NUNCHUK_TILT = 214, // To Be Used on Java Side - NUNCHUK_TILT_FORWARD = 215, - NUNCHUK_TILT_BACKWARD = 216, - NUNCHUK_TILT_LEFT = 217, - NUNCHUK_TILT_RIGHT = 218, - NUNCHUK_TILT_MODIFIER = 219, - NUNCHUK_SHAKE_X = 220, - NUNCHUK_SHAKE_Y = 221, - NUNCHUK_SHAKE_Z = 222, - // Classic - CLASSIC_BUTTON_A = 300, - CLASSIC_BUTTON_B = 301, - CLASSIC_BUTTON_X = 302, - CLASSIC_BUTTON_Y = 303, - CLASSIC_BUTTON_MINUS = 304, - CLASSIC_BUTTON_PLUS = 305, - CLASSIC_BUTTON_HOME = 306, - CLASSIC_BUTTON_ZL = 307, - CLASSIC_BUTTON_ZR = 308, - CLASSIC_DPAD_UP = 309, - CLASSIC_DPAD_DOWN = 310, - CLASSIC_DPAD_LEFT = 311, - CLASSIC_DPAD_RIGHT = 312, - CLASSIC_STICK_LEFT = 313, // To Be Used on Java Side - CLASSIC_STICK_LEFT_UP = 314, - CLASSIC_STICK_LEFT_DOWN = 315, - CLASSIC_STICK_LEFT_LEFT = 316, - CLASSIC_STICK_LEFT_RIGHT = 317, - CLASSIC_STICK_RIGHT = 318, // To Be Used on Java Side - CLASSIC_STICK_RIGHT_UP = 319, - CLASSIC_STICK_RIGHT_DOWN = 320, - CLASSIC_STICK_RIGHT_LEFT = 321, - CLASSIC_STICK_RIGHT_RIGHT = 322, - CLASSIC_TRIGGER_L = 323, - CLASSIC_TRIGGER_R = 324, - // Guitar - GUITAR_BUTTON_MINUS = 400, - GUITAR_BUTTON_PLUS = 401, - GUITAR_FRET_GREEN = 402, - GUITAR_FRET_RED = 403, - GUITAR_FRET_YELLOW = 404, - GUITAR_FRET_BLUE = 405, - GUITAR_FRET_ORANGE = 406, - GUITAR_STRUM_UP = 407, - GUITAR_STRUM_DOWN = 408, - GUITAR_STICK = 409, // To Be Used on Java Side - GUITAR_STICK_UP = 410, - GUITAR_STICK_DOWN = 411, - GUITAR_STICK_LEFT = 412, - GUITAR_STICK_RIGHT = 413, - GUITAR_WHAMMY_BAR = 414, - // Drums - DRUMS_BUTTON_MINUS = 500, - DRUMS_BUTTON_PLUS = 501, - DRUMS_PAD_RED = 502, - DRUMS_PAD_YELLOW = 503, - DRUMS_PAD_BLUE = 504, - DRUMS_PAD_GREEN = 505, - DRUMS_PAD_ORANGE = 506, - DRUMS_PAD_BASS = 507, - DRUMS_STICK = 508, // To Be Used on Java Side - DRUMS_STICK_UP = 509, - DRUMS_STICK_DOWN = 510, - DRUMS_STICK_LEFT = 511, - DRUMS_STICK_RIGHT = 512, - // Turntable - TURNTABLE_BUTTON_GREEN_LEFT = 600, - TURNTABLE_BUTTON_RED_LEFT = 601, - TURNTABLE_BUTTON_BLUE_LEFT = 602, - TURNTABLE_BUTTON_GREEN_RIGHT = 603, - TURNTABLE_BUTTON_RED_RIGHT = 604, - TURNTABLE_BUTTON_BLUE_RIGHT = 605, - TURNTABLE_BUTTON_MINUS = 606, - TURNTABLE_BUTTON_PLUS = 607, - TURNTABLE_BUTTON_HOME = 608, - TURNTABLE_BUTTON_EUPHORIA = 609, - TURNTABLE_TABLE_LEFT = 610, // To Be Used on Java Side - TURNTABLE_TABLE_LEFT_LEFT = 611, - TURNTABLE_TABLE_LEFT_RIGHT = 612, - TURNTABLE_TABLE_RIGHT = 613, // To Be Used on Java Side - TURNTABLE_TABLE_RIGHT_LEFT = 614, - TURNTABLE_TABLE_RIGHT_RIGHT = 615, - TURNTABLE_STICK = 616, // To Be Used on Java Side - TURNTABLE_STICK_UP = 617, - TURNTABLE_STICK_DOWN = 618, - TURNTABLE_STICK_LEFT = 619, - TURNTABLE_STICK_RIGHT = 620, - TURNTABLE_EFFECT_DIAL = 621, - 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, -}; -enum ButtonState -{ - BUTTON_RELEASED = 0, - BUTTON_PRESSED = 1 -}; -enum BindType -{ - BIND_BUTTON = 0, - BIND_AXIS -}; -class Button -{ -private: - ButtonState m_state; - -public: - Button() : m_state(BUTTON_RELEASED) {} - void SetState(ButtonState state) { m_state = state; } - bool Pressed() const { return m_state == BUTTON_PRESSED; } - ~Button() {} -}; -class Axis -{ -private: - float m_value; - -public: - Axis() : m_value(0.0f) {} - void SetValue(float value) { m_value = value; } - float AxisValue() const { return m_value; } - ~Axis() {} -}; - -struct sBind -{ - const int m_pad_id; - const ButtonType m_button_type; - const BindType m_bind_type; - const int m_bind; - const float m_neg; - sBind(int pad_id, ButtonType button_type, BindType bind_type, int bind, float neg) - : m_pad_id(pad_id), m_button_type(button_type), m_bind_type(bind_type), m_bind(bind), - m_neg(neg) - { - } -}; - -class InputDevice -{ -private: - const std::string m_dev; - std::map m_buttons; - std::map m_axes; - - // Key is pad_id and ButtonType - std::map, sBind*> m_input_binds; - -public: - InputDevice(std::string dev) : m_dev(dev) {} - ~InputDevice() - { - for (const auto& bind : m_input_binds) - delete bind.second; - m_input_binds.clear(); - } - void AddBind(sBind* bind) - { - m_input_binds[std::make_pair(bind->m_pad_id, bind->m_button_type)] = bind; - } - bool PressEvent(int button, int action); - void AxisEvent(int axis, float value); - bool ButtonValue(int pad_id, ButtonType button) const; - float AxisValue(int pad_id, ButtonType axis) const; -}; - -void Init(const std::string&); - -// pad_id is numbered 0 to 3 for GC pads and 4 to 7 for Wiimotes -bool GetButtonPressed(int pad_id, ButtonType button); -float GetAxisValue(int pad_id, ButtonType axis); - -bool GamepadEvent(const std::string& dev, int button, int action); -void GamepadAxisEvent(const std::string& dev, int axis, float value); - -void Shutdown(); -} // namespace ButtonManager diff --git a/Source/Core/InputCommon/ControllerInterface/Touch/Touchscreen.cpp b/Source/Core/InputCommon/ControllerInterface/Touch/Touchscreen.cpp deleted file mode 100644 index a4c20b0ae0..0000000000 --- a/Source/Core/InputCommon/ControllerInterface/Touch/Touchscreen.cpp +++ /dev/null @@ -1,264 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "InputCommon/ControllerInterface/Touch/Touchscreen.h" - -#include -#include -#ifdef ANDROID -#include -#endif - -#include "InputCommon/ControllerInterface/ControllerInterface.h" - -namespace ciface::Touch -{ -// Touchscreens and stuff -std::string Touchscreen::GetName() const -{ - return "Touchscreen"; -} - -std::string Touchscreen::GetSource() const -{ - return "Android"; -} - -Touchscreen::Touchscreen(int pad_id, bool accelerometer_enabled, bool gyroscope_enabled) - : m_pad_id(pad_id) -{ - // GC - AddInput(new Button(m_pad_id, ButtonManager::BUTTON_A)); - AddInput(new Button(m_pad_id, ButtonManager::BUTTON_B)); - AddInput(new Button(m_pad_id, ButtonManager::BUTTON_START)); - AddInput(new Button(m_pad_id, ButtonManager::BUTTON_X)); - AddInput(new Button(m_pad_id, ButtonManager::BUTTON_Y)); - AddInput(new Button(m_pad_id, ButtonManager::BUTTON_Z)); - AddInput(new Button(m_pad_id, ButtonManager::BUTTON_UP)); - AddInput(new Button(m_pad_id, ButtonManager::BUTTON_DOWN)); - AddInput(new Button(m_pad_id, ButtonManager::BUTTON_LEFT)); - AddInput(new Button(m_pad_id, ButtonManager::BUTTON_RIGHT)); - AddInput(new Axis(m_pad_id, ButtonManager::STICK_MAIN_LEFT)); - AddInput(new Axis(m_pad_id, ButtonManager::STICK_MAIN_RIGHT)); - AddInput(new Axis(m_pad_id, ButtonManager::STICK_MAIN_UP)); - AddInput(new Axis(m_pad_id, ButtonManager::STICK_MAIN_DOWN)); - AddInput(new Axis(m_pad_id, ButtonManager::STICK_C_LEFT)); - AddInput(new Axis(m_pad_id, ButtonManager::STICK_C_RIGHT)); - AddInput(new Axis(m_pad_id, ButtonManager::STICK_C_UP)); - AddInput(new Axis(m_pad_id, ButtonManager::STICK_C_DOWN)); - AddInput(new Axis(m_pad_id, ButtonManager::TRIGGER_L)); - AddInput(new Axis(m_pad_id, ButtonManager::TRIGGER_R)); - - // Wiimote - AddInput(new Button(m_pad_id, ButtonManager::WIIMOTE_BUTTON_A)); - AddInput(new Button(m_pad_id, ButtonManager::WIIMOTE_BUTTON_B)); - AddInput(new Button(m_pad_id, ButtonManager::WIIMOTE_BUTTON_MINUS)); - AddInput(new Button(m_pad_id, ButtonManager::WIIMOTE_BUTTON_PLUS)); - AddInput(new Button(m_pad_id, ButtonManager::WIIMOTE_BUTTON_HOME)); - AddInput(new Button(m_pad_id, ButtonManager::WIIMOTE_BUTTON_1)); - AddInput(new Button(m_pad_id, ButtonManager::WIIMOTE_BUTTON_2)); - AddInput(new Button(m_pad_id, ButtonManager::WIIMOTE_UP)); - AddInput(new Button(m_pad_id, ButtonManager::WIIMOTE_DOWN)); - AddInput(new Button(m_pad_id, ButtonManager::WIIMOTE_LEFT)); - AddInput(new Button(m_pad_id, ButtonManager::WIIMOTE_RIGHT)); - AddInput(new Button(m_pad_id, ButtonManager::WIIMOTE_IR_HIDE)); - AddInput(new Button(m_pad_id, ButtonManager::WIIMOTE_TILT_MODIFIER)); - AddInput(new Button(m_pad_id, ButtonManager::WIIMOTE_SHAKE_X)); - AddInput(new Button(m_pad_id, ButtonManager::WIIMOTE_SHAKE_Y)); - AddInput(new Button(m_pad_id, ButtonManager::WIIMOTE_SHAKE_Z)); - AddInput(new Axis(m_pad_id, ButtonManager::WIIMOTE_IR_UP)); - AddInput(new Axis(m_pad_id, ButtonManager::WIIMOTE_IR_DOWN)); - AddInput(new Axis(m_pad_id, ButtonManager::WIIMOTE_IR_LEFT)); - AddInput(new Axis(m_pad_id, ButtonManager::WIIMOTE_IR_RIGHT)); - AddInput(new Axis(m_pad_id, ButtonManager::WIIMOTE_IR_FORWARD)); - AddInput(new Axis(m_pad_id, ButtonManager::WIIMOTE_IR_BACKWARD)); - AddInput(new Axis(m_pad_id, ButtonManager::WIIMOTE_SWING_UP)); - AddInput(new Axis(m_pad_id, ButtonManager::WIIMOTE_SWING_DOWN)); - AddInput(new Axis(m_pad_id, ButtonManager::WIIMOTE_SWING_LEFT)); - AddInput(new Axis(m_pad_id, ButtonManager::WIIMOTE_SWING_RIGHT)); - AddInput(new Axis(m_pad_id, ButtonManager::WIIMOTE_SWING_FORWARD)); - AddInput(new Axis(m_pad_id, ButtonManager::WIIMOTE_SWING_BACKWARD)); - AddInput(new Axis(m_pad_id, ButtonManager::WIIMOTE_TILT_LEFT)); - AddInput(new Axis(m_pad_id, ButtonManager::WIIMOTE_TILT_RIGHT)); - AddInput(new Axis(m_pad_id, ButtonManager::WIIMOTE_TILT_FORWARD)); - AddInput(new Axis(m_pad_id, ButtonManager::WIIMOTE_TILT_BACKWARD)); - - // Wii ext: Nunchuk - AddInput(new Button(m_pad_id, ButtonManager::NUNCHUK_BUTTON_C)); - AddInput(new Button(m_pad_id, ButtonManager::NUNCHUK_BUTTON_Z)); - AddInput(new Button(m_pad_id, ButtonManager::NUNCHUK_TILT_MODIFIER)); - AddInput(new Button(m_pad_id, ButtonManager::NUNCHUK_SHAKE_X)); - AddInput(new Button(m_pad_id, ButtonManager::NUNCHUK_SHAKE_Y)); - AddInput(new Button(m_pad_id, ButtonManager::NUNCHUK_SHAKE_Z)); - AddInput(new Axis(m_pad_id, ButtonManager::NUNCHUK_STICK_LEFT)); - AddInput(new Axis(m_pad_id, ButtonManager::NUNCHUK_STICK_RIGHT)); - AddInput(new Axis(m_pad_id, ButtonManager::NUNCHUK_STICK_UP)); - AddInput(new Axis(m_pad_id, ButtonManager::NUNCHUK_STICK_DOWN)); - AddInput(new Axis(m_pad_id, ButtonManager::NUNCHUK_SWING_LEFT)); - AddInput(new Axis(m_pad_id, ButtonManager::NUNCHUK_SWING_RIGHT)); - AddInput(new Axis(m_pad_id, ButtonManager::NUNCHUK_SWING_UP)); - AddInput(new Axis(m_pad_id, ButtonManager::NUNCHUK_SWING_DOWN)); - AddInput(new Axis(m_pad_id, ButtonManager::NUNCHUK_SWING_FORWARD)); - AddInput(new Axis(m_pad_id, ButtonManager::NUNCHUK_SWING_BACKWARD)); - AddInput(new Axis(m_pad_id, ButtonManager::NUNCHUK_TILT_LEFT)); - AddInput(new Axis(m_pad_id, ButtonManager::NUNCHUK_TILT_RIGHT)); - AddInput(new Axis(m_pad_id, ButtonManager::NUNCHUK_TILT_FORWARD)); - AddInput(new Axis(m_pad_id, ButtonManager::NUNCHUK_TILT_BACKWARD)); - - // Wii ext: Classic - AddInput(new Button(m_pad_id, ButtonManager::CLASSIC_BUTTON_A)); - AddInput(new Button(m_pad_id, ButtonManager::CLASSIC_BUTTON_B)); - AddInput(new Button(m_pad_id, ButtonManager::CLASSIC_BUTTON_X)); - AddInput(new Button(m_pad_id, ButtonManager::CLASSIC_BUTTON_Y)); - AddInput(new Button(m_pad_id, ButtonManager::CLASSIC_BUTTON_MINUS)); - AddInput(new Button(m_pad_id, ButtonManager::CLASSIC_BUTTON_PLUS)); - AddInput(new Button(m_pad_id, ButtonManager::CLASSIC_BUTTON_HOME)); - AddInput(new Button(m_pad_id, ButtonManager::CLASSIC_BUTTON_ZL)); - AddInput(new Button(m_pad_id, ButtonManager::CLASSIC_BUTTON_ZR)); - AddInput(new Button(m_pad_id, ButtonManager::CLASSIC_DPAD_UP)); - AddInput(new Button(m_pad_id, ButtonManager::CLASSIC_DPAD_DOWN)); - AddInput(new Button(m_pad_id, ButtonManager::CLASSIC_DPAD_LEFT)); - AddInput(new Button(m_pad_id, ButtonManager::CLASSIC_DPAD_RIGHT)); - AddInput(new Axis(m_pad_id, ButtonManager::CLASSIC_STICK_LEFT_LEFT)); - AddInput(new Axis(m_pad_id, ButtonManager::CLASSIC_STICK_LEFT_RIGHT)); - AddInput(new Axis(m_pad_id, ButtonManager::CLASSIC_STICK_LEFT_UP)); - AddInput(new Axis(m_pad_id, ButtonManager::CLASSIC_STICK_LEFT_DOWN)); - AddInput(new Axis(m_pad_id, ButtonManager::CLASSIC_STICK_RIGHT_LEFT)); - AddInput(new Axis(m_pad_id, ButtonManager::CLASSIC_STICK_RIGHT_RIGHT)); - AddInput(new Axis(m_pad_id, ButtonManager::CLASSIC_STICK_RIGHT_UP)); - AddInput(new Axis(m_pad_id, ButtonManager::CLASSIC_STICK_RIGHT_DOWN)); - AddInput(new Axis(m_pad_id, ButtonManager::CLASSIC_TRIGGER_L)); - AddInput(new Axis(m_pad_id, ButtonManager::CLASSIC_TRIGGER_R)); - - // Wii-ext: Guitar - AddInput(new Button(m_pad_id, ButtonManager::GUITAR_BUTTON_MINUS)); - AddInput(new Button(m_pad_id, ButtonManager::GUITAR_BUTTON_PLUS)); - AddInput(new Button(m_pad_id, ButtonManager::GUITAR_FRET_GREEN)); - AddInput(new Button(m_pad_id, ButtonManager::GUITAR_FRET_RED)); - AddInput(new Button(m_pad_id, ButtonManager::GUITAR_FRET_YELLOW)); - AddInput(new Button(m_pad_id, ButtonManager::GUITAR_FRET_BLUE)); - AddInput(new Button(m_pad_id, ButtonManager::GUITAR_FRET_ORANGE)); - AddInput(new Button(m_pad_id, ButtonManager::GUITAR_STRUM_UP)); - AddInput(new Button(m_pad_id, ButtonManager::GUITAR_STRUM_DOWN)); - AddInput(new Axis(m_pad_id, ButtonManager::GUITAR_STICK_LEFT)); - AddInput(new Axis(m_pad_id, ButtonManager::GUITAR_STICK_RIGHT)); - AddInput(new Axis(m_pad_id, ButtonManager::GUITAR_STICK_UP)); - AddInput(new Axis(m_pad_id, ButtonManager::GUITAR_STICK_DOWN)); - AddInput(new Axis(m_pad_id, ButtonManager::GUITAR_WHAMMY_BAR)); - - // Wii-ext: Drums - AddInput(new Button(m_pad_id, ButtonManager::DRUMS_BUTTON_MINUS)); - AddInput(new Button(m_pad_id, ButtonManager::DRUMS_BUTTON_PLUS)); - AddInput(new Button(m_pad_id, ButtonManager::DRUMS_PAD_RED)); - AddInput(new Button(m_pad_id, ButtonManager::DRUMS_PAD_YELLOW)); - AddInput(new Button(m_pad_id, ButtonManager::DRUMS_PAD_BLUE)); - AddInput(new Button(m_pad_id, ButtonManager::DRUMS_PAD_GREEN)); - AddInput(new Button(m_pad_id, ButtonManager::DRUMS_PAD_ORANGE)); - AddInput(new Button(m_pad_id, ButtonManager::DRUMS_PAD_BASS)); - AddInput(new Axis(m_pad_id, ButtonManager::DRUMS_STICK_LEFT)); - AddInput(new Axis(m_pad_id, ButtonManager::DRUMS_STICK_RIGHT)); - AddInput(new Axis(m_pad_id, ButtonManager::DRUMS_STICK_UP)); - AddInput(new Axis(m_pad_id, ButtonManager::DRUMS_STICK_DOWN)); - - // Wii-ext: Turntable - AddInput(new Button(m_pad_id, ButtonManager::TURNTABLE_BUTTON_GREEN_LEFT)); - AddInput(new Button(m_pad_id, ButtonManager::TURNTABLE_BUTTON_RED_LEFT)); - AddInput(new Button(m_pad_id, ButtonManager::TURNTABLE_BUTTON_BLUE_LEFT)); - AddInput(new Button(m_pad_id, ButtonManager::TURNTABLE_BUTTON_GREEN_RIGHT)); - AddInput(new Button(m_pad_id, ButtonManager::TURNTABLE_BUTTON_RED_RIGHT)); - AddInput(new Button(m_pad_id, ButtonManager::TURNTABLE_BUTTON_BLUE_RIGHT)); - AddInput(new Button(m_pad_id, ButtonManager::TURNTABLE_BUTTON_MINUS)); - AddInput(new Button(m_pad_id, ButtonManager::TURNTABLE_BUTTON_PLUS)); - AddInput(new Button(m_pad_id, ButtonManager::TURNTABLE_BUTTON_HOME)); - AddInput(new Button(m_pad_id, ButtonManager::TURNTABLE_BUTTON_EUPHORIA)); - AddInput(new Axis(m_pad_id, ButtonManager::TURNTABLE_TABLE_LEFT_LEFT)); - AddInput(new Axis(m_pad_id, ButtonManager::TURNTABLE_TABLE_LEFT_RIGHT)); - AddInput(new Axis(m_pad_id, ButtonManager::TURNTABLE_TABLE_RIGHT_LEFT)); - AddInput(new Axis(m_pad_id, ButtonManager::TURNTABLE_TABLE_RIGHT_RIGHT)); - AddInput(new Axis(m_pad_id, ButtonManager::TURNTABLE_STICK_LEFT)); - AddInput(new Axis(m_pad_id, ButtonManager::TURNTABLE_STICK_RIGHT)); - AddInput(new Axis(m_pad_id, ButtonManager::TURNTABLE_STICK_UP)); - AddInput(new Axis(m_pad_id, ButtonManager::TURNTABLE_STICK_DOWN)); - AddInput(new Axis(m_pad_id, ButtonManager::TURNTABLE_CROSSFADE_LEFT)); - AddInput(new Axis(m_pad_id, ButtonManager::TURNTABLE_CROSSFADE_RIGHT)); - AddInput(new Axis(m_pad_id, 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 (accelerometer_enabled) - { - AddInput(new Axis(m_pad_id, ButtonManager::WIIMOTE_ACCEL_LEFT)); - AddInput(new Axis(m_pad_id, ButtonManager::WIIMOTE_ACCEL_RIGHT)); - AddInput(new Axis(m_pad_id, ButtonManager::WIIMOTE_ACCEL_FORWARD)); - AddInput(new Axis(m_pad_id, ButtonManager::WIIMOTE_ACCEL_BACKWARD)); - AddInput(new Axis(m_pad_id, ButtonManager::WIIMOTE_ACCEL_UP)); - AddInput(new Axis(m_pad_id, ButtonManager::WIIMOTE_ACCEL_DOWN)); - } - if (gyroscope_enabled) - { - AddInput(new Axis(m_pad_id, ButtonManager::WIIMOTE_GYRO_PITCH_UP)); - AddInput(new Axis(m_pad_id, ButtonManager::WIIMOTE_GYRO_PITCH_DOWN)); - AddInput(new Axis(m_pad_id, ButtonManager::WIIMOTE_GYRO_ROLL_LEFT)); - AddInput(new Axis(m_pad_id, ButtonManager::WIIMOTE_GYRO_ROLL_RIGHT)); - AddInput(new Axis(m_pad_id, ButtonManager::WIIMOTE_GYRO_YAW_LEFT)); - AddInput(new Axis(m_pad_id, ButtonManager::WIIMOTE_GYRO_YAW_RIGHT)); - } - - // Rumble - AddOutput(new Motor(m_pad_id, ButtonManager::RUMBLE)); -} -// Buttons and stuff - -std::string Touchscreen::Button::GetName() const -{ - std::ostringstream ss; - ss << "Button " << static_cast(m_index); - return ss.str(); -} - -ControlState Touchscreen::Button::GetState() const -{ - return ButtonManager::GetButtonPressed(m_pad_id, m_index); -} - -std::string Touchscreen::Axis::GetName() const -{ - std::ostringstream ss; - ss << "Axis " << static_cast(m_index); - return ss.str(); -} - -ControlState Touchscreen::Axis::GetState() const -{ - return ButtonManager::GetAxisValue(m_pad_id, m_index) * m_neg; -} - -Touchscreen::Motor::~Motor() -{ -} - -std::string Touchscreen::Motor::GetName() const -{ - std::ostringstream ss; - ss << "Rumble " << static_cast(m_index); - return ss.str(); -} - -void Touchscreen::Motor::SetState(ControlState state) -{ - if (state > 0) - { - std::thread(Rumble, m_pad_id, state).detach(); - } -} - -void Touchscreen::Motor::Rumble(int pad_id, double state) -{ -#ifdef ANDROID - JNIEnv* env = IDCache::GetEnvForThread(); - env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), IDCache::GetDoRumble(), pad_id, - state); -#endif -} -} // namespace ciface::Touch diff --git a/Source/Core/InputCommon/ControllerInterface/Touch/Touchscreen.h b/Source/Core/InputCommon/ControllerInterface/Touch/Touchscreen.h deleted file mode 100644 index 9d12df1a4c..0000000000 --- a/Source/Core/InputCommon/ControllerInterface/Touch/Touchscreen.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2008 Dolphin Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "InputCommon/ControllerInterface/ControllerInterface.h" -#include "InputCommon/ControllerInterface/Touch/ButtonManager.h" - -namespace ciface::Touch -{ -class Touchscreen : public Core::Device -{ -private: - class Button : public Input - { - public: - std::string GetName() const override; - Button(int pad_id, ButtonManager::ButtonType index) : m_pad_id(pad_id), m_index(index) {} - ControlState GetState() const override; - - private: - const int m_pad_id; - const ButtonManager::ButtonType m_index; - }; - class Axis : public Input - { - public: - std::string GetName() const override; - bool IsDetectable() const override { return false; } - Axis(int pad_id, ButtonManager::ButtonType index, float neg = 1.0f) - : m_pad_id(pad_id), m_index(index), m_neg(neg) - { - } - ControlState GetState() const override; - - private: - const int m_pad_id; - const ButtonManager::ButtonType m_index; - const float m_neg; - }; - class Motor : public Core::Device::Output - { - public: - Motor(int pad_id, ButtonManager::ButtonType index) : m_pad_id(pad_id), m_index(index) {} - ~Motor(); - std::string GetName() const override; - void SetState(ControlState state) override; - - private: - const int m_pad_id; - const ButtonManager::ButtonType m_index; - static void Rumble(int pad_id, double state); - }; - -public: - Touchscreen(int pad_id, bool accelerometer_enabled, bool gyroscope_enabled); - ~Touchscreen() {} - std::string GetName() const override; - std::string GetSource() const override; - -private: - const int m_pad_id; -}; -} // namespace ciface::Touch -- cgit v1.2.3 From 792cb6219533bd9ce5154da9a87f6eabddfaa977 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Fri, 31 Dec 2021 16:14:15 +0100 Subject: ControllerInterface/Android: Implement device population --- .../ControllerInterface/Android/Android.cpp | 603 ++++++++++++++++++++- .../ControllerInterface/Android/Android.h | 6 +- .../ControllerInterface/ControllerInterface.cpp | 4 +- 3 files changed, 609 insertions(+), 4 deletions(-) (limited to 'Source/Core/InputCommon/ControllerInterface') diff --git a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp index d59dc03588..681641c2e3 100644 --- a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp @@ -1,13 +1,614 @@ -// Copyright 2013 Dolphin Emulator Project +// Copyright 2021 Dolphin Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "InputCommon/ControllerInterface/Android/Android.h" +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "Common/Logging/Log.h" + #include "InputCommon/ControllerInterface/ControllerInterface.h" +#include "jni/AndroidCommon/AndroidCommon.h" +#include "jni/AndroidCommon/IDCache.h" + +namespace +{ +jclass s_list_class; +jmethodID s_list_get; +jmethodID s_list_size; + +jclass s_input_device_class; +jmethodID s_input_device_get_device_ids; +jmethodID s_input_device_get_device; +jmethodID s_input_device_get_controller_number; +jmethodID s_input_device_get_motion_ranges; +jmethodID s_input_device_get_name; +jmethodID s_input_device_get_sources; +jmethodID s_input_device_has_keys; + +jclass s_motion_range_class; +jmethodID s_motion_range_get_axis; +jmethodID s_motion_range_get_max; +jmethodID s_motion_range_get_min; +jmethodID s_motion_range_get_source; + +jintArray s_keycodes_array; + +constexpr int MAX_KEYCODE = AKEYCODE_PROFILE_SWITCH; // Up to date as of SDK 31 + +const std::array KEYCODE_NAMES = { + "Unknown", + "Soft Left", + "Soft Right", + "Home", + "Back", + "Call", + "End Call", + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "Star", + "Pound", + "Up", + "Down", + "Left", + "Right", + "Center", + "Volume Up", + "Volume Down", + "Power", + "Camera", + "Clear", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "Comma", + "Period", + "Left Alt", + "Right Alt", + "Left Shift", + "Right Shift", + "Tab", + "Space", + "Sym", + "Explorer", + "Envelope", + "Enter", + "Backspace", + "Grave", + "Minus", + "Equals", + "Left Bracket", + "Right Bracket", + "Backslash", + "Semicolon", + "Apostrophe", + "Slash", + "At", + "Num", + "Headset Hook", + "Focus", + "Plus", + "Menu", + "Notification", + "Search", + "Play Pause", + "Stop", + "Next", + "Previous", + "Rewind", + "Fast Forward", + "Mute", + "Page Up", + "Page Down", + "Emoji", + "Switch Charset", + "Button A", + "Button B", + "Button C", + "Button X", + "Button Y", + "Button Z", + "Button L1", + "Button R1", + "Button L2", + "Button R2", + "Button L3", + "Button R3", + "Start", + "Select", + "Mode", + "Escape", + "Delete", + "Left Ctrl", + "Right Ctrl", + "Caps Lock", + "Scroll Lock", + "Left Meta", + "Right Meta", + "Fn", + "PrtSc SysRq", + "Pause Break", + "Move Home", + "Move End", + "Insert", + "Forward", + "Play", + "Pause", + "Close", + "Eject", + "Record", + "F1", + "F2", + "F3", + "F4", + "F5", + "F6", + "F7", + "F8", + "F9", + "F10", + "F11", + "F12", + "Num Lock", + "Numpad 0", + "Numpad 1", + "Numpad 2", + "Numpad 3", + "Numpad 4", + "Numpad 5", + "Numpad 6", + "Numpad 7", + "Numpad 8", + "Numpad 9", + "Numpad Divide", + "Numpad Multiply", + "Numpad Subtract", + "Numpad Add", + "Numpad Dot", + "Numpad Comma", + "Numpad Enter", + "Numpad Equals", + "Numpad Left Paren", + "Numpad Right Paren", + "Volume Mute", + "Info", + "Channel Up", + "Channel Down", + "Zoom In", + "Zoom Out", + "TV", + "Window", + "Guide", + "DVR", + "Bookmark", + "Captions", + "Settings", + "TV Power", + "TV Input", + "STB Power", + "STB Input", + "AVR Power", + "AVR Input", + "Prog Red", + "Prog Green", + "Prog Yellow", + "Prog Blue", + "App Switch", + "Button 1", + "Button 2", + "Button 3", + "Button 4", + "Button 5", + "Button 6", + "Button 7", + "Button 8", + "Button 9", + "Button 10", + "Button 11", + "Button 12", + "Button 13", + "Button 14", + "Button 15", + "Button 16", + "Language Switch", + "Manner Mode", + "3D Mode", + "Contacts", + "Calendar", + "Music", + "Calculator", + "Zenkaku Hankaku", + "Eisu", + "Henkan", + "Muhenkan", + "Katakana Hiragana", + "Yen", + "Ro", + "Kana", + "Assist", + "Brightness Down", + "Brightness Up", + "Audio Track", + "Sleep", + "Wakeup", + "Pairing", + "Top Menu", + "11", + "12", + "Last Channel", + "Data Service", + "Voice Assist", + "Radio Service", + "Teletext", + "Number Entry", + "Terrestrial Analog", + "Terrestrial Digital", + "Satellite", + "Satellite BS", + "Satellite CS", + "Satellite Service", + "Network", + "Antenna Cable", + "Input HDMI 1", + "Input HDMI 2", + "Input HDMI 3", + "Input HDMI 4", + "Input Composite 1", + "Input Composite 2", + "Input Component 1", + "Input Component 2", + "Input VGA 1", + "Audio Description", + "Audio Description Mix Up", + "Audio Description Mix Down", + "Zoom Mode", + "Contents Menu", + "Media Context Menu", + "Timer Programming", + "Help", + "Navigate Previous", + "Navigate Next", + "Navigate In", + "Navigate Out", + "Stem Primary", + "Stem 1", + "Stem 2", + "Stem 3", + "Up Left", + "Down Left", + "Up Right", + "Down Right", + "Skip Forward", + "Skip Backward", + "Step Forward", + "Step Backward", + "Soft Sleep", + "Cut", + "Copy", + "Paste", + "System Navigation Up", + "System Navigation Down", + "System Navigation Left", + "System Navigation Right", + "All Apps", + "Refresh", + "Thumbs Up", + "Thumbs Down", + "Profile Switch", +}; + +std::string ConstructKeyName(int keycode) +{ + return std::string(KEYCODE_NAMES[keycode]); +} + +std::string ConstructAxisNamePrefix(int source) +{ + // A device is allowed to have two axes with the same axis ID but different source IDs, + // so we have to make sure to include the source in the axis name. + + static const std::unordered_map source_names{ + {AINPUT_SOURCE_KEYBOARD, "Keyboard"}, + {AINPUT_SOURCE_DPAD, "Dpad"}, + {AINPUT_SOURCE_GAMEPAD, "Gamepad"}, + {AINPUT_SOURCE_TOUCHSCREEN, "Touch"}, + {AINPUT_SOURCE_MOUSE, "Cursor"}, + {AINPUT_SOURCE_STYLUS, "Stylus"}, + {AINPUT_SOURCE_BLUETOOTH_STYLUS, "BTStylus"}, + {AINPUT_SOURCE_TRACKBALL, "Trackball"}, + {AINPUT_SOURCE_MOUSE_RELATIVE, "Mouse"}, + {AINPUT_SOURCE_TOUCHPAD, "Touchpad"}, + {AINPUT_SOURCE_TOUCH_NAVIGATION, "Touchnav"}, + {AINPUT_SOURCE_JOYSTICK, "Axis"}, // The typical source for all axes on a gamepad + {AINPUT_SOURCE_HDMI, "HDMI"}, + {AINPUT_SOURCE_SENSOR, "Sensor"}, + {AINPUT_SOURCE_ROTARY_ENCODER, "Rotary"}, + }; + + const auto it = source_names.find(source); + if (it != source_names.end()) + return fmt::format("{} ", it->second); + else + return fmt::format("Axis {:08x}/", source); +} + +std::string ConstructAxisName(int source, int axis, bool negative) +{ + const char sign = negative ? '-' : '+'; + return fmt::format("{}{}{}", ConstructAxisNamePrefix(source), axis, sign); +} + +} // namespace + namespace ciface::Android { +class AndroidKey final : public Core::Device::Input +{ +public: + explicit AndroidKey(int keycode) : m_name(ConstructKeyName(keycode)) + { + DEBUG_LOG_FMT(CONTROLLERINTERFACE, "Created {}", m_name); + } + + std::string GetName() const override { return m_name; } + + ControlState GetState() const override + { + return 0; // TODO + } + +private: + std::string m_name; +}; + +class AndroidAxis final : public Core::Device::Input +{ +public: + AndroidAxis(int source, int axis, bool negative) + : m_name(ConstructAxisName(source, axis, negative)) + { + DEBUG_LOG_FMT(CONTROLLERINTERFACE, "Created {}", m_name); + } + + std::string GetName() const override { return m_name; }; + + ControlState GetState() const override + { + return 0; // TODO + }; + +private: + std::string m_name; +}; + +class AndroidDevice final : public Core::Device +{ +public: + AndroidDevice(JNIEnv* env, jobject input_device) + : m_source(env->CallIntMethod(input_device, s_input_device_get_sources)), + m_controller_number(env->CallIntMethod(input_device, s_input_device_get_controller_number) + { + jstring j_name = + reinterpret_cast(env->CallObjectMethod(input_device, s_input_device_get_name)); + m_name = GetJString(env, j_name); + env->DeleteLocalRef(j_name); + + DEBUG_LOG_FMT(CONTROLLERINTERFACE, "Sources for {}: {:08x}", GetQualifiedName(), m_source); + + AddKeys(env, input_device); + AddAxes(env, input_device); + } + + std::string GetName() const override { return m_name; } + + std::string GetSource() const override { return "Android"; } + + std::optional GetPreferredId() const override + { + return m_controller_number != 0 ? std::make_optional(m_controller_number) : std::nullopt; + } + + int GetSortPriority() const override + { + // If m_controller_number is non-zero, Android considers this to be a gamepad + if (m_controller_number != 0) + return 0; + + if ((m_source & AINPUT_SOURCE_KEYBOARD) != 0) + return -1; + + if ((m_source & (AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_MOUSE_RELATIVE)) != 0) + return -2; + + return -3; + } + +private: + void AddKeys(JNIEnv* env, jobject input_device) + { + jbooleanArray keys_array = reinterpret_cast( + env->CallObjectMethod(input_device, s_input_device_has_keys, s_keycodes_array)); + jboolean* keys = env->GetBooleanArrayElements(keys_array, nullptr); + jsize keys_count = env->GetArrayLength(keys_array); + for (jsize i = 0; i < keys_count; ++i) + { + // These specific keys never get delivered to applications, + // so there's no point in letting users try to map them + if (i == AKEYCODE_HOME || i == AKEYCODE_ASSIST || i == AKEYCODE_VOICE_ASSIST) + continue; + + if (keys[i]) + AddInput(new AndroidKey(i)); + } + env->ReleaseBooleanArrayElements(keys_array, keys, JNI_ABORT); + env->DeleteLocalRef(keys_array); + } + + void AddAxes(JNIEnv* env, jobject input_device) + { + jobject motion_ranges_list = + env->CallObjectMethod(input_device, s_input_device_get_motion_ranges); + jint motion_ranges_count = env->CallIntMethod(motion_ranges_list, s_list_size); + for (jint i = 0; i < motion_ranges_count; ++i) + { + jobject motion_range = env->CallObjectMethod(motion_ranges_list, s_list_get, i); + + jint source = env->CallIntMethod(motion_range, s_motion_range_get_source); + jint axis = env->CallIntMethod(motion_range, s_motion_range_get_axis); + jfloat min = env->CallFloatMethod(motion_range, s_motion_range_get_min); + jfloat max = env->CallFloatMethod(motion_range, s_motion_range_get_max); + + env->DeleteLocalRef(motion_range); + + AndroidAxis* positive = nullptr; + AndroidAxis* negative = nullptr; + if (max > 0) + positive = new AndroidAxis(source, axis, false); + if (min < 0) + negative = new AndroidAxis(source, axis, true); + + if (positive && negative) + AddAnalogInputs(positive, negative); + else if (positive || negative) + AddInput(positive ? positive : negative); + } + env->DeleteLocalRef(motion_ranges_list); + } + + const int m_source; + const int m_controller_number; + std::string m_name; +}; + +// Creates an array that contains every possible keycode +static jintArray CreateKeyCodesArray(JNIEnv* env) +{ + jintArray keycodes_array = env->NewIntArray(MAX_KEYCODE + 1); + + int* keycodes = env->GetIntArrayElements(keycodes_array, nullptr); + for (int i = 0; i <= MAX_KEYCODE; ++i) + keycodes[i] = i; + env->ReleaseIntArrayElements(keycodes_array, keycodes, 0); + + return keycodes_array; +} + +void Init() +{ + JNIEnv* env = IDCache::GetEnvForThread(); + + const jclass list_class = env->FindClass("java/util/List"); + s_list_class = reinterpret_cast(env->NewGlobalRef(list_class)); + s_list_get = env->GetMethodID(s_list_class, "get", "(I)Ljava/lang/Object;"); + s_list_size = env->GetMethodID(s_list_class, "size", "()I"); + env->DeleteLocalRef(list_class); + + const jclass input_device_class = env->FindClass("android/view/InputDevice"); + s_input_device_class = reinterpret_cast(env->NewGlobalRef(input_device_class)); + s_input_device_get_device_ids = + env->GetStaticMethodID(s_input_device_class, "getDeviceIds", "()[I"); + s_input_device_get_device = + env->GetStaticMethodID(s_input_device_class, "getDevice", "(I)Landroid/view/InputDevice;"); + s_input_device_get_controller_number = + env->GetMethodID(s_input_device_class, "getControllerNumber", "()I"); + s_input_device_get_motion_ranges = + env->GetMethodID(s_input_device_class, "getMotionRanges", "()Ljava/util/List;"); + s_input_device_get_name = + env->GetMethodID(s_input_device_class, "getName", "()Ljava/lang/String;"); + s_input_device_get_sources = env->GetMethodID(s_input_device_class, "getSources", "()I"); + s_input_device_has_keys = env->GetMethodID(s_input_device_class, "hasKeys", "([I)[Z"); + env->DeleteLocalRef(input_device_class); + + const jclass motion_range_class = env->FindClass("android/view/InputDevice$MotionRange"); + s_motion_range_class = reinterpret_cast(env->NewGlobalRef(motion_range_class)); + s_motion_range_get_axis = env->GetMethodID(s_motion_range_class, "getAxis", "()I"); + s_motion_range_get_max = env->GetMethodID(s_motion_range_class, "getMax", "()F"); + s_motion_range_get_min = env->GetMethodID(s_motion_range_class, "getMin", "()F"); + s_motion_range_get_source = env->GetMethodID(s_motion_range_class, "getSource", "()I"); + env->DeleteLocalRef(motion_range_class); + + jintArray keycodes_array = CreateKeyCodesArray(env); + s_keycodes_array = reinterpret_cast(env->NewGlobalRef(keycodes_array)); + env->DeleteLocalRef(keycodes_array); +} + +void Shutdown() +{ + JNIEnv* env = IDCache::GetEnvForThread(); + + env->DeleteGlobalRef(s_input_device_class); + env->DeleteGlobalRef(s_motion_range_class); + env->DeleteGlobalRef(s_keycodes_array); +} + +static void AddDevice(JNIEnv* env, int device_id) +{ + jobject input_device = + env->CallStaticObjectMethod(s_input_device_class, s_input_device_get_device, device_id); + + auto device = std::make_shared(env, input_device); + + env->DeleteLocalRef(input_device); + + if (!device->Inputs().empty() || !device->Outputs().empty()) + g_controller_interface.AddDevice(std::move(device)); +} + void PopulateDevices() { + INFO_LOG_FMT(CONTROLLERINTERFACE, "Android populating devices"); + + JNIEnv* env = IDCache::GetEnvForThread(); + + jintArray device_ids_array = reinterpret_cast( + env->CallStaticObjectMethod(s_input_device_class, s_input_device_get_device_ids)); + int* device_ids = env->GetIntArrayElements(device_ids_array, nullptr); + jsize device_ids_count = env->GetArrayLength(device_ids_array); + for (jsize i = 0; i < device_ids_count; ++i) + AddDevice(env, device_ids[i]); + env->ReleaseIntArrayElements(device_ids_array, device_ids, JNI_ABORT); + env->DeleteLocalRef(device_ids_array); } + } // namespace ciface::Android diff --git a/Source/Core/InputCommon/ControllerInterface/Android/Android.h b/Source/Core/InputCommon/ControllerInterface/Android/Android.h index 9f57f5ba2e..8b8478d7ac 100644 --- a/Source/Core/InputCommon/ControllerInterface/Android/Android.h +++ b/Source/Core/InputCommon/ControllerInterface/Android/Android.h @@ -1,9 +1,13 @@ -// Copyright 2008 Dolphin Emulator Project +// Copyright 2021 Dolphin Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once namespace ciface::Android { +void Init(); +void Shutdown(); + void PopulateDevices(); + } // namespace ciface::Android diff --git a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp index 6a6affd478..8f58525f0c 100644 --- a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp +++ b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp @@ -67,7 +67,7 @@ void ControllerInterface::Initialize(const WindowSystemInfo& wsi) m_input_backends.emplace_back(ciface::SDL::CreateInputBackend(this)); #endif #ifdef CIFACE_USE_ANDROID -// nothing needed + ciface::Android::Init(); #endif #ifdef CIFACE_USE_EVDEV m_input_backends.emplace_back(ciface::evdev::CreateInputBackend(this)); @@ -237,7 +237,7 @@ void ControllerInterface::Shutdown() ciface::Quartz::DeInit(); #endif #ifdef CIFACE_USE_ANDROID -// nothing needed + ciface::Android::Shutdown(); #endif // Empty the container of input backends to deconstruct and deinitialize them. -- cgit v1.2.3 From ca508e45033c022dbef558a11d170ab7f41c7bf9 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sat, 1 Jan 2022 18:31:50 +0100 Subject: ControllerInterface/Android: Handle input events Android doesn't let us poll inputs whenever we want. Instead, we listen to input events (activities will have to forward them to the input backend), and store the received values in atomic variables in the Input classes. This is similar in concept to how ButtonManager worked, but without its homegrown second input mapping system. --- .../ControllerInterface/Android/Android.cpp | 189 +++++++++++++++++++-- 1 file changed, 173 insertions(+), 16 deletions(-) (limited to 'Source/Core/InputCommon/ControllerInterface') diff --git a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp index 681641c2e3..26aad585fc 100644 --- a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp @@ -3,6 +3,7 @@ #include "InputCommon/ControllerInterface/Android/Android.h" +#include #include #include #include @@ -15,6 +16,7 @@ #include #include "Common/Logging/Log.h" +#include "Common/StringUtil.h" #include "InputCommon/ControllerInterface/ControllerInterface.h" @@ -31,6 +33,7 @@ jclass s_input_device_class; jmethodID s_input_device_get_device_ids; jmethodID s_input_device_get_device; jmethodID s_input_device_get_controller_number; +jmethodID s_input_device_get_id; jmethodID s_input_device_get_motion_ranges; jmethodID s_input_device_get_name; jmethodID s_input_device_get_sources; @@ -42,8 +45,21 @@ jmethodID s_motion_range_get_max; jmethodID s_motion_range_get_min; jmethodID s_motion_range_get_source; +jclass s_input_event_class; +jmethodID s_input_event_get_device; + +jclass s_key_event_class; +jmethodID s_key_event_get_action; +jmethodID s_key_event_get_keycode; + +jclass s_motion_event_class; +jmethodID s_motion_event_get_axis_value; +jmethodID s_motion_event_get_source; + jintArray s_keycodes_array; +std::unordered_map s_device_id_to_device_qualifier; + constexpr int MAX_KEYCODE = AKEYCODE_PROFILE_SWITCH; // Up to date as of SDK 31 const std::array KEYCODE_NAMES = { @@ -379,47 +395,70 @@ std::string ConstructAxisName(int source, int axis, bool negative) return fmt::format("{}{}{}", ConstructAxisNamePrefix(source), axis, sign); } +std::shared_ptr FindDevice(jint device_id) +{ + const auto it = s_device_id_to_device_qualifier.find(device_id); + if (it == s_device_id_to_device_qualifier.end()) + { + ERROR_LOG_FMT(CONTROLLERINTERFACE, "Could not find device ID {}", device_id); + return nullptr; + } + + const ciface::Core::DeviceQualifier& qualifier = it->second; + std::shared_ptr device = g_controller_interface.FindDevice(qualifier); + if (!device) + { + ERROR_LOG_FMT(CONTROLLERINTERFACE, "Could not find device {}", qualifier.ToString()); + return nullptr; + } + + return device; +} + } // namespace namespace ciface::Android { -class AndroidKey final : public Core::Device::Input +class AndroidInput : public Core::Device::Input { public: - explicit AndroidKey(int keycode) : m_name(ConstructKeyName(keycode)) + explicit AndroidInput(std::string name) : m_name(std::move(name)) { DEBUG_LOG_FMT(CONTROLLERINTERFACE, "Created {}", m_name); } std::string GetName() const override { return m_name; } - ControlState GetState() const override - { - return 0; // TODO - } + ControlState GetState() const override { return m_state.load(std::memory_order_relaxed); } + + void SetState(ControlState state) { m_state.store(state, std::memory_order_relaxed); } private: std::string m_name; + std::atomic m_state = 0; +}; + +class AndroidKey final : public AndroidInput +{ +public: + explicit AndroidKey(int keycode) : AndroidInput(ConstructKeyName(keycode)) {} }; -class AndroidAxis final : public Core::Device::Input +class AndroidAxis final : public AndroidInput { public: AndroidAxis(int source, int axis, bool negative) - : m_name(ConstructAxisName(source, axis, negative)) + : AndroidInput(ConstructAxisName(source, axis, negative)), m_negative(negative) { - DEBUG_LOG_FMT(CONTROLLERINTERFACE, "Created {}", m_name); } - std::string GetName() const override { return m_name; }; - ControlState GetState() const override { - return 0; // TODO - }; + return m_negative ? -AndroidInput::GetState() : AndroidInput::GetState(); + } private: - std::string m_name; + bool m_negative; }; class AndroidDevice final : public Core::Device @@ -552,6 +591,7 @@ void Init() env->GetStaticMethodID(s_input_device_class, "getDevice", "(I)Landroid/view/InputDevice;"); s_input_device_get_controller_number = env->GetMethodID(s_input_device_class, "getControllerNumber", "()I"); + s_input_device_get_id = env->GetMethodID(s_input_device_class, "getId", "()I"); s_input_device_get_motion_ranges = env->GetMethodID(s_input_device_class, "getMotionRanges", "()Ljava/util/List;"); s_input_device_get_name = @@ -568,6 +608,21 @@ void Init() s_motion_range_get_source = env->GetMethodID(s_motion_range_class, "getSource", "()I"); env->DeleteLocalRef(motion_range_class); + const jclass input_event_class = env->FindClass("android/view/InputEvent"); + s_input_event_class = reinterpret_cast(env->NewGlobalRef(input_event_class)); + s_input_event_get_device = + env->GetMethodID(s_input_event_class, "getDevice", "()Landroid/view/InputDevice;"); + + const jclass key_event_class = env->FindClass("android/view/KeyEvent"); + s_key_event_class = reinterpret_cast(env->NewGlobalRef(key_event_class)); + s_key_event_get_action = env->GetMethodID(s_key_event_class, "getAction", "()I"); + s_key_event_get_keycode = env->GetMethodID(s_key_event_class, "getKeyCode", "()I"); + + const jclass motion_event_class = env->FindClass("android/view/MotionEvent"); + s_motion_event_class = reinterpret_cast(env->NewGlobalRef(motion_event_class)); + s_motion_event_get_axis_value = env->GetMethodID(s_motion_event_class, "getAxisValue", "(I)F"); + s_motion_event_get_source = env->GetMethodID(s_motion_event_class, "getSource", "()I"); + jintArray keycodes_array = CreateKeyCodesArray(env); s_keycodes_array = reinterpret_cast(env->NewGlobalRef(keycodes_array)); env->DeleteLocalRef(keycodes_array); @@ -579,6 +634,9 @@ void Shutdown() env->DeleteGlobalRef(s_input_device_class); env->DeleteGlobalRef(s_motion_range_class); + env->DeleteGlobalRef(s_input_event_class); + env->DeleteGlobalRef(s_key_event_class); + env->DeleteGlobalRef(s_motion_event_class); env->DeleteGlobalRef(s_keycodes_array); } @@ -591,8 +649,17 @@ static void AddDevice(JNIEnv* env, int device_id) env->DeleteLocalRef(input_device); - if (!device->Inputs().empty() || !device->Outputs().empty()) - g_controller_interface.AddDevice(std::move(device)); + if (device->Inputs().empty() && device->Outputs().empty()) + return; + + g_controller_interface.AddDevice(device); + + Core::DeviceQualifier qualifier; + qualifier.FromDevice(device.get()); + + INFO_LOG_FMT(CONTROLLERINTERFACE, "Added device ID {} as {}", device_id, + device->GetQualifiedName()); + s_device_id_to_device_qualifier.emplace(device_id, qualifier); } void PopulateDevices() @@ -612,3 +679,93 @@ void PopulateDevices() } } // namespace ciface::Android + +extern "C" { + +JNIEXPORT jboolean JNICALL +Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_dispatchKeyEvent( + JNIEnv* env, jclass, jobject key_event) +{ + const jint action = env->CallIntMethod(key_event, s_key_event_get_action); + ControlState state; + switch (action) + { + case AKEY_EVENT_ACTION_DOWN: + state = 1; + break; + case AKEY_EVENT_ACTION_UP: + state = 0; + break; + default: + return JNI_FALSE; + } + + const jobject input_device = env->CallObjectMethod(key_event, s_input_event_get_device); + const jint device_id = env->CallIntMethod(input_device, s_input_device_get_id); + env->DeleteLocalRef(input_device); + const std::shared_ptr device = FindDevice(device_id); + if (!device) + return JNI_FALSE; + + const jint keycode = env->CallIntMethod(key_event, s_key_event_get_keycode); + const std::string input_name = ConstructKeyName(keycode); + + ciface::Core::Device::Input* input = device->FindInput(input_name); + if (!input) + { + ERROR_LOG_FMT(CONTROLLERINTERFACE, "Could not find input {} in device {}", input_name, + device->GetQualifiedName()); + return false; + } + + static_cast(input)->SetState(state); + + DEBUG_LOG_FMT(CONTROLLERINTERFACE, "Set {} of {} to {}", input_name, device->GetQualifiedName(), + state); + + // TODO: Return true when appropriate + return JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_dispatchGenericMotionEvent( + JNIEnv* env, jclass, jobject motion_event) +{ + const jobject input_device = env->CallObjectMethod(motion_event, s_input_event_get_device); + const jint device_id = env->CallIntMethod(input_device, s_input_device_get_id); + env->DeleteLocalRef(input_device); + const std::shared_ptr device = FindDevice(device_id); + if (!device) + return JNI_FALSE; + + const jint source = env->CallIntMethod(motion_event, s_motion_event_get_source); + const std::string axis_name_prefix = ConstructAxisNamePrefix(source); + + for (ciface::Core::Device::Input* input : device->Inputs()) + { + const std::string input_name = input->GetName(); + if (input_name.starts_with(axis_name_prefix)) + { + const std::string axis_id_str = input_name.substr( + axis_name_prefix.size(), input_name.size() - axis_name_prefix.size() - sizeof('+')); + + int axis_id; + if (!TryParse(axis_id_str, &axis_id)) + { + ERROR_LOG_FMT(CONTROLLERINTERFACE, "Failed to parse \"{}\" from \"{}\" as axis ID", + axis_id_str, input_name); + continue; + } + + float value = env->CallFloatMethod(motion_event, s_motion_event_get_axis_value, axis_id); + static_cast(input)->SetState(value); + + DEBUG_LOG_FMT(CONTROLLERINTERFACE, "Set {} of {} to {}", input_name, + device->GetQualifiedName(), value); + } + } + + // TODO: Return true when appropriate + return JNI_FALSE; +} +} -- cgit v1.2.3 From d6af294a2370b1827508cdf1819ad7cedbb39f7b Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sun, 6 Mar 2022 11:51:59 +0100 Subject: ControllerInterface/Android: Return whether input was handled When Android presents an input event to an app, it wants the app to return true or false depending on whether the app handled the event or not. If the event wasn't handled by the app, it will be passed on to the system, which may decide to take an action depending on what kind of input event it is. For instance, if a B button press is passed on to the system, it will be turned into a Back press. But if an R1 press is passed on to the system, nothing in particular happens. It's important that we get this return value right in Dolphin. For instance, the user generally wouldn't want a B button press to open the EmulationActivity menu, so B button presses usually shouldn't be passed on to the system - but volume button presses usually should be passed on to the system, since it would be hard to adjust the volume otherwise. What ButtonManager did was to pass on input events that are for a button which the user has not mapped, which I think makes sense. But exactly how to implement that is more complicated in the new input backend than in ButtonManager, because now we have a separation between the input backend and the code that keeps track of the user's mappings. What I'm going with in this commit is to treat an input as mapped if it has been polled recently. In part I chose this because it seemed like a simple way of implementing it that wouldn't cause too many layering violations, but it also has two useful side effects: 1. If a controller is not being polled (e.g. GameCube controllers in Wii games that don't use them), its mappings will not be considered. 2. Once sensor input is implemented in the Android input backend, we will be able to use this "polled recently" tracking to power down the sensors at times when the game is using a Wii Remote reporting mode that doesn't include motion data. (Assuming that the sensor inputs only are mapped to Wii Remote motion controls, that is.) --- .../ControllerInterface/Android/Android.cpp | 31 +++++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) (limited to 'Source/Core/InputCommon/ControllerInterface') diff --git a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp index 26aad585fc..5a16ef56d0 100644 --- a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp @@ -3,7 +3,9 @@ #include "InputCommon/ControllerInterface/Android/Android.h" +#include #include +#include #include #include #include @@ -58,6 +60,9 @@ jmethodID s_motion_event_get_source; jintArray s_keycodes_array; +using Clock = std::chrono::steady_clock; +constexpr Clock::duration ACTIVE_INPUT_TIMEOUT = std::chrono::milliseconds(1000); + std::unordered_map s_device_id_to_device_qualifier; constexpr int MAX_KEYCODE = AKEYCODE_PROFILE_SWITCH; // Up to date as of SDK 31 @@ -429,13 +434,20 @@ public: std::string GetName() const override { return m_name; } - ControlState GetState() const override { return m_state.load(std::memory_order_relaxed); } + ControlState GetState() const override + { + m_last_polled.store(Clock::now(), std::memory_order_relaxed); + return m_state.load(std::memory_order_relaxed); + } void SetState(ControlState state) { m_state.store(state, std::memory_order_relaxed); } + Clock::time_point GetLastPolled() const { return m_last_polled.load(std::memory_order_relaxed); } + private: std::string m_name; std::atomic m_state = 0; + mutable std::atomic m_last_polled{}; }; class AndroidKey final : public AndroidInput @@ -718,13 +730,14 @@ Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_dispatch return false; } - static_cast(input)->SetState(state); + auto casted_input = static_cast(input); + casted_input->SetState(state); + const Clock::time_point last_polled = casted_input->GetLastPolled(); DEBUG_LOG_FMT(CONTROLLERINTERFACE, "Set {} of {} to {}", input_name, device->GetQualifiedName(), state); - // TODO: Return true when appropriate - return JNI_FALSE; + return last_polled >= Clock::now() - ACTIVE_INPUT_TIMEOUT; } JNIEXPORT jboolean JNICALL @@ -741,6 +754,8 @@ Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_dispatch const jint source = env->CallIntMethod(motion_event, s_motion_event_get_source); const std::string axis_name_prefix = ConstructAxisNamePrefix(source); + Clock::time_point last_polled{}; + for (ciface::Core::Device::Input* input : device->Inputs()) { const std::string input_name = input->GetName(); @@ -758,14 +773,16 @@ Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_dispatch } float value = env->CallFloatMethod(motion_event, s_motion_event_get_axis_value, axis_id); - static_cast(input)->SetState(value); + + auto casted_input = static_cast(input); + casted_input->SetState(value); + last_polled = std::max(last_polled, casted_input->GetLastPolled()); DEBUG_LOG_FMT(CONTROLLERINTERFACE, "Set {} of {} to {}", input_name, device->GetQualifiedName(), value); } } - // TODO: Return true when appropriate - return JNI_FALSE; + return last_polled >= Clock::now() - ACTIVE_INPUT_TIMEOUT; } } -- cgit v1.2.3 From 104ea098921846e01eb58ebfa00822b14da46cda Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sun, 6 Mar 2022 20:27:25 +0100 Subject: ControllerInterface/Android: Implement hotplug --- .../ControllerInterface/Android/Android.cpp | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'Source/Core/InputCommon/ControllerInterface') diff --git a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp index 5a16ef56d0..e5baa4e43e 100644 --- a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp @@ -58,6 +58,10 @@ jclass s_motion_event_class; jmethodID s_motion_event_get_axis_value; jmethodID s_motion_event_get_source; +jclass s_controller_interface_class; +jmethodID s_controller_interface_register_input_device_listener; +jmethodID s_controller_interface_unregister_input_device_listener; + jintArray s_keycodes_array; using Clock = std::chrono::steady_clock; @@ -635,20 +639,36 @@ void Init() s_motion_event_get_axis_value = env->GetMethodID(s_motion_event_class, "getAxisValue", "(I)F"); s_motion_event_get_source = env->GetMethodID(s_motion_event_class, "getSource", "()I"); + const jclass controller_interface_class = + env->FindClass("org/dolphinemu/dolphinemu/features/input/model/ControllerInterface"); + s_controller_interface_class = + reinterpret_cast(env->NewGlobalRef(controller_interface_class)); + s_controller_interface_register_input_device_listener = + env->GetStaticMethodID(s_controller_interface_class, "registerInputDeviceListener", "()V"); + s_controller_interface_unregister_input_device_listener = + env->GetStaticMethodID(s_controller_interface_class, "unregisterInputDeviceListener", "()V"); + jintArray keycodes_array = CreateKeyCodesArray(env); s_keycodes_array = reinterpret_cast(env->NewGlobalRef(keycodes_array)); env->DeleteLocalRef(keycodes_array); + + env->CallStaticVoidMethod(s_controller_interface_class, + s_controller_interface_register_input_device_listener); } void Shutdown() { JNIEnv* env = IDCache::GetEnvForThread(); + env->CallStaticVoidMethod(s_controller_interface_class, + s_controller_interface_unregister_input_device_listener); + env->DeleteGlobalRef(s_input_device_class); env->DeleteGlobalRef(s_motion_range_class); env->DeleteGlobalRef(s_input_event_class); env->DeleteGlobalRef(s_key_event_class); env->DeleteGlobalRef(s_motion_event_class); + env->DeleteGlobalRef(s_controller_interface_class); env->DeleteGlobalRef(s_keycodes_array); } @@ -785,4 +805,11 @@ Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_dispatch return last_polled >= Clock::now() - ACTIVE_INPUT_TIMEOUT; } + +JNIEXPORT void JNICALL +Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_refreshDevices(JNIEnv* env, + jclass) +{ + g_controller_interface.RefreshDevices(); +} } -- cgit v1.2.3 From 5e51b56d723cdd69bbe1eee39e53accfe609a812 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Fri, 16 Sep 2022 22:03:03 +0200 Subject: ControllerInterface/Android: Implement sensor input --- .../ControllerInterface/Android/Android.cpp | 160 ++++++++++++++++++++- 1 file changed, 157 insertions(+), 3 deletions(-) (limited to 'Source/Core/InputCommon/ControllerInterface') diff --git a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp index e5baa4e43e..71b99f9ef3 100644 --- a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp @@ -17,6 +17,7 @@ #include #include +#include "Common/Assert.h" #include "Common/Logging/Log.h" #include "Common/StringUtil.h" @@ -62,12 +63,20 @@ jclass s_controller_interface_class; jmethodID s_controller_interface_register_input_device_listener; jmethodID s_controller_interface_unregister_input_device_listener; +jclass s_sensor_event_listener_class; +jmethodID s_sensor_event_listener_constructor; +jmethodID s_sensor_event_listener_enable_sensor_events; +jmethodID s_sensor_event_listener_disable_sensor_events; +jmethodID s_sensor_event_listener_get_axis_names; +jmethodID s_sensor_event_listener_get_negative_axes; + jintArray s_keycodes_array; using Clock = std::chrono::steady_clock; constexpr Clock::duration ACTIVE_INPUT_TIMEOUT = std::chrono::milliseconds(1000); std::unordered_map s_device_id_to_device_qualifier; +ciface::Core::DeviceQualifier s_sensor_device_qualifier; constexpr int MAX_KEYCODE = AKEYCODE_PROFILE_SWITCH; // Up to date as of SDK 31 @@ -460,7 +469,7 @@ public: explicit AndroidKey(int keycode) : AndroidInput(ConstructKeyName(keycode)) {} }; -class AndroidAxis final : public AndroidInput +class AndroidAxis : public AndroidInput { public: AndroidAxis(int source, int axis, bool negative) @@ -468,6 +477,10 @@ public: { } + AndroidAxis(std::string name, bool negative) : AndroidInput(std::move(name)), m_negative(negative) + { + } + ControlState GetState() const override { return m_negative ? -AndroidInput::GetState() : AndroidInput::GetState(); @@ -477,12 +490,21 @@ private: bool m_negative; }; +class AndroidSensorAxis final : public AndroidAxis +{ +public: + AndroidSensorAxis(std::string name, bool negative) : AndroidAxis(std::move(name), negative) {} + + bool IsDetectable() const override { return false; } +}; + class AndroidDevice final : public Core::Device { public: AndroidDevice(JNIEnv* env, jobject input_device) - : m_source(env->CallIntMethod(input_device, s_input_device_get_sources)), - m_controller_number(env->CallIntMethod(input_device, s_input_device_get_controller_number) + : m_sensor_event_listener(nullptr), + m_source(env->CallIntMethod(input_device, s_input_device_get_sources)), + m_controller_number(env->CallIntMethod(input_device, s_input_device_get_controller_number)) { jstring j_name = reinterpret_cast(env->CallObjectMethod(input_device, s_input_device_get_name)); @@ -495,6 +517,19 @@ public: AddAxes(env, input_device); } + // Constructor for the device added by Dolphin to contain sensor inputs + AndroidDevice(JNIEnv* env, std::string name) + : m_sensor_event_listener(AddSensors(env)), m_source(AINPUT_SOURCE_SENSOR), + m_controller_number(0), m_name(std::move(name)) + { + } + + ~AndroidDevice() + { + if (m_sensor_event_listener) + IDCache::GetEnvForThread()->DeleteGlobalRef(m_sensor_event_listener); + } + std::string GetName() const override { return m_name; } std::string GetSource() const override { return "Android"; } @@ -519,6 +554,8 @@ public: return -3; } + jobject GetSensorEventListener() { return m_sensor_event_listener; } + private: void AddKeys(JNIEnv* env, jobject input_device) { @@ -571,6 +608,35 @@ private: env->DeleteLocalRef(motion_ranges_list); } + jobject AddSensors(JNIEnv* env) + { + jobject sensor_event_listener = + env->NewObject(s_sensor_event_listener_class, s_sensor_event_listener_constructor); + + jobjectArray j_axis_names = reinterpret_cast( + env->CallObjectMethod(sensor_event_listener, s_sensor_event_listener_get_axis_names)); + std::vector axis_names = JStringArrayToVector(env, j_axis_names); + env->DeleteLocalRef(j_axis_names); + + jbooleanArray j_negative_axes = reinterpret_cast( + env->CallObjectMethod(sensor_event_listener, s_sensor_event_listener_get_negative_axes)); + jboolean* negative_axes = env->GetBooleanArrayElements(j_negative_axes, nullptr); + + ASSERT(axis_names.size() == env->GetArrayLength(j_negative_axes)); + for (size_t i = 0; i < axis_names.size(); ++i) + AddInput(new AndroidSensorAxis(axis_names[i], negative_axes[i])); + + env->ReleaseBooleanArrayElements(j_negative_axes, negative_axes, 0); + env->DeleteLocalRef(j_negative_axes); + + jobject global_sensor_event_listener = env->NewGlobalRef(sensor_event_listener); + + env->DeleteLocalRef(sensor_event_listener); + + return global_sensor_event_listener; + } + + const jobject m_sensor_event_listener; const int m_source; const int m_controller_number; std::string m_name; @@ -648,6 +714,22 @@ void Init() s_controller_interface_unregister_input_device_listener = env->GetStaticMethodID(s_controller_interface_class, "unregisterInputDeviceListener", "()V"); + const jclass sensor_event_listener_class = + env->FindClass("org/dolphinemu/dolphinemu/features/input/model/DolphinSensorEventListener"); + s_sensor_event_listener_class = + reinterpret_cast(env->NewGlobalRef(sensor_event_listener_class)); + s_sensor_event_listener_constructor = + env->GetMethodID(s_sensor_event_listener_class, "", "()V"); + s_sensor_event_listener_enable_sensor_events = + env->GetMethodID(s_sensor_event_listener_class, "enableSensorEvents", + "(Lorg/dolphinemu/dolphinemu/features/input/model/SensorEventRequester;)V"); + s_sensor_event_listener_disable_sensor_events = + env->GetMethodID(s_sensor_event_listener_class, "disableSensorEvents", "()V"); + s_sensor_event_listener_get_axis_names = + env->GetMethodID(s_sensor_event_listener_class, "getAxisNames", "()[Ljava/lang/String;"); + s_sensor_event_listener_get_negative_axes = + env->GetMethodID(s_sensor_event_listener_class, "getNegativeAxes", "()[Z"); + jintArray keycodes_array = CreateKeyCodesArray(env); s_keycodes_array = reinterpret_cast(env->NewGlobalRef(keycodes_array)); env->DeleteLocalRef(keycodes_array); @@ -669,6 +751,7 @@ void Shutdown() env->DeleteGlobalRef(s_key_event_class); env->DeleteGlobalRef(s_motion_event_class); env->DeleteGlobalRef(s_controller_interface_class); + env->DeleteGlobalRef(s_sensor_event_listener_class); env->DeleteGlobalRef(s_keycodes_array); } @@ -694,6 +777,25 @@ static void AddDevice(JNIEnv* env, int device_id) s_device_id_to_device_qualifier.emplace(device_id, qualifier); } +static void AddSensorDevice(JNIEnv* env) +{ + // Device sensors (accelerometer, etc.) aren't associated with any Android InputDevice. + // Create an otherwise empty Dolphin input device so that they have somewhere to live. + + auto device = std::make_shared(env, "Device Sensors"); + + if (device->Inputs().empty() && device->Outputs().empty()) + return; + + g_controller_interface.AddDevice(device); + + Core::DeviceQualifier qualifier; + qualifier.FromDevice(device.get()); + + INFO_LOG_FMT(CONTROLLERINTERFACE, "Added sensor device as {}", device->GetQualifiedName()); + s_sensor_device_qualifier = qualifier; +} + void PopulateDevices() { INFO_LOG_FMT(CONTROLLERINTERFACE, "Android populating devices"); @@ -708,6 +810,8 @@ void PopulateDevices() AddDevice(env, device_ids[i]); env->ReleaseIntArrayElements(device_ids_array, device_ids, JNI_ABORT); env->DeleteLocalRef(device_ids_array); + + AddSensorDevice(env); } } // namespace ciface::Android @@ -806,6 +910,56 @@ Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_dispatch return last_polled >= Clock::now() - ACTIVE_INPUT_TIMEOUT; } +JNIEXPORT void JNICALL +Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_dispatchSensorEvent( + JNIEnv* env, jclass, jstring j_axis_name, jfloat value) +{ + const std::shared_ptr device = + g_controller_interface.FindDevice(s_sensor_device_qualifier); + if (!device) + return; + + const std::string axis_name = GetJString(env, j_axis_name); + + for (ciface::Core::Device::Input* input : device->Inputs()) + { + const std::string input_name = input->GetName(); + if (input_name == axis_name) + { + auto casted_input = static_cast(input); + casted_input->SetState(value); + } + } +} + +JNIEXPORT void JNICALL +Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_enableSensorEvents( + JNIEnv* env, jclass, jobject j_sensor_event_requester) +{ + const std::shared_ptr device = + g_controller_interface.FindDevice(s_sensor_device_qualifier); + if (!device) + return; + + env->CallVoidMethod( + static_cast(device.get())->GetSensorEventListener(), + s_sensor_event_listener_enable_sensor_events, j_sensor_event_requester); +} + +JNIEXPORT void JNICALL +Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_disableSensorEvents( + JNIEnv* env, jclass) +{ + const std::shared_ptr device = + g_controller_interface.FindDevice(s_sensor_device_qualifier); + if (!device) + return; + + env->CallVoidMethod( + static_cast(device.get())->GetSensorEventListener(), + s_sensor_event_listener_disable_sensor_events); +} + JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_refreshDevices(JNIEnv* env, jclass) -- cgit v1.2.3 From 36acb17700554f0789d8650b7fba77ac8a7796b6 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Fri, 16 Sep 2022 23:02:30 +0200 Subject: ControllerInterface/Android: Implement sensor input for InputDevices This functionality was added in Android 12 to let apps get motion data for gamepads. --- .../ControllerInterface/Android/Android.cpp | 72 ++++++++++++++-------- .../InputCommon/ControllerInterface/CoreDevice.cpp | 12 ++++ .../InputCommon/ControllerInterface/CoreDevice.h | 1 + 3 files changed, 60 insertions(+), 25 deletions(-) (limited to 'Source/Core/InputCommon/ControllerInterface') diff --git a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp index 71b99f9ef3..cf7e602a77 100644 --- a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp @@ -65,6 +65,8 @@ jmethodID s_controller_interface_unregister_input_device_listener; jclass s_sensor_event_listener_class; jmethodID s_sensor_event_listener_constructor; +jmethodID s_sensor_event_listener_constructor_input_device; +jmethodID s_sensor_event_listener_set_device_qualifier; jmethodID s_sensor_event_listener_enable_sensor_events; jmethodID s_sensor_event_listener_disable_sensor_events; jmethodID s_sensor_event_listener_get_axis_names; @@ -76,7 +78,6 @@ using Clock = std::chrono::steady_clock; constexpr Clock::duration ACTIVE_INPUT_TIMEOUT = std::chrono::milliseconds(1000); std::unordered_map s_device_id_to_device_qualifier; -ciface::Core::DeviceQualifier s_sensor_device_qualifier; constexpr int MAX_KEYCODE = AKEYCODE_PROFILE_SWITCH; // Up to date as of SDK 31 @@ -502,7 +503,7 @@ class AndroidDevice final : public Core::Device { public: AndroidDevice(JNIEnv* env, jobject input_device) - : m_sensor_event_listener(nullptr), + : m_sensor_event_listener(AddSensors(env, input_device)), m_source(env->CallIntMethod(input_device, s_input_device_get_sources)), m_controller_number(env->CallIntMethod(input_device, s_input_device_get_controller_number)) { @@ -519,7 +520,7 @@ public: // Constructor for the device added by Dolphin to contain sensor inputs AndroidDevice(JNIEnv* env, std::string name) - : m_sensor_event_listener(AddSensors(env)), m_source(AINPUT_SOURCE_SENSOR), + : m_sensor_event_listener(AddSensors(env, nullptr)), m_source(AINPUT_SOURCE_SENSOR), m_controller_number(0), m_name(std::move(name)) { } @@ -608,10 +609,20 @@ private: env->DeleteLocalRef(motion_ranges_list); } - jobject AddSensors(JNIEnv* env) + jobject AddSensors(JNIEnv* env, jobject input_device) { - jobject sensor_event_listener = - env->NewObject(s_sensor_event_listener_class, s_sensor_event_listener_constructor); + jobject sensor_event_listener; + if (input_device) + { + sensor_event_listener = + env->NewObject(s_sensor_event_listener_class, + s_sensor_event_listener_constructor_input_device, input_device); + } + else + { + sensor_event_listener = + env->NewObject(s_sensor_event_listener_class, s_sensor_event_listener_constructor); + } jobjectArray j_axis_names = reinterpret_cast( env->CallObjectMethod(sensor_event_listener, s_sensor_event_listener_get_axis_names)); @@ -720,6 +731,10 @@ void Init() reinterpret_cast(env->NewGlobalRef(sensor_event_listener_class)); s_sensor_event_listener_constructor = env->GetMethodID(s_sensor_event_listener_class, "", "()V"); + s_sensor_event_listener_constructor_input_device = + env->GetMethodID(s_sensor_event_listener_class, "", "(Landroid/view/InputDevice;)V"); + s_sensor_event_listener_set_device_qualifier = env->GetMethodID( + s_sensor_event_listener_class, "setDeviceQualifier", "(Ljava/lang/String;)V"); s_sensor_event_listener_enable_sensor_events = env->GetMethodID(s_sensor_event_listener_class, "enableSensorEvents", "(Lorg/dolphinemu/dolphinemu/features/input/model/SensorEventRequester;)V"); @@ -775,6 +790,11 @@ static void AddDevice(JNIEnv* env, int device_id) INFO_LOG_FMT(CONTROLLERINTERFACE, "Added device ID {} as {}", device_id, device->GetQualifiedName()); s_device_id_to_device_qualifier.emplace(device_id, qualifier); + + jstring j_qualifier = ToJString(env, qualifier.ToString()); + env->CallVoidMethod(device->GetSensorEventListener(), + s_sensor_event_listener_set_device_qualifier, j_qualifier); + env->DeleteLocalRef(j_qualifier); } static void AddSensorDevice(JNIEnv* env) @@ -793,7 +813,11 @@ static void AddSensorDevice(JNIEnv* env) qualifier.FromDevice(device.get()); INFO_LOG_FMT(CONTROLLERINTERFACE, "Added sensor device as {}", device->GetQualifiedName()); - s_sensor_device_qualifier = qualifier; + + jstring j_qualifier = ToJString(env, qualifier.ToString()); + env->CallVoidMethod(device->GetSensorEventListener(), + s_sensor_event_listener_set_device_qualifier, j_qualifier); + env->DeleteLocalRef(j_qualifier); } void PopulateDevices() @@ -912,10 +936,12 @@ Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_dispatch JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_dispatchSensorEvent( - JNIEnv* env, jclass, jstring j_axis_name, jfloat value) + JNIEnv* env, jclass, jstring j_device_qualifier, jstring j_axis_name, jfloat value) { + ciface::Core::DeviceQualifier device_qualifier; + device_qualifier.FromString(GetJString(env, j_device_qualifier)); const std::shared_ptr device = - g_controller_interface.FindDevice(s_sensor_device_qualifier); + g_controller_interface.FindDevice(device_qualifier); if (!device) return; @@ -936,28 +962,24 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_enableSensorEvents( JNIEnv* env, jclass, jobject j_sensor_event_requester) { - const std::shared_ptr device = - g_controller_interface.FindDevice(s_sensor_device_qualifier); - if (!device) - return; - - env->CallVoidMethod( - static_cast(device.get())->GetSensorEventListener(), - s_sensor_event_listener_enable_sensor_events, j_sensor_event_requester); + for (std::shared_ptr& device : g_controller_interface.GetAllDevices()) + { + env->CallVoidMethod( + static_cast(device.get())->GetSensorEventListener(), + s_sensor_event_listener_enable_sensor_events, j_sensor_event_requester); + } } JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_disableSensorEvents( JNIEnv* env, jclass) { - const std::shared_ptr device = - g_controller_interface.FindDevice(s_sensor_device_qualifier); - if (!device) - return; - - env->CallVoidMethod( - static_cast(device.get())->GetSensorEventListener(), - s_sensor_event_listener_disable_sensor_events); + for (std::shared_ptr& device : g_controller_interface.GetAllDevices()) + { + env->CallVoidMethod( + static_cast(device.get())->GetSensorEventListener(), + s_sensor_event_listener_disable_sensor_events); + } } JNIEXPORT void JNICALL diff --git a/Source/Core/InputCommon/ControllerInterface/CoreDevice.cpp b/Source/Core/InputCommon/ControllerInterface/CoreDevice.cpp index 4e46179fc6..222791f03f 100644 --- a/Source/Core/InputCommon/ControllerInterface/CoreDevice.cpp +++ b/Source/Core/InputCommon/ControllerInterface/CoreDevice.cpp @@ -242,6 +242,18 @@ std::shared_ptr DeviceContainer::FindDevice(const DeviceQualifier& devq) return nullptr; } +std::vector> DeviceContainer::GetAllDevices() const +{ + std::lock_guard lk(m_devices_mutex); + + std::vector> devices; + + for (const auto& d : m_devices) + devices.emplace_back(d); + + return devices; +} + std::vector DeviceContainer::GetAllDeviceStrings() const { std::lock_guard lk(m_devices_mutex); diff --git a/Source/Core/InputCommon/ControllerInterface/CoreDevice.h b/Source/Core/InputCommon/ControllerInterface/CoreDevice.h index 2280ddac3b..a2176637ab 100644 --- a/Source/Core/InputCommon/ControllerInterface/CoreDevice.h +++ b/Source/Core/InputCommon/ControllerInterface/CoreDevice.h @@ -226,6 +226,7 @@ public: Device::Input* FindInput(std::string_view name, const Device* def_dev) const; Device::Output* FindOutput(std::string_view name, const Device* def_dev) const; + std::vector> GetAllDevices() const; std::vector GetAllDeviceStrings() const; bool HasDefaultDevice() const; std::string GetDefaultDeviceString() const; -- cgit v1.2.3 From 065481d9899e6debc94bdbbb812512757f8eac62 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sat, 17 Sep 2022 12:12:39 +0200 Subject: ControllerInterface/Android: Automatically suspend sensors This is a battery-saving measure. Whether a sensor should be suspended is determined in the same way as whether key events and motion events should be handled by the OS rather than consumed by Dolphin. --- .../ControllerInterface/Android/Android.cpp | 122 ++++++++++++++------- 1 file changed, 82 insertions(+), 40 deletions(-) (limited to 'Source/Core/InputCommon/ControllerInterface') diff --git a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp index cf7e602a77..058a9e3171 100644 --- a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp @@ -67,8 +67,7 @@ jclass s_sensor_event_listener_class; jmethodID s_sensor_event_listener_constructor; jmethodID s_sensor_event_listener_constructor_input_device; jmethodID s_sensor_event_listener_set_device_qualifier; -jmethodID s_sensor_event_listener_enable_sensor_events; -jmethodID s_sensor_event_listener_disable_sensor_events; +jmethodID s_sensor_event_listener_request_unsuspend_sensor; jmethodID s_sensor_event_listener_get_axis_names; jmethodID s_sensor_event_listener_get_negative_axes; @@ -494,9 +493,45 @@ private: class AndroidSensorAxis final : public AndroidAxis { public: - AndroidSensorAxis(std::string name, bool negative) : AndroidAxis(std::move(name), negative) {} + // This class does not create its own global reference to the passed-in sensor_event_listener. + // That is, it's up to the device that contains this axis to keep sensor_event_listener valid. + // It does however create its own global reference to the passed-in name. + AndroidSensorAxis(JNIEnv* env, jobject sensor_event_listener, jstring j_name, bool negative) + : AndroidAxis(GetJString(env, j_name), negative), + m_sensor_event_listener(sensor_event_listener), + m_j_name(reinterpret_cast(env->NewGlobalRef(j_name))) + { + } + + ~AndroidSensorAxis() { IDCache::GetEnvForThread()->DeleteGlobalRef(m_j_name); } bool IsDetectable() const override { return false; } + + ControlState GetState() const override + { + if (m_is_suspended.load(std::memory_order_relaxed)) + { + IDCache::GetEnvForThread()->CallVoidMethod( + m_sensor_event_listener, s_sensor_event_listener_request_unsuspend_sensor, m_j_name); + + // m_is_suspended is intentionally not updated here. To prevent the C++ suspended status from + // ending up desynced with the Java suspended status, we only update m_is_suspended when Java + // calls notifySensorSuspendedState (which calls NotifyIsSuspended). This way, Java is the + // authoritative source for the suspended status, and C++ mirrors it (possibly with a delay). + } + + return AndroidAxis::GetState(); + } + + void NotifyIsSuspended(bool is_suspended) + { + m_is_suspended.store(is_suspended, std::memory_order_relaxed); + } + +private: + const jobject m_sensor_event_listener; + const jstring m_j_name; + std::atomic m_is_suspended = true; }; class AndroidDevice final : public Core::Device @@ -611,40 +646,45 @@ private: jobject AddSensors(JNIEnv* env, jobject input_device) { - jobject sensor_event_listener; + jobject local_sensor_event_listener; if (input_device) { - sensor_event_listener = + local_sensor_event_listener = env->NewObject(s_sensor_event_listener_class, s_sensor_event_listener_constructor_input_device, input_device); } else { - sensor_event_listener = + local_sensor_event_listener = env->NewObject(s_sensor_event_listener_class, s_sensor_event_listener_constructor); } + jobject sensor_event_listener = env->NewGlobalRef(local_sensor_event_listener); + + env->DeleteLocalRef(local_sensor_event_listener); + jobjectArray j_axis_names = reinterpret_cast( env->CallObjectMethod(sensor_event_listener, s_sensor_event_listener_get_axis_names)); - std::vector axis_names = JStringArrayToVector(env, j_axis_names); - env->DeleteLocalRef(j_axis_names); jbooleanArray j_negative_axes = reinterpret_cast( env->CallObjectMethod(sensor_event_listener, s_sensor_event_listener_get_negative_axes)); jboolean* negative_axes = env->GetBooleanArrayElements(j_negative_axes, nullptr); - ASSERT(axis_names.size() == env->GetArrayLength(j_negative_axes)); - for (size_t i = 0; i < axis_names.size(); ++i) - AddInput(new AndroidSensorAxis(axis_names[i], negative_axes[i])); + const jsize axis_count = env->GetArrayLength(j_axis_names); + ASSERT(axis_count == env->GetArrayLength(j_negative_axes)); + for (jsize i = 0; i < axis_count; ++i) + { + const jstring axis_name = + reinterpret_cast(env->GetObjectArrayElement(j_axis_names, i)); + AddInput(new AndroidSensorAxis(env, sensor_event_listener, axis_name, negative_axes[i])); + env->DeleteLocalRef(axis_name); + } + env->DeleteLocalRef(j_axis_names); env->ReleaseBooleanArrayElements(j_negative_axes, negative_axes, 0); env->DeleteLocalRef(j_negative_axes); - jobject global_sensor_event_listener = env->NewGlobalRef(sensor_event_listener); - - env->DeleteLocalRef(sensor_event_listener); - - return global_sensor_event_listener; + return sensor_event_listener; } const jobject m_sensor_event_listener; @@ -735,11 +775,8 @@ void Init() env->GetMethodID(s_sensor_event_listener_class, "", "(Landroid/view/InputDevice;)V"); s_sensor_event_listener_set_device_qualifier = env->GetMethodID( s_sensor_event_listener_class, "setDeviceQualifier", "(Ljava/lang/String;)V"); - s_sensor_event_listener_enable_sensor_events = - env->GetMethodID(s_sensor_event_listener_class, "enableSensorEvents", - "(Lorg/dolphinemu/dolphinemu/features/input/model/SensorEventRequester;)V"); - s_sensor_event_listener_disable_sensor_events = - env->GetMethodID(s_sensor_event_listener_class, "disableSensorEvents", "()V"); + s_sensor_event_listener_request_unsuspend_sensor = env->GetMethodID( + s_sensor_event_listener_class, "requestUnsuspendSensor", "(Ljava/lang/String;)V"); s_sensor_event_listener_get_axis_names = env->GetMethodID(s_sensor_event_listener_class, "getAxisNames", "()[Ljava/lang/String;"); s_sensor_event_listener_get_negative_axes = @@ -934,7 +971,7 @@ Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_dispatch return last_polled >= Clock::now() - ACTIVE_INPUT_TIMEOUT; } -JNIEXPORT void JNICALL +JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_dispatchSensorEvent( JNIEnv* env, jclass, jstring j_device_qualifier, jstring j_axis_name, jfloat value) { @@ -943,10 +980,12 @@ Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_dispatch const std::shared_ptr device = g_controller_interface.FindDevice(device_qualifier); if (!device) - return; + return JNI_FALSE; const std::string axis_name = GetJString(env, j_axis_name); + Clock::time_point last_polled{}; + for (ciface::Core::Device::Input* input : device->Inputs()) { const std::string input_name = input->GetName(); @@ -954,31 +993,34 @@ Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_dispatch { auto casted_input = static_cast(input); casted_input->SetState(value); + last_polled = std::max(last_polled, casted_input->GetLastPolled()); } } -} -JNIEXPORT void JNICALL -Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_enableSensorEvents( - JNIEnv* env, jclass, jobject j_sensor_event_requester) -{ - for (std::shared_ptr& device : g_controller_interface.GetAllDevices()) - { - env->CallVoidMethod( - static_cast(device.get())->GetSensorEventListener(), - s_sensor_event_listener_enable_sensor_events, j_sensor_event_requester); - } + return last_polled >= Clock::now() - ACTIVE_INPUT_TIMEOUT; } JNIEXPORT void JNICALL -Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_disableSensorEvents( - JNIEnv* env, jclass) +Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_notifySensorSuspendedState( + JNIEnv* env, jclass, jstring j_device_qualifier, jobjectArray j_axis_names, jboolean suspended) { - for (std::shared_ptr& device : g_controller_interface.GetAllDevices()) + ciface::Core::DeviceQualifier device_qualifier; + device_qualifier.FromString(GetJString(env, j_device_qualifier)); + const std::shared_ptr device = + g_controller_interface.FindDevice(device_qualifier); + if (!device) + return; + + const std::vector axis_names = JStringArrayToVector(env, j_axis_names); + + for (ciface::Core::Device::Input* input : device->Inputs()) { - env->CallVoidMethod( - static_cast(device.get())->GetSensorEventListener(), - s_sensor_event_listener_disable_sensor_events); + const std::string input_name = input->GetName(); + if (std::find(axis_names.begin(), axis_names.end(), input_name) != axis_names.end()) + { + auto casted_input = static_cast(input); + casted_input->NotifyIsSuspended(static_cast(suspended)); + } } } -- cgit v1.2.3 From 8e33458f4832daedf04a626d07c4541ad17ee675 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sun, 18 Sep 2022 19:14:15 +0200 Subject: ControllerInterface/Android: Implement rumble --- .../ControllerInterface/Android/Android.cpp | 92 ++++++++++++++++++++++ 1 file changed, 92 insertions(+) (limited to 'Source/Core/InputCommon/ControllerInterface') diff --git a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp index 058a9e3171..811343bf73 100644 --- a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp @@ -62,6 +62,9 @@ jmethodID s_motion_event_get_source; jclass s_controller_interface_class; jmethodID s_controller_interface_register_input_device_listener; jmethodID s_controller_interface_unregister_input_device_listener; +jmethodID s_controller_interface_get_vibrator_manager; +jmethodID s_controller_interface_get_system_vibrator_manager; +jmethodID s_controller_interface_vibrate; jclass s_sensor_event_listener_class; jmethodID s_sensor_event_listener_constructor; @@ -71,6 +74,10 @@ jmethodID s_sensor_event_listener_request_unsuspend_sensor; jmethodID s_sensor_event_listener_get_axis_names; jmethodID s_sensor_event_listener_get_negative_axes; +jclass s_dolphin_vibrator_manager_class; +jmethodID s_dolphin_vibrator_manager_get_vibrator; +jmethodID s_dolphin_vibrator_manager_get_vibrator_ids; + jintArray s_keycodes_array; using Clock = std::chrono::steady_clock; @@ -534,6 +541,35 @@ private: std::atomic m_is_suspended = true; }; +class AndroidMotor : public Core::Device::Output +{ +public: + AndroidMotor(JNIEnv* env, jobject vibrator, jint id) + : m_vibrator(env->NewGlobalRef(vibrator)), m_id(id) + { + } + + ~AndroidMotor() { IDCache::GetEnvForThread()->DeleteGlobalRef(m_vibrator); } + + std::string GetName() const override { return "Motor " + std::to_string(m_id); } + + void SetState(ControlState state) override + { + ControlState old_state = m_state.exchange(state, std::memory_order_relaxed); + + if (old_state < 0.5 && state >= 0.5) + { + IDCache::GetEnvForThread()->CallStaticVoidMethod(s_controller_interface_class, + s_controller_interface_vibrate, m_vibrator); + } + } + +private: + const jobject m_vibrator; + const jint m_id; + std::atomic m_state = 0; +}; + class AndroidDevice final : public Core::Device { public: @@ -551,6 +587,7 @@ public: AddKeys(env, input_device); AddAxes(env, input_device); + AddMotors(env, input_device); } // Constructor for the device added by Dolphin to contain sensor inputs @@ -558,6 +595,7 @@ public: : m_sensor_event_listener(AddSensors(env, nullptr)), m_source(AINPUT_SOURCE_SENSOR), m_controller_number(0), m_name(std::move(name)) { + AddSystemMotors(env); } ~AndroidDevice() @@ -687,6 +725,41 @@ private: return sensor_event_listener; } + void AddMotors(JNIEnv* env, jobject input_device) + { + jobject vibrator_manager = env->CallStaticObjectMethod( + s_controller_interface_class, s_controller_interface_get_vibrator_manager, input_device); + AddMotorsFromManager(env, vibrator_manager); + env->DeleteLocalRef(vibrator_manager); + } + + void AddSystemMotors(JNIEnv* env) + { + jobject vibrator_manager = env->CallStaticObjectMethod( + s_controller_interface_class, s_controller_interface_get_system_vibrator_manager); + AddMotorsFromManager(env, vibrator_manager); + env->DeleteLocalRef(vibrator_manager); + } + + void AddMotorsFromManager(JNIEnv* env, jobject vibrator_manager) + { + jintArray j_vibrator_ids = reinterpret_cast( + env->CallObjectMethod(vibrator_manager, s_dolphin_vibrator_manager_get_vibrator_ids)); + jint* vibrator_ids = env->GetIntArrayElements(j_vibrator_ids, nullptr); + + jint size = env->GetArrayLength(j_vibrator_ids); + for (jint i = 0; i < size; ++i) + { + jobject vibrator = + env->CallObjectMethod(vibrator_manager, s_dolphin_vibrator_manager_get_vibrator, i); + AddOutput(new AndroidMotor(env, vibrator, i)); + env->DeleteLocalRef(vibrator); + } + + env->ReleaseIntArrayElements(j_vibrator_ids, vibrator_ids, 0); + env->DeleteLocalRef(j_vibrator_ids); + } + const jobject m_sensor_event_listener; const int m_source; const int m_controller_number; @@ -764,6 +837,15 @@ void Init() env->GetStaticMethodID(s_controller_interface_class, "registerInputDeviceListener", "()V"); s_controller_interface_unregister_input_device_listener = env->GetStaticMethodID(s_controller_interface_class, "unregisterInputDeviceListener", "()V"); + s_controller_interface_get_vibrator_manager = + env->GetStaticMethodID(s_controller_interface_class, "getVibratorManager", + "(Landroid/view/InputDevice;)Lorg/dolphinemu/dolphinemu/features/" + "input/model/DolphinVibratorManager;"); + s_controller_interface_get_system_vibrator_manager = env->GetStaticMethodID( + s_controller_interface_class, "getSystemVibratorManager", + "()Lorg/dolphinemu/dolphinemu/features/input/model/DolphinVibratorManager;"); + s_controller_interface_vibrate = + env->GetStaticMethodID(s_controller_interface_class, "vibrate", "(Landroid/os/Vibrator;)V"); const jclass sensor_event_listener_class = env->FindClass("org/dolphinemu/dolphinemu/features/input/model/DolphinSensorEventListener"); @@ -782,6 +864,15 @@ void Init() s_sensor_event_listener_get_negative_axes = env->GetMethodID(s_sensor_event_listener_class, "getNegativeAxes", "()[Z"); + const jclass dolphin_vibrator_manager_class = + env->FindClass("org/dolphinemu/dolphinemu/features/input/model/DolphinVibratorManager"); + s_dolphin_vibrator_manager_class = + reinterpret_cast(env->NewGlobalRef(dolphin_vibrator_manager_class)); + s_dolphin_vibrator_manager_get_vibrator = + env->GetMethodID(s_dolphin_vibrator_manager_class, "getVibrator", "(I)Landroid/os/Vibrator;"); + s_dolphin_vibrator_manager_get_vibrator_ids = + env->GetMethodID(s_dolphin_vibrator_manager_class, "getVibratorIds", "()[I"); + jintArray keycodes_array = CreateKeyCodesArray(env); s_keycodes_array = reinterpret_cast(env->NewGlobalRef(keycodes_array)); env->DeleteLocalRef(keycodes_array); @@ -804,6 +895,7 @@ void Shutdown() env->DeleteGlobalRef(s_motion_event_class); env->DeleteGlobalRef(s_controller_interface_class); env->DeleteGlobalRef(s_sensor_event_listener_class); + env->DeleteGlobalRef(s_dolphin_vibrator_manager_class); env->DeleteGlobalRef(s_keycodes_array); } -- cgit v1.2.3 From 2b1dd52750c8c85796be4a6785fb769481ec191c Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sun, 14 Aug 2022 11:32:22 +0200 Subject: Android: Add input device selection --- Source/Core/InputCommon/ControllerInterface/Android/Android.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'Source/Core/InputCommon/ControllerInterface') diff --git a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp index 811343bf73..d2ccec4bb3 100644 --- a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp @@ -1122,4 +1122,11 @@ Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_refreshD { g_controller_interface.RefreshDevices(); } + +JNIEXPORT jobjectArray JNICALL +Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_getAllDeviceStrings( + JNIEnv* env, jclass) +{ + return VectorToJStringArray(env, g_controller_interface.GetAllDeviceStrings()); +} } -- cgit v1.2.3 From c2779aef060137d9062cfd29babb3c43fc5fa2b5 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Tue, 27 Dec 2022 16:29:01 +0100 Subject: Android: Add the advanced input mapping dialog It's missing a lot of features from the PC version for now, like buttons for inserting functions and the ability to see what the expression evaluates to. I mostly just wanted to get something in place so you can set up rumble. Co-authored-by: Charles Lombardo --- .../Core/InputCommon/ControllerInterface/Android/Android.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'Source/Core/InputCommon/ControllerInterface') diff --git a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp index d2ccec4bb3..a4bd7a3d46 100644 --- a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp @@ -25,6 +25,7 @@ #include "jni/AndroidCommon/AndroidCommon.h" #include "jni/AndroidCommon/IDCache.h" +#include "jni/Input/CoreDevice.h" namespace { @@ -1129,4 +1130,13 @@ Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_getAllDe { return VectorToJStringArray(env, g_controller_interface.GetAllDeviceStrings()); } + +JNIEXPORT jobject JNICALL +Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_getDevice( + JNIEnv* env, jclass, jstring j_device_string) +{ + ciface::Core::DeviceQualifier qualifier; + qualifier.FromString(GetJString(env, j_device_string)); + return CoreDeviceToJava(env, g_controller_interface.FindDevice(qualifier)); +} } -- cgit v1.2.3