diff options
| author | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
|---|---|---|
| committer | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
| commit | 39ed87570bdb2f86969d4be821c94b722dc71179 (patch) | |
| tree | abc53757f75f40c80278e87650ea92808274aa59 /mp/src/game/shared/particle_property.cpp | |
| download | source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip | |
First version of the SOurce SDK 2013
Diffstat (limited to 'mp/src/game/shared/particle_property.cpp')
| -rw-r--r-- | mp/src/game/shared/particle_property.cpp | 655 |
1 files changed, 655 insertions, 0 deletions
diff --git a/mp/src/game/shared/particle_property.cpp b/mp/src/game/shared/particle_property.cpp new file mode 100644 index 00000000..b1ae32a7 --- /dev/null +++ b/mp/src/game/shared/particle_property.cpp @@ -0,0 +1,655 @@ +//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================
+
+#include "cbase.h"
+#include "particle_property.h"
+#include "utlvector.h"
+
+#ifdef CLIENT_DLL
+
+#include "c_baseentity.h"
+#include "c_baseanimating.h"
+#include "recvproxy.h"
+#include "particles_new.h"
+#include "engine/ivdebugoverlay.h"
+#include "bone_setup.h"
+#else
+
+#include "baseentity.h"
+#include "baseanimating.h"
+#include "sendproxy.h"
+#endif
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+//-----------------------------------------------------------------------------
+// Save/load
+//-----------------------------------------------------------------------------
+BEGIN_DATADESC_NO_BASE( CParticleProperty )
+ // DEFINE_FIELD( m_pOuter, FIELD_CLASSPTR ),
+END_DATADESC()
+
+#ifdef CLIENT_DLL
+//-----------------------------------------------------------------------------
+// Prediction
+//-----------------------------------------------------------------------------
+BEGIN_PREDICTION_DATA_NO_BASE( CParticleProperty )
+ //DEFINE_PRED_FIELD( m_vecMins, FIELD_VECTOR, FTYPEDESC_INSENDTABLE ),
+END_PREDICTION_DATA()
+#endif
+
+//-----------------------------------------------------------------------------
+// Networking
+//-----------------------------------------------------------------------------
+BEGIN_NETWORK_TABLE_NOBASE( CParticleProperty, DT_ParticleProperty )
+#ifdef CLIENT_DLL
+//RecvPropVector( RECVINFO(m_vecMins), 0, RecvProxy_OBBMins ),
+#else
+//SendPropVector( SENDINFO(m_vecMins), 0, SPROP_NOSCALE),
+#endif
+END_NETWORK_TABLE()
+
+
+//-----------------------------------------------------------------------------
+// Constructor, destructor
+//-----------------------------------------------------------------------------
+CParticleProperty::CParticleProperty()
+{
+ Init( NULL );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CParticleProperty::~CParticleProperty()
+{
+ // We're being removed. Call StopEmission() on any particle system
+ // that has an unlimited number of particles to emit.
+ StopEmission( NULL, false, true );
+}
+
+//-----------------------------------------------------------------------------
+// Initialization
+//-----------------------------------------------------------------------------
+void CParticleProperty::Init( CBaseEntity *pEntity )
+{
+ m_pOuter = pEntity;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+int CParticleProperty::GetParticleAttachment( C_BaseEntity *pEntity, const char *pszAttachmentName, const char *pszParticleName )
+{
+ Assert( pEntity && pEntity->GetBaseAnimating() );
+ if ( !pEntity || !pEntity->GetBaseAnimating() )
+ return INVALID_PARTICLE_ATTACHMENT;
+
+ // Find the attachment point index
+ int iAttachment = pEntity->GetBaseAnimating()->LookupAttachment( pszAttachmentName );
+ if ( iAttachment == INVALID_PARTICLE_ATTACHMENT )
+ {
+ Warning("Model '%s' doesn't have attachment '%s' to attach particle system '%s' to.\n", STRING(pEntity->GetBaseAnimating()->GetModelName()), pszAttachmentName, pszParticleName );
+ }
+
+ return iAttachment;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Create a new particle system and attach it to our owner
+//-----------------------------------------------------------------------------
+CNewParticleEffect *CParticleProperty::Create( const char *pszParticleName, ParticleAttachment_t iAttachType, const char *pszAttachmentName )
+{
+ int iAttachment = GetParticleAttachment( GetOuter(), pszAttachmentName, pszParticleName );
+ if ( iAttachment == INVALID_PARTICLE_ATTACHMENT )
+ return NULL;
+
+ // Create the system
+ return Create( pszParticleName, iAttachType, iAttachment );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Create a new particle system and attach it to our owner
+//-----------------------------------------------------------------------------
+static ConVar cl_particle_batch_mode( "cl_particle_batch_mode", "1" );
+CNewParticleEffect *CParticleProperty::Create( const char *pszParticleName, ParticleAttachment_t iAttachType, int iAttachmentPoint, Vector vecOriginOffset )
+{
+ if ( GameRules() )
+ {
+ pszParticleName = GameRules()->TranslateEffectForVisionFilter( "particles", pszParticleName );
+ }
+
+ int nBatchMode = cl_particle_batch_mode.GetInt();
+ CParticleSystemDefinition *pDef = g_pParticleSystemMgr->FindParticleSystem( pszParticleName );
+ bool bRequestedBatch = ( nBatchMode == 2 ) || ( ( nBatchMode == 1 ) && pDef && pDef->ShouldBatch() );
+ if ( ( iAttachType == PATTACH_CUSTOMORIGIN ) && bRequestedBatch )
+ {
+ int iIndex = FindEffect( pszParticleName );
+ if ( iIndex >= 0 )
+ {
+ CNewParticleEffect *pEffect = m_ParticleEffects[iIndex].pParticleEffect.GetObject();
+ pEffect->Restart();
+ return pEffect;
+ }
+ }
+
+ if ( !pDef )
+ {
+ AssertMsg( 0, "Attempting to create unknown particle system" );
+ Warning( "Attempting to create unknown particle system '%s' \n", pszParticleName );
+ return NULL;
+ }
+
+ int iIndex = m_ParticleEffects.AddToTail();
+ ParticleEffectList_t *newEffect = &m_ParticleEffects[iIndex];
+ newEffect->pParticleEffect = CNewParticleEffect::Create( m_pOuter, pDef );
+
+ if ( !newEffect->pParticleEffect->IsValid() )
+ {
+ // Caused by trying to spawn an unregistered particle effect. Remove it.
+ ParticleMgr()->RemoveEffect( newEffect->pParticleEffect.GetObject() );
+ return NULL;
+ }
+
+ AddControlPoint( iIndex, 0, GetOuter(), iAttachType, iAttachmentPoint, vecOriginOffset );
+
+ if ( m_pOuter )
+ {
+ m_pOuter->OnNewParticleEffect( pszParticleName, newEffect->pParticleEffect.GetObject() );
+ }
+
+ return newEffect->pParticleEffect.GetObject();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CParticleProperty::AddControlPoint( CNewParticleEffect *pEffect, int iPoint, C_BaseEntity *pEntity, ParticleAttachment_t iAttachType, const char *pszAttachmentName, Vector vecOriginOffset )
+{
+ int iAttachment = INVALID_PARTICLE_ATTACHMENT;
+ if ( pszAttachmentName )
+ {
+ iAttachment = GetParticleAttachment( pEntity, pszAttachmentName, pEffect->GetEffectName() );
+ }
+
+ for ( int i = 0; i < m_ParticleEffects.Count(); i++ )
+ {
+ if ( m_ParticleEffects[i].pParticleEffect == pEffect )
+ {
+ AddControlPoint( i, iPoint, pEntity, iAttachType, iAttachment, vecOriginOffset );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CParticleProperty::AddControlPoint( int iEffectIndex, int iPoint, C_BaseEntity *pEntity, ParticleAttachment_t iAttachType, int iAttachmentPoint, Vector vecOriginOffset )
+{
+ Assert( iEffectIndex >= 0 && iEffectIndex < m_ParticleEffects.Count() );
+ ParticleEffectList_t *pEffect = &m_ParticleEffects[iEffectIndex];
+ Assert( pEffect->pControlPoints.Count() < MAX_PARTICLE_CONTROL_POINTS );
+
+ int iIndex = pEffect->pControlPoints.AddToTail();
+ ParticleControlPoint_t *pNewPoint = &pEffect->pControlPoints[iIndex];
+ pNewPoint->iControlPoint = iPoint;
+ pNewPoint->hEntity = pEntity;
+ pNewPoint->iAttachType = iAttachType;
+ pNewPoint->iAttachmentPoint = iAttachmentPoint;
+ pNewPoint->vecOriginOffset = vecOriginOffset;
+
+ UpdateParticleEffect( pEffect, true, iIndex );
+}
+
+
+//-----------------------------------------------------------------------------
+// Used to replace a particle effect with a different one; attaches the control point updating to the new one
+//-----------------------------------------------------------------------------
+void CParticleProperty::ReplaceParticleEffect( CNewParticleEffect *pOldEffect, CNewParticleEffect *pNewEffect )
+{
+ int nCount = m_ParticleEffects.Count();
+ for ( int i = 0; i < nCount; ++i )
+ {
+ if ( pOldEffect != m_ParticleEffects[i].pParticleEffect.GetObject() )
+ continue;
+
+ m_ParticleEffects[i].pParticleEffect = pNewEffect;
+ UpdateParticleEffect( &m_ParticleEffects[i], true );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Set the parent of a given control point to the index of some other
+// control point.
+//-----------------------------------------------------------------------------
+void CParticleProperty::SetControlPointParent( int iEffectIndex, int whichControlPoint, int parentIdx )
+{
+
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Stop effects from emitting more particles. If no effect is
+// specified, all effects attached to this entity are stopped.
+//-----------------------------------------------------------------------------
+void CParticleProperty::StopEmission( CNewParticleEffect *pEffect, bool bWakeOnStop, bool bDestroyAsleepSystems )
+{
+ // If we return from dormancy and are then told to stop emitting,
+ // we should have died while dormant. Remove ourselves immediately.
+ bool bRemoveInstantly = (m_iDormancyChangedAtFrame == gpGlobals->framecount);
+
+ if ( pEffect )
+ {
+ if ( FindEffect( pEffect ) != -1 )
+ {
+ pEffect->StopEmission( false, bRemoveInstantly, bWakeOnStop );
+ }
+ }
+ else
+ {
+ // Stop all effects
+ float flNow = g_pParticleSystemMgr->GetLastSimulationTime();
+ int nCount = m_ParticleEffects.Count();
+ for ( int i = nCount-1; i >= 0; i-- )
+ {
+ CNewParticleEffect *pTmp = m_ParticleEffects[i].pParticleEffect.GetObject();
+ bool bRemoveSystem = bRemoveInstantly || ( bDestroyAsleepSystems && ( flNow >= pTmp->m_flNextSleepTime ) );
+ if ( bRemoveSystem )
+ {
+ m_ParticleEffects.Remove( i );
+ pTmp->SetOwner( NULL );
+ }
+ pTmp->StopEmission( false, bRemoveSystem, !bRemoveSystem && bWakeOnStop );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Remove effects immediately, including all current particles. If no
+// effect is specified, all effects attached to this entity are removed.
+//-----------------------------------------------------------------------------
+void CParticleProperty::StopEmissionAndDestroyImmediately( CNewParticleEffect *pEffect )
+{
+ if ( pEffect )
+ {
+ int iIndex = FindEffect( pEffect );
+ //Assert( iIndex != -1 );
+ if ( iIndex != -1 )
+ {
+ m_ParticleEffects.Remove( iIndex );
+
+ // Clear the owner so it doesn't try to call back to us on deletion
+ pEffect->SetOwner( NULL );
+ pEffect->StopEmission( false, true );
+ }
+ }
+ else
+ {
+ // Immediately destroy all effects
+ int nCount = m_ParticleEffects.Count();
+ for ( int i = nCount-1; i >= 0; i-- )
+ {
+ CNewParticleEffect *pTmp = m_ParticleEffects[i].pParticleEffect.GetObject();
+ m_ParticleEffects.Remove( i );
+
+ // Clear the owner so it doesn't try to call back to us on deletion
+ pTmp->SetOwner( NULL );
+ pTmp->StopEmission( false, true );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Stop all effects that have a control point associated with the given
+// entity.
+//-----------------------------------------------------------------------------
+void CParticleProperty::StopParticlesInvolving( CBaseEntity *pEntity )
+{
+ Assert( pEntity );
+
+ EHANDLE entHandle(pEntity);
+
+ // If we return from dormancy and are then told to stop emitting,
+ // we should have died while dormant. Remove ourselves immediately.
+ bool bRemoveInstantly = (m_iDormancyChangedAtFrame == gpGlobals->framecount);
+
+ int nCount = m_ParticleEffects.Count();
+ for ( int i = 0; i < nCount; ++i )
+ {
+ // for each effect...
+ ParticleEffectList_t &part = m_ParticleEffects[i];
+ // look through all the control points to see if any mention the given object
+ int cpCount = part.pControlPoints.Count();
+ for (int j = 0; j < cpCount ; ++j )
+ {
+ // if any control points respond to the given handle...
+ if (part.pControlPoints[j].hEntity == entHandle)
+ {
+ part.pParticleEffect->StopEmission( false, bRemoveInstantly );
+ part.pControlPoints.Remove( j );
+ break; // break out of the inner loop (to where it says BREAK TO HERE)
+ }
+ }
+ // BREAK TO HERE
+ }
+}
+
+//g_pParticleSystemMgr->FindParticleSystem( pParticleSystemName );
+
+//-----------------------------------------------------------------------------
+// Purpose: Stop all effects that were created using the given definition
+// name.
+//-----------------------------------------------------------------------------
+void CParticleProperty::StopParticlesNamed( const char *pszEffectName, bool bForceRemoveInstantly /* =false */ )
+{
+ CParticleSystemDefinition *pDef = g_pParticleSystemMgr->FindParticleSystem( pszEffectName );
+ AssertMsg1(pDef, "Could not find particle definition %s", pszEffectName );
+ if (!pDef)
+ return;
+
+
+ // If we return from dormancy and are then told to stop emitting,
+ // we should have died while dormant. Remove ourselves immediately.
+ bool bRemoveInstantly = (m_iDormancyChangedAtFrame == gpGlobals->framecount);
+ // force remove particles instantly if caller specified
+ bRemoveInstantly |= bForceRemoveInstantly;
+
+ int nCount = m_ParticleEffects.Count();
+ for ( int i = 0; i < nCount; ++i )
+ {
+ // for each effect...
+ CNewParticleEffect *pParticleEffect = m_ParticleEffects[i].pParticleEffect.GetObject();
+ if (pParticleEffect->m_pDef() == pDef)
+ {
+ pParticleEffect->StopEmission( false, bRemoveInstantly );
+ }
+ }
+}
+
+void CParticleProperty::StopParticlesWithNameAndAttachment( const char *pszEffectName, int iAttachmentPoint, bool bForceRemoveInstantly /* =false */ )
+{
+ CParticleSystemDefinition *pDef = g_pParticleSystemMgr->FindParticleSystem( pszEffectName );
+ AssertMsg1(pDef, "Could not find particle definition %s", pszEffectName );
+ if (!pDef)
+ return;
+
+
+ // If we return from dormancy and are then told to stop emitting,
+ // we should have died while dormant. Remove ourselves immediately.
+ bool bRemoveInstantly = (m_iDormancyChangedAtFrame == gpGlobals->framecount);
+ // force remove particles instantly if caller specified
+ bRemoveInstantly |= bForceRemoveInstantly;
+
+ int nCount = m_ParticleEffects.Count();
+ for ( int i = 0; i < nCount; ++i )
+ {
+ // for each effect...
+ ParticleEffectList_t *pParticleEffectList = &m_ParticleEffects[i];
+ CNewParticleEffect *pParticleEffect = pParticleEffectList->pParticleEffect.GetObject();
+ if (pParticleEffect->m_pDef() == pDef)
+ {
+ int nControlPointCount = pParticleEffectList->pControlPoints.Count();
+ for ( int j = 0; j < nControlPointCount; ++j )
+ {
+ if ( pParticleEffectList->pControlPoints[j].iAttachmentPoint == iAttachmentPoint )
+ {
+ pParticleEffect->StopEmission( false, bRemoveInstantly );
+ break;
+ }
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CParticleProperty::OnParticleSystemUpdated( CNewParticleEffect *pEffect, float flTimeDelta )
+{
+ int iIndex = FindEffect( pEffect );
+ Assert( iIndex != -1 );
+ if ( iIndex == -1 )
+ return;
+
+ // Enable FP exceptions here when FP_EXCEPTIONS_ENABLED is defined,
+ // to help track down bad math.
+ FPExceptionEnabler enableExceptions;
+
+ UpdateParticleEffect( &m_ParticleEffects[iIndex] );
+
+ /*
+ // Display the bounding box of the particle effect
+ Vector vecMins, vecMaxs;
+ pEffect->GetRenderBounds( vecMins, vecMaxs );
+ debugoverlay->AddBoxOverlay( pEffect->GetRenderOrigin(), vecMins, vecMaxs, QAngle( 0, 0, 0 ), 0, 255, 255, 0, 0 );
+ */
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CParticleProperty::OnParticleSystemDeleted( CNewParticleEffect *pEffect )
+{
+ int iIndex = FindEffect( pEffect );
+ if ( iIndex == -1 )
+ return;
+
+ m_ParticleEffects[iIndex].pParticleEffect.MarkDeleted();
+ m_ParticleEffects.Remove( iIndex );
+}
+
+#ifdef CLIENT_DLL
+//-----------------------------------------------------------------------------
+// Purpose: The entity we're attached to has change dormancy state on our client
+//-----------------------------------------------------------------------------
+void CParticleProperty::OwnerSetDormantTo( bool bDormant )
+{
+ m_iDormancyChangedAtFrame = gpGlobals->framecount;
+
+ int nCount = m_ParticleEffects.Count();
+ for ( int i = 0; i < nCount; i++ )
+ {
+ //m_ParticleEffects[i].pParticleEffect->SetShouldSimulate( !bDormant );
+ m_ParticleEffects[i].pParticleEffect->SetDormant( bDormant );
+ }
+}
+#endif
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+int CParticleProperty::FindEffect( CNewParticleEffect *pEffect )
+{
+ for ( int i = 0; i < m_ParticleEffects.Count(); i++ )
+ {
+ if ( m_ParticleEffects[i].pParticleEffect == pEffect )
+ return i;
+ }
+
+ return -1;
+}
+
+int CParticleProperty::FindEffect( const char *pEffectName, int nStart /*= 0*/ )
+{
+ for ( int i = nStart; i < m_ParticleEffects.Count(); i++ )
+ {
+ if ( !Q_stricmp( m_ParticleEffects[i].pParticleEffect->GetName(), pEffectName ) )
+ return i;
+ }
+
+ return -1;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CParticleProperty::UpdateParticleEffect( ParticleEffectList_t *pEffect, bool bInitializing, int iOnlyThisControlPoint )
+{
+ if ( iOnlyThisControlPoint != -1 )
+ {
+ UpdateControlPoint( pEffect, iOnlyThisControlPoint, bInitializing );
+ return;
+ }
+
+ // Loop through our control points and update them all
+ for ( int i = 0; i < pEffect->pControlPoints.Count(); i++ )
+ {
+ UpdateControlPoint( pEffect, i, bInitializing );
+ }
+}
+
+extern void FormatViewModelAttachment( Vector &vOrigin, bool bInverse );
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CParticleProperty::UpdateControlPoint( ParticleEffectList_t *pEffect, int iPoint, bool bInitializing )
+{
+ ParticleControlPoint_t *pPoint = &pEffect->pControlPoints[iPoint];
+
+ if ( !pPoint->hEntity.Get() )
+ {
+ if ( pPoint->iAttachType == PATTACH_WORLDORIGIN && bInitializing )
+ {
+ pEffect->pParticleEffect->SetControlPointOrientation( pPoint->iControlPoint, Vector(1,0,0), Vector(0,1,0), Vector(0,0,1) );
+ pEffect->pParticleEffect->SetControlPoint( pPoint->iControlPoint, pPoint->vecOriginOffset );
+ pEffect->pParticleEffect->SetSortOrigin( pPoint->vecOriginOffset );
+ }
+
+ pEffect->pParticleEffect->SetControlPointEntity( pPoint->iControlPoint, NULL );
+ return;
+ }
+
+ // Only update non-follow particles when we're initializing,
+ // unless we're parented to something, in which case we should always update
+ if ( !bInitializing && !pPoint->hEntity->GetMoveParent() && (pPoint->iAttachType == PATTACH_ABSORIGIN || pPoint->iAttachType == PATTACH_POINT ) )
+ return;
+
+ if ( pPoint->iAttachType == PATTACH_CUSTOMORIGIN )
+ return;
+
+ Vector vecOrigin, vecForward, vecRight, vecUp;
+
+ float flOffset = 0.0f;
+ bool bUsingHeadOrigin = false;
+
+#ifdef TF_CLIENT_DLL
+
+ CBaseEntity *pWearable = (CBaseEntity*) pPoint->hEntity.Get();
+ if ( pWearable && dynamic_cast<IHasAttributes*>( pWearable ) && !pWearable->IsPlayer() )
+ {
+ C_BaseAnimating *pAnimating = pPoint->hEntity->GetBaseAnimating();
+ if ( pAnimating )
+ {
+ int bUseHeadOrigin = 0;
+ CALL_ATTRIB_HOOK_INT_ON_OTHER( pPoint->hEntity.Get(), bUseHeadOrigin, particle_effect_use_head_origin );
+ if ( bUseHeadOrigin > 0 )
+ {
+ int iBone = Studio_BoneIndexByName( pAnimating->GetModelPtr(), "bip_head" );
+ if ( iBone >= 0 )
+ {
+ bUsingHeadOrigin = true;
+ const matrix3x4_t headBone = pAnimating->GetBone( iBone );
+ MatrixVectors( headBone, &vecForward, &vecRight, &vecUp );
+ MatrixPosition( headBone, vecOrigin );
+
+ CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( pPoint->hEntity.Get(), flOffset, particle_effect_vertical_offset );
+ }
+ }
+ }
+ }
+#endif
+
+ if ( !bUsingHeadOrigin )
+ {
+ switch ( pPoint->iAttachType )
+ {
+ case PATTACH_POINT:
+ case PATTACH_POINT_FOLLOW:
+ {
+ C_BaseAnimating *pAnimating = pPoint->hEntity->GetBaseAnimating();
+
+ Assert( pAnimating );
+ if ( pAnimating )
+ {
+ matrix3x4_t attachmentToWorld;
+
+ if ( !pAnimating->GetAttachment( pPoint->iAttachmentPoint, attachmentToWorld ) )
+ {
+ Warning( "Cannot update control point %d for effect '%s'.\n", pPoint->iAttachmentPoint, pEffect->pParticleEffect->GetEffectName() );
+ attachmentToWorld = pAnimating->RenderableToWorldTransform();
+ }
+
+ MatrixVectors( attachmentToWorld, &vecForward, &vecRight, &vecUp );
+ MatrixPosition( attachmentToWorld, vecOrigin );
+
+ if ( pEffect->pParticleEffect->m_pDef->IsViewModelEffect() )
+ {
+ FormatViewModelAttachment( vecOrigin, true );
+ }
+
+ }
+ }
+ break;
+
+ case PATTACH_ABSORIGIN:
+ case PATTACH_ABSORIGIN_FOLLOW:
+ default:
+ {
+ vecOrigin = pPoint->hEntity->GetAbsOrigin() + pPoint->vecOriginOffset;
+ pPoint->hEntity->GetVectors( &vecForward, &vecRight, &vecUp );
+ }
+ break;
+
+ case PATTACH_ROOTBONE_FOLLOW:
+ {
+ C_BaseAnimating *pAnimating = pPoint->hEntity->GetBaseAnimating();
+
+ Assert( pAnimating );
+ if ( pAnimating )
+ {
+ matrix3x4_t rootBone;
+ if ( pAnimating->GetRootBone( rootBone ) )
+ {
+ MatrixVectors( rootBone, &vecForward, &vecRight, &vecUp );
+ MatrixPosition( rootBone, vecOrigin );
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ Vector vecForcedOriginOffset( 0, 0, flOffset );
+ pEffect->pParticleEffect->SetControlPointOrientation( pPoint->iControlPoint, vecForward, vecRight, vecUp );
+ pEffect->pParticleEffect->SetControlPointEntity( pPoint->iControlPoint, pPoint->hEntity );
+ pEffect->pParticleEffect->SetControlPoint( pPoint->iControlPoint, vecOrigin + vecForcedOriginOffset );
+ pEffect->pParticleEffect->SetSortOrigin( vecOrigin + vecForcedOriginOffset);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Output all active effects
+//-----------------------------------------------------------------------------
+void CParticleProperty::DebugPrintEffects( void )
+{
+ int nCount = m_ParticleEffects.Count();
+ for ( int i = 0; i < nCount; ++i )
+ {
+ // for each effect...
+ CNewParticleEffect *pParticleEffect = m_ParticleEffects[i].pParticleEffect.GetObject();
+
+ if ( !pParticleEffect )
+ continue;
+
+ Msg( "(%d) EffectName \"%s\" Dormant? %s Emission Stopped? %s \n",
+ i,
+ pParticleEffect->GetEffectName(),
+ ( pParticleEffect->m_bDormant ) ? "yes" : "no",
+ ( pParticleEffect->m_bEmissionStopped ) ? "yes" : "no" );
+ }
+}
|