rust_raylib/
core.rs

1use crate::{drawing::DrawHandle, ffi, math::Vector2, texture::Image};
2
3use std::{
4    ffi::{CStr, CString},
5    marker::PhantomData,
6    sync::atomic::{AtomicBool, Ordering},
7    time::Duration,
8};
9
10pub use ffi::{
11    ConfigFlags, GamepadAxis, GamepadButton, Gesture, KeyboardKey, MouseButton, MouseCursor,
12    TraceLogLevel,
13};
14
15static INITIALIZED: AtomicBool = AtomicBool::new(false);
16
17/// Main raylib handle
18#[derive(Debug)]
19pub struct Raylib(PhantomData<*const ()>);
20
21impl Raylib {
22    /// Initialize window and OpenGL context
23    #[inline]
24    pub fn init_window(width: u32, height: u32, title: &str) -> Option<Self> {
25        if !INITIALIZED.load(Ordering::Relaxed) {
26            let title = CString::new(title).unwrap();
27
28            unsafe {
29                ffi::InitWindow(width as _, height as _, title.as_ptr());
30            }
31
32            if unsafe { ffi::IsWindowReady() } {
33                INITIALIZED.store(true, Ordering::Relaxed);
34
35                Some(Self(PhantomData))
36            } else {
37                None
38            }
39        } else {
40            None
41        }
42    }
43
44    /// Initialize window and OpenGL context with config flags
45    #[inline]
46    pub fn init_window_ex(
47        width: u32,
48        height: u32,
49        title: &str,
50        flags: ConfigFlags,
51    ) -> Option<Self> {
52        unsafe {
53            ffi::SetConfigFlags(flags.bits());
54        }
55
56        Self::init_window(width, height, title)
57    }
58
59    /// Check if Escape key or Close icon is pressed
60    #[inline]
61    pub fn window_should_close(&self) -> bool {
62        unsafe { ffi::WindowShouldClose() }
63    }
64
65    /// Close window and unload OpenGL context
66    #[inline]
67    pub fn close_window(self) {
68        drop(self)
69    }
70
71    /// Check if window is currently fullscreen
72    #[inline]
73    pub fn is_window_fullscreen(&self) -> bool {
74        unsafe { ffi::IsWindowFullscreen() }
75    }
76
77    /// Check if window is currently hidden (only PLATFORM_DESKTOP)
78    #[inline]
79    pub fn is_window_hidden(&self) -> bool {
80        unsafe { ffi::IsWindowHidden() }
81    }
82
83    /// Check if window is currently minimized (only PLATFORM_DESKTOP)
84    #[inline]
85    pub fn is_window_minimized(&self) -> bool {
86        unsafe { ffi::IsWindowMinimized() }
87    }
88
89    /// Check if window is currently maximized (only PLATFORM_DESKTOP)
90    #[inline]
91    pub fn is_window_maximized(&self) -> bool {
92        unsafe { ffi::IsWindowMaximized() }
93    }
94
95    /// Check if window is currently focused (only PLATFORM_DESKTOP)
96    #[inline]
97    pub fn is_window_focused(&self) -> bool {
98        unsafe { ffi::IsWindowFocused() }
99    }
100
101    /// Check if window has been resized last frame
102    #[inline]
103    pub fn is_window_resized(&self) -> bool {
104        unsafe { ffi::IsWindowResized() }
105    }
106
107    /// Check if one specific window flag is enabled
108    #[inline]
109    pub fn is_window_state(&self, flag: ConfigFlags) -> bool {
110        unsafe { ffi::IsWindowState(flag.bits()) }
111    }
112
113    /// Set window configuration state using flags (only PLATFORM_DESKTOP)
114    #[inline]
115    pub fn set_window_state(&mut self, flags: ConfigFlags) {
116        unsafe { ffi::SetWindowState(flags.bits()) }
117    }
118
119    /// Clear window configuration state flags
120    #[inline]
121    pub fn clear_window_state(&mut self, flags: ConfigFlags) {
122        unsafe { ffi::ClearWindowState(flags.bits()) }
123    }
124
125    /// Toggle window state: fullscreen/windowed (only PLATFORM_DESKTOP)
126    #[inline]
127    pub fn toggle_fullscreen(&mut self) {
128        unsafe { ffi::ToggleFullscreen() }
129    }
130
131    /// Set window state: maximized, if resizable (only PLATFORM_DESKTOP)
132    #[inline]
133    pub fn maximize_window(&mut self) {
134        unsafe { ffi::MaximizeWindow() }
135    }
136
137    /// Set window state: minimized, if resizable (only PLATFORM_DESKTOP)
138    #[inline]
139    pub fn minimize_window(&mut self) {
140        unsafe { ffi::MinimizeWindow() }
141    }
142
143    /// Set window state: not minimized/maximized (only PLATFORM_DESKTOP)
144    #[inline]
145    pub fn restore_window(&mut self) {
146        unsafe { ffi::RestoreWindow() }
147    }
148
149    /// Set icon for window (single image, RGBA 32bit, only PLATFORM_DESKTOP)
150    #[inline]
151    pub fn set_window_icon(&mut self, image: &Image) {
152        unsafe { ffi::SetWindowIcon(image.raw.clone()) }
153    }
154
155    /// Set icon for window (multiple images, RGBA 32bit, only PLATFORM_DESKTOP)
156    #[inline]
157    pub fn set_window_icons(&mut self, images: &[&Image]) {
158        let mut images: Vec<_> = images.iter().map(|img| img.raw.clone()).collect();
159
160        unsafe { ffi::SetWindowIcons(images.as_mut_ptr(), images.len() as _) }
161    }
162
163    /// Set title for window (only PLATFORM_DESKTOP)
164    #[inline]
165    pub fn set_window_title(&mut self, title: &str) {
166        let title = CString::new(title).unwrap();
167
168        unsafe { ffi::SetWindowTitle(title.as_ptr()) }
169    }
170
171    /// Set window position on screen (only PLATFORM_DESKTOP)
172    #[inline]
173    pub fn set_window_position(&mut self, x: i32, y: i32) {
174        unsafe { ffi::SetWindowPosition(x, y) }
175    }
176
177    /// Set monitor for the current window (fullscreen mode)
178    #[inline]
179    pub fn set_window_monitor(&mut self, monitor: u32) {
180        unsafe { ffi::SetWindowMonitor(monitor as _) }
181    }
182
183    /// Set window minimum dimensions (for FLAG_WINDOW_RESIZABLE)
184    #[inline]
185    pub fn set_window_min_size(&mut self, width: u32, height: u32) {
186        unsafe { ffi::SetWindowMinSize(width as _, height as _) }
187    }
188
189    /// Set window dimensions
190    #[inline]
191    pub fn set_window_size(&mut self, width: u32, height: u32) {
192        unsafe { ffi::SetWindowSize(width as _, height as _) }
193    }
194
195    /// Set window opacity [0.0f..1.0f] (only PLATFORM_DESKTOP)
196    #[inline]
197    pub fn set_window_opacity(&mut self, opacity: f32) {
198        unsafe { ffi::SetWindowOpacity(opacity) }
199    }
200
201    /// Get native window handle
202    #[inline]
203    pub fn get_window_handle(&self) -> *mut core::ffi::c_void {
204        unsafe { ffi::GetWindowHandle() }
205    }
206
207    /// Get current screen width
208    #[inline]
209    pub fn get_screen_width(&self) -> u32 {
210        unsafe { ffi::GetScreenWidth() as _ }
211    }
212
213    /// Get current screen height
214    #[inline]
215    pub fn get_screen_height(&self) -> u32 {
216        unsafe { ffi::GetScreenHeight() as _ }
217    }
218
219    /// Get current render width (it considers HiDPI)
220    #[inline]
221    pub fn get_render_width(&self) -> u32 {
222        unsafe { ffi::GetRenderWidth() as _ }
223    }
224
225    /// Get current render height (it considers HiDPI)
226    #[inline]
227    pub fn get_render_height(&self) -> u32 {
228        unsafe { ffi::GetRenderHeight() as _ }
229    }
230
231    /// Get number of connected monitors
232    #[inline]
233    pub fn get_monitor_count(&self) -> u32 {
234        unsafe { ffi::GetMonitorCount() as _ }
235    }
236
237    /// Get current connected monitor
238    #[inline]
239    pub fn get_current_monitor(&self) -> u32 {
240        unsafe { ffi::GetCurrentMonitor() as _ }
241    }
242
243    /// Get specified monitor position
244    #[inline]
245    pub fn get_monitor_position(&self, monitor: u32) -> Vector2 {
246        unsafe { ffi::GetMonitorPosition(monitor as _).into() }
247    }
248
249    /// Get specified monitor width (current video mode used by monitor)
250    #[inline]
251    pub fn get_monitor_width(&self, monitor: u32) -> u32 {
252        unsafe { ffi::GetMonitorWidth(monitor as _) as _ }
253    }
254
255    /// Get specified monitor height (current video mode used by monitor)
256    #[inline]
257    pub fn get_monitor_height(&self, monitor: u32) -> u32 {
258        unsafe { ffi::GetMonitorHeight(monitor as _) as _ }
259    }
260
261    /// Get specified monitor physical width in millimetres
262    #[inline]
263    pub fn get_monitor_physical_width(&self, monitor: u32) -> u32 {
264        unsafe { ffi::GetMonitorPhysicalWidth(monitor as _) as _ }
265    }
266
267    /// Get specified monitor physical height in millimetres
268    #[inline]
269    pub fn get_monitor_physical_height(&self, monitor: u32) -> u32 {
270        unsafe { ffi::GetMonitorPhysicalHeight(monitor as _) as _ }
271    }
272
273    /// Get specified monitor refresh rate
274    #[inline]
275    pub fn get_monitor_refresh_rate(&self, monitor: u32) -> u32 {
276        unsafe { ffi::GetMonitorRefreshRate(monitor as _) as _ }
277    }
278
279    /// Get window position XY on monitor
280    #[inline]
281    pub fn get_window_position(&self) -> Vector2 {
282        unsafe { ffi::GetWindowPosition().into() }
283    }
284
285    /// Get window scale DPI factor
286    #[inline]
287    pub fn get_window_scale_dpi(&self) -> Vector2 {
288        unsafe { ffi::GetWindowScaleDPI().into() }
289    }
290
291    /// Get the human-readable, UTF-8 encoded name of the primary monitor
292    #[inline]
293    pub fn get_monitor_name(&self, monitor: u32) -> String {
294        let name = unsafe { ffi::GetMonitorName(monitor as _) };
295
296        if name.is_null() {
297            String::new()
298        } else {
299            unsafe { CStr::from_ptr(name) }
300                .to_string_lossy()
301                .into_owned()
302        }
303    }
304
305    /// Set clipboard text content
306    #[inline]
307    pub fn set_clipboard_text(&mut self, text: &str) {
308        let text = CString::new(text).unwrap();
309
310        unsafe { ffi::SetClipboardText(text.as_ptr()) }
311    }
312
313    /// Get clipboard text content
314    #[inline]
315    pub fn get_clipboard_text(&self) -> String {
316        let text = unsafe { ffi::GetClipboardText() };
317
318        if text.is_null() {
319            String::new()
320        } else {
321            unsafe { CStr::from_ptr(text) }
322                .to_string_lossy()
323                .into_owned()
324        }
325    }
326
327    /// Enable waiting for events on EndDrawing(), no automatic event polling
328    #[inline]
329    pub fn enable_event_waiting(&mut self) {
330        unsafe { ffi::EnableEventWaiting() }
331    }
332
333    /// Disable waiting for events on EndDrawing(), automatic events polling
334    #[inline]
335    pub fn disable_event_waiting(&mut self) {
336        unsafe { ffi::DisableEventWaiting() }
337    }
338
339    /// Swap back buffer with front buffer (screen drawing)
340    /// NOTE: Those functions are intended for advance users that want full control over the frame processing
341    #[inline]
342    pub fn swap_screen_buffer(&mut self) {
343        unsafe { ffi::SwapScreenBuffer() }
344    }
345
346    /// Register all input events
347    /// NOTE: Those functions are intended for advance users that want full control over the frame processing
348    #[inline]
349    pub fn poll_input_events(&mut self) {
350        unsafe { ffi::PollInputEvents() }
351    }
352
353    /// Wait for some time (halt program execution)
354    /// NOTE: Those functions are intended for advance users that want full control over the frame processing
355    #[inline]
356    pub fn wait_time(&mut self, duration: Duration) {
357        unsafe { ffi::WaitTime(duration.as_secs_f64()) }
358    }
359
360    /// Shows cursor
361    #[inline]
362    pub fn show_cursor(&mut self) {
363        unsafe { ffi::ShowCursor() }
364    }
365
366    /// Hides cursor
367    #[inline]
368    pub fn hide_cursor(&mut self) {
369        unsafe { ffi::HideCursor() }
370    }
371
372    /// Check if cursor is not visible
373    #[inline]
374    pub fn is_cursor_hidden(&self) -> bool {
375        unsafe { ffi::IsCursorHidden() }
376    }
377
378    /// Enables cursor (unlock cursor)
379    #[inline]
380    pub fn enable_cursor(&mut self) {
381        unsafe { ffi::EnableCursor() }
382    }
383
384    /// Disables cursor (lock cursor)
385    #[inline]
386    pub fn disable_cursor(&mut self) {
387        unsafe { ffi::DisableCursor() }
388    }
389
390    /// Check if cursor is on the screen
391    #[inline]
392    pub fn is_cursor_on_screen(&self) -> bool {
393        unsafe { ffi::IsCursorOnScreen() }
394    }
395
396    /// Set target FPS (maximum)
397    #[inline]
398    pub fn set_target_fps(&mut self, fps: u32) {
399        unsafe { ffi::SetTargetFPS(fps as _) }
400    }
401
402    /// Get current FPS
403    #[inline]
404    pub fn get_fps(&self) -> u32 {
405        unsafe { ffi::GetFPS() as _ }
406    }
407
408    /// Get time for last frame drawn (delta time)
409    #[inline]
410    pub fn get_frame_time(&self) -> Duration {
411        Duration::from_secs_f32(unsafe { ffi::GetFrameTime() })
412    }
413
414    /// Get elapsed time since InitWindow()
415    #[inline]
416    pub fn get_time(&self) -> Duration {
417        Duration::from_secs_f64(unsafe { ffi::GetTime() })
418    }
419
420    /// Get a random value between min and max (both included)
421    #[inline]
422    pub fn get_random_value(&self, min: i32, max: i32) -> i32 {
423        unsafe { ffi::GetRandomValue(min, max) }
424    }
425
426    /// Set the seed for the random number generator
427    #[inline]
428    pub fn set_random_seed(&mut self, seed: u32) {
429        unsafe { ffi::SetRandomSeed(seed) }
430    }
431
432    /// Takes a screenshot of current screen (file_name extension defines format)
433    #[inline]
434    pub fn take_screenshot(&mut self, file_name: &str) {
435        let file_name = CString::new(file_name).unwrap();
436
437        unsafe { ffi::TakeScreenshot(file_name.as_ptr()) }
438    }
439
440    /// Open URL with default system browser (if available)
441    #[inline]
442    pub fn open_url(&self, url: &str) {
443        let url = CString::new(url).unwrap();
444
445        unsafe { ffi::OpenURL(url.as_ptr()) }
446    }
447
448    /// Check if a file has been dropped into window
449    #[inline]
450    pub fn is_file_dropped(&self) -> bool {
451        unsafe { ffi::IsFileDropped() }
452    }
453
454    /// Load dropped filepaths
455    #[inline]
456    pub fn get_dropped_files(&self) -> Vec<String> {
457        let path_list = unsafe { ffi::LoadDroppedFiles() };
458        let mut paths = Vec::new();
459
460        for i in 0..(path_list.count as usize) {
461            let path = unsafe { CStr::from_ptr(path_list.paths.add(i).read()) };
462
463            paths.push(path.to_string_lossy().into_owned());
464        }
465
466        unsafe {
467            ffi::UnloadDroppedFiles(path_list);
468        }
469
470        paths
471    }
472
473    /// Check if a key has been pressed once
474    #[inline]
475    pub fn is_key_pressed(&self, key: KeyboardKey) -> bool {
476        unsafe { ffi::IsKeyPressed(key as _) }
477    }
478
479    /// Check if a key is being pressed
480    #[inline]
481    pub fn is_key_down(&self, key: KeyboardKey) -> bool {
482        unsafe { ffi::IsKeyDown(key as _) }
483    }
484
485    /// Check if a key has been released once
486    #[inline]
487    pub fn is_key_released(&self, key: KeyboardKey) -> bool {
488        unsafe { ffi::IsKeyReleased(key as _) }
489    }
490
491    /// Check if a key is NOT being pressed
492    #[inline]
493    pub fn is_key_up(&self, key: KeyboardKey) -> bool {
494        unsafe { ffi::IsKeyUp(key as _) }
495    }
496
497    /// Set a custom key to exit program (default is ESC)
498    #[inline]
499    pub fn set_exit_key(&mut self, key: KeyboardKey) {
500        unsafe { ffi::SetExitKey(key as _) }
501    }
502
503    /// Get key pressed (keycode), call it multiple times for keys queued, returns [`KeyboardKey::Null`] when the queue is empty
504    #[inline]
505    pub fn get_key_pressed(&self) -> KeyboardKey {
506        unsafe { std::mem::transmute(ffi::GetKeyPressed()) }
507    }
508
509    /// Get char pressed (unicode), call it multiple times for chars queued, returns `None` when the queue is empty
510    #[inline]
511    pub fn get_char_pressed(&self) -> Option<char> {
512        let ch = unsafe { ffi::GetCharPressed() as u32 };
513
514        if ch != 0 {
515            char::from_u32(ch)
516        } else {
517            None
518        }
519    }
520
521    /// Check if a gamepad is available
522    #[inline]
523    pub fn is_gamepad_available(&self, gamepad: u32) -> bool {
524        unsafe { ffi::IsGamepadAvailable(gamepad as _) }
525    }
526
527    /// Get gamepad internal name id
528    #[inline]
529    pub fn get_gamepad_name(&self, gamepad: u32) -> String {
530        let name = unsafe { ffi::GetGamepadName(gamepad as _) };
531
532        if !name.is_null() {
533            let name = unsafe { CStr::from_ptr(name) };
534
535            name.to_string_lossy().into_owned()
536        } else {
537            String::new()
538        }
539    }
540
541    /// Check if a gamepad button has been pressed once
542    #[inline]
543    pub fn is_gamepad_button_pressed(&self, gamepad: u32, button: GamepadButton) -> bool {
544        unsafe { ffi::IsGamepadButtonPressed(gamepad as _, button as _) }
545    }
546
547    /// Check if a gamepad button is being pressed
548    #[inline]
549    pub fn is_gamepad_button_down(&self, gamepad: u32, button: GamepadButton) -> bool {
550        unsafe { ffi::IsGamepadButtonDown(gamepad as _, button as _) }
551    }
552
553    /// Check if a gamepad button has been released once
554    #[inline]
555    pub fn is_gamepad_button_released(&self, gamepad: u32, button: GamepadButton) -> bool {
556        unsafe { ffi::IsGamepadButtonReleased(gamepad as _, button as _) }
557    }
558
559    /// Check if a gamepad button is NOT being pressed
560    #[inline]
561    pub fn is_gamepad_button_up(&self, gamepad: u32, button: GamepadButton) -> bool {
562        unsafe { ffi::IsGamepadButtonUp(gamepad as _, button as _) }
563    }
564
565    /// Get the last gamepad button pressed
566    #[inline]
567    pub fn get_gamepad_button_pressed(&self) -> GamepadButton {
568        unsafe { std::mem::transmute(ffi::GetGamepadButtonPressed()) }
569    }
570
571    /// Get gamepad axis count for a gamepad
572    #[inline]
573    pub fn get_gamepad_axis_count(&self, gamepad: u32) -> u32 {
574        unsafe { ffi::GetGamepadAxisCount(gamepad as _) as _ }
575    }
576
577    /// Get axis movement value for a gamepad axis
578    #[inline]
579    pub fn get_gamepad_axis_movement(&self, gamepad: u32, axis: GamepadAxis) -> f32 {
580        unsafe { ffi::GetGamepadAxisMovement(gamepad as _, axis as _) }
581    }
582
583    /// Set internal gamepad mappings (SDL_GameControllerDB)
584    #[inline]
585    pub fn set_gamepad_mappings(&mut self, mappings: &str) -> i32 {
586        let mappings = CString::new(mappings).unwrap();
587
588        unsafe { ffi::SetGamepadMappings(mappings.as_ptr()) }
589    }
590
591    /// Check if a mouse button has been pressed once
592    #[inline]
593    pub fn is_mouse_button_pressed(&self, button: MouseButton) -> bool {
594        unsafe { ffi::IsMouseButtonPressed(button as _) }
595    }
596
597    /// Check if a mouse button is being pressed
598    #[inline]
599    pub fn is_mouse_button_down(&self, button: MouseButton) -> bool {
600        unsafe { ffi::IsMouseButtonDown(button as _) }
601    }
602
603    /// Check if a mouse button has been released once
604    #[inline]
605    pub fn is_mouse_button_released(&self, button: MouseButton) -> bool {
606        unsafe { ffi::IsMouseButtonReleased(button as _) }
607    }
608
609    /// Check if a mouse button is NOT being pressed
610    #[inline]
611    pub fn is_mouse_button_up(&self, button: MouseButton) -> bool {
612        unsafe { ffi::IsMouseButtonUp(button as _) }
613    }
614
615    /// Get mouse position X
616    #[inline]
617    pub fn get_mouse_x(&self) -> i32 {
618        unsafe { ffi::GetMouseX() }
619    }
620
621    /// Get mouse position Y
622    #[inline]
623    pub fn get_mouse_y(&self) -> i32 {
624        unsafe { ffi::GetMouseY() }
625    }
626
627    /// Get mouse position XY
628    #[inline]
629    pub fn get_mouse_position(&self) -> Vector2 {
630        unsafe { ffi::GetMousePosition().into() }
631    }
632
633    /// Get mouse delta between frames
634    #[inline]
635    pub fn get_mouse_delta(&self) -> Vector2 {
636        unsafe { ffi::GetMouseDelta().into() }
637    }
638
639    /// Set mouse position XY
640    #[inline]
641    pub fn set_mouse_position(&mut self, x: i32, y: i32) {
642        unsafe { ffi::SetMousePosition(x, y) }
643    }
644
645    /// Set mouse offset
646    #[inline]
647    pub fn set_mouse_offset(&mut self, offset_x: i32, offset_y: i32) {
648        unsafe { ffi::SetMouseOffset(offset_x, offset_y) }
649    }
650
651    /// Set mouse scaling
652    #[inline]
653    pub fn set_mouse_scale(&mut self, scale_x: f32, scale_y: f32) {
654        unsafe { ffi::SetMouseScale(scale_x, scale_y) }
655    }
656
657    /// Get mouse wheel movement for X or Y, whichever is larger
658    #[inline]
659    pub fn get_mouse_wheel_move(&self) -> f32 {
660        unsafe { ffi::GetMouseWheelMove() }
661    }
662
663    /// Get mouse wheel movement for both X and Y
664    #[inline]
665    pub fn get_mouse_wheel_move_vec(&self) -> Vector2 {
666        unsafe { ffi::GetMouseWheelMoveV().into() }
667    }
668
669    /// Set mouse cursor
670    #[inline]
671    pub fn set_mouse_cursor(&mut self, cursor: MouseCursor) {
672        unsafe { ffi::SetMouseCursor(cursor as _) }
673    }
674
675    /// Get touch position X for touch point 0 (relative to screen size)
676    #[inline]
677    pub fn get_touch_x(&self) -> i32 {
678        unsafe { ffi::GetTouchX() }
679    }
680
681    /// Get touch position Y for touch point 0 (relative to screen size)
682    #[inline]
683    pub fn get_touch_y(&self) -> i32 {
684        unsafe { ffi::GetTouchY() }
685    }
686
687    /// Get touch position XY for a touch point index (relative to screen size)
688    #[inline]
689    pub fn get_touch_position(&self, index: u32) -> Vector2 {
690        unsafe { ffi::GetTouchPosition(index as _).into() }
691    }
692
693    /// Get touch point identifier for given index
694    #[inline]
695    pub fn get_touch_point_id(&self, index: u32) -> u32 {
696        unsafe { ffi::GetTouchPointId(index as _) as _ }
697    }
698
699    /// Get number of touch points
700    #[inline]
701    pub fn get_touch_point_count(&self) -> u32 {
702        unsafe { ffi::GetTouchPointCount() as _ }
703    }
704
705    /// Enable a set of gestures using flags
706    #[inline]
707    pub fn set_gestures_enabled(&mut self, flags: Gesture) {
708        unsafe { ffi::SetGesturesEnabled(flags.bits()) }
709    }
710
711    /// Check if a gesture have been detected
712    #[inline]
713    pub fn is_gesture_detected(&self, gesture: Gesture) -> bool {
714        unsafe { ffi::IsGestureDetected(gesture.bits() as _) }
715    }
716
717    /// Get latest detected gesture
718    #[inline]
719    pub fn get_gesture_detected(&self) -> Gesture {
720        unsafe { Gesture(ffi::GetGestureDetected() as _) }
721    }
722
723    /// Get gesture hold time
724    #[inline]
725    pub fn get_gesture_hold_duration(&self) -> Duration {
726        Duration::from_micros(unsafe { ffi::GetGestureHoldDuration() * 1000. } as u64)
727    }
728
729    /// Get gesture drag vector
730    #[inline]
731    pub fn get_gesture_drag_vector(&self) -> Vector2 {
732        unsafe { ffi::GetGestureDragVector().into() }
733    }
734
735    /// Get gesture drag angle
736    #[inline]
737    pub fn get_gesture_drag_angle(&self) -> f32 {
738        unsafe { ffi::GetGestureDragAngle() }
739    }
740
741    /// Get gesture pinch delta
742    #[inline]
743    pub fn get_gesture_pinch_vector(&self) -> Vector2 {
744        unsafe { ffi::GetGesturePinchVector().into() }
745    }
746
747    /// Get gesture pinch angle
748    #[inline]
749    pub fn get_gesture_pinch_angle(&self) -> f32 {
750        unsafe { ffi::GetGesturePinchAngle() }
751    }
752
753    /// Setup canvas (framebuffer) to start drawing
754    #[inline]
755    pub fn begin_drawing(&mut self) -> DrawHandle {
756        unsafe {
757            ffi::BeginDrawing();
758        }
759
760        DrawHandle(self)
761    }
762
763    /// Set the current threshold (minimum) log level (for raylib's own logging)
764    #[inline]
765    pub fn set_trace_log_level(&mut self, level: TraceLogLevel) {
766        unsafe { ffi::SetTraceLogLevel(level as _) }
767    }
768}
769
770impl Drop for Raylib {
771    #[inline]
772    fn drop(&mut self) {
773        unsafe { ffi::CloseWindow() }
774    }
775}