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.
753pub fn last_key_name() -> Option<String> {
754    ctx(|s| s.last_key_name())
755}
756
757// -- DRAWING --------------------------------------------------------------------------------------------------------------
758
759/// Clears the background using a color.
760///
761/// # Examples
762///
763/// ```
764/// clear_background(RED);
765/// ```
766
767pub fn clear_background(color: Color) {
768    if STATE.get().is_some() {
769        return ctx(|s| {
770            s.clear_color = Some(color);
771            s.draw_state.clear();
772        });
773    }
774
775    PENDING_CONFIG.with_borrow_mut(|c| c.window_clear_color = Some(color));
776}
777
778/// Draws a filled rectangle with its top-left corner at `(x, y)`.
779///
780/// # Examples
781///
782/// ```
783/// draw_rectangle(100.0, 100.0, 50.0, 80.0, RED);
784/// ```
785
786pub fn draw_rectangle(x: f32, y: f32, w: f32, h: f32, color: Color) {
787    draw_rectangle_rounded(x, y, w, h, 0.0, color);
788}
789
790/// Draws a **rounded**, filled rectangle with its top-left corner at `(x, y)`.
791/// All corners have the same radius. Use `draw_rectangle_rounded_ex()` to set all the radii separately.
792///
793/// # Examples
794///
795/// ```
796/// draw_rectangle_rounded(100.0, 100.0, 50.0, 80.0, 20.0, RED); // 20.0 is the radius of each corner
797/// ```
798pub fn draw_rectangle_rounded(x: f32, y: f32, w: f32, h: f32, radius: f32, color: Color) {
799    draw_rectangle_rounded_ex(x, y, w, h, radius, radius, radius, radius, color)
800}
801
802/// Draws a **rounded**, filled rectangle with its top-left corner at `(x, y)`
803/// with the ability to set each corner's radius manually.
804///
805/// # Examples
806///
807/// ```
808/// draw_rectangle_rounded_ex(
809///     x, y,
810///     w, h,
811///     top_left, top_right,
812///     bottom_left, bottom_right,
813///     RED
814/// );
815/// ```
816pub fn draw_rectangle_rounded_ex(
817    x: f32,
818    y: f32,
819    w: f32,
820    h: f32,
821    top_left: f32,
822    top_right: f32,
823    bottom_left: f32,
824    bottom_right: f32,
825    color: Color,
826) {
827    ctx(|s| {
828        s.draw_state.draw_rectangle(
829            x,
830            y,
831            w,
832            h,
833            top_left,
834            top_right,
835            bottom_left,
836            bottom_right,
837            color,
838        )
839    });
840}
841
842/// Draws a filled rectangle using a `Rect`.
843///
844/// # Examples
845///
846/// ```
847/// draw_rectangle_from_rect(rect, RED);
848/// ```
849pub fn draw_rectangle_from_rect(rect: Rect, color: Color) {
850    draw_rectangle(rect.x, rect.y, rect.w, rect.h, color);
851}
852
853/// Draws a **rounded**, filled rectangle using a `Rect` where all corners have the same radius.
854/// Use `draw_rectangle_rounded_from_rect_ex()` to set all radii separately.
855///
856/// # Examples
857///
858/// ```
859/// draw_rectangle_rounded_from_rect(rect, 20.0, RED); // 20.0 is the radius
860/// ```
861pub fn draw_rectangle_rounded_from_rect(rect: Rect, radius: f32, color: Color) {
862    draw_rectangle_rounded(rect.x, rect.y, rect.w, rect.h, radius, color);
863}
864
865/// Draws **rounded**, outlines of a rectangle using a `Rect` where all corners have the same radius.
866/// Use `draw_rectangle_lines_rounded_from_rect_ex()` to set all radii separately.
867///
868/// # Examples
869///
870/// ```
871/// draw_rectangle_lines_rounded_from_rect(rect, 20.0, RED); // 20.0 is the radius
872/// ```
873pub fn draw_rectangle_lines_rounded_from_rect(
874    rect: Rect,
875    radius: f32,
876    thickness: f32,
877    color: Color,
878) {
879    draw_rectangle_lines_rounded(rect.x, rect.y, rect.w, rect.h, radius, thickness, color);
880}
881
882/// Draws **rounded**, outlines of a rectangle using a `Rect` where all corners have the same radius.
883/// Use `draw_rectangle_lines_rounded_from_rect_ex()` to set all radii separately.
884///
885/// # Examples
886///
887/// ```
888/// draw_rectangle_lines_rounded_from_rect(rect, 20.0, RED); // 20.0 is the radius
889/// ```
890pub fn draw_rectangle_lines_rounded_from_rect_ex(
891    rect: Rect,
892    top_left: f32,
893    top_right: f32,
894    bottom_left: f32,
895    bottom_right: f32,
896    thickness: f32,
897    color: Color,
898) {
899    draw_rectangle_lines_rounded_ex(
900        rect.x,
901        rect.y,
902        rect.w,
903        rect.h,
904        top_left,
905        top_right,
906        bottom_left,
907        bottom_right,
908        thickness,
909        color,
910    );
911}
912
913/// Draws a **rounded**, filled rectangle using a `Rect`,
914/// with the ability to set each corner's radius separately.
915///
916/// # Examples
917///
918/// ```
919/// draw_rectangle_rounded_from_rect_ex(
920///     rect,
921///     top_left, top_right,
922///     bottom_left, bottom_right,
923///     RED
924/// );
925/// ```
926pub fn draw_rectangle_rounded_from_rect_ex(
927    rect: Rect,
928    top_left: f32,
929    top_right: f32,
930    bottom_left: f32,
931    bottom_right: f32,
932    color: Color,
933) {
934    draw_rectangle_rounded_ex(
935        rect.x,
936        rect.y,
937        rect.w,
938        rect.h,
939        top_left,
940        top_right,
941        bottom_left,
942        bottom_right,
943        color,
944    );
945}
946
947/// Draws the outline of a rectangle with its top-left corner at `(x, y)`.
948///
949/// # Examples
950///
951/// ```
952/// draw_rectangle_lines(100.0, 100.0, 50.0, 80.0, 4.0, WHITE);
953/// ```
954pub fn draw_rectangle_lines(x: f32, y: f32, w: f32, h: f32, thickness: f32, color: Color) {
955    draw_rectangle_lines_rounded(x, y, w, h, 0.0, thickness, color)
956}
957
958/// Draws the outline of a rectangle using a `Rect`.
959///
960/// # Examples
961///
962/// ```
963/// draw_rectangle_lines_from_rect(rect, 4.0, WHITE);
964/// ```
965pub fn draw_rectangle_lines_from_rect(rect: Rect, thickness: f32, color: Color) {
966    draw_rectangle_lines(rect.x, rect.y, rect.w, rect.h, thickness, color);
967}
968
969/// Draws the outline of a **rounded** rectangle with its top-left corner at `(x, y)`.
970/// All corners have the same radius. The stroke is centered on the rectangle's edge.
971/// Use `draw_rectangle_lines_rounded_ex()` to set each corner's radius separately.
972///
973/// # Examples
974///
975/// ```
976/// draw_rectangle_lines_rounded(100.0, 100.0, 50.0, 80.0, 12.0, 3.0, WHITE);
977/// // radius = 12.0, thickness = 3.0
978/// ```
979pub fn draw_rectangle_lines_rounded(
980    x: f32,
981    y: f32,
982    w: f32,
983    h: f32,
984    radius: f32,
985    thickness: f32,
986    color: Color,
987) {
988    draw_rectangle_lines_rounded_ex(x, y, w, h, radius, radius, radius, radius, thickness, color);
989}
990
991/// Draws the outline of a **rounded** rectangle with its top-left corner at `(x, y)`,
992/// with the ability to set each corner's radius separately.
993/// Radii are clamped to half the shorter side.
994///
995/// # Examples
996///
997/// ```
998/// draw_rectangle_lines_rounded_ex(
999///     100.0, 100.0, 50.0, 80.0,
1000///     20.0, 0.0,   // top_left, top_right
1001///     0.0, 20.0,   // bottom_left, bottom_right
1002///     3.0, WHITE,  // thickness, color
1003/// );
1004/// ```
1005pub fn draw_rectangle_lines_rounded_ex(
1006    x: f32,
1007    y: f32,
1008    w: f32,
1009    h: f32,
1010    top_left: f32,
1011    top_right: f32,
1012    bottom_left: f32,
1013    bottom_right: f32,
1014    thickness: f32,
1015    color: Color,
1016) {
1017    ctx(|s| {
1018        s.draw_state.draw_rectangle_lines(
1019            x,
1020            y,
1021            w,
1022            h,
1023            top_left,
1024            top_right,
1025            bottom_left,
1026            bottom_right,
1027            thickness,
1028            color,
1029        )
1030    });
1031}
1032
1033/// Draws a filled rectangle of size `w` x `h` centered at `(x, y)`,
1034/// rotated by `rotation` radians around that center.
1035///
1036/// # Examples
1037///
1038/// ```
1039/// draw_rectangle_rotated(200.0, 200.0, 50.0, 80.0, std::f32::consts::FRAC_PI_4, GREEN);
1040/// ```
1041pub fn draw_rectangle_rotated(x: f32, y: f32, w: f32, h: f32, rotation: f32, color: Color) {
1042    ctx(|s| {
1043        s.draw_state
1044            .draw_rectangle_rotated(x, y, w, h, rotation, 0.0, 0.0, 0.0, 0.0, color)
1045    });
1046}
1047
1048/// Draws the outline of a rectangle with its top-left corner at `(x, y)` (before rotation),
1049/// rotated by `rotation` radians around its center.
1050pub fn draw_rectangle_lines_rotated(
1051    x: f32,
1052    y: f32,
1053    w: f32,
1054    h: f32,
1055    rotation: f32,
1056    thickness: f32,
1057    color: Color,
1058) {
1059    ctx(|s| {
1060        s.draw_state.draw_rectangle_lines_rotated(
1061            x, y, w, h, rotation, 0.0, 0.0, 0.0, 0.0, thickness, color,
1062        )
1063    });
1064}
1065
1066/// Draws a rounded, filled rectangle centered at `(x, y)`,
1067/// rotated by `rotation` radians around that center.
1068/// All corners have the same radius.
1069pub fn draw_rectangle_rounded_rotated(
1070    x: f32,
1071    y: f32,
1072    w: f32,
1073    h: f32,
1074    rotation: f32,
1075    radius: f32,
1076    color: Color,
1077) {
1078    draw_rectangle_rounded_rotated_ex(x, y, w, h, rotation, radius, radius, radius, radius, color);
1079}
1080
1081pub fn draw_rectangle_rounded_rotated_ex(
1082    x: f32,
1083    y: f32,
1084    w: f32,
1085    h: f32,
1086    rotation: f32,
1087    top_left: f32,
1088    top_right: f32,
1089    bottom_left: f32,
1090    bottom_right: f32,
1091    color: Color,
1092) {
1093    ctx(|s| {
1094        s.draw_state.draw_rectangle_rotated(
1095            x,
1096            y,
1097            w,
1098            h,
1099            rotation,
1100            top_left,
1101            top_right,
1102            bottom_left,
1103            bottom_right,
1104            color,
1105        )
1106    });
1107}
1108
1109/// Draws the outline of a rounded rectangle centered at `(x, y)`,
1110/// rotated by `rotation` radians around that center.
1111/// All corners have the same radius.
1112pub fn draw_rectangle_lines_rounded_rotated(
1113    x: f32,
1114    y: f32,
1115    w: f32,
1116    h: f32,
1117    rotation: f32,
1118    radius: f32,
1119    thickness: f32,
1120    color: Color,
1121) {
1122    draw_rectangle_lines_rounded_rotated_ex(
1123        x, y, w, h, rotation, radius, radius, radius, radius, thickness, color,
1124    );
1125}
1126
1127/// Draws the outline of a rounded rectangle centered at `(x, y)`,
1128/// rotated by `rotation` radians around that center.
1129/// Can set each corner's radius separately.
1130pub fn draw_rectangle_lines_rounded_rotated_ex(
1131    x: f32,
1132    y: f32,
1133    w: f32,
1134    h: f32,
1135    rotation: f32,
1136    top_left: f32,
1137    top_right: f32,
1138    bottom_left: f32,
1139    bottom_right: f32,
1140    thickness: f32,
1141    color: Color,
1142) {
1143    ctx(|s| {
1144        s.draw_state.draw_rectangle_lines_rotated(
1145            x,
1146            y,
1147            w,
1148            h,
1149            rotation,
1150            top_left,
1151            top_right,
1152            bottom_left,
1153            bottom_right,
1154            thickness,
1155            color,
1156        )
1157    });
1158}
1159
1160/// Draws a filled circle centered at `(x, y)` with radius `r`.
1161///
1162/// # Examples
1163///
1164/// ```
1165/// draw_circle(300.0, 300.0, 40.0, BLUE);
1166/// ```
1167pub fn draw_circle(x: f32, y: f32, r: f32, color: Color) {
1168    ctx(|s| s.draw_state.draw_circle(x, y, r, color));
1169}
1170
1171/// Draws the outline of a circle centered at `(x, y)` with radius `r`.
1172///
1173/// # Examples
1174///
1175/// ```
1176/// draw_circle_lines(300.0, 300.0, 40.0, 3.0, WHITE);
1177/// ```
1178
1179pub fn draw_circle_lines(x: f32, y: f32, r: f32, thickness: f32, color: Color) {
1180    ctx(|s| s.draw_state.draw_circle_lines(x, y, r, thickness, color));
1181}
1182
1183/// Draws a filled triangle from three points.
1184///
1185/// # Examples
1186///
1187/// ```
1188/// draw_triangle(100.0, 200.0, 200.0, 200.0, 150.0, 100.0, YELLOW);
1189/// ```
1190
1191pub fn draw_triangle(x1: f32, y1: f32, x2: f32, y2: f32, x3: f32, y3: f32, color: Color) {
1192    ctx(|s| s.draw_state.draw_triangle(x1, y1, x2, y2, x3, y3, color));
1193}
1194
1195/// Draws the outline of a triangle from three points.
1196///
1197/// # Examples
1198///
1199/// ```
1200/// draw_triangle_lines(100.0, 200.0, 200.0, 200.0, 150.0, 100.0, 3.0, WHITE);
1201/// ```
1202
1203pub fn draw_triangle_lines(
1204    x1: f32,
1205    y1: f32,
1206    x2: f32,
1207    y2: f32,
1208    x3: f32,
1209    y3: f32,
1210    thickness: f32,
1211    color: Color,
1212) {
1213    ctx(|s| {
1214        s.draw_state
1215            .draw_triangle_lines(x1, y1, x2, y2, x3, y3, thickness, color)
1216    });
1217}
1218
1219/// Draws a line segment from `(x1, y1)` to `(x2, y2)`.
1220///
1221/// # Examples
1222///
1223/// ```
1224/// draw_line(0.0, 0.0, 200.0, 150.0, 4.0, WHITE);
1225/// ```
1226
1227pub fn draw_line(x1: f32, y1: f32, x2: f32, y2: f32, thickness: f32, color: Color) {
1228    ctx(|s| s.draw_state.draw_line(x1, y1, x2, y2, thickness, color))
1229}
1230
1231/// Draws connected line segments through `points` with mitered joins.
1232/// If `closed` is true, the last point connects back to the first.
1233///
1234/// # Examples
1235///
1236/// ```
1237/// let pts = [Vector2::new(50.0, 50.0), Vector2::new(150.0, 80.0), Vector2::new(100.0, 160.0)];
1238/// draw_poly_line(&pts, 3.0, WHITE, true);
1239/// ```
1240
1241pub fn draw_poly_line(points: &[Vector2], thickness: f32, color: Color, closed: bool) {
1242    ctx(|s| {
1243        s.draw_state
1244            .draw_poly_line_miter(points, thickness, color, closed)
1245    })
1246}
1247
1248/// Draws connected line segments through `points` with rounded joints and caps.
1249/// If `closed` is true, the last point connects back to the first.
1250///
1251/// # Examples
1252///
1253/// ```
1254/// let pts = [Vector2::new(50.0, 50.0), Vector2::new(150.0, 80.0), Vector2::new(100.0, 160.0)];
1255/// draw_poly_line_rounded(&pts, 6.0, WHITE, false);
1256/// ```
1257
1258pub fn draw_poly_line_rounded(points: &[Vector2], thickness: f32, color: Color, closed: bool) {
1259    ctx(|s| {
1260        s.draw_state
1261            .draw_poly_line(points, thickness, color, closed, true)
1262    })
1263}
1264
1265/// Draws a filled convex polygon from `points` as a triangle fan.
1266/// Fewer than 3 points draws nothing. Use `draw_polygon_concave` for concave shapes.
1267///
1268/// # Examples
1269///
1270/// ```
1271/// let pts = [
1272///     Vector2::new(100.0, 100.0), Vector2::new(200.0, 100.0),
1273///     Vector2::new(220.0, 180.0), Vector2::new(80.0, 180.0),
1274/// ];
1275/// draw_polygon(&pts, GREEN);
1276/// ```
1277pub fn draw_polygon(points: &[Vector2], color: Color) {
1278    ctx(|s| s.draw_state.draw_polygon(points, color))
1279}
1280
1281/// Draws a filled polygon that may be concave, using ear clipping.
1282/// Self-intersecting polygons may not render correctly.
1283///
1284/// # Examples
1285///
1286/// ```
1287/// let pts = [
1288///     Vector2::new(100.0, 100.0), Vector2::new(200.0, 100.0),
1289///     Vector2::new(150.0, 150.0), Vector2::new(200.0, 200.0),
1290///     Vector2::new(100.0, 200.0),
1291/// ];
1292/// draw_polygon_concave(&pts, RED);
1293/// ```
1294pub fn draw_polygon_concave(points: &[Vector2], color: Color) {
1295    ctx(|s| s.draw_state.draw_polygon_concave(points, color))
1296}
1297
1298/// Draws text with its top-left corner at `(x, y)` with the given font, size, and color.
1299///
1300/// # Examples
1301///
1302/// ```
1303/// draw_text("Hello", 10.0, 10.0, 32.0, None, WHITE);           // default font
1304/// draw_text("Hello", 10.0, 10.0, 32.0, Some(&font), WHITE);    // loaded font
1305/// ```
1306pub fn draw_text(t: &str, x: f32, y: f32, size: f32, font: Option<&Font>, color: Color) {
1307    ctx(|s| s.draw_state.draw_text(&s.fonts, t, x, y, size, font, color));
1308}
1309
1310/// Draws a collection of `Span`s in sequence where each Span can have different properties such as
1311/// - text
1312/// - color
1313/// - size
1314/// - font
1315/// The `spans` should implement IntoIterator. Which means you can just pass an iterator.
1316///
1317/// ## Examples
1318///
1319/// ```
1320/// draw_rich_text(vec2(10.0, 10.0), &[
1321///     span("Hello there\n", WHITE),
1322///     span("My name is ", WHITE),
1323///     span("John Doe", RED)
1324///         .with_color(RED)
1325///         .with_size(32.0)
1326/// ]);
1327/// ```
1328pub fn draw_rich_text<'a, I>(
1329    position: Vector2,
1330    size: f32,
1331    font: Option<&Font>,
1332    color: Color,
1333    spans: I,
1334) where
1335    I: IntoIterator,
1336    I::Item: Borrow<Span<'a>>,
1337{
1338    ctx(|s| {
1339        s.draw_state
1340            .draw_richtext(position, size, font, color, spans)
1341    })
1342}
1343
1344/// Loads a `.ttf`/`.otf` font from path and returns the `Font` object.
1345/// (Do not load the font every frame, it will lag)
1346///
1347/// # Examples
1348///
1349/// ```
1350/// // Put this before the `flake::run()` to avoid loading it each frame
1351/// let font = load_font_from_path("src/Arial.ttf");
1352///
1353/// flake::run(|| {
1354///     draw_text("Hello", 10.0, 10.0, 32.0, Some(&font), WHITE)
1355/// })
1356/// ```
1357pub fn load_font_from_path(path: &str) -> Font {
1358    if STATE.get().is_some() {
1359        return ctx(|s| {
1360            s.load_font_from_path(path);
1361            s.fonts[s.fonts.len() - 1].clone()
1362        });
1363    }
1364
1365    PENDING_CONFIG.with_borrow_mut(|s| {
1366        let font = Font::from_path(s.fonts.len() + 1, path);
1367        s.fonts.push(font.clone());
1368        font
1369    })
1370}
1371
1372/// Loads a `.ttf`/`.otf` font from bytes and returns the `Font` object.
1373/// (Do not load the font every frame, it will lag)
1374///
1375/// # Examples
1376///
1377/// ```
1378/// // Put this before the `flake::run()` to avoid loading it each frame
1379/// let font = load_font_from_bytes(include_bytes!("Arial.ttf"));
1380///
1381/// flake::run(|| {
1382///     draw_text("Hello", 10.0, 10.0, 32.0, Some(&font), WHITE)
1383/// })
1384/// ```
1385pub fn load_font_from_bytes(bytes: &[u8]) -> Font {
1386    if STATE.get().is_some() {
1387        return ctx(|s| {
1388            s.load_font_from_bytes(bytes);
1389            s.fonts[s.fonts.len() - 1].clone()
1390        });
1391    }
1392
1393    PENDING_CONFIG.with_borrow_mut(|s| {
1394        let font = Font::from_bytes(s.fonts.len() + 1, bytes);
1395        s.fonts.push(font.clone());
1396        font
1397    })
1398}
1399
1400/// Returns the (width, height) of `text` when drawn with `draw_text` at this size.
1401pub fn measure_text(t: &str, size: f32, font: Option<&Font>) -> Vector2 {
1402    let (w, h) = ctx(|s| s.measure_text(t, size, font));
1403    Vector2::new(w, h)
1404}
1405
1406/// Draws a line from `(x1, y1)` to `(x2, y2)` with a triangular head at the end.
1407/// The tip extends `head_size` past `(x2, y2)`.
1408pub fn draw_arrow(
1409    x1: f32,
1410    y1: f32,
1411    x2: f32,
1412    y2: f32,
1413    thickness: f32,
1414    head_size: f32,
1415    color: Color,
1416) {
1417    ctx(|s| {
1418        s.draw_state
1419            .draw_arrow(x1, y1, x2, y2, thickness, head_size, color)
1420    });
1421}
1422
1423/// Returns the size of the monitor the window is on, or the window size if it can't be determined.
1424pub fn screen_size() -> Vector2 {
1425    let win = get_window();
1426    match win.current_monitor() {
1427        Some(m) => {
1428            let s = m.size();
1429            Vector2::new(s.width as f32, s.height as f32)
1430        }
1431        None => window_size(),
1432    }
1433}
1434
1435pub fn screen_width() -> f32 {
1436    screen_size().x
1437}
1438pub fn screen_height() -> f32 {
1439    screen_size().y
1440}
1441
1442// -- TEXTURES --------------------------------------------------------------------------------------------------------------
1443
1444/// Creates an empty texture of the given size. Fill it with `update_texture`.
1445pub fn create_empty_texture(width: u32, height: u32, filter_type: FilterType) -> Texture {
1446    ctx(|s| {
1447        let gpu = GpuTexture::empty(
1448            &s.device,
1449            width,
1450            height,
1451            filter_type,
1452            wgpu::TextureFormat::Rgba8UnormSrgb,
1453        )
1454        .expect("Couldn't create empty GpuTexture");
1455
1456        Texture {
1457            id: s.add_gpu_texture(gpu, false),
1458            width,
1459            height,
1460        }
1461    })
1462}
1463
1464/// Loads a texture from an image file using linear filtering. Panics if the file can't be read or decoded.
1465pub fn load_texture(path: &str) -> Texture {
1466    ctx(|s| {
1467        let image = image::load_from_memory(&std::fs::read(path).unwrap()).unwrap();
1468        let width = image.width();
1469        let height = image.height();
1470
1471        Texture {
1472            id: s.add_texture(image, FilterType::Linear),
1473            width,
1474            height,
1475        }
1476    })
1477}
1478
1479/// Same as `load_texture`, with an explicit `FilterType` (e.g. nearest for pixel art).
1480pub fn load_texture_with_filter_type(path: &str, filter_type: FilterType) -> Texture {
1481    ctx(|s| {
1482        let image = image::load_from_memory(&std::fs::read(path).unwrap()).unwrap();
1483        let width = image.width();
1484        let height = image.height();
1485
1486        Texture {
1487            id: s.add_texture(image, filter_type),
1488            width,
1489            height,
1490        }
1491    })
1492}
1493
1494/// Loads a texture from encoded image bytes (e.g. `include_bytes!`) using linear filtering.
1495pub fn load_texture_from_bytes(bytes: &[u8]) -> Texture {
1496    ctx(|s| {
1497        let image = image::load_from_memory(bytes).unwrap();
1498        let (width, height) = image.dimensions();
1499
1500        Texture {
1501            id: s.add_texture(image, FilterType::Linear),
1502            width,
1503            height,
1504        }
1505    })
1506}
1507
1508/// Loads a texture from raw RGBA `f32` pixels. `data.len()` must equal `width * height * 4`, otherwise this panics.
1509pub fn load_texture_from_bytes_with_filter_type(bytes: &[u8], filter_type: FilterType) -> Texture {
1510    ctx(|s| {
1511        let image = image::load_from_memory(bytes).unwrap();
1512        let (width, height) = image.dimensions();
1513
1514        Texture {
1515            id: s.add_texture(image, filter_type),
1516            width,
1517            height,
1518        }
1519    })
1520}
1521
1522/// Loads a texture from raw RGBA `f32` pixels. `data.len()` must equal `width * height * 4`, otherwise this panics.
1523pub fn load_texture_from_data(width: u32, height: u32, data: &[f32]) -> Texture {
1524    ctx(|s| {
1525        let img_buf = ImageBuffer::<Rgba<f32>, Vec<f32>>::from_raw(width, height, data.to_vec())
1526            .expect("Buffer size mismatch");
1527
1528        let dynamic_img = DynamicImage::ImageRgba32F(img_buf);
1529
1530        Texture {
1531            id: s.add_texture(dynamic_img, FilterType::Linear),
1532            width,
1533            height,
1534        }
1535    })
1536}
1537
1538/// Loads a texture from raw RGBA `f32` pixels.
1539/// `data.len()` must equal `width * height * 4`, otherwise this panics.
1540/// (Use nearest for pixel art)
1541pub fn load_texture_from_data_with_filter_type(
1542    width: u32,
1543    height: u32,
1544    data: &[f32],
1545    filter_type: FilterType,
1546) -> Texture {
1547    ctx(|s| {
1548        let img_buf = ImageBuffer::<Rgba<f32>, Vec<f32>>::from_raw(width, height, data.to_vec())
1549            .expect("Buffer size mismatch");
1550
1551        let dynamic_img = DynamicImage::ImageRgba32F(img_buf);
1552
1553        Texture {
1554            id: s.add_texture(dynamic_img, filter_type),
1555            width,
1556            height,
1557        }
1558    })
1559}
1560
1561/// Creates a texture from an `Image`.
1562pub fn load_texture_from_image(image: &Image) -> Texture {
1563    let tex = create_empty_texture(image.width, image.height, image.filter_type);
1564    update_texture(tex, image);
1565
1566    tex
1567}
1568
1569/// Draws a texture stretched to `w` x `h` with its top-left at `(x, y)`.
1570/// `tint` multiplies the texture color (use `WHITE` for none).
1571pub fn draw_texture(texture: Texture, x: f32, y: f32, w: f32, h: f32, tint: Color) {
1572    ctx(|s| s.draw_state.draw_texture(texture, x, y, w, h, tint))
1573}
1574
1575/// Draws a texture with extra options from `DrawTextureParams`: destination size,
1576/// source rect, horizontal/vertical flip, rotation (radians), pivot, and tint.
1577pub fn draw_texture_ex(texture: Texture, x: f32, y: f32, p: DrawTextureParams) {
1578    ctx(|s| s.draw_state.draw_texture_ex(texture, x, y, p))
1579}
1580
1581/// Replaces the pixels of an existing texture with those from `image`.
1582pub fn update_texture(texture: Texture, image: &Image) {
1583    ctx(|s| s.update_texture(texture.id, image))
1584}
1585
1586/// Creates a new RenderTarget.
1587pub fn render_target(width: u32, height: u32, filter_type: FilterType) -> RenderTarget {
1588    ctx(|s| s.create_render_target(width, height, filter_type))
1589}
1590
1591/// Sets the currently active camera being used to draw on.
1592pub fn set_camera(cam: &Camera2D) {
1593    ctx(|s| s.set_camera(cam))
1594}
1595
1596/// Resets the camera to the default screen one.
1597pub fn set_default_camera() {
1598    ctx(|s| s.set_default_camera())
1599}