use std::cell::{RefCell, RefMut};
use crate::{support::nameof, Scene};
pub struct World {
scene: Option<Scene>,
resources: Vec<Box<dyn WorldResource>>,
}
impl World {
pub fn new() -> Self {
return Self {
scene: None,
resources: vec![],
};
}
pub fn set_scene(&mut self, scene: Scene) {
self.scene = Some(scene);
}
pub fn insert_resource<T: 'static>(&mut self, resource: T) {
for r in &self.resources {
if r.as_any().is::<T>() {
panic!("World already has resource of type: {}", nameof(&resource));
}
}
self.resources.push(Box::new(RefCell::new(resource)));
}
pub fn get_resource<T: 'static>(&self) -> Option<RefMut<T>> {
for r in &self.resources {
if let Some(r) = r.as_any().downcast_ref::<RefCell<T>>() {
return Some(r.borrow_mut());
}
}
return None;
}
pub fn tick_systems(&mut self, tag: &str) {
let mut scene = self.scene.take().expect("Scene not set in world.");
scene.tick_systems(tag, self);
if self.scene.is_none() {
self.scene = Some(scene);
}
}
pub fn dispatch_event(&mut self, tag: &str, data: &dyn std::any::Any) {
let mut scene = self.scene.take().expect("Scene not set in world.");
scene.dispatch_event(tag, self, data);
if self.scene.is_none() {
self.scene = Some(scene);
}
}
}
pub trait WorldResource {
fn as_any(&self) -> &dyn std::any::Any;
fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
}
impl<T: 'static> WorldResource for RefCell<T> {
fn as_any(&self) -> &dyn std::any::Any {
return self;
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
return self;
}
}