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 #[visit(optional)] max_particles: Option<u32>,
44 #[visit(rename = "LifeTime")]
46 lifetime: Range<f32>,
47 size: Range<f32>,
49 size_modifier: Range<f32>,
51 x_velocity: Range<f32>,
53 y_velocity: Range<f32>,
55 z_velocity: Range<f32>,
57 rotation_speed: Range<f32>,
59 rotation: Range<f32>,
61 #[reflect(hidden)]
62 pub(crate) alive_particles: u32,
63 #[visit(skip)]
64 #[reflect(hidden)]
65 time: f32,
66 #[visit(skip)]
67 #[reflect(hidden)]
68 pub(crate) particles_to_spawn: u32,
69 resurrect_particles: bool,
70 #[reflect(hidden)]
71 pub(crate) spawned_particles: u64,
72}
73
74pub struct BaseEmitterBuilder {
77 position: Option<Vector3<f32>>,
78 particle_spawn_rate: Option<u32>,
79 max_particles: Option<u32>,
80 lifetime: Range<f32>,
81 size: Range<f32>,
82 size_modifier: Range<f32>,
83 x_velocity: Range<f32>,
84 y_velocity: Range<f32>,
85 z_velocity: Range<f32>,
86 rotation_speed: Range<f32>,
87 rotation: Range<f32>,
88 resurrect_particles: bool,
89}
90
91impl Default for BaseEmitterBuilder {
92 fn default() -> Self {
93 Self::new()
94 }
95}
96
97impl BaseEmitterBuilder {
98 pub fn new() -> Self {
100 Self {
101 position: None,
102 particle_spawn_rate: None,
103 max_particles: None,
104 lifetime: 5.0..10.0,
105 size: 0.125..0.250,
106 size_modifier: 0.0005..0.0010,
107 x_velocity: -0.001..0.001,
108 y_velocity: -0.001..0.001,
109 z_velocity: -0.001..0.001,
110 rotation_speed: -0.02..0.02,
111 rotation: -std::f32::consts::PI..std::f32::consts::PI,
112 resurrect_particles: true,
113 }
114 }
115
116 pub fn with_position(mut self, position: Vector3<f32>) -> Self {
118 self.position = Some(position);
119 self
120 }
121
122 pub fn with_spawn_rate(mut self, rate: u32) -> Self {
124 self.particle_spawn_rate = Some(rate);
125 self
126 }
127
128 pub fn with_max_particles(mut self, value: u32) -> Self {
130 self.max_particles = Some(value);
131 self
132 }
133
134 pub fn with_lifetime_range(mut self, time_range: Range<f32>) -> Self {
136 self.lifetime = time_range;
137 self
138 }
139
140 pub fn with_size_range(mut self, size_range: Range<f32>) -> Self {
142 self.size = size_range;
143 self
144 }
145
146 pub fn with_size_modifier_range(mut self, mod_range: Range<f32>) -> Self {
148 self.size_modifier = mod_range;
149 self
150 }
151
152 pub fn with_x_velocity_range(mut self, x_vel_range: Range<f32>) -> Self {
154 self.x_velocity = x_vel_range;
155 self
156 }
157
158 pub fn with_y_velocity_range(mut self, y_vel_range: Range<f32>) -> Self {
160 self.y_velocity = y_vel_range;
161 self
162 }
163
164 pub fn with_z_velocity_range(mut self, z_vel_range: Range<f32>) -> Self {
166 self.z_velocity = z_vel_range;
167 self
168 }
169
170 pub fn with_rotation_speed_range(mut self, speed_range: Range<f32>) -> Self {
172 self.rotation_speed = speed_range;
173 self
174 }
175
176 pub fn with_rotation_range(mut self, angle_range: Range<f32>) -> Self {
178 self.rotation = angle_range;
179 self
180 }
181
182 pub fn resurrect_particles(mut self, value: bool) -> Self {
184 self.resurrect_particles = value;
185 self
186 }
187
188 pub fn build(self) -> BaseEmitter {
190 BaseEmitter {
191 position: self.position.unwrap_or_default(),
192 particle_spawn_rate: self.particle_spawn_rate.unwrap_or(25),
193 max_particles: self.max_particles,
194 lifetime: self.lifetime,
195 size: self.size,
196 size_modifier: self.size_modifier,
197 x_velocity: self.x_velocity,
198 y_velocity: self.y_velocity,
199 z_velocity: self.z_velocity,
200 rotation_speed: self.rotation_speed,
201 rotation: self.rotation,
202 alive_particles: 0,
203 time: 0.0,
204 particles_to_spawn: 0,
205 resurrect_particles: self.resurrect_particles,
206 spawned_particles: 0,
207 }
208 }
209}
210
211impl BaseEmitter {
212 pub fn tick(&mut self, dt: f32) {
215 self.time += dt;
216 let time_amount_per_particle = 1.0 / self.particle_spawn_rate as f32;
217 self.particles_to_spawn = (self.time / time_amount_per_particle) as u32;
218 self.time -= time_amount_per_particle * self.particles_to_spawn as f32;
219 if let Some(max_particles) = self.max_particles {
220 let alive_particles = self.alive_particles;
221 if alive_particles < max_particles
222 && alive_particles + self.particles_to_spawn > max_particles
223 {
224 self.particles_to_spawn = max_particles.saturating_sub(alive_particles);
225 }
226 if !self.resurrect_particles && self.spawned_particles >= u64::from(max_particles) {
227 self.particles_to_spawn = 0;
228 }
229 }
230 self.spawned_particles += self.particles_to_spawn as u64;
231 }
232
233 pub fn emit(&self, particle: &mut Particle, rng: &mut ParticleSystemRng) {
236 particle.lifetime = 0.0;
237 particle.initial_lifetime = self.lifetime.random(rng);
238 particle.color = Color::WHITE;
239 particle.size = self.size.random(rng);
240 particle.size_modifier = self.size_modifier.random(rng);
241 particle.velocity = Vector3::new(
242 self.x_velocity.random(rng),
243 self.y_velocity.random(rng),
244 self.z_velocity.random(rng),
245 );
246 particle.rotation = self.rotation.random(rng);
247 particle.rotation_speed = self.rotation_speed.random(rng);
248 }
249
250 pub fn set_position(&mut self, position: Vector3<f32>) -> &mut Self {
252 self.position = position;
253 self
254 }
255
256 pub fn position(&self) -> Vector3<f32> {
258 self.position
259 }
260
261 pub fn set_spawn_rate(&mut self, rate: u32) -> &mut Self {
263 self.particle_spawn_rate = rate;
264 self
265 }
266
267 pub fn spawn_rate(&self) -> u32 {
269 self.particle_spawn_rate
270 }
271
272 pub fn set_max_particles(&mut self, max: Option<u32>) -> &mut Self {
274 self.max_particles = max;
275 self
276 }
277
278 pub fn max_particles(&self) -> Option<u32> {
280 self.max_particles
281 }
282
283 pub fn set_life_time_range(&mut self, range: Range<f32>) -> &mut Self {
286 self.lifetime = range;
287 self
288 }
289
290 pub fn life_time_range(&self) -> Range<f32> {
292 self.lifetime.clone()
293 }
294
295 pub fn set_size_range(&mut self, range: Range<f32>) -> &mut Self {
298 self.size = range;
299 self
300 }
301
302 pub fn size_range(&self) -> Range<f32> {
304 self.size.clone()
305 }
306
307 pub fn set_size_modifier_range(&mut self, range: Range<f32>) -> &mut Self {
310 self.size_modifier = range;
311 self
312 }
313
314 pub fn size_modifier_range(&self) -> Range<f32> {
316 self.size_modifier.clone()
317 }
318
319 pub fn set_x_velocity_range(&mut self, range: Range<f32>) -> &mut Self {
322 self.x_velocity = range;
323 self
324 }
325
326 pub fn x_velocity_range(&self) -> Range<f32> {
329 self.x_velocity.clone()
330 }
331
332 pub fn set_y_velocity_range(&mut self, range: Range<f32>) -> &mut Self {
335 self.y_velocity = range;
336 self
337 }
338
339 pub fn y_velocity_range(&self) -> Range<f32> {
342 self.y_velocity.clone()
343 }
344
345 pub fn set_z_velocity_range(&mut self, range: Range<f32>) -> &mut Self {
348 self.z_velocity = range;
349 self
350 }
351
352 pub fn z_velocity_range(&self) -> Range<f32> {
355 self.z_velocity.clone()
356 }
357
358 pub fn set_rotation_speed_range(&mut self, range: Range<f32>) -> &mut Self {
361 self.rotation_speed = range;
362 self
363 }
364
365 pub fn rotation_speed_range(&self) -> Range<f32> {
368 self.rotation_speed.clone()
369 }
370
371 pub fn set_rotation_range(&mut self, range: Range<f32>) -> &mut Self {
374 self.rotation = range;
375 self
376 }
377
378 pub fn rotation_range(&self) -> Range<f32> {
381 self.rotation.clone()
382 }
383
384 pub fn enable_particle_resurrection(&mut self, state: bool) -> &mut Self {
387 self.resurrect_particles = state;
388 self
389 }
390
391 pub fn is_particles_resurrects(&self) -> bool {
393 self.resurrect_particles
394 }
395
396 pub fn spawned_particles(&self) -> u64 {
398 self.spawned_particles
399 }
400}
401
402impl Clone for BaseEmitter {
403 fn clone(&self) -> Self {
404 Self {
405 position: self.position,
406 particle_spawn_rate: self.particle_spawn_rate,
407 max_particles: self.max_particles,
408 lifetime: self.lifetime.clone(),
409 size: self.size.clone(),
410 size_modifier: self.size_modifier.clone(),
411 x_velocity: self.x_velocity.clone(),
412 y_velocity: self.y_velocity.clone(),
413 z_velocity: self.z_velocity.clone(),
414 rotation_speed: self.rotation_speed.clone(),
415 rotation: self.rotation.clone(),
416 alive_particles: self.alive_particles,
417 time: self.time,
418 particles_to_spawn: 0,
419 resurrect_particles: self.resurrect_particles,
420 spawned_particles: self.spawned_particles,
421 }
422 }
423}
424
425impl Default for BaseEmitter {
426 fn default() -> Self {
427 Self {
428 position: Vector3::default(),
429 particle_spawn_rate: 100,
430 max_particles: None,
431 lifetime: 5.0..10.0,
432 size: 0.125..0.250,
433 size_modifier: 0.0005..0.0010,
434 x_velocity: -0.001..0.001,
435 y_velocity: -0.001..0.001,
436 z_velocity: -0.001..0.001,
437 rotation_speed: -0.02..0.02,
438 rotation: -std::f32::consts::PI..std::f32::consts::PI,
439 alive_particles: 0,
440 time: 0.0,
441 particles_to_spawn: 0,
442 resurrect_particles: true,
443 spawned_particles: 0,
444 }
445 }
446}