use crate::prelude::*;
use beet_core::prelude::*;
use bevy::ecs::component::Immutable;
use bevy::ecs::component::StorageType;
use bevy::ecs::lifecycle::ComponentHook;
use bevy::reflect::Reflectable;
#[derive(Debug, Clone, Resource, Deref)]
pub struct ClientIslandRegistry(SceneFilter);
impl Default for ClientIslandRegistry {
fn default() -> Self {
Self(
SceneFilter::default()
.allow::<ClientLoadDirective>()
.allow::<ClientOnlyDirective>()
.allow::<DomIdx>()
.allow::<NodeTag>(),
)
}
}
impl ClientIslandRegistry {
pub fn add<T: Component>(&mut self) -> &mut Self {
self.0 = self.0.clone().allow::<T>();
self
}
pub fn filter(&self) -> SceneFilter { self.0.clone() }
}
#[derive(Debug, Clone, Reflect)]
#[reflect(Component)]
pub struct ClientIslandRoot<T, U = T>
where
T: 'static + Send + Sync + FromReflect + Reflectable + IntoBundle<U>,
U: 'static + Send + Sync + TypePath,
{
value: T,
#[reflect(ignore)]
phantom: std::marker::PhantomData<U>,
}
impl<T, U> ClientIslandRoot<T, U>
where
T: 'static + Send + Sync + FromReflect + Reflectable + IntoBundle<U>,
U: 'static + Send + Sync + TypePath,
{
pub fn new(value: T) -> impl Bundle {
Self {
value,
phantom: std::marker::PhantomData,
}
}
}
impl<T, U> Component for ClientIslandRoot<T, U>
where
T: 'static + Send + Sync + FromReflect + Reflectable + IntoBundle<U>,
U: 'static + Send + Sync + TypePath,
{
const STORAGE_TYPE: StorageType = StorageType::Table;
type Mutability = Immutable;
fn on_add() -> Option<ComponentHook> {
Some(|mut world, cx| {
let entity = cx.entity;
world.commands().queue(move |world: &mut World| {
if let Ok(mut registry) =
world.resource::<AppTypeRegistry>().internal.try_write()
{
registry.register::<Self>();
}
world.resource_mut::<ClientIslandRegistry>().add::<Self>();
let this = world.entity(entity).get::<Self>().unwrap();
let dynamic: Box<dyn PartialReflect> = this.value.to_dynamic();
let value =
<T as FromReflect>::from_reflect(&*dynamic).unwrap();
world.entity_mut(entity).insert((
BeetRoot,
TemplateRoot::spawn(Spawn(value.into_bundle())),
));
});
})
}
}