Skip to content

Commit 973ab12

Browse files
SiegeLordExSiegeLord
authored andcommitted
Sort the usages for MacOS gamepads.
The ideas is taken from GLFW, which does the same thing in a slightly different way. Fixes #1663
1 parent a382933 commit 973ab12

File tree

3 files changed

+97
-55
lines changed

3 files changed

+97
-55
lines changed

include/allegro5/joystick.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
#endif
2525

2626
/* internal values */
27-
#define _AL_MAX_JOYSTICK_AXES 5
27+
#define _AL_MAX_JOYSTICK_AXES 6
2828
#define _AL_MAX_JOYSTICK_STICKS 16
2929
#ifdef ALLEGRO_ANDROID
3030
#define _AL_MAX_JOYSTICK_BUTTONS 36

python/generate_python_ctypes.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,8 +297,8 @@ def parse_protos(self, filename):
297297
n = 0
298298
ftype = mob.group(1)
299299
if ftype.startswith("struct"):
300-
if ftype == "struct {float axis[5];}":
301-
t = "c_float * 5"
300+
if ftype == "struct {float axis[6];}":
301+
t = "c_float * 6"
302302
else:
303303
print("Error: Can't parse " + ftype + " yet.")
304304
t = None

src/macosx/hidjoy.m

Lines changed: 94 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,20 @@ static void add_elements(CFArrayRef elements, ALLEGRO_JOYSTICK_OSX *joy)
319319
joy->parent.info.num_buttons = num_buttons;
320320
}
321321

322+
static NSInteger element_compare_func(id val1, id val2)
323+
{
324+
IOHIDElementRef elem1 = [(NSValue *)val1 pointerValue];
325+
IOHIDElementRef elem2 = [(NSValue *)val2 pointerValue];
326+
327+
int usage1 = IOHIDElementGetUsage(elem1);
328+
int usage2 = IOHIDElementGetUsage(elem2);
329+
if (usage1 < usage2)
330+
return kCFCompareLessThan;
331+
if (usage1 > usage2)
332+
return kCFCompareGreaterThan;
333+
return kCFCompareEqualTo;
334+
}
335+
322336
static bool add_elements_with_mapping(CFArrayRef elements, ALLEGRO_JOYSTICK_OSX *joy, const _AL_JOYSTICK_MAPPING *mapping)
323337
{
324338
int num_buttons = 0;
@@ -329,6 +343,10 @@ static bool add_elements_with_mapping(CFArrayRef elements, ALLEGRO_JOYSTICK_OSX
329343
int num_axes_mapped = 0;
330344
_AL_JOYSTICK_OUTPUT *output;
331345

346+
NSMutableArray* buttons_elems = [[[NSMutableArray alloc] init] autorelease];
347+
NSMutableArray* axes_elems = [[[NSMutableArray alloc] init] autorelease];
348+
NSMutableArray* hats_elems = [[[NSMutableArray alloc] init] autorelease];
349+
332350
for (int i = 0; i < CFArrayGetCount(elements); i++) {
333351
IOHIDElementRef elem = (IOHIDElementRef)CFArrayGetValueAtIndex(
334352
elements,
@@ -338,83 +356,107 @@ static bool add_elements_with_mapping(CFArrayRef elements, ALLEGRO_JOYSTICK_OSX
338356
int usage = IOHIDElementGetUsage(elem);
339357
int usage_page = IOHIDElementGetUsagePage(elem);
340358
if (IOHIDElementGetType(elem) == kIOHIDElementTypeInput_Button) {
341-
int idx = num_buttons;
342359
// 0x09 is the Button Page.
343360
if (usage_page != 0x09)
344361
continue;
345-
if (idx >= 0 && idx < _AL_MAX_JOYSTICK_BUTTONS && !joy->buttons[idx].elem) {
346-
joy->buttons[idx].elem = elem;
347-
output = _al_get_joystick_output(&mapping->button_map, idx);
348-
if (output) {
349-
joy->buttons[idx].output = *output;
350-
num_buttons_mapped++;
351-
}
352-
num_buttons++;
353-
}
362+
[buttons_elems addObject: [NSValue valueWithPointer:elem]];
354363
}
355364
else if (IOHIDElementGetType(elem) == kIOHIDElementTypeInput_Misc) {
356-
long min = IOHIDElementGetLogicalMin(elem);
357-
long max = IOHIDElementGetLogicalMax(elem);
358-
359-
int elem_kind = -1;
360365
switch (usage) {
361366
case kHIDUsage_GD_X:
362367
case kHIDUsage_GD_Y:
363368
case kHIDUsage_GD_Z:
364369
case kHIDUsage_GD_Rx:
365370
case kHIDUsage_GD_Ry:
366-
case kHIDUsage_GD_Rz: {
367-
elem_kind = 0;
371+
case kHIDUsage_GD_Rz:
372+
case kHIDUsage_GD_Slider:
373+
case kHIDUsage_GD_Dial:
374+
case kHIDUsage_GD_Wheel: {
375+
[axes_elems addObject: [NSValue valueWithPointer:elem]];
368376
break;
369377
}
370378
case kHIDUsage_GD_Hatswitch: {
371-
elem_kind = 1;
379+
[hats_elems addObject: [NSValue valueWithPointer:elem]];
372380
break;
373381
}
374382
default:
375383
continue;
376384
}
385+
}
386+
}
377387

378-
if (elem_kind < 0)
379-
continue;
388+
// This sorting is inspired by what GLFW does.
389+
[buttons_elems sortWithOptions:NSSortStable
390+
usingComparator:^NSComparisonResult(id val1, id val2) {
391+
return element_compare_func(val1, val2);
392+
}];
393+
[axes_elems sortWithOptions:NSSortStable
394+
usingComparator:^NSComparisonResult(id val1, id val2) {
395+
return element_compare_func(val1, val2);
396+
}];
397+
[hats_elems sortWithOptions:NSSortStable
398+
usingComparator:^NSComparisonResult(id val1, id val2) {
399+
return element_compare_func(val1, val2);
400+
}];
401+
402+
for (int i = 0; i < (int)[buttons_elems count]; i++) {
403+
IOHIDElementRef elem = [(NSValue *)buttons_elems[i] pointerValue];
404+
int idx = num_buttons;
405+
if (idx >= 0 && idx < _AL_MAX_JOYSTICK_BUTTONS && !joy->buttons[idx].elem) {
406+
joy->buttons[idx].elem = elem;
407+
output = _al_get_joystick_output(&mapping->button_map, idx);
408+
if (output) {
409+
joy->buttons[idx].output = *output;
410+
num_buttons_mapped++;
411+
}
412+
num_buttons++;
413+
}
414+
}
380415

381-
if (elem_kind == 1) {
382-
if (num_hats >= _AL_MAX_JOYSTICK_AXES)
383-
continue;
416+
for (int i = 0; i < (int)[axes_elems count]; i++) {
417+
IOHIDElementRef elem = [(NSValue *)axes_elems[i] pointerValue];
418+
int usage = IOHIDElementGetUsage(elem);
419+
long min = IOHIDElementGetLogicalMin(elem);
420+
long max = IOHIDElementGetLogicalMax(elem);
421+
if (num_axes >= _AL_MAX_JOYSTICK_AXES)
422+
continue;
384423

385-
HAT_MAPPING *map = &joy->hats[num_hats];
386-
map->min = min;
387-
map->max = max;
388-
map->elem = elem;
389-
output = _al_get_joystick_output(&mapping->hat_map, 2 * num_hats);
390-
if (output) {
391-
map->x_output = *output;
392-
num_hats_mapped++;
393-
}
394-
output = _al_get_joystick_output(&mapping->hat_map, 2 * num_hats + 1);
395-
if (output) {
396-
map->y_output = *output;
397-
num_hats_mapped++;
398-
}
399-
num_hats++;
400-
}
401-
else {
402-
if (num_axes >= _AL_MAX_JOYSTICK_AXES)
403-
continue;
424+
AXIS_MAPPING *map = &joy->axes[num_axes];
425+
map->min = min;
426+
map->max = max;
427+
map->elem = elem;
428+
output = _al_get_joystick_output(&mapping->axis_map, num_axes);
429+
if (output) {
430+
map->output = *output;
431+
num_axes_mapped++;
432+
}
433+
num_axes++;
434+
}
404435

405-
AXIS_MAPPING *map = &joy->axes[num_axes];
406-
map->min = min;
407-
map->max = max;
408-
map->elem = elem;
409-
output = _al_get_joystick_output(&mapping->axis_map, num_axes);
410-
if (output) {
411-
map->output = *output;
412-
num_axes_mapped++;
413-
}
414-
num_axes++;
415-
}
436+
for (int i = 0; i < (int)[hats_elems count]; i++) {
437+
IOHIDElementRef elem = [(NSValue *)hats_elems[i] pointerValue];
438+
long min = IOHIDElementGetLogicalMin(elem);
439+
long max = IOHIDElementGetLogicalMax(elem);
440+
if (num_hats >= _AL_MAX_JOYSTICK_AXES)
441+
continue;
442+
443+
HAT_MAPPING *map = &joy->hats[num_hats];
444+
map->min = min;
445+
map->max = max;
446+
map->elem = elem;
447+
output = _al_get_joystick_output(&mapping->hat_map, 2 * num_hats);
448+
if (output) {
449+
map->x_output = *output;
450+
num_hats_mapped++;
416451
}
452+
output = _al_get_joystick_output(&mapping->hat_map, 2 * num_hats + 1);
453+
if (output) {
454+
map->y_output = *output;
455+
num_hats_mapped++;
456+
}
457+
num_hats++;
417458
}
459+
418460
if (num_axes_mapped != (int)_al_vector_size(&mapping->axis_map)) {
419461
ALLEGRO_ERROR("Could not use mapping, some axes are not mapped.\n");
420462
return false;

0 commit comments

Comments
 (0)