X-Git-Url: https://git.yukkurigames.com/?p=enjoyable.git;a=blobdiff_plain;f=JoystickController.m;h=33201f5ba2b98e6235f6f5506c2fc129591785fd;hp=317e9a51c9b09ae0680c9cf42b9565ee9c8fd447;hb=1bb3f553caac2b6b74380bd20ddc4bb1ff22abb2;hpb=3f6df7a954fb74bcebf6fc6c0e60821843b0f31b diff --git a/JoystickController.m b/JoystickController.m index 317e9a5..33201f5 100644 --- a/JoystickController.m +++ b/JoystickController.m @@ -7,21 +7,23 @@ #import "JoystickController.h" +#import "Config.h" +#import "ConfigsController.h" +#import "Joystick.h" +#import "JSAction.h" +#import "Target.h" +#import "TargetController.h" + @implementation JoystickController { IOHIDManagerRef hidManager; - BOOL programmaticallySelecting; NSTimer *continuousTimer; + NSMutableArray *runningTargets; + NSMutableArray *_joysticks; } -@synthesize joysticks; -@synthesize runningTargets; -@synthesize selectedAction; -@synthesize frontWindowOnly; -@synthesize mouseLoc; - - (id)init { if ((self = [super init])) { - joysticks = [[NSMutableArray alloc] initWithCapacity:16]; + _joysticks = [[NSMutableArray alloc] initWithCapacity:16]; runningTargets = [[NSMutableArray alloc] initWithCapacity:32]; } return self; @@ -40,8 +42,9 @@ } - (void)addRunningTarget:(Target *)target { - if (![runningTargets containsObject:target]) + if (![runningTargets containsObject:target]) { [runningTargets addObject:target]; + } if (!continuousTimer) { continuousTimer = [NSTimer scheduledTimerWithTimeInterval:1.f/60.f target:self @@ -52,32 +55,39 @@ } } +- (void)runTargetForDevice:(IOHIDDeviceRef)device value:(IOHIDValueRef)value { + Joystick *js = [self findJoystickByRef:device]; + JSAction *mainAction = [js actionForEvent:value]; + [mainAction notifyEvent:value]; + NSArray *children = mainAction.children ? mainAction.children : mainAction ? @[mainAction] : @[]; + for (JSAction *subaction in children) { + Target *target = configsController.currentConfig[subaction]; + target.magnitude = mainAction.magnitude; + target.running = subaction.active; + if (target.running && target.isContinuous) + [self addRunningTarget:target]; + } +} + +- (void)showTargetForDevice:(IOHIDDeviceRef)device value:(IOHIDValueRef)value { + Joystick *js = [self findJoystickByRef:device]; + JSAction *handler = [js handlerForEvent:value]; + if (!handler) + return; + + [self expandRecursive:handler]; + [outlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:[outlineView rowForItem:handler]] byExtendingSelection: NO]; + [targetController focusKey]; +} + static void input_callback(void *ctx, IOReturn inResult, void *inSender, IOHIDValueRef value) { JoystickController *controller = (__bridge JoystickController *)ctx; IOHIDDeviceRef device = IOHIDQueueGetDevice(inSender); - Joystick *js = [controller findJoystickByRef:device]; - if (((ApplicationController *)[NSApplication sharedApplication].delegate).active) { - JSAction *mainAction = [js actionForEvent:value]; - [mainAction notifyEvent:value]; - NSArray *children = mainAction.children ? mainAction.children : mainAction ? @[mainAction] : @[]; - for (JSAction *subaction in children) { - Target *target = [controller.currentConfig getTargetForAction:subaction]; - target.magnitude = mainAction.magnitude; - target.running = subaction.active; - if (target.running && target.isContinuous) - [controller addRunningTarget:target]; - } - } else if ([NSApplication sharedApplication].isActive - && [NSApplication sharedApplication].mainWindow.isVisible) { - // joysticks not active, use it to select stuff - JSAction *handler = [js handlerForEvent:value]; - if (!handler) - return; - - [controller expandRecursive:handler]; - controller->programmaticallySelecting = YES; - [controller->outlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:[controller->outlineView rowForItem:handler]] byExtendingSelection: NO]; + if (controller.sendingRealEvents) { + [controller runTargetForDevice:device value:value]; + } else if ([NSApplication sharedApplication].mainWindow.isVisible) { + [controller showTargetForDevice:device value:value]; } } @@ -95,17 +105,21 @@ static int findAvailableIndex(NSArray *list, Joystick *js) { } } +- (void)addJoystickForDevice:(IOHIDDeviceRef)device { + IOHIDDeviceRegisterInputValueCallback(device, input_callback, (__bridge void*)self); + Joystick *js = [[Joystick alloc] initWithDevice:device]; + js.index = findAvailableIndex(_joysticks, js); + [_joysticks addObject:js]; + [outlineView reloadData]; +} + static void add_callback(void *ctx, IOReturn inResult, void *inSender, IOHIDDeviceRef device) { JoystickController *controller = (__bridge JoystickController *)ctx; - IOHIDDeviceRegisterInputValueCallback(device, input_callback, (__bridge void*)controller); - Joystick *js = [[Joystick alloc] initWithDevice:device]; - js.index = findAvailableIndex(controller.joysticks, js); - [[controller joysticks] addObject:js]; - [controller->outlineView reloadData]; + [controller addJoystickForDevice:device]; } - (Joystick *)findJoystickByRef:(IOHIDDeviceRef)device { - for (Joystick *js in joysticks) + for (Joystick *js in _joysticks) if (js.device == device) return js; return nil; @@ -113,21 +127,27 @@ static void add_callback(void *ctx, IOReturn inResult, void *inSender, IOHIDDevi static void remove_callback(void *ctx, IOReturn inResult, void *inSender, IOHIDDeviceRef device) { JoystickController *controller = (__bridge JoystickController *)ctx; - Joystick *match = [controller findJoystickByRef:device]; + [controller removeJoystickForDevice:device]; +} + +- (void)removeJoystickForDevice:(IOHIDDeviceRef)device { + Joystick *match = [self findJoystickByRef:device]; IOHIDDeviceRegisterInputValueCallback(device, NULL, NULL); if (match) { - [controller.joysticks removeObject:match]; - [controller->outlineView reloadData]; + [_joysticks removeObject:match]; + [outlineView reloadData]; } + } - (void)updateContinuousActions:(NSTimer *)timer { self.mouseLoc = [NSEvent mouseLocation]; - for (Target *target in [self.runningTargets copy]) { - if (![target update:self]) - [self.runningTargets removeObject:target]; + for (Target *target in [runningTargets copy]) { + if (![target update:self]) { + [runningTargets removeObject:target]; + } } - if (!self.runningTargets.count) { + if (!runningTargets.count) { [continuousTimer invalidate]; continuousTimer = nil; NSLog(@"Unscheduled continuous target timer."); @@ -148,31 +168,37 @@ static void remove_callback(void *ctx, IOReturn inResult, void *inSender, IOHIDD IOHIDManagerSetDeviceMatchingMultiple(hidManager, (__bridge CFArrayRef)criteria); IOHIDManagerScheduleWithRunLoop(hidManager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); - IOHIDManagerOpen(hidManager, kIOHIDOptionsTypeNone); // FIXME: If an error happens, report it! + IOReturn ret = IOHIDManagerOpen(hidManager, kIOHIDOptionsTypeNone); + if (ret != kIOReturnSuccess) { + [[NSAlert alertWithMessageText:@"Input devices are unavailable" + defaultButton:nil + alternateButton:nil + otherButton:nil + informativeTextWithFormat:@"Error 0x%08x occured trying to access your devices. " + @"Input may not be correctly detected or mapped.", + ret] + runModal]; + } IOHIDManagerRegisterDeviceMatchingCallback(hidManager, add_callback, (__bridge void *)self); IOHIDManagerRegisterDeviceRemovalCallback(hidManager, remove_callback, (__bridge void *)self); } -- (Config *)currentConfig { - return configsController.currentConfig; -} - - (JSAction *)selectedAction { id item = [outlineView itemAtRow:outlineView.selectedRow]; return [item children] ? nil : item; } -- (int)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item { - return item ? [[item children] count] : [joysticks count]; +- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item { + return item ? [[item children] count] : _joysticks.count; } - (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item { return item ? [[item children] count] > 0: YES; } -- (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item { - return item ? [item children][index] : joysticks[index]; +- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item { + return item ? [item children][index] : _joysticks[index]; } - (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item { @@ -181,12 +207,8 @@ static void remove_callback(void *ctx, IOReturn inResult, void *inSender, IOHIDD return [item name]; } -- (void)outlineViewSelectionDidChange: (NSNotification*) notification { - [targetController reset]; - [targetController load]; - if (programmaticallySelecting) - [targetController focusKey]; - programmaticallySelecting = NO; +- (void)outlineViewSelectionDidChange:(NSNotification *)notification { + [targetController loadCurrent]; } @end