33use std:: { f32:: consts:: TAU , iter} ;
44
55use bevy_app:: FixedUpdateScheduleIsCurrentlyRunning ;
6+ use bevy_derive:: { Deref , DerefMut } ;
67use 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 ) ]
3739pub 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
4253const _: ( ) = {
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