diff --git a/examples/blocks/blocks/gamepad.go b/examples/blocks/blocks/gamepad.go index c676cfc29..966987812 100644 --- a/examples/blocks/blocks/gamepad.go +++ b/examples/blocks/blocks/gamepad.go @@ -47,7 +47,7 @@ type axis struct { } type gamepadConfig struct { - gamepadID int + gamepadID ebiten.GamepadID gamepadIDInitialized bool current virtualGamepadButton @@ -59,7 +59,7 @@ type gamepadConfig struct { defaultAxesValues map[int]float64 } -func (c *gamepadConfig) SetGamepadID(id int) { +func (c *gamepadConfig) SetGamepadID(id ebiten.GamepadID) { c.gamepadID = id c.gamepadIDInitialized = true } diff --git a/examples/blocks/blocks/gamepadscene.go b/examples/blocks/blocks/gamepadscene.go index d11849584..24cb1de8f 100644 --- a/examples/blocks/blocks/gamepadscene.go +++ b/examples/blocks/blocks/gamepadscene.go @@ -24,7 +24,7 @@ import ( ) type GamepadScene struct { - gamepadID int + gamepadID ebiten.GamepadID currentIndex int countAfterSetting int buttonStates []string diff --git a/examples/blocks/blocks/input.go b/examples/blocks/blocks/input.go index 78179e2f1..dc2e313c6 100644 --- a/examples/blocks/blocks/input.go +++ b/examples/blocks/blocks/input.go @@ -27,7 +27,7 @@ type Input struct { // GamepadIDButtonPressed returns a gamepad ID where at least one button is pressed. // If no button is pressed, GamepadIDButtonPressed returns -1. -func (i *Input) GamepadIDButtonPressed() int { +func (i *Input) GamepadIDButtonPressed() ebiten.GamepadID { for _, id := range ebiten.GamepadIDs() { for b := ebiten.GamepadButton(0); b <= ebiten.GamepadButtonMax; b++ { if ebiten.IsGamepadButtonPressed(id, b) { diff --git a/examples/gamepad/main.go b/examples/gamepad/main.go index cf1d1520e..74e3350a7 100644 --- a/examples/gamepad/main.go +++ b/examples/gamepad/main.go @@ -34,14 +34,14 @@ const ( ) type Game struct { - gamepadIDs map[int]struct{} - axes map[int][]string - pressedButtons map[int][]string + gamepadIDs map[ebiten.GamepadID]struct{} + axes map[ebiten.GamepadID][]string + pressedButtons map[ebiten.GamepadID][]string } func (g *Game) Update() error { if g.gamepadIDs == nil { - g.gamepadIDs = map[int]struct{}{} + g.gamepadIDs = map[ebiten.GamepadID]struct{}{} } // Log the gamepad connection events. @@ -56,8 +56,8 @@ func (g *Game) Update() error { } } - g.axes = map[int][]string{} - g.pressedButtons = map[int][]string{} + g.axes = map[ebiten.GamepadID][]string{} + g.pressedButtons = map[ebiten.GamepadID][]string{} for id := range g.gamepadIDs { maxAxis := ebiten.GamepadAxisNum(id) for a := 0; a < maxAxis; a++ { @@ -86,11 +86,13 @@ func (g *Game) Draw(screen *ebiten.Image) { // Draw the current gamepad status. str := "" if len(g.gamepadIDs) > 0 { - ids := make([]int, 0, len(g.gamepadIDs)) + ids := make([]ebiten.GamepadID, 0, len(g.gamepadIDs)) for id := range g.gamepadIDs { ids = append(ids, id) } - sort.Ints(ids) + sort.Slice(ids, func(a, b int) bool { + return ids[a] < ids[b] + }) for _, id := range ids { str += fmt.Sprintf("Gamepad (ID: %d, SDL ID: %s):\n", id, ebiten.GamepadSDLID(id)) str += fmt.Sprintf(" Axes: %s\n", strings.Join(g.axes[id], ", ")) diff --git a/input.go b/input.go index a1e86c912..b66b0c314 100644 --- a/input.go +++ b/input.go @@ -103,18 +103,21 @@ func IsMouseButtonPressed(mouseButton MouseButton) bool { return uiDriver().Input().IsMouseButtonPressed(driver.MouseButton(mouseButton)) } +// GamepadID represents a gamepad's identifier. +type GamepadID = driver.GamepadID + // GamepadSDLID returns a string with the GUID generated in the same way as SDL. // To detect devices, see also the community project of gamepad devices database: https://github.com/gabomdq/SDL_GameControllerDB // // GamepadSDLID always returns an empty string on browsers and mobiles. // // GamepadSDLID is concurrent-safe. -func GamepadSDLID(id int) string { +func GamepadSDLID(id GamepadID) string { return uiDriver().Input().GamepadSDLID(id) } // GamepadName returns a string with the name. -// This function may vary in how it returns descriptions for the same device across platforms +// This function may vary in how it returns descriptions for the same device across platforms. // for example the following drivers/platforms see a Xbox One controller as the following: // // - Windows: "Xbox Controller" @@ -124,7 +127,7 @@ func GamepadSDLID(id int) string { // GamepadName always returns an empty string on mobiles. // // GamepadName is concurrent-safe. -func GamepadName(id int) string { +func GamepadName(id GamepadID) string { return uiDriver().Input().GamepadName(id) } @@ -133,7 +136,7 @@ func GamepadName(id int) string { // GamepadIDs is concurrent-safe. // // GamepadIDs always returns an empty slice on mobiles. -func GamepadIDs() []int { +func GamepadIDs() []GamepadID { return uiDriver().Input().GamepadIDs() } @@ -142,7 +145,7 @@ func GamepadIDs() []int { // GamepadAxisNum is concurrent-safe. // // GamepadAxisNum always returns 0 on mobiles. -func GamepadAxisNum(id int) int { +func GamepadAxisNum(id GamepadID) int { return uiDriver().Input().GamepadAxisNum(id) } @@ -151,7 +154,7 @@ func GamepadAxisNum(id int) int { // GamepadAxis is concurrent-safe. // // GamepadAxis always returns 0 on mobiles. -func GamepadAxis(id int, axis int) float64 { +func GamepadAxis(id GamepadID, axis int) float64 { return uiDriver().Input().GamepadAxis(id, axis) } @@ -160,7 +163,7 @@ func GamepadAxis(id int, axis int) float64 { // GamepadButtonNum is concurrent-safe. // // GamepadButtonNum always returns 0 on mobiles. -func GamepadButtonNum(id int) int { +func GamepadButtonNum(id GamepadID) int { return uiDriver().Input().GamepadButtonNum(id) } @@ -175,7 +178,7 @@ func GamepadButtonNum(id int) int { // There can be differences even between Chrome and Firefox. // // IsGamepadButtonPressed always returns false on mobiles. -func IsGamepadButtonPressed(id int, button GamepadButton) bool { +func IsGamepadButtonPressed(id GamepadID, button GamepadButton) bool { return uiDriver().Input().IsGamepadButtonPressed(id, driver.GamepadButton(button)) } diff --git a/inpututil/inpututil.go b/inpututil/inpututil.go index 3f30830cb..68fa6f537 100644 --- a/inpututil/inpututil.go +++ b/inpututil/inpututil.go @@ -30,11 +30,11 @@ type inputState struct { mouseButtonDurations map[ebiten.MouseButton]int prevMouseButtonDurations map[ebiten.MouseButton]int - gamepadIDs map[int]struct{} - prevGamepadIDs map[int]struct{} + gamepadIDs map[ebiten.GamepadID]struct{} + prevGamepadIDs map[ebiten.GamepadID]struct{} - gamepadButtonDurations map[int][]int - prevGamepadButtonDurations map[int][]int + gamepadButtonDurations map[ebiten.GamepadID][]int + prevGamepadButtonDurations map[ebiten.GamepadID][]int touchDurations map[int]int prevTouchDurations map[int]int @@ -49,11 +49,11 @@ var theInputState = &inputState{ mouseButtonDurations: map[ebiten.MouseButton]int{}, prevMouseButtonDurations: map[ebiten.MouseButton]int{}, - gamepadIDs: map[int]struct{}{}, - prevGamepadIDs: map[int]struct{}{}, + gamepadIDs: map[ebiten.GamepadID]struct{}{}, + prevGamepadIDs: map[ebiten.GamepadID]struct{}{}, - gamepadButtonDurations: map[int][]int{}, - prevGamepadButtonDurations: map[int][]int{}, + gamepadButtonDurations: map[ebiten.GamepadID][]int{}, + prevGamepadButtonDurations: map[ebiten.GamepadID][]int{}, touchDurations: map[int]int{}, prevTouchDurations: map[int]int{}, @@ -97,18 +97,18 @@ func (i *inputState) update() { // Gamepads // Copy the gamepad IDs. - i.prevGamepadIDs = map[int]struct{}{} + i.prevGamepadIDs = map[ebiten.GamepadID]struct{}{} for id := range i.gamepadIDs { i.prevGamepadIDs[id] = struct{}{} } // Copy the gamepad button durations. - i.prevGamepadButtonDurations = map[int][]int{} + i.prevGamepadButtonDurations = map[ebiten.GamepadID][]int{} for id, ds := range i.gamepadButtonDurations { i.prevGamepadButtonDurations[id] = append([]int{}, ds...) } - i.gamepadIDs = map[int]struct{}{} + i.gamepadIDs = map[ebiten.GamepadID]struct{}{} for _, id := range ebiten.GamepadIDs() { i.gamepadIDs[id] = struct{}{} if _, ok := i.gamepadButtonDurations[id]; !ok { @@ -123,13 +123,13 @@ func (i *inputState) update() { } } } - idsToDelete := []int{} + gamepadIDsToDelete := []ebiten.GamepadID{} for id := range i.gamepadButtonDurations { if _, ok := i.gamepadIDs[id]; !ok { - idsToDelete = append(idsToDelete, id) + gamepadIDsToDelete = append(gamepadIDsToDelete, id) } } - for _, id := range idsToDelete { + for _, id := range gamepadIDsToDelete { delete(i.gamepadButtonDurations, id) } @@ -146,13 +146,13 @@ func (i *inputState) update() { ids[id] = struct{}{} i.touchDurations[id]++ } - idsToDelete = []int{} + touchIDsToDelete := []int{} for id := range i.touchDurations { if _, ok := ids[id]; !ok { - idsToDelete = append(idsToDelete, id) + touchIDsToDelete = append(touchIDsToDelete, id) } } - for _, id := range idsToDelete { + for _, id := range touchIDsToDelete { delete(i.touchDurations, id) } } @@ -221,8 +221,8 @@ func MouseButtonPressDuration(button ebiten.MouseButton) int { // JustConnectedGamepadIDs might return nil when there is no connected gamepad. // // JustConnectedGamepadIDs is concurrent safe. -func JustConnectedGamepadIDs() []int { - var ids []int +func JustConnectedGamepadIDs() []ebiten.GamepadID { + var ids []ebiten.GamepadID theInputState.m.RLock() for id := range theInputState.gamepadIDs { if _, ok := theInputState.prevGamepadIDs[id]; !ok { @@ -230,7 +230,9 @@ func JustConnectedGamepadIDs() []int { } } theInputState.m.RUnlock() - sort.Ints(ids) + sort.Slice(ids, func(a, b int) bool { + return ids[a] < ids[b] + }) return ids } @@ -238,7 +240,7 @@ func JustConnectedGamepadIDs() []int { // whether the gamepad of the given id is released just in the current frame. // // IsGamepadJustDisconnected is concurrent safe. -func IsGamepadJustDisconnected(id int) bool { +func IsGamepadJustDisconnected(id ebiten.GamepadID) bool { theInputState.m.RLock() _, prev := theInputState.prevGamepadIDs[id] _, current := theInputState.gamepadIDs[id] @@ -250,7 +252,7 @@ func IsGamepadJustDisconnected(id int) bool { // whether the given gamepad button of the gamepad id is pressed just in the current frame. // // IsGamepadButtonJustPressed is concurrent safe. -func IsGamepadButtonJustPressed(id int, button ebiten.GamepadButton) bool { +func IsGamepadButtonJustPressed(id ebiten.GamepadID, button ebiten.GamepadButton) bool { return GamepadButtonPressDuration(id, button) == 1 } @@ -258,7 +260,7 @@ func IsGamepadButtonJustPressed(id int, button ebiten.GamepadButton) bool { // whether the given gamepad button of the gamepad id is released just in the current frame. // // IsGamepadButtonJustReleased is concurrent safe. -func IsGamepadButtonJustReleased(id int, button ebiten.GamepadButton) bool { +func IsGamepadButtonJustReleased(id ebiten.GamepadID, button ebiten.GamepadButton) bool { theInputState.m.RLock() prev := 0 if _, ok := theInputState.prevGamepadButtonDurations[id]; ok { @@ -275,7 +277,7 @@ func IsGamepadButtonJustReleased(id int, button ebiten.GamepadButton) bool { // GamepadButtonPressDuration returns how long the gamepad button of the gamepad id is pressed in frames. // // GamepadButtonPressDuration is concurrent safe. -func GamepadButtonPressDuration(id int, button ebiten.GamepadButton) int { +func GamepadButtonPressDuration(id ebiten.GamepadID, button ebiten.GamepadButton) int { theInputState.m.RLock() s := 0 if _, ok := theInputState.gamepadButtonDurations[id]; ok { diff --git a/internal/driver/input.go b/internal/driver/input.go index c1edccaa4..a5945010c 100644 --- a/internal/driver/input.go +++ b/internal/driver/input.go @@ -14,15 +14,17 @@ package driver +type GamepadID int + type Input interface { CursorPosition() (x, y int) - GamepadSDLID(id int) string - GamepadName(id int) string - GamepadAxis(id int, axis int) float64 - GamepadAxisNum(id int) int - GamepadButtonNum(id int) int - GamepadIDs() []int - IsGamepadButtonPressed(id int, button GamepadButton) bool + GamepadSDLID(id GamepadID) string + GamepadName(id GamepadID) string + GamepadAxis(id GamepadID, axis int) float64 + GamepadAxisNum(id GamepadID) int + GamepadButtonNum(id GamepadID) int + GamepadIDs() []GamepadID + IsGamepadButtonPressed(id GamepadID, button GamepadButton) bool IsKeyPressed(key Key) bool IsMouseButtonPressed(button MouseButton) bool RuneBuffer() []rune diff --git a/internal/uidriver/glfw/input.go b/internal/uidriver/glfw/input.go index 343421826..ae57ed80f 100644 --- a/internal/uidriver/glfw/input.go +++ b/internal/uidriver/glfw/input.go @@ -67,15 +67,15 @@ func (i *Input) CursorPosition() (x, y int) { return cx, cy } -func (i *Input) GamepadIDs() []int { +func (i *Input) GamepadIDs() []driver.GamepadID { if !i.ui.isRunning() { return nil } - var r []int + var r []driver.GamepadID _ = i.ui.t.Call(func() error { for id, g := range i.gamepads { if g.valid { - r = append(r, id) + r = append(r, driver.GamepadID(id)) } } return nil @@ -83,13 +83,13 @@ func (i *Input) GamepadIDs() []int { return r } -func (i *Input) GamepadSDLID(id int) string { +func (i *Input) GamepadSDLID(id driver.GamepadID) string { if !i.ui.isRunning() { return "" } var r string _ = i.ui.t.Call(func() error { - if len(i.gamepads) <= id { + if len(i.gamepads) <= int(id) { return nil } r = i.gamepads[id].guid @@ -98,13 +98,13 @@ func (i *Input) GamepadSDLID(id int) string { return r } -func (i *Input) GamepadName(id int) string { +func (i *Input) GamepadName(id driver.GamepadID) string { if !i.ui.isRunning() { return "" } var r string _ = i.ui.t.Call(func() error { - if len(i.gamepads) <= id { + if len(i.gamepads) <= int(id) { return nil } r = i.gamepads[id].name @@ -113,13 +113,13 @@ func (i *Input) GamepadName(id int) string { return r } -func (i *Input) GamepadAxisNum(id int) int { +func (i *Input) GamepadAxisNum(id driver.GamepadID) int { if !i.ui.isRunning() { return 0 } var r int _ = i.ui.t.Call(func() error { - if len(i.gamepads) <= id { + if len(i.gamepads) <= int(id) { return nil } r = i.gamepads[id].axisNum @@ -128,13 +128,13 @@ func (i *Input) GamepadAxisNum(id int) int { return r } -func (i *Input) GamepadAxis(id int, axis int) float64 { +func (i *Input) GamepadAxis(id driver.GamepadID, axis int) float64 { if !i.ui.isRunning() { return 0 } var r float64 _ = i.ui.t.Call(func() error { - if len(i.gamepads) <= id { + if len(i.gamepads) <= int(id) { return nil } r = i.gamepads[id].axes[axis] @@ -143,13 +143,13 @@ func (i *Input) GamepadAxis(id int, axis int) float64 { return r } -func (i *Input) GamepadButtonNum(id int) int { +func (i *Input) GamepadButtonNum(id driver.GamepadID) int { if !i.ui.isRunning() { return 0 } var r int _ = i.ui.t.Call(func() error { - if len(i.gamepads) <= id { + if len(i.gamepads) <= int(id) { return nil } r = i.gamepads[id].buttonNum @@ -158,13 +158,13 @@ func (i *Input) GamepadButtonNum(id int) int { return r } -func (i *Input) IsGamepadButtonPressed(id int, button driver.GamepadButton) bool { +func (i *Input) IsGamepadButtonPressed(id driver.GamepadID, button driver.GamepadButton) bool { if !i.ui.isRunning() { return false } var r bool _ = i.ui.t.Call(func() error { - if len(i.gamepads) <= id { + if len(i.gamepads) <= int(id) { return nil } r = i.gamepads[id].buttonPressed[button] diff --git a/internal/uidriver/js/input_js.go b/internal/uidriver/js/input_js.go index 88a60850d..fc041c876 100644 --- a/internal/uidriver/js/input_js.go +++ b/internal/uidriver/js/input_js.go @@ -56,10 +56,10 @@ func (i *Input) CursorPosition() (x, y int) { return int(xf), int(yf) } -func (i *Input) GamepadSDLID(id int) string { +func (i *Input) GamepadSDLID(id driver.GamepadID) string { // This emulates the implementation of EMSCRIPTEN_JoystickGetDeviceGUID. // https://hg.libsdl.org/SDL/file/bc90ce38f1e2/src/joystick/emscripten/SDL_sysjoystick.c#l385 - if len(i.gamepads) <= id { + if len(i.gamepads) <= int(id) { return "" } var sdlid [16]byte @@ -70,49 +70,49 @@ func (i *Input) GamepadSDLID(id int) string { // GamepadName returns a string containing some information about the controller. // A PS2 controller returned "810-3-USB Gamepad" on Firefox // A Xbox 360 controller returned "xinput" on Firefox and "Xbox 360 Controller (XInput STANDARD GAMEPAD)" on Chrome -func (i *Input) GamepadName(id int) string { - if len(i.gamepads) <= id { +func (i *Input) GamepadName(id driver.GamepadID) string { + if len(i.gamepads) <= int(id) { return "" } return i.gamepads[id].name } -func (i *Input) GamepadIDs() []int { +func (i *Input) GamepadIDs() []driver.GamepadID { if len(i.gamepads) == 0 { return nil } - r := []int{} + var r []driver.GamepadID for id, g := range i.gamepads { if g.valid { - r = append(r, id) + r = append(r, driver.GamepadID(id)) } } return r } -func (i *Input) GamepadAxisNum(id int) int { - if len(i.gamepads) <= id { +func (i *Input) GamepadAxisNum(id driver.GamepadID) int { + if len(i.gamepads) <= int(id) { return 0 } return i.gamepads[id].axisNum } -func (i *Input) GamepadAxis(id int, axis int) float64 { - if len(i.gamepads) <= id { +func (i *Input) GamepadAxis(id driver.GamepadID, axis int) float64 { + if len(i.gamepads) <= int(id) { return 0 } return i.gamepads[id].axes[axis] } -func (i *Input) GamepadButtonNum(id int) int { - if len(i.gamepads) <= id { +func (i *Input) GamepadButtonNum(id driver.GamepadID) int { + if len(i.gamepads) <= int(id) { return 0 } return i.gamepads[id].buttonNum } -func (i *Input) IsGamepadButtonPressed(id int, button driver.GamepadButton) bool { - if len(i.gamepads) <= id { +func (i *Input) IsGamepadButtonPressed(id driver.GamepadID, button driver.GamepadButton) bool { + if len(i.gamepads) <= int(id) { return false } return i.gamepads[id].buttonPressed[button] diff --git a/internal/uidriver/mobile/input.go b/internal/uidriver/mobile/input.go index cda0bf18a..b2c024b6c 100644 --- a/internal/uidriver/mobile/input.go +++ b/internal/uidriver/mobile/input.go @@ -41,18 +41,18 @@ func (i *Input) CursorPosition() (x, y int) { return i.ui.adjustPosition(i.cursorX, i.cursorY) } -func (i *Input) GamepadIDs() []int { +func (i *Input) GamepadIDs() []driver.GamepadID { i.ui.m.RLock() defer i.ui.m.RUnlock() - ids := make([]int, 0, len(i.gamepads)) + ids := make([]driver.GamepadID, 0, len(i.gamepads)) for _, g := range i.gamepads { ids = append(ids, g.ID) } return ids } -func (i *Input) GamepadSDLID(id int) string { +func (i *Input) GamepadSDLID(id driver.GamepadID) string { i.ui.m.RLock() defer i.ui.m.RUnlock() @@ -65,7 +65,7 @@ func (i *Input) GamepadSDLID(id int) string { return "" } -func (i *Input) GamepadName(id int) string { +func (i *Input) GamepadName(id driver.GamepadID) string { i.ui.m.RLock() defer i.ui.m.RUnlock() @@ -78,7 +78,7 @@ func (i *Input) GamepadName(id int) string { return "" } -func (i *Input) GamepadAxisNum(id int) int { +func (i *Input) GamepadAxisNum(id driver.GamepadID) int { i.ui.m.RLock() defer i.ui.m.RUnlock() @@ -91,7 +91,7 @@ func (i *Input) GamepadAxisNum(id int) int { return 0 } -func (i *Input) GamepadAxis(id int, axis int) float64 { +func (i *Input) GamepadAxis(id driver.GamepadID, axis int) float64 { i.ui.m.RLock() defer i.ui.m.RUnlock() @@ -107,7 +107,7 @@ func (i *Input) GamepadAxis(id int, axis int) float64 { return 0 } -func (i *Input) GamepadButtonNum(id int) int { +func (i *Input) GamepadButtonNum(id driver.GamepadID) int { i.ui.m.RLock() defer i.ui.m.RUnlock() @@ -120,7 +120,7 @@ func (i *Input) GamepadButtonNum(id int) int { return 0 } -func (i *Input) IsGamepadButtonPressed(id int, button driver.GamepadButton) bool { +func (i *Input) IsGamepadButtonPressed(id driver.GamepadID, button driver.GamepadButton) bool { i.ui.m.RLock() defer i.ui.m.RUnlock() diff --git a/internal/uidriver/mobile/ui.go b/internal/uidriver/mobile/ui.go index 4d3490593..f075d1b72 100644 --- a/internal/uidriver/mobile/ui.go +++ b/internal/uidriver/mobile/ui.go @@ -480,7 +480,7 @@ type Touch struct { } type Gamepad struct { - ID int + ID driver.GamepadID SDLID string Name string Buttons [driver.GamepadButtonNum]bool diff --git a/mobile/ebitenmobileview/input.go b/mobile/ebitenmobileview/input.go index 94b7c9949..0fc5baca0 100644 --- a/mobile/ebitenmobileview/input.go +++ b/mobile/ebitenmobileview/input.go @@ -30,7 +30,7 @@ var ( keys = map[driver.Key]struct{}{} runes []rune touches = map[int]position{} - gamepads = map[int]*mobile.Gamepad{} + gamepads = map[driver.GamepadID]*mobile.Gamepad{} ) func updateInput() { diff --git a/mobile/ebitenmobileview/input_android.go b/mobile/ebitenmobileview/input_android.go index f3528b1db..af29d6318 100644 --- a/mobile/ebitenmobileview/input_android.go +++ b/mobile/ebitenmobileview/input_android.go @@ -177,18 +177,18 @@ var androidAxisIDToAxisID = map[int]int{ var ( // deviceIDToGamepadID is a map from Android device IDs to Ebiten gamepad IDs. // As convention, Ebiten gamepad IDs start with 0, and many applications depend on this fact. - deviceIDToGamepadID = map[int]int{} + deviceIDToGamepadID = map[int]driver.GamepadID{} ) -func gamepadIDFromDeviceID(deviceID int) int { +func gamepadIDFromDeviceID(deviceID int) driver.GamepadID { if id, ok := deviceIDToGamepadID[deviceID]; ok { return id } - ids := map[int]struct{}{} + ids := map[driver.GamepadID]struct{}{} for _, id := range deviceIDToGamepadID { ids[id] = struct{}{} } - for i := 0; ; i++ { + for i := driver.GamepadID(0); ; i++ { if _, ok := ids[i]; ok { continue }