mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +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}};
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.input.InputManager;
|
||||
import android.os.Handler;
|
||||
@ -371,6 +376,32 @@ import android.view.WindowManager;
|
||||
import {{.JavaPkg}}.ebitenmobileview.Ebitenmobileview;
|
||||
|
||||
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) {
|
||||
return x / Ebitenmobileview.deviceScale();
|
||||
}
|
||||
@ -386,6 +417,8 @@ public class EbitenView extends ViewGroup implements InputManager.InputDeviceLis
|
||||
}
|
||||
|
||||
private void initialize(Context context) {
|
||||
this.gamepads = new ArrayList<Gamepad>();
|
||||
|
||||
this.ebitenSurfaceView = new EbitenSurfaceView(getContext());
|
||||
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
|
||||
addView(this.ebitenSurfaceView, params);
|
||||
@ -433,75 +466,14 @@ public class EbitenView extends ViewGroup implements InputManager.InputDeviceLis
|
||||
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,
|
||||
};
|
||||
|
||||
// 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,
|
||||
};
|
||||
private Gamepad getGamepad(int deviceId) {
|
||||
for (Gamepad gamepad : this.gamepads) {
|
||||
if (gamepad.deviceId == deviceId) {
|
||||
return gamepad;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onGenericMotionEvent(MotionEvent event) {
|
||||
@ -511,17 +483,24 @@ public class EbitenView extends ViewGroup implements InputManager.InputDeviceLis
|
||||
if (event.getAction() != MotionEvent.ACTION_MOVE) {
|
||||
return super.onGenericMotionEvent(event);
|
||||
}
|
||||
InputDevice inputDevice = this.inputManager.getInputDevice(event.getDeviceId());
|
||||
for (int axis : axes) {
|
||||
InputDevice.MotionRange motionRange = inputDevice.getMotionRange(axis, event.getSource());
|
||||
float value = 0.0f;
|
||||
if (motionRange != null) {
|
||||
value = event.getAxisValue(axis);
|
||||
if (Math.abs(value) <= motionRange.getFlat()) {
|
||||
value = 0.0f;
|
||||
}
|
||||
}
|
||||
Ebitenmobileview.onGamepadAxesOrHatsChanged(event.getDeviceId(), axis, value);
|
||||
|
||||
// See https://github.com/libsdl-org/SDL/blob/2df2da11f627299c6e05b7e0aff407c915043372/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java#L256-L277
|
||||
Gamepad gamepad = this.getGamepad(event.getDeviceId());
|
||||
if (gamepad == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
@ -545,34 +524,43 @@ public class EbitenView extends ViewGroup implements InputManager.InputDeviceLis
|
||||
return;
|
||||
}
|
||||
|
||||
int naxes = 0;
|
||||
int nhats2 = 0;
|
||||
for (int i = 0; i < axes.length; i++) {
|
||||
InputDevice.MotionRange range = inputDevice.getMotionRange(axes[i], InputDevice.SOURCE_JOYSTICK);
|
||||
if (range == null) {
|
||||
continue;
|
||||
}
|
||||
// See https://github.com/libsdl-org/SDL/blob/2df2da11f627299c6e05b7e0aff407c915043372/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java#L182-L216
|
||||
List<InputDevice.MotionRange> ranges = inputDevice.getMotionRanges();
|
||||
Collections.sort(ranges, new RangeComparator());
|
||||
|
||||
Gamepad gamepad = new Gamepad();
|
||||
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) {
|
||||
nhats2++;
|
||||
gamepad.hats.add(range);
|
||||
} else {
|
||||
naxes++;
|
||||
gamepad.axes.add(range);
|
||||
}
|
||||
}
|
||||
this.gamepads.add(gamepad);
|
||||
|
||||
String descriptor = inputDevice.getDescriptor();
|
||||
int vendorId = inputDevice.getVendorId();
|
||||
int productId = inputDevice.getProductId();
|
||||
|
||||
// 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);
|
||||
|
||||
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:
|
||||
// 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[] keys = new int[] {
|
||||
KeyEvent.KEYCODE_BUTTON_A,
|
||||
@ -672,7 +660,7 @@ public class EbitenView extends ViewGroup implements InputManager.InputDeviceLis
|
||||
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_LEFTY = 1;
|
||||
final int SDL_CONTROLLER_AXIS_RIGHTX = 2;
|
||||
@ -712,6 +700,7 @@ public class EbitenView extends ViewGroup implements InputManager.InputDeviceLis
|
||||
public void onInputDeviceRemoved(int deviceId) {
|
||||
// Do not call inputManager.getInputDevice(), which returns null (#1185).
|
||||
Ebitenmobileview.onInputDeviceRemoved(deviceId);
|
||||
this.gamepads.remove(this.getGamepad(deviceId));
|
||||
}
|
||||
|
||||
// suspendGame suspends the game.
|
||||
@ -748,6 +737,7 @@ public class EbitenView extends ViewGroup implements InputManager.InputDeviceLis
|
||||
|
||||
private EbitenSurfaceView ebitenSurfaceView;
|
||||
private InputManager inputManager;
|
||||
private ArrayList<Gamepad> gamepads;
|
||||
}
|
||||
`
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
@ -18,14 +18,7 @@
|
||||
package gamepad
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type AndroidHatDirection int
|
||||
|
||||
const (
|
||||
AndroidHatDirectionX AndroidHatDirection = iota
|
||||
AndroidHatDirectionY
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/gamepaddb"
|
||||
)
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
func UpdateAndroidGamepadHat(androidDeviceID int, hat int, dir AndroidHatDirection, value int) {
|
||||
theGamepads.updateAndroidGamepadHat(androidDeviceID, hat, dir, value)
|
||||
func UpdateAndroidGamepadHat(androidDeviceID int, hat int, xValue, yValue int) {
|
||||
theGamepads.updateAndroidGamepadHat(androidDeviceID, hat, xValue, yValue)
|
||||
}
|
||||
|
||||
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{
|
||||
androidDeviceID: androidDeviceID,
|
||||
axes: make([]float64, axisCount),
|
||||
buttons: make([]bool, ButtonCount),
|
||||
buttons: make([]bool, gamepaddb.SDLControllerButtonMax+1),
|
||||
hats: make([]int, hatCount),
|
||||
}
|
||||
}
|
||||
@ -96,7 +89,7 @@ func (g *gamepads) updateAndroidGamepadButton(androidDeviceID int, button Button
|
||||
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()
|
||||
defer g.m.Unlock()
|
||||
|
||||
@ -106,7 +99,7 @@ func (g *gamepads) updateAndroidGamepadHat(androidDeviceID int, hat int, dir And
|
||||
if gp == nil {
|
||||
return
|
||||
}
|
||||
gp.updateAndroidGamepadHat(hat, dir, value)
|
||||
gp.updateAndroidGamepadHat(hat, xValue, yValue)
|
||||
}
|
||||
|
||||
func (g *Gamepad) updateAndroidGamepadAxis(axis int, value float64) {
|
||||
@ -131,7 +124,7 @@ func (g *Gamepad) updateAndroidGamepadButton(button Button, pressed bool) {
|
||||
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()
|
||||
defer g.m.Unlock()
|
||||
|
||||
@ -139,32 +132,43 @@ func (g *Gamepad) updateAndroidGamepadHat(hat int, dir AndroidHatDirection, valu
|
||||
if hat < 0 || hat >= len(n.hats) {
|
||||
return
|
||||
}
|
||||
v := n.hats[hat]
|
||||
switch dir {
|
||||
case AndroidHatDirectionX:
|
||||
switch {
|
||||
case value < 0:
|
||||
v |= hatLeft
|
||||
v &^= hatRight
|
||||
case value > 0:
|
||||
v &^= hatLeft
|
||||
v |= hatRight
|
||||
default:
|
||||
v &^= (hatLeft | hatRight)
|
||||
}
|
||||
case AndroidHatDirectionY:
|
||||
switch {
|
||||
case value < 0:
|
||||
v |= hatUp
|
||||
v &^= hatDown
|
||||
case value > 0:
|
||||
v &^= hatUp
|
||||
v |= hatDown
|
||||
default:
|
||||
v &^= (hatUp | hatDown)
|
||||
}
|
||||
default:
|
||||
panic(fmt.Sprintf("gamepad: invalid direction: %d", dir))
|
||||
var v int
|
||||
switch {
|
||||
case xValue < 0:
|
||||
v |= hatLeft
|
||||
case xValue > 0:
|
||||
v |= hatRight
|
||||
}
|
||||
switch {
|
||||
case yValue < 0:
|
||||
v |= hatUp
|
||||
case yValue > 0:
|
||||
v |= hatDown
|
||||
}
|
||||
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 {
|
||||
// TODO: Use the database instead of the original mapping (#2308).
|
||||
// The buttons and axes assignments should be fixed.
|
||||
if m, ok := gamepadButtonMappings[id]; ok {
|
||||
return m
|
||||
}
|
||||
if currentPlatform == platformAndroid {
|
||||
if addAndroidDefaultMappings(id) {
|
||||
return gamepadButtonMappings[id]
|
||||
}
|
||||
}
|
||||
if m, ok := gamepadButtonMappings[id]; ok {
|
||||
return m
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func axisMappings(id string) map[StandardAxis]*mapping {
|
||||
// TODO: Use the database instead of the original mapping (#2308).
|
||||
// The buttons and axes assignments should be fixed.
|
||||
if m, ok := gamepadAxisMappings[id]; ok {
|
||||
return m
|
||||
}
|
||||
if currentPlatform == platformAndroid {
|
||||
if addAndroidDefaultMappings(id) {
|
||||
return gamepadAxisMappings[id]
|
||||
}
|
||||
}
|
||||
if m, ok := gamepadAxisMappings[id]; ok {
|
||||
return m
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -585,35 +581,6 @@ func Update(mappingData []byte) error {
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
const faceButtonMask = ((1 << SDLControllerButtonA) |
|
||||
@ -642,38 +609,38 @@ func addAndroidDefaultMappings(id string) bool {
|
||||
if buttonMask&(1<<SDLControllerButtonA) != 0 {
|
||||
gamepadButtonMappings[id][StandardButtonRightBottom] = &mapping{
|
||||
Type: mappingTypeButton,
|
||||
Index: 0,
|
||||
Index: SDLControllerButtonA,
|
||||
}
|
||||
}
|
||||
if buttonMask&(1<<SDLControllerButtonB) != 0 {
|
||||
gamepadButtonMappings[id][StandardButtonRightRight] = &mapping{
|
||||
Type: mappingTypeButton,
|
||||
Index: 1,
|
||||
Index: SDLControllerButtonB,
|
||||
}
|
||||
} else {
|
||||
// Use the back button as "B" for easy UI navigation with TV remotes.
|
||||
gamepadButtonMappings[id][StandardButtonRightRight] = &mapping{
|
||||
Type: mappingTypeButton,
|
||||
Index: 13,
|
||||
Index: SDLControllerButtonBack,
|
||||
}
|
||||
buttonMask &^= uint16(1) << SDLControllerButtonBack
|
||||
}
|
||||
if buttonMask&(1<<SDLControllerButtonX) != 0 {
|
||||
gamepadButtonMappings[id][StandardButtonRightLeft] = &mapping{
|
||||
Type: mappingTypeButton,
|
||||
Index: 3,
|
||||
Index: SDLControllerButtonX,
|
||||
}
|
||||
}
|
||||
if buttonMask&(1<<SDLControllerButtonY) != 0 {
|
||||
gamepadButtonMappings[id][StandardButtonRightTop] = &mapping{
|
||||
Type: mappingTypeButton,
|
||||
Index: 4,
|
||||
Index: SDLControllerButtonY,
|
||||
}
|
||||
}
|
||||
if buttonMask&(1<<SDLControllerButtonBack) != 0 {
|
||||
gamepadButtonMappings[id][StandardButtonCenterLeft] = &mapping{
|
||||
Type: mappingTypeButton,
|
||||
Index: 13,
|
||||
Index: SDLControllerButtonBack,
|
||||
}
|
||||
}
|
||||
if buttonMask&(1<<SDLControllerButtonGuide) != 0 {
|
||||
@ -687,67 +654,63 @@ func addAndroidDefaultMappings(id string) bool {
|
||||
if buttonMask&(1<<SDLControllerButtonStart) != 0 {
|
||||
gamepadButtonMappings[id][StandardButtonCenterRight] = &mapping{
|
||||
Type: mappingTypeButton,
|
||||
Index: 12,
|
||||
Index: SDLControllerButtonStart,
|
||||
}
|
||||
}
|
||||
if buttonMask&(1<<SDLControllerButtonLeftStick) != 0 {
|
||||
gamepadButtonMappings[id][StandardButtonLeftStick] = &mapping{
|
||||
Type: mappingTypeButton,
|
||||
Index: 10,
|
||||
Index: SDLControllerButtonLeftStick,
|
||||
}
|
||||
}
|
||||
if buttonMask&(1<<SDLControllerButtonRightStick) != 0 {
|
||||
gamepadButtonMappings[id][StandardButtonRightStick] = &mapping{
|
||||
Type: mappingTypeButton,
|
||||
Index: 11,
|
||||
Index: SDLControllerButtonRightStick,
|
||||
}
|
||||
}
|
||||
if buttonMask&(1<<SDLControllerButtonLeftShoulder) != 0 {
|
||||
gamepadButtonMappings[id][StandardButtonFrontTopLeft] = &mapping{
|
||||
Type: mappingTypeButton,
|
||||
Index: 6,
|
||||
Index: SDLControllerButtonLeftShoulder,
|
||||
}
|
||||
}
|
||||
if buttonMask&(1<<SDLControllerButtonRightShoulder) != 0 {
|
||||
gamepadButtonMappings[id][StandardButtonFrontTopRight] = &mapping{
|
||||
Type: mappingTypeButton,
|
||||
Index: 7,
|
||||
Index: SDLControllerButtonRightShoulder,
|
||||
}
|
||||
}
|
||||
|
||||
if buttonMask&(1<<SDLControllerButtonDpadUp) != 0 {
|
||||
gamepadButtonMappings[id][StandardButtonLeftTop] = &mapping{
|
||||
Type: mappingTypeHat,
|
||||
Index: 0,
|
||||
HatState: HatUp,
|
||||
Type: mappingTypeButton,
|
||||
Index: SDLControllerButtonDpadUp,
|
||||
}
|
||||
}
|
||||
if buttonMask&(1<<SDLControllerButtonDpadDown) != 0 {
|
||||
gamepadButtonMappings[id][StandardButtonLeftBottom] = &mapping{
|
||||
Type: mappingTypeHat,
|
||||
Index: 0,
|
||||
HatState: HatDown,
|
||||
Type: mappingTypeButton,
|
||||
Index: SDLControllerButtonDpadDown,
|
||||
}
|
||||
}
|
||||
if buttonMask&(1<<SDLControllerButtonDpadLeft) != 0 {
|
||||
gamepadButtonMappings[id][StandardButtonLeftLeft] = &mapping{
|
||||
Type: mappingTypeHat,
|
||||
Index: 0,
|
||||
HatState: HatLeft,
|
||||
Type: mappingTypeButton,
|
||||
Index: SDLControllerButtonDpadLeft,
|
||||
}
|
||||
}
|
||||
if buttonMask&(1<<SDLControllerButtonDpadRight) != 0 {
|
||||
gamepadButtonMappings[id][StandardButtonLeftRight] = &mapping{
|
||||
Type: mappingTypeHat,
|
||||
Index: 0,
|
||||
HatState: HatRight,
|
||||
Type: mappingTypeButton,
|
||||
Index: SDLControllerButtonDpadRight,
|
||||
}
|
||||
}
|
||||
|
||||
if axisMask&(1<<SDLControllerAxisLeftX) != 0 {
|
||||
gamepadAxisMappings[id][StandardAxisLeftStickHorizontal] = &mapping{
|
||||
Type: mappingTypeAxis,
|
||||
Index: 0,
|
||||
Index: SDLControllerAxisLeftX,
|
||||
AxisScale: 1,
|
||||
AxisOffset: 0,
|
||||
}
|
||||
@ -755,27 +718,23 @@ func addAndroidDefaultMappings(id string) bool {
|
||||
if axisMask&(1<<SDLControllerAxisLeftY) != 0 {
|
||||
gamepadAxisMappings[id][StandardAxisLeftStickVertical] = &mapping{
|
||||
Type: mappingTypeAxis,
|
||||
Index: 1,
|
||||
Index: SDLControllerAxisLeftY,
|
||||
AxisScale: 1,
|
||||
AxisOffset: 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{
|
||||
Type: mappingTypeAxis,
|
||||
Index: 2,
|
||||
Index: SDLControllerAxisRightX,
|
||||
AxisScale: 1,
|
||||
AxisOffset: 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{
|
||||
Type: mappingTypeAxis,
|
||||
Index: 5,
|
||||
Index: SDLControllerAxisRightY,
|
||||
AxisScale: 1,
|
||||
AxisOffset: 0,
|
||||
}
|
||||
@ -783,17 +742,17 @@ func addAndroidDefaultMappings(id string) bool {
|
||||
if axisMask&(1<<SDLControllerAxisTriggerLeft) != 0 {
|
||||
gamepadButtonMappings[id][StandardButtonFrontBottomLeft] = &mapping{
|
||||
Type: mappingTypeAxis,
|
||||
Index: 6,
|
||||
AxisScale: 2,
|
||||
AxisOffset: -1,
|
||||
Index: SDLControllerAxisTriggerLeft,
|
||||
AxisScale: 1,
|
||||
AxisOffset: 0,
|
||||
}
|
||||
}
|
||||
if axisMask&(1<<SDLControllerAxisTriggerRight) != 0 {
|
||||
gamepadButtonMappings[id][StandardButtonFrontBottomRight] = &mapping{
|
||||
Type: mappingTypeAxis,
|
||||
Index: 7,
|
||||
AxisScale: 2,
|
||||
AxisOffset: -1,
|
||||
Index: SDLControllerAxisTriggerRight,
|
||||
AxisScale: 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 (
|
||||
"encoding/hex"
|
||||
"hash/crc32"
|
||||
"math"
|
||||
"unicode"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/gamepad"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/gamepaddb"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/ui"
|
||||
)
|
||||
|
||||
@ -58,10 +58,14 @@ const (
|
||||
keycodeButton15 = 0x000000ca
|
||||
keycodeButton16 = 0x000000cb
|
||||
|
||||
keycodeDpadUp = 0x00000013
|
||||
keycodeDpadDown = 0x00000014
|
||||
keycodeDpadLeft = 0x00000015
|
||||
keycodeDpadRight = 0x00000016
|
||||
keycodeDpadUp = 0x00000013
|
||||
keycodeDpadDown = 0x00000014
|
||||
keycodeDpadLeft = 0x00000015
|
||||
keycodeDpadRight = 0x00000016
|
||||
keycodeDpadCenter = 0x00000017
|
||||
|
||||
keycodeBack = 0x00000004
|
||||
keycodeMenu = 0x00000052
|
||||
)
|
||||
|
||||
// https://developer.android.com/reference/android/view/InputDevice
|
||||
@ -71,113 +75,48 @@ const (
|
||||
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{
|
||||
keycodeButtonA: gamepad.Button0,
|
||||
keycodeButtonB: gamepad.Button1,
|
||||
keycodeButtonC: gamepad.Button2,
|
||||
keycodeButtonX: gamepad.Button3,
|
||||
keycodeButtonY: gamepad.Button4,
|
||||
keycodeButtonZ: gamepad.Button5,
|
||||
keycodeButtonL1: gamepad.Button6,
|
||||
keycodeButtonR1: gamepad.Button7,
|
||||
keycodeButtonL2: gamepad.Button8,
|
||||
keycodeButtonR2: gamepad.Button9,
|
||||
keycodeButtonThumbl: gamepad.Button10,
|
||||
keycodeButtonThumbr: gamepad.Button11,
|
||||
keycodeButtonStart: gamepad.Button12,
|
||||
keycodeButtonSelect: gamepad.Button13,
|
||||
keycodeButtonMode: gamepad.Button14,
|
||||
keycodeButton1: gamepad.Button15,
|
||||
keycodeButton2: gamepad.Button16,
|
||||
keycodeButton3: gamepad.Button17,
|
||||
keycodeButton4: gamepad.Button18,
|
||||
keycodeButton5: gamepad.Button19,
|
||||
keycodeButton6: gamepad.Button20,
|
||||
keycodeButton7: gamepad.Button21,
|
||||
keycodeButton8: gamepad.Button22,
|
||||
keycodeButton9: gamepad.Button23,
|
||||
keycodeButton10: gamepad.Button24,
|
||||
keycodeButton11: gamepad.Button25,
|
||||
keycodeButton12: gamepad.Button26,
|
||||
keycodeButton13: gamepad.Button27,
|
||||
keycodeButton14: gamepad.Button28,
|
||||
keycodeButton15: gamepad.Button29,
|
||||
keycodeButton16: gamepad.Button30,
|
||||
}
|
||||
|
||||
// Axis constant definitions for joysticks only.
|
||||
// https://developer.android.com/reference/android/view/MotionEvent
|
||||
const (
|
||||
axisX = 0x00000000
|
||||
axisY = 0x00000001
|
||||
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,
|
||||
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) {
|
||||
@ -195,8 +134,8 @@ 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 := androidKeyToGamepadButton[keyCode]; ok {
|
||||
gamepad.UpdateAndroidGamepadButton(deviceID, button, true)
|
||||
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.
|
||||
@ -215,8 +154,8 @@ 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 := androidKeyToGamepadButton[keyCode]; ok {
|
||||
gamepad.UpdateAndroidGamepadButton(deviceID, button, false)
|
||||
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.
|
||||
@ -228,30 +167,12 @@ func OnKeyUpOnAndroid(keyCode int, source int, deviceID int) {
|
||||
}
|
||||
}
|
||||
|
||||
func OnGamepadAxesOrHatsChanged(deviceID int, axisID int, value float32) {
|
||||
if axis, ok := androidAxisIDToAxisID[axisID]; ok {
|
||||
gamepad.UpdateAndroidGamepadAxis(deviceID, axis, float64(value))
|
||||
return
|
||||
}
|
||||
func OnGamepadAxisChanged(deviceID int, axisID int, value float32) {
|
||||
gamepad.UpdateAndroidGamepadAxis(deviceID, axisID, float64(value))
|
||||
}
|
||||
|
||||
if hid2, ok := androidAxisIDToHatID2[axisID]; ok {
|
||||
const (
|
||||
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 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) {
|
||||
|
Loading…
Reference in New Issue
Block a user