// Copyright (c) Craftwork Games. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
using System;
using Microsoft.Xna.Framework;
using MonoGame.Extended.Particles.Data;
namespace MonoGame.Extended.Particles.Modifiers;
///
/// A modifier that changes particle colors based on their velocity.
///
///
/// The adjusts particle colors dynamically according to their
/// movement speed. Particles can transition smoothly between two defined colors:
///
/// - A color for stationary or slow-moving particles ()
/// - A color for fast-moving particles ()
///
///
/// The color values are represented in HSL (Hue, Saturation, Lightness) format as a Vector3.
///
public class VelocityColorModifier : Modifier
{
///
/// Gets or sets the color for particles that are stationary or moving slowly.
///
///
/// This color is applied to particles with zero velocity and serves as the starting
/// point for color interpolation. The Vector3 components represent HSL values
/// (Hue, Saturation, Lightness).
///
public Vector3 StationaryColor;
///
/// Gets or sets the color for particles that have reached or exceeded the velocity threshold.
///
///
/// This color is applied to fast-moving particles and serves as the end point
/// for color interpolation. The Vector3 components represent HSL values
/// (Hue, Saturation, Lightness).
///
public Vector3 VelocityColor;
///
/// Gets or sets the velocity magnitude at which particles fully transition to the velocity color.
///
///
/// This value defines the speed threshold that determines when a particle should
/// display the full . Particles moving slower than this
/// threshold will display a color interpolated between and
/// based on their speed relative to this threshold.
///
public float VelocityThreshold;
///
/// Updates all particles by changing their colors based on their current velocity.
///
///
protected internal override unsafe void Update(float elapsedSeconds, ParticleIterator iterator, int particleCount)
{
if (!Enabled) { return; }
float velocityThreshold2 = VelocityThreshold * VelocityThreshold;
for (int i = 0; i < particleCount && iterator.HasNext; i++)
{
Particle* particle = iterator.Next();
float velocitySquared = particle->Velocity[0] * particle->Velocity[0] +
particle->Velocity[1] * particle->Velocity[1];
if (velocitySquared >= velocityThreshold2)
{
particle->Color[0] = VelocityColor.X;
particle->Color[1] = VelocityColor.Y;
particle->Color[2] = VelocityColor.Z;
}
else
{
Vector3 deltaColor = VelocityColor - StationaryColor;
float t = MathF.Sqrt(velocitySquared) / VelocityThreshold;
float h = deltaColor.X * t + StationaryColor.X;
float s = deltaColor.Y * t + StationaryColor.Y;
float l = deltaColor.Z * t + StationaryColor.Z;
particle->Color[0] = h;
particle->Color[1] = s;
particle->Color[2] = l;
}
}
}
}