2022-06-15 01:24:29 +02:00
//============================================================================//
//
// Purpose: Debug interface functions
//
//============================================================================//
# include "core/stdafx.h"
2022-07-07 21:31:00 +02:00
# include "common/pseudodefs.h"
2022-07-22 16:34:10 +02:00
# include "tier0/memstd.h"
2022-06-15 01:24:29 +02:00
# include "tier0/basetypes.h"
# include "tier1/cvar.h"
2022-07-07 21:31:00 +02:00
# include "tier2/renderutils.h"
2022-06-15 01:24:29 +02:00
# include "engine/client/clientstate.h"
# include "engine/host_cmd.h"
# include "engine/debugoverlay.h"
# include "materialsystem/cmaterialsystem.h"
2022-07-07 21:31:00 +02:00
# include "mathlib/mathlib.h"
2022-09-30 01:16:26 +02:00
# ifndef CLIENT_DLL
2022-07-25 16:39:07 +02:00
# include "game/shared/ai_utility_shared.h"
2022-09-30 01:16:26 +02:00
# include "game/server/ai_network.h"
# endif // !CLIENT_DLL
2022-06-15 01:24:29 +02:00
2024-02-24 02:15:09 +01:00
ConVar r_debug_draw_depth_test ( " r_debug_draw_depth_test " , " 1 " , FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT , " Toggle depth test for other debug draw functionality " ) ;
static ConVar r_debug_overlay_nodecay ( " r_debug_overlay_nodecay " , " 0 " , FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT , " Keeps all debug overlays alive regardless of their lifetime. Use command 'clear_debug_overlays' to clear everything " ) ;
static ConVar r_debug_overlay_invisible ( " r_debug_overlay_invisible " , " 1 " , FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT , " Show invisible debug overlays (alpha < 1 = 255) " ) ;
static ConVar r_debug_overlay_wireframe ( " r_debug_overlay_wireframe " , " 1 " , FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT , " Use wireframe in debug overlay " ) ;
2022-06-15 01:24:29 +02:00
//------------------------------------------------------------------------------
// Purpose: checks if overlay should be decayed
2022-07-11 12:00:08 +02:00
// Output : true to decay, false otherwise
2022-06-15 01:24:29 +02:00
//------------------------------------------------------------------------------
bool OverlayBase_t : : IsDead ( ) const
{
2024-02-24 02:15:09 +01:00
if ( r_debug_overlay_nodecay . GetBool ( ) )
2022-06-15 01:24:29 +02:00
{
2022-09-09 19:47:31 +02:00
// Keep rendering the overlay if no-decay is set.
2022-06-15 01:24:29 +02:00
return false ;
}
if ( g_pClientState - > IsPaused ( ) )
{
// Keep rendering the overlay if the client simulation is paused.
return false ;
}
if ( m_nCreationTick = = - 1 )
{
if ( m_nOverlayTick = = - 1 )
{
if ( m_flEndTime = = NDEBUG_PERSIST_TILL_NEXT_SERVER )
{
return false ;
}
return g_pClientState - > GetClientTime ( ) > = m_flEndTime ;
}
else
{
2022-08-18 02:15:23 +02:00
return m_nOverlayTick < * g_nOverlayTickCount ;
2022-06-15 01:24:29 +02:00
}
}
else
{
2022-08-18 02:15:23 +02:00
return m_nCreationTick < * g_nRenderTickCount ;
2022-06-15 01:24:29 +02:00
}
}
//------------------------------------------------------------------------------
// Purpose: destroys the overlay
2022-07-11 12:00:08 +02:00
// Input : *pOverlay -
2022-06-15 01:24:29 +02:00
//------------------------------------------------------------------------------
2022-06-15 01:35:48 +02:00
void DestroyOverlay ( OverlayBase_t * pOverlay )
2022-06-15 01:24:29 +02:00
{
2023-06-26 22:34:24 +02:00
EnterCriticalSection ( s_OverlayMutex ) ;
2022-06-15 01:24:29 +02:00
switch ( pOverlay - > m_Type )
{
case OverlayType_t : : OVERLAY_BOX :
case OverlayType_t : : OVERLAY_SPHERE :
case OverlayType_t : : OVERLAY_LINE :
case OverlayType_t : : OVERLAY_TRIANGLE :
case OverlayType_t : : OVERLAY_BOX2 :
case OverlayType_t : : OVERLAY_CAPSULE :
case OverlayType_t : : OVERLAY_UNK0 :
2023-06-26 22:34:24 +02:00
delete pOverlay ;
break ;
// The laser line overlay, used for the smart pistol's guidance
// line, appears to be not deleted in this particular function.
// Its unclear whether or not something else takes care of this,
// research needed!!!
case OverlayType_t : : OVERLAY_LASER_LINE :
2022-06-15 01:24:29 +02:00
break ;
default :
2023-06-26 22:34:24 +02:00
Assert ( 0 ) ; // Code bug; invalid overlay type.
2022-06-15 01:24:29 +02:00
break ;
}
2023-06-26 22:34:24 +02:00
LeaveCriticalSection ( s_OverlayMutex ) ;
2022-06-15 01:24:29 +02:00
}
//------------------------------------------------------------------------------
// Purpose: draws a generic overlay
2022-07-11 12:00:08 +02:00
// Input : *pOverlay -
2022-06-15 01:24:29 +02:00
//------------------------------------------------------------------------------
void DrawOverlay ( OverlayBase_t * pOverlay )
{
2023-06-26 22:34:24 +02:00
EnterCriticalSection ( s_OverlayMutex ) ;
2022-06-15 01:24:29 +02:00
switch ( pOverlay - > m_Type )
{
case OverlayType_t : : OVERLAY_BOX :
{
2022-07-07 21:31:00 +02:00
OverlayBox_t * pBox = static_cast < OverlayBox_t * > ( pOverlay ) ;
2022-07-06 21:11:32 +02:00
if ( pBox - > a < 1 )
2022-07-10 14:30:28 +02:00
{
2024-02-24 02:15:09 +01:00
if ( r_debug_overlay_invisible . GetBool ( ) )
2022-07-10 14:30:28 +02:00
{
pBox - > a = 255 ;
}
else
{
2023-06-26 22:34:24 +02:00
LeaveCriticalSection ( s_OverlayMutex ) ;
2022-07-10 14:30:28 +02:00
return ;
}
}
2022-06-15 01:24:29 +02:00
2023-01-24 12:05:09 +01:00
v_RenderBox ( pBox - > transforms . mat , pBox - > mins , pBox - > maxs , Color ( pBox - > r , pBox - > g , pBox - > b , pBox - > a ) , ! pBox - > noDepthTest ) ;
2022-06-15 01:24:29 +02:00
break ;
}
case OverlayType_t : : OVERLAY_SPHERE :
{
OverlaySphere_t * pSphere = static_cast < OverlaySphere_t * > ( pOverlay ) ;
2022-07-10 14:30:28 +02:00
if ( pSphere - > a < 1 )
{
2024-02-24 02:15:09 +01:00
if ( r_debug_overlay_invisible . GetBool ( ) )
2022-07-10 14:30:28 +02:00
{
pSphere - > a = 255 ;
}
else
{
2023-06-26 22:34:24 +02:00
LeaveCriticalSection ( s_OverlayMutex ) ;
2022-07-10 14:30:28 +02:00
return ;
}
}
2024-02-24 02:15:09 +01:00
if ( r_debug_overlay_wireframe . GetBool ( ) )
2022-07-11 12:22:35 +02:00
{
2022-07-11 21:23:26 +02:00
v_RenderWireframeSphere ( pSphere - > vOrigin , pSphere - > flRadius , pSphere - > nTheta , pSphere - > nPhi ,
2024-02-24 02:15:09 +01:00
Color ( pSphere - > r , pSphere - > g , pSphere - > b , pSphere - > a ) , r_debug_draw_depth_test . GetBool ( ) ) ;
2022-07-11 12:22:35 +02:00
}
2022-07-10 14:30:28 +02:00
else
2022-07-11 12:22:35 +02:00
{
2024-02-24 02:15:09 +01:00
DebugDrawSphere ( pSphere - > vOrigin , pSphere - > flRadius , Color ( pSphere - > r , pSphere - > g , pSphere - > b , pSphere - > a ) , 16 , r_debug_draw_depth_test . GetBool ( ) ) ;
2022-07-11 12:22:35 +02:00
}
2022-06-15 01:24:29 +02:00
break ;
}
case OverlayType_t : : OVERLAY_LINE :
{
OverlayLine_t * pLine = static_cast < OverlayLine_t * > ( pOverlay ) ;
2022-07-10 14:30:28 +02:00
if ( pLine - > a < 1 )
{
2024-02-24 02:15:09 +01:00
if ( r_debug_overlay_invisible . GetBool ( ) )
2022-07-10 14:30:28 +02:00
{
pLine - > a = 255 ;
}
else
{
2023-06-26 22:34:24 +02:00
LeaveCriticalSection ( s_OverlayMutex ) ;
2022-07-10 14:30:28 +02:00
return ;
}
}
2022-07-11 21:23:26 +02:00
v_RenderLine ( pLine - > origin , pLine - > dest , Color ( pLine - > r , pLine - > g , pLine - > b , pLine - > a ) , ! pLine - > noDepthTest ) ;
2022-06-15 01:24:29 +02:00
break ;
}
case OverlayType_t : : OVERLAY_TRIANGLE :
{
2022-07-07 21:31:00 +02:00
//printf("TRIANGLE %p\n", pOverlay);
2022-06-15 01:24:29 +02:00
break ;
}
2022-10-30 23:38:19 +01:00
case OverlayType_t : : OVERLAY_LASER_LINE :
2022-06-15 01:24:29 +02:00
{
2022-10-30 23:38:19 +01:00
OverlayLaserLine_t * pLaser = static_cast < OverlayLaserLine_t * > ( pOverlay ) ;
v_RenderLine ( pLaser - > start , pLaser - > end , Color ( pLaser - > r , pLaser - > g , pLaser - > b , pLaser - > a ) , ! pLaser - > noDepthTest ) ;
2022-06-15 01:24:29 +02:00
break ;
}
case OverlayType_t : : OVERLAY_BOX2 :
{
2022-07-07 21:31:00 +02:00
//printf("BOX2 %p\n", pOverlay);
2022-06-15 01:24:29 +02:00
break ;
}
case OverlayType_t : : OVERLAY_CAPSULE :
{
2022-07-11 20:35:20 +02:00
OverlayCapsule_t * pCapsule = static_cast < OverlayCapsule_t * > ( pOverlay ) ;
if ( pCapsule - > a < 1 )
{
2024-02-24 02:15:09 +01:00
if ( r_debug_overlay_invisible . GetBool ( ) )
2022-07-11 20:35:20 +02:00
{
pCapsule - > a = 255 ;
}
else
{
2023-06-26 22:34:24 +02:00
LeaveCriticalSection ( s_OverlayMutex ) ;
2022-07-11 20:35:20 +02:00
return ;
}
}
QAngle angles ;
VectorAngles ( pCapsule - > end , pCapsule - > start , angles ) ;
AngleInverse ( angles , angles ) ;
2022-07-11 21:23:26 +02:00
DebugDrawCapsule ( pCapsule - > start , angles , pCapsule - > radius , pCapsule - > start . DistTo ( pCapsule - > end ) ,
2024-02-24 02:15:09 +01:00
Color ( pCapsule - > r , pCapsule - > g , pCapsule - > b , pCapsule - > a ) , r_debug_draw_depth_test . GetBool ( ) ) ;
2022-06-15 01:24:29 +02:00
break ;
}
case OverlayType_t : : OVERLAY_UNK0 :
{
2022-07-07 21:31:00 +02:00
//printf("UNK0 %p\n", pOverlay);
2022-06-15 01:24:29 +02:00
break ;
}
case OverlayType_t : : OVERLAY_UNK1 :
{
2022-07-07 21:31:00 +02:00
//printf("UNK1 %p\n", pOverlay);
2022-06-15 01:24:29 +02:00
break ;
}
}
2023-06-26 22:34:24 +02:00
LeaveCriticalSection ( s_OverlayMutex ) ;
2022-06-15 01:24:29 +02:00
}
//------------------------------------------------------------------------------
// Purpose : overlay drawing entrypoint
2023-04-02 09:27:54 +02:00
// Input : bRender - won't render anything if false
2022-06-15 01:24:29 +02:00
//------------------------------------------------------------------------------
2023-04-02 09:27:54 +02:00
void DrawAllOverlays ( bool bRender )
2022-06-15 01:24:29 +02:00
{
2023-06-26 22:34:24 +02:00
EnterCriticalSection ( s_OverlayMutex ) ;
2022-06-15 01:24:29 +02:00
2023-04-02 09:27:54 +02:00
const bool bOverlayEnabled = ( bRender & & enable_debug_overlays - > GetBool ( ) ) ;
2022-06-15 01:24:29 +02:00
OverlayBase_t * pCurrOverlay = * s_pOverlays ; // rdi
OverlayBase_t * pPrevOverlay = nullptr ; // rsi
OverlayBase_t * pNextOverlay = nullptr ; // rbx
while ( pCurrOverlay )
{
if ( pCurrOverlay - > IsDead ( ) )
{
if ( pPrevOverlay )
{
// If I had a last overlay reset it's next pointer
pPrevOverlay - > m_pNextOverlay = pCurrOverlay - > m_pNextOverlay ;
}
else
{
// If the first line, reset the s_pOverlays pointer
* s_pOverlays = pCurrOverlay - > m_pNextOverlay ;
}
pNextOverlay = pCurrOverlay - > m_pNextOverlay ;
2022-06-15 01:35:48 +02:00
DestroyOverlay ( pCurrOverlay ) ;
2022-06-15 01:24:29 +02:00
pCurrOverlay = pNextOverlay ;
}
else
{
2023-06-26 22:34:24 +02:00
bool bShouldDraw = false ;
2022-06-15 01:24:29 +02:00
if ( pCurrOverlay - > m_nCreationTick = = - 1 )
{
2022-08-18 02:15:23 +02:00
if ( pCurrOverlay - > m_nOverlayTick = = * g_nOverlayTickCount )
2022-06-15 01:24:29 +02:00
{
// Draw overlay if unk0 == *overlay_tickcount
2023-04-02 09:27:54 +02:00
bShouldDraw = true ;
2022-06-15 01:24:29 +02:00
}
if ( pCurrOverlay - > m_nOverlayTick = = - 1 )
{
// Draw overlay if unk0 == -1
2023-04-02 09:27:54 +02:00
bShouldDraw = true ;
2022-06-15 01:24:29 +02:00
}
}
else
{
2023-04-02 09:27:54 +02:00
bShouldDraw = pCurrOverlay - > m_nCreationTick = = * g_nRenderTickCount ;
2022-06-15 01:24:29 +02:00
}
2023-04-02 09:27:54 +02:00
if ( bOverlayEnabled & & bShouldDraw )
2022-06-15 01:24:29 +02:00
{
2023-04-02 09:27:54 +02:00
if ( bShouldDraw )
2022-06-15 01:24:29 +02:00
{
DrawOverlay ( pCurrOverlay ) ;
}
}
2023-06-26 22:34:24 +02:00
2022-06-15 01:24:29 +02:00
pPrevOverlay = pCurrOverlay ;
pCurrOverlay = pCurrOverlay - > m_pNextOverlay ;
}
}
2022-11-10 02:40:34 +01:00
# ifndef CLIENT_DLL
if ( bOverlayEnabled )
{
2023-09-23 14:01:53 +02:00
g_pAIUtility - > RunRenderFrame ( ) ;
2022-11-10 02:40:34 +01:00
}
# endif // !CLIENT_DLL
2023-06-26 22:34:24 +02:00
LeaveCriticalSection ( s_OverlayMutex ) ;
2022-06-15 01:24:29 +02:00
}
///////////////////////////////////////////////////////////////////////////////
2023-11-26 13:21:20 +01:00
void VDebugOverlay : : Detour ( const bool bAttach ) const
2022-06-15 01:24:29 +02:00
{
2023-11-26 13:21:20 +01:00
DetourSetup ( & v_DrawAllOverlays , & DrawAllOverlays , bAttach ) ;
2022-06-15 01:24:29 +02:00
}