mirror of
https://github.com/encounter/SDL.git
synced 2025-12-08 21:17:45 +00:00
Added initial support for MFi game controllers on iOS.
This commit is contained in:
@@ -45,6 +45,10 @@ static const char *s_ControllerMappings [] =
|
||||
"25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,",
|
||||
"4c05c405000000000000504944564944,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
|
||||
#endif
|
||||
#if SDL_JOYSTICK_MFI
|
||||
"4d466947616d65706164010000000000,MFi Extended Gamepad,a:b0,b:b1,start:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,",
|
||||
"4d466947616d65706164020000000000,MFi Gamepad,a:b0,b:b1,start:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,",
|
||||
#endif
|
||||
#if defined(__MACOSX__)
|
||||
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
|
||||
"6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* Guide button doesn't seem to be sent in DInput mode. */
|
||||
|
||||
@@ -669,14 +669,17 @@ SDL_JoystickUpdate(void)
|
||||
int i;
|
||||
|
||||
/* Tell the app that everything is centered/unpressed... */
|
||||
for (i = 0; i < joystick->naxes; i++)
|
||||
for (i = 0; i < joystick->naxes; i++) {
|
||||
SDL_PrivateJoystickAxis(joystick, i, 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < joystick->nbuttons; i++)
|
||||
for (i = 0; i < joystick->nbuttons; i++) {
|
||||
SDL_PrivateJoystickButton(joystick, i, 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < joystick->nhats; i++)
|
||||
for (i = 0; i < joystick->nhats; i++) {
|
||||
SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED);
|
||||
}
|
||||
|
||||
joystick->force_recentering = SDL_FALSE;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
/* This is the iOS implementation of the SDL joystick API */
|
||||
#include "SDL_sysjoystick_c.h"
|
||||
|
||||
/* needed for SDL_IPHONE_MAX_GFORCE macro */
|
||||
#include "SDL_config_iphoneos.h"
|
||||
|
||||
#include "SDL_joystick.h"
|
||||
#include "SDL_hints.h"
|
||||
@@ -28,15 +32,221 @@
|
||||
#include "../SDL_sysjoystick.h"
|
||||
#include "../SDL_joystick_c.h"
|
||||
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#endif
|
||||
|
||||
#import <CoreMotion/CoreMotion.h>
|
||||
|
||||
/* needed for SDL_IPHONE_MAX_GFORCE macro */
|
||||
#import "SDL_config_iphoneos.h"
|
||||
#ifdef SDL_JOYSTICK_MFI
|
||||
#import <GameController/GameController.h>
|
||||
|
||||
const char *accelerometerName = "iOS Accelerometer";
|
||||
static id connectObserver = nil;
|
||||
static id disconnectObserver = nil;
|
||||
#endif /* SDL_JOYSTICK_MFI */
|
||||
|
||||
static const char *accelerometerName = "iOS Accelerometer";
|
||||
static CMMotionManager *motionManager = nil;
|
||||
|
||||
static SDL_JoystickDeviceItem *deviceList = NULL;
|
||||
|
||||
static int numjoysticks = 0;
|
||||
static SDL_JoystickID instancecounter = 0;
|
||||
|
||||
static SDL_JoystickDeviceItem *
|
||||
GetDeviceForIndex(int device_index)
|
||||
{
|
||||
SDL_JoystickDeviceItem *device = deviceList;
|
||||
int i = 0;
|
||||
|
||||
while (i < device_index) {
|
||||
if (device == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
device = device->next;
|
||||
i++;
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
static void
|
||||
SDL_SYS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controller)
|
||||
{
|
||||
#ifdef SDL_JOYSTICK_MFI
|
||||
const char *name = NULL;
|
||||
/* Explicitly retain the controller because SDL_JoystickDeviceItem is a
|
||||
* struct, and ARC doesn't work with structs. */
|
||||
device->controller = (__bridge GCController *) CFBridgingRetain(controller);
|
||||
|
||||
if (controller.vendorName) {
|
||||
name = controller.vendorName.UTF8String;
|
||||
}
|
||||
|
||||
if (!name) {
|
||||
name = "MFi Gamepad";
|
||||
}
|
||||
|
||||
device->name = SDL_strdup(name);
|
||||
|
||||
device->guid.data[0] = 'M';
|
||||
device->guid.data[1] = 'F';
|
||||
device->guid.data[2] = 'i';
|
||||
device->guid.data[3] = 'G';
|
||||
device->guid.data[4] = 'a';
|
||||
device->guid.data[5] = 'm';
|
||||
device->guid.data[6] = 'e';
|
||||
device->guid.data[7] = 'p';
|
||||
device->guid.data[8] = 'a';
|
||||
device->guid.data[9] = 'd';
|
||||
|
||||
if (controller.extendedGamepad) {
|
||||
device->guid.data[10] = 1;
|
||||
} else if (controller.gamepad) {
|
||||
device->guid.data[10] = 2;
|
||||
}
|
||||
|
||||
if (controller.extendedGamepad) {
|
||||
device->naxes = 6; /* 2 thumbsticks and 2 triggers */
|
||||
device->nhats = 1; /* d-pad */
|
||||
device->nbuttons = 7; /* ABXY, shoulder buttons, pause button */
|
||||
} else if (controller.gamepad) {
|
||||
device->naxes = 0; /* no traditional analog inputs */
|
||||
device->nhats = 1; /* d-pad */
|
||||
device->nbuttons = 7; /* ABXY, shoulder buttons, pause button */
|
||||
}
|
||||
/* TODO: Handle micro profiles on tvOS. */
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
SDL_SYS_AddJoystickDevice(GCController *controller, SDL_bool accelerometer)
|
||||
{
|
||||
SDL_JoystickDeviceItem *device = deviceList;
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
SDL_Event event;
|
||||
#endif
|
||||
|
||||
while (device != NULL) {
|
||||
if (device->controller == controller) {
|
||||
return;
|
||||
}
|
||||
device = device->next;
|
||||
}
|
||||
|
||||
device = (SDL_JoystickDeviceItem *) SDL_malloc(sizeof(SDL_JoystickDeviceItem));
|
||||
if (device == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_zerop(device);
|
||||
|
||||
device->accelerometer = accelerometer;
|
||||
device->instance_id = instancecounter++;
|
||||
|
||||
if (accelerometer) {
|
||||
device->name = SDL_strdup(accelerometerName);
|
||||
device->naxes = 3; /* Device acceleration in the x, y, and z axes. */
|
||||
device->nhats = 0;
|
||||
device->nbuttons = 0;
|
||||
|
||||
/* Use the accelerometer name as a GUID. */
|
||||
SDL_memcpy(&device->guid.data, device->name, SDL_min(sizeof(SDL_JoystickGUID), SDL_strlen(device->name)));
|
||||
} else if (controller) {
|
||||
SDL_SYS_AddMFIJoystickDevice(device, controller);
|
||||
}
|
||||
|
||||
if (deviceList == NULL) {
|
||||
deviceList = device;
|
||||
} else {
|
||||
SDL_JoystickDeviceItem *lastdevice = deviceList;
|
||||
while (lastdevice->next != NULL) {
|
||||
lastdevice = lastdevice->next;
|
||||
}
|
||||
lastdevice->next = device;
|
||||
}
|
||||
|
||||
++numjoysticks;
|
||||
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
event.type = SDL_JOYDEVICEADDED;
|
||||
|
||||
if (SDL_GetEventState(event.type) == SDL_ENABLE) {
|
||||
event.jdevice.which = numjoysticks - 1;
|
||||
if ((SDL_EventOK == NULL) ||
|
||||
(*SDL_EventOK)(SDL_EventOKParam, &event)) {
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
}
|
||||
#endif /* !SDL_EVENTS_DISABLED */
|
||||
}
|
||||
|
||||
SDL_JoystickDeviceItem *
|
||||
SDL_SYS_RemoveJoystickDevice(SDL_JoystickDeviceItem *device)
|
||||
{
|
||||
SDL_JoystickDeviceItem *prev = NULL;
|
||||
SDL_JoystickDeviceItem *next = NULL;
|
||||
SDL_JoystickDeviceItem *item = deviceList;
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
SDL_Event event;
|
||||
#endif
|
||||
|
||||
if (device == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
next = device->next;
|
||||
|
||||
while (item != NULL) {
|
||||
if (item == device) {
|
||||
break;
|
||||
}
|
||||
prev = item;
|
||||
item = item->next;
|
||||
}
|
||||
|
||||
/* Unlink the device item from the device list. */
|
||||
if (prev) {
|
||||
prev->next = device->next;
|
||||
} else if (device == deviceList) {
|
||||
deviceList = device->next;
|
||||
}
|
||||
|
||||
if (device->joystick) {
|
||||
device->joystick->hwdata = NULL;
|
||||
}
|
||||
|
||||
#ifdef SDL_JOYSTICK_MFI
|
||||
@autoreleasepool {
|
||||
if (device->controller) {
|
||||
/* The controller was explicitly retained in the struct, so it
|
||||
* should be explicitly released before freeing the struct. */
|
||||
GCController *controller = CFBridgingRelease((__bridge CFTypeRef)(device->controller));
|
||||
controller.controllerPausedHandler = nil;
|
||||
device->controller = nil;
|
||||
}
|
||||
}
|
||||
#endif /* SDL_JOYSTICK_MFI */
|
||||
|
||||
SDL_free(device->name);
|
||||
SDL_free(device);
|
||||
|
||||
--numjoysticks;
|
||||
|
||||
#if !SDL_EVENTS_DISABLED
|
||||
event.type = SDL_JOYDEVICEREMOVED;
|
||||
|
||||
if (SDL_GetEventState(event.type) == SDL_ENABLE) {
|
||||
event.jdevice.which = device->instance_id;
|
||||
if ((SDL_EventOK == NULL) ||
|
||||
(*SDL_EventOK)(SDL_EventOKParam, &event)) {
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
}
|
||||
#endif /* !SDL_EVENTS_DISABLED */
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
/* Function to scan the system for joysticks.
|
||||
* Joystick 0 should be the system default joystick.
|
||||
@@ -45,10 +255,48 @@ static int numjoysticks = 0;
|
||||
int
|
||||
SDL_SYS_JoystickInit(void)
|
||||
{
|
||||
const char *hint = SDL_GetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK);
|
||||
if (!hint || SDL_atoi(hint)) {
|
||||
/* Default behavior, accelerometer as joystick */
|
||||
numjoysticks = 1;
|
||||
@autoreleasepool {
|
||||
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
|
||||
const char *hint = SDL_GetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK);
|
||||
|
||||
if (!hint || SDL_atoi(hint)) {
|
||||
/* Default behavior, accelerometer as joystick */
|
||||
SDL_SYS_AddJoystickDevice(nil, SDL_TRUE);
|
||||
}
|
||||
|
||||
#ifdef SDL_JOYSTICK_MFI
|
||||
/* GameController.framework was added in iOS 7. */
|
||||
if (![GCController class]) {
|
||||
return numjoysticks;
|
||||
}
|
||||
|
||||
for (GCController *controller in [GCController controllers]) {
|
||||
SDL_SYS_AddJoystickDevice(controller, SDL_FALSE);
|
||||
}
|
||||
|
||||
connectObserver = [center addObserverForName:GCControllerDidConnectNotification
|
||||
object:nil
|
||||
queue:nil
|
||||
usingBlock:^(NSNotification *note) {
|
||||
GCController *controller = note.object;
|
||||
SDL_SYS_AddJoystickDevice(controller, SDL_FALSE);
|
||||
}];
|
||||
|
||||
disconnectObserver = [center addObserverForName:GCControllerDidDisconnectNotification
|
||||
object:nil
|
||||
queue:nil
|
||||
usingBlock:^(NSNotification *note) {
|
||||
GCController *controller = note.object;
|
||||
SDL_JoystickDeviceItem *device = deviceList;
|
||||
while (device != NULL) {
|
||||
if (device->controller == controller) {
|
||||
SDL_SYS_RemoveJoystickDevice(device);
|
||||
break;
|
||||
}
|
||||
device = device->next;
|
||||
}
|
||||
}];
|
||||
#endif /* SDL_JOYSTICK_MFI */
|
||||
}
|
||||
|
||||
return numjoysticks;
|
||||
@@ -67,13 +315,15 @@ void SDL_SYS_JoystickDetect()
|
||||
const char *
|
||||
SDL_SYS_JoystickNameForDeviceIndex(int device_index)
|
||||
{
|
||||
return accelerometerName;
|
||||
SDL_JoystickDeviceItem *device = GetDeviceForIndex(device_index);
|
||||
return device ? device->name : "Unknown";
|
||||
}
|
||||
|
||||
/* Function to perform the mapping from device index to the instance id for this index */
|
||||
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
|
||||
{
|
||||
return device_index;
|
||||
SDL_JoystickDeviceItem *device = GetDeviceForIndex(device_index);
|
||||
return device ? device->instance_id : 0;
|
||||
}
|
||||
|
||||
/* Function to open a joystick for use.
|
||||
@@ -84,19 +334,40 @@ SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
|
||||
int
|
||||
SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
|
||||
{
|
||||
joystick->naxes = 3;
|
||||
joystick->nhats = 0;
|
||||
SDL_JoystickDeviceItem *device = GetDeviceForIndex(device_index);
|
||||
if (device == NULL) {
|
||||
return SDL_SetError("Could not open Joystick: no hardware device for the specified index");
|
||||
}
|
||||
|
||||
joystick->hwdata = device;
|
||||
joystick->instance_id = device->instance_id;
|
||||
|
||||
joystick->naxes = device->naxes;
|
||||
joystick->nhats = device->nhats;
|
||||
joystick->nbuttons = device->nbuttons;
|
||||
joystick->nballs = 0;
|
||||
joystick->nbuttons = 0;
|
||||
|
||||
device->joystick = joystick;
|
||||
|
||||
@autoreleasepool {
|
||||
if (motionManager == nil) {
|
||||
motionManager = [[CMMotionManager alloc] init];
|
||||
}
|
||||
if (device->accelerometer) {
|
||||
if (motionManager == nil) {
|
||||
motionManager = [[CMMotionManager alloc] init];
|
||||
}
|
||||
|
||||
/* Shorter times between updates can significantly increase CPU usage. */
|
||||
motionManager.accelerometerUpdateInterval = 0.1;
|
||||
[motionManager startAccelerometerUpdates];
|
||||
/* Shorter times between updates can significantly increase CPU usage. */
|
||||
motionManager.accelerometerUpdateInterval = 0.1;
|
||||
[motionManager startAccelerometerUpdates];
|
||||
} else {
|
||||
#ifdef SDL_JOYSTICK_MFI
|
||||
GCController *controller = device->controller;
|
||||
controller.controllerPausedHandler = ^(GCController *controller) {
|
||||
if (joystick->hwdata) {
|
||||
++joystick->hwdata->num_pause_presses;
|
||||
}
|
||||
};
|
||||
#endif /* SDL_JOYSTICK_MFI */
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -105,7 +376,7 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
|
||||
/* Function to determine if this joystick is attached to the system right now */
|
||||
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
|
||||
{
|
||||
return SDL_TRUE;
|
||||
return joystick->hwdata != NULL;
|
||||
}
|
||||
|
||||
static void SDL_SYS_AccelerometerUpdate(SDL_Joystick * joystick)
|
||||
@@ -115,7 +386,7 @@ static void SDL_SYS_AccelerometerUpdate(SDL_Joystick * joystick)
|
||||
CMAcceleration accel;
|
||||
|
||||
@autoreleasepool {
|
||||
if (!motionManager.accelerometerActive) {
|
||||
if (!motionManager.isAccelerometerActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -144,9 +415,94 @@ static void SDL_SYS_AccelerometerUpdate(SDL_Joystick * joystick)
|
||||
accel.z = SDL_min(SDL_max(accel.z, -maxgforce), maxgforce);
|
||||
|
||||
/* pass in data mapped to range of SInt16 */
|
||||
SDL_PrivateJoystickAxis(joystick, 0, (accel.x / maxgforce) * maxsint16);
|
||||
SDL_PrivateJoystickAxis(joystick, 0, (accel.x / maxgforce) * maxsint16);
|
||||
SDL_PrivateJoystickAxis(joystick, 1, -(accel.y / maxgforce) * maxsint16);
|
||||
SDL_PrivateJoystickAxis(joystick, 2, (accel.z / maxgforce) * maxsint16);
|
||||
SDL_PrivateJoystickAxis(joystick, 2, (accel.z / maxgforce) * maxsint16);
|
||||
}
|
||||
|
||||
#ifdef SDL_JOYSTICK_MFI
|
||||
static Uint8
|
||||
SDL_SYS_MFIJoystickHatStateForDPad(GCControllerDirectionPad *dpad)
|
||||
{
|
||||
Uint8 hat = 0;
|
||||
|
||||
if (dpad.up.isPressed) {
|
||||
hat |= SDL_HAT_UP;
|
||||
} else if (dpad.down.isPressed) {
|
||||
hat |= SDL_HAT_DOWN;
|
||||
}
|
||||
|
||||
if (dpad.left.isPressed) {
|
||||
hat |= SDL_HAT_LEFT;
|
||||
} else if (dpad.right.isPressed) {
|
||||
hat |= SDL_HAT_RIGHT;
|
||||
}
|
||||
|
||||
if (hat == 0) {
|
||||
return SDL_HAT_CENTERED;
|
||||
}
|
||||
|
||||
return hat;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
SDL_SYS_MFIJoystickUpdate(SDL_Joystick * joystick)
|
||||
{
|
||||
#ifdef SDL_JOYSTICK_MFI
|
||||
@autoreleasepool {
|
||||
GCController *controller = joystick->hwdata->controller;
|
||||
Uint8 hatstate = SDL_HAT_CENTERED;
|
||||
int i;
|
||||
|
||||
if (controller.extendedGamepad) {
|
||||
GCExtendedGamepad *gamepad = controller.extendedGamepad;
|
||||
|
||||
/* Axis order matches the XInput Windows mappings. */
|
||||
SDL_PrivateJoystickAxis(joystick, 0, (Sint16) (gamepad.leftThumbstick.xAxis.value * 32767));
|
||||
SDL_PrivateJoystickAxis(joystick, 1, (Sint16) (gamepad.leftThumbstick.yAxis.value * 32767));
|
||||
SDL_PrivateJoystickAxis(joystick, 2, (Sint16) (gamepad.leftTrigger.value * 32767));
|
||||
SDL_PrivateJoystickAxis(joystick, 3, (Sint16) (gamepad.rightThumbstick.xAxis.value * 32767));
|
||||
SDL_PrivateJoystickAxis(joystick, 4, (Sint16) (gamepad.rightThumbstick.yAxis.value * 32767));
|
||||
SDL_PrivateJoystickAxis(joystick, 5, (Sint16) (gamepad.rightTrigger.value * 32767));
|
||||
|
||||
hatstate = SDL_SYS_MFIJoystickHatStateForDPad(gamepad.dpad);
|
||||
|
||||
/* Button order matches the XInput Windows mappings. */
|
||||
SDL_PrivateJoystickButton(joystick, 0, gamepad.buttonA.isPressed);
|
||||
SDL_PrivateJoystickButton(joystick, 1, gamepad.buttonB.isPressed);
|
||||
SDL_PrivateJoystickButton(joystick, 2, gamepad.buttonX.isPressed);
|
||||
SDL_PrivateJoystickButton(joystick, 3, gamepad.buttonY.isPressed);
|
||||
SDL_PrivateJoystickButton(joystick, 4, gamepad.leftShoulder.isPressed);
|
||||
SDL_PrivateJoystickButton(joystick, 5, gamepad.rightShoulder.isPressed);
|
||||
} else if (controller.gamepad) {
|
||||
GCGamepad *gamepad = controller.gamepad;
|
||||
|
||||
hatstate = SDL_SYS_MFIJoystickHatStateForDPad(gamepad.dpad);
|
||||
|
||||
/* Button order matches the XInput Windows mappings. */
|
||||
SDL_PrivateJoystickButton(joystick, 0, gamepad.buttonA.isPressed);
|
||||
SDL_PrivateJoystickButton(joystick, 1, gamepad.buttonB.isPressed);
|
||||
SDL_PrivateJoystickButton(joystick, 2, gamepad.buttonX.isPressed);
|
||||
SDL_PrivateJoystickButton(joystick, 3, gamepad.buttonY.isPressed);
|
||||
SDL_PrivateJoystickButton(joystick, 4, gamepad.leftShoulder.isPressed);
|
||||
SDL_PrivateJoystickButton(joystick, 5, gamepad.rightShoulder.isPressed);
|
||||
}
|
||||
/* TODO: Handle micro profiles on tvOS. */
|
||||
|
||||
SDL_PrivateJoystickHat(joystick, 0, hatstate);
|
||||
|
||||
for (i = 0; i < joystick->hwdata->num_pause_presses; i++) {
|
||||
/* The pause button is always last. */
|
||||
Uint8 pausebutton = joystick->nbuttons - 1;
|
||||
|
||||
SDL_PrivateJoystickButton(joystick, pausebutton, 1);
|
||||
SDL_PrivateJoystickButton(joystick, pausebutton, 0);
|
||||
}
|
||||
|
||||
joystick->hwdata->num_pause_presses = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Function to update the state of a joystick - called as a device poll.
|
||||
@@ -157,15 +513,40 @@ static void SDL_SYS_AccelerometerUpdate(SDL_Joystick * joystick)
|
||||
void
|
||||
SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
|
||||
{
|
||||
SDL_SYS_AccelerometerUpdate(joystick);
|
||||
SDL_JoystickDeviceItem *device = joystick->hwdata;
|
||||
|
||||
if (device == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (device->accelerometer) {
|
||||
SDL_SYS_AccelerometerUpdate(joystick);
|
||||
} else if (device->controller) {
|
||||
SDL_SYS_MFIJoystickUpdate(joystick);
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to close a joystick after use */
|
||||
void
|
||||
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
|
||||
{
|
||||
SDL_JoystickDeviceItem *device = joystick->hwdata;
|
||||
|
||||
if (device == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
device->joystick = NULL;
|
||||
|
||||
@autoreleasepool {
|
||||
[motionManager stopAccelerometerUpdates];
|
||||
if (device->accelerometer) {
|
||||
[motionManager stopAccelerometerUpdates];
|
||||
} else if (device->controller) {
|
||||
#ifdef SDL_JOYSTICK_MFI
|
||||
GCController *controller = device->controller;
|
||||
controller.controllerPausedHandler = nil;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,6 +555,24 @@ void
|
||||
SDL_SYS_JoystickQuit(void)
|
||||
{
|
||||
@autoreleasepool {
|
||||
#ifdef SDL_JOYSTICK_MFI
|
||||
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
|
||||
|
||||
if (connectObserver) {
|
||||
[center removeObserver:connectObserver name:GCControllerDidConnectNotification object:nil];
|
||||
connectObserver = nil;
|
||||
}
|
||||
|
||||
if (disconnectObserver) {
|
||||
[center removeObserver:disconnectObserver name:GCControllerDidDisconnectNotification object:nil];
|
||||
disconnectObserver = nil;
|
||||
}
|
||||
#endif /* SDL_JOYSTICK_MFI */
|
||||
|
||||
while (deviceList != NULL) {
|
||||
SDL_SYS_RemoveJoystickDevice(deviceList);
|
||||
}
|
||||
|
||||
motionManager = nil;
|
||||
}
|
||||
|
||||
@@ -182,21 +581,24 @@ SDL_SYS_JoystickQuit(void)
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
|
||||
{
|
||||
SDL_JoystickDeviceItem *device = GetDeviceForIndex(device_index);
|
||||
SDL_JoystickGUID guid;
|
||||
/* the GUID is just the first 16 chars of the name for now */
|
||||
const char *name = SDL_SYS_JoystickNameForDeviceIndex( device_index );
|
||||
SDL_zero( guid );
|
||||
SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
|
||||
if (device) {
|
||||
guid = device->guid;
|
||||
} else {
|
||||
SDL_zero(guid);
|
||||
}
|
||||
return guid;
|
||||
}
|
||||
|
||||
SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
|
||||
{
|
||||
SDL_JoystickGUID guid;
|
||||
/* the GUID is just the first 16 chars of the name for now */
|
||||
const char *name = joystick->name;
|
||||
SDL_zero( guid );
|
||||
SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
|
||||
if (joystick->hwdata) {
|
||||
guid = joystick->hwdata->guid;
|
||||
} else {
|
||||
SDL_zero(guid);
|
||||
}
|
||||
return guid;
|
||||
}
|
||||
|
||||
|
||||
55
src/joystick/iphoneos/SDL_sysjoystick_c.h
Normal file
55
src/joystick/iphoneos/SDL_sysjoystick_c.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifndef SDL_JOYSTICK_IOS_H
|
||||
#define SDL_JOYSTICK_IOS_H
|
||||
|
||||
#include "SDL_stdinc.h"
|
||||
#include "../SDL_sysjoystick.h"
|
||||
|
||||
@class GCController;
|
||||
|
||||
typedef struct joystick_hwdata
|
||||
{
|
||||
SDL_bool accelerometer;
|
||||
|
||||
GCController __unsafe_unretained *controller;
|
||||
int num_pause_presses;
|
||||
|
||||
char *name;
|
||||
SDL_Joystick *joystick;
|
||||
SDL_JoystickID instance_id;
|
||||
SDL_JoystickGUID guid;
|
||||
|
||||
int naxes;
|
||||
int nbuttons;
|
||||
int nhats;
|
||||
|
||||
struct joystick_hwdata *next;
|
||||
} joystick_hwdata;
|
||||
|
||||
typedef joystick_hwdata SDL_JoystickDeviceItem;
|
||||
|
||||
#endif /* SDL_JOYSTICK_IOS_H */
|
||||
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
Reference in New Issue
Block a user