viewport_debug/
viewport_debug.rs

1//! A simple example for debugging viewport coordinates
2//!
3//! This example creates two UI node trees, one using viewport coordinates and one using pixel coordinates,
4//! and then switches between them once per second using the `Display` style property.
5//! If there are no problems both layouts should be identical, except for the color of the margin changing which is used to signal that the displayed UI node tree has changed
6//! (red for viewport, yellow for pixel).
7use bevy::{color::palettes::css::*, prelude::*};
8
9const PALETTE: [Srgba; 10] = [
10    RED, YELLOW, WHITE, BEIGE, AQUA, CRIMSON, NAVY, AZURE, LIME, BLACK,
11];
12
13#[derive(Component, Default, PartialEq)]
14enum Coords {
15    #[default]
16    Viewport,
17    Pixel,
18}
19
20fn main() {
21    App::new()
22        .insert_resource(UiScale(2.0))
23        .add_plugins(DefaultPlugins.set(WindowPlugin {
24            primary_window: Some(Window {
25                title: "Viewport Coordinates Debug".to_string(),
26                // This example relies on these specific viewport dimensions, so let's explicitly
27                // define them.
28                resolution: [1280., 720.].into(),
29                resizable: false,
30                ..Default::default()
31            }),
32            ..Default::default()
33        }))
34        .add_systems(Startup, setup)
35        .add_systems(Update, update)
36        .run();
37}
38
39fn update(
40    mut timer: Local<f32>,
41    mut visible_tree: Local<Coords>,
42    time: Res<Time>,
43    mut coords_nodes: Query<(&Coords, &mut Node)>,
44) {
45    *timer -= time.delta_secs();
46    if *timer <= 0. {
47        *timer = 1.;
48        *visible_tree = match *visible_tree {
49            Coords::Viewport => Coords::Pixel,
50            Coords::Pixel => Coords::Viewport,
51        };
52        for (coords, mut node) in coords_nodes.iter_mut() {
53            node.display = if *coords == *visible_tree {
54                Display::Flex
55            } else {
56                Display::None
57            };
58        }
59    }
60}
61
62fn setup(mut commands: Commands) {
63    commands.spawn(Camera2d);
64    spawn_with_viewport_coords(&mut commands);
65    spawn_with_pixel_coords(&mut commands);
66}
67
68fn spawn_with_viewport_coords(commands: &mut Commands) {
69    commands
70        .spawn((
71            Node {
72                width: Val::Vw(100.),
73                height: Val::Vh(100.),
74                border: UiRect::axes(Val::Vw(5.), Val::Vh(5.)),
75                flex_wrap: FlexWrap::Wrap,
76                ..default()
77            },
78            BorderColor(PALETTE[0].into()),
79            Coords::Viewport,
80        ))
81        .with_children(|builder| {
82            builder.spawn((
83                Node {
84                    width: Val::Vw(30.),
85                    height: Val::Vh(30.),
86                    border: UiRect::all(Val::VMin(5.)),
87                    ..default()
88                },
89                BackgroundColor(PALETTE[2].into()),
90                BorderColor(PALETTE[9].into()),
91            ));
92
93            builder.spawn((
94                Node {
95                    width: Val::Vw(60.),
96                    height: Val::Vh(30.),
97                    ..default()
98                },
99                BackgroundColor(PALETTE[3].into()),
100            ));
101
102            builder.spawn((
103                Node {
104                    width: Val::Vw(45.),
105                    height: Val::Vh(30.),
106                    border: UiRect::left(Val::VMax(45. / 2.)),
107                    ..default()
108                },
109                BackgroundColor(PALETTE[4].into()),
110                BorderColor(PALETTE[8].into()),
111            ));
112
113            builder.spawn((
114                Node {
115                    width: Val::Vw(45.),
116                    height: Val::Vh(30.),
117                    border: UiRect::right(Val::VMax(45. / 2.)),
118                    ..default()
119                },
120                BackgroundColor(PALETTE[5].into()),
121                BorderColor(PALETTE[8].into()),
122            ));
123
124            builder.spawn((
125                Node {
126                    width: Val::Vw(60.),
127                    height: Val::Vh(30.),
128                    ..default()
129                },
130                BackgroundColor(PALETTE[6].into()),
131            ));
132
133            builder.spawn((
134                Node {
135                    width: Val::Vw(30.),
136                    height: Val::Vh(30.),
137                    border: UiRect::all(Val::VMin(5.)),
138                    ..default()
139                },
140                BackgroundColor(PALETTE[7].into()),
141                BorderColor(PALETTE[9].into()),
142            ));
143        });
144}
145
146fn spawn_with_pixel_coords(commands: &mut Commands) {
147    commands
148        .spawn((
149            Node {
150                width: Val::Px(640.),
151                height: Val::Px(360.),
152                border: UiRect::axes(Val::Px(32.), Val::Px(18.)),
153                flex_wrap: FlexWrap::Wrap,
154                ..default()
155            },
156            BorderColor(PALETTE[1].into()),
157            Coords::Pixel,
158        ))
159        .with_children(|builder| {
160            builder.spawn((
161                Node {
162                    width: Val::Px(192.),
163                    height: Val::Px(108.),
164                    border: UiRect::axes(Val::Px(18.), Val::Px(18.)),
165                    ..default()
166                },
167                BackgroundColor(PALETTE[2].into()),
168                BorderColor(PALETTE[9].into()),
169            ));
170
171            builder.spawn((
172                Node {
173                    width: Val::Px(384.),
174                    height: Val::Px(108.),
175                    ..default()
176                },
177                BackgroundColor(PALETTE[3].into()),
178            ));
179
180            builder.spawn((
181                Node {
182                    width: Val::Px(288.),
183                    height: Val::Px(108.),
184                    border: UiRect::left(Val::Px(144.)),
185                    ..default()
186                },
187                BackgroundColor(PALETTE[4].into()),
188                BorderColor(PALETTE[8].into()),
189            ));
190
191            builder.spawn((
192                Node {
193                    width: Val::Px(288.),
194                    height: Val::Px(108.),
195                    border: UiRect::right(Val::Px(144.)),
196                    ..default()
197                },
198                BackgroundColor(PALETTE[5].into()),
199                BorderColor(PALETTE[8].into()),
200            ));
201
202            builder.spawn((
203                Node {
204                    width: Val::Px(384.),
205                    height: Val::Px(108.),
206                    ..default()
207                },
208                BackgroundColor(PALETTE[6].into()),
209            ));
210
211            builder.spawn((
212                Node {
213                    width: Val::Px(192.),
214                    height: Val::Px(108.),
215                    border: UiRect::axes(Val::Px(18.), Val::Px(18.)),
216                    ..default()
217                },
218                BackgroundColor(PALETTE[7].into()),
219                BorderColor(PALETTE[9].into()),
220            ));
221        });
222}