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