1#[cfg(feature = "ghost_nodes")]
4use crate::ui_node::ComputedUiTargetCamera;
5use crate::Node;
6#[cfg(feature = "ghost_nodes")]
7use bevy_camera::visibility::Visibility;
8use bevy_ecs::{prelude::*, system::SystemParam};
9#[cfg(feature = "ghost_nodes")]
10use bevy_reflect::prelude::*;
11#[cfg(feature = "ghost_nodes")]
12use bevy_transform::prelude::Transform;
13#[cfg(feature = "ghost_nodes")]
14use smallvec::SmallVec;
15#[cfg(feature = "ghost_nodes")]
21#[derive(#[doc =
"**Required Components**: [`Visibility`], [`Transform`], [`ComputedUiTargetCamera`]. \n\n A component's Required Components are inserted whenever it is inserted. Note that this will also insert the required components _of_ the required components, recursively, in depth-first order."]
impl bevy_ecs::component::Component for GhostNode where
Self: ::core::marker::Send + ::core::marker::Sync + 'static {
const STORAGE_TYPE: bevy_ecs::component::StorageType =
bevy_ecs::component::StorageType::Table;
type Mutability = bevy_ecs::component::Mutable;
fn register_required_components(_requiree:
bevy_ecs::component::ComponentId,
required_components:
&mut bevy_ecs::component::RequiredComponentsRegistrator) {
required_components.register_required::<Visibility>(<Visibility as
::core::default::Default>::default);
required_components.register_required::<Transform>(<Transform as
::core::default::Default>::default);
required_components.register_required::<ComputedUiTargetCamera>(<ComputedUiTargetCamera
as ::core::default::Default>::default);
}
fn clone_behavior() -> bevy_ecs::component::ComponentCloneBehavior {
use bevy_ecs::component::{
DefaultCloneBehaviorBase, DefaultCloneBehaviorViaClone,
};
(&&&bevy_ecs::component::DefaultCloneBehaviorSpecialization::<Self>::default()).default_clone_behavior()
}
fn relationship_accessor()
->
::core::option::Option<bevy_ecs::relationship::ComponentRelationshipAccessor<Self>> {
::core::option::Option::None
}
}Component, #[automatically_derived]
impl ::core::fmt::Debug for GhostNode {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "GhostNode")
}
}Debug, #[automatically_derived]
impl ::core::marker::Copy for GhostNode { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for GhostNode { }
#[automatically_derived]
impl ::core::clone::Clone for GhostNode {
#[inline]
fn clone(&self) -> Self { *self }
}Clone, const _: () =
{
impl bevy_reflect::GetTypeRegistration for GhostNode where {
fn get_type_registration() -> bevy_reflect::TypeRegistration {
let mut registration =
bevy_reflect::TypeRegistration::of::<Self>();
registration.insert(<bevy_reflect::ReflectFromPtr as
bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
registration.insert(<bevy_reflect::ReflectFromReflect as
bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
registration.register_type_data_with::<ReflectComponent, Self,
_>(());
registration
}
#[inline(never)]
fn register_type_dependencies(registry:
&mut bevy_reflect::TypeRegistry) {}
}
impl bevy_reflect::Typed for GhostNode where {
#[inline(never)]
fn type_info() -> &'static bevy_reflect::TypeInfo {
static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
bevy_reflect::utility::NonGenericTypeInfoCell::new();
CELL.get_or_set(#[inline(never)] ||
{
bevy_reflect::TypeInfo::Struct(bevy_reflect::structs::StructInfo::new::<Self>(&[]))
})
}
}
#[allow(deprecated, reason =
"derives on a deprecated type shouldn't be considered a usage")]
impl bevy_reflect::TypePath for GhostNode where {
fn type_path() -> &'static str {
"bevy_ui::experimental::ghost_hierarchy::GhostNode"
}
fn short_type_path() -> &'static str { "GhostNode" }
fn type_ident() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("GhostNode")
}
fn crate_name() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("bevy_ui::experimental::ghost_hierarchy".split(':').next().unwrap())
}
fn module_path() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("bevy_ui::experimental::ghost_hierarchy")
}
}
impl bevy_reflect::Reflect for GhostNode where {
#[inline]
fn into_any(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
self
}
#[inline]
fn as_any(&self) -> &dyn ::core::any::Any { self }
#[inline]
fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
#[inline]
fn into_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
self
}
#[inline]
fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
#[inline]
fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
self
}
#[inline]
fn set(&mut self,
value:
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
->
::core::result::Result<(),
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
*self = <dyn bevy_reflect::Reflect>::take(value)?;
::core::result::Result::Ok(())
}
}
#[allow(non_upper_case_globals)]
const _: () =
{
static __INVENTORY: ::inventory::Node =
::inventory::Node {
value: &{
bevy_reflect::__macro_exports::auto_register::AutomaticReflectRegistrations(<GhostNode
as
bevy_reflect::__macro_exports::auto_register::RegisterForReflection>::__register)
},
next: ::inventory::__private::UnsafeCell::new(::inventory::__private::Option::None),
};
#[link_section = ".text.startup"]
unsafe extern "C" fn __ctor() {
unsafe {
::inventory::ErasedNode::submit(__INVENTORY.value,
&__INVENTORY)
}
}
#[used]
#[link_section = ".init_array"]
static __CTOR: unsafe extern "C" fn() = __ctor;
};
impl bevy_reflect::structs::Struct for GhostNode where {
fn field(&self, name: &str)
-> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
match name { _ => ::core::option::Option::None, }
}
fn field_mut(&mut self, name: &str)
->
::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
match name { _ => ::core::option::Option::None, }
}
fn field_at(&self, index: usize)
-> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
match index { _ => ::core::option::Option::None, }
}
fn field_at_mut(&mut self, index: usize)
->
::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
match index { _ => ::core::option::Option::None, }
}
fn name_at(&self, index: usize) -> ::core::option::Option<&str> {
match index { _ => ::core::option::Option::None, }
}
fn index_of_name(&self, name: &str)
-> ::core::option::Option<usize> {
match name { _ => ::core::option::Option::None, }
}
fn field_len(&self) -> usize { 0usize }
fn iter_fields(&self) -> bevy_reflect::structs::FieldIter {
bevy_reflect::structs::FieldIter::new(self)
}
fn to_dynamic_struct(&self)
->
::core::result::Result<bevy_reflect::structs::DynamicStruct,
bevy_reflect::ReflectCloneError> {
let mut dynamic: bevy_reflect::structs::DynamicStruct =
::core::default::Default::default();
dynamic.set_represented_type(bevy_reflect::PartialReflect::get_represented_type_info(self));
::core::result::Result::Ok(dynamic)
}
}
impl bevy_reflect::PartialReflect for GhostNode where {
#[inline]
fn get_represented_type_info(&self)
-> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
::core::option::Option::Some(<Self as
bevy_reflect::Typed>::type_info())
}
#[inline]
fn try_apply(&mut self, value: &dyn bevy_reflect::PartialReflect)
-> ::core::result::Result<(), bevy_reflect::ApplyError> {
if let bevy_reflect::ReflectRef::Struct(struct_value) =
bevy_reflect::PartialReflect::reflect_ref(value) {
for (name, value) in
bevy_reflect::structs::Struct::iter_fields(struct_value) {
if let ::core::option::Option::Some(v) =
bevy_reflect::structs::Struct::field_mut(self, name) {
bevy_reflect::PartialReflect::try_apply(v, value)?;
}
}
} else {
return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
from_kind: bevy_reflect::PartialReflect::reflect_kind(value),
to_kind: bevy_reflect::ReflectKind::Struct,
});
}
::core::result::Result::Ok(())
}
#[inline]
fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
bevy_reflect::ReflectKind::Struct
}
#[inline]
fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
bevy_reflect::ReflectRef::Struct(self)
}
#[inline]
fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
bevy_reflect::ReflectMut::Struct(self)
}
#[inline]
fn reflect_owned(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
-> bevy_reflect::ReflectOwned {
bevy_reflect::ReflectOwned::Struct(self)
}
#[inline]
fn try_into_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
::core::result::Result::Ok(self)
}
#[inline]
fn try_as_reflect(&self)
-> ::core::option::Option<&dyn bevy_reflect::Reflect> {
::core::option::Option::Some(self)
}
#[inline]
fn try_as_reflect_mut(&mut self)
-> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
::core::option::Option::Some(self)
}
#[inline]
fn into_partial_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
self
}
#[inline]
fn as_partial_reflect(&self)
-> &dyn bevy_reflect::PartialReflect {
self
}
#[inline]
fn as_partial_reflect_mut(&mut self)
-> &mut dyn bevy_reflect::PartialReflect {
self
}
fn reflect_partial_eq(&self,
value: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<bool> {
(bevy_reflect::structs::struct_partial_eq)(self, value)
}
fn reflect_partial_cmp(&self,
value: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<::core::cmp::Ordering> {
(bevy_reflect::structs::struct_partial_cmp)(self, value)
}
fn debug(&self, f: &mut ::core::fmt::Formatter<'_>)
-> ::core::fmt::Result {
::core::fmt::Debug::fmt(self, f)
}
#[inline]
fn reflect_clone(&self)
->
::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
bevy_reflect::ReflectCloneError> {
::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(::core::clone::Clone::clone(self)))
}
}
impl bevy_reflect::FromReflect for GhostNode where {
fn from_reflect(reflect: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<Self> {
if let bevy_reflect::ReflectRef::Struct(__ref_struct) =
bevy_reflect::PartialReflect::reflect_ref(reflect) {
let __this = Self {};
::core::option::Option::Some(__this)
} else { ::core::option::Option::None }
}
}
};Reflect)]
22#[cfg_attr(feature = "ghost_nodes", derive(#[automatically_derived]
impl ::core::default::Default for GhostNode {
#[inline]
fn default() -> Self { Self }
}Default))]
23#[reflect(Component, Debug, Clone)]
24#[require(Visibility, Transform, ComputedUiTargetCamera)]
25pub struct GhostNode;
26
27#[cfg(feature = "ghost_nodes")]
28#[derive(const _: () =
{
type __StructFieldsAlias<'w, 's> =
(Query<'w, 's, Entity, (With<Node>, Without<ChildOf>)>,
Query<'w, 's, Entity, (With<GhostNode>, Without<ChildOf>)>,
Query<'w, 's, Entity, With<Node>>, UiChildren<'w, 's>);
#[doc(hidden)]
pub struct FetchState {
state: <__StructFieldsAlias<'static, 'static> as
bevy_ecs::system::SystemParam>::State,
}
unsafe impl bevy_ecs::system::SystemParam for UiRootNodes<'_, '_> {
type State = FetchState<>;
type Item<'w, 's> = UiRootNodes<'w, 's>;
fn init_state(world: &mut bevy_ecs::world::World) -> Self::State {
FetchState {
state: <__StructFieldsAlias<'_, '_> as
bevy_ecs::system::SystemParam>::init_state(world),
}
}
fn init_access(state: &Self::State,
system_meta: &mut bevy_ecs::system::SystemMeta,
system_access: &mut bevy_ecs::system::SystemAccess,
world: &mut bevy_ecs::world::World) {
<__StructFieldsAlias<'_, '_> as
bevy_ecs::system::SystemParam>::init_access(&state.state,
system_meta, system_access, world);
}
fn apply(state: &mut Self::State,
system_meta: &bevy_ecs::system::SystemMeta,
world: &mut bevy_ecs::world::World) {
<__StructFieldsAlias<'_, '_> as
bevy_ecs::system::SystemParam>::apply(&mut state.state,
system_meta, world);
}
fn queue(state: &mut Self::State,
system_meta: &bevy_ecs::system::SystemMeta,
world: bevy_ecs::world::DeferredWorld) {
<__StructFieldsAlias<'_, '_> as
bevy_ecs::system::SystemParam>::queue(&mut state.state,
system_meta, world);
}
#[inline]
unsafe fn get_param<'w,
's>(state: &'s mut Self::State,
system_meta: &bevy_ecs::system::SystemMeta,
world:
bevy_ecs::world::unsafe_world_cell::UnsafeWorldCell<'w>,
change_tick: bevy_ecs::change_detection::Tick)
->
::core::result::Result<Self::Item<'w, 's>,
bevy_ecs::system::SystemParamValidationError> {
let (fieldroot_node_query, fieldroot_ghost_node_query,
fieldall_nodes_query, fieldui_children) = &mut state.state;
let fieldroot_node_query =
unsafe {
<Query<'w, 's, Entity, (With<Node>, Without<ChildOf>)> as
bevy_ecs::system::SystemParam>::get_param(fieldroot_node_query,
system_meta, world, change_tick)
}.map_err(|err|
bevy_ecs::system::SystemParamValidationError::new::<Self>(err.skipped,
err.message, "::root_node_query"))?;
let fieldroot_ghost_node_query =
unsafe {
<Query<'w, 's, Entity, (With<GhostNode>, Without<ChildOf>)>
as
bevy_ecs::system::SystemParam>::get_param(fieldroot_ghost_node_query,
system_meta, world, change_tick)
}.map_err(|err|
bevy_ecs::system::SystemParamValidationError::new::<Self>(err.skipped,
err.message, "::root_ghost_node_query"))?;
let fieldall_nodes_query =
unsafe {
<Query<'w, 's, Entity, With<Node>> as
bevy_ecs::system::SystemParam>::get_param(fieldall_nodes_query,
system_meta, world, change_tick)
}.map_err(|err|
bevy_ecs::system::SystemParamValidationError::new::<Self>(err.skipped,
err.message, "::all_nodes_query"))?;
let fieldui_children =
unsafe {
<UiChildren<'w, 's> as
bevy_ecs::system::SystemParam>::get_param(fieldui_children,
system_meta, world, change_tick)
}.map_err(|err|
bevy_ecs::system::SystemParamValidationError::new::<Self>(err.skipped,
err.message, "::ui_children"))?;
::core::result::Result::Ok(UiRootNodes {
root_node_query: fieldroot_node_query,
root_ghost_node_query: fieldroot_ghost_node_query,
all_nodes_query: fieldall_nodes_query,
ui_children: fieldui_children,
})
}
}
unsafe impl<'w, 's> bevy_ecs::system::ReadOnlySystemParam for
UiRootNodes<'w, 's> where
Query<'w, 's, Entity,
(With<Node>,
Without<ChildOf>)>: bevy_ecs::system::ReadOnlySystemParam,
Query<'w, 's, Entity,
(With<GhostNode>,
Without<ChildOf>)>: bevy_ecs::system::ReadOnlySystemParam,
Query<'w, 's, Entity,
With<Node>>: bevy_ecs::system::ReadOnlySystemParam,
UiChildren<'w, 's>: bevy_ecs::system::ReadOnlySystemParam {}
};SystemParam)]
32pub struct UiRootNodes<'w, 's> {
33 root_node_query: Query<'w, 's, Entity, (With<Node>, Without<ChildOf>)>,
34 root_ghost_node_query: Query<'w, 's, Entity, (With<GhostNode>, Without<ChildOf>)>,
35 all_nodes_query: Query<'w, 's, Entity, With<Node>>,
36 ui_children: UiChildren<'w, 's>,
37}
38
39#[cfg(not(feature = "ghost_nodes"))]
40pub type UiRootNodes<'w, 's> = Query<'w, 's, Entity, (With<Node>, Without<ChildOf>)>;
41
42#[cfg(feature = "ghost_nodes")]
43impl<'w, 's> UiRootNodes<'w, 's> {
44 pub fn iter(&'s self) -> impl Iterator<Item = Entity> + 's {
45 self.root_node_query
46 .iter()
47 .chain(self.root_ghost_node_query.iter().flat_map(|root_ghost| {
48 self.all_nodes_query
49 .iter_many(self.ui_children.iter_ui_children(root_ghost))
50 .matched()
51 }))
52 }
53}
54
55#[cfg(feature = "ghost_nodes")]
56#[derive(const _: () =
{
type __StructFieldsAlias<'w, 's> =
(Query<'w, 's, (Option<&'static Children>, Has<GhostNode>),
Or<(With<Node>, With<GhostNode>)>>,
Query<'w, 's, Entity, Changed<Children>>,
Query<'w, 's, &'static Children>,
Query<'w, 's, Entity, With<GhostNode>>,
Query<'w, 's, &'static ChildOf>);
#[doc(hidden)]
pub struct FetchState {
state: <__StructFieldsAlias<'static, 'static> as
bevy_ecs::system::SystemParam>::State,
}
unsafe impl bevy_ecs::system::SystemParam for UiChildren<'_, '_> {
type State = FetchState<>;
type Item<'w, 's> = UiChildren<'w, 's>;
fn init_state(world: &mut bevy_ecs::world::World) -> Self::State {
FetchState {
state: <__StructFieldsAlias<'_, '_> as
bevy_ecs::system::SystemParam>::init_state(world),
}
}
fn init_access(state: &Self::State,
system_meta: &mut bevy_ecs::system::SystemMeta,
system_access: &mut bevy_ecs::system::SystemAccess,
world: &mut bevy_ecs::world::World) {
<__StructFieldsAlias<'_, '_> as
bevy_ecs::system::SystemParam>::init_access(&state.state,
system_meta, system_access, world);
}
fn apply(state: &mut Self::State,
system_meta: &bevy_ecs::system::SystemMeta,
world: &mut bevy_ecs::world::World) {
<__StructFieldsAlias<'_, '_> as
bevy_ecs::system::SystemParam>::apply(&mut state.state,
system_meta, world);
}
fn queue(state: &mut Self::State,
system_meta: &bevy_ecs::system::SystemMeta,
world: bevy_ecs::world::DeferredWorld) {
<__StructFieldsAlias<'_, '_> as
bevy_ecs::system::SystemParam>::queue(&mut state.state,
system_meta, world);
}
#[inline]
unsafe fn get_param<'w,
's>(state: &'s mut Self::State,
system_meta: &bevy_ecs::system::SystemMeta,
world:
bevy_ecs::world::unsafe_world_cell::UnsafeWorldCell<'w>,
change_tick: bevy_ecs::change_detection::Tick)
->
::core::result::Result<Self::Item<'w, 's>,
bevy_ecs::system::SystemParamValidationError> {
let (fieldui_children_query, fieldchanged_children_query,
fieldchildren_query, fieldghost_nodes_query,
fieldparents_query) = &mut state.state;
let fieldui_children_query =
unsafe {
<Query<'w, 's, (Option<&'static Children>, Has<GhostNode>),
Or<(With<Node>, With<GhostNode>)>> as
bevy_ecs::system::SystemParam>::get_param(fieldui_children_query,
system_meta, world, change_tick)
}.map_err(|err|
bevy_ecs::system::SystemParamValidationError::new::<Self>(err.skipped,
err.message, "::ui_children_query"))?;
let fieldchanged_children_query =
unsafe {
<Query<'w, 's, Entity, Changed<Children>> as
bevy_ecs::system::SystemParam>::get_param(fieldchanged_children_query,
system_meta, world, change_tick)
}.map_err(|err|
bevy_ecs::system::SystemParamValidationError::new::<Self>(err.skipped,
err.message, "::changed_children_query"))?;
let fieldchildren_query =
unsafe {
<Query<'w, 's, &'static Children> as
bevy_ecs::system::SystemParam>::get_param(fieldchildren_query,
system_meta, world, change_tick)
}.map_err(|err|
bevy_ecs::system::SystemParamValidationError::new::<Self>(err.skipped,
err.message, "::children_query"))?;
let fieldghost_nodes_query =
unsafe {
<Query<'w, 's, Entity, With<GhostNode>> as
bevy_ecs::system::SystemParam>::get_param(fieldghost_nodes_query,
system_meta, world, change_tick)
}.map_err(|err|
bevy_ecs::system::SystemParamValidationError::new::<Self>(err.skipped,
err.message, "::ghost_nodes_query"))?;
let fieldparents_query =
unsafe {
<Query<'w, 's, &'static ChildOf> as
bevy_ecs::system::SystemParam>::get_param(fieldparents_query,
system_meta, world, change_tick)
}.map_err(|err|
bevy_ecs::system::SystemParamValidationError::new::<Self>(err.skipped,
err.message, "::parents_query"))?;
::core::result::Result::Ok(UiChildren {
ui_children_query: fieldui_children_query,
changed_children_query: fieldchanged_children_query,
children_query: fieldchildren_query,
ghost_nodes_query: fieldghost_nodes_query,
parents_query: fieldparents_query,
})
}
}
unsafe impl<'w, 's> bevy_ecs::system::ReadOnlySystemParam for
UiChildren<'w, 's> where
Query<'w, 's, (Option<&'static Children>, Has<GhostNode>),
Or<(With<Node>,
With<GhostNode>)>>: bevy_ecs::system::ReadOnlySystemParam,
Query<'w, 's, Entity,
Changed<Children>>: bevy_ecs::system::ReadOnlySystemParam,
Query<'w, 's,
&'static Children>: bevy_ecs::system::ReadOnlySystemParam,
Query<'w, 's, Entity,
With<GhostNode>>: bevy_ecs::system::ReadOnlySystemParam,
Query<'w, 's,
&'static ChildOf>: bevy_ecs::system::ReadOnlySystemParam {}
};SystemParam)]
58pub struct UiChildren<'w, 's> {
59 ui_children_query: Query<
60 'w,
61 's,
62 (Option<&'static Children>, Has<GhostNode>),
63 Or<(With<Node>, With<GhostNode>)>,
64 >,
65 changed_children_query: Query<'w, 's, Entity, Changed<Children>>,
66 children_query: Query<'w, 's, &'static Children>,
67 ghost_nodes_query: Query<'w, 's, Entity, With<GhostNode>>,
68 parents_query: Query<'w, 's, &'static ChildOf>,
69}
70
71#[cfg(not(feature = "ghost_nodes"))]
72#[derive(SystemParam)]
74pub struct UiChildren<'w, 's> {
75 ui_children_query: Query<'w, 's, Option<&'static Children>, With<Node>>,
76 changed_children_query: Query<'w, 's, Entity, Changed<Children>>,
77 parents_query: Query<'w, 's, &'static ChildOf>,
78}
79
80#[cfg(feature = "ghost_nodes")]
81impl<'w, 's> UiChildren<'w, 's> {
82 pub fn iter_ui_children(&'s self, entity: Entity) -> UiChildrenIter<'w, 's> {
90 UiChildrenIter {
91 stack: self
92 .ui_children_query
93 .get(entity)
94 .map_or(SmallVec::new(), |(children, _)| {
95 children.into_iter().flatten().rev().copied().collect()
96 }),
97 query: &self.ui_children_query,
98 }
99 }
100
101 pub fn get_parent(&'s self, entity: Entity) -> Option<Entity> {
103 self.parents_query
104 .iter_ancestors(entity)
105 .find(|entity| !self.ghost_nodes_query.contains(*entity))
106 }
107
108 pub fn iter_ghost_nodes(&'s self, entity: Entity) -> Box<dyn Iterator<Item = Entity> + 's> {
110 Box::new(
111 self.children_query
112 .get(entity)
113 .into_iter()
114 .flat_map(|children| {
115 self.ghost_nodes_query
116 .iter_many(children)
117 .matched()
118 .flat_map(|entity| {
119 core::iter::once(entity).chain(self.iter_ghost_nodes(entity))
120 })
121 }),
122 )
123 }
124
125 pub fn is_changed(&'s self, entity: Entity) -> bool {
127 self.changed_children_query.contains(entity)
128 || self
129 .iter_ghost_nodes(entity)
130 .any(|entity| self.changed_children_query.contains(entity))
131 }
132
133 pub fn is_ui_node(&'s self, entity: Entity) -> bool {
135 self.ui_children_query.contains(entity)
136 }
137}
138
139#[cfg(not(feature = "ghost_nodes"))]
140impl<'w, 's> UiChildren<'w, 's> {
141 pub fn iter_ui_children(&'s self, entity: Entity) -> impl Iterator<Item = Entity> + 's {
143 self.ui_children_query
144 .get(entity)
145 .ok()
146 .flatten()
147 .map(|children| children.as_ref())
148 .unwrap_or(&[])
149 .iter()
150 .copied()
151 }
152
153 pub fn get_parent(&'s self, entity: Entity) -> Option<Entity> {
155 self.parents_query.get(entity).ok().map(ChildOf::parent)
156 }
157
158 pub fn is_changed(&'s self, entity: Entity) -> bool {
160 self.changed_children_query.contains(entity)
161 }
162
163 pub fn is_ui_node(&'s self, entity: Entity) -> bool {
165 self.ui_children_query.contains(entity)
166 }
167}
168
169#[cfg(feature = "ghost_nodes")]
170pub struct UiChildrenIter<'w, 's> {
171 stack: SmallVec<[Entity; 8]>,
172 query: &'s Query<
173 'w,
174 's,
175 (Option<&'static Children>, Has<GhostNode>),
176 Or<(With<Node>, With<GhostNode>)>,
177 >,
178}
179
180#[cfg(feature = "ghost_nodes")]
181impl<'w, 's> Iterator for UiChildrenIter<'w, 's> {
182 type Item = Entity;
183 fn next(&mut self) -> Option<Self::Item> {
184 loop {
185 let entity = self.stack.pop()?;
186 if let Ok((children, has_ghost_node)) = self.query.get(entity) {
187 if !has_ghost_node {
188 return Some(entity);
189 }
190 if let Some(children) = children {
191 self.stack.extend(children.iter().rev());
192 }
193 }
194 }
195 }
196}
197
198#[cfg(all(test, feature = "ghost_nodes"))]
199mod tests {
200 use bevy_ecs::{
201 prelude::Component,
202 system::{Query, SystemState},
203 world::World,
204 };
205
206 use super::{GhostNode, Node, UiChildren, UiRootNodes};
207
208 #[derive(Component, PartialEq, Debug)]
209 struct A(usize);
210
211 #[test]
212 fn iterate_ui_root_nodes() {
213 let world = &mut World::new();
214
215 world
217 .spawn((A(1), Node::default()))
218 .with_children(|parent| {
219 parent.spawn((A(2), Node::default()));
220 parent
221 .spawn((A(3), GhostNode))
222 .with_child((A(4), Node::default()));
223 });
224
225 world.spawn((A(5), GhostNode)).with_children(|parent| {
227 parent.spawn((A(6), Node::default()));
228 parent
229 .spawn((A(7), GhostNode))
230 .with_child((A(8), Node::default()))
231 .with_child(A(9));
232 });
233
234 let mut system_state = SystemState::<(UiRootNodes, Query<&A>)>::new(world);
235 let (ui_root_nodes, a_query) = system_state.get(world).unwrap();
236
237 let result: Vec<_> = a_query.iter_many(ui_root_nodes.iter()).matched().collect();
238
239 assert_eq!([&A(1), &A(6), &A(8)], result.as_slice());
240 }
241
242 #[test]
243 fn iterate_ui_children() {
244 let world = &mut World::new();
245
246 let n1 = world.spawn((A(1), Node::default())).id();
247 let n2 = world.spawn((A(2), GhostNode)).id();
248 let n3 = world.spawn((A(3), GhostNode)).id();
249 let n4 = world.spawn((A(4), Node::default())).id();
250 let n5 = world.spawn((A(5), Node::default())).id();
251
252 let n6 = world.spawn((A(6), GhostNode)).id();
253 let n7 = world.spawn((A(7), GhostNode)).id();
254 let n8 = world.spawn((A(8), Node::default())).id();
255 let n9 = world.spawn((A(9), GhostNode)).id();
256 let n10 = world.spawn((A(10), Node::default())).id();
257
258 let no_ui = world.spawn_empty().id();
259
260 world.entity_mut(n1).add_children(&[n2, n3, n4, n6]);
261 world.entity_mut(n2).add_children(&[n5]);
262
263 world.entity_mut(n6).add_children(&[n7, no_ui, n9]);
264 world.entity_mut(n7).add_children(&[n8]);
265 world.entity_mut(n9).add_children(&[n10]);
266
267 let mut system_state = SystemState::<(UiChildren, Query<&A>)>::new(world);
268 let (ui_children, a_query) = system_state.get(world).unwrap();
269
270 let result: Vec<_> = a_query
271 .iter_many(ui_children.iter_ui_children(n1))
272 .matched()
273 .collect();
274
275 assert_eq!([&A(5), &A(4), &A(8), &A(10)], result.as_slice());
276 }
277}