From a933eae0a92b29078e71936e8d465cb5af3ffba9 Mon Sep 17 00:00:00 2001 From: mika-n Date: Sat, 17 Nov 2018 01:41:21 +0200 Subject: [PATCH 01/66] New "360 degree gyro steering wheel emulation" functionality. This works best if the DS4 controller is mounted on a "DoItYourself steering wheel rig" (ie. controller attached at a tip of a plastic or wooden pipe which acts as a "steering shaft". This way the controller turns around like a steering wheel and gyro sensor values are more consistent). At this point there is no GUI to enable this, so you should edit a profile XML file (fex default.xml profile) with Notepad and add LXPos entry. Accepted values are None, LXPos, LYPos, RXPos, RYPos) which indicates which X360 axis is used for steering wheel values (ie. gyro tilt converted as steering wheel turning range values). The normal behaviour of this axis should be set as "unmapped" to avoid conflicting values. If steering wheel axis is LX then LY axis is still available for other purposes. --- DS4Windows/DS4Control/Mapping.cs | 261 ++++++++++++++++++++++++++++ DS4Windows/DS4Control/ScpUtil.cs | 142 ++++++++++++++- DS4Windows/DS4Control/X360Device.cs | 25 ++- DS4Windows/DS4Library/DS4Device.cs | 28 +++ DS4Windows/DS4Library/DS4State.cs | 4 + 5 files changed, 455 insertions(+), 5 deletions(-) diff --git a/DS4Windows/DS4Control/Mapping.cs b/DS4Windows/DS4Control/Mapping.cs index 32671b7..cfad5a4 100644 --- a/DS4Windows/DS4Control/Mapping.cs +++ b/DS4Windows/DS4Control/Mapping.cs @@ -6,6 +6,8 @@ using System.Threading.Tasks; using System.Diagnostics; using static DS4Windows.Global; +using System.Drawing; // Point struct + namespace DS4Windows { public class Mapping @@ -1648,6 +1650,9 @@ namespace DS4Windows } } + if (getSASteeringWheelEmulationAxis(device) != DS4Controls.None) + MappedState.SASteeringWheelEmulationUnit = Mapping.Scale360degreeGyroAxis(device, eState, ctrl); + calculateFinalMouseMovement(ref tempMouseDeltaX, ref tempMouseDeltaY, out mouseDeltaX, out mouseDeltaY); if (mouseDeltaX != 0 || mouseDeltaY != 0) @@ -3773,5 +3778,261 @@ namespace DS4Windows fieldMap.buttons[controlNum] = false; } } + + // BEGIN: SixAxis steering wheel emulation logic + + // "In-game" calibration process: + // TODO: Launching a calibration process should probably be a special action which allows multiple key bindings to launch a specific task. + // - Place controller at "steering wheel center" position and press DS4 Option button to start the calibration (Profile should have "SASteeringWheelEmulationAxis" option set to LXPos, LYPos, RXPos or RYPos value). + // - Hold the controller still for a while and wait until red lightbar turns to blinking yellow (center point calibrated) + // - Turn the controller at 90 degree left or right position and hold still for few seconds and wait until lightbar turns to blinking light blue (two points calibrated) + // - Turn the controller at 90 degree position on the opposite side (but do it by going through 0 degree center position. Don't go through 180deg mark). Wait until lighbar turns to green (three points calibrated) + // - Now you can check the calibratio by turning the wheel and see when the green lightbar starts to blink (it should blink at those three calibrated positions). + // - Press DS4 Options button to accept the calibration (result is saved to ControllerConfigs.xml xml file in AppData folder). + // + // 0 = None of the anchors calibrated yet. Hold controller still at "wheel center position" and wait until lightbar turns from constant red to flashing yellow color + // 1 = one anchor calibrated (The first calibration point should always be the center position) + // 2 = two anchors calibrated (center and 90Right or 90Left depending on which way user turn the wheel after the first center calibration point) + // 3 = all three anchor points calibrated (center, 90Right, 90Left). Good to go. User can check calibration by turning the wheel and checking when the green lightbar blinks. If happy then pressing Options btn accepts the calibration. + private static readonly DS4Color calibrationColor_0 = new DS4Color { red = 0xA0, green = 0x00, blue = 0x00 }; + private static readonly DS4Color calibrationColor_1 = new DS4Color { red = 0xFF, green = 0xFF, blue = 0x00 }; + private static readonly DS4Color calibrationColor_2 = new DS4Color { red = 0x00, green = 0x50, blue = 0x50 }; + private static readonly DS4Color calibrationColor_3 = new DS4Color { red = 0x00, green = 0xC0, blue = 0x00 }; + + private static DateTime latestDebugMsgTime; + private static void LogToGuiSACalibrationDebugMsg(string data) + { + // Print debug calibration log messages only once per 2 secs to avoid flooding the log receiver + DateTime curTime = DateTime.Now; + if (((TimeSpan)(curTime - latestDebugMsgTime)).TotalSeconds > 2) + { + latestDebugMsgTime = curTime; + AppLogger.LogToGui(data, false); + } + } + + // Return number of bits set in a value + protected static int CountNumOfSetBits(int bitValue) + { + int count = 0; + while (bitValue != 0) + { + count++; + bitValue &= (bitValue - 1); + } + return count; + } + + // Calculate and return the angle of the controller as -180...0...+180 value. + // TODO: Support >360 degree turn range by adding "lap counter" when wheel is rotated full rounds left or right.At the moment this logic supports only 360 degree turn range. + protected static Int32 CalculateControllerAngle(int gyroAccelX, int gyroAccelZ, DS4Device controller) + { + Int32 result; + + if (Math.Abs(gyroAccelX - controller.wheelCenterPoint.X) <= 1 && Math.Abs(gyroAccelZ - controller.wheelCenterPoint.Y) <= 1) + { + // When the current gyro position is "close enough" the wheel center point then no need to go through the hassle of calculating an angle + result = 0; + } + else + { + // Calculate two vectors based on "circle center" (ie. circle represents the 360 degree wheel turn and wheelCenterPoint and currentPosition vectors both start from circle center). + // To improve accuracy both left and right turns use a decicated calibration "circle" because DS4 gyro and DoItYourselfWheelRig may return slightly different SA sensor values depending on the tilt direction (well, only one or two degree difference so nothing major). + Point vectorAB; + Point vectorCD; + + if (gyroAccelX >= controller.wheelCenterPoint.X) + { + // "DS4 gyro wheel" tilted to right + vectorAB = new Point(controller.wheelCenterPoint.X - controller.wheelCircleCenterPointRight.X, controller.wheelCenterPoint.Y - controller.wheelCircleCenterPointRight.Y); + vectorCD = new Point(gyroAccelX - controller.wheelCircleCenterPointRight.X, gyroAccelZ - controller.wheelCircleCenterPointRight.Y); + } + else + { + // "DS4 gyro wheel" tilted to left + vectorAB = new Point(controller.wheelCenterPoint.X - controller.wheelCircleCenterPointLeft.X, controller.wheelCenterPoint.Y - controller.wheelCircleCenterPointLeft.Y); + vectorCD = new Point(gyroAccelX - controller.wheelCircleCenterPointLeft.X, gyroAccelZ - controller.wheelCircleCenterPointLeft.Y); + } + + // Calculate dot product and magnitude of vectors (center vector and the current tilt vector) + double dotProduct = vectorAB.X * vectorCD.X + vectorAB.Y * vectorCD.Y; + double magAB = Math.Sqrt(vectorAB.X * vectorAB.X + vectorAB.Y * vectorAB.Y); + double magCD = Math.Sqrt(vectorCD.X * vectorCD.X + vectorCD.Y * vectorCD.Y); + + // Calculate angle between vectors and convert radian to degrees + double angle = Math.Acos(dotProduct / (magAB * magCD)); + result = Convert.ToInt32(Math.Round(angle * (180.0 / Math.PI))); + + // Left turn is -180..0 and right turn 0..180 degrees + if (gyroAccelX < controller.wheelCenterPoint.X) result = -result; + + // Just to be sure.. Probably not needed. TODO: Add support for 360/720/900 turn ranges by counting "laps" how many times the steering wheel is turned around + result = ClampInt(-180, result, 180); + } + + return result; + } + + protected static Int32 Scale360degreeGyroAxis(int device, /*DS4State state,*/ DS4StateExposed exposedState, ControlService ctrl) + { + unchecked + { + DS4Device controller; + DS4State currentDeviceState; + + int gyroAccelX, gyroAccelZ; + int result; + + //controller = Program.rootHub.DS4Controllers[device]; + controller = ctrl.DS4Controllers[device]; + if (controller == null) return 0; + + currentDeviceState = controller.getCurrentStateRef(); + + gyroAccelX = exposedState.getAccelX(); + gyroAccelZ = exposedState.getAccelZ(); + + // If DS4 Options btn is pressed and the previous re-calibration was done more than 2 secs ago (avoids repeated "calibration" loops if user holds down the Option btn too long) then re-calibrate the gyro wheel emulation. + // TODO. Maybe here should be logic to enter calibration process only if Options btn is hold down minimum of 3 secs? This way Option btn can be re-mapped to do other things without kicking on re-calibration everytime it is pressed. + if (currentDeviceState.Options && ((TimeSpan)(DateTime.Now - controller.wheelPrevRecalibrateTime)).TotalSeconds > 2) + { + if (controller.WheelRecalibrateActive == false) + { + AppLogger.LogToGui($"Controller {ctrl.x360Bus.FirstController + device} activated re-calibration of motion steering wheel emulation", false); + + controller.WheelRecalibrateActive = true; + + // Clear existing calibration value and use current position as "center" point. + // This initial center value may be off-center because of shaking the controller while button was pressed. The value will be overriden with correct value once controller is stabilized and hold still few secs at the center point + controller.wheelCenterPoint.X = gyroAccelX; + controller.wheelCenterPoint.Y = gyroAccelZ; + controller.wheel90DegPointRight.X = gyroAccelX + 25; + controller.wheel90DegPointLeft.X = gyroAccelX - 25; + + // Clear bitmask for calibration points. All three calibration points need to be set before re-calibration process is valid + controller.wheelCalibratedAxisBitmask = DS4Device.WheelCalibrationPoint.None; + } + else + { + AppLogger.LogToGui($"Controller {ctrl.x360Bus.FirstController + device} completed steering wheel calibration. center=({controller.wheelCenterPoint.X}, {controller.wheelCenterPoint.Y}) 90L=({controller.wheel90DegPointLeft.X}, {controller.wheel90DegPointLeft.Y}) 90R=({controller.wheel90DegPointRight.X}, {controller.wheel90DegPointRight.Y})", false); + + controller.WheelRecalibrateActive = false; + + // If any of the calibration points (center, left 90deg, right 90deg) are missing then reset back to default calibration values + if (((controller.wheelCalibratedAxisBitmask & DS4Device.WheelCalibrationPoint.All) == DS4Device.WheelCalibrationPoint.All)) + Global.SaveControllerConfigs(controller); + else + controller.wheelCenterPoint.X = controller.wheelCenterPoint.Y = 0; + + // Reset lightbar back to normal color + DS4LightBar.forcelight[device] = false; + DS4LightBar.forcedFlash[device] = 0; + controller.LightBarColor = Global.getMainColor(device); + DS4LightBar.updateLightBar(controller, device); + } + + controller.wheelPrevRecalibrateTime = DateTime.Now; + } + + if (controller.WheelRecalibrateActive) + { + // Auto calibrate 90deg left/right positions (these values may change over time because gyro/accel sensor values are not "precise mathematics", so user can trigger calibration even in mid-game sessions by pressing DS4 Options btn), + // but make sure controller is stable enough to avoid misaligments because of hard shaking (check velocity of gyro axis) + if (Math.Abs(/*state*/ currentDeviceState.Motion.angVelPitch) < 0.5 && Math.Abs(currentDeviceState.Motion.angVelYaw) < 0.5 && Math.Abs(currentDeviceState.Motion.angVelRoll) < 0.5) + { + if (controller.wheelCalibratedAxisBitmask == DS4Device.WheelCalibrationPoint.None) + { + // Wait few secs after re-calibration button was pressed. Hold controller still at center position and don't shake it too much until red lightbar turns to yellow. + if (((TimeSpan)(DateTime.Now - controller.wheelPrevRecalibrateTime)).TotalSeconds >= 3) + { + controller.wheelCenterPoint.X = gyroAccelX; + controller.wheelCenterPoint.Y = gyroAccelZ; + + controller.wheelCalibratedAxisBitmask |= DS4Device.WheelCalibrationPoint.Center; + } + } + else if (controller.wheel90DegPointRight.X < gyroAccelX) + { + controller.wheel90DegPointRight.X = gyroAccelX; + controller.wheel90DegPointRight.Y = gyroAccelZ; + controller.wheelCircleCenterPointRight.X = controller.wheelCenterPoint.X; + controller.wheelCircleCenterPointRight.Y = controller.wheel90DegPointRight.Y; + + controller.wheelCalibratedAxisBitmask |= DS4Device.WheelCalibrationPoint.Right90; + } + else if (controller.wheel90DegPointLeft.X > gyroAccelX) + { + controller.wheel90DegPointLeft.X = gyroAccelX; + controller.wheel90DegPointLeft.Y = gyroAccelZ; + controller.wheelCircleCenterPointLeft.X = controller.wheelCenterPoint.X; + controller.wheelCircleCenterPointLeft.Y = controller.wheel90DegPointLeft.Y; + + controller.wheelCalibratedAxisBitmask |= DS4Device.WheelCalibrationPoint.Left90; + } + } + + // Show lightbar color feedback how the calibration process is proceeding. + // red / yellow / blue / green = No calibration anchors/one anchor/two anchors/three anchors calibrated (center, 90DegLeft, 90DegRight) + // Blinking led = Controller is tilted at the current calibration point (or calibration routine just set a new anchor point) + // TODO: device num to flash led idx (use red for center calibrated, yellow for one 90deg and green for both 90deg calibration and then reset back to normal led) + int bitsSet = CountNumOfSetBits((int)controller.wheelCalibratedAxisBitmask); + if (bitsSet >= 3) DS4LightBar.forcedColor[device] = calibrationColor_3; + else if (bitsSet == 2) DS4LightBar.forcedColor[device] = calibrationColor_2; + else if (bitsSet == 1) DS4LightBar.forcedColor[device] = calibrationColor_1; + else DS4LightBar.forcedColor[device] = calibrationColor_0; + + result = CalculateControllerAngle(gyroAccelX, gyroAccelZ, controller); + if (bitsSet >= 1 && (Math.Abs(result) <= 1 || (Math.Abs(result) >= 88 && Math.Abs(result) <= 92) || Math.Abs(result) >= 178)) DS4LightBar.forcedFlash[device] = 2; + else DS4LightBar.forcedFlash[device] = 0; + + DS4LightBar.forcelight[device] = true; + //DS4LightBar.updateLightBar(controller, device); + + LogToGuiSACalibrationDebugMsg($"Calibration values ({gyroAccelX}, {gyroAccelZ}) angle={result}\n"); + + // Return center wheel position while gyro is calibrated, not the calculated angle + return 0; + } + + + // If calibration values are missing then use "educated guesses" about good starting values. + // TODO. Use pre-calibrated default values from configuration file. + if (controller.wheelCenterPoint.IsEmpty) + { + if (!Global.LoadControllerConfigs(controller)) + { + AppLogger.LogToGui($"Controller {ctrl.x360Bus.FirstController + device} motion steering wheel calibration data missing. It is recommended to run steering wheel calibration process by pressing DS4 Options button. Using estimated values until the controller is calibrated at least once.", false); + + controller.wheelCenterPoint.X = gyroAccelX; + controller.wheelCenterPoint.Y = gyroAccelZ; + + controller.wheel90DegPointRight.X = controller.wheelCenterPoint.X + 113; // 113; + controller.wheel90DegPointRight.Y = controller.wheelCenterPoint.Y + 110; // 110; + + controller.wheel90DegPointLeft.X = controller.wheelCenterPoint.X - 127; // -127; + controller.wheel90DegPointLeft.Y = controller.wheel90DegPointRight.Y; // 2; + } + + controller.wheelCircleCenterPointRight.X = controller.wheelCenterPoint.X; + controller.wheelCircleCenterPointRight.Y = controller.wheel90DegPointRight.Y; + controller.wheelCircleCenterPointLeft.X = controller.wheelCenterPoint.X; + controller.wheelCircleCenterPointLeft.Y = controller.wheel90DegPointLeft.Y; + + AppLogger.LogToGui($"Controller {ctrl.x360Bus.FirstController + device} steering wheel emulation calibration values. center=({controller.wheelCenterPoint.X}, {controller.wheelCenterPoint.Y}) 90L=({controller.wheel90DegPointLeft.X}, {controller.wheel90DegPointLeft.Y}) 90R=({controller.wheel90DegPointRight.X}, {controller.wheel90DegPointRight.Y})", false); + controller.wheelPrevRecalibrateTime = DateTime.Now; + } + + result = CalculateControllerAngle(gyroAccelX, gyroAccelZ, controller); + + // Keep outputting debug data 30secs after the latest re-calibration event (user can check these values from the log screen of DS4Windows GUI) + //if (((TimeSpan)(DateTime.Now - prevRecalibrateTime)).TotalSeconds < 30) + // LogToGuiSACalibrationDebugMsg($"DEBUG gyro=({gyroAccelX}, {gyroAccelZ}) angle={result}"); + + // Scale input to a raw x360 thumbstick output scale + return (((result - (-180)) * (32767 - (-32768))) / (180 - (-180))) + (-32768); + } + } + // END: SixAxis steering wheel emulation logic + } } diff --git a/DS4Windows/DS4Control/ScpUtil.cs b/DS4Windows/DS4Control/ScpUtil.cs index 6959f53..7e3e3a1 100644 --- a/DS4Windows/DS4Control/ScpUtil.cs +++ b/DS4Windows/DS4Control/ScpUtil.cs @@ -270,6 +270,7 @@ namespace DS4Windows m_Config.m_Profile = appdatapath + "\\Profiles.xml"; m_Config.m_Actions = appdatapath + "\\Actions.xml"; m_Config.m_linkedProfiles = Global.appdatapath + "\\LinkedProfiles.xml"; + m_Config.m_controllerConfigs = Global.appdatapath + "\\ControllerConfigs.xml"; } /// @@ -717,6 +718,12 @@ namespace DS4Windows m_Config.SetSaTriggerCond(index, text); } + public static DS4Controls[] SASteeringWheelEmulationAxis => m_Config.sASteeringWheelEmulationAxis; + public static DS4Controls getSASteeringWheelEmulationAxis(int index) + { + return m_Config.sASteeringWheelEmulationAxis[index]; + } + public static int[][] TouchDisInvertTriggers => m_Config.touchDisInvertTriggers; public static int[] getTouchDisInvertTriggers(int index) { @@ -1284,6 +1291,30 @@ namespace DS4Windows return m_Config.LoadLinkedProfiles(); } + public static bool SaveControllerConfigs(DS4Device device = null) + { + if (device != null) + return m_Config.SaveControllerConfigsForDevice(device); + + for (int idx = 0; idx < ControlService.DS4_CONTROLLER_COUNT; idx++) + if (Program.rootHub.DS4Controllers[idx] != null) + m_Config.SaveControllerConfigsForDevice(Program.rootHub.DS4Controllers[idx]); + + return true; + } + + public static bool LoadControllerConfigs(DS4Device device = null) + { + if (device != null) + return m_Config.LoadControllerConfigsForDevice(device); + + for (int idx = 0; idx < ControlService.DS4_CONTROLLER_COUNT; idx++) + if (Program.rootHub.DS4Controllers[idx] != null) + m_Config.LoadControllerConfigsForDevice(Program.rootHub.DS4Controllers[idx]); + + return true; + } + private static byte applyRatio(byte b1, byte b2, double r) { if (r > 100.0) @@ -1382,6 +1413,7 @@ namespace DS4Windows public String m_Profile = Directory.GetParent(Assembly.GetExecutingAssembly().Location).FullName + "\\Profiles.xml"; public String m_Actions = Global.appdatapath + "\\Actions.xml"; public string m_linkedProfiles = Global.appdatapath + "\\LinkedProfiles.xml"; + public string m_controllerConfigs = Global.appdatapath + "\\ControllerConfigs.xml"; protected XmlDocument m_Xdoc = new XmlDocument(); // fifth value used for options, not fifth controller @@ -1481,6 +1513,7 @@ namespace DS4Windows public bool[] useSAforMouse = new bool[5] { false, false, false, false, false }; public string[] sATriggers = new string[5] { string.Empty, string.Empty, string.Empty, string.Empty, string.Empty }; public bool[] sATriggerCond = new bool[5] { true, true, true, true, true }; + public DS4Controls[] sASteeringWheelEmulationAxis = new DS4Controls[5] { DS4Controls.None, DS4Controls.None, DS4Controls.None, DS4Controls.None, DS4Controls.None }; public int[][] touchDisInvertTriggers = new int[5][] { new int[1] { -1 }, new int[1] { -1 }, new int[1] { -1 }, new int[1] { -1 }, new int[1] { -1 } }; public int[] lsCurve = new int[5] { 0, 0, 0, 0, 0 }; @@ -1727,6 +1760,7 @@ namespace DS4Windows XmlNode xmlUseSAforMouse = m_Xdoc.CreateNode(XmlNodeType.Element, "UseSAforMouse", null); xmlUseSAforMouse.InnerText = useSAforMouse[device].ToString(); Node.AppendChild(xmlUseSAforMouse); XmlNode xmlSATriggers = m_Xdoc.CreateNode(XmlNodeType.Element, "SATriggers", null); xmlSATriggers.InnerText = sATriggers[device].ToString(); Node.AppendChild(xmlSATriggers); XmlNode xmlSATriggerCond = m_Xdoc.CreateNode(XmlNodeType.Element, "SATriggerCond", null); xmlSATriggerCond.InnerText = SaTriggerCondString(sATriggerCond[device]); Node.AppendChild(xmlSATriggerCond); + XmlNode xmlSASteeringWheelEmulationAxis = m_Xdoc.CreateNode(XmlNodeType.Element, "SASteeringWheelEmulationAxis", null); xmlSASteeringWheelEmulationAxis.InnerText = sASteeringWheelEmulationAxis[device].ToString("G"); Node.AppendChild(xmlSASteeringWheelEmulationAxis); XmlNode xmlTouchDisInvTriggers = m_Xdoc.CreateNode(XmlNodeType.Element, "TouchDisInvTriggers", null); string tempTouchDisInv = string.Join(",", touchDisInvertTriggers[device]); @@ -2603,7 +2637,11 @@ namespace DS4Windows try { Item = m_Xdoc.SelectSingleNode("/" + rootname + "/SATriggerCond"); sATriggerCond[device] = SaTriggerCondValue(Item.InnerText); } catch { sATriggerCond[device] = true; missingSetting = true; } - try { + try { Item = m_Xdoc.SelectSingleNode("/" + rootname + "/SASteeringWheelEmulationAxis"); DS4Controls.TryParse(Item.InnerText, out sASteeringWheelEmulationAxis[device]); } + catch { sASteeringWheelEmulationAxis[device] = DS4Controls.None; missingSetting = true; } + + try + { Item = m_Xdoc.SelectSingleNode("/" + rootname + "/TouchDisInvTriggers"); string[] triggers = Item.InnerText.Split(','); int temp = -1; @@ -3467,6 +3505,107 @@ namespace DS4Windows return saved; } + public bool createControllerConfigs() + { + bool saved = true; + XmlDocument configXdoc = new XmlDocument(); + XmlNode Node; + + Node = configXdoc.CreateXmlDeclaration("1.0", "utf-8", string.Empty); + configXdoc.AppendChild(Node); + + Node = configXdoc.CreateComment(string.Format(" Controller config data. {0} ", DateTime.Now)); + configXdoc.AppendChild(Node); + + Node = configXdoc.CreateWhitespace("\r\n"); + configXdoc.AppendChild(Node); + + Node = configXdoc.CreateNode(XmlNodeType.Element, "Controllers", ""); + configXdoc.AppendChild(Node); + + try { configXdoc.Save(m_controllerConfigs); } + catch (UnauthorizedAccessException) { AppLogger.LogToGui("Unauthorized Access - Save failed to path: " + m_controllerConfigs, false); saved = false; } + + return saved; + } + + public bool LoadControllerConfigsForDevice(DS4Device device) + { + bool loaded = false; + + if (device == null) return false; + if (!File.Exists(m_controllerConfigs)) createControllerConfigs(); + + try + { + XmlDocument xmlDoc = new XmlDocument(); + xmlDoc.Load(m_controllerConfigs); + + XmlNode node = xmlDoc.SelectSingleNode("/Controllers/Controller[@Mac=\"" + device.getMacAddress() + "\"]"); + if (node != null) + { + Int32 intValue; + if (Int32.TryParse(node["wheelCenterPoint"].InnerText.Split(',')[0], out intValue)) device.wheelCenterPoint.X = intValue; + if (Int32.TryParse(node["wheelCenterPoint"].InnerText.Split(',')[1], out intValue)) device.wheelCenterPoint.Y = intValue; + if (Int32.TryParse(node["wheel90DegPointLeft"].InnerText.Split(',')[0], out intValue)) device.wheel90DegPointLeft.X = intValue; + if (Int32.TryParse(node["wheel90DegPointLeft"].InnerText.Split(',')[1], out intValue)) device.wheel90DegPointLeft.Y = intValue; + if (Int32.TryParse(node["wheel90DegPointRight"].InnerText.Split(',')[0], out intValue)) device.wheel90DegPointRight.X = intValue; + if (Int32.TryParse(node["wheel90DegPointRight"].InnerText.Split(',')[1], out intValue)) device.wheel90DegPointRight.Y = intValue; + + loaded = true; + } + } + catch + { + AppLogger.LogToGui("ControllerConfigs.xml can't be found.", false); + loaded = false; + } + + return loaded; + } + + public bool SaveControllerConfigsForDevice(DS4Device device) + { + bool saved = true; + + if (device == null) return false; + if (!File.Exists(m_controllerConfigs)) createControllerConfigs(); + + try + { + //XmlNode node = null; + XmlDocument xmlDoc = new XmlDocument(); + xmlDoc.Load(m_controllerConfigs); + + XmlNode node = xmlDoc.SelectSingleNode("/Controllers/Controller[@Mac=\"" + device.getMacAddress() + "\"]"); + if (node == null) + { + XmlNode xmlControllersNode = xmlDoc.SelectSingleNode("/Controllers"); + XmlElement el = xmlDoc.CreateElement("Controller"); + el.SetAttribute("Mac", device.getMacAddress()); + + el.AppendChild(xmlDoc.CreateElement("wheelCenterPoint")); + el.AppendChild(xmlDoc.CreateElement("wheel90DegPointLeft")); + el.AppendChild(xmlDoc.CreateElement("wheel90DegPointRight")); + + node = xmlControllersNode.AppendChild(el); + } + + node["wheelCenterPoint"].InnerText = $"{device.wheelCenterPoint.X},{device.wheelCenterPoint.Y}"; + node["wheel90DegPointLeft"].InnerText = $"{device.wheel90DegPointLeft.X},{device.wheel90DegPointLeft.Y}"; + node["wheel90DegPointRight"].InnerText = $"{device.wheel90DegPointRight.X},{device.wheel90DegPointRight.Y}"; + + xmlDoc.Save(m_controllerConfigs); + } + catch (UnauthorizedAccessException) + { + AppLogger.LogToGui("Unauthorized Access - Save failed to path: " + m_controllerConfigs, false); + saved = false; + } + + return saved; + } + public void UpdateDS4CSetting(int deviceNum, string buttonName, bool shift, object action, string exts, DS4KeyType kt, int trigger = 0) { DS4Controls dc; @@ -3780,6 +3919,7 @@ namespace DS4Windows useSAforMouse[device] = false; sATriggers[device] = string.Empty; sATriggerCond[device] = true; + sASteeringWheelEmulationAxis[device] = DS4Controls.None; touchDisInvertTriggers[device] = new int[1] { -1 }; lsCurve[device] = rsCurve[device] = 0; gyroSensitivity[device] = 100; diff --git a/DS4Windows/DS4Control/X360Device.cs b/DS4Windows/DS4Control/X360Device.cs index e3dd1fb..7ef8123 100644 --- a/DS4Windows/DS4Control/X360Device.cs +++ b/DS4Windows/DS4Control/X360Device.cs @@ -5,6 +5,8 @@ using System.ComponentModel; using System.Runtime.InteropServices; using Microsoft.Win32.SafeHandles; +using System.Drawing; // Point struct + namespace DS4Windows { public partial class X360Device : ScpDevice @@ -141,10 +143,25 @@ namespace DS4Windows Output[12] = state.L2; // Left Trigger Output[13] = state.R2; // Right Trigger - Int32 ThumbLX = Scale(state.LX, false); - Int32 ThumbLY = Scale(state.LY, true); - Int32 ThumbRX = Scale(state.RX, false); - Int32 ThumbRY = Scale(state.RY, true); + Int32 ThumbLX; + Int32 ThumbLY; + Int32 ThumbRX; + Int32 ThumbRY; + + DS4Controls steeringWheelMappedAxis = Global.getSASteeringWheelEmulationAxis(device); + + if (steeringWheelMappedAxis == DS4Controls.LXPos) ThumbLX = state.SASteeringWheelEmulationUnit; + else ThumbLX = Scale(state.LX, false); + + if (steeringWheelMappedAxis == DS4Controls.LYPos) ThumbLY = state.SASteeringWheelEmulationUnit; + else ThumbLY = Scale(state.LY, true); + + if (steeringWheelMappedAxis == DS4Controls.RXPos) ThumbRX = state.SASteeringWheelEmulationUnit; + else ThumbRX = Scale(state.RX, false); + + if (steeringWheelMappedAxis == DS4Controls.RYPos) ThumbRY = state.SASteeringWheelEmulationUnit; + else ThumbRY = Scale(state.RY, true); + Output[14] = (Byte)((ThumbLX >> 0) & 0xFF); // LX Output[15] = (Byte)((ThumbLX >> 8) & 0xFF); Output[16] = (Byte)((ThumbLY >> 0) & 0xFF); // LY diff --git a/DS4Windows/DS4Library/DS4Device.cs b/DS4Windows/DS4Library/DS4Device.cs index aba9179..dc18361 100644 --- a/DS4Windows/DS4Library/DS4Device.cs +++ b/DS4Windows/DS4Library/DS4Device.cs @@ -157,6 +157,34 @@ namespace DS4Windows return warnInterval; } + public Point wheelCenterPoint; + public Point wheel90DegPointLeft; + public Point wheelCircleCenterPointLeft; + public Point wheel90DegPointRight; + public Point wheelCircleCenterPointRight; + + public DateTime wheelPrevRecalibrateTime; + + private bool wheelRecalibrateActive = false; + public bool WheelRecalibrateActive + { + get { return wheelRecalibrateActive; } + set + { + wheelRecalibrateActive = value; + } + } + + public enum WheelCalibrationPoint + { + None = 0, + Center = 1, + Right90 = 2, + Left90 = 4, + All = Center | Right90 | Left90 + } + public WheelCalibrationPoint wheelCalibratedAxisBitmask; + private bool exitOutputThread = false; public bool ExitOutputThread => exitOutputThread; private bool exitInputThread = false; diff --git a/DS4Windows/DS4Library/DS4State.cs b/DS4Windows/DS4Library/DS4State.cs index 7400f15..1aae958 100644 --- a/DS4Windows/DS4Library/DS4State.cs +++ b/DS4Windows/DS4Library/DS4State.cs @@ -28,6 +28,7 @@ namespace DS4Windows public ulong totalMicroSec = 0; public SixAxis Motion = null; public static readonly int DEFAULT_AXISDIR_VALUE = 127; + public Int32 SASteeringWheelEmulationUnit; public struct TrackPadTouch { @@ -66,6 +67,7 @@ namespace DS4Windows Motion = new SixAxis(0, 0, 0, 0, 0, 0, 0.0); TrackPadTouch0.IsActive = false; TrackPadTouch1.IsActive = false; + SASteeringWheelEmulationUnit = 0; } public DS4State(DS4State state) @@ -120,6 +122,7 @@ namespace DS4Windows Motion = state.Motion; TrackPadTouch0 = state.TrackPadTouch0; TrackPadTouch1 = state.TrackPadTouch1; + SASteeringWheelEmulationUnit = state.SASteeringWheelEmulationUnit; } public DS4State Clone() @@ -179,6 +182,7 @@ namespace DS4Windows state.Motion = Motion; state.TrackPadTouch0 = TrackPadTouch0; state.TrackPadTouch1 = TrackPadTouch1; + state.SASteeringWheelEmulationUnit = SASteeringWheelEmulationUnit; } public void calculateStickAngles() From 1cb04d03adbdd4c0b7c75c600257b1a8c5f8f506 Mon Sep 17 00:00:00 2001 From: mika-n Date: Mon, 19 Nov 2018 13:32:48 +0200 Subject: [PATCH 02/66] Changed precision of angle values sent to x360 virtual controller from 1 degree to 1/10th degree precision. Also, minimized "center deadzone" gap (the previous optimization of angle calculation was too aggressive in wheel center position). --- DS4Windows/DS4Control/Mapping.cs | 39 +++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/DS4Windows/DS4Control/Mapping.cs b/DS4Windows/DS4Control/Mapping.cs index cfad5a4..ae4d6aa 100644 --- a/DS4Windows/DS4Control/Mapping.cs +++ b/DS4Windows/DS4Control/Mapping.cs @@ -3781,6 +3781,9 @@ namespace DS4Windows // BEGIN: SixAxis steering wheel emulation logic + private const int C_WHEEL_ANGLE_PRECISION = 10; // 1=precision of one degree, 10=precision of 1/10 of degree. Bigger number means fine graned precision + private const int C_WHEEL_ANGLE_PRECISION_DECIMALS = (C_WHEEL_ANGLE_PRECISION == 1 ? 0 : C_WHEEL_ANGLE_PRECISION/10); + // "In-game" calibration process: // TODO: Launching a calibration process should probably be a special action which allows multiple key bindings to launch a specific task. // - Place controller at "steering wheel center" position and press DS4 Option button to start the calibration (Profile should have "SASteeringWheelEmulationAxis" option set to LXPos, LYPos, RXPos or RYPos value). @@ -3829,7 +3832,7 @@ namespace DS4Windows { Int32 result; - if (Math.Abs(gyroAccelX - controller.wheelCenterPoint.X) <= 1 && Math.Abs(gyroAccelZ - controller.wheelCenterPoint.Y) <= 1) + if (gyroAccelX == controller.wheelCenterPoint.X && Math.Abs(gyroAccelZ - controller.wheelCenterPoint.Y) <= 1) { // When the current gyro position is "close enough" the wheel center point then no need to go through the hassle of calculating an angle result = 0; @@ -3860,14 +3863,24 @@ namespace DS4Windows double magCD = Math.Sqrt(vectorCD.X * vectorCD.X + vectorCD.Y * vectorCD.Y); // Calculate angle between vectors and convert radian to degrees - double angle = Math.Acos(dotProduct / (magAB * magCD)); - result = Convert.ToInt32(Math.Round(angle * (180.0 / Math.PI))); + if (magAB == 0 || magCD == 0) + { + result = 0; + } + else + { + double angle = Math.Acos(dotProduct / (magAB * magCD)); + result = Convert.ToInt32( Clamp(-180.0 * C_WHEEL_ANGLE_PRECISION, + Math.Round((angle * (180.0 / Math.PI)), C_WHEEL_ANGLE_PRECISION_DECIMALS) * C_WHEEL_ANGLE_PRECISION, + 180.0 * C_WHEEL_ANGLE_PRECISION) + ); + } // Left turn is -180..0 and right turn 0..180 degrees if (gyroAccelX < controller.wheelCenterPoint.X) result = -result; // Just to be sure.. Probably not needed. TODO: Add support for 360/720/900 turn ranges by counting "laps" how many times the steering wheel is turned around - result = ClampInt(-180, result, 180); + //result = ClampInt(-180, result, 180); } return result; @@ -3974,7 +3987,6 @@ namespace DS4Windows // Show lightbar color feedback how the calibration process is proceeding. // red / yellow / blue / green = No calibration anchors/one anchor/two anchors/three anchors calibrated (center, 90DegLeft, 90DegRight) // Blinking led = Controller is tilted at the current calibration point (or calibration routine just set a new anchor point) - // TODO: device num to flash led idx (use red for center calibrated, yellow for one 90deg and green for both 90deg calibration and then reset back to normal led) int bitsSet = CountNumOfSetBits((int)controller.wheelCalibratedAxisBitmask); if (bitsSet >= 3) DS4LightBar.forcedColor[device] = calibrationColor_3; else if (bitsSet == 2) DS4LightBar.forcedColor[device] = calibrationColor_2; @@ -3982,13 +3994,19 @@ namespace DS4Windows else DS4LightBar.forcedColor[device] = calibrationColor_0; result = CalculateControllerAngle(gyroAccelX, gyroAccelZ, controller); - if (bitsSet >= 1 && (Math.Abs(result) <= 1 || (Math.Abs(result) >= 88 && Math.Abs(result) <= 92) || Math.Abs(result) >= 178)) DS4LightBar.forcedFlash[device] = 2; - else DS4LightBar.forcedFlash[device] = 0; + if (bitsSet >= 1 && ( + Math.Abs(result) <= 1 * C_WHEEL_ANGLE_PRECISION + || (Math.Abs(result) >= 88 * C_WHEEL_ANGLE_PRECISION && Math.Abs(result) <= 92 * C_WHEEL_ANGLE_PRECISION) + || Math.Abs(result) >= 178 * C_WHEEL_ANGLE_PRECISION + )) + DS4LightBar.forcedFlash[device] = 2; + else + DS4LightBar.forcedFlash[device] = 0; DS4LightBar.forcelight[device] = true; //DS4LightBar.updateLightBar(controller, device); - LogToGuiSACalibrationDebugMsg($"Calibration values ({gyroAccelX}, {gyroAccelZ}) angle={result}\n"); + LogToGuiSACalibrationDebugMsg($"Calibration values ({gyroAccelX}, {gyroAccelZ}) angle={result / (1.0 * C_WHEEL_ANGLE_PRECISION)}\n"); // Return center wheel position while gyro is calibrated, not the calculated angle return 0; @@ -3996,7 +4014,6 @@ namespace DS4Windows // If calibration values are missing then use "educated guesses" about good starting values. - // TODO. Use pre-calibrated default values from configuration file. if (controller.wheelCenterPoint.IsEmpty) { if (!Global.LoadControllerConfigs(controller)) @@ -4026,10 +4043,10 @@ namespace DS4Windows // Keep outputting debug data 30secs after the latest re-calibration event (user can check these values from the log screen of DS4Windows GUI) //if (((TimeSpan)(DateTime.Now - prevRecalibrateTime)).TotalSeconds < 30) - // LogToGuiSACalibrationDebugMsg($"DEBUG gyro=({gyroAccelX}, {gyroAccelZ}) angle={result}"); + // LogToGuiSACalibrationDebugMsg($"DEBUG gyro=({gyroAccelX}, {gyroAccelZ}) angle={result / (1.0 * C_WHEEL_ANGLE_PRECISION)}"); // Scale input to a raw x360 thumbstick output scale - return (((result - (-180)) * (32767 - (-32768))) / (180 - (-180))) + (-32768); + return (((result - (-180 * C_WHEEL_ANGLE_PRECISION)) * (32767 - (-32768))) / (180 * C_WHEEL_ANGLE_PRECISION - (-180 * C_WHEEL_ANGLE_PRECISION))) + (-32768); } } // END: SixAxis steering wheel emulation logic From 1eed418022640fc8f77a22c844204b480b975100 Mon Sep 17 00:00:00 2001 From: mika-n Date: Tue, 4 Dec 2018 00:50:37 +0200 Subject: [PATCH 03/66] Added support for 180/360/720/900/1440 turn range (or any other turn range between 90-3240 degrees). New SASteeringWheelEmulationRange profile option with int32 value (default 360). --- DS4Windows/DS4Control/Mapping.cs | 319 ++++++++++------ DS4Windows/DS4Control/ScpUtil.cs | 30 +- DS4Windows/DS4Forms/Options.cs | 3 + DS4Windows/DS4Forms/SpecActions.Designer.cs | 11 +- DS4Windows/DS4Forms/SpecActions.cs | 13 +- DS4Windows/DS4Forms/SpecActions.resx | 393 ++++++-------------- DS4Windows/DS4Library/DS4Device.cs | 11 +- DS4Windows/DS4Windows.csproj | 2 + DS4Windows/Properties/Resources.Designer.cs | 9 + DS4Windows/Properties/Resources.resx | 3 + DS4Windows/Settings.cs | 28 ++ 11 files changed, 406 insertions(+), 416 deletions(-) create mode 100644 DS4Windows/Settings.cs diff --git a/DS4Windows/DS4Control/Mapping.cs b/DS4Windows/DS4Control/Mapping.cs index ae4d6aa..32e561a 100644 --- a/DS4Windows/DS4Control/Mapping.cs +++ b/DS4Windows/DS4Control/Mapping.cs @@ -1964,6 +1964,25 @@ namespace DS4Windows } actionDone[index].dev[device] = true; } + else if (action.typeID == SpecialAction.ActionTypeId.SASteeringWheelEmulationCalibrate) + { + actionFound = true; + + DS4Device d = ctrl.DS4Controllers[device]; + // If controller is not already in SASteeringWheelCalibration state then enable it now. If calibration is active then complete it (commit calibration values) + if (d.WheelRecalibrateActiveState == 0 && DateTime.UtcNow > (action.firstTap + TimeSpan.FromMilliseconds(3000))) + { + action.firstTap = DateTime.UtcNow; + d.WheelRecalibrateActiveState = 1; // Start calibration process + } + else if (d.WheelRecalibrateActiveState == 2 && DateTime.UtcNow > (action.firstTap + TimeSpan.FromMilliseconds(3000))) + { + action.firstTap = DateTime.UtcNow; + d.WheelRecalibrateActiveState = 3; // Complete calibration process + } + + actionDone[index].dev[device] = true; + } } else { @@ -3803,14 +3822,19 @@ namespace DS4Windows private static readonly DS4Color calibrationColor_3 = new DS4Color { red = 0x00, green = 0xC0, blue = 0x00 }; private static DateTime latestDebugMsgTime; - private static void LogToGuiSACalibrationDebugMsg(string data) + private static string latestDebugData; + private static void LogToGuiSACalibrationDebugMsg(string data, bool forceOutput = false) { // Print debug calibration log messages only once per 2 secs to avoid flooding the log receiver DateTime curTime = DateTime.Now; - if (((TimeSpan)(curTime - latestDebugMsgTime)).TotalSeconds > 2) + if (forceOutput || ((TimeSpan)(curTime - latestDebugMsgTime)).TotalSeconds > 2) { latestDebugMsgTime = curTime; - AppLogger.LogToGui(data, false); + if (data != latestDebugData) + { + AppLogger.LogToGui(data, false); + latestDebugData = data; + } } } @@ -3828,7 +3852,7 @@ namespace DS4Windows // Calculate and return the angle of the controller as -180...0...+180 value. // TODO: Support >360 degree turn range by adding "lap counter" when wheel is rotated full rounds left or right.At the moment this logic supports only 360 degree turn range. - protected static Int32 CalculateControllerAngle(int gyroAccelX, int gyroAccelZ, DS4Device controller) + private static Int32 CalculateControllerAngle(int gyroAccelX, int gyroAccelZ, DS4Device controller) { Int32 result; @@ -3870,7 +3894,8 @@ namespace DS4Windows else { double angle = Math.Acos(dotProduct / (magAB * magCD)); - result = Convert.ToInt32( Clamp(-180.0 * C_WHEEL_ANGLE_PRECISION, + result = Convert.ToInt32( Global.Clamp( + -180.0 * C_WHEEL_ANGLE_PRECISION, Math.Round((angle * (180.0 / Math.PI)), C_WHEEL_ANGLE_PRECISION_DECIMALS) * C_WHEEL_ANGLE_PRECISION, 180.0 * C_WHEEL_ANGLE_PRECISION) ); @@ -3878,15 +3903,130 @@ namespace DS4Windows // Left turn is -180..0 and right turn 0..180 degrees if (gyroAccelX < controller.wheelCenterPoint.X) result = -result; - - // Just to be sure.. Probably not needed. TODO: Add support for 360/720/900 turn ranges by counting "laps" how many times the steering wheel is turned around - //result = ClampInt(-180, result, 180); } return result; } - protected static Int32 Scale360degreeGyroAxis(int device, /*DS4State state,*/ DS4StateExposed exposedState, ControlService ctrl) + private static void SAWheelEmulationCalibration(int device, DS4StateExposed exposedState, ControlService ctrl, DS4State currentDeviceState, DS4Device controller) + { + int gyroAccelX, gyroAccelZ; + int result; + + gyroAccelX = exposedState.getAccelX(); + gyroAccelZ = exposedState.getAccelZ(); + + // "SASteeringWheelEmulaationCalibration" action key combination is used to run "in-game" calibration process (user can define the action key combination in DS4Windows GUI). + // State 0=Normal mode (ie. calibration process is not running), 1=Activating calibration, 2=Calibration process running, 3=Completing calibration + if (controller.WheelRecalibrateActiveState == 1) + { + AppLogger.LogToGui($"Controller {ctrl.x360Bus.FirstController + device} activated re-calibration of SA steering wheel emulation", false); + + controller.WheelRecalibrateActiveState = 2; + + controller.wheelPrevPhysicalAngle = 0; + controller.wheelFullTurnCount = 0; + + // Clear existing calibration value and use current position as "center" point. + // This initial center value may be off-center because of shaking the controller while button was pressed. The value will be overriden with correct value once controller is stabilized and hold still few secs at the center point + controller.wheelCenterPoint.X = gyroAccelX; + controller.wheelCenterPoint.Y = gyroAccelZ; + controller.wheel90DegPointRight.X = gyroAccelX + 25; + controller.wheel90DegPointLeft.X = gyroAccelX - 25; + + // Clear bitmask for calibration points. All three calibration points need to be set before re-calibration process is valid + controller.wheelCalibratedAxisBitmask = DS4Device.WheelCalibrationPoint.None; + + controller.wheelPrevRecalibrateTime = DateTime.Now; + } + else if (controller.WheelRecalibrateActiveState == 3 /*&& currentDeviceState.Options && ((TimeSpan)(DateTime.Now - controller.wheelPrevRecalibrateTime)).TotalSeconds > 3 */) + { + AppLogger.LogToGui($"Controller {ctrl.x360Bus.FirstController + device} completed the calibration of SA steering wheel emulation. center=({controller.wheelCenterPoint.X}, {controller.wheelCenterPoint.Y}) 90L=({controller.wheel90DegPointLeft.X}, {controller.wheel90DegPointLeft.Y}) 90R=({controller.wheel90DegPointRight.X}, {controller.wheel90DegPointRight.Y})", false); + + // If any of the calibration points (center, left 90deg, right 90deg) are missing then reset back to default calibration values + if (((controller.wheelCalibratedAxisBitmask & DS4Device.WheelCalibrationPoint.All) == DS4Device.WheelCalibrationPoint.All)) + Global.SaveControllerConfigs(controller); + else + controller.wheelCenterPoint.X = controller.wheelCenterPoint.Y = 0; + + // Reset lightbar back to normal color + // TODO: hmmm... Sometimes color is not reset back to normal "main color". Investigate why following code logic doesn't always restore it. + DS4LightBar.forcelight[device] = false; + DS4LightBar.forcedFlash[device] = 0; + DS4LightBar.updateLightBar(controller, device); + + controller.LightBarColor = Global.getMainColor(device); + DS4LightBar.updateLightBar(controller, device); + + controller.WheelRecalibrateActiveState = 0; + + controller.wheelPrevRecalibrateTime = DateTime.Now; + } + + if (controller.WheelRecalibrateActiveState > 0) + { + // Auto calibrate 90deg left/right positions (these values may change over time because gyro/accel sensor values are not "precise mathematics", so user can trigger calibration even in mid-game sessions by pressing DS4 Options btn), + // but make sure controller is stable enough to avoid misaligments because of hard shaking (check velocity of gyro axis) + if (Math.Abs(currentDeviceState.Motion.angVelPitch) < 0.5 && Math.Abs(currentDeviceState.Motion.angVelYaw) < 0.5 && Math.Abs(currentDeviceState.Motion.angVelRoll) < 0.5) + { + if (controller.wheelCalibratedAxisBitmask == DS4Device.WheelCalibrationPoint.None) + { + // Wait few secs after re-calibration button was pressed. Hold controller still at center position and don't shake it too much until red lightbar turns to yellow. + if (((TimeSpan)(DateTime.Now - controller.wheelPrevRecalibrateTime)).TotalSeconds >= 3) + { + controller.wheelCenterPoint.X = gyroAccelX; + controller.wheelCenterPoint.Y = gyroAccelZ; + + controller.wheelCalibratedAxisBitmask |= DS4Device.WheelCalibrationPoint.Center; + } + } + else if (controller.wheel90DegPointRight.X < gyroAccelX) + { + controller.wheel90DegPointRight.X = gyroAccelX; + controller.wheel90DegPointRight.Y = gyroAccelZ; + controller.wheelCircleCenterPointRight.X = controller.wheelCenterPoint.X; + controller.wheelCircleCenterPointRight.Y = controller.wheel90DegPointRight.Y; + + controller.wheelCalibratedAxisBitmask |= DS4Device.WheelCalibrationPoint.Right90; + } + else if (controller.wheel90DegPointLeft.X > gyroAccelX) + { + controller.wheel90DegPointLeft.X = gyroAccelX; + controller.wheel90DegPointLeft.Y = gyroAccelZ; + controller.wheelCircleCenterPointLeft.X = controller.wheelCenterPoint.X; + controller.wheelCircleCenterPointLeft.Y = controller.wheel90DegPointLeft.Y; + + controller.wheelCalibratedAxisBitmask |= DS4Device.WheelCalibrationPoint.Left90; + } + } + + // Show lightbar color feedback how the calibration process is proceeding. + // red / yellow / blue / green = No calibration anchors/one anchor/two anchors/three anchors calibrated (center, 90DegLeft, 90DegRight) + // Blinking led = Controller is tilted at the current calibration point (or calibration routine just set a new anchor point) + int bitsSet = CountNumOfSetBits((int)controller.wheelCalibratedAxisBitmask); + if (bitsSet >= 3) DS4LightBar.forcedColor[device] = calibrationColor_3; + else if (bitsSet == 2) DS4LightBar.forcedColor[device] = calibrationColor_2; + else if (bitsSet == 1) DS4LightBar.forcedColor[device] = calibrationColor_1; + else DS4LightBar.forcedColor[device] = calibrationColor_0; + + result = CalculateControllerAngle(gyroAccelX, gyroAccelZ, controller); + if (bitsSet >= 1 && ( + Math.Abs(result) <= 1 * C_WHEEL_ANGLE_PRECISION + || (Math.Abs(result) >= 88 * C_WHEEL_ANGLE_PRECISION && Math.Abs(result) <= 92 * C_WHEEL_ANGLE_PRECISION) + || Math.Abs(result) >= 178 * C_WHEEL_ANGLE_PRECISION + )) + DS4LightBar.forcedFlash[device] = 2; + else + DS4LightBar.forcedFlash[device] = 0; + + DS4LightBar.forcelight[device] = true; + //DS4LightBar.updateLightBar(controller, device); + + LogToGuiSACalibrationDebugMsg($"Calibration values ({gyroAccelX}, {gyroAccelZ}) angle={result / (1.0 * C_WHEEL_ANGLE_PRECISION)}\n"); + } + } + + protected static Int32 Scale360degreeGyroAxis(int device, DS4StateExposed exposedState, ControlService ctrl) { unchecked { @@ -3902,132 +4042,34 @@ namespace DS4Windows currentDeviceState = controller.getCurrentStateRef(); - gyroAccelX = exposedState.getAccelX(); - gyroAccelZ = exposedState.getAccelZ(); - - // If DS4 Options btn is pressed and the previous re-calibration was done more than 2 secs ago (avoids repeated "calibration" loops if user holds down the Option btn too long) then re-calibrate the gyro wheel emulation. - // TODO. Maybe here should be logic to enter calibration process only if Options btn is hold down minimum of 3 secs? This way Option btn can be re-mapped to do other things without kicking on re-calibration everytime it is pressed. - if (currentDeviceState.Options && ((TimeSpan)(DateTime.Now - controller.wheelPrevRecalibrateTime)).TotalSeconds > 2) + // If user has pressed "SASteeringWheelEmulationCalibration" special action key combination then run "in-game" calibration process + if (controller.WheelRecalibrateActiveState > 0) { - if (controller.WheelRecalibrateActive == false) - { - AppLogger.LogToGui($"Controller {ctrl.x360Bus.FirstController + device} activated re-calibration of motion steering wheel emulation", false); + SAWheelEmulationCalibration(device, exposedState, ctrl, currentDeviceState, controller); - controller.WheelRecalibrateActive = true; - - // Clear existing calibration value and use current position as "center" point. - // This initial center value may be off-center because of shaking the controller while button was pressed. The value will be overriden with correct value once controller is stabilized and hold still few secs at the center point - controller.wheelCenterPoint.X = gyroAccelX; - controller.wheelCenterPoint.Y = gyroAccelZ; - controller.wheel90DegPointRight.X = gyroAccelX + 25; - controller.wheel90DegPointLeft.X = gyroAccelX - 25; - - // Clear bitmask for calibration points. All three calibration points need to be set before re-calibration process is valid - controller.wheelCalibratedAxisBitmask = DS4Device.WheelCalibrationPoint.None; - } - else - { - AppLogger.LogToGui($"Controller {ctrl.x360Bus.FirstController + device} completed steering wheel calibration. center=({controller.wheelCenterPoint.X}, {controller.wheelCenterPoint.Y}) 90L=({controller.wheel90DegPointLeft.X}, {controller.wheel90DegPointLeft.Y}) 90R=({controller.wheel90DegPointRight.X}, {controller.wheel90DegPointRight.Y})", false); - - controller.WheelRecalibrateActive = false; - - // If any of the calibration points (center, left 90deg, right 90deg) are missing then reset back to default calibration values - if (((controller.wheelCalibratedAxisBitmask & DS4Device.WheelCalibrationPoint.All) == DS4Device.WheelCalibrationPoint.All)) - Global.SaveControllerConfigs(controller); - else - controller.wheelCenterPoint.X = controller.wheelCenterPoint.Y = 0; - - // Reset lightbar back to normal color - DS4LightBar.forcelight[device] = false; - DS4LightBar.forcedFlash[device] = 0; - controller.LightBarColor = Global.getMainColor(device); - DS4LightBar.updateLightBar(controller, device); - } - - controller.wheelPrevRecalibrateTime = DateTime.Now; - } - - if (controller.WheelRecalibrateActive) - { - // Auto calibrate 90deg left/right positions (these values may change over time because gyro/accel sensor values are not "precise mathematics", so user can trigger calibration even in mid-game sessions by pressing DS4 Options btn), - // but make sure controller is stable enough to avoid misaligments because of hard shaking (check velocity of gyro axis) - if (Math.Abs(/*state*/ currentDeviceState.Motion.angVelPitch) < 0.5 && Math.Abs(currentDeviceState.Motion.angVelYaw) < 0.5 && Math.Abs(currentDeviceState.Motion.angVelRoll) < 0.5) - { - if (controller.wheelCalibratedAxisBitmask == DS4Device.WheelCalibrationPoint.None) - { - // Wait few secs after re-calibration button was pressed. Hold controller still at center position and don't shake it too much until red lightbar turns to yellow. - if (((TimeSpan)(DateTime.Now - controller.wheelPrevRecalibrateTime)).TotalSeconds >= 3) - { - controller.wheelCenterPoint.X = gyroAccelX; - controller.wheelCenterPoint.Y = gyroAccelZ; - - controller.wheelCalibratedAxisBitmask |= DS4Device.WheelCalibrationPoint.Center; - } - } - else if (controller.wheel90DegPointRight.X < gyroAccelX) - { - controller.wheel90DegPointRight.X = gyroAccelX; - controller.wheel90DegPointRight.Y = gyroAccelZ; - controller.wheelCircleCenterPointRight.X = controller.wheelCenterPoint.X; - controller.wheelCircleCenterPointRight.Y = controller.wheel90DegPointRight.Y; - - controller.wheelCalibratedAxisBitmask |= DS4Device.WheelCalibrationPoint.Right90; - } - else if (controller.wheel90DegPointLeft.X > gyroAccelX) - { - controller.wheel90DegPointLeft.X = gyroAccelX; - controller.wheel90DegPointLeft.Y = gyroAccelZ; - controller.wheelCircleCenterPointLeft.X = controller.wheelCenterPoint.X; - controller.wheelCircleCenterPointLeft.Y = controller.wheel90DegPointLeft.Y; - - controller.wheelCalibratedAxisBitmask |= DS4Device.WheelCalibrationPoint.Left90; - } - } - - // Show lightbar color feedback how the calibration process is proceeding. - // red / yellow / blue / green = No calibration anchors/one anchor/two anchors/three anchors calibrated (center, 90DegLeft, 90DegRight) - // Blinking led = Controller is tilted at the current calibration point (or calibration routine just set a new anchor point) - int bitsSet = CountNumOfSetBits((int)controller.wheelCalibratedAxisBitmask); - if (bitsSet >= 3) DS4LightBar.forcedColor[device] = calibrationColor_3; - else if (bitsSet == 2) DS4LightBar.forcedColor[device] = calibrationColor_2; - else if (bitsSet == 1) DS4LightBar.forcedColor[device] = calibrationColor_1; - else DS4LightBar.forcedColor[device] = calibrationColor_0; - - result = CalculateControllerAngle(gyroAccelX, gyroAccelZ, controller); - if (bitsSet >= 1 && ( - Math.Abs(result) <= 1 * C_WHEEL_ANGLE_PRECISION - || (Math.Abs(result) >= 88 * C_WHEEL_ANGLE_PRECISION && Math.Abs(result) <= 92 * C_WHEEL_ANGLE_PRECISION) - || Math.Abs(result) >= 178 * C_WHEEL_ANGLE_PRECISION - )) - DS4LightBar.forcedFlash[device] = 2; - else - DS4LightBar.forcedFlash[device] = 0; - - DS4LightBar.forcelight[device] = true; - //DS4LightBar.updateLightBar(controller, device); - - LogToGuiSACalibrationDebugMsg($"Calibration values ({gyroAccelX}, {gyroAccelZ}) angle={result / (1.0 * C_WHEEL_ANGLE_PRECISION)}\n"); - - // Return center wheel position while gyro is calibrated, not the calculated angle + // Return center wheel position while SA wheel emuation is being calibrated return 0; } + gyroAccelX = exposedState.getAccelX(); + gyroAccelZ = exposedState.getAccelZ(); - // If calibration values are missing then use "educated guesses" about good starting values. + // If calibration values are missing then use "educated guesses" about good starting values if (controller.wheelCenterPoint.IsEmpty) { if (!Global.LoadControllerConfigs(controller)) { - AppLogger.LogToGui($"Controller {ctrl.x360Bus.FirstController + device} motion steering wheel calibration data missing. It is recommended to run steering wheel calibration process by pressing DS4 Options button. Using estimated values until the controller is calibrated at least once.", false); + AppLogger.LogToGui($"Controller {ctrl.x360Bus.FirstController + device} sixaxis steering wheel calibration data missing. It is recommended to run steering wheel calibration process by pressing SASteeringWheelEmulationCalibration special action key. Using estimated values until the controller is calibrated at least once.", false); - controller.wheelCenterPoint.X = gyroAccelX; + // Use current controller position as "center point". Assume DS4Windows was started while controller was hold in center position (yes, dangerous assumption but can't do much until controller is calibrated) + controller.wheelCenterPoint.X = gyroAccelX; controller.wheelCenterPoint.Y = gyroAccelZ; - controller.wheel90DegPointRight.X = controller.wheelCenterPoint.X + 113; // 113; - controller.wheel90DegPointRight.Y = controller.wheelCenterPoint.Y + 110; // 110; + controller.wheel90DegPointRight.X = controller.wheelCenterPoint.X + 113; + controller.wheel90DegPointRight.Y = controller.wheelCenterPoint.Y + 110; - controller.wheel90DegPointLeft.X = controller.wheelCenterPoint.X - 127; // -127; - controller.wheel90DegPointLeft.Y = controller.wheel90DegPointRight.Y; // 2; + controller.wheel90DegPointLeft.X = controller.wheelCenterPoint.X - 127; + controller.wheel90DegPointLeft.Y = controller.wheel90DegPointRight.Y; } controller.wheelCircleCenterPointRight.X = controller.wheelCenterPoint.X; @@ -4040,13 +4082,46 @@ namespace DS4Windows } result = CalculateControllerAngle(gyroAccelX, gyroAccelZ, controller); + + if (controller.wheelPrevPhysicalAngle < 0 && result > 0) + { + // If wrapped around from -180 to +180 side then SA steering wheel keeps on turning "left" (ie. beyond 360 degrees) + if ((result - controller.wheelPrevPhysicalAngle) > 180 * C_WHEEL_ANGLE_PRECISION) + controller.wheelFullTurnCount--; + } + else if (controller.wheelPrevPhysicalAngle > 0 && result < 0) + { + // If wrapped around from +180 to -180 side then SA steering wheel keeps on turning "right" (ie. beyond 360 degrees) + if ((controller.wheelPrevPhysicalAngle - result) > 180 * C_WHEEL_ANGLE_PRECISION) + controller.wheelFullTurnCount++; + } + controller.wheelPrevPhysicalAngle = result; + + if (controller.wheelFullTurnCount != 0) + { + if (controller.wheelFullTurnCount > 0) + result = (controller.wheelFullTurnCount * 180 * C_WHEEL_ANGLE_PRECISION) + ((controller.wheelFullTurnCount * 180 * C_WHEEL_ANGLE_PRECISION) + result); + else + result = (controller.wheelFullTurnCount * 180 * C_WHEEL_ANGLE_PRECISION) - ((controller.wheelFullTurnCount * -180 * C_WHEEL_ANGLE_PRECISION) - result); + } + + // TODO: How to prevent "too many laps" problem or reset it (DS4Win doesn't know when a game is running so it keeps counting laps)? + + int maxRangeRight = Global.getSASteeringWheelEmulationRange(device) / 2 * C_WHEEL_ANGLE_PRECISION; + int maxRangeLeft = -maxRangeRight; + + if (maxRangeRight != (360 / 2 * C_WHEEL_ANGLE_PRECISION) ) + result = Mapping.ClampInt(maxRangeLeft, result, maxRangeRight); // Keep outputting debug data 30secs after the latest re-calibration event (user can check these values from the log screen of DS4Windows GUI) //if (((TimeSpan)(DateTime.Now - prevRecalibrateTime)).TotalSeconds < 30) // LogToGuiSACalibrationDebugMsg($"DEBUG gyro=({gyroAccelX}, {gyroAccelZ}) angle={result / (1.0 * C_WHEEL_ANGLE_PRECISION)}"); + //LogToGuiSACalibrationDebugMsg($"DEBUG gyro=({gyroAccelX}, {gyroAccelZ}) angle={result / (1.0 * C_WHEEL_ANGLE_PRECISION)} fullTurns={controller.wheelFullTurnCount}", false); + // Scale input to a raw x360 thumbstick output scale - return (((result - (-180 * C_WHEEL_ANGLE_PRECISION)) * (32767 - (-32768))) / (180 * C_WHEEL_ANGLE_PRECISION - (-180 * C_WHEEL_ANGLE_PRECISION))) + (-32768); + //return (((result - (-180 * C_WHEEL_ANGLE_PRECISION)) * (32767 - (-32768))) / (180 * C_WHEEL_ANGLE_PRECISION - (-180 * C_WHEEL_ANGLE_PRECISION))) + (-32768); + return (( (result - maxRangeLeft) * (32767 - (-32768))) / (maxRangeRight - maxRangeLeft)) + (-32768); } } // END: SixAxis steering wheel emulation logic diff --git a/DS4Windows/DS4Control/ScpUtil.cs b/DS4Windows/DS4Control/ScpUtil.cs index 7e3e3a1..e526897 100644 --- a/DS4Windows/DS4Control/ScpUtil.cs +++ b/DS4Windows/DS4Control/ScpUtil.cs @@ -724,6 +724,12 @@ namespace DS4Windows return m_Config.sASteeringWheelEmulationAxis[index]; } + public static int[] SASteeringWheelEmulationRange => m_Config.sASteeringWheelEmulationRange; + public static int getSASteeringWheelEmulationRange(int index) + { + return m_Config.sASteeringWheelEmulationRange[index]; + } + public static int[][] TouchDisInvertTriggers => m_Config.touchDisInvertTriggers; public static int[] getTouchDisInvertTriggers(int index) { @@ -1514,6 +1520,7 @@ namespace DS4Windows public string[] sATriggers = new string[5] { string.Empty, string.Empty, string.Empty, string.Empty, string.Empty }; public bool[] sATriggerCond = new bool[5] { true, true, true, true, true }; public DS4Controls[] sASteeringWheelEmulationAxis = new DS4Controls[5] { DS4Controls.None, DS4Controls.None, DS4Controls.None, DS4Controls.None, DS4Controls.None }; + public int[] sASteeringWheelEmulationRange = new int[5] { 360, 360, 360, 360, 360 }; public int[][] touchDisInvertTriggers = new int[5][] { new int[1] { -1 }, new int[1] { -1 }, new int[1] { -1 }, new int[1] { -1 }, new int[1] { -1 } }; public int[] lsCurve = new int[5] { 0, 0, 0, 0, 0 }; @@ -1761,6 +1768,7 @@ namespace DS4Windows XmlNode xmlSATriggers = m_Xdoc.CreateNode(XmlNodeType.Element, "SATriggers", null); xmlSATriggers.InnerText = sATriggers[device].ToString(); Node.AppendChild(xmlSATriggers); XmlNode xmlSATriggerCond = m_Xdoc.CreateNode(XmlNodeType.Element, "SATriggerCond", null); xmlSATriggerCond.InnerText = SaTriggerCondString(sATriggerCond[device]); Node.AppendChild(xmlSATriggerCond); XmlNode xmlSASteeringWheelEmulationAxis = m_Xdoc.CreateNode(XmlNodeType.Element, "SASteeringWheelEmulationAxis", null); xmlSASteeringWheelEmulationAxis.InnerText = sASteeringWheelEmulationAxis[device].ToString("G"); Node.AppendChild(xmlSASteeringWheelEmulationAxis); + XmlNode xmlSASteeringWheelEmulationRange = m_Xdoc.CreateNode(XmlNodeType.Element, "SASteeringWheelEmulationRange", null); xmlSASteeringWheelEmulationRange.InnerText = sASteeringWheelEmulationRange[device].ToString(); Node.AppendChild(xmlSASteeringWheelEmulationRange); XmlNode xmlTouchDisInvTriggers = m_Xdoc.CreateNode(XmlNodeType.Element, "TouchDisInvTriggers", null); string tempTouchDisInv = string.Join(",", touchDisInvertTriggers[device]); @@ -2640,6 +2648,9 @@ namespace DS4Windows try { Item = m_Xdoc.SelectSingleNode("/" + rootname + "/SASteeringWheelEmulationAxis"); DS4Controls.TryParse(Item.InnerText, out sASteeringWheelEmulationAxis[device]); } catch { sASteeringWheelEmulationAxis[device] = DS4Controls.None; missingSetting = true; } + try { Item = m_Xdoc.SelectSingleNode("/" + rootname + "/SASteeringWheelEmulationRange"); int.TryParse(Item.InnerText, out sASteeringWheelEmulationRange[device]); } + catch { sASteeringWheelEmulationRange[device] = 360; missingSetting = true; } + try { Item = m_Xdoc.SelectSingleNode("/" + rootname + "/TouchDisInvTriggers"); @@ -3281,6 +3292,10 @@ namespace DS4Windows el.AppendChild(m_Xdoc.CreateElement("Type")).InnerText = "MultiAction"; el.AppendChild(m_Xdoc.CreateElement("Details")).InnerText = details; break; + case 8: + el.AppendChild(m_Xdoc.CreateElement("Type")).InnerText = "SASteeringWheelEmulationCalibrate"; + el.AppendChild(m_Xdoc.CreateElement("Details")).InnerText = details; + break; } if (edit) @@ -3400,6 +3415,14 @@ namespace DS4Windows { actions.Add(new SpecialAction(name, controls, type, details)); } + else if (type == "SASteeringWheelEmulationCalibrate") + { + double doub; + if (double.TryParse(details, out doub)) + actions.Add(new SpecialAction(name, controls, type, "", doub)); + else + actions.Add(new SpecialAction(name, controls, type, "")); + } } } catch { saved = false; } @@ -3920,6 +3943,7 @@ namespace DS4Windows sATriggers[device] = string.Empty; sATriggerCond[device] = true; sASteeringWheelEmulationAxis[device] = DS4Controls.None; + sASteeringWheelEmulationRange[device] = 360; touchDisInvertTriggers[device] = new int[1] { -1 }; lsCurve[device] = rsCurve[device] = 0; gyroSensitivity[device] = 100; @@ -3941,7 +3965,7 @@ namespace DS4Windows public class SpecialAction { - public enum ActionTypeId { None, Key, Program, Profile, Macro, DisconnectBT, BatteryCheck, MultiAction, XboxGameDVR } + public enum ActionTypeId { None, Key, Program, Profile, Macro, DisconnectBT, BatteryCheck, MultiAction, XboxGameDVR, SASteeringWheelEmulationCalibrate } public string name; public List trigger = new List(); @@ -4059,6 +4083,10 @@ namespace DS4Windows type = "MultiAction"; this.details = string.Join(",", macros); } + else if (type == "SASteeringWheelEmulationCalibrate") + { + typeID = ActionTypeId.SASteeringWheelEmulationCalibrate; + } else this.details = details; diff --git a/DS4Windows/DS4Forms/Options.cs b/DS4Windows/DS4Forms/Options.cs index 7c9aa91..bad6866 100644 --- a/DS4Windows/DS4Forms/Options.cs +++ b/DS4Windows/DS4Forms/Options.cs @@ -873,6 +873,9 @@ namespace DS4Windows case "MultiAction": lvi.SubItems.Add(Properties.Resources.MultiAction); break; + case "SASteeringWheelEmulationCalibrate": + lvi.SubItems.Add(Properties.Resources.SASteeringWheelEmulationCalibrate); + break; } if (newp) diff --git a/DS4Windows/DS4Forms/SpecActions.Designer.cs b/DS4Windows/DS4Forms/SpecActions.Designer.cs index 054a3a3..3283401 100644 --- a/DS4Windows/DS4Forms/SpecActions.Designer.cs +++ b/DS4Windows/DS4Forms/SpecActions.Designer.cs @@ -86,7 +86,6 @@ this.lbDTapDVR = new System.Windows.Forms.Label(); this.lbHoldDVR = new System.Windows.Forms.Label(); this.lbTapDVR = new System.Windows.Forms.Label(); - this.advColorDialog = new DS4Windows.AdvancedColorDialog(); ((System.ComponentModel.ISupportInitialize)(this.pBProgram)).BeginInit(); this.pnlProgram.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.nUDProg)).BeginInit(); @@ -221,7 +220,8 @@ resources.GetString("cBActions.Items4"), resources.GetString("cBActions.Items5"), resources.GetString("cBActions.Items6"), - resources.GetString("cBActions.Items7")}); + resources.GetString("cBActions.Items7"), + resources.GetString("cBActions.Items8")}); resources.ApplyResources(this.cBActions, "cBActions"); this.cBActions.Name = "cBActions"; this.cBActions.SelectedIndexChanged += new System.EventHandler(this.cBActions_SelectedIndexChanged); @@ -596,13 +596,6 @@ resources.ApplyResources(this.lbTapDVR, "lbTapDVR"); this.lbTapDVR.Name = "lbTapDVR"; // - // advColorDialog - // - this.advColorDialog.AnyColor = true; - this.advColorDialog.Color = System.Drawing.Color.Blue; - this.advColorDialog.FullOpen = true; - this.advColorDialog.OnUpdateColor += new DS4Windows.AdvancedColorDialog.ColorUpdateHandler(this.advColorDialog_OnUpdateColor); - // // SpecActions // resources.ApplyResources(this, "$this"); diff --git a/DS4Windows/DS4Forms/SpecActions.cs b/DS4Windows/DS4Forms/SpecActions.cs index 3f65003..d70aa69 100644 --- a/DS4Windows/DS4Forms/SpecActions.cs +++ b/DS4Windows/DS4Forms/SpecActions.cs @@ -177,6 +177,10 @@ namespace DS4Windows cBHoldDVR.SelectedIndex = int.Parse(dets[1]); cBDTapDVR.SelectedIndex = int.Parse(dets[2]);*/ break; + case "SASteeringWheelEmulationCalibrate": + cBActions.SelectedIndex = 8; + nUDDCBT.Value = (decimal)act.delayTime; + break; } } @@ -331,6 +335,13 @@ namespace DS4Windows } break; + case 8: + action = Properties.Resources.SASteeringWheelEmulationCalibrate; + actRe = true; + if (!string.IsNullOrEmpty(oldprofilename) && oldprofilename != tBName.Text) + Global.RemoveAction(oldprofilename); + Global.SaveAction(tBName.Text, String.Join("/", controls), cBActions.SelectedIndex, Math.Round(nUDDCBT.Value, 1).ToString(), edit); + break; } if (actRe) { @@ -368,7 +379,7 @@ namespace DS4Windows pnlProgram.Visible = i == 2; pnlProfile.Visible = i == 3; pnlKeys.Visible = i == 4; - pnlDisconnectBT.Visible = i == 5; + pnlDisconnectBT.Visible = i == 5 || i == 8; // SASteeringWheelEmulationCalibrate action #8 re-uses DisconnectBT panel ("hold for X secs" detail option) pnlBatteryCheck.Visible = i == 6; pnlGameDVR.Visible = i == 7; btnSave.Enabled = i > 0; diff --git a/DS4Windows/DS4Forms/SpecActions.resx b/DS4Windows/DS4Forms/SpecActions.resx index 1df5a54..13b7a3a 100644 --- a/DS4Windows/DS4Forms/SpecActions.resx +++ b/DS4Windows/DS4Forms/SpecActions.resx @@ -796,13 +796,10 @@ - 19, 41 - - - 4, 4, 4, 4 + 14, 33 - 237, 267 + 178, 217 14 @@ -825,11 +822,8 @@ 0, 0 - - 4, 4, 4, 4 - - 204, 28 + 153, 23 16 @@ -853,13 +847,10 @@ NoControl - 1, 33 - - - 4, 4, 4, 4 + 1, 27 - 204, 28 + 153, 23 16 @@ -882,11 +873,8 @@ 0, 0 - - 4, 4, 4, 4 - - 203, 24 + 153, 21 17 @@ -913,13 +901,10 @@ NoControl - 275, 282 - - - 4, 4, 4, 4 + 206, 229 - 105, 28 + 79, 23 16 @@ -946,13 +931,10 @@ NoControl - 388, 282 - - - 4, 4, 4, 4 + 291, 229 - 91, 28 + 68, 23 16 @@ -976,13 +958,10 @@ NoControl - 16, 10 - - - 4, 0, 4, 0 + 12, 8 - 72, 16 + 54, 13 15 @@ -1009,13 +988,10 @@ Top, Left, Right - 77, 6 - - - 4, 4, 4, 4 + 58, 5 - 431, 22 + 324, 20 18 @@ -1056,14 +1032,14 @@ Mutli Action Button - - 273, 38 + + Calibration of sixaxis wheel emulation - - 4, 4, 4, 4 + + 205, 31 - 203, 24 + 153, 21 17 @@ -1093,13 +1069,10 @@ NoControl - 173, 65 - - - 4, 4, 4, 4 + 130, 53 - 31, 28 + 23, 23 Zoom @@ -1123,13 +1096,10 @@ NoControl - 4, 65 - - - 4, 0, 4, 0 + 3, 53 - 163, 28 + 122, 23 15 @@ -1159,13 +1129,10 @@ NoControl - 16, 38 - - - 4, 4, 4, 4 + 12, 31 - 243, 272 + 182, 221 257 @@ -1186,13 +1153,10 @@ NoControl - 0, 33 - - - 4, 4, 4, 4 + 0, 27 - 204, 28 + 153, 23 258 @@ -1888,13 +1852,10 @@ - 19, 41 - - - 4, 4, 4, 4 + 14, 33 - 237, 267 + 178, 217 259 @@ -1912,13 +1873,10 @@ 7 - 5, 112 - - - 4, 4, 4, 4 + 4, 91 - 196, 22 + 148, 20 264 @@ -1936,13 +1894,10 @@ 0 - 75, 4 - - - 4, 4, 4, 4 + 56, 3 - 71, 22 + 53, 20 263 @@ -1966,13 +1921,10 @@ NoControl - 4, 94 - - - 4, 0, 4, 0 + 3, 76 - 76, 17 + 57, 13 261 @@ -1999,20 +1951,17 @@ NoControl - 4, 6 - - - 4, 0, 4, 0 + 3, 5 - 63, 22 + 47, 18 261 Hold for - @Invariant + TopCenter @@ -2032,20 +1981,17 @@ NoControl - 153, 6 - - - 4, 0, 4, 0 + 115, 5 - 44, 22 + 33, 18 262 secs - @Invariant + TopCenter @@ -2062,13 +2008,10 @@ 4 - 275, 71 - - - 4, 4, 4, 4 + 206, 58 - 216, 153 + 162, 124 260 @@ -2095,13 +2038,10 @@ NoControl - 5, 37 - - - 4, 4, 4, 4 + 4, 30 - 99, 21 + 79, 17 17 @@ -2125,13 +2065,10 @@ NoControl - 0, 62 - - - 4, 0, 4, 0 + 0, 50 - 204, 28 + 153, 23 15 @@ -2152,13 +2089,10 @@ 2 - 275, 71 - - - 4, 4, 4, 4 + 206, 58 - 217, 116 + 163, 94 261 @@ -2182,13 +2116,10 @@ NoControl - 0, 68 - - - 4, 0, 4, 0 + 0, 55 - 133, 28 + 100, 23 259 @@ -2206,13 +2137,10 @@ 0 - 275, 71 - - - 4, 4, 4, 4 + 206, 58 - 215, 116 + 161, 94 262 @@ -2233,13 +2161,10 @@ 11 - 75, 4 - - - 4, 4, 4, 4 + 56, 3 - 71, 22 + 53, 20 260 @@ -2260,13 +2185,10 @@ NoControl - 4, 6 - - - 4, 0, 4, 0 + 3, 5 - 63, 22 + 47, 18 259 @@ -2293,13 +2215,10 @@ NoControl - 153, 6 - - - 4, 0, 4, 0 + 115, 5 - 44, 22 + 33, 18 259 @@ -2323,13 +2242,10 @@ 2 - 275, 71 - - - 4, 4, 4, 4 + 206, 58 - 215, 73 + 161, 59 262 @@ -2353,13 +2269,10 @@ NoControl - 7, 4 - - - 4, 4, 4, 4 + 5, 3 - 204, 28 + 153, 23 260 @@ -2386,13 +2299,10 @@ releasing unload trigger - 7, 94 - - - 4, 4, 4, 4 + 5, 76 - 203, 24 + 153, 21 17 @@ -2416,13 +2326,10 @@ NoControl - 7, 36 - - - 4, 4, 4, 4 + 5, 29 - 204, 28 + 153, 23 258 @@ -2449,13 +2356,10 @@ NoControl - 7, 75 - - - 4, 0, 4, 0 + 5, 61 - 203, 27 + 152, 22 259 @@ -2482,13 +2386,10 @@ 3 - 267, 71 - - - 4, 4, 4, 4 + 200, 58 - 215, 132 + 161, 107 263 @@ -2512,13 +2413,10 @@ NoControl - 37, 87 - - - 4, 4, 4, 4 + 28, 71 - 145, 16 + 109, 13 264 @@ -2542,13 +2440,10 @@ NoControl - 24, 31 - - - 4, 4, 4, 4 + 18, 25 - 120, 21 + 94, 17 263 @@ -2575,13 +2470,10 @@ NoControl - 24, 54 - - - 4, 4, 4, 4 + 18, 44 - 99, 21 + 77, 17 262 @@ -2608,13 +2500,10 @@ NoControl - 191, 87 - - - 4, 4, 4, 4 + 143, 71 - 17, 16 + 13, 13 261 @@ -2638,13 +2527,10 @@ NoControl - 12, 87 - - - 4, 4, 4, 4 + 9, 71 - 17, 16 + 13, 13 261 @@ -2662,13 +2548,10 @@ 4 - 75, 4 - - - 4, 4, 4, 4 + 56, 3 - 71, 22 + 53, 20 260 @@ -2689,20 +2572,17 @@ NoControl - 4, 6 - - - 4, 0, 4, 0 + 3, 5 - 63, 22 + 47, 18 259 Hold for - @Invariant + TopCenter @@ -2722,20 +2602,17 @@ NoControl - 171, 114 - - - 4, 0, 4, 0 + 128, 93 - 44, 22 + 33, 18 259 100% - @Invariant + TopRight @@ -2755,20 +2632,17 @@ NoControl - 8, 114 - - - 4, 0, 4, 0 + 6, 93 - 44, 22 + 33, 18 259 0% - @Invariant + lbEmptyBatt @@ -2785,20 +2659,17 @@ NoControl - 153, 6 - - - 4, 0, 4, 0 + 115, 5 - 44, 22 + 33, 18 259 secs - @Invariant + TopCenter @@ -2815,13 +2686,10 @@ 9 - 271, 73 - - - 4, 4, 4, 4 + 203, 59 - 215, 151 + 161, 123 264 @@ -2845,13 +2713,10 @@ NoControl - 4, 123 - - - 4, 4, 4, 4 + 3, 100 - 217, 28 + 163, 23 267 @@ -2875,13 +2740,10 @@ NoControl - 6, 73 - - - 4, 4, 4, 4 + 4, 59 - 217, 28 + 163, 23 266 @@ -2905,13 +2767,10 @@ NoControl - 6, 25 - - - 4, 4, 4, 4 + 4, 20 - 217, 28 + 163, 23 265 @@ -2938,13 +2797,10 @@ NoControl - 5, 102 - - - 4, 0, 4, 0 + 4, 83 - 132, 17 + 99, 13 263 @@ -2971,13 +2827,10 @@ NoControl - 5, 54 - - - 4, 0, 4, 0 + 4, 44 - 87, 17 + 65, 13 261 @@ -3004,13 +2857,10 @@ NoControl - 4, 4 - - - 4, 0, 4, 0 + 3, 3 - 83, 17 + 62, 13 259 @@ -3031,13 +2881,10 @@ 5 - 267, 70 - - - 4, 4, 4, 4 + 200, 57 - 228, 154 + 171, 125 264 @@ -3057,24 +2904,18 @@ 0 - - 267, 17 - True - 8, 16 + 6, 13 - 536, 325 - - - 4, 4, 4, 4 + 402, 264 SpecActions - @Invariant + cHTrigger @@ -3099,12 +2940,6 @@ System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - advColorDialog - - - DS4Windows.AdvancedColorDialog, DS4Windows, Version=1.4.5.0, Culture=neutral, PublicKeyToken=null - SpecActions diff --git a/DS4Windows/DS4Library/DS4Device.cs b/DS4Windows/DS4Library/DS4Device.cs index dc18361..1dc2991 100644 --- a/DS4Windows/DS4Library/DS4Device.cs +++ b/DS4Windows/DS4Library/DS4Device.cs @@ -157,6 +157,9 @@ namespace DS4Windows return warnInterval; } + public Int32 wheelPrevPhysicalAngle = 0; + public Int32 wheelFullTurnCount = 0; + public Point wheelCenterPoint; public Point wheel90DegPointLeft; public Point wheelCircleCenterPointLeft; @@ -165,13 +168,13 @@ namespace DS4Windows public DateTime wheelPrevRecalibrateTime; - private bool wheelRecalibrateActive = false; - public bool WheelRecalibrateActive + private int wheelRecalibrateActiveState = 0; + public int WheelRecalibrateActiveState { - get { return wheelRecalibrateActive; } + get { return wheelRecalibrateActiveState; } set { - wheelRecalibrateActive = value; + wheelRecalibrateActiveState = value; } } diff --git a/DS4Windows/DS4Windows.csproj b/DS4Windows/DS4Windows.csproj index aabe5b0..3646923 100644 --- a/DS4Windows/DS4Windows.csproj +++ b/DS4Windows/DS4Windows.csproj @@ -250,6 +250,7 @@ + DS4Form.cs Designer @@ -874,6 +875,7 @@ SpecActions.cs + Designer SpecActions.cs diff --git a/DS4Windows/Properties/Resources.Designer.cs b/DS4Windows/Properties/Resources.Designer.cs index 2f233d7..3236d4e 100644 --- a/DS4Windows/Properties/Resources.Designer.cs +++ b/DS4Windows/Properties/Resources.Designer.cs @@ -1627,6 +1627,15 @@ namespace DS4Windows.Properties { } } + /// + /// Looks up a localized string similar to Calibration of sixaxis wheel emulation. + /// + internal static string SASteeringWheelEmulationCalibrate { + get { + return ResourceManager.GetString("SASteeringWheelEmulationCalibrate", resourceCulture); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// diff --git a/DS4Windows/Properties/Resources.resx b/DS4Windows/Properties/Resources.resx index f04a78a..d6b7155 100644 --- a/DS4Windows/Properties/Resources.resx +++ b/DS4Windows/Properties/Resources.resx @@ -637,6 +637,9 @@ Shortcuts + + Calibration of sixaxis wheel emulation + Click for advanced Sixaxis reading diff --git a/DS4Windows/Settings.cs b/DS4Windows/Settings.cs new file mode 100644 index 0000000..ac0570e --- /dev/null +++ b/DS4Windows/Settings.cs @@ -0,0 +1,28 @@ +namespace DS4Windows.Properties { + + + // This class allows you to handle specific events on the settings class: + // The SettingChanging event is raised before a setting's value is changed. + // The PropertyChanged event is raised after a setting's value is changed. + // The SettingsLoaded event is raised after the setting values are loaded. + // The SettingsSaving event is raised before the setting values are saved. + internal sealed partial class Settings { + + public Settings() { + // // To add event handlers for saving and changing settings, uncomment the lines below: + // + // this.SettingChanging += this.SettingChangingEventHandler; + // + // this.SettingsSaving += this.SettingsSavingEventHandler; + // + } + + private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) { + // Add code to handle the SettingChangingEvent event here. + } + + private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) { + // Add code to handle the SettingsSaving event here. + } + } +} From 94d5f83db10ab6450a876251e8aa331d93d01137 Mon Sep 17 00:00:00 2001 From: mika-n Date: Fri, 7 Dec 2018 00:09:09 +0200 Subject: [PATCH 04/66] Added config options of sixaxis steering wheel emulation and calibration btn to config GUI form (Options). If controller is calibrated via this config screen then there is no need to define "calibrate" special action key. Improved >360 turn range calculation. Added possibility to map SA steering values to L2+R2 trigger axis (Z-axis). For example in ETS2/ATS game controller settings it is possible to use that axis for steering if triggers are not used for throttling and braking (this would leave all axis of L and R thumbstick available for other purposes). --- DS4Windows/DS4Control/Mapping.cs | 182 ++++++++++--------- DS4Windows/DS4Control/X360Device.cs | 19 +- DS4Windows/DS4Forms/Options.Designer.cs | 102 +++++++++-- DS4Windows/DS4Forms/Options.cs | 95 ++++++++++ DS4Windows/DS4Forms/Options.resx | 191 +++++++++++++++++++- DS4Windows/DS4Library/DS4Device.cs | 1 + DS4Windows/Properties/Resources.Designer.cs | 54 ++++++ DS4Windows/Properties/Resources.resx | 18 ++ 8 files changed, 552 insertions(+), 110 deletions(-) diff --git a/DS4Windows/DS4Control/Mapping.cs b/DS4Windows/DS4Control/Mapping.cs index 32e561a..4b052de 100644 --- a/DS4Windows/DS4Control/Mapping.cs +++ b/DS4Windows/DS4Control/Mapping.cs @@ -3804,18 +3804,13 @@ namespace DS4Windows private const int C_WHEEL_ANGLE_PRECISION_DECIMALS = (C_WHEEL_ANGLE_PRECISION == 1 ? 0 : C_WHEEL_ANGLE_PRECISION/10); // "In-game" calibration process: - // TODO: Launching a calibration process should probably be a special action which allows multiple key bindings to launch a specific task. - // - Place controller at "steering wheel center" position and press DS4 Option button to start the calibration (Profile should have "SASteeringWheelEmulationAxis" option set to LXPos, LYPos, RXPos or RYPos value). - // - Hold the controller still for a while and wait until red lightbar turns to blinking yellow (center point calibrated) - // - Turn the controller at 90 degree left or right position and hold still for few seconds and wait until lightbar turns to blinking light blue (two points calibrated) - // - Turn the controller at 90 degree position on the opposite side (but do it by going through 0 degree center position. Don't go through 180deg mark). Wait until lighbar turns to green (three points calibrated) - // - Now you can check the calibratio by turning the wheel and see when the green lightbar starts to blink (it should blink at those three calibrated positions). - // - Press DS4 Options button to accept the calibration (result is saved to ControllerConfigs.xml xml file in AppData folder). + // - Place controller at "steering wheel center" position and press "Calibrate SA steering wheel" special action button to start the calibration + // - Hold the controller still for a while at center point and press "X" + // - Turn the controller at 90 degree left or right position and hold still for few seconds and press "X" + // - Turn the controller at 90 degree position on the opposite side and press "X" + // - Now you can check the calibratio by turning the wheel and see when the green lightbar starts to blink (it should blink at those three calibrated positions) + // - Press "Calibrate SA steering wheel" special action key to accept the calibration (result is saved to ControllerConfigs.xml xml file) // - // 0 = None of the anchors calibrated yet. Hold controller still at "wheel center position" and wait until lightbar turns from constant red to flashing yellow color - // 1 = one anchor calibrated (The first calibration point should always be the center position) - // 2 = two anchors calibrated (center and 90Right or 90Left depending on which way user turn the wheel after the first center calibration point) - // 3 = all three anchor points calibrated (center, 90Right, 90Left). Good to go. User can check calibration by turning the wheel and checking when the green lightbar blinks. If happy then pressing Options btn accepts the calibration. private static readonly DS4Color calibrationColor_0 = new DS4Color { red = 0xA0, green = 0x00, blue = 0x00 }; private static readonly DS4Color calibrationColor_1 = new DS4Color { red = 0xFF, green = 0xFF, blue = 0x00 }; private static readonly DS4Color calibrationColor_2 = new DS4Color { red = 0x00, green = 0x50, blue = 0x50 }; @@ -3851,7 +3846,6 @@ namespace DS4Windows } // Calculate and return the angle of the controller as -180...0...+180 value. - // TODO: Support >360 degree turn range by adding "lap counter" when wheel is rotated full rounds left or right.At the moment this logic supports only 360 degree turn range. private static Int32 CalculateControllerAngle(int gyroAccelX, int gyroAccelZ, DS4Device controller) { Int32 result; @@ -3908,6 +3902,7 @@ namespace DS4Windows return result; } + // Calibrate sixaxis steering wheel emulation. Use DS4Windows configuration screen to start a calibration or press a special action key (if defined) private static void SAWheelEmulationCalibration(int device, DS4StateExposed exposedState, ControlService ctrl, DS4State currentDeviceState, DS4Device controller) { int gyroAccelX, gyroAccelZ; @@ -3916,8 +3911,7 @@ namespace DS4Windows gyroAccelX = exposedState.getAccelX(); gyroAccelZ = exposedState.getAccelZ(); - // "SASteeringWheelEmulaationCalibration" action key combination is used to run "in-game" calibration process (user can define the action key combination in DS4Windows GUI). - // State 0=Normal mode (ie. calibration process is not running), 1=Activating calibration, 2=Calibration process running, 3=Completing calibration + // State 0=Normal mode (ie. calibration process is not running), 1=Activating calibration, 2=Calibration process running, 3=Completing calibration, 4=Cancelling calibration if (controller.WheelRecalibrateActiveState == 1) { AppLogger.LogToGui($"Controller {ctrl.x360Bus.FirstController + device} activated re-calibration of SA steering wheel emulation", false); @@ -3925,21 +3919,22 @@ namespace DS4Windows controller.WheelRecalibrateActiveState = 2; controller.wheelPrevPhysicalAngle = 0; + controller.wheelPrevFullAngle = 0; controller.wheelFullTurnCount = 0; // Clear existing calibration value and use current position as "center" point. // This initial center value may be off-center because of shaking the controller while button was pressed. The value will be overriden with correct value once controller is stabilized and hold still few secs at the center point controller.wheelCenterPoint.X = gyroAccelX; controller.wheelCenterPoint.Y = gyroAccelZ; - controller.wheel90DegPointRight.X = gyroAccelX + 25; - controller.wheel90DegPointLeft.X = gyroAccelX - 25; + controller.wheel90DegPointRight.X = gyroAccelX + 20; + controller.wheel90DegPointLeft.X = gyroAccelX - 20; // Clear bitmask for calibration points. All three calibration points need to be set before re-calibration process is valid controller.wheelCalibratedAxisBitmask = DS4Device.WheelCalibrationPoint.None; - controller.wheelPrevRecalibrateTime = DateTime.Now; + controller.wheelPrevRecalibrateTime = new DateTime(2500, 1, 1); } - else if (controller.WheelRecalibrateActiveState == 3 /*&& currentDeviceState.Options && ((TimeSpan)(DateTime.Now - controller.wheelPrevRecalibrateTime)).TotalSeconds > 3 */) + else if (controller.WheelRecalibrateActiveState == 3) { AppLogger.LogToGui($"Controller {ctrl.x360Bus.FirstController + device} completed the calibration of SA steering wheel emulation. center=({controller.wheelCenterPoint.X}, {controller.wheelCenterPoint.Y}) 90L=({controller.wheel90DegPointLeft.X}, {controller.wheel90DegPointLeft.Y}) 90R=({controller.wheel90DegPointRight.X}, {controller.wheel90DegPointRight.Y})", false); @@ -3949,36 +3944,34 @@ namespace DS4Windows else controller.wheelCenterPoint.X = controller.wheelCenterPoint.Y = 0; - // Reset lightbar back to normal color - // TODO: hmmm... Sometimes color is not reset back to normal "main color". Investigate why following code logic doesn't always restore it. - DS4LightBar.forcelight[device] = false; - DS4LightBar.forcedFlash[device] = 0; - DS4LightBar.updateLightBar(controller, device); - - controller.LightBarColor = Global.getMainColor(device); - DS4LightBar.updateLightBar(controller, device); + controller.WheelRecalibrateActiveState = 0; + controller.wheelPrevRecalibrateTime = DateTime.Now; + } + else if (controller.WheelRecalibrateActiveState == 4) + { + AppLogger.LogToGui($"Controller {ctrl.x360Bus.FirstController + device} cancelled the calibration of SA steering wheel emulation.", false); controller.WheelRecalibrateActiveState = 0; - controller.wheelPrevRecalibrateTime = DateTime.Now; } if (controller.WheelRecalibrateActiveState > 0) { - // Auto calibrate 90deg left/right positions (these values may change over time because gyro/accel sensor values are not "precise mathematics", so user can trigger calibration even in mid-game sessions by pressing DS4 Options btn), - // but make sure controller is stable enough to avoid misaligments because of hard shaking (check velocity of gyro axis) - if (Math.Abs(currentDeviceState.Motion.angVelPitch) < 0.5 && Math.Abs(currentDeviceState.Motion.angVelYaw) < 0.5 && Math.Abs(currentDeviceState.Motion.angVelRoll) < 0.5) + // Cross "X" key pressed. Set calibration point when the key is released and controller hold steady for a few seconds + if(currentDeviceState.Cross == true) controller.wheelPrevRecalibrateTime = DateTime.Now; + + // Make sure controller is hold steady (velocity of gyro axis) to avoid misaligments and set calibration few secs after the "X" key was released + if (Math.Abs(currentDeviceState.Motion.angVelPitch) < 0.5 && Math.Abs(currentDeviceState.Motion.angVelYaw) < 0.5 && Math.Abs(currentDeviceState.Motion.angVelRoll) < 0.5 + && ((TimeSpan)(DateTime.Now - controller.wheelPrevRecalibrateTime)).TotalSeconds > 1) { + controller.wheelPrevRecalibrateTime = new DateTime(2500, 1, 1); + if (controller.wheelCalibratedAxisBitmask == DS4Device.WheelCalibrationPoint.None) { - // Wait few secs after re-calibration button was pressed. Hold controller still at center position and don't shake it too much until red lightbar turns to yellow. - if (((TimeSpan)(DateTime.Now - controller.wheelPrevRecalibrateTime)).TotalSeconds >= 3) - { - controller.wheelCenterPoint.X = gyroAccelX; - controller.wheelCenterPoint.Y = gyroAccelZ; + controller.wheelCenterPoint.X = gyroAccelX; + controller.wheelCenterPoint.Y = gyroAccelZ; - controller.wheelCalibratedAxisBitmask |= DS4Device.WheelCalibrationPoint.Center; - } + controller.wheelCalibratedAxisBitmask |= DS4Device.WheelCalibrationPoint.Center; } else if (controller.wheel90DegPointRight.X < gyroAccelX) { @@ -4001,8 +3994,7 @@ namespace DS4Windows } // Show lightbar color feedback how the calibration process is proceeding. - // red / yellow / blue / green = No calibration anchors/one anchor/two anchors/three anchors calibrated (center, 90DegLeft, 90DegRight) - // Blinking led = Controller is tilted at the current calibration point (or calibration routine just set a new anchor point) + // red / yellow / blue / green = No calibration anchors/one anchor/two anchors/all three anchors calibrated when color turns to green (center, 90DegLeft, 90DegRight). int bitsSet = CountNumOfSetBits((int)controller.wheelCalibratedAxisBitmask); if (bitsSet >= 3) DS4LightBar.forcedColor[device] = calibrationColor_3; else if (bitsSet == 2) DS4LightBar.forcedColor[device] = calibrationColor_2; @@ -4010,20 +4002,28 @@ namespace DS4Windows else DS4LightBar.forcedColor[device] = calibrationColor_0; result = CalculateControllerAngle(gyroAccelX, gyroAccelZ, controller); - if (bitsSet >= 1 && ( - Math.Abs(result) <= 1 * C_WHEEL_ANGLE_PRECISION - || (Math.Abs(result) >= 88 * C_WHEEL_ANGLE_PRECISION && Math.Abs(result) <= 92 * C_WHEEL_ANGLE_PRECISION) - || Math.Abs(result) >= 178 * C_WHEEL_ANGLE_PRECISION - )) + + // Force lightbar flashing when controller is currently at calibration point (user can verify the calibration before accepting it by looking at flashing lightbar) + if( ((controller.wheelCalibratedAxisBitmask & DS4Device.WheelCalibrationPoint.Center) != 0 && Math.Abs(result) <= 1 * C_WHEEL_ANGLE_PRECISION) + || ((controller.wheelCalibratedAxisBitmask & DS4Device.WheelCalibrationPoint.Left90) != 0 && result <= -89 * C_WHEEL_ANGLE_PRECISION && result >= -91 * C_WHEEL_ANGLE_PRECISION) + || ((controller.wheelCalibratedAxisBitmask & DS4Device.WheelCalibrationPoint.Right90) != 0 && result >= 89 * C_WHEEL_ANGLE_PRECISION && result <= 91 * C_WHEEL_ANGLE_PRECISION) + || ((controller.wheelCalibratedAxisBitmask & DS4Device.WheelCalibrationPoint.Left90) != 0 && Math.Abs(result) >= 179 * C_WHEEL_ANGLE_PRECISION) ) DS4LightBar.forcedFlash[device] = 2; else DS4LightBar.forcedFlash[device] = 0; DS4LightBar.forcelight[device] = true; - //DS4LightBar.updateLightBar(controller, device); LogToGuiSACalibrationDebugMsg($"Calibration values ({gyroAccelX}, {gyroAccelZ}) angle={result / (1.0 * C_WHEEL_ANGLE_PRECISION)}\n"); } + else + { + // Re-calibration completed or cancelled. Set lightbar color back to normal color + DS4LightBar.forcedFlash[device] = 0; + DS4LightBar.forcedColor[device] = Global.getMainColor(device); + DS4LightBar.forcelight[device] = false; + DS4LightBar.updateLightBar(controller, device); + } } protected static Int32 Scale360degreeGyroAxis(int device, DS4StateExposed exposedState, ControlService ctrl) @@ -4036,13 +4036,12 @@ namespace DS4Windows int gyroAccelX, gyroAccelZ; int result; - //controller = Program.rootHub.DS4Controllers[device]; controller = ctrl.DS4Controllers[device]; if (controller == null) return 0; currentDeviceState = controller.getCurrentStateRef(); - // If user has pressed "SASteeringWheelEmulationCalibration" special action key combination then run "in-game" calibration process + // If calibration is active then do the calibration process instead of the normal "angle calculation" if (controller.WheelRecalibrateActiveState > 0) { SAWheelEmulationCalibration(device, exposedState, ctrl, currentDeviceState, controller); @@ -4081,47 +4080,68 @@ namespace DS4Windows controller.wheelPrevRecalibrateTime = DateTime.Now; } - result = CalculateControllerAngle(gyroAccelX, gyroAccelZ, controller); - - if (controller.wheelPrevPhysicalAngle < 0 && result > 0) - { - // If wrapped around from -180 to +180 side then SA steering wheel keeps on turning "left" (ie. beyond 360 degrees) - if ((result - controller.wheelPrevPhysicalAngle) > 180 * C_WHEEL_ANGLE_PRECISION) - controller.wheelFullTurnCount--; - } - else if (controller.wheelPrevPhysicalAngle > 0 && result < 0) - { - // If wrapped around from +180 to -180 side then SA steering wheel keeps on turning "right" (ie. beyond 360 degrees) - if ((controller.wheelPrevPhysicalAngle - result) > 180 * C_WHEEL_ANGLE_PRECISION) - controller.wheelFullTurnCount++; - } - controller.wheelPrevPhysicalAngle = result; - - if (controller.wheelFullTurnCount != 0) - { - if (controller.wheelFullTurnCount > 0) - result = (controller.wheelFullTurnCount * 180 * C_WHEEL_ANGLE_PRECISION) + ((controller.wheelFullTurnCount * 180 * C_WHEEL_ANGLE_PRECISION) + result); - else - result = (controller.wheelFullTurnCount * 180 * C_WHEEL_ANGLE_PRECISION) - ((controller.wheelFullTurnCount * -180 * C_WHEEL_ANGLE_PRECISION) - result); - } - - // TODO: How to prevent "too many laps" problem or reset it (DS4Win doesn't know when a game is running so it keeps counting laps)? int maxRangeRight = Global.getSASteeringWheelEmulationRange(device) / 2 * C_WHEEL_ANGLE_PRECISION; int maxRangeLeft = -maxRangeRight; - if (maxRangeRight != (360 / 2 * C_WHEEL_ANGLE_PRECISION) ) - result = Mapping.ClampInt(maxRangeLeft, result, maxRangeRight); + result = CalculateControllerAngle(gyroAccelX, gyroAccelZ, controller); - // Keep outputting debug data 30secs after the latest re-calibration event (user can check these values from the log screen of DS4Windows GUI) - //if (((TimeSpan)(DateTime.Now - prevRecalibrateTime)).TotalSeconds < 30) - // LogToGuiSACalibrationDebugMsg($"DEBUG gyro=({gyroAccelX}, {gyroAccelZ}) angle={result / (1.0 * C_WHEEL_ANGLE_PRECISION)}"); + // If wrapped around from +180 to -180 side (or vice versa) then SA steering wheel keeps on turning beyond 360 degrees (if range is >360) + int wheelFullTurnCount = controller.wheelFullTurnCount; + if (controller.wheelPrevPhysicalAngle < 0 && result > 0) + { + if ((result - controller.wheelPrevPhysicalAngle) > 180 * C_WHEEL_ANGLE_PRECISION) + if (maxRangeRight > 360 * C_WHEEL_ANGLE_PRECISION) + wheelFullTurnCount--; + else + result = maxRangeLeft; + } + else if (controller.wheelPrevPhysicalAngle > 0 && result < 0) + { + if ((controller.wheelPrevPhysicalAngle - result) > 180 * C_WHEEL_ANGLE_PRECISION) + if (maxRangeRight > 360 * C_WHEEL_ANGLE_PRECISION) + wheelFullTurnCount++; + else + result = maxRangeRight; + } + controller.wheelPrevPhysicalAngle = result; - //LogToGuiSACalibrationDebugMsg($"DEBUG gyro=({gyroAccelX}, {gyroAccelZ}) angle={result / (1.0 * C_WHEEL_ANGLE_PRECISION)} fullTurns={controller.wheelFullTurnCount}", false); + if (wheelFullTurnCount != 0) + { + if (wheelFullTurnCount > 0) + result = (wheelFullTurnCount * 180 * C_WHEEL_ANGLE_PRECISION) + ((wheelFullTurnCount * 180 * C_WHEEL_ANGLE_PRECISION) + result); + else + result = (wheelFullTurnCount * 180 * C_WHEEL_ANGLE_PRECISION) - ((wheelFullTurnCount * -180 * C_WHEEL_ANGLE_PRECISION) - result); + } - // Scale input to a raw x360 thumbstick output scale - //return (((result - (-180 * C_WHEEL_ANGLE_PRECISION)) * (32767 - (-32768))) / (180 * C_WHEEL_ANGLE_PRECISION - (-180 * C_WHEEL_ANGLE_PRECISION))) + (-32768); - return (( (result - maxRangeLeft) * (32767 - (-32768))) / (maxRangeRight - maxRangeLeft)) + (-32768); + // If the new angle is more than 180 degrees further away then this is probably bogus value (controller shaking too much and gyro and velocity sensors went crazy). + // Accept the new angle only when the new angle is within a "stability threshold", otherwise use the previous full angle value. + if (Math.Abs(result - controller.wheelPrevFullAngle) <= 180 * C_WHEEL_ANGLE_PRECISION) + { + controller.wheelPrevFullAngle = result; + controller.wheelFullTurnCount = wheelFullTurnCount; + } + else + { + result = controller.wheelPrevFullAngle; + } + + result = Mapping.ClampInt(maxRangeLeft, result, maxRangeRight); + + //LogToGuiSACalibrationDebugMsg($"DEBUG gyro=({gyroAccelX}, {gyroAccelZ}) gyroPitchRollYaw=({currentDeviceState.Motion.gyroPitch}, {currentDeviceState.Motion.gyroRoll}, {currentDeviceState.Motion.gyroYaw}) gyroPitchRollYaw=({currentDeviceState.Motion.angVelPitch}, {currentDeviceState.Motion.angVelRoll}, {currentDeviceState.Motion.angVelYaw}) angle={result / (1.0 * C_WHEEL_ANGLE_PRECISION)} fullTurns={controller.wheelFullTurnCount}", false); + + // Scale input to a raw x360 16bit output scale, except if output axis of steering wheel emulation is L2+R2 trigger axis. + // L2+R2 triggers use independent 8bit values, so use -255..0..+255 scaled values (therefore L2+R2 Trigger axis supports only 360 turn range) + if (Global.getSASteeringWheelEmulationAxis(device) != DS4Controls.L2) + { + return (((result - maxRangeLeft) * (32767 - (-32768))) / (maxRangeRight - maxRangeLeft)) + (-32768); + } + else + { + result = Convert.ToInt32(Math.Round(result / (1.0 * C_WHEEL_ANGLE_PRECISION))); + if (result < 0) result = -181 - result; + return (((result - (-180)) * (255 - (-255))) / (180 - (-180))) + (-255); + } } } // END: SixAxis steering wheel emulation logic diff --git a/DS4Windows/DS4Control/X360Device.cs b/DS4Windows/DS4Control/X360Device.cs index 7ef8123..a19fc51 100644 --- a/DS4Windows/DS4Control/X360Device.cs +++ b/DS4Windows/DS4Control/X360Device.cs @@ -140,16 +140,27 @@ namespace DS4Windows if (state.PS) Output[11] |= (Byte)(1 << 2); // Guide - Output[12] = state.L2; // Left Trigger - Output[13] = state.R2; // Right Trigger + DS4Controls steeringWheelMappedAxis = Global.getSASteeringWheelEmulationAxis(device); + + if (steeringWheelMappedAxis == DS4Controls.L2) + { + Output[12] = Output[13] = 0; + if (state.SASteeringWheelEmulationUnit >= 0) + Output[12] = (Byte)state.SASteeringWheelEmulationUnit; + else + Output[13] = (Byte)state.SASteeringWheelEmulationUnit; + } + else + { + Output[12] = state.L2; // Left Trigger + Output[13] = state.R2; // Right Trigger + } Int32 ThumbLX; Int32 ThumbLY; Int32 ThumbRX; Int32 ThumbRY; - DS4Controls steeringWheelMappedAxis = Global.getSASteeringWheelEmulationAxis(device); - if (steeringWheelMappedAxis == DS4Controls.LXPos) ThumbLX = state.SASteeringWheelEmulationUnit; else ThumbLX = Scale(state.LX, false); diff --git a/DS4Windows/DS4Forms/Options.Designer.cs b/DS4Windows/DS4Forms/Options.Designer.cs index cd9742a..7bc6cfb 100644 --- a/DS4Windows/DS4Forms/Options.Designer.cs +++ b/DS4Windows/DS4Forms/Options.Designer.cs @@ -188,6 +188,11 @@ this.lbGyroXP = new System.Windows.Forms.Label(); this.bnGyroXN = new System.Windows.Forms.Button(); this.lbGyroXN = new System.Windows.Forms.Label(); + this.lblSteeringWheelEmulationAxis = new System.Windows.Forms.Label(); + this.cBSteeringWheelEmulationAxis = new System.Windows.Forms.ComboBox(); + this.lblSteeringWheelEmulationRange = new System.Windows.Forms.Label(); + this.cBSteeringWheelEmulationRange = new System.Windows.Forms.ComboBox(); + this.btnSteeringWheelEmulationCalibrate = new System.Windows.Forms.Button(); this.tCControls = new System.Windows.Forms.TabControl(); this.tPControls = new System.Windows.Forms.TabPage(); this.lBControls = new System.Windows.Forms.ListBox(); @@ -315,6 +320,8 @@ this.rBSAControls = new System.Windows.Forms.RadioButton(); this.rBSAMouse = new System.Windows.Forms.RadioButton(); this.pnlSAMouse = new System.Windows.Forms.Panel(); + this.label26 = new System.Windows.Forms.Label(); + this.triggerCondAndCombo = new System.Windows.Forms.ComboBox(); this.cBGyroMouseXAxis = new System.Windows.Forms.ComboBox(); this.label16 = new System.Windows.Forms.Label(); this.lbGyroSmooth = new System.Windows.Forms.Label(); @@ -386,8 +393,6 @@ this.optionsTouchInvStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.shareTouchInvStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.psTouchInvStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.triggerCondAndCombo = new System.Windows.Forms.ComboBox(); - this.label26 = new System.Windows.Forms.Label(); this.advColorDialog = new DS4Windows.AdvancedColorDialog(); ((System.ComponentModel.ISupportInitialize)(this.nUDRainbow)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.tBBlueBar)).BeginInit(); @@ -1856,6 +1861,11 @@ this.fLPTiltControls.Controls.Add(this.lbGyroXP); this.fLPTiltControls.Controls.Add(this.bnGyroXN); this.fLPTiltControls.Controls.Add(this.lbGyroXN); + this.fLPTiltControls.Controls.Add(this.lblSteeringWheelEmulationAxis); + this.fLPTiltControls.Controls.Add(this.cBSteeringWheelEmulationAxis); + this.fLPTiltControls.Controls.Add(this.lblSteeringWheelEmulationRange); + this.fLPTiltControls.Controls.Add(this.cBSteeringWheelEmulationRange); + this.fLPTiltControls.Controls.Add(this.btnSteeringWheelEmulationCalibrate); resources.ApplyResources(this.fLPTiltControls, "fLPTiltControls"); this.fLPTiltControls.Name = "fLPTiltControls"; // @@ -1911,6 +1921,56 @@ resources.ApplyResources(this.lbGyroXN, "lbGyroXN"); this.lbGyroXN.Name = "lbGyroXN"; // + // lblSteeringWheelEmulationAxis + // + resources.ApplyResources(this.lblSteeringWheelEmulationAxis, "lblSteeringWheelEmulationAxis"); + this.lblSteeringWheelEmulationAxis.Name = "lblSteeringWheelEmulationAxis"; + // + // cBSteeringWheelEmulationAxis + // + this.cBSteeringWheelEmulationAxis.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cBSteeringWheelEmulationAxis.FormattingEnabled = true; + this.cBSteeringWheelEmulationAxis.Items.AddRange(new object[] { + resources.GetString("cBSteeringWheelEmulationAxis.Items"), + resources.GetString("cBSteeringWheelEmulationAxis.Items1"), + resources.GetString("cBSteeringWheelEmulationAxis.Items2"), + resources.GetString("cBSteeringWheelEmulationAxis.Items3"), + resources.GetString("cBSteeringWheelEmulationAxis.Items4"), + resources.GetString("cBSteeringWheelEmulationAxis.Items5")}); + resources.ApplyResources(this.cBSteeringWheelEmulationAxis, "cBSteeringWheelEmulationAxis"); + this.cBSteeringWheelEmulationAxis.Name = "cBSteeringWheelEmulationAxis"; + this.cBSteeringWheelEmulationAxis.SelectedIndexChanged += new System.EventHandler(this.cBSteeringWheelEmulationAxis_SelectedIndexChanged); + // + // lblSteeringWheelEmulationRange + // + resources.ApplyResources(this.lblSteeringWheelEmulationRange, "lblSteeringWheelEmulationRange"); + this.lblSteeringWheelEmulationRange.Name = "lblSteeringWheelEmulationRange"; + // + // cBSteeringWheelEmulationRange + // + this.cBSteeringWheelEmulationRange.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cBSteeringWheelEmulationRange.FormattingEnabled = true; + this.cBSteeringWheelEmulationRange.Items.AddRange(new object[] { + resources.GetString("cBSteeringWheelEmulationRange.Items"), + resources.GetString("cBSteeringWheelEmulationRange.Items1"), + resources.GetString("cBSteeringWheelEmulationRange.Items2"), + resources.GetString("cBSteeringWheelEmulationRange.Items3"), + resources.GetString("cBSteeringWheelEmulationRange.Items4"), + resources.GetString("cBSteeringWheelEmulationRange.Items5"), + resources.GetString("cBSteeringWheelEmulationRange.Items6"), + resources.GetString("cBSteeringWheelEmulationRange.Items7"), + resources.GetString("cBSteeringWheelEmulationRange.Items8")}); + resources.ApplyResources(this.cBSteeringWheelEmulationRange, "cBSteeringWheelEmulationRange"); + this.cBSteeringWheelEmulationRange.Name = "cBSteeringWheelEmulationRange"; + this.cBSteeringWheelEmulationRange.SelectedIndexChanged += new System.EventHandler(this.cBSteeringWheelEmulationRange_SelectedIndexChanged); + // + // btnSteeringWheelEmulationCalibrate + // + resources.ApplyResources(this.btnSteeringWheelEmulationCalibrate, "btnSteeringWheelEmulationCalibrate"); + this.btnSteeringWheelEmulationCalibrate.Name = "btnSteeringWheelEmulationCalibrate"; + this.btnSteeringWheelEmulationCalibrate.UseVisualStyleBackColor = true; + this.btnSteeringWheelEmulationCalibrate.Click += new System.EventHandler(this.btnSteeringWheelEmulationCalibrate_Click); + // // tCControls // this.tCControls.Controls.Add(this.tPControls); @@ -3362,8 +3422,8 @@ this.gBGyro.BackColor = System.Drawing.SystemColors.Control; this.gBGyro.Controls.Add(this.rBSAControls); this.gBGyro.Controls.Add(this.rBSAMouse); - this.gBGyro.Controls.Add(this.pnlSAMouse); this.gBGyro.Controls.Add(this.fLPTiltControls); + this.gBGyro.Controls.Add(this.pnlSAMouse); resources.ApplyResources(this.gBGyro, "gBGyro"); this.gBGyro.Name = "gBGyro"; this.gBGyro.TabStop = false; @@ -3408,6 +3468,21 @@ resources.ApplyResources(this.pnlSAMouse, "pnlSAMouse"); this.pnlSAMouse.Name = "pnlSAMouse"; // + // label26 + // + resources.ApplyResources(this.label26, "label26"); + this.label26.Name = "label26"; + // + // triggerCondAndCombo + // + this.triggerCondAndCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.triggerCondAndCombo.FormattingEnabled = true; + this.triggerCondAndCombo.Items.AddRange(new object[] { + resources.GetString("triggerCondAndCombo.Items"), + resources.GetString("triggerCondAndCombo.Items1")}); + resources.ApplyResources(this.triggerCondAndCombo, "triggerCondAndCombo"); + this.triggerCondAndCombo.Name = "triggerCondAndCombo"; + // // cBGyroMouseXAxis // this.cBGyroMouseXAxis.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; @@ -4110,21 +4185,6 @@ resources.ApplyResources(this.psTouchInvStripMenuItem, "psTouchInvStripMenuItem"); this.psTouchInvStripMenuItem.CheckedChanged += new System.EventHandler(this.TouchDisableInvert_CheckedChanged); // - // triggerCondAndCombo - // - this.triggerCondAndCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.triggerCondAndCombo.FormattingEnabled = true; - this.triggerCondAndCombo.Items.AddRange(new object[] { - resources.GetString("triggerCondAndCombo.Items"), - resources.GetString("triggerCondAndCombo.Items1")}); - resources.ApplyResources(this.triggerCondAndCombo, "triggerCondAndCombo"); - this.triggerCondAndCombo.Name = "triggerCondAndCombo"; - // - // label26 - // - resources.ApplyResources(this.label26, "label26"); - this.label26.Name = "label26"; - // // Options // resources.ApplyResources(this, "$this"); @@ -4192,6 +4252,7 @@ this.pnlLSTrack.ResumeLayout(false); this.pnlRSTrack.ResumeLayout(false); this.fLPTiltControls.ResumeLayout(false); + this.fLPTiltControls.PerformLayout(); this.tCControls.ResumeLayout(false); this.tPControls.ResumeLayout(false); this.pnlController.ResumeLayout(false); @@ -4614,5 +4675,10 @@ private System.Windows.Forms.CheckBox trackballCk; private System.Windows.Forms.Label label26; private System.Windows.Forms.ComboBox triggerCondAndCombo; + private System.Windows.Forms.Label lblSteeringWheelEmulationAxis; + private System.Windows.Forms.ComboBox cBSteeringWheelEmulationAxis; + private System.Windows.Forms.Label lblSteeringWheelEmulationRange; + private System.Windows.Forms.ComboBox cBSteeringWheelEmulationRange; + private System.Windows.Forms.Button btnSteeringWheelEmulationCalibrate; } } \ No newline at end of file diff --git a/DS4Windows/DS4Forms/Options.cs b/DS4Windows/DS4Forms/Options.cs index bad6866..b10b94c 100644 --- a/DS4Windows/DS4Forms/Options.cs +++ b/DS4Windows/DS4Forms/Options.cs @@ -718,6 +718,20 @@ namespace DS4Windows nUDGyroSmoothWeight.Value = (decimal)(GyroSmoothingWeight[device]); cBGyroMouseXAxis.SelectedIndex = GyroMouseHorizontalAxis[device]; triggerCondAndCombo.SelectedIndex = SATriggerCond[device] ? 0 : 1; + + switch (getSASteeringWheelEmulationAxis(device)) + { + case DS4Controls.None: cBSteeringWheelEmulationAxis.SelectedIndex = 0; break; + case DS4Controls.LXPos: cBSteeringWheelEmulationAxis.SelectedIndex = 1; break; + case DS4Controls.LYPos: cBSteeringWheelEmulationAxis.SelectedIndex = 2; break; + case DS4Controls.RXPos: cBSteeringWheelEmulationAxis.SelectedIndex = 3; break; + case DS4Controls.RYPos: cBSteeringWheelEmulationAxis.SelectedIndex = 4; break; + case DS4Controls.L2: + case DS4Controls.R2: cBSteeringWheelEmulationAxis.SelectedIndex = 5; break; + } + + int idxSASteeringWheelEmulationRange = cBSteeringWheelEmulationRange.Items.IndexOf(getSASteeringWheelEmulationRange(device).ToString()); + if (idxSASteeringWheelEmulationRange >= 0) cBSteeringWheelEmulationRange.SelectedIndex = idxSASteeringWheelEmulationRange; } else { @@ -836,6 +850,8 @@ namespace DS4Windows nUDGyroSmoothWeight.Value = 0.5m; cBGyroMouseXAxis.SelectedIndex = 0; triggerCondAndCombo.SelectedIndex = 0; + cBSteeringWheelEmulationAxis.SelectedIndex = 0; + cBSteeringWheelEmulationRange.SelectedIndex = cBSteeringWheelEmulationRange.Items.IndexOf("360"); Set(); } @@ -2992,6 +3008,85 @@ namespace DS4Windows } } + private void cBSteeringWheelEmulationRange_SelectedIndexChanged(object sender, EventArgs e) + { + if (loading == false) + { + SASteeringWheelEmulationRange[device] = Convert.ToInt32(cBSteeringWheelEmulationRange.Items[cBSteeringWheelEmulationRange.SelectedIndex].ToString()); + } + } + + private void cBSteeringWheelEmulationAxis_SelectedIndexChanged(object sender, EventArgs e) + { + if (loading == false) + { + switch (cBSteeringWheelEmulationAxis.SelectedIndex) + { + case 0: SASteeringWheelEmulationAxis[device] = DS4Controls.None; break; // Gyro SA steering wheel emulation disabled + case 1: SASteeringWheelEmulationAxis[device] = DS4Controls.LXPos; break; // Left stick X axis + case 2: SASteeringWheelEmulationAxis[device] = DS4Controls.LYPos; break; // Left stick Y axis + case 3: SASteeringWheelEmulationAxis[device] = DS4Controls.RXPos; break; // Right stick X axis + case 4: SASteeringWheelEmulationAxis[device] = DS4Controls.RYPos; break; // Right stick Y axis + case 5: SASteeringWheelEmulationAxis[device] = DS4Controls.L2; break; // Left+Right trigger axis (max range -255..0 as left trigger and 0..+255 as right trigger) + } + } + } + + private void btnSteeringWheelEmulationCalibrate_Click(object sender, EventArgs e) + { + if(cBSteeringWheelEmulationAxis.SelectedIndex > 0) + { + DS4Device d; + int tempDeviceNum = (int)nUDSixaxis.Value - 1; + + d = Program.rootHub.DS4Controllers[tempDeviceNum]; + if (d != null) + { + Point origWheelCenterPoint = new Point(d.wheelCenterPoint.X, d.wheelCenterPoint.Y); + Point origWheel90DegPointLeft = new Point(d.wheel90DegPointLeft.X, d.wheel90DegPointLeft.Y); + Point origWheel90DegPointRight = new Point(d.wheel90DegPointRight.X, d.wheel90DegPointRight.Y); + + d.WheelRecalibrateActiveState = 1; + + DialogResult msgBoxResult = MessageBox.Show($"{Properties.Resources.SASteeringWheelEmulationCalibrate}.\n\n" + + $"{Properties.Resources.SASteeringWheelEmulationCalibrateInstruction1}.\n" + + $"{Properties.Resources.SASteeringWheelEmulationCalibrateInstruction2}.\n" + + $"{Properties.Resources.SASteeringWheelEmulationCalibrateInstruction3}.\n\n" + + $"{Properties.Resources.SASteeringWheelEmulationCalibrateInstruction}.\n", + Properties.Resources.SASteeringWheelEmulationCalibrate, + MessageBoxButtons.OKCancel, + MessageBoxIcon.Information, + MessageBoxDefaultButton.Button1, + 0, + false); + + if (msgBoxResult == DialogResult.OK) + { + // Accept new calibration values (State 3 is "Complete calibration" state) + d.WheelRecalibrateActiveState = 3; + } + else + { + // Cancel calibration and reset back to original calibration values + d.WheelRecalibrateActiveState = 4; + + d.wheelFullTurnCount = 0; + d.wheelCenterPoint = origWheelCenterPoint; + d.wheel90DegPointLeft = origWheel90DegPointLeft; + d.wheel90DegPointRight = origWheel90DegPointRight; + } + } + else + { + MessageBox.Show($"{Properties.Resources.SASteeringWheelEmulationCalibrateNoControllerError}."); + } + } + else + { + MessageBox.Show($"{Properties.Resources.SASteeringWheelEmulationCalibrateNoneAxisError}."); + } + } + private void trackFrictionNUD_ValueChanged(object sender, EventArgs e) { if (loading == false) diff --git a/DS4Windows/DS4Forms/Options.resx b/DS4Windows/DS4Forms/Options.resx index dc50f18..4a5c38d 100644 --- a/DS4Windows/DS4Forms/Options.resx +++ b/DS4Windows/DS4Forms/Options.resx @@ -4057,11 +4057,191 @@ with profile 7 + + True + + + NoControl + + + 3, 116 + + + 0, 5, 0, 0 + + + 98, 18 + + + 290 + + + Steering wheel axis + + + lblSteeringWheelEmulationAxis + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + fLPTiltControls + + + 8 + + + None + + + Left X-Axis + + + Left Y-Axis + + + Right X-Axis + + + Right Y-Axis + + + Trigger L+R Axis + + + 107, 119 + + + 110, 21 + + + 291 + + + cBSteeringWheelEmulationAxis + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + fLPTiltControls + + + 9 + + + True + + + NoControl + + + 3, 143 + + + 0, 5, 0, 0 + + + 107, 18 + + + 292 + + + Steering wheel range + + + lblSteeringWheelEmulationRange + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + fLPTiltControls + + + 10 + + + 90 + + + 180 + + + 270 + + + 360 + + + 450 + + + 720 + + + 900 + + + 1080 + + + 1440 + + + 116, 146 + + + 60, 21 + + + 293 + + + cBSteeringWheelEmulationRange + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + fLPTiltControls + + + 11 + + + NoControl + + + 182, 146 + + + 75, 23 + + + 294 + + + Calibrate... + + + btnSteeringWheelEmulationCalibrate + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + fLPTiltControls + + + 12 + 4, 43 - 271, 167 + 271, 170 254 @@ -4076,7 +4256,7 @@ with profile gBGyro - 3 + 2 True @@ -8297,7 +8477,7 @@ with profile gBGyro - 2 + 3 3, 253 @@ -8971,9 +9151,6 @@ with profile 1011, 481 - - NoControl - 4, 4, 4, 4 @@ -9392,7 +9569,7 @@ with profile advColorDialog - DS4Windows.AdvancedColorDialog, DS4Windows, Version=1.5.8.0, Culture=neutral, PublicKeyToken=null + DS4Windows.AdvancedColorDialog, DS4Windows, Version=1.5.17.0, Culture=neutral, PublicKeyToken=null Options diff --git a/DS4Windows/DS4Library/DS4Device.cs b/DS4Windows/DS4Library/DS4Device.cs index 1dc2991..283e582 100644 --- a/DS4Windows/DS4Library/DS4Device.cs +++ b/DS4Windows/DS4Library/DS4Device.cs @@ -158,6 +158,7 @@ namespace DS4Windows } public Int32 wheelPrevPhysicalAngle = 0; + public Int32 wheelPrevFullAngle = 0; public Int32 wheelFullTurnCount = 0; public Point wheelCenterPoint; diff --git a/DS4Windows/Properties/Resources.Designer.cs b/DS4Windows/Properties/Resources.Designer.cs index 2145fc9..1d7eb76 100644 --- a/DS4Windows/Properties/Resources.Designer.cs +++ b/DS4Windows/Properties/Resources.Designer.cs @@ -1636,6 +1636,60 @@ namespace DS4Windows.Properties { } } + /// + /// Looks up a localized string similar to All calibraton points are set when lightbar color turns to green. While turning the controller the lightbar color flashes when the controller is at calibration point. Accept calibration with OK button. + /// + internal static string SASteeringWheelEmulationCalibrateInstruction { + get { + return ResourceManager.GetString("SASteeringWheelEmulationCalibrateInstruction", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to (1) Center the controller, hold it steady and press "X". + /// + internal static string SASteeringWheelEmulationCalibrateInstruction1 { + get { + return ResourceManager.GetString("SASteeringWheelEmulationCalibrateInstruction1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to (2) Turn to 90° left (or right) position and press "X". + /// + internal static string SASteeringWheelEmulationCalibrateInstruction2 { + get { + return ResourceManager.GetString("SASteeringWheelEmulationCalibrateInstruction2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to (3) Turn to 90° right (or left) position and press "X". + /// + internal static string SASteeringWheelEmulationCalibrateInstruction3 { + get { + return ResourceManager.GetString("SASteeringWheelEmulationCalibrateInstruction3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot calibrate gyro (sixaxis) steering wheel emulation values without a controller. Connect a controller via bluetooth or usb. + /// + internal static string SASteeringWheelEmulationCalibrateNoControllerError { + get { + return ResourceManager.GetString("SASteeringWheelEmulationCalibrateNoControllerError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Gyro steering wheel emulation axis option is set to NONE (emulation is not used). Please select an axis option before calibrating the sixaxis gyro steering wheel emulation. + /// + internal static string SASteeringWheelEmulationCalibrateNoneAxisError { + get { + return ResourceManager.GetString("SASteeringWheelEmulationCalibrateNoneAxisError", resourceCulture); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// diff --git a/DS4Windows/Properties/Resources.resx b/DS4Windows/Properties/Resources.resx index dbc3d2c..af66c79 100644 --- a/DS4Windows/Properties/Resources.resx +++ b/DS4Windows/Properties/Resources.resx @@ -640,6 +640,24 @@ Calibration of sixaxis wheel emulation + + (1) Center the controller, hold it steady and press "X" + + + (2) Turn to 90° left (or right) position and press "X" + + + (3) Turn to 90° right (or left) position and press "X" + + + All calibraton points are set when lightbar color turns to green. While turning the controller the lightbar color flashes when the controller is at calibration point. Accept calibration with OK button + + + Cannot calibrate gyro (sixaxis) steering wheel emulation values without a controller. Connect a controller via bluetooth or usb + + + Gyro steering wheel emulation axis option is set to NONE (emulation is not used). Please select an axis option before calibrating the sixaxis gyro steering wheel emulation + Click for advanced Sixaxis reading From 5bd49065213a069a74ea330fcc01508f14047ab2 Mon Sep 17 00:00:00 2001 From: mika-n Date: Mon, 10 Dec 2018 20:29:49 +0200 Subject: [PATCH 05/66] Fine tunes. synced with upstream changes --- DS4Windows/DS4Control/Mapping.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DS4Windows/DS4Control/Mapping.cs b/DS4Windows/DS4Control/Mapping.cs index 585ca7d..a6daa98 100644 --- a/DS4Windows/DS4Control/Mapping.cs +++ b/DS4Windows/DS4Control/Mapping.cs @@ -4134,11 +4134,11 @@ namespace DS4Windows // L2+R2 triggers use independent 8bit values, so use -255..0..+255 scaled values (therefore L2+R2 Trigger axis supports only 360 turn range) if (Global.getSASteeringWheelEmulationAxis(device) != DS4Controls.L2) { - return (((result - maxRangeLeft) * (32767 - (-32768))) / (maxRangeRight - maxRangeLeft)) + (-32768); + return (((result - maxRangeLeft) * (32767 - (-32768))) / (maxRangeRight - maxRangeLeft)) + (-32768); // Stick axis with configurable range } else { - result = Convert.ToInt32(Math.Round(result / (1.0 * C_WHEEL_ANGLE_PRECISION))); + result = Convert.ToInt32(Math.Round(result / (1.0 * C_WHEEL_ANGLE_PRECISION))); // Trigger axis with fixed 360 range if (result < 0) result = -181 - result; return (((result - (-180)) * (255 - (-255))) / (180 - (-180))) + (-255); } From 5b49a8ed4742ad2557e3759fcfb76537464fd0fa Mon Sep 17 00:00:00 2001 From: mika-n Date: Wed, 2 Jan 2019 21:44:15 +0200 Subject: [PATCH 06/66] SA steering wheel emulation can now feed VJoy virtual joystick device (analog axies there). This leaves all original X360/DS4 analog axies for other purposes. Useful in games which support mapping controls to more than one controller (for example EurotruckSimulator/AmericalTruckSimulator). --- DS4Windows/DS4Control/Mapping.cs | 27 +- DS4Windows/DS4Control/ScpUtil.cs | 14 +- DS4Windows/DS4Control/X360Device.cs | 83 ++- DS4Windows/DS4Forms/Options.Designer.cs | 8 +- DS4Windows/DS4Forms/Options.cs | 22 +- DS4Windows/DS4Forms/Options.resx | 22 +- DS4Windows/DS4Windows.csproj | 7 +- DS4Windows/Program.cs | 2 +- DS4Windows/VJoyFeeder/vJoyFeeder.cs | 701 ++++++++++++++++++++++++ 9 files changed, 823 insertions(+), 63 deletions(-) create mode 100644 DS4Windows/VJoyFeeder/vJoyFeeder.cs diff --git a/DS4Windows/DS4Control/Mapping.cs b/DS4Windows/DS4Control/Mapping.cs index db5766e..15538d7 100644 --- a/DS4Windows/DS4Control/Mapping.cs +++ b/DS4Windows/DS4Control/Mapping.cs @@ -1650,7 +1650,7 @@ namespace DS4Windows } } - if (getSASteeringWheelEmulationAxis(device) != DS4Controls.None) + if (getSASteeringWheelEmulationAxis(device) != SASteeringWheelEmulationAxisType.None) MappedState.SASteeringWheelEmulationUnit = Mapping.Scale360degreeGyroAxis(device, eState, ctrl); calculateFinalMouseMovement(ref tempMouseDeltaX, ref tempMouseDeltaY, @@ -4132,15 +4132,24 @@ namespace DS4Windows // Scale input to a raw x360 16bit output scale, except if output axis of steering wheel emulation is L2+R2 trigger axis. // L2+R2 triggers use independent 8bit values, so use -255..0..+255 scaled values (therefore L2+R2 Trigger axis supports only 360 turn range) - if (Global.getSASteeringWheelEmulationAxis(device) != DS4Controls.L2) + switch(Global.getSASteeringWheelEmulationAxis(device)) { - return (((result - maxRangeLeft) * (32767 - (-32768))) / (maxRangeRight - maxRangeLeft)) + (-32768); // Stick axis with configurable range - } - else - { - result = Convert.ToInt32(Math.Round(result / (1.0 * C_WHEEL_ANGLE_PRECISION))); // Trigger axis with fixed 360 range - if (result < 0) result = -181 - result; - return (((result - (-180)) * (255 - (-255))) / (180 - (-180))) + (-255); + case SASteeringWheelEmulationAxisType.LX: + case SASteeringWheelEmulationAxisType.LY: + case SASteeringWheelEmulationAxisType.RX: + case SASteeringWheelEmulationAxisType.RY: + // DS4 Stick axis values with configurable range + return (((result - maxRangeLeft) * (32767 - (-32768))) / (maxRangeRight - maxRangeLeft)) + (-32768); + + case SASteeringWheelEmulationAxisType.L2R2: + // DS4 Trigger axis values with fixed 360 range + result = Convert.ToInt32(Math.Round(result / (1.0 * C_WHEEL_ANGLE_PRECISION))); + if (result < 0) result = -181 - result; + return (((result - (-180)) * (255 - (-255))) / (180 - (-180))) + (-255); + + default: + // VJoy axis values with configurable range + return (((result - maxRangeLeft) * (32767 - (-0))) / (maxRangeRight - maxRangeLeft)) + (-0); } } } diff --git a/DS4Windows/DS4Control/ScpUtil.cs b/DS4Windows/DS4Control/ScpUtil.cs index e526897..a5f7660 100644 --- a/DS4Windows/DS4Control/ScpUtil.cs +++ b/DS4Windows/DS4Control/ScpUtil.cs @@ -20,6 +20,8 @@ namespace DS4Windows public enum DS4Controls : byte { None, LXNeg, LXPos, LYNeg, LYPos, RXNeg, RXPos, RYNeg, RYPos, L1, L2, L3, R1, R2, R3, Square, Triangle, Circle, Cross, DpadUp, DpadRight, DpadDown, DpadLeft, PS, TouchLeft, TouchUpper, TouchMulti, TouchRight, Share, Options, GyroXPos, GyroXNeg, GyroZPos, GyroZNeg, SwipeLeft, SwipeRight, SwipeUp, SwipeDown }; public enum X360Controls : byte { None, LXNeg, LXPos, LYNeg, LYPos, RXNeg, RXPos, RYNeg, RYPos, LB, LT, LS, RB, RT, RS, X, Y, B, A, DpadUp, DpadRight, DpadDown, DpadLeft, Guide, Back, Start, LeftMouse, RightMouse, MiddleMouse, FourthMouse, FifthMouse, WUP, WDOWN, MouseUp, MouseDown, MouseLeft, MouseRight, Unbound }; + public enum SASteeringWheelEmulationAxisType: byte { None = 0, LX, LY, RX, RY, L2R2, VJoy1X, VJoy1Y, VJoy1Z, VJoy2X, VJoy2Y, VJoy2Z }; + public class DS4ControlSettings { public DS4Controls control; @@ -718,8 +720,8 @@ namespace DS4Windows m_Config.SetSaTriggerCond(index, text); } - public static DS4Controls[] SASteeringWheelEmulationAxis => m_Config.sASteeringWheelEmulationAxis; - public static DS4Controls getSASteeringWheelEmulationAxis(int index) + public static SASteeringWheelEmulationAxisType[] SASteeringWheelEmulationAxis => m_Config.sASteeringWheelEmulationAxis; + public static SASteeringWheelEmulationAxisType getSASteeringWheelEmulationAxis(int index) { return m_Config.sASteeringWheelEmulationAxis[index]; } @@ -1519,7 +1521,7 @@ namespace DS4Windows public bool[] useSAforMouse = new bool[5] { false, false, false, false, false }; public string[] sATriggers = new string[5] { string.Empty, string.Empty, string.Empty, string.Empty, string.Empty }; public bool[] sATriggerCond = new bool[5] { true, true, true, true, true }; - public DS4Controls[] sASteeringWheelEmulationAxis = new DS4Controls[5] { DS4Controls.None, DS4Controls.None, DS4Controls.None, DS4Controls.None, DS4Controls.None }; + public SASteeringWheelEmulationAxisType[] sASteeringWheelEmulationAxis = new SASteeringWheelEmulationAxisType[5] { SASteeringWheelEmulationAxisType.None, SASteeringWheelEmulationAxisType.None, SASteeringWheelEmulationAxisType.None, SASteeringWheelEmulationAxisType.None, SASteeringWheelEmulationAxisType.None }; public int[] sASteeringWheelEmulationRange = new int[5] { 360, 360, 360, 360, 360 }; public int[][] touchDisInvertTriggers = new int[5][] { new int[1] { -1 }, new int[1] { -1 }, new int[1] { -1 }, new int[1] { -1 }, new int[1] { -1 } }; @@ -2645,8 +2647,8 @@ namespace DS4Windows try { Item = m_Xdoc.SelectSingleNode("/" + rootname + "/SATriggerCond"); sATriggerCond[device] = SaTriggerCondValue(Item.InnerText); } catch { sATriggerCond[device] = true; missingSetting = true; } - try { Item = m_Xdoc.SelectSingleNode("/" + rootname + "/SASteeringWheelEmulationAxis"); DS4Controls.TryParse(Item.InnerText, out sASteeringWheelEmulationAxis[device]); } - catch { sASteeringWheelEmulationAxis[device] = DS4Controls.None; missingSetting = true; } + try { Item = m_Xdoc.SelectSingleNode("/" + rootname + "/SASteeringWheelEmulationAxis"); SASteeringWheelEmulationAxisType.TryParse(Item.InnerText, out sASteeringWheelEmulationAxis[device]); } + catch { sASteeringWheelEmulationAxis[device] = SASteeringWheelEmulationAxisType.None; missingSetting = true; } try { Item = m_Xdoc.SelectSingleNode("/" + rootname + "/SASteeringWheelEmulationRange"); int.TryParse(Item.InnerText, out sASteeringWheelEmulationRange[device]); } catch { sASteeringWheelEmulationRange[device] = 360; missingSetting = true; } @@ -3942,7 +3944,7 @@ namespace DS4Windows useSAforMouse[device] = false; sATriggers[device] = string.Empty; sATriggerCond[device] = true; - sASteeringWheelEmulationAxis[device] = DS4Controls.None; + sASteeringWheelEmulationAxis[device] = SASteeringWheelEmulationAxisType.None; sASteeringWheelEmulationRange[device] = 360; touchDisInvertTriggers[device] = new int[1] { -1 }; lsCurve[device] = rsCurve[device] = 0; diff --git a/DS4Windows/DS4Control/X360Device.cs b/DS4Windows/DS4Control/X360Device.cs index 84b9ed5..a8244ee 100644 --- a/DS4Windows/DS4Control/X360Device.cs +++ b/DS4Windows/DS4Control/X360Device.cs @@ -129,38 +129,73 @@ namespace DS4Windows if (state.PS) Output[11] |= (Byte)(1 << 2); // Guide - DS4Controls steeringWheelMappedAxis = Global.getSASteeringWheelEmulationAxis(device); - - if (steeringWheelMappedAxis == DS4Controls.L2) - { - Output[12] = Output[13] = 0; - if (state.SASteeringWheelEmulationUnit >= 0) - Output[12] = (Byte)state.SASteeringWheelEmulationUnit; - else - Output[13] = (Byte)state.SASteeringWheelEmulationUnit; - } - else - { - Output[12] = state.L2; // Left Trigger - Output[13] = state.R2; // Right Trigger - } - + SASteeringWheelEmulationAxisType steeringWheelMappedAxis = Global.getSASteeringWheelEmulationAxis(device); Int32 ThumbLX; Int32 ThumbLY; Int32 ThumbRX; Int32 ThumbRY; - if (steeringWheelMappedAxis == DS4Controls.LXPos) ThumbLX = state.SASteeringWheelEmulationUnit; - else ThumbLX = Scale(state.LX, false); + Output[12] = state.L2; // Left Trigger + Output[13] = state.R2; // Right Trigger - if (steeringWheelMappedAxis == DS4Controls.LYPos) ThumbLY = state.SASteeringWheelEmulationUnit; - else ThumbLY = Scale(state.LY, true); + switch(steeringWheelMappedAxis) + { + case SASteeringWheelEmulationAxisType.LX: + ThumbLX = state.SASteeringWheelEmulationUnit; + ThumbLY = Scale(state.LY, true); + ThumbRX = Scale(state.RX, false); + ThumbRY = Scale(state.RY, true); + break; - if (steeringWheelMappedAxis == DS4Controls.RXPos) ThumbRX = state.SASteeringWheelEmulationUnit; - else ThumbRX = Scale(state.RX, false); + case SASteeringWheelEmulationAxisType.LY: + ThumbLX = Scale(state.LX, false); + ThumbLY = state.SASteeringWheelEmulationUnit; + ThumbRX = Scale(state.RX, false); + ThumbRY = Scale(state.RY, true); + break; - if (steeringWheelMappedAxis == DS4Controls.RYPos) ThumbRY = state.SASteeringWheelEmulationUnit; - else ThumbRY = Scale(state.RY, true); + case SASteeringWheelEmulationAxisType.RX: + ThumbLX = Scale(state.LX, false); + ThumbLY = Scale(state.LY, true); + ThumbRX = state.SASteeringWheelEmulationUnit; + ThumbRY = Scale(state.RY, true); + break; + + case SASteeringWheelEmulationAxisType.RY: + ThumbLX = Scale(state.LX, false); + ThumbLY = Scale(state.LY, true); + ThumbRX = Scale(state.RX, false); + ThumbRY = state.SASteeringWheelEmulationUnit; + break; + + case SASteeringWheelEmulationAxisType.L2R2: + Output[12] = Output[13] = 0; + if (state.SASteeringWheelEmulationUnit >= 0) Output[12] = (Byte)state.SASteeringWheelEmulationUnit; + else Output[13] = (Byte)state.SASteeringWheelEmulationUnit; + goto default; // Usually GOTO is not a good idea but in switch-case statements it is sometimes pretty handy and acceptable way to fall through case options + + case SASteeringWheelEmulationAxisType.VJoy1X: + case SASteeringWheelEmulationAxisType.VJoy2X: + DS4Windows.VJoyFeeder.vJoyFeeder.FeedAxisValue(state.SASteeringWheelEmulationUnit, ((((uint)steeringWheelMappedAxis) - ((uint)SASteeringWheelEmulationAxisType.VJoy1X)) / 3) + 1, DS4Windows.VJoyFeeder.HID_USAGES.HID_USAGE_X); + goto default; + + case SASteeringWheelEmulationAxisType.VJoy1Y: + case SASteeringWheelEmulationAxisType.VJoy2Y: + DS4Windows.VJoyFeeder.vJoyFeeder.FeedAxisValue(state.SASteeringWheelEmulationUnit, ((((uint)steeringWheelMappedAxis) - ((uint)SASteeringWheelEmulationAxisType.VJoy1X)) / 3) + 1, DS4Windows.VJoyFeeder.HID_USAGES.HID_USAGE_Y); + goto default; + + case SASteeringWheelEmulationAxisType.VJoy1Z: + case SASteeringWheelEmulationAxisType.VJoy2Z: + DS4Windows.VJoyFeeder.vJoyFeeder.FeedAxisValue(state.SASteeringWheelEmulationUnit, ((((uint)steeringWheelMappedAxis) - ((uint)SASteeringWheelEmulationAxisType.VJoy1X)) / 3) + 1, DS4Windows.VJoyFeeder.HID_USAGES.HID_USAGE_Z); + goto default; + + default: + ThumbLX = Scale(state.LX, false); + ThumbLY = Scale(state.LY, true); + ThumbRX = Scale(state.RX, false); + ThumbRY = Scale(state.RY, true); + break; + } Output[14] = (Byte)((ThumbLX >> 0) & 0xFF); // LX Output[15] = (Byte)((ThumbLX >> 8) & 0xFF); diff --git a/DS4Windows/DS4Forms/Options.Designer.cs b/DS4Windows/DS4Forms/Options.Designer.cs index 7bc6cfb..180e074 100644 --- a/DS4Windows/DS4Forms/Options.Designer.cs +++ b/DS4Windows/DS4Forms/Options.Designer.cs @@ -1936,7 +1936,13 @@ resources.GetString("cBSteeringWheelEmulationAxis.Items2"), resources.GetString("cBSteeringWheelEmulationAxis.Items3"), resources.GetString("cBSteeringWheelEmulationAxis.Items4"), - resources.GetString("cBSteeringWheelEmulationAxis.Items5")}); + resources.GetString("cBSteeringWheelEmulationAxis.Items5"), + resources.GetString("cBSteeringWheelEmulationAxis.Items6"), + resources.GetString("cBSteeringWheelEmulationAxis.Items7"), + resources.GetString("cBSteeringWheelEmulationAxis.Items8"), + resources.GetString("cBSteeringWheelEmulationAxis.Items9"), + resources.GetString("cBSteeringWheelEmulationAxis.Items10"), + resources.GetString("cBSteeringWheelEmulationAxis.Items11")}); resources.ApplyResources(this.cBSteeringWheelEmulationAxis, "cBSteeringWheelEmulationAxis"); this.cBSteeringWheelEmulationAxis.Name = "cBSteeringWheelEmulationAxis"; this.cBSteeringWheelEmulationAxis.SelectedIndexChanged += new System.EventHandler(this.cBSteeringWheelEmulationAxis_SelectedIndexChanged); diff --git a/DS4Windows/DS4Forms/Options.cs b/DS4Windows/DS4Forms/Options.cs index b10b94c..16f5001 100644 --- a/DS4Windows/DS4Forms/Options.cs +++ b/DS4Windows/DS4Forms/Options.cs @@ -719,16 +719,7 @@ namespace DS4Windows cBGyroMouseXAxis.SelectedIndex = GyroMouseHorizontalAxis[device]; triggerCondAndCombo.SelectedIndex = SATriggerCond[device] ? 0 : 1; - switch (getSASteeringWheelEmulationAxis(device)) - { - case DS4Controls.None: cBSteeringWheelEmulationAxis.SelectedIndex = 0; break; - case DS4Controls.LXPos: cBSteeringWheelEmulationAxis.SelectedIndex = 1; break; - case DS4Controls.LYPos: cBSteeringWheelEmulationAxis.SelectedIndex = 2; break; - case DS4Controls.RXPos: cBSteeringWheelEmulationAxis.SelectedIndex = 3; break; - case DS4Controls.RYPos: cBSteeringWheelEmulationAxis.SelectedIndex = 4; break; - case DS4Controls.L2: - case DS4Controls.R2: cBSteeringWheelEmulationAxis.SelectedIndex = 5; break; - } + cBSteeringWheelEmulationAxis.SelectedIndex = (int) getSASteeringWheelEmulationAxis(device); int idxSASteeringWheelEmulationRange = cBSteeringWheelEmulationRange.Items.IndexOf(getSASteeringWheelEmulationRange(device).ToString()); if (idxSASteeringWheelEmulationRange >= 0) cBSteeringWheelEmulationRange.SelectedIndex = idxSASteeringWheelEmulationRange; @@ -3020,15 +3011,8 @@ namespace DS4Windows { if (loading == false) { - switch (cBSteeringWheelEmulationAxis.SelectedIndex) - { - case 0: SASteeringWheelEmulationAxis[device] = DS4Controls.None; break; // Gyro SA steering wheel emulation disabled - case 1: SASteeringWheelEmulationAxis[device] = DS4Controls.LXPos; break; // Left stick X axis - case 2: SASteeringWheelEmulationAxis[device] = DS4Controls.LYPos; break; // Left stick Y axis - case 3: SASteeringWheelEmulationAxis[device] = DS4Controls.RXPos; break; // Right stick X axis - case 4: SASteeringWheelEmulationAxis[device] = DS4Controls.RYPos; break; // Right stick Y axis - case 5: SASteeringWheelEmulationAxis[device] = DS4Controls.L2; break; // Left+Right trigger axis (max range -255..0 as left trigger and 0..+255 as right trigger) - } + if (cBSteeringWheelEmulationAxis.SelectedIndex >= 0) SASteeringWheelEmulationAxis[device] = (SASteeringWheelEmulationAxisType) ((byte) cBSteeringWheelEmulationAxis.SelectedIndex); + else SASteeringWheelEmulationAxis[device] = SASteeringWheelEmulationAxisType.None; } } diff --git a/DS4Windows/DS4Forms/Options.resx b/DS4Windows/DS4Forms/Options.resx index 4a5c38d..7996876 100644 --- a/DS4Windows/DS4Forms/Options.resx +++ b/DS4Windows/DS4Forms/Options.resx @@ -4108,6 +4108,24 @@ with profile Trigger L+R Axis + + VJoy1 X-Axis + + + VJoy1 Y-Axis + + + VJoy1 Z-Axis + + + VJoy2 X-Axis + + + VJoy2 Y-Axis + + + VJoy2 Z-Axis + 107, 119 @@ -9140,7 +9158,7 @@ with profile True - 102 + 25 96, 96 @@ -9569,7 +9587,7 @@ with profile advColorDialog - DS4Windows.AdvancedColorDialog, DS4Windows, Version=1.5.17.0, Culture=neutral, PublicKeyToken=null + DS4Windows.AdvancedColorDialog, DS4Windows, Version=1.6.0.0, Culture=neutral, PublicKeyToken=null Options diff --git a/DS4Windows/DS4Windows.csproj b/DS4Windows/DS4Windows.csproj index 94900f6..70fae34 100644 --- a/DS4Windows/DS4Windows.csproj +++ b/DS4Windows/DS4Windows.csproj @@ -231,6 +231,7 @@ + DS4Form.cs Designer @@ -621,6 +622,7 @@ Options.cs + Designer Options.cs @@ -1044,7 +1046,9 @@ - + + Designer + @@ -1172,6 +1176,7 @@ true + rem Copy compiled l18n assemblies to alt folder diff --git a/DS4Windows/Program.cs b/DS4Windows/Program.cs index 06406da..838d22b 100644 --- a/DS4Windows/Program.cs +++ b/DS4Windows/Program.cs @@ -99,7 +99,7 @@ namespace DS4Windows //if (mutex.WaitOne(TimeSpan.Zero, true)) //{ - createControlService(); + createControlService(); //rootHub = new ControlService(); Application.EnableVisualStyles(); ds4form = new DS4Form(args); diff --git a/DS4Windows/VJoyFeeder/vJoyFeeder.cs b/DS4Windows/VJoyFeeder/vJoyFeeder.cs new file mode 100644 index 0000000..f44a37c --- /dev/null +++ b/DS4Windows/VJoyFeeder/vJoyFeeder.cs @@ -0,0 +1,701 @@ +// VJoy C# interface file taken from an excellent Shaul's virtual joystick driver project. +// Licensed to public domain as is (http://vjoystick.sourceforge.net/site/index.php/forum/5-Discussion/104-what-is-the-usage-license-for-this-software). +// http://vjoystick.sourceforge.net/site/ +// https://github.com/shauleiz/vJoy/tree/master/apps/common/vJoyInterfaceCS +// +// This module is a feeder for VJoy virtual joystick driver. DS4Windows can optionally re-map and feed buttons and analog axis values from DS4 Controller to VJoy device. +// At first this may seem silly because DS4Windows can already to re-mapping by using a virtual X360 Controller driver, so why feed VJoy virtual driver also? +// Sometimes X360 driver may run out of analog axis options, so for example "SA motion sensor steering wheel emulation" in DS4Windows would reserve a thumbstick X or Y +// axis for SA steering wheel emulation usage. That thumbstick axis would be unavailable for "normal" thumbstick usage after this re-mapping. +// The problem can be solved by configuring DS4Windows to re-map SA steering wheel emulation axis to VJoy axis, so all analog axies in DS4 controller are still available for normal usage. +// + +using System; +using System.Runtime.InteropServices; + +namespace DS4Windows.VJoyFeeder +{ + [Flags] + public enum HID_USAGES + { + HID_USAGE_X = 0x30, + HID_USAGE_Y = 0x31, + HID_USAGE_Z = 0x32, + HID_USAGE_RX = 0x33, + HID_USAGE_RY = 0x34, + HID_USAGE_RZ = 0x35, + HID_USAGE_SL0 = 0x36, + HID_USAGE_SL1 = 0x37, + HID_USAGE_WHL = 0x38, + HID_USAGE_POV = 0x39, + } + + public enum VjdStat /* Declares an enumeration data type called BOOLEAN */ + { + VJD_STAT_OWN, // The vJoy Device is owned by this application. + VJD_STAT_FREE, // The vJoy Device is NOT owned by any application (including this one). + VJD_STAT_BUSY, // The vJoy Device is owned by another application. It cannot be acquired by this application. + VJD_STAT_MISS, // The vJoy Device is missing. It either does not exist or the driver is down. + VJD_STAT_UNKN // Unknown + }; + + + // FFB Declarations + + // HID Descriptor definitions - FFB Report IDs + + public enum FFBPType // FFB Packet Type + { + // Write + PT_EFFREP = 0x01, // Usage Set Effect Report + PT_ENVREP = 0x02, // Usage Set Envelope Report + PT_CONDREP = 0x03, // Usage Set Condition Report + PT_PRIDREP = 0x04, // Usage Set Periodic Report + PT_CONSTREP = 0x05, // Usage Set Constant Force Report + PT_RAMPREP = 0x06, // Usage Set Ramp Force Report + PT_CSTMREP = 0x07, // Usage Custom Force Data Report + PT_SMPLREP = 0x08, // Usage Download Force Sample + PT_EFOPREP = 0x0A, // Usage Effect Operation Report + PT_BLKFRREP = 0x0B, // Usage PID Block Free Report + PT_CTRLREP = 0x0C, // Usage PID Device Control + PT_GAINREP = 0x0D, // Usage Device Gain Report + PT_SETCREP = 0x0E, // Usage Set Custom Force Report + + // Feature + PT_NEWEFREP = 0x01 + 0x10, // Usage Create New Effect Report + PT_BLKLDREP = 0x02 + 0x10, // Usage Block Load Report + PT_POOLREP = 0x03 + 0x10, // Usage PID Pool Report + }; + + public enum FFBEType // FFB Effect Type + { + + // Effect Type + ET_NONE = 0, // No Force + ET_CONST = 1, // Constant Force + ET_RAMP = 2, // Ramp + ET_SQR = 3, // Square + ET_SINE = 4, // Sine + ET_TRNGL = 5, // Triangle + ET_STUP = 6, // Sawtooth Up + ET_STDN = 7, // Sawtooth Down + ET_SPRNG = 8, // Spring + ET_DMPR = 9, // Damper + ET_INRT = 10, // Inertia + ET_FRCTN = 11, // Friction + ET_CSTM = 12, // Custom Force Data + }; + + public enum FFB_CTRL + { + CTRL_ENACT = 1, // Enable all device actuators. + CTRL_DISACT = 2, // Disable all the device actuators. + CTRL_STOPALL = 3, // Stop All Effects­ Issues a stop on every running effect. + CTRL_DEVRST = 4, // Device Reset– Clears any device paused condition, enables all actuators and clears all effects from memory. + CTRL_DEVPAUSE = 5, // Device Pause– The all effects on the device are paused at the current time step. + CTRL_DEVCONT = 6, // Device Continue– The all effects that running when the device was paused are restarted from their last time step. + }; + + public enum FFBOP + { + EFF_START = 1, // EFFECT START + EFF_SOLO = 2, // EFFECT SOLO START + EFF_STOP = 3, // EFFECT STOP + }; + + //namespace vJoyInterfaceWrap + //{ + public class vJoy + { + + /***************************************************/ + /*********** Various declarations ******************/ + /***************************************************/ + private static RemovalCbFunc UserRemCB; + private static WrapRemovalCbFunc wrf; + private static GCHandle hRemUserData; + + + private static FfbCbFunc UserFfbCB; + private static WrapFfbCbFunc wf; + private static GCHandle hFfbUserData; + + [StructLayout(LayoutKind.Sequential)] + public struct JoystickState + { + public byte bDevice; + public Int32 Throttle; + public Int32 Rudder; + public Int32 Aileron; + public Int32 AxisX; + public Int32 AxisY; + public Int32 AxisZ; + public Int32 AxisXRot; + public Int32 AxisYRot; + public Int32 AxisZRot; + public Int32 Slider; + public Int32 Dial; + public Int32 Wheel; + public Int32 AxisVX; + public Int32 AxisVY; + public Int32 AxisVZ; + public Int32 AxisVBRX; + public Int32 AxisVBRY; + public Int32 AxisVBRZ; + public UInt32 Buttons; + public UInt32 bHats; // Lower 4 bits: HAT switch or 16-bit of continuous HAT switch + public UInt32 bHatsEx1; // Lower 4 bits: HAT switch or 16-bit of continuous HAT switch + public UInt32 bHatsEx2; // Lower 4 bits: HAT switch or 16-bit of continuous HAT switch + public UInt32 bHatsEx3; // Lower 4 bits: HAT switch or 16-bit of continuous HAT switch + public UInt32 ButtonsEx1; + public UInt32 ButtonsEx2; + public UInt32 ButtonsEx3; + }; + + [StructLayout(LayoutKind.Sequential)] + private struct FFB_DATA + { + private UInt32 size; + private UInt32 cmd; + private IntPtr data; + } + + [StructLayout(LayoutKind.Explicit)] + public struct FFB_EFF_CONSTANT + { + [FieldOffset(0)] + public Byte EffectBlockIndex; + [FieldOffset(4)] + public Int16 Magnitude; + } + + [System.Obsolete("use FFB_EFF_REPORT")] + [StructLayout(LayoutKind.Explicit)] + public struct FFB_EFF_CONST + { + [FieldOffset(0)] + public Byte EffectBlockIndex; + [FieldOffset(4)] + public FFBEType EffectType; + [FieldOffset(8)] + public UInt16 Duration;// Value in milliseconds. 0xFFFF means infinite + [FieldOffset(10)] + public UInt16 TrigerRpt; + [FieldOffset(12)] + public UInt16 SamplePrd; + [FieldOffset(14)] + public Byte Gain; + [FieldOffset(15)] + public Byte TrigerBtn; + [FieldOffset(16)] + public bool Polar; // How to interpret force direction Polar (0-360°) or Cartesian (X,Y) + [FieldOffset(20)] + public Byte Direction; // Polar direction: (0x00-0xFF correspond to 0-360°) + [FieldOffset(20)] + public Byte DirX; // X direction: Positive values are To the right of the center (X); Negative are Two's complement + [FieldOffset(21)] + public Byte DirY; // Y direction: Positive values are below the center (Y); Negative are Two's complement + } + + [StructLayout(LayoutKind.Explicit)] + public struct FFB_EFF_REPORT + { + [FieldOffset(0)] + public Byte EffectBlockIndex; + [FieldOffset(4)] + public FFBEType EffectType; + [FieldOffset(8)] + public UInt16 Duration;// Value in milliseconds. 0xFFFF means infinite + [FieldOffset(10)] + public UInt16 TrigerRpt; + [FieldOffset(12)] + public UInt16 SamplePrd; + [FieldOffset(14)] + public Byte Gain; + [FieldOffset(15)] + public Byte TrigerBtn; + [FieldOffset(16)] + public bool Polar; // How to interpret force direction Polar (0-360°) or Cartesian (X,Y) + [FieldOffset(20)] + public Byte Direction; // Polar direction: (0x00-0xFF correspond to 0-360°) + [FieldOffset(20)] + public Byte DirX; // X direction: Positive values are To the right of the center (X); Negative are Two's complement + [FieldOffset(21)] + public Byte DirY; // Y direction: Positive values are below the center (Y); Negative are Two's complement + } + + [StructLayout(LayoutKind.Explicit)] + public struct FFB_EFF_OP + { + [FieldOffset(0)] + public Byte EffectBlockIndex; + [FieldOffset(4)] + public FFBOP EffectOp; + [FieldOffset(8)] + public Byte LoopCount; + } + + [StructLayout(LayoutKind.Explicit)] + public struct FFB_EFF_COND + { + [FieldOffset(0)] + public Byte EffectBlockIndex; + [FieldOffset(4)] + public bool isY; + [FieldOffset(8)] + public Int16 CenterPointOffset; // CP Offset: Range 0x80­0x7F (­10000 ­ 10000) + [FieldOffset(12)] + public Int16 PosCoeff; // Positive Coefficient: Range 0x80­0x7F (­10000 ­ 10000) + [FieldOffset(16)] + public Int16 NegCoeff; // Negative Coefficient: Range 0x80­0x7F (­10000 ­ 10000) + [FieldOffset(20)] + public UInt32 PosSatur; // Positive Saturation: Range 0x00­0xFF (0 – 10000) + [FieldOffset(24)] + public UInt32 NegSatur; // Negative Saturation: Range 0x00­0xFF (0 – 10000) + [FieldOffset(28)] + public Int32 DeadBand; // Dead Band: : Range 0x00­0xFF (0 – 10000) + } + + [StructLayout(LayoutKind.Explicit)] + public struct FFB_EFF_ENVLP + { + [FieldOffset(0)] + public Byte EffectBlockIndex; + [FieldOffset(4)] + public UInt16 AttackLevel; + [FieldOffset(8)] + public UInt16 FadeLevel; + [FieldOffset(12)] + public UInt32 AttackTime; + [FieldOffset(16)] + public UInt32 FadeTime; + } + + [StructLayout(LayoutKind.Explicit)] + public struct FFB_EFF_PERIOD + { + [FieldOffset(0)] + public Byte EffectBlockIndex; + [FieldOffset(4)] + public UInt32 Magnitude; + [FieldOffset(8)] + public Int16 Offset; + [FieldOffset(12)] + public UInt32 Phase; + [FieldOffset(16)] + public UInt32 Period; + } + + [StructLayout(LayoutKind.Explicit)] + public struct FFB_EFF_RAMP + { + [FieldOffset(0)] + public Byte EffectBlockIndex; + [FieldOffset(4)] + public Int16 Start; // The Normalized magnitude at the start of the effect + [FieldOffset(8)] + public Int16 End; // The Normalized magnitude at the end of the effect + } + + + /***************************************************/ + /***** Import from file vJoyInterface.dll (C) ******/ + /***************************************************/ + + ///// General driver data + [DllImport("vJoyInterface.dll", EntryPoint = "GetvJoyVersion")] + private static extern short _GetvJoyVersion(); + + [DllImport("vJoyInterface.dll", EntryPoint = "vJoyEnabled")] + private static extern bool _vJoyEnabled(); + + [DllImport("vJoyInterface.dll", EntryPoint = "GetvJoyProductString")] + private static extern IntPtr _GetvJoyProductString(); + + [DllImport("vJoyInterface.dll", EntryPoint = "GetvJoyManufacturerString")] + private static extern IntPtr _GetvJoyManufacturerString(); + + [DllImport("vJoyInterface.dll", EntryPoint = "GetvJoySerialNumberString")] + private static extern IntPtr _GetvJoySerialNumberString(); + + [DllImport("vJoyInterface.dll", EntryPoint = "DriverMatch")] + private static extern bool _DriverMatch(ref UInt32 DllVer, ref UInt32 DrvVer); + + ///// vJoy Device properties + [DllImport("vJoyInterface.dll", EntryPoint = "GetVJDButtonNumber")] + private static extern int _GetVJDButtonNumber(UInt32 rID); + + [DllImport("vJoyInterface.dll", EntryPoint = "GetVJDDiscPovNumber")] + private static extern int _GetVJDDiscPovNumber(UInt32 rID); + + [DllImport("vJoyInterface.dll", EntryPoint = "GetVJDContPovNumber")] + private static extern int _GetVJDContPovNumber(UInt32 rID); + + [DllImport("vJoyInterface.dll", EntryPoint = "GetVJDAxisExist")] + private static extern UInt32 _GetVJDAxisExist(UInt32 rID, UInt32 Axis); + + [DllImport("vJoyInterface.dll", EntryPoint = "GetVJDAxisMax")] + private static extern bool _GetVJDAxisMax(UInt32 rID, UInt32 Axis, ref long Max); + + [DllImport("vJoyInterface.dll", EntryPoint = "GetVJDAxisMin")] + private static extern bool _GetVJDAxisMin(UInt32 rID, UInt32 Axis, ref long Min); + + [DllImport("vJoyInterface.dll", EntryPoint = "isVJDExists")] + private static extern bool _isVJDExists(UInt32 rID); + + [DllImport("vJoyInterface.dll", EntryPoint = "GetOwnerPid")] + private static extern int _GetOwnerPid(UInt32 rID); + + ///// Write access to vJoy Device - Basic + [DllImport("vJoyInterface.dll", EntryPoint = "AcquireVJD")] + private static extern bool _AcquireVJD(UInt32 rID); + + [DllImport("vJoyInterface.dll", EntryPoint = "RelinquishVJD")] + private static extern void _RelinquishVJD(UInt32 rID); + + [DllImport("vJoyInterface.dll", EntryPoint = "UpdateVJD")] + private static extern bool _UpdateVJD(UInt32 rID, ref JoystickState pData); + + [DllImport("vJoyInterface.dll", EntryPoint = "GetVJDStatus")] + private static extern int _GetVJDStatus(UInt32 rID); + + + //// Reset functions + [DllImport("vJoyInterface.dll", EntryPoint = "ResetVJD")] + private static extern bool _ResetVJD(UInt32 rID); + + [DllImport("vJoyInterface.dll", EntryPoint = "ResetAll")] + private static extern bool _ResetAll(); + + [DllImport("vJoyInterface.dll", EntryPoint = "ResetButtons")] + private static extern bool _ResetButtons(UInt32 rID); + + [DllImport("vJoyInterface.dll", EntryPoint = "ResetPovs")] + private static extern bool _ResetPovs(UInt32 rID); + + ////// Write data + [DllImport("vJoyInterface.dll", EntryPoint = "SetAxis")] + private static extern bool _SetAxis(Int32 Value, UInt32 rID, HID_USAGES Axis); + + [DllImport("vJoyInterface.dll", EntryPoint = "SetBtn")] + private static extern bool _SetBtn(bool Value, UInt32 rID, Byte nBtn); + + [DllImport("vJoyInterface.dll", EntryPoint = "SetDiscPov")] + private static extern bool _SetDiscPov(Int32 Value, UInt32 rID, uint nPov); + + [DllImport("vJoyInterface.dll", EntryPoint = "SetContPov")] + private static extern bool _SetContPov(Int32 Value, UInt32 rID, uint nPov); + + [DllImport("vJoyInterface.dll", EntryPoint = "RegisterRemovalCB", CallingConvention = CallingConvention.Cdecl)] + private extern static void _RegisterRemovalCB(WrapRemovalCbFunc cb, IntPtr data); + + public delegate void RemovalCbFunc(bool complete, bool First, object userData); + public delegate void WrapRemovalCbFunc(bool complete, bool First, IntPtr userData); + + public static void WrapperRemCB(bool complete, bool First, IntPtr userData) + { + + object obj = null; + + if (userData != IntPtr.Zero) + { + // Convert userData from pointer to object + GCHandle handle2 = (GCHandle)userData; + obj = handle2.Target as object; + } + + // Call user-defined CB function + UserRemCB(complete, First, obj); + } + + // Force Feedback (FFB) + [DllImport("vJoyInterface.dll", EntryPoint = "FfbRegisterGenCB", CallingConvention = CallingConvention.Cdecl)] + private extern static void _FfbRegisterGenCB(WrapFfbCbFunc cb, IntPtr data); + + public delegate void FfbCbFunc(IntPtr data, object userData); + public delegate void WrapFfbCbFunc(IntPtr data, IntPtr userData); + + public static void WrapperFfbCB(IntPtr data, IntPtr userData) + { + + object obj = null; + + if (userData != IntPtr.Zero) + { + // Convert userData from pointer to object + GCHandle handle2 = (GCHandle)userData; + obj = handle2.Target as object; + } + + // Call user-defined CB function + UserFfbCB(data, obj); + } + + [DllImport("vJoyInterface.dll", EntryPoint = "FfbStart")] + private static extern bool _FfbStart(UInt32 rID); + + [DllImport("vJoyInterface.dll", EntryPoint = "FfbStop")] + private static extern bool _FfbStop(UInt32 rID); + + [DllImport("vJoyInterface.dll", EntryPoint = "IsDeviceFfb")] + private static extern bool _IsDeviceFfb(UInt32 rID); + + [DllImport("vJoyInterface.dll", EntryPoint = "IsDeviceFfbEffect")] + private static extern bool _IsDeviceFfbEffect(UInt32 rID, UInt32 Effect); + + [DllImport("vJoyInterface.dll", EntryPoint = "Ffb_h_DeviceID")] + private static extern UInt32 _Ffb_h_DeviceID(IntPtr Packet, ref int DeviceID); + + [DllImport("vJoyInterface.dll", EntryPoint = "Ffb_h_Type")] + private static extern UInt32 _Ffb_h_Type(IntPtr Packet, ref FFBPType Type); + + [DllImport("vJoyInterface.dll", EntryPoint = "Ffb_h_Packet")] + private static extern UInt32 _Ffb_h_Packet(IntPtr Packet, ref UInt32 Type, ref Int32 DataSize, ref IntPtr Data); + + + [DllImport("vJoyInterface.dll", EntryPoint = "Ffb_h_EBI")] + private static extern UInt32 _Ffb_h_EBI(IntPtr Packet, ref Int32 Index); + +#pragma warning disable 618 + [DllImport("vJoyInterface.dll", EntryPoint = "Ffb_h_Eff_Const")] + private static extern UInt32 _Ffb_h_Eff_Const(IntPtr Packet, ref FFB_EFF_CONST Effect); +#pragma warning restore 618 + + [DllImport("vJoyInterface.dll", EntryPoint = "Ffb_h_Eff_Report")] + private static extern UInt32 _Ffb_h_Eff_Report(IntPtr Packet, ref FFB_EFF_REPORT Effect); + + [DllImport("vJoyInterface.dll", EntryPoint = "Ffb_h_DevCtrl")] + private static extern UInt32 _Ffb_h_DevCtrl(IntPtr Packet, ref FFB_CTRL Control); + + [DllImport("vJoyInterface.dll", EntryPoint = "Ffb_h_EffOp")] + private static extern UInt32 _Ffb_h_EffOp(IntPtr Packet, ref FFB_EFF_OP Operation); + + [DllImport("vJoyInterface.dll", EntryPoint = "Ffb_h_DevGain")] + private static extern UInt32 _Ffb_h_DevGain(IntPtr Packet, ref Byte Gain); + + [DllImport("vJoyInterface.dll", EntryPoint = "Ffb_h_Eff_Cond")] + private static extern UInt32 _Ffb_h_Eff_Cond(IntPtr Packet, ref FFB_EFF_COND Condition); + + [DllImport("vJoyInterface.dll", EntryPoint = "Ffb_h_Eff_Envlp")] + private static extern UInt32 _Ffb_h_Eff_Envlp(IntPtr Packet, ref FFB_EFF_ENVLP Envelope); + + [DllImport("vJoyInterface.dll", EntryPoint = "Ffb_h_Eff_Period")] + private static extern UInt32 _Ffb_h_Eff_Period(IntPtr Packet, ref FFB_EFF_PERIOD Effect); + + [DllImport("vJoyInterface.dll", EntryPoint = "Ffb_h_EffNew")] + private static extern UInt32 _Ffb_h_EffNew(IntPtr Packet, ref FFBEType Effect); + + [DllImport("vJoyInterface.dll", EntryPoint = "Ffb_h_Eff_Ramp")] + private static extern UInt32 _Ffb_h_Eff_Ramp(IntPtr Packet, ref FFB_EFF_RAMP RampEffect); + + [DllImport("vJoyInterface.dll", EntryPoint = "Ffb_h_Eff_Constant")] + private static extern UInt32 _Ffb_h_Eff_Constant(IntPtr Packet, ref FFB_EFF_CONSTANT ConstantEffect); + + /***************************************************/ + /********** Export functions (C#) ******************/ + /***************************************************/ + + ///// General driver data + public short GetvJoyVersion() { return _GetvJoyVersion(); } + public bool vJoyEnabled() { return _vJoyEnabled(); } + public string GetvJoyProductString() { return Marshal.PtrToStringAuto(_GetvJoyProductString()); } + public string GetvJoyManufacturerString() { return Marshal.PtrToStringAuto(_GetvJoyManufacturerString()); } + public string GetvJoySerialNumberString() { return Marshal.PtrToStringAuto(_GetvJoySerialNumberString()); } + public bool DriverMatch(ref UInt32 DllVer, ref UInt32 DrvVer) { return _DriverMatch(ref DllVer, ref DrvVer); } + + ///// vJoy Device properties + public int GetVJDButtonNumber(uint rID) { return _GetVJDButtonNumber(rID); } + public int GetVJDDiscPovNumber(uint rID) { return _GetVJDDiscPovNumber(rID); } + public int GetVJDContPovNumber(uint rID) { return _GetVJDContPovNumber(rID); } + public bool GetVJDAxisExist(UInt32 rID, HID_USAGES Axis) + { + UInt32 res = _GetVJDAxisExist(rID, (uint)Axis); + if (res == 1) + return true; + else + return false; + } + public bool GetVJDAxisMax(UInt32 rID, HID_USAGES Axis, ref long Max) { return _GetVJDAxisMax(rID, (uint)Axis, ref Max); } + public bool GetVJDAxisMin(UInt32 rID, HID_USAGES Axis, ref long Min) { return _GetVJDAxisMin(rID, (uint)Axis, ref Min); } + public bool isVJDExists(UInt32 rID) { return _isVJDExists(rID); } + public int GetOwnerPid(UInt32 rID) { return _GetOwnerPid(rID); } + + ///// Write access to vJoy Device - Basic + public bool AcquireVJD(UInt32 rID) { return _AcquireVJD(rID); } + public void RelinquishVJD(uint rID) { _RelinquishVJD(rID); } + public bool UpdateVJD(UInt32 rID, ref JoystickState pData) { return _UpdateVJD(rID, ref pData); } + public VjdStat GetVJDStatus(UInt32 rID) { return (VjdStat)_GetVJDStatus(rID); } + + //// Reset functions + public bool ResetVJD(UInt32 rID) { return _ResetVJD(rID); } + public bool ResetAll() { return _ResetAll(); } + public bool ResetButtons(UInt32 rID) { return _ResetButtons(rID); } + public bool ResetPovs(UInt32 rID) { return _ResetPovs(rID); } + + ////// Write data + public bool SetAxis(Int32 Value, UInt32 rID, HID_USAGES Axis) { return _SetAxis(Value, rID, Axis); } + public bool SetBtn(bool Value, UInt32 rID, uint nBtn) { return _SetBtn(Value, rID, (Byte)nBtn); } + public bool SetDiscPov(Int32 Value, UInt32 rID, uint nPov) { return _SetDiscPov(Value, rID, nPov); } + public bool SetContPov(Int32 Value, UInt32 rID, uint nPov) { return _SetContPov(Value, rID, nPov); } + + // Register CB function that takes a C# object as userdata + public void RegisterRemovalCB(RemovalCbFunc cb, object data) + { + // Free existing GCHandle (if exists) + if (hRemUserData.IsAllocated && hRemUserData.Target != null) + hRemUserData.Free(); + + // Convert object to pointer + hRemUserData = GCHandle.Alloc(data); + + // Apply the user-defined CB function + UserRemCB = new RemovalCbFunc(cb); + wrf = new WrapRemovalCbFunc(WrapperRemCB); + + _RegisterRemovalCB(wrf, (IntPtr)hRemUserData); + } + + // Register CB function that takes a pointer as userdata + public void RegisterRemovalCB(WrapRemovalCbFunc cb, IntPtr data) + { + wrf = new WrapRemovalCbFunc(cb); + _RegisterRemovalCB(wrf, data); + } + + + ///////////////////////////////////////////////////////////////////////////////////////////// + //// Force Feedback (FFB) + + // Register CB function that takes a C# object as userdata + public void FfbRegisterGenCB(FfbCbFunc cb, object data) + { + // Free existing GCHandle (if exists) + if (hFfbUserData.IsAllocated && hFfbUserData.Target != null) + hFfbUserData.Free(); + + // Convert object to pointer + hFfbUserData = GCHandle.Alloc(data); + + // Apply the user-defined CB function + UserFfbCB = new FfbCbFunc(cb); + wf = new WrapFfbCbFunc(WrapperFfbCB); + + _FfbRegisterGenCB(wf, (IntPtr)hFfbUserData); + } + + // Register CB function that takes a pointer as userdata + public void FfbRegisterGenCB(WrapFfbCbFunc cb, IntPtr data) + { + wf = new WrapFfbCbFunc(cb); + _FfbRegisterGenCB(wf, data); + } + + [Obsolete("you can remove the function from your code")] + public bool FfbStart(UInt32 rID) { return _FfbStart(rID); } + [Obsolete("you can remove the function from your code")] + public bool FfbStop(UInt32 rID) { return _FfbStop(rID); } + public bool IsDeviceFfb(UInt32 rID) { return _IsDeviceFfb(rID); } + public bool IsDeviceFfbEffect(UInt32 rID, UInt32 Effect) { return _IsDeviceFfbEffect(rID, Effect); } + public UInt32 Ffb_h_DeviceID(IntPtr Packet, ref int DeviceID) { return _Ffb_h_DeviceID(Packet, ref DeviceID); } + public UInt32 Ffb_h_Type(IntPtr Packet, ref FFBPType Type) { return _Ffb_h_Type(Packet, ref Type); } + public UInt32 Ffb_h_Packet(IntPtr Packet, ref UInt32 Type, ref Int32 DataSize, ref Byte[] Data) + { + IntPtr buf = IntPtr.Zero; + UInt32 res = _Ffb_h_Packet(Packet, ref Type, ref DataSize, ref buf); + if (res != 0) + return res; + + DataSize -= 8; + Data = new byte[DataSize]; + Marshal.Copy(buf, Data, 0, DataSize); + return res; + } + public UInt32 Ffb_h_EBI(IntPtr Packet, ref Int32 Index) { return _Ffb_h_EBI(Packet, ref Index); } + [Obsolete("use Ffb_h_Eff_Report instead")] + public UInt32 Ffb_h_Eff_Const(IntPtr Packet, ref FFB_EFF_CONST Effect) { return _Ffb_h_Eff_Const(Packet, ref Effect); } + public UInt32 Ffb_h_Eff_Report(IntPtr Packet, ref FFB_EFF_REPORT Effect) { return _Ffb_h_Eff_Report(Packet, ref Effect); } + public UInt32 Ffb_h_DevCtrl(IntPtr Packet, ref FFB_CTRL Control) { return _Ffb_h_DevCtrl(Packet, ref Control); } + public UInt32 Ffb_h_EffOp(IntPtr Packet, ref FFB_EFF_OP Operation) { return _Ffb_h_EffOp(Packet, ref Operation); } + public UInt32 Ffb_h_DevGain(IntPtr Packet, ref Byte Gain) { return _Ffb_h_DevGain(Packet, ref Gain); } + public UInt32 Ffb_h_Eff_Cond(IntPtr Packet, ref FFB_EFF_COND Condition) { return _Ffb_h_Eff_Cond(Packet, ref Condition); } + public UInt32 Ffb_h_Eff_Envlp(IntPtr Packet, ref FFB_EFF_ENVLP Envelope) { return _Ffb_h_Eff_Envlp(Packet, ref Envelope); } + public UInt32 Ffb_h_Eff_Period(IntPtr Packet, ref FFB_EFF_PERIOD Effect) { return _Ffb_h_Eff_Period(Packet, ref Effect); } + public UInt32 Ffb_h_EffNew(IntPtr Packet, ref FFBEType Effect) { return _Ffb_h_EffNew(Packet, ref Effect); } + public UInt32 Ffb_h_Eff_Ramp(IntPtr Packet, ref FFB_EFF_RAMP RampEffect) { return _Ffb_h_Eff_Ramp(Packet, ref RampEffect); } + public UInt32 Ffb_h_Eff_Constant(IntPtr Packet, ref FFB_EFF_CONSTANT ConstantEffect) { return _Ffb_h_Eff_Constant(Packet, ref ConstantEffect); } + } + //} + + public class vJoyFeeder + { + private static readonly object vJoyLocker = new object(); + + static bool vJoyInitialized = false; + static bool vJoyAvailable = false; + static vJoy vJoyObj = null; + + vJoyFeeder() + { + // Do nothing + } + + ~vJoyFeeder() + { + // Do nothing + } + + public static void InitializeVJoyDevice(uint vJoyID, HID_USAGES axis) + { + lock (vJoyLocker) + { + if (vJoyInitialized) return; + + vJoyInitialized = true; + AppLogger.LogToGui("Initializing VJoy virtual joystick driver via vJoyInterface.dll interface", false); + + if (vJoyObj == null) vJoyObj = new vJoy(); + + if (vJoyObj.vJoyEnabled() && vJoyObj.GetVJDAxisExist(vJoyID, axis)) + { + AppLogger.LogToGui("Connection to VJoy virtual joystick established", false); + AppLogger.LogToGui($"VJoy driver. Vendor={vJoyObj.GetvJoyManufacturerString()} Product={vJoyObj.GetvJoyProductString()} Version={vJoyObj.GetvJoySerialNumberString()} Device#={vJoyID} Axis={axis}", false); + + // Test if DLL matches the driver + UInt32 DllVer = 0, DrvVer = 0; + if (!vJoyObj.DriverMatch(ref DllVer, ref DrvVer)) + AppLogger.LogToGui("WARNING. VJoy version of Driver {DrvVer}) does not match interface DLL Version {DllVer}. This may lead to unexpected problems or crashes. Update VJoy driver and vJoyInterface.dll", false); + + VjdStat status = vJoyObj.GetVJDStatus(vJoyID); + if ((status == VjdStat.VJD_STAT_OWN) || ((status == VjdStat.VJD_STAT_FREE) && (!vJoyObj.AcquireVJD(vJoyID)))) + { + vJoyAvailable = false; + AppLogger.LogToGui("ERROR. Failed to acquire vJoy device# {vJoyID}. Use another VJoy device or make sure there are no other VJoy feeder apps using the same device", false); + } + else + { + //vJoyObj.GetVJDAxisMax(vJoyID, axis, ref vJoyAxisMaxValue); + //AppLogger.LogToGui($"VJoy axis {axis} max value={vJoyAxisMaxValue}", false); + vJoyObj.ResetVJD(vJoyID); + vJoyAvailable = true; + } + } + else + { + vJoyAvailable = false; + AppLogger.LogToGui($"ERROR. VJoy device# {vJoyID} or {axis} axis not available. Check vJoy driver installation and configuration", false); + } + } + } + + // Feed axis value to VJoy virtual joystic driver (DS4Windows sixaxis (SA) motion sensor steering wheel emulation feature can optionally feed VJoy analog axis instead of ScpVBus x360 axis + public static void FeedAxisValue(int value, uint vJoyID, HID_USAGES axis) + { + if (!vJoyInitialized) + InitializeVJoyDevice(vJoyID, axis); + + if (vJoyAvailable) + vJoyObj.SetAxis(value, vJoyID, axis); + } + + } +} From abadfb137bc4e73a011d8312239b70544c5fe0cb Mon Sep 17 00:00:00 2001 From: mika-n Date: Sun, 13 Jan 2019 21:25:42 +0200 Subject: [PATCH 07/66] Fine tuning vJoy output feeder --- DS4Windows/DS4Control/Mapping.cs | 11 ++++--- DS4Windows/VJoyFeeder/vJoyFeeder.cs | 48 +++++++++++++++++------------ 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/DS4Windows/DS4Control/Mapping.cs b/DS4Windows/DS4Control/Mapping.cs index 18779dd..3673ab1 100644 --- a/DS4Windows/DS4Control/Mapping.cs +++ b/DS4Windows/DS4Control/Mapping.cs @@ -4128,28 +4128,29 @@ namespace DS4Windows result = Mapping.ClampInt(maxRangeLeft, result, maxRangeRight); + // Debug log output of SA sensor values //LogToGuiSACalibrationDebugMsg($"DEBUG gyro=({gyroAccelX}, {gyroAccelZ}) gyroPitchRollYaw=({currentDeviceState.Motion.gyroPitch}, {currentDeviceState.Motion.gyroRoll}, {currentDeviceState.Motion.gyroYaw}) gyroPitchRollYaw=({currentDeviceState.Motion.angVelPitch}, {currentDeviceState.Motion.angVelRoll}, {currentDeviceState.Motion.angVelYaw}) angle={result / (1.0 * C_WHEEL_ANGLE_PRECISION)} fullTurns={controller.wheelFullTurnCount}", false); // Scale input to a raw x360 16bit output scale, except if output axis of steering wheel emulation is L2+R2 trigger axis. - // L2+R2 triggers use independent 8bit values, so use -255..0..+255 scaled values (therefore L2+R2 Trigger axis supports only 360 turn range) switch(Global.getSASteeringWheelEmulationAxis(device)) { case SASteeringWheelEmulationAxisType.LX: case SASteeringWheelEmulationAxisType.LY: case SASteeringWheelEmulationAxisType.RX: case SASteeringWheelEmulationAxisType.RY: - // DS4 Stick axis values with configurable range + // DS4 thumbstick axis output (-32768..32767 raw value range) return (((result - maxRangeLeft) * (32767 - (-32768))) / (maxRangeRight - maxRangeLeft)) + (-32768); case SASteeringWheelEmulationAxisType.L2R2: - // DS4 Trigger axis values with fixed 360 range + // DS4 Trigger axis output. L2+R2 triggers share the same axis in x360 xInput/DInput controller, + // so L2+R2 steering output supports only 360 turn range (-255..255 raw value range in the shared trigger axis) result = Convert.ToInt32(Math.Round(result / (1.0 * C_WHEEL_ANGLE_PRECISION))); if (result < 0) result = -181 - result; return (((result - (-180)) * (255 - (-255))) / (180 - (-180))) + (-255); default: - // VJoy axis values with configurable range - return (((result - maxRangeLeft) * (32767 - (-0))) / (maxRangeRight - maxRangeLeft)) + (-0); + // SASteeringWheelEmulationAxisType.VJoy1X/VJoy1Y/VJoy1Z/VJoy2X/VJoy2Y/VJoy2Z VJoy axis output (0..32767 raw value range by default) + return (((result - maxRangeLeft) * (32767 - (-0))) / (maxRangeRight - maxRangeLeft)) + (-0); } } } diff --git a/DS4Windows/VJoyFeeder/vJoyFeeder.cs b/DS4Windows/VJoyFeeder/vJoyFeeder.cs index f44a37c..8304cbb 100644 --- a/DS4Windows/VJoyFeeder/vJoyFeeder.cs +++ b/DS4Windows/VJoyFeeder/vJoyFeeder.cs @@ -653,36 +653,44 @@ namespace DS4Windows.VJoyFeeder vJoyInitialized = true; AppLogger.LogToGui("Initializing VJoy virtual joystick driver via vJoyInterface.dll interface", false); - if (vJoyObj == null) vJoyObj = new vJoy(); - - if (vJoyObj.vJoyEnabled() && vJoyObj.GetVJDAxisExist(vJoyID, axis)) + try { - AppLogger.LogToGui("Connection to VJoy virtual joystick established", false); - AppLogger.LogToGui($"VJoy driver. Vendor={vJoyObj.GetvJoyManufacturerString()} Product={vJoyObj.GetvJoyProductString()} Version={vJoyObj.GetvJoySerialNumberString()} Device#={vJoyID} Axis={axis}", false); + if (vJoyObj == null) vJoyObj = new vJoy(); - // Test if DLL matches the driver - UInt32 DllVer = 0, DrvVer = 0; - if (!vJoyObj.DriverMatch(ref DllVer, ref DrvVer)) - AppLogger.LogToGui("WARNING. VJoy version of Driver {DrvVer}) does not match interface DLL Version {DllVer}. This may lead to unexpected problems or crashes. Update VJoy driver and vJoyInterface.dll", false); - - VjdStat status = vJoyObj.GetVJDStatus(vJoyID); - if ((status == VjdStat.VJD_STAT_OWN) || ((status == VjdStat.VJD_STAT_FREE) && (!vJoyObj.AcquireVJD(vJoyID)))) + if (vJoyObj.vJoyEnabled() && vJoyObj.GetVJDAxisExist(vJoyID, axis)) { - vJoyAvailable = false; - AppLogger.LogToGui("ERROR. Failed to acquire vJoy device# {vJoyID}. Use another VJoy device or make sure there are no other VJoy feeder apps using the same device", false); + AppLogger.LogToGui("Connection to VJoy virtual joystick established", false); + AppLogger.LogToGui($"VJoy driver. Vendor={vJoyObj.GetvJoyManufacturerString()} Product={vJoyObj.GetvJoyProductString()} Version={vJoyObj.GetvJoySerialNumberString()} Device#={vJoyID} Axis={axis}", false); + + // Test if DLL matches the driver + UInt32 DllVer = 0, DrvVer = 0; + if (!vJoyObj.DriverMatch(ref DllVer, ref DrvVer)) + AppLogger.LogToGui("WARNING. VJoy version of Driver {DrvVer}) does not match interface DLL Version {DllVer}. This may lead to unexpected problems or crashes. Update VJoy driver and vJoyInterface.dll", false); + + VjdStat status = vJoyObj.GetVJDStatus(vJoyID); + if ((status == VjdStat.VJD_STAT_OWN) || ((status == VjdStat.VJD_STAT_FREE) && (!vJoyObj.AcquireVJD(vJoyID)))) + { + vJoyAvailable = false; + AppLogger.LogToGui("ERROR. Failed to acquire vJoy device# {vJoyID}. Use another VJoy device or make sure there are no other VJoy feeder apps using the same device", false); + } + else + { + //vJoyObj.GetVJDAxisMax(vJoyID, axis, ref vJoyAxisMaxValue); + //AppLogger.LogToGui($"VJoy axis {axis} max value={vJoyAxisMaxValue}", false); + vJoyObj.ResetVJD(vJoyID); + vJoyAvailable = true; + } } else { - //vJoyObj.GetVJDAxisMax(vJoyID, axis, ref vJoyAxisMaxValue); - //AppLogger.LogToGui($"VJoy axis {axis} max value={vJoyAxisMaxValue}", false); - vJoyObj.ResetVJD(vJoyID); - vJoyAvailable = true; + vJoyAvailable = false; + AppLogger.LogToGui($"ERROR. VJoy device# {vJoyID} or {axis} axis not available. Check vJoy driver installation and configuration", false); } } - else + catch { vJoyAvailable = false; - AppLogger.LogToGui($"ERROR. VJoy device# {vJoyID} or {axis} axis not available. Check vJoy driver installation and configuration", false); + AppLogger.LogToGui("ERROR. vJoy initialization failed. Make sure that DS4Windows application can find vJoyInterface.dll library file", false); } } } From 63f7dcfdceb9c05c738e8f30d3a2ac9dc17cf0dd Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Tue, 29 Jan 2019 21:19:25 -0600 Subject: [PATCH 08/66] Added easeout quad curves for LS and RS --- DS4Windows/DS4Control/Mapping.cs | 18 +++++++++++ DS4Windows/DS4Control/ScpUtil.cs | 2 ++ DS4Windows/DS4Forms/Options.Designer.cs | 40 +++++++++++++------------ DS4Windows/DS4Forms/Options.resx | 11 ++++--- 4 files changed, 48 insertions(+), 23 deletions(-) diff --git a/DS4Windows/DS4Control/Mapping.cs b/DS4Windows/DS4Control/Mapping.cs index d663640..5664715 100644 --- a/DS4Windows/DS4Control/Mapping.cs +++ b/DS4Windows/DS4Control/Mapping.cs @@ -822,6 +822,15 @@ namespace DS4Windows dState.LX = (byte)(outputX * capX + 128.0); dState.LY = (byte)(outputY * capY + 128.0); } + else if (lsOutCurveMode == 4) + { + double absX = Math.Abs(tempX); + double absY = Math.Abs(tempY); + double outputX = absX * (absX - 2.0); + double outputY = absY * (absY - 2.0); + dState.LX = (byte)(-1.0 * outputX * signX * capX + 128.0); + dState.LY = (byte)(-1.0 * outputY * signY * capY + 128.0); + } } int rsOutCurveMode = rsOutCurveModeArray[device] = getRsOutCurveMode(device); @@ -884,6 +893,15 @@ namespace DS4Windows dState.RX = (byte)(outputX * capX + 128.0); dState.RY = (byte)(outputY * capY + 128.0); } + else if (rsOutCurveMode == 4) + { + double absX = Math.Abs(tempX); + double absY = Math.Abs(tempY); + double outputX = absX * (absX - 2.0); + double outputY = absY * (absY - 2.0); + dState.RX = (byte)(-1.0 * outputX * signX * capX + 128.0); + dState.RY = (byte)(-1.0 * outputY * signY * capY + 128.0); + } } int l2OutCurveMode = tempIntArray[device] = getL2OutCurveMode(device); diff --git a/DS4Windows/DS4Control/ScpUtil.cs b/DS4Windows/DS4Control/ScpUtil.cs index bed1180..49a2906 100644 --- a/DS4Windows/DS4Control/ScpUtil.cs +++ b/DS4Windows/DS4Control/ScpUtil.cs @@ -1579,6 +1579,7 @@ namespace DS4Windows case 1: result = "enhanced-precision"; break; case 2: result = "quadratic"; break; case 3: result = "cubic"; break; + case 4: result = "easeout-quad"; break; default: break; } @@ -1594,6 +1595,7 @@ namespace DS4Windows case "enhanced-precision": id = 1; break; case "quadratic": id = 2; break; case "cubic": id = 3; break; + case "easeout-quad": id = 4; break; default: break; } diff --git a/DS4Windows/DS4Forms/Options.Designer.cs b/DS4Windows/DS4Forms/Options.Designer.cs index cd9742a..184e813 100644 --- a/DS4Windows/DS4Forms/Options.Designer.cs +++ b/DS4Windows/DS4Forms/Options.Designer.cs @@ -315,6 +315,8 @@ this.rBSAControls = new System.Windows.Forms.RadioButton(); this.rBSAMouse = new System.Windows.Forms.RadioButton(); this.pnlSAMouse = new System.Windows.Forms.Panel(); + this.label26 = new System.Windows.Forms.Label(); + this.triggerCondAndCombo = new System.Windows.Forms.ComboBox(); this.cBGyroMouseXAxis = new System.Windows.Forms.ComboBox(); this.label16 = new System.Windows.Forms.Label(); this.lbGyroSmooth = new System.Windows.Forms.Label(); @@ -386,8 +388,6 @@ this.optionsTouchInvStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.shareTouchInvStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.psTouchInvStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.triggerCondAndCombo = new System.Windows.Forms.ComboBox(); - this.label26 = new System.Windows.Forms.Label(); this.advColorDialog = new DS4Windows.AdvancedColorDialog(); ((System.ComponentModel.ISupportInitialize)(this.nUDRainbow)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.tBBlueBar)).BeginInit(); @@ -3210,7 +3210,8 @@ resources.GetString("rsOutCurveComboBox.Items"), resources.GetString("rsOutCurveComboBox.Items1"), resources.GetString("rsOutCurveComboBox.Items2"), - resources.GetString("rsOutCurveComboBox.Items3")}); + resources.GetString("rsOutCurveComboBox.Items3"), + resources.GetString("rsOutCurveComboBox.Items4")}); resources.ApplyResources(this.rsOutCurveComboBox, "rsOutCurveComboBox"); this.rsOutCurveComboBox.Name = "rsOutCurveComboBox"; this.rsOutCurveComboBox.SelectedIndexChanged += new System.EventHandler(this.rsOutCurveComboBox_SelectedIndexChanged); @@ -3224,7 +3225,8 @@ resources.GetString("lsOutCurveComboBox.Items"), resources.GetString("lsOutCurveComboBox.Items1"), resources.GetString("lsOutCurveComboBox.Items2"), - resources.GetString("lsOutCurveComboBox.Items3")}); + resources.GetString("lsOutCurveComboBox.Items3"), + resources.GetString("lsOutCurveComboBox.Items4")}); resources.ApplyResources(this.lsOutCurveComboBox, "lsOutCurveComboBox"); this.lsOutCurveComboBox.Name = "lsOutCurveComboBox"; this.lsOutCurveComboBox.SelectedIndexChanged += new System.EventHandler(this.lsOutCurveComboBox_SelectedIndexChanged); @@ -3408,6 +3410,21 @@ resources.ApplyResources(this.pnlSAMouse, "pnlSAMouse"); this.pnlSAMouse.Name = "pnlSAMouse"; // + // label26 + // + resources.ApplyResources(this.label26, "label26"); + this.label26.Name = "label26"; + // + // triggerCondAndCombo + // + this.triggerCondAndCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.triggerCondAndCombo.FormattingEnabled = true; + this.triggerCondAndCombo.Items.AddRange(new object[] { + resources.GetString("triggerCondAndCombo.Items"), + resources.GetString("triggerCondAndCombo.Items1")}); + resources.ApplyResources(this.triggerCondAndCombo, "triggerCondAndCombo"); + this.triggerCondAndCombo.Name = "triggerCondAndCombo"; + // // cBGyroMouseXAxis // this.cBGyroMouseXAxis.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; @@ -4110,21 +4127,6 @@ resources.ApplyResources(this.psTouchInvStripMenuItem, "psTouchInvStripMenuItem"); this.psTouchInvStripMenuItem.CheckedChanged += new System.EventHandler(this.TouchDisableInvert_CheckedChanged); // - // triggerCondAndCombo - // - this.triggerCondAndCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.triggerCondAndCombo.FormattingEnabled = true; - this.triggerCondAndCombo.Items.AddRange(new object[] { - resources.GetString("triggerCondAndCombo.Items"), - resources.GetString("triggerCondAndCombo.Items1")}); - resources.ApplyResources(this.triggerCondAndCombo, "triggerCondAndCombo"); - this.triggerCondAndCombo.Name = "triggerCondAndCombo"; - // - // label26 - // - resources.ApplyResources(this.label26, "label26"); - this.label26.Name = "label26"; - // // Options // resources.ApplyResources(this, "$this"); diff --git a/DS4Windows/DS4Forms/Options.resx b/DS4Windows/DS4Forms/Options.resx index dc50f18..f32fa8c 100644 --- a/DS4Windows/DS4Forms/Options.resx +++ b/DS4Windows/DS4Forms/Options.resx @@ -7165,6 +7165,9 @@ with profile Cubic + + Easeout Quad + 111, 3 @@ -7198,6 +7201,9 @@ with profile Cubic + + Easeout Quad + 31, 2 @@ -8971,9 +8977,6 @@ with profile 1011, 481 - - NoControl - 4, 4, 4, 4 @@ -9392,7 +9395,7 @@ with profile advColorDialog - DS4Windows.AdvancedColorDialog, DS4Windows, Version=1.5.8.0, Culture=neutral, PublicKeyToken=null + DS4Windows.AdvancedColorDialog, DS4Windows, Version=1.6.8.0, Culture=neutral, PublicKeyToken=null Options From 70909bdaa91823c815dc9f7690fbc18095e11ab9 Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Tue, 29 Jan 2019 21:50:29 -0600 Subject: [PATCH 09/66] Added easeout quad curve option for other axes --- DS4Windows/DS4Control/Mapping.cs | 22 ++++++++++++++++++++++ DS4Windows/DS4Control/ScpUtil.cs | 2 ++ DS4Windows/DS4Forms/Options.Designer.cs | 12 ++++++++---- DS4Windows/DS4Forms/Options.resx | 12 ++++++++++++ 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/DS4Windows/DS4Control/Mapping.cs b/DS4Windows/DS4Control/Mapping.cs index 5664715..e0847fe 100644 --- a/DS4Windows/DS4Control/Mapping.cs +++ b/DS4Windows/DS4Control/Mapping.cs @@ -918,6 +918,11 @@ namespace DS4Windows double output = temp * temp * temp; dState.L2 = (byte)(output * 255.0); } + else if (l2OutCurveMode == 3) + { + double output = temp * (temp - 2.0); + dState.L2 = (byte)(-1.0 * output * 255.0); + } } int r2OutCurveMode = tempIntArray[device] = getR2OutCurveMode(device); @@ -934,6 +939,11 @@ namespace DS4Windows double output = temp * temp * temp; dState.R2 = (byte)(output * 255.0); } + else if (r2OutCurveMode == 3) + { + double output = temp * (temp - 2.0); + dState.R2 = (byte)(-1.0 * output * 255.0); + } } bool sOff = tempBool = isUsingSAforMouse(device); @@ -1009,6 +1019,12 @@ namespace DS4Windows result = (int)(output * 128.0); dState.Motion.outputAccelX = result; } + else if (sxOutCurveMode == 3) + { + double output = temp * (temp - 2.0); + result = (int)(-1.0 * output * 128.0); + dState.Motion.outputAccelX = result; + } } int szOutCurveMode = tempIntArray[device] = getSZOutCurveMode(device); @@ -1028,6 +1044,12 @@ namespace DS4Windows result = (int)(output * 128.0); dState.Motion.outputAccelZ = result; } + else if (szOutCurveMode == 3) + { + double output = temp * (temp - 2.0); + result = (int)(-1.0 * output * 128.0); + dState.Motion.outputAccelZ = result; + } } } diff --git a/DS4Windows/DS4Control/ScpUtil.cs b/DS4Windows/DS4Control/ScpUtil.cs index 49a2906..e8d9f07 100644 --- a/DS4Windows/DS4Control/ScpUtil.cs +++ b/DS4Windows/DS4Control/ScpUtil.cs @@ -1610,6 +1610,7 @@ namespace DS4Windows case 0: break; case 1: result = "quadratic"; break; case 2: result = "cubic"; break; + case 3: result = "easeout-quad"; break; default: break; } @@ -1624,6 +1625,7 @@ namespace DS4Windows case "linear": id = 0; break; case "quadratic": id = 1; break; case "cubic": id = 2; break; + case "easeout-quad": id = 3; break; default: break; } diff --git a/DS4Windows/DS4Forms/Options.Designer.cs b/DS4Windows/DS4Forms/Options.Designer.cs index 184e813..bbd76ae 100644 --- a/DS4Windows/DS4Forms/Options.Designer.cs +++ b/DS4Windows/DS4Forms/Options.Designer.cs @@ -3137,7 +3137,8 @@ this.cBSixaxisZOutputCurve.Items.AddRange(new object[] { resources.GetString("cBSixaxisZOutputCurve.Items"), resources.GetString("cBSixaxisZOutputCurve.Items1"), - resources.GetString("cBSixaxisZOutputCurve.Items2")}); + resources.GetString("cBSixaxisZOutputCurve.Items2"), + resources.GetString("cBSixaxisZOutputCurve.Items3")}); resources.ApplyResources(this.cBSixaxisZOutputCurve, "cBSixaxisZOutputCurve"); this.cBSixaxisZOutputCurve.Name = "cBSixaxisZOutputCurve"; this.cBSixaxisZOutputCurve.SelectedIndexChanged += new System.EventHandler(this.cBSixaxisZOutputCurve_SelectedIndexChanged); @@ -3150,7 +3151,8 @@ this.cBSixaxisXOutputCurve.Items.AddRange(new object[] { resources.GetString("cBSixaxisXOutputCurve.Items"), resources.GetString("cBSixaxisXOutputCurve.Items1"), - resources.GetString("cBSixaxisXOutputCurve.Items2")}); + resources.GetString("cBSixaxisXOutputCurve.Items2"), + resources.GetString("cBSixaxisXOutputCurve.Items3")}); resources.ApplyResources(this.cBSixaxisXOutputCurve, "cBSixaxisXOutputCurve"); this.cBSixaxisXOutputCurve.Name = "cBSixaxisXOutputCurve"; this.cBSixaxisXOutputCurve.SelectedIndexChanged += new System.EventHandler(this.cBSixaxisXOutputCurve_SelectedIndexChanged); @@ -3173,7 +3175,8 @@ this.cBR2OutputCurve.Items.AddRange(new object[] { resources.GetString("cBR2OutputCurve.Items"), resources.GetString("cBR2OutputCurve.Items1"), - resources.GetString("cBR2OutputCurve.Items2")}); + resources.GetString("cBR2OutputCurve.Items2"), + resources.GetString("cBR2OutputCurve.Items3")}); resources.ApplyResources(this.cBR2OutputCurve, "cBR2OutputCurve"); this.cBR2OutputCurve.Name = "cBR2OutputCurve"; this.cBR2OutputCurve.SelectedIndexChanged += new System.EventHandler(this.cBR2OutputCurve_SelectedIndexChanged); @@ -3186,7 +3189,8 @@ this.cBL2OutputCurve.Items.AddRange(new object[] { resources.GetString("cBL2OutputCurve.Items"), resources.GetString("cBL2OutputCurve.Items1"), - resources.GetString("cBL2OutputCurve.Items2")}); + resources.GetString("cBL2OutputCurve.Items2"), + resources.GetString("cBL2OutputCurve.Items3")}); resources.ApplyResources(this.cBL2OutputCurve, "cBL2OutputCurve"); this.cBL2OutputCurve.Name = "cBL2OutputCurve"; this.cBL2OutputCurve.SelectedIndexChanged += new System.EventHandler(this.cBL2OutputCurve_SelectedIndexChanged); diff --git a/DS4Windows/DS4Forms/Options.resx b/DS4Windows/DS4Forms/Options.resx index f32fa8c..4e941eb 100644 --- a/DS4Windows/DS4Forms/Options.resx +++ b/DS4Windows/DS4Forms/Options.resx @@ -6922,6 +6922,9 @@ with profile Cubic + + Easeout Quad + 221, 28 @@ -6952,6 +6955,9 @@ with profile Cubic + + Easeout Quad + 221, 1 @@ -7042,6 +7048,9 @@ with profile Cubic + + Easeout Quad + 111, 28 @@ -7072,6 +7081,9 @@ with profile Cubic + + Easeout Quad + 31, 28 From 7a35ca19cbfa66da2e9cb19bb9fab61f33194a25 Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Tue, 29 Jan 2019 22:11:01 -0600 Subject: [PATCH 10/66] Fixed sixaxis easeout quad --- DS4Windows/DS4Control/Mapping.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/DS4Windows/DS4Control/Mapping.cs b/DS4Windows/DS4Control/Mapping.cs index e0847fe..d797c6e 100644 --- a/DS4Windows/DS4Control/Mapping.cs +++ b/DS4Windows/DS4Control/Mapping.cs @@ -1021,9 +1021,10 @@ namespace DS4Windows } else if (sxOutCurveMode == 3) { - double output = temp * (temp - 2.0); - result = (int)(-1.0 * output * 128.0); - dState.Motion.outputAccelX = result; + double abs = Math.Abs(temp); + double output = abs * (abs - 2.0); + dState.Motion.outputAccelX = (byte)(-1.0 * output * + sign * 128.0); } } @@ -1046,9 +1047,10 @@ namespace DS4Windows } else if (szOutCurveMode == 3) { - double output = temp * (temp - 2.0); - result = (int)(-1.0 * output * 128.0); - dState.Motion.outputAccelZ = result; + double abs = Math.Abs(temp); + double output = abs * (abs - 2.0); + dState.Motion.outputAccelZ = (byte)(-1.0 * output * + sign * 128.0); } } } From 4a7e233bd1f3fb20d4d34b87071515fac63b89cf Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Thu, 31 Jan 2019 00:50:37 -0600 Subject: [PATCH 11/66] Fixed bad refactor Fixes issue #561. --- DS4Windows/DS4Control/ScpUtil.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DS4Windows/DS4Control/ScpUtil.cs b/DS4Windows/DS4Control/ScpUtil.cs index e8d9f07..497d584 100644 --- a/DS4Windows/DS4Control/ScpUtil.cs +++ b/DS4Windows/DS4Control/ScpUtil.cs @@ -3556,7 +3556,7 @@ namespace DS4Windows DS4ControlSettings dcs = ds4settings[deviceNum][index]; if (shift) { - return dcs.shiftTrigger; + return dcs.shiftAction; } else { From ff870230a6587097771c2d99810659c6d9070703 Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Thu, 31 Jan 2019 10:59:00 -0600 Subject: [PATCH 12/66] Implemented user defined gyro mouse dead zone Related to issue #338. --- DS4Windows/DS4Control/ControlService.cs | 5 +- DS4Windows/DS4Control/Mouse.cs | 2 + DS4Windows/DS4Control/MouseCursor.cs | 9 +- DS4Windows/DS4Control/ScpUtil.cs | 26 + DS4Windows/DS4Forms/Options.Designer.cs | 24 + DS4Windows/DS4Forms/Options.cs | 12 + DS4Windows/DS4Forms/Options.resx | 3976 +++++++++++++++++++---- 7 files changed, 3326 insertions(+), 728 deletions(-) diff --git a/DS4Windows/DS4Control/ControlService.cs b/DS4Windows/DS4Control/ControlService.cs index 3d9c79b..82f5fb5 100644 --- a/DS4Windows/DS4Control/ControlService.cs +++ b/DS4Windows/DS4Control/ControlService.cs @@ -369,8 +369,9 @@ namespace DS4Windows { ProfilePath[i] = OlderProfilePath[i]; } - LoadProfile(i, false, this, false, false); + touchPad[i] = new Mouse(i, device); + LoadProfile(i, false, this, false, false); device.LightBarColor = getMainColor(i); if (!getDInputOnly(i) && device.isSynced()) @@ -604,8 +605,8 @@ namespace DS4Windows ProfilePath[Index] = OlderProfilePath[Index]; } - LoadProfile(Index, false, this, false, false); touchPad[Index] = new Mouse(Index, device); + LoadProfile(Index, false, this, false, false); device.LightBarColor = getMainColor(Index); int tempIdx = Index; diff --git a/DS4Windows/DS4Control/Mouse.cs b/DS4Windows/DS4Control/Mouse.cs index 701021c..7faaa72 100644 --- a/DS4Windows/DS4Control/Mouse.cs +++ b/DS4Windows/DS4Control/Mouse.cs @@ -23,6 +23,7 @@ namespace DS4Windows public bool priorLeftDown, priorRightDown, priorUpperDown, priorMultiDown; protected DS4Controls pushed = DS4Controls.None; protected Mapping.Click clicked = Mapping.Click.None; + public int CursorGyroDead { get => cursor.GyroCursorDeadZone; set => cursor.GyroCursorDeadZone = value; } internal const int TRACKBALL_INIT_FICTION = 10; internal const int TRACKBALL_MASS = 45; @@ -419,6 +420,7 @@ namespace DS4Windows } public bool dragging, dragging2; + private void synthesizeMouseButtons() { if (Global.GetDS4Action(deviceNum, DS4Controls.TouchLeft, false) == null && leftDown) diff --git a/DS4Windows/DS4Control/MouseCursor.cs b/DS4Windows/DS4Control/MouseCursor.cs index e437403..3cd0444 100644 --- a/DS4Windows/DS4Control/MouseCursor.cs +++ b/DS4Windows/DS4Control/MouseCursor.cs @@ -21,7 +21,7 @@ namespace DS4Windows private Direction hDirection = Direction.Neutral, vDirection = Direction.Neutral; private const double GYRO_MOUSE_COEFFICIENT = 0.0095; - private const int GYRO_MOUSE_DEADZONE = 10; + public const int GYRO_MOUSE_DEADZONE = 10; private const double GYRO_MOUSE_OFFSET = 0.1463; private const double GYRO_SMOOTH_MOUSE_OFFSET = 0.14698; private const double TOUCHPAD_MOUSE_OFFSET = 0.015; @@ -30,8 +30,9 @@ namespace DS4Windows private double[] xSmoothBuffer = new double[SMOOTH_BUFFER_LEN]; private double[] ySmoothBuffer = new double[SMOOTH_BUFFER_LEN]; private int smoothBufferTail = 0; + private int gyroCursorDeadZone = GYRO_MOUSE_DEADZONE; + public int GyroCursorDeadZone { get => gyroCursorDeadZone; set => gyroCursorDeadZone = value; } - double coefficient = 0.0; double verticalScale = 0.0; @@ -80,8 +81,8 @@ namespace DS4Windows vRemainder = 0.0; } - int deadzoneX = (int)Math.Abs(normX * GYRO_MOUSE_DEADZONE); - int deadzoneY = (int)Math.Abs(normY * GYRO_MOUSE_DEADZONE); + int deadzoneX = (int)Math.Abs(normX * gyroCursorDeadZone); + int deadzoneY = (int)Math.Abs(normY * gyroCursorDeadZone); if (Math.Abs(deltaX) > deadzoneX) { diff --git a/DS4Windows/DS4Control/ScpUtil.cs b/DS4Windows/DS4Control/ScpUtil.cs index 497d584..3430e23 100644 --- a/DS4Windows/DS4Control/ScpUtil.cs +++ b/DS4Windows/DS4Control/ScpUtil.cs @@ -778,6 +778,17 @@ namespace DS4Windows return m_Config.gyroMouseHorizontalAxis[index]; } + public static int[] GyroMouseDeadZone => m_Config.gyroMouseDZ; + public static int GetGyroMouseDeadZone(int index) + { + return m_Config.gyroMouseDZ[index]; + } + + public static void SetGyroMouseDeadZone(int index, int value, ControlService control) + { + m_Config.SetGyroMouseDZ(index, value, control); + } + public static DS4Color[] MainColor => m_Config.m_Leds; public static DS4Color getMainColor(int index) { @@ -1437,6 +1448,9 @@ namespace DS4Windows public int[] flashAt = new int[5] { 0, 0, 0, 0, 0 }; public bool[] mouseAccel = new bool[5] { true, true, true, true, true }; public int[] btPollRate = new int[5] { 4, 4, 4, 4, 4 }; + public int[] gyroMouseDZ = new int[5] { MouseCursor.GYRO_MOUSE_DEADZONE, MouseCursor.GYRO_MOUSE_DEADZONE, + MouseCursor.GYRO_MOUSE_DEADZONE, MouseCursor.GYRO_MOUSE_DEADZONE, + MouseCursor.GYRO_MOUSE_DEADZONE }; public int[] lsOutCurveMode = new int[5] { 0, 0, 0, 0, 0 }; public int[] rsOutCurveMode = new int[5] { 0, 0, 0, 0, 0 }; public int[] l2OutCurveMode = new int[5] { 0, 0, 0, 0, 0 }; @@ -1656,6 +1670,13 @@ namespace DS4Windows sATriggerCond[index] = SaTriggerCondValue(text); } + public void SetGyroMouseDZ(int index, int value, ControlService control) + { + gyroMouseDZ[index] = value; + if (index < 4 && control.touchPad[index] != null) + control.touchPad[index].CursorGyroDead = value; + } + public bool SaveProfile(int device, string propath) { bool Saved = true; @@ -1757,6 +1778,7 @@ namespace DS4Windows XmlNode xmlGyroSmoothWeight = m_Xdoc.CreateNode(XmlNodeType.Element, "GyroSmoothingWeight", null); xmlGyroSmoothWeight.InnerText = Convert.ToInt32(gyroSmoothWeight[device] * 100).ToString(); Node.AppendChild(xmlGyroSmoothWeight); XmlNode xmlGyroSmoothing = m_Xdoc.CreateNode(XmlNodeType.Element, "GyroSmoothing", null); xmlGyroSmoothing.InnerText = gyroSmoothing[device].ToString(); Node.AppendChild(xmlGyroSmoothing); XmlNode xmlGyroMouseHAxis = m_Xdoc.CreateNode(XmlNodeType.Element, "GyroMouseHAxis", null); xmlGyroMouseHAxis.InnerText = gyroMouseHorizontalAxis[device].ToString(); Node.AppendChild(xmlGyroMouseHAxis); + XmlNode xmlGyroMouseDZ = m_Xdoc.CreateNode(XmlNodeType.Element, "GyroMouseDeadZone", null); xmlGyroMouseDZ.InnerText = gyroMouseDZ[device].ToString(); Node.AppendChild(xmlGyroMouseDZ); XmlNode xmlLSC = m_Xdoc.CreateNode(XmlNodeType.Element, "LSCurve", null); xmlLSC.InnerText = lsCurve[device].ToString(); Node.AppendChild(xmlLSC); XmlNode xmlRSC = m_Xdoc.CreateNode(XmlNodeType.Element, "RSCurve", null); xmlRSC.InnerText = rsCurve[device].ToString(); Node.AppendChild(xmlRSC); XmlNode xmlProfileActions = m_Xdoc.CreateNode(XmlNodeType.Element, "ProfileActions", null); xmlProfileActions.InnerText = string.Join("/", profileActions[device]); Node.AppendChild(xmlProfileActions); @@ -2656,6 +2678,10 @@ namespace DS4Windows try { Item = m_Xdoc.SelectSingleNode("/" + rootname + "/GyroMouseHAxis"); int temp = 0; int.TryParse(Item.InnerText, out temp); gyroMouseHorizontalAxis[device] = Math.Min(Math.Max(0, temp), 1); } catch { gyroMouseHorizontalAxis[device] = 0; missingSetting = true; } + try { Item = m_Xdoc.SelectSingleNode("/" + rootname + "/GyroMouseDeadZone"); int.TryParse(Item.InnerText, out int temp); + SetGyroMouseDZ(device, temp, control); } + catch { SetGyroMouseDZ(device, MouseCursor.GYRO_MOUSE_DEADZONE, control); missingSetting = true; } + try { Item = m_Xdoc.SelectSingleNode("/" + rootname + "/LSCurve"); int.TryParse(Item.InnerText, out lsCurve[device]); } catch { lsCurve[device] = 0; missingSetting = true; } diff --git a/DS4Windows/DS4Forms/Options.Designer.cs b/DS4Windows/DS4Forms/Options.Designer.cs index bbd76ae..ecd459a 100644 --- a/DS4Windows/DS4Forms/Options.Designer.cs +++ b/DS4Windows/DS4Forms/Options.Designer.cs @@ -315,6 +315,8 @@ this.rBSAControls = new System.Windows.Forms.RadioButton(); this.rBSAMouse = new System.Windows.Forms.RadioButton(); this.pnlSAMouse = new System.Windows.Forms.Panel(); + this.label27 = new System.Windows.Forms.Label(); + this.gyroMouseDzNUD = new System.Windows.Forms.NumericUpDown(); this.label26 = new System.Windows.Forms.Label(); this.triggerCondAndCombo = new System.Windows.Forms.ComboBox(); this.cBGyroMouseXAxis = new System.Windows.Forms.ComboBox(); @@ -470,6 +472,7 @@ this.fLPSettings.SuspendLayout(); this.gBGyro.SuspendLayout(); this.pnlSAMouse.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gyroMouseDzNUD)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.nUDGyroSmoothWeight)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.nUDGyroMouseVertScale)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.nUDGyroSensitivity)).BeginInit(); @@ -3392,6 +3395,8 @@ // // pnlSAMouse // + this.pnlSAMouse.Controls.Add(this.label27); + this.pnlSAMouse.Controls.Add(this.gyroMouseDzNUD); this.pnlSAMouse.Controls.Add(this.label26); this.pnlSAMouse.Controls.Add(this.triggerCondAndCombo); this.pnlSAMouse.Controls.Add(this.cBGyroMouseXAxis); @@ -3414,6 +3419,22 @@ resources.ApplyResources(this.pnlSAMouse, "pnlSAMouse"); this.pnlSAMouse.Name = "pnlSAMouse"; // + // label27 + // + resources.ApplyResources(this.label27, "label27"); + this.label27.Name = "label27"; + // + // gyroMouseDzNUD + // + resources.ApplyResources(this.gyroMouseDzNUD, "gyroMouseDzNUD"); + this.gyroMouseDzNUD.Name = "gyroMouseDzNUD"; + this.gyroMouseDzNUD.Value = new decimal(new int[] { + 10, + 0, + 0, + 0}); + this.gyroMouseDzNUD.ValueChanged += new System.EventHandler(this.gyroMouseDzNUD_ValueChanged); + // // label26 // resources.ApplyResources(this.label26, "label26"); @@ -4240,6 +4261,7 @@ this.gBGyro.PerformLayout(); this.pnlSAMouse.ResumeLayout(false); this.pnlSAMouse.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gyroMouseDzNUD)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.nUDGyroSmoothWeight)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.nUDGyroMouseVertScale)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.nUDGyroSensitivity)).EndInit(); @@ -4620,5 +4642,7 @@ private System.Windows.Forms.CheckBox trackballCk; private System.Windows.Forms.Label label26; private System.Windows.Forms.ComboBox triggerCondAndCombo; + private System.Windows.Forms.Label label27; + private System.Windows.Forms.NumericUpDown gyroMouseDzNUD; } } \ No newline at end of file diff --git a/DS4Windows/DS4Forms/Options.cs b/DS4Windows/DS4Forms/Options.cs index 7c9aa91..368dfff 100644 --- a/DS4Windows/DS4Forms/Options.cs +++ b/DS4Windows/DS4Forms/Options.cs @@ -718,6 +718,7 @@ namespace DS4Windows nUDGyroSmoothWeight.Value = (decimal)(GyroSmoothingWeight[device]); cBGyroMouseXAxis.SelectedIndex = GyroMouseHorizontalAxis[device]; triggerCondAndCombo.SelectedIndex = SATriggerCond[device] ? 0 : 1; + gyroMouseDzNUD.Value = GyroMouseDeadZone[device]; } else { @@ -834,6 +835,7 @@ namespace DS4Windows cBGyroInvertY.Checked = false; cBGyroSmooth.Checked = false; nUDGyroSmoothWeight.Value = 0.5m; + gyroMouseDzNUD.Value = MouseCursor.GYRO_MOUSE_DEADZONE; cBGyroMouseXAxis.SelectedIndex = 0; triggerCondAndCombo.SelectedIndex = 0; Set(); @@ -1334,6 +1336,7 @@ namespace DS4Windows GyroSmoothing[device] = cBGyroSmooth.Checked; GyroSmoothingWeight[device] = (double)nUDGyroSmoothWeight.Value; GyroMouseHorizontalAxis[device] = cBGyroMouseXAxis.SelectedIndex; + SetGyroMouseDeadZone(device, (int)gyroMouseDzNUD.Value, Program.rootHub); int invert = 0; if (cBGyroInvertX.Checked) @@ -2989,6 +2992,15 @@ namespace DS4Windows } } + private void gyroMouseDzNUD_ValueChanged(object sender, EventArgs e) + { + if (loading == false) + { + SetGyroMouseDeadZone(device, (int)gyroMouseDzNUD.Value, + Program.rootHub); + } + } + private void trackFrictionNUD_ValueChanged(object sender, EventArgs e) { if (loading == false) diff --git a/DS4Windows/DS4Forms/Options.resx b/DS4Windows/DS4Forms/Options.resx index 4e941eb..5dffefb 100644 --- a/DS4Windows/DS4Forms/Options.resx +++ b/DS4Windows/DS4Forms/Options.resx @@ -148,7 +148,7 @@ 0 - 30, 215 + 28, 207 39, 20 @@ -256,7 +256,7 @@ NoControl - 6, 191 + 6, 184 111, 17 @@ -346,7 +346,7 @@ NoControl - 72, 218 + 70, 210 59, 13 @@ -1335,6 +1335,198 @@ 1 + + pnlTPMouse + + + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBTouchpad + + + 0 + + + rBTPControls + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBTouchpad + + + 1 + + + rBTPMouse + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBTouchpad + + + 2 + + + fLPTouchSwipe + + + System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBTouchpad + + + 3 + + + 2, 259 + + + 270, 190 + + + 246 + + + Touchpad + + + gBTouchpad + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tPControls + + + 1 + + + trackFrictionLb + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlTPMouse + + + 0 + + + trackFrictionNUD + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlTPMouse + + + 1 + + + trackballCk + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlTPMouse + + + 2 + + + touchpadDisInvertButton + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlTPMouse + + + 3 + + + label25 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlTPMouse + + + 4 + + + label15 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlTPMouse + + + 5 + + + touchpadInvertComboBox + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlTPMouse + + + 6 + + + cbStartTouchpadOff + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlTPMouse + + + 16 + + + 0, 36 + + + 2, 2, 2, 2 + + + 266, 149 + + + 257 + + + pnlTPMouse + + + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBTouchpad + + + 0 + True @@ -1566,30 +1758,6 @@ 16 - - 0, 36 - - - 2, 2, 2, 2 - - - 266, 149 - - - 257 - - - pnlTPMouse - - - System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBTouchpad - - - 0 - True @@ -1656,156 +1824,126 @@ 2 + + bnSwipeUp + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + fLPTouchSwipe + + + 0 + + + lbSwipeUp + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + fLPTouchSwipe + + + 1 + + + bnSwipeDown + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + fLPTouchSwipe + + + 2 + + + lbSwipeDown + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + fLPTouchSwipe + + + 3 + + + bnSwipeLeft + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + fLPTouchSwipe + + + 4 + + + lbSwipeLeft + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + fLPTouchSwipe + + + 5 + + + bnSwipeRight + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + fLPTouchSwipe + + + 6 + + + lbSwipeRight + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + fLPTouchSwipe + + + 7 + + + 6, 40 + + + 260, 148 + + + 256 + + + fLPTouchSwipe + + + System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBTouchpad + + + 3 + 326, 13 - - False - - - 117, 22 - - - Control - - - 114, 6 - - - 117, 22 - - - Default - - - 127, 22 - - - Inverted - - - 127, 22 - - - Inverted X - - - 127, 22 - - - Inverted Y - - - 117, 22 - - - Dpad - - - 127, 22 - - - Inverted - - - 127, 22 - - - Inverted X - - - 127, 22 - - - Inverted Y - - - 117, 22 - - - Left Stick - - - 127, 22 - - - Inverted - - - 127, 22 - - - Inverted X - - - 127, 22 - - - Inverted Y - - - 117, 22 - - - Right Stick - - - 117, 22 - - - Face Buttons - - - 147, 22 - - - w/ Scan Code - - - False - - - 117, 22 - - - WASD - - - 147, 22 - - - w/ Scan Code - - - 117, 22 - - - Arrow Keys - - - 127, 22 - - - Inverted - - - 127, 22 - - - Inverted X - - - 127, 22 - - - Inverted Y - - - 117, 22 - - - Mouse - 118, 208 @@ -1845,6 +1983,153 @@ 0 + + False + + + 117, 22 + + + Control + + + 114, 6 + + + 117, 22 + + + Default + + + 117, 22 + + + Dpad + + + 127, 22 + + + Inverted + + + 127, 22 + + + Inverted X + + + 127, 22 + + + Inverted Y + + + 117, 22 + + + Left Stick + + + 127, 22 + + + Inverted + + + 127, 22 + + + Inverted X + + + 127, 22 + + + Inverted Y + + + 117, 22 + + + Right Stick + + + 127, 22 + + + Inverted + + + 127, 22 + + + Inverted X + + + 127, 22 + + + Inverted Y + + + 117, 22 + + + Face Buttons + + + False + + + 117, 22 + + + WASD + + + 147, 22 + + + w/ Scan Code + + + 117, 22 + + + Arrow Keys + + + 147, 22 + + + w/ Scan Code + + + 117, 22 + + + Mouse + + + 127, 22 + + + Inverted + + + 127, 22 + + + Inverted X + + + 127, 22 + + + Inverted Y + NoControl @@ -2067,50 +2352,173 @@ 7 - - 6, 40 + + btPollRateLabel - - 260, 148 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 256 + + gBOther - - fLPTouchSwipe + + 0 - - System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + btPollRateComboBox - - gBTouchpad + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + gBOther + + + 1 + + + enableTouchToggleCheckbox + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBOther + + + 2 + + + cBDinput + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBOther + + 3 - - 2, 259 + + pBProgram - - 270, 190 + + System.Windows.Forms.PictureBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 246 + + gBOther - - Touchpad + + 4 - - gBTouchpad + + cBLaunchProgram - + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBOther + + + 5 + + + btnBrowse + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBOther + + + 6 + + + lbUseController + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBOther + + + 7 + + + cBMouseAccel + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBOther + + + 8 + + + nUDSixaxis + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBOther + + + 9 + + + cBControllerInput + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBOther + + + 10 + + + cBIdleDisconnect + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBOther + + + 12 + + + 281, 221 + + + 272, 256 + + + 247 + + + Other + + + gBOther + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - tPControls + + fLPSettings - - 1 + + 5 True @@ -2524,35 +2932,155 @@ with profile 12 - - 281, 221 + + btnRainbow - - 272, 256 + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + gBLightbar + + + 0 + + + lbRainbowB + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBLightbar + + + 1 + + + nUDRainbowB + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBLightbar + + + 2 + + + cBFlashType + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBLightbar + + + 3 + + + cBWhileCharging + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBLightbar + + + 4 + + + btnFlashColor + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBLightbar + + + 5 + + + btnChargingColor + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBLightbar + + + 6 + + + lbWhileCharging + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBLightbar + + + 7 + + + lbPercentFlashBar + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBLightbar + + + 8 + + + nUDflashLED + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBLightbar + + + 9 + + + 3, 3 + + + 272, 233 + + 247 - - Other + + Lightbar - - gBOther + + gBLightbar - + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + fLPSettings - - 5 + + 0 NoControl - 6, 214 + 4, 206 2, 2, 2, 2 @@ -2582,7 +3110,7 @@ with profile NoControl - 203, 214 + 201, 206 15, 13 @@ -2609,7 +3137,7 @@ with profile 1 - 151, 214 + 149, 206 43, 20 @@ -2639,7 +3167,7 @@ with profile Pulse at - 4, 133 + 6, 123 68, 21 @@ -2672,7 +3200,7 @@ with profile Color - 91, 166 + 90, 156 121, 21 @@ -2702,7 +3230,7 @@ with profile NoControl - 146, 137 + 148, 127 13, 13 @@ -2729,7 +3257,7 @@ with profile NoControl - 218, 168 + 217, 158 13, 13 @@ -2759,7 +3287,7 @@ with profile NoControl - 5, 167 + 4, 157 82, 13 @@ -2813,7 +3341,7 @@ with profile 8 - 78, 134 + 80, 124 43, 20 @@ -2833,29 +3361,53 @@ with profile 9 - - 3, 3 + + lbPercentRumble - - 272, 244 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + gBRumble + + + 0 + + + btnRumbleLightTest + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBRumble + + + 1 + + + 281, 3 + + + 272, 46 + + 247 - - Lightbar + + Rumble - - gBLightbar + + gBRumble - + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + fLPSettings - - 0 + + 2 True @@ -2914,30 +3466,6 @@ with profile 1 - - 281, 3 - - - 272, 46 - - - 247 - - - Rumble - - - gBRumble - - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - fLPSettings - - - 2 - True @@ -3046,6 +3574,225 @@ with profile 153, 17 + + pnlSATrack + + + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + lbL2TrackS + + + 0 + + + lbL2Track + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + lbL2TrackS + + + 1 + + + lbRSTip + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + lbL2TrackS + + + 2 + + + lbInputDelay + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + lbL2TrackS + + + 3 + + + lbR2Track + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + lbL2TrackS + + + 4 + + + lbLSTip + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + lbL2TrackS + + + 5 + + + lbSATip + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + lbL2TrackS + + + 6 + + + tBR2 + + + System.Windows.Forms.TrackBar, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + lbL2TrackS + + + 7 + + + tBL2 + + + System.Windows.Forms.TrackBar, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + lbL2TrackS + + + 8 + + + pnlSixaxis + + + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + lbL2TrackS + + + 9 + + + pnlLSTrack + + + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + lbL2TrackS + + + 10 + + + pnlRSTrack + + + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + lbL2TrackS + + + 11 + + + 4, 22 + + + 3, 3, 3, 3 + + + 438, 455 + + + 2 + + + Controller Readings + + + lbL2TrackS + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tCControls + + + 2 + + + btnSATrack + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSATrack + + + 0 + + + btnSATrackS + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSATrack + + + 1 + + + 300, 88 + + + 2, 2, 2, 2 + + + 125, 125 + + + 252 + + + pnlSATrack + + + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + lbL2TrackS + + + 0 + False @@ -3109,30 +3856,6 @@ with profile 1 - - 300, 88 - - - 2, 2, 2, 2 - - - 125, 125 - - - 252 - - - pnlSATrack - - - System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - lbL2TrackS - - - 0 - True @@ -3397,6 +4120,123 @@ with profile 8 + + tBsixaxisAccelX + + + System.Windows.Forms.TrackBar, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSixaxis + + + 0 + + + lb6Accel + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSixaxis + + + 1 + + + tBsixaxisGyroX + + + System.Windows.Forms.TrackBar, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSixaxis + + + 2 + + + lb6Gryo + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSixaxis + + + 3 + + + tBsixaxisGyroY + + + System.Windows.Forms.TrackBar, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSixaxis + + + 4 + + + tBsixaxisGyroZ + + + System.Windows.Forms.TrackBar, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSixaxis + + + 5 + + + tBsixaxisAccelY + + + System.Windows.Forms.TrackBar, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSixaxis + + + 6 + + + tBsixaxisAccelZ + + + System.Windows.Forms.TrackBar, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSixaxis + + + 7 + + + 300, 233 + + + 125, 125 + + + 236 + + + pnlSixaxis + + + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + lbL2TrackS + + + 9 + False @@ -3619,26 +4459,53 @@ with profile 7 - - 300, 233 + + btnLSTrack - + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlLSTrack + + + 0 + + + btnLSTrackS + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlLSTrack + + + 1 + + + 5, 88 + + + 2, 2, 2, 2 + + 125, 125 - - 236 + + 250 - - pnlSixaxis + + pnlLSTrack - + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + lbL2TrackS - - 9 + + 10 False @@ -3703,29 +4570,53 @@ with profile 1 - - 5, 88 + + btnRSTrackS - + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlRSTrack + + + 0 + + + btnRSTrack + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlRSTrack + + + 1 + + + 151, 88 + + 2, 2, 2, 2 - + 125, 125 - - 250 + + 251 - - pnlLSTrack + + pnlRSTrack - + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + lbL2TrackS - - 10 + + 11 False @@ -3790,56 +4681,122 @@ with profile 1 - - 151, 88 + + bnGyroZN - - 2, 2, 2, 2 + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 125, 125 + + fLPTiltControls - - 251 + + 0 - - pnlRSTrack + + lbGyroZN - - System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - lbL2TrackS + + fLPTiltControls - - 11 + + 1 - - 4, 22 + + bnGyroZP - - 3, 3, 3, 3 + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 438, 455 + + fLPTiltControls - + 2 - - Controller Readings + + lbGyroZP - - lbL2TrackS + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + fLPTiltControls - - tCControls + + 3 - - 2 + + bnGyroXP + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + fLPTiltControls + + + 4 + + + lbGyroXP + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + fLPTiltControls + + + 5 + + + bnGyroXN + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + fLPTiltControls + + + 6 + + + lbGyroXN + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + fLPTiltControls + + + 7 + + + 4, 43 + + + 271, 167 + + + 254 + + + fLPTiltControls + + + System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBGyro + + + 3 NoControl @@ -4057,30 +5014,120 @@ with profile 7 - - 4, 43 + + tPControls - - 271, 167 + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 254 + + tCControls - - fLPTiltControls + + 0 - - System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + tPSpecial - - gBGyro + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 3 + + tCControls + + + 1 + + + Left + + + 0, 0 + + + 446, 481 + + + 253 + + + tCControls + + + System.Windows.Forms.TabControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 4 True + + lBControls + + + System.Windows.Forms.ListBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tPControls + + + 0 + + + lbControlTip + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tPControls + + + 2 + + + pnlController + + + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tPControls + + + 3 + + + 4, 22 + + + 3, 3, 3, 3 + + + 438, 455 + + + 0 + + + Controls + + + tPControls + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tCControls + + + 0 + Top, Bottom, Left @@ -4240,6 +5287,654 @@ with profile Zoom + + pBHoveredButton + + + System.Windows.Forms.PictureBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 0 + + + lbLRS + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 1 + + + lbLLS + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 2 + + + bnRSDown + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 3 + + + lbLTouchUpper + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 4 + + + lbLTouchRight + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 5 + + + bnL3 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 6 + + + lbLTouchLM + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 7 + + + bnRSUp + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 8 + + + lbLR2 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 9 + + + bnRSRight + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 10 + + + lbLL2 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 11 + + + bnR3 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 12 + + + lbLR1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 13 + + + bnRSLeft + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 14 + + + lbLL1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 15 + + + bnLSLeft + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 16 + + + lbLPS + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 17 + + + bnLSUp + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 18 + + + lbLLeft + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 19 + + + bnLSRight + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 20 + + + lbLright + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 21 + + + bnLSDown + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 22 + + + lbLDown + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 23 + + + bnR2 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 24 + + + bnUp + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 25 + + + bnDown + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 26 + + + bnTriangle + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 27 + + + bnR1 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 28 + + + bnSquare + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 29 + + + bnRight + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 30 + + + lbLUp + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 31 + + + bnLeft + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 32 + + + lbLShare + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 33 + + + bnOptions + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 34 + + + bnShare + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 35 + + + lbLOptions + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 36 + + + bnL1 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 37 + + + bnTouchRight + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 38 + + + bnL2 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 39 + + + lbLTriangle + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 40 + + + bnTouchLeft + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 41 + + + lbLSquare + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 42 + + + bnTouchMulti + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 43 + + + lbLCircle + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 44 + + + lbLCross + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 45 + + + bnTouchUpper + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 46 + + + btnLightbar + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 47 + + + bnPS + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 48 + + + bnCross + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 49 + + + bnCircle + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 50 + + + lbControlName + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlController + + + 51 + + + 2, 2 + + + 2, 2, 2, 2 + + + 422, 230 + + + 282 + + + pnlController + + + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tPControls + + + 3 + False @@ -5890,74 +7585,89 @@ with profile 51 - - 2, 2 + + pnlActions - - 2, 2, 2, 2 - - - 422, 230 - - - 282 - - - pnlController - - + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - tPControls + + tPSpecial - - 3 + + 0 - + 4, 22 - - 3, 3, 3, 3 - - + 438, 455 - - 0 + + 3 - - Controls + + Special Actions - - tPControls + + tPSpecial - + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + tCControls - + + 1 + + + lVActions + + + System.Windows.Forms.ListView, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlActions + + 0 - - Name + + panel2 - - 140 + + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Trigger + + pnlActions - - 105 + + 1 - - Action + + Fill - - 100 + + 0, 0 + + + 438, 455 + + + 15 + + + pnlActions + + + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tPSpecial + + + 0 Fill @@ -5983,6 +7693,135 @@ with profile 0 + + Name + + + 140 + + + Trigger + + + 105 + + + Action + + + 100 + + + fLPActionButtons + + + System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + panel2 + + + 0 + + + lbActionsTip + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + panel2 + + + 1 + + + Top + + + 0, 0 + + + 2, 2, 2, 2 + + + 438, 66 + + + 16 + + + panel2 + + + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlActions + + + 1 + + + btnNewAction + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + fLPActionButtons + + + 0 + + + btnEditAction + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + fLPActionButtons + + + 1 + + + btnRemAction + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + fLPActionButtons + + + 2 + + + Fill + + + 0, 28 + + + 438, 38 + + + 15 + + + fLPActionButtons + + + System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + panel2 + + + 0 + NoControl @@ -6064,30 +7903,6 @@ with profile 2 - - Fill - - - 0, 28 - - - 438, 38 - - - 15 - - - fLPActionButtons - - - System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - panel2 - - - 0 - Top @@ -6121,104 +7936,98 @@ with profile 1 - - Top + + tPDeadzone - - 0, 0 - - - 2, 2, 2, 2 - - - 438, 66 - - - 16 - - - panel2 - - - System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlActions - - - 1 - - - Fill - - - 0, 0 - - - 438, 455 - - - 15 - - - pnlActions - - - System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tPSpecial - - - 0 - - - 4, 22 - - - 438, 455 - - - 3 - - - Special Actions - - - tPSpecial - - + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - tCControls + + tCSens - + + 0 + + + antiDeadzoneTabPage + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tCSens + + 1 - - Left + + maxZoneTabPage - - 0, 0 + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 446, 481 + + tCSens - - 253 + + 2 - - tCControls + + tPOutCurve - + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tCSens + + + 3 + + + tPCurve + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tCSens + + + 4 + + + tpRotation + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tCSens + + + 5 + + + 281, 55 + + + 272, 78 + + + 234 + + + tCSens + + System.Windows.Forms.TabControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - $this + + fLPSettings - - 4 + + 3 4, 22 @@ -6247,6 +8056,177 @@ with profile 0 + + nUDSixaxisZAntiDead + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + antiDeadzoneTabPage + + + 0 + + + nUDSixaxisXAntiDead + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + antiDeadzoneTabPage + + + 1 + + + label20 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + antiDeadzoneTabPage + + + 2 + + + label19 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + antiDeadzoneTabPage + + + 3 + + + nUDR2AntiDead + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + antiDeadzoneTabPage + + + 4 + + + label3 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + antiDeadzoneTabPage + + + 5 + + + nUDL2AntiDead + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + antiDeadzoneTabPage + + + 6 + + + label4 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + antiDeadzoneTabPage + + + 7 + + + nUDRSAntiDead + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + antiDeadzoneTabPage + + + 8 + + + label2 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + antiDeadzoneTabPage + + + 9 + + + nUDLSAntiDead + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + antiDeadzoneTabPage + + + 10 + + + label1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + antiDeadzoneTabPage + + + 11 + + + 4, 22 + + + 3, 3, 3, 3 + + + 264, 52 + + + 2 + + + Anti-Deadzone + + + antiDeadzoneTabPage + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tCSens + + + 1 + 214, 29 @@ -6553,32 +8533,176 @@ with profile 11 - - 4, 22 + + nUDSixAxisZMaxZone - - 3, 3, 3, 3 + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 264, 52 + + maxZoneTabPage - + + 0 + + + nUDSixAxisXMaxZone + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + maxZoneTabPage + + + 1 + + + label18 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + maxZoneTabPage + + 2 - - Anti-Deadzone + + label17 - - antiDeadzoneTabPage + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + maxZoneTabPage + + + 3 + + + nUDR2Maxzone + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + maxZoneTabPage + + + 4 + + + nUDL2Maxzone + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + maxZoneTabPage + + + 5 + + + label8 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + maxZoneTabPage + + + 6 + + + label7 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + maxZoneTabPage + + + 7 + + + nUDRSMaxZone + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + maxZoneTabPage + + + 8 + + + label6 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + maxZoneTabPage + + + 9 + + + nUDLSMaxZone + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + maxZoneTabPage + + + 10 + + + label5 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + maxZoneTabPage + + + 11 + + + 4, 22 + + + 3, 3, 3, 3 + + + 264, 52 + + + 3 + + + Max Zone + + + maxZoneTabPage + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + tCSens - - 1 + + 2 220, 29 @@ -6886,32 +9010,173 @@ with profile 11 - - 4, 22 + + cBSixaxisZOutputCurve - - 3, 3, 3, 3 + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 264, 52 + + tPOutCurve - + + 0 + + + cBSixaxisXOutputCurve + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tPOutCurve + + + 1 + + + label24 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tPOutCurve + + + 2 + + + label23 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tPOutCurve + + 3 - - Max Zone + + cBR2OutputCurve - - maxZoneTabPage + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + tPOutCurve + + + 4 + + + cBL2OutputCurve + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tPOutCurve + + + 5 + + + label22 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tPOutCurve + + + 6 + + + label21 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tPOutCurve + + + 7 + + + rsOutCurveComboBox + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tPOutCurve + + + 8 + + + lsOutCurveComboBox + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tPOutCurve + + + 9 + + + label10 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tPOutCurve + + + 10 + + + label9 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tPOutCurve + + + 11 + + + 4, 22 + + + 264, 52 + + + 4 + + + Output Curve + + + tPOutCurve + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + tCSens - - 2 + + 3 Linear @@ -7297,29 +9562,104 @@ with profile 11 - - 4, 22 + + nUDLSCurve - - 264, 52 + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + tPCurve + + + 0 + + + nUDRSCurve + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tPCurve + + + 1 + + + lbRSCurve + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tPCurve + + + 2 + + + lbRSCurvePercent + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tPCurve + + + 3 + + + lbLSCurvePercent + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tPCurve + + 4 - - Output Curve + + lbLSCurve - - tPOutCurve + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + tPCurve + + + 5 + + + 4, 22 + + + 3, 3, 3, 3 + + + 264, 52 + + + 1 + + + Curve (Input) + + + tPCurve + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + tCSens - - 3 + + 4 36, 16 @@ -7489,32 +9829,80 @@ with profile 5 - - 4, 22 + + nUDRSRotation - - 3, 3, 3, 3 + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 264, 52 + + tpRotation - + + 0 + + + label14 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tpRotation + + 1 - - Curve (Input) + + nUDLSRotation - - tPCurve + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + tpRotation + + + 2 + + + label13 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tpRotation + + + 3 + + + 4, 22 + + + 3, 3, 3, 3 + + + 264, 52 + + + 5 + + + Rotation + + + tpRotation + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + tCSens - - 4 + + 5 160, 21 @@ -7618,54 +10006,6 @@ with profile 3 - - 4, 22 - - - 3, 3, 3, 3 - - - 264, 52 - - - 5 - - - Rotation - - - tpRotation - - - System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tCSens - - - 5 - - - 281, 55 - - - 272, 78 - - - 234 - - - tCSens - - - System.Windows.Forms.TabControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - fLPSettings - - - 3 - True @@ -7735,6 +10075,54 @@ with profile 1 + + True + + + 6, 158 + + + 56, 13 + + + 275 + + + Deadzone + + + label27 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSAMouse + + + 0 + + + 94, 156 + + + 43, 20 + + + 274 + + + gyroMouseDzNUD + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSAMouse + + + 1 + True @@ -7763,7 +10151,7 @@ with profile pnlSAMouse - 0 + 2 And @@ -7772,7 +10160,7 @@ with profile Or - 165, 67 + 165, 62 73, 21 @@ -7790,7 +10178,7 @@ with profile pnlSAMouse - 1 + 3 Yaw @@ -7799,7 +10187,7 @@ with profile Roll - 170, 114 + 169, 107 74, 21 @@ -7817,7 +10205,7 @@ with profile pnlSAMouse - 2 + 4 True @@ -7826,7 +10214,7 @@ with profile NoControl - 167, 95 + 166, 91 39, 13 @@ -7847,7 +10235,7 @@ with profile pnlSAMouse - 3 + 5 True @@ -7856,7 +10244,7 @@ with profile NoControl - 8, 145 + 6, 139 60, 13 @@ -7877,7 +10265,7 @@ with profile pnlSAMouse - 4 + 6 True @@ -7886,7 +10274,7 @@ with profile NoControl - 75, 145 + 73, 139 Yes @@ -7907,7 +10295,7 @@ with profile pnlSAMouse - 5 + 7 True @@ -7916,7 +10304,7 @@ with profile NoControl - 96, 145 + 94, 139 83, 13 @@ -7937,13 +10325,13 @@ with profile pnlSAMouse - 6 + 8 False - 185, 141 + 183, 135 55, 20 @@ -7961,7 +10349,7 @@ with profile pnlSAMouse - 7 + 9 True @@ -7991,10 +10379,10 @@ with profile pnlSAMouse - 8 + 10 - 96, 93 + 95, 89 49, 20 @@ -8012,7 +10400,7 @@ with profile pnlSAMouse - 9 + 11 True @@ -8021,7 +10409,7 @@ with profile NoControl - 8, 95 + 7, 91 75, 13 @@ -8042,7 +10430,7 @@ with profile pnlSAMouse - 10 + 12 True @@ -8075,7 +10463,7 @@ with profile pnlSAMouse - 11 + 13 True @@ -8084,7 +10472,7 @@ with profile NoControl - 92, 119 + 95, 114 Yes @@ -8108,7 +10496,7 @@ with profile pnlSAMouse - 12 + 14 True @@ -8117,7 +10505,7 @@ with profile NoControl - 49, 119 + 52, 114 Yes @@ -8141,7 +10529,7 @@ with profile pnlSAMouse - 13 + 15 True @@ -8150,7 +10538,7 @@ with profile NoControl - 8, 119 + 11, 114 37, 13 @@ -8174,7 +10562,7 @@ with profile pnlSAMouse - 14 + 16 True @@ -8207,7 +10595,7 @@ with profile pnlSAMouse - 15 + 17 NoControl @@ -8237,10 +10625,10 @@ with profile pnlSAMouse - 16 + 18 - 96, 67 + 96, 62 49, 20 @@ -8258,7 +10646,7 @@ with profile pnlSAMouse - 17 + 19 True @@ -8267,7 +10655,7 @@ with profile NoControl - 8, 69 + 8, 64 82, 13 @@ -8291,16 +10679,16 @@ with profile pnlSAMouse - 18 + 20 - 6, 43 + 6, 39 2, 2, 2, 2 - 263, 170 + 263, 181 259 @@ -8318,7 +10706,7 @@ with profile 2 - 3, 253 + 3, 242 272, 224 @@ -8341,6 +10729,204 @@ with profile 1 + + lbL2S + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBSensitivity + + + 0 + + + nUDL2S + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBSensitivity + + + 1 + + + nUDLSS + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBSensitivity + + + 2 + + + lbSixaxisXS + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBSensitivity + + + 3 + + + nUDR2S + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBSensitivity + + + 4 + + + lbSixaxisZS + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBSensitivity + + + 5 + + + nUDRSS + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBSensitivity + + + 6 + + + lbR2LS + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBSensitivity + + + 7 + + + nUDSXS + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBSensitivity + + + 8 + + + lbRSS + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBSensitivity + + + 9 + + + lbLSS + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBSensitivity + + + 10 + + + nUDSZS + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBSensitivity + + + 11 + + + 281, 139 + + + 272, 76 + + + 257 + + + Sensitivity + + + gBSensitivity + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + fLPSettings + + + 4 + + + Fill + + + TopDown + + + 446, 0 + + + 2, 2, 2, 2 + + + 565, 481 + + + 254 + + + fLPSettings + + + System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + True @@ -8659,63 +11245,18 @@ with profile 11 - - 281, 139 - - - 272, 76 - - - 257 - - - Sensitivity - - - gBSensitivity - - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - fLPSettings - - - 4 - - - Fill - - - TopDown - - - 446, 0 - - - 2, 2, 2, 2 - - - 565, 481 - - - 254 - - - fLPSettings - - - System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 3 - 482, 17 + + 195, 444 + + + cMGyroTriggers + + + System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + 194, 22 @@ -8836,18 +11377,18 @@ with profile Always on - - 195, 444 - - - cMGyroTriggers - - - System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - 144, 63 + + 195, 422 + + + cMTouchDisableInvert + + + System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + 194, 22 @@ -8962,15 +11503,6 @@ with profile PS - - 195, 422 - - - cMTouchDisableInvert - - - System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - 647, 17 From 6eb5ddf58980735ecb2121152610bebca5839c82 Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Thu, 31 Jan 2019 11:48:01 -0600 Subject: [PATCH 13/66] Increase minimum size of Options form --- DS4Windows/DS4Forms/Options.resx | 480 +++++++++++++++++++++++++------ 1 file changed, 396 insertions(+), 84 deletions(-) diff --git a/DS4Windows/DS4Forms/Options.resx b/DS4Windows/DS4Forms/Options.resx index 5dffefb..6826eb5 100644 --- a/DS4Windows/DS4Forms/Options.resx +++ b/DS4Windows/DS4Forms/Options.resx @@ -5045,7 +5045,7 @@ with profile 0, 0 - 446, 481 + 446, 511 253 @@ -5108,7 +5108,7 @@ with profile 3, 3, 3, 3 - 438, 455 + 438, 485 0 @@ -5234,7 +5234,7 @@ with profile 278, 254 - 157, 186 + 157, 212 180 @@ -10009,6 +10009,120 @@ with profile True + + gBGyro + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + fLPSettings + + + 1 + + + gBSensitivity + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + fLPSettings + + + 4 + + + Fill + + + TopDown + + + 446, 0 + + + 2, 2, 2, 2 + + + 565, 511 + + + 254 + + + fLPSettings + + + System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + rBSAControls + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBGyro + + + 0 + + + rBSAMouse + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBGyro + + + 1 + + + pnlSAMouse + + + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBGyro + + + 2 + + + 3, 242 + + + 272, 224 + + + 248 + + + Gyro + + + gBGyro + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + fLPSettings + + + 1 + True @@ -10075,6 +10189,282 @@ with profile 1 + + label27 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSAMouse + + + 0 + + + gyroMouseDzNUD + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSAMouse + + + 1 + + + label26 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSAMouse + + + 2 + + + triggerCondAndCombo + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSAMouse + + + 3 + + + cBGyroMouseXAxis + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSAMouse + + + 4 + + + label16 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSAMouse + + + 5 + + + lbGyroSmooth + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSAMouse + + + 6 + + + cBGyroSmooth + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSAMouse + + + 7 + + + lbSmoothWeight + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSAMouse + + + 8 + + + nUDGyroSmoothWeight + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSAMouse + + + 9 + + + label12 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSAMouse + + + 10 + + + nUDGyroMouseVertScale + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSAMouse + + + 11 + + + label11 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSAMouse + + + 12 + + + gyroTriggerBehavior + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSAMouse + + + 13 + + + cBGyroInvertY + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSAMouse + + + 14 + + + cBGyroInvertX + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSAMouse + + + 15 + + + lbGyroInvert + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSAMouse + + + 16 + + + lbGyroTriggers + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSAMouse + + + 17 + + + btnGyroTriggers + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSAMouse + + + 18 + + + nUDGyroSensitivity + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSAMouse + + + 19 + + + lbGyroSens + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pnlSAMouse + + + 20 + + + 6, 39 + + + 2, 2, 2, 2 + + + 263, 181 + + + 259 + + + pnlSAMouse + + + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBGyro + + + 2 + True @@ -10681,54 +11071,6 @@ with profile 20 - - 6, 39 - - - 2, 2, 2, 2 - - - 263, 181 - - - 259 - - - pnlSAMouse - - - System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBGyro - - - 2 - - - 3, 242 - - - 272, 224 - - - 248 - - - Gyro - - - gBGyro - - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - fLPSettings - - - 1 - lbL2S @@ -10897,36 +11239,6 @@ with profile 4 - - Fill - - - TopDown - - - 446, 0 - - - 2, 2, 2, 2 - - - 565, 481 - - - 254 - - - fLPSettings - - - System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 3 - True @@ -11519,16 +11831,16 @@ with profile True - 1011, 481 + 1011, 511 4, 4, 4, 4 - 1027, 520 + 1027, 550 - 18, 94 + 18, 520 Profile Options From dd96beafbe2ff8849318acc18a5be409d9b36454 Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Thu, 31 Jan 2019 16:19:08 -0600 Subject: [PATCH 14/66] Purged old state mapping code that required dictionary object --- DS4Windows/DS4Control/Mapping.cs | 203 +++++-------------------------- 1 file changed, 31 insertions(+), 172 deletions(-) diff --git a/DS4Windows/DS4Control/Mapping.cs b/DS4Windows/DS4Control/Mapping.cs index d797c6e..c78a7fa 100644 --- a/DS4Windows/DS4Control/Mapping.cs +++ b/DS4Windows/DS4Control/Mapping.cs @@ -1183,7 +1183,7 @@ namespace DS4Windows cState.CopyTo(MappedState); - Dictionary tempControlDict = new Dictionary(); + //Dictionary tempControlDict = new Dictionary(); //MultiValueDict tempControlDict = new MultiValueDict(); DS4Controls usingExtra = DS4Controls.None; List tempSettingsList = getDS4CSettings(device); @@ -1345,10 +1345,38 @@ namespace DS4Windows xboxControl = getX360ControlsByName(action.ToString()); } - if (xboxControl >= X360Controls.LXNeg && xboxControl <= X360Controls.Start) + if (xboxControl >= X360Controls.LXNeg && xboxControl <= X360Controls.RYPos) { DS4Controls tempDS4Control = reverseX360ButtonMapping[(int)xboxControl]; - tempControlDict.Add(dcs.control, tempDS4Control); + int controlNum = (int)dcs.control; + int tempOutControl = (int)tempDS4Control; + DS4StateFieldMapping.ControlType controlType = DS4StateFieldMapping.mappedType[tempOutControl]; + bool alt = controlType == DS4StateFieldMapping.ControlType.AxisDir && tempOutControl % 2 == 0 ? true : false; + byte axisMapping = getXYAxisMapping2(device, dcs.control, cState, eState, tp, fieldMapping, alt); + if (axisMapping != 128) + { + int controlRelation = tempOutControl % 2 == 0 ? tempOutControl - 1 : tempOutControl + 1; + outputfieldMapping.axisdirs[tempOutControl] = axisMapping; + outputfieldMapping.axisdirs[controlRelation] = axisMapping; + } + + //tempControlDict.Add(dcs.control, tempDS4Control); + } + else if (xboxControl >= X360Controls.LB && xboxControl <= X360Controls.Start) + { + DS4Controls tempDS4Control = reverseX360ButtonMapping[(int)xboxControl]; + int controlNum = (int)dcs.control; + if (xboxControl == X360Controls.LT || xboxControl == X360Controls.RT) + { + byte axisMapping = getByteMapping2(device, dcs.control, cState, eState, tp, outputfieldMapping); + if (axisMapping != 0) + outputfieldMapping.triggers[(int)tempDS4Control] = axisMapping; + } + else + { + bool value = getBoolMapping2(device, dcs.control, cState, eState, tp, outputfieldMapping); + outputfieldMapping.buttons[(int)tempDS4Control] = value; + } } else if (xboxControl >= X360Controls.LeftMouse && xboxControl <= X360Controls.WDOWN) { @@ -1475,7 +1503,6 @@ namespace DS4Windows { if (getBoolActionMapping2(device, dcs.control, cState, eState, tp, fieldMapping)) { - resetToDefaultValue2(dcs.control, MappedState, outputfieldMapping); if (!pressedonce[keyvalue]) { deviceState.currentClicks.toggle = !deviceState.currentClicks.toggle; @@ -1526,174 +1553,6 @@ namespace DS4Windows if (macroControl[24]) MappedState.RY = 0; } - if (IfAxisIsNotModified(device, ShiftTrigger2(GetDS4STrigger(device, DS4Controls.LXNeg), device, cState, eState, tp, fieldMapping), DS4Controls.LXNeg)) - tempControlDict[DS4Controls.LXNeg] = DS4Controls.LXNeg; - - if (IfAxisIsNotModified(device, ShiftTrigger2(GetDS4STrigger(device, DS4Controls.LXPos), device, cState, eState, tp, fieldMapping), DS4Controls.LXPos)) - tempControlDict[DS4Controls.LXPos] = DS4Controls.LXPos; - - if (IfAxisIsNotModified(device, ShiftTrigger2(GetDS4STrigger(device, DS4Controls.LYNeg), device, cState, eState, tp, fieldMapping), DS4Controls.LYNeg)) - tempControlDict[DS4Controls.LYNeg] = DS4Controls.LYNeg; - - if (IfAxisIsNotModified(device, ShiftTrigger2(GetDS4STrigger(device, DS4Controls.LYPos), device, cState, eState, tp, fieldMapping), DS4Controls.LYPos)) - tempControlDict[DS4Controls.LYPos] = DS4Controls.LYPos; - - if (IfAxisIsNotModified(device, ShiftTrigger2(GetDS4STrigger(device, DS4Controls.RXNeg), device, cState, eState, tp, fieldMapping), DS4Controls.RXNeg)) - tempControlDict[DS4Controls.RXNeg] = DS4Controls.RXNeg; - - if (IfAxisIsNotModified(device, ShiftTrigger2(GetDS4STrigger(device, DS4Controls.RXPos), device, cState, eState, tp, fieldMapping), DS4Controls.RXPos)) - tempControlDict[DS4Controls.RXPos] = DS4Controls.RXPos; - - if (IfAxisIsNotModified(device, ShiftTrigger2(GetDS4STrigger(device, DS4Controls.RYNeg), device, cState, eState, tp, fieldMapping), DS4Controls.RYNeg)) - tempControlDict[DS4Controls.RYNeg] = DS4Controls.RYNeg; - - if (IfAxisIsNotModified(device, ShiftTrigger2(GetDS4STrigger(device, DS4Controls.RYPos), device, cState, eState, tp, fieldMapping), DS4Controls.RYPos)) - tempControlDict[DS4Controls.RYPos] = DS4Controls.RYPos; - - Dictionary.KeyCollection controlKeys = tempControlDict.Keys; - //Dictionary>.KeyCollection controlKeys = tempControlDict.Keys; - - //foreach (KeyValuePair entry in tempControlDict) - for (int i = 0, keyCount = controlKeys.Count; i < keyCount; i++) - { - DS4Controls key = controlKeys.ElementAt(i); - DS4Controls dc = tempControlDict[key]; - //DS4Controls key = entry.Key; - //DS4Controls dc = entry.Value; - - if (getBoolActionMapping2(device, key, cState, eState, tp, fieldMapping, true)) - { - if (dc >= DS4Controls.Square && dc <= DS4Controls.Cross) - { - switch (dc) - { - case DS4Controls.Cross: MappedState.Cross = true; break; - case DS4Controls.Circle: MappedState.Circle = true; break; - case DS4Controls.Square: MappedState.Square = true; break; - case DS4Controls.Triangle: MappedState.Triangle = true; break; - default: break; - } - } - else if (dc >= DS4Controls.L1 && dc <= DS4Controls.R3) - { - switch (dc) - { - case DS4Controls.L1: MappedState.L1 = true; break; - case DS4Controls.L2: MappedState.L2 = getByteMapping2(device, key, cState, eState, tp, fieldMapping); break; - case DS4Controls.L3: MappedState.L3 = true; break; - case DS4Controls.R1: MappedState.R1 = true; break; - case DS4Controls.R2: MappedState.R2 = getByteMapping2(device, key, cState, eState, tp, fieldMapping); break; - case DS4Controls.R3: MappedState.R3 = true; break; - default: break; - } - } - else if (dc >= DS4Controls.DpadUp && dc <= DS4Controls.DpadLeft) - { - switch (dc) - { - case DS4Controls.DpadUp: MappedState.DpadUp = true; break; - case DS4Controls.DpadRight: MappedState.DpadRight = true; break; - case DS4Controls.DpadLeft: MappedState.DpadLeft = true; break; - case DS4Controls.DpadDown: MappedState.DpadDown = true; break; - default: break; - } - } - else if (dc >= DS4Controls.LXNeg && dc <= DS4Controls.RYPos) - { - switch (dc) - { - case DS4Controls.LXNeg: - case DS4Controls.LXPos: - { - if (MappedState.LX == 128) - { - if (dc == DS4Controls.LXNeg) - { - byte axisMapping = getXYAxisMapping2(device, key, cState, eState, tp, fieldMapping); - MappedState.LX = axisMapping; - } - else - { - byte axisMapping = getXYAxisMapping2(device, key, cState, eState, tp, fieldMapping, true); - MappedState.LX = axisMapping; - } - } - - break; - } - case DS4Controls.LYNeg: - case DS4Controls.LYPos: - { - if (MappedState.LY == 128) - { - if (dc == DS4Controls.LYNeg) - { - byte axisMapping = getXYAxisMapping2(device, key, cState, eState, tp, fieldMapping); - MappedState.LY = axisMapping; - } - else - { - byte axisMapping = getXYAxisMapping2(device, key, cState, eState, tp, fieldMapping, true); - MappedState.LY = axisMapping; - } - } - - break; - } - case DS4Controls.RXNeg: - case DS4Controls.RXPos: - { - if (MappedState.RX == 128) - { - if (dc == DS4Controls.RXNeg) - { - byte axisMapping = getXYAxisMapping2(device, key, cState, eState, tp, fieldMapping); - MappedState.RX = axisMapping; - } - else - { - byte axisMapping = getXYAxisMapping2(device, key, cState, eState, tp, fieldMapping, true); - MappedState.RX = axisMapping; - } - } - - break; - } - case DS4Controls.RYNeg: - case DS4Controls.RYPos: - { - if (MappedState.RY == 128) - { - if (dc == DS4Controls.RYNeg) - { - byte axisMapping = getXYAxisMapping2(device, key, cState, eState, tp, fieldMapping); - MappedState.RY = axisMapping; - } - else - { - byte axisMapping = getXYAxisMapping2(device, key, cState, eState, tp, fieldMapping, true); - MappedState.RY = axisMapping; - } - } - - break; - } - default: break; - } - } - else - { - switch (dc) - { - case DS4Controls.Options: MappedState.Options = true; break; - case DS4Controls.Share: MappedState.Share = true; break; - case DS4Controls.PS: MappedState.PS = true; break; - default: break; - } - } - } - } - calculateFinalMouseMovement(ref tempMouseDeltaX, ref tempMouseDeltaY, out mouseDeltaX, out mouseDeltaY); if (mouseDeltaX != 0 || mouseDeltaY != 0) From 09103dcea8861f2424c869974aeaf8878fbeebfa Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Fri, 1 Feb 2019 05:08:53 -0600 Subject: [PATCH 15/66] Use input field mapping instead of output field mapping for refactor --- DS4Windows/DS4Control/Mapping.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DS4Windows/DS4Control/Mapping.cs b/DS4Windows/DS4Control/Mapping.cs index c78a7fa..7b4f893 100644 --- a/DS4Windows/DS4Control/Mapping.cs +++ b/DS4Windows/DS4Control/Mapping.cs @@ -1368,13 +1368,13 @@ namespace DS4Windows int controlNum = (int)dcs.control; if (xboxControl == X360Controls.LT || xboxControl == X360Controls.RT) { - byte axisMapping = getByteMapping2(device, dcs.control, cState, eState, tp, outputfieldMapping); + byte axisMapping = getByteMapping2(device, dcs.control, cState, eState, tp, fieldMapping); if (axisMapping != 0) outputfieldMapping.triggers[(int)tempDS4Control] = axisMapping; } else { - bool value = getBoolMapping2(device, dcs.control, cState, eState, tp, outputfieldMapping); + bool value = getBoolMapping2(device, dcs.control, cState, eState, tp, fieldMapping); outputfieldMapping.buttons[(int)tempDS4Control] = value; } } From ce87d8c212f794b1383a9dfabeae4ff2ca49f1fc Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Wed, 6 Feb 2019 21:42:34 -0600 Subject: [PATCH 16/66] Added toggle option for Gyro Mouse activation Not sure about this feature tbh. Related to issue #464. --- DS4Windows/DS4Control/Mouse.cs | 25 + DS4Windows/DS4Control/ScpUtil.cs | 21 + DS4Windows/DS4Forms/Options.Designer.cs | 10 + DS4Windows/DS4Forms/Options.cs | 16 + DS4Windows/DS4Forms/Options.resx | 4224 ++++------------------- 5 files changed, 801 insertions(+), 3495 deletions(-) diff --git a/DS4Windows/DS4Control/Mouse.cs b/DS4Windows/DS4Control/Mouse.cs index 7faaa72..cfba098 100644 --- a/DS4Windows/DS4Control/Mouse.cs +++ b/DS4Windows/DS4Control/Mouse.cs @@ -58,8 +58,18 @@ namespace DS4Windows trackballAccel = TRACKBALL_RADIUS * friction / TRACKBALL_INERTIA; } + public void ResetToggleGyroM() + { + currentToggleGyroM = false; + } + bool triggeractivated = false; + bool previousTriggerActivated = false; bool useReverseRatchet = false; + bool toggleGyroMouse = true; + public bool ToggleGyroMouse { get => toggleGyroMouse; + set { toggleGyroMouse = value; ResetToggleGyroM(); } } + bool currentToggleGyroM = false; public virtual void sixaxisMoved(object sender, SixAxisEventArgs arg) { @@ -91,6 +101,21 @@ namespace DS4Windows } } + if (toggleGyroMouse) + { + if (triggeractivated && triggeractivated != previousTriggerActivated) + { + currentToggleGyroM = !currentToggleGyroM; + } + + previousTriggerActivated = triggeractivated; + triggeractivated = currentToggleGyroM; + } + else + { + previousTriggerActivated = triggeractivated; + } + if (useReverseRatchet && triggeractivated) cursor.sixaxisMoved(arg); else if (!useReverseRatchet && !triggeractivated) diff --git a/DS4Windows/DS4Control/ScpUtil.cs b/DS4Windows/DS4Control/ScpUtil.cs index 3430e23..3716c4a 100644 --- a/DS4Windows/DS4Control/ScpUtil.cs +++ b/DS4Windows/DS4Control/ScpUtil.cs @@ -789,6 +789,10 @@ namespace DS4Windows m_Config.SetGyroMouseDZ(index, value, control); } + public static bool[] GyroMouseToggle => m_Config.gyroMouseToggle; + public static void SetGyroMouseToggle(int index, bool value, ControlService control) + => m_Config.SetGyroMouseToggle(index, value, control); + public static DS4Color[] MainColor => m_Config.m_Leds; public static DS4Color getMainColor(int index) { @@ -1451,6 +1455,8 @@ namespace DS4Windows public int[] gyroMouseDZ = new int[5] { MouseCursor.GYRO_MOUSE_DEADZONE, MouseCursor.GYRO_MOUSE_DEADZONE, MouseCursor.GYRO_MOUSE_DEADZONE, MouseCursor.GYRO_MOUSE_DEADZONE, MouseCursor.GYRO_MOUSE_DEADZONE }; + public bool[] gyroMouseToggle = new bool[5] { false, false, false, + false, false }; public int[] lsOutCurveMode = new int[5] { 0, 0, 0, 0, 0 }; public int[] rsOutCurveMode = new int[5] { 0, 0, 0, 0, 0 }; public int[] l2OutCurveMode = new int[5] { 0, 0, 0, 0, 0 }; @@ -1677,6 +1683,13 @@ namespace DS4Windows control.touchPad[index].CursorGyroDead = value; } + public void SetGyroMouseToggle(int index, bool value, ControlService control) + { + gyroMouseToggle[index] = value; + if (index < 4 && control.touchPad[index] != null) + control.touchPad[index].ToggleGyroMouse = value; + } + public bool SaveProfile(int device, string propath) { bool Saved = true; @@ -1779,6 +1792,7 @@ namespace DS4Windows XmlNode xmlGyroSmoothing = m_Xdoc.CreateNode(XmlNodeType.Element, "GyroSmoothing", null); xmlGyroSmoothing.InnerText = gyroSmoothing[device].ToString(); Node.AppendChild(xmlGyroSmoothing); XmlNode xmlGyroMouseHAxis = m_Xdoc.CreateNode(XmlNodeType.Element, "GyroMouseHAxis", null); xmlGyroMouseHAxis.InnerText = gyroMouseHorizontalAxis[device].ToString(); Node.AppendChild(xmlGyroMouseHAxis); XmlNode xmlGyroMouseDZ = m_Xdoc.CreateNode(XmlNodeType.Element, "GyroMouseDeadZone", null); xmlGyroMouseDZ.InnerText = gyroMouseDZ[device].ToString(); Node.AppendChild(xmlGyroMouseDZ); + XmlNode xmlGyroMouseToggle = m_Xdoc.CreateNode(XmlNodeType.Element, "GyroMouseToggle", null); xmlGyroMouseToggle.InnerText = gyroMouseToggle[device].ToString(); Node.AppendChild(xmlGyroMouseToggle); XmlNode xmlLSC = m_Xdoc.CreateNode(XmlNodeType.Element, "LSCurve", null); xmlLSC.InnerText = lsCurve[device].ToString(); Node.AppendChild(xmlLSC); XmlNode xmlRSC = m_Xdoc.CreateNode(XmlNodeType.Element, "RSCurve", null); xmlRSC.InnerText = rsCurve[device].ToString(); Node.AppendChild(xmlRSC); XmlNode xmlProfileActions = m_Xdoc.CreateNode(XmlNodeType.Element, "ProfileActions", null); xmlProfileActions.InnerText = string.Join("/", profileActions[device]); Node.AppendChild(xmlProfileActions); @@ -2682,6 +2696,13 @@ namespace DS4Windows SetGyroMouseDZ(device, temp, control); } catch { SetGyroMouseDZ(device, MouseCursor.GYRO_MOUSE_DEADZONE, control); missingSetting = true; } + try + { + Item = m_Xdoc.SelectSingleNode("/" + rootname + "/GyroMouseToggle"); bool.TryParse(Item.InnerText, out bool temp); + SetGyroMouseToggle(device, temp, control); + } + catch { SetGyroMouseToggle(device, false, control); missingSetting = true; } + try { Item = m_Xdoc.SelectSingleNode("/" + rootname + "/LSCurve"); int.TryParse(Item.InnerText, out lsCurve[device]); } catch { lsCurve[device] = 0; missingSetting = true; } diff --git a/DS4Windows/DS4Forms/Options.Designer.cs b/DS4Windows/DS4Forms/Options.Designer.cs index ecd459a..abb5e16 100644 --- a/DS4Windows/DS4Forms/Options.Designer.cs +++ b/DS4Windows/DS4Forms/Options.Designer.cs @@ -315,6 +315,7 @@ this.rBSAControls = new System.Windows.Forms.RadioButton(); this.rBSAMouse = new System.Windows.Forms.RadioButton(); this.pnlSAMouse = new System.Windows.Forms.Panel(); + this.toggleGyroMCb = new System.Windows.Forms.CheckBox(); this.label27 = new System.Windows.Forms.Label(); this.gyroMouseDzNUD = new System.Windows.Forms.NumericUpDown(); this.label26 = new System.Windows.Forms.Label(); @@ -3395,6 +3396,7 @@ // // pnlSAMouse // + this.pnlSAMouse.Controls.Add(this.toggleGyroMCb); this.pnlSAMouse.Controls.Add(this.label27); this.pnlSAMouse.Controls.Add(this.gyroMouseDzNUD); this.pnlSAMouse.Controls.Add(this.label26); @@ -3419,6 +3421,13 @@ resources.ApplyResources(this.pnlSAMouse, "pnlSAMouse"); this.pnlSAMouse.Name = "pnlSAMouse"; // + // toggleGyroMCb + // + resources.ApplyResources(this.toggleGyroMCb, "toggleGyroMCb"); + this.toggleGyroMCb.Name = "toggleGyroMCb"; + this.toggleGyroMCb.UseVisualStyleBackColor = true; + this.toggleGyroMCb.Click += new System.EventHandler(this.toggleGyroMCb_Click); + // // label27 // resources.ApplyResources(this.label27, "label27"); @@ -4644,5 +4653,6 @@ private System.Windows.Forms.ComboBox triggerCondAndCombo; private System.Windows.Forms.Label label27; private System.Windows.Forms.NumericUpDown gyroMouseDzNUD; + private System.Windows.Forms.CheckBox toggleGyroMCb; } } \ No newline at end of file diff --git a/DS4Windows/DS4Forms/Options.cs b/DS4Windows/DS4Forms/Options.cs index 368dfff..1ca64cc 100644 --- a/DS4Windows/DS4Forms/Options.cs +++ b/DS4Windows/DS4Forms/Options.cs @@ -719,6 +719,7 @@ namespace DS4Windows cBGyroMouseXAxis.SelectedIndex = GyroMouseHorizontalAxis[device]; triggerCondAndCombo.SelectedIndex = SATriggerCond[device] ? 0 : 1; gyroMouseDzNUD.Value = GyroMouseDeadZone[device]; + toggleGyroMCb.Checked = GyroMouseToggle[device]; } else { @@ -836,6 +837,7 @@ namespace DS4Windows cBGyroSmooth.Checked = false; nUDGyroSmoothWeight.Value = 0.5m; gyroMouseDzNUD.Value = MouseCursor.GYRO_MOUSE_DEADZONE; + toggleGyroMCb.Checked = false; cBGyroMouseXAxis.SelectedIndex = 0; triggerCondAndCombo.SelectedIndex = 0; Set(); @@ -1337,6 +1339,7 @@ namespace DS4Windows GyroSmoothingWeight[device] = (double)nUDGyroSmoothWeight.Value; GyroMouseHorizontalAxis[device] = cBGyroMouseXAxis.SelectedIndex; SetGyroMouseDeadZone(device, (int)gyroMouseDzNUD.Value, Program.rootHub); + SetGyroMouseToggle(device, toggleGyroMCb.Checked, Program.rootHub); int invert = 0; if (cBGyroInvertX.Checked) @@ -2817,6 +2820,8 @@ namespace DS4Windows if (!loading) { GyroTriggerTurns[device] = gyroTriggerBehavior.Checked; + if (device < 4) + Program.rootHub.touchPad[device]?.ResetToggleGyroM(); } } @@ -3001,6 +3006,17 @@ namespace DS4Windows } } + private void toggleGyroMCb_Click(object sender, EventArgs e) + { + if (loading == false) + { + if (device < 4) + { + SetGyroMouseToggle(device, toggleGyroMCb.Checked, Program.rootHub); + } + } + } + private void trackFrictionNUD_ValueChanged(object sender, EventArgs e) { if (loading == false) diff --git a/DS4Windows/DS4Forms/Options.resx b/DS4Windows/DS4Forms/Options.resx index 6826eb5..6663aff 100644 --- a/DS4Windows/DS4Forms/Options.resx +++ b/DS4Windows/DS4Forms/Options.resx @@ -1335,198 +1335,6 @@ 1 - - pnlTPMouse - - - System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBTouchpad - - - 0 - - - rBTPControls - - - System.Windows.Forms.RadioButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBTouchpad - - - 1 - - - rBTPMouse - - - System.Windows.Forms.RadioButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBTouchpad - - - 2 - - - fLPTouchSwipe - - - System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBTouchpad - - - 3 - - - 2, 259 - - - 270, 190 - - - 246 - - - Touchpad - - - gBTouchpad - - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tPControls - - - 1 - - - trackFrictionLb - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlTPMouse - - - 0 - - - trackFrictionNUD - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlTPMouse - - - 1 - - - trackballCk - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlTPMouse - - - 2 - - - touchpadDisInvertButton - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlTPMouse - - - 3 - - - label25 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlTPMouse - - - 4 - - - label15 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlTPMouse - - - 5 - - - touchpadInvertComboBox - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlTPMouse - - - 6 - - - cbStartTouchpadOff - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlTPMouse - - - 16 - - - 0, 36 - - - 2, 2, 2, 2 - - - 266, 149 - - - 257 - - - pnlTPMouse - - - System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBTouchpad - - - 0 - True @@ -1758,6 +1566,30 @@ 16 + + 0, 36 + + + 2, 2, 2, 2 + + + 266, 149 + + + 257 + + + pnlTPMouse + + + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gBTouchpad + + + 0 + True @@ -1824,126 +1656,156 @@ 2 - - bnSwipeUp - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - fLPTouchSwipe - - - 0 - - - lbSwipeUp - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - fLPTouchSwipe - - - 1 - - - bnSwipeDown - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - fLPTouchSwipe - - - 2 - - - lbSwipeDown - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - fLPTouchSwipe - - - 3 - - - bnSwipeLeft - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - fLPTouchSwipe - - - 4 - - - lbSwipeLeft - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - fLPTouchSwipe - - - 5 - - - bnSwipeRight - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - fLPTouchSwipe - - - 6 - - - lbSwipeRight - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - fLPTouchSwipe - - - 7 - - - 6, 40 - - - 260, 148 - - - 256 - - - fLPTouchSwipe - - - System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBTouchpad - - - 3 - 326, 13 + + False + + + 117, 22 + + + Control + + + 114, 6 + + + 117, 22 + + + Default + + + 127, 22 + + + Inverted + + + 127, 22 + + + Inverted X + + + 127, 22 + + + Inverted Y + + + 117, 22 + + + Dpad + + + 127, 22 + + + Inverted + + + 127, 22 + + + Inverted X + + + 127, 22 + + + Inverted Y + + + 117, 22 + + + Left Stick + + + 127, 22 + + + Inverted + + + 127, 22 + + + Inverted X + + + 127, 22 + + + Inverted Y + + + 117, 22 + + + Right Stick + + + 117, 22 + + + Face Buttons + + + 147, 22 + + + w/ Scan Code + + + False + + + 117, 22 + + + WASD + + + 147, 22 + + + w/ Scan Code + + + 117, 22 + + + Arrow Keys + + + 127, 22 + + + Inverted + + + 127, 22 + + + Inverted X + + + 127, 22 + + + Inverted Y + + + 117, 22 + + + Mouse + 118, 208 @@ -1983,153 +1845,6 @@ 0 - - False - - - 117, 22 - - - Control - - - 114, 6 - - - 117, 22 - - - Default - - - 117, 22 - - - Dpad - - - 127, 22 - - - Inverted - - - 127, 22 - - - Inverted X - - - 127, 22 - - - Inverted Y - - - 117, 22 - - - Left Stick - - - 127, 22 - - - Inverted - - - 127, 22 - - - Inverted X - - - 127, 22 - - - Inverted Y - - - 117, 22 - - - Right Stick - - - 127, 22 - - - Inverted - - - 127, 22 - - - Inverted X - - - 127, 22 - - - Inverted Y - - - 117, 22 - - - Face Buttons - - - False - - - 117, 22 - - - WASD - - - 147, 22 - - - w/ Scan Code - - - 117, 22 - - - Arrow Keys - - - 147, 22 - - - w/ Scan Code - - - 117, 22 - - - Mouse - - - 127, 22 - - - Inverted - - - 127, 22 - - - Inverted X - - - 127, 22 - - - Inverted Y - NoControl @@ -2352,173 +2067,50 @@ 7 - - btPollRateLabel + + 6, 40 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 260, 148 - - gBOther + + 256 - - 0 + + fLPTouchSwipe - - btPollRateComboBox + + System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + gBTouchpad - - gBOther - - - 1 - - - enableTouchToggleCheckbox - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBOther - - - 2 - - - cBDinput - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBOther - - + 3 - - pBProgram + + 2, 259 - - System.Windows.Forms.PictureBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 270, 190 - - gBOther + + 246 - - 4 + + Touchpad - - cBLaunchProgram + + gBTouchpad - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBOther - - - 5 - - - btnBrowse - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBOther - - - 6 - - - lbUseController - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBOther - - - 7 - - - cBMouseAccel - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBOther - - - 8 - - - nUDSixaxis - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBOther - - - 9 - - - cBControllerInput - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBOther - - - 10 - - - cBIdleDisconnect - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBOther - - - 12 - - - 281, 221 - - - 272, 256 - - - 247 - - - Other - - - gBOther - - + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - fLPSettings + + tPControls - - 5 + + 1 True @@ -2932,149 +2524,29 @@ with profile 12 - - btnRainbow + + 281, 221 - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 272, 256 - - gBLightbar - - - 0 - - - lbRainbowB - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBLightbar - - - 1 - - - nUDRainbowB - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBLightbar - - - 2 - - - cBFlashType - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBLightbar - - - 3 - - - cBWhileCharging - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBLightbar - - - 4 - - - btnFlashColor - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBLightbar - - - 5 - - - btnChargingColor - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBLightbar - - - 6 - - - lbWhileCharging - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBLightbar - - - 7 - - - lbPercentFlashBar - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBLightbar - - - 8 - - - nUDflashLED - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBLightbar - - - 9 - - - 3, 3 - - - 272, 233 - - + 247 - - Lightbar + + Other - - gBLightbar + + gBOther - + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + fLPSettings - - 0 + + 5 NoControl @@ -3361,53 +2833,29 @@ with profile 9 - - lbPercentRumble + + 3, 3 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 272, 233 - - gBRumble - - - 0 - - - btnRumbleLightTest - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBRumble - - - 1 - - - 281, 3 - - - 272, 46 - - + 247 - - Rumble + + Lightbar - - gBRumble + + gBLightbar - + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + fLPSettings - - 2 + + 0 True @@ -3466,6 +2914,30 @@ with profile 1 + + 281, 3 + + + 272, 46 + + + 247 + + + Rumble + + + gBRumble + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + fLPSettings + + + 2 + True @@ -3574,225 +3046,6 @@ with profile 153, 17 - - pnlSATrack - - - System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - lbL2TrackS - - - 0 - - - lbL2Track - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - lbL2TrackS - - - 1 - - - lbRSTip - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - lbL2TrackS - - - 2 - - - lbInputDelay - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - lbL2TrackS - - - 3 - - - lbR2Track - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - lbL2TrackS - - - 4 - - - lbLSTip - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - lbL2TrackS - - - 5 - - - lbSATip - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - lbL2TrackS - - - 6 - - - tBR2 - - - System.Windows.Forms.TrackBar, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - lbL2TrackS - - - 7 - - - tBL2 - - - System.Windows.Forms.TrackBar, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - lbL2TrackS - - - 8 - - - pnlSixaxis - - - System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - lbL2TrackS - - - 9 - - - pnlLSTrack - - - System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - lbL2TrackS - - - 10 - - - pnlRSTrack - - - System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - lbL2TrackS - - - 11 - - - 4, 22 - - - 3, 3, 3, 3 - - - 438, 455 - - - 2 - - - Controller Readings - - - lbL2TrackS - - - System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tCControls - - - 2 - - - btnSATrack - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSATrack - - - 0 - - - btnSATrackS - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSATrack - - - 1 - - - 300, 88 - - - 2, 2, 2, 2 - - - 125, 125 - - - 252 - - - pnlSATrack - - - System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - lbL2TrackS - - - 0 - False @@ -3856,6 +3109,30 @@ with profile 1 + + 300, 88 + + + 2, 2, 2, 2 + + + 125, 125 + + + 252 + + + pnlSATrack + + + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + lbL2TrackS + + + 0 + True @@ -4120,123 +3397,6 @@ with profile 8 - - tBsixaxisAccelX - - - System.Windows.Forms.TrackBar, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSixaxis - - - 0 - - - lb6Accel - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSixaxis - - - 1 - - - tBsixaxisGyroX - - - System.Windows.Forms.TrackBar, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSixaxis - - - 2 - - - lb6Gryo - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSixaxis - - - 3 - - - tBsixaxisGyroY - - - System.Windows.Forms.TrackBar, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSixaxis - - - 4 - - - tBsixaxisGyroZ - - - System.Windows.Forms.TrackBar, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSixaxis - - - 5 - - - tBsixaxisAccelY - - - System.Windows.Forms.TrackBar, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSixaxis - - - 6 - - - tBsixaxisAccelZ - - - System.Windows.Forms.TrackBar, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSixaxis - - - 7 - - - 300, 233 - - - 125, 125 - - - 236 - - - pnlSixaxis - - - System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - lbL2TrackS - - - 9 - False @@ -4459,53 +3619,26 @@ with profile 7 - - btnLSTrack + + 300, 233 - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlLSTrack - - - 0 - - - btnLSTrackS - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlLSTrack - - - 1 - - - 5, 88 - - - 2, 2, 2, 2 - - + 125, 125 - - 250 + + 236 - - pnlLSTrack + + pnlSixaxis - + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + lbL2TrackS - - 10 + + 9 False @@ -4570,53 +3703,29 @@ with profile 1 - - btnRSTrackS + + 5, 88 - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlRSTrack - - - 0 - - - btnRSTrack - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlRSTrack - - - 1 - - - 151, 88 - - + 2, 2, 2, 2 - + 125, 125 - - 251 + + 250 - - pnlRSTrack + + pnlLSTrack - + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + lbL2TrackS - - 11 + + 10 False @@ -4681,122 +3790,56 @@ with profile 1 - - bnGyroZN + + 151, 88 - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 2, 2, 2, 2 - - fLPTiltControls + + 125, 125 - - 0 + + 251 - - lbGyroZN + + pnlRSTrack - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - fLPTiltControls + + lbL2TrackS - - 1 + + 11 - - bnGyroZP + + 4, 22 - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 3, 3, 3, 3 - - fLPTiltControls + + 438, 485 - + 2 - - lbGyroZP + + Controller Readings - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + lbL2TrackS - - fLPTiltControls + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 3 + + tCControls - - bnGyroXP - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - fLPTiltControls - - - 4 - - - lbGyroXP - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - fLPTiltControls - - - 5 - - - bnGyroXN - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - fLPTiltControls - - - 6 - - - lbGyroXN - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - fLPTiltControls - - - 7 - - - 4, 43 - - - 271, 167 - - - 254 - - - fLPTiltControls - - - System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBGyro - - - 3 + + 2 NoControl @@ -5014,120 +4057,30 @@ with profile 7 - - tPControls + + 4, 43 - - System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 271, 203 - - tCControls + + 254 - - 0 + + fLPTiltControls - - tPSpecial + + System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + gBGyro - - tCControls - - - 1 - - - Left - - - 0, 0 - - - 446, 511 - - - 253 - - - tCControls - - - System.Windows.Forms.TabControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 4 + + 3 True - - lBControls - - - System.Windows.Forms.ListBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tPControls - - - 0 - - - lbControlTip - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tPControls - - - 2 - - - pnlController - - - System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tPControls - - - 3 - - - 4, 22 - - - 3, 3, 3, 3 - - - 438, 485 - - - 0 - - - Controls - - - tPControls - - - System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tCControls - - - 0 - Top, Bottom, Left @@ -5287,654 +4240,6 @@ with profile Zoom - - pBHoveredButton - - - System.Windows.Forms.PictureBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 0 - - - lbLRS - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 1 - - - lbLLS - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 2 - - - bnRSDown - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 3 - - - lbLTouchUpper - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 4 - - - lbLTouchRight - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 5 - - - bnL3 - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 6 - - - lbLTouchLM - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 7 - - - bnRSUp - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 8 - - - lbLR2 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 9 - - - bnRSRight - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 10 - - - lbLL2 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 11 - - - bnR3 - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 12 - - - lbLR1 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 13 - - - bnRSLeft - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 14 - - - lbLL1 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 15 - - - bnLSLeft - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 16 - - - lbLPS - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 17 - - - bnLSUp - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 18 - - - lbLLeft - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 19 - - - bnLSRight - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 20 - - - lbLright - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 21 - - - bnLSDown - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 22 - - - lbLDown - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 23 - - - bnR2 - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 24 - - - bnUp - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 25 - - - bnDown - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 26 - - - bnTriangle - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 27 - - - bnR1 - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 28 - - - bnSquare - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 29 - - - bnRight - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 30 - - - lbLUp - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 31 - - - bnLeft - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 32 - - - lbLShare - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 33 - - - bnOptions - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 34 - - - bnShare - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 35 - - - lbLOptions - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 36 - - - bnL1 - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 37 - - - bnTouchRight - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 38 - - - bnL2 - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 39 - - - lbLTriangle - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 40 - - - bnTouchLeft - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 41 - - - lbLSquare - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 42 - - - bnTouchMulti - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 43 - - - lbLCircle - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 44 - - - lbLCross - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 45 - - - bnTouchUpper - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 46 - - - btnLightbar - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 47 - - - bnPS - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 48 - - - bnCross - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 49 - - - bnCircle - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 50 - - - lbControlName - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlController - - - 51 - - - 2, 2 - - - 2, 2, 2, 2 - - - 422, 230 - - - 282 - - - pnlController - - - System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tPControls - - - 3 - False @@ -7585,112 +5890,55 @@ with profile 51 - - pnlActions + + 2, 2 - + + 2, 2, 2, 2 + + + 422, 230 + + + 282 + + + pnlController + + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - tPSpecial + + tPControls - - 0 - - - 4, 22 - - - 438, 455 - - + 3 - - Special Actions + + 4, 22 - - tPSpecial + + 3, 3, 3, 3 - + + 438, 485 + + + 0 + + + Controls + + + tPControls + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + tCControls - - 1 - - - lVActions - - - System.Windows.Forms.ListView, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlActions - - - 0 - - - panel2 - - - System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlActions - - - 1 - - - Fill - - - 0, 0 - - - 438, 455 - - - 15 - - - pnlActions - - - System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tPSpecial - - - 0 - - - Fill - - - 0, 66 - - - 438, 389 - - - 13 - - - lVActions - - - System.Windows.Forms.ListView, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlActions - - + 0 @@ -7711,115 +5959,28 @@ with profile 100 - - fLPActionButtons - - - System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - panel2 - - - 0 - - - lbActionsTip - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - panel2 - - - 1 - - - Top - - - 0, 0 - - - 2, 2, 2, 2 - - - 438, 66 - - - 16 - - - panel2 - - - System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlActions - - - 1 - - - btnNewAction - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - fLPActionButtons - - - 0 - - - btnEditAction - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - fLPActionButtons - - - 1 - - - btnRemAction - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - fLPActionButtons - - - 2 - - + Fill - - 0, 28 + + 0, 66 - - 438, 38 + + 438, 419 - - 15 + + 13 - - fLPActionButtons + + lVActions - - System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.ListView, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - panel2 + + pnlActions - + 0 @@ -7903,6 +6064,30 @@ with profile 2 + + Fill + + + 0, 28 + + + 438, 38 + + + 15 + + + fLPActionButtons + + + System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + panel2 + + + 0 + Top @@ -7936,98 +6121,104 @@ with profile 1 - - tPDeadzone + + Top - - System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 0, 0 - - tCSens + + 2, 2, 2, 2 - - 0 + + 438, 66 - - antiDeadzoneTabPage + + 16 - - System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + panel2 - - tCSens + + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + pnlActions + + 1 - - maxZoneTabPage + + Fill - - System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 0, 0 - - tCSens + + 438, 485 - - 2 + + 15 - - tPOutCurve + + pnlActions - - System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - tCSens + + tPSpecial - + + 0 + + + 4, 22 + + + 438, 485 + + 3 - - tPCurve + + Special Actions - + + tPSpecial + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - tCSens + + tCControls - - 4 + + 1 - - tpRotation + + Left - - System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 0, 0 - - tCSens + + 446, 511 - - 5 + + 253 - - 281, 55 + + tCControls - - 272, 78 - - - 234 - - - tCSens - - + System.Windows.Forms.TabControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - fLPSettings + + $this - - 3 + + 4 4, 22 @@ -8056,177 +6247,6 @@ with profile 0 - - nUDSixaxisZAntiDead - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - antiDeadzoneTabPage - - - 0 - - - nUDSixaxisXAntiDead - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - antiDeadzoneTabPage - - - 1 - - - label20 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - antiDeadzoneTabPage - - - 2 - - - label19 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - antiDeadzoneTabPage - - - 3 - - - nUDR2AntiDead - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - antiDeadzoneTabPage - - - 4 - - - label3 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - antiDeadzoneTabPage - - - 5 - - - nUDL2AntiDead - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - antiDeadzoneTabPage - - - 6 - - - label4 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - antiDeadzoneTabPage - - - 7 - - - nUDRSAntiDead - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - antiDeadzoneTabPage - - - 8 - - - label2 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - antiDeadzoneTabPage - - - 9 - - - nUDLSAntiDead - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - antiDeadzoneTabPage - - - 10 - - - label1 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - antiDeadzoneTabPage - - - 11 - - - 4, 22 - - - 3, 3, 3, 3 - - - 264, 52 - - - 2 - - - Anti-Deadzone - - - antiDeadzoneTabPage - - - System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tCSens - - - 1 - 214, 29 @@ -8533,176 +6553,32 @@ with profile 11 - - nUDSixAxisZMaxZone - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - maxZoneTabPage - - - 0 - - - nUDSixAxisXMaxZone - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - maxZoneTabPage - - - 1 - - - label18 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - maxZoneTabPage - - - 2 - - - label17 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - maxZoneTabPage - - - 3 - - - nUDR2Maxzone - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - maxZoneTabPage - - - 4 - - - nUDL2Maxzone - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - maxZoneTabPage - - - 5 - - - label8 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - maxZoneTabPage - - - 6 - - - label7 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - maxZoneTabPage - - - 7 - - - nUDRSMaxZone - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - maxZoneTabPage - - - 8 - - - label6 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - maxZoneTabPage - - - 9 - - - nUDLSMaxZone - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - maxZoneTabPage - - - 10 - - - label5 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - maxZoneTabPage - - - 11 - - + 4, 22 - + 3, 3, 3, 3 - + 264, 52 - - 3 + + 2 - - Max Zone + + Anti-Deadzone - - maxZoneTabPage + + antiDeadzoneTabPage - + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + tCSens - - 2 + + 1 220, 29 @@ -9010,173 +6886,32 @@ with profile 11 - - cBSixaxisZOutputCurve - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tPOutCurve - - - 0 - - - cBSixaxisXOutputCurve - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tPOutCurve - - - 1 - - - label24 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tPOutCurve - - - 2 - - - label23 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tPOutCurve - - - 3 - - - cBR2OutputCurve - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tPOutCurve - - - 4 - - - cBL2OutputCurve - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tPOutCurve - - - 5 - - - label22 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tPOutCurve - - - 6 - - - label21 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tPOutCurve - - - 7 - - - rsOutCurveComboBox - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tPOutCurve - - - 8 - - - lsOutCurveComboBox - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tPOutCurve - - - 9 - - - label10 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tPOutCurve - - - 10 - - - label9 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tPOutCurve - - - 11 - - + 4, 22 - + + 3, 3, 3, 3 + + 264, 52 - - 4 + + 3 - - Output Curve + + Max Zone - - tPOutCurve + + maxZoneTabPage - + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + tCSens - - 3 + + 2 Linear @@ -9562,104 +7297,29 @@ with profile 11 - - nUDLSCurve - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tPCurve - - - 0 - - - nUDRSCurve - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tPCurve - - - 1 - - - lbRSCurve - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tPCurve - - - 2 - - - lbRSCurvePercent - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tPCurve - - - 3 - - - lbLSCurvePercent - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tPCurve - - - 4 - - - lbLSCurve - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tPCurve - - - 5 - - + 4, 22 - - 3, 3, 3, 3 - - + 264, 52 - - 1 + + 4 - - Curve (Input) + + Output Curve - - tPCurve + + tPOutCurve - + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + tCSens - - 4 + + 3 36, 16 @@ -9829,80 +7489,32 @@ with profile 5 - - nUDRSRotation - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tpRotation - - - 0 - - - label14 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tpRotation - - - 1 - - - nUDLSRotation - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tpRotation - - - 2 - - - label13 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tpRotation - - - 3 - - + 4, 22 - + 3, 3, 3, 3 - + 264, 52 - - 5 + + 1 - - Rotation + + Curve (Input) - - tpRotation + + tPCurve - + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + tCSens - - 5 + + 4 160, 21 @@ -10006,122 +7618,56 @@ with profile 3 - - True + + 4, 22 - - gBGyro + + 3, 3, 3, 3 - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 264, 52 - + + 5 + + + Rotation + + + tpRotation + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tCSens + + + 5 + + + 281, 55 + + + 272, 78 + + + 234 + + + tCSens + + + System.Windows.Forms.TabControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + fLPSettings - - 1 - - - gBSensitivity - - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - fLPSettings - - - 4 - - - Fill - - - TopDown - - - 446, 0 - - - 2, 2, 2, 2 - - - 565, 511 - - - 254 - - - fLPSettings - - - System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - + 3 - - rBSAControls - - - System.Windows.Forms.RadioButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBGyro - - - 0 - - - rBSAMouse - - - System.Windows.Forms.RadioButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBGyro - - - 1 - - - pnlSAMouse - - - System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBGyro - - - 2 - - - 3, 242 - - - 272, 224 - - - 248 - - - Gyro - - - gBGyro - - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - fLPSettings - - - 1 + + True True @@ -10189,287 +7735,41 @@ with profile 1 - - label27 + + True - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 9, 187 - + + Yes + + + 59, 17 + + + 276 + + + Toggle + + + toggleGyroMCb + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + pnlSAMouse - + 0 - - gyroMouseDzNUD - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSAMouse - - - 1 - - - label26 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSAMouse - - - 2 - - - triggerCondAndCombo - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSAMouse - - - 3 - - - cBGyroMouseXAxis - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSAMouse - - - 4 - - - label16 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSAMouse - - - 5 - - - lbGyroSmooth - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSAMouse - - - 6 - - - cBGyroSmooth - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSAMouse - - - 7 - - - lbSmoothWeight - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSAMouse - - - 8 - - - nUDGyroSmoothWeight - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSAMouse - - - 9 - - - label12 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSAMouse - - - 10 - - - nUDGyroMouseVertScale - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSAMouse - - - 11 - - - label11 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSAMouse - - - 12 - - - gyroTriggerBehavior - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSAMouse - - - 13 - - - cBGyroInvertY - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSAMouse - - - 14 - - - cBGyroInvertX - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSAMouse - - - 15 - - - lbGyroInvert - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSAMouse - - - 16 - - - lbGyroTriggers - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSAMouse - - - 17 - - - btnGyroTriggers - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSAMouse - - - 18 - - - nUDGyroSensitivity - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSAMouse - - - 19 - - - lbGyroSens - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - pnlSAMouse - - - 20 - - - 6, 39 - - - 2, 2, 2, 2 - - - 263, 181 - - - 259 - - - pnlSAMouse - - - System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBGyro - - - 2 - True - 6, 158 + 11, 166 56, 13 @@ -10490,10 +7790,10 @@ with profile pnlSAMouse - 0 + 1 - 94, 156 + 78, 166 43, 20 @@ -10511,7 +7811,7 @@ with profile pnlSAMouse - 1 + 2 True @@ -10541,7 +7841,7 @@ with profile pnlSAMouse - 2 + 3 And @@ -10568,7 +7868,7 @@ with profile pnlSAMouse - 3 + 4 Yaw @@ -10595,7 +7895,7 @@ with profile pnlSAMouse - 4 + 5 True @@ -10625,7 +7925,7 @@ with profile pnlSAMouse - 5 + 6 True @@ -10655,7 +7955,7 @@ with profile pnlSAMouse - 6 + 7 True @@ -10685,7 +7985,7 @@ with profile pnlSAMouse - 7 + 8 True @@ -10715,7 +8015,7 @@ with profile pnlSAMouse - 8 + 9 False @@ -10739,7 +8039,7 @@ with profile pnlSAMouse - 9 + 10 True @@ -10769,7 +8069,7 @@ with profile pnlSAMouse - 10 + 11 95, 89 @@ -10790,7 +8090,7 @@ with profile pnlSAMouse - 11 + 12 True @@ -10820,7 +8120,7 @@ with profile pnlSAMouse - 12 + 13 True @@ -10853,7 +8153,7 @@ with profile pnlSAMouse - 13 + 14 True @@ -10886,7 +8186,7 @@ with profile pnlSAMouse - 14 + 15 True @@ -10919,7 +8219,7 @@ with profile pnlSAMouse - 15 + 16 True @@ -10952,7 +8252,7 @@ with profile pnlSAMouse - 16 + 17 True @@ -10985,7 +8285,7 @@ with profile pnlSAMouse - 17 + 18 NoControl @@ -11015,7 +8315,7 @@ with profile pnlSAMouse - 18 + 19 96, 62 @@ -11036,7 +8336,7 @@ with profile pnlSAMouse - 19 + 20 True @@ -11069,175 +8369,55 @@ with profile pnlSAMouse - 20 + 21 - - lbL2S + + 6, 39 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 2, 2, 2, 2 - - gBSensitivity + + 263, 207 - - 0 + + 259 - - nUDL2S + + pnlSAMouse - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - gBSensitivity + + gBGyro - - 1 - - - nUDLSS - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBSensitivity - - + 2 - - lbSixaxisXS + + 3, 242 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 272, 257 - - gBSensitivity + + 248 - - 3 + + Gyro - - nUDR2S + + gBGyro - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBSensitivity - - - 4 - - - lbSixaxisZS - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBSensitivity - - - 5 - - - nUDRSS - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBSensitivity - - - 6 - - - lbR2LS - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBSensitivity - - - 7 - - - nUDSXS - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBSensitivity - - - 8 - - - lbRSS - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBSensitivity - - - 9 - - - lbLSS - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBSensitivity - - - 10 - - - nUDSZS - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - gBSensitivity - - - 11 - - - 281, 139 - - - 272, 76 - - - 257 - - - Sensitivity - - - gBSensitivity - - + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + fLPSettings - - 4 + + 1 True @@ -11557,18 +8737,63 @@ with profile 11 + + 281, 139 + + + 272, 76 + + + 257 + + + Sensitivity + + + gBSensitivity + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + fLPSettings + + + 4 + + + Fill + + + TopDown + + + 446, 0 + + + 2, 2, 2, 2 + + + 565, 511 + + + 254 + + + fLPSettings + + + System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + 482, 17 - - 195, 444 - - - cMGyroTriggers - - - System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - 194, 22 @@ -11689,18 +8914,18 @@ with profile Always on + + 195, 444 + + + cMGyroTriggers + + + System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + 144, 63 - - 195, 422 - - - cMTouchDisableInvert - - - System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - 194, 22 @@ -11815,6 +9040,15 @@ with profile PS + + 195, 422 + + + cMTouchDisableInvert + + + System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + 647, 17 From 255fc8f8fc9ea3a6920e13751c68197d5e4f7f27 Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Thu, 7 Feb 2019 11:52:28 -0600 Subject: [PATCH 17/66] Minor fix for update check when offline Related to issue #568 --- DS4Windows/DS4Forms/DS4Form.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DS4Windows/DS4Forms/DS4Form.cs b/DS4Windows/DS4Forms/DS4Form.cs index d89b20c..cd4f967 100644 --- a/DS4Windows/DS4Forms/DS4Form.cs +++ b/DS4Windows/DS4Forms/DS4Form.cs @@ -786,7 +786,7 @@ namespace DS4Windows FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location); string version = fvi.FileVersion; string newversion = File.ReadAllText(appdatapath + "\\version.txt").Trim(); - if (version.Replace(',', '.').CompareTo(newversion) != 0) + if (!string.IsNullOrWhiteSpace(newversion) && version.Replace(',', '.').CompareTo(newversion) != 0) { if ((DialogResult)this.Invoke(new Func(() => { return MessageBox.Show(Properties.Resources.DownloadVersion.Replace("*number*", newversion), @@ -2097,7 +2097,7 @@ Properties.Resources.DS4Update, MessageBoxButtons.YesNo, MessageBoxIcon.Question FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location); string version2 = fvi.FileVersion; string newversion2 = File.ReadAllText(appdatapath + "\\version.txt").Trim(); - if (version2.Replace(',', '.').CompareTo(newversion2) != 0) + if (!string.IsNullOrWhiteSpace(newversion2) && version2.Replace(',', '.').CompareTo(newversion2) != 0) { if ((DialogResult)this.Invoke(new Func(() => { From 4d989bb5f0e41459a5f00c1b9645ecfcdf8c25da Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Thu, 7 Feb 2019 12:08:12 -0600 Subject: [PATCH 18/66] Added xrossb to contributors file --- contributors.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/contributors.txt b/contributors.txt index ad9e1d2..0514e44 100644 --- a/contributors.txt +++ b/contributors.txt @@ -4,4 +4,5 @@ jdfeng justalemon Rajko Stojadinovic (rajkosto) Yuki-nyan +xrossb From 3dd88e481c678e2ea4a1acca141e6a7ae3b5075a Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Thu, 7 Feb 2019 16:40:24 -0600 Subject: [PATCH 19/66] Fixed issue with xinput unplug routine on device removal Related to issue #554 --- DS4Windows/DS4Control/ScpUtil.cs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/DS4Windows/DS4Control/ScpUtil.cs b/DS4Windows/DS4Control/ScpUtil.cs index 3716c4a..a5a4073 100644 --- a/DS4Windows/DS4Control/ScpUtil.cs +++ b/DS4Windows/DS4Control/ScpUtil.cs @@ -2602,7 +2602,6 @@ namespace DS4Windows catch { dinputOnly[device] = false; missingSetting = true; } bool oldUseDInputOnly = Global.useDInputOnly[device]; - Global.useDInputOnly[device] = dinputOnly[device]; // Only change xinput devices under certain conditions. Avoid // performing this upon program startup before loading devices. @@ -2618,20 +2617,14 @@ namespace DS4Windows { if (dinputOnly[device] == true) { - Global.useDInputOnly[device] = true; xinputPlug = false; xinputStatus = true; } else if (synced && isAlive) { - Global.useDInputOnly[device] = false; xinputPlug = true; xinputStatus = true; } - else if (!synced) - { - Global.useDInputOnly[device] = true; - } } } } @@ -2995,12 +2988,12 @@ namespace DS4Windows int xinputIndex = control.x360Bus.FirstController + device; if (xinputResult) { - dinputOnly[device] = false; + Global.useDInputOnly[device] = false; AppLogger.LogToGui("X360 Controller # " + xinputIndex + " connected", false); } else { - dinputOnly[device] = true; + Global.useDInputOnly[device] = true; AppLogger.LogToGui("X360 Controller # " + xinputIndex + " failed. Using DInput only mode", true); } } @@ -3010,11 +3003,12 @@ namespace DS4Windows int xinputIndex = control.x360Bus.FirstController + device; if (xinputResult) { - dinputOnly[device] = true; + Global.useDInputOnly[device] = true; AppLogger.LogToGui("X360 Controller # " + xinputIndex + " unplugged", false); } else { + Global.useDInputOnly[device] = false; AppLogger.LogToGui("X360 Controller # " + xinputIndex + " failed to unplug", true); } } From 8c6cfa4c137ae921e775b8433c4988280c2c6f25 Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Thu, 7 Feb 2019 21:00:36 -0600 Subject: [PATCH 20/66] Fixed another action getter --- DS4Windows/DS4Control/ScpUtil.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DS4Windows/DS4Control/ScpUtil.cs b/DS4Windows/DS4Control/ScpUtil.cs index a5a4073..4e2ee7a 100644 --- a/DS4Windows/DS4Control/ScpUtil.cs +++ b/DS4Windows/DS4Control/ScpUtil.cs @@ -3617,7 +3617,7 @@ namespace DS4Windows DS4ControlSettings dcs = ds4settings[deviceNum][index]; if (shift) { - return dcs.shiftTrigger; + return dcs.shiftAction; } else { From e64c7f0455ab3f60a51bccae90f376c0603b7ee5 Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Thu, 7 Feb 2019 22:56:07 -0600 Subject: [PATCH 21/66] Fixed double tap interval issue with Multi-Action Button special action Related to issue #556 --- DS4Windows/DS4Control/Mapping.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DS4Windows/DS4Control/Mapping.cs b/DS4Windows/DS4Control/Mapping.cs index 7b4f893..3db3eef 100644 --- a/DS4Windows/DS4Control/Mapping.cs +++ b/DS4Windows/DS4Control/Mapping.cs @@ -1950,7 +1950,7 @@ namespace DS4Windows { // pressed down action.pastTime = DateTime.UtcNow; - if (action.pastTime <= (action.firstTap + TimeSpan.FromMilliseconds(100))) + if (action.pastTime <= (action.firstTap + TimeSpan.FromMilliseconds(150))) { action.tappedOnce = tappedOnce = false; action.secondtouchbegin = secondtouchbegin = true; From 925d2584c0874d92ab1d7f474d37b8601444f61f Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Fri, 8 Feb 2019 08:14:01 -0600 Subject: [PATCH 22/66] Updated newest.txt file --- DS4Windows/newest.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DS4Windows/newest.txt b/DS4Windows/newest.txt index d8c5e72..15d45d4 100644 --- a/DS4Windows/newest.txt +++ b/DS4Windows/newest.txt @@ -1 +1 @@ -1.6.8 +1.6.9 From 1f0c144d42a144e1008fea203354ed1a46ad7c7d Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Fri, 8 Feb 2019 08:14:14 -0600 Subject: [PATCH 23/66] Version 1.6.9 --- DS4Windows/Properties/AssemblyInfo.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DS4Windows/Properties/AssemblyInfo.cs b/DS4Windows/Properties/AssemblyInfo.cs index 1497a9d..15b3909 100644 --- a/DS4Windows/Properties/AssemblyInfo.cs +++ b/DS4Windows/Properties/AssemblyInfo.cs @@ -33,7 +33,7 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.6.8")] -[assembly: AssemblyFileVersion("1.6.8")] +[assembly: AssemblyVersion("1.6.9")] +[assembly: AssemblyFileVersion("1.6.9")] [assembly: NeutralResourcesLanguage("en")] From 7818e88b72cfd94de053b28e5bf3d621918e794f Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Fri, 8 Feb 2019 11:26:42 -0600 Subject: [PATCH 24/66] Added dispose call when closing Options form --- DS4Windows/DS4Forms/DS4Form.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/DS4Windows/DS4Forms/DS4Form.cs b/DS4Windows/DS4Forms/DS4Form.cs index cd4f967..ccdd743 100644 --- a/DS4Windows/DS4Forms/DS4Form.cs +++ b/DS4Windows/DS4Forms/DS4Form.cs @@ -1612,6 +1612,7 @@ Properties.Resources.DS4Update, MessageBoxButtons.YesNo, MessageBoxIcon.Question opt.Dock = DockStyle.None; tabProfiles.Controls.Remove(opt); + opt.Dispose(); optPop = false; opt = null; lBProfiles.Visible = true; From 34e3db6cea70d9e909efd80289aaac689962117a Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Fri, 8 Feb 2019 16:56:38 -0600 Subject: [PATCH 25/66] Undo last commit. Extra dispose call is not necessary --- DS4Windows/DS4Forms/DS4Form.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/DS4Windows/DS4Forms/DS4Form.cs b/DS4Windows/DS4Forms/DS4Form.cs index ccdd743..cd4f967 100644 --- a/DS4Windows/DS4Forms/DS4Form.cs +++ b/DS4Windows/DS4Forms/DS4Form.cs @@ -1612,7 +1612,6 @@ Properties.Resources.DS4Update, MessageBoxButtons.YesNo, MessageBoxIcon.Question opt.Dock = DockStyle.None; tabProfiles.Controls.Remove(opt); - opt.Dispose(); optPop = false; opt = null; lBProfiles.Visible = true; From 49c7ee35cf6af3e36c7e13e9f4dc892ce03b5ee0 Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Fri, 8 Feb 2019 21:04:08 -0600 Subject: [PATCH 26/66] Make remapping to xinput actions a two pass process again Related to issue #570 --- DS4Windows/DS4Control/Mapping.cs | 85 +++++++++++++++++++------------- 1 file changed, 51 insertions(+), 34 deletions(-) diff --git a/DS4Windows/DS4Control/Mapping.cs b/DS4Windows/DS4Control/Mapping.cs index 3db3eef..fa3eae1 100644 --- a/DS4Windows/DS4Control/Mapping.cs +++ b/DS4Windows/DS4Control/Mapping.cs @@ -58,6 +58,23 @@ namespace DS4Windows public bool[] dev = new bool[4]; } + struct ControlToXInput + { + public DS4Controls ds4input; + public DS4Controls xoutput; + + public ControlToXInput(DS4Controls input, DS4Controls output) + { + ds4input = input; xoutput = output; + } + } + + static Queue[] customMapQueue = new Queue[4] + { + new Queue(), new Queue(), + new Queue(), new Queue() + }; + public static SyntheticState globalState = new SyntheticState(); public static SyntheticState[] deviceState = new SyntheticState[4] { new SyntheticState(), new SyntheticState(), new SyntheticState(), @@ -1159,10 +1176,6 @@ namespace DS4Windows Mouse tp, ControlService ctrl) { /* TODO: This method is slow sauce. Find ways to speed up action execution */ - MappedState.LX = 128; - MappedState.LY = 128; - MappedState.RX = 128; - MappedState.RY = 128; double tempMouseDeltaX = 0.0; double tempMouseDeltaY = 0.0; int mouseDeltaX = 0; @@ -1181,7 +1194,7 @@ namespace DS4Windows MapCustomAction(device, cState, MappedState, eState, tp, ctrl, fieldMapping, outputfieldMapping); if (ctrl.DS4Controllers[device] == null) return; - cState.CopyTo(MappedState); + //cState.CopyTo(MappedState); //Dictionary tempControlDict = new Dictionary(); //MultiValueDict tempControlDict = new MultiValueDict(); @@ -1345,39 +1358,12 @@ namespace DS4Windows xboxControl = getX360ControlsByName(action.ToString()); } - if (xboxControl >= X360Controls.LXNeg && xboxControl <= X360Controls.RYPos) + if (xboxControl >= X360Controls.LXNeg && xboxControl <= X360Controls.Start) { DS4Controls tempDS4Control = reverseX360ButtonMapping[(int)xboxControl]; - int controlNum = (int)dcs.control; - int tempOutControl = (int)tempDS4Control; - DS4StateFieldMapping.ControlType controlType = DS4StateFieldMapping.mappedType[tempOutControl]; - bool alt = controlType == DS4StateFieldMapping.ControlType.AxisDir && tempOutControl % 2 == 0 ? true : false; - byte axisMapping = getXYAxisMapping2(device, dcs.control, cState, eState, tp, fieldMapping, alt); - if (axisMapping != 128) - { - int controlRelation = tempOutControl % 2 == 0 ? tempOutControl - 1 : tempOutControl + 1; - outputfieldMapping.axisdirs[tempOutControl] = axisMapping; - outputfieldMapping.axisdirs[controlRelation] = axisMapping; - } - + customMapQueue[device].Enqueue(new ControlToXInput(dcs.control, tempDS4Control)); //tempControlDict.Add(dcs.control, tempDS4Control); } - else if (xboxControl >= X360Controls.LB && xboxControl <= X360Controls.Start) - { - DS4Controls tempDS4Control = reverseX360ButtonMapping[(int)xboxControl]; - int controlNum = (int)dcs.control; - if (xboxControl == X360Controls.LT || xboxControl == X360Controls.RT) - { - byte axisMapping = getByteMapping2(device, dcs.control, cState, eState, tp, fieldMapping); - if (axisMapping != 0) - outputfieldMapping.triggers[(int)tempDS4Control] = axisMapping; - } - else - { - bool value = getBoolMapping2(device, dcs.control, cState, eState, tp, fieldMapping); - outputfieldMapping.buttons[(int)tempDS4Control] = value; - } - } else if (xboxControl >= X360Controls.LeftMouse && xboxControl <= X360Controls.WDOWN) { switch (xboxControl) @@ -1522,6 +1508,37 @@ namespace DS4Windows } } + Queue tempControl = customMapQueue[device]; + for (int i = 0, len = tempControl.Count; i < len; i++) + //while(tempControl.Any()) + { + ControlToXInput tempMap = tempControl.Dequeue(); + int controlNum = (int)tempMap.ds4input; + int tempOutControl = (int)tempMap.xoutput; + if (tempMap.xoutput >= DS4Controls.LXNeg && tempMap.xoutput <= DS4Controls.RYPos) + { + DS4StateFieldMapping.ControlType controlType = DS4StateFieldMapping.mappedType[tempOutControl]; + bool alt = controlType == DS4StateFieldMapping.ControlType.AxisDir && tempOutControl % 2 == 0 ? true : false; + byte axisMapping = getXYAxisMapping2(device, tempMap.ds4input, cState, eState, tp, fieldMapping, alt); + int controlRelation = tempOutControl % 2 == 0 ? tempOutControl - 1 : tempOutControl + 1; + outputfieldMapping.axisdirs[tempOutControl] = axisMapping; + outputfieldMapping.axisdirs[controlRelation] = axisMapping; + } + else + { + if (tempMap.xoutput == DS4Controls.L2 || tempMap.xoutput == DS4Controls.R2) + { + byte axisMapping = getByteMapping2(device, tempMap.ds4input, cState, eState, tp, fieldMapping); + outputfieldMapping.triggers[tempOutControl] = axisMapping; + } + else + { + bool value = getBoolMapping2(device, tempMap.ds4input, cState, eState, tp, fieldMapping); + outputfieldMapping.buttons[tempOutControl] = value; + } + } + } + outputfieldMapping.populateState(MappedState); if (macroCount > 0) From fc40e0084627fac8d4dd1571b6e7bbf01cb03040 Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Sat, 9 Feb 2019 11:06:31 -0600 Subject: [PATCH 27/66] Only take active binding into account for multiple binds. Fixes ATS profile. --- DS4Windows/DS4Control/Mapping.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/DS4Windows/DS4Control/Mapping.cs b/DS4Windows/DS4Control/Mapping.cs index fa3eae1..00a86ff 100644 --- a/DS4Windows/DS4Control/Mapping.cs +++ b/DS4Windows/DS4Control/Mapping.cs @@ -1520,21 +1520,26 @@ namespace DS4Windows DS4StateFieldMapping.ControlType controlType = DS4StateFieldMapping.mappedType[tempOutControl]; bool alt = controlType == DS4StateFieldMapping.ControlType.AxisDir && tempOutControl % 2 == 0 ? true : false; byte axisMapping = getXYAxisMapping2(device, tempMap.ds4input, cState, eState, tp, fieldMapping, alt); - int controlRelation = tempOutControl % 2 == 0 ? tempOutControl - 1 : tempOutControl + 1; - outputfieldMapping.axisdirs[tempOutControl] = axisMapping; - outputfieldMapping.axisdirs[controlRelation] = axisMapping; + if (axisMapping != 128) + { + int controlRelation = tempOutControl % 2 == 0 ? tempOutControl - 1 : tempOutControl + 1; + outputfieldMapping.axisdirs[tempOutControl] = axisMapping; + outputfieldMapping.axisdirs[controlRelation] = axisMapping; + } } else { if (tempMap.xoutput == DS4Controls.L2 || tempMap.xoutput == DS4Controls.R2) { byte axisMapping = getByteMapping2(device, tempMap.ds4input, cState, eState, tp, fieldMapping); - outputfieldMapping.triggers[tempOutControl] = axisMapping; + if (axisMapping != 0) + outputfieldMapping.triggers[tempOutControl] = axisMapping; } else { bool value = getBoolMapping2(device, tempMap.ds4input, cState, eState, tp, fieldMapping); - outputfieldMapping.buttons[tempOutControl] = value; + if (value) + outputfieldMapping.buttons[tempOutControl] = value; } } } From 7631080d87362b424e163e49ae8eea45cb8f5748 Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Sat, 9 Feb 2019 11:30:06 -0600 Subject: [PATCH 28/66] Add const variables to skip type casting --- DS4Windows/DS4Control/Mapping.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/DS4Windows/DS4Control/Mapping.cs b/DS4Windows/DS4Control/Mapping.cs index 00a86ff..29a0bcd 100644 --- a/DS4Windows/DS4Control/Mapping.cs +++ b/DS4Windows/DS4Control/Mapping.cs @@ -1517,10 +1517,11 @@ namespace DS4Windows int tempOutControl = (int)tempMap.xoutput; if (tempMap.xoutput >= DS4Controls.LXNeg && tempMap.xoutput <= DS4Controls.RYPos) { + const byte axisDead = 128; DS4StateFieldMapping.ControlType controlType = DS4StateFieldMapping.mappedType[tempOutControl]; bool alt = controlType == DS4StateFieldMapping.ControlType.AxisDir && tempOutControl % 2 == 0 ? true : false; byte axisMapping = getXYAxisMapping2(device, tempMap.ds4input, cState, eState, tp, fieldMapping, alt); - if (axisMapping != 128) + if (axisMapping != axisDead) { int controlRelation = tempOutControl % 2 == 0 ? tempOutControl - 1 : tempOutControl + 1; outputfieldMapping.axisdirs[tempOutControl] = axisMapping; @@ -1531,8 +1532,9 @@ namespace DS4Windows { if (tempMap.xoutput == DS4Controls.L2 || tempMap.xoutput == DS4Controls.R2) { + const byte axisZero = 0; byte axisMapping = getByteMapping2(device, tempMap.ds4input, cState, eState, tp, fieldMapping); - if (axisMapping != 0) + if (axisMapping != axisZero) outputfieldMapping.triggers[tempOutControl] = axisMapping; } else From 43b9f9e0c4af0b86573b9627c173fd0f911da4d8 Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Sat, 9 Feb 2019 11:36:39 -0600 Subject: [PATCH 29/66] Updated newest text file --- DS4Windows/newest.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DS4Windows/newest.txt b/DS4Windows/newest.txt index 15d45d4..1df3b82 100644 --- a/DS4Windows/newest.txt +++ b/DS4Windows/newest.txt @@ -1 +1 @@ -1.6.9 +1.6.10 From 244bdae7f336704c87c7d9e9e9f2e26ea50a1b1f Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Sat, 9 Feb 2019 11:36:56 -0600 Subject: [PATCH 30/66] Version 1.6.10 --- DS4Windows/Properties/AssemblyInfo.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DS4Windows/Properties/AssemblyInfo.cs b/DS4Windows/Properties/AssemblyInfo.cs index 15b3909..9608b42 100644 --- a/DS4Windows/Properties/AssemblyInfo.cs +++ b/DS4Windows/Properties/AssemblyInfo.cs @@ -33,7 +33,7 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.6.9")] -[assembly: AssemblyFileVersion("1.6.9")] +[assembly: AssemblyVersion("1.6.10")] +[assembly: AssemblyFileVersion("1.6.10")] [assembly: NeutralResourcesLanguage("en")] From 42b75c717a8e44a7847f235340dea76678424ba0 Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Sat, 9 Feb 2019 21:33:58 -0600 Subject: [PATCH 31/66] Added unchecked blocks for populating field mapping arrays Seems to help a lot --- DS4Windows/DS4Control/DS4StateFieldMapping.cs | 143 +++++++++--------- 1 file changed, 75 insertions(+), 68 deletions(-) diff --git a/DS4Windows/DS4Control/DS4StateFieldMapping.cs b/DS4Windows/DS4Control/DS4StateFieldMapping.cs index 2eb3daa..d99e472 100644 --- a/DS4Windows/DS4Control/DS4StateFieldMapping.cs +++ b/DS4Windows/DS4Control/DS4StateFieldMapping.cs @@ -63,93 +63,100 @@ namespace DS4Windows public void populateFieldMapping(DS4State cState, DS4StateExposed exposeState, Mouse tp, bool priorMouse = false) { - axisdirs[(int)DS4Controls.LXNeg] = cState.LX; - axisdirs[(int)DS4Controls.LXPos] = cState.LX; - axisdirs[(int)DS4Controls.LYNeg] = cState.LY; - axisdirs[(int)DS4Controls.LYPos] = cState.LY; + unchecked + { + axisdirs[(int)DS4Controls.LXNeg] = cState.LX; + axisdirs[(int)DS4Controls.LXPos] = cState.LX; + axisdirs[(int)DS4Controls.LYNeg] = cState.LY; + axisdirs[(int)DS4Controls.LYPos] = cState.LY; - axisdirs[(int)DS4Controls.RXNeg] = cState.RX; - axisdirs[(int)DS4Controls.RXPos] = cState.RX; - axisdirs[(int)DS4Controls.RYNeg] = cState.RY; - axisdirs[(int)DS4Controls.RYPos] = cState.RY; + axisdirs[(int)DS4Controls.RXNeg] = cState.RX; + axisdirs[(int)DS4Controls.RXPos] = cState.RX; + axisdirs[(int)DS4Controls.RYNeg] = cState.RY; + axisdirs[(int)DS4Controls.RYPos] = cState.RY; - triggers[(int)DS4Controls.L2] = cState.L2; - triggers[(int)DS4Controls.R2] = cState.R2; + triggers[(int)DS4Controls.L2] = cState.L2; + triggers[(int)DS4Controls.R2] = cState.R2; - buttons[(int)DS4Controls.L1] = cState.L1; - buttons[(int)DS4Controls.L3] = cState.L3; - buttons[(int)DS4Controls.R1] = cState.R1; - buttons[(int)DS4Controls.R3] = cState.R3; + buttons[(int)DS4Controls.L1] = cState.L1; + buttons[(int)DS4Controls.L3] = cState.L3; + buttons[(int)DS4Controls.R1] = cState.R1; + buttons[(int)DS4Controls.R3] = cState.R3; - buttons[(int)DS4Controls.Cross] = cState.Cross; - buttons[(int)DS4Controls.Triangle] = cState.Triangle; - buttons[(int)DS4Controls.Circle] = cState.Circle; - buttons[(int)DS4Controls.Square] = cState.Square; - buttons[(int)DS4Controls.PS] = cState.PS; - buttons[(int)DS4Controls.Options] = cState.Options; - buttons[(int)DS4Controls.Share] = cState.Share; + buttons[(int)DS4Controls.Cross] = cState.Cross; + buttons[(int)DS4Controls.Triangle] = cState.Triangle; + buttons[(int)DS4Controls.Circle] = cState.Circle; + buttons[(int)DS4Controls.Square] = cState.Square; + buttons[(int)DS4Controls.PS] = cState.PS; + buttons[(int)DS4Controls.Options] = cState.Options; + buttons[(int)DS4Controls.Share] = cState.Share; - buttons[(int)DS4Controls.DpadUp] = cState.DpadUp; - buttons[(int)DS4Controls.DpadRight] = cState.DpadRight; - buttons[(int)DS4Controls.DpadDown] = cState.DpadDown; - buttons[(int)DS4Controls.DpadLeft] = cState.DpadLeft; + buttons[(int)DS4Controls.DpadUp] = cState.DpadUp; + buttons[(int)DS4Controls.DpadRight] = cState.DpadRight; + buttons[(int)DS4Controls.DpadDown] = cState.DpadDown; + buttons[(int)DS4Controls.DpadLeft] = cState.DpadLeft; - buttons[(int)DS4Controls.TouchLeft] = tp != null ? (!priorMouse ? tp.leftDown : tp.priorLeftDown) : false; - buttons[(int)DS4Controls.TouchRight] = tp != null ? (!priorMouse ? tp.rightDown : tp.priorRightDown) : false; - buttons[(int)DS4Controls.TouchUpper] = tp != null ? (!priorMouse ? tp.upperDown : tp.priorUpperDown) : false; - buttons[(int)DS4Controls.TouchMulti] = tp != null ? (!priorMouse ? tp.multiDown : tp.priorMultiDown) : false; + buttons[(int)DS4Controls.TouchLeft] = tp != null ? (!priorMouse ? tp.leftDown : tp.priorLeftDown) : false; + buttons[(int)DS4Controls.TouchRight] = tp != null ? (!priorMouse ? tp.rightDown : tp.priorRightDown) : false; + buttons[(int)DS4Controls.TouchUpper] = tp != null ? (!priorMouse ? tp.upperDown : tp.priorUpperDown) : false; + buttons[(int)DS4Controls.TouchMulti] = tp != null ? (!priorMouse ? tp.multiDown : tp.priorMultiDown) : false; - int sixAxisX = -exposeState.getOutputAccelX(); - gryodirs[(int)DS4Controls.GyroXPos] = sixAxisX > 0 ? sixAxisX : 0; - gryodirs[(int)DS4Controls.GyroXNeg] = sixAxisX < 0 ? sixAxisX : 0; + int sixAxisX = -exposeState.getOutputAccelX(); + gryodirs[(int)DS4Controls.GyroXPos] = sixAxisX > 0 ? sixAxisX : 0; + gryodirs[(int)DS4Controls.GyroXNeg] = sixAxisX < 0 ? sixAxisX : 0; - int sixAxisZ = exposeState.getOutputAccelZ(); - gryodirs[(int)DS4Controls.GyroZPos] = sixAxisZ > 0 ? sixAxisZ : 0; - gryodirs[(int)DS4Controls.GyroZNeg] = sixAxisZ < 0 ? sixAxisZ : 0; + int sixAxisZ = exposeState.getOutputAccelZ(); + gryodirs[(int)DS4Controls.GyroZPos] = sixAxisZ > 0 ? sixAxisZ : 0; + gryodirs[(int)DS4Controls.GyroZNeg] = sixAxisZ < 0 ? sixAxisZ : 0; - swipedirs[(int)DS4Controls.SwipeLeft] = tp != null ? (!priorMouse ? tp.swipeLeftB : tp.priorSwipeLeftB) : (byte)0; - swipedirs[(int)DS4Controls.SwipeRight] = tp != null ? (!priorMouse ? tp.swipeRightB : tp.priorSwipeRightB) : (byte)0; - swipedirs[(int)DS4Controls.SwipeUp] = tp != null ? (!priorMouse ? tp.swipeUpB : tp.priorSwipeUpB) : (byte)0; - swipedirs[(int)DS4Controls.SwipeDown] = tp != null ? (!priorMouse ? tp.swipeDownB : tp.priorSwipeDownB) : (byte)0; + swipedirs[(int)DS4Controls.SwipeLeft] = tp != null ? (!priorMouse ? tp.swipeLeftB : tp.priorSwipeLeftB) : (byte)0; + swipedirs[(int)DS4Controls.SwipeRight] = tp != null ? (!priorMouse ? tp.swipeRightB : tp.priorSwipeRightB) : (byte)0; + swipedirs[(int)DS4Controls.SwipeUp] = tp != null ? (!priorMouse ? tp.swipeUpB : tp.priorSwipeUpB) : (byte)0; + swipedirs[(int)DS4Controls.SwipeDown] = tp != null ? (!priorMouse ? tp.swipeDownB : tp.priorSwipeDownB) : (byte)0; - swipedirbools[(int)DS4Controls.SwipeLeft] = tp != null ? (!priorMouse ? tp.swipeLeft : tp.priorSwipeLeft) : false; - swipedirbools[(int)DS4Controls.SwipeRight] = tp != null ? (!priorMouse ? tp.swipeRight : tp.priorSwipeRight) : false; - swipedirbools[(int)DS4Controls.SwipeUp] = tp != null ? (!priorMouse ? tp.swipeUp : tp.priorSwipeUp) : false; - swipedirbools[(int)DS4Controls.SwipeDown] = tp != null ? (!priorMouse ? tp.swipeDown : tp.priorSwipeDown) : false; + swipedirbools[(int)DS4Controls.SwipeLeft] = tp != null ? (!priorMouse ? tp.swipeLeft : tp.priorSwipeLeft) : false; + swipedirbools[(int)DS4Controls.SwipeRight] = tp != null ? (!priorMouse ? tp.swipeRight : tp.priorSwipeRight) : false; + swipedirbools[(int)DS4Controls.SwipeUp] = tp != null ? (!priorMouse ? tp.swipeUp : tp.priorSwipeUp) : false; + swipedirbools[(int)DS4Controls.SwipeDown] = tp != null ? (!priorMouse ? tp.swipeDown : tp.priorSwipeDown) : false; + } + } public void populateState(DS4State state) { - state.LX = axisdirs[(int)DS4Controls.LXNeg]; - state.LX = axisdirs[(int)DS4Controls.LXPos]; - state.LY = axisdirs[(int)DS4Controls.LYNeg]; - state.LY = axisdirs[(int)DS4Controls.LYPos]; + unchecked + { + state.LX = axisdirs[(int)DS4Controls.LXNeg]; + state.LX = axisdirs[(int)DS4Controls.LXPos]; + state.LY = axisdirs[(int)DS4Controls.LYNeg]; + state.LY = axisdirs[(int)DS4Controls.LYPos]; - state.RX = axisdirs[(int)DS4Controls.RXNeg]; - state.RX = axisdirs[(int)DS4Controls.RXPos]; - state.RY = axisdirs[(int)DS4Controls.RYNeg]; - state.RY = axisdirs[(int)DS4Controls.RYPos]; + state.RX = axisdirs[(int)DS4Controls.RXNeg]; + state.RX = axisdirs[(int)DS4Controls.RXPos]; + state.RY = axisdirs[(int)DS4Controls.RYNeg]; + state.RY = axisdirs[(int)DS4Controls.RYPos]; - state.L2 = triggers[(int)DS4Controls.L2]; - state.R2 = triggers[(int)DS4Controls.R2]; + state.L2 = triggers[(int)DS4Controls.L2]; + state.R2 = triggers[(int)DS4Controls.R2]; - state.L1 = buttons[(int)DS4Controls.L1]; - state.L3 = buttons[(int)DS4Controls.L3]; - state.R1 = buttons[(int)DS4Controls.R1]; - state.R3 = buttons[(int)DS4Controls.R3]; + state.L1 = buttons[(int)DS4Controls.L1]; + state.L3 = buttons[(int)DS4Controls.L3]; + state.R1 = buttons[(int)DS4Controls.R1]; + state.R3 = buttons[(int)DS4Controls.R3]; - state.Cross = buttons[(int)DS4Controls.Cross]; - state.Triangle = buttons[(int)DS4Controls.Triangle]; - state.Circle = buttons[(int)DS4Controls.Circle]; - state.Square = buttons[(int)DS4Controls.Square]; - state.PS = buttons[(int)DS4Controls.PS]; - state.Options = buttons[(int)DS4Controls.Options]; - state.Share = buttons[(int)DS4Controls.Share]; + state.Cross = buttons[(int)DS4Controls.Cross]; + state.Triangle = buttons[(int)DS4Controls.Triangle]; + state.Circle = buttons[(int)DS4Controls.Circle]; + state.Square = buttons[(int)DS4Controls.Square]; + state.PS = buttons[(int)DS4Controls.PS]; + state.Options = buttons[(int)DS4Controls.Options]; + state.Share = buttons[(int)DS4Controls.Share]; - state.DpadUp = buttons[(int)DS4Controls.DpadUp]; - state.DpadRight = buttons[(int)DS4Controls.DpadRight]; - state.DpadDown = buttons[(int)DS4Controls.DpadDown]; - state.DpadLeft = buttons[(int)DS4Controls.DpadLeft]; + state.DpadUp = buttons[(int)DS4Controls.DpadUp]; + state.DpadRight = buttons[(int)DS4Controls.DpadRight]; + state.DpadDown = buttons[(int)DS4Controls.DpadDown]; + state.DpadLeft = buttons[(int)DS4Controls.DpadLeft]; + } } } } From 2a4570bb735e077f51276d38ea2a99245f058302 Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Sun, 10 Feb 2019 11:39:59 -0600 Subject: [PATCH 32/66] Include links to my Steam and GOG library listings to help point out testing targets --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index fc90714..c310ec9 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,21 @@ use DS4Windows properly, you have to open Steam Big Picture Mode, navigate to Settings > Controller> Controller Settings and uncheck **Xbox Configuration Support** along with **PlayStation Configuration Support**. +## Personal Game Testing + +My PC game library is not that expansive so there are likely games +that will be tested by users that I will not have access to +playing. There are likely going to be times when I cannot directly test +against a game since I will not have access to play it. Most free to play +games or games that include a playable demo should be fine for testing. +For other games, it might be better if people could test against any game +that I have in my game library and try to reproduce a problem. Here are +links to my Steam and GOG profiles so that people can see what games I have +access to play. + +https://steamcommunity.com/id/Ryochan7/games/?tab=all +https://www.gog.com/u/Ryochan7/games + ## Pull Requests Pull requests for DS4Windows are welcome. Before making a pull request, please From ce0ac67dcd7703edca9d4c04d2a2466fc7e81431 Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Mon, 11 Feb 2019 23:51:26 -0600 Subject: [PATCH 33/66] Remove some struct copying from lightbar routine --- DS4Windows/DS4Control/DS4LightBar.cs | 36 +++++++++++++++++++++------- DS4Windows/DS4Control/Mapping.cs | 4 ++-- DS4Windows/DS4Control/ScpUtil.cs | 17 +++++++------ 3 files changed, 40 insertions(+), 17 deletions(-) diff --git a/DS4Windows/DS4Control/DS4LightBar.cs b/DS4Windows/DS4Control/DS4LightBar.cs index 0a146c6..c81baf4 100644 --- a/DS4Windows/DS4Control/DS4LightBar.cs +++ b/DS4Windows/DS4Control/DS4LightBar.cs @@ -49,7 +49,7 @@ namespace DS4Windows { DS4Color fullColor = getCustomColor(deviceNum); DS4Color lowColor = getLowColor(deviceNum); - color = getTransitionedColor(lowColor, fullColor, device.getBattery()); + color = getTransitionedColor(ref lowColor, ref fullColor, device.getBattery()); } else color = getCustomColor(deviceNum); @@ -85,7 +85,7 @@ namespace DS4Windows { DS4Color fullColor = getMainColor(deviceNum); DS4Color lowColor = getLowColor(deviceNum); - color = getTransitionedColor(lowColor, fullColor, device.getBattery()); + color = getTransitionedColor(ref lowColor, ref fullColor, device.getBattery()); } else { @@ -144,7 +144,8 @@ namespace DS4Windows } } - color = getTransitionedColor(color, new DS4Color(0, 0, 0), ratio); + DS4Color tempCol = new DS4Color(0, 0, 0); + color = getTransitionedColor(ref color, ref tempCol, ratio); } } @@ -159,11 +160,16 @@ namespace DS4Windows double ratio = 100.0 * (botratio / topratio), elapsed = ratio; if (ratio >= 50.0 && ratio < 100.0) { - color = getTransitionedColor(color, new DS4Color(0, 0, 0), + DS4Color emptyCol = new DS4Color(0, 0, 0); + color = getTransitionedColor(ref color, ref emptyCol, (uint)(-100.0 * (elapsed = 0.02 * (ratio - 50.0)) * (elapsed - 2.0))); } else if (ratio >= 100.0) - color = getTransitionedColor(color, new DS4Color(0, 0, 0), 100.0); + { + DS4Color emptyCol = new DS4Color(0, 0, 0); + color = getTransitionedColor(ref color, ref emptyCol, 100.0); + } + } if (device.isCharging() && device.getBattery() < 100) @@ -217,7 +223,8 @@ namespace DS4Windows } } - color = getTransitionedColor(color, new DS4Color(0, 0, 0), ratio); + DS4Color emptyCol = new DS4Color(0, 0, 0); + color = getTransitionedColor(ref color, ref emptyCol, ratio); break; } case 2: @@ -257,9 +264,22 @@ namespace DS4Windows float rumble = device.getLeftHeavySlowRumble() / 2.55f; byte max = Max(color.red, Max(color.green, color.blue)); if (device.getLeftHeavySlowRumble() > 100) - color = getTransitionedColor(new DS4Color(max, max, 0), new DS4Color(255, 0, 0), rumble); + { + DS4Color maxCol = new DS4Color(max, max, 0); + DS4Color redCol = new DS4Color(255, 0, 0); + color = getTransitionedColor(ref maxCol, ref redCol, rumble); + } + else - color = getTransitionedColor(color, getTransitionedColor(new DS4Color(max, max, 0), new DS4Color(255, 0, 0), 39.6078f), device.getLeftHeavySlowRumble()); + { + DS4Color maxCol = new DS4Color(max, max, 0); + DS4Color redCol = new DS4Color(255, 0, 0); + DS4Color tempCol = getTransitionedColor(ref maxCol, + ref redCol, 39.6078f); + color = getTransitionedColor(ref color, ref tempCol, + device.getLeftHeavySlowRumble()); + } + } DS4HapticState haptics = new DS4HapticState diff --git a/DS4Windows/DS4Control/Mapping.cs b/DS4Windows/DS4Control/Mapping.cs index 29a0bcd..391456d 100644 --- a/DS4Windows/DS4Control/Mapping.cs +++ b/DS4Windows/DS4Control/Mapping.cs @@ -1885,9 +1885,9 @@ namespace DS4Windows } DS4Color empty = new DS4Color(byte.Parse(dets[3]), byte.Parse(dets[4]), byte.Parse(dets[5])); DS4Color full = new DS4Color(byte.Parse(dets[6]), byte.Parse(dets[7]), byte.Parse(dets[8])); - DS4Color trans = getTransitionedColor(empty, full, d.Battery); + DS4Color trans = getTransitionedColor(ref empty, ref full, d.Battery); if (fadetimer[device] < 100) - DS4LightBar.forcedColor[device] = getTransitionedColor(lastColor[device], trans, fadetimer[device] += 2); + DS4LightBar.forcedColor[device] = getTransitionedColor(ref lastColor[device], ref trans, fadetimer[device] += 2); } actionDone[index].dev[device] = true; } diff --git a/DS4Windows/DS4Control/ScpUtil.cs b/DS4Windows/DS4Control/ScpUtil.cs index 4e2ee7a..9e707bc 100644 --- a/DS4Windows/DS4Control/ScpUtil.cs +++ b/DS4Windows/DS4Control/ScpUtil.cs @@ -1319,17 +1319,20 @@ namespace DS4Windows else if (r < 0.0) r = 0.0; - r /= 100.0; - return (byte)Math.Round((b1 * (1 - r) + b2 * r), 0); + r *= 0.01; + return (byte)Math.Round((b1 * (1 - r)) + b2 * r, 0); } - public static DS4Color getTransitionedColor(DS4Color c1, DS4Color c2, double ratio) + public static DS4Color getTransitionedColor(ref DS4Color c1, ref DS4Color c2, double ratio) { //Color cs = Color.FromArgb(c1.red, c1.green, c1.blue); - c1.red = applyRatio(c1.red, c2.red, ratio); - c1.green = applyRatio(c1.green, c2.green, ratio); - c1.blue = applyRatio(c1.blue, c2.blue, ratio); - return c1; + DS4Color cs = new DS4Color + { + red = applyRatio(c1.red, c2.red, ratio), + green = applyRatio(c1.green, c2.green, ratio), + blue = applyRatio(c1.blue, c2.blue, ratio) + }; + return cs; } private static Color applyRatio(Color c1, Color c2, uint r) From 6098c91e2913e52348bbfc708522965892410580 Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Tue, 12 Feb 2019 01:31:18 -0600 Subject: [PATCH 34/66] Use ref for more color struct routines --- DS4Windows/DS4Control/DS4LightBar.cs | 10 +++++----- DS4Windows/DS4Control/ScpUtil.cs | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/DS4Windows/DS4Control/DS4LightBar.cs b/DS4Windows/DS4Control/DS4LightBar.cs index c81baf4..5e72314 100644 --- a/DS4Windows/DS4Control/DS4LightBar.cs +++ b/DS4Windows/DS4Control/DS4LightBar.cs @@ -47,8 +47,8 @@ namespace DS4Windows { if (getLedAsBatteryIndicator(deviceNum)) { - DS4Color fullColor = getCustomColor(deviceNum); - DS4Color lowColor = getLowColor(deviceNum); + ref DS4Color fullColor = ref getCustomColor(deviceNum); + ref DS4Color lowColor = ref getLowColor(deviceNum); color = getTransitionedColor(ref lowColor, ref fullColor, device.getBattery()); } else @@ -83,8 +83,8 @@ namespace DS4Windows } else if (getLedAsBatteryIndicator(deviceNum)) { - DS4Color fullColor = getMainColor(deviceNum); - DS4Color lowColor = getLowColor(deviceNum); + ref DS4Color fullColor = ref getMainColor(deviceNum); + ref DS4Color lowColor = ref getLowColor(deviceNum); color = getTransitionedColor(ref lowColor, ref fullColor, device.getBattery()); } else @@ -95,7 +95,7 @@ namespace DS4Windows if (device.getBattery() <= getFlashAt(deviceNum) && !defaultLight && !device.isCharging()) { - DS4Color flashColor = getFlashColor(deviceNum); + ref DS4Color flashColor = ref getFlashColor(deviceNum); if (!(flashColor.red == 0 && flashColor.green == 0 && flashColor.blue == 0)) diff --git a/DS4Windows/DS4Control/ScpUtil.cs b/DS4Windows/DS4Control/ScpUtil.cs index 9e707bc..9823864 100644 --- a/DS4Windows/DS4Control/ScpUtil.cs +++ b/DS4Windows/DS4Control/ScpUtil.cs @@ -794,27 +794,27 @@ namespace DS4Windows => m_Config.SetGyroMouseToggle(index, value, control); public static DS4Color[] MainColor => m_Config.m_Leds; - public static DS4Color getMainColor(int index) + public static ref DS4Color getMainColor(int index) { - return m_Config.m_Leds[index]; + return ref m_Config.m_Leds[index]; } public static DS4Color[] LowColor => m_Config.m_LowLeds; - public static DS4Color getLowColor(int index) + public static ref DS4Color getLowColor(int index) { - return m_Config.m_LowLeds[index]; + return ref m_Config.m_LowLeds[index]; } public static DS4Color[] ChargingColor => m_Config.m_ChargingLeds; - public static DS4Color getChargingColor(int index) + public static ref DS4Color getChargingColor(int index) { - return m_Config.m_ChargingLeds[index]; + return ref m_Config.m_ChargingLeds[index]; } public static DS4Color[] CustomColor => m_Config.m_CustomLeds; - public static DS4Color getCustomColor(int index) + public static ref DS4Color getCustomColor(int index) { - return m_Config.m_CustomLeds[index]; + return ref m_Config.m_CustomLeds[index]; } public static bool[] UseCustomLed => m_Config.useCustomLeds; @@ -824,9 +824,9 @@ namespace DS4Windows } public static DS4Color[] FlashColor => m_Config.m_FlashLeds; - public static DS4Color getFlashColor(int index) + public static ref DS4Color getFlashColor(int index) { - return m_Config.m_FlashLeds[index]; + return ref m_Config.m_FlashLeds[index]; } public static byte[] TapSensitivity => m_Config.tapSensitivity; From 688bc01916ddca3ca74cfee3aae017c8225c1c24 Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Tue, 12 Feb 2019 18:33:42 -0600 Subject: [PATCH 35/66] Target C# 7.3 --- DS4Windows/DS4Windows.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DS4Windows/DS4Windows.csproj b/DS4Windows/DS4Windows.csproj index edf5bf5..8e2e478 100644 --- a/DS4Windows/DS4Windows.csproj +++ b/DS4Windows/DS4Windows.csproj @@ -82,7 +82,7 @@ MinimumRecommendedRules.ruleset WIN64 On - 7.2 + 7.3 false true 1 From 5b19dc76cda16d761be8b90b467ff301209e25ac Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Fri, 15 Feb 2019 18:04:09 -0600 Subject: [PATCH 36/66] Re-added extra default axis mapping pass Related to issue #579 --- DS4Windows/DS4Control/Mapping.cs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/DS4Windows/DS4Control/Mapping.cs b/DS4Windows/DS4Control/Mapping.cs index 391456d..e5ff393 100644 --- a/DS4Windows/DS4Control/Mapping.cs +++ b/DS4Windows/DS4Control/Mapping.cs @@ -1506,6 +1506,15 @@ namespace DS4Windows resetToDefaultValue2(dcs.control, MappedState, outputfieldMapping); } } + else + { + DS4StateFieldMapping.ControlType controlType = DS4StateFieldMapping.mappedType[(int)dcs.control]; + if (controlType == DS4StateFieldMapping.ControlType.AxisDir) + //if (dcs.control > DS4Controls.None && dcs.control < DS4Controls.L1) + { + customMapQueue[device].Enqueue(new ControlToXInput(dcs.control, dcs.control)); + } + } } Queue tempControl = customMapQueue[device]; @@ -3371,9 +3380,9 @@ namespace DS4Windows private static byte getXYAxisMapping2(int device, DS4Controls control, DS4State cState, DS4StateExposed eState, Mouse tp, DS4StateFieldMapping fieldMap, bool alt = false) { + const byte falseVal = 128; byte result = 0; byte trueVal = 0; - byte falseVal = 128; if (alt) trueVal = 255; @@ -3391,11 +3400,11 @@ namespace DS4Windows switch (control) { - case DS4Controls.LXNeg: if (!alt) result = cState.LX; else result = (byte)(255 - cState.LX); break; - case DS4Controls.LYNeg: if (!alt) result = cState.LY; else result = (byte)(255 - cState.LY); break; - case DS4Controls.RXNeg: if (!alt) result = cState.RX; else result = (byte)(255 - cState.RX); break; - case DS4Controls.RYNeg: if (!alt) result = cState.RY; else result = (byte)(255 - cState.RY); break; - default: if (!alt) result = (byte)(255 - axisValue); else result = axisValue; break; + case DS4Controls.LXNeg: if (!alt) result = axisValue < falseVal ? axisValue : falseVal; else result = axisValue < falseVal ? (byte)(255 - axisValue) : falseVal; break; + case DS4Controls.LYNeg: if (!alt) result = axisValue < falseVal ? axisValue : falseVal; else result = axisValue < falseVal ? (byte)(255 - axisValue) : falseVal; break; + case DS4Controls.RXNeg: if (!alt) result = axisValue < falseVal ? axisValue : falseVal; else result = axisValue < falseVal ? (byte)(255 - axisValue) : falseVal; break; + case DS4Controls.RYNeg: if (!alt) result = axisValue < falseVal ? axisValue : falseVal; else result = axisValue < falseVal ? (byte)(255 - axisValue) : falseVal; break; + default: if (!alt) result = axisValue > falseVal ? (byte)(255 - axisValue) : falseVal; else result = axisValue > falseVal ? axisValue : falseVal; break; } } else if (controlType == DS4StateFieldMapping.ControlType.Trigger) From 50109282f46e0d06cd2b74caa7643b1d179be413 Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Fri, 15 Feb 2019 21:58:00 -0600 Subject: [PATCH 37/66] Added unchecked region --- DS4Windows/DS4Control/Mapping.cs | 59 +++++++++++++++++--------------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/DS4Windows/DS4Control/Mapping.cs b/DS4Windows/DS4Control/Mapping.cs index e5ff393..a1b1d7d 100644 --- a/DS4Windows/DS4Control/Mapping.cs +++ b/DS4Windows/DS4Control/Mapping.cs @@ -1512,45 +1512,50 @@ namespace DS4Windows if (controlType == DS4StateFieldMapping.ControlType.AxisDir) //if (dcs.control > DS4Controls.None && dcs.control < DS4Controls.L1) { + //int current = (int)dcs.control; + //outputfieldMapping.axisdirs[current] = fieldMapping.axisdirs[current]; customMapQueue[device].Enqueue(new ControlToXInput(dcs.control, dcs.control)); } } } Queue tempControl = customMapQueue[device]; - for (int i = 0, len = tempControl.Count; i < len; i++) - //while(tempControl.Any()) + unchecked { - ControlToXInput tempMap = tempControl.Dequeue(); - int controlNum = (int)tempMap.ds4input; - int tempOutControl = (int)tempMap.xoutput; - if (tempMap.xoutput >= DS4Controls.LXNeg && tempMap.xoutput <= DS4Controls.RYPos) + for (int i = 0, len = tempControl.Count; i < len; i++) + //while(tempControl.Any()) { - const byte axisDead = 128; - DS4StateFieldMapping.ControlType controlType = DS4StateFieldMapping.mappedType[tempOutControl]; - bool alt = controlType == DS4StateFieldMapping.ControlType.AxisDir && tempOutControl % 2 == 0 ? true : false; - byte axisMapping = getXYAxisMapping2(device, tempMap.ds4input, cState, eState, tp, fieldMapping, alt); - if (axisMapping != axisDead) + ControlToXInput tempMap = tempControl.Dequeue(); + int controlNum = (int)tempMap.ds4input; + int tempOutControl = (int)tempMap.xoutput; + if (tempMap.xoutput >= DS4Controls.LXNeg && tempMap.xoutput <= DS4Controls.RYPos) { - int controlRelation = tempOutControl % 2 == 0 ? tempOutControl - 1 : tempOutControl + 1; - outputfieldMapping.axisdirs[tempOutControl] = axisMapping; - outputfieldMapping.axisdirs[controlRelation] = axisMapping; - } - } - else - { - if (tempMap.xoutput == DS4Controls.L2 || tempMap.xoutput == DS4Controls.R2) - { - const byte axisZero = 0; - byte axisMapping = getByteMapping2(device, tempMap.ds4input, cState, eState, tp, fieldMapping); - if (axisMapping != axisZero) - outputfieldMapping.triggers[tempOutControl] = axisMapping; + const byte axisDead = 128; + DS4StateFieldMapping.ControlType controlType = DS4StateFieldMapping.mappedType[tempOutControl]; + bool alt = controlType == DS4StateFieldMapping.ControlType.AxisDir && tempOutControl % 2 == 0 ? true : false; + byte axisMapping = getXYAxisMapping2(device, tempMap.ds4input, cState, eState, tp, fieldMapping, alt); + if (axisMapping != axisDead) + { + int controlRelation = tempOutControl % 2 == 0 ? tempOutControl - 1 : tempOutControl + 1; + outputfieldMapping.axisdirs[tempOutControl] = axisMapping; + outputfieldMapping.axisdirs[controlRelation] = axisMapping; + } } else { - bool value = getBoolMapping2(device, tempMap.ds4input, cState, eState, tp, fieldMapping); - if (value) - outputfieldMapping.buttons[tempOutControl] = value; + if (tempMap.xoutput == DS4Controls.L2 || tempMap.xoutput == DS4Controls.R2) + { + const byte axisZero = 0; + byte axisMapping = getByteMapping2(device, tempMap.ds4input, cState, eState, tp, fieldMapping); + if (axisMapping != axisZero) + outputfieldMapping.triggers[tempOutControl] = axisMapping; + } + else + { + bool value = getBoolMapping2(device, tempMap.ds4input, cState, eState, tp, fieldMapping); + if (value) + outputfieldMapping.buttons[tempOutControl] = value; + } } } } From cd6742cf56142639b4182707e586652cd04d34d4 Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Sat, 16 Feb 2019 02:16:56 -0600 Subject: [PATCH 38/66] Found faster way to iterate over a ValueCollection --- DS4Windows/DS4Control/Mapping.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/DS4Windows/DS4Control/Mapping.cs b/DS4Windows/DS4Control/Mapping.cs index a1b1d7d..44199c1 100644 --- a/DS4Windows/DS4Control/Mapping.cs +++ b/DS4Windows/DS4Control/Mapping.cs @@ -40,9 +40,11 @@ namespace DS4Windows //foreach (KeyPresses kp in keyPresses.Values) Dictionary.ValueCollection keyValues = keyPresses.Values; - for (int i = 0, kpCount = keyValues.Count; i < kpCount; i++) + for (var keyEnum = keyValues.GetEnumerator(); keyEnum.MoveNext();) + //for (int i = 0, kpCount = keyValues.Count; i < kpCount; i++) { - KeyPresses kp = keyValues.ElementAt(i); + //KeyPresses kp = keyValues.ElementAt(i); + KeyPresses kp = keyEnum.Current; kp.previous = kp.current; if (performClear) { From 61a5ab07eac507bea08a6368f0d29a58f4fa7654 Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Sat, 16 Feb 2019 02:25:54 -0600 Subject: [PATCH 39/66] Use enumeartor for KeyCollection as well --- DS4Windows/DS4Control/Mapping.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/DS4Windows/DS4Control/Mapping.cs b/DS4Windows/DS4Control/Mapping.cs index 44199c1..dc2a2ec 100644 --- a/DS4Windows/DS4Control/Mapping.cs +++ b/DS4Windows/DS4Control/Mapping.cs @@ -290,9 +290,11 @@ namespace DS4Windows // TODO what about the rest? e.g. repeat keys really ought to be on some set schedule Dictionary.KeyCollection kvpKeys = state.keyPresses.Keys; //foreach (KeyValuePair kvp in state.keyPresses) - for (int i = 0, keyCount = kvpKeys.Count; i < keyCount; i++) + //for (int i = 0, keyCount = kvpKeys.Count; i < keyCount; i++) + for (var keyEnum = kvpKeys.GetEnumerator(); keyEnum.MoveNext();) { - UInt16 kvpKey = kvpKeys.ElementAt(i); + //UInt16 kvpKey = kvpKeys.ElementAt(i); + UInt16 kvpKey = keyEnum.Current; SyntheticState.KeyPresses kvpValue = state.keyPresses[kvpKey]; SyntheticState.KeyPresses gkp; From 3417c08a87f99a6edb1d4b35e2ab023659c77f02 Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Sat, 16 Feb 2019 02:41:13 -0600 Subject: [PATCH 40/66] Get rid of more ElementAt usage Old code is commented out as a reference --- DS4Windows/DS4Library/DS4Devices.cs | 6 ++++-- DS4Windows/HidLibrary/HidDevices.cs | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/DS4Windows/DS4Library/DS4Devices.cs b/DS4Windows/DS4Library/DS4Devices.cs index 09c4a53..6aaa4f1 100644 --- a/DS4Windows/DS4Library/DS4Devices.cs +++ b/DS4Windows/DS4Library/DS4Devices.cs @@ -248,9 +248,11 @@ namespace DS4Windows if (disabledDevCount > 0) { List disabledDevList = new List(); - for (int i = 0, arlen = disabledDevCount; i < arlen; i++) + for (var devEnum = DisabledDevices.GetEnumerator(); devEnum.MoveNext();) + //for (int i = 0, arlen = disabledDevCount; i < arlen; i++) { - HidDevice tempDev = DisabledDevices.ElementAt(i); + //HidDevice tempDev = DisabledDevices.ElementAt(i); + HidDevice tempDev = devEnum.Current; if (tempDev != null) { if (tempDev.IsOpen && tempDev.IsConnected) diff --git a/DS4Windows/HidLibrary/HidDevices.cs b/DS4Windows/HidLibrary/HidDevices.cs index 00125eb..a3c35a0 100644 --- a/DS4Windows/HidLibrary/HidDevices.cs +++ b/DS4Windows/HidLibrary/HidDevices.cs @@ -46,9 +46,11 @@ namespace DS4Windows List foundDevs = new List(); int devInfoLen = devInfo.Length; IEnumerable temp = EnumerateDevices(); - for (int i = 0, len = temp.Count(); i < len; i++) + for (var devEnum = temp.GetEnumerator(); devEnum.MoveNext();) + //for (int i = 0, len = temp.Count(); i < len; i++) { - DeviceInfo x = temp.ElementAt(i); + DeviceInfo x = devEnum.Current; + //DeviceInfo x = temp.ElementAt(i); HidDevice tempDev = new HidDevice(x.Path, x.Description); bool found = false; for (int j = 0; !found && j < devInfoLen; j++) From a9e7a3cb5bbf6ed43e275f217ea0b6c158ec9aad Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Sat, 16 Feb 2019 02:50:53 -0600 Subject: [PATCH 41/66] More enumerator usage --- DS4Windows/DS4Control/ControlService.cs | 13 +++++++++---- DS4Windows/DS4Control/ScpUtil.cs | 6 ++++-- DS4Windows/DS4Library/DS4Devices.cs | 6 ++++-- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/DS4Windows/DS4Control/ControlService.cs b/DS4Windows/DS4Control/ControlService.cs index 82f5fb5..30a9db5 100644 --- a/DS4Windows/DS4Control/ControlService.cs +++ b/DS4Windows/DS4Control/ControlService.cs @@ -346,9 +346,12 @@ namespace DS4Windows DS4LightBar.defaultLight = false; //foreach (DS4Device device in devices) - for (int i = 0, devCount = devices.Count(); i < devCount; i++) + //for (int i = 0, devCount = devices.Count(); i < devCount; i++) + int i = 0; + for (var devEnum = devices.GetEnumerator(); devEnum.MoveNext(); i++) { - DS4Device device = devices.ElementAt(i); + DS4Device device = devEnum.Current; + //DS4Device device = devices.ElementAt(i); if (showlog) LogDebug(Properties.Resources.FoundController + device.getMacAddress() + " (" + device.getConnectionType() + ")"); @@ -561,9 +564,11 @@ namespace DS4Windows DS4Devices.findControllers(); IEnumerable devices = DS4Devices.getDS4Controllers(); //foreach (DS4Device device in devices) - for (int i = 0, devlen = devices.Count(); i < devlen; i++) + //for (int i = 0, devlen = devices.Count(); i < devlen; i++) + for (var devEnum = devices.GetEnumerator(); devEnum.MoveNext();) { - DS4Device device = devices.ElementAt(i); + DS4Device device = devEnum.Current; + //DS4Device device = devices.ElementAt(i); if (device.isDisconnectingStatus()) continue; diff --git a/DS4Windows/DS4Control/ScpUtil.cs b/DS4Windows/DS4Control/ScpUtil.cs index 9823864..d33ba7d 100644 --- a/DS4Windows/DS4Control/ScpUtil.cs +++ b/DS4Windows/DS4Control/ScpUtil.cs @@ -3507,9 +3507,11 @@ namespace DS4Windows linkedXdoc.AppendChild(Node); Dictionary.KeyCollection serials = linkedProfiles.Keys; - for (int i = 0, itemCount = linkedProfiles.Count; i < itemCount; i++) + //for (int i = 0, itemCount = linkedProfiles.Count; i < itemCount; i++) + for (var serialEnum = serials.GetEnumerator(); serialEnum.MoveNext();) { - string serial = serials.ElementAt(i); + //string serial = serials.ElementAt(i); + string serial = serialEnum.Current; string profile = linkedProfiles[serial]; XmlElement link = linkedXdoc.CreateElement("MAC" + serial); link.InnerText = profile; diff --git a/DS4Windows/DS4Library/DS4Devices.cs b/DS4Windows/DS4Library/DS4Devices.cs index 6aaa4f1..c97ea87 100644 --- a/DS4Windows/DS4Library/DS4Devices.cs +++ b/DS4Windows/DS4Library/DS4Devices.cs @@ -179,9 +179,11 @@ namespace DS4Windows { IEnumerable devices = getDS4Controllers(); //foreach (DS4Device device in devices) - for (int i = 0, devCount = devices.Count(); i < devCount; i++) + //for (int i = 0, devCount = devices.Count(); i < devCount; i++) + for (var devEnum = devices.GetEnumerator(); devEnum.MoveNext();) { - DS4Device device = devices.ElementAt(i); + DS4Device device = devEnum.Current; + //DS4Device device = devices.ElementAt(i); device.StopUpdate(); //device.runRemoval(); device.HidDevice.CloseDevice(); From 40278c9d1bb28c273c48173f35ff345918667490 Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Sat, 16 Feb 2019 15:49:36 -0600 Subject: [PATCH 42/66] Use enumerator for settings iteration --- DS4Windows/DS4Control/Mapping.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/DS4Windows/DS4Control/Mapping.cs b/DS4Windows/DS4Control/Mapping.cs index dc2a2ec..76bfd70 100644 --- a/DS4Windows/DS4Control/Mapping.cs +++ b/DS4Windows/DS4Control/Mapping.cs @@ -1205,9 +1205,11 @@ namespace DS4Windows DS4Controls usingExtra = DS4Controls.None; List tempSettingsList = getDS4CSettings(device); //foreach (DS4ControlSettings dcs in getDS4CSettings(device)) - for (int settingIndex = 0, arlen = tempSettingsList.Count; settingIndex < arlen; settingIndex++) + //for (int settingIndex = 0, arlen = tempSettingsList.Count; settingIndex < arlen; settingIndex++) + for (var settingEnum = tempSettingsList.GetEnumerator(); settingEnum.MoveNext();) { - DS4ControlSettings dcs = tempSettingsList[settingIndex]; + //DS4ControlSettings dcs = tempSettingsList[settingIndex]; + DS4ControlSettings dcs = settingEnum.Current; object action = null; DS4ControlSettings.ActionType actionType = 0; DS4KeyType keyType = DS4KeyType.None; From 9baceec6568fcbf6bbefaf52dfeda0d91ed29779 Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Sun, 17 Feb 2019 02:04:03 -0600 Subject: [PATCH 43/66] Update newest text file --- DS4Windows/newest.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DS4Windows/newest.txt b/DS4Windows/newest.txt index 1df3b82..99c026b 100644 --- a/DS4Windows/newest.txt +++ b/DS4Windows/newest.txt @@ -1 +1 @@ -1.6.10 +1.6.11 From 7f94a33e973da95fd8f21d8827ad7ce70a61b935 Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Sun, 17 Feb 2019 02:04:37 -0600 Subject: [PATCH 44/66] Version 1.6.11 --- DS4Windows/Properties/AssemblyInfo.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DS4Windows/Properties/AssemblyInfo.cs b/DS4Windows/Properties/AssemblyInfo.cs index 9608b42..0f07a6f 100644 --- a/DS4Windows/Properties/AssemblyInfo.cs +++ b/DS4Windows/Properties/AssemblyInfo.cs @@ -33,7 +33,7 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.6.10")] -[assembly: AssemblyFileVersion("1.6.10")] +[assembly: AssemblyVersion("1.6.11")] +[assembly: AssemblyFileVersion("1.6.11")] [assembly: NeutralResourcesLanguage("en")] From d609453f12d4bf760c0dd6ce524b88937b7392af Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Mon, 18 Feb 2019 18:33:36 -0600 Subject: [PATCH 45/66] Now target .NET Framework 4.6.2 Seems to work better than version 4.6.1 on my system --- DS4Windows/DS4Windows.csproj | 2 +- DS4Windows/app.config | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/DS4Windows/DS4Windows.csproj b/DS4Windows/DS4Windows.csproj index 8e2e478..15ed516 100644 --- a/DS4Windows/DS4Windows.csproj +++ b/DS4Windows/DS4Windows.csproj @@ -9,7 +9,7 @@ Properties DS4Windows DS4Windows - v4.6.1 + v4.6.2 512 true diff --git a/DS4Windows/app.config b/DS4Windows/app.config index 38e445e..6475090 100644 --- a/DS4Windows/app.config +++ b/DS4Windows/app.config @@ -1,12 +1,12 @@ - + - + From 27dbab06c551b9e3d1abba214f1f8182108e54e9 Mon Sep 17 00:00:00 2001 From: mika-n Date: Tue, 19 Feb 2019 11:10:16 +0200 Subject: [PATCH 46/66] Deadzone and anti-deadzone handling (the first rugged version, not perfect yet) and small performance improvements here and there. --- DS4Windows/DS4Control/Mapping.cs | 80 +++++++++++++++++++++++++---- DS4Windows/DS4Control/ScpUtil.cs | 4 +- DS4Windows/DS4Control/X360Device.cs | 24 +++++---- DS4Windows/DS4Forms/Options.cs | 4 +- DS4Windows/VJoyFeeder/vJoyFeeder.cs | 19 ++++--- 5 files changed, 102 insertions(+), 29 deletions(-) diff --git a/DS4Windows/DS4Control/Mapping.cs b/DS4Windows/DS4Control/Mapping.cs index 84ce6d8..c8f8da2 100644 --- a/DS4Windows/DS4Control/Mapping.cs +++ b/DS4Windows/DS4Control/Mapping.cs @@ -1650,8 +1650,10 @@ namespace DS4Windows } } - if (getSASteeringWheelEmulationAxis(device) != SASteeringWheelEmulationAxisType.None) + if (GetSASteeringWheelEmulationAxis(device) != SASteeringWheelEmulationAxisType.None) + { MappedState.SASteeringWheelEmulationUnit = Mapping.Scale360degreeGyroAxis(device, eState, ctrl); + } calculateFinalMouseMovement(ref tempMouseDeltaX, ref tempMouseDeltaY, out mouseDeltaX, out mouseDeltaY); @@ -3915,6 +3917,8 @@ namespace DS4Windows gyroAccelX = exposedState.getAccelX(); gyroAccelZ = exposedState.getAccelZ(); + //gyroAccelX = exposedState.OutputAccelX; + //gyroAccelZ = exposedState.OutputAccelZ; // State 0=Normal mode (ie. calibration process is not running), 1=Activating calibration, 2=Calibration process running, 3=Completing calibration, 4=Cancelling calibration if (controller.WheelRecalibrateActiveState == 1) @@ -4057,6 +4061,8 @@ namespace DS4Windows gyroAccelX = exposedState.getAccelX(); gyroAccelZ = exposedState.getAccelZ(); + //gyroAccelX = exposedState.OutputAccelX; + //gyroAccelZ = exposedState.OutputAccelZ; // If calibration values are missing then use "educated guesses" about good starting values if (controller.wheelCenterPoint.IsEmpty) @@ -4086,11 +4092,19 @@ namespace DS4Windows } - int maxRangeRight = Global.getSASteeringWheelEmulationRange(device) / 2 * C_WHEEL_ANGLE_PRECISION; + int maxRangeRight = Global.GetSASteeringWheelEmulationRange(device) / 2 * C_WHEEL_ANGLE_PRECISION; int maxRangeLeft = -maxRangeRight; result = CalculateControllerAngle(gyroAccelX, gyroAccelZ, controller); + // Apply deadzone (SA X-deadzone value). This code assumes that 20deg is the max deadzone anyone ever might wanna use (in practice effective deadzone + // is probably just few degrees by using SXDeadZone values 0.01...0.05) + double sxDead = getSXDeadzone(device); + if ( sxDead > 0 && result != 0 && Math.Abs(result) < (20.0 * C_WHEEL_ANGLE_PRECISION * sxDead) ) + { + result = 0; + } + // If wrapped around from +180 to -180 side (or vice versa) then SA steering wheel keeps on turning beyond 360 degrees (if range is >360) int wheelFullTurnCount = controller.wheelFullTurnCount; if (controller.wheelPrevPhysicalAngle < 0 && result > 0) @@ -4134,28 +4148,76 @@ namespace DS4Windows result = Mapping.ClampInt(maxRangeLeft, result, maxRangeRight); // Debug log output of SA sensor values - //LogToGuiSACalibrationDebugMsg($"DEBUG gyro=({gyroAccelX}, {gyroAccelZ}) gyroPitchRollYaw=({currentDeviceState.Motion.gyroPitch}, {currentDeviceState.Motion.gyroRoll}, {currentDeviceState.Motion.gyroYaw}) gyroPitchRollYaw=({currentDeviceState.Motion.angVelPitch}, {currentDeviceState.Motion.angVelRoll}, {currentDeviceState.Motion.angVelYaw}) angle={result / (1.0 * C_WHEEL_ANGLE_PRECISION)} fullTurns={controller.wheelFullTurnCount}", false); + //LogToGuiSACalibrationDebugMsg($"DBG gyro=({gyroAccelX}, {gyroAccelZ}) output=({exposedState.OutputAccelX}, {exposedState.OutputAccelZ}) PitRolYaw=({currentDeviceState.Motion.gyroPitch}, {currentDeviceState.Motion.gyroRoll}, {currentDeviceState.Motion.gyroYaw}) VelPitRolYaw=({currentDeviceState.Motion.angVelPitch}, {currentDeviceState.Motion.angVelRoll}, {currentDeviceState.Motion.angVelYaw}) angle={result / (1.0 * C_WHEEL_ANGLE_PRECISION)} fullTurns={controller.wheelFullTurnCount}", false); - // Scale input to a raw x360 16bit output scale, except if output axis of steering wheel emulation is L2+R2 trigger axis. - switch(Global.getSASteeringWheelEmulationAxis(device)) + // Apply anti-deadzone (SA X-antideadzone value) + double sxAntiDead = getSXAntiDeadzone(device); + + switch (Global.GetSASteeringWheelEmulationAxis(device)) { case SASteeringWheelEmulationAxisType.LX: case SASteeringWheelEmulationAxisType.LY: case SASteeringWheelEmulationAxisType.RX: case SASteeringWheelEmulationAxisType.RY: // DS4 thumbstick axis output (-32768..32767 raw value range) - return (((result - maxRangeLeft) * (32767 - (-32768))) / (maxRangeRight - maxRangeLeft)) + (-32768); + //return (((result - maxRangeLeft) * (32767 - (-32768))) / (maxRangeRight - maxRangeLeft)) + (-32768); + if (result == 0) return 0; + + if (sxAntiDead > 0) + { + sxAntiDead *= 32767; + if (result < 0) return (((result - maxRangeLeft) * (-Convert.ToInt32(sxAntiDead) - (-32768))) / (0 - maxRangeLeft)) + (-32768); + else return (((result - 0) * (32767 - (Convert.ToInt32(sxAntiDead)))) / (maxRangeRight - 0)) + (Convert.ToInt32(sxAntiDead)); + } + else + { + return (((result - maxRangeLeft) * (32767 - (-32768))) / (maxRangeRight - maxRangeLeft)) + (-32768); + } case SASteeringWheelEmulationAxisType.L2R2: // DS4 Trigger axis output. L2+R2 triggers share the same axis in x360 xInput/DInput controller, // so L2+R2 steering output supports only 360 turn range (-255..255 raw value range in the shared trigger axis) + // return (((result - (-180)) * (255 - (-255))) / (180 - (-180))) + (-255); + if (result == 0) return 0; + result = Convert.ToInt32(Math.Round(result / (1.0 * C_WHEEL_ANGLE_PRECISION))); if (result < 0) result = -181 - result; - return (((result - (-180)) * (255 - (-255))) / (180 - (-180))) + (-255); + + if (sxAntiDead > 0) + { + sxAntiDead *= 255; + if(result < 0) return (((result - (-180)) * (-Convert.ToInt32(sxAntiDead) - (-255))) / (0 - (-180))) + (-255); + else return (((result - (0)) * (255 - (Convert.ToInt32(sxAntiDead)))) / (180 - (0))) + (Convert.ToInt32(sxAntiDead)); + } + else + { + return (((result - (-180)) * (255 - (-255))) / (180 - (-180))) + (-255); + } + + case SASteeringWheelEmulationAxisType.VJoy1X: + case SASteeringWheelEmulationAxisType.VJoy1Y: + case SASteeringWheelEmulationAxisType.VJoy1Z: + case SASteeringWheelEmulationAxisType.VJoy2X: + case SASteeringWheelEmulationAxisType.VJoy2Y: + case SASteeringWheelEmulationAxisType.VJoy2Z: + // SASteeringWheelEmulationAxisType.VJoy1X/VJoy1Y/VJoy1Z/VJoy2X/VJoy2Y/VJoy2Z VJoy axis output (0..32767 raw value range by default) + // return (((result - maxRangeLeft) * (32767 - (-0))) / (maxRangeRight - maxRangeLeft)) + (-0); + if (result == 0) return 16384; + + if (sxAntiDead > 0) + { + sxAntiDead *= 16384; + if (result < 0) return (((result - maxRangeLeft) * (16384 - Convert.ToInt32(sxAntiDead) - (-0))) / (0 - maxRangeLeft)) + (-0); + else return (((result - 0) * (32767 - (16384 + Convert.ToInt32(sxAntiDead)))) / (maxRangeRight - 0)) + (16384 + Convert.ToInt32(sxAntiDead)); + } + else + { + return (((result - maxRangeLeft) * (32767 - (-0))) / (maxRangeRight - maxRangeLeft)) + (-0); + } default: - // SASteeringWheelEmulationAxisType.VJoy1X/VJoy1Y/VJoy1Z/VJoy2X/VJoy2Y/VJoy2Z VJoy axis output (0..32767 raw value range by default) - return (((result - maxRangeLeft) * (32767 - (-0))) / (maxRangeRight - maxRangeLeft)) + (-0); + // Should never come here, but C# case statement syntax requires DEFAULT handler + return 0; } } } diff --git a/DS4Windows/DS4Control/ScpUtil.cs b/DS4Windows/DS4Control/ScpUtil.cs index a5f7660..d6af7e1 100644 --- a/DS4Windows/DS4Control/ScpUtil.cs +++ b/DS4Windows/DS4Control/ScpUtil.cs @@ -721,13 +721,13 @@ namespace DS4Windows } public static SASteeringWheelEmulationAxisType[] SASteeringWheelEmulationAxis => m_Config.sASteeringWheelEmulationAxis; - public static SASteeringWheelEmulationAxisType getSASteeringWheelEmulationAxis(int index) + public static SASteeringWheelEmulationAxisType GetSASteeringWheelEmulationAxis(int index) { return m_Config.sASteeringWheelEmulationAxis[index]; } public static int[] SASteeringWheelEmulationRange => m_Config.sASteeringWheelEmulationRange; - public static int getSASteeringWheelEmulationRange(int index) + public static int GetSASteeringWheelEmulationRange(int index) { return m_Config.sASteeringWheelEmulationRange[index]; } diff --git a/DS4Windows/DS4Control/X360Device.cs b/DS4Windows/DS4Control/X360Device.cs index a8244ee..e0873e2 100644 --- a/DS4Windows/DS4Control/X360Device.cs +++ b/DS4Windows/DS4Control/X360Device.cs @@ -129,7 +129,7 @@ namespace DS4Windows if (state.PS) Output[11] |= (Byte)(1 << 2); // Guide - SASteeringWheelEmulationAxisType steeringWheelMappedAxis = Global.getSASteeringWheelEmulationAxis(device); + SASteeringWheelEmulationAxisType steeringWheelMappedAxis = Global.GetSASteeringWheelEmulationAxis(device); Int32 ThumbLX; Int32 ThumbLY; Int32 ThumbRX; @@ -140,6 +140,13 @@ namespace DS4Windows switch(steeringWheelMappedAxis) { + case SASteeringWheelEmulationAxisType.None: + ThumbLX = Scale(state.LX, false); + ThumbLY = Scale(state.LY, true); + ThumbRX = Scale(state.RX, false); + ThumbRY = Scale(state.RY, true); + break; + case SASteeringWheelEmulationAxisType.LX: ThumbLX = state.SASteeringWheelEmulationUnit; ThumbLY = Scale(state.LY, true); @@ -172,29 +179,26 @@ namespace DS4Windows Output[12] = Output[13] = 0; if (state.SASteeringWheelEmulationUnit >= 0) Output[12] = (Byte)state.SASteeringWheelEmulationUnit; else Output[13] = (Byte)state.SASteeringWheelEmulationUnit; - goto default; // Usually GOTO is not a good idea but in switch-case statements it is sometimes pretty handy and acceptable way to fall through case options + goto case SASteeringWheelEmulationAxisType.None; case SASteeringWheelEmulationAxisType.VJoy1X: case SASteeringWheelEmulationAxisType.VJoy2X: DS4Windows.VJoyFeeder.vJoyFeeder.FeedAxisValue(state.SASteeringWheelEmulationUnit, ((((uint)steeringWheelMappedAxis) - ((uint)SASteeringWheelEmulationAxisType.VJoy1X)) / 3) + 1, DS4Windows.VJoyFeeder.HID_USAGES.HID_USAGE_X); - goto default; + goto case SASteeringWheelEmulationAxisType.None; case SASteeringWheelEmulationAxisType.VJoy1Y: case SASteeringWheelEmulationAxisType.VJoy2Y: DS4Windows.VJoyFeeder.vJoyFeeder.FeedAxisValue(state.SASteeringWheelEmulationUnit, ((((uint)steeringWheelMappedAxis) - ((uint)SASteeringWheelEmulationAxisType.VJoy1X)) / 3) + 1, DS4Windows.VJoyFeeder.HID_USAGES.HID_USAGE_Y); - goto default; + goto case SASteeringWheelEmulationAxisType.None; case SASteeringWheelEmulationAxisType.VJoy1Z: case SASteeringWheelEmulationAxisType.VJoy2Z: DS4Windows.VJoyFeeder.vJoyFeeder.FeedAxisValue(state.SASteeringWheelEmulationUnit, ((((uint)steeringWheelMappedAxis) - ((uint)SASteeringWheelEmulationAxisType.VJoy1X)) / 3) + 1, DS4Windows.VJoyFeeder.HID_USAGES.HID_USAGE_Z); - goto default; + goto case SASteeringWheelEmulationAxisType.None; default: - ThumbLX = Scale(state.LX, false); - ThumbLY = Scale(state.LY, true); - ThumbRX = Scale(state.RX, false); - ThumbRY = Scale(state.RY, true); - break; + // Should never come here but just in case use the NONE case as default handler.... + goto case SASteeringWheelEmulationAxisType.None; } Output[14] = (Byte)((ThumbLX >> 0) & 0xFF); // LX diff --git a/DS4Windows/DS4Forms/Options.cs b/DS4Windows/DS4Forms/Options.cs index 16f5001..a4d8b48 100644 --- a/DS4Windows/DS4Forms/Options.cs +++ b/DS4Windows/DS4Forms/Options.cs @@ -719,9 +719,9 @@ namespace DS4Windows cBGyroMouseXAxis.SelectedIndex = GyroMouseHorizontalAxis[device]; triggerCondAndCombo.SelectedIndex = SATriggerCond[device] ? 0 : 1; - cBSteeringWheelEmulationAxis.SelectedIndex = (int) getSASteeringWheelEmulationAxis(device); + cBSteeringWheelEmulationAxis.SelectedIndex = (int) GetSASteeringWheelEmulationAxis(device); - int idxSASteeringWheelEmulationRange = cBSteeringWheelEmulationRange.Items.IndexOf(getSASteeringWheelEmulationRange(device).ToString()); + int idxSASteeringWheelEmulationRange = cBSteeringWheelEmulationRange.Items.IndexOf(GetSASteeringWheelEmulationRange(device).ToString()); if (idxSASteeringWheelEmulationRange >= 0) cBSteeringWheelEmulationRange.SelectedIndex = idxSASteeringWheelEmulationRange; } else diff --git a/DS4Windows/VJoyFeeder/vJoyFeeder.cs b/DS4Windows/VJoyFeeder/vJoyFeeder.cs index 8304cbb..fcee9ff 100644 --- a/DS4Windows/VJoyFeeder/vJoyFeeder.cs +++ b/DS4Windows/VJoyFeeder/vJoyFeeder.cs @@ -4,7 +4,7 @@ // https://github.com/shauleiz/vJoy/tree/master/apps/common/vJoyInterfaceCS // // This module is a feeder for VJoy virtual joystick driver. DS4Windows can optionally re-map and feed buttons and analog axis values from DS4 Controller to VJoy device. -// At first this may seem silly because DS4Windows can already to re-mapping by using a virtual X360 Controller driver, so why feed VJoy virtual driver also? +// At first this may seem silly because DS4Windows can already do re-mapping by using a virtual X360 Controller driver, so why feed VJoy virtual driver also? // Sometimes X360 driver may run out of analog axis options, so for example "SA motion sensor steering wheel emulation" in DS4Windows would reserve a thumbstick X or Y // axis for SA steering wheel emulation usage. That thumbstick axis would be unavailable for "normal" thumbstick usage after this re-mapping. // The problem can be solved by configuring DS4Windows to re-map SA steering wheel emulation axis to VJoy axis, so all analog axies in DS4 controller are still available for normal usage. @@ -12,6 +12,7 @@ using System; using System.Runtime.InteropServices; +using System.Security; // SuppressUnmanagedCodeSecurity support to optimize for performance instead of code security namespace DS4Windows.VJoyFeeder { @@ -105,7 +106,8 @@ namespace DS4Windows.VJoyFeeder //namespace vJoyInterfaceWrap //{ - public class vJoy + [SuppressUnmanagedCodeSecurity] + public class vJoy { /***************************************************/ @@ -698,12 +700,17 @@ namespace DS4Windows.VJoyFeeder // Feed axis value to VJoy virtual joystic driver (DS4Windows sixaxis (SA) motion sensor steering wheel emulation feature can optionally feed VJoy analog axis instead of ScpVBus x360 axis public static void FeedAxisValue(int value, uint vJoyID, HID_USAGES axis) { - if (!vJoyInitialized) - InitializeVJoyDevice(vJoyID, axis); - if (vJoyAvailable) + { vJoyObj.SetAxis(value, vJoyID, axis); + } + else if (!vJoyInitialized) + { + // If this was the first call to this FeedAxisValue function and VJoy driver connection is not yet initialized + // then try to do it now. Subsequent calls will see the the vJoy as available (if connection succeeded) and + // there is no need to re-initialize the connection everytime the feeder is used. + InitializeVJoyDevice(vJoyID, axis); + } } - } } From f828eb888cca5fb061600c61409bcd4fd96372c5 Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Tue, 19 Feb 2019 03:16:42 -0600 Subject: [PATCH 47/66] Use struct reference rather than copy --- DS4Windows/DS4Library/DS4Device.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DS4Windows/DS4Library/DS4Device.cs b/DS4Windows/DS4Library/DS4Device.cs index 9dd72ec..43ba4f2 100644 --- a/DS4Windows/DS4Library/DS4Device.cs +++ b/DS4Windows/DS4Library/DS4Device.cs @@ -43,12 +43,12 @@ namespace DS4Windows { byte alphacolor = Math.Max(red, Math.Max(green, blue)); Color reg = Color.FromArgb(red, green, blue); - Color full = HuetoRGB(reg.GetHue(), reg.GetBrightness(), reg); + Color full = HuetoRGB(reg.GetHue(), reg.GetBrightness(), ref reg); return Color.FromArgb((alphacolor > 205 ? 255 : (alphacolor + 50)), full); } } - private Color HuetoRGB(float hue, float light, Color rgb) + private Color HuetoRGB(float hue, float light, ref Color rgb) { float L = (float)Math.Max(.5, light); float C = (1 - Math.Abs(2 * L - 1)); From a8c722d6049906bc54e077329c4f21ea3550c480 Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Tue, 19 Feb 2019 04:24:52 -0600 Subject: [PATCH 48/66] Replace old lock with ReaderWriterLockSlim instance --- DS4Windows/DS4Control/Mapping.cs | 345 ++++++++++++++++--------------- 1 file changed, 175 insertions(+), 170 deletions(-) diff --git a/DS4Windows/DS4Control/Mapping.cs b/DS4Windows/DS4Control/Mapping.cs index 76bfd70..9a81c48 100644 --- a/DS4Windows/DS4Control/Mapping.cs +++ b/DS4Windows/DS4Control/Mapping.cs @@ -2,10 +2,12 @@ using System.Collections.Generic; using System.Linq; +using System.Threading; using System.Threading.Tasks; using System.Diagnostics; using static DS4Windows.Global; + namespace DS4Windows { public class Mapping @@ -77,6 +79,8 @@ namespace DS4Windows new Queue(), new Queue() }; + static ReaderWriterLockSlim syncStateLock = new ReaderWriterLockSlim(); + public static SyntheticState globalState = new SyntheticState(); public static SyntheticState[] deviceState = new SyntheticState[4] { new SyntheticState(), new SyntheticState(), new SyntheticState(), @@ -190,206 +194,207 @@ namespace DS4Windows public static void Commit(int device) { SyntheticState state = deviceState[device]; - lock (globalState) + syncStateLock.EnterWriteLock(); + + globalState.currentClicks.leftCount += state.currentClicks.leftCount - state.previousClicks.leftCount; + globalState.currentClicks.middleCount += state.currentClicks.middleCount - state.previousClicks.middleCount; + globalState.currentClicks.rightCount += state.currentClicks.rightCount - state.previousClicks.rightCount; + globalState.currentClicks.fourthCount += state.currentClicks.fourthCount - state.previousClicks.fourthCount; + globalState.currentClicks.fifthCount += state.currentClicks.fifthCount - state.previousClicks.fifthCount; + globalState.currentClicks.wUpCount += state.currentClicks.wUpCount - state.previousClicks.wUpCount; + globalState.currentClicks.wDownCount += state.currentClicks.wDownCount - state.previousClicks.wDownCount; + globalState.currentClicks.toggleCount += state.currentClicks.toggleCount - state.previousClicks.toggleCount; + globalState.currentClicks.toggle = state.currentClicks.toggle; + + if (globalState.currentClicks.toggleCount != 0 && globalState.previousClicks.toggleCount == 0 && globalState.currentClicks.toggle) { - globalState.currentClicks.leftCount += state.currentClicks.leftCount - state.previousClicks.leftCount; - globalState.currentClicks.middleCount += state.currentClicks.middleCount - state.previousClicks.middleCount; - globalState.currentClicks.rightCount += state.currentClicks.rightCount - state.previousClicks.rightCount; - globalState.currentClicks.fourthCount += state.currentClicks.fourthCount - state.previousClicks.fourthCount; - globalState.currentClicks.fifthCount += state.currentClicks.fifthCount - state.previousClicks.fifthCount; - globalState.currentClicks.wUpCount += state.currentClicks.wUpCount - state.previousClicks.wUpCount; - globalState.currentClicks.wDownCount += state.currentClicks.wDownCount - state.previousClicks.wDownCount; - globalState.currentClicks.toggleCount += state.currentClicks.toggleCount - state.previousClicks.toggleCount; - globalState.currentClicks.toggle = state.currentClicks.toggle; + if (globalState.currentClicks.leftCount != 0 && globalState.previousClicks.leftCount == 0) + InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_LEFTDOWN); + if (globalState.currentClicks.rightCount != 0 && globalState.previousClicks.rightCount == 0) + InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_RIGHTDOWN); + if (globalState.currentClicks.middleCount != 0 && globalState.previousClicks.middleCount == 0) + InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_MIDDLEDOWN); + if (globalState.currentClicks.fourthCount != 0 && globalState.previousClicks.fourthCount == 0) + InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONDOWN, 1); + if (globalState.currentClicks.fifthCount != 0 && globalState.previousClicks.fifthCount == 0) + InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONDOWN, 2); + } + else if (globalState.currentClicks.toggleCount != 0 && globalState.previousClicks.toggleCount == 0 && !globalState.currentClicks.toggle) + { + if (globalState.currentClicks.leftCount != 0 && globalState.previousClicks.leftCount == 0) + InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_LEFTUP); + if (globalState.currentClicks.rightCount != 0 && globalState.previousClicks.rightCount == 0) + InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_RIGHTUP); + if (globalState.currentClicks.middleCount != 0 && globalState.previousClicks.middleCount == 0) + InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_MIDDLEUP); + if (globalState.currentClicks.fourthCount != 0 && globalState.previousClicks.fourthCount == 0) + InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONUP, 1); + if (globalState.currentClicks.fifthCount != 0 && globalState.previousClicks.fifthCount == 0) + InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONUP, 2); + } - if (globalState.currentClicks.toggleCount != 0 && globalState.previousClicks.toggleCount == 0 && globalState.currentClicks.toggle) + if (globalState.currentClicks.toggleCount == 0 && globalState.previousClicks.toggleCount == 0) + { + if (globalState.currentClicks.leftCount != 0 && globalState.previousClicks.leftCount == 0) + InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_LEFTDOWN); + else if (globalState.currentClicks.leftCount == 0 && globalState.previousClicks.leftCount != 0) + InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_LEFTUP); + + if (globalState.currentClicks.middleCount != 0 && globalState.previousClicks.middleCount == 0) + InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_MIDDLEDOWN); + else if (globalState.currentClicks.middleCount == 0 && globalState.previousClicks.middleCount != 0) + InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_MIDDLEUP); + + if (globalState.currentClicks.rightCount != 0 && globalState.previousClicks.rightCount == 0) + InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_RIGHTDOWN); + else if (globalState.currentClicks.rightCount == 0 && globalState.previousClicks.rightCount != 0) + InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_RIGHTUP); + + if (globalState.currentClicks.fourthCount != 0 && globalState.previousClicks.fourthCount == 0) + InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONDOWN, 1); + else if (globalState.currentClicks.fourthCount == 0 && globalState.previousClicks.fourthCount != 0) + InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONUP, 1); + + if (globalState.currentClicks.fifthCount != 0 && globalState.previousClicks.fifthCount == 0) + InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONDOWN, 2); + else if (globalState.currentClicks.fifthCount == 0 && globalState.previousClicks.fifthCount != 0) + InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONUP, 2); + + if (globalState.currentClicks.wUpCount != 0 && globalState.previousClicks.wUpCount == 0) { - if (globalState.currentClicks.leftCount != 0 && globalState.previousClicks.leftCount == 0) - InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_LEFTDOWN); - if (globalState.currentClicks.rightCount != 0 && globalState.previousClicks.rightCount == 0) - InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_RIGHTDOWN); - if (globalState.currentClicks.middleCount != 0 && globalState.previousClicks.middleCount == 0) - InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_MIDDLEDOWN); - if (globalState.currentClicks.fourthCount != 0 && globalState.previousClicks.fourthCount == 0) - InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONDOWN, 1); - if (globalState.currentClicks.fifthCount != 0 && globalState.previousClicks.fifthCount == 0) - InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONDOWN, 2); + InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_WHEEL, 120); + oldnow = DateTime.UtcNow; + wheel = 120; } - else if (globalState.currentClicks.toggleCount != 0 && globalState.previousClicks.toggleCount == 0 && !globalState.currentClicks.toggle) + else if (globalState.currentClicks.wUpCount == 0 && globalState.previousClicks.wUpCount != 0) + wheel = 0; + + if (globalState.currentClicks.wDownCount != 0 && globalState.previousClicks.wDownCount == 0) { - if (globalState.currentClicks.leftCount != 0 && globalState.previousClicks.leftCount == 0) - InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_LEFTUP); - if (globalState.currentClicks.rightCount != 0 && globalState.previousClicks.rightCount == 0) - InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_RIGHTUP); - if (globalState.currentClicks.middleCount != 0 && globalState.previousClicks.middleCount == 0) - InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_MIDDLEUP); - if (globalState.currentClicks.fourthCount != 0 && globalState.previousClicks.fourthCount == 0) - InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONUP, 1); - if (globalState.currentClicks.fifthCount != 0 && globalState.previousClicks.fifthCount == 0) - InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONUP, 2); - } - - if (globalState.currentClicks.toggleCount == 0 && globalState.previousClicks.toggleCount == 0) - { - if (globalState.currentClicks.leftCount != 0 && globalState.previousClicks.leftCount == 0) - InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_LEFTDOWN); - else if (globalState.currentClicks.leftCount == 0 && globalState.previousClicks.leftCount != 0) - InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_LEFTUP); - - if (globalState.currentClicks.middleCount != 0 && globalState.previousClicks.middleCount == 0) - InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_MIDDLEDOWN); - else if (globalState.currentClicks.middleCount == 0 && globalState.previousClicks.middleCount != 0) - InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_MIDDLEUP); - - if (globalState.currentClicks.rightCount != 0 && globalState.previousClicks.rightCount == 0) - InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_RIGHTDOWN); - else if (globalState.currentClicks.rightCount == 0 && globalState.previousClicks.rightCount != 0) - InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_RIGHTUP); - - if (globalState.currentClicks.fourthCount != 0 && globalState.previousClicks.fourthCount == 0) - InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONDOWN, 1); - else if (globalState.currentClicks.fourthCount == 0 && globalState.previousClicks.fourthCount != 0) - InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONUP, 1); - - if (globalState.currentClicks.fifthCount != 0 && globalState.previousClicks.fifthCount == 0) - InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONDOWN, 2); - else if (globalState.currentClicks.fifthCount == 0 && globalState.previousClicks.fifthCount != 0) - InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONUP, 2); - - if (globalState.currentClicks.wUpCount != 0 && globalState.previousClicks.wUpCount == 0) - { - InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_WHEEL, 120); - oldnow = DateTime.UtcNow; - wheel = 120; - } - else if (globalState.currentClicks.wUpCount == 0 && globalState.previousClicks.wUpCount != 0) - wheel = 0; - - if (globalState.currentClicks.wDownCount != 0 && globalState.previousClicks.wDownCount == 0) - { - InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_WHEEL, -120); - oldnow = DateTime.UtcNow; - wheel = -120; - } - if (globalState.currentClicks.wDownCount == 0 && globalState.previousClicks.wDownCount != 0) - wheel = 0; + InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_WHEEL, -120); + oldnow = DateTime.UtcNow; + wheel = -120; } + if (globalState.currentClicks.wDownCount == 0 && globalState.previousClicks.wDownCount != 0) + wheel = 0; + } - if (wheel != 0) //Continue mouse wheel movement + if (wheel != 0) //Continue mouse wheel movement + { + DateTime now = DateTime.UtcNow; + if (now >= oldnow + TimeSpan.FromMilliseconds(100) && !pressagain) { - DateTime now = DateTime.UtcNow; - if (now >= oldnow + TimeSpan.FromMilliseconds(100) && !pressagain) - { - oldnow = now; - InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_WHEEL, wheel); - } + oldnow = now; + InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_WHEEL, wheel); } + } - // Merge and synthesize all key presses/releases that are present in this device's mapping. - // TODO what about the rest? e.g. repeat keys really ought to be on some set schedule - Dictionary.KeyCollection kvpKeys = state.keyPresses.Keys; - //foreach (KeyValuePair kvp in state.keyPresses) - //for (int i = 0, keyCount = kvpKeys.Count; i < keyCount; i++) - for (var keyEnum = kvpKeys.GetEnumerator(); keyEnum.MoveNext();) + // Merge and synthesize all key presses/releases that are present in this device's mapping. + // TODO what about the rest? e.g. repeat keys really ought to be on some set schedule + Dictionary.KeyCollection kvpKeys = state.keyPresses.Keys; + //foreach (KeyValuePair kvp in state.keyPresses) + //for (int i = 0, keyCount = kvpKeys.Count; i < keyCount; i++) + for (var keyEnum = kvpKeys.GetEnumerator(); keyEnum.MoveNext();) + { + //UInt16 kvpKey = kvpKeys.ElementAt(i); + UInt16 kvpKey = keyEnum.Current; + SyntheticState.KeyPresses kvpValue = state.keyPresses[kvpKey]; + + SyntheticState.KeyPresses gkp; + if (globalState.keyPresses.TryGetValue(kvpKey, out gkp)) { - //UInt16 kvpKey = kvpKeys.ElementAt(i); - UInt16 kvpKey = keyEnum.Current; - SyntheticState.KeyPresses kvpValue = state.keyPresses[kvpKey]; - - SyntheticState.KeyPresses gkp; - if (globalState.keyPresses.TryGetValue(kvpKey, out gkp)) + gkp.current.vkCount += kvpValue.current.vkCount - kvpValue.previous.vkCount; + gkp.current.scanCodeCount += kvpValue.current.scanCodeCount - kvpValue.previous.scanCodeCount; + gkp.current.repeatCount += kvpValue.current.repeatCount - kvpValue.previous.repeatCount; + gkp.current.toggle = kvpValue.current.toggle; + gkp.current.toggleCount += kvpValue.current.toggleCount - kvpValue.previous.toggleCount; + } + else + { + gkp = new SyntheticState.KeyPresses(); + gkp.current = kvpValue.current; + globalState.keyPresses[kvpKey] = gkp; + } + if (gkp.current.toggleCount != 0 && gkp.previous.toggleCount == 0 && gkp.current.toggle) + { + if (gkp.current.scanCodeCount != 0) + InputMethods.performSCKeyPress(kvpKey); + else + InputMethods.performKeyPress(kvpKey); + } + else if (gkp.current.toggleCount != 0 && gkp.previous.toggleCount == 0 && !gkp.current.toggle) + { + if (gkp.previous.scanCodeCount != 0) // use the last type of VK/SC + InputMethods.performSCKeyRelease(kvpKey); + else + InputMethods.performKeyRelease(kvpKey); + } + else if (gkp.current.vkCount + gkp.current.scanCodeCount != 0 && gkp.previous.vkCount + gkp.previous.scanCodeCount == 0) + { + if (gkp.current.scanCodeCount != 0) { - gkp.current.vkCount += kvpValue.current.vkCount - kvpValue.previous.vkCount; - gkp.current.scanCodeCount += kvpValue.current.scanCodeCount - kvpValue.previous.scanCodeCount; - gkp.current.repeatCount += kvpValue.current.repeatCount - kvpValue.previous.repeatCount; - gkp.current.toggle = kvpValue.current.toggle; - gkp.current.toggleCount += kvpValue.current.toggleCount - kvpValue.previous.toggleCount; + oldnow = DateTime.UtcNow; + InputMethods.performSCKeyPress(kvpKey); + pressagain = false; + keyshelddown = kvpKey; } else { - gkp = new SyntheticState.KeyPresses(); - gkp.current = kvpValue.current; - globalState.keyPresses[kvpKey] = gkp; + oldnow = DateTime.UtcNow; + InputMethods.performKeyPress(kvpKey); + pressagain = false; + keyshelddown = kvpKey; } - if (gkp.current.toggleCount != 0 && gkp.previous.toggleCount == 0 && gkp.current.toggle) + } + else if (gkp.current.toggleCount != 0 || gkp.previous.toggleCount != 0 || gkp.current.repeatCount != 0 || // repeat or SC/VK transition + ((gkp.previous.scanCodeCount == 0) != (gkp.current.scanCodeCount == 0))) //repeat keystroke after 500ms + { + if (keyshelddown == kvpKey) { - if (gkp.current.scanCodeCount != 0) - InputMethods.performSCKeyPress(kvpKey); - else - InputMethods.performKeyPress(kvpKey); - } - else if (gkp.current.toggleCount != 0 && gkp.previous.toggleCount == 0 && !gkp.current.toggle) - { - if (gkp.previous.scanCodeCount != 0) // use the last type of VK/SC - InputMethods.performSCKeyRelease(kvpKey); - else - InputMethods.performKeyRelease(kvpKey); - } - else if (gkp.current.vkCount + gkp.current.scanCodeCount != 0 && gkp.previous.vkCount + gkp.previous.scanCodeCount == 0) - { - if (gkp.current.scanCodeCount != 0) + DateTime now = DateTime.UtcNow; + if (now >= oldnow + TimeSpan.FromMilliseconds(500) && !pressagain) { - oldnow = DateTime.UtcNow; - InputMethods.performSCKeyPress(kvpKey); - pressagain = false; - keyshelddown = kvpKey; + oldnow = now; + pressagain = true; } - else + if (pressagain && gkp.current.scanCodeCount != 0) { - oldnow = DateTime.UtcNow; - InputMethods.performKeyPress(kvpKey); - pressagain = false; - keyshelddown = kvpKey; - } - } - else if (gkp.current.toggleCount != 0 || gkp.previous.toggleCount != 0 || gkp.current.repeatCount != 0 || // repeat or SC/VK transition - ((gkp.previous.scanCodeCount == 0) != (gkp.current.scanCodeCount == 0))) //repeat keystroke after 500ms - { - if (keyshelddown == kvpKey) - { - DateTime now = DateTime.UtcNow; - if (now >= oldnow + TimeSpan.FromMilliseconds(500) && !pressagain) + now = DateTime.UtcNow; + if (now >= oldnow + TimeSpan.FromMilliseconds(25) && pressagain) { oldnow = now; - pressagain = true; - } - if (pressagain && gkp.current.scanCodeCount != 0) - { - now = DateTime.UtcNow; - if (now >= oldnow + TimeSpan.FromMilliseconds(25) && pressagain) - { - oldnow = now; - InputMethods.performSCKeyPress(kvpKey); - } - } - else if (pressagain) - { - now = DateTime.UtcNow; - if (now >= oldnow + TimeSpan.FromMilliseconds(25) && pressagain) - { - oldnow = now; - InputMethods.performKeyPress(kvpKey); - } + InputMethods.performSCKeyPress(kvpKey); } } - } - if ((gkp.current.toggleCount == 0 && gkp.previous.toggleCount == 0) && gkp.current.vkCount + gkp.current.scanCodeCount == 0 && gkp.previous.vkCount + gkp.previous.scanCodeCount != 0) - { - if (gkp.previous.scanCodeCount != 0) // use the last type of VK/SC + else if (pressagain) { - InputMethods.performSCKeyRelease(kvpKey); - pressagain = false; - } - else - { - InputMethods.performKeyRelease(kvpKey); - pressagain = false; + now = DateTime.UtcNow; + if (now >= oldnow + TimeSpan.FromMilliseconds(25) && pressagain) + { + oldnow = now; + InputMethods.performKeyPress(kvpKey); + } } } } - globalState.SaveToPrevious(false); + if ((gkp.current.toggleCount == 0 && gkp.previous.toggleCount == 0) && gkp.current.vkCount + gkp.current.scanCodeCount == 0 && gkp.previous.vkCount + gkp.previous.scanCodeCount != 0) + { + if (gkp.previous.scanCodeCount != 0) // use the last type of VK/SC + { + InputMethods.performSCKeyRelease(kvpKey); + pressagain = false; + } + else + { + InputMethods.performKeyRelease(kvpKey); + pressagain = false; + } + } } + globalState.SaveToPrevious(false); + + syncStateLock.ExitWriteLock(); state.SaveToPrevious(true); } From 4b0134faf9c2421487c91ab589ff26f968172e66 Mon Sep 17 00:00:00 2001 From: mika-n Date: Tue, 19 Feb 2019 15:19:10 +0200 Subject: [PATCH 49/66] merge --- DS4Windows/DS4Control/Mapping.cs | 444 +++++++++++++++++++++++++++++++ DS4Windows/DS4Windows.csproj | 1 + 2 files changed, 445 insertions(+) diff --git a/DS4Windows/DS4Control/Mapping.cs b/DS4Windows/DS4Control/Mapping.cs index 9a81c48..c9f5175 100644 --- a/DS4Windows/DS4Control/Mapping.cs +++ b/DS4Windows/DS4Control/Mapping.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using System.Diagnostics; using static DS4Windows.Global; +using System.Drawing; // Point struct namespace DS4Windows { @@ -1602,6 +1603,11 @@ namespace DS4Windows if (macroControl[24]) MappedState.RY = 0; } + if (GetSASteeringWheelEmulationAxis(device) != SASteeringWheelEmulationAxisType.None) + { + MappedState.SASteeringWheelEmulationUnit = Mapping.Scale360degreeGyroAxis(device, eState, ctrl); + } + calculateFinalMouseMovement(ref tempMouseDeltaX, ref tempMouseDeltaY, out mouseDeltaX, out mouseDeltaY); if (mouseDeltaX != 0 || mouseDeltaY != 0) @@ -1916,6 +1922,25 @@ namespace DS4Windows } actionDone[index].dev[device] = true; } + else if (action.typeID == SpecialAction.ActionTypeId.SASteeringWheelEmulationCalibrate) + { + actionFound = true; + + DS4Device d = ctrl.DS4Controllers[device]; + // If controller is not already in SASteeringWheelCalibration state then enable it now. If calibration is active then complete it (commit calibration values) + if (d.WheelRecalibrateActiveState == 0 && DateTime.UtcNow > (action.firstTap + TimeSpan.FromMilliseconds(3000))) + { + action.firstTap = DateTime.UtcNow; + d.WheelRecalibrateActiveState = 1; // Start calibration process + } + else if (d.WheelRecalibrateActiveState == 2 && DateTime.UtcNow > (action.firstTap + TimeSpan.FromMilliseconds(3000))) + { + action.firstTap = DateTime.UtcNow; + d.WheelRecalibrateActiveState = 3; // Complete calibration process + } + + actionDone[index].dev[device] = true; + } } else { @@ -3665,5 +3690,424 @@ namespace DS4Windows fieldMap.buttons[controlNum] = false; } } + + // BEGIN: SixAxis steering wheel emulation logic + + private const int C_WHEEL_ANGLE_PRECISION = 10; // 1=precision of one degree, 10=precision of 1/10 of degree. Bigger number means fine graned precision + private const int C_WHEEL_ANGLE_PRECISION_DECIMALS = (C_WHEEL_ANGLE_PRECISION == 1 ? 0 : C_WHEEL_ANGLE_PRECISION / 10); + + // "In-game" calibration process: + // - Place controller at "steering wheel center" position and press "Calibrate SA steering wheel" special action button to start the calibration + // - Hold the controller still for a while at center point and press "X" + // - Turn the controller at 90 degree left or right position and hold still for few seconds and press "X" + // - Turn the controller at 90 degree position on the opposite side and press "X" + // - Now you can check the calibratio by turning the wheel and see when the green lightbar starts to blink (it should blink at those three calibrated positions) + // - Press "Calibrate SA steering wheel" special action key to accept the calibration (result is saved to ControllerConfigs.xml xml file) + // + private static readonly DS4Color calibrationColor_0 = new DS4Color { red = 0xA0, green = 0x00, blue = 0x00 }; + private static readonly DS4Color calibrationColor_1 = new DS4Color { red = 0xFF, green = 0xFF, blue = 0x00 }; + private static readonly DS4Color calibrationColor_2 = new DS4Color { red = 0x00, green = 0x50, blue = 0x50 }; + private static readonly DS4Color calibrationColor_3 = new DS4Color { red = 0x00, green = 0xC0, blue = 0x00 }; + + private static DateTime latestDebugMsgTime; + private static string latestDebugData; + private static void LogToGuiSACalibrationDebugMsg(string data, bool forceOutput = false) + { + // Print debug calibration log messages only once per 2 secs to avoid flooding the log receiver + DateTime curTime = DateTime.Now; + if (forceOutput || ((TimeSpan)(curTime - latestDebugMsgTime)).TotalSeconds > 2) + { + latestDebugMsgTime = curTime; + if (data != latestDebugData) + { + AppLogger.LogToGui(data, false); + latestDebugData = data; + } + } + } + + // Return number of bits set in a value + protected static int CountNumOfSetBits(int bitValue) + { + int count = 0; + while (bitValue != 0) + { + count++; + bitValue &= (bitValue - 1); + } + return count; + } + + // Calculate and return the angle of the controller as -180...0...+180 value. + private static Int32 CalculateControllerAngle(int gyroAccelX, int gyroAccelZ, DS4Device controller) + { + Int32 result; + + if (gyroAccelX == controller.wheelCenterPoint.X && Math.Abs(gyroAccelZ - controller.wheelCenterPoint.Y) <= 1) + { + // When the current gyro position is "close enough" the wheel center point then no need to go through the hassle of calculating an angle + result = 0; + } + else + { + // Calculate two vectors based on "circle center" (ie. circle represents the 360 degree wheel turn and wheelCenterPoint and currentPosition vectors both start from circle center). + // To improve accuracy both left and right turns use a decicated calibration "circle" because DS4 gyro and DoItYourselfWheelRig may return slightly different SA sensor values depending on the tilt direction (well, only one or two degree difference so nothing major). + Point vectorAB; + Point vectorCD; + + if (gyroAccelX >= controller.wheelCenterPoint.X) + { + // "DS4 gyro wheel" tilted to right + vectorAB = new Point(controller.wheelCenterPoint.X - controller.wheelCircleCenterPointRight.X, controller.wheelCenterPoint.Y - controller.wheelCircleCenterPointRight.Y); + vectorCD = new Point(gyroAccelX - controller.wheelCircleCenterPointRight.X, gyroAccelZ - controller.wheelCircleCenterPointRight.Y); + } + else + { + // "DS4 gyro wheel" tilted to left + vectorAB = new Point(controller.wheelCenterPoint.X - controller.wheelCircleCenterPointLeft.X, controller.wheelCenterPoint.Y - controller.wheelCircleCenterPointLeft.Y); + vectorCD = new Point(gyroAccelX - controller.wheelCircleCenterPointLeft.X, gyroAccelZ - controller.wheelCircleCenterPointLeft.Y); + } + + // Calculate dot product and magnitude of vectors (center vector and the current tilt vector) + double dotProduct = vectorAB.X * vectorCD.X + vectorAB.Y * vectorCD.Y; + double magAB = Math.Sqrt(vectorAB.X * vectorAB.X + vectorAB.Y * vectorAB.Y); + double magCD = Math.Sqrt(vectorCD.X * vectorCD.X + vectorCD.Y * vectorCD.Y); + + // Calculate angle between vectors and convert radian to degrees + if (magAB == 0 || magCD == 0) + { + result = 0; + } + else + { + double angle = Math.Acos(dotProduct / (magAB * magCD)); + result = Convert.ToInt32(Global.Clamp( + -180.0 * C_WHEEL_ANGLE_PRECISION, + Math.Round((angle * (180.0 / Math.PI)), C_WHEEL_ANGLE_PRECISION_DECIMALS) * C_WHEEL_ANGLE_PRECISION, + 180.0 * C_WHEEL_ANGLE_PRECISION) + ); + } + + // Left turn is -180..0 and right turn 0..180 degrees + if (gyroAccelX < controller.wheelCenterPoint.X) result = -result; + } + + return result; + } + + // Calibrate sixaxis steering wheel emulation. Use DS4Windows configuration screen to start a calibration or press a special action key (if defined) + private static void SAWheelEmulationCalibration(int device, DS4StateExposed exposedState, ControlService ctrl, DS4State currentDeviceState, DS4Device controller) + { + int gyroAccelX, gyroAccelZ; + int result; + + gyroAccelX = exposedState.getAccelX(); + gyroAccelZ = exposedState.getAccelZ(); + //gyroAccelX = exposedState.OutputAccelX; + //gyroAccelZ = exposedState.OutputAccelZ; + + // State 0=Normal mode (ie. calibration process is not running), 1=Activating calibration, 2=Calibration process running, 3=Completing calibration, 4=Cancelling calibration + if (controller.WheelRecalibrateActiveState == 1) + { + AppLogger.LogToGui($"Controller {ctrl.x360Bus.FirstController + device} activated re-calibration of SA steering wheel emulation", false); + + controller.WheelRecalibrateActiveState = 2; + + controller.wheelPrevPhysicalAngle = 0; + controller.wheelPrevFullAngle = 0; + controller.wheelFullTurnCount = 0; + + // Clear existing calibration value and use current position as "center" point. + // This initial center value may be off-center because of shaking the controller while button was pressed. The value will be overriden with correct value once controller is stabilized and hold still few secs at the center point + controller.wheelCenterPoint.X = gyroAccelX; + controller.wheelCenterPoint.Y = gyroAccelZ; + controller.wheel90DegPointRight.X = gyroAccelX + 20; + controller.wheel90DegPointLeft.X = gyroAccelX - 20; + + // Clear bitmask for calibration points. All three calibration points need to be set before re-calibration process is valid + controller.wheelCalibratedAxisBitmask = DS4Device.WheelCalibrationPoint.None; + + controller.wheelPrevRecalibrateTime = new DateTime(2500, 1, 1); + } + else if (controller.WheelRecalibrateActiveState == 3) + { + AppLogger.LogToGui($"Controller {ctrl.x360Bus.FirstController + device} completed the calibration of SA steering wheel emulation. center=({controller.wheelCenterPoint.X}, {controller.wheelCenterPoint.Y}) 90L=({controller.wheel90DegPointLeft.X}, {controller.wheel90DegPointLeft.Y}) 90R=({controller.wheel90DegPointRight.X}, {controller.wheel90DegPointRight.Y})", false); + + // If any of the calibration points (center, left 90deg, right 90deg) are missing then reset back to default calibration values + if (((controller.wheelCalibratedAxisBitmask & DS4Device.WheelCalibrationPoint.All) == DS4Device.WheelCalibrationPoint.All)) + Global.SaveControllerConfigs(controller); + else + controller.wheelCenterPoint.X = controller.wheelCenterPoint.Y = 0; + + controller.WheelRecalibrateActiveState = 0; + controller.wheelPrevRecalibrateTime = DateTime.Now; + } + else if (controller.WheelRecalibrateActiveState == 4) + { + AppLogger.LogToGui($"Controller {ctrl.x360Bus.FirstController + device} cancelled the calibration of SA steering wheel emulation.", false); + + controller.WheelRecalibrateActiveState = 0; + controller.wheelPrevRecalibrateTime = DateTime.Now; + } + + if (controller.WheelRecalibrateActiveState > 0) + { + // Cross "X" key pressed. Set calibration point when the key is released and controller hold steady for a few seconds + if (currentDeviceState.Cross == true) controller.wheelPrevRecalibrateTime = DateTime.Now; + + // Make sure controller is hold steady (velocity of gyro axis) to avoid misaligments and set calibration few secs after the "X" key was released + if (Math.Abs(currentDeviceState.Motion.angVelPitch) < 0.5 && Math.Abs(currentDeviceState.Motion.angVelYaw) < 0.5 && Math.Abs(currentDeviceState.Motion.angVelRoll) < 0.5 + && ((TimeSpan)(DateTime.Now - controller.wheelPrevRecalibrateTime)).TotalSeconds > 1) + { + controller.wheelPrevRecalibrateTime = new DateTime(2500, 1, 1); + + if (controller.wheelCalibratedAxisBitmask == DS4Device.WheelCalibrationPoint.None) + { + controller.wheelCenterPoint.X = gyroAccelX; + controller.wheelCenterPoint.Y = gyroAccelZ; + + controller.wheelCalibratedAxisBitmask |= DS4Device.WheelCalibrationPoint.Center; + } + else if (controller.wheel90DegPointRight.X < gyroAccelX) + { + controller.wheel90DegPointRight.X = gyroAccelX; + controller.wheel90DegPointRight.Y = gyroAccelZ; + controller.wheelCircleCenterPointRight.X = controller.wheelCenterPoint.X; + controller.wheelCircleCenterPointRight.Y = controller.wheel90DegPointRight.Y; + + controller.wheelCalibratedAxisBitmask |= DS4Device.WheelCalibrationPoint.Right90; + } + else if (controller.wheel90DegPointLeft.X > gyroAccelX) + { + controller.wheel90DegPointLeft.X = gyroAccelX; + controller.wheel90DegPointLeft.Y = gyroAccelZ; + controller.wheelCircleCenterPointLeft.X = controller.wheelCenterPoint.X; + controller.wheelCircleCenterPointLeft.Y = controller.wheel90DegPointLeft.Y; + + controller.wheelCalibratedAxisBitmask |= DS4Device.WheelCalibrationPoint.Left90; + } + } + + // Show lightbar color feedback how the calibration process is proceeding. + // red / yellow / blue / green = No calibration anchors/one anchor/two anchors/all three anchors calibrated when color turns to green (center, 90DegLeft, 90DegRight). + int bitsSet = CountNumOfSetBits((int)controller.wheelCalibratedAxisBitmask); + if (bitsSet >= 3) DS4LightBar.forcedColor[device] = calibrationColor_3; + else if (bitsSet == 2) DS4LightBar.forcedColor[device] = calibrationColor_2; + else if (bitsSet == 1) DS4LightBar.forcedColor[device] = calibrationColor_1; + else DS4LightBar.forcedColor[device] = calibrationColor_0; + + result = CalculateControllerAngle(gyroAccelX, gyroAccelZ, controller); + + // Force lightbar flashing when controller is currently at calibration point (user can verify the calibration before accepting it by looking at flashing lightbar) + if (((controller.wheelCalibratedAxisBitmask & DS4Device.WheelCalibrationPoint.Center) != 0 && Math.Abs(result) <= 1 * C_WHEEL_ANGLE_PRECISION) + || ((controller.wheelCalibratedAxisBitmask & DS4Device.WheelCalibrationPoint.Left90) != 0 && result <= -89 * C_WHEEL_ANGLE_PRECISION && result >= -91 * C_WHEEL_ANGLE_PRECISION) + || ((controller.wheelCalibratedAxisBitmask & DS4Device.WheelCalibrationPoint.Right90) != 0 && result >= 89 * C_WHEEL_ANGLE_PRECISION && result <= 91 * C_WHEEL_ANGLE_PRECISION) + || ((controller.wheelCalibratedAxisBitmask & DS4Device.WheelCalibrationPoint.Left90) != 0 && Math.Abs(result) >= 179 * C_WHEEL_ANGLE_PRECISION)) + DS4LightBar.forcedFlash[device] = 2; + else + DS4LightBar.forcedFlash[device] = 0; + + DS4LightBar.forcelight[device] = true; + + LogToGuiSACalibrationDebugMsg($"Calibration values ({gyroAccelX}, {gyroAccelZ}) angle={result / (1.0 * C_WHEEL_ANGLE_PRECISION)}\n"); + } + else + { + // Re-calibration completed or cancelled. Set lightbar color back to normal color + DS4LightBar.forcedFlash[device] = 0; + DS4LightBar.forcedColor[device] = Global.getMainColor(device); + DS4LightBar.forcelight[device] = false; + DS4LightBar.updateLightBar(controller, device); + } + } + + protected static Int32 Scale360degreeGyroAxis(int device, DS4StateExposed exposedState, ControlService ctrl) + { + unchecked + { + DS4Device controller; + DS4State currentDeviceState; + + int gyroAccelX, gyroAccelZ; + int result; + + controller = ctrl.DS4Controllers[device]; + if (controller == null) return 0; + + currentDeviceState = controller.getCurrentStateRef(); + + // If calibration is active then do the calibration process instead of the normal "angle calculation" + if (controller.WheelRecalibrateActiveState > 0) + { + SAWheelEmulationCalibration(device, exposedState, ctrl, currentDeviceState, controller); + + // Return center wheel position while SA wheel emuation is being calibrated + return 0; + } + + gyroAccelX = exposedState.getAccelX(); + gyroAccelZ = exposedState.getAccelZ(); + //gyroAccelX = exposedState.OutputAccelX; + //gyroAccelZ = exposedState.OutputAccelZ; + + // If calibration values are missing then use "educated guesses" about good starting values + if (controller.wheelCenterPoint.IsEmpty) + { + if (!Global.LoadControllerConfigs(controller)) + { + AppLogger.LogToGui($"Controller {ctrl.x360Bus.FirstController + device} sixaxis steering wheel calibration data missing. It is recommended to run steering wheel calibration process by pressing SASteeringWheelEmulationCalibration special action key. Using estimated values until the controller is calibrated at least once.", false); + + // Use current controller position as "center point". Assume DS4Windows was started while controller was hold in center position (yes, dangerous assumption but can't do much until controller is calibrated) + controller.wheelCenterPoint.X = gyroAccelX; + controller.wheelCenterPoint.Y = gyroAccelZ; + + controller.wheel90DegPointRight.X = controller.wheelCenterPoint.X + 113; + controller.wheel90DegPointRight.Y = controller.wheelCenterPoint.Y + 110; + + controller.wheel90DegPointLeft.X = controller.wheelCenterPoint.X - 127; + controller.wheel90DegPointLeft.Y = controller.wheel90DegPointRight.Y; + } + + controller.wheelCircleCenterPointRight.X = controller.wheelCenterPoint.X; + controller.wheelCircleCenterPointRight.Y = controller.wheel90DegPointRight.Y; + controller.wheelCircleCenterPointLeft.X = controller.wheelCenterPoint.X; + controller.wheelCircleCenterPointLeft.Y = controller.wheel90DegPointLeft.Y; + + AppLogger.LogToGui($"Controller {ctrl.x360Bus.FirstController + device} steering wheel emulation calibration values. center=({controller.wheelCenterPoint.X}, {controller.wheelCenterPoint.Y}) 90L=({controller.wheel90DegPointLeft.X}, {controller.wheel90DegPointLeft.Y}) 90R=({controller.wheel90DegPointRight.X}, {controller.wheel90DegPointRight.Y})", false); + controller.wheelPrevRecalibrateTime = DateTime.Now; + } + + + int maxRangeRight = Global.GetSASteeringWheelEmulationRange(device) / 2 * C_WHEEL_ANGLE_PRECISION; + int maxRangeLeft = -maxRangeRight; + + result = CalculateControllerAngle(gyroAccelX, gyroAccelZ, controller); + + // Apply deadzone (SA X-deadzone value). This code assumes that 20deg is the max deadzone anyone ever might wanna use (in practice effective deadzone + // is probably just few degrees by using SXDeadZone values 0.01...0.05) + double sxDead = getSXDeadzone(device); + if (sxDead > 0 && result != 0 && Math.Abs(result) < (20.0 * C_WHEEL_ANGLE_PRECISION * sxDead)) + { + result = 0; + } + + // If wrapped around from +180 to -180 side (or vice versa) then SA steering wheel keeps on turning beyond 360 degrees (if range is >360) + int wheelFullTurnCount = controller.wheelFullTurnCount; + if (controller.wheelPrevPhysicalAngle < 0 && result > 0) + { + if ((result - controller.wheelPrevPhysicalAngle) > 180 * C_WHEEL_ANGLE_PRECISION) + if (maxRangeRight > 360 * C_WHEEL_ANGLE_PRECISION) + wheelFullTurnCount--; + else + result = maxRangeLeft; + } + else if (controller.wheelPrevPhysicalAngle > 0 && result < 0) + { + if ((controller.wheelPrevPhysicalAngle - result) > 180 * C_WHEEL_ANGLE_PRECISION) + if (maxRangeRight > 360 * C_WHEEL_ANGLE_PRECISION) + wheelFullTurnCount++; + else + result = maxRangeRight; + } + controller.wheelPrevPhysicalAngle = result; + + if (wheelFullTurnCount != 0) + { + if (wheelFullTurnCount > 0) + result = (wheelFullTurnCount * 180 * C_WHEEL_ANGLE_PRECISION) + ((wheelFullTurnCount * 180 * C_WHEEL_ANGLE_PRECISION) + result); + else + result = (wheelFullTurnCount * 180 * C_WHEEL_ANGLE_PRECISION) - ((wheelFullTurnCount * -180 * C_WHEEL_ANGLE_PRECISION) - result); + } + + // If the new angle is more than 180 degrees further away then this is probably bogus value (controller shaking too much and gyro and velocity sensors went crazy). + // Accept the new angle only when the new angle is within a "stability threshold", otherwise use the previous full angle value. + if (Math.Abs(result - controller.wheelPrevFullAngle) <= 180 * C_WHEEL_ANGLE_PRECISION) + { + controller.wheelPrevFullAngle = result; + controller.wheelFullTurnCount = wheelFullTurnCount; + } + else + { + result = controller.wheelPrevFullAngle; + } + + result = Mapping.ClampInt(maxRangeLeft, result, maxRangeRight); + + // Debug log output of SA sensor values + //LogToGuiSACalibrationDebugMsg($"DBG gyro=({gyroAccelX}, {gyroAccelZ}) output=({exposedState.OutputAccelX}, {exposedState.OutputAccelZ}) PitRolYaw=({currentDeviceState.Motion.gyroPitch}, {currentDeviceState.Motion.gyroRoll}, {currentDeviceState.Motion.gyroYaw}) VelPitRolYaw=({currentDeviceState.Motion.angVelPitch}, {currentDeviceState.Motion.angVelRoll}, {currentDeviceState.Motion.angVelYaw}) angle={result / (1.0 * C_WHEEL_ANGLE_PRECISION)} fullTurns={controller.wheelFullTurnCount}", false); + + // Apply anti-deadzone (SA X-antideadzone value) + double sxAntiDead = getSXAntiDeadzone(device); + + switch (Global.GetSASteeringWheelEmulationAxis(device)) + { + case SASteeringWheelEmulationAxisType.LX: + case SASteeringWheelEmulationAxisType.LY: + case SASteeringWheelEmulationAxisType.RX: + case SASteeringWheelEmulationAxisType.RY: + // DS4 thumbstick axis output (-32768..32767 raw value range) + //return (((result - maxRangeLeft) * (32767 - (-32768))) / (maxRangeRight - maxRangeLeft)) + (-32768); + if (result == 0) return 0; + + if (sxAntiDead > 0) + { + sxAntiDead *= 32767; + if (result < 0) return (((result - maxRangeLeft) * (-Convert.ToInt32(sxAntiDead) - (-32768))) / (0 - maxRangeLeft)) + (-32768); + else return (((result - 0) * (32767 - (Convert.ToInt32(sxAntiDead)))) / (maxRangeRight - 0)) + (Convert.ToInt32(sxAntiDead)); + } + else + { + return (((result - maxRangeLeft) * (32767 - (-32768))) / (maxRangeRight - maxRangeLeft)) + (-32768); + } + + case SASteeringWheelEmulationAxisType.L2R2: + // DS4 Trigger axis output. L2+R2 triggers share the same axis in x360 xInput/DInput controller, + // so L2+R2 steering output supports only 360 turn range (-255..255 raw value range in the shared trigger axis) + // return (((result - (-180)) * (255 - (-255))) / (180 - (-180))) + (-255); + if (result == 0) return 0; + + result = Convert.ToInt32(Math.Round(result / (1.0 * C_WHEEL_ANGLE_PRECISION))); + if (result < 0) result = -181 - result; + + if (sxAntiDead > 0) + { + sxAntiDead *= 255; + if (result < 0) return (((result - (-180)) * (-Convert.ToInt32(sxAntiDead) - (-255))) / (0 - (-180))) + (-255); + else return (((result - (0)) * (255 - (Convert.ToInt32(sxAntiDead)))) / (180 - (0))) + (Convert.ToInt32(sxAntiDead)); + } + else + { + return (((result - (-180)) * (255 - (-255))) / (180 - (-180))) + (-255); + } + + case SASteeringWheelEmulationAxisType.VJoy1X: + case SASteeringWheelEmulationAxisType.VJoy1Y: + case SASteeringWheelEmulationAxisType.VJoy1Z: + case SASteeringWheelEmulationAxisType.VJoy2X: + case SASteeringWheelEmulationAxisType.VJoy2Y: + case SASteeringWheelEmulationAxisType.VJoy2Z: + // SASteeringWheelEmulationAxisType.VJoy1X/VJoy1Y/VJoy1Z/VJoy2X/VJoy2Y/VJoy2Z VJoy axis output (0..32767 raw value range by default) + // return (((result - maxRangeLeft) * (32767 - (-0))) / (maxRangeRight - maxRangeLeft)) + (-0); + if (result == 0) return 16384; + + if (sxAntiDead > 0) + { + sxAntiDead *= 16384; + if (result < 0) return (((result - maxRangeLeft) * (16384 - Convert.ToInt32(sxAntiDead) - (-0))) / (0 - maxRangeLeft)) + (-0); + else return (((result - 0) * (32767 - (16384 + Convert.ToInt32(sxAntiDead)))) / (maxRangeRight - 0)) + (16384 + Convert.ToInt32(sxAntiDead)); + } + else + { + return (((result - maxRangeLeft) * (32767 - (-0))) / (maxRangeRight - maxRangeLeft)) + (-0); + } + + default: + // Should never come here, but C# case statement syntax requires DEFAULT handler + return 0; + } + } + } + // END: SixAxis steering wheel emulation logic + } } diff --git a/DS4Windows/DS4Windows.csproj b/DS4Windows/DS4Windows.csproj index 46fc663..7a1ae54 100644 --- a/DS4Windows/DS4Windows.csproj +++ b/DS4Windows/DS4Windows.csproj @@ -298,6 +298,7 @@ DS4Form.cs + Designer DS4Form.cs From 48bd457d668863d794bf10011e660141231b0c2d Mon Sep 17 00:00:00 2001 From: mika-n Date: Tue, 19 Feb 2019 15:19:45 +0200 Subject: [PATCH 50/66] merge --- DS4Windows/DS4Control/Mapping.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/DS4Windows/DS4Control/Mapping.cs b/DS4Windows/DS4Control/Mapping.cs index c9f5175..9cae578 100644 --- a/DS4Windows/DS4Control/Mapping.cs +++ b/DS4Windows/DS4Control/Mapping.cs @@ -6,7 +6,6 @@ using System.Threading; using System.Threading.Tasks; using System.Diagnostics; using static DS4Windows.Global; - using System.Drawing; // Point struct namespace DS4Windows From e70aa452e34e9ea6660841f236c20a3a98784d00 Mon Sep 17 00:00:00 2001 From: mika-n Date: Tue, 19 Feb 2019 15:29:33 +0200 Subject: [PATCH 51/66] removed unnecessary using System.Draw reference. --- DS4Windows/DS4Control/X360Device.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/DS4Windows/DS4Control/X360Device.cs b/DS4Windows/DS4Control/X360Device.cs index e0873e2..f794d5e 100644 --- a/DS4Windows/DS4Control/X360Device.cs +++ b/DS4Windows/DS4Control/X360Device.cs @@ -4,8 +4,6 @@ using System.Collections.Generic; using System.Runtime.InteropServices; using Microsoft.Win32.SafeHandles; -using System.Drawing; // Point struct - namespace DS4Windows { public class X360Device : ScpDevice From a3c51c8688be204993486f48510ec1632eed2c77 Mon Sep 17 00:00:00 2001 From: mika-n Date: Wed, 20 Feb 2019 08:39:55 +0200 Subject: [PATCH 52/66] merge --- DS4Windows/DS4Forms/Options.Designer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/DS4Windows/DS4Forms/Options.Designer.cs b/DS4Windows/DS4Forms/Options.Designer.cs index 386cea7..f9cf0af 100644 --- a/DS4Windows/DS4Forms/Options.Designer.cs +++ b/DS4Windows/DS4Forms/Options.Designer.cs @@ -4294,7 +4294,6 @@ this.pnlLSTrack.ResumeLayout(false); this.pnlRSTrack.ResumeLayout(false); this.fLPTiltControls.ResumeLayout(false); - this.fLPTiltControls.PerformLayout(); this.tCControls.ResumeLayout(false); this.tPControls.ResumeLayout(false); this.pnlController.ResumeLayout(false); From abad91ca2a01eb570273ddb5baf632383def7a36 Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Fri, 22 Feb 2019 01:50:50 -0600 Subject: [PATCH 53/66] Changed class name to remove VS name violation warning --- DS4Windows/VJoyFeeder/vJoyFeeder.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/DS4Windows/VJoyFeeder/vJoyFeeder.cs b/DS4Windows/VJoyFeeder/vJoyFeeder.cs index fcee9ff..1e6a398 100644 --- a/DS4Windows/VJoyFeeder/vJoyFeeder.cs +++ b/DS4Windows/VJoyFeeder/vJoyFeeder.cs @@ -107,7 +107,7 @@ namespace DS4Windows.VJoyFeeder //namespace vJoyInterfaceWrap //{ [SuppressUnmanagedCodeSecurity] - public class vJoy + public class VJoy { /***************************************************/ @@ -634,7 +634,7 @@ namespace DS4Windows.VJoyFeeder static bool vJoyInitialized = false; static bool vJoyAvailable = false; - static vJoy vJoyObj = null; + static VJoy vJoyObj = null; vJoyFeeder() { @@ -657,7 +657,7 @@ namespace DS4Windows.VJoyFeeder try { - if (vJoyObj == null) vJoyObj = new vJoy(); + if (vJoyObj == null) vJoyObj = new VJoy(); if (vJoyObj.vJoyEnabled() && vJoyObj.GetVJDAxisExist(vJoyID, axis)) { From afea15f38f7a1627314c73cca33b8f960b31abca Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Fri, 22 Feb 2019 01:51:54 -0600 Subject: [PATCH 54/66] Output report len is constant No need to pull from property every poll --- DS4Windows/DS4Control/X360Device.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DS4Windows/DS4Control/X360Device.cs b/DS4Windows/DS4Control/X360Device.cs index f794d5e..256d817 100644 --- a/DS4Windows/DS4Control/X360Device.cs +++ b/DS4Windows/DS4Control/X360Device.cs @@ -100,7 +100,7 @@ namespace DS4Windows Output[4] = (Byte)(device + firstController); Output[9] = 0x14; - for (int i = 10, outLen = Output.Length; i < outLen; i++) + for (int i = 10; i < 28; i++) { Output[i] = 0; } From 4c577b22a78b62c73c0d1d2caa2520cc9dd4b6d2 Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Fri, 22 Feb 2019 01:55:56 -0600 Subject: [PATCH 55/66] Added mika-n as a contributor --- contributors.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/contributors.txt b/contributors.txt index 0514e44..b865773 100644 --- a/contributors.txt +++ b/contributors.txt @@ -1,5 +1,6 @@ Travis Nickles (Ryochan7) Korney Czukowski (czukowski) +mika-n jdfeng justalemon Rajko Stojadinovic (rajkosto) From 668ecafe6c9ac2800e2ec2584f707f4381e86272 Mon Sep 17 00:00:00 2001 From: mika-n Date: Sun, 24 Feb 2019 00:27:48 +0200 Subject: [PATCH 56/66] Check synchronized state of controller before trying to load calibation values (SonyWA connected devices could be in non-sync state without a valid controller MAC address) --- DS4Windows/DS4Control/Mapping.cs | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/DS4Windows/DS4Control/Mapping.cs b/DS4Windows/DS4Control/Mapping.cs index 9cae578..f2a60fc 100644 --- a/DS4Windows/DS4Control/Mapping.cs +++ b/DS4Windows/DS4Control/Mapping.cs @@ -3690,19 +3690,11 @@ namespace DS4Windows } } - // BEGIN: SixAxis steering wheel emulation logic - private const int C_WHEEL_ANGLE_PRECISION = 10; // 1=precision of one degree, 10=precision of 1/10 of degree. Bigger number means fine graned precision - private const int C_WHEEL_ANGLE_PRECISION_DECIMALS = (C_WHEEL_ANGLE_PRECISION == 1 ? 0 : C_WHEEL_ANGLE_PRECISION / 10); + // SA steering wheel emulation mapping - // "In-game" calibration process: - // - Place controller at "steering wheel center" position and press "Calibrate SA steering wheel" special action button to start the calibration - // - Hold the controller still for a while at center point and press "X" - // - Turn the controller at 90 degree left or right position and hold still for few seconds and press "X" - // - Turn the controller at 90 degree position on the opposite side and press "X" - // - Now you can check the calibratio by turning the wheel and see when the green lightbar starts to blink (it should blink at those three calibrated positions) - // - Press "Calibrate SA steering wheel" special action key to accept the calibration (result is saved to ControllerConfigs.xml xml file) - // + private const int C_WHEEL_ANGLE_PRECISION = 10; // Precision of SA angle in 1/10 of degrees + private static readonly DS4Color calibrationColor_0 = new DS4Color { red = 0xA0, green = 0x00, blue = 0x00 }; private static readonly DS4Color calibrationColor_1 = new DS4Color { red = 0xFF, green = 0xFF, blue = 0x00 }; private static readonly DS4Color calibrationColor_2 = new DS4Color { red = 0x00, green = 0x50, blue = 0x50 }; @@ -3782,7 +3774,7 @@ namespace DS4Windows double angle = Math.Acos(dotProduct / (magAB * magCD)); result = Convert.ToInt32(Global.Clamp( -180.0 * C_WHEEL_ANGLE_PRECISION, - Math.Round((angle * (180.0 / Math.PI)), C_WHEEL_ANGLE_PRECISION_DECIMALS) * C_WHEEL_ANGLE_PRECISION, + Math.Round((angle * (180.0 / Math.PI)), 1) * C_WHEEL_ANGLE_PRECISION, 180.0 * C_WHEEL_ANGLE_PRECISION) ); } @@ -3802,8 +3794,6 @@ namespace DS4Windows gyroAccelX = exposedState.getAccelX(); gyroAccelZ = exposedState.getAccelZ(); - //gyroAccelX = exposedState.OutputAccelX; - //gyroAccelZ = exposedState.OutputAccelZ; // State 0=Normal mode (ie. calibration process is not running), 1=Activating calibration, 2=Calibration process running, 3=Completing calibration, 4=Cancelling calibration if (controller.WheelRecalibrateActiveState == 1) @@ -3944,10 +3934,12 @@ namespace DS4Windows return 0; } + // Do nothing if connection is active but the actual DS4 controller is still missing or not yet synchronized + if (!controller.Synced) + return 0; + gyroAccelX = exposedState.getAccelX(); gyroAccelZ = exposedState.getAccelZ(); - //gyroAccelX = exposedState.OutputAccelX; - //gyroAccelZ = exposedState.OutputAccelZ; // If calibration values are missing then use "educated guesses" about good starting values if (controller.wheelCenterPoint.IsEmpty) @@ -4106,7 +4098,6 @@ namespace DS4Windows } } } - // END: SixAxis steering wheel emulation logic } } From f4819d4a3ea0ef635ea79c169a472fb5a0749ed5 Mon Sep 17 00:00:00 2001 From: Travis Nickles Date: Sat, 23 Feb 2019 21:11:15 -0600 Subject: [PATCH 57/66] Added Discord link to README --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index c310ec9..329fc27 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,10 @@ you've used a 360 controller before) or built in pc). Toshiba's adapters currently do not work. - Disable Steam Controller Mapping support in Steam +## Social + +[Discord](https://discord.gg/zrpPgyN) + ## Device Detection Issue If your DS4 is not detected by DS4Windows and the lightbar continues to From 7f0ebb955dda2282fdc6f32c179f3f59ce351ab7 Mon Sep 17 00:00:00 2001 From: mika-n Date: Sun, 24 Feb 2019 21:05:24 +0200 Subject: [PATCH 58/66] Updated missing Finnish translations in ResourcesFI file and changed few resource strings public just like other resources are (few items were accidentally private) --- DS4Windows/Properties/Resources.Designer.cs | 14 +++--- DS4Windows/Properties/Resources.fi.resx | 53 ++++++++++++++++++++- 2 files changed, 59 insertions(+), 8 deletions(-) diff --git a/DS4Windows/Properties/Resources.Designer.cs b/DS4Windows/Properties/Resources.Designer.cs index d468473..60e5a65 100644 --- a/DS4Windows/Properties/Resources.Designer.cs +++ b/DS4Windows/Properties/Resources.Designer.cs @@ -1630,7 +1630,7 @@ namespace DS4Windows.Properties { /// /// Looks up a localized string similar to Calibration of sixaxis wheel emulation. /// - internal static string SASteeringWheelEmulationCalibrate { + public static string SASteeringWheelEmulationCalibrate { get { return ResourceManager.GetString("SASteeringWheelEmulationCalibrate", resourceCulture); } @@ -1639,7 +1639,7 @@ namespace DS4Windows.Properties { /// /// Looks up a localized string similar to All calibraton points are set when lightbar color turns to green. While turning the controller the lightbar color flashes when the controller is at calibration point. Accept calibration with OK button. /// - internal static string SASteeringWheelEmulationCalibrateInstruction { + public static string SASteeringWheelEmulationCalibrateInstruction { get { return ResourceManager.GetString("SASteeringWheelEmulationCalibrateInstruction", resourceCulture); } @@ -1648,7 +1648,7 @@ namespace DS4Windows.Properties { /// /// Looks up a localized string similar to (1) Center the controller, hold it steady and press "X". /// - internal static string SASteeringWheelEmulationCalibrateInstruction1 { + public static string SASteeringWheelEmulationCalibrateInstruction1 { get { return ResourceManager.GetString("SASteeringWheelEmulationCalibrateInstruction1", resourceCulture); } @@ -1657,7 +1657,7 @@ namespace DS4Windows.Properties { /// /// Looks up a localized string similar to (2) Turn to 90° left (or right) position and press "X". /// - internal static string SASteeringWheelEmulationCalibrateInstruction2 { + public static string SASteeringWheelEmulationCalibrateInstruction2 { get { return ResourceManager.GetString("SASteeringWheelEmulationCalibrateInstruction2", resourceCulture); } @@ -1666,7 +1666,7 @@ namespace DS4Windows.Properties { /// /// Looks up a localized string similar to (3) Turn to 90° right (or left) position and press "X". /// - internal static string SASteeringWheelEmulationCalibrateInstruction3 { + public static string SASteeringWheelEmulationCalibrateInstruction3 { get { return ResourceManager.GetString("SASteeringWheelEmulationCalibrateInstruction3", resourceCulture); } @@ -1675,7 +1675,7 @@ namespace DS4Windows.Properties { /// /// Looks up a localized string similar to Cannot calibrate gyro (sixaxis) steering wheel emulation values without a controller. Connect a controller via bluetooth or usb. /// - internal static string SASteeringWheelEmulationCalibrateNoControllerError { + public static string SASteeringWheelEmulationCalibrateNoControllerError { get { return ResourceManager.GetString("SASteeringWheelEmulationCalibrateNoControllerError", resourceCulture); } @@ -1684,7 +1684,7 @@ namespace DS4Windows.Properties { /// /// Looks up a localized string similar to Gyro steering wheel emulation axis option is set to NONE (emulation is not used). Please select an axis option before calibrating the sixaxis gyro steering wheel emulation. /// - internal static string SASteeringWheelEmulationCalibrateNoneAxisError { + public static string SASteeringWheelEmulationCalibrateNoneAxisError { get { return ResourceManager.GetString("SASteeringWheelEmulationCalibrateNoneAxisError", resourceCulture); } diff --git a/DS4Windows/Properties/Resources.fi.resx b/DS4Windows/Properties/Resources.fi.resx index e314f7d..0c79338 100644 --- a/DS4Windows/Properties/Resources.fi.resx +++ b/DS4Windows/Properties/Resources.fi.resx @@ -1,4 +1,4 @@ - +