2018-06-10 23:14:31 +00:00
# include "hud.h"
# include "cl_util.h"
# include "parsemsg.h"
# include "hudgl.h"
2018-08-01 04:49:49 +00:00
// Crosshair system based on OpenAG
// https://github.com/YaLTeR/OpenAG
2018-06-10 23:14:31 +00:00
int CHudCrosshairs : : Init ( )
{
m_iFlags = HUD_ACTIVE ;
cl_cross = CVAR_CREATE ( " cl_cross " , " 0 " , FCVAR_ARCHIVE ) ;
2018-08-01 04:49:49 +00:00
cl_cross_color = CVAR_CREATE ( " cl_cross_color " , " 255 255 255 " , FCVAR_ARCHIVE ) ;
2018-06-10 23:14:31 +00:00
cl_cross_alpha = CVAR_CREATE ( " cl_cross_alpha " , " 255 " , FCVAR_ARCHIVE ) ;
cl_cross_thickness = CVAR_CREATE ( " cl_cross_thickness " , " 2 " , FCVAR_ARCHIVE ) ;
2018-08-01 04:49:49 +00:00
cl_cross_size = CVAR_CREATE ( " cl_cross_size " , " 6 " , FCVAR_ARCHIVE ) ;
2018-06-10 23:14:31 +00:00
cl_cross_gap = CVAR_CREATE ( " cl_cross_gap " , " 3 " , FCVAR_ARCHIVE ) ;
2018-08-01 04:49:49 +00:00
cl_cross_outline = CVAR_CREATE ( " cl_cross_outline " , " 2 " , FCVAR_ARCHIVE ) ;
cl_cross_outline_alpha = CVAR_CREATE ( " cl_cross_outline_alpha " , " 255 " , FCVAR_ARCHIVE ) ;
cl_cross_outline_inner = CVAR_CREATE ( " cl_cross_outline_inner " , " 0 " , FCVAR_ARCHIVE ) ;
cl_cross_circle_radius = CVAR_CREATE ( " cl_cross_circle_radius " , " 0 " , FCVAR_ARCHIVE ) ;
2018-06-10 23:14:31 +00:00
cl_cross_dot_size = CVAR_CREATE ( " cl_cross_dot_size " , " 0 " , FCVAR_ARCHIVE ) ;
cl_cross_dot_color = CVAR_CREATE ( " cl_cross_dot_color " , " " , FCVAR_ARCHIVE ) ;
2018-08-01 04:49:49 +00:00
cl_cross_dot_outline = CVAR_CREATE ( " cl_cross_dot_outline " , " 0 " , FCVAR_ARCHIVE ) ;
cl_cross_line_top = CVAR_CREATE ( " cl_cross_line_top " , " 1 " , FCVAR_ARCHIVE ) ;
cl_cross_line_bottom = CVAR_CREATE ( " cl_cross_line_bottom " , " 1 " , FCVAR_ARCHIVE ) ;
cl_cross_line_left = CVAR_CREATE ( " cl_cross_line_left " , " 1 " , FCVAR_ARCHIVE ) ;
cl_cross_line_right = CVAR_CREATE ( " cl_cross_line_right " , " 1 " , FCVAR_ARCHIVE ) ;
2018-06-10 23:14:31 +00:00
gHUD . AddHudElem ( this ) ;
return 0 ;
}
int CHudCrosshairs : : VidInit ( )
{
return 1 ;
}
int CHudCrosshairs : : Draw ( float time )
{
if ( cl_cross - > value = = 0.0f )
return 0 ;
unsigned char alpha ;
if ( sscanf ( cl_cross_alpha - > string , " %hhu " , & alpha ) ! = 1 )
alpha = 255 ;
if ( alpha = = 0 )
return 0 ;
2018-08-01 04:49:49 +00:00
if ( gHUD . GetInTopDownMode ( ) )
return 0 ;
// outline alpha perhaps unnecessary since odd numbered thicknesses feather the outline edges
unsigned char outalpha ;
if ( sscanf ( cl_cross_outline_alpha - > string , " %hhu " , & outalpha ) ! = 1 )
outalpha = 255 ;
if ( outalpha = = 0 )
return 0 ;
2018-06-10 23:14:31 +00:00
unsigned char r , g , b ;
if ( sscanf ( cl_cross_color - > string , " %hhu %hhu %hhu " , & r , & g , & b ) ! = 3 ) {
r = 0 ;
g = 255 ;
b = 0 ;
}
Vector2D center ( ScreenWidth ( ) / 2.0f , ScreenHeight ( ) / 2.0f ) ;
HudGL gl ;
// Draw the outline.
// TODO: this contains a terrible amount of repeating complex code.
2018-08-01 04:49:49 +00:00
//
// Possible solution: can be changed to this with the one downside being in rare cases where cl_cross_thickness is high AND its alpha is <255, the center of each line will be slightly darker.
// Example below is for bottom line. Would also cause certain crosshairs that have outlines on invisible cross lines to not look right.
2018-06-10 23:14:31 +00:00
// gl.rectangle(Vector2D(center.x + offset, center.y + gap - half_width), Vector2D(center.x - offset, center.y + gap + size + half_width));
if ( cl_cross_outline - > value > 0.0f ) {
2018-08-01 04:49:49 +00:00
//gl.color(0, 0, 0, alpha);
gl . color ( 0 , 0 , 0 , outalpha ) ;
2018-06-10 23:14:31 +00:00
gl . line_width ( cl_cross_outline - > value ) ;
auto size = cl_cross_size - > value ;
auto gap = cl_cross_gap - > value ;
auto half_thickness = cl_cross_thickness - > value / 2.0f ;
auto half_width = cl_cross_outline - > value / 2.0f ;
auto offset = half_thickness + half_width ;
// Top line
2018-08-01 04:49:49 +00:00
if ( cl_cross_line_top - > value ) {
2018-06-10 23:14:31 +00:00
gl . line ( Vector2D ( center . x - offset , center . y - gap - size ) , Vector2D ( center . x + offset , center . y - gap - size ) ) ;
if ( cl_cross_outline_inner - > value = = 0.0f )
{
gl . line ( Vector2D ( center . x + half_thickness , center . y - gap - size + half_width ) , Vector2D ( center . x + half_thickness , center . y - gap ) ) ;
gl . line ( Vector2D ( center . x - half_thickness , center . y - gap ) , Vector2D ( center . x - half_thickness , center . y - gap - size + half_width ) ) ;
}
else
{
gl . line ( Vector2D ( center . x + half_thickness , center . y - gap - size + half_width ) , Vector2D ( center . x + half_thickness , center . y - gap - half_width ) ) ;
gl . line ( Vector2D ( center . x + offset , center . y - gap ) , Vector2D ( center . x - offset , center . y - gap ) ) ;
gl . line ( Vector2D ( center . x - half_thickness , center . y - gap - half_width ) , Vector2D ( center . x - half_thickness , center . y - gap - size + half_width ) ) ;
}
}
// Bottom line
2018-08-01 04:49:49 +00:00
if ( cl_cross_line_bottom - > value ) {
2018-06-10 23:14:31 +00:00
gl . line ( Vector2D ( center . x - offset , center . y + gap + size ) , Vector2D ( center . x + offset , center . y + gap + size ) ) ;
if ( cl_cross_outline_inner - > value = = 0.0f )
{
gl . line ( Vector2D ( center . x + half_thickness , center . y + gap + size - half_width ) , Vector2D ( center . x + half_thickness , center . y + gap ) ) ;
gl . line ( Vector2D ( center . x - half_thickness , center . y + gap ) , Vector2D ( center . x - half_thickness , center . y + gap + size - half_width ) ) ;
}
else
{
gl . line ( Vector2D ( center . x + half_thickness , center . y + gap + size - half_width ) , Vector2D ( center . x + half_thickness , center . y + gap + half_width ) ) ;
gl . line ( Vector2D ( center . x + offset , center . y + gap ) , Vector2D ( center . x - offset , center . y + gap ) ) ;
gl . line ( Vector2D ( center . x - half_thickness , center . y + gap + half_width ) , Vector2D ( center . x - half_thickness , center . y + gap + size - half_width ) ) ;
}
}
// Left line
2018-08-01 04:49:49 +00:00
if ( cl_cross_line_left - > value ) {
2018-06-10 23:14:31 +00:00
gl . line ( Vector2D ( center . x - gap - size , center . y - offset ) , Vector2D ( center . x - gap - size , center . y + offset ) ) ;
if ( cl_cross_outline_inner - > value = = 0.0f )
{
gl . line ( Vector2D ( center . x - gap - size + half_width , center . y + half_thickness ) , Vector2D ( center . x - gap , center . y + half_thickness ) ) ;
gl . line ( Vector2D ( center . x - gap , center . y - half_thickness ) , Vector2D ( center . x - gap - size + half_width , center . y - half_thickness ) ) ;
}
else
{
gl . line ( Vector2D ( center . x - gap - size + half_width , center . y + half_thickness ) , Vector2D ( center . x - gap - half_width , center . y + half_thickness ) ) ;
gl . line ( Vector2D ( center . x - gap , center . y + offset ) , Vector2D ( center . x - gap , center . y - offset ) ) ;
gl . line ( Vector2D ( center . x - gap - half_width , center . y - half_thickness ) , Vector2D ( center . x - gap - size + half_width , center . y - half_thickness ) ) ;
}
}
// Right line
2018-08-01 04:49:49 +00:00
if ( cl_cross_line_right - > value ) {
2018-06-10 23:14:31 +00:00
gl . line ( Vector2D ( center . x + gap + size , center . y - offset ) , Vector2D ( center . x + gap + size , center . y + offset ) ) ;
if ( cl_cross_outline_inner - > value = = 0.0f )
{
gl . line ( Vector2D ( center . x + gap + size - half_width , center . y + half_thickness ) , Vector2D ( center . x + gap , center . y + half_thickness ) ) ;
gl . line ( Vector2D ( center . x + gap , center . y - half_thickness ) , Vector2D ( center . x + gap + size - half_width , center . y - half_thickness ) ) ;
}
else
{
gl . line ( Vector2D ( center . x + gap + size - half_width , center . y + half_thickness ) , Vector2D ( center . x + gap + half_width , center . y + half_thickness ) ) ;
gl . line ( Vector2D ( center . x + gap , center . y + offset ) , Vector2D ( center . x + gap , center . y - offset ) ) ;
gl . line ( Vector2D ( center . x + gap + half_width , center . y - half_thickness ) , Vector2D ( center . x + gap + size - half_width , center . y - half_thickness ) ) ;
}
}
// Dot
if ( cl_cross_dot_size - > value > 0.0f & & cl_cross_dot_outline - > value > 0.0f ) {
auto size = cl_cross_dot_size - > value ;
auto offset = Vector2D ( size / 2.0f , size / 2.0f ) ;
auto dot_half_width = cl_cross_dot_outline - > value / 2.0f ;
gl . line ( Vector2D ( center . x - offset . x - dot_half_width , center . y - offset . y ) , Vector2D ( center . x + offset . x + dot_half_width , center . y - offset . y ) ) ;
gl . line ( Vector2D ( center . x + offset . x , center . y - offset . y + dot_half_width ) , Vector2D ( center . x + offset . x , center . y + offset . y - dot_half_width ) ) ;
gl . line ( Vector2D ( center . x - offset . x , center . y - offset . y + dot_half_width ) , Vector2D ( center . x - offset . x , center . y + offset . y - dot_half_width ) ) ;
gl . line ( Vector2D ( center . x - offset . x - dot_half_width , center . y + offset . y ) , Vector2D ( center . x + offset . x + dot_half_width , center . y + offset . y ) ) ;
}
}
gl . color ( r , g , b , alpha ) ;
// Draw the crosshairs.
if ( cl_cross_thickness - > value > 0.0f ) {
gl . line_width ( cl_cross_thickness - > value ) ;
auto size = cl_cross_size - > value ;
auto gap = cl_cross_gap - > value ;
2018-08-01 04:49:49 +00:00
if ( cl_cross_line_top - > value )
2018-06-10 23:14:31 +00:00
gl . line ( Vector2D ( center . x , center . y - gap - size ) , Vector2D ( center . x , center . y - gap ) ) ;
2018-08-01 04:49:49 +00:00
if ( cl_cross_line_bottom - > value )
2018-06-10 23:14:31 +00:00
gl . line ( Vector2D ( center . x , center . y + gap + size ) , Vector2D ( center . x , center . y + gap ) ) ;
2018-08-01 04:49:49 +00:00
if ( cl_cross_line_left - > value )
2018-06-10 23:14:31 +00:00
gl . line ( Vector2D ( center . x - gap - size , center . y ) , Vector2D ( center . x - gap , center . y ) ) ;
2018-08-01 04:49:49 +00:00
if ( cl_cross_line_right - > value )
2018-06-10 23:14:31 +00:00
gl . line ( Vector2D ( center . x + gap + size , center . y ) , Vector2D ( center . x + gap , center . y ) ) ;
}
2018-08-01 04:49:49 +00:00
// Draw the circle.
if ( cl_cross_circle_radius - > value > 0.0f ) {
gl . line_width ( 1.0f ) ;
2018-06-10 23:14:31 +00:00
2018-08-01 04:49:49 +00:00
auto radius = cl_cross_circle_radius - > value ;
if ( old_circle_radius ! = radius ) {
// Recompute the circle points.
circle_points = HudGL : : compute_circle ( radius ) ;
old_circle_radius = radius ;
}
2018-06-10 23:14:31 +00:00
2018-08-01 04:49:49 +00:00
gl . circle ( center , circle_points ) ;
}
2018-06-10 23:14:31 +00:00
// Draw the dot.
if ( cl_cross_dot_size - > value > 0.0f ) {
unsigned char r , g , b ;
if ( sscanf ( cl_cross_dot_color - > string , " %hhu %hhu %hhu " , & r , & g , & b ) = = 3 )
gl . color ( r , g , b , alpha ) ;
auto size = cl_cross_dot_size - > value ;
auto offset = Vector2D ( size / 2.0f , size / 2.0f ) ;
gl . rectangle ( center - offset , center + offset ) ;
}
return 0 ;
}