internal/gamepad: stop embedding a member into a struct

This is a preparation to switch the gamepad implementation for Xbox.

Updates #2084
This commit is contained in:
Hajime Hoshi 2022-06-24 18:28:02 +09:00
parent a4d782da5b
commit 0cd43bd081
8 changed files with 109 additions and 109 deletions

View File

@ -407,14 +407,14 @@ func (g *gamepads) addIOSGamepad(controller C.uintptr_t, prop *C.struct_Controll
name := C.GoString(&prop.name[0])
sdlID := C.GoStringN(&prop.guid[0], 16)
gp := g.add(name, sdlID)
gp.controller = uintptr(controller)
gp.axes = make([]float64, prop.nAxes)
gp.buttons = make([]bool, prop.nButtons+prop.nHats*4)
gp.hats = make([]int, prop.nHats)
gp.buttonMask = uint16(prop.buttonMask)
gp.hasDualshockTouchpad = bool(prop.hasDualshockTouchpad)
gp.hasXboxPaddles = bool(prop.hasXboxPaddles)
gp.hasXboxShareButton = bool(prop.hasXboxShareButton)
gp.native.controller = uintptr(controller)
gp.native.axes = make([]float64, prop.nAxes)
gp.native.buttons = make([]bool, prop.nButtons+prop.nHats*4)
gp.native.hats = make([]int, prop.nHats)
gp.native.buttonMask = uint16(prop.buttonMask)
gp.native.hasDualshockTouchpad = bool(prop.hasDualshockTouchpad)
gp.native.hasXboxPaddles = bool(prop.hasXboxPaddles)
gp.native.hasXboxShareButton = bool(prop.hasXboxShareButton)
}
func (g *gamepads) removeIOSGamepad(controller C.uintptr_t) {
@ -422,7 +422,7 @@ func (g *gamepads) removeIOSGamepad(controller C.uintptr_t) {
defer g.m.Unlock()
g.remove(func(gamepad *Gamepad) bool {
return gamepad.controller == uintptr(controller)
return gamepad.native.controller == uintptr(controller)
})
}

View File

@ -53,10 +53,10 @@ func (g *gamepads) addAndroidGamepad(androidDeviceID int, name, sdlID string, ax
defer g.m.Unlock()
gp := g.add(name, sdlID)
gp.androidDeviceID = androidDeviceID
gp.axes = make([]float64, axisCount)
gp.buttons = make([]bool, buttonCount)
gp.hats = make([]int, hatCount)
gp.native.androidDeviceID = androidDeviceID
gp.native.axes = make([]float64, axisCount)
gp.native.buttons = make([]bool, buttonCount)
gp.native.hats = make([]int, hatCount)
}
func (g *gamepads) removeAndroidGamepad(androidDeviceID int) {
@ -64,7 +64,7 @@ func (g *gamepads) removeAndroidGamepad(androidDeviceID int) {
defer g.m.Unlock()
g.remove(func(gamepad *Gamepad) bool {
return gamepad.androidDeviceID == androidDeviceID
return gamepad.native.androidDeviceID == androidDeviceID
})
}
@ -73,7 +73,7 @@ func (g *gamepads) updateAndroidGamepadAxis(androidDeviceID int, axis int, value
defer g.m.Unlock()
gp := g.find(func(gamepad *Gamepad) bool {
return gamepad.androidDeviceID == androidDeviceID
return gamepad.native.androidDeviceID == androidDeviceID
})
if gp == nil {
return
@ -86,7 +86,7 @@ func (g *gamepads) updateAndroidGamepadButton(androidDeviceID int, button Button
defer g.m.Unlock()
gp := g.find(func(gamepad *Gamepad) bool {
return gamepad.androidDeviceID == androidDeviceID
return gamepad.native.androidDeviceID == androidDeviceID
})
if gp == nil {
return
@ -99,7 +99,7 @@ func (g *gamepads) updateAndroidGamepadHat(androidDeviceID int, hat int, dir And
defer g.m.Unlock()
gp := g.find(func(gamepad *Gamepad) bool {
return gamepad.androidDeviceID == androidDeviceID
return gamepad.native.androidDeviceID == androidDeviceID
})
if gp == nil {
return
@ -111,30 +111,30 @@ func (g *Gamepad) updateAndroidGamepadAxis(axis int, value float64) {
g.m.Lock()
defer g.m.Unlock()
if axis < 0 || axis >= len(g.axes) {
if axis < 0 || axis >= len(g.native.axes) {
return
}
g.axes[axis] = value
g.native.axes[axis] = value
}
func (g *Gamepad) updateAndroidGamepadButton(button Button, pressed bool) {
g.m.Lock()
defer g.m.Unlock()
if button < 0 || int(button) >= len(g.buttons) {
if button < 0 || int(button) >= len(g.native.buttons) {
return
}
g.buttons[button] = pressed
g.native.buttons[button] = pressed
}
func (g *Gamepad) updateAndroidGamepadHat(hat int, dir AndroidHatDirection, value int) {
g.m.Lock()
defer g.m.Unlock()
if hat < 0 || hat >= len(g.hats) {
if hat < 0 || hat >= len(g.native.hats) {
return
}
v := g.hats[hat]
v := g.native.hats[hat]
switch dir {
case AndroidHatDirectionX:
switch {
@ -161,5 +161,5 @@ func (g *Gamepad) updateAndroidGamepadHat(hat int, dir AndroidHatDirection, valu
default:
panic(fmt.Sprintf("gamepad: invalid direction: %d", dir))
}
g.hats[hat] = v
g.native.hats[hat] = v
}

View File

@ -40,7 +40,7 @@ type gamepads struct {
gamepads []*Gamepad
m sync.Mutex
nativeGamepads
native nativeGamepads
}
var theGamepads gamepads
@ -81,13 +81,13 @@ func (g *gamepads) update() error {
defer g.m.Unlock()
if !g.inited {
if err := g.nativeGamepads.init(g); err != nil {
if err := g.native.init(g); err != nil {
return err
}
g.inited = true
}
if err := g.nativeGamepads.update(g); err != nil {
if err := g.native.update(g); err != nil {
return err
}
@ -166,7 +166,7 @@ func (g *gamepads) setNativeWindow(nativeWindow uintptr) {
g.m.Lock()
defer g.m.Unlock()
var n interface{} = &g.nativeGamepads
var n interface{} = &g.native
if n, ok := n.(interface{ setNativeWindow(uintptr) }); ok {
n.setNativeWindow(nativeWindow)
}
@ -177,14 +177,14 @@ type Gamepad struct {
sdlID string
m sync.Mutex
nativeGamepad
native nativeGamepad
}
func (g *Gamepad) update(gamepads *gamepads) error {
g.m.Lock()
defer g.m.Unlock()
return g.nativeGamepad.update(gamepads)
return g.native.update(gamepads)
}
// Name is concurrent-safe.
@ -207,7 +207,7 @@ func (g *Gamepad) AxisCount() int {
g.m.Lock()
defer g.m.Unlock()
return g.nativeGamepad.axisCount()
return g.native.axisCount()
}
// ButtonCount is concurrent-safe.
@ -215,7 +215,7 @@ func (g *Gamepad) ButtonCount() int {
g.m.Lock()
defer g.m.Unlock()
return g.nativeGamepad.buttonCount()
return g.native.buttonCount()
}
// HatCount is concurrent-safe.
@ -223,7 +223,7 @@ func (g *Gamepad) HatCount() int {
g.m.Lock()
defer g.m.Unlock()
return g.nativeGamepad.hatCount()
return g.native.hatCount()
}
// Axis is concurrent-safe.
@ -231,7 +231,7 @@ func (g *Gamepad) Axis(axis int) float64 {
g.m.Lock()
defer g.m.Unlock()
return g.nativeGamepad.axisValue(axis)
return g.native.axisValue(axis)
}
// Button is concurrent-safe.
@ -239,7 +239,7 @@ func (g *Gamepad) Button(button int) bool {
g.m.Lock()
defer g.m.Unlock()
return g.nativeGamepad.isButtonPressed(button)
return g.native.isButtonPressed(button)
}
// Hat is concurrent-safe.
@ -247,7 +247,7 @@ func (g *Gamepad) Hat(hat int) int {
g.m.Lock()
defer g.m.Unlock()
return g.nativeGamepad.hatState(hat)
return g.native.hatState(hat)
}
// IsStandardLayoutAvailable is concurrent-safe.
@ -258,7 +258,7 @@ func (g *Gamepad) IsStandardLayoutAvailable() bool {
if gamepaddb.HasStandardLayoutMapping(g.sdlID) {
return true
}
return g.hasOwnStandardLayoutMapping()
return g.native.hasOwnStandardLayoutMapping()
}
// StandardAxisValue is concurrent-safe.
@ -266,8 +266,8 @@ func (g *Gamepad) StandardAxisValue(axis gamepaddb.StandardAxis) float64 {
if gamepaddb.HasStandardLayoutMapping(g.sdlID) {
return gamepaddb.AxisValue(g.sdlID, axis, g)
}
if g.hasOwnStandardLayoutMapping() {
return g.nativeGamepad.axisValue(int(axis))
if g.native.hasOwnStandardLayoutMapping() {
return g.native.axisValue(int(axis))
}
return 0
}
@ -277,8 +277,8 @@ func (g *Gamepad) StandardButtonValue(button gamepaddb.StandardButton) float64 {
if gamepaddb.HasStandardLayoutMapping(g.sdlID) {
return gamepaddb.ButtonValue(g.sdlID, button, g)
}
if g.hasOwnStandardLayoutMapping() {
return g.nativeGamepad.buttonValue(int(button))
if g.native.hasOwnStandardLayoutMapping() {
return g.native.buttonValue(int(button))
}
return 0
}
@ -288,8 +288,8 @@ func (g *Gamepad) IsStandardButtonPressed(button gamepaddb.StandardButton) bool
if gamepaddb.HasStandardLayoutMapping(g.sdlID) {
return gamepaddb.IsButtonPressed(g.sdlID, button, g)
}
if g.hasOwnStandardLayoutMapping() {
return g.nativeGamepad.isButtonPressed(int(button))
if g.native.hasOwnStandardLayoutMapping() {
return g.native.isButtonPressed(int(button))
}
return false
}
@ -299,5 +299,5 @@ func (g *Gamepad) Vibrate(duration time.Duration, strongMagnitude float64, weakM
g.m.Lock()
defer g.m.Unlock()
g.nativeGamepad.vibrate(duration, strongMagnitude, weakMagnitude)
g.native.vibrate(duration, strongMagnitude, weakMagnitude)
}

View File

@ -47,27 +47,27 @@ func (g *nativeGamepads) update(gamepads *gamepads) error {
g.ids[gp.ID] = struct{}{}
gamepad := gamepads.find(func(gamepad *Gamepad) bool {
return gamepad.id == gp.ID
return gamepad.native.id == gp.ID
})
if gamepad == nil {
gamepad = gamepads.add("", "")
gamepad.id = gp.ID
gamepad.standard = gp.Standard
gamepad.axisValues = make([]float64, gp.AxisCount)
gamepad.buttonPressed = make([]bool, gp.ButtonCount)
gamepad.buttonValues = make([]float64, gp.ButtonCount)
gamepad.native.id = gp.ID
gamepad.native.standard = gp.Standard
gamepad.native.axisValues = make([]float64, gp.AxisCount)
gamepad.native.buttonPressed = make([]bool, gp.ButtonCount)
gamepad.native.buttonValues = make([]float64, gp.ButtonCount)
}
gamepad.m.Lock()
copy(gamepad.axisValues, gp.AxisValues[:])
copy(gamepad.buttonValues, gp.ButtonValues[:])
copy(gamepad.buttonPressed, gp.ButtonPressed[:])
copy(gamepad.native.axisValues, gp.AxisValues[:])
copy(gamepad.native.buttonValues, gp.ButtonValues[:])
copy(gamepad.native.buttonPressed, gp.ButtonPressed[:])
gamepad.m.Unlock()
}
// Remove an unused gamepads.
gamepads.remove(func(gamepad *Gamepad) bool {
_, ok := g.ids[gamepad.id]
_, ok := g.ids[gamepad.native.id]
return !ok
})

View File

@ -135,28 +135,28 @@ func (g *nativeGamepads) init(gamepads *gamepads) error {
//export ebitenGamepadMatchingCallback
func ebitenGamepadMatchingCallback(ctx unsafe.Pointer, res C.IOReturn, sender unsafe.Pointer, device C.IOHIDDeviceRef) {
theGamepads.devicesM.Lock()
defer theGamepads.devicesM.Unlock()
theGamepads.devicesToAdd = append(theGamepads.devicesToAdd, device)
theGamepads.native.devicesM.Lock()
defer theGamepads.native.devicesM.Unlock()
theGamepads.native.devicesToAdd = append(theGamepads.native.devicesToAdd, device)
}
//export ebitenGamepadRemovalCallback
func ebitenGamepadRemovalCallback(ctx unsafe.Pointer, res C.IOReturn, sender unsafe.Pointer, device C.IOHIDDeviceRef) {
theGamepads.devicesM.Lock()
defer theGamepads.devicesM.Unlock()
theGamepads.devicesToRemove = append(theGamepads.devicesToRemove, device)
theGamepads.native.devicesM.Lock()
defer theGamepads.native.devicesM.Unlock()
theGamepads.native.devicesToRemove = append(theGamepads.native.devicesToRemove, device)
}
func (g *nativeGamepads) update(gamepads *gamepads) error {
theGamepads.devicesM.Lock()
defer theGamepads.devicesM.Unlock()
theGamepads.native.devicesM.Lock()
defer theGamepads.native.devicesM.Unlock()
for _, device := range g.devicesToAdd {
g.addDevice(device, gamepads)
}
for _, device := range g.devicesToRemove {
gamepads.remove(func(g *Gamepad) bool {
return g.device == device
return g.native.device == device
})
}
g.devicesToAdd = g.devicesToAdd[:0]
@ -166,7 +166,7 @@ func (g *nativeGamepads) update(gamepads *gamepads) error {
func (g *nativeGamepads) addDevice(device C.IOHIDDeviceRef, gamepads *gamepads) {
if gamepads.find(func(g *Gamepad) bool {
return g.device == device
return g.native.device == device
}) != nil {
return
}
@ -212,7 +212,7 @@ func (g *nativeGamepads) addDevice(device C.IOHIDDeviceRef, gamepads *gamepads)
defer C.CFRelease(C.CFTypeRef(elements))
gp := gamepads.add(name, sdlID)
gp.device = device
gp.native.device = device
for i := C.CFIndex(0); i < C.CFArrayGetCount(elements); i++ {
native := (C.IOHIDElementRef)(C.CFArrayGetValueAtIndex(elements, i))
@ -236,27 +236,27 @@ func (g *nativeGamepads) addDevice(device C.IOHIDDeviceRef, gamepads *gamepads)
case C.kHIDUsage_GD_X, C.kHIDUsage_GD_Y, C.kHIDUsage_GD_Z,
C.kHIDUsage_GD_Rx, C.kHIDUsage_GD_Ry, C.kHIDUsage_GD_Rz,
C.kHIDUsage_GD_Slider, C.kHIDUsage_GD_Dial, C.kHIDUsage_GD_Wheel:
gp.axes = append(gp.axes, element{
gp.native.axes = append(gp.native.axes, element{
native: native,
usage: int(usage),
index: len(gp.axes),
index: len(gp.native.axes),
minimum: int(C.IOHIDElementGetLogicalMin(native)),
maximum: int(C.IOHIDElementGetLogicalMax(native)),
})
case C.kHIDUsage_GD_Hatswitch:
gp.hats = append(gp.hats, element{
gp.native.hats = append(gp.native.hats, element{
native: native,
usage: int(usage),
index: len(gp.hats),
index: len(gp.native.hats),
minimum: int(C.IOHIDElementGetLogicalMin(native)),
maximum: int(C.IOHIDElementGetLogicalMax(native)),
})
case C.kHIDUsage_GD_DPadUp, C.kHIDUsage_GD_DPadRight, C.kHIDUsage_GD_DPadDown, C.kHIDUsage_GD_DPadLeft,
C.kHIDUsage_GD_SystemMainMenu, C.kHIDUsage_GD_Select, C.kHIDUsage_GD_Start:
gp.buttons = append(gp.buttons, element{
gp.native.buttons = append(gp.native.buttons, element{
native: native,
usage: int(usage),
index: len(gp.buttons),
index: len(gp.native.buttons),
minimum: int(C.IOHIDElementGetLogicalMin(native)),
maximum: int(C.IOHIDElementGetLogicalMax(native)),
})
@ -264,28 +264,28 @@ func (g *nativeGamepads) addDevice(device C.IOHIDDeviceRef, gamepads *gamepads)
case C.kHIDPage_Simulation:
switch usage {
case C.kHIDUsage_Sim_Accelerator, C.kHIDUsage_Sim_Brake, C.kHIDUsage_Sim_Throttle, C.kHIDUsage_Sim_Rudder, C.kHIDUsage_Sim_Steering:
gp.axes = append(gp.axes, element{
gp.native.axes = append(gp.native.axes, element{
native: native,
usage: int(usage),
index: len(gp.axes),
index: len(gp.native.axes),
minimum: int(C.IOHIDElementGetLogicalMin(native)),
maximum: int(C.IOHIDElementGetLogicalMax(native)),
})
}
case C.kHIDPage_Button, C.kHIDPage_Consumer:
gp.buttons = append(gp.buttons, element{
gp.native.buttons = append(gp.native.buttons, element{
native: native,
usage: int(usage),
index: len(gp.buttons),
index: len(gp.native.buttons),
minimum: int(C.IOHIDElementGetLogicalMin(native)),
maximum: int(C.IOHIDElementGetLogicalMax(native)),
})
}
}
sort.Stable(gp.axes)
sort.Stable(gp.buttons)
sort.Stable(gp.hats)
sort.Stable(gp.native.axes)
sort.Stable(gp.native.buttons)
sort.Stable(gp.native.hats)
}
type element struct {

View File

@ -73,7 +73,7 @@ func (g *nativeGamepads) update(gamepads *gamepads) error {
// The gamepad is not registered yet, register this.
gamepad := gamepads.find(func(gamepad *Gamepad) bool {
return index == gamepad.index
return index == gamepad.native.index
})
if gamepad == nil {
name := gp.Get("id").String()
@ -84,15 +84,15 @@ func (g *nativeGamepads) update(gamepads *gamepads) error {
copy(sdlID[:], []byte(name))
gamepad = gamepads.add(name, hex.EncodeToString(sdlID[:]))
gamepad.index = index
gamepad.mapping = gp.Get("mapping").String()
gamepad.native.index = index
gamepad.native.mapping = gp.Get("mapping").String()
}
gamepad.value = gp
gamepad.native.value = gp
}
// Remove an unused gamepads.
gamepads.remove(func(gamepad *Gamepad) bool {
_, ok := g.indices[gamepad.index]
_, ok := g.indices[gamepad.native.index]
return !ok
})

View File

@ -92,7 +92,7 @@ func (g *nativeGamepads) init(gamepads *gamepads) error {
func (*nativeGamepads) openGamepad(gamepads *gamepads, path string) (err error) {
if gamepads.find(func(gamepad *Gamepad) bool {
return gamepad.path == path
return gamepad.native.path == path
}) != nil {
return nil
}
@ -165,10 +165,10 @@ func (*nativeGamepads) openGamepad(gamepads *gamepads, path string) (err error)
}
gp := gamepads.add(name, sdlID)
gp.path = path
gp.fd = fd
gp.native.path = path
gp.native.fd = fd
runtime.SetFinalizer(gp, func(gp *Gamepad) {
gp.close()
gp.native.close()
})
var axisCount int
@ -178,33 +178,33 @@ func (*nativeGamepads) openGamepad(gamepads *gamepads, path string) (err error)
if !isBitSet(keyBits, code) {
continue
}
gp.keyMap[code-_BTN_MISC] = buttonCount
gp.native.keyMap[code-_BTN_MISC] = buttonCount
buttonCount++
}
for code := 0; code < _ABS_CNT; code++ {
gp.absMap[code] = -1
gp.native.absMap[code] = -1
if !isBitSet(absBits, code) {
continue
}
if code >= _ABS_HAT0X && code <= _ABS_HAT3Y {
gp.absMap[code] = hatCount
gp.native.absMap[code] = hatCount
hatCount++
// Skip Y.
code++
continue
}
if err := ioctl(gp.fd, uint(_EVIOCGABS(uint(code))), unsafe.Pointer(&gp.absInfo[code])); err != nil {
if err := ioctl(gp.native.fd, uint(_EVIOCGABS(uint(code))), unsafe.Pointer(&gp.native.absInfo[code])); err != nil {
return fmt.Errorf("gamepad: ioctl for an abs at openGamepad failed: %w", err)
}
gp.absMap[code] = axisCount
gp.native.absMap[code] = axisCount
axisCount++
}
gp.axisCount_ = axisCount
gp.buttonCount_ = buttonCount
gp.hatCount_ = hatCount
gp.native.axisCount_ = axisCount
gp.native.buttonCount_ = buttonCount
gp.native.hatCount_ = hatCount
if err := gp.pollAbsState(); err != nil {
if err := gp.native.pollAbsState(); err != nil {
return err
}
@ -248,9 +248,9 @@ func (g *nativeGamepads) update(gamepads *gamepads) error {
}
if e.Mask&unix.IN_DELETE != 0 {
if gp := gamepads.find(func(gamepad *Gamepad) bool {
return gamepad.path == path
return gamepad.native.path == path
}); gp != nil {
gp.close()
gp.native.close()
gamepads.remove(func(gamepad *Gamepad) bool {
return gamepad == gp
})

View File

@ -241,7 +241,7 @@ func (g *nativeGamepads) detectConnection(gamepads *gamepads) error {
for i := 0; i < xuserMaxCount; i++ {
if gamepads.find(func(g *Gamepad) bool {
return g.dinputDevice == nil && g.xinputIndex == i
return g.native.dinputDevice == nil && g.native.xinputIndex == i
}) != nil {
continue
}
@ -278,7 +278,7 @@ func (g *nativeGamepads) detectConnection(gamepads *gamepads) error {
}
gp := gamepads.add(name, sdlID)
gp.xinputIndex = i
gp.native.xinputIndex = i
}
}
return nil
@ -292,7 +292,7 @@ func (g *nativeGamepads) dinput8EnumDevicesCallback(lpddi *_DIDEVICEINSTANCEW, p
}
if gamepads.find(func(g *Gamepad) bool {
return g.dinputGUID == lpddi.guidInstance
return g.native.dinputGUID == lpddi.guidInstance
}) != nil {
return _DIENUM_CONTINUE
}
@ -389,12 +389,12 @@ func (g *nativeGamepads) dinput8EnumDevicesCallback(lpddi *_DIDEVICEINSTANCEW, p
}
gp := gamepads.add(name, sdlID)
gp.dinputDevice = device
gp.dinputObjects = ctx.objects
gp.dinputGUID = lpddi.guidInstance
gp.dinputAxes = make([]float64, ctx.axisCount+ctx.sliderCount)
gp.dinputButtons = make([]bool, ctx.buttonCount)
gp.dinputHats = make([]int, ctx.povCount)
gp.native.dinputDevice = device
gp.native.dinputObjects = ctx.objects
gp.native.dinputGUID = lpddi.guidInstance
gp.native.dinputAxes = make([]float64, ctx.axisCount+ctx.sliderCount)
gp.native.dinputButtons = make([]bool, ctx.buttonCount)
gp.native.dinputHats = make([]int, ctx.povCount)
return _DIENUM_CONTINUE
}
@ -576,7 +576,7 @@ func (g *nativeGamepad) update(gamepads *gamepads) (err error) {
return
}
gamepads.remove(func(gamepad *Gamepad) bool {
return &gamepad.nativeGamepad == g
return &gamepad.native == g
})
}()
@ -666,7 +666,7 @@ func (g *nativeGamepad) update(gamepads *gamepads) (err error) {
}
var state _XINPUT_STATE
if err := gamepads.xinputGetState(uint32(g.xinputIndex), &state); err != nil {
if err := gamepads.native.xinputGetState(uint32(g.xinputIndex), &state); err != nil {
if !errors.Is(err, windows.ERROR_DEVICE_NOT_CONNECTED) {
return err
}