/** Look for dead particles and move from the end of the list to the dead location, compacting in the process */ void FNiagaraSimulation::KillParticles() { SCOPE_CYCLE_COUNTER(STAT_NiagaraKill); int32 OrigNumParticles = Data.GetNumInstances(); int32 CurNumParticles = OrigNumParticles; int32 ParticleIndex = OrigNumParticles - 1; if (bGenerateDeathEvents) { DeathEventGenerator.BeginTrackingDeaths(); } const FVector4* ParticleRelativeTimes = Data.GetVariableData(FNiagaraVariableInfo(BUILTIN_VAR_PARTICLEAGE, ENiagaraDataType::Vector)); if (ParticleRelativeTimes) { while (ParticleIndex >= 0) { if (ParticleRelativeTimes[ParticleIndex].X > 1.0f) { if (bGenerateDeathEvents) { DeathEventGenerator.OnDeath(ParticleIndex); } check(CurNumParticles > ParticleIndex); // Particle is dead, move one from the end here. MoveParticleToIndex(--CurNumParticles, ParticleIndex); } --ParticleIndex; } } Data.SetNumInstances(CurNumParticles); if (bGenerateDeathEvents) { DeathEventGenerator.EndTrackingDeaths(); } // check if the emitter has officially died if (GetTickState() == NTS_Dieing && CurNumParticles == 0) { SetTickState(NTS_Dead); } }
void FNiagaraSimulation::PreTick() { UNiagaraEmitterProperties* PinnedProps = Props.Get(); if (!PinnedProps || !bIsEnabled || TickState == NTS_Suspended || TickState == NTS_Dead) return; check(Data.GetNumVariables() > 0); check(PinnedProps->SpawnScriptProps.Script); check(PinnedProps->UpdateScriptProps.Script); // Iterate over looking for dead particles and move from the end of the list to the dead location, compacting in the process { SCOPE_CYCLE_COUNTER(STAT_NiagaraKill); int32 OrigNumParticles = Data.GetNumInstances(); int32 CurNumParticles = OrigNumParticles; int32 ParticleIndex = OrigNumParticles-1; if (bGenerateDeathEvents) { DeathEventGenerator.BeginTrackingDeaths(); } const FVector4* ParticleRelativeTimes = Data.GetVariableData(FNiagaraVariableInfo(FName(TEXT("Age")), ENiagaraDataType::Vector)); if (ParticleRelativeTimes) { while (ParticleIndex >= 0) { if (ParticleRelativeTimes[ParticleIndex].X > 1.0f) { if (bGenerateDeathEvents) { DeathEventGenerator.OnDeath(ParticleIndex); } check(CurNumParticles > ParticleIndex); // Particle is dead, move one from the end here. MoveParticleToIndex(--CurNumParticles, ParticleIndex); DebuggerHook_OnDeath(this, ParticleIndex, CurNumParticles); } --ParticleIndex; } } Data.SetNumInstances(CurNumParticles); if (bGenerateDeathEvents) { DeathEventGenerator.EndTrackingDeaths(); } // check if the emitter has officially died if (GetTickState() == NTS_Dieing && CurNumParticles == 0) { SetTickState(NTS_Dead); } } //Swap all data set buffers before doing the main tick on any simulation. for (TPair<FNiagaraDataSetID, FNiagaraDataSet*> SetPair : DataSetMap) { SetPair.Value->Tick(); } }
void FNiagaraSimulation::Tick(float DeltaSeconds) { SCOPE_CYCLE_COUNTER(STAT_NiagaraTick); if (!bIsEnabled || TickState==NTS_Suspended || TickState==NTS_Dead) return; SimpleTimer TickTime; check(Data.GetNumAttributes() > 0); check(Props->SpawnScript); check(Props->UpdateScript); // Cache the ComponentToWorld transform. // CachedComponentToWorld = Component.GetComponentToWorld(); Data.SwapBuffers(); Data.SetNumParticles(Data.GetPrevNumParticles()); int32 OrigNumParticles = Data.GetNumParticles(); int32 NumToSpawn = 0; // Figure out how many we will spawn. NumToSpawn = CalcNumToSpawn(DeltaSeconds); int32 MaxNewParticles = OrigNumParticles + NumToSpawn; Data.Allocate(MaxNewParticles); Age += DeltaSeconds; Constants.SetOrAdd(TEXT("Emitter Age"), FVector4(Age, Age, Age, Age)); Constants.SetOrAdd(TEXT("Delta Time"), FVector4(DeltaSeconds, DeltaSeconds, DeltaSeconds, DeltaSeconds)); // Simulate particles forward by DeltaSeconds. if (TickState==NTS_Running || TickState==NTS_Dieing) { SCOPE_CYCLE_COUNTER(STAT_NiagaraSimulate); RunVMScript(Props->UpdateScript, EUnusedAttributeBehaviour::Copy); } //Init new particles with the spawn script. if (TickState==NTS_Running) { SCOPE_CYCLE_COUNTER(STAT_NiagaraSpawn); Data.SetNumParticles(MaxNewParticles); //For now, zero any unused attributes here. But as this is really uninitialized data we should maybe make this a more serious error. RunVMScript(Props->SpawnScript, EUnusedAttributeBehaviour::Zero, OrigNumParticles, NumToSpawn); } // Iterate over looking for dead particles and move from the end of the list to the dead location, compacting in the process { SCOPE_CYCLE_COUNTER(STAT_NiagaraKill); int32 CurNumParticles = OrigNumParticles = Data.GetNumParticles(); int32 ParticleIndex = 0; const FVector4* ParticleRelativeTimes = Data.GetAttributeData(FNiagaraVariableInfo(FName(TEXT("Age")), ENiagaraDataType::Vector)); if (ParticleRelativeTimes) { while (ParticleIndex < OrigNumParticles) { if (ParticleRelativeTimes[ParticleIndex].X > 1.0f) { // Particle is dead, move one from the end here. MoveParticleToIndex(--CurNumParticles, ParticleIndex); } ParticleIndex++; } } Data.SetNumParticles(CurNumParticles); // check if the emitter has officially died if (GetTickState() == NTS_Dieing && CurNumParticles == 0) { SetTickState(NTS_Dead); } } CPUTimeMS = TickTime.GetElapsedMilliseconds(); DECLARE_DWORD_COUNTER_STAT(TEXT("NumParticles"), STAT_NiagaraNumParticles, STATGROUP_Niagara); INC_DWORD_STAT_BY(STAT_NiagaraNumParticles, Data.GetNumParticles()); }