using System; using System.Drawing; using Amphora; using Azimuth; using Blacklight.Core; using Blacklight.Core.Drawables; using Prism; using UnitTestSharp; namespace Konis.Blacklight.UnitTests { public class ParticleSpriteWriterTests : TestFixture { private static SpriteSource Source() { return new SpriteSource(null, new Point(4, 6), new Size(16, 8)); } private static StandardEmitterDef Def( Variation speed = default(Variation), double size = 1, Variation spin = default(Variation), Gradient tint = null, double rate = 1) { return new StandardEmitterDef { Capacity = 10, Rate = rate, Lifetime = 2, Speed = speed, Size = size, AngularVelocity = spin, TintOverLife = new GradientDef { Gradient = tint ?? Gradient.Constant(Colors.White) }, }; } private static StandardEmitter Born(StandardEmitterDef def, double secondsAfterBirth = 0) { var emitter = new StandardEmitter(def, new ScriptedGenerator()); emitter.Update(1f); emitter.Update((float)secondsAfterBirth); return emitter; } private static bool Near(double expected, double actual) { return Math.Abs(expected - actual) < 1e-5; } public class WriteTests : TestFixture { public void AnEmptyEmitter_WritesNothingAndReturnsZero() { var emitter = new StandardEmitter(Def(), new ScriptedGenerator()); var entries = new SpriteBatch.EntrySet(); CheckEqual(0, ParticleSpriteWriter.Write(emitter, ViewProjection.TopDown, Source(), entries)); } public void AddsTheTintAndTransformColumnsToASetThatLacksThem() { var entries = new SpriteBatch.EntrySet(); ParticleSpriteWriter.Write(Born(Def()), ViewProjection.TopDown, Source(), entries); CheckEqual( SpriteBatch.Varying.TintColor | SpriteBatch.Varying.Transform, entries.Columns); } public void LeavesAnotherColumnTheSetHadAlone() { var entries = new SpriteBatch.EntrySet(capacity: 4, columns: SpriteBatch.Varying.Additiveness); ParticleSpriteWriter.Write(Born(Def()), ViewProjection.TopDown, Source(), entries); CheckEqual( SpriteBatch.Varying.Additiveness | SpriteBatch.Varying.TintColor | SpriteBatch.Varying.Transform, entries.Columns); } public void ReturnsTheNumberOfLiveParticles() { var emitter = new StandardEmitter(Def(rate: 8), new ScriptedGenerator()); emitter.Update(0.5f); var entries = new SpriteBatch.EntrySet(); CheckEqual(4, ParticleSpriteWriter.Write(emitter, ViewProjection.TopDown, Source(), entries)); } public void GrowsTheSetToHoldEveryParticle() { var emitter = new StandardEmitter(Def(rate: 8), new ScriptedGenerator()); emitter.Update(1f); var entries = new SpriteBatch.EntrySet(); ParticleSpriteWriter.Write(emitter, ViewProjection.TopDown, Source(), entries); CheckTrue(entries.Capacity >= 8); CheckEqual(entries.Capacity, entries.Transforms.Length); CheckEqual(entries.Capacity, entries.TintColors.Length); } public void LeavesEntriesPastTheCountAlone() { var entries = new SpriteBatch.EntrySet(capacity: 4, columns: SpriteBatch.Varying.Transform); entries.Transforms[3] = new AffineMatrix(0, new Vector(7, 8), 2); ParticleSpriteWriter.Write(Born(Def()), ViewProjection.TopDown, Source(), entries); CheckEqual(7.0, entries.Transforms[3].Translation.X.Value); } public void CopiesTheSourceRegionAndCentersTheDestinationOnIt() { var entries = new SpriteBatch.EntrySet(); ParticleSpriteWriter.Write(Born(Def()), ViewProjection.TopDown, Source(), entries); SpriteBatch.Entry entry = entries.Entries[0]; CheckEqual(new Point(4, 6), entry.SourceOrigin); CheckEqual(new Size(16, 8), entry.SourceSize); CheckEqual(-8.0, entry.Destination.min.X.Value); CheckEqual(-4.0, entry.Destination.min.Y.Value); CheckEqual(8.0, entry.Destination.max.X.Value); CheckEqual(4.0, entry.Destination.max.Y.Value); } public void PositionsAParticleAtTheEmittersPositionPlusItsOwnProjected() { StandardEmitter emitter = Born(Def(speed: 4), secondsAfterBirth: 0.5); emitter.Position = new Vector3(10, 20, 0); var entries = new SpriteBatch.EntrySet(); ParticleSpriteWriter.Write(emitter, ViewProjection.TopDown, Source(), entries); CheckTrue(Near(12, entries.Transforms[0].Translation.X.Value)); CheckTrue(Near(20, entries.Transforms[0].Translation.Y.Value)); } public void UnderATopDownView_IgnoresAltitude() { StandardEmitter emitter = Born(Def()); emitter.Position = new Vector3(0, 0, 5); var entries = new SpriteBatch.EntrySet(); ParticleSpriteWriter.Write(emitter, ViewProjection.TopDown, Source(), entries); CheckTrue(Near(0, entries.Transforms[0].Translation.Y.Value)); } public void UnderAnAngledView_RaisesAParticleOnTheScreenWithAltitude() { StandardEmitter emitter = Born(Def()); emitter.Position = new Vector3(0, 0, 5); var entries = new SpriteBatch.EntrySet(); ParticleSpriteWriter.Write(emitter, ViewProjection.Dimetric2To1, Source(), entries); CheckTrue(entries.Transforms[0].Translation.Y.Value > 1); } public void ScalesByTheSizeOverTheSourceWidth() { var entries = new SpriteBatch.EntrySet(); ParticleSpriteWriter.Write(Born(Def(size: 8)), ViewProjection.TopDown, Source(), entries); CheckTrue(Near(0.5, entries.Transforms[0].M00.Value)); CheckTrue(Near(0.5, entries.Transforms[0].M11.Value)); } public void TurnsByTheParticlesRotation() { StandardEmitter emitter = Born(Def(size: 16, spin: 0.5), secondsAfterBirth: 0.5); var entries = new SpriteBatch.EntrySet(); ParticleSpriteWriter.Write(emitter, ViewProjection.TopDown, Source(), entries); CheckTrue(Near(0, entries.Transforms[0].M00.Value)); CheckTrue(Near(1, entries.Transforms[0].M10.Value)); } public void TintsByTheParticlesColor() { var entries = new SpriteBatch.EntrySet(); ParticleSpriteWriter.Write( Born(Def(tint: Gradient.Constant(Colors.Red))), ViewProjection.TopDown, Source(), entries); CheckEqual(Colors.Red.ToArgb(), entries.TintColors[0].ToArgb()); } public void WritesEveryParticleInTheOrderTheEmitterKeepsThem() { var emitter = new StandardEmitter(Def(speed: 4), new ScriptedGenerator()); emitter.Update(2f); var entries = new SpriteBatch.EntrySet(); int count = ParticleSpriteWriter.Write(emitter, ViewProjection.TopDown, Source(), entries); CheckEqual(2, count); CheckTrue(Near(emitter.Store.Items[0].PositionX, entries.Transforms[0].Translation.X.Value)); CheckTrue(Near(emitter.Store.Items[1].PositionX, entries.Transforms[1].Translation.X.Value)); } } } }