@property (copy) NSArray *children;
@property (strong) id base;
@property (copy) NSString *name;
-@property (readonly) BOOL active;
+@property (assign) BOOL active;
+@property (readonly) float magnitude;
- (void)notifyEvent:(IOHIDValueRef)value;
- (NSString *)stringify;
@synthesize children;
@synthesize base;
@synthesize name;
+@synthesize active;
- (id)findSubActionForValue:(IOHIDValueRef)value {
return NULL;
[self doesNotRecognizeSelector:_cmd];
}
-- (BOOL)active {
- [self doesNotRecognizeSelector:_cmd];
- return NO;
+- (float)magnitude {
+ return 0.f;
}
@end
@property (assign) float scale;
- (id)initWithIndex:(int)newIndex offset:(float)offset scale:(float)scale;
-- (float)getRealValue:(int)value;
@end
#import "JSActionAnalog.h"
-@implementation JSActionAnalog
+@implementation JSActionAnalog {
+ float magnitude;
+}
@synthesize offset, scale;
- (id)findSubActionForValue:(IOHIDValueRef)value {
int raw = IOHIDValueGetIntegerValue(value);
- float parsed = [self getRealValue:raw];
-
- if (parsed < -DEAD_ZONE)
+ float mag = offset + scale * raw;
+ if (mag < -DEAD_ZONE)
return self.children[0];
- else if (parsed > DEAD_ZONE)
+ else if (mag > DEAD_ZONE)
return self.children[1];
else
return nil;
- (void)notifyEvent:(IOHIDValueRef)value {
int raw = IOHIDValueGetIntegerValue(value);
- float parsed = [self getRealValue:raw];
- [self.children[0] setActive:parsed < -DEAD_ZONE];
- [self.children[1] setActive:parsed > DEAD_ZONE];
+ magnitude = offset + scale * raw;
+ [self.children[0] setActive:magnitude < -DEAD_ZONE];
+ [self.children[1] setActive:magnitude > DEAD_ZONE];
}
-- (float)getRealValue:(int)value {
- return offset + scale * value;
+- (float)magnitude {
+ return magnitude;
}
-
@end
@class JSAction;
@class ConfigsController;
@class TargetController;
+@class Config;
@interface JoystickController : NSObject {
IBOutlet NSOutlineView *outlineView;
- (void)setup;
- (Joystick *)findJoystickByRef:(IOHIDDeviceRef)device;
+@property (readonly) Config *currentConfig;
@property (readonly) JSAction *selectedAction;
@property (readonly) NSMutableArray *joysticks;
@property (readonly) NSMutableArray *runningTargets;
Joystick *js = [controller findJoystickByRef:device];
if (((ApplicationController *)[NSApplication sharedApplication].delegate).active) {
JSAction *mainAction = [js actionForEvent:value];
- if (!mainAction)
- return;
-
[mainAction notifyEvent:value];
NSArray *children = mainAction.children ? mainAction.children : @[mainAction];
for (JSAction *subaction in children) {
- Target *target = [[controller->configsController currentConfig] getTargetForAction:subaction];
- if (!target)
- continue;
- // TODO: Can we just trigger based on setRunning:?
- if (target.running != subaction.active) {
- if (subaction.active)
- [target trigger:controller];
- else
- [target untrigger:controller];
- target.running = subaction.active;
- }
-
- // FIXME: Hack, should just expose analog info properly in continuous target.
- if ([mainAction isKindOfClass:[JSActionAnalog class]]) {
- double realValue = [(JSActionAnalog *)mainAction getRealValue:IOHIDValueGetIntegerValue(value)];
- [target setInputValue:realValue];
- if (target.isContinuous && target.running)
- [controller addRunningTarget:target];
- }
+ 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) {
+ } else if ([NSApplication sharedApplication].isActive
+ && [NSApplication sharedApplication].mainWindow.isVisible) {
// joysticks not active, use it to select stuff
JSAction *handler = [js handlerForEvent:value];
if (!handler)
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;
- (id)initWithIndex:(int)newIndex name:(NSString *)newName base:(JSAction *)newBase;
-@property (assign) BOOL active;
-
@end
#import "SubAction.h"
-@implementation SubAction {
- BOOL active;
-}
-
-@synthesize active;
+@implementation SubAction
- (id)initWithIndex:(int)newIndex name:(NSString *)newName base:(JSAction *)newBase {
if ((self = [super init])) {
#import <Cocoa/Cocoa.h>
-@interface Target : NSObject {
- BOOL running;
- BOOL isContinuous;
- double inputValue;
-}
+@interface Target : NSObject
-@property(readwrite) BOOL running;
-@property(readonly) BOOL isContinuous;
-@property(readwrite) double inputValue;
--(void) trigger: (JoystickController *)jc;
--(void) untrigger: (JoystickController *)jc;
+@property (assign) float magnitude;
+@property (assign) BOOL running;
+@property (readonly) BOOL isContinuous;
+
+- (void)trigger;
+- (void)untrigger;
- (BOOL)update:(JoystickController *)jc;
--(NSString*) stringify;
-+(Target*) unstringify: (NSString*) str withConfigList: (NSArray*) configs;
+- (NSString*) stringify;
++ (Target *)unstringify:(NSString*)str withConfigList:(NSArray*)configs;
@end
// Created by Sam McCall on 5/05/09.
//
-@implementation Target
+@implementation Target {
+ BOOL running;
+}
+
+@synthesize magnitude;
+// TODO: Should just be NSCoding? Or like a dictionary?
+(Target*) unstringify: (NSString*) str withConfigList: (NSArray*) configs {
- NSArray* components = [str componentsSeparatedByString:@"~"];
- NSParameterAssert([components count]);
- NSString* typeTag = components[0];
- if([typeTag isEqualToString:@"key"])
- return [TargetKeyboard unstringifyImpl:components];
- if([typeTag isEqualToString:@"cfg"])
- return [TargetConfig unstringifyImpl:components withConfigList:configs];
+ NSArray* components = [str componentsSeparatedByString:@"~"];
+ NSParameterAssert([components count]);
+ NSString* typeTag = components[0];
+ if([typeTag isEqualToString:@"key"])
+ return [TargetKeyboard unstringifyImpl:components];
+ if([typeTag isEqualToString:@"cfg"])
+ return [TargetConfig unstringifyImpl:components withConfigList:configs];
if([typeTag isEqualToString:@"mmove"])
return [TargetMouseMove unstringifyImpl:components];
if([typeTag isEqualToString:@"mbtn"])
return [TargetMouseScroll unstringifyImpl:components];
if([typeTag isEqualToString:@"mtoggle"])
return [TargetToggleMouseScope unstringifyImpl:components];
-
- NSParameterAssert(NO);
- return NULL;
+
+ NSParameterAssert(NO);
+ return NULL;
}
--(NSString*) stringify {
- [self doesNotRecognizeSelector:_cmd];
- return NULL;
+- (NSString *)stringify {
+ [self doesNotRecognizeSelector:_cmd];
+ return NULL;
}
--(void) trigger: (JoystickController *)jc {
- [self doesNotRecognizeSelector:_cmd];
+- (void)trigger {
}
--(void) untrigger: (JoystickController *)jc {
- // no-op by default
+- (void)untrigger {
}
- (BOOL)update:(JoystickController *)jc {
return NO;
}
--(BOOL) isContinuous {
- return false;
+- (BOOL)isContinuous {
+ return NO;
+}
+
+- (BOOL)running {
+ return running;
+}
+
+- (void)setRunning:(BOOL)newRunning {
+ if (running != newRunning) {
+ running = newRunning;
+ if (running)
+ [self trigger];
+ else
+ [self untrigger];
+ }
}
-@synthesize inputValue, running;
@end
return target;
}
--(void) trigger: (JoystickController *)jc {
+-(void) trigger {
CGEventRef keyDown = CGEventCreateKeyboardEvent(NULL, vk, true);
CGEventPost(kCGHIDEventTap, keyDown);
CFRelease(keyDown);
}
--(void) untrigger: (JoystickController *)jc {
+-(void) untrigger {
CGEventRef keyUp = CGEventCreateKeyboardEvent(NULL, vk, false);
CGEventPost(kCGHIDEventTap, keyUp);
CFRelease(keyUp);
return target;
}
--(void) trigger: (JoystickController *)jc {
+-(void) trigger {
NSRect screenRect = [[NSScreen mainScreen] frame];
NSInteger height = screenRect.size.height;
NSPoint mouseLoc = [NSEvent mouseLocation];
CFRelease(click);
}
--(void) untrigger: (JoystickController *)jc {
+-(void) untrigger {
NSRect screenRect = [[NSScreen mainScreen] frame];
NSInteger height = screenRect.size.height;
NSPoint mouseLoc = [NSEvent mouseLocation];
return target;
}
--(void) trigger: (JoystickController *)jc {
- return;
-}
-
--(void) untrigger: (JoystickController *)jc {
- return;
-}
-
- (BOOL)update:(JoystickController *)jc {
//printf("Dir %d inputValue %f\n", [self dir], [self inputValue]);
- if (fabs([self inputValue]) < 0.01)
+ if (fabs(self.magnitude) < 0.01)
return NO; // dead zone
NSRect screenRect = [[NSScreen mainScreen] frame];
NSInteger height = screenRect.size.height;
// TODO
- double speed = 4.0;
+ float speed = 4.0;
if ([jc frontWindowOnly])
speed = 12.0;
- double dx = 0.0, dy = 0.0;
+ float dx = 0.0, dy = 0.0;
if ([self dir] == 0)
- dx = [self inputValue] * speed;
+ dx = self.magnitude * speed;
else
- dy = [self inputValue] * speed;
+ dy = self.magnitude * speed;
NSPoint mouseLoc = jc.mouseLoc;
mouseLoc.x += dx;
mouseLoc.y -= dy;
return target;
}
--(void) trigger: (JoystickController *)jc {
+-(void) trigger {
CGEventRef scroll = CGEventCreateScrollWheelEvent(NULL,
kCGScrollEventUnitLine,
1,
return target;
}
--(void) trigger: (JoystickController *)jc {
+- (void)trigger {
+ // FIXME: It's hacky to get at the controller this way, but it's
+ // also hacky to pass it. Shouldn't need to do either.
+ ApplicationController *ac = [NSApplication sharedApplication].delegate;
+ JoystickController *jc = ac.jsController;
[jc setFrontWindowOnly: ![jc frontWindowOnly]];
printf("Front window only: %d\n", [jc frontWindowOnly]);
}