Joystick hat support in Cocoa
This commit is contained in:
parent
66b814a226
commit
b2397a2e7a
@ -4,5 +4,6 @@
|
||||
|
||||
- (void) joystick:(NSString *)joystick_name button: (unsigned)button changedState: (bool) state;
|
||||
- (void) joystick:(NSString *)joystick_name axis: (unsigned)axis movedTo: (signed) value;
|
||||
- (void) joystick:(NSString *)joystick_name hat: (unsigned)hat changedState: (int8_t) value;
|
||||
|
||||
@end
|
||||
|
@ -309,6 +309,42 @@
|
||||
[self advanceConfigurationStateMachine];
|
||||
}
|
||||
|
||||
- (void) joystick:(NSString *)joystick_name hat: (unsigned)hat changedState: (int8_t) state
|
||||
{
|
||||
/* Hats are always mapped to the D-pad, ignore them on non-Dpad keys and skip the D-pad configuration if used*/
|
||||
if (!state) return;
|
||||
if (joystick_configuration_state == -1) return;
|
||||
if (joystick_configuration_state > GBDown) return;
|
||||
if (!joystick_being_configured) {
|
||||
joystick_being_configured = joystick_name;
|
||||
}
|
||||
else if (![joystick_being_configured isEqualToString:joystick_name]) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSMutableDictionary *all_mappings = [[[NSUserDefaults standardUserDefaults] dictionaryForKey:@"GBJoypadMappings"] mutableCopy];
|
||||
|
||||
if (!all_mappings) {
|
||||
all_mappings = [[NSMutableDictionary alloc] init];
|
||||
}
|
||||
|
||||
NSMutableDictionary *mapping = [[all_mappings objectForKey:joystick_name] mutableCopy];
|
||||
|
||||
if (!mapping) {
|
||||
mapping = [[NSMutableDictionary alloc] init];
|
||||
}
|
||||
|
||||
for (joystick_configuration_state = 0;; joystick_configuration_state++) {
|
||||
[mapping removeObjectForKey:GBButtonNames[joystick_configuration_state]];
|
||||
if (joystick_configuration_state == GBDown) break;
|
||||
}
|
||||
|
||||
all_mappings[joystick_name] = mapping;
|
||||
[[NSUserDefaults standardUserDefaults] setObject:all_mappings forKey:@"GBJoypadMappings"];
|
||||
[self refreshJoypadMenu:nil];
|
||||
[self advanceConfigurationStateMachine];
|
||||
}
|
||||
|
||||
- (NSButton *)aspectRatioCheckbox
|
||||
{
|
||||
return _aspectRatioCheckbox;
|
||||
|
@ -341,6 +341,27 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void) joystick:(NSString *)joystick_name hat: (unsigned)hat changedState: (int8_t) state
|
||||
{
|
||||
unsigned player_count = GB_get_player_count(_gb);
|
||||
|
||||
UpdateSystemActivity(UsrActivity);
|
||||
for (unsigned player = 0; player < player_count; player++) {
|
||||
NSString *preferred_joypad = [[[NSUserDefaults standardUserDefaults] dictionaryForKey:@"GBDefaultJoypads"]
|
||||
objectForKey:[NSString stringWithFormat:@"%u", player]];
|
||||
if (player_count != 1 && // Single player, accpet inputs from all joypads
|
||||
!(player == 0 && !preferred_joypad) && // Multiplayer, but player 1 has no joypad configured, so it takes inputs from all joypads
|
||||
![preferred_joypad isEqualToString:joystick_name]) {
|
||||
continue;
|
||||
}
|
||||
assert(state + 1 < 9);
|
||||
/* - N NE E SE S SW W NW */
|
||||
GB_set_key_state_for_player(_gb, GB_KEY_UP, player, (bool []){0, 1, 1, 0, 0, 0, 0, 0, 1}[state + 1]);
|
||||
GB_set_key_state_for_player(_gb, GB_KEY_RIGHT, player, (bool []){0, 0, 1, 1, 1, 0, 0, 0, 0}[state + 1]);
|
||||
GB_set_key_state_for_player(_gb, GB_KEY_DOWN, player, (bool []){0, 0, 0, 0, 1, 1, 1, 0, 0}[state + 1]);
|
||||
GB_set_key_state_for_player(_gb, GB_KEY_LEFT, player, (bool []){0, 0, 0, 0, 0, 0, 1, 1, 1}[state + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)acceptsFirstResponder
|
||||
{
|
||||
|
@ -53,6 +53,9 @@ struct _SDL_Joystick
|
||||
int nbuttons; /* Number of buttons on the joystick */
|
||||
uint8_t *buttons; /* Current button states */
|
||||
|
||||
int nhats;
|
||||
uint8_t *hats;
|
||||
|
||||
struct joystick_hwdata *hwdata; /* Driver dependent information */
|
||||
|
||||
int ref_count; /* Reference count for multiple opens */
|
||||
@ -93,10 +96,12 @@ struct joystick_hwdata
|
||||
|
||||
int axes; /* number of axis (calculated, not reported by device) */
|
||||
int buttons; /* number of buttons (calculated, not reported by device) */
|
||||
int hats;
|
||||
int elements; /* number of total elements (should be total of above) (calculated, not reported by device) */
|
||||
|
||||
recElement *firstAxis;
|
||||
recElement *firstButton;
|
||||
recElement *firstHat;
|
||||
|
||||
bool removed;
|
||||
|
||||
@ -178,6 +183,30 @@ void SDL_PrivateJoystickButton(SDL_Joystick *joystick, uint8_t button, uint8_t s
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_PrivateJoystickHat(SDL_Joystick *joystick, uint8_t hat, uint8_t state)
|
||||
{
|
||||
|
||||
/* Make sure we're not getting garbage or duplicate events */
|
||||
if (hat >= joystick->nhats) {
|
||||
return;
|
||||
}
|
||||
if (state == joystick->hats[hat]) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Update internal joystick state */
|
||||
joystick->hats[hat] = state;
|
||||
|
||||
NSResponder<GBJoystickListener> *responder = (typeof(responder)) [[NSApp keyWindow] firstResponder];
|
||||
while (responder) {
|
||||
if ([responder respondsToSelector:@selector(joystick:button:changedState:)]) {
|
||||
[responder joystick:@(joystick->name) hat:hat changedState:state];
|
||||
break;
|
||||
}
|
||||
responder = (typeof(responder)) [responder nextResponder];
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
FreeElementList(recElement *pElement)
|
||||
{
|
||||
@ -202,6 +231,7 @@ FreeDevice(recDevice *removeDevice)
|
||||
/* free element lists */
|
||||
FreeElementList(removeDevice->firstAxis);
|
||||
FreeElementList(removeDevice->firstButton);
|
||||
FreeElementList(removeDevice->firstHat);
|
||||
|
||||
free(removeDevice);
|
||||
}
|
||||
@ -315,6 +345,15 @@ AddHIDElement(const void *value, void *parameter)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case kHIDUsage_GD_Hatswitch:
|
||||
if (!ElementAlreadyAdded(cookie, pDevice->firstHat)) {
|
||||
element = (recElement *) calloc(1, sizeof (recElement));
|
||||
if (element) {
|
||||
pDevice->hats++;
|
||||
headElement = &(pDevice->firstHat);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case kHIDUsage_GD_DPadUp:
|
||||
case kHIDUsage_GD_DPadDown:
|
||||
@ -535,6 +574,27 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
|
||||
element = element->pNext;
|
||||
++i;
|
||||
}
|
||||
|
||||
element = device->firstHat;
|
||||
i = 0;
|
||||
while (element) {
|
||||
signed range = (element->max - element->min + 1);
|
||||
value = GetHIDElementState(device, element) - element->min;
|
||||
if (range == 4) { /* 4 position hatswitch - scale up value */
|
||||
value *= 2;
|
||||
} else if (range != 8) { /* Neither a 4 nor 8 positions - fall back to default position (centered) */
|
||||
value = -1;
|
||||
}
|
||||
if ((unsigned)value >= 8) {
|
||||
value = -1;
|
||||
}
|
||||
|
||||
SDL_PrivateJoystickHat(joystick, i, value);
|
||||
|
||||
element = element->pNext;
|
||||
++i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void JoystickInputCallback(
|
||||
@ -579,6 +639,7 @@ JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender, IOHIDDevic
|
||||
|
||||
joystick->naxes = device->axes;
|
||||
joystick->nbuttons = device->buttons;
|
||||
joystick->nhats = device->hats;
|
||||
|
||||
if (joystick->naxes > 0) {
|
||||
joystick->axes = (SDL_JoystickAxisInfo *) calloc(joystick->naxes, sizeof(SDL_JoystickAxisInfo));
|
||||
@ -586,6 +647,9 @@ JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender, IOHIDDevic
|
||||
if (joystick->nbuttons > 0) {
|
||||
joystick->buttons = (uint8_t *) calloc(joystick->nbuttons, 1);
|
||||
}
|
||||
if (joystick->nhats > 0) {
|
||||
joystick->hats = (uint8_t *) calloc(joystick->nhats, 1);
|
||||
}
|
||||
|
||||
/* Get notified when this device is disconnected. */
|
||||
IOHIDDeviceRegisterRemovalCallback(ioHIDDeviceObject, JoystickDeviceWasRemovedCallback, device);
|
||||
|
Loading…
Reference in New Issue
Block a user