Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

191
vendor/bevy/examples/gizmos/2d_gizmos.rs vendored Normal file
View File

@@ -0,0 +1,191 @@
//! This example demonstrates Bevy's immediate mode drawing API intended for visual debugging.
use std::f32::consts::{FRAC_PI_2, PI, TAU};
use bevy::{color::palettes::css::*, math::Isometry2d, prelude::*};
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.init_gizmo_group::<MyRoundGizmos>()
.add_systems(Startup, setup)
.add_systems(Update, (draw_example_collection, update_config))
.run();
}
// We can create our own gizmo config group!
#[derive(Default, Reflect, GizmoConfigGroup)]
struct MyRoundGizmos {}
fn setup(mut commands: Commands) {
commands.spawn(Camera2d);
// text
commands.spawn((
Text::new(
"Hold 'Left' or 'Right' to change the line width of straight gizmos\n\
Hold 'Up' or 'Down' to change the line width of round gizmos\n\
Press '1' / '2' to toggle the visibility of straight / round gizmos\n\
Press 'U' / 'I' to cycle through line styles\n\
Press 'J' / 'K' to cycle through line joins",
),
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.),
left: Val::Px(12.),
..default()
},
));
}
fn draw_example_collection(
mut gizmos: Gizmos,
mut my_gizmos: Gizmos<MyRoundGizmos>,
time: Res<Time>,
) {
let sin_t_scaled = ops::sin(time.elapsed_secs()) * 50.;
gizmos.line_2d(Vec2::Y * -sin_t_scaled, Vec2::splat(-80.), RED);
gizmos.ray_2d(Vec2::Y * sin_t_scaled, Vec2::splat(80.), LIME);
gizmos
.grid_2d(
Isometry2d::IDENTITY,
UVec2::new(16, 9),
Vec2::new(80., 80.),
// Dark gray
LinearRgba::gray(0.05),
)
.outer_edges();
// Triangle
gizmos.linestrip_gradient_2d([
(Vec2::Y * 300., BLUE),
(Vec2::new(-255., -155.), RED),
(Vec2::new(255., -155.), LIME),
(Vec2::Y * 300., BLUE),
]);
gizmos.rect_2d(Isometry2d::IDENTITY, Vec2::splat(650.), BLACK);
gizmos.cross_2d(Vec2::new(-160., 120.), 12., FUCHSIA);
let domain = Interval::EVERYWHERE;
let curve = FunctionCurve::new(domain, |t| Vec2::new(t, ops::sin(t / 25.0) * 100.0));
let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 50.0) as usize;
let times_and_colors = (0..=resolution)
.map(|n| n as f32 / resolution as f32)
.map(|t| (t - 0.5) * 600.0)
.map(|t| (t, TEAL.mix(&HOT_PINK, (t + 300.0) / 600.0)));
gizmos.curve_gradient_2d(curve, times_and_colors);
my_gizmos
.rounded_rect_2d(Isometry2d::IDENTITY, Vec2::splat(630.), BLACK)
.corner_radius(ops::cos(time.elapsed_secs() / 3.) * 100.);
// Circles have 32 line-segments by default.
// You may want to increase this for larger circles.
my_gizmos
.circle_2d(Isometry2d::IDENTITY, 300., NAVY)
.resolution(64);
my_gizmos.ellipse_2d(
Rot2::radians(time.elapsed_secs() % TAU),
Vec2::new(100., 200.),
YELLOW_GREEN,
);
// Arcs default resolution is linearly interpolated between
// 1 and 32, using the arc length as scalar.
my_gizmos.arc_2d(
Rot2::radians(sin_t_scaled / 10.),
FRAC_PI_2,
310.,
ORANGE_RED,
);
my_gizmos.arc_2d(Isometry2d::IDENTITY, FRAC_PI_2, 80.0, ORANGE_RED);
my_gizmos.long_arc_2d_between(Vec2::ZERO, Vec2::X * 20.0, Vec2::Y * 20.0, ORANGE_RED);
my_gizmos.short_arc_2d_between(Vec2::ZERO, Vec2::X * 40.0, Vec2::Y * 40.0, ORANGE_RED);
gizmos.arrow_2d(
Vec2::ZERO,
Vec2::from_angle(sin_t_scaled / -10. + PI / 2.) * 50.,
YELLOW,
);
// You can create more complex arrows using the arrow builder.
gizmos
.arrow_2d(
Vec2::ZERO,
Vec2::from_angle(sin_t_scaled / -10.) * 50.,
GREEN,
)
.with_double_end()
.with_tip_length(10.);
}
fn update_config(
mut config_store: ResMut<GizmoConfigStore>,
keyboard: Res<ButtonInput<KeyCode>>,
time: Res<Time>,
) {
let (config, _) = config_store.config_mut::<DefaultGizmoConfigGroup>();
if keyboard.pressed(KeyCode::ArrowRight) {
config.line.width += 5. * time.delta_secs();
config.line.width = config.line.width.clamp(0., 50.);
}
if keyboard.pressed(KeyCode::ArrowLeft) {
config.line.width -= 5. * time.delta_secs();
config.line.width = config.line.width.clamp(0., 50.);
}
if keyboard.just_pressed(KeyCode::Digit1) {
config.enabled ^= true;
}
if keyboard.just_pressed(KeyCode::KeyU) {
config.line.style = match config.line.style {
GizmoLineStyle::Solid => GizmoLineStyle::Dotted,
GizmoLineStyle::Dotted => GizmoLineStyle::Dashed {
gap_scale: 3.0,
line_scale: 5.0,
},
_ => GizmoLineStyle::Solid,
};
}
if keyboard.just_pressed(KeyCode::KeyJ) {
config.line.joints = match config.line.joints {
GizmoLineJoint::Bevel => GizmoLineJoint::Miter,
GizmoLineJoint::Miter => GizmoLineJoint::Round(4),
GizmoLineJoint::Round(_) => GizmoLineJoint::None,
GizmoLineJoint::None => GizmoLineJoint::Bevel,
};
}
let (my_config, _) = config_store.config_mut::<MyRoundGizmos>();
if keyboard.pressed(KeyCode::ArrowUp) {
my_config.line.width += 5. * time.delta_secs();
my_config.line.width = my_config.line.width.clamp(0., 50.);
}
if keyboard.pressed(KeyCode::ArrowDown) {
my_config.line.width -= 5. * time.delta_secs();
my_config.line.width = my_config.line.width.clamp(0., 50.);
}
if keyboard.just_pressed(KeyCode::Digit2) {
my_config.enabled ^= true;
}
if keyboard.just_pressed(KeyCode::KeyI) {
my_config.line.style = match my_config.line.style {
GizmoLineStyle::Solid => GizmoLineStyle::Dotted,
GizmoLineStyle::Dotted => GizmoLineStyle::Dashed {
gap_scale: 3.0,
line_scale: 5.0,
},
_ => GizmoLineStyle::Solid,
};
}
if keyboard.just_pressed(KeyCode::KeyK) {
my_config.line.joints = match my_config.line.joints {
GizmoLineJoint::Bevel => GizmoLineJoint::Miter,
GizmoLineJoint::Miter => GizmoLineJoint::Round(4),
GizmoLineJoint::Round(_) => GizmoLineJoint::None,
GizmoLineJoint::None => GizmoLineJoint::Bevel,
};
}
}

292
vendor/bevy/examples/gizmos/3d_gizmos.rs vendored Normal file
View File

@@ -0,0 +1,292 @@
//! This example demonstrates Bevy's immediate mode drawing API intended for visual debugging.
#[path = "../helpers/camera_controller.rs"]
mod camera_controller;
use bevy::{color::palettes::css::*, prelude::*};
use camera_controller::{CameraController, CameraControllerPlugin};
use std::f32::consts::PI;
fn main() {
App::new()
.add_plugins((DefaultPlugins, CameraControllerPlugin))
.init_gizmo_group::<MyRoundGizmos>()
.add_systems(Startup, setup)
.add_systems(Update, (draw_example_collection, update_config))
.run();
}
// We can create our own gizmo config group!
#[derive(Default, Reflect, GizmoConfigGroup)]
struct MyRoundGizmos;
fn setup(
mut commands: Commands,
mut gizmo_assets: ResMut<Assets<GizmoAsset>>,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
let mut gizmo = GizmoAsset::new();
// When drawing a lot of static lines a Gizmo component can have
// far better performance than the Gizmos system parameter,
// but the system parameter will perform better for smaller lines that update often.
// A sphere made out of 30_000 lines!
gizmo
.sphere(Isometry3d::IDENTITY, 0.5, CRIMSON)
.resolution(30_000 / 3);
commands.spawn((
Gizmo {
handle: gizmo_assets.add(gizmo),
line_config: GizmoLineConfig {
width: 5.,
..default()
},
..default()
},
Transform::from_xyz(4., 1., 0.),
));
commands.spawn((
Camera3d::default(),
Transform::from_xyz(0., 1.5, 6.).looking_at(Vec3::ZERO, Vec3::Y),
CameraController::default(),
));
// plane
commands.spawn((
Mesh3d(meshes.add(Plane3d::default().mesh().size(5.0, 5.0))),
MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))),
));
// cube
commands.spawn((
Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
MeshMaterial3d(materials.add(Color::srgb(0.8, 0.7, 0.6))),
Transform::from_xyz(0.0, 0.5, 0.0),
));
// light
commands.spawn((
PointLight {
shadows_enabled: true,
..default()
},
Transform::from_xyz(4.0, 8.0, 4.0),
));
// example instructions
commands.spawn((
Text::new(
"Press 'T' to toggle drawing gizmos on top of everything else in the scene\n\
Press 'P' to toggle perspective for line gizmos\n\
Hold 'Left' or 'Right' to change the line width of straight gizmos\n\
Hold 'Up' or 'Down' to change the line width of round gizmos\n\
Press '1' or '2' to toggle the visibility of straight gizmos or round gizmos\n\
Press 'B' to show all AABB boxes\n\
Press 'U' or 'I' to cycle through line styles for straight or round gizmos\n\
Press 'J' or 'K' to cycle through line joins for straight or round gizmos",
),
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),
..default()
},
));
}
fn draw_example_collection(
mut gizmos: Gizmos,
mut my_gizmos: Gizmos<MyRoundGizmos>,
time: Res<Time>,
) {
gizmos.grid(
Quat::from_rotation_x(PI / 2.),
UVec2::splat(20),
Vec2::new(2., 2.),
// Light gray
LinearRgba::gray(0.65),
);
gizmos.grid(
Isometry3d::new(Vec3::splat(10.0), Quat::from_rotation_x(PI / 3. * 2.)),
UVec2::splat(20),
Vec2::new(2., 2.),
PURPLE,
);
gizmos.sphere(Vec3::splat(10.0), 1.0, PURPLE);
gizmos
.primitive_3d(
&Plane3d {
normal: Dir3::Y,
half_size: Vec2::splat(1.0),
},
Isometry3d::new(
Vec3::splat(4.0) + Vec2::from(ops::sin_cos(time.elapsed_secs())).extend(0.0),
Quat::from_rotation_x(PI / 2. + time.elapsed_secs()),
),
GREEN,
)
.cell_count(UVec2::new(5, 10))
.spacing(Vec2::new(0.2, 0.1));
gizmos.cuboid(
Transform::from_translation(Vec3::Y * 0.5).with_scale(Vec3::splat(1.25)),
BLACK,
);
gizmos.rect(
Isometry3d::new(
Vec3::new(ops::cos(time.elapsed_secs()) * 2.5, 1., 0.),
Quat::from_rotation_y(PI / 2.),
),
Vec2::splat(2.),
LIME,
);
gizmos.cross(Vec3::new(-1., 1., 1.), 0.5, FUCHSIA);
let domain = Interval::EVERYWHERE;
let curve = FunctionCurve::new(domain, |t| {
(Vec2::from(ops::sin_cos(t * 10.0))).extend(t - 6.0)
});
let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 100.0) as usize;
let times_and_colors = (0..=resolution)
.map(|n| n as f32 / resolution as f32)
.map(|t| t * 5.0)
.map(|t| (t, TEAL.mix(&HOT_PINK, t / 5.0)));
gizmos.curve_gradient_3d(curve, times_and_colors);
my_gizmos.sphere(Vec3::new(1., 0.5, 0.), 0.5, RED);
my_gizmos
.rounded_cuboid(Vec3::new(-2.0, 0.75, -0.75), Vec3::splat(0.9), TURQUOISE)
.edge_radius(0.1)
.arc_resolution(4);
for y in [0., 0.5, 1.] {
gizmos.ray(
Vec3::new(1., y, 0.),
Vec3::new(-3., ops::sin(time.elapsed_secs() * 3.), 0.),
BLUE,
);
}
my_gizmos
.arc_3d(
180.0_f32.to_radians(),
0.2,
Isometry3d::new(
Vec3::ONE,
Quat::from_rotation_arc(Vec3::Y, Vec3::ONE.normalize()),
),
ORANGE,
)
.resolution(10);
// Circles have 32 line-segments by default.
my_gizmos.circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3., BLACK);
// You may want to increase this for larger circles or spheres.
my_gizmos
.circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3.1, NAVY)
.resolution(64);
my_gizmos
.sphere(Isometry3d::IDENTITY, 3.2, BLACK)
.resolution(64);
gizmos.arrow(Vec3::ZERO, Vec3::splat(1.5), YELLOW);
// You can create more complex arrows using the arrow builder.
gizmos
.arrow(Vec3::new(2., 0., 2.), Vec3::new(2., 2., 2.), ORANGE_RED)
.with_double_end()
.with_tip_length(0.5);
}
fn update_config(
mut config_store: ResMut<GizmoConfigStore>,
keyboard: Res<ButtonInput<KeyCode>>,
time: Res<Time>,
) {
if keyboard.just_pressed(KeyCode::KeyT) {
for (_, config, _) in config_store.iter_mut() {
config.depth_bias = if config.depth_bias == 0. { -1. } else { 0. };
}
}
if keyboard.just_pressed(KeyCode::KeyP) {
for (_, config, _) in config_store.iter_mut() {
// Toggle line perspective
config.line.perspective ^= true;
// Increase the line width when line perspective is on
config.line.width *= if config.line.perspective { 5. } else { 1. / 5. };
}
}
let (config, _) = config_store.config_mut::<DefaultGizmoConfigGroup>();
if keyboard.pressed(KeyCode::ArrowRight) {
config.line.width += 5. * time.delta_secs();
config.line.width = config.line.width.clamp(0., 50.);
}
if keyboard.pressed(KeyCode::ArrowLeft) {
config.line.width -= 5. * time.delta_secs();
config.line.width = config.line.width.clamp(0., 50.);
}
if keyboard.just_pressed(KeyCode::Digit1) {
config.enabled ^= true;
}
if keyboard.just_pressed(KeyCode::KeyU) {
config.line.style = match config.line.style {
GizmoLineStyle::Solid => GizmoLineStyle::Dotted,
GizmoLineStyle::Dotted => GizmoLineStyle::Dashed {
gap_scale: 3.0,
line_scale: 5.0,
},
_ => GizmoLineStyle::Solid,
};
}
if keyboard.just_pressed(KeyCode::KeyJ) {
config.line.joints = match config.line.joints {
GizmoLineJoint::Bevel => GizmoLineJoint::Miter,
GizmoLineJoint::Miter => GizmoLineJoint::Round(4),
GizmoLineJoint::Round(_) => GizmoLineJoint::None,
GizmoLineJoint::None => GizmoLineJoint::Bevel,
};
}
let (my_config, _) = config_store.config_mut::<MyRoundGizmos>();
if keyboard.pressed(KeyCode::ArrowUp) {
my_config.line.width += 5. * time.delta_secs();
my_config.line.width = my_config.line.width.clamp(0., 50.);
}
if keyboard.pressed(KeyCode::ArrowDown) {
my_config.line.width -= 5. * time.delta_secs();
my_config.line.width = my_config.line.width.clamp(0., 50.);
}
if keyboard.just_pressed(KeyCode::Digit2) {
my_config.enabled ^= true;
}
if keyboard.just_pressed(KeyCode::KeyI) {
my_config.line.style = match my_config.line.style {
GizmoLineStyle::Solid => GizmoLineStyle::Dotted,
GizmoLineStyle::Dotted => GizmoLineStyle::Dashed {
gap_scale: 3.0,
line_scale: 5.0,
},
_ => GizmoLineStyle::Solid,
};
}
if keyboard.just_pressed(KeyCode::KeyK) {
my_config.line.joints = match my_config.line.joints {
GizmoLineJoint::Bevel => GizmoLineJoint::Miter,
GizmoLineJoint::Miter => GizmoLineJoint::Round(4),
GizmoLineJoint::Round(_) => GizmoLineJoint::None,
GizmoLineJoint::None => GizmoLineJoint::Bevel,
};
}
if keyboard.just_pressed(KeyCode::KeyB) {
// AABB gizmos are normally only drawn on entities with a ShowAabbGizmo component
// We can change this behavior in the configuration of AabbGizmoGroup
config_store.config_mut::<AabbGizmoConfigGroup>().1.draw_all ^= true;
}
}

220
vendor/bevy/examples/gizmos/axes.rs vendored Normal file
View File

@@ -0,0 +1,220 @@
//! This example demonstrates the implementation and behavior of the axes gizmo.
use bevy::{prelude::*, render::primitives::Aabb};
use rand::{Rng, SeedableRng};
use rand_chacha::ChaCha8Rng;
use std::f32::consts::PI;
const TRANSITION_DURATION: f32 = 2.0;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(Update, (move_cubes, draw_axes).chain())
.run();
}
/// The `ShowAxes` component is attached to an entity to get the `draw_axes` system to
/// display axes according to its Transform component.
#[derive(Component)]
struct ShowAxes;
/// The `TransformTracking` component keeps track of the data we need to interpolate
/// between two transforms in our example.
#[derive(Component)]
struct TransformTracking {
/// The initial transform of the cube during the move
initial_transform: Transform,
/// The target transform of the cube during the move
target_transform: Transform,
/// The progress of the cube during the move in seconds
progress: f32,
}
#[derive(Resource)]
struct SeededRng(ChaCha8Rng);
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// We're seeding the PRNG here to make this example deterministic for testing purposes.
// This isn't strictly required in practical use unless you need your app to be deterministic.
let mut rng = ChaCha8Rng::seed_from_u64(19878367467713);
// Lights...
commands.spawn((
PointLight {
shadows_enabled: true,
..default()
},
Transform::from_xyz(2., 6., 0.),
));
// Camera...
commands.spawn((
Camera3d::default(),
Transform::from_xyz(0., 1.5, -8.).looking_at(Vec3::new(0., -0.5, 0.), Vec3::Y),
));
// Action! (Our cubes that are going to move)
commands.spawn((
Mesh3d(meshes.add(Cuboid::new(1., 1., 1.))),
MeshMaterial3d(materials.add(Color::srgb(0.8, 0.7, 0.6))),
ShowAxes,
TransformTracking {
initial_transform: default(),
target_transform: random_transform(&mut rng),
progress: 0.0,
},
));
commands.spawn((
Mesh3d(meshes.add(Cuboid::new(0.5, 0.5, 0.5))),
MeshMaterial3d(materials.add(Color::srgb(0.6, 0.7, 0.8))),
ShowAxes,
TransformTracking {
initial_transform: default(),
target_transform: random_transform(&mut rng),
progress: 0.0,
},
));
// A plane to give a sense of place
commands.spawn((
Mesh3d(meshes.add(Plane3d::default().mesh().size(20., 20.))),
MeshMaterial3d(materials.add(Color::srgb(0.1, 0.1, 0.1))),
Transform::from_xyz(0., -2., 0.),
));
commands.insert_resource(SeededRng(rng));
}
// This system draws the axes based on the cube's transform, with length based on the size of
// the entity's axis-aligned bounding box (AABB).
fn draw_axes(mut gizmos: Gizmos, query: Query<(&Transform, &Aabb), With<ShowAxes>>) {
for (&transform, &aabb) in &query {
let length = aabb.half_extents.length();
gizmos.axes(transform, length);
}
}
// This system changes the cubes' transforms to interpolate between random transforms
fn move_cubes(
mut query: Query<(&mut Transform, &mut TransformTracking)>,
time: Res<Time>,
mut rng: ResMut<SeededRng>,
) {
for (mut transform, mut tracking) in &mut query {
*transform = interpolate_transforms(
tracking.initial_transform,
tracking.target_transform,
tracking.progress / TRANSITION_DURATION,
);
if tracking.progress < TRANSITION_DURATION {
tracking.progress += time.delta_secs();
} else {
tracking.initial_transform = *transform;
tracking.target_transform = random_transform(&mut rng.0);
tracking.progress = 0.0;
}
}
}
// Helper functions for random transforms and interpolation:
const TRANSLATION_BOUND_LOWER_X: f32 = -5.;
const TRANSLATION_BOUND_UPPER_X: f32 = 5.;
const TRANSLATION_BOUND_LOWER_Y: f32 = -1.;
const TRANSLATION_BOUND_UPPER_Y: f32 = 1.;
const TRANSLATION_BOUND_LOWER_Z: f32 = -2.;
const TRANSLATION_BOUND_UPPER_Z: f32 = 6.;
const SCALING_BOUND_LOWER_LOG: f32 = -1.2;
const SCALING_BOUND_UPPER_LOG: f32 = 1.2;
fn random_transform(rng: &mut impl Rng) -> Transform {
Transform {
translation: random_translation(rng),
rotation: random_rotation(rng),
scale: random_scale(rng),
}
}
fn random_translation(rng: &mut impl Rng) -> Vec3 {
let x = rng.r#gen::<f32>() * (TRANSLATION_BOUND_UPPER_X - TRANSLATION_BOUND_LOWER_X)
+ TRANSLATION_BOUND_LOWER_X;
let y = rng.r#gen::<f32>() * (TRANSLATION_BOUND_UPPER_Y - TRANSLATION_BOUND_LOWER_Y)
+ TRANSLATION_BOUND_LOWER_Y;
let z = rng.r#gen::<f32>() * (TRANSLATION_BOUND_UPPER_Z - TRANSLATION_BOUND_LOWER_Z)
+ TRANSLATION_BOUND_LOWER_Z;
Vec3::new(x, y, z)
}
fn random_scale(rng: &mut impl Rng) -> Vec3 {
let x_factor_log = rng.r#gen::<f32>() * (SCALING_BOUND_UPPER_LOG - SCALING_BOUND_LOWER_LOG)
+ SCALING_BOUND_LOWER_LOG;
let y_factor_log = rng.r#gen::<f32>() * (SCALING_BOUND_UPPER_LOG - SCALING_BOUND_LOWER_LOG)
+ SCALING_BOUND_LOWER_LOG;
let z_factor_log = rng.r#gen::<f32>() * (SCALING_BOUND_UPPER_LOG - SCALING_BOUND_LOWER_LOG)
+ SCALING_BOUND_LOWER_LOG;
Vec3::new(
ops::exp2(x_factor_log),
ops::exp2(y_factor_log),
ops::exp2(z_factor_log),
)
}
fn elerp(v1: Vec3, v2: Vec3, t: f32) -> Vec3 {
let x_factor_log = (1. - t) * ops::log2(v1.x) + t * ops::log2(v2.x);
let y_factor_log = (1. - t) * ops::log2(v1.y) + t * ops::log2(v2.y);
let z_factor_log = (1. - t) * ops::log2(v1.z) + t * ops::log2(v2.z);
Vec3::new(
ops::exp2(x_factor_log),
ops::exp2(y_factor_log),
ops::exp2(z_factor_log),
)
}
fn random_rotation(rng: &mut impl Rng) -> Quat {
let dir = random_direction(rng);
let angle = rng.r#gen::<f32>() * 2. * PI;
Quat::from_axis_angle(dir, angle)
}
fn random_direction(rng: &mut impl Rng) -> Vec3 {
let height = rng.r#gen::<f32>() * 2. - 1.;
let theta = rng.r#gen::<f32>() * 2. * PI;
build_direction(height, theta)
}
fn build_direction(height: f32, theta: f32) -> Vec3 {
let z = height;
let m = ops::sin(ops::acos(z));
let x = ops::cos(theta) * m;
let y = ops::sin(theta) * m;
Vec3::new(x, y, z)
}
fn interpolate_transforms(t1: Transform, t2: Transform, t: f32) -> Transform {
let translation = t1.translation.lerp(t2.translation, t);
let rotation = t1.rotation.slerp(t2.rotation, t);
let scale = elerp(t1.scale, t2.scale, t);
Transform {
translation,
rotation,
scale,
}
}

View File

@@ -0,0 +1,177 @@
//! This example demonstrates how to visualize lights properties through the gizmo API.
use std::f32::consts::{FRAC_PI_2, PI};
use bevy::{
color::palettes::css::{DARK_CYAN, GOLD, GRAY, PURPLE},
prelude::*,
};
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(Update, rotate_camera)
.add_systems(Update, update_config)
.run();
}
#[derive(Component)]
struct GizmoColorText;
fn gizmo_color_text(config: &LightGizmoConfigGroup) -> String {
match config.color {
LightGizmoColor::Manual(color) => format!("Manual {}", Srgba::from(color).to_hex()),
LightGizmoColor::Varied => "Random from entity".to_owned(),
LightGizmoColor::MatchLightColor => "Match light color".to_owned(),
LightGizmoColor::ByLightType => {
format!(
"Point {}, Spot {}, Directional {}",
Srgba::from(config.point_light_color).to_hex(),
Srgba::from(config.spot_light_color).to_hex(),
Srgba::from(config.directional_light_color).to_hex()
)
}
}
}
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
mut config_store: ResMut<GizmoConfigStore>,
) {
// Circular base.
commands.spawn((
Mesh3d(meshes.add(Circle::new(4.0))),
MeshMaterial3d(materials.add(Color::WHITE)),
Transform::from_rotation(Quat::from_rotation_x(-FRAC_PI_2)),
));
// Cubes.
{
let mesh = meshes.add(Cuboid::new(1.0, 1.0, 1.0));
let material = materials.add(Color::srgb_u8(124, 144, 255));
for x in [-2.0, 0.0, 2.0] {
commands.spawn((
Mesh3d(mesh.clone()),
MeshMaterial3d(material.clone()),
Transform::from_xyz(x, 0.5, 0.0),
));
}
}
// Lights.
{
commands.spawn((
PointLight {
shadows_enabled: true,
range: 2.0,
color: DARK_CYAN.into(),
..default()
},
Transform::from_xyz(0.0, 1.5, 0.0),
));
commands.spawn((
SpotLight {
shadows_enabled: true,
range: 3.5,
color: PURPLE.into(),
outer_angle: PI / 4.0,
inner_angle: PI / 4.0 * 0.8,
..default()
},
Transform::from_xyz(4.0, 2.0, 0.0).looking_at(Vec3::X * 1.5, Vec3::Y),
));
commands.spawn((
DirectionalLight {
color: GOLD.into(),
illuminance: DirectionalLight::default().illuminance * 0.05,
shadows_enabled: true,
..default()
},
Transform::from_xyz(-4.0, 2.0, 0.0).looking_at(Vec3::NEG_X * 1.5, Vec3::Y),
));
}
// Camera.
commands.spawn((
Camera3d::default(),
Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
));
// Example instructions and gizmo config.
{
commands.spawn((
Text::new(
"Press 'D' to toggle drawing gizmos on top of everything else in the scene\n\
Hold 'Left' or 'Right' to change the line width of the gizmos\n\
Press 'A' to toggle drawing of the light gizmos\n\
Press 'C' to cycle between the light gizmos coloring modes",
),
Node {
position_type: PositionType::Absolute,
top: Val::Px(12.0),
left: Val::Px(12.0),
..default()
},
));
let (_, light_config) = config_store.config_mut::<LightGizmoConfigGroup>();
light_config.draw_all = true;
light_config.color = LightGizmoColor::MatchLightColor;
commands
.spawn((
Text::new("Gizmo color mode: "),
GizmoColorText,
Node {
position_type: PositionType::Absolute,
bottom: Val::Px(12.0),
left: Val::Px(12.0),
..default()
},
))
.with_child(TextSpan(gizmo_color_text(light_config)));
}
}
fn rotate_camera(mut transform: Single<&mut Transform, With<Camera>>, time: Res<Time>) {
transform.rotate_around(Vec3::ZERO, Quat::from_rotation_y(time.delta_secs() / 2.));
}
fn update_config(
mut config_store: ResMut<GizmoConfigStore>,
keyboard: Res<ButtonInput<KeyCode>>,
time: Res<Time>,
color_text_query: Single<Entity, With<GizmoColorText>>,
mut writer: TextUiWriter,
) {
if keyboard.just_pressed(KeyCode::KeyD) {
for (_, config, _) in config_store.iter_mut() {
config.depth_bias = if config.depth_bias == 0. { -1. } else { 0. };
}
}
let (config, light_config) = config_store.config_mut::<LightGizmoConfigGroup>();
if keyboard.pressed(KeyCode::ArrowRight) {
config.line.width += 5. * time.delta_secs();
config.line.width = config.line.width.clamp(0., 50.);
}
if keyboard.pressed(KeyCode::ArrowLeft) {
config.line.width -= 5. * time.delta_secs();
config.line.width = config.line.width.clamp(0., 50.);
}
if keyboard.just_pressed(KeyCode::KeyA) {
config.enabled ^= true;
}
if keyboard.just_pressed(KeyCode::KeyC) {
light_config.color = match light_config.color {
LightGizmoColor::Manual(_) => LightGizmoColor::Varied,
LightGizmoColor::Varied => LightGizmoColor::MatchLightColor,
LightGizmoColor::MatchLightColor => LightGizmoColor::ByLightType,
LightGizmoColor::ByLightType => LightGizmoColor::Manual(GRAY.into()),
};
*writer.text(*color_text_query, 1) = gizmo_color_text(light_config);
}
}