Struct Ui

Source
pub struct Ui {
    pub frame: u64,
    /* private fields */
}

Fields§

§frame: u64

Returns the number of frames that have elapsed since the program started.

Implementations§

Source§

impl Ui

Source

pub fn button<'a, P: Into<Option<Vec2>>, S: Into<UiContent<'a>>>( &mut self, position: P, label: S, ) -> bool

Examples found in repository?
examples/audio.rs (line 13)
4async fn main() {
5    set_pc_assets_folder("examples");
6
7    let sound1 = audio::load_sound("sound.wav").await.unwrap();
8    let sound2 = audio::load_sound("sound2.wav").await.unwrap();
9
10    loop {
11        clear_background(LIGHTGRAY);
12
13        if ui::root_ui().button(None, "Play sound 1") {
14            warn!("play 1!");
15            audio::play_sound_once(&sound1);
16        }
17        if ui::root_ui().button(None, "Play sound 2") {
18            warn!("play 2!");
19            audio::play_sound_once(&sound2);
20        }
21        next_frame().await
22    }
23}
More examples
Hide additional examples
examples/exit_dialog.rs (line 26)
5async fn main() {
6    prevent_quit();
7
8    let mut show_exit_dialog = false;
9    let mut user_decided_to_exit = false;
10
11    loop {
12        clear_background(GRAY);
13
14        if is_quit_requested() {
15            show_exit_dialog = true;
16        }
17
18        if show_exit_dialog {
19            let dialog_size = vec2(200., 70.);
20            let screen_size = vec2(screen_width(), screen_height());
21            let dialog_position = screen_size / 2. - dialog_size / 2.;
22            Window::new(hash!(), dialog_position, dialog_size).ui(&mut *root_ui(), |ui| {
23                ui.label(None, "Do you really want to quit?");
24                ui.separator();
25                ui.same_line(60.);
26                if ui.button(None, "Yes") {
27                    user_decided_to_exit = true;
28                }
29                ui.same_line(120.);
30                if ui.button(None, "No") {
31                    show_exit_dialog = false;
32                }
33            });
34        }
35
36        if user_decided_to_exit {
37            break;
38        }
39
40        next_frame().await
41    }
42}
examples/ui.rs (line 162)
136async fn main() {
137    let mut data = Data::new();
138
139    let mut data0 = String::new();
140    let mut data1 = String::new();
141
142    let mut text0 = String::new();
143    let mut text1 = String::new();
144
145    let mut number0 = 0.;
146    let mut number1 = 0.;
147
148    let texture: Texture2D = load_texture("examples/ferris.png").await.unwrap();
149
150    loop {
151        clear_background(WHITE);
152
153        widgets::Window::new(hash!(), vec2(400., 200.), vec2(320., 400.))
154            .label("Shop")
155            .titlebar(true)
156            .ui(&mut *root_ui(), |ui| {
157                for i in 0..30 {
158                    Group::new(hash!("shop", i), Vec2::new(300., 80.)).ui(ui, |ui| {
159                        ui.label(Vec2::new(10., 10.), &format!("Item N {i}"));
160                        ui.label(Vec2::new(260., 40.), "10/10");
161                        ui.label(Vec2::new(200., 58.), &format!("{} kr", 800));
162                        if ui.button(Vec2::new(260., 55.), "buy") {
163                            data.inventory.push(format!("Item {i}"));
164                        }
165                    });
166                }
167            });
168
169        widgets::Window::new(hash!(), vec2(100., 220.), vec2(542., 430.))
170            .label("Fitting window")
171            .titlebar(true)
172            .ui(&mut *root_ui(), |ui| {
173                Group::new(hash!(), Vec2::new(230., 400.)).ui(ui, |ui| {
174                    data.slots(ui);
175                });
176                Group::new(hash!(), Vec2::new(280., 400.)).ui(ui, |ui| {
177                    data.inventory(ui);
178                });
179            });
180
181        widgets::Window::new(hash!(), vec2(470., 50.), vec2(300., 300.))
182            .label("Megaui Showcase Window")
183            .ui(&mut *root_ui(), |ui| {
184                ui.tree_node(hash!(), "input", |ui| {
185                    ui.label(None, "Some random text");
186                    if ui.button(None, "click me") {
187                        println!("hi");
188                    }
189
190                    ui.separator();
191
192                    ui.label(None, "Some other random text");
193                    if ui.button(None, "other button") {
194                        println!("hi2");
195                    }
196
197                    ui.separator();
198
199                    ui.input_text(hash!(), "<- input text 1", &mut data0);
200                    ui.input_text(hash!(), "<- input text 2", &mut data1);
201                    ui.label(None, &format!("Text entered: \"{data0}\" and \"{data1}\""));
202
203                    ui.separator();
204                });
205                ui.tree_node(hash!(), "buttons", |ui| {
206                    widgets::Button::new(texture.clone())
207                        .size(vec2(120., 70.))
208                        .ui(ui);
209                    ui.same_line(0.);
210                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
211                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
212                    ui.same_line(0.);
213                    widgets::Button::new(texture.clone())
214                        .size(vec2(120., 70.))
215                        .ui(ui);
216                });
217                ui.tree_node(hash!(), "sliders", |ui| {
218                    ui.slider(hash!(), "[-10 .. 10]", -10f32..10f32, &mut number0);
219                    ui.slider(hash!(), "[0 .. 100]", 0f32..100f32, &mut number1);
220                });
221                ui.tree_node(hash!(), "editbox 1", |ui| {
222                    ui.label(None, "This is editbox!");
223                    ui.editbox(hash!(), vec2(285., 165.), &mut text0);
224                });
225                ui.tree_node(hash!(), "editbox 2", |ui| {
226                    ui.label(None, "This is editbox!");
227                    ui.editbox(hash!(), vec2(285., 165.), &mut text1);
228                });
229            });
230
231        match data.fit_command.take() {
232            Some(FittingCommand::Unfit { target_slot }) => data.set_item(target_slot, None),
233            Some(FittingCommand::Fit { target_slot, item }) => {
234                data.set_item(target_slot, Some(item));
235            }
236            Some(FittingCommand::Refit {
237                target_slot,
238                origin_slot,
239            }) => {
240                let origin_item = data
241                    .slots
242                    .iter()
243                    .find_map(|(_, slot)| {
244                        if slot.id == origin_slot {
245                            Some(slot.item.clone())
246                        } else {
247                            None
248                        }
249                    })
250                    .flatten();
251                data.set_item(target_slot, origin_item);
252                data.set_item(origin_slot, None);
253            }
254            None => {}
255        };
256
257        next_frame().await;
258    }
259}
examples/ui_skins.rs (line 221)
6async fn main() {
7    let skin1 = {
8        let font = load_ttf_font("examples/ui_assets/HTOWERT.TTF")
9            .await
10            .unwrap();
11        let label_style = root_ui()
12            .style_builder()
13            .with_font(&font)
14            .unwrap()
15            .text_color(Color::from_rgba(180, 180, 120, 255))
16            .font_size(30)
17            .build();
18
19        let window_style = root_ui()
20            .style_builder()
21            .background(
22                Image::from_file_with_format(
23                    include_bytes!("../examples/ui_assets/window_background.png"),
24                    None,
25                )
26                .unwrap(),
27            )
28            .background_margin(RectOffset::new(20.0, 20.0, 10.0, 10.0))
29            .margin(RectOffset::new(-20.0, -30.0, 0.0, 0.0))
30            .build();
31
32        let button_style = root_ui()
33            .style_builder()
34            .background(
35                Image::from_file_with_format(
36                    include_bytes!("../examples/ui_assets/button_background.png"),
37                    None,
38                )
39                .unwrap(),
40            )
41            .background_margin(RectOffset::new(37.0, 37.0, 5.0, 5.0))
42            .margin(RectOffset::new(10.0, 10.0, 0.0, 0.0))
43            .background_hovered(
44                Image::from_file_with_format(
45                    include_bytes!("../examples/ui_assets/button_hovered_background.png"),
46                    None,
47                )
48                .unwrap(),
49            )
50            .background_clicked(
51                Image::from_file_with_format(
52                    include_bytes!("../examples/ui_assets/button_clicked_background.png"),
53                    None,
54                )
55                .unwrap(),
56            )
57            .with_font(&font)
58            .unwrap()
59            .text_color(Color::from_rgba(180, 180, 100, 255))
60            .font_size(40)
61            .build();
62
63        let editbox_style = root_ui()
64            .style_builder()
65            .background_margin(RectOffset::new(0., 0., 0., 0.))
66            .with_font(&font)
67            .unwrap()
68            .text_color(Color::from_rgba(120, 120, 120, 255))
69            .color_selected(Color::from_rgba(190, 190, 190, 255))
70            .font_size(50)
71            .build();
72
73        Skin {
74            editbox_style,
75            window_style,
76            button_style,
77            label_style,
78            ..root_ui().default_skin()
79        }
80    };
81
82    let skin2 = {
83        let font = load_ttf_font("examples/ui_assets/MinimalPixel v2.ttf")
84            .await
85            .unwrap();
86        let label_style = root_ui()
87            .style_builder()
88            .with_font(&font)
89            .unwrap()
90            .text_color(Color::from_rgba(120, 120, 120, 255))
91            .font_size(25)
92            .build();
93
94        let window_style = root_ui()
95            .style_builder()
96            .background(
97                Image::from_file_with_format(
98                    include_bytes!("../examples/ui_assets/window_background_2.png"),
99                    None,
100                )
101                .unwrap(),
102            )
103            .background_margin(RectOffset::new(52.0, 52.0, 52.0, 52.0))
104            .margin(RectOffset::new(-30.0, 0.0, -30.0, 0.0))
105            .build();
106
107        let button_style = root_ui()
108            .style_builder()
109            .background(
110                Image::from_file_with_format(
111                    include_bytes!("../examples/ui_assets/button_background_2.png"),
112                    None,
113                )
114                .unwrap(),
115            )
116            .background_margin(RectOffset::new(8.0, 8.0, 8.0, 8.0))
117            .background_hovered(
118                Image::from_file_with_format(
119                    include_bytes!("../examples/ui_assets/button_hovered_background_2.png"),
120                    None,
121                )
122                .unwrap(),
123            )
124            .background_clicked(
125                Image::from_file_with_format(
126                    include_bytes!("../examples/ui_assets/button_clicked_background_2.png"),
127                    None,
128                )
129                .unwrap(),
130            )
131            .with_font(&font)
132            .unwrap()
133            .text_color(Color::from_rgba(180, 180, 100, 255))
134            .font_size(40)
135            .build();
136
137        let checkbox_style = root_ui()
138            .style_builder()
139            .background(
140                Image::from_file_with_format(
141                    include_bytes!("../examples/ui_assets/checkbox_background.png"),
142                    None,
143                )
144                .unwrap(),
145            )
146            .background_hovered(
147                Image::from_file_with_format(
148                    include_bytes!("../examples/ui_assets/checkbox_hovered_background.png"),
149                    None,
150                )
151                .unwrap(),
152            )
153            .background_clicked(
154                Image::from_file_with_format(
155                    include_bytes!("../examples/ui_assets/checkbox_clicked_background.png"),
156                    None,
157                )
158                .unwrap(),
159            )
160            .build();
161
162        let editbox_style = root_ui()
163            .style_builder()
164            .background(
165                Image::from_file_with_format(
166                    include_bytes!("../examples/ui_assets/editbox_background.png"),
167                    None,
168                )
169                .unwrap(),
170            )
171            .background_margin(RectOffset::new(2., 2., 2., 2.))
172            .with_font(&font)
173            .unwrap()
174            .text_color(Color::from_rgba(120, 120, 120, 255))
175            .font_size(25)
176            .build();
177
178        let combobox_style = root_ui()
179            .style_builder()
180            .background(
181                Image::from_file_with_format(
182                    include_bytes!("../examples/ui_assets/combobox_background.png"),
183                    None,
184                )
185                .unwrap(),
186            )
187            .background_margin(RectOffset::new(4., 25., 6., 6.))
188            .with_font(&font)
189            .unwrap()
190            .text_color(Color::from_rgba(120, 120, 120, 255))
191            .color(Color::from_rgba(210, 210, 210, 255))
192            .font_size(25)
193            .build();
194
195        Skin {
196            window_style,
197            button_style,
198            label_style,
199            checkbox_style,
200            editbox_style,
201            combobox_style,
202            ..root_ui().default_skin()
203        }
204    };
205    let default_skin = root_ui().default_skin().clone();
206
207    let mut window1_skin = skin1.clone();
208    let mut window2_skin = skin2.clone();
209
210    let mut checkbox = false;
211    let mut text = String::new();
212    let mut number = 0.0f32;
213    let mut combobox = 0;
214
215    loop {
216        clear_background(GRAY);
217
218        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
219            ui.label(None, "Window 1");
220
221            if ui.button(None, "Skin 1") {
222                window1_skin = skin1.clone();
223            }
224            if ui.button(None, "Skin 2") {
225                window1_skin = skin2.clone();
226            }
227            if ui.button(None, "No Skin") {
228                window1_skin = default_skin.clone();
229            }
230        });
231        root_ui().same_line(0.);
232        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
233            ui.label(None, "Window 2");
234            if ui.button(None, "Skin 1") {
235                window2_skin = skin1.clone();
236            }
237            if ui.button(None, "Skin 2") {
238                window2_skin = skin2.clone();
239            }
240            if ui.button(None, "No Skin") {
241                window2_skin = default_skin.clone();
242            }
243        });
244
245        root_ui().push_skin(&window1_skin);
246
247        root_ui().window(hash!(), vec2(20., 250.), vec2(300., 300.), |ui| {
248            widgets::Button::new("Play")
249                .position(vec2(65.0, 15.0))
250                .ui(ui);
251            widgets::Button::new("Options")
252                .position(vec2(40.0, 75.0))
253                .ui(ui);
254
255            widgets::Button::new("Quit")
256                .position(vec2(65.0, 195.0))
257                .ui(ui);
258        });
259        root_ui().pop_skin();
260
261        root_ui().push_skin(&window2_skin);
262        root_ui().window(hash!(), vec2(250., 20.), vec2(500., 250.), |ui| {
263            ui.checkbox(hash!(), "Checkbox 1", &mut checkbox);
264            ui.combo_box(
265                hash!(),
266                "Combobox",
267                &["First option", "Second option"],
268                &mut combobox,
269            );
270            ui.input_text(hash!(), "Text", &mut text);
271            ui.drag(hash!(), "Drag", None, &mut number);
272
273            widgets::Button::new("Apply")
274                .position(vec2(80.0, 150.0))
275                .ui(ui);
276            widgets::Button::new("Cancel")
277                .position(vec2(280.0, 150.0))
278                .ui(ui);
279        });
280        root_ui().pop_skin();
281
282        next_frame().await;
283    }
284}
examples/shadertoy.rs (line 123)
47async fn main() {
48    let ferris = load_texture("examples/rust.png").await.unwrap();
49    let (color_picker_texture, color_picker_image) = color_picker_texture(200, 200);
50
51    let mut fragment_shader = DEFAULT_FRAGMENT_SHADER.to_string();
52    let mut vertex_shader = DEFAULT_VERTEX_SHADER.to_string();
53
54    let pipeline_params = PipelineParams {
55        depth_write: true,
56        depth_test: Comparison::LessOrEqual,
57        ..Default::default()
58    };
59
60    let mut material = load_material(
61        ShaderSource::Glsl {
62            vertex: &vertex_shader,
63            fragment: &fragment_shader,
64        },
65        MaterialParams {
66            pipeline_params,
67            ..Default::default()
68        },
69    )
70    .unwrap();
71    let mut error: Option<String> = None;
72
73    enum Mesh {
74        Sphere,
75        Cube,
76        Plane,
77    }
78    let mut mesh = Mesh::Sphere;
79
80    let mut camera = Camera3D {
81        position: vec3(-15., 15., -5.),
82        up: vec3(0., 1., 0.),
83        target: vec3(0., 5., -5.),
84        ..Default::default()
85    };
86
87    let mut colorpicker_window = false;
88    let mut color_picking_uniform = None;
89
90    let mut new_uniform_window = false;
91    let mut new_uniform_name = String::new();
92    let mut uniforms: Vec<(String, Uniform)> = vec![];
93
94    loop {
95        clear_background(WHITE);
96
97        set_camera(&camera);
98
99        draw_grid(
100            20,
101            1.,
102            Color::new(0.55, 0.55, 0.55, 0.75),
103            Color::new(0.75, 0.75, 0.75, 0.75),
104        );
105
106        gl_use_material(&material);
107        match mesh {
108            Mesh::Plane => draw_plane(vec3(0., 2., 0.), vec2(5., 5.), Some(&ferris), WHITE),
109            Mesh::Sphere => draw_sphere(vec3(0., 6., 0.), 5., Some(&ferris), WHITE),
110            Mesh::Cube => draw_cube(vec3(0., 5., 0.), vec3(10., 10., 10.), Some(&ferris), WHITE),
111        }
112        gl_use_default_material();
113
114        set_default_camera();
115
116        let mut need_update = false;
117
118        widgets::Window::new(hash!(), vec2(20., 20.), vec2(470., 650.))
119            .label("Shader")
120            .ui(&mut *root_ui(), |ui| {
121                ui.label(None, "Camera: ");
122                ui.same_line(0.0);
123                if ui.button(None, "Ortho") {
124                    camera.projection = Projection::Orthographics;
125                }
126                ui.same_line(0.0);
127                if ui.button(None, "Perspective") {
128                    camera.projection = Projection::Perspective;
129                }
130                ui.label(None, "Mesh: ");
131                ui.same_line(0.0);
132                if ui.button(None, "Sphere") {
133                    mesh = Mesh::Sphere;
134                }
135                ui.same_line(0.0);
136                if ui.button(None, "Cube") {
137                    mesh = Mesh::Cube;
138                }
139                ui.same_line(0.0);
140                if ui.button(None, "Plane") {
141                    mesh = Mesh::Plane;
142                }
143
144                ui.label(None, "Uniforms:");
145                ui.separator();
146
147                for (i, (name, uniform)) in uniforms.iter_mut().enumerate() {
148                    ui.label(None, &format!("{name}"));
149                    ui.same_line(120.0);
150
151                    match uniform {
152                        Uniform::Float1(x) => {
153                            widgets::InputText::new(hash!(hash!(), i))
154                                .size(vec2(200.0, 19.0))
155                                .filter_numbers()
156                                .ui(ui, x);
157
158                            if let Ok(x) = x.parse::<f32>() {
159                                material.set_uniform(name, x);
160                            }
161                        }
162                        Uniform::Float2(x, y) => {
163                            widgets::InputText::new(hash!(hash!(), i))
164                                .size(vec2(99.0, 19.0))
165                                .filter_numbers()
166                                .ui(ui, x);
167
168                            ui.same_line(0.0);
169
170                            widgets::InputText::new(hash!(hash!(), i))
171                                .size(vec2(99.0, 19.0))
172                                .filter_numbers()
173                                .ui(ui, y);
174
175                            if let (Ok(x), Ok(y)) = (x.parse::<f32>(), y.parse::<f32>()) {
176                                material.set_uniform(name, (x, y));
177                            }
178                        }
179                        Uniform::Float3(x, y, z) => {
180                            widgets::InputText::new(hash!(hash!(), i))
181                                .size(vec2(65.0, 19.0))
182                                .filter_numbers()
183                                .ui(ui, x);
184
185                            ui.same_line(0.0);
186
187                            widgets::InputText::new(hash!(hash!(), i))
188                                .size(vec2(65.0, 19.0))
189                                .filter_numbers()
190                                .ui(ui, y);
191
192                            ui.same_line(0.0);
193
194                            widgets::InputText::new(hash!(hash!(), i))
195                                .size(vec2(65.0, 19.0))
196                                .filter_numbers()
197                                .ui(ui, z);
198
199                            if let (Ok(x), Ok(y), Ok(z)) =
200                                (x.parse::<f32>(), y.parse::<f32>(), z.parse::<f32>())
201                            {
202                                material.set_uniform(name, (x, y, z));
203                            }
204                        }
205
206                        Uniform::Color(color) => {
207                            let mut canvas = ui.canvas();
208
209                            let cursor = canvas.cursor();
210
211                            canvas.rect(
212                                Rect::new(cursor.x + 20.0, cursor.y, 50.0, 18.0),
213                                Color::new(0.2, 0.2, 0.2, 1.0),
214                                Color::new(color.x, color.y, color.z, 1.0),
215                            );
216
217                            if ui.button(None, "change") {
218                                colorpicker_window = true;
219                                color_picking_uniform = Some(name.to_owned());
220                            }
221                            material.set_uniform(name, (color.x, color.y, color.z));
222                        }
223                    }
224                }
225                ui.separator();
226                if ui.button(None, "New uniform") {
227                    new_uniform_window = true;
228                }
229                TreeNode::new(hash!(), "Fragment shader")
230                    .init_unfolded()
231                    .ui(ui, |ui| {
232                        if ui.editbox(hash!(), vec2(440., 200.), &mut fragment_shader) {
233                            need_update = true;
234                        };
235                    });
236                ui.tree_node(hash!(), "Vertex shader", |ui| {
237                    if ui.editbox(hash!(), vec2(440., 300.), &mut vertex_shader) {
238                        need_update = true;
239                    };
240                });
241
242                if let Some(ref error) = error {
243                    Label::new(error).multiline(14.0).ui(ui);
244                }
245            });
246
247        if new_uniform_window {
248            widgets::Window::new(hash!(), vec2(100., 100.), vec2(200., 80.))
249                .label("New uniform")
250                .ui(&mut *root_ui(), |ui| {
251                    if ui.active_window_focused() == false {
252                        new_uniform_window = false;
253                    }
254                    ui.input_text(hash!(), "Name", &mut new_uniform_name);
255                    let uniform_type = ui.combo_box(
256                        hash!(),
257                        "Type",
258                        &["Float1", "Float2", "Float3", "Color"],
259                        None,
260                    );
261
262                    if ui.button(None, "Add") {
263                        if new_uniform_name.is_empty() == false {
264                            let uniform = match uniform_type {
265                                0 => Uniform::Float1("0".to_string()),
266                                1 => Uniform::Float2("0".to_string(), "0".to_string()),
267                                2 => Uniform::Float3(
268                                    "0".to_string(),
269                                    "0".to_string(),
270                                    "0".to_string(),
271                                ),
272                                3 => Uniform::Color(vec3(0.0, 0.0, 0.0)),
273                                _ => unreachable!(),
274                            };
275                            uniforms.push((new_uniform_name.clone(), uniform));
276                            new_uniform_name.clear();
277                            need_update = true;
278                        }
279                        new_uniform_window = false;
280                    }
281
282                    ui.same_line(0.0);
283                    if ui.button(None, "Cancel") {
284                        new_uniform_window = false;
285                    }
286                });
287        }
288
289        if colorpicker_window {
290            colorpicker_window &= widgets::Window::new(hash!(), vec2(140., 100.), vec2(210., 240.))
291                .label("Colorpicker")
292                .ui(&mut *root_ui(), |ui| {
293                    if ui.active_window_focused() == false {
294                        colorpicker_window = false;
295                    }
296
297                    let mut canvas = ui.canvas();
298                    let cursor = canvas.cursor();
299                    let mouse = mouse_position();
300                    let x = mouse.0 as i32 - cursor.x as i32;
301                    let y = mouse.1 as i32 - (cursor.y as i32 + 20);
302
303                    let color = color_picker_image
304                        .get_pixel(x.max(0).min(199) as u32, y.max(0).min(199) as u32);
305
306                    canvas.rect(
307                        Rect::new(cursor.x, cursor.y, 200.0, 18.0),
308                        Color::new(0.0, 0.0, 0.0, 1.0),
309                        Color::new(color.r, color.g, color.b, 1.0),
310                    );
311                    canvas.image(
312                        Rect::new(cursor.x, cursor.y + 20.0, 200.0, 200.0),
313                        &color_picker_texture,
314                    );
315
316                    if x >= 0 && x < 200 && y >= 0 && y < 200 {
317                        canvas.rect(
318                            Rect::new(mouse.0 - 3.5, mouse.1 - 3.5, 7.0, 7.0),
319                            Color::new(0.3, 0.3, 0.3, 1.0),
320                            Color::new(1.0, 1.0, 1.0, 1.0),
321                        );
322
323                        if is_mouse_button_down(MouseButton::Left) {
324                            colorpicker_window = false;
325                            let uniform_name = color_picking_uniform.take().unwrap();
326
327                            uniforms
328                                .iter_mut()
329                                .find(|(name, _)| name == &uniform_name)
330                                .unwrap()
331                                .1 = Uniform::Color(vec3(color.r, color.g, color.b));
332                        }
333                    }
334                });
335        }
336
337        if need_update {
338            let uniforms = uniforms
339                .iter()
340                .map(|(name, uniform)| UniformDesc::new(name, uniform.uniform_type()))
341                .collect::<Vec<_>>();
342
343            match load_material(
344                ShaderSource::Glsl {
345                    vertex: &vertex_shader,
346                    fragment: &fragment_shader,
347                },
348                MaterialParams {
349                    pipeline_params,
350                    uniforms,
351                    textures: vec![],
352                },
353            ) {
354                Ok(new_material) => {
355                    material = new_material;
356                    error = None;
357                }
358                Err(err) => {
359                    error = Some(format!("{err:#?}"));
360                }
361            }
362        }
363
364        next_frame().await
365    }
366}
Source§

impl Ui

Source

pub fn checkbox(&mut self, id: Id, label: &str, data: &mut bool)

Examples found in repository?
examples/ui_skins.rs (line 263)
6async fn main() {
7    let skin1 = {
8        let font = load_ttf_font("examples/ui_assets/HTOWERT.TTF")
9            .await
10            .unwrap();
11        let label_style = root_ui()
12            .style_builder()
13            .with_font(&font)
14            .unwrap()
15            .text_color(Color::from_rgba(180, 180, 120, 255))
16            .font_size(30)
17            .build();
18
19        let window_style = root_ui()
20            .style_builder()
21            .background(
22                Image::from_file_with_format(
23                    include_bytes!("../examples/ui_assets/window_background.png"),
24                    None,
25                )
26                .unwrap(),
27            )
28            .background_margin(RectOffset::new(20.0, 20.0, 10.0, 10.0))
29            .margin(RectOffset::new(-20.0, -30.0, 0.0, 0.0))
30            .build();
31
32        let button_style = root_ui()
33            .style_builder()
34            .background(
35                Image::from_file_with_format(
36                    include_bytes!("../examples/ui_assets/button_background.png"),
37                    None,
38                )
39                .unwrap(),
40            )
41            .background_margin(RectOffset::new(37.0, 37.0, 5.0, 5.0))
42            .margin(RectOffset::new(10.0, 10.0, 0.0, 0.0))
43            .background_hovered(
44                Image::from_file_with_format(
45                    include_bytes!("../examples/ui_assets/button_hovered_background.png"),
46                    None,
47                )
48                .unwrap(),
49            )
50            .background_clicked(
51                Image::from_file_with_format(
52                    include_bytes!("../examples/ui_assets/button_clicked_background.png"),
53                    None,
54                )
55                .unwrap(),
56            )
57            .with_font(&font)
58            .unwrap()
59            .text_color(Color::from_rgba(180, 180, 100, 255))
60            .font_size(40)
61            .build();
62
63        let editbox_style = root_ui()
64            .style_builder()
65            .background_margin(RectOffset::new(0., 0., 0., 0.))
66            .with_font(&font)
67            .unwrap()
68            .text_color(Color::from_rgba(120, 120, 120, 255))
69            .color_selected(Color::from_rgba(190, 190, 190, 255))
70            .font_size(50)
71            .build();
72
73        Skin {
74            editbox_style,
75            window_style,
76            button_style,
77            label_style,
78            ..root_ui().default_skin()
79        }
80    };
81
82    let skin2 = {
83        let font = load_ttf_font("examples/ui_assets/MinimalPixel v2.ttf")
84            .await
85            .unwrap();
86        let label_style = root_ui()
87            .style_builder()
88            .with_font(&font)
89            .unwrap()
90            .text_color(Color::from_rgba(120, 120, 120, 255))
91            .font_size(25)
92            .build();
93
94        let window_style = root_ui()
95            .style_builder()
96            .background(
97                Image::from_file_with_format(
98                    include_bytes!("../examples/ui_assets/window_background_2.png"),
99                    None,
100                )
101                .unwrap(),
102            )
103            .background_margin(RectOffset::new(52.0, 52.0, 52.0, 52.0))
104            .margin(RectOffset::new(-30.0, 0.0, -30.0, 0.0))
105            .build();
106
107        let button_style = root_ui()
108            .style_builder()
109            .background(
110                Image::from_file_with_format(
111                    include_bytes!("../examples/ui_assets/button_background_2.png"),
112                    None,
113                )
114                .unwrap(),
115            )
116            .background_margin(RectOffset::new(8.0, 8.0, 8.0, 8.0))
117            .background_hovered(
118                Image::from_file_with_format(
119                    include_bytes!("../examples/ui_assets/button_hovered_background_2.png"),
120                    None,
121                )
122                .unwrap(),
123            )
124            .background_clicked(
125                Image::from_file_with_format(
126                    include_bytes!("../examples/ui_assets/button_clicked_background_2.png"),
127                    None,
128                )
129                .unwrap(),
130            )
131            .with_font(&font)
132            .unwrap()
133            .text_color(Color::from_rgba(180, 180, 100, 255))
134            .font_size(40)
135            .build();
136
137        let checkbox_style = root_ui()
138            .style_builder()
139            .background(
140                Image::from_file_with_format(
141                    include_bytes!("../examples/ui_assets/checkbox_background.png"),
142                    None,
143                )
144                .unwrap(),
145            )
146            .background_hovered(
147                Image::from_file_with_format(
148                    include_bytes!("../examples/ui_assets/checkbox_hovered_background.png"),
149                    None,
150                )
151                .unwrap(),
152            )
153            .background_clicked(
154                Image::from_file_with_format(
155                    include_bytes!("../examples/ui_assets/checkbox_clicked_background.png"),
156                    None,
157                )
158                .unwrap(),
159            )
160            .build();
161
162        let editbox_style = root_ui()
163            .style_builder()
164            .background(
165                Image::from_file_with_format(
166                    include_bytes!("../examples/ui_assets/editbox_background.png"),
167                    None,
168                )
169                .unwrap(),
170            )
171            .background_margin(RectOffset::new(2., 2., 2., 2.))
172            .with_font(&font)
173            .unwrap()
174            .text_color(Color::from_rgba(120, 120, 120, 255))
175            .font_size(25)
176            .build();
177
178        let combobox_style = root_ui()
179            .style_builder()
180            .background(
181                Image::from_file_with_format(
182                    include_bytes!("../examples/ui_assets/combobox_background.png"),
183                    None,
184                )
185                .unwrap(),
186            )
187            .background_margin(RectOffset::new(4., 25., 6., 6.))
188            .with_font(&font)
189            .unwrap()
190            .text_color(Color::from_rgba(120, 120, 120, 255))
191            .color(Color::from_rgba(210, 210, 210, 255))
192            .font_size(25)
193            .build();
194
195        Skin {
196            window_style,
197            button_style,
198            label_style,
199            checkbox_style,
200            editbox_style,
201            combobox_style,
202            ..root_ui().default_skin()
203        }
204    };
205    let default_skin = root_ui().default_skin().clone();
206
207    let mut window1_skin = skin1.clone();
208    let mut window2_skin = skin2.clone();
209
210    let mut checkbox = false;
211    let mut text = String::new();
212    let mut number = 0.0f32;
213    let mut combobox = 0;
214
215    loop {
216        clear_background(GRAY);
217
218        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
219            ui.label(None, "Window 1");
220
221            if ui.button(None, "Skin 1") {
222                window1_skin = skin1.clone();
223            }
224            if ui.button(None, "Skin 2") {
225                window1_skin = skin2.clone();
226            }
227            if ui.button(None, "No Skin") {
228                window1_skin = default_skin.clone();
229            }
230        });
231        root_ui().same_line(0.);
232        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
233            ui.label(None, "Window 2");
234            if ui.button(None, "Skin 1") {
235                window2_skin = skin1.clone();
236            }
237            if ui.button(None, "Skin 2") {
238                window2_skin = skin2.clone();
239            }
240            if ui.button(None, "No Skin") {
241                window2_skin = default_skin.clone();
242            }
243        });
244
245        root_ui().push_skin(&window1_skin);
246
247        root_ui().window(hash!(), vec2(20., 250.), vec2(300., 300.), |ui| {
248            widgets::Button::new("Play")
249                .position(vec2(65.0, 15.0))
250                .ui(ui);
251            widgets::Button::new("Options")
252                .position(vec2(40.0, 75.0))
253                .ui(ui);
254
255            widgets::Button::new("Quit")
256                .position(vec2(65.0, 195.0))
257                .ui(ui);
258        });
259        root_ui().pop_skin();
260
261        root_ui().push_skin(&window2_skin);
262        root_ui().window(hash!(), vec2(250., 20.), vec2(500., 250.), |ui| {
263            ui.checkbox(hash!(), "Checkbox 1", &mut checkbox);
264            ui.combo_box(
265                hash!(),
266                "Combobox",
267                &["First option", "Second option"],
268                &mut combobox,
269            );
270            ui.input_text(hash!(), "Text", &mut text);
271            ui.drag(hash!(), "Drag", None, &mut number);
272
273            widgets::Button::new("Apply")
274                .position(vec2(80.0, 150.0))
275                .ui(ui);
276            widgets::Button::new("Cancel")
277                .position(vec2(280.0, 150.0))
278                .ui(ui);
279        });
280        root_ui().pop_skin();
281
282        next_frame().await;
283    }
284}
Source§

impl Ui

Source

pub fn combo_box<'a>( &mut self, id: Id, label: &str, variants: &[&str], data: impl Into<Option<&'a mut usize>>, ) -> usize

Examples found in repository?
examples/ui_skins.rs (lines 264-269)
6async fn main() {
7    let skin1 = {
8        let font = load_ttf_font("examples/ui_assets/HTOWERT.TTF")
9            .await
10            .unwrap();
11        let label_style = root_ui()
12            .style_builder()
13            .with_font(&font)
14            .unwrap()
15            .text_color(Color::from_rgba(180, 180, 120, 255))
16            .font_size(30)
17            .build();
18
19        let window_style = root_ui()
20            .style_builder()
21            .background(
22                Image::from_file_with_format(
23                    include_bytes!("../examples/ui_assets/window_background.png"),
24                    None,
25                )
26                .unwrap(),
27            )
28            .background_margin(RectOffset::new(20.0, 20.0, 10.0, 10.0))
29            .margin(RectOffset::new(-20.0, -30.0, 0.0, 0.0))
30            .build();
31
32        let button_style = root_ui()
33            .style_builder()
34            .background(
35                Image::from_file_with_format(
36                    include_bytes!("../examples/ui_assets/button_background.png"),
37                    None,
38                )
39                .unwrap(),
40            )
41            .background_margin(RectOffset::new(37.0, 37.0, 5.0, 5.0))
42            .margin(RectOffset::new(10.0, 10.0, 0.0, 0.0))
43            .background_hovered(
44                Image::from_file_with_format(
45                    include_bytes!("../examples/ui_assets/button_hovered_background.png"),
46                    None,
47                )
48                .unwrap(),
49            )
50            .background_clicked(
51                Image::from_file_with_format(
52                    include_bytes!("../examples/ui_assets/button_clicked_background.png"),
53                    None,
54                )
55                .unwrap(),
56            )
57            .with_font(&font)
58            .unwrap()
59            .text_color(Color::from_rgba(180, 180, 100, 255))
60            .font_size(40)
61            .build();
62
63        let editbox_style = root_ui()
64            .style_builder()
65            .background_margin(RectOffset::new(0., 0., 0., 0.))
66            .with_font(&font)
67            .unwrap()
68            .text_color(Color::from_rgba(120, 120, 120, 255))
69            .color_selected(Color::from_rgba(190, 190, 190, 255))
70            .font_size(50)
71            .build();
72
73        Skin {
74            editbox_style,
75            window_style,
76            button_style,
77            label_style,
78            ..root_ui().default_skin()
79        }
80    };
81
82    let skin2 = {
83        let font = load_ttf_font("examples/ui_assets/MinimalPixel v2.ttf")
84            .await
85            .unwrap();
86        let label_style = root_ui()
87            .style_builder()
88            .with_font(&font)
89            .unwrap()
90            .text_color(Color::from_rgba(120, 120, 120, 255))
91            .font_size(25)
92            .build();
93
94        let window_style = root_ui()
95            .style_builder()
96            .background(
97                Image::from_file_with_format(
98                    include_bytes!("../examples/ui_assets/window_background_2.png"),
99                    None,
100                )
101                .unwrap(),
102            )
103            .background_margin(RectOffset::new(52.0, 52.0, 52.0, 52.0))
104            .margin(RectOffset::new(-30.0, 0.0, -30.0, 0.0))
105            .build();
106
107        let button_style = root_ui()
108            .style_builder()
109            .background(
110                Image::from_file_with_format(
111                    include_bytes!("../examples/ui_assets/button_background_2.png"),
112                    None,
113                )
114                .unwrap(),
115            )
116            .background_margin(RectOffset::new(8.0, 8.0, 8.0, 8.0))
117            .background_hovered(
118                Image::from_file_with_format(
119                    include_bytes!("../examples/ui_assets/button_hovered_background_2.png"),
120                    None,
121                )
122                .unwrap(),
123            )
124            .background_clicked(
125                Image::from_file_with_format(
126                    include_bytes!("../examples/ui_assets/button_clicked_background_2.png"),
127                    None,
128                )
129                .unwrap(),
130            )
131            .with_font(&font)
132            .unwrap()
133            .text_color(Color::from_rgba(180, 180, 100, 255))
134            .font_size(40)
135            .build();
136
137        let checkbox_style = root_ui()
138            .style_builder()
139            .background(
140                Image::from_file_with_format(
141                    include_bytes!("../examples/ui_assets/checkbox_background.png"),
142                    None,
143                )
144                .unwrap(),
145            )
146            .background_hovered(
147                Image::from_file_with_format(
148                    include_bytes!("../examples/ui_assets/checkbox_hovered_background.png"),
149                    None,
150                )
151                .unwrap(),
152            )
153            .background_clicked(
154                Image::from_file_with_format(
155                    include_bytes!("../examples/ui_assets/checkbox_clicked_background.png"),
156                    None,
157                )
158                .unwrap(),
159            )
160            .build();
161
162        let editbox_style = root_ui()
163            .style_builder()
164            .background(
165                Image::from_file_with_format(
166                    include_bytes!("../examples/ui_assets/editbox_background.png"),
167                    None,
168                )
169                .unwrap(),
170            )
171            .background_margin(RectOffset::new(2., 2., 2., 2.))
172            .with_font(&font)
173            .unwrap()
174            .text_color(Color::from_rgba(120, 120, 120, 255))
175            .font_size(25)
176            .build();
177
178        let combobox_style = root_ui()
179            .style_builder()
180            .background(
181                Image::from_file_with_format(
182                    include_bytes!("../examples/ui_assets/combobox_background.png"),
183                    None,
184                )
185                .unwrap(),
186            )
187            .background_margin(RectOffset::new(4., 25., 6., 6.))
188            .with_font(&font)
189            .unwrap()
190            .text_color(Color::from_rgba(120, 120, 120, 255))
191            .color(Color::from_rgba(210, 210, 210, 255))
192            .font_size(25)
193            .build();
194
195        Skin {
196            window_style,
197            button_style,
198            label_style,
199            checkbox_style,
200            editbox_style,
201            combobox_style,
202            ..root_ui().default_skin()
203        }
204    };
205    let default_skin = root_ui().default_skin().clone();
206
207    let mut window1_skin = skin1.clone();
208    let mut window2_skin = skin2.clone();
209
210    let mut checkbox = false;
211    let mut text = String::new();
212    let mut number = 0.0f32;
213    let mut combobox = 0;
214
215    loop {
216        clear_background(GRAY);
217
218        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
219            ui.label(None, "Window 1");
220
221            if ui.button(None, "Skin 1") {
222                window1_skin = skin1.clone();
223            }
224            if ui.button(None, "Skin 2") {
225                window1_skin = skin2.clone();
226            }
227            if ui.button(None, "No Skin") {
228                window1_skin = default_skin.clone();
229            }
230        });
231        root_ui().same_line(0.);
232        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
233            ui.label(None, "Window 2");
234            if ui.button(None, "Skin 1") {
235                window2_skin = skin1.clone();
236            }
237            if ui.button(None, "Skin 2") {
238                window2_skin = skin2.clone();
239            }
240            if ui.button(None, "No Skin") {
241                window2_skin = default_skin.clone();
242            }
243        });
244
245        root_ui().push_skin(&window1_skin);
246
247        root_ui().window(hash!(), vec2(20., 250.), vec2(300., 300.), |ui| {
248            widgets::Button::new("Play")
249                .position(vec2(65.0, 15.0))
250                .ui(ui);
251            widgets::Button::new("Options")
252                .position(vec2(40.0, 75.0))
253                .ui(ui);
254
255            widgets::Button::new("Quit")
256                .position(vec2(65.0, 195.0))
257                .ui(ui);
258        });
259        root_ui().pop_skin();
260
261        root_ui().push_skin(&window2_skin);
262        root_ui().window(hash!(), vec2(250., 20.), vec2(500., 250.), |ui| {
263            ui.checkbox(hash!(), "Checkbox 1", &mut checkbox);
264            ui.combo_box(
265                hash!(),
266                "Combobox",
267                &["First option", "Second option"],
268                &mut combobox,
269            );
270            ui.input_text(hash!(), "Text", &mut text);
271            ui.drag(hash!(), "Drag", None, &mut number);
272
273            widgets::Button::new("Apply")
274                .position(vec2(80.0, 150.0))
275                .ui(ui);
276            widgets::Button::new("Cancel")
277                .position(vec2(280.0, 150.0))
278                .ui(ui);
279        });
280        root_ui().pop_skin();
281
282        next_frame().await;
283    }
284}
More examples
Hide additional examples
examples/shadertoy.rs (lines 255-260)
47async fn main() {
48    let ferris = load_texture("examples/rust.png").await.unwrap();
49    let (color_picker_texture, color_picker_image) = color_picker_texture(200, 200);
50
51    let mut fragment_shader = DEFAULT_FRAGMENT_SHADER.to_string();
52    let mut vertex_shader = DEFAULT_VERTEX_SHADER.to_string();
53
54    let pipeline_params = PipelineParams {
55        depth_write: true,
56        depth_test: Comparison::LessOrEqual,
57        ..Default::default()
58    };
59
60    let mut material = load_material(
61        ShaderSource::Glsl {
62            vertex: &vertex_shader,
63            fragment: &fragment_shader,
64        },
65        MaterialParams {
66            pipeline_params,
67            ..Default::default()
68        },
69    )
70    .unwrap();
71    let mut error: Option<String> = None;
72
73    enum Mesh {
74        Sphere,
75        Cube,
76        Plane,
77    }
78    let mut mesh = Mesh::Sphere;
79
80    let mut camera = Camera3D {
81        position: vec3(-15., 15., -5.),
82        up: vec3(0., 1., 0.),
83        target: vec3(0., 5., -5.),
84        ..Default::default()
85    };
86
87    let mut colorpicker_window = false;
88    let mut color_picking_uniform = None;
89
90    let mut new_uniform_window = false;
91    let mut new_uniform_name = String::new();
92    let mut uniforms: Vec<(String, Uniform)> = vec![];
93
94    loop {
95        clear_background(WHITE);
96
97        set_camera(&camera);
98
99        draw_grid(
100            20,
101            1.,
102            Color::new(0.55, 0.55, 0.55, 0.75),
103            Color::new(0.75, 0.75, 0.75, 0.75),
104        );
105
106        gl_use_material(&material);
107        match mesh {
108            Mesh::Plane => draw_plane(vec3(0., 2., 0.), vec2(5., 5.), Some(&ferris), WHITE),
109            Mesh::Sphere => draw_sphere(vec3(0., 6., 0.), 5., Some(&ferris), WHITE),
110            Mesh::Cube => draw_cube(vec3(0., 5., 0.), vec3(10., 10., 10.), Some(&ferris), WHITE),
111        }
112        gl_use_default_material();
113
114        set_default_camera();
115
116        let mut need_update = false;
117
118        widgets::Window::new(hash!(), vec2(20., 20.), vec2(470., 650.))
119            .label("Shader")
120            .ui(&mut *root_ui(), |ui| {
121                ui.label(None, "Camera: ");
122                ui.same_line(0.0);
123                if ui.button(None, "Ortho") {
124                    camera.projection = Projection::Orthographics;
125                }
126                ui.same_line(0.0);
127                if ui.button(None, "Perspective") {
128                    camera.projection = Projection::Perspective;
129                }
130                ui.label(None, "Mesh: ");
131                ui.same_line(0.0);
132                if ui.button(None, "Sphere") {
133                    mesh = Mesh::Sphere;
134                }
135                ui.same_line(0.0);
136                if ui.button(None, "Cube") {
137                    mesh = Mesh::Cube;
138                }
139                ui.same_line(0.0);
140                if ui.button(None, "Plane") {
141                    mesh = Mesh::Plane;
142                }
143
144                ui.label(None, "Uniforms:");
145                ui.separator();
146
147                for (i, (name, uniform)) in uniforms.iter_mut().enumerate() {
148                    ui.label(None, &format!("{name}"));
149                    ui.same_line(120.0);
150
151                    match uniform {
152                        Uniform::Float1(x) => {
153                            widgets::InputText::new(hash!(hash!(), i))
154                                .size(vec2(200.0, 19.0))
155                                .filter_numbers()
156                                .ui(ui, x);
157
158                            if let Ok(x) = x.parse::<f32>() {
159                                material.set_uniform(name, x);
160                            }
161                        }
162                        Uniform::Float2(x, y) => {
163                            widgets::InputText::new(hash!(hash!(), i))
164                                .size(vec2(99.0, 19.0))
165                                .filter_numbers()
166                                .ui(ui, x);
167
168                            ui.same_line(0.0);
169
170                            widgets::InputText::new(hash!(hash!(), i))
171                                .size(vec2(99.0, 19.0))
172                                .filter_numbers()
173                                .ui(ui, y);
174
175                            if let (Ok(x), Ok(y)) = (x.parse::<f32>(), y.parse::<f32>()) {
176                                material.set_uniform(name, (x, y));
177                            }
178                        }
179                        Uniform::Float3(x, y, z) => {
180                            widgets::InputText::new(hash!(hash!(), i))
181                                .size(vec2(65.0, 19.0))
182                                .filter_numbers()
183                                .ui(ui, x);
184
185                            ui.same_line(0.0);
186
187                            widgets::InputText::new(hash!(hash!(), i))
188                                .size(vec2(65.0, 19.0))
189                                .filter_numbers()
190                                .ui(ui, y);
191
192                            ui.same_line(0.0);
193
194                            widgets::InputText::new(hash!(hash!(), i))
195                                .size(vec2(65.0, 19.0))
196                                .filter_numbers()
197                                .ui(ui, z);
198
199                            if let (Ok(x), Ok(y), Ok(z)) =
200                                (x.parse::<f32>(), y.parse::<f32>(), z.parse::<f32>())
201                            {
202                                material.set_uniform(name, (x, y, z));
203                            }
204                        }
205
206                        Uniform::Color(color) => {
207                            let mut canvas = ui.canvas();
208
209                            let cursor = canvas.cursor();
210
211                            canvas.rect(
212                                Rect::new(cursor.x + 20.0, cursor.y, 50.0, 18.0),
213                                Color::new(0.2, 0.2, 0.2, 1.0),
214                                Color::new(color.x, color.y, color.z, 1.0),
215                            );
216
217                            if ui.button(None, "change") {
218                                colorpicker_window = true;
219                                color_picking_uniform = Some(name.to_owned());
220                            }
221                            material.set_uniform(name, (color.x, color.y, color.z));
222                        }
223                    }
224                }
225                ui.separator();
226                if ui.button(None, "New uniform") {
227                    new_uniform_window = true;
228                }
229                TreeNode::new(hash!(), "Fragment shader")
230                    .init_unfolded()
231                    .ui(ui, |ui| {
232                        if ui.editbox(hash!(), vec2(440., 200.), &mut fragment_shader) {
233                            need_update = true;
234                        };
235                    });
236                ui.tree_node(hash!(), "Vertex shader", |ui| {
237                    if ui.editbox(hash!(), vec2(440., 300.), &mut vertex_shader) {
238                        need_update = true;
239                    };
240                });
241
242                if let Some(ref error) = error {
243                    Label::new(error).multiline(14.0).ui(ui);
244                }
245            });
246
247        if new_uniform_window {
248            widgets::Window::new(hash!(), vec2(100., 100.), vec2(200., 80.))
249                .label("New uniform")
250                .ui(&mut *root_ui(), |ui| {
251                    if ui.active_window_focused() == false {
252                        new_uniform_window = false;
253                    }
254                    ui.input_text(hash!(), "Name", &mut new_uniform_name);
255                    let uniform_type = ui.combo_box(
256                        hash!(),
257                        "Type",
258                        &["Float1", "Float2", "Float3", "Color"],
259                        None,
260                    );
261
262                    if ui.button(None, "Add") {
263                        if new_uniform_name.is_empty() == false {
264                            let uniform = match uniform_type {
265                                0 => Uniform::Float1("0".to_string()),
266                                1 => Uniform::Float2("0".to_string(), "0".to_string()),
267                                2 => Uniform::Float3(
268                                    "0".to_string(),
269                                    "0".to_string(),
270                                    "0".to_string(),
271                                ),
272                                3 => Uniform::Color(vec3(0.0, 0.0, 0.0)),
273                                _ => unreachable!(),
274                            };
275                            uniforms.push((new_uniform_name.clone(), uniform));
276                            new_uniform_name.clear();
277                            need_update = true;
278                        }
279                        new_uniform_window = false;
280                    }
281
282                    ui.same_line(0.0);
283                    if ui.button(None, "Cancel") {
284                        new_uniform_window = false;
285                    }
286                });
287        }
288
289        if colorpicker_window {
290            colorpicker_window &= widgets::Window::new(hash!(), vec2(140., 100.), vec2(210., 240.))
291                .label("Colorpicker")
292                .ui(&mut *root_ui(), |ui| {
293                    if ui.active_window_focused() == false {
294                        colorpicker_window = false;
295                    }
296
297                    let mut canvas = ui.canvas();
298                    let cursor = canvas.cursor();
299                    let mouse = mouse_position();
300                    let x = mouse.0 as i32 - cursor.x as i32;
301                    let y = mouse.1 as i32 - (cursor.y as i32 + 20);
302
303                    let color = color_picker_image
304                        .get_pixel(x.max(0).min(199) as u32, y.max(0).min(199) as u32);
305
306                    canvas.rect(
307                        Rect::new(cursor.x, cursor.y, 200.0, 18.0),
308                        Color::new(0.0, 0.0, 0.0, 1.0),
309                        Color::new(color.r, color.g, color.b, 1.0),
310                    );
311                    canvas.image(
312                        Rect::new(cursor.x, cursor.y + 20.0, 200.0, 200.0),
313                        &color_picker_texture,
314                    );
315
316                    if x >= 0 && x < 200 && y >= 0 && y < 200 {
317                        canvas.rect(
318                            Rect::new(mouse.0 - 3.5, mouse.1 - 3.5, 7.0, 7.0),
319                            Color::new(0.3, 0.3, 0.3, 1.0),
320                            Color::new(1.0, 1.0, 1.0, 1.0),
321                        );
322
323                        if is_mouse_button_down(MouseButton::Left) {
324                            colorpicker_window = false;
325                            let uniform_name = color_picking_uniform.take().unwrap();
326
327                            uniforms
328                                .iter_mut()
329                                .find(|(name, _)| name == &uniform_name)
330                                .unwrap()
331                                .1 = Uniform::Color(vec3(color.r, color.g, color.b));
332                        }
333                    }
334                });
335        }
336
337        if need_update {
338            let uniforms = uniforms
339                .iter()
340                .map(|(name, uniform)| UniformDesc::new(name, uniform.uniform_type()))
341                .collect::<Vec<_>>();
342
343            match load_material(
344                ShaderSource::Glsl {
345                    vertex: &vertex_shader,
346                    fragment: &fragment_shader,
347                },
348                MaterialParams {
349                    pipeline_params,
350                    uniforms,
351                    textures: vec![],
352                },
353            ) {
354                Ok(new_material) => {
355                    material = new_material;
356                    error = None;
357                }
358                Err(err) => {
359                    error = Some(format!("{err:#?}"));
360                }
361            }
362        }
363
364        next_frame().await
365    }
366}
Source§

impl Ui

Source

pub fn drag<T: Num, T1: Into<Option<(T, T)>>>( &mut self, id: Id, label: &str, range: T1, data: &mut T, )

Examples found in repository?
examples/ui_skins.rs (line 271)
6async fn main() {
7    let skin1 = {
8        let font = load_ttf_font("examples/ui_assets/HTOWERT.TTF")
9            .await
10            .unwrap();
11        let label_style = root_ui()
12            .style_builder()
13            .with_font(&font)
14            .unwrap()
15            .text_color(Color::from_rgba(180, 180, 120, 255))
16            .font_size(30)
17            .build();
18
19        let window_style = root_ui()
20            .style_builder()
21            .background(
22                Image::from_file_with_format(
23                    include_bytes!("../examples/ui_assets/window_background.png"),
24                    None,
25                )
26                .unwrap(),
27            )
28            .background_margin(RectOffset::new(20.0, 20.0, 10.0, 10.0))
29            .margin(RectOffset::new(-20.0, -30.0, 0.0, 0.0))
30            .build();
31
32        let button_style = root_ui()
33            .style_builder()
34            .background(
35                Image::from_file_with_format(
36                    include_bytes!("../examples/ui_assets/button_background.png"),
37                    None,
38                )
39                .unwrap(),
40            )
41            .background_margin(RectOffset::new(37.0, 37.0, 5.0, 5.0))
42            .margin(RectOffset::new(10.0, 10.0, 0.0, 0.0))
43            .background_hovered(
44                Image::from_file_with_format(
45                    include_bytes!("../examples/ui_assets/button_hovered_background.png"),
46                    None,
47                )
48                .unwrap(),
49            )
50            .background_clicked(
51                Image::from_file_with_format(
52                    include_bytes!("../examples/ui_assets/button_clicked_background.png"),
53                    None,
54                )
55                .unwrap(),
56            )
57            .with_font(&font)
58            .unwrap()
59            .text_color(Color::from_rgba(180, 180, 100, 255))
60            .font_size(40)
61            .build();
62
63        let editbox_style = root_ui()
64            .style_builder()
65            .background_margin(RectOffset::new(0., 0., 0., 0.))
66            .with_font(&font)
67            .unwrap()
68            .text_color(Color::from_rgba(120, 120, 120, 255))
69            .color_selected(Color::from_rgba(190, 190, 190, 255))
70            .font_size(50)
71            .build();
72
73        Skin {
74            editbox_style,
75            window_style,
76            button_style,
77            label_style,
78            ..root_ui().default_skin()
79        }
80    };
81
82    let skin2 = {
83        let font = load_ttf_font("examples/ui_assets/MinimalPixel v2.ttf")
84            .await
85            .unwrap();
86        let label_style = root_ui()
87            .style_builder()
88            .with_font(&font)
89            .unwrap()
90            .text_color(Color::from_rgba(120, 120, 120, 255))
91            .font_size(25)
92            .build();
93
94        let window_style = root_ui()
95            .style_builder()
96            .background(
97                Image::from_file_with_format(
98                    include_bytes!("../examples/ui_assets/window_background_2.png"),
99                    None,
100                )
101                .unwrap(),
102            )
103            .background_margin(RectOffset::new(52.0, 52.0, 52.0, 52.0))
104            .margin(RectOffset::new(-30.0, 0.0, -30.0, 0.0))
105            .build();
106
107        let button_style = root_ui()
108            .style_builder()
109            .background(
110                Image::from_file_with_format(
111                    include_bytes!("../examples/ui_assets/button_background_2.png"),
112                    None,
113                )
114                .unwrap(),
115            )
116            .background_margin(RectOffset::new(8.0, 8.0, 8.0, 8.0))
117            .background_hovered(
118                Image::from_file_with_format(
119                    include_bytes!("../examples/ui_assets/button_hovered_background_2.png"),
120                    None,
121                )
122                .unwrap(),
123            )
124            .background_clicked(
125                Image::from_file_with_format(
126                    include_bytes!("../examples/ui_assets/button_clicked_background_2.png"),
127                    None,
128                )
129                .unwrap(),
130            )
131            .with_font(&font)
132            .unwrap()
133            .text_color(Color::from_rgba(180, 180, 100, 255))
134            .font_size(40)
135            .build();
136
137        let checkbox_style = root_ui()
138            .style_builder()
139            .background(
140                Image::from_file_with_format(
141                    include_bytes!("../examples/ui_assets/checkbox_background.png"),
142                    None,
143                )
144                .unwrap(),
145            )
146            .background_hovered(
147                Image::from_file_with_format(
148                    include_bytes!("../examples/ui_assets/checkbox_hovered_background.png"),
149                    None,
150                )
151                .unwrap(),
152            )
153            .background_clicked(
154                Image::from_file_with_format(
155                    include_bytes!("../examples/ui_assets/checkbox_clicked_background.png"),
156                    None,
157                )
158                .unwrap(),
159            )
160            .build();
161
162        let editbox_style = root_ui()
163            .style_builder()
164            .background(
165                Image::from_file_with_format(
166                    include_bytes!("../examples/ui_assets/editbox_background.png"),
167                    None,
168                )
169                .unwrap(),
170            )
171            .background_margin(RectOffset::new(2., 2., 2., 2.))
172            .with_font(&font)
173            .unwrap()
174            .text_color(Color::from_rgba(120, 120, 120, 255))
175            .font_size(25)
176            .build();
177
178        let combobox_style = root_ui()
179            .style_builder()
180            .background(
181                Image::from_file_with_format(
182                    include_bytes!("../examples/ui_assets/combobox_background.png"),
183                    None,
184                )
185                .unwrap(),
186            )
187            .background_margin(RectOffset::new(4., 25., 6., 6.))
188            .with_font(&font)
189            .unwrap()
190            .text_color(Color::from_rgba(120, 120, 120, 255))
191            .color(Color::from_rgba(210, 210, 210, 255))
192            .font_size(25)
193            .build();
194
195        Skin {
196            window_style,
197            button_style,
198            label_style,
199            checkbox_style,
200            editbox_style,
201            combobox_style,
202            ..root_ui().default_skin()
203        }
204    };
205    let default_skin = root_ui().default_skin().clone();
206
207    let mut window1_skin = skin1.clone();
208    let mut window2_skin = skin2.clone();
209
210    let mut checkbox = false;
211    let mut text = String::new();
212    let mut number = 0.0f32;
213    let mut combobox = 0;
214
215    loop {
216        clear_background(GRAY);
217
218        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
219            ui.label(None, "Window 1");
220
221            if ui.button(None, "Skin 1") {
222                window1_skin = skin1.clone();
223            }
224            if ui.button(None, "Skin 2") {
225                window1_skin = skin2.clone();
226            }
227            if ui.button(None, "No Skin") {
228                window1_skin = default_skin.clone();
229            }
230        });
231        root_ui().same_line(0.);
232        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
233            ui.label(None, "Window 2");
234            if ui.button(None, "Skin 1") {
235                window2_skin = skin1.clone();
236            }
237            if ui.button(None, "Skin 2") {
238                window2_skin = skin2.clone();
239            }
240            if ui.button(None, "No Skin") {
241                window2_skin = default_skin.clone();
242            }
243        });
244
245        root_ui().push_skin(&window1_skin);
246
247        root_ui().window(hash!(), vec2(20., 250.), vec2(300., 300.), |ui| {
248            widgets::Button::new("Play")
249                .position(vec2(65.0, 15.0))
250                .ui(ui);
251            widgets::Button::new("Options")
252                .position(vec2(40.0, 75.0))
253                .ui(ui);
254
255            widgets::Button::new("Quit")
256                .position(vec2(65.0, 195.0))
257                .ui(ui);
258        });
259        root_ui().pop_skin();
260
261        root_ui().push_skin(&window2_skin);
262        root_ui().window(hash!(), vec2(250., 20.), vec2(500., 250.), |ui| {
263            ui.checkbox(hash!(), "Checkbox 1", &mut checkbox);
264            ui.combo_box(
265                hash!(),
266                "Combobox",
267                &["First option", "Second option"],
268                &mut combobox,
269            );
270            ui.input_text(hash!(), "Text", &mut text);
271            ui.drag(hash!(), "Drag", None, &mut number);
272
273            widgets::Button::new("Apply")
274                .position(vec2(80.0, 150.0))
275                .ui(ui);
276            widgets::Button::new("Cancel")
277                .position(vec2(280.0, 150.0))
278                .ui(ui);
279        });
280        root_ui().pop_skin();
281
282        next_frame().await;
283    }
284}
Source§

impl Ui

Source

pub fn editbox(&mut self, id: Id, size: Vec2, text: &mut String) -> bool

Examples found in repository?
examples/ui.rs (line 223)
136async fn main() {
137    let mut data = Data::new();
138
139    let mut data0 = String::new();
140    let mut data1 = String::new();
141
142    let mut text0 = String::new();
143    let mut text1 = String::new();
144
145    let mut number0 = 0.;
146    let mut number1 = 0.;
147
148    let texture: Texture2D = load_texture("examples/ferris.png").await.unwrap();
149
150    loop {
151        clear_background(WHITE);
152
153        widgets::Window::new(hash!(), vec2(400., 200.), vec2(320., 400.))
154            .label("Shop")
155            .titlebar(true)
156            .ui(&mut *root_ui(), |ui| {
157                for i in 0..30 {
158                    Group::new(hash!("shop", i), Vec2::new(300., 80.)).ui(ui, |ui| {
159                        ui.label(Vec2::new(10., 10.), &format!("Item N {i}"));
160                        ui.label(Vec2::new(260., 40.), "10/10");
161                        ui.label(Vec2::new(200., 58.), &format!("{} kr", 800));
162                        if ui.button(Vec2::new(260., 55.), "buy") {
163                            data.inventory.push(format!("Item {i}"));
164                        }
165                    });
166                }
167            });
168
169        widgets::Window::new(hash!(), vec2(100., 220.), vec2(542., 430.))
170            .label("Fitting window")
171            .titlebar(true)
172            .ui(&mut *root_ui(), |ui| {
173                Group::new(hash!(), Vec2::new(230., 400.)).ui(ui, |ui| {
174                    data.slots(ui);
175                });
176                Group::new(hash!(), Vec2::new(280., 400.)).ui(ui, |ui| {
177                    data.inventory(ui);
178                });
179            });
180
181        widgets::Window::new(hash!(), vec2(470., 50.), vec2(300., 300.))
182            .label("Megaui Showcase Window")
183            .ui(&mut *root_ui(), |ui| {
184                ui.tree_node(hash!(), "input", |ui| {
185                    ui.label(None, "Some random text");
186                    if ui.button(None, "click me") {
187                        println!("hi");
188                    }
189
190                    ui.separator();
191
192                    ui.label(None, "Some other random text");
193                    if ui.button(None, "other button") {
194                        println!("hi2");
195                    }
196
197                    ui.separator();
198
199                    ui.input_text(hash!(), "<- input text 1", &mut data0);
200                    ui.input_text(hash!(), "<- input text 2", &mut data1);
201                    ui.label(None, &format!("Text entered: \"{data0}\" and \"{data1}\""));
202
203                    ui.separator();
204                });
205                ui.tree_node(hash!(), "buttons", |ui| {
206                    widgets::Button::new(texture.clone())
207                        .size(vec2(120., 70.))
208                        .ui(ui);
209                    ui.same_line(0.);
210                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
211                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
212                    ui.same_line(0.);
213                    widgets::Button::new(texture.clone())
214                        .size(vec2(120., 70.))
215                        .ui(ui);
216                });
217                ui.tree_node(hash!(), "sliders", |ui| {
218                    ui.slider(hash!(), "[-10 .. 10]", -10f32..10f32, &mut number0);
219                    ui.slider(hash!(), "[0 .. 100]", 0f32..100f32, &mut number1);
220                });
221                ui.tree_node(hash!(), "editbox 1", |ui| {
222                    ui.label(None, "This is editbox!");
223                    ui.editbox(hash!(), vec2(285., 165.), &mut text0);
224                });
225                ui.tree_node(hash!(), "editbox 2", |ui| {
226                    ui.label(None, "This is editbox!");
227                    ui.editbox(hash!(), vec2(285., 165.), &mut text1);
228                });
229            });
230
231        match data.fit_command.take() {
232            Some(FittingCommand::Unfit { target_slot }) => data.set_item(target_slot, None),
233            Some(FittingCommand::Fit { target_slot, item }) => {
234                data.set_item(target_slot, Some(item));
235            }
236            Some(FittingCommand::Refit {
237                target_slot,
238                origin_slot,
239            }) => {
240                let origin_item = data
241                    .slots
242                    .iter()
243                    .find_map(|(_, slot)| {
244                        if slot.id == origin_slot {
245                            Some(slot.item.clone())
246                        } else {
247                            None
248                        }
249                    })
250                    .flatten();
251                data.set_item(target_slot, origin_item);
252                data.set_item(origin_slot, None);
253            }
254            None => {}
255        };
256
257        next_frame().await;
258    }
259}
More examples
Hide additional examples
examples/shadertoy.rs (line 232)
47async fn main() {
48    let ferris = load_texture("examples/rust.png").await.unwrap();
49    let (color_picker_texture, color_picker_image) = color_picker_texture(200, 200);
50
51    let mut fragment_shader = DEFAULT_FRAGMENT_SHADER.to_string();
52    let mut vertex_shader = DEFAULT_VERTEX_SHADER.to_string();
53
54    let pipeline_params = PipelineParams {
55        depth_write: true,
56        depth_test: Comparison::LessOrEqual,
57        ..Default::default()
58    };
59
60    let mut material = load_material(
61        ShaderSource::Glsl {
62            vertex: &vertex_shader,
63            fragment: &fragment_shader,
64        },
65        MaterialParams {
66            pipeline_params,
67            ..Default::default()
68        },
69    )
70    .unwrap();
71    let mut error: Option<String> = None;
72
73    enum Mesh {
74        Sphere,
75        Cube,
76        Plane,
77    }
78    let mut mesh = Mesh::Sphere;
79
80    let mut camera = Camera3D {
81        position: vec3(-15., 15., -5.),
82        up: vec3(0., 1., 0.),
83        target: vec3(0., 5., -5.),
84        ..Default::default()
85    };
86
87    let mut colorpicker_window = false;
88    let mut color_picking_uniform = None;
89
90    let mut new_uniform_window = false;
91    let mut new_uniform_name = String::new();
92    let mut uniforms: Vec<(String, Uniform)> = vec![];
93
94    loop {
95        clear_background(WHITE);
96
97        set_camera(&camera);
98
99        draw_grid(
100            20,
101            1.,
102            Color::new(0.55, 0.55, 0.55, 0.75),
103            Color::new(0.75, 0.75, 0.75, 0.75),
104        );
105
106        gl_use_material(&material);
107        match mesh {
108            Mesh::Plane => draw_plane(vec3(0., 2., 0.), vec2(5., 5.), Some(&ferris), WHITE),
109            Mesh::Sphere => draw_sphere(vec3(0., 6., 0.), 5., Some(&ferris), WHITE),
110            Mesh::Cube => draw_cube(vec3(0., 5., 0.), vec3(10., 10., 10.), Some(&ferris), WHITE),
111        }
112        gl_use_default_material();
113
114        set_default_camera();
115
116        let mut need_update = false;
117
118        widgets::Window::new(hash!(), vec2(20., 20.), vec2(470., 650.))
119            .label("Shader")
120            .ui(&mut *root_ui(), |ui| {
121                ui.label(None, "Camera: ");
122                ui.same_line(0.0);
123                if ui.button(None, "Ortho") {
124                    camera.projection = Projection::Orthographics;
125                }
126                ui.same_line(0.0);
127                if ui.button(None, "Perspective") {
128                    camera.projection = Projection::Perspective;
129                }
130                ui.label(None, "Mesh: ");
131                ui.same_line(0.0);
132                if ui.button(None, "Sphere") {
133                    mesh = Mesh::Sphere;
134                }
135                ui.same_line(0.0);
136                if ui.button(None, "Cube") {
137                    mesh = Mesh::Cube;
138                }
139                ui.same_line(0.0);
140                if ui.button(None, "Plane") {
141                    mesh = Mesh::Plane;
142                }
143
144                ui.label(None, "Uniforms:");
145                ui.separator();
146
147                for (i, (name, uniform)) in uniforms.iter_mut().enumerate() {
148                    ui.label(None, &format!("{name}"));
149                    ui.same_line(120.0);
150
151                    match uniform {
152                        Uniform::Float1(x) => {
153                            widgets::InputText::new(hash!(hash!(), i))
154                                .size(vec2(200.0, 19.0))
155                                .filter_numbers()
156                                .ui(ui, x);
157
158                            if let Ok(x) = x.parse::<f32>() {
159                                material.set_uniform(name, x);
160                            }
161                        }
162                        Uniform::Float2(x, y) => {
163                            widgets::InputText::new(hash!(hash!(), i))
164                                .size(vec2(99.0, 19.0))
165                                .filter_numbers()
166                                .ui(ui, x);
167
168                            ui.same_line(0.0);
169
170                            widgets::InputText::new(hash!(hash!(), i))
171                                .size(vec2(99.0, 19.0))
172                                .filter_numbers()
173                                .ui(ui, y);
174
175                            if let (Ok(x), Ok(y)) = (x.parse::<f32>(), y.parse::<f32>()) {
176                                material.set_uniform(name, (x, y));
177                            }
178                        }
179                        Uniform::Float3(x, y, z) => {
180                            widgets::InputText::new(hash!(hash!(), i))
181                                .size(vec2(65.0, 19.0))
182                                .filter_numbers()
183                                .ui(ui, x);
184
185                            ui.same_line(0.0);
186
187                            widgets::InputText::new(hash!(hash!(), i))
188                                .size(vec2(65.0, 19.0))
189                                .filter_numbers()
190                                .ui(ui, y);
191
192                            ui.same_line(0.0);
193
194                            widgets::InputText::new(hash!(hash!(), i))
195                                .size(vec2(65.0, 19.0))
196                                .filter_numbers()
197                                .ui(ui, z);
198
199                            if let (Ok(x), Ok(y), Ok(z)) =
200                                (x.parse::<f32>(), y.parse::<f32>(), z.parse::<f32>())
201                            {
202                                material.set_uniform(name, (x, y, z));
203                            }
204                        }
205
206                        Uniform::Color(color) => {
207                            let mut canvas = ui.canvas();
208
209                            let cursor = canvas.cursor();
210
211                            canvas.rect(
212                                Rect::new(cursor.x + 20.0, cursor.y, 50.0, 18.0),
213                                Color::new(0.2, 0.2, 0.2, 1.0),
214                                Color::new(color.x, color.y, color.z, 1.0),
215                            );
216
217                            if ui.button(None, "change") {
218                                colorpicker_window = true;
219                                color_picking_uniform = Some(name.to_owned());
220                            }
221                            material.set_uniform(name, (color.x, color.y, color.z));
222                        }
223                    }
224                }
225                ui.separator();
226                if ui.button(None, "New uniform") {
227                    new_uniform_window = true;
228                }
229                TreeNode::new(hash!(), "Fragment shader")
230                    .init_unfolded()
231                    .ui(ui, |ui| {
232                        if ui.editbox(hash!(), vec2(440., 200.), &mut fragment_shader) {
233                            need_update = true;
234                        };
235                    });
236                ui.tree_node(hash!(), "Vertex shader", |ui| {
237                    if ui.editbox(hash!(), vec2(440., 300.), &mut vertex_shader) {
238                        need_update = true;
239                    };
240                });
241
242                if let Some(ref error) = error {
243                    Label::new(error).multiline(14.0).ui(ui);
244                }
245            });
246
247        if new_uniform_window {
248            widgets::Window::new(hash!(), vec2(100., 100.), vec2(200., 80.))
249                .label("New uniform")
250                .ui(&mut *root_ui(), |ui| {
251                    if ui.active_window_focused() == false {
252                        new_uniform_window = false;
253                    }
254                    ui.input_text(hash!(), "Name", &mut new_uniform_name);
255                    let uniform_type = ui.combo_box(
256                        hash!(),
257                        "Type",
258                        &["Float1", "Float2", "Float3", "Color"],
259                        None,
260                    );
261
262                    if ui.button(None, "Add") {
263                        if new_uniform_name.is_empty() == false {
264                            let uniform = match uniform_type {
265                                0 => Uniform::Float1("0".to_string()),
266                                1 => Uniform::Float2("0".to_string(), "0".to_string()),
267                                2 => Uniform::Float3(
268                                    "0".to_string(),
269                                    "0".to_string(),
270                                    "0".to_string(),
271                                ),
272                                3 => Uniform::Color(vec3(0.0, 0.0, 0.0)),
273                                _ => unreachable!(),
274                            };
275                            uniforms.push((new_uniform_name.clone(), uniform));
276                            new_uniform_name.clear();
277                            need_update = true;
278                        }
279                        new_uniform_window = false;
280                    }
281
282                    ui.same_line(0.0);
283                    if ui.button(None, "Cancel") {
284                        new_uniform_window = false;
285                    }
286                });
287        }
288
289        if colorpicker_window {
290            colorpicker_window &= widgets::Window::new(hash!(), vec2(140., 100.), vec2(210., 240.))
291                .label("Colorpicker")
292                .ui(&mut *root_ui(), |ui| {
293                    if ui.active_window_focused() == false {
294                        colorpicker_window = false;
295                    }
296
297                    let mut canvas = ui.canvas();
298                    let cursor = canvas.cursor();
299                    let mouse = mouse_position();
300                    let x = mouse.0 as i32 - cursor.x as i32;
301                    let y = mouse.1 as i32 - (cursor.y as i32 + 20);
302
303                    let color = color_picker_image
304                        .get_pixel(x.max(0).min(199) as u32, y.max(0).min(199) as u32);
305
306                    canvas.rect(
307                        Rect::new(cursor.x, cursor.y, 200.0, 18.0),
308                        Color::new(0.0, 0.0, 0.0, 1.0),
309                        Color::new(color.r, color.g, color.b, 1.0),
310                    );
311                    canvas.image(
312                        Rect::new(cursor.x, cursor.y + 20.0, 200.0, 200.0),
313                        &color_picker_texture,
314                    );
315
316                    if x >= 0 && x < 200 && y >= 0 && y < 200 {
317                        canvas.rect(
318                            Rect::new(mouse.0 - 3.5, mouse.1 - 3.5, 7.0, 7.0),
319                            Color::new(0.3, 0.3, 0.3, 1.0),
320                            Color::new(1.0, 1.0, 1.0, 1.0),
321                        );
322
323                        if is_mouse_button_down(MouseButton::Left) {
324                            colorpicker_window = false;
325                            let uniform_name = color_picking_uniform.take().unwrap();
326
327                            uniforms
328                                .iter_mut()
329                                .find(|(name, _)| name == &uniform_name)
330                                .unwrap()
331                                .1 = Uniform::Color(vec3(color.r, color.g, color.b));
332                        }
333                    }
334                });
335        }
336
337        if need_update {
338            let uniforms = uniforms
339                .iter()
340                .map(|(name, uniform)| UniformDesc::new(name, uniform.uniform_type()))
341                .collect::<Vec<_>>();
342
343            match load_material(
344                ShaderSource::Glsl {
345                    vertex: &vertex_shader,
346                    fragment: &fragment_shader,
347                },
348                MaterialParams {
349                    pipeline_params,
350                    uniforms,
351                    textures: vec![],
352                },
353            ) {
354                Ok(new_material) => {
355                    material = new_material;
356                    error = None;
357                }
358                Err(err) => {
359                    error = Some(format!("{err:#?}"));
360                }
361            }
362        }
363
364        next_frame().await
365    }
366}
Source§

impl Ui

Source

pub fn group<F: FnOnce(&mut Ui)>(&mut self, id: Id, size: Vec2, f: F) -> Drag

Examples found in repository?
examples/ui_skins.rs (lines 218-230)
6async fn main() {
7    let skin1 = {
8        let font = load_ttf_font("examples/ui_assets/HTOWERT.TTF")
9            .await
10            .unwrap();
11        let label_style = root_ui()
12            .style_builder()
13            .with_font(&font)
14            .unwrap()
15            .text_color(Color::from_rgba(180, 180, 120, 255))
16            .font_size(30)
17            .build();
18
19        let window_style = root_ui()
20            .style_builder()
21            .background(
22                Image::from_file_with_format(
23                    include_bytes!("../examples/ui_assets/window_background.png"),
24                    None,
25                )
26                .unwrap(),
27            )
28            .background_margin(RectOffset::new(20.0, 20.0, 10.0, 10.0))
29            .margin(RectOffset::new(-20.0, -30.0, 0.0, 0.0))
30            .build();
31
32        let button_style = root_ui()
33            .style_builder()
34            .background(
35                Image::from_file_with_format(
36                    include_bytes!("../examples/ui_assets/button_background.png"),
37                    None,
38                )
39                .unwrap(),
40            )
41            .background_margin(RectOffset::new(37.0, 37.0, 5.0, 5.0))
42            .margin(RectOffset::new(10.0, 10.0, 0.0, 0.0))
43            .background_hovered(
44                Image::from_file_with_format(
45                    include_bytes!("../examples/ui_assets/button_hovered_background.png"),
46                    None,
47                )
48                .unwrap(),
49            )
50            .background_clicked(
51                Image::from_file_with_format(
52                    include_bytes!("../examples/ui_assets/button_clicked_background.png"),
53                    None,
54                )
55                .unwrap(),
56            )
57            .with_font(&font)
58            .unwrap()
59            .text_color(Color::from_rgba(180, 180, 100, 255))
60            .font_size(40)
61            .build();
62
63        let editbox_style = root_ui()
64            .style_builder()
65            .background_margin(RectOffset::new(0., 0., 0., 0.))
66            .with_font(&font)
67            .unwrap()
68            .text_color(Color::from_rgba(120, 120, 120, 255))
69            .color_selected(Color::from_rgba(190, 190, 190, 255))
70            .font_size(50)
71            .build();
72
73        Skin {
74            editbox_style,
75            window_style,
76            button_style,
77            label_style,
78            ..root_ui().default_skin()
79        }
80    };
81
82    let skin2 = {
83        let font = load_ttf_font("examples/ui_assets/MinimalPixel v2.ttf")
84            .await
85            .unwrap();
86        let label_style = root_ui()
87            .style_builder()
88            .with_font(&font)
89            .unwrap()
90            .text_color(Color::from_rgba(120, 120, 120, 255))
91            .font_size(25)
92            .build();
93
94        let window_style = root_ui()
95            .style_builder()
96            .background(
97                Image::from_file_with_format(
98                    include_bytes!("../examples/ui_assets/window_background_2.png"),
99                    None,
100                )
101                .unwrap(),
102            )
103            .background_margin(RectOffset::new(52.0, 52.0, 52.0, 52.0))
104            .margin(RectOffset::new(-30.0, 0.0, -30.0, 0.0))
105            .build();
106
107        let button_style = root_ui()
108            .style_builder()
109            .background(
110                Image::from_file_with_format(
111                    include_bytes!("../examples/ui_assets/button_background_2.png"),
112                    None,
113                )
114                .unwrap(),
115            )
116            .background_margin(RectOffset::new(8.0, 8.0, 8.0, 8.0))
117            .background_hovered(
118                Image::from_file_with_format(
119                    include_bytes!("../examples/ui_assets/button_hovered_background_2.png"),
120                    None,
121                )
122                .unwrap(),
123            )
124            .background_clicked(
125                Image::from_file_with_format(
126                    include_bytes!("../examples/ui_assets/button_clicked_background_2.png"),
127                    None,
128                )
129                .unwrap(),
130            )
131            .with_font(&font)
132            .unwrap()
133            .text_color(Color::from_rgba(180, 180, 100, 255))
134            .font_size(40)
135            .build();
136
137        let checkbox_style = root_ui()
138            .style_builder()
139            .background(
140                Image::from_file_with_format(
141                    include_bytes!("../examples/ui_assets/checkbox_background.png"),
142                    None,
143                )
144                .unwrap(),
145            )
146            .background_hovered(
147                Image::from_file_with_format(
148                    include_bytes!("../examples/ui_assets/checkbox_hovered_background.png"),
149                    None,
150                )
151                .unwrap(),
152            )
153            .background_clicked(
154                Image::from_file_with_format(
155                    include_bytes!("../examples/ui_assets/checkbox_clicked_background.png"),
156                    None,
157                )
158                .unwrap(),
159            )
160            .build();
161
162        let editbox_style = root_ui()
163            .style_builder()
164            .background(
165                Image::from_file_with_format(
166                    include_bytes!("../examples/ui_assets/editbox_background.png"),
167                    None,
168                )
169                .unwrap(),
170            )
171            .background_margin(RectOffset::new(2., 2., 2., 2.))
172            .with_font(&font)
173            .unwrap()
174            .text_color(Color::from_rgba(120, 120, 120, 255))
175            .font_size(25)
176            .build();
177
178        let combobox_style = root_ui()
179            .style_builder()
180            .background(
181                Image::from_file_with_format(
182                    include_bytes!("../examples/ui_assets/combobox_background.png"),
183                    None,
184                )
185                .unwrap(),
186            )
187            .background_margin(RectOffset::new(4., 25., 6., 6.))
188            .with_font(&font)
189            .unwrap()
190            .text_color(Color::from_rgba(120, 120, 120, 255))
191            .color(Color::from_rgba(210, 210, 210, 255))
192            .font_size(25)
193            .build();
194
195        Skin {
196            window_style,
197            button_style,
198            label_style,
199            checkbox_style,
200            editbox_style,
201            combobox_style,
202            ..root_ui().default_skin()
203        }
204    };
205    let default_skin = root_ui().default_skin().clone();
206
207    let mut window1_skin = skin1.clone();
208    let mut window2_skin = skin2.clone();
209
210    let mut checkbox = false;
211    let mut text = String::new();
212    let mut number = 0.0f32;
213    let mut combobox = 0;
214
215    loop {
216        clear_background(GRAY);
217
218        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
219            ui.label(None, "Window 1");
220
221            if ui.button(None, "Skin 1") {
222                window1_skin = skin1.clone();
223            }
224            if ui.button(None, "Skin 2") {
225                window1_skin = skin2.clone();
226            }
227            if ui.button(None, "No Skin") {
228                window1_skin = default_skin.clone();
229            }
230        });
231        root_ui().same_line(0.);
232        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
233            ui.label(None, "Window 2");
234            if ui.button(None, "Skin 1") {
235                window2_skin = skin1.clone();
236            }
237            if ui.button(None, "Skin 2") {
238                window2_skin = skin2.clone();
239            }
240            if ui.button(None, "No Skin") {
241                window2_skin = default_skin.clone();
242            }
243        });
244
245        root_ui().push_skin(&window1_skin);
246
247        root_ui().window(hash!(), vec2(20., 250.), vec2(300., 300.), |ui| {
248            widgets::Button::new("Play")
249                .position(vec2(65.0, 15.0))
250                .ui(ui);
251            widgets::Button::new("Options")
252                .position(vec2(40.0, 75.0))
253                .ui(ui);
254
255            widgets::Button::new("Quit")
256                .position(vec2(65.0, 195.0))
257                .ui(ui);
258        });
259        root_ui().pop_skin();
260
261        root_ui().push_skin(&window2_skin);
262        root_ui().window(hash!(), vec2(250., 20.), vec2(500., 250.), |ui| {
263            ui.checkbox(hash!(), "Checkbox 1", &mut checkbox);
264            ui.combo_box(
265                hash!(),
266                "Combobox",
267                &["First option", "Second option"],
268                &mut combobox,
269            );
270            ui.input_text(hash!(), "Text", &mut text);
271            ui.drag(hash!(), "Drag", None, &mut number);
272
273            widgets::Button::new("Apply")
274                .position(vec2(80.0, 150.0))
275                .ui(ui);
276            widgets::Button::new("Cancel")
277                .position(vec2(280.0, 150.0))
278                .ui(ui);
279        });
280        root_ui().pop_skin();
281
282        next_frame().await;
283    }
284}
Source§

impl Ui

Source

pub fn input_text(&mut self, id: Id, label: &str, data: &mut String)

Examples found in repository?
examples/ui.rs (line 199)
136async fn main() {
137    let mut data = Data::new();
138
139    let mut data0 = String::new();
140    let mut data1 = String::new();
141
142    let mut text0 = String::new();
143    let mut text1 = String::new();
144
145    let mut number0 = 0.;
146    let mut number1 = 0.;
147
148    let texture: Texture2D = load_texture("examples/ferris.png").await.unwrap();
149
150    loop {
151        clear_background(WHITE);
152
153        widgets::Window::new(hash!(), vec2(400., 200.), vec2(320., 400.))
154            .label("Shop")
155            .titlebar(true)
156            .ui(&mut *root_ui(), |ui| {
157                for i in 0..30 {
158                    Group::new(hash!("shop", i), Vec2::new(300., 80.)).ui(ui, |ui| {
159                        ui.label(Vec2::new(10., 10.), &format!("Item N {i}"));
160                        ui.label(Vec2::new(260., 40.), "10/10");
161                        ui.label(Vec2::new(200., 58.), &format!("{} kr", 800));
162                        if ui.button(Vec2::new(260., 55.), "buy") {
163                            data.inventory.push(format!("Item {i}"));
164                        }
165                    });
166                }
167            });
168
169        widgets::Window::new(hash!(), vec2(100., 220.), vec2(542., 430.))
170            .label("Fitting window")
171            .titlebar(true)
172            .ui(&mut *root_ui(), |ui| {
173                Group::new(hash!(), Vec2::new(230., 400.)).ui(ui, |ui| {
174                    data.slots(ui);
175                });
176                Group::new(hash!(), Vec2::new(280., 400.)).ui(ui, |ui| {
177                    data.inventory(ui);
178                });
179            });
180
181        widgets::Window::new(hash!(), vec2(470., 50.), vec2(300., 300.))
182            .label("Megaui Showcase Window")
183            .ui(&mut *root_ui(), |ui| {
184                ui.tree_node(hash!(), "input", |ui| {
185                    ui.label(None, "Some random text");
186                    if ui.button(None, "click me") {
187                        println!("hi");
188                    }
189
190                    ui.separator();
191
192                    ui.label(None, "Some other random text");
193                    if ui.button(None, "other button") {
194                        println!("hi2");
195                    }
196
197                    ui.separator();
198
199                    ui.input_text(hash!(), "<- input text 1", &mut data0);
200                    ui.input_text(hash!(), "<- input text 2", &mut data1);
201                    ui.label(None, &format!("Text entered: \"{data0}\" and \"{data1}\""));
202
203                    ui.separator();
204                });
205                ui.tree_node(hash!(), "buttons", |ui| {
206                    widgets::Button::new(texture.clone())
207                        .size(vec2(120., 70.))
208                        .ui(ui);
209                    ui.same_line(0.);
210                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
211                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
212                    ui.same_line(0.);
213                    widgets::Button::new(texture.clone())
214                        .size(vec2(120., 70.))
215                        .ui(ui);
216                });
217                ui.tree_node(hash!(), "sliders", |ui| {
218                    ui.slider(hash!(), "[-10 .. 10]", -10f32..10f32, &mut number0);
219                    ui.slider(hash!(), "[0 .. 100]", 0f32..100f32, &mut number1);
220                });
221                ui.tree_node(hash!(), "editbox 1", |ui| {
222                    ui.label(None, "This is editbox!");
223                    ui.editbox(hash!(), vec2(285., 165.), &mut text0);
224                });
225                ui.tree_node(hash!(), "editbox 2", |ui| {
226                    ui.label(None, "This is editbox!");
227                    ui.editbox(hash!(), vec2(285., 165.), &mut text1);
228                });
229            });
230
231        match data.fit_command.take() {
232            Some(FittingCommand::Unfit { target_slot }) => data.set_item(target_slot, None),
233            Some(FittingCommand::Fit { target_slot, item }) => {
234                data.set_item(target_slot, Some(item));
235            }
236            Some(FittingCommand::Refit {
237                target_slot,
238                origin_slot,
239            }) => {
240                let origin_item = data
241                    .slots
242                    .iter()
243                    .find_map(|(_, slot)| {
244                        if slot.id == origin_slot {
245                            Some(slot.item.clone())
246                        } else {
247                            None
248                        }
249                    })
250                    .flatten();
251                data.set_item(target_slot, origin_item);
252                data.set_item(origin_slot, None);
253            }
254            None => {}
255        };
256
257        next_frame().await;
258    }
259}
More examples
Hide additional examples
examples/ui_skins.rs (line 270)
6async fn main() {
7    let skin1 = {
8        let font = load_ttf_font("examples/ui_assets/HTOWERT.TTF")
9            .await
10            .unwrap();
11        let label_style = root_ui()
12            .style_builder()
13            .with_font(&font)
14            .unwrap()
15            .text_color(Color::from_rgba(180, 180, 120, 255))
16            .font_size(30)
17            .build();
18
19        let window_style = root_ui()
20            .style_builder()
21            .background(
22                Image::from_file_with_format(
23                    include_bytes!("../examples/ui_assets/window_background.png"),
24                    None,
25                )
26                .unwrap(),
27            )
28            .background_margin(RectOffset::new(20.0, 20.0, 10.0, 10.0))
29            .margin(RectOffset::new(-20.0, -30.0, 0.0, 0.0))
30            .build();
31
32        let button_style = root_ui()
33            .style_builder()
34            .background(
35                Image::from_file_with_format(
36                    include_bytes!("../examples/ui_assets/button_background.png"),
37                    None,
38                )
39                .unwrap(),
40            )
41            .background_margin(RectOffset::new(37.0, 37.0, 5.0, 5.0))
42            .margin(RectOffset::new(10.0, 10.0, 0.0, 0.0))
43            .background_hovered(
44                Image::from_file_with_format(
45                    include_bytes!("../examples/ui_assets/button_hovered_background.png"),
46                    None,
47                )
48                .unwrap(),
49            )
50            .background_clicked(
51                Image::from_file_with_format(
52                    include_bytes!("../examples/ui_assets/button_clicked_background.png"),
53                    None,
54                )
55                .unwrap(),
56            )
57            .with_font(&font)
58            .unwrap()
59            .text_color(Color::from_rgba(180, 180, 100, 255))
60            .font_size(40)
61            .build();
62
63        let editbox_style = root_ui()
64            .style_builder()
65            .background_margin(RectOffset::new(0., 0., 0., 0.))
66            .with_font(&font)
67            .unwrap()
68            .text_color(Color::from_rgba(120, 120, 120, 255))
69            .color_selected(Color::from_rgba(190, 190, 190, 255))
70            .font_size(50)
71            .build();
72
73        Skin {
74            editbox_style,
75            window_style,
76            button_style,
77            label_style,
78            ..root_ui().default_skin()
79        }
80    };
81
82    let skin2 = {
83        let font = load_ttf_font("examples/ui_assets/MinimalPixel v2.ttf")
84            .await
85            .unwrap();
86        let label_style = root_ui()
87            .style_builder()
88            .with_font(&font)
89            .unwrap()
90            .text_color(Color::from_rgba(120, 120, 120, 255))
91            .font_size(25)
92            .build();
93
94        let window_style = root_ui()
95            .style_builder()
96            .background(
97                Image::from_file_with_format(
98                    include_bytes!("../examples/ui_assets/window_background_2.png"),
99                    None,
100                )
101                .unwrap(),
102            )
103            .background_margin(RectOffset::new(52.0, 52.0, 52.0, 52.0))
104            .margin(RectOffset::new(-30.0, 0.0, -30.0, 0.0))
105            .build();
106
107        let button_style = root_ui()
108            .style_builder()
109            .background(
110                Image::from_file_with_format(
111                    include_bytes!("../examples/ui_assets/button_background_2.png"),
112                    None,
113                )
114                .unwrap(),
115            )
116            .background_margin(RectOffset::new(8.0, 8.0, 8.0, 8.0))
117            .background_hovered(
118                Image::from_file_with_format(
119                    include_bytes!("../examples/ui_assets/button_hovered_background_2.png"),
120                    None,
121                )
122                .unwrap(),
123            )
124            .background_clicked(
125                Image::from_file_with_format(
126                    include_bytes!("../examples/ui_assets/button_clicked_background_2.png"),
127                    None,
128                )
129                .unwrap(),
130            )
131            .with_font(&font)
132            .unwrap()
133            .text_color(Color::from_rgba(180, 180, 100, 255))
134            .font_size(40)
135            .build();
136
137        let checkbox_style = root_ui()
138            .style_builder()
139            .background(
140                Image::from_file_with_format(
141                    include_bytes!("../examples/ui_assets/checkbox_background.png"),
142                    None,
143                )
144                .unwrap(),
145            )
146            .background_hovered(
147                Image::from_file_with_format(
148                    include_bytes!("../examples/ui_assets/checkbox_hovered_background.png"),
149                    None,
150                )
151                .unwrap(),
152            )
153            .background_clicked(
154                Image::from_file_with_format(
155                    include_bytes!("../examples/ui_assets/checkbox_clicked_background.png"),
156                    None,
157                )
158                .unwrap(),
159            )
160            .build();
161
162        let editbox_style = root_ui()
163            .style_builder()
164            .background(
165                Image::from_file_with_format(
166                    include_bytes!("../examples/ui_assets/editbox_background.png"),
167                    None,
168                )
169                .unwrap(),
170            )
171            .background_margin(RectOffset::new(2., 2., 2., 2.))
172            .with_font(&font)
173            .unwrap()
174            .text_color(Color::from_rgba(120, 120, 120, 255))
175            .font_size(25)
176            .build();
177
178        let combobox_style = root_ui()
179            .style_builder()
180            .background(
181                Image::from_file_with_format(
182                    include_bytes!("../examples/ui_assets/combobox_background.png"),
183                    None,
184                )
185                .unwrap(),
186            )
187            .background_margin(RectOffset::new(4., 25., 6., 6.))
188            .with_font(&font)
189            .unwrap()
190            .text_color(Color::from_rgba(120, 120, 120, 255))
191            .color(Color::from_rgba(210, 210, 210, 255))
192            .font_size(25)
193            .build();
194
195        Skin {
196            window_style,
197            button_style,
198            label_style,
199            checkbox_style,
200            editbox_style,
201            combobox_style,
202            ..root_ui().default_skin()
203        }
204    };
205    let default_skin = root_ui().default_skin().clone();
206
207    let mut window1_skin = skin1.clone();
208    let mut window2_skin = skin2.clone();
209
210    let mut checkbox = false;
211    let mut text = String::new();
212    let mut number = 0.0f32;
213    let mut combobox = 0;
214
215    loop {
216        clear_background(GRAY);
217
218        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
219            ui.label(None, "Window 1");
220
221            if ui.button(None, "Skin 1") {
222                window1_skin = skin1.clone();
223            }
224            if ui.button(None, "Skin 2") {
225                window1_skin = skin2.clone();
226            }
227            if ui.button(None, "No Skin") {
228                window1_skin = default_skin.clone();
229            }
230        });
231        root_ui().same_line(0.);
232        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
233            ui.label(None, "Window 2");
234            if ui.button(None, "Skin 1") {
235                window2_skin = skin1.clone();
236            }
237            if ui.button(None, "Skin 2") {
238                window2_skin = skin2.clone();
239            }
240            if ui.button(None, "No Skin") {
241                window2_skin = default_skin.clone();
242            }
243        });
244
245        root_ui().push_skin(&window1_skin);
246
247        root_ui().window(hash!(), vec2(20., 250.), vec2(300., 300.), |ui| {
248            widgets::Button::new("Play")
249                .position(vec2(65.0, 15.0))
250                .ui(ui);
251            widgets::Button::new("Options")
252                .position(vec2(40.0, 75.0))
253                .ui(ui);
254
255            widgets::Button::new("Quit")
256                .position(vec2(65.0, 195.0))
257                .ui(ui);
258        });
259        root_ui().pop_skin();
260
261        root_ui().push_skin(&window2_skin);
262        root_ui().window(hash!(), vec2(250., 20.), vec2(500., 250.), |ui| {
263            ui.checkbox(hash!(), "Checkbox 1", &mut checkbox);
264            ui.combo_box(
265                hash!(),
266                "Combobox",
267                &["First option", "Second option"],
268                &mut combobox,
269            );
270            ui.input_text(hash!(), "Text", &mut text);
271            ui.drag(hash!(), "Drag", None, &mut number);
272
273            widgets::Button::new("Apply")
274                .position(vec2(80.0, 150.0))
275                .ui(ui);
276            widgets::Button::new("Cancel")
277                .position(vec2(280.0, 150.0))
278                .ui(ui);
279        });
280        root_ui().pop_skin();
281
282        next_frame().await;
283    }
284}
examples/shadertoy.rs (line 254)
47async fn main() {
48    let ferris = load_texture("examples/rust.png").await.unwrap();
49    let (color_picker_texture, color_picker_image) = color_picker_texture(200, 200);
50
51    let mut fragment_shader = DEFAULT_FRAGMENT_SHADER.to_string();
52    let mut vertex_shader = DEFAULT_VERTEX_SHADER.to_string();
53
54    let pipeline_params = PipelineParams {
55        depth_write: true,
56        depth_test: Comparison::LessOrEqual,
57        ..Default::default()
58    };
59
60    let mut material = load_material(
61        ShaderSource::Glsl {
62            vertex: &vertex_shader,
63            fragment: &fragment_shader,
64        },
65        MaterialParams {
66            pipeline_params,
67            ..Default::default()
68        },
69    )
70    .unwrap();
71    let mut error: Option<String> = None;
72
73    enum Mesh {
74        Sphere,
75        Cube,
76        Plane,
77    }
78    let mut mesh = Mesh::Sphere;
79
80    let mut camera = Camera3D {
81        position: vec3(-15., 15., -5.),
82        up: vec3(0., 1., 0.),
83        target: vec3(0., 5., -5.),
84        ..Default::default()
85    };
86
87    let mut colorpicker_window = false;
88    let mut color_picking_uniform = None;
89
90    let mut new_uniform_window = false;
91    let mut new_uniform_name = String::new();
92    let mut uniforms: Vec<(String, Uniform)> = vec![];
93
94    loop {
95        clear_background(WHITE);
96
97        set_camera(&camera);
98
99        draw_grid(
100            20,
101            1.,
102            Color::new(0.55, 0.55, 0.55, 0.75),
103            Color::new(0.75, 0.75, 0.75, 0.75),
104        );
105
106        gl_use_material(&material);
107        match mesh {
108            Mesh::Plane => draw_plane(vec3(0., 2., 0.), vec2(5., 5.), Some(&ferris), WHITE),
109            Mesh::Sphere => draw_sphere(vec3(0., 6., 0.), 5., Some(&ferris), WHITE),
110            Mesh::Cube => draw_cube(vec3(0., 5., 0.), vec3(10., 10., 10.), Some(&ferris), WHITE),
111        }
112        gl_use_default_material();
113
114        set_default_camera();
115
116        let mut need_update = false;
117
118        widgets::Window::new(hash!(), vec2(20., 20.), vec2(470., 650.))
119            .label("Shader")
120            .ui(&mut *root_ui(), |ui| {
121                ui.label(None, "Camera: ");
122                ui.same_line(0.0);
123                if ui.button(None, "Ortho") {
124                    camera.projection = Projection::Orthographics;
125                }
126                ui.same_line(0.0);
127                if ui.button(None, "Perspective") {
128                    camera.projection = Projection::Perspective;
129                }
130                ui.label(None, "Mesh: ");
131                ui.same_line(0.0);
132                if ui.button(None, "Sphere") {
133                    mesh = Mesh::Sphere;
134                }
135                ui.same_line(0.0);
136                if ui.button(None, "Cube") {
137                    mesh = Mesh::Cube;
138                }
139                ui.same_line(0.0);
140                if ui.button(None, "Plane") {
141                    mesh = Mesh::Plane;
142                }
143
144                ui.label(None, "Uniforms:");
145                ui.separator();
146
147                for (i, (name, uniform)) in uniforms.iter_mut().enumerate() {
148                    ui.label(None, &format!("{name}"));
149                    ui.same_line(120.0);
150
151                    match uniform {
152                        Uniform::Float1(x) => {
153                            widgets::InputText::new(hash!(hash!(), i))
154                                .size(vec2(200.0, 19.0))
155                                .filter_numbers()
156                                .ui(ui, x);
157
158                            if let Ok(x) = x.parse::<f32>() {
159                                material.set_uniform(name, x);
160                            }
161                        }
162                        Uniform::Float2(x, y) => {
163                            widgets::InputText::new(hash!(hash!(), i))
164                                .size(vec2(99.0, 19.0))
165                                .filter_numbers()
166                                .ui(ui, x);
167
168                            ui.same_line(0.0);
169
170                            widgets::InputText::new(hash!(hash!(), i))
171                                .size(vec2(99.0, 19.0))
172                                .filter_numbers()
173                                .ui(ui, y);
174
175                            if let (Ok(x), Ok(y)) = (x.parse::<f32>(), y.parse::<f32>()) {
176                                material.set_uniform(name, (x, y));
177                            }
178                        }
179                        Uniform::Float3(x, y, z) => {
180                            widgets::InputText::new(hash!(hash!(), i))
181                                .size(vec2(65.0, 19.0))
182                                .filter_numbers()
183                                .ui(ui, x);
184
185                            ui.same_line(0.0);
186
187                            widgets::InputText::new(hash!(hash!(), i))
188                                .size(vec2(65.0, 19.0))
189                                .filter_numbers()
190                                .ui(ui, y);
191
192                            ui.same_line(0.0);
193
194                            widgets::InputText::new(hash!(hash!(), i))
195                                .size(vec2(65.0, 19.0))
196                                .filter_numbers()
197                                .ui(ui, z);
198
199                            if let (Ok(x), Ok(y), Ok(z)) =
200                                (x.parse::<f32>(), y.parse::<f32>(), z.parse::<f32>())
201                            {
202                                material.set_uniform(name, (x, y, z));
203                            }
204                        }
205
206                        Uniform::Color(color) => {
207                            let mut canvas = ui.canvas();
208
209                            let cursor = canvas.cursor();
210
211                            canvas.rect(
212                                Rect::new(cursor.x + 20.0, cursor.y, 50.0, 18.0),
213                                Color::new(0.2, 0.2, 0.2, 1.0),
214                                Color::new(color.x, color.y, color.z, 1.0),
215                            );
216
217                            if ui.button(None, "change") {
218                                colorpicker_window = true;
219                                color_picking_uniform = Some(name.to_owned());
220                            }
221                            material.set_uniform(name, (color.x, color.y, color.z));
222                        }
223                    }
224                }
225                ui.separator();
226                if ui.button(None, "New uniform") {
227                    new_uniform_window = true;
228                }
229                TreeNode::new(hash!(), "Fragment shader")
230                    .init_unfolded()
231                    .ui(ui, |ui| {
232                        if ui.editbox(hash!(), vec2(440., 200.), &mut fragment_shader) {
233                            need_update = true;
234                        };
235                    });
236                ui.tree_node(hash!(), "Vertex shader", |ui| {
237                    if ui.editbox(hash!(), vec2(440., 300.), &mut vertex_shader) {
238                        need_update = true;
239                    };
240                });
241
242                if let Some(ref error) = error {
243                    Label::new(error).multiline(14.0).ui(ui);
244                }
245            });
246
247        if new_uniform_window {
248            widgets::Window::new(hash!(), vec2(100., 100.), vec2(200., 80.))
249                .label("New uniform")
250                .ui(&mut *root_ui(), |ui| {
251                    if ui.active_window_focused() == false {
252                        new_uniform_window = false;
253                    }
254                    ui.input_text(hash!(), "Name", &mut new_uniform_name);
255                    let uniform_type = ui.combo_box(
256                        hash!(),
257                        "Type",
258                        &["Float1", "Float2", "Float3", "Color"],
259                        None,
260                    );
261
262                    if ui.button(None, "Add") {
263                        if new_uniform_name.is_empty() == false {
264                            let uniform = match uniform_type {
265                                0 => Uniform::Float1("0".to_string()),
266                                1 => Uniform::Float2("0".to_string(), "0".to_string()),
267                                2 => Uniform::Float3(
268                                    "0".to_string(),
269                                    "0".to_string(),
270                                    "0".to_string(),
271                                ),
272                                3 => Uniform::Color(vec3(0.0, 0.0, 0.0)),
273                                _ => unreachable!(),
274                            };
275                            uniforms.push((new_uniform_name.clone(), uniform));
276                            new_uniform_name.clear();
277                            need_update = true;
278                        }
279                        new_uniform_window = false;
280                    }
281
282                    ui.same_line(0.0);
283                    if ui.button(None, "Cancel") {
284                        new_uniform_window = false;
285                    }
286                });
287        }
288
289        if colorpicker_window {
290            colorpicker_window &= widgets::Window::new(hash!(), vec2(140., 100.), vec2(210., 240.))
291                .label("Colorpicker")
292                .ui(&mut *root_ui(), |ui| {
293                    if ui.active_window_focused() == false {
294                        colorpicker_window = false;
295                    }
296
297                    let mut canvas = ui.canvas();
298                    let cursor = canvas.cursor();
299                    let mouse = mouse_position();
300                    let x = mouse.0 as i32 - cursor.x as i32;
301                    let y = mouse.1 as i32 - (cursor.y as i32 + 20);
302
303                    let color = color_picker_image
304                        .get_pixel(x.max(0).min(199) as u32, y.max(0).min(199) as u32);
305
306                    canvas.rect(
307                        Rect::new(cursor.x, cursor.y, 200.0, 18.0),
308                        Color::new(0.0, 0.0, 0.0, 1.0),
309                        Color::new(color.r, color.g, color.b, 1.0),
310                    );
311                    canvas.image(
312                        Rect::new(cursor.x, cursor.y + 20.0, 200.0, 200.0),
313                        &color_picker_texture,
314                    );
315
316                    if x >= 0 && x < 200 && y >= 0 && y < 200 {
317                        canvas.rect(
318                            Rect::new(mouse.0 - 3.5, mouse.1 - 3.5, 7.0, 7.0),
319                            Color::new(0.3, 0.3, 0.3, 1.0),
320                            Color::new(1.0, 1.0, 1.0, 1.0),
321                        );
322
323                        if is_mouse_button_down(MouseButton::Left) {
324                            colorpicker_window = false;
325                            let uniform_name = color_picking_uniform.take().unwrap();
326
327                            uniforms
328                                .iter_mut()
329                                .find(|(name, _)| name == &uniform_name)
330                                .unwrap()
331                                .1 = Uniform::Color(vec3(color.r, color.g, color.b));
332                        }
333                    }
334                });
335        }
336
337        if need_update {
338            let uniforms = uniforms
339                .iter()
340                .map(|(name, uniform)| UniformDesc::new(name, uniform.uniform_type()))
341                .collect::<Vec<_>>();
342
343            match load_material(
344                ShaderSource::Glsl {
345                    vertex: &vertex_shader,
346                    fragment: &fragment_shader,
347                },
348                MaterialParams {
349                    pipeline_params,
350                    uniforms,
351                    textures: vec![],
352                },
353            ) {
354                Ok(new_material) => {
355                    material = new_material;
356                    error = None;
357                }
358                Err(err) => {
359                    error = Some(format!("{err:#?}"));
360                }
361            }
362        }
363
364        next_frame().await
365    }
366}
Source

pub fn input_password(&mut self, id: Id, label: &str, data: &mut String)

Source§

impl Ui

Source

pub fn label<P: Into<Option<Vec2>>>(&mut self, position: P, label: &str)

Examples found in repository?
examples/exit_dialog.rs (line 23)
5async fn main() {
6    prevent_quit();
7
8    let mut show_exit_dialog = false;
9    let mut user_decided_to_exit = false;
10
11    loop {
12        clear_background(GRAY);
13
14        if is_quit_requested() {
15            show_exit_dialog = true;
16        }
17
18        if show_exit_dialog {
19            let dialog_size = vec2(200., 70.);
20            let screen_size = vec2(screen_width(), screen_height());
21            let dialog_position = screen_size / 2. - dialog_size / 2.;
22            Window::new(hash!(), dialog_position, dialog_size).ui(&mut *root_ui(), |ui| {
23                ui.label(None, "Do you really want to quit?");
24                ui.separator();
25                ui.same_line(60.);
26                if ui.button(None, "Yes") {
27                    user_decided_to_exit = true;
28                }
29                ui.same_line(120.);
30                if ui.button(None, "No") {
31                    show_exit_dialog = false;
32                }
33            });
34        }
35
36        if user_decided_to_exit {
37            break;
38        }
39
40        next_frame().await
41    }
42}
More examples
Hide additional examples
examples/events.rs (line 11)
6async fn main() {
7    loop {
8        clear_background(WHITE);
9        root_ui().window(hash!(), Vec2::new(20., 20.), Vec2::new(450., 200.), |ui| {
10            let (mouse_x, mouse_y) = mouse_position();
11            ui.label(None, &format!("Mouse position: {mouse_x} {mouse_y}"));
12
13            let (mouse_wheel_x, mouse_wheel_y) = mouse_wheel();
14            ui.label(None, &format!("Mouse wheel x: {mouse_wheel_x}"));
15            ui.label(None, &format!("Mouse wheel y: {mouse_wheel_y}"));
16
17            widgets::Group::new(hash!(), Vec2::new(200., 90.))
18                .position(Vec2::new(240., 0.))
19                .ui(ui, |ui| {
20                    ui.label(None, "Pressed kbd keys");
21
22                    if let Some(key) = get_last_key_pressed() {
23                        ui.label(None, &format!("{key:?}"))
24                    }
25                });
26
27            widgets::Group::new(hash!(), Vec2::new(200., 90.))
28                .position(Vec2::new(240., 92.))
29                .ui(ui, |ui| {
30                    ui.label(None, "Pressed mouse keys");
31
32                    if is_mouse_button_down(MouseButton::Left) {
33                        ui.label(None, "Left");
34                    }
35                    if is_mouse_button_down(MouseButton::Right) {
36                        ui.label(None, "Right");
37                    }
38                    if is_mouse_button_down(MouseButton::Middle) {
39                        ui.label(None, "Middle");
40                    }
41                });
42        });
43        next_frame().await;
44    }
45}
examples/ui.rs (line 67)
52    fn slots(&mut self, ui: &mut Ui) {
53        let item_dragging = &mut self.item_dragging;
54
55        let fit_command = &mut self.fit_command;
56        for (label, slot) in self.slots.iter_mut() {
57            Group::new(hash!("grp", slot.id, &label), Vec2::new(210., 55.)).ui(ui, |ui| {
58                let drag = Group::new(slot.id, Vec2::new(50., 50.))
59                    // slot without item is not draggable
60                    .draggable(slot.item.is_some())
61                    // but could be a target of drag
62                    .hoverable(*item_dragging)
63                    // and is highlighted with other color when some item is dragging
64                    .highlight(*item_dragging)
65                    .ui(ui, |ui| {
66                        if let Some(ref item) = slot.item {
67                            ui.label(Vec2::new(5., 10.), &item);
68                        }
69                    });
70
71                match drag {
72                    // there is some item in this slot and it was dragged to another slot
73                    Drag::Dropped(_, Some(id)) if slot.item.is_some() => {
74                        *fit_command = Some(FittingCommand::Refit {
75                            target_slot: id,
76                            origin_slot: slot.id,
77                        });
78                    }
79                    // there is some item in this slot and it was dragged out - unfit it
80                    Drag::Dropped(_, None) if slot.item.is_some() => {
81                        *fit_command = Some(FittingCommand::Unfit {
82                            target_slot: slot.id,
83                        });
84                    }
85                    // there is no item in this slot
86                    // this is impossible - slots without items are non-draggable
87                    Drag::Dropped(_, _) => unreachable!(),
88                    Drag::Dragging(pos, id) => {
89                        debug!("slots: pos: {:?}, id {:?}", pos, id);
90                        *item_dragging = true;
91                    }
92                    Drag::No => {}
93                }
94                ui.label(Vec2::new(60., 20.), label);
95            });
96        }
97    }
98
99    fn inventory(&mut self, ui: &mut Ui) {
100        let item_dragging = &mut self.item_dragging;
101        for (n, item) in self.inventory.iter().enumerate() {
102            let drag = Group::new(hash!("inventory", n), Vec2::new(50., 50.))
103                .draggable(true)
104                .ui(ui, |ui| {
105                    ui.label(Vec2::new(5., 10.), &item);
106                });
107
108            match drag {
109                Drag::Dropped(_, Some(id)) => {
110                    self.fit_command = Some(FittingCommand::Fit {
111                        target_slot: id,
112                        item: item.clone(),
113                    });
114                    *item_dragging = false;
115                }
116                Drag::Dropped(_, _) => {
117                    *item_dragging = false;
118                }
119                Drag::Dragging(pos, id) => {
120                    debug!("inventory: pos: {:?}, id {:?}", pos, id);
121                    *item_dragging = true;
122                }
123                _ => {}
124            }
125        }
126    }
127
128    fn set_item(&mut self, id: u64, item: Option<String>) {
129        if let Some(slot) = self.slots.iter_mut().find(|(_, slot)| slot.id == id) {
130            slot.1.item = item;
131        }
132    }
133}
134
135#[macroquad::main("UI showcase")]
136async fn main() {
137    let mut data = Data::new();
138
139    let mut data0 = String::new();
140    let mut data1 = String::new();
141
142    let mut text0 = String::new();
143    let mut text1 = String::new();
144
145    let mut number0 = 0.;
146    let mut number1 = 0.;
147
148    let texture: Texture2D = load_texture("examples/ferris.png").await.unwrap();
149
150    loop {
151        clear_background(WHITE);
152
153        widgets::Window::new(hash!(), vec2(400., 200.), vec2(320., 400.))
154            .label("Shop")
155            .titlebar(true)
156            .ui(&mut *root_ui(), |ui| {
157                for i in 0..30 {
158                    Group::new(hash!("shop", i), Vec2::new(300., 80.)).ui(ui, |ui| {
159                        ui.label(Vec2::new(10., 10.), &format!("Item N {i}"));
160                        ui.label(Vec2::new(260., 40.), "10/10");
161                        ui.label(Vec2::new(200., 58.), &format!("{} kr", 800));
162                        if ui.button(Vec2::new(260., 55.), "buy") {
163                            data.inventory.push(format!("Item {i}"));
164                        }
165                    });
166                }
167            });
168
169        widgets::Window::new(hash!(), vec2(100., 220.), vec2(542., 430.))
170            .label("Fitting window")
171            .titlebar(true)
172            .ui(&mut *root_ui(), |ui| {
173                Group::new(hash!(), Vec2::new(230., 400.)).ui(ui, |ui| {
174                    data.slots(ui);
175                });
176                Group::new(hash!(), Vec2::new(280., 400.)).ui(ui, |ui| {
177                    data.inventory(ui);
178                });
179            });
180
181        widgets::Window::new(hash!(), vec2(470., 50.), vec2(300., 300.))
182            .label("Megaui Showcase Window")
183            .ui(&mut *root_ui(), |ui| {
184                ui.tree_node(hash!(), "input", |ui| {
185                    ui.label(None, "Some random text");
186                    if ui.button(None, "click me") {
187                        println!("hi");
188                    }
189
190                    ui.separator();
191
192                    ui.label(None, "Some other random text");
193                    if ui.button(None, "other button") {
194                        println!("hi2");
195                    }
196
197                    ui.separator();
198
199                    ui.input_text(hash!(), "<- input text 1", &mut data0);
200                    ui.input_text(hash!(), "<- input text 2", &mut data1);
201                    ui.label(None, &format!("Text entered: \"{data0}\" and \"{data1}\""));
202
203                    ui.separator();
204                });
205                ui.tree_node(hash!(), "buttons", |ui| {
206                    widgets::Button::new(texture.clone())
207                        .size(vec2(120., 70.))
208                        .ui(ui);
209                    ui.same_line(0.);
210                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
211                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
212                    ui.same_line(0.);
213                    widgets::Button::new(texture.clone())
214                        .size(vec2(120., 70.))
215                        .ui(ui);
216                });
217                ui.tree_node(hash!(), "sliders", |ui| {
218                    ui.slider(hash!(), "[-10 .. 10]", -10f32..10f32, &mut number0);
219                    ui.slider(hash!(), "[0 .. 100]", 0f32..100f32, &mut number1);
220                });
221                ui.tree_node(hash!(), "editbox 1", |ui| {
222                    ui.label(None, "This is editbox!");
223                    ui.editbox(hash!(), vec2(285., 165.), &mut text0);
224                });
225                ui.tree_node(hash!(), "editbox 2", |ui| {
226                    ui.label(None, "This is editbox!");
227                    ui.editbox(hash!(), vec2(285., 165.), &mut text1);
228                });
229            });
230
231        match data.fit_command.take() {
232            Some(FittingCommand::Unfit { target_slot }) => data.set_item(target_slot, None),
233            Some(FittingCommand::Fit { target_slot, item }) => {
234                data.set_item(target_slot, Some(item));
235            }
236            Some(FittingCommand::Refit {
237                target_slot,
238                origin_slot,
239            }) => {
240                let origin_item = data
241                    .slots
242                    .iter()
243                    .find_map(|(_, slot)| {
244                        if slot.id == origin_slot {
245                            Some(slot.item.clone())
246                        } else {
247                            None
248                        }
249                    })
250                    .flatten();
251                data.set_item(target_slot, origin_item);
252                data.set_item(origin_slot, None);
253            }
254            None => {}
255        };
256
257        next_frame().await;
258    }
259}
examples/ui_skins.rs (line 219)
6async fn main() {
7    let skin1 = {
8        let font = load_ttf_font("examples/ui_assets/HTOWERT.TTF")
9            .await
10            .unwrap();
11        let label_style = root_ui()
12            .style_builder()
13            .with_font(&font)
14            .unwrap()
15            .text_color(Color::from_rgba(180, 180, 120, 255))
16            .font_size(30)
17            .build();
18
19        let window_style = root_ui()
20            .style_builder()
21            .background(
22                Image::from_file_with_format(
23                    include_bytes!("../examples/ui_assets/window_background.png"),
24                    None,
25                )
26                .unwrap(),
27            )
28            .background_margin(RectOffset::new(20.0, 20.0, 10.0, 10.0))
29            .margin(RectOffset::new(-20.0, -30.0, 0.0, 0.0))
30            .build();
31
32        let button_style = root_ui()
33            .style_builder()
34            .background(
35                Image::from_file_with_format(
36                    include_bytes!("../examples/ui_assets/button_background.png"),
37                    None,
38                )
39                .unwrap(),
40            )
41            .background_margin(RectOffset::new(37.0, 37.0, 5.0, 5.0))
42            .margin(RectOffset::new(10.0, 10.0, 0.0, 0.0))
43            .background_hovered(
44                Image::from_file_with_format(
45                    include_bytes!("../examples/ui_assets/button_hovered_background.png"),
46                    None,
47                )
48                .unwrap(),
49            )
50            .background_clicked(
51                Image::from_file_with_format(
52                    include_bytes!("../examples/ui_assets/button_clicked_background.png"),
53                    None,
54                )
55                .unwrap(),
56            )
57            .with_font(&font)
58            .unwrap()
59            .text_color(Color::from_rgba(180, 180, 100, 255))
60            .font_size(40)
61            .build();
62
63        let editbox_style = root_ui()
64            .style_builder()
65            .background_margin(RectOffset::new(0., 0., 0., 0.))
66            .with_font(&font)
67            .unwrap()
68            .text_color(Color::from_rgba(120, 120, 120, 255))
69            .color_selected(Color::from_rgba(190, 190, 190, 255))
70            .font_size(50)
71            .build();
72
73        Skin {
74            editbox_style,
75            window_style,
76            button_style,
77            label_style,
78            ..root_ui().default_skin()
79        }
80    };
81
82    let skin2 = {
83        let font = load_ttf_font("examples/ui_assets/MinimalPixel v2.ttf")
84            .await
85            .unwrap();
86        let label_style = root_ui()
87            .style_builder()
88            .with_font(&font)
89            .unwrap()
90            .text_color(Color::from_rgba(120, 120, 120, 255))
91            .font_size(25)
92            .build();
93
94        let window_style = root_ui()
95            .style_builder()
96            .background(
97                Image::from_file_with_format(
98                    include_bytes!("../examples/ui_assets/window_background_2.png"),
99                    None,
100                )
101                .unwrap(),
102            )
103            .background_margin(RectOffset::new(52.0, 52.0, 52.0, 52.0))
104            .margin(RectOffset::new(-30.0, 0.0, -30.0, 0.0))
105            .build();
106
107        let button_style = root_ui()
108            .style_builder()
109            .background(
110                Image::from_file_with_format(
111                    include_bytes!("../examples/ui_assets/button_background_2.png"),
112                    None,
113                )
114                .unwrap(),
115            )
116            .background_margin(RectOffset::new(8.0, 8.0, 8.0, 8.0))
117            .background_hovered(
118                Image::from_file_with_format(
119                    include_bytes!("../examples/ui_assets/button_hovered_background_2.png"),
120                    None,
121                )
122                .unwrap(),
123            )
124            .background_clicked(
125                Image::from_file_with_format(
126                    include_bytes!("../examples/ui_assets/button_clicked_background_2.png"),
127                    None,
128                )
129                .unwrap(),
130            )
131            .with_font(&font)
132            .unwrap()
133            .text_color(Color::from_rgba(180, 180, 100, 255))
134            .font_size(40)
135            .build();
136
137        let checkbox_style = root_ui()
138            .style_builder()
139            .background(
140                Image::from_file_with_format(
141                    include_bytes!("../examples/ui_assets/checkbox_background.png"),
142                    None,
143                )
144                .unwrap(),
145            )
146            .background_hovered(
147                Image::from_file_with_format(
148                    include_bytes!("../examples/ui_assets/checkbox_hovered_background.png"),
149                    None,
150                )
151                .unwrap(),
152            )
153            .background_clicked(
154                Image::from_file_with_format(
155                    include_bytes!("../examples/ui_assets/checkbox_clicked_background.png"),
156                    None,
157                )
158                .unwrap(),
159            )
160            .build();
161
162        let editbox_style = root_ui()
163            .style_builder()
164            .background(
165                Image::from_file_with_format(
166                    include_bytes!("../examples/ui_assets/editbox_background.png"),
167                    None,
168                )
169                .unwrap(),
170            )
171            .background_margin(RectOffset::new(2., 2., 2., 2.))
172            .with_font(&font)
173            .unwrap()
174            .text_color(Color::from_rgba(120, 120, 120, 255))
175            .font_size(25)
176            .build();
177
178        let combobox_style = root_ui()
179            .style_builder()
180            .background(
181                Image::from_file_with_format(
182                    include_bytes!("../examples/ui_assets/combobox_background.png"),
183                    None,
184                )
185                .unwrap(),
186            )
187            .background_margin(RectOffset::new(4., 25., 6., 6.))
188            .with_font(&font)
189            .unwrap()
190            .text_color(Color::from_rgba(120, 120, 120, 255))
191            .color(Color::from_rgba(210, 210, 210, 255))
192            .font_size(25)
193            .build();
194
195        Skin {
196            window_style,
197            button_style,
198            label_style,
199            checkbox_style,
200            editbox_style,
201            combobox_style,
202            ..root_ui().default_skin()
203        }
204    };
205    let default_skin = root_ui().default_skin().clone();
206
207    let mut window1_skin = skin1.clone();
208    let mut window2_skin = skin2.clone();
209
210    let mut checkbox = false;
211    let mut text = String::new();
212    let mut number = 0.0f32;
213    let mut combobox = 0;
214
215    loop {
216        clear_background(GRAY);
217
218        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
219            ui.label(None, "Window 1");
220
221            if ui.button(None, "Skin 1") {
222                window1_skin = skin1.clone();
223            }
224            if ui.button(None, "Skin 2") {
225                window1_skin = skin2.clone();
226            }
227            if ui.button(None, "No Skin") {
228                window1_skin = default_skin.clone();
229            }
230        });
231        root_ui().same_line(0.);
232        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
233            ui.label(None, "Window 2");
234            if ui.button(None, "Skin 1") {
235                window2_skin = skin1.clone();
236            }
237            if ui.button(None, "Skin 2") {
238                window2_skin = skin2.clone();
239            }
240            if ui.button(None, "No Skin") {
241                window2_skin = default_skin.clone();
242            }
243        });
244
245        root_ui().push_skin(&window1_skin);
246
247        root_ui().window(hash!(), vec2(20., 250.), vec2(300., 300.), |ui| {
248            widgets::Button::new("Play")
249                .position(vec2(65.0, 15.0))
250                .ui(ui);
251            widgets::Button::new("Options")
252                .position(vec2(40.0, 75.0))
253                .ui(ui);
254
255            widgets::Button::new("Quit")
256                .position(vec2(65.0, 195.0))
257                .ui(ui);
258        });
259        root_ui().pop_skin();
260
261        root_ui().push_skin(&window2_skin);
262        root_ui().window(hash!(), vec2(250., 20.), vec2(500., 250.), |ui| {
263            ui.checkbox(hash!(), "Checkbox 1", &mut checkbox);
264            ui.combo_box(
265                hash!(),
266                "Combobox",
267                &["First option", "Second option"],
268                &mut combobox,
269            );
270            ui.input_text(hash!(), "Text", &mut text);
271            ui.drag(hash!(), "Drag", None, &mut number);
272
273            widgets::Button::new("Apply")
274                .position(vec2(80.0, 150.0))
275                .ui(ui);
276            widgets::Button::new("Cancel")
277                .position(vec2(280.0, 150.0))
278                .ui(ui);
279        });
280        root_ui().pop_skin();
281
282        next_frame().await;
283    }
284}
examples/shadertoy.rs (line 121)
47async fn main() {
48    let ferris = load_texture("examples/rust.png").await.unwrap();
49    let (color_picker_texture, color_picker_image) = color_picker_texture(200, 200);
50
51    let mut fragment_shader = DEFAULT_FRAGMENT_SHADER.to_string();
52    let mut vertex_shader = DEFAULT_VERTEX_SHADER.to_string();
53
54    let pipeline_params = PipelineParams {
55        depth_write: true,
56        depth_test: Comparison::LessOrEqual,
57        ..Default::default()
58    };
59
60    let mut material = load_material(
61        ShaderSource::Glsl {
62            vertex: &vertex_shader,
63            fragment: &fragment_shader,
64        },
65        MaterialParams {
66            pipeline_params,
67            ..Default::default()
68        },
69    )
70    .unwrap();
71    let mut error: Option<String> = None;
72
73    enum Mesh {
74        Sphere,
75        Cube,
76        Plane,
77    }
78    let mut mesh = Mesh::Sphere;
79
80    let mut camera = Camera3D {
81        position: vec3(-15., 15., -5.),
82        up: vec3(0., 1., 0.),
83        target: vec3(0., 5., -5.),
84        ..Default::default()
85    };
86
87    let mut colorpicker_window = false;
88    let mut color_picking_uniform = None;
89
90    let mut new_uniform_window = false;
91    let mut new_uniform_name = String::new();
92    let mut uniforms: Vec<(String, Uniform)> = vec![];
93
94    loop {
95        clear_background(WHITE);
96
97        set_camera(&camera);
98
99        draw_grid(
100            20,
101            1.,
102            Color::new(0.55, 0.55, 0.55, 0.75),
103            Color::new(0.75, 0.75, 0.75, 0.75),
104        );
105
106        gl_use_material(&material);
107        match mesh {
108            Mesh::Plane => draw_plane(vec3(0., 2., 0.), vec2(5., 5.), Some(&ferris), WHITE),
109            Mesh::Sphere => draw_sphere(vec3(0., 6., 0.), 5., Some(&ferris), WHITE),
110            Mesh::Cube => draw_cube(vec3(0., 5., 0.), vec3(10., 10., 10.), Some(&ferris), WHITE),
111        }
112        gl_use_default_material();
113
114        set_default_camera();
115
116        let mut need_update = false;
117
118        widgets::Window::new(hash!(), vec2(20., 20.), vec2(470., 650.))
119            .label("Shader")
120            .ui(&mut *root_ui(), |ui| {
121                ui.label(None, "Camera: ");
122                ui.same_line(0.0);
123                if ui.button(None, "Ortho") {
124                    camera.projection = Projection::Orthographics;
125                }
126                ui.same_line(0.0);
127                if ui.button(None, "Perspective") {
128                    camera.projection = Projection::Perspective;
129                }
130                ui.label(None, "Mesh: ");
131                ui.same_line(0.0);
132                if ui.button(None, "Sphere") {
133                    mesh = Mesh::Sphere;
134                }
135                ui.same_line(0.0);
136                if ui.button(None, "Cube") {
137                    mesh = Mesh::Cube;
138                }
139                ui.same_line(0.0);
140                if ui.button(None, "Plane") {
141                    mesh = Mesh::Plane;
142                }
143
144                ui.label(None, "Uniforms:");
145                ui.separator();
146
147                for (i, (name, uniform)) in uniforms.iter_mut().enumerate() {
148                    ui.label(None, &format!("{name}"));
149                    ui.same_line(120.0);
150
151                    match uniform {
152                        Uniform::Float1(x) => {
153                            widgets::InputText::new(hash!(hash!(), i))
154                                .size(vec2(200.0, 19.0))
155                                .filter_numbers()
156                                .ui(ui, x);
157
158                            if let Ok(x) = x.parse::<f32>() {
159                                material.set_uniform(name, x);
160                            }
161                        }
162                        Uniform::Float2(x, y) => {
163                            widgets::InputText::new(hash!(hash!(), i))
164                                .size(vec2(99.0, 19.0))
165                                .filter_numbers()
166                                .ui(ui, x);
167
168                            ui.same_line(0.0);
169
170                            widgets::InputText::new(hash!(hash!(), i))
171                                .size(vec2(99.0, 19.0))
172                                .filter_numbers()
173                                .ui(ui, y);
174
175                            if let (Ok(x), Ok(y)) = (x.parse::<f32>(), y.parse::<f32>()) {
176                                material.set_uniform(name, (x, y));
177                            }
178                        }
179                        Uniform::Float3(x, y, z) => {
180                            widgets::InputText::new(hash!(hash!(), i))
181                                .size(vec2(65.0, 19.0))
182                                .filter_numbers()
183                                .ui(ui, x);
184
185                            ui.same_line(0.0);
186
187                            widgets::InputText::new(hash!(hash!(), i))
188                                .size(vec2(65.0, 19.0))
189                                .filter_numbers()
190                                .ui(ui, y);
191
192                            ui.same_line(0.0);
193
194                            widgets::InputText::new(hash!(hash!(), i))
195                                .size(vec2(65.0, 19.0))
196                                .filter_numbers()
197                                .ui(ui, z);
198
199                            if let (Ok(x), Ok(y), Ok(z)) =
200                                (x.parse::<f32>(), y.parse::<f32>(), z.parse::<f32>())
201                            {
202                                material.set_uniform(name, (x, y, z));
203                            }
204                        }
205
206                        Uniform::Color(color) => {
207                            let mut canvas = ui.canvas();
208
209                            let cursor = canvas.cursor();
210
211                            canvas.rect(
212                                Rect::new(cursor.x + 20.0, cursor.y, 50.0, 18.0),
213                                Color::new(0.2, 0.2, 0.2, 1.0),
214                                Color::new(color.x, color.y, color.z, 1.0),
215                            );
216
217                            if ui.button(None, "change") {
218                                colorpicker_window = true;
219                                color_picking_uniform = Some(name.to_owned());
220                            }
221                            material.set_uniform(name, (color.x, color.y, color.z));
222                        }
223                    }
224                }
225                ui.separator();
226                if ui.button(None, "New uniform") {
227                    new_uniform_window = true;
228                }
229                TreeNode::new(hash!(), "Fragment shader")
230                    .init_unfolded()
231                    .ui(ui, |ui| {
232                        if ui.editbox(hash!(), vec2(440., 200.), &mut fragment_shader) {
233                            need_update = true;
234                        };
235                    });
236                ui.tree_node(hash!(), "Vertex shader", |ui| {
237                    if ui.editbox(hash!(), vec2(440., 300.), &mut vertex_shader) {
238                        need_update = true;
239                    };
240                });
241
242                if let Some(ref error) = error {
243                    Label::new(error).multiline(14.0).ui(ui);
244                }
245            });
246
247        if new_uniform_window {
248            widgets::Window::new(hash!(), vec2(100., 100.), vec2(200., 80.))
249                .label("New uniform")
250                .ui(&mut *root_ui(), |ui| {
251                    if ui.active_window_focused() == false {
252                        new_uniform_window = false;
253                    }
254                    ui.input_text(hash!(), "Name", &mut new_uniform_name);
255                    let uniform_type = ui.combo_box(
256                        hash!(),
257                        "Type",
258                        &["Float1", "Float2", "Float3", "Color"],
259                        None,
260                    );
261
262                    if ui.button(None, "Add") {
263                        if new_uniform_name.is_empty() == false {
264                            let uniform = match uniform_type {
265                                0 => Uniform::Float1("0".to_string()),
266                                1 => Uniform::Float2("0".to_string(), "0".to_string()),
267                                2 => Uniform::Float3(
268                                    "0".to_string(),
269                                    "0".to_string(),
270                                    "0".to_string(),
271                                ),
272                                3 => Uniform::Color(vec3(0.0, 0.0, 0.0)),
273                                _ => unreachable!(),
274                            };
275                            uniforms.push((new_uniform_name.clone(), uniform));
276                            new_uniform_name.clear();
277                            need_update = true;
278                        }
279                        new_uniform_window = false;
280                    }
281
282                    ui.same_line(0.0);
283                    if ui.button(None, "Cancel") {
284                        new_uniform_window = false;
285                    }
286                });
287        }
288
289        if colorpicker_window {
290            colorpicker_window &= widgets::Window::new(hash!(), vec2(140., 100.), vec2(210., 240.))
291                .label("Colorpicker")
292                .ui(&mut *root_ui(), |ui| {
293                    if ui.active_window_focused() == false {
294                        colorpicker_window = false;
295                    }
296
297                    let mut canvas = ui.canvas();
298                    let cursor = canvas.cursor();
299                    let mouse = mouse_position();
300                    let x = mouse.0 as i32 - cursor.x as i32;
301                    let y = mouse.1 as i32 - (cursor.y as i32 + 20);
302
303                    let color = color_picker_image
304                        .get_pixel(x.max(0).min(199) as u32, y.max(0).min(199) as u32);
305
306                    canvas.rect(
307                        Rect::new(cursor.x, cursor.y, 200.0, 18.0),
308                        Color::new(0.0, 0.0, 0.0, 1.0),
309                        Color::new(color.r, color.g, color.b, 1.0),
310                    );
311                    canvas.image(
312                        Rect::new(cursor.x, cursor.y + 20.0, 200.0, 200.0),
313                        &color_picker_texture,
314                    );
315
316                    if x >= 0 && x < 200 && y >= 0 && y < 200 {
317                        canvas.rect(
318                            Rect::new(mouse.0 - 3.5, mouse.1 - 3.5, 7.0, 7.0),
319                            Color::new(0.3, 0.3, 0.3, 1.0),
320                            Color::new(1.0, 1.0, 1.0, 1.0),
321                        );
322
323                        if is_mouse_button_down(MouseButton::Left) {
324                            colorpicker_window = false;
325                            let uniform_name = color_picking_uniform.take().unwrap();
326
327                            uniforms
328                                .iter_mut()
329                                .find(|(name, _)| name == &uniform_name)
330                                .unwrap()
331                                .1 = Uniform::Color(vec3(color.r, color.g, color.b));
332                        }
333                    }
334                });
335        }
336
337        if need_update {
338            let uniforms = uniforms
339                .iter()
340                .map(|(name, uniform)| UniformDesc::new(name, uniform.uniform_type()))
341                .collect::<Vec<_>>();
342
343            match load_material(
344                ShaderSource::Glsl {
345                    vertex: &vertex_shader,
346                    fragment: &fragment_shader,
347                },
348                MaterialParams {
349                    pipeline_params,
350                    uniforms,
351                    textures: vec![],
352                },
353            ) {
354                Ok(new_material) => {
355                    material = new_material;
356                    error = None;
357                }
358                Err(err) => {
359                    error = Some(format!("{err:#?}"));
360                }
361            }
362        }
363
364        next_frame().await
365    }
366}
Source

pub fn calc_size(&mut self, label: &str) -> Vec2

Source§

impl Ui

Source

pub fn popup<F: FnOnce(&mut Ui)>(&mut self, id: Id, size: Vec2, f: F)

Source§

impl Ui

Source

pub fn separator(&mut self)

Examples found in repository?
examples/exit_dialog.rs (line 24)
5async fn main() {
6    prevent_quit();
7
8    let mut show_exit_dialog = false;
9    let mut user_decided_to_exit = false;
10
11    loop {
12        clear_background(GRAY);
13
14        if is_quit_requested() {
15            show_exit_dialog = true;
16        }
17
18        if show_exit_dialog {
19            let dialog_size = vec2(200., 70.);
20            let screen_size = vec2(screen_width(), screen_height());
21            let dialog_position = screen_size / 2. - dialog_size / 2.;
22            Window::new(hash!(), dialog_position, dialog_size).ui(&mut *root_ui(), |ui| {
23                ui.label(None, "Do you really want to quit?");
24                ui.separator();
25                ui.same_line(60.);
26                if ui.button(None, "Yes") {
27                    user_decided_to_exit = true;
28                }
29                ui.same_line(120.);
30                if ui.button(None, "No") {
31                    show_exit_dialog = false;
32                }
33            });
34        }
35
36        if user_decided_to_exit {
37            break;
38        }
39
40        next_frame().await
41    }
42}
More examples
Hide additional examples
examples/ui.rs (line 190)
136async fn main() {
137    let mut data = Data::new();
138
139    let mut data0 = String::new();
140    let mut data1 = String::new();
141
142    let mut text0 = String::new();
143    let mut text1 = String::new();
144
145    let mut number0 = 0.;
146    let mut number1 = 0.;
147
148    let texture: Texture2D = load_texture("examples/ferris.png").await.unwrap();
149
150    loop {
151        clear_background(WHITE);
152
153        widgets::Window::new(hash!(), vec2(400., 200.), vec2(320., 400.))
154            .label("Shop")
155            .titlebar(true)
156            .ui(&mut *root_ui(), |ui| {
157                for i in 0..30 {
158                    Group::new(hash!("shop", i), Vec2::new(300., 80.)).ui(ui, |ui| {
159                        ui.label(Vec2::new(10., 10.), &format!("Item N {i}"));
160                        ui.label(Vec2::new(260., 40.), "10/10");
161                        ui.label(Vec2::new(200., 58.), &format!("{} kr", 800));
162                        if ui.button(Vec2::new(260., 55.), "buy") {
163                            data.inventory.push(format!("Item {i}"));
164                        }
165                    });
166                }
167            });
168
169        widgets::Window::new(hash!(), vec2(100., 220.), vec2(542., 430.))
170            .label("Fitting window")
171            .titlebar(true)
172            .ui(&mut *root_ui(), |ui| {
173                Group::new(hash!(), Vec2::new(230., 400.)).ui(ui, |ui| {
174                    data.slots(ui);
175                });
176                Group::new(hash!(), Vec2::new(280., 400.)).ui(ui, |ui| {
177                    data.inventory(ui);
178                });
179            });
180
181        widgets::Window::new(hash!(), vec2(470., 50.), vec2(300., 300.))
182            .label("Megaui Showcase Window")
183            .ui(&mut *root_ui(), |ui| {
184                ui.tree_node(hash!(), "input", |ui| {
185                    ui.label(None, "Some random text");
186                    if ui.button(None, "click me") {
187                        println!("hi");
188                    }
189
190                    ui.separator();
191
192                    ui.label(None, "Some other random text");
193                    if ui.button(None, "other button") {
194                        println!("hi2");
195                    }
196
197                    ui.separator();
198
199                    ui.input_text(hash!(), "<- input text 1", &mut data0);
200                    ui.input_text(hash!(), "<- input text 2", &mut data1);
201                    ui.label(None, &format!("Text entered: \"{data0}\" and \"{data1}\""));
202
203                    ui.separator();
204                });
205                ui.tree_node(hash!(), "buttons", |ui| {
206                    widgets::Button::new(texture.clone())
207                        .size(vec2(120., 70.))
208                        .ui(ui);
209                    ui.same_line(0.);
210                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
211                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
212                    ui.same_line(0.);
213                    widgets::Button::new(texture.clone())
214                        .size(vec2(120., 70.))
215                        .ui(ui);
216                });
217                ui.tree_node(hash!(), "sliders", |ui| {
218                    ui.slider(hash!(), "[-10 .. 10]", -10f32..10f32, &mut number0);
219                    ui.slider(hash!(), "[0 .. 100]", 0f32..100f32, &mut number1);
220                });
221                ui.tree_node(hash!(), "editbox 1", |ui| {
222                    ui.label(None, "This is editbox!");
223                    ui.editbox(hash!(), vec2(285., 165.), &mut text0);
224                });
225                ui.tree_node(hash!(), "editbox 2", |ui| {
226                    ui.label(None, "This is editbox!");
227                    ui.editbox(hash!(), vec2(285., 165.), &mut text1);
228                });
229            });
230
231        match data.fit_command.take() {
232            Some(FittingCommand::Unfit { target_slot }) => data.set_item(target_slot, None),
233            Some(FittingCommand::Fit { target_slot, item }) => {
234                data.set_item(target_slot, Some(item));
235            }
236            Some(FittingCommand::Refit {
237                target_slot,
238                origin_slot,
239            }) => {
240                let origin_item = data
241                    .slots
242                    .iter()
243                    .find_map(|(_, slot)| {
244                        if slot.id == origin_slot {
245                            Some(slot.item.clone())
246                        } else {
247                            None
248                        }
249                    })
250                    .flatten();
251                data.set_item(target_slot, origin_item);
252                data.set_item(origin_slot, None);
253            }
254            None => {}
255        };
256
257        next_frame().await;
258    }
259}
examples/shadertoy.rs (line 145)
47async fn main() {
48    let ferris = load_texture("examples/rust.png").await.unwrap();
49    let (color_picker_texture, color_picker_image) = color_picker_texture(200, 200);
50
51    let mut fragment_shader = DEFAULT_FRAGMENT_SHADER.to_string();
52    let mut vertex_shader = DEFAULT_VERTEX_SHADER.to_string();
53
54    let pipeline_params = PipelineParams {
55        depth_write: true,
56        depth_test: Comparison::LessOrEqual,
57        ..Default::default()
58    };
59
60    let mut material = load_material(
61        ShaderSource::Glsl {
62            vertex: &vertex_shader,
63            fragment: &fragment_shader,
64        },
65        MaterialParams {
66            pipeline_params,
67            ..Default::default()
68        },
69    )
70    .unwrap();
71    let mut error: Option<String> = None;
72
73    enum Mesh {
74        Sphere,
75        Cube,
76        Plane,
77    }
78    let mut mesh = Mesh::Sphere;
79
80    let mut camera = Camera3D {
81        position: vec3(-15., 15., -5.),
82        up: vec3(0., 1., 0.),
83        target: vec3(0., 5., -5.),
84        ..Default::default()
85    };
86
87    let mut colorpicker_window = false;
88    let mut color_picking_uniform = None;
89
90    let mut new_uniform_window = false;
91    let mut new_uniform_name = String::new();
92    let mut uniforms: Vec<(String, Uniform)> = vec![];
93
94    loop {
95        clear_background(WHITE);
96
97        set_camera(&camera);
98
99        draw_grid(
100            20,
101            1.,
102            Color::new(0.55, 0.55, 0.55, 0.75),
103            Color::new(0.75, 0.75, 0.75, 0.75),
104        );
105
106        gl_use_material(&material);
107        match mesh {
108            Mesh::Plane => draw_plane(vec3(0., 2., 0.), vec2(5., 5.), Some(&ferris), WHITE),
109            Mesh::Sphere => draw_sphere(vec3(0., 6., 0.), 5., Some(&ferris), WHITE),
110            Mesh::Cube => draw_cube(vec3(0., 5., 0.), vec3(10., 10., 10.), Some(&ferris), WHITE),
111        }
112        gl_use_default_material();
113
114        set_default_camera();
115
116        let mut need_update = false;
117
118        widgets::Window::new(hash!(), vec2(20., 20.), vec2(470., 650.))
119            .label("Shader")
120            .ui(&mut *root_ui(), |ui| {
121                ui.label(None, "Camera: ");
122                ui.same_line(0.0);
123                if ui.button(None, "Ortho") {
124                    camera.projection = Projection::Orthographics;
125                }
126                ui.same_line(0.0);
127                if ui.button(None, "Perspective") {
128                    camera.projection = Projection::Perspective;
129                }
130                ui.label(None, "Mesh: ");
131                ui.same_line(0.0);
132                if ui.button(None, "Sphere") {
133                    mesh = Mesh::Sphere;
134                }
135                ui.same_line(0.0);
136                if ui.button(None, "Cube") {
137                    mesh = Mesh::Cube;
138                }
139                ui.same_line(0.0);
140                if ui.button(None, "Plane") {
141                    mesh = Mesh::Plane;
142                }
143
144                ui.label(None, "Uniforms:");
145                ui.separator();
146
147                for (i, (name, uniform)) in uniforms.iter_mut().enumerate() {
148                    ui.label(None, &format!("{name}"));
149                    ui.same_line(120.0);
150
151                    match uniform {
152                        Uniform::Float1(x) => {
153                            widgets::InputText::new(hash!(hash!(), i))
154                                .size(vec2(200.0, 19.0))
155                                .filter_numbers()
156                                .ui(ui, x);
157
158                            if let Ok(x) = x.parse::<f32>() {
159                                material.set_uniform(name, x);
160                            }
161                        }
162                        Uniform::Float2(x, y) => {
163                            widgets::InputText::new(hash!(hash!(), i))
164                                .size(vec2(99.0, 19.0))
165                                .filter_numbers()
166                                .ui(ui, x);
167
168                            ui.same_line(0.0);
169
170                            widgets::InputText::new(hash!(hash!(), i))
171                                .size(vec2(99.0, 19.0))
172                                .filter_numbers()
173                                .ui(ui, y);
174
175                            if let (Ok(x), Ok(y)) = (x.parse::<f32>(), y.parse::<f32>()) {
176                                material.set_uniform(name, (x, y));
177                            }
178                        }
179                        Uniform::Float3(x, y, z) => {
180                            widgets::InputText::new(hash!(hash!(), i))
181                                .size(vec2(65.0, 19.0))
182                                .filter_numbers()
183                                .ui(ui, x);
184
185                            ui.same_line(0.0);
186
187                            widgets::InputText::new(hash!(hash!(), i))
188                                .size(vec2(65.0, 19.0))
189                                .filter_numbers()
190                                .ui(ui, y);
191
192                            ui.same_line(0.0);
193
194                            widgets::InputText::new(hash!(hash!(), i))
195                                .size(vec2(65.0, 19.0))
196                                .filter_numbers()
197                                .ui(ui, z);
198
199                            if let (Ok(x), Ok(y), Ok(z)) =
200                                (x.parse::<f32>(), y.parse::<f32>(), z.parse::<f32>())
201                            {
202                                material.set_uniform(name, (x, y, z));
203                            }
204                        }
205
206                        Uniform::Color(color) => {
207                            let mut canvas = ui.canvas();
208
209                            let cursor = canvas.cursor();
210
211                            canvas.rect(
212                                Rect::new(cursor.x + 20.0, cursor.y, 50.0, 18.0),
213                                Color::new(0.2, 0.2, 0.2, 1.0),
214                                Color::new(color.x, color.y, color.z, 1.0),
215                            );
216
217                            if ui.button(None, "change") {
218                                colorpicker_window = true;
219                                color_picking_uniform = Some(name.to_owned());
220                            }
221                            material.set_uniform(name, (color.x, color.y, color.z));
222                        }
223                    }
224                }
225                ui.separator();
226                if ui.button(None, "New uniform") {
227                    new_uniform_window = true;
228                }
229                TreeNode::new(hash!(), "Fragment shader")
230                    .init_unfolded()
231                    .ui(ui, |ui| {
232                        if ui.editbox(hash!(), vec2(440., 200.), &mut fragment_shader) {
233                            need_update = true;
234                        };
235                    });
236                ui.tree_node(hash!(), "Vertex shader", |ui| {
237                    if ui.editbox(hash!(), vec2(440., 300.), &mut vertex_shader) {
238                        need_update = true;
239                    };
240                });
241
242                if let Some(ref error) = error {
243                    Label::new(error).multiline(14.0).ui(ui);
244                }
245            });
246
247        if new_uniform_window {
248            widgets::Window::new(hash!(), vec2(100., 100.), vec2(200., 80.))
249                .label("New uniform")
250                .ui(&mut *root_ui(), |ui| {
251                    if ui.active_window_focused() == false {
252                        new_uniform_window = false;
253                    }
254                    ui.input_text(hash!(), "Name", &mut new_uniform_name);
255                    let uniform_type = ui.combo_box(
256                        hash!(),
257                        "Type",
258                        &["Float1", "Float2", "Float3", "Color"],
259                        None,
260                    );
261
262                    if ui.button(None, "Add") {
263                        if new_uniform_name.is_empty() == false {
264                            let uniform = match uniform_type {
265                                0 => Uniform::Float1("0".to_string()),
266                                1 => Uniform::Float2("0".to_string(), "0".to_string()),
267                                2 => Uniform::Float3(
268                                    "0".to_string(),
269                                    "0".to_string(),
270                                    "0".to_string(),
271                                ),
272                                3 => Uniform::Color(vec3(0.0, 0.0, 0.0)),
273                                _ => unreachable!(),
274                            };
275                            uniforms.push((new_uniform_name.clone(), uniform));
276                            new_uniform_name.clear();
277                            need_update = true;
278                        }
279                        new_uniform_window = false;
280                    }
281
282                    ui.same_line(0.0);
283                    if ui.button(None, "Cancel") {
284                        new_uniform_window = false;
285                    }
286                });
287        }
288
289        if colorpicker_window {
290            colorpicker_window &= widgets::Window::new(hash!(), vec2(140., 100.), vec2(210., 240.))
291                .label("Colorpicker")
292                .ui(&mut *root_ui(), |ui| {
293                    if ui.active_window_focused() == false {
294                        colorpicker_window = false;
295                    }
296
297                    let mut canvas = ui.canvas();
298                    let cursor = canvas.cursor();
299                    let mouse = mouse_position();
300                    let x = mouse.0 as i32 - cursor.x as i32;
301                    let y = mouse.1 as i32 - (cursor.y as i32 + 20);
302
303                    let color = color_picker_image
304                        .get_pixel(x.max(0).min(199) as u32, y.max(0).min(199) as u32);
305
306                    canvas.rect(
307                        Rect::new(cursor.x, cursor.y, 200.0, 18.0),
308                        Color::new(0.0, 0.0, 0.0, 1.0),
309                        Color::new(color.r, color.g, color.b, 1.0),
310                    );
311                    canvas.image(
312                        Rect::new(cursor.x, cursor.y + 20.0, 200.0, 200.0),
313                        &color_picker_texture,
314                    );
315
316                    if x >= 0 && x < 200 && y >= 0 && y < 200 {
317                        canvas.rect(
318                            Rect::new(mouse.0 - 3.5, mouse.1 - 3.5, 7.0, 7.0),
319                            Color::new(0.3, 0.3, 0.3, 1.0),
320                            Color::new(1.0, 1.0, 1.0, 1.0),
321                        );
322
323                        if is_mouse_button_down(MouseButton::Left) {
324                            colorpicker_window = false;
325                            let uniform_name = color_picking_uniform.take().unwrap();
326
327                            uniforms
328                                .iter_mut()
329                                .find(|(name, _)| name == &uniform_name)
330                                .unwrap()
331                                .1 = Uniform::Color(vec3(color.r, color.g, color.b));
332                        }
333                    }
334                });
335        }
336
337        if need_update {
338            let uniforms = uniforms
339                .iter()
340                .map(|(name, uniform)| UniformDesc::new(name, uniform.uniform_type()))
341                .collect::<Vec<_>>();
342
343            match load_material(
344                ShaderSource::Glsl {
345                    vertex: &vertex_shader,
346                    fragment: &fragment_shader,
347                },
348                MaterialParams {
349                    pipeline_params,
350                    uniforms,
351                    textures: vec![],
352                },
353            ) {
354                Ok(new_material) => {
355                    material = new_material;
356                    error = None;
357                }
358                Err(err) => {
359                    error = Some(format!("{err:#?}"));
360                }
361            }
362        }
363
364        next_frame().await
365    }
366}
Source§

impl Ui

Source

pub fn slider(&mut self, id: Id, label: &str, range: Range<f32>, data: &mut f32)

Examples found in repository?
examples/ui.rs (line 218)
136async fn main() {
137    let mut data = Data::new();
138
139    let mut data0 = String::new();
140    let mut data1 = String::new();
141
142    let mut text0 = String::new();
143    let mut text1 = String::new();
144
145    let mut number0 = 0.;
146    let mut number1 = 0.;
147
148    let texture: Texture2D = load_texture("examples/ferris.png").await.unwrap();
149
150    loop {
151        clear_background(WHITE);
152
153        widgets::Window::new(hash!(), vec2(400., 200.), vec2(320., 400.))
154            .label("Shop")
155            .titlebar(true)
156            .ui(&mut *root_ui(), |ui| {
157                for i in 0..30 {
158                    Group::new(hash!("shop", i), Vec2::new(300., 80.)).ui(ui, |ui| {
159                        ui.label(Vec2::new(10., 10.), &format!("Item N {i}"));
160                        ui.label(Vec2::new(260., 40.), "10/10");
161                        ui.label(Vec2::new(200., 58.), &format!("{} kr", 800));
162                        if ui.button(Vec2::new(260., 55.), "buy") {
163                            data.inventory.push(format!("Item {i}"));
164                        }
165                    });
166                }
167            });
168
169        widgets::Window::new(hash!(), vec2(100., 220.), vec2(542., 430.))
170            .label("Fitting window")
171            .titlebar(true)
172            .ui(&mut *root_ui(), |ui| {
173                Group::new(hash!(), Vec2::new(230., 400.)).ui(ui, |ui| {
174                    data.slots(ui);
175                });
176                Group::new(hash!(), Vec2::new(280., 400.)).ui(ui, |ui| {
177                    data.inventory(ui);
178                });
179            });
180
181        widgets::Window::new(hash!(), vec2(470., 50.), vec2(300., 300.))
182            .label("Megaui Showcase Window")
183            .ui(&mut *root_ui(), |ui| {
184                ui.tree_node(hash!(), "input", |ui| {
185                    ui.label(None, "Some random text");
186                    if ui.button(None, "click me") {
187                        println!("hi");
188                    }
189
190                    ui.separator();
191
192                    ui.label(None, "Some other random text");
193                    if ui.button(None, "other button") {
194                        println!("hi2");
195                    }
196
197                    ui.separator();
198
199                    ui.input_text(hash!(), "<- input text 1", &mut data0);
200                    ui.input_text(hash!(), "<- input text 2", &mut data1);
201                    ui.label(None, &format!("Text entered: \"{data0}\" and \"{data1}\""));
202
203                    ui.separator();
204                });
205                ui.tree_node(hash!(), "buttons", |ui| {
206                    widgets::Button::new(texture.clone())
207                        .size(vec2(120., 70.))
208                        .ui(ui);
209                    ui.same_line(0.);
210                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
211                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
212                    ui.same_line(0.);
213                    widgets::Button::new(texture.clone())
214                        .size(vec2(120., 70.))
215                        .ui(ui);
216                });
217                ui.tree_node(hash!(), "sliders", |ui| {
218                    ui.slider(hash!(), "[-10 .. 10]", -10f32..10f32, &mut number0);
219                    ui.slider(hash!(), "[0 .. 100]", 0f32..100f32, &mut number1);
220                });
221                ui.tree_node(hash!(), "editbox 1", |ui| {
222                    ui.label(None, "This is editbox!");
223                    ui.editbox(hash!(), vec2(285., 165.), &mut text0);
224                });
225                ui.tree_node(hash!(), "editbox 2", |ui| {
226                    ui.label(None, "This is editbox!");
227                    ui.editbox(hash!(), vec2(285., 165.), &mut text1);
228                });
229            });
230
231        match data.fit_command.take() {
232            Some(FittingCommand::Unfit { target_slot }) => data.set_item(target_slot, None),
233            Some(FittingCommand::Fit { target_slot, item }) => {
234                data.set_item(target_slot, Some(item));
235            }
236            Some(FittingCommand::Refit {
237                target_slot,
238                origin_slot,
239            }) => {
240                let origin_item = data
241                    .slots
242                    .iter()
243                    .find_map(|(_, slot)| {
244                        if slot.id == origin_slot {
245                            Some(slot.item.clone())
246                        } else {
247                            None
248                        }
249                    })
250                    .flatten();
251                data.set_item(target_slot, origin_item);
252                data.set_item(origin_slot, None);
253            }
254            None => {}
255        };
256
257        next_frame().await;
258    }
259}
Source§

impl Ui

Source

pub fn tabbar<'a>(&mut self, id: Id, size: Vec2, tabs: &'a [&'a str]) -> u32

Source§

impl Ui

Source

pub fn texture(&mut self, texture: Texture2D, w: f32, h: f32) -> bool

Source§

impl Ui

Source

pub fn tree_node<F: FnOnce(&mut Ui)>( &mut self, id: Id, label: &str, f: F, ) -> bool

Examples found in repository?
examples/ui.rs (lines 184-204)
136async fn main() {
137    let mut data = Data::new();
138
139    let mut data0 = String::new();
140    let mut data1 = String::new();
141
142    let mut text0 = String::new();
143    let mut text1 = String::new();
144
145    let mut number0 = 0.;
146    let mut number1 = 0.;
147
148    let texture: Texture2D = load_texture("examples/ferris.png").await.unwrap();
149
150    loop {
151        clear_background(WHITE);
152
153        widgets::Window::new(hash!(), vec2(400., 200.), vec2(320., 400.))
154            .label("Shop")
155            .titlebar(true)
156            .ui(&mut *root_ui(), |ui| {
157                for i in 0..30 {
158                    Group::new(hash!("shop", i), Vec2::new(300., 80.)).ui(ui, |ui| {
159                        ui.label(Vec2::new(10., 10.), &format!("Item N {i}"));
160                        ui.label(Vec2::new(260., 40.), "10/10");
161                        ui.label(Vec2::new(200., 58.), &format!("{} kr", 800));
162                        if ui.button(Vec2::new(260., 55.), "buy") {
163                            data.inventory.push(format!("Item {i}"));
164                        }
165                    });
166                }
167            });
168
169        widgets::Window::new(hash!(), vec2(100., 220.), vec2(542., 430.))
170            .label("Fitting window")
171            .titlebar(true)
172            .ui(&mut *root_ui(), |ui| {
173                Group::new(hash!(), Vec2::new(230., 400.)).ui(ui, |ui| {
174                    data.slots(ui);
175                });
176                Group::new(hash!(), Vec2::new(280., 400.)).ui(ui, |ui| {
177                    data.inventory(ui);
178                });
179            });
180
181        widgets::Window::new(hash!(), vec2(470., 50.), vec2(300., 300.))
182            .label("Megaui Showcase Window")
183            .ui(&mut *root_ui(), |ui| {
184                ui.tree_node(hash!(), "input", |ui| {
185                    ui.label(None, "Some random text");
186                    if ui.button(None, "click me") {
187                        println!("hi");
188                    }
189
190                    ui.separator();
191
192                    ui.label(None, "Some other random text");
193                    if ui.button(None, "other button") {
194                        println!("hi2");
195                    }
196
197                    ui.separator();
198
199                    ui.input_text(hash!(), "<- input text 1", &mut data0);
200                    ui.input_text(hash!(), "<- input text 2", &mut data1);
201                    ui.label(None, &format!("Text entered: \"{data0}\" and \"{data1}\""));
202
203                    ui.separator();
204                });
205                ui.tree_node(hash!(), "buttons", |ui| {
206                    widgets::Button::new(texture.clone())
207                        .size(vec2(120., 70.))
208                        .ui(ui);
209                    ui.same_line(0.);
210                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
211                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
212                    ui.same_line(0.);
213                    widgets::Button::new(texture.clone())
214                        .size(vec2(120., 70.))
215                        .ui(ui);
216                });
217                ui.tree_node(hash!(), "sliders", |ui| {
218                    ui.slider(hash!(), "[-10 .. 10]", -10f32..10f32, &mut number0);
219                    ui.slider(hash!(), "[0 .. 100]", 0f32..100f32, &mut number1);
220                });
221                ui.tree_node(hash!(), "editbox 1", |ui| {
222                    ui.label(None, "This is editbox!");
223                    ui.editbox(hash!(), vec2(285., 165.), &mut text0);
224                });
225                ui.tree_node(hash!(), "editbox 2", |ui| {
226                    ui.label(None, "This is editbox!");
227                    ui.editbox(hash!(), vec2(285., 165.), &mut text1);
228                });
229            });
230
231        match data.fit_command.take() {
232            Some(FittingCommand::Unfit { target_slot }) => data.set_item(target_slot, None),
233            Some(FittingCommand::Fit { target_slot, item }) => {
234                data.set_item(target_slot, Some(item));
235            }
236            Some(FittingCommand::Refit {
237                target_slot,
238                origin_slot,
239            }) => {
240                let origin_item = data
241                    .slots
242                    .iter()
243                    .find_map(|(_, slot)| {
244                        if slot.id == origin_slot {
245                            Some(slot.item.clone())
246                        } else {
247                            None
248                        }
249                    })
250                    .flatten();
251                data.set_item(target_slot, origin_item);
252                data.set_item(origin_slot, None);
253            }
254            None => {}
255        };
256
257        next_frame().await;
258    }
259}
More examples
Hide additional examples
examples/shadertoy.rs (lines 236-240)
47async fn main() {
48    let ferris = load_texture("examples/rust.png").await.unwrap();
49    let (color_picker_texture, color_picker_image) = color_picker_texture(200, 200);
50
51    let mut fragment_shader = DEFAULT_FRAGMENT_SHADER.to_string();
52    let mut vertex_shader = DEFAULT_VERTEX_SHADER.to_string();
53
54    let pipeline_params = PipelineParams {
55        depth_write: true,
56        depth_test: Comparison::LessOrEqual,
57        ..Default::default()
58    };
59
60    let mut material = load_material(
61        ShaderSource::Glsl {
62            vertex: &vertex_shader,
63            fragment: &fragment_shader,
64        },
65        MaterialParams {
66            pipeline_params,
67            ..Default::default()
68        },
69    )
70    .unwrap();
71    let mut error: Option<String> = None;
72
73    enum Mesh {
74        Sphere,
75        Cube,
76        Plane,
77    }
78    let mut mesh = Mesh::Sphere;
79
80    let mut camera = Camera3D {
81        position: vec3(-15., 15., -5.),
82        up: vec3(0., 1., 0.),
83        target: vec3(0., 5., -5.),
84        ..Default::default()
85    };
86
87    let mut colorpicker_window = false;
88    let mut color_picking_uniform = None;
89
90    let mut new_uniform_window = false;
91    let mut new_uniform_name = String::new();
92    let mut uniforms: Vec<(String, Uniform)> = vec![];
93
94    loop {
95        clear_background(WHITE);
96
97        set_camera(&camera);
98
99        draw_grid(
100            20,
101            1.,
102            Color::new(0.55, 0.55, 0.55, 0.75),
103            Color::new(0.75, 0.75, 0.75, 0.75),
104        );
105
106        gl_use_material(&material);
107        match mesh {
108            Mesh::Plane => draw_plane(vec3(0., 2., 0.), vec2(5., 5.), Some(&ferris), WHITE),
109            Mesh::Sphere => draw_sphere(vec3(0., 6., 0.), 5., Some(&ferris), WHITE),
110            Mesh::Cube => draw_cube(vec3(0., 5., 0.), vec3(10., 10., 10.), Some(&ferris), WHITE),
111        }
112        gl_use_default_material();
113
114        set_default_camera();
115
116        let mut need_update = false;
117
118        widgets::Window::new(hash!(), vec2(20., 20.), vec2(470., 650.))
119            .label("Shader")
120            .ui(&mut *root_ui(), |ui| {
121                ui.label(None, "Camera: ");
122                ui.same_line(0.0);
123                if ui.button(None, "Ortho") {
124                    camera.projection = Projection::Orthographics;
125                }
126                ui.same_line(0.0);
127                if ui.button(None, "Perspective") {
128                    camera.projection = Projection::Perspective;
129                }
130                ui.label(None, "Mesh: ");
131                ui.same_line(0.0);
132                if ui.button(None, "Sphere") {
133                    mesh = Mesh::Sphere;
134                }
135                ui.same_line(0.0);
136                if ui.button(None, "Cube") {
137                    mesh = Mesh::Cube;
138                }
139                ui.same_line(0.0);
140                if ui.button(None, "Plane") {
141                    mesh = Mesh::Plane;
142                }
143
144                ui.label(None, "Uniforms:");
145                ui.separator();
146
147                for (i, (name, uniform)) in uniforms.iter_mut().enumerate() {
148                    ui.label(None, &format!("{name}"));
149                    ui.same_line(120.0);
150
151                    match uniform {
152                        Uniform::Float1(x) => {
153                            widgets::InputText::new(hash!(hash!(), i))
154                                .size(vec2(200.0, 19.0))
155                                .filter_numbers()
156                                .ui(ui, x);
157
158                            if let Ok(x) = x.parse::<f32>() {
159                                material.set_uniform(name, x);
160                            }
161                        }
162                        Uniform::Float2(x, y) => {
163                            widgets::InputText::new(hash!(hash!(), i))
164                                .size(vec2(99.0, 19.0))
165                                .filter_numbers()
166                                .ui(ui, x);
167
168                            ui.same_line(0.0);
169
170                            widgets::InputText::new(hash!(hash!(), i))
171                                .size(vec2(99.0, 19.0))
172                                .filter_numbers()
173                                .ui(ui, y);
174
175                            if let (Ok(x), Ok(y)) = (x.parse::<f32>(), y.parse::<f32>()) {
176                                material.set_uniform(name, (x, y));
177                            }
178                        }
179                        Uniform::Float3(x, y, z) => {
180                            widgets::InputText::new(hash!(hash!(), i))
181                                .size(vec2(65.0, 19.0))
182                                .filter_numbers()
183                                .ui(ui, x);
184
185                            ui.same_line(0.0);
186
187                            widgets::InputText::new(hash!(hash!(), i))
188                                .size(vec2(65.0, 19.0))
189                                .filter_numbers()
190                                .ui(ui, y);
191
192                            ui.same_line(0.0);
193
194                            widgets::InputText::new(hash!(hash!(), i))
195                                .size(vec2(65.0, 19.0))
196                                .filter_numbers()
197                                .ui(ui, z);
198
199                            if let (Ok(x), Ok(y), Ok(z)) =
200                                (x.parse::<f32>(), y.parse::<f32>(), z.parse::<f32>())
201                            {
202                                material.set_uniform(name, (x, y, z));
203                            }
204                        }
205
206                        Uniform::Color(color) => {
207                            let mut canvas = ui.canvas();
208
209                            let cursor = canvas.cursor();
210
211                            canvas.rect(
212                                Rect::new(cursor.x + 20.0, cursor.y, 50.0, 18.0),
213                                Color::new(0.2, 0.2, 0.2, 1.0),
214                                Color::new(color.x, color.y, color.z, 1.0),
215                            );
216
217                            if ui.button(None, "change") {
218                                colorpicker_window = true;
219                                color_picking_uniform = Some(name.to_owned());
220                            }
221                            material.set_uniform(name, (color.x, color.y, color.z));
222                        }
223                    }
224                }
225                ui.separator();
226                if ui.button(None, "New uniform") {
227                    new_uniform_window = true;
228                }
229                TreeNode::new(hash!(), "Fragment shader")
230                    .init_unfolded()
231                    .ui(ui, |ui| {
232                        if ui.editbox(hash!(), vec2(440., 200.), &mut fragment_shader) {
233                            need_update = true;
234                        };
235                    });
236                ui.tree_node(hash!(), "Vertex shader", |ui| {
237                    if ui.editbox(hash!(), vec2(440., 300.), &mut vertex_shader) {
238                        need_update = true;
239                    };
240                });
241
242                if let Some(ref error) = error {
243                    Label::new(error).multiline(14.0).ui(ui);
244                }
245            });
246
247        if new_uniform_window {
248            widgets::Window::new(hash!(), vec2(100., 100.), vec2(200., 80.))
249                .label("New uniform")
250                .ui(&mut *root_ui(), |ui| {
251                    if ui.active_window_focused() == false {
252                        new_uniform_window = false;
253                    }
254                    ui.input_text(hash!(), "Name", &mut new_uniform_name);
255                    let uniform_type = ui.combo_box(
256                        hash!(),
257                        "Type",
258                        &["Float1", "Float2", "Float3", "Color"],
259                        None,
260                    );
261
262                    if ui.button(None, "Add") {
263                        if new_uniform_name.is_empty() == false {
264                            let uniform = match uniform_type {
265                                0 => Uniform::Float1("0".to_string()),
266                                1 => Uniform::Float2("0".to_string(), "0".to_string()),
267                                2 => Uniform::Float3(
268                                    "0".to_string(),
269                                    "0".to_string(),
270                                    "0".to_string(),
271                                ),
272                                3 => Uniform::Color(vec3(0.0, 0.0, 0.0)),
273                                _ => unreachable!(),
274                            };
275                            uniforms.push((new_uniform_name.clone(), uniform));
276                            new_uniform_name.clear();
277                            need_update = true;
278                        }
279                        new_uniform_window = false;
280                    }
281
282                    ui.same_line(0.0);
283                    if ui.button(None, "Cancel") {
284                        new_uniform_window = false;
285                    }
286                });
287        }
288
289        if colorpicker_window {
290            colorpicker_window &= widgets::Window::new(hash!(), vec2(140., 100.), vec2(210., 240.))
291                .label("Colorpicker")
292                .ui(&mut *root_ui(), |ui| {
293                    if ui.active_window_focused() == false {
294                        colorpicker_window = false;
295                    }
296
297                    let mut canvas = ui.canvas();
298                    let cursor = canvas.cursor();
299                    let mouse = mouse_position();
300                    let x = mouse.0 as i32 - cursor.x as i32;
301                    let y = mouse.1 as i32 - (cursor.y as i32 + 20);
302
303                    let color = color_picker_image
304                        .get_pixel(x.max(0).min(199) as u32, y.max(0).min(199) as u32);
305
306                    canvas.rect(
307                        Rect::new(cursor.x, cursor.y, 200.0, 18.0),
308                        Color::new(0.0, 0.0, 0.0, 1.0),
309                        Color::new(color.r, color.g, color.b, 1.0),
310                    );
311                    canvas.image(
312                        Rect::new(cursor.x, cursor.y + 20.0, 200.0, 200.0),
313                        &color_picker_texture,
314                    );
315
316                    if x >= 0 && x < 200 && y >= 0 && y < 200 {
317                        canvas.rect(
318                            Rect::new(mouse.0 - 3.5, mouse.1 - 3.5, 7.0, 7.0),
319                            Color::new(0.3, 0.3, 0.3, 1.0),
320                            Color::new(1.0, 1.0, 1.0, 1.0),
321                        );
322
323                        if is_mouse_button_down(MouseButton::Left) {
324                            colorpicker_window = false;
325                            let uniform_name = color_picking_uniform.take().unwrap();
326
327                            uniforms
328                                .iter_mut()
329                                .find(|(name, _)| name == &uniform_name)
330                                .unwrap()
331                                .1 = Uniform::Color(vec3(color.r, color.g, color.b));
332                        }
333                    }
334                });
335        }
336
337        if need_update {
338            let uniforms = uniforms
339                .iter()
340                .map(|(name, uniform)| UniformDesc::new(name, uniform.uniform_type()))
341                .collect::<Vec<_>>();
342
343            match load_material(
344                ShaderSource::Glsl {
345                    vertex: &vertex_shader,
346                    fragment: &fragment_shader,
347                },
348                MaterialParams {
349                    pipeline_params,
350                    uniforms,
351                    textures: vec![],
352                },
353            ) {
354                Ok(new_material) => {
355                    material = new_material;
356                    error = None;
357                }
358                Err(err) => {
359                    error = Some(format!("{err:#?}"));
360                }
361            }
362        }
363
364        next_frame().await
365    }
366}
Source§

impl Ui

Source

pub fn window<F: FnOnce(&mut Ui)>( &mut self, id: Id, position: Vec2, size: Vec2, f: F, ) -> bool

Examples found in repository?
examples/events.rs (lines 9-42)
6async fn main() {
7    loop {
8        clear_background(WHITE);
9        root_ui().window(hash!(), Vec2::new(20., 20.), Vec2::new(450., 200.), |ui| {
10            let (mouse_x, mouse_y) = mouse_position();
11            ui.label(None, &format!("Mouse position: {mouse_x} {mouse_y}"));
12
13            let (mouse_wheel_x, mouse_wheel_y) = mouse_wheel();
14            ui.label(None, &format!("Mouse wheel x: {mouse_wheel_x}"));
15            ui.label(None, &format!("Mouse wheel y: {mouse_wheel_y}"));
16
17            widgets::Group::new(hash!(), Vec2::new(200., 90.))
18                .position(Vec2::new(240., 0.))
19                .ui(ui, |ui| {
20                    ui.label(None, "Pressed kbd keys");
21
22                    if let Some(key) = get_last_key_pressed() {
23                        ui.label(None, &format!("{key:?}"))
24                    }
25                });
26
27            widgets::Group::new(hash!(), Vec2::new(200., 90.))
28                .position(Vec2::new(240., 92.))
29                .ui(ui, |ui| {
30                    ui.label(None, "Pressed mouse keys");
31
32                    if is_mouse_button_down(MouseButton::Left) {
33                        ui.label(None, "Left");
34                    }
35                    if is_mouse_button_down(MouseButton::Right) {
36                        ui.label(None, "Right");
37                    }
38                    if is_mouse_button_down(MouseButton::Middle) {
39                        ui.label(None, "Middle");
40                    }
41                });
42        });
43        next_frame().await;
44    }
45}
More examples
Hide additional examples
examples/ui_skins.rs (lines 247-258)
6async fn main() {
7    let skin1 = {
8        let font = load_ttf_font("examples/ui_assets/HTOWERT.TTF")
9            .await
10            .unwrap();
11        let label_style = root_ui()
12            .style_builder()
13            .with_font(&font)
14            .unwrap()
15            .text_color(Color::from_rgba(180, 180, 120, 255))
16            .font_size(30)
17            .build();
18
19        let window_style = root_ui()
20            .style_builder()
21            .background(
22                Image::from_file_with_format(
23                    include_bytes!("../examples/ui_assets/window_background.png"),
24                    None,
25                )
26                .unwrap(),
27            )
28            .background_margin(RectOffset::new(20.0, 20.0, 10.0, 10.0))
29            .margin(RectOffset::new(-20.0, -30.0, 0.0, 0.0))
30            .build();
31
32        let button_style = root_ui()
33            .style_builder()
34            .background(
35                Image::from_file_with_format(
36                    include_bytes!("../examples/ui_assets/button_background.png"),
37                    None,
38                )
39                .unwrap(),
40            )
41            .background_margin(RectOffset::new(37.0, 37.0, 5.0, 5.0))
42            .margin(RectOffset::new(10.0, 10.0, 0.0, 0.0))
43            .background_hovered(
44                Image::from_file_with_format(
45                    include_bytes!("../examples/ui_assets/button_hovered_background.png"),
46                    None,
47                )
48                .unwrap(),
49            )
50            .background_clicked(
51                Image::from_file_with_format(
52                    include_bytes!("../examples/ui_assets/button_clicked_background.png"),
53                    None,
54                )
55                .unwrap(),
56            )
57            .with_font(&font)
58            .unwrap()
59            .text_color(Color::from_rgba(180, 180, 100, 255))
60            .font_size(40)
61            .build();
62
63        let editbox_style = root_ui()
64            .style_builder()
65            .background_margin(RectOffset::new(0., 0., 0., 0.))
66            .with_font(&font)
67            .unwrap()
68            .text_color(Color::from_rgba(120, 120, 120, 255))
69            .color_selected(Color::from_rgba(190, 190, 190, 255))
70            .font_size(50)
71            .build();
72
73        Skin {
74            editbox_style,
75            window_style,
76            button_style,
77            label_style,
78            ..root_ui().default_skin()
79        }
80    };
81
82    let skin2 = {
83        let font = load_ttf_font("examples/ui_assets/MinimalPixel v2.ttf")
84            .await
85            .unwrap();
86        let label_style = root_ui()
87            .style_builder()
88            .with_font(&font)
89            .unwrap()
90            .text_color(Color::from_rgba(120, 120, 120, 255))
91            .font_size(25)
92            .build();
93
94        let window_style = root_ui()
95            .style_builder()
96            .background(
97                Image::from_file_with_format(
98                    include_bytes!("../examples/ui_assets/window_background_2.png"),
99                    None,
100                )
101                .unwrap(),
102            )
103            .background_margin(RectOffset::new(52.0, 52.0, 52.0, 52.0))
104            .margin(RectOffset::new(-30.0, 0.0, -30.0, 0.0))
105            .build();
106
107        let button_style = root_ui()
108            .style_builder()
109            .background(
110                Image::from_file_with_format(
111                    include_bytes!("../examples/ui_assets/button_background_2.png"),
112                    None,
113                )
114                .unwrap(),
115            )
116            .background_margin(RectOffset::new(8.0, 8.0, 8.0, 8.0))
117            .background_hovered(
118                Image::from_file_with_format(
119                    include_bytes!("../examples/ui_assets/button_hovered_background_2.png"),
120                    None,
121                )
122                .unwrap(),
123            )
124            .background_clicked(
125                Image::from_file_with_format(
126                    include_bytes!("../examples/ui_assets/button_clicked_background_2.png"),
127                    None,
128                )
129                .unwrap(),
130            )
131            .with_font(&font)
132            .unwrap()
133            .text_color(Color::from_rgba(180, 180, 100, 255))
134            .font_size(40)
135            .build();
136
137        let checkbox_style = root_ui()
138            .style_builder()
139            .background(
140                Image::from_file_with_format(
141                    include_bytes!("../examples/ui_assets/checkbox_background.png"),
142                    None,
143                )
144                .unwrap(),
145            )
146            .background_hovered(
147                Image::from_file_with_format(
148                    include_bytes!("../examples/ui_assets/checkbox_hovered_background.png"),
149                    None,
150                )
151                .unwrap(),
152            )
153            .background_clicked(
154                Image::from_file_with_format(
155                    include_bytes!("../examples/ui_assets/checkbox_clicked_background.png"),
156                    None,
157                )
158                .unwrap(),
159            )
160            .build();
161
162        let editbox_style = root_ui()
163            .style_builder()
164            .background(
165                Image::from_file_with_format(
166                    include_bytes!("../examples/ui_assets/editbox_background.png"),
167                    None,
168                )
169                .unwrap(),
170            )
171            .background_margin(RectOffset::new(2., 2., 2., 2.))
172            .with_font(&font)
173            .unwrap()
174            .text_color(Color::from_rgba(120, 120, 120, 255))
175            .font_size(25)
176            .build();
177
178        let combobox_style = root_ui()
179            .style_builder()
180            .background(
181                Image::from_file_with_format(
182                    include_bytes!("../examples/ui_assets/combobox_background.png"),
183                    None,
184                )
185                .unwrap(),
186            )
187            .background_margin(RectOffset::new(4., 25., 6., 6.))
188            .with_font(&font)
189            .unwrap()
190            .text_color(Color::from_rgba(120, 120, 120, 255))
191            .color(Color::from_rgba(210, 210, 210, 255))
192            .font_size(25)
193            .build();
194
195        Skin {
196            window_style,
197            button_style,
198            label_style,
199            checkbox_style,
200            editbox_style,
201            combobox_style,
202            ..root_ui().default_skin()
203        }
204    };
205    let default_skin = root_ui().default_skin().clone();
206
207    let mut window1_skin = skin1.clone();
208    let mut window2_skin = skin2.clone();
209
210    let mut checkbox = false;
211    let mut text = String::new();
212    let mut number = 0.0f32;
213    let mut combobox = 0;
214
215    loop {
216        clear_background(GRAY);
217
218        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
219            ui.label(None, "Window 1");
220
221            if ui.button(None, "Skin 1") {
222                window1_skin = skin1.clone();
223            }
224            if ui.button(None, "Skin 2") {
225                window1_skin = skin2.clone();
226            }
227            if ui.button(None, "No Skin") {
228                window1_skin = default_skin.clone();
229            }
230        });
231        root_ui().same_line(0.);
232        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
233            ui.label(None, "Window 2");
234            if ui.button(None, "Skin 1") {
235                window2_skin = skin1.clone();
236            }
237            if ui.button(None, "Skin 2") {
238                window2_skin = skin2.clone();
239            }
240            if ui.button(None, "No Skin") {
241                window2_skin = default_skin.clone();
242            }
243        });
244
245        root_ui().push_skin(&window1_skin);
246
247        root_ui().window(hash!(), vec2(20., 250.), vec2(300., 300.), |ui| {
248            widgets::Button::new("Play")
249                .position(vec2(65.0, 15.0))
250                .ui(ui);
251            widgets::Button::new("Options")
252                .position(vec2(40.0, 75.0))
253                .ui(ui);
254
255            widgets::Button::new("Quit")
256                .position(vec2(65.0, 195.0))
257                .ui(ui);
258        });
259        root_ui().pop_skin();
260
261        root_ui().push_skin(&window2_skin);
262        root_ui().window(hash!(), vec2(250., 20.), vec2(500., 250.), |ui| {
263            ui.checkbox(hash!(), "Checkbox 1", &mut checkbox);
264            ui.combo_box(
265                hash!(),
266                "Combobox",
267                &["First option", "Second option"],
268                &mut combobox,
269            );
270            ui.input_text(hash!(), "Text", &mut text);
271            ui.drag(hash!(), "Drag", None, &mut number);
272
273            widgets::Button::new("Apply")
274                .position(vec2(80.0, 150.0))
275                .ui(ui);
276            widgets::Button::new("Cancel")
277                .position(vec2(280.0, 150.0))
278                .ui(ui);
279        });
280        root_ui().pop_skin();
281
282        next_frame().await;
283    }
284}
Source§

impl Ui

Source

pub fn new( ctx: &mut dyn RenderingBackend, screen_width: f32, screen_height: f32, ) -> Ui

Source

pub fn set_default_skin(&mut self, _skin: Skin)

Source

pub fn style_builder(&self) -> StyleBuilder

Examples found in repository?
examples/ui_skins.rs (line 12)
6async fn main() {
7    let skin1 = {
8        let font = load_ttf_font("examples/ui_assets/HTOWERT.TTF")
9            .await
10            .unwrap();
11        let label_style = root_ui()
12            .style_builder()
13            .with_font(&font)
14            .unwrap()
15            .text_color(Color::from_rgba(180, 180, 120, 255))
16            .font_size(30)
17            .build();
18
19        let window_style = root_ui()
20            .style_builder()
21            .background(
22                Image::from_file_with_format(
23                    include_bytes!("../examples/ui_assets/window_background.png"),
24                    None,
25                )
26                .unwrap(),
27            )
28            .background_margin(RectOffset::new(20.0, 20.0, 10.0, 10.0))
29            .margin(RectOffset::new(-20.0, -30.0, 0.0, 0.0))
30            .build();
31
32        let button_style = root_ui()
33            .style_builder()
34            .background(
35                Image::from_file_with_format(
36                    include_bytes!("../examples/ui_assets/button_background.png"),
37                    None,
38                )
39                .unwrap(),
40            )
41            .background_margin(RectOffset::new(37.0, 37.0, 5.0, 5.0))
42            .margin(RectOffset::new(10.0, 10.0, 0.0, 0.0))
43            .background_hovered(
44                Image::from_file_with_format(
45                    include_bytes!("../examples/ui_assets/button_hovered_background.png"),
46                    None,
47                )
48                .unwrap(),
49            )
50            .background_clicked(
51                Image::from_file_with_format(
52                    include_bytes!("../examples/ui_assets/button_clicked_background.png"),
53                    None,
54                )
55                .unwrap(),
56            )
57            .with_font(&font)
58            .unwrap()
59            .text_color(Color::from_rgba(180, 180, 100, 255))
60            .font_size(40)
61            .build();
62
63        let editbox_style = root_ui()
64            .style_builder()
65            .background_margin(RectOffset::new(0., 0., 0., 0.))
66            .with_font(&font)
67            .unwrap()
68            .text_color(Color::from_rgba(120, 120, 120, 255))
69            .color_selected(Color::from_rgba(190, 190, 190, 255))
70            .font_size(50)
71            .build();
72
73        Skin {
74            editbox_style,
75            window_style,
76            button_style,
77            label_style,
78            ..root_ui().default_skin()
79        }
80    };
81
82    let skin2 = {
83        let font = load_ttf_font("examples/ui_assets/MinimalPixel v2.ttf")
84            .await
85            .unwrap();
86        let label_style = root_ui()
87            .style_builder()
88            .with_font(&font)
89            .unwrap()
90            .text_color(Color::from_rgba(120, 120, 120, 255))
91            .font_size(25)
92            .build();
93
94        let window_style = root_ui()
95            .style_builder()
96            .background(
97                Image::from_file_with_format(
98                    include_bytes!("../examples/ui_assets/window_background_2.png"),
99                    None,
100                )
101                .unwrap(),
102            )
103            .background_margin(RectOffset::new(52.0, 52.0, 52.0, 52.0))
104            .margin(RectOffset::new(-30.0, 0.0, -30.0, 0.0))
105            .build();
106
107        let button_style = root_ui()
108            .style_builder()
109            .background(
110                Image::from_file_with_format(
111                    include_bytes!("../examples/ui_assets/button_background_2.png"),
112                    None,
113                )
114                .unwrap(),
115            )
116            .background_margin(RectOffset::new(8.0, 8.0, 8.0, 8.0))
117            .background_hovered(
118                Image::from_file_with_format(
119                    include_bytes!("../examples/ui_assets/button_hovered_background_2.png"),
120                    None,
121                )
122                .unwrap(),
123            )
124            .background_clicked(
125                Image::from_file_with_format(
126                    include_bytes!("../examples/ui_assets/button_clicked_background_2.png"),
127                    None,
128                )
129                .unwrap(),
130            )
131            .with_font(&font)
132            .unwrap()
133            .text_color(Color::from_rgba(180, 180, 100, 255))
134            .font_size(40)
135            .build();
136
137        let checkbox_style = root_ui()
138            .style_builder()
139            .background(
140                Image::from_file_with_format(
141                    include_bytes!("../examples/ui_assets/checkbox_background.png"),
142                    None,
143                )
144                .unwrap(),
145            )
146            .background_hovered(
147                Image::from_file_with_format(
148                    include_bytes!("../examples/ui_assets/checkbox_hovered_background.png"),
149                    None,
150                )
151                .unwrap(),
152            )
153            .background_clicked(
154                Image::from_file_with_format(
155                    include_bytes!("../examples/ui_assets/checkbox_clicked_background.png"),
156                    None,
157                )
158                .unwrap(),
159            )
160            .build();
161
162        let editbox_style = root_ui()
163            .style_builder()
164            .background(
165                Image::from_file_with_format(
166                    include_bytes!("../examples/ui_assets/editbox_background.png"),
167                    None,
168                )
169                .unwrap(),
170            )
171            .background_margin(RectOffset::new(2., 2., 2., 2.))
172            .with_font(&font)
173            .unwrap()
174            .text_color(Color::from_rgba(120, 120, 120, 255))
175            .font_size(25)
176            .build();
177
178        let combobox_style = root_ui()
179            .style_builder()
180            .background(
181                Image::from_file_with_format(
182                    include_bytes!("../examples/ui_assets/combobox_background.png"),
183                    None,
184                )
185                .unwrap(),
186            )
187            .background_margin(RectOffset::new(4., 25., 6., 6.))
188            .with_font(&font)
189            .unwrap()
190            .text_color(Color::from_rgba(120, 120, 120, 255))
191            .color(Color::from_rgba(210, 210, 210, 255))
192            .font_size(25)
193            .build();
194
195        Skin {
196            window_style,
197            button_style,
198            label_style,
199            checkbox_style,
200            editbox_style,
201            combobox_style,
202            ..root_ui().default_skin()
203        }
204    };
205    let default_skin = root_ui().default_skin().clone();
206
207    let mut window1_skin = skin1.clone();
208    let mut window2_skin = skin2.clone();
209
210    let mut checkbox = false;
211    let mut text = String::new();
212    let mut number = 0.0f32;
213    let mut combobox = 0;
214
215    loop {
216        clear_background(GRAY);
217
218        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
219            ui.label(None, "Window 1");
220
221            if ui.button(None, "Skin 1") {
222                window1_skin = skin1.clone();
223            }
224            if ui.button(None, "Skin 2") {
225                window1_skin = skin2.clone();
226            }
227            if ui.button(None, "No Skin") {
228                window1_skin = default_skin.clone();
229            }
230        });
231        root_ui().same_line(0.);
232        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
233            ui.label(None, "Window 2");
234            if ui.button(None, "Skin 1") {
235                window2_skin = skin1.clone();
236            }
237            if ui.button(None, "Skin 2") {
238                window2_skin = skin2.clone();
239            }
240            if ui.button(None, "No Skin") {
241                window2_skin = default_skin.clone();
242            }
243        });
244
245        root_ui().push_skin(&window1_skin);
246
247        root_ui().window(hash!(), vec2(20., 250.), vec2(300., 300.), |ui| {
248            widgets::Button::new("Play")
249                .position(vec2(65.0, 15.0))
250                .ui(ui);
251            widgets::Button::new("Options")
252                .position(vec2(40.0, 75.0))
253                .ui(ui);
254
255            widgets::Button::new("Quit")
256                .position(vec2(65.0, 195.0))
257                .ui(ui);
258        });
259        root_ui().pop_skin();
260
261        root_ui().push_skin(&window2_skin);
262        root_ui().window(hash!(), vec2(250., 20.), vec2(500., 250.), |ui| {
263            ui.checkbox(hash!(), "Checkbox 1", &mut checkbox);
264            ui.combo_box(
265                hash!(),
266                "Combobox",
267                &["First option", "Second option"],
268                &mut combobox,
269            );
270            ui.input_text(hash!(), "Text", &mut text);
271            ui.drag(hash!(), "Drag", None, &mut number);
272
273            widgets::Button::new("Apply")
274                .position(vec2(80.0, 150.0))
275                .ui(ui);
276            widgets::Button::new("Cancel")
277                .position(vec2(280.0, 150.0))
278                .ui(ui);
279        });
280        root_ui().pop_skin();
281
282        next_frame().await;
283    }
284}
Source

pub fn default_skin(&self) -> Skin

Examples found in repository?
examples/ui_skins.rs (line 78)
6async fn main() {
7    let skin1 = {
8        let font = load_ttf_font("examples/ui_assets/HTOWERT.TTF")
9            .await
10            .unwrap();
11        let label_style = root_ui()
12            .style_builder()
13            .with_font(&font)
14            .unwrap()
15            .text_color(Color::from_rgba(180, 180, 120, 255))
16            .font_size(30)
17            .build();
18
19        let window_style = root_ui()
20            .style_builder()
21            .background(
22                Image::from_file_with_format(
23                    include_bytes!("../examples/ui_assets/window_background.png"),
24                    None,
25                )
26                .unwrap(),
27            )
28            .background_margin(RectOffset::new(20.0, 20.0, 10.0, 10.0))
29            .margin(RectOffset::new(-20.0, -30.0, 0.0, 0.0))
30            .build();
31
32        let button_style = root_ui()
33            .style_builder()
34            .background(
35                Image::from_file_with_format(
36                    include_bytes!("../examples/ui_assets/button_background.png"),
37                    None,
38                )
39                .unwrap(),
40            )
41            .background_margin(RectOffset::new(37.0, 37.0, 5.0, 5.0))
42            .margin(RectOffset::new(10.0, 10.0, 0.0, 0.0))
43            .background_hovered(
44                Image::from_file_with_format(
45                    include_bytes!("../examples/ui_assets/button_hovered_background.png"),
46                    None,
47                )
48                .unwrap(),
49            )
50            .background_clicked(
51                Image::from_file_with_format(
52                    include_bytes!("../examples/ui_assets/button_clicked_background.png"),
53                    None,
54                )
55                .unwrap(),
56            )
57            .with_font(&font)
58            .unwrap()
59            .text_color(Color::from_rgba(180, 180, 100, 255))
60            .font_size(40)
61            .build();
62
63        let editbox_style = root_ui()
64            .style_builder()
65            .background_margin(RectOffset::new(0., 0., 0., 0.))
66            .with_font(&font)
67            .unwrap()
68            .text_color(Color::from_rgba(120, 120, 120, 255))
69            .color_selected(Color::from_rgba(190, 190, 190, 255))
70            .font_size(50)
71            .build();
72
73        Skin {
74            editbox_style,
75            window_style,
76            button_style,
77            label_style,
78            ..root_ui().default_skin()
79        }
80    };
81
82    let skin2 = {
83        let font = load_ttf_font("examples/ui_assets/MinimalPixel v2.ttf")
84            .await
85            .unwrap();
86        let label_style = root_ui()
87            .style_builder()
88            .with_font(&font)
89            .unwrap()
90            .text_color(Color::from_rgba(120, 120, 120, 255))
91            .font_size(25)
92            .build();
93
94        let window_style = root_ui()
95            .style_builder()
96            .background(
97                Image::from_file_with_format(
98                    include_bytes!("../examples/ui_assets/window_background_2.png"),
99                    None,
100                )
101                .unwrap(),
102            )
103            .background_margin(RectOffset::new(52.0, 52.0, 52.0, 52.0))
104            .margin(RectOffset::new(-30.0, 0.0, -30.0, 0.0))
105            .build();
106
107        let button_style = root_ui()
108            .style_builder()
109            .background(
110                Image::from_file_with_format(
111                    include_bytes!("../examples/ui_assets/button_background_2.png"),
112                    None,
113                )
114                .unwrap(),
115            )
116            .background_margin(RectOffset::new(8.0, 8.0, 8.0, 8.0))
117            .background_hovered(
118                Image::from_file_with_format(
119                    include_bytes!("../examples/ui_assets/button_hovered_background_2.png"),
120                    None,
121                )
122                .unwrap(),
123            )
124            .background_clicked(
125                Image::from_file_with_format(
126                    include_bytes!("../examples/ui_assets/button_clicked_background_2.png"),
127                    None,
128                )
129                .unwrap(),
130            )
131            .with_font(&font)
132            .unwrap()
133            .text_color(Color::from_rgba(180, 180, 100, 255))
134            .font_size(40)
135            .build();
136
137        let checkbox_style = root_ui()
138            .style_builder()
139            .background(
140                Image::from_file_with_format(
141                    include_bytes!("../examples/ui_assets/checkbox_background.png"),
142                    None,
143                )
144                .unwrap(),
145            )
146            .background_hovered(
147                Image::from_file_with_format(
148                    include_bytes!("../examples/ui_assets/checkbox_hovered_background.png"),
149                    None,
150                )
151                .unwrap(),
152            )
153            .background_clicked(
154                Image::from_file_with_format(
155                    include_bytes!("../examples/ui_assets/checkbox_clicked_background.png"),
156                    None,
157                )
158                .unwrap(),
159            )
160            .build();
161
162        let editbox_style = root_ui()
163            .style_builder()
164            .background(
165                Image::from_file_with_format(
166                    include_bytes!("../examples/ui_assets/editbox_background.png"),
167                    None,
168                )
169                .unwrap(),
170            )
171            .background_margin(RectOffset::new(2., 2., 2., 2.))
172            .with_font(&font)
173            .unwrap()
174            .text_color(Color::from_rgba(120, 120, 120, 255))
175            .font_size(25)
176            .build();
177
178        let combobox_style = root_ui()
179            .style_builder()
180            .background(
181                Image::from_file_with_format(
182                    include_bytes!("../examples/ui_assets/combobox_background.png"),
183                    None,
184                )
185                .unwrap(),
186            )
187            .background_margin(RectOffset::new(4., 25., 6., 6.))
188            .with_font(&font)
189            .unwrap()
190            .text_color(Color::from_rgba(120, 120, 120, 255))
191            .color(Color::from_rgba(210, 210, 210, 255))
192            .font_size(25)
193            .build();
194
195        Skin {
196            window_style,
197            button_style,
198            label_style,
199            checkbox_style,
200            editbox_style,
201            combobox_style,
202            ..root_ui().default_skin()
203        }
204    };
205    let default_skin = root_ui().default_skin().clone();
206
207    let mut window1_skin = skin1.clone();
208    let mut window2_skin = skin2.clone();
209
210    let mut checkbox = false;
211    let mut text = String::new();
212    let mut number = 0.0f32;
213    let mut combobox = 0;
214
215    loop {
216        clear_background(GRAY);
217
218        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
219            ui.label(None, "Window 1");
220
221            if ui.button(None, "Skin 1") {
222                window1_skin = skin1.clone();
223            }
224            if ui.button(None, "Skin 2") {
225                window1_skin = skin2.clone();
226            }
227            if ui.button(None, "No Skin") {
228                window1_skin = default_skin.clone();
229            }
230        });
231        root_ui().same_line(0.);
232        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
233            ui.label(None, "Window 2");
234            if ui.button(None, "Skin 1") {
235                window2_skin = skin1.clone();
236            }
237            if ui.button(None, "Skin 2") {
238                window2_skin = skin2.clone();
239            }
240            if ui.button(None, "No Skin") {
241                window2_skin = default_skin.clone();
242            }
243        });
244
245        root_ui().push_skin(&window1_skin);
246
247        root_ui().window(hash!(), vec2(20., 250.), vec2(300., 300.), |ui| {
248            widgets::Button::new("Play")
249                .position(vec2(65.0, 15.0))
250                .ui(ui);
251            widgets::Button::new("Options")
252                .position(vec2(40.0, 75.0))
253                .ui(ui);
254
255            widgets::Button::new("Quit")
256                .position(vec2(65.0, 195.0))
257                .ui(ui);
258        });
259        root_ui().pop_skin();
260
261        root_ui().push_skin(&window2_skin);
262        root_ui().window(hash!(), vec2(250., 20.), vec2(500., 250.), |ui| {
263            ui.checkbox(hash!(), "Checkbox 1", &mut checkbox);
264            ui.combo_box(
265                hash!(),
266                "Combobox",
267                &["First option", "Second option"],
268                &mut combobox,
269            );
270            ui.input_text(hash!(), "Text", &mut text);
271            ui.drag(hash!(), "Drag", None, &mut number);
272
273            widgets::Button::new("Apply")
274                .position(vec2(80.0, 150.0))
275                .ui(ui);
276            widgets::Button::new("Cancel")
277                .position(vec2(280.0, 150.0))
278                .ui(ui);
279        });
280        root_ui().pop_skin();
281
282        next_frame().await;
283    }
284}
Source

pub fn last_item_clicked(&mut self) -> bool

Returns true if the last widget which had .ui called on it is being clicked.

Source

pub fn last_item_hovered(&mut self) -> bool

Returns true if the mouse is over the last widget which had .ui called on it.

Source

pub fn scroll_here(&mut self)

Scrolls the middle of the active GUI window to its GUI cursor

Note that this does not work on the first frame of the GUI application. If you want your widget to start with its scrollbar in a particular location, consider if ui.frame == 1 { ui.scroll_here() }.

Source

pub fn scroll_here_ratio(&mut self, ratio: f32)

Scrolls the active GUI window to its GUI cursor.

1.0 puts the bottom of the window at the GUI cursor, 0.0 puts the top of the window there.

0.5 as the ratio puts the middle of the window at the GUI cursor, and is equivalent to Ui::scroll_here.

Source

pub fn scroll(&mut self) -> Vec2

How far the active gui window has been scrolled down on the y axis.

Note that for these purposes, a Group widget is still considered a Window because it can have its own scrollbar.

Source

pub fn scroll_max(&mut self) -> Vec2

The farthest down a scrollbar may go given the constraints of its window.

Note that for these purposes, a Group widget is still considered a Window because it can have its own scrollbar.

Source

pub const fn is_mouse_captured(&self) -> bool

Source

pub fn is_mouse_over(&self, mouse_position: Vec2) -> bool

Source

pub fn active_window_focused(&self) -> bool

Examples found in repository?
examples/shadertoy.rs (line 251)
47async fn main() {
48    let ferris = load_texture("examples/rust.png").await.unwrap();
49    let (color_picker_texture, color_picker_image) = color_picker_texture(200, 200);
50
51    let mut fragment_shader = DEFAULT_FRAGMENT_SHADER.to_string();
52    let mut vertex_shader = DEFAULT_VERTEX_SHADER.to_string();
53
54    let pipeline_params = PipelineParams {
55        depth_write: true,
56        depth_test: Comparison::LessOrEqual,
57        ..Default::default()
58    };
59
60    let mut material = load_material(
61        ShaderSource::Glsl {
62            vertex: &vertex_shader,
63            fragment: &fragment_shader,
64        },
65        MaterialParams {
66            pipeline_params,
67            ..Default::default()
68        },
69    )
70    .unwrap();
71    let mut error: Option<String> = None;
72
73    enum Mesh {
74        Sphere,
75        Cube,
76        Plane,
77    }
78    let mut mesh = Mesh::Sphere;
79
80    let mut camera = Camera3D {
81        position: vec3(-15., 15., -5.),
82        up: vec3(0., 1., 0.),
83        target: vec3(0., 5., -5.),
84        ..Default::default()
85    };
86
87    let mut colorpicker_window = false;
88    let mut color_picking_uniform = None;
89
90    let mut new_uniform_window = false;
91    let mut new_uniform_name = String::new();
92    let mut uniforms: Vec<(String, Uniform)> = vec![];
93
94    loop {
95        clear_background(WHITE);
96
97        set_camera(&camera);
98
99        draw_grid(
100            20,
101            1.,
102            Color::new(0.55, 0.55, 0.55, 0.75),
103            Color::new(0.75, 0.75, 0.75, 0.75),
104        );
105
106        gl_use_material(&material);
107        match mesh {
108            Mesh::Plane => draw_plane(vec3(0., 2., 0.), vec2(5., 5.), Some(&ferris), WHITE),
109            Mesh::Sphere => draw_sphere(vec3(0., 6., 0.), 5., Some(&ferris), WHITE),
110            Mesh::Cube => draw_cube(vec3(0., 5., 0.), vec3(10., 10., 10.), Some(&ferris), WHITE),
111        }
112        gl_use_default_material();
113
114        set_default_camera();
115
116        let mut need_update = false;
117
118        widgets::Window::new(hash!(), vec2(20., 20.), vec2(470., 650.))
119            .label("Shader")
120            .ui(&mut *root_ui(), |ui| {
121                ui.label(None, "Camera: ");
122                ui.same_line(0.0);
123                if ui.button(None, "Ortho") {
124                    camera.projection = Projection::Orthographics;
125                }
126                ui.same_line(0.0);
127                if ui.button(None, "Perspective") {
128                    camera.projection = Projection::Perspective;
129                }
130                ui.label(None, "Mesh: ");
131                ui.same_line(0.0);
132                if ui.button(None, "Sphere") {
133                    mesh = Mesh::Sphere;
134                }
135                ui.same_line(0.0);
136                if ui.button(None, "Cube") {
137                    mesh = Mesh::Cube;
138                }
139                ui.same_line(0.0);
140                if ui.button(None, "Plane") {
141                    mesh = Mesh::Plane;
142                }
143
144                ui.label(None, "Uniforms:");
145                ui.separator();
146
147                for (i, (name, uniform)) in uniforms.iter_mut().enumerate() {
148                    ui.label(None, &format!("{name}"));
149                    ui.same_line(120.0);
150
151                    match uniform {
152                        Uniform::Float1(x) => {
153                            widgets::InputText::new(hash!(hash!(), i))
154                                .size(vec2(200.0, 19.0))
155                                .filter_numbers()
156                                .ui(ui, x);
157
158                            if let Ok(x) = x.parse::<f32>() {
159                                material.set_uniform(name, x);
160                            }
161                        }
162                        Uniform::Float2(x, y) => {
163                            widgets::InputText::new(hash!(hash!(), i))
164                                .size(vec2(99.0, 19.0))
165                                .filter_numbers()
166                                .ui(ui, x);
167
168                            ui.same_line(0.0);
169
170                            widgets::InputText::new(hash!(hash!(), i))
171                                .size(vec2(99.0, 19.0))
172                                .filter_numbers()
173                                .ui(ui, y);
174
175                            if let (Ok(x), Ok(y)) = (x.parse::<f32>(), y.parse::<f32>()) {
176                                material.set_uniform(name, (x, y));
177                            }
178                        }
179                        Uniform::Float3(x, y, z) => {
180                            widgets::InputText::new(hash!(hash!(), i))
181                                .size(vec2(65.0, 19.0))
182                                .filter_numbers()
183                                .ui(ui, x);
184
185                            ui.same_line(0.0);
186
187                            widgets::InputText::new(hash!(hash!(), i))
188                                .size(vec2(65.0, 19.0))
189                                .filter_numbers()
190                                .ui(ui, y);
191
192                            ui.same_line(0.0);
193
194                            widgets::InputText::new(hash!(hash!(), i))
195                                .size(vec2(65.0, 19.0))
196                                .filter_numbers()
197                                .ui(ui, z);
198
199                            if let (Ok(x), Ok(y), Ok(z)) =
200                                (x.parse::<f32>(), y.parse::<f32>(), z.parse::<f32>())
201                            {
202                                material.set_uniform(name, (x, y, z));
203                            }
204                        }
205
206                        Uniform::Color(color) => {
207                            let mut canvas = ui.canvas();
208
209                            let cursor = canvas.cursor();
210
211                            canvas.rect(
212                                Rect::new(cursor.x + 20.0, cursor.y, 50.0, 18.0),
213                                Color::new(0.2, 0.2, 0.2, 1.0),
214                                Color::new(color.x, color.y, color.z, 1.0),
215                            );
216
217                            if ui.button(None, "change") {
218                                colorpicker_window = true;
219                                color_picking_uniform = Some(name.to_owned());
220                            }
221                            material.set_uniform(name, (color.x, color.y, color.z));
222                        }
223                    }
224                }
225                ui.separator();
226                if ui.button(None, "New uniform") {
227                    new_uniform_window = true;
228                }
229                TreeNode::new(hash!(), "Fragment shader")
230                    .init_unfolded()
231                    .ui(ui, |ui| {
232                        if ui.editbox(hash!(), vec2(440., 200.), &mut fragment_shader) {
233                            need_update = true;
234                        };
235                    });
236                ui.tree_node(hash!(), "Vertex shader", |ui| {
237                    if ui.editbox(hash!(), vec2(440., 300.), &mut vertex_shader) {
238                        need_update = true;
239                    };
240                });
241
242                if let Some(ref error) = error {
243                    Label::new(error).multiline(14.0).ui(ui);
244                }
245            });
246
247        if new_uniform_window {
248            widgets::Window::new(hash!(), vec2(100., 100.), vec2(200., 80.))
249                .label("New uniform")
250                .ui(&mut *root_ui(), |ui| {
251                    if ui.active_window_focused() == false {
252                        new_uniform_window = false;
253                    }
254                    ui.input_text(hash!(), "Name", &mut new_uniform_name);
255                    let uniform_type = ui.combo_box(
256                        hash!(),
257                        "Type",
258                        &["Float1", "Float2", "Float3", "Color"],
259                        None,
260                    );
261
262                    if ui.button(None, "Add") {
263                        if new_uniform_name.is_empty() == false {
264                            let uniform = match uniform_type {
265                                0 => Uniform::Float1("0".to_string()),
266                                1 => Uniform::Float2("0".to_string(), "0".to_string()),
267                                2 => Uniform::Float3(
268                                    "0".to_string(),
269                                    "0".to_string(),
270                                    "0".to_string(),
271                                ),
272                                3 => Uniform::Color(vec3(0.0, 0.0, 0.0)),
273                                _ => unreachable!(),
274                            };
275                            uniforms.push((new_uniform_name.clone(), uniform));
276                            new_uniform_name.clear();
277                            need_update = true;
278                        }
279                        new_uniform_window = false;
280                    }
281
282                    ui.same_line(0.0);
283                    if ui.button(None, "Cancel") {
284                        new_uniform_window = false;
285                    }
286                });
287        }
288
289        if colorpicker_window {
290            colorpicker_window &= widgets::Window::new(hash!(), vec2(140., 100.), vec2(210., 240.))
291                .label("Colorpicker")
292                .ui(&mut *root_ui(), |ui| {
293                    if ui.active_window_focused() == false {
294                        colorpicker_window = false;
295                    }
296
297                    let mut canvas = ui.canvas();
298                    let cursor = canvas.cursor();
299                    let mouse = mouse_position();
300                    let x = mouse.0 as i32 - cursor.x as i32;
301                    let y = mouse.1 as i32 - (cursor.y as i32 + 20);
302
303                    let color = color_picker_image
304                        .get_pixel(x.max(0).min(199) as u32, y.max(0).min(199) as u32);
305
306                    canvas.rect(
307                        Rect::new(cursor.x, cursor.y, 200.0, 18.0),
308                        Color::new(0.0, 0.0, 0.0, 1.0),
309                        Color::new(color.r, color.g, color.b, 1.0),
310                    );
311                    canvas.image(
312                        Rect::new(cursor.x, cursor.y + 20.0, 200.0, 200.0),
313                        &color_picker_texture,
314                    );
315
316                    if x >= 0 && x < 200 && y >= 0 && y < 200 {
317                        canvas.rect(
318                            Rect::new(mouse.0 - 3.5, mouse.1 - 3.5, 7.0, 7.0),
319                            Color::new(0.3, 0.3, 0.3, 1.0),
320                            Color::new(1.0, 1.0, 1.0, 1.0),
321                        );
322
323                        if is_mouse_button_down(MouseButton::Left) {
324                            colorpicker_window = false;
325                            let uniform_name = color_picking_uniform.take().unwrap();
326
327                            uniforms
328                                .iter_mut()
329                                .find(|(name, _)| name == &uniform_name)
330                                .unwrap()
331                                .1 = Uniform::Color(vec3(color.r, color.g, color.b));
332                        }
333                    }
334                });
335        }
336
337        if need_update {
338            let uniforms = uniforms
339                .iter()
340                .map(|(name, uniform)| UniformDesc::new(name, uniform.uniform_type()))
341                .collect::<Vec<_>>();
342
343            match load_material(
344                ShaderSource::Glsl {
345                    vertex: &vertex_shader,
346                    fragment: &fragment_shader,
347                },
348                MaterialParams {
349                    pipeline_params,
350                    uniforms,
351                    textures: vec![],
352                },
353            ) {
354                Ok(new_material) => {
355                    material = new_material;
356                    error = None;
357                }
358                Err(err) => {
359                    error = Some(format!("{err:#?}"));
360                }
361            }
362        }
363
364        next_frame().await
365    }
366}
Source

pub const fn is_dragging(&self) -> bool

Source

pub fn close_current_window(&mut self)

Source

pub fn new_frame(&mut self, delta: f32)

Source

pub fn render(&mut self, draw_list: &mut Vec<DrawList>)

Source

pub fn focus_window(&mut self, id: Id)

Source

pub fn set_input_focus(&mut self, id: Id)

Source

pub fn clear_input_focus(&mut self)

Source

pub fn move_window(&mut self, id: Id, position: Vec2)

Source

pub fn same_line(&mut self, x: f32)

Examples found in repository?
examples/exit_dialog.rs (line 25)
5async fn main() {
6    prevent_quit();
7
8    let mut show_exit_dialog = false;
9    let mut user_decided_to_exit = false;
10
11    loop {
12        clear_background(GRAY);
13
14        if is_quit_requested() {
15            show_exit_dialog = true;
16        }
17
18        if show_exit_dialog {
19            let dialog_size = vec2(200., 70.);
20            let screen_size = vec2(screen_width(), screen_height());
21            let dialog_position = screen_size / 2. - dialog_size / 2.;
22            Window::new(hash!(), dialog_position, dialog_size).ui(&mut *root_ui(), |ui| {
23                ui.label(None, "Do you really want to quit?");
24                ui.separator();
25                ui.same_line(60.);
26                if ui.button(None, "Yes") {
27                    user_decided_to_exit = true;
28                }
29                ui.same_line(120.);
30                if ui.button(None, "No") {
31                    show_exit_dialog = false;
32                }
33            });
34        }
35
36        if user_decided_to_exit {
37            break;
38        }
39
40        next_frame().await
41    }
42}
More examples
Hide additional examples
examples/ui.rs (line 209)
136async fn main() {
137    let mut data = Data::new();
138
139    let mut data0 = String::new();
140    let mut data1 = String::new();
141
142    let mut text0 = String::new();
143    let mut text1 = String::new();
144
145    let mut number0 = 0.;
146    let mut number1 = 0.;
147
148    let texture: Texture2D = load_texture("examples/ferris.png").await.unwrap();
149
150    loop {
151        clear_background(WHITE);
152
153        widgets::Window::new(hash!(), vec2(400., 200.), vec2(320., 400.))
154            .label("Shop")
155            .titlebar(true)
156            .ui(&mut *root_ui(), |ui| {
157                for i in 0..30 {
158                    Group::new(hash!("shop", i), Vec2::new(300., 80.)).ui(ui, |ui| {
159                        ui.label(Vec2::new(10., 10.), &format!("Item N {i}"));
160                        ui.label(Vec2::new(260., 40.), "10/10");
161                        ui.label(Vec2::new(200., 58.), &format!("{} kr", 800));
162                        if ui.button(Vec2::new(260., 55.), "buy") {
163                            data.inventory.push(format!("Item {i}"));
164                        }
165                    });
166                }
167            });
168
169        widgets::Window::new(hash!(), vec2(100., 220.), vec2(542., 430.))
170            .label("Fitting window")
171            .titlebar(true)
172            .ui(&mut *root_ui(), |ui| {
173                Group::new(hash!(), Vec2::new(230., 400.)).ui(ui, |ui| {
174                    data.slots(ui);
175                });
176                Group::new(hash!(), Vec2::new(280., 400.)).ui(ui, |ui| {
177                    data.inventory(ui);
178                });
179            });
180
181        widgets::Window::new(hash!(), vec2(470., 50.), vec2(300., 300.))
182            .label("Megaui Showcase Window")
183            .ui(&mut *root_ui(), |ui| {
184                ui.tree_node(hash!(), "input", |ui| {
185                    ui.label(None, "Some random text");
186                    if ui.button(None, "click me") {
187                        println!("hi");
188                    }
189
190                    ui.separator();
191
192                    ui.label(None, "Some other random text");
193                    if ui.button(None, "other button") {
194                        println!("hi2");
195                    }
196
197                    ui.separator();
198
199                    ui.input_text(hash!(), "<- input text 1", &mut data0);
200                    ui.input_text(hash!(), "<- input text 2", &mut data1);
201                    ui.label(None, &format!("Text entered: \"{data0}\" and \"{data1}\""));
202
203                    ui.separator();
204                });
205                ui.tree_node(hash!(), "buttons", |ui| {
206                    widgets::Button::new(texture.clone())
207                        .size(vec2(120., 70.))
208                        .ui(ui);
209                    ui.same_line(0.);
210                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
211                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
212                    ui.same_line(0.);
213                    widgets::Button::new(texture.clone())
214                        .size(vec2(120., 70.))
215                        .ui(ui);
216                });
217                ui.tree_node(hash!(), "sliders", |ui| {
218                    ui.slider(hash!(), "[-10 .. 10]", -10f32..10f32, &mut number0);
219                    ui.slider(hash!(), "[0 .. 100]", 0f32..100f32, &mut number1);
220                });
221                ui.tree_node(hash!(), "editbox 1", |ui| {
222                    ui.label(None, "This is editbox!");
223                    ui.editbox(hash!(), vec2(285., 165.), &mut text0);
224                });
225                ui.tree_node(hash!(), "editbox 2", |ui| {
226                    ui.label(None, "This is editbox!");
227                    ui.editbox(hash!(), vec2(285., 165.), &mut text1);
228                });
229            });
230
231        match data.fit_command.take() {
232            Some(FittingCommand::Unfit { target_slot }) => data.set_item(target_slot, None),
233            Some(FittingCommand::Fit { target_slot, item }) => {
234                data.set_item(target_slot, Some(item));
235            }
236            Some(FittingCommand::Refit {
237                target_slot,
238                origin_slot,
239            }) => {
240                let origin_item = data
241                    .slots
242                    .iter()
243                    .find_map(|(_, slot)| {
244                        if slot.id == origin_slot {
245                            Some(slot.item.clone())
246                        } else {
247                            None
248                        }
249                    })
250                    .flatten();
251                data.set_item(target_slot, origin_item);
252                data.set_item(origin_slot, None);
253            }
254            None => {}
255        };
256
257        next_frame().await;
258    }
259}
examples/ui_skins.rs (line 231)
6async fn main() {
7    let skin1 = {
8        let font = load_ttf_font("examples/ui_assets/HTOWERT.TTF")
9            .await
10            .unwrap();
11        let label_style = root_ui()
12            .style_builder()
13            .with_font(&font)
14            .unwrap()
15            .text_color(Color::from_rgba(180, 180, 120, 255))
16            .font_size(30)
17            .build();
18
19        let window_style = root_ui()
20            .style_builder()
21            .background(
22                Image::from_file_with_format(
23                    include_bytes!("../examples/ui_assets/window_background.png"),
24                    None,
25                )
26                .unwrap(),
27            )
28            .background_margin(RectOffset::new(20.0, 20.0, 10.0, 10.0))
29            .margin(RectOffset::new(-20.0, -30.0, 0.0, 0.0))
30            .build();
31
32        let button_style = root_ui()
33            .style_builder()
34            .background(
35                Image::from_file_with_format(
36                    include_bytes!("../examples/ui_assets/button_background.png"),
37                    None,
38                )
39                .unwrap(),
40            )
41            .background_margin(RectOffset::new(37.0, 37.0, 5.0, 5.0))
42            .margin(RectOffset::new(10.0, 10.0, 0.0, 0.0))
43            .background_hovered(
44                Image::from_file_with_format(
45                    include_bytes!("../examples/ui_assets/button_hovered_background.png"),
46                    None,
47                )
48                .unwrap(),
49            )
50            .background_clicked(
51                Image::from_file_with_format(
52                    include_bytes!("../examples/ui_assets/button_clicked_background.png"),
53                    None,
54                )
55                .unwrap(),
56            )
57            .with_font(&font)
58            .unwrap()
59            .text_color(Color::from_rgba(180, 180, 100, 255))
60            .font_size(40)
61            .build();
62
63        let editbox_style = root_ui()
64            .style_builder()
65            .background_margin(RectOffset::new(0., 0., 0., 0.))
66            .with_font(&font)
67            .unwrap()
68            .text_color(Color::from_rgba(120, 120, 120, 255))
69            .color_selected(Color::from_rgba(190, 190, 190, 255))
70            .font_size(50)
71            .build();
72
73        Skin {
74            editbox_style,
75            window_style,
76            button_style,
77            label_style,
78            ..root_ui().default_skin()
79        }
80    };
81
82    let skin2 = {
83        let font = load_ttf_font("examples/ui_assets/MinimalPixel v2.ttf")
84            .await
85            .unwrap();
86        let label_style = root_ui()
87            .style_builder()
88            .with_font(&font)
89            .unwrap()
90            .text_color(Color::from_rgba(120, 120, 120, 255))
91            .font_size(25)
92            .build();
93
94        let window_style = root_ui()
95            .style_builder()
96            .background(
97                Image::from_file_with_format(
98                    include_bytes!("../examples/ui_assets/window_background_2.png"),
99                    None,
100                )
101                .unwrap(),
102            )
103            .background_margin(RectOffset::new(52.0, 52.0, 52.0, 52.0))
104            .margin(RectOffset::new(-30.0, 0.0, -30.0, 0.0))
105            .build();
106
107        let button_style = root_ui()
108            .style_builder()
109            .background(
110                Image::from_file_with_format(
111                    include_bytes!("../examples/ui_assets/button_background_2.png"),
112                    None,
113                )
114                .unwrap(),
115            )
116            .background_margin(RectOffset::new(8.0, 8.0, 8.0, 8.0))
117            .background_hovered(
118                Image::from_file_with_format(
119                    include_bytes!("../examples/ui_assets/button_hovered_background_2.png"),
120                    None,
121                )
122                .unwrap(),
123            )
124            .background_clicked(
125                Image::from_file_with_format(
126                    include_bytes!("../examples/ui_assets/button_clicked_background_2.png"),
127                    None,
128                )
129                .unwrap(),
130            )
131            .with_font(&font)
132            .unwrap()
133            .text_color(Color::from_rgba(180, 180, 100, 255))
134            .font_size(40)
135            .build();
136
137        let checkbox_style = root_ui()
138            .style_builder()
139            .background(
140                Image::from_file_with_format(
141                    include_bytes!("../examples/ui_assets/checkbox_background.png"),
142                    None,
143                )
144                .unwrap(),
145            )
146            .background_hovered(
147                Image::from_file_with_format(
148                    include_bytes!("../examples/ui_assets/checkbox_hovered_background.png"),
149                    None,
150                )
151                .unwrap(),
152            )
153            .background_clicked(
154                Image::from_file_with_format(
155                    include_bytes!("../examples/ui_assets/checkbox_clicked_background.png"),
156                    None,
157                )
158                .unwrap(),
159            )
160            .build();
161
162        let editbox_style = root_ui()
163            .style_builder()
164            .background(
165                Image::from_file_with_format(
166                    include_bytes!("../examples/ui_assets/editbox_background.png"),
167                    None,
168                )
169                .unwrap(),
170            )
171            .background_margin(RectOffset::new(2., 2., 2., 2.))
172            .with_font(&font)
173            .unwrap()
174            .text_color(Color::from_rgba(120, 120, 120, 255))
175            .font_size(25)
176            .build();
177
178        let combobox_style = root_ui()
179            .style_builder()
180            .background(
181                Image::from_file_with_format(
182                    include_bytes!("../examples/ui_assets/combobox_background.png"),
183                    None,
184                )
185                .unwrap(),
186            )
187            .background_margin(RectOffset::new(4., 25., 6., 6.))
188            .with_font(&font)
189            .unwrap()
190            .text_color(Color::from_rgba(120, 120, 120, 255))
191            .color(Color::from_rgba(210, 210, 210, 255))
192            .font_size(25)
193            .build();
194
195        Skin {
196            window_style,
197            button_style,
198            label_style,
199            checkbox_style,
200            editbox_style,
201            combobox_style,
202            ..root_ui().default_skin()
203        }
204    };
205    let default_skin = root_ui().default_skin().clone();
206
207    let mut window1_skin = skin1.clone();
208    let mut window2_skin = skin2.clone();
209
210    let mut checkbox = false;
211    let mut text = String::new();
212    let mut number = 0.0f32;
213    let mut combobox = 0;
214
215    loop {
216        clear_background(GRAY);
217
218        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
219            ui.label(None, "Window 1");
220
221            if ui.button(None, "Skin 1") {
222                window1_skin = skin1.clone();
223            }
224            if ui.button(None, "Skin 2") {
225                window1_skin = skin2.clone();
226            }
227            if ui.button(None, "No Skin") {
228                window1_skin = default_skin.clone();
229            }
230        });
231        root_ui().same_line(0.);
232        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
233            ui.label(None, "Window 2");
234            if ui.button(None, "Skin 1") {
235                window2_skin = skin1.clone();
236            }
237            if ui.button(None, "Skin 2") {
238                window2_skin = skin2.clone();
239            }
240            if ui.button(None, "No Skin") {
241                window2_skin = default_skin.clone();
242            }
243        });
244
245        root_ui().push_skin(&window1_skin);
246
247        root_ui().window(hash!(), vec2(20., 250.), vec2(300., 300.), |ui| {
248            widgets::Button::new("Play")
249                .position(vec2(65.0, 15.0))
250                .ui(ui);
251            widgets::Button::new("Options")
252                .position(vec2(40.0, 75.0))
253                .ui(ui);
254
255            widgets::Button::new("Quit")
256                .position(vec2(65.0, 195.0))
257                .ui(ui);
258        });
259        root_ui().pop_skin();
260
261        root_ui().push_skin(&window2_skin);
262        root_ui().window(hash!(), vec2(250., 20.), vec2(500., 250.), |ui| {
263            ui.checkbox(hash!(), "Checkbox 1", &mut checkbox);
264            ui.combo_box(
265                hash!(),
266                "Combobox",
267                &["First option", "Second option"],
268                &mut combobox,
269            );
270            ui.input_text(hash!(), "Text", &mut text);
271            ui.drag(hash!(), "Drag", None, &mut number);
272
273            widgets::Button::new("Apply")
274                .position(vec2(80.0, 150.0))
275                .ui(ui);
276            widgets::Button::new("Cancel")
277                .position(vec2(280.0, 150.0))
278                .ui(ui);
279        });
280        root_ui().pop_skin();
281
282        next_frame().await;
283    }
284}
examples/shadertoy.rs (line 122)
47async fn main() {
48    let ferris = load_texture("examples/rust.png").await.unwrap();
49    let (color_picker_texture, color_picker_image) = color_picker_texture(200, 200);
50
51    let mut fragment_shader = DEFAULT_FRAGMENT_SHADER.to_string();
52    let mut vertex_shader = DEFAULT_VERTEX_SHADER.to_string();
53
54    let pipeline_params = PipelineParams {
55        depth_write: true,
56        depth_test: Comparison::LessOrEqual,
57        ..Default::default()
58    };
59
60    let mut material = load_material(
61        ShaderSource::Glsl {
62            vertex: &vertex_shader,
63            fragment: &fragment_shader,
64        },
65        MaterialParams {
66            pipeline_params,
67            ..Default::default()
68        },
69    )
70    .unwrap();
71    let mut error: Option<String> = None;
72
73    enum Mesh {
74        Sphere,
75        Cube,
76        Plane,
77    }
78    let mut mesh = Mesh::Sphere;
79
80    let mut camera = Camera3D {
81        position: vec3(-15., 15., -5.),
82        up: vec3(0., 1., 0.),
83        target: vec3(0., 5., -5.),
84        ..Default::default()
85    };
86
87    let mut colorpicker_window = false;
88    let mut color_picking_uniform = None;
89
90    let mut new_uniform_window = false;
91    let mut new_uniform_name = String::new();
92    let mut uniforms: Vec<(String, Uniform)> = vec![];
93
94    loop {
95        clear_background(WHITE);
96
97        set_camera(&camera);
98
99        draw_grid(
100            20,
101            1.,
102            Color::new(0.55, 0.55, 0.55, 0.75),
103            Color::new(0.75, 0.75, 0.75, 0.75),
104        );
105
106        gl_use_material(&material);
107        match mesh {
108            Mesh::Plane => draw_plane(vec3(0., 2., 0.), vec2(5., 5.), Some(&ferris), WHITE),
109            Mesh::Sphere => draw_sphere(vec3(0., 6., 0.), 5., Some(&ferris), WHITE),
110            Mesh::Cube => draw_cube(vec3(0., 5., 0.), vec3(10., 10., 10.), Some(&ferris), WHITE),
111        }
112        gl_use_default_material();
113
114        set_default_camera();
115
116        let mut need_update = false;
117
118        widgets::Window::new(hash!(), vec2(20., 20.), vec2(470., 650.))
119            .label("Shader")
120            .ui(&mut *root_ui(), |ui| {
121                ui.label(None, "Camera: ");
122                ui.same_line(0.0);
123                if ui.button(None, "Ortho") {
124                    camera.projection = Projection::Orthographics;
125                }
126                ui.same_line(0.0);
127                if ui.button(None, "Perspective") {
128                    camera.projection = Projection::Perspective;
129                }
130                ui.label(None, "Mesh: ");
131                ui.same_line(0.0);
132                if ui.button(None, "Sphere") {
133                    mesh = Mesh::Sphere;
134                }
135                ui.same_line(0.0);
136                if ui.button(None, "Cube") {
137                    mesh = Mesh::Cube;
138                }
139                ui.same_line(0.0);
140                if ui.button(None, "Plane") {
141                    mesh = Mesh::Plane;
142                }
143
144                ui.label(None, "Uniforms:");
145                ui.separator();
146
147                for (i, (name, uniform)) in uniforms.iter_mut().enumerate() {
148                    ui.label(None, &format!("{name}"));
149                    ui.same_line(120.0);
150
151                    match uniform {
152                        Uniform::Float1(x) => {
153                            widgets::InputText::new(hash!(hash!(), i))
154                                .size(vec2(200.0, 19.0))
155                                .filter_numbers()
156                                .ui(ui, x);
157
158                            if let Ok(x) = x.parse::<f32>() {
159                                material.set_uniform(name, x);
160                            }
161                        }
162                        Uniform::Float2(x, y) => {
163                            widgets::InputText::new(hash!(hash!(), i))
164                                .size(vec2(99.0, 19.0))
165                                .filter_numbers()
166                                .ui(ui, x);
167
168                            ui.same_line(0.0);
169
170                            widgets::InputText::new(hash!(hash!(), i))
171                                .size(vec2(99.0, 19.0))
172                                .filter_numbers()
173                                .ui(ui, y);
174
175                            if let (Ok(x), Ok(y)) = (x.parse::<f32>(), y.parse::<f32>()) {
176                                material.set_uniform(name, (x, y));
177                            }
178                        }
179                        Uniform::Float3(x, y, z) => {
180                            widgets::InputText::new(hash!(hash!(), i))
181                                .size(vec2(65.0, 19.0))
182                                .filter_numbers()
183                                .ui(ui, x);
184
185                            ui.same_line(0.0);
186
187                            widgets::InputText::new(hash!(hash!(), i))
188                                .size(vec2(65.0, 19.0))
189                                .filter_numbers()
190                                .ui(ui, y);
191
192                            ui.same_line(0.0);
193
194                            widgets::InputText::new(hash!(hash!(), i))
195                                .size(vec2(65.0, 19.0))
196                                .filter_numbers()
197                                .ui(ui, z);
198
199                            if let (Ok(x), Ok(y), Ok(z)) =
200                                (x.parse::<f32>(), y.parse::<f32>(), z.parse::<f32>())
201                            {
202                                material.set_uniform(name, (x, y, z));
203                            }
204                        }
205
206                        Uniform::Color(color) => {
207                            let mut canvas = ui.canvas();
208
209                            let cursor = canvas.cursor();
210
211                            canvas.rect(
212                                Rect::new(cursor.x + 20.0, cursor.y, 50.0, 18.0),
213                                Color::new(0.2, 0.2, 0.2, 1.0),
214                                Color::new(color.x, color.y, color.z, 1.0),
215                            );
216
217                            if ui.button(None, "change") {
218                                colorpicker_window = true;
219                                color_picking_uniform = Some(name.to_owned());
220                            }
221                            material.set_uniform(name, (color.x, color.y, color.z));
222                        }
223                    }
224                }
225                ui.separator();
226                if ui.button(None, "New uniform") {
227                    new_uniform_window = true;
228                }
229                TreeNode::new(hash!(), "Fragment shader")
230                    .init_unfolded()
231                    .ui(ui, |ui| {
232                        if ui.editbox(hash!(), vec2(440., 200.), &mut fragment_shader) {
233                            need_update = true;
234                        };
235                    });
236                ui.tree_node(hash!(), "Vertex shader", |ui| {
237                    if ui.editbox(hash!(), vec2(440., 300.), &mut vertex_shader) {
238                        need_update = true;
239                    };
240                });
241
242                if let Some(ref error) = error {
243                    Label::new(error).multiline(14.0).ui(ui);
244                }
245            });
246
247        if new_uniform_window {
248            widgets::Window::new(hash!(), vec2(100., 100.), vec2(200., 80.))
249                .label("New uniform")
250                .ui(&mut *root_ui(), |ui| {
251                    if ui.active_window_focused() == false {
252                        new_uniform_window = false;
253                    }
254                    ui.input_text(hash!(), "Name", &mut new_uniform_name);
255                    let uniform_type = ui.combo_box(
256                        hash!(),
257                        "Type",
258                        &["Float1", "Float2", "Float3", "Color"],
259                        None,
260                    );
261
262                    if ui.button(None, "Add") {
263                        if new_uniform_name.is_empty() == false {
264                            let uniform = match uniform_type {
265                                0 => Uniform::Float1("0".to_string()),
266                                1 => Uniform::Float2("0".to_string(), "0".to_string()),
267                                2 => Uniform::Float3(
268                                    "0".to_string(),
269                                    "0".to_string(),
270                                    "0".to_string(),
271                                ),
272                                3 => Uniform::Color(vec3(0.0, 0.0, 0.0)),
273                                _ => unreachable!(),
274                            };
275                            uniforms.push((new_uniform_name.clone(), uniform));
276                            new_uniform_name.clear();
277                            need_update = true;
278                        }
279                        new_uniform_window = false;
280                    }
281
282                    ui.same_line(0.0);
283                    if ui.button(None, "Cancel") {
284                        new_uniform_window = false;
285                    }
286                });
287        }
288
289        if colorpicker_window {
290            colorpicker_window &= widgets::Window::new(hash!(), vec2(140., 100.), vec2(210., 240.))
291                .label("Colorpicker")
292                .ui(&mut *root_ui(), |ui| {
293                    if ui.active_window_focused() == false {
294                        colorpicker_window = false;
295                    }
296
297                    let mut canvas = ui.canvas();
298                    let cursor = canvas.cursor();
299                    let mouse = mouse_position();
300                    let x = mouse.0 as i32 - cursor.x as i32;
301                    let y = mouse.1 as i32 - (cursor.y as i32 + 20);
302
303                    let color = color_picker_image
304                        .get_pixel(x.max(0).min(199) as u32, y.max(0).min(199) as u32);
305
306                    canvas.rect(
307                        Rect::new(cursor.x, cursor.y, 200.0, 18.0),
308                        Color::new(0.0, 0.0, 0.0, 1.0),
309                        Color::new(color.r, color.g, color.b, 1.0),
310                    );
311                    canvas.image(
312                        Rect::new(cursor.x, cursor.y + 20.0, 200.0, 200.0),
313                        &color_picker_texture,
314                    );
315
316                    if x >= 0 && x < 200 && y >= 0 && y < 200 {
317                        canvas.rect(
318                            Rect::new(mouse.0 - 3.5, mouse.1 - 3.5, 7.0, 7.0),
319                            Color::new(0.3, 0.3, 0.3, 1.0),
320                            Color::new(1.0, 1.0, 1.0, 1.0),
321                        );
322
323                        if is_mouse_button_down(MouseButton::Left) {
324                            colorpicker_window = false;
325                            let uniform_name = color_picking_uniform.take().unwrap();
326
327                            uniforms
328                                .iter_mut()
329                                .find(|(name, _)| name == &uniform_name)
330                                .unwrap()
331                                .1 = Uniform::Color(vec3(color.r, color.g, color.b));
332                        }
333                    }
334                });
335        }
336
337        if need_update {
338            let uniforms = uniforms
339                .iter()
340                .map(|(name, uniform)| UniformDesc::new(name, uniform.uniform_type()))
341                .collect::<Vec<_>>();
342
343            match load_material(
344                ShaderSource::Glsl {
345                    vertex: &vertex_shader,
346                    fragment: &fragment_shader,
347                },
348                MaterialParams {
349                    pipeline_params,
350                    uniforms,
351                    textures: vec![],
352                },
353            ) {
354                Ok(new_material) => {
355                    material = new_material;
356                    error = None;
357                }
358                Err(err) => {
359                    error = Some(format!("{err:#?}"));
360                }
361            }
362        }
363
364        next_frame().await
365    }
366}
Source

pub fn canvas(&mut self) -> DrawCanvas<'_>

Examples found in repository?
examples/shadertoy.rs (line 207)
47async fn main() {
48    let ferris = load_texture("examples/rust.png").await.unwrap();
49    let (color_picker_texture, color_picker_image) = color_picker_texture(200, 200);
50
51    let mut fragment_shader = DEFAULT_FRAGMENT_SHADER.to_string();
52    let mut vertex_shader = DEFAULT_VERTEX_SHADER.to_string();
53
54    let pipeline_params = PipelineParams {
55        depth_write: true,
56        depth_test: Comparison::LessOrEqual,
57        ..Default::default()
58    };
59
60    let mut material = load_material(
61        ShaderSource::Glsl {
62            vertex: &vertex_shader,
63            fragment: &fragment_shader,
64        },
65        MaterialParams {
66            pipeline_params,
67            ..Default::default()
68        },
69    )
70    .unwrap();
71    let mut error: Option<String> = None;
72
73    enum Mesh {
74        Sphere,
75        Cube,
76        Plane,
77    }
78    let mut mesh = Mesh::Sphere;
79
80    let mut camera = Camera3D {
81        position: vec3(-15., 15., -5.),
82        up: vec3(0., 1., 0.),
83        target: vec3(0., 5., -5.),
84        ..Default::default()
85    };
86
87    let mut colorpicker_window = false;
88    let mut color_picking_uniform = None;
89
90    let mut new_uniform_window = false;
91    let mut new_uniform_name = String::new();
92    let mut uniforms: Vec<(String, Uniform)> = vec![];
93
94    loop {
95        clear_background(WHITE);
96
97        set_camera(&camera);
98
99        draw_grid(
100            20,
101            1.,
102            Color::new(0.55, 0.55, 0.55, 0.75),
103            Color::new(0.75, 0.75, 0.75, 0.75),
104        );
105
106        gl_use_material(&material);
107        match mesh {
108            Mesh::Plane => draw_plane(vec3(0., 2., 0.), vec2(5., 5.), Some(&ferris), WHITE),
109            Mesh::Sphere => draw_sphere(vec3(0., 6., 0.), 5., Some(&ferris), WHITE),
110            Mesh::Cube => draw_cube(vec3(0., 5., 0.), vec3(10., 10., 10.), Some(&ferris), WHITE),
111        }
112        gl_use_default_material();
113
114        set_default_camera();
115
116        let mut need_update = false;
117
118        widgets::Window::new(hash!(), vec2(20., 20.), vec2(470., 650.))
119            .label("Shader")
120            .ui(&mut *root_ui(), |ui| {
121                ui.label(None, "Camera: ");
122                ui.same_line(0.0);
123                if ui.button(None, "Ortho") {
124                    camera.projection = Projection::Orthographics;
125                }
126                ui.same_line(0.0);
127                if ui.button(None, "Perspective") {
128                    camera.projection = Projection::Perspective;
129                }
130                ui.label(None, "Mesh: ");
131                ui.same_line(0.0);
132                if ui.button(None, "Sphere") {
133                    mesh = Mesh::Sphere;
134                }
135                ui.same_line(0.0);
136                if ui.button(None, "Cube") {
137                    mesh = Mesh::Cube;
138                }
139                ui.same_line(0.0);
140                if ui.button(None, "Plane") {
141                    mesh = Mesh::Plane;
142                }
143
144                ui.label(None, "Uniforms:");
145                ui.separator();
146
147                for (i, (name, uniform)) in uniforms.iter_mut().enumerate() {
148                    ui.label(None, &format!("{name}"));
149                    ui.same_line(120.0);
150
151                    match uniform {
152                        Uniform::Float1(x) => {
153                            widgets::InputText::new(hash!(hash!(), i))
154                                .size(vec2(200.0, 19.0))
155                                .filter_numbers()
156                                .ui(ui, x);
157
158                            if let Ok(x) = x.parse::<f32>() {
159                                material.set_uniform(name, x);
160                            }
161                        }
162                        Uniform::Float2(x, y) => {
163                            widgets::InputText::new(hash!(hash!(), i))
164                                .size(vec2(99.0, 19.0))
165                                .filter_numbers()
166                                .ui(ui, x);
167
168                            ui.same_line(0.0);
169
170                            widgets::InputText::new(hash!(hash!(), i))
171                                .size(vec2(99.0, 19.0))
172                                .filter_numbers()
173                                .ui(ui, y);
174
175                            if let (Ok(x), Ok(y)) = (x.parse::<f32>(), y.parse::<f32>()) {
176                                material.set_uniform(name, (x, y));
177                            }
178                        }
179                        Uniform::Float3(x, y, z) => {
180                            widgets::InputText::new(hash!(hash!(), i))
181                                .size(vec2(65.0, 19.0))
182                                .filter_numbers()
183                                .ui(ui, x);
184
185                            ui.same_line(0.0);
186
187                            widgets::InputText::new(hash!(hash!(), i))
188                                .size(vec2(65.0, 19.0))
189                                .filter_numbers()
190                                .ui(ui, y);
191
192                            ui.same_line(0.0);
193
194                            widgets::InputText::new(hash!(hash!(), i))
195                                .size(vec2(65.0, 19.0))
196                                .filter_numbers()
197                                .ui(ui, z);
198
199                            if let (Ok(x), Ok(y), Ok(z)) =
200                                (x.parse::<f32>(), y.parse::<f32>(), z.parse::<f32>())
201                            {
202                                material.set_uniform(name, (x, y, z));
203                            }
204                        }
205
206                        Uniform::Color(color) => {
207                            let mut canvas = ui.canvas();
208
209                            let cursor = canvas.cursor();
210
211                            canvas.rect(
212                                Rect::new(cursor.x + 20.0, cursor.y, 50.0, 18.0),
213                                Color::new(0.2, 0.2, 0.2, 1.0),
214                                Color::new(color.x, color.y, color.z, 1.0),
215                            );
216
217                            if ui.button(None, "change") {
218                                colorpicker_window = true;
219                                color_picking_uniform = Some(name.to_owned());
220                            }
221                            material.set_uniform(name, (color.x, color.y, color.z));
222                        }
223                    }
224                }
225                ui.separator();
226                if ui.button(None, "New uniform") {
227                    new_uniform_window = true;
228                }
229                TreeNode::new(hash!(), "Fragment shader")
230                    .init_unfolded()
231                    .ui(ui, |ui| {
232                        if ui.editbox(hash!(), vec2(440., 200.), &mut fragment_shader) {
233                            need_update = true;
234                        };
235                    });
236                ui.tree_node(hash!(), "Vertex shader", |ui| {
237                    if ui.editbox(hash!(), vec2(440., 300.), &mut vertex_shader) {
238                        need_update = true;
239                    };
240                });
241
242                if let Some(ref error) = error {
243                    Label::new(error).multiline(14.0).ui(ui);
244                }
245            });
246
247        if new_uniform_window {
248            widgets::Window::new(hash!(), vec2(100., 100.), vec2(200., 80.))
249                .label("New uniform")
250                .ui(&mut *root_ui(), |ui| {
251                    if ui.active_window_focused() == false {
252                        new_uniform_window = false;
253                    }
254                    ui.input_text(hash!(), "Name", &mut new_uniform_name);
255                    let uniform_type = ui.combo_box(
256                        hash!(),
257                        "Type",
258                        &["Float1", "Float2", "Float3", "Color"],
259                        None,
260                    );
261
262                    if ui.button(None, "Add") {
263                        if new_uniform_name.is_empty() == false {
264                            let uniform = match uniform_type {
265                                0 => Uniform::Float1("0".to_string()),
266                                1 => Uniform::Float2("0".to_string(), "0".to_string()),
267                                2 => Uniform::Float3(
268                                    "0".to_string(),
269                                    "0".to_string(),
270                                    "0".to_string(),
271                                ),
272                                3 => Uniform::Color(vec3(0.0, 0.0, 0.0)),
273                                _ => unreachable!(),
274                            };
275                            uniforms.push((new_uniform_name.clone(), uniform));
276                            new_uniform_name.clear();
277                            need_update = true;
278                        }
279                        new_uniform_window = false;
280                    }
281
282                    ui.same_line(0.0);
283                    if ui.button(None, "Cancel") {
284                        new_uniform_window = false;
285                    }
286                });
287        }
288
289        if colorpicker_window {
290            colorpicker_window &= widgets::Window::new(hash!(), vec2(140., 100.), vec2(210., 240.))
291                .label("Colorpicker")
292                .ui(&mut *root_ui(), |ui| {
293                    if ui.active_window_focused() == false {
294                        colorpicker_window = false;
295                    }
296
297                    let mut canvas = ui.canvas();
298                    let cursor = canvas.cursor();
299                    let mouse = mouse_position();
300                    let x = mouse.0 as i32 - cursor.x as i32;
301                    let y = mouse.1 as i32 - (cursor.y as i32 + 20);
302
303                    let color = color_picker_image
304                        .get_pixel(x.max(0).min(199) as u32, y.max(0).min(199) as u32);
305
306                    canvas.rect(
307                        Rect::new(cursor.x, cursor.y, 200.0, 18.0),
308                        Color::new(0.0, 0.0, 0.0, 1.0),
309                        Color::new(color.r, color.g, color.b, 1.0),
310                    );
311                    canvas.image(
312                        Rect::new(cursor.x, cursor.y + 20.0, 200.0, 200.0),
313                        &color_picker_texture,
314                    );
315
316                    if x >= 0 && x < 200 && y >= 0 && y < 200 {
317                        canvas.rect(
318                            Rect::new(mouse.0 - 3.5, mouse.1 - 3.5, 7.0, 7.0),
319                            Color::new(0.3, 0.3, 0.3, 1.0),
320                            Color::new(1.0, 1.0, 1.0, 1.0),
321                        );
322
323                        if is_mouse_button_down(MouseButton::Left) {
324                            colorpicker_window = false;
325                            let uniform_name = color_picking_uniform.take().unwrap();
326
327                            uniforms
328                                .iter_mut()
329                                .find(|(name, _)| name == &uniform_name)
330                                .unwrap()
331                                .1 = Uniform::Color(vec3(color.r, color.g, color.b));
332                        }
333                    }
334                });
335        }
336
337        if need_update {
338            let uniforms = uniforms
339                .iter()
340                .map(|(name, uniform)| UniformDesc::new(name, uniform.uniform_type()))
341                .collect::<Vec<_>>();
342
343            match load_material(
344                ShaderSource::Glsl {
345                    vertex: &vertex_shader,
346                    fragment: &fragment_shader,
347                },
348                MaterialParams {
349                    pipeline_params,
350                    uniforms,
351                    textures: vec![],
352                },
353            ) {
354                Ok(new_material) => {
355                    material = new_material;
356                    error = None;
357                }
358                Err(err) => {
359                    error = Some(format!("{err:#?}"));
360                }
361            }
362        }
363
364        next_frame().await
365    }
366}
Source

pub fn get_bool(&mut self, id: Id) -> &mut bool

small hack to keep some internal state used like this:

if ui.last_item_clicked() {
    *ui.get_bool(hash!("color picker opened")) ^= true;
}
if *ui.get_bool(hash!("color picker opened"))  {
}
Source

pub fn get_any<T: Any + Default>(&mut self, id: Id) -> &mut T

Source

pub fn push_skin(&mut self, skin: &Skin)

Examples found in repository?
examples/ui_skins.rs (line 245)
6async fn main() {
7    let skin1 = {
8        let font = load_ttf_font("examples/ui_assets/HTOWERT.TTF")
9            .await
10            .unwrap();
11        let label_style = root_ui()
12            .style_builder()
13            .with_font(&font)
14            .unwrap()
15            .text_color(Color::from_rgba(180, 180, 120, 255))
16            .font_size(30)
17            .build();
18
19        let window_style = root_ui()
20            .style_builder()
21            .background(
22                Image::from_file_with_format(
23                    include_bytes!("../examples/ui_assets/window_background.png"),
24                    None,
25                )
26                .unwrap(),
27            )
28            .background_margin(RectOffset::new(20.0, 20.0, 10.0, 10.0))
29            .margin(RectOffset::new(-20.0, -30.0, 0.0, 0.0))
30            .build();
31
32        let button_style = root_ui()
33            .style_builder()
34            .background(
35                Image::from_file_with_format(
36                    include_bytes!("../examples/ui_assets/button_background.png"),
37                    None,
38                )
39                .unwrap(),
40            )
41            .background_margin(RectOffset::new(37.0, 37.0, 5.0, 5.0))
42            .margin(RectOffset::new(10.0, 10.0, 0.0, 0.0))
43            .background_hovered(
44                Image::from_file_with_format(
45                    include_bytes!("../examples/ui_assets/button_hovered_background.png"),
46                    None,
47                )
48                .unwrap(),
49            )
50            .background_clicked(
51                Image::from_file_with_format(
52                    include_bytes!("../examples/ui_assets/button_clicked_background.png"),
53                    None,
54                )
55                .unwrap(),
56            )
57            .with_font(&font)
58            .unwrap()
59            .text_color(Color::from_rgba(180, 180, 100, 255))
60            .font_size(40)
61            .build();
62
63        let editbox_style = root_ui()
64            .style_builder()
65            .background_margin(RectOffset::new(0., 0., 0., 0.))
66            .with_font(&font)
67            .unwrap()
68            .text_color(Color::from_rgba(120, 120, 120, 255))
69            .color_selected(Color::from_rgba(190, 190, 190, 255))
70            .font_size(50)
71            .build();
72
73        Skin {
74            editbox_style,
75            window_style,
76            button_style,
77            label_style,
78            ..root_ui().default_skin()
79        }
80    };
81
82    let skin2 = {
83        let font = load_ttf_font("examples/ui_assets/MinimalPixel v2.ttf")
84            .await
85            .unwrap();
86        let label_style = root_ui()
87            .style_builder()
88            .with_font(&font)
89            .unwrap()
90            .text_color(Color::from_rgba(120, 120, 120, 255))
91            .font_size(25)
92            .build();
93
94        let window_style = root_ui()
95            .style_builder()
96            .background(
97                Image::from_file_with_format(
98                    include_bytes!("../examples/ui_assets/window_background_2.png"),
99                    None,
100                )
101                .unwrap(),
102            )
103            .background_margin(RectOffset::new(52.0, 52.0, 52.0, 52.0))
104            .margin(RectOffset::new(-30.0, 0.0, -30.0, 0.0))
105            .build();
106
107        let button_style = root_ui()
108            .style_builder()
109            .background(
110                Image::from_file_with_format(
111                    include_bytes!("../examples/ui_assets/button_background_2.png"),
112                    None,
113                )
114                .unwrap(),
115            )
116            .background_margin(RectOffset::new(8.0, 8.0, 8.0, 8.0))
117            .background_hovered(
118                Image::from_file_with_format(
119                    include_bytes!("../examples/ui_assets/button_hovered_background_2.png"),
120                    None,
121                )
122                .unwrap(),
123            )
124            .background_clicked(
125                Image::from_file_with_format(
126                    include_bytes!("../examples/ui_assets/button_clicked_background_2.png"),
127                    None,
128                )
129                .unwrap(),
130            )
131            .with_font(&font)
132            .unwrap()
133            .text_color(Color::from_rgba(180, 180, 100, 255))
134            .font_size(40)
135            .build();
136
137        let checkbox_style = root_ui()
138            .style_builder()
139            .background(
140                Image::from_file_with_format(
141                    include_bytes!("../examples/ui_assets/checkbox_background.png"),
142                    None,
143                )
144                .unwrap(),
145            )
146            .background_hovered(
147                Image::from_file_with_format(
148                    include_bytes!("../examples/ui_assets/checkbox_hovered_background.png"),
149                    None,
150                )
151                .unwrap(),
152            )
153            .background_clicked(
154                Image::from_file_with_format(
155                    include_bytes!("../examples/ui_assets/checkbox_clicked_background.png"),
156                    None,
157                )
158                .unwrap(),
159            )
160            .build();
161
162        let editbox_style = root_ui()
163            .style_builder()
164            .background(
165                Image::from_file_with_format(
166                    include_bytes!("../examples/ui_assets/editbox_background.png"),
167                    None,
168                )
169                .unwrap(),
170            )
171            .background_margin(RectOffset::new(2., 2., 2., 2.))
172            .with_font(&font)
173            .unwrap()
174            .text_color(Color::from_rgba(120, 120, 120, 255))
175            .font_size(25)
176            .build();
177
178        let combobox_style = root_ui()
179            .style_builder()
180            .background(
181                Image::from_file_with_format(
182                    include_bytes!("../examples/ui_assets/combobox_background.png"),
183                    None,
184                )
185                .unwrap(),
186            )
187            .background_margin(RectOffset::new(4., 25., 6., 6.))
188            .with_font(&font)
189            .unwrap()
190            .text_color(Color::from_rgba(120, 120, 120, 255))
191            .color(Color::from_rgba(210, 210, 210, 255))
192            .font_size(25)
193            .build();
194
195        Skin {
196            window_style,
197            button_style,
198            label_style,
199            checkbox_style,
200            editbox_style,
201            combobox_style,
202            ..root_ui().default_skin()
203        }
204    };
205    let default_skin = root_ui().default_skin().clone();
206
207    let mut window1_skin = skin1.clone();
208    let mut window2_skin = skin2.clone();
209
210    let mut checkbox = false;
211    let mut text = String::new();
212    let mut number = 0.0f32;
213    let mut combobox = 0;
214
215    loop {
216        clear_background(GRAY);
217
218        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
219            ui.label(None, "Window 1");
220
221            if ui.button(None, "Skin 1") {
222                window1_skin = skin1.clone();
223            }
224            if ui.button(None, "Skin 2") {
225                window1_skin = skin2.clone();
226            }
227            if ui.button(None, "No Skin") {
228                window1_skin = default_skin.clone();
229            }
230        });
231        root_ui().same_line(0.);
232        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
233            ui.label(None, "Window 2");
234            if ui.button(None, "Skin 1") {
235                window2_skin = skin1.clone();
236            }
237            if ui.button(None, "Skin 2") {
238                window2_skin = skin2.clone();
239            }
240            if ui.button(None, "No Skin") {
241                window2_skin = default_skin.clone();
242            }
243        });
244
245        root_ui().push_skin(&window1_skin);
246
247        root_ui().window(hash!(), vec2(20., 250.), vec2(300., 300.), |ui| {
248            widgets::Button::new("Play")
249                .position(vec2(65.0, 15.0))
250                .ui(ui);
251            widgets::Button::new("Options")
252                .position(vec2(40.0, 75.0))
253                .ui(ui);
254
255            widgets::Button::new("Quit")
256                .position(vec2(65.0, 195.0))
257                .ui(ui);
258        });
259        root_ui().pop_skin();
260
261        root_ui().push_skin(&window2_skin);
262        root_ui().window(hash!(), vec2(250., 20.), vec2(500., 250.), |ui| {
263            ui.checkbox(hash!(), "Checkbox 1", &mut checkbox);
264            ui.combo_box(
265                hash!(),
266                "Combobox",
267                &["First option", "Second option"],
268                &mut combobox,
269            );
270            ui.input_text(hash!(), "Text", &mut text);
271            ui.drag(hash!(), "Drag", None, &mut number);
272
273            widgets::Button::new("Apply")
274                .position(vec2(80.0, 150.0))
275                .ui(ui);
276            widgets::Button::new("Cancel")
277                .position(vec2(280.0, 150.0))
278                .ui(ui);
279        });
280        root_ui().pop_skin();
281
282        next_frame().await;
283    }
284}
Source

pub fn pop_skin(&mut self)

Examples found in repository?
examples/ui_skins.rs (line 259)
6async fn main() {
7    let skin1 = {
8        let font = load_ttf_font("examples/ui_assets/HTOWERT.TTF")
9            .await
10            .unwrap();
11        let label_style = root_ui()
12            .style_builder()
13            .with_font(&font)
14            .unwrap()
15            .text_color(Color::from_rgba(180, 180, 120, 255))
16            .font_size(30)
17            .build();
18
19        let window_style = root_ui()
20            .style_builder()
21            .background(
22                Image::from_file_with_format(
23                    include_bytes!("../examples/ui_assets/window_background.png"),
24                    None,
25                )
26                .unwrap(),
27            )
28            .background_margin(RectOffset::new(20.0, 20.0, 10.0, 10.0))
29            .margin(RectOffset::new(-20.0, -30.0, 0.0, 0.0))
30            .build();
31
32        let button_style = root_ui()
33            .style_builder()
34            .background(
35                Image::from_file_with_format(
36                    include_bytes!("../examples/ui_assets/button_background.png"),
37                    None,
38                )
39                .unwrap(),
40            )
41            .background_margin(RectOffset::new(37.0, 37.0, 5.0, 5.0))
42            .margin(RectOffset::new(10.0, 10.0, 0.0, 0.0))
43            .background_hovered(
44                Image::from_file_with_format(
45                    include_bytes!("../examples/ui_assets/button_hovered_background.png"),
46                    None,
47                )
48                .unwrap(),
49            )
50            .background_clicked(
51                Image::from_file_with_format(
52                    include_bytes!("../examples/ui_assets/button_clicked_background.png"),
53                    None,
54                )
55                .unwrap(),
56            )
57            .with_font(&font)
58            .unwrap()
59            .text_color(Color::from_rgba(180, 180, 100, 255))
60            .font_size(40)
61            .build();
62
63        let editbox_style = root_ui()
64            .style_builder()
65            .background_margin(RectOffset::new(0., 0., 0., 0.))
66            .with_font(&font)
67            .unwrap()
68            .text_color(Color::from_rgba(120, 120, 120, 255))
69            .color_selected(Color::from_rgba(190, 190, 190, 255))
70            .font_size(50)
71            .build();
72
73        Skin {
74            editbox_style,
75            window_style,
76            button_style,
77            label_style,
78            ..root_ui().default_skin()
79        }
80    };
81
82    let skin2 = {
83        let font = load_ttf_font("examples/ui_assets/MinimalPixel v2.ttf")
84            .await
85            .unwrap();
86        let label_style = root_ui()
87            .style_builder()
88            .with_font(&font)
89            .unwrap()
90            .text_color(Color::from_rgba(120, 120, 120, 255))
91            .font_size(25)
92            .build();
93
94        let window_style = root_ui()
95            .style_builder()
96            .background(
97                Image::from_file_with_format(
98                    include_bytes!("../examples/ui_assets/window_background_2.png"),
99                    None,
100                )
101                .unwrap(),
102            )
103            .background_margin(RectOffset::new(52.0, 52.0, 52.0, 52.0))
104            .margin(RectOffset::new(-30.0, 0.0, -30.0, 0.0))
105            .build();
106
107        let button_style = root_ui()
108            .style_builder()
109            .background(
110                Image::from_file_with_format(
111                    include_bytes!("../examples/ui_assets/button_background_2.png"),
112                    None,
113                )
114                .unwrap(),
115            )
116            .background_margin(RectOffset::new(8.0, 8.0, 8.0, 8.0))
117            .background_hovered(
118                Image::from_file_with_format(
119                    include_bytes!("../examples/ui_assets/button_hovered_background_2.png"),
120                    None,
121                )
122                .unwrap(),
123            )
124            .background_clicked(
125                Image::from_file_with_format(
126                    include_bytes!("../examples/ui_assets/button_clicked_background_2.png"),
127                    None,
128                )
129                .unwrap(),
130            )
131            .with_font(&font)
132            .unwrap()
133            .text_color(Color::from_rgba(180, 180, 100, 255))
134            .font_size(40)
135            .build();
136
137        let checkbox_style = root_ui()
138            .style_builder()
139            .background(
140                Image::from_file_with_format(
141                    include_bytes!("../examples/ui_assets/checkbox_background.png"),
142                    None,
143                )
144                .unwrap(),
145            )
146            .background_hovered(
147                Image::from_file_with_format(
148                    include_bytes!("../examples/ui_assets/checkbox_hovered_background.png"),
149                    None,
150                )
151                .unwrap(),
152            )
153            .background_clicked(
154                Image::from_file_with_format(
155                    include_bytes!("../examples/ui_assets/checkbox_clicked_background.png"),
156                    None,
157                )
158                .unwrap(),
159            )
160            .build();
161
162        let editbox_style = root_ui()
163            .style_builder()
164            .background(
165                Image::from_file_with_format(
166                    include_bytes!("../examples/ui_assets/editbox_background.png"),
167                    None,
168                )
169                .unwrap(),
170            )
171            .background_margin(RectOffset::new(2., 2., 2., 2.))
172            .with_font(&font)
173            .unwrap()
174            .text_color(Color::from_rgba(120, 120, 120, 255))
175            .font_size(25)
176            .build();
177
178        let combobox_style = root_ui()
179            .style_builder()
180            .background(
181                Image::from_file_with_format(
182                    include_bytes!("../examples/ui_assets/combobox_background.png"),
183                    None,
184                )
185                .unwrap(),
186            )
187            .background_margin(RectOffset::new(4., 25., 6., 6.))
188            .with_font(&font)
189            .unwrap()
190            .text_color(Color::from_rgba(120, 120, 120, 255))
191            .color(Color::from_rgba(210, 210, 210, 255))
192            .font_size(25)
193            .build();
194
195        Skin {
196            window_style,
197            button_style,
198            label_style,
199            checkbox_style,
200            editbox_style,
201            combobox_style,
202            ..root_ui().default_skin()
203        }
204    };
205    let default_skin = root_ui().default_skin().clone();
206
207    let mut window1_skin = skin1.clone();
208    let mut window2_skin = skin2.clone();
209
210    let mut checkbox = false;
211    let mut text = String::new();
212    let mut number = 0.0f32;
213    let mut combobox = 0;
214
215    loop {
216        clear_background(GRAY);
217
218        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
219            ui.label(None, "Window 1");
220
221            if ui.button(None, "Skin 1") {
222                window1_skin = skin1.clone();
223            }
224            if ui.button(None, "Skin 2") {
225                window1_skin = skin2.clone();
226            }
227            if ui.button(None, "No Skin") {
228                window1_skin = default_skin.clone();
229            }
230        });
231        root_ui().same_line(0.);
232        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
233            ui.label(None, "Window 2");
234            if ui.button(None, "Skin 1") {
235                window2_skin = skin1.clone();
236            }
237            if ui.button(None, "Skin 2") {
238                window2_skin = skin2.clone();
239            }
240            if ui.button(None, "No Skin") {
241                window2_skin = default_skin.clone();
242            }
243        });
244
245        root_ui().push_skin(&window1_skin);
246
247        root_ui().window(hash!(), vec2(20., 250.), vec2(300., 300.), |ui| {
248            widgets::Button::new("Play")
249                .position(vec2(65.0, 15.0))
250                .ui(ui);
251            widgets::Button::new("Options")
252                .position(vec2(40.0, 75.0))
253                .ui(ui);
254
255            widgets::Button::new("Quit")
256                .position(vec2(65.0, 195.0))
257                .ui(ui);
258        });
259        root_ui().pop_skin();
260
261        root_ui().push_skin(&window2_skin);
262        root_ui().window(hash!(), vec2(250., 20.), vec2(500., 250.), |ui| {
263            ui.checkbox(hash!(), "Checkbox 1", &mut checkbox);
264            ui.combo_box(
265                hash!(),
266                "Combobox",
267                &["First option", "Second option"],
268                &mut combobox,
269            );
270            ui.input_text(hash!(), "Text", &mut text);
271            ui.drag(hash!(), "Drag", None, &mut number);
272
273            widgets::Button::new("Apply")
274                .position(vec2(80.0, 150.0))
275                .ui(ui);
276            widgets::Button::new("Cancel")
277                .position(vec2(280.0, 150.0))
278                .ui(ui);
279        });
280        root_ui().pop_skin();
281
282        next_frame().await;
283    }
284}

Trait Implementations§

Source§

impl InputHandler for Ui

Source§

fn mouse_down(&mut self, position: (f32, f32))

Source§

fn mouse_up(&mut self, _: (f32, f32))

Source§

fn mouse_wheel(&mut self, x: f32, y: f32)

Source§

fn mouse_move(&mut self, position: (f32, f32))

Source§

fn char_event(&mut self, character: char, shift: bool, ctrl: bool)

Source§

fn key_down(&mut self, key: KeyCode, shift: bool, ctrl: bool)

Auto Trait Implementations§

§

impl Freeze for Ui

§

impl !RefUnwindSafe for Ui

§

impl !Send for Ui

§

impl !Sync for Ui

§

impl Unpin for Ui

§

impl !UnwindSafe for Ui

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<S> FromSample<S> for S

Source§

fn from_sample_(s: S) -> S

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> ToSample<U> for T
where U: FromSample<T>,

Source§

fn to_sample_(self) -> U

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,