1	use specs::prelude::*;
2	use super::{Rltk, ParticleLifetime, Position, Renderable};
3	use rltk::{RGB};
4	
5	pub struct ParticleSpawnSystem {}
6	
7	impl<'a> System<'a> for ParticleSpawnSystem {
8	    #[allow(clippy::type_complexity)]
9	    type SystemData = ( 
10	                        Entities<'a>,
11	                        WriteStorage<'a, Position>,
12	                        WriteStorage<'a, Renderable>,
13	                        WriteStorage<'a, ParticleLifetime>,
14	                        WriteExpect<'a, ParticleBuilder>
15	                      );
16	
17	    fn run(&mut self, data : Self::SystemData) {
18	        let (entities, mut positions, mut renderables, mut particles, mut particle_builder) = data;
19	        for new_particle in particle_builder.requests.iter() {
20	            let p = entities.create();
21	            positions.insert(p, Position{ x: new_particle.x, y: new_particle.y }).expect("Unable to inser position");
22	            renderables.insert(p, Renderable{ fg: new_particle.fg, bg: new_particle.bg, glyph: new_particle.glyph, render_order: 0 }).expect("Unable to insert renderable");
23	            particles.insert(p, ParticleLifetime{ lifetime_ms: new_particle.lifetime }).expect("Unable to insert lifetime");
24	        }
25	
26	        particle_builder.requests.clear();
27	    }
28	}
29	
30	struct ParticleRequest {
31	    x: i32,
32	    y: i32,
33	    fg: RGB,
34	    bg: RGB,
35	    glyph: rltk::FontCharType,
36	    lifetime: f32
37	}
38	
39	pub struct ParticleBuilder {
40	    requests : Vec<ParticleRequest>
41	}
42	
43	impl ParticleBuilder {
44	    #[allow(clippy::new_without_default)]
45	    pub fn new() -> ParticleBuilder {
46	        ParticleBuilder{ requests : Vec::new() }
47	    }
48	
49	    pub fn request(&mut self, x:i32, y:i32, fg: RGB, bg:RGB, glyph: rltk::FontCharType, lifetime: f32) {
50	        self.requests.push(
51	            ParticleRequest{
52	                x, y, fg, bg, glyph, lifetime
53	            }
54	        );
55	    }
56	}
57	
58	pub fn cull_dead_particles(ecs : &mut World, ctx : &Rltk) {
59	    let mut dead_particles : Vec<Entity> = Vec::new();
60	    {
61	        // Age out particles
62	        let mut particles = ecs.write_storage::<ParticleLifetime>();
63	        let entities = ecs.entities();
64	        for (entity, mut particle) in (&entities, &mut particles).join() {
65	            particle.lifetime_ms -= ctx.frame_time_ms;
66	            if particle.lifetime_ms < 0.0 {
67	                dead_particles.push(entity);
68	            }
69	        }                    
70	    }
71	    for dead in dead_particles.iter() {
72	        ecs.delete_entity(*dead).expect("Particle will not die");
73	    } 
74	}