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 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")]
|
||||
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.
|
||||
///
|
||||
/// Any components necessary for transform and visibility propagation will be added automatically.
|
||||
///
|
||||
/// Instances of this type cannot be constructed unless the `ghost_nodes` feature is enabled.
|
||||
#[cfg(feature = "ghost_nodes")]
|
||||
#[derive(Component, Debug, Copy, Clone, Reflect)]
|
||||
#[cfg_attr(feature = "ghost_nodes", derive(Default))]
|
||||
#[reflect(Component, Debug)]
|
||||
#[require(Visibility, Transform)]
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
pub struct GhostNode;
|
||||
|
||||
#[cfg(feature = "ghost_nodes")]
|
||||
/// System param that allows iteration of all UI root nodes.
|
||||
@ -232,20 +216,18 @@ mod tests {
|
||||
.with_children(|parent| {
|
||||
parent.spawn((A(2), Node::default()));
|
||||
parent
|
||||
.spawn((A(3), GhostNode::new()))
|
||||
.spawn((A(3), GhostNode))
|
||||
.with_child((A(4), Node::default()));
|
||||
});
|
||||
|
||||
// Ghost root
|
||||
world
|
||||
.spawn((A(5), GhostNode::new()))
|
||||
.with_children(|parent| {
|
||||
parent.spawn((A(6), Node::default()));
|
||||
parent
|
||||
.spawn((A(7), GhostNode::new()))
|
||||
.with_child((A(8), Node::default()))
|
||||
.with_child(A(9));
|
||||
});
|
||||
world.spawn((A(5), GhostNode)).with_children(|parent| {
|
||||
parent.spawn((A(6), Node::default()));
|
||||
parent
|
||||
.spawn((A(7), GhostNode))
|
||||
.with_child((A(8), Node::default()))
|
||||
.with_child(A(9));
|
||||
});
|
||||
|
||||
let mut system_state = SystemState::<(UiRootNodes, Query<&A>)>::new(world);
|
||||
let (ui_root_nodes, a_query) = system_state.get(world);
|
||||
@ -260,15 +242,15 @@ mod tests {
|
||||
let world = &mut World::new();
|
||||
|
||||
let n1 = world.spawn((A(1), Node::default())).id();
|
||||
let n2 = world.spawn((A(2), GhostNode::new())).id();
|
||||
let n3 = world.spawn((A(3), GhostNode::new())).id();
|
||||
let n2 = world.spawn((A(2), GhostNode)).id();
|
||||
let n3 = world.spawn((A(3), GhostNode)).id();
|
||||
let n4 = world.spawn((A(4), Node::default())).id();
|
||||
let n5 = world.spawn((A(5), Node::default())).id();
|
||||
|
||||
let n6 = world.spawn((A(6), GhostNode::new())).id();
|
||||
let n7 = world.spawn((A(7), GhostNode::new())).id();
|
||||
let n6 = world.spawn((A(6), GhostNode)).id();
|
||||
let n7 = world.spawn((A(7), GhostNode)).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 no_ui = world.spawn_empty().id();
|
||||
|
@ -7,8 +7,7 @@
|
||||
//! 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.
|
||||
//!
|
||||
//! To add [`GhostNode`] components to entities, you must enable the `ghost_nodes` feature flag,
|
||||
//! as they are otherwise unconstructable even though the type is defined.
|
||||
//! In order to use [`GhostNode`]s you must enable the `ghost_nodes` feature flag.
|
||||
|
||||
use bevy::{prelude::*, ui::experimental::GhostNode, winit::WinitSettings};
|
||||
|
||||
@ -30,14 +29,12 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
commands.spawn(Camera2d);
|
||||
|
||||
// Ghost UI root
|
||||
commands
|
||||
.spawn(GhostNode::new())
|
||||
.with_children(|ghost_root| {
|
||||
ghost_root.spawn(Node::default()).with_child(create_label(
|
||||
"This text node is rendered under a ghost root",
|
||||
font_handle.clone(),
|
||||
));
|
||||
});
|
||||
commands.spawn(GhostNode).with_children(|ghost_root| {
|
||||
ghost_root.spawn(Node::default()).with_child(create_label(
|
||||
"This text node is rendered under a ghost root",
|
||||
font_handle.clone(),
|
||||
));
|
||||
});
|
||||
|
||||
// Normal UI root
|
||||
commands
|
||||
@ -53,7 +50,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
.spawn((Node::default(), Counter(0)))
|
||||
.with_children(|layout_parent| {
|
||||
layout_parent
|
||||
.spawn((GhostNode::new(), Counter(0)))
|
||||
.spawn((GhostNode, Counter(0)))
|
||||
.with_children(|ghost_parent| {
|
||||
// Ghost children using a separate counter state
|
||||
// These buttons are being treated as children of layout_parent in the context of UI
|
||||
|
Loading…
Reference in New Issue
Block a user