Created
December 7, 2023 11:08
-
-
Save DJm00n/597c44fcf82f2b51cd7ca46ebc819737 to your computer and use it in GitHub Desktop.
Mouse acceleration
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/***************************************************************************** | |
* | |
* The algorithm for applying acceleration is: | |
* | |
* dxC = dxR | |
* if A >= 1 and abs(dxR) > T1 then | |
* dxC = dxR * 2 | |
* if A >= 2 and abs(dxR) > Thres2 then | |
* dxC = dxR * 4 | |
* end if | |
* end if | |
* | |
* where | |
* dxR is the raw mouse motion | |
* dxC is the cooked mouse motion | |
* A is the acceleration | |
* T1 is the first threshold | |
* T2 is the second threshold | |
* | |
* Repeat for dy instead of dx. | |
* | |
* We can optimize this by simply setting the thresholds to MAXLONG | |
* if they are disabled; that way, abs(dx) will never exceed it. | |
* | |
* The result is the following piecewise linear function: | |
* | |
* if 0 < abs(dxR) <= T1: dxC = dxR | |
* if T1 < abs(dxR) <= T2: dxC = dxR * 2 | |
* if T2 < abs(dxR): dxC = dxR * 4 | |
* | |
* If you graph this function, you'll see that it's discontinuous! | |
* | |
* The inverse mapping of this function is what concerns us. | |
* It looks like this: | |
* | |
* if 0 < abs(dxC) <= T1: dxR = dxC | |
* if T1 * 2 < abs(dxC) <= T2 * 2: dxR = dxC / 2 | |
* if T2 * 4 < abs(dxC): dxR = dxC / 4 | |
* | |
* Notice that there are gaps in the graph, so we can fill them in | |
* any way we want, as long as it isn't blatantly *wrong*. (In the | |
* case where we are using emulation, it is possible to get relative | |
* mouse motions that live in the "impossible" limbo zone due to | |
* clipping.) | |
* | |
* if 0 < abs(dxC) <= T1: dxR = dxC | |
* if T1 < abs(dxC) <= T2 * 2: dxR = dxC / 2 | |
* if T2 * 2 < abs(dxC): dxR = dxC / 4 | |
* | |
* Therefore: (you knew the punch line was coming) | |
* | |
* s_rgiMouseThresh[0] = T1 (or MAXLONG) | |
* s_rgiMouseThresh[1] = T2 * 2 (or MAXLONG) | |
* | |
* | |
*****************************************************************************/ | |
static int s_rgiMouseThresh[2]; | |
/***************************************************************************** | |
* | |
* @doc INTERNAL | |
* | |
* @func void | CEm_Mouse_OnMouseChange | | |
* | |
* The mouse acceleration changed. Go recompute the | |
* unacceleration variables. | |
* | |
*****************************************************************************/ | |
void EXTERNAL | |
CEm_Mouse_OnMouseChange(void) | |
{ | |
int rgi[3]; /* Mouse acceleration information */ | |
/* | |
* See the huge comment block at the definition of | |
* s_rgiMouseThresh for an explanation of the math | |
* that is happening here. | |
* | |
* If acceleration is enabled at all... | |
*/ | |
if (SystemParametersInfo(SPI_GETMOUSE, 0, &rgi, 0) && rgi[2]) { | |
s_rgiMouseThresh[0] = rgi[0]; | |
if (rgi[2] >= 2) { | |
s_rgiMouseThresh[1] = rgi[1] * 2; | |
} else { /* Disable level 2 acceleration */ | |
s_rgiMouseThresh[1] = MAXLONG; | |
} | |
} else { /* Disable all acceleration */ | |
s_rgiMouseThresh[0] = MAXLONG; | |
} | |
SquirtSqflPtszV(sqfl, TEXT("CEm_Mouse_OnMouseChange: ") | |
TEXT("New accelerations %d / %d"), | |
s_rgiMouseThresh[0], s_rgiMouseThresh[1]); | |
} | |
/***************************************************************************** | |
* | |
* @doc INTERNAL | |
* | |
* @func void | CEm_Mouse_RemoveAccel | | |
* | |
* Remove any acceleration from the mouse motion. | |
* | |
* See the huge comment block at s_rgiMouseThresh | |
* for an explanation of what we are doing. | |
* | |
* @parm int | dx | | |
* | |
* Change in coordinate, either dx or dy. | |
* | |
*****************************************************************************/ | |
int INTERNAL | |
CEm_Mouse_RemoveAccel(int dx) | |
{ | |
int x = abs(dx); | |
if (x > s_rgiMouseThresh[0]) { | |
dx /= 2; | |
if (x > s_rgiMouseThresh[1]) { | |
dx /= 2; | |
} | |
} | |
return dx; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment