1use crate::{
2 color::Color,
3 core::Raylib,
4 ffi,
5 math::{Rectangle, Vector2},
6 text::Font,
7};
8
9use std::ffi::{CStr, CString};
10
11use static_assertions::{assert_eq_align, assert_eq_size};
12
13pub use crate::ffi::{CubemapLayout, NPatchLayout, PixelFormat, TextureFilter, TextureWrap};
14
15#[inline]
17pub fn get_pixel_data_size(width: u32, height: u32, format: PixelFormat) -> usize {
18 unsafe { ffi::GetPixelDataSize(width as _, height as _, format as _) as usize }
19}
20
21#[derive(Clone, Copy, Debug, PartialEq, Eq)]
23pub enum ImageFormat {
24 Png,
26 Bmp,
28 Tga,
30 Jpg,
32 Gif,
34 Pic,
36 Pnm,
38 Psd,
40 Hdr,
42 Qoi,
44 Dds,
46 Pkm,
48 Ktx,
50 Pvr,
52 Astc,
54}
55
56impl ImageFormat {
57 fn as_cstr(&self) -> &'static CStr {
58 use ImageFormat::*;
59
60 CStr::from_bytes_with_nul(match self {
61 Png => b".png\0",
62 Bmp => b".bmp\0",
63 Tga => b".tga\0",
64 Jpg => b".jpg\0",
65 Gif => b".gif\0",
66 Pic => b".pic\0",
67 Pnm => b".ppm\0",
68 Psd => b".psd\0",
69 Hdr => b".hdr\0",
70 Qoi => b".qoi\0",
71 Dds => b".dds\0",
72 Pkm => b".pkm\0",
73 Ktx => b".ktx\0",
74 Pvr => b".pvr\0",
75 Astc => b".astc\0",
76 })
77 .unwrap()
78 }
79}
80
81#[repr(C)]
83#[derive(Clone, Debug, PartialEq)]
84pub struct NPatchInfo {
85 pub source: Rectangle,
87 pub left: i32,
89 pub top: i32,
91 pub right: i32,
93 pub bottom: i32,
95 pub layout: NPatchLayout,
97}
98
99assert_eq_size!(NPatchInfo, ffi::NPatchInfo);
100assert_eq_align!(NPatchInfo, ffi::NPatchInfo);
101
102impl From<NPatchInfo> for ffi::NPatchInfo {
103 #[inline]
104 fn from(val: NPatchInfo) -> Self {
105 unsafe { std::mem::transmute(val) }
106 }
107}
108
109impl From<ffi::NPatchInfo> for NPatchInfo {
110 #[inline]
111 fn from(value: ffi::NPatchInfo) -> Self {
112 unsafe { std::mem::transmute(value) }
113 }
114}
115
116#[derive(Debug)]
118#[repr(transparent)]
119pub struct Image {
120 pub(crate) raw: ffi::Image,
121}
122
123impl Image {
124 #[inline]
126 pub fn width(&self) -> u32 {
127 self.raw.width as u32
128 }
129
130 #[inline]
132 pub fn height(&self) -> u32 {
133 self.raw.height as u32
134 }
135
136 #[inline]
138 pub fn mipmaps(&self) -> u32 {
139 self.raw.mipmaps as u32
140 }
141
142 #[inline]
144 pub fn format(&self) -> PixelFormat {
145 unsafe { std::mem::transmute(self.raw.format) }
146 }
147
148 #[inline]
150 pub fn from_file(file_name: &str) -> Option<Self> {
151 let file_name = CString::new(file_name).unwrap();
152
153 let raw = unsafe { ffi::LoadImage(file_name.as_ptr()) };
154
155 if unsafe { ffi::IsImageReady(raw.clone()) } {
156 Some(Self { raw })
157 } else {
158 None
159 }
160 }
161
162 #[inline]
164 pub fn from_raw_file(
165 file_name: &str,
166 width: u32,
167 height: u32,
168 format: PixelFormat,
169 header_size: u32,
170 ) -> Option<Self> {
171 let file_name = CString::new(file_name).unwrap();
172
173 let raw = unsafe {
174 ffi::LoadImageRaw(
175 file_name.as_ptr(),
176 width as _,
177 height as _,
178 format as _,
179 header_size as _,
180 )
181 };
182
183 if unsafe { ffi::IsImageReady(raw.clone()) } {
184 Some(Self { raw })
185 } else {
186 None
187 }
188 }
189
190 #[inline]
194 pub fn from_file_anim(file_name: &str) -> Option<(Self, usize)> {
195 let file_name = CString::new(file_name).unwrap();
196 let mut frames: i32 = 0;
197
198 let image = unsafe { ffi::LoadImageAnim(file_name.as_ptr(), (&mut frames) as *mut _) };
199
200 if unsafe { ffi::IsImageReady(image.clone()) } {
201 Some((Self { raw: image }, frames as _))
202 } else {
203 None
204 }
205 }
206
207 #[inline]
211 pub fn from_memory(file_data: &[u8], format: Option<ImageFormat>) -> Option<Self> {
212 let raw = unsafe {
213 let format = if let Some(format) = format {
214 format.as_cstr().as_ptr()
215 } else {
216 CStr::from_bytes_with_nul(b".png\0").unwrap().as_ptr()
217 };
218
219 ffi::LoadImageFromMemory(format, file_data.as_ptr(), file_data.len() as _)
220 };
221
222 if unsafe { ffi::IsImageReady(raw.clone()) } {
223 Some(Self { raw })
224 } else {
225 None
226 }
227 }
228
229 #[inline]
231 pub fn from_texture(texture: &Texture) -> Option<Self> {
232 let raw = unsafe { ffi::LoadImageFromTexture(texture.raw.clone()) };
233
234 if unsafe { ffi::IsImageReady(raw.clone()) } {
235 Some(Self { raw })
236 } else {
237 None
238 }
239 }
240
241 #[inline]
243 pub fn from_screen(_raylib: &Raylib) -> Option<Self> {
244 let raw = unsafe { ffi::LoadImageFromScreen() };
245
246 if unsafe { ffi::IsImageReady(raw.clone()) } {
247 Some(Self { raw })
248 } else {
249 None
250 }
251 }
252
253 #[inline]
255 pub fn export(&self, file_name: &str) -> bool {
256 let file_name = CString::new(file_name).unwrap();
257
258 unsafe { ffi::ExportImage(self.raw.clone(), file_name.as_ptr()) }
259 }
260
261 #[inline]
263 pub fn export_as_code(&self, file_name: &str) -> bool {
264 let file_name = CString::new(file_name).unwrap();
265
266 unsafe { ffi::ExportImageAsCode(self.raw.clone(), file_name.as_ptr()) }
267 }
268
269 #[inline]
271 pub fn generate_color(width: u32, height: u32, color: Color) -> Self {
272 Self {
273 raw: unsafe { ffi::GenImageColor(width as _, height as _, color.into()) },
274 }
275 }
276
277 #[inline]
279 pub fn generate_gradient_vertical(width: u32, height: u32, top: Color, bottom: Color) -> Self {
280 Self {
281 raw: unsafe {
282 ffi::GenImageGradientV(width as _, height as _, top.into(), bottom.into())
283 },
284 }
285 }
286
287 #[inline]
289 pub fn generate_gradient_horizontal(
290 width: u32,
291 height: u32,
292 left: Color,
293 right: Color,
294 ) -> Self {
295 Self {
296 raw: unsafe {
297 ffi::GenImageGradientH(width as _, height as _, left.into(), right.into())
298 },
299 }
300 }
301
302 #[inline]
304 pub fn generate_gradient_radial(
305 width: u32,
306 height: u32,
307 density: f32,
308 inner: Color,
309 outer: Color,
310 ) -> Self {
311 Self {
312 raw: unsafe {
313 ffi::GenImageGradientRadial(
314 width as _,
315 height as _,
316 density,
317 inner.into(),
318 outer.into(),
319 )
320 },
321 }
322 }
323
324 #[inline]
326 pub fn generate_checked(
327 width: u32,
328 height: u32,
329 checks_x: u32,
330 checks_y: u32,
331 color1: Color,
332 color2: Color,
333 ) -> Self {
334 Self {
335 raw: unsafe {
336 ffi::GenImageChecked(
337 width as _,
338 height as _,
339 checks_x as _,
340 checks_y as _,
341 color1.into(),
342 color2.into(),
343 )
344 },
345 }
346 }
347
348 #[inline]
350 pub fn generate_white_noise(width: u32, height: u32, factor: f32) -> Self {
351 Self {
352 raw: unsafe { ffi::GenImageWhiteNoise(width as _, height as _, factor) },
353 }
354 }
355
356 #[inline]
358 pub fn generate_perlin_noise(
359 width: u32,
360 height: u32,
361 offset_x: i32,
362 offset_y: i32,
363 scale: f32,
364 ) -> Self {
365 Self {
366 raw: unsafe {
367 ffi::GenImagePerlinNoise(width as _, height as _, offset_x, offset_y, scale)
368 },
369 }
370 }
371
372 #[inline]
374 pub fn generate_cellular(width: u32, height: u32, tile_size: u32) -> Self {
375 Self {
376 raw: unsafe { ffi::GenImageCellular(width as _, height as _, tile_size as _) },
377 }
378 }
379
380 #[inline]
382 pub fn generate_text(width: u32, height: u32, text: &str) -> Self {
383 let text = CString::new(text).unwrap();
384
385 Self {
386 raw: unsafe { ffi::GenImageText(width as _, height as _, text.as_ptr()) },
387 }
388 }
389
390 #[inline]
392 pub fn from_other_image(image: Self, rect: Rectangle) -> Self {
393 Self {
394 raw: unsafe { ffi::ImageFromImage(image.raw.clone(), rect.into()) },
395 }
396 }
397
398 #[inline]
400 pub fn text(text: &str, font_size: u32, color: Color) -> Self {
401 let text = CString::new(text).unwrap();
402
403 Self {
404 raw: unsafe { ffi::ImageText(text.as_ptr(), font_size as _, color.into()) },
405 }
406 }
407
408 #[inline]
410 pub fn text_with_font(
411 text: &str,
412 font: &Font,
413 font_size: f32,
414 spacing: f32,
415 tint: Color,
416 ) -> Self {
417 let text = CString::new(text).unwrap();
418
419 Self {
420 raw: unsafe {
421 ffi::ImageTextEx(
422 font.raw.clone(),
423 text.as_ptr(),
424 font_size,
425 spacing,
426 tint.into(),
427 )
428 },
429 }
430 }
431
432 #[inline]
434 pub fn convert_to_format(&mut self, new_format: PixelFormat) {
435 unsafe { ffi::ImageFormat(self.as_mut_ptr(), new_format as _) }
436 }
437
438 #[inline]
440 pub fn convert_to_power_of_two(&mut self, fill: Color) {
441 unsafe { ffi::ImageToPOT(self.as_mut_ptr(), fill.into()) }
442 }
443
444 #[inline]
446 pub fn crop(&mut self, rect: Rectangle) {
447 unsafe { ffi::ImageCrop(self.as_mut_ptr(), rect.into()) }
448 }
449
450 #[inline]
452 pub fn alpha_crop(&mut self, threshold: f32) {
453 unsafe { ffi::ImageAlphaCrop(self.as_mut_ptr(), threshold) }
454 }
455
456 #[inline]
458 pub fn alpha_clear(&mut self, color: Color, threshold: f32) {
459 unsafe { ffi::ImageAlphaClear(self.as_mut_ptr(), color.into(), threshold) }
460 }
461
462 #[inline]
464 pub fn alpha_mask(&mut self, alpha_mask: &Image) {
465 unsafe { ffi::ImageAlphaMask(self.as_mut_ptr(), alpha_mask.raw.clone()) }
466 }
467
468 #[inline]
470 pub fn alpha_premultiply(&mut self) {
471 unsafe { ffi::ImageAlphaPremultiply(self.as_mut_ptr()) }
472 }
473
474 #[inline]
476 pub fn blur_gaussian(&mut self, blur_size: u32) {
477 unsafe { ffi::ImageBlurGaussian(self.as_mut_ptr(), blur_size as _) }
478 }
479
480 #[inline]
482 pub fn resize(&mut self, new_width: u32, new_height: u32) {
483 unsafe { ffi::ImageResize(self.as_mut_ptr(), new_width as _, new_height as _) }
484 }
485
486 #[inline]
488 pub fn resize_nn(&mut self, new_width: u32, new_height: u32) {
489 unsafe { ffi::ImageResizeNN(self.as_mut_ptr(), new_width as _, new_height as _) }
490 }
491
492 #[inline]
494 pub fn resize_canvas(
495 &mut self,
496 new_width: u32,
497 new_height: u32,
498 offset_x: i32,
499 offset_y: i32,
500 fill: Color,
501 ) {
502 unsafe {
503 ffi::ImageResizeCanvas(
504 self.as_mut_ptr(),
505 new_width as _,
506 new_height as _,
507 offset_x,
508 offset_y,
509 fill.into(),
510 )
511 }
512 }
513
514 #[inline]
516 pub fn compute_mipmaps(&mut self) {
517 unsafe { ffi::ImageMipmaps(self.as_mut_ptr()) }
518 }
519
520 #[inline]
522 pub fn dither(&mut self, r_bpp: u32, g_bpp: u32, b_bpp: u32, a_bpp: u32) {
523 unsafe {
524 ffi::ImageDither(
525 self.as_mut_ptr(),
526 r_bpp as _,
527 g_bpp as _,
528 b_bpp as _,
529 a_bpp as _,
530 )
531 }
532 }
533
534 #[inline]
536 pub fn flip_vertical(&mut self) {
537 unsafe { ffi::ImageFlipVertical(self.as_mut_ptr()) }
538 }
539
540 #[inline]
542 pub fn flip_horizontal(&mut self) {
543 unsafe { ffi::ImageFlipHorizontal(self.as_mut_ptr()) }
544 }
545
546 #[inline]
548 pub fn rotate_clockwise(&mut self) {
549 unsafe { ffi::ImageRotateCW(self.as_mut_ptr()) }
550 }
551
552 #[inline]
554 pub fn rotate_counter_clockwise(&mut self) {
555 unsafe { ffi::ImageRotateCCW(self.as_mut_ptr()) }
556 }
557
558 #[inline]
560 pub fn color_tint(&mut self, color: Color) {
561 unsafe { ffi::ImageColorTint(self.as_mut_ptr(), color.into()) }
562 }
563
564 #[inline]
566 pub fn color_invert(&mut self) {
567 unsafe { ffi::ImageColorInvert(self.as_mut_ptr()) }
568 }
569
570 #[inline]
572 pub fn color_grayscale(&mut self) {
573 unsafe { ffi::ImageColorGrayscale(self.as_mut_ptr()) }
574 }
575
576 #[inline]
578 pub fn color_contrast(&mut self, contrast: f32) {
579 unsafe { ffi::ImageColorContrast(self.as_mut_ptr(), contrast) }
580 }
581
582 #[inline]
584 pub fn color_brightness(&mut self, brightness: i32) {
585 unsafe { ffi::ImageColorBrightness(self.as_mut_ptr(), brightness) }
586 }
587
588 #[inline]
590 pub fn color_replace(&mut self, color: Color, replace: Color) {
591 unsafe { ffi::ImageColorReplace(self.as_mut_ptr(), color.into(), replace.into()) }
592 }
593
594 pub fn load_colors(&self) -> Vec<Color> {
596 let colors = unsafe { ffi::LoadImageColors(self.raw.clone()) };
597 let len = (self.width() * self.height()) as usize;
598
599 let mut vec = Vec::with_capacity(len);
600
601 for i in 0..len {
602 unsafe {
603 vec.push(colors.add(i).read().into());
604 }
605 }
606
607 unsafe {
608 ffi::UnloadImageColors(colors);
609 }
610
611 vec
612 }
613
614 pub fn load_palette(&self, max_size: usize) -> Vec<Color> {
616 let mut count: i32 = 0;
617 let palette = unsafe {
618 ffi::LoadImagePalette(self.raw.clone(), max_size as _, (&mut count) as *mut _)
619 };
620
621 let mut vec = Vec::with_capacity(count as usize);
622
623 for i in 0..(count as usize) {
624 unsafe {
625 vec.push(palette.add(i).read().into());
626 }
627 }
628
629 unsafe {
630 ffi::UnloadImagePalette(palette);
631 }
632
633 vec
634 }
635
636 #[inline]
638 pub fn get_alpha_border(&self, threshold: f32) -> Rectangle {
639 unsafe { ffi::GetImageAlphaBorder(self.raw.clone(), threshold).into() }
640 }
641
642 #[inline]
644 pub fn get_color(&self, x: u32, y: u32) -> Color {
645 unsafe { ffi::GetImageColor(self.raw.clone(), x as _, y as _).into() }
646 }
647
648 #[inline]
650 pub fn clear_background(&mut self, color: Color) {
651 unsafe { ffi::ImageClearBackground(self.as_mut_ptr(), color.into()) }
652 }
653
654 #[inline]
656 pub fn draw_pixel(&mut self, pos: Vector2, color: Color) {
657 unsafe { ffi::ImageDrawPixelV(self.as_mut_ptr(), pos.into(), color.into()) }
658 }
659
660 #[inline]
662 pub fn draw_line(&mut self, start: Vector2, end: Vector2, color: Color) {
663 unsafe { ffi::ImageDrawLineV(self.as_mut_ptr(), start.into(), end.into(), color.into()) }
664 }
665
666 #[inline]
668 pub fn draw_circle(&mut self, center: Vector2, radius: u32, color: Color) {
669 unsafe {
670 ffi::ImageDrawCircleV(self.as_mut_ptr(), center.into(), radius as _, color.into())
671 }
672 }
673
674 #[inline]
676 pub fn draw_circle_lines_v(&mut self, center: Vector2, radius: u32, color: Color) {
677 unsafe {
678 ffi::ImageDrawCircleLinesV(self.as_mut_ptr(), center.into(), radius as _, color.into())
679 }
680 }
681
682 #[inline]
684 pub fn draw_rectangle(&mut self, rect: Rectangle, color: Color) {
685 unsafe { ffi::ImageDrawRectangleRec(self.as_mut_ptr(), rect.into(), color.into()) }
686 }
687
688 #[inline]
690 pub fn draw_rectangle_lines(&mut self, rect: Rectangle, thickness: u32, color: Color) {
691 unsafe {
692 ffi::ImageDrawRectangleLines(
693 self.as_mut_ptr(),
694 rect.into(),
695 thickness as _,
696 color.into(),
697 )
698 }
699 }
700
701 #[inline]
703 pub fn draw_image(
704 &mut self,
705 source: &Image,
706 source_rect: Rectangle,
707 dest_rect: Rectangle,
708 tint: Color,
709 ) {
710 unsafe {
711 ffi::ImageDraw(
712 self.as_mut_ptr(),
713 source.raw.clone(),
714 source_rect.into(),
715 dest_rect.into(),
716 tint.into(),
717 )
718 }
719 }
720
721 #[inline]
723 pub fn draw_text(&mut self, text: &str, position: Vector2, font_size: u32, color: Color) {
724 let text = CString::new(text).unwrap();
725
726 unsafe {
727 ffi::ImageDrawText(
728 self.as_mut_ptr(),
729 text.as_ptr(),
730 position.x as _,
731 position.y as _,
732 font_size as _,
733 color.into(),
734 )
735 }
736 }
737
738 #[inline]
740 pub fn draw_text_with_font(
741 &mut self,
742 text: &str,
743 pos: Vector2,
744 font: &Font,
745 font_size: f32,
746 spacing: f32,
747 tint: Color,
748 ) {
749 let text = CString::new(text).unwrap();
750
751 unsafe {
752 ffi::ImageDrawTextEx(
753 self.as_mut_ptr(),
754 font.raw.clone(),
755 text.as_ptr(),
756 pos.into(),
757 font_size,
758 spacing,
759 tint.into(),
760 )
761 }
762 }
763
764 #[inline]
766 pub fn get_pixel_data_size(&self) -> usize {
767 unsafe { ffi::GetPixelDataSize(self.raw.width, self.raw.height, self.raw.format) as usize }
768 }
769
770 #[inline]
772 pub fn rectangle(&self) -> Rectangle {
773 Rectangle::new(0., 0., self.raw.width as f32, self.raw.height as f32)
774 }
775
776 #[inline]
777 fn as_mut_ptr(&mut self) -> *mut ffi::Image {
778 (&mut self.raw) as *mut ffi::Image
779 }
780
781 #[inline]
784 pub fn as_raw(&self) -> &ffi::Image {
785 &self.raw
786 }
787
788 #[inline]
791 pub fn as_raw_mut(&mut self) -> &mut ffi::Image {
792 &mut self.raw
793 }
794
795 #[inline]
801 pub unsafe fn from_raw(raw: ffi::Image) -> Self {
802 Self { raw }
803 }
804}
805
806impl Clone for Image {
807 #[inline]
808 fn clone(&self) -> Self {
809 Self {
810 raw: unsafe { ffi::ImageCopy(self.raw.clone()) },
811 }
812 }
813}
814
815impl Drop for Image {
816 #[inline]
817 fn drop(&mut self) {
818 unsafe { ffi::UnloadImage(self.raw.clone()) }
819 }
820}
821
822#[derive(Debug)]
824#[repr(transparent)]
825pub struct Texture {
826 pub(crate) raw: ffi::Texture,
827}
828
829impl Texture {
830 #[inline]
832 pub fn width(&self) -> u32 {
833 self.raw.width as u32
834 }
835
836 #[inline]
838 pub fn height(&self) -> u32 {
839 self.raw.height as u32
840 }
841
842 #[inline]
844 pub fn mipmaps(&self) -> u32 {
845 self.raw.mipmaps as u32
846 }
847
848 #[inline]
850 pub fn format(&self) -> PixelFormat {
851 unsafe { std::mem::transmute(self.raw.format) }
852 }
853
854 #[inline]
856 pub fn from_file(file_name: &str) -> Option<Self> {
857 let file_name = CString::new(file_name).unwrap();
858
859 let raw = unsafe { ffi::LoadTexture(file_name.as_ptr()) };
860
861 if unsafe { ffi::IsTextureReady(raw.clone()) } {
862 Some(Self { raw })
863 } else {
864 None
865 }
866 }
867
868 #[inline]
870 pub fn from_image(image: &Image) -> Option<Self> {
871 let raw = unsafe { ffi::LoadTextureFromImage(image.raw.clone()) };
872
873 if unsafe { ffi::IsTextureReady(raw.clone()) } {
874 Some(Self { raw })
875 } else {
876 None
877 }
878 }
879
880 #[inline]
882 pub fn from_cubemap(image: &Image, layout: CubemapLayout) -> Option<TextureCubemap> {
883 let raw = unsafe { ffi::LoadTextureCubemap(image.raw.clone(), layout as _) };
884
885 if unsafe { ffi::IsTextureReady(raw.clone()) } {
886 Some(Self { raw })
887 } else {
888 None
889 }
890 }
891
892 #[inline]
896 pub fn update(&mut self, pixels: &[u8]) -> bool {
897 if pixels.len() == self.get_pixel_data_size() {
898 unsafe {
899 ffi::UpdateTexture(self.raw.clone(), pixels.as_ptr() as *const _);
900 }
901 true
902 } else {
903 false
904 }
905 }
906
907 #[inline]
911 pub fn update_rect(&mut self, rect: Rectangle, pixels: &[u8]) -> bool {
912 if pixels.len() == get_pixel_data_size(rect.width as u32, rect.height as u32, self.format())
913 && rect.x >= 0.
914 && rect.y >= 0.
915 && ((rect.x + rect.width) as u32) < self.width()
916 && ((rect.y + rect.height) as u32) < self.height()
917 {
918 unsafe {
919 ffi::UpdateTextureRec(self.raw.clone(), rect.into(), pixels.as_ptr() as *const _);
920 }
921 true
922 } else {
923 false
924 }
925 }
926
927 #[inline]
929 pub fn get_pixel_data_size(&self) -> usize {
930 get_pixel_data_size(self.width(), self.height(), self.format())
931 }
932
933 #[inline]
935 pub fn generate_mipmaps(&mut self) {
936 unsafe {
937 ffi::GenTextureMipmaps(&mut self.raw as *mut _);
938 }
939 }
940
941 #[inline]
943 pub fn set_filter(&mut self, filter: TextureFilter) {
944 unsafe { ffi::SetTextureFilter(self.raw.clone(), filter as _) }
945 }
946
947 #[inline]
949 pub fn set_wrap(&mut self, wrap: TextureWrap) {
950 unsafe { ffi::SetTextureWrap(self.raw.clone(), wrap as _) }
951 }
952
953 #[inline]
956 pub fn as_raw(&self) -> &ffi::Texture {
957 &self.raw
958 }
959
960 #[inline]
963 pub fn as_raw_mut(&mut self) -> &mut ffi::Texture {
964 &mut self.raw
965 }
966
967 #[inline]
973 pub unsafe fn from_raw(raw: ffi::Texture) -> Self {
974 Self { raw }
975 }
976}
977
978impl Drop for Texture {
979 #[inline]
980 fn drop(&mut self) {
981 unsafe { ffi::UnloadTexture(self.raw.clone()) }
982 }
983}
984
985#[derive(Debug)]
987#[repr(transparent)]
988pub struct RenderTexture {
989 pub(crate) raw: ffi::RenderTexture,
990}
991
992impl RenderTexture {
993 #[inline]
995 pub fn width(&self) -> u32 {
996 self.raw.texture.width as u32
997 }
998
999 #[inline]
1001 pub fn height(&self) -> u32 {
1002 self.raw.texture.height as u32
1003 }
1004
1005 #[inline]
1007 pub fn new(width: u32, height: u32) -> Option<Self> {
1008 let raw = unsafe { ffi::LoadRenderTexture(width as _, height as _) };
1009
1010 if unsafe { ffi::IsRenderTextureReady(raw.clone()) } {
1011 Some(Self { raw })
1012 } else {
1013 None
1014 }
1015 }
1016
1017 #[inline]
1020 pub fn as_raw(&self) -> &ffi::RenderTexture {
1021 &self.raw
1022 }
1023
1024 #[inline]
1027 pub fn as_raw_mut(&mut self) -> &mut ffi::RenderTexture {
1028 &mut self.raw
1029 }
1030
1031 #[inline]
1037 pub unsafe fn from_raw(raw: ffi::RenderTexture) -> Self {
1038 Self { raw }
1039 }
1040}
1041
1042impl Drop for RenderTexture {
1043 #[inline]
1044 fn drop(&mut self) {
1045 unsafe { ffi::UnloadRenderTexture(self.raw.clone()) }
1046 }
1047}
1048
1049pub type Texture2D = Texture;
1051
1052pub type TextureCubemap = Texture;
1054
1055pub type RenderTexture2D = RenderTexture;