Improve drawing with digital zone highligts, futher colour tweaks, & thicker lines in GL.

It's also now no longer possible to trigger NW & SE angles when digital is set to 4 direction.
This commit is contained in:
2022-11-18 05:44:30 +11:00
parent 0cf89816cd
commit 4255841a6b
9 changed files with 177 additions and 42 deletions

108
stick.c
View File

@ -17,28 +17,37 @@ vector RadialDeadzone(vector v, double min, double max)
return (vector){v.x / mag * rescale, v.y / mag * rescale};
}
vector DigitalEight(vector v, double angle, double deadzone)
point DigitalEight(vector v, double angle, double deadzone)
{
vector res = {0, 0};
const double absx = fabs(v.x);
const double absy = fabs(v.y);
point p = {0, 0};
if (fabs(v.x) * angle > fabs(v.y))
if (absx * angle >= absy)
{
if (fabs(v.x) > deadzone)
res.x = copysign(1.0, v.x);
if (absx > deadzone)
p.x = signbit(v.x) ? -1 : 1;
}
else if (fabs(v.y) * angle > fabs(v.x))
else if (absy * angle > absx)
{
if (fabs(v.y) > deadzone)
res.y = copysign(1.0, v.y);
if (absy > deadzone)
p.y = signbit(v.y) ? -1 : 1;
}
else if (fabs(v.x) + fabs(v.y) > deadzone * (1.0 + angle))
else if (absx + absy >= deadzone * (1.0 + angle))
{
const double dscale = 1/sqrt(2);
res.x = copysign(dscale, v.x);
res.y = copysign(dscale, v.y);
p.x = signbit(v.x) ? -1 : 1;
p.y = signbit(v.y) ? -1 : 1;
}
return res;
return p;
}
vector DigitalToVector(point p)
{
const double dscale = (p.x && p.y) ? 1.0 / sqrt(2.0) : 1.0;
return (vector){
p.x ? copysign(dscale, (double)p.x) : 0.0,
p.y ? copysign(dscale, (double)p.y) : 0.0};
}
static inline double AccelCurve(double x, double y)
@ -84,7 +93,7 @@ void DrawAnalogue(const rect* win, StickState* p)
const int oy = win->y + win->h / 2;
// acceleration curve
SetDrawColour(GREY4);
SetDrawColour(GREY5);
const int accelsamp = (int)(sqrt(size) * 4.20);
const double step = 1.0 / (double)accelsamp;
double y1 = AccelCurve(0.0, p->accelpow);
@ -92,10 +101,10 @@ void DrawAnalogue(const rect* win, StickState* p)
{
double y2 = AccelCurve(step * i, p->accelpow);
DrawLine(
win->x + (int)(step * (i - 1) * size) + (win->w - (int)round(size)) / 2,
win->y + (int)((1.0 - y1) * size) + (win->h - (int)round(size)) / 2,
win->x + (int)(step * i * size) + (win->w - (int)round(size)) / 2,
win->y + (int)((1.0 - y2) * size) + (win->h - (int)round(size)) / 2);
win->x + (int)(step * (i - 1) * size) + (win->w - rectSz) / 2,
win->y + (int)((1.0 - y1) * size) + (win->h - rectSz) / 2,
win->x + (int)(step * i * size) + (win->w - rectSz) / 2,
win->y + (int)((1.0 - y2) * size) + (win->h - rectSz) / 2);
y1 = y2;
}
const int tickerx = (int)((p->preaccel - 0.5) * size);
@ -103,21 +112,21 @@ void DrawAnalogue(const rect* win, StickState* p)
SetDrawColour(HILIGHT_PU1);
DrawLine(
ox + tickerx,
win->y + (win->h - (int)round(size)) / 2,
win->y + (win->h - rectSz) / 2,
ox + tickerx,
win->y + (win->h + (int)round(size)) / 2);
win->y + (win->h + rectSz) / 2);
SetDrawColour(HILIGHT_PU2);
DrawLine(
win->x + (win->w - (int)round(size)) / 2,
win->x + (win->w - rectSz) / 2,
oy + tickery,
win->x + (win->w + (int)round(size)) / 2,
win->x + (win->w + rectSz) / 2,
oy + tickery);
// guide circle
SetDrawColour(GREY4);
DrawCircle(ox, oy, (int)round(size) / 2);
SetDrawColour(GREY5);
DrawCircle(ox, oy, rectSz / 2);
SetDrawColour(GREY3);
SetDrawColour(GREY4);
DrawCircle(ox, oy, (int)round(p->deadzone * size) / 2);
// 0,0 line axis'
@ -157,7 +166,8 @@ void DrawDigital(const rect* win, StickState* p)
{
if (p->recalc)
{
p->compos = DigitalEight(p->rawpos, p->digiangle, p->digideadzone);
p->digixy = DigitalEight(p->rawpos, p->digiangle, p->digideadzone);
p->compos = DigitalToVector(p->digixy);
p->recalc = false;
}
@ -176,8 +186,9 @@ void DrawDigital(const rect* win, StickState* p)
const int oy = win->y + win->h / 2;
// guide circle
SetDrawColour(GREY4);
DrawCircle(ox, oy, (int)round(size) / 2);
SetDrawColour(GREY5);
int radius = rectSz / 2;
DrawCircle(ox, oy, radius);
// 0,0 line axis'
SetDrawColour(GREY2);
@ -195,7 +206,7 @@ void DrawDigital(const rect* win, StickState* p)
const int innh = (int)round(p->digideadzone * size / 2.0);
const int innq = (int)round(p->digideadzone * size / 2.0 * p->digiangle);
SetDrawColour(GREY3);
SetDrawColour(GREY4);
// angles preview
DrawLine(ox - outq, oy - outh, ox - innq, oy - innh);
@ -218,6 +229,45 @@ void DrawDigital(const rect* win, StickState* p)
DrawLine(ox - innh, oy + innq, ox - innh, oy - innq);
DrawLine(ox - innh, oy - innq, ox - innq, oy - innh);
// highlight active zone
if (p->digixy.x || p->digixy.y)
{
const int x = p->digixy.x;
const int y = p->digixy.y;
SetDrawColour(HILIGHT_GR2);
if (x)
{
if (y <= 0) DrawLine(ox + outh * x, oy - outq, ox + innh * x, oy - innq);
if (!y) DrawLine(ox + innh * x, oy + innq, ox + innh * x, oy - innq);
if (y >= 0) DrawLine(ox + outh * x, oy + outq, ox + innh * x, oy + innq);
}
if (y)
{
if (x <= 0) DrawLine(ox - outq, oy + outh * y, ox - innq, oy + innh * y);
if (!x) DrawLine(ox + innq, oy + innh * y, ox - innq, oy + innh * y);
if (x >= 0) DrawLine(ox + outq, oy + outh * y, ox + innq, oy + innh * y);
}
if (x && y)
{
DrawLine(ox + innh * x, oy + innq * y, ox + innq * x, oy + innh * y);
DrawArc(ox, oy, radius,
-(int)round(atan2(outerinvmag * p->digiangle * y, outerinvmag * x) * RAD2DEG),
-(int)round(atan2(outerinvmag * y, outerinvmag * p->digiangle * x) * RAD2DEG));
}
else
{
const int hemi = (int)round(atan2(outerinvmag * p->digiangle, outerinvmag) * RAD2DEG);
if (x > 0) DrawArc(ox, oy, radius, -hemi, hemi);
else if (y < 0) DrawArc(ox, oy, radius, -hemi + 90, hemi + 90);
else if (x < 0) DrawArc(ox, oy, radius, -hemi + 180, hemi + 180);
else if (y > 0) DrawArc(ox, oy, radius, -hemi + 270, hemi + 270);
}
}
// compensated position
SetDrawColour(HILIGHT_GR3);
DrawCircleSteps(