1import sys 2from ctypes import (Structure, Union, c_int, c_char_p, c_void_p, c_float, 3 POINTER, create_string_buffer) 4from .dll import _bind 5from .dll import version as sdl_version 6from .stdinc import SDL_bool, Sint16, Uint32, Uint16, Uint8 7from .joystick import (SDL_JoystickGUID, SDL_Joystick, SDL_JoystickID, 8 SDL_JoystickGetGUIDString) 9from .rwops import SDL_RWops, SDL_RWFromFile 10from .sensor import SDL_SensorType 11 12__all__ = [ 13 # Structs & Opaque Types 14 "SDL_GameController", "SDL_GameControllerButtonBind", 15 16 # Enums 17 "SDL_GameControllerType", 18 "SDL_CONTROLLER_TYPE_UNKNOWN", "SDL_CONTROLLER_TYPE_XBOX360", 19 "SDL_CONTROLLER_TYPE_XBOXONE", "SDL_CONTROLLER_TYPE_PS3", 20 "SDL_CONTROLLER_TYPE_PS4", "SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO", 21 "SDL_CONTROLLER_TYPE_VIRTUAL", "SDL_CONTROLLER_TYPE_PS5", 22 "SDL_CONTROLLER_TYPE_AMAZON_LUNA", "SDL_CONTROLLER_TYPE_GOOGLE_STADIA", 23 24 "SDL_GameControllerBindType", 25 "SDL_CONTROLLER_BINDTYPE_NONE", "SDL_CONTROLLER_BINDTYPE_BUTTON", 26 "SDL_CONTROLLER_BINDTYPE_AXIS", "SDL_CONTROLLER_BINDTYPE_HAT", 27 28 "SDL_GameControllerAxis", 29 "SDL_CONTROLLER_AXIS_INVALID", "SDL_CONTROLLER_AXIS_LEFTX", 30 "SDL_CONTROLLER_AXIS_LEFTY", "SDL_CONTROLLER_AXIS_RIGHTX", 31 "SDL_CONTROLLER_AXIS_RIGHTY", "SDL_CONTROLLER_AXIS_TRIGGERLEFT", 32 "SDL_CONTROLLER_AXIS_TRIGGERRIGHT", "SDL_CONTROLLER_AXIS_MAX", 33 34 "SDL_GameControllerButton", 35 "SDL_CONTROLLER_BUTTON_INVALID", "SDL_CONTROLLER_BUTTON_A", 36 "SDL_CONTROLLER_BUTTON_B", "SDL_CONTROLLER_BUTTON_X", 37 "SDL_CONTROLLER_BUTTON_Y", "SDL_CONTROLLER_BUTTON_BACK", 38 "SDL_CONTROLLER_BUTTON_GUIDE", "SDL_CONTROLLER_BUTTON_START", 39 "SDL_CONTROLLER_BUTTON_LEFTSTICK", "SDL_CONTROLLER_BUTTON_RIGHTSTICK", 40 "SDL_CONTROLLER_BUTTON_LEFTSHOULDER", 41 "SDL_CONTROLLER_BUTTON_RIGHTSHOULDER", 42 "SDL_CONTROLLER_BUTTON_DPAD_UP", "SDL_CONTROLLER_BUTTON_DPAD_DOWN", 43 "SDL_CONTROLLER_BUTTON_DPAD_LEFT", "SDL_CONTROLLER_BUTTON_DPAD_RIGHT", 44 "SDL_CONTROLLER_BUTTON_MISC1", "SDL_CONTROLLER_BUTTON_PADDLE1", 45 "SDL_CONTROLLER_BUTTON_PADDLE2", "SDL_CONTROLLER_BUTTON_PADDLE3", 46 "SDL_CONTROLLER_BUTTON_PADDLE4", "SDL_CONTROLLER_BUTTON_TOUCHPAD", 47 "SDL_CONTROLLER_BUTTON_MAX", 48 49 # Macro Functions 50 "SDL_GameControllerAddMappingsFromFile", 51 52 # Functions 53 "SDL_GameControllerAddMappingsFromRW", "SDL_GameControllerAddMapping", 54 "SDL_GameControllerNumMappings", "SDL_GameControllerMappingForIndex", 55 "SDL_GameControllerMappingForGUID", "SDL_GameControllerMapping", 56 "SDL_IsGameController", "SDL_GameControllerNameForIndex", 57 "SDL_GameControllerTypeForIndex", "SDL_GameControllerMappingForDeviceIndex", 58 "SDL_GameControllerOpen", "SDL_GameControllerFromInstanceID", 59 "SDL_GameControllerFromPlayerIndex", "SDL_GameControllerName", 60 "SDL_GameControllerGetType", 61 "SDL_GameControllerGetPlayerIndex", "SDL_GameControllerSetPlayerIndex", 62 "SDL_GameControllerGetVendor", "SDL_GameControllerGetProduct", 63 "SDL_GameControllerGetProductVersion", "SDL_GameControllerGetSerial", 64 "SDL_GameControllerGetAttached", "SDL_GameControllerGetJoystick", 65 "SDL_GameControllerEventState", "SDL_GameControllerUpdate", 66 "SDL_GameControllerGetAxisFromString", "SDL_GameControllerGetStringForAxis", 67 "SDL_GameControllerGetBindForAxis", "SDL_GameControllerHasAxis", 68 "SDL_GameControllerGetAxis", 69 "SDL_GameControllerGetButtonFromString", 70 "SDL_GameControllerGetStringForButton", 71 "SDL_GameControllerGetBindForButton", "SDL_GameControllerHasButton", 72 "SDL_GameControllerGetButton", 73 "SDL_GameControllerGetNumTouchpads", 74 "SDL_GameControllerGetNumTouchpadFingers", 75 "SDL_GameControllerGetTouchpadFinger", 76 "SDL_GameControllerHasSensor", "SDL_GameControllerSetSensorEnabled", 77 "SDL_GameControllerIsSensorEnabled", 78 "SDL_GameControllerGetSensorDataRate", "SDL_GameControllerGetSensorData", 79 "SDL_GameControllerRumble", "SDL_GameControllerRumbleTriggers", 80 "SDL_GameControllerHasLED", "SDL_GameControllerSetLED", 81 "SDL_GameControllerSendEffect", 82 "SDL_GameControllerClose" 83] 84 85 86class SDL_GameController(c_void_p): 87 pass 88 89 90SDL_GameControllerBindType = c_int 91 92SDL_CONTROLLER_BINDTYPE_NONE = 0 93SDL_CONTROLLER_BINDTYPE_BUTTON = 1 94SDL_CONTROLLER_BINDTYPE_AXIS = 2 95SDL_CONTROLLER_BINDTYPE_HAT = 3 96 97 98SDL_GameControllerType = c_int 99 100SDL_CONTROLLER_TYPE_UNKNOWN = 0 101SDL_CONTROLLER_TYPE_XBOX360 = 1 102SDL_CONTROLLER_TYPE_XBOXONE = 2 103SDL_CONTROLLER_TYPE_PS3 = 3 104SDL_CONTROLLER_TYPE_PS4 = 4 105SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO = 5 106SDL_CONTROLLER_TYPE_VIRTUAL = 6 107SDL_CONTROLLER_TYPE_PS5 = 7 108SDL_CONTROLLER_TYPE_AMAZON_LUNA = 8 109SDL_CONTROLLER_TYPE_GOOGLE_STADIA = 9 110 111 112class _gchat(Structure): 113 _fields_ = [("hat", c_int), ("hat_mask", c_int)] 114 115class _gcvalue(Union): 116 _fields_ = [("button", c_int), ("axis", c_int), ("hat", _gchat)] 117 118class SDL_GameControllerButtonBind(Structure): 119 _fields_ = [("bindType", SDL_GameControllerBindType), ("value", _gcvalue)] 120 121 122SDL_GameControllerAddMapping = _bind("SDL_GameControllerAddMapping", [c_char_p], c_int) 123SDL_GameControllerMapping = _bind("SDL_GameControllerMapping", [POINTER(SDL_GameController)], c_char_p) 124SDL_IsGameController = _bind("SDL_IsGameController", [c_int], SDL_bool) 125SDL_GameControllerNameForIndex = _bind("SDL_GameControllerNameForIndex", [c_int], c_char_p) 126SDL_GameControllerTypeForIndex = _bind("SDL_GameControllerTypeForIndex", [c_int], SDL_GameControllerType, added='2.0.12') 127SDL_GameControllerOpen = _bind("SDL_GameControllerOpen", [c_int], POINTER(SDL_GameController)) 128SDL_GameControllerName = _bind("SDL_GameControllerName", [POINTER(SDL_GameController)], c_char_p) 129SDL_GameControllerGetType = _bind("SDL_GameControllerGetType", [POINTER(SDL_GameController)], SDL_GameControllerType, added='2.0.12') 130SDL_GameControllerGetAttached = _bind("SDL_GameControllerGetAttached", [POINTER(SDL_GameController)], SDL_bool) 131SDL_GameControllerGetJoystick = _bind("SDL_GameControllerGetJoystick", [POINTER(SDL_GameController)], POINTER(SDL_Joystick)) 132SDL_GameControllerEventState = _bind("SDL_GameControllerEventState", [c_int], c_int) 133SDL_GameControllerUpdate = _bind("SDL_GameControllerUpdate") 134 135 136SDL_GameControllerAxis = c_int 137 138SDL_CONTROLLER_AXIS_INVALID = -1 139SDL_CONTROLLER_AXIS_LEFTX = 0 140SDL_CONTROLLER_AXIS_LEFTY = 1 141SDL_CONTROLLER_AXIS_RIGHTX = 2 142SDL_CONTROLLER_AXIS_RIGHTY = 3 143SDL_CONTROLLER_AXIS_TRIGGERLEFT = 4 144SDL_CONTROLLER_AXIS_TRIGGERRIGHT = 5 145SDL_CONTROLLER_AXIS_MAX = 6 146 147 148SDL_GameControllerGetAxisFromString = _bind("SDL_GameControllerGetAxisFromString", [c_char_p], SDL_GameControllerAxis) 149SDL_GameControllerGetStringForAxis = _bind("SDL_GameControllerGetStringForAxis", [SDL_GameControllerAxis], c_char_p) 150SDL_GameControllerGetBindForAxis = _bind("SDL_GameControllerGetBindForAxis", [POINTER(SDL_GameController), SDL_GameControllerAxis], SDL_GameControllerButtonBind) 151SDL_GameControllerHasAxis = _bind("SDL_GameControllerHasAxis", [POINTER(SDL_GameController), SDL_GameControllerAxis], SDL_bool, added='2.0.14') 152SDL_GameControllerGetAxis = _bind("SDL_GameControllerGetAxis", [POINTER(SDL_GameController), SDL_GameControllerAxis], Sint16) 153 154 155SDL_GameControllerButton = c_int 156 157SDL_CONTROLLER_BUTTON_INVALID = -1 158SDL_CONTROLLER_BUTTON_A = 0 159SDL_CONTROLLER_BUTTON_B = 1 160SDL_CONTROLLER_BUTTON_X = 2 161SDL_CONTROLLER_BUTTON_Y = 3 162SDL_CONTROLLER_BUTTON_BACK = 4 163SDL_CONTROLLER_BUTTON_GUIDE = 5 164SDL_CONTROLLER_BUTTON_START = 6 165SDL_CONTROLLER_BUTTON_LEFTSTICK = 7 166SDL_CONTROLLER_BUTTON_RIGHTSTICK = 8 167SDL_CONTROLLER_BUTTON_LEFTSHOULDER = 9 168SDL_CONTROLLER_BUTTON_RIGHTSHOULDER = 10 169SDL_CONTROLLER_BUTTON_DPAD_UP = 11 170SDL_CONTROLLER_BUTTON_DPAD_DOWN = 12 171SDL_CONTROLLER_BUTTON_DPAD_LEFT = 13 172SDL_CONTROLLER_BUTTON_DPAD_RIGHT = 14 173SDL_CONTROLLER_BUTTON_MISC1 = 15 174SDL_CONTROLLER_BUTTON_PADDLE1 = 16 175SDL_CONTROLLER_BUTTON_PADDLE2 = 17 176SDL_CONTROLLER_BUTTON_PADDLE3 = 18 177SDL_CONTROLLER_BUTTON_PADDLE4 = 19 178SDL_CONTROLLER_BUTTON_TOUCHPAD = 20 179SDL_CONTROLLER_BUTTON_MAX = 21 180if sdl_version < 2014: 181 SDL_CONTROLLER_BUTTON_MAX = 15 # For backwards compatibility 182 183 184SDL_GameControllerGetButtonFromString = _bind("SDL_GameControllerGetButtonFromString", [c_char_p], SDL_GameControllerButton) 185SDL_GameControllerGetStringForButton = _bind("SDL_GameControllerGetStringForButton", [SDL_GameControllerButton], c_char_p) 186SDL_GameControllerGetBindForButton = _bind("SDL_GameControllerGetBindForButton", [POINTER(SDL_GameController), SDL_GameControllerButton], SDL_GameControllerButtonBind) 187SDL_GameControllerHasButton = _bind("SDL_GameControllerHasButton", [POINTER(SDL_GameController), SDL_GameControllerButton], SDL_bool, added='2.0.14') 188SDL_GameControllerGetButton = _bind("SDL_GameControllerGetButton", [POINTER(SDL_GameController), SDL_GameControllerButton], Uint8) 189SDL_GameControllerGetNumTouchpads = _bind("SDL_GameControllerGetNumTouchpads", [POINTER(SDL_GameController)], c_int, added='2.0.14') 190SDL_GameControllerGetNumTouchpadFingers = _bind("SDL_GameControllerGetNumTouchpadFingers", [POINTER(SDL_GameController), c_int], c_int, added='2.0.14') 191SDL_GameControllerGetTouchpadFinger = _bind("SDL_GameControllerGetTouchpadFinger", [POINTER(SDL_GameController), c_int, c_int, POINTER(Uint8), POINTER(c_float), POINTER(c_float), POINTER(c_float)], c_int, added='2.0.14') 192SDL_GameControllerHasSensor = _bind("SDL_GameControllerHasSensor", [POINTER(SDL_GameController), SDL_SensorType], SDL_bool, added='2.0.14') 193SDL_GameControllerSetSensorEnabled = _bind("SDL_GameControllerSetSensorEnabled", [POINTER(SDL_GameController), SDL_SensorType, SDL_bool], c_int, added='2.0.14') 194SDL_GameControllerIsSensorEnabled = _bind("SDL_GameControllerIsSensorEnabled", [POINTER(SDL_GameController), SDL_SensorType], SDL_bool, added='2.0.14') 195SDL_GameControllerGetSensorDataRate = _bind("SDL_GameControllerGetSensorDataRate", [POINTER(SDL_GameController), SDL_SensorType], c_float, added='2.0.16') 196# TODO: Read how GetSensorData is implemented to figure out how the # of floats is determined 197SDL_GameControllerGetSensorData = _bind("SDL_GameControllerGetSensorData", [POINTER(SDL_GameController), SDL_SensorType, POINTER(c_float), c_int], c_int, added='2.0.14') 198SDL_GameControllerClose = _bind("SDL_GameControllerClose", [POINTER(SDL_GameController)]) 199SDL_GameControllerAddMappingsFromRW = _bind("SDL_GameControllerAddMappingsFromRW", [POINTER(SDL_RWops), c_int], c_int) 200SDL_GameControllerAddMappingsFromFile = lambda fname: SDL_GameControllerAddMappingsFromRW(SDL_RWFromFile(fname, b"rb"), 1) 201SDL_GameControllerFromInstanceID = _bind("SDL_GameControllerFromInstanceID", [SDL_JoystickID], POINTER(SDL_GameController)) 202SDL_GameControllerFromPlayerIndex = _bind("SDL_GameControllerFromPlayerIndex", [c_int], POINTER(SDL_GameController), added='2.0.12') 203SDL_GameControllerGetPlayerIndex = _bind("SDL_GameControllerGetPlayerIndex", [POINTER(SDL_GameController)], c_int, added='2.0.9') 204SDL_GameControllerSetPlayerIndex = _bind("SDL_GameControllerSetPlayerIndex", [POINTER(SDL_GameController), c_int], added='2.0.12') 205SDL_GameControllerGetVendor = _bind("SDL_GameControllerGetVendor", [POINTER(SDL_GameController)], Uint16, added='2.0.6') 206SDL_GameControllerGetProduct = _bind("SDL_GameControllerGetProduct", [POINTER(SDL_GameController)], Uint16, added='2.0.6') 207SDL_GameControllerGetProductVersion = _bind("SDL_GameControllerGetProductVersion", [POINTER(SDL_GameController)], Uint16, added='2.0.6') 208SDL_GameControllerGetSerial = _bind("SDL_GameControllerGetSerial", [POINTER(SDL_GameController)], c_char_p, added='2.0.14') 209SDL_GameControllerNumMappings = _bind("SDL_GameControllerNumMappings", None, c_int, added='2.0.6') 210SDL_GameControllerMappingForIndex = _bind("SDL_GameControllerMappingForIndex", [c_int], c_char_p, added='2.0.6') 211SDL_GameControllerMappingForDeviceIndex = _bind("SDL_GameControllerMappingForDeviceIndex", [c_int], c_char_p, added='2.0.9') 212SDL_GameControllerRumble = _bind("SDL_GameControllerRumble", [POINTER(SDL_GameController), Uint16, Uint16, Uint32], c_int, added='2.0.9') 213SDL_GameControllerRumbleTriggers = _bind("SDL_GameControllerRumbleTriggers", [POINTER(SDL_GameController), Uint16, Uint16, Uint32], c_int, added='2.0.14') 214SDL_GameControllerHasLED = _bind("SDL_GameControllerHasLED", [POINTER(SDL_GameController)], SDL_bool, added='2.0.14') 215SDL_GameControllerSetLED = _bind("SDL_GameControllerSetLED", [POINTER(SDL_GameController), Uint8, Uint8, Uint8], c_int, added='2.0.14') 216SDL_GameControllerSendEffect = _bind("SDL_GameControllerSendEffect", [POINTER(SDL_GameController), c_void_p, c_int], c_int, added='2.0.16') 217 218# Reimplemented w/ other functions due to crash-causing ctypes bug (fixed in 3.8) 219if sys.version_info >= (3, 8, 0, 'final'): 220 SDL_GameControllerMappingForGUID = _bind("SDL_GameControllerMappingForGUID", [SDL_JoystickGUID], c_char_p) 221else: 222 def SDL_GameControllerMappingForGUID(guid): 223 buff = create_string_buffer(33) 224 SDL_JoystickGetGUIDString(guid, buff, 33) # Get GUID string 225 guid_str = buff.value 226 # Iterate over controller mappings and look for a GUID match 227 # Note: iterates in reverse, so user-defined mappings are checked first 228 num = SDL_GameControllerNumMappings() 229 for i in range(num - 1, -1, -1): 230 m = SDL_GameControllerMappingForIndex(i) 231 if m.split(b',')[0] == guid_str: 232 return m 233 return None 234