ebiten: Support updating the gamepad mapping (#1775)

This is only supported on desktops yet (on mobile standard layout isn't
implemented yet, and on the web this is the browser's responsibility).

Closes #1723
This commit is contained in:
divVerent 2021-08-23 08:44:49 -04:00 committed by GitHub
parent 35deb53624
commit 7b11377bce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 58 additions and 0 deletions

View File

@ -234,6 +234,27 @@ func IsStandardGamepadLayoutAvailable(id GamepadID) bool {
return uiDriver().Input().IsStandardGamepadLayoutAvailable(id)
}
// UpdateStandardGamepadLayoutMappings updates the gamepad layout definitions using a set of definitions in SDL_GameControllerDB format.
//
// Multiple input definitions can be provided separated by newlines.
// In particular, it is valid to pass an entire gamecontrollerdb.txt file.
//
// Note though that Ebiten already includes its own copy of this file,
// so this call should only be necessary to add mappings for hardware not supported yet;
// ideally games using the StandardGamepad functions should allow the user to provide mappings and then call this function if provided.
// When using this facility to support new hardware, please also send a pull request to https://github.com/gabomdq/SDL_GameControllerDB to make your mapping available to everyone else.
//
// UpdateStandardGamepadLayoutMappings reports whether the mappings were applied, and returns an error in case any occurred while parsing the mappings.
//
// On platforms where gamepad mappings are not managed by Ebiten, this always returns false and nil.
//
// UpdateStandardGamepadLayoutMappings must be called on the main thread before ebiten.Run, and is concurrent-safe after ebiten.Run.
//
// Updated mappings take effect immediately even for already connected gamepads.
func UpdateStandardGamepadLayoutMappings(mappings string) (bool, error) {
return uiDriver().Input().UpdateStandardGamepadLayoutMappings(mappings)
}
// TouchID represents a touch's identifier.
type TouchID = driver.TouchID

View File

@ -34,6 +34,7 @@ type Input interface {
IsStandardGamepadButtonPressed(id GamepadID, button StandardGamepadButton) bool
IsStandardGamepadLayoutAvailable(id GamepadID) bool
StandardGamepadAxisValue(id GamepadID, button StandardGamepadAxis) float64
UpdateStandardGamepadLayoutMappings(mapping string) (bool, error)
TouchPosition(id TouchID) (x, y int)
Wheel() (xoff, yoff float64)
}

View File

@ -452,3 +452,26 @@ func standardButtonToGLFWButton(button driver.StandardGamepadButton) glfw.Gamepa
panic(fmt.Sprintf("glfw: invalid or inconvertible StandardGamepadButton: %d", button))
}
}
// UpdateStandardGamepadLayoutMappings can be used to provide new gamepad mappings to Ebiten.
// The string must be in the format of SDL_GameControllerDB.
func (i *Input) UpdateStandardGamepadLayoutMappings(mapping string) (bool, error) {
var err error
if i.ui.isRunning() {
err = i.ui.t.Call(func() error {
return i.updateStandardGamepadLayoutMappings(mapping)
})
} else {
err = i.updateStandardGamepadLayoutMappings(mapping)
}
return err == nil, err
}
func (i *Input) updateStandardGamepadLayoutMappings(mapping string) error {
if !glfw.UpdateGamepadMappings(mapping) {
// Would be nice if we could actually get the error string.
// However, go-gl currently does not provide it in any way.
return fmt.Errorf("glfw: could not parse or update gamepad mappings")
}
return nil
}

View File

@ -496,3 +496,9 @@ func (i *Input) IsStandardGamepadButtonPressed(id driver.GamepadID, button drive
}
return g.standardButtonPressed[button]
}
// UpdateStandardGamepadLayoutMappings is not supported for JS - the browser maintains the mappings.
func (i *Input) UpdateStandardGamepadLayoutMappings(mapping string) (bool, error) {
// All OK - browser owns this though.
return false, nil
}

View File

@ -147,6 +147,13 @@ func (i *Input) StandardGamepadAxisValue(id driver.GamepadID, axis driver.Standa
return 0
}
// UpdateStandardGamepadLayoutMappings is not supported on mobile - this still needs to be implemented.
func (i *Input) UpdateStandardGamepadLayoutMappings(mapping string) (bool, error) {
// TODO: Implement this (#1557)
// Note: NOT returning an error, as mappings also do not matter right now (all functions above return nothing is pressed anyway).
return false, nil
}
func (i *Input) AppendTouchIDs(touchIDs []driver.TouchID) []driver.TouchID {
i.ui.m.RLock()
defer i.ui.m.RUnlock()