fyrox_impl/scene/particle_system/emitter/
mod.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//! Emitter is an enum over all possible emitter types, they all must
22//! use BaseEmitter which contains base functionality.
23
24use crate::{
25    core::{reflect::prelude::*, visitor::prelude::*},
26    scene::particle_system::{
27        emitter::{
28            base::BaseEmitter, cuboid::CuboidEmitter, cylinder::CylinderEmitter,
29            sphere::SphereEmitter,
30        },
31        Particle, ParticleSystemRng,
32    },
33};
34use fyrox_core::uuid_provider;
35use std::ops::{Deref, DerefMut};
36use strum_macros::{AsRefStr, EnumString, VariantNames};
37
38pub mod base;
39pub mod cuboid;
40pub mod cylinder;
41pub mod sphere;
42
43/// Emit trait must be implemented for any particle system emitter.
44pub trait Emit {
45    /// Initializes state of particle using given emitter and particle system.
46    fn emit(&self, particle: &mut Particle, rng: &mut ParticleSystemRng);
47}
48
49/// See module docs.
50#[derive(PartialEq, Debug, Reflect, AsRefStr, EnumString, VariantNames)]
51pub enum Emitter {
52    /// See BoxEmitter docs.
53    Cuboid(CuboidEmitter),
54    /// See SphereEmitter docs.
55    Sphere(SphereEmitter),
56    /// Cylinder emitter.
57    Cylinder(CylinderEmitter),
58}
59
60uuid_provider!(Emitter = "4cad87ed-6b2c-411d-8c05-86dc26e463b2");
61
62impl Emitter {
63    /// Creates new emitter from given id.
64    pub fn new(id: i32) -> Result<Self, String> {
65        match id {
66            1 => Ok(Self::Cuboid(Default::default())),
67            2 => Ok(Self::Sphere(Default::default())),
68            3 => Ok(Self::Cylinder(Default::default())),
69            _ => Err(format!("Invalid emitter id {id}!")),
70        }
71    }
72
73    /// Returns id of current emitter kind.
74    pub fn id(&self) -> i32 {
75        match self {
76            Self::Cuboid(_) => 1,
77            Self::Sphere(_) => 2,
78            Self::Cylinder(_) => 3,
79        }
80    }
81}
82
83macro_rules! static_dispatch {
84    ($self:ident, $func:ident, $($args:expr),*) => {
85        match $self {
86            Emitter::Cuboid(v) => v.$func($($args),*),
87            Emitter::Sphere(v) => v.$func($($args),*),
88            Emitter::Cylinder(v) => v.$func($($args),*),
89        }
90    };
91}
92
93impl Visit for Emitter {
94    fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
95        let mut kind_id: i32 = self.id();
96        kind_id.visit("KindId", visitor)?;
97        if visitor.is_reading() {
98            *self = Emitter::new(kind_id)?;
99        }
100
101        static_dispatch!(self, visit, name, visitor)
102    }
103}
104
105impl Emit for Emitter {
106    fn emit(&self, particle: &mut Particle, rng: &mut ParticleSystemRng) {
107        static_dispatch!(self, emit, particle, rng)
108    }
109}
110
111impl Clone for Emitter {
112    fn clone(&self) -> Self {
113        match self {
114            Self::Cuboid(box_emitter) => Self::Cuboid(box_emitter.clone()),
115            Self::Sphere(sphere_emitter) => Self::Sphere(sphere_emitter.clone()),
116            Self::Cylinder(cylinder) => Self::Cylinder(cylinder.clone()),
117        }
118    }
119}
120
121impl Deref for Emitter {
122    type Target = BaseEmitter;
123
124    fn deref(&self) -> &Self::Target {
125        static_dispatch!(self, deref,)
126    }
127}
128
129impl DerefMut for Emitter {
130    fn deref_mut(&mut self) -> &mut Self::Target {
131        static_dispatch!(self, deref_mut,)
132    }
133}
134
135impl Default for Emitter {
136    fn default() -> Self {
137        Self::Cuboid(Default::default())
138    }
139}