use std::collections::HashMap;
use uuid::Uuid;
use graphics::{ Graphics, ImageSize };
use graphics::math::{ Matrix2d };
use event::GenericEvent;
use ai_behavior::{
Behavior,
State,
Running,
};
use sprite::Sprite;
use animation::{
Animation,
AnimationState,
};
pub struct Scene<I: ImageSize> {
children: Vec<Sprite<I>>,
children_index: HashMap<Uuid, usize>,
running: HashMap<Uuid,
Vec<(Behavior<Animation>, State<Animation, AnimationState>, bool)>>,
}
impl<I: ImageSize> Scene<I> {
pub fn new() -> Scene<I> {
Scene {
children: Vec::new(),
children_index: HashMap::new(),
running: HashMap::new(),
}
}
pub fn event<E>(&mut self, e: &E) where E: GenericEvent {
let running = self.running.clone();
self.running.clear();
for (id, animations) in running.into_iter() {
let mut new_animations = Vec::new();
for (b, mut a, paused) in animations.into_iter() {
if paused {
new_animations.push((b, a, paused));
continue;
}
let sprite = self.child_mut(id).unwrap();
let (status, _) = a.event(e, &mut |_, dt, animation, s| {
let (state, status, remain) = {
let start_state;
let state = match *s {
None => { start_state = animation.to_state(sprite); &start_state },
Some(ref state) => state,
};
state.update(sprite, dt)
};
*s = state;
(status, remain)
});
match status {
Running => {
new_animations.push((b, a, paused));
},
_ => {},
}
}
if new_animations.len() > 0 {
self.running.insert(id, new_animations);
}
}
}
pub fn draw<B: Graphics<Texture = I>>(&self, t: Matrix2d, b: &mut B) {
for child in self.children.iter() {
child.draw(t, b);
}
}
pub fn draw_tinted<B: Graphics<Texture = I>>(&self, t: Matrix2d, b: &mut B, c: [f32;3]) {
for child in self.children.iter() {
child.draw_tinted(t,b,c)
}
}
pub fn run(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
use std::collections::hash_map::Entry::{ Vacant, Occupied };
let animations = match self.running.entry(sprite_id) {
Vacant(entry) => entry.insert(Vec::new()),
Occupied(entry) => entry.into_mut()
};
let state = State::new(animation.clone());
animations.push((animation.clone(), state, false));
}
fn find(&self, sprite_id: Uuid, animation: &Behavior<Animation>) -> Option<usize> {
let mut index = None;
if let Some(animations) = self.running.get(&sprite_id) {
for i in 0..animations.len() {
let (ref b, _, _) = animations[i];
if b == animation {
index = Some(i);
break;
}
}
}
index
}
pub fn pause(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
if let Some(index) = self.find(sprite_id, animation) {
let animations = self.running.get_mut(&sprite_id).unwrap();
let (b, s, _) = animations.remove(index);
animations.push((b, s, true));
}
}
pub fn resume(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
if let Some(index) = self.find(sprite_id, animation) {
let animations = self.running.get_mut(&sprite_id).unwrap();
let (b, s, _) = animations.remove(index);
animations.push((b, s, false));
}
}
pub fn toggle(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
if let Some(index) = self.find(sprite_id, animation) {
let animations = self.running.get_mut(&sprite_id).unwrap();
let (b, s, paused) = animations.remove(index);
animations.push((b, s, !paused));
}
}
pub fn stop(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
if let Some(index) = self.find(sprite_id, animation) {
self.running.get_mut(&sprite_id).unwrap().remove(index);
}
}
pub fn stop_all(&mut self, sprite_id: Uuid) {
self.running.remove(&sprite_id);
}
pub fn running(&self) -> usize {
let mut total = 0;
for (_, animations) in self.running.iter() {
total += animations.len();
}
total
}
pub fn add_child(&mut self, sprite: Sprite<I>) -> Uuid {
let id = sprite.id();
self.children.push(sprite);
self.children_index.insert(id.clone(), self.children.len() - 1);
id
}
fn stop_all_including_children(&mut self, sprite: &Sprite<I>) {
self.stop_all(sprite.id());
for child in sprite.children().iter() {
self.stop_all_including_children(child);
}
}
pub fn remove_child(&mut self, id: Uuid) -> Option<Sprite<I>> {
let removed = if let Some(index) = self.children_index.remove(&id) {
let removed = self.children.remove(index);
for i in index..self.children.len() {
let uuid = self.children[i].id();
self.children_index.insert(uuid, i);
}
Some(removed)
} else {
for child in self.children.iter_mut() {
if let Some(c) = child.remove_child(id.clone()) {
return Some(c);
}
}
None
};
if removed.is_some() {
self.stop_all_including_children(removed.as_ref().unwrap());
}
removed
}
pub fn child(&self, id: Uuid) -> Option<&Sprite<I>> {
if let Some(index) = self.children_index.get(&id) {
Some(&self.children[*index])
} else {
for child in self.children.iter() {
if let Some(c) = child.child(id.clone()) {
return Some(c);
}
}
None
}
}
pub fn child_mut(&mut self, id: Uuid) -> Option<&mut Sprite<I>> {
if let Some(index) = self.children_index.get(&id) {
Some(&mut self.children[*index])
} else {
for child in self.children.iter_mut() {
if let Some(c) = child.child_mut(id.clone()) {
return Some(c);
}
}
None
}
}
}