Skip to content

Commit 29b26f7

Browse files
committed
Update API. Add basic shapes.
1 parent 7d8e1e5 commit 29b26f7

File tree

6 files changed

+247
-76
lines changed

6 files changed

+247
-76
lines changed

Cargo.toml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,16 @@ description = "Renders a rectangle, circle, and hexagon"
204204
category = "2D Rendering"
205205
wasm = true
206206

207+
[[example]]
208+
name = "2d_debug_draw"
209+
path = "examples/2d/2d_debug_draw.rs"
210+
211+
[package.metadata.example.2d_debug_draw]
212+
name = "2D Debug Drawing"
213+
description = "Simple 2D scene with basic shapes and lighting"
214+
category = "2D Rendering"
215+
wasm = true
216+
207217
[[example]]
208218
name = "sprite"
209219
path = "examples/2d/sprite.rs"
@@ -285,6 +295,16 @@ description = "A scene showcasing the built-in 3D shapes"
285295
category = "3D Rendering"
286296
wasm = true
287297

298+
[[example]]
299+
name = "3d_debug_draw"
300+
path = "examples/3d/3d_debug_draw.rs"
301+
302+
[package.metadata.example.3d_debug_draw]
303+
name = "3D Debug Drawing"
304+
description = "Simple 3D scene with basic shapes and lighting"
305+
category = "3D Rendering"
306+
wasm = true
307+
288308
[[example]]
289309
name = "lighting"
290310
path = "examples/3d/lighting.rs"

crates/bevy_debug_draw/Cargo.toml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,6 @@ repository = "https://github.com/bevyengine/bevy"
88
license = "MIT OR Apache-2.0"
99
keywords = ["bevy"]
1010

11-
[features]
12-
default = ["2d", "3d"]
13-
14-
3d = ["bevy_pbr"]
15-
2d = ["bevy_sprite"]
16-
1711
[dependencies]
1812
bevy_pbr = { path = "../bevy_pbr", version = "0.9.0-dev", optional = true }
1913
bevy_sprite = { path = "../bevy_sprite", version = "0.9.0-dev", optional = true }

crates/bevy_debug_draw/src/lib.rs

Lines changed: 142 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
use std::{marker::PhantomData, mem};
1+
use std::f32::consts::TAU;
22

33
use bevy_app::{CoreStage, Plugin};
44
use bevy_asset::{load_internal_asset, Assets, Handle, HandleUntyped};
55
use bevy_ecs::{
66
prelude::{Component, Entity},
77
query::With,
8-
system::{Commands, Query, Res, ResMut, Resource, SystemParam},
8+
system::{Commands, Query, Res, ResMut, Resource},
99
};
10-
use bevy_math::{Vec2, Vec3};
10+
use bevy_math::{vec3, Quat, Vec2, Vec3};
1111
use bevy_reflect::TypeUuid;
1212
use bevy_render::{
1313
prelude::{Color, Mesh, SpatialBundle},
@@ -16,20 +16,20 @@ use bevy_render::{
1616
Extract, RenderApp, RenderStage,
1717
};
1818

19-
#[cfg(feature = "3d")]
19+
#[cfg(feature = "bevy_pbr")]
2020
use bevy_pbr::{NotShadowCaster, NotShadowReceiver};
21-
#[cfg(feature = "2d")]
21+
#[cfg(feature = "bevy_sprite")]
2222
use bevy_sprite::Mesh2dHandle;
2323

24-
#[cfg(feature = "2d")]
24+
#[cfg(feature = "bevy_sprite")]
2525
pub mod pipeline_2d;
26-
#[cfg(feature = "3d")]
26+
#[cfg(feature = "bevy_pbr")]
2727
pub mod pipeline_3d;
2828

2929
/// The `bevy_debug_draw` prelude.
3030
pub mod prelude {
3131
#[doc(hidden)]
32-
pub use crate::{DebugDraw, DebugDraw2d, DebugDrawConfig, DebugDrawPlugin};
32+
pub use crate::{DebugDraw, DebugDrawConfig, DebugDrawPlugin};
3333
}
3434

3535
pub const SHADER_HANDLE: HandleUntyped =
@@ -39,13 +39,15 @@ pub struct DebugDrawPlugin;
3939

4040
impl Plugin for DebugDrawPlugin {
4141
fn build(&self, app: &mut bevy_app::App) {
42-
app.init_resource::<DebugDrawResource>()
42+
load_internal_asset!(app, SHADER_HANDLE, "debuglines.wgsl", Shader::from_wgsl);
43+
44+
app.init_resource::<DebugDraw>()
4345
.init_resource::<DebugDrawConfig>()
4446
.add_system_to_stage(CoreStage::PostUpdate, update)
4547
.sub_app_mut(RenderApp)
4648
.add_system_to_stage(RenderStage::Extract, extract);
4749

48-
#[cfg(feature = "2d")]
50+
#[cfg(feature = "bevy_sprite")]
4951
{
5052
use bevy_core_pipeline::core_2d::Transparent2d;
5153
use pipeline_2d::*;
@@ -57,7 +59,7 @@ impl Plugin for DebugDrawPlugin {
5759
.add_system_to_stage(RenderStage::Queue, queue);
5860
}
5961

60-
#[cfg(feature = "3d")]
62+
#[cfg(feature = "bevy_pbr")]
6163
{
6264
use bevy_core_pipeline::core_3d::Opaque3d;
6365
use pipeline_3d::*;
@@ -68,13 +70,15 @@ impl Plugin for DebugDrawPlugin {
6870
.init_resource::<SpecializedMeshPipelines<DebugLinePipeline>>()
6971
.add_system_to_stage(RenderStage::Queue, queue);
7072
}
71-
72-
load_internal_asset!(app, SHADER_HANDLE, "debuglines.wgsl", Shader::from_wgsl);
7373
}
7474
}
7575

7676
#[derive(Resource, Clone, Copy)]
7777
pub struct DebugDrawConfig {
78+
/// Whether debug drawing should be shown.
79+
///
80+
/// Defaults to `true`.
81+
pub enabled: bool,
7882
/// Whether debug drawing should ignore depth and draw on top of everything else.
7983
///
8084
/// Defaults to `true`.
@@ -84,118 +88,188 @@ pub struct DebugDrawConfig {
8488
impl Default for DebugDrawConfig {
8589
fn default() -> Self {
8690
Self {
91+
enabled: true,
8792
always_on_top: true,
8893
}
8994
}
9095
}
9196

92-
#[derive(Resource, Default)]
93-
pub struct DebugDrawResource {
97+
#[derive(Resource)]
98+
pub struct DebugDraw {
9499
positions: Vec<[f32; 3]>,
95100
colors: Vec<[f32; 4]>,
96101
mesh_handle: Option<Handle<Mesh>>,
102+
/// The amount of line segments to use when drawing a circle.
103+
///
104+
/// Defaults to `24`.
105+
pub circle_segments: u32,
106+
}
107+
108+
impl Default for DebugDraw {
109+
fn default() -> Self {
110+
DebugDraw {
111+
positions: Vec::new(),
112+
colors: Vec::new(),
113+
mesh_handle: None,
114+
circle_segments: 24,
115+
}
116+
}
97117
}
98118

99-
impl DebugDrawResource {
119+
impl DebugDraw {
100120
/// Draw a line from `start` to `end`.
101-
fn line(&mut self, start: Vec3, end: Vec3, color: Color) {
102-
self.positions
103-
.extend_from_slice(&[start.to_array(), end.to_array()]);
121+
pub fn line(&mut self, start: Vec3, end: Vec3, color: Color) {
122+
self.positions.extend([start.to_array(), end.to_array()]);
104123
let color = color.as_linear_rgba_f32();
105-
self.colors.extend_from_slice(&[color, color]);
124+
self.colors.extend([color, color]);
106125
}
107126

108127
/// Draw a line from `start` to `start + vector`.
109-
fn ray(&mut self, start: Vec3, vector: Vec3, color: Color) {
128+
pub fn ray(&mut self, start: Vec3, vector: Vec3, color: Color) {
110129
self.line(start, start + vector, color);
111130
}
112131

113-
fn clear(&mut self) {
114-
self.positions.clear();
115-
self.colors.clear();
116-
}
132+
/// Draw a circle at `position` with the flat side facing `normal`.
133+
pub fn circle(&mut self, position: Vec3, normal: Vec3, radius: f32, color: Color) {
134+
let rotation = Quat::from_rotation_arc(Vec3::Z, normal);
135+
self.positions
136+
.extend((0..self.circle_segments).into_iter().flat_map(|i| {
137+
let angle = i as f32 * TAU / self.circle_segments as f32;
117138

118-
fn update_mesh(&mut self, mesh: &mut Mesh) {
119-
mesh.insert_attribute(Mesh::ATTRIBUTE_POSITION, mem::take(&mut self.positions));
120-
mesh.insert_attribute(Mesh::ATTRIBUTE_COLOR, mem::take(&mut self.colors));
121-
}
122-
}
139+
let (y, x) = angle.sin_cos();
140+
let start = rotation * Vec3::new(x, y, 0.) * radius + position;
123141

124-
#[derive(SystemParam)]
125-
pub struct DebugDraw<'w, 's> {
126-
debug_draw: ResMut<'w, DebugDrawResource>,
127-
#[system_param(ignore)]
128-
marker: PhantomData<&'s ()>,
129-
}
142+
let (y, x) = (angle + TAU / self.circle_segments as f32).sin_cos();
143+
let end = rotation * Vec3::new(x, y, 0.) * radius + position;
130144

131-
impl<'w, 's> DebugDraw<'w, 's> {
132-
/// Draw a line from `start` to `end`.
133-
pub fn line(&mut self, start: Vec3, end: Vec3, color: Color) {
134-
self.debug_draw.line(start, end, color);
145+
[start.to_array(), end.to_array()]
146+
}));
147+
148+
self.colors.extend(
149+
std::iter::repeat(color.as_linear_rgba_f32()).take(self.circle_segments as usize * 2),
150+
);
135151
}
136152

137-
/// Draw a line from `start` to `start + vector`.
138-
pub fn ray(&mut self, start: Vec3, vector: Vec3, color: Color) {
139-
self.debug_draw.ray(start, vector, color);
153+
/// Draw a sphere.
154+
pub fn sphere(&mut self, position: Vec3, radius: f32, color: Color) {
155+
self.circle(position, Vec3::X, radius, color);
156+
self.circle(position, Vec3::Y, radius, color);
157+
self.circle(position, Vec3::Z, radius, color);
140158
}
141159

142-
pub fn clear(&mut self) {
143-
self.debug_draw.clear();
160+
/// Draw a rectangle.
161+
pub fn rect(&mut self, position: Vec3, rotation: Quat, size: Vec2, color: Color) {
162+
let half_size = size / 2.;
163+
let tl = (position + rotation * vec3(-half_size.x, half_size.y, 0.)).to_array();
164+
let tr = (position + rotation * vec3(half_size.x, half_size.y, 0.)).to_array();
165+
let bl = (position + rotation * vec3(-half_size.x, -half_size.y, 0.)).to_array();
166+
let br = (position + rotation * vec3(half_size.x, -half_size.y, 0.)).to_array();
167+
self.positions.extend([tl, tr, tr, br, br, bl, bl, tl]);
168+
self.colors
169+
.extend(std::iter::repeat(color.as_linear_rgba_f32()).take(8))
144170
}
145-
}
146171

147-
#[derive(SystemParam)]
148-
pub struct DebugDraw2d<'w, 's> {
149-
debug_draw: ResMut<'w, DebugDrawResource>,
150-
#[system_param(ignore)]
151-
marker: PhantomData<&'s ()>,
152-
}
172+
/// Draw a box.
173+
pub fn cuboid(&mut self, position: Vec3, rotation: Quat, size: Vec3, color: Color) {
174+
let half_size = size / 2.;
175+
// Front
176+
let tlf = (position + rotation * vec3(-half_size.x, half_size.y, half_size.z)).to_array();
177+
let trf = (position + rotation * vec3(half_size.x, half_size.y, half_size.z)).to_array();
178+
let blf = (position + rotation * vec3(-half_size.x, -half_size.y, half_size.z)).to_array();
179+
let brf = (position + rotation * vec3(half_size.x, -half_size.y, half_size.z)).to_array();
180+
// Back
181+
let tlb = (position + rotation * vec3(-half_size.x, half_size.y, -half_size.z)).to_array();
182+
let trb = (position + rotation * vec3(half_size.x, half_size.y, -half_size.z)).to_array();
183+
let blb = (position + rotation * vec3(-half_size.x, -half_size.y, -half_size.z)).to_array();
184+
let brb = (position + rotation * vec3(half_size.x, -half_size.y, -half_size.z)).to_array();
185+
self.positions.extend([
186+
tlf, trf, trf, brf, brf, blf, blf, tlf, // Front
187+
tlb, trb, trb, brb, brb, blb, blb, tlb, // Back
188+
tlf, tlb, trf, trb, brf, brb, blf, blb, // Front to back
189+
]);
190+
self.colors
191+
.extend(std::iter::repeat(color.as_linear_rgba_f32()).take(24))
192+
}
193+
194+
/// Draw an axis-aligned box.
195+
pub fn aab(&mut self, position: Vec3, size: Vec3, color: Color) {
196+
self.cuboid(position, Quat::IDENTITY, size, color);
197+
}
153198

154-
impl<'w, 's> DebugDraw2d<'w, 's> {
155199
/// Draw a line from `start` to `end`.
156-
pub fn line(&mut self, start: Vec2, end: Vec2, color: Color) {
157-
self.debug_draw
158-
.line(start.extend(0.), end.extend(0.), color);
200+
pub fn line_2d(&mut self, start: Vec2, end: Vec2, color: Color) {
201+
self.line(start.extend(0.), end.extend(0.), color);
159202
}
160203

161204
/// Draw a line from `start` to `start + vector`.
162-
pub fn ray(&mut self, start: Vec2, vector: Vec2, color: Color) {
163-
self.debug_draw
164-
.ray(start.extend(0.), vector.extend(0.), color);
205+
pub fn ray_2d(&mut self, start: Vec2, vector: Vec2, color: Color) {
206+
self.ray(start.extend(0.), vector.extend(0.), color);
207+
}
208+
209+
pub fn circle_2d(&mut self, position: Vec2, radius: f32, color: Color) {
210+
self.circle(position.extend(0.), Vec3::Z, radius, color);
211+
}
212+
213+
/// Draw a rectangle at `position`.
214+
pub fn rect_2d(&mut self, position: Vec2, rotation: f32, size: Vec2, color: Color) {
215+
self.rect(
216+
position.extend(0.),
217+
Quat::from_rotation_z(rotation),
218+
size,
219+
color,
220+
);
165221
}
166222

167223
pub fn clear(&mut self) {
168-
self.debug_draw.clear();
224+
self.positions.clear();
225+
self.colors.clear();
226+
}
227+
228+
pub fn update_mesh(&mut self, mesh: &mut Mesh) {
229+
mesh.insert_attribute(
230+
Mesh::ATTRIBUTE_POSITION,
231+
std::mem::take(&mut self.positions),
232+
);
233+
mesh.insert_attribute(Mesh::ATTRIBUTE_COLOR, std::mem::take(&mut self.colors));
169234
}
170235
}
171236

172237
#[derive(Component)]
173238
pub struct DebugDrawMesh;
174239

175240
pub(crate) fn update(
176-
mut draw: ResMut<DebugDrawResource>,
241+
config: Res<DebugDrawConfig>,
242+
mut debug_draw: ResMut<DebugDraw>,
177243
mut meshes: ResMut<Assets<Mesh>>,
178244
mut commands: Commands,
179245
) {
180-
if let Some(mut mesh) = draw
246+
if let Some(mut mesh) = debug_draw
181247
.mesh_handle
182248
.as_ref()
183249
.and_then(|handle| meshes.get_mut(handle))
184250
{
185-
draw.update_mesh(&mut mesh);
186-
} else {
251+
if config.enabled {
252+
debug_draw.update_mesh(&mut mesh);
253+
} else {
254+
debug_draw.clear();
255+
mesh.remove_attribute(Mesh::ATTRIBUTE_POSITION);
256+
mesh.remove_attribute(Mesh::ATTRIBUTE_COLOR);
257+
}
258+
} else if config.enabled {
187259
let mut mesh = Mesh::new(PrimitiveTopology::LineList);
188-
draw.update_mesh(&mut mesh);
260+
debug_draw.update_mesh(&mut mesh);
189261
let mesh_handle = meshes.add(mesh);
190262
commands.spawn((
191263
SpatialBundle::VISIBLE_IDENTITY,
192264
DebugDrawMesh,
193-
#[cfg(feature = "3d")]
265+
#[cfg(feature = "bevy_pbr")]
194266
(mesh_handle.clone_weak(), NotShadowCaster, NotShadowReceiver),
195-
#[cfg(feature = "2d")]
267+
#[cfg(feature = "bevy_sprite")]
196268
Mesh2dHandle(mesh_handle.clone_weak()),
197269
));
198-
draw.mesh_handle = Some(mesh_handle);
270+
debug_draw.mesh_handle = Some(mesh_handle);
271+
} else {
272+
debug_draw.clear();
199273
}
200274
}
201275

crates/bevy_internal/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ bevy_ci_testing = ["bevy_app/bevy_ci_testing", "bevy_render?/ci_limits"]
6363
# Enable animation support, and glTF animation loading
6464
animation = ["bevy_animation", "bevy_gltf?/bevy_animation"]
6565

66-
bevy_sprite = ["dep:bevy_sprite", "bevy_debug_draw?/2d"]
67-
bevy_pbr = ["dep:bevy_pbr", "bevy_debug_draw?/3d"]
66+
bevy_sprite = ["dep:bevy_sprite", "bevy_debug_draw?/bevy_sprite"]
67+
bevy_pbr = ["dep:bevy_pbr", "bevy_debug_draw?/bevy_pbr"]
6868

6969
[dependencies]
7070
# bevy

0 commit comments

Comments
 (0)