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