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/client/c_env_particlescript.cpp | 304 ++++++++++++++++++++++++++++ 1 file changed, 304 insertions(+) create mode 100644 mp/src/game/client/c_env_particlescript.cpp (limited to 'mp/src/game/client/c_env_particlescript.cpp') diff --git a/mp/src/game/client/c_env_particlescript.cpp b/mp/src/game/client/c_env_particlescript.cpp new file mode 100644 index 00000000..cfbaa84d --- /dev/null +++ b/mp/src/game/client/c_env_particlescript.cpp @@ -0,0 +1,304 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#include "cbase.h" +#include "c_baseanimating.h" +#include "particlemgr.h" +#include "materialsystem/imaterialvar.h" +#include "cl_animevent.h" +#include "particle_util.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +//----------------------------------------------------------------------------- +// An entity which emits other entities at points +//----------------------------------------------------------------------------- +class C_EnvParticleScript : public C_BaseAnimating, public IParticleEffect +{ +public: + DECLARE_CLASS( C_EnvParticleScript, C_BaseAnimating ); + DECLARE_CLIENTCLASS(); + + C_EnvParticleScript(); + +// IParticleEffect overrides. +public: + virtual bool ShouldSimulate() const { return m_bSimulate; } + virtual void SetShouldSimulate( bool bSim ) { m_bSimulate = bSim; } + + virtual void RenderParticles( CParticleRenderIterator *pIterator ); + virtual void SimulateParticles( CParticleSimulateIterator *pIterator ); + + virtual const Vector &GetSortOrigin(); + +// C_BaseAnimating overrides +public: + // NOTE: Ths enclosed particle effect binding will do all the drawing + // But we have to return true, unlike other particle systems, for the animation events to work + virtual bool ShouldDraw() { return true; } + virtual int DrawModel( int flags ) { return 0; } + virtual int GetFxBlend( void ) { return 0; } + + virtual void FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options ); + virtual void OnPreDataChanged( DataUpdateType_t updateType ); + virtual void OnDataChanged( DataUpdateType_t updateType ); + +private: + + // Creates, destroys particles attached to an attachment + void CreateParticle( const char *pAttachmentName, const char *pSpriteName ); + void DestroyAllParticles( const char *pAttachmentName ); + void DestroyAllParticles( ); + +private: + struct ParticleScriptParticle_t : public Particle + { + int m_nAttachment; + float m_flSize; + }; + + CParticleEffectBinding m_ParticleEffect; + float m_flMaxParticleSize; + int m_nOldSequence; + float m_flSequenceScale; + bool m_bSimulate; +}; + +REGISTER_EFFECT( C_EnvParticleScript ); + +//----------------------------------------------------------------------------- +// Datatable +//----------------------------------------------------------------------------- +IMPLEMENT_CLIENTCLASS_DT( C_EnvParticleScript, DT_EnvParticleScript, CEnvParticleScript ) + RecvPropFloat( RECVINFO(m_flSequenceScale) ), +END_RECV_TABLE() + + +//----------------------------------------------------------------------------- +// Constructor +//----------------------------------------------------------------------------- +C_EnvParticleScript::C_EnvParticleScript() +{ + m_flMaxParticleSize = 0.0f; + m_bSimulate = true; +} + + +//----------------------------------------------------------------------------- +// Check for changed sequence numbers +//----------------------------------------------------------------------------- +void C_EnvParticleScript::OnPreDataChanged( DataUpdateType_t updateType ) +{ + BaseClass::OnPreDataChanged( updateType ); + + m_nOldSequence = GetSequence(); +} + + +//----------------------------------------------------------------------------- +// Starts up the particle system +//----------------------------------------------------------------------------- +void C_EnvParticleScript::OnDataChanged( DataUpdateType_t updateType ) +{ + BaseClass::OnDataChanged( updateType ); + + if(updateType == DATA_UPDATE_CREATED) + { + ParticleMgr()->AddEffect( &m_ParticleEffect, this ); + } + + if ( m_nOldSequence != GetSequence() ) + { + DestroyAllParticles(); + } +} + + +//----------------------------------------------------------------------------- +// Creates, destroys particles attached to an attachment +//----------------------------------------------------------------------------- +void C_EnvParticleScript::CreateParticle( const char *pAttachmentName, const char *pSpriteName ) +{ + // Find the attachment + int nAttachment = LookupAttachment( pAttachmentName ); + if ( nAttachment <= 0 ) + return; + + // Get the sprite materials + PMaterialHandle hMat = m_ParticleEffect.FindOrAddMaterial( pSpriteName ); + ParticleScriptParticle_t *pParticle = + (ParticleScriptParticle_t*)m_ParticleEffect.AddParticle(sizeof(ParticleScriptParticle_t), hMat); + + if ( pParticle == NULL ) + return; + + // Get the sprite size from the material's materialvars + bool bFound = false; + IMaterialVar *pMaterialVar = NULL; + IMaterial *pMaterial = ParticleMgr()->PMaterialToIMaterial( hMat ); + if ( pMaterial ) + { + pMaterialVar = pMaterial->FindVar( "$spritesize", &bFound, false ); + } + + if ( bFound ) + { + pParticle->m_flSize = pMaterialVar->GetFloatValue(); + } + else + { + pParticle->m_flSize = 100.0f; + } + + // Make sure the particle cull size reflects our particles + if ( pParticle->m_flSize > m_flMaxParticleSize ) + { + m_flMaxParticleSize = pParticle->m_flSize; + m_ParticleEffect.SetParticleCullRadius( m_flMaxParticleSize ); + } + + // Place the particle on the attachment specified + pParticle->m_nAttachment = nAttachment; + QAngle vecAngles; + GetAttachment( nAttachment, pParticle->m_Pos, vecAngles ); + + if ( m_flSequenceScale != 1.0f ) + { + pParticle->m_Pos -= GetAbsOrigin(); + pParticle->m_Pos *= m_flSequenceScale; + pParticle->m_Pos += GetAbsOrigin(); + } +} + +void C_EnvParticleScript::DestroyAllParticles( const char *pAttachmentName ) +{ + int nAttachment = LookupAttachment( pAttachmentName ); + if ( nAttachment <= 0 ) + return; + + int nCount = m_ParticleEffect.GetNumActiveParticles(); + Particle** ppParticles = (Particle**)stackalloc( nCount * sizeof(Particle*) ); + int nActualCount = m_ParticleEffect.GetActiveParticleList( nCount, ppParticles ); + Assert( nActualCount == nCount ); + + for ( int i = 0; i < nActualCount; ++i ) + { + ParticleScriptParticle_t *pParticle = (ParticleScriptParticle_t*)ppParticles[i]; + if ( pParticle->m_nAttachment == nAttachment ) + { + // Mark for deletion + pParticle->m_nAttachment = -1; + } + } +} + +void C_EnvParticleScript::DestroyAllParticles( ) +{ + int nCount = m_ParticleEffect.GetNumActiveParticles(); + Particle** ppParticles = (Particle**)stackalloc( nCount * sizeof(Particle*) ); + int nActualCount = m_ParticleEffect.GetActiveParticleList( nCount, ppParticles ); + Assert( nActualCount == nCount ); + + for ( int i = 0; i < nActualCount; ++i ) + { + ParticleScriptParticle_t *pParticle = (ParticleScriptParticle_t*)ppParticles[i]; + + // Mark for deletion + pParticle->m_nAttachment = -1; + } +} + + +//----------------------------------------------------------------------------- +// The animation events will create particles on the attachment points +//----------------------------------------------------------------------------- +void C_EnvParticleScript::FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options ) +{ + // Handle events to create + destroy particles + switch( event ) + { + case CL_EVENT_SPRITEGROUP_CREATE: + { + char pAttachmentName[256]; + char pSpriteName[256]; + int nArgs = sscanf( options, "%255s %255s", pAttachmentName, pSpriteName ); + if ( nArgs == 2 ) + { + CreateParticle( pAttachmentName, pSpriteName ); + } + } + return; + + case CL_EVENT_SPRITEGROUP_DESTROY: + { + char pAttachmentName[256]; + int nArgs = sscanf( options, "%255s", pAttachmentName ); + if ( nArgs == 1 ) + { + DestroyAllParticles( pAttachmentName ); + } + } + return; + } + + // Fall back + BaseClass::FireEvent( origin, angles, event, options ); +} + + +//----------------------------------------------------------------------------- +// Simulate the particles +//----------------------------------------------------------------------------- +void C_EnvParticleScript::RenderParticles( CParticleRenderIterator *pIterator ) +{ + const ParticleScriptParticle_t* pParticle = (const ParticleScriptParticle_t*)pIterator->GetFirst(); + while ( pParticle ) + { + Vector vecRenderPos; + TransformParticle( ParticleMgr()->GetModelView(), pParticle->m_Pos, vecRenderPos ); + float sortKey = vecRenderPos.z; + + Vector color( 1, 1, 1 ); + RenderParticle_ColorSize( pIterator->GetParticleDraw(), vecRenderPos, color, 1.0f, pParticle->m_flSize ); + + pParticle = (const ParticleScriptParticle_t*)pIterator->GetNext( sortKey ); + } +} + +void C_EnvParticleScript::SimulateParticles( CParticleSimulateIterator *pIterator ) +{ + ParticleScriptParticle_t* pParticle = (ParticleScriptParticle_t*)pIterator->GetFirst(); + while ( pParticle ) + { + // Here's how we retire particles + if ( pParticle->m_nAttachment == -1 ) + { + pIterator->RemoveParticle( pParticle ); + } + else + { + // Move the particle to the attachment point + QAngle vecAngles; + GetAttachment( pParticle->m_nAttachment, pParticle->m_Pos, vecAngles ); + + if ( m_flSequenceScale != 1.0f ) + { + pParticle->m_Pos -= GetAbsOrigin(); + pParticle->m_Pos *= m_flSequenceScale; + pParticle->m_Pos += GetAbsOrigin(); + } + } + + pParticle = (ParticleScriptParticle_t*)pIterator->GetNext(); + } +} + +const Vector &C_EnvParticleScript::GetSortOrigin() +{ + return GetAbsOrigin(); +} -- cgit v1.2.3