mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +01:00
mobile/ebitenmobileview: Handle keyboard keys on Android (ebitenmobile)
Updates #237
This commit is contained in:
parent
6faad68931
commit
5b7151595b
@ -338,6 +338,7 @@ import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import {{.JavaPkg}}.ebitenmobileview.Ebitenmobileview;
|
||||
@ -354,10 +355,6 @@ public class EbitenView extends ViewGroup {
|
||||
return x / getDeviceScale();
|
||||
}
|
||||
|
||||
private double dpToPx(double x) {
|
||||
return x * getDeviceScale();
|
||||
}
|
||||
|
||||
private double deviceScale_ = 0.0;
|
||||
|
||||
public EbitenView(Context context) {
|
||||
@ -384,6 +381,18 @@ public class EbitenView extends ViewGroup {
|
||||
Ebitenmobileview.layout(widthInDp, heightInDp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
Ebitenmobileview.onKeyDownOnAndroid(keyCode);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
Ebitenmobileview.onKeyUpOnAndroid(keyCode);
|
||||
return true;
|
||||
}
|
||||
|
||||
// suspendGame suspends the game.
|
||||
// It is recommended to call this when the application is being suspended e.g.,
|
||||
// Activity's onPause is called.
|
||||
|
File diff suppressed because one or more lines are too long
89
genkeys.go
89
genkeys.go
@ -35,6 +35,7 @@ import (
|
||||
|
||||
var (
|
||||
nameToGLFWKey map[string]glfw.Key
|
||||
nameToAndroidKey map[string]int
|
||||
nameToJSKey map[string]string
|
||||
edgeKeyCodeToName map[int]string
|
||||
)
|
||||
@ -93,6 +94,56 @@ func init() {
|
||||
"KPEqual": glfw.KeyKPEqual,
|
||||
"Last": glfw.KeyLast,
|
||||
}
|
||||
|
||||
// https://developer.android.com/reference/android/view/KeyEvent
|
||||
nameToAndroidKey = map[string]int{
|
||||
"Comma": 55,
|
||||
"Period": 56,
|
||||
"LeftAlt": 57,
|
||||
"RightAlt": 58,
|
||||
"CapsLock": 115,
|
||||
"LeftControl": 113,
|
||||
"RightControl": 114,
|
||||
"LeftShift": 59,
|
||||
"RightShift": 60,
|
||||
"Enter": 66,
|
||||
"Space": 62,
|
||||
"Tab": 61,
|
||||
"Delete": 112, // KEYCODE_FORWARD_DEL
|
||||
"End": 123,
|
||||
"Home": 122,
|
||||
"Insert": 124,
|
||||
"PageDown": 93,
|
||||
"PageUp": 92,
|
||||
"Down": 20,
|
||||
"Left": 21,
|
||||
"Right": 22,
|
||||
"Up": 19,
|
||||
"Escape": 111,
|
||||
"Backspace": 67, // KEYCODE_DEL
|
||||
"Apostrophe": 75,
|
||||
"Minus": 69,
|
||||
"Slash": 76,
|
||||
"Semicolon": 74,
|
||||
"Equal": 70,
|
||||
"LeftBracket": 71,
|
||||
"Backslash": 73,
|
||||
"RightBracket": 72,
|
||||
"GraveAccent": 68,
|
||||
"NumLock": 143,
|
||||
"Pause": 121, // KEYCODE_BREAK
|
||||
"PrintScreen": 120, // KEYCODE_SYSRQ
|
||||
"ScrollLock": 116,
|
||||
"Menu": 82,
|
||||
"KPDecimal": 158,
|
||||
"KPDivide": 154,
|
||||
"KPMultiply": 155,
|
||||
"KPSubtract": 156,
|
||||
"KPAdd": 157,
|
||||
"KPEnter": 160,
|
||||
"KPEqual": 161,
|
||||
}
|
||||
|
||||
nameToJSKey = map[string]string{
|
||||
"Comma": "Comma",
|
||||
"Period": "Period",
|
||||
@ -140,20 +191,24 @@ func init() {
|
||||
"KPEnter": "NumpadEnter",
|
||||
"KPEqual": "NumpadEqual",
|
||||
}
|
||||
|
||||
// ASCII: 0 - 9
|
||||
for c := '0'; c <= '9'; c++ {
|
||||
nameToGLFWKey[string(c)] = glfw.Key0 + glfw.Key(c) - '0'
|
||||
nameToAndroidKey[string(c)] = int(7 + c - '0')
|
||||
nameToJSKey[string(c)] = "Digit" + string(c)
|
||||
}
|
||||
// ASCII: A - Z
|
||||
for c := 'A'; c <= 'Z'; c++ {
|
||||
nameToGLFWKey[string(c)] = glfw.KeyA + glfw.Key(c) - 'A'
|
||||
nameToAndroidKey[string(c)] = int(29 + c - 'A')
|
||||
nameToJSKey[string(c)] = "Key" + string(c)
|
||||
}
|
||||
// Function keys
|
||||
for i := 1; i <= 12; i++ {
|
||||
name := "F" + strconv.Itoa(i)
|
||||
nameToGLFWKey[name] = glfw.KeyF1 + glfw.Key(i) - 1
|
||||
nameToAndroidKey[name] = 131 + i - 1
|
||||
nameToJSKey[name] = name
|
||||
}
|
||||
// Numpad
|
||||
@ -161,6 +216,7 @@ func init() {
|
||||
for c := '0'; c <= '9'; c++ {
|
||||
name := "KP" + string(c)
|
||||
nameToGLFWKey[name] = glfw.KeyKP0 + glfw.Key(c) - '0'
|
||||
nameToAndroidKey[name] = int(144 + c - '0')
|
||||
nameToJSKey[name] = "Numpad" + string(c)
|
||||
}
|
||||
}
|
||||
@ -384,6 +440,24 @@ const (
|
||||
)
|
||||
`
|
||||
|
||||
const mobileAndroidKeysTmpl = `{{.License}}
|
||||
|
||||
{{.DoNotEdit}}
|
||||
|
||||
{{.BuildTag}}
|
||||
|
||||
package ebitenmobileview
|
||||
|
||||
import (
|
||||
"github.com/hajimehoshi/ebiten/internal/driver"
|
||||
)
|
||||
|
||||
var androidKeyToDriverKey = map[int]driver.Key{
|
||||
{{range $name, $code := .NameToAndroidKey}}{{$code}}: driver.Key{{$name}},
|
||||
{{end}}
|
||||
}
|
||||
`
|
||||
|
||||
func digitKey(name string) int {
|
||||
if len(name) != 1 {
|
||||
return -1
|
||||
@ -502,12 +576,13 @@ func main() {
|
||||
sort.Slice(driverKeyNames, keyNamesLess(driverKeyNames))
|
||||
|
||||
for path, tmpl := range map[string]string{
|
||||
filepath.Join("event", "keys.go"): eventKeysTmpl,
|
||||
filepath.Join("internal", "driver", "keys.go"): driverKeysTmpl,
|
||||
filepath.Join("internal", "glfw", "keys.go"): glfwKeysTmpl,
|
||||
filepath.Join("internal", "uidriver", "glfw", "keys.go"): uidriverGlfwKeysTmpl,
|
||||
filepath.Join("internal", "uidriver", "js", "keys.go"): uidriverJsKeysTmpl,
|
||||
filepath.Join("keys.go"): ebitenKeysTmpl,
|
||||
filepath.Join("event", "keys.go"): eventKeysTmpl,
|
||||
filepath.Join("internal", "driver", "keys.go"): driverKeysTmpl,
|
||||
filepath.Join("internal", "glfw", "keys.go"): glfwKeysTmpl,
|
||||
filepath.Join("internal", "uidriver", "glfw", "keys.go"): uidriverGlfwKeysTmpl,
|
||||
filepath.Join("internal", "uidriver", "js", "keys.go"): uidriverJsKeysTmpl,
|
||||
filepath.Join("keys.go"): ebitenKeysTmpl,
|
||||
filepath.Join("mobile", "ebitenmobileview", "keys_android.go"): mobileAndroidKeysTmpl,
|
||||
} {
|
||||
f, err := os.Create(path)
|
||||
if err != nil {
|
||||
@ -546,6 +621,7 @@ func main() {
|
||||
EbitenKeyNamesWithoutMods []string
|
||||
DriverKeyNames []string
|
||||
NameToGLFWKey map[string]glfw.Key
|
||||
NameToAndroidKey map[string]int
|
||||
}{
|
||||
License: license,
|
||||
DoNotEdit: doNotEdit,
|
||||
@ -556,6 +632,7 @@ func main() {
|
||||
EbitenKeyNamesWithoutMods: ebitenKeyNamesWithoutMods,
|
||||
DriverKeyNames: driverKeyNames,
|
||||
NameToGLFWKey: nameToGLFWKey,
|
||||
NameToAndroidKey: nameToAndroidKey,
|
||||
}); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
2
input.go
2
input.go
@ -39,6 +39,8 @@ func InputChars() []rune {
|
||||
// - KeyKPEnter and KeyKPEqual are recognized as KeyEnter and KeyEqual.
|
||||
// - KeyPrintScreen is only treated at keyup event.
|
||||
//
|
||||
// On Android (ebitenmobile), EbitenView must be focusable to enable to handle keys.
|
||||
//
|
||||
// IsKeyPressed is concurrent-safe.
|
||||
func IsKeyPressed(key Key) bool {
|
||||
// There are keys that are invalid values as ebiten.Key (e.g., driver.KeyLeftAlt).
|
||||
|
@ -28,6 +28,7 @@ type pos struct {
|
||||
type Input struct {
|
||||
cursorX int
|
||||
cursorY int
|
||||
keys map[driver.Key]struct{}
|
||||
touches map[int]pos
|
||||
ui *UserInterface
|
||||
}
|
||||
@ -98,7 +99,14 @@ func (i *Input) RuneBuffer() []rune {
|
||||
}
|
||||
|
||||
func (i *Input) IsKeyPressed(key driver.Key) bool {
|
||||
return false
|
||||
i.ui.m.RLock()
|
||||
defer i.ui.m.RUnlock()
|
||||
|
||||
if i.keys == nil {
|
||||
return false
|
||||
}
|
||||
_, ok := i.keys[key]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (i *Input) Wheel() (xoff, yoff float64) {
|
||||
@ -109,8 +117,15 @@ func (i *Input) IsMouseButtonPressed(key driver.MouseButton) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (i *Input) update(touches []*Touch) {
|
||||
func (i *Input) update(keys map[driver.Key]struct{}, touches []*Touch) {
|
||||
i.ui.m.Lock()
|
||||
defer i.ui.m.Unlock()
|
||||
|
||||
i.keys = map[driver.Key]struct{}{}
|
||||
for k := range keys {
|
||||
i.keys[k] = struct{}{}
|
||||
}
|
||||
|
||||
i.touches = map[int]pos{}
|
||||
for _, t := range touches {
|
||||
i.touches[t.ID] = pos{
|
||||
@ -118,7 +133,6 @@ func (i *Input) update(touches []*Touch) {
|
||||
Y: t.Y,
|
||||
}
|
||||
}
|
||||
i.ui.m.Unlock()
|
||||
}
|
||||
|
||||
func (i *Input) ResetForFrame() {
|
||||
|
@ -199,7 +199,8 @@ func (u *UserInterface) appMain(a app.App) {
|
||||
for _, t := range touches {
|
||||
ts = append(ts, t)
|
||||
}
|
||||
u.input.update(ts)
|
||||
// TODO: Give keyboard keys.
|
||||
u.input.update(nil, ts)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -421,6 +422,6 @@ type Touch struct {
|
||||
Y int
|
||||
}
|
||||
|
||||
func (u *UserInterface) UpdateInput(touches []*Touch) {
|
||||
u.input.update(touches)
|
||||
func (u *UserInterface) UpdateInput(keys map[driver.Key]struct{}, touches []*Touch) {
|
||||
u.input.update(keys, touches)
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
package ebitenmobileview
|
||||
|
||||
import (
|
||||
"github.com/hajimehoshi/ebiten/internal/driver"
|
||||
"github.com/hajimehoshi/ebiten/internal/uidriver/mobile"
|
||||
)
|
||||
|
||||
@ -26,6 +27,7 @@ type position struct {
|
||||
}
|
||||
|
||||
var (
|
||||
keys = map[driver.Key]struct{}{}
|
||||
touches = map[int]position{}
|
||||
)
|
||||
|
||||
@ -38,5 +40,5 @@ func updateInput() {
|
||||
Y: position.y,
|
||||
})
|
||||
}
|
||||
mobile.Get().UpdateInput(ts)
|
||||
mobile.Get().UpdateInput(keys, ts)
|
||||
}
|
||||
|
@ -30,3 +30,21 @@ func UpdateTouchesOnAndroid(action int, id int, x, y int) {
|
||||
func UpdateTouchesOnIOS(phase int, ptr int64, x, y int) {
|
||||
panic("ebitenmobileview: updateTouchesOnIOSImpl must not be called on Android")
|
||||
}
|
||||
|
||||
func OnKeyDownOnAndroid(keyCode int) {
|
||||
key, ok := androidKeyToDriverKey[keyCode]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
keys[key] = struct{}{}
|
||||
updateInput()
|
||||
}
|
||||
|
||||
func OnKeyUpOnAndroid(keyCode int) {
|
||||
key, ok := androidKeyToDriverKey[keyCode]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
delete(keys, key)
|
||||
updateInput()
|
||||
}
|
||||
|
127
mobile/ebitenmobileview/keys_android.go
Normal file
127
mobile/ebitenmobileview/keys_android.go
Normal file
@ -0,0 +1,127 @@
|
||||
// Copyright 2013 The Ebiten Authors
|
||||
//
|
||||
// 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.
|
||||
|
||||
// Code generated by genkeys.go using 'go generate'. DO NOT EDIT.
|
||||
|
||||
package ebitenmobileview
|
||||
|
||||
import (
|
||||
"github.com/hajimehoshi/ebiten/internal/driver"
|
||||
)
|
||||
|
||||
var androidKeyToDriverKey = map[int]driver.Key{
|
||||
7: driver.Key0,
|
||||
8: driver.Key1,
|
||||
9: driver.Key2,
|
||||
10: driver.Key3,
|
||||
11: driver.Key4,
|
||||
12: driver.Key5,
|
||||
13: driver.Key6,
|
||||
14: driver.Key7,
|
||||
15: driver.Key8,
|
||||
16: driver.Key9,
|
||||
29: driver.KeyA,
|
||||
75: driver.KeyApostrophe,
|
||||
30: driver.KeyB,
|
||||
73: driver.KeyBackslash,
|
||||
67: driver.KeyBackspace,
|
||||
31: driver.KeyC,
|
||||
115: driver.KeyCapsLock,
|
||||
55: driver.KeyComma,
|
||||
32: driver.KeyD,
|
||||
112: driver.KeyDelete,
|
||||
20: driver.KeyDown,
|
||||
33: driver.KeyE,
|
||||
123: driver.KeyEnd,
|
||||
66: driver.KeyEnter,
|
||||
70: driver.KeyEqual,
|
||||
111: driver.KeyEscape,
|
||||
34: driver.KeyF,
|
||||
131: driver.KeyF1,
|
||||
140: driver.KeyF10,
|
||||
141: driver.KeyF11,
|
||||
142: driver.KeyF12,
|
||||
132: driver.KeyF2,
|
||||
133: driver.KeyF3,
|
||||
134: driver.KeyF4,
|
||||
135: driver.KeyF5,
|
||||
136: driver.KeyF6,
|
||||
137: driver.KeyF7,
|
||||
138: driver.KeyF8,
|
||||
139: driver.KeyF9,
|
||||
35: driver.KeyG,
|
||||
68: driver.KeyGraveAccent,
|
||||
36: driver.KeyH,
|
||||
122: driver.KeyHome,
|
||||
37: driver.KeyI,
|
||||
124: driver.KeyInsert,
|
||||
38: driver.KeyJ,
|
||||
39: driver.KeyK,
|
||||
144: driver.KeyKP0,
|
||||
145: driver.KeyKP1,
|
||||
146: driver.KeyKP2,
|
||||
147: driver.KeyKP3,
|
||||
148: driver.KeyKP4,
|
||||
149: driver.KeyKP5,
|
||||
150: driver.KeyKP6,
|
||||
151: driver.KeyKP7,
|
||||
152: driver.KeyKP8,
|
||||
153: driver.KeyKP9,
|
||||
157: driver.KeyKPAdd,
|
||||
158: driver.KeyKPDecimal,
|
||||
154: driver.KeyKPDivide,
|
||||
160: driver.KeyKPEnter,
|
||||
161: driver.KeyKPEqual,
|
||||
155: driver.KeyKPMultiply,
|
||||
156: driver.KeyKPSubtract,
|
||||
40: driver.KeyL,
|
||||
21: driver.KeyLeft,
|
||||
57: driver.KeyLeftAlt,
|
||||
71: driver.KeyLeftBracket,
|
||||
113: driver.KeyLeftControl,
|
||||
59: driver.KeyLeftShift,
|
||||
41: driver.KeyM,
|
||||
82: driver.KeyMenu,
|
||||
69: driver.KeyMinus,
|
||||
42: driver.KeyN,
|
||||
143: driver.KeyNumLock,
|
||||
43: driver.KeyO,
|
||||
44: driver.KeyP,
|
||||
93: driver.KeyPageDown,
|
||||
92: driver.KeyPageUp,
|
||||
121: driver.KeyPause,
|
||||
56: driver.KeyPeriod,
|
||||
120: driver.KeyPrintScreen,
|
||||
45: driver.KeyQ,
|
||||
46: driver.KeyR,
|
||||
22: driver.KeyRight,
|
||||
58: driver.KeyRightAlt,
|
||||
72: driver.KeyRightBracket,
|
||||
114: driver.KeyRightControl,
|
||||
60: driver.KeyRightShift,
|
||||
47: driver.KeyS,
|
||||
116: driver.KeyScrollLock,
|
||||
74: driver.KeySemicolon,
|
||||
76: driver.KeySlash,
|
||||
62: driver.KeySpace,
|
||||
48: driver.KeyT,
|
||||
61: driver.KeyTab,
|
||||
49: driver.KeyU,
|
||||
19: driver.KeyUp,
|
||||
50: driver.KeyV,
|
||||
51: driver.KeyW,
|
||||
52: driver.KeyX,
|
||||
53: driver.KeyY,
|
||||
54: driver.KeyZ,
|
||||
}
|
Loading…
Reference in New Issue
Block a user