Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

871 lines
25 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Implements visual effects entities: sprites, beams, bubbles, etc.
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "Sprite.h"
  9. #include "model_types.h"
  10. #include "engine/ivmodelinfo.h"
  11. #include "tier0/vprof.h"
  12. #include "engine/ivdebugoverlay.h"
  13. #if defined( CLIENT_DLL )
  14. #include "enginesprite.h"
  15. #include "iclientmode.h"
  16. #include "c_baseviewmodel.h"
  17. # ifdef PORTAL
  18. #include "c_prop_portal.h"
  19. # endif //ifdef PORTAL
  20. #else
  21. #include "baseviewmodel.h"
  22. #endif
  23. // memdbgon must be the last include file in a .cpp file!!!
  24. #include "tier0/memdbgon.h"
  25. const float MAX_SPRITE_SCALE = 64.0f;
  26. const float MAX_GLOW_PROXY_SIZE = 64.0f;
  27. LINK_ENTITY_TO_CLASS( env_sprite, CSprite );
  28. LINK_ENTITY_TO_CLASS( env_sprite_oriented, CSpriteOriented );
  29. #if !defined( CLIENT_DLL )
  30. LINK_ENTITY_TO_CLASS( env_glow, CSprite ); // For backwards compatibility, remove when no longer needed.
  31. #endif
  32. #if !defined( CLIENT_DLL )
  33. BEGIN_DATADESC( CSprite )
  34. DEFINE_FIELD( m_flLastTime, FIELD_TIME ),
  35. DEFINE_FIELD( m_flMaxFrame, FIELD_FLOAT ),
  36. DEFINE_FIELD( m_hAttachedToEntity, FIELD_EHANDLE ),
  37. DEFINE_FIELD( m_nAttachment, FIELD_INTEGER ),
  38. DEFINE_FIELD( m_flDieTime, FIELD_TIME ),
  39. DEFINE_FIELD( m_nBrightness, FIELD_INTEGER ),
  40. DEFINE_FIELD( m_flBrightnessTime, FIELD_FLOAT ),
  41. DEFINE_KEYFIELD( m_flSpriteScale, FIELD_FLOAT, "scale" ),
  42. DEFINE_KEYFIELD( m_flSpriteFramerate, FIELD_FLOAT, "framerate" ),
  43. DEFINE_KEYFIELD( m_flFrame, FIELD_FLOAT, "frame" ),
  44. #ifdef PORTAL
  45. DEFINE_FIELD( m_bDrawInMainRender, FIELD_BOOLEAN ),
  46. DEFINE_FIELD( m_bDrawInPortalRender, FIELD_BOOLEAN ),
  47. #endif
  48. DEFINE_KEYFIELD( m_flHDRColorScale, FIELD_FLOAT, "HDRColorScale" ),
  49. DEFINE_KEYFIELD( m_flGlowProxySize, FIELD_FLOAT, "GlowProxySize" ),
  50. DEFINE_FIELD( m_flScaleTime, FIELD_FLOAT ),
  51. DEFINE_FIELD( m_flStartScale, FIELD_FLOAT ),
  52. DEFINE_FIELD( m_flDestScale, FIELD_FLOAT ),
  53. DEFINE_FIELD( m_flScaleTimeStart, FIELD_TIME ),
  54. DEFINE_FIELD( m_nStartBrightness, FIELD_INTEGER ),
  55. DEFINE_FIELD( m_nDestBrightness, FIELD_INTEGER ),
  56. DEFINE_FIELD( m_flBrightnessTimeStart, FIELD_TIME ),
  57. DEFINE_FIELD( m_bWorldSpaceScale, FIELD_BOOLEAN ),
  58. // Function Pointers
  59. DEFINE_FUNCTION( AnimateThink ),
  60. DEFINE_FUNCTION( ExpandThink ),
  61. DEFINE_FUNCTION( AnimateUntilDead ),
  62. DEFINE_FUNCTION( BeginFadeOutThink ),
  63. // Inputs
  64. DEFINE_INPUT( m_flSpriteScale, FIELD_FLOAT, "SetScale" ),
  65. DEFINE_INPUTFUNC( FIELD_VOID, "HideSprite", InputHideSprite ),
  66. DEFINE_INPUTFUNC( FIELD_VOID, "ShowSprite", InputShowSprite ),
  67. DEFINE_INPUTFUNC( FIELD_VOID, "ToggleSprite", InputToggleSprite ),
  68. DEFINE_INPUTFUNC( FIELD_FLOAT, "ColorRedValue", InputColorRedValue ),
  69. DEFINE_INPUTFUNC( FIELD_FLOAT, "ColorGreenValue", InputColorGreenValue ),
  70. DEFINE_INPUTFUNC( FIELD_FLOAT, "ColorBlueValue", InputColorBlueValue ),
  71. END_DATADESC()
  72. #else
  73. BEGIN_PREDICTION_DATA( CSprite )
  74. // Networked
  75. DEFINE_PRED_FIELD( m_hAttachedToEntity, FIELD_EHANDLE, FTYPEDESC_INSENDTABLE ),
  76. DEFINE_PRED_FIELD( m_nAttachment, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
  77. DEFINE_PRED_FIELD( m_flScaleTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
  78. DEFINE_PRED_FIELD( m_flSpriteScale, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
  79. DEFINE_PRED_FIELD( m_flSpriteFramerate, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
  80. DEFINE_PRED_FIELD( m_flFrame, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
  81. #ifdef PORTAL
  82. DEFINE_PRED_FIELD( m_bDrawInMainRender, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
  83. DEFINE_PRED_FIELD( m_bDrawInPortalRender, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
  84. #endif
  85. DEFINE_PRED_FIELD( m_flBrightnessTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
  86. DEFINE_PRED_FIELD( m_nBrightness, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
  87. DEFINE_FIELD( m_flLastTime, FIELD_FLOAT ),
  88. DEFINE_FIELD( m_flMaxFrame, FIELD_FLOAT ),
  89. DEFINE_FIELD( m_flDieTime, FIELD_FLOAT ),
  90. // DEFINE_FIELD( m_flHDRColorScale, FIELD_FLOAT ),
  91. // DEFINE_FIELD( m_flStartScale, FIELD_FLOAT ), //Starting scale
  92. // DEFINE_FIELD( m_flDestScale, FIELD_FLOAT ), //Destination scale
  93. // DEFINE_FIELD( m_flScaleTimeStart, FIELD_FLOAT ), //Real time for start of scale
  94. // DEFINE_FIELD( m_nStartBrightness, FIELD_INTEGER ), //Starting brightness
  95. // DEFINE_FIELD( m_nDestBrightness, FIELD_INTEGER ), //Destination brightness
  96. // DEFINE_FIELD( m_flBrightnessTimeStart, FIELD_FLOAT ), //Real time for brightness
  97. END_PREDICTION_DATA()
  98. #endif
  99. IMPLEMENT_NETWORKCLASS_ALIASED( Sprite, DT_Sprite );
  100. #if defined( CLIENT_DLL )
  101. static void RecvProxy_SpriteScale( const CRecvProxyData *pData, void *pStruct, void *pOut )
  102. {
  103. ((CSprite*)pStruct)->SetSpriteScale( pData->m_Value.m_Float );
  104. }
  105. #endif
  106. BEGIN_NETWORK_TABLE( CSprite, DT_Sprite )
  107. #if !defined( CLIENT_DLL )
  108. SendPropEHandle( SENDINFO(m_hAttachedToEntity )),
  109. SendPropInt( SENDINFO(m_nAttachment ), 8 ),
  110. SendPropFloat( SENDINFO(m_flScaleTime ), 0, SPROP_NOSCALE ),
  111. #ifdef HL2_DLL
  112. SendPropFloat( SENDINFO(m_flSpriteScale ), 0, SPROP_NOSCALE),
  113. #else
  114. SendPropFloat( SENDINFO(m_flSpriteScale ), 8, SPROP_ROUNDUP, 0.0f, MAX_SPRITE_SCALE),
  115. #endif
  116. SendPropFloat( SENDINFO(m_flGlowProxySize ), 6, SPROP_ROUNDUP, 0.0f, MAX_GLOW_PROXY_SIZE),
  117. SendPropFloat( SENDINFO(m_flHDRColorScale ), 0, SPROP_NOSCALE, 0.0f, 100.0f),
  118. SendPropFloat( SENDINFO(m_flSpriteFramerate ), 8, SPROP_ROUNDUP, 0, 60.0f),
  119. SendPropFloat( SENDINFO(m_flFrame), 20, SPROP_ROUNDDOWN, 0.0f, 256.0f),
  120. #ifdef PORTAL
  121. SendPropBool( SENDINFO(m_bDrawInMainRender) ),
  122. SendPropBool( SENDINFO(m_bDrawInPortalRender) ),
  123. #endif //#ifdef PORTAL
  124. SendPropFloat( SENDINFO(m_flBrightnessTime ), 0, SPROP_NOSCALE ),
  125. SendPropInt( SENDINFO(m_nBrightness), 8, SPROP_UNSIGNED ),
  126. SendPropBool( SENDINFO(m_bWorldSpaceScale) ),
  127. #else
  128. RecvPropEHandle(RECVINFO(m_hAttachedToEntity)),
  129. RecvPropInt(RECVINFO(m_nAttachment)),
  130. RecvPropFloat(RECVINFO(m_flScaleTime)),
  131. RecvPropFloat(RECVINFO(m_flSpriteScale), 0, RecvProxy_SpriteScale),
  132. RecvPropFloat(RECVINFO(m_flSpriteFramerate)),
  133. RecvPropFloat(RECVINFO(m_flGlowProxySize)),
  134. RecvPropFloat( RECVINFO(m_flHDRColorScale )),
  135. RecvPropFloat(RECVINFO(m_flFrame)),
  136. #ifdef PORTAL
  137. RecvPropBool( RECVINFO(m_bDrawInMainRender) ),
  138. RecvPropBool( RECVINFO(m_bDrawInPortalRender) ),
  139. #endif //#ifdef PORTAL
  140. RecvPropFloat(RECVINFO(m_flBrightnessTime)),
  141. RecvPropInt(RECVINFO(m_nBrightness)),
  142. RecvPropBool( RECVINFO(m_bWorldSpaceScale) ),
  143. #endif
  144. END_NETWORK_TABLE()
  145. CSprite::CSprite()
  146. {
  147. m_flGlowProxySize = 2.0f;
  148. m_flHDRColorScale = 1.0f;
  149. #ifdef PORTAL
  150. m_bDrawInMainRender = true;
  151. m_bDrawInPortalRender = true;
  152. #endif
  153. }
  154. //-----------------------------------------------------------------------------
  155. // Purpose:
  156. //-----------------------------------------------------------------------------
  157. void CSprite::Spawn( void )
  158. {
  159. SetSolid( SOLID_NONE );
  160. SetMoveType( MOVETYPE_NONE );
  161. m_flFrame = 0;
  162. Precache();
  163. SetModel( STRING( GetModelName() ) );
  164. CollisionProp()->SetSurroundingBoundsType( USE_GAME_CODE );
  165. m_flMaxFrame = (float)modelinfo->GetModelFrameCount( GetModel() ) - 1;
  166. AddEffects( EF_NOSHADOW | EF_NORECEIVESHADOW );
  167. #if defined( CLIENT_DLL )
  168. SetNextClientThink( CLIENT_THINK_ALWAYS );
  169. #endif
  170. #if !defined( CLIENT_DLL )
  171. if ( GetEntityName() != NULL_STRING && !(m_spawnflags & SF_SPRITE_STARTON) )
  172. {
  173. TurnOff();
  174. }
  175. else
  176. #endif
  177. {
  178. TurnOn();
  179. }
  180. // Worldcraft only sets y rotation, copy to Z
  181. if ( GetLocalAngles().y != 0 && GetLocalAngles().z == 0 )
  182. {
  183. QAngle angles = GetLocalAngles();
  184. angles.z = angles.y;
  185. angles.y = 0;
  186. SetLocalAngles( angles );
  187. }
  188. // Clamp our scale if necessary
  189. float scale = m_flSpriteScale;
  190. if ( scale < 0 || scale > MAX_SPRITE_SCALE )
  191. {
  192. #if !defined( CLIENT_DLL )
  193. DevMsg( "LEVEL DESIGN ERROR: Sprite %s with bad scale %f [0..%f]\n", GetDebugName(), m_flSpriteScale.Get(), MAX_SPRITE_SCALE );
  194. #endif
  195. scale = clamp( (float) m_flSpriteScale, 0.f, MAX_SPRITE_SCALE );
  196. }
  197. //Set our state
  198. SetBrightness( m_clrRender->a );
  199. SetScale( scale );
  200. #if defined( CLIENT_DLL )
  201. m_flStartScale = m_flDestScale = m_flSpriteScale;
  202. m_nStartBrightness = m_nDestBrightness = m_nBrightness;
  203. #endif
  204. }
  205. //-----------------------------------------------------------------------------
  206. // Purpose: Initialize absmin & absmax to the appropriate box
  207. //-----------------------------------------------------------------------------
  208. void CSprite::EnableWorldSpaceScale( bool bEnable )
  209. {
  210. m_bWorldSpaceScale = bEnable;
  211. }
  212. //-----------------------------------------------------------------------------
  213. // Purpose: Initialize absmin & absmax to the appropriate box
  214. //-----------------------------------------------------------------------------
  215. void CSprite::ComputeWorldSpaceSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs )
  216. {
  217. float flScale = m_flSpriteScale * 0.5f;
  218. if ( m_bWorldSpaceScale == false )
  219. {
  220. // Find the height and width of the source of the sprite
  221. float width = modelinfo->GetModelSpriteWidth( GetModel() );
  222. float height = modelinfo->GetModelSpriteHeight( GetModel() );
  223. flScale *= MAX( width, height );
  224. }
  225. pVecWorldMins->Init( -flScale, -flScale, -flScale );
  226. pVecWorldMaxs->Init( flScale, flScale, flScale );
  227. *pVecWorldMins += GetAbsOrigin();
  228. *pVecWorldMaxs += GetAbsOrigin();
  229. }
  230. //-----------------------------------------------------------------------------
  231. // Purpose:
  232. // Input : *szModelName -
  233. //-----------------------------------------------------------------------------
  234. void CSprite::SetModel( const char *szModelName )
  235. {
  236. int index_ = modelinfo->GetModelIndex( szModelName );
  237. const model_t *pModel = modelinfo->GetModel( index_ );
  238. if ( pModel && modelinfo->GetModelType( pModel ) != mod_sprite )
  239. {
  240. Msg( "Setting CSprite to non-sprite model %s\n", szModelName?szModelName:"NULL" );
  241. }
  242. #if !defined( CLIENT_DLL )
  243. UTIL_SetModel( this, szModelName );
  244. #else
  245. BaseClass::SetModel( szModelName );
  246. #endif
  247. }
  248. //-----------------------------------------------------------------------------
  249. // Purpose:
  250. //-----------------------------------------------------------------------------
  251. void CSprite::Precache( void )
  252. {
  253. if ( GetModelName() != NULL_STRING )
  254. {
  255. PrecacheModel( STRING( GetModelName() ) );
  256. }
  257. }
  258. //-----------------------------------------------------------------------------
  259. // Purpose:
  260. // Input : *pSpriteName -
  261. // &origin -
  262. //-----------------------------------------------------------------------------
  263. void CSprite::SpriteInit( const char *pSpriteName, const Vector &origin )
  264. {
  265. SetModelName( MAKE_STRING(pSpriteName) );
  266. SetLocalOrigin( origin );
  267. Spawn();
  268. }
  269. #if !defined( CLIENT_DLL )
  270. int CSprite::UpdateTransmitState( void )
  271. {
  272. if ( GetMoveParent() )
  273. {
  274. // we must call ShouldTransmit() if we have a move parent
  275. return SetTransmitState( FL_EDICT_FULLCHECK );
  276. }
  277. else
  278. {
  279. return SetTransmitState( FL_EDICT_ALWAYS );
  280. }
  281. }
  282. int CSprite::ShouldTransmit( const CCheckTransmitInfo *pInfo )
  283. {
  284. // Certain entities like sprites and ropes are strewn throughout the level and they rarely change.
  285. // For these entities, it's more efficient to transmit them once and then always leave them on
  286. // the client. Otherwise, the server will have to send big bursts of data with the entity states
  287. // as they come in and out of the PVS.
  288. if ( GetMoveParent() )
  289. {
  290. CBaseViewModel *pViewModel = dynamic_cast<CBaseViewModel *>( GetMoveParent() );
  291. if ( pViewModel )
  292. {
  293. return pViewModel->ShouldTransmit( pInfo );
  294. }
  295. }
  296. return FL_EDICT_ALWAYS;
  297. }
  298. //-----------------------------------------------------------------------------
  299. // Purpose: Fixup parent after restore
  300. //-----------------------------------------------------------------------------
  301. void CSprite::OnRestore()
  302. {
  303. BaseClass::OnRestore();
  304. // Reset attachment after save/restore
  305. if ( GetFollowedEntity() )
  306. {
  307. SetAttachment( GetFollowedEntity(), m_nAttachment );
  308. }
  309. else
  310. {
  311. // Clear attachment
  312. m_hAttachedToEntity = NULL;
  313. m_nAttachment = 0;
  314. }
  315. }
  316. //-----------------------------------------------------------------------------
  317. // Purpose:
  318. // Input : *pSpriteName -
  319. // &origin -
  320. // animate -
  321. // Output : CSprite
  322. //-----------------------------------------------------------------------------
  323. CSprite *CSprite::SpriteCreate( const char *pSpriteName, const Vector &origin, bool animate )
  324. {
  325. CSprite *pSprite = CREATE_ENTITY( CSprite, "env_sprite" );
  326. pSprite->SpriteInit( pSpriteName, origin );
  327. pSprite->SetSolid( SOLID_NONE );
  328. UTIL_SetSize( pSprite, vec3_origin, vec3_origin );
  329. pSprite->SetMoveType( MOVETYPE_NONE );
  330. if ( animate )
  331. pSprite->TurnOn();
  332. return pSprite;
  333. }
  334. #endif
  335. //-----------------------------------------------------------------------------
  336. // Purpose:
  337. // Input : *pSpriteName -
  338. // &origin -
  339. // animate -
  340. // Output : CSprite
  341. //-----------------------------------------------------------------------------
  342. CSprite *CSprite::SpriteCreatePredictable( const char *module, int line, const char *pSpriteName, const Vector &origin, bool animate )
  343. {
  344. CSprite *pSprite = ( CSprite * )CBaseEntity::CreatePredictedEntityByName( "env_sprite", module, line );
  345. if ( pSprite )
  346. {
  347. pSprite->SpriteInit( pSpriteName, origin );
  348. pSprite->SetSolid( SOLID_NONE );
  349. pSprite->SetSize( vec3_origin, vec3_origin );
  350. pSprite->SetMoveType( MOVETYPE_NONE );
  351. if ( animate )
  352. pSprite->TurnOn();
  353. }
  354. return pSprite;
  355. }
  356. //-----------------------------------------------------------------------------
  357. // Purpose:
  358. //-----------------------------------------------------------------------------
  359. void CSprite::AnimateThink( void )
  360. {
  361. Animate( m_flSpriteFramerate * (gpGlobals->curtime - m_flLastTime) );
  362. SetNextThink( gpGlobals->curtime );
  363. m_flLastTime = gpGlobals->curtime;
  364. }
  365. //-----------------------------------------------------------------------------
  366. // Purpose:
  367. //-----------------------------------------------------------------------------
  368. void CSprite::AnimateUntilDead( void )
  369. {
  370. if ( gpGlobals->curtime > m_flDieTime )
  371. {
  372. Remove( );
  373. }
  374. else
  375. {
  376. AnimateThink();
  377. SetNextThink( gpGlobals->curtime );
  378. }
  379. }
  380. //-----------------------------------------------------------------------------
  381. // Purpose:
  382. // Input : scaleSpeed -
  383. // fadeSpeed -
  384. //-----------------------------------------------------------------------------
  385. void CSprite::Expand( float scaleSpeed, float fadeSpeed )
  386. {
  387. m_flSpeed = scaleSpeed;
  388. m_iHealth = fadeSpeed;
  389. SetThink( &CSprite::ExpandThink );
  390. SetNextThink( gpGlobals->curtime );
  391. m_flLastTime = gpGlobals->curtime;
  392. }
  393. //-----------------------------------------------------------------------------
  394. // Purpose:
  395. //-----------------------------------------------------------------------------
  396. void CSprite::ExpandThink( void )
  397. {
  398. float frametime = gpGlobals->curtime - m_flLastTime;
  399. SetSpriteScale( m_flSpriteScale + m_flSpeed * frametime );
  400. int sub = (int)(m_iHealth * frametime);
  401. if ( sub > m_clrRender->a )
  402. {
  403. SetRenderColorA( 0 );
  404. Remove( );
  405. }
  406. else
  407. {
  408. SetRenderColorA( m_clrRender->a - sub );
  409. SetNextThink( gpGlobals->curtime );
  410. m_flLastTime = gpGlobals->curtime;
  411. }
  412. }
  413. //-----------------------------------------------------------------------------
  414. // Purpose:
  415. // Input : frames -
  416. //-----------------------------------------------------------------------------
  417. void CSprite::Animate( float frames )
  418. {
  419. m_flFrame += frames;
  420. if ( m_flFrame > m_flMaxFrame )
  421. {
  422. #if !defined( CLIENT_DLL )
  423. if ( m_spawnflags & SF_SPRITE_ONCE )
  424. {
  425. TurnOff();
  426. }
  427. else
  428. #endif
  429. {
  430. if ( m_flMaxFrame > 0 )
  431. m_flFrame = fmod( m_flFrame, m_flMaxFrame );
  432. }
  433. }
  434. }
  435. //-----------------------------------------------------------------------------
  436. // Purpose:
  437. //-----------------------------------------------------------------------------
  438. void CSprite::SetBrightness( int brightness, float time )
  439. {
  440. m_nBrightness = brightness; //Take our current position as our starting position
  441. m_flBrightnessTime = time;
  442. }
  443. //-----------------------------------------------------------------------------
  444. // Purpose:
  445. //-----------------------------------------------------------------------------
  446. void CSprite::SetSpriteScale( float scale )
  447. {
  448. if ( scale != m_flSpriteScale )
  449. {
  450. m_flSpriteScale = scale; //Take our current position as our new starting position
  451. // The surrounding box is based on sprite scale... it changes, box is dirty
  452. CollisionProp()->MarkSurroundingBoundsDirty();
  453. }
  454. }
  455. void CSprite::SetScale( float scale, float time )
  456. {
  457. m_flScaleTime = time;
  458. SetSpriteScale( scale );
  459. // The surrounding box is based on sprite scale... it changes, box is dirty
  460. }
  461. //-----------------------------------------------------------------------------
  462. // Purpose:
  463. //-----------------------------------------------------------------------------
  464. void CSprite::TurnOff( void )
  465. {
  466. AddEffects( EF_NODRAW );
  467. SetNextThink( TICK_NEVER_THINK );
  468. }
  469. //-----------------------------------------------------------------------------
  470. // Purpose:
  471. //-----------------------------------------------------------------------------
  472. void CSprite::TurnOn( void )
  473. {
  474. RemoveEffects( EF_NODRAW );
  475. if ( (m_flSpriteFramerate && m_flMaxFrame > 1.0)
  476. #if !defined( CLIENT_DLL )
  477. || (m_spawnflags & SF_SPRITE_ONCE)
  478. #endif
  479. )
  480. {
  481. SetThink( &CSprite::AnimateThink );
  482. SetNextThink( gpGlobals->curtime );
  483. m_flLastTime = gpGlobals->curtime;
  484. }
  485. m_flFrame = 0;
  486. }
  487. #if !defined( CLIENT_DLL )
  488. // DVS TODO: Obsolete Use handler
  489. void CSprite::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
  490. {
  491. int on = !IsEffectActive( EF_NODRAW );
  492. if ( ShouldToggle( useType, on ) )
  493. {
  494. if ( on )
  495. {
  496. TurnOff();
  497. }
  498. else
  499. {
  500. TurnOn();
  501. }
  502. }
  503. }
  504. //-----------------------------------------------------------------------------
  505. // Purpose: Input handler that hides the sprite.
  506. //-----------------------------------------------------------------------------
  507. void CSprite::InputHideSprite( inputdata_t &inputdata )
  508. {
  509. TurnOff();
  510. }
  511. //-----------------------------------------------------------------------------
  512. // Purpose: Input handler that hides the sprite.
  513. //-----------------------------------------------------------------------------
  514. void CSprite::InputShowSprite( inputdata_t &inputdata )
  515. {
  516. TurnOn();
  517. }
  518. void CSprite::InputColorRedValue( inputdata_t &inputdata )
  519. {
  520. int nNewColor = clamp( FastFloatToSmallInt( inputdata.value.Float() ), 0, 255 );
  521. SetColor( nNewColor, m_clrRender->g, m_clrRender->b );
  522. }
  523. void CSprite::InputColorGreenValue( inputdata_t &inputdata )
  524. {
  525. int nNewColor = clamp( FastFloatToSmallInt( inputdata.value.Float() ), 0, 255 );
  526. SetColor( m_clrRender->r, nNewColor, m_clrRender->b );
  527. }
  528. void CSprite::InputColorBlueValue( inputdata_t &inputdata )
  529. {
  530. int nNewColor = clamp( FastFloatToSmallInt( inputdata.value.Float() ), 0, 255 );
  531. SetColor( m_clrRender->r, m_clrRender->g, nNewColor );
  532. }
  533. //-----------------------------------------------------------------------------
  534. // Purpose: Input handler that toggles the sprite between hidden and shown.
  535. //-----------------------------------------------------------------------------
  536. void CSprite::InputToggleSprite( inputdata_t &inputdata )
  537. {
  538. if ( !IsEffectActive( EF_NODRAW ) )
  539. {
  540. TurnOff();
  541. }
  542. else
  543. {
  544. TurnOn();
  545. }
  546. }
  547. #endif
  548. #if defined( CLIENT_DLL )
  549. //-----------------------------------------------------------------------------
  550. // Purpose:
  551. // Output : float
  552. //-----------------------------------------------------------------------------
  553. float CSprite::GetRenderScale( void )
  554. {
  555. //See if we're done scaling
  556. if ( ( m_flScaleTime == 0 ) || ( (m_flScaleTimeStart+m_flScaleTime) < gpGlobals->curtime ) )
  557. return m_flSpriteScale;
  558. //Get our percentage
  559. float timeDelta = ( gpGlobals->curtime - m_flScaleTimeStart ) / m_flScaleTime;
  560. //Return the result
  561. return ( m_flStartScale + ( ( m_flDestScale - m_flStartScale ) * timeDelta ) );
  562. }
  563. //-----------------------------------------------------------------------------
  564. // Purpose: Get the rendered extents of the sprite
  565. //-----------------------------------------------------------------------------
  566. void CSprite::GetRenderBounds( Vector &vecMins, Vector &vecMaxs )
  567. {
  568. float flScale = GetRenderScale() * 0.5f;
  569. // If our scale is normalized we need to convert that to actual world units
  570. if ( m_bWorldSpaceScale == false )
  571. {
  572. CEngineSprite *psprite = (CEngineSprite *) modelinfo->GetModelExtraData( GetModel() );
  573. if ( psprite )
  574. {
  575. float flSize = MAX( psprite->GetWidth(), psprite->GetHeight() );
  576. flScale *= flSize;
  577. }
  578. }
  579. vecMins.Init( -flScale, -flScale, -flScale );
  580. vecMaxs.Init( flScale, flScale, flScale );
  581. #if 0
  582. // Visualize the bounds
  583. if ( debugoverlay )
  584. {
  585. debugoverlay->AddBoxOverlay( GetRenderOrigin(), vecMins, vecMaxs, GetRenderAngles(), 255, 255, 255, 0, 0.01f );
  586. }
  587. #endif
  588. }
  589. //-----------------------------------------------------------------------------
  590. // Purpose:
  591. //-----------------------------------------------------------------------------
  592. int CSprite::GetRenderBrightness( void )
  593. {
  594. //See if we're done scaling
  595. if ( ( m_flBrightnessTime == 0 ) || ( (m_flBrightnessTimeStart+m_flBrightnessTime) < gpGlobals->curtime ) )
  596. {
  597. return m_nBrightness;
  598. }
  599. //Get our percentage
  600. float timeDelta = ( gpGlobals->curtime - m_flBrightnessTimeStart ) / m_flBrightnessTime;
  601. float brightness = ( (float) m_nStartBrightness + ( (float) ( m_nDestBrightness - m_nStartBrightness ) * timeDelta ) );
  602. //Return the result
  603. return (int) brightness;
  604. }
  605. //-----------------------------------------------------------------------------
  606. // Purpose:
  607. //-----------------------------------------------------------------------------
  608. void CSprite::OnDataChanged( DataUpdateType_t updateType )
  609. {
  610. BaseClass::OnDataChanged( updateType );
  611. // Only think when sapping
  612. SetNextClientThink( CLIENT_THINK_ALWAYS );
  613. if ( updateType == DATA_UPDATE_CREATED )
  614. {
  615. m_flStartScale = m_flDestScale = m_flSpriteScale;
  616. m_nStartBrightness = m_nDestBrightness = m_nBrightness;
  617. }
  618. UpdateVisibility();
  619. }
  620. void CSprite::ClientThink( void )
  621. {
  622. BaseClass::ClientThink();
  623. // Module render colors over time
  624. if ( m_flSpriteScale != m_flDestScale )
  625. {
  626. m_flStartScale = m_flDestScale;
  627. m_flDestScale = m_flSpriteScale;
  628. m_flScaleTimeStart = gpGlobals->curtime;
  629. }
  630. if ( m_nBrightness != m_nDestBrightness )
  631. {
  632. m_nStartBrightness = m_nDestBrightness;
  633. m_nDestBrightness = m_nBrightness;
  634. m_flBrightnessTimeStart = gpGlobals->curtime;
  635. }
  636. }
  637. extern bool g_bRenderingScreenshot;
  638. extern ConVar r_drawviewmodel;
  639. //-----------------------------------------------------------------------------
  640. // Purpose:
  641. // Input : flags -
  642. // Output : int
  643. //-----------------------------------------------------------------------------
  644. int CSprite::DrawModel( int flags )
  645. {
  646. VPROF_BUDGET( "CSprite::DrawModel", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
  647. //See if we should draw
  648. if ( !IsVisible() || ( m_bReadyToDraw == false ) )
  649. return 0;
  650. #ifdef PORTAL
  651. if ( ( !g_pPortalRender->IsRenderingPortal() && !m_bDrawInMainRender ) ||
  652. ( g_pPortalRender->IsRenderingPortal() && !m_bDrawInPortalRender ) )
  653. {
  654. return 0;
  655. }
  656. #endif //#ifdef PORTAL
  657. // Tracker 16432: If rendering a savegame screenshot then don't draw sprites
  658. // who have viewmodels as their moveparent
  659. if ( g_bRenderingScreenshot || !r_drawviewmodel.GetBool() )
  660. {
  661. C_BaseViewModel *vm = dynamic_cast< C_BaseViewModel * >( GetMoveParent() );
  662. if ( vm )
  663. {
  664. return 0;
  665. }
  666. }
  667. //Must be a sprite
  668. if ( modelinfo->GetModelType( GetModel() ) != mod_sprite )
  669. {
  670. Assert( 0 );
  671. return 0;
  672. }
  673. float renderscale = GetRenderScale();
  674. if ( m_bWorldSpaceScale )
  675. {
  676. CEngineSprite *psprite = ( CEngineSprite * )modelinfo->GetModelExtraData( GetModel() );
  677. float flMinSize = MIN( psprite->GetWidth(), psprite->GetHeight() );
  678. renderscale /= flMinSize;
  679. }
  680. //Draw it
  681. int drawn = DrawSprite(
  682. this,
  683. GetModel(),
  684. GetAbsOrigin(),
  685. GetAbsAngles(),
  686. m_flFrame, // sprite frame to render
  687. m_hAttachedToEntity, // attach to
  688. m_nAttachment, // attachment point
  689. GetRenderMode(), // rendermode
  690. m_nRenderFX,
  691. GetRenderBrightness(), // alpha
  692. m_clrRender->r,
  693. m_clrRender->g,
  694. m_clrRender->b,
  695. renderscale, // sprite scale
  696. GetHDRColorScale() // HDR Color Scale
  697. );
  698. return drawn;
  699. }
  700. const Vector& CSprite::GetRenderOrigin()
  701. {
  702. static Vector vOrigin;
  703. vOrigin = GetAbsOrigin();
  704. if ( m_hAttachedToEntity )
  705. {
  706. C_BaseEntity *ent = m_hAttachedToEntity->GetBaseEntity();
  707. if ( ent )
  708. {
  709. QAngle dummyAngles;
  710. ent->GetAttachment( m_nAttachment, vOrigin, dummyAngles );
  711. }
  712. }
  713. return vOrigin;
  714. }
  715. #endif
  716. //-----------------------------------------------------------------------------
  717. // Purpose: oriented sprites
  718. // CSprites swap the roll and yaw angle inputs, and rotate the yaw 180 degrees
  719. //-----------------------------------------------------------------------------
  720. #if !defined( CLIENT_DLL )
  721. IMPLEMENT_SERVERCLASS_ST( CSpriteOriented, DT_SpriteOriented )
  722. END_SEND_TABLE()
  723. #else
  724. #undef CSpriteOriented
  725. IMPLEMENT_CLIENTCLASS_DT(C_SpriteOriented, DT_SpriteOriented, CSpriteOriented)
  726. #define CSpriteOriented C_SpriteOriented
  727. END_RECV_TABLE()
  728. #endif
  729. #if !defined( CLIENT_DLL )
  730. void CSpriteOriented::Spawn( void )
  731. {
  732. // save a copy of the angles, CSprite swaps the yaw and roll
  733. QAngle angles = GetAbsAngles();
  734. BaseClass::Spawn();
  735. // ORIENTED sprites "forward" vector points in the players "view" direction, not the direction "out" from the sprite (gah)
  736. angles.y = anglemod( angles.y + 180 );
  737. SetAbsAngles( angles );
  738. }
  739. #else
  740. bool CSpriteOriented::IsTransparent( void )
  741. {
  742. return true;
  743. }
  744. #endif