fyrox_impl/scene/particle_system/emitter/
cuboid.rs

1// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21//! Box emitter emits particles uniformly in its volume. Can be used to create simple fog
22//! layer.
23
24use crate::core::numeric_range::RangeExt;
25use crate::scene::particle_system::ParticleSystemRng;
26use crate::{
27    core::{algebra::Vector3, reflect::prelude::*, visitor::prelude::*},
28    scene::particle_system::{
29        emitter::{
30            base::{BaseEmitter, BaseEmitterBuilder},
31            Emit, Emitter,
32        },
33        particle::Particle,
34    },
35};
36use std::ops::{Deref, DerefMut};
37
38/// See module docs.
39#[derive(Debug, Clone, Visit, PartialEq, Reflect)]
40pub struct CuboidEmitter {
41    emitter: BaseEmitter,
42    #[reflect(min_value = 0.0, step = 0.1)]
43    half_width: f32,
44    #[reflect(min_value = 0.0, step = 0.1)]
45    half_height: f32,
46    #[reflect(min_value = 0.0, step = 0.1)]
47    half_depth: f32,
48}
49
50impl Deref for CuboidEmitter {
51    type Target = BaseEmitter;
52
53    fn deref(&self) -> &Self::Target {
54        &self.emitter
55    }
56}
57
58impl DerefMut for CuboidEmitter {
59    fn deref_mut(&mut self) -> &mut Self::Target {
60        &mut self.emitter
61    }
62}
63
64impl CuboidEmitter {
65    /// Creates new box emitter of given width, height and depth.
66    pub fn new(emitter: BaseEmitter, width: f32, height: f32, depth: f32) -> Self {
67        Self {
68            emitter,
69            half_width: width * 0.5,
70            half_height: height * 0.5,
71            half_depth: depth * 0.5,
72        }
73    }
74
75    /// Returns half width of the box emitter.
76    pub fn half_width(&self) -> f32 {
77        self.half_width
78    }
79
80    /// Sets half width of the box emitter.
81    pub fn set_half_width(&mut self, half_width: f32) {
82        self.half_width = half_width.max(0.0);
83    }
84
85    /// Returns half height of the box emitter.
86    pub fn half_height(&self) -> f32 {
87        self.half_height
88    }
89
90    /// Sets half height of the box emitter.
91    pub fn set_half_height(&mut self, half_height: f32) {
92        self.half_height = half_height.max(0.0);
93    }
94
95    /// Returns half depth of the box emitter.
96    pub fn half_depth(&self) -> f32 {
97        self.half_depth
98    }
99
100    /// Sets half depth of the box emitter.
101    pub fn set_half_depth(&mut self, half_depth: f32) {
102        self.half_depth = half_depth.max(0.0);
103    }
104}
105
106impl Default for CuboidEmitter {
107    fn default() -> Self {
108        Self {
109            emitter: Default::default(),
110            half_width: 0.5,
111            half_height: 0.5,
112            half_depth: 0.5,
113        }
114    }
115}
116
117impl Emit for CuboidEmitter {
118    fn emit(&self, particle: &mut Particle, rng: &mut ParticleSystemRng) {
119        self.emitter.emit(particle, rng);
120        let position = self.position();
121        particle.position = Vector3::new(
122            position.x + (-self.half_width..self.half_width).random(rng),
123            position.y + (-self.half_height..self.half_height).random(rng),
124            position.z + (-self.half_depth..self.half_depth).random(rng),
125        )
126    }
127}
128
129/// Box emitter builder allows you to construct box emitter in declarative manner.
130/// This is typical implementation of Builder pattern.
131pub struct CuboidEmitterBuilder {
132    base: BaseEmitterBuilder,
133    width: f32,
134    height: f32,
135    depth: f32,
136}
137
138impl CuboidEmitterBuilder {
139    /// Creates new box emitter builder with
140    pub fn new(base: BaseEmitterBuilder) -> Self {
141        Self {
142            base,
143            width: 1.0,
144            height: 1.0,
145            depth: 1.0,
146        }
147    }
148
149    /// Sets desired width of the emitter.
150    pub fn with_width(mut self, width: f32) -> Self {
151        self.width = width;
152        self
153    }
154
155    /// Sets desired height of the emitter.
156    pub fn with_height(mut self, height: f32) -> Self {
157        self.height = height;
158        self
159    }
160
161    /// Sets desired depth of the emitter.
162    pub fn with_depth(mut self, depth: f32) -> Self {
163        self.depth = depth;
164        self
165    }
166
167    /// Creates new box emitter with given parameters.
168    pub fn build(self) -> Emitter {
169        Emitter::Cuboid(CuboidEmitter {
170            emitter: self.base.build(),
171            half_width: self.width * 0.5,
172            half_height: self.height * 0.5,
173            half_depth: self.depth * 0.5,
174        })
175    }
176}