Skip to content

Commit f526697

Browse files
exposed GizmoBuffer
1 parent 4acb25a commit f526697

File tree

2 files changed

+88
-59
lines changed

2 files changed

+88
-59
lines changed

crates/bevy_gizmos/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ webgl = []
1616
bevy_pbr = { path = "../bevy_pbr", version = "0.12.0-dev", optional = true }
1717
bevy_sprite = { path = "../bevy_sprite", version = "0.12.0-dev", optional = true }
1818
bevy_app = { path = "../bevy_app", version = "0.12.0-dev" }
19+
bevy_derive = { path = "../bevy_derive", version = "0.12.0-dev" }
1920
bevy_ecs = { path = "../bevy_ecs", version = "0.12.0-dev" }
2021
bevy_math = { path = "../bevy_math", version = "0.12.0-dev" }
2122
bevy_asset = { path = "../bevy_asset", version = "0.12.0-dev" }

crates/bevy_gizmos/src/gizmos.rs

Lines changed: 87 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use std::{f32::consts::TAU, iter};
44

55
use bevy_app::FixedUpdateScheduleIsCurrentlyRunning;
6+
use bevy_derive::{Deref, DerefMut};
67
use bevy_ecs::{
78
component::Tick,
89
system::{Resource, SystemMeta, SystemParam},
@@ -34,25 +35,32 @@ pub(crate) struct GizmoStorage {
3435
}
3536

3637
/// A [`SystemParam`](bevy_ecs::system::SystemParam) for drawing gizmos.
38+
#[derive(Deref, DerefMut)]
3739
pub struct Gizmos<'s> {
38-
buffer: &'s mut <Self as SystemParam>::State,
40+
buffer: &'s mut GizmoBuffer,
41+
}
42+
43+
/// Buffer in which gizmos are recorded, usually accessed via the [`Gizmos SystemParam`](Gizmos).
44+
#[derive(Default)]
45+
pub struct GizmoBuffer {
46+
list_positions: Vec<PositionItem>,
47+
list_colors: Vec<ColorItem>,
48+
strip_positions: Vec<PositionItem>,
49+
strip_colors: Vec<ColorItem>,
3950
}
4051

4152
// Wrap to keep GizmoBuffer hidden
4253
const _: () = {
4354
#[derive(Default)]
44-
pub struct GizmoBuffer {
55+
pub struct State {
56+
buffer: GizmoBuffer,
4557
/// Which fixed update tick this belongs to, `None` if this isn't from a fixed update.
4658
fixed_time_update: Option<u64>,
47-
list_positions: Vec<PositionItem>,
48-
list_colors: Vec<ColorItem>,
49-
strip_positions: Vec<PositionItem>,
50-
strip_colors: Vec<ColorItem>,
5159
}
5260

5361
// SAFETY: Only local state is accessed.
5462
unsafe impl SystemParam for Gizmos<'_> {
55-
type State = GizmoBuffer;
63+
type State = State;
5664
type Item<'w, 's> = Gizmos<'s>;
5765

5866
fn init_state(_: &mut World, _system_meta: &mut SystemMeta) -> Self::State {
@@ -76,10 +84,14 @@ const _: () = {
7684
&mut storages.frame
7785
};
7886

79-
storage.list_positions.append(&mut state.list_positions);
80-
storage.list_colors.append(&mut state.list_colors);
81-
storage.strip_positions.append(&mut state.strip_positions);
82-
storage.strip_colors.append(&mut state.strip_colors);
87+
storage
88+
.list_positions
89+
.append(&mut state.buffer.list_positions);
90+
storage.list_colors.append(&mut state.buffer.list_colors);
91+
storage
92+
.strip_positions
93+
.append(&mut state.buffer.strip_positions);
94+
storage.strip_colors.append(&mut state.buffer.strip_colors);
8395
}
8496

8597
unsafe fn get_param<'w, 's>(
@@ -91,12 +103,14 @@ const _: () = {
91103
state.fixed_time_update = world
92104
.get_resource::<FixedUpdateScheduleIsCurrentlyRunning>()
93105
.map(|current| current.update);
94-
Gizmos { buffer: state }
106+
Gizmos {
107+
buffer: &mut state.buffer,
108+
}
95109
}
96110
}
97111
};
98112

99-
impl<'s> Gizmos<'s> {
113+
impl GizmoBuffer {
100114
/// Draw a line from `start` to `end`.
101115
///
102116
/// # Example
@@ -188,11 +202,10 @@ impl<'s> Gizmos<'s> {
188202
#[inline]
189203
pub fn linestrip(&mut self, positions: impl IntoIterator<Item = Vec3>, color: Color) {
190204
self.extend_strip_positions(positions.into_iter());
191-
let len = self.buffer.strip_positions.len();
192-
self.buffer
193-
.strip_colors
205+
let len = self.strip_positions.len();
206+
self.strip_colors
194207
.resize(len - 1, color.as_linear_rgba_f32());
195-
self.buffer.strip_colors.push([f32::NAN; 4]);
208+
self.strip_colors.push([f32::NAN; 4]);
196209
}
197210

198211
/// Draw lines between a list of points with a color gradient.
@@ -215,8 +228,8 @@ impl<'s> Gizmos<'s> {
215228
pub fn linestrip_gradient(&mut self, points: impl IntoIterator<Item = (Vec3, Color)>) {
216229
let points = points.into_iter();
217230

218-
let strip_positions = &mut self.buffer.strip_positions;
219-
let strip_colors = &mut self.buffer.strip_colors;
231+
let strip_positions = &mut self.strip_positions;
232+
let strip_colors = &mut self.strip_colors;
220233

221234
let (min, _) = points.size_hint();
222235
strip_positions.reserve(min);
@@ -256,9 +269,9 @@ impl<'s> Gizmos<'s> {
256269
normal: Vec3,
257270
radius: f32,
258271
color: Color,
259-
) -> CircleBuilder<'_, 's> {
272+
) -> CircleBuilder<'_> {
260273
CircleBuilder {
261-
gizmos: self,
274+
buffer: self,
262275
position,
263276
normal,
264277
radius,
@@ -292,9 +305,9 @@ impl<'s> Gizmos<'s> {
292305
rotation: Quat,
293306
radius: f32,
294307
color: Color,
295-
) -> SphereBuilder<'_, 's> {
308+
) -> SphereBuilder<'_> {
296309
SphereBuilder {
297-
gizmos: self,
310+
buffer: self,
298311
position,
299312
rotation,
300313
radius,
@@ -495,12 +508,7 @@ impl<'s> Gizmos<'s> {
495508
/// # bevy_ecs::system::assert_is_system(system);
496509
/// ```
497510
#[inline]
498-
pub fn circle_2d(
499-
&mut self,
500-
position: Vec2,
501-
radius: f32,
502-
color: Color,
503-
) -> Circle2dBuilder<'_, 's> {
511+
pub fn circle_2d(&mut self, position: Vec2, radius: f32, color: Color) -> Circle2dBuilder<'_> {
504512
Circle2dBuilder {
505513
gizmos: self,
506514
position,
@@ -543,7 +551,7 @@ impl<'s> Gizmos<'s> {
543551
arc_angle: f32,
544552
radius: f32,
545553
color: Color,
546-
) -> Arc2dBuilder<'_, 's> {
554+
) -> Arc2dBuilder<'_> {
547555
Arc2dBuilder {
548556
gizmos: self,
549557
position,
@@ -574,30 +582,50 @@ impl<'s> Gizmos<'s> {
574582
self.linestrip_2d([tl, tr, br, bl, tl], color);
575583
}
576584

585+
/// Draw all gizmos from another buffer.
586+
///
587+
/// # Example
588+
/// ```
589+
/// # use bevy_gizmos::{gizmos::GizmoBuffer, prelude::*};
590+
/// # use bevy_ecs::prelude::*;
591+
/// #[derive(Resource)]
592+
/// struct Buffer(GizmoBuffer);
593+
///
594+
/// fn system(mut gizmos: Gizmos, buffered: Res<Buffer>) {
595+
/// gizmos.submit_buffer(&buffered.0);
596+
/// }
597+
/// # bevy_ecs::system::assert_is_system(system);
598+
/// ```
599+
pub fn submit_buffer(&mut self, gizmos: &Self) {
600+
self.list_positions
601+
.extend_from_slice(&gizmos.list_positions);
602+
self.list_colors.extend_from_slice(&gizmos.list_colors);
603+
self.strip_positions
604+
.extend_from_slice(&gizmos.strip_positions);
605+
self.strip_colors.extend_from_slice(&gizmos.strip_colors);
606+
}
607+
577608
#[inline]
578609
fn extend_list_positions(&mut self, positions: impl IntoIterator<Item = Vec3>) {
579-
self.buffer
580-
.list_positions
610+
self.list_positions
581611
.extend(positions.into_iter().map(|vec3| vec3.to_array()));
582612
}
583613

584614
#[inline]
585615
fn extend_list_colors(&mut self, colors: impl IntoIterator<Item = Color>) {
586-
self.buffer
587-
.list_colors
616+
self.list_colors
588617
.extend(colors.into_iter().map(|color| color.as_linear_rgba_f32()));
589618
}
590619

591620
#[inline]
592621
fn add_list_color(&mut self, color: Color, count: usize) {
593-
self.buffer
594-
.list_colors
622+
self.list_colors
595623
.extend(iter::repeat(color.as_linear_rgba_f32()).take(count));
596624
}
597625

598626
#[inline]
599627
fn extend_strip_positions(&mut self, positions: impl IntoIterator<Item = Vec3>) {
600-
self.buffer.strip_positions.extend(
628+
self.strip_positions.extend(
601629
positions
602630
.into_iter()
603631
.map(|vec3| vec3.to_array())
@@ -606,88 +634,88 @@ impl<'s> Gizmos<'s> {
606634
}
607635
}
608636

609-
/// A builder returned by [`Gizmos::circle`].
610-
pub struct CircleBuilder<'a, 's> {
611-
gizmos: &'a mut Gizmos<'s>,
637+
/// A builder returned by [`GizmoBuffer::circle`].
638+
pub struct CircleBuilder<'a> {
639+
buffer: &'a mut GizmoBuffer,
612640
position: Vec3,
613641
normal: Vec3,
614642
radius: f32,
615643
color: Color,
616644
segments: usize,
617645
}
618646

619-
impl CircleBuilder<'_, '_> {
647+
impl CircleBuilder<'_> {
620648
/// Set the number of line-segments for this circle.
621649
pub fn segments(mut self, segments: usize) -> Self {
622650
self.segments = segments;
623651
self
624652
}
625653
}
626654

627-
impl Drop for CircleBuilder<'_, '_> {
655+
impl Drop for CircleBuilder<'_> {
628656
fn drop(&mut self) {
629657
let rotation = Quat::from_rotation_arc(Vec3::Z, self.normal);
630658
let positions = circle_inner(self.radius, self.segments)
631659
.map(|vec2| (self.position + rotation * vec2.extend(0.)));
632-
self.gizmos.linestrip(positions, self.color);
660+
self.buffer.linestrip(positions, self.color);
633661
}
634662
}
635663

636-
/// A builder returned by [`Gizmos::sphere`].
637-
pub struct SphereBuilder<'a, 's> {
638-
gizmos: &'a mut Gizmos<'s>,
664+
/// A builder returned by [`GizmoBuffer::sphere`].
665+
pub struct SphereBuilder<'a> {
666+
buffer: &'a mut GizmoBuffer,
639667
position: Vec3,
640668
rotation: Quat,
641669
radius: f32,
642670
color: Color,
643671
circle_segments: usize,
644672
}
645673

646-
impl SphereBuilder<'_, '_> {
674+
impl SphereBuilder<'_> {
647675
/// Set the number of line-segments per circle for this sphere.
648676
pub fn circle_segments(mut self, segments: usize) -> Self {
649677
self.circle_segments = segments;
650678
self
651679
}
652680
}
653681

654-
impl Drop for SphereBuilder<'_, '_> {
682+
impl Drop for SphereBuilder<'_> {
655683
fn drop(&mut self) {
656684
for axis in Vec3::AXES {
657-
self.gizmos
685+
self.buffer
658686
.circle(self.position, self.rotation * axis, self.radius, self.color)
659687
.segments(self.circle_segments);
660688
}
661689
}
662690
}
663691

664-
/// A builder returned by [`Gizmos::circle_2d`].
665-
pub struct Circle2dBuilder<'a, 's> {
666-
gizmos: &'a mut Gizmos<'s>,
692+
/// A builder returned by [`GizmoBuffer::circle_2d`].
693+
pub struct Circle2dBuilder<'a> {
694+
gizmos: &'a mut GizmoBuffer,
667695
position: Vec2,
668696
radius: f32,
669697
color: Color,
670698
segments: usize,
671699
}
672700

673-
impl Circle2dBuilder<'_, '_> {
701+
impl Circle2dBuilder<'_> {
674702
/// Set the number of line-segments for this circle.
675703
pub fn segments(mut self, segments: usize) -> Self {
676704
self.segments = segments;
677705
self
678706
}
679707
}
680708

681-
impl Drop for Circle2dBuilder<'_, '_> {
709+
impl Drop for Circle2dBuilder<'_> {
682710
fn drop(&mut self) {
683711
let positions = circle_inner(self.radius, self.segments).map(|vec2| (vec2 + self.position));
684712
self.gizmos.linestrip_2d(positions, self.color);
685713
}
686714
}
687715

688-
/// A builder returned by [`Gizmos::arc_2d`].
689-
pub struct Arc2dBuilder<'a, 's> {
690-
gizmos: &'a mut Gizmos<'s>,
716+
/// A builder returned by [`GizmoBuffer::arc_2d`].
717+
pub struct Arc2dBuilder<'a> {
718+
gizmos: &'a mut GizmoBuffer,
691719
position: Vec2,
692720
direction_angle: f32,
693721
arc_angle: f32,
@@ -696,15 +724,15 @@ pub struct Arc2dBuilder<'a, 's> {
696724
segments: Option<usize>,
697725
}
698726

699-
impl Arc2dBuilder<'_, '_> {
727+
impl Arc2dBuilder<'_> {
700728
/// Set the number of line-segments for this arc.
701729
pub fn segments(mut self, segments: usize) -> Self {
702730
self.segments = Some(segments);
703731
self
704732
}
705733
}
706734

707-
impl Drop for Arc2dBuilder<'_, '_> {
735+
impl Drop for Arc2dBuilder<'_> {
708736
fn drop(&mut self) {
709737
let segments = match self.segments {
710738
Some(segments) => segments,

0 commit comments

Comments
 (0)