diff --git a/D3DCursor/D3DCursor.vcxproj b/D3DCursor/D3DCursor.vcxproj index 3132ac2e..ba644060 100644 --- a/D3DCursor/D3DCursor.vcxproj +++ b/D3DCursor/D3DCursor.vcxproj @@ -1,144 +1,144 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {4796387A-2F8E-4ED0-96E4-A72137B4428C} - Win32Proj - D3DCursor - - - - DynamicLibrary - true - v120 - Unicode - - - DynamicLibrary - false - v120 - true - Unicode - - - v120 - Unicode - DynamicLibrary - - - v120 - Unicode - DynamicLibrary - true - - - - - - - - - - - - - false - $(DXSDK_DIR)Include;$(IncludePath) - $(DXSDK_DIR)Lib\x86;$(LibraryPath) - $(ProjectDir)..\bin\x86\$(Configuration)\ - x86\$(Configuration)\ - - - false - $(DXSDK_DIR)Include;$(IncludePath) - $(DXSDK_DIR)Lib\x86;$(LibraryPath) - $(ProjectDir)..\bin\x86\$(Configuration)\ - x86\$(Configuration)\ - - - $(DXSDK_DIR)Include;$(IncludePath) - $(DXSDK_DIR)Lib\x64;$(LibraryPath) - false - $(ProjectDir)..\bin\$(Platform)\$(Configuration)\ - - - $(DXSDK_DIR)Include;$(IncludePath) - $(DXSDK_DIR)Lib\x64;$(LibraryPath) - false - $(ProjectDir)..\bin\$(Platform)\$(Configuration)\ - - - - NotUsing - Level3 - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;D3DCURSOR_EXPORTS;%(PreprocessorDefinitions) - true - - - Windows - true - - - - - Level3 - NotUsing - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;D3DCURSOR_EXPORTS;%(PreprocessorDefinitions) - - - Windows - true - true - true - - - - - Disabled - NotUsing - Level3 - - - true - - - Windows - - - - - NotUsing - true - - - Windows - - - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {4796387A-2F8E-4ED0-96E4-A72137B4428C} + Win32Proj + D3DCursor + + + + DynamicLibrary + true + v140 + Unicode + + + DynamicLibrary + false + v140 + true + Unicode + + + v140 + Unicode + DynamicLibrary + + + v140 + Unicode + DynamicLibrary + true + + + + + + + + + + + + + false + $(DXSDK_DIR)Include;$(IncludePath) + $(DXSDK_DIR)Lib\x86;$(LibraryPath) + $(ProjectDir)..\bin\x86\$(Configuration)\ + x86\$(Configuration)\ + + + false + $(DXSDK_DIR)Include;$(IncludePath) + $(DXSDK_DIR)Lib\x86;$(LibraryPath) + $(ProjectDir)..\bin\x86\$(Configuration)\ + x86\$(Configuration)\ + + + $(DXSDK_DIR)Include;$(IncludePath) + $(DXSDK_DIR)Lib\x64;$(LibraryPath) + false + $(ProjectDir)..\bin\$(Platform)\$(Configuration)\ + + + $(DXSDK_DIR)Include;$(IncludePath) + $(DXSDK_DIR)Lib\x64;$(LibraryPath) + false + $(ProjectDir)..\bin\$(Platform)\$(Configuration)\ + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;D3DCURSOR_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + Level3 + NotUsing + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;D3DCURSOR_EXPORTS;%(PreprocessorDefinitions) + + + Windows + true + true + true + + + + + Disabled + NotUsing + Level3 + + + true + + + Windows + + + + + NotUsing + true + + + Windows + + + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index 11eb0e51..10c3d78d 100644 --- a/README.md +++ b/README.md @@ -1,128 +1,124 @@ -Touchmote +BIO: ============== -Introducing Touchmote, a Windows app to control the Windows 8 Metro interface from your couch.
-Swipe, scroll and tap by pointing your Wiimote on your screen or HDTV. +Hy Dear Gamers! I am an electrotechnicer and programmer. I think i write some special code algorythm for touchmote to play ALL TYPE OF GAMES FOR FREE from couch. The Wiimote is very special and senstivy stuff. +When i firstly meet with WiiRemote i think i have Parkinson :D, but i not have. Just placed it to a paper box and aim to sensor bar and leave it alone and the cursor not shaked anymore. +That mean the wiimote is very sensitive and just need an effective interpolation system. That was i made. NO handshake, NO deadzone, NO buffer just precise fast mouse moves ;) +I played out Doom twice on ultra violence while i programming, so i know it is work fine! -Visit http://touchmote.net/ for a compiled installer. +FLYFPS Mode Description +============== +This mode for Touchmote is designed to play all types of games. FPS, flysym, strategy... FlyFPS mode use NOT AIM TO SCREEN but use AIM TO SENSORBAR method. +This mode have 6 innovative mouse moving for turn. -Touchmote is based on the WiiTUIO project which allows data from a Wii Remote to be translated as genuine Windows touch events.
-Touch position is calculated using the Wii Sensor Bar.
-The application is developed in primarily C# .NET 4.5 and some C++. +You can several SETTINGS (see below SETTINGS:) defining for mouse move. (1:flyfps_main, 2:flyfps_fine, 3:flyfps_mouse_forward, 4:flyfps_extra_turn, 5:flyfps_border_turn, 6:flyfps_auto_turn) -Prerequisites -============== -1x Nintendo Wii Remote
-1x Wireless Wii Sensor Bar
-1x Bluetooth enabled computer with Windows 8 +I mean important thing to set pointer_FPS syncron with your game frame rate or increase the pointer_FPS in the settings.json file while you not have the desired moving/turning. +Otherwise the mouse move still laggy or stutter. ie: i locked the doom to 60 frame rate and set the pointer_FPS to 200 and i can shoot very precisly and fast. -Bug reports -============== -Please use the GitHub Issue tracker to report bugs. Always include the following information:
-1. System configuration, including Bluetooth device vendor and model
-2. Steps to reproduce the error
-3. Expected output
-4. Actual output
+The Wiimote is VERY sensitive. Just chock your wrist on your leg or on the bed. When you leave with your pointer the sensorbar area and camera stopped, just aim to sensorbar fast as you can. -How to build -============== -*First install:*
-Microsoft Visual Studio 2013
-Direct X SDK +TIPP: when your camera not move ie: Doom glory kill or entering a vechile. Just recenter your pointer. +Try setup in settings.json in touchmote directory. Just increasing values step by step and test it on your game while it is reach the desired smooth fast motion. -1. Install the Touchmote drivers and test certificate by running the installer from touchmote.net
-2. Run Visual Studio "as Administrator". Open the project file Touchmote.sln.
-3. If you want to use the debugger, edit the file called app.manifest and change uiAccess to false. Otherwise the app has to be run under Program Files. This is for the cursor to be able to show on top of the Modern UI.
-4. Go to Build->Configuration manager...
-5. Choose solution platform for either x86 or x64 depending on your system. Close it and Build.
-Credits +IMPORTANT: ============== -WiimoteLib 1.7: http://wiimotelib.codeplex.com/
-WiiTUIO project: http://code.google.com/p/wiituio/
-TouchInjector: http://touchinjector.codeplex.com/
-Scarlet.Crush Xinput wrapper: http://forums.pcsx2.net/Thread-XInput-Wrapper-for-DS3-and-Play-com-USB-Dual-DS2-Controller
-WiiPair: http://www.richlynch.com/code/wiipair
-EcoTUIOdriver: https://github.com/ecologylab/EcoTUIODriver
-MultiTouchVista: http://multitouchvista.codeplex.com
- -Release History +flyfps_main_mouse: this is the main mouse mover. You can draw a vector with your IRpointer that move your mouse. + +flyfps_main_acceleration mouse: this is the acceleration of vector mouse. This work independent from mouse vector sensitivity. Can use alone. + +flyfps_main_acceleration_finer: This value define how fast react your mouse acceleration for IRpointer acceleration. When you increase this value the mouse react slower. This is very sensitive. This value define how fast can you react for things in game. + +flyfps_fine_sensitivity: this is the fine mouse aim. When you hold the right and left mouse button then activate it. ie: assign your right mouse button to the Remote B or A button. I use for fire mouse left = A button, fine aim right mouse = B button. + +flyfps_mouse_forward: this activated when your hand arriving a specified acceleration (flyfps_mouse_forward_turn_on_threshold) and move the mouse with specified distance. + +flyfps_extra_turn: this is relative for your pointer position. When you move your IRponter in the desired direction this accelerated in specified distance to the specified sensitivity. + +flyfps_border_turn_speed: when your pointer leave the border this accelerated your mouse depending the pointer distance from border. + +flyfps_auto_turn_speed: when your pointer leave the border this continuosly move your mouse, the speed depending from the pointer distance from border + +All these thing work individually, independent from each other. + +SETTINGS: ============== +flyfps_horizontal_screen_border: 50.0, // range 0 - 100, this is the width of rectangle on screen in percent, when pointer leave this border than start work flyfps_border_turn_speed or flyfps_auto_turn_speed + +flyfps_vertical_screen_border: 80.0, // range 0 - 100, this is the height of rectangle in percent, when pointer leave this border than start work flyfps_border_turn_speed or flyfps_auto_turn_speed + +flyfps_mouse_finer_low: 85, // range 0 - 100, default = 85, step 0.1, this fining your mouse moves on low hand speed. Decreasing the distance of two mouse steps. The result is very fine and smooth mouse move. When increaseing pointer_FPS the move is faster you can add more fining. I prefer pointer_FPS=200,in the game lock fps to 60FPS. When you set your framerate in touchmote(ie:60-120-180-200FPS) and in the game(ie:30-60FPS+) that give the best result. Just try it :) I use for Doom 60FPS locked and pointer_FPS=200 + +flyfps_mouse_finer_high: 75, // range 0 - 100, default = 75, step 0.1, this fining your mouse moves on high hand speed. Decreasing the distance of two mouse steps. The result is very fine and smooth mouse move. When increaseing pointer_FPS the move is faster you can add more fining. I prefer pointer_FPS=200,in the game lock fps to 60FPS. When you set your framerate in touchmote(ie:60-120-180-200FPS) and in the game(ie:30-60FPS+) that give the best result. Just try it what is the smoothest setting :) Bigger steps on higher hand speed give faster mouse move + +flyfps_mouse_finer_threshold: 5, // range 0 - 100, default = 5, step 1, When mouse speed(pixel) reach this value the mousefiner reach flyfps_mouse_finer_high. Below this value flyfps_mouse_finer_low ranged to flyfps_mouse_finer_high. With mouse finer you can calibrate how fast follow the camera the IRmouse. + +flyfps_out_bound_decceleration: 10.0, //range 0-100, step 0.1, default = 10, when leave the sensorbar bounds, the mouse speed deccelerated with this value. When you set it 0 then the pointer leave the sensorbar the mouse turn continously for the desired direction. + +flyfps_return_bound_acceleration: 5.0, //range 0-100, step 0,1, default = 5, When the pointer return from out of bounds, the speed of mouse start from 0 and increased with this acceleration. When lower the value, you have more time for recenter your pointer to the sensor bar after you leave the sensed zone. + +flyfps_main_buffer: 1, // range 1+; 1 = BUFFER OFF :) This buffer smoothing your shaking hand when you need, JUST IN MAIN AND FINE MOUSE, but keep in mind, this slowing down the reaction time. Set it to lowes value where your cursor not shaked. Default 1 for me, main_sens = 0.25; 1 = no buffering + +flyfps_main_sensitivity: 0.25,// range 0-10, step 0.01, default = 0.25, Sensitivity X and Y of mouse vector. When main_sensitivity_y=0 then main_sensitivity_y calculated from main_sensitivity by actual screen aspect ratio. You can draw the mosue vector with pointer. This drawed vector move the mouse. This work independent from acceleration. + +flyfps_main_decceleration_low: 4.5, //range 0-100, step 0.1, default = 4.5. When your hand speed is slow, this ranged to flyfps_main_decceleration_high when you move faster. This value decrease the pointer drawed mouse mover vector in each frame. When you not slow down the mouse vector, it turns for continously. Bigger value give more decceleration. This work independently from acceleration. + +flyfps_main_decceleration_high: 10.0, //range 0-100, step 0.1, default = 10. When your hand speed is fast, this ranged to flyfps_main_decceleration_low when you move slower. This value decrease the pointer drawed mouse mover vector in each frame. When you not slow down the mouse vector, it turns for continously. Bigger value give more decceleration. When flyfps_main_decceleration_high < flyfps_main_decceleration_low than your faster hand speed not break the mouse vector. But when flyfps_main_decceleration_end > flyfps_main_decceleration_start, you can break the mouse, so not slide when you wanna make a fast turn. This work independently from acceleration. + +flyfps_main_decceleration_threshold: 50 //range 0-100, step 0.01, default = 50, When your hand speed above flyfps_main_decceleration_threshold the mouse deceleration = flyfps_main_decceleration_high. When your hand speed slower then flyfps_main_decceleration_threshold the mouse deceleration ranged from flyfps_main_decceleration_low to flyfps_main_decceleration_high. When you lower this value, mouse speed reach faster flyfps_main_decceleration_high. + +flyfps_main_acceleration: 30.0, //range 0+, step 0.1, default = 30, multiply the mouse speed depending from the current hand speed. Acceleration X and Y of mouse vector. When vector_acceleration_y=0 then vector_acceleration_y calculated from vector_acceleration by actual screen aspect ratio. You can draw the mosue vector with pointer. This drawed vector move the mouse. This work independent from sensitivity. + +flyfps_main_acceleration_threshold: 50.0, //range 0-100, step 0.1, default = 50, When your hand speed above flyfps_main_acceleration_threshold the mouse acceleration = flyfps_main_acceleration. When your hand speed slower then flyfps_main_acceleration_threshold the mouse acceleration ranged from 0 to flyfps_main_acceleration. When you lower this value, mouse speed accelerated faster to the flyfps_main_acceleration. You can use lower value than 1. ie: 0.1 or 0.01 when you need ;) + +flyfps_main_acceleration_finer: 85 //range 0-100, step 0.1, default 85, This value define how fast react your mouse acceleration for IRpointer acceleration. When you increase this value the mouse react slower. This is very important and individually for evry one. This value define how fast can you react for things in game. + +flyfps_left_button_fine: true // true or false. When set to true, while holding down left mouse button the mouse switch to fine aiming mode like on right mouse hold down. + +flyfps_fine_sensitivity: 0.25, //range 0-10, step 0.1, default = 0.25, Fine Sensitivity X and Y of mouse, when you hold the right or left mouse button you switch to fine aiming sensitivity mode. When set it 0 = turns off. The fine mouse flyfps_fine_sensitivity_y calculatod from flyfps_fine_sensitivity by actual screen aspect ratio. + +flyfps_fine_acceleration: 5.0, //range 0-100, step 0.1, default = 5, Fine acceleration X and Y of mouse, when you hold the right or left mouse button you switch to fine aiming sensitivity mode. When set it 0 it turns off. The fine mouse flyfps_fine_acceleration_y calculatod from flyfps_fine_acceleration. + +flyfps_fine_decceleration: 5.0, //range 0-10, step 0.1, default = 5, Fine decceleration X and Y of mouse, when you hold the right or left mouse button you switch to fine aiming sensitivity mode. When set it 0 it turns off the mouse accelerating from the current position to the desired direction. + +flyfps_mouse_smooth_buffer: 10, // range 1+ this buffer smoothing your shaking hand in (flyfps_mouse_forward, flyfps_extra_turn, flyfps_border_turn, flyfps_auto_turn), but keep in mind, this slowing down the reaction time. Set it to lowes value where your cursor not shaked. + +flyfps_mouse_forward: 0.0, //range 0-1000, step 1, default = 0 add fixed X direction jump to the mouse, when you shake your hand to the desired direction with defined acceleration. When your acceleration X reach the specified acceleretaion the mouse jump with fixed value. + +flyfps_mouse_forward_turn_on_threshold: 25.0, //range 0-100, default = 25, step 1, below this IR acceleration limit mouse forward not take effect. When your hand acceleration above this value it add fix mouse move to the desired direction. + +flyfps_mouse_forward_decceleration: 5.0, //range 0-100, default = 5, when mouse jump with fixed mouse forward its not stop instantly, slowed down with this decceleration. + +flyfps_extra_turn_sensitivity: 0.0, //range 0-100, default = 0 = off, step 0.1, set extra turn sensitivity X and Y. During travelled distance with pointer, the speed increased to this sensitivity. When flyfps_extra_turn_sensitivity_y = 0 then flyfps_extra_turn_sensitivity_y calculated from this value by actual screen aspect ratio. + +flyfps_extra_turn_deadzone: 20.0,// range 0 - 100, default = 20. In this zone the extra turn speed not take affect. When you move the opposite direction the pointer start from 0 the travelled deadzone. For proper work increase flyfps_mouse_smooth_buffer for your hand. + +flyfps_extra_turn_easein: 40.0, // range 0 - 100, default = 40. After travelling deadzone, the speed begin increasing to the extra sensitivity during this easein distance. + +flyfps_border_turn_speed_x: 0.0, // range 0+, default = 0, step 0.1, when pointer leave flyfps_horizontal_border the sensitivity is increased depending the distance of pointer from border + +flyfps_border_turn_speed_y: 0.0, // range 0+, default = 0, step 0.1, when pointer leave flyfps_vertical_border the sensitivity is increased depending the distance of pointer from border + +flyfps_auto_turn_speed_x: 0.0, // range 0+, default = 0, step 0.1, when pointer leave flyfps_horizontal_border the mouse speed X continuosly increased depending the distance of pointer from border + +flyfps_auto_turn_speed_y: 0.0, // range 0+, default = 0, step 0.1, when pointer leave flyfps_vertical_border the mouse speed Y continuosly increased depending the distance of pointer from border + +flyfps_main_sensitivity_y: 0.0, //range 0-10, step 0.01, default = 0 = auto from screen width/height aspect ratio, Sensitivity Y of mouse vector. When main_sensitivity_y=0 then main_sensitivity_y calculated from main_sensitivity. You can draw the mosue vector with pointer. This drawed vector move the mouse.This work independent from acceleration. + +flyfps_main_acceleration_y: 0.0, //range 0+, step 0.1, default = 0 = auto from screen width/height aspect ratio, multiply the mouse speed depending from the current hand speed. Acceleration Y of mouse vector. When vector_acceleration_y=0 then vector_acceleration_y calculated from vector_acceleration by actual screen aspect ratio. You can draw the mosue vector with pointer. This drawed vector move the mouse. This work independent from sensitivity. + +flyfps_fine_sensitivity_y: 0.0, //range 0-10, step: 0.1, default: 0 = auto from screen width/height aspect ratio, Fine Sensitivity Y of mouse, when you press the right or left mouse button you switch to fine aiming sensitivity mode. When set it 0 then the fine mouse flyfps_fine_sensitivity_y calculatod from flyfps_fine_sensitivity by actual screen aspect ratio. + +flyfps_fine_acceleration_y: 0.0, //range 0-100, step: 0.1, default: 0 = auto from screen width/height aspect ratio, Fine acceleration Y of mouse, when you press the right or left mouse button you switch to fine aiming sensitivity mode the pointer. When set it 0 then the fine mouse flyfps_fine_acceleration_y calculatod from flyfps_fine_acceleration. + +flyfps_mouse_forward_y: 0.0, //range 0-1000, step 1, default = 0 add fixed Y direction jump to the mouse. when you shake your hand to the desired direction with defined acceleration. When set to 0 its equal to flyfps_mouse_forward. When your acceleration Y reach the specified acceleretaion the mouse jump with fixed value. + +flyfps_extra_turn_sensitivity_y: 0.0, //range 0+, default = 0 = auto from screen width/height aspect ratio, step 0.1, set extra turn sensitivity Y. During travelled distance with pointer the speed increased to this sensitivity. When flyfps_extra_turn_sensitivity_y = 0 then flyfps_extra_turn_sensitivity_y calculated from this value. + +flyfps_debug: false, // when set to true, its create a debug.txt file where the touchmote.exe. First start touchmote and switch to flyfps mode. Then debug.txt can open with LiveGraph free software and analyze your graph. -**v1.0 beta 14**
-- FPS cursor mapping and cursor to stick mapping, thanks rVinor -- Updated OSD GUI - -**v1.0 beta 13**
-- Less GPU usage -- Works together with other Xbox 360 controls -- Bug fixes - -**v1.0 beta 12**
-- Classic Controller Pro support -- Raw input support -- Automatic check for new versions - -**v1.0 beta 11**
-- Support for multiple monitors -- More possibilities with analog sticks -- Better pairing -- Bug fixes - -**v1.0 beta 10**
-- Added visual keymap editor. -- Experimental Windows 7 support. - -**v1.0 beta 9**
-- Nunchuk and Classic Controller support. -- XBox 360 controller emulation. -- Change keymaps on the fly. Hold the Home button for 5 seconds to open the layout chooser. -- Pointer will consider Wiimote rotation. -- Better more responsive cursor. -- Enabled "Minimize to tray" option. - -**v1.0 beta 8**
-- Implemented custom cursors -- New windowed UI -- Added Sleepmode to save battery when Wiimote is not in use. -- Added option to pair a Wiimote at startup. -- Increased CPU utilization, for smoother cursor movement. - -**v1.0 beta 7**
-- Added ability to connect several Wiimotes. -- Enabled individual keymap settings for each Wiimote. -- Added GameMouse pointer mode through keymap setting. -- Moved settings file into the application folder. -- Fixed 64 bit installer default install folder. -- Fixed support for MultiTouchVista drivers (for Windows 7 or lower) - -**v1.0 beta 6**
-- Added support for new Wiimotes (RVL-CNT-01-TR) -- Added option to specify Sensor Bar position -- Bugfix, using two touch points would sometimes disable edge gestures - -**v1.0 beta 5**
-- Multi touch! Use the B button to add a second touch point and zoom or rotate with the A button. -- Added application specific keymaps. Edit or add new keymaps in the Keymaps folder. -- Now using native Windows 8 touch cursor. -- Added helpers to perform edge guestures and taps. - -**v1.0 beta 4**
-- Much better performance and stability on Windows 8 -- Driver is now optional -- Only works on Windows 8, use beta3 for Windows 7/Vista -- Completely disconnects the Wiimote so it doesn't drain battery when not used - -**v1.0 beta 3**
-- Forgot to enable driver detection -- Added error messaging - -**v1.0 beta 2**
-- Press minus or plus to zoom in or out -- Press 2 to reset connection to touch driver -- No crash on restart -- Pointer settings saves correctly -- Improved pairing -- Bug fixes - -**v1.0 beta 1**
-- First release. +DEBUG description: +IRDeltaX = input pointer relative delta, the main buffer is used here; +mouseMainSpeedX = mouse main vector output; +mouseMainStoreX = mouse main vector output, sum of IRDelta with decceleration / frame; +mouseOutX = Sum of all mouse moves. You can analyze. flyfps_mouse_finer take effect on all mouse moves (flyfps_main, flyfps_fine, flyfps_mouse_forward, flyfps_extra_turn, flyfps_border_turn, flyfps_auto_turn) diff --git a/TouchMotex64Release.zip b/TouchMotex64Release.zip new file mode 100644 index 00000000..8b6a434f Binary files /dev/null and b/TouchMotex64Release.zip differ diff --git a/Touchmote.sln b/Touchmote.sln index 63038eb5..50cda92e 100644 --- a/Touchmote.sln +++ b/Touchmote.sln @@ -1,90 +1,84 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.21005.1 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WiiTUIO", "WiiTUIO\WiiTUIO.csproj", "{87CC8302-A614-490E-9100-1059AF5FE8FC}" - ProjectSection(ProjectDependencies) = postProject - {14BD1D44-261D-4FC2-A7DD-A3CDA413D790} = {14BD1D44-261D-4FC2-A7DD-A3CDA413D790} - {9E8F1D50-74EA-4C60-BD5C-AB2C5B53BC66} = {9E8F1D50-74EA-4C60-BD5C-AB2C5B53BC66} - {4796387A-2F8E-4ED0-96E4-A72137B4428C} = {4796387A-2F8E-4ED0-96E4-A72137B4428C} - {78EB9DE8-B6FC-47F3-970F-0B4FCB0F38A8} = {78EB9DE8-B6FC-47F3-970F-0B4FCB0F38A8} - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OSC.NET", "OSC.NET\OSC.NET.csproj", "{14BD1D44-261D-4FC2-A7DD-A3CDA413D790}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WiiCPP", "WiiCPP\WiiCPP.vcxproj", "{78EB9DE8-B6FC-47F3-970F-0B4FCB0F38A8}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HidLibrary", "HidLibrary\HidLibrary.csproj", "{9E8F1D50-74EA-4C60-BD5C-AB2C5B53BC66}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DriverInstall", "DriverInstall\DriverInstall.csproj", "{914C6098-F4B6-4AFA-AFD0-5B90411C9271}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ResetTouchInjection", "ResetTouchInjection\ResetTouchInjection.csproj", "{D1E85F1A-3BE3-46C1-B086-EF1335457EF5}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "D3DCursor", "D3DCursor\D3DCursor.vcxproj", "{4796387A-2F8E-4ED0-96E4-A72137B4428C}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {87CC8302-A614-490E-9100-1059AF5FE8FC}.Debug|x64.ActiveCfg = Debug|x64 - {87CC8302-A614-490E-9100-1059AF5FE8FC}.Debug|x64.Build.0 = Debug|x64 - {87CC8302-A614-490E-9100-1059AF5FE8FC}.Debug|x86.ActiveCfg = Debug|x86 - {87CC8302-A614-490E-9100-1059AF5FE8FC}.Debug|x86.Build.0 = Debug|x86 - {87CC8302-A614-490E-9100-1059AF5FE8FC}.Release|x64.ActiveCfg = Release|x64 - {87CC8302-A614-490E-9100-1059AF5FE8FC}.Release|x64.Build.0 = Release|x64 - {87CC8302-A614-490E-9100-1059AF5FE8FC}.Release|x86.ActiveCfg = Release|x86 - {87CC8302-A614-490E-9100-1059AF5FE8FC}.Release|x86.Build.0 = Release|x86 - {14BD1D44-261D-4FC2-A7DD-A3CDA413D790}.Debug|x64.ActiveCfg = Debug|x64 - {14BD1D44-261D-4FC2-A7DD-A3CDA413D790}.Debug|x64.Build.0 = Debug|x64 - {14BD1D44-261D-4FC2-A7DD-A3CDA413D790}.Debug|x86.ActiveCfg = Debug|x86 - {14BD1D44-261D-4FC2-A7DD-A3CDA413D790}.Debug|x86.Build.0 = Debug|x86 - {14BD1D44-261D-4FC2-A7DD-A3CDA413D790}.Release|x64.ActiveCfg = Release|x64 - {14BD1D44-261D-4FC2-A7DD-A3CDA413D790}.Release|x64.Build.0 = Release|x64 - {14BD1D44-261D-4FC2-A7DD-A3CDA413D790}.Release|x86.ActiveCfg = Release|x86 - {14BD1D44-261D-4FC2-A7DD-A3CDA413D790}.Release|x86.Build.0 = Release|x86 - {78EB9DE8-B6FC-47F3-970F-0B4FCB0F38A8}.Debug|x64.ActiveCfg = Debug|x64 - {78EB9DE8-B6FC-47F3-970F-0B4FCB0F38A8}.Debug|x64.Build.0 = Debug|x64 - {78EB9DE8-B6FC-47F3-970F-0B4FCB0F38A8}.Debug|x86.ActiveCfg = Debug|Win32 - {78EB9DE8-B6FC-47F3-970F-0B4FCB0F38A8}.Debug|x86.Build.0 = Debug|Win32 - {78EB9DE8-B6FC-47F3-970F-0B4FCB0F38A8}.Release|x64.ActiveCfg = Release|x64 - {78EB9DE8-B6FC-47F3-970F-0B4FCB0F38A8}.Release|x64.Build.0 = Release|x64 - {78EB9DE8-B6FC-47F3-970F-0B4FCB0F38A8}.Release|x86.ActiveCfg = Release|Win32 - {78EB9DE8-B6FC-47F3-970F-0B4FCB0F38A8}.Release|x86.Build.0 = Release|Win32 - {9E8F1D50-74EA-4C60-BD5C-AB2C5B53BC66}.Debug|x64.ActiveCfg = Debug|x64 - {9E8F1D50-74EA-4C60-BD5C-AB2C5B53BC66}.Debug|x64.Build.0 = Debug|x64 - {9E8F1D50-74EA-4C60-BD5C-AB2C5B53BC66}.Debug|x86.ActiveCfg = Debug|x86 - {9E8F1D50-74EA-4C60-BD5C-AB2C5B53BC66}.Debug|x86.Build.0 = Debug|x86 - {9E8F1D50-74EA-4C60-BD5C-AB2C5B53BC66}.Release|x64.ActiveCfg = Release|x64 - {9E8F1D50-74EA-4C60-BD5C-AB2C5B53BC66}.Release|x64.Build.0 = Release|x64 - {9E8F1D50-74EA-4C60-BD5C-AB2C5B53BC66}.Release|x86.ActiveCfg = Release|x86 - {9E8F1D50-74EA-4C60-BD5C-AB2C5B53BC66}.Release|x86.Build.0 = Release|x86 - {914C6098-F4B6-4AFA-AFD0-5B90411C9271}.Debug|x64.ActiveCfg = Debug|x64 - {914C6098-F4B6-4AFA-AFD0-5B90411C9271}.Debug|x86.ActiveCfg = Debug|x86 - {914C6098-F4B6-4AFA-AFD0-5B90411C9271}.Release|x64.ActiveCfg = Release|x64 - {914C6098-F4B6-4AFA-AFD0-5B90411C9271}.Release|x64.Build.0 = Release|x64 - {914C6098-F4B6-4AFA-AFD0-5B90411C9271}.Release|x86.ActiveCfg = Release|x86 - {914C6098-F4B6-4AFA-AFD0-5B90411C9271}.Release|x86.Build.0 = Release|x86 - {D1E85F1A-3BE3-46C1-B086-EF1335457EF5}.Debug|x64.ActiveCfg = Debug|x64 - {D1E85F1A-3BE3-46C1-B086-EF1335457EF5}.Debug|x86.ActiveCfg = Debug|x86 - {D1E85F1A-3BE3-46C1-B086-EF1335457EF5}.Release|x64.ActiveCfg = Release|x64 - {D1E85F1A-3BE3-46C1-B086-EF1335457EF5}.Release|x64.Build.0 = Release|x64 - {D1E85F1A-3BE3-46C1-B086-EF1335457EF5}.Release|x86.ActiveCfg = Release|x86 - {D1E85F1A-3BE3-46C1-B086-EF1335457EF5}.Release|x86.Build.0 = Release|x86 - {4796387A-2F8E-4ED0-96E4-A72137B4428C}.Debug|x64.ActiveCfg = Debug|x64 - {4796387A-2F8E-4ED0-96E4-A72137B4428C}.Debug|x64.Build.0 = Debug|x64 - {4796387A-2F8E-4ED0-96E4-A72137B4428C}.Debug|x86.ActiveCfg = Debug|Win32 - {4796387A-2F8E-4ED0-96E4-A72137B4428C}.Debug|x86.Build.0 = Debug|Win32 - {4796387A-2F8E-4ED0-96E4-A72137B4428C}.Release|x64.ActiveCfg = Release|x64 - {4796387A-2F8E-4ED0-96E4-A72137B4428C}.Release|x64.Build.0 = Release|x64 - {4796387A-2F8E-4ED0-96E4-A72137B4428C}.Release|x86.ActiveCfg = Release|Win32 - {4796387A-2F8E-4ED0-96E4-A72137B4428C}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.40629.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WiiTUIO", "WiiTUIO\WiiTUIO.csproj", "{87CC8302-A614-490E-9100-1059AF5FE8FC}" + ProjectSection(ProjectDependencies) = postProject + {14BD1D44-261D-4FC2-A7DD-A3CDA413D790} = {14BD1D44-261D-4FC2-A7DD-A3CDA413D790} + {9E8F1D50-74EA-4C60-BD5C-AB2C5B53BC66} = {9E8F1D50-74EA-4C60-BD5C-AB2C5B53BC66} + {4796387A-2F8E-4ED0-96E4-A72137B4428C} = {4796387A-2F8E-4ED0-96E4-A72137B4428C} + {78EB9DE8-B6FC-47F3-970F-0B4FCB0F38A8} = {78EB9DE8-B6FC-47F3-970F-0B4FCB0F38A8} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OSC.NET", "OSC.NET\OSC.NET.csproj", "{14BD1D44-261D-4FC2-A7DD-A3CDA413D790}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WiiCPP", "WiiCPP\WiiCPP.vcxproj", "{78EB9DE8-B6FC-47F3-970F-0B4FCB0F38A8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HidLibrary", "HidLibrary\HidLibrary.csproj", "{9E8F1D50-74EA-4C60-BD5C-AB2C5B53BC66}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DriverInstall", "DriverInstall\DriverInstall.csproj", "{914C6098-F4B6-4AFA-AFD0-5B90411C9271}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ResetTouchInjection", "ResetTouchInjection\ResetTouchInjection.csproj", "{D1E85F1A-3BE3-46C1-B086-EF1335457EF5}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "D3DCursor", "D3DCursor\D3DCursor.vcxproj", "{4796387A-2F8E-4ED0-96E4-A72137B4428C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {87CC8302-A614-490E-9100-1059AF5FE8FC}.Debug|x64.ActiveCfg = Debug|x64 + {87CC8302-A614-490E-9100-1059AF5FE8FC}.Debug|x64.Build.0 = Debug|x64 + {87CC8302-A614-490E-9100-1059AF5FE8FC}.Debug|x86.ActiveCfg = Debug|x86 + {87CC8302-A614-490E-9100-1059AF5FE8FC}.Debug|x86.Build.0 = Debug|x86 + {87CC8302-A614-490E-9100-1059AF5FE8FC}.Release|x64.ActiveCfg = Release|x64 + {87CC8302-A614-490E-9100-1059AF5FE8FC}.Release|x64.Build.0 = Release|x64 + {87CC8302-A614-490E-9100-1059AF5FE8FC}.Release|x86.ActiveCfg = Release|x86 + {87CC8302-A614-490E-9100-1059AF5FE8FC}.Release|x86.Build.0 = Release|x86 + {14BD1D44-261D-4FC2-A7DD-A3CDA413D790}.Debug|x64.ActiveCfg = Debug|x64 + {14BD1D44-261D-4FC2-A7DD-A3CDA413D790}.Debug|x64.Build.0 = Debug|x64 + {14BD1D44-261D-4FC2-A7DD-A3CDA413D790}.Debug|x86.ActiveCfg = Debug|x86 + {14BD1D44-261D-4FC2-A7DD-A3CDA413D790}.Debug|x86.Build.0 = Debug|x86 + {14BD1D44-261D-4FC2-A7DD-A3CDA413D790}.Release|x64.ActiveCfg = Release|x64 + {14BD1D44-261D-4FC2-A7DD-A3CDA413D790}.Release|x86.ActiveCfg = Release|x86 + {14BD1D44-261D-4FC2-A7DD-A3CDA413D790}.Release|x86.Build.0 = Release|x86 + {78EB9DE8-B6FC-47F3-970F-0B4FCB0F38A8}.Debug|x64.ActiveCfg = Debug|x64 + {78EB9DE8-B6FC-47F3-970F-0B4FCB0F38A8}.Debug|x64.Build.0 = Debug|x64 + {78EB9DE8-B6FC-47F3-970F-0B4FCB0F38A8}.Debug|x86.ActiveCfg = Debug|Win32 + {78EB9DE8-B6FC-47F3-970F-0B4FCB0F38A8}.Debug|x86.Build.0 = Debug|Win32 + {78EB9DE8-B6FC-47F3-970F-0B4FCB0F38A8}.Release|x64.ActiveCfg = Release|x64 + {78EB9DE8-B6FC-47F3-970F-0B4FCB0F38A8}.Release|x86.ActiveCfg = Release|Win32 + {78EB9DE8-B6FC-47F3-970F-0B4FCB0F38A8}.Release|x86.Build.0 = Release|Win32 + {9E8F1D50-74EA-4C60-BD5C-AB2C5B53BC66}.Debug|x64.ActiveCfg = Debug|x64 + {9E8F1D50-74EA-4C60-BD5C-AB2C5B53BC66}.Debug|x64.Build.0 = Debug|x64 + {9E8F1D50-74EA-4C60-BD5C-AB2C5B53BC66}.Debug|x86.ActiveCfg = Debug|x86 + {9E8F1D50-74EA-4C60-BD5C-AB2C5B53BC66}.Debug|x86.Build.0 = Debug|x86 + {9E8F1D50-74EA-4C60-BD5C-AB2C5B53BC66}.Release|x64.ActiveCfg = Release|x64 + {9E8F1D50-74EA-4C60-BD5C-AB2C5B53BC66}.Release|x86.ActiveCfg = Release|x86 + {9E8F1D50-74EA-4C60-BD5C-AB2C5B53BC66}.Release|x86.Build.0 = Release|x86 + {914C6098-F4B6-4AFA-AFD0-5B90411C9271}.Debug|x64.ActiveCfg = Debug|x64 + {914C6098-F4B6-4AFA-AFD0-5B90411C9271}.Debug|x86.ActiveCfg = Debug|x86 + {914C6098-F4B6-4AFA-AFD0-5B90411C9271}.Release|x64.ActiveCfg = Release|x64 + {914C6098-F4B6-4AFA-AFD0-5B90411C9271}.Release|x86.ActiveCfg = Release|x86 + {914C6098-F4B6-4AFA-AFD0-5B90411C9271}.Release|x86.Build.0 = Release|x86 + {D1E85F1A-3BE3-46C1-B086-EF1335457EF5}.Debug|x64.ActiveCfg = Debug|x64 + {D1E85F1A-3BE3-46C1-B086-EF1335457EF5}.Debug|x86.ActiveCfg = Debug|x86 + {D1E85F1A-3BE3-46C1-B086-EF1335457EF5}.Release|x64.ActiveCfg = Release|x64 + {D1E85F1A-3BE3-46C1-B086-EF1335457EF5}.Release|x86.ActiveCfg = Release|x86 + {D1E85F1A-3BE3-46C1-B086-EF1335457EF5}.Release|x86.Build.0 = Release|x86 + {4796387A-2F8E-4ED0-96E4-A72137B4428C}.Debug|x64.ActiveCfg = Debug|x64 + {4796387A-2F8E-4ED0-96E4-A72137B4428C}.Debug|x64.Build.0 = Debug|x64 + {4796387A-2F8E-4ED0-96E4-A72137B4428C}.Debug|x86.ActiveCfg = Debug|Win32 + {4796387A-2F8E-4ED0-96E4-A72137B4428C}.Debug|x86.Build.0 = Debug|Win32 + {4796387A-2F8E-4ED0-96E4-A72137B4428C}.Release|x64.ActiveCfg = Release|x64 + {4796387A-2F8E-4ED0-96E4-A72137B4428C}.Release|x86.ActiveCfg = Release|Win32 + {4796387A-2F8E-4ED0-96E4-A72137B4428C}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/WiiCPP/WiiCPP.vcxproj b/WiiCPP/WiiCPP.vcxproj index 8af7fcbb..05864a05 100644 --- a/WiiCPP/WiiCPP.vcxproj +++ b/WiiCPP/WiiCPP.vcxproj @@ -1,166 +1,166 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {78EB9DE8-B6FC-47F3-970F-0B4FCB0F38A8} - v4.5 - ManagedCProj - WiiCPP - - - - DynamicLibrary - true - v120 - true - Unicode - - - DynamicLibrary - true - v120 - true - Unicode - - - DynamicLibrary - false - v120 - true - Unicode - - - DynamicLibrary - false - v120 - true - Unicode - - - - - - - - - - - - - - - - - - - true - $(ProjectDir)bin\$(Platform)\$(Configuration)\ - - - true - $(ProjectDir)bin\$(Platform)\$(Configuration)\ - - - false - $(ProjectDir)bin\$(Platform)\$(Configuration)\ - - - false - $(ProjectDir)bin\$(Platform)\$(Configuration)\ - - - - Level3 - Disabled - WIN32;_DEBUG;%(PreprocessorDefinitions) - Use - - - true - - - - - Level3 - Disabled - WIN32;_DEBUG;%(PreprocessorDefinitions) - Use - - - true - - - - - Level3 - WIN32;NDEBUG;%(PreprocessorDefinitions) - Use - - - false - - - - - Level3 - WIN32;NDEBUG;%(PreprocessorDefinitions) - Use - - - false - - - - - - true - true - true - - - - - - - - - - - - Create - Create - Create - Create - - - - - - - - - - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {78EB9DE8-B6FC-47F3-970F-0B4FCB0F38A8} + v4.5.2 + ManagedCProj + WiiCPP + + + + DynamicLibrary + true + v140 + true + Unicode + + + DynamicLibrary + true + v140 + true + Unicode + + + DynamicLibrary + false + v140 + true + Unicode + + + DynamicLibrary + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(ProjectDir)bin\$(Platform)\$(Configuration)\ + + + true + $(ProjectDir)bin\$(Platform)\$(Configuration)\ + + + false + $(ProjectDir)bin\$(Platform)\$(Configuration)\ + + + false + $(ProjectDir)bin\$(Platform)\$(Configuration)\ + + + + Level3 + Disabled + WIN32;_DEBUG;%(PreprocessorDefinitions) + Use + + + true + + + + + Level3 + Disabled + WIN32;_DEBUG;%(PreprocessorDefinitions) + Use + + + true + + + + + Level3 + WIN32;NDEBUG;%(PreprocessorDefinitions) + Use + + + false + + + + + Level3 + WIN32;NDEBUG;%(PreprocessorDefinitions) + Use + + + false + + + + + + true + true + true + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/WiiTUIO/Input/WiiProvider/SpatiotemporalClassifier.cs b/WiiTUIO/Input/WiiProvider/SpatiotemporalClassifier.cs index 9a01f3bd..6a181f52 100644 --- a/WiiTUIO/Input/WiiProvider/SpatiotemporalClassifier.cs +++ b/WiiTUIO/Input/WiiProvider/SpatiotemporalClassifier.cs @@ -1,815 +1,830 @@ - -using Microsoft.Win32; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Windows; -using WiiTUIO.Properties; - -namespace WiiTUIO.Provider -{ - /// - /// A SpatiotemporalClassifier is a class which is able to classify a frame of points based on the set of previous points - /// avaiable to it. This is designed to solve the problem of the lack of buffer-ordering from data returned by the Wiimote. - /// As such this has no concept of order; rather order is determined based on the likelyhood of it a point being related to another - /// if it was in a similar place. - /// Whilst there is no perfect solution beyond implementing buffer tracking within the actual Wiimote hardware - this class - /// uses some spatial and temporal statistics to compute a likely solution using simple calculations. As such, while its output - /// may be 'good enough' it is far from perfect. - /// - public class SpatioTemporalClassifier - { - #region Helper Pair Class - /// - /// A ProcessPair is a simple helper class which is used to enumerate and compare trackers and inputs. - /// - private class ProcessPair : IComparable - { - /// - /// The input in this pair. - /// - public SpatioTemporalInput pInput; - /// - /// The tracker in this pair. - /// - public SpatioTemporalTracker pTracker; - /// - /// The ranking between the tracker and the pair. - /// - public double fRanking; - - /// - /// Construct a new process pair. This will invoke 'getClassificationRanking' on the tracker. - /// - /// The tracker to pair. - /// The input to pair. - public ProcessPair(SpatioTemporalTracker pTracker, SpatioTemporalInput pInput) - { - this.pInput = pInput; - this.pTracker = pTracker; - this.fRanking = pTracker.getClassificationRanking(this.pInput); - } - - #region IComparable Members - /// - /// Compare this process pair to another by looking at the ranking. - /// - /// The other process pair to compare two. - /// A 32-Bit Signed Integer that states the relative sortorder of the two objects - public int CompareTo(ProcessPair pOther) - { - return this.fRanking.CompareTo(pOther.fRanking); - } - #endregion - } - #endregion - - #region Classifier Properties - /// - /// A list of active trackers. - /// - private List lTrackers; - - /// - /// The default smoothing value for any trackers created. - /// - public int DefaultSmoothSize { get; set; } - - /// - /// The distance at which we are confident two trackers are duplicating/following the same input. - /// - public double DuplicateDistance { get; set; } - - /// - /// A delegate which describes the function signature of the events this class raises. - /// - /// The classifer which raised the event. - /// The tracker of interest. - public delegate void TrackerEventHandler(SpatioTemporalClassifier pSource, SpatioTemporalTracker pTracker); - - /// - /// A counter for session varaibles. - /// - private ulong iNextID = 0; - - /// - /// An event which is raised when a new tracker is created. - /// - public event TrackerEventHandler OnStart; - - /// - /// An event which is raised when an existing tracker is removed. - /// - public event TrackerEventHandler OnEnd; - - /// - /// An event which is raised when an existing tracker is updated. - /// - public event TrackerEventHandler OnUpdate; - #endregion - - /// - /// Construct a new SpatioTemporalClassifier. - /// - public SpatioTemporalClassifier() - { - // Create the table. - this.lTrackers = new List(4); - - // Defaults. - this.DefaultSmoothSize = 3; - this.DuplicateDistance = 10; - } - - /// - /// Reset the tracker list so there is no context preserved after this call. - /// This also resets the session counter to 0. - /// - public void reset() - { - this.lTrackers.Clear(); - this.iNextID = 0; - } - - /// - /// This is called to process a 'frame' of inputs which will be ranked against eachother before being dispatched - /// to the appropriate existing inputs, removing old ones or generating new ones. - /// - /// The array of inputs which we want to process as a frame. - public void processFrame(List lInputs) - { - // Check we have data. - if (lInputs.Count + lTrackers.Count == 0) - return; - - #region Ugly (but fairly quick) duplicate tracker removal. - // Loop over an exclusive half-diagonal of a number square! :-) Ahh the memories! - bool bPossible = true; - bool bFound = false; - while (bPossible) - { - // Check for a collision! - for (int i = 0; i < lTrackers.Count; ++i) - { - // Flag that we have not found a collision on this loop round. - bFound = false; - for (int j = i + 1; j < lTrackers.Count; ++j) - { - // Test the trackers are in very close range of eachother (i.e. overlapping and stealing inputs!). - if ((lTrackers[i].Position - lTrackers[j].Position).Length < this.DuplicateDistance) - { - // They are too close - set one to be dead! - SpatioTemporalTracker pRemove = lTrackers[i]; - - // Remove it. - this.lTrackers.Remove(pRemove); - pRemove.eTrackerState = TrackerState.Destroy; - bFound = true; - - // Raise the event. - if (pRemove.StrongLock) - { - if (this.OnEnd != null) - this.OnEnd(this, pRemove); - } - } - } - - // If we found a collision we have removed it from the list and this need to check again. - if (bFound) - break; - } - - // So we got this far and had no collisions. - bPossible = bFound; - } - #endregion - - #region Process and Sort the table of all possible trackers. - // Build the big table of trackers-inputs-distances. - List lTable = new List(lInputs.Count * lTrackers.Count); - foreach (SpatioTemporalTracker pTracker in lTrackers) - { - foreach (SpatioTemporalInput pInput in lInputs) - { - // Only add it to to the table if it will not be rejected out of hand. - ProcessPair pPair = new ProcessPair(pTracker, pInput); - //if (pPair.fRanking < pTracker.PredictionScale) - lTable.Add(pPair); - } - } - - // Sort the above table based on the distance rankings. - lTable.Sort(); - #endregion - - #region Strip duplicate pairs from the tracker ranking table based on 'best' selections. - // Remove duplicate tracker entries from the table whilst saving the best pairs in their own table. - List lBest = new List(); - foreach (ProcessPair pPair in lTable) - { - // Does the table of best matches already contain this tracker? - bool bContains = false; - for (int i = 0; i < lBest.Count; ++i) - { - if (lBest[i].pTracker == pPair.pTracker) - { - bContains = true; - break; - } - } - - // If it doesn't then add it. - if (!bContains) - lBest.Add(pPair); - } - #endregion - - #region Build a list of remove candidates. - // Create an array which contains old trackers to be removed. - List lRemove = new List(); - foreach (SpatioTemporalTracker pTracker in lTrackers) - { - // Does the table of best matches already contain this input? - bool bContains = false; - for (int i = 0; i < lBest.Count; ++i) - { - if (lBest[i].pTracker == pTracker) - { - bContains = true; - break; - } - } - - // If it doesn't then add it. - if (!bContains) - lRemove.Add(pTracker); - } - #endregion - - #region Build a list of create candidates. - // Create an array which contains new trackers to be created. - List lCreate = new List(); - foreach (SpatioTemporalInput pInput in lInputs) - { - // Does the table of best matches already contain this input? - bool bContains = false; - for (int i = 0; i < lBest.Count; ++i) - { - if (lBest[i].pInput == pInput) - { - bContains = true; - break; - } - } - - // If it doesn't then add it. - if (!bContains) - lCreate.Add(pInput); - } - #endregion - - // So now we need to dispatch some more processing. - - // Update the best matches. - this.dispatchUpdates(lBest); - - // Remove the old. - this.removeOld(lRemove); - - // Create the new. - this.createNew(lCreate); - } - - /// - /// Dispatch updates to trackers which have just consumed a new input. - /// - /// The list of pairs to dispatch. - private void dispatchUpdates(List lPairs) - { - // Have the tracker in each pair consume its own input.. How perverse does that sound? :-p - foreach (ProcessPair pPair in lPairs) - { - // Consume it. - pPair.pTracker.consumeInput(pPair.pInput); - - // Ensure we have a strong lock before firing the event. - if (pPair.pTracker.StrongLock) - { - // If the tracker state has moved from discovered then good times. - if (pPair.pTracker.eTrackerState == TrackerState.Discover) - { - // Update the state to match a forwarder and raise the 'OnStart' event. - pPair.pTracker.eTrackerState = TrackerState.Forward; - if (this.OnStart != null) - this.OnStart(this, pPair.pTracker); - } - else - { - // Raise the event. - if (this.OnUpdate != null) - this.OnUpdate(this, pPair.pTracker); - } - } - } - } - - /// - /// Dispatch updates to trackers which have recieved no inputs. - /// - /// The list trackers to remove. - private void removeOld(List lTrackers) - { - // Remove the old trackers from the list and raise an event for each one saying its happened. - foreach (SpatioTemporalTracker pRemove in lTrackers) - { - // Consume nothing (used so we know how many events before it died). - pRemove.consumeNothing(); - - // If we have strong feeling we lost the lock - kill it. - if (pRemove.StrongLostLock) - { - // Remove it. - this.lTrackers.Remove(pRemove); - pRemove.eTrackerState = TrackerState.Destroy; - - // Raise the event. - if (pRemove.StrongLock) - { - if (this.OnEnd != null) - this.OnEnd(this, pRemove); - } - } - } - } - - /// - /// Dispatch updates to trackers which have just been created. - /// - /// The list trackers to create. - private void createNew(List lInputs) - { - // Create new trackers for each input. - foreach (SpatioTemporalInput pInput in lInputs) - { - // Create new, insert input and then append. - SpatioTemporalTracker pTracker = new SpatioTemporalTracker(this.DefaultSmoothSize, ++this.iNextID); - pTracker.consumeInput(pInput); - pTracker.eTrackerState = TrackerState.Discover; - lTrackers.Add(pTracker); - - // Raise the event. - //if (this.OnStart != null) - // this.OnStart(this, pTracker); - } - } - - } - - /// - /// An internally enumerated tracker state that is only known to the Classifier and Tracker. - /// - internal enum TrackerState - { - /// - /// The tracker has just been discovered and should be raised as a start event once the next move event is recieved. - /// - Discover = 0, - /// - /// The tracker has just been lost and should be raised as a lost event if no more move events are recieved. - /// - Destroy = 1, - /// - /// The tracker has moved from discovered to forward so all subsequent events should be forwarded. - /// - Forward = 2, - } - - /// - /// A SpatioTemporalTracker is a class which represents a context for an existing input. It is used to determine if a new input bears any relevance to it or is - /// simply a new point. - /// - public class SpatioTemporalTracker - { - #region Static Defaults - /// - /// The number of inputs the tracker should recieve before we are confident it is definately active. - /// - public static uint StrongLockThreshold = 0; - - /// - /// The number of non-inputs the tracker should recieve before we are confident it is definately dead. - /// - public static uint StrongLockLostThreshold = 0; - #endregion - - #region Properties - /// - /// A reference to the smoothing buffer which is responsible for, well, smoothing the input positions. - /// - public SmoothingBuffer SmoothingBuffer { get; protected set; } - - /// - /// Return the smoothed position of the input this tracker is tracking. - /// - public Vector Position { get; protected set; } - - /// - /// Return the smoothed normalised position of the input this tracker is tracking. - /// - public Vector NormalPosition { get; protected set; } - - /// - /// Return the non-normalised forward vector of this tracker which is essentially the lastpos - currentpos. - /// - public Vector Forward { get; protected set; } - - /// - /// Return the normalised forward vector of this tracker which is essentially the lastpos - currentpos scaled by its length. - /// - public Vector NormalForward { get; protected set; } - - /// - /// Return the unique tracker number as returned from this classifier. - /// - public ulong ID { get; protected set; } - - /// - /// This will return True if we are sure that this tracker is actively recieving input. - /// - public bool StrongLock { get { return iTrackerLock > StrongLockThreshold; } } - - /// - /// This will return True if we are sure this tracker has not recieved any recent input. - /// - public bool StrongLostLock { get { return iTrackerLostLock > StrongLockLostThreshold; } } - - /// - /// The starting position of this tracker object. - /// - public Vector StartPosition { get; protected set; } - #endregion - - #region Prediction - /// - /// Return the scale factor for the prediction megnitude. - /// - public double PredictionScale { get; set; } - - /// - /// Return the next predicted position of this tracker. - /// - public Vector PredictedNextPosition { get { return new Vector(Position.X + (NormalForward.X * PredictionScale), Position.Y + (NormalForward.Y * PredictionScale)); } } - - /// - /// Return the next predicted position of this tracker but in the opposite direction. - /// - public Vector PredictedLastPosition { get { return new Vector(Position.X - (NormalForward.X * PredictionScale), Position.Y - (NormalForward.Y * PredictionScale)); } } - #endregion - - #region Helpers - /// - /// The classifier-internal state of this tracker (i.e. do we need to treat it spectially because it is existing in an undetermined state?) - /// - internal TrackerState eTrackerState { get; set; } - - /// - /// The counter for the number of inputs recieved. - /// - internal int iTrackerLock = 0; - - /// - /// The counter for the number of non-inputs recieved. - /// - internal int iTrackerLostLock = 0; - #endregion - - System.Windows.Forms.Screen primaryScreen; - - /// - /// Construct a new tracker with a default smoothing value. - /// - /// The smoothing value. - /// The unique session ID for this tracker. - public SpatioTemporalTracker(int iSmoothSize, ulong iID)//, double fMinRadius, double fMaxRadius, double fRadiusExpansion) - { - // Build a smoothing buffer. - this.SmoothingBuffer = new SmoothingBuffer(iSmoothSize); - - // Save the ID. - this.ID = iID; - - this.primaryScreen = DeviceUtils.DeviceUtil.GetScreen(Settings.Default.primaryMonitor); - - Settings.Default.PropertyChanged += SettingsChanged; - SystemEvents.DisplaySettingsChanged += SystemEvents_DisplaySettingsChanged; - - // Save the state. - this.eTrackerState = TrackerState.Discover; - this.PredictionScale = Math.Max(primaryScreen.Bounds.Width, primaryScreen.Bounds.Height); - } - - - private void SettingsChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) - { - if (e.PropertyName == "primaryMonitor") - { - primaryScreen = DeviceUtils.DeviceUtil.GetScreen(Settings.Default.primaryMonitor); - this.PredictionScale = Math.Max(primaryScreen.Bounds.Width, primaryScreen.Bounds.Height); - } - } - private void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e) - { - primaryScreen = DeviceUtils.DeviceUtil.GetScreen(Settings.Default.primaryMonitor); - this.PredictionScale = Math.Max(primaryScreen.Bounds.Width, primaryScreen.Bounds.Height); - } - - /// - /// Take an input which is gaurenteed to be part of this tracker. Update the tracker based on the input. - /// - /// The input we wish to consume. - public void consumeInput(SpatioTemporalInput pInput) - { - // Add the point to the smoothing buffer. - this.SmoothingBuffer.addValue(pInput.Point); - - // Compute the position as the newly smoothed value. - Vector tLastPosition = this.Position; - this.Position = this.SmoothingBuffer.getSmoothedValue(); - - // Compute the forward as the difference between the two. - Forward = new Vector(tLastPosition.X - this.Position.X, tLastPosition.Y - this.Position.Y); - - // Compute the radius as the length of the next predicted. - //double fLength = Forward.Length * 10; - //fLength = 100;// Math.Max(50, Math.Min(fLength, 500)); - //if (fLength == 0) - // fLength = 100.0f; - - // Compute the normalised forward vector. - NormalForward = Forward; - NormalForward.Normalize(); - - // Now, if I were handling an adaptive radius, I would update it here to encompass the new predicted position. - //PredictionScale = fLength; - - // If our tracker lock is 0 then it is sorta-safe to say we are the starting position. - if (iTrackerLock == 0) - StartPosition = Position; - - // Increment the tracker lock and reset the lost lock to 0. - ++iTrackerLock; - iTrackerLostLock = 0; - } - - /// - /// This is called to notify this tracker that we recieved a situation which made it seem like it was lost. - /// Internally this increments a counter which affects a 'lost lock', which, when it reaches a threshold becomes sure that we have no more data for it. - /// - public void consumeNothing() - { - ++iTrackerLostLock; - } - - /// - /// This function determines a double value which ranks the likelyhood a point is part of this tracker. - /// Smaller numbers are more likely than larger ones. Distributions need all the data in order to be normalised with respect to another. - /// - /// - /// A double word value which ranks the likelyhood of this input being part of this tracker. Smaller is better. - public double getClassificationRanking(SpatioTemporalInput pInput) - { - // TODO: TIME IS NOT TAKEN INTO ACCOUNT OF IN THESE EQUATIONS.... - - // Compute the distance of the input point to the best and predicted. - Vector vInput = pInput.Point; - double fDistanceFromBest = (Position - vInput).Length; - double fDistanceFromPredicted = (PredictedNextPosition - vInput).Length; - - // Select the smallest of the two lengths (an optimistic algorythm). - return Math.Min(fDistanceFromBest, fDistanceFromPredicted); - } - - /// - /// Returns the distance of vPoint to the segment defined by vLineA,vLineB; - /// - /// First point of the segment. - /// Second point of the segment. - /// The point to which we want to know the distance of the segment. - /// The distance of vPoint to the segment defined by vLineA, vLineB. - public static double distanceToSegment(Vector vLineA, Vector vLineB, Vector vPoint) - { - // Compute the delta. - Vector vDelta = vLineB - vLineA; - - // Ensure the arguments are ok. - if ((vDelta.X == 0) && (vDelta.Y == 0)) - { - throw new Exception("vLineA and vLineB cannot be the same point"); - } - - // Solve for u: [P3 - P1 - u(P2 - P1)] dot (P2 - P1) = 0 - double u = ((vPoint.X - vLineA.X) * vDelta.X + (vPoint.Y - vLineA.Y) * vDelta.Y) / (vDelta.X * vDelta.X + vDelta.Y * vDelta.Y); - - // Compute the closest point on the line segment. - Vector vClosest; - if (u < 0) - { - vClosest = vLineA; - } - else if (u > 1) - { - vClosest = vLineB; - } - else - { - vClosest = new Vector(vLineA.X + u * vDelta.X, vLineA.Y + u * vDelta.Y); - } - - // Return the distance between the closest point on the line and the actual point. - return (vClosest - vPoint).Length; //vClosest.distance(vPoint); - } - } - - /// - /// A SpatioTemporalInput describes an input to the SpatioTemporalClassifier. - /// - public class SpatioTemporalInput - { - /// - /// The point which describes this input. - /// - public Vector Point { get; set; } - - /// - /// Construct a new SpatioTemporalInput with coordinate data. - /// - /// The X coordinate. - /// The Y coordinate. - public SpatioTemporalInput(double x, double y) - { - this.Point = new Vector(x, y); - } - } - - /// - /// A SmoothingBuffer class is a helper around a smoothing array. It implements a linear smoothing by taking the average over the - /// number of items pushed into the buffer. The oldest items are replaced by the newest ones. - /// - public class SmoothingBuffer - { - /// - /// A reference to an array which contains our smoothing buffer data. - /// - public Vector[] tSmoothBuffer; - - /// - /// A reference to the front of the buffer. - /// - public int iSmoothIndex = 0; - - /// - /// Create a new smoothing buffer with a default size. - /// - /// The number of elements of smoothing to use. - public SmoothingBuffer(int iSmoothSize) - { - // Check the smooth size is valid. - if (iSmoothSize <= 0) - throw new ArgumentOutOfRangeException("Cannot have a smooth size that is <= 0."); - - // Create a new smoothing buffer. - this.tSmoothBuffer = new Vector[iSmoothSize]; - this.iSmoothIndex = 0; - } - - /// - /// Return the length of the smoothing buffer. - /// - /// An integer which describes the length of the smoothing buffer. - public int getSmoothSize() - { - return this.tSmoothBuffer.Length; - } - - /// - /// This method will expand or contract the smoothing array with an option to preserve smoothing data - /// as best as it can (naturally if we are contracting then we don't take the time to compute a similar distribution) - /// we just truncate the data. Sorry for being lazy! lol - /// - /// The new size of the smoothing buffer. - /// True to preseve data, False for not. - public void resize(int iSmoothSize, bool bPreserve) - { - // Argument checking. - if (iSmoothSize <= 0) - throw new ArgumentOutOfRangeException("The smooth size cannot be <= 0."); - - // Create a new array. - Vector[] tNewBuffer = new Vector[iSmoothIndex]; - - // If we want to preserve the data we already have.. (or as much as we can). - int iMax = Math.Min(iSmoothIndex, tSmoothBuffer.Length); - if (bPreserve && tSmoothBuffer != null) - { - iMax = Math.Min(iSmoothSize, iMax); - if (iMax != 0) - { - for (int i = 0; i < iMax; ++i) - tNewBuffer[i] = tSmoothBuffer[i]; - } - } - - // Swap the pointers. - this.tSmoothBuffer = tNewBuffer; - this.iSmoothIndex = iMax; - } - - /// - /// Clear the information in this smoothing buffer. - /// - public void clear() - { - this.iSmoothIndex = 0; - } - - /// - /// Insert a value into this buffer for smoothing. - /// - /// The X coordinate. - /// The Y coordinate. - public void addValue(double x, double y) - { - // Insert the value then update the counter. - int iIndex = iSmoothIndex % tSmoothBuffer.Length; - tSmoothBuffer[iIndex].X = x; - tSmoothBuffer[iIndex].Y = y; - ++iSmoothIndex; - } - - /// - /// Insert a value into this buffer for smoothing. - /// - /// A pointer to the point structure. - public void addValue(Vector vPoint) - { - // Insert the value then update the counter. - tSmoothBuffer[iSmoothIndex % tSmoothBuffer.Length] = vPoint; - ++iSmoothIndex; - } - - public void replaceLast(Vector vPoint) - { - // Insert the value then update the counter. - int lastIndex = (iSmoothIndex - 1) % tSmoothBuffer.Length; - if(lastIndex<0) - { - lastIndex = tSmoothBuffer.Length-1; - } - - tSmoothBuffer[lastIndex] = vPoint; - } - - /// - /// Calculate and return the smoothed value. - /// Note that this function is worst case O(n) where n is the size of the smoothing buffer. - /// - /// - public Vector getSmoothedValue() - { - // Get the number of values to iterate too. - Vector tSmooth = new Vector(0, 0); - int iMax = Math.Min(iSmoothIndex, tSmoothBuffer.Length); - if (iMax == 0) - throw new Exception("No values in the smoothing buffer!"); - /* - Vector curVector = tSmoothBuffer[iMax-1]; - - if(iMax >= 5) - { - - double deltaX = Math.Abs(curVector.X*4 - tSmoothBuffer[iMax-2].X - tSmoothBuffer[iMax-3].X - tSmoothBuffer[iMax-4].X - tSmoothBuffer[iMax-5].X); - Console.WriteLine("DeltaX: "+deltaX); - if(deltaX < 200) - { - tSmoothBuffer[iMax - 1] = tSmoothBuffer[iMax - 2]; - return tSmoothBuffer[iMax-2]; - } - } - */ - // Sum up the values in the array. - for (int i = 0; i < iMax; ++i) - { - tSmooth.X += tSmoothBuffer[i].X; - tSmooth.Y += tSmoothBuffer[i].Y; - } - - // Divide to average. - tSmooth.X /= iMax; - tSmooth.Y /= iMax; - - // Return the value. - return tSmooth; - } - } -} + +using Microsoft.Win32; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows; +using WiiTUIO.Properties; + +namespace WiiTUIO.Provider +{ + /// + /// A SpatiotemporalClassifier is a class which is able to classify a frame of points based on the set of previous points + /// avaiable to it. This is designed to solve the problem of the lack of buffer-ordering from data returned by the Wiimote. + /// As such this has no concept of order; rather order is determined based on the likelyhood of it a point being related to another + /// if it was in a similar place. + /// Whilst there is no perfect solution beyond implementing buffer tracking within the actual Wiimote hardware - this class + /// uses some spatial and temporal statistics to compute a likely solution using simple calculations. As such, while its output + /// may be 'good enough' it is far from perfect. + /// + public class SpatioTemporalClassifier + { + #region Helper Pair Class + /// + /// A ProcessPair is a simple helper class which is used to enumerate and compare trackers and inputs. + /// + private class ProcessPair : IComparable + { + /// + /// The input in this pair. + /// + public SpatioTemporalInput pInput; + /// + /// The tracker in this pair. + /// + public SpatioTemporalTracker pTracker; + /// + /// The ranking between the tracker and the pair. + /// + public double fRanking; + + /// + /// Construct a new process pair. This will invoke 'getClassificationRanking' on the tracker. + /// + /// The tracker to pair. + /// The input to pair. + public ProcessPair(SpatioTemporalTracker pTracker, SpatioTemporalInput pInput) + { + this.pInput = pInput; + this.pTracker = pTracker; + this.fRanking = pTracker.getClassificationRanking(this.pInput); + } + + #region IComparable Members + /// + /// Compare this process pair to another by looking at the ranking. + /// + /// The other process pair to compare two. + /// A 32-Bit Signed Integer that states the relative sortorder of the two objects + public int CompareTo(ProcessPair pOther) + { + return this.fRanking.CompareTo(pOther.fRanking); + } + #endregion + } + #endregion + + #region Classifier Properties + /// + /// A list of active trackers. + /// + private List lTrackers; + + /// + /// The default smoothing value for any trackers created. + /// + public int DefaultSmoothSize { get; set; } + + /// + /// The distance at which we are confident two trackers are duplicating/following the same input. + /// + public double DuplicateDistance { get; set; } + + /// + /// A delegate which describes the function signature of the events this class raises. + /// + /// The classifer which raised the event. + /// The tracker of interest. + public delegate void TrackerEventHandler(SpatioTemporalClassifier pSource, SpatioTemporalTracker pTracker); + + /// + /// A counter for session varaibles. + /// + private ulong iNextID = 0; + + /// + /// An event which is raised when a new tracker is created. + /// + public event TrackerEventHandler OnStart; + + /// + /// An event which is raised when an existing tracker is removed. + /// + public event TrackerEventHandler OnEnd; + + /// + /// An event which is raised when an existing tracker is updated. + /// + public event TrackerEventHandler OnUpdate; + #endregion + + /// + /// Construct a new SpatioTemporalClassifier. + /// + public SpatioTemporalClassifier() + { + // Create the table. + this.lTrackers = new List(4); + + // Defaults. + this.DefaultSmoothSize = 3; + this.DuplicateDistance = 10; + } + + /// + /// Reset the tracker list so there is no context preserved after this call. + /// This also resets the session counter to 0. + /// + public void reset() + { + this.lTrackers.Clear(); + this.iNextID = 0; + } + + /// + /// This is called to process a 'frame' of inputs which will be ranked against eachother before being dispatched + /// to the appropriate existing inputs, removing old ones or generating new ones. + /// + /// The array of inputs which we want to process as a frame. + public void processFrame(List lInputs) + { + // Check we have data. + if (lInputs.Count + lTrackers.Count == 0) + return; + + #region Ugly (but fairly quick) duplicate tracker removal. + // Loop over an exclusive half-diagonal of a number square! :-) Ahh the memories! + bool bPossible = true; + bool bFound = false; + while (bPossible) + { + // Check for a collision! + for (int i = 0; i < lTrackers.Count; ++i) + { + // Flag that we have not found a collision on this loop round. + bFound = false; + for (int j = i + 1; j < lTrackers.Count; ++j) + { + // Test the trackers are in very close range of eachother (i.e. overlapping and stealing inputs!). + if ((lTrackers[i].Position - lTrackers[j].Position).Length < this.DuplicateDistance) + { + // They are too close - set one to be dead! + SpatioTemporalTracker pRemove = lTrackers[i]; + + // Remove it. + this.lTrackers.Remove(pRemove); + pRemove.eTrackerState = TrackerState.Destroy; + bFound = true; + + // Raise the event. + if (pRemove.StrongLock) + { + if (this.OnEnd != null) + this.OnEnd(this, pRemove); + } + } + } + + // If we found a collision we have removed it from the list and this need to check again. + if (bFound) + break; + } + + // So we got this far and had no collisions. + bPossible = bFound; + } + #endregion + + #region Process and Sort the table of all possible trackers. + // Build the big table of trackers-inputs-distances. + List lTable = new List(lInputs.Count * lTrackers.Count); + foreach (SpatioTemporalTracker pTracker in lTrackers) + { + foreach (SpatioTemporalInput pInput in lInputs) + { + // Only add it to to the table if it will not be rejected out of hand. + ProcessPair pPair = new ProcessPair(pTracker, pInput); + //if (pPair.fRanking < pTracker.PredictionScale) + lTable.Add(pPair); + } + } + + // Sort the above table based on the distance rankings. + lTable.Sort(); + #endregion + + #region Strip duplicate pairs from the tracker ranking table based on 'best' selections. + // Remove duplicate tracker entries from the table whilst saving the best pairs in their own table. + List lBest = new List(); + foreach (ProcessPair pPair in lTable) + { + // Does the table of best matches already contain this tracker? + bool bContains = false; + for (int i = 0; i < lBest.Count; ++i) + { + if (lBest[i].pTracker == pPair.pTracker) + { + bContains = true; + break; + } + } + + // If it doesn't then add it. + if (!bContains) + lBest.Add(pPair); + } + #endregion + + #region Build a list of remove candidates. + // Create an array which contains old trackers to be removed. + List lRemove = new List(); + foreach (SpatioTemporalTracker pTracker in lTrackers) + { + // Does the table of best matches already contain this input? + bool bContains = false; + for (int i = 0; i < lBest.Count; ++i) + { + if (lBest[i].pTracker == pTracker) + { + bContains = true; + break; + } + } + + // If it doesn't then add it. + if (!bContains) + lRemove.Add(pTracker); + } + #endregion + + #region Build a list of create candidates. + // Create an array which contains new trackers to be created. + List lCreate = new List(); + foreach (SpatioTemporalInput pInput in lInputs) + { + // Does the table of best matches already contain this input? + bool bContains = false; + for (int i = 0; i < lBest.Count; ++i) + { + if (lBest[i].pInput == pInput) + { + bContains = true; + break; + } + } + + // If it doesn't then add it. + if (!bContains) + lCreate.Add(pInput); + } + #endregion + + // So now we need to dispatch some more processing. + + // Update the best matches. + this.dispatchUpdates(lBest); + + // Remove the old. + this.removeOld(lRemove); + + // Create the new. + this.createNew(lCreate); + } + + /// + /// Dispatch updates to trackers which have just consumed a new input. + /// + /// The list of pairs to dispatch. + private void dispatchUpdates(List lPairs) + { + // Have the tracker in each pair consume its own input.. How perverse does that sound? :-p + foreach (ProcessPair pPair in lPairs) + { + // Consume it. + pPair.pTracker.consumeInput(pPair.pInput); + + // Ensure we have a strong lock before firing the event. + if (pPair.pTracker.StrongLock) + { + // If the tracker state has moved from discovered then good times. + if (pPair.pTracker.eTrackerState == TrackerState.Discover) + { + // Update the state to match a forwarder and raise the 'OnStart' event. + pPair.pTracker.eTrackerState = TrackerState.Forward; + if (this.OnStart != null) + this.OnStart(this, pPair.pTracker); + } + else + { + // Raise the event. + if (this.OnUpdate != null) + this.OnUpdate(this, pPair.pTracker); + } + } + } + } + + /// + /// Dispatch updates to trackers which have recieved no inputs. + /// + /// The list trackers to remove. + private void removeOld(List lTrackers) + { + // Remove the old trackers from the list and raise an event for each one saying its happened. + foreach (SpatioTemporalTracker pRemove in lTrackers) + { + // Consume nothing (used so we know how many events before it died). + pRemove.consumeNothing(); + + // If we have strong feeling we lost the lock - kill it. + if (pRemove.StrongLostLock) + { + // Remove it. + this.lTrackers.Remove(pRemove); + pRemove.eTrackerState = TrackerState.Destroy; + + // Raise the event. + if (pRemove.StrongLock) + { + if (this.OnEnd != null) + this.OnEnd(this, pRemove); + } + } + } + } + + /// + /// Dispatch updates to trackers which have just been created. + /// + /// The list trackers to create. + private void createNew(List lInputs) + { + // Create new trackers for each input. + foreach (SpatioTemporalInput pInput in lInputs) + { + // Create new, insert input and then append. + SpatioTemporalTracker pTracker = new SpatioTemporalTracker(this.DefaultSmoothSize, ++this.iNextID); + pTracker.consumeInput(pInput); + pTracker.eTrackerState = TrackerState.Discover; + lTrackers.Add(pTracker); + + // Raise the event. + //if (this.OnStart != null) + // this.OnStart(this, pTracker); + } + } + + } + + /// + /// An internally enumerated tracker state that is only known to the Classifier and Tracker. + /// + internal enum TrackerState + { + /// + /// The tracker has just been discovered and should be raised as a start event once the next move event is recieved. + /// + Discover = 0, + /// + /// The tracker has just been lost and should be raised as a lost event if no more move events are recieved. + /// + Destroy = 1, + /// + /// The tracker has moved from discovered to forward so all subsequent events should be forwarded. + /// + Forward = 2, + } + + /// + /// A SpatioTemporalTracker is a class which represents a context for an existing input. It is used to determine if a new input bears any relevance to it or is + /// simply a new point. + /// + public class SpatioTemporalTracker + { + #region Static Defaults + /// + /// The number of inputs the tracker should recieve before we are confident it is definately active. + /// + public static uint StrongLockThreshold = 0; + + /// + /// The number of non-inputs the tracker should recieve before we are confident it is definately dead. + /// + public static uint StrongLockLostThreshold = 0; + #endregion + + #region Properties + /// + /// A reference to the smoothing buffer which is responsible for, well, smoothing the input positions. + /// + public SmoothingBuffer SmoothingBuffer { get; protected set; } + + /// + /// Return the smoothed position of the input this tracker is tracking. + /// + public Vector Position { get; protected set; } + + /// + /// Return the smoothed normalised position of the input this tracker is tracking. + /// + public Vector NormalPosition { get; protected set; } + + /// + /// Return the non-normalised forward vector of this tracker which is essentially the lastpos - currentpos. + /// + public Vector Forward { get; protected set; } + + /// + /// Return the normalised forward vector of this tracker which is essentially the lastpos - currentpos scaled by its length. + /// + public Vector NormalForward { get; protected set; } + + /// + /// Return the unique tracker number as returned from this classifier. + /// + public ulong ID { get; protected set; } + + /// + /// This will return True if we are sure that this tracker is actively recieving input. + /// + public bool StrongLock { get { return iTrackerLock > StrongLockThreshold; } } + + /// + /// This will return True if we are sure this tracker has not recieved any recent input. + /// + public bool StrongLostLock { get { return iTrackerLostLock > StrongLockLostThreshold; } } + + /// + /// The starting position of this tracker object. + /// + public Vector StartPosition { get; protected set; } + #endregion + + #region Prediction + /// + /// Return the scale factor for the prediction megnitude. + /// + public double PredictionScale { get; set; } + + /// + /// Return the next predicted position of this tracker. + /// + public Vector PredictedNextPosition { get { return new Vector(Position.X + (NormalForward.X * PredictionScale), Position.Y + (NormalForward.Y * PredictionScale)); } } + + /// + /// Return the next predicted position of this tracker but in the opposite direction. + /// + public Vector PredictedLastPosition { get { return new Vector(Position.X - (NormalForward.X * PredictionScale), Position.Y - (NormalForward.Y * PredictionScale)); } } + #endregion + + #region Helpers + /// + /// The classifier-internal state of this tracker (i.e. do we need to treat it spectially because it is existing in an undetermined state?) + /// + internal TrackerState eTrackerState { get; set; } + + /// + /// The counter for the number of inputs recieved. + /// + internal int iTrackerLock = 0; + + /// + /// The counter for the number of non-inputs recieved. + /// + internal int iTrackerLostLock = 0; + #endregion + + System.Windows.Forms.Screen primaryScreen; + + /// + /// Construct a new tracker with a default smoothing value. + /// + /// The smoothing value. + /// The unique session ID for this tracker. + public SpatioTemporalTracker(int iSmoothSize, ulong iID)//, double fMinRadius, double fMaxRadius, double fRadiusExpansion) + { + // Build a smoothing buffer. + this.SmoothingBuffer = new SmoothingBuffer(iSmoothSize); + + // Save the ID. + this.ID = iID; + + this.primaryScreen = DeviceUtils.DeviceUtil.GetScreen(Settings.Default.primaryMonitor); + + Settings.Default.PropertyChanged += SettingsChanged; + SystemEvents.DisplaySettingsChanged += SystemEvents_DisplaySettingsChanged; + + // Save the state. + this.eTrackerState = TrackerState.Discover; + this.PredictionScale = Math.Max(primaryScreen.Bounds.Width, primaryScreen.Bounds.Height); + } + + + private void SettingsChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) + { + if (e.PropertyName == "primaryMonitor") + { + primaryScreen = DeviceUtils.DeviceUtil.GetScreen(Settings.Default.primaryMonitor); + this.PredictionScale = Math.Max(primaryScreen.Bounds.Width, primaryScreen.Bounds.Height); + } + } + private void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e) + { + primaryScreen = DeviceUtils.DeviceUtil.GetScreen(Settings.Default.primaryMonitor); + this.PredictionScale = Math.Max(primaryScreen.Bounds.Width, primaryScreen.Bounds.Height); + } + + /// + /// Take an input which is gaurenteed to be part of this tracker. Update the tracker based on the input. + /// + /// The input we wish to consume. + public void consumeInput(SpatioTemporalInput pInput) + { + // Add the point to the smoothing buffer. + this.SmoothingBuffer.addValue(pInput.Point); + + // Compute the position as the newly smoothed value. + Vector tLastPosition = this.Position; + this.Position = this.SmoothingBuffer.getSmoothedValue(); + + // Compute the forward as the difference between the two. + Forward = new Vector(tLastPosition.X - this.Position.X, tLastPosition.Y - this.Position.Y); + + // Compute the radius as the length of the next predicted. + //double fLength = Forward.Length * 10; + //fLength = 100;// Math.Max(50, Math.Min(fLength, 500)); + //if (fLength == 0) + // fLength = 100.0f; + + // Compute the normalised forward vector. + NormalForward = Forward; + NormalForward.Normalize(); + + // Now, if I were handling an adaptive radius, I would update it here to encompass the new predicted position. + //PredictionScale = fLength; + + // If our tracker lock is 0 then it is sorta-safe to say we are the starting position. + if (iTrackerLock == 0) + StartPosition = Position; + + // Increment the tracker lock and reset the lost lock to 0. + ++iTrackerLock; + iTrackerLostLock = 0; + } + + /// + /// This is called to notify this tracker that we recieved a situation which made it seem like it was lost. + /// Internally this increments a counter which affects a 'lost lock', which, when it reaches a threshold becomes sure that we have no more data for it. + /// + public void consumeNothing() + { + ++iTrackerLostLock; + } + + /// + /// This function determines a double value which ranks the likelyhood a point is part of this tracker. + /// Smaller numbers are more likely than larger ones. Distributions need all the data in order to be normalised with respect to another. + /// + /// + /// A double word value which ranks the likelyhood of this input being part of this tracker. Smaller is better. + public double getClassificationRanking(SpatioTemporalInput pInput) + { + // TODO: TIME IS NOT TAKEN INTO ACCOUNT OF IN THESE EQUATIONS.... + + // Compute the distance of the input point to the best and predicted. + Vector vInput = pInput.Point; + double fDistanceFromBest = (Position - vInput).Length; + double fDistanceFromPredicted = (PredictedNextPosition - vInput).Length; + + // Select the smallest of the two lengths (an optimistic algorythm). + return Math.Min(fDistanceFromBest, fDistanceFromPredicted); + } + + /// + /// Returns the distance of vPoint to the segment defined by vLineA,vLineB; + /// + /// First point of the segment. + /// Second point of the segment. + /// The point to which we want to know the distance of the segment. + /// The distance of vPoint to the segment defined by vLineA, vLineB. + public static double distanceToSegment(Vector vLineA, Vector vLineB, Vector vPoint) + { + // Compute the delta. + Vector vDelta = vLineB - vLineA; + + // Ensure the arguments are ok. + if ((vDelta.X == 0) && (vDelta.Y == 0)) + { + throw new Exception("vLineA and vLineB cannot be the same point"); + } + + // Solve for u: [P3 - P1 - u(P2 - P1)] dot (P2 - P1) = 0 + double u = ((vPoint.X - vLineA.X) * vDelta.X + (vPoint.Y - vLineA.Y) * vDelta.Y) / (vDelta.X * vDelta.X + vDelta.Y * vDelta.Y); + + // Compute the closest point on the line segment. + Vector vClosest; + if (u < 0) + { + vClosest = vLineA; + } + else if (u > 1) + { + vClosest = vLineB; + } + else + { + vClosest = new Vector(vLineA.X + u * vDelta.X, vLineA.Y + u * vDelta.Y); + } + + // Return the distance between the closest point on the line and the actual point. + return (vClosest - vPoint).Length; //vClosest.distance(vPoint); + } + } + + /// + /// A SpatioTemporalInput describes an input to the SpatioTemporalClassifier. + /// + public class SpatioTemporalInput + { + /// + /// The point which describes this input. + /// + public Vector Point { get; set; } + + /// + /// Construct a new SpatioTemporalInput with coordinate data. + /// + /// The X coordinate. + /// The Y coordinate. + public SpatioTemporalInput(double x, double y) + { + this.Point = new Vector(x, y); + } + } + + /// + /// A SmoothingBuffer class is a helper around a smoothing array. It implements a linear smoothing by taking the average over the + /// number of items pushed into the buffer. The oldest items are replaced by the newest ones. + /// + public class SmoothingBuffer + { + /// + /// A reference to an array which contains our smoothing buffer data. + /// + public Vector[] tSmoothBuffer; + + /// + /// A reference to the front of the buffer. + /// + public int iSmoothIndex = 0; + + /// + /// Create a new smoothing buffer with a default size. + /// + /// The number of elements of smoothing to use. + public SmoothingBuffer(int iSmoothSize) + { + // Check the smooth size is valid. + if (iSmoothSize <= 0) + throw new ArgumentOutOfRangeException("Cannot have a smooth size that is <= 0."); + + // Create a new smoothing buffer. + this.tSmoothBuffer = new Vector[iSmoothSize]; + this.iSmoothIndex = 0; + } + + /// + /// Return the length of the smoothing buffer. + /// + /// An integer which describes the length of the smoothing buffer. + public int getSmoothSize() + { + return this.tSmoothBuffer.Length; + } + + /// + /// This method will expand or contract the smoothing array with an option to preserve smoothing data + /// as best as it can (naturally if we are contracting then we don't take the time to compute a similar distribution) + /// we just truncate the data. Sorry for being lazy! lol + /// + /// The new size of the smoothing buffer. + /// True to preseve data, False for not. + public void resize(int iSmoothSize, bool bPreserve) + { + // Argument checking. + if (iSmoothSize <= 0) + throw new ArgumentOutOfRangeException("The smooth size cannot be <= 0."); + + // Create a new array. + Vector[] tNewBuffer = new Vector[iSmoothIndex]; + + // If we want to preserve the data we already have.. (or as much as we can). + int iMax = Math.Min(iSmoothIndex, tSmoothBuffer.Length); + if (bPreserve && tSmoothBuffer != null) + { + iMax = Math.Min(iSmoothSize, iMax); + if (iMax != 0) + { + for (int i = 0; i < iMax; ++i) + tNewBuffer[i] = tSmoothBuffer[i]; + } + } + + // Swap the pointers. + this.tSmoothBuffer = tNewBuffer; + this.iSmoothIndex = iMax; + } + + /// + /// Clear the information in this smoothing buffer. + /// + public void clear() + { + this.iSmoothIndex = 0; + } + + /// + /// Insert a value into this buffer for smoothing. + /// + /// The X coordinate. + /// The Y coordinate. + public void addValue(double x, double y) + { + // Insert the value then update the counter. + int iIndex = iSmoothIndex % tSmoothBuffer.Length; + tSmoothBuffer[iIndex].X = x; + tSmoothBuffer[iIndex].Y = y; + ++iSmoothIndex; + } + + /// + /// Insert a value into this buffer for smoothing. + /// + /// A pointer to the point structure. + public void addValue(Vector vPoint) + { + // Insert the value then update the counter. + tSmoothBuffer[iSmoothIndex % tSmoothBuffer.Length] = vPoint; + ++iSmoothIndex; + } + + /// + /// Fill a value into this buffer. No mouse run when coming back from out of bounds. + /// + /// The X coordinate. + /// The Y coordinate. + public void fill(double x, double y) + { + // Insert the value then update the counter. + for (int i = 0; i < tSmoothBuffer.Length; ++i) + { + tSmoothBuffer[i].X = x; + tSmoothBuffer[i].Y = y; + } + } + + public void replaceLast(Vector vPoint) + { + // Insert the value then update the counter. + int lastIndex = (iSmoothIndex - 1) % tSmoothBuffer.Length; + if(lastIndex<0) + { + lastIndex = tSmoothBuffer.Length-1; + } + + tSmoothBuffer[lastIndex] = vPoint; + } + + /// + /// Calculate and return the smoothed value. + /// Note that this function is worst case O(n) where n is the size of the smoothing buffer. + /// + /// + public Vector getSmoothedValue() + { + // Get the number of values to iterate too. + Vector tSmooth = new Vector(0, 0); + int iMax = Math.Min(iSmoothIndex, tSmoothBuffer.Length); + if (iMax == 0) + throw new Exception("No values in the smoothing buffer!"); + /* + Vector curVector = tSmoothBuffer[iMax-1]; + + if(iMax >= 5) + { + + double deltaX = Math.Abs(curVector.X*4 - tSmoothBuffer[iMax-2].X - tSmoothBuffer[iMax-3].X - tSmoothBuffer[iMax-4].X - tSmoothBuffer[iMax-5].X); + Console.WriteLine("DeltaX: "+deltaX); + if(deltaX < 200) + { + tSmoothBuffer[iMax - 1] = tSmoothBuffer[iMax - 2]; + return tSmoothBuffer[iMax-2]; + } + } + */ + // Sum up the values in the array. + for (int i = 0; i < iMax; ++i) + { + tSmooth.X += tSmoothBuffer[i].X; + tSmooth.Y += tSmoothBuffer[i].Y; + } + + // Divide to average. + tSmooth.X /= iMax; + tSmooth.Y /= iMax; + + // Return the value. + return tSmooth; + } + } +} diff --git a/WiiTUIO/KeymapConfig/KeymapDatabase.cs b/WiiTUIO/KeymapConfig/KeymapDatabase.cs index 720e0c5a..6fe8bcda 100644 --- a/WiiTUIO/KeymapConfig/KeymapDatabase.cs +++ b/WiiTUIO/KeymapConfig/KeymapDatabase.cs @@ -1,697 +1,698 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using WiiTUIO.Properties; - -namespace WiiTUIO -{ - class KeymapDatabase - { - public string DisableKey { get; private set; } - - private List allInputs; - private List allOutputs; - - private string DEFAULT_JSON_FILENAME = "default.json"; - - private static KeymapDatabase currentInstance; - public static KeymapDatabase Current - { - get - { - if (currentInstance == null) - { - currentInstance = new KeymapDatabase(); - } - return currentInstance; - } - } - - private KeymapDatabase() - { - this.DisableKey = "disable"; - - allInputs = new List(); - allInputs.Add(new KeymapInput(KeymapInputSource.IR, "Pointer", "Pointer", false, false, true)); - allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "A", "A")); - allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "B", "B")); - allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "Home", "Home")); - allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "Left", "Left")); - allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "Right", "Right")); - allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "Up", "Up")); - allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "Down", "Down")); - allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "Plus", "Plus")); - allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "Minus", "Minus")); - allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "One", "One")); - allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "Two", "Two")); - allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "Tilt X-", "AccelX-", true, true, false)); - allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "Tilt X+", "AccelX+", true, true, false)); - allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "Tilt Y-", "AccelY-", true, true, false)); - allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "Tilt Y+", "AccelY+", true, true, false)); - allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "Tilt Z-", "AccelZ-", true, true, false)); - allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "Tilt Z+", "AccelZ+", true, true, false)); - - allInputs.Add(new KeymapInput(KeymapInputSource.NUNCHUK, "C", "Nunchuk.C")); - allInputs.Add(new KeymapInput(KeymapInputSource.NUNCHUK, "Z", "Nunchuk.Z")); - allInputs.Add(new KeymapInput(KeymapInputSource.NUNCHUK, "Stick Up", "Nunchuk.StickUp", true, true, false)); - allInputs.Add(new KeymapInput(KeymapInputSource.NUNCHUK, "Stick Down", "Nunchuk.StickDown", true, true, false)); - allInputs.Add(new KeymapInput(KeymapInputSource.NUNCHUK, "Stick Left", "Nunchuk.StickLeft", true, true, false)); - allInputs.Add(new KeymapInput(KeymapInputSource.NUNCHUK, "Stick Right", "Nunchuk.StickRight", true, true, false)); - allInputs.Add(new KeymapInput(KeymapInputSource.NUNCHUK, "Tilt X-", "Nunchuk.AccelX-", true, true, false)); - allInputs.Add(new KeymapInput(KeymapInputSource.NUNCHUK, "Tilt X+", "Nunchuk.AccelX+", true, true, false)); - allInputs.Add(new KeymapInput(KeymapInputSource.NUNCHUK, "Tilt Y-", "Nunchuk.AccelY-", true, true, false)); - allInputs.Add(new KeymapInput(KeymapInputSource.NUNCHUK, "Tilt Y+", "Nunchuk.AccelY+", true, true, false)); - allInputs.Add(new KeymapInput(KeymapInputSource.NUNCHUK, "Tilt Z-", "Nunchuk.AccelZ-", true, true, false)); - allInputs.Add(new KeymapInput(KeymapInputSource.NUNCHUK, "Tilt Z+", "Nunchuk.AccelZ+", true, true, false)); - - - allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Left", "Classic.Left")); - allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Right", "Classic.Right")); - allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Up", "Classic.Up")); - allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Down", "Classic.Down")); - - allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Left Stick Left", "Classic.StickLLeft", true, true, false)); - allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Left Stick Right", "Classic.StickLRight", true, true, false)); - allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Left Stick Up", "Classic.StickLUp", true, true, false)); - allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Left Stick Down", "Classic.StickLDown", true, true, false)); - allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Right Stick Left", "Classic.StickRLeft", true, true, false)); - allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Right Stick Right", "Classic.StickRRight", true, true, false)); - allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Right Stick Up", "Classic.StickRUp", true, true, false)); - allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Right Stick Down", "Classic.StickRDown", true, true, false)); - - allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Minus", "Classic.Minus")); - allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Plus", "Classic.Plus")); - allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Home", "Classic.Home")); - allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Y", "Classic.Y")); - allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "X", "Classic.X")); - allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "A", "Classic.A")); - allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "B", "Classic.B")); - allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Left Trigger", "Classic.TriggerL", false, true, false)); - allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Right Trigger", "Classic.TriggerR", false, true, false)); - allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Left Trigger Push", "Classic.L")); - allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Right Trigger Push", "Classic.R")); - allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "ZL", "Classic.ZL")); - allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "ZR", "Classic.ZR")); - - allOutputs = new List(); - allOutputs.Add(new KeymapOutput(KeymapOutputType.TOUCH, "Touch Cursor", "touch", false, false, true, false)); - allOutputs.Add(new KeymapOutput(KeymapOutputType.TOUCH, "Touch Cursor Left", "touchx-", false, true, false, false)); - allOutputs.Add(new KeymapOutput(KeymapOutputType.TOUCH, "Touch Cursor Right", "touchx+", false, true, false, false)); - allOutputs.Add(new KeymapOutput(KeymapOutputType.TOUCH, "Touch Cursor Up", "touchy+", false, true, false, false)); - allOutputs.Add(new KeymapOutput(KeymapOutputType.TOUCH, "Touch Cursor Down", "touchy-", false, true, false, false)); - allOutputs.Add(new KeymapOutput(KeymapOutputType.TOUCH, "Touch Main", "touchmaster")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.TOUCH, "Touch Slave", "touchslave")); - - allOutputs.Add(new KeymapOutput(KeymapOutputType.MOUSE, "Mouse Cursor", "mouse", false, false, true, false)); - allOutputs.Add(new KeymapOutput(KeymapOutputType.MOUSE, "Mouse Camera/View", "fpsmouse", false, false, true, false)); - allOutputs.Add(new KeymapOutput(KeymapOutputType.MOUSE, "Mouse Left", "mouseleft")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.MOUSE, "Mouse Right", "mouseright")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.MOUSE, "Mouse Move Right", "mousex+", true, true, false, false)); - allOutputs.Add(new KeymapOutput(KeymapOutputType.MOUSE, "Mouse Move Up", "mousey+", true, true, false, false)); - allOutputs.Add(new KeymapOutput(KeymapOutputType.MOUSE, "Mouse Move Left", "mousex-", true, true, false, false)); - allOutputs.Add(new KeymapOutput(KeymapOutputType.MOUSE, "Mouse Move Down", "mousey-", true, true, false, false)); - //allOutputs.Add(new KeymapOutput(KeymapOutputType.MOUSE, "Mouse Middle", "mbutton")); - //allOutputs.Add(new KeymapOutput(KeymapOutputType.MOUSE, "Mouse Extra 1", "xbutton1")); - //allOutputs.Add(new KeymapOutput(KeymapOutputType.MOUSE, "Mouse Extra 2", "xbutton2")); - - - - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Tab", "tab")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Backspace", "back")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Return", "return")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Shift", "shift")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Control", "control")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Alt", "menu")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Pause", "pause")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Caps Lock", "capital")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Escape", "escape")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Spacebar", "space")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Page Up", "prior")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Page Down", "next")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "End", "end")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Home", "home")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Arrow Left", "left")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Arrow Up", "up")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Arrow Right", "right")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Arrow Down", "down")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Print Screen", "snapshot")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Insert", "insert")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Delete", "delete")); - - - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "0", "vk_0")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "1", "vk_1")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "2", "vk_2")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "3", "vk_3")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "4", "vk_4")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "5", "vk_5")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "6", "vk_6")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "7", "vk_7")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "8", "vk_8")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "9", "vk_9")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "A", "vk_a")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "B", "vk_b")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "C", "vk_c")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "D", "vk_d")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "E", "vk_e")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "F", "vk_f")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "G", "vk_g")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "H", "vk_h")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "I", "vk_i")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "J", "vk_j")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "K", "vk_k")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "L", "vk_l")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "M", "vk_m")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "N", "vk_n")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "O", "vk_o")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "P", "vk_p")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Q", "vk_q")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "R", "vk_r")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "S", "vk_s")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "T", "vk_t")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "U", "vk_u")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "V", "vk_v")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "W", "vk_w")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "X", "vk_x")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Y", "vk_y")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Z", "vk_z")); - - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Period .", "oem_period")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Comma ,", "oem_comma")); - - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Left Win", "lwin")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Right Win", "rwin")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Apps / Menu", "apps")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Numpad 0", "numpad0")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Numpad 1", "numpad1")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Numpad 2", "numpad2")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Numpad 3", "numpad3")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Numpad 4", "numpad4")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Numpad 5", "numpad5")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Numpad 6", "numpad6")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Numpad 7", "numpad7")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Numpad 8", "numpad8")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Numpad 9", "numpad9")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Multiply *", "multiply")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Add +", "add")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Subtract -", "subtract")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Decimal ,", "decimal")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Divide /", "divide")); - - - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "F1", "f1")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "F2", "f2")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "F3", "f3")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "F4", "f4")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "F5", "f5")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "F6", "f6")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "F7", "f7")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "F8", "f8")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "F9", "f9")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "F10", "f10")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "F11", "f11")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "F12", "f12")); - - - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Numlock", "numlock")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Left Shift", "lshift")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Right Shift", "rshift")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Left Control", "lcontrol")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Right Control", "rcontrol")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Left Alt", "lmenu")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Right Alt", "rmenu")); - - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Browser Back", "browser_back")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Browser Forward", "browser_forward")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Browser Refresh", "browser_refresh")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Browser Stop", "browser_stop")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Browser Search", "browser_search")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Browser Favorites", "browser_favorites")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Browser Home", "browser_home")); - - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Volume Mute", "volume_mute")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Volume Up", "volume_up")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Volume Down", "volume_down")); - - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Next Track", "media_next_track")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Previous Track", "media_prev_track")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Stop Media", "media_stop")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Play/Pause Media", "media_play_pause")); - - allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Zoom", "zoom")); - - allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "A", "360.a")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "B", "360.b")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "X", "360.x")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Y", "360.y")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Left", "360.left")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Right", "360.right")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Up", "360.up")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Down", "360.down")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Back", "360.back")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Start", "360.start")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Guide", "360.guide")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Left Stick Press", "360.stickpressl")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Right Stick Press", "360.stickpressr")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Left Stick", "360.stickl", false, false, true, false)); - allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Left Stick Up", "360.sticklup", true, true, false, false)); - allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Left Stick Down", "360.stickldown", true, true, false, false)); - allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Left Stick Left", "360.sticklleft", true, true, false, false)); - allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Left Stick Right", "360.sticklright", true, true, false, false)); - allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Right Stick", "360.stickr", false, false, true, false)); - allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Right Stick Up", "360.stickrup", true, true, false, false)); - allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Right Stick Down", "360.stickrdown", true, true, false, false)); - allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Right Stick Left", "360.stickrleft", true, true, false, false)); - allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Right Stick Right", "360.stickrright", true, true, false, false)); - allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Left Trigger", "360.triggerl", true, true, false, false)); - allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Right Trigger", "360.triggerr", true, true, false, false)); - allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Left Bumper", "360.bumperl")); - allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Right Bumper", "360.bumperr")); - - allOutputs.Add(new KeymapOutput(KeymapOutputType.DISABLE, "Disable", this.DisableKey)); - } - - - public KeymapSettings getKeymapSettings() - { - return new KeymapSettings(Settings.Default.keymaps_config); - } - - public List getAllKeymaps() - { - List list = new List(); - string[] files = Directory.GetFiles(Settings.Default.keymaps_path, "*.json"); - string defaultKeymapFilename = this.getKeymapSettings().getDefaultKeymap(); - - Keymap defaultKeymap = new Keymap(null, defaultKeymapFilename); - list.Add(defaultKeymap); - - foreach (string filepath in files) - { - string filename = Path.GetFileName(filepath); - if (filename != Settings.Default.keymaps_config && filename != defaultKeymapFilename) - { - list.Add(new Keymap(defaultKeymap, filename)); - } - } - return list; - } - - public Keymap getKeymap(string filename) - { - List list = this.getAllKeymaps(); - - foreach (Keymap keymap in list) - { - if (keymap.Filename == filename) - { - return keymap; - } - } - return null; - } - - public Keymap getDefaultKeymap() - { - List list = this.getAllKeymaps(); - KeymapSettings settings = this.getKeymapSettings(); - - foreach (Keymap keymap in list) - { - if (keymap.Filename == settings.getDefaultKeymap()) - { - return keymap; - } - } - return null; - } - - public List getAvailableInputs() - { - return allInputs; - } - - public List getAvailableInputs(KeymapInputSource source) - { - List list = new List(); - foreach (KeymapInput input in allInputs) - { - if (input.Source == source) - { - list.Add(input); - } - } - return list; - } - - public List getAvailableOutputs() - { - return allOutputs; - } - - public List getAvailableOutputs(KeymapOutputType type) - { - if (type == KeymapOutputType.ALL) - { - return allOutputs; - } - List list = new List(); - foreach (KeymapOutput output in allOutputs) - { - if (output.Type == type) - { - list.Add(output); - } - } - return list; - } - - public KeymapInput getInput(string key) - { - List list = this.allInputs; - foreach (KeymapInput input in list) - { - if (input.Key.ToLower() == key.ToLower()) - { - return input; - } - } - return null; - } - - public KeymapOutput getOutput(string key) - { - List list = this.allOutputs; - foreach (KeymapOutput output in list) - { - if (output.Key.ToLower() == key.ToLower()) - { - return output; - } - } - return null; - } - - public KeymapOutput getDisableOutput() - { - return this.getAvailableOutputs(KeymapOutputType.DISABLE).First(); - } - - public bool deleteKeymap(Keymap keymap) - { - if (keymap.Filename == this.getKeymapSettings().getDefaultKeymap()) - { - return false; - } - this.getKeymapSettings().removeFromLayoutChooser(keymap); - this.getKeymapSettings().removeFromApplicationSearch(keymap); - File.Delete(Settings.Default.keymaps_path + keymap.Filename); - return true; - } - - public Keymap createNewKeymap() - { - List list = new List(); - string[] files = Directory.GetFiles(Settings.Default.keymaps_path, "*.json"); - - string suggestedFilename = "z_custom.json"; - - bool recheck = false; - - int iterations = 0; - - do - { - recheck = false; - foreach (string filepath in files) - { - string filename = Path.GetFileName(filepath); - if (suggestedFilename == filename) - { - suggestedFilename = "z_custom_" + (++iterations) + ".json"; - recheck = true; - } - } - } while (recheck); - - return new Keymap(this.getDefaultKeymap(), suggestedFilename); - } - - - - public void CreateDefaultFiles() - { - this.createDefaultApplicationsJSON(); - this.createDefaultKeymapJSON(); - } - - private static void MergeJSON(JObject receiver, JObject donor) - { - foreach (var property in donor) - { - JObject receiverValue = receiver[property.Key] as JObject; - JObject donorValue = property.Value as JObject; - if (receiverValue != null && donorValue != null) - MergeJSON(receiverValue, donorValue); - else - receiver[property.Key] = property.Value; - } - } - - private JObject createDefaultApplicationsJSON() - { - JArray layouts = new JArray(); - layouts.Add(new JObject( - new JProperty("Name", "Default"), - new JProperty("Keymap", DEFAULT_JSON_FILENAME) - )); - - JArray applications = new JArray(); - - JObject applicationList = - new JObject( - new JProperty("LayoutChooser", layouts), - new JProperty("Applications", applications), - new JProperty("Default", DEFAULT_JSON_FILENAME) - ); - - JObject union = applicationList; - - if (File.Exists(Settings.Default.keymaps_path + Settings.Default.keymaps_config)) - { - StreamReader reader = File.OpenText(Settings.Default.keymaps_path + Settings.Default.keymaps_config); - try - { - JObject existingConfig = (JObject)JToken.ReadFrom(new JsonTextReader(reader)); - reader.Close(); - - MergeJSON(union, existingConfig); - } - catch (Exception e) - { - throw new Exception(Settings.Default.keymaps_path + Settings.Default.keymaps_config + " is not valid JSON"); - } - } - - File.WriteAllText(Settings.Default.keymaps_path + Settings.Default.keymaps_config, union.ToString()); - return union; - } - - private JObject createDefaultKeymapJSON() - { - JObject buttons = new JObject(); - - buttons.Add(new JProperty("Pointer", "Touch")); - - buttons.Add(new JProperty("A", "TouchMaster")); - - buttons.Add(new JProperty("B", "TouchSlave")); - - buttons.Add(new JProperty("Home", "LWin")); - - buttons.Add(new JProperty("Left", "Left")); - buttons.Add(new JProperty("Right", "Right")); - buttons.Add(new JProperty("Up", "Up")); - buttons.Add(new JProperty("Down", "Down")); - - buttons.Add(new JProperty("Plus", "Volume_Up")); - - buttons.Add(new JProperty("Minus", "Volume_Down")); - - JArray buttonOne = new JArray(); - buttonOne.Add(new JValue("LWin")); - buttonOne.Add(new JValue("VK_C")); - buttons.Add(new JProperty("One", buttonOne)); - - JArray buttonTwo = new JArray(); - buttonTwo.Add(new JValue("LWin")); - buttonTwo.Add(new JValue("Tab")); - buttons.Add(new JProperty("Two", buttonTwo)); - - buttons.Add(new JProperty("AccelX+", "disable")); - buttons.Add(new JProperty("AccelX-", "disable")); - buttons.Add(new JProperty("AccelY+", "disable")); - buttons.Add(new JProperty("AccelY-", "disable")); - buttons.Add(new JProperty("AccelZ+", "disable")); - buttons.Add(new JProperty("AccelZ-", "disable")); - - buttons.Add(new JProperty("Nunchuk.StickUp", "360.StickLUp")); - buttons.Add(new JProperty("Nunchuk.StickDown", "360.StickLDown")); - buttons.Add(new JProperty("Nunchuk.StickLeft", "360.StickLLeft")); - buttons.Add(new JProperty("Nunchuk.StickRight", "360.StickLRight")); - buttons.Add(new JProperty("Nunchuk.C", "360.TriggerL")); - buttons.Add(new JProperty("Nunchuk.Z", "360.TriggerR")); - - buttons.Add(new JProperty("Classic.Left", "360.Left")); - buttons.Add(new JProperty("Classic.Right", "360.Right")); - buttons.Add(new JProperty("Classic.Up", "360.Up")); - buttons.Add(new JProperty("Classic.Down", "360.Down")); - buttons.Add(new JProperty("Classic.StickLUp", "360.StickLUp")); - buttons.Add(new JProperty("Classic.StickLDown", "360.StickLDown")); - buttons.Add(new JProperty("Classic.StickLLeft", "360.StickLLeft")); - buttons.Add(new JProperty("Classic.StickLRight", "360.StickLRight")); - buttons.Add(new JProperty("Classic.StickRUp", "360.StickRUp")); - buttons.Add(new JProperty("Classic.StickRDown", "360.StickRDown")); - buttons.Add(new JProperty("Classic.StickRLeft", "360.StickRLeft")); - buttons.Add(new JProperty("Classic.StickRRight", "360.StickRRight")); - buttons.Add(new JProperty("Classic.Minus", "360.Back")); - buttons.Add(new JProperty("Classic.Plus", "360.Start")); - buttons.Add(new JProperty("Classic.Home", "360.Guide")); - buttons.Add(new JProperty("Classic.Y", "360.Y")); - buttons.Add(new JProperty("Classic.X", "360.X")); - buttons.Add(new JProperty("Classic.A", "360.A")); - buttons.Add(new JProperty("Classic.B", "360.B")); - buttons.Add(new JProperty("Classic.TriggerL", "360.TriggerL")); - buttons.Add(new JProperty("Classic.TriggerR", "360.TriggerR")); - buttons.Add(new JProperty("Classic.L", "360.L")); - buttons.Add(new JProperty("Classic.R", "360.R")); - buttons.Add(new JProperty("Classic.ZL", "360.BumperL")); - buttons.Add(new JProperty("Classic.ZR", "360.BumperR")); - - JObject union = new JObject(); - - union.Add(new JProperty("Title", "Default")); - - union.Add(new JProperty("All", buttons)); - - if (File.Exists(Settings.Default.keymaps_path + Settings.Default.keymaps_config)) - { - StreamReader reader = File.OpenText(Settings.Default.keymaps_path + DEFAULT_JSON_FILENAME); - try - { - JObject existingConfig = (JObject)JToken.ReadFrom(new JsonTextReader(reader)); - reader.Close(); - - MergeJSON(union, existingConfig); - } - catch (Exception e) - { - throw new Exception(Settings.Default.keymaps_path + DEFAULT_JSON_FILENAME + " is not valid JSON"); - } - } - File.WriteAllText(Settings.Default.keymaps_path + DEFAULT_JSON_FILENAME, union.ToString()); - return union; - } - } - - public enum KeymapInputSource - { - IR, - WIIMOTE, - NUNCHUK, - CLASSIC - } - - public class KeymapInput - { - public string Name { get; private set; } - public string Key { get; private set; } - public KeymapInputSource Source { get; private set; } - public bool Button { get; private set; } - public bool Continous { get; private set; } - public bool Cursor { get; private set; } - - public KeymapInput(KeymapInputSource source, string name, string key) - : this(source, name, key, true, false, false) - { - - } - - public KeymapInput(KeymapInputSource source, string name, string key, bool button, bool continous, bool cursor) - { - this.Source = source; - this.Name = name; - this.Key = key; - this.Button = button; - this.Continous = continous; - this.Cursor = cursor; - } - - public bool canHandle(KeymapOutput output) - { - return ((this.Button == output.Button || this.Continous == output.Continous) && this.Cursor == output.Cursor) || output.Type == KeymapOutputType.DISABLE; - } - } - - - public enum KeymapOutputType - { - ALL, //Only used in search - TOUCH, - MOUSE, - XINPUT, - KEYBOARD, - DISABLE - } - public class KeymapOutput - { - public string Name { get; private set; } - public string Key { get; private set; } - public KeymapOutputType Type { get; private set; } - public bool Button { get; private set; } - public bool Continous { get; private set; } - public bool Cursor { get; private set; } - public bool Stackable { get; private set; } - - public KeymapOutput(KeymapOutputType type, string name, string key) - : this(type, name, key, true, false, false, true) - { - - } - - public KeymapOutput(KeymapOutputType type, string name, string key, bool button, bool continous, bool cursor, bool stackable) - { - this.Type = type; - this.Name = name; - this.Key = key; - this.Button = button; - this.Continous = continous; - this.Cursor = cursor; - } - - public bool canStack(KeymapOutput other) - { - return this.Stackable && other.Stackable; - } - } - - - public class KeymapOutputComparer : IComparer - { - StringComparer comparer = StringComparer.CurrentCulture; - - public int Compare(KeymapOutput x, KeymapOutput y) - { - if (x.Type - y.Type == 0) - { - return comparer.Compare(x.Name, y.Name); - } - return x.Type - y.Type; - } - } -} +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WiiTUIO.Properties; + +namespace WiiTUIO +{ + class KeymapDatabase + { + public string DisableKey { get; private set; } + + private List allInputs; + private List allOutputs; + + private string DEFAULT_JSON_FILENAME = "default.json"; + + private static KeymapDatabase currentInstance; + public static KeymapDatabase Current + { + get + { + if (currentInstance == null) + { + currentInstance = new KeymapDatabase(); + } + return currentInstance; + } + } + + private KeymapDatabase() + { + this.DisableKey = "disable"; + + allInputs = new List(); + allInputs.Add(new KeymapInput(KeymapInputSource.IR, "Pointer", "Pointer", false, false, true)); + allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "A", "A")); + allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "B", "B")); + allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "Home", "Home")); + allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "Left", "Left")); + allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "Right", "Right")); + allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "Up", "Up")); + allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "Down", "Down")); + allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "Plus", "Plus")); + allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "Minus", "Minus")); + allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "One", "One")); + allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "Two", "Two")); + allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "Tilt X-", "AccelX-", true, true, false)); + allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "Tilt X+", "AccelX+", true, true, false)); + allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "Tilt Y-", "AccelY-", true, true, false)); + allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "Tilt Y+", "AccelY+", true, true, false)); + allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "Tilt Z-", "AccelZ-", true, true, false)); + allInputs.Add(new KeymapInput(KeymapInputSource.WIIMOTE, "Tilt Z+", "AccelZ+", true, true, false)); + + allInputs.Add(new KeymapInput(KeymapInputSource.NUNCHUK, "C", "Nunchuk.C")); + allInputs.Add(new KeymapInput(KeymapInputSource.NUNCHUK, "Z", "Nunchuk.Z")); + allInputs.Add(new KeymapInput(KeymapInputSource.NUNCHUK, "Stick Up", "Nunchuk.StickUp", true, true, false)); + allInputs.Add(new KeymapInput(KeymapInputSource.NUNCHUK, "Stick Down", "Nunchuk.StickDown", true, true, false)); + allInputs.Add(new KeymapInput(KeymapInputSource.NUNCHUK, "Stick Left", "Nunchuk.StickLeft", true, true, false)); + allInputs.Add(new KeymapInput(KeymapInputSource.NUNCHUK, "Stick Right", "Nunchuk.StickRight", true, true, false)); + allInputs.Add(new KeymapInput(KeymapInputSource.NUNCHUK, "Tilt X-", "Nunchuk.AccelX-", true, true, false)); + allInputs.Add(new KeymapInput(KeymapInputSource.NUNCHUK, "Tilt X+", "Nunchuk.AccelX+", true, true, false)); + allInputs.Add(new KeymapInput(KeymapInputSource.NUNCHUK, "Tilt Y-", "Nunchuk.AccelY-", true, true, false)); + allInputs.Add(new KeymapInput(KeymapInputSource.NUNCHUK, "Tilt Y+", "Nunchuk.AccelY+", true, true, false)); + allInputs.Add(new KeymapInput(KeymapInputSource.NUNCHUK, "Tilt Z-", "Nunchuk.AccelZ-", true, true, false)); + allInputs.Add(new KeymapInput(KeymapInputSource.NUNCHUK, "Tilt Z+", "Nunchuk.AccelZ+", true, true, false)); + + + allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Left", "Classic.Left")); + allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Right", "Classic.Right")); + allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Up", "Classic.Up")); + allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Down", "Classic.Down")); + + allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Left Stick Left", "Classic.StickLLeft", true, true, false)); + allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Left Stick Right", "Classic.StickLRight", true, true, false)); + allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Left Stick Up", "Classic.StickLUp", true, true, false)); + allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Left Stick Down", "Classic.StickLDown", true, true, false)); + allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Right Stick Left", "Classic.StickRLeft", true, true, false)); + allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Right Stick Right", "Classic.StickRRight", true, true, false)); + allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Right Stick Up", "Classic.StickRUp", true, true, false)); + allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Right Stick Down", "Classic.StickRDown", true, true, false)); + + allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Minus", "Classic.Minus")); + allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Plus", "Classic.Plus")); + allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Home", "Classic.Home")); + allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Y", "Classic.Y")); + allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "X", "Classic.X")); + allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "A", "Classic.A")); + allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "B", "Classic.B")); + allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Left Trigger", "Classic.TriggerL", false, true, false)); + allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Right Trigger", "Classic.TriggerR", false, true, false)); + allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Left Trigger Push", "Classic.L")); + allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "Right Trigger Push", "Classic.R")); + allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "ZL", "Classic.ZL")); + allInputs.Add(new KeymapInput(KeymapInputSource.CLASSIC, "ZR", "Classic.ZR")); + + allOutputs = new List(); + allOutputs.Add(new KeymapOutput(KeymapOutputType.TOUCH, "Touch Cursor", "touch", false, false, true, false)); + allOutputs.Add(new KeymapOutput(KeymapOutputType.TOUCH, "Touch Cursor Left", "touchx-", false, true, false, false)); + allOutputs.Add(new KeymapOutput(KeymapOutputType.TOUCH, "Touch Cursor Right", "touchx+", false, true, false, false)); + allOutputs.Add(new KeymapOutput(KeymapOutputType.TOUCH, "Touch Cursor Up", "touchy+", false, true, false, false)); + allOutputs.Add(new KeymapOutput(KeymapOutputType.TOUCH, "Touch Cursor Down", "touchy-", false, true, false, false)); + allOutputs.Add(new KeymapOutput(KeymapOutputType.TOUCH, "Touch Main", "touchmaster")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.TOUCH, "Touch Slave", "touchslave")); + + allOutputs.Add(new KeymapOutput(KeymapOutputType.MOUSE, "Mouse Cursor", "mouse", false, false, true, false)); + allOutputs.Add(new KeymapOutput(KeymapOutputType.MOUSE, "Mouse Camera/View", "fpsmouse", false, false, true, false)); + allOutputs.Add(new KeymapOutput(KeymapOutputType.MOUSE, "Mouse Fly/Fps", "flyfpsmouse", false, false, true, false)); + allOutputs.Add(new KeymapOutput(KeymapOutputType.MOUSE, "Mouse Left", "mouseleft")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.MOUSE, "Mouse Right", "mouseright")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.MOUSE, "Mouse Move Right", "mousex+", true, true, false, false)); + allOutputs.Add(new KeymapOutput(KeymapOutputType.MOUSE, "Mouse Move Up", "mousey+", true, true, false, false)); + allOutputs.Add(new KeymapOutput(KeymapOutputType.MOUSE, "Mouse Move Left", "mousex-", true, true, false, false)); + allOutputs.Add(new KeymapOutput(KeymapOutputType.MOUSE, "Mouse Move Down", "mousey-", true, true, false, false)); + //allOutputs.Add(new KeymapOutput(KeymapOutputType.MOUSE, "Mouse Middle", "mbutton")); + //allOutputs.Add(new KeymapOutput(KeymapOutputType.MOUSE, "Mouse Extra 1", "xbutton1")); + //allOutputs.Add(new KeymapOutput(KeymapOutputType.MOUSE, "Mouse Extra 2", "xbutton2")); + + + + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Tab", "tab")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Backspace", "back")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Return", "return")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Shift", "shift")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Control", "control")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Alt", "menu")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Pause", "pause")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Caps Lock", "capital")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Escape", "escape")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Spacebar", "space")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Page Up", "prior")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Page Down", "next")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "End", "end")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Home", "home")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Arrow Left", "left")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Arrow Up", "up")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Arrow Right", "right")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Arrow Down", "down")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Print Screen", "snapshot")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Insert", "insert")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Delete", "delete")); + + + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "0", "vk_0")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "1", "vk_1")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "2", "vk_2")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "3", "vk_3")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "4", "vk_4")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "5", "vk_5")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "6", "vk_6")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "7", "vk_7")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "8", "vk_8")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "9", "vk_9")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "A", "vk_a")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "B", "vk_b")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "C", "vk_c")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "D", "vk_d")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "E", "vk_e")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "F", "vk_f")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "G", "vk_g")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "H", "vk_h")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "I", "vk_i")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "J", "vk_j")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "K", "vk_k")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "L", "vk_l")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "M", "vk_m")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "N", "vk_n")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "O", "vk_o")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "P", "vk_p")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Q", "vk_q")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "R", "vk_r")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "S", "vk_s")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "T", "vk_t")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "U", "vk_u")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "V", "vk_v")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "W", "vk_w")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "X", "vk_x")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Y", "vk_y")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Z", "vk_z")); + + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Period .", "oem_period")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Comma ,", "oem_comma")); + + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Left Win", "lwin")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Right Win", "rwin")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Apps / Menu", "apps")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Numpad 0", "numpad0")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Numpad 1", "numpad1")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Numpad 2", "numpad2")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Numpad 3", "numpad3")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Numpad 4", "numpad4")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Numpad 5", "numpad5")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Numpad 6", "numpad6")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Numpad 7", "numpad7")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Numpad 8", "numpad8")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Numpad 9", "numpad9")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Multiply *", "multiply")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Add +", "add")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Subtract -", "subtract")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Decimal ,", "decimal")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Divide /", "divide")); + + + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "F1", "f1")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "F2", "f2")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "F3", "f3")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "F4", "f4")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "F5", "f5")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "F6", "f6")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "F7", "f7")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "F8", "f8")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "F9", "f9")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "F10", "f10")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "F11", "f11")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "F12", "f12")); + + + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Numlock", "numlock")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Left Shift", "lshift")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Right Shift", "rshift")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Left Control", "lcontrol")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Right Control", "rcontrol")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Left Alt", "lmenu")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Right Alt", "rmenu")); + + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Browser Back", "browser_back")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Browser Forward", "browser_forward")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Browser Refresh", "browser_refresh")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Browser Stop", "browser_stop")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Browser Search", "browser_search")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Browser Favorites", "browser_favorites")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Browser Home", "browser_home")); + + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Volume Mute", "volume_mute")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Volume Up", "volume_up")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Volume Down", "volume_down")); + + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Next Track", "media_next_track")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Previous Track", "media_prev_track")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Stop Media", "media_stop")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Play/Pause Media", "media_play_pause")); + + allOutputs.Add(new KeymapOutput(KeymapOutputType.KEYBOARD, "Zoom", "zoom")); + + allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "A", "360.a")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "B", "360.b")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "X", "360.x")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Y", "360.y")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Left", "360.left")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Right", "360.right")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Up", "360.up")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Down", "360.down")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Back", "360.back")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Start", "360.start")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Guide", "360.guide")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Left Stick Press", "360.stickpressl")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Right Stick Press", "360.stickpressr")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Left Stick", "360.stickl", false, false, true, false)); + allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Left Stick Up", "360.sticklup", true, true, false, false)); + allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Left Stick Down", "360.stickldown", true, true, false, false)); + allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Left Stick Left", "360.sticklleft", true, true, false, false)); + allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Left Stick Right", "360.sticklright", true, true, false, false)); + allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Right Stick", "360.stickr", false, false, true, false)); + allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Right Stick Up", "360.stickrup", true, true, false, false)); + allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Right Stick Down", "360.stickrdown", true, true, false, false)); + allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Right Stick Left", "360.stickrleft", true, true, false, false)); + allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Right Stick Right", "360.stickrright", true, true, false, false)); + allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Left Trigger", "360.triggerl", true, true, false, false)); + allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Right Trigger", "360.triggerr", true, true, false, false)); + allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Left Bumper", "360.bumperl")); + allOutputs.Add(new KeymapOutput(KeymapOutputType.XINPUT, "Right Bumper", "360.bumperr")); + + allOutputs.Add(new KeymapOutput(KeymapOutputType.DISABLE, "Disable", this.DisableKey)); + } + + + public KeymapSettings getKeymapSettings() + { + return new KeymapSettings(Settings.Default.keymaps_config); + } + + public List getAllKeymaps() + { + List list = new List(); + string[] files = Directory.GetFiles(Settings.Default.keymaps_path, "*.json"); + string defaultKeymapFilename = this.getKeymapSettings().getDefaultKeymap(); + + Keymap defaultKeymap = new Keymap(null, defaultKeymapFilename); + list.Add(defaultKeymap); + + foreach (string filepath in files) + { + string filename = Path.GetFileName(filepath); + if (filename != Settings.Default.keymaps_config && filename != defaultKeymapFilename) + { + list.Add(new Keymap(defaultKeymap, filename)); + } + } + return list; + } + + public Keymap getKeymap(string filename) + { + List list = this.getAllKeymaps(); + + foreach (Keymap keymap in list) + { + if (keymap.Filename == filename) + { + return keymap; + } + } + return null; + } + + public Keymap getDefaultKeymap() + { + List list = this.getAllKeymaps(); + KeymapSettings settings = this.getKeymapSettings(); + + foreach (Keymap keymap in list) + { + if (keymap.Filename == settings.getDefaultKeymap()) + { + return keymap; + } + } + return null; + } + + public List getAvailableInputs() + { + return allInputs; + } + + public List getAvailableInputs(KeymapInputSource source) + { + List list = new List(); + foreach (KeymapInput input in allInputs) + { + if (input.Source == source) + { + list.Add(input); + } + } + return list; + } + + public List getAvailableOutputs() + { + return allOutputs; + } + + public List getAvailableOutputs(KeymapOutputType type) + { + if (type == KeymapOutputType.ALL) + { + return allOutputs; + } + List list = new List(); + foreach (KeymapOutput output in allOutputs) + { + if (output.Type == type) + { + list.Add(output); + } + } + return list; + } + + public KeymapInput getInput(string key) + { + List list = this.allInputs; + foreach (KeymapInput input in list) + { + if (input.Key.ToLower() == key.ToLower()) + { + return input; + } + } + return null; + } + + public KeymapOutput getOutput(string key) + { + List list = this.allOutputs; + foreach (KeymapOutput output in list) + { + if (output.Key.ToLower() == key.ToLower()) + { + return output; + } + } + return null; + } + + public KeymapOutput getDisableOutput() + { + return this.getAvailableOutputs(KeymapOutputType.DISABLE).First(); + } + + public bool deleteKeymap(Keymap keymap) + { + if (keymap.Filename == this.getKeymapSettings().getDefaultKeymap()) + { + return false; + } + this.getKeymapSettings().removeFromLayoutChooser(keymap); + this.getKeymapSettings().removeFromApplicationSearch(keymap); + File.Delete(Settings.Default.keymaps_path + keymap.Filename); + return true; + } + + public Keymap createNewKeymap() + { + List list = new List(); + string[] files = Directory.GetFiles(Settings.Default.keymaps_path, "*.json"); + + string suggestedFilename = "z_custom.json"; + + bool recheck = false; + + int iterations = 0; + + do + { + recheck = false; + foreach (string filepath in files) + { + string filename = Path.GetFileName(filepath); + if (suggestedFilename == filename) + { + suggestedFilename = "z_custom_" + (++iterations) + ".json"; + recheck = true; + } + } + } while (recheck); + + return new Keymap(this.getDefaultKeymap(), suggestedFilename); + } + + + + public void CreateDefaultFiles() + { + this.createDefaultApplicationsJSON(); + this.createDefaultKeymapJSON(); + } + + private static void MergeJSON(JObject receiver, JObject donor) + { + foreach (var property in donor) + { + JObject receiverValue = receiver[property.Key] as JObject; + JObject donorValue = property.Value as JObject; + if (receiverValue != null && donorValue != null) + MergeJSON(receiverValue, donorValue); + else + receiver[property.Key] = property.Value; + } + } + + private JObject createDefaultApplicationsJSON() + { + JArray layouts = new JArray(); + layouts.Add(new JObject( + new JProperty("Name", "Default"), + new JProperty("Keymap", DEFAULT_JSON_FILENAME) + )); + + JArray applications = new JArray(); + + JObject applicationList = + new JObject( + new JProperty("LayoutChooser", layouts), + new JProperty("Applications", applications), + new JProperty("Default", DEFAULT_JSON_FILENAME) + ); + + JObject union = applicationList; + + if (File.Exists(Settings.Default.keymaps_path + Settings.Default.keymaps_config)) + { + StreamReader reader = File.OpenText(Settings.Default.keymaps_path + Settings.Default.keymaps_config); + try + { + JObject existingConfig = (JObject)JToken.ReadFrom(new JsonTextReader(reader)); + reader.Close(); + + MergeJSON(union, existingConfig); + } + catch (Exception e) + { + throw new Exception(Settings.Default.keymaps_path + Settings.Default.keymaps_config + " is not valid JSON"); + } + } + + File.WriteAllText(Settings.Default.keymaps_path + Settings.Default.keymaps_config, union.ToString()); + return union; + } + + private JObject createDefaultKeymapJSON() + { + JObject buttons = new JObject(); + + buttons.Add(new JProperty("Pointer", "Touch")); + + buttons.Add(new JProperty("A", "TouchMaster")); + + buttons.Add(new JProperty("B", "TouchSlave")); + + buttons.Add(new JProperty("Home", "LWin")); + + buttons.Add(new JProperty("Left", "Left")); + buttons.Add(new JProperty("Right", "Right")); + buttons.Add(new JProperty("Up", "Up")); + buttons.Add(new JProperty("Down", "Down")); + + buttons.Add(new JProperty("Plus", "Volume_Up")); + + buttons.Add(new JProperty("Minus", "Volume_Down")); + + JArray buttonOne = new JArray(); + buttonOne.Add(new JValue("LWin")); + buttonOne.Add(new JValue("VK_C")); + buttons.Add(new JProperty("One", buttonOne)); + + JArray buttonTwo = new JArray(); + buttonTwo.Add(new JValue("LWin")); + buttonTwo.Add(new JValue("Tab")); + buttons.Add(new JProperty("Two", buttonTwo)); + + buttons.Add(new JProperty("AccelX+", "disable")); + buttons.Add(new JProperty("AccelX-", "disable")); + buttons.Add(new JProperty("AccelY+", "disable")); + buttons.Add(new JProperty("AccelY-", "disable")); + buttons.Add(new JProperty("AccelZ+", "disable")); + buttons.Add(new JProperty("AccelZ-", "disable")); + + buttons.Add(new JProperty("Nunchuk.StickUp", "360.StickLUp")); + buttons.Add(new JProperty("Nunchuk.StickDown", "360.StickLDown")); + buttons.Add(new JProperty("Nunchuk.StickLeft", "360.StickLLeft")); + buttons.Add(new JProperty("Nunchuk.StickRight", "360.StickLRight")); + buttons.Add(new JProperty("Nunchuk.C", "360.TriggerL")); + buttons.Add(new JProperty("Nunchuk.Z", "360.TriggerR")); + + buttons.Add(new JProperty("Classic.Left", "360.Left")); + buttons.Add(new JProperty("Classic.Right", "360.Right")); + buttons.Add(new JProperty("Classic.Up", "360.Up")); + buttons.Add(new JProperty("Classic.Down", "360.Down")); + buttons.Add(new JProperty("Classic.StickLUp", "360.StickLUp")); + buttons.Add(new JProperty("Classic.StickLDown", "360.StickLDown")); + buttons.Add(new JProperty("Classic.StickLLeft", "360.StickLLeft")); + buttons.Add(new JProperty("Classic.StickLRight", "360.StickLRight")); + buttons.Add(new JProperty("Classic.StickRUp", "360.StickRUp")); + buttons.Add(new JProperty("Classic.StickRDown", "360.StickRDown")); + buttons.Add(new JProperty("Classic.StickRLeft", "360.StickRLeft")); + buttons.Add(new JProperty("Classic.StickRRight", "360.StickRRight")); + buttons.Add(new JProperty("Classic.Minus", "360.Back")); + buttons.Add(new JProperty("Classic.Plus", "360.Start")); + buttons.Add(new JProperty("Classic.Home", "360.Guide")); + buttons.Add(new JProperty("Classic.Y", "360.Y")); + buttons.Add(new JProperty("Classic.X", "360.X")); + buttons.Add(new JProperty("Classic.A", "360.A")); + buttons.Add(new JProperty("Classic.B", "360.B")); + buttons.Add(new JProperty("Classic.TriggerL", "360.TriggerL")); + buttons.Add(new JProperty("Classic.TriggerR", "360.TriggerR")); + buttons.Add(new JProperty("Classic.L", "360.L")); + buttons.Add(new JProperty("Classic.R", "360.R")); + buttons.Add(new JProperty("Classic.ZL", "360.BumperL")); + buttons.Add(new JProperty("Classic.ZR", "360.BumperR")); + + JObject union = new JObject(); + + union.Add(new JProperty("Title", "Default")); + + union.Add(new JProperty("All", buttons)); + + if (File.Exists(Settings.Default.keymaps_path + Settings.Default.keymaps_config)) + { + StreamReader reader = File.OpenText(Settings.Default.keymaps_path + DEFAULT_JSON_FILENAME); + try + { + JObject existingConfig = (JObject)JToken.ReadFrom(new JsonTextReader(reader)); + reader.Close(); + + MergeJSON(union, existingConfig); + } + catch (Exception e) + { + throw new Exception(Settings.Default.keymaps_path + DEFAULT_JSON_FILENAME + " is not valid JSON"); + } + } + File.WriteAllText(Settings.Default.keymaps_path + DEFAULT_JSON_FILENAME, union.ToString()); + return union; + } + } + + public enum KeymapInputSource + { + IR, + WIIMOTE, + NUNCHUK, + CLASSIC + } + + public class KeymapInput + { + public string Name { get; private set; } + public string Key { get; private set; } + public KeymapInputSource Source { get; private set; } + public bool Button { get; private set; } + public bool Continous { get; private set; } + public bool Cursor { get; private set; } + + public KeymapInput(KeymapInputSource source, string name, string key) + : this(source, name, key, true, false, false) + { + + } + + public KeymapInput(KeymapInputSource source, string name, string key, bool button, bool continous, bool cursor) + { + this.Source = source; + this.Name = name; + this.Key = key; + this.Button = button; + this.Continous = continous; + this.Cursor = cursor; + } + + public bool canHandle(KeymapOutput output) + { + return ((this.Button == output.Button || this.Continous == output.Continous) && this.Cursor == output.Cursor) || output.Type == KeymapOutputType.DISABLE; + } + } + + + public enum KeymapOutputType + { + ALL, //Only used in search + TOUCH, + MOUSE, + XINPUT, + KEYBOARD, + DISABLE + } + public class KeymapOutput + { + public string Name { get; private set; } + public string Key { get; private set; } + public KeymapOutputType Type { get; private set; } + public bool Button { get; private set; } + public bool Continous { get; private set; } + public bool Cursor { get; private set; } + public bool Stackable { get; private set; } + + public KeymapOutput(KeymapOutputType type, string name, string key) + : this(type, name, key, true, false, false, true) + { + + } + + public KeymapOutput(KeymapOutputType type, string name, string key, bool button, bool continous, bool cursor, bool stackable) + { + this.Type = type; + this.Name = name; + this.Key = key; + this.Button = button; + this.Continous = continous; + this.Cursor = cursor; + } + + public bool canStack(KeymapOutput other) + { + return this.Stackable && other.Stackable; + } + } + + + public class KeymapOutputComparer : IComparer + { + StringComparer comparer = StringComparer.CurrentCulture; + + public int Compare(KeymapOutput x, KeymapOutput y) + { + if (x.Type - y.Type == 0) + { + return comparer.Compare(x.Name, y.Name); + } + return x.Type - y.Type; + } + } +} diff --git a/WiiTUIO/Output/Handlers/MouseHandler.cs b/WiiTUIO/Output/Handlers/MouseHandler.cs index 7aa5f8be..7fb027fa 100644 --- a/WiiTUIO/Output/Handlers/MouseHandler.cs +++ b/WiiTUIO/Output/Handlers/MouseHandler.cs @@ -1,177 +1,664 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Forms; -using WiiTUIO.Properties; -using WiiTUIO.Provider; -using WindowsInput; -using WindowsInput.Native; - -namespace WiiTUIO.Output.Handlers -{ - public class MouseHandler : IButtonHandler, IStickHandler, ICursorHandler - { - private InputSimulator inputSimulator; - - private bool mouseLeftDown = false; - private bool mouseRightDown = false; - - private CursorPositionHelper cursorPositionHelper; - - public MouseHandler() - { - this.inputSimulator = new InputSimulator(); - cursorPositionHelper = new CursorPositionHelper(); - } - - public bool reset() - { - if (mouseLeftDown) - { - setButtonUp("mouseleft"); - } - if (mouseRightDown) - { - setButtonUp("mouseright"); - } - return true; - } - - public bool setButtonDown(string key) - { - if (Enum.IsDefined(typeof(MouseCode), key.ToUpper())) - { - MouseCode mouseCode = (MouseCode)Enum.Parse(typeof(MouseCode), key, true); - switch (mouseCode) - { - case MouseCode.MOUSELEFT: - this.inputSimulator.Mouse.LeftButtonDown(); - mouseLeftDown = true; - break; - case MouseCode.MOUSERIGHT: - this.inputSimulator.Mouse.RightButtonDown(); - mouseRightDown = true; - break; - default: - return false; - } - return true; - } - return false; - } - - public bool setButtonUp(string key) - { - if (Enum.IsDefined(typeof(MouseCode), key.ToUpper())) - { - MouseCode mouseCode = (MouseCode)Enum.Parse(typeof(MouseCode), key, true); - switch (mouseCode) - { - case MouseCode.MOUSELEFT: - this.inputSimulator.Mouse.LeftButtonUp(); - mouseLeftDown = false; - break; - case MouseCode.MOUSERIGHT: - this.inputSimulator.Mouse.RightButtonUp(); - mouseLeftDown = false; - break; - default: - return false; - } - return true; - } - return false; - } - - public bool setPosition(string key, CursorPos cursorPos) - { - key = key.ToLower(); - if (key.Equals("mouse")) - { - if (!cursorPos.OutOfReach) - { - Point smoothedPos = cursorPositionHelper.getRelativePosition(new Point(cursorPos.X, cursorPos.Y)); - this.inputSimulator.Mouse.MoveMouseToPositionOnVirtualDesktop((65535 * smoothedPos.X), (65535 * smoothedPos.Y)); - return true; - } - } - - if (key.Equals("fpsmouse")) - { - Point smoothedPos = cursorPositionHelper.getSmoothedPosition(new Point(cursorPos.RelativeX, cursorPos.RelativeY)); - - /* - * TODO: Consider sensor bar position? - if (Settings.Default.pointer_sensorBarPos == "top") - { - smoothedPos.Y = smoothedPos.Y - Settings.Default.pointer_sensorBarPosCompensation; - } - else if (Settings.Default.pointer_sensorBarPos == "bottom") - { - smoothedPos.Y = smoothedPos.Y + Settings.Default.pointer_sensorBarPosCompensation; - } - */ - double deadzone = Settings.Default.fpsmouse_deadzone; // TODO: Move to settings - double shiftX = Math.Abs(smoothedPos.X - 0.5) > deadzone ? smoothedPos.X - 0.5 : 0; - double shiftY = Math.Abs(smoothedPos.Y - 0.5) > deadzone ? smoothedPos.Y - 0.5 : 0; - - this.inputSimulator.Mouse.MoveMouseBy((int)(Settings.Default.fpsmouse_speed * shiftX), (int)(Settings.Default.fpsmouse_speed * shiftY)); - - return true; - } - return false; - } - - public bool setValue(string key, double value) - { - key = key.ToLower(); - switch (key) - { - case "mousey+": - this.inputSimulator.Mouse.MoveMouseBy(0, (int)(-30 * value + 0.5)); - break; - case "mousey-": - this.inputSimulator.Mouse.MoveMouseBy(0, (int)(30 * value + 0.5)); - break; - case "mousex+": - this.inputSimulator.Mouse.MoveMouseBy((int)(30 * value + 0.5), 0); - break; - case "mousex-": - this.inputSimulator.Mouse.MoveMouseBy((int)(-30 * value + 0.5), 0); - break; - default: - return false; - } - return true; - } - - public bool connect() - { - return true; - } - - public bool disconnect() - { - return true; - } - - public bool startUpdate() - { - return true; - } - - public bool endUpdate() - { - return true; - } - } - - public enum MouseCode - { - MOUSELEFT, - MOUSERIGHT - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Forms; +using WiiTUIO.Properties; +using WiiTUIO.Provider; +using WindowsInput; +using WindowsInput.Native; + +using System.IO; + +namespace WiiTUIO.Output.Handlers +{ + public class MouseHandler : IButtonHandler, IStickHandler, ICursorHandler + { + private InputSimulator inputSimulator; + + private bool mouseLeftDown = false; + private bool mouseRightDown = false; + + private CursorPositionHelper cursorPositionHelper; + + // TODO: BEGIN; add a user friendly control gear panel in the UI, setting -> control cobfiguration like the gear in Tilt-x, Tilt-y box, parameters min, max values and steps are given below + + private double mouseMainSensX = Settings.Default.flyfps_main_sensitivity; //range 0-10, step 0.01, default = 0.25, Sensitivity X and Y of mouse vector. When main_sensitivity_y=0 then main_sensitivity_y calculated from main_sensitivity by actual screen aspect ratio. You can draw the mosue vector with pointer. This drawed vector move the mouse. This work independent from acceleration. + private double mouseMainSensY = Settings.Default.flyfps_main_sensitivity_y; //range 0-10, step 0.01, default = 0 = auto from screen width/height aspect ratio, Sensitivity Y of mouse vector. When main_sensitivity_y=0 then main_sensitivity_y calculated from main_sensitivity. You can draw the mosue vector with pointer. This drawed vector move the mouse.This work independent from acceleration. + private double mouseMainAccX = Settings.Default.flyfps_main_acceleration; //range 0+, step 0.1, default = 40, multiply the mouse speed depending from the current mouse speed. Acceleration X and Y of mouse vector. When vector_acceleration_y=0 then vector_acceleration_y calculated from vector_acceleration by actual screen aspect ratio. You can draw the mosue vector with pointer. This drawed vector move the mouse. This work independent from sensitivity. + private double mouseMainAccY = Settings.Default.flyfps_main_acceleration_y; //range 0+, step 0.1, default = 0 = auto from screen width/height aspect ratio, multiply the mouse speed depending from the current mouse speed. Acceleration Y of mouse vector. When vector_acceleration_y=0 then vector_acceleration_y calculated from vector_acceleration by actual screen aspect ratio. You can draw the mosue vector with pointer. This drawed vector move the mouse. This work independent from sensitivity. + private double mouseMainAccThreshold = Settings.Default.flyfps_main_acceleration_threshold; //range 0-100, step 0.01, default = 40, When your hand speed above flyfps_main_acceleration_threshold the mouse acceleration = flyfps_main_acceleration. When your hand speed slower then flyfps_main_acceleration_threshold the mouse acceleration ranged from 0 to flyfps_main_acceleration. When you lower this value, mouse speed accelerated faster to the flyfps_main_acceleration. + private double mouseMainAccFiner = Settings.Default.flyfps_main_acceleration_finer; //range 0-100, step 0.1, default = 10, This value determine how fast react the mouse speed to your hand. Bigger value mean react slower. Lower value mean react faster. The remote is very sensitive to acceleretaion so must extend it. + private double mouseMainDeccStart = Settings.Default.flyfps_main_decceleration_low; //range 0-100, step 0.1, default = 5. When your hand speed is slow, this ranged to flyfps_main_decceleration_end when you move faster. This value decrease the pointer drawed mouse mover vector in each frame. When you not slow down the mouse vector, it turns for continously. Bigger value give more decceleration. This work independently from acceleration. + private double mouseMainDeccEnd = Settings.Default.flyfps_main_decceleration_high; //range 0-100, step 0.1, default = 10.When your hand speed is fast, this ranged to flyfps_main_decceleration_start when you move slower. This value decrease the pointer drawed mouse mover vector in each frame. When you not slow down the mouse vector, it turns for continously. Bigger value give more decceleration. when flyfps_main_decceleration_end < flyfps_main_decceleration_start than your faster hand speed not break the mouse vector. This work independently from acceleration. + private double mouseMainDeccThreshold = Settings.Default.flyfps_main_decceleration_threshold; //range 0-100, step 0.01, default = 40, When your hand speed above flyfps_main_decceleration_threshold the mouse deceleration = flyfps_main_decceleration_end. When your hand speed slower then flyfps_main_decceleration_threshold the mouse deceleration ranged from flyfps_main_decceleration_start to flyfps_main_decceleration_end. When you lower this value, mouse speed reach faster flyfps_main_decceleration_end. + private double returnBoundAccelerator = Settings.Default.flyfps_return_bound_acceleration; //range 0-100, step 0,1, default = 5, When the pointer return from out of bounds, the speed of mouse start from 0 and increased with this acceleration. When lower the value, you have more time for recenter your pointer to the sensor bar after you leave the sensed zone. + private double outOfBoundsDecceleration = Settings.Default.flyfps_out_bound_decceleration; //range 0-100, step 0.1, default = 10, when leave the sensorbar bounds, the mouse speed deccelerated with this value. When you set it 0 then the pointer leave the sensorbar the mouse turn continously for the desired direction. + private bool mouseFineLeftEnable = Settings.Default.flyfps_left_button_fine; // + private double mouseFineSensX = Settings.Default.flyfps_fine_sensitivity; //range 0-10, step 0.1, default = 0.25, Fine Sensitivity X and Y of mouse, when you press the right or left mouse button you switch to fine aiming sensitivity mode. When set it 0 it turns off. The fine mouse flyfps_fine_sensitivity_y calculatod from flyfps_fine_sensitivity by actual screen aspect ratio. + private double mouseFineSensY = Settings.Default.flyfps_fine_sensitivity_y; //range 0-10, step: 0.1, default: 0 = auto from screen width/height aspect ratio, Fine Sensitivity Y of mouse, when you press the right or left mouse button you switch to fine aiming sensitivity mode. When set it 0 then the fine mouse flyfps_fine_sensitivity_y calculatod from flyfps_fine_sensitivity by actual screen aspect ratio. + private double mouseFineAccX = Settings.Default.flyfps_fine_acceleration; //range 0-100, step 0.1, default = 10, Fine acceleration X and Y of mouse, when you press the right or left mouse button you switch to fine aiming sensitivity mode. When set it 0 it turns off. The fine mouse flyfps_fine_acceleration_y calculatod from flyfps_fine_acceleration. + private double mouseFineAccY = Settings.Default.flyfps_fine_acceleration_y; //range 0-100, step: 0.1, default: 0 = auto from screen width/height aspect ratio, Fine acceleration Y of mouse, when you press the right mouse button you switch to fine aiming sensitivity mode the pointer. When set it 0 then the fine mouse flyfps_fine_acceleration_y calculatod from flyfps_fine_acceleration. + private double mouseFineDecc = Settings.Default.flyfps_fine_decceleration; //range 0-10, step 0.1, default = 10, Fine decceleration X and Y of mouse, when you press the right or left mouse button you switch to fine aiming sensitivity mode. When set it 0 it turns off the mouse accelerating from the current position. + private double mouseForwardControlX = Settings.Default.flyfps_mouse_forward; //range 0-1000, step 1, default = 0 add fixed X direction jump to the mouse, when you shake your hand to the desired direction with defined acceleration. When your acceleration X reach the specified acceleretaion the mouse jump with fixed value. + private double mouseForwardControlY = Settings.Default.flyfps_mouse_forward_y; //range 0-1000, step 1, default = 0 add fixed Y direction jump to the mouse. when you shake your hand to the desired direction with defined acceleration. When set to 0 its equal to flyfps_mouse_forward. When your acceleration Y reach the specified acceleretaion the mouse jump with fixed value. + private double mouseForwardTurnOnThreshold = Settings.Default.flyfps_mouse_forward_turn_on_threshold; //range 0-100, default = 25, step 1, below this mousespeed limit mouse forward not take effect. When your hand acceleration above this value it add fix mouse move to the desired direction. + private double mouseFoewardDecceleration = Settings.Default.flyfps_mouse_forward_decceleration; //range 0-100, default = 5, when mouse jump with fixed mouse forward its not stop instantly, slowed down with this decceleration. + private double extraTurnSensX = Settings.Default.flyfps_extra_turn_sensitivity; //range 0-100, default = 0 = off, step 0.1, set extra turn sensitivity X and Y. During travelled distance with pointer the speed increased to this sensitivity. When flyfps_extra_turn_sensitivity_y = 0 then flyfps_extra_turn_sensitivity_y calculated from this value by actual screen aspect ratio. + private double extraTurnSensY = Settings.Default.flyfps_extra_turn_sensitivity_y; //range 0+, default = 0 = auto from screen width/height aspect ratio, step 0.1, set extra turn sensitivity Y. During travelled distance with pointer the speed increased to this sensitivity. When flyfps_extra_turn_sensitivity_y = 0 then flyfps_extra_turn_sensitivity_y calculated from this value. + private Vector extraTurnDeadZone = new Vector(Settings.Default.flyfps_extra_turn_deadzone, Settings.Default.flyfps_extra_turn_deadzone); // range 0 - 100, default = 20. In this zone the extra turn speed not take affect. When you move the opposite direction the pointer its start from beginning the travelling deadzone. For proper work increase flyfps_mouse_smooth_buffer for your hand. + private Vector extraTurnEaseIn = new Vector(Settings.Default.flyfps_extra_turn_easein, Settings.Default.flyfps_extra_turn_easein); // range 0 - 100, default = 40. After travelling deadzone, the speed begin increasing to the extra sensitivity during this easein distance. + private double mouseFinerLow = Settings.Default.flyfps_mouse_finer_low; // range 0 - 100, default = 85, step 0.1, this fining your mouse moves on low hand speed. Decreasing the distance of two mouse steps. The result is very fine and smooth mouse move. When increaseing pointer_FPS the move is faster you can add more fining. I prefer pointer_FPS=200,in the game lock fps to 60FPS. When you sync your framerate in touchmote(ie:60-120-180-200FPS) and in the game(ie:30-60FPS+) that give the best result. Just try it :) + private double mouseFinerHigh = Settings.Default.flyfps_mouse_finer_high; // range 0 - 100, default = 80, step 0.1, this fining your mouse moves on high hand speed. Decreasing the distance of two mouse steps. The result is very fine and smooth mouse move. When increaseing pointer_FPS the move is faster you can add more fining. I prefer pointer_FPS=200,in the game lock fps to 60FPS. When you sync your framerate in touchmote(ie:60-120-180-200FPS) and in the game(ie:30-60FPS+) that give the best result. Just try it :) + private double mouseFinerThreshold = Settings.Default.flyfps_mouse_finer_threshold; // range 0 - 100, default = 5, step 1, When mouse speed(pixel) reach this value the mousfiner reach flyfps_mouse_finer_high. Below this value flyfps_mouse_finer_low ranged to flyfps_mouse_finer_high. + private double borderTurnControlX = Settings.Default.flyfps_border_turn_speed_x; // range 0+, default = 0, step 0.1, when pointer leave flyfps_horizontal_border the sensitivity is increased depending the distance of pointer from border + private double borderTurnControlY = Settings.Default.flyfps_border_turn_speed_y; // range 0+, default = 0, step 0.1, when pointer leave flyfps_vertical_border the sensitivity is increased depending the distance of pointer from border + private double autoTurnControlX = Settings.Default.flyfps_auto_turn_speed_x; // range 0+, default = 0, step 0.1, when pointer leave flyfps_horizontal_border the mouse speed X continuosly increased depending the distance of pointer from border + private double autoTurnControlY = Settings.Default.flyfps_auto_turn_speed_y; // range 0+, default = 0, step 0.1, when pointer leave flyfps_vertical_border the mouse speed Y continuosly increased depending the distance of pointer from border + // TODO: END; add a user friendly control gear panel in the UI, like on the right Tilt X- ... + + private double screenWidth; + private double screenHeight; + private Vector cursorTargetPos; + private Vector cursorVirtualPos; + + private Vector[] cursorVectorBuffer = new Vector[2]; + private Vector cursorVectorDelta; + private SmoothingBuffer smoothingVectorBuffer; + private Vector mouseMainSpeed; + private Vector mouseMainStore; + private Vector mouseMainAccStore; + + private SmoothingBuffer smoothingRelativeBuffer; + private Vector smoothedCursorRelative; + private Vector[] smoothedCursorRelativeBuffer = new Vector[2]; + private Vector smoothedCursorRelativeDelta; + + private bool mustFillSmoothedRelativeBuffer; + private bool outTurnLeftRight; + private bool outTurnUpDown; + private double deltaOutAccelerator; + private Vector outTurn; + + private Vector mouseForward; + private Vector turnAcceleration; + private Vector sumRelativeDelta; + private Vector cursorDelta; + + private Vector mouseTurnSpeed; + private Vector currentMouseSpeed; + private double startingTurningSpeedX; + private double startingTurningSpeedY; + + private double leftBorderRelative; private double rightBorderRelative; private double topBorderRelative; private double bottomBorderRelative; + + private string mydebug; + private uint liveGraphAxisX; + private bool debugEnabled = Settings.Default.flyfps_debug; + + public MouseHandler() + { + this.inputSimulator = new InputSimulator(); + cursorPositionHelper = new CursorPositionHelper(); + + // common + System.Drawing.Rectangle screenBounds = DeviceUtils.DeviceUtil.GetScreen(Settings.Default.primaryMonitor).Bounds; + screenWidth = screenBounds.Width; + screenHeight = screenBounds.Height; + + leftBorderRelative = (100 - Settings.Default.flyfps_horizontal_border) / 2 / 100; + rightBorderRelative = 1 - leftBorderRelative; + topBorderRelative = (100 - Settings.Default.flyfps_vertical_border) / 2 / 100; + bottomBorderRelative = 1 - topBorderRelative; + + smoothingRelativeBuffer = new SmoothingBuffer(Settings.Default.flyfps_mouse_smooth_buffer); + mustFillSmoothedRelativeBuffer = true; + returnBoundAccelerator = mapRange(returnBoundAccelerator, 0, 100, 0.000000000000001, 0.1); + outOfBoundsDecceleration = 1 - mapRange(outOfBoundsDecceleration, 0, 100, 0, 1); + mouseFinerLow = 1 - mapRange(mouseFinerLow, 0, 100, 0, 0.99); + mouseFinerHigh = 1 - mapRange(mouseFinerHigh, 0, 100, 0, 0.99); + mouseFinerThreshold = mapRange(mouseFinerThreshold, 0, 100, 0, 100); + + // mouse speed vector + smoothingVectorBuffer = new SmoothingBuffer(Settings.Default.flyfps_main_buffer); + if (mouseMainSensY == 0) + mouseMainSensY = Settings.Default.flyfps_main_sensitivity * screenHeight / screenWidth; + + if (mouseMainAccY == 0) + mouseMainAccY = Settings.Default.flyfps_main_acceleration * screenHeight / screenWidth; + mouseMainAccThreshold = mapRange(mouseMainAccThreshold, 0, 100, 0, 0.1); + mouseMainAccFiner = 1 - mapRange(mouseMainAccFiner, 0, 100, 0, 0.99); + + mouseMainDeccStart = 0.99 - mapRange(mouseMainDeccStart, 0, 100, 0, 0.98); + mouseMainDeccEnd = 0.99 - mapRange(mouseMainDeccEnd, 0, 100, 0, 0.98); + mouseMainDeccThreshold = mapRange(mouseMainDeccThreshold, 0, 100, 0, 0.1); + + // mouse fine + if (mouseFineSensY == 0) + mouseFineSensY = Settings.Default.flyfps_fine_sensitivity * screenHeight / screenWidth; + + if (mouseFineAccY == 0) + mouseFineAccY = Settings.Default.flyfps_fine_acceleration * screenHeight / screenWidth; + + mouseFineDecc = 1 - mapRange(mouseFineDecc, 0, 100, 0, 0.999); + + // mouse forward + if (mouseForwardControlY == 0) + mouseForwardControlY = Settings.Default.flyfps_mouse_forward; + mouseForwardTurnOnThreshold = mapRange(mouseForwardTurnOnThreshold, 0, 100, 0, 0.1); + mouseFoewardDecceleration = mapRange(mouseFoewardDecceleration, 0, 100, 0, 0.99); + + // extra turn distance + extraTurnDeadZone.X = mapRange(extraTurnDeadZone.X, 0, 100, 0, 0.5); + extraTurnDeadZone.Y = extraTurnDeadZone.X; + + extraTurnEaseIn.X = mapRange(extraTurnEaseIn.X, 0, 100, 0, 0.5); + extraTurnEaseIn.Y = extraTurnEaseIn.X; + + if (extraTurnSensY == 0) + extraTurnSensY = extraTurnSensX * screenHeight / screenWidth; + + liveGraphAxisX = 0; + mydebug = "##|##\n"; + mydebug += "liveGraphAxisX|IRDeltaX|IRDeltaY|mouseMainSpeedX|mouseMainSpeedY|mouseMainStoreX|mouseMainStoreY|mouseOutX|mouseOutY\n"; + File.Delete(@"debug.txt"); + } + + public bool reset() + { + if (mouseLeftDown) + { + setButtonUp("mouseleft"); + } + if (mouseRightDown) + { + setButtonUp("mouseright"); + } + return true; + } + + public bool setButtonDown(string key) + { + if (Enum.IsDefined(typeof(MouseCode), key.ToUpper())) + { + MouseCode mouseCode = (MouseCode)Enum.Parse(typeof(MouseCode), key, true); + switch (mouseCode) + { + case MouseCode.MOUSELEFT: + this.inputSimulator.Mouse.LeftButtonDown(); + mouseLeftDown = true; + break; + case MouseCode.MOUSERIGHT: + this.inputSimulator.Mouse.RightButtonDown(); + mouseRightDown = true; + break; + default: + return false; + } + return true; + } + return false; + } + + public bool setButtonUp(string key) + { + if (Enum.IsDefined(typeof(MouseCode), key.ToUpper())) + { + MouseCode mouseCode = (MouseCode)Enum.Parse(typeof(MouseCode), key, true); + switch (mouseCode) + { + case MouseCode.MOUSELEFT: + this.inputSimulator.Mouse.LeftButtonUp(); + mouseLeftDown = false; + break; + case MouseCode.MOUSERIGHT: + this.inputSimulator.Mouse.RightButtonUp(); + mouseRightDown = false; + break; + default: + return false; + } + return true; + } + return false; + } + + public bool setPosition(string key, CursorPos cursorPos) + { + key = key.ToLower(); + if (key.Equals("mouse")) + { + if (!cursorPos.OutOfReach) + { + Point smoothedPos = cursorPositionHelper.getRelativePosition(new Point(cursorPos.X, cursorPos.Y)); + this.inputSimulator.Mouse.MoveMouseToPositionOnVirtualDesktop((65535 * smoothedPos.X), (65535 * smoothedPos.Y)); + return true; + } + } + + if (key.Equals("fpsmouse")) + { + Point smoothedPos = cursorPositionHelper.getSmoothedPosition(new Point(cursorPos.RelativeX, cursorPos.RelativeY)); + + /* + * TODO: Consider sensor bar position? + if (Settings.Default.pointer_sensorBarPos == "top") + { + smoothedPos.Y = smoothedPos.Y - Settings.Default.pointer_sensorBarPosCompensation; + } + else if (Settings.Default.pointer_sensorBarPos == "bottom") + { + smoothedPos.Y = smoothedPos.Y + Settings.Default.pointer_sensorBarPosCompensation; + } + */ + double deadzone = Settings.Default.fpsmouse_deadzone; // TODO: Move to settings + double shiftX = Math.Abs(smoothedPos.X - 0.5) > deadzone ? smoothedPos.X - 0.5 : 0; + double shiftY = Math.Abs(smoothedPos.Y - 0.5) > deadzone ? smoothedPos.Y - 0.5 : 0; + + this.inputSimulator.Mouse.MoveMouseBy((int)(Settings.Default.fpsmouse_speed * shiftX), (int)(Settings.Default.fpsmouse_speed * shiftY)); + + return true; + } + + if (key.Equals("flyfpsmouse")) + { + String tmpDebug = ""; + + if (cursorPos.OutOfReach) + { + double tmpOutTurnX = mouseMainSpeed.X + mouseForward.X + turnAcceleration.X + mouseTurnSpeed.X + currentMouseSpeed.X; + double tmpOutTurnY = mouseMainSpeed.Y + mouseForward.Y + turnAcceleration.Y + mouseTurnSpeed.Y + currentMouseSpeed.Y; + if (outTurnLeftRight & !outTurnUpDown) tmpOutTurnY = 0.000000000000001; + if (!outTurnLeftRight & outTurnUpDown) tmpOutTurnX = 0.000000000000001; + + if (tmpOutTurnX == 0) + { + outTurn.X *= outOfBoundsDecceleration; + } + else + { + outTurn.X = tmpOutTurnX; + mouseMainSpeed.X = mouseForward.X = turnAcceleration.X = mouseTurnSpeed.X = currentMouseSpeed.X = 0; + } + + if (tmpOutTurnY == 0) + { + outTurn.Y *= outOfBoundsDecceleration; + } + else + { + outTurn.Y = tmpOutTurnY; + mouseMainSpeed.Y = mouseForward.Y = turnAcceleration.Y = mouseTurnSpeed.Y = currentMouseSpeed.Y = 0; + } + + mouseMainStore.X = mouseMainStore.Y = 0; + sumRelativeDelta.X = sumRelativeDelta.Y = 0; + mustFillSmoothedRelativeBuffer = true; + deltaOutAccelerator = 0.000000000000001; + } + else + { + if (mustFillSmoothedRelativeBuffer) + { + smoothingRelativeBuffer.fill(cursorPos.RelativeX, cursorPos.RelativeY); + smoothingVectorBuffer.fill(cursorPos.RelativeX, cursorPos.RelativeY); + + cursorVectorBuffer[1].X = smoothedCursorRelativeBuffer[1].X = cursorPos.RelativeX; + cursorVectorBuffer[1].Y = smoothedCursorRelativeBuffer[1].Y = cursorPos.RelativeY; + smoothedCursorRelativeDelta.X = smoothedCursorRelativeDelta.Y = 0;// mouseForvard + mustFillSmoothedRelativeBuffer = false; + } + else + { + smoothingRelativeBuffer.addValue(cursorPos.RelativeX, cursorPos.RelativeY); + smoothingVectorBuffer.addValue(cursorPos.RelativeX, cursorPos.RelativeY); + } + + // mouseFineSpeed smoothed relative + smoothedCursorRelative = smoothingRelativeBuffer.getSmoothedValue(); + smoothedCursorRelativeBuffer[0] = smoothedCursorRelativeBuffer[1]; + smoothedCursorRelativeBuffer[1] = smoothedCursorRelative; + Vector prevSmoothedCursorRelativeDelta = smoothedCursorRelativeDelta; + smoothedCursorRelativeDelta = smoothedCursorRelativeBuffer[1] - smoothedCursorRelativeBuffer[0]; + + // vector smoothed relative + cursorVectorBuffer[0] = cursorVectorBuffer[1]; + cursorVectorBuffer[1] = smoothingVectorBuffer.getSmoothedValue(); + Vector prevCursorVectorDelta = cursorVectorDelta; + cursorVectorDelta = cursorVectorBuffer[1] - cursorVectorBuffer[0]; + + // outturn + if (deltaOutAccelerator != 0) + { + if (Math.Abs(outTurn.X) > 1 | Math.Abs(outTurn.Y) > 1) + { + outTurn.X *= 0.5; + outTurn.Y *= 0.5; + smoothedCursorRelativeDelta.X = smoothedCursorRelativeDelta.Y = cursorVectorDelta.X = cursorVectorDelta.Y = 0; + } + else + { + smoothedCursorRelativeDelta.X *= deltaOutAccelerator; + smoothedCursorRelativeDelta.Y *= deltaOutAccelerator; + cursorVectorDelta.X *= deltaOutAccelerator; + cursorVectorDelta.Y *= deltaOutAccelerator; + deltaOutAccelerator += returnBoundAccelerator; + if (deltaOutAccelerator >= 1) + { + deltaOutAccelerator = 0; + } + outTurn.X = outTurn.Y = 0; + } + } + + // mouse aim speed mod + double mouseMainSensTmpX = mouseMainSensX; + double mouseMainAccTmpX = mouseMainAccX; + double mouseMainDeccTmp = mouseMainDeccStart; + double mouseMainDeccTmpMax = mouseMainDeccEnd; + + double mouseMainSensTmpY = mouseMainSensY; + double mouseMainAccTmpY = mouseMainAccY; + + if ((mouseRightDown || (mouseLeftDown && mouseFineLeftEnable)) && mouseFineSensX != 0) + { + mouseMainSensTmpX = mouseFineSensX; + mouseMainAccTmpX = mouseFineAccX; + + mouseMainDeccTmp = mouseFineDecc; + mouseMainDeccTmpMax = mouseFineDecc; + + mouseMainSensTmpY = mouseFineSensY; + mouseMainAccTmpY = mouseFineAccY; + } + + // mouseMainSpeed Vector + mouseMainDeccTmp = mapRangeLength(mouseMainStore.Length, 0, mouseMainDeccThreshold, mouseMainDeccTmp, mouseMainDeccTmpMax); + + mouseMainStore.X *= mouseMainDeccTmp; + mouseMainStore.X += cursorVectorDelta.X; + + double readyAccelerationX = mapRangeLength(cursorVectorDelta.Length, 0, mouseMainAccThreshold, 0, mouseMainAccTmpX); + mouseMainAccStore.X += readyAccelerationX; + readyAccelerationX = mouseMainAccStore.X * mouseMainAccFiner; + mouseMainAccStore.X -= readyAccelerationX; + + mouseMainSpeed.X = mouseMainStore.X * (mouseMainSensTmpX + readyAccelerationX) * screenWidth; + + + mouseMainStore.Y *= mouseMainDeccTmp; + mouseMainStore.Y += cursorVectorDelta.Y; + + double readyAccelerationY = mapRangeLength(cursorVectorDelta.Length, 0, mouseMainAccThreshold, 0, mouseMainAccTmpY); + mouseMainAccStore.Y += readyAccelerationY; + readyAccelerationY = mouseMainAccStore.Y * mouseMainAccFiner; + mouseMainAccStore.Y -= readyAccelerationY; + + mouseMainSpeed.Y = mouseMainStore.Y * (mouseMainSensTmpY + readyAccelerationY) * screenWidth; // DO NOT CHANGE :P + + + // mouseForward + double tmpMouseForwardX = Math.Abs(smoothedCursorRelativeDelta.X) - Math.Abs(prevSmoothedCursorRelativeDelta.X); + tmpMouseForwardX = Math.Max(tmpMouseForwardX, 0); + if (Math.Abs(smoothedCursorRelativeDelta.X) > mouseForwardTurnOnThreshold & Math.Abs(mouseForward.X) < 1) + { + mouseForward.X = Math.Sign(smoothedCursorRelativeDelta.X) * mouseForwardControlX; + } + else mouseForward.X = Math.Sign(mouseForward.X) * valueFollow(Math.Abs(mouseForward.X), 0, mouseFoewardDecceleration, mouseFoewardDecceleration); + + double tmpMouseForwardY = Math.Abs(smoothedCursorRelativeDelta.Y) - Math.Abs(prevSmoothedCursorRelativeDelta.Y); + tmpMouseForwardY = Math.Max(tmpMouseForwardY, 0); + if (Math.Abs(smoothedCursorRelativeDelta.Y) > mouseForwardTurnOnThreshold & Math.Abs(mouseForward.Y) < 1) + { + mouseForward.Y = Math.Sign(smoothedCursorRelativeDelta.Y) * mouseForwardControlY; + } + else mouseForward.Y = Math.Sign(mouseForward.Y) * valueFollow(Math.Abs(mouseForward.Y), 0, mouseFoewardDecceleration, mouseFoewardDecceleration); + + // turn acceleration from distance + Vector prevSumRelativeDelta = sumRelativeDelta; + sumRelativeDelta += smoothedCursorRelativeDelta; + Vector sumDeadZoneEaseIn = extraTurnDeadZone + extraTurnEaseIn; + + double sumRelativeDeltaAbsX = Math.Abs(sumRelativeDelta.X); + double directionX = Math.Sign(sumRelativeDelta.X); + if (sumRelativeDeltaAbsX > sumDeadZoneEaseIn.X) sumRelativeDelta.X = directionX * sumDeadZoneEaseIn.X; + if (sumRelativeDeltaAbsX < Math.Abs(prevSumRelativeDelta.X)) sumRelativeDelta.X = 0; + turnAcceleration.X = directionX * mapRange(sumRelativeDeltaAbsX, extraTurnDeadZone.X, sumDeadZoneEaseIn.X, 0, extraTurnSensX) * screenWidth * Math.Abs(smoothedCursorRelativeDelta.X); + + double sumRelativeDeltaAbsY = Math.Abs(sumRelativeDelta.Y); + double directionY = Math.Sign(sumRelativeDelta.Y); + if (sumRelativeDeltaAbsY > sumDeadZoneEaseIn.Y) sumRelativeDelta.Y = directionY * sumDeadZoneEaseIn.Y; + if (sumRelativeDeltaAbsY < Math.Abs(prevSumRelativeDelta.Y)) sumRelativeDelta.Y = 0; + turnAcceleration.Y = directionY * mapRange(sumRelativeDeltaAbsY, extraTurnDeadZone.Y, sumDeadZoneEaseIn.Y, 0, extraTurnSensY) * screenWidth * Math.Abs(smoothedCursorRelativeDelta.Y); + + // turn acceleration from border + if (borderTurnControlX != 0) + { + double multiplyer; + double distanceFromBorder; + if (smoothedCursorRelative.X < leftBorderRelative) + { + distanceFromBorder = leftBorderRelative - smoothedCursorRelative.X; + multiplyer = mapRange(distanceFromBorder, 0, leftBorderRelative, 0.5, 1); + + if (smoothedCursorRelativeDelta.X > 0) multiplyer *= multiplyer; + mouseTurnSpeed.X += smoothedCursorRelativeDelta.X * screenWidth * borderTurnControlX; + } + else if (smoothedCursorRelative.X > rightBorderRelative) + { + distanceFromBorder = smoothedCursorRelative.X - rightBorderRelative; + multiplyer = mapRange(distanceFromBorder, 0, leftBorderRelative, 0.5, 1); + + if (smoothedCursorRelativeDelta.X < 0) multiplyer *= multiplyer; + mouseTurnSpeed.X += smoothedCursorRelativeDelta.X * screenWidth * borderTurnControlX; + } + else + { + distanceFromBorder = multiplyer = 0; + } + mouseTurnSpeed.X *= multiplyer; + } + + if (borderTurnControlY != 0) + { + double multiplyer; + double distanceFromBorder; + if (smoothedCursorRelative.Y < topBorderRelative) + { + distanceFromBorder = topBorderRelative - smoothedCursorRelative.Y; + multiplyer = mapRange(distanceFromBorder, 0, topBorderRelative, 0.5, 1); + + if (smoothedCursorRelativeDelta.Y > 0) multiplyer *= multiplyer; + mouseTurnSpeed.Y += smoothedCursorRelativeDelta.Y * screenHeight * borderTurnControlY; + } + else if (smoothedCursorRelative.Y > bottomBorderRelative) + { + distanceFromBorder = smoothedCursorRelative.Y - bottomBorderRelative; + multiplyer = mapRange(distanceFromBorder, 0, topBorderRelative, 0.5, 1); + + if (smoothedCursorRelativeDelta.Y < 0) multiplyer *= multiplyer; + mouseTurnSpeed.Y += smoothedCursorRelativeDelta.Y * screenHeight * borderTurnControlY; + } + else + { + distanceFromBorder = multiplyer = 0; + } + mouseTurnSpeed.Y *= multiplyer; + } + + // autoTurn + if (autoTurnControlX != 0) + { + if (startingTurningSpeedX == 999) startingTurningSpeedX = mouseMainSpeed.X + mouseTurnSpeed.X; + if (smoothedCursorRelative.X < leftBorderRelative) + { + currentMouseSpeed.X = -mapRange((leftBorderRelative - smoothedCursorRelative.X), 0, leftBorderRelative, 1, autoTurnControlX) + startingTurningSpeedX; + startingTurningSpeedX *= 0.85; + mouseMainSpeed.X = 0; + } + else if (smoothedCursorRelative.X > rightBorderRelative) + { + currentMouseSpeed.X = mapRange((smoothedCursorRelative.X - rightBorderRelative), 0, leftBorderRelative, 1, autoTurnControlX) + startingTurningSpeedX; + startingTurningSpeedX *= 0.85; + mouseMainSpeed.X = 0; + } + else + { + currentMouseSpeed.X = 0; + startingTurningSpeedX = 999; + } + } + if (autoTurnControlY != 0) + { + if (startingTurningSpeedY == 999) startingTurningSpeedY = mouseMainSpeed.Y + mouseTurnSpeed.Y; + if (smoothedCursorRelative.Y < topBorderRelative) + { + currentMouseSpeed.Y = -mapRange((topBorderRelative - smoothedCursorRelative.Y), 0, topBorderRelative, 1, autoTurnControlY) + startingTurningSpeedY; + startingTurningSpeedY *= 0.85; + mouseMainSpeed.Y = 0; + } + else if (smoothedCursorRelative.Y > bottomBorderRelative) + { + currentMouseSpeed.Y = mapRange((smoothedCursorRelative.Y - bottomBorderRelative), 0, topBorderRelative, 1, autoTurnControlY) + startingTurningSpeedY; + startingTurningSpeedY *= 0.85; + mouseMainSpeed.Y = 0; + } + else + { + currentMouseSpeed.Y = 0; + startingTurningSpeedY = 999; + } + } + // out bound turning direction + if (smoothedCursorRelative.X < leftBorderRelative | smoothedCursorRelative.X > rightBorderRelative) outTurnLeftRight = true; + else outTurnLeftRight = false; + if (smoothedCursorRelative.Y < topBorderRelative | smoothedCursorRelative.Y > bottomBorderRelative) outTurnUpDown = true; + else outTurnUpDown = false; + } + + cursorDelta = new Vector( + turnAcceleration.X + mouseForward.X + mouseTurnSpeed.X + currentMouseSpeed.X + outTurn.X + mouseMainSpeed.X, + turnAcceleration.Y + mouseForward.Y + mouseTurnSpeed.Y + currentMouseSpeed.Y + outTurn.Y + mouseMainSpeed.Y + ); + + // mouse fining + cursorTargetPos += cursorDelta; + cursorDelta = cursorTargetPos - cursorVirtualPos; + + double mouseFinerTMP = mapRangeLength(cursorDelta.Length, 0, mouseFinerThreshold, mouseFinerLow, mouseFinerHigh); + + cursorDelta = cursorDelta * mouseFinerTMP; + + if (Math.Abs(cursorDelta.X) >= 1) cursorVirtualPos.X += cursorDelta.X; + if (Math.Abs(cursorDelta.Y) >= 1) cursorVirtualPos.Y += cursorDelta.Y; + // move the mouse + this.inputSimulator.Mouse.MoveMouseBy( + (int)(cursorDelta.X), + (int)(cursorDelta.Y)); + + if (debugEnabled) + { + tmpDebug += liveGraphAxisX + "|"; + tmpDebug += (cursorVectorDelta.X * 10000) + "|"; + tmpDebug += (cursorVectorDelta.Y * 10000) + "|"; + tmpDebug += Math.Floor(mouseMainSpeed.X) + "|"; + tmpDebug += Math.Floor(mouseMainSpeed.Y) + "|"; + tmpDebug += (mouseMainStore.X * 1000) + "|"; + tmpDebug += (mouseMainStore.Y * 1000) + "|"; + tmpDebug += Math.Floor(cursorDelta.X) + "|"; + tmpDebug += Math.Floor(cursorDelta.Y) + "\n"; + mydebug += tmpDebug.Replace(",", "."); + liveGraphAxisX++; + MainWindow.Current.ShowMessage("DebugENABLED", MainWindow.MessageType.Info); + + using (StreamWriter outputFile = new StreamWriter("debug.txt", true)) + { + //if (mydebug.Length > 102400) + if (liveGraphAxisX % 1900 == 0) + { + outputFile.WriteLine(mydebug); + mydebug = ""; + } + } + } + + } + + return false; + } + private double mapRange(double toRange, double inputStart, double inputEnd, double outputStart, double outputEnd) + { + if (toRange < inputStart) return outputStart; + if (toRange > inputEnd) return outputEnd; + if (outputEnd < outputStart) return outputStart; + return outputStart + (toRange - inputStart) * (outputEnd - outputStart) / (inputEnd - inputStart); + } + private double mapRangeLength(double toRange, double inputStart, double inputEnd, double outputStart, double outputEnd) + { + if (toRange > inputEnd) return outputEnd; + return outputStart + (toRange - inputStart) * (outputEnd - outputStart) / (inputEnd - inputStart); + } + private double valueFollow(double myvalue, double target, double acceleration, double deccelaration) + { + if (myvalue < target) + { + myvalue += Math.Abs(target - myvalue) * acceleration; + } + else if (myvalue > target) + { + myvalue -= Math.Abs(target - myvalue) * deccelaration; + } + return myvalue; + } + public bool setValue(string key, double value) + { + key = key.ToLower(); + switch (key) + { + case "mousey+": + this.inputSimulator.Mouse.MoveMouseBy(0, (int)(-30 * value + 0.5)); + break; + case "mousey-": + this.inputSimulator.Mouse.MoveMouseBy(0, (int)(30 * value + 0.5)); + break; + case "mousex+": + this.inputSimulator.Mouse.MoveMouseBy((int)(30 * value + 0.5), 0); + break; + case "mousex-": + this.inputSimulator.Mouse.MoveMouseBy((int)(-30 * value + 0.5), 0); + break; + default: + return false; + } + return true; + } + + public bool connect() + { + return true; + } + + public bool disconnect() + { + return true; + } + + public bool startUpdate() + { + return true; + } + + public bool endUpdate() + { + return true; + } + } + + public enum MouseCode + { + MOUSELEFT, + MOUSERIGHT + } +} diff --git a/WiiTUIO/Properties/Settings.cs b/WiiTUIO/Properties/Settings.cs index 003d6c89..37c0185f 100644 --- a/WiiTUIO/Properties/Settings.cs +++ b/WiiTUIO/Properties/Settings.cs @@ -1,485 +1,892 @@ -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Configuration; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using WiiTUIO.Input; - -namespace WiiTUIO.Properties -{ - class Settings - { - - public event PropertyChangedEventHandler PropertyChanged; - - private string _input = "multipointer"; - public string input - { - get { return _input; } - set - { - _input = value; - OnPropertyChanged("input"); - } - } - - private string _output = "touch"; - public string output - { - get { return _output; } - set - { - _output = value; - OnPropertyChanged("output"); - } - } - - private bool _pairOnStart = false; - public bool pairOnStart - { - get { return _pairOnStart; } - set - { - _pairOnStart = value; - OnPropertyChanged("pairOnStart"); - } - } - - private bool _connectOnStart = true; - public bool connectOnStart - { - get { return _connectOnStart; } - set - { - _connectOnStart = value; - OnPropertyChanged("connectOnStart"); - } - } - - private bool _minimizeOnStart = false; - public bool minimizeOnStart - { - get { return _minimizeOnStart; } - set - { - _minimizeOnStart = value; - OnPropertyChanged("minimizeOnStart"); - } - } - - private bool _minimizeToTray = false; - public bool minimizeToTray - { - get { return _minimizeToTray; } - set - { - _minimizeToTray = value; - OnPropertyChanged("minimizeToTray"); - } - } - - private bool _pairedOnce = false; - public bool pairedOnce - { - get { return _pairedOnce; } - set - { - _pairedOnce = value; - OnPropertyChanged("pairedOnce"); - } - } - - private string _primaryMonitor = ""; - public string primaryMonitor - { - get { return _primaryMonitor; } - set - { - _primaryMonitor = value; - OnPropertyChanged("primaryMonitor"); - } - } - - private bool _completelyDisconnect = false; - public bool completelyDisconnect - { - get { return _completelyDisconnect; } - set - { - _completelyDisconnect = value; - OnPropertyChanged("completelyDisconnect"); - } - } - - private int _autoDisconnectTimeout = 300000; - public int autoDisconnectTimeout - { - get { return _autoDisconnectTimeout; } - set - { - _autoDisconnectTimeout = value; - OnPropertyChanged("autoDisconnectTimeout"); - } - } - - private double _defaultContinousScale = 1.0; - public double defaultContinousScale - { - get { return _defaultContinousScale; } - set - { - _defaultContinousScale = value; - OnPropertyChanged("defaultContinousScale"); - } - } - - private double _defaultContinousPressThreshold = 0.4; - public double defaultContinousPressThreshold - { - get { return _defaultContinousPressThreshold; } - set - { - _defaultContinousPressThreshold = value; - OnPropertyChanged("defaultContinousPressThreshold"); - } - } - - private double _defaultContinousDeadzone = 0.01; - public double defaultContinousDeadzone - { - get { return _defaultContinousDeadzone; } - set - { - _defaultContinousDeadzone = value; - OnPropertyChanged("defaultContinousDeadzone"); - } - } - - private bool _alternativeStickToCursorMapping = false; - public bool alternativeStickToCursorMapping - { - get { return _alternativeStickToCursorMapping; } - set - { - _alternativeStickToCursorMapping = value; - OnPropertyChanged("alternativeStickToCursorMapping"); - } - } - - private bool _disconnectWiimotesOnDolphin = false; - public bool disconnectWiimotesOnDolphin - { - get { return _disconnectWiimotesOnDolphin; } - set - { - _disconnectWiimotesOnDolphin = value; - OnPropertyChanged("disconnectWiimotesOnDolphin"); - } - } - - private string _tuio_IP = "127.0.0.1"; - public string tuio_IP - { - get { return _tuio_IP; } - set - { - _tuio_IP = value; - OnPropertyChanged("tuio_IP"); - } - } - - private int _tuio_port = 3333; - public int tuio_port - { - get { return _tuio_port; } - set - { - _tuio_port = value; - OnPropertyChanged("tuio_port"); - } - } - - private string _keymaps_path = @"Keymaps\"; - public string keymaps_path - { - get { return _keymaps_path; } - set - { - _keymaps_path = value; - OnPropertyChanged("keymaps_path"); - } - } - - private bool _noTopmost = false; - public bool noTopmost - { - get { return _noTopmost; } - set - { - _noTopmost = value; - OnPropertyChanged("noTopmost"); - } - } - - private string _keymaps_config = @"Keymaps.json"; - public string keymaps_config - { - get { return _keymaps_config; } - set - { - _keymaps_config = value; - OnPropertyChanged("keymaps_config"); - } - } - - private double _pointer_sensorBarPosCompensation = 0.30; - public double pointer_sensorBarPosCompensation - { - get { return _pointer_sensorBarPosCompensation; } - set - { - _pointer_sensorBarPosCompensation = value; - OnPropertyChanged("pointer_sensorBarPosCompensation"); - } - } - - private double _pointer_cursorSize = 0.03; - public double pointer_cursorSize - { - get { return _pointer_cursorSize; } - set - { - _pointer_cursorSize = value; - OnPropertyChanged("pointer_cursorSize"); - } - } - - private double _pointer_marginsTopBottom = 0.8; - public double pointer_marginsTopBottom - { - get { return _pointer_marginsTopBottom; } - set - { - _pointer_marginsTopBottom = value; - OnPropertyChanged("pointer_marginsTopBottom"); - } - } - - private double _pointer_marginsLeftRight = 0.7; - public double pointer_marginsLeftRight - { - get { return _pointer_marginsLeftRight; } - set - { - _pointer_marginsLeftRight = value; - OnPropertyChanged("pointer_marginsLeftRight"); - } - } - - private bool _pointer_considerRotation = true; - public bool pointer_considerRotation - { - get { return _pointer_considerRotation; } - set - { - _pointer_considerRotation = value; - OnPropertyChanged("pointer_considerRotation"); - } - } - - private bool _pointer_customCursor = true; - public bool pointer_customCursor - { - get { return _pointer_customCursor; } - set - { - _pointer_customCursor = value; - OnPropertyChanged("pointer_customCursor"); - } - } - - private int _pointer_cursorStillHideTimeout = 3000; - public int pointer_cursorStillHideTimeout - { - get { return _pointer_cursorStillHideTimeout; } - set - { - _pointer_cursorStillHideTimeout = value; - OnPropertyChanged("pointer_cursorStillHideTimeout"); - } - } - - //Delta pixels before the cursor is considered still. - private int _pointer_cursorStillThreshold = 10; - public int pointer_cursorStillThreshold - { - get { return _pointer_cursorStillThreshold; } - set - { - _pointer_cursorStillThreshold = value; - OnPropertyChanged("pointer_cursorStillThreshold"); - } - } - - private string _pointer_sensorBarPos = "center"; - public string pointer_sensorBarPos - { - get { return _pointer_sensorBarPos; } - set - { - _pointer_sensorBarPos = value; - OnPropertyChanged("pointer_sensorBarPos"); - } - } - - private int _pointer_FPS = 100; - public int pointer_FPS - { - get { return _pointer_FPS; } - set - { - _pointer_FPS = value; - OnPropertyChanged("pointer_FPS"); - } - } - - private int _pointer_positionSmoothing = 3; - public int pointer_positionSmoothing - { - get { return _pointer_positionSmoothing; } - set - { - _pointer_positionSmoothing = value; - OnPropertyChanged("pointer_positionSmoothing"); - } - } - - private double _fpsmouse_deadzone = 0.03; - public double fpsmouse_deadzone - { - get { return _fpsmouse_deadzone; } - set - { - _fpsmouse_deadzone = value; - OnPropertyChanged("fpsmouse_deadzone"); - } - } - - private int _fpsmouse_speed = 30; - public int fpsmouse_speed - { - get { return _fpsmouse_speed; } - set - { - _fpsmouse_speed = value; - OnPropertyChanged("fpsmouse_speed"); - } - } - - private int _touch_touchTapThreshold = 40; - public int touch_touchTapThreshold - { - get { return _touch_touchTapThreshold; } - set - { - _touch_touchTapThreshold = value; - OnPropertyChanged("touch_touchTapThreshold"); - } - } - - private int _touch_edgeGestureHelperMargins = 30; - public int touch_edgeGestureHelperMargins - { - get { return _touch_edgeGestureHelperMargins; } - set - { - _touch_edgeGestureHelperMargins = value; - OnPropertyChanged("touch_edgeGestureHelperMargins"); - } - } - - private int _touch_edgeGestureHelperRelease = 60; - public int touch_edgeGestureHelperRelease - { - get { return _touch_edgeGestureHelperRelease; } - set - { - _touch_edgeGestureHelperRelease = value; - OnPropertyChanged("touch_edgeGestureHelperRelease"); - } - } - - private int _xinput_rumbleThreshold_big = 200; - public int xinput_rumbleThreshold_big - { - get { return _xinput_rumbleThreshold_big; } - set - { - _xinput_rumbleThreshold_big = value; - OnPropertyChanged("xinput_rumbleThreshold_big"); - } - } - - private int _xinput_rumbleThreshold_small = 200; - public int xinput_rumbleThreshold_small - { - get { return _xinput_rumbleThreshold_small; } - set - { - _xinput_rumbleThreshold_small = value; - OnPropertyChanged("xinput_rumbleThreshold_small"); - } - } - - private static string SETTINGS_FILENAME = System.AppDomain.CurrentDomain.BaseDirectory+"settings.json"; - - private static Settings defaultInstance; - - public static Settings Default - { - get - { - if (defaultInstance == null) - { - defaultInstance = Load(); - } - return defaultInstance; - } - } - - private static Settings Load() - { - Settings result; - try - { - result = JsonConvert.DeserializeObject(File.ReadAllText(SETTINGS_FILENAME)); - } - catch //If anything goes wrong, just load default values - { - result = new Settings(); - } - - return result; - } - - public void Save() - { - File.WriteAllText(SETTINGS_FILENAME, JsonConvert.SerializeObject(Default,Formatting.Indented)); - } - - protected void OnPropertyChanged(string name) - { - PropertyChangedEventHandler handler = PropertyChanged; - if (handler != null) - { - handler(this, new PropertyChangedEventArgs(name)); - } - } - - } - -} +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Configuration; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WiiTUIO.Input; + +namespace WiiTUIO.Properties +{ + class Settings + { + + public event PropertyChangedEventHandler PropertyChanged; + + private string _input = "multipointer"; + public string input + { + get { return _input; } + set + { + _input = value; + OnPropertyChanged("input"); + } + } + + private string _output = "touch"; + public string output + { + get { return _output; } + set + { + _output = value; + OnPropertyChanged("output"); + } + } + + private bool _pairOnStart = false; + public bool pairOnStart + { + get { return _pairOnStart; } + set + { + _pairOnStart = value; + OnPropertyChanged("pairOnStart"); + } + } + + private bool _connectOnStart = true; + public bool connectOnStart + { + get { return _connectOnStart; } + set + { + _connectOnStart = value; + OnPropertyChanged("connectOnStart"); + } + } + + private bool _minimizeOnStart = false; + public bool minimizeOnStart + { + get { return _minimizeOnStart; } + set + { + _minimizeOnStart = value; + OnPropertyChanged("minimizeOnStart"); + } + } + + private bool _minimizeToTray = false; + public bool minimizeToTray + { + get { return _minimizeToTray; } + set + { + _minimizeToTray = value; + OnPropertyChanged("minimizeToTray"); + } + } + + private bool _pairedOnce = false; + public bool pairedOnce + { + get { return _pairedOnce; } + set + { + _pairedOnce = value; + OnPropertyChanged("pairedOnce"); + } + } + + private string _primaryMonitor = ""; + public string primaryMonitor + { + get { return _primaryMonitor; } + set + { + _primaryMonitor = value; + OnPropertyChanged("primaryMonitor"); + } + } + + private bool _completelyDisconnect = false; + public bool completelyDisconnect + { + get { return _completelyDisconnect; } + set + { + _completelyDisconnect = value; + OnPropertyChanged("completelyDisconnect"); + } + } + + private int _autoDisconnectTimeout = 300000; + public int autoDisconnectTimeout + { + get { return _autoDisconnectTimeout; } + set + { + _autoDisconnectTimeout = value; + OnPropertyChanged("autoDisconnectTimeout"); + } + } + + private double _defaultContinousScale = 1.0; + public double defaultContinousScale + { + get { return _defaultContinousScale; } + set + { + _defaultContinousScale = value; + OnPropertyChanged("defaultContinousScale"); + } + } + + private double _defaultContinousPressThreshold = 0.4; + public double defaultContinousPressThreshold + { + get { return _defaultContinousPressThreshold; } + set + { + _defaultContinousPressThreshold = value; + OnPropertyChanged("defaultContinousPressThreshold"); + } + } + + private double _defaultContinousDeadzone = 0.01; + public double defaultContinousDeadzone + { + get { return _defaultContinousDeadzone; } + set + { + _defaultContinousDeadzone = value; + OnPropertyChanged("defaultContinousDeadzone"); + } + } + + private bool _alternativeStickToCursorMapping = false; + public bool alternativeStickToCursorMapping + { + get { return _alternativeStickToCursorMapping; } + set + { + _alternativeStickToCursorMapping = value; + OnPropertyChanged("alternativeStickToCursorMapping"); + } + } + + private bool _disconnectWiimotesOnDolphin = false; + public bool disconnectWiimotesOnDolphin + { + get { return _disconnectWiimotesOnDolphin; } + set + { + _disconnectWiimotesOnDolphin = value; + OnPropertyChanged("disconnectWiimotesOnDolphin"); + } + } + + private string _tuio_IP = "127.0.0.1"; + public string tuio_IP + { + get { return _tuio_IP; } + set + { + _tuio_IP = value; + OnPropertyChanged("tuio_IP"); + } + } + + private int _tuio_port = 3333; + public int tuio_port + { + get { return _tuio_port; } + set + { + _tuio_port = value; + OnPropertyChanged("tuio_port"); + } + } + + private string _keymaps_path = @"Keymaps\"; + public string keymaps_path + { + get { return _keymaps_path; } + set + { + _keymaps_path = value; + OnPropertyChanged("keymaps_path"); + } + } + + private bool _noTopmost = false; + public bool noTopmost + { + get { return _noTopmost; } + set + { + _noTopmost = value; + OnPropertyChanged("noTopmost"); + } + } + + private string _keymaps_config = @"Keymaps.json"; + public string keymaps_config + { + get { return _keymaps_config; } + set + { + _keymaps_config = value; + OnPropertyChanged("keymaps_config"); + } + } + + private double _pointer_sensorBarPosCompensation = 0.30; + public double pointer_sensorBarPosCompensation + { + get { return _pointer_sensorBarPosCompensation; } + set + { + _pointer_sensorBarPosCompensation = value; + OnPropertyChanged("pointer_sensorBarPosCompensation"); + } + } + + private double _pointer_cursorSize = 0.03; + public double pointer_cursorSize + { + get { return _pointer_cursorSize; } + set + { + _pointer_cursorSize = value; + OnPropertyChanged("pointer_cursorSize"); + } + } + + private double _pointer_marginsTopBottom = 0.8; + public double pointer_marginsTopBottom + { + get { return _pointer_marginsTopBottom; } + set + { + _pointer_marginsTopBottom = value; + OnPropertyChanged("pointer_marginsTopBottom"); + } + } + + private double _pointer_marginsLeftRight = 0.7; + public double pointer_marginsLeftRight + { + get { return _pointer_marginsLeftRight; } + set + { + _pointer_marginsLeftRight = value; + OnPropertyChanged("pointer_marginsLeftRight"); + } + } + + private bool _pointer_considerRotation = true; + public bool pointer_considerRotation + { + get { return _pointer_considerRotation; } + set + { + _pointer_considerRotation = value; + OnPropertyChanged("pointer_considerRotation"); + } + } + + private bool _pointer_customCursor = true; + public bool pointer_customCursor + { + get { return _pointer_customCursor; } + set + { + _pointer_customCursor = value; + OnPropertyChanged("pointer_customCursor"); + } + } + + private int _pointer_cursorStillHideTimeout = 3000; + public int pointer_cursorStillHideTimeout + { + get { return _pointer_cursorStillHideTimeout; } + set + { + _pointer_cursorStillHideTimeout = value; + OnPropertyChanged("pointer_cursorStillHideTimeout"); + } + } + + //Delta pixels before the cursor is considered still. + private int _pointer_cursorStillThreshold = 10; + public int pointer_cursorStillThreshold + { + get { return _pointer_cursorStillThreshold; } + set + { + _pointer_cursorStillThreshold = value; + OnPropertyChanged("pointer_cursorStillThreshold"); + } + } + + private string _pointer_sensorBarPos = "center"; + public string pointer_sensorBarPos + { + get { return _pointer_sensorBarPos; } + set + { + _pointer_sensorBarPos = value; + OnPropertyChanged("pointer_sensorBarPos"); + } + } + + private int _pointer_FPS = 200; + public int pointer_FPS + { + get { return _pointer_FPS; } + set + { + _pointer_FPS = value; + OnPropertyChanged("pointer_FPS"); + } + } + + private int _pointer_positionSmoothing = 3; + public int pointer_positionSmoothing + { + get { return _pointer_positionSmoothing; } + set + { + _pointer_positionSmoothing = value; + OnPropertyChanged("pointer_positionSmoothing"); + } + } + + private double _fpsmouse_deadzone = 0.03; + public double fpsmouse_deadzone + { + get { return _fpsmouse_deadzone; } + set + { + _fpsmouse_deadzone = value; + OnPropertyChanged("fpsmouse_deadzone"); + } + } + + private int _fpsmouse_speed = 30; + public int fpsmouse_speed + { + get { return _fpsmouse_speed; } + set + { + _fpsmouse_speed = value; + OnPropertyChanged("fpsmouse_speed"); + } + } + + private double _flyfps_horizontal_border = 50; + public double flyfps_horizontal_border + { + get { return _flyfps_horizontal_border; } + set + { + _flyfps_horizontal_border = value; + OnPropertyChanged("flyfps_horizontal_border"); + } + } + + private double _flyfps_vertical_border = 80; + public double flyfps_vertical_border + { + get { return _flyfps_vertical_border; } + set + { + _flyfps_vertical_border = value; + OnPropertyChanged("flyfps_vertical_border"); + } + } + + private int _flyfps_mouse_finer_low = 85; + public int flyfps_mouse_finer_low + { + get { return _flyfps_mouse_finer_low; } + set + { + _flyfps_mouse_finer_low = value; + OnPropertyChanged("flyfps_mouse_finer_low"); + } + } + + private int _flyfps_mouse_finer_high = 75; + public int flyfps_mouse_finer_high + { + get { return _flyfps_mouse_finer_high; } + set + { + _flyfps_mouse_finer_high = value; + OnPropertyChanged("flyfps_mouse_finer_high"); + } + } + + private int _flyfps_mouse_finer_threshold = 5; + public int flyfps_mouse_finer_threshold + { + get { return _flyfps_mouse_finer_threshold; } + set + { + _flyfps_mouse_finer_threshold = value; + OnPropertyChanged("flyfps_mouse_finer_threshold"); + } + } + + private double _flyfps_out_bound_decceleration = 10; + public double flyfps_out_bound_decceleration + { + get { return _flyfps_out_bound_decceleration; } + set + { + _flyfps_out_bound_decceleration = value; + OnPropertyChanged("flyfps_out_bound_decceleration"); + } + } + + private double _flyfps_return_bound_acceleration = 5; + public double flyfps_return_bound_acceleration + { + get { return _flyfps_return_bound_acceleration; } + set + { + _flyfps_return_bound_acceleration = value; + OnPropertyChanged("flyfps_return_bound_acceleration"); + } + } + + private int _flyfps_main_buffer = 1; + public int flyfps_main_buffer + { + get { return _flyfps_main_buffer; } + set + { + _flyfps_main_buffer = value; + OnPropertyChanged("flyfps_main_buffer"); + } + } + + private double _flyfps_main_sensitivity = 0.25; + public double flyfps_main_sensitivity + { + get { return _flyfps_main_sensitivity; } + set + { + _flyfps_main_sensitivity = value; + OnPropertyChanged("flyfps_main_sensitivity"); + } + } + + private double _flyfps_main_decceleration_low = 4.5; + public double flyfps_main_decceleration_low + { + get { return _flyfps_main_decceleration_low; } + set + { + _flyfps_main_decceleration_low = value; + OnPropertyChanged("flyfps_main_decceleration_low"); + } + } + + private double _flyfps_main_decceleration_high = 10; + public double flyfps_main_decceleration_high + { + get { return _flyfps_main_decceleration_high; } + set + { + _flyfps_main_decceleration_high = value; + OnPropertyChanged("flyfps_main_decceleration_high"); + } + } + + private double _flyfps_main_decceleration_threshold = 50; + public double flyfps_main_decceleration_threshold + { + get { return _flyfps_main_decceleration_threshold; } + set + { + _flyfps_main_decceleration_threshold = value; + OnPropertyChanged("flyfps_main_decceleration_threshold"); + } + } + + private double _flyfps_main_acceleration = 30; + public double flyfps_main_acceleration + { + get { return _flyfps_main_acceleration; } + set + { + _flyfps_main_acceleration = value; + OnPropertyChanged("flyfps_main_acceleration"); + } + } + + private double _flyfps_main_acceleration_threshold = 50; + public double flyfps_main_acceleration_threshold + { + get { return _flyfps_main_acceleration_threshold; } + set + { + _flyfps_main_acceleration_threshold = value; + OnPropertyChanged("flyfps_main_acceleration_threshold"); + } + } + + private double _flyfps_main_acceleration_finer = 85; + public double flyfps_main_acceleration_finer + { + get { return _flyfps_main_acceleration_finer; } + set + { + _flyfps_main_acceleration_finer = value; + OnPropertyChanged("flyfps_main_acceleration_finer"); + } + } + + private bool _flyfps_left_button_fine = true; + public bool flyfps_left_button_fine + { + get { return _flyfps_left_button_fine; } + set + { + _flyfps_left_button_fine = value; + OnPropertyChanged("flyfps_left_button_fine"); + } + } + + private double _flyfps_fine_sensitivity = 0.25; + public double flyfps_fine_sensitivity + { + get { return _flyfps_fine_sensitivity; } + set + { + _flyfps_fine_sensitivity = value; + OnPropertyChanged("flyfps_fine_sensitivity"); + } + } + + private double _flyfps_fine_decceleration = 5; + public double flyfps_fine_decceleration + { + get { return _flyfps_fine_decceleration; } + set + { + _flyfps_fine_decceleration = value; + OnPropertyChanged("flyfps_fine_decceleration"); + } + } + + private double _flyfps_fine_acceleration = 5; + public double flyfps_fine_acceleration + { + get { return _flyfps_fine_acceleration; } + set + { + _flyfps_fine_acceleration = value; + OnPropertyChanged("flyfps_fine_acceleration"); + } + } + + private int _flyfps_mouse_smooth_buffer = 10; + public int flyfps_mouse_smooth_buffer + { + get { return _flyfps_mouse_smooth_buffer; } + set + { + _flyfps_mouse_smooth_buffer = value; + OnPropertyChanged("flyfps_mouse_smooth_buffer"); + } + } + + private double _flyfps_mouse_forward = 0; + public double flyfps_mouse_forward + { + get { return _flyfps_mouse_forward; } + set + { + _flyfps_mouse_forward = value; + OnPropertyChanged("flyfps_mouse_forward"); + } + } + + private double _flyfps_mouse_forward_turn_on_threshold = 25; + public double flyfps_mouse_forward_turn_on_threshold + { + get { return _flyfps_mouse_forward_turn_on_threshold; } + set + { + _flyfps_mouse_forward_turn_on_threshold = value; + OnPropertyChanged("flyfps_mouse_forward_turn_on_threshold"); + } + } + + private double _flyfps_mouse_forward_decceleration = 5; + public double flyfps_mouse_forward_decceleration + { + get { return _flyfps_mouse_forward_decceleration; } + set + { + _flyfps_mouse_forward_decceleration = value; + OnPropertyChanged("flyfps_mouse_forward_decceleration"); + } + } + + private double _flyfps_extra_turn_sensitivity = 0.0; + public double flyfps_extra_turn_sensitivity + { + get { return _flyfps_extra_turn_sensitivity; } + set + { + _flyfps_extra_turn_sensitivity = value; + OnPropertyChanged("flyfps_extra_turn_sensitivity"); + } + } + + private double _flyfps_extra_turn_deadzone = 20; + public double flyfps_extra_turn_deadzone + { + get { return _flyfps_extra_turn_deadzone; } + set + { + _flyfps_extra_turn_deadzone = value; + OnPropertyChanged("flyfps_extra_turn_deadzone"); + } + } + + private double _flyfps_extra_turn_easein = 40; + public double flyfps_extra_turn_easein + { + get { return _flyfps_extra_turn_easein; } + set + { + _flyfps_extra_turn_easein = value; + OnPropertyChanged("flyfps_extra_turn_easein"); + } + } + + private double _flyfps_border_turn_speed_x = 0; + public double flyfps_border_turn_speed_x + { + get { return _flyfps_border_turn_speed_x; } + set + { + _flyfps_border_turn_speed_x = value; + OnPropertyChanged("flyfps_border_turn_speed"); + } + } + + private double _flyfps_border_turn_speed_y = 0; + public double flyfps_border_turn_speed_y + { + get { return _flyfps_border_turn_speed_y; } + set + { + _flyfps_border_turn_speed_y = value; + OnPropertyChanged("flyfps_border_turn_speed_y"); + } + } + + private double _flyfps_auto_turn_speed_x = 0; + public double flyfps_auto_turn_speed_x + { + get { return _flyfps_auto_turn_speed_x; } + set + { + _flyfps_auto_turn_speed_x = value; + OnPropertyChanged("flyfps_auto_turn_speed_x"); + } + } + + private double _flyfps_auto_turn_speed_y = 0; + public double flyfps_auto_turn_speed_y + { + get { return _flyfps_auto_turn_speed_y; } + set + { + _flyfps_auto_turn_speed_y = value; + OnPropertyChanged("flyfps_auto_turn_speed_y"); + } + } + + private double _flyfps_main_sensitivity_y = 0; + public double flyfps_main_sensitivity_y + { + get { return _flyfps_main_sensitivity_y; } + set + { + _flyfps_main_sensitivity_y = value; + OnPropertyChanged("flyfps_main_sensitivity_y"); + } + } + + private double _flyfps_main_acceleration_y = 0; + public double flyfps_main_acceleration_y + { + get { return _flyfps_main_acceleration_y; } + set + { + _flyfps_main_acceleration_y = value; + OnPropertyChanged("flyfps_main_acceleration_y"); + } + } + + private double _flyfps_fine_sensitivity_y = 0; + public double flyfps_fine_sensitivity_y + { + get { return _flyfps_fine_sensitivity_y; } + set + { + _flyfps_fine_sensitivity_y = value; + OnPropertyChanged("flyfps_fine_sensitivity_y"); + } + } + + private double _flyfps_fine_acceleration_y = 0; + public double flyfps_fine_acceleration_y + { + get { return _flyfps_fine_acceleration_y; } + set + { + _flyfps_fine_acceleration_y = value; + OnPropertyChanged("flyfps_fine_acceleration_y"); + } + } + + private double _flyfps_mouse_forward_y = 0; + public double flyfps_mouse_forward_y + { + get { return _flyfps_mouse_forward_y; } + set + { + _flyfps_mouse_forward_y = value; + OnPropertyChanged("flyfps_mouse_forward_y"); + } + } + + private double _flyfps_extra_turn_sensitivity_y = 0; + public double flyfps_extra_turn_sensitivity_y + { + get { return _flyfps_extra_turn_sensitivity_y; } + set + { + _flyfps_extra_turn_sensitivity_y = value; + OnPropertyChanged("flyfps_extra_turn_sensitivity_y"); + } + } + + private bool _flyfps_debug = false; + public bool flyfps_debug + { + get { return _flyfps_debug; } + set + { + _flyfps_debug = value; + OnPropertyChanged("flyfps_debug"); + } + } + + private int _touch_touchTapThreshold = 40; + public int touch_touchTapThreshold + { + get { return _touch_touchTapThreshold; } + set + { + _touch_touchTapThreshold = value; + OnPropertyChanged("touch_touchTapThreshold"); + } + } + + private int _touch_edgeGestureHelperMargins = 30; + public int touch_edgeGestureHelperMargins + { + get { return _touch_edgeGestureHelperMargins; } + set + { + _touch_edgeGestureHelperMargins = value; + OnPropertyChanged("touch_edgeGestureHelperMargins"); + } + } + + private int _touch_edgeGestureHelperRelease = 60; + public int touch_edgeGestureHelperRelease + { + get { return _touch_edgeGestureHelperRelease; } + set + { + _touch_edgeGestureHelperRelease = value; + OnPropertyChanged("touch_edgeGestureHelperRelease"); + } + } + + private int _xinput_rumbleThreshold_big = 200; + public int xinput_rumbleThreshold_big + { + get { return _xinput_rumbleThreshold_big; } + set + { + _xinput_rumbleThreshold_big = value; + OnPropertyChanged("xinput_rumbleThreshold_big"); + } + } + + private int _xinput_rumbleThreshold_small = 200; + public int xinput_rumbleThreshold_small + { + get { return _xinput_rumbleThreshold_small; } + set + { + _xinput_rumbleThreshold_small = value; + OnPropertyChanged("xinput_rumbleThreshold_small"); + } + } + + private static string SETTINGS_FILENAME = System.AppDomain.CurrentDomain.BaseDirectory + "settings.json"; + + private static Settings defaultInstance; + + public static Settings Default + { + get + { + if (defaultInstance == null) + { + defaultInstance = Load(); + } + return defaultInstance; + } + } + + private static Settings Load() + { + Settings result; + try + { + result = JsonConvert.DeserializeObject(File.ReadAllText(SETTINGS_FILENAME)); + } + catch //If anything goes wrong, just load default values + { + result = new Settings(); + } + + return result; + } + + public void Save() + { + File.WriteAllText(SETTINGS_FILENAME, JsonConvert.SerializeObject(Default, Formatting.Indented)); + } + + protected void OnPropertyChanged(string name) + { + PropertyChangedEventHandler handler = PropertyChanged; + if (handler != null) + { + handler(this, new PropertyChangedEventArgs(name)); + } + } + + } + +}