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