pub struct Gizmos<'w, 's, Config = DefaultGizmoConfigGroup, Clear = ()>{
pub config: &'w GizmoConfig,
pub config_ext: &'w Config,
/* private fields */
}
Expand description
A SystemParam
for drawing gizmos.
They are drawn in immediate mode, which means they will be rendered only for
the frames, or ticks when in FixedMain
, in which
they are spawned.
A system in Main
will be cleared each rendering
frame, while a system in FixedMain
will be
cleared each time the RunFixedMainLoop
schedule is run.
Gizmos should be spawned before the Last
schedule
to ensure they are drawn.
To set up your own clearing context (useful for custom scheduling similar
to FixedMain
):
use bevy_gizmos::{prelude::*, *, gizmos::GizmoStorage};
struct ClearContextSetup;
impl Plugin for ClearContextSetup {
fn build(&self, app: &mut App) {
app.init_resource::<GizmoStorage<DefaultGizmoConfigGroup, MyContext>>()
// Make sure this context starts/ends cleanly if inside another context. E.g. it
// should start after the parent context starts and end after the parent context ends.
.add_systems(StartOfMyContext, start_gizmo_context::<DefaultGizmoConfigGroup, MyContext>)
// If not running multiple times, put this with [`start_gizmo_context`].
.add_systems(StartOfRun, clear_gizmo_context::<DefaultGizmoConfigGroup, MyContext>)
// If not running multiple times, put this with [`end_gizmo_context`].
.add_systems(EndOfRun, collect_requested_gizmos::<DefaultGizmoConfigGroup, MyContext>)
.add_systems(EndOfMyContext, end_gizmo_context::<DefaultGizmoConfigGroup, MyContext>)
.add_systems(
Last,
propagate_gizmos::<DefaultGizmoConfigGroup, MyContext>.before(UpdateGizmoMeshes),
);
}
}
Fields§
§config: &'w GizmoConfig
The currently used GizmoConfig
config_ext: &'w Config
The currently used GizmoConfigGroup
Methods from Deref<Target = GizmoBuffer<Config, Clear>>§
Sourcepub fn arc_2d(
&mut self,
isometry: impl Into<Isometry2d>,
arc_angle: f32,
radius: f32,
color: impl Into<Color>,
) -> Arc2dBuilder<'_, Config, Clear>
pub fn arc_2d( &mut self, isometry: impl Into<Isometry2d>, arc_angle: f32, radius: f32, color: impl Into<Color>, ) -> Arc2dBuilder<'_, Config, Clear>
Draw an arc, which is a part of the circumference of a circle, in 2D.
This should be called for each frame the arc needs to be rendered.
§Arguments
isometry
defines the translation and rotation of the arc.- the translation specifies the center of the arc
- the rotation is counter-clockwise starting from
Vec2::Y
arc_angle
sets the length of this arc, in radians.radius
controls the distance fromposition
to this arc, and thus its curvature.color
sets the color to draw the arc.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.arc_2d(Isometry2d::IDENTITY, FRAC_PI_4, 1., GREEN);
// Arcs have 32 line-segments by default.
// You may want to increase this for larger arcs.
gizmos
.arc_2d(Isometry2d::IDENTITY, FRAC_PI_4, 5., RED)
.resolution(64);
}
Examples found in repository?
40fn draw_example_collection(
41 mut gizmos: Gizmos,
42 mut my_gizmos: Gizmos<MyRoundGizmos>,
43 time: Res<Time>,
44) {
45 let sin_t_scaled = ops::sin(time.elapsed_secs()) * 50.;
46 gizmos.line_2d(Vec2::Y * -sin_t_scaled, Vec2::splat(-80.), RED);
47 gizmos.ray_2d(Vec2::Y * sin_t_scaled, Vec2::splat(80.), LIME);
48
49 gizmos
50 .grid_2d(
51 Isometry2d::IDENTITY,
52 UVec2::new(16, 9),
53 Vec2::new(80., 80.),
54 // Dark gray
55 LinearRgba::gray(0.05),
56 )
57 .outer_edges();
58
59 // Triangle
60 gizmos.linestrip_gradient_2d([
61 (Vec2::Y * 300., BLUE),
62 (Vec2::new(-255., -155.), RED),
63 (Vec2::new(255., -155.), LIME),
64 (Vec2::Y * 300., BLUE),
65 ]);
66
67 gizmos.rect_2d(Isometry2d::IDENTITY, Vec2::splat(650.), BLACK);
68
69 gizmos.cross_2d(Vec2::new(-160., 120.), 12., FUCHSIA);
70
71 let domain = Interval::EVERYWHERE;
72 let curve = FunctionCurve::new(domain, |t| Vec2::new(t, ops::sin(t / 25.0) * 100.0));
73 let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 50.0) as usize;
74 let times_and_colors = (0..=resolution)
75 .map(|n| n as f32 / resolution as f32)
76 .map(|t| (t - 0.5) * 600.0)
77 .map(|t| (t, TEAL.mix(&HOT_PINK, (t + 300.0) / 600.0)));
78 gizmos.curve_gradient_2d(curve, times_and_colors);
79
80 my_gizmos
81 .rounded_rect_2d(Isometry2d::IDENTITY, Vec2::splat(630.), BLACK)
82 .corner_radius(ops::cos(time.elapsed_secs() / 3.) * 100.);
83
84 // Circles have 32 line-segments by default.
85 // You may want to increase this for larger circles.
86 my_gizmos
87 .circle_2d(Isometry2d::IDENTITY, 300., NAVY)
88 .resolution(64);
89
90 my_gizmos.ellipse_2d(
91 Rot2::radians(time.elapsed_secs() % TAU),
92 Vec2::new(100., 200.),
93 YELLOW_GREEN,
94 );
95
96 // Arcs default resolution is linearly interpolated between
97 // 1 and 32, using the arc length as scalar.
98 my_gizmos.arc_2d(
99 Rot2::radians(sin_t_scaled / 10.),
100 FRAC_PI_2,
101 310.,
102 ORANGE_RED,
103 );
104 my_gizmos.arc_2d(Isometry2d::IDENTITY, FRAC_PI_2, 80.0, ORANGE_RED);
105 my_gizmos.long_arc_2d_between(Vec2::ZERO, Vec2::X * 20.0, Vec2::Y * 20.0, ORANGE_RED);
106 my_gizmos.short_arc_2d_between(Vec2::ZERO, Vec2::X * 40.0, Vec2::Y * 40.0, ORANGE_RED);
107
108 gizmos.arrow_2d(
109 Vec2::ZERO,
110 Vec2::from_angle(sin_t_scaled / -10. + PI / 2.) * 50.,
111 YELLOW,
112 );
113
114 // You can create more complex arrows using the arrow builder.
115 gizmos
116 .arrow_2d(
117 Vec2::ZERO,
118 Vec2::from_angle(sin_t_scaled / -10.) * 50.,
119 GREEN,
120 )
121 .with_double_end()
122 .with_tip_length(10.);
123}
Sourcepub fn arc_3d(
&mut self,
angle: f32,
radius: f32,
isometry: impl Into<Isometry3d>,
color: impl Into<Color>,
) -> Arc3dBuilder<'_, Config, Clear>
pub fn arc_3d( &mut self, angle: f32, radius: f32, isometry: impl Into<Isometry3d>, color: impl Into<Color>, ) -> Arc3dBuilder<'_, Config, Clear>
Draw an arc, which is a part of the circumference of a circle, in 3D. For default values this is drawing a standard arc. A standard arc is defined as
- an arc with a center at
Vec3::ZERO
- starting at
Vec3::X
- embedded in the XZ plane
- rotates counterclockwise
This should be called for each frame the arc needs to be rendered.
§Arguments
angle
: sets how much of a circle circumference is passed, e.g. PI is half a circle. This value should be in the range (-2 * PI..=2 * PI)radius
: distance between the arc and its center pointisometry
defines the translation and rotation of the arc.- the translation specifies the center of the arc
- the rotation is counter-clockwise starting from
Vec3::Y
color
: color of the arc
§Builder methods
The resolution of the arc (i.e. the level of detail) can be adjusted with the
.resolution(...)
method.
§Example
fn system(mut gizmos: Gizmos) {
// rotation rotates normal to point in the direction of `Vec3::NEG_ONE`
let rotation = Quat::from_rotation_arc(Vec3::Y, Vec3::NEG_ONE.normalize());
gizmos
.arc_3d(
270.0_f32.to_radians(),
0.25,
Isometry3d::new(Vec3::ONE, rotation),
ORANGE
)
.resolution(100);
}
Examples found in repository?
98fn draw_example_collection(
99 mut gizmos: Gizmos,
100 mut my_gizmos: Gizmos<MyRoundGizmos>,
101 time: Res<Time>,
102) {
103 gizmos.grid(
104 Quat::from_rotation_x(PI / 2.),
105 UVec2::splat(20),
106 Vec2::new(2., 2.),
107 // Light gray
108 LinearRgba::gray(0.65),
109 );
110 gizmos.grid(
111 Isometry3d::new(Vec3::splat(10.0), Quat::from_rotation_x(PI / 3. * 2.)),
112 UVec2::splat(20),
113 Vec2::new(2., 2.),
114 PURPLE,
115 );
116 gizmos.sphere(Vec3::splat(10.0), 1.0, PURPLE);
117
118 gizmos
119 .primitive_3d(
120 &Plane3d {
121 normal: Dir3::Y,
122 half_size: Vec2::splat(1.0),
123 },
124 Isometry3d::new(
125 Vec3::splat(4.0) + Vec2::from(ops::sin_cos(time.elapsed_secs())).extend(0.0),
126 Quat::from_rotation_x(PI / 2. + time.elapsed_secs()),
127 ),
128 GREEN,
129 )
130 .cell_count(UVec2::new(5, 10))
131 .spacing(Vec2::new(0.2, 0.1));
132
133 gizmos.cuboid(
134 Transform::from_translation(Vec3::Y * 0.5).with_scale(Vec3::splat(1.25)),
135 BLACK,
136 );
137 gizmos.rect(
138 Isometry3d::new(
139 Vec3::new(ops::cos(time.elapsed_secs()) * 2.5, 1., 0.),
140 Quat::from_rotation_y(PI / 2.),
141 ),
142 Vec2::splat(2.),
143 LIME,
144 );
145
146 gizmos.cross(Vec3::new(-1., 1., 1.), 0.5, FUCHSIA);
147
148 let domain = Interval::EVERYWHERE;
149 let curve = FunctionCurve::new(domain, |t| {
150 (Vec2::from(ops::sin_cos(t * 10.0))).extend(t - 6.0)
151 });
152 let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 100.0) as usize;
153 let times_and_colors = (0..=resolution)
154 .map(|n| n as f32 / resolution as f32)
155 .map(|t| t * 5.0)
156 .map(|t| (t, TEAL.mix(&HOT_PINK, t / 5.0)));
157 gizmos.curve_gradient_3d(curve, times_and_colors);
158
159 my_gizmos.sphere(Vec3::new(1., 0.5, 0.), 0.5, RED);
160
161 my_gizmos
162 .rounded_cuboid(Vec3::new(-2.0, 0.75, -0.75), Vec3::splat(0.9), TURQUOISE)
163 .edge_radius(0.1)
164 .arc_resolution(4);
165
166 for y in [0., 0.5, 1.] {
167 gizmos.ray(
168 Vec3::new(1., y, 0.),
169 Vec3::new(-3., ops::sin(time.elapsed_secs() * 3.), 0.),
170 BLUE,
171 );
172 }
173
174 my_gizmos
175 .arc_3d(
176 180.0_f32.to_radians(),
177 0.2,
178 Isometry3d::new(
179 Vec3::ONE,
180 Quat::from_rotation_arc(Vec3::Y, Vec3::ONE.normalize()),
181 ),
182 ORANGE,
183 )
184 .resolution(10);
185
186 // Circles have 32 line-segments by default.
187 my_gizmos.circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3., BLACK);
188
189 // You may want to increase this for larger circles or spheres.
190 my_gizmos
191 .circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3.1, NAVY)
192 .resolution(64);
193 my_gizmos
194 .sphere(Isometry3d::IDENTITY, 3.2, BLACK)
195 .resolution(64);
196
197 gizmos.arrow(Vec3::ZERO, Vec3::splat(1.5), YELLOW);
198
199 // You can create more complex arrows using the arrow builder.
200 gizmos
201 .arrow(Vec3::new(2., 0., 2.), Vec3::new(2., 2., 2.), ORANGE_RED)
202 .with_double_end()
203 .with_tip_length(0.5);
204}
Sourcepub fn short_arc_3d_between(
&mut self,
center: Vec3,
from: Vec3,
to: Vec3,
color: impl Into<Color>,
) -> Arc3dBuilder<'_, Config, Clear>
pub fn short_arc_3d_between( &mut self, center: Vec3, from: Vec3, to: Vec3, color: impl Into<Color>, ) -> Arc3dBuilder<'_, Config, Clear>
Draws the shortest arc between two points (from
and to
) relative to a specified center
point.
§Arguments
center
: The center point around which the arc is drawn.from
: The starting point of the arc.to
: The ending point of the arc.color
: color of the arc
§Builder methods
The resolution of the arc (i.e. the level of detail) can be adjusted with the
.resolution(...)
method.
§Examples
fn system(mut gizmos: Gizmos) {
gizmos.short_arc_3d_between(
Vec3::ONE,
Vec3::ONE + Vec3::NEG_ONE,
Vec3::ZERO,
ORANGE
)
.resolution(100);
}
§Notes
- This method assumes that the points
from
andto
are distinct fromcenter
. If one of the points is coincident withcenter
, nothing is rendered. - The arc is drawn as a portion of a circle with a radius equal to the distance from the
center
tofrom
. If the distance fromcenter
toto
is not equal to the radius, then the results will behave as if this were the case
Sourcepub fn long_arc_3d_between(
&mut self,
center: Vec3,
from: Vec3,
to: Vec3,
color: impl Into<Color>,
) -> Arc3dBuilder<'_, Config, Clear>
pub fn long_arc_3d_between( &mut self, center: Vec3, from: Vec3, to: Vec3, color: impl Into<Color>, ) -> Arc3dBuilder<'_, Config, Clear>
Draws the longest arc between two points (from
and to
) relative to a specified center
point.
§Arguments
center
: The center point around which the arc is drawn.from
: The starting point of the arc.to
: The ending point of the arc.color
: color of the arc
§Builder methods
The resolution of the arc (i.e. the level of detail) can be adjusted with the
.resolution(...)
method.
§Examples
fn system(mut gizmos: Gizmos) {
gizmos.long_arc_3d_between(
Vec3::ONE,
Vec3::ONE + Vec3::NEG_ONE,
Vec3::ZERO,
ORANGE
)
.resolution(100);
}
§Notes
- This method assumes that the points
from
andto
are distinct fromcenter
. If one of the points is coincident withcenter
, nothing is rendered. - The arc is drawn as a portion of a circle with a radius equal to the distance from the
center
tofrom
. If the distance fromcenter
toto
is not equal to the radius, then the results will behave as if this were the case.
Sourcepub fn short_arc_2d_between(
&mut self,
center: Vec2,
from: Vec2,
to: Vec2,
color: impl Into<Color>,
) -> Arc2dBuilder<'_, Config, Clear>
pub fn short_arc_2d_between( &mut self, center: Vec2, from: Vec2, to: Vec2, color: impl Into<Color>, ) -> Arc2dBuilder<'_, Config, Clear>
Draws the shortest arc between two points (from
and to
) relative to a specified center
point.
§Arguments
center
: The center point around which the arc is drawn.from
: The starting point of the arc.to
: The ending point of the arc.color
: color of the arc
§Builder methods
The resolution of the arc (i.e. the level of detail) can be adjusted with the
.resolution(...)
method.
§Examples
fn system(mut gizmos: Gizmos) {
gizmos.short_arc_2d_between(
Vec2::ZERO,
Vec2::X,
Vec2::Y,
ORANGE
)
.resolution(100);
}
§Notes
- This method assumes that the points
from
andto
are distinct fromcenter
. If one of the points is coincident withcenter
, nothing is rendered. - The arc is drawn as a portion of a circle with a radius equal to the distance from the
center
tofrom
. If the distance fromcenter
toto
is not equal to the radius, then the results will behave as if this were the case
Examples found in repository?
40fn draw_example_collection(
41 mut gizmos: Gizmos,
42 mut my_gizmos: Gizmos<MyRoundGizmos>,
43 time: Res<Time>,
44) {
45 let sin_t_scaled = ops::sin(time.elapsed_secs()) * 50.;
46 gizmos.line_2d(Vec2::Y * -sin_t_scaled, Vec2::splat(-80.), RED);
47 gizmos.ray_2d(Vec2::Y * sin_t_scaled, Vec2::splat(80.), LIME);
48
49 gizmos
50 .grid_2d(
51 Isometry2d::IDENTITY,
52 UVec2::new(16, 9),
53 Vec2::new(80., 80.),
54 // Dark gray
55 LinearRgba::gray(0.05),
56 )
57 .outer_edges();
58
59 // Triangle
60 gizmos.linestrip_gradient_2d([
61 (Vec2::Y * 300., BLUE),
62 (Vec2::new(-255., -155.), RED),
63 (Vec2::new(255., -155.), LIME),
64 (Vec2::Y * 300., BLUE),
65 ]);
66
67 gizmos.rect_2d(Isometry2d::IDENTITY, Vec2::splat(650.), BLACK);
68
69 gizmos.cross_2d(Vec2::new(-160., 120.), 12., FUCHSIA);
70
71 let domain = Interval::EVERYWHERE;
72 let curve = FunctionCurve::new(domain, |t| Vec2::new(t, ops::sin(t / 25.0) * 100.0));
73 let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 50.0) as usize;
74 let times_and_colors = (0..=resolution)
75 .map(|n| n as f32 / resolution as f32)
76 .map(|t| (t - 0.5) * 600.0)
77 .map(|t| (t, TEAL.mix(&HOT_PINK, (t + 300.0) / 600.0)));
78 gizmos.curve_gradient_2d(curve, times_and_colors);
79
80 my_gizmos
81 .rounded_rect_2d(Isometry2d::IDENTITY, Vec2::splat(630.), BLACK)
82 .corner_radius(ops::cos(time.elapsed_secs() / 3.) * 100.);
83
84 // Circles have 32 line-segments by default.
85 // You may want to increase this for larger circles.
86 my_gizmos
87 .circle_2d(Isometry2d::IDENTITY, 300., NAVY)
88 .resolution(64);
89
90 my_gizmos.ellipse_2d(
91 Rot2::radians(time.elapsed_secs() % TAU),
92 Vec2::new(100., 200.),
93 YELLOW_GREEN,
94 );
95
96 // Arcs default resolution is linearly interpolated between
97 // 1 and 32, using the arc length as scalar.
98 my_gizmos.arc_2d(
99 Rot2::radians(sin_t_scaled / 10.),
100 FRAC_PI_2,
101 310.,
102 ORANGE_RED,
103 );
104 my_gizmos.arc_2d(Isometry2d::IDENTITY, FRAC_PI_2, 80.0, ORANGE_RED);
105 my_gizmos.long_arc_2d_between(Vec2::ZERO, Vec2::X * 20.0, Vec2::Y * 20.0, ORANGE_RED);
106 my_gizmos.short_arc_2d_between(Vec2::ZERO, Vec2::X * 40.0, Vec2::Y * 40.0, ORANGE_RED);
107
108 gizmos.arrow_2d(
109 Vec2::ZERO,
110 Vec2::from_angle(sin_t_scaled / -10. + PI / 2.) * 50.,
111 YELLOW,
112 );
113
114 // You can create more complex arrows using the arrow builder.
115 gizmos
116 .arrow_2d(
117 Vec2::ZERO,
118 Vec2::from_angle(sin_t_scaled / -10.) * 50.,
119 GREEN,
120 )
121 .with_double_end()
122 .with_tip_length(10.);
123}
Sourcepub fn long_arc_2d_between(
&mut self,
center: Vec2,
from: Vec2,
to: Vec2,
color: impl Into<Color>,
) -> Arc2dBuilder<'_, Config, Clear>
pub fn long_arc_2d_between( &mut self, center: Vec2, from: Vec2, to: Vec2, color: impl Into<Color>, ) -> Arc2dBuilder<'_, Config, Clear>
Draws the longest arc between two points (from
and to
) relative to a specified center
point.
§Arguments
center
: The center point around which the arc is drawn.from
: The starting point of the arc.to
: The ending point of the arc.color
: color of the arc
§Builder methods
The resolution of the arc (i.e. the level of detail) can be adjusted with the
.resolution(...)
method.
§Examples
fn system(mut gizmos: Gizmos) {
gizmos.long_arc_2d_between(
Vec2::ZERO,
Vec2::X,
Vec2::Y,
ORANGE
)
.resolution(100);
}
§Notes
- This method assumes that the points
from
andto
are distinct fromcenter
. If one of the points is coincident withcenter
, nothing is rendered. - The arc is drawn as a portion of a circle with a radius equal to the distance from the
center
tofrom
. If the distance fromcenter
toto
is not equal to the radius, then the results will behave as if this were the case.
Examples found in repository?
40fn draw_example_collection(
41 mut gizmos: Gizmos,
42 mut my_gizmos: Gizmos<MyRoundGizmos>,
43 time: Res<Time>,
44) {
45 let sin_t_scaled = ops::sin(time.elapsed_secs()) * 50.;
46 gizmos.line_2d(Vec2::Y * -sin_t_scaled, Vec2::splat(-80.), RED);
47 gizmos.ray_2d(Vec2::Y * sin_t_scaled, Vec2::splat(80.), LIME);
48
49 gizmos
50 .grid_2d(
51 Isometry2d::IDENTITY,
52 UVec2::new(16, 9),
53 Vec2::new(80., 80.),
54 // Dark gray
55 LinearRgba::gray(0.05),
56 )
57 .outer_edges();
58
59 // Triangle
60 gizmos.linestrip_gradient_2d([
61 (Vec2::Y * 300., BLUE),
62 (Vec2::new(-255., -155.), RED),
63 (Vec2::new(255., -155.), LIME),
64 (Vec2::Y * 300., BLUE),
65 ]);
66
67 gizmos.rect_2d(Isometry2d::IDENTITY, Vec2::splat(650.), BLACK);
68
69 gizmos.cross_2d(Vec2::new(-160., 120.), 12., FUCHSIA);
70
71 let domain = Interval::EVERYWHERE;
72 let curve = FunctionCurve::new(domain, |t| Vec2::new(t, ops::sin(t / 25.0) * 100.0));
73 let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 50.0) as usize;
74 let times_and_colors = (0..=resolution)
75 .map(|n| n as f32 / resolution as f32)
76 .map(|t| (t - 0.5) * 600.0)
77 .map(|t| (t, TEAL.mix(&HOT_PINK, (t + 300.0) / 600.0)));
78 gizmos.curve_gradient_2d(curve, times_and_colors);
79
80 my_gizmos
81 .rounded_rect_2d(Isometry2d::IDENTITY, Vec2::splat(630.), BLACK)
82 .corner_radius(ops::cos(time.elapsed_secs() / 3.) * 100.);
83
84 // Circles have 32 line-segments by default.
85 // You may want to increase this for larger circles.
86 my_gizmos
87 .circle_2d(Isometry2d::IDENTITY, 300., NAVY)
88 .resolution(64);
89
90 my_gizmos.ellipse_2d(
91 Rot2::radians(time.elapsed_secs() % TAU),
92 Vec2::new(100., 200.),
93 YELLOW_GREEN,
94 );
95
96 // Arcs default resolution is linearly interpolated between
97 // 1 and 32, using the arc length as scalar.
98 my_gizmos.arc_2d(
99 Rot2::radians(sin_t_scaled / 10.),
100 FRAC_PI_2,
101 310.,
102 ORANGE_RED,
103 );
104 my_gizmos.arc_2d(Isometry2d::IDENTITY, FRAC_PI_2, 80.0, ORANGE_RED);
105 my_gizmos.long_arc_2d_between(Vec2::ZERO, Vec2::X * 20.0, Vec2::Y * 20.0, ORANGE_RED);
106 my_gizmos.short_arc_2d_between(Vec2::ZERO, Vec2::X * 40.0, Vec2::Y * 40.0, ORANGE_RED);
107
108 gizmos.arrow_2d(
109 Vec2::ZERO,
110 Vec2::from_angle(sin_t_scaled / -10. + PI / 2.) * 50.,
111 YELLOW,
112 );
113
114 // You can create more complex arrows using the arrow builder.
115 gizmos
116 .arrow_2d(
117 Vec2::ZERO,
118 Vec2::from_angle(sin_t_scaled / -10.) * 50.,
119 GREEN,
120 )
121 .with_double_end()
122 .with_tip_length(10.);
123}
Sourcepub fn arrow(
&mut self,
start: Vec3,
end: Vec3,
color: impl Into<Color>,
) -> ArrowBuilder<'_, Config, Clear>
pub fn arrow( &mut self, start: Vec3, end: Vec3, color: impl Into<Color>, ) -> ArrowBuilder<'_, Config, Clear>
Draw an arrow in 3D, from start
to end
. Has four tips for convenient viewing from any direction.
This should be called for each frame the arrow needs to be rendered.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.arrow(Vec3::ZERO, Vec3::ONE, GREEN);
}
Examples found in repository?
122fn draw_ship_axes(mut gizmos: Gizmos, ship_transform: Single<&Transform, With<Ship>>) {
123 // Local Z-axis arrow, negative direction
124 let z_ends = arrow_ends(*ship_transform, Vec3::NEG_Z, 1.5);
125 gizmos.arrow(z_ends.0, z_ends.1, RED);
126
127 // local X-axis arrow
128 let x_ends = arrow_ends(*ship_transform, Vec3::X, 1.5);
129 gizmos.arrow(x_ends.0, x_ends.1, Color::srgb(0.65, 0., 0.));
130}
131
132// Draw the randomly generated axes
133fn draw_random_axes(mut gizmos: Gizmos, random_axes: Single<&RandomAxes>) {
134 let RandomAxes(v1, v2) = *random_axes;
135 gizmos.arrow(Vec3::ZERO, 1.5 * *v1, WHITE);
136 gizmos.arrow(Vec3::ZERO, 1.5 * *v2, GRAY);
137}
More examples
98fn draw_example_collection(
99 mut gizmos: Gizmos,
100 mut my_gizmos: Gizmos<MyRoundGizmos>,
101 time: Res<Time>,
102) {
103 gizmos.grid(
104 Quat::from_rotation_x(PI / 2.),
105 UVec2::splat(20),
106 Vec2::new(2., 2.),
107 // Light gray
108 LinearRgba::gray(0.65),
109 );
110 gizmos.grid(
111 Isometry3d::new(Vec3::splat(10.0), Quat::from_rotation_x(PI / 3. * 2.)),
112 UVec2::splat(20),
113 Vec2::new(2., 2.),
114 PURPLE,
115 );
116 gizmos.sphere(Vec3::splat(10.0), 1.0, PURPLE);
117
118 gizmos
119 .primitive_3d(
120 &Plane3d {
121 normal: Dir3::Y,
122 half_size: Vec2::splat(1.0),
123 },
124 Isometry3d::new(
125 Vec3::splat(4.0) + Vec2::from(ops::sin_cos(time.elapsed_secs())).extend(0.0),
126 Quat::from_rotation_x(PI / 2. + time.elapsed_secs()),
127 ),
128 GREEN,
129 )
130 .cell_count(UVec2::new(5, 10))
131 .spacing(Vec2::new(0.2, 0.1));
132
133 gizmos.cuboid(
134 Transform::from_translation(Vec3::Y * 0.5).with_scale(Vec3::splat(1.25)),
135 BLACK,
136 );
137 gizmos.rect(
138 Isometry3d::new(
139 Vec3::new(ops::cos(time.elapsed_secs()) * 2.5, 1., 0.),
140 Quat::from_rotation_y(PI / 2.),
141 ),
142 Vec2::splat(2.),
143 LIME,
144 );
145
146 gizmos.cross(Vec3::new(-1., 1., 1.), 0.5, FUCHSIA);
147
148 let domain = Interval::EVERYWHERE;
149 let curve = FunctionCurve::new(domain, |t| {
150 (Vec2::from(ops::sin_cos(t * 10.0))).extend(t - 6.0)
151 });
152 let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 100.0) as usize;
153 let times_and_colors = (0..=resolution)
154 .map(|n| n as f32 / resolution as f32)
155 .map(|t| t * 5.0)
156 .map(|t| (t, TEAL.mix(&HOT_PINK, t / 5.0)));
157 gizmos.curve_gradient_3d(curve, times_and_colors);
158
159 my_gizmos.sphere(Vec3::new(1., 0.5, 0.), 0.5, RED);
160
161 my_gizmos
162 .rounded_cuboid(Vec3::new(-2.0, 0.75, -0.75), Vec3::splat(0.9), TURQUOISE)
163 .edge_radius(0.1)
164 .arc_resolution(4);
165
166 for y in [0., 0.5, 1.] {
167 gizmos.ray(
168 Vec3::new(1., y, 0.),
169 Vec3::new(-3., ops::sin(time.elapsed_secs() * 3.), 0.),
170 BLUE,
171 );
172 }
173
174 my_gizmos
175 .arc_3d(
176 180.0_f32.to_radians(),
177 0.2,
178 Isometry3d::new(
179 Vec3::ONE,
180 Quat::from_rotation_arc(Vec3::Y, Vec3::ONE.normalize()),
181 ),
182 ORANGE,
183 )
184 .resolution(10);
185
186 // Circles have 32 line-segments by default.
187 my_gizmos.circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3., BLACK);
188
189 // You may want to increase this for larger circles or spheres.
190 my_gizmos
191 .circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3.1, NAVY)
192 .resolution(64);
193 my_gizmos
194 .sphere(Isometry3d::IDENTITY, 3.2, BLACK)
195 .resolution(64);
196
197 gizmos.arrow(Vec3::ZERO, Vec3::splat(1.5), YELLOW);
198
199 // You can create more complex arrows using the arrow builder.
200 gizmos
201 .arrow(Vec3::new(2., 0., 2.), Vec3::new(2., 2., 2.), ORANGE_RED)
202 .with_double_end()
203 .with_tip_length(0.5);
204}
Sourcepub fn arrow_2d(
&mut self,
start: Vec2,
end: Vec2,
color: impl Into<Color>,
) -> ArrowBuilder<'_, Config, Clear>
pub fn arrow_2d( &mut self, start: Vec2, end: Vec2, color: impl Into<Color>, ) -> ArrowBuilder<'_, Config, Clear>
Draw an arrow in 2D (on the xy plane), from start
to end
.
This should be called for each frame the arrow needs to be rendered.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.arrow_2d(Vec2::ZERO, Vec2::X, GREEN);
}
Examples found in repository?
185fn draw_control_points(
186 control_points: Res<ControlPoints>,
187 spline_mode: Res<SplineMode>,
188 mut gizmos: Gizmos,
189) {
190 for &(point, tangent) in &control_points.points_and_tangents {
191 gizmos.circle_2d(point, 10.0, Color::srgb(0.0, 1.0, 0.0));
192
193 if matches!(*spline_mode, SplineMode::Hermite) {
194 gizmos.arrow_2d(point, point + tangent, Color::srgb(1.0, 0.0, 0.0));
195 }
196 }
197}
198
199/// Helper function for generating a [`Curve`] from [control points] and selected modes.
200///
201/// [control points]: ControlPoints
202fn form_curve(
203 control_points: &ControlPoints,
204 spline_mode: SplineMode,
205 cycling_mode: CyclingMode,
206) -> Curve {
207 let (points, tangents): (Vec<_>, Vec<_>) =
208 control_points.points_and_tangents.iter().copied().unzip();
209
210 match spline_mode {
211 SplineMode::Hermite => {
212 let spline = CubicHermite::new(points, tangents);
213 Curve(match cycling_mode {
214 CyclingMode::NotCyclic => spline.to_curve().ok(),
215 CyclingMode::Cyclic => spline.to_curve_cyclic().ok(),
216 })
217 }
218 SplineMode::Cardinal => {
219 let spline = CubicCardinalSpline::new_catmull_rom(points);
220 Curve(match cycling_mode {
221 CyclingMode::NotCyclic => spline.to_curve().ok(),
222 CyclingMode::Cyclic => spline.to_curve_cyclic().ok(),
223 })
224 }
225 SplineMode::B => {
226 let spline = CubicBSpline::new(points);
227 Curve(match cycling_mode {
228 CyclingMode::NotCyclic => spline.to_curve().ok(),
229 CyclingMode::Cyclic => spline.to_curve_cyclic().ok(),
230 })
231 }
232 }
233}
234
235// --------------------
236// Text-related Components and Systems
237// --------------------
238
239/// Marker component for the text node that displays the current [`SplineMode`].
240#[derive(Component)]
241struct SplineModeText;
242
243/// Marker component for the text node that displays the current [`CyclingMode`].
244#[derive(Component)]
245struct CyclingModeText;
246
247fn update_spline_mode_text(
248 spline_mode: Res<SplineMode>,
249 mut spline_mode_text: Query<&mut Text, With<SplineModeText>>,
250) {
251 if !spline_mode.is_changed() {
252 return;
253 }
254
255 let new_text = format!("Spline: {}", *spline_mode);
256
257 for mut spline_mode_text in spline_mode_text.iter_mut() {
258 (**spline_mode_text).clone_from(&new_text);
259 }
260}
261
262fn update_cycling_mode_text(
263 cycling_mode: Res<CyclingMode>,
264 mut cycling_mode_text: Query<&mut Text, With<CyclingModeText>>,
265) {
266 if !cycling_mode.is_changed() {
267 return;
268 }
269
270 let new_text = format!("{}", *cycling_mode);
271
272 for mut cycling_mode_text in cycling_mode_text.iter_mut() {
273 (**cycling_mode_text).clone_from(&new_text);
274 }
275}
276
277// -----------------------------------
278// Input-related Resources and Systems
279// -----------------------------------
280
281/// A small state machine which tracks a click-and-drag motion used to create new control points.
282///
283/// When the user is not doing a click-and-drag motion, the `start` field is `None`. When the user
284/// presses the left mouse button, the location of that press is temporarily stored in the field.
285#[derive(Clone, Default, Resource)]
286struct MouseEditMove {
287 start: Option<Vec2>,
288}
289
290/// The current mouse position, if known.
291#[derive(Clone, Default, Resource)]
292struct MousePosition(Option<Vec2>);
293
294/// Update the current cursor position and track it in the [`MousePosition`] resource.
295fn handle_mouse_move(
296 mut cursor_events: EventReader<CursorMoved>,
297 mut mouse_position: ResMut<MousePosition>,
298) {
299 if let Some(cursor_event) = cursor_events.read().last() {
300 mouse_position.0 = Some(cursor_event.position);
301 }
302}
303
304/// This system handles updating the [`MouseEditMove`] resource, orchestrating the logical part
305/// of the click-and-drag motion which actually creates new control points.
306fn handle_mouse_press(
307 mut button_events: EventReader<MouseButtonInput>,
308 mouse_position: Res<MousePosition>,
309 mut edit_move: ResMut<MouseEditMove>,
310 mut control_points: ResMut<ControlPoints>,
311 camera: Single<(&Camera, &GlobalTransform)>,
312) {
313 let Some(mouse_pos) = mouse_position.0 else {
314 return;
315 };
316
317 // Handle click and drag behavior
318 for button_event in button_events.read() {
319 if button_event.button != MouseButton::Left {
320 continue;
321 }
322
323 match button_event.state {
324 ButtonState::Pressed => {
325 if edit_move.start.is_some() {
326 // If the edit move already has a start, press event should do nothing.
327 continue;
328 }
329 // This press represents the start of the edit move.
330 edit_move.start = Some(mouse_pos);
331 }
332
333 ButtonState::Released => {
334 // Release is only meaningful if we started an edit move.
335 let Some(start) = edit_move.start else {
336 continue;
337 };
338
339 let (camera, camera_transform) = *camera;
340
341 // Convert the starting point and end point (current mouse pos) into world coords:
342 let Ok(point) = camera.viewport_to_world_2d(camera_transform, start) else {
343 continue;
344 };
345 let Ok(end_point) = camera.viewport_to_world_2d(camera_transform, mouse_pos) else {
346 continue;
347 };
348 let tangent = end_point - point;
349
350 // The start of the click-and-drag motion represents the point to add,
351 // while the difference with the current position represents the tangent.
352 control_points.points_and_tangents.push((point, tangent));
353
354 // Reset the edit move since we've consumed it.
355 edit_move.start = None;
356 }
357 }
358 }
359}
360
361/// This system handles drawing the "preview" control point based on the state of [`MouseEditMove`].
362fn draw_edit_move(
363 edit_move: Res<MouseEditMove>,
364 mouse_position: Res<MousePosition>,
365 mut gizmos: Gizmos,
366 camera: Single<(&Camera, &GlobalTransform)>,
367) {
368 let Some(start) = edit_move.start else {
369 return;
370 };
371 let Some(mouse_pos) = mouse_position.0 else {
372 return;
373 };
374
375 let (camera, camera_transform) = *camera;
376
377 // Resources store data in viewport coordinates, so we need to convert to world coordinates
378 // to display them:
379 let Ok(start) = camera.viewport_to_world_2d(camera_transform, start) else {
380 return;
381 };
382 let Ok(end) = camera.viewport_to_world_2d(camera_transform, mouse_pos) else {
383 return;
384 };
385
386 gizmos.circle_2d(start, 10.0, Color::srgb(0.0, 1.0, 0.7));
387 gizmos.circle_2d(start, 7.0, Color::srgb(0.0, 1.0, 0.7));
388 gizmos.arrow_2d(start, end, Color::srgb(1.0, 0.0, 0.7));
389}
More examples
40fn draw_example_collection(
41 mut gizmos: Gizmos,
42 mut my_gizmos: Gizmos<MyRoundGizmos>,
43 time: Res<Time>,
44) {
45 let sin_t_scaled = ops::sin(time.elapsed_secs()) * 50.;
46 gizmos.line_2d(Vec2::Y * -sin_t_scaled, Vec2::splat(-80.), RED);
47 gizmos.ray_2d(Vec2::Y * sin_t_scaled, Vec2::splat(80.), LIME);
48
49 gizmos
50 .grid_2d(
51 Isometry2d::IDENTITY,
52 UVec2::new(16, 9),
53 Vec2::new(80., 80.),
54 // Dark gray
55 LinearRgba::gray(0.05),
56 )
57 .outer_edges();
58
59 // Triangle
60 gizmos.linestrip_gradient_2d([
61 (Vec2::Y * 300., BLUE),
62 (Vec2::new(-255., -155.), RED),
63 (Vec2::new(255., -155.), LIME),
64 (Vec2::Y * 300., BLUE),
65 ]);
66
67 gizmos.rect_2d(Isometry2d::IDENTITY, Vec2::splat(650.), BLACK);
68
69 gizmos.cross_2d(Vec2::new(-160., 120.), 12., FUCHSIA);
70
71 let domain = Interval::EVERYWHERE;
72 let curve = FunctionCurve::new(domain, |t| Vec2::new(t, ops::sin(t / 25.0) * 100.0));
73 let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 50.0) as usize;
74 let times_and_colors = (0..=resolution)
75 .map(|n| n as f32 / resolution as f32)
76 .map(|t| (t - 0.5) * 600.0)
77 .map(|t| (t, TEAL.mix(&HOT_PINK, (t + 300.0) / 600.0)));
78 gizmos.curve_gradient_2d(curve, times_and_colors);
79
80 my_gizmos
81 .rounded_rect_2d(Isometry2d::IDENTITY, Vec2::splat(630.), BLACK)
82 .corner_radius(ops::cos(time.elapsed_secs() / 3.) * 100.);
83
84 // Circles have 32 line-segments by default.
85 // You may want to increase this for larger circles.
86 my_gizmos
87 .circle_2d(Isometry2d::IDENTITY, 300., NAVY)
88 .resolution(64);
89
90 my_gizmos.ellipse_2d(
91 Rot2::radians(time.elapsed_secs() % TAU),
92 Vec2::new(100., 200.),
93 YELLOW_GREEN,
94 );
95
96 // Arcs default resolution is linearly interpolated between
97 // 1 and 32, using the arc length as scalar.
98 my_gizmos.arc_2d(
99 Rot2::radians(sin_t_scaled / 10.),
100 FRAC_PI_2,
101 310.,
102 ORANGE_RED,
103 );
104 my_gizmos.arc_2d(Isometry2d::IDENTITY, FRAC_PI_2, 80.0, ORANGE_RED);
105 my_gizmos.long_arc_2d_between(Vec2::ZERO, Vec2::X * 20.0, Vec2::Y * 20.0, ORANGE_RED);
106 my_gizmos.short_arc_2d_between(Vec2::ZERO, Vec2::X * 40.0, Vec2::Y * 40.0, ORANGE_RED);
107
108 gizmos.arrow_2d(
109 Vec2::ZERO,
110 Vec2::from_angle(sin_t_scaled / -10. + PI / 2.) * 50.,
111 YELLOW,
112 );
113
114 // You can create more complex arrows using the arrow builder.
115 gizmos
116 .arrow_2d(
117 Vec2::ZERO,
118 Vec2::from_angle(sin_t_scaled / -10.) * 50.,
119 GREEN,
120 )
121 .with_double_end()
122 .with_tip_length(10.);
123}
Sourcepub fn axes(&mut self, transform: impl TransformPoint, base_length: f32)
pub fn axes(&mut self, transform: impl TransformPoint, base_length: f32)
Draw a set of axes local to the given transform (transform
), with length scaled by a factor
of base_length
.
This should be called for each frame the axes need to be rendered.
§Example
fn draw_axes(
mut gizmos: Gizmos,
query: Query<&Transform, With<MyComponent>>,
) {
for &transform in &query {
gizmos.axes(transform, 1.);
}
}
Examples found in repository?
More examples
188fn joint_animation(
189 time: Res<Time>,
190 mut query: Query<(&mut Transform, &AnimatedJoint)>,
191 mut gizmos: Gizmos,
192) {
193 for (mut transform, animated_joint) in &mut query {
194 match animated_joint.0 {
195 -5 => {
196 transform.rotation =
197 Quat::from_rotation_x(FRAC_PI_2 * ops::sin(time.elapsed_secs()));
198 }
199 -4 => {
200 transform.rotation =
201 Quat::from_rotation_y(FRAC_PI_2 * ops::sin(time.elapsed_secs()));
202 }
203 -3 => {
204 transform.rotation =
205 Quat::from_rotation_z(FRAC_PI_2 * ops::sin(time.elapsed_secs()));
206 }
207 -2 => {
208 transform.scale.x = ops::sin(time.elapsed_secs()) + 1.0;
209 }
210 -1 => {
211 transform.scale.y = ops::sin(time.elapsed_secs()) + 1.0;
212 }
213 0 => {
214 transform.translation.x = 0.5 * ops::sin(time.elapsed_secs());
215 transform.translation.y = ops::cos(time.elapsed_secs());
216 }
217 1 => {
218 transform.translation.y = ops::sin(time.elapsed_secs());
219 transform.translation.z = ops::cos(time.elapsed_secs());
220 }
221 2 => {
222 transform.translation.x = ops::sin(time.elapsed_secs());
223 }
224 3 => {
225 transform.translation.y = ops::sin(time.elapsed_secs());
226 transform.scale.x = ops::sin(time.elapsed_secs()) + 1.0;
227 }
228 _ => (),
229 }
230 // Show transform
231 let mut axis = *transform;
232 axis.translation.x += animated_joint.0 as f32 * 1.5;
233 gizmos.axes(axis, 1.0);
234 }
235}
Sourcepub fn axes_2d(&mut self, transform: impl TransformPoint, base_length: f32)
pub fn axes_2d(&mut self, transform: impl TransformPoint, base_length: f32)
Draw a set of axes local to the given transform (transform
), with length scaled by a factor
of base_length
.
This should be called for each frame the axes need to be rendered.
§Example
fn draw_axes_2d(
mut gizmos: Gizmos,
query: Query<&Transform, With<AxesComponent>>,
) {
for &transform in &query {
gizmos.axes_2d(transform, 1.);
}
}
Sourcepub fn ellipse(
&mut self,
isometry: impl Into<Isometry3d>,
half_size: Vec2,
color: impl Into<Color>,
) -> EllipseBuilder<'_, Config, Clear>
pub fn ellipse( &mut self, isometry: impl Into<Isometry3d>, half_size: Vec2, color: impl Into<Color>, ) -> EllipseBuilder<'_, Config, Clear>
Draw an ellipse in 3D with the given isometry
applied.
If isometry == Isometry3d::IDENTITY
then
- the center is at
Vec3::ZERO
- the
half_sizes
are aligned with theVec3::X
andVec3::Y
axes.
This should be called for each frame the ellipse needs to be rendered.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.ellipse(Isometry3d::IDENTITY, Vec2::new(1., 2.), GREEN);
// Ellipses have 32 line-segments by default.
// You may want to increase this for larger ellipses.
gizmos
.ellipse(Isometry3d::IDENTITY, Vec2::new(5., 1.), RED)
.resolution(64);
}
Sourcepub fn ellipse_2d(
&mut self,
isometry: impl Into<Isometry2d>,
half_size: Vec2,
color: impl Into<Color>,
) -> Ellipse2dBuilder<'_, Config, Clear>
pub fn ellipse_2d( &mut self, isometry: impl Into<Isometry2d>, half_size: Vec2, color: impl Into<Color>, ) -> Ellipse2dBuilder<'_, Config, Clear>
Draw an ellipse in 2D with the given isometry
applied.
If isometry == Isometry2d::IDENTITY
then
- the center is at
Vec2::ZERO
- the
half_sizes
are aligned with theVec2::X
andVec2::Y
axes.
This should be called for each frame the ellipse needs to be rendered.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.ellipse_2d(Isometry2d::from_rotation(Rot2::degrees(180.0)), Vec2::new(2., 1.), GREEN);
// Ellipses have 32 line-segments by default.
// You may want to increase this for larger ellipses.
gizmos
.ellipse_2d(Isometry2d::from_rotation(Rot2::degrees(180.0)), Vec2::new(5., 1.), RED)
.resolution(64);
}
Examples found in repository?
40fn draw_example_collection(
41 mut gizmos: Gizmos,
42 mut my_gizmos: Gizmos<MyRoundGizmos>,
43 time: Res<Time>,
44) {
45 let sin_t_scaled = ops::sin(time.elapsed_secs()) * 50.;
46 gizmos.line_2d(Vec2::Y * -sin_t_scaled, Vec2::splat(-80.), RED);
47 gizmos.ray_2d(Vec2::Y * sin_t_scaled, Vec2::splat(80.), LIME);
48
49 gizmos
50 .grid_2d(
51 Isometry2d::IDENTITY,
52 UVec2::new(16, 9),
53 Vec2::new(80., 80.),
54 // Dark gray
55 LinearRgba::gray(0.05),
56 )
57 .outer_edges();
58
59 // Triangle
60 gizmos.linestrip_gradient_2d([
61 (Vec2::Y * 300., BLUE),
62 (Vec2::new(-255., -155.), RED),
63 (Vec2::new(255., -155.), LIME),
64 (Vec2::Y * 300., BLUE),
65 ]);
66
67 gizmos.rect_2d(Isometry2d::IDENTITY, Vec2::splat(650.), BLACK);
68
69 gizmos.cross_2d(Vec2::new(-160., 120.), 12., FUCHSIA);
70
71 let domain = Interval::EVERYWHERE;
72 let curve = FunctionCurve::new(domain, |t| Vec2::new(t, ops::sin(t / 25.0) * 100.0));
73 let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 50.0) as usize;
74 let times_and_colors = (0..=resolution)
75 .map(|n| n as f32 / resolution as f32)
76 .map(|t| (t - 0.5) * 600.0)
77 .map(|t| (t, TEAL.mix(&HOT_PINK, (t + 300.0) / 600.0)));
78 gizmos.curve_gradient_2d(curve, times_and_colors);
79
80 my_gizmos
81 .rounded_rect_2d(Isometry2d::IDENTITY, Vec2::splat(630.), BLACK)
82 .corner_radius(ops::cos(time.elapsed_secs() / 3.) * 100.);
83
84 // Circles have 32 line-segments by default.
85 // You may want to increase this for larger circles.
86 my_gizmos
87 .circle_2d(Isometry2d::IDENTITY, 300., NAVY)
88 .resolution(64);
89
90 my_gizmos.ellipse_2d(
91 Rot2::radians(time.elapsed_secs() % TAU),
92 Vec2::new(100., 200.),
93 YELLOW_GREEN,
94 );
95
96 // Arcs default resolution is linearly interpolated between
97 // 1 and 32, using the arc length as scalar.
98 my_gizmos.arc_2d(
99 Rot2::radians(sin_t_scaled / 10.),
100 FRAC_PI_2,
101 310.,
102 ORANGE_RED,
103 );
104 my_gizmos.arc_2d(Isometry2d::IDENTITY, FRAC_PI_2, 80.0, ORANGE_RED);
105 my_gizmos.long_arc_2d_between(Vec2::ZERO, Vec2::X * 20.0, Vec2::Y * 20.0, ORANGE_RED);
106 my_gizmos.short_arc_2d_between(Vec2::ZERO, Vec2::X * 40.0, Vec2::Y * 40.0, ORANGE_RED);
107
108 gizmos.arrow_2d(
109 Vec2::ZERO,
110 Vec2::from_angle(sin_t_scaled / -10. + PI / 2.) * 50.,
111 YELLOW,
112 );
113
114 // You can create more complex arrows using the arrow builder.
115 gizmos
116 .arrow_2d(
117 Vec2::ZERO,
118 Vec2::from_angle(sin_t_scaled / -10.) * 50.,
119 GREEN,
120 )
121 .with_double_end()
122 .with_tip_length(10.);
123}
Sourcepub fn circle(
&mut self,
isometry: impl Into<Isometry3d>,
radius: f32,
color: impl Into<Color>,
) -> EllipseBuilder<'_, Config, Clear>
pub fn circle( &mut self, isometry: impl Into<Isometry3d>, radius: f32, color: impl Into<Color>, ) -> EllipseBuilder<'_, Config, Clear>
Draw a circle in 3D with the given isometry
applied.
If isometry == Isometry3d::IDENTITY
then
- the center is at
Vec3::ZERO
- the radius is aligned with the
Vec3::X
andVec3::Y
axes.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.circle(Isometry3d::IDENTITY, 1., GREEN);
// Circles have 32 line-segments by default.
// You may want to increase this for larger circles.
gizmos
.circle(Isometry3d::IDENTITY, 5., RED)
.resolution(64);
}
Examples found in repository?
13fn draw_cursor(
14 camera_query: Single<(&Camera, &GlobalTransform)>,
15 ground: Single<&GlobalTransform, With<Ground>>,
16 windows: Query<&Window>,
17 mut gizmos: Gizmos,
18) {
19 let Ok(windows) = windows.single() else {
20 return;
21 };
22
23 let (camera, camera_transform) = *camera_query;
24
25 let Some(cursor_position) = windows.cursor_position() else {
26 return;
27 };
28
29 // Calculate a ray pointing from the camera into the world based on the cursor's position.
30 let Ok(ray) = camera.viewport_to_world(camera_transform, cursor_position) else {
31 return;
32 };
33
34 // Calculate if and where the ray is hitting the ground plane.
35 let Some(distance) =
36 ray.intersect_plane(ground.translation(), InfinitePlane3d::new(ground.up()))
37 else {
38 return;
39 };
40 let point = ray.get_point(distance);
41
42 // Draw a circle just above the ground plane at that position.
43 gizmos.circle(
44 Isometry3d::new(
45 point + ground.up() * 0.01,
46 Quat::from_rotation_arc(Vec3::Z, ground.up().as_vec3()),
47 ),
48 0.2,
49 Color::WHITE,
50 );
51}
More examples
98fn draw_example_collection(
99 mut gizmos: Gizmos,
100 mut my_gizmos: Gizmos<MyRoundGizmos>,
101 time: Res<Time>,
102) {
103 gizmos.grid(
104 Quat::from_rotation_x(PI / 2.),
105 UVec2::splat(20),
106 Vec2::new(2., 2.),
107 // Light gray
108 LinearRgba::gray(0.65),
109 );
110 gizmos.grid(
111 Isometry3d::new(Vec3::splat(10.0), Quat::from_rotation_x(PI / 3. * 2.)),
112 UVec2::splat(20),
113 Vec2::new(2., 2.),
114 PURPLE,
115 );
116 gizmos.sphere(Vec3::splat(10.0), 1.0, PURPLE);
117
118 gizmos
119 .primitive_3d(
120 &Plane3d {
121 normal: Dir3::Y,
122 half_size: Vec2::splat(1.0),
123 },
124 Isometry3d::new(
125 Vec3::splat(4.0) + Vec2::from(ops::sin_cos(time.elapsed_secs())).extend(0.0),
126 Quat::from_rotation_x(PI / 2. + time.elapsed_secs()),
127 ),
128 GREEN,
129 )
130 .cell_count(UVec2::new(5, 10))
131 .spacing(Vec2::new(0.2, 0.1));
132
133 gizmos.cuboid(
134 Transform::from_translation(Vec3::Y * 0.5).with_scale(Vec3::splat(1.25)),
135 BLACK,
136 );
137 gizmos.rect(
138 Isometry3d::new(
139 Vec3::new(ops::cos(time.elapsed_secs()) * 2.5, 1., 0.),
140 Quat::from_rotation_y(PI / 2.),
141 ),
142 Vec2::splat(2.),
143 LIME,
144 );
145
146 gizmos.cross(Vec3::new(-1., 1., 1.), 0.5, FUCHSIA);
147
148 let domain = Interval::EVERYWHERE;
149 let curve = FunctionCurve::new(domain, |t| {
150 (Vec2::from(ops::sin_cos(t * 10.0))).extend(t - 6.0)
151 });
152 let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 100.0) as usize;
153 let times_and_colors = (0..=resolution)
154 .map(|n| n as f32 / resolution as f32)
155 .map(|t| t * 5.0)
156 .map(|t| (t, TEAL.mix(&HOT_PINK, t / 5.0)));
157 gizmos.curve_gradient_3d(curve, times_and_colors);
158
159 my_gizmos.sphere(Vec3::new(1., 0.5, 0.), 0.5, RED);
160
161 my_gizmos
162 .rounded_cuboid(Vec3::new(-2.0, 0.75, -0.75), Vec3::splat(0.9), TURQUOISE)
163 .edge_radius(0.1)
164 .arc_resolution(4);
165
166 for y in [0., 0.5, 1.] {
167 gizmos.ray(
168 Vec3::new(1., y, 0.),
169 Vec3::new(-3., ops::sin(time.elapsed_secs() * 3.), 0.),
170 BLUE,
171 );
172 }
173
174 my_gizmos
175 .arc_3d(
176 180.0_f32.to_radians(),
177 0.2,
178 Isometry3d::new(
179 Vec3::ONE,
180 Quat::from_rotation_arc(Vec3::Y, Vec3::ONE.normalize()),
181 ),
182 ORANGE,
183 )
184 .resolution(10);
185
186 // Circles have 32 line-segments by default.
187 my_gizmos.circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3., BLACK);
188
189 // You may want to increase this for larger circles or spheres.
190 my_gizmos
191 .circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3.1, NAVY)
192 .resolution(64);
193 my_gizmos
194 .sphere(Isometry3d::IDENTITY, 3.2, BLACK)
195 .resolution(64);
196
197 gizmos.arrow(Vec3::ZERO, Vec3::splat(1.5), YELLOW);
198
199 // You can create more complex arrows using the arrow builder.
200 gizmos
201 .arrow(Vec3::new(2., 0., 2.), Vec3::new(2., 2., 2.), ORANGE_RED)
202 .with_double_end()
203 .with_tip_length(0.5);
204}
Sourcepub fn circle_2d(
&mut self,
isometry: impl Into<Isometry2d>,
radius: f32,
color: impl Into<Color>,
) -> Ellipse2dBuilder<'_, Config, Clear>
pub fn circle_2d( &mut self, isometry: impl Into<Isometry2d>, radius: f32, color: impl Into<Color>, ) -> Ellipse2dBuilder<'_, Config, Clear>
Draw a circle in 2D with the given isometry
applied.
If isometry == Isometry2d::IDENTITY
then
- the center is at
Vec2::ZERO
- the radius is aligned with the
Vec2::X
andVec2::Y
axes.
This should be called for each frame the circle needs to be rendered.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.circle_2d(Isometry2d::IDENTITY, 1., GREEN);
// Circles have 32 line-segments by default.
// You may want to increase this for larger circles.
gizmos
.circle_2d(Isometry2d::IDENTITY, 5., RED)
.resolution(64);
}
Examples found in repository?
More examples
185fn draw_control_points(
186 control_points: Res<ControlPoints>,
187 spline_mode: Res<SplineMode>,
188 mut gizmos: Gizmos,
189) {
190 for &(point, tangent) in &control_points.points_and_tangents {
191 gizmos.circle_2d(point, 10.0, Color::srgb(0.0, 1.0, 0.0));
192
193 if matches!(*spline_mode, SplineMode::Hermite) {
194 gizmos.arrow_2d(point, point + tangent, Color::srgb(1.0, 0.0, 0.0));
195 }
196 }
197}
198
199/// Helper function for generating a [`Curve`] from [control points] and selected modes.
200///
201/// [control points]: ControlPoints
202fn form_curve(
203 control_points: &ControlPoints,
204 spline_mode: SplineMode,
205 cycling_mode: CyclingMode,
206) -> Curve {
207 let (points, tangents): (Vec<_>, Vec<_>) =
208 control_points.points_and_tangents.iter().copied().unzip();
209
210 match spline_mode {
211 SplineMode::Hermite => {
212 let spline = CubicHermite::new(points, tangents);
213 Curve(match cycling_mode {
214 CyclingMode::NotCyclic => spline.to_curve().ok(),
215 CyclingMode::Cyclic => spline.to_curve_cyclic().ok(),
216 })
217 }
218 SplineMode::Cardinal => {
219 let spline = CubicCardinalSpline::new_catmull_rom(points);
220 Curve(match cycling_mode {
221 CyclingMode::NotCyclic => spline.to_curve().ok(),
222 CyclingMode::Cyclic => spline.to_curve_cyclic().ok(),
223 })
224 }
225 SplineMode::B => {
226 let spline = CubicBSpline::new(points);
227 Curve(match cycling_mode {
228 CyclingMode::NotCyclic => spline.to_curve().ok(),
229 CyclingMode::Cyclic => spline.to_curve_cyclic().ok(),
230 })
231 }
232 }
233}
234
235// --------------------
236// Text-related Components and Systems
237// --------------------
238
239/// Marker component for the text node that displays the current [`SplineMode`].
240#[derive(Component)]
241struct SplineModeText;
242
243/// Marker component for the text node that displays the current [`CyclingMode`].
244#[derive(Component)]
245struct CyclingModeText;
246
247fn update_spline_mode_text(
248 spline_mode: Res<SplineMode>,
249 mut spline_mode_text: Query<&mut Text, With<SplineModeText>>,
250) {
251 if !spline_mode.is_changed() {
252 return;
253 }
254
255 let new_text = format!("Spline: {}", *spline_mode);
256
257 for mut spline_mode_text in spline_mode_text.iter_mut() {
258 (**spline_mode_text).clone_from(&new_text);
259 }
260}
261
262fn update_cycling_mode_text(
263 cycling_mode: Res<CyclingMode>,
264 mut cycling_mode_text: Query<&mut Text, With<CyclingModeText>>,
265) {
266 if !cycling_mode.is_changed() {
267 return;
268 }
269
270 let new_text = format!("{}", *cycling_mode);
271
272 for mut cycling_mode_text in cycling_mode_text.iter_mut() {
273 (**cycling_mode_text).clone_from(&new_text);
274 }
275}
276
277// -----------------------------------
278// Input-related Resources and Systems
279// -----------------------------------
280
281/// A small state machine which tracks a click-and-drag motion used to create new control points.
282///
283/// When the user is not doing a click-and-drag motion, the `start` field is `None`. When the user
284/// presses the left mouse button, the location of that press is temporarily stored in the field.
285#[derive(Clone, Default, Resource)]
286struct MouseEditMove {
287 start: Option<Vec2>,
288}
289
290/// The current mouse position, if known.
291#[derive(Clone, Default, Resource)]
292struct MousePosition(Option<Vec2>);
293
294/// Update the current cursor position and track it in the [`MousePosition`] resource.
295fn handle_mouse_move(
296 mut cursor_events: EventReader<CursorMoved>,
297 mut mouse_position: ResMut<MousePosition>,
298) {
299 if let Some(cursor_event) = cursor_events.read().last() {
300 mouse_position.0 = Some(cursor_event.position);
301 }
302}
303
304/// This system handles updating the [`MouseEditMove`] resource, orchestrating the logical part
305/// of the click-and-drag motion which actually creates new control points.
306fn handle_mouse_press(
307 mut button_events: EventReader<MouseButtonInput>,
308 mouse_position: Res<MousePosition>,
309 mut edit_move: ResMut<MouseEditMove>,
310 mut control_points: ResMut<ControlPoints>,
311 camera: Single<(&Camera, &GlobalTransform)>,
312) {
313 let Some(mouse_pos) = mouse_position.0 else {
314 return;
315 };
316
317 // Handle click and drag behavior
318 for button_event in button_events.read() {
319 if button_event.button != MouseButton::Left {
320 continue;
321 }
322
323 match button_event.state {
324 ButtonState::Pressed => {
325 if edit_move.start.is_some() {
326 // If the edit move already has a start, press event should do nothing.
327 continue;
328 }
329 // This press represents the start of the edit move.
330 edit_move.start = Some(mouse_pos);
331 }
332
333 ButtonState::Released => {
334 // Release is only meaningful if we started an edit move.
335 let Some(start) = edit_move.start else {
336 continue;
337 };
338
339 let (camera, camera_transform) = *camera;
340
341 // Convert the starting point and end point (current mouse pos) into world coords:
342 let Ok(point) = camera.viewport_to_world_2d(camera_transform, start) else {
343 continue;
344 };
345 let Ok(end_point) = camera.viewport_to_world_2d(camera_transform, mouse_pos) else {
346 continue;
347 };
348 let tangent = end_point - point;
349
350 // The start of the click-and-drag motion represents the point to add,
351 // while the difference with the current position represents the tangent.
352 control_points.points_and_tangents.push((point, tangent));
353
354 // Reset the edit move since we've consumed it.
355 edit_move.start = None;
356 }
357 }
358 }
359}
360
361/// This system handles drawing the "preview" control point based on the state of [`MouseEditMove`].
362fn draw_edit_move(
363 edit_move: Res<MouseEditMove>,
364 mouse_position: Res<MousePosition>,
365 mut gizmos: Gizmos,
366 camera: Single<(&Camera, &GlobalTransform)>,
367) {
368 let Some(start) = edit_move.start else {
369 return;
370 };
371 let Some(mouse_pos) = mouse_position.0 else {
372 return;
373 };
374
375 let (camera, camera_transform) = *camera;
376
377 // Resources store data in viewport coordinates, so we need to convert to world coordinates
378 // to display them:
379 let Ok(start) = camera.viewport_to_world_2d(camera_transform, start) else {
380 return;
381 };
382 let Ok(end) = camera.viewport_to_world_2d(camera_transform, mouse_pos) else {
383 return;
384 };
385
386 gizmos.circle_2d(start, 10.0, Color::srgb(0.0, 1.0, 0.7));
387 gizmos.circle_2d(start, 7.0, Color::srgb(0.0, 1.0, 0.7));
388 gizmos.arrow_2d(start, end, Color::srgb(1.0, 0.0, 0.7));
389}
182fn render_volumes(mut gizmos: Gizmos, query: Query<(&CurrentVolume, &Intersects)>) {
183 for (volume, intersects) in query.iter() {
184 let color = if **intersects { AQUA } else { ORANGE_RED };
185 match volume {
186 CurrentVolume::Aabb(a) => {
187 gizmos.rect_2d(a.center(), a.half_size() * 2., color);
188 }
189 CurrentVolume::Circle(c) => {
190 gizmos.circle_2d(c.center(), c.radius(), color);
191 }
192 }
193 }
194}
195
196#[derive(Component, Deref, DerefMut, Default)]
197struct Intersects(bool);
198
199const OFFSET_X: f32 = 125.;
200const OFFSET_Y: f32 = 75.;
201
202fn setup(mut commands: Commands) {
203 commands.spawn(Camera2d);
204
205 commands.spawn((
206 Transform::from_xyz(-OFFSET_X, OFFSET_Y, 0.),
207 Shape::Circle(Circle::new(45.)),
208 DesiredVolume::Aabb,
209 Intersects::default(),
210 ));
211
212 commands.spawn((
213 Transform::from_xyz(0., OFFSET_Y, 0.),
214 Shape::Rectangle(Rectangle::new(80., 80.)),
215 Spin,
216 DesiredVolume::Circle,
217 Intersects::default(),
218 ));
219
220 commands.spawn((
221 Transform::from_xyz(OFFSET_X, OFFSET_Y, 0.),
222 Shape::Triangle(Triangle2d::new(
223 Vec2::new(-40., -40.),
224 Vec2::new(-20., 40.),
225 Vec2::new(40., 50.),
226 )),
227 Spin,
228 DesiredVolume::Aabb,
229 Intersects::default(),
230 ));
231
232 commands.spawn((
233 Transform::from_xyz(-OFFSET_X, -OFFSET_Y, 0.),
234 Shape::Line(Segment2d::from_direction_and_length(
235 Dir2::from_xy(1., 0.3).unwrap(),
236 90.,
237 )),
238 Spin,
239 DesiredVolume::Circle,
240 Intersects::default(),
241 ));
242
243 commands.spawn((
244 Transform::from_xyz(0., -OFFSET_Y, 0.),
245 Shape::Capsule(Capsule2d::new(25., 50.)),
246 Spin,
247 DesiredVolume::Aabb,
248 Intersects::default(),
249 ));
250
251 commands.spawn((
252 Transform::from_xyz(OFFSET_X, -OFFSET_Y, 0.),
253 Shape::Polygon(RegularPolygon::new(50., 6)),
254 Spin,
255 DesiredVolume::Circle,
256 Intersects::default(),
257 ));
258
259 commands.spawn((
260 Text::default(),
261 Node {
262 position_type: PositionType::Absolute,
263 top: Val::Px(12.0),
264 left: Val::Px(12.0),
265 ..default()
266 },
267 ));
268}
269
270fn draw_filled_circle(gizmos: &mut Gizmos, position: Vec2, color: Srgba) {
271 for r in [1., 2., 3.] {
272 gizmos.circle_2d(position, r, color);
273 }
274}
275
276fn draw_ray(gizmos: &mut Gizmos, ray: &RayCast2d) {
277 gizmos.line_2d(
278 ray.ray.origin,
279 ray.ray.origin + *ray.ray.direction * ray.max,
280 WHITE,
281 );
282 draw_filled_circle(gizmos, ray.ray.origin, FUCHSIA);
283}
284
285fn get_and_draw_ray(gizmos: &mut Gizmos, time: &Time) -> RayCast2d {
286 let ray = Vec2::new(ops::cos(time.elapsed_secs()), ops::sin(time.elapsed_secs()));
287 let dist = 150. + ops::sin(0.5 * time.elapsed_secs()).abs() * 500.;
288
289 let aabb_ray = Ray2d {
290 origin: ray * 250.,
291 direction: Dir2::new_unchecked(-ray),
292 };
293 let ray_cast = RayCast2d::from_ray(aabb_ray, dist - 20.);
294
295 draw_ray(gizmos, &ray_cast);
296 ray_cast
297}
298
299fn ray_cast_system(
300 mut gizmos: Gizmos,
301 time: Res<Time>,
302 mut volumes: Query<(&CurrentVolume, &mut Intersects)>,
303) {
304 let ray_cast = get_and_draw_ray(&mut gizmos, &time);
305
306 for (volume, mut intersects) in volumes.iter_mut() {
307 let toi = match volume {
308 CurrentVolume::Aabb(a) => ray_cast.aabb_intersection_at(a),
309 CurrentVolume::Circle(c) => ray_cast.circle_intersection_at(c),
310 };
311 **intersects = toi.is_some();
312 if let Some(toi) = toi {
313 draw_filled_circle(
314 &mut gizmos,
315 ray_cast.ray.origin + *ray_cast.ray.direction * toi,
316 LIME,
317 );
318 }
319 }
320}
321
322fn aabb_cast_system(
323 mut gizmos: Gizmos,
324 time: Res<Time>,
325 mut volumes: Query<(&CurrentVolume, &mut Intersects)>,
326) {
327 let ray_cast = get_and_draw_ray(&mut gizmos, &time);
328 let aabb_cast = AabbCast2d {
329 aabb: Aabb2d::new(Vec2::ZERO, Vec2::splat(15.)),
330 ray: ray_cast,
331 };
332
333 for (volume, mut intersects) in volumes.iter_mut() {
334 let toi = match *volume {
335 CurrentVolume::Aabb(a) => aabb_cast.aabb_collision_at(a),
336 CurrentVolume::Circle(_) => None,
337 };
338
339 **intersects = toi.is_some();
340 if let Some(toi) = toi {
341 gizmos.rect_2d(
342 aabb_cast.ray.ray.origin + *aabb_cast.ray.ray.direction * toi,
343 aabb_cast.aabb.half_size() * 2.,
344 LIME,
345 );
346 }
347 }
348}
349
350fn bounding_circle_cast_system(
351 mut gizmos: Gizmos,
352 time: Res<Time>,
353 mut volumes: Query<(&CurrentVolume, &mut Intersects)>,
354) {
355 let ray_cast = get_and_draw_ray(&mut gizmos, &time);
356 let circle_cast = BoundingCircleCast {
357 circle: BoundingCircle::new(Vec2::ZERO, 15.),
358 ray: ray_cast,
359 };
360
361 for (volume, mut intersects) in volumes.iter_mut() {
362 let toi = match *volume {
363 CurrentVolume::Aabb(_) => None,
364 CurrentVolume::Circle(c) => circle_cast.circle_collision_at(c),
365 };
366
367 **intersects = toi.is_some();
368 if let Some(toi) = toi {
369 gizmos.circle_2d(
370 circle_cast.ray.ray.origin + *circle_cast.ray.ray.direction * toi,
371 circle_cast.circle.radius(),
372 LIME,
373 );
374 }
375 }
376}
377
378fn get_intersection_position(time: &Time) -> Vec2 {
379 let x = ops::cos(0.8 * time.elapsed_secs()) * 250.;
380 let y = ops::sin(0.4 * time.elapsed_secs()) * 100.;
381 Vec2::new(x, y)
382}
383
384fn aabb_intersection_system(
385 mut gizmos: Gizmos,
386 time: Res<Time>,
387 mut volumes: Query<(&CurrentVolume, &mut Intersects)>,
388) {
389 let center = get_intersection_position(&time);
390 let aabb = Aabb2d::new(center, Vec2::splat(50.));
391 gizmos.rect_2d(center, aabb.half_size() * 2., YELLOW);
392
393 for (volume, mut intersects) in volumes.iter_mut() {
394 let hit = match volume {
395 CurrentVolume::Aabb(a) => aabb.intersects(a),
396 CurrentVolume::Circle(c) => aabb.intersects(c),
397 };
398
399 **intersects = hit;
400 }
401}
402
403fn circle_intersection_system(
404 mut gizmos: Gizmos,
405 time: Res<Time>,
406 mut volumes: Query<(&CurrentVolume, &mut Intersects)>,
407) {
408 let center = get_intersection_position(&time);
409 let circle = BoundingCircle::new(center, 50.);
410 gizmos.circle_2d(center, circle.radius(), YELLOW);
411
412 for (volume, mut intersects) in volumes.iter_mut() {
413 let hit = match volume {
414 CurrentVolume::Aabb(a) => circle.intersects(a),
415 CurrentVolume::Circle(c) => circle.intersects(c),
416 };
417
418 **intersects = hit;
419 }
420}
104fn draw_bounds<Shape: Bounded2d + Send + Sync + 'static>(
105 q: Query<(&DrawBounds<Shape>, &GlobalTransform)>,
106 mut gizmos: Gizmos,
107) {
108 for (shape, transform) in &q {
109 let (_, rotation, translation) = transform.to_scale_rotation_translation();
110 let translation = translation.truncate();
111 let rotation = rotation.to_euler(EulerRot::XYZ).2;
112 let isometry = Isometry2d::new(translation, Rot2::radians(rotation));
113
114 let aabb = shape.0.aabb_2d(isometry);
115 gizmos.rect_2d(aabb.center(), aabb.half_size() * 2.0, RED);
116
117 let bounding_circle = shape.0.bounding_circle(isometry);
118 gizmos.circle_2d(bounding_circle.center, bounding_circle.radius(), BLUE);
119 }
120}
25fn draw_cursor(
26 camera_query: Single<(&Camera, &GlobalTransform)>,
27 window: Query<&Window>,
28 mut gizmos: Gizmos,
29) {
30 let (camera, camera_transform) = *camera_query;
31 let Ok(window) = window.single() else {
32 return;
33 };
34
35 let Some(cursor_position) = window.cursor_position() else {
36 return;
37 };
38
39 // Calculate a world position based on the cursor's position.
40 let Ok(world_pos) = camera.viewport_to_world_2d(camera_transform, cursor_position) else {
41 return;
42 };
43
44 // To test Camera::world_to_viewport, convert result back to viewport space and then back to world space.
45 let Ok(viewport_check) = camera.world_to_viewport(camera_transform, world_pos.extend(0.0))
46 else {
47 return;
48 };
49 let Ok(world_check) = camera.viewport_to_world_2d(camera_transform, viewport_check.xy()) else {
50 return;
51 };
52
53 gizmos.circle_2d(world_pos, 10., WHITE);
54 // Should be the same as world_pos
55 gizmos.circle_2d(world_check, 8., RED);
56}
Sourcepub fn sphere(
&mut self,
isometry: impl Into<Isometry3d>,
radius: f32,
color: impl Into<Color>,
) -> SphereBuilder<'_, Config, Clear>
pub fn sphere( &mut self, isometry: impl Into<Isometry3d>, radius: f32, color: impl Into<Color>, ) -> SphereBuilder<'_, Config, Clear>
Draw a wireframe sphere in 3D made out of 3 circles around the axes with the given
isometry
applied.
If isometry == Isometry3d::IDENTITY
then
- the center is at
Vec3::ZERO
- the 3 circles are in the XY, YZ and XZ planes.
This should be called for each frame the sphere needs to be rendered.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.sphere(Isometry3d::IDENTITY, 1., Color::BLACK);
// Each circle has 32 line-segments by default.
// You may want to increase this for larger spheres.
gizmos
.sphere(Isometry3d::IDENTITY, 5., Color::BLACK)
.resolution(64);
}
Examples found in repository?
More examples
26fn bouncing_raycast(
27 mut ray_cast: MeshRayCast,
28 mut gizmos: Gizmos,
29 time: Res<Time>,
30 // The ray map stores rays cast by the cursor
31 ray_map: Res<RayMap>,
32) {
33 // Cast an automatically moving ray and bounce it off of surfaces
34 let t = ops::cos((time.elapsed_secs() - 4.0).max(0.0) * LASER_SPEED) * PI;
35 let ray_pos = Vec3::new(ops::sin(t), ops::cos(3.0 * t) * 0.5, ops::cos(t)) * 0.5;
36 let ray_dir = Dir3::new(-ray_pos).unwrap();
37 let ray = Ray3d::new(ray_pos, ray_dir);
38 gizmos.sphere(ray_pos, 0.1, Color::WHITE);
39 bounce_ray(ray, &mut ray_cast, &mut gizmos, Color::from(css::RED));
40
41 // Cast a ray from the cursor and bounce it off of surfaces
42 for (_, ray) in ray_map.iter() {
43 bounce_ray(*ray, &mut ray_cast, &mut gizmos, Color::from(css::GREEN));
44 }
45}
46
47// Bounces a ray off of surfaces `MAX_BOUNCES` times.
48fn bounce_ray(mut ray: Ray3d, ray_cast: &mut MeshRayCast, gizmos: &mut Gizmos, color: Color) {
49 let mut intersections = Vec::with_capacity(MAX_BOUNCES + 1);
50 intersections.push((ray.origin, Color::srgb(30.0, 0.0, 0.0)));
51
52 for i in 0..MAX_BOUNCES {
53 // Cast the ray and get the first hit
54 let Some((_, hit)) = ray_cast
55 .cast_ray(ray, &MeshRayCastSettings::default())
56 .first()
57 else {
58 break;
59 };
60
61 // Draw the point of intersection and add it to the list
62 let brightness = 1.0 + 10.0 * (1.0 - i as f32 / MAX_BOUNCES as f32);
63 intersections.push((hit.point, Color::BLACK.mix(&color, brightness)));
64 gizmos.sphere(hit.point, 0.005, Color::BLACK.mix(&color, brightness * 2.0));
65
66 // Reflect the ray off of the surface
67 ray.direction = Dir3::new(ray.direction.reflect(hit.normal)).unwrap();
68 ray.origin = hit.point + ray.direction * 1e-6;
69 }
70 gizmos.linestrip_gradient(intersections);
71}
221fn bounding_shapes_3d(
222 shapes: Query<&Transform, With<Shape3d>>,
223 mut gizmos: Gizmos,
224 bounding_shape: Res<State<BoundingShape>>,
225) {
226 for transform in shapes.iter() {
227 match bounding_shape.get() {
228 BoundingShape::None => (),
229 BoundingShape::BoundingBox => {
230 // Get the AABB of the extrusion with the rotation and translation of the mesh.
231 let aabb = EXTRUSION.aabb_3d(transform.to_isometry());
232
233 gizmos.primitive_3d(
234 &Cuboid::from_size(Vec3::from(aabb.half_size()) * 2.),
235 aabb.center(),
236 WHITE,
237 );
238 }
239 BoundingShape::BoundingSphere => {
240 // Get the bounding sphere of the extrusion with the rotation and translation of the mesh.
241 let bounding_sphere = EXTRUSION.bounding_sphere(transform.to_isometry());
242
243 gizmos.sphere(bounding_sphere.center(), bounding_sphere.radius(), WHITE);
244 }
245 }
246 }
247}
23fn setup(
24 mut commands: Commands,
25 mut gizmo_assets: ResMut<Assets<GizmoAsset>>,
26 mut meshes: ResMut<Assets<Mesh>>,
27 mut materials: ResMut<Assets<StandardMaterial>>,
28) {
29 let mut gizmo = GizmoAsset::new();
30
31 // When drawing a lot of static lines a Gizmo component can have
32 // far better performance than the Gizmos system parameter,
33 // but the system parameter will perform better for smaller lines that update often.
34
35 // A sphere made out of 30_000 lines!
36 gizmo
37 .sphere(Isometry3d::IDENTITY, 0.5, CRIMSON)
38 .resolution(30_000 / 3);
39
40 commands.spawn((
41 Gizmo {
42 handle: gizmo_assets.add(gizmo),
43 line_config: GizmoLineConfig {
44 width: 5.,
45 ..default()
46 },
47 ..default()
48 },
49 Transform::from_xyz(4., 1., 0.),
50 ));
51
52 commands.spawn((
53 Camera3d::default(),
54 Transform::from_xyz(0., 1.5, 6.).looking_at(Vec3::ZERO, Vec3::Y),
55 CameraController::default(),
56 ));
57 // plane
58 commands.spawn((
59 Mesh3d(meshes.add(Plane3d::default().mesh().size(5.0, 5.0))),
60 MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))),
61 ));
62 // cube
63 commands.spawn((
64 Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
65 MeshMaterial3d(materials.add(Color::srgb(0.8, 0.7, 0.6))),
66 Transform::from_xyz(0.0, 0.5, 0.0),
67 ));
68 // light
69 commands.spawn((
70 PointLight {
71 shadows_enabled: true,
72 ..default()
73 },
74 Transform::from_xyz(4.0, 8.0, 4.0),
75 ));
76
77 // example instructions
78 commands.spawn((
79 Text::new(
80 "Press 'T' to toggle drawing gizmos on top of everything else in the scene\n\
81 Press 'P' to toggle perspective for line gizmos\n\
82 Hold 'Left' or 'Right' to change the line width of straight gizmos\n\
83 Hold 'Up' or 'Down' to change the line width of round gizmos\n\
84 Press '1' or '2' to toggle the visibility of straight gizmos or round gizmos\n\
85 Press 'B' to show all AABB boxes\n\
86 Press 'U' or 'I' to cycle through line styles for straight or round gizmos\n\
87 Press 'J' or 'K' to cycle through line joins for straight or round gizmos",
88 ),
89 Node {
90 position_type: PositionType::Absolute,
91 top: Val::Px(12.0),
92 left: Val::Px(12.0),
93 ..default()
94 },
95 ));
96}
97
98fn draw_example_collection(
99 mut gizmos: Gizmos,
100 mut my_gizmos: Gizmos<MyRoundGizmos>,
101 time: Res<Time>,
102) {
103 gizmos.grid(
104 Quat::from_rotation_x(PI / 2.),
105 UVec2::splat(20),
106 Vec2::new(2., 2.),
107 // Light gray
108 LinearRgba::gray(0.65),
109 );
110 gizmos.grid(
111 Isometry3d::new(Vec3::splat(10.0), Quat::from_rotation_x(PI / 3. * 2.)),
112 UVec2::splat(20),
113 Vec2::new(2., 2.),
114 PURPLE,
115 );
116 gizmos.sphere(Vec3::splat(10.0), 1.0, PURPLE);
117
118 gizmos
119 .primitive_3d(
120 &Plane3d {
121 normal: Dir3::Y,
122 half_size: Vec2::splat(1.0),
123 },
124 Isometry3d::new(
125 Vec3::splat(4.0) + Vec2::from(ops::sin_cos(time.elapsed_secs())).extend(0.0),
126 Quat::from_rotation_x(PI / 2. + time.elapsed_secs()),
127 ),
128 GREEN,
129 )
130 .cell_count(UVec2::new(5, 10))
131 .spacing(Vec2::new(0.2, 0.1));
132
133 gizmos.cuboid(
134 Transform::from_translation(Vec3::Y * 0.5).with_scale(Vec3::splat(1.25)),
135 BLACK,
136 );
137 gizmos.rect(
138 Isometry3d::new(
139 Vec3::new(ops::cos(time.elapsed_secs()) * 2.5, 1., 0.),
140 Quat::from_rotation_y(PI / 2.),
141 ),
142 Vec2::splat(2.),
143 LIME,
144 );
145
146 gizmos.cross(Vec3::new(-1., 1., 1.), 0.5, FUCHSIA);
147
148 let domain = Interval::EVERYWHERE;
149 let curve = FunctionCurve::new(domain, |t| {
150 (Vec2::from(ops::sin_cos(t * 10.0))).extend(t - 6.0)
151 });
152 let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 100.0) as usize;
153 let times_and_colors = (0..=resolution)
154 .map(|n| n as f32 / resolution as f32)
155 .map(|t| t * 5.0)
156 .map(|t| (t, TEAL.mix(&HOT_PINK, t / 5.0)));
157 gizmos.curve_gradient_3d(curve, times_and_colors);
158
159 my_gizmos.sphere(Vec3::new(1., 0.5, 0.), 0.5, RED);
160
161 my_gizmos
162 .rounded_cuboid(Vec3::new(-2.0, 0.75, -0.75), Vec3::splat(0.9), TURQUOISE)
163 .edge_radius(0.1)
164 .arc_resolution(4);
165
166 for y in [0., 0.5, 1.] {
167 gizmos.ray(
168 Vec3::new(1., y, 0.),
169 Vec3::new(-3., ops::sin(time.elapsed_secs() * 3.), 0.),
170 BLUE,
171 );
172 }
173
174 my_gizmos
175 .arc_3d(
176 180.0_f32.to_radians(),
177 0.2,
178 Isometry3d::new(
179 Vec3::ONE,
180 Quat::from_rotation_arc(Vec3::Y, Vec3::ONE.normalize()),
181 ),
182 ORANGE,
183 )
184 .resolution(10);
185
186 // Circles have 32 line-segments by default.
187 my_gizmos.circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3., BLACK);
188
189 // You may want to increase this for larger circles or spheres.
190 my_gizmos
191 .circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3.1, NAVY)
192 .resolution(64);
193 my_gizmos
194 .sphere(Isometry3d::IDENTITY, 3.2, BLACK)
195 .resolution(64);
196
197 gizmos.arrow(Vec3::ZERO, Vec3::splat(1.5), YELLOW);
198
199 // You can create more complex arrows using the arrow builder.
200 gizmos
201 .arrow(Vec3::new(2., 0., 2.), Vec3::new(2., 2., 2.), ORANGE_RED)
202 .with_double_end()
203 .with_tip_length(0.5);
204}
Sourcepub fn cross(
&mut self,
isometry: impl Into<Isometry3d>,
half_size: f32,
color: impl Into<Color>,
)
pub fn cross( &mut self, isometry: impl Into<Isometry3d>, half_size: f32, color: impl Into<Color>, )
Draw a cross in 3D with the given isometry
applied.
If isometry == Isometry3d::IDENTITY
then
- the center is at
Vec3::ZERO
- the
half_size
s are aligned with theVec3::X
,Vec3::Y
andVec3::Z
axes.
This should be called for each frame the cross needs to be rendered.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.cross(Isometry3d::IDENTITY, 0.5, WHITE);
}
Examples found in repository?
98fn draw_example_collection(
99 mut gizmos: Gizmos,
100 mut my_gizmos: Gizmos<MyRoundGizmos>,
101 time: Res<Time>,
102) {
103 gizmos.grid(
104 Quat::from_rotation_x(PI / 2.),
105 UVec2::splat(20),
106 Vec2::new(2., 2.),
107 // Light gray
108 LinearRgba::gray(0.65),
109 );
110 gizmos.grid(
111 Isometry3d::new(Vec3::splat(10.0), Quat::from_rotation_x(PI / 3. * 2.)),
112 UVec2::splat(20),
113 Vec2::new(2., 2.),
114 PURPLE,
115 );
116 gizmos.sphere(Vec3::splat(10.0), 1.0, PURPLE);
117
118 gizmos
119 .primitive_3d(
120 &Plane3d {
121 normal: Dir3::Y,
122 half_size: Vec2::splat(1.0),
123 },
124 Isometry3d::new(
125 Vec3::splat(4.0) + Vec2::from(ops::sin_cos(time.elapsed_secs())).extend(0.0),
126 Quat::from_rotation_x(PI / 2. + time.elapsed_secs()),
127 ),
128 GREEN,
129 )
130 .cell_count(UVec2::new(5, 10))
131 .spacing(Vec2::new(0.2, 0.1));
132
133 gizmos.cuboid(
134 Transform::from_translation(Vec3::Y * 0.5).with_scale(Vec3::splat(1.25)),
135 BLACK,
136 );
137 gizmos.rect(
138 Isometry3d::new(
139 Vec3::new(ops::cos(time.elapsed_secs()) * 2.5, 1., 0.),
140 Quat::from_rotation_y(PI / 2.),
141 ),
142 Vec2::splat(2.),
143 LIME,
144 );
145
146 gizmos.cross(Vec3::new(-1., 1., 1.), 0.5, FUCHSIA);
147
148 let domain = Interval::EVERYWHERE;
149 let curve = FunctionCurve::new(domain, |t| {
150 (Vec2::from(ops::sin_cos(t * 10.0))).extend(t - 6.0)
151 });
152 let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 100.0) as usize;
153 let times_and_colors = (0..=resolution)
154 .map(|n| n as f32 / resolution as f32)
155 .map(|t| t * 5.0)
156 .map(|t| (t, TEAL.mix(&HOT_PINK, t / 5.0)));
157 gizmos.curve_gradient_3d(curve, times_and_colors);
158
159 my_gizmos.sphere(Vec3::new(1., 0.5, 0.), 0.5, RED);
160
161 my_gizmos
162 .rounded_cuboid(Vec3::new(-2.0, 0.75, -0.75), Vec3::splat(0.9), TURQUOISE)
163 .edge_radius(0.1)
164 .arc_resolution(4);
165
166 for y in [0., 0.5, 1.] {
167 gizmos.ray(
168 Vec3::new(1., y, 0.),
169 Vec3::new(-3., ops::sin(time.elapsed_secs() * 3.), 0.),
170 BLUE,
171 );
172 }
173
174 my_gizmos
175 .arc_3d(
176 180.0_f32.to_radians(),
177 0.2,
178 Isometry3d::new(
179 Vec3::ONE,
180 Quat::from_rotation_arc(Vec3::Y, Vec3::ONE.normalize()),
181 ),
182 ORANGE,
183 )
184 .resolution(10);
185
186 // Circles have 32 line-segments by default.
187 my_gizmos.circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3., BLACK);
188
189 // You may want to increase this for larger circles or spheres.
190 my_gizmos
191 .circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3.1, NAVY)
192 .resolution(64);
193 my_gizmos
194 .sphere(Isometry3d::IDENTITY, 3.2, BLACK)
195 .resolution(64);
196
197 gizmos.arrow(Vec3::ZERO, Vec3::splat(1.5), YELLOW);
198
199 // You can create more complex arrows using the arrow builder.
200 gizmos
201 .arrow(Vec3::new(2., 0., 2.), Vec3::new(2., 2., 2.), ORANGE_RED)
202 .with_double_end()
203 .with_tip_length(0.5);
204}
Sourcepub fn cross_2d(
&mut self,
isometry: impl Into<Isometry2d>,
half_size: f32,
color: impl Into<Color>,
)
pub fn cross_2d( &mut self, isometry: impl Into<Isometry2d>, half_size: f32, color: impl Into<Color>, )
Draw a cross in 2D with the given isometry
applied.
If isometry == Isometry2d::IDENTITY
then
- the center is at
Vec3::ZERO
- the
half_size
s are aligned with theVec3::X
andVec3::Y
axes.
This should be called for each frame the cross needs to be rendered.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.cross_2d(Isometry2d::IDENTITY, 0.5, WHITE);
}
Examples found in repository?
40fn draw_example_collection(
41 mut gizmos: Gizmos,
42 mut my_gizmos: Gizmos<MyRoundGizmos>,
43 time: Res<Time>,
44) {
45 let sin_t_scaled = ops::sin(time.elapsed_secs()) * 50.;
46 gizmos.line_2d(Vec2::Y * -sin_t_scaled, Vec2::splat(-80.), RED);
47 gizmos.ray_2d(Vec2::Y * sin_t_scaled, Vec2::splat(80.), LIME);
48
49 gizmos
50 .grid_2d(
51 Isometry2d::IDENTITY,
52 UVec2::new(16, 9),
53 Vec2::new(80., 80.),
54 // Dark gray
55 LinearRgba::gray(0.05),
56 )
57 .outer_edges();
58
59 // Triangle
60 gizmos.linestrip_gradient_2d([
61 (Vec2::Y * 300., BLUE),
62 (Vec2::new(-255., -155.), RED),
63 (Vec2::new(255., -155.), LIME),
64 (Vec2::Y * 300., BLUE),
65 ]);
66
67 gizmos.rect_2d(Isometry2d::IDENTITY, Vec2::splat(650.), BLACK);
68
69 gizmos.cross_2d(Vec2::new(-160., 120.), 12., FUCHSIA);
70
71 let domain = Interval::EVERYWHERE;
72 let curve = FunctionCurve::new(domain, |t| Vec2::new(t, ops::sin(t / 25.0) * 100.0));
73 let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 50.0) as usize;
74 let times_and_colors = (0..=resolution)
75 .map(|n| n as f32 / resolution as f32)
76 .map(|t| (t - 0.5) * 600.0)
77 .map(|t| (t, TEAL.mix(&HOT_PINK, (t + 300.0) / 600.0)));
78 gizmos.curve_gradient_2d(curve, times_and_colors);
79
80 my_gizmos
81 .rounded_rect_2d(Isometry2d::IDENTITY, Vec2::splat(630.), BLACK)
82 .corner_radius(ops::cos(time.elapsed_secs() / 3.) * 100.);
83
84 // Circles have 32 line-segments by default.
85 // You may want to increase this for larger circles.
86 my_gizmos
87 .circle_2d(Isometry2d::IDENTITY, 300., NAVY)
88 .resolution(64);
89
90 my_gizmos.ellipse_2d(
91 Rot2::radians(time.elapsed_secs() % TAU),
92 Vec2::new(100., 200.),
93 YELLOW_GREEN,
94 );
95
96 // Arcs default resolution is linearly interpolated between
97 // 1 and 32, using the arc length as scalar.
98 my_gizmos.arc_2d(
99 Rot2::radians(sin_t_scaled / 10.),
100 FRAC_PI_2,
101 310.,
102 ORANGE_RED,
103 );
104 my_gizmos.arc_2d(Isometry2d::IDENTITY, FRAC_PI_2, 80.0, ORANGE_RED);
105 my_gizmos.long_arc_2d_between(Vec2::ZERO, Vec2::X * 20.0, Vec2::Y * 20.0, ORANGE_RED);
106 my_gizmos.short_arc_2d_between(Vec2::ZERO, Vec2::X * 40.0, Vec2::Y * 40.0, ORANGE_RED);
107
108 gizmos.arrow_2d(
109 Vec2::ZERO,
110 Vec2::from_angle(sin_t_scaled / -10. + PI / 2.) * 50.,
111 YELLOW,
112 );
113
114 // You can create more complex arrows using the arrow builder.
115 gizmos
116 .arrow_2d(
117 Vec2::ZERO,
118 Vec2::from_angle(sin_t_scaled / -10.) * 50.,
119 GREEN,
120 )
121 .with_double_end()
122 .with_tip_length(10.);
123}
Sourcepub fn curve_2d(
&mut self,
curve_2d: impl Curve<Vec2>,
times: impl IntoIterator<Item = f32>,
color: impl Into<Color>,
)
pub fn curve_2d( &mut self, curve_2d: impl Curve<Vec2>, times: impl IntoIterator<Item = f32>, color: impl Into<Color>, )
Draw a curve, at the given time points, sampling in 2D.
This should be called for each frame the curve needs to be rendered.
Samples of time points outside of the curve’s domain will be filtered out and won’t contribute to the rendering. If you wish to render the curve outside of its domain you need to create a new curve with an extended domain.
§Arguments
curve_2d
some type that implements theCurve
trait and samplesVec2
stimes
some iterable type yieldingf32
which will be used for sampling the curvecolor
the color of the curve
§Example
fn system(mut gizmos: Gizmos) {
let domain = Interval::UNIT;
let curve = FunctionCurve::new(domain, |t| Vec2::from(t.sin_cos()));
gizmos.curve_2d(curve, (0..=100).map(|n| n as f32 / 100.0), RED);
}
Examples found in repository?
129fn display_curves(
130 mut gizmos: Gizmos,
131 ease_functions: Query<(&EaseFunctionPlot, &Transform, &Children)>,
132 mut transforms: Query<&mut Transform, Without<EaseFunctionPlot>>,
133 mut ui_text: Single<&mut Text>,
134 time: Res<Time>,
135) {
136 let samples = 100;
137 let duration = 2.5;
138 let time_margin = 0.5;
139
140 let now = ((time.elapsed_secs() % (duration + time_margin * 2.0) - time_margin) / duration)
141 .clamp(0.0, 1.0);
142
143 ui_text.0 = format!("Progress: {:.2}", now);
144
145 for (EaseFunctionPlot(function, color), transform, children) in &ease_functions {
146 let center = transform.translation.xy();
147 let half_size = PLOT_SIZE / 2.0;
148
149 // Draw a box around the curve
150 gizmos.linestrip_2d(
151 [
152 center + half_size,
153 center + half_size * Vec2::new(-1., 1.),
154 center + half_size * Vec2::new(-1., -1.),
155 center + half_size * Vec2::new(1., -1.),
156 center + half_size,
157 ],
158 color.darker(0.4),
159 );
160
161 // Draw the curve
162 let f = EasingCurve::new(0.0, 1.0, *function);
163 let drawn_curve = f
164 .by_ref()
165 .graph()
166 .map(|(x, y)| center - half_size + Vec2::new(x, y) * PLOT_SIZE);
167 gizmos.curve_2d(
168 &drawn_curve,
169 drawn_curve.domain().spaced_points(samples).unwrap(),
170 *color,
171 );
172
173 // Show progress along the curve for the current time
174 let y = f.sample(now).unwrap() * PLOT_SIZE.y;
175 transforms.get_mut(children[0]).unwrap().translation.y = -half_size.y + y;
176 transforms.get_mut(children[1]).unwrap().translation =
177 -half_size.extend(0.0) + Vec3::new(now * PLOT_SIZE.x, y, 0.0);
178
179 // Show horizontal bar at y value
180 gizmos.linestrip_2d(
181 [
182 center - half_size + Vec2::Y * y,
183 center - half_size + Vec2::new(PLOT_SIZE.x, y),
184 ],
185 color.darker(0.2),
186 );
187 }
188}
Sourcepub fn curve_3d(
&mut self,
curve_3d: impl Curve<Vec3>,
times: impl IntoIterator<Item = f32>,
color: impl Into<Color>,
)
pub fn curve_3d( &mut self, curve_3d: impl Curve<Vec3>, times: impl IntoIterator<Item = f32>, color: impl Into<Color>, )
Draw a curve, at the given time points, sampling in 3D.
This should be called for each frame the curve needs to be rendered.
Samples of time points outside of the curve’s domain will be filtered out and won’t contribute to the rendering. If you wish to render the curve outside of its domain you need to create a new curve with an extended domain.
§Arguments
curve_3d
some type that implements theCurve
trait and samplesVec3
stimes
some iterable type yieldingf32
which will be used for sampling the curvecolor
the color of the curve
§Example
fn system(mut gizmos: Gizmos) {
let domain = Interval::UNIT;
let curve = FunctionCurve::new(domain, |t| {
let (x,y) = t.sin_cos();
Vec3::new(x, y, t)
});
gizmos.curve_3d(curve, (0..=100).map(|n| n as f32 / 100.0), RED);
}
Sourcepub fn curve_gradient_2d<C>(
&mut self,
curve_2d: impl Curve<Vec2>,
times_with_colors: impl IntoIterator<Item = (f32, C)>,
)
pub fn curve_gradient_2d<C>( &mut self, curve_2d: impl Curve<Vec2>, times_with_colors: impl IntoIterator<Item = (f32, C)>, )
Draw a curve, at the given time points, sampling in 2D, with a color gradient.
This should be called for each frame the curve needs to be rendered.
Samples of time points outside of the curve’s domain will be filtered out and won’t contribute to the rendering. If you wish to render the curve outside of its domain you need to create a new curve with an extended domain.
§Arguments
curve_2d
some type that implements theCurve
trait and samplesVec2
stimes_with_colors
some iterable type yieldingf32
which will be used for sampling the curve together with the color at this position
§Example
fn system(mut gizmos: Gizmos) {
let domain = Interval::UNIT;
let curve = FunctionCurve::new(domain, |t| Vec2::from(t.sin_cos()));
gizmos.curve_gradient_2d(
curve,
(0..=100).map(|n| n as f32 / 100.0)
.map(|t| (t, GREEN.mix(&RED, t)))
);
}
Examples found in repository?
40fn draw_example_collection(
41 mut gizmos: Gizmos,
42 mut my_gizmos: Gizmos<MyRoundGizmos>,
43 time: Res<Time>,
44) {
45 let sin_t_scaled = ops::sin(time.elapsed_secs()) * 50.;
46 gizmos.line_2d(Vec2::Y * -sin_t_scaled, Vec2::splat(-80.), RED);
47 gizmos.ray_2d(Vec2::Y * sin_t_scaled, Vec2::splat(80.), LIME);
48
49 gizmos
50 .grid_2d(
51 Isometry2d::IDENTITY,
52 UVec2::new(16, 9),
53 Vec2::new(80., 80.),
54 // Dark gray
55 LinearRgba::gray(0.05),
56 )
57 .outer_edges();
58
59 // Triangle
60 gizmos.linestrip_gradient_2d([
61 (Vec2::Y * 300., BLUE),
62 (Vec2::new(-255., -155.), RED),
63 (Vec2::new(255., -155.), LIME),
64 (Vec2::Y * 300., BLUE),
65 ]);
66
67 gizmos.rect_2d(Isometry2d::IDENTITY, Vec2::splat(650.), BLACK);
68
69 gizmos.cross_2d(Vec2::new(-160., 120.), 12., FUCHSIA);
70
71 let domain = Interval::EVERYWHERE;
72 let curve = FunctionCurve::new(domain, |t| Vec2::new(t, ops::sin(t / 25.0) * 100.0));
73 let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 50.0) as usize;
74 let times_and_colors = (0..=resolution)
75 .map(|n| n as f32 / resolution as f32)
76 .map(|t| (t - 0.5) * 600.0)
77 .map(|t| (t, TEAL.mix(&HOT_PINK, (t + 300.0) / 600.0)));
78 gizmos.curve_gradient_2d(curve, times_and_colors);
79
80 my_gizmos
81 .rounded_rect_2d(Isometry2d::IDENTITY, Vec2::splat(630.), BLACK)
82 .corner_radius(ops::cos(time.elapsed_secs() / 3.) * 100.);
83
84 // Circles have 32 line-segments by default.
85 // You may want to increase this for larger circles.
86 my_gizmos
87 .circle_2d(Isometry2d::IDENTITY, 300., NAVY)
88 .resolution(64);
89
90 my_gizmos.ellipse_2d(
91 Rot2::radians(time.elapsed_secs() % TAU),
92 Vec2::new(100., 200.),
93 YELLOW_GREEN,
94 );
95
96 // Arcs default resolution is linearly interpolated between
97 // 1 and 32, using the arc length as scalar.
98 my_gizmos.arc_2d(
99 Rot2::radians(sin_t_scaled / 10.),
100 FRAC_PI_2,
101 310.,
102 ORANGE_RED,
103 );
104 my_gizmos.arc_2d(Isometry2d::IDENTITY, FRAC_PI_2, 80.0, ORANGE_RED);
105 my_gizmos.long_arc_2d_between(Vec2::ZERO, Vec2::X * 20.0, Vec2::Y * 20.0, ORANGE_RED);
106 my_gizmos.short_arc_2d_between(Vec2::ZERO, Vec2::X * 40.0, Vec2::Y * 40.0, ORANGE_RED);
107
108 gizmos.arrow_2d(
109 Vec2::ZERO,
110 Vec2::from_angle(sin_t_scaled / -10. + PI / 2.) * 50.,
111 YELLOW,
112 );
113
114 // You can create more complex arrows using the arrow builder.
115 gizmos
116 .arrow_2d(
117 Vec2::ZERO,
118 Vec2::from_angle(sin_t_scaled / -10.) * 50.,
119 GREEN,
120 )
121 .with_double_end()
122 .with_tip_length(10.);
123}
Sourcepub fn curve_gradient_3d<C>(
&mut self,
curve_3d: impl Curve<Vec3>,
times_with_colors: impl IntoIterator<Item = (f32, C)>,
)
pub fn curve_gradient_3d<C>( &mut self, curve_3d: impl Curve<Vec3>, times_with_colors: impl IntoIterator<Item = (f32, C)>, )
Draw a curve, at the given time points, sampling in 3D, with a color gradient.
This should be called for each frame the curve needs to be rendered.
Samples of time points outside of the curve’s domain will be filtered out and won’t contribute to the rendering. If you wish to render the curve outside of its domain you need to create a new curve with an extended domain.
§Arguments
curve_3d
some type that implements theCurve
trait and samplesVec3
stimes_with_colors
some iterable type yieldingf32
which will be used for sampling the curve together with the color at this position
§Example
fn system(mut gizmos: Gizmos) {
let domain = Interval::UNIT;
let curve = FunctionCurve::new(domain, |t| {
let (x,y) = t.sin_cos();
Vec3::new(x, y, t)
});
gizmos.curve_gradient_3d(
curve,
(0..=100).map(|n| n as f32 / 100.0)
.map(|t| (t, GREEN.mix(&RED, t)))
);
}
Examples found in repository?
98fn draw_example_collection(
99 mut gizmos: Gizmos,
100 mut my_gizmos: Gizmos<MyRoundGizmos>,
101 time: Res<Time>,
102) {
103 gizmos.grid(
104 Quat::from_rotation_x(PI / 2.),
105 UVec2::splat(20),
106 Vec2::new(2., 2.),
107 // Light gray
108 LinearRgba::gray(0.65),
109 );
110 gizmos.grid(
111 Isometry3d::new(Vec3::splat(10.0), Quat::from_rotation_x(PI / 3. * 2.)),
112 UVec2::splat(20),
113 Vec2::new(2., 2.),
114 PURPLE,
115 );
116 gizmos.sphere(Vec3::splat(10.0), 1.0, PURPLE);
117
118 gizmos
119 .primitive_3d(
120 &Plane3d {
121 normal: Dir3::Y,
122 half_size: Vec2::splat(1.0),
123 },
124 Isometry3d::new(
125 Vec3::splat(4.0) + Vec2::from(ops::sin_cos(time.elapsed_secs())).extend(0.0),
126 Quat::from_rotation_x(PI / 2. + time.elapsed_secs()),
127 ),
128 GREEN,
129 )
130 .cell_count(UVec2::new(5, 10))
131 .spacing(Vec2::new(0.2, 0.1));
132
133 gizmos.cuboid(
134 Transform::from_translation(Vec3::Y * 0.5).with_scale(Vec3::splat(1.25)),
135 BLACK,
136 );
137 gizmos.rect(
138 Isometry3d::new(
139 Vec3::new(ops::cos(time.elapsed_secs()) * 2.5, 1., 0.),
140 Quat::from_rotation_y(PI / 2.),
141 ),
142 Vec2::splat(2.),
143 LIME,
144 );
145
146 gizmos.cross(Vec3::new(-1., 1., 1.), 0.5, FUCHSIA);
147
148 let domain = Interval::EVERYWHERE;
149 let curve = FunctionCurve::new(domain, |t| {
150 (Vec2::from(ops::sin_cos(t * 10.0))).extend(t - 6.0)
151 });
152 let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 100.0) as usize;
153 let times_and_colors = (0..=resolution)
154 .map(|n| n as f32 / resolution as f32)
155 .map(|t| t * 5.0)
156 .map(|t| (t, TEAL.mix(&HOT_PINK, t / 5.0)));
157 gizmos.curve_gradient_3d(curve, times_and_colors);
158
159 my_gizmos.sphere(Vec3::new(1., 0.5, 0.), 0.5, RED);
160
161 my_gizmos
162 .rounded_cuboid(Vec3::new(-2.0, 0.75, -0.75), Vec3::splat(0.9), TURQUOISE)
163 .edge_radius(0.1)
164 .arc_resolution(4);
165
166 for y in [0., 0.5, 1.] {
167 gizmos.ray(
168 Vec3::new(1., y, 0.),
169 Vec3::new(-3., ops::sin(time.elapsed_secs() * 3.), 0.),
170 BLUE,
171 );
172 }
173
174 my_gizmos
175 .arc_3d(
176 180.0_f32.to_radians(),
177 0.2,
178 Isometry3d::new(
179 Vec3::ONE,
180 Quat::from_rotation_arc(Vec3::Y, Vec3::ONE.normalize()),
181 ),
182 ORANGE,
183 )
184 .resolution(10);
185
186 // Circles have 32 line-segments by default.
187 my_gizmos.circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3., BLACK);
188
189 // You may want to increase this for larger circles or spheres.
190 my_gizmos
191 .circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3.1, NAVY)
192 .resolution(64);
193 my_gizmos
194 .sphere(Isometry3d::IDENTITY, 3.2, BLACK)
195 .resolution(64);
196
197 gizmos.arrow(Vec3::ZERO, Vec3::splat(1.5), YELLOW);
198
199 // You can create more complex arrows using the arrow builder.
200 gizmos
201 .arrow(Vec3::new(2., 0., 2.), Vec3::new(2., 2., 2.), ORANGE_RED)
202 .with_double_end()
203 .with_tip_length(0.5);
204}
Sourcepub fn buffer(&self) -> GizmoBufferView<'_>
pub fn buffer(&self) -> GizmoBufferView<'_>
Read-only view into the buffers data.
Sourcepub fn line(&mut self, start: Vec3, end: Vec3, color: impl Into<Color>)
pub fn line(&mut self, start: Vec3, end: Vec3, color: impl Into<Color>)
Draw a line in 3D from start
to end
.
This should be called for each frame the line needs to be rendered.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.line(Vec3::ZERO, Vec3::X, GREEN);
}
Examples found in repository?
65fn system(config: Res<Config>, time: Res<Time>, mut draw: Gizmos) {
66 if !config.fancy {
67 for _ in 0..(config.line_count / SYSTEM_COUNT) {
68 draw.line(Vec3::NEG_Y, Vec3::Y, Color::BLACK);
69 }
70 } else {
71 for i in 0..(config.line_count / SYSTEM_COUNT) {
72 let angle = i as f32 / (config.line_count / SYSTEM_COUNT) as f32 * TAU;
73
74 let vector = Vec2::from(ops::sin_cos(angle)).extend(ops::sin(time.elapsed_secs()));
75 let start_color = LinearRgba::rgb(vector.x, vector.z, 0.5);
76 let end_color = LinearRgba::rgb(-vector.z, -vector.y, 0.5);
77
78 draw.line_gradient(vector, -vector, start_color, end_color);
79 }
80 }
81}
Sourcepub fn line_gradient<C>(
&mut self,
start: Vec3,
end: Vec3,
start_color: C,
end_color: C,
)
pub fn line_gradient<C>( &mut self, start: Vec3, end: Vec3, start_color: C, end_color: C, )
Draw a line in 3D with a color gradient from start
to end
.
This should be called for each frame the line needs to be rendered.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.line_gradient(Vec3::ZERO, Vec3::X, GREEN, RED);
}
Examples found in repository?
65fn system(config: Res<Config>, time: Res<Time>, mut draw: Gizmos) {
66 if !config.fancy {
67 for _ in 0..(config.line_count / SYSTEM_COUNT) {
68 draw.line(Vec3::NEG_Y, Vec3::Y, Color::BLACK);
69 }
70 } else {
71 for i in 0..(config.line_count / SYSTEM_COUNT) {
72 let angle = i as f32 / (config.line_count / SYSTEM_COUNT) as f32 * TAU;
73
74 let vector = Vec2::from(ops::sin_cos(angle)).extend(ops::sin(time.elapsed_secs()));
75 let start_color = LinearRgba::rgb(vector.x, vector.z, 0.5);
76 let end_color = LinearRgba::rgb(-vector.z, -vector.y, 0.5);
77
78 draw.line_gradient(vector, -vector, start_color, end_color);
79 }
80 }
81}
Sourcepub fn ray(&mut self, start: Vec3, vector: Vec3, color: impl Into<Color>)
pub fn ray(&mut self, start: Vec3, vector: Vec3, color: impl Into<Color>)
Draw a line in 3D from start
to start + vector
.
This should be called for each frame the line needs to be rendered.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.ray(Vec3::Y, Vec3::X, GREEN);
}
Examples found in repository?
98fn draw_example_collection(
99 mut gizmos: Gizmos,
100 mut my_gizmos: Gizmos<MyRoundGizmos>,
101 time: Res<Time>,
102) {
103 gizmos.grid(
104 Quat::from_rotation_x(PI / 2.),
105 UVec2::splat(20),
106 Vec2::new(2., 2.),
107 // Light gray
108 LinearRgba::gray(0.65),
109 );
110 gizmos.grid(
111 Isometry3d::new(Vec3::splat(10.0), Quat::from_rotation_x(PI / 3. * 2.)),
112 UVec2::splat(20),
113 Vec2::new(2., 2.),
114 PURPLE,
115 );
116 gizmos.sphere(Vec3::splat(10.0), 1.0, PURPLE);
117
118 gizmos
119 .primitive_3d(
120 &Plane3d {
121 normal: Dir3::Y,
122 half_size: Vec2::splat(1.0),
123 },
124 Isometry3d::new(
125 Vec3::splat(4.0) + Vec2::from(ops::sin_cos(time.elapsed_secs())).extend(0.0),
126 Quat::from_rotation_x(PI / 2. + time.elapsed_secs()),
127 ),
128 GREEN,
129 )
130 .cell_count(UVec2::new(5, 10))
131 .spacing(Vec2::new(0.2, 0.1));
132
133 gizmos.cuboid(
134 Transform::from_translation(Vec3::Y * 0.5).with_scale(Vec3::splat(1.25)),
135 BLACK,
136 );
137 gizmos.rect(
138 Isometry3d::new(
139 Vec3::new(ops::cos(time.elapsed_secs()) * 2.5, 1., 0.),
140 Quat::from_rotation_y(PI / 2.),
141 ),
142 Vec2::splat(2.),
143 LIME,
144 );
145
146 gizmos.cross(Vec3::new(-1., 1., 1.), 0.5, FUCHSIA);
147
148 let domain = Interval::EVERYWHERE;
149 let curve = FunctionCurve::new(domain, |t| {
150 (Vec2::from(ops::sin_cos(t * 10.0))).extend(t - 6.0)
151 });
152 let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 100.0) as usize;
153 let times_and_colors = (0..=resolution)
154 .map(|n| n as f32 / resolution as f32)
155 .map(|t| t * 5.0)
156 .map(|t| (t, TEAL.mix(&HOT_PINK, t / 5.0)));
157 gizmos.curve_gradient_3d(curve, times_and_colors);
158
159 my_gizmos.sphere(Vec3::new(1., 0.5, 0.), 0.5, RED);
160
161 my_gizmos
162 .rounded_cuboid(Vec3::new(-2.0, 0.75, -0.75), Vec3::splat(0.9), TURQUOISE)
163 .edge_radius(0.1)
164 .arc_resolution(4);
165
166 for y in [0., 0.5, 1.] {
167 gizmos.ray(
168 Vec3::new(1., y, 0.),
169 Vec3::new(-3., ops::sin(time.elapsed_secs() * 3.), 0.),
170 BLUE,
171 );
172 }
173
174 my_gizmos
175 .arc_3d(
176 180.0_f32.to_radians(),
177 0.2,
178 Isometry3d::new(
179 Vec3::ONE,
180 Quat::from_rotation_arc(Vec3::Y, Vec3::ONE.normalize()),
181 ),
182 ORANGE,
183 )
184 .resolution(10);
185
186 // Circles have 32 line-segments by default.
187 my_gizmos.circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3., BLACK);
188
189 // You may want to increase this for larger circles or spheres.
190 my_gizmos
191 .circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3.1, NAVY)
192 .resolution(64);
193 my_gizmos
194 .sphere(Isometry3d::IDENTITY, 3.2, BLACK)
195 .resolution(64);
196
197 gizmos.arrow(Vec3::ZERO, Vec3::splat(1.5), YELLOW);
198
199 // You can create more complex arrows using the arrow builder.
200 gizmos
201 .arrow(Vec3::new(2., 0., 2.), Vec3::new(2., 2., 2.), ORANGE_RED)
202 .with_double_end()
203 .with_tip_length(0.5);
204}
Sourcepub fn ray_gradient<C>(
&mut self,
start: Vec3,
vector: Vec3,
start_color: C,
end_color: C,
)
pub fn ray_gradient<C>( &mut self, start: Vec3, vector: Vec3, start_color: C, end_color: C, )
Draw a line in 3D with a color gradient from start
to start + vector
.
This should be called for each frame the line needs to be rendered.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.ray_gradient(Vec3::Y, Vec3::X, GREEN, RED);
}
Sourcepub fn linestrip(
&mut self,
positions: impl IntoIterator<Item = Vec3>,
color: impl Into<Color>,
)
pub fn linestrip( &mut self, positions: impl IntoIterator<Item = Vec3>, color: impl Into<Color>, )
Draw a line in 3D made of straight segments between the points.
This should be called for each frame the line needs to be rendered.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.linestrip([Vec3::ZERO, Vec3::X, Vec3::Y], GREEN);
}
Sourcepub fn linestrip_gradient<C>(
&mut self,
points: impl IntoIterator<Item = (Vec3, C)>,
)
pub fn linestrip_gradient<C>( &mut self, points: impl IntoIterator<Item = (Vec3, C)>, )
Draw a line in 3D made of straight segments between the points, with a color gradient.
This should be called for each frame the lines need to be rendered.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.linestrip_gradient([
(Vec3::ZERO, GREEN),
(Vec3::X, RED),
(Vec3::Y, BLUE)
]);
}
Examples found in repository?
48fn bounce_ray(mut ray: Ray3d, ray_cast: &mut MeshRayCast, gizmos: &mut Gizmos, color: Color) {
49 let mut intersections = Vec::with_capacity(MAX_BOUNCES + 1);
50 intersections.push((ray.origin, Color::srgb(30.0, 0.0, 0.0)));
51
52 for i in 0..MAX_BOUNCES {
53 // Cast the ray and get the first hit
54 let Some((_, hit)) = ray_cast
55 .cast_ray(ray, &MeshRayCastSettings::default())
56 .first()
57 else {
58 break;
59 };
60
61 // Draw the point of intersection and add it to the list
62 let brightness = 1.0 + 10.0 * (1.0 - i as f32 / MAX_BOUNCES as f32);
63 intersections.push((hit.point, Color::BLACK.mix(&color, brightness)));
64 gizmos.sphere(hit.point, 0.005, Color::BLACK.mix(&color, brightness * 2.0));
65
66 // Reflect the ray off of the surface
67 ray.direction = Dir3::new(ray.direction.reflect(hit.normal)).unwrap();
68 ray.origin = hit.point + ray.direction * 1e-6;
69 }
70 gizmos.linestrip_gradient(intersections);
71}
Sourcepub fn rect(
&mut self,
isometry: impl Into<Isometry3d>,
size: Vec2,
color: impl Into<Color>,
)
pub fn rect( &mut self, isometry: impl Into<Isometry3d>, size: Vec2, color: impl Into<Color>, )
Draw a wireframe rectangle in 3D with the given isometry
applied.
If isometry == Isometry3d::IDENTITY
then
- the center is at
Vec3::ZERO
- the sizes are aligned with the
Vec3::X
andVec3::Y
axes.
This should be called for each frame the rectangle needs to be rendered.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.rect(Isometry3d::IDENTITY, Vec2::ONE, GREEN);
}
Examples found in repository?
98fn draw_example_collection(
99 mut gizmos: Gizmos,
100 mut my_gizmos: Gizmos<MyRoundGizmos>,
101 time: Res<Time>,
102) {
103 gizmos.grid(
104 Quat::from_rotation_x(PI / 2.),
105 UVec2::splat(20),
106 Vec2::new(2., 2.),
107 // Light gray
108 LinearRgba::gray(0.65),
109 );
110 gizmos.grid(
111 Isometry3d::new(Vec3::splat(10.0), Quat::from_rotation_x(PI / 3. * 2.)),
112 UVec2::splat(20),
113 Vec2::new(2., 2.),
114 PURPLE,
115 );
116 gizmos.sphere(Vec3::splat(10.0), 1.0, PURPLE);
117
118 gizmos
119 .primitive_3d(
120 &Plane3d {
121 normal: Dir3::Y,
122 half_size: Vec2::splat(1.0),
123 },
124 Isometry3d::new(
125 Vec3::splat(4.0) + Vec2::from(ops::sin_cos(time.elapsed_secs())).extend(0.0),
126 Quat::from_rotation_x(PI / 2. + time.elapsed_secs()),
127 ),
128 GREEN,
129 )
130 .cell_count(UVec2::new(5, 10))
131 .spacing(Vec2::new(0.2, 0.1));
132
133 gizmos.cuboid(
134 Transform::from_translation(Vec3::Y * 0.5).with_scale(Vec3::splat(1.25)),
135 BLACK,
136 );
137 gizmos.rect(
138 Isometry3d::new(
139 Vec3::new(ops::cos(time.elapsed_secs()) * 2.5, 1., 0.),
140 Quat::from_rotation_y(PI / 2.),
141 ),
142 Vec2::splat(2.),
143 LIME,
144 );
145
146 gizmos.cross(Vec3::new(-1., 1., 1.), 0.5, FUCHSIA);
147
148 let domain = Interval::EVERYWHERE;
149 let curve = FunctionCurve::new(domain, |t| {
150 (Vec2::from(ops::sin_cos(t * 10.0))).extend(t - 6.0)
151 });
152 let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 100.0) as usize;
153 let times_and_colors = (0..=resolution)
154 .map(|n| n as f32 / resolution as f32)
155 .map(|t| t * 5.0)
156 .map(|t| (t, TEAL.mix(&HOT_PINK, t / 5.0)));
157 gizmos.curve_gradient_3d(curve, times_and_colors);
158
159 my_gizmos.sphere(Vec3::new(1., 0.5, 0.), 0.5, RED);
160
161 my_gizmos
162 .rounded_cuboid(Vec3::new(-2.0, 0.75, -0.75), Vec3::splat(0.9), TURQUOISE)
163 .edge_radius(0.1)
164 .arc_resolution(4);
165
166 for y in [0., 0.5, 1.] {
167 gizmos.ray(
168 Vec3::new(1., y, 0.),
169 Vec3::new(-3., ops::sin(time.elapsed_secs() * 3.), 0.),
170 BLUE,
171 );
172 }
173
174 my_gizmos
175 .arc_3d(
176 180.0_f32.to_radians(),
177 0.2,
178 Isometry3d::new(
179 Vec3::ONE,
180 Quat::from_rotation_arc(Vec3::Y, Vec3::ONE.normalize()),
181 ),
182 ORANGE,
183 )
184 .resolution(10);
185
186 // Circles have 32 line-segments by default.
187 my_gizmos.circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3., BLACK);
188
189 // You may want to increase this for larger circles or spheres.
190 my_gizmos
191 .circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3.1, NAVY)
192 .resolution(64);
193 my_gizmos
194 .sphere(Isometry3d::IDENTITY, 3.2, BLACK)
195 .resolution(64);
196
197 gizmos.arrow(Vec3::ZERO, Vec3::splat(1.5), YELLOW);
198
199 // You can create more complex arrows using the arrow builder.
200 gizmos
201 .arrow(Vec3::new(2., 0., 2.), Vec3::new(2., 2., 2.), ORANGE_RED)
202 .with_double_end()
203 .with_tip_length(0.5);
204}
Sourcepub fn cuboid(
&mut self,
transform: impl TransformPoint,
color: impl Into<Color>,
)
pub fn cuboid( &mut self, transform: impl TransformPoint, color: impl Into<Color>, )
Draw a wireframe cube in 3D.
This should be called for each frame the cube needs to be rendered.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.cuboid(Transform::IDENTITY, GREEN);
}
Examples found in repository?
More examples
98fn draw_example_collection(
99 mut gizmos: Gizmos,
100 mut my_gizmos: Gizmos<MyRoundGizmos>,
101 time: Res<Time>,
102) {
103 gizmos.grid(
104 Quat::from_rotation_x(PI / 2.),
105 UVec2::splat(20),
106 Vec2::new(2., 2.),
107 // Light gray
108 LinearRgba::gray(0.65),
109 );
110 gizmos.grid(
111 Isometry3d::new(Vec3::splat(10.0), Quat::from_rotation_x(PI / 3. * 2.)),
112 UVec2::splat(20),
113 Vec2::new(2., 2.),
114 PURPLE,
115 );
116 gizmos.sphere(Vec3::splat(10.0), 1.0, PURPLE);
117
118 gizmos
119 .primitive_3d(
120 &Plane3d {
121 normal: Dir3::Y,
122 half_size: Vec2::splat(1.0),
123 },
124 Isometry3d::new(
125 Vec3::splat(4.0) + Vec2::from(ops::sin_cos(time.elapsed_secs())).extend(0.0),
126 Quat::from_rotation_x(PI / 2. + time.elapsed_secs()),
127 ),
128 GREEN,
129 )
130 .cell_count(UVec2::new(5, 10))
131 .spacing(Vec2::new(0.2, 0.1));
132
133 gizmos.cuboid(
134 Transform::from_translation(Vec3::Y * 0.5).with_scale(Vec3::splat(1.25)),
135 BLACK,
136 );
137 gizmos.rect(
138 Isometry3d::new(
139 Vec3::new(ops::cos(time.elapsed_secs()) * 2.5, 1., 0.),
140 Quat::from_rotation_y(PI / 2.),
141 ),
142 Vec2::splat(2.),
143 LIME,
144 );
145
146 gizmos.cross(Vec3::new(-1., 1., 1.), 0.5, FUCHSIA);
147
148 let domain = Interval::EVERYWHERE;
149 let curve = FunctionCurve::new(domain, |t| {
150 (Vec2::from(ops::sin_cos(t * 10.0))).extend(t - 6.0)
151 });
152 let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 100.0) as usize;
153 let times_and_colors = (0..=resolution)
154 .map(|n| n as f32 / resolution as f32)
155 .map(|t| t * 5.0)
156 .map(|t| (t, TEAL.mix(&HOT_PINK, t / 5.0)));
157 gizmos.curve_gradient_3d(curve, times_and_colors);
158
159 my_gizmos.sphere(Vec3::new(1., 0.5, 0.), 0.5, RED);
160
161 my_gizmos
162 .rounded_cuboid(Vec3::new(-2.0, 0.75, -0.75), Vec3::splat(0.9), TURQUOISE)
163 .edge_radius(0.1)
164 .arc_resolution(4);
165
166 for y in [0., 0.5, 1.] {
167 gizmos.ray(
168 Vec3::new(1., y, 0.),
169 Vec3::new(-3., ops::sin(time.elapsed_secs() * 3.), 0.),
170 BLUE,
171 );
172 }
173
174 my_gizmos
175 .arc_3d(
176 180.0_f32.to_radians(),
177 0.2,
178 Isometry3d::new(
179 Vec3::ONE,
180 Quat::from_rotation_arc(Vec3::Y, Vec3::ONE.normalize()),
181 ),
182 ORANGE,
183 )
184 .resolution(10);
185
186 // Circles have 32 line-segments by default.
187 my_gizmos.circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3., BLACK);
188
189 // You may want to increase this for larger circles or spheres.
190 my_gizmos
191 .circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3.1, NAVY)
192 .resolution(64);
193 my_gizmos
194 .sphere(Isometry3d::IDENTITY, 3.2, BLACK)
195 .resolution(64);
196
197 gizmos.arrow(Vec3::ZERO, Vec3::splat(1.5), YELLOW);
198
199 // You can create more complex arrows using the arrow builder.
200 gizmos
201 .arrow(Vec3::new(2., 0., 2.), Vec3::new(2., 2., 2.), ORANGE_RED)
202 .with_double_end()
203 .with_tip_length(0.5);
204}
Sourcepub fn line_2d(&mut self, start: Vec2, end: Vec2, color: impl Into<Color>)
pub fn line_2d(&mut self, start: Vec2, end: Vec2, color: impl Into<Color>)
Draw a line in 2D from start
to end
.
This should be called for each frame the line needs to be rendered.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.line_2d(Vec2::ZERO, Vec2::X, GREEN);
}
Examples found in repository?
More examples
40fn draw_example_collection(
41 mut gizmos: Gizmos,
42 mut my_gizmos: Gizmos<MyRoundGizmos>,
43 time: Res<Time>,
44) {
45 let sin_t_scaled = ops::sin(time.elapsed_secs()) * 50.;
46 gizmos.line_2d(Vec2::Y * -sin_t_scaled, Vec2::splat(-80.), RED);
47 gizmos.ray_2d(Vec2::Y * sin_t_scaled, Vec2::splat(80.), LIME);
48
49 gizmos
50 .grid_2d(
51 Isometry2d::IDENTITY,
52 UVec2::new(16, 9),
53 Vec2::new(80., 80.),
54 // Dark gray
55 LinearRgba::gray(0.05),
56 )
57 .outer_edges();
58
59 // Triangle
60 gizmos.linestrip_gradient_2d([
61 (Vec2::Y * 300., BLUE),
62 (Vec2::new(-255., -155.), RED),
63 (Vec2::new(255., -155.), LIME),
64 (Vec2::Y * 300., BLUE),
65 ]);
66
67 gizmos.rect_2d(Isometry2d::IDENTITY, Vec2::splat(650.), BLACK);
68
69 gizmos.cross_2d(Vec2::new(-160., 120.), 12., FUCHSIA);
70
71 let domain = Interval::EVERYWHERE;
72 let curve = FunctionCurve::new(domain, |t| Vec2::new(t, ops::sin(t / 25.0) * 100.0));
73 let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 50.0) as usize;
74 let times_and_colors = (0..=resolution)
75 .map(|n| n as f32 / resolution as f32)
76 .map(|t| (t - 0.5) * 600.0)
77 .map(|t| (t, TEAL.mix(&HOT_PINK, (t + 300.0) / 600.0)));
78 gizmos.curve_gradient_2d(curve, times_and_colors);
79
80 my_gizmos
81 .rounded_rect_2d(Isometry2d::IDENTITY, Vec2::splat(630.), BLACK)
82 .corner_radius(ops::cos(time.elapsed_secs() / 3.) * 100.);
83
84 // Circles have 32 line-segments by default.
85 // You may want to increase this for larger circles.
86 my_gizmos
87 .circle_2d(Isometry2d::IDENTITY, 300., NAVY)
88 .resolution(64);
89
90 my_gizmos.ellipse_2d(
91 Rot2::radians(time.elapsed_secs() % TAU),
92 Vec2::new(100., 200.),
93 YELLOW_GREEN,
94 );
95
96 // Arcs default resolution is linearly interpolated between
97 // 1 and 32, using the arc length as scalar.
98 my_gizmos.arc_2d(
99 Rot2::radians(sin_t_scaled / 10.),
100 FRAC_PI_2,
101 310.,
102 ORANGE_RED,
103 );
104 my_gizmos.arc_2d(Isometry2d::IDENTITY, FRAC_PI_2, 80.0, ORANGE_RED);
105 my_gizmos.long_arc_2d_between(Vec2::ZERO, Vec2::X * 20.0, Vec2::Y * 20.0, ORANGE_RED);
106 my_gizmos.short_arc_2d_between(Vec2::ZERO, Vec2::X * 40.0, Vec2::Y * 40.0, ORANGE_RED);
107
108 gizmos.arrow_2d(
109 Vec2::ZERO,
110 Vec2::from_angle(sin_t_scaled / -10. + PI / 2.) * 50.,
111 YELLOW,
112 );
113
114 // You can create more complex arrows using the arrow builder.
115 gizmos
116 .arrow_2d(
117 Vec2::ZERO,
118 Vec2::from_angle(sin_t_scaled / -10.) * 50.,
119 GREEN,
120 )
121 .with_double_end()
122 .with_tip_length(10.);
123}
Sourcepub fn line_gradient_2d<C>(
&mut self,
start: Vec2,
end: Vec2,
start_color: C,
end_color: C,
)
pub fn line_gradient_2d<C>( &mut self, start: Vec2, end: Vec2, start_color: C, end_color: C, )
Draw a line in 2D with a color gradient from start
to end
.
This should be called for each frame the line needs to be rendered.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.line_gradient_2d(Vec2::ZERO, Vec2::X, GREEN, RED);
}
Sourcepub fn linestrip_2d(
&mut self,
positions: impl IntoIterator<Item = Vec2>,
color: impl Into<Color>,
)
pub fn linestrip_2d( &mut self, positions: impl IntoIterator<Item = Vec2>, color: impl Into<Color>, )
Draw a line in 2D made of straight segments between the points.
This should be called for each frame the line needs to be rendered.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.linestrip_2d([Vec2::ZERO, Vec2::X, Vec2::Y], GREEN);
}
Examples found in repository?
129fn display_curves(
130 mut gizmos: Gizmos,
131 ease_functions: Query<(&EaseFunctionPlot, &Transform, &Children)>,
132 mut transforms: Query<&mut Transform, Without<EaseFunctionPlot>>,
133 mut ui_text: Single<&mut Text>,
134 time: Res<Time>,
135) {
136 let samples = 100;
137 let duration = 2.5;
138 let time_margin = 0.5;
139
140 let now = ((time.elapsed_secs() % (duration + time_margin * 2.0) - time_margin) / duration)
141 .clamp(0.0, 1.0);
142
143 ui_text.0 = format!("Progress: {:.2}", now);
144
145 for (EaseFunctionPlot(function, color), transform, children) in &ease_functions {
146 let center = transform.translation.xy();
147 let half_size = PLOT_SIZE / 2.0;
148
149 // Draw a box around the curve
150 gizmos.linestrip_2d(
151 [
152 center + half_size,
153 center + half_size * Vec2::new(-1., 1.),
154 center + half_size * Vec2::new(-1., -1.),
155 center + half_size * Vec2::new(1., -1.),
156 center + half_size,
157 ],
158 color.darker(0.4),
159 );
160
161 // Draw the curve
162 let f = EasingCurve::new(0.0, 1.0, *function);
163 let drawn_curve = f
164 .by_ref()
165 .graph()
166 .map(|(x, y)| center - half_size + Vec2::new(x, y) * PLOT_SIZE);
167 gizmos.curve_2d(
168 &drawn_curve,
169 drawn_curve.domain().spaced_points(samples).unwrap(),
170 *color,
171 );
172
173 // Show progress along the curve for the current time
174 let y = f.sample(now).unwrap() * PLOT_SIZE.y;
175 transforms.get_mut(children[0]).unwrap().translation.y = -half_size.y + y;
176 transforms.get_mut(children[1]).unwrap().translation =
177 -half_size.extend(0.0) + Vec3::new(now * PLOT_SIZE.x, y, 0.0);
178
179 // Show horizontal bar at y value
180 gizmos.linestrip_2d(
181 [
182 center - half_size + Vec2::Y * y,
183 center - half_size + Vec2::new(PLOT_SIZE.x, y),
184 ],
185 color.darker(0.2),
186 );
187 }
188}
Sourcepub fn linestrip_gradient_2d<C>(
&mut self,
positions: impl IntoIterator<Item = (Vec2, C)>,
)
pub fn linestrip_gradient_2d<C>( &mut self, positions: impl IntoIterator<Item = (Vec2, C)>, )
Draw a line in 2D made of straight segments between the points, with a color gradient.
This should be called for each frame the line needs to be rendered.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.linestrip_gradient_2d([
(Vec2::ZERO, GREEN),
(Vec2::X, RED),
(Vec2::Y, BLUE)
]);
}
Examples found in repository?
40fn draw_example_collection(
41 mut gizmos: Gizmos,
42 mut my_gizmos: Gizmos<MyRoundGizmos>,
43 time: Res<Time>,
44) {
45 let sin_t_scaled = ops::sin(time.elapsed_secs()) * 50.;
46 gizmos.line_2d(Vec2::Y * -sin_t_scaled, Vec2::splat(-80.), RED);
47 gizmos.ray_2d(Vec2::Y * sin_t_scaled, Vec2::splat(80.), LIME);
48
49 gizmos
50 .grid_2d(
51 Isometry2d::IDENTITY,
52 UVec2::new(16, 9),
53 Vec2::new(80., 80.),
54 // Dark gray
55 LinearRgba::gray(0.05),
56 )
57 .outer_edges();
58
59 // Triangle
60 gizmos.linestrip_gradient_2d([
61 (Vec2::Y * 300., BLUE),
62 (Vec2::new(-255., -155.), RED),
63 (Vec2::new(255., -155.), LIME),
64 (Vec2::Y * 300., BLUE),
65 ]);
66
67 gizmos.rect_2d(Isometry2d::IDENTITY, Vec2::splat(650.), BLACK);
68
69 gizmos.cross_2d(Vec2::new(-160., 120.), 12., FUCHSIA);
70
71 let domain = Interval::EVERYWHERE;
72 let curve = FunctionCurve::new(domain, |t| Vec2::new(t, ops::sin(t / 25.0) * 100.0));
73 let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 50.0) as usize;
74 let times_and_colors = (0..=resolution)
75 .map(|n| n as f32 / resolution as f32)
76 .map(|t| (t - 0.5) * 600.0)
77 .map(|t| (t, TEAL.mix(&HOT_PINK, (t + 300.0) / 600.0)));
78 gizmos.curve_gradient_2d(curve, times_and_colors);
79
80 my_gizmos
81 .rounded_rect_2d(Isometry2d::IDENTITY, Vec2::splat(630.), BLACK)
82 .corner_radius(ops::cos(time.elapsed_secs() / 3.) * 100.);
83
84 // Circles have 32 line-segments by default.
85 // You may want to increase this for larger circles.
86 my_gizmos
87 .circle_2d(Isometry2d::IDENTITY, 300., NAVY)
88 .resolution(64);
89
90 my_gizmos.ellipse_2d(
91 Rot2::radians(time.elapsed_secs() % TAU),
92 Vec2::new(100., 200.),
93 YELLOW_GREEN,
94 );
95
96 // Arcs default resolution is linearly interpolated between
97 // 1 and 32, using the arc length as scalar.
98 my_gizmos.arc_2d(
99 Rot2::radians(sin_t_scaled / 10.),
100 FRAC_PI_2,
101 310.,
102 ORANGE_RED,
103 );
104 my_gizmos.arc_2d(Isometry2d::IDENTITY, FRAC_PI_2, 80.0, ORANGE_RED);
105 my_gizmos.long_arc_2d_between(Vec2::ZERO, Vec2::X * 20.0, Vec2::Y * 20.0, ORANGE_RED);
106 my_gizmos.short_arc_2d_between(Vec2::ZERO, Vec2::X * 40.0, Vec2::Y * 40.0, ORANGE_RED);
107
108 gizmos.arrow_2d(
109 Vec2::ZERO,
110 Vec2::from_angle(sin_t_scaled / -10. + PI / 2.) * 50.,
111 YELLOW,
112 );
113
114 // You can create more complex arrows using the arrow builder.
115 gizmos
116 .arrow_2d(
117 Vec2::ZERO,
118 Vec2::from_angle(sin_t_scaled / -10.) * 50.,
119 GREEN,
120 )
121 .with_double_end()
122 .with_tip_length(10.);
123}
Sourcepub fn ray_2d(&mut self, start: Vec2, vector: Vec2, color: impl Into<Color>)
pub fn ray_2d(&mut self, start: Vec2, vector: Vec2, color: impl Into<Color>)
Draw a line in 2D from start
to start + vector
.
This should be called for each frame the line needs to be rendered.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.ray_2d(Vec2::Y, Vec2::X, GREEN);
}
Examples found in repository?
40fn draw_example_collection(
41 mut gizmos: Gizmos,
42 mut my_gizmos: Gizmos<MyRoundGizmos>,
43 time: Res<Time>,
44) {
45 let sin_t_scaled = ops::sin(time.elapsed_secs()) * 50.;
46 gizmos.line_2d(Vec2::Y * -sin_t_scaled, Vec2::splat(-80.), RED);
47 gizmos.ray_2d(Vec2::Y * sin_t_scaled, Vec2::splat(80.), LIME);
48
49 gizmos
50 .grid_2d(
51 Isometry2d::IDENTITY,
52 UVec2::new(16, 9),
53 Vec2::new(80., 80.),
54 // Dark gray
55 LinearRgba::gray(0.05),
56 )
57 .outer_edges();
58
59 // Triangle
60 gizmos.linestrip_gradient_2d([
61 (Vec2::Y * 300., BLUE),
62 (Vec2::new(-255., -155.), RED),
63 (Vec2::new(255., -155.), LIME),
64 (Vec2::Y * 300., BLUE),
65 ]);
66
67 gizmos.rect_2d(Isometry2d::IDENTITY, Vec2::splat(650.), BLACK);
68
69 gizmos.cross_2d(Vec2::new(-160., 120.), 12., FUCHSIA);
70
71 let domain = Interval::EVERYWHERE;
72 let curve = FunctionCurve::new(domain, |t| Vec2::new(t, ops::sin(t / 25.0) * 100.0));
73 let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 50.0) as usize;
74 let times_and_colors = (0..=resolution)
75 .map(|n| n as f32 / resolution as f32)
76 .map(|t| (t - 0.5) * 600.0)
77 .map(|t| (t, TEAL.mix(&HOT_PINK, (t + 300.0) / 600.0)));
78 gizmos.curve_gradient_2d(curve, times_and_colors);
79
80 my_gizmos
81 .rounded_rect_2d(Isometry2d::IDENTITY, Vec2::splat(630.), BLACK)
82 .corner_radius(ops::cos(time.elapsed_secs() / 3.) * 100.);
83
84 // Circles have 32 line-segments by default.
85 // You may want to increase this for larger circles.
86 my_gizmos
87 .circle_2d(Isometry2d::IDENTITY, 300., NAVY)
88 .resolution(64);
89
90 my_gizmos.ellipse_2d(
91 Rot2::radians(time.elapsed_secs() % TAU),
92 Vec2::new(100., 200.),
93 YELLOW_GREEN,
94 );
95
96 // Arcs default resolution is linearly interpolated between
97 // 1 and 32, using the arc length as scalar.
98 my_gizmos.arc_2d(
99 Rot2::radians(sin_t_scaled / 10.),
100 FRAC_PI_2,
101 310.,
102 ORANGE_RED,
103 );
104 my_gizmos.arc_2d(Isometry2d::IDENTITY, FRAC_PI_2, 80.0, ORANGE_RED);
105 my_gizmos.long_arc_2d_between(Vec2::ZERO, Vec2::X * 20.0, Vec2::Y * 20.0, ORANGE_RED);
106 my_gizmos.short_arc_2d_between(Vec2::ZERO, Vec2::X * 40.0, Vec2::Y * 40.0, ORANGE_RED);
107
108 gizmos.arrow_2d(
109 Vec2::ZERO,
110 Vec2::from_angle(sin_t_scaled / -10. + PI / 2.) * 50.,
111 YELLOW,
112 );
113
114 // You can create more complex arrows using the arrow builder.
115 gizmos
116 .arrow_2d(
117 Vec2::ZERO,
118 Vec2::from_angle(sin_t_scaled / -10.) * 50.,
119 GREEN,
120 )
121 .with_double_end()
122 .with_tip_length(10.);
123}
Sourcepub fn ray_gradient_2d<C>(
&mut self,
start: Vec2,
vector: Vec2,
start_color: C,
end_color: C,
)
pub fn ray_gradient_2d<C>( &mut self, start: Vec2, vector: Vec2, start_color: C, end_color: C, )
Draw a line in 2D with a color gradient from start
to start + vector
.
This should be called for each frame the line needs to be rendered.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.line_gradient(Vec3::Y, Vec3::X, GREEN, RED);
}
Sourcepub fn rect_2d(
&mut self,
isometry: impl Into<Isometry2d>,
size: Vec2,
color: impl Into<Color>,
)
pub fn rect_2d( &mut self, isometry: impl Into<Isometry2d>, size: Vec2, color: impl Into<Color>, )
Draw a wireframe rectangle in 2D with the given isometry
applied.
If isometry == Isometry2d::IDENTITY
then
- the center is at
Vec2::ZERO
- the sizes are aligned with the
Vec2::X
andVec2::Y
axes.
This should be called for each frame the rectangle needs to be rendered.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.rect_2d(Isometry2d::IDENTITY, Vec2::ONE, GREEN);
}
Examples found in repository?
More examples
182fn render_volumes(mut gizmos: Gizmos, query: Query<(&CurrentVolume, &Intersects)>) {
183 for (volume, intersects) in query.iter() {
184 let color = if **intersects { AQUA } else { ORANGE_RED };
185 match volume {
186 CurrentVolume::Aabb(a) => {
187 gizmos.rect_2d(a.center(), a.half_size() * 2., color);
188 }
189 CurrentVolume::Circle(c) => {
190 gizmos.circle_2d(c.center(), c.radius(), color);
191 }
192 }
193 }
194}
195
196#[derive(Component, Deref, DerefMut, Default)]
197struct Intersects(bool);
198
199const OFFSET_X: f32 = 125.;
200const OFFSET_Y: f32 = 75.;
201
202fn setup(mut commands: Commands) {
203 commands.spawn(Camera2d);
204
205 commands.spawn((
206 Transform::from_xyz(-OFFSET_X, OFFSET_Y, 0.),
207 Shape::Circle(Circle::new(45.)),
208 DesiredVolume::Aabb,
209 Intersects::default(),
210 ));
211
212 commands.spawn((
213 Transform::from_xyz(0., OFFSET_Y, 0.),
214 Shape::Rectangle(Rectangle::new(80., 80.)),
215 Spin,
216 DesiredVolume::Circle,
217 Intersects::default(),
218 ));
219
220 commands.spawn((
221 Transform::from_xyz(OFFSET_X, OFFSET_Y, 0.),
222 Shape::Triangle(Triangle2d::new(
223 Vec2::new(-40., -40.),
224 Vec2::new(-20., 40.),
225 Vec2::new(40., 50.),
226 )),
227 Spin,
228 DesiredVolume::Aabb,
229 Intersects::default(),
230 ));
231
232 commands.spawn((
233 Transform::from_xyz(-OFFSET_X, -OFFSET_Y, 0.),
234 Shape::Line(Segment2d::from_direction_and_length(
235 Dir2::from_xy(1., 0.3).unwrap(),
236 90.,
237 )),
238 Spin,
239 DesiredVolume::Circle,
240 Intersects::default(),
241 ));
242
243 commands.spawn((
244 Transform::from_xyz(0., -OFFSET_Y, 0.),
245 Shape::Capsule(Capsule2d::new(25., 50.)),
246 Spin,
247 DesiredVolume::Aabb,
248 Intersects::default(),
249 ));
250
251 commands.spawn((
252 Transform::from_xyz(OFFSET_X, -OFFSET_Y, 0.),
253 Shape::Polygon(RegularPolygon::new(50., 6)),
254 Spin,
255 DesiredVolume::Circle,
256 Intersects::default(),
257 ));
258
259 commands.spawn((
260 Text::default(),
261 Node {
262 position_type: PositionType::Absolute,
263 top: Val::Px(12.0),
264 left: Val::Px(12.0),
265 ..default()
266 },
267 ));
268}
269
270fn draw_filled_circle(gizmos: &mut Gizmos, position: Vec2, color: Srgba) {
271 for r in [1., 2., 3.] {
272 gizmos.circle_2d(position, r, color);
273 }
274}
275
276fn draw_ray(gizmos: &mut Gizmos, ray: &RayCast2d) {
277 gizmos.line_2d(
278 ray.ray.origin,
279 ray.ray.origin + *ray.ray.direction * ray.max,
280 WHITE,
281 );
282 draw_filled_circle(gizmos, ray.ray.origin, FUCHSIA);
283}
284
285fn get_and_draw_ray(gizmos: &mut Gizmos, time: &Time) -> RayCast2d {
286 let ray = Vec2::new(ops::cos(time.elapsed_secs()), ops::sin(time.elapsed_secs()));
287 let dist = 150. + ops::sin(0.5 * time.elapsed_secs()).abs() * 500.;
288
289 let aabb_ray = Ray2d {
290 origin: ray * 250.,
291 direction: Dir2::new_unchecked(-ray),
292 };
293 let ray_cast = RayCast2d::from_ray(aabb_ray, dist - 20.);
294
295 draw_ray(gizmos, &ray_cast);
296 ray_cast
297}
298
299fn ray_cast_system(
300 mut gizmos: Gizmos,
301 time: Res<Time>,
302 mut volumes: Query<(&CurrentVolume, &mut Intersects)>,
303) {
304 let ray_cast = get_and_draw_ray(&mut gizmos, &time);
305
306 for (volume, mut intersects) in volumes.iter_mut() {
307 let toi = match volume {
308 CurrentVolume::Aabb(a) => ray_cast.aabb_intersection_at(a),
309 CurrentVolume::Circle(c) => ray_cast.circle_intersection_at(c),
310 };
311 **intersects = toi.is_some();
312 if let Some(toi) = toi {
313 draw_filled_circle(
314 &mut gizmos,
315 ray_cast.ray.origin + *ray_cast.ray.direction * toi,
316 LIME,
317 );
318 }
319 }
320}
321
322fn aabb_cast_system(
323 mut gizmos: Gizmos,
324 time: Res<Time>,
325 mut volumes: Query<(&CurrentVolume, &mut Intersects)>,
326) {
327 let ray_cast = get_and_draw_ray(&mut gizmos, &time);
328 let aabb_cast = AabbCast2d {
329 aabb: Aabb2d::new(Vec2::ZERO, Vec2::splat(15.)),
330 ray: ray_cast,
331 };
332
333 for (volume, mut intersects) in volumes.iter_mut() {
334 let toi = match *volume {
335 CurrentVolume::Aabb(a) => aabb_cast.aabb_collision_at(a),
336 CurrentVolume::Circle(_) => None,
337 };
338
339 **intersects = toi.is_some();
340 if let Some(toi) = toi {
341 gizmos.rect_2d(
342 aabb_cast.ray.ray.origin + *aabb_cast.ray.ray.direction * toi,
343 aabb_cast.aabb.half_size() * 2.,
344 LIME,
345 );
346 }
347 }
348}
349
350fn bounding_circle_cast_system(
351 mut gizmos: Gizmos,
352 time: Res<Time>,
353 mut volumes: Query<(&CurrentVolume, &mut Intersects)>,
354) {
355 let ray_cast = get_and_draw_ray(&mut gizmos, &time);
356 let circle_cast = BoundingCircleCast {
357 circle: BoundingCircle::new(Vec2::ZERO, 15.),
358 ray: ray_cast,
359 };
360
361 for (volume, mut intersects) in volumes.iter_mut() {
362 let toi = match *volume {
363 CurrentVolume::Aabb(_) => None,
364 CurrentVolume::Circle(c) => circle_cast.circle_collision_at(c),
365 };
366
367 **intersects = toi.is_some();
368 if let Some(toi) = toi {
369 gizmos.circle_2d(
370 circle_cast.ray.ray.origin + *circle_cast.ray.ray.direction * toi,
371 circle_cast.circle.radius(),
372 LIME,
373 );
374 }
375 }
376}
377
378fn get_intersection_position(time: &Time) -> Vec2 {
379 let x = ops::cos(0.8 * time.elapsed_secs()) * 250.;
380 let y = ops::sin(0.4 * time.elapsed_secs()) * 100.;
381 Vec2::new(x, y)
382}
383
384fn aabb_intersection_system(
385 mut gizmos: Gizmos,
386 time: Res<Time>,
387 mut volumes: Query<(&CurrentVolume, &mut Intersects)>,
388) {
389 let center = get_intersection_position(&time);
390 let aabb = Aabb2d::new(center, Vec2::splat(50.));
391 gizmos.rect_2d(center, aabb.half_size() * 2., YELLOW);
392
393 for (volume, mut intersects) in volumes.iter_mut() {
394 let hit = match volume {
395 CurrentVolume::Aabb(a) => aabb.intersects(a),
396 CurrentVolume::Circle(c) => aabb.intersects(c),
397 };
398
399 **intersects = hit;
400 }
401}
104fn draw_bounds<Shape: Bounded2d + Send + Sync + 'static>(
105 q: Query<(&DrawBounds<Shape>, &GlobalTransform)>,
106 mut gizmos: Gizmos,
107) {
108 for (shape, transform) in &q {
109 let (_, rotation, translation) = transform.to_scale_rotation_translation();
110 let translation = translation.truncate();
111 let rotation = rotation.to_euler(EulerRot::XYZ).2;
112 let isometry = Isometry2d::new(translation, Rot2::radians(rotation));
113
114 let aabb = shape.0.aabb_2d(isometry);
115 gizmos.rect_2d(aabb.center(), aabb.half_size() * 2.0, RED);
116
117 let bounding_circle = shape.0.bounding_circle(isometry);
118 gizmos.circle_2d(bounding_circle.center, bounding_circle.radius(), BLUE);
119 }
120}
182fn bounding_shapes_2d(
183 shapes: Query<&Transform, With<Shape2d>>,
184 mut gizmos: Gizmos,
185 bounding_shape: Res<State<BoundingShape>>,
186) {
187 for transform in shapes.iter() {
188 // Get the rotation angle from the 3D rotation.
189 let rotation = transform.rotation.to_scaled_axis().z;
190 let rotation = Rot2::radians(rotation);
191 let isometry = Isometry2d::new(transform.translation.xy(), rotation);
192
193 match bounding_shape.get() {
194 BoundingShape::None => (),
195 BoundingShape::BoundingBox => {
196 // Get the AABB of the primitive with the rotation and translation of the mesh.
197 let aabb = HEART.aabb_2d(isometry);
198 gizmos.rect_2d(aabb.center(), aabb.half_size() * 2., WHITE);
199 }
200 BoundingShape::BoundingSphere => {
201 // Get the bounding sphere of the primitive with the rotation and translation of the mesh.
202 let bounding_circle = HEART.bounding_circle(isometry);
203 gizmos
204 .circle_2d(bounding_circle.center(), bounding_circle.radius(), WHITE)
205 .resolution(64);
206 }
207 }
208 }
209}
40fn draw_example_collection(
41 mut gizmos: Gizmos,
42 mut my_gizmos: Gizmos<MyRoundGizmos>,
43 time: Res<Time>,
44) {
45 let sin_t_scaled = ops::sin(time.elapsed_secs()) * 50.;
46 gizmos.line_2d(Vec2::Y * -sin_t_scaled, Vec2::splat(-80.), RED);
47 gizmos.ray_2d(Vec2::Y * sin_t_scaled, Vec2::splat(80.), LIME);
48
49 gizmos
50 .grid_2d(
51 Isometry2d::IDENTITY,
52 UVec2::new(16, 9),
53 Vec2::new(80., 80.),
54 // Dark gray
55 LinearRgba::gray(0.05),
56 )
57 .outer_edges();
58
59 // Triangle
60 gizmos.linestrip_gradient_2d([
61 (Vec2::Y * 300., BLUE),
62 (Vec2::new(-255., -155.), RED),
63 (Vec2::new(255., -155.), LIME),
64 (Vec2::Y * 300., BLUE),
65 ]);
66
67 gizmos.rect_2d(Isometry2d::IDENTITY, Vec2::splat(650.), BLACK);
68
69 gizmos.cross_2d(Vec2::new(-160., 120.), 12., FUCHSIA);
70
71 let domain = Interval::EVERYWHERE;
72 let curve = FunctionCurve::new(domain, |t| Vec2::new(t, ops::sin(t / 25.0) * 100.0));
73 let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 50.0) as usize;
74 let times_and_colors = (0..=resolution)
75 .map(|n| n as f32 / resolution as f32)
76 .map(|t| (t - 0.5) * 600.0)
77 .map(|t| (t, TEAL.mix(&HOT_PINK, (t + 300.0) / 600.0)));
78 gizmos.curve_gradient_2d(curve, times_and_colors);
79
80 my_gizmos
81 .rounded_rect_2d(Isometry2d::IDENTITY, Vec2::splat(630.), BLACK)
82 .corner_radius(ops::cos(time.elapsed_secs() / 3.) * 100.);
83
84 // Circles have 32 line-segments by default.
85 // You may want to increase this for larger circles.
86 my_gizmos
87 .circle_2d(Isometry2d::IDENTITY, 300., NAVY)
88 .resolution(64);
89
90 my_gizmos.ellipse_2d(
91 Rot2::radians(time.elapsed_secs() % TAU),
92 Vec2::new(100., 200.),
93 YELLOW_GREEN,
94 );
95
96 // Arcs default resolution is linearly interpolated between
97 // 1 and 32, using the arc length as scalar.
98 my_gizmos.arc_2d(
99 Rot2::radians(sin_t_scaled / 10.),
100 FRAC_PI_2,
101 310.,
102 ORANGE_RED,
103 );
104 my_gizmos.arc_2d(Isometry2d::IDENTITY, FRAC_PI_2, 80.0, ORANGE_RED);
105 my_gizmos.long_arc_2d_between(Vec2::ZERO, Vec2::X * 20.0, Vec2::Y * 20.0, ORANGE_RED);
106 my_gizmos.short_arc_2d_between(Vec2::ZERO, Vec2::X * 40.0, Vec2::Y * 40.0, ORANGE_RED);
107
108 gizmos.arrow_2d(
109 Vec2::ZERO,
110 Vec2::from_angle(sin_t_scaled / -10. + PI / 2.) * 50.,
111 YELLOW,
112 );
113
114 // You can create more complex arrows using the arrow builder.
115 gizmos
116 .arrow_2d(
117 Vec2::ZERO,
118 Vec2::from_angle(sin_t_scaled / -10.) * 50.,
119 GREEN,
120 )
121 .with_double_end()
122 .with_tip_length(10.);
123}
Sourcepub fn grid(
&mut self,
isometry: impl Into<Isometry3d>,
cell_count: UVec2,
spacing: Vec2,
color: impl Into<Color>,
) -> GridBuilder2d<'_, Config, Clear>
pub fn grid( &mut self, isometry: impl Into<Isometry3d>, cell_count: UVec2, spacing: Vec2, color: impl Into<Color>, ) -> GridBuilder2d<'_, Config, Clear>
Draw a 2D grid in 3D.
This should be called for each frame the grid needs to be rendered.
The grid’s default orientation aligns with the XY-plane.
§Arguments
isometry
defines the translation and rotation of the grid.- the translation specifies the center of the grid
- defines the orientation of the grid, by default we assume the grid is contained in a plane parallel to the XY plane
cell_count
: defines the amount of cells in the x and y axesspacing
: defines the distance between cells along the x and y axescolor
: color of the grid
§Builder methods
- The skew of the grid can be adjusted using the
.skew(...)
,.skew_x(...)
or.skew_y(...)
methods. They behave very similar to their CSS equivalents. - All outer edges can be toggled on or off using
.outer_edges(...)
. Alternatively you can use.outer_edges_x(...)
or.outer_edges_y(...)
to toggle the outer edges along an axis.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.grid(
Isometry3d::IDENTITY,
UVec2::new(10, 10),
Vec2::splat(2.),
GREEN
)
.skew_x(0.25)
.outer_edges();
}
Examples found in repository?
98fn draw_example_collection(
99 mut gizmos: Gizmos,
100 mut my_gizmos: Gizmos<MyRoundGizmos>,
101 time: Res<Time>,
102) {
103 gizmos.grid(
104 Quat::from_rotation_x(PI / 2.),
105 UVec2::splat(20),
106 Vec2::new(2., 2.),
107 // Light gray
108 LinearRgba::gray(0.65),
109 );
110 gizmos.grid(
111 Isometry3d::new(Vec3::splat(10.0), Quat::from_rotation_x(PI / 3. * 2.)),
112 UVec2::splat(20),
113 Vec2::new(2., 2.),
114 PURPLE,
115 );
116 gizmos.sphere(Vec3::splat(10.0), 1.0, PURPLE);
117
118 gizmos
119 .primitive_3d(
120 &Plane3d {
121 normal: Dir3::Y,
122 half_size: Vec2::splat(1.0),
123 },
124 Isometry3d::new(
125 Vec3::splat(4.0) + Vec2::from(ops::sin_cos(time.elapsed_secs())).extend(0.0),
126 Quat::from_rotation_x(PI / 2. + time.elapsed_secs()),
127 ),
128 GREEN,
129 )
130 .cell_count(UVec2::new(5, 10))
131 .spacing(Vec2::new(0.2, 0.1));
132
133 gizmos.cuboid(
134 Transform::from_translation(Vec3::Y * 0.5).with_scale(Vec3::splat(1.25)),
135 BLACK,
136 );
137 gizmos.rect(
138 Isometry3d::new(
139 Vec3::new(ops::cos(time.elapsed_secs()) * 2.5, 1., 0.),
140 Quat::from_rotation_y(PI / 2.),
141 ),
142 Vec2::splat(2.),
143 LIME,
144 );
145
146 gizmos.cross(Vec3::new(-1., 1., 1.), 0.5, FUCHSIA);
147
148 let domain = Interval::EVERYWHERE;
149 let curve = FunctionCurve::new(domain, |t| {
150 (Vec2::from(ops::sin_cos(t * 10.0))).extend(t - 6.0)
151 });
152 let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 100.0) as usize;
153 let times_and_colors = (0..=resolution)
154 .map(|n| n as f32 / resolution as f32)
155 .map(|t| t * 5.0)
156 .map(|t| (t, TEAL.mix(&HOT_PINK, t / 5.0)));
157 gizmos.curve_gradient_3d(curve, times_and_colors);
158
159 my_gizmos.sphere(Vec3::new(1., 0.5, 0.), 0.5, RED);
160
161 my_gizmos
162 .rounded_cuboid(Vec3::new(-2.0, 0.75, -0.75), Vec3::splat(0.9), TURQUOISE)
163 .edge_radius(0.1)
164 .arc_resolution(4);
165
166 for y in [0., 0.5, 1.] {
167 gizmos.ray(
168 Vec3::new(1., y, 0.),
169 Vec3::new(-3., ops::sin(time.elapsed_secs() * 3.), 0.),
170 BLUE,
171 );
172 }
173
174 my_gizmos
175 .arc_3d(
176 180.0_f32.to_radians(),
177 0.2,
178 Isometry3d::new(
179 Vec3::ONE,
180 Quat::from_rotation_arc(Vec3::Y, Vec3::ONE.normalize()),
181 ),
182 ORANGE,
183 )
184 .resolution(10);
185
186 // Circles have 32 line-segments by default.
187 my_gizmos.circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3., BLACK);
188
189 // You may want to increase this for larger circles or spheres.
190 my_gizmos
191 .circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3.1, NAVY)
192 .resolution(64);
193 my_gizmos
194 .sphere(Isometry3d::IDENTITY, 3.2, BLACK)
195 .resolution(64);
196
197 gizmos.arrow(Vec3::ZERO, Vec3::splat(1.5), YELLOW);
198
199 // You can create more complex arrows using the arrow builder.
200 gizmos
201 .arrow(Vec3::new(2., 0., 2.), Vec3::new(2., 2., 2.), ORANGE_RED)
202 .with_double_end()
203 .with_tip_length(0.5);
204}
Sourcepub fn grid_3d(
&mut self,
isometry: impl Into<Isometry3d>,
cell_count: UVec3,
spacing: Vec3,
color: impl Into<Color>,
) -> GridBuilder3d<'_, Config, Clear>
pub fn grid_3d( &mut self, isometry: impl Into<Isometry3d>, cell_count: UVec3, spacing: Vec3, color: impl Into<Color>, ) -> GridBuilder3d<'_, Config, Clear>
Draw a 3D grid of voxel-like cells.
This should be called for each frame the grid needs to be rendered.
§Arguments
isometry
defines the translation and rotation of the grid.- the translation specifies the center of the grid
- defines the orientation of the grid, by default we assume the grid is aligned with all axes
cell_count
: defines the amount of cells in the x, y and z axesspacing
: defines the distance between cells along the x, y and z axescolor
: color of the grid
§Builder methods
- The skew of the grid can be adjusted using the
.skew(...)
,.skew_x(...)
,.skew_y(...)
or.skew_z(...)
methods. They behave very similar to their CSS equivalents. - All outer edges can be toggled on or off using
.outer_edges(...)
. Alternatively you can use.outer_edges_x(...)
,.outer_edges_y(...)
or.outer_edges_z(...)
to toggle the outer edges along an axis.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.grid_3d(
Isometry3d::IDENTITY,
UVec3::new(10, 2, 10),
Vec3::splat(2.),
GREEN
)
.skew_x(0.25)
.outer_edges();
}
Sourcepub fn grid_2d(
&mut self,
isometry: impl Into<Isometry2d>,
cell_count: UVec2,
spacing: Vec2,
color: impl Into<Color>,
) -> GridBuilder2d<'_, Config, Clear>
pub fn grid_2d( &mut self, isometry: impl Into<Isometry2d>, cell_count: UVec2, spacing: Vec2, color: impl Into<Color>, ) -> GridBuilder2d<'_, Config, Clear>
Draw a grid in 2D.
This should be called for each frame the grid needs to be rendered.
§Arguments
isometry
defines the translation and rotation of the grid.- the translation specifies the center of the grid
- defines the orientation of the grid, by default we assume the grid is aligned with all axes
cell_count
: defines the amount of cells in the x and y axesspacing
: defines the distance between cells along the x and y axescolor
: color of the grid
§Builder methods
- The skew of the grid can be adjusted using the
.skew(...)
,.skew_x(...)
or.skew_y(...)
methods. They behave very similar to their CSS equivalents. - All outer edges can be toggled on or off using
.outer_edges(...)
. Alternatively you can use.outer_edges_x(...)
or.outer_edges_y(...)
to toggle the outer edges along an axis.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.grid_2d(
Isometry2d::IDENTITY,
UVec2::new(10, 10),
Vec2::splat(1.),
GREEN
)
.skew_x(0.25)
.outer_edges();
}
Examples found in repository?
40fn draw_example_collection(
41 mut gizmos: Gizmos,
42 mut my_gizmos: Gizmos<MyRoundGizmos>,
43 time: Res<Time>,
44) {
45 let sin_t_scaled = ops::sin(time.elapsed_secs()) * 50.;
46 gizmos.line_2d(Vec2::Y * -sin_t_scaled, Vec2::splat(-80.), RED);
47 gizmos.ray_2d(Vec2::Y * sin_t_scaled, Vec2::splat(80.), LIME);
48
49 gizmos
50 .grid_2d(
51 Isometry2d::IDENTITY,
52 UVec2::new(16, 9),
53 Vec2::new(80., 80.),
54 // Dark gray
55 LinearRgba::gray(0.05),
56 )
57 .outer_edges();
58
59 // Triangle
60 gizmos.linestrip_gradient_2d([
61 (Vec2::Y * 300., BLUE),
62 (Vec2::new(-255., -155.), RED),
63 (Vec2::new(255., -155.), LIME),
64 (Vec2::Y * 300., BLUE),
65 ]);
66
67 gizmos.rect_2d(Isometry2d::IDENTITY, Vec2::splat(650.), BLACK);
68
69 gizmos.cross_2d(Vec2::new(-160., 120.), 12., FUCHSIA);
70
71 let domain = Interval::EVERYWHERE;
72 let curve = FunctionCurve::new(domain, |t| Vec2::new(t, ops::sin(t / 25.0) * 100.0));
73 let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 50.0) as usize;
74 let times_and_colors = (0..=resolution)
75 .map(|n| n as f32 / resolution as f32)
76 .map(|t| (t - 0.5) * 600.0)
77 .map(|t| (t, TEAL.mix(&HOT_PINK, (t + 300.0) / 600.0)));
78 gizmos.curve_gradient_2d(curve, times_and_colors);
79
80 my_gizmos
81 .rounded_rect_2d(Isometry2d::IDENTITY, Vec2::splat(630.), BLACK)
82 .corner_radius(ops::cos(time.elapsed_secs() / 3.) * 100.);
83
84 // Circles have 32 line-segments by default.
85 // You may want to increase this for larger circles.
86 my_gizmos
87 .circle_2d(Isometry2d::IDENTITY, 300., NAVY)
88 .resolution(64);
89
90 my_gizmos.ellipse_2d(
91 Rot2::radians(time.elapsed_secs() % TAU),
92 Vec2::new(100., 200.),
93 YELLOW_GREEN,
94 );
95
96 // Arcs default resolution is linearly interpolated between
97 // 1 and 32, using the arc length as scalar.
98 my_gizmos.arc_2d(
99 Rot2::radians(sin_t_scaled / 10.),
100 FRAC_PI_2,
101 310.,
102 ORANGE_RED,
103 );
104 my_gizmos.arc_2d(Isometry2d::IDENTITY, FRAC_PI_2, 80.0, ORANGE_RED);
105 my_gizmos.long_arc_2d_between(Vec2::ZERO, Vec2::X * 20.0, Vec2::Y * 20.0, ORANGE_RED);
106 my_gizmos.short_arc_2d_between(Vec2::ZERO, Vec2::X * 40.0, Vec2::Y * 40.0, ORANGE_RED);
107
108 gizmos.arrow_2d(
109 Vec2::ZERO,
110 Vec2::from_angle(sin_t_scaled / -10. + PI / 2.) * 50.,
111 YELLOW,
112 );
113
114 // You can create more complex arrows using the arrow builder.
115 gizmos
116 .arrow_2d(
117 Vec2::ZERO,
118 Vec2::from_angle(sin_t_scaled / -10.) * 50.,
119 GREEN,
120 )
121 .with_double_end()
122 .with_tip_length(10.);
123}
Sourcepub fn rounded_rect(
&mut self,
isometry: impl Into<Isometry3d>,
size: Vec2,
color: impl Into<Color>,
) -> RoundedRectBuilder<'_, Config, Clear>
pub fn rounded_rect( &mut self, isometry: impl Into<Isometry3d>, size: Vec2, color: impl Into<Color>, ) -> RoundedRectBuilder<'_, Config, Clear>
Draw a wireframe rectangle with rounded corners in 3D.
This should be called for each frame the rectangle needs to be rendered.
§Arguments
isometry
defines the translation and rotation of the rectangle.- the translation specifies the center of the rectangle
- defines orientation of the rectangle, by default we assume the rectangle is contained in a plane parallel to the XY plane.
size
: defines the size of the rectangle. This refers to the ‘outer size’, similar to a bounding box.color
: color of the rectangle
§Builder methods
- The corner radius can be adjusted with the
.corner_radius(...)
method. - The resolution of the arcs at each corner (i.e. the level of detail) can be adjusted with the
.arc_resolution(...)
method.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.rounded_rect(
Isometry3d::IDENTITY,
Vec2::ONE,
GREEN
)
.corner_radius(0.25)
.arc_resolution(10);
}
Sourcepub fn rounded_rect_2d(
&mut self,
isometry: impl Into<Isometry2d>,
size: Vec2,
color: impl Into<Color>,
) -> RoundedRectBuilder<'_, Config, Clear>
pub fn rounded_rect_2d( &mut self, isometry: impl Into<Isometry2d>, size: Vec2, color: impl Into<Color>, ) -> RoundedRectBuilder<'_, Config, Clear>
Draw a wireframe rectangle with rounded corners in 2D.
This should be called for each frame the rectangle needs to be rendered.
§Arguments
isometry
defines the translation and rotation of the rectangle.- the translation specifies the center of the rectangle
- defines orientation of the rectangle, by default we assume the rectangle aligned with all axes.
size
: defines the size of the rectangle. This refers to the ‘outer size’, similar to a bounding box.color
: color of the rectangle
§Builder methods
- The corner radius can be adjusted with the
.corner_radius(...)
method. - The resolution of the arcs at each corner (i.e. the level of detail) can be adjusted with the
.arc_resolution(...)
method.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.rounded_rect_2d(
Isometry2d::IDENTITY,
Vec2::ONE,
GREEN
)
.corner_radius(0.25)
.arc_resolution(10);
}
Examples found in repository?
40fn draw_example_collection(
41 mut gizmos: Gizmos,
42 mut my_gizmos: Gizmos<MyRoundGizmos>,
43 time: Res<Time>,
44) {
45 let sin_t_scaled = ops::sin(time.elapsed_secs()) * 50.;
46 gizmos.line_2d(Vec2::Y * -sin_t_scaled, Vec2::splat(-80.), RED);
47 gizmos.ray_2d(Vec2::Y * sin_t_scaled, Vec2::splat(80.), LIME);
48
49 gizmos
50 .grid_2d(
51 Isometry2d::IDENTITY,
52 UVec2::new(16, 9),
53 Vec2::new(80., 80.),
54 // Dark gray
55 LinearRgba::gray(0.05),
56 )
57 .outer_edges();
58
59 // Triangle
60 gizmos.linestrip_gradient_2d([
61 (Vec2::Y * 300., BLUE),
62 (Vec2::new(-255., -155.), RED),
63 (Vec2::new(255., -155.), LIME),
64 (Vec2::Y * 300., BLUE),
65 ]);
66
67 gizmos.rect_2d(Isometry2d::IDENTITY, Vec2::splat(650.), BLACK);
68
69 gizmos.cross_2d(Vec2::new(-160., 120.), 12., FUCHSIA);
70
71 let domain = Interval::EVERYWHERE;
72 let curve = FunctionCurve::new(domain, |t| Vec2::new(t, ops::sin(t / 25.0) * 100.0));
73 let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 50.0) as usize;
74 let times_and_colors = (0..=resolution)
75 .map(|n| n as f32 / resolution as f32)
76 .map(|t| (t - 0.5) * 600.0)
77 .map(|t| (t, TEAL.mix(&HOT_PINK, (t + 300.0) / 600.0)));
78 gizmos.curve_gradient_2d(curve, times_and_colors);
79
80 my_gizmos
81 .rounded_rect_2d(Isometry2d::IDENTITY, Vec2::splat(630.), BLACK)
82 .corner_radius(ops::cos(time.elapsed_secs() / 3.) * 100.);
83
84 // Circles have 32 line-segments by default.
85 // You may want to increase this for larger circles.
86 my_gizmos
87 .circle_2d(Isometry2d::IDENTITY, 300., NAVY)
88 .resolution(64);
89
90 my_gizmos.ellipse_2d(
91 Rot2::radians(time.elapsed_secs() % TAU),
92 Vec2::new(100., 200.),
93 YELLOW_GREEN,
94 );
95
96 // Arcs default resolution is linearly interpolated between
97 // 1 and 32, using the arc length as scalar.
98 my_gizmos.arc_2d(
99 Rot2::radians(sin_t_scaled / 10.),
100 FRAC_PI_2,
101 310.,
102 ORANGE_RED,
103 );
104 my_gizmos.arc_2d(Isometry2d::IDENTITY, FRAC_PI_2, 80.0, ORANGE_RED);
105 my_gizmos.long_arc_2d_between(Vec2::ZERO, Vec2::X * 20.0, Vec2::Y * 20.0, ORANGE_RED);
106 my_gizmos.short_arc_2d_between(Vec2::ZERO, Vec2::X * 40.0, Vec2::Y * 40.0, ORANGE_RED);
107
108 gizmos.arrow_2d(
109 Vec2::ZERO,
110 Vec2::from_angle(sin_t_scaled / -10. + PI / 2.) * 50.,
111 YELLOW,
112 );
113
114 // You can create more complex arrows using the arrow builder.
115 gizmos
116 .arrow_2d(
117 Vec2::ZERO,
118 Vec2::from_angle(sin_t_scaled / -10.) * 50.,
119 GREEN,
120 )
121 .with_double_end()
122 .with_tip_length(10.);
123}
Sourcepub fn rounded_cuboid(
&mut self,
isometry: impl Into<Isometry3d>,
size: Vec3,
color: impl Into<Color>,
) -> RoundedCuboidBuilder<'_, Config, Clear>
pub fn rounded_cuboid( &mut self, isometry: impl Into<Isometry3d>, size: Vec3, color: impl Into<Color>, ) -> RoundedCuboidBuilder<'_, Config, Clear>
Draw a wireframe cuboid with rounded corners in 3D.
This should be called for each frame the cuboid needs to be rendered.
§Arguments
isometry
defines the translation and rotation of the cuboid.- the translation specifies the center of the cuboid
- defines orientation of the cuboid, by default we assume the cuboid aligned with all axes.
size
: defines the size of the cuboid. This refers to the ‘outer size’, similar to a bounding box.color
: color of the cuboid
§Builder methods
- The edge radius can be adjusted with the
.edge_radius(...)
method. - The resolution of the arcs at each edge (i.e. the level of detail) can be adjusted with the
.arc_resolution(...)
method.
§Example
fn system(mut gizmos: Gizmos) {
gizmos.rounded_cuboid(
Isometry3d::IDENTITY,
Vec3::ONE,
GREEN
)
.edge_radius(0.25)
.arc_resolution(10);
}
Examples found in repository?
98fn draw_example_collection(
99 mut gizmos: Gizmos,
100 mut my_gizmos: Gizmos<MyRoundGizmos>,
101 time: Res<Time>,
102) {
103 gizmos.grid(
104 Quat::from_rotation_x(PI / 2.),
105 UVec2::splat(20),
106 Vec2::new(2., 2.),
107 // Light gray
108 LinearRgba::gray(0.65),
109 );
110 gizmos.grid(
111 Isometry3d::new(Vec3::splat(10.0), Quat::from_rotation_x(PI / 3. * 2.)),
112 UVec2::splat(20),
113 Vec2::new(2., 2.),
114 PURPLE,
115 );
116 gizmos.sphere(Vec3::splat(10.0), 1.0, PURPLE);
117
118 gizmos
119 .primitive_3d(
120 &Plane3d {
121 normal: Dir3::Y,
122 half_size: Vec2::splat(1.0),
123 },
124 Isometry3d::new(
125 Vec3::splat(4.0) + Vec2::from(ops::sin_cos(time.elapsed_secs())).extend(0.0),
126 Quat::from_rotation_x(PI / 2. + time.elapsed_secs()),
127 ),
128 GREEN,
129 )
130 .cell_count(UVec2::new(5, 10))
131 .spacing(Vec2::new(0.2, 0.1));
132
133 gizmos.cuboid(
134 Transform::from_translation(Vec3::Y * 0.5).with_scale(Vec3::splat(1.25)),
135 BLACK,
136 );
137 gizmos.rect(
138 Isometry3d::new(
139 Vec3::new(ops::cos(time.elapsed_secs()) * 2.5, 1., 0.),
140 Quat::from_rotation_y(PI / 2.),
141 ),
142 Vec2::splat(2.),
143 LIME,
144 );
145
146 gizmos.cross(Vec3::new(-1., 1., 1.), 0.5, FUCHSIA);
147
148 let domain = Interval::EVERYWHERE;
149 let curve = FunctionCurve::new(domain, |t| {
150 (Vec2::from(ops::sin_cos(t * 10.0))).extend(t - 6.0)
151 });
152 let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 100.0) as usize;
153 let times_and_colors = (0..=resolution)
154 .map(|n| n as f32 / resolution as f32)
155 .map(|t| t * 5.0)
156 .map(|t| (t, TEAL.mix(&HOT_PINK, t / 5.0)));
157 gizmos.curve_gradient_3d(curve, times_and_colors);
158
159 my_gizmos.sphere(Vec3::new(1., 0.5, 0.), 0.5, RED);
160
161 my_gizmos
162 .rounded_cuboid(Vec3::new(-2.0, 0.75, -0.75), Vec3::splat(0.9), TURQUOISE)
163 .edge_radius(0.1)
164 .arc_resolution(4);
165
166 for y in [0., 0.5, 1.] {
167 gizmos.ray(
168 Vec3::new(1., y, 0.),
169 Vec3::new(-3., ops::sin(time.elapsed_secs() * 3.), 0.),
170 BLUE,
171 );
172 }
173
174 my_gizmos
175 .arc_3d(
176 180.0_f32.to_radians(),
177 0.2,
178 Isometry3d::new(
179 Vec3::ONE,
180 Quat::from_rotation_arc(Vec3::Y, Vec3::ONE.normalize()),
181 ),
182 ORANGE,
183 )
184 .resolution(10);
185
186 // Circles have 32 line-segments by default.
187 my_gizmos.circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3., BLACK);
188
189 // You may want to increase this for larger circles or spheres.
190 my_gizmos
191 .circle(Quat::from_rotation_arc(Vec3::Z, Vec3::Y), 3.1, NAVY)
192 .resolution(64);
193 my_gizmos
194 .sphere(Isometry3d::IDENTITY, 3.2, BLACK)
195 .resolution(64);
196
197 gizmos.arrow(Vec3::ZERO, Vec3::splat(1.5), YELLOW);
198
199 // You can create more complex arrows using the arrow builder.
200 gizmos
201 .arrow(Vec3::new(2., 0., 2.), Vec3::new(2., 2., 2.), ORANGE_RED)
202 .with_double_end()
203 .with_tip_length(0.5);
204}
Trait Implementations§
Source§impl<Config, Clear> SystemParam for Gizmos<'_, '_, Config, Clear>
impl<Config, Clear> SystemParam for Gizmos<'_, '_, Config, Clear>
Source§type State = GizmosFetchState<Config, Clear>
type State = GizmosFetchState<Config, Clear>
Source§type Item<'w, 's> = Gizmos<'w, 's, Config, Clear>
type Item<'w, 's> = Gizmos<'w, 's, Config, Clear>
Self
, instantiated with new lifetimes. Read moreSource§fn init_state(
world: &mut World,
system_meta: &mut SystemMeta,
) -> <Gizmos<'_, '_, Config, Clear> as SystemParam>::State
fn init_state( world: &mut World, system_meta: &mut SystemMeta, ) -> <Gizmos<'_, '_, Config, Clear> as SystemParam>::State
World
access used by this SystemParam
and creates a new instance of this param’s State
.Source§unsafe fn new_archetype(
state: &mut <Gizmos<'_, '_, Config, Clear> as SystemParam>::State,
archetype: &Archetype,
system_meta: &mut SystemMeta,
)
unsafe fn new_archetype( state: &mut <Gizmos<'_, '_, Config, Clear> as SystemParam>::State, archetype: &Archetype, system_meta: &mut SystemMeta, )
Archetype
, registers the components accessed by this SystemParam
(if applicable).a Read moreSource§fn apply(
state: &mut <Gizmos<'_, '_, Config, Clear> as SystemParam>::State,
system_meta: &SystemMeta,
world: &mut World,
)
fn apply( state: &mut <Gizmos<'_, '_, Config, Clear> as SystemParam>::State, system_meta: &SystemMeta, world: &mut World, )
SystemParam
’s state.
This is used to apply Commands
during ApplyDeferred
.Source§unsafe fn validate_param(
state: &<Gizmos<'_, '_, Config, Clear> as SystemParam>::State,
system_meta: &SystemMeta,
world: UnsafeWorldCell<'_>,
) -> Result<(), SystemParamValidationError>
unsafe fn validate_param( state: &<Gizmos<'_, '_, Config, Clear> as SystemParam>::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'_>, ) -> Result<(), SystemParamValidationError>
Source§unsafe fn get_param<'w, 's>(
state: &'s mut <Gizmos<'_, '_, Config, Clear> as SystemParam>::State,
system_meta: &SystemMeta,
world: UnsafeWorldCell<'w>,
change_tick: Tick,
) -> <Gizmos<'_, '_, Config, Clear> as SystemParam>::Item<'w, 's>
unsafe fn get_param<'w, 's>( state: &'s mut <Gizmos<'_, '_, Config, Clear> as SystemParam>::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'w>, change_tick: Tick, ) -> <Gizmos<'_, '_, Config, Clear> as SystemParam>::Item<'w, 's>
SystemParamFunction
. Read moreSource§fn queue(
state: &mut Self::State,
system_meta: &SystemMeta,
world: DeferredWorld<'_>,
)
fn queue( state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld<'_>, )
ApplyDeferred
.impl<'w, 's, Config, Clear> ReadOnlySystemParam for Gizmos<'w, 's, Config, Clear>where
Config: GizmoConfigGroup,
Clear: 'static + Send + Sync,
Deferred<'s, GizmoBuffer<Config, Clear>>: ReadOnlySystemParam,
Res<'w, GizmoConfigStore>: ReadOnlySystemParam,
Auto Trait Implementations§
impl<'w, 's, Config, Clear> Freeze for Gizmos<'w, 's, Config, Clear>
impl<'w, 's, Config, Clear> RefUnwindSafe for Gizmos<'w, 's, Config, Clear>where
Config: RefUnwindSafe,
Clear: RefUnwindSafe,
impl<'w, 's, Config, Clear> Send for Gizmos<'w, 's, Config, Clear>
impl<'w, 's, Config, Clear> Sync for Gizmos<'w, 's, Config, Clear>
impl<'w, 's, Config, Clear> Unpin for Gizmos<'w, 's, Config, Clear>
impl<'w, 's, Config = DefaultGizmoConfigGroup, Clear = ()> !UnwindSafe for Gizmos<'w, 's, Config, Clear>
Blanket Implementations§
Source§impl<T, U> AsBindGroupShaderType<U> for T
impl<T, U> AsBindGroupShaderType<U> for T
Source§fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
T
ShaderType
for self
. When used in AsBindGroup
derives, it is safe to assume that all images in self
exist.Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
, which can then be
downcast
into Box<dyn ConcreteType>
where ConcreteType
implements Trait
.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
, which can then be further
downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> FmtForward for T
impl<T> FmtForward for T
Source§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self
to use its Binary
implementation when Debug
-formatted.Source§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self
to use its Display
implementation when
Debug
-formatted.Source§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self
to use its LowerExp
implementation when
Debug
-formatted.Source§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self
to use its LowerHex
implementation when
Debug
-formatted.Source§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self
to use its Octal
implementation when Debug
-formatted.Source§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self
to use its Pointer
implementation when
Debug
-formatted.Source§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self
to use its UpperExp
implementation when
Debug
-formatted.Source§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self
to use its UpperHex
implementation when
Debug
-formatted.Source§impl<S> FromSample<S> for S
impl<S> FromSample<S> for S
fn from_sample_(s: S) -> S
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
fn into_sample(self) -> T
Source§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self
, then passes self.as_ref()
into the pipe function.Source§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self
, then passes self.as_mut()
into the pipe
function.Source§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self
, then passes self.deref()
into the pipe function.Source§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B>
of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B>
of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R>
view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R>
view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target
of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target
of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap()
only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut()
only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow()
only in debug builds, and is erased in release
builds.Source§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut()
only in debug builds, and is erased in release
builds.Source§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref()
only in debug builds, and is erased in release
builds.Source§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut()
only in debug builds, and is erased in release
builds.Source§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref()
only in debug builds, and is erased in release
builds.