HandheldCompanion icon indicating copy to clipboard operation
HandheldCompanion copied to clipboard

Gyro based on mouse control

Open CasperH2O opened this issue 3 years ago • 1 comments

Code proposal from Frank, as is currently implemented in the Gyro application.

Especially interesting features:

  • Additional gain rate multiplier when a certain button is pressed. When using below code with an FPS that has a scope option, a lot of games reduce the sensitivity, this can then be overcome with this extra multiplier
  • Very smooth motion!
//鼠标操作. mouse
        [System.Runtime.InteropServices.DllImport("user32")]
        private static extern int mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);
        //移动鼠标 
        const int MOUSEEVENTF_MOVE = 0x0001;
        //模拟鼠标左键按下 
        const int MOUSEEVENTF_LEFTDOWN = 0x0002;
        //模拟鼠标左键抬起 
        const int MOUSEEVENTF_LEFTUP = 0x0004;
        //模拟鼠标右键按下 
        const int MOUSEEVENTF_RIGHTDOWN = 0x0008;
        //模拟鼠标右键抬起 
        const int MOUSEEVENTF_RIGHTUP = 0x0010;
        //模拟鼠标中键按下 
        const int MOUSEEVENTF_MIDDLEDOWN = 0x0020;
        //模拟鼠标中键抬起 
        const int MOUSEEVENTF_MIDDLEUP = 0x0040;
        //标示是否采用绝对坐标 
        const int MOUSEEVENTF_ABSOLUTE = 0x8000;
        //模拟鼠标滚轮滚动操作,必须配合dwData参数
        const int MOUSEEVENTF_WHEEL = 0x0800;


        public static void MoveMouse(int a, int b)
        {
            mouse_event(MOUSEEVENTF_MOVE, a, b, 0, 0);
        }



        double[] mouseBuffer = new double[3]; //used for slowly move which gyro data less than 1
        public void mouseMove(double[] gyro) //gyro is raw data from gyrometer
        {
            if (setting.simulateType == Settings.SIMULATETYPE.Mouse && setting.gyroEnabled) 
            {
                if (getHotkeyTriggerState()) //check enabled button pressed or hotkey pressed
                {
                    if (Math.Abs(gyro[0]) >= setting.mouseThreshold || Math.Abs(gyro[1]) >= setting.mouseThreshold || Math.Abs(gyro[2]) >= setting.mouseThreshold) //check threshold, setting.mouseThreshold's default value is 1
                    {

                        double gainRate = 1.0;
                        if (selectedIndex >= 0 && PhysicalController[selectedIndex].isConnected() && PhysicalController[selectedIndex].HasGainButtonPressed(setting.gainButton)) //check if gain button pressed which supplies a multiplier by mouseRate
                        {
                            gainRate = setting.gainRate;
                        }

                        if (Math.Abs(gyro[0]) >= setting.mouseThreshold)
                        {
                            gyro[0] = gyro[0] * setting.mouseRate * gainRate / 20;
                            if( Math.Abs(gyro[0]) < 1 )
                            {
                                mouseBuffer[0] += gyro[0];
                                if(Math.Abs(mouseBuffer[0]) >= setting.mouseThreshold)
                                {
                                    if( gyro[0] > 0 )
                                    {
                                        gyro[0] += 1;
                                    } 
                                    else
                                    {
                                        gyro[0] -= 1;
                                    }
                                    mouseBuffer[0] = 0;
                                }
                            } else
                            {
                                mouseBuffer[0] = 0;
                            }
                        }
                        else
                        {
                            gyro[0] = 0;
                        }

                        if (Math.Abs(gyro[1]) >= setting.mouseThreshold)
                        {
                            gyro[1] = gyro[1] * setting.mouseRate * gainRate / 20;
                            if (Math.Abs(gyro[1]) < 1)
                            {
                                mouseBuffer[1] += gyro[1];
                                if ( Math.Abs(mouseBuffer[1]) >= setting.mouseThreshold)
                                {
                                    if (gyro[1] > 0)
                                    {
                                        gyro[1] += 1;
                                    }
                                    else
                                    {
                                        gyro[1] -= 1;
                                    }
                                    mouseBuffer[1] = 0;
                                }
                            }
                            else
                            {
                                mouseBuffer[1] = 0;
                            }
                        }
                        else
                        {
                            gyro[1] = 0;
                        }

                        if (Math.Abs(gyro[2]) >= setting.mouseThreshold)
                        {
                            gyro[2] = gyro[2] * setting.mouseRate * gainRate / 20;
                            if (Math.Abs(gyro[2]) < 1)
                            {
                                mouseBuffer[2] += gyro[2];
                                if ( Math.Abs(mouseBuffer[2]) >= setting.mouseThreshold )
                                {
                                    if (gyro[2] > 0)
                                    {
                                        gyro[2] += 1;
                                    }
                                    else
                                    {
                                        gyro[2] -= 1;
                                    }
                                    mouseBuffer[2] = 0;
                                }
                            }
                            else
                            {
                                mouseBuffer[2] = 0;
                            }
                        }
                        else
                        {
                            gyro[2] = 0;
                        }

                        if (setting.axisSelectType == Settings.AXISTYPE.XY) //different axis
                        {
                            MoveMouse((int)(setting.XReverse * setting.XRate * gyro[1]), (int)(-setting.YReverse * setting.YRate * gyro[0]));
                        }
                        else if (setting.axisSelectType == Settings.AXISTYPE.XZ)
                        {
                            MoveMouse((int)(setting.XReverse * setting.XRate * gyro[2]), (int)(-setting.YReverse * setting.YRate * gyro[0]));
                        }
                    }
                }
            }
        }
       ```

CasperH2O avatar Jun 27 '22 14:06 CasperH2O

This is really cool

mrjojo245 avatar Jul 26 '22 17:07 mrjojo245

Yeah, I'd love this as well. I like to use gamepad + mouse for FPS games (on my steamdeck). And I love to mix the gyro into the mouse so I can use the trackpads for rough movement, and the gyro for exact aiming.

dragonfax avatar May 02 '23 03:05 dragonfax

It is with great pleasure I can say that after more then a year this feature is included in upcoming release 0.18. Mind you, it will probably require additional tweaks and settings etc, but it works.

CasperH2O avatar Aug 16 '23 10:08 CasperH2O