1use std::marker::PhantomData;
2
3pub trait ParticleSystem {
5 type ParticleType: Particle;
7
8 type EmitterType: ParticleEmitter<ParticleType = Self::ParticleType>;
10
11 fn iter_particles(&self) -> impl Iterator<Item = &Self::ParticleType>;
13
14 fn iter_particles_mut(&mut self) -> impl Iterator<Item = &mut Self::ParticleType>;
16
17 fn iter_emitters(&self) -> impl Iterator<Item = &Self::EmitterType>;
19
20 fn iter_emitters_mut(&mut self) -> impl Iterator<Item = &mut Self::EmitterType>;
22
23 fn add_particle(&mut self, particle: Self::ParticleType);
25
26 fn add_emitter(&mut self, emitter: Self::EmitterType);
28
29 fn update_particles(&mut self, dt: f64) {
31 for particle in self.iter_particles_mut() {
32 particle.update(dt);
33 }
34 }
35
36 fn update_emitters(&mut self, dt: f64) -> Vec<Self::ParticleType> {
38 self.iter_emitters_mut()
39 .flat_map(|emitter| emitter.update(dt))
40 .collect()
41 }
42
43 fn clean_particles(&mut self);
45
46 fn clean_emitters(&mut self);
48
49 fn update(&mut self, dt: f64) {
56 let new_particles = self.update_emitters(dt);
57
58 for new_particle in new_particles {
59 self.add_particle(new_particle);
60 }
61
62 self.update_particles(dt);
63
64 self.clean_particles();
65 self.clean_emitters();
66 }
67}
68
69#[derive(Debug, Clone)]
73pub struct VecParticleSystem<P, E> {
74 particles: Vec<P>,
75 emitters: Vec<E>,
76}
77
78impl<P, E> Default for VecParticleSystem<P, E>
79{
80 fn default() -> Self {
81 Self {
82 particles: Vec::default(),
83 emitters: Vec::default(),
84 }
85 }
86}
87
88impl<P: Particle, E: ParticleEmitter<ParticleType = P>> ParticleSystem for VecParticleSystem<P, E> {
89 type ParticleType = P;
91
92 type EmitterType = E;
94
95 fn iter_particles(&self) -> impl Iterator<Item = &Self::ParticleType> {
96 self.particles.iter()
97 }
98
99 fn iter_particles_mut(&mut self) -> impl Iterator<Item = &mut Self::ParticleType> {
100 self.particles.iter_mut()
101 }
102
103 fn iter_emitters(&self) -> impl Iterator<Item = &Self::EmitterType> {
104 self.emitters.iter()
105 }
106
107 fn iter_emitters_mut(&mut self) -> impl Iterator<Item = &mut Self::EmitterType> {
108 self.emitters.iter_mut()
109 }
110
111 fn add_particle(&mut self, particle: Self::ParticleType) {
112 self.particles.push(particle);
113 }
114
115 fn add_emitter(&mut self, emitter: Self::EmitterType) {
116 self.emitters.push(emitter);
117 }
118
119 fn clean_particles(&mut self) {
120 self.particles.retain(|particle| particle.is_alive());
121 }
122
123 fn clean_emitters(&mut self) {
124 self.emitters.retain(|emitter| emitter.is_alive());
125 }
126}
127
128pub type BaseParticleSystem<C> = VecParticleSystem<
129 Box<dyn Particle<Coordinate = C>>,
130 Box<dyn ParticleEmitter<ParticleType = Box<dyn Particle<Coordinate = C>>>>,
131>;
132
133pub trait ParticleEmitter {
135 type ParticleType: Particle;
137
138 fn update(&mut self, dt: f64) -> Vec<Self::ParticleType>;
140
141 fn is_alive(&self) -> bool;
143}
144
145impl<E: ParticleEmitter + ?Sized> ParticleEmitter for Box<E> {
146 type ParticleType = E::ParticleType;
147
148 fn update(&mut self, dt: f64) -> Vec<Self::ParticleType> {
149 E::update(self, dt)
150 }
151
152 fn is_alive(&self) -> bool {
153 E::is_alive(self)
154 }
155}
156
157#[derive(Debug, Clone, Copy)]
160pub struct NullParticleEmitter<P> {
161 phantom: PhantomData<P>,
162}
163
164impl<P: Particle> ParticleEmitter for NullParticleEmitter<P> {
165 type ParticleType = P;
166
167 fn update(&mut self, _dt: f64) -> Vec<Self::ParticleType> {
168 vec![]
169 }
170
171 fn is_alive(&self) -> bool {
172 false
173 }
174}
175
176pub trait Particle {
178 type Coordinate;
180
181 fn get_position(&self) -> Self::Coordinate;
183
184 fn update(&mut self, dt: f64);
186
187 fn is_alive(&self) -> bool;
189}
190
191impl<P: Particle + ?Sized> Particle for Box<P> {
192 type Coordinate = P::Coordinate;
193
194 fn get_position(&self) -> Self::Coordinate {
195 P::get_position(self)
196 }
197
198 fn update(&mut self, dt: f64) {
199 P::update(self, dt);
200 }
201
202 fn is_alive(&self) -> bool {
203 P::is_alive(self)
204 }
205}
206
207pub trait Aging {
209 fn get_age(&self) -> f64;
211
212 fn set_age(&mut self, age: f64);
214}
215
216pub trait MaxAging: Aging {
218 fn get_max_age(&self) -> f64;
220
221 fn get_age_percent(&self) -> f64 {
223 self.get_age() / self.get_max_age()
224 }
225
226 fn is_alive(&self) -> bool {
228 self.get_age_percent() < 1.0
229 }
230}