@@ -4,36 +4,39 @@ use bevy_math::{Mat2, Quat, Vec2, Vec3};
44use bevy_render:: prelude:: Color ;
55use crossbeam_channel:: { unbounded, Receiver , Sender } ;
66
7- use crate :: SendItem ;
7+ use crate :: { SendItem , GIZMO } ;
88
99pub struct GizmoDraw {
1010 sender : Sender < SendItem > ,
1111 pub ( crate ) receiver : Receiver < SendItem > ,
12- circle_segments : usize ,
1312}
1413
1514impl GizmoDraw {
1615 pub ( crate ) fn new ( ) -> Self {
1716 let ( sender, receiver) = unbounded ( ) ;
18- GizmoDraw {
19- sender,
20- receiver,
21- circle_segments : 32 ,
22- }
17+ GizmoDraw { sender, receiver }
2318 }
2419}
2520
21+ const CIRCLE_SEGMENTS : usize = 32 ;
22+
2623impl GizmoDraw {
2724 /// Draw a line from `start` to `end`.
2825 #[ inline]
2926 pub fn line ( & self , start : Vec3 , end : Vec3 , color : Color ) {
30- self . send_line ( [ start, end] , [ color, color] ) ;
27+ self . line_gradient ( start, end, color, color) ;
3128 }
3229
3330 /// Draw a line from `start` to `end`.
3431 #[ inline]
3532 pub fn line_gradient ( & self , start : Vec3 , end : Vec3 , start_color : Color , end_color : Color ) {
36- self . send_line ( [ start, end] , [ start_color, end_color] ) ;
33+ let _ = self . sender . send ( SendItem :: Single ( (
34+ [ start. to_array ( ) , end. to_array ( ) ] ,
35+ [
36+ start_color. as_linear_rgba_f32 ( ) ,
37+ end_color. as_linear_rgba_f32 ( ) ,
38+ ] ,
39+ ) ) ) ;
3740 }
3841
3942 /// Draw a line from `start` to `start + vector`.
@@ -61,39 +64,49 @@ impl GizmoDraw {
6164 let _ = self . sender . send ( SendItem :: Strip ( iter. unzip ( ) ) ) ;
6265 }
6366
64- /// Draw a circle at `position` with the flat side facing `normal`.
6567 #[ inline]
66- pub fn circle ( & self , position : Vec3 , normal : Vec3 , radius : f32 , color : Color ) {
67- let rotation = Quat :: from_rotation_arc ( Vec3 :: Z , normal) ;
68-
69- let positions = self
70- . circle_inner ( radius)
71- . map ( |vec2| ( position + rotation * vec2. extend ( 0. ) ) ) ;
68+ fn linelist ( & self , list : impl IntoIterator < Item = Vec3 > , color : Color ) {
69+ let iter = list
70+ . into_iter ( )
71+ . map ( |p| p. to_array ( ) )
72+ . zip ( iter:: repeat ( color. as_linear_rgba_f32 ( ) ) ) ;
73+ let _ = self . sender . send ( SendItem :: List ( iter. unzip ( ) ) ) ;
74+ }
7275
73- self . linestrip ( positions, color) ;
76+ /// Draw a circle at `position` with the flat side facing `normal`.
77+ #[ inline]
78+ pub fn circle ( & self , position : Vec3 , normal : Vec3 , radius : f32 , color : Color ) -> DrawCircle {
79+ DrawCircle {
80+ position,
81+ normal,
82+ radius,
83+ color,
84+ segments : CIRCLE_SEGMENTS ,
85+ }
7486 }
7587
7688 /// Draw a sphere.
7789 #[ inline]
78- pub fn sphere ( & self , position : Vec3 , radius : f32 , color : Color ) {
79- self . circle ( position, Vec3 :: X , radius, color) ;
80- self . circle ( position, Vec3 :: Y , radius, color) ;
81- self . circle ( position, Vec3 :: Z , radius, color) ;
90+ pub fn sphere ( & self , position : Vec3 , radius : f32 , color : Color ) -> DrawSphere {
91+ DrawSphere {
92+ position,
93+ radius,
94+ color,
95+ circle_segments : CIRCLE_SEGMENTS ,
96+ }
8297 }
8398
8499 /// Draw a rectangle.
85100 #[ inline]
86101 pub fn rect ( & self , position : Vec3 , rotation : Quat , size : Vec2 , color : Color ) {
87- let [ tl, tr, br, bl] = self
88- . rect_inner ( size)
89- . map ( |vec2| position + rotation * vec2. extend ( 0. ) ) ;
102+ let [ tl, tr, br, bl] = rect_inner ( size) . map ( |vec2| position + rotation * vec2. extend ( 0. ) ) ;
90103 self . linestrip ( [ tl, tr, br, bl, tl] , color) ;
91104 }
92105
93106 /// Draw a box.
94107 #[ inline]
95108 pub fn cuboid ( & self , position : Vec3 , rotation : Quat , size : Vec3 , color : Color ) {
96- let rect = self . rect_inner ( size. truncate ( ) ) ;
109+ let rect = rect_inner ( size. truncate ( ) ) ;
97110 // Front
98111 let [ tlf, trf, brf, blf] = rect. map ( |vec2| position + rotation * vec2. extend ( size. z / 2. ) ) ;
99112 // Back
@@ -147,50 +160,104 @@ impl GizmoDraw {
147160
148161 // Draw a circle.
149162 #[ inline]
150- pub fn circle_2d ( & self , position : Vec2 , radius : f32 , color : Color ) {
151- let positions = self . circle_inner ( radius) . map ( |vec2| ( vec2 + position) ) ;
152- self . linestrip_2d ( positions, color) ;
163+ pub fn circle_2d ( & self , position : Vec2 , radius : f32 , color : Color ) -> DrawCircle2d {
164+ DrawCircle2d {
165+ position,
166+ radius,
167+ color,
168+ segments : CIRCLE_SEGMENTS ,
169+ }
153170 }
154171
155172 /// Draw a rectangle.
156173 #[ inline]
157174 pub fn rect_2d ( & self , position : Vec2 , rotation : f32 , size : Vec2 , color : Color ) {
158175 let rotation = Mat2 :: from_angle ( rotation) ;
159- let [ tl, tr, br, bl] = self . rect_inner ( size) . map ( |vec2| position + rotation * vec2) ;
176+ let [ tl, tr, br, bl] = rect_inner ( size) . map ( |vec2| position + rotation * vec2) ;
160177 self . linestrip_2d ( [ tl, tr, br, bl, tl] , color) ;
161178 }
179+ }
180+
181+ pub struct DrawCircle {
182+ position : Vec3 ,
183+ normal : Vec3 ,
184+ radius : f32 ,
185+ color : Color ,
186+ segments : usize ,
187+ }
188+
189+ impl DrawCircle {
190+ pub fn segments ( mut self , segments : usize ) -> Self {
191+ self . segments = segments;
192+ self
193+ }
194+ }
195+
196+ impl Drop for DrawCircle {
197+ fn drop ( & mut self ) {
198+ let rotation = Quat :: from_rotation_arc ( Vec3 :: Z , self . normal ) ;
199+ let positions = circle_inner ( self . radius , self . segments )
200+ . map ( |vec2| ( self . position + rotation * vec2. extend ( 0. ) ) ) ;
201+ GIZMO . linestrip ( positions, self . color ) ;
202+ }
203+ }
204+ pub struct DrawCircle2d {
205+ position : Vec2 ,
206+ radius : f32 ,
207+ color : Color ,
208+ segments : usize ,
209+ }
162210
163- fn circle_inner ( & self , radius : f32 ) -> impl Iterator < Item = Vec2 > {
164- let circle_segments = self . circle_segments ;
165- ( 0 ..( circle_segments + 1 ) ) . into_iter ( ) . map ( move |i| {
166- let angle = i as f32 * TAU / circle_segments as f32 ;
167- Vec2 :: from ( angle. sin_cos ( ) ) * radius
168- } )
211+ impl DrawCircle2d {
212+ pub fn segments ( mut self , segments : usize ) -> Self {
213+ self . segments = segments;
214+ self
169215 }
216+ }
170217
171- fn rect_inner ( & self , size : Vec2 ) -> [ Vec2 ; 4 ] {
172- let half_size = size / 2. ;
173- let tl = Vec2 :: new ( -half_size. x , half_size. y ) ;
174- let tr = Vec2 :: new ( half_size. x , half_size. y ) ;
175- let bl = Vec2 :: new ( -half_size. x , -half_size. y ) ;
176- let br = Vec2 :: new ( half_size. x , -half_size. y ) ;
177- [ tl, tr, br, bl]
218+ impl Drop for DrawCircle2d {
219+ fn drop ( & mut self ) {
220+ let positions = circle_inner ( self . radius , self . segments ) . map ( |vec2| ( vec2 + self . position ) ) ;
221+ GIZMO . linestrip_2d ( positions, self . color ) ;
178222 }
223+ }
179224
180- #[ inline]
181- fn send_line ( & self , [ p0, p1] : [ Vec3 ; 2 ] , [ c0, c1] : [ Color ; 2 ] ) {
182- let _ = self . sender . send ( SendItem :: Single ( (
183- [ p0. to_array ( ) , p1. to_array ( ) ] ,
184- [ c0. as_linear_rgba_f32 ( ) , c1. as_linear_rgba_f32 ( ) ] ,
185- ) ) ) ;
225+ pub struct DrawSphere {
226+ position : Vec3 ,
227+ radius : f32 ,
228+ color : Color ,
229+ circle_segments : usize ,
230+ }
231+
232+ impl DrawSphere {
233+ pub fn circle_segments ( mut self , segments : usize ) -> Self {
234+ self . circle_segments = segments;
235+ self
186236 }
237+ }
187238
188- # [ inline ]
189- fn linelist ( & self , list : impl IntoIterator < Item = Vec3 > , color : Color ) {
190- let iter = list
191- . into_iter ( )
192- . map ( |p| p . to_array ( ) )
193- . zip ( iter :: repeat ( color . as_linear_rgba_f32 ( ) ) ) ;
194- let _ = self . sender . send ( SendItem :: List ( iter . unzip ( ) ) ) ;
239+ impl Drop for DrawSphere {
240+ fn drop ( & mut self ) {
241+ for axis in Vec3 :: AXES {
242+ GIZMO
243+ . circle ( self . position , axis , self . radius , self . color )
244+ . segments ( self . circle_segments ) ;
245+ }
195246 }
196247}
248+
249+ fn circle_inner ( radius : f32 , segments : usize ) -> impl Iterator < Item = Vec2 > {
250+ ( 0 ..segments + 1 ) . into_iter ( ) . map ( move |i| {
251+ let angle = i as f32 * TAU / segments as f32 ;
252+ Vec2 :: from ( angle. sin_cos ( ) ) * radius
253+ } )
254+ }
255+
256+ fn rect_inner ( size : Vec2 ) -> [ Vec2 ; 4 ] {
257+ let half_size = size / 2. ;
258+ let tl = Vec2 :: new ( -half_size. x , half_size. y ) ;
259+ let tr = Vec2 :: new ( half_size. x , half_size. y ) ;
260+ let bl = Vec2 :: new ( -half_size. x , -half_size. y ) ;
261+ let br = Vec2 :: new ( half_size. x , -half_size. y ) ;
262+ [ tl, tr, br, bl]
263+ }
0 commit comments