ebiten: add IsStandardGamepadAxisAvailable and IsStandardGamepadButtonAvailable (#2241)

Closes #2040
This commit is contained in:
Hajime Hoshi 2022-08-11 12:35:20 +09:00 committed by GitHub
parent 8f792fef45
commit 094726915b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 194 additions and 2 deletions

View File

@ -154,13 +154,17 @@ func standardMap(id ebiten.GamepadID) string {
for b, str := range standardButtonToString {
placeholder := "[" + str + strings.Repeat(" ", 4-len(str)) + "]"
v := ebiten.StandardGamepadButtonValue(id, b)
if ebiten.IsStandardGamepadButtonPressed(id, b) {
switch {
case !ebiten.IsStandardGamepadButtonAvailable(id, b):
m = strings.Replace(m, placeholder, " -- ", 1)
case ebiten.IsStandardGamepadButtonPressed(id, b):
m = strings.Replace(m, placeholder, fmt.Sprintf("[%0.2f]", v), 1)
} else {
default:
m = strings.Replace(m, placeholder, fmt.Sprintf(" %0.2f ", v), 1)
}
}
// TODO: Use ebiten.IsStandardGamepadAxisAvailable
m += fmt.Sprintf(" Left Stick: X: %+0.2f, Y: %+0.2f\n Right Stick: X: %+0.2f, Y: %+0.2f",
ebiten.StandardGamepadAxisValue(id, ebiten.StandardGamepadAxisLeftStickHorizontal),
ebiten.StandardGamepadAxisValue(id, ebiten.StandardGamepadAxisLeftStickVertical),

View File

@ -303,6 +303,28 @@ func IsStandardGamepadLayoutAvailable(id GamepadID) bool {
return g.IsStandardLayoutAvailable()
}
// IsStandardGamepadAxisAvailable reports whether the standard gamepad axis is available on the gamepad (id).
//
// IsStandardGamepadAxisAvailable is concurrent-safe.
func IsStandardGamepadAxisAvailable(id GamepadID, axis StandardGamepadAxis) bool {
g := gamepad.Get(id)
if g == nil {
return false
}
return g.IsStandardAxisAvailable(axis)
}
// IsStandardGamepadButtonAvailable reports whether the standard gamepad button is available on the gamepad (id).
//
// IsStandardGamepadButtonAvailable is concurrent-safe.
func IsStandardGamepadButtonAvailable(id GamepadID, button StandardGamepadButton) bool {
g := gamepad.Get(id)
if g == nil {
return false
}
return g.IsStandardButtonAvailable(button)
}
// UpdateStandardGamepadLayoutMappings parses the specified string mappings in SDL_GameControllerDB format and
// updates the gamepad layout definitions.
//

View File

@ -190,6 +190,8 @@ type Gamepad struct {
type nativeGamepad interface {
update(gamepads *gamepads) error
hasOwnStandardLayoutMapping() bool
isStandardAxisAvailableInOwnMapping(axis gamepaddb.StandardAxis) bool
isStandardButtonAvailableInOwnMapping(button gamepaddb.StandardButton) bool
axisCount() int
buttonCount() int
hatCount() int
@ -281,6 +283,28 @@ func (g *Gamepad) IsStandardLayoutAvailable() bool {
return g.native.hasOwnStandardLayoutMapping()
}
// IsStandardAxisAvailable is concurrent safe.
func (g *Gamepad) IsStandardAxisAvailable(button gamepaddb.StandardAxis) bool {
g.m.Lock()
defer g.m.Unlock()
if gamepaddb.HasStandardLayoutMapping(g.sdlID) {
return gamepaddb.HasStandardAxis(g.sdlID, button)
}
return g.native.isStandardAxisAvailableInOwnMapping(button)
}
// IsStandardButtonAvailable is concurrent safe.
func (g *Gamepad) IsStandardButtonAvailable(button gamepaddb.StandardButton) bool {
g.m.Lock()
defer g.m.Unlock()
if gamepaddb.HasStandardLayoutMapping(g.sdlID) {
return gamepaddb.HasStandardButton(g.sdlID, button)
}
return g.native.isStandardButtonAvailableInOwnMapping(button)
}
// StandardAxisValue is concurrent-safe.
func (g *Gamepad) StandardAxisValue(axis gamepaddb.StandardAxis) float64 {
if gamepaddb.HasStandardLayoutMapping(g.sdlID) {

View File

@ -19,6 +19,8 @@ package gamepad
import (
"time"
"github.com/hajimehoshi/ebiten/v2/internal/gamepaddb"
)
type nativeGamepadsImpl struct{}
@ -52,6 +54,14 @@ func (*nativeGamepadImpl) hasOwnStandardLayoutMapping() bool {
return false
}
func (*nativeGamepadImpl) isStandardAxisAvailableInOwnMapping(axis gamepaddb.StandardAxis) bool {
return false
}
func (*nativeGamepadImpl) isStandardButtonAvailableInOwnMapping(button gamepaddb.StandardButton) bool {
return false
}
func (g *nativeGamepadImpl) axisCount() int {
return len(g.axes)
}

View File

@ -21,6 +21,7 @@ import (
"time"
"github.com/hajimehoshi/ebiten/v2/internal/cbackend"
"github.com/hajimehoshi/ebiten/v2/internal/gamepaddb"
)
type nativeGamepadsImpl struct {
@ -98,6 +99,16 @@ func (g *nativeGamepadImpl) hasOwnStandardLayoutMapping() bool {
return g.standard
}
func (g *nativeGamepadImpl) isStandardAxisAvailableInOwnMapping(axis gamepaddb.StandardAxis) bool {
// TODO: Implement this on the C side.
return axis >= 0 && int(axis) < len(g.axisValues)
}
func (g *nativeGamepadImpl) isStandardButtonAvailableInOwnMapping(button gamepaddb.StandardButton) bool {
// TODO: Implement this on the C side.
return button >= 0 && int(button) < len(g.buttonValues)
}
func (g *nativeGamepadImpl) axisCount() int {
return len(g.axisValues)
}

View File

@ -24,6 +24,8 @@ import (
"sync"
"time"
"unsafe"
"github.com/hajimehoshi/ebiten/v2/internal/gamepaddb"
)
// #cgo LDFLAGS: -framework CoreFoundation -framework IOKit
@ -406,6 +408,14 @@ func (g *nativeGamepadImpl) hasOwnStandardLayoutMapping() bool {
return false
}
func (g *nativeGamepadImpl) isStandardAxisAvailableInOwnMapping(axis gamepaddb.StandardAxis) bool {
return false
}
func (g *nativeGamepadImpl) isStandardButtonAvailableInOwnMapping(button gamepaddb.StandardButton) bool {
return false
}
func (g *nativeGamepadImpl) axisCount() int {
return len(g.axisValues)
}

View File

@ -28,6 +28,8 @@ import (
"unsafe"
"golang.org/x/sys/windows"
"github.com/hajimehoshi/ebiten/v2/internal/gamepaddb"
)
type dinputObjectType int
@ -571,6 +573,14 @@ func (*nativeGamepadDesktop) hasOwnStandardLayoutMapping() bool {
return false
}
func (*nativeGamepadDesktop) isStandardAxisAvailableInOwnMapping(axis gamepaddb.StandardAxis) bool {
return false
}
func (*nativeGamepadDesktop) isStandardButtonAvailableInOwnMapping(button gamepaddb.StandardButton) bool {
return false
}
func (g *nativeGamepadDesktop) usesDInput() bool {
return g.dinputDevice != nil
}

View File

@ -19,6 +19,8 @@ package gamepad
import (
"time"
"github.com/hajimehoshi/ebiten/v2/internal/gamepaddb"
)
type nativeGamepadsImpl struct{}
@ -57,6 +59,14 @@ func (*nativeGamepadImpl) hasOwnStandardLayoutMapping() bool {
return false
}
func (*nativeGamepadImpl) isStandardAxisAvailableInOwnMapping(axis gamepaddb.StandardAxis) bool {
return false
}
func (*nativeGamepadImpl) isStandardButtonAvailableInOwnMapping(button gamepaddb.StandardButton) bool {
return false
}
func (g *nativeGamepadImpl) axisCount() int {
return len(g.axes)
}

View File

@ -18,6 +18,8 @@ import (
"encoding/hex"
"syscall/js"
"time"
"github.com/hajimehoshi/ebiten/v2/internal/gamepaddb"
)
var (
@ -114,6 +116,20 @@ func (g *nativeGamepadImpl) hasOwnStandardLayoutMapping() bool {
return g.mapping == "standard"
}
func (g *nativeGamepadImpl) isStandardAxisAvailableInOwnMapping(axis gamepaddb.StandardAxis) bool {
if !g.hasOwnStandardLayoutMapping() {
return false
}
return axis >= 0 && int(axis) < g.axisCount()
}
func (g *nativeGamepadImpl) isStandardButtonAvailableInOwnMapping(button gamepaddb.StandardButton) bool {
if !g.hasOwnStandardLayoutMapping() {
return false
}
return button >= 0 && int(button) < g.buttonCount()
}
func (g *nativeGamepadImpl) update(gamepads *gamepads) error {
return nil
}

View File

@ -27,6 +27,8 @@ import (
"unsafe"
"golang.org/x/sys/unix"
"github.com/hajimehoshi/ebiten/v2/internal/gamepaddb"
)
const dirName = "/dev/input"
@ -410,6 +412,14 @@ func (*nativeGamepadImpl) hasOwnStandardLayoutMapping() bool {
return false
}
func (*nativeGamepadImpl) isStandardAxisAvailableInOwnMapping(axis gamepaddb.StandardAxis) bool {
return false
}
func (*nativeGamepadImpl) isStandardButtonAvailableInOwnMapping(button gamepaddb.StandardButton) bool {
return false
}
func (g *nativeGamepadImpl) axisCount() int {
return g.axisCount_
}

View File

@ -19,6 +19,8 @@ package gamepad
import (
"time"
"github.com/hajimehoshi/ebiten/v2/internal/gamepaddb"
)
type nativeGamepadsImpl struct{}
@ -45,6 +47,14 @@ func (*nativeGamepadImpl) hasOwnStandardLayoutMapping() bool {
return false
}
func (*nativeGamepadImpl) isStandardAxisAvailableInOwnMapping(axis gamepaddb.StandardAxis) bool {
return false
}
func (*nativeGamepadImpl) isStandardButtonAvailableInOwnMapping(button gamepaddb.StandardButton) bool {
return false
}
func (*nativeGamepadImpl) axisCount() int {
return 0
}

View File

@ -158,6 +158,27 @@ func (n *nativeGamepadXbox) hasOwnStandardLayoutMapping() bool {
return true
}
func (n *nativeGamepadXbox) isStandardAxisAvailableInOwnMapping(axis gamepaddb.StandardAxis) bool {
switch gamepaddb.StandardAxis(axis) {
case gamepaddb.StandardAxisLeftStickHorizontal,
gamepaddb.StandardAxisLeftStickVertical,
gamepaddb.StandardAxisRightStickHorizontal,
gamepaddb.StandardAxisRightStickVertical:
return true
}
return false
}
func (n *nativeGamepadXbox) isStandardButtonAvailableInOwnMapping(button gamepaddb.StandardButton) bool {
switch gamepaddb.StandardButton(button) {
case gamepaddb.StandardButtonFrontBottomLeft,
gamepaddb.StandardButtonFrontBottomRight:
return true
}
_, ok := standardButtonToGamepadInputGamepadButton(button)
return ok
}
func (n *nativeGamepadXbox) axisCount() int {
return int(gamepaddb.StandardAxisMax) + 1
}

View File

@ -389,6 +389,23 @@ func Name(id string) string {
return gamepadNames[id]
}
func HasStandardAxis(id string, axis StandardAxis) bool {
mappingsM.RLock()
defer mappingsM.RUnlock()
mappings := axisMappings(id)
if mappings == nil {
return false
}
mapping := mappings[axis]
if mapping == nil {
return false
}
return true
}
func AxisValue(id string, axis StandardAxis, state GamepadState) float64 {
mappingsM.RLock()
defer mappingsM.RUnlock()
@ -429,6 +446,23 @@ func AxisValue(id string, axis StandardAxis, state GamepadState) float64 {
return 0
}
func HasStandardButton(id string, button StandardButton) bool {
mappingsM.RLock()
defer mappingsM.RUnlock()
mappings := buttonMappings(id)
if mappings == nil {
return false
}
mapping := mappings[button]
if mapping == nil {
return false
}
return true
}
func ButtonValue(id string, button StandardButton, state GamepadState) float64 {
mappingsM.RLock()
defer mappingsM.RUnlock()