cemu-DS4Windows/DS4Windows/DS4Control/MouseCursor.cs
2017-06-26 23:38:01 -07:00

246 lines
8.4 KiB
C#

namespace DS4Windows
{
class MouseCursor
{
private readonly int deviceNumber;
public MouseCursor(int deviceNum)
{
deviceNumber = deviceNum;
}
// Keep track of remainders when performing moves or we lose fractional parts.
private double horizontalRemainder = 0.0, verticalRemainder = 0.0;
private double hRemainder = 0.0, vRemainder = 0.0;
/** Indicate x/y direction for doing jitter compensation, etc. */
public enum Direction { Negative, Neutral, Positive }
// Track direction vector separately and very trivially for now.
private Direction horizontalDirection = Direction.Neutral, verticalDirection = Direction.Neutral;
private Direction hDirection = Direction.Neutral, vDirection = Direction.Neutral;
double verticalScale = 0.0;
public virtual void sixaxisMoved(SixAxisEventArgs arg)
{
int deltaX = 0, deltaY = 0;
deltaX = -arg.sixAxis.gyroXFull;
deltaY = -arg.sixAxis.gyroYFull;
//Console.WriteLine(arg.sixAxis.deltaX);
double coefficient = (Global.getGyroSensitivity(deviceNumber) * 0.01) * 0.0095;
double offset = 0.14725;
double tempAngle = System.Math.Atan2(-deltaY, deltaX);
double normX = System.Math.Abs(System.Math.Cos(tempAngle));
double normY = System.Math.Abs(System.Math.Sin(tempAngle));
int signX = System.Math.Sign(deltaX);
int signY = System.Math.Sign(deltaY);
if ((hRemainder > 0) != (deltaX > 0))
{
hRemainder = 0.0;
}
if ((vRemainder > 0) != (deltaY > 0))
{
vRemainder = 0.0;
}
int deadzone = 12;
//int deadzone = 0;
int deadzoneX = (int)System.Math.Abs(normX * deadzone);
int deadzoneY = (int)System.Math.Abs(normY * deadzone);
if (System.Math.Abs(deltaX) > deadzoneX)
{
deltaX -= signX * deadzoneX;
}
else
{
deltaX = 0;
}
if (System.Math.Abs(deltaY) > deadzoneY)
{
deltaY -= signY * deadzoneY;
}
else
{
deltaY = 0;
}
double xMotion = deltaX != 0 ? coefficient * deltaX + (normX * (offset * signX)) : 0;
int xAction = 0;
if (xMotion != 0.0)
{
xMotion += hRemainder;
xAction = (int)xMotion;
hRemainder = xMotion - xAction;
}
else
{
hRemainder = 0.0;
}
//hRemainder -= (int)hRemainder;
verticalScale = Global.getGyroSensVerticalScale(deviceNumber) * 0.01;
double yMotion = deltaY != 0 ? (coefficient * verticalScale) * deltaY + (normY * (offset * signY)) : 0;
int yAction = 0;
if (yMotion != 0.0)
{
yMotion += vRemainder;
yAction = (int)yMotion;
vRemainder = yMotion - yAction;
}
else
{
vRemainder = 0.0;
}
//vRemainder -= (int)vRemainder;
int gyroInvert = Global.getGyroInvert(deviceNumber);
if (gyroInvert == 2 || gyroInvert == 3)
xAction *= -1;
if (gyroInvert == 1 || gyroInvert == 3)
yAction *= -1;
if (yAction != 0 || xAction != 0)
InputMethods.MoveCursorBy(xAction, yAction);
hDirection = xMotion > 0.0 ? Direction.Positive : xMotion < 0.0 ? Direction.Negative : Direction.Neutral;
vDirection = yMotion > 0.0 ? Direction.Positive : yMotion < 0.0 ? Direction.Negative : Direction.Neutral;
}
public void mouseRemainderReset()
{
hRemainder = vRemainder = 0.0;
}
public void touchesBegan(TouchpadEventArgs arg)
{
if (arg.touches.Length == 1)
{
horizontalRemainder = verticalRemainder = 0.0;
horizontalDirection = verticalDirection = Direction.Neutral;
}
}
private byte lastTouchID;
public void touchesMoved(TouchpadEventArgs arg, bool dragging)
{
int touchesLen = arg.touches.Length;
if ((!dragging && touchesLen != 1) || (dragging && touchesLen < 1))
return;
int deltaX, deltaY;
if (arg.touches[0].touchID != lastTouchID)
{
deltaX = deltaY = 0;
horizontalRemainder = verticalRemainder = 0.0;
horizontalDirection = verticalDirection = Direction.Neutral;
lastTouchID = arg.touches[0].touchID;
}
else if (Global.TouchpadJitterCompensation[deviceNumber])
{
// Often the DS4's internal jitter compensation kicks in and starts hiding changes, ironically creating jitter...
if (dragging && touchesLen > 1)
{
deltaX = arg.touches[1].deltaX;
deltaY = arg.touches[1].deltaY;
}
else
{
deltaX = arg.touches[0].deltaX;
deltaY = arg.touches[0].deltaY;
}
// allow only very fine, slow motions, when changing direction, even from neutral
// TODO maybe just consume it completely?
if (deltaX <= -1)
{
if (horizontalDirection != Direction.Negative)
{
deltaX = -1;
horizontalRemainder = 0.0;
}
}
else if (deltaX >= 1)
{
if (horizontalDirection != Direction.Positive)
{
deltaX = 1;
horizontalRemainder = 0.0;
}
}
if (deltaY <= -1)
{
if (verticalDirection != Direction.Negative)
{
deltaY = -1;
verticalRemainder = 0.0;
}
}
else if (deltaY >= 1)
{
if (verticalDirection != Direction.Positive)
{
deltaY = 1;
verticalRemainder = 0.0;
}
}
}
else
{
if (dragging && touchesLen > 1)
{
deltaX = arg.touches[1].deltaX;
deltaY = arg.touches[1].deltaY;
}
else
{
deltaX = arg.touches[0].deltaX;
deltaY = arg.touches[0].deltaY;
}
}
double coefficient = Global.TouchSensitivity[deviceNumber] / 100.0;
// Collect rounding errors instead of losing motion.
double xMotion = coefficient * deltaX;
if (xMotion > 0.0)
{
if (horizontalRemainder > 0.0)
xMotion += horizontalRemainder;
}
else if (xMotion < 0.0)
{
if (horizontalRemainder < 0.0)
xMotion += horizontalRemainder;
}
int xAction = (int)xMotion;
horizontalRemainder = xMotion - xAction;
double yMotion = coefficient * deltaY;
if (yMotion > 0.0)
{
if (verticalRemainder > 0.0)
yMotion += verticalRemainder;
}
else if (yMotion < 0.0)
{
if (verticalRemainder < 0.0)
yMotion += verticalRemainder;
}
int yAction = (int)yMotion;
verticalRemainder = yMotion - yAction;
if (yAction != 0 || xAction != 0)
InputMethods.MoveCursorBy(xAction, yAction);
horizontalDirection = xMotion > 0.0 ? Direction.Positive : xMotion < 0.0 ? Direction.Negative : Direction.Neutral;
verticalDirection = yMotion > 0.0 ? Direction.Positive : yMotion < 0.0 ? Direction.Negative : Direction.Neutral;
}
}
}