@@ -4,36 +4,39 @@ use bevy_math::{Mat2, Quat, Vec2, Vec3};
4
4
use bevy_render:: prelude:: Color ;
5
5
use crossbeam_channel:: { unbounded, Receiver , Sender } ;
6
6
7
- use crate :: SendItem ;
7
+ use crate :: { SendItem , GIZMO } ;
8
8
9
9
pub struct GizmoDraw {
10
10
sender : Sender < SendItem > ,
11
11
pub ( crate ) receiver : Receiver < SendItem > ,
12
- circle_segments : usize ,
13
12
}
14
13
15
14
impl GizmoDraw {
16
15
pub ( crate ) fn new ( ) -> Self {
17
16
let ( sender, receiver) = unbounded ( ) ;
18
- GizmoDraw {
19
- sender,
20
- receiver,
21
- circle_segments : 32 ,
22
- }
17
+ GizmoDraw { sender, receiver }
23
18
}
24
19
}
25
20
21
+ const CIRCLE_SEGMENTS : usize = 32 ;
22
+
26
23
impl GizmoDraw {
27
24
/// Draw a line from `start` to `end`.
28
25
#[ inline]
29
26
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) ;
31
28
}
32
29
33
30
/// Draw a line from `start` to `end`.
34
31
#[ inline]
35
32
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
+ ) ) ) ;
37
40
}
38
41
39
42
/// Draw a line from `start` to `start + vector`.
@@ -61,39 +64,49 @@ impl GizmoDraw {
61
64
let _ = self . sender . send ( SendItem :: Strip ( iter. unzip ( ) ) ) ;
62
65
}
63
66
64
- /// Draw a circle at `position` with the flat side facing `normal`.
65
67
#[ 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
+ }
72
75
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
+ }
74
86
}
75
87
76
88
/// Draw a sphere.
77
89
#[ 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
+ }
82
97
}
83
98
84
99
/// Draw a rectangle.
85
100
#[ inline]
86
101
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. ) ) ;
90
103
self . linestrip ( [ tl, tr, br, bl, tl] , color) ;
91
104
}
92
105
93
106
/// Draw a box.
94
107
#[ inline]
95
108
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 ( ) ) ;
97
110
// Front
98
111
let [ tlf, trf, brf, blf] = rect. map ( |vec2| position + rotation * vec2. extend ( size. z / 2. ) ) ;
99
112
// Back
@@ -147,50 +160,104 @@ impl GizmoDraw {
147
160
148
161
// Draw a circle.
149
162
#[ 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
+ }
153
170
}
154
171
155
172
/// Draw a rectangle.
156
173
#[ inline]
157
174
pub fn rect_2d ( & self , position : Vec2 , rotation : f32 , size : Vec2 , color : Color ) {
158
175
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) ;
160
177
self . linestrip_2d ( [ tl, tr, br, bl, tl] , color) ;
161
178
}
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
+ }
162
210
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
169
215
}
216
+ }
170
217
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 ) ;
178
222
}
223
+ }
179
224
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
186
236
}
237
+ }
187
238
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
+ }
195
246
}
196
247
}
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