mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +01:00
mobile/ebitenmobileview: Implement Android gamepad buttons
This is still work in progress. Updates #1083
This commit is contained in:
parent
37a8ae06c5
commit
8fcee54849
@ -334,49 +334,57 @@ const viewJava = `// Code generated by ebitenmobile. DO NOT EDIT.
|
|||||||
package {{.JavaPkg}}.{{.PrefixLower}};
|
package {{.JavaPkg}}.{{.PrefixLower}};
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.hardware.input.InputManager;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
|
import android.view.InputDevice;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import {{.JavaPkg}}.ebitenmobileview.Ebitenmobileview;
|
import {{.JavaPkg}}.ebitenmobileview.Ebitenmobileview;
|
||||||
|
|
||||||
public class EbitenView extends ViewGroup {
|
public class EbitenView extends ViewGroup implements InputManager.InputDeviceListener {
|
||||||
private double getDeviceScale() {
|
private double getDeviceScale() {
|
||||||
if (deviceScale_ == 0.0) {
|
if (this.deviceScale == 0.0) {
|
||||||
deviceScale_ = getResources().getDisplayMetrics().density;
|
this.deviceScale = getResources().getDisplayMetrics().density;
|
||||||
}
|
}
|
||||||
return deviceScale_;
|
return this.deviceScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
private double pxToDp(double x) {
|
private double pxToDp(double x) {
|
||||||
return x / getDeviceScale();
|
return x / getDeviceScale();
|
||||||
}
|
}
|
||||||
|
|
||||||
private double deviceScale_ = 0.0;
|
private double deviceScale = 0.0;
|
||||||
|
|
||||||
public EbitenView(Context context) {
|
public EbitenView(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
initialize();
|
initialize(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public EbitenView(Context context, AttributeSet attrs) {
|
public EbitenView(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
initialize();
|
initialize(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initialize() {
|
private void initialize(Context context) {
|
||||||
ebitenSurfaceView_ = new EbitenSurfaceView(getContext());
|
this.ebitenSurfaceView = new EbitenSurfaceView(getContext());
|
||||||
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
|
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
|
||||||
addView(ebitenSurfaceView_, params);
|
addView(this.ebitenSurfaceView, params);
|
||||||
|
|
||||||
|
this.inputManager = (InputManager)context.getSystemService(Context.INPUT_SERVICE);
|
||||||
|
this.inputManager.registerInputDeviceListener(this, null);
|
||||||
|
for (int id : this.inputManager.getInputDeviceIds()) {
|
||||||
|
this.onInputDeviceAdded(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||||
ebitenSurfaceView_.layout(0, 0, right - left, bottom - top);
|
this.ebitenSurfaceView.layout(0, 0, right - left, bottom - top);
|
||||||
double widthInDp = pxToDp(right - left);
|
double widthInDp = pxToDp(right - left);
|
||||||
double heightInDp = pxToDp(bottom - top);
|
double heightInDp = pxToDp(bottom - top);
|
||||||
Ebitenmobileview.layout(widthInDp, heightInDp);
|
Ebitenmobileview.layout(widthInDp, heightInDp);
|
||||||
@ -384,13 +392,13 @@ public class EbitenView extends ViewGroup {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||||
Ebitenmobileview.onKeyDownOnAndroid(keyCode, event.getUnicodeChar());
|
Ebitenmobileview.onKeyDownOnAndroid(keyCode, event.getUnicodeChar(), event.getSource(), event.getDeviceId());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||||
Ebitenmobileview.onKeyUpOnAndroid(keyCode);
|
Ebitenmobileview.onKeyUpOnAndroid(keyCode, event.getSource(), event.getDeviceId());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -405,11 +413,82 @@ public class EbitenView extends ViewGroup {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The order must be the same as mobile/ebitenmobileview/input_android.go.
|
||||||
|
static int[] gamepadButtons = {
|
||||||
|
KeyEvent.KEYCODE_BUTTON_A,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_B,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_C,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_X,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_Y,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_Z,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_L1,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_R1,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_L2,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_R2,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_THUMBL,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_THUMBR,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_START,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_SELECT,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_MODE,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_1,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_2,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_3,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_4,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_5,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_6,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_7,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_8,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_9,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_10,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_11,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_12,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_13,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_14,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_15,
|
||||||
|
KeyEvent.KEYCODE_BUTTON_16,
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInputDeviceAdded(int deviceId) {
|
||||||
|
InputDevice inputDevice = this.inputManager.getInputDevice(deviceId);
|
||||||
|
int sources = inputDevice.getSources();
|
||||||
|
if ((sources & InputDevice.SOURCE_GAMEPAD) != InputDevice.SOURCE_GAMEPAD &&
|
||||||
|
(sources & InputDevice.SOURCE_JOYSTICK) != InputDevice.SOURCE_JOYSTICK) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
boolean[] keyExistences = inputDevice.hasKeys(gamepadButtons);
|
||||||
|
int buttonNum = gamepadButtons.length - 1;
|
||||||
|
for (int i = gamepadButtons.length - 1; i >= 0; i--) {
|
||||||
|
if (keyExistences[i]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
buttonNum--;
|
||||||
|
}
|
||||||
|
Ebitenmobileview.onGamepadAdded(deviceId, inputDevice.getName(), buttonNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInputDeviceChanged(int deviceId) {
|
||||||
|
// Do nothing.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInputDeviceRemoved(int deviceId) {
|
||||||
|
InputDevice inputDevice = this.inputManager.getInputDevice(deviceId);
|
||||||
|
int sources = inputDevice.getSources();
|
||||||
|
if ((sources & InputDevice.SOURCE_GAMEPAD) != InputDevice.SOURCE_GAMEPAD &&
|
||||||
|
(sources & InputDevice.SOURCE_JOYSTICK) != InputDevice.SOURCE_JOYSTICK) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Ebitenmobileview.onGamepadRemoved(deviceId);
|
||||||
|
}
|
||||||
|
|
||||||
// suspendGame suspends the game.
|
// suspendGame suspends the game.
|
||||||
// It is recommended to call this when the application is being suspended e.g.,
|
// It is recommended to call this when the application is being suspended e.g.,
|
||||||
// Activity's onPause is called.
|
// Activity's onPause is called.
|
||||||
public void suspendGame() {
|
public void suspendGame() {
|
||||||
ebitenSurfaceView_.onPause();
|
this.inputManager.unregisterInputDeviceListener(this);
|
||||||
|
this.ebitenSurfaceView.onPause();
|
||||||
Ebitenmobileview.suspend();
|
Ebitenmobileview.suspend();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -417,7 +496,8 @@ public class EbitenView extends ViewGroup {
|
|||||||
// It is recommended to call this when the application is being resumed e.g.,
|
// It is recommended to call this when the application is being resumed e.g.,
|
||||||
// Activity's onResume is called.
|
// Activity's onResume is called.
|
||||||
public void resumeGame() {
|
public void resumeGame() {
|
||||||
ebitenSurfaceView_.onResume();
|
this.inputManager.registerInputDeviceListener(this, null);
|
||||||
|
this.ebitenSurfaceView.onResume();
|
||||||
Ebitenmobileview.resume();
|
Ebitenmobileview.resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,7 +507,8 @@ public class EbitenView extends ViewGroup {
|
|||||||
Log.e("Go", e.toString());
|
Log.e("Go", e.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private EbitenSurfaceView ebitenSurfaceView_;
|
private EbitenSurfaceView ebitenSurfaceView;
|
||||||
|
private InputManager inputManager;
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
@ -440,6 +521,7 @@ import android.opengl.GLSurfaceView;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import javax.microedition.khronos.egl.EGLConfig;
|
import javax.microedition.khronos.egl.EGLConfig;
|
||||||
import javax.microedition.khronos.opengles.GL10;
|
import javax.microedition.khronos.opengles.GL10;
|
||||||
@ -499,7 +581,5 @@ class EbitenSurfaceView extends GLSurfaceView {
|
|||||||
private void onErrorOnGameUpdate(Exception e) {
|
private void onErrorOnGameUpdate(Exception e) {
|
||||||
((EbitenView)getParent()).onErrorOnGameUpdate(e);
|
((EbitenView)getParent()).onErrorOnGameUpdate(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
private double deviceScale_ = 0.0;
|
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
File diff suppressed because one or more lines are too long
@ -50,3 +50,5 @@ const (
|
|||||||
GamepadButton30
|
GamepadButton30
|
||||||
GamepadButton31
|
GamepadButton31
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const GamepadButtonNum = 32
|
||||||
|
@ -26,12 +26,13 @@ type pos struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Input struct {
|
type Input struct {
|
||||||
cursorX int
|
cursorX int
|
||||||
cursorY int
|
cursorY int
|
||||||
keys map[driver.Key]struct{}
|
keys map[driver.Key]struct{}
|
||||||
runes []rune
|
runes []rune
|
||||||
touches map[int]pos
|
touches map[int]pos
|
||||||
ui *UserInterface
|
gamepads []Gamepad
|
||||||
|
ui *UserInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Input) CursorPosition() (x, y int) {
|
func (i *Input) CursorPosition() (x, y int) {
|
||||||
@ -41,30 +42,78 @@ func (i *Input) CursorPosition() (x, y int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *Input) GamepadIDs() []int {
|
func (i *Input) GamepadIDs() []int {
|
||||||
return nil
|
i.ui.m.RLock()
|
||||||
|
defer i.ui.m.RUnlock()
|
||||||
|
|
||||||
|
ids := make([]int, 0, len(i.gamepads))
|
||||||
|
for _, g := range i.gamepads {
|
||||||
|
ids = append(ids, g.ID)
|
||||||
|
}
|
||||||
|
return ids
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Input) GamepadSDLID(id int) string {
|
func (i *Input) GamepadSDLID(id int) string {
|
||||||
|
i.ui.m.RLock()
|
||||||
|
defer i.ui.m.RUnlock()
|
||||||
|
|
||||||
|
for _, g := range i.gamepads {
|
||||||
|
if g.ID != id {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return g.SDLID
|
||||||
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Input) GamepadName(id int) string {
|
func (i *Input) GamepadName(id int) string {
|
||||||
|
i.ui.m.RLock()
|
||||||
|
defer i.ui.m.RUnlock()
|
||||||
|
|
||||||
|
for _, g := range i.gamepads {
|
||||||
|
if g.ID != id {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return g.Name
|
||||||
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Input) GamepadAxisNum(id int) int {
|
func (i *Input) GamepadAxisNum(id int) int {
|
||||||
|
// TODO: Implement this
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Input) GamepadAxis(id int, axis int) float64 {
|
func (i *Input) GamepadAxis(id int, axis int) float64 {
|
||||||
|
// TODO: Implement this
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Input) GamepadButtonNum(id int) int {
|
func (i *Input) GamepadButtonNum(id int) int {
|
||||||
|
i.ui.m.RLock()
|
||||||
|
defer i.ui.m.RUnlock()
|
||||||
|
|
||||||
|
for _, g := range i.gamepads {
|
||||||
|
if g.ID != id {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return g.ButtonNum
|
||||||
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Input) IsGamepadButtonPressed(id int, button driver.GamepadButton) bool {
|
func (i *Input) IsGamepadButtonPressed(id int, button driver.GamepadButton) bool {
|
||||||
|
i.ui.m.RLock()
|
||||||
|
defer i.ui.m.RUnlock()
|
||||||
|
|
||||||
|
for _, g := range i.gamepads {
|
||||||
|
if g.ID != id {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if g.ButtonNum <= int(button) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return g.Buttons[button]
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +167,7 @@ func (i *Input) IsMouseButtonPressed(key driver.MouseButton) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Input) update(keys map[driver.Key]struct{}, runes []rune, touches []*Touch) {
|
func (i *Input) update(keys map[driver.Key]struct{}, runes []rune, touches []*Touch, gamepads []Gamepad) {
|
||||||
i.ui.m.Lock()
|
i.ui.m.Lock()
|
||||||
defer i.ui.m.Unlock()
|
defer i.ui.m.Unlock()
|
||||||
|
|
||||||
@ -137,6 +186,9 @@ func (i *Input) update(keys map[driver.Key]struct{}, runes []rune, touches []*To
|
|||||||
Y: t.Y,
|
Y: t.Y,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i.gamepads = make([]Gamepad, len(gamepads))
|
||||||
|
copy(i.gamepads, gamepads)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Input) ResetForFrame() {
|
func (i *Input) ResetForFrame() {
|
||||||
|
@ -229,7 +229,7 @@ func (u *UserInterface) appMain(a app.App) {
|
|||||||
for _, t := range touches {
|
for _, t := range touches {
|
||||||
ts = append(ts, t)
|
ts = append(ts, t)
|
||||||
}
|
}
|
||||||
u.input.update(keys, runes, ts)
|
u.input.update(keys, runes, ts, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -451,6 +451,14 @@ type Touch struct {
|
|||||||
Y int
|
Y int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInterface) UpdateInput(keys map[driver.Key]struct{}, runes []rune, touches []*Touch) {
|
type Gamepad struct {
|
||||||
u.input.update(keys, runes, touches)
|
ID int
|
||||||
|
SDLID string
|
||||||
|
Name string
|
||||||
|
Buttons [driver.GamepadButtonNum]bool
|
||||||
|
ButtonNum int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *UserInterface) UpdateInput(keys map[driver.Key]struct{}, runes []rune, touches []*Touch, gamepads []Gamepad) {
|
||||||
|
u.input.update(keys, runes, touches, gamepads)
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,10 @@ type position struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
keys = map[driver.Key]struct{}{}
|
keys = map[driver.Key]struct{}{}
|
||||||
runes []rune
|
runes []rune
|
||||||
touches = map[int]position{}
|
touches = map[int]position{}
|
||||||
|
gamepads = map[int]*mobile.Gamepad{}
|
||||||
)
|
)
|
||||||
|
|
||||||
func updateInput() {
|
func updateInput() {
|
||||||
@ -41,5 +42,11 @@ func updateInput() {
|
|||||||
Y: position.y,
|
Y: position.y,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
mobile.Get().UpdateInput(keys, runes, ts)
|
|
||||||
|
gs := make([]mobile.Gamepad, 0, len(gamepads))
|
||||||
|
for _, g := range gamepads {
|
||||||
|
gs = append(gs, *g)
|
||||||
|
}
|
||||||
|
|
||||||
|
mobile.Get().UpdateInput(keys, runes, ts, gs)
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,111 @@ package ebitenmobileview
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
|
"github.com/hajimehoshi/ebiten/internal/driver"
|
||||||
|
"github.com/hajimehoshi/ebiten/internal/uidriver/mobile"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 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
|
||||||
|
)
|
||||||
|
|
||||||
|
// https://developer.android.com/reference/android/view/InputDevice
|
||||||
|
const (
|
||||||
|
sourceKeyboard = 0x00000101
|
||||||
|
sourceGamepad = 0x00000401
|
||||||
|
sourceJoystick = 0x01000010
|
||||||
|
)
|
||||||
|
|
||||||
|
var androidKeyToGamepadButton = map[int]driver.GamepadButton{
|
||||||
|
keycodeButtonA: driver.GamepadButton0,
|
||||||
|
keycodeButtonB: driver.GamepadButton1,
|
||||||
|
keycodeButtonC: driver.GamepadButton2,
|
||||||
|
keycodeButtonX: driver.GamepadButton3,
|
||||||
|
keycodeButtonY: driver.GamepadButton4,
|
||||||
|
keycodeButtonZ: driver.GamepadButton5,
|
||||||
|
keycodeButtonL1: driver.GamepadButton6,
|
||||||
|
keycodeButtonR1: driver.GamepadButton7,
|
||||||
|
keycodeButtonL2: driver.GamepadButton8,
|
||||||
|
keycodeButtonR2: driver.GamepadButton9,
|
||||||
|
keycodeButtonThumbl: driver.GamepadButton10,
|
||||||
|
keycodeButtonThumbr: driver.GamepadButton11,
|
||||||
|
keycodeButtonStart: driver.GamepadButton12,
|
||||||
|
keycodeButtonSelect: driver.GamepadButton13,
|
||||||
|
keycodeButtonMode: driver.GamepadButton14,
|
||||||
|
keycodeButton1: driver.GamepadButton15,
|
||||||
|
keycodeButton2: driver.GamepadButton16,
|
||||||
|
keycodeButton3: driver.GamepadButton17,
|
||||||
|
keycodeButton4: driver.GamepadButton18,
|
||||||
|
keycodeButton5: driver.GamepadButton19,
|
||||||
|
keycodeButton6: driver.GamepadButton20,
|
||||||
|
keycodeButton7: driver.GamepadButton21,
|
||||||
|
keycodeButton8: driver.GamepadButton22,
|
||||||
|
keycodeButton9: driver.GamepadButton23,
|
||||||
|
keycodeButton10: driver.GamepadButton24,
|
||||||
|
keycodeButton11: driver.GamepadButton25,
|
||||||
|
keycodeButton12: driver.GamepadButton26,
|
||||||
|
keycodeButton13: driver.GamepadButton27,
|
||||||
|
keycodeButton14: driver.GamepadButton28,
|
||||||
|
keycodeButton15: driver.GamepadButton29,
|
||||||
|
keycodeButton16: driver.GamepadButton30,
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// deviceIDToGamepadID is a map from Android device IDs to Ebiten gamepad IDs.
|
||||||
|
// As convention, Ebiten gamepad IDs start with 0, and many applications depend on this fact.
|
||||||
|
deviceIDToGamepadID = map[int]int{}
|
||||||
|
)
|
||||||
|
|
||||||
|
func gamepadIDFromDeviceID(deviceID int) int {
|
||||||
|
if id, ok := deviceIDToGamepadID[deviceID]; ok {
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
ids := map[int]struct{}{}
|
||||||
|
for _, id := range deviceIDToGamepadID {
|
||||||
|
ids[id] = struct{}{}
|
||||||
|
}
|
||||||
|
for i := 0; ; i++ {
|
||||||
|
if _, ok := ids[i]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
deviceIDToGamepadID[deviceID] = i
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
panic("ebitenmobileview: a gamepad ID cannot be determined")
|
||||||
|
}
|
||||||
|
|
||||||
func UpdateTouchesOnAndroid(action int, id int, x, y int) {
|
func UpdateTouchesOnAndroid(action int, id int, x, y int) {
|
||||||
switch action {
|
switch action {
|
||||||
case 0x00, 0x05, 0x02: // ACTION_DOWN, ACTION_POINTER_DOWN, ACTION_MOVE
|
case 0x00, 0x05, 0x02: // ACTION_DOWN, ACTION_POINTER_DOWN, ACTION_MOVE
|
||||||
@ -35,23 +138,66 @@ func UpdateTouchesOnIOS(phase int, ptr int64, x, y int) {
|
|||||||
panic("ebitenmobileview: updateTouchesOnIOSImpl must not be called on Android")
|
panic("ebitenmobileview: updateTouchesOnIOSImpl must not be called on Android")
|
||||||
}
|
}
|
||||||
|
|
||||||
func OnKeyDownOnAndroid(keyCode int, unicodeChar int) {
|
func OnKeyDownOnAndroid(keyCode int, unicodeChar int, source int, deviceID int) {
|
||||||
key, ok := androidKeyToDriverKey[keyCode]
|
switch {
|
||||||
if !ok {
|
case source&sourceGamepad == sourceGamepad:
|
||||||
return
|
// A gamepad can be detected as a keyboard. Detect the device as a gamepad first.
|
||||||
|
if button, ok := androidKeyToGamepadButton[keyCode]; ok {
|
||||||
|
id := gamepadIDFromDeviceID(deviceID)
|
||||||
|
if _, ok := gamepads[id]; !ok {
|
||||||
|
// Can this happen?
|
||||||
|
gamepads[id] = &mobile.Gamepad{}
|
||||||
|
}
|
||||||
|
gamepads[id].Buttons[button] = true
|
||||||
|
updateInput()
|
||||||
|
}
|
||||||
|
case source&sourceJoystick == sourceJoystick:
|
||||||
|
// TODO: Handle DPAD keys
|
||||||
|
case source&sourceKeyboard == sourceKeyboard:
|
||||||
|
if key, ok := androidKeyToDriverKey[keyCode]; ok {
|
||||||
|
keys[key] = struct{}{}
|
||||||
|
if r := rune(unicodeChar); r != 0 && unicode.IsPrint(r) {
|
||||||
|
runes = []rune{r}
|
||||||
|
}
|
||||||
|
updateInput()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
keys[key] = struct{}{}
|
|
||||||
if r := rune(unicodeChar); r != 0 && unicode.IsPrint(r) {
|
|
||||||
runes = []rune{r}
|
|
||||||
}
|
|
||||||
updateInput()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func OnKeyUpOnAndroid(keyCode int) {
|
func OnKeyUpOnAndroid(keyCode int, source int, deviceID int) {
|
||||||
key, ok := androidKeyToDriverKey[keyCode]
|
switch {
|
||||||
if !ok {
|
case source&sourceGamepad == sourceGamepad:
|
||||||
return
|
// A gamepad can be detected as a keyboard. Detect the device as a gamepad first.
|
||||||
|
if button, ok := androidKeyToGamepadButton[keyCode]; ok {
|
||||||
|
id := gamepadIDFromDeviceID(deviceID)
|
||||||
|
if _, ok := gamepads[id]; !ok {
|
||||||
|
// Can this happen?
|
||||||
|
gamepads[id] = &mobile.Gamepad{}
|
||||||
|
}
|
||||||
|
gamepads[id].Buttons[button] = false
|
||||||
|
updateInput()
|
||||||
|
}
|
||||||
|
case source&sourceJoystick == sourceJoystick:
|
||||||
|
// TODO: Handle DPAD keys
|
||||||
|
case source&sourceKeyboard == sourceKeyboard:
|
||||||
|
if key, ok := androidKeyToDriverKey[keyCode]; ok {
|
||||||
|
delete(keys, key)
|
||||||
|
updateInput()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
delete(keys, key)
|
}
|
||||||
updateInput()
|
|
||||||
|
func OnGamepadAdded(deviceID int, name string, buttonNum int) {
|
||||||
|
id := gamepadIDFromDeviceID(deviceID)
|
||||||
|
gamepads[id] = &mobile.Gamepad{
|
||||||
|
ID: id,
|
||||||
|
SDLID: "", // TODO: Implement this
|
||||||
|
Name: name,
|
||||||
|
ButtonNum: buttonNum,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func OnGamepadRemoved(deviceID int) {
|
||||||
|
id := gamepadIDFromDeviceID(deviceID)
|
||||||
|
delete(gamepads, id)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user