use bevy::ecs::observer::Observer;
use bevy::ecs::system::IntoObserverSystem;
use bevy::prelude::*;
use crate::core::element::EasyElement;
pub trait Container<C: Into<EasyElement> = EasyElement>: Sized {
fn take_bundle(&mut self) -> impl Bundle;
fn take_children(&mut self) -> Vec<C>;
fn take_observers(&mut self) -> Vec<Observer>;
fn with_child(mut self, child: impl Into<C>) -> Self
where
Self: PushChild<C>,
{
self.push_child(child.into());
self
}
fn with_observer<E, ObsB, M>(
mut self,
observer: impl IntoObserverSystem<E, ObsB, M> + 'static,
) -> Self
where
Self: PushObserver<C>,
E: Event,
ObsB: Bundle,
{
self.push_observer(Observer::new(observer));
self
}
fn spawn(self, commands: &mut Commands) -> Entity
where
Self: PushChild<C> + PushObserver<C>,
{
spawn_container(self, commands)
}
}
pub trait PushChild<C: Into<EasyElement> = EasyElement>: Container<C> {
fn push_child(&mut self, child: C);
}
pub trait PushObserver<C: Into<EasyElement> = EasyElement>:
Container<C>
{
fn push_observer(&mut self, observer: Observer);
}
fn spawn_container<C: Into<EasyElement>>(
mut c: impl PushChild<C> + PushObserver<C>,
commands: &mut Commands,
) -> Entity {
let bundle = c.take_bundle();
let children = c.take_children();
let observers = c.take_observers();
let entity = commands.spawn(bundle).id();
commands.entity(entity).with_children(|p| {
for child in children {
let el: EasyElement = child.into();
el.spawn_in(p);
}
});
for observer in observers {
commands.spawn(observer.with_entity(entity));
}
entity
}
pub trait WithObservers<C: Into<EasyElement> = EasyElement>: Sized {
fn take_bundle(&mut self) -> impl Bundle;
fn take_observers(&mut self) -> Vec<Observer>;
fn spawn(self, commands: &mut Commands) -> Entity {
spawn(self, commands)
}
}
fn spawn<C: Into<EasyElement>>(
mut c: impl WithObservers<C>,
commands: &mut Commands,
) -> Entity {
let bundle = c.take_bundle();
let observers = c.take_observers();
let entity = commands.spawn(bundle).id();
for observer in observers {
commands.spawn(observer.with_entity(entity));
}
entity
}