Major improvements to JoyKit, fixing Xbox and 8BitDo controllers as well as analog mappings in PS controllers in some situations
This commit is contained in:
parent
0ff882f3bc
commit
690a263648
@ -491,16 +491,12 @@
|
||||
[GBUnderclock] = JOYButtonUsageR1,
|
||||
};
|
||||
|
||||
// Todo: JoyKit might need an API to match an axis to a button
|
||||
if (joystick_configuration_state == GBUnderclock) {
|
||||
mapping[@"AnalogUnderclock"] = nil;
|
||||
double max = 0;
|
||||
for (JOYAxis *axis in controller.axes) {
|
||||
if (axis.value > 0.5 ||
|
||||
(axis.usage == JOYAxisUsageL1 && button.usage == JOYButtonUsageL1) ||
|
||||
(axis.usage == JOYAxisUsageL2 && button.usage == JOYButtonUsageL2) ||
|
||||
(axis.usage == JOYAxisUsageL3 && button.usage == JOYButtonUsageL3) ||
|
||||
(axis.usage == JOYAxisUsageR1 && button.usage == JOYButtonUsageR1) ||
|
||||
(axis.usage == JOYAxisUsageR2 && button.usage == JOYButtonUsageR2) ||
|
||||
(axis.usage == JOYAxisUsageR3 && button.usage == JOYButtonUsageR3)) {
|
||||
if ((axis.value > 0.5 || (axis.equivalentButtonUsage == button.usage)) && axis.value >= max) {
|
||||
max = axis.value;
|
||||
mapping[@"AnalogUnderclock"] = @(axis.uniqueID);
|
||||
break;
|
||||
}
|
||||
@ -508,16 +504,12 @@
|
||||
}
|
||||
|
||||
if (joystick_configuration_state == GBTurbo) {
|
||||
mapping[@"AnalogTurbo"] = nil;
|
||||
double max = 0;
|
||||
for (JOYAxis *axis in controller.axes) {
|
||||
if (axis.value > 0.5 ||
|
||||
(axis.usage == JOYAxisUsageL1 && button.usage == JOYButtonUsageL1) ||
|
||||
(axis.usage == JOYAxisUsageL2 && button.usage == JOYButtonUsageL2) ||
|
||||
(axis.usage == JOYAxisUsageL3 && button.usage == JOYButtonUsageL3) ||
|
||||
(axis.usage == JOYAxisUsageR1 && button.usage == JOYButtonUsageR1) ||
|
||||
(axis.usage == JOYAxisUsageR2 && button.usage == JOYButtonUsageR2) ||
|
||||
(axis.usage == JOYAxisUsageR3 && button.usage == JOYButtonUsageR3)) {
|
||||
if ((axis.value > 0.5 || (axis.equivalentButtonUsage == button.usage)) && axis.value >= max) {
|
||||
max = axis.value;
|
||||
mapping[@"AnalogTurbo"] = @(axis.uniqueID);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -736,9 +736,9 @@
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="d2I-jU-sLb">
|
||||
<rect key="frame" x="195" y="13" width="72" height="32"/>
|
||||
<rect key="frame" x="198" y="13" width="67" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Clear" bezelStyle="rounded" alignment="center" enabled="NO" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="sug-xy-tbw">
|
||||
<buttonCell key="cell" type="push" title="Skip" bezelStyle="rounded" alignment="center" enabled="NO" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="sug-xy-tbw">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
|
@ -4,8 +4,6 @@
|
||||
|
||||
hacksByManufacturer = @{
|
||||
@(0x045E): @{ // Microsoft
|
||||
/* Generally untested, but Microsoft goes by the book when it comes to HID report descriptors, so
|
||||
it should work out of the box. The hack is only here for automatic mapping */
|
||||
|
||||
JOYAxisGroups: @{
|
||||
@(kHIDUsage_GD_X): @(0),
|
||||
@ -13,7 +11,7 @@ hacksByManufacturer = @{
|
||||
@(kHIDUsage_GD_Z): @(2),
|
||||
@(kHIDUsage_GD_Rx): @(1),
|
||||
@(kHIDUsage_GD_Ry): @(1),
|
||||
@(kHIDUsage_GD_Rz): @(3),
|
||||
@(kHIDUsage_GD_Rz): @(2),
|
||||
},
|
||||
|
||||
JOYButtonUsageMapping: @{
|
||||
@ -37,8 +35,10 @@ hacksByManufacturer = @{
|
||||
|
||||
JOYAxes2DUsageMapping: @{
|
||||
AXES2D(1): @(JOYAxes2DUsageLeftStick),
|
||||
AXES2D(4): @(JOYAxes2DUsageRightStick),
|
||||
AXES2D(3): @(JOYAxes2DUsageRightStick),
|
||||
},
|
||||
|
||||
JOYEmulateAxisButtons: @YES,
|
||||
},
|
||||
|
||||
@(0x054C): @{ // Sony
|
||||
|
@ -1,4 +1,5 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "JOYButton.h"
|
||||
|
||||
typedef enum {
|
||||
JOYAxisUsageNone,
|
||||
@ -8,11 +9,16 @@ typedef enum {
|
||||
JOYAxisUsageR1,
|
||||
JOYAxisUsageR2,
|
||||
JOYAxisUsageR3,
|
||||
|
||||
JOYAxisUsageSlider,
|
||||
JOYAxisUsageDial,
|
||||
JOYAxisUsageWheel,
|
||||
|
||||
JOYAxisUsageRudder,
|
||||
JOYAxisUsageThrottle,
|
||||
JOYAxisUsageAccelerator,
|
||||
JOYAxisUsageBrake,
|
||||
|
||||
JOYAxisUsageNonGenericMax,
|
||||
|
||||
JOYAxisUsageGeneric0 = 0x10000,
|
||||
@ -23,6 +29,7 @@ typedef enum {
|
||||
+ (NSString *)usageToString: (JOYAxisUsage) usage;
|
||||
- (uint64_t)uniqueID;
|
||||
- (double)value;
|
||||
- (JOYButtonUsage)equivalentButtonUsage;
|
||||
@property JOYAxisUsage usage;
|
||||
@end
|
||||
|
||||
|
@ -19,6 +19,8 @@
|
||||
@"Analog R1",
|
||||
@"Analog R2",
|
||||
@"Analog R3",
|
||||
@"Slider",
|
||||
@"Dial",
|
||||
@"Wheel",
|
||||
@"Rudder",
|
||||
@"Throttle",
|
||||
@ -57,10 +59,23 @@
|
||||
|
||||
|
||||
if (element.usagePage == kHIDPage_GenericDesktop) {
|
||||
uint16_t usage = element.usage;
|
||||
_usage = JOYAxisUsageGeneric0 + usage - kHIDUsage_GD_X + 1;
|
||||
switch (element.usage) {
|
||||
case kHIDUsage_GD_Slider: _usage = JOYAxisUsageSlider; break;
|
||||
case kHIDUsage_GD_Dial: _usage = JOYAxisUsageDial; break;
|
||||
case kHIDUsage_GD_Wheel: _usage = JOYAxisUsageWheel; break;
|
||||
default:
|
||||
_usage = JOYAxisUsageGeneric0 + element.usage - kHIDUsage_GD_X + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (element.usagePage == kHIDPage_Simulation) {
|
||||
switch (element.usage) {
|
||||
case kHIDUsage_Sim_Accelerator: _usage = JOYAxisUsageAccelerator; break;
|
||||
case kHIDUsage_Sim_Brake: _usage = JOYAxisUsageBrake; break;
|
||||
case kHIDUsage_Sim_Rudder: _usage = JOYAxisUsageRudder; break;
|
||||
case kHIDUsage_Sim_Throttle: _usage = JOYAxisUsageThrottle; break;
|
||||
}
|
||||
}
|
||||
|
||||
_min = 1.0;
|
||||
|
||||
return self;
|
||||
@ -87,4 +102,28 @@
|
||||
return old != _state;
|
||||
}
|
||||
|
||||
- (JOYButtonUsage)equivalentButtonUsage
|
||||
{
|
||||
if (self.usage >= JOYAxisUsageGeneric0) {
|
||||
return self.usage - JOYAxisUsageGeneric0 + JOYButtonUsageGeneric0;
|
||||
}
|
||||
switch (self.usage) {
|
||||
case JOYAxisUsageL1: return JOYButtonUsageL1;
|
||||
case JOYAxisUsageL2: return JOYButtonUsageL2;
|
||||
case JOYAxisUsageL3: return JOYButtonUsageL3;
|
||||
case JOYAxisUsageR1: return JOYButtonUsageR1;
|
||||
case JOYAxisUsageR2: return JOYButtonUsageR2;
|
||||
case JOYAxisUsageR3: return JOYButtonUsageR3;
|
||||
case JOYAxisUsageSlider: return JOYButtonUsageSlider;
|
||||
case JOYAxisUsageDial: return JOYButtonUsageDial;
|
||||
case JOYAxisUsageWheel: return JOYButtonUsageWheel;
|
||||
case JOYAxisUsageRudder: return JOYButtonUsageRudder;
|
||||
case JOYAxisUsageThrottle: return JOYButtonUsageThrottle;
|
||||
case JOYAxisUsageAccelerator: return JOYButtonUsageAccelerator;
|
||||
case JOYAxisUsageBrake: return JOYButtonUsageBrake;
|
||||
default: return JOYButtonUsageNone;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
@ -26,6 +26,16 @@ typedef enum {
|
||||
JOYButtonUsageDPadRight,
|
||||
JOYButtonUsageDPadUp,
|
||||
JOYButtonUsageDPadDown,
|
||||
|
||||
JOYButtonUsageSlider,
|
||||
JOYButtonUsageDial,
|
||||
JOYButtonUsageWheel,
|
||||
|
||||
JOYButtonUsageRudder,
|
||||
JOYButtonUsageThrottle,
|
||||
JOYButtonUsageAccelerator,
|
||||
JOYButtonUsageBrake,
|
||||
|
||||
JOYButtonUsageNonGenericMax,
|
||||
|
||||
JOYButtonUsageGeneric0 = 0x10000,
|
||||
|
@ -1,5 +1,6 @@
|
||||
#import "JOYButton.h"
|
||||
#import "JOYElement.h"
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
@implementation JOYButton
|
||||
{
|
||||
@ -80,6 +81,12 @@
|
||||
case kHIDUsage_GD_SystemMainMenu: _usage = JOYButtonUsageHome; break;
|
||||
}
|
||||
}
|
||||
else if (element.usagePage == kHIDPage_Consumer) {
|
||||
switch (element.usage) {
|
||||
case kHIDUsage_Csmr_ACHome: _usage = JOYButtonUsageHome; break;
|
||||
case kHIDUsage_Csmr_ACBack: _usage = JOYButtonUsageSelect; break;
|
||||
}
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
@ -98,5 +105,4 @@
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -4,7 +4,6 @@
|
||||
#import "JOYAxes2D.h"
|
||||
#import "JOYHat.h"
|
||||
|
||||
static NSString const *JOYAxesEmulateButtonsKey = @"JOYAxesEmulateButtons";
|
||||
static NSString const *JOYAxes2DEmulateButtonsKey = @"JOYAxes2DEmulateButtons";
|
||||
static NSString const *JOYHatsEmulateButtonsKey = @"JOYHatsEmulateButtons";
|
||||
|
||||
|
@ -7,6 +7,9 @@
|
||||
#import "JOYEmulatedButton.h"
|
||||
#include <IOKit/hid/IOHIDLib.h>
|
||||
|
||||
#include <AppKit/AppKit.h>
|
||||
extern NSTextField *globalDebugField;
|
||||
|
||||
#define PWM_RESOLUTION 16
|
||||
|
||||
static NSString const *JOYAxisGroups = @"JOYAxisGroups";
|
||||
@ -27,6 +30,7 @@ static NSString const *JOYActivationReport = @"JOYActivationReport";
|
||||
static NSString const *JOYIgnoredReports = @"JOYIgnoredReports";
|
||||
static NSString const *JOYIsDualShock3 = @"JOYIsDualShock3";
|
||||
static NSString const *JOYIsSony = @"JOYIsSony";
|
||||
static NSString const *JOYEmulateAxisButtons = @"JOYEmulateAxisButtons";
|
||||
|
||||
static NSMutableDictionary<id, JOYController *> *controllers; // Physical controllers
|
||||
static NSMutableArray<JOYController *> *exposedControllers; // Logical controllers
|
||||
@ -36,7 +40,6 @@ static NSDictionary *hacksByManufacturer = nil;
|
||||
|
||||
static NSMutableSet<id<JOYListener>> *listeners = nil;
|
||||
|
||||
static bool axesEmulateButtons = false;
|
||||
static bool axes2DEmulateButtons = false;
|
||||
static bool hatsEmulateButtons = false;
|
||||
|
||||
@ -234,29 +237,40 @@ typedef union {
|
||||
return;
|
||||
}
|
||||
|
||||
if (element.usagePage == kHIDPage_Button) {
|
||||
NSDictionary *axisGroups = @{
|
||||
@(kHIDUsage_GD_X): @(0),
|
||||
@(kHIDUsage_GD_Y): @(0),
|
||||
@(kHIDUsage_GD_Z): @(1),
|
||||
@(kHIDUsage_GD_Rx): @(2),
|
||||
@(kHIDUsage_GD_Ry): @(2),
|
||||
@(kHIDUsage_GD_Rz): @(1),
|
||||
};
|
||||
|
||||
axisGroups = _hacks[JOYAxisGroups] ?: axisGroups;
|
||||
|
||||
if (element.usagePage == kHIDPage_Button ||
|
||||
(element.usagePage == kHIDPage_Consumer && (element.usage == kHIDUsage_Csmr_ACHome ||
|
||||
element.usage == kHIDUsage_Csmr_ACBack))) {
|
||||
button: {
|
||||
JOYButton *button = [[JOYButton alloc] initWithElement: element];
|
||||
[_buttons setObject:button forKey:element];
|
||||
NSNumber *replacementUsage = _hacks[JOYButtonUsageMapping][@(button.usage)];
|
||||
NSNumber *replacementUsage = element.usagePage == kHIDPage_Button? _hacks[JOYButtonUsageMapping][@(button.usage)] : nil;
|
||||
if (replacementUsage) {
|
||||
button.usage = [replacementUsage unsignedIntValue];
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (element.usagePage == kHIDPage_Simulation) {
|
||||
switch (element.usage) {
|
||||
case kHIDUsage_Sim_Accelerator:
|
||||
case kHIDUsage_Sim_Brake:
|
||||
case kHIDUsage_Sim_Rudder:
|
||||
case kHIDUsage_Sim_Throttle:
|
||||
goto single;
|
||||
}
|
||||
}
|
||||
else if (element.usagePage == kHIDPage_GenericDesktop) {
|
||||
NSDictionary *axisGroups = @{
|
||||
@(kHIDUsage_GD_X): @(0),
|
||||
@(kHIDUsage_GD_Y): @(0),
|
||||
@(kHIDUsage_GD_Z): @(1),
|
||||
@(kHIDUsage_GD_Rx): @(2),
|
||||
@(kHIDUsage_GD_Ry): @(2),
|
||||
@(kHIDUsage_GD_Rz): @(1),
|
||||
};
|
||||
|
||||
axisGroups = _hacks[JOYAxisGroups] ?: axisGroups;
|
||||
|
||||
switch (element.usage) {
|
||||
case kHIDUsage_GD_X:
|
||||
case kHIDUsage_GD_Y:
|
||||
@ -318,30 +332,26 @@ typedef union {
|
||||
}*/
|
||||
break;
|
||||
}
|
||||
single:
|
||||
case kHIDUsage_GD_Slider:
|
||||
case kHIDUsage_GD_Dial:
|
||||
case kHIDUsage_GD_Wheel: {
|
||||
case kHIDUsage_GD_Wheel:
|
||||
{ single: {
|
||||
JOYAxis *axis = [[JOYAxis alloc] initWithElement: element];
|
||||
[_axes setObject:axis forKey:element];
|
||||
|
||||
NSNumber *replacementUsage = _hacks[JOYAxisUsageMapping][@(axis.usage)];
|
||||
NSNumber *replacementUsage = element.usagePage == kHIDPage_GenericDesktop? _hacks[JOYAxisUsageMapping][@(axis.usage)] : nil;
|
||||
if (replacementUsage) {
|
||||
axis.usage = [replacementUsage unsignedIntValue];
|
||||
}
|
||||
|
||||
if (axesEmulateButtons && axis.usage >= JOYAxisUsageL1 && axis.usage <= JOYAxisUsageR3) {
|
||||
if ([_hacks[JOYEmulateAxisButtons] boolValue]) {
|
||||
_axisEmulatedButtons[@(axis.uniqueID)] =
|
||||
[[JOYEmulatedButton alloc] initWithUsage:axis.usage - JOYAxisUsageL1 + JOYButtonUsageL1 uniqueID:axis.uniqueID];
|
||||
[[JOYEmulatedButton alloc] initWithUsage:axis.equivalentButtonUsage uniqueID:axis.uniqueID];
|
||||
}
|
||||
|
||||
if (axesEmulateButtons && axis.usage >= JOYAxisUsageGeneric0) {
|
||||
_axisEmulatedButtons[@(axis.uniqueID)] =
|
||||
[[JOYEmulatedButton alloc] initWithUsage:axis.usage - JOYAxisUsageGeneric0 + JOYButtonUsageGeneric0 uniqueID:axis.uniqueID];
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}}
|
||||
case kHIDUsage_GD_DPadUp:
|
||||
case kHIDUsage_GD_DPadDown:
|
||||
case kHIDUsage_GD_DPadRight:
|
||||
@ -1030,7 +1040,6 @@ typedef union {
|
||||
|
||||
+ (void)startOnRunLoop:(NSRunLoop *)runloop withOptions: (NSDictionary *)options
|
||||
{
|
||||
axesEmulateButtons = [options[JOYAxesEmulateButtonsKey] boolValue];
|
||||
axes2DEmulateButtons = [options[JOYAxes2DEmulateButtonsKey] boolValue];
|
||||
hatsEmulateButtons = [options[JOYHatsEmulateButtonsKey] boolValue];
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
#import "JOYEmulatedButton.h"
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
@interface JOYButton ()
|
||||
{
|
||||
@ -28,7 +29,7 @@
|
||||
- (bool)updateStateFromAxis:(JOYAxis *)axis
|
||||
{
|
||||
bool old = _state;
|
||||
_state = [axis value] > 0.5;
|
||||
_state = [axis value] > 0.8;
|
||||
return _state != old;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#import "JOYHat.h"
|
||||
#import "JOYElement.h"
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
@implementation JOYHat
|
||||
{
|
||||
@ -27,6 +28,7 @@
|
||||
if (!self) return self;
|
||||
|
||||
_element = element;
|
||||
_state = -1;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user