fyrox_impl/scene/particle_system/emitter/
base.rs1use crate::{
24 core::{
25 algebra::Vector3, color::Color, numeric_range::RangeExt, reflect::prelude::*,
26 visitor::prelude::*,
27 },
28 scene::particle_system::{Particle, ParticleSystemRng},
29};
30use std::ops::Range;
31
32#[derive(Debug, Visit, PartialEq, Reflect)]
34pub struct BaseEmitter {
35 position: Vector3<f32>,
37 #[visit(rename = "SpawnRate")]
40 particle_spawn_rate: u32,
41 max_particles: Option<u32>,
43 #[visit(rename = "LifeTime")]
45 lifetime: Range<f32>,
46 size: Range<f32>,
48 size_modifier: Range<f32>,
50 x_velocity: Range<f32>,
52 y_velocity: Range<f32>,
54 z_velocity: Range<f32>,
56 rotation_speed: Range<f32>,
58 rotation: Range<f32>,
60 #[reflect(hidden)]
61 pub(crate) alive_particles: u32,
62 #[visit(skip)]
63 #[reflect(hidden)]
64 time: f32,
65 #[visit(skip)]
66 #[reflect(hidden)]
67 pub(crate) particles_to_spawn: u32,
68 resurrect_particles: bool,
69 #[reflect(hidden)]
70 pub(crate) spawned_particles: u64,
71}
72
73pub struct BaseEmitterBuilder {
76 position: Option<Vector3<f32>>,
77 particle_spawn_rate: Option<u32>,
78 max_particles: Option<u32>,
79 lifetime: Range<f32>,
80 size: Range<f32>,
81 size_modifier: Range<f32>,
82 x_velocity: Range<f32>,
83 y_velocity: Range<f32>,
84 z_velocity: Range<f32>,
85 rotation_speed: Range<f32>,
86 rotation: Range<f32>,
87 resurrect_particles: bool,
88}
89
90impl Default for BaseEmitterBuilder {
91 fn default() -> Self {
92 Self::new()
93 }
94}
95
96impl BaseEmitterBuilder {
97 pub fn new() -> Self {
99 Self {
100 position: None,
101 particle_spawn_rate: None,
102 max_particles: None,
103 lifetime: 5.0..10.0,
104 size: 0.125..0.250,
105 size_modifier: 0.0005..0.0010,
106 x_velocity: -0.001..0.001,
107 y_velocity: -0.001..0.001,
108 z_velocity: -0.001..0.001,
109 rotation_speed: -0.02..0.02,
110 rotation: -std::f32::consts::PI..std::f32::consts::PI,
111 resurrect_particles: true,
112 }
113 }
114
115 pub fn with_position(mut self, position: Vector3<f32>) -> Self {
117 self.position = Some(position);
118 self
119 }
120
121 pub fn with_spawn_rate(mut self, rate: u32) -> Self {
123 self.particle_spawn_rate = Some(rate);
124 self
125 }
126
127 pub fn with_max_particles(mut self, value: u32) -> Self {
129 self.max_particles = Some(value);
130 self
131 }
132
133 pub fn with_lifetime_range(mut self, time_range: Range<f32>) -> Self {
135 self.lifetime = time_range;
136 self
137 }
138
139 pub fn with_size_range(mut self, size_range: Range<f32>) -> Self {
141 self.size = size_range;
142 self
143 }
144
145 pub fn with_size_modifier_range(mut self, mod_range: Range<f32>) -> Self {
147 self.size_modifier = mod_range;
148 self
149 }
150
151 pub fn with_x_velocity_range(mut self, x_vel_range: Range<f32>) -> Self {
153 self.x_velocity = x_vel_range;
154 self
155 }
156
157 pub fn with_y_velocity_range(mut self, y_vel_range: Range<f32>) -> Self {
159 self.y_velocity = y_vel_range;
160 self
161 }
162
163 pub fn with_z_velocity_range(mut self, z_vel_range: Range<f32>) -> Self {
165 self.z_velocity = z_vel_range;
166 self
167 }
168
169 pub fn with_rotation_speed_range(mut self, speed_range: Range<f32>) -> Self {
171 self.rotation_speed = speed_range;
172 self
173 }
174
175 pub fn with_rotation_range(mut self, angle_range: Range<f32>) -> Self {
177 self.rotation = angle_range;
178 self
179 }
180
181 pub fn resurrect_particles(mut self, value: bool) -> Self {
183 self.resurrect_particles = value;
184 self
185 }
186
187 pub fn build(self) -> BaseEmitter {
189 BaseEmitter {
190 position: self.position.unwrap_or_default(),
191 particle_spawn_rate: self.particle_spawn_rate.unwrap_or(25),
192 max_particles: self.max_particles,
193 lifetime: self.lifetime,
194 size: self.size,
195 size_modifier: self.size_modifier,
196 x_velocity: self.x_velocity,
197 y_velocity: self.y_velocity,
198 z_velocity: self.z_velocity,
199 rotation_speed: self.rotation_speed,
200 rotation: self.rotation,
201 alive_particles: 0,
202 time: 0.0,
203 particles_to_spawn: 0,
204 resurrect_particles: self.resurrect_particles,
205 spawned_particles: 0,
206 }
207 }
208}
209
210impl BaseEmitter {
211 pub fn tick(&mut self, dt: f32) {
214 self.time += dt;
215 let time_amount_per_particle = 1.0 / self.particle_spawn_rate as f32;
216 self.particles_to_spawn = (self.time / time_amount_per_particle) as u32;
217 self.time -= time_amount_per_particle * self.particles_to_spawn as f32;
218 if let Some(max_particles) = self.max_particles {
219 let alive_particles = self.alive_particles;
220 if alive_particles < max_particles
221 && alive_particles + self.particles_to_spawn > max_particles
222 {
223 self.particles_to_spawn = max_particles.saturating_sub(alive_particles);
224 }
225 if !self.resurrect_particles && self.spawned_particles >= u64::from(max_particles) {
226 self.particles_to_spawn = 0;
227 }
228 }
229 self.spawned_particles += self.particles_to_spawn as u64;
230 }
231
232 pub fn emit(&self, particle: &mut Particle, rng: &mut ParticleSystemRng) {
235 particle.lifetime = 0.0;
236 particle.initial_lifetime = self.lifetime.random(rng);
237 particle.color = Color::WHITE;
238 particle.size = self.size.random(rng);
239 particle.size_modifier = self.size_modifier.random(rng);
240 particle.velocity = Vector3::new(
241 self.x_velocity.random(rng),
242 self.y_velocity.random(rng),
243 self.z_velocity.random(rng),
244 );
245 particle.rotation = self.rotation.random(rng);
246 particle.rotation_speed = self.rotation_speed.random(rng);
247 }
248
249 pub fn set_position(&mut self, position: Vector3<f32>) -> &mut Self {
251 self.position = position;
252 self
253 }
254
255 pub fn position(&self) -> Vector3<f32> {
257 self.position
258 }
259
260 pub fn set_spawn_rate(&mut self, rate: u32) -> &mut Self {
262 self.particle_spawn_rate = rate;
263 self
264 }
265
266 pub fn spawn_rate(&self) -> u32 {
268 self.particle_spawn_rate
269 }
270
271 pub fn set_max_particles(&mut self, max: Option<u32>) -> &mut Self {
273 self.max_particles = max;
274 self
275 }
276
277 pub fn max_particles(&self) -> Option<u32> {
279 self.max_particles
280 }
281
282 pub fn set_life_time_range(&mut self, range: Range<f32>) -> &mut Self {
285 self.lifetime = range;
286 self
287 }
288
289 pub fn life_time_range(&self) -> Range<f32> {
291 self.lifetime.clone()
292 }
293
294 pub fn set_size_range(&mut self, range: Range<f32>) -> &mut Self {
297 self.size = range;
298 self
299 }
300
301 pub fn size_range(&self) -> Range<f32> {
303 self.size.clone()
304 }
305
306 pub fn set_size_modifier_range(&mut self, range: Range<f32>) -> &mut Self {
309 self.size_modifier = range;
310 self
311 }
312
313 pub fn size_modifier_range(&self) -> Range<f32> {
315 self.size_modifier.clone()
316 }
317
318 pub fn set_x_velocity_range(&mut self, range: Range<f32>) -> &mut Self {
321 self.x_velocity = range;
322 self
323 }
324
325 pub fn x_velocity_range(&self) -> Range<f32> {
328 self.x_velocity.clone()
329 }
330
331 pub fn set_y_velocity_range(&mut self, range: Range<f32>) -> &mut Self {
334 self.y_velocity = range;
335 self
336 }
337
338 pub fn y_velocity_range(&self) -> Range<f32> {
341 self.y_velocity.clone()
342 }
343
344 pub fn set_z_velocity_range(&mut self, range: Range<f32>) -> &mut Self {
347 self.z_velocity = range;
348 self
349 }
350
351 pub fn z_velocity_range(&self) -> Range<f32> {
354 self.z_velocity.clone()
355 }
356
357 pub fn set_rotation_speed_range(&mut self, range: Range<f32>) -> &mut Self {
360 self.rotation_speed = range;
361 self
362 }
363
364 pub fn rotation_speed_range(&self) -> Range<f32> {
367 self.rotation_speed.clone()
368 }
369
370 pub fn set_rotation_range(&mut self, range: Range<f32>) -> &mut Self {
373 self.rotation = range;
374 self
375 }
376
377 pub fn rotation_range(&self) -> Range<f32> {
380 self.rotation.clone()
381 }
382
383 pub fn enable_particle_resurrection(&mut self, state: bool) -> &mut Self {
386 self.resurrect_particles = state;
387 self
388 }
389
390 pub fn is_particles_resurrects(&self) -> bool {
392 self.resurrect_particles
393 }
394
395 pub fn spawned_particles(&self) -> u64 {
397 self.spawned_particles
398 }
399}
400
401impl Clone for BaseEmitter {
402 fn clone(&self) -> Self {
403 Self {
404 position: self.position,
405 particle_spawn_rate: self.particle_spawn_rate,
406 max_particles: self.max_particles,
407 lifetime: self.lifetime.clone(),
408 size: self.size.clone(),
409 size_modifier: self.size_modifier.clone(),
410 x_velocity: self.x_velocity.clone(),
411 y_velocity: self.y_velocity.clone(),
412 z_velocity: self.z_velocity.clone(),
413 rotation_speed: self.rotation_speed.clone(),
414 rotation: self.rotation.clone(),
415 alive_particles: self.alive_particles,
416 time: self.time,
417 particles_to_spawn: 0,
418 resurrect_particles: self.resurrect_particles,
419 spawned_particles: self.spawned_particles,
420 }
421 }
422}
423
424impl Default for BaseEmitter {
425 fn default() -> Self {
426 Self {
427 position: Vector3::default(),
428 particle_spawn_rate: 100,
429 max_particles: None,
430 lifetime: 5.0..10.0,
431 size: 0.125..0.250,
432 size_modifier: 0.0005..0.0010,
433 x_velocity: -0.001..0.001,
434 y_velocity: -0.001..0.001,
435 z_velocity: -0.001..0.001,
436 rotation_speed: -0.02..0.02,
437 rotation: -std::f32::consts::PI..std::f32::consts::PI,
438 alive_particles: 0,
439 time: 0.0,
440 particles_to_spawn: 0,
441 resurrect_particles: true,
442 spawned_particles: 0,
443 }
444 }
445}