Client: Add Cross_ helper functions. This will take care of common crosshair specific rendering tasks, as well as handle third-person and XR versions of crosshairs.

This commit is contained in:
Marco Cawthorne 2022-12-28 16:48:57 -08:00
parent 633046d28e
commit 3c71b49b49
Signed by: eukara
GPG Key ID: CE2032F0A2882A22
12 changed files with 345 additions and 76 deletions

View File

@ -13,6 +13,15 @@
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/** Registers console commands that are provided by Nuclide. */
void Cmd_Init(void);
int Cmd_Parse(string);
/** @brief Interprets a console command that is not defined within the gamesources.
Called from CSQC_ConsoleCommand to handle any builtin commands from the Nuclide SDK,
unless a game decided to implement its own interpretation of the commands.
@param strCommand the command (with parameters) in question
@return true if the command was successfully handled, false if not. */
bool Cmd_Parse(string strCommand);

View File

@ -14,7 +14,7 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void
static void
CMD_testPointLight(void)
{
makevectors(getproperty(VF_ANGLES));
@ -22,7 +22,7 @@ CMD_testPointLight(void)
dynamiclight_spawnstatic(trace_endpos + (v_forward * -16), 1024, [1,1,1]);
}
void
static void
CMD_dev_modeltest(void)
{
entity mt = spawn();
@ -34,7 +34,7 @@ CMD_dev_modeltest(void)
mt.angles[0] = mt.angles[2] = 0;
}
void
static void
CMD_dev_explode(void)
{
makevectors(getproperty(VF_ANGLES));
@ -42,7 +42,7 @@ CMD_dev_explode(void)
FX_Explosion(trace_endpos);
}
void
static void
CMD_dev_sunpos(void)
{
vector sunpos, sunang;
@ -63,7 +63,7 @@ CMD_dev_sunpos(void)
print(sprintf("light_environment: sunangle: %d; pitch: %d\n", leang[1], leang[0]));
}
void
static void
CMD_dev_measure(void)
{
static vector measurepos;
@ -76,7 +76,7 @@ CMD_dev_measure(void)
}
}
void
static void
CMD_vote(void)
{
if (argv(1) == "yes") {
@ -86,45 +86,45 @@ CMD_vote(void)
}
}
void
static void
CMD_getpos(void)
{
print(sprintf("setpos %v;setang -%v\n", getproperty(VF_ORIGIN), getproperty(VF_ANGLES)));
}
void
static void
CMD_setpos(void)
{
localcmd(sprintf("cmd setpos \"%s\"\n", argv(1)));
}
void
static void
CMD_setang(void)
{
g_view.SetCameraAngle(stov(argv(1)));
g_view.SetClientAngle(stov(argv(1)));
}
void
static void
CMD_titles_test(void)
{
GameMessage_Setup(argv(1), 0);
}
void
static void
CMD_way_menu(void)
{
Way_Autoload();
Textmenu_Call("WAY_MENU");
}
void
static void
CMD_view_geomtest(void)
{
Weapons_SetGeomset(sprintf("geomset %s %s\n", argv(1), argv(2)));
}
void
static void
CMD_player_geomtest(void)
{
setcustomskin(pSeat->m_ePlayer, "", sprintf("geomset %s %s\n", argv(1), argv(2)));
@ -140,7 +140,7 @@ CMD_Cleardecals(void)
}
/* Wishlist: list size and potential vmem usage */
void
static void
CMD_ListModels(void)
{
string tmp;
@ -159,7 +159,7 @@ CMD_ListModels(void)
}
/* Wishlist: list size and samplerate/bitdepth */
void
static void
CMD_ListSounds(void)
{
string tmp;
@ -182,7 +182,7 @@ CMD_ListSounds(void)
print(sprintf("\t%f seconds worth of samples\n", total_length));
}
void
static void
CMD_ListParticles(void)
{
string tmp;
@ -210,7 +210,7 @@ Returns 0 if the command isn't handled and the engine is expected
to handle it from there.
=================
*/
int
bool
Cmd_Parse(string sCMD)
{
switch (argv(0)) {
@ -378,9 +378,9 @@ Cmd_Parse(string sCMD)
pSeat->m_iInputReload = FALSE;
break;
default:
return (0);
return (false);
}
return (1);
return (true);
}
/*

74
src/client/crosshair.h Normal file
View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2016-2022 Vera Visions LLC.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*! @file crosshair.h
@brief Crosshair helper functions.
Helper functions for dealing with crosshairs in games.
If you don't want to deal with handling accurate crosshairs in
a variety of view modes (1st-person, 3rd-person, XR) then simply
use one of the supplied functions.
*/
/** Draws a crosshair on the screen with the desired material and size.
@param strMat is the material to use.
@param vecSize is the size in pixels it is meant to take up on screen. */
void Cross_Draw(string strMat, vector vecSize);
/** Draw a given crosshair on the screen, with variable color.
@param strMat is the material to use.
@param vecSize is the size in pixels it is meant to take up on screen.
@param vecColor is the normalized color values to tint the surface with.*/
void Cross_DrawRGB(string strMat, vector vecSize, vector vecColor);
/** Draw a given crosshair on the screen, with variable color and alpha.
@param strMat is the material to use.
@param vecSize is the size in pixels it is meant to take up on screen.
@param vecColor is the normalized color values to tint the surface with.
@param flAlpha is the alpha values to use on the whole surface.*/
void Cross_DrawRGBA(string strMat, vector vecSize, vector vecColor, float flAlpha);
/** Draw a given crosshair on the screen, of only a section from a material.
@param strMat is the material to use.
@param vecSize is the size in pixels it is meant to take up on screen.
@param vecSrcPos is a normalized starting position within the material from which we should start drawing from.
@param vecSrcSize is the normalized size within the material from which we should draw from.*/
void Cross_DrawSub(string strMat, vector vecSize, vector vecSrcPos, vector vecSrcSize);
/** Draw a given crosshair on the screen, of only a section from a material, with variable color.
@param strMat is the material to use.
@param vecSize is the size in pixels it is meant to take up on screen.
@param vecSrcPos is a normalized starting position within the material from which we should start drawing from.
@param vecSrcSize is the normalized size within the material from which we should draw from.
@param vecColor is the normalized color values to tint the surface with.*/
void Cross_DrawSubRGB(string strMat, vector vecSize, vector vecSrcPos, vector vecSrcSize, vector vecColor);
/** Draw a given crosshair on the screen, of only a section from a material, with variable color/alpha.
@param strMat is the material to use.
@param vecSize is the size in pixels it is meant to take up on screen.
@param vecSrcPos is a normalized starting position within the material from which we should start drawing from.
@param vecSrcSize is the normalized size within the material from which we should draw from.
@param vecColor is the normalized color values to tint the surface with.
@param flAlpha is the alpha values to use on the whole surface.*/
void Cross_DrawSubRGBA(string strMat, vector vecSize, vector vecSrcPos, vector vecSrcSize, vector vecColor, float flAlpha);

71
src/client/crosshair.qc Normal file
View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2016-2022 Vera Visions LLC.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void
Cross_Draw(string strMat, vector vecSize)
{
Cross_DrawSubRGBA(strMat, vecSize, [0,0], [1,1], [1.0f, 1.0f, 1.0f], 1.0f);
}
void
Cross_DrawRGB(string strMat, vector vecSize, vector vecColor)
{
Cross_DrawSubRGBA(strMat, vecSize, [0,0], [1,1], vecColor, 1.0f);
}
void
Cross_DrawRGBA(string strMat, vector vecSize, vector vecColor, float flAlpha)
{
Cross_DrawSubRGBA(strMat, vecSize, [0,0], [1,1], vecColor, flAlpha);
}
void
Cross_DrawSub(string strMat, vector vecSize, vector vecSrcPos, vector vecSrcSize)
{
Cross_DrawSubRGBA(strMat, vecSize, vecSrcPos, vecSrcSize, [1.0f, 1.0f, 1.0f], 1.0f);
}
void
Cross_DrawSubRGB(string strMat, vector vecSize, vector vecSrcPos, vector vecSrcSize, vector vecColor)
{
Cross_DrawSubRGBA(strMat, vecSize, vecSrcPos, vecSrcSize, vecColor, 1.0f);
}
void
Cross_DrawSubRGBA(string strMat, vector vecSize, vector vecSrcPos, vector vecSrcSize, vector vecColor, float flAlpha)
{
static vector cross_pos;
if (cvar("cl_thirdperson") < 1) {
cross_pos = g_hudmins + (g_hudres / 2) + [-(vecSize[0]/2),-(vecSize[1]/2)];
cross_pos[0] = rint(cross_pos[0]);
cross_pos[1] = rint(cross_pos[1]);
drawsubpic(cross_pos, vecSize, strMat, vecSrcPos, vecSrcSize, vecColor, flAlpha, DRAWFLAG_NORMAL);
} else {
vector vecSrc;
vector vecDst;
player pl = pSeat->m_ePlayer;
vecSrc = pSeat->m_vecPredictedOrigin + pSeat->m_ePlayer.view_ofs;
makevectors(view_angles);
vecDst = (vecSrc + v_forward * 4096);
traceline(vecSrc, vecDst, MOVE_NORMAL, pSeat->m_ePlayer);
cross_pos = project(trace_endpos) + [-(vecSize[0]/2),-(vecSize[1]/2)];
cross_pos[0] = rint(cross_pos[0]);
cross_pos[1] = rint(cross_pos[1]);
drawsubpic(cross_pos, vecSize, strMat, vecSrcPos, vecSrcSize, vecColor, flAlpha, DRAWFLAG_NORMAL);
}
}

View File

@ -22,6 +22,7 @@
#include "cmd.h"
#include "util.h"
#include "NSView.h"
#include "crosshair.h"
#define READENTITY_BYTE(field, changedflag) {\
if (flChanged & changedflag)\

View File

@ -14,54 +14,132 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* flags for 2d drawing */
#define DRAWFLAG_NORMAL 0
#define DRAWFLAG_ADDITIVE 1
#define DRAWFLAG_MODULATE 2
#define DRAWFLAG_2XMODULATE 3
/** Flags for 2D drawing operations. */
typedef enum
{
DRAWFLAG_NORMAL = 0, /**< The default. */
DRAWFLAG_ADDITIVE, /**< Render with an additive blend mode. */
DRAWFLAG_MODULATE, /**< Not implemented in FTEQW. */
DRAWFLAG_2XMODULATE /**< Not implemented in FTEQW. */
} drawflag_t;
enumflags
/** Defines the valid alignment flags for text fields.
@sa Font_DrawField */
typedef enumflags
{
AF_LEFT,
AF_TOP,
AF_RIGHT,
AF_BOTTOM
};
} alignflags_t;
/** Representation of a font. */
typedef struct
{
int iID;
int iScaleX;
int iScaleY;
vector vecColor;
float flAlpha;
int iFlags;
int iID; /**< Internal ID, will be passed to 'drawfont' before rendering text. */
int iScaleX; /**< Suggested maximum width of a character in the font. */
int iScaleY; /**< Maximum height of a chracter in the font. */
vector vecColor; /**< Suggested default color of the font. */
float flAlpha; /**< Suggested default alpha of the font. */
int iFlags; /**< Rendering flags that the font posesses. @sa drawflag_t */
} font_s;
/** Load a desired .font definition into memory.
@param strFile is the path to the file in question.
@param fntNew is the location of where the font will be stored. */
void Font_Load(string strFile, font_s &fntNew);
/* standard drawing */
/** Draw text on the screen at the desired position with a desired font.
@param vecOrigin is the absolute starting position.
@param strText is the text to be drawn.
@param fnt is the font to be used. */
void Font_DrawText(vector vecOrigin, string strText, font_s fnt);
/** Draw alpha-blended text on the screen at the desired position with a desired font.
@param vecOrigin is the absolute starting position.
@param strText is the text to be drawn.
@param a is the alpha value to blend with.
@param fnt is the font to be used. */
void Font_DrawText_A(vector vecOrigin, string strText, float a, font_s fnt);
/** Draw tinted text on the screen at the desired position with a desired font.
@param vecOrigin is the absolute starting position.
@param strText is the text to be drawn.
@param col is the normalized color value to tint the text with.
@param fnt is the font to be used. */
void Font_DrawText_RGB(vector vecOrigin, string strText, vector col, font_s fnt);
/** Draw tinted and alpha blended text on the screen at the desired position
with a desired font.
@param vecOrigin is the absolute starting position.
@param strText is the text to be drawn.
@param col is the normalized color value to tint the text with.
@param a is the alpha value to blend with.
@param fnt is the font to be used. */
void Font_DrawText_RGBA(vector vecOrigin, string strText, vector col, float a, font_s fnt);
/* right aligned variants */
/** Right-aligned variant of Font_DrawText.
@sa Font_DrawText */
void Font_DrawRText(vector vecOrigin, string strText, font_s fnt);
/** Right-aligned variant of Font_DrawText_A.
@sa Font_DrawText_A */
void Font_DrawRText_A(vector vecOrigin, string strText, float a, font_s fnt);
/** Right-aligned variant of Font_DrawText_RGB.
@sa Font_DrawText_RGB */
void Font_DrawRText_RGB(vector vecOrigin, string strText, vector col, font_s fnt);
/** Right-aligned variant of Font_DrawText_RGBA.
@sa Font_DrawText_RGBA */
void Font_DrawRText_RGBA(vector vecOrigin, string strText, vector col, float a, font_s fnt);
void Font_DrawField(vector vecOrigin, vector vecSize, string strText, font_s fnt, int iAlignFlags);
/** Draws a textfield with line wrapping.
/* returns a 0xFFFFFF type color code you can put into your strings */
@param vecOrigin is the absolute starting position.
@param vecSize is the total area in pixels that the field takes up on the screen.
@param strText is the text to be drawn onto the screen.
@param fnt is the font to be used for rendering the text.
@param iAlignFlags sets how the text may be aligned. */
void Font_DrawField(vector vecOrigin, vector vecSize, string strText, font_s fnt, alignflags_t iAlignFlags);
/** Converts a normalized RGB color vector to a hex color string.
@param vecColor is the normalized input color. E.g. [1.0f, 0.0f, 0.0f]
@return is a hex color string. e.g. "^xF00" */
string Font_RGBtoHex(vector vecColor);
/* gets the height for a single character of the specified font */
int Font_GetHeight(font_s);
/** @brief Returns the height of a specified font in pixels.
@param fnt is the font to be queried.
@return is the height of a font in pixels.
@sa Font_StringWidth
*/
int Font_GetHeight(font_s fnt);
/* gets the width of a series of characters */
float Font_StringWidth(string strText, float flColors, font_s fnt);
/** @brief Returns the width of a series of characters in pixels.
/* get the 'drawfont' ID, only use this when porting old code quickly. */
If you have a string with funstring color codes (e.g. ^1 or ^xF00) and want to make
sure those are not interpreted as visible characters, set the parameter hasColor
to true. Rendering may be more expensive this way, but you should generally cache the
result instead of querying it every frame anyway.
The return value is of type float, to be a drop-in replacement for the engine builtin
stringwidth().
@param strText is the text to get the length of.
@param hasColor hints if funstring color codes are present in the string.
@param fnt is the font used with the text in question. */
float Font_StringWidth(string strText, bool hasColor, font_s fnt);
/** @brief Get the internal font id.
The internal font id is only useful for when you want to assign 'drawfont'
yourself, or have some other use for it. Those id's are meant to be unique,
but may change between vid_reload or other cases where video memory is de-allocated.
Overall you should never need to use this, unless you know what you're doing or are
porting old code.
@param fnt is the font to be queried.
@return the internal 'drawfont' id of the specified font. */
float Font_GetID(font_s fnt);

View File

@ -152,7 +152,7 @@ Font_DrawRText_RGBA(vector vecOrigin, string strText, vector rgb, float a, font_
}
void
Font_DrawField(vector vecOrigin, vector vecSize, string strText, font_s fnt, int iAlignFlags)
Font_DrawField(vector vecOrigin, vector vecSize, string strText, font_s fnt, alignflags_t iAlignFlags)
{
drawfont = (float)fnt.iID;
drawfontscale[0] = (float)fnt.iScaleX / 8;
@ -186,11 +186,11 @@ Font_GetHeight(font_s fnt)
}
float
Font_StringWidth(string strText, float flColors, font_s fnt)
Font_StringWidth(string strText, bool hasColor, font_s fnt)
{
float w;
drawfont = (float)fnt.iID;
w = stringwidth(strText, flColors, [fnt.iScaleX, fnt.iScaleY]);
w = stringwidth(strText, (float)hasColor, [fnt.iScaleX, fnt.iScaleY]);
drawfont = 0;
drawfontscale = [1,1,0];
return w;

View File

@ -26,5 +26,6 @@ shake.qc
cmd.qc
event.qc
entry.qc
crosshair.qc
util.qc
#endlist

View File

@ -14,18 +14,50 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/** @brief Definition of a text channel.
A text channel is a special type of text string that is commonly
defined within the titles.txt file of a game. Common use cases are
chapter titles and message with a special type of fade in/out rendering effect
on them.*/
typedef struct
{
string m_strMessage;
float m_flPosX;
float m_flPosY;
int m_iEffect;
vector m_vecColor1;
vector m_vecColor2;
float m_flFadeIn;
float m_flFadeOut;
float m_flHoldTime;
float m_flFXTime;
float m_flTime;
string m_strMessage; /**< the message contents. */
float m_flPosX; /**< Normalized starting position on the X-axis. -1 is center. */
float m_flPosY; /**< Normalized starting position on the X-axis. -1 is center. */
int m_iEffect; /**< Effect to use when rendering the text. */
vector m_vecColor1; /**< Primary text color. */
vector m_vecColor2; /**< Secondary text color for use with effects. */
float m_flFadeIn; /**< Time in seconds it takes for the text to fade in. */
float m_flFadeOut; /**< Time in seconds it takes for the text to fade out. */
float m_flHoldTime; /**< Time in seconds on which we'll hold onto the text. */
float m_flFXTime; /**< Time in seconds that it takes for the effect to finish. */
float m_flTime; /**< The time that's passed on the active channel. */
} gametext_t;
/** Global pool of text channels. */
gametext_t g_textchannels[6];
/** Used by Nuclide to draw all active text channels to the screen. */
void GameText_Draw(void);
/** @brief Places a message within a specified channel.
We look up a message within our titles.txt file and copy its parameters
and string contents into a text channel.
We have 6 channels in total.
@param strMessage is the message we'll look up.
@param iChannel is the channel it will be stored in. */
void GameMessage_Setup(string strMessage, int iChannel);
/** Used by Nuclide to parse a message delivered by the game_text entity.
@sa game_text */
void GameText_Parse(void);
/** Used by Nuclide to parse a message delivered by the env_message entity.
@sa env_message */
void GameMessage_Parse(void);

View File

@ -15,7 +15,7 @@
*/
/* for effect 2 */
int
static int
GameText_CharCount(float fadein, float timer, string msg)
{
float len = (timer / fadein);
@ -27,7 +27,7 @@ GameText_CharCount(float fadein, float timer, string msg)
}
/* the engine its drawstring doesn't like newlines that much */
void
static void
GameText_DrawString(vector pos, string msg, vector col, float alpha)
{
vector rpos = [0.0f, 0.0f, 0.0f];
@ -58,7 +58,7 @@ GameText_DrawString(vector pos, string msg, vector col, float alpha)
}
}
void
static void
GameText_DrawMessage(int i, float timer, int highlight)
{
float a = 0.0f;

View File

@ -14,25 +14,28 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* Returns if the specified client is a NSClientSpectator, doesn't matter if real or fake */
float Client_IsSpectator(NSClient);
/** Returns if the specified client is a NSClientSpectator, doesn't matter if real or fake */
bool Client_IsSpectator(NSClient);
/* Returns if we're a permanent NSClientSpectator, USE THIS if you want to access NSClientSpectator class attributes */
float Client_IsRealSpectator(NSClient cl);
/** Returns if we're a permanent NSClientSpectator, USE THIS if you want to access NSClientSpectator class attributes */
bool Client_IsRealSpectator(NSClient cl);
/* Returns if we're a fake NSClientSpectator, in case you need to be certain */
float Client_IsFakeSpectator(NSClient cl);
/** Returns if we're a fake NSClientSpectator, in case you need to be certain */
bool Client_IsFakeSpectator(NSClient cl);
/* Return if the specified client is dead. If they're a NSClientSpectator they're always alive. */
float Client_IsDead(NSClient);
/** Return if the specified client is dead. If they're a NSClientSpectator they're always alive. */
bool Client_IsDead(NSClient);
/* Returns if the specified client is a playable client class */
float Client_IsPlayer(NSClient cl);
/** Returns if the specified client is a playable client class */
bool Client_IsPlayer(NSClient cl);
/* Are we in an intermission? (Match ending screen) */
float Client_InIntermission(void);
/** Are we in an intermission? (Match ending screen) */
bool Client_InIntermission(void);
string Util_GetKeyString(string);
/** Returns the name of the key that a given command is bound to.
@param strBind the command in question. E.g. "+forward" */
string Util_GetKeyString(string strBind);
/** Returns if the currently active client-seat is in a vehicle. */
bool Client_InVehicle(void);

View File

@ -14,7 +14,7 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
float
bool
Client_IsSpectator(NSClient cl)
{
if (cl.IsRealSpectator() || cl.IsFakeSpectator())
@ -23,25 +23,25 @@ Client_IsSpectator(NSClient cl)
return false;
}
float
bool
Client_IsRealSpectator(NSClient cl)
{
return cl.IsRealSpectator();
}
float
bool
Client_IsFakeSpectator(NSClient cl)
{
return cl.IsFakeSpectator();
}
float
bool
Client_IsDead(NSClient cl)
{
return cl.IsDead();
}
float
bool
Client_IsPlayer(NSClient cl)
{
return cl.IsPlayer();