Updates to particle system for ember editor (#1001)

* Add enabled state for modifiers

* Add enabled state for interpolators

* Move AutoTrigger to effect not emitters

* Remove LineUniformProfile

* Set Enabled field true by default

* Don't render invisible emitters

* Remove unused member

* Document update method

* Add documentation

* Remove test now that LineUniformProfile was removed

* Fix unit tests
This commit is contained in:
Christopher Whitley
2025-07-25 00:52:05 -04:00
committed by GitHub
parent 96fe78c4a6
commit 2ea7e85398
28 changed files with 242 additions and 306 deletions
@@ -34,6 +34,8 @@ public class AgeModifier : Modifier
/// <inheritdoc/> /// <inheritdoc/>
public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator) public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator)
{ {
if (!Enabled) { return; }
while (iterator.HasNext) while (iterator.HasNext)
{ {
Particle* particle = iterator.Next(); Particle* particle = iterator.Next();
@@ -66,6 +66,8 @@ public class CircleContainerModifier : Modifier
/// <inheritdoc/> /// <inheritdoc/>
public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator) public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator)
{ {
if (!Enabled) { return; }
float radiusSq = Radius * Radius; float radiusSq = Radius * Radius;
while (iterator.HasNext) while (iterator.HasNext)
@@ -53,6 +53,8 @@ public sealed class RectangleContainerModifier : Modifier
/// <inheritdoc/> /// <inheritdoc/>
public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator) public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator)
{ {
if (!Enabled) { return; }
while (iterator.HasNext) while (iterator.HasNext)
{ {
Particle* particle = iterator.Next(); Particle* particle = iterator.Next();
@@ -32,6 +32,8 @@ public class RectangleLoopContainerModifier : Modifier
/// <inheritdoc/> /// <inheritdoc/>
public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator) public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator)
{ {
if (!Enabled) { return; }
while (iterator.HasNext) while (iterator.HasNext)
{ {
Particle* particle = iterator.Next(); Particle* particle = iterator.Next();
@@ -51,6 +51,8 @@ public class DragModifier : Modifier
/// <inheritdoc/> /// <inheritdoc/>
public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator) public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator)
{ {
if (!Enabled) { return; }
while (iterator.HasNext) while (iterator.HasNext)
{ {
Particle* particle = iterator.Next(); Particle* particle = iterator.Next();
@@ -29,6 +29,8 @@ public sealed class ColorInterpolator : Interpolator<Vector3>
/// <param name="particle">A pointer to the particle to update.</param> /// <param name="particle">A pointer to the particle to update.</param>
public override unsafe void Update(float amount, Particle* particle) public override unsafe void Update(float amount, Particle* particle)
{ {
if (!Enabled) { return; }
float h = StartValue.X + (EndValue.X - StartValue.X) * amount; float h = StartValue.X + (EndValue.X - StartValue.X) * amount;
float s = StartValue.Y + (EndValue.Y - StartValue.Y) * amount; float s = StartValue.Y + (EndValue.Y - StartValue.Y) * amount;
float l = StartValue.Z + (EndValue.Z - StartValue.Z) * amount; float l = StartValue.Z + (EndValue.Z - StartValue.Z) * amount;
@@ -23,6 +23,8 @@ public class HueInterpolator : Interpolator<float>
/// <param name="particle">A pointer to the particle to update.</param> /// <param name="particle">A pointer to the particle to update.</param>
public override unsafe void Update(float amount, Particle* particle) public override unsafe void Update(float amount, Particle* particle)
{ {
if (!Enabled) { return; }
float h = StartValue + (EndValue - StartValue) * amount; float h = StartValue + (EndValue - StartValue) * amount;
particle->Color[0] = h; particle->Color[0] = h;
} }
@@ -22,12 +22,22 @@ public abstract class Interpolator
/// </summary> /// </summary>
public string Name; public string Name;
/// <summary>
/// Indicates if this interpolator is enabled.
/// </summary>
/// <remarks>
/// This value determines if this interpolator is enabled. When an interpolator is disabled, the interpolator is
/// not applied to the modifier.
/// </remarks>
public bool Enabled;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Interpolator"/> class. /// Initializes a new instance of the <see cref="Interpolator"/> class.
/// </summary> /// </summary>
protected Interpolator() protected Interpolator()
{ {
Name = GetType().Name; Name = GetType().Name;
Enabled = true;
} }
/// <summary> /// <summary>
@@ -28,6 +28,8 @@ public class OpacityInterpolator : Interpolator<float>
/// <param name="particle">A pointer to the particle to update.</param> /// <param name="particle">A pointer to the particle to update.</param>
public override unsafe void Update(float amount, Particle* particle) public override unsafe void Update(float amount, Particle* particle)
{ {
if (!Enabled) { return; }
particle->Opacity = StartValue + (EndValue - StartValue) * amount; particle->Opacity = StartValue + (EndValue - StartValue) * amount;
} }
} }
@@ -23,6 +23,8 @@ public class RotationInterpolator : Interpolator<float>
/// <param name="particle">A pointer to the particle to update.</param> /// <param name="particle">A pointer to the particle to update.</param>
public override unsafe void Update(float amount, Particle* particle) public override unsafe void Update(float amount, Particle* particle)
{ {
if (!Enabled) { return; }
particle->Rotation = StartValue + (EndValue - StartValue) * amount; particle->Rotation = StartValue + (EndValue - StartValue) * amount;
} }
} }
@@ -24,6 +24,8 @@ public class ScaleInterpolator : Interpolator<Vector2>
/// <param name="particle">A pointer to the particle to update.</param> /// <param name="particle">A pointer to the particle to update.</param>
public override unsafe void Update(float amount, Particle* particle) public override unsafe void Update(float amount, Particle* particle)
{ {
if (!Enabled) { return; }
particle->Scale[0] = StartValue.X + (EndValue.X - StartValue.X) * amount; particle->Scale[0] = StartValue.X + (EndValue.X - StartValue.X) * amount;
particle->Scale[1] = StartValue.Y + (EndValue.Y - StartValue.Y) * amount; particle->Scale[1] = StartValue.Y + (EndValue.Y - StartValue.Y) * amount;
} }
@@ -24,6 +24,8 @@ public class VelocityInterpolator : Interpolator<Vector2>
/// <param name="particle">A pointer to the particle to update.</param> /// <param name="particle">A pointer to the particle to update.</param>
public override unsafe void Update(float amount, Particle* particle) public override unsafe void Update(float amount, Particle* particle)
{ {
if (!Enabled) { return; }
particle->Velocity[0] = StartValue.X + (EndValue.X - StartValue.X) * amount; particle->Velocity[0] = StartValue.X + (EndValue.X - StartValue.X) * amount;
particle->Velocity[1] = StartValue.Y + (EndValue.Y - StartValue.Y) * amount; particle->Velocity[1] = StartValue.Y + (EndValue.Y - StartValue.Y) * amount;
} }
@@ -43,6 +43,8 @@ public class LinearGravityModifier : Modifier
/// <inheritdoc/> /// <inheritdoc/>
public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator) public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator)
{ {
if (!Enabled) { return; }
Vector2 vector = Direction * (Strength * elapsedSeconds); Vector2 vector = Direction * (Strength * elapsedSeconds);
while (iterator.HasNext) while (iterator.HasNext)
@@ -17,8 +17,6 @@ public abstract class Modifier
{ {
private const float DEFAULT_MODIFIER_FREQUENCY = 60.0f; private const float DEFAULT_MODIFIER_FREQUENCY = 60.0f;
private int _particlesUpdatedThisCycle;
/// <summary> /// <summary>
/// Gets or sets the display name of this modifier. /// Gets or sets the display name of this modifier.
/// </summary> /// </summary>
@@ -44,6 +42,15 @@ public abstract class Modifier
/// </remarks> /// </remarks>
public float Frequency; public float Frequency;
/// <summary>
/// Indicates whether this modifier is enabled.
/// </summary>
/// <remarks>
/// This value determines if this modifier is enabled. When a modifier is disabled, the modifier is not applied
/// to the particles.
/// </remarks>
public bool Enabled;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Modifier"/> class. /// Initializes a new instance of the <see cref="Modifier"/> class.
/// </summary> /// </summary>
@@ -55,6 +62,7 @@ public abstract class Modifier
{ {
Name = GetType().Name; Name = GetType().Name;
Frequency = DEFAULT_MODIFIER_FREQUENCY; Frequency = DEFAULT_MODIFIER_FREQUENCY;
Enabled = true;
} }
/// <summary> /// <summary>
@@ -34,6 +34,8 @@ public sealed class OpacityFastFadeModifier : Modifier
/// <inheritdoc/> /// <inheritdoc/>
public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator) public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator)
{ {
if (!Enabled) { return; }
while (iterator.HasNext) while (iterator.HasNext)
{ {
Particle* particle = iterator.Next(); Particle* particle = iterator.Next();
@@ -34,6 +34,8 @@ public class RotationModifier : Modifier
/// <inheritdoc/> /// <inheritdoc/>
public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator) public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator)
{ {
if (!Enabled) { return; }
float rotationRateDelta = RotationRate * elapsedSeconds; float rotationRateDelta = RotationRate * elapsedSeconds;
while (iterator.HasNext) while (iterator.HasNext)
@@ -60,6 +60,8 @@ public class VelocityColorModifier : Modifier
/// <inheritdoc/> /// <inheritdoc/>
public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator) public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator)
{ {
if (!Enabled) { return; }
float velocityThreshold2 = VelocityThreshold * VelocityThreshold; float velocityThreshold2 = VelocityThreshold * VelocityThreshold;
while (iterator.HasNext) while (iterator.HasNext)
@@ -40,6 +40,8 @@ public class VelocityModifier : Modifier
/// <inheritdoc /> /// <inheritdoc />
public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator) public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator)
{ {
if (!Enabled) { return; }
float velocityThreshold2 = VelocityThreshold * VelocityThreshold; float velocityThreshold2 = VelocityThreshold * VelocityThreshold;
while (iterator.HasNext) while (iterator.HasNext)
@@ -54,6 +54,8 @@ public unsafe class VortexModifier : Modifier
/// <inheritdoc/> /// <inheritdoc/>
public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator) public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator)
{ {
if (!Enabled) { return; }
while (iterator.HasNext) while (iterator.HasNext)
{ {
Particle* particle = iterator.Next(); Particle* particle = iterator.Next();
@@ -23,6 +23,8 @@ namespace MonoGame.Extended.Particles;
/// </remarks> /// </remarks>
public class ParticleEffect : IDisposable public class ParticleEffect : IDisposable
{ {
private float _nextAutoTrigger;
/// <summary> /// <summary>
/// Gets or sets the name of this effect, used for identification and debugging. /// Gets or sets the name of this effect, used for identification and debugging.
/// </summary> /// </summary>
@@ -55,6 +57,24 @@ public class ParticleEffect : IDisposable
/// </remarks> /// </remarks>
public Vector2 Scale; public Vector2 Scale;
/// <summary>
/// A value indicating whether this particle effect should automatically trigger its particle emitters.
/// </summary>
/// <remarks>
/// When <see langword="true"/>, all emitters of this <see cref="ParticleEffect"/> will be triggered at the same
/// based on the <see cref="AutoTriggerFrequency"/>. When <see langword="false"/>, users will need to manually call
/// the <see cref="Trigger()"/> method to trigger emitters.
/// </remarks>
public bool AutoTrigger;
/// <summary>
/// The frequency, in seconds, at which this <see cref="ParticleEffect"/> automatically triggers emitters.
/// </summary>
/// <remarks>
/// If <see cref="AutoTrigger"/> is <see langword="false"/>, this value is ignored.
/// </remarks>
public float AutoTriggerFrequency;
/// <summary> /// <summary>
/// Gets or sets the collection of emitters that compose this effect. /// Gets or sets the collection of emitters that compose this effect.
/// </summary> /// </summary>
@@ -97,6 +117,8 @@ public class ParticleEffect : IDisposable
Rotation = 0.0f; Rotation = 0.0f;
Scale = Vector2.One; Scale = Vector2.One;
Emitters = new List<ParticleEmitter>(); Emitters = new List<ParticleEmitter>();
AutoTrigger = true;
AutoTriggerFrequency = 1.0f;
} }
/// <summary> /// <summary>
@@ -128,6 +150,13 @@ public class ParticleEffect : IDisposable
} }
} }
/// <summary>
/// Updates the state of all emitters in this effect.
/// </summary>
/// <param name="gameTime">The timing values for the current update cycle.</param>
/// <exception cref="ObjectDisposedException">
/// Thrown if this method is called after the effect has been disposed.
/// </exception>
public void Update(GameTime gameTime) public void Update(GameTime gameTime)
{ {
Update((float)gameTime.ElapsedGameTime.TotalSeconds); Update((float)gameTime.ElapsedGameTime.TotalSeconds);
@@ -137,10 +166,6 @@ public class ParticleEffect : IDisposable
/// Updates the state of all emitters in this effect. /// Updates the state of all emitters in this effect.
/// </summary> /// </summary>
/// <param name="elapsedSeconds">The elapsed time, in seconds, since the last update.</param> /// <param name="elapsedSeconds">The elapsed time, in seconds, since the last update.</param>
/// <remarks>
/// This method propagates the update call to each emitter in the effect, passing along
/// the elapsed time and the current position of the effect.
/// </remarks>
/// <exception cref="ObjectDisposedException"> /// <exception cref="ObjectDisposedException">
/// Thrown if this method is called after the effect has been disposed. /// Thrown if this method is called after the effect has been disposed.
/// </exception> /// </exception>
@@ -148,6 +173,17 @@ public class ParticleEffect : IDisposable
{ {
ObjectDisposedException.ThrowIf(IsDisposed, typeof(ParticleBuffer)); ObjectDisposedException.ThrowIf(IsDisposed, typeof(ParticleBuffer));
if (AutoTrigger)
{
_nextAutoTrigger -= elapsedSeconds;
if (_nextAutoTrigger <= 0)
{
Trigger();
_nextAutoTrigger += AutoTriggerFrequency;
}
}
for (int i = 0; i < Emitters.Count; i++) for (int i = 0; i < Emitters.Count; i++)
{ {
Emitters[i].Update(elapsedSeconds, Position); Emitters[i].Update(elapsedSeconds, Position);
@@ -34,12 +34,12 @@ public sealed class ParticleEffectReader : IDisposable
public bool IsDisposed { get; private set; } public bool IsDisposed { get; private set; }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ParticleEffectReader"/> class that reads from a file. /// Initializes a new instance of the <see cref="ParticleEffectReader"/> class that reads from a file.
/// </summary> /// </summary>
/// <param name="fileName">The file path to read the XMl from.</param> /// <param name="fileName">The file path to read the XMl from.</param>
/// <param name="content">The <see cref="ContentManager"/> to use for loading textures.</param> /// <param name="content">The <see cref="ContentManager"/> to use for loading textures.</param>
/// <exception cref="ArgumentNullException"><paramref name="content"/> is <see langword="null"/></exception> /// <exception cref="ArgumentNullException"><paramref name="content"/> is <see langword="null"/></exception>
/// <exception cref="ArgumentException"><paramref name="fileName"/> is <see langword="null"/> or empty.</exception> /// <exception cref="ArgumentException"><paramref name="fileName"/> is <see langword="null"/> or empty.</exception>
public ParticleEffectReader(string fileName, ContentManager content) public ParticleEffectReader(string fileName, ContentManager content)
{ {
ArgumentNullException.ThrowIfNull(content); ArgumentNullException.ThrowIfNull(content);
@@ -97,8 +97,11 @@ public sealed class ParticleEffectReader : IDisposable
string name = _reader.GetAttribute(nameof(ParticleEffect.Name)) ?? "Unnamed"; string name = _reader.GetAttribute(nameof(ParticleEffect.Name)) ?? "Unnamed";
ParticleEffect effect = new ParticleEffect(name); ParticleEffect effect = new ParticleEffect(name);
effect.Position = _reader.GetAttributeVector2(nameof(ParticleEffect.Position));
effect.Rotation = _reader.GetAttributeFloat(nameof(ParticleEffect.Rotation)); effect.Rotation = _reader.GetAttributeFloat(nameof(ParticleEffect.Rotation));
effect.Scale = _reader.GetAttributeVector2(nameof(ParticleEffect.Scale)); effect.Scale = _reader.GetAttributeVector2(nameof(ParticleEffect.Scale));
effect.AutoTrigger = _reader.GetAttributeBool(nameof(ParticleEffect.AutoTrigger));
effect.AutoTriggerFrequency = _reader.GetAttributeFloat(nameof(ParticleEffect.AutoTriggerFrequency));
if (_reader.ReadToDescendant(nameof(ParticleEffect.Emitters))) if (_reader.ReadToDescendant(nameof(ParticleEffect.Emitters)))
{ {
@@ -124,8 +127,6 @@ public sealed class ParticleEffectReader : IDisposable
emitter.LifeSpan = _reader.GetAttributeFloat(nameof(ParticleEmitter.LifeSpan)); emitter.LifeSpan = _reader.GetAttributeFloat(nameof(ParticleEmitter.LifeSpan));
emitter.Offset = _reader.GetAttributeVector2(nameof(ParticleEmitter.Offset)); emitter.Offset = _reader.GetAttributeVector2(nameof(ParticleEmitter.Offset));
emitter.LayerDepth = _reader.GetAttributeFloat(nameof(ParticleEmitter.LayerDepth)); emitter.LayerDepth = _reader.GetAttributeFloat(nameof(ParticleEmitter.LayerDepth));
emitter.AutoTrigger = _reader.GetAttributeBool(nameof(ParticleEmitter.AutoTrigger));
emitter.AutoTriggerFrequency = _reader.GetAttributeFloat(nameof(ParticleEmitter.AutoTriggerFrequency));
emitter.ReclaimFrequency = _reader.GetAttributeFloat(nameof(ParticleEmitter.ReclaimFrequency)); emitter.ReclaimFrequency = _reader.GetAttributeFloat(nameof(ParticleEmitter.ReclaimFrequency));
string strategy = _reader.GetAttribute(nameof(ParticleEmitter.ModifierExecutionStrategy)); string strategy = _reader.GetAttribute(nameof(ParticleEmitter.ModifierExecutionStrategy));
@@ -400,13 +401,6 @@ public sealed class ParticleEffectReader : IDisposable
lineProfile.Length = reader.GetAttributeFloat(nameof(LineProfile.Length)); lineProfile.Length = reader.GetAttributeFloat(nameof(LineProfile.Length));
return lineProfile; return lineProfile;
case nameof(LineUniformProfile):
LineUniformProfile lineUniformProfile = new LineUniformProfile();
lineUniformProfile.Axis = reader.GetAttributeVector2(nameof(LineUniformProfile.Axis));
lineUniformProfile.Length = reader.GetAttributeFloat(nameof(LineUniformProfile.Length));
lineUniformProfile.PerpendicularDirection = reader.GetAttributeVector2(nameof(LineUniformProfile.PerpendicularDirection));
return lineUniformProfile;
case nameof(PointProfile): case nameof(PointProfile):
return Profile.Point(); return Profile.Point();
@@ -75,6 +75,8 @@ public class ParticleEffectWriter : IDisposable
_writer.WriteAttributeVector2(nameof(ParticleEffect.Position), effect.Position); _writer.WriteAttributeVector2(nameof(ParticleEffect.Position), effect.Position);
_writer.WriteAttributeFloat(nameof(ParticleEffect.Rotation), effect.Rotation); _writer.WriteAttributeFloat(nameof(ParticleEffect.Rotation), effect.Rotation);
_writer.WriteAttributeVector2(nameof(ParticleEffect.Scale), effect.Scale); _writer.WriteAttributeVector2(nameof(ParticleEffect.Scale), effect.Scale);
_writer.WriteAttributeBool(nameof(ParticleEffect.AutoTrigger), effect.AutoTrigger);
_writer.WriteAttributeFloat(nameof(ParticleEffect.AutoTriggerFrequency), effect.AutoTriggerFrequency);
if (effect.Emitters.Count > 0) if (effect.Emitters.Count > 0)
{ {
@@ -100,8 +102,6 @@ public class ParticleEffectWriter : IDisposable
_writer.WriteAttributeFloat(nameof(ParticleEmitter.LifeSpan), emitter.LifeSpan); _writer.WriteAttributeFloat(nameof(ParticleEmitter.LifeSpan), emitter.LifeSpan);
_writer.WriteAttributeVector2(nameof(ParticleEmitter.Offset), emitter.Offset); _writer.WriteAttributeVector2(nameof(ParticleEmitter.Offset), emitter.Offset);
_writer.WriteAttributeFloat(nameof(ParticleEmitter.LayerDepth), emitter.LayerDepth); _writer.WriteAttributeFloat(nameof(ParticleEmitter.LayerDepth), emitter.LayerDepth);
_writer.WriteAttributeBool(nameof(ParticleEmitter.AutoTrigger), emitter.AutoTrigger);
_writer.WriteAttributeFloat(nameof(ParticleEmitter.AutoTriggerFrequency), emitter.AutoTriggerFrequency);
_writer.WriteAttributeFloat(nameof(ParticleEmitter.ReclaimFrequency), emitter.ReclaimFrequency); _writer.WriteAttributeFloat(nameof(ParticleEmitter.ReclaimFrequency), emitter.ReclaimFrequency);
_writer.WriteAttributeInt(nameof(ParticleEmitter.Capacity), emitter.Capacity); _writer.WriteAttributeInt(nameof(ParticleEmitter.Capacity), emitter.Capacity);
_writer.WriteAttributeString(nameof(ParticleEmitter.ModifierExecutionStrategy), emitter.ModifierExecutionStrategy.ToString()); _writer.WriteAttributeString(nameof(ParticleEmitter.ModifierExecutionStrategy), emitter.ModifierExecutionStrategy.ToString());
@@ -261,13 +261,6 @@ public class ParticleEffectWriter : IDisposable
_writer.WriteAttributeFloat(nameof(LineProfile.Length), lineProfile.Length); _writer.WriteAttributeFloat(nameof(LineProfile.Length), lineProfile.Length);
break; break;
case LineUniformProfile lineUniformProfile:
_writer.WriteAttributeString(nameof(Type), nameof(LineUniformProfile));
_writer.WriteAttributeVector2(nameof(LineUniformProfile.Axis), lineUniformProfile.Axis);
_writer.WriteAttributeFloat(nameof(LineUniformProfile.Length), lineUniformProfile.Length);
_writer.WriteAttributeVector2(nameof(LineUniformProfile.PerpendicularDirection), lineUniformProfile.PerpendicularDirection);
break;
case PointProfile: case PointProfile:
_writer.WriteAttributeString(nameof(Type), nameof(PointProfile)); _writer.WriteAttributeString(nameof(Type), nameof(PointProfile));
break; break;
@@ -26,7 +26,6 @@ public sealed unsafe class ParticleEmitter : IDisposable
{ {
private float _totalSeconds; private float _totalSeconds;
private float _secondsSinceLastReclaim; private float _secondsSinceLastReclaim;
private float _nextAutoTrigger;
/// <summary> /// <summary>
/// Gets or sets the buffer that stores and manages the particles for this emitter. /// Gets or sets the buffer that stores and manages the particles for this emitter.
@@ -88,23 +87,6 @@ public sealed unsafe class ParticleEmitter : IDisposable
/// </remarks> /// </remarks>
public float LayerDepth; public float LayerDepth;
/// <summary>
/// Gets or sets a value indicating whether this emitter should automatically trigger particle emissions.
/// </summary>
/// <remarks>
/// When set to <see langword="true"/>, the emitter will periodically emit particles based on the
/// <see cref="AutoTriggerFrequency"/> property, without requiring explicit calls to <see cref="Trigger(Vector2, float)"/>.
/// </remarks>
public bool AutoTrigger;
/// <summary>
/// Gets or sets the frequency, in seconds, at which this emitter automatically triggers particle emissions.
/// </summary>
/// <remarks>
/// This property only has an effect when <see cref="AutoTrigger"/> is set to <see langword="true"/>.
/// </remarks>
public float AutoTriggerFrequency;
/// <summary> /// <summary>
/// Gets or sets the frequency, in times per second, at which expired particles are reclaimed. /// Gets or sets the frequency, in times per second, at which expired particles are reclaimed.
/// </summary> /// </summary>
@@ -162,6 +144,11 @@ public sealed unsafe class ParticleEmitter : IDisposable
/// </remarks> /// </remarks>
public ParticleRenderingOrder RenderingOrder; public ParticleRenderingOrder RenderingOrder;
/// <summary>
/// Indicates whether the particles emitted by this emitter are visible.
/// </summary>
public bool Visible;
/// <summary> /// <summary>
/// Gets a value indicating whether this <see cref="ParticleEmitter"/> has been disposed. /// Gets a value indicating whether this <see cref="ParticleEmitter"/> has been disposed.
/// </summary> /// </summary>
@@ -197,8 +184,7 @@ public sealed unsafe class ParticleEmitter : IDisposable
ReclaimFrequency = 60.0f; ReclaimFrequency = 60.0f;
Offset = Vector2.Zero; Offset = Vector2.Zero;
LayerDepth = 0.0f; LayerDepth = 0.0f;
AutoTrigger = true; Visible = true;
AutoTriggerFrequency = 1.0f;
} }
/// <summary> /// <summary>
@@ -256,17 +242,6 @@ public sealed unsafe class ParticleEmitter : IDisposable
_totalSeconds += elapsedSeconds; _totalSeconds += elapsedSeconds;
_secondsSinceLastReclaim += elapsedSeconds; _secondsSinceLastReclaim += elapsedSeconds;
if (AutoTrigger)
{
_nextAutoTrigger -= elapsedSeconds;
if (_nextAutoTrigger <= 0)
{
Trigger(position, LayerDepth);
_nextAutoTrigger = AutoTriggerFrequency;
}
}
if (Buffer.Count == 0) if (Buffer.Count == 0)
{ {
return; return;
@@ -1,58 +0,0 @@
// Copyright (c) Craftwork Games. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
using Microsoft.Xna.Framework;
namespace MonoGame.Extended.Particles.Profiles;
/// <summary>
/// A profile that distributes particles uniformly along a line segment with a fixed heading direction.
/// </summary>
/// <remarks>
/// The <see cref="LineUniformProfile"/> positions particles randomly along a line segment centered at the emitter
/// position and defined by an axis direction and length. Unlike other profiles, this profile uses a fixed heading
/// direction for all particles, perpendicular to the line.
/// </remarks>
public sealed class LineUniformProfile : Profile
{
/// <summary>
/// The direction vector of the line axis.
/// </summary>
public Vector2 Axis;
/// <summary>
/// The length of the line segment.
/// </summary>
public float Length;
/// <summary>
/// The fixed heading direction for all particles spawned from this profile.
/// </summary>
public Vector2 PerpendicularDirection;
/// <summary>
/// Computes the offset and heading for a new particle.
/// </summary>
/// <param name="offset">A pointer to the Vector2 where the offset from the emitter position will be stored.</param>
/// <param name="heading">A pointer to the Vector2 where the unit direction vector will be stored.</param>
public override unsafe void GetOffsetAndHeading(Vector2* offset, Vector2* heading)
{
// 1. Spawn the particle at a random point on the line axis
float value = FastRandom.Shared.NextSingle(Length * -0.5f, Length * 0.5f);
offset->X = Axis.X * value;
offset->Y = Axis.Y * value;
// 2. Set the heading to the perpendicular direction
*heading = PerpendicularDirection;
}
/// <summary>
/// Sets the <see cref="PerpendicularDirection"/> property to a normalized version of the specified vector.
/// </summary>
/// <param name="direction">The direction vector to normalize and use as the perpendicular direction.</param>
public void SetPerpendicularDirection(Vector2 direction)
{
PerpendicularDirection = Vector2.Normalize(direction);
}
}
@@ -43,18 +43,6 @@ public abstract class Profile
return new LineProfile { Axis = axis, Length = length }; return new LineProfile { Axis = axis, Length = length };
} }
/// <summary>
/// Creates a <see cref="LineUniformProfile"/> that emits particles uniformly along a line segment with a fixed heading.
/// </summary>
/// <param name="axis">The direction vector of the line axis.</param>
/// <param name="length">The length fo the line segment.</param>
/// <param name="perpendicularDirection">The fixed heading direction for all particles spawned from the profile.</param>
/// <returns></returns>
public static Profile LineUniform(Vector2 axis, float length, Vector2 perpendicularDirection)
{
return new LineUniformProfile { Axis = axis, Length = length, PerpendicularDirection = perpendicularDirection };
}
/// <summary> /// <summary>
/// Creates a <see cref="RingProfile"/> that emits particles from the perimeter of a circle. /// Creates a <see cref="RingProfile"/> that emits particles from the perimeter of a circle.
/// </summary> /// </summary>
@@ -1,5 +1,4 @@
using System; using System;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using MonoGame.Extended.Graphics; using MonoGame.Extended.Graphics;
@@ -7,8 +6,18 @@ using MonoGame.Extended.Particles.Data;
namespace MonoGame.Extended.Particles; namespace MonoGame.Extended.Particles;
/// <summary>
/// Provides extension methods for <see cref="SpriteBatch"/> to draw particle effects and emitters.
/// </summary>
public static class SpriteBatchExtensions public static class SpriteBatchExtensions
{ {
/// <summary>
/// Draws a particle effect by rendering all of its active emitters.
/// </summary>
/// <param name="spriteBatch">The <see cref="SpriteBatch"/> used for drawing.</param>
/// <param name="effect">The <see cref="ParticleEffect"/> to draw.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="effect"/> is null.</exception>
/// <exception cref="ObjectDisposedException">Thrown when <paramref name="effect"/> is disposed.</exception>
public static void Draw(this SpriteBatch spriteBatch, ParticleEffect effect) public static void Draw(this SpriteBatch spriteBatch, ParticleEffect effect)
{ {
ArgumentNullException.ThrowIfNull(effect); ArgumentNullException.ThrowIfNull(effect);
@@ -20,6 +29,13 @@ public static class SpriteBatchExtensions
} }
} }
/// <summary>
/// Draws a particle emitter by rendering all of its active particles.
/// </summary>
/// <param name="spriteBatch">The <see cref="SpriteBatch"/> used for drawing.</param>
/// <param name="emitter">The <see cref="ParticleEmitter"/> to draw.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="emitter"/> is null.</exception>
/// <exception cref="ObjectDisposedException">Thrown when <paramref name="emitter"/> is disposed.</exception>
public static void Draw(this SpriteBatch spriteBatch, ParticleEmitter emitter) public static void Draw(this SpriteBatch spriteBatch, ParticleEmitter emitter)
{ {
ArgumentNullException.ThrowIfNull(emitter); ArgumentNullException.ThrowIfNull(emitter);
@@ -43,6 +59,12 @@ public static class SpriteBatchExtensions
return; return;
} }
// Early exit if the emitter is not visible
if (!emitter.Visible)
{
return;
}
Texture2DRegion region = emitter.TextureRegion; Texture2DRegion region = emitter.TextureRegion;
Texture2D texture = region.Texture; Texture2D texture = region.Texture;
Rectangle sourceRect = region.Bounds; Rectangle sourceRect = region.Bounds;
@@ -61,7 +61,7 @@ public class ParticleEffectReaderTests
string xml = string xml =
""" """
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="EmptyEffect" Position="0,0" Rotation="0" Scale="1,1" /> <ParticleEffect Name="EmptyEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1" />
"""; """;
ParticleEffect effect = ReadParticleEffectFromXml(xml); ParticleEffect effect = ReadParticleEffectFromXml(xml);
@@ -71,6 +71,8 @@ public class ParticleEffectReaderTests
Assert.Equal(0.0f, effect.Rotation); Assert.Equal(0.0f, effect.Rotation);
Assert.Equal(Vector2.One, effect.Scale); Assert.Equal(Vector2.One, effect.Scale);
Assert.Empty(effect.Emitters); Assert.Empty(effect.Emitters);
Assert.True(effect.AutoTrigger);
Assert.Equal(effect.AutoTriggerFrequency, 1.0f);
} }
[Fact] [Fact]
@@ -79,9 +81,9 @@ public class ParticleEffectReaderTests
string xml = string xml =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="EmptyModifiers" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="EmptyModifiers" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -111,9 +113,9 @@ public class ParticleEffectReaderTests
string xml = string xml =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -147,9 +149,9 @@ public class ParticleEffectReaderTests
string xml = string xml =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -181,9 +183,9 @@ public class ParticleEffectReaderTests
string xml = string xml =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -215,9 +217,9 @@ public class ParticleEffectReaderTests
string xml = string xml =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -249,9 +251,9 @@ public class ParticleEffectReaderTests
string xml = string xml =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -283,9 +285,9 @@ public class ParticleEffectReaderTests
string xml = string xml =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -311,49 +313,15 @@ public class ParticleEffectReaderTests
Assert.Equal(1.0f, profile.Length); Assert.Equal(1.0f, profile.Length);
} }
[Fact]
public void ReadParticleEffect_LineUniformProfile_ReadsExpected()
{
string xml =
$"""
<?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1">
<Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" />
<Color Kind="Constant" Constant="1,1,1" />
<Opacity Kind="Random" RandomMin="0" RandomMax="1" />
<Scale Kind="Random" RandomMin="0.5,0.5" RandomMax="1,1" />
<Rotation Kind="Random" RandomMin="{-MathF.PI}" RandomMax="{MathF.PI}" />
<Mass Kind="Constant" Constant="1" />
</Parameters>
<Profile Type="LineUniformProfile" Axis="1,1" Length="1" PerpendicularDirection="1,1" />
</ParticleEmitter>
</Emitters>
</ParticleEffect>
""";
ParticleEffect effect = ReadParticleEffectFromXml(xml);
Assert.Single(effect.Emitters);
ParticleEmitter emitter = effect.Emitters[0];
LineUniformProfile profile = Assert.IsType<LineUniformProfile>(emitter.Profile);
Assert.Equal(Vector2.One, profile.Axis);
Assert.Equal(1.0f, profile.Length);
}
[Fact] [Fact]
public void ReadParticleEffect_PointProfile_ReadsExpected() public void ReadParticleEffect_PointProfile_ReadsExpected()
{ {
string xml = string xml =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -383,9 +351,9 @@ public class ParticleEffectReaderTests
string xml = string xml =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -417,9 +385,9 @@ public class ParticleEffectReaderTests
string xml = string xml =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -451,9 +419,9 @@ public class ParticleEffectReaderTests
string xml = string xml =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -490,9 +458,9 @@ public class ParticleEffectReaderTests
string xml = string xml =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -532,9 +500,9 @@ public class ParticleEffectReaderTests
string xml = string xml =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -573,9 +541,9 @@ public class ParticleEffectReaderTests
string xml = string xml =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -614,9 +582,9 @@ public class ParticleEffectReaderTests
string xml = string xml =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -653,9 +621,9 @@ public class ParticleEffectReaderTests
string xml = string xml =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -695,9 +663,9 @@ public class ParticleEffectReaderTests
string xml = string xml =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -736,9 +704,9 @@ public class ParticleEffectReaderTests
string xml = string xml =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -776,9 +744,9 @@ public class ParticleEffectReaderTests
string xml = string xml =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -818,9 +786,9 @@ public class ParticleEffectReaderTests
string xml = string xml =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -858,9 +826,9 @@ public class ParticleEffectReaderTests
string xml = string xml =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -900,9 +868,9 @@ public class ParticleEffectReaderTests
string xml = string xml =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -946,9 +914,9 @@ public class ParticleEffectReaderTests
string xml = string xml =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -992,9 +960,9 @@ public class ParticleEffectReaderTests
string xml = string xml =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -1038,9 +1006,9 @@ public class ParticleEffectReaderTests
string xml = string xml =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -1084,9 +1052,9 @@ public class ParticleEffectReaderTests
string xml = string xml =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -1130,9 +1098,9 @@ public class ParticleEffectReaderTests
string xml = string xml =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -31,7 +31,7 @@ public class ParticleEffectWriterTests
string expected = string expected =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="EmptyEffect" Position="0,0" Rotation="0" Scale="1,1" /> <ParticleEffect Name="EmptyEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1" />
"""; """;
AssertParticleEffect(effect, expected); AssertParticleEffect(effect, expected);
@@ -48,9 +48,9 @@ public class ParticleEffectWriterTests
string expected = string expected =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="EmptyModifiers" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="EmptyModifiers" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -82,9 +82,9 @@ public class ParticleEffectWriterTests
string expected = string expected =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -119,9 +119,9 @@ public class ParticleEffectWriterTests
string expected = string expected =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -153,9 +153,9 @@ public class ParticleEffectWriterTests
string expected = string expected =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -187,9 +187,9 @@ public class ParticleEffectWriterTests
string expected = string expected =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -221,9 +221,9 @@ public class ParticleEffectWriterTests
string expected = string expected =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -255,9 +255,9 @@ public class ParticleEffectWriterTests
string expected = string expected =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -276,40 +276,6 @@ public class ParticleEffectWriterTests
AssertParticleEffect(effect, expected); AssertParticleEffect(effect, expected);
} }
[Fact]
public void WriteParticleEffect_LineUniformProfile_WritesExpected()
{
ParticleEffect effect = new ParticleEffect("TestEffect");
ParticleEmitter emitter = new ParticleEmitter(1);
emitter.Name = "TestEmitter";
emitter.Profile = Profile.LineUniform(Vector2.One, 1.0f, Vector2.One);
effect.Emitters.Add(emitter);
string expected =
$"""
<?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1">
<Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" />
<Color Kind="Constant" Constant="1,1,1" />
<Opacity Kind="Random" RandomMin="0" RandomMax="1" />
<Scale Kind="Random" RandomMin="0.5,0.5" RandomMax="1,1" />
<Rotation Kind="Random" RandomMin="{-MathF.PI}" RandomMax="{MathF.PI}" />
<Mass Kind="Constant" Constant="1" />
</Parameters>
<Profile Type="LineUniformProfile" Axis="1,1" Length="1" PerpendicularDirection="1,1" />
</ParticleEmitter>
</Emitters>
</ParticleEffect>
""";
AssertParticleEffect(effect, expected);
}
[Fact] [Fact]
public void WriteParticleEffect_PointProfile_WritesExpected() public void WriteParticleEffect_PointProfile_WritesExpected()
{ {
@@ -323,9 +289,9 @@ public class ParticleEffectWriterTests
string expected = string expected =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -357,9 +323,9 @@ public class ParticleEffectWriterTests
string expected = string expected =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -391,9 +357,9 @@ public class ParticleEffectWriterTests
string expected = string expected =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -427,9 +393,9 @@ public class ParticleEffectWriterTests
string expected = string expected =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -466,9 +432,9 @@ public class ParticleEffectWriterTests
string expected = string expected =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -505,9 +471,9 @@ public class ParticleEffectWriterTests
string expected = string expected =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -544,9 +510,9 @@ public class ParticleEffectWriterTests
string expected = string expected =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -583,9 +549,9 @@ public class ParticleEffectWriterTests
string expected = string expected =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -622,9 +588,9 @@ public class ParticleEffectWriterTests
string expected = string expected =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -661,9 +627,9 @@ public class ParticleEffectWriterTests
string expected = string expected =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -700,9 +666,9 @@ public class ParticleEffectWriterTests
string expected = string expected =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -739,9 +705,9 @@ public class ParticleEffectWriterTests
string expected = string expected =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -778,9 +744,9 @@ public class ParticleEffectWriterTests
string expected = string expected =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -817,9 +783,9 @@ public class ParticleEffectWriterTests
string expected = string expected =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -858,9 +824,9 @@ public class ParticleEffectWriterTests
string expected = string expected =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -903,9 +869,9 @@ public class ParticleEffectWriterTests
string expected = string expected =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -948,9 +914,9 @@ public class ParticleEffectWriterTests
string expected = string expected =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -993,9 +959,9 @@ public class ParticleEffectWriterTests
string expected = string expected =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -1038,9 +1004,9 @@ public class ParticleEffectWriterTests
string expected = string expected =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />
@@ -1083,9 +1049,9 @@ public class ParticleEffectWriterTests
string expected = string expected =
$""" $"""
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1"> <ParticleEffect Name="TestEffect" Position="0,0" Rotation="0" Scale="1,1" AutoTrigger="True" AutoTriggerFrequency="1">
<Emitters> <Emitters>
<ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" AutoTrigger="True" AutoTriggerFrequency="1" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack"> <ParticleEmitter Name="TestEmitter" LifeSpan="1" Offset="0,0" LayerDepth="0" ReclaimFrequency="60" Capacity="1" ModifierExecutionStrategy="Serial" RenderingOrder="FrontToBack">
<Parameters> <Parameters>
<Quantity Kind="Random" RandomMin="5" RandomMax="100" /> <Quantity Kind="Random" RandomMin="5" RandomMax="100" />
<Speed Kind="Random" RandomMin="50" RandomMax="100" /> <Speed Kind="Random" RandomMin="50" RandomMax="100" />