From f0f16adfe652bab3aa86d922330932f03bca38a3 Mon Sep 17 00:00:00 2001 From: pierow Date: Sun, 10 Jun 2018 19:14:31 -0400 Subject: [PATCH] WIP crosshair system --- main/source/cl_dll/chud.h | 4 +- main/source/cl_dll/cl_dll.vcxproj | 4 + main/source/cl_dll/cl_dll.vcxproj.filters | 12 ++ main/source/cl_dll/hud.cpp | 2 + main/source/cl_dll/hud_crosshairs.cpp | 208 ++++++++++++++++++++++ main/source/cl_dll/hud_crosshairs.h | 30 ++++ main/source/cl_dll/hudgl.cpp | 88 +++++++++ main/source/cl_dll/hudgl.h | 17 ++ 8 files changed, 364 insertions(+), 1 deletion(-) create mode 100644 main/source/cl_dll/hud_crosshairs.cpp create mode 100644 main/source/cl_dll/hud_crosshairs.h create mode 100644 main/source/cl_dll/hudgl.cpp create mode 100644 main/source/cl_dll/hudgl.h diff --git a/main/source/cl_dll/chud.h b/main/source/cl_dll/chud.h index 5469e44f..3efd7ffa 100644 --- a/main/source/cl_dll/chud.h +++ b/main/source/cl_dll/chud.h @@ -4,6 +4,7 @@ #include "chudmisc.h" #include "hud_spectator.h" #include "AvHFont.h" +#include "hud_crosshairs.h" class CHud @@ -82,7 +83,8 @@ public: CHudAmmoSecondary m_AmmoSecondary; CHudTextMessage m_TextMessage; CHudStatusIcons m_StatusIcons; - + CHudCrosshairs m_Crosshairs; + AvHFont mFont; AvHFont mSmallFont; diff --git a/main/source/cl_dll/cl_dll.vcxproj b/main/source/cl_dll/cl_dll.vcxproj index c5cf7613..0746c7ac 100644 --- a/main/source/cl_dll/cl_dll.vcxproj +++ b/main/source/cl_dll/cl_dll.vcxproj @@ -164,6 +164,8 @@ MaxSpeed %(AdditionalIncludeDirectories) + + MaxSpeed %(AdditionalIncludeDirectories) @@ -799,6 +801,8 @@ + + diff --git a/main/source/cl_dll/cl_dll.vcxproj.filters b/main/source/cl_dll/cl_dll.vcxproj.filters index 4bc1e2e5..63cc5236 100644 --- a/main/source/cl_dll/cl_dll.vcxproj.filters +++ b/main/source/cl_dll/cl_dll.vcxproj.filters @@ -594,6 +594,12 @@ Source Files + + Source Files + + + Source Files + @@ -1040,6 +1046,12 @@ textrep + + Header Files + + + Header Files + diff --git a/main/source/cl_dll/hud.cpp b/main/source/cl_dll/hud.cpp index 8a71d72f..2dccc600 100644 --- a/main/source/cl_dll/hud.cpp +++ b/main/source/cl_dll/hud.cpp @@ -251,6 +251,7 @@ void CHud :: Init( void ) m_AmmoSecondary.Init(); m_TextMessage.Init(); m_StatusIcons.Init(); + m_Crosshairs.Init(); m_Spectator.m_chatEnabled = (m_SayText.m_HUD_saytext->value!=0); @@ -414,6 +415,7 @@ void CHud :: VidInit( void ) m_AmmoSecondary.VidInit(); m_TextMessage.VidInit(); m_StatusIcons.VidInit(); + m_Crosshairs.VidInit(); GetClientVoiceMgr()->VidInit(); } diff --git a/main/source/cl_dll/hud_crosshairs.cpp b/main/source/cl_dll/hud_crosshairs.cpp new file mode 100644 index 00000000..48e01806 --- /dev/null +++ b/main/source/cl_dll/hud_crosshairs.cpp @@ -0,0 +1,208 @@ +#include "hud.h" +#include "cl_util.h" +#include "parsemsg.h" +#include "hudgl.h" + +int CHudCrosshairs::Init() +{ + m_iFlags = HUD_ACTIVE; + + cl_cross = CVAR_CREATE("cl_cross", "0", FCVAR_ARCHIVE); + cl_cross_color = CVAR_CREATE("cl_cross_color", "0 255 0", FCVAR_ARCHIVE); + cl_cross_alpha = CVAR_CREATE("cl_cross_alpha", "255", FCVAR_ARCHIVE); + cl_cross_thickness = CVAR_CREATE("cl_cross_thickness", "2", FCVAR_ARCHIVE); + cl_cross_size = CVAR_CREATE("cl_cross_size", "10", FCVAR_ARCHIVE); + cl_cross_gap = CVAR_CREATE("cl_cross_gap", "3", FCVAR_ARCHIVE); + cl_cross_outline = CVAR_CREATE("cl_cross_outline", "0", 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", "1", FCVAR_ARCHIVE); + //cl_cross_circle_radius = CVAR_CREATE("cl_cross_circle_radius", "0", FCVAR_ARCHIVE); + 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); + cl_cross_dot_outline = CVAR_CREATE("cl_cross_dot_outline", "1", FCVAR_ARCHIVE); + cl_cross_top_line = CVAR_CREATE("cl_cross_top_line", "1", FCVAR_ARCHIVE); + cl_cross_bottom_line = CVAR_CREATE("cl_cross_bottom_line", "1", FCVAR_ARCHIVE); + cl_cross_left_line = CVAR_CREATE("cl_cross_left_line", "1", FCVAR_ARCHIVE); + cl_cross_right_line = CVAR_CREATE("cl_cross_right_line", "1", FCVAR_ARCHIVE); + + 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; + + //// 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; + + 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. + // 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. ex. below is for bottom line. Would also cause certain crosshairs that have outlines on invisible cross lines to not look right. + // 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) { + gl.color(0, 0, 0, alpha); + //gl.color(0, 0, 0, outalpha); + 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 + if (cl_cross_top_line->value) { + 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 + if (cl_cross_bottom_line->value) { + 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 + if (cl_cross_left_line->value) { + 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 + if (cl_cross_right_line->value) { + 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; + + if (cl_cross_top_line->value) + gl.line(Vector2D(center.x, center.y - gap - size), Vector2D(center.x, center.y - gap)); + if (cl_cross_bottom_line->value) + gl.line(Vector2D(center.x, center.y + gap + size), Vector2D(center.x, center.y + gap)); + if (cl_cross_left_line->value) + gl.line(Vector2D(center.x - gap - size, center.y), Vector2D(center.x - gap, center.y)); + if (cl_cross_right_line->value) + gl.line(Vector2D(center.x + gap + size, center.y), Vector2D(center.x + gap, center.y)); + } + + // PLZ FIX: compile errors + //// Draw the circle. + //if (cl_cross_circle_radius->value > 0.0f) { + // gl.line_width(1.0f); + + // 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; + // } + + // gl.circle(center, circle_points); + //} + + // 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; +} diff --git a/main/source/cl_dll/hud_crosshairs.h b/main/source/cl_dll/hud_crosshairs.h new file mode 100644 index 00000000..422d498f --- /dev/null +++ b/main/source/cl_dll/hud_crosshairs.h @@ -0,0 +1,30 @@ +#pragma once +#include + +class CHudCrosshairs : public CHudBase +{ + cvar_t* cl_cross; + cvar_t* cl_cross_color; + cvar_t* cl_cross_alpha; + cvar_t* cl_cross_thickness; + cvar_t* cl_cross_size; + cvar_t* cl_cross_gap; + cvar_t* cl_cross_outline; + cvar_t* cl_cross_outline_inner; + //cvar_t* cl_cross_circle_radius; + cvar_t* cl_cross_dot_size; + cvar_t* cl_cross_dot_color; + cvar_t* cl_cross_dot_outline; + cvar_t* cl_cross_top_line; + cvar_t* cl_cross_bottom_line; + cvar_t* cl_cross_left_line; + cvar_t* cl_cross_right_line; + + //float old_circle_radius; + //std::vector circle_points; + +public: + virtual int Init(); + virtual int VidInit(); + virtual int Draw(float time); +}; diff --git a/main/source/cl_dll/hudgl.cpp b/main/source/cl_dll/hudgl.cpp new file mode 100644 index 00000000..be6fe70e --- /dev/null +++ b/main/source/cl_dll/hudgl.cpp @@ -0,0 +1,88 @@ +#define _USE_MATH_DEFINES +#include "util_vector.h" +#include "hudgl.h" + +#include +#include + +#ifdef _WIN32 +#include +#endif + +#include + +HudGL::HudGL() { + // Same steps as FillRGBA does. + glDisable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +} + +HudGL::~HudGL() { + // Reset the line width in case we changed it. + glLineWidth(1.0f); + + // Same steps as FillRGBA does. + glColor3f(1.0f, 1.0f, 1.0f); + glDisable(GL_BLEND); + glEnable(GL_TEXTURE_2D); +} + +void HudGL::color(float r, float g, float b, float a) const { + glColor4f(r, g, b, a); +} + +void HudGL::color(unsigned char r, unsigned char g, unsigned char b, unsigned char a) const { + glColor4ub(r, g, b, a); +} + +void HudGL::line_width(float width) const { + glLineWidth(width); +} + +void HudGL::line(const Vector2D& start, const Vector2D& end) const { + glBegin(GL_LINES); + glVertex2f(start.x, start.y); + glVertex2f(end.x, end.y); + glEnd(); +} + + +// to fix +//void HudGL::circle(const Vector2D& center, const std::vector& points) const { +// glBegin(GL_LINE_STRIP); +// +// for (const auto& point ,: points) +// glVertex2f(center.x + point.x, center.y + point.y); +// +// glVertex2f(center.x + points[0].x, center.y + points[0].y); +// glEnd(); +//} + +void HudGL::rectangle(const Vector2D& corner_a, const Vector2D& corner_b) const { + glBegin(GL_QUADS); + glVertex2f(corner_a.x, corner_a.y); + glVertex2f(corner_a.x, corner_b.y); + glVertex2f(corner_b.x, corner_b.y); + glVertex2f(corner_b.x, corner_a.y); + glEnd(); +} + +// to fix +//std::vector HudGL::compute_circle(float radius) { +// // Maximum allowed distance between the circle and the rendered line segment. +// const float MAX_ERROR = 0.1f; +// const unsigned segment_count = +// static_cast(std::ceil(M_PI / std::acos((radius - MAX_ERROR) / radius))); +// +// std::vector points; +// points.reserve(segment_count); +// +// for (unsigned i = 0; i < segment_count; ++i) { +// float angle = static_cast(M_PI * 2 * i / segment_count); +// points.emplace_back(radius * std::cos(angle), radius * std::sin(angle)); +// } +// +// return points; +//} diff --git a/main/source/cl_dll/hudgl.h b/main/source/cl_dll/hudgl.h new file mode 100644 index 00000000..1432bd8d --- /dev/null +++ b/main/source/cl_dll/hudgl.h @@ -0,0 +1,17 @@ +# pragma comment(lib,"opengl32.lib") +#include + +class HudGL { +public: + HudGL(); + ~HudGL(); + + void color(float r, float g, float b, float a) const; + void color(unsigned char r, unsigned char g, unsigned char b, unsigned char a) const; + void line_width(float width) const; + void line(const Vector2D& start, const Vector2D& end) const; + void circle(const Vector2D& center, const std::vector& points) const; + void rectangle(const Vector2D& corner_a, const Vector2D& corner_b) const; + + static std::vector compute_circle(float radius); +};