3
3
use std:: { f32:: consts:: TAU , iter} ;
4
4
5
5
use bevy_app:: FixedUpdateScheduleIsCurrentlyRunning ;
6
+ use bevy_derive:: { Deref , DerefMut } ;
6
7
use bevy_ecs:: {
7
8
component:: Tick ,
8
9
system:: { Resource , SystemMeta , SystemParam } ,
@@ -34,25 +35,32 @@ pub(crate) struct GizmoStorage {
34
35
}
35
36
36
37
/// A [`SystemParam`](bevy_ecs::system::SystemParam) for drawing gizmos.
38
+ #[ derive( Deref , DerefMut ) ]
37
39
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 > ,
39
50
}
40
51
41
52
// Wrap to keep GizmoBuffer hidden
42
53
const _: ( ) = {
43
54
#[ derive( Default ) ]
44
- pub struct GizmoBuffer {
55
+ pub struct State {
56
+ buffer : GizmoBuffer ,
45
57
/// Which fixed update tick this belongs to, `None` if this isn't from a fixed update.
46
58
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 > ,
51
59
}
52
60
53
61
// SAFETY: Only local state is accessed.
54
62
unsafe impl SystemParam for Gizmos < ' _ > {
55
- type State = GizmoBuffer ;
63
+ type State = State ;
56
64
type Item < ' w , ' s > = Gizmos < ' s > ;
57
65
58
66
fn init_state ( _: & mut World , _system_meta : & mut SystemMeta ) -> Self :: State {
@@ -76,10 +84,14 @@ const _: () = {
76
84
& mut storages. frame
77
85
} ;
78
86
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 ) ;
83
95
}
84
96
85
97
unsafe fn get_param < ' w , ' s > (
@@ -91,12 +103,14 @@ const _: () = {
91
103
state. fixed_time_update = world
92
104
. get_resource :: < FixedUpdateScheduleIsCurrentlyRunning > ( )
93
105
. map ( |current| current. update ) ;
94
- Gizmos { buffer : state }
106
+ Gizmos {
107
+ buffer : & mut state. buffer ,
108
+ }
95
109
}
96
110
}
97
111
} ;
98
112
99
- impl < ' s > Gizmos < ' s > {
113
+ impl GizmoBuffer {
100
114
/// Draw a line from `start` to `end`.
101
115
///
102
116
/// # Example
@@ -188,11 +202,10 @@ impl<'s> Gizmos<'s> {
188
202
#[ inline]
189
203
pub fn linestrip ( & mut self , positions : impl IntoIterator < Item = Vec3 > , color : Color ) {
190
204
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
194
207
. 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 ] ) ;
196
209
}
197
210
198
211
/// Draw lines between a list of points with a color gradient.
@@ -215,8 +228,8 @@ impl<'s> Gizmos<'s> {
215
228
pub fn linestrip_gradient ( & mut self , points : impl IntoIterator < Item = ( Vec3 , Color ) > ) {
216
229
let points = points. into_iter ( ) ;
217
230
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 ;
220
233
221
234
let ( min, _) = points. size_hint ( ) ;
222
235
strip_positions. reserve ( min) ;
@@ -256,9 +269,9 @@ impl<'s> Gizmos<'s> {
256
269
normal : Vec3 ,
257
270
radius : f32 ,
258
271
color : Color ,
259
- ) -> CircleBuilder < ' _ , ' s > {
272
+ ) -> CircleBuilder < ' _ > {
260
273
CircleBuilder {
261
- gizmos : self ,
274
+ buffer : self ,
262
275
position,
263
276
normal,
264
277
radius,
@@ -292,9 +305,9 @@ impl<'s> Gizmos<'s> {
292
305
rotation : Quat ,
293
306
radius : f32 ,
294
307
color : Color ,
295
- ) -> SphereBuilder < ' _ , ' s > {
308
+ ) -> SphereBuilder < ' _ > {
296
309
SphereBuilder {
297
- gizmos : self ,
310
+ buffer : self ,
298
311
position,
299
312
rotation,
300
313
radius,
@@ -495,12 +508,7 @@ impl<'s> Gizmos<'s> {
495
508
/// # bevy_ecs::system::assert_is_system(system);
496
509
/// ```
497
510
#[ 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 < ' _ > {
504
512
Circle2dBuilder {
505
513
gizmos : self ,
506
514
position,
@@ -543,7 +551,7 @@ impl<'s> Gizmos<'s> {
543
551
arc_angle : f32 ,
544
552
radius : f32 ,
545
553
color : Color ,
546
- ) -> Arc2dBuilder < ' _ , ' s > {
554
+ ) -> Arc2dBuilder < ' _ > {
547
555
Arc2dBuilder {
548
556
gizmos : self ,
549
557
position,
@@ -574,30 +582,50 @@ impl<'s> Gizmos<'s> {
574
582
self . linestrip_2d ( [ tl, tr, br, bl, tl] , color) ;
575
583
}
576
584
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
+
577
608
#[ inline]
578
609
fn extend_list_positions ( & mut self , positions : impl IntoIterator < Item = Vec3 > ) {
579
- self . buffer
580
- . list_positions
610
+ self . list_positions
581
611
. extend ( positions. into_iter ( ) . map ( |vec3| vec3. to_array ( ) ) ) ;
582
612
}
583
613
584
614
#[ inline]
585
615
fn extend_list_colors ( & mut self , colors : impl IntoIterator < Item = Color > ) {
586
- self . buffer
587
- . list_colors
616
+ self . list_colors
588
617
. extend ( colors. into_iter ( ) . map ( |color| color. as_linear_rgba_f32 ( ) ) ) ;
589
618
}
590
619
591
620
#[ inline]
592
621
fn add_list_color ( & mut self , color : Color , count : usize ) {
593
- self . buffer
594
- . list_colors
622
+ self . list_colors
595
623
. extend ( iter:: repeat ( color. as_linear_rgba_f32 ( ) ) . take ( count) ) ;
596
624
}
597
625
598
626
#[ inline]
599
627
fn extend_strip_positions ( & mut self , positions : impl IntoIterator < Item = Vec3 > ) {
600
- self . buffer . strip_positions . extend (
628
+ self . strip_positions . extend (
601
629
positions
602
630
. into_iter ( )
603
631
. map ( |vec3| vec3. to_array ( ) )
@@ -606,88 +634,88 @@ impl<'s> Gizmos<'s> {
606
634
}
607
635
}
608
636
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 ,
612
640
position : Vec3 ,
613
641
normal : Vec3 ,
614
642
radius : f32 ,
615
643
color : Color ,
616
644
segments : usize ,
617
645
}
618
646
619
- impl CircleBuilder < ' _ , ' _ > {
647
+ impl CircleBuilder < ' _ > {
620
648
/// Set the number of line-segments for this circle.
621
649
pub fn segments ( mut self , segments : usize ) -> Self {
622
650
self . segments = segments;
623
651
self
624
652
}
625
653
}
626
654
627
- impl Drop for CircleBuilder < ' _ , ' _ > {
655
+ impl Drop for CircleBuilder < ' _ > {
628
656
fn drop ( & mut self ) {
629
657
let rotation = Quat :: from_rotation_arc ( Vec3 :: Z , self . normal ) ;
630
658
let positions = circle_inner ( self . radius , self . segments )
631
659
. map ( |vec2| ( self . position + rotation * vec2. extend ( 0. ) ) ) ;
632
- self . gizmos . linestrip ( positions, self . color ) ;
660
+ self . buffer . linestrip ( positions, self . color ) ;
633
661
}
634
662
}
635
663
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 ,
639
667
position : Vec3 ,
640
668
rotation : Quat ,
641
669
radius : f32 ,
642
670
color : Color ,
643
671
circle_segments : usize ,
644
672
}
645
673
646
- impl SphereBuilder < ' _ , ' _ > {
674
+ impl SphereBuilder < ' _ > {
647
675
/// Set the number of line-segments per circle for this sphere.
648
676
pub fn circle_segments ( mut self , segments : usize ) -> Self {
649
677
self . circle_segments = segments;
650
678
self
651
679
}
652
680
}
653
681
654
- impl Drop for SphereBuilder < ' _ , ' _ > {
682
+ impl Drop for SphereBuilder < ' _ > {
655
683
fn drop ( & mut self ) {
656
684
for axis in Vec3 :: AXES {
657
- self . gizmos
685
+ self . buffer
658
686
. circle ( self . position , self . rotation * axis, self . radius , self . color )
659
687
. segments ( self . circle_segments ) ;
660
688
}
661
689
}
662
690
}
663
691
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 ,
667
695
position : Vec2 ,
668
696
radius : f32 ,
669
697
color : Color ,
670
698
segments : usize ,
671
699
}
672
700
673
- impl Circle2dBuilder < ' _ , ' _ > {
701
+ impl Circle2dBuilder < ' _ > {
674
702
/// Set the number of line-segments for this circle.
675
703
pub fn segments ( mut self , segments : usize ) -> Self {
676
704
self . segments = segments;
677
705
self
678
706
}
679
707
}
680
708
681
- impl Drop for Circle2dBuilder < ' _ , ' _ > {
709
+ impl Drop for Circle2dBuilder < ' _ > {
682
710
fn drop ( & mut self ) {
683
711
let positions = circle_inner ( self . radius , self . segments ) . map ( |vec2| ( vec2 + self . position ) ) ;
684
712
self . gizmos . linestrip_2d ( positions, self . color ) ;
685
713
}
686
714
}
687
715
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 ,
691
719
position : Vec2 ,
692
720
direction_angle : f32 ,
693
721
arc_angle : f32 ,
@@ -696,15 +724,15 @@ pub struct Arc2dBuilder<'a, 's> {
696
724
segments : Option < usize > ,
697
725
}
698
726
699
- impl Arc2dBuilder < ' _ , ' _ > {
727
+ impl Arc2dBuilder < ' _ > {
700
728
/// Set the number of line-segments for this arc.
701
729
pub fn segments ( mut self , segments : usize ) -> Self {
702
730
self . segments = Some ( segments) ;
703
731
self
704
732
}
705
733
}
706
734
707
- impl Drop for Arc2dBuilder < ' _ , ' _ > {
735
+ impl Drop for Arc2dBuilder < ' _ > {
708
736
fn drop ( & mut self ) {
709
737
let segments = match self . segments {
710
738
Some ( segments) => segments,
0 commit comments