From: Frank Huang Date: Mon, 30 Jul 2012 18:10:23 +0000 (-0700) Subject: Scrolling, mouse scope, icon X-Git-Tag: version-1.0~129 X-Git-Url: https://git.yukkurigames.com/?a=commitdiff_plain;h=61f8cdec21ab083b29c22aa11fda54d6005666ca;p=enjoyable.git Scrolling, mouse scope, icon --- diff --git a/Credits.rtf b/Credits.rtf index d05d232..60f8d64 100644 --- a/Credits.rtf +++ b/Credits.rtf @@ -1,8 +1,8 @@ -{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf430 +{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470 {\fonttbl\f0\fswiss\fcharset0 Helvetica;} {\colortbl;\red255\green255\blue255;} \paperw11900\paperh16840\margl1440\margr1440\vieww9800\viewh11760\viewkind0 -\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural \f0\fs24 \cf0 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\ \ @@ -10,4 +10,6 @@ The above copyright notice and this permission notice shall be included in\ all copies or substantial portions of the Software.\ \ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\ -} \ No newline at end of file +\ +\ +The joystick icon is from the Tango icon set and is public domain.} \ No newline at end of file diff --git a/English.lproj/MainMenu.xib b/English.lproj/MainMenu.xib index 60d948f..486e9db 100644 --- a/English.lproj/MainMenu.xib +++ b/English.lproj/MainMenu.xib @@ -860,6 +860,7 @@ 256 {242, 485} + YES @@ -956,6 +957,7 @@ {{1, 1}, {242, 485}} + @@ -966,6 +968,7 @@ -2147483392 {{1, 1}, {8, 298}} + _doScroller: @@ -976,6 +979,7 @@ -2147483392 {{-100, -100}, {473, 15}} + 1 @@ -985,6 +989,7 @@ {244, 487} + 133650 @@ -995,6 +1000,7 @@ {244, 487} + NSView @@ -1003,23 +1009,89 @@ 256 YES - + 268 - {{227, 57}, {180, 24}} + {{227, 241}, {180, 24}} - + + _NS:9 YES - + 67239424 0 - + LucidaGrande 13 16 _NS:9 + + + YES + + 87 + Horizontal + YES + 0 + + + 86 + Vertical + 1 + 0 + + + 1 + + + + + 268 + {{227, 137}, {180, 24}} + + + _NS:9 + YES + + 67239424 + 0 + + _NS:9 + + + YES + + 87 + Up + YES + 0 + + + 86 + Down + 1 + 0 + + + 1 + + + + + 268 + {{227, 189}, {180, 24}} + + + + _NS:9 + YES + + 67239424 + 0 + + _NS:9 YES @@ -1042,10 +1114,11 @@ 268 - {{20, 39}, {201, 388}} + {{20, 70}, {201, 369}} + - 6 + 7 1 YES @@ -1298,7 +1371,7 @@ ZSwgSW5jLiwgMjAwOQA 604110336 0 - Mouse X + Mouse movement 1211912703 @@ -1310,7 +1383,7 @@ ZSwgSW5jLiwgMjAwOQA 604110336 0 - Mouse Y + Mouse button 1211912703 @@ -1322,7 +1395,19 @@ ZSwgSW5jLiwgMjAwOQA 604110336 0 - Mouse button + Mouse scroll + + + 1211912703 + 128 + + 400 + 75 + + + 604110336 + 0 + Toggle mouse scope 1211912703 @@ -1332,7 +1417,7 @@ ZSwgSW5jLiwgMjAwOQA 75 - {201, 63} + {201, 51} {4, 2} 1151868928 NSActionCell @@ -1413,6 +1498,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 2322 {172, 14} + @@ -1490,11 +1576,12 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {{2, 2}, {172, 20}} + - {1, -1} + {5, 5} 0 4 @@ -1504,6 +1591,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA -2147483392 {{-100, -100}, {15, 133}} + _doScroller: @@ -1514,6 +1602,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA -2147483392 {{-100, -100}, {87, 18}} + 1 @@ -1522,8 +1611,9 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 0.94565220000000005 - {{229, 318}, {176, 24}} + {{229, 350}, {176, 24}} + 133123 @@ -1533,9 +1623,10 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 - {{226, 251}, {182, 26}} + {{226, 293}, {182, 26}} - + + YES -1539178944 @@ -1568,6 +1659,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 268 {{5, 456}, {507, 17}} + YES @@ -1590,6 +1682,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 12 {{12, 445}, {493, 5}} + {0, 0} @@ -1616,26 +1709,29 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {{253, 0}, {517, 487}} + NSView {770, 487} + YES {770, 487} + - {{0, 0}, {1920, 1178}} + {{0, 0}, {1600, 1178}} {10000000000000, 10000000000000} YES - + 256 YES @@ -1777,7 +1873,6 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 260 {{57, 4}, {39, 28}} - YES 604110336 @@ -1799,7 +1894,6 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {322, 454} - NSView @@ -2398,6 +2492,38 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 747 + + + scrollDirSelect + + + + 751 + + + + sdirChanged: + + + + 752 + + + + mouseDirSelect + + + + 756 + + + + mdirChanged: + + + + 757 + @@ -3124,6 +3250,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + + @@ -3170,6 +3298,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + @@ -3272,6 +3401,39 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + + 748 + + + + + 749 + + + YES + + + + + + 750 + + + + + 754 + + + YES + + + + + + 755 + + + @@ -3401,6 +3563,13 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 744.IBPluginDependency 745.IBNSSegmentedControlInspectorSelectedSegmentMetadataKey 745.IBPluginDependency + 748.IBPluginDependency + 749.IBPluginDependency + 750.IBNSSegmentedControlInspectorSelectedSegmentMetadataKey + 750.IBPluginDependency + 754.IBPluginDependency + 755.IBNSSegmentedControlInspectorSelectedSegmentMetadataKey + 755.IBPluginDependency 81.IBPluginDependency 83.IBPluginDependency 92.IBPluginDependency @@ -3532,6 +3701,13 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -3547,15 +3723,445 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA - 747 + 757 + + + + YES + + ApplicationController + NSObject + + toggleActivity: + id + + + toggleActivity: + + toggleActivity: + id + + + + YES + + YES + activeButton + activeMenuItem + configsController + dockMenuBase + drawer + jsController + mainWindow + targetController + + + YES + NSToolbarItem + NSMenuItem + ConfigsController + NSMenu + NSDrawer + JoystickController + NSWindow + TargetController + + + + YES + + YES + activeButton + activeMenuItem + configsController + dockMenuBase + drawer + jsController + mainWindow + targetController + + + YES + + activeButton + NSToolbarItem + + + activeMenuItem + NSMenuItem + + + configsController + ConfigsController + + + dockMenuBase + NSMenu + + + drawer + NSDrawer + + + jsController + JoystickController + + + mainWindow + NSWindow + + + targetController + TargetController + + + + + IBProjectSource + ./Classes/ApplicationController.h + + + + ConfigsController + NSObject + + YES + + YES + addPressed: + removePressed: + + + YES + id + id + + + + YES + + YES + addPressed: + removePressed: + + + YES + + addPressed: + id + + + removePressed: + id + + + + + YES + + YES + removeButton + tableView + targetController + + + YES + NSButton + NSTableView + TargetController + + + + YES + + YES + removeButton + tableView + targetController + + + YES + + removeButton + NSButton + + + tableView + NSTableView + + + targetController + TargetController + + + + + IBProjectSource + ./Classes/ConfigsController.h + + + + JoystickController + NSObject + + YES + + YES + configsController + outlineView + targetController + + + YES + ConfigsController + NSOutlineView + TargetController + + + + YES + + YES + configsController + outlineView + targetController + + + YES + + configsController + ConfigsController + + + outlineView + NSOutlineView + + + targetController + TargetController + + + + + IBProjectSource + ./Classes/JoystickController.h + + + + KeyInputTextView + NSTextView + + YES + + YES + targetController + window + + + YES + TargetController + NSWindow + + + + YES + + YES + targetController + window + + + YES + + targetController + TargetController + + + window + NSWindow + + + + + IBProjectSource + ./Classes/KeyInputTextView.h + + + + TargetController + NSObject + + YES + + YES + configChosen: + mbtnChanged: + mdirChanged: + radioChanged: + sdirChanged: + + + YES + id + id + id + id + id + + + + YES + + YES + configChosen: + mbtnChanged: + mdirChanged: + radioChanged: + sdirChanged: + + + YES + + configChosen: + id + + + mbtnChanged: + id + + + mdirChanged: + id + + + radioChanged: + id + + + sdirChanged: + id + + + + + YES + + YES + configPopup + configsController + joystickController + keyInput + mouseBtnSelect + mouseDirSelect + radioButtons + radioConfig + radioKey + radioNoAction + scrollDirSelect + title + + + YES + NSPopUpButton + ConfigsController + JoystickController + KeyInputTextView + NSSegmentedControl + NSSegmentedControl + NSMatrix + NSButtonCell + NSButtonCell + NSButtonCell + NSSegmentedControl + NSTextField + + + + YES + + YES + configPopup + configsController + joystickController + keyInput + mouseBtnSelect + mouseDirSelect + radioButtons + radioConfig + radioKey + radioNoAction + scrollDirSelect + title + + + YES + + configPopup + NSPopUpButton + + + configsController + ConfigsController + + + joystickController + JoystickController + + + keyInput + KeyInputTextView + + + mouseBtnSelect + NSSegmentedControl + + + mouseDirSelect + NSSegmentedControl + + + radioButtons + NSMatrix + + + radioConfig + NSButtonCell + + + radioKey + NSButtonCell + + + radioNoAction + NSButtonCell + + + scrollDirSelect + NSSegmentedControl + + + title + NSTextField + + + + + IBProjectSource + ./Classes/TargetController.h + + + - 0 IBCocoaFramework com.apple.InterfaceBuilder.CocoaPlugin.macosx + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 diff --git a/Enjoy.xcodeproj/project.pbxproj b/Enjoy.xcodeproj/project.pbxproj index 44084e7..8892e86 100644 --- a/Enjoy.xcodeproj/project.pbxproj +++ b/Enjoy.xcodeproj/project.pbxproj @@ -10,6 +10,8 @@ 1DDD58160DA1D0A300B32029 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1DDD58140DA1D0A300B32029 /* MainMenu.xib */; }; 8B7E476C15C314A200C588FA /* TargetMouseBtn.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B7E476B15C314A200C588FA /* TargetMouseBtn.m */; }; 8BD9B54315C230FF00929C5D /* TargetMouseMove.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BD9B54215C230FE00929C5D /* TargetMouseMove.m */; }; + 8BEFAD9C15C46BFF00823AEC /* TargetMouseScroll.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BEFAD9B15C46BFF00823AEC /* TargetMouseScroll.m */; }; + 8BEFADA015C476DC00823AEC /* TargetToggleMouseScope.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BEFAD9F15C476DC00823AEC /* TargetToggleMouseScope.m */; }; 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; }; 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; @@ -47,6 +49,10 @@ 8B7E476B15C314A200C588FA /* TargetMouseBtn.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TargetMouseBtn.m; sourceTree = ""; }; 8BD9B54115C230FE00929C5D /* TargetMouseMove.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TargetMouseMove.h; sourceTree = ""; }; 8BD9B54215C230FE00929C5D /* TargetMouseMove.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TargetMouseMove.m; sourceTree = ""; }; + 8BEFAD9A15C46BFF00823AEC /* TargetMouseScroll.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TargetMouseScroll.h; sourceTree = ""; }; + 8BEFAD9B15C46BFF00823AEC /* TargetMouseScroll.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TargetMouseScroll.m; sourceTree = ""; }; + 8BEFAD9E15C476DC00823AEC /* TargetToggleMouseScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TargetToggleMouseScope.h; sourceTree = ""; }; + 8BEFAD9F15C476DC00823AEC /* TargetToggleMouseScope.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TargetToggleMouseScope.m; sourceTree = ""; }; 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 8D1107320486CEB800E47090 /* Enjoy.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Enjoy.app; sourceTree = BUILT_PRODUCTS_DIR; }; D549CA4B0FBB441B00BC8203 /* Credits.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = Credits.rtf; sourceTree = ""; }; @@ -136,6 +142,10 @@ 8BD9B54215C230FE00929C5D /* TargetMouseMove.m */, 8B7E476A15C314A200C588FA /* TargetMouseBtn.h */, 8B7E476B15C314A200C588FA /* TargetMouseBtn.m */, + 8BEFAD9A15C46BFF00823AEC /* TargetMouseScroll.h */, + 8BEFAD9B15C46BFF00823AEC /* TargetMouseScroll.m */, + 8BEFAD9E15C476DC00823AEC /* TargetToggleMouseScope.h */, + 8BEFAD9F15C476DC00823AEC /* TargetToggleMouseScope.m */, ); name = Classes; sourceTree = ""; @@ -292,6 +302,8 @@ D5F809710FB093400006A4DE /* TargetConfig.m in Sources */, 8BD9B54315C230FF00929C5D /* TargetMouseMove.m in Sources */, 8B7E476C15C314A200C588FA /* TargetMouseBtn.m in Sources */, + 8BEFAD9C15C46BFF00823AEC /* TargetMouseScroll.m in Sources */, + 8BEFADA015C476DC00823AEC /* TargetToggleMouseScope.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Enjoy_Prefix.pch b/Enjoy_Prefix.pch index b915d20..0fab501 100644 --- a/Enjoy_Prefix.pch +++ b/Enjoy_Prefix.pch @@ -24,4 +24,6 @@ #import "TargetController.h" #import "TargetKeyboard.h" #import "TargetMouseMove.h" -#import "TargetMouseBtn.h" \ No newline at end of file +#import "TargetMouseBtn.h" +#import "TargetMouseScroll.h" +#import "TargetToggleMouseScope.h" \ No newline at end of file diff --git a/JSActionAnalog.h b/JSActionAnalog.h index 5087582..f1276d5 100644 --- a/JSActionAnalog.h +++ b/JSActionAnalog.h @@ -16,4 +16,7 @@ @property(readwrite) double offset; @property(readwrite) double scale; +- (id) initWithIndex: (int)newIndex; +-(double) getRealValue: (int) value; + @end diff --git a/JSActionAnalog.m b/JSActionAnalog.m index a1c57e8..e351996 100644 --- a/JSActionAnalog.m +++ b/JSActionAnalog.m @@ -30,7 +30,7 @@ //Target* target = [[base->configsController currentConfig] getTargetForAction: [subActions objectAtIndex: 0]]; int raw = IOHIDValueGetIntegerValue(value); - double parsed = offset + scale * raw; + double parsed = [self getRealValue: raw]; if(parsed < -0.3) // fixed?! return [subActions objectAtIndex: 0]; @@ -44,12 +44,17 @@ [[subActions objectAtIndex: 2] setActive: true]; int raw = IOHIDValueGetIntegerValue(value); - double parsed = offset + scale * raw; + double parsed = [self getRealValue: raw]; [[subActions objectAtIndex: 0] setActive: (parsed < -0.3)]; [[subActions objectAtIndex: 1] setActive: (parsed > 0.3)]; } +-(double) getRealValue: (int)value { + double parsed = offset + scale * value; + return parsed; +} + @synthesize offset, scale; diff --git a/JoystickController.h b/JoystickController.h index 4c878f2..aa95815 100644 --- a/JoystickController.h +++ b/JoystickController.h @@ -15,12 +15,17 @@ @interface JoystickController : NSObject { NSMutableArray *joysticks; + NSMutableArray *runningTargets; IOHIDManagerRef hidManager; IBOutlet NSOutlineView* outlineView; IBOutlet TargetController* targetController; IBOutlet ConfigsController* configsController; id selectedAction; BOOL programmaticallySelecting; + BOOL frontWindowOnly; + + @public + NSPoint mouseLoc; } -(void) setup; @@ -28,5 +33,7 @@ @property(readonly) id selectedAction; @property(readonly) NSMutableArray *joysticks; +@property(readonly) NSMutableArray *runningTargets; +@property(readwrite) BOOL frontWindowOnly; @end diff --git a/JoystickController.m b/JoystickController.m index b510848..976b531 100644 --- a/JoystickController.m +++ b/JoystickController.m @@ -5,14 +5,18 @@ // 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; } @@ -40,6 +44,22 @@ 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); @@ -61,8 +81,27 @@ void input_callback(void* inContext, IOReturn inResult, void* inSender, IOHIDVal 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 @@ -134,11 +173,11 @@ void remove_callback(void* inContext, IOReturn inResult, void* inSender, IOHIDDe 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), + //create_criterion(kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard), nil]; IOHIDManagerSetDeviceMatchingMultiple(hidManager, (CFArrayRef)criteria); - + IOHIDManagerScheduleWithRunLoop( hidManager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode ); IOReturn tIOReturn = IOHIDManagerOpen( hidManager, kIOHIDOptionsTypeNone ); (void)tIOReturn; @@ -147,6 +186,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 { diff --git a/README.md b/README.md index daf4ed6..2a7c478 100644 --- a/README.md +++ b/README.md @@ -8,11 +8,21 @@ If you've ever played a video game which only supports mouse and keyboard input, * Key events * Mouse clicks * Mouse movement (for analog sticks) +* Scrolling Enjoy2 supports multiple configurations (for different games or programs) and you can even map joystick buttons to change configurations on-the-fly. Enjoy2 is written by [Yifeng Huang](htty://nongraphical.com) and is based on [Enjoy by Sam McCall](http://abstractable.net/enjoy/). Enjoy is MIT-licensed. +## How to use + +At startup, and when Enjoy2 is paused, press any button or move any analog stick to jump to the configuration for that button or stick. From there, select one of the mapping options from the choices on the right. + +To use an analog axis to move the mouse, select the "Analog" sub-item on the left. + +### Mapping modes + +Enjoy2 offers two mouse mapping modes: global and single-window. Enjoy2 starts in global mode, but you can set any joystick button to the "toggle mouse scope" action, which will change the mode. If you are using Enjoy2 to play a video game, you may find that one or the other mode offers better compatibility with your game's specific requirements. ## Requirements @@ -25,4 +35,6 @@ Version 1.1 * Forked from Enjoy * Mouse movement support -* Mouse button support \ No newline at end of file +* Mouse button support +* Scrollwheel support +* Support for two mouse movement modes diff --git a/Target.h b/Target.h index 215245f..43b7d0c 100644 --- a/Target.h +++ b/Target.h @@ -10,13 +10,16 @@ @interface Target : NSObject { BOOL running; - int inputValue; + BOOL isContinuous; + double inputValue; } @property(readwrite) BOOL running; -@property(readwrite) int inputValue; --(void) trigger; --(void) untrigger; +@property(readonly) BOOL isContinuous; +@property(readwrite) double inputValue; +-(void) trigger: (JoystickController *)jc; +-(void) untrigger: (JoystickController *)jc; +-(void) update: (JoystickController *)jc; -(NSString*) stringify; +(Target*) unstringify: (NSString*) str withConfigList: (NSArray*) configs; diff --git a/Target.m b/Target.m index 35ebfc2..ec2d6a1 100644 --- a/Target.m +++ b/Target.m @@ -19,6 +19,10 @@ return [TargetMouseMove unstringifyImpl:components]; if([typeTag isEqualToString:@"mbtn"]) return [TargetMouseBtn unstringifyImpl:components]; + if([typeTag isEqualToString:@"mscroll"]) + return [TargetMouseScroll unstringifyImpl:components]; + if([typeTag isEqualToString:@"mtoggle"]) + return [TargetToggleMouseScope unstringifyImpl:components]; NSParameterAssert(NO); return NULL; @@ -29,27 +33,22 @@ return NULL; } --(void) trigger { +-(void) trigger: (JoystickController *)jc { [self doesNotRecognizeSelector:_cmd]; } --(void) untrigger { +-(void) untrigger: (JoystickController *)jc { // no-op by default } --(BOOL) running { - return running; +-(void) update: (JoystickController *) jc { + [self doesNotRecognizeSelector:_cmd]; } --(void) setRunning: (BOOL) newRunning { - if(newRunning == running) - return; - if(newRunning) - [self trigger]; - else - [self untrigger]; - running = newRunning; + +-(BOOL) isContinuous { + return false; } -@synthesize inputValue; +@synthesize inputValue, running; @end diff --git a/TargetController.h b/TargetController.h index f68a6da..2d499b7 100644 --- a/TargetController.h +++ b/TargetController.h @@ -18,7 +18,9 @@ IBOutlet KeyInputTextView* keyInput; IBOutlet NSButtonCell *radioNoAction, *radioKey, *radioConfig; IBOutlet NSMatrix* radioButtons; + IBOutlet NSSegmentedControl* mouseDirSelect; IBOutlet NSSegmentedControl* mouseBtnSelect; + IBOutlet NSSegmentedControl* scrollDirSelect; IBOutlet NSTextField* title; IBOutlet NSPopUpButton* configPopup; IBOutlet ConfigsController* configsController; @@ -34,7 +36,9 @@ -(void) refreshConfigsPreservingSelection: (BOOL) preserve; -(IBAction)configChosen:(id)sender; -(IBAction)radioChanged:(id)sender; +-(IBAction)mdirChanged:(id)sender; -(IBAction)mbtnChanged:(id)sender; +-(IBAction)sdirChanged:(id)sender; -(void) focusKey; @property(readwrite) BOOL enabled; diff --git a/TargetController.m b/TargetController.m index 9b075a1..3442a61 100644 --- a/TargetController.m +++ b/TargetController.m @@ -15,7 +15,17 @@ [[[NSApplication sharedApplication] mainWindow] makeFirstResponder: sender]; [self commit]; } +-(IBAction)mdirChanged:(id)sender { + [radioButtons setState: 1 atRow: 3 column: 0]; + [[[NSApplication sharedApplication] mainWindow] makeFirstResponder: sender]; + [self commit]; +} -(IBAction)mbtnChanged:(id)sender { + [radioButtons setState: 1 atRow: 4 column: 0]; + [[[NSApplication sharedApplication] mainWindow] makeFirstResponder: sender]; + [self commit]; +} +-(IBAction)sdirChanged:(id)sender { [radioButtons setState: 1 atRow: 5 column: 0]; [[[NSApplication sharedApplication] mainWindow] makeFirstResponder: sender]; [self commit]; @@ -41,18 +51,12 @@ return c; } case 3: { - // mouse X + // mouse X/Y TargetMouseMove *mm = [[TargetMouseMove alloc] init]; - [mm setDir: 0]; + [mm setDir: [mouseDirSelect selectedSegment]]; return mm; } case 4: { - // mouse Y - TargetMouseMove *mm = [[TargetMouseMove alloc] init]; - [mm setDir: 1]; - return mm; - } - case 5: { // mouse button TargetMouseBtn *mb = [[TargetMouseBtn alloc] init]; if ([mouseBtnSelect selectedSegment] == 0) { @@ -63,6 +67,22 @@ } return mb; } + case 5: { + // scroll + TargetMouseScroll *ms = [[TargetMouseScroll alloc] init]; + if ([scrollDirSelect selectedSegment] == 0) { + [ms setHowMuch: -1]; + } + else { + [ms setHowMuch: 1]; + } + return ms; + } + case 6: { + // toggle mouse scope + TargetToggleMouseScope *tms = [[TargetToggleMouseScope alloc] init]; + return tms; + } } return NULL; } @@ -83,7 +103,9 @@ -(void) reset { [keyInput clear]; [radioButtons setState: 1 atRow: 0 column: 0]; + [mouseDirSelect setSelectedSegment: 0]; [mouseBtnSelect setSelectedSegment: 0]; + [scrollDirSelect setSelectedSegment: 0]; [self refreshConfigsPreservingSelection: NO]; } @@ -91,7 +113,9 @@ [radioButtons setEnabled: enabled]; [keyInput setEnabled: enabled]; [configPopup setEnabled: enabled]; + [mouseDirSelect setEnabled: enabled]; [mouseBtnSelect setEnabled: enabled]; + [scrollDirSelect setEnabled: enabled]; } -(BOOL) enabled { return [radioButtons isEnabled]; @@ -127,17 +151,25 @@ [configPopup selectItemAtIndex: [[configsController configs] indexOfObject: [(TargetConfig*)target config]]]; } else if ([target isKindOfClass: [TargetMouseMove class]]) { - if ([(TargetMouseMove *)target dir] == 0) - [radioButtons setState:1 atRow: 3 column: 0]; - else - [radioButtons setState:1 atRow: 4 column: 0]; + [radioButtons setState:1 atRow: 3 column: 0]; + [mouseDirSelect setSelectedSegment: [(TargetMouseMove *)target dir]]; } else if ([target isKindOfClass: [TargetMouseBtn class]]) { - [radioButtons setState: 1 atRow: 5 column: 0]; + [radioButtons setState: 1 atRow: 4 column: 0]; if ([(TargetMouseBtn *)target which] == kCGMouseButtonLeft) [mouseBtnSelect setSelectedSegment: 0]; else [mouseBtnSelect setSelectedSegment: 1]; + } + else if ([target isKindOfClass: [TargetMouseScroll class]]) { + [radioButtons setState: 1 atRow: 5 column: 0]; + if ([(TargetMouseScroll *)target howMuch] < 0) + [scrollDirSelect setSelectedSegment: 0]; + else + [scrollDirSelect setSelectedSegment: 1]; + } + else if ([target isKindOfClass: [TargetToggleMouseScope class]]) { + [radioButtons setState: 1 atRow: 6 column: 0]; } else { [NSException raise:@"Unknown target subclass" format:@"Unknown target subclass"]; } diff --git a/TargetKeyboard.m b/TargetKeyboard.m index 7bf9f83..40661b8 100644 --- a/TargetKeyboard.m +++ b/TargetKeyboard.m @@ -21,13 +21,13 @@ return target; } --(void) trigger { +-(void) trigger: (JoystickController *)jc { CGEventRef keyDown = CGEventCreateKeyboardEvent(NULL, vk, true); CGEventPost(kCGHIDEventTap, keyDown); CFRelease(keyDown); } --(void) untrigger { +-(void) untrigger: (JoystickController *)jc { CGEventRef keyUp = CGEventCreateKeyboardEvent(NULL, vk, false); CGEventPost(kCGHIDEventTap, keyUp); CFRelease(keyUp); diff --git a/TargetMouseBtn.m b/TargetMouseBtn.m index 857de7b..7429874 100644 --- a/TargetMouseBtn.m +++ b/TargetMouseBtn.m @@ -23,7 +23,7 @@ return target; } --(void) trigger { +-(void) trigger: (JoystickController *)jc { NSRect screenRect = [[NSScreen mainScreen] frame]; NSInteger height = screenRect.size.height; NSPoint mouseLoc = [NSEvent mouseLocation]; @@ -36,7 +36,7 @@ CFRelease(click); } --(void) untrigger { +-(void) untrigger: (JoystickController *)jc { NSRect screenRect = [[NSScreen mainScreen] frame]; NSInteger height = screenRect.size.height; NSPoint mouseLoc = [NSEvent mouseLocation]; diff --git a/TargetMouseMove.m b/TargetMouseMove.m index 2bcbce3..8cf09d2 100644 --- a/TargetMouseMove.m +++ b/TargetMouseMove.m @@ -10,20 +10,8 @@ @implementation TargetMouseMove --(void) setInputValue: (int) newIV { - NSRect screenRect = [[NSScreen mainScreen] frame]; - NSInteger height = screenRect.size.height; - NSPoint mouseLoc = [NSEvent mouseLocation]; - if (dir == 0) - mouseLoc.x += newIV; - else - mouseLoc.y += newIV; - - CGEventRef move = CGEventCreateMouseEvent(NULL, kCGEventMouseMoved, - CGPointMake(mouseLoc.x, height - mouseLoc.y), - kCGMouseButtonLeft); - CGEventPost(kCGHIDEventTap, move); - CFRelease(move); +-(BOOL) isContinuous { + return true; } @synthesize dir; @@ -39,12 +27,52 @@ return target; } --(void) trigger { +-(void) trigger: (JoystickController *)jc { return; } --(void) untrigger { +-(void) untrigger: (JoystickController *)jc { return; } +-(void) update: (JoystickController *)jc { + //printf("Dir %d inputValue %f\n", [self dir], [self inputValue]); + if (fabs([self inputValue]) < 0.01) + return; // dead zone + + NSRect screenRect = [[NSScreen mainScreen] frame]; + NSInteger height = screenRect.size.height; + + // TODO + double speed = 4.0; + if ([jc frontWindowOnly]) + speed = 12.0; + double dx = 0.0, dy = 0.0; + if ([self dir] == 0) + dx = [self inputValue] * speed; + else + dy = [self inputValue] * speed; + NSPoint *mouseLoc = &jc->mouseLoc; + mouseLoc->x += dx; + mouseLoc->y -= dy; + + CGEventRef move = CGEventCreateMouseEvent(NULL, kCGEventMouseMoved, + CGPointMake(mouseLoc->x, height - mouseLoc->y), + 0); + CGEventSetType(move, kCGEventMouseMoved); + CGEventSetIntegerValueField(move, kCGMouseEventDeltaX, dx); + CGEventSetIntegerValueField(move, kCGMouseEventDeltaY, dy); + + if ([jc frontWindowOnly]) { + ProcessSerialNumber psn; + GetFrontProcess(&psn); + CGEventPostToPSN(&psn, move); + } + else { + CGEventPost(kCGHIDEventTap, move); + } + + CFRelease(move); +} + @end diff --git a/TargetMouseScroll.h b/TargetMouseScroll.h new file mode 100644 index 0000000..ddafef4 --- /dev/null +++ b/TargetMouseScroll.h @@ -0,0 +1,19 @@ +// +// TargetMouseScroll.h +// Enjoy +// +// Created by Yifeng Huang on 7/28/12. +// Copyright (c) 2012 __MyCompanyName__. All rights reserved. +// + +#import + +@interface TargetMouseScroll : Target { + int howMuch; +} + +@property(readwrite) int howMuch; + ++(TargetMouseScroll*) unstringifyImpl: (NSArray*) comps; + +@end diff --git a/TargetMouseScroll.m b/TargetMouseScroll.m new file mode 100644 index 0000000..a1cca9c --- /dev/null +++ b/TargetMouseScroll.m @@ -0,0 +1,35 @@ +// +// TargetMouseScroll.m +// Enjoy +// +// Created by Yifeng Huang on 7/28/12. +// Copyright (c) 2012 __MyCompanyName__. All rights reserved. +// + +#import "TargetMouseScroll.h" + +@implementation TargetMouseScroll + +@synthesize howMuch; + +-(NSString*) stringify { + return [[NSString alloc] initWithFormat: @"mscroll~%d", howMuch]; +} + ++(TargetMouseScroll*) unstringifyImpl: (NSArray*) comps { + NSParameterAssert([comps count] == 2); + TargetMouseScroll* target = [[TargetMouseScroll alloc] init]; + [target setHowMuch: [[comps objectAtIndex:1] integerValue]]; + return target; +} + +-(void) trigger: (JoystickController *)jc { + CGEventRef scroll = CGEventCreateScrollWheelEvent(NULL, + kCGScrollEventUnitLine, + 1, + [self howMuch]); + CGEventPost(kCGHIDEventTap, scroll); + CFRelease(scroll); +} + +@end diff --git a/TargetToggleMouseScope.h b/TargetToggleMouseScope.h new file mode 100644 index 0000000..f167b5e --- /dev/null +++ b/TargetToggleMouseScope.h @@ -0,0 +1,15 @@ +// +// TargetToggleMouseScope.h +// Enjoy +// +// Created by Yifeng Huang on 7/28/12. +// Copyright (c) 2012 __MyCompanyName__. All rights reserved. +// + +#import "Target.h" + +@interface TargetToggleMouseScope : Target + ++(TargetToggleMouseScope*) unstringifyImpl: (NSArray*) comps; + +@end diff --git a/TargetToggleMouseScope.m b/TargetToggleMouseScope.m new file mode 100644 index 0000000..55357e5 --- /dev/null +++ b/TargetToggleMouseScope.m @@ -0,0 +1,28 @@ +// +// TargetToggleMouseScope.m +// Enjoy +// +// Created by Yifeng Huang on 7/28/12. +// Copyright (c) 2012 __MyCompanyName__. All rights reserved. +// + +#import "TargetToggleMouseScope.h" + +@implementation TargetToggleMouseScope + +-(NSString*) stringify { + return [[NSString alloc] initWithFormat: @"mtoggle"]; +} + ++(TargetToggleMouseScope*) unstringifyImpl: (NSArray*) comps { + NSParameterAssert([comps count] == 1); + TargetToggleMouseScope* target = [[TargetToggleMouseScope alloc] init]; + return target; +} + +-(void) trigger: (JoystickController *)jc { + [jc setFrontWindowOnly: ![jc frontWindowOnly]]; + printf("Front window only: %d\n", [jc frontWindowOnly]); +} + +@end diff --git a/icon.icns b/icon.icns new file mode 100644 index 0000000..d9a900d Binary files /dev/null and b/icon.icns differ