sprite/
scene.rs

1use std::collections::{HashSet,HashMap};
2use std::mem;
3use uuid::Uuid;
4
5use graphics::{ Graphics, ImageSize };
6use graphics::math::{ Matrix2d };
7
8use input::GenericEvent;
9use ai_behavior::{
10    Behavior,
11    State,
12    Running,
13};
14
15use sprite::Sprite;
16
17use animation::{
18    Animation,
19    AnimationState,
20};
21
22/// A scene is used to manage sprite's life and run animation with sprite
23pub struct Scene<I: ImageSize> {
24    children: Vec<Sprite<I>>,
25    children_index: HashMap<Uuid, usize>,
26    running: HashMap<Uuid,
27        Vec<(Behavior<Animation>, State<Animation, AnimationState>, bool)>>,
28    // Set of sprites that should be removed once animations have finished.
29    dead_sprites: HashSet<Uuid>,
30}
31
32impl<I: ImageSize> Scene<I> {
33    /// Create a new scene
34    pub fn new() -> Scene<I> {
35        Scene {
36            children: Vec::new(),
37            children_index: HashMap::new(),
38            running: HashMap::new(),
39            dead_sprites: HashSet::new(),
40        }
41    }
42
43    /// Update animation's state
44    pub fn event<E>(&mut self, e: &E) where E: GenericEvent {
45        // regenerate the animations and their states
46        let running = mem::take(&mut self.running);
47
48        for (id, animations) in running.into_iter() {
49            let mut new_animations = Vec::new();
50
51            for (b, mut a, paused) in animations.into_iter() {
52                if paused {
53                    new_animations.push((b, a, paused));
54                    continue;
55                }
56
57                let sprite = self.child_mut(id).unwrap();
58                let (status, _) = a.event(e, &mut |args| {
59                    let (state, status, remain) = {
60                        let start_state;
61                        let state = match *args.state {
62                            None => { start_state = args.action.to_state(sprite); &start_state },
63                            Some(ref state) => state,
64                        };
65                        state.update(sprite, args.dt)
66                    };
67                    *args.state = state;
68                    (status, remain)
69                });
70
71                match status {
72                    // the behavior is still running, add it for next update
73                    Running => {
74                        new_animations.push((b, a, paused));
75                    },
76                    _ => {},
77                }
78            }
79
80            if !new_animations.is_empty() {
81                self.running.insert(id, new_animations);
82            }
83        }
84
85        self.prune_dead_sprites();
86    }
87
88    fn prune_dead_sprites(&mut self) {
89        if !self.dead_sprites.is_empty() {
90            let mut to_remove = HashSet::new();
91
92            for sprite_id in self.dead_sprites.iter() {
93                let n = self.running_for_child(*sprite_id)
94                    .expect("Assert failed: invalid internal state for dead_sprites");
95
96                if n == 0 {
97                    to_remove.insert(*sprite_id);
98                }
99            }
100
101            for sprite_id in to_remove.iter() {
102                self.remove_child(*sprite_id);
103            }
104        }
105    }
106
107    /// Render this scene
108    pub fn draw<B: Graphics<Texture = I>>(&self, t: Matrix2d, b: &mut B) {
109        for child in &self.children {
110            child.draw(t, b);
111        }
112    }
113
114    /// Render this scene with tint
115    pub fn draw_tinted<B: Graphics<Texture = I>>(&self, t: Matrix2d, b: &mut B, c: [f32;3]) {
116        for child in &self.children {
117            child.draw_tinted(t,b,c)
118        }
119    }
120
121    /// Register animation with sprite
122    pub fn run(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
123        use std::collections::hash_map::Entry::{ Vacant, Occupied };
124        let animations = match self.running.entry(sprite_id) {
125            Vacant(entry) => entry.insert(Vec::new()),
126            Occupied(entry) => entry.into_mut()
127        };
128        let state = State::new(animation.clone());
129        animations.push((animation.clone(), state, false));
130    }
131
132    fn find(&self, sprite_id: Uuid, animation: &Behavior<Animation>) -> Option<usize> {
133        let mut index = None;
134        if let Some(animations) = self.running.get(&sprite_id) {
135            for (i, &(ref b, _, _)) in animations.iter().enumerate() {
136                if b == animation {
137                    index = Some(i);
138                    break;
139                }
140            }
141        }
142        index
143    }
144
145    /// Pause a running animation of the sprite
146    pub fn pause(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
147        if let Some(index) = self.find(sprite_id, animation) {
148            let animations = self.running.get_mut(&sprite_id).unwrap();
149            let (b, s, _) = animations.remove(index);
150            animations.push((b, s, true));
151        }
152    }
153
154    /// Resume a paused animation of the sprite
155    pub fn resume(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
156        if let Some(index) = self.find(sprite_id, animation) {
157            let animations = self.running.get_mut(&sprite_id).unwrap();
158            let (b, s, _) = animations.remove(index);
159            animations.push((b, s, false));
160        }
161    }
162
163    /// Toggle an animation of the sprite
164    pub fn toggle(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
165        if let Some(index) = self.find(sprite_id, animation) {
166            let animations = self.running.get_mut(&sprite_id).unwrap();
167            let (b, s, paused) = animations.remove(index);
168            animations.push((b, s, !paused));
169        }
170    }
171
172    /// Stop a running animation of the sprite
173    pub fn stop(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
174        if let Some(index) = self.find(sprite_id, animation) {
175            self.running.get_mut(&sprite_id).unwrap().remove(index);
176        }
177    }
178
179    /// Stop all running animations of the sprite
180    pub fn stop_all(&mut self, sprite_id: Uuid) {
181        self.running.remove(&sprite_id);
182    }
183
184    /// Get all the running animations in the scene
185    pub fn running(&self) -> usize {
186        let mut total = 0;
187        for (_, animations) in &self.running {
188            total += animations.len();
189        }
190        total
191    }
192
193    /// Get the number of running animations for a sprite. If sprite does not
194    /// exist, returns None.
195    pub fn running_for_child(&self, sprite_id: Uuid) -> Option<usize> {
196        if let Some(animations) = self.running.get(&sprite_id) {
197            Some(animations.len())
198        } else {
199            if self.child(sprite_id).is_some() {
200                Some(0)
201            } else {
202                None
203            }
204        }
205    }
206
207    /// Add sprite to scene
208    pub fn add_child(&mut self, sprite: Sprite<I>) -> Uuid {
209        let id = sprite.id();
210        self.children.push(sprite);
211        self.children_index.insert(id.clone(), self.children.len() - 1);
212        id
213    }
214
215    fn stop_all_including_children(&mut self, sprite: &Sprite<I>) {
216        self.stop_all(sprite.id());
217        for child in sprite.children().iter() {
218            self.stop_all_including_children(child);
219        }
220    }
221
222    /// Remove the child by `id` from the scene's children or grandchild
223    /// will stop all the animations run by this child
224    pub fn remove_child(&mut self, id: Uuid) -> Option<Sprite<I>> {
225        let removed = if let Some(index) = self.children_index.remove(&id) {
226            let removed = self.children.remove(index);
227            // Removing a element of vector will alter the index,
228            // update the mapping from uuid to index.
229            for i in index..self.children.len() {
230                let uuid = self.children[i].id();
231                self.children_index.insert(uuid, i);
232            }
233            Some(removed)
234        } else {
235            for child in &mut self.children {
236                if let Some(c) = child.remove_child(id.clone()) {
237                    return Some(c);
238                }
239            }
240            None
241        };
242
243        if removed.is_some() {
244            self.dead_sprites.remove(&id);
245            self.stop_all_including_children(removed.as_ref().unwrap());
246        }
247
248        removed
249    }
250
251    /// Remove the child by `id` from the scene's children or grandchild once
252    /// all of its animations have finished. If the child current has no
253    /// animations, it is removed immediately. Children with paused animations
254    /// will not be removed until the animations are resumed and completed.
255    pub fn remove_child_when_done(&mut self, id: Uuid) {
256        match self.running_for_child(id) {
257            Some(n) => {
258                if n == 0 {
259                    self.remove_child(id);
260                } else {
261                    self.dead_sprites.insert(id);
262                }
263            },
264            None => {}
265        }
266    }
267
268    /// Find the child by `id` from the scene's children or grandchild
269    pub fn child(&self, id: Uuid) -> Option<&Sprite<I>> {
270        if let Some(index) = self.children_index.get(&id) {
271            Some(&self.children[*index])
272        } else {
273            for child in &self.children {
274                if let Some(c) = child.child(id.clone()) {
275                    return Some(c);
276                }
277            }
278            None
279        }
280    }
281
282    /// Find the child by `id` from this sprite's children or grandchild, mutability
283    pub fn child_mut(&mut self, id: Uuid) -> Option<&mut Sprite<I>> {
284        if let Some(index) = self.children_index.get(&id) {
285            Some(&mut self.children[*index])
286        } else {
287            for child in &mut self.children {
288                if let Some(c) = child.child_mut(id.clone()) {
289                    return Some(c);
290                }
291            }
292            None
293        }
294    }
295
296    /// Get the list of top-level (non-child) sprites.
297    #[inline(always)]
298    pub fn children(&self) -> &Vec<Sprite<I>> {
299        &self.children
300    }
301}