egui_macroquad/
lib.rs

1//! # egui bindings for macroquad
2//!
3//! This is the easiest way to use egui. Just two functions!
4//!
5//! [Web demo.](https://optozorax.github.io/egui-macroquad/)
6//!
7//! # Usage
8//!
9//! You need to call [`ui`] when you need to get information from ui. Then, only after that function you must call [`draw`] function when you need to draw egui contents. All this functions should be called each frame and once per frame.
10//!
11//! Here is the small example on how to use this library:
12//! ```rust
13//! use macroquad::prelude::*;
14//!
15//! #[macroquad::main("egui with macroquad")]
16//! async fn main() {
17//!     loop {
18//!         clear_background(WHITE);
19//!
20//!         // Process keys, mouse etc.
21//!
22//!         egui_macroquad::ui(|egui_ctx| {
23//!             egui::Window::new("egui ❤ macroquad")
24//!                 .show(egui_ctx, |ui| {
25//!                     ui.label("Test");
26//!                 });
27//!         });
28//!
29//!         // Draw things before egui
30//!
31//!         egui_macroquad::draw();
32//!         
33//!         // Draw things after egui
34//!
35//!         next_frame().await;
36//!     }
37//! }
38//! ```
39//!
40//! # Building
41//!
42//! Building for native and for web works just as in `macroquad`. You can read about it [here](https://github.com/not-fl3/miniquad/#building-examples). Or you could look at building example at [egui-miniquad](https://github.com/not-fl3/egui-miniquad).
43//!
44//! But for wasm you will need to include two more `.js` files, which is plugins for quads, instruction is written [here](https://github.com/optozorax/quad-url).
45
46use egui_miniquad::EguiMq;
47use macroquad::prelude::*;
48use miniquad as mq;
49
50pub use egui;
51pub use macroquad;
52
53struct Egui(EguiMq, usize);
54
55// Global variable and global functions because it's more like macroquad way
56static mut EGUI: Option<Egui> = None;
57
58fn get_egui() -> &'static mut Egui {
59    unsafe {
60        if let Some(egui) = &mut EGUI {
61            egui
62        } else {
63            EGUI = Some(Egui::new());
64            EGUI.as_mut().unwrap()
65        }
66    }
67}
68
69impl Egui {
70    fn new() -> Self {
71        Self(
72            EguiMq::new(unsafe { get_internal_gl() }.quad_context),
73            macroquad::input::utils::register_input_subscriber(),
74        )
75    }
76
77    fn ui<F: FnOnce(&mut mq::Context, &egui::Context)>(&mut self, f: F) {
78        let gl = unsafe { get_internal_gl() };
79        macroquad::input::utils::repeat_all_miniquad_input(self, self.1);
80
81        self.0.run(gl.quad_context, f);
82    }
83
84    fn draw(&mut self) {
85        let mut gl = unsafe { get_internal_gl() };
86        // Ensure that macroquad's shapes are not goint to be lost, and draw them now
87        gl.flush();
88        self.0.draw(&mut gl.quad_context);
89    }
90}
91
92/// Calculates egui ui. Must be called once per frame.
93pub fn ui<F: FnOnce(&egui::Context)>(f: F) {
94    get_egui().ui(|_, ctx| f(ctx))
95}
96
97/// Configure egui without beginning or ending a frame.
98pub fn cfg<F: FnOnce(&egui::Context)>(f: F) {
99    f(get_egui().0.egui_ctx());
100}
101
102/// Draw egui ui. Must be called after `ui` and once per frame.
103pub fn draw() {
104    get_egui().draw()
105}
106
107impl mq::EventHandler for Egui {
108    fn update(&mut self, _ctx: &mut mq::Context) {}
109
110    fn draw(&mut self, _ctx: &mut mq::Context) {}
111
112    fn mouse_motion_event(&mut self, _ctx: &mut mq::Context, x: f32, y: f32) {
113        self.0.mouse_motion_event(x, y);
114    }
115
116    fn mouse_wheel_event(&mut self, _ctx: &mut mq::Context, dx: f32, dy: f32) {
117        self.0.mouse_wheel_event(dx, dy);
118    }
119
120    fn mouse_button_down_event(
121        &mut self,
122        ctx: &mut mq::Context,
123        mb: mq::MouseButton,
124        x: f32,
125        y: f32,
126    ) {
127        self.0.mouse_button_down_event(ctx, mb, x, y);
128    }
129
130    fn mouse_button_up_event(
131        &mut self,
132        ctx: &mut mq::Context,
133        mb: mq::MouseButton,
134        x: f32,
135        y: f32,
136    ) {
137        self.0.mouse_button_up_event(ctx, mb, x, y);
138    }
139
140    fn char_event(
141        &mut self,
142        _ctx: &mut mq::Context,
143        character: char,
144        _keymods: mq::KeyMods,
145        _repeat: bool,
146    ) {
147        self.0.char_event(character);
148    }
149
150    fn key_down_event(
151        &mut self,
152        ctx: &mut mq::Context,
153        keycode: mq::KeyCode,
154        keymods: mq::KeyMods,
155        _repeat: bool,
156    ) {
157        self.0.key_down_event(ctx, keycode, keymods);
158    }
159
160    fn key_up_event(&mut self, _ctx: &mut mq::Context, keycode: mq::KeyCode, keymods: mq::KeyMods) {
161        self.0.key_up_event(keycode, keymods);
162    }
163}