Skip to content

Commit a74923e

Browse files
committed
Add light gizmos example and add update gizmos prelude
1 parent cdb8c9f commit a74923e

File tree

5 files changed

+208
-7
lines changed

5 files changed

+208
-7
lines changed

Cargo.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2669,6 +2669,17 @@ description = "A scene showcasing 3D gizmos"
26692669
category = "Gizmos"
26702670
wasm = true
26712671

2672+
[[example]]
2673+
name = "light_gizmos"
2674+
path = "examples/gizmos/light_gizmos.rs"
2675+
doc-scrape-examples = true
2676+
2677+
[package.metadata.example.light_gizmos]
2678+
name = "Light Gizmos"
2679+
description = "A scene showcasing light gizmos"
2680+
category = "Gizmos"
2681+
wasm = true
2682+
26722683
[profile.wasm-release]
26732684
inherits = "release"
26742685
opt-level = "z"

crates/bevy_gizmos/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ pub mod prelude {
4747
aabb::{AabbGizmoConfigGroup, ShowAabbGizmo},
4848
config::{DefaultGizmoConfigGroup, GizmoConfig, GizmoConfigGroup, GizmoConfigStore},
4949
gizmos::Gizmos,
50+
light::{LightGizmoColor, LightGizmoConfigGroup, ShowLightGizmo},
5051
primitives::{dim2::GizmoPrimitive2d, dim3::GizmoPrimitive3d},
5152
AppGizmoBuilder,
5253
};
@@ -86,10 +87,9 @@ use config::{
8687
DefaultGizmoConfigGroup, GizmoConfig, GizmoConfigGroup, GizmoConfigStore, GizmoMeshConfig,
8788
};
8889
use gizmos::GizmoStorage;
90+
use light::LightGizmoPlugin;
8991
use std::{any::TypeId, mem};
9092

91-
use crate::light::LightGizmoPlugin;
92-
9393
const LINE_SHADER_HANDLE: Handle<Shader> = Handle::weak_from_u128(7414812689238026784);
9494

9595
/// A [`Plugin`] that provides an immediate mode drawing api for visual debugging.

crates/bevy_gizmos/src/light.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ fn spot_light_gizmo(
7575
.segments(16);
7676

7777
// Offset the tip of the cone to the light position.
78-
gizmos.sphere(translation, Quat::IDENTITY, 0.01, LinearRgba::GREEN);
7978
for angle in [spot_light.inner_angle, spot_light.outer_angle] {
8079
let height = spot_light.range * angle.cos();
8180
let position = translation + rotation * Vec3::NEG_Z * height / 2.0;
@@ -203,7 +202,7 @@ impl Default for LightGizmoConfigGroup {
203202
#[derive(Component, Reflect, Default, Debug)]
204203
#[reflect(Component, Default)]
205204
pub struct ShowLightGizmo {
206-
/// Default color strategy for this light gizmo. if none, use the one provided by [`LightGizmoConfigGroup`].
205+
/// Default color strategy for this light gizmo. if [`None`], use the one provided by [`LightGizmoConfigGroup`].
207206
///
208207
/// Defaults to [`None`].
209208
color: Option<LightGizmoColor>,
@@ -237,7 +236,7 @@ fn draw_lights(
237236
entity,
238237
light_gizmo.color,
239238
light.color,
240-
gizmos.config_ext.point_light_color,
239+
gizmos.config_ext.spot_light_color,
241240
);
242241
spot_light_gizmo(transform, light, color, &mut gizmos);
243242
}
@@ -246,7 +245,7 @@ fn draw_lights(
246245
entity,
247246
light_gizmo.color,
248247
light.color,
249-
gizmos.config_ext.point_light_color,
248+
gizmos.config_ext.directional_light_color,
250249
);
251250
directional_light_gizmo(transform, color, &mut gizmos);
252251
}

crates/bevy_gizmos/src/primitives/dim3.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -609,9 +609,10 @@ pub struct Cone3dBuilder<'a, 'w, 's, T: GizmoConfigGroup> {
609609
// Color of the cone
610610
color: Color,
611611

612-
// Number of segments used to approximate the cone geometry
612+
// Number of segments used to approximate the cone base geometry
613613
base_segments: usize,
614614

615+
// Number of segments used to approximate the cone height geometry
615616
height_segments: usize,
616617
}
617618

examples/gizmos/light_gizmos.rs

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
//! This example demonstrates how to visualize lights properties through the gizmo API.
2+
3+
use std::f32::consts::{FRAC_PI_2, PI};
4+
5+
use bevy::{
6+
color::palettes::css::{DARK_CYAN, GOLD, GRAY, PURPLE},
7+
gizmos::light::{LightGizmoColor, LightGizmoConfigGroup},
8+
prelude::*,
9+
};
10+
11+
fn main() {
12+
App::new()
13+
.add_plugins(DefaultPlugins)
14+
.add_systems(Startup, setup)
15+
.add_systems(Update, rotate_camera)
16+
.add_systems(Update, update_config)
17+
.run();
18+
}
19+
20+
#[derive(Component)]
21+
struct GizmoColorText;
22+
23+
fn gizmo_color_text(config: &LightGizmoConfigGroup) -> String {
24+
match config.color {
25+
LightGizmoColor::Manual(color) => format!("Manual {}", Srgba::from(color).to_hex()),
26+
LightGizmoColor::Varied => "Random from entity".to_owned(),
27+
LightGizmoColor::MatchLightColor => "Match light color".to_owned(),
28+
LightGizmoColor::ByLightType => {
29+
format!(
30+
"Point {}, Spot {}, Directional {}",
31+
Srgba::from(config.point_light_color).to_hex(),
32+
Srgba::from(config.spot_light_color).to_hex(),
33+
Srgba::from(config.directional_light_color).to_hex()
34+
)
35+
}
36+
}
37+
}
38+
39+
fn 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+
// Circular base.
46+
commands.spawn(PbrBundle {
47+
mesh: meshes.add(Circle::new(4.0)),
48+
material: materials.add(Color::WHITE),
49+
transform: Transform::from_rotation(Quat::from_rotation_x(-FRAC_PI_2)),
50+
..default()
51+
});
52+
53+
// Cubes.
54+
{
55+
let mesh = meshes.add(Cuboid::new(1.0, 1.0, 1.0));
56+
let material = materials.add(Color::srgb_u8(124, 144, 255));
57+
for x in [-2.0, 0.0, 2.0] {
58+
commands.spawn(PbrBundle {
59+
mesh: mesh.clone(),
60+
material: material.clone(),
61+
transform: Transform::from_xyz(x, 0.5, 0.0),
62+
..default()
63+
});
64+
}
65+
}
66+
67+
// Lights.
68+
{
69+
commands.spawn(PointLightBundle {
70+
point_light: PointLight {
71+
shadows_enabled: true,
72+
range: 2.0,
73+
color: DARK_CYAN.into(),
74+
..default()
75+
},
76+
transform: Transform::from_xyz(0.0, 1.5, 0.0),
77+
..default()
78+
});
79+
commands.spawn(SpotLightBundle {
80+
spot_light: SpotLight {
81+
shadows_enabled: true,
82+
range: 3.5,
83+
color: PURPLE.into(),
84+
outer_angle: PI / 4.0,
85+
inner_angle: PI / 4.0 * 0.8,
86+
..default()
87+
},
88+
transform: Transform::from_xyz(4.0, 2.0, 0.0).looking_at(Vec3::X * 1.5, Vec3::Y),
89+
..default()
90+
});
91+
commands.spawn(DirectionalLightBundle {
92+
directional_light: DirectionalLight {
93+
color: GOLD.into(),
94+
illuminance: DirectionalLight::default().illuminance * 0.05,
95+
shadows_enabled: true,
96+
..default()
97+
},
98+
transform: Transform::from_xyz(-4.0, 2.0, 0.0).looking_at(Vec3::NEG_X * 1.5, Vec3::Y),
99+
..default()
100+
});
101+
}
102+
103+
// Camera.
104+
commands.spawn(Camera3dBundle {
105+
transform: Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
106+
..default()
107+
});
108+
109+
// Example instructions and gizmo config.
110+
{
111+
let text_style = TextStyle {
112+
font_size: 20.0,
113+
..default()
114+
};
115+
commands.spawn(
116+
TextBundle::from_section(
117+
"Press 'D' to toggle drawing gizmos on top of everything else in the scene\n\
118+
Hold 'Left' or 'Right' to change the line width of the gizmos\n\
119+
Press 'A' to toggle drawing of the light gizmos\n\
120+
Press 'C' to cycle between the light gizmos coloring modes",
121+
text_style.clone(),
122+
)
123+
.with_style(Style {
124+
position_type: PositionType::Absolute,
125+
top: Val::Px(12.0),
126+
left: Val::Px(12.0),
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.spawn((
136+
TextBundle::from_sections([
137+
TextSection::new("Gizmo color mode: ", text_style.clone()),
138+
TextSection::new(gizmo_color_text(light_config), text_style),
139+
])
140+
.with_style(Style {
141+
position_type: PositionType::Absolute,
142+
bottom: Val::Px(12.0),
143+
left: Val::Px(12.0),
144+
..default()
145+
}),
146+
GizmoColorText,
147+
));
148+
}
149+
}
150+
151+
fn rotate_camera(mut query: Query<&mut Transform, With<Camera>>, time: Res<Time>) {
152+
let mut transform = query.single_mut();
153+
154+
transform.rotate_around(Vec3::ZERO, Quat::from_rotation_y(time.delta_seconds() / 2.));
155+
}
156+
157+
fn update_config(
158+
mut config_store: ResMut<GizmoConfigStore>,
159+
keyboard: Res<ButtonInput<KeyCode>>,
160+
time: Res<Time>,
161+
mut color_text_query: Query<&mut Text, With<GizmoColorText>>,
162+
) {
163+
if keyboard.just_pressed(KeyCode::KeyD) {
164+
for (_, config, _) in config_store.iter_mut() {
165+
config.depth_bias = if config.depth_bias == 0. { -1. } else { 0. };
166+
}
167+
}
168+
169+
let (config, light_config) = config_store.config_mut::<LightGizmoConfigGroup>();
170+
if keyboard.pressed(KeyCode::ArrowRight) {
171+
config.line_width += 5. * time.delta_seconds();
172+
config.line_width = config.line_width.clamp(0., 50.);
173+
}
174+
if keyboard.pressed(KeyCode::ArrowLeft) {
175+
config.line_width -= 5. * time.delta_seconds();
176+
config.line_width = config.line_width.clamp(0., 50.);
177+
}
178+
if keyboard.just_pressed(KeyCode::KeyA) {
179+
config.enabled ^= true;
180+
}
181+
if keyboard.just_pressed(KeyCode::KeyC) {
182+
light_config.color = match light_config.color {
183+
LightGizmoColor::Manual(_) => LightGizmoColor::Varied,
184+
LightGizmoColor::Varied => LightGizmoColor::MatchLightColor,
185+
LightGizmoColor::MatchLightColor => LightGizmoColor::ByLightType,
186+
LightGizmoColor::ByLightType => LightGizmoColor::Manual(GRAY.into()),
187+
};
188+
color_text_query.single_mut().sections[1].value = gizmo_color_text(light_config);
189+
}
190+
}

0 commit comments

Comments
 (0)