269 lines
8.2 KiB
C++
269 lines
8.2 KiB
C++
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
||
//
|
||
// Purpose: Namespace for functions dealing with Debug Overlays
|
||
//
|
||
// $Workfile: $
|
||
// $Date: $
|
||
// $NoKeywords: $
|
||
//=============================================================================//
|
||
|
||
#include "cbase.h"
|
||
#include "mathlib/mathlib.h"
|
||
#include "player.h"
|
||
#include "ndebugoverlay.h"
|
||
#include "wcedit.h"
|
||
|
||
#ifdef DEDICATED
|
||
#include "ai_basenpc.h"
|
||
#include "ai_network.h"
|
||
#include "ai_networkmanager.h"
|
||
#endif
|
||
|
||
// memdbgon must be the last include file in a .cpp file!!!
|
||
#include "tier0/memdbgon.h"
|
||
|
||
|
||
#define NUM_DEBUG_OVERLAY_LINES 20
|
||
|
||
int m_nDebugOverlayIndex = -1;
|
||
OverlayLine_t* m_debugOverlayLine[NUM_DEBUG_OVERLAY_LINES];
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose: Return the old overlay line from the overlay pool
|
||
//-----------------------------------------------------------------------------
|
||
OverlayLine_t* GetDebugOverlayLine(void)
|
||
{
|
||
// Make casing pool if not initialized
|
||
if (m_nDebugOverlayIndex == -1)
|
||
{
|
||
for (int i=0;i<NUM_DEBUG_OVERLAY_LINES;i++)
|
||
{
|
||
m_debugOverlayLine[i] = new OverlayLine_t;
|
||
m_debugOverlayLine[i]->noDepthTest = true;
|
||
m_debugOverlayLine[i]->draw = false;
|
||
}
|
||
m_nDebugOverlayIndex = 0;
|
||
}
|
||
|
||
int id;
|
||
|
||
m_nDebugOverlayIndex++;
|
||
if (m_nDebugOverlayIndex == NUM_DEBUG_OVERLAY_LINES)
|
||
{
|
||
m_nDebugOverlayIndex = 0;
|
||
id = NUM_DEBUG_OVERLAY_LINES-1;
|
||
|
||
}
|
||
else
|
||
{
|
||
id = m_nDebugOverlayIndex-1;
|
||
}
|
||
return m_debugOverlayLine[id];
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose: Adds a debug line to be drawn on the screen
|
||
// Input : If testLOS is true, color is based on line of sight test
|
||
// Output :
|
||
//-----------------------------------------------------------------------------
|
||
void UTIL_AddDebugLine(const Vector &startPos, const Vector &endPos, bool noDepthTest, bool testLOS)
|
||
{
|
||
OverlayLine_t* debugLine = GetDebugOverlayLine();
|
||
|
||
debugLine->origin = startPos;
|
||
debugLine->dest = endPos;
|
||
debugLine->noDepthTest = noDepthTest;
|
||
debugLine->draw = true;
|
||
|
||
if (testLOS)
|
||
{
|
||
trace_t tr;
|
||
UTIL_TraceLine ( debugLine->origin, debugLine->dest, MASK_BLOCKLOS, NULL, COLLISION_GROUP_NONE, &tr );
|
||
if (tr.startsolid || tr.fraction < 1.0)
|
||
{
|
||
debugLine->r = 255;
|
||
debugLine->g = 0;
|
||
debugLine->b = 0;
|
||
return;
|
||
}
|
||
}
|
||
|
||
debugLine->r = 255;
|
||
debugLine->g = 255;
|
||
debugLine->b = 255;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose: Returns z value of floor below given point (up to 384 inches below)
|
||
//-----------------------------------------------------------------------------
|
||
float GetLongFloorZ(const Vector &origin)
|
||
{
|
||
// trace to the ground, then pop up 8 units and place node there to make it
|
||
// easier for them to connect (think stairs, chairs, and bumps in the floor).
|
||
// After the routing is done, push them back down.
|
||
//
|
||
trace_t tr;
|
||
UTIL_TraceLine ( origin,
|
||
origin - Vector ( 0, 0, 2048 ),
|
||
MASK_NPCSOLID_BRUSHONLY,
|
||
NULL,
|
||
COLLISION_GROUP_NONE,
|
||
&tr );
|
||
|
||
// This trace is ONLY used if we hit an entity flagged with FL_WORLDBRUSH
|
||
trace_t trEnt;
|
||
UTIL_TraceLine ( origin,
|
||
origin - Vector ( 0, 0, 2048 ),
|
||
MASK_NPCSOLID,
|
||
NULL,
|
||
COLLISION_GROUP_NONE,
|
||
&trEnt );
|
||
|
||
|
||
// Did we hit something closer than the floor?
|
||
if ( trEnt.fraction < tr.fraction )
|
||
{
|
||
// If it was a world brush entity, copy the node location
|
||
if ( trEnt.m_pEnt )
|
||
{
|
||
CBaseEntity *e = trEnt.m_pEnt;
|
||
if ( e && (e->GetFlags() & FL_WORLDBRUSH) )
|
||
{
|
||
tr.endpos = trEnt.endpos;
|
||
}
|
||
}
|
||
}
|
||
|
||
return tr.endpos.z;
|
||
}
|
||
|
||
//------------------------------------------------------------------------------
|
||
// Purpose : Draws a large crosshair at flCrossDistance from the debug player
|
||
// with tick marks
|
||
//------------------------------------------------------------------------------
|
||
void UTIL_DrawPositioningOverlay( float flCrossDistance )
|
||
{
|
||
#ifndef SWDS
|
||
CBasePlayer* pPlayer = UTIL_PlayerByIndex(CBaseEntity::m_nDebugPlayer);
|
||
|
||
if (!pPlayer)
|
||
{
|
||
return;
|
||
}
|
||
|
||
Vector pRight;
|
||
pPlayer->EyeVectors( NULL, &pRight, NULL );
|
||
|
||
#ifdef _WIN32
|
||
Vector topPos = NWCEdit::AirNodePlacementPosition();
|
||
#else
|
||
Vector pForward;
|
||
pPlayer->EyeVectors( &pForward );
|
||
|
||
Vector floorVec = pForward;
|
||
floorVec.z = 0;
|
||
VectorNormalize( floorVec );
|
||
VectorNormalize( pForward );
|
||
|
||
float cosAngle = DotProduct(floorVec,pForward);
|
||
|
||
float lookDist = g_pAINetworkManager->GetEditOps()->m_flAirEditDistance/cosAngle;
|
||
Vector topPos = pPlayer->EyePosition()+pForward * lookDist;
|
||
#endif
|
||
|
||
Vector bottomPos = topPos;
|
||
bottomPos.z = GetLongFloorZ(bottomPos);
|
||
|
||
// Make sure we can see the target pos
|
||
trace_t tr;
|
||
Vector endPos;
|
||
UTIL_TraceLine(pPlayer->EyePosition(), topPos, MASK_NPCSOLID_BRUSHONLY, pPlayer, COLLISION_GROUP_NONE, &tr);
|
||
if (tr.fraction == 1.0)
|
||
{
|
||
Vector rightTrace = topPos + pRight*400;
|
||
float traceLen = (topPos - rightTrace).Length();
|
||
UTIL_TraceLine(topPos, rightTrace, MASK_NPCSOLID_BRUSHONLY, pPlayer, COLLISION_GROUP_NONE, &tr);
|
||
endPos = topPos+(pRight*traceLen*tr.fraction);
|
||
NDebugOverlay::DrawTickMarkedLine(topPos, endPos, 24.0, 5, 255,0,0,false,0);
|
||
|
||
Vector leftTrace = topPos - pRight*400;
|
||
traceLen = (topPos - leftTrace).Length();
|
||
UTIL_TraceLine(topPos, leftTrace, MASK_NPCSOLID_BRUSHONLY, pPlayer, COLLISION_GROUP_NONE, &tr);
|
||
endPos = topPos-(pRight*traceLen*tr.fraction);
|
||
NDebugOverlay::DrawTickMarkedLine(topPos, endPos, 24.0, 5, 255,0,0,false,0);
|
||
|
||
Vector upTrace = topPos + Vector(0,0,1)*400;
|
||
traceLen = (topPos - upTrace).Length();
|
||
UTIL_TraceLine(topPos, upTrace, MASK_NPCSOLID_BRUSHONLY, pPlayer, COLLISION_GROUP_NONE, &tr);
|
||
endPos = topPos+(Vector(0,0,1)*traceLen*tr.fraction);
|
||
NDebugOverlay::DrawTickMarkedLine(bottomPos, endPos, 24.0, 5, 255,0,0,false,0);
|
||
|
||
// Draw white cross at center
|
||
NDebugOverlay::Cross3D(topPos, Vector(-2,-2,-2), Vector(2,2,2), 255,255,255, true, 0);
|
||
}
|
||
else
|
||
{
|
||
// Draw warning cross at center
|
||
NDebugOverlay::Cross3D(topPos, Vector(-2,-2,-2), Vector(2,2,2), 255,100,100, true, 0 );
|
||
}
|
||
/* Don't show distance for now.
|
||
char text[25];
|
||
Q_snprintf(text,sizeof(text),"%3.0f",flCrossDistance/12.0);
|
||
Vector textPos = topPos - pRight*16 + Vector(0,0,10);
|
||
NDebugOverlay::Text( textPos, text, true, 0 );
|
||
*/
|
||
#endif
|
||
}
|
||
|
||
//------------------------------------------------------------------------------
|
||
// Purpose : Draw all overlay lines in the list
|
||
//------------------------------------------------------------------------------
|
||
void UTIL_DrawOverlayLines(void)
|
||
{
|
||
if (m_nDebugOverlayIndex != -1)
|
||
{
|
||
for (int i=0;i<NUM_DEBUG_OVERLAY_LINES;i++)
|
||
{
|
||
if (m_debugOverlayLine[i]->draw)
|
||
{
|
||
NDebugOverlay::Line(m_debugOverlayLine[i]->origin,
|
||
m_debugOverlayLine[i]->dest,
|
||
m_debugOverlayLine[i]->r,
|
||
m_debugOverlayLine[i]->g,
|
||
m_debugOverlayLine[i]->b,
|
||
m_debugOverlayLine[i]->noDepthTest,0);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose: Add an overlay line with padding on the start and end
|
||
//-----------------------------------------------------------------------------
|
||
void DebugDrawLine( const Vector& vecAbsStart, const Vector& vecAbsEnd, int r, int g, int b, bool test, float duration )
|
||
{
|
||
NDebugOverlay::Line( vecAbsStart + Vector( 0,0,0.1), vecAbsEnd + Vector( 0,0,0.1), r,g,b, test, duration );
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Purpose: Allow all debug overlays to be cleared at once
|
||
//-----------------------------------------------------------------------------
|
||
CON_COMMAND( clear_debug_overlays, "clears debug overlays" )
|
||
{
|
||
CBaseEntity *pEntity = gEntList.FirstEnt();
|
||
|
||
// Clear all entities of their debug overlays
|
||
while ( pEntity )
|
||
{
|
||
pEntity->m_debugOverlays = 0;
|
||
// UNDONE: Clear out / expire timed overlays?
|
||
pEntity = gEntList.NextEnt( pEntity );
|
||
}
|
||
|
||
// Clear all engine overlays
|
||
if ( debugoverlay )
|
||
{
|
||
debugoverlay->ClearAllOverlays();
|
||
}
|
||
}
|