ebiten/internal/gamepad/api_xbox_windows.go
2022-10-02 02:22:06 +09:00

272 lines
9.4 KiB
Go

// Copyright 2022 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 !nintendosdk
// +build !nintendosdk
package gamepad
import (
"fmt"
"runtime"
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
type handleError windows.Handle
func (h handleError) Error() string {
return fmt.Sprintf("HANDLE(%d)", h)
}
var (
gameInput = windows.NewLazySystemDLL("GameInput.dll")
procGameInputCreate = gameInput.NewProc("GameInputCreate")
)
type _GameInputCallbackToken uint64
type _GameInputDeviceStatus int32
const (
_GameInputDeviceNoStatus _GameInputDeviceStatus = 0x00000000
_GameInputDeviceConnected _GameInputDeviceStatus = 0x00000001
_GameInputDeviceInputEnabled _GameInputDeviceStatus = 0x00000002
_GameInputDeviceOutputEnabled _GameInputDeviceStatus = 0x00000004
_GameInputDeviceRawIoEnabled _GameInputDeviceStatus = 0x00000008
_GameInputDeviceAudioCapture _GameInputDeviceStatus = 0x00000010
_GameInputDeviceAudioRender _GameInputDeviceStatus = 0x00000020
_GameInputDeviceSynchronized _GameInputDeviceStatus = 0x00000040
_GameInputDeviceWireless _GameInputDeviceStatus = 0x00000080
_GameInputDeviceUserIdle _GameInputDeviceStatus = 0x00100000
_GameInputDeviceAnyStatus _GameInputDeviceStatus = 0x00FFFFFF
)
type _GameInputEnumerationKind int32
const (
_GameInputNoEnumeration _GameInputEnumerationKind = 0
_GameInputAsyncEnumeration _GameInputEnumerationKind = 1
_GameInputBlockingEnumeration _GameInputEnumerationKind = 2
)
type _GameInputGamepadButtons int32
const (
_GameInputGamepadNone _GameInputGamepadButtons = 0x00000000
_GameInputGamepadMenu _GameInputGamepadButtons = 0x00000001
_GameInputGamepadView _GameInputGamepadButtons = 0x00000002
_GameInputGamepadA _GameInputGamepadButtons = 0x00000004
_GameInputGamepadB _GameInputGamepadButtons = 0x00000008
_GameInputGamepadX _GameInputGamepadButtons = 0x00000010
_GameInputGamepadY _GameInputGamepadButtons = 0x00000020
_GameInputGamepadDPadUp _GameInputGamepadButtons = 0x00000040
_GameInputGamepadDPadDown _GameInputGamepadButtons = 0x00000080
_GameInputGamepadDPadLeft _GameInputGamepadButtons = 0x00000100
_GameInputGamepadDPadRight _GameInputGamepadButtons = 0x00000200
_GameInputGamepadLeftShoulder _GameInputGamepadButtons = 0x00000400
_GameInputGamepadRightShoulder _GameInputGamepadButtons = 0x00000800
_GameInputGamepadLeftThumbstick _GameInputGamepadButtons = 0x00001000
_GameInputGamepadRightThumbstick _GameInputGamepadButtons = 0x00002000
)
type _GameInputKind int32
const (
_GameInputKindUnknown _GameInputKind = 0x00000000
_GameInputKindRawDeviceReport _GameInputKind = 0x00000001
_GameInputKindControllerAxis _GameInputKind = 0x00000002
_GameInputKindControllerButton _GameInputKind = 0x00000004
_GameInputKindControllerSwitch _GameInputKind = 0x00000008
_GameInputKindController _GameInputKind = 0x0000000E
_GameInputKindKeyboard _GameInputKind = 0x00000010
_GameInputKindMouse _GameInputKind = 0x00000020
_GameInputKindTouch _GameInputKind = 0x00000100
_GameInputKindMotion _GameInputKind = 0x00001000
_GameInputKindArcadeStick _GameInputKind = 0x00010000
_GameInputKindFlightStick _GameInputKind = 0x00020000
_GameInputKindGamepad _GameInputKind = 0x00040000
_GameInputKindRacingWheel _GameInputKind = 0x00080000
_GameInputKindUiNavigation _GameInputKind = 0x01000000
_GameInputKindAny _GameInputKind = 0x0FFFFFFF
)
type _GameInputGamepadState struct {
buttons _GameInputGamepadButtons
leftTrigger float32
rightTrigger float32
leftThumbstickX float32
leftThumbstickY float32
rightThumbstickX float32
rightThumbstickY float32
}
type _GameInputRumbleParams struct {
lowFrequency float32
highFrequency float32
leftTrigger float32
rightTrigger float32
}
func _GameInputCreate() (*_IGameInput, error) {
var gameInput *_IGameInput
r, _, _ := procGameInputCreate.Call(uintptr(unsafe.Pointer(&gameInput)))
if uint32(r) != uint32(windows.S_OK) {
return nil, fmt.Errorf("gamepad: GameInputCreate failed: %w", handleError(windows.Handle(uint32(r))))
}
return gameInput, nil
}
type _IGameInput struct {
vtbl *_IGameInput_Vtbl
}
type _IGameInput_Vtbl struct {
QueryInterface uintptr
AddRef uintptr
Release uintptr
GetCurrentTimestamp uintptr
GetCurrentReading uintptr
GetNextReading uintptr
GetPreviousReading uintptr
GetTemporalReading uintptr
RegisterReadingCallback uintptr
RegisterDeviceCallback uintptr
RegisterGuideButtonCallback uintptr
RegisterKeyboardLayoutCallback uintptr
StopCallback uintptr
UnregisterCallback uintptr
CreateDispatcher uintptr
CreateAggregateDevice uintptr
FindDeviceFromId uintptr
FindDeviceFromObject uintptr
FindDeviceFromPlatformHandle uintptr
FindDeviceFromPlatformString uintptr
EnableOemDeviceSupport uintptr
SetFocusPolicy uintptr
}
func (i *_IGameInput) GetCurrentReading(inputKind _GameInputKind, device *_IGameInputDevice) (*_IGameInputReading, error) {
var reading *_IGameInputReading
r, _, _ := syscall.Syscall6(i.vtbl.GetCurrentReading, 4, uintptr(unsafe.Pointer(i)),
uintptr(inputKind), uintptr(unsafe.Pointer(device)), uintptr(unsafe.Pointer(&reading)),
0, 0)
runtime.KeepAlive(device)
if uint32(r) != uint32(windows.S_OK) {
return nil, fmt.Errorf("gamepad: IGameInput::GetCurrentReading failed: %w", handleError(windows.Handle(uint32(r))))
}
return reading, nil
}
func (i *_IGameInput) RegisterDeviceCallback(device *_IGameInputDevice,
inputKind _GameInputKind,
statusFilter _GameInputDeviceStatus,
enumerationKind _GameInputEnumerationKind,
context unsafe.Pointer,
callbackFunc uintptr,
callbackToken *_GameInputCallbackToken) error {
r, _, _ := syscall.Syscall9(i.vtbl.RegisterDeviceCallback, 8, uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(device)), uintptr(inputKind), uintptr(statusFilter),
uintptr(enumerationKind), uintptr(context), callbackFunc,
uintptr(unsafe.Pointer(callbackToken)), 0)
runtime.KeepAlive(device)
runtime.KeepAlive(callbackToken)
if uint32(r) != uint32(windows.S_OK) {
return fmt.Errorf("gamepad: IGameInput::RegisterDeviceCallback failed: %w", handleError(windows.Handle(uint32(r))))
}
return nil
}
type _IGameInputDevice struct {
vtbl *_IGameInputDevice_Vtbl
}
type _IGameInputDevice_Vtbl struct {
QueryInterface uintptr
AddRef uintptr
Release uintptr
GetDeviceInfo uintptr
GetDeviceStatus uintptr
GetBatteryState uintptr
CreateForceFeedbackEffect uintptr
IsForceFeedbackMotorPoweredOn uintptr
SetForceFeedbackMotorGain uintptr
SetHapticMotorState uintptr
SetRumbleState uintptr
SetInputSynchronizationState uintptr
SendInputSynchronizationHint uintptr
PowerOff uintptr
CreateRawDeviceReport uintptr
GetRawDeviceFeature uintptr
SetRawDeviceFeature uintptr
SendRawDeviceOutput uintptr
ExecuteRawDeviceIoControl uintptr
AcquireExclusiveRawDeviceAccess uintptr
ReleaseExclusiveRawDeviceAccess uintptr
}
func (i *_IGameInputDevice) SetRumbleState(params *_GameInputRumbleParams, timestamp uint64) {
_, _, _ = syscall.Syscall(i.vtbl.SetRumbleState, 3, uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(params)), uintptr(timestamp))
runtime.KeepAlive(params)
}
type _IGameInputReading struct {
vtbl *_IGameInputReading_Vtbl
}
type _IGameInputReading_Vtbl struct {
QueryInterface uintptr
AddRef uintptr
Release uintptr
GetInputKind uintptr
GetSequenceNumber uintptr
GetTimestamp uintptr
GetDevice uintptr
GetRawReport uintptr
GetControllerAxisCount uintptr
GetControllerAxisState uintptr
GetControllerButtonCount uintptr
GetControllerButtonState uintptr
GetControllerSwitchCount uintptr
GetControllerSwitchState uintptr
GetKeyCount uintptr
GetKeyState uintptr
GetMouseState uintptr
GetTouchCount uintptr
GetTouchState uintptr
GetMotionState uintptr
GetArcadeStickState uintptr
GetFlightStickState uintptr
GetGamepadState uintptr
GetRacingWheelState uintptr
GetUiNavigationState uintptr
}
func (i *_IGameInputReading) GetGamepadState() (_GameInputGamepadState, bool) {
var state _GameInputGamepadState
r, _, _ := syscall.Syscall(i.vtbl.GetGamepadState, 2, uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(&state)), 0)
return state, int32(r) != 0
}
func (i *_IGameInputReading) Release() uint32 {
r, _, _ := syscall.Syscall(i.vtbl.Release, 1, uintptr(unsafe.Pointer(i)), 0, 0)
return uint32(r)
}