use std::collections::HashSet;
use crate::event::{Builder, Event, EventManager};
use crate::object::{Context, Factory, ObjectRef, Storage, Tree};
use crate::scene::{Interface, ObjectContext};
use crate::scene::state::{State, Common};
use crate::system::Update;
pub struct Scene<I: Interface> {
state: ObjectContext<I>,
objects: Storage<ObjectContext<I>>,
updatable: HashSet<ObjectRef>,
init_updatable: HashSet<ObjectRef>
}
impl<I: Interface> Scene<I>
{
pub fn new(component_manager: I::ComponentManager, systems: I::SystemManager) -> Scene<I> {
return Scene {
state: State {
common: Common {
component_manager,
event_manager: EventManager::new(),
system_event_manager: EventManager::new(),
tree: Tree::new()
},
systems
},
objects: Storage::new(),
updatable: HashSet::new(),
init_updatable: HashSet::new()
};
}
fn object_event_call(&mut self, state: &I::AppState, obj_ref: ObjectRef, event: &Event<I::Event>)
{
if !self.state.common.tree.is_enabled(obj_ref) {
return;
}
let obj = &mut self.objects[obj_ref];
obj.on_event(&mut self.state, state, &event);
}
fn handle_system_event(&mut self, state: &I::AppState, ev: Event<super::event::Event<ObjectContext<I>>>)
{
let sender = ev.sender();
let target = ev.target();
let inner = ev.into_inner();
match inner.ty {
super::event::Type::EnableObject(flag) => {
let target = target.expect("No target given to EnableObject");
self.state.common.tree.set_enabled(target, flag);
if !flag {
self.updatable.remove(&target);
} else if flag && self.init_updatable.contains(&target) {
self.updatable.insert(target);
}
},
super::event::Type::SpawnObject(obj) => {
let updatable = obj.updates();
let (obj_ref, obj) = self.objects.insert(|this_ref| obj.invoke(&mut self.state, state, this_ref));
self.state.common.tree.insert(obj_ref, obj.class());
if updatable {
self.updatable.insert(obj_ref);
self.init_updatable.insert(obj_ref);
}
},
super::event::Type::RemoveObject => {
let target = target.expect("No target given to RemoveObject");
self.objects[target].on_remove(&mut self.state, state);
self.state.common.tree.remove(target, self.objects[target].class());
self.objects.destroy(target);
}
};
if inner.notify {
match sender {
None => {
}
Some(_target) => {
}
}
}
}
pub fn update(&mut self, state: &I::AppState)
{
self.state.systems.update(&mut self.state.common, state);
while let Some(ev) = self.state.common.system_event_manager.poll() {
self.handle_system_event(state, ev);
}
for obj in &self.updatable {
self.objects[*obj].on_update(&mut self.state, state);
}
while let Some(event) = self.state.common.event_manager.poll() {
if let Some(obj_ref) = event.target() {
self.object_event_call(state, obj_ref, &event);
} else {
for (obj_ref, obj) in self.objects.objects().enumerate() {
if let Some(o) = obj.as_mut() {
if self.state.common.tree.is_enabled(obj_ref as ObjectRef) {
o.on_event(&mut self.state, state, &event);
}
}
}
}
}
}
pub fn spawn_object(&mut self, factory: Factory<ObjectContext<I>>)
{
let ev = super::event::Event {
notify: false,
ty: super::event::Type::SpawnObject(factory)
};
self.state.common.system_event_manager.send(Builder::new(ev));
}
pub fn state_mut(&mut self) -> &mut impl Context {
&mut self.state
}
pub fn state(&self) -> & impl Context {
&self.state
}
pub fn consume(self) -> I::ComponentManager
{
return self.state.common.component_manager;
}
}