Skip to main content

flake/
prelude.rs

1#![allow(unused)]
2
3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4
5pub use crate::camera::camera2d::Camera2D;
6pub use crate::camera::render_target::RenderTarget;
7use crate::draw_state::shapes::Shape;
8pub use crate::draw_state::shapes::color::*;
9pub use crate::end_frame;
10use crate::global::{PENDING_CONFIG, STATE, ctx};
11pub use crate::misc::flake_image::Image;
12use crate::misc::font::Font;
13pub use crate::misc::math::*;
14pub use crate::misc::rect::Rect;
15use crate::misc::span::RichtextSection;
16pub use crate::misc::span::Span;
17pub use crate::misc::timer::Timer;
18pub use crate::misc::*;
19use crate::model::instance::Instance;
20pub use crate::model::texture::DrawTextureParams;
21pub use crate::model::texture::FilterType;
22use crate::model::texture::{GpuTexture, Texture};
23pub use crate::runtime::next_frame::next_frame;
24pub use crate::{FlakeResult, flake};
25use image::{DynamicImage, GenericImageView, ImageBuffer, Rgb, Rgba};
26use std::borrow::Borrow;
27use std::sync::{Arc, Mutex};
28use wgpu::{CommandEncoder, Device, Queue, SurfaceConfiguration, TextureView};
29pub use winit::event::MouseButton;
30pub use winit::event::WindowEvent;
31pub use winit::keyboard::KeyCode;
32#[cfg(target_os = "windows")]
33use winit::platform::windows::WindowExtWindows;
34use winit::window::Window;
35pub use winit::window::{CursorIcon, WindowButtons, WindowLevel};
36// -- Out-facing API --------------------------------------------------------------------------------------------------------------
37
38/// Exits the running application, must be called while running.
39///
40/// # Examples
41///
42/// ```
43/// flake_quit();
44/// ```
45pub fn flake_quit() {
46    ctx(|s| s.exit())
47}
48
49/// Sleeps (waits) for a set amount of seconds.
50/// (Will pause the window thread as well)
51/// App may become "not responding" if time is too high.
52/// Good for games like tetris/snake.
53///
54/// # Examples
55///
56/// ```
57/// flake_sleep(0.1);
58/// ```
59pub fn flake_sleep(seconds: f32) {
60    std::thread::sleep(std::time::Duration::from_secs_f32(seconds));
61}
62
63/// Creates a `Timer` whose time goes down each frame. Can be paused. Check `Timer` docs for more info.
64///
65/// # Examples
66///
67/// ```
68/// let mut my_timer = add_timer(Timer::new(5.0));
69///
70/// my_timer.on_completed(|| {
71///     println!("Timer got completed");
72/// });
73/// ```
74pub fn add_timer(timer: Timer) -> Timer {
75    if STATE.get().is_some() {
76        return ctx(|s| {
77            if !s.timers.contains(&timer) {
78                s.add_timer(timer.clone());
79            }
80            timer
81        });
82    }
83
84    PENDING_CONFIG.with_borrow_mut(|s| {
85        if !s.timers.contains(&timer) {
86            s.timers.push(timer.clone())
87        }
88    });
89
90    timer
91}
92
93/// Gets the winit window used by the application
94///
95/// # Examples
96///
97/// ```
98/// let win = get_window();
99/// win.set_transparent(true);
100/// ```
101pub fn get_window() -> Arc<Window> {
102    ctx(|s| s.get_window())
103}
104
105/// Gets the wgpu device used by the application
106///
107/// # Examples
108///
109/// ```
110/// let device = get_device();
111/// ```
112pub fn get_device() -> Arc<Device> {
113    ctx(|s| s.device.clone())
114}
115
116/// Gets the wgpu queue used by the application
117///
118/// # Examples
119///
120/// ```
121/// let queue = get_queue();
122/// ```
123pub fn get_queue() -> Queue {
124    ctx(|s| s.queue.clone())
125}
126
127/// Adds a post render hook to the application.
128/// Binds a closure which will run before submitting the queue.
129///
130/// # Examples
131///
132/// ```
133/// let queue = get_queue();
134/// ```
135pub fn add_post_render_hook(
136    hook: impl FnMut(&Device, &Queue, &mut CommandEncoder, &TextureView, (u32, u32)) + 'static,
137) {
138    ctx(|s| s.post_render_hooks.push(Box::new(hook)));
139}
140
141/// Gets the wgpu surface config used by the application
142///
143/// # Examples
144///
145/// ```
146/// let config = get_surface_config();
147/// ```
148pub fn get_surface_config() -> Arc<Mutex<SurfaceConfiguration>> {
149    ctx(|s| s.config.clone())
150}
151
152/// Gets the window events that happened this frame
153///
154/// # Examples
155///
156/// ```
157/// let events = get_window_events();
158/// ```
159pub fn get_window_events() -> Vec<WindowEvent> {
160    ctx(|s| s.event_list.clone())
161}
162
163/// Sets whether window catches mouse events.
164pub fn set_window_passthrough(passthrough: bool) {
165    if STATE.get().is_some() {
166        return ctx(|s| s.set_window_passthrough(passthrough));
167    }
168
169    PENDING_CONFIG.with_borrow_mut(|s| s.window_passthrough = Some(passthrough));
170}
171
172/// Sets whether the window is AlwaysOnTop, AlwaysOnBottom, or Normal
173pub fn set_window_level(level: WindowLevel) {
174    if STATE.get().is_some() {
175        return ctx(|s| s.set_window_level(level));
176    }
177
178    PENDING_CONFIG.with_borrow_mut(|s| s.window_level = Some(level));
179}
180
181/// Sets which window buttons are enabled. Any button not included is disabled
182/// (e.g. `WindowButtons::CLOSE` leaves only the close button).
183pub fn set_window_enabled_buttons(window_buttons: WindowButtons) {
184    ctx(|s| s.get_window().set_enabled_buttons(window_buttons));
185}
186
187/// Sets whether the app is shown or not shown (skipped) in the taskbar
188pub fn set_skip_taskbar(skip: bool) {
189    if STATE.get().is_some() {
190        #[cfg(target_os = "windows")]
191        return ctx(|s| s.window.set_skip_taskbar(skip));
192    }
193
194    PENDING_CONFIG.with_borrow_mut(|s| s.skip_taskbar = Some(skip));
195}
196
197/// Sets whether the window is transparent.
198/// **Run this before `flake::run()`** as it might not work after the window has been created.
199pub fn set_window_transparent(transparent: bool) {
200    if STATE.get().is_some() {
201        return get_window().set_transparent(transparent);
202    }
203
204    PENDING_CONFIG.with_borrow_mut(|s| s.window_transparent = Some(transparent));
205}
206
207/// Sets whether the window decorations (titlebar, border, etc.) are enabled
208pub fn set_window_decorations(enabled: bool) {
209    if STATE.get().is_some() {
210        return get_window().set_decorations(enabled);
211    }
212
213    PENDING_CONFIG.with_borrow_mut(|s| s.window_decorations = Some(enabled));
214}
215
216// -- Window --------------------------------------------------------------------------------------------------------------
217
218/// Sets the title of the window.
219///
220/// # Examples
221///
222/// ```
223/// set_window_title("Hello");
224/// ```
225pub fn set_window_title(title: &str) {
226    if STATE.get().is_some() {
227        return ctx(|s| s.set_window_title(title));
228    }
229
230    PENDING_CONFIG.with_borrow_mut(|s| s.window_title = Some(title.into()));
231}
232
233/// Sets whether the window is visible or not.
234///
235/// # Examples
236///
237/// ```
238/// set_window_visible(false); // hides the window
239/// set_window_visible(true); // shows the window
240/// ```
241pub fn set_window_visible(visible: bool) {
242    if STATE.get().is_some() {
243        return ctx(|s| s.set_window_visible(visible));
244    }
245
246    PENDING_CONFIG.with_borrow_mut(|s| s.window_visible = Some(visible));
247}
248
249/// Sets the icon of the window.
250///
251/// # Examples
252///
253/// ```
254/// set_window_icon("path_to_icon");
255/// ```
256pub fn set_window_icon(path: &str) {
257    let img = image::open(path)
258        .expect("image icon does not exist at path")
259        .into_rgba8();
260    let (width, height) = img.dimensions();
261    let rgba = img.into_raw();
262
263    if STATE.get().is_some() {
264        return ctx(|s| s.set_window_icon(rgba, width, height));
265    }
266
267    PENDING_CONFIG.with_borrow_mut(|s| s.window_icon = Some((rgba, width, height)));
268}
269
270/// Sets the window icon from encoded image bytes (PNG, etc.). Panics if the bytes aren't a valid image.
271pub fn set_window_icon_bytes(bytes: &[u8]) {
272    let img = image::load_from_memory(bytes)
273        .expect("image icon does not exist at path")
274        .into_rgba8();
275    let (width, height) = img.dimensions();
276    let rgba = img.into_raw();
277
278    if STATE.get().is_some() {
279        return ctx(|s| s.set_window_icon(rgba, width, height));
280    }
281
282    PENDING_CONFIG.with_borrow_mut(|s| s.window_icon = Some((rgba, width, height)));
283}
284
285/// Sets position X of the window.
286///
287/// # Examples
288///
289/// ```
290/// set_window_x(500);
291/// ```
292pub fn set_window_x(x: i32) {
293    if STATE.get().is_some() {
294        return ctx(|s| s.set_window_x(x));
295    }
296
297    PENDING_CONFIG.with_borrow_mut(|s| s.window_x = Some(x));
298}
299
300/// Sets position Y of the window.
301///
302/// # Examples
303///
304/// ```
305/// set_window_y(500);
306/// ```
307pub fn set_window_y(y: i32) {
308    if STATE.get().is_some() {
309        return ctx(|s| s.set_window_y(y));
310    }
311
312    PENDING_CONFIG.with_borrow_mut(|s| s.window_y = Some(y));
313}
314
315/// Sets position of the window.
316///
317/// # Examples
318///
319/// ```
320/// set_window_position(500, 500);
321/// ```
322pub fn set_window_position(x: i32, y: i32) {
323    set_window_x(x);
324    set_window_y(y);
325}
326
327/// Gets width of the window
328pub fn window_width() -> f32 {
329    ctx(|s| s.window_width())
330}
331
332/// Gets height of the window
333pub fn window_height() -> f32 {
334    ctx(|s| s.window_height())
335}
336
337/// Gets size of the window
338pub fn window_size() -> Vector2 {
339    ctx(|s| Vector2::new(s.window_width(), s.window_height()))
340}
341
342/// Gets position of the window
343pub fn window_position() -> (f32, f32) {
344    ctx(|s| s.window_position())
345}
346
347/// Gets position of the window as Vector2<f32>
348pub fn window_position_vec2() -> Vector2 {
349    ctx(|s| s.window_position().into())
350}
351
352/// Gets X position of the window
353pub fn window_x() -> f32 {
354    ctx(|s| s.window_x())
355}
356
357/// Gets Y position of the window
358pub fn window_y() -> f32 {
359    ctx(|s| s.window_y())
360}
361
362/// Sets width of the window.
363///
364/// # Examples
365///
366/// ```
367/// set_window_width(500);
368/// ```
369pub fn set_window_width(w: u32) {
370    if STATE.get().is_some() {
371        return ctx(|s| s.set_window_w(w));
372    }
373
374    PENDING_CONFIG.with_borrow_mut(|s| s.window_width = Some(w));
375}
376
377/// Sets height of the window.
378///
379/// # Examples
380///
381/// ```
382/// set_window_height(500);
383/// ```
384pub fn set_window_height(h: u32) {
385    if STATE.get().is_some() {
386        return ctx(|s| s.set_window_h(h));
387    }
388
389    PENDING_CONFIG.with_borrow_mut(|s| s.window_height = Some(h));
390}
391
392/// Sets size of the window.
393///
394/// # Examples
395///
396/// ```
397/// set_window_size(500, 500);
398/// ```
399pub fn set_window_size(w: u32, h: u32) {
400    if STATE.get().is_some() {
401        return ctx(|s| s.set_window_size(w, h));
402    }
403
404    PENDING_CONFIG.with_borrow_mut(|s| {
405        s.window_width = Some(w);
406        s.window_height = Some(h);
407    });
408}
409
410/// Sets whether the window can be resized using the resize handles.
411pub fn set_window_resizable(resizeable: bool) {
412    ctx(|s| s.window.set_resizable(resizeable));
413}
414
415// -- TIME --------------------------------------------------------------------------------------------------------------
416
417/// Gets the frames per second of the application.
418/// (Limited by target framerate & fps cap). Uncap the FPS using `set_fps_capped(false)`.
419///
420/// # Examples
421///
422/// ```
423/// println!("{}", get_fps());
424/// ```
425pub fn get_fps() -> f32 {
426    ctx(|s| s.get_fps())
427}
428
429/// Sets target FPS of the application (Uses screen refresh rate by default).
430///
431/// # Examples
432///
433/// ```
434/// set_target_fps(60);
435/// ```
436pub fn set_target_fps(fps: usize) {
437    if STATE.get().is_some() {
438        return ctx(|s| s.set_target_fps(fps));
439    }
440
441    PENDING_CONFIG.with_borrow_mut(|s| s.target_fps = Some(fps));
442}
443
444/// Caps/unlocks the FPS of the application. (Capped by default)
445///
446/// # Examples
447///
448/// ```
449/// set_fps_capped(false); // uncaps the FPS
450/// set_fps_capped(true); // caps the FPS to target FPS
451/// ```
452pub fn set_fps_capped(capped: bool) {
453    if STATE.get().is_some() {
454        return ctx(|s| s.set_fps_capped(capped));
455    }
456
457    PENDING_CONFIG.with_borrow_mut(|s| s.fps_capped = Some(capped));
458}
459
460/// Gets the time taken since last frame in seconds.
461///
462/// # Examples
463///
464/// ```
465/// println!("{}", get_frame_time());
466/// ```
467
468pub fn get_frame_time() -> f32 {
469    ctx(|s| s.get_frame_time())
470}
471
472/// Gets the amount of frames that have gone by since the start of the application.
473///
474/// # Examples
475///
476/// ```
477/// println!("{}", get_frames());
478/// ```
479
480pub fn get_frames() -> usize {
481    ctx(|s| s.get_frames())
482}
483
484// -- INPUT --------------------------------------------------------------------------------------------------------------
485
486/// Returns the window-relative mouse x and y position in a tuple.
487///
488/// # Examples
489///
490/// ```
491/// let (mx, my) = mouse_position();
492/// ```
493pub fn mouse_position() -> (f32, f32) {
494    ctx(|s| s.mouse_state.get_position().into())
495}
496
497/// Returns the window-relative mouse x and y position in a `Vector2`.
498///
499/// # Examples
500///
501/// ```
502/// let pos = mouse_position_vec2();
503/// println!("{}, {}", pos.x, pos.y);
504/// ```
505pub fn mouse_position_vec2() -> Vector2 {
506    ctx(|s| s.mouse_state.get_position())
507}
508
509/// Returns the mouse x and y position on the screen instead of window-relative as Vector2.
510pub fn mouse_screen_position_vec2() -> Vector2 {
511    ctx(|s| s.mouse_state.get_screen_position())
512}
513
514/// Returns the mouse x and y position on the screen instead of window-relative.
515pub fn mouse_screen_position() -> (f32, f32) {
516    ctx(|s| s.mouse_state.get_screen_position().into())
517}
518
519/// Returns the mouse scroll direction this frame (line delta).
520/// (You might need to multiply this by something like 20).
521///
522/// # Examples
523///
524/// ```
525/// let scroll_y = mouse_wheel().y;
526/// ```
527pub fn mouse_wheel() -> Vector2 {
528    ctx(|s| s.mouse_state.get_mouse_wheel())
529}
530
531/// Set the mouse cursor icon.
532///
533/// ## Examples
534///
535/// ```
536/// set_mouse_icon(CursorIcon::Pointer)
537/// ```
538pub fn set_mouse_icon(cursor_icon: CursorIcon) {
539    ctx(|s| s.window.set_cursor(cursor_icon))
540}
541/// Requests keyboard focus for the window.
542pub fn focus_window() {
543    get_window().focus_window();
544}
545
546/// Checks if a `MouseButton` is being held.
547///
548/// # Examples
549///
550/// ```
551/// if is_mouse_button_down(MouseButton::Left) {
552///     println!("Left mouse button is being held");
553/// }
554/// ```
555
556pub fn is_mouse_button_down(btn: MouseButton) -> bool {
557    ctx(|s| s.mouse_state.is_button_down(btn))
558}
559
560/// Checks if a `MouseButton` was just clicked this frame.
561///
562/// # Examples
563///
564/// ```
565/// if is_mouse_button_pressed(MouseButton::Left) {
566///     println!("User clicked left mouse button once");
567/// }
568/// ```
569pub fn is_mouse_button_pressed(btn: MouseButton) -> bool {
570    ctx(|s| s.mouse_state.is_button_pressed(btn))
571}
572
573/// Checks if a `MouseButton` was just released this frame.
574///
575/// # Examples
576///
577/// ```
578/// if is_mouse_button_released(MouseButton::Left) {
579///     println!("User let go of left mouse button once");
580/// }
581/// ```
582
583pub fn is_mouse_button_released(btn: MouseButton) -> bool {
584    ctx(|s| s.mouse_state.is_button_released(btn))
585}
586
587/// Checks if a key on the keyboard is being held.
588///
589/// # Examples
590///
591/// ```
592/// println!("is Space being held: {}", is_key_down(KeyCode::Space));
593/// ```
594
595pub fn is_key_down(key: KeyCode) -> bool {
596    ctx(|s| s.keyboard_state.is_key_down(key))
597}
598
599/// Checks if a key on the keyboard was just clicked.
600///
601/// # Examples
602///
603/// ```
604/// if is_key_pressed(KeyCode::Space) {
605///     println!("User clicked Space once");
606/// }
607/// ```
608pub fn is_key_pressed(key: KeyCode) -> bool {
609    ctx(|s| s.keyboard_state.is_key_pressed(key))
610}
611
612/// Checks if a key on the keyboard was just released.
613///
614/// # Examples
615///
616/// ```
617/// if is_key_released(KeyCode::Space) {
618///     println!("User let go of Space");
619/// }
620/// ```
621pub fn is_key_released(key: KeyCode) -> bool {
622    ctx(|s| s.keyboard_state.is_key_released(key))
623}
624
625/// Returns -1.0 if only `left` is held, 1.0 if only `right` is held, otherwise 0.0.
626pub fn get_axis(left: KeyCode, right: KeyCode) -> f32 {
627    ctx(|s| match (is_key_down(left), is_key_down(right)) {
628        (true, false) => -1.0,
629        (false, true) => 1.0,
630        _ => 0.0,
631    })
632}
633
634/// Returns a direction from four keys. Up is -1.0 on Y (screen coordinates).
635/// The result is not normalized, so diagonals have length √2.
636pub fn get_vector(left: KeyCode, right: KeyCode, up: KeyCode, down: KeyCode) -> Vector2 {
637    ctx(|s| {
638        Vector2::new(
639            match (is_key_down(left), is_key_down(right)) {
640                (true, false) => -1.0,
641                (false, true) => 1.0,
642                _ => 0.0,
643            },
644            match (is_key_down(up), is_key_down(down)) {
645                (true, false) => -1.0,
646                (false, true) => 1.0,
647                _ => 0.0,
648            },
649        )
650    })
651}
652
653// -- GLOBAL INPUT (system-wide, works while unfocused) ----------------------------
654
655/// Window-relative mouse position, tracked system-wide (updates outside the window too).
656pub fn mouse_position_global() -> (f32, f32) {
657    ctx(|s| s.mouse_state.get_position_global().into())
658}
659
660pub fn mouse_position_vec2_global() -> Vector2 {
661    ctx(|s| s.mouse_state.get_position_global())
662}
663
664/// Screen-space mouse position, tracked system-wide.
665pub fn mouse_screen_position_global() -> (f32, f32) {
666    ctx(|s| s.mouse_state.get_screen_position_global().into())
667}
668
669pub fn mouse_screen_position_vec2_global() -> Vector2 {
670    ctx(|s| s.mouse_state.get_screen_position_global())
671}
672
673/// Scroll this frame, system-wide.
674pub fn mouse_wheel_global() -> Vector2 {
675    ctx(|s| s.mouse_state.get_mouse_wheel_global())
676}
677
678pub fn is_mouse_button_down_global(btn: MouseButton) -> bool {
679    ctx(|s| s.mouse_state.is_button_down_global(btn))
680}
681
682pub fn is_mouse_button_pressed_global(btn: MouseButton) -> bool {
683    ctx(|s| s.mouse_state.is_button_pressed_global(btn))
684}
685
686pub fn is_mouse_button_released_global(btn: MouseButton) -> bool {
687    ctx(|s| s.mouse_state.is_button_released_global(btn))
688}
689
690pub fn is_key_down_global(key: KeyCode) -> bool {
691    ctx(|s| s.keyboard_state.is_key_down_global(key))
692}
693
694pub fn is_key_pressed_global(key: KeyCode) -> bool {
695    ctx(|s| s.keyboard_state.is_key_pressed_global(key))
696}
697
698pub fn is_key_released_global(key: KeyCode) -> bool {
699    ctx(|s| s.keyboard_state.is_key_released_global(key))
700}
701
702/// Like `get_axis`, but from global key state.
703pub fn get_axis_global(left: KeyCode, right: KeyCode) -> f32 {
704    ctx(|s| {
705        match (
706            s.keyboard_state.is_key_down_global(left),
707            s.keyboard_state.is_key_down_global(right),
708        ) {
709            (true, false) => -1.0,
710            (false, true) => 1.0,
711            _ => 0.0,
712        }
713    })
714}
715
716/// Like `get_vector`, but from global key state. Up is -1.0 on Y.
717pub fn get_vector_global(left: KeyCode, right: KeyCode, up: KeyCode, down: KeyCode) -> Vector2 {
718    Vector2::new(
719        get_axis_global(left, right),
720        get_axis_global(up, down),
721    )
722}
723
724/// Application will block this key and swallow it before the rest of the OS can use it.
725/// Useful for global keyboard shortcuts. (May not work on all operating systems.)
726pub fn block_key(key: KeyCode)   { ctx(|s| s.block_key(key)) }
727
728/// Keys blocked with `block_key()` will be unblocked.
729pub fn unblock_key(key: KeyCode) { ctx(|s| s.unblock_key(key)) }
730
731// -- DRAWING --------------------------------------------------------------------------------------------------------------
732
733/// Clears the background using a color.
734///
735/// # Examples
736///
737/// ```
738/// clear_background(RED);
739/// ```
740
741pub fn clear_background(color: Color) {
742    if STATE.get().is_some() {
743        return ctx(|s| {
744            s.clear_color = Some(color);
745            s.draw_state.clear();
746        });
747    }
748
749    PENDING_CONFIG.with_borrow_mut(|c| c.window_clear_color = Some(color));
750}
751
752/// Draws a filled rectangle with its top-left corner at `(x, y)`.
753///
754/// # Examples
755///
756/// ```
757/// draw_rectangle(100.0, 100.0, 50.0, 80.0, RED);
758/// ```
759
760pub fn draw_rectangle(x: f32, y: f32, w: f32, h: f32, color: Color) {
761    draw_rectangle_rounded(x, y, w, h, 0.0, color);
762}
763
764/// Draws a **rounded**, filled rectangle with its top-left corner at `(x, y)`.
765/// All corners have the same radius. Use `draw_rectangle_rounded_ex()` to set all the radii separately.
766///
767/// # Examples
768///
769/// ```
770/// draw_rectangle_rounded(100.0, 100.0, 50.0, 80.0, 20.0, RED); // 20.0 is the radius of each corner
771/// ```
772pub fn draw_rectangle_rounded(x: f32, y: f32, w: f32, h: f32, radius: f32, color: Color) {
773    draw_rectangle_rounded_ex(x, y, w, h, radius, radius, radius, radius, color)
774}
775
776/// Draws a **rounded**, filled rectangle with its top-left corner at `(x, y)`
777/// with the ability to set each corner's radius manually.
778///
779/// # Examples
780///
781/// ```
782/// draw_rectangle_rounded_ex(
783///     x, y,
784///     w, h,
785///     top_left, top_right,
786///     bottom_left, bottom_right,
787///     RED
788/// );
789/// ```
790pub fn draw_rectangle_rounded_ex(
791    x: f32,
792    y: f32,
793    w: f32,
794    h: f32,
795    top_left: f32,
796    top_right: f32,
797    bottom_left: f32,
798    bottom_right: f32,
799    color: Color,
800) {
801    ctx(|s| {
802        s.draw_state.draw_rectangle(
803            x,
804            y,
805            w,
806            h,
807            top_left,
808            top_right,
809            bottom_left,
810            bottom_right,
811            color,
812        )
813    });
814}
815
816/// Draws a filled rectangle using a `Rect`.
817///
818/// # Examples
819///
820/// ```
821/// draw_rectangle_from_rect(rect, RED);
822/// ```
823pub fn draw_rectangle_from_rect(rect: Rect, color: Color) {
824    draw_rectangle(rect.x, rect.y, rect.w, rect.h, color);
825}
826
827/// Draws a **rounded**, filled rectangle using a `Rect` where all corners have the same radius.
828/// Use `draw_rectangle_rounded_from_rect_ex()` to set all radii separately.
829///
830/// # Examples
831///
832/// ```
833/// draw_rectangle_rounded_from_rect(rect, 20.0, RED); // 20.0 is the radius
834/// ```
835pub fn draw_rectangle_rounded_from_rect(rect: Rect, radius: f32, color: Color) {
836    draw_rectangle_rounded(rect.x, rect.y, rect.w, rect.h, radius, color);
837}
838
839/// Draws **rounded**, outlines of a rectangle using a `Rect` where all corners have the same radius.
840/// Use `draw_rectangle_lines_rounded_from_rect_ex()` to set all radii separately.
841///
842/// # Examples
843///
844/// ```
845/// draw_rectangle_lines_rounded_from_rect(rect, 20.0, RED); // 20.0 is the radius
846/// ```
847pub fn draw_rectangle_lines_rounded_from_rect(
848    rect: Rect,
849    radius: f32,
850    thickness: f32,
851    color: Color,
852) {
853    draw_rectangle_lines_rounded(rect.x, rect.y, rect.w, rect.h, radius, thickness, color);
854}
855
856/// Draws **rounded**, outlines of a rectangle using a `Rect` where all corners have the same radius.
857/// Use `draw_rectangle_lines_rounded_from_rect_ex()` to set all radii separately.
858///
859/// # Examples
860///
861/// ```
862/// draw_rectangle_lines_rounded_from_rect(rect, 20.0, RED); // 20.0 is the radius
863/// ```
864pub fn draw_rectangle_lines_rounded_from_rect_ex(
865    rect: Rect,
866    top_left: f32,
867    top_right: f32,
868    bottom_left: f32,
869    bottom_right: f32,
870    thickness: f32,
871    color: Color,
872) {
873    draw_rectangle_lines_rounded_ex(
874        rect.x,
875        rect.y,
876        rect.w,
877        rect.h,
878        top_left,
879        top_right,
880        bottom_left,
881        bottom_right,
882        thickness,
883        color,
884    );
885}
886
887/// Draws a **rounded**, filled rectangle using a `Rect`,
888/// with the ability to set each corner's radius separately.
889///
890/// # Examples
891///
892/// ```
893/// draw_rectangle_rounded_from_rect_ex(
894///     rect,
895///     top_left, top_right,
896///     bottom_left, bottom_right,
897///     RED
898/// );
899/// ```
900pub fn draw_rectangle_rounded_from_rect_ex(
901    rect: Rect,
902    top_left: f32,
903    top_right: f32,
904    bottom_left: f32,
905    bottom_right: f32,
906    color: Color,
907) {
908    draw_rectangle_rounded_ex(
909        rect.x,
910        rect.y,
911        rect.w,
912        rect.h,
913        top_left,
914        top_right,
915        bottom_left,
916        bottom_right,
917        color,
918    );
919}
920
921/// Draws the outline of a rectangle with its top-left corner at `(x, y)`.
922///
923/// # Examples
924///
925/// ```
926/// draw_rectangle_lines(100.0, 100.0, 50.0, 80.0, 4.0, WHITE);
927/// ```
928pub fn draw_rectangle_lines(x: f32, y: f32, w: f32, h: f32, thickness: f32, color: Color) {
929    draw_rectangle_lines_rounded(x, y, w, h, 0.0, thickness, color)
930}
931
932/// Draws the outline of a rectangle using a `Rect`.
933///
934/// # Examples
935///
936/// ```
937/// draw_rectangle_lines_from_rect(rect, 4.0, WHITE);
938/// ```
939pub fn draw_rectangle_lines_from_rect(rect: Rect, thickness: f32, color: Color) {
940    draw_rectangle_lines(rect.x, rect.y, rect.w, rect.h, thickness, color);
941}
942
943/// Draws the outline of a **rounded** rectangle with its top-left corner at `(x, y)`.
944/// All corners have the same radius. The stroke is centered on the rectangle's edge.
945/// Use `draw_rectangle_lines_rounded_ex()` to set each corner's radius separately.
946///
947/// # Examples
948///
949/// ```
950/// draw_rectangle_lines_rounded(100.0, 100.0, 50.0, 80.0, 12.0, 3.0, WHITE);
951/// // radius = 12.0, thickness = 3.0
952/// ```
953pub fn draw_rectangle_lines_rounded(
954    x: f32,
955    y: f32,
956    w: f32,
957    h: f32,
958    radius: f32,
959    thickness: f32,
960    color: Color,
961) {
962    draw_rectangle_lines_rounded_ex(x, y, w, h, radius, radius, radius, radius, thickness, color);
963}
964
965/// Draws the outline of a **rounded** rectangle with its top-left corner at `(x, y)`,
966/// with the ability to set each corner's radius separately.
967/// Radii are clamped to half the shorter side.
968///
969/// # Examples
970///
971/// ```
972/// draw_rectangle_lines_rounded_ex(
973///     100.0, 100.0, 50.0, 80.0,
974///     20.0, 0.0,   // top_left, top_right
975///     0.0, 20.0,   // bottom_left, bottom_right
976///     3.0, WHITE,  // thickness, color
977/// );
978/// ```
979pub fn draw_rectangle_lines_rounded_ex(
980    x: f32,
981    y: f32,
982    w: f32,
983    h: f32,
984    top_left: f32,
985    top_right: f32,
986    bottom_left: f32,
987    bottom_right: f32,
988    thickness: f32,
989    color: Color,
990) {
991    ctx(|s| {
992        s.draw_state.draw_rectangle_lines(
993            x,
994            y,
995            w,
996            h,
997            top_left,
998            top_right,
999            bottom_left,
1000            bottom_right,
1001            thickness,
1002            color,
1003        )
1004    });
1005}
1006
1007/// Draws a filled rectangle of size `w` x `h` centered at `(x, y)`,
1008/// rotated by `rotation` radians around that center.
1009///
1010/// # Examples
1011///
1012/// ```
1013/// draw_rectangle_rotated(200.0, 200.0, 50.0, 80.0, std::f32::consts::FRAC_PI_4, GREEN);
1014/// ```
1015pub fn draw_rectangle_rotated(x: f32, y: f32, w: f32, h: f32, rotation: f32, color: Color) {
1016    ctx(|s| {
1017        s.draw_state
1018            .draw_rectangle_rotated(x, y, w, h, rotation, 0.0, 0.0, 0.0, 0.0, color)
1019    });
1020}
1021
1022/// Draws the outline of a rectangle with its top-left corner at `(x, y)` (before rotation),
1023/// rotated by `rotation` radians around its center.
1024pub fn draw_rectangle_lines_rotated(
1025    x: f32,
1026    y: f32,
1027    w: f32,
1028    h: f32,
1029    rotation: f32,
1030    thickness: f32,
1031    color: Color,
1032) {
1033    ctx(|s| {
1034        s.draw_state.draw_rectangle_lines_rotated(
1035            x, y, w, h, rotation, 0.0, 0.0, 0.0, 0.0, thickness, color,
1036        )
1037    });
1038}
1039
1040/// Draws a rounded, filled rectangle centered at `(x, y)`,
1041/// rotated by `rotation` radians around that center.
1042/// All corners have the same radius.
1043pub fn draw_rectangle_rounded_rotated(
1044    x: f32,
1045    y: f32,
1046    w: f32,
1047    h: f32,
1048    rotation: f32,
1049    radius: f32,
1050    color: Color,
1051) {
1052    draw_rectangle_rounded_rotated_ex(x, y, w, h, rotation, radius, radius, radius, radius, color);
1053}
1054
1055pub fn draw_rectangle_rounded_rotated_ex(
1056    x: f32,
1057    y: f32,
1058    w: f32,
1059    h: f32,
1060    rotation: f32,
1061    top_left: f32,
1062    top_right: f32,
1063    bottom_left: f32,
1064    bottom_right: f32,
1065    color: Color,
1066) {
1067    ctx(|s| {
1068        s.draw_state.draw_rectangle_rotated(
1069            x,
1070            y,
1071            w,
1072            h,
1073            rotation,
1074            top_left,
1075            top_right,
1076            bottom_left,
1077            bottom_right,
1078            color,
1079        )
1080    });
1081}
1082
1083/// Draws the outline of a rounded rectangle centered at `(x, y)`,
1084/// rotated by `rotation` radians around that center.
1085/// All corners have the same radius.
1086pub fn draw_rectangle_lines_rounded_rotated(
1087    x: f32,
1088    y: f32,
1089    w: f32,
1090    h: f32,
1091    rotation: f32,
1092    radius: f32,
1093    thickness: f32,
1094    color: Color,
1095) {
1096    draw_rectangle_lines_rounded_rotated_ex(
1097        x, y, w, h, rotation, radius, radius, radius, radius, thickness, color,
1098    );
1099}
1100
1101/// Draws the outline of a rounded rectangle centered at `(x, y)`,
1102/// rotated by `rotation` radians around that center.
1103/// Can set each corner's radius separately.
1104pub fn draw_rectangle_lines_rounded_rotated_ex(
1105    x: f32,
1106    y: f32,
1107    w: f32,
1108    h: f32,
1109    rotation: f32,
1110    top_left: f32,
1111    top_right: f32,
1112    bottom_left: f32,
1113    bottom_right: f32,
1114    thickness: f32,
1115    color: Color,
1116) {
1117    ctx(|s| {
1118        s.draw_state.draw_rectangle_lines_rotated(
1119            x,
1120            y,
1121            w,
1122            h,
1123            rotation,
1124            top_left,
1125            top_right,
1126            bottom_left,
1127            bottom_right,
1128            thickness,
1129            color,
1130        )
1131    });
1132}
1133
1134/// Draws a filled circle centered at `(x, y)` with radius `r`.
1135///
1136/// # Examples
1137///
1138/// ```
1139/// draw_circle(300.0, 300.0, 40.0, BLUE);
1140/// ```
1141pub fn draw_circle(x: f32, y: f32, r: f32, color: Color) {
1142    ctx(|s| s.draw_state.draw_circle(x, y, r, color));
1143}
1144
1145/// Draws the outline of a circle centered at `(x, y)` with radius `r`.
1146///
1147/// # Examples
1148///
1149/// ```
1150/// draw_circle_lines(300.0, 300.0, 40.0, 3.0, WHITE);
1151/// ```
1152
1153pub fn draw_circle_lines(x: f32, y: f32, r: f32, thickness: f32, color: Color) {
1154    ctx(|s| s.draw_state.draw_circle_lines(x, y, r, thickness, color));
1155}
1156
1157/// Draws a filled triangle from three points.
1158///
1159/// # Examples
1160///
1161/// ```
1162/// draw_triangle(100.0, 200.0, 200.0, 200.0, 150.0, 100.0, YELLOW);
1163/// ```
1164
1165pub fn draw_triangle(x1: f32, y1: f32, x2: f32, y2: f32, x3: f32, y3: f32, color: Color) {
1166    ctx(|s| s.draw_state.draw_triangle(x1, y1, x2, y2, x3, y3, color));
1167}
1168
1169/// Draws the outline of a triangle from three points.
1170///
1171/// # Examples
1172///
1173/// ```
1174/// draw_triangle_lines(100.0, 200.0, 200.0, 200.0, 150.0, 100.0, 3.0, WHITE);
1175/// ```
1176
1177pub fn draw_triangle_lines(
1178    x1: f32,
1179    y1: f32,
1180    x2: f32,
1181    y2: f32,
1182    x3: f32,
1183    y3: f32,
1184    thickness: f32,
1185    color: Color,
1186) {
1187    ctx(|s| {
1188        s.draw_state
1189            .draw_triangle_lines(x1, y1, x2, y2, x3, y3, thickness, color)
1190    });
1191}
1192
1193/// Draws a line segment from `(x1, y1)` to `(x2, y2)`.
1194///
1195/// # Examples
1196///
1197/// ```
1198/// draw_line(0.0, 0.0, 200.0, 150.0, 4.0, WHITE);
1199/// ```
1200
1201pub fn draw_line(x1: f32, y1: f32, x2: f32, y2: f32, thickness: f32, color: Color) {
1202    ctx(|s| s.draw_state.draw_line(x1, y1, x2, y2, thickness, color))
1203}
1204
1205/// Draws connected line segments through `points` with mitered joins.
1206/// If `closed` is true, the last point connects back to the first.
1207///
1208/// # Examples
1209///
1210/// ```
1211/// let pts = [Vector2::new(50.0, 50.0), Vector2::new(150.0, 80.0), Vector2::new(100.0, 160.0)];
1212/// draw_poly_line(&pts, 3.0, WHITE, true);
1213/// ```
1214
1215pub fn draw_poly_line(points: &[Vector2], thickness: f32, color: Color, closed: bool) {
1216    ctx(|s| {
1217        s.draw_state
1218            .draw_poly_line_miter(points, thickness, color, closed)
1219    })
1220}
1221
1222/// Draws connected line segments through `points` with rounded joints and caps.
1223/// If `closed` is true, the last point connects back to the first.
1224///
1225/// # Examples
1226///
1227/// ```
1228/// let pts = [Vector2::new(50.0, 50.0), Vector2::new(150.0, 80.0), Vector2::new(100.0, 160.0)];
1229/// draw_poly_line_rounded(&pts, 6.0, WHITE, false);
1230/// ```
1231
1232pub fn draw_poly_line_rounded(points: &[Vector2], thickness: f32, color: Color, closed: bool) {
1233    ctx(|s| {
1234        s.draw_state
1235            .draw_poly_line(points, thickness, color, closed, true)
1236    })
1237}
1238
1239/// Draws a filled convex polygon from `points` as a triangle fan.
1240/// Fewer than 3 points draws nothing. Use `draw_polygon_concave` for concave shapes.
1241///
1242/// # Examples
1243///
1244/// ```
1245/// let pts = [
1246///     Vector2::new(100.0, 100.0), Vector2::new(200.0, 100.0),
1247///     Vector2::new(220.0, 180.0), Vector2::new(80.0, 180.0),
1248/// ];
1249/// draw_polygon(&pts, GREEN);
1250/// ```
1251pub fn draw_polygon(points: &[Vector2], color: Color) {
1252    ctx(|s| s.draw_state.draw_polygon(points, color))
1253}
1254
1255/// Draws a filled polygon that may be concave, using ear clipping.
1256/// Self-intersecting polygons may not render correctly.
1257///
1258/// # Examples
1259///
1260/// ```
1261/// let pts = [
1262///     Vector2::new(100.0, 100.0), Vector2::new(200.0, 100.0),
1263///     Vector2::new(150.0, 150.0), Vector2::new(200.0, 200.0),
1264///     Vector2::new(100.0, 200.0),
1265/// ];
1266/// draw_polygon_concave(&pts, RED);
1267/// ```
1268pub fn draw_polygon_concave(points: &[Vector2], color: Color) {
1269    ctx(|s| s.draw_state.draw_polygon_concave(points, color))
1270}
1271
1272/// Draws text with its top-left corner at `(x, y)` with the given font, size, and color.
1273///
1274/// # Examples
1275///
1276/// ```
1277/// draw_text("Hello", 10.0, 10.0, 32.0, None, WHITE);           // default font
1278/// draw_text("Hello", 10.0, 10.0, 32.0, Some(&font), WHITE);    // loaded font
1279/// ```
1280pub fn draw_text(t: &str, x: f32, y: f32, size: f32, font: Option<&Font>, color: Color) {
1281    ctx(|s| s.draw_state.draw_text(&s.fonts, t, x, y, size, font, color));
1282}
1283
1284/// Draws a collection of `Span`s in sequence where each Span can have different properties such as
1285/// - text
1286/// - color
1287/// - size
1288/// - font
1289/// The `spans` should implement IntoIterator. Which means you can just pass an iterator.
1290///
1291/// ## Examples
1292///
1293/// ```
1294/// draw_rich_text(vec2(10.0, 10.0), &[
1295///     span("Hello there\n", WHITE),
1296///     span("My name is ", WHITE),
1297///     span("John Doe", RED)
1298///         .with_color(RED)
1299///         .with_size(32.0)
1300/// ]);
1301/// ```
1302pub fn draw_rich_text<'a, I>(
1303    position: Vector2,
1304    size: f32,
1305    font: Option<&Font>,
1306    color: Color,
1307    spans: I,
1308) where
1309    I: IntoIterator,
1310    I::Item: Borrow<Span<'a>>,
1311{
1312    ctx(|s| {
1313        s.draw_state
1314            .draw_richtext(position, size, font, color, spans)
1315    })
1316}
1317
1318/// Loads a `.ttf`/`.otf` font from path and returns the `Font` object.
1319/// (Do not load the font every frame, it will lag)
1320///
1321/// # Examples
1322///
1323/// ```
1324/// // Put this before the `flake::run()` to avoid loading it each frame
1325/// let font = load_font_from_path("src/Arial.ttf");
1326///
1327/// flake::run(|| {
1328///     draw_text("Hello", 10.0, 10.0, 32.0, Some(&font), WHITE)
1329/// })
1330/// ```
1331pub fn load_font_from_path(path: &str) -> Font {
1332    if STATE.get().is_some() {
1333        return ctx(|s| {
1334            s.load_font_from_path(path);
1335            s.fonts[s.fonts.len() - 1].clone()
1336        });
1337    }
1338
1339    PENDING_CONFIG.with_borrow_mut(|s| {
1340        let font = Font::from_path(s.fonts.len() + 1, path);
1341        s.fonts.push(font.clone());
1342        font
1343    })
1344}
1345
1346/// Loads a `.ttf`/`.otf` font from bytes and returns the `Font` object.
1347/// (Do not load the font every frame, it will lag)
1348///
1349/// # Examples
1350///
1351/// ```
1352/// // Put this before the `flake::run()` to avoid loading it each frame
1353/// let font = load_font_from_bytes(include_bytes!("Arial.ttf"));
1354///
1355/// flake::run(|| {
1356///     draw_text("Hello", 10.0, 10.0, 32.0, Some(&font), WHITE)
1357/// })
1358/// ```
1359pub fn load_font_from_bytes(bytes: &[u8]) -> Font {
1360    if STATE.get().is_some() {
1361        return ctx(|s| {
1362            s.load_font_from_bytes(bytes);
1363            s.fonts[s.fonts.len() - 1].clone()
1364        });
1365    }
1366
1367    PENDING_CONFIG.with_borrow_mut(|s| {
1368        let font = Font::from_bytes(s.fonts.len() + 1, bytes);
1369        s.fonts.push(font.clone());
1370        font
1371    })
1372}
1373
1374/// Returns the (width, height) of `text` when drawn with `draw_text` at this size.
1375pub fn measure_text(t: &str, size: f32, font: Option<&Font>) -> Vector2 {
1376    let (w, h) = ctx(|s| s.measure_text(t, size, font));
1377    Vector2::new(w, h)
1378}
1379
1380/// Draws a line from `(x1, y1)` to `(x2, y2)` with a triangular head at the end.
1381/// The tip extends `head_size` past `(x2, y2)`.
1382pub fn draw_arrow(
1383    x1: f32,
1384    y1: f32,
1385    x2: f32,
1386    y2: f32,
1387    thickness: f32,
1388    head_size: f32,
1389    color: Color,
1390) {
1391    ctx(|s| {
1392        s.draw_state
1393            .draw_arrow(x1, y1, x2, y2, thickness, head_size, color)
1394    });
1395}
1396
1397/// Returns the size of the monitor the window is on, or the window size if it can't be determined.
1398pub fn screen_size() -> Vector2 {
1399    let win = get_window();
1400    match win.current_monitor() {
1401        Some(m) => {
1402            let s = m.size();
1403            Vector2::new(s.width as f32, s.height as f32)
1404        }
1405        None => window_size(),
1406    }
1407}
1408
1409pub fn screen_width() -> f32 {
1410    screen_size().x
1411}
1412pub fn screen_height() -> f32 {
1413    screen_size().y
1414}
1415
1416// -- TEXTURES --------------------------------------------------------------------------------------------------------------
1417
1418/// Creates an empty texture of the given size. Fill it with `update_texture`.
1419pub fn create_empty_texture(width: u32, height: u32, filter_type: FilterType) -> Texture {
1420    ctx(|s| {
1421        let gpu = GpuTexture::empty(
1422            &s.device,
1423            width,
1424            height,
1425            filter_type,
1426            wgpu::TextureFormat::Rgba8UnormSrgb,
1427        )
1428        .expect("Couldn't create empty GpuTexture");
1429
1430        Texture {
1431            id: s.add_gpu_texture(gpu, false),
1432            width,
1433            height,
1434        }
1435    })
1436}
1437
1438/// Loads a texture from an image file using linear filtering. Panics if the file can't be read or decoded.
1439pub fn load_texture(path: &str) -> Texture {
1440    ctx(|s| {
1441        let image = image::load_from_memory(&std::fs::read(path).unwrap()).unwrap();
1442        let width = image.width();
1443        let height = image.height();
1444
1445        Texture {
1446            id: s.add_texture(image, FilterType::Linear),
1447            width,
1448            height,
1449        }
1450    })
1451}
1452
1453/// Same as `load_texture`, with an explicit `FilterType` (e.g. nearest for pixel art).
1454pub fn load_texture_with_filter_type(path: &str, filter_type: FilterType) -> Texture {
1455    ctx(|s| {
1456        let image = image::load_from_memory(&std::fs::read(path).unwrap()).unwrap();
1457        let width = image.width();
1458        let height = image.height();
1459
1460        Texture {
1461            id: s.add_texture(image, filter_type),
1462            width,
1463            height,
1464        }
1465    })
1466}
1467
1468/// Loads a texture from encoded image bytes (e.g. `include_bytes!`) using linear filtering.
1469pub fn load_texture_from_bytes(bytes: &[u8]) -> Texture {
1470    ctx(|s| {
1471        let image = image::load_from_memory(bytes).unwrap();
1472        let (width, height) = image.dimensions();
1473
1474        Texture {
1475            id: s.add_texture(image, FilterType::Linear),
1476            width,
1477            height,
1478        }
1479    })
1480}
1481
1482/// Loads a texture from raw RGBA `f32` pixels. `data.len()` must equal `width * height * 4`, otherwise this panics.
1483pub fn load_texture_from_bytes_with_filter_type(bytes: &[u8], filter_type: FilterType) -> Texture {
1484    ctx(|s| {
1485        let image = image::load_from_memory(bytes).unwrap();
1486        let (width, height) = image.dimensions();
1487
1488        Texture {
1489            id: s.add_texture(image, filter_type),
1490            width,
1491            height,
1492        }
1493    })
1494}
1495
1496/// Loads a texture from raw RGBA `f32` pixels. `data.len()` must equal `width * height * 4`, otherwise this panics.
1497pub fn load_texture_from_data(width: u32, height: u32, data: &[f32]) -> Texture {
1498    ctx(|s| {
1499        let img_buf = ImageBuffer::<Rgba<f32>, Vec<f32>>::from_raw(width, height, data.to_vec())
1500            .expect("Buffer size mismatch");
1501
1502        let dynamic_img = DynamicImage::ImageRgba32F(img_buf);
1503
1504        Texture {
1505            id: s.add_texture(dynamic_img, FilterType::Linear),
1506            width,
1507            height,
1508        }
1509    })
1510}
1511
1512/// Loads a texture from raw RGBA `f32` pixels.
1513/// `data.len()` must equal `width * height * 4`, otherwise this panics.
1514/// (Use nearest for pixel art)
1515pub fn load_texture_from_data_with_filter_type(
1516    width: u32,
1517    height: u32,
1518    data: &[f32],
1519    filter_type: FilterType,
1520) -> Texture {
1521    ctx(|s| {
1522        let img_buf = ImageBuffer::<Rgba<f32>, Vec<f32>>::from_raw(width, height, data.to_vec())
1523            .expect("Buffer size mismatch");
1524
1525        let dynamic_img = DynamicImage::ImageRgba32F(img_buf);
1526
1527        Texture {
1528            id: s.add_texture(dynamic_img, filter_type),
1529            width,
1530            height,
1531        }
1532    })
1533}
1534
1535/// Creates a texture from an `Image`.
1536pub fn load_texture_from_image(image: &Image) -> Texture {
1537    let tex = create_empty_texture(image.width, image.height, image.filter_type);
1538    update_texture(tex, image);
1539
1540    tex
1541}
1542
1543/// Draws a texture stretched to `w` x `h` with its top-left at `(x, y)`.
1544/// `tint` multiplies the texture color (use `WHITE` for none).
1545pub fn draw_texture(texture: Texture, x: f32, y: f32, w: f32, h: f32, tint: Color) {
1546    ctx(|s| s.draw_state.draw_texture(texture, x, y, w, h, tint))
1547}
1548
1549/// Draws a texture with extra options from `DrawTextureParams`: destination size,
1550/// source rect, horizontal/vertical flip, rotation (radians), pivot, and tint.
1551pub fn draw_texture_ex(texture: Texture, x: f32, y: f32, p: DrawTextureParams) {
1552    ctx(|s| s.draw_state.draw_texture_ex(texture, x, y, p))
1553}
1554
1555/// Replaces the pixels of an existing texture with those from `image`.
1556pub fn update_texture(texture: Texture, image: &Image) {
1557    ctx(|s| s.update_texture(texture.id, image))
1558}
1559
1560/// Creates a new RenderTarget.
1561pub fn render_target(width: u32, height: u32, filter_type: FilterType) -> RenderTarget {
1562    ctx(|s| s.create_render_target(width, height, filter_type))
1563}
1564
1565/// Sets the currently active camera being used to draw on.
1566pub fn set_camera(cam: &Camera2D) {
1567    ctx(|s| s.set_camera(cam))
1568}
1569
1570/// Resets the camera to the default screen one.
1571pub fn set_default_camera() {
1572    ctx(|s| s.set_default_camera())
1573}