1use std::f32::consts::{FRAC_PI_2, PI};
4
5use bevy::{
6 color::palettes::css::{DARK_CYAN, GOLD, GRAY, ORANGE, PURPLE},
7 prelude::*,
8};
9
10fn main() {
11 App::new()
12 .add_plugins(DefaultPlugins)
13 .add_systems(Startup, setup)
14 .add_systems(Update, rotate_camera)
15 .add_systems(Update, update_config)
16 .run();
17}
18
19#[derive(Component)]
20struct GizmoColorText;
21
22fn gizmo_color_text(config: &LightGizmoConfigGroup) -> String {
23 match config.color {
24 LightGizmoColor::Manual(color) => format!("Manual {}", Srgba::from(color).to_hex()),
25 LightGizmoColor::Varied => "Random from entity".to_owned(),
26 LightGizmoColor::MatchLightColor => "Match light color".to_owned(),
27 LightGizmoColor::ByLightType => {
28 format!(
29 "Point {}, Spot {}, Directional {}, Rect {}",
30 Srgba::from(config.point_light_color).to_hex(),
31 Srgba::from(config.spot_light_color).to_hex(),
32 Srgba::from(config.directional_light_color).to_hex(),
33 Srgba::from(config.rect_light_color).to_hex()
34 )
35 }
36 }
37}
38
39fn setup(
40 mut commands: Commands,
41 mut meshes: ResMut<Assets<Mesh>>,
42 mut materials: ResMut<Assets<StandardMaterial>>,
43 mut config_store: ResMut<GizmoConfigStore>,
44) {
45 commands.spawn((
47 Mesh3d(meshes.add(Circle::new(4.0))),
48 MeshMaterial3d(materials.add(Color::WHITE)),
49 Transform::from_rotation(Quat::from_rotation_x(-FRAC_PI_2)),
50 ));
51
52 {
54 let mesh = meshes.add(Cuboid::new(1.0, 1.0, 1.0));
55 let material = materials.add(Color::srgb_u8(124, 144, 255));
56 for x in [-2.0, 0.0, 2.0] {
57 commands.spawn((
58 Mesh3d(mesh.clone()),
59 MeshMaterial3d(material.clone()),
60 Transform::from_xyz(x, 0.5, 0.0),
61 ));
62 }
63 }
64
65 {
67 commands.spawn((
68 PointLight {
69 shadow_maps_enabled: true,
70 range: 2.0,
71 color: DARK_CYAN.into(),
72 ..default()
73 },
74 Transform::from_xyz(0.0, 1.5, 0.0),
75 ));
76 commands.spawn((
77 SpotLight {
78 shadow_maps_enabled: true,
79 range: 3.5,
80 color: PURPLE.into(),
81 outer_angle: PI / 4.0,
82 inner_angle: PI / 4.0 * 0.8,
83 ..default()
84 },
85 Transform::from_xyz(4.0, 2.0, 0.0).looking_at(Vec3::X * 1.5, Vec3::Y),
86 ));
87 commands.spawn((
88 DirectionalLight {
89 color: GOLD.into(),
90 illuminance: DirectionalLight::default().illuminance * 0.05,
91 shadow_maps_enabled: true,
92 ..default()
93 },
94 Transform::from_xyz(-4.0, 2.0, 0.0).looking_at(Vec3::NEG_X * 1.5, Vec3::Y),
95 ));
96 commands.spawn((
97 RectLight {
98 color: ORANGE.into(),
99 intensity: 200_000.0,
100 width: 1.5,
101 height: 0.8,
102 range: 20.0,
103 },
104 Transform::from_xyz(0.0, 3.0, -3.0).looking_at(Vec3::ZERO, Vec3::Y),
105 ));
106 }
107
108 commands.spawn((
110 Camera3d::default(),
111 Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
112 ));
113
114 {
116 commands.spawn((
117 Text::new(
118 "Press 'D' to toggle drawing gizmos on top of everything else in the scene\n\
119 Hold 'Left' or 'Right' to change the line width of the gizmos\n\
120 Press 'A' to toggle drawing of the light gizmos\n\
121 Press 'C' to cycle between the light gizmos coloring modes",
122 ),
123 Node {
124 position_type: PositionType::Absolute,
125 top: px(12),
126 left: px(12),
127 ..default()
128 },
129 ));
130
131 let (_, light_config) = config_store.config_mut::<LightGizmoConfigGroup>();
132 light_config.draw_all = true;
133 light_config.color = LightGizmoColor::MatchLightColor;
134
135 commands
136 .spawn((
137 Text::new("Gizmo color mode: "),
138 GizmoColorText,
139 Node {
140 position_type: PositionType::Absolute,
141 bottom: px(12),
142 left: px(12),
143 ..default()
144 },
145 ))
146 .with_child(TextSpan(gizmo_color_text(light_config)));
147 }
148}
149
150fn rotate_camera(mut transform: Single<&mut Transform, With<Camera>>, time: Res<Time>) {
151 transform.rotate_around(Vec3::ZERO, Quat::from_rotation_y(time.delta_secs() / 2.));
152}
153
154fn update_config(
155 mut config_store: ResMut<GizmoConfigStore>,
156 keyboard: Res<ButtonInput<KeyCode>>,
157 time: Res<Time>,
158 color_text_query: Single<Entity, With<GizmoColorText>>,
159 mut writer: TextUiWriter,
160) {
161 if keyboard.just_pressed(KeyCode::KeyD) {
162 for (_, config, _) in config_store.iter_mut() {
163 config.depth_bias = if config.depth_bias == 0. { -1. } else { 0. };
164 }
165 }
166
167 let (config, light_config) = config_store.config_mut::<LightGizmoConfigGroup>();
168 if keyboard.pressed(KeyCode::ArrowRight) {
169 config.line.width += 5. * time.delta_secs();
170 config.line.width = config.line.width.clamp(0., 50.);
171 }
172 if keyboard.pressed(KeyCode::ArrowLeft) {
173 config.line.width -= 5. * time.delta_secs();
174 config.line.width = config.line.width.clamp(0., 50.);
175 }
176 if keyboard.just_pressed(KeyCode::KeyA) {
177 config.enabled ^= true;
178 }
179 if keyboard.just_pressed(KeyCode::KeyC) {
180 light_config.color = match light_config.color {
181 LightGizmoColor::Manual(_) => LightGizmoColor::Varied,
182 LightGizmoColor::Varied => LightGizmoColor::MatchLightColor,
183 LightGizmoColor::MatchLightColor => LightGizmoColor::ByLightType,
184 LightGizmoColor::ByLightType => LightGizmoColor::Manual(GRAY.into()),
185 };
186 *writer.text(*color_text_query, 1) = gizmo_color_text(light_config);
187 }
188}