ghost_nodes/
ghost_nodes.rs1use bevy::{prelude::*, ui::experimental::GhostNode};
13
14fn main() {
15 App::new()
16 .add_plugins(DefaultPlugins)
17 .add_systems(Startup, setup)
18 .add_systems(Update, button_system)
19 .run();
20}
21
22#[derive(Component)]
23struct Counter(i32);
24
25fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
26 let font_handle = asset_server.load("fonts/FiraSans-Bold.ttf");
27
28 commands.spawn(Camera2d);
29
30 commands.spawn(GhostNode).with_children(|ghost_root| {
32 ghost_root.spawn(Node::default()).with_child(create_label(
33 "This text node is rendered under a ghost root",
34 font_handle.clone(),
35 ));
36 });
37
38 commands
40 .spawn(Node {
41 width: percent(100),
42 height: percent(100),
43 align_items: AlignItems::Center,
44 justify_content: JustifyContent::Center,
45 ..default()
46 })
47 .with_children(|parent| {
48 parent
49 .spawn((Node::default(), Counter(0)))
50 .with_children(|layout_parent| {
51 layout_parent
52 .spawn((GhostNode, Counter(0)))
53 .with_children(|ghost_parent| {
54 ghost_parent
57 .spawn(create_button())
58 .with_child(create_label("0", font_handle.clone()));
59 ghost_parent
60 .spawn(create_button())
61 .with_child(create_label("0", font_handle.clone()));
62 });
63
64 layout_parent
66 .spawn(create_button())
67 .with_child(create_label("0", font_handle.clone()));
68 });
69 });
70}
71
72fn create_button() -> impl Bundle {
73 (
74 Button,
75 Node {
76 width: px(150),
77 height: px(65),
78 border: UiRect::all(px(5)),
79 justify_content: JustifyContent::Center,
81 align_items: AlignItems::Center,
83 ..default()
84 },
85 BorderColor::all(Color::BLACK),
86 BorderRadius::MAX,
87 BackgroundColor(Color::srgb(0.15, 0.15, 0.15)),
88 )
89}
90
91fn create_label(text: &str, font: Handle<Font>) -> (Text, TextFont, TextColor) {
92 (
93 Text::new(text),
94 TextFont {
95 font,
96 font_size: 33.0,
97 ..default()
98 },
99 TextColor(Color::srgb(0.9, 0.9, 0.9)),
100 )
101}
102
103fn button_system(
104 mut interaction_query: Query<(&Interaction, &ChildOf), (Changed<Interaction>, With<Button>)>,
105 labels_query: Query<(&Children, &ChildOf), With<Button>>,
106 mut text_query: Query<&mut Text>,
107 mut counter_query: Query<&mut Counter>,
108) {
109 for (interaction, child_of) in &mut interaction_query {
111 if matches!(interaction, Interaction::Pressed) {
112 let mut counter = counter_query.get_mut(child_of.parent()).unwrap();
113 counter.0 += 1;
114 }
115 }
116
117 for (children, child_of) in &labels_query {
119 let counter = counter_query.get(child_of.parent()).unwrap();
120 let mut text = text_query.get_mut(children[0]).unwrap();
121
122 **text = counter.0.to_string();
123 }
124}