From 39ed87570bdb2f86969d4be821c94b722dc71179 Mon Sep 17 00:00:00 2001 From: Joe Ludwig Date: Wed, 26 Jun 2013 15:22:04 -0700 Subject: First version of the SOurce SDK 2013 --- mp/src/game/shared/Sprite.cpp | 868 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 868 insertions(+) create mode 100644 mp/src/game/shared/Sprite.cpp (limited to 'mp/src/game/shared/Sprite.cpp') diff --git a/mp/src/game/shared/Sprite.cpp b/mp/src/game/shared/Sprite.cpp new file mode 100644 index 00000000..8b8ce38e --- /dev/null +++ b/mp/src/game/shared/Sprite.cpp @@ -0,0 +1,868 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Implements visual effects entities: sprites, beams, bubbles, etc. +// +// $NoKeywords: $ +//=============================================================================// +#include "cbase.h" +#include "Sprite.h" +#include "model_types.h" +#include "engine/ivmodelinfo.h" +#include "tier0/vprof.h" +#include "engine/ivdebugoverlay.h" + +#if defined( CLIENT_DLL ) + #include "enginesprite.h" + #include "iclientmode.h" + #include "c_baseviewmodel.h" +# ifdef PORTAL + #include "c_prop_portal.h" +# endif //ifdef PORTAL +#else + #include "baseviewmodel.h" +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +const float MAX_SPRITE_SCALE = 64.0f; +const float MAX_GLOW_PROXY_SIZE = 64.0f; + +LINK_ENTITY_TO_CLASS( env_sprite, CSprite ); +LINK_ENTITY_TO_CLASS( env_sprite_oriented, CSpriteOriented ); +#if !defined( CLIENT_DLL ) +LINK_ENTITY_TO_CLASS( env_glow, CSprite ); // For backwards compatibility, remove when no longer needed. +#endif + +#if !defined( CLIENT_DLL ) +BEGIN_DATADESC( CSprite ) + + DEFINE_FIELD( m_flLastTime, FIELD_TIME ), + DEFINE_FIELD( m_flMaxFrame, FIELD_FLOAT ), + DEFINE_FIELD( m_hAttachedToEntity, FIELD_EHANDLE ), + DEFINE_FIELD( m_nAttachment, FIELD_INTEGER ), + DEFINE_FIELD( m_flDieTime, FIELD_TIME ), + + DEFINE_FIELD( m_nBrightness, FIELD_INTEGER ), + DEFINE_FIELD( m_flBrightnessTime, FIELD_FLOAT ), + + DEFINE_KEYFIELD( m_flSpriteScale, FIELD_FLOAT, "scale" ), + DEFINE_KEYFIELD( m_flSpriteFramerate, FIELD_FLOAT, "framerate" ), + DEFINE_KEYFIELD( m_flFrame, FIELD_FLOAT, "frame" ), +#ifdef PORTAL + DEFINE_FIELD( m_bDrawInMainRender, FIELD_BOOLEAN ), + DEFINE_FIELD( m_bDrawInPortalRender, FIELD_BOOLEAN ), +#endif + DEFINE_KEYFIELD( m_flHDRColorScale, FIELD_FLOAT, "HDRColorScale" ), + + DEFINE_KEYFIELD( m_flGlowProxySize, FIELD_FLOAT, "GlowProxySize" ), + + DEFINE_FIELD( m_flScaleTime, FIELD_FLOAT ), + DEFINE_FIELD( m_flStartScale, FIELD_FLOAT ), + DEFINE_FIELD( m_flDestScale, FIELD_FLOAT ), + DEFINE_FIELD( m_flScaleTimeStart, FIELD_TIME ), + DEFINE_FIELD( m_nStartBrightness, FIELD_INTEGER ), + DEFINE_FIELD( m_nDestBrightness, FIELD_INTEGER ), + DEFINE_FIELD( m_flBrightnessTimeStart, FIELD_TIME ), + DEFINE_FIELD( m_bWorldSpaceScale, FIELD_BOOLEAN ), + + // Function Pointers + DEFINE_FUNCTION( AnimateThink ), + DEFINE_FUNCTION( ExpandThink ), + DEFINE_FUNCTION( AnimateUntilDead ), + DEFINE_FUNCTION( BeginFadeOutThink ), + + // Inputs + DEFINE_INPUT( m_flSpriteScale, FIELD_FLOAT, "SetScale" ), + DEFINE_INPUTFUNC( FIELD_VOID, "HideSprite", InputHideSprite ), + DEFINE_INPUTFUNC( FIELD_VOID, "ShowSprite", InputShowSprite ), + DEFINE_INPUTFUNC( FIELD_VOID, "ToggleSprite", InputToggleSprite ), + DEFINE_INPUTFUNC( FIELD_FLOAT, "ColorRedValue", InputColorRedValue ), + DEFINE_INPUTFUNC( FIELD_FLOAT, "ColorGreenValue", InputColorGreenValue ), + DEFINE_INPUTFUNC( FIELD_FLOAT, "ColorBlueValue", InputColorBlueValue ), + +END_DATADESC() + +#else + +BEGIN_PREDICTION_DATA( CSprite ) + + // Networked + DEFINE_PRED_FIELD( m_hAttachedToEntity, FIELD_EHANDLE, FTYPEDESC_INSENDTABLE ), + DEFINE_PRED_FIELD( m_nAttachment, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), + DEFINE_PRED_FIELD( m_flScaleTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ), + DEFINE_PRED_FIELD( m_flSpriteScale, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ), + DEFINE_PRED_FIELD( m_flSpriteFramerate, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ), + DEFINE_PRED_FIELD( m_flFrame, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ), +#ifdef PORTAL + DEFINE_PRED_FIELD( m_bDrawInMainRender, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), + DEFINE_PRED_FIELD( m_bDrawInPortalRender, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), +#endif + DEFINE_PRED_FIELD( m_flBrightnessTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ), + DEFINE_PRED_FIELD( m_nBrightness, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), + + DEFINE_FIELD( m_flLastTime, FIELD_FLOAT ), + DEFINE_FIELD( m_flMaxFrame, FIELD_FLOAT ), + DEFINE_FIELD( m_flDieTime, FIELD_FLOAT ), + +// DEFINE_FIELD( m_flHDRColorScale, FIELD_FLOAT ), +// DEFINE_FIELD( m_flStartScale, FIELD_FLOAT ), //Starting scale +// DEFINE_FIELD( m_flDestScale, FIELD_FLOAT ), //Destination scale +// DEFINE_FIELD( m_flScaleTimeStart, FIELD_FLOAT ), //Real time for start of scale +// DEFINE_FIELD( m_nStartBrightness, FIELD_INTEGER ), //Starting brightness +// DEFINE_FIELD( m_nDestBrightness, FIELD_INTEGER ), //Destination brightness +// DEFINE_FIELD( m_flBrightnessTimeStart, FIELD_FLOAT ), //Real time for brightness + +END_PREDICTION_DATA() + +#endif + +IMPLEMENT_NETWORKCLASS_ALIASED( Sprite, DT_Sprite ); + +#if defined( CLIENT_DLL ) + +static void RecvProxy_SpriteScale( const CRecvProxyData *pData, void *pStruct, void *pOut ) +{ + ((CSprite*)pStruct)->SetSpriteScale( pData->m_Value.m_Float ); +} + +#endif + +BEGIN_NETWORK_TABLE( CSprite, DT_Sprite ) +#if !defined( CLIENT_DLL ) + SendPropEHandle( SENDINFO(m_hAttachedToEntity )), + SendPropInt( SENDINFO(m_nAttachment ), 8 ), + SendPropFloat( SENDINFO(m_flScaleTime ), 0, SPROP_NOSCALE ), + +#ifdef HL2_DLL + SendPropFloat( SENDINFO(m_flSpriteScale ), 0, SPROP_NOSCALE), +#else + SendPropFloat( SENDINFO(m_flSpriteScale ), 8, SPROP_ROUNDUP, 0.0f, MAX_SPRITE_SCALE), +#endif + SendPropFloat( SENDINFO(m_flGlowProxySize ), 6, SPROP_ROUNDUP, 0.0f, MAX_GLOW_PROXY_SIZE), + + SendPropFloat( SENDINFO(m_flHDRColorScale ), 0, SPROP_NOSCALE, 0.0f, 100.0f), + + SendPropFloat( SENDINFO(m_flSpriteFramerate ), 8, SPROP_ROUNDUP, 0, 60.0f), + SendPropFloat( SENDINFO(m_flFrame), 20, SPROP_ROUNDDOWN, 0.0f, 256.0f), +#ifdef PORTAL + SendPropBool( SENDINFO(m_bDrawInMainRender) ), + SendPropBool( SENDINFO(m_bDrawInPortalRender) ), +#endif //#ifdef PORTAL + SendPropFloat( SENDINFO(m_flBrightnessTime ), 0, SPROP_NOSCALE ), + SendPropInt( SENDINFO(m_nBrightness), 8, SPROP_UNSIGNED ), + SendPropBool( SENDINFO(m_bWorldSpaceScale) ), +#else + RecvPropEHandle(RECVINFO(m_hAttachedToEntity)), + RecvPropInt(RECVINFO(m_nAttachment)), + RecvPropFloat(RECVINFO(m_flScaleTime)), + RecvPropFloat(RECVINFO(m_flSpriteScale), 0, RecvProxy_SpriteScale), + RecvPropFloat(RECVINFO(m_flSpriteFramerate)), + RecvPropFloat(RECVINFO(m_flGlowProxySize)), + + RecvPropFloat( RECVINFO(m_flHDRColorScale )), + + RecvPropFloat(RECVINFO(m_flFrame)), +#ifdef PORTAL + RecvPropBool( RECVINFO(m_bDrawInMainRender) ), + RecvPropBool( RECVINFO(m_bDrawInPortalRender) ), +#endif //#ifdef PORTAL + RecvPropFloat(RECVINFO(m_flBrightnessTime)), + RecvPropInt(RECVINFO(m_nBrightness)), + RecvPropBool( RECVINFO(m_bWorldSpaceScale) ), +#endif +END_NETWORK_TABLE() + + +CSprite::CSprite() +{ + m_flGlowProxySize = 2.0f; + m_flHDRColorScale = 1.0f; + +#ifdef PORTAL + m_bDrawInMainRender = true; + m_bDrawInPortalRender = true; +#endif +} +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CSprite::Spawn( void ) +{ + SetSolid( SOLID_NONE ); + SetMoveType( MOVETYPE_NONE ); + m_flFrame = 0; + + Precache(); + SetModel( STRING( GetModelName() ) ); + CollisionProp()->SetSurroundingBoundsType( USE_GAME_CODE ); + + m_flMaxFrame = (float)modelinfo->GetModelFrameCount( GetModel() ) - 1; + AddEffects( EF_NOSHADOW | EF_NORECEIVESHADOW ); + +#if defined( CLIENT_DLL ) + SetNextClientThink( CLIENT_THINK_ALWAYS ); +#endif + +#if !defined( CLIENT_DLL ) + if ( GetEntityName() != NULL_STRING && !(m_spawnflags & SF_SPRITE_STARTON) ) + { + TurnOff(); + } + else +#endif + { + TurnOn(); + } + + // Worldcraft only sets y rotation, copy to Z + if ( GetLocalAngles().y != 0 && GetLocalAngles().z == 0 ) + { + QAngle angles = GetLocalAngles(); + + angles.z = angles.y; + angles.y = 0; + + SetLocalAngles( angles ); + } + + // Clamp our scale if necessary + float scale = m_flSpriteScale; + + if ( scale < 0 || scale > MAX_SPRITE_SCALE ) + { +#if !defined( CLIENT_DLL ) + DevMsg( "LEVEL DESIGN ERROR: Sprite %s with bad scale %f [0..%f]\n", GetDebugName(), m_flSpriteScale.Get(), MAX_SPRITE_SCALE ); +#endif + scale = clamp( (float) m_flSpriteScale, 0.f, MAX_SPRITE_SCALE ); + } + + //Set our state + SetBrightness( m_clrRender->a ); + SetScale( scale ); + +#if defined( CLIENT_DLL ) + m_flStartScale = m_flDestScale = m_flSpriteScale; + m_nStartBrightness = m_nDestBrightness = m_nBrightness; +#endif + +} + + +//----------------------------------------------------------------------------- +// Purpose: Initialize absmin & absmax to the appropriate box +//----------------------------------------------------------------------------- +void CSprite::EnableWorldSpaceScale( bool bEnable ) +{ + m_bWorldSpaceScale = bEnable; +} + +//----------------------------------------------------------------------------- +// Purpose: Initialize absmin & absmax to the appropriate box +//----------------------------------------------------------------------------- +void CSprite::ComputeWorldSpaceSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs ) +{ + float flScale = m_flSpriteScale * 0.5f; + + if ( m_bWorldSpaceScale == false ) + { + // Find the height and width of the source of the sprite + float width = modelinfo->GetModelSpriteWidth( GetModel() ); + float height = modelinfo->GetModelSpriteHeight( GetModel() ); + flScale *= MAX( width, height ); + } + + pVecWorldMins->Init( -flScale, -flScale, -flScale ); + pVecWorldMaxs->Init( flScale, flScale, flScale ); + *pVecWorldMins += GetAbsOrigin(); + *pVecWorldMaxs += GetAbsOrigin(); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *szModelName - +//----------------------------------------------------------------------------- +void CSprite::SetModel( const char *szModelName ) +{ + int index = modelinfo->GetModelIndex( szModelName ); + const model_t *model = modelinfo->GetModel( index ); + if ( model && modelinfo->GetModelType( model ) != mod_sprite ) + { + Msg( "Setting CSprite to non-sprite model %s\n", szModelName?szModelName:"NULL" ); + } + +#if !defined( CLIENT_DLL ) + UTIL_SetModel( this, szModelName ); +#else + BaseClass::SetModel( szModelName ); +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CSprite::Precache( void ) +{ + if ( GetModelName() != NULL_STRING ) + { + PrecacheModel( STRING( GetModelName() ) ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pSpriteName - +// &origin - +//----------------------------------------------------------------------------- +void CSprite::SpriteInit( const char *pSpriteName, const Vector &origin ) +{ + SetModelName( MAKE_STRING(pSpriteName) ); + SetLocalOrigin( origin ); + Spawn(); +} + +#if !defined( CLIENT_DLL ) + +int CSprite::UpdateTransmitState( void ) +{ + if ( GetMoveParent() ) + { + // we must call ShouldTransmit() if we have a move parent + return SetTransmitState( FL_EDICT_FULLCHECK ); + } + else + { + return SetTransmitState( FL_EDICT_ALWAYS ); + } +} + +int CSprite::ShouldTransmit( const CCheckTransmitInfo *pInfo ) +{ + // Certain entities like sprites and ropes are strewn throughout the level and they rarely change. + // For these entities, it's more efficient to transmit them once and then always leave them on + // the client. Otherwise, the server will have to send big bursts of data with the entity states + // as they come in and out of the PVS. + + if ( GetMoveParent() ) + { + CBaseViewModel *pViewModel = dynamic_cast( GetMoveParent() ); + + if ( pViewModel ) + { + return pViewModel->ShouldTransmit( pInfo ); + } + } + + return FL_EDICT_ALWAYS; +} + +//----------------------------------------------------------------------------- +// Purpose: Fixup parent after restore +//----------------------------------------------------------------------------- +void CSprite::OnRestore() +{ + BaseClass::OnRestore(); + + // Reset attachment after save/restore + if ( GetFollowedEntity() ) + { + SetAttachment( GetFollowedEntity(), m_nAttachment ); + } + else + { + // Clear attachment + m_hAttachedToEntity = NULL; + m_nAttachment = 0; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pSpriteName - +// &origin - +// animate - +// Output : CSprite +//----------------------------------------------------------------------------- +CSprite *CSprite::SpriteCreate( const char *pSpriteName, const Vector &origin, bool animate ) +{ + CSprite *pSprite = CREATE_ENTITY( CSprite, "env_sprite" ); + pSprite->SpriteInit( pSpriteName, origin ); + pSprite->SetSolid( SOLID_NONE ); + UTIL_SetSize( pSprite, vec3_origin, vec3_origin ); + pSprite->SetMoveType( MOVETYPE_NONE ); + if ( animate ) + pSprite->TurnOn(); + + return pSprite; +} +#endif + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pSpriteName - +// &origin - +// animate - +// Output : CSprite +//----------------------------------------------------------------------------- +CSprite *CSprite::SpriteCreatePredictable( const char *module, int line, const char *pSpriteName, const Vector &origin, bool animate ) +{ + CSprite *pSprite = ( CSprite * )CBaseEntity::CreatePredictedEntityByName( "env_sprite", module, line ); + if ( pSprite ) + { + pSprite->SpriteInit( pSpriteName, origin ); + pSprite->SetSolid( SOLID_NONE ); + pSprite->SetSize( vec3_origin, vec3_origin ); + pSprite->SetMoveType( MOVETYPE_NONE ); + if ( animate ) + pSprite->TurnOn(); + } + + return pSprite; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CSprite::AnimateThink( void ) +{ + Animate( m_flSpriteFramerate * (gpGlobals->curtime - m_flLastTime) ); + + SetNextThink( gpGlobals->curtime ); + m_flLastTime = gpGlobals->curtime; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CSprite::AnimateUntilDead( void ) +{ + if ( gpGlobals->curtime > m_flDieTime ) + { + Remove( ); + } + else + { + AnimateThink(); + SetNextThink( gpGlobals->curtime ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : scaleSpeed - +// fadeSpeed - +//----------------------------------------------------------------------------- +void CSprite::Expand( float scaleSpeed, float fadeSpeed ) +{ + m_flSpeed = scaleSpeed; + m_iHealth = fadeSpeed; + SetThink( &CSprite::ExpandThink ); + + SetNextThink( gpGlobals->curtime ); + m_flLastTime = gpGlobals->curtime; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CSprite::ExpandThink( void ) +{ + float frametime = gpGlobals->curtime - m_flLastTime; + SetSpriteScale( m_flSpriteScale + m_flSpeed * frametime ); + + int sub = (int)(m_iHealth * frametime); + if ( sub > m_clrRender->a ) + { + SetRenderColorA( 0 ); + Remove( ); + } + else + { + SetRenderColorA( m_clrRender->a - sub ); + SetNextThink( gpGlobals->curtime ); + m_flLastTime = gpGlobals->curtime; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : frames - +//----------------------------------------------------------------------------- +void CSprite::Animate( float frames ) +{ + m_flFrame += frames; + if ( m_flFrame > m_flMaxFrame ) + { +#if !defined( CLIENT_DLL ) + if ( m_spawnflags & SF_SPRITE_ONCE ) + { + TurnOff(); + } + else +#endif + { + if ( m_flMaxFrame > 0 ) + m_flFrame = fmod( m_flFrame, m_flMaxFrame ); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CSprite::SetBrightness( int brightness, float time ) +{ + m_nBrightness = brightness; //Take our current position as our starting position + m_flBrightnessTime = time; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CSprite::SetSpriteScale( float scale ) +{ + if ( scale != m_flSpriteScale ) + { + m_flSpriteScale = scale; //Take our current position as our new starting position + // The surrounding box is based on sprite scale... it changes, box is dirty + CollisionProp()->MarkSurroundingBoundsDirty(); + } +} + +void CSprite::SetScale( float scale, float time ) +{ + m_flScaleTime = time; + SetSpriteScale( scale ); + // The surrounding box is based on sprite scale... it changes, box is dirty +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CSprite::TurnOff( void ) +{ + AddEffects( EF_NODRAW ); + SetNextThink( TICK_NEVER_THINK ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CSprite::TurnOn( void ) +{ + RemoveEffects( EF_NODRAW ); + if ( (m_flSpriteFramerate && m_flMaxFrame > 1.0) +#if !defined( CLIENT_DLL ) + || (m_spawnflags & SF_SPRITE_ONCE) +#endif + ) + { + SetThink( &CSprite::AnimateThink ); + SetNextThink( gpGlobals->curtime ); + m_flLastTime = gpGlobals->curtime; + } + m_flFrame = 0; +} + +#if !defined( CLIENT_DLL ) +// DVS TODO: Obsolete Use handler +void CSprite::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) +{ + int on = !IsEffectActive( EF_NODRAW ); + if ( ShouldToggle( useType, on ) ) + { + if ( on ) + { + TurnOff(); + } + else + { + TurnOn(); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: Input handler that hides the sprite. +//----------------------------------------------------------------------------- +void CSprite::InputHideSprite( inputdata_t &inputdata ) +{ + TurnOff(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Input handler that hides the sprite. +//----------------------------------------------------------------------------- +void CSprite::InputShowSprite( inputdata_t &inputdata ) +{ + TurnOn(); +} + +void CSprite::InputColorRedValue( inputdata_t &inputdata ) +{ + int nNewColor = clamp( FastFloatToSmallInt( inputdata.value.Float() ), 0, 255 ); + SetColor( nNewColor, m_clrRender->g, m_clrRender->b ); +} + +void CSprite::InputColorGreenValue( inputdata_t &inputdata ) +{ + int nNewColor = clamp( FastFloatToSmallInt( inputdata.value.Float() ), 0, 255 ); + SetColor( m_clrRender->r, nNewColor, m_clrRender->b ); +} + +void CSprite::InputColorBlueValue( inputdata_t &inputdata ) +{ + int nNewColor = clamp( FastFloatToSmallInt( inputdata.value.Float() ), 0, 255 ); + SetColor( m_clrRender->r, m_clrRender->g, nNewColor ); +} + +//----------------------------------------------------------------------------- +// Purpose: Input handler that toggles the sprite between hidden and shown. +//----------------------------------------------------------------------------- +void CSprite::InputToggleSprite( inputdata_t &inputdata ) +{ + if ( !IsEffectActive( EF_NODRAW ) ) + { + TurnOff(); + } + else + { + TurnOn(); + } +} +#endif + +#if defined( CLIENT_DLL ) + +//----------------------------------------------------------------------------- +// Purpose: +// Output : float +//----------------------------------------------------------------------------- +float CSprite::GetRenderScale( void ) +{ + //See if we're done scaling + if ( ( m_flScaleTime == 0 ) || ( (m_flScaleTimeStart+m_flScaleTime) < gpGlobals->curtime ) ) + return m_flSpriteScale; + + //Get our percentage + float timeDelta = ( gpGlobals->curtime - m_flScaleTimeStart ) / m_flScaleTime; + + //Return the result + return ( m_flStartScale + ( ( m_flDestScale - m_flStartScale ) * timeDelta ) ); +} + +//----------------------------------------------------------------------------- +// Purpose: Get the rendered extents of the sprite +//----------------------------------------------------------------------------- +void CSprite::GetRenderBounds( Vector &vecMins, Vector &vecMaxs ) +{ + float flScale = GetRenderScale() * 0.5f; + + // If our scale is normalized we need to convert that to actual world units + if ( m_bWorldSpaceScale == false ) + { + CEngineSprite *psprite = (CEngineSprite *) modelinfo->GetModelExtraData( GetModel() ); + if ( psprite ) + { + float flSize = MAX( psprite->GetWidth(), psprite->GetHeight() ); + flScale *= flSize; + } + } + + vecMins.Init( -flScale, -flScale, -flScale ); + vecMaxs.Init( flScale, flScale, flScale ); + +#if 0 + // Visualize the bounds + debugoverlay->AddBoxOverlay( GetRenderOrigin(), vecMins, vecMaxs, GetRenderAngles(), 255, 255, 255, 0, 0.01f ); +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +int CSprite::GetRenderBrightness( void ) +{ + //See if we're done scaling + if ( ( m_flBrightnessTime == 0 ) || ( (m_flBrightnessTimeStart+m_flBrightnessTime) < gpGlobals->curtime ) ) + { + return m_nBrightness; + } + + //Get our percentage + float timeDelta = ( gpGlobals->curtime - m_flBrightnessTimeStart ) / m_flBrightnessTime; + + float brightness = ( (float) m_nStartBrightness + ( (float) ( m_nDestBrightness - m_nStartBrightness ) * timeDelta ) ); + + //Return the result + return (int) brightness; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CSprite::OnDataChanged( DataUpdateType_t updateType ) +{ + BaseClass::OnDataChanged( updateType ); + + // Only think when sapping + SetNextClientThink( CLIENT_THINK_ALWAYS ); + if ( updateType == DATA_UPDATE_CREATED ) + { + m_flStartScale = m_flDestScale = m_flSpriteScale; + m_nStartBrightness = m_nDestBrightness = m_nBrightness; + } + + UpdateVisibility(); +} + +void CSprite::ClientThink( void ) +{ + BaseClass::ClientThink(); + + // Module render colors over time + if ( m_flSpriteScale != m_flDestScale ) + { + m_flStartScale = m_flDestScale; + m_flDestScale = m_flSpriteScale; + m_flScaleTimeStart = gpGlobals->curtime; + } + + if ( m_nBrightness != m_nDestBrightness ) + { + m_nStartBrightness = m_nDestBrightness; + m_nDestBrightness = m_nBrightness; + m_flBrightnessTimeStart = gpGlobals->curtime; + } +} + +extern bool g_bRenderingScreenshot; +extern ConVar r_drawviewmodel; + +//----------------------------------------------------------------------------- +// Purpose: +// Input : flags - +// Output : int +//----------------------------------------------------------------------------- +int CSprite::DrawModel( int flags ) +{ + VPROF_BUDGET( "CSprite::DrawModel", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); + //See if we should draw + if ( !IsVisible() || ( m_bReadyToDraw == false ) ) + return 0; + +#ifdef PORTAL + if ( ( !g_pPortalRender->IsRenderingPortal() && !m_bDrawInMainRender ) || + ( g_pPortalRender->IsRenderingPortal() && !m_bDrawInPortalRender ) ) + { + return 0; + } +#endif //#ifdef PORTAL + + // Tracker 16432: If rendering a savegame screenshot then don't draw sprites + // who have viewmodels as their moveparent + if ( g_bRenderingScreenshot || !r_drawviewmodel.GetBool() ) + { + C_BaseViewModel *vm = dynamic_cast< C_BaseViewModel * >( GetMoveParent() ); + if ( vm ) + { + return 0; + } + } + + //Must be a sprite + if ( modelinfo->GetModelType( GetModel() ) != mod_sprite ) + { + Assert( 0 ); + return 0; + } + + float renderscale = GetRenderScale(); + if ( m_bWorldSpaceScale ) + { + CEngineSprite *psprite = ( CEngineSprite * )modelinfo->GetModelExtraData( GetModel() ); + float flMinSize = MIN( psprite->GetWidth(), psprite->GetHeight() ); + renderscale /= flMinSize; + } + + //Draw it + int drawn = DrawSprite( + this, + GetModel(), + GetAbsOrigin(), + GetAbsAngles(), + m_flFrame, // sprite frame to render + m_hAttachedToEntity, // attach to + m_nAttachment, // attachment point + GetRenderMode(), // rendermode + m_nRenderFX, + GetRenderBrightness(), // alpha + m_clrRender->r, + m_clrRender->g, + m_clrRender->b, + renderscale, // sprite scale + GetHDRColorScale() // HDR Color Scale + ); + + return drawn; +} + + +const Vector& CSprite::GetRenderOrigin() +{ + static Vector vOrigin; + vOrigin = GetAbsOrigin(); + + if ( m_hAttachedToEntity ) + { + C_BaseEntity *ent = m_hAttachedToEntity->GetBaseEntity(); + if ( ent ) + { + QAngle dummyAngles; + ent->GetAttachment( m_nAttachment, vOrigin, dummyAngles ); + } + } + + return vOrigin; +} + +#endif + +//----------------------------------------------------------------------------- +// Purpose: oriented sprites +// CSprites swap the roll and yaw angle inputs, and rotate the yaw 180 degrees +//----------------------------------------------------------------------------- + +#if !defined( CLIENT_DLL ) +IMPLEMENT_SERVERCLASS_ST( CSpriteOriented, DT_SpriteOriented ) +END_SEND_TABLE() +#else +#undef CSpriteOriented +IMPLEMENT_CLIENTCLASS_DT(C_SpriteOriented, DT_SpriteOriented, CSpriteOriented) +#define CSpriteOriented C_SpriteOriented +END_RECV_TABLE() +#endif + +#if !defined( CLIENT_DLL ) + +void CSpriteOriented::Spawn( void ) +{ + // save a copy of the angles, CSprite swaps the yaw and roll + QAngle angles = GetAbsAngles(); + BaseClass::Spawn(); + // ORIENTED sprites "forward" vector points in the players "view" direction, not the direction "out" from the sprite (gah) + angles.y = anglemod( angles.y + 180 ); + SetAbsAngles( angles ); +} + +#else + +bool CSpriteOriented::IsTransparent( void ) +{ + return true; +} + +#endif -- cgit v1.2.3