csgo-2018-source/game/shared/portal/paint_power_user_interface.cpp
2021-07-24 21:11:47 -07:00

109 lines
3.4 KiB
C++

//========= Copyright © 1996-2009, Valve Corporation, All rights reserved. ============//
//
// Purpose: Implements the interface class for all paint power users.
//
//=============================================================================//
#include "cbase.h"
#include "paint_power_user_interface.h"
#include "paintable_entity.h"
#ifdef GAME_DLL
#include "world.h"
#else
#include "c_world.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
ConVar sv_enable_paint_power_user_debug("sv_enable_paint_power_user_debug", "0", FCVAR_REPLICATED | FCVAR_CHEAT,"Enable debug spew for paint power users.");
extern ConVar sv_debug_draw_contacts;
IPaintPowerUser::~IPaintPowerUser()
{}
void MapSurfaceToPower( PaintPowerInfo_t& info )
{
IHandleEntity* pEntityHandle = info.m_HandleToOther.Get();
CBaseEntity* pEnt = pEntityHandle != NULL ? EntityFromEntityHandle( pEntityHandle ) : NULL;
// If the power hasn't been set to anything elsewhere, and the entity is valid
if ( info.m_PaintPowerType == NO_POWER && pEnt != NULL )
{
// Treat portalsimulator_collisionentity as the world
if( FClassnameIs( pEnt, "portalsimulator_collisionentity" ) )
{
#ifdef GAME_DLL
pEnt = GetWorldEntity();
#else
pEnt = GetClientWorldEntity();
#endif
}
// If this is a world entity
if( pEnt->IsBSPModel() )
{
Vector vStart = info.m_ContactPoint + info.m_SurfaceNormal;
Vector vEnd = vStart - 10.f * info.m_SurfaceNormal;
Ray_t ray;
ray.Init( vStart, vEnd );
trace_t tr;
UTIL_TraceRay( ray, MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &tr );
// Trace into the paint map to find the power if the surface is paintable
if ( UTIL_IsPaintableSurface( tr.surface ) )
{
Vector contactPoint = info.m_ContactPoint + 0.1f * info.m_SurfaceNormal;
info.m_PaintPowerType = UTIL_Paint_TracePower( pEnt, contactPoint, info.m_SurfaceNormal );
}
else
{
info.m_PaintPowerType = NO_POWER;
}
}
else if( !pEnt->IsPlayer() )
{
// The dynamic_cast here shouldn't be any more of a performance concern than the
// dynamic_cast that would be necessary when this PaintPowerInfo_t was added in the first place.
const IPaintableEntity* pPaintableEnt = dynamic_cast< const IPaintableEntity* >( pEnt );
if( pPaintableEnt )
{
info.m_PaintPowerType = pPaintableEnt->GetPaintPowerAtPoint( info.m_ContactPoint );
}
else
{
//Use the render color of the owner if this entity is a bone follower
if( FClassnameIs( pEnt, "phys_bone_follower" ) )
{
CBaseEntity *pBoneOwner = pEnt->GetOwnerEntity();
if( pBoneOwner )
{
info.m_PaintPowerType = MapColorToPower( pBoneOwner->GetRenderColor() );
}
}
else //Use the render color of this entity
{
info.m_PaintPowerType = MapColorToPower( pEnt->GetRenderColor() );
}
if( sv_enable_paint_power_user_debug.GetBool() )
{
Warning( "Non-world, non-player entity, %s, doesn't implement IPaintableEntity. See the global version of MapSurfacesToPowers() in paint_power_user_interface.cpp.\n", pEnt->GetClassname() );
}
}
}
}
if( sv_debug_draw_contacts.GetInt() == 2 )
{
Color color = MapPowerToVisualColor( info.m_PaintPowerType );
NDebugOverlay::Sphere( info.m_ContactPoint, 5.0f, color.r(), color.g(), color.b(), true, 0 );
NDebugOverlay::Line( info.m_ContactPoint, info.m_ContactPoint + 20.0f * info.m_SurfaceNormal, color.r(), color.g(), color.b(), true, 0 );
}
}