21 #include "../../SDL_internal.h" 34 #include "../SDL_sysjoystick.h" 35 #include "../SDL_joystick_c.h" 36 #include "../steam/SDL_steamcontroller.h" 39 #if !SDL_EVENTS_DISABLED 40 #include "../../events/SDL_events_c.h" 44 #import <CoreMotion/CoreMotion.h> 47 #ifdef SDL_JOYSTICK_MFI 48 #import <GameController/GameController.h> 50 static id connectObserver = nil;
51 static id disconnectObserver = nil;
71 while (i < device_index) {
75 device = device->
next;
85 #ifdef SDL_JOYSTICK_MFI 89 device->
controller = (__bridge GCController *) CFBridgingRetain(controller);
91 if (controller.vendorName) {
92 name = controller.vendorName.UTF8String;
112 if (controller.extendedGamepad) {
114 }
else if (controller.gamepad) {
118 else if (controller.microGamepad) {
124 if (controller.extendedGamepad) {
128 }
else if (controller.gamepad) {
134 else if (controller.microGamepad) {
145 controller.playerIndex = -1;
158 if (controller && !controller.extendedGamepad && !controller.gamepad && controller.microGamepad) {
164 while (device !=
NULL) {
168 device = device->
next;
172 if (device ==
NULL) {
192 }
else if (controller) {
196 if (deviceList ==
NULL) {
201 lastdevice = lastdevice->
next;
218 if (device ==
NULL) {
224 while (item !=
NULL) {
225 if (item == device) {
235 }
else if (device == deviceList) {
236 deviceList = device->
next;
243 #ifdef SDL_JOYSTICK_MFI 249 controller.controllerPausedHandler = nil;
267 SDL_AppleTVRemoteRotationHintChanged(
void *udata,
const char *
name,
const char *oldValue,
const char *newValue)
269 BOOL allowRotation = newValue !=
NULL && *newValue !=
'0';
274 controller.microGamepad.allowsRotation = allowRotation;
284 if (device ==
NULL) {
296 if (deviceList ==
NULL) {
301 lastdevice = lastdevice->
next;
317 for (item = deviceList;
item; item = item->
next) {
333 NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
345 #ifdef SDL_JOYSTICK_MFI 347 if (![GCController
class]) {
357 SDL_AppleTVRemoteRotationHintChanged,
NULL);
360 connectObserver = [center addObserverForName:GCControllerDidConnectNotification
363 usingBlock:^(NSNotification *note) {
364 GCController *controller = note.object;
365 SDL_SYS_AddJoystickDevice(controller, SDL_FALSE);
368 disconnectObserver = [center addObserverForName:GCControllerDidDisconnectNotification
371 usingBlock:^(NSNotification *note) {
372 GCController *controller = note.object;
373 SDL_JoystickDeviceItem *device = deviceList;
374 while (device != NULL) {
375 if (device->controller == controller) {
376 SDL_SYS_RemoveJoystickDevice(device);
379 device = device->next;
405 return device ? device->
name :
"Unknown";
424 if (device ==
NULL) {
425 return SDL_SetError(
"Could not open Joystick: no hardware device for the specified index");
428 joystick->hwdata =
device;
431 joystick->naxes = device->
naxes;
432 joystick->nhats = device->
nhats;
433 joystick->nbuttons = device->
nbuttons;
434 joystick->nballs = 0;
447 [motionManager startAccelerometerUpdates];
450 #ifdef SDL_JOYSTICK_MFI 452 controller.controllerPausedHandler = ^(GCController *
c) {
453 if (joystick->hwdata) {
454 ++joystick->hwdata->num_pause_presses;
471 return joystick->hwdata !=
NULL;
479 const SInt16 maxsint16 = 0x7FFF;
480 CMAcceleration accel;
518 #ifdef SDL_JOYSTICK_MFI 520 SDL_SYS_MFIJoystickHatStateForDPad(GCControllerDirectionPad *dpad)
524 if (dpad.up.isPressed) {
526 }
else if (dpad.down.isPressed) {
530 if (dpad.left.isPressed) {
532 }
else if (dpad.right.isPressed) {
549 GCController *
controller = joystick->hwdata->controller;
552 int updateplayerindex = 0;
554 if (controller.extendedGamepad) {
555 GCExtendedGamepad *gamepad = controller.extendedGamepad;
559 (
Sint16) (gamepad.leftThumbstick.xAxis.value * 32767),
560 (
Sint16) (gamepad.leftThumbstick.yAxis.value * -32767),
561 (
Sint16) ((gamepad.leftTrigger.value * 65535) - 32768),
562 (
Sint16) (gamepad.rightThumbstick.xAxis.value * 32767),
563 (
Sint16) (gamepad.rightThumbstick.yAxis.value * -32767),
564 (
Sint16) ((gamepad.rightTrigger.value * 65535) - 32768),
569 gamepad.buttonA.isPressed, gamepad.buttonB.isPressed,
570 gamepad.buttonX.isPressed, gamepad.buttonY.isPressed,
571 gamepad.leftShoulder.isPressed,
572 gamepad.rightShoulder.isPressed,
575 hatstate = SDL_SYS_MFIJoystickHatStateForDPad(gamepad.dpad);
581 if ((i != 2 && i != 5) || axes[i] != -32768) {
582 updateplayerindex |= (joystick->axes[i].value != axes[i]);
588 updateplayerindex |= (joystick->buttons[i] != buttons[i]);
591 }
else if (controller.gamepad) {
592 GCGamepad *gamepad = controller.gamepad;
596 gamepad.buttonA.isPressed, gamepad.buttonB.isPressed,
597 gamepad.buttonX.isPressed, gamepad.buttonY.isPressed,
598 gamepad.leftShoulder.isPressed,
599 gamepad.rightShoulder.isPressed,
602 hatstate = SDL_SYS_MFIJoystickHatStateForDPad(gamepad.dpad);
605 updateplayerindex |= (joystick->buttons[i] != buttons[i]);
610 else if (controller.microGamepad) {
611 GCMicroGamepad *gamepad = controller.microGamepad;
614 (
Sint16) (gamepad.dpad.xAxis.value * 32767),
615 (
Sint16) (gamepad.dpad.yAxis.value * -32767),
619 updateplayerindex |= (joystick->axes[i].value != axes[i]);
624 gamepad.buttonA.isPressed,
625 gamepad.buttonX.isPressed,
629 updateplayerindex |= (joystick->buttons[i] != buttons[i]);
635 if (joystick->nhats > 0) {
636 updateplayerindex |= (joystick->hats[0] != hatstate);
640 for (i = 0; i < joystick->hwdata->num_pause_presses; i++) {
642 Uint8 pausebutton = joystick->nbuttons - 1;
647 updateplayerindex = YES;
650 joystick->hwdata->num_pause_presses = 0;
652 if (updateplayerindex && controller.playerIndex == -1) {
653 BOOL usedPlayerIndexSlots[4] = {NO, NO, NO, NO};
657 if (
c != controller &&
c.playerIndex >= 0) {
666 if (!usedPlayerIndexSlots[i]) {
667 controller.playerIndex =
i;
686 if (device ==
NULL) {
708 if (device ==
NULL) {
717 [motionManager stopAccelerometerUpdates];
720 #ifdef SDL_JOYSTICK_MFI 722 controller.controllerPausedHandler = nil;
723 controller.playerIndex = -1;
737 #ifdef SDL_JOYSTICK_MFI 738 NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
740 if (connectObserver) {
741 [center removeObserver:connectObserver name:GCControllerDidConnectNotification object:nil];
742 connectObserver = nil;
745 if (disconnectObserver) {
746 [center removeObserver:disconnectObserver name:GCControllerDidDisconnectNotification object:nil];
747 disconnectObserver = nil;
752 SDL_AppleTVRemoteRotationHintChanged,
NULL);
756 while (deviceList !=
NULL) {
787 if (joystick->hwdata) {
788 guid = joystick->hwdata->guid;
#define SDL_HINT_TV_REMOTE_AS_JOYSTICK
A variable controlling whether the Android / tvOS remotes should be listed as joystick devices...
void SDL_UpdateSteamControllers(void)
void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
int SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value)
void SDL_InitSteamControllers(SteamControllerConnectedCallback_t connectedCallback, SteamControllerDisconnectedCallback_t disconnectedCallback)
static void SteamControllerDisconnectedCallback(int device_instance)
void SDL_QuitSteamControllers(void)
static SDL_JoystickDeviceItem * deviceList
static void SDL_SYS_MFIJoystickUpdate(SDL_Joystick *joystick)
#define SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION
A variable controlling whether the Apple TV remote's joystick axes will automatically match the rotat...
int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
static const char * accelerometerName
struct joystick_hwdata * next
void SDL_SYS_JoystickQuit(void)
static SDL_JoystickDeviceItem * GetDeviceForIndex(int device_index)
int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
GLuint const GLchar * name
#define SDL_GetHintBoolean
static SDL_AudioDeviceID device
#define SDL_HINT_ACCELEROMETER_AS_JOYSTICK
A variable controlling whether the Android / iOS built-in accelerometer should be listed as a joystic...
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
static void SDL_SYS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controller)
void SDL_PrivateJoystickAdded(int device_index)
const char * SDL_SYS_JoystickNameForDeviceIndex(int device_index)
void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick *joystick)
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
static SDL_bool SteamControllerConnectedCallback(const char *name, SDL_JoystickGUID guid, int *device_instance)
int SDL_SYS_JoystickInit(void)
#define SDL_IPHONE_MAX_GFORCE
void SDL_UpdateSteamController(SDL_Joystick *joystick)
int SDL_SYS_NumJoysticks(void)
SDL_bool m_bSteamController
static void SDL_SYS_AccelerometerUpdate(SDL_Joystick *joystick)
static SDL_JoystickID instancecounter
int SDL_AppleTVRemoteOpenedAsJoystick
struct SDL_joylist_item * item
#define SDL_AddHintCallback
#define SDL_DelHintCallback
static SDL_JoystickDeviceItem * SDL_SYS_RemoveJoystickDevice(SDL_JoystickDeviceItem *device)
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
void SDL_GetSteamControllerInputs(int *nbuttons, int *naxes, int *nhats)
#define SDL_arraysize(array)
int SDL_SYS_JoystickOpen(SDL_Joystick *joystick, int device_index)
void SDL_SYS_JoystickClose(SDL_Joystick *joystick)
static void SDL_SYS_AddJoystickDevice(GCController *controller, SDL_bool accelerometer)
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID(int device_index)
GCController __unsafe_unretained * controller
void SDL_SYS_JoystickDetect(void)
static CMMotionManager * motionManager