ParticleEffectsManager.cs
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;
using Sandbox;
[Title( "Particle Effects Manager" )]
[Category( "Particle" )]
[Description(
"This component let's you manage the TimeScale , the pause and restart of every particle effect component present in the childrens of this component gameobject so it is easier to preview the whole system" )]
public sealed class ParticleEffectsManager : Component, Component.ExecuteInEditor
{
[Property] List<ParticleEffect> ParticleEffects { get; set; }
[Property] List<ParticleEmitter> ParticleEmitters { get; set; }
[Property, Group( "Parameters" ), Range( -1f, 1f, 0.1f )]
float TimeScale { get; set; } = 1f;
[JsonIgnore] public bool IsPaused { get; set; }
[JsonIgnore] public bool IsRestart { get; set; }
[JsonIgnore]
public float LongestDuration
{
get
{
var duration = 0f;
foreach ( var emitter in ParticleEmitters )
{
if ( emitter.Duration + emitter.Delay > duration )
{
duration = emitter.Duration + emitter.Delay;
}
}
return duration;
}
}
[Property, Group( "Actions" )] private bool Emit { get; set; }
[JsonIgnore, Range( 0f, 1f, 0.001f )] public float PlayBack { get; set; }
[JsonIgnore] public bool IsPlayBack { get; set; }
[Property, Range( 0, 10, 0.001f )] public float DelayEffect { get; set; }
public int ParticleCount
{
get
{
int count = 0;
foreach ( var particleEffect in ParticleEffects )
{
count += particleEffect.ParticleCount;
}
return count;
}
}
public float PlaybackTime
{
get
{
float playbackTime = 0;
foreach ( var emitter in ParticleEmitters )
{
if ( emitter.IsValid() && emitter.time > playbackTime )
{
playbackTime = emitter.time;
}
}
return playbackTime;
}
}
protected override void OnEnabled()
{
ParticleEffects = GameObject.GetComponentsInChildren<ParticleEffect>().ToList();
ParticleEmitters = GameObject.GetComponentsInChildren<ParticleEmitter>().ToList();
if ( Scene.IsEditor ) return;
foreach ( var particleEmitter in ParticleEmitters )
{
particleEmitter.Delay += DelayEffect;
}
}
protected override void OnUpdate()
{
if ( !Scene.IsEditor ) return;
if ( Emit ) EmitParticles();
if ( IsRestart ) Restart();
if ( IsPlayBack )
{
foreach ( var particleEffect in ParticleEffects )
{
PlayBacking( particleEffect );
}
}
else
{
foreach ( var particleEffect in ParticleEffects )
{
TimeScaling( particleEffect );
}
}
}
private void EmitParticles()
{
Emit = false;
foreach ( var effect in ParticleEffects )
{
effect.Emit( 0, 0 );
}
}
private void TimeScaling( ParticleEffect particleEffect )
{
particleEffect.TimeScale = TimeScale;
var particleEmitter = particleEffect.Components.Get<ParticleEmitter>();
if ( TimeScale < 0 && particleEmitter.time <= 0 && !IsPaused )
{
var timing = particleEmitter.Duration - 0.01f;
SetParticulesTiming( particleEffect, timing );
particleEmitter.time = timing;
}
else
{
particleEffect.Paused = IsPaused;
}
}
private void PlayBacking( ParticleEffect particleEffect )
{
particleEffect.TimeScale = 0;
var particleEmitter = particleEffect.Components.Get<ParticleEmitter>();
var remappedTiming = PlayBack.Remap( 0, 1f, 0, particleEmitter.Duration + particleEmitter.Delay );
particleEmitter.time = remappedTiming;
SetParticulesTiming( particleEffect, remappedTiming );
}
private void Restart()
{
IsPaused = false;
IsRestart = false;
foreach ( var particleEffect in ParticleEffects )
{
particleEffect.Clear();
particleEffect.ResetEmitters();
}
}
private void SetParticulesTiming( ParticleEffect particleEffect, float timing )
{
var particleEmitter = particleEffect.Components.Get<ParticleEmitter>();
particleEmitter.time = timing;
foreach ( var particule in particleEffect.Particles )
{
particule.Age = timing;
}
}
}