123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- // Copyright 2016 Hajime Hoshi
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package ebitenmobileview
- import (
- "encoding/hex"
- "hash/crc32"
- "unicode"
- "github.com/hajimehoshi/ebiten/v2/internal/gamepad"
- "github.com/hajimehoshi/ebiten/v2/internal/gamepaddb"
- "github.com/hajimehoshi/ebiten/v2/internal/ui"
- )
- // https://developer.android.com/reference/android/view/KeyEvent
- const (
- keycodeButtonA = 0x00000060
- keycodeButtonB = 0x00000061
- keycodeButtonC = 0x00000062
- keycodeButtonX = 0x00000063
- keycodeButtonY = 0x00000064
- keycodeButtonZ = 0x00000065
- keycodeButtonL1 = 0x00000066
- keycodeButtonR1 = 0x00000067
- keycodeButtonL2 = 0x00000068
- keycodeButtonR2 = 0x00000069
- keycodeButtonThumbl = 0x0000006a
- keycodeButtonThumbr = 0x0000006b
- keycodeButtonStart = 0x0000006c
- keycodeButtonSelect = 0x0000006d
- keycodeButtonMode = 0x0000006e
- keycodeButton1 = 0x000000bc
- keycodeButton2 = 0x000000bd
- keycodeButton3 = 0x000000be
- keycodeButton4 = 0x000000bf
- keycodeButton5 = 0x000000c0
- keycodeButton6 = 0x000000c1
- keycodeButton7 = 0x000000c2
- keycodeButton8 = 0x000000c3
- keycodeButton9 = 0x000000c4
- keycodeButton10 = 0x000000c5
- keycodeButton11 = 0x000000c6
- keycodeButton12 = 0x000000c7
- keycodeButton13 = 0x000000c8
- keycodeButton14 = 0x000000c9
- keycodeButton15 = 0x000000ca
- keycodeButton16 = 0x000000cb
- keycodeDpadUp = 0x00000013
- keycodeDpadDown = 0x00000014
- keycodeDpadLeft = 0x00000015
- keycodeDpadRight = 0x00000016
- keycodeDpadCenter = 0x00000017
- keycodeBack = 0x00000004
- keycodeMenu = 0x00000052
- )
- // https://developer.android.com/reference/android/view/InputDevice
- const (
- sourceKeyboard = 0x00000101
- sourceGamepad = 0x00000401
- sourceJoystick = 0x01000010
- )
- // See https://github.com/libsdl-org/SDL/blob/47f2373dc13b66c48bf4024fcdab53cd0bdd59bb/src/joystick/android/SDL_sysjoystick.c#L71-L172
- // TODO: This exceeds gamepad.SDLControllerButtonMax. Is that OK?
- var androidKeyToSDL = map[int]int{
- keycodeButtonA: gamepaddb.SDLControllerButtonA,
- keycodeButtonB: gamepaddb.SDLControllerButtonB,
- keycodeButtonX: gamepaddb.SDLControllerButtonX,
- keycodeButtonY: gamepaddb.SDLControllerButtonY,
- keycodeButtonL1: gamepaddb.SDLControllerButtonLeftShoulder,
- keycodeButtonR1: gamepaddb.SDLControllerButtonRightShoulder,
- keycodeButtonThumbl: gamepaddb.SDLControllerButtonLeftStick,
- keycodeButtonThumbr: gamepaddb.SDLControllerButtonRightStick,
- keycodeMenu: gamepaddb.SDLControllerButtonStart,
- keycodeButtonStart: gamepaddb.SDLControllerButtonStart,
- keycodeBack: gamepaddb.SDLControllerButtonBack,
- keycodeButtonSelect: gamepaddb.SDLControllerButtonBack,
- keycodeButtonMode: gamepaddb.SDLControllerButtonGuide,
- keycodeButtonL2: 15,
- keycodeButtonR2: 16,
- keycodeButtonC: 17,
- keycodeButtonZ: 18,
- keycodeDpadUp: gamepaddb.SDLControllerButtonDpadUp,
- keycodeDpadDown: gamepaddb.SDLControllerButtonDpadDown,
- keycodeDpadLeft: gamepaddb.SDLControllerButtonDpadLeft,
- keycodeDpadRight: gamepaddb.SDLControllerButtonDpadRight,
- keycodeDpadCenter: gamepaddb.SDLControllerButtonA,
- keycodeButton1: 20,
- keycodeButton2: 21,
- keycodeButton3: 22,
- keycodeButton4: 23,
- keycodeButton5: 24,
- keycodeButton6: 25,
- keycodeButton7: 26,
- keycodeButton8: 27,
- keycodeButton9: 28,
- keycodeButton10: 29,
- keycodeButton11: 30,
- keycodeButton12: 31,
- keycodeButton13: 32,
- keycodeButton14: 33,
- keycodeButton15: 34,
- keycodeButton16: 35,
- }
- func UpdateTouchesOnAndroid(action int, id int, x, y int) {
- switch action {
- case 0x00, 0x05, 0x02: // ACTION_DOWN, ACTION_POINTER_DOWN, ACTION_MOVE
- touches[ui.TouchID(id)] = position{x, y}
- updateInput(nil)
- case 0x01, 0x06: // ACTION_UP, ACTION_POINTER_UP
- delete(touches, ui.TouchID(id))
- updateInput(nil)
- }
- }
- func OnKeyDownOnAndroid(keyCode int, unicodeChar int, source int, deviceID int) {
- switch {
- case source&sourceGamepad == sourceGamepad:
- // A gamepad can be detected as a keyboard. Detect the device as a gamepad first.
- if button, ok := androidKeyToSDL[keyCode]; ok {
- gamepad.UpdateAndroidGamepadButton(deviceID, gamepad.Button(button), true)
- }
- case source&sourceJoystick == sourceJoystick:
- // DPAD keys can come here, but they are also treated as an axis at a motion event. Ignore them.
- case source&sourceKeyboard == sourceKeyboard:
- if key, ok := androidKeyToUIKey[keyCode]; ok {
- keys[key] = struct{}{}
- }
- var runes []rune
- if r := rune(unicodeChar); r != 0 && unicode.IsPrint(r) {
- runes = []rune{r}
- }
- updateInput(runes)
- }
- }
- func OnKeyUpOnAndroid(keyCode int, source int, deviceID int) {
- switch {
- case source&sourceGamepad == sourceGamepad:
- // A gamepad can be detected as a keyboard. Detect the device as a gamepad first.
- if button, ok := androidKeyToSDL[keyCode]; ok {
- gamepad.UpdateAndroidGamepadButton(deviceID, gamepad.Button(button), false)
- }
- case source&sourceJoystick == sourceJoystick:
- // DPAD keys can come here, but they are also treated as an axis at a motion event. Ignore them.
- case source&sourceKeyboard == sourceKeyboard:
- if key, ok := androidKeyToUIKey[keyCode]; ok {
- delete(keys, key)
- }
- updateInput(nil)
- }
- }
- func OnGamepadAxisChanged(deviceID int, axisID int, value float32) {
- gamepad.UpdateAndroidGamepadAxis(deviceID, axisID, float64(value))
- }
- func OnGamepadHatChanged(deviceID int, hatID int, xValue, yValue int) {
- gamepad.UpdateAndroidGamepadHat(deviceID, hatID, xValue, yValue)
- }
- func OnGamepadAdded(deviceID int, name string, axisCount int, hatCount int, descriptor string, vendorID int, productID int, buttonMask int, axisMask int) {
- // This emulates the implementation of Android_AddJoystick.
- // https://github.com/libsdl-org/SDL/blob/0e9560aea22818884921e5e5064953257bfe7fa7/src/joystick/android/SDL_sysjoystick.c#L386
- const SDL_HARDWARE_BUS_BLUETOOTH = 0x05
- var sdlid [16]byte
- sdlid[0] = byte(SDL_HARDWARE_BUS_BLUETOOTH)
- sdlid[1] = byte(SDL_HARDWARE_BUS_BLUETOOTH >> 8)
- if vendorID != 0 && productID != 0 {
- sdlid[4] = byte(vendorID)
- sdlid[5] = byte(vendorID >> 8)
- sdlid[8] = byte(productID)
- sdlid[9] = byte(productID >> 8)
- } else {
- crc := crc32.ChecksumIEEE(([]byte)(descriptor))
- copy(sdlid[4:8], ([]byte)(descriptor))
- sdlid[8] = byte(crc)
- sdlid[9] = byte(crc >> 8)
- sdlid[10] = byte(crc >> 16)
- sdlid[11] = byte(crc >> 24)
- }
- sdlid[12] = byte(buttonMask)
- sdlid[13] = byte(buttonMask >> 8)
- sdlid[14] = byte(axisMask)
- sdlid[15] = byte(axisMask >> 8)
- gamepad.AddAndroidGamepad(deviceID, name, hex.EncodeToString(sdlid[:]), axisCount, hatCount)
- }
- func OnInputDeviceRemoved(deviceID int) {
- gamepad.RemoveAndroidGamepad(deviceID)
- }
|