float arrow_size = max(panel_size.y * min(autocvar_hud_panel_strafehud_angle_arrow_size, 10), 0); // there's only one size cvar for the arrows, they will always have a 45° angle to ensure proper rendering without antialiasing
float text_offset_top = 0;
float text_offset_bottom = 0;
+ float hfov = getproperty(VF_FOVX);
if(onground)
{
hudangle = range_minangle; // use minimum angle required if dynamically setting hud angle
}
}
+ else if(autocvar_hud_panel_strafehud_range < 0)
+ {
+ hudangle = hfov;
+ }
else
{
hudangle = bound(0, fabs(autocvar_hud_panel_strafehud_range), 360); // limit HUD range to 360 degrees, higher values don't make sense
}
+ // limit strafe-meter angle to values suitable for the current projection mode
+ switch(autocvar_hud_panel_strafehud_projection) {
+ case STRAFEHUD_PROJECTION_PERSPECTIVE:
+ hudangle = min(hudangle, 170);
+ break;
+ case STRAFEHUD_PROJECTION_PANORAMIC:
+ hudangle = min(hudangle, 350);
+ break;
+ }
+
// detect air strafe turning
if((!strafekeys && vlen(vec2(movement)) > 0) || onground || autocvar__hud_configure)
{
overturn_offset += shift_offset;
// draw left acceleration zone
- HUD_Panel_DrawStrafeHUD(accelzone_left_offset, accelzone_width, hidden_width, autocvar_hud_panel_strafehud_bar_accel_color, autocvar_hud_panel_strafehud_bar_accel_alpha * panel_fg_alpha, autocvar_hud_panel_strafehud_style, STRAFEHUD_GRADIENT_LEFT);
+ HUD_Panel_DrawStrafeHUD(accelzone_left_offset, accelzone_width, hidden_width, autocvar_hud_panel_strafehud_bar_accel_color, autocvar_hud_panel_strafehud_bar_accel_alpha * panel_fg_alpha, autocvar_hud_panel_strafehud_style, STRAFEHUD_GRADIENT_LEFT, true, hudangle);
if(autocvar_hud_panel_strafehud_bar_preaccel)
- HUD_Panel_DrawStrafeHUD(preaccelzone_left_offset, preaccelzone_width, hidden_width, autocvar_hud_panel_strafehud_bar_accel_color, autocvar_hud_panel_strafehud_bar_accel_alpha * panel_fg_alpha, autocvar_hud_panel_strafehud_style, STRAFEHUD_GRADIENT_RIGHT);
+ HUD_Panel_DrawStrafeHUD(preaccelzone_left_offset, preaccelzone_width, hidden_width, autocvar_hud_panel_strafehud_bar_accel_color, autocvar_hud_panel_strafehud_bar_accel_alpha * panel_fg_alpha, autocvar_hud_panel_strafehud_style, STRAFEHUD_GRADIENT_RIGHT, true, hudangle);
// draw right acceleration zone
- HUD_Panel_DrawStrafeHUD(accelzone_right_offset, accelzone_width, hidden_width, autocvar_hud_panel_strafehud_bar_accel_color, autocvar_hud_panel_strafehud_bar_accel_alpha * panel_fg_alpha, autocvar_hud_panel_strafehud_style, STRAFEHUD_GRADIENT_RIGHT);
+ HUD_Panel_DrawStrafeHUD(accelzone_right_offset, accelzone_width, hidden_width, autocvar_hud_panel_strafehud_bar_accel_color, autocvar_hud_panel_strafehud_bar_accel_alpha * panel_fg_alpha, autocvar_hud_panel_strafehud_style, STRAFEHUD_GRADIENT_RIGHT, true, hudangle);
if(autocvar_hud_panel_strafehud_bar_preaccel)
- HUD_Panel_DrawStrafeHUD(preaccelzone_right_offset, preaccelzone_width, hidden_width, autocvar_hud_panel_strafehud_bar_accel_color, autocvar_hud_panel_strafehud_bar_accel_alpha * panel_fg_alpha, autocvar_hud_panel_strafehud_style, STRAFEHUD_GRADIENT_LEFT);
+ HUD_Panel_DrawStrafeHUD(preaccelzone_right_offset, preaccelzone_width, hidden_width, autocvar_hud_panel_strafehud_bar_accel_color, autocvar_hud_panel_strafehud_bar_accel_alpha * panel_fg_alpha, autocvar_hud_panel_strafehud_style, STRAFEHUD_GRADIENT_LEFT, true, hudangle);
// draw overturn zone (technically incorrect, acceleration decreases at 90 degrees but speed loss happens a little bit after 90 degrees, however due to sv_airstopaccelerate that's hard to calculate)
- HUD_Panel_DrawStrafeHUD(overturn_offset, overturn_width, hidden_width, autocvar_hud_panel_strafehud_bar_overturn_color, autocvar_hud_panel_strafehud_bar_overturn_alpha * panel_fg_alpha, autocvar_hud_panel_strafehud_style, STRAFEHUD_GRADIENT_BOTH);
+ HUD_Panel_DrawStrafeHUD(overturn_offset, overturn_width, hidden_width, autocvar_hud_panel_strafehud_bar_overturn_color, autocvar_hud_panel_strafehud_bar_overturn_alpha * panel_fg_alpha, autocvar_hud_panel_strafehud_style, STRAFEHUD_GRADIENT_BOTH, true, hudangle);
// draw neutral zone
- HUD_Panel_DrawStrafeHUD(neutral_offset, neutral_width, hidden_width, autocvar_hud_panel_strafehud_bar_neutral_color, autocvar_hud_panel_strafehud_bar_neutral_alpha * panel_fg_alpha, autocvar_hud_panel_strafehud_style, STRAFEHUD_GRADIENT_NONE);
+ HUD_Panel_DrawStrafeHUD(neutral_offset, neutral_width, hidden_width, autocvar_hud_panel_strafehud_bar_neutral_color, autocvar_hud_panel_strafehud_bar_neutral_alpha * panel_fg_alpha, autocvar_hud_panel_strafehud_style, STRAFEHUD_GRADIENT_NONE, true, hudangle);
if(autocvar_hud_panel_strafehud_switch && speed >= minspeed && bestangle_width > 0 && autocvar_hud_panel_strafehud_switch_alpha > 0) // only draw indicators if minspeed is reached
{
offset -= bestangle_width;
}
- HUD_Panel_DrawStrafeHUD(switch_offset, bestangle_width, hidden_width, autocvar_hud_panel_strafehud_switch_color, autocvar_hud_panel_strafehud_switch_alpha * panel_fg_alpha, STRAFEHUD_STYLE_DRAWFILL, STRAFEHUD_GRADIENT_NONE);
- if(direction == STRAFEHUD_DIRECTION_NONE) HUD_Panel_DrawStrafeHUD(offset, bestangle_width, hidden_width, autocvar_hud_panel_strafehud_switch_color, autocvar_hud_panel_strafehud_switch_alpha * panel_fg_alpha, STRAFEHUD_STYLE_DRAWFILL, STRAFEHUD_GRADIENT_NONE);
+ HUD_Panel_DrawStrafeHUD(switch_offset, bestangle_width, hidden_width, autocvar_hud_panel_strafehud_switch_color, autocvar_hud_panel_strafehud_switch_alpha * panel_fg_alpha, STRAFEHUD_STYLE_DRAWFILL, STRAFEHUD_GRADIENT_NONE, false, hudangle);
+ if(direction == STRAFEHUD_DIRECTION_NONE) HUD_Panel_DrawStrafeHUD(offset, bestangle_width, hidden_width, autocvar_hud_panel_strafehud_switch_color, autocvar_hud_panel_strafehud_switch_alpha * panel_fg_alpha, STRAFEHUD_STYLE_DRAWFILL, STRAFEHUD_GRADIENT_NONE, false, hudangle);
}
}
ghost_offset = bound(0, (odd_angles ? odd_bestangle_offset : bestangle_offset), panel_size.x);
}
+ currentangle_offset = StrafeHUD_projectOffset(currentangle_offset, hudangle);
+ ghost_offset = StrafeHUD_projectOffset(ghost_offset, hudangle);
+
switch(autocvar_hud_panel_strafehud_angle_style)
{
case STRAFEHUD_INDICATOR_SOLID:
hud_lasttime = time;
}
+float StrafeHUD_projectOffset(float offset, float range) {
+ range *= DEG2RAD / 2;
+ float angle = (offset - (panel_size.x/2)) / (panel_size.x/2) * range;
+ switch(autocvar_hud_panel_strafehud_projection) {
+ default:
+ case STRAFEHUD_PROJECTION_LINEAR:
+ return offset;
+ case STRAFEHUD_PROJECTION_PERSPECTIVE:
+ offset = tan(angle) / tan(range);
+ break;
+ case STRAFEHUD_PROJECTION_PANORAMIC:
+ offset = tan(angle/2) / tan(range/2);
+ break;
+ }
+ offset = offset * (panel_size.x/2) + (panel_size.x/2);
+ return offset;
+}
+
+float StrafeHUD_projectWidth(float offset, float width, float range) {
+ return StrafeHUD_projectOffset(offset + width, range) - StrafeHUD_projectOffset(offset, range);
+}
+
// functions to make hud elements align perfectly in the hud area
-void HUD_Panel_DrawStrafeHUD(float offset, float width, float hidden_width, vector color, float alpha, int type, int gradientType)
+void HUD_Panel_DrawStrafeHUD(float offset, float width, float hidden_width, vector color, float alpha, int type, int gradientType, bool projectWidth, float range)
{
float mirror_offset, mirror_width;
vector size = panel_size;
}
size.x = width;
+ vector original_size = size;
+ float original_offset = offset;
+ if(projectWidth && size.x > 0) size.x = StrafeHUD_projectWidth(offset, size.x, range);
+ offset = StrafeHUD_projectOffset(offset, range);
+
if(mirror_offset < 0)
{
mirror_width += mirror_offset;
}
mirror_size.x = mirror_width;
+ vector original_mirror_size = mirror_size;
+ float original_mirror_offset = mirror_offset;
+ if(projectWidth && mirror_size.x > 0) mirror_size.x = StrafeHUD_projectWidth(mirror_offset, mirror_size.x, range);
+ mirror_offset = StrafeHUD_projectOffset(mirror_offset, range);
+
switch(type)
{
default:
gradient_mirror_offset = 0;
}
- StrafeHUD_drawGradient(color, autocvar_hud_panel_strafehud_bar_neutral_color, mirror_size, original_width, mirror_offset, alpha, gradient_mirror_offset, gradientType);
- StrafeHUD_drawGradient(color, autocvar_hud_panel_strafehud_bar_neutral_color, size, original_width, offset, alpha, gradient_offset, gradientType);
+ StrafeHUD_drawGradient(color, autocvar_hud_panel_strafehud_bar_neutral_color, original_mirror_size, original_width, original_mirror_offset, alpha, gradient_mirror_offset, gradientType, range);
+ StrafeHUD_drawGradient(color, autocvar_hud_panel_strafehud_bar_neutral_color, original_size, original_width, original_offset, alpha, gradient_offset, gradientType, range);
}
}
return mixedColor;
}
-void StrafeHUD_drawGradient(vector color1, vector color2, vector size, float original_width, float offset, float alpha, float gradientOffset, int gradientType)
+void StrafeHUD_drawGradient(vector color1, vector color2, vector size, float original_width, float offset, float alpha, float gradientOffset, int gradientType, float range)
{
float color_ratio, alpha1, alpha2;
vector segment_size = size;
color_ratio = alpha1/(alpha1+alpha2);
for(int i = 0; i < size.x; ++i)
{
- float ratio, alpha_ratio, combine_ratio1, combine_ratio2;
+ float ratio, alpha_ratio, combine_ratio1, combine_ratio2, segment_offset;
+ segment_offset = offset + i;
segment_size.x = min(size.x - i, 1); // each gradient segment is 1 unit wide except if there is less than 1 unit of gradient remaining
+ segment_size.x = StrafeHUD_projectWidth(segment_offset, segment_size.x, range);
+ segment_offset = StrafeHUD_projectOffset(segment_offset, range);
ratio = (i + gradientOffset) / original_width * (gradientType == STRAFEHUD_GRADIENT_BOTH ? 2 : 1);
if(ratio > 1) ratio = 2 - ratio;
if(gradientType != STRAFEHUD_GRADIENT_RIGHT) ratio = 1 - ratio;
combine_ratio1 = ratio*(1-color_ratio);
combine_ratio2 = (1-ratio)*color_ratio;
ratio = (combine_ratio1 + combine_ratio2) == 0 ? 1 : combine_ratio1/(combine_ratio1 + combine_ratio2);
- if(alpha_ratio > 0) drawfill(panel_pos + eX * (offset + i), segment_size, StrafeHUD_mixColors(color1, color2, ratio), alpha_ratio, DRAWFLAG_NORMAL);
+ if(alpha_ratio > 0) drawfill(panel_pos + eX * segment_offset, segment_size, StrafeHUD_mixColors(color1, color2, ratio), alpha_ratio, DRAWFLAG_NORMAL);
}
}
AUTOCVAR_SAVE(_hud_panel_strafehud_demo, bool, false, "strafehud changes angle during configure");
AUTOCVAR_SAVE(hud_panel_strafehud_dynamichud, bool, true, "apply the dynamic hud effects to this panel");
AUTOCVAR_SAVE(hud_panel_strafehud_mode, int, 0, "strafehud mode which controls whether the strafehud is centered at \"0\" = view angle, \"1\" = velocity angle");
-AUTOCVAR_SAVE(hud_panel_strafehud_range, float, 90, "the angle range up to 360 degrees displayed on the strafehud, \"0\" = dynamic (chooses the minimum range required to still see the whole area needed for accelerating)");
+AUTOCVAR_SAVE(hud_panel_strafehud_range, float, 90, "the angle range up to 360 degrees displayed on the strafehud, \"-1\" = current fov, \"0\" = dynamic (chooses the minimum range required to still see the whole area needed for accelerating)");
AUTOCVAR_SAVE(hud_panel_strafehud_style, int, 2, "\"0\" = no styling, \"1\" = progress bar style for the strafe bar, \"2\" = gradient for the strafe bar");
AUTOCVAR_SAVE(hud_panel_strafehud_unit, int, 1, "speed unit (1 = qu/s, 2 = m/s, 3 = km/h, 4 = mph, 5 = knots), length unit (1 = qu, 2 = m, 3 = km, 4 = mi, 5 = nmi)");
AUTOCVAR_SAVE(hud_panel_strafehud_unit_show, bool, true, "show units");
AUTOCVAR_SAVE(hud_panel_strafehud_vangle, bool, false, "set to \"1\" to enable the vertical angle indicator");
AUTOCVAR_SAVE(hud_panel_strafehud_vangle_color, vector, '0.75 0.75 0.75', "color of the vertical angle text");
AUTOCVAR_SAVE(hud_panel_strafehud_vangle_size, float, 1, "size of the vertical angle text (relative to the panel height)");
+AUTOCVAR_SAVE(hud_panel_strafehud_projection, int, 1, "strafehud projection mode, \"0\" = Linear, \"1\" = Perspective, \"2\" = Panoramic");
-void HUD_Panel_DrawStrafeHUD(float, float, float, vector, float, int, int);
+void HUD_Panel_DrawStrafeHUD(float, float, float, vector, float, int, int, bool, float);
vector StrafeHUD_mixColors(vector, vector, float);
-void StrafeHUD_drawGradient(vector, vector, vector, float, float, float, float, int);
+void StrafeHUD_drawGradient(vector, vector, vector, float, float, float, float, int, float);
float GetLengthUnitFactor(int);
string GetLengthUnit(int);
void StrafeHUD_drawStrafeArrow(vector, float, vector, float, bool);
bool StrafeHUD_drawTextIndicator(string, float, vector, float, float, float, int);
+float StrafeHUD_projectOffset(float, float);
+float StrafeHUD_projectWidth(float, float, float);
const int STRAFEHUD_MODE_VIEW_CENTERED = 0;
const int STRAFEHUD_MODE_VELOCITY_CENTERED = 1;
const int STRAFEHUD_TEXT_TOP = 0;
const int STRAFEHUD_TEXT_BOTTOM = 1;
+
+const int STRAFEHUD_PROJECTION_LINEAR = 0;
+const int STRAFEHUD_PROJECTION_PERSPECTIVE = 1;
+const int STRAFEHUD_PROJECTION_PANORAMIC = 2;