Change GhostNode
into a unit type (#17692)
# Objective The feature gates for the `UiChildren` and `UiRootNodes` system params make the unconstructable `GhostNode` `PhantomData` trick redundant. ## Solution Remove the `GhostNode::new` method and change `GhostNode` into a unit struct. ## Testing ```cargo run --example ghost_nodes``` still works
This commit is contained in:
parent
6f39e44c48
commit
6be11a8a42
@ -2,11 +2,13 @@
|
|||||||
|
|
||||||
use crate::Node;
|
use crate::Node;
|
||||||
use bevy_ecs::{prelude::*, system::SystemParam};
|
use bevy_ecs::{prelude::*, system::SystemParam};
|
||||||
use bevy_reflect::prelude::*;
|
|
||||||
use bevy_render::view::Visibility;
|
|
||||||
use bevy_transform::prelude::Transform;
|
|
||||||
use core::marker::PhantomData;
|
|
||||||
|
|
||||||
|
#[cfg(feature = "ghost_nodes")]
|
||||||
|
use bevy_reflect::prelude::*;
|
||||||
|
#[cfg(feature = "ghost_nodes")]
|
||||||
|
use bevy_render::view::Visibility;
|
||||||
|
#[cfg(feature = "ghost_nodes")]
|
||||||
|
use bevy_transform::prelude::Transform;
|
||||||
#[cfg(feature = "ghost_nodes")]
|
#[cfg(feature = "ghost_nodes")]
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
@ -15,30 +17,12 @@ use smallvec::SmallVec;
|
|||||||
/// The UI systems will traverse past these and treat their first non-ghost descendants as direct children of their first non-ghost ancestor.
|
/// The UI systems will traverse past these and treat their first non-ghost descendants as direct children of their first non-ghost ancestor.
|
||||||
///
|
///
|
||||||
/// Any components necessary for transform and visibility propagation will be added automatically.
|
/// Any components necessary for transform and visibility propagation will be added automatically.
|
||||||
///
|
#[cfg(feature = "ghost_nodes")]
|
||||||
/// Instances of this type cannot be constructed unless the `ghost_nodes` feature is enabled.
|
|
||||||
#[derive(Component, Debug, Copy, Clone, Reflect)]
|
#[derive(Component, Debug, Copy, Clone, Reflect)]
|
||||||
#[cfg_attr(feature = "ghost_nodes", derive(Default))]
|
#[cfg_attr(feature = "ghost_nodes", derive(Default))]
|
||||||
#[reflect(Component, Debug)]
|
#[reflect(Component, Debug)]
|
||||||
#[require(Visibility, Transform)]
|
#[require(Visibility, Transform)]
|
||||||
pub struct GhostNode {
|
pub struct GhostNode;
|
||||||
// This is a workaround to ensure that GhostNode is only constructable when the appropriate feature flag is enabled
|
|
||||||
#[reflect(ignore)]
|
|
||||||
unconstructable: PhantomData<()>, // Spooky!
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "ghost_nodes")]
|
|
||||||
impl GhostNode {
|
|
||||||
/// Creates a new ghost node.
|
|
||||||
///
|
|
||||||
/// This method is only available when the `ghost_node` feature is enabled,
|
|
||||||
/// and will eventually be deprecated then removed in favor of simply using `GhostNode` as no meaningful data is stored.
|
|
||||||
pub const fn new() -> Self {
|
|
||||||
GhostNode {
|
|
||||||
unconstructable: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "ghost_nodes")]
|
#[cfg(feature = "ghost_nodes")]
|
||||||
/// System param that allows iteration of all UI root nodes.
|
/// System param that allows iteration of all UI root nodes.
|
||||||
@ -232,20 +216,18 @@ mod tests {
|
|||||||
.with_children(|parent| {
|
.with_children(|parent| {
|
||||||
parent.spawn((A(2), Node::default()));
|
parent.spawn((A(2), Node::default()));
|
||||||
parent
|
parent
|
||||||
.spawn((A(3), GhostNode::new()))
|
.spawn((A(3), GhostNode))
|
||||||
.with_child((A(4), Node::default()));
|
.with_child((A(4), Node::default()));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Ghost root
|
// Ghost root
|
||||||
world
|
world.spawn((A(5), GhostNode)).with_children(|parent| {
|
||||||
.spawn((A(5), GhostNode::new()))
|
parent.spawn((A(6), Node::default()));
|
||||||
.with_children(|parent| {
|
parent
|
||||||
parent.spawn((A(6), Node::default()));
|
.spawn((A(7), GhostNode))
|
||||||
parent
|
.with_child((A(8), Node::default()))
|
||||||
.spawn((A(7), GhostNode::new()))
|
.with_child(A(9));
|
||||||
.with_child((A(8), Node::default()))
|
});
|
||||||
.with_child(A(9));
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut system_state = SystemState::<(UiRootNodes, Query<&A>)>::new(world);
|
let mut system_state = SystemState::<(UiRootNodes, Query<&A>)>::new(world);
|
||||||
let (ui_root_nodes, a_query) = system_state.get(world);
|
let (ui_root_nodes, a_query) = system_state.get(world);
|
||||||
@ -260,15 +242,15 @@ mod tests {
|
|||||||
let world = &mut World::new();
|
let world = &mut World::new();
|
||||||
|
|
||||||
let n1 = world.spawn((A(1), Node::default())).id();
|
let n1 = world.spawn((A(1), Node::default())).id();
|
||||||
let n2 = world.spawn((A(2), GhostNode::new())).id();
|
let n2 = world.spawn((A(2), GhostNode)).id();
|
||||||
let n3 = world.spawn((A(3), GhostNode::new())).id();
|
let n3 = world.spawn((A(3), GhostNode)).id();
|
||||||
let n4 = world.spawn((A(4), Node::default())).id();
|
let n4 = world.spawn((A(4), Node::default())).id();
|
||||||
let n5 = world.spawn((A(5), Node::default())).id();
|
let n5 = world.spawn((A(5), Node::default())).id();
|
||||||
|
|
||||||
let n6 = world.spawn((A(6), GhostNode::new())).id();
|
let n6 = world.spawn((A(6), GhostNode)).id();
|
||||||
let n7 = world.spawn((A(7), GhostNode::new())).id();
|
let n7 = world.spawn((A(7), GhostNode)).id();
|
||||||
let n8 = world.spawn((A(8), Node::default())).id();
|
let n8 = world.spawn((A(8), Node::default())).id();
|
||||||
let n9 = world.spawn((A(9), GhostNode::new())).id();
|
let n9 = world.spawn((A(9), GhostNode)).id();
|
||||||
let n10 = world.spawn((A(10), Node::default())).id();
|
let n10 = world.spawn((A(10), Node::default())).id();
|
||||||
|
|
||||||
let no_ui = world.spawn_empty().id();
|
let no_ui = world.spawn_empty().id();
|
||||||
|
@ -7,8 +7,7 @@
|
|||||||
//! This is an experimental feature, and should be used with caution,
|
//! This is an experimental feature, and should be used with caution,
|
||||||
//! especially in concert with 3rd party plugins or systems that may not be aware of ghost nodes.
|
//! especially in concert with 3rd party plugins or systems that may not be aware of ghost nodes.
|
||||||
//!
|
//!
|
||||||
//! To add [`GhostNode`] components to entities, you must enable the `ghost_nodes` feature flag,
|
//! In order to use [`GhostNode`]s you must enable the `ghost_nodes` feature flag.
|
||||||
//! as they are otherwise unconstructable even though the type is defined.
|
|
||||||
|
|
||||||
use bevy::{prelude::*, ui::experimental::GhostNode, winit::WinitSettings};
|
use bevy::{prelude::*, ui::experimental::GhostNode, winit::WinitSettings};
|
||||||
|
|
||||||
@ -30,14 +29,12 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||||||
commands.spawn(Camera2d);
|
commands.spawn(Camera2d);
|
||||||
|
|
||||||
// Ghost UI root
|
// Ghost UI root
|
||||||
commands
|
commands.spawn(GhostNode).with_children(|ghost_root| {
|
||||||
.spawn(GhostNode::new())
|
ghost_root.spawn(Node::default()).with_child(create_label(
|
||||||
.with_children(|ghost_root| {
|
"This text node is rendered under a ghost root",
|
||||||
ghost_root.spawn(Node::default()).with_child(create_label(
|
font_handle.clone(),
|
||||||
"This text node is rendered under a ghost root",
|
));
|
||||||
font_handle.clone(),
|
});
|
||||||
));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Normal UI root
|
// Normal UI root
|
||||||
commands
|
commands
|
||||||
@ -53,7 +50,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||||||
.spawn((Node::default(), Counter(0)))
|
.spawn((Node::default(), Counter(0)))
|
||||||
.with_children(|layout_parent| {
|
.with_children(|layout_parent| {
|
||||||
layout_parent
|
layout_parent
|
||||||
.spawn((GhostNode::new(), Counter(0)))
|
.spawn((GhostNode, Counter(0)))
|
||||||
.with_children(|ghost_parent| {
|
.with_children(|ghost_parent| {
|
||||||
// Ghost children using a separate counter state
|
// Ghost children using a separate counter state
|
||||||
// These buttons are being treated as children of layout_parent in the context of UI
|
// These buttons are being treated as children of layout_parent in the context of UI
|
||||||
|
Loading…
Reference in New Issue
Block a user