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 {
54 egui_mq: EguiMq,
55 input_subscriber_id: usize,
56}
57
58// Global variable and global functions because it's more like macroquad way
59static mut EGUI: Option<Egui> = None;
60
61fn get_egui() -> &'static mut Egui {
62 unsafe {
63 if let Some(egui) = EGUI.as_mut() {
64 egui
65 } else {
66 EGUI = Some(Egui::new());
67 EGUI.as_mut().unwrap()
68 }
69 }
70}
71
72impl Egui {
73 fn new() -> Self {
74 Self {
75 egui_mq: EguiMq::new(unsafe { get_internal_gl() }.quad_context),
76 input_subscriber_id: macroquad::input::utils::register_input_subscriber(),
77 }
78 }
79
80 fn ui<F>(&mut self, f: F)
81 where
82 F: FnMut(&mut dyn mq::RenderingBackend, &egui::Context),
83 {
84 let gl = unsafe { get_internal_gl() };
85 macroquad::input::utils::repeat_all_miniquad_input(self, self.input_subscriber_id);
86
87 self.egui_mq.run(gl.quad_context, f);
88 }
89
90 fn draw(&mut self) {
91 let mut gl = unsafe { get_internal_gl() };
92 // Ensure that macroquad's shapes are not goint to be lost, and draw them now
93 gl.flush();
94 self.egui_mq.draw(gl.quad_context);
95 }
96}
97
98/// Calculates egui ui. Must be called once per frame.
99pub fn ui<F: FnMut(&egui::Context)>(mut f: F) {
100 get_egui().ui(|_, ctx| f(ctx))
101}
102
103/// Configure egui without beginning or ending a frame.
104pub fn cfg<F: FnOnce(&egui::Context)>(f: F) {
105 f(get_egui().egui_mq.egui_ctx());
106}
107
108/// Draw egui ui. Must be called after `ui` and once per frame.
109pub fn draw() {
110 get_egui().draw()
111}
112
113// Intended to be used only if you recreate the window, making the old EGUI instance invalid.
114#[doc(hidden)]
115pub fn reset_egui() {
116 unsafe {
117 EGUI = None;
118 }
119}
120
121impl mq::EventHandler for Egui {
122 fn update(&mut self) {}
123
124 fn draw(&mut self) {}
125
126 fn mouse_motion_event(&mut self, x: f32, y: f32) {
127 self.egui_mq.mouse_motion_event(x, y);
128 }
129
130 fn mouse_wheel_event(&mut self, dx: f32, dy: f32) {
131 self.egui_mq.mouse_wheel_event(dx, dy);
132 }
133
134 fn mouse_button_down_event(&mut self, mb: mq::MouseButton, x: f32, y: f32) {
135 self.egui_mq.mouse_button_down_event(mb, x, y);
136 }
137
138 fn mouse_button_up_event(&mut self, mb: mq::MouseButton, x: f32, y: f32) {
139 self.egui_mq.mouse_button_up_event(mb, x, y);
140 }
141
142 fn char_event(&mut self, character: char, _keymods: mq::KeyMods, _repeat: bool) {
143 self.egui_mq.char_event(character);
144 }
145
146 fn key_down_event(&mut self, keycode: mq::KeyCode, keymods: mq::KeyMods, _repeat: bool) {
147 self.egui_mq.key_down_event(keycode, keymods);
148 }
149
150 fn key_up_event(&mut self, keycode: mq::KeyCode, keymods: mq::KeyMods) {
151 self.egui_mq.key_up_event(keycode, keymods);
152 }
153}