TomlDataReader, documentation updates, move ParticleSystem to Voile.Systems.Particles.
This commit is contained in:
@@ -1,10 +1,9 @@
|
||||
using System.ComponentModel;
|
||||
using System.Numerics;
|
||||
using Tommy;
|
||||
using Voile.Resources;
|
||||
using Voile.Resources.DataReaders;
|
||||
using Voile.Utils;
|
||||
|
||||
namespace Voile.Systems;
|
||||
namespace Voile.Systems.Particles;
|
||||
|
||||
public struct Particle
|
||||
{
|
||||
@@ -53,6 +52,9 @@ public class ParticleEmitterSettingsResource : Resource
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads <see cref="ParticleEmitterSettingsResource"/> from a provided TOML data file.
|
||||
/// </summary>
|
||||
public class ParticleEmitterSettingsResourceLoader : ResourceLoader<ParticleEmitterSettingsResource>
|
||||
{
|
||||
public override IEnumerable<string> SupportedExtensions => new string[] {
|
||||
@@ -63,45 +65,57 @@ public class ParticleEmitterSettingsResourceLoader : ResourceLoader<ParticleEmit
|
||||
{
|
||||
// TODO: this is ugly, better to make some sort of wrapper API for TOML files.
|
||||
var settings = new ParticleEmitterSettings();
|
||||
// Parse into a node
|
||||
using (StreamReader reader = File.OpenText(path))
|
||||
|
||||
using (var reader = new TomlDataReader("ParticleEmitterSettings"))
|
||||
{
|
||||
// Parse the table
|
||||
TomlTable table = TOML.Parse(reader);
|
||||
|
||||
if (!table.HasKey("ParticleEmitterSettings"))
|
||||
{
|
||||
Console.WriteLine("Particle emitter settings doesnt have a header!");
|
||||
}
|
||||
|
||||
if (table["ParticleEmitterSettings"]["MaxParticles"] is TomlInteger maxParticles)
|
||||
{
|
||||
settings.MaxParticles = (int)maxParticles.Value;
|
||||
}
|
||||
|
||||
if (table["ParticleEmitterSettings"]["EmitRadius"] is TomlInteger emitRadius)
|
||||
{
|
||||
settings.EmitRadius = (int)emitRadius.Value;
|
||||
}
|
||||
|
||||
if (table["ParticleEmitterSettings"]["LifeTime"] is TomlFloat lifetime)
|
||||
{
|
||||
settings.LifeTime = (float)lifetime.Value;
|
||||
}
|
||||
reader.Read(File.Open(path, FileMode.Open));
|
||||
|
||||
settings.MaxParticles = reader.GetInt("MaxParticles");
|
||||
settings.EmitRadius = reader.GetInt("EmitRadius");
|
||||
settings.LifeTime = reader.GetFloat("LifeTime", 1.0f);
|
||||
settings.Explosiveness = reader.GetFloat("Explosiveness");
|
||||
settings.Direction = reader.GetVector2("Direction", Vector2.Zero);
|
||||
settings.LinearVelocity = reader.GetFloat("LinearVelocity", 980f);
|
||||
settings.AngularVelocity = reader.GetFloat("AngularVelocity");
|
||||
settings.AngularVelocityRandom = reader.GetFloat("AngularVelocityRandom", 1.0f);
|
||||
settings.LinearVelocityRandom = reader.GetFloat("LinearVelocityRandom", 1.0f);
|
||||
settings.Gravity = reader.GetVector2("Gravity", Vector2.UnitY * 980f);
|
||||
settings.ScaleBegin = reader.GetFloat("ScaleBegin");
|
||||
settings.ScaleEnd = reader.GetFloat("ScaleEnd");
|
||||
settings.ColorBegin = reader.GetColor("ColorBegin", Color.White);
|
||||
settings.ColorEnd = reader.GetColor("ColorEnd", Color.Black);
|
||||
settings.Damping = reader.GetFloat("Damping", 1.0f);
|
||||
}
|
||||
|
||||
return new ParticleEmitterSettingsResource(path, settings);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Emits and simulates particles from a provided particle segment.
|
||||
/// </summary>
|
||||
public class ParticleEmitter : IUpdatableSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// A segment of particles this emitter simulates.
|
||||
/// </summary>
|
||||
public ReadOnlySpan<Particle> Particles => _particles.AsSpan();
|
||||
/// <summary>
|
||||
/// Origin position in the world of this emitter.
|
||||
/// </summary>
|
||||
public Vector2 OriginPosition => _originPosition;
|
||||
/// <summary>
|
||||
/// <see cref="ParticleEmitterSettings"/> for this emitter.
|
||||
/// </summary>
|
||||
public ParticleEmitterSettings Settings => _settingsResource.Value.Settings;
|
||||
public int ParticleArrayOffset => _particles.Offset;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new <see cref="ParticleEmitter"/>.
|
||||
/// </summary>
|
||||
/// <param name="originPosition">World origin position.</param>
|
||||
/// <param name="settingsResource">Emitter settings resource.</param>
|
||||
/// <param name="particles">Particle segment that this emitter will simulate.</param>
|
||||
public ParticleEmitter(Vector2 originPosition, ResourceRef<ParticleEmitterSettingsResource> settingsResource, ArraySegment<Particle> particles)
|
||||
{
|
||||
_originPosition = originPosition;
|
||||
@@ -115,13 +129,12 @@ public class ParticleEmitter : IUpdatableSystem
|
||||
_random = new LehmerRandom();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restart this emitter.
|
||||
/// </summary>
|
||||
/// <param name="particles">New particle segment.</param>
|
||||
public void Restart(ArraySegment<Particle> particles)
|
||||
{
|
||||
// foreach (var particle in _particles)
|
||||
// {
|
||||
// particle.LifeTimeRemaining = 0.0f;
|
||||
// }
|
||||
|
||||
for (int i = 0; i < _particles.Count; i++)
|
||||
{
|
||||
var particle = _particles[i];
|
||||
@@ -134,6 +147,10 @@ public class ParticleEmitter : IUpdatableSystem
|
||||
_particleIndex = _maxParticles - 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates this emitter's simulation.
|
||||
/// </summary>
|
||||
/// <param name="deltaTime"></param>
|
||||
public void Update(double deltaTime)
|
||||
{
|
||||
var rate = (int)MathUtils.Lerp(1, _maxParticles, Settings.Explosiveness);
|
||||
@@ -146,13 +163,6 @@ public class ParticleEmitter : IUpdatableSystem
|
||||
for (int i = 0; i < _maxParticles; i++)
|
||||
{
|
||||
var particle = _particles[i];
|
||||
// if (!particle.Alive) continue;
|
||||
|
||||
// if (particle.LifeTimeRemaining <= 0.0f)
|
||||
// {
|
||||
// particle.Alive = false;
|
||||
// continue;
|
||||
// }
|
||||
|
||||
particle.LifeTimeRemaining = Math.Clamp(particle.LifeTimeRemaining - (float)deltaTime, 0.0f, particle.LifeTime);
|
||||
|
||||
@@ -215,6 +225,9 @@ public class ParticleEmitter : IUpdatableSystem
|
||||
private ResourceRef<ParticleEmitterSettingsResource> _settingsResource;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// CPU based particle simulator.
|
||||
/// </summary>
|
||||
public class ParticleSystem : IUpdatableSystem, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
@@ -222,14 +235,26 @@ public class ParticleSystem : IUpdatableSystem, IDisposable
|
||||
/// </summary>
|
||||
public int ParticleLimit { get; set; } = 8192;
|
||||
|
||||
/// <summary>
|
||||
/// List of particle emitters created for this ParticleSystem.
|
||||
/// </summary>
|
||||
public IReadOnlyList<ParticleEmitter> Emitters => _emitters;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new <see cref="ParticleSystem"/>.
|
||||
/// </summary>
|
||||
public ParticleSystem()
|
||||
{
|
||||
_particleIndex = ParticleLimit - 1;
|
||||
_particles = new Particle[ParticleLimit];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an emitter from a <see cref="ParticleEmitterSettingsResource"/>.
|
||||
/// </summary>
|
||||
/// <param name="originPosition"></param>
|
||||
/// <param name="settingsResource"></param>
|
||||
/// <returns></returns>
|
||||
public int CreateEmitter(Vector2 originPosition, ResourceRef<ParticleEmitterSettingsResource> settingsResource)
|
||||
{
|
||||
var settings = settingsResource.Value.Settings;
|
||||
@@ -242,11 +267,6 @@ public class ParticleSystem : IUpdatableSystem, IDisposable
|
||||
|
||||
var particles = new ArraySegment<Particle>(_particles, _emitterSliceOffset, settings.MaxParticles);
|
||||
|
||||
// foreach (var particle in particles)
|
||||
// {
|
||||
// particle.LifeTime = settings.LifeTime;
|
||||
// }
|
||||
|
||||
for (int i = 0; i < particles.Count; i++)
|
||||
{
|
||||
var particle = particles[i];
|
||||
@@ -261,6 +281,11 @@ public class ParticleSystem : IUpdatableSystem, IDisposable
|
||||
return _emitters.Count - 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restarts an emitter.
|
||||
/// </summary>
|
||||
/// <param name="id">Id of an emitter to restart.</param>
|
||||
/// <exception cref="ArgumentException"></exception>
|
||||
public void RestartEmitter(int id)
|
||||
{
|
||||
if (id > _emitters.Count - 1)
|
||||
@@ -274,6 +299,10 @@ public class ParticleSystem : IUpdatableSystem, IDisposable
|
||||
emitter.Restart(particles);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates this particle simulation. It is recommended to use a fixed timestep for the particle simulation for performance reasons.
|
||||
/// </summary>
|
||||
/// <param name="deltaTime"></param>
|
||||
public void Update(double deltaTime)
|
||||
{
|
||||
foreach (var emitter in _emitters)
|
||||
|
||||
Reference in New Issue
Block a user