WIP crosshair system

This commit is contained in:
pierow 2018-06-10 19:14:31 -04:00
parent b3fcf00ea8
commit f0f16adfe6
8 changed files with 364 additions and 1 deletions

View file

@ -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;

View file

@ -164,6 +164,8 @@
<Optimization Condition="'$(Configuration)|$(Platform)'=='Playtest|Win32'">MaxSpeed</Optimization>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Playtest|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<ClCompile Include="hudgl.cpp" />
<ClCompile Include="hud_crosshairs.cpp" />
<ClCompile Include="hud_msg.cpp">
<Optimization Condition="'$(Configuration)|$(Platform)'=='Playtest|Win32'">MaxSpeed</Optimization>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Playtest|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
@ -799,6 +801,8 @@
<ClInclude Include="GameStudioModelRenderer.h" />
<ClInclude Include="health.h" />
<ClInclude Include="hud.h" />
<ClInclude Include="hudgl.h" />
<ClInclude Include="hud_crosshairs.h" />
<ClInclude Include="hud_iface.h" />
<ClInclude Include="hud_servers.h" />
<ClInclude Include="hud_servers_priv.h" />

View file

@ -594,6 +594,12 @@
<ClCompile Include="cdll_int.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="hud_crosshairs.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="hudgl.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\mod\AvHAlienAbilities.h">
@ -1040,6 +1046,12 @@
<ClInclude Include="..\textrep\TRTagValuePair.h">
<Filter>textrep</Filter>
</ClInclude>
<ClInclude Include="hud_crosshairs.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="hudgl.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Library Include="..\lib\public\game_controls.lib" />

View file

@ -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();
}

View file

@ -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;
}

View file

@ -0,0 +1,30 @@
#pragma once
#include <vector>
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<Vector2D> circle_points;
public:
virtual int Init();
virtual int VidInit();
virtual int Draw(float time);
};

View file

@ -0,0 +1,88 @@
#define _USE_MATH_DEFINES
#include "util_vector.h"
#include "hudgl.h"
#include <cmath>
#include <vector>
#ifdef _WIN32
#include <Windows.h>
#endif
#include <GL/gl.h>
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<Vector2D>& 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<Vector2D> 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<unsigned>(std::ceil(M_PI / std::acos((radius - MAX_ERROR) / radius)));
//
// std::vector<Vector2D> points;
// points.reserve(segment_count);
//
// for (unsigned i = 0; i < segment_count; ++i) {
// float angle = static_cast<float>(M_PI * 2 * i / segment_count);
// points.emplace_back(radius * std::cos(angle), radius * std::sin(angle));
// }
//
// return points;
//}

View file

@ -0,0 +1,17 @@
# pragma comment(lib,"opengl32.lib")
#include <vector>
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<Vector2D>& points) const;
void rectangle(const Vector2D& corner_a, const Vector2D& corner_b) const;
static std::vector<Vector2D> compute_circle(float radius);
};