use bevy_ecs::component::Component;
use bevy_ecs::entity::Entity;
use bevy_ecs::lifecycle::HookContext;
use bevy_ecs::prelude::ReflectComponent;
use bevy_ecs::world::DeferredWorld;
use bevy_reflect::Reflect;
#[derive(Component, Reflect, Clone, Copy, Debug, PartialEq, Eq)]
#[reflect(Component)]
#[relationship(relationship_target = GodotChildren)]
pub struct GodotChildOf(pub Entity);
impl GodotChildOf {
#[inline]
pub fn get(&self) -> Entity {
self.0
}
}
#[derive(Component, Reflect, Default, Clone, Debug, PartialEq, Eq)]
#[reflect(Component)]
#[relationship_target(relationship = GodotChildOf)]
#[component(on_despawn = godot_children_on_despawn)]
pub struct GodotChildren(Vec<Entity>);
impl GodotChildren {
#[inline]
pub fn iter(&self) -> impl Iterator<Item = &Entity> {
self.0.iter()
}
#[inline]
pub fn len(&self) -> usize {
self.0.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
#[inline]
pub fn get(&self, index: usize) -> Option<Entity> {
self.0.get(index).copied()
}
#[inline]
pub fn contains(&self, entity: Entity) -> bool {
self.0.contains(&entity)
}
}
fn godot_children_on_despawn(mut world: DeferredWorld, context: HookContext) {
let auto_despawn = world
.get_resource::<super::SceneTreeConfig>()
.map(|config| config.auto_despawn_children)
.unwrap_or(true);
if !auto_despawn {
return;
}
let Some(children) = world.get::<GodotChildren>(context.entity) else {
return;
};
let to_despawn: Vec<Entity> = children
.iter()
.copied()
.filter(|entity| world.get::<super::ProtectedNodeEntity>(*entity).is_none())
.collect();
let mut commands = world.commands();
for entity in to_despawn {
commands.entity(entity).try_despawn();
}
}