2025-05-17 14:17:42 -04:00
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
2010-07-22 01:46:14 -05:00
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
# include "cbase.h"
# include "c_baseanimating.h"
# include "materialsystem/imaterialsystem.h"
# include "model_types.h"
# include "viewrender.h"
# include "c_pixel_visibility.h"
extern view_id_t CurrentViewID ( ) ;
extern bool IsMainView ( view_id_t id ) ;
// memdbgon must be the last include file in a .cpp file!!!
# include "tier0/memdbgon.h"
class C_Prop_Hallucination : public C_BaseAnimating
{
public :
DECLARE_CLASS ( C_Prop_Hallucination , C_BaseAnimating ) ;
DECLARE_CLIENTCLASS ( ) ;
virtual void Spawn ( void ) ;
virtual void UpdateOnRemove ( void ) ;
//virtual bool ShouldDraw( void );
virtual int DrawModel ( int flags , const RenderableInstance_t & instance ) ;
virtual ShadowType_t ShadowCastType ( void ) ;
virtual void OnDataChanged ( DataUpdateType_t type ) ;
COcclusionQuerySet m_OcclusionSet ;
int m_iLastDrawCallFrame ;
bool m_bVisibleInAnyViewLastFrame ;
//float m_fVisibilityRemaining; //an ill defined measure of how much longer we're visible. When it reaches 0 we no longer show the hallucination until it's recharged to 1. Being occluded before reaching 0 is going to be up in the air on what to do.
double m_fLastStateChangeTime ;
bool m_bVisibleEligible ;
bool m_bEnabled ;
float m_fVisibleTime ;
float m_fRechargeTime ;
static CMaterialReference sm_OcclusionProxyMaterial ;
} ;
CMaterialReference C_Prop_Hallucination : : sm_OcclusionProxyMaterial ;
IMPLEMENT_CLIENTCLASS_DT ( C_Prop_Hallucination , DT_Prop_Hallucination , CProp_Hallucination )
RecvPropBool ( RECVINFO ( m_bEnabled ) ) ,
RecvPropFloat ( RECVINFO ( m_fVisibleTime ) ) ,
RecvPropFloat ( RECVINFO ( m_fRechargeTime ) ) ,
END_RECV_TABLE ( )
//ConVar cl_hallucination_dischargescale( "cl_hallucination_dischargescale", "3000.0", FCVAR_CHEAT, "(delta time) * (percentage of screen drawn to) * (this scale) is how much visibility charge (0.0-1.0) we use up per frame. When it's 0.0 the hallucination is invisible" );
//ConVar cl_hallucination_visibletime( "cl_hallucination_visibletime", "0.215", FCVAR_CHEAT, "the maximum time (in seconds) from first visible frame to when we stop drawing the hallucination" );
//ConVar cl_hallucination_rechargetime( "cl_hallucination_rechargetime", "2.0", FCVAR_CHEAT, "How much time must pass without drawing the hallucination before it's eligble to draw again" );
void C_Prop_Hallucination : : Spawn ( void )
{
if ( ! sm_OcclusionProxyMaterial . IsValid ( ) )
{
sm_OcclusionProxyMaterial . Init ( " engine/occlusionproxy " , TEXTURE_GROUP_CLIENT_EFFECTS ) ;
}
BaseClass : : Spawn ( ) ;
}
void C_Prop_Hallucination : : UpdateOnRemove ( void )
{
BaseClass : : UpdateOnRemove ( ) ;
}
void C_Prop_Hallucination : : OnDataChanged ( DataUpdateType_t type )
{
if ( ! m_bEnabled )
{
if ( m_bVisibleEligible & & ( m_fLastStateChangeTime ! = 0.0f ) )
{
m_fLastStateChangeTime = Plat_FloatTime ( ) ;
}
m_bVisibleEligible = false ;
}
}
int C_Prop_Hallucination : : DrawModel ( int flags , const RenderableInstance_t & instance )
{
switch ( CurrentViewID ( ) )
{
case VIEW_SHADOW_DEPTH_TEXTURE :
if ( m_bVisibleEligible )
{
return BaseClass : : DrawModel ( flags , instance ) ;
}
default :
if ( IsMainView ( CurrentViewID ( ) ) ) //VIEW_MAIN and portal views are true
{
break ;
}
else
{
return 0 ;
}
} ;
bool bSameFrame = ( m_iLastDrawCallFrame = = gpGlobals - > framecount ) ;
if ( ( flags & STUDIO_RENDER ) & & ! bSameFrame )
{
bool bDrewLastFrame = ( m_iLastDrawCallFrame = = ( gpGlobals - > framecount - 1 ) ) ;
if ( m_bVisibleEligible )
{
if ( m_fLastStateChangeTime = = 0.0 ) //waiting for the first frame of actual visibility mark the state change
{
if ( bDrewLastFrame & & ( m_OcclusionSet . QueryNumPixelsRenderedForAllViewsLastFrame ( ) > 0 ) )
{
m_fLastStateChangeTime = Plat_FloatTime ( ) ; // - gpGlobals->realtime; //state change occurred last frame
}
}
else if ( ( Plat_FloatTime ( ) - m_fLastStateChangeTime ) > m_fVisibleTime )
{
m_bVisibleEligible = false ;
}
}
else
{
if ( ( ( m_fLastStateChangeTime = = 0.0f ) | | ( Plat_FloatTime ( ) - m_fLastStateChangeTime ) > m_fRechargeTime ) & &
( ( m_OcclusionSet . QueryNumPixelsRenderedForAllViewsLastFrame ( ) = = 0 ) | | ! bDrewLastFrame ) )
{
m_bVisibleEligible = true ;
m_fLastStateChangeTime = 0.0f ;
}
}
}
if ( flags & STUDIO_RENDER )
{
if ( ! m_bVisibleEligible )
{
modelrender - > ForcedMaterialOverride ( sm_OcclusionProxyMaterial ) ;
}
m_iLastDrawCallFrame = gpGlobals - > framecount ;
m_OcclusionSet . BeginQueryDrawing ( ) ;
int iRetVal = BaseClass : : DrawModel ( flags , instance ) ;
m_OcclusionSet . EndQueryDrawing ( ) ;
if ( ! m_bVisibleEligible )
{
modelrender - > ForcedMaterialOverride ( NULL ) ;
}
return iRetVal ;
}
else
{
return BaseClass : : DrawModel ( flags , instance ) ;
}
}
ShadowType_t C_Prop_Hallucination : : ShadowCastType ( void )
{
return SHADOWS_NONE ;
}