Click or drag to resize
DigitalRuneHow To: Clamp a Particle Parameter

This topic shows how you can limit particle parameter values at runtime, e.g. to limit the alpha value of particles.

This topic contains the following sections:

Creating a ClampValueEffector

You can use a custom ParticleEffector to change particle parameters. See How To: Create a Particle Effector.

Here is a code snippet of a particle effector that clamps a value between a min and max value:

C#
using System;
using DigitalRune.Mathematics;
using DigitalRune.Particles;

namespace Samples.Particles
{
  public class ClampValueEffector<T> : ParticleEffector where T : IComparable<T>
  {
    private IParticleParameter<T> _parameter;

    [ParticleParameter(ParticleParameterUsage.InOut)]
    public string Parameter { get; set; }

    public T Min { get; set; }
    public T Max { get; set; }

    protected override ParticleEffector CreateInstanceCore()
    {
      return new ClampValueEffector<T>();
    }

    protected override void CloneCore(ParticleEffector source)
    {
      base.CloneCore(source);

      var sourceTyped = (ClampValueEffector<T>)source;
      Parameter = sourceTyped.Parameter;
    }

    protected override void OnRequeryParameters()
    {
      _parameter = ParticleSystem.Parameters.Get<T>(Parameter);
    }

    protected override void OnUninitialize()
    {
      _parameter = null;
    }

    protected override void OnBeginUpdate(TimeSpan deltaTime)
    {
      if (_parameter == null)
        return;

      T[] values = _parameter.Values;
      if (values == null)
      {
        // Value is a uniform parameter.
        _parameter.DefaultValue = MathHelper.Clamp(_parameter.DefaultValue, Min, Max);
      }
    }

    protected override void OnUpdateParticles(TimeSpan deltaTime, int startIndex, int count)
    {
      if (_parameter == null)
        return;

      T[] values = _parameter.Values;
      if (values == null)
      {
        // Value is a uniform parameter. Uniform parameters are handled in OnBeginUpdate().
        return;
      }

      // Value is a varying parameter.
      for (int i = startIndex; i < startIndex + count; i++)
        values[i] = MathHelper.Clamp(values[i], Min, Max);
    }
  }
}
Adding ClampValueEffector to a ParticleSystem

You need to add the new ClampValueEffecto to the particle system, for example:

C#
_particleSystem.Effectors.Add(new ClampValueEffector<float>
{
  Parameter = ParticleParameterNames.Alpha,
  Min = 0.2f,
  Max = 0.8f,
});
Clamping using a standard FuncEffector

Alternatively, you can use the FuncEffectorT, TResult:

C#
particleSystem.Effectors.Add(new FuncEffector<float, float>
{
  InputParameter = "Alpha",
  OutputParameter = "Alpha",
  Func = x => MathHelper.Clamp(x, 0.2f, 0.8f),
});