1#![allow(clippy::too_many_arguments)]
39
40pub mod particles;
42
43pub mod camera;
45
46pub mod debug_log;
48
49pub mod render_queue;
51
52pub mod gpu_instancing;
57
58pub mod input_sdl2;
60
61pub mod backend_sdl2;
63
64pub mod audio_sdl2;
66
67pub mod font_sdl2;
69
70pub mod sdl2_ffi;
72
73pub mod toolkit;
75
76pub mod fsr;
78
79use raylib::consts::KeyboardKey;
80use raylib::prelude::*;
81
82#[cfg(feature = "migui")]
84use migui::{Color as MiguiColor, MiguiBackend, Rect as MiguiRect};
85
86use std::collections::HashMap;
93use std::ffi::CString;
94use std::str::FromStr;
95
96pub struct AudioSystem {
99 initialized: bool,
100 sounds: HashMap<String, raylib::ffi::Sound>,
101 music: Option<raylib::ffi::Music>,
102}
103
104impl AudioSystem {
105 pub fn new() -> Self {
107 unsafe {
108 raylib::ffi::InitAudioDevice();
109 println!("[AUDIO] Dispositivo de audio inicializado");
110 }
111 Self {
112 initialized: true,
113 sounds: HashMap::new(),
114 music: None,
115 }
116 }
117
118 pub fn load_sound(&mut self, id: &str, path: &str) -> Result<(), String> {
120 if !self.initialized {
121 return Err("Audio no inicializado".into());
122 }
123
124 let c_path = CString::new(path).map_err(|e| format!("Error en path: {}", e))?;
125
126 unsafe {
127 let sound = raylib::ffi::LoadSound(c_path.as_ptr());
128 if !sound.stream.buffer.is_null() || sound.frameCount > 0 {
130 println!("[AUDIO] Sonido '{}' cargado: {}", id, path);
131 self.sounds.insert(id.to_string(), sound);
132 Ok(())
133 } else {
134 Err(format!("Error cargando sonido '{}'", path))
135 }
136 }
137 }
138
139 pub fn play_sound(&self, id: &str) -> bool {
141 if let Some(sound) = self.sounds.get(id) {
142 unsafe {
143 raylib::ffi::PlaySound(*sound);
144 }
145 true
146 } else {
147 false
148 }
149 }
150
151 pub fn stop_sound(&self, id: &str) -> bool {
153 if let Some(sound) = self.sounds.get(id) {
154 unsafe {
155 raylib::ffi::StopSound(*sound);
156 }
157 true
158 } else {
159 false
160 }
161 }
162
163 pub fn set_sound_volume(&self, id: &str, volume: f32) -> bool {
165 if let Some(sound) = self.sounds.get(id) {
166 unsafe {
167 raylib::ffi::SetSoundVolume(*sound, volume);
168 }
169 true
170 } else {
171 false
172 }
173 }
174
175 pub fn load_music(&mut self, path: &str) -> Result<(), String> {
177 if !self.initialized {
178 return Err("Audio no inicializado".into());
179 }
180
181 let c_path = CString::new(path).map_err(|e| format!("Error en path: {}", e))?;
182
183 unsafe {
184 let music = raylib::ffi::LoadMusicStream(c_path.as_ptr());
185 if !music.stream.buffer.is_null() || music.frameCount > 0 {
187 println!("[AUDIO] Música cargada: {}", path);
188 self.music = Some(music);
189 Ok(())
190 } else {
191 Err(format!("Error cargando música '{}'", path))
192 }
193 }
194 }
195
196 pub fn play_music(&mut self) {
198 if let Some(ref music) = self.music {
199 unsafe {
200 raylib::ffi::PlayMusicStream(*music);
201 }
202 println!("[AUDIO] Reproduciendo música");
203 }
204 }
205
206 pub fn stop_music(&mut self) {
208 if let Some(ref music) = self.music {
209 unsafe {
210 raylib::ffi::StopMusicStream(*music);
211 }
212 println!("[AUDIO] Música detenida");
213 }
214 }
215
216 pub fn update_music(&mut self) {
218 if let Some(ref music) = self.music {
219 unsafe {
220 raylib::ffi::UpdateMusicStream(*music);
221 }
222 }
223 }
224
225 pub fn set_music_volume(&mut self, volume: f32) {
227 if let Some(ref music) = self.music {
228 unsafe {
229 raylib::ffi::SetMusicVolume(*music, volume);
230 }
231 }
232 }
233
234 pub fn is_music_playing(&self) -> bool {
236 if let Some(ref music) = self.music {
237 unsafe { raylib::ffi::IsMusicStreamPlaying(*music) }
238 } else {
239 false
240 }
241 }
242
243 pub fn unload_sound(&mut self, id: &str) {
245 if let Some(sound) = self.sounds.remove(id) {
246 unsafe {
247 raylib::ffi::UnloadSound(sound);
248 }
249 println!("[AUDIO] Sonido '{}' descargado", id);
250 }
251 }
252
253 pub fn unload_music(&mut self) {
255 if let Some(music) = self.music.take() {
256 unsafe {
257 raylib::ffi::UnloadMusicStream(music);
258 }
259 println!("[AUDIO] Música descargada");
260 }
261 }
262
263 pub fn has_sound(&self, id: &str) -> bool {
265 self.sounds.contains_key(id)
266 }
267
268 pub fn sound_count(&self) -> usize {
270 self.sounds.len()
271 }
272}
273
274impl Default for AudioSystem {
275 fn default() -> Self {
276 Self::new()
277 }
278}
279
280impl Drop for AudioSystem {
281 fn drop(&mut self) {
282 println!("[AUDIO] Cerrando sistema de audio...");
283 for (_, sound) in self.sounds.drain() {
285 unsafe {
286 raylib::ffi::UnloadSound(sound);
287 }
288 }
289 if let Some(music) = self.music.take() {
291 unsafe {
292 raylib::ffi::UnloadMusicStream(music);
293 }
294 }
295 if self.initialized {
297 unsafe {
298 raylib::ffi::CloseAudioDevice();
299 }
300 println!("[AUDIO] Dispositivo cerrado");
301 }
302 }
303}
304
305pub const RED: Color = Color {
307 r: 230,
308 g: 41,
309 b: 55,
310 a: 255,
311};
312pub const GREEN: Color = Color {
313 r: 117,
314 g: 203,
315 b: 100,
316 a: 255,
317};
318pub const BLUE: Color = Color {
319 r: 51,
320 g: 122,
321 b: 206,
322 a: 255,
323};
324pub const YELLOW: Color = Color {
325 r: 253,
326 g: 249,
327 b: 0,
328 a: 255,
329};
330pub const WHITE: Color = Color {
331 r: 255,
332 g: 255,
333 b: 255,
334 a: 255,
335};
336pub const BLACK: Color = Color {
337 r: 0,
338 g: 0,
339 b: 0,
340 a: 255,
341};
342pub const MAGENTA: Color = Color {
343 r: 255,
344 g: 0,
345 b: 255,
346 a: 255,
347};
348pub const PINK: Color = Color {
349 r: 255,
350 g: 192,
351 b: 203,
352 a: 255,
353};
354pub const ORANGE: Color = Color {
355 r: 255,
356 g: 165,
357 b: 0,
358 a: 255,
359};
360pub const GRAY: Color = Color {
361 r: 128,
362 g: 128,
363 b: 128,
364 a: 255,
365};
366
367pub const CYAN: Color = Color {
369 r: 0,
370 g: 255,
371 b: 255,
372 a: 255,
373};
374pub const PURPLE: Color = Color {
375 r: 128,
376 g: 0,
377 b: 128,
378 a: 255,
379};
380pub const BROWN: Color = Color {
381 r: 165,
382 g: 42,
383 b: 42,
384 a: 255,
385};
386pub const LIME: Color = Color {
387 r: 0,
388 g: 255,
389 b: 0,
390 a: 255,
391};
392pub const NAVY: Color = Color {
393 r: 0,
394 g: 0,
395 b: 128,
396 a: 255,
397};
398pub const OLIVE: Color = Color {
399 r: 128,
400 g: 128,
401 b: 0,
402 a: 255,
403};
404pub const TEAL: Color = Color {
405 r: 0,
406 g: 128,
407 b: 128,
408 a: 255,
409};
410pub const MAROON: Color = Color {
411 r: 128,
412 g: 0,
413 b: 0,
414 a: 255,
415};
416
417pub const KEY_ESCAPE: KeyboardKey = unsafe { std::mem::transmute(256i32) };
419pub const KEY_SPACE: KeyboardKey = unsafe { std::mem::transmute(32i32) };
420pub const KEY_ENTER: KeyboardKey = unsafe { std::mem::transmute(257i32) };
421pub const KEY_UP: KeyboardKey = unsafe { std::mem::transmute(265i32) };
422pub const KEY_DOWN: KeyboardKey = unsafe { std::mem::transmute(264i32) };
423pub const KEY_LEFT: KeyboardKey = unsafe { std::mem::transmute(263i32) };
424pub const KEY_RIGHT: KeyboardKey = unsafe { std::mem::transmute(262i32) };
425pub const KEY_A: KeyboardKey = unsafe { std::mem::transmute(65i32) };
426pub const KEY_B: KeyboardKey = unsafe { std::mem::transmute(66i32) };
427pub const KEY_C: KeyboardKey = unsafe { std::mem::transmute(67i32) };
428pub const KEY_D: KeyboardKey = unsafe { std::mem::transmute(68i32) };
429pub const KEY_E: KeyboardKey = unsafe { std::mem::transmute(69i32) };
430pub const KEY_F: KeyboardKey = unsafe { std::mem::transmute(70i32) };
431pub const KEY_G: KeyboardKey = unsafe { std::mem::transmute(71i32) };
432pub const KEY_H: KeyboardKey = unsafe { std::mem::transmute(72i32) };
433pub const KEY_I: KeyboardKey = unsafe { std::mem::transmute(73i32) };
434pub const KEY_J: KeyboardKey = unsafe { std::mem::transmute(74i32) };
435pub const KEY_K: KeyboardKey = unsafe { std::mem::transmute(75i32) };
436pub const KEY_L: KeyboardKey = unsafe { std::mem::transmute(76i32) };
437pub const KEY_M: KeyboardKey = unsafe { std::mem::transmute(77i32) };
438pub const KEY_N: KeyboardKey = unsafe { std::mem::transmute(78i32) };
439pub const KEY_O: KeyboardKey = unsafe { std::mem::transmute(79i32) };
440pub const KEY_P: KeyboardKey = unsafe { std::mem::transmute(80i32) };
441pub const KEY_Q: KeyboardKey = unsafe { std::mem::transmute(81i32) };
442pub const KEY_R: KeyboardKey = unsafe { std::mem::transmute(82i32) };
443pub const KEY_S: KeyboardKey = unsafe { std::mem::transmute(83i32) };
444pub const KEY_T: KeyboardKey = unsafe { std::mem::transmute(84i32) };
445pub const KEY_U: KeyboardKey = unsafe { std::mem::transmute(85i32) };
446pub const KEY_V: KeyboardKey = unsafe { std::mem::transmute(86i32) };
447pub const KEY_W: KeyboardKey = unsafe { std::mem::transmute(87i32) };
448pub const KEY_X: KeyboardKey = unsafe { std::mem::transmute(88i32) };
449pub const KEY_Y: KeyboardKey = unsafe { std::mem::transmute(89i32) };
450pub const KEY_Z: KeyboardKey = unsafe { std::mem::transmute(90i32) };
451pub const KEY_ZERO: KeyboardKey = unsafe { std::mem::transmute(48i32) };
452pub const KEY_ONE: KeyboardKey = unsafe { std::mem::transmute(49i32) };
453pub const KEY_TWO: KeyboardKey = unsafe { std::mem::transmute(50i32) };
454pub const KEY_THREE: KeyboardKey = unsafe { std::mem::transmute(51i32) };
455pub const KEY_FOUR: KeyboardKey = unsafe { std::mem::transmute(52i32) };
456pub const KEY_FIVE: KeyboardKey = unsafe { std::mem::transmute(53i32) };
457pub const KEY_SIX: KeyboardKey = unsafe { std::mem::transmute(54i32) };
458pub const KEY_SEVEN: KeyboardKey = unsafe { std::mem::transmute(55i32) };
459pub const KEY_EIGHT: KeyboardKey = unsafe { std::mem::transmute(56i32) };
460pub const KEY_NINE: KeyboardKey = unsafe { std::mem::transmute(57i32) };
461
462pub const KEY_TAB: KeyboardKey = unsafe { std::mem::transmute(258i32) };
464pub const KEY_CAPS_LOCK: KeyboardKey = unsafe { std::mem::transmute(259i32) };
465pub const KEY_LEFT_SHIFT: KeyboardKey = unsafe { std::mem::transmute(340i32) };
466pub const KEY_RIGHT_SHIFT: KeyboardKey = unsafe { std::mem::transmute(344i32) };
467pub const KEY_LEFT_CONTROL: KeyboardKey = unsafe { std::mem::transmute(341i32) };
468pub const KEY_RIGHT_CONTROL: KeyboardKey = unsafe { std::mem::transmute(345i32) };
469pub const KEY_LEFT_ALT: KeyboardKey = unsafe { std::mem::transmute(342i32) };
470pub const KEY_RIGHT_ALT: KeyboardKey = unsafe { std::mem::transmute(346i32) };
471pub const KEY_PAGE_UP: KeyboardKey = unsafe { std::mem::transmute(266i32) };
472pub const KEY_PAGE_DOWN: KeyboardKey = unsafe { std::mem::transmute(267i32) };
473pub const KEY_HOME: KeyboardKey = unsafe { std::mem::transmute(268i32) };
474pub const KEY_END: KeyboardKey = unsafe { std::mem::transmute(269i32) };
475pub const KEY_INSERT: KeyboardKey = unsafe { std::mem::transmute(260i32) };
476pub const KEY_DELETE: KeyboardKey = unsafe { std::mem::transmute(261i32) };
477pub const KEY_F1: KeyboardKey = unsafe { std::mem::transmute(290i32) };
478pub const KEY_F2: KeyboardKey = unsafe { std::mem::transmute(291i32) };
479pub const KEY_F3: KeyboardKey = unsafe { std::mem::transmute(292i32) };
480pub const KEY_F4: KeyboardKey = unsafe { std::mem::transmute(293i32) };
481pub const KEY_F5: KeyboardKey = unsafe { std::mem::transmute(294i32) };
482pub const KEY_F6: KeyboardKey = unsafe { std::mem::transmute(295i32) };
483pub const KEY_F7: KeyboardKey = unsafe { std::mem::transmute(296i32) };
484pub const KEY_F8: KeyboardKey = unsafe { std::mem::transmute(297i32) };
485pub const KEY_F9: KeyboardKey = unsafe { std::mem::transmute(298i32) };
486pub const KEY_F10: KeyboardKey = unsafe { std::mem::transmute(299i32) };
487pub const KEY_F11: KeyboardKey = unsafe { std::mem::transmute(300i32) };
488pub const KEY_F12: KeyboardKey = unsafe { std::mem::transmute(301i32) };
489
490#[derive(Debug, Clone, Copy, PartialEq)]
496pub enum ColorRydit {
497 Rojo,
498 Verde,
499 Azul,
500 Amarillo,
501 Blanco,
502 Negro,
503 Magenta,
504 Rosa,
505 Naranja,
506 Gris,
507 Cyan,
509 Morado,
510 Cafe,
511 Lima,
512 AzulOscuro,
513 Oliva,
514 Turquesa,
515 Vino,
516}
517
518impl ColorRydit {
519 pub fn to_color(&self) -> Color {
521 match self {
522 ColorRydit::Rojo => RED,
523 ColorRydit::Verde => GREEN,
524 ColorRydit::Azul => BLUE,
525 ColorRydit::Amarillo => YELLOW,
526 ColorRydit::Blanco => WHITE,
527 ColorRydit::Negro => BLACK,
528 ColorRydit::Magenta => MAGENTA,
529 ColorRydit::Rosa => PINK,
530 ColorRydit::Naranja => ORANGE,
531 ColorRydit::Gris => GRAY,
532 ColorRydit::Cyan => CYAN,
533 ColorRydit::Morado => PURPLE,
534 ColorRydit::Cafe => BROWN,
535 ColorRydit::Lima => LIME,
536 ColorRydit::AzulOscuro => NAVY,
537 ColorRydit::Oliva => OLIVE,
538 ColorRydit::Turquesa => TEAL,
539 ColorRydit::Vino => MAROON,
540 }
541 }
542
543 pub fn to_rgb(&self) -> (u8, u8, u8) {
545 match self {
546 ColorRydit::Rojo => (255, 0, 0),
547 ColorRydit::Verde => (0, 255, 0),
548 ColorRydit::Azul => (0, 0, 255),
549 ColorRydit::Amarillo => (255, 255, 0),
550 ColorRydit::Blanco => (255, 255, 255),
551 ColorRydit::Negro => (0, 0, 0),
552 ColorRydit::Magenta => (255, 0, 255),
553 ColorRydit::Rosa => (255, 192, 203),
554 ColorRydit::Naranja => (255, 165, 0),
555 ColorRydit::Gris => (128, 128, 128),
556 ColorRydit::Cyan => (0, 255, 255),
557 ColorRydit::Morado => (128, 0, 128),
558 ColorRydit::Cafe => (165, 42, 42),
559 ColorRydit::Lima => (0, 255, 0),
560 ColorRydit::AzulOscuro => (0, 0, 139),
561 ColorRydit::Oliva => (128, 128, 0),
562 ColorRydit::Turquesa => (64, 224, 208),
563 ColorRydit::Vino => (128, 0, 64),
564 }
565 }
566
567 #[cfg(feature = "migui")]
569 pub fn from_migui(color: MiguiColor) -> Self {
570 let r = color.r;
574 let g = color.g;
575 let b = color.b;
576
577 let colores = vec![
579 (ColorRydit::Rojo, RED),
580 (ColorRydit::Verde, GREEN),
581 (ColorRydit::Azul, BLUE),
582 (ColorRydit::Amarillo, YELLOW),
583 (ColorRydit::Blanco, WHITE),
584 (ColorRydit::Negro, BLACK),
585 (ColorRydit::Gris, GRAY),
586 (ColorRydit::Naranja, ORANGE),
587 (ColorRydit::Cyan, CYAN),
588 (ColorRydit::Morado, PURPLE),
589 (ColorRydit::Cafe, BROWN),
590 (ColorRydit::Lima, LIME),
591 (ColorRydit::AzulOscuro, NAVY),
592 (ColorRydit::Oliva, OLIVE),
593 (ColorRydit::Turquesa, TEAL),
594 (ColorRydit::Vino, MAROON),
595 ];
596
597 let mut mejor_color = ColorRydit::Blanco;
598 let mut mejor_distancia = f32::MAX;
599
600 for (ry_color, raylib_color) in colores {
601 let dr = (r as i32 - raylib_color.r as i32).pow(2) as f32;
602 let dg = (g as i32 - raylib_color.g as i32).pow(2) as f32;
603 let db = (b as i32 - raylib_color.b as i32).pow(2) as f32;
604 let distancia = dr + dg + db;
605
606 if distancia < mejor_distancia {
607 mejor_distancia = distancia;
608 mejor_color = ry_color;
609 }
610 }
611
612 mejor_color
613 }
614}
615
616impl FromStr for ColorRydit {
618 type Err = ();
619
620 fn from_str(s: &str) -> Result<Self, Self::Err> {
621 match s.to_lowercase().as_str() {
622 "rojo" | "red" => Ok(ColorRydit::Rojo),
623 "verde" | "green" => Ok(ColorRydit::Verde),
624 "azul" | "blue" => Ok(ColorRydit::Azul),
625 "amarillo" | "yellow" => Ok(ColorRydit::Amarillo),
626 "blanco" | "white" => Ok(ColorRydit::Blanco),
627 "negro" | "black" => Ok(ColorRydit::Negro),
628 "magenta" | "fucsia" => Ok(ColorRydit::Magenta),
629 "rosa" | "pink" => Ok(ColorRydit::Rosa),
630 "naranja" | "orange" => Ok(ColorRydit::Naranja),
631 "gris" | "gray" | "grey" => Ok(ColorRydit::Gris),
632 "cyan" | "celeste" => Ok(ColorRydit::Cyan),
633 "morado" | "purple" | "violeta" => Ok(ColorRydit::Morado),
634 "cafe" | "brown" | "marron" => Ok(ColorRydit::Cafe),
635 "lima" | "lime" => Ok(ColorRydit::Lima),
636 "azuloscuro" | "navy" | "azul oscuro" => Ok(ColorRydit::AzulOscuro),
637 "oliva" | "olive" => Ok(ColorRydit::Oliva),
638 "turquesa" | "teal" => Ok(ColorRydit::Turquesa),
639 "vino" | "maroon" | "granate" => Ok(ColorRydit::Vino),
640 _ => Ok(ColorRydit::Blanco),
641 }
642 }
643}
644
645#[derive(Debug, Clone, Copy, PartialEq)]
652pub enum Key {
653 Escape,
654 Space,
655 Enter,
656 Tab,
657 CapsLock,
658 LeftShift,
659 RightShift,
660 LeftControl,
661 RightControl,
662 LeftAlt,
663 RightAlt,
664 PageUp,
665 PageDown,
666 Home,
667 End,
668 Insert,
669 Delete,
670 F1,
671 F2,
672 F3,
673 F4,
674 F5,
675 F6,
676 F7,
677 F8,
678 F9,
679 F10,
680 F11,
681 F12,
682 ArrowUp,
683 ArrowDown,
684 ArrowLeft,
685 ArrowRight,
686 A,
687 B,
688 C,
689 D,
690 E,
691 F,
692 G,
693 H,
694 I,
695 J,
696 K,
697 L,
698 M,
699 N,
700 O,
701 P,
702 Q,
703 R,
704 S,
705 T,
706 U,
707 V,
708 W,
709 X,
710 Y,
711 Z,
712 Num0,
713 Num1,
714 Num2,
715 Num3,
716 Num4,
717 Num5,
718 Num6,
719 Num7,
720 Num8,
721 Num9,
722}
723
724impl Key {
725 pub fn to_raylib(&self) -> KeyboardKey {
727 match self {
728 Key::Escape => KEY_ESCAPE,
730 Key::Space => KEY_SPACE,
731 Key::Enter => KEY_ENTER,
732 Key::Tab => KEY_TAB,
733 Key::CapsLock => KEY_CAPS_LOCK,
734 Key::LeftShift => KEY_LEFT_SHIFT,
735 Key::RightShift => KEY_RIGHT_SHIFT,
736 Key::LeftControl => KEY_LEFT_CONTROL,
737 Key::RightControl => KEY_RIGHT_CONTROL,
738 Key::LeftAlt => KEY_LEFT_ALT,
739 Key::RightAlt => KEY_RIGHT_ALT,
740
741 Key::PageUp => KEY_PAGE_UP,
743 Key::PageDown => KEY_PAGE_DOWN,
744 Key::Home => KEY_HOME,
745 Key::End => KEY_END,
746 Key::Insert => KEY_INSERT,
747 Key::Delete => KEY_DELETE,
748
749 Key::F1 => KEY_F1,
751 Key::F2 => KEY_F2,
752 Key::F3 => KEY_F3,
753 Key::F4 => KEY_F4,
754 Key::F5 => KEY_F5,
755 Key::F6 => KEY_F6,
756 Key::F7 => KEY_F7,
757 Key::F8 => KEY_F8,
758 Key::F9 => KEY_F9,
759 Key::F10 => KEY_F10,
760 Key::F11 => KEY_F11,
761 Key::F12 => KEY_F12,
762
763 Key::ArrowUp => KEY_UP,
765 Key::ArrowDown => KEY_DOWN,
766 Key::ArrowLeft => KEY_LEFT,
767 Key::ArrowRight => KEY_RIGHT,
768
769 Key::A => KEY_A,
771 Key::B => KEY_B,
772 Key::C => KEY_C,
773 Key::D => KEY_D,
774 Key::E => KEY_E,
775 Key::F => KEY_F,
776 Key::G => KEY_G,
777 Key::H => KEY_H,
778 Key::I => KEY_I,
779 Key::J => KEY_J,
780 Key::K => KEY_K,
781 Key::L => KEY_L,
782 Key::M => KEY_M,
783 Key::N => KEY_N,
784 Key::O => KEY_O,
785 Key::P => KEY_P,
786 Key::Q => KEY_Q,
787 Key::R => KEY_R,
788 Key::S => KEY_S,
789 Key::T => KEY_T,
790 Key::U => KEY_U,
791 Key::V => KEY_V,
792 Key::W => KEY_W,
793 Key::X => KEY_X,
794 Key::Y => KEY_Y,
795 Key::Z => KEY_Z,
796
797 Key::Num0 => KEY_ZERO,
799 Key::Num1 => KEY_ONE,
800 Key::Num2 => KEY_TWO,
801 Key::Num3 => KEY_THREE,
802 Key::Num4 => KEY_FOUR,
803 Key::Num5 => KEY_FIVE,
804 Key::Num6 => KEY_SIX,
805 Key::Num7 => KEY_SEVEN,
806 Key::Num8 => KEY_EIGHT,
807 Key::Num9 => KEY_NINE,
808 }
809 }
810}
811
812pub struct RyditGfx {
825 handle: RaylibHandle,
826 thread: RaylibThread,
827 width: i32,
828 height: i32,
829 fps: i32,
830 pub input_sdl2: input_sdl2::InputState,
832 #[allow(dead_code)]
834 sdl_context: Option<sdl2::Sdl>,
835 sdl_event_pump: Option<sdl2::EventPump>,
836 #[allow(dead_code)]
838 fsr: Option<fsr::FsrUpscaler>,
839 #[allow(dead_code)]
840 fsr_enabled: bool,
841}
842
843impl RyditGfx {
844 pub fn new(title: &str, width: i32, height: i32) -> Self {
846 let (handle, thread) = raylib::init().size(width, height).title(title).build();
847
848 println!("[RYDIT-GFX]: Ventana creada {}x{}", width, height);
849 println!("[RYDIT-GFX]: Rust = Arquitecto, Raylib = Pincel");
850 println!(
851 "[RYDIT-GFX]: DISPLAY={}",
852 std::env::var("DISPLAY").unwrap_or_else(|_| "NO SET".to_string())
853 );
854
855 let sdl_context = sdl2::init().ok();
857
858 if let Some(_) = &sdl_context {
860 sdl2::hint::set("SDL_VIDEODRIVER", "x11");
862 sdl2::hint::set("SDL_HINT_VIDEO_X11_FORCE_EGL", "1");
864 sdl2::hint::set("SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH", "1");
866 sdl2::hint::set("SDL_HINT_TOUCH_MOUSE_EVENTS", "1");
868 sdl2::hint::set("SDL_HINT_ENABLE_SCREEN_KEYBOARD", "1");
870 sdl2::hint::set("SDL_HINT_IME_SHOW_UI", "1");
872
873 eprintln!("[RYDIT-GFX] SDL2 hints configurados para Android/Termux-X11");
874 }
875
876 let sdl_event_pump = sdl_context.as_ref().and_then(|ctx| ctx.event_pump().ok());
877
878 Self {
879 handle,
880 thread,
881 width,
882 height,
883 fps: 60,
884 input_sdl2: input_sdl2::InputState::new(),
885 sdl_context,
886 sdl_event_pump,
887 fsr: None, fsr_enabled: false,
889 }
890 }
891
892 pub fn set_target_fps(&mut self, fps: i32) {
894 self.fps = fps;
895 self.handle.set_target_fps(fps as u32);
896 }
897
898 pub fn get_target_fps(&self) -> i32 {
900 self.fps
901 }
902
903 pub fn get_fps(&self) -> i32 {
905 self.handle.get_fps() as i32
906 }
907
908 pub fn should_close(&self) -> bool {
910 self.handle.window_should_close()
911 }
912
913 pub fn procesar_eventos_sdl2(&mut self) {
919 self.input_sdl2.limpiar_frame();
921
922 if let Some(ref mut event_pump) = self.sdl_event_pump {
924 for event in event_pump.poll_iter() {
926 match event {
927 sdl2::event::Event::KeyDown {
928 keycode: Some(keycode),
929 repeat: false,
930 ..
931 } => {
932 self.input_sdl2.teclas.insert(keycode, true);
933 self.input_sdl2.teclas_pressionadas_frame.push(keycode);
934 }
935 sdl2::event::Event::KeyUp {
936 keycode: Some(keycode),
937 ..
938 } => {
939 self.input_sdl2.teclas.insert(keycode, false);
940 }
941 _ => {}
942 }
943 }
944 }
945 }
946
947 pub fn is_key_pressed_sdl2(&self, nombre: &str) -> bool {
949 self.input_sdl2.is_key_pressed(nombre)
950 }
951
952 pub fn is_key_just_pressed_sdl2(&self, nombre: &str) -> bool {
954 self.input_sdl2.is_key_just_pressed(nombre)
955 }
956
957 pub fn width(&self) -> i32 {
959 self.width
960 }
961
962 pub fn height(&self) -> i32 {
964 self.height
965 }
966
967 pub fn begin_draw(&mut self) -> DrawHandle<'_> {
969 let d = self.handle.begin_drawing(&self.thread);
970 DrawHandle::new(d)
971 }
972
973 pub fn end_draw(&mut self) {
975 }
977
978 pub fn init_fsr(&mut self, quality: fsr::FsrQuality) -> Result<(), String> {
984 match fsr::FsrUpscaler::new() {
985 Ok(fsr) => {
986 eprintln!("[FSR] Inicializado: {:?}", quality);
987 self.fsr = Some(fsr);
988 self.fsr_enabled = true;
989 Ok(())
990 }
991 Err(e) => {
992 eprintln!("[FSR] Error al inicializar: {} (FSR desactivado)", e);
993 self.fsr = None;
994 self.fsr_enabled = false;
995 Err(e)
996 }
997 }
998 }
999
1000 pub fn set_fsr_enabled(&mut self, enabled: bool) {
1002 if let Some(ref mut fsr) = self.fsr {
1003 fsr.set_enabled(enabled);
1004 self.fsr_enabled = enabled;
1005 }
1006 }
1007
1008 pub fn set_fsr_quality(&mut self, quality: fsr::FsrQuality) {
1010 if let Some(ref mut fsr) = self.fsr {
1011 fsr.set_quality(quality);
1012 }
1013 }
1014
1015 pub fn cycle_fsr_quality(&mut self) {
1017 if let Some(ref mut fsr) = self.fsr {
1018 fsr.cycle_quality();
1019 }
1020 }
1021
1022 pub fn is_fsr_enabled(&self) -> bool {
1024 self.fsr_enabled && self.fsr.is_some()
1025 }
1026
1027 pub fn fsr_quality(&self) -> Option<fsr::FsrQuality> {
1029 self.fsr.as_ref().map(|f| f.quality())
1030 }
1031
1032 pub fn clear_background(&mut self, color: ColorRydit) {
1034 let mut d = self.begin_draw();
1035 d.clear(color);
1036 }
1038
1039 pub fn draw_circle(&mut self, x: i32, y: i32, radius: i32, color: ColorRydit) {
1041 {
1042 let mut d = self.begin_draw();
1043 d.draw_circle(x, y, radius, color);
1044 drop(d); }
1046 }
1047
1048 pub fn draw_rect(&mut self, x: i32, y: i32, w: i32, h: i32, color: ColorRydit) {
1050 {
1051 let mut d = self.begin_draw();
1052 d.draw_rectangle(x, y, w, h, color);
1053 drop(d); }
1055 }
1056
1057 pub fn draw_line(&mut self, x1: i32, y1: i32, x2: i32, y2: i32, color: ColorRydit) {
1059 {
1060 let mut d = self.begin_draw();
1061 d.draw_line(x1, y1, x2, y2, color);
1062 drop(d); }
1064 }
1065
1066 pub fn draw_text(&mut self, text: &str, x: i32, y: i32, size: i32, color: ColorRydit) {
1068 {
1069 let mut d = self.begin_draw();
1070 d.draw_text(text, x, y, size, color);
1071 drop(d); }
1073 }
1074
1075 pub fn load_texture(&mut self, path: &str) -> Texture2D {
1077 unsafe {
1080 let c_path = std::ffi::CString::new(path).unwrap();
1081 let tex = raylib::ffi::LoadTexture(c_path.as_ptr());
1082 std::mem::transmute(tex)
1084 }
1085 }
1086
1087 pub fn draw_texture(&mut self, _texture: &Texture2D, x: i32, y: i32, color: ColorRydit) {
1089 self.draw_rect(x, y, 32, 32, color);
1091 }
1092
1093 pub fn draw_texture_ex(
1095 &mut self,
1096 _texture: &Texture2D,
1097 x: i32,
1098 y: i32,
1099 scale: f32,
1100 color: ColorRydit,
1101 ) {
1102 let size = (32.0 * scale) as i32;
1104 self.draw_rect(x, y, size, size, color);
1105 }
1106
1107 pub fn is_key_pressed(&self, key: Key) -> bool {
1109 self.handle.is_key_pressed(key.to_raylib())
1110 }
1111
1112 pub fn is_key_down(&self, key: Key) -> bool {
1114 self.handle.is_key_down(key.to_raylib())
1115 }
1116
1117 pub fn get_mouse_x(&self) -> i32 {
1119 self.handle.get_mouse_x()
1120 }
1121
1122 pub fn get_mouse_y(&self) -> i32 {
1124 self.handle.get_mouse_y()
1125 }
1126
1127 pub fn get_mouse_position(&self) -> (i32, i32) {
1133 (self.handle.get_mouse_x(), self.handle.get_mouse_y())
1134 }
1135
1136 pub fn is_mouse_button_pressed(&self, button: i32) -> bool {
1138 unsafe {
1140 let ffi_button = button;
1141 raylib::ffi::IsMouseButtonPressed(ffi_button)
1142 }
1143 }
1144
1145 pub fn is_mouse_button_down(&self, button: i32) -> bool {
1147 unsafe {
1148 let ffi_button = button;
1149 raylib::ffi::IsMouseButtonDown(ffi_button)
1150 }
1151 }
1152
1153 pub fn get_mouse_delta(&self) -> (i32, i32) {
1155 let delta = self.handle.get_mouse_delta();
1156 (delta.x as i32, delta.y as i32)
1157 }
1158
1159 pub fn get_mouse_wheel(&self) -> f32 {
1161 self.handle.get_mouse_wheel_move()
1163 }
1164}
1165
1166impl Drop for RyditGfx {
1167 fn drop(&mut self) {
1168 println!("[RYDIT-GFX]: Cerrando ventana...");
1169 }
1170}
1171
1172pub struct DrawHandle<'a> {
1181 pub draw: RaylibDrawHandle<'a>,
1182}
1183
1184impl<'a> DrawHandle<'a> {
1185 fn new(draw: RaylibDrawHandle<'a>) -> Self {
1186 Self { draw }
1187 }
1188
1189 pub fn clear(&mut self, color: ColorRydit) {
1191 self.draw.clear_background(color.to_color());
1192 }
1193
1194 pub fn draw_circle(&mut self, x: i32, y: i32, radius: i32, color: ColorRydit) {
1196 self.draw.draw_circle(x, y, radius as f32, color.to_color());
1197 }
1198
1199 pub fn draw_rectangle(&mut self, x: i32, y: i32, w: i32, h: i32, color: ColorRydit) {
1201 self.draw.draw_rectangle(x, y, w, h, color.to_color());
1202 }
1203
1204 pub fn draw_line(&mut self, x1: i32, y1: i32, x2: i32, y2: i32, color: ColorRydit) {
1206 self.draw.draw_line(x1, y1, x2, y2, color.to_color());
1207 }
1208
1209 pub fn draw_text(&mut self, text: &str, x: i32, y: i32, size: i32, color: ColorRydit) {
1211 self.draw.draw_text(text, x, y, size, color.to_color());
1212 }
1213
1214 pub fn draw_triangle(
1220 &mut self,
1221 v1: (i32, i32),
1222 v2: (i32, i32),
1223 v3: (i32, i32),
1224 color: ColorRydit,
1225 ) {
1226 let v1_raylib = Vector2::new(v1.0 as f32, v1.1 as f32);
1227 let v2_raylib = Vector2::new(v2.0 as f32, v2.1 as f32);
1228 let v3_raylib = Vector2::new(v3.0 as f32, v3.1 as f32);
1229 self.draw
1230 .draw_triangle(v1_raylib, v2_raylib, v3_raylib, color.to_color());
1231 }
1232
1233 pub fn draw_triangle_lines(
1235 &mut self,
1236 v1: (i32, i32),
1237 v2: (i32, i32),
1238 v3: (i32, i32),
1239 color: ColorRydit,
1240 ) {
1241 self.draw_line(v1.0, v1.1, v2.0, v2.1, color);
1242 self.draw_line(v2.0, v2.1, v3.0, v3.1, color);
1243 self.draw_line(v3.0, v3.1, v1.0, v1.1, color);
1244 }
1245
1246 pub fn draw_rectangle_lines(&mut self, x: i32, y: i32, w: i32, h: i32, color: ColorRydit) {
1248 self.draw.draw_rectangle_lines(x, y, w, h, color.to_color());
1249 }
1250
1251 pub fn draw_ring(
1253 &mut self,
1254 center: (i32, i32),
1255 _inner_radius: i32,
1256 outer_radius: i32,
1257 color: ColorRydit,
1258 ) {
1259 self.draw
1261 .draw_circle(center.0, center.1, outer_radius as f32, color.to_color());
1262 }
1263
1264 pub fn draw_ellipse(
1266 &mut self,
1267 center: (i32, i32),
1268 radius_h: i32,
1269 radius_v: i32,
1270 color: ColorRydit,
1271 ) {
1272 self.draw.draw_ellipse(
1273 center.0,
1274 center.1,
1275 radius_h as f32,
1276 radius_v as f32,
1277 color.to_color(),
1278 );
1279 }
1280
1281 pub fn draw_line_thick(
1283 &mut self,
1284 start_pos: (i32, i32),
1285 end_pos: (i32, i32),
1286 thick: f32,
1287 color: ColorRydit,
1288 ) {
1289 let start = Vector2::new(start_pos.0 as f32, start_pos.1 as f32);
1290 let end = Vector2::new(end_pos.0 as f32, end_pos.1 as f32);
1291 self.draw.draw_line_ex(start, end, thick, color.to_color());
1292 }
1293
1294 pub fn draw_rectangle_pro(
1296 &mut self,
1297 x: i32,
1298 y: i32,
1299 width: i32,
1300 height: i32,
1301 angle: f32,
1302 color: ColorRydit,
1303 ) {
1304 let origin = Vector2::new(width as f32 / 2.0, height as f32 / 2.0);
1305 let rect = Rectangle::new(x as f32, y as f32, width as f32, height as f32);
1306 self.draw
1307 .draw_rectangle_pro(rect, origin, angle, color.to_color());
1308 }
1309
1310 pub fn draw_texture_ex(
1312 &mut self,
1313 texture: &Texture2D,
1314 position: Vector2,
1315 rotation: f32,
1316 scale: f32,
1317 color: Color,
1318 ) {
1319 self.draw
1320 .draw_texture_ex(texture, position, rotation, scale, color);
1321 }
1322}
1323
1324impl<'a> Drop for DrawHandle<'a> {
1325 fn drop(&mut self) {
1326 }
1329}
1330
1331pub struct Assets {
1338 textures: HashMap<String, Texture2D>,
1339}
1340
1341impl Assets {
1342 pub fn new() -> Self {
1343 Self {
1344 textures: HashMap::new(),
1345 }
1346 }
1347
1348 pub fn load_texture_from_path(path: &str) -> Result<Texture2D, String> {
1350 use std::ffi::CString;
1351 use std::path::Path;
1352
1353 if Path::new(path).exists() {
1354 unsafe {
1356 let c_path =
1357 CString::new(path).map_err(|e| format!("Error convirtiendo path: {}", e))?;
1358 let ffi_texture = raylib::ffi::LoadTexture(c_path.as_ptr());
1359 if ffi_texture.id != 0 {
1360 Ok(Texture2D::from_raw(ffi_texture))
1362 } else {
1363 Err(format!("Error cargando textura '{}'", path))
1364 }
1365 }
1366 } else {
1367 Err(format!("Archivo '{}' no encontrado", path))
1368 }
1369 }
1370
1371 pub fn insert_texture(&mut self, id: String, texture: Texture2D) {
1375 self.textures.insert(id, texture);
1376 }
1377
1378 pub fn get_texture(&self, id: &str) -> Option<&Texture2D> {
1380 self.textures.get(id)
1381 }
1382
1383 pub fn unload_texture(&mut self, id: &str) -> bool {
1385 self.textures.remove(id).is_some()
1386 }
1387
1388 #[allow(clippy::too_many_arguments)]
1400 pub fn draw_texture(
1401 &self,
1402 d: &mut RaylibDrawHandle,
1403 id: &str,
1404 x: f32,
1405 y: f32,
1406 _w: f32,
1407 _h: f32,
1408 color: Color,
1409 ) {
1410 if let Some(texture) = self.textures.get(id) {
1411 d.draw_texture_ex(texture, Vector2::new(x, y), 0.0, 1.0, color);
1412 }
1413 }
1414
1415 pub fn draw_texture_scaled(
1417 &self,
1418 d: &mut RaylibDrawHandle,
1419 id: &str,
1420 x: f32,
1421 y: f32,
1422 scale: f32,
1423 color: Color,
1424 ) {
1425 if let Some(texture) = self.textures.get(id) {
1426 d.draw_texture_ex(texture, Vector2::new(x, y), 0.0, scale, color);
1427 }
1428 }
1429
1430 pub fn draw_texture_ex_by_id(
1432 &self,
1433 d: &mut RaylibDrawHandle,
1434 id: &str,
1435 x: f32,
1436 y: f32,
1437 scale: f32,
1438 rotation: f32,
1439 color: ColorRydit,
1440 ) {
1441 if let Some(texture) = self.textures.get(id) {
1442 d.draw_texture_ex(
1443 texture,
1444 Vector2::new(x, y),
1445 rotation,
1446 scale,
1447 color.to_color(),
1448 );
1449 }
1450 }
1451
1452 pub fn draw_texture_rec(
1454 &self,
1455 d: &mut RaylibDrawHandle,
1456 id: &str,
1457 source: Rectangle,
1458 dest: Rectangle,
1459 color: Color,
1460 ) {
1461 if let Some(texture) = self.textures.get(id) {
1462 d.draw_texture_rec(texture, source, Vector2::new(dest.x, dest.y), color);
1463 }
1464 }
1465
1466 pub fn has_texture(&self, id: &str) -> bool {
1468 self.textures.contains_key(id)
1469 }
1470
1471 pub fn texture_count(&self) -> usize {
1473 self.textures.len()
1474 }
1475
1476 pub fn clear(&mut self) {
1478 self.textures.clear();
1479 }
1480
1481 pub fn load_texture_sdl2<'a>(
1487 path: &str,
1488 texture_creator: &'a sdl2::render::TextureCreator<sdl2::video::WindowContext>,
1489 ) -> Result<sdl2::render::Texture<'a>, String> {
1490 use crate::sdl2_ffi::TextureFFI;
1491 use sdl2::surface::Surface;
1492 use std::path::Path;
1493
1494 if !Path::new(path).exists() {
1495 return Err(format!("Archivo '{}' no encontrado", path));
1496 }
1497
1498 let texture_ffi = TextureFFI::load(path)?;
1500 let surface_ptr = texture_ffi.surface();
1501
1502 unsafe {
1503 let sdl_surface = Surface::from_ll(surface_ptr as *mut sdl2::sys::SDL_Surface);
1505
1506 let texture = texture_creator
1508 .create_texture_from_surface(&sdl_surface)
1509 .map_err(|e| format!("Error creando textura SDL2: {}", e))?;
1510
1511 Ok(texture)
1512 }
1513 }
1514
1515 pub fn draw_texture_sdl2(
1517 canvas: &mut sdl2::render::Canvas<sdl2::video::Window>,
1518 texture: &sdl2::render::Texture,
1519 x: i32,
1520 y: i32,
1521 width: u32,
1522 height: u32,
1523 ) -> Result<(), String> {
1524 let rect = sdl2::rect::Rect::new(x, y, width, height);
1525 canvas
1526 .copy(texture, None, rect)
1527 .map_err(|e| format!("Error dibujando textura SDL2: {}", e))?;
1528
1529 Ok(())
1530 }
1531}
1532
1533impl Default for Assets {
1534 fn default() -> Self {
1535 Self::new()
1536 }
1537}
1538
1539#[cfg(feature = "migui")]
1550impl MiguiBackend for RyditGfx {
1551 fn clear(&mut self, color: MiguiColor) {
1552 let color_rydit = ColorRydit::from_migui(color);
1553 let mut d = self.begin_draw();
1554 d.clear(color_rydit);
1555 }
1556
1557 fn draw_rect(&mut self, rect: MiguiRect, color: MiguiColor) {
1558 let color_rydit = ColorRydit::from_migui(color);
1559 let mut d = self.begin_draw();
1560 d.draw_rectangle(
1561 rect.x as i32,
1562 rect.y as i32,
1563 rect.w as i32,
1564 rect.h as i32,
1565 color_rydit,
1566 );
1567 }
1568
1569 fn draw_text(&mut self, text: &str, x: f32, y: f32, size: f32, color: MiguiColor) {
1570 let color_rydit = ColorRydit::from_migui(color);
1571 let mut d = self.begin_draw();
1572 d.draw_text(text, x as i32, y as i32, size as i32, color_rydit);
1573 }
1574
1575 fn draw_line(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, color: MiguiColor, thickness: f32) {
1576 let color_rydit = ColorRydit::from_migui(color);
1577 let mut d = self.begin_draw();
1578 d.draw.draw_line_ex(
1579 Vector2::new(x1, y1),
1580 Vector2::new(x2, y2),
1581 thickness,
1582 color_rydit.to_color(),
1583 );
1584 }
1585}
1586
1587#[cfg(feature = "migui")]
1592impl RyditGfx {
1593 pub fn render_migui_frame(&mut self, commands: &[migui::DrawCommand]) {
1595 let mut d = self.begin_draw();
1596 d.clear(ColorRydit::Negro);
1597
1598 for cmd in commands {
1599 match cmd {
1600 migui::DrawCommand::Clear { color } => {
1601 d.clear(ColorRydit::from_migui(*color));
1602 }
1603 migui::DrawCommand::DrawRect { rect, color } => {
1604 d.draw_rectangle(
1605 rect.x as i32,
1606 rect.y as i32,
1607 rect.w as i32,
1608 rect.h as i32,
1609 ColorRydit::from_migui(*color),
1610 );
1611 }
1612 migui::DrawCommand::DrawText {
1613 text,
1614 x,
1615 y,
1616 size,
1617 color,
1618 } => {
1619 d.draw_text(
1620 text,
1621 *x as i32,
1622 *y as i32,
1623 *size as i32,
1624 ColorRydit::from_migui(*color),
1625 );
1626 }
1627 migui::DrawCommand::DrawLine {
1628 x1,
1629 y1,
1630 x2,
1631 y2,
1632 color,
1633 thickness,
1634 } => {
1635 d.draw.draw_line_ex(
1636 Vector2::new(*x1, *y1),
1637 Vector2::new(*x2, *y2),
1638 *thickness,
1639 ColorRydit::from_migui(*color).to_color(),
1640 );
1641 }
1642 }
1643 }
1644 }
1645}
1646
1647#[cfg(test)]
1652mod tests {
1653 use super::*;
1654
1655 #[test]
1656 fn test_color_from_str() {
1657 assert_eq!(ColorRydit::from_str("rojo").unwrap(), ColorRydit::Rojo);
1658 assert_eq!(ColorRydit::from_str("RED").unwrap(), ColorRydit::Rojo);
1659 assert_eq!(ColorRydit::from_str("verde").unwrap(), ColorRydit::Verde);
1660 assert_eq!(ColorRydit::from_str("azul").unwrap(), ColorRydit::Azul);
1661 assert_eq!(
1662 ColorRydit::from_str("amarillo").unwrap(),
1663 ColorRydit::Amarillo
1664 );
1665 assert_eq!(ColorRydit::from_str("blanco").unwrap(), ColorRydit::Blanco);
1666 assert_eq!(ColorRydit::from_str("negro").unwrap(), ColorRydit::Negro);
1667 assert_eq!(
1668 ColorRydit::from_str("desconocido").unwrap(),
1669 ColorRydit::Blanco
1670 );
1671 }
1672
1673 #[test]
1674 fn test_key_to_raylib() {
1675 let _ = Key::Escape.to_raylib();
1677 let _ = Key::Space.to_raylib();
1678 let _ = Key::A.to_raylib();
1679 let _ = Key::Num0.to_raylib();
1680 }
1681
1682 #[test]
1683 fn test_color_to_color() {
1684 let color = ColorRydit::Rojo.to_color();
1685 assert_eq!(color.r, 230);
1686 assert_eq!(color.g, 41);
1687 assert_eq!(color.b, 55);
1688 assert_eq!(color.a, 255);
1689 }
1690
1691 #[test]
1696 fn test_draw_circle_colores() {
1697 let colores = vec!["rojo", "verde", "azul", "amarillo", "blanco", "negro"];
1699
1700 for color_str in colores {
1701 let color_rydit = ColorRydit::from_str(color_str).unwrap();
1702 let color = color_rydit.to_color();
1703 assert_eq!(color.a, 255, "Color {} debe tener alpha 255", color_str);
1705 }
1706 }
1707
1708 #[test]
1709 fn test_draw_rect_dimensiones() {
1710 let x: i32 = 100;
1713 let y: i32 = 200;
1714 let ancho: i32 = 50;
1715 let alto: i32 = 75;
1716
1717 assert_eq!(x, 100);
1719 assert_eq!(y, 200);
1720 assert_eq!(ancho, 50);
1721 assert_eq!(alto, 75);
1722
1723 let rect = raylib::prelude::Rectangle::new(x as f32, y as f32, ancho as f32, alto as f32);
1725 assert_eq!(rect.x, 100.0);
1726 assert_eq!(rect.y, 200.0);
1727 assert!((rect.width - 50.0).abs() < 0.01);
1728 assert!((rect.height - 75.0).abs() < 0.01);
1729 }
1730
1731 #[test]
1736 fn test_mouse_functions_exist() {
1737 let _ = RyditGfx::new("Test", 800, 600);
1740 }
1744
1745 #[test]
1746 fn test_mouse_button_mapping() {
1747 assert_eq!(0, 0); assert_eq!(1, 1); assert_eq!(2, 2); }
1752
1753 #[cfg(feature = "migui")]
1758 #[test]
1759 fn test_migui_backend_exists() {
1760 let _ = RyditGfx::new("Test", 800, 600);
1762 }
1764}