|
@@ -3,17 +3,24 @@
|
|
|
|
|
|
|
|
package org.yuzu.yuzu_emu.utils
|
|
package org.yuzu.yuzu_emu.utils
|
|
|
|
|
|
|
|
|
|
+import android.view.InputDevice
|
|
|
import android.view.KeyEvent
|
|
import android.view.KeyEvent
|
|
|
import android.view.MotionEvent
|
|
import android.view.MotionEvent
|
|
|
import kotlin.math.sqrt
|
|
import kotlin.math.sqrt
|
|
|
import org.yuzu.yuzu_emu.NativeLibrary
|
|
import org.yuzu.yuzu_emu.NativeLibrary
|
|
|
|
|
|
|
|
-class InputHandler {
|
|
|
|
|
|
|
+object InputHandler {
|
|
|
|
|
+ private var controllerIds = getGameControllerIds()
|
|
|
|
|
+
|
|
|
fun initialize() {
|
|
fun initialize() {
|
|
|
// Connect first controller
|
|
// Connect first controller
|
|
|
NativeLibrary.onGamePadConnectEvent(getPlayerNumber(NativeLibrary.Player1Device))
|
|
NativeLibrary.onGamePadConnectEvent(getPlayerNumber(NativeLibrary.Player1Device))
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ fun updateControllerIds() {
|
|
|
|
|
+ controllerIds = getGameControllerIds()
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
fun dispatchKeyEvent(event: KeyEvent): Boolean {
|
|
fun dispatchKeyEvent(event: KeyEvent): Boolean {
|
|
|
val button: Int = when (event.device.vendorId) {
|
|
val button: Int = when (event.device.vendorId) {
|
|
|
0x045E -> getInputXboxButtonKey(event.keyCode)
|
|
0x045E -> getInputXboxButtonKey(event.keyCode)
|
|
@@ -35,7 +42,7 @@ class InputHandler {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return NativeLibrary.onGamePadButtonEvent(
|
|
return NativeLibrary.onGamePadButtonEvent(
|
|
|
- getPlayerNumber(event.device.controllerNumber),
|
|
|
|
|
|
|
+ getPlayerNumber(event.device.controllerNumber, event.deviceId),
|
|
|
button,
|
|
button,
|
|
|
action
|
|
action
|
|
|
)
|
|
)
|
|
@@ -58,9 +65,14 @@ class InputHandler {
|
|
|
return true
|
|
return true
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private fun getPlayerNumber(index: Int): Int {
|
|
|
|
|
|
|
+ private fun getPlayerNumber(index: Int, deviceId: Int = -1): Int {
|
|
|
|
|
+ var deviceIndex = index
|
|
|
|
|
+ if (deviceId != -1) {
|
|
|
|
|
+ deviceIndex = controllerIds[deviceId]!!
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// TODO: Joycons are handled as different controllers. Find a way to merge them.
|
|
// TODO: Joycons are handled as different controllers. Find a way to merge them.
|
|
|
- return when (index) {
|
|
|
|
|
|
|
+ return when (deviceIndex) {
|
|
|
2 -> NativeLibrary.Player2Device
|
|
2 -> NativeLibrary.Player2Device
|
|
|
3 -> NativeLibrary.Player3Device
|
|
3 -> NativeLibrary.Player3Device
|
|
|
4 -> NativeLibrary.Player4Device
|
|
4 -> NativeLibrary.Player4Device
|
|
@@ -238,7 +250,7 @@ class InputHandler {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private fun setGenericAxisInput(event: MotionEvent, axis: Int) {
|
|
private fun setGenericAxisInput(event: MotionEvent, axis: Int) {
|
|
|
- val playerNumber = getPlayerNumber(event.device.controllerNumber)
|
|
|
|
|
|
|
+ val playerNumber = getPlayerNumber(event.device.controllerNumber, event.deviceId)
|
|
|
|
|
|
|
|
when (axis) {
|
|
when (axis) {
|
|
|
MotionEvent.AXIS_X, MotionEvent.AXIS_Y ->
|
|
MotionEvent.AXIS_X, MotionEvent.AXIS_Y ->
|
|
@@ -297,7 +309,7 @@ class InputHandler {
|
|
|
|
|
|
|
|
private fun setJoyconAxisInput(event: MotionEvent, axis: Int) {
|
|
private fun setJoyconAxisInput(event: MotionEvent, axis: Int) {
|
|
|
// Joycon support is half dead. Right joystick doesn't work
|
|
// Joycon support is half dead. Right joystick doesn't work
|
|
|
- val playerNumber = getPlayerNumber(event.device.controllerNumber)
|
|
|
|
|
|
|
+ val playerNumber = getPlayerNumber(event.device.controllerNumber, event.deviceId)
|
|
|
|
|
|
|
|
when (axis) {
|
|
when (axis) {
|
|
|
MotionEvent.AXIS_X, MotionEvent.AXIS_Y ->
|
|
MotionEvent.AXIS_X, MotionEvent.AXIS_Y ->
|
|
@@ -325,7 +337,7 @@ class InputHandler {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private fun setRazerAxisInput(event: MotionEvent, axis: Int) {
|
|
private fun setRazerAxisInput(event: MotionEvent, axis: Int) {
|
|
|
- val playerNumber = getPlayerNumber(event.device.controllerNumber)
|
|
|
|
|
|
|
+ val playerNumber = getPlayerNumber(event.device.controllerNumber, event.deviceId)
|
|
|
|
|
|
|
|
when (axis) {
|
|
when (axis) {
|
|
|
MotionEvent.AXIS_X, MotionEvent.AXIS_Y ->
|
|
MotionEvent.AXIS_X, MotionEvent.AXIS_Y ->
|
|
@@ -362,4 +374,33 @@ class InputHandler {
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ fun getGameControllerIds(): Map<Int, Int> {
|
|
|
|
|
+ val gameControllerDeviceIds = mutableMapOf<Int, Int>()
|
|
|
|
|
+ val deviceIds = InputDevice.getDeviceIds()
|
|
|
|
|
+ var controllerSlot = 1
|
|
|
|
|
+ deviceIds.forEach { deviceId ->
|
|
|
|
|
+ InputDevice.getDevice(deviceId)?.apply {
|
|
|
|
|
+ // Don't over-assign controllers
|
|
|
|
|
+ if (controllerSlot >= 8) {
|
|
|
|
|
+ return gameControllerDeviceIds
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Verify that the device has gamepad buttons, control sticks, or both.
|
|
|
|
|
+ if (sources and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD ||
|
|
|
|
|
+ sources and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK
|
|
|
|
|
+ ) {
|
|
|
|
|
+ // This device is a game controller. Store its device ID.
|
|
|
|
|
+ if (deviceId and id and vendorId and productId != 0) {
|
|
|
|
|
+ // Additionally filter out devices that have no ID
|
|
|
|
|
+ gameControllerDeviceIds
|
|
|
|
|
+ .takeIf { !it.contains(deviceId) }
|
|
|
|
|
+ ?.put(deviceId, controllerSlot)
|
|
|
|
|
+ controllerSlot++
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return gameControllerDeviceIds
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|