aframe/entity/
mod.rs

1//! Module for the instantiaion of entities and primitives.
2
3pub mod primitive;
4
5use std::borrow::Cow;
6use crate::{Attribute, ComponentVec, component::Component};
7
8/// Defines the high-level API for describing entities, with one form for 
9/// describing general entities and another for defining specific primitives.
10
11/// Here's an example of a general entity definition:
12/// ```ignore
13/// entity!
14/// {
15///     attributes: ("id", "cube-rig"),
16///     components: 
17///     ("position", component::Position{x: 0.0, y: 2.5, z: -2.0}),
18///     ("sound", component!
19///     {
20///         component::Sound,
21///         src: Cow::Borrowed("#ambient_music"), 
22///         volume: 0.5
23///     }),
24///     ("play-sound-on-event", component!
25///     {
26///         component::PlaySoundOnEvent,
27///         mode: component::PlaySoundOnEventMode::ToggleStop, 
28///         event: Cow::Borrowed("click")
29///     }),
30///     ("light", component!
31///     {
32///         component::Light,
33///         light_type: component::LightType::Point
34///         {
35///             decay: 1.0,
36///             distance: 50.0,
37///             shadow: component::OptionalLocalShadow::NoCast{},
38///         }, 
39///         intensity: 0.0
40///     }),
41///     ("animation__mouseenter", component!
42///     {
43///         component::Animation,
44///         property: Cow::Borrowed("light.intensity"),
45///         to: Cow::Borrowed("1.0"),
46///         start_events: component::List(Cow::Borrowed(&[Cow::Borrowed("mouseenter")])),
47///         dur: 250
48///     }),
49///     ("animation__mouseleave", component!
50///     {
51///         component::Animation,
52///         property: Cow::Borrowed("light.intensity"),
53///         to: Cow::Borrowed("0.0"),
54///         start_events: component::List(Cow::Borrowed(&[Cow::Borrowed("mouseleave")])),
55///         dur: 250
56///     }),
57///     children: entity!
58///     {
59///         primitive: primitive::A_BOX,
60///         attributes: ("id", "my-box"),
61///         components:
62///     }
63/// },
64/// ```
65/// and here's an example of a primitive definition:
66/// ```ignore
67/// entity!
68/// {
69///     // This can also jsut a be a string: "a-box" 
70///     primitive: primitive::A_BOX,
71///     attributes: ("id", "my-box"),
72///     components: 
73/// }
74/// ```
75#[macro_export]
76macro_rules! entity
77{
78    ( 
79        $(attributes: $(($attr_id:literal, $attr_value:expr)),*)? $(,)?
80        $(components: $(($cmp_id:literal, $cmp_value:expr)),*)? $(,)? 
81        $(children: $($child:expr),*)? 
82    ) => 
83    {
84        Entity::new
85        (
86            attributes_vec!
87            {
88                $($(($attr_id, $attr_value)),*)?
89            },
90            components_vec!
91            {
92                $($(($cmp_id, $cmp_value)),*)?
93            },
94            vec!
95            {
96                $($($child),*)?
97            }
98        )
99    };
100    ( 
101        primitive: $name:expr,
102        $(attributes: $(($attr_id:literal, $attr_value:expr)),*)? $(,)?
103        $(components: $(($cmp_id:literal, $cmp_value:expr)),*)? $(,)? 
104        $(children: $($child:expr),*)? 
105    ) => 
106    {
107        Entity::new_primitive
108        (
109            std::borrow::Cow::Borrowed($name),
110            attributes_vec!
111            {
112                $($(($attr_id, $attr_value)),*)?
113            },
114            components_vec!
115            {
116                $($(($cmp_id, $cmp_value)),*)?
117            },
118            vec!
119            {
120                $($($child),*)?
121            }
122        )
123    }
124}
125
126/// Mid-level macro to create a vector of attributes
127#[macro_export]
128macro_rules! attributes_vec
129{
130    ( 
131        $(($attr_id:literal, $attr_value:expr)),*
132    ) => 
133    {
134        vec![ $(Attribute::new($attr_id, $attr_value)),* ]
135    }
136}
137
138/// Mid-level macro to create a vector of components
139#[macro_export]
140macro_rules! components_vec
141{
142    ( 
143        $(($cmp_id:literal, $cmp_value:expr)),* 
144    ) => 
145    {
146        vec![ $(($cmp_id.into(), Box::new($cmp_value))),* ]
147    }
148}
149
150/// Struct which represents an Aframe entity or primitive
151#[derive(Default, Debug, Clone, PartialEq)]
152pub struct Entity
153{
154    primitive: Option<Cow<'static, str>>,
155    attributes: Vec<Attribute>,
156    components: ComponentVec,
157    children: Vec<Entity>
158}
159
160impl Entity
161{
162    pub fn new(attributes: Vec<Attribute>, components: Vec<(Cow<'static, str>, Box<dyn Component>)>, children: Vec<Entity>) -> Self
163    {
164        Self { primitive: None, attributes, components: ComponentVec(components), children }
165    }
166
167    pub fn new_primitive(tag: Cow<'static, str>, attributes: Vec<Attribute>, components: Vec<(Cow<'static, str>, Box<dyn Component>)>, children: Vec<Entity>) -> Self
168    {
169        Self { primitive: Some(tag), attributes, components: ComponentVec(components), children }
170    }
171
172    pub fn with_components(components: Vec<(Cow<'static, str>, Box<dyn Component>)>) -> Self
173    {
174        Self { primitive: None, attributes: vec!(), components: ComponentVec(components), children: vec!() }
175    }
176
177    pub fn attributes(&self) -> &Vec<Attribute>
178    {
179        &self.attributes
180    }
181
182    pub fn attributes_mut(&mut self) -> &mut Vec<Attribute>
183    {
184        &mut self.attributes
185    }
186
187    pub fn components(&self) -> &Vec<(Cow<'static, str>, Box<dyn Component>)>
188    {
189        &self.components
190    }
191
192    pub fn components_mut(&mut self) -> &mut Vec<(Cow<'static, str>, Box<dyn Component>)>
193    {
194        &mut self.components
195    }
196
197    pub fn children(&self) -> &Vec<Entity>
198    {
199        &self.children
200    }
201
202    pub fn children_mut(&mut self) -> &mut Vec<Entity>
203    {
204        &mut self.children
205    }
206
207    pub fn tag(&self) -> Cow<'static, str>
208    {
209        match self.primitive
210        {
211            Some(ref tag) => tag.clone(),
212            None => self.tag().into()
213        }
214    }
215}