rust_raylib/
drawing.rs

1use crate::{
2    color::Color,
3    ffi,
4    math::{BoundingBox, Camera, Camera2D, Camera3D, Matrix, Ray, Rectangle, Vector2, Vector3},
5    model::{Material, Mesh, Model},
6    shader::Shader,
7    text::Font,
8    texture::{NPatchInfo, RenderTexture2D, Texture, Texture2D},
9    vr::VrStereoConfig,
10    Raylib,
11};
12
13use std::{
14    ffi::CString,
15    ops::{Deref, Range},
16};
17
18pub use crate::ffi::BlendMode;
19
20/// A struct containing the info for drawing textures.
21#[derive(Clone, Debug)]
22pub struct DrawTextureParams {
23    /// Part of texture to draw. If None - draw the whole texture.
24    /// Default: None
25    pub source: Option<Rectangle>,
26    /// Default: (1.0, 1.0)
27    pub scale: Vector2,
28    /// Rotate around this point.
29    /// Default: (0, 0)
30    pub origin: Vector2,
31    /// Default: 0.0
32    pub rotation: f32,
33    /// Default: white.
34    pub tint: Color,
35}
36
37impl Default for DrawTextureParams {
38    #[inline]
39    fn default() -> Self {
40        Self {
41            source: None,
42            scale: Vector2 { x: 1., y: 1. },
43            origin: Vector2 { x: 0., y: 0. },
44            rotation: 0.,
45            tint: Color::WHITE,
46        }
47    }
48}
49
50/// A struct containing the info for drawing billboard textures.
51#[derive(Clone, Debug)]
52pub struct DrawBillboardParams {
53    /// Part of texture to draw. If None - draw the whole texture.
54    /// Default: None
55    pub source: Option<Rectangle>,
56    /// Default: (0, 1, 0) - Y axis
57    pub up: Vector3,
58    /// Rotate the texture around this point.
59    /// Default: (0, 0)
60    pub origin: Vector2,
61    /// Default: 0.0
62    pub rotation: f32,
63    /// Default: white.
64    pub tint: Color,
65}
66
67impl Default for DrawBillboardParams {
68    #[inline]
69    fn default() -> Self {
70        Self {
71            source: None,
72            up: Vector3 {
73                x: 0.,
74                y: 1.,
75                z: 0.,
76            },
77            origin: Vector2 { x: 0., y: 0. },
78            rotation: 0.,
79            tint: Color::WHITE,
80        }
81    }
82}
83
84/// An object that handles drawing
85pub struct DrawHandle<'a>(pub(crate) &'a mut Raylib);
86
87impl<'a> DrawHandle<'a> {
88    /// End canvas drawing and swap buffers (double buffering)
89    #[inline]
90    pub fn end_drawing(self) {
91        drop(self)
92    }
93}
94
95impl<'a> Deref for DrawHandle<'a> {
96    type Target = Raylib;
97
98    fn deref(&self) -> &Self::Target {
99        self.0
100    }
101}
102
103impl<'a> Drop for DrawHandle<'a> {
104    #[inline]
105    fn drop(&mut self) {
106        unsafe { ffi::EndDrawing() }
107    }
108}
109
110/// An object that handles drawing with a custom 2D camera
111pub struct DrawMode2D<'a, T>(&'a mut T);
112
113impl<'a, T> DrawMode2D<'a, T> {
114    /// Ends 2D mode with custom camera
115    #[inline]
116    pub fn end_mode_2d(self) {
117        drop(self)
118    }
119}
120
121impl<'a, T> Deref for DrawMode2D<'a, T> {
122    type Target = T;
123
124    #[inline]
125    fn deref(&self) -> &Self::Target {
126        self.0
127    }
128}
129
130impl<'a, T> Drop for DrawMode2D<'a, T> {
131    #[inline]
132    fn drop(&mut self) {
133        unsafe { ffi::EndMode2D() }
134    }
135}
136
137/// An object that handles drawing with a custom 3D camera
138pub struct DrawMode3D<'a, T>(&'a mut T);
139
140impl<'a, T> DrawMode3D<'a, T> {
141    /// Ends 3D mode and returns to default 2D orthographic mode
142    #[inline]
143    pub fn end_mode_3d(self) {
144        drop(self)
145    }
146}
147
148impl<'a, T> Deref for DrawMode3D<'a, T> {
149    type Target = T;
150
151    #[inline]
152    fn deref(&self) -> &Self::Target {
153        self.0
154    }
155}
156
157impl<'a, T> Drop for DrawMode3D<'a, T> {
158    #[inline]
159    fn drop(&mut self) {
160        unsafe { ffi::EndMode3D() }
161    }
162}
163
164/// An object that handles drawing onto a `RenderTexture`
165pub struct DrawTextureMode<'a, T>(&'a mut T);
166
167impl<'a, T> DrawTextureMode<'a, T> {
168    /// Ends drawing to render texture
169    #[inline]
170    pub fn end_texture_mode(self) {
171        drop(self)
172    }
173}
174
175impl<'a, T> Deref for DrawTextureMode<'a, T> {
176    type Target = T;
177
178    #[inline]
179    fn deref(&self) -> &Self::Target {
180        self.0
181    }
182}
183
184impl<'a, T> Drop for DrawTextureMode<'a, T> {
185    #[inline]
186    fn drop(&mut self) {
187        unsafe { ffi::EndTextureMode() }
188    }
189}
190
191/// An object that handles drawing with a custom shader
192pub struct DrawShaderMode<'a, T>(&'a mut T);
193
194impl<'a, T> DrawShaderMode<'a, T> {
195    /// End custom shader drawing (use default shader)
196    #[inline]
197    pub fn end_shader_mode(self) {
198        drop(self)
199    }
200}
201
202impl<'a, T> Deref for DrawShaderMode<'a, T> {
203    type Target = T;
204
205    #[inline]
206    fn deref(&self) -> &Self::Target {
207        self.0
208    }
209}
210
211impl<'a, T> Drop for DrawShaderMode<'a, T> {
212    #[inline]
213    fn drop(&mut self) {
214        unsafe { ffi::EndShaderMode() }
215    }
216}
217
218/// An object that handles drawing with a custom blend mode
219pub struct DrawBlendMode<'a, T>(&'a mut T);
220
221impl<'a, T> DrawTextureMode<'a, T> {
222    /// End blending mode (reset to default: alpha blending)
223    #[inline]
224    pub fn end_blend_mode(self) {
225        drop(self)
226    }
227}
228
229impl<'a, T> Deref for DrawBlendMode<'a, T> {
230    type Target = T;
231
232    #[inline]
233    fn deref(&self) -> &Self::Target {
234        self.0
235    }
236}
237
238impl<'a, T> Drop for DrawBlendMode<'a, T> {
239    #[inline]
240    fn drop(&mut self) {
241        unsafe { ffi::EndBlendMode() }
242    }
243}
244
245/// An object that handles drawing within a screen area
246pub struct DrawScissorMode<'a, T>(&'a mut T);
247
248impl<'a, T> DrawScissorMode<'a, T> {
249    /// End scissor mode
250    #[inline]
251    pub fn end_scissor_mode(self) {
252        drop(self)
253    }
254}
255
256impl<'a, T> Deref for DrawScissorMode<'a, T> {
257    type Target = T;
258
259    #[inline]
260    fn deref(&self) -> &Self::Target {
261        self.0
262    }
263}
264
265impl<'a, T> Drop for DrawScissorMode<'a, T> {
266    #[inline]
267    fn drop(&mut self) {
268        unsafe { ffi::EndScissorMode() }
269    }
270}
271
272/// An object that handles stereo drawing (VR)
273pub struct DrawVrStereoMode<'a, T>(&'a mut T);
274
275impl<'a, T> DrawVrStereoMode<'a, T> {
276    /// End stereo rendering (requires VR simulator)
277    #[inline]
278    pub fn end_vr_stereo_mode(self) {
279        drop(self)
280    }
281}
282
283impl<'a, T> Deref for DrawVrStereoMode<'a, T> {
284    type Target = T;
285
286    #[inline]
287    fn deref(&self) -> &Self::Target {
288        self.0
289    }
290}
291
292impl<'a, T> Drop for DrawVrStereoMode<'a, T> {
293    #[inline]
294    fn drop(&mut self) {
295        unsafe { ffi::EndVrStereoMode() }
296    }
297}
298
299/// A trait that contains all the drawing functions
300pub trait Draw
301where
302    Self: Sized,
303{
304    /// Set background color (framebuffer clear color)
305    #[inline]
306    fn clear_background(&mut self, color: Color) {
307        unsafe { ffi::ClearBackground(color.into()) }
308    }
309
310    /// Begin 2D mode with custom camera (2D)
311    #[inline]
312    fn begin_mode_2d(&mut self, camera: Camera2D) -> DrawMode2D<Self> {
313        unsafe {
314            ffi::BeginMode2D(camera.into());
315        }
316
317        DrawMode2D(self)
318    }
319
320    /// Begin 3D mode with custom camera (3D)
321    #[inline]
322    fn begin_mode_3d(&mut self, camera: Camera3D) -> DrawMode3D<Self> {
323        unsafe {
324            ffi::BeginMode3D(camera.into());
325        }
326
327        DrawMode3D(self)
328    }
329
330    /// Begin drawing to render texture
331    #[inline]
332    fn begin_texture_mode(&mut self, target: &RenderTexture2D) -> DrawTextureMode<Self> {
333        unsafe {
334            ffi::BeginTextureMode(target.raw.clone());
335        }
336
337        DrawTextureMode(self)
338    }
339
340    /// Begin custom shader drawing
341    #[inline]
342    fn begin_shader_mode(&mut self, shader: &Shader) -> DrawShaderMode<Self> {
343        unsafe {
344            ffi::BeginShaderMode(shader.raw.clone());
345        }
346
347        DrawShaderMode(self)
348    }
349
350    /// Begin blending mode (alpha, additive, multiplied, subtract, custom)
351    #[inline]
352    fn begin_blend_mode(&mut self, mode: BlendMode) -> DrawBlendMode<Self> {
353        unsafe {
354            ffi::BeginBlendMode(mode as _);
355        }
356
357        DrawBlendMode(self)
358    }
359
360    /// Begin scissor mode (define screen area for following drawing)
361    #[inline]
362    fn begin_scissor_mode(
363        &mut self,
364        x: u32,
365        y: u32,
366        width: u32,
367        height: u32,
368    ) -> DrawScissorMode<Self> {
369        unsafe {
370            ffi::BeginScissorMode(x as _, y as _, width as _, height as _);
371        }
372
373        DrawScissorMode(self)
374    }
375
376    /// Begin stereo rendering (requires VR simulator)
377    #[inline]
378    fn begin_vr_stereo_mode(&mut self, config: VrStereoConfig) -> DrawVrStereoMode<Self> {
379        unsafe {
380            ffi::BeginVrStereoMode(config.into());
381        }
382
383        DrawVrStereoMode(self)
384    }
385
386    /// Draw a part of a texture defined by source and destination rectangles
387    #[inline]
388    fn draw_texture(&mut self, tex: &Texture, position: Vector2, params: DrawTextureParams) {
389        // rectangle checks?
390        let source =
391            params
392                .source
393                .unwrap_or(Rectangle::new(0., 0., tex.width() as _, tex.height() as _));
394
395        unsafe {
396            ffi::DrawTexturePro(
397                tex.raw.clone(),
398                source.into(),
399                Rectangle::new(
400                    position.x,
401                    position.y,
402                    params.scale.x * source.width,
403                    params.scale.y * source.height,
404                )
405                .into(),
406                params.origin.into(),
407                params.rotation,
408                params.tint.into(),
409            )
410        }
411    }
412
413    /// Draws a texture (or part of it) that stretches or shrinks nicely
414    #[inline]
415    fn draw_texture_patch(
416        &mut self,
417        tex: &Texture,
418        position: Vector2,
419        params: DrawTextureParams,
420        patch_info: NPatchInfo,
421    ) {
422        let source = patch_info.source;
423
424        unsafe {
425            ffi::DrawTextureNPatch(
426                tex.raw.clone(),
427                patch_info.into(),
428                Rectangle::new(
429                    position.x,
430                    position.y,
431                    params.scale.x * source.width,
432                    params.scale.y * source.height,
433                )
434                .into(),
435                params.origin.into(),
436                params.rotation,
437                params.tint.into(),
438            )
439        }
440    }
441
442    /// Set texture and rectangle to be used on shapes drawing
443    #[inline]
444    fn set_shapes_texture(&mut self, texture: &Texture, source: Rectangle) {
445        unsafe { ffi::SetShapesTexture(texture.raw.clone(), source.into()) }
446    }
447
448    /// Draw a pixel
449    #[inline]
450    fn draw_pixel(&mut self, position: Vector2, color: Color) {
451        unsafe { ffi::DrawPixelV(position.into(), color.into()) }
452    }
453
454    /// Draw a line
455    #[inline]
456    fn draw_line(&mut self, start: Vector2, end: Vector2, color: Color) {
457        unsafe { ffi::DrawLineV(start.into(), end.into(), color.into()) }
458    }
459
460    /// Draw a line defining thickness
461    #[inline]
462    fn draw_line_thick(&mut self, start: Vector2, end: Vector2, thickness: f32, color: Color) {
463        unsafe { ffi::DrawLineEx(start.into(), end.into(), thickness, color.into()) }
464    }
465
466    /// Draw a line using cubic-bezier curves in-out
467    #[inline]
468    fn draw_line_bezier(&mut self, start: Vector2, end: Vector2, thickness: f32, color: Color) {
469        unsafe { ffi::DrawLineBezier(start.into(), end.into(), thickness, color.into()) }
470    }
471
472    /// Draw line using quadratic bezier curves with a control point
473    #[inline]
474    fn draw_line_bezier_quad(
475        &mut self,
476        start: Vector2,
477        end: Vector2,
478        control_pos: Vector2,
479        thickness: f32,
480        color: Color,
481    ) {
482        unsafe {
483            ffi::DrawLineBezierQuad(
484                start.into(),
485                end.into(),
486                control_pos.into(),
487                thickness,
488                color.into(),
489            )
490        }
491    }
492
493    /// Draw line using cubic bezier curves with 2 control points
494    #[inline]
495    fn draw_line_bezier_cubic(
496        &mut self,
497        start: Vector2,
498        end: Vector2,
499        start_control_pos: Vector2,
500        end_control_pos: Vector2,
501        thickness: f32,
502        color: Color,
503    ) {
504        unsafe {
505            ffi::DrawLineBezierCubic(
506                start.into(),
507                end.into(),
508                start_control_pos.into(),
509                end_control_pos.into(),
510                thickness,
511                color.into(),
512            )
513        }
514    }
515
516    /// Draw lines sequence
517    #[inline]
518    fn draw_line_strip(&mut self, points: &[Vector2], color: Color) {
519        unsafe { ffi::DrawLineStrip(points.as_ptr() as *mut _, points.len() as _, color.into()) }
520    }
521
522    /// Draw a color-filled circle
523    #[inline]
524    fn draw_circle(&mut self, center: Vector2, radius: f32, color: Color) {
525        unsafe { ffi::DrawCircleV(center.into(), radius, color.into()) }
526    }
527
528    /// Draw circle outline
529    #[inline]
530    fn draw_circle_lines(&mut self, center_x: i32, center_y: i32, radius: f32, color: Color) {
531        unsafe { ffi::DrawCircleLines(center_x, center_y, radius, color.into()) }
532    }
533
534    /// Draw ellipse
535    #[inline]
536    fn draw_ellipse(&mut self, center: Vector2, radius: Vector2, color: Color) {
537        unsafe {
538            ffi::DrawEllipse(
539                center.x as _,
540                center.y as _,
541                radius.x as _,
542                radius.y as _,
543                color.into(),
544            )
545        }
546    }
547
548    /// Draw ellipse outline
549    #[inline]
550    fn draw_ellipse_lines(&mut self, center: Vector2, radius: Vector2, color: Color) {
551        unsafe {
552            ffi::DrawEllipseLines(
553                center.x as _,
554                center.y as _,
555                radius.x as _,
556                radius.y as _,
557                color.into(),
558            )
559        }
560    }
561
562    /// Draw a piece of a circle
563    #[inline]
564    fn draw_circle_sector(
565        &mut self,
566        center: Vector2,
567        radius: f32,
568        angle: Range<f32>,
569        segments: u32,
570        color: Color,
571    ) {
572        unsafe {
573            ffi::DrawCircleSector(
574                center.into(),
575                radius,
576                angle.start,
577                angle.end,
578                segments as _,
579                color.into(),
580            )
581        }
582    }
583
584    /// Draw circle sector outline
585    #[inline]
586    fn draw_circle_sector_lines(
587        &mut self,
588        center: Vector2,
589        radius: f32,
590        angle: Range<f32>,
591        segments: u32,
592        color: Color,
593    ) {
594        unsafe {
595            ffi::DrawCircleSectorLines(
596                center.into(),
597                radius,
598                angle.start,
599                angle.end,
600                segments as _,
601                color.into(),
602            )
603        }
604    }
605
606    /// Draw a gradient-filled circle
607    #[inline]
608    fn draw_circle_gradient(&mut self, center: Vector2, radius: f32, color1: Color, color2: Color) {
609        unsafe {
610            ffi::DrawCircleGradient(
611                center.x as _,
612                center.y as _,
613                radius,
614                color1.into(),
615                color2.into(),
616            )
617        }
618    }
619
620    /// Draw ring
621    #[inline]
622    #[allow(clippy::too_many_arguments)]
623    fn draw_ring(
624        &mut self,
625        center: Vector2,
626        inner_radius: f32,
627        outer_radius: f32,
628        start_angle: f32,
629        end_angle: f32,
630        segments: u32,
631        color: Color,
632    ) {
633        unsafe {
634            ffi::DrawRing(
635                center.into(),
636                inner_radius,
637                outer_radius,
638                start_angle,
639                end_angle,
640                segments as _,
641                color.into(),
642            )
643        }
644    }
645
646    /// Draw ring outline
647    #[inline]
648    fn draw_ring_lines(
649        &mut self,
650        center: Vector2,
651        radius: Range<f32>,
652        angle: Range<f32>,
653        segments: u32,
654        color: Color,
655    ) {
656        unsafe {
657            ffi::DrawRingLines(
658                center.into(),
659                radius.start,
660                radius.end,
661                angle.start,
662                angle.end,
663                segments as _,
664                color.into(),
665            )
666        }
667    }
668
669    /// Draw a color-filled rectangle
670    #[inline]
671    fn draw_rectangle(&mut self, rect: Rectangle, color: Color) {
672        unsafe { ffi::DrawRectangleRec(rect.into(), color.into()) }
673    }
674
675    /// Draw rectangle outline
676    #[inline]
677    fn draw_rectangle_lines(&mut self, rect: Rectangle, color: Color) {
678        unsafe {
679            ffi::DrawRectangleLines(
680                rect.x as _,
681                rect.y as _,
682                rect.width as _,
683                rect.height as _,
684                color.into(),
685            )
686        }
687    }
688
689    /// Draw rectangle outline with thickness
690    #[inline]
691    fn draw_rectangle_lines_thick(&mut self, rect: Rectangle, line_thickness: f32, color: Color) {
692        unsafe { ffi::DrawRectangleLinesEx(rect.into(), line_thickness, color.into()) }
693    }
694
695    /// Draw a color-filled rotated
696    #[inline]
697    fn draw_rectangle_rotated(
698        &mut self,
699        rect: Rectangle,
700        origin: Vector2,
701        rotation: f32,
702        color: Color,
703    ) {
704        unsafe { ffi::DrawRectanglePro(rect.into(), origin.into(), rotation, color.into()) }
705    }
706
707    /// Draw a vertical-gradient-filled rectangle
708    #[inline]
709    fn draw_rectangle_gradient_vertical(&mut self, rect: Rectangle, color1: Color, color2: Color) {
710        unsafe {
711            ffi::DrawRectangleGradientV(
712                rect.x as _,
713                rect.y as _,
714                rect.width as _,
715                rect.height as _,
716                color1.into(),
717                color2.into(),
718            )
719        }
720    }
721
722    /// Draw a horizontal-gradient-filled rectangle
723    #[inline]
724    fn draw_rectangle_gradient_horizontal(
725        &mut self,
726        rect: Rectangle,
727        color1: Color,
728        color2: Color,
729    ) {
730        unsafe {
731            ffi::DrawRectangleGradientH(
732                rect.x as _,
733                rect.y as _,
734                rect.width as _,
735                rect.height as _,
736                color1.into(),
737                color2.into(),
738            )
739        }
740    }
741
742    /// Draw a gradient-filled rectangle with custom vertex colors
743    #[inline]
744    fn draw_rectangle_gradient(
745        &mut self,
746        rect: Rectangle,
747        col1: Color,
748        col2: Color,
749        col3: Color,
750        col4: Color,
751    ) {
752        unsafe {
753            ffi::DrawRectangleGradientEx(
754                rect.into(),
755                col1.into(),
756                col2.into(),
757                col3.into(),
758                col4.into(),
759            )
760        }
761    }
762
763    /// Draw rectangle with rounded edges
764    #[inline]
765    fn draw_rectangle_rounded(
766        &mut self,
767        rect: Rectangle,
768        roundness: f32,
769        segments: u32,
770        color: Color,
771    ) {
772        unsafe { ffi::DrawRectangleRounded(rect.into(), roundness, segments as _, color.into()) }
773    }
774
775    /// Draw rectangle with rounded edges outline
776    #[inline]
777    fn draw_rectangle_rounded_lines(
778        &mut self,
779        rect: Rectangle,
780        roundness: f32,
781        segments: u32,
782        line_thickness: f32,
783        color: Color,
784    ) {
785        unsafe {
786            ffi::DrawRectangleRoundedLines(
787                rect.into(),
788                roundness,
789                segments as _,
790                line_thickness,
791                color.into(),
792            )
793        }
794    }
795
796    /// Draw a color-filled triangle (vertex in counter-clockwise order!)
797    #[inline]
798    fn draw_triangle(&mut self, v1: Vector2, v2: Vector2, v3: Vector2, color: Color) {
799        unsafe { ffi::DrawTriangle(v1.into(), v2.into(), v3.into(), color.into()) }
800    }
801
802    /// Draw triangle outline (vertex in counter-clockwise order!)
803    #[inline]
804    fn draw_triangle_lines(&mut self, v1: Vector2, v2: Vector2, v3: Vector2, color: Color) {
805        unsafe { ffi::DrawTriangleLines(v1.into(), v2.into(), v3.into(), color.into()) }
806    }
807
808    /// Draw a triangle fan defined by points (first vertex is the center)
809    #[inline]
810    fn draw_triangle_fan(&mut self, points: &[Vector2], color: Color) {
811        unsafe { ffi::DrawTriangleFan(points.as_ptr() as *mut _, points.len() as _, color.into()) }
812    }
813
814    /// Draw a triangle strip defined by points
815    #[inline]
816    fn draw_triangle_strip(&mut self, points: &[Vector2], color: Color) {
817        unsafe {
818            ffi::DrawTriangleStrip(points.as_ptr() as *mut _, points.len() as _, color.into())
819        }
820    }
821
822    /// Draw a regular polygon (Vector version)
823    #[inline]
824    fn draw_polygon(
825        &mut self,
826        center: Vector2,
827        sides: u32,
828        radius: f32,
829        rotation: f32,
830        color: Color,
831    ) {
832        unsafe { ffi::DrawPoly(center.into(), sides as _, radius, rotation, color.into()) }
833    }
834
835    /// Draw a polygon outline of n sides
836    #[inline]
837    fn draw_polygon_lines(
838        &mut self,
839        center: Vector2,
840        sides: u32,
841        radius: f32,
842        rotation: f32,
843        color: Color,
844    ) {
845        unsafe { ffi::DrawPolyLines(center.into(), sides as _, radius, rotation, color.into()) }
846    }
847
848    /// Draw a polygon outline of n sides with thickness
849    #[inline]
850    fn draw_polygon_lines_thick(
851        &mut self,
852        center: Vector2,
853        sides: u32,
854        radius: f32,
855        rotation: f32,
856        line_thickness: f32,
857        color: Color,
858    ) {
859        unsafe {
860            ffi::DrawPolyLinesEx(
861                center.into(),
862                sides as _,
863                radius,
864                rotation,
865                line_thickness,
866                color.into(),
867            )
868        }
869    }
870
871    /// Draw current FPS
872    #[inline]
873    fn draw_fps(&mut self, position: Vector2) {
874        unsafe { ffi::DrawFPS(position.x as _, position.y as _) }
875    }
876
877    /// Draw text (using default font)
878    #[inline]
879    fn draw_text(&mut self, text: &str, position: Vector2, font_size: u32, color: Color) {
880        let text = CString::new(text).unwrap();
881
882        unsafe {
883            ffi::DrawText(
884                text.as_ptr(),
885                position.x as _,
886                position.y as _,
887                font_size as _,
888                color.into(),
889            )
890        }
891    }
892
893    /// Draw text using font and additional parameters
894    #[inline]
895    fn draw_text_with_font(
896        &mut self,
897        text: &str,
898        pos: Vector2,
899        font: &Font,
900        font_size: f32,
901        spacing: f32,
902        tint: Color,
903    ) {
904        let text = CString::new(text).unwrap();
905
906        unsafe {
907            ffi::DrawTextEx(
908                font.raw.clone(),
909                text.as_ptr(),
910                pos.into(),
911                font_size,
912                spacing,
913                tint.into(),
914            )
915        }
916    }
917
918    /// Draw text using Font and pro parameters (rotation)
919    #[inline]
920    #[allow(clippy::too_many_arguments)]
921    fn draw_text_with_font_and_rotation(
922        &mut self,
923        text: &str,
924        pos: Vector2,
925        origin: Vector2,
926        rotation: f32,
927        font: &Font,
928        font_size: f32,
929        spacing: f32,
930        tint: Color,
931    ) {
932        let text = CString::new(text).unwrap();
933
934        unsafe {
935            ffi::DrawTextPro(
936                font.raw.clone(),
937                text.as_ptr(),
938                pos.into(),
939                origin.into(),
940                rotation,
941                font_size,
942                spacing,
943                tint.into(),
944            )
945        }
946    }
947
948    /// Draw one character
949    #[inline]
950    fn draw_char(&mut self, ch: char, pos: Vector2, font: &Font, font_size: f32, tint: Color) {
951        unsafe {
952            ffi::DrawTextCodepoint(
953                font.raw.clone(),
954                ch as _,
955                pos.into(),
956                font_size,
957                tint.into(),
958            )
959        }
960    }
961
962    /// Draw multiple characters
963    #[inline]
964    fn draw_chars(
965        &mut self,
966        chars: &[char],
967        pos: Vector2,
968        font: &Font,
969        font_size: f32,
970        spacing: f32,
971        tint: Color,
972    ) {
973        unsafe {
974            ffi::DrawTextCodepoints(
975                font.raw.clone(),
976                chars.as_ptr() as *const _,
977                chars.len() as _,
978                pos.into(),
979                font_size,
980                spacing,
981                tint.into(),
982            )
983        }
984    }
985
986    /// Draw a line in 3D world space
987    #[inline]
988    fn draw_line_3d(&mut self, start_pos: Vector3, end_pos: Vector3, color: Color) {
989        unsafe { ffi::DrawLine3D(start_pos.into(), end_pos.into(), color.into()) }
990    }
991
992    /// Draw a point in 3D space, actually a small line
993    #[inline]
994    fn draw_point_3d(&mut self, position: Vector3, color: Color) {
995        unsafe { ffi::DrawPoint3D(position.into(), color.into()) }
996    }
997
998    /// Draw a circle in 3D world space
999    #[inline]
1000    fn draw_circle_3d(
1001        &mut self,
1002        center: Vector3,
1003        radius: f32,
1004        rotation_axis: Vector3,
1005        rotation_angle: f32,
1006        color: Color,
1007    ) {
1008        unsafe {
1009            ffi::DrawCircle3D(
1010                center.into(),
1011                radius,
1012                rotation_axis.into(),
1013                rotation_angle,
1014                color.into(),
1015            )
1016        }
1017    }
1018
1019    /// Draw a color-filled triangle (vertex in counter-clockwise order!)
1020    #[inline]
1021    fn draw_triangle_3d(&mut self, v1: Vector3, v2: Vector3, v3: Vector3, color: Color) {
1022        unsafe { ffi::DrawTriangle3D(v1.into(), v2.into(), v3.into(), color.into()) }
1023    }
1024
1025    /// Draw a triangle strip defined by points
1026    #[inline]
1027    fn draw_triangle_strip_3d(&mut self, points: &[Vector3], color: Color) {
1028        unsafe {
1029            ffi::DrawTriangleStrip3D(points.as_ptr() as *mut _, points.len() as _, color.into())
1030        }
1031    }
1032
1033    /// Draw cube
1034    #[inline]
1035    fn draw_cube(&mut self, position: Vector3, size: Vector3, color: Color) {
1036        unsafe { ffi::DrawCubeV(position.into(), size.into(), color.into()) }
1037    }
1038
1039    /// Draw cube wires (Vector version)
1040    #[inline]
1041    fn draw_cube_wires(&mut self, position: Vector3, size: Vector3, color: Color) {
1042        unsafe { ffi::DrawCubeWiresV(position.into(), size.into(), color.into()) }
1043    }
1044
1045    /// Draw sphere
1046    #[inline]
1047    fn draw_sphere(&mut self, center_pos: Vector3, radius: f32, color: Color) {
1048        unsafe { ffi::DrawSphere(center_pos.into(), radius, color.into()) }
1049    }
1050
1051    /// Draw sphere with extended parameters
1052    #[inline]
1053    fn draw_sphere_ex(
1054        &mut self,
1055        center_pos: Vector3,
1056        radius: f32,
1057        rings: u32,
1058        slices: u32,
1059        color: Color,
1060    ) {
1061        unsafe {
1062            ffi::DrawSphereEx(
1063                center_pos.into(),
1064                radius,
1065                rings as _,
1066                slices as _,
1067                color.into(),
1068            )
1069        }
1070    }
1071
1072    /// Draw sphere wires
1073    #[inline]
1074    fn draw_sphere_wires(
1075        &mut self,
1076        center_pos: Vector3,
1077        radius: f32,
1078        rings: u32,
1079        slices: u32,
1080        color: Color,
1081    ) {
1082        unsafe {
1083            ffi::DrawSphereWires(
1084                center_pos.into(),
1085                radius,
1086                rings as _,
1087                slices as _,
1088                color.into(),
1089            )
1090        }
1091    }
1092
1093    /// Draw a cylinder/cone
1094    #[inline]
1095    fn draw_cylinder(
1096        &mut self,
1097        position: Vector3,
1098        radius_top: f32,
1099        radius_bottom: f32,
1100        height: f32,
1101        slices: u32,
1102        color: Color,
1103    ) {
1104        unsafe {
1105            ffi::DrawCylinder(
1106                position.into(),
1107                radius_top,
1108                radius_bottom,
1109                height,
1110                slices as _,
1111                color.into(),
1112            )
1113        }
1114    }
1115
1116    /// Draw a cylinder with extended parameters
1117    #[inline]
1118    fn draw_cylinder_ex(
1119        &mut self,
1120        pos_top: Vector3,
1121        pos_bottom: Vector3,
1122        radius_top: f32,
1123        radius_bottom: f32,
1124        sides: u32,
1125        color: Color,
1126    ) {
1127        unsafe {
1128            ffi::DrawCylinderEx(
1129                pos_bottom.into(),
1130                pos_top.into(),
1131                radius_bottom,
1132                radius_top,
1133                sides as _,
1134                color.into(),
1135            )
1136        }
1137    }
1138
1139    /// Draw a cylinder/cone wires
1140    #[inline]
1141    fn draw_cylinder_wires(
1142        &mut self,
1143        position: Vector3,
1144        radius_top: f32,
1145        radius_bottom: f32,
1146        height: f32,
1147        slices: u32,
1148        color: Color,
1149    ) {
1150        unsafe {
1151            ffi::DrawCylinderWires(
1152                position.into(),
1153                radius_top,
1154                radius_bottom,
1155                height,
1156                slices as _,
1157                color.into(),
1158            )
1159        }
1160    }
1161
1162    /// Draw a cylinder wires with extended parameters
1163    #[inline]
1164    fn draw_cylinder_wires_ex(
1165        &mut self,
1166        pos_top: Vector3,
1167        pos_bottom: Vector3,
1168        radius_top: f32,
1169        radius_bottom: f32,
1170        sides: u32,
1171        color: Color,
1172    ) {
1173        unsafe {
1174            ffi::DrawCylinderWiresEx(
1175                pos_bottom.into(),
1176                pos_top.into(),
1177                radius_bottom,
1178                radius_top,
1179                sides as _,
1180                color.into(),
1181            )
1182        }
1183    }
1184
1185    /// Draw a capsule with the center of its sphere caps at start_pos and end_pos
1186    #[inline]
1187    fn draw_capsule(
1188        &mut self,
1189        start_pos: Vector3,
1190        end_pos: Vector3,
1191        radius: f32,
1192        slices: u32,
1193        rings: u32,
1194        color: Color,
1195    ) {
1196        unsafe {
1197            ffi::DrawCapsule(
1198                start_pos.into(),
1199                end_pos.into(),
1200                radius,
1201                slices as _,
1202                rings as _,
1203                color.into(),
1204            )
1205        }
1206    }
1207
1208    /// Draw capsule wireframe with the center of its sphere caps at start_pos and end_pos
1209    #[inline]
1210    fn draw_capsule_wires(
1211        &mut self,
1212        start_pos: Vector3,
1213        end_pos: Vector3,
1214        radius: f32,
1215        slices: u32,
1216        rings: u32,
1217        color: Color,
1218    ) {
1219        unsafe {
1220            ffi::DrawCapsuleWires(
1221                start_pos.into(),
1222                end_pos.into(),
1223                radius,
1224                slices as _,
1225                rings as _,
1226                color.into(),
1227            )
1228        }
1229    }
1230
1231    /// Draw a plane XZ
1232    #[inline]
1233    fn draw_plane(&mut self, center_pos: Vector3, size: Vector2, color: Color) {
1234        unsafe { ffi::DrawPlane(center_pos.into(), size.into(), color.into()) }
1235    }
1236
1237    /// Draw a ray line
1238    #[inline]
1239    fn draw_ray(&mut self, ray: Ray, color: Color) {
1240        unsafe { ffi::DrawRay(ray.into(), color.into()) }
1241    }
1242
1243    /// Draw a grid (centered at (0, 0, 0))
1244    #[inline]
1245    fn draw_grid(&mut self, slices: u32, spacing: f32) {
1246        unsafe { ffi::DrawGrid(slices as _, spacing) }
1247    }
1248
1249    /// Draw a model (with texture if set)
1250    #[inline]
1251    fn draw_model(&mut self, model: &Model, position: Vector3, scale: f32, tint: Color) {
1252        unsafe { ffi::DrawModel(model.raw.clone(), position.into(), scale, tint.into()) }
1253    }
1254
1255    /// Draw a model with extended parameters
1256    #[inline]
1257    fn draw_model_ex(
1258        &mut self,
1259        model: &Model,
1260        position: Vector3,
1261        rotation_axis: Vector3,
1262        rotation_angle: f32,
1263        scale: Vector3,
1264        tint: Color,
1265    ) {
1266        unsafe {
1267            ffi::DrawModelEx(
1268                model.raw.clone(),
1269                position.into(),
1270                rotation_axis.into(),
1271                rotation_angle,
1272                scale.into(),
1273                tint.into(),
1274            )
1275        }
1276    }
1277
1278    /// Draw a model wires (with texture if set)
1279    #[inline]
1280    fn draw_model_wires(&mut self, model: &Model, position: Vector3, scale: f32, tint: Color) {
1281        unsafe { ffi::DrawModelWires(model.raw.clone(), position.into(), scale, tint.into()) }
1282    }
1283
1284    /// Draw a model wires (with texture if set) with extended parameters
1285    #[inline]
1286    fn draw_model_wires_ex(
1287        &mut self,
1288        model: &Model,
1289        position: Vector3,
1290        rotation_axis: Vector3,
1291        rotation_angle: f32,
1292        scale: Vector3,
1293        tint: Color,
1294    ) {
1295        unsafe {
1296            ffi::DrawModelWiresEx(
1297                model.raw.clone(),
1298                position.into(),
1299                rotation_axis.into(),
1300                rotation_angle,
1301                scale.into(),
1302                tint.into(),
1303            )
1304        }
1305    }
1306
1307    /// Draw bounding box (wires)
1308    #[inline]
1309    fn draw_bounding_box(&mut self, bbox: BoundingBox, color: Color) {
1310        unsafe { ffi::DrawBoundingBox(bbox.into(), color.into()) }
1311    }
1312
1313    /// Draw a billboard texture
1314    #[inline]
1315    fn draw_billboard(
1316        &mut self,
1317        camera: Camera,
1318        texture: &Texture2D,
1319        position: Vector3,
1320        size: Vector2,
1321        params: DrawBillboardParams,
1322    ) {
1323        unsafe {
1324            ffi::DrawBillboardPro(
1325                camera.into(),
1326                texture.raw.clone(),
1327                params
1328                    .source
1329                    .unwrap_or(Rectangle::new(
1330                        0.,
1331                        0.,
1332                        texture.width() as _,
1333                        texture.height() as _,
1334                    ))
1335                    .into(),
1336                position.into(),
1337                params.up.into(),
1338                size.into(),
1339                params.origin.into(),
1340                params.rotation,
1341                params.tint.into(),
1342            )
1343        }
1344    }
1345
1346    /// Draw a 3d mesh with material and transform
1347    #[inline]
1348    fn draw_mesh(&mut self, mesh: &Mesh, material: &Material, transform: Matrix) {
1349        unsafe { ffi::DrawMesh(mesh.raw.clone(), material.raw.clone(), transform.into()) }
1350    }
1351
1352    /// Draw multiple mesh instances with material and different transforms
1353    #[inline]
1354    fn draw_mesh_instanced(&mut self, mesh: &Mesh, material: &Material, transforms: &[Matrix]) {
1355        unsafe {
1356            ffi::DrawMeshInstanced(
1357                mesh.raw.clone(),
1358                material.raw.clone(),
1359                transforms.as_ptr() as *const _,
1360                transforms.len() as _,
1361            )
1362        }
1363    }
1364}
1365
1366impl<'a> Draw for DrawHandle<'a> {}
1367impl<'a, T> Draw for DrawBlendMode<'a, T> {}
1368impl<'a, T> Draw for DrawMode2D<'a, T> {}
1369impl<'a, T> Draw for DrawMode3D<'a, T> {}
1370impl<'a, T> Draw for DrawScissorMode<'a, T> {}
1371impl<'a, T> Draw for DrawShaderMode<'a, T> {}
1372impl<'a, T> Draw for DrawTextureMode<'a, T> {}
1373impl<'a, T> Draw for DrawVrStereoMode<'a, T> {}