r5sdk/r5dev/engine/debugoverlay.cpp

312 lines
9.6 KiB
C++
Raw Normal View History

2022-06-15 01:24:29 +02:00
//============================================================================//
//
// Purpose: Debug interface functions
//
//============================================================================//
#include "core/stdafx.h"
#include "common/pseudodefs.h"
#include "tier0/memstd.h"
2022-06-15 01:24:29 +02:00
#include "tier0/basetypes.h"
#include "tier1/cvar.h"
#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"
#include "mathlib/mathlib.h"
#ifndef CLIENT_DLL
#include "game/shared/ai_utility_shared.h"
#include "game/server/ai_network.h"
#endif // !CLIENT_DLL
2022-06-15 01:24:29 +02: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
// Output : true to decay, false otherwise
2022-06-15 01:24:29 +02:00
//------------------------------------------------------------------------------
bool OverlayBase_t::IsDead() const
{
if (r_debug_overlay_nodecay.GetBool())
2022-06-15 01:24:29 +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
{
return m_nOverlayTick < *g_nOverlayTickCount;
2022-06-15 01:24:29 +02:00
}
}
else
{
return m_nCreationTick < *g_nRenderTickCount;
2022-06-15 01:24:29 +02:00
}
}
//------------------------------------------------------------------------------
// Purpose: destroys the overlay
// Input : *pOverlay -
2022-06-15 01:24:29 +02:00
//------------------------------------------------------------------------------
void DestroyOverlay(OverlayBase_t* pOverlay)
2022-06-15 01:24:29 +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:
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:
Assert(0); // Code bug; invalid overlay type.
2022-06-15 01:24:29 +02:00
break;
}
LeaveCriticalSection(s_OverlayMutex);
2022-06-15 01:24:29 +02:00
}
//------------------------------------------------------------------------------
// Purpose: draws a generic overlay
// Input : *pOverlay -
2022-06-15 01:24:29 +02:00
//------------------------------------------------------------------------------
void DrawOverlay(OverlayBase_t* pOverlay)
{
EnterCriticalSection(s_OverlayMutex);
2022-06-15 01:24:29 +02:00
switch (pOverlay->m_Type)
{
case OverlayType_t::OVERLAY_BOX:
{
OverlayBox_t* pBox = static_cast<OverlayBox_t*>(pOverlay);
if (pBox->a < 1)
{
if (r_debug_overlay_invisible.GetBool())
{
pBox->a = 255;
}
else
{
LeaveCriticalSection(s_OverlayMutex);
return;
}
}
2022-06-15 01:24:29 +02: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);
if (pSphere->a < 1)
{
if (r_debug_overlay_invisible.GetBool())
{
pSphere->a = 255;
}
else
{
LeaveCriticalSection(s_OverlayMutex);
return;
}
}
if (r_debug_overlay_wireframe.GetBool())
2022-07-11 12:22:35 +02:00
{
v_RenderWireframeSphere(pSphere->vOrigin, pSphere->flRadius, pSphere->nTheta, pSphere->nPhi,
Color(pSphere->r, pSphere->g, pSphere->b, pSphere->a), r_debug_draw_depth_test.GetBool());
2022-07-11 12:22:35 +02:00
}
else
2022-07-11 12:22:35 +02: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);
if (pLine->a < 1)
{
if (r_debug_overlay_invisible.GetBool())
{
pLine->a = 255;
}
else
{
LeaveCriticalSection(s_OverlayMutex);
return;
}
}
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:
{
//printf("TRIANGLE %p\n", pOverlay);
2022-06-15 01:24:29 +02:00
break;
}
case OverlayType_t::OVERLAY_LASER_LINE:
2022-06-15 01:24:29 +02: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:
{
//printf("BOX2 %p\n", pOverlay);
2022-06-15 01:24:29 +02:00
break;
}
case OverlayType_t::OVERLAY_CAPSULE:
{
OverlayCapsule_t* pCapsule = static_cast<OverlayCapsule_t*>(pOverlay);
if (pCapsule->a < 1)
{
if (r_debug_overlay_invisible.GetBool())
{
pCapsule->a = 255;
}
else
{
LeaveCriticalSection(s_OverlayMutex);
return;
}
}
QAngle angles;
VectorAngles(pCapsule->end, pCapsule->start, angles);
AngleInverse(angles, angles);
DebugDrawCapsule(pCapsule->start, angles, pCapsule->radius, pCapsule->start.DistTo(pCapsule->end),
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:
{
//printf("UNK0 %p\n", pOverlay);
2022-06-15 01:24:29 +02:00
break;
}
case OverlayType_t::OVERLAY_UNK1:
{
//printf("UNK1 %p\n", pOverlay);
2022-06-15 01:24:29 +02:00
break;
}
}
LeaveCriticalSection(s_OverlayMutex);
2022-06-15 01:24:29 +02:00
}
//------------------------------------------------------------------------------
// Purpose : overlay drawing entrypoint
// Input : bRender - won't render anything if false
2022-06-15 01:24:29 +02:00
//------------------------------------------------------------------------------
void DrawAllOverlays(bool bRender)
2022-06-15 01:24:29 +02:00
{
EnterCriticalSection(s_OverlayMutex);
2022-06-15 01:24:29 +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;
DestroyOverlay(pCurrOverlay);
2022-06-15 01:24:29 +02:00
pCurrOverlay = pNextOverlay;
}
else
{
bool bShouldDraw = false;
2022-06-15 01:24:29 +02:00
if (pCurrOverlay->m_nCreationTick == -1)
{
if (pCurrOverlay->m_nOverlayTick == *g_nOverlayTickCount)
2022-06-15 01:24:29 +02:00
{
// Draw overlay if unk0 == *overlay_tickcount
bShouldDraw = true;
2022-06-15 01:24:29 +02:00
}
if (pCurrOverlay->m_nOverlayTick == -1)
{
// Draw overlay if unk0 == -1
bShouldDraw = true;
2022-06-15 01:24:29 +02:00
}
}
else
{
bShouldDraw = pCurrOverlay->m_nCreationTick == *g_nRenderTickCount;
2022-06-15 01:24:29 +02:00
}
if (bOverlayEnabled && bShouldDraw)
2022-06-15 01:24:29 +02:00
{
if (bShouldDraw)
2022-06-15 01:24:29 +02:00
{
DrawOverlay(pCurrOverlay);
}
}
2022-06-15 01:24:29 +02:00
pPrevOverlay = pCurrOverlay;
pCurrOverlay = pCurrOverlay->m_pNextOverlay;
}
}
#ifndef CLIENT_DLL
if (bOverlayEnabled)
{
2023-09-23 14:01:53 +02:00
g_pAIUtility->RunRenderFrame();
}
#endif // !CLIENT_DLL
LeaveCriticalSection(s_OverlayMutex);
2022-06-15 01:24:29 +02:00
}
///////////////////////////////////////////////////////////////////////////////
void VDebugOverlay::Detour(const bool bAttach) const
2022-06-15 01:24:29 +02:00
{
DetourSetup(&v_DrawAllOverlays, &DrawAllOverlays, bAttach);
2022-06-15 01:24:29 +02:00
}