Skip to content

Instantly share code, notes, and snippets.

@Ryochan7
Last active October 21, 2020 03:55
Show Gist options
  • Save Ryochan7/8fbbf5d43f7e687b0ffb04a26fd4fa59 to your computer and use it in GitHub Desktop.
Save Ryochan7/8fbbf5d43f7e687b0ffb04a26fd4fa59 to your computer and use it in GitHub Desktop.
Diff showing steps needed for Flick Stick to work in DS4Windows
diff --git a/DS4Windows/DS4Control/Mapping.cs b/DS4Windows/DS4Control/Mapping.cs
index a0c6f43b..ddfa002a 100644
--- a/DS4Windows/DS4Control/Mapping.cs
+++ b/DS4Windows/DS4Control/Mapping.cs
@@ -1996,6 +1996,45 @@ namespace DS4Windows
MappedState.SASteeringWheelEmulationUnit = Mapping.Scale360degreeGyroAxis(device, eState, ctrl);
}
+ DS4Device d = ctrl.DS4Controllers[device];
+ DS4State crawState = d.getCurrentStateRef();
+ DS4State pState = d.getPreviousStateRef();
+ double angleChange = HandleFlickStickAngle(crawState, pState);
+ //angleChange = flickFilter.Filter(angleChange, cState.elapsedTime);
+ //Console.WriteLine(angleChange);
+ //if (angleChange != 0.0)
+ double lsangle = angleChange * 180.0 / Math.PI;
+ if (lsangle == 0.0)
+ {
+ flickAngleRemainder = 0.0;
+ }
+ else if (lsangle >= 0.0 && flickAngleRemainder >= 0.0)
+ {
+ lsangle += flickAngleRemainder;
+ }
+
+ flickAngleRemainder = 0.0;
+ //Console.WriteLine(lsangle);
+ //if (angleChange != 0.0)
+ if (lsangle != 0.0)
+ //if (Math.Abs(lsangle) >= 0.5)
+ {
+ flickAngleRemainder = 0.0;
+ //flickAngleRemainder = lsangle - (int)lsangle;
+ //lsangle = (int)lsangle;
+ tempMouseDeltaX += lsangle * REAL_WORLD_CALIBRATION;
+ }
+ else
+ {
+ flickAngleRemainder = lsangle;
+ }
+ /*else
+ {
+ horizontalRemainder = 0.0;
+ verticalRemainder = 0.0;
+ }
+ */
+
ref byte gyroTempX = ref gyroStickX[device];
if (gyroTempX != 128)
{
@@ -2026,6 +2065,94 @@ namespace DS4Windows
}
}
+ private static OneEuroFilter flickFilter = new OneEuroFilter(0.4, 0.4);
+ private const double REAL_WORLD_CALIBRATION = 10;
+ private static double flickProgress = 0.0;
+ private static double flickSize = 0.0;
+
+ private static double FlickThreshold = 0.9;
+ private static double FlickTime = 0.1;
+
+ private static double flickAngleRemainder = 0.0;
+
+ private static double HandleFlickStickAngle(DS4State cState, DS4State pState)
+ {
+ double result = 0.0;
+
+ double lastXMax = pState.RX >= 128 ? 127.0 : -128.0;
+ double lastTestX = (pState.RX - 128) / lastXMax;
+ double lastYMax = pState.RY >= 128 ? 127.0 : -128.0;
+ double lastTestY = (pState.RY - 128) / lastYMax;
+
+ double currentXMax = cState.RX >= 128 ? 127.0 : -128.0;
+ double currentTestX = (cState.RX - 128) / currentXMax;
+ double currentYMax = cState.RY >= 128 ? 127.0 : -128.0;
+ double currentTestY = (cState.RY - 128) / currentYMax;
+
+ double lastLength = (lastTestX * lastTestX) + (lastTestY * lastTestY);
+ double length = (currentTestX * currentTestX) + (currentTestY * currentTestY);
+ double testLength = FlickThreshold * FlickThreshold;
+
+ if (length >= testLength)
+ {
+ if (lastLength < testLength)
+ {
+ // Start new Flick
+ flickProgress = 0.0; // Reset Flick progress
+ flickSize = Math.Atan2((cState.RX - 128), -(cState.RY - 128));
+ flickFilter.Filter(0.0, cState.elapsedTime);
+ }
+ else
+ {
+ // Turn camera
+ double stickAngle = Math.Atan2((cState.RX - 128), -(cState.RY - 128));
+ double lastStickAngle = Math.Atan2((pState.RX - 128),-(pState.RY - 128));
+ double angleChange = (stickAngle - lastStickAngle);
+ double rawAngleChange = angleChange;
+ angleChange = (angleChange+Math.PI) % (2*Math.PI);
+ if (angleChange < 0)
+ {
+ angleChange += 2 * Math.PI;
+ }
+ angleChange -= Math.PI;
+ //Console.WriteLine("ANGLE CHANGE: {0} {1} {2}", stickAngle, lastStickAngle, rawAngleChange);
+ //Console.WriteLine("{0} {1} | {2} {3}", cState.RX, pState.RX, cState.RY, pState.RY);
+ angleChange = flickFilter.Filter(angleChange, cState.elapsedTime);
+ result += angleChange;
+ }
+ }
+ else
+ {
+ // Cleanup
+ flickFilter.Filter(0.0, cState.elapsedTime);
+ result = 0.0;
+ }
+
+ // Continue Flick motion
+ double lastFlickProgress = flickProgress;
+ if (lastFlickProgress < FlickTime)
+ {
+ flickProgress = Math.Min(flickProgress + cState.elapsedTime, FlickTime);
+
+ double lastPerOne = lastFlickProgress / FlickTime;
+ double thisPerOne = flickProgress / FlickTime;
+
+ double warpedLastPerOne = WarpEaseOut(lastPerOne);
+ double warpedThisPerone = WarpEaseOut(thisPerOne);
+ //Console.WriteLine("{0} {1}", warpedThisPerone, warpedLastPerOne);
+
+ result += (warpedThisPerone - warpedLastPerOne) * flickSize;
+ }
+
+ return result;
+ }
+
+ private static double WarpEaseOut(double input)
+ {
+ double flipped = 1.0 - input;
+ return 1.0 - flipped * flipped;
+ }
+
private static bool IfAxisIsNotModified(int device, bool shift, DS4Controls dc)
{
return shift ? false : GetDS4Action(device, dc, false) == null;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment