X-Git-Url: https://git.yukkurigames.com/?p=enjoyable.git;a=blobdiff_plain;f=JoystickController.m;h=6b748df7a33eaae1322268b63f4bbd59951e03df;hp=b510848f89bea27c42d2f4712392be06803055ef;hb=51ca12b552a9c17c4d4029b0340e193b273044a8;hpb=530009447c5bbd360ac5023979cffc6d32a28df3 diff --git a/JoystickController.m b/JoystickController.m index b510848..6b748df 100644 --- a/JoystickController.m +++ b/JoystickController.m @@ -5,21 +5,25 @@ // Created by Sam McCall on 4/05/09. // +#import "CoreFoundation/CoreFoundation.h" + @implementation JoystickController -@synthesize joysticks, selectedAction; +@synthesize joysticks, runningTargets, selectedAction, frontWindowOnly; -(id) init { if(self=[super init]) { joysticks = [[NSMutableArray alloc]init]; + runningTargets = [[NSMutableArray alloc]init]; programmaticallySelecting = NO; + mouseLoc.x = mouseLoc.y = 0; } return self; } -(void) finalize { for(int i=0; i<[joysticks count]; i++) { - [[joysticks objectAtIndex:i] invalidate]; + [joysticks[i] invalidate]; } IOHIDManagerClose(hidManager, kIOHIDOptionsTypeNone); CFRelease(hidManager); @@ -29,8 +33,8 @@ static NSMutableDictionary* create_criterion( UInt32 inUsagePage, UInt32 inUsage ) { NSMutableDictionary* dict = [[NSMutableDictionary alloc] init]; - [dict setObject: [NSNumber numberWithInt: inUsagePage] forKey: (NSString*)CFSTR(kIOHIDDeviceUsagePageKey)]; - [dict setObject: [NSNumber numberWithInt: inUsage] forKey: (NSString*)CFSTR(kIOHIDDeviceUsageKey)]; + dict[(NSString*)CFSTR(kIOHIDDeviceUsagePageKey)] = [NSNumber numberWithInt: inUsagePage]; + dict[(NSString*)CFSTR(kIOHIDDeviceUsageKey)] = [NSNumber numberWithInt: inUsage]; return dict; } @@ -40,12 +44,28 @@ static NSMutableDictionary* create_criterion( UInt32 inUsagePage, UInt32 inUsage [outlineView expandItem: handler]; } +BOOL objInArray(NSMutableArray *array, id object) { + for (id o in array) { + if (o == object) + return true; + } + return false; +} + +void timer_callback(CFRunLoopTimerRef timer, void *ctx) { + JoystickController *jc = (JoystickController *)ctx; + jc->mouseLoc = [NSEvent mouseLocation]; + for (Target *target in [jc runningTargets]) { + [target update: jc]; + } +} + void input_callback(void* inContext, IOReturn inResult, void* inSender, IOHIDValueRef value) { JoystickController* self = (JoystickController*)inContext; IOHIDDeviceRef device = IOHIDQueueGetDevice((IOHIDQueueRef) inSender); Joystick* js = [self findJoystickByRef: device]; - if([[[NSApplication sharedApplication] delegate] active]) { + if([(ApplicationController *)[[NSApplication sharedApplication] delegate] active]) { // for reals JSAction* mainAction = [js actionForEvent: value]; if(!mainAction) @@ -54,15 +74,34 @@ void input_callback(void* inContext, IOReturn inResult, void* inSender, IOHIDVal [mainAction notifyEvent: value]; NSArray* subactions = [mainAction subActions]; if(!subactions) - subactions = [NSArray arrayWithObject:mainAction]; + subactions = @[mainAction]; for(id subaction in subactions) { Target* target = [[self->configsController currentConfig] getTargetForAction:subaction]; if(!target) continue; /* target application? doesn't seem to be any need since we are only active when it's in front */ /* might be required for some strange actions */ - [target setRunning: [subaction active]]; - [target setInputValue: IOHIDValueGetIntegerValue(value)]; + if ([target running] != [subaction active]) { + if ([subaction active]) { + [target trigger: self]; + } + else { + [target untrigger: self]; + } + [target setRunning: [subaction active]]; + } + + if ([mainAction isKindOfClass: [JSActionAnalog class]]) { + double realValue = [(JSActionAnalog*)mainAction getRealValue: IOHIDValueGetIntegerValue(value)]; + [target setInputValue: realValue]; + + // Add to list of running targets + if ([target isContinuous] && [target running]) { + if (!objInArray([self runningTargets], target)) { + [[self runningTargets] addObject: target]; + } + } + } } } else if([[NSApplication sharedApplication] isActive] && [[[NSApplication sharedApplication]mainWindow]isVisible]) { // joysticks not active, use it to select stuff @@ -82,7 +121,7 @@ int findAvailableIndex(id list, Joystick* js) { for(int index=0;;index++) { available = YES; for(int i=0; i<[list count]; i++) { - js2 = [list objectAtIndex: i]; + js2 = list[i]; if([js2 vendorId] == [js vendorId] && [js2 productId] == [js productId] && [js index] == index) { available = NO; break; @@ -109,10 +148,10 @@ void add_callback(void* inContext, IOReturn inResult, void* inSender, IOHIDDevic } -(Joystick*) findJoystickByRef: (IOHIDDeviceRef) device { - for(int i=0; i<[joysticks count]; i++) - if([[joysticks objectAtIndex:i] device] == device) - return [joysticks objectAtIndex:i]; - return NULL; + for (Joystick *js in joysticks) + if (js.device == device) + return js; + return nil; } void remove_callback(void* inContext, IOReturn inResult, void* inSender, IOHIDDeviceRef device) { @@ -130,15 +169,12 @@ void remove_callback(void* inContext, IOReturn inResult, void* inSender, IOHIDDe -(void) setup { hidManager = IOHIDManagerCreate( kCFAllocatorDefault, kIOHIDOptionsTypeNone); - NSArray *criteria = [NSArray arrayWithObjects: - create_criterion(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick), + NSArray *criteria = @[create_criterion(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick), create_criterion(kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad), - create_criterion(kHIDPage_GenericDesktop, kHIDUsage_GD_MultiAxisController), - create_criterion(kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard), - nil]; + create_criterion(kHIDPage_GenericDesktop, kHIDUsage_GD_MultiAxisController)]; IOHIDManagerSetDeviceMatchingMultiple(hidManager, (CFArrayRef)criteria); - + IOHIDManagerScheduleWithRunLoop( hidManager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode ); IOReturn tIOReturn = IOHIDManagerOpen( hidManager, kIOHIDOptionsTypeNone ); (void)tIOReturn; @@ -147,6 +183,17 @@ void remove_callback(void* inContext, IOReturn inResult, void* inSender, IOHIDDe IOHIDManagerRegisterDeviceRemovalCallback(hidManager, remove_callback, (void*) self); // IOHIDManagerRegisterInputValueCallback(hidManager, input_callback, (void*)self); // register individually so we can find the device more easily + + + + // Setup timer for continuous targets + CFRunLoopTimerContext ctx = { + 0, (void*)self, NULL, NULL, NULL + }; + CFRunLoopTimerRef timer = CFRunLoopTimerCreate(kCFAllocatorDefault, + CFAbsoluteTimeGetCurrent(), 1.0/80.0, + 0, 0, timer_callback, &ctx); + CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopDefaultMode); } -(id) determineSelectedAction { @@ -184,13 +231,13 @@ void remove_callback(void* inContext, IOReturn inResult, void* inSender, IOHIDDe - (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item { if(item == nil) - return [joysticks objectAtIndex: index]; + return joysticks[index]; if([item isKindOfClass: [Joystick class]]) - return [[item children] objectAtIndex: index]; + return [item children][index]; if([item isKindOfClass: [JSAction class]]) - return [[item subActions] objectAtIndex:index]; + return [item subActions][index]; return NULL; }