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,31 @@ 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+ #[ derive( Default ) ]
44+ pub struct GizmoBuffer {
45+ list_positions : Vec < PositionItem > ,
46+ list_colors : Vec < ColorItem > ,
47+ strip_positions : Vec < PositionItem > ,
48+ strip_colors : Vec < ColorItem > ,
3949}
4050
4151// Wrap to keep GizmoBuffer hidden
4252const _: ( ) = {
4353 #[ derive( Default ) ]
44- pub struct GizmoBuffer {
54+ pub struct State {
55+ buffer : GizmoBuffer ,
4556 /// Which fixed update tick this belongs to, `None` if this isn't from a fixed update.
4657 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 > ,
5158 }
5259
5360 // SAFETY: Only local state is accessed.
5461 unsafe impl SystemParam for Gizmos < ' _ > {
55- type State = GizmoBuffer ;
62+ type State = State ;
5663 type Item < ' w , ' s > = Gizmos < ' s > ;
5764
5865 fn init_state ( _: & mut World , _system_meta : & mut SystemMeta ) -> Self :: State {
@@ -76,10 +83,14 @@ const _: () = {
7683 & mut storages. frame
7784 } ;
7885
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 ) ;
86+ storage
87+ . list_positions
88+ . append ( & mut state. buffer . list_positions ) ;
89+ storage. list_colors . append ( & mut state. buffer . list_colors ) ;
90+ storage
91+ . strip_positions
92+ . append ( & mut state. buffer . strip_positions ) ;
93+ storage. strip_colors . append ( & mut state. buffer . strip_colors ) ;
8394 }
8495
8596 unsafe fn get_param < ' w , ' s > (
@@ -91,12 +102,14 @@ const _: () = {
91102 state. fixed_time_update = world
92103 . get_resource :: < FixedUpdateScheduleIsCurrentlyRunning > ( )
93104 . map ( |current| current. update ) ;
94- Gizmos { buffer : state }
105+ Gizmos {
106+ buffer : & mut state. buffer ,
107+ }
95108 }
96109 }
97110} ;
98111
99- impl < ' s > Gizmos < ' s > {
112+ impl GizmoBuffer {
100113 /// Draw a line from `start` to `end`.
101114 ///
102115 /// # Example
@@ -188,11 +201,10 @@ impl<'s> Gizmos<'s> {
188201 #[ inline]
189202 pub fn linestrip ( & mut self , positions : impl IntoIterator < Item = Vec3 > , color : Color ) {
190203 self . extend_strip_positions ( positions. into_iter ( ) ) ;
191- let len = self . buffer . strip_positions . len ( ) ;
192- self . buffer
193- . strip_colors
204+ let len = self . strip_positions . len ( ) ;
205+ self . strip_colors
194206 . resize ( len - 1 , color. as_linear_rgba_f32 ( ) ) ;
195- self . buffer . strip_colors . push ( [ f32:: NAN ; 4 ] ) ;
207+ self . strip_colors . push ( [ f32:: NAN ; 4 ] ) ;
196208 }
197209
198210 /// Draw lines between a list of points with a color gradient.
@@ -215,8 +227,8 @@ impl<'s> Gizmos<'s> {
215227 pub fn linestrip_gradient ( & mut self , points : impl IntoIterator < Item = ( Vec3 , Color ) > ) {
216228 let points = points. into_iter ( ) ;
217229
218- let strip_positions = & mut self . buffer . strip_positions ;
219- let strip_colors = & mut self . buffer . strip_colors ;
230+ let strip_positions = & mut self . strip_positions ;
231+ let strip_colors = & mut self . strip_colors ;
220232
221233 let ( min, _) = points. size_hint ( ) ;
222234 strip_positions. reserve ( min) ;
@@ -256,9 +268,9 @@ impl<'s> Gizmos<'s> {
256268 normal : Vec3 ,
257269 radius : f32 ,
258270 color : Color ,
259- ) -> CircleBuilder < ' _ , ' s > {
271+ ) -> CircleBuilder < ' _ > {
260272 CircleBuilder {
261- gizmos : self ,
273+ buffer : self ,
262274 position,
263275 normal,
264276 radius,
@@ -292,9 +304,9 @@ impl<'s> Gizmos<'s> {
292304 rotation : Quat ,
293305 radius : f32 ,
294306 color : Color ,
295- ) -> SphereBuilder < ' _ , ' s > {
307+ ) -> SphereBuilder < ' _ > {
296308 SphereBuilder {
297- gizmos : self ,
309+ buffer : self ,
298310 position,
299311 rotation,
300312 radius,
@@ -495,12 +507,7 @@ impl<'s> Gizmos<'s> {
495507 /// # bevy_ecs::system::assert_is_system(system);
496508 /// ```
497509 #[ inline]
498- pub fn circle_2d (
499- & mut self ,
500- position : Vec2 ,
501- radius : f32 ,
502- color : Color ,
503- ) -> Circle2dBuilder < ' _ , ' s > {
510+ pub fn circle_2d ( & mut self , position : Vec2 , radius : f32 , color : Color ) -> Circle2dBuilder < ' _ > {
504511 Circle2dBuilder {
505512 gizmos : self ,
506513 position,
@@ -543,7 +550,7 @@ impl<'s> Gizmos<'s> {
543550 arc_angle : f32 ,
544551 radius : f32 ,
545552 color : Color ,
546- ) -> Arc2dBuilder < ' _ , ' s > {
553+ ) -> Arc2dBuilder < ' _ > {
547554 Arc2dBuilder {
548555 gizmos : self ,
549556 position,
@@ -574,30 +581,50 @@ impl<'s> Gizmos<'s> {
574581 self . linestrip_2d ( [ tl, tr, br, bl, tl] , color) ;
575582 }
576583
584+ /// Draw all gizmos from another buffer.
585+ ///
586+ /// # Example
587+ /// ```
588+ /// # use bevy_gizmos::{gizmos::GizmoBuffer, prelude::*};
589+ /// # use bevy_ecs::prelude::*;
590+ /// #[derive(Resource)]
591+ /// struct Buffer(GizmoBuffer);
592+ ///
593+ /// fn system(mut gizmos: Gizmos, buffered: Res<Buffer>) {
594+ /// gizmos.submit_buffer(&buffered.0);
595+ /// }
596+ /// # bevy_ecs::system::assert_is_system(system);
597+ /// ```
598+ pub fn submit_buffer ( & mut self , gizmos : & Self ) {
599+ self . list_positions
600+ . extend_from_slice ( & gizmos. list_positions ) ;
601+ self . list_colors . extend_from_slice ( & gizmos. list_colors ) ;
602+ self . strip_positions
603+ . extend_from_slice ( & gizmos. strip_positions ) ;
604+ self . strip_colors . extend_from_slice ( & gizmos. strip_colors ) ;
605+ }
606+
577607 #[ inline]
578608 fn extend_list_positions ( & mut self , positions : impl IntoIterator < Item = Vec3 > ) {
579- self . buffer
580- . list_positions
609+ self . list_positions
581610 . extend ( positions. into_iter ( ) . map ( |vec3| vec3. to_array ( ) ) ) ;
582611 }
583612
584613 #[ inline]
585614 fn extend_list_colors ( & mut self , colors : impl IntoIterator < Item = Color > ) {
586- self . buffer
587- . list_colors
615+ self . list_colors
588616 . extend ( colors. into_iter ( ) . map ( |color| color. as_linear_rgba_f32 ( ) ) ) ;
589617 }
590618
591619 #[ inline]
592620 fn add_list_color ( & mut self , color : Color , count : usize ) {
593- self . buffer
594- . list_colors
621+ self . list_colors
595622 . extend ( iter:: repeat ( color. as_linear_rgba_f32 ( ) ) . take ( count) ) ;
596623 }
597624
598625 #[ inline]
599626 fn extend_strip_positions ( & mut self , positions : impl IntoIterator < Item = Vec3 > ) {
600- self . buffer . strip_positions . extend (
627+ self . strip_positions . extend (
601628 positions
602629 . into_iter ( )
603630 . map ( |vec3| vec3. to_array ( ) )
@@ -606,88 +633,88 @@ impl<'s> Gizmos<'s> {
606633 }
607634}
608635
609- /// A builder returned by [`Gizmos ::circle`].
610- pub struct CircleBuilder < ' a , ' s > {
611- gizmos : & ' a mut Gizmos < ' s > ,
636+ /// A builder returned by [`GizmoBuffer ::circle`].
637+ pub struct CircleBuilder < ' a > {
638+ buffer : & ' a mut GizmoBuffer ,
612639 position : Vec3 ,
613640 normal : Vec3 ,
614641 radius : f32 ,
615642 color : Color ,
616643 segments : usize ,
617644}
618645
619- impl CircleBuilder < ' _ , ' _ > {
646+ impl CircleBuilder < ' _ > {
620647 /// Set the number of line-segments for this circle.
621648 pub fn segments ( mut self , segments : usize ) -> Self {
622649 self . segments = segments;
623650 self
624651 }
625652}
626653
627- impl Drop for CircleBuilder < ' _ , ' _ > {
654+ impl Drop for CircleBuilder < ' _ > {
628655 fn drop ( & mut self ) {
629656 let rotation = Quat :: from_rotation_arc ( Vec3 :: Z , self . normal ) ;
630657 let positions = circle_inner ( self . radius , self . segments )
631658 . map ( |vec2| ( self . position + rotation * vec2. extend ( 0. ) ) ) ;
632- self . gizmos . linestrip ( positions, self . color ) ;
659+ self . buffer . linestrip ( positions, self . color ) ;
633660 }
634661}
635662
636- /// A builder returned by [`Gizmos ::sphere`].
637- pub struct SphereBuilder < ' a , ' s > {
638- gizmos : & ' a mut Gizmos < ' s > ,
663+ /// A builder returned by [`GizmoBuffer ::sphere`].
664+ pub struct SphereBuilder < ' a > {
665+ buffer : & ' a mut GizmoBuffer ,
639666 position : Vec3 ,
640667 rotation : Quat ,
641668 radius : f32 ,
642669 color : Color ,
643670 circle_segments : usize ,
644671}
645672
646- impl SphereBuilder < ' _ , ' _ > {
673+ impl SphereBuilder < ' _ > {
647674 /// Set the number of line-segments per circle for this sphere.
648675 pub fn circle_segments ( mut self , segments : usize ) -> Self {
649676 self . circle_segments = segments;
650677 self
651678 }
652679}
653680
654- impl Drop for SphereBuilder < ' _ , ' _ > {
681+ impl Drop for SphereBuilder < ' _ > {
655682 fn drop ( & mut self ) {
656683 for axis in Vec3 :: AXES {
657- self . gizmos
684+ self . buffer
658685 . circle ( self . position , self . rotation * axis, self . radius , self . color )
659686 . segments ( self . circle_segments ) ;
660687 }
661688 }
662689}
663690
664- /// A builder returned by [`Gizmos ::circle_2d`].
665- pub struct Circle2dBuilder < ' a , ' s > {
666- gizmos : & ' a mut Gizmos < ' s > ,
691+ /// A builder returned by [`GizmoBuffer ::circle_2d`].
692+ pub struct Circle2dBuilder < ' a > {
693+ gizmos : & ' a mut GizmoBuffer ,
667694 position : Vec2 ,
668695 radius : f32 ,
669696 color : Color ,
670697 segments : usize ,
671698}
672699
673- impl Circle2dBuilder < ' _ , ' _ > {
700+ impl Circle2dBuilder < ' _ > {
674701 /// Set the number of line-segments for this circle.
675702 pub fn segments ( mut self , segments : usize ) -> Self {
676703 self . segments = segments;
677704 self
678705 }
679706}
680707
681- impl Drop for Circle2dBuilder < ' _ , ' _ > {
708+ impl Drop for Circle2dBuilder < ' _ > {
682709 fn drop ( & mut self ) {
683710 let positions = circle_inner ( self . radius , self . segments ) . map ( |vec2| ( vec2 + self . position ) ) ;
684711 self . gizmos . linestrip_2d ( positions, self . color ) ;
685712 }
686713}
687714
688- /// A builder returned by [`Gizmos ::arc_2d`].
689- pub struct Arc2dBuilder < ' a , ' s > {
690- gizmos : & ' a mut Gizmos < ' s > ,
715+ /// A builder returned by [`GizmoBuffer ::arc_2d`].
716+ pub struct Arc2dBuilder < ' a > {
717+ gizmos : & ' a mut GizmoBuffer ,
691718 position : Vec2 ,
692719 direction_angle : f32 ,
693720 arc_angle : f32 ,
@@ -696,15 +723,15 @@ pub struct Arc2dBuilder<'a, 's> {
696723 segments : Option < usize > ,
697724}
698725
699- impl Arc2dBuilder < ' _ , ' _ > {
726+ impl Arc2dBuilder < ' _ > {
700727 /// Set the number of line-segments for this arc.
701728 pub fn segments ( mut self , segments : usize ) -> Self {
702729 self . segments = Some ( segments) ;
703730 self
704731 }
705732}
706733
707- impl Drop for Arc2dBuilder < ' _ , ' _ > {
734+ impl Drop for Arc2dBuilder < ' _ > {
708735 fn drop ( & mut self ) {
709736 let segments = match self . segments {
710737 Some ( segments) => segments,
0 commit comments