updated ebiten version from 2.7.9 to 2.9.9

This commit is contained in:
2026-06-15 19:06:55 +02:00
parent 21edbc41c4
commit db1b625069
405 changed files with 31913 additions and 12595 deletions
+3
View File
@@ -293,6 +293,8 @@ package gamepad
// return hat;
// }
//
// #cgo noescape getControllerState
// #cgo nocallback getControllerState
// static void getControllerState(uintptr_t controller_ptr, struct ControllerState* controllerState,
// uint16_t buttonMask, uint8_t nHats,
// bool hasDualshockTouchpad, bool hasXboxPaddles, bool hasXboxShareButton) {
@@ -365,6 +367,7 @@ package gamepad
// }
// }
//
// #cgo noescape initializeGamepads
// static void initializeGamepads(void) {
// @autoreleasepool {
// for (GCController* controller in [GCController controllers]) {
+1 -1
View File
@@ -131,7 +131,7 @@ type input_id struct {
func ioctl(fd int, request uint, ptr unsafe.Pointer) error {
r, _, e := unix.Syscall(unix.SYS_IOCTL, uintptr(fd), uintptr(request), uintptr(ptr))
if r < 0 {
if int32(r) < 0 {
return unix.Errno(e)
}
return nil
@@ -152,6 +152,14 @@ func (g *nativeGamepadsImpl) addDevice(device _IOHIDDeviceRef, gamepads *gamepad
return
}
elements := _IOHIDDeviceCopyMatchingElements(device, 0, kIOHIDOptionsTypeNone)
// It is reportedly possible for this to fail on macOS 13 Ventura
// if the application does not have input monitoring permissions
if elements == 0 {
return
}
defer _CFRelease(_CFTypeRef(elements))
name := "Unknown"
if prop := _IOHIDDeviceGetProperty(device, _CFStringCreateWithCString(kCFAllocatorDefault, kIOHIDProductKey, kCFStringEncodingUTF8)); prop != 0 {
var cstr [256]byte
@@ -189,9 +197,6 @@ func (g *nativeGamepadsImpl) addDevice(device _IOHIDDeviceRef, gamepads *gamepad
bs[0], bs[1], bs[2], bs[3], bs[4], bs[5], bs[6], bs[7], bs[8], bs[9], bs[10], bs[11])
}
elements := _IOHIDDeviceCopyMatchingElements(device, 0, kIOHIDOptionsTypeNone)
defer _CFRelease(_CFTypeRef(elements))
n := &nativeGamepadImpl{
device: device,
}
@@ -113,7 +113,7 @@ type nativeGamepadsDesktop struct {
enumObjectsCallback uintptr
nativeWindow windows.HWND
deviceChanged int32
deviceChanged atomic.Bool
err error
}
@@ -309,12 +309,16 @@ func (g *nativeGamepadsDesktop) dinput8EnumDevicesCallback(lpddi *_DIDEVICEINSTA
return _DIENUM_STOP
}
// lpddi.guidInstance is not relialable as a unique identity when the same multiple devices are connected (#3046).
// lpddi.guidInstance is not reliable as a unique identity when the same multiple devices are connected (#3046).
// Use HID Path instead.
getDInputPath := func(device *_IDirectInputDevice8W) (string, error) {
var prop _DIPROPGUIDANDPATH
prop.diph.dwHeaderSize = uint32(unsafe.Sizeof(_DIPROPHEADER{}))
prop.diph.dwSize = uint32(unsafe.Sizeof(_DIPROPGUIDANDPATH{}))
prop := _DIPROPGUIDANDPATH{
diph: _DIPROPHEADER{
dwHeaderSize: uint32(unsafe.Sizeof(_DIPROPHEADER{})),
dwSize: uint32(unsafe.Sizeof(_DIPROPGUIDANDPATH{})),
dwHow: _DIPH_DEVICE,
},
}
if err := device.GetProperty(_DIPROP_GUIDANDPATH, &prop.diph); err != nil {
return "", err
}
@@ -572,11 +576,11 @@ func (g *nativeGamepadsDesktop) update(gamepads *gamepads) error {
g.origWndProc = h
}
if atomic.LoadInt32(&g.deviceChanged) != 0 {
if g.deviceChanged.Load() {
if err := g.detectConnection(gamepads); err != nil {
g.err = err
}
atomic.StoreInt32(&g.deviceChanged, 0)
g.deviceChanged.Store(false)
}
return nil
@@ -585,7 +589,7 @@ func (g *nativeGamepadsDesktop) update(gamepads *gamepads) error {
func (g *nativeGamepadsDesktop) wndProc(hWnd uintptr, uMsg uint32, wParam, lParam uintptr) uintptr {
switch uMsg {
case _WM_DEVICECHANGE:
atomic.StoreInt32(&g.deviceChanged, 1)
g.deviceChanged.Store(true)
}
return _CallWindowProcW(g.origWndProc, hWnd, uMsg, wParam, lParam)
}
@@ -829,6 +833,16 @@ func (g *nativeGamepadDesktop) hatState(hat int) int {
if g.xinputState.Gamepad.wButtons&_XINPUT_GAMEPAD_DPAD_LEFT != 0 {
v |= hatLeft
}
// Treat invalid combinations as neither being pressed
// while preserving what data can be preserved
if (v&hatRight) != 0 && (v&hatLeft) != 0 {
v &^= hatRight | hatLeft
}
if (v&hatUp) != 0 && (v&hatDown) != 0 {
v &^= hatUp | hatDown
}
return v
}
+6 -9
View File
@@ -54,6 +54,10 @@ func (g *nativeGamepadsImpl) init(gamepads *gamepads) error {
if err == unix.ENOENT {
return nil
}
// `/dev/input` might not be accessible in some environments (#3057).
if err == unix.EACCES {
return nil
}
return fmt.Errorf("gamepad: Stat failed: %w", err)
}
if stat.Mode&unix.S_IFDIR == 0 {
@@ -140,13 +144,6 @@ func (*nativeGamepadsImpl) openGamepad(gamepads *gamepads, path string) (err err
return fmt.Errorf("gamepad: ioctl for an ID failed: %w", err)
}
if !isBitSet(evBits, unix.EV_KEY) {
if err := unix.Close(fd); err != nil {
return err
}
return nil
}
if !isBitSet(evBits, unix.EV_ABS) {
if err := unix.Close(fd); err != nil {
return err
@@ -185,9 +182,9 @@ func (*nativeGamepadsImpl) openGamepad(gamepads *gamepads, path string) (err err
}
gp := gamepads.add(name, sdlID)
gp.native = n
runtime.SetFinalizer(gp, func(gp *Gamepad) {
runtime.AddCleanup(gp, func(n *nativeGamepadImpl) {
n.close()
})
}, n)
var axisCount int
var buttonCount int
@@ -14,7 +14,7 @@
//go:build nintendosdk
// The actual implementation will be provided by -overlay.
// The actual implementation will be provided by github.com/hajimehoshi/uwagaki.
#include "gamepad_nintendosdk.h"
@@ -0,0 +1,29 @@
// Copyright 2024 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.
//go:build playstation5
// The actual implementation will be provided by github.com/hajimehoshi/uwagaki.
#include "gamepad_nintendosdk.h"
extern "C" void ebitengine_UpdateGamepads() {}
extern "C" int ebitengine_GetGamepadCount() { return 0; }
extern "C" void ebitengine_GetGamepads(struct Gamepad *gamepads) {}
extern "C" void ebitengine_VibrateGamepad(int id, double durationInSeconds,
double strongMagnitude,
double weakMagnitude) {}
@@ -16,17 +16,163 @@
package gamepad
// #cgo !darwin LDFLAGS: -Wl,-unresolved-symbols=ignore-all
// #cgo darwin LDFLAGS: -Wl,-undefined,dynamic_lookup
//
// #include "gamepad_playstation5.h"
import "C"
import (
"time"
"github.com/hajimehoshi/ebiten/v2/internal/gamepaddb"
)
type nativeGamepadsImpl struct {
gamepads []C.struct_Gamepad
ids map[int]struct{}
}
func newNativeGamepadsImpl() nativeGamepads {
return &nativeGamepadsImpl{}
}
func (g *nativeGamepadsImpl) init(gamepads *gamepads) error {
func (*nativeGamepadsImpl) init(gamepads *gamepads) error {
return nil
}
func (g *nativeGamepadsImpl) update(gamepads *gamepads) error {
C.ebitengine_UpdateGamepads()
g.gamepads = g.gamepads[:0]
if n := int(C.ebitengine_GetGamepadCount()); n > 0 {
if cap(g.gamepads) < n {
g.gamepads = make([]C.struct_Gamepad, n)
} else {
g.gamepads = g.gamepads[:n]
}
C.ebitengine_GetGamepads(&g.gamepads[0])
}
for id := range g.ids {
delete(g.ids, id)
}
for _, gp := range g.gamepads {
if g.ids == nil {
g.ids = map[int]struct{}{}
}
g.ids[int(gp.id)] = struct{}{}
gamepad := gamepads.find(func(gamepad *Gamepad) bool {
return gamepad.native.(*nativeGamepadImpl).id == int(gp.id)
})
if gamepad == nil {
gamepad = gamepads.add("", "")
gamepad.native = &nativeGamepadImpl{
id: int(gp.id),
axisValues: make([]float64, gp.axis_count),
buttonPressed: make([]bool, gp.button_count),
buttonValues: make([]float64, gp.button_count),
}
}
gamepad.m.Lock()
n := gamepad.native.(*nativeGamepadImpl)
for i := range n.axisValues {
n.axisValues[i] = float64(gp.axis_values[i])
}
for i := range n.buttonValues {
n.buttonValues[i] = float64(gp.button_values[i])
}
for i := range n.buttonPressed {
n.buttonPressed[i] = gp.button_pressed[i] != 0
}
gamepad.m.Unlock()
}
// Remove an unused gamepads.
gamepads.remove(func(gamepad *Gamepad) bool {
_, ok := g.ids[gamepad.native.(*nativeGamepadImpl).id]
return !ok
})
return nil
}
type nativeGamepadImpl struct {
id int
axisValues []float64
buttonPressed []bool
buttonValues []float64
}
func (*nativeGamepadImpl) update(gamepad *gamepads) error {
return nil
}
func (g *nativeGamepadImpl) hasOwnStandardLayoutMapping() bool {
return true
}
func (g *nativeGamepadImpl) standardAxisInOwnMapping(axis gamepaddb.StandardAxis) mappingInput {
// TODO: Implement this on the C side.
if axis < 0 || int(axis) >= len(g.axisValues) {
return nil
}
return axisMappingInput{g: g, axis: int(axis)}
}
func (g *nativeGamepadImpl) standardButtonInOwnMapping(button gamepaddb.StandardButton) mappingInput {
// TODO: Implement this on the C side.
if button < 0 || int(button) >= len(g.buttonValues) {
return nil
}
return buttonMappingInput{g: g, button: int(button)}
}
func (g *nativeGamepadImpl) axisCount() int {
return len(g.axisValues)
}
func (g *nativeGamepadImpl) buttonCount() int {
return len(g.buttonValues)
}
func (g *nativeGamepadImpl) hatCount() int {
return 0
}
func (g *nativeGamepadImpl) isAxisReady(axis int) bool {
return axis >= 0 && axis < g.axisCount()
}
func (g *nativeGamepadImpl) axisValue(axis int) float64 {
if axis < 0 || axis >= len(g.axisValues) {
return 0
}
return g.axisValues[axis]
}
func (g *nativeGamepadImpl) isButtonPressed(button int) bool {
if button < 0 || button >= len(g.buttonPressed) {
return false
}
return g.buttonPressed[button]
}
func (g *nativeGamepadImpl) buttonValue(button int) float64 {
if button < 0 || button >= len(g.buttonValues) {
return 0
}
return g.buttonValues[button]
}
func (*nativeGamepadImpl) hatState(hat int) int {
return hatCentered
}
func (g *nativeGamepadImpl) vibrate(duration time.Duration, strongMagnitude float64, weakMagnitude float64) {
C.ebitengine_VibrateGamepad(C.int(g.id), C.double(float64(duration)/float64(time.Second)), C.double(strongMagnitude), C.double(weakMagnitude))
}
@@ -0,0 +1,38 @@
// Copyright 2024 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.
//go:build playstation5
struct Gamepad {
int id;
int button_count;
int axis_count;
char button_pressed[32];
float button_values[32];
float axis_values[16];
};
#ifdef __cplusplus
extern "C" {
#endif
void ebitengine_UpdateGamepads();
int ebitengine_GetGamepadCount();
void ebitengine_GetGamepads(struct Gamepad *gamepads);
void ebitengine_VibrateGamepad(int id, double durationInSeconds,
double strongMagnitude, double weakMagnitude);
#ifdef __cplusplus
} // extern "C"
#endif