1 use std::collections::{HashSet,HashMap};
2 use uuid::Uuid;
3 
4 use graphics::{ Graphics, ImageSize };
5 use graphics::math::{ Matrix2d };
6 
7 use input::GenericEvent;
8 use ai_behavior::{
9     Behavior,
10     State,
11     Running,
12 };
13 
14 use sprite::Sprite;
15 
16 use animation::{
17     Animation,
18     AnimationState,
19 };
20 
21 /// A scene is used to manage sprite's life and run animation with sprite
22 pub struct Scene<I: ImageSize> {
23     children: Vec<Sprite<I>>,
24     children_index: HashMap<Uuid, usize>,
25     running: HashMap<Uuid,
26         Vec<(Behavior<Animation>, State<Animation, AnimationState>, bool)>>,
27     // Set of sprites that should be removed once animations have finished.
28     dead_sprites: HashSet<Uuid>,
29 }
30 
31 impl<I: ImageSize> Scene<I> {
32     /// Create a new scene
new() -> Scene<I>33     pub fn new() -> Scene<I> {
34         Scene {
35             children: Vec::new(),
36             children_index: HashMap::new(),
37             running: HashMap::new(),
38             dead_sprites: HashSet::new(),
39         }
40     }
41 
42     /// Update animation's state
event<E>(&mut self, e: &E) where E: GenericEvent43     pub fn event<E>(&mut self, e: &E) where E: GenericEvent {
44         // regenerate the animations and their states
45         let running = self.running.clone();
46         self.running.clear();
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 
prune_dead_sprites(&mut self)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
draw<B: Graphics<Texture = I>>(&self, t: Matrix2d, b: &mut B)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
draw_tinted<B: Graphics<Texture = I>>(&self, t: Matrix2d, b: &mut B, c: [f32;3])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
run(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>)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 
find(&self, sprite_id: Uuid, animation: &Behavior<Animation>) -> Option<usize>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
pause(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>)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
resume(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>)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
toggle(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>)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
stop(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>)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
stop_all(&mut self, sprite_id: Uuid)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
running(&self) -> usize185     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.
running_for_child(&self, sprite_id: Uuid) -> Option<usize>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
add_child(&mut self, sprite: Sprite<I>) -> Uuid208     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 
stop_all_including_children(&mut self, sprite: &Sprite<I>)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
remove_child(&mut self, id: Uuid) -> Option<Sprite<I>>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.
remove_child_when_done(&mut self, id: Uuid)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
child(&self, id: Uuid) -> Option<&Sprite<I>>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
child_mut(&mut self, id: Uuid) -> Option<&mut Sprite<I>>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)]
children(&self) -> &Vec<Sprite<I>>298     pub fn children(&self) -> &Vec<Sprite<I>> {
299         &self.children
300     }
301 }
302