mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-01-23 17:32:02 +01:00
internal/gamepaddb: enable the database for Android
Before this fix, the button and axis IDs are from the OS. These didn't match with the SDL game controller databaes unfortunately. This fix changes the assignments of the buttons and the axes to match with the database. Closes #2312
This commit is contained in:
parent
6b1502ee71
commit
47558d20c5
@ -354,6 +354,11 @@ const viewJava = `// Code generated by ebitenmobile. DO NOT EDIT.
|
|||||||
|
|
||||||
package {{.JavaPkg}}.{{.PrefixLower}};
|
package {{.JavaPkg}}.{{.PrefixLower}};
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.hardware.input.InputManager;
|
import android.hardware.input.InputManager;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
@ -371,6 +376,32 @@ import android.view.WindowManager;
|
|||||||
import {{.JavaPkg}}.ebitenmobileview.Ebitenmobileview;
|
import {{.JavaPkg}}.ebitenmobileview.Ebitenmobileview;
|
||||||
|
|
||||||
public class EbitenView extends ViewGroup implements InputManager.InputDeviceListener {
|
public class EbitenView extends ViewGroup implements InputManager.InputDeviceListener {
|
||||||
|
static class Gamepad {
|
||||||
|
public int deviceId;
|
||||||
|
public ArrayList<InputDevice.MotionRange> axes;
|
||||||
|
public ArrayList<InputDevice.MotionRange> hats;
|
||||||
|
}
|
||||||
|
|
||||||
|
// See https://github.com/libsdl-org/SDL/blob/2df2da11f627299c6e05b7e0aff407c915043372/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java#L154-L173
|
||||||
|
static class RangeComparator implements Comparator<InputDevice.MotionRange> {
|
||||||
|
@Override
|
||||||
|
public int compare(InputDevice.MotionRange arg0, InputDevice.MotionRange arg1) {
|
||||||
|
int arg0Axis = arg0.getAxis();
|
||||||
|
int arg1Axis = arg1.getAxis();
|
||||||
|
if (arg0Axis == MotionEvent.AXIS_GAS) {
|
||||||
|
arg0Axis = MotionEvent.AXIS_BRAKE;
|
||||||
|
} else if (arg0Axis == MotionEvent.AXIS_BRAKE) {
|
||||||
|
arg0Axis = MotionEvent.AXIS_GAS;
|
||||||
|
}
|
||||||
|
if (arg1Axis == MotionEvent.AXIS_GAS) {
|
||||||
|
arg1Axis = MotionEvent.AXIS_BRAKE;
|
||||||
|
} else if (arg1Axis == MotionEvent.AXIS_BRAKE) {
|
||||||
|
arg1Axis = MotionEvent.AXIS_GAS;
|
||||||
|
}
|
||||||
|
return arg0Axis - arg1Axis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static double pxToDp(double x) {
|
private static double pxToDp(double x) {
|
||||||
return x / Ebitenmobileview.deviceScale();
|
return x / Ebitenmobileview.deviceScale();
|
||||||
}
|
}
|
||||||
@ -386,6 +417,8 @@ public class EbitenView extends ViewGroup implements InputManager.InputDeviceLis
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void initialize(Context context) {
|
private void initialize(Context context) {
|
||||||
|
this.gamepads = new ArrayList<Gamepad>();
|
||||||
|
|
||||||
this.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(this.ebitenSurfaceView, params);
|
addView(this.ebitenSurfaceView, params);
|
||||||
@ -433,75 +466,14 @@ public class EbitenView extends ViewGroup implements InputManager.InputDeviceLis
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The order must be the same as mobile/ebitenmobileview/input_android.go.
|
private Gamepad getGamepad(int deviceId) {
|
||||||
static int[] gamepadButtons = {
|
for (Gamepad gamepad : this.gamepads) {
|
||||||
KeyEvent.KEYCODE_BUTTON_A,
|
if (gamepad.deviceId == deviceId) {
|
||||||
KeyEvent.KEYCODE_BUTTON_B,
|
return gamepad;
|
||||||
KeyEvent.KEYCODE_BUTTON_C,
|
}
|
||||||
KeyEvent.KEYCODE_BUTTON_X,
|
}
|
||||||
KeyEvent.KEYCODE_BUTTON_Y,
|
return null;
|
||||||
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,
|
|
||||||
};
|
|
||||||
|
|
||||||
// The order must be the same as mobile/ebitenmobileview/input_android.go.
|
|
||||||
static int[] axes = {
|
|
||||||
MotionEvent.AXIS_X,
|
|
||||||
MotionEvent.AXIS_Y,
|
|
||||||
MotionEvent.AXIS_Z,
|
|
||||||
MotionEvent.AXIS_RX,
|
|
||||||
MotionEvent.AXIS_RY,
|
|
||||||
MotionEvent.AXIS_RZ,
|
|
||||||
MotionEvent.AXIS_HAT_X,
|
|
||||||
MotionEvent.AXIS_HAT_Y,
|
|
||||||
MotionEvent.AXIS_LTRIGGER,
|
|
||||||
MotionEvent.AXIS_RTRIGGER,
|
|
||||||
MotionEvent.AXIS_THROTTLE,
|
|
||||||
MotionEvent.AXIS_RUDDER,
|
|
||||||
MotionEvent.AXIS_WHEEL,
|
|
||||||
MotionEvent.AXIS_GAS,
|
|
||||||
MotionEvent.AXIS_BRAKE,
|
|
||||||
MotionEvent.AXIS_GENERIC_1,
|
|
||||||
MotionEvent.AXIS_GENERIC_2,
|
|
||||||
MotionEvent.AXIS_GENERIC_3,
|
|
||||||
MotionEvent.AXIS_GENERIC_4,
|
|
||||||
MotionEvent.AXIS_GENERIC_5,
|
|
||||||
MotionEvent.AXIS_GENERIC_6,
|
|
||||||
MotionEvent.AXIS_GENERIC_7,
|
|
||||||
MotionEvent.AXIS_GENERIC_8,
|
|
||||||
MotionEvent.AXIS_GENERIC_9,
|
|
||||||
MotionEvent.AXIS_GENERIC_10,
|
|
||||||
MotionEvent.AXIS_GENERIC_11,
|
|
||||||
MotionEvent.AXIS_GENERIC_12,
|
|
||||||
MotionEvent.AXIS_GENERIC_13,
|
|
||||||
MotionEvent.AXIS_GENERIC_14,
|
|
||||||
MotionEvent.AXIS_GENERIC_15,
|
|
||||||
MotionEvent.AXIS_GENERIC_16,
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onGenericMotionEvent(MotionEvent event) {
|
public boolean onGenericMotionEvent(MotionEvent event) {
|
||||||
@ -511,17 +483,24 @@ public class EbitenView extends ViewGroup implements InputManager.InputDeviceLis
|
|||||||
if (event.getAction() != MotionEvent.ACTION_MOVE) {
|
if (event.getAction() != MotionEvent.ACTION_MOVE) {
|
||||||
return super.onGenericMotionEvent(event);
|
return super.onGenericMotionEvent(event);
|
||||||
}
|
}
|
||||||
InputDevice inputDevice = this.inputManager.getInputDevice(event.getDeviceId());
|
|
||||||
for (int axis : axes) {
|
// See https://github.com/libsdl-org/SDL/blob/2df2da11f627299c6e05b7e0aff407c915043372/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java#L256-L277
|
||||||
InputDevice.MotionRange motionRange = inputDevice.getMotionRange(axis, event.getSource());
|
Gamepad gamepad = this.getGamepad(event.getDeviceId());
|
||||||
float value = 0.0f;
|
if (gamepad == null) {
|
||||||
if (motionRange != null) {
|
return true;
|
||||||
value = event.getAxisValue(axis);
|
|
||||||
if (Math.abs(value) <= motionRange.getFlat()) {
|
|
||||||
value = 0.0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int actionPointerIndex = event.getActionIndex();
|
||||||
|
for (int i = 0; i < gamepad.axes.size(); i++) {
|
||||||
|
InputDevice.MotionRange range = gamepad.axes.get(i);
|
||||||
|
float axisValue = event.getAxisValue(range.getAxis(), actionPointerIndex);
|
||||||
|
float value = (axisValue - range.getMin()) / range.getRange() * 2.0f - 1.0f;
|
||||||
|
Ebitenmobileview.onGamepadAxisChanged(gamepad.deviceId, i, value);
|
||||||
}
|
}
|
||||||
Ebitenmobileview.onGamepadAxesOrHatsChanged(event.getDeviceId(), axis, value);
|
for (int i = 0; i < gamepad.hats.size() / 2; i++) {
|
||||||
|
int hatX = Math.round(event.getAxisValue(gamepad.hats.get(2*i).getAxis(), actionPointerIndex));
|
||||||
|
int hatY = Math.round(event.getAxisValue(gamepad.hats.get(2*i+1).getAxis(), actionPointerIndex));
|
||||||
|
Ebitenmobileview.onGamepadHatChanged(gamepad.deviceId, i, hatX, hatY);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -545,34 +524,43 @@ public class EbitenView extends ViewGroup implements InputManager.InputDeviceLis
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int naxes = 0;
|
// See https://github.com/libsdl-org/SDL/blob/2df2da11f627299c6e05b7e0aff407c915043372/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java#L182-L216
|
||||||
int nhats2 = 0;
|
List<InputDevice.MotionRange> ranges = inputDevice.getMotionRanges();
|
||||||
for (int i = 0; i < axes.length; i++) {
|
Collections.sort(ranges, new RangeComparator());
|
||||||
InputDevice.MotionRange range = inputDevice.getMotionRange(axes[i], InputDevice.SOURCE_JOYSTICK);
|
|
||||||
if (range == null) {
|
Gamepad gamepad = new Gamepad();
|
||||||
continue;
|
gamepad.deviceId = deviceId;
|
||||||
}
|
gamepad.axes = new ArrayList<InputDevice.MotionRange>();
|
||||||
|
gamepad.hats = new ArrayList<InputDevice.MotionRange>();
|
||||||
|
for (InputDevice.MotionRange range : ranges) {
|
||||||
if (range.getAxis() == MotionEvent.AXIS_HAT_X || range.getAxis() == MotionEvent.AXIS_HAT_Y) {
|
if (range.getAxis() == MotionEvent.AXIS_HAT_X || range.getAxis() == MotionEvent.AXIS_HAT_Y) {
|
||||||
nhats2++;
|
gamepad.hats.add(range);
|
||||||
} else {
|
} else {
|
||||||
naxes++;
|
gamepad.axes.add(range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.gamepads.add(gamepad);
|
||||||
|
|
||||||
String descriptor = inputDevice.getDescriptor();
|
String descriptor = inputDevice.getDescriptor();
|
||||||
int vendorId = inputDevice.getVendorId();
|
int vendorId = inputDevice.getVendorId();
|
||||||
int productId = inputDevice.getProductId();
|
int productId = inputDevice.getProductId();
|
||||||
|
|
||||||
// These values are required to calculate SDL's GUID.
|
// These values are required to calculate SDL's GUID.
|
||||||
int buttonMask = getButtonMask(inputDevice, nhats2/2);
|
int buttonMask = getButtonMask(inputDevice, gamepad.hats.size()/2);
|
||||||
int axisMask = getAxisMask(inputDevice);
|
int axisMask = getAxisMask(inputDevice);
|
||||||
|
|
||||||
Ebitenmobileview.onGamepadAdded(deviceId, inputDevice.getName(), naxes, nhats2/2, descriptor, vendorId, productId, buttonMask, axisMask);
|
Ebitenmobileview.onGamepadAdded(deviceId, inputDevice.getName(), gamepad.axes.size(), gamepad.hats.size()/2, descriptor, vendorId, productId, buttonMask, axisMask);
|
||||||
|
|
||||||
|
// Initialize the trigger axes values explicitly, or the initial button values would be 0.5 instead of 0.
|
||||||
|
if (gamepad.axes.size() >= 6) {
|
||||||
|
Ebitenmobileview.onGamepadAxisChanged(deviceId, 4, -1);
|
||||||
|
Ebitenmobileview.onGamepadAxisChanged(deviceId, 5, -1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The implementation is copied from SDL:
|
// The implementation is copied from SDL:
|
||||||
// https://github.com/libsdl-org/SDL/blob/0e9560aea22818884921e5e5064953257bfe7fa7/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java#L308
|
// https://github.com/libsdl-org/SDL/blob/0e9560aea22818884921e5e5064953257bfe7fa7/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java#L308
|
||||||
private int getButtonMask(InputDevice joystickDevice, int nhats) {
|
private static int getButtonMask(InputDevice joystickDevice, int nhats) {
|
||||||
int buttonMask = 0;
|
int buttonMask = 0;
|
||||||
int[] keys = new int[] {
|
int[] keys = new int[] {
|
||||||
KeyEvent.KEYCODE_BUTTON_A,
|
KeyEvent.KEYCODE_BUTTON_A,
|
||||||
@ -672,7 +660,7 @@ public class EbitenView extends ViewGroup implements InputManager.InputDeviceLis
|
|||||||
return buttonMask;
|
return buttonMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getAxisMask(InputDevice joystickDevice) {
|
private static int getAxisMask(InputDevice joystickDevice) {
|
||||||
final int SDL_CONTROLLER_AXIS_LEFTX = 0;
|
final int SDL_CONTROLLER_AXIS_LEFTX = 0;
|
||||||
final int SDL_CONTROLLER_AXIS_LEFTY = 1;
|
final int SDL_CONTROLLER_AXIS_LEFTY = 1;
|
||||||
final int SDL_CONTROLLER_AXIS_RIGHTX = 2;
|
final int SDL_CONTROLLER_AXIS_RIGHTX = 2;
|
||||||
@ -712,6 +700,7 @@ public class EbitenView extends ViewGroup implements InputManager.InputDeviceLis
|
|||||||
public void onInputDeviceRemoved(int deviceId) {
|
public void onInputDeviceRemoved(int deviceId) {
|
||||||
// Do not call inputManager.getInputDevice(), which returns null (#1185).
|
// Do not call inputManager.getInputDevice(), which returns null (#1185).
|
||||||
Ebitenmobileview.onInputDeviceRemoved(deviceId);
|
Ebitenmobileview.onInputDeviceRemoved(deviceId);
|
||||||
|
this.gamepads.remove(this.getGamepad(deviceId));
|
||||||
}
|
}
|
||||||
|
|
||||||
// suspendGame suspends the game.
|
// suspendGame suspends the game.
|
||||||
@ -748,6 +737,7 @@ public class EbitenView extends ViewGroup implements InputManager.InputDeviceLis
|
|||||||
|
|
||||||
private EbitenSurfaceView ebitenSurfaceView;
|
private EbitenSurfaceView ebitenSurfaceView;
|
||||||
private InputManager inputManager;
|
private InputManager inputManager;
|
||||||
|
private ArrayList<Gamepad> gamepads;
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
File diff suppressed because one or more lines are too long
@ -18,14 +18,7 @@
|
|||||||
package gamepad
|
package gamepad
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"github.com/hajimehoshi/ebiten/v2/internal/gamepaddb"
|
||||||
)
|
|
||||||
|
|
||||||
type AndroidHatDirection int
|
|
||||||
|
|
||||||
const (
|
|
||||||
AndroidHatDirectionX AndroidHatDirection = iota
|
|
||||||
AndroidHatDirectionY
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func AddAndroidGamepad(androidDeviceID int, name, sdlID string, axisCount, hatCount int) {
|
func AddAndroidGamepad(androidDeviceID int, name, sdlID string, axisCount, hatCount int) {
|
||||||
@ -44,8 +37,8 @@ func UpdateAndroidGamepadButton(androidDeviceID int, button Button, pressed bool
|
|||||||
theGamepads.updateAndroidGamepadButton(androidDeviceID, button, pressed)
|
theGamepads.updateAndroidGamepadButton(androidDeviceID, button, pressed)
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateAndroidGamepadHat(androidDeviceID int, hat int, dir AndroidHatDirection, value int) {
|
func UpdateAndroidGamepadHat(androidDeviceID int, hat int, xValue, yValue int) {
|
||||||
theGamepads.updateAndroidGamepadHat(androidDeviceID, hat, dir, value)
|
theGamepads.updateAndroidGamepadHat(androidDeviceID, hat, xValue, yValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *gamepads) addAndroidGamepad(androidDeviceID int, name, sdlID string, axisCount, hatCount int) {
|
func (g *gamepads) addAndroidGamepad(androidDeviceID int, name, sdlID string, axisCount, hatCount int) {
|
||||||
@ -56,7 +49,7 @@ func (g *gamepads) addAndroidGamepad(androidDeviceID int, name, sdlID string, ax
|
|||||||
gp.native = &nativeGamepadImpl{
|
gp.native = &nativeGamepadImpl{
|
||||||
androidDeviceID: androidDeviceID,
|
androidDeviceID: androidDeviceID,
|
||||||
axes: make([]float64, axisCount),
|
axes: make([]float64, axisCount),
|
||||||
buttons: make([]bool, ButtonCount),
|
buttons: make([]bool, gamepaddb.SDLControllerButtonMax+1),
|
||||||
hats: make([]int, hatCount),
|
hats: make([]int, hatCount),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -96,7 +89,7 @@ func (g *gamepads) updateAndroidGamepadButton(androidDeviceID int, button Button
|
|||||||
gp.updateAndroidGamepadButton(button, pressed)
|
gp.updateAndroidGamepadButton(button, pressed)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *gamepads) updateAndroidGamepadHat(androidDeviceID int, hat int, dir AndroidHatDirection, value int) {
|
func (g *gamepads) updateAndroidGamepadHat(androidDeviceID int, hat int, xValue, yValue int) {
|
||||||
g.m.Lock()
|
g.m.Lock()
|
||||||
defer g.m.Unlock()
|
defer g.m.Unlock()
|
||||||
|
|
||||||
@ -106,7 +99,7 @@ func (g *gamepads) updateAndroidGamepadHat(androidDeviceID int, hat int, dir And
|
|||||||
if gp == nil {
|
if gp == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
gp.updateAndroidGamepadHat(hat, dir, value)
|
gp.updateAndroidGamepadHat(hat, xValue, yValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Gamepad) updateAndroidGamepadAxis(axis int, value float64) {
|
func (g *Gamepad) updateAndroidGamepadAxis(axis int, value float64) {
|
||||||
@ -131,7 +124,7 @@ func (g *Gamepad) updateAndroidGamepadButton(button Button, pressed bool) {
|
|||||||
n.buttons[button] = pressed
|
n.buttons[button] = pressed
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Gamepad) updateAndroidGamepadHat(hat int, dir AndroidHatDirection, value int) {
|
func (g *Gamepad) updateAndroidGamepadHat(hat int, xValue, yValue int) {
|
||||||
g.m.Lock()
|
g.m.Lock()
|
||||||
defer g.m.Unlock()
|
defer g.m.Unlock()
|
||||||
|
|
||||||
@ -139,32 +132,43 @@ func (g *Gamepad) updateAndroidGamepadHat(hat int, dir AndroidHatDirection, valu
|
|||||||
if hat < 0 || hat >= len(n.hats) {
|
if hat < 0 || hat >= len(n.hats) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
v := n.hats[hat]
|
var v int
|
||||||
switch dir {
|
|
||||||
case AndroidHatDirectionX:
|
|
||||||
switch {
|
switch {
|
||||||
case value < 0:
|
case xValue < 0:
|
||||||
v |= hatLeft
|
v |= hatLeft
|
||||||
v &^= hatRight
|
case xValue > 0:
|
||||||
case value > 0:
|
|
||||||
v &^= hatLeft
|
|
||||||
v |= hatRight
|
v |= hatRight
|
||||||
default:
|
|
||||||
v &^= (hatLeft | hatRight)
|
|
||||||
}
|
}
|
||||||
case AndroidHatDirectionY:
|
|
||||||
switch {
|
switch {
|
||||||
case value < 0:
|
case yValue < 0:
|
||||||
v |= hatUp
|
v |= hatUp
|
||||||
v &^= hatDown
|
case yValue > 0:
|
||||||
case value > 0:
|
|
||||||
v &^= hatUp
|
|
||||||
v |= hatDown
|
v |= hatDown
|
||||||
default:
|
|
||||||
v &^= (hatUp | hatDown)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
panic(fmt.Sprintf("gamepad: invalid direction: %d", dir))
|
|
||||||
}
|
}
|
||||||
n.hats[hat] = v
|
n.hats[hat] = v
|
||||||
|
|
||||||
|
// Update the gamepad buttons in addition to hats.
|
||||||
|
// See https://github.com/libsdl-org/SDL/blob/47f2373dc13b66c48bf4024fcdab53cd0bdd59bb/src/joystick/android/SDL_sysjoystick.c#L290-L301
|
||||||
|
switch {
|
||||||
|
case xValue < 0:
|
||||||
|
n.buttons[gamepaddb.SDLControllerButtonDpadLeft] = true
|
||||||
|
n.buttons[gamepaddb.SDLControllerButtonDpadRight] = false
|
||||||
|
case xValue > 0:
|
||||||
|
n.buttons[gamepaddb.SDLControllerButtonDpadLeft] = false
|
||||||
|
n.buttons[gamepaddb.SDLControllerButtonDpadRight] = true
|
||||||
|
default:
|
||||||
|
n.buttons[gamepaddb.SDLControllerButtonDpadLeft] = false
|
||||||
|
n.buttons[gamepaddb.SDLControllerButtonDpadRight] = false
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case yValue < 0:
|
||||||
|
n.buttons[gamepaddb.SDLControllerButtonDpadUp] = true
|
||||||
|
n.buttons[gamepaddb.SDLControllerButtonDpadDown] = false
|
||||||
|
case yValue > 0:
|
||||||
|
n.buttons[gamepaddb.SDLControllerButtonDpadUp] = false
|
||||||
|
n.buttons[gamepaddb.SDLControllerButtonDpadDown] = true
|
||||||
|
default:
|
||||||
|
n.buttons[gamepaddb.SDLControllerButtonDpadUp] = false
|
||||||
|
n.buttons[gamepaddb.SDLControllerButtonDpadDown] = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -341,30 +341,26 @@ func toStandardGamepadAxis(str string) (StandardAxis, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func buttonMappings(id string) map[StandardButton]*mapping {
|
func buttonMappings(id string) map[StandardButton]*mapping {
|
||||||
// TODO: Use the database instead of the original mapping (#2308).
|
if m, ok := gamepadButtonMappings[id]; ok {
|
||||||
// The buttons and axes assignments should be fixed.
|
return m
|
||||||
|
}
|
||||||
if currentPlatform == platformAndroid {
|
if currentPlatform == platformAndroid {
|
||||||
if addAndroidDefaultMappings(id) {
|
if addAndroidDefaultMappings(id) {
|
||||||
return gamepadButtonMappings[id]
|
return gamepadButtonMappings[id]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if m, ok := gamepadButtonMappings[id]; ok {
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func axisMappings(id string) map[StandardAxis]*mapping {
|
func axisMappings(id string) map[StandardAxis]*mapping {
|
||||||
// TODO: Use the database instead of the original mapping (#2308).
|
if m, ok := gamepadAxisMappings[id]; ok {
|
||||||
// The buttons and axes assignments should be fixed.
|
return m
|
||||||
|
}
|
||||||
if currentPlatform == platformAndroid {
|
if currentPlatform == platformAndroid {
|
||||||
if addAndroidDefaultMappings(id) {
|
if addAndroidDefaultMappings(id) {
|
||||||
return gamepadAxisMappings[id]
|
return gamepadAxisMappings[id]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if m, ok := gamepadAxisMappings[id]; ok {
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -585,35 +581,6 @@ func Update(mappingData []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func addAndroidDefaultMappings(id string) bool {
|
func addAndroidDefaultMappings(id string) bool {
|
||||||
// See https://github.com/libsdl-org/SDL/blob/120c76c84bbce4c1bfed4e9eb74e10678bd83120/include/SDL_gamecontroller.h#L655-L680
|
|
||||||
const (
|
|
||||||
SDLControllerButtonA = 0
|
|
||||||
SDLControllerButtonB = 1
|
|
||||||
SDLControllerButtonX = 2
|
|
||||||
SDLControllerButtonY = 3
|
|
||||||
SDLControllerButtonBack = 4
|
|
||||||
SDLControllerButtonGuide = 5
|
|
||||||
SDLControllerButtonStart = 6
|
|
||||||
SDLControllerButtonLeftStick = 7
|
|
||||||
SDLControllerButtonRightStick = 8
|
|
||||||
SDLControllerButtonLeftShoulder = 9
|
|
||||||
SDLControllerButtonRightShoulder = 10
|
|
||||||
SDLControllerButtonDpadUp = 11
|
|
||||||
SDLControllerButtonDpadDown = 12
|
|
||||||
SDLControllerButtonDpadLeft = 13
|
|
||||||
SDLControllerButtonDpadRight = 14
|
|
||||||
)
|
|
||||||
|
|
||||||
// See https://github.com/libsdl-org/SDL/blob/120c76c84bbce4c1bfed4e9eb74e10678bd83120/include/SDL_gamecontroller.h#L550-L560
|
|
||||||
const (
|
|
||||||
SDLControllerAxisLeftX = 0
|
|
||||||
SDLControllerAxisLeftY = 1
|
|
||||||
SDLControllerAxisRightX = 2
|
|
||||||
SDLControllerAxisRightY = 3
|
|
||||||
SDLControllerAxisTriggerLeft = 4
|
|
||||||
SDLControllerAxisTriggerRight = 5
|
|
||||||
)
|
|
||||||
|
|
||||||
// See https://github.com/libsdl-org/SDL/blob/120c76c84bbce4c1bfed4e9eb74e10678bd83120/src/joystick/SDL_gamecontroller.c#L468-L568
|
// See https://github.com/libsdl-org/SDL/blob/120c76c84bbce4c1bfed4e9eb74e10678bd83120/src/joystick/SDL_gamecontroller.c#L468-L568
|
||||||
|
|
||||||
const faceButtonMask = ((1 << SDLControllerButtonA) |
|
const faceButtonMask = ((1 << SDLControllerButtonA) |
|
||||||
@ -642,38 +609,38 @@ func addAndroidDefaultMappings(id string) bool {
|
|||||||
if buttonMask&(1<<SDLControllerButtonA) != 0 {
|
if buttonMask&(1<<SDLControllerButtonA) != 0 {
|
||||||
gamepadButtonMappings[id][StandardButtonRightBottom] = &mapping{
|
gamepadButtonMappings[id][StandardButtonRightBottom] = &mapping{
|
||||||
Type: mappingTypeButton,
|
Type: mappingTypeButton,
|
||||||
Index: 0,
|
Index: SDLControllerButtonA,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if buttonMask&(1<<SDLControllerButtonB) != 0 {
|
if buttonMask&(1<<SDLControllerButtonB) != 0 {
|
||||||
gamepadButtonMappings[id][StandardButtonRightRight] = &mapping{
|
gamepadButtonMappings[id][StandardButtonRightRight] = &mapping{
|
||||||
Type: mappingTypeButton,
|
Type: mappingTypeButton,
|
||||||
Index: 1,
|
Index: SDLControllerButtonB,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Use the back button as "B" for easy UI navigation with TV remotes.
|
// Use the back button as "B" for easy UI navigation with TV remotes.
|
||||||
gamepadButtonMappings[id][StandardButtonRightRight] = &mapping{
|
gamepadButtonMappings[id][StandardButtonRightRight] = &mapping{
|
||||||
Type: mappingTypeButton,
|
Type: mappingTypeButton,
|
||||||
Index: 13,
|
Index: SDLControllerButtonBack,
|
||||||
}
|
}
|
||||||
buttonMask &^= uint16(1) << SDLControllerButtonBack
|
buttonMask &^= uint16(1) << SDLControllerButtonBack
|
||||||
}
|
}
|
||||||
if buttonMask&(1<<SDLControllerButtonX) != 0 {
|
if buttonMask&(1<<SDLControllerButtonX) != 0 {
|
||||||
gamepadButtonMappings[id][StandardButtonRightLeft] = &mapping{
|
gamepadButtonMappings[id][StandardButtonRightLeft] = &mapping{
|
||||||
Type: mappingTypeButton,
|
Type: mappingTypeButton,
|
||||||
Index: 3,
|
Index: SDLControllerButtonX,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if buttonMask&(1<<SDLControllerButtonY) != 0 {
|
if buttonMask&(1<<SDLControllerButtonY) != 0 {
|
||||||
gamepadButtonMappings[id][StandardButtonRightTop] = &mapping{
|
gamepadButtonMappings[id][StandardButtonRightTop] = &mapping{
|
||||||
Type: mappingTypeButton,
|
Type: mappingTypeButton,
|
||||||
Index: 4,
|
Index: SDLControllerButtonY,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if buttonMask&(1<<SDLControllerButtonBack) != 0 {
|
if buttonMask&(1<<SDLControllerButtonBack) != 0 {
|
||||||
gamepadButtonMappings[id][StandardButtonCenterLeft] = &mapping{
|
gamepadButtonMappings[id][StandardButtonCenterLeft] = &mapping{
|
||||||
Type: mappingTypeButton,
|
Type: mappingTypeButton,
|
||||||
Index: 13,
|
Index: SDLControllerButtonBack,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if buttonMask&(1<<SDLControllerButtonGuide) != 0 {
|
if buttonMask&(1<<SDLControllerButtonGuide) != 0 {
|
||||||
@ -687,67 +654,63 @@ func addAndroidDefaultMappings(id string) bool {
|
|||||||
if buttonMask&(1<<SDLControllerButtonStart) != 0 {
|
if buttonMask&(1<<SDLControllerButtonStart) != 0 {
|
||||||
gamepadButtonMappings[id][StandardButtonCenterRight] = &mapping{
|
gamepadButtonMappings[id][StandardButtonCenterRight] = &mapping{
|
||||||
Type: mappingTypeButton,
|
Type: mappingTypeButton,
|
||||||
Index: 12,
|
Index: SDLControllerButtonStart,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if buttonMask&(1<<SDLControllerButtonLeftStick) != 0 {
|
if buttonMask&(1<<SDLControllerButtonLeftStick) != 0 {
|
||||||
gamepadButtonMappings[id][StandardButtonLeftStick] = &mapping{
|
gamepadButtonMappings[id][StandardButtonLeftStick] = &mapping{
|
||||||
Type: mappingTypeButton,
|
Type: mappingTypeButton,
|
||||||
Index: 10,
|
Index: SDLControllerButtonLeftStick,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if buttonMask&(1<<SDLControllerButtonRightStick) != 0 {
|
if buttonMask&(1<<SDLControllerButtonRightStick) != 0 {
|
||||||
gamepadButtonMappings[id][StandardButtonRightStick] = &mapping{
|
gamepadButtonMappings[id][StandardButtonRightStick] = &mapping{
|
||||||
Type: mappingTypeButton,
|
Type: mappingTypeButton,
|
||||||
Index: 11,
|
Index: SDLControllerButtonRightStick,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if buttonMask&(1<<SDLControllerButtonLeftShoulder) != 0 {
|
if buttonMask&(1<<SDLControllerButtonLeftShoulder) != 0 {
|
||||||
gamepadButtonMappings[id][StandardButtonFrontTopLeft] = &mapping{
|
gamepadButtonMappings[id][StandardButtonFrontTopLeft] = &mapping{
|
||||||
Type: mappingTypeButton,
|
Type: mappingTypeButton,
|
||||||
Index: 6,
|
Index: SDLControllerButtonLeftShoulder,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if buttonMask&(1<<SDLControllerButtonRightShoulder) != 0 {
|
if buttonMask&(1<<SDLControllerButtonRightShoulder) != 0 {
|
||||||
gamepadButtonMappings[id][StandardButtonFrontTopRight] = &mapping{
|
gamepadButtonMappings[id][StandardButtonFrontTopRight] = &mapping{
|
||||||
Type: mappingTypeButton,
|
Type: mappingTypeButton,
|
||||||
Index: 7,
|
Index: SDLControllerButtonRightShoulder,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if buttonMask&(1<<SDLControllerButtonDpadUp) != 0 {
|
if buttonMask&(1<<SDLControllerButtonDpadUp) != 0 {
|
||||||
gamepadButtonMappings[id][StandardButtonLeftTop] = &mapping{
|
gamepadButtonMappings[id][StandardButtonLeftTop] = &mapping{
|
||||||
Type: mappingTypeHat,
|
Type: mappingTypeButton,
|
||||||
Index: 0,
|
Index: SDLControllerButtonDpadUp,
|
||||||
HatState: HatUp,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if buttonMask&(1<<SDLControllerButtonDpadDown) != 0 {
|
if buttonMask&(1<<SDLControllerButtonDpadDown) != 0 {
|
||||||
gamepadButtonMappings[id][StandardButtonLeftBottom] = &mapping{
|
gamepadButtonMappings[id][StandardButtonLeftBottom] = &mapping{
|
||||||
Type: mappingTypeHat,
|
Type: mappingTypeButton,
|
||||||
Index: 0,
|
Index: SDLControllerButtonDpadDown,
|
||||||
HatState: HatDown,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if buttonMask&(1<<SDLControllerButtonDpadLeft) != 0 {
|
if buttonMask&(1<<SDLControllerButtonDpadLeft) != 0 {
|
||||||
gamepadButtonMappings[id][StandardButtonLeftLeft] = &mapping{
|
gamepadButtonMappings[id][StandardButtonLeftLeft] = &mapping{
|
||||||
Type: mappingTypeHat,
|
Type: mappingTypeButton,
|
||||||
Index: 0,
|
Index: SDLControllerButtonDpadLeft,
|
||||||
HatState: HatLeft,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if buttonMask&(1<<SDLControllerButtonDpadRight) != 0 {
|
if buttonMask&(1<<SDLControllerButtonDpadRight) != 0 {
|
||||||
gamepadButtonMappings[id][StandardButtonLeftRight] = &mapping{
|
gamepadButtonMappings[id][StandardButtonLeftRight] = &mapping{
|
||||||
Type: mappingTypeHat,
|
Type: mappingTypeButton,
|
||||||
Index: 0,
|
Index: SDLControllerButtonDpadRight,
|
||||||
HatState: HatRight,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if axisMask&(1<<SDLControllerAxisLeftX) != 0 {
|
if axisMask&(1<<SDLControllerAxisLeftX) != 0 {
|
||||||
gamepadAxisMappings[id][StandardAxisLeftStickHorizontal] = &mapping{
|
gamepadAxisMappings[id][StandardAxisLeftStickHorizontal] = &mapping{
|
||||||
Type: mappingTypeAxis,
|
Type: mappingTypeAxis,
|
||||||
Index: 0,
|
Index: SDLControllerAxisLeftX,
|
||||||
AxisScale: 1,
|
AxisScale: 1,
|
||||||
AxisOffset: 0,
|
AxisOffset: 0,
|
||||||
}
|
}
|
||||||
@ -755,27 +718,23 @@ func addAndroidDefaultMappings(id string) bool {
|
|||||||
if axisMask&(1<<SDLControllerAxisLeftY) != 0 {
|
if axisMask&(1<<SDLControllerAxisLeftY) != 0 {
|
||||||
gamepadAxisMappings[id][StandardAxisLeftStickVertical] = &mapping{
|
gamepadAxisMappings[id][StandardAxisLeftStickVertical] = &mapping{
|
||||||
Type: mappingTypeAxis,
|
Type: mappingTypeAxis,
|
||||||
Index: 1,
|
Index: SDLControllerAxisLeftY,
|
||||||
AxisScale: 1,
|
AxisScale: 1,
|
||||||
AxisOffset: 0,
|
AxisOffset: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if axisMask&(1<<SDLControllerAxisRightX) != 0 {
|
if axisMask&(1<<SDLControllerAxisRightX) != 0 {
|
||||||
// https://developer.android.com/reference/android/view/MotionEvent#AXIS_Z
|
|
||||||
// > On game pads with two analog joysticks, this axis is often reinterpreted to report the absolute X position of the second joystick instead.
|
|
||||||
gamepadAxisMappings[id][StandardAxisRightStickHorizontal] = &mapping{
|
gamepadAxisMappings[id][StandardAxisRightStickHorizontal] = &mapping{
|
||||||
Type: mappingTypeAxis,
|
Type: mappingTypeAxis,
|
||||||
Index: 2,
|
Index: SDLControllerAxisRightX,
|
||||||
AxisScale: 1,
|
AxisScale: 1,
|
||||||
AxisOffset: 0,
|
AxisOffset: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if axisMask&(1<<SDLControllerAxisRightY) != 0 {
|
if axisMask&(1<<SDLControllerAxisRightY) != 0 {
|
||||||
// https://developer.android.com/reference/android/view/MotionEvent#AXIS_RZ
|
|
||||||
// > On game pads with two analog joysticks, this axis is often reinterpreted to report the absolute Y position of the second joystick instead.
|
|
||||||
gamepadAxisMappings[id][StandardAxisRightStickVertical] = &mapping{
|
gamepadAxisMappings[id][StandardAxisRightStickVertical] = &mapping{
|
||||||
Type: mappingTypeAxis,
|
Type: mappingTypeAxis,
|
||||||
Index: 5,
|
Index: SDLControllerAxisRightY,
|
||||||
AxisScale: 1,
|
AxisScale: 1,
|
||||||
AxisOffset: 0,
|
AxisOffset: 0,
|
||||||
}
|
}
|
||||||
@ -783,17 +742,17 @@ func addAndroidDefaultMappings(id string) bool {
|
|||||||
if axisMask&(1<<SDLControllerAxisTriggerLeft) != 0 {
|
if axisMask&(1<<SDLControllerAxisTriggerLeft) != 0 {
|
||||||
gamepadButtonMappings[id][StandardButtonFrontBottomLeft] = &mapping{
|
gamepadButtonMappings[id][StandardButtonFrontBottomLeft] = &mapping{
|
||||||
Type: mappingTypeAxis,
|
Type: mappingTypeAxis,
|
||||||
Index: 6,
|
Index: SDLControllerAxisTriggerLeft,
|
||||||
AxisScale: 2,
|
AxisScale: 1,
|
||||||
AxisOffset: -1,
|
AxisOffset: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if axisMask&(1<<SDLControllerAxisTriggerRight) != 0 {
|
if axisMask&(1<<SDLControllerAxisTriggerRight) != 0 {
|
||||||
gamepadButtonMappings[id][StandardButtonFrontBottomRight] = &mapping{
|
gamepadButtonMappings[id][StandardButtonFrontBottomRight] = &mapping{
|
||||||
Type: mappingTypeAxis,
|
Type: mappingTypeAxis,
|
||||||
Index: 7,
|
Index: SDLControllerAxisTriggerRight,
|
||||||
AxisScale: 2,
|
AxisScale: 1,
|
||||||
AxisOffset: -1,
|
AxisOffset: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
51
internal/gamepaddb/sdl.go
Normal file
51
internal/gamepaddb/sdl.go
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
// Copyright 2022 The Ebitengine 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.
|
||||||
|
|
||||||
|
package gamepaddb
|
||||||
|
|
||||||
|
// See https://github.com/libsdl-org/SDL/blob/120c76c84bbce4c1bfed4e9eb74e10678bd83120/include/SDL_gamecontroller.h#L655-L680
|
||||||
|
const (
|
||||||
|
SDLControllerButtonA = 0
|
||||||
|
SDLControllerButtonB = 1
|
||||||
|
SDLControllerButtonX = 2
|
||||||
|
SDLControllerButtonY = 3
|
||||||
|
SDLControllerButtonBack = 4
|
||||||
|
SDLControllerButtonGuide = 5
|
||||||
|
SDLControllerButtonStart = 6
|
||||||
|
SDLControllerButtonLeftStick = 7
|
||||||
|
SDLControllerButtonRightStick = 8
|
||||||
|
SDLControllerButtonLeftShoulder = 9
|
||||||
|
SDLControllerButtonRightShoulder = 10
|
||||||
|
SDLControllerButtonDpadUp = 11
|
||||||
|
SDLControllerButtonDpadDown = 12
|
||||||
|
SDLControllerButtonDpadLeft = 13
|
||||||
|
SDLControllerButtonDpadRight = 14
|
||||||
|
SDLControllerButtonMisc1 = 15
|
||||||
|
SDLControllerButtonPaddle1 = 16
|
||||||
|
SDLControllerButtonPaddle2 = 17
|
||||||
|
SDLControllerButtonPaddle3 = 18
|
||||||
|
SDLControllerButtonPaddle4 = 19
|
||||||
|
SDLControllerButtonTouchpad = 20
|
||||||
|
SDLControllerButtonMax = SDLControllerButtonTouchpad // This is different from the original SDL_CONTROLLER_BUTTON_MAX.
|
||||||
|
)
|
||||||
|
|
||||||
|
// See https://github.com/libsdl-org/SDL/blob/120c76c84bbce4c1bfed4e9eb74e10678bd83120/include/SDL_gamecontroller.h#L550-L560
|
||||||
|
const (
|
||||||
|
SDLControllerAxisLeftX = 0
|
||||||
|
SDLControllerAxisLeftY = 1
|
||||||
|
SDLControllerAxisRightX = 2
|
||||||
|
SDLControllerAxisRightY = 3
|
||||||
|
SDLControllerAxisTriggerLeft = 4
|
||||||
|
SDLControllerAxisTriggerRight = 5
|
||||||
|
)
|
@ -17,10 +17,10 @@ package ebitenmobileview
|
|||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"hash/crc32"
|
"hash/crc32"
|
||||||
"math"
|
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/gamepad"
|
"github.com/hajimehoshi/ebiten/v2/internal/gamepad"
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/internal/gamepaddb"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/ui"
|
"github.com/hajimehoshi/ebiten/v2/internal/ui"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -62,6 +62,10 @@ const (
|
|||||||
keycodeDpadDown = 0x00000014
|
keycodeDpadDown = 0x00000014
|
||||||
keycodeDpadLeft = 0x00000015
|
keycodeDpadLeft = 0x00000015
|
||||||
keycodeDpadRight = 0x00000016
|
keycodeDpadRight = 0x00000016
|
||||||
|
keycodeDpadCenter = 0x00000017
|
||||||
|
|
||||||
|
keycodeBack = 0x00000004
|
||||||
|
keycodeMenu = 0x00000052
|
||||||
)
|
)
|
||||||
|
|
||||||
// https://developer.android.com/reference/android/view/InputDevice
|
// https://developer.android.com/reference/android/view/InputDevice
|
||||||
@ -71,113 +75,48 @@ const (
|
|||||||
sourceJoystick = 0x01000010
|
sourceJoystick = 0x01000010
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: Can we map these values to the standard gamepad buttons?
|
// 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 androidKeyToGamepadButton = map[int]gamepad.Button{
|
var androidKeyToSDL = map[int]int{
|
||||||
keycodeButtonA: gamepad.Button0,
|
keycodeButtonA: gamepaddb.SDLControllerButtonA,
|
||||||
keycodeButtonB: gamepad.Button1,
|
keycodeButtonB: gamepaddb.SDLControllerButtonB,
|
||||||
keycodeButtonC: gamepad.Button2,
|
keycodeButtonX: gamepaddb.SDLControllerButtonX,
|
||||||
keycodeButtonX: gamepad.Button3,
|
keycodeButtonY: gamepaddb.SDLControllerButtonY,
|
||||||
keycodeButtonY: gamepad.Button4,
|
keycodeButtonL1: gamepaddb.SDLControllerButtonLeftShoulder,
|
||||||
keycodeButtonZ: gamepad.Button5,
|
keycodeButtonR1: gamepaddb.SDLControllerButtonRightShoulder,
|
||||||
keycodeButtonL1: gamepad.Button6,
|
keycodeButtonThumbl: gamepaddb.SDLControllerButtonLeftStick,
|
||||||
keycodeButtonR1: gamepad.Button7,
|
keycodeButtonThumbr: gamepaddb.SDLControllerButtonRightStick,
|
||||||
keycodeButtonL2: gamepad.Button8,
|
keycodeMenu: gamepaddb.SDLControllerButtonStart,
|
||||||
keycodeButtonR2: gamepad.Button9,
|
keycodeButtonStart: gamepaddb.SDLControllerButtonStart,
|
||||||
keycodeButtonThumbl: gamepad.Button10,
|
keycodeBack: gamepaddb.SDLControllerButtonBack,
|
||||||
keycodeButtonThumbr: gamepad.Button11,
|
keycodeButtonSelect: gamepaddb.SDLControllerButtonBack,
|
||||||
keycodeButtonStart: gamepad.Button12,
|
keycodeButtonMode: gamepaddb.SDLControllerButtonGuide,
|
||||||
keycodeButtonSelect: gamepad.Button13,
|
keycodeButtonL2: 15,
|
||||||
keycodeButtonMode: gamepad.Button14,
|
keycodeButtonR2: 16,
|
||||||
keycodeButton1: gamepad.Button15,
|
keycodeButtonC: 17,
|
||||||
keycodeButton2: gamepad.Button16,
|
keycodeButtonZ: 18,
|
||||||
keycodeButton3: gamepad.Button17,
|
keycodeDpadUp: gamepaddb.SDLControllerButtonDpadUp,
|
||||||
keycodeButton4: gamepad.Button18,
|
keycodeDpadDown: gamepaddb.SDLControllerButtonDpadDown,
|
||||||
keycodeButton5: gamepad.Button19,
|
keycodeDpadLeft: gamepaddb.SDLControllerButtonDpadLeft,
|
||||||
keycodeButton6: gamepad.Button20,
|
keycodeDpadRight: gamepaddb.SDLControllerButtonDpadRight,
|
||||||
keycodeButton7: gamepad.Button21,
|
keycodeDpadCenter: gamepaddb.SDLControllerButtonA,
|
||||||
keycodeButton8: gamepad.Button22,
|
keycodeButton1: 20,
|
||||||
keycodeButton9: gamepad.Button23,
|
keycodeButton2: 21,
|
||||||
keycodeButton10: gamepad.Button24,
|
keycodeButton3: 22,
|
||||||
keycodeButton11: gamepad.Button25,
|
keycodeButton4: 23,
|
||||||
keycodeButton12: gamepad.Button26,
|
keycodeButton5: 24,
|
||||||
keycodeButton13: gamepad.Button27,
|
keycodeButton6: 25,
|
||||||
keycodeButton14: gamepad.Button28,
|
keycodeButton7: 26,
|
||||||
keycodeButton15: gamepad.Button29,
|
keycodeButton8: 27,
|
||||||
keycodeButton16: gamepad.Button30,
|
keycodeButton9: 28,
|
||||||
}
|
keycodeButton10: 29,
|
||||||
|
keycodeButton11: 30,
|
||||||
// Axis constant definitions for joysticks only.
|
keycodeButton12: 31,
|
||||||
// https://developer.android.com/reference/android/view/MotionEvent
|
keycodeButton13: 32,
|
||||||
const (
|
keycodeButton14: 33,
|
||||||
axisX = 0x00000000
|
keycodeButton15: 34,
|
||||||
axisY = 0x00000001
|
keycodeButton16: 35,
|
||||||
axisZ = 0x0000000b
|
|
||||||
axisRx = 0x0000000c
|
|
||||||
axisRy = 0x0000000d
|
|
||||||
axisRz = 0x0000000e
|
|
||||||
axisHatX = 0x0000000f
|
|
||||||
axisHatY = 0x00000010
|
|
||||||
axisLtrigger = 0x00000011
|
|
||||||
axisRtrigger = 0x00000012
|
|
||||||
axisThrottle = 0x00000013
|
|
||||||
axisRudder = 0x00000014
|
|
||||||
axisWheel = 0x00000015
|
|
||||||
axisGas = 0x00000016
|
|
||||||
axisBrake = 0x00000017
|
|
||||||
axisGeneric1 = 0x00000020
|
|
||||||
axisGeneric2 = 0x00000021
|
|
||||||
axisGeneric3 = 0x00000022
|
|
||||||
axisGeneric4 = 0x00000023
|
|
||||||
axisGeneric5 = 0x00000024
|
|
||||||
axisGeneric6 = 0x00000025
|
|
||||||
axisGeneric7 = 0x00000026
|
|
||||||
axisGeneric8 = 0x00000027
|
|
||||||
axisGeneric9 = 0x00000028
|
|
||||||
axisGeneric10 = 0x00000029
|
|
||||||
axisGeneric11 = 0x0000002a
|
|
||||||
axisGeneric12 = 0x0000002b
|
|
||||||
axisGeneric13 = 0x0000002c
|
|
||||||
axisGeneric14 = 0x0000002d
|
|
||||||
axisGeneric15 = 0x0000002e
|
|
||||||
axisGeneric16 = 0x0000002f
|
|
||||||
)
|
|
||||||
|
|
||||||
var androidAxisIDToAxisID = map[int]int{
|
|
||||||
axisX: 0,
|
|
||||||
axisY: 1,
|
|
||||||
axisZ: 2,
|
|
||||||
axisRx: 3,
|
|
||||||
axisRy: 4,
|
|
||||||
axisRz: 5,
|
|
||||||
axisLtrigger: 6,
|
|
||||||
axisRtrigger: 7,
|
|
||||||
axisThrottle: 8,
|
|
||||||
axisRudder: 9,
|
|
||||||
axisWheel: 10,
|
|
||||||
axisGas: 11,
|
|
||||||
axisBrake: 12,
|
|
||||||
axisGeneric1: 13,
|
|
||||||
axisGeneric2: 14,
|
|
||||||
axisGeneric3: 15,
|
|
||||||
axisGeneric4: 16,
|
|
||||||
axisGeneric5: 17,
|
|
||||||
axisGeneric6: 18,
|
|
||||||
axisGeneric7: 19,
|
|
||||||
axisGeneric8: 20,
|
|
||||||
axisGeneric9: 21,
|
|
||||||
axisGeneric10: 22,
|
|
||||||
axisGeneric11: 23,
|
|
||||||
axisGeneric12: 24,
|
|
||||||
axisGeneric13: 25,
|
|
||||||
axisGeneric14: 26,
|
|
||||||
axisGeneric15: 27,
|
|
||||||
axisGeneric16: 28,
|
|
||||||
}
|
|
||||||
|
|
||||||
var androidAxisIDToHatID2 = map[int]int{
|
|
||||||
axisHatX: 0,
|
|
||||||
axisHatY: 1,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateTouchesOnAndroid(action int, id int, x, y int) {
|
func UpdateTouchesOnAndroid(action int, id int, x, y int) {
|
||||||
@ -195,8 +134,8 @@ func OnKeyDownOnAndroid(keyCode int, unicodeChar int, source int, deviceID int)
|
|||||||
switch {
|
switch {
|
||||||
case source&sourceGamepad == sourceGamepad:
|
case source&sourceGamepad == sourceGamepad:
|
||||||
// A gamepad can be detected as a keyboard. Detect the device as a gamepad first.
|
// A gamepad can be detected as a keyboard. Detect the device as a gamepad first.
|
||||||
if button, ok := androidKeyToGamepadButton[keyCode]; ok {
|
if button, ok := androidKeyToSDL[keyCode]; ok {
|
||||||
gamepad.UpdateAndroidGamepadButton(deviceID, button, true)
|
gamepad.UpdateAndroidGamepadButton(deviceID, gamepad.Button(button), true)
|
||||||
}
|
}
|
||||||
case source&sourceJoystick == sourceJoystick:
|
case source&sourceJoystick == sourceJoystick:
|
||||||
// DPAD keys can come here, but they are also treated as an axis at a motion event. Ignore them.
|
// DPAD keys can come here, but they are also treated as an axis at a motion event. Ignore them.
|
||||||
@ -215,8 +154,8 @@ func OnKeyUpOnAndroid(keyCode int, source int, deviceID int) {
|
|||||||
switch {
|
switch {
|
||||||
case source&sourceGamepad == sourceGamepad:
|
case source&sourceGamepad == sourceGamepad:
|
||||||
// A gamepad can be detected as a keyboard. Detect the device as a gamepad first.
|
// A gamepad can be detected as a keyboard. Detect the device as a gamepad first.
|
||||||
if button, ok := androidKeyToGamepadButton[keyCode]; ok {
|
if button, ok := androidKeyToSDL[keyCode]; ok {
|
||||||
gamepad.UpdateAndroidGamepadButton(deviceID, button, false)
|
gamepad.UpdateAndroidGamepadButton(deviceID, gamepad.Button(button), false)
|
||||||
}
|
}
|
||||||
case source&sourceJoystick == sourceJoystick:
|
case source&sourceJoystick == sourceJoystick:
|
||||||
// DPAD keys can come here, but they are also treated as an axis at a motion event. Ignore them.
|
// DPAD keys can come here, but they are also treated as an axis at a motion event. Ignore them.
|
||||||
@ -228,30 +167,12 @@ func OnKeyUpOnAndroid(keyCode int, source int, deviceID int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func OnGamepadAxesOrHatsChanged(deviceID int, axisID int, value float32) {
|
func OnGamepadAxisChanged(deviceID int, axisID int, value float32) {
|
||||||
if axis, ok := androidAxisIDToAxisID[axisID]; ok {
|
gamepad.UpdateAndroidGamepadAxis(deviceID, axisID, float64(value))
|
||||||
gamepad.UpdateAndroidGamepadAxis(deviceID, axis, float64(value))
|
}
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if hid2, ok := androidAxisIDToHatID2[axisID]; ok {
|
func OnGamepadHatChanged(deviceID int, hatID int, xValue, yValue int) {
|
||||||
const (
|
gamepad.UpdateAndroidGamepadHat(deviceID, hatID, xValue, yValue)
|
||||||
hatUp = 1
|
|
||||||
hatRight = 2
|
|
||||||
hatDown = 4
|
|
||||||
hatLeft = 8
|
|
||||||
)
|
|
||||||
hatID := hid2 / 2
|
|
||||||
var dir gamepad.AndroidHatDirection
|
|
||||||
switch hid2 % 2 {
|
|
||||||
case 0:
|
|
||||||
dir = gamepad.AndroidHatDirectionX
|
|
||||||
case 1:
|
|
||||||
dir = gamepad.AndroidHatDirectionY
|
|
||||||
}
|
|
||||||
gamepad.UpdateAndroidGamepadHat(deviceID, hatID, dir, int(math.Round(float64(value))))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func OnGamepadAdded(deviceID int, name string, axisCount int, hatCount int, descriptor string, vendorID int, productID int, buttonMask int, axisMask int) {
|
func OnGamepadAdded(deviceID int, name string, axisCount int, hatCount int, descriptor string, vendorID int, productID int, buttonMask int, axisMask int) {
|
||||||
|
Loading…
Reference in New Issue
Block a user