Поддержка различных производителей контроллеров геймпада - PullRequest
1 голос
/ 27 сентября 2019

Недавно я хотел добавить поддержку контроллера геймпада для моего приложения , однако обнаружил, что отображение клавиш Sony Dualshock сильно отличается от того, что указано в документации .Я сделал отображение в зависимости от поставщика, но я понятия не имею, так ли это для всех контроллеров Dualshock ps4 и как я могу быть уверен, что не будет проблем с другими контроллерами.Как вы, люди, справляетесь с этим дерьмом?

class KeyMapping(context: Context) {

    private val preferences = Preferences(context)

    companion object {
        private const val SONY = 1356
    }

    fun key(event: KeyEvent): Event? {
        return if (Dpad.isDpadDevice(event)) {
            when (Dpad().getDirectionPressed(event)) {
                Dpad.UP -> Event.UP
                Dpad.DOWN -> Event.DOWN
                Dpad.LEFT -> Event.BACK
                Dpad.RIGHT -> Event.FORWARD
                else -> getEvent(event, getDefault(event))

            }
        } else {
            null
        }
    }

    private fun getDefault(event: KeyEvent): Event {
        val isSony = if (Build.VERSION.SDK_INT >= 19) {
            event.device.vendorId == SONY
        } else {
            false
        }

        return when (event.keyCode) {
            KeyEvent.KEYCODE_BUTTON_A -> if (isSony) Event.SQUARE else Event.X
            KeyEvent.KEYCODE_BUTTON_X -> if (isSony) Event.TRIANGLE else Event.SQUARE
            KeyEvent.KEYCODE_BUTTON_Y -> if (isSony) Event.EXTRA else Event.TRIANGLE
            KeyEvent.KEYCODE_BUTTON_B -> if (isSony) Event.X else Event.CIRCLE
            KeyEvent.KEYCODE_BUTTON_R1 -> Event.AMPLIFY
            KeyEvent.KEYCODE_BUTTON_R2 -> Event.AMPLIFY
            KeyEvent.KEYCODE_BUTTON_L1 -> Event.EXTRA
            KeyEvent.KEYCODE_BUTTON_L2 -> Event.EXTRA
            KeyEvent.KEYCODE_BUTTON_C -> Event.CIRCLE
            KeyEvent.KEYCODE_BUTTON_Z -> Event.AMPLIFY
            else -> Event.X
        }
    }

    private fun getEvent(event: KeyEvent, defaultEvent: Event): Event {
        return preferences.key(event.keyCode, defaultEvent)
    }
}

class Dpad {

    private var directionPressed = -1 // initialized to -1

    fun getDirectionPressed(event: InputEvent): Int {
        if (!isDpadDevice(event)) {
            return -1
        }

        // If the input event is a MotionEvent, check its hat axis values.
        (event as? MotionEvent)?.apply {

            // Use the hat axis value to find the D-pad direction
            val xaxis: Float = event.getAxisValue(MotionEvent.AXIS_HAT_X)
            val yaxis: Float = event.getAxisValue(MotionEvent.AXIS_HAT_Y)

            directionPressed = when {
                // Check if the AXIS_HAT_X value is -1 or 1, and set the D-pad
                // LEFT and RIGHT direction accordingly.
                xaxis.compareTo(-1.0f) == 0 -> Dpad.LEFT
                xaxis.compareTo(1.0f) == 0 -> Dpad.RIGHT
                // Check if the AXIS_HAT_Y value is -1 or 1, and set the D-pad
                // UP and DOWN direction accordingly.
                yaxis.compareTo(-1.0f) == 0 -> Dpad.UP
                yaxis.compareTo(1.0f) == 0 -> Dpad.DOWN
                else -> directionPressed
            }
        }
        // If the input event is a KeyEvent, check its key code.
        (event as? KeyEvent)?.apply {

            // Use the key code to find the D-pad direction.
            directionPressed = when (event.keyCode) {
                KeyEvent.KEYCODE_DPAD_LEFT -> Dpad.LEFT
                KeyEvent.KEYCODE_DPAD_RIGHT -> Dpad.RIGHT
                KeyEvent.KEYCODE_DPAD_UP -> Dpad.UP
                KeyEvent.KEYCODE_DPAD_DOWN -> Dpad.DOWN
                KeyEvent.KEYCODE_DPAD_CENTER -> Dpad.CENTER
                else -> directionPressed
            }
        }
        return directionPressed
    }

    companion object {
        internal const val UP = 0
        internal const val LEFT = 1
        internal const val RIGHT = 2
        internal const val DOWN = 3
        internal const val CENTER = 4

        fun isDpadDevice(event: InputEvent): Boolean =
                // Check that input comes from a device with directional pads.
                event.source and InputDevice.SOURCE_DPAD != InputDevice.SOURCE_DPAD
    }
}
...