From 72f3603c86460c5715702c0a0f4419881bd8b05c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fil=C3=A1tz=20R=C3=B3bert?= Date: Wed, 12 Apr 2017 00:46:08 +0200 Subject: [PATCH 1/9] Add files via upload Added FlyFPS mode. --- README.md | 189 ++++++++++++++++++-------------------------------- Touchmote.sln | 174 ++++++++++++++++++++++------------------------ 2 files changed, 152 insertions(+), 211 deletions(-) diff --git a/README.md b/README.md index 11eb0e51..041ec5bf 100644 --- a/README.md +++ b/README.md @@ -1,128 +1,75 @@ -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. - -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++. - -Prerequisites +FLYFPS Mode Description ============== -1x Nintendo Wii Remote
-1x Wireless Wii Sensor Bar
-1x Bluetooth enabled computer with Windows 8 +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. +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) +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. +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. +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. -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
-How to build +IMPORTANT: ============== -*First install:*
-Microsoft Visual Studio 2013
-Direct X SDK - -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 +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: ============== -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 -============== - -**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. +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. +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) \ No newline at end of file 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 From 289a6306607bf48c67006d2915555ebb44cc209b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fil=C3=A1tz=20R=C3=B3bert?= Date: Wed, 12 Apr 2017 00:48:11 +0200 Subject: [PATCH 2/9] Add files via upload added FlyFPS mode --- D3DCursor/D3DCursor.vcxproj | 286 ++++++++++++++++++------------------ 1 file changed, 143 insertions(+), 143 deletions(-) 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 From 44053dcf128db6f3ad7bf28395a37547b3fbeffc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fil=C3=A1tz=20R=C3=B3bert?= Date: Wed, 12 Apr 2017 00:49:22 +0200 Subject: [PATCH 3/9] Add files via upload added FlyFPS mode --- WiiCPP/WiiCPP.vcxproj | 330 +++++++++++++++++++++--------------------- 1 file changed, 165 insertions(+), 165 deletions(-) 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 From a7c9ede4d908ad5ab0fa4cd5804c04b22c9609bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fil=C3=A1tz=20R=C3=B3bert?= Date: Wed, 12 Apr 2017 00:51:04 +0200 Subject: [PATCH 4/9] Add files via upload added FlyFPS mode --- .../WiiProvider/SpatiotemporalClassifier.cs | 1645 +++++++++-------- 1 file changed, 830 insertions(+), 815 deletions(-) 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; + } + } +} From b80d869bf68f60f862db44c367674eee190d9807 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fil=C3=A1tz=20R=C3=B3bert?= Date: Wed, 12 Apr 2017 00:53:25 +0200 Subject: [PATCH 5/9] Add files via upload added FlyFPS mode --- WiiTUIO/KeymapConfig/KeymapDatabase.cs | 1395 ++++++++++++------------ 1 file changed, 698 insertions(+), 697 deletions(-) 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; + } + } +} From 578eba93ce733c3ff00ab2f5b597c5d343d3d057 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fil=C3=A1tz=20R=C3=B3bert?= Date: Wed, 12 Apr 2017 00:54:37 +0200 Subject: [PATCH 6/9] Add files via upload added FlyFPS mode --- WiiTUIO/Output/Handlers/MouseHandler.cs | 841 +++++++++++++++++++----- 1 file changed, 664 insertions(+), 177 deletions(-) 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 + } +} From bd5bb8ffecba44ef0cf8684b8ffd959a45df4a53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fil=C3=A1tz=20R=C3=B3bert?= Date: Wed, 12 Apr 2017 00:55:31 +0200 Subject: [PATCH 7/9] Add files via upload added FlyFPS mode --- WiiTUIO/Properties/Settings.cs | 1377 +++++++++++++++++++++----------- 1 file changed, 892 insertions(+), 485 deletions(-) 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)); + } + } + + } + +} From 38637cc0e1249a7aac2cf35b63ef3d2673bcd990 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fil=C3=A1tz=20R=C3=B3bert?= Date: Wed, 12 Apr 2017 01:12:49 +0200 Subject: [PATCH 8/9] Add files via upload added FlyFPS mode --- README.md | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 041ec5bf..10c3d78d 100644 --- a/README.md +++ b/README.md @@ -9,10 +9,14 @@ 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. + 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) + 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. + 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. + 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. @@ -20,56 +24,101 @@ Try setup in settings.json in touchmote directory. Just increasing values step b IMPORTANT: ============== 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. + 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) \ No newline at end of file +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) From f8ac7b3df1a281135860919be9bba88fe4132854 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fil=C3=A1tz=20R=C3=B3bert?= Date: Wed, 31 Jan 2018 14:11:05 +0100 Subject: [PATCH 9/9] Just an x64 release for peoples ;) --- TouchMotex64Release.zip | Bin 0 -> 283718 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 TouchMotex64Release.zip diff --git a/TouchMotex64Release.zip b/TouchMotex64Release.zip new file mode 100644 index 0000000000000000000000000000000000000000..8b6a434f681f4965ed24fe940054580711b567e0 GIT binary patch literal 283718 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%0D+V?n6$_dHq@?-(q15}qM`^BWx-#LZn_#CYk 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 w{!|_@U`5s$NseHOxk`7cgVD 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

YwF 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 literal 0 HcmV?d00001