2
0
mirror of https://github.com/FWGS/hlsdk-xash3d synced 2024-11-22 01:47:45 +01:00
hlsdk-xash3d/cl_dll/hud_redraw.cpp

440 lines
10 KiB
C++
Raw Normal View History

2016-06-04 15:24:23 +02:00
/***
*
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
//
// hud_redraw.cpp
//
2019-10-13 15:37:32 +02:00
#include <cmath>
2016-06-04 15:24:23 +02:00
#include "hud.h"
#include "cl_util.h"
//#include "triangleapi.h"
#if USE_VGUI
#include "vgui_TeamFortressViewport.h"
#endif
2016-06-04 15:24:23 +02:00
#define MAX_LOGO_FRAMES 56
2016-07-03 15:39:55 +02:00
int grgLogoFrame[MAX_LOGO_FRAMES] =
2016-06-04 15:24:23 +02:00
{
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, 13, 13, 13, 12, 11, 10, 9, 8, 14, 15,
16, 17, 18, 19, 20, 20, 20, 20, 20, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
29, 29, 29, 29, 29, 28, 27, 26, 25, 24, 30, 31
};
extern int g_iVisibleMouse;
float HUD_GetFOV( void );
extern cvar_t *sensitivity;
// Think
2016-07-03 15:39:55 +02:00
void CHud::Think( void )
2016-06-04 15:24:23 +02:00
{
#if USE_VGUI
m_scrinfo.iSize = sizeof(m_scrinfo);
GetScreenInfo(&m_scrinfo);
#endif
2016-06-04 15:24:23 +02:00
int newfov;
HUDLIST *pList = m_pHudList;
2016-07-03 15:39:55 +02:00
while( pList )
2016-06-04 15:24:23 +02:00
{
2016-07-03 15:39:55 +02:00
if( pList->p->m_iFlags & HUD_ACTIVE )
2016-06-04 15:24:23 +02:00
pList->p->Think();
pList = pList->pNext;
}
newfov = HUD_GetFOV();
2016-07-03 15:39:55 +02:00
if( newfov == 0 )
2016-06-04 15:24:23 +02:00
{
m_iFOV = default_fov->value;
}
else
{
m_iFOV = newfov;
}
// the clients fov is actually set in the client data update section of the hud
// Set a new sensitivity
2016-07-03 15:39:55 +02:00
if( m_iFOV == default_fov->value )
{
2016-06-04 15:24:23 +02:00
// reset to saved sensitivity
m_flMouseSensitivity = 0;
}
else
2016-07-03 15:39:55 +02:00
{
2016-06-04 15:24:23 +02:00
// set a new sensitivity that is proportional to the change from the FOV default
m_flMouseSensitivity = sensitivity->value * ((float)newfov / (float)default_fov->value) * CVAR_GET_FLOAT("zoom_sensitivity_ratio");
}
// think about default fov
2016-07-03 15:39:55 +02:00
if( m_iFOV == 0 )
{
// only let players adjust up in fov, and only if they are not overriden by something else
2019-08-11 23:25:50 +02:00
m_iFOV = Q_max( default_fov->value, 90 );
2016-06-04 15:24:23 +02:00
}
2024-02-12 23:41:13 +01:00
if( gEngfuncs.IsSpectateOnly() )
{
m_iFOV = gHUD.m_Spectator.GetFOV(); // default_fov->value;
}
2016-06-04 15:24:23 +02:00
}
// Redraw
// step through the local data, placing the appropriate graphics & text as appropriate
// returns 1 if they've changed, 0 otherwise
2016-07-03 15:39:55 +02:00
int CHud::Redraw( float flTime, int intermission )
2016-06-04 15:24:23 +02:00
{
m_fOldTime = m_flTime; // save time of previous redraw
m_flTime = flTime;
2019-10-13 13:49:25 +02:00
m_flTimeDelta = (double)( m_flTime - m_fOldTime );
2016-06-04 15:24:23 +02:00
static float m_flShotTime = 0;
2016-07-03 15:39:55 +02:00
2016-06-04 15:24:23 +02:00
// Clock was reset, reset delta
2016-07-03 15:39:55 +02:00
if( m_flTimeDelta < 0 )
2016-06-04 15:24:23 +02:00
m_flTimeDelta = 0;
#if USE_VGUI
// Bring up the scoreboard during intermission
if (gViewPort)
{
if( m_iIntermission && !intermission )
{
// Have to do this here so the scoreboard goes away
m_iIntermission = intermission;
gViewPort->HideCommandMenu();
gViewPort->HideScoreBoard();
gViewPort->UpdateSpectatorPanel();
}
else if( !m_iIntermission && intermission )
{
m_iIntermission = intermission;
gViewPort->HideCommandMenu();
gViewPort->HideVGUIMenu();
#if !USE_NOVGUI_SCOREBOARD
gViewPort->ShowScoreBoard();
#endif
gViewPort->UpdateSpectatorPanel();
// Take a screenshot if the client's got the cvar set
if( CVAR_GET_FLOAT( "hud_takesshots" ) != 0 )
m_flShotTime = flTime + 1.0; // Take a screenshot in a second
}
}
#else
if( !m_iIntermission && intermission )
{
// Take a screenshot if the client's got the cvar set
if( CVAR_GET_FLOAT( "hud_takesshots" ) != 0 )
2019-10-13 13:49:25 +02:00
m_flShotTime = flTime + 1.0f; // Take a screenshot in a second
}
#endif
2016-07-03 15:39:55 +02:00
if( m_flShotTime && m_flShotTime < flTime )
2016-06-04 15:24:23 +02:00
{
2016-07-03 15:39:55 +02:00
gEngfuncs.pfnClientCmd( "snapshot\n" );
2016-06-04 15:24:23 +02:00
m_flShotTime = 0;
}
m_iIntermission = intermission;
// if no redrawing is necessary
// return 0;
2016-07-03 15:39:55 +02:00
m_iHudNumbersYOffset = IsHL25() ? m_iFontHeight * 0.2 : 0;
2016-07-03 15:39:55 +02:00
if( m_pCvarDraw->value )
2016-06-04 15:24:23 +02:00
{
HUDLIST *pList = m_pHudList;
2016-07-03 15:39:55 +02:00
while( pList )
2016-06-04 15:24:23 +02:00
{
2016-07-03 15:39:55 +02:00
if( !intermission )
2016-06-04 15:24:23 +02:00
{
2016-07-03 15:39:55 +02:00
if ( ( pList->p->m_iFlags & HUD_ACTIVE ) && !( m_iHideHUDDisplay & HIDEHUD_ALL ) )
pList->p->Draw( flTime );
2016-06-04 15:24:23 +02:00
}
else
2016-07-03 15:39:55 +02:00
{
// it's an intermission, so only draw hud elements that are set to draw during intermissions
if( pList->p->m_iFlags & HUD_INTERMISSION )
2016-06-04 15:24:23 +02:00
pList->p->Draw( flTime );
}
pList = pList->pNext;
}
}
// are we in demo mode? do we need to draw the logo in the top corner?
2016-07-03 15:39:55 +02:00
if( m_iLogo )
2016-06-04 15:24:23 +02:00
{
int x, y, i;
2016-07-03 15:39:55 +02:00
if( m_hsprLogo == 0 )
m_hsprLogo = LoadSprite( "sprites/%d_logo.spr" );
SPR_Set( m_hsprLogo, 250, 250, 250 );
2016-06-04 15:24:23 +02:00
2016-07-03 15:39:55 +02:00
x = SPR_Width( m_hsprLogo, 0 );
2016-06-04 15:24:23 +02:00
x = ScreenWidth - x;
2016-07-03 15:39:55 +02:00
y = SPR_Height( m_hsprLogo, 0 ) / 2;
2016-06-04 15:24:23 +02:00
// Draw the logo at 20 fps
2016-07-03 15:39:55 +02:00
int iFrame = (int)( flTime * 20 ) % MAX_LOGO_FRAMES;
2016-06-04 15:24:23 +02:00
i = grgLogoFrame[iFrame] - 1;
2016-07-03 15:39:55 +02:00
SPR_DrawAdditive( i, x, y, NULL );
2016-06-04 15:24:23 +02:00
}
/*
2016-07-03 15:39:55 +02:00
if( g_iVisibleMouse )
2016-06-04 15:24:23 +02:00
{
void IN_GetMousePos( int *mx, int *my );
int mx, my;
IN_GetMousePos( &mx, &my );
2016-07-03 15:39:55 +02:00
if( m_hsprCursor == 0 )
2016-06-04 15:24:23 +02:00
{
2022-11-14 03:41:21 +01:00
m_hsprCursor = SPR_Load( "sprites/cursor.spr" );
2016-06-04 15:24:23 +02:00
}
2016-07-03 15:39:55 +02:00
SPR_Set( m_hsprCursor, 250, 250, 250 );
2016-06-04 15:24:23 +02:00
// Draw the logo at 20 fps
SPR_DrawAdditive( 0, mx, my, NULL );
}
*/
return 1;
}
void ScaleColors( int &r, int &g, int &b, int a )
{
float x = (float)a / 255;
2016-07-03 15:39:55 +02:00
r = (int)( r * x );
g = (int)( g * x );
b = (int)( b * x );
2016-06-04 15:24:23 +02:00
}
const unsigned char colors[8][3] =
{
{127, 127, 127}, // additive cannot be black
{255, 0, 0},
{ 0, 255, 0},
{255, 255, 0},
{ 0, 0, 255},
{ 0, 255, 255},
{255, 0, 255},
{240, 180, 24}
};
2017-06-29 15:56:03 +02:00
int CHud::DrawHudString( int xpos, int ypos, int iMaxX, const char *szIt, int r, int g, int b )
2016-06-04 15:24:23 +02:00
{
if( hud_textmode->value == 2 )
{
2016-07-03 15:39:55 +02:00
gEngfuncs.pfnDrawSetTextColor( r / 255.0, g / 255.0, b / 255.0 );
2016-06-04 15:24:23 +02:00
return gEngfuncs.pfnDrawConsoleString( xpos, ypos, (char*) szIt );
}
// xash3d: reset unicode state
TextMessageDrawChar( 0, 0, 0, 0, 0, 0 );
// draw the string until we hit the null character or a newline character
2016-07-03 15:39:55 +02:00
for( ; *szIt != 0 && *szIt != '\n'; szIt++ )
2016-06-04 15:24:23 +02:00
{
2016-07-03 15:39:55 +02:00
int w = gHUD.m_scrinfo.charWidths['M'];
if( xpos + w > iMaxX )
2016-06-04 15:24:23 +02:00
return xpos;
2016-07-03 15:39:55 +02:00
if( ( *szIt == '^' ) && ( *( szIt + 1 ) >= '0') && ( *( szIt + 1 ) <= '7') )
2016-06-04 15:24:23 +02:00
{
szIt++;
2016-07-03 15:39:55 +02:00
r = colors[*szIt - '0'][0];
g = colors[*szIt - '0'][1];
b = colors[*szIt - '0'][2];
if( !*(++szIt) )
2016-06-04 15:24:23 +02:00
return xpos;
}
int c = (unsigned int)(unsigned char)*szIt;
xpos += TextMessageDrawChar( xpos, ypos, c, r, g, b );
}
2017-03-29 21:59:50 +02:00
return xpos;
}
2017-06-29 15:56:03 +02:00
int DrawUtfString( int xpos, int ypos, int iMaxX, const char *szIt, int r, int g, int b )
2017-03-29 21:59:50 +02:00
{
if (IsXashFWGS())
2017-03-29 21:59:50 +02:00
{
// xash3d: reset unicode state
gEngfuncs.pfnVGUI2DrawCharacterAdditive( 0, 0, 0, 0, 0, 0, 0 );
// draw the string until we hit the null character or a newline character
for( ; *szIt != 0 && *szIt != '\n'; szIt++ )
2017-03-29 21:59:50 +02:00
{
int w = gHUD.m_scrinfo.charWidths['M'];
if( xpos + w > iMaxX )
2017-03-29 21:59:50 +02:00
return xpos;
if( ( *szIt == '^' ) && ( *( szIt + 1 ) >= '0') && ( *( szIt + 1 ) <= '7') )
{
szIt++;
r = colors[*szIt - '0'][0];
g = colors[*szIt - '0'][1];
b = colors[*szIt - '0'][2];
if( !*(++szIt) )
return xpos;
}
int c = (unsigned int)(unsigned char)*szIt;
xpos += gEngfuncs.pfnVGUI2DrawCharacterAdditive( xpos, ypos, c, r, g, b, 0 );
2017-03-29 21:59:50 +02:00
}
return xpos;
}
else
{
return gHUD.DrawHudString(xpos, ypos, iMaxX, szIt, r, g, b);
2017-03-29 21:59:50 +02:00
}
2016-06-04 15:24:23 +02:00
}
2017-06-29 15:56:03 +02:00
int CHud::DrawHudStringLen( const char *szIt )
2016-06-04 15:24:23 +02:00
{
int l = 0;
2016-07-03 15:39:55 +02:00
for( ; *szIt != 0 && *szIt != '\n'; szIt++ )
2016-06-04 15:24:23 +02:00
{
2016-07-03 15:39:55 +02:00
l += gHUD.m_scrinfo.charWidths[(unsigned char)*szIt];
2016-06-04 15:24:23 +02:00
}
return l;
}
2016-07-03 15:39:55 +02:00
int CHud::DrawHudNumberString( int xpos, int ypos, int iMinX, int iNumber, int r, int g, int b )
2016-06-04 15:24:23 +02:00
{
char szString[32];
sprintf( szString, "%d", iNumber );
return DrawHudStringReverse( xpos, ypos, iMinX, szString, r, g, b );
}
// draws a string from right to left (right-aligned)
2017-06-29 15:56:03 +02:00
int CHud::DrawHudStringReverse( int xpos, int ypos, int iMinX, const char *szString, int r, int g, int b )
2016-06-04 15:24:23 +02:00
{
// find the end of the string
2017-07-01 23:36:56 +02:00
for( const char *szIt = szString; *szIt != 0; szIt++ )
2016-07-03 15:39:55 +02:00
xpos -= gHUD.m_scrinfo.charWidths[(unsigned char)*szIt];
2016-06-04 15:24:23 +02:00
if( xpos < iMinX )
xpos = iMinX;
DrawHudString( xpos, ypos, gHUD.m_scrinfo.iWidth, szString, r, g, b );
return xpos;
}
2016-07-03 15:39:55 +02:00
int CHud::DrawHudNumber( int x, int y, int iFlags, int iNumber, int r, int g, int b )
2016-06-04 15:24:23 +02:00
{
2016-07-03 15:39:55 +02:00
int iWidth = GetSpriteRect( m_HUD_number_0 ).right - GetSpriteRect( m_HUD_number_0 ).left;
2016-06-04 15:24:23 +02:00
int k;
2016-07-03 15:39:55 +02:00
if( iNumber > 0 )
2016-06-04 15:24:23 +02:00
{
// SPR_Draw 100's
2016-07-03 15:39:55 +02:00
if( iNumber >= 100 )
2016-06-04 15:24:23 +02:00
{
2016-07-03 15:39:55 +02:00
k = iNumber / 100;
SPR_Set( GetSprite( m_HUD_number_0 + k ), r, g, b );
SPR_DrawAdditive( 0, x, y, &GetSpriteRect( m_HUD_number_0 + k ) );
2016-06-04 15:24:23 +02:00
x += iWidth;
}
2016-07-03 15:39:55 +02:00
else if( iFlags & ( DHN_3DIGITS ) )
2016-06-04 15:24:23 +02:00
{
//SPR_DrawAdditive( 0, x, y, &rc );
x += iWidth;
}
// SPR_Draw 10's
2016-07-03 15:39:55 +02:00
if( iNumber >= 10 )
2016-06-04 15:24:23 +02:00
{
2016-07-03 15:39:55 +02:00
k = ( iNumber % 100 ) / 10;
SPR_Set( GetSprite( m_HUD_number_0 + k ), r, g, b );
SPR_DrawAdditive( 0, x, y, &GetSpriteRect( m_HUD_number_0 + k ) );
2016-06-04 15:24:23 +02:00
x += iWidth;
}
2016-07-03 15:39:55 +02:00
else if( iFlags & ( DHN_3DIGITS | DHN_2DIGITS ) )
2016-06-04 15:24:23 +02:00
{
//SPR_DrawAdditive( 0, x, y, &rc );
x += iWidth;
}
// SPR_Draw ones
k = iNumber % 10;
2016-07-03 15:39:55 +02:00
SPR_Set( GetSprite( m_HUD_number_0 + k ), r, g, b );
SPR_DrawAdditive( 0, x, y, &GetSpriteRect( m_HUD_number_0 + k ) );
2016-06-04 15:24:23 +02:00
x += iWidth;
2016-07-03 15:39:55 +02:00
}
else if( iFlags & DHN_DRAWZERO )
2016-06-04 15:24:23 +02:00
{
2016-07-03 15:39:55 +02:00
SPR_Set( GetSprite( m_HUD_number_0 ), r, g, b );
2016-06-04 15:24:23 +02:00
// SPR_Draw 100's
2016-07-03 15:39:55 +02:00
if( iFlags & ( DHN_3DIGITS ) )
2016-06-04 15:24:23 +02:00
{
//SPR_DrawAdditive( 0, x, y, &rc );
x += iWidth;
}
2016-07-03 15:39:55 +02:00
if( iFlags & ( DHN_3DIGITS | DHN_2DIGITS ) )
2016-06-04 15:24:23 +02:00
{
//SPR_DrawAdditive( 0, x, y, &rc );
x += iWidth;
}
// SPR_Draw ones
2016-07-03 15:39:55 +02:00
SPR_DrawAdditive( 0, x, y, &GetSpriteRect( m_HUD_number_0 ) );
2016-06-04 15:24:23 +02:00
x += iWidth;
}
return x;
}
int CHud::GetNumWidth( int iNumber, int iFlags )
{
2016-07-03 15:39:55 +02:00
if( iFlags & ( DHN_3DIGITS ) )
2016-06-04 15:24:23 +02:00
return 3;
2016-07-03 15:39:55 +02:00
if( iFlags & ( DHN_2DIGITS ) )
2016-06-04 15:24:23 +02:00
return 2;
2016-07-03 15:39:55 +02:00
if( iNumber <= 0 )
2016-06-04 15:24:23 +02:00
{
2016-07-03 15:39:55 +02:00
if( iFlags & ( DHN_DRAWZERO ) )
2016-06-04 15:24:23 +02:00
return 1;
else
return 0;
}
2016-07-03 15:39:55 +02:00
if( iNumber < 10 )
2016-06-04 15:24:23 +02:00
return 1;
2016-07-03 15:39:55 +02:00
if( iNumber < 100 )
2016-06-04 15:24:23 +02:00
return 2;
return 3;
}
void CHud::DrawDarkRectangle( int x, int y, int wide, int tall )
{
//gEngfuncs.pTriAPI->RenderMode( kRenderTransTexture );
gEngfuncs.pfnFillRGBABlend( x, y, wide, tall, 0, 0, 0, 255 * 0.6 );
2016-07-03 15:39:55 +02:00
FillRGBA( x + 1, y, wide - 1, 1, 255, 140, 0, 255 );
FillRGBA( x, y, 1, tall - 1, 255, 140, 0, 255 );
FillRGBA( x + wide - 1, y + 1, 1, tall - 1, 255, 140, 0, 255 );
FillRGBA( x, y + tall - 1, wide - 1, 1, 255, 140, 0, 255 );
2016-06-04 15:24:23 +02:00
}