Struct macroquad::ui::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)
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
async fn main() {
    set_pc_assets_folder("examples");

    let sound1 = audio::load_sound("sound.wav").await.unwrap();
    let sound2 = audio::load_sound("sound2.wav").await.unwrap();

    loop {
        clear_background(LIGHTGRAY);

        if ui::root_ui().button(None, "Play sound 1") {
            warn!("play 1!");
            audio::play_sound_once(&sound1);
        }
        if ui::root_ui().button(None, "Play sound 2") {
            warn!("play 2!");
            audio::play_sound_once(&sound2);
        }
        next_frame().await
    }
}
More examples
Hide additional examples
examples/exit_dialog.rs (line 26)
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
async fn main() {
    prevent_quit();

    let mut show_exit_dialog = false;
    let mut user_decided_to_exit = false;

    loop {
        clear_background(GRAY);

        if is_quit_requested() {
            show_exit_dialog = true;
        }

        if show_exit_dialog {
            let dialog_size = vec2(200., 70.);
            let screen_size = vec2(screen_width(), screen_height());
            let dialog_position = screen_size / 2. - dialog_size / 2.;
            Window::new(hash!(), dialog_position, dialog_size).ui(&mut *root_ui(), |ui| {
                ui.label(None, "Do you really want to quit?");
                ui.separator();
                ui.same_line(60.);
                if ui.button(None, "Yes") {
                    user_decided_to_exit = true;
                }
                ui.same_line(120.);
                if ui.button(None, "No") {
                    show_exit_dialog = false;
                }
            });
        }

        if user_decided_to_exit {
            break;
        }

        next_frame().await
    }
}
examples/ui.rs (line 162)
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
async fn main() {
    let mut data = Data::new();

    let mut data0 = String::new();
    let mut data1 = String::new();

    let mut text0 = String::new();
    let mut text1 = String::new();

    let mut number0 = 0.;
    let mut number1 = 0.;

    let texture: Texture2D = load_texture("examples/ferris.png").await.unwrap();

    loop {
        clear_background(WHITE);

        widgets::Window::new(hash!(), vec2(400., 200.), vec2(320., 400.))
            .label("Shop")
            .titlebar(true)
            .ui(&mut *root_ui(), |ui| {
                for i in 0..30 {
                    Group::new(hash!("shop", i), Vec2::new(300., 80.)).ui(ui, |ui| {
                        ui.label(Vec2::new(10., 10.), &format!("Item N {}", i));
                        ui.label(Vec2::new(260., 40.), "10/10");
                        ui.label(Vec2::new(200., 58.), &format!("{} kr", 800));
                        if ui.button(Vec2::new(260., 55.), "buy") {
                            data.inventory.push(format!("Item {}", i));
                        }
                    });
                }
            });

        widgets::Window::new(hash!(), vec2(100., 220.), vec2(542., 430.))
            .label("Fitting window")
            .titlebar(true)
            .ui(&mut *root_ui(), |ui| {
                Group::new(hash!(), Vec2::new(230., 400.)).ui(ui, |ui| {
                    data.slots(ui);
                });
                Group::new(hash!(), Vec2::new(280., 400.)).ui(ui, |ui| {
                    data.inventory(ui);
                });
            });

        widgets::Window::new(hash!(), vec2(470., 50.), vec2(300., 300.))
            .label("Megaui Showcase Window")
            .ui(&mut *root_ui(), |ui| {
                ui.tree_node(hash!(), "input", |ui| {
                    ui.label(None, "Some random text");
                    if ui.button(None, "click me") {
                        println!("hi");
                    }

                    ui.separator();

                    ui.label(None, "Some other random text");
                    if ui.button(None, "other button") {
                        println!("hi2");
                    }

                    ui.separator();

                    ui.input_text(hash!(), "<- input text 1", &mut data0);
                    ui.input_text(hash!(), "<- input text 2", &mut data1);
                    ui.label(
                        None,
                        &format!("Text entered: \"{}\" and \"{}\"", data0, data1),
                    );

                    ui.separator();
                });
                ui.tree_node(hash!(), "buttons", |ui| {
                    widgets::Button::new(texture.clone())
                        .size(vec2(120., 70.))
                        .ui(ui);
                    ui.same_line(0.);
                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
                    ui.same_line(0.);
                    widgets::Button::new(texture.clone())
                        .size(vec2(120., 70.))
                        .ui(ui);
                });
                ui.tree_node(hash!(), "sliders", |ui| {
                    ui.slider(hash!(), "[-10 .. 10]", -10f32..10f32, &mut number0);
                    ui.slider(hash!(), "[0 .. 100]", 0f32..100f32, &mut number1);
                });
                ui.tree_node(hash!(), "editbox 1", |ui| {
                    ui.label(None, "This is editbox!");
                    ui.editbox(hash!(), vec2(285., 165.), &mut text0);
                });
                ui.tree_node(hash!(), "editbox 2", |ui| {
                    ui.label(None, "This is editbox!");
                    ui.editbox(hash!(), vec2(285., 165.), &mut text1);
                });
            });

        match data.fit_command.take() {
            Some(FittingCommand::Unfit { target_slot }) => data.set_item(target_slot, None),
            Some(FittingCommand::Fit { target_slot, item }) => {
                data.set_item(target_slot, Some(item));
            }
            Some(FittingCommand::Refit {
                target_slot,
                origin_slot,
            }) => {
                let origin_item = data
                    .slots
                    .iter()
                    .find_map(|(_, slot)| {
                        if slot.id == origin_slot {
                            Some(slot.item.clone())
                        } else {
                            None
                        }
                    })
                    .flatten();
                data.set_item(target_slot, origin_item);
                data.set_item(origin_slot, None);
            }
            None => {}
        };

        next_frame().await;
    }
}
examples/ui_skins.rs (line 215)
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
async fn main() {
    let skin1 = {
        let label_style = root_ui()
            .style_builder()
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 120, 255))
            .font_size(30)
            .build();

        let window_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/window_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(20.0, 20.0, 10.0, 10.0))
            .margin(RectOffset::new(-20.0, -30.0, 0.0, 0.0))
            .build();

        let button_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(37.0, 37.0, 5.0, 5.0))
            .margin(RectOffset::new(10.0, 10.0, 0.0, 0.0))
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_hovered_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_clicked_background.png"),
                    None,
                )
                .unwrap(),
            )
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 100, 255))
            .font_size(40)
            .build();

        let editbox_style = root_ui()
            .style_builder()
            .background_margin(RectOffset::new(0., 0., 0., 0.))
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .color_selected(Color::from_rgba(190, 190, 190, 255))
            .font_size(50)
            .build();

        Skin {
            editbox_style,
            window_style,
            button_style,
            label_style,
            ..root_ui().default_skin()
        }
    };

    let skin2 = {
        let label_style = root_ui()
            .style_builder()
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .font_size(25)
            .build();

        let window_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/window_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(52.0, 52.0, 52.0, 52.0))
            .margin(RectOffset::new(-30.0, 0.0, -30.0, 0.0))
            .build();

        let button_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(8.0, 8.0, 8.0, 8.0))
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_hovered_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_clicked_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 100, 255))
            .font_size(40)
            .build();

        let checkbox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_hovered_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_clicked_background.png"),
                    None,
                )
                .unwrap(),
            )
            .build();

        let editbox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/editbox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(2., 2., 2., 2.))
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .font_size(25)
            .build();

        let combobox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/combobox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(4., 25., 6., 6.))
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .color(Color::from_rgba(210, 210, 210, 255))
            .font_size(25)
            .build();

        Skin {
            window_style,
            button_style,
            label_style,
            checkbox_style,
            editbox_style,
            combobox_style,
            ..root_ui().default_skin()
        }
    };
    let default_skin = root_ui().default_skin().clone();

    let mut window1_skin = skin1.clone();
    let mut window2_skin = skin2.clone();

    let mut checkbox = false;
    let mut text = String::new();
    let mut number = 0.0f32;
    let mut combobox = 0;

    loop {
        clear_background(GRAY);

        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
            ui.label(None, "Window 1");

            if ui.button(None, "Skin 1") {
                window1_skin = skin1.clone();
            }
            if ui.button(None, "Skin 2") {
                window1_skin = skin2.clone();
            }
            if ui.button(None, "No Skin") {
                window1_skin = default_skin.clone();
            }
        });
        root_ui().same_line(0.);
        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
            ui.label(None, "Window 2");
            if ui.button(None, "Skin 1") {
                window2_skin = skin1.clone();
            }
            if ui.button(None, "Skin 2") {
                window2_skin = skin2.clone();
            }
            if ui.button(None, "No Skin") {
                window2_skin = default_skin.clone();
            }
        });

        root_ui().push_skin(&window1_skin);

        root_ui().window(hash!(), vec2(20., 250.), vec2(300., 300.), |ui| {
            widgets::Button::new("Play")
                .position(vec2(65.0, 15.0))
                .ui(ui);
            widgets::Button::new("Options")
                .position(vec2(40.0, 75.0))
                .ui(ui);

            widgets::Button::new("Quit")
                .position(vec2(65.0, 195.0))
                .ui(ui);
        });
        root_ui().pop_skin();

        root_ui().push_skin(&window2_skin);
        root_ui().window(hash!(), vec2(250., 20.), vec2(500., 250.), |ui| {
            ui.checkbox(hash!(), "Checkbox 1", &mut checkbox);
            ui.combo_box(
                hash!(),
                "Combobox",
                &["First option", "Second option"],
                &mut combobox,
            );
            ui.input_text(hash!(), "Text", &mut text);
            ui.drag(hash!(), "Drag", None, &mut number);

            widgets::Button::new("Apply")
                .position(vec2(80.0, 150.0))
                .ui(ui);
            widgets::Button::new("Cancel")
                .position(vec2(280.0, 150.0))
                .ui(ui);
        });
        root_ui().pop_skin();

        next_frame().await;
    }
}
examples/shadertoy.rs (line 123)
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
async fn main() {
    let ferris = load_texture("examples/rust.png").await.unwrap();
    let (color_picker_texture, color_picker_image) = color_picker_texture(200, 200);

    let mut fragment_shader = DEFAULT_FRAGMENT_SHADER.to_string();
    let mut vertex_shader = DEFAULT_VERTEX_SHADER.to_string();

    let pipeline_params = PipelineParams {
        depth_write: true,
        depth_test: Comparison::LessOrEqual,
        ..Default::default()
    };

    let mut material = load_material(
        ShaderSource::Glsl {
            vertex: &vertex_shader,
            fragment: &fragment_shader,
        },
        MaterialParams {
            pipeline_params,
            ..Default::default()
        },
    )
    .unwrap();
    let mut error: Option<String> = None;

    enum Mesh {
        Sphere,
        Cube,
        Plane,
    }
    let mut mesh = Mesh::Sphere;

    let mut camera = Camera3D {
        position: vec3(-15., 15., -5.),
        up: vec3(0., 1., 0.),
        target: vec3(0., 5., -5.),
        ..Default::default()
    };

    let mut colorpicker_window = false;
    let mut color_picking_uniform = None;

    let mut new_uniform_window = false;
    let mut new_uniform_name = String::new();
    let mut uniforms: Vec<(String, Uniform)> = vec![];

    loop {
        clear_background(WHITE);

        set_camera(&camera);

        draw_grid(
            20,
            1.,
            Color::new(0.55, 0.55, 0.55, 0.75),
            Color::new(0.75, 0.75, 0.75, 0.75),
        );

        gl_use_material(&material);
        match mesh {
            Mesh::Plane => draw_plane(vec3(0., 2., 0.), vec2(5., 5.), Some(&ferris), WHITE),
            Mesh::Sphere => draw_sphere(vec3(0., 6., 0.), 5., Some(&ferris), WHITE),
            Mesh::Cube => draw_cube(vec3(0., 5., 0.), vec3(10., 10., 10.), Some(&ferris), WHITE),
        }
        gl_use_default_material();

        set_default_camera();

        let mut need_update = false;

        widgets::Window::new(hash!(), vec2(20., 20.), vec2(470., 650.))
            .label("Shader")
            .ui(&mut *root_ui(), |ui| {
                ui.label(None, "Camera: ");
                ui.same_line(0.0);
                if ui.button(None, "Ortho") {
                    camera.projection = Projection::Orthographics;
                }
                ui.same_line(0.0);
                if ui.button(None, "Perspective") {
                    camera.projection = Projection::Perspective;
                }
                ui.label(None, "Mesh: ");
                ui.same_line(0.0);
                if ui.button(None, "Sphere") {
                    mesh = Mesh::Sphere;
                }
                ui.same_line(0.0);
                if ui.button(None, "Cube") {
                    mesh = Mesh::Cube;
                }
                ui.same_line(0.0);
                if ui.button(None, "Plane") {
                    mesh = Mesh::Plane;
                }

                ui.label(None, "Uniforms:");
                ui.separator();

                for (i, (name, uniform)) in uniforms.iter_mut().enumerate() {
                    ui.label(None, &format!("{}", name));
                    ui.same_line(120.0);

                    match uniform {
                        Uniform::Float1(x) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(200.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            if let Ok(x) = x.parse::<f32>() {
                                material.set_uniform(name, x);
                            }
                        }
                        Uniform::Float2(x, y) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(99.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(99.0, 19.0))
                                .filter_numbers()
                                .ui(ui, y);

                            if let (Ok(x), Ok(y)) = (x.parse::<f32>(), y.parse::<f32>()) {
                                material.set_uniform(name, (x, y));
                            }
                        }
                        Uniform::Float3(x, y, z) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, y);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, z);

                            if let (Ok(x), Ok(y), Ok(z)) =
                                (x.parse::<f32>(), y.parse::<f32>(), z.parse::<f32>())
                            {
                                material.set_uniform(name, (x, y, z));
                            }
                        }

                        Uniform::Color(color) => {
                            let mut canvas = ui.canvas();

                            let cursor = canvas.cursor();

                            canvas.rect(
                                Rect::new(cursor.x + 20.0, cursor.y, 50.0, 18.0),
                                Color::new(0.2, 0.2, 0.2, 1.0),
                                Color::new(color.x, color.y, color.z, 1.0),
                            );

                            if ui.button(None, "change") {
                                colorpicker_window = true;
                                color_picking_uniform = Some(name.to_owned());
                            }
                            material.set_uniform(name, (color.x, color.y, color.z));
                        }
                    }
                }
                ui.separator();
                if ui.button(None, "New uniform") {
                    new_uniform_window = true;
                }
                TreeNode::new(hash!(), "Fragment shader")
                    .init_unfolded()
                    .ui(ui, |ui| {
                        if ui.editbox(hash!(), vec2(440., 200.), &mut fragment_shader) {
                            need_update = true;
                        };
                    });
                ui.tree_node(hash!(), "Vertex shader", |ui| {
                    if ui.editbox(hash!(), vec2(440., 300.), &mut vertex_shader) {
                        need_update = true;
                    };
                });

                if let Some(ref error) = error {
                    Label::new(error).multiline(14.0).ui(ui);
                }
            });

        if new_uniform_window {
            widgets::Window::new(hash!(), vec2(100., 100.), vec2(200., 80.))
                .label("New uniform")
                .ui(&mut *root_ui(), |ui| {
                    if ui.active_window_focused() == false {
                        new_uniform_window = false;
                    }
                    ui.input_text(hash!(), "Name", &mut new_uniform_name);
                    let uniform_type = ui.combo_box(
                        hash!(),
                        "Type",
                        &["Float1", "Float2", "Float3", "Color"],
                        None,
                    );

                    if ui.button(None, "Add") {
                        if new_uniform_name.is_empty() == false {
                            let uniform = match uniform_type {
                                0 => Uniform::Float1("0".to_string()),
                                1 => Uniform::Float2("0".to_string(), "0".to_string()),
                                2 => Uniform::Float3(
                                    "0".to_string(),
                                    "0".to_string(),
                                    "0".to_string(),
                                ),
                                3 => Uniform::Color(vec3(0.0, 0.0, 0.0)),
                                _ => unreachable!(),
                            };
                            uniforms.push((new_uniform_name.clone(), uniform));
                            new_uniform_name.clear();
                            need_update = true;
                        }
                        new_uniform_window = false;
                    }

                    ui.same_line(0.0);
                    if ui.button(None, "Cancel") {
                        new_uniform_window = false;
                    }
                });
        }

        if colorpicker_window {
            colorpicker_window &= widgets::Window::new(hash!(), vec2(140., 100.), vec2(210., 240.))
                .label("Colorpicker")
                .ui(&mut *root_ui(), |ui| {
                    if ui.active_window_focused() == false {
                        colorpicker_window = false;
                    }

                    let mut canvas = ui.canvas();
                    let cursor = canvas.cursor();
                    let mouse = mouse_position();
                    let x = mouse.0 as i32 - cursor.x as i32;
                    let y = mouse.1 as i32 - (cursor.y as i32 + 20);

                    let color = color_picker_image
                        .get_pixel(x.max(0).min(199) as u32, y.max(0).min(199) as u32);

                    canvas.rect(
                        Rect::new(cursor.x, cursor.y, 200.0, 18.0),
                        Color::new(0.0, 0.0, 0.0, 1.0),
                        Color::new(color.r, color.g, color.b, 1.0),
                    );
                    canvas.image(
                        Rect::new(cursor.x, cursor.y + 20.0, 200.0, 200.0),
                        &color_picker_texture,
                    );

                    if x >= 0 && x < 200 && y >= 0 && y < 200 {
                        canvas.rect(
                            Rect::new(mouse.0 - 3.5, mouse.1 - 3.5, 7.0, 7.0),
                            Color::new(0.3, 0.3, 0.3, 1.0),
                            Color::new(1.0, 1.0, 1.0, 1.0),
                        );

                        if is_mouse_button_down(MouseButton::Left) {
                            colorpicker_window = false;
                            let uniform_name = color_picking_uniform.take().unwrap();

                            uniforms
                                .iter_mut()
                                .find(|(name, _)| name == &uniform_name)
                                .unwrap()
                                .1 = Uniform::Color(vec3(color.r, color.g, color.b));
                        }
                    }
                });
        }

        if need_update {
            let uniforms = uniforms
                .iter()
                .map(|(name, uniform)| (name.clone(), uniform.uniform_type()))
                .collect::<Vec<_>>();

            match load_material(
                ShaderSource::Glsl {
                    vertex: &vertex_shader,
                    fragment: &fragment_shader,
                },
                MaterialParams {
                    pipeline_params,
                    uniforms,
                    textures: vec![],
                },
            ) {
                Ok(new_material) => {
                    material = new_material;
                    error = None;
                }
                Err(err) => {
                    error = Some(format!("{:#?}", err));
                }
            }
        }

        next_frame().await
    }
}
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 257)
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
async fn main() {
    let skin1 = {
        let label_style = root_ui()
            .style_builder()
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 120, 255))
            .font_size(30)
            .build();

        let window_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/window_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(20.0, 20.0, 10.0, 10.0))
            .margin(RectOffset::new(-20.0, -30.0, 0.0, 0.0))
            .build();

        let button_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(37.0, 37.0, 5.0, 5.0))
            .margin(RectOffset::new(10.0, 10.0, 0.0, 0.0))
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_hovered_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_clicked_background.png"),
                    None,
                )
                .unwrap(),
            )
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 100, 255))
            .font_size(40)
            .build();

        let editbox_style = root_ui()
            .style_builder()
            .background_margin(RectOffset::new(0., 0., 0., 0.))
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .color_selected(Color::from_rgba(190, 190, 190, 255))
            .font_size(50)
            .build();

        Skin {
            editbox_style,
            window_style,
            button_style,
            label_style,
            ..root_ui().default_skin()
        }
    };

    let skin2 = {
        let label_style = root_ui()
            .style_builder()
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .font_size(25)
            .build();

        let window_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/window_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(52.0, 52.0, 52.0, 52.0))
            .margin(RectOffset::new(-30.0, 0.0, -30.0, 0.0))
            .build();

        let button_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(8.0, 8.0, 8.0, 8.0))
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_hovered_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_clicked_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 100, 255))
            .font_size(40)
            .build();

        let checkbox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_hovered_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_clicked_background.png"),
                    None,
                )
                .unwrap(),
            )
            .build();

        let editbox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/editbox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(2., 2., 2., 2.))
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .font_size(25)
            .build();

        let combobox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/combobox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(4., 25., 6., 6.))
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .color(Color::from_rgba(210, 210, 210, 255))
            .font_size(25)
            .build();

        Skin {
            window_style,
            button_style,
            label_style,
            checkbox_style,
            editbox_style,
            combobox_style,
            ..root_ui().default_skin()
        }
    };
    let default_skin = root_ui().default_skin().clone();

    let mut window1_skin = skin1.clone();
    let mut window2_skin = skin2.clone();

    let mut checkbox = false;
    let mut text = String::new();
    let mut number = 0.0f32;
    let mut combobox = 0;

    loop {
        clear_background(GRAY);

        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
            ui.label(None, "Window 1");

            if ui.button(None, "Skin 1") {
                window1_skin = skin1.clone();
            }
            if ui.button(None, "Skin 2") {
                window1_skin = skin2.clone();
            }
            if ui.button(None, "No Skin") {
                window1_skin = default_skin.clone();
            }
        });
        root_ui().same_line(0.);
        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
            ui.label(None, "Window 2");
            if ui.button(None, "Skin 1") {
                window2_skin = skin1.clone();
            }
            if ui.button(None, "Skin 2") {
                window2_skin = skin2.clone();
            }
            if ui.button(None, "No Skin") {
                window2_skin = default_skin.clone();
            }
        });

        root_ui().push_skin(&window1_skin);

        root_ui().window(hash!(), vec2(20., 250.), vec2(300., 300.), |ui| {
            widgets::Button::new("Play")
                .position(vec2(65.0, 15.0))
                .ui(ui);
            widgets::Button::new("Options")
                .position(vec2(40.0, 75.0))
                .ui(ui);

            widgets::Button::new("Quit")
                .position(vec2(65.0, 195.0))
                .ui(ui);
        });
        root_ui().pop_skin();

        root_ui().push_skin(&window2_skin);
        root_ui().window(hash!(), vec2(250., 20.), vec2(500., 250.), |ui| {
            ui.checkbox(hash!(), "Checkbox 1", &mut checkbox);
            ui.combo_box(
                hash!(),
                "Combobox",
                &["First option", "Second option"],
                &mut combobox,
            );
            ui.input_text(hash!(), "Text", &mut text);
            ui.drag(hash!(), "Drag", None, &mut number);

            widgets::Button::new("Apply")
                .position(vec2(80.0, 150.0))
                .ui(ui);
            widgets::Button::new("Cancel")
                .position(vec2(280.0, 150.0))
                .ui(ui);
        });
        root_ui().pop_skin();

        next_frame().await;
    }
}
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 258-263)
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
async fn main() {
    let skin1 = {
        let label_style = root_ui()
            .style_builder()
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 120, 255))
            .font_size(30)
            .build();

        let window_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/window_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(20.0, 20.0, 10.0, 10.0))
            .margin(RectOffset::new(-20.0, -30.0, 0.0, 0.0))
            .build();

        let button_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(37.0, 37.0, 5.0, 5.0))
            .margin(RectOffset::new(10.0, 10.0, 0.0, 0.0))
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_hovered_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_clicked_background.png"),
                    None,
                )
                .unwrap(),
            )
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 100, 255))
            .font_size(40)
            .build();

        let editbox_style = root_ui()
            .style_builder()
            .background_margin(RectOffset::new(0., 0., 0., 0.))
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .color_selected(Color::from_rgba(190, 190, 190, 255))
            .font_size(50)
            .build();

        Skin {
            editbox_style,
            window_style,
            button_style,
            label_style,
            ..root_ui().default_skin()
        }
    };

    let skin2 = {
        let label_style = root_ui()
            .style_builder()
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .font_size(25)
            .build();

        let window_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/window_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(52.0, 52.0, 52.0, 52.0))
            .margin(RectOffset::new(-30.0, 0.0, -30.0, 0.0))
            .build();

        let button_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(8.0, 8.0, 8.0, 8.0))
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_hovered_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_clicked_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 100, 255))
            .font_size(40)
            .build();

        let checkbox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_hovered_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_clicked_background.png"),
                    None,
                )
                .unwrap(),
            )
            .build();

        let editbox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/editbox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(2., 2., 2., 2.))
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .font_size(25)
            .build();

        let combobox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/combobox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(4., 25., 6., 6.))
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .color(Color::from_rgba(210, 210, 210, 255))
            .font_size(25)
            .build();

        Skin {
            window_style,
            button_style,
            label_style,
            checkbox_style,
            editbox_style,
            combobox_style,
            ..root_ui().default_skin()
        }
    };
    let default_skin = root_ui().default_skin().clone();

    let mut window1_skin = skin1.clone();
    let mut window2_skin = skin2.clone();

    let mut checkbox = false;
    let mut text = String::new();
    let mut number = 0.0f32;
    let mut combobox = 0;

    loop {
        clear_background(GRAY);

        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
            ui.label(None, "Window 1");

            if ui.button(None, "Skin 1") {
                window1_skin = skin1.clone();
            }
            if ui.button(None, "Skin 2") {
                window1_skin = skin2.clone();
            }
            if ui.button(None, "No Skin") {
                window1_skin = default_skin.clone();
            }
        });
        root_ui().same_line(0.);
        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
            ui.label(None, "Window 2");
            if ui.button(None, "Skin 1") {
                window2_skin = skin1.clone();
            }
            if ui.button(None, "Skin 2") {
                window2_skin = skin2.clone();
            }
            if ui.button(None, "No Skin") {
                window2_skin = default_skin.clone();
            }
        });

        root_ui().push_skin(&window1_skin);

        root_ui().window(hash!(), vec2(20., 250.), vec2(300., 300.), |ui| {
            widgets::Button::new("Play")
                .position(vec2(65.0, 15.0))
                .ui(ui);
            widgets::Button::new("Options")
                .position(vec2(40.0, 75.0))
                .ui(ui);

            widgets::Button::new("Quit")
                .position(vec2(65.0, 195.0))
                .ui(ui);
        });
        root_ui().pop_skin();

        root_ui().push_skin(&window2_skin);
        root_ui().window(hash!(), vec2(250., 20.), vec2(500., 250.), |ui| {
            ui.checkbox(hash!(), "Checkbox 1", &mut checkbox);
            ui.combo_box(
                hash!(),
                "Combobox",
                &["First option", "Second option"],
                &mut combobox,
            );
            ui.input_text(hash!(), "Text", &mut text);
            ui.drag(hash!(), "Drag", None, &mut number);

            widgets::Button::new("Apply")
                .position(vec2(80.0, 150.0))
                .ui(ui);
            widgets::Button::new("Cancel")
                .position(vec2(280.0, 150.0))
                .ui(ui);
        });
        root_ui().pop_skin();

        next_frame().await;
    }
}
More examples
Hide additional examples
examples/shadertoy.rs (lines 255-260)
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
async fn main() {
    let ferris = load_texture("examples/rust.png").await.unwrap();
    let (color_picker_texture, color_picker_image) = color_picker_texture(200, 200);

    let mut fragment_shader = DEFAULT_FRAGMENT_SHADER.to_string();
    let mut vertex_shader = DEFAULT_VERTEX_SHADER.to_string();

    let pipeline_params = PipelineParams {
        depth_write: true,
        depth_test: Comparison::LessOrEqual,
        ..Default::default()
    };

    let mut material = load_material(
        ShaderSource::Glsl {
            vertex: &vertex_shader,
            fragment: &fragment_shader,
        },
        MaterialParams {
            pipeline_params,
            ..Default::default()
        },
    )
    .unwrap();
    let mut error: Option<String> = None;

    enum Mesh {
        Sphere,
        Cube,
        Plane,
    }
    let mut mesh = Mesh::Sphere;

    let mut camera = Camera3D {
        position: vec3(-15., 15., -5.),
        up: vec3(0., 1., 0.),
        target: vec3(0., 5., -5.),
        ..Default::default()
    };

    let mut colorpicker_window = false;
    let mut color_picking_uniform = None;

    let mut new_uniform_window = false;
    let mut new_uniform_name = String::new();
    let mut uniforms: Vec<(String, Uniform)> = vec![];

    loop {
        clear_background(WHITE);

        set_camera(&camera);

        draw_grid(
            20,
            1.,
            Color::new(0.55, 0.55, 0.55, 0.75),
            Color::new(0.75, 0.75, 0.75, 0.75),
        );

        gl_use_material(&material);
        match mesh {
            Mesh::Plane => draw_plane(vec3(0., 2., 0.), vec2(5., 5.), Some(&ferris), WHITE),
            Mesh::Sphere => draw_sphere(vec3(0., 6., 0.), 5., Some(&ferris), WHITE),
            Mesh::Cube => draw_cube(vec3(0., 5., 0.), vec3(10., 10., 10.), Some(&ferris), WHITE),
        }
        gl_use_default_material();

        set_default_camera();

        let mut need_update = false;

        widgets::Window::new(hash!(), vec2(20., 20.), vec2(470., 650.))
            .label("Shader")
            .ui(&mut *root_ui(), |ui| {
                ui.label(None, "Camera: ");
                ui.same_line(0.0);
                if ui.button(None, "Ortho") {
                    camera.projection = Projection::Orthographics;
                }
                ui.same_line(0.0);
                if ui.button(None, "Perspective") {
                    camera.projection = Projection::Perspective;
                }
                ui.label(None, "Mesh: ");
                ui.same_line(0.0);
                if ui.button(None, "Sphere") {
                    mesh = Mesh::Sphere;
                }
                ui.same_line(0.0);
                if ui.button(None, "Cube") {
                    mesh = Mesh::Cube;
                }
                ui.same_line(0.0);
                if ui.button(None, "Plane") {
                    mesh = Mesh::Plane;
                }

                ui.label(None, "Uniforms:");
                ui.separator();

                for (i, (name, uniform)) in uniforms.iter_mut().enumerate() {
                    ui.label(None, &format!("{}", name));
                    ui.same_line(120.0);

                    match uniform {
                        Uniform::Float1(x) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(200.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            if let Ok(x) = x.parse::<f32>() {
                                material.set_uniform(name, x);
                            }
                        }
                        Uniform::Float2(x, y) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(99.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(99.0, 19.0))
                                .filter_numbers()
                                .ui(ui, y);

                            if let (Ok(x), Ok(y)) = (x.parse::<f32>(), y.parse::<f32>()) {
                                material.set_uniform(name, (x, y));
                            }
                        }
                        Uniform::Float3(x, y, z) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, y);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, z);

                            if let (Ok(x), Ok(y), Ok(z)) =
                                (x.parse::<f32>(), y.parse::<f32>(), z.parse::<f32>())
                            {
                                material.set_uniform(name, (x, y, z));
                            }
                        }

                        Uniform::Color(color) => {
                            let mut canvas = ui.canvas();

                            let cursor = canvas.cursor();

                            canvas.rect(
                                Rect::new(cursor.x + 20.0, cursor.y, 50.0, 18.0),
                                Color::new(0.2, 0.2, 0.2, 1.0),
                                Color::new(color.x, color.y, color.z, 1.0),
                            );

                            if ui.button(None, "change") {
                                colorpicker_window = true;
                                color_picking_uniform = Some(name.to_owned());
                            }
                            material.set_uniform(name, (color.x, color.y, color.z));
                        }
                    }
                }
                ui.separator();
                if ui.button(None, "New uniform") {
                    new_uniform_window = true;
                }
                TreeNode::new(hash!(), "Fragment shader")
                    .init_unfolded()
                    .ui(ui, |ui| {
                        if ui.editbox(hash!(), vec2(440., 200.), &mut fragment_shader) {
                            need_update = true;
                        };
                    });
                ui.tree_node(hash!(), "Vertex shader", |ui| {
                    if ui.editbox(hash!(), vec2(440., 300.), &mut vertex_shader) {
                        need_update = true;
                    };
                });

                if let Some(ref error) = error {
                    Label::new(error).multiline(14.0).ui(ui);
                }
            });

        if new_uniform_window {
            widgets::Window::new(hash!(), vec2(100., 100.), vec2(200., 80.))
                .label("New uniform")
                .ui(&mut *root_ui(), |ui| {
                    if ui.active_window_focused() == false {
                        new_uniform_window = false;
                    }
                    ui.input_text(hash!(), "Name", &mut new_uniform_name);
                    let uniform_type = ui.combo_box(
                        hash!(),
                        "Type",
                        &["Float1", "Float2", "Float3", "Color"],
                        None,
                    );

                    if ui.button(None, "Add") {
                        if new_uniform_name.is_empty() == false {
                            let uniform = match uniform_type {
                                0 => Uniform::Float1("0".to_string()),
                                1 => Uniform::Float2("0".to_string(), "0".to_string()),
                                2 => Uniform::Float3(
                                    "0".to_string(),
                                    "0".to_string(),
                                    "0".to_string(),
                                ),
                                3 => Uniform::Color(vec3(0.0, 0.0, 0.0)),
                                _ => unreachable!(),
                            };
                            uniforms.push((new_uniform_name.clone(), uniform));
                            new_uniform_name.clear();
                            need_update = true;
                        }
                        new_uniform_window = false;
                    }

                    ui.same_line(0.0);
                    if ui.button(None, "Cancel") {
                        new_uniform_window = false;
                    }
                });
        }

        if colorpicker_window {
            colorpicker_window &= widgets::Window::new(hash!(), vec2(140., 100.), vec2(210., 240.))
                .label("Colorpicker")
                .ui(&mut *root_ui(), |ui| {
                    if ui.active_window_focused() == false {
                        colorpicker_window = false;
                    }

                    let mut canvas = ui.canvas();
                    let cursor = canvas.cursor();
                    let mouse = mouse_position();
                    let x = mouse.0 as i32 - cursor.x as i32;
                    let y = mouse.1 as i32 - (cursor.y as i32 + 20);

                    let color = color_picker_image
                        .get_pixel(x.max(0).min(199) as u32, y.max(0).min(199) as u32);

                    canvas.rect(
                        Rect::new(cursor.x, cursor.y, 200.0, 18.0),
                        Color::new(0.0, 0.0, 0.0, 1.0),
                        Color::new(color.r, color.g, color.b, 1.0),
                    );
                    canvas.image(
                        Rect::new(cursor.x, cursor.y + 20.0, 200.0, 200.0),
                        &color_picker_texture,
                    );

                    if x >= 0 && x < 200 && y >= 0 && y < 200 {
                        canvas.rect(
                            Rect::new(mouse.0 - 3.5, mouse.1 - 3.5, 7.0, 7.0),
                            Color::new(0.3, 0.3, 0.3, 1.0),
                            Color::new(1.0, 1.0, 1.0, 1.0),
                        );

                        if is_mouse_button_down(MouseButton::Left) {
                            colorpicker_window = false;
                            let uniform_name = color_picking_uniform.take().unwrap();

                            uniforms
                                .iter_mut()
                                .find(|(name, _)| name == &uniform_name)
                                .unwrap()
                                .1 = Uniform::Color(vec3(color.r, color.g, color.b));
                        }
                    }
                });
        }

        if need_update {
            let uniforms = uniforms
                .iter()
                .map(|(name, uniform)| (name.clone(), uniform.uniform_type()))
                .collect::<Vec<_>>();

            match load_material(
                ShaderSource::Glsl {
                    vertex: &vertex_shader,
                    fragment: &fragment_shader,
                },
                MaterialParams {
                    pipeline_params,
                    uniforms,
                    textures: vec![],
                },
            ) {
                Ok(new_material) => {
                    material = new_material;
                    error = None;
                }
                Err(err) => {
                    error = Some(format!("{:#?}", err));
                }
            }
        }

        next_frame().await
    }
}
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 265)
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
async fn main() {
    let skin1 = {
        let label_style = root_ui()
            .style_builder()
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 120, 255))
            .font_size(30)
            .build();

        let window_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/window_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(20.0, 20.0, 10.0, 10.0))
            .margin(RectOffset::new(-20.0, -30.0, 0.0, 0.0))
            .build();

        let button_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(37.0, 37.0, 5.0, 5.0))
            .margin(RectOffset::new(10.0, 10.0, 0.0, 0.0))
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_hovered_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_clicked_background.png"),
                    None,
                )
                .unwrap(),
            )
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 100, 255))
            .font_size(40)
            .build();

        let editbox_style = root_ui()
            .style_builder()
            .background_margin(RectOffset::new(0., 0., 0., 0.))
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .color_selected(Color::from_rgba(190, 190, 190, 255))
            .font_size(50)
            .build();

        Skin {
            editbox_style,
            window_style,
            button_style,
            label_style,
            ..root_ui().default_skin()
        }
    };

    let skin2 = {
        let label_style = root_ui()
            .style_builder()
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .font_size(25)
            .build();

        let window_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/window_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(52.0, 52.0, 52.0, 52.0))
            .margin(RectOffset::new(-30.0, 0.0, -30.0, 0.0))
            .build();

        let button_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(8.0, 8.0, 8.0, 8.0))
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_hovered_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_clicked_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 100, 255))
            .font_size(40)
            .build();

        let checkbox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_hovered_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_clicked_background.png"),
                    None,
                )
                .unwrap(),
            )
            .build();

        let editbox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/editbox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(2., 2., 2., 2.))
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .font_size(25)
            .build();

        let combobox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/combobox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(4., 25., 6., 6.))
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .color(Color::from_rgba(210, 210, 210, 255))
            .font_size(25)
            .build();

        Skin {
            window_style,
            button_style,
            label_style,
            checkbox_style,
            editbox_style,
            combobox_style,
            ..root_ui().default_skin()
        }
    };
    let default_skin = root_ui().default_skin().clone();

    let mut window1_skin = skin1.clone();
    let mut window2_skin = skin2.clone();

    let mut checkbox = false;
    let mut text = String::new();
    let mut number = 0.0f32;
    let mut combobox = 0;

    loop {
        clear_background(GRAY);

        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
            ui.label(None, "Window 1");

            if ui.button(None, "Skin 1") {
                window1_skin = skin1.clone();
            }
            if ui.button(None, "Skin 2") {
                window1_skin = skin2.clone();
            }
            if ui.button(None, "No Skin") {
                window1_skin = default_skin.clone();
            }
        });
        root_ui().same_line(0.);
        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
            ui.label(None, "Window 2");
            if ui.button(None, "Skin 1") {
                window2_skin = skin1.clone();
            }
            if ui.button(None, "Skin 2") {
                window2_skin = skin2.clone();
            }
            if ui.button(None, "No Skin") {
                window2_skin = default_skin.clone();
            }
        });

        root_ui().push_skin(&window1_skin);

        root_ui().window(hash!(), vec2(20., 250.), vec2(300., 300.), |ui| {
            widgets::Button::new("Play")
                .position(vec2(65.0, 15.0))
                .ui(ui);
            widgets::Button::new("Options")
                .position(vec2(40.0, 75.0))
                .ui(ui);

            widgets::Button::new("Quit")
                .position(vec2(65.0, 195.0))
                .ui(ui);
        });
        root_ui().pop_skin();

        root_ui().push_skin(&window2_skin);
        root_ui().window(hash!(), vec2(250., 20.), vec2(500., 250.), |ui| {
            ui.checkbox(hash!(), "Checkbox 1", &mut checkbox);
            ui.combo_box(
                hash!(),
                "Combobox",
                &["First option", "Second option"],
                &mut combobox,
            );
            ui.input_text(hash!(), "Text", &mut text);
            ui.drag(hash!(), "Drag", None, &mut number);

            widgets::Button::new("Apply")
                .position(vec2(80.0, 150.0))
                .ui(ui);
            widgets::Button::new("Cancel")
                .position(vec2(280.0, 150.0))
                .ui(ui);
        });
        root_ui().pop_skin();

        next_frame().await;
    }
}
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 226)
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
async fn main() {
    let mut data = Data::new();

    let mut data0 = String::new();
    let mut data1 = String::new();

    let mut text0 = String::new();
    let mut text1 = String::new();

    let mut number0 = 0.;
    let mut number1 = 0.;

    let texture: Texture2D = load_texture("examples/ferris.png").await.unwrap();

    loop {
        clear_background(WHITE);

        widgets::Window::new(hash!(), vec2(400., 200.), vec2(320., 400.))
            .label("Shop")
            .titlebar(true)
            .ui(&mut *root_ui(), |ui| {
                for i in 0..30 {
                    Group::new(hash!("shop", i), Vec2::new(300., 80.)).ui(ui, |ui| {
                        ui.label(Vec2::new(10., 10.), &format!("Item N {}", i));
                        ui.label(Vec2::new(260., 40.), "10/10");
                        ui.label(Vec2::new(200., 58.), &format!("{} kr", 800));
                        if ui.button(Vec2::new(260., 55.), "buy") {
                            data.inventory.push(format!("Item {}", i));
                        }
                    });
                }
            });

        widgets::Window::new(hash!(), vec2(100., 220.), vec2(542., 430.))
            .label("Fitting window")
            .titlebar(true)
            .ui(&mut *root_ui(), |ui| {
                Group::new(hash!(), Vec2::new(230., 400.)).ui(ui, |ui| {
                    data.slots(ui);
                });
                Group::new(hash!(), Vec2::new(280., 400.)).ui(ui, |ui| {
                    data.inventory(ui);
                });
            });

        widgets::Window::new(hash!(), vec2(470., 50.), vec2(300., 300.))
            .label("Megaui Showcase Window")
            .ui(&mut *root_ui(), |ui| {
                ui.tree_node(hash!(), "input", |ui| {
                    ui.label(None, "Some random text");
                    if ui.button(None, "click me") {
                        println!("hi");
                    }

                    ui.separator();

                    ui.label(None, "Some other random text");
                    if ui.button(None, "other button") {
                        println!("hi2");
                    }

                    ui.separator();

                    ui.input_text(hash!(), "<- input text 1", &mut data0);
                    ui.input_text(hash!(), "<- input text 2", &mut data1);
                    ui.label(
                        None,
                        &format!("Text entered: \"{}\" and \"{}\"", data0, data1),
                    );

                    ui.separator();
                });
                ui.tree_node(hash!(), "buttons", |ui| {
                    widgets::Button::new(texture.clone())
                        .size(vec2(120., 70.))
                        .ui(ui);
                    ui.same_line(0.);
                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
                    ui.same_line(0.);
                    widgets::Button::new(texture.clone())
                        .size(vec2(120., 70.))
                        .ui(ui);
                });
                ui.tree_node(hash!(), "sliders", |ui| {
                    ui.slider(hash!(), "[-10 .. 10]", -10f32..10f32, &mut number0);
                    ui.slider(hash!(), "[0 .. 100]", 0f32..100f32, &mut number1);
                });
                ui.tree_node(hash!(), "editbox 1", |ui| {
                    ui.label(None, "This is editbox!");
                    ui.editbox(hash!(), vec2(285., 165.), &mut text0);
                });
                ui.tree_node(hash!(), "editbox 2", |ui| {
                    ui.label(None, "This is editbox!");
                    ui.editbox(hash!(), vec2(285., 165.), &mut text1);
                });
            });

        match data.fit_command.take() {
            Some(FittingCommand::Unfit { target_slot }) => data.set_item(target_slot, None),
            Some(FittingCommand::Fit { target_slot, item }) => {
                data.set_item(target_slot, Some(item));
            }
            Some(FittingCommand::Refit {
                target_slot,
                origin_slot,
            }) => {
                let origin_item = data
                    .slots
                    .iter()
                    .find_map(|(_, slot)| {
                        if slot.id == origin_slot {
                            Some(slot.item.clone())
                        } else {
                            None
                        }
                    })
                    .flatten();
                data.set_item(target_slot, origin_item);
                data.set_item(origin_slot, None);
            }
            None => {}
        };

        next_frame().await;
    }
}
More examples
Hide additional examples
examples/shadertoy.rs (line 232)
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
async fn main() {
    let ferris = load_texture("examples/rust.png").await.unwrap();
    let (color_picker_texture, color_picker_image) = color_picker_texture(200, 200);

    let mut fragment_shader = DEFAULT_FRAGMENT_SHADER.to_string();
    let mut vertex_shader = DEFAULT_VERTEX_SHADER.to_string();

    let pipeline_params = PipelineParams {
        depth_write: true,
        depth_test: Comparison::LessOrEqual,
        ..Default::default()
    };

    let mut material = load_material(
        ShaderSource::Glsl {
            vertex: &vertex_shader,
            fragment: &fragment_shader,
        },
        MaterialParams {
            pipeline_params,
            ..Default::default()
        },
    )
    .unwrap();
    let mut error: Option<String> = None;

    enum Mesh {
        Sphere,
        Cube,
        Plane,
    }
    let mut mesh = Mesh::Sphere;

    let mut camera = Camera3D {
        position: vec3(-15., 15., -5.),
        up: vec3(0., 1., 0.),
        target: vec3(0., 5., -5.),
        ..Default::default()
    };

    let mut colorpicker_window = false;
    let mut color_picking_uniform = None;

    let mut new_uniform_window = false;
    let mut new_uniform_name = String::new();
    let mut uniforms: Vec<(String, Uniform)> = vec![];

    loop {
        clear_background(WHITE);

        set_camera(&camera);

        draw_grid(
            20,
            1.,
            Color::new(0.55, 0.55, 0.55, 0.75),
            Color::new(0.75, 0.75, 0.75, 0.75),
        );

        gl_use_material(&material);
        match mesh {
            Mesh::Plane => draw_plane(vec3(0., 2., 0.), vec2(5., 5.), Some(&ferris), WHITE),
            Mesh::Sphere => draw_sphere(vec3(0., 6., 0.), 5., Some(&ferris), WHITE),
            Mesh::Cube => draw_cube(vec3(0., 5., 0.), vec3(10., 10., 10.), Some(&ferris), WHITE),
        }
        gl_use_default_material();

        set_default_camera();

        let mut need_update = false;

        widgets::Window::new(hash!(), vec2(20., 20.), vec2(470., 650.))
            .label("Shader")
            .ui(&mut *root_ui(), |ui| {
                ui.label(None, "Camera: ");
                ui.same_line(0.0);
                if ui.button(None, "Ortho") {
                    camera.projection = Projection::Orthographics;
                }
                ui.same_line(0.0);
                if ui.button(None, "Perspective") {
                    camera.projection = Projection::Perspective;
                }
                ui.label(None, "Mesh: ");
                ui.same_line(0.0);
                if ui.button(None, "Sphere") {
                    mesh = Mesh::Sphere;
                }
                ui.same_line(0.0);
                if ui.button(None, "Cube") {
                    mesh = Mesh::Cube;
                }
                ui.same_line(0.0);
                if ui.button(None, "Plane") {
                    mesh = Mesh::Plane;
                }

                ui.label(None, "Uniforms:");
                ui.separator();

                for (i, (name, uniform)) in uniforms.iter_mut().enumerate() {
                    ui.label(None, &format!("{}", name));
                    ui.same_line(120.0);

                    match uniform {
                        Uniform::Float1(x) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(200.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            if let Ok(x) = x.parse::<f32>() {
                                material.set_uniform(name, x);
                            }
                        }
                        Uniform::Float2(x, y) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(99.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(99.0, 19.0))
                                .filter_numbers()
                                .ui(ui, y);

                            if let (Ok(x), Ok(y)) = (x.parse::<f32>(), y.parse::<f32>()) {
                                material.set_uniform(name, (x, y));
                            }
                        }
                        Uniform::Float3(x, y, z) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, y);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, z);

                            if let (Ok(x), Ok(y), Ok(z)) =
                                (x.parse::<f32>(), y.parse::<f32>(), z.parse::<f32>())
                            {
                                material.set_uniform(name, (x, y, z));
                            }
                        }

                        Uniform::Color(color) => {
                            let mut canvas = ui.canvas();

                            let cursor = canvas.cursor();

                            canvas.rect(
                                Rect::new(cursor.x + 20.0, cursor.y, 50.0, 18.0),
                                Color::new(0.2, 0.2, 0.2, 1.0),
                                Color::new(color.x, color.y, color.z, 1.0),
                            );

                            if ui.button(None, "change") {
                                colorpicker_window = true;
                                color_picking_uniform = Some(name.to_owned());
                            }
                            material.set_uniform(name, (color.x, color.y, color.z));
                        }
                    }
                }
                ui.separator();
                if ui.button(None, "New uniform") {
                    new_uniform_window = true;
                }
                TreeNode::new(hash!(), "Fragment shader")
                    .init_unfolded()
                    .ui(ui, |ui| {
                        if ui.editbox(hash!(), vec2(440., 200.), &mut fragment_shader) {
                            need_update = true;
                        };
                    });
                ui.tree_node(hash!(), "Vertex shader", |ui| {
                    if ui.editbox(hash!(), vec2(440., 300.), &mut vertex_shader) {
                        need_update = true;
                    };
                });

                if let Some(ref error) = error {
                    Label::new(error).multiline(14.0).ui(ui);
                }
            });

        if new_uniform_window {
            widgets::Window::new(hash!(), vec2(100., 100.), vec2(200., 80.))
                .label("New uniform")
                .ui(&mut *root_ui(), |ui| {
                    if ui.active_window_focused() == false {
                        new_uniform_window = false;
                    }
                    ui.input_text(hash!(), "Name", &mut new_uniform_name);
                    let uniform_type = ui.combo_box(
                        hash!(),
                        "Type",
                        &["Float1", "Float2", "Float3", "Color"],
                        None,
                    );

                    if ui.button(None, "Add") {
                        if new_uniform_name.is_empty() == false {
                            let uniform = match uniform_type {
                                0 => Uniform::Float1("0".to_string()),
                                1 => Uniform::Float2("0".to_string(), "0".to_string()),
                                2 => Uniform::Float3(
                                    "0".to_string(),
                                    "0".to_string(),
                                    "0".to_string(),
                                ),
                                3 => Uniform::Color(vec3(0.0, 0.0, 0.0)),
                                _ => unreachable!(),
                            };
                            uniforms.push((new_uniform_name.clone(), uniform));
                            new_uniform_name.clear();
                            need_update = true;
                        }
                        new_uniform_window = false;
                    }

                    ui.same_line(0.0);
                    if ui.button(None, "Cancel") {
                        new_uniform_window = false;
                    }
                });
        }

        if colorpicker_window {
            colorpicker_window &= widgets::Window::new(hash!(), vec2(140., 100.), vec2(210., 240.))
                .label("Colorpicker")
                .ui(&mut *root_ui(), |ui| {
                    if ui.active_window_focused() == false {
                        colorpicker_window = false;
                    }

                    let mut canvas = ui.canvas();
                    let cursor = canvas.cursor();
                    let mouse = mouse_position();
                    let x = mouse.0 as i32 - cursor.x as i32;
                    let y = mouse.1 as i32 - (cursor.y as i32 + 20);

                    let color = color_picker_image
                        .get_pixel(x.max(0).min(199) as u32, y.max(0).min(199) as u32);

                    canvas.rect(
                        Rect::new(cursor.x, cursor.y, 200.0, 18.0),
                        Color::new(0.0, 0.0, 0.0, 1.0),
                        Color::new(color.r, color.g, color.b, 1.0),
                    );
                    canvas.image(
                        Rect::new(cursor.x, cursor.y + 20.0, 200.0, 200.0),
                        &color_picker_texture,
                    );

                    if x >= 0 && x < 200 && y >= 0 && y < 200 {
                        canvas.rect(
                            Rect::new(mouse.0 - 3.5, mouse.1 - 3.5, 7.0, 7.0),
                            Color::new(0.3, 0.3, 0.3, 1.0),
                            Color::new(1.0, 1.0, 1.0, 1.0),
                        );

                        if is_mouse_button_down(MouseButton::Left) {
                            colorpicker_window = false;
                            let uniform_name = color_picking_uniform.take().unwrap();

                            uniforms
                                .iter_mut()
                                .find(|(name, _)| name == &uniform_name)
                                .unwrap()
                                .1 = Uniform::Color(vec3(color.r, color.g, color.b));
                        }
                    }
                });
        }

        if need_update {
            let uniforms = uniforms
                .iter()
                .map(|(name, uniform)| (name.clone(), uniform.uniform_type()))
                .collect::<Vec<_>>();

            match load_material(
                ShaderSource::Glsl {
                    vertex: &vertex_shader,
                    fragment: &fragment_shader,
                },
                MaterialParams {
                    pipeline_params,
                    uniforms,
                    textures: vec![],
                },
            ) {
                Ok(new_material) => {
                    material = new_material;
                    error = None;
                }
                Err(err) => {
                    error = Some(format!("{:#?}", err));
                }
            }
        }

        next_frame().await
    }
}
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 212-224)
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
async fn main() {
    let skin1 = {
        let label_style = root_ui()
            .style_builder()
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 120, 255))
            .font_size(30)
            .build();

        let window_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/window_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(20.0, 20.0, 10.0, 10.0))
            .margin(RectOffset::new(-20.0, -30.0, 0.0, 0.0))
            .build();

        let button_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(37.0, 37.0, 5.0, 5.0))
            .margin(RectOffset::new(10.0, 10.0, 0.0, 0.0))
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_hovered_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_clicked_background.png"),
                    None,
                )
                .unwrap(),
            )
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 100, 255))
            .font_size(40)
            .build();

        let editbox_style = root_ui()
            .style_builder()
            .background_margin(RectOffset::new(0., 0., 0., 0.))
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .color_selected(Color::from_rgba(190, 190, 190, 255))
            .font_size(50)
            .build();

        Skin {
            editbox_style,
            window_style,
            button_style,
            label_style,
            ..root_ui().default_skin()
        }
    };

    let skin2 = {
        let label_style = root_ui()
            .style_builder()
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .font_size(25)
            .build();

        let window_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/window_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(52.0, 52.0, 52.0, 52.0))
            .margin(RectOffset::new(-30.0, 0.0, -30.0, 0.0))
            .build();

        let button_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(8.0, 8.0, 8.0, 8.0))
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_hovered_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_clicked_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 100, 255))
            .font_size(40)
            .build();

        let checkbox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_hovered_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_clicked_background.png"),
                    None,
                )
                .unwrap(),
            )
            .build();

        let editbox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/editbox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(2., 2., 2., 2.))
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .font_size(25)
            .build();

        let combobox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/combobox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(4., 25., 6., 6.))
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .color(Color::from_rgba(210, 210, 210, 255))
            .font_size(25)
            .build();

        Skin {
            window_style,
            button_style,
            label_style,
            checkbox_style,
            editbox_style,
            combobox_style,
            ..root_ui().default_skin()
        }
    };
    let default_skin = root_ui().default_skin().clone();

    let mut window1_skin = skin1.clone();
    let mut window2_skin = skin2.clone();

    let mut checkbox = false;
    let mut text = String::new();
    let mut number = 0.0f32;
    let mut combobox = 0;

    loop {
        clear_background(GRAY);

        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
            ui.label(None, "Window 1");

            if ui.button(None, "Skin 1") {
                window1_skin = skin1.clone();
            }
            if ui.button(None, "Skin 2") {
                window1_skin = skin2.clone();
            }
            if ui.button(None, "No Skin") {
                window1_skin = default_skin.clone();
            }
        });
        root_ui().same_line(0.);
        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
            ui.label(None, "Window 2");
            if ui.button(None, "Skin 1") {
                window2_skin = skin1.clone();
            }
            if ui.button(None, "Skin 2") {
                window2_skin = skin2.clone();
            }
            if ui.button(None, "No Skin") {
                window2_skin = default_skin.clone();
            }
        });

        root_ui().push_skin(&window1_skin);

        root_ui().window(hash!(), vec2(20., 250.), vec2(300., 300.), |ui| {
            widgets::Button::new("Play")
                .position(vec2(65.0, 15.0))
                .ui(ui);
            widgets::Button::new("Options")
                .position(vec2(40.0, 75.0))
                .ui(ui);

            widgets::Button::new("Quit")
                .position(vec2(65.0, 195.0))
                .ui(ui);
        });
        root_ui().pop_skin();

        root_ui().push_skin(&window2_skin);
        root_ui().window(hash!(), vec2(250., 20.), vec2(500., 250.), |ui| {
            ui.checkbox(hash!(), "Checkbox 1", &mut checkbox);
            ui.combo_box(
                hash!(),
                "Combobox",
                &["First option", "Second option"],
                &mut combobox,
            );
            ui.input_text(hash!(), "Text", &mut text);
            ui.drag(hash!(), "Drag", None, &mut number);

            widgets::Button::new("Apply")
                .position(vec2(80.0, 150.0))
                .ui(ui);
            widgets::Button::new("Cancel")
                .position(vec2(280.0, 150.0))
                .ui(ui);
        });
        root_ui().pop_skin();

        next_frame().await;
    }
}
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)
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
async fn main() {
    let mut data = Data::new();

    let mut data0 = String::new();
    let mut data1 = String::new();

    let mut text0 = String::new();
    let mut text1 = String::new();

    let mut number0 = 0.;
    let mut number1 = 0.;

    let texture: Texture2D = load_texture("examples/ferris.png").await.unwrap();

    loop {
        clear_background(WHITE);

        widgets::Window::new(hash!(), vec2(400., 200.), vec2(320., 400.))
            .label("Shop")
            .titlebar(true)
            .ui(&mut *root_ui(), |ui| {
                for i in 0..30 {
                    Group::new(hash!("shop", i), Vec2::new(300., 80.)).ui(ui, |ui| {
                        ui.label(Vec2::new(10., 10.), &format!("Item N {}", i));
                        ui.label(Vec2::new(260., 40.), "10/10");
                        ui.label(Vec2::new(200., 58.), &format!("{} kr", 800));
                        if ui.button(Vec2::new(260., 55.), "buy") {
                            data.inventory.push(format!("Item {}", i));
                        }
                    });
                }
            });

        widgets::Window::new(hash!(), vec2(100., 220.), vec2(542., 430.))
            .label("Fitting window")
            .titlebar(true)
            .ui(&mut *root_ui(), |ui| {
                Group::new(hash!(), Vec2::new(230., 400.)).ui(ui, |ui| {
                    data.slots(ui);
                });
                Group::new(hash!(), Vec2::new(280., 400.)).ui(ui, |ui| {
                    data.inventory(ui);
                });
            });

        widgets::Window::new(hash!(), vec2(470., 50.), vec2(300., 300.))
            .label("Megaui Showcase Window")
            .ui(&mut *root_ui(), |ui| {
                ui.tree_node(hash!(), "input", |ui| {
                    ui.label(None, "Some random text");
                    if ui.button(None, "click me") {
                        println!("hi");
                    }

                    ui.separator();

                    ui.label(None, "Some other random text");
                    if ui.button(None, "other button") {
                        println!("hi2");
                    }

                    ui.separator();

                    ui.input_text(hash!(), "<- input text 1", &mut data0);
                    ui.input_text(hash!(), "<- input text 2", &mut data1);
                    ui.label(
                        None,
                        &format!("Text entered: \"{}\" and \"{}\"", data0, data1),
                    );

                    ui.separator();
                });
                ui.tree_node(hash!(), "buttons", |ui| {
                    widgets::Button::new(texture.clone())
                        .size(vec2(120., 70.))
                        .ui(ui);
                    ui.same_line(0.);
                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
                    ui.same_line(0.);
                    widgets::Button::new(texture.clone())
                        .size(vec2(120., 70.))
                        .ui(ui);
                });
                ui.tree_node(hash!(), "sliders", |ui| {
                    ui.slider(hash!(), "[-10 .. 10]", -10f32..10f32, &mut number0);
                    ui.slider(hash!(), "[0 .. 100]", 0f32..100f32, &mut number1);
                });
                ui.tree_node(hash!(), "editbox 1", |ui| {
                    ui.label(None, "This is editbox!");
                    ui.editbox(hash!(), vec2(285., 165.), &mut text0);
                });
                ui.tree_node(hash!(), "editbox 2", |ui| {
                    ui.label(None, "This is editbox!");
                    ui.editbox(hash!(), vec2(285., 165.), &mut text1);
                });
            });

        match data.fit_command.take() {
            Some(FittingCommand::Unfit { target_slot }) => data.set_item(target_slot, None),
            Some(FittingCommand::Fit { target_slot, item }) => {
                data.set_item(target_slot, Some(item));
            }
            Some(FittingCommand::Refit {
                target_slot,
                origin_slot,
            }) => {
                let origin_item = data
                    .slots
                    .iter()
                    .find_map(|(_, slot)| {
                        if slot.id == origin_slot {
                            Some(slot.item.clone())
                        } else {
                            None
                        }
                    })
                    .flatten();
                data.set_item(target_slot, origin_item);
                data.set_item(origin_slot, None);
            }
            None => {}
        };

        next_frame().await;
    }
}
More examples
Hide additional examples
examples/ui_skins.rs (line 264)
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
async fn main() {
    let skin1 = {
        let label_style = root_ui()
            .style_builder()
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 120, 255))
            .font_size(30)
            .build();

        let window_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/window_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(20.0, 20.0, 10.0, 10.0))
            .margin(RectOffset::new(-20.0, -30.0, 0.0, 0.0))
            .build();

        let button_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(37.0, 37.0, 5.0, 5.0))
            .margin(RectOffset::new(10.0, 10.0, 0.0, 0.0))
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_hovered_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_clicked_background.png"),
                    None,
                )
                .unwrap(),
            )
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 100, 255))
            .font_size(40)
            .build();

        let editbox_style = root_ui()
            .style_builder()
            .background_margin(RectOffset::new(0., 0., 0., 0.))
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .color_selected(Color::from_rgba(190, 190, 190, 255))
            .font_size(50)
            .build();

        Skin {
            editbox_style,
            window_style,
            button_style,
            label_style,
            ..root_ui().default_skin()
        }
    };

    let skin2 = {
        let label_style = root_ui()
            .style_builder()
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .font_size(25)
            .build();

        let window_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/window_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(52.0, 52.0, 52.0, 52.0))
            .margin(RectOffset::new(-30.0, 0.0, -30.0, 0.0))
            .build();

        let button_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(8.0, 8.0, 8.0, 8.0))
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_hovered_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_clicked_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 100, 255))
            .font_size(40)
            .build();

        let checkbox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_hovered_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_clicked_background.png"),
                    None,
                )
                .unwrap(),
            )
            .build();

        let editbox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/editbox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(2., 2., 2., 2.))
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .font_size(25)
            .build();

        let combobox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/combobox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(4., 25., 6., 6.))
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .color(Color::from_rgba(210, 210, 210, 255))
            .font_size(25)
            .build();

        Skin {
            window_style,
            button_style,
            label_style,
            checkbox_style,
            editbox_style,
            combobox_style,
            ..root_ui().default_skin()
        }
    };
    let default_skin = root_ui().default_skin().clone();

    let mut window1_skin = skin1.clone();
    let mut window2_skin = skin2.clone();

    let mut checkbox = false;
    let mut text = String::new();
    let mut number = 0.0f32;
    let mut combobox = 0;

    loop {
        clear_background(GRAY);

        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
            ui.label(None, "Window 1");

            if ui.button(None, "Skin 1") {
                window1_skin = skin1.clone();
            }
            if ui.button(None, "Skin 2") {
                window1_skin = skin2.clone();
            }
            if ui.button(None, "No Skin") {
                window1_skin = default_skin.clone();
            }
        });
        root_ui().same_line(0.);
        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
            ui.label(None, "Window 2");
            if ui.button(None, "Skin 1") {
                window2_skin = skin1.clone();
            }
            if ui.button(None, "Skin 2") {
                window2_skin = skin2.clone();
            }
            if ui.button(None, "No Skin") {
                window2_skin = default_skin.clone();
            }
        });

        root_ui().push_skin(&window1_skin);

        root_ui().window(hash!(), vec2(20., 250.), vec2(300., 300.), |ui| {
            widgets::Button::new("Play")
                .position(vec2(65.0, 15.0))
                .ui(ui);
            widgets::Button::new("Options")
                .position(vec2(40.0, 75.0))
                .ui(ui);

            widgets::Button::new("Quit")
                .position(vec2(65.0, 195.0))
                .ui(ui);
        });
        root_ui().pop_skin();

        root_ui().push_skin(&window2_skin);
        root_ui().window(hash!(), vec2(250., 20.), vec2(500., 250.), |ui| {
            ui.checkbox(hash!(), "Checkbox 1", &mut checkbox);
            ui.combo_box(
                hash!(),
                "Combobox",
                &["First option", "Second option"],
                &mut combobox,
            );
            ui.input_text(hash!(), "Text", &mut text);
            ui.drag(hash!(), "Drag", None, &mut number);

            widgets::Button::new("Apply")
                .position(vec2(80.0, 150.0))
                .ui(ui);
            widgets::Button::new("Cancel")
                .position(vec2(280.0, 150.0))
                .ui(ui);
        });
        root_ui().pop_skin();

        next_frame().await;
    }
}
examples/shadertoy.rs (line 254)
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
async fn main() {
    let ferris = load_texture("examples/rust.png").await.unwrap();
    let (color_picker_texture, color_picker_image) = color_picker_texture(200, 200);

    let mut fragment_shader = DEFAULT_FRAGMENT_SHADER.to_string();
    let mut vertex_shader = DEFAULT_VERTEX_SHADER.to_string();

    let pipeline_params = PipelineParams {
        depth_write: true,
        depth_test: Comparison::LessOrEqual,
        ..Default::default()
    };

    let mut material = load_material(
        ShaderSource::Glsl {
            vertex: &vertex_shader,
            fragment: &fragment_shader,
        },
        MaterialParams {
            pipeline_params,
            ..Default::default()
        },
    )
    .unwrap();
    let mut error: Option<String> = None;

    enum Mesh {
        Sphere,
        Cube,
        Plane,
    }
    let mut mesh = Mesh::Sphere;

    let mut camera = Camera3D {
        position: vec3(-15., 15., -5.),
        up: vec3(0., 1., 0.),
        target: vec3(0., 5., -5.),
        ..Default::default()
    };

    let mut colorpicker_window = false;
    let mut color_picking_uniform = None;

    let mut new_uniform_window = false;
    let mut new_uniform_name = String::new();
    let mut uniforms: Vec<(String, Uniform)> = vec![];

    loop {
        clear_background(WHITE);

        set_camera(&camera);

        draw_grid(
            20,
            1.,
            Color::new(0.55, 0.55, 0.55, 0.75),
            Color::new(0.75, 0.75, 0.75, 0.75),
        );

        gl_use_material(&material);
        match mesh {
            Mesh::Plane => draw_plane(vec3(0., 2., 0.), vec2(5., 5.), Some(&ferris), WHITE),
            Mesh::Sphere => draw_sphere(vec3(0., 6., 0.), 5., Some(&ferris), WHITE),
            Mesh::Cube => draw_cube(vec3(0., 5., 0.), vec3(10., 10., 10.), Some(&ferris), WHITE),
        }
        gl_use_default_material();

        set_default_camera();

        let mut need_update = false;

        widgets::Window::new(hash!(), vec2(20., 20.), vec2(470., 650.))
            .label("Shader")
            .ui(&mut *root_ui(), |ui| {
                ui.label(None, "Camera: ");
                ui.same_line(0.0);
                if ui.button(None, "Ortho") {
                    camera.projection = Projection::Orthographics;
                }
                ui.same_line(0.0);
                if ui.button(None, "Perspective") {
                    camera.projection = Projection::Perspective;
                }
                ui.label(None, "Mesh: ");
                ui.same_line(0.0);
                if ui.button(None, "Sphere") {
                    mesh = Mesh::Sphere;
                }
                ui.same_line(0.0);
                if ui.button(None, "Cube") {
                    mesh = Mesh::Cube;
                }
                ui.same_line(0.0);
                if ui.button(None, "Plane") {
                    mesh = Mesh::Plane;
                }

                ui.label(None, "Uniforms:");
                ui.separator();

                for (i, (name, uniform)) in uniforms.iter_mut().enumerate() {
                    ui.label(None, &format!("{}", name));
                    ui.same_line(120.0);

                    match uniform {
                        Uniform::Float1(x) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(200.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            if let Ok(x) = x.parse::<f32>() {
                                material.set_uniform(name, x);
                            }
                        }
                        Uniform::Float2(x, y) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(99.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(99.0, 19.0))
                                .filter_numbers()
                                .ui(ui, y);

                            if let (Ok(x), Ok(y)) = (x.parse::<f32>(), y.parse::<f32>()) {
                                material.set_uniform(name, (x, y));
                            }
                        }
                        Uniform::Float3(x, y, z) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, y);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, z);

                            if let (Ok(x), Ok(y), Ok(z)) =
                                (x.parse::<f32>(), y.parse::<f32>(), z.parse::<f32>())
                            {
                                material.set_uniform(name, (x, y, z));
                            }
                        }

                        Uniform::Color(color) => {
                            let mut canvas = ui.canvas();

                            let cursor = canvas.cursor();

                            canvas.rect(
                                Rect::new(cursor.x + 20.0, cursor.y, 50.0, 18.0),
                                Color::new(0.2, 0.2, 0.2, 1.0),
                                Color::new(color.x, color.y, color.z, 1.0),
                            );

                            if ui.button(None, "change") {
                                colorpicker_window = true;
                                color_picking_uniform = Some(name.to_owned());
                            }
                            material.set_uniform(name, (color.x, color.y, color.z));
                        }
                    }
                }
                ui.separator();
                if ui.button(None, "New uniform") {
                    new_uniform_window = true;
                }
                TreeNode::new(hash!(), "Fragment shader")
                    .init_unfolded()
                    .ui(ui, |ui| {
                        if ui.editbox(hash!(), vec2(440., 200.), &mut fragment_shader) {
                            need_update = true;
                        };
                    });
                ui.tree_node(hash!(), "Vertex shader", |ui| {
                    if ui.editbox(hash!(), vec2(440., 300.), &mut vertex_shader) {
                        need_update = true;
                    };
                });

                if let Some(ref error) = error {
                    Label::new(error).multiline(14.0).ui(ui);
                }
            });

        if new_uniform_window {
            widgets::Window::new(hash!(), vec2(100., 100.), vec2(200., 80.))
                .label("New uniform")
                .ui(&mut *root_ui(), |ui| {
                    if ui.active_window_focused() == false {
                        new_uniform_window = false;
                    }
                    ui.input_text(hash!(), "Name", &mut new_uniform_name);
                    let uniform_type = ui.combo_box(
                        hash!(),
                        "Type",
                        &["Float1", "Float2", "Float3", "Color"],
                        None,
                    );

                    if ui.button(None, "Add") {
                        if new_uniform_name.is_empty() == false {
                            let uniform = match uniform_type {
                                0 => Uniform::Float1("0".to_string()),
                                1 => Uniform::Float2("0".to_string(), "0".to_string()),
                                2 => Uniform::Float3(
                                    "0".to_string(),
                                    "0".to_string(),
                                    "0".to_string(),
                                ),
                                3 => Uniform::Color(vec3(0.0, 0.0, 0.0)),
                                _ => unreachable!(),
                            };
                            uniforms.push((new_uniform_name.clone(), uniform));
                            new_uniform_name.clear();
                            need_update = true;
                        }
                        new_uniform_window = false;
                    }

                    ui.same_line(0.0);
                    if ui.button(None, "Cancel") {
                        new_uniform_window = false;
                    }
                });
        }

        if colorpicker_window {
            colorpicker_window &= widgets::Window::new(hash!(), vec2(140., 100.), vec2(210., 240.))
                .label("Colorpicker")
                .ui(&mut *root_ui(), |ui| {
                    if ui.active_window_focused() == false {
                        colorpicker_window = false;
                    }

                    let mut canvas = ui.canvas();
                    let cursor = canvas.cursor();
                    let mouse = mouse_position();
                    let x = mouse.0 as i32 - cursor.x as i32;
                    let y = mouse.1 as i32 - (cursor.y as i32 + 20);

                    let color = color_picker_image
                        .get_pixel(x.max(0).min(199) as u32, y.max(0).min(199) as u32);

                    canvas.rect(
                        Rect::new(cursor.x, cursor.y, 200.0, 18.0),
                        Color::new(0.0, 0.0, 0.0, 1.0),
                        Color::new(color.r, color.g, color.b, 1.0),
                    );
                    canvas.image(
                        Rect::new(cursor.x, cursor.y + 20.0, 200.0, 200.0),
                        &color_picker_texture,
                    );

                    if x >= 0 && x < 200 && y >= 0 && y < 200 {
                        canvas.rect(
                            Rect::new(mouse.0 - 3.5, mouse.1 - 3.5, 7.0, 7.0),
                            Color::new(0.3, 0.3, 0.3, 1.0),
                            Color::new(1.0, 1.0, 1.0, 1.0),
                        );

                        if is_mouse_button_down(MouseButton::Left) {
                            colorpicker_window = false;
                            let uniform_name = color_picking_uniform.take().unwrap();

                            uniforms
                                .iter_mut()
                                .find(|(name, _)| name == &uniform_name)
                                .unwrap()
                                .1 = Uniform::Color(vec3(color.r, color.g, color.b));
                        }
                    }
                });
        }

        if need_update {
            let uniforms = uniforms
                .iter()
                .map(|(name, uniform)| (name.clone(), uniform.uniform_type()))
                .collect::<Vec<_>>();

            match load_material(
                ShaderSource::Glsl {
                    vertex: &vertex_shader,
                    fragment: &fragment_shader,
                },
                MaterialParams {
                    pipeline_params,
                    uniforms,
                    textures: vec![],
                },
            ) {
                Ok(new_material) => {
                    material = new_material;
                    error = None;
                }
                Err(err) => {
                    error = Some(format!("{:#?}", err));
                }
            }
        }

        next_frame().await
    }
}
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)
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
async fn main() {
    prevent_quit();

    let mut show_exit_dialog = false;
    let mut user_decided_to_exit = false;

    loop {
        clear_background(GRAY);

        if is_quit_requested() {
            show_exit_dialog = true;
        }

        if show_exit_dialog {
            let dialog_size = vec2(200., 70.);
            let screen_size = vec2(screen_width(), screen_height());
            let dialog_position = screen_size / 2. - dialog_size / 2.;
            Window::new(hash!(), dialog_position, dialog_size).ui(&mut *root_ui(), |ui| {
                ui.label(None, "Do you really want to quit?");
                ui.separator();
                ui.same_line(60.);
                if ui.button(None, "Yes") {
                    user_decided_to_exit = true;
                }
                ui.same_line(120.);
                if ui.button(None, "No") {
                    show_exit_dialog = false;
                }
            });
        }

        if user_decided_to_exit {
            break;
        }

        next_frame().await
    }
}
More examples
Hide additional examples
examples/events.rs (line 11)
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
async fn main() {
    loop {
        clear_background(WHITE);
        root_ui().window(hash!(), Vec2::new(20., 20.), Vec2::new(450., 200.), |ui| {
            let (mouse_x, mouse_y) = mouse_position();
            ui.label(None, &format!("Mouse position: {} {}", mouse_x, mouse_y));

            let (mouse_wheel_x, mouse_wheel_y) = mouse_wheel();
            ui.label(None, &format!("Mouse wheel x: {}", mouse_wheel_x));
            ui.label(None, &format!("Mouse wheel y: {}", mouse_wheel_y));

            widgets::Group::new(hash!(), Vec2::new(200., 90.))
                .position(Vec2::new(240., 0.))
                .ui(ui, |ui| {
                    ui.label(None, "Pressed kbd keys");

                    if let Some(key) = get_last_key_pressed() {
                        ui.label(None, &format!("{:?}", key))
                    }
                });

            widgets::Group::new(hash!(), Vec2::new(200., 90.))
                .position(Vec2::new(240., 92.))
                .ui(ui, |ui| {
                    ui.label(None, "Pressed mouse keys");

                    if is_mouse_button_down(MouseButton::Left) {
                        ui.label(None, "Left");
                    }
                    if is_mouse_button_down(MouseButton::Right) {
                        ui.label(None, "Right");
                    }
                    if is_mouse_button_down(MouseButton::Middle) {
                        ui.label(None, "Middle");
                    }
                });
        });
        next_frame().await;
    }
}
examples/ui.rs (line 67)
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
    fn slots(&mut self, ui: &mut Ui) {
        let item_dragging = &mut self.item_dragging;

        let fit_command = &mut self.fit_command;
        for (label, slot) in self.slots.iter_mut() {
            Group::new(hash!("grp", slot.id, &label), Vec2::new(210., 55.)).ui(ui, |ui| {
                let drag = Group::new(slot.id, Vec2::new(50., 50.))
                    // slot without item is not draggable
                    .draggable(slot.item.is_some())
                    // but could be a target of drag
                    .hoverable(*item_dragging)
                    // and is highlighted with other color when some item is dragging
                    .highlight(*item_dragging)
                    .ui(ui, |ui| {
                        if let Some(ref item) = slot.item {
                            ui.label(Vec2::new(5., 10.), &item);
                        }
                    });

                match drag {
                    // there is some item in this slot and it was dragged to another slot
                    Drag::Dropped(_, Some(id)) if slot.item.is_some() => {
                        *fit_command = Some(FittingCommand::Refit {
                            target_slot: id,
                            origin_slot: slot.id,
                        });
                    }
                    // there is some item in this slot and it was dragged out - unfit it
                    Drag::Dropped(_, None) if slot.item.is_some() => {
                        *fit_command = Some(FittingCommand::Unfit {
                            target_slot: slot.id,
                        });
                    }
                    // there is no item in this slot
                    // this is impossible - slots without items are non-draggable
                    Drag::Dropped(_, _) => unreachable!(),
                    Drag::Dragging(pos, id) => {
                        debug!("slots: pos: {:?}, id {:?}", pos, id);
                        *item_dragging = true;
                    }
                    Drag::No => {}
                }
                ui.label(Vec2::new(60., 20.), label);
            });
        }
    }

    fn inventory(&mut self, ui: &mut Ui) {
        let item_dragging = &mut self.item_dragging;
        for (n, item) in self.inventory.iter().enumerate() {
            let drag = Group::new(hash!("inventory", n), Vec2::new(50., 50.))
                .draggable(true)
                .ui(ui, |ui| {
                    ui.label(Vec2::new(5., 10.), &item);
                });

            match drag {
                Drag::Dropped(_, Some(id)) => {
                    self.fit_command = Some(FittingCommand::Fit {
                        target_slot: id,
                        item: item.clone(),
                    });
                    *item_dragging = false;
                }
                Drag::Dropped(_, _) => {
                    *item_dragging = false;
                }
                Drag::Dragging(pos, id) => {
                    debug!("inventory: pos: {:?}, id {:?}", pos, id);
                    *item_dragging = true;
                }
                _ => {}
            }
        }
    }

    fn set_item(&mut self, id: u64, item: Option<String>) {
        if let Some(slot) = self.slots.iter_mut().find(|(_, slot)| slot.id == id) {
            slot.1.item = item;
        }
    }
}

#[macroquad::main("UI showcase")]
async fn main() {
    let mut data = Data::new();

    let mut data0 = String::new();
    let mut data1 = String::new();

    let mut text0 = String::new();
    let mut text1 = String::new();

    let mut number0 = 0.;
    let mut number1 = 0.;

    let texture: Texture2D = load_texture("examples/ferris.png").await.unwrap();

    loop {
        clear_background(WHITE);

        widgets::Window::new(hash!(), vec2(400., 200.), vec2(320., 400.))
            .label("Shop")
            .titlebar(true)
            .ui(&mut *root_ui(), |ui| {
                for i in 0..30 {
                    Group::new(hash!("shop", i), Vec2::new(300., 80.)).ui(ui, |ui| {
                        ui.label(Vec2::new(10., 10.), &format!("Item N {}", i));
                        ui.label(Vec2::new(260., 40.), "10/10");
                        ui.label(Vec2::new(200., 58.), &format!("{} kr", 800));
                        if ui.button(Vec2::new(260., 55.), "buy") {
                            data.inventory.push(format!("Item {}", i));
                        }
                    });
                }
            });

        widgets::Window::new(hash!(), vec2(100., 220.), vec2(542., 430.))
            .label("Fitting window")
            .titlebar(true)
            .ui(&mut *root_ui(), |ui| {
                Group::new(hash!(), Vec2::new(230., 400.)).ui(ui, |ui| {
                    data.slots(ui);
                });
                Group::new(hash!(), Vec2::new(280., 400.)).ui(ui, |ui| {
                    data.inventory(ui);
                });
            });

        widgets::Window::new(hash!(), vec2(470., 50.), vec2(300., 300.))
            .label("Megaui Showcase Window")
            .ui(&mut *root_ui(), |ui| {
                ui.tree_node(hash!(), "input", |ui| {
                    ui.label(None, "Some random text");
                    if ui.button(None, "click me") {
                        println!("hi");
                    }

                    ui.separator();

                    ui.label(None, "Some other random text");
                    if ui.button(None, "other button") {
                        println!("hi2");
                    }

                    ui.separator();

                    ui.input_text(hash!(), "<- input text 1", &mut data0);
                    ui.input_text(hash!(), "<- input text 2", &mut data1);
                    ui.label(
                        None,
                        &format!("Text entered: \"{}\" and \"{}\"", data0, data1),
                    );

                    ui.separator();
                });
                ui.tree_node(hash!(), "buttons", |ui| {
                    widgets::Button::new(texture.clone())
                        .size(vec2(120., 70.))
                        .ui(ui);
                    ui.same_line(0.);
                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
                    ui.same_line(0.);
                    widgets::Button::new(texture.clone())
                        .size(vec2(120., 70.))
                        .ui(ui);
                });
                ui.tree_node(hash!(), "sliders", |ui| {
                    ui.slider(hash!(), "[-10 .. 10]", -10f32..10f32, &mut number0);
                    ui.slider(hash!(), "[0 .. 100]", 0f32..100f32, &mut number1);
                });
                ui.tree_node(hash!(), "editbox 1", |ui| {
                    ui.label(None, "This is editbox!");
                    ui.editbox(hash!(), vec2(285., 165.), &mut text0);
                });
                ui.tree_node(hash!(), "editbox 2", |ui| {
                    ui.label(None, "This is editbox!");
                    ui.editbox(hash!(), vec2(285., 165.), &mut text1);
                });
            });

        match data.fit_command.take() {
            Some(FittingCommand::Unfit { target_slot }) => data.set_item(target_slot, None),
            Some(FittingCommand::Fit { target_slot, item }) => {
                data.set_item(target_slot, Some(item));
            }
            Some(FittingCommand::Refit {
                target_slot,
                origin_slot,
            }) => {
                let origin_item = data
                    .slots
                    .iter()
                    .find_map(|(_, slot)| {
                        if slot.id == origin_slot {
                            Some(slot.item.clone())
                        } else {
                            None
                        }
                    })
                    .flatten();
                data.set_item(target_slot, origin_item);
                data.set_item(origin_slot, None);
            }
            None => {}
        };

        next_frame().await;
    }
}
examples/ui_skins.rs (line 213)
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
async fn main() {
    let skin1 = {
        let label_style = root_ui()
            .style_builder()
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 120, 255))
            .font_size(30)
            .build();

        let window_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/window_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(20.0, 20.0, 10.0, 10.0))
            .margin(RectOffset::new(-20.0, -30.0, 0.0, 0.0))
            .build();

        let button_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(37.0, 37.0, 5.0, 5.0))
            .margin(RectOffset::new(10.0, 10.0, 0.0, 0.0))
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_hovered_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_clicked_background.png"),
                    None,
                )
                .unwrap(),
            )
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 100, 255))
            .font_size(40)
            .build();

        let editbox_style = root_ui()
            .style_builder()
            .background_margin(RectOffset::new(0., 0., 0., 0.))
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .color_selected(Color::from_rgba(190, 190, 190, 255))
            .font_size(50)
            .build();

        Skin {
            editbox_style,
            window_style,
            button_style,
            label_style,
            ..root_ui().default_skin()
        }
    };

    let skin2 = {
        let label_style = root_ui()
            .style_builder()
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .font_size(25)
            .build();

        let window_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/window_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(52.0, 52.0, 52.0, 52.0))
            .margin(RectOffset::new(-30.0, 0.0, -30.0, 0.0))
            .build();

        let button_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(8.0, 8.0, 8.0, 8.0))
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_hovered_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_clicked_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 100, 255))
            .font_size(40)
            .build();

        let checkbox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_hovered_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_clicked_background.png"),
                    None,
                )
                .unwrap(),
            )
            .build();

        let editbox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/editbox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(2., 2., 2., 2.))
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .font_size(25)
            .build();

        let combobox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/combobox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(4., 25., 6., 6.))
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .color(Color::from_rgba(210, 210, 210, 255))
            .font_size(25)
            .build();

        Skin {
            window_style,
            button_style,
            label_style,
            checkbox_style,
            editbox_style,
            combobox_style,
            ..root_ui().default_skin()
        }
    };
    let default_skin = root_ui().default_skin().clone();

    let mut window1_skin = skin1.clone();
    let mut window2_skin = skin2.clone();

    let mut checkbox = false;
    let mut text = String::new();
    let mut number = 0.0f32;
    let mut combobox = 0;

    loop {
        clear_background(GRAY);

        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
            ui.label(None, "Window 1");

            if ui.button(None, "Skin 1") {
                window1_skin = skin1.clone();
            }
            if ui.button(None, "Skin 2") {
                window1_skin = skin2.clone();
            }
            if ui.button(None, "No Skin") {
                window1_skin = default_skin.clone();
            }
        });
        root_ui().same_line(0.);
        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
            ui.label(None, "Window 2");
            if ui.button(None, "Skin 1") {
                window2_skin = skin1.clone();
            }
            if ui.button(None, "Skin 2") {
                window2_skin = skin2.clone();
            }
            if ui.button(None, "No Skin") {
                window2_skin = default_skin.clone();
            }
        });

        root_ui().push_skin(&window1_skin);

        root_ui().window(hash!(), vec2(20., 250.), vec2(300., 300.), |ui| {
            widgets::Button::new("Play")
                .position(vec2(65.0, 15.0))
                .ui(ui);
            widgets::Button::new("Options")
                .position(vec2(40.0, 75.0))
                .ui(ui);

            widgets::Button::new("Quit")
                .position(vec2(65.0, 195.0))
                .ui(ui);
        });
        root_ui().pop_skin();

        root_ui().push_skin(&window2_skin);
        root_ui().window(hash!(), vec2(250., 20.), vec2(500., 250.), |ui| {
            ui.checkbox(hash!(), "Checkbox 1", &mut checkbox);
            ui.combo_box(
                hash!(),
                "Combobox",
                &["First option", "Second option"],
                &mut combobox,
            );
            ui.input_text(hash!(), "Text", &mut text);
            ui.drag(hash!(), "Drag", None, &mut number);

            widgets::Button::new("Apply")
                .position(vec2(80.0, 150.0))
                .ui(ui);
            widgets::Button::new("Cancel")
                .position(vec2(280.0, 150.0))
                .ui(ui);
        });
        root_ui().pop_skin();

        next_frame().await;
    }
}
examples/shadertoy.rs (line 121)
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
async fn main() {
    let ferris = load_texture("examples/rust.png").await.unwrap();
    let (color_picker_texture, color_picker_image) = color_picker_texture(200, 200);

    let mut fragment_shader = DEFAULT_FRAGMENT_SHADER.to_string();
    let mut vertex_shader = DEFAULT_VERTEX_SHADER.to_string();

    let pipeline_params = PipelineParams {
        depth_write: true,
        depth_test: Comparison::LessOrEqual,
        ..Default::default()
    };

    let mut material = load_material(
        ShaderSource::Glsl {
            vertex: &vertex_shader,
            fragment: &fragment_shader,
        },
        MaterialParams {
            pipeline_params,
            ..Default::default()
        },
    )
    .unwrap();
    let mut error: Option<String> = None;

    enum Mesh {
        Sphere,
        Cube,
        Plane,
    }
    let mut mesh = Mesh::Sphere;

    let mut camera = Camera3D {
        position: vec3(-15., 15., -5.),
        up: vec3(0., 1., 0.),
        target: vec3(0., 5., -5.),
        ..Default::default()
    };

    let mut colorpicker_window = false;
    let mut color_picking_uniform = None;

    let mut new_uniform_window = false;
    let mut new_uniform_name = String::new();
    let mut uniforms: Vec<(String, Uniform)> = vec![];

    loop {
        clear_background(WHITE);

        set_camera(&camera);

        draw_grid(
            20,
            1.,
            Color::new(0.55, 0.55, 0.55, 0.75),
            Color::new(0.75, 0.75, 0.75, 0.75),
        );

        gl_use_material(&material);
        match mesh {
            Mesh::Plane => draw_plane(vec3(0., 2., 0.), vec2(5., 5.), Some(&ferris), WHITE),
            Mesh::Sphere => draw_sphere(vec3(0., 6., 0.), 5., Some(&ferris), WHITE),
            Mesh::Cube => draw_cube(vec3(0., 5., 0.), vec3(10., 10., 10.), Some(&ferris), WHITE),
        }
        gl_use_default_material();

        set_default_camera();

        let mut need_update = false;

        widgets::Window::new(hash!(), vec2(20., 20.), vec2(470., 650.))
            .label("Shader")
            .ui(&mut *root_ui(), |ui| {
                ui.label(None, "Camera: ");
                ui.same_line(0.0);
                if ui.button(None, "Ortho") {
                    camera.projection = Projection::Orthographics;
                }
                ui.same_line(0.0);
                if ui.button(None, "Perspective") {
                    camera.projection = Projection::Perspective;
                }
                ui.label(None, "Mesh: ");
                ui.same_line(0.0);
                if ui.button(None, "Sphere") {
                    mesh = Mesh::Sphere;
                }
                ui.same_line(0.0);
                if ui.button(None, "Cube") {
                    mesh = Mesh::Cube;
                }
                ui.same_line(0.0);
                if ui.button(None, "Plane") {
                    mesh = Mesh::Plane;
                }

                ui.label(None, "Uniforms:");
                ui.separator();

                for (i, (name, uniform)) in uniforms.iter_mut().enumerate() {
                    ui.label(None, &format!("{}", name));
                    ui.same_line(120.0);

                    match uniform {
                        Uniform::Float1(x) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(200.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            if let Ok(x) = x.parse::<f32>() {
                                material.set_uniform(name, x);
                            }
                        }
                        Uniform::Float2(x, y) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(99.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(99.0, 19.0))
                                .filter_numbers()
                                .ui(ui, y);

                            if let (Ok(x), Ok(y)) = (x.parse::<f32>(), y.parse::<f32>()) {
                                material.set_uniform(name, (x, y));
                            }
                        }
                        Uniform::Float3(x, y, z) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, y);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, z);

                            if let (Ok(x), Ok(y), Ok(z)) =
                                (x.parse::<f32>(), y.parse::<f32>(), z.parse::<f32>())
                            {
                                material.set_uniform(name, (x, y, z));
                            }
                        }

                        Uniform::Color(color) => {
                            let mut canvas = ui.canvas();

                            let cursor = canvas.cursor();

                            canvas.rect(
                                Rect::new(cursor.x + 20.0, cursor.y, 50.0, 18.0),
                                Color::new(0.2, 0.2, 0.2, 1.0),
                                Color::new(color.x, color.y, color.z, 1.0),
                            );

                            if ui.button(None, "change") {
                                colorpicker_window = true;
                                color_picking_uniform = Some(name.to_owned());
                            }
                            material.set_uniform(name, (color.x, color.y, color.z));
                        }
                    }
                }
                ui.separator();
                if ui.button(None, "New uniform") {
                    new_uniform_window = true;
                }
                TreeNode::new(hash!(), "Fragment shader")
                    .init_unfolded()
                    .ui(ui, |ui| {
                        if ui.editbox(hash!(), vec2(440., 200.), &mut fragment_shader) {
                            need_update = true;
                        };
                    });
                ui.tree_node(hash!(), "Vertex shader", |ui| {
                    if ui.editbox(hash!(), vec2(440., 300.), &mut vertex_shader) {
                        need_update = true;
                    };
                });

                if let Some(ref error) = error {
                    Label::new(error).multiline(14.0).ui(ui);
                }
            });

        if new_uniform_window {
            widgets::Window::new(hash!(), vec2(100., 100.), vec2(200., 80.))
                .label("New uniform")
                .ui(&mut *root_ui(), |ui| {
                    if ui.active_window_focused() == false {
                        new_uniform_window = false;
                    }
                    ui.input_text(hash!(), "Name", &mut new_uniform_name);
                    let uniform_type = ui.combo_box(
                        hash!(),
                        "Type",
                        &["Float1", "Float2", "Float3", "Color"],
                        None,
                    );

                    if ui.button(None, "Add") {
                        if new_uniform_name.is_empty() == false {
                            let uniform = match uniform_type {
                                0 => Uniform::Float1("0".to_string()),
                                1 => Uniform::Float2("0".to_string(), "0".to_string()),
                                2 => Uniform::Float3(
                                    "0".to_string(),
                                    "0".to_string(),
                                    "0".to_string(),
                                ),
                                3 => Uniform::Color(vec3(0.0, 0.0, 0.0)),
                                _ => unreachable!(),
                            };
                            uniforms.push((new_uniform_name.clone(), uniform));
                            new_uniform_name.clear();
                            need_update = true;
                        }
                        new_uniform_window = false;
                    }

                    ui.same_line(0.0);
                    if ui.button(None, "Cancel") {
                        new_uniform_window = false;
                    }
                });
        }

        if colorpicker_window {
            colorpicker_window &= widgets::Window::new(hash!(), vec2(140., 100.), vec2(210., 240.))
                .label("Colorpicker")
                .ui(&mut *root_ui(), |ui| {
                    if ui.active_window_focused() == false {
                        colorpicker_window = false;
                    }

                    let mut canvas = ui.canvas();
                    let cursor = canvas.cursor();
                    let mouse = mouse_position();
                    let x = mouse.0 as i32 - cursor.x as i32;
                    let y = mouse.1 as i32 - (cursor.y as i32 + 20);

                    let color = color_picker_image
                        .get_pixel(x.max(0).min(199) as u32, y.max(0).min(199) as u32);

                    canvas.rect(
                        Rect::new(cursor.x, cursor.y, 200.0, 18.0),
                        Color::new(0.0, 0.0, 0.0, 1.0),
                        Color::new(color.r, color.g, color.b, 1.0),
                    );
                    canvas.image(
                        Rect::new(cursor.x, cursor.y + 20.0, 200.0, 200.0),
                        &color_picker_texture,
                    );

                    if x >= 0 && x < 200 && y >= 0 && y < 200 {
                        canvas.rect(
                            Rect::new(mouse.0 - 3.5, mouse.1 - 3.5, 7.0, 7.0),
                            Color::new(0.3, 0.3, 0.3, 1.0),
                            Color::new(1.0, 1.0, 1.0, 1.0),
                        );

                        if is_mouse_button_down(MouseButton::Left) {
                            colorpicker_window = false;
                            let uniform_name = color_picking_uniform.take().unwrap();

                            uniforms
                                .iter_mut()
                                .find(|(name, _)| name == &uniform_name)
                                .unwrap()
                                .1 = Uniform::Color(vec3(color.r, color.g, color.b));
                        }
                    }
                });
        }

        if need_update {
            let uniforms = uniforms
                .iter()
                .map(|(name, uniform)| (name.clone(), uniform.uniform_type()))
                .collect::<Vec<_>>();

            match load_material(
                ShaderSource::Glsl {
                    vertex: &vertex_shader,
                    fragment: &fragment_shader,
                },
                MaterialParams {
                    pipeline_params,
                    uniforms,
                    textures: vec![],
                },
            ) {
                Ok(new_material) => {
                    material = new_material;
                    error = None;
                }
                Err(err) => {
                    error = Some(format!("{:#?}", err));
                }
            }
        }

        next_frame().await
    }
}
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)
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
async fn main() {
    prevent_quit();

    let mut show_exit_dialog = false;
    let mut user_decided_to_exit = false;

    loop {
        clear_background(GRAY);

        if is_quit_requested() {
            show_exit_dialog = true;
        }

        if show_exit_dialog {
            let dialog_size = vec2(200., 70.);
            let screen_size = vec2(screen_width(), screen_height());
            let dialog_position = screen_size / 2. - dialog_size / 2.;
            Window::new(hash!(), dialog_position, dialog_size).ui(&mut *root_ui(), |ui| {
                ui.label(None, "Do you really want to quit?");
                ui.separator();
                ui.same_line(60.);
                if ui.button(None, "Yes") {
                    user_decided_to_exit = true;
                }
                ui.same_line(120.);
                if ui.button(None, "No") {
                    show_exit_dialog = false;
                }
            });
        }

        if user_decided_to_exit {
            break;
        }

        next_frame().await
    }
}
More examples
Hide additional examples
examples/ui.rs (line 190)
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
async fn main() {
    let mut data = Data::new();

    let mut data0 = String::new();
    let mut data1 = String::new();

    let mut text0 = String::new();
    let mut text1 = String::new();

    let mut number0 = 0.;
    let mut number1 = 0.;

    let texture: Texture2D = load_texture("examples/ferris.png").await.unwrap();

    loop {
        clear_background(WHITE);

        widgets::Window::new(hash!(), vec2(400., 200.), vec2(320., 400.))
            .label("Shop")
            .titlebar(true)
            .ui(&mut *root_ui(), |ui| {
                for i in 0..30 {
                    Group::new(hash!("shop", i), Vec2::new(300., 80.)).ui(ui, |ui| {
                        ui.label(Vec2::new(10., 10.), &format!("Item N {}", i));
                        ui.label(Vec2::new(260., 40.), "10/10");
                        ui.label(Vec2::new(200., 58.), &format!("{} kr", 800));
                        if ui.button(Vec2::new(260., 55.), "buy") {
                            data.inventory.push(format!("Item {}", i));
                        }
                    });
                }
            });

        widgets::Window::new(hash!(), vec2(100., 220.), vec2(542., 430.))
            .label("Fitting window")
            .titlebar(true)
            .ui(&mut *root_ui(), |ui| {
                Group::new(hash!(), Vec2::new(230., 400.)).ui(ui, |ui| {
                    data.slots(ui);
                });
                Group::new(hash!(), Vec2::new(280., 400.)).ui(ui, |ui| {
                    data.inventory(ui);
                });
            });

        widgets::Window::new(hash!(), vec2(470., 50.), vec2(300., 300.))
            .label("Megaui Showcase Window")
            .ui(&mut *root_ui(), |ui| {
                ui.tree_node(hash!(), "input", |ui| {
                    ui.label(None, "Some random text");
                    if ui.button(None, "click me") {
                        println!("hi");
                    }

                    ui.separator();

                    ui.label(None, "Some other random text");
                    if ui.button(None, "other button") {
                        println!("hi2");
                    }

                    ui.separator();

                    ui.input_text(hash!(), "<- input text 1", &mut data0);
                    ui.input_text(hash!(), "<- input text 2", &mut data1);
                    ui.label(
                        None,
                        &format!("Text entered: \"{}\" and \"{}\"", data0, data1),
                    );

                    ui.separator();
                });
                ui.tree_node(hash!(), "buttons", |ui| {
                    widgets::Button::new(texture.clone())
                        .size(vec2(120., 70.))
                        .ui(ui);
                    ui.same_line(0.);
                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
                    ui.same_line(0.);
                    widgets::Button::new(texture.clone())
                        .size(vec2(120., 70.))
                        .ui(ui);
                });
                ui.tree_node(hash!(), "sliders", |ui| {
                    ui.slider(hash!(), "[-10 .. 10]", -10f32..10f32, &mut number0);
                    ui.slider(hash!(), "[0 .. 100]", 0f32..100f32, &mut number1);
                });
                ui.tree_node(hash!(), "editbox 1", |ui| {
                    ui.label(None, "This is editbox!");
                    ui.editbox(hash!(), vec2(285., 165.), &mut text0);
                });
                ui.tree_node(hash!(), "editbox 2", |ui| {
                    ui.label(None, "This is editbox!");
                    ui.editbox(hash!(), vec2(285., 165.), &mut text1);
                });
            });

        match data.fit_command.take() {
            Some(FittingCommand::Unfit { target_slot }) => data.set_item(target_slot, None),
            Some(FittingCommand::Fit { target_slot, item }) => {
                data.set_item(target_slot, Some(item));
            }
            Some(FittingCommand::Refit {
                target_slot,
                origin_slot,
            }) => {
                let origin_item = data
                    .slots
                    .iter()
                    .find_map(|(_, slot)| {
                        if slot.id == origin_slot {
                            Some(slot.item.clone())
                        } else {
                            None
                        }
                    })
                    .flatten();
                data.set_item(target_slot, origin_item);
                data.set_item(origin_slot, None);
            }
            None => {}
        };

        next_frame().await;
    }
}
examples/shadertoy.rs (line 145)
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
async fn main() {
    let ferris = load_texture("examples/rust.png").await.unwrap();
    let (color_picker_texture, color_picker_image) = color_picker_texture(200, 200);

    let mut fragment_shader = DEFAULT_FRAGMENT_SHADER.to_string();
    let mut vertex_shader = DEFAULT_VERTEX_SHADER.to_string();

    let pipeline_params = PipelineParams {
        depth_write: true,
        depth_test: Comparison::LessOrEqual,
        ..Default::default()
    };

    let mut material = load_material(
        ShaderSource::Glsl {
            vertex: &vertex_shader,
            fragment: &fragment_shader,
        },
        MaterialParams {
            pipeline_params,
            ..Default::default()
        },
    )
    .unwrap();
    let mut error: Option<String> = None;

    enum Mesh {
        Sphere,
        Cube,
        Plane,
    }
    let mut mesh = Mesh::Sphere;

    let mut camera = Camera3D {
        position: vec3(-15., 15., -5.),
        up: vec3(0., 1., 0.),
        target: vec3(0., 5., -5.),
        ..Default::default()
    };

    let mut colorpicker_window = false;
    let mut color_picking_uniform = None;

    let mut new_uniform_window = false;
    let mut new_uniform_name = String::new();
    let mut uniforms: Vec<(String, Uniform)> = vec![];

    loop {
        clear_background(WHITE);

        set_camera(&camera);

        draw_grid(
            20,
            1.,
            Color::new(0.55, 0.55, 0.55, 0.75),
            Color::new(0.75, 0.75, 0.75, 0.75),
        );

        gl_use_material(&material);
        match mesh {
            Mesh::Plane => draw_plane(vec3(0., 2., 0.), vec2(5., 5.), Some(&ferris), WHITE),
            Mesh::Sphere => draw_sphere(vec3(0., 6., 0.), 5., Some(&ferris), WHITE),
            Mesh::Cube => draw_cube(vec3(0., 5., 0.), vec3(10., 10., 10.), Some(&ferris), WHITE),
        }
        gl_use_default_material();

        set_default_camera();

        let mut need_update = false;

        widgets::Window::new(hash!(), vec2(20., 20.), vec2(470., 650.))
            .label("Shader")
            .ui(&mut *root_ui(), |ui| {
                ui.label(None, "Camera: ");
                ui.same_line(0.0);
                if ui.button(None, "Ortho") {
                    camera.projection = Projection::Orthographics;
                }
                ui.same_line(0.0);
                if ui.button(None, "Perspective") {
                    camera.projection = Projection::Perspective;
                }
                ui.label(None, "Mesh: ");
                ui.same_line(0.0);
                if ui.button(None, "Sphere") {
                    mesh = Mesh::Sphere;
                }
                ui.same_line(0.0);
                if ui.button(None, "Cube") {
                    mesh = Mesh::Cube;
                }
                ui.same_line(0.0);
                if ui.button(None, "Plane") {
                    mesh = Mesh::Plane;
                }

                ui.label(None, "Uniforms:");
                ui.separator();

                for (i, (name, uniform)) in uniforms.iter_mut().enumerate() {
                    ui.label(None, &format!("{}", name));
                    ui.same_line(120.0);

                    match uniform {
                        Uniform::Float1(x) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(200.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            if let Ok(x) = x.parse::<f32>() {
                                material.set_uniform(name, x);
                            }
                        }
                        Uniform::Float2(x, y) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(99.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(99.0, 19.0))
                                .filter_numbers()
                                .ui(ui, y);

                            if let (Ok(x), Ok(y)) = (x.parse::<f32>(), y.parse::<f32>()) {
                                material.set_uniform(name, (x, y));
                            }
                        }
                        Uniform::Float3(x, y, z) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, y);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, z);

                            if let (Ok(x), Ok(y), Ok(z)) =
                                (x.parse::<f32>(), y.parse::<f32>(), z.parse::<f32>())
                            {
                                material.set_uniform(name, (x, y, z));
                            }
                        }

                        Uniform::Color(color) => {
                            let mut canvas = ui.canvas();

                            let cursor = canvas.cursor();

                            canvas.rect(
                                Rect::new(cursor.x + 20.0, cursor.y, 50.0, 18.0),
                                Color::new(0.2, 0.2, 0.2, 1.0),
                                Color::new(color.x, color.y, color.z, 1.0),
                            );

                            if ui.button(None, "change") {
                                colorpicker_window = true;
                                color_picking_uniform = Some(name.to_owned());
                            }
                            material.set_uniform(name, (color.x, color.y, color.z));
                        }
                    }
                }
                ui.separator();
                if ui.button(None, "New uniform") {
                    new_uniform_window = true;
                }
                TreeNode::new(hash!(), "Fragment shader")
                    .init_unfolded()
                    .ui(ui, |ui| {
                        if ui.editbox(hash!(), vec2(440., 200.), &mut fragment_shader) {
                            need_update = true;
                        };
                    });
                ui.tree_node(hash!(), "Vertex shader", |ui| {
                    if ui.editbox(hash!(), vec2(440., 300.), &mut vertex_shader) {
                        need_update = true;
                    };
                });

                if let Some(ref error) = error {
                    Label::new(error).multiline(14.0).ui(ui);
                }
            });

        if new_uniform_window {
            widgets::Window::new(hash!(), vec2(100., 100.), vec2(200., 80.))
                .label("New uniform")
                .ui(&mut *root_ui(), |ui| {
                    if ui.active_window_focused() == false {
                        new_uniform_window = false;
                    }
                    ui.input_text(hash!(), "Name", &mut new_uniform_name);
                    let uniform_type = ui.combo_box(
                        hash!(),
                        "Type",
                        &["Float1", "Float2", "Float3", "Color"],
                        None,
                    );

                    if ui.button(None, "Add") {
                        if new_uniform_name.is_empty() == false {
                            let uniform = match uniform_type {
                                0 => Uniform::Float1("0".to_string()),
                                1 => Uniform::Float2("0".to_string(), "0".to_string()),
                                2 => Uniform::Float3(
                                    "0".to_string(),
                                    "0".to_string(),
                                    "0".to_string(),
                                ),
                                3 => Uniform::Color(vec3(0.0, 0.0, 0.0)),
                                _ => unreachable!(),
                            };
                            uniforms.push((new_uniform_name.clone(), uniform));
                            new_uniform_name.clear();
                            need_update = true;
                        }
                        new_uniform_window = false;
                    }

                    ui.same_line(0.0);
                    if ui.button(None, "Cancel") {
                        new_uniform_window = false;
                    }
                });
        }

        if colorpicker_window {
            colorpicker_window &= widgets::Window::new(hash!(), vec2(140., 100.), vec2(210., 240.))
                .label("Colorpicker")
                .ui(&mut *root_ui(), |ui| {
                    if ui.active_window_focused() == false {
                        colorpicker_window = false;
                    }

                    let mut canvas = ui.canvas();
                    let cursor = canvas.cursor();
                    let mouse = mouse_position();
                    let x = mouse.0 as i32 - cursor.x as i32;
                    let y = mouse.1 as i32 - (cursor.y as i32 + 20);

                    let color = color_picker_image
                        .get_pixel(x.max(0).min(199) as u32, y.max(0).min(199) as u32);

                    canvas.rect(
                        Rect::new(cursor.x, cursor.y, 200.0, 18.0),
                        Color::new(0.0, 0.0, 0.0, 1.0),
                        Color::new(color.r, color.g, color.b, 1.0),
                    );
                    canvas.image(
                        Rect::new(cursor.x, cursor.y + 20.0, 200.0, 200.0),
                        &color_picker_texture,
                    );

                    if x >= 0 && x < 200 && y >= 0 && y < 200 {
                        canvas.rect(
                            Rect::new(mouse.0 - 3.5, mouse.1 - 3.5, 7.0, 7.0),
                            Color::new(0.3, 0.3, 0.3, 1.0),
                            Color::new(1.0, 1.0, 1.0, 1.0),
                        );

                        if is_mouse_button_down(MouseButton::Left) {
                            colorpicker_window = false;
                            let uniform_name = color_picking_uniform.take().unwrap();

                            uniforms
                                .iter_mut()
                                .find(|(name, _)| name == &uniform_name)
                                .unwrap()
                                .1 = Uniform::Color(vec3(color.r, color.g, color.b));
                        }
                    }
                });
        }

        if need_update {
            let uniforms = uniforms
                .iter()
                .map(|(name, uniform)| (name.clone(), uniform.uniform_type()))
                .collect::<Vec<_>>();

            match load_material(
                ShaderSource::Glsl {
                    vertex: &vertex_shader,
                    fragment: &fragment_shader,
                },
                MaterialParams {
                    pipeline_params,
                    uniforms,
                    textures: vec![],
                },
            ) {
                Ok(new_material) => {
                    material = new_material;
                    error = None;
                }
                Err(err) => {
                    error = Some(format!("{:#?}", err));
                }
            }
        }

        next_frame().await
    }
}
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 221)
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
async fn main() {
    let mut data = Data::new();

    let mut data0 = String::new();
    let mut data1 = String::new();

    let mut text0 = String::new();
    let mut text1 = String::new();

    let mut number0 = 0.;
    let mut number1 = 0.;

    let texture: Texture2D = load_texture("examples/ferris.png").await.unwrap();

    loop {
        clear_background(WHITE);

        widgets::Window::new(hash!(), vec2(400., 200.), vec2(320., 400.))
            .label("Shop")
            .titlebar(true)
            .ui(&mut *root_ui(), |ui| {
                for i in 0..30 {
                    Group::new(hash!("shop", i), Vec2::new(300., 80.)).ui(ui, |ui| {
                        ui.label(Vec2::new(10., 10.), &format!("Item N {}", i));
                        ui.label(Vec2::new(260., 40.), "10/10");
                        ui.label(Vec2::new(200., 58.), &format!("{} kr", 800));
                        if ui.button(Vec2::new(260., 55.), "buy") {
                            data.inventory.push(format!("Item {}", i));
                        }
                    });
                }
            });

        widgets::Window::new(hash!(), vec2(100., 220.), vec2(542., 430.))
            .label("Fitting window")
            .titlebar(true)
            .ui(&mut *root_ui(), |ui| {
                Group::new(hash!(), Vec2::new(230., 400.)).ui(ui, |ui| {
                    data.slots(ui);
                });
                Group::new(hash!(), Vec2::new(280., 400.)).ui(ui, |ui| {
                    data.inventory(ui);
                });
            });

        widgets::Window::new(hash!(), vec2(470., 50.), vec2(300., 300.))
            .label("Megaui Showcase Window")
            .ui(&mut *root_ui(), |ui| {
                ui.tree_node(hash!(), "input", |ui| {
                    ui.label(None, "Some random text");
                    if ui.button(None, "click me") {
                        println!("hi");
                    }

                    ui.separator();

                    ui.label(None, "Some other random text");
                    if ui.button(None, "other button") {
                        println!("hi2");
                    }

                    ui.separator();

                    ui.input_text(hash!(), "<- input text 1", &mut data0);
                    ui.input_text(hash!(), "<- input text 2", &mut data1);
                    ui.label(
                        None,
                        &format!("Text entered: \"{}\" and \"{}\"", data0, data1),
                    );

                    ui.separator();
                });
                ui.tree_node(hash!(), "buttons", |ui| {
                    widgets::Button::new(texture.clone())
                        .size(vec2(120., 70.))
                        .ui(ui);
                    ui.same_line(0.);
                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
                    ui.same_line(0.);
                    widgets::Button::new(texture.clone())
                        .size(vec2(120., 70.))
                        .ui(ui);
                });
                ui.tree_node(hash!(), "sliders", |ui| {
                    ui.slider(hash!(), "[-10 .. 10]", -10f32..10f32, &mut number0);
                    ui.slider(hash!(), "[0 .. 100]", 0f32..100f32, &mut number1);
                });
                ui.tree_node(hash!(), "editbox 1", |ui| {
                    ui.label(None, "This is editbox!");
                    ui.editbox(hash!(), vec2(285., 165.), &mut text0);
                });
                ui.tree_node(hash!(), "editbox 2", |ui| {
                    ui.label(None, "This is editbox!");
                    ui.editbox(hash!(), vec2(285., 165.), &mut text1);
                });
            });

        match data.fit_command.take() {
            Some(FittingCommand::Unfit { target_slot }) => data.set_item(target_slot, None),
            Some(FittingCommand::Fit { target_slot, item }) => {
                data.set_item(target_slot, Some(item));
            }
            Some(FittingCommand::Refit {
                target_slot,
                origin_slot,
            }) => {
                let origin_item = data
                    .slots
                    .iter()
                    .find_map(|(_, slot)| {
                        if slot.id == origin_slot {
                            Some(slot.item.clone())
                        } else {
                            None
                        }
                    })
                    .flatten();
                data.set_item(target_slot, origin_item);
                data.set_item(origin_slot, None);
            }
            None => {}
        };

        next_frame().await;
    }
}
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-207)
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
async fn main() {
    let mut data = Data::new();

    let mut data0 = String::new();
    let mut data1 = String::new();

    let mut text0 = String::new();
    let mut text1 = String::new();

    let mut number0 = 0.;
    let mut number1 = 0.;

    let texture: Texture2D = load_texture("examples/ferris.png").await.unwrap();

    loop {
        clear_background(WHITE);

        widgets::Window::new(hash!(), vec2(400., 200.), vec2(320., 400.))
            .label("Shop")
            .titlebar(true)
            .ui(&mut *root_ui(), |ui| {
                for i in 0..30 {
                    Group::new(hash!("shop", i), Vec2::new(300., 80.)).ui(ui, |ui| {
                        ui.label(Vec2::new(10., 10.), &format!("Item N {}", i));
                        ui.label(Vec2::new(260., 40.), "10/10");
                        ui.label(Vec2::new(200., 58.), &format!("{} kr", 800));
                        if ui.button(Vec2::new(260., 55.), "buy") {
                            data.inventory.push(format!("Item {}", i));
                        }
                    });
                }
            });

        widgets::Window::new(hash!(), vec2(100., 220.), vec2(542., 430.))
            .label("Fitting window")
            .titlebar(true)
            .ui(&mut *root_ui(), |ui| {
                Group::new(hash!(), Vec2::new(230., 400.)).ui(ui, |ui| {
                    data.slots(ui);
                });
                Group::new(hash!(), Vec2::new(280., 400.)).ui(ui, |ui| {
                    data.inventory(ui);
                });
            });

        widgets::Window::new(hash!(), vec2(470., 50.), vec2(300., 300.))
            .label("Megaui Showcase Window")
            .ui(&mut *root_ui(), |ui| {
                ui.tree_node(hash!(), "input", |ui| {
                    ui.label(None, "Some random text");
                    if ui.button(None, "click me") {
                        println!("hi");
                    }

                    ui.separator();

                    ui.label(None, "Some other random text");
                    if ui.button(None, "other button") {
                        println!("hi2");
                    }

                    ui.separator();

                    ui.input_text(hash!(), "<- input text 1", &mut data0);
                    ui.input_text(hash!(), "<- input text 2", &mut data1);
                    ui.label(
                        None,
                        &format!("Text entered: \"{}\" and \"{}\"", data0, data1),
                    );

                    ui.separator();
                });
                ui.tree_node(hash!(), "buttons", |ui| {
                    widgets::Button::new(texture.clone())
                        .size(vec2(120., 70.))
                        .ui(ui);
                    ui.same_line(0.);
                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
                    ui.same_line(0.);
                    widgets::Button::new(texture.clone())
                        .size(vec2(120., 70.))
                        .ui(ui);
                });
                ui.tree_node(hash!(), "sliders", |ui| {
                    ui.slider(hash!(), "[-10 .. 10]", -10f32..10f32, &mut number0);
                    ui.slider(hash!(), "[0 .. 100]", 0f32..100f32, &mut number1);
                });
                ui.tree_node(hash!(), "editbox 1", |ui| {
                    ui.label(None, "This is editbox!");
                    ui.editbox(hash!(), vec2(285., 165.), &mut text0);
                });
                ui.tree_node(hash!(), "editbox 2", |ui| {
                    ui.label(None, "This is editbox!");
                    ui.editbox(hash!(), vec2(285., 165.), &mut text1);
                });
            });

        match data.fit_command.take() {
            Some(FittingCommand::Unfit { target_slot }) => data.set_item(target_slot, None),
            Some(FittingCommand::Fit { target_slot, item }) => {
                data.set_item(target_slot, Some(item));
            }
            Some(FittingCommand::Refit {
                target_slot,
                origin_slot,
            }) => {
                let origin_item = data
                    .slots
                    .iter()
                    .find_map(|(_, slot)| {
                        if slot.id == origin_slot {
                            Some(slot.item.clone())
                        } else {
                            None
                        }
                    })
                    .flatten();
                data.set_item(target_slot, origin_item);
                data.set_item(origin_slot, None);
            }
            None => {}
        };

        next_frame().await;
    }
}
More examples
Hide additional examples
examples/shadertoy.rs (lines 236-240)
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
async fn main() {
    let ferris = load_texture("examples/rust.png").await.unwrap();
    let (color_picker_texture, color_picker_image) = color_picker_texture(200, 200);

    let mut fragment_shader = DEFAULT_FRAGMENT_SHADER.to_string();
    let mut vertex_shader = DEFAULT_VERTEX_SHADER.to_string();

    let pipeline_params = PipelineParams {
        depth_write: true,
        depth_test: Comparison::LessOrEqual,
        ..Default::default()
    };

    let mut material = load_material(
        ShaderSource::Glsl {
            vertex: &vertex_shader,
            fragment: &fragment_shader,
        },
        MaterialParams {
            pipeline_params,
            ..Default::default()
        },
    )
    .unwrap();
    let mut error: Option<String> = None;

    enum Mesh {
        Sphere,
        Cube,
        Plane,
    }
    let mut mesh = Mesh::Sphere;

    let mut camera = Camera3D {
        position: vec3(-15., 15., -5.),
        up: vec3(0., 1., 0.),
        target: vec3(0., 5., -5.),
        ..Default::default()
    };

    let mut colorpicker_window = false;
    let mut color_picking_uniform = None;

    let mut new_uniform_window = false;
    let mut new_uniform_name = String::new();
    let mut uniforms: Vec<(String, Uniform)> = vec![];

    loop {
        clear_background(WHITE);

        set_camera(&camera);

        draw_grid(
            20,
            1.,
            Color::new(0.55, 0.55, 0.55, 0.75),
            Color::new(0.75, 0.75, 0.75, 0.75),
        );

        gl_use_material(&material);
        match mesh {
            Mesh::Plane => draw_plane(vec3(0., 2., 0.), vec2(5., 5.), Some(&ferris), WHITE),
            Mesh::Sphere => draw_sphere(vec3(0., 6., 0.), 5., Some(&ferris), WHITE),
            Mesh::Cube => draw_cube(vec3(0., 5., 0.), vec3(10., 10., 10.), Some(&ferris), WHITE),
        }
        gl_use_default_material();

        set_default_camera();

        let mut need_update = false;

        widgets::Window::new(hash!(), vec2(20., 20.), vec2(470., 650.))
            .label("Shader")
            .ui(&mut *root_ui(), |ui| {
                ui.label(None, "Camera: ");
                ui.same_line(0.0);
                if ui.button(None, "Ortho") {
                    camera.projection = Projection::Orthographics;
                }
                ui.same_line(0.0);
                if ui.button(None, "Perspective") {
                    camera.projection = Projection::Perspective;
                }
                ui.label(None, "Mesh: ");
                ui.same_line(0.0);
                if ui.button(None, "Sphere") {
                    mesh = Mesh::Sphere;
                }
                ui.same_line(0.0);
                if ui.button(None, "Cube") {
                    mesh = Mesh::Cube;
                }
                ui.same_line(0.0);
                if ui.button(None, "Plane") {
                    mesh = Mesh::Plane;
                }

                ui.label(None, "Uniforms:");
                ui.separator();

                for (i, (name, uniform)) in uniforms.iter_mut().enumerate() {
                    ui.label(None, &format!("{}", name));
                    ui.same_line(120.0);

                    match uniform {
                        Uniform::Float1(x) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(200.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            if let Ok(x) = x.parse::<f32>() {
                                material.set_uniform(name, x);
                            }
                        }
                        Uniform::Float2(x, y) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(99.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(99.0, 19.0))
                                .filter_numbers()
                                .ui(ui, y);

                            if let (Ok(x), Ok(y)) = (x.parse::<f32>(), y.parse::<f32>()) {
                                material.set_uniform(name, (x, y));
                            }
                        }
                        Uniform::Float3(x, y, z) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, y);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, z);

                            if let (Ok(x), Ok(y), Ok(z)) =
                                (x.parse::<f32>(), y.parse::<f32>(), z.parse::<f32>())
                            {
                                material.set_uniform(name, (x, y, z));
                            }
                        }

                        Uniform::Color(color) => {
                            let mut canvas = ui.canvas();

                            let cursor = canvas.cursor();

                            canvas.rect(
                                Rect::new(cursor.x + 20.0, cursor.y, 50.0, 18.0),
                                Color::new(0.2, 0.2, 0.2, 1.0),
                                Color::new(color.x, color.y, color.z, 1.0),
                            );

                            if ui.button(None, "change") {
                                colorpicker_window = true;
                                color_picking_uniform = Some(name.to_owned());
                            }
                            material.set_uniform(name, (color.x, color.y, color.z));
                        }
                    }
                }
                ui.separator();
                if ui.button(None, "New uniform") {
                    new_uniform_window = true;
                }
                TreeNode::new(hash!(), "Fragment shader")
                    .init_unfolded()
                    .ui(ui, |ui| {
                        if ui.editbox(hash!(), vec2(440., 200.), &mut fragment_shader) {
                            need_update = true;
                        };
                    });
                ui.tree_node(hash!(), "Vertex shader", |ui| {
                    if ui.editbox(hash!(), vec2(440., 300.), &mut vertex_shader) {
                        need_update = true;
                    };
                });

                if let Some(ref error) = error {
                    Label::new(error).multiline(14.0).ui(ui);
                }
            });

        if new_uniform_window {
            widgets::Window::new(hash!(), vec2(100., 100.), vec2(200., 80.))
                .label("New uniform")
                .ui(&mut *root_ui(), |ui| {
                    if ui.active_window_focused() == false {
                        new_uniform_window = false;
                    }
                    ui.input_text(hash!(), "Name", &mut new_uniform_name);
                    let uniform_type = ui.combo_box(
                        hash!(),
                        "Type",
                        &["Float1", "Float2", "Float3", "Color"],
                        None,
                    );

                    if ui.button(None, "Add") {
                        if new_uniform_name.is_empty() == false {
                            let uniform = match uniform_type {
                                0 => Uniform::Float1("0".to_string()),
                                1 => Uniform::Float2("0".to_string(), "0".to_string()),
                                2 => Uniform::Float3(
                                    "0".to_string(),
                                    "0".to_string(),
                                    "0".to_string(),
                                ),
                                3 => Uniform::Color(vec3(0.0, 0.0, 0.0)),
                                _ => unreachable!(),
                            };
                            uniforms.push((new_uniform_name.clone(), uniform));
                            new_uniform_name.clear();
                            need_update = true;
                        }
                        new_uniform_window = false;
                    }

                    ui.same_line(0.0);
                    if ui.button(None, "Cancel") {
                        new_uniform_window = false;
                    }
                });
        }

        if colorpicker_window {
            colorpicker_window &= widgets::Window::new(hash!(), vec2(140., 100.), vec2(210., 240.))
                .label("Colorpicker")
                .ui(&mut *root_ui(), |ui| {
                    if ui.active_window_focused() == false {
                        colorpicker_window = false;
                    }

                    let mut canvas = ui.canvas();
                    let cursor = canvas.cursor();
                    let mouse = mouse_position();
                    let x = mouse.0 as i32 - cursor.x as i32;
                    let y = mouse.1 as i32 - (cursor.y as i32 + 20);

                    let color = color_picker_image
                        .get_pixel(x.max(0).min(199) as u32, y.max(0).min(199) as u32);

                    canvas.rect(
                        Rect::new(cursor.x, cursor.y, 200.0, 18.0),
                        Color::new(0.0, 0.0, 0.0, 1.0),
                        Color::new(color.r, color.g, color.b, 1.0),
                    );
                    canvas.image(
                        Rect::new(cursor.x, cursor.y + 20.0, 200.0, 200.0),
                        &color_picker_texture,
                    );

                    if x >= 0 && x < 200 && y >= 0 && y < 200 {
                        canvas.rect(
                            Rect::new(mouse.0 - 3.5, mouse.1 - 3.5, 7.0, 7.0),
                            Color::new(0.3, 0.3, 0.3, 1.0),
                            Color::new(1.0, 1.0, 1.0, 1.0),
                        );

                        if is_mouse_button_down(MouseButton::Left) {
                            colorpicker_window = false;
                            let uniform_name = color_picking_uniform.take().unwrap();

                            uniforms
                                .iter_mut()
                                .find(|(name, _)| name == &uniform_name)
                                .unwrap()
                                .1 = Uniform::Color(vec3(color.r, color.g, color.b));
                        }
                    }
                });
        }

        if need_update {
            let uniforms = uniforms
                .iter()
                .map(|(name, uniform)| (name.clone(), uniform.uniform_type()))
                .collect::<Vec<_>>();

            match load_material(
                ShaderSource::Glsl {
                    vertex: &vertex_shader,
                    fragment: &fragment_shader,
                },
                MaterialParams {
                    pipeline_params,
                    uniforms,
                    textures: vec![],
                },
            ) {
                Ok(new_material) => {
                    material = new_material;
                    error = None;
                }
                Err(err) => {
                    error = Some(format!("{:#?}", err));
                }
            }
        }

        next_frame().await
    }
}
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)
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
async fn main() {
    loop {
        clear_background(WHITE);
        root_ui().window(hash!(), Vec2::new(20., 20.), Vec2::new(450., 200.), |ui| {
            let (mouse_x, mouse_y) = mouse_position();
            ui.label(None, &format!("Mouse position: {} {}", mouse_x, mouse_y));

            let (mouse_wheel_x, mouse_wheel_y) = mouse_wheel();
            ui.label(None, &format!("Mouse wheel x: {}", mouse_wheel_x));
            ui.label(None, &format!("Mouse wheel y: {}", mouse_wheel_y));

            widgets::Group::new(hash!(), Vec2::new(200., 90.))
                .position(Vec2::new(240., 0.))
                .ui(ui, |ui| {
                    ui.label(None, "Pressed kbd keys");

                    if let Some(key) = get_last_key_pressed() {
                        ui.label(None, &format!("{:?}", key))
                    }
                });

            widgets::Group::new(hash!(), Vec2::new(200., 90.))
                .position(Vec2::new(240., 92.))
                .ui(ui, |ui| {
                    ui.label(None, "Pressed mouse keys");

                    if is_mouse_button_down(MouseButton::Left) {
                        ui.label(None, "Left");
                    }
                    if is_mouse_button_down(MouseButton::Right) {
                        ui.label(None, "Right");
                    }
                    if is_mouse_button_down(MouseButton::Middle) {
                        ui.label(None, "Middle");
                    }
                });
        });
        next_frame().await;
    }
}
More examples
Hide additional examples
examples/ui_skins.rs (lines 241-252)
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
async fn main() {
    let skin1 = {
        let label_style = root_ui()
            .style_builder()
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 120, 255))
            .font_size(30)
            .build();

        let window_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/window_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(20.0, 20.0, 10.0, 10.0))
            .margin(RectOffset::new(-20.0, -30.0, 0.0, 0.0))
            .build();

        let button_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(37.0, 37.0, 5.0, 5.0))
            .margin(RectOffset::new(10.0, 10.0, 0.0, 0.0))
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_hovered_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_clicked_background.png"),
                    None,
                )
                .unwrap(),
            )
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 100, 255))
            .font_size(40)
            .build();

        let editbox_style = root_ui()
            .style_builder()
            .background_margin(RectOffset::new(0., 0., 0., 0.))
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .color_selected(Color::from_rgba(190, 190, 190, 255))
            .font_size(50)
            .build();

        Skin {
            editbox_style,
            window_style,
            button_style,
            label_style,
            ..root_ui().default_skin()
        }
    };

    let skin2 = {
        let label_style = root_ui()
            .style_builder()
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .font_size(25)
            .build();

        let window_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/window_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(52.0, 52.0, 52.0, 52.0))
            .margin(RectOffset::new(-30.0, 0.0, -30.0, 0.0))
            .build();

        let button_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(8.0, 8.0, 8.0, 8.0))
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_hovered_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_clicked_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 100, 255))
            .font_size(40)
            .build();

        let checkbox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_hovered_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_clicked_background.png"),
                    None,
                )
                .unwrap(),
            )
            .build();

        let editbox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/editbox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(2., 2., 2., 2.))
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .font_size(25)
            .build();

        let combobox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/combobox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(4., 25., 6., 6.))
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .color(Color::from_rgba(210, 210, 210, 255))
            .font_size(25)
            .build();

        Skin {
            window_style,
            button_style,
            label_style,
            checkbox_style,
            editbox_style,
            combobox_style,
            ..root_ui().default_skin()
        }
    };
    let default_skin = root_ui().default_skin().clone();

    let mut window1_skin = skin1.clone();
    let mut window2_skin = skin2.clone();

    let mut checkbox = false;
    let mut text = String::new();
    let mut number = 0.0f32;
    let mut combobox = 0;

    loop {
        clear_background(GRAY);

        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
            ui.label(None, "Window 1");

            if ui.button(None, "Skin 1") {
                window1_skin = skin1.clone();
            }
            if ui.button(None, "Skin 2") {
                window1_skin = skin2.clone();
            }
            if ui.button(None, "No Skin") {
                window1_skin = default_skin.clone();
            }
        });
        root_ui().same_line(0.);
        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
            ui.label(None, "Window 2");
            if ui.button(None, "Skin 1") {
                window2_skin = skin1.clone();
            }
            if ui.button(None, "Skin 2") {
                window2_skin = skin2.clone();
            }
            if ui.button(None, "No Skin") {
                window2_skin = default_skin.clone();
            }
        });

        root_ui().push_skin(&window1_skin);

        root_ui().window(hash!(), vec2(20., 250.), vec2(300., 300.), |ui| {
            widgets::Button::new("Play")
                .position(vec2(65.0, 15.0))
                .ui(ui);
            widgets::Button::new("Options")
                .position(vec2(40.0, 75.0))
                .ui(ui);

            widgets::Button::new("Quit")
                .position(vec2(65.0, 195.0))
                .ui(ui);
        });
        root_ui().pop_skin();

        root_ui().push_skin(&window2_skin);
        root_ui().window(hash!(), vec2(250., 20.), vec2(500., 250.), |ui| {
            ui.checkbox(hash!(), "Checkbox 1", &mut checkbox);
            ui.combo_box(
                hash!(),
                "Combobox",
                &["First option", "Second option"],
                &mut combobox,
            );
            ui.input_text(hash!(), "Text", &mut text);
            ui.drag(hash!(), "Drag", None, &mut number);

            widgets::Button::new("Apply")
                .position(vec2(80.0, 150.0))
                .ui(ui);
            widgets::Button::new("Cancel")
                .position(vec2(280.0, 150.0))
                .ui(ui);
        });
        root_ui().pop_skin();

        next_frame().await;
    }
}
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 9)
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
async fn main() {
    let skin1 = {
        let label_style = root_ui()
            .style_builder()
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 120, 255))
            .font_size(30)
            .build();

        let window_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/window_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(20.0, 20.0, 10.0, 10.0))
            .margin(RectOffset::new(-20.0, -30.0, 0.0, 0.0))
            .build();

        let button_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(37.0, 37.0, 5.0, 5.0))
            .margin(RectOffset::new(10.0, 10.0, 0.0, 0.0))
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_hovered_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_clicked_background.png"),
                    None,
                )
                .unwrap(),
            )
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 100, 255))
            .font_size(40)
            .build();

        let editbox_style = root_ui()
            .style_builder()
            .background_margin(RectOffset::new(0., 0., 0., 0.))
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .color_selected(Color::from_rgba(190, 190, 190, 255))
            .font_size(50)
            .build();

        Skin {
            editbox_style,
            window_style,
            button_style,
            label_style,
            ..root_ui().default_skin()
        }
    };

    let skin2 = {
        let label_style = root_ui()
            .style_builder()
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .font_size(25)
            .build();

        let window_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/window_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(52.0, 52.0, 52.0, 52.0))
            .margin(RectOffset::new(-30.0, 0.0, -30.0, 0.0))
            .build();

        let button_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(8.0, 8.0, 8.0, 8.0))
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_hovered_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_clicked_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 100, 255))
            .font_size(40)
            .build();

        let checkbox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_hovered_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_clicked_background.png"),
                    None,
                )
                .unwrap(),
            )
            .build();

        let editbox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/editbox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(2., 2., 2., 2.))
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .font_size(25)
            .build();

        let combobox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/combobox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(4., 25., 6., 6.))
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .color(Color::from_rgba(210, 210, 210, 255))
            .font_size(25)
            .build();

        Skin {
            window_style,
            button_style,
            label_style,
            checkbox_style,
            editbox_style,
            combobox_style,
            ..root_ui().default_skin()
        }
    };
    let default_skin = root_ui().default_skin().clone();

    let mut window1_skin = skin1.clone();
    let mut window2_skin = skin2.clone();

    let mut checkbox = false;
    let mut text = String::new();
    let mut number = 0.0f32;
    let mut combobox = 0;

    loop {
        clear_background(GRAY);

        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
            ui.label(None, "Window 1");

            if ui.button(None, "Skin 1") {
                window1_skin = skin1.clone();
            }
            if ui.button(None, "Skin 2") {
                window1_skin = skin2.clone();
            }
            if ui.button(None, "No Skin") {
                window1_skin = default_skin.clone();
            }
        });
        root_ui().same_line(0.);
        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
            ui.label(None, "Window 2");
            if ui.button(None, "Skin 1") {
                window2_skin = skin1.clone();
            }
            if ui.button(None, "Skin 2") {
                window2_skin = skin2.clone();
            }
            if ui.button(None, "No Skin") {
                window2_skin = default_skin.clone();
            }
        });

        root_ui().push_skin(&window1_skin);

        root_ui().window(hash!(), vec2(20., 250.), vec2(300., 300.), |ui| {
            widgets::Button::new("Play")
                .position(vec2(65.0, 15.0))
                .ui(ui);
            widgets::Button::new("Options")
                .position(vec2(40.0, 75.0))
                .ui(ui);

            widgets::Button::new("Quit")
                .position(vec2(65.0, 195.0))
                .ui(ui);
        });
        root_ui().pop_skin();

        root_ui().push_skin(&window2_skin);
        root_ui().window(hash!(), vec2(250., 20.), vec2(500., 250.), |ui| {
            ui.checkbox(hash!(), "Checkbox 1", &mut checkbox);
            ui.combo_box(
                hash!(),
                "Combobox",
                &["First option", "Second option"],
                &mut combobox,
            );
            ui.input_text(hash!(), "Text", &mut text);
            ui.drag(hash!(), "Drag", None, &mut number);

            widgets::Button::new("Apply")
                .position(vec2(80.0, 150.0))
                .ui(ui);
            widgets::Button::new("Cancel")
                .position(vec2(280.0, 150.0))
                .ui(ui);
        });
        root_ui().pop_skin();

        next_frame().await;
    }
}
source

pub fn default_skin(&self) -> Skin

Examples found in repository?
examples/ui_skins.rs (line 75)
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
async fn main() {
    let skin1 = {
        let label_style = root_ui()
            .style_builder()
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 120, 255))
            .font_size(30)
            .build();

        let window_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/window_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(20.0, 20.0, 10.0, 10.0))
            .margin(RectOffset::new(-20.0, -30.0, 0.0, 0.0))
            .build();

        let button_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(37.0, 37.0, 5.0, 5.0))
            .margin(RectOffset::new(10.0, 10.0, 0.0, 0.0))
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_hovered_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_clicked_background.png"),
                    None,
                )
                .unwrap(),
            )
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 100, 255))
            .font_size(40)
            .build();

        let editbox_style = root_ui()
            .style_builder()
            .background_margin(RectOffset::new(0., 0., 0., 0.))
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .color_selected(Color::from_rgba(190, 190, 190, 255))
            .font_size(50)
            .build();

        Skin {
            editbox_style,
            window_style,
            button_style,
            label_style,
            ..root_ui().default_skin()
        }
    };

    let skin2 = {
        let label_style = root_ui()
            .style_builder()
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .font_size(25)
            .build();

        let window_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/window_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(52.0, 52.0, 52.0, 52.0))
            .margin(RectOffset::new(-30.0, 0.0, -30.0, 0.0))
            .build();

        let button_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(8.0, 8.0, 8.0, 8.0))
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_hovered_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_clicked_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 100, 255))
            .font_size(40)
            .build();

        let checkbox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_hovered_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_clicked_background.png"),
                    None,
                )
                .unwrap(),
            )
            .build();

        let editbox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/editbox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(2., 2., 2., 2.))
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .font_size(25)
            .build();

        let combobox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/combobox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(4., 25., 6., 6.))
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .color(Color::from_rgba(210, 210, 210, 255))
            .font_size(25)
            .build();

        Skin {
            window_style,
            button_style,
            label_style,
            checkbox_style,
            editbox_style,
            combobox_style,
            ..root_ui().default_skin()
        }
    };
    let default_skin = root_ui().default_skin().clone();

    let mut window1_skin = skin1.clone();
    let mut window2_skin = skin2.clone();

    let mut checkbox = false;
    let mut text = String::new();
    let mut number = 0.0f32;
    let mut combobox = 0;

    loop {
        clear_background(GRAY);

        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
            ui.label(None, "Window 1");

            if ui.button(None, "Skin 1") {
                window1_skin = skin1.clone();
            }
            if ui.button(None, "Skin 2") {
                window1_skin = skin2.clone();
            }
            if ui.button(None, "No Skin") {
                window1_skin = default_skin.clone();
            }
        });
        root_ui().same_line(0.);
        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
            ui.label(None, "Window 2");
            if ui.button(None, "Skin 1") {
                window2_skin = skin1.clone();
            }
            if ui.button(None, "Skin 2") {
                window2_skin = skin2.clone();
            }
            if ui.button(None, "No Skin") {
                window2_skin = default_skin.clone();
            }
        });

        root_ui().push_skin(&window1_skin);

        root_ui().window(hash!(), vec2(20., 250.), vec2(300., 300.), |ui| {
            widgets::Button::new("Play")
                .position(vec2(65.0, 15.0))
                .ui(ui);
            widgets::Button::new("Options")
                .position(vec2(40.0, 75.0))
                .ui(ui);

            widgets::Button::new("Quit")
                .position(vec2(65.0, 195.0))
                .ui(ui);
        });
        root_ui().pop_skin();

        root_ui().push_skin(&window2_skin);
        root_ui().window(hash!(), vec2(250., 20.), vec2(500., 250.), |ui| {
            ui.checkbox(hash!(), "Checkbox 1", &mut checkbox);
            ui.combo_box(
                hash!(),
                "Combobox",
                &["First option", "Second option"],
                &mut combobox,
            );
            ui.input_text(hash!(), "Text", &mut text);
            ui.drag(hash!(), "Drag", None, &mut number);

            widgets::Button::new("Apply")
                .position(vec2(80.0, 150.0))
                .ui(ui);
            widgets::Button::new("Cancel")
                .position(vec2(280.0, 150.0))
                .ui(ui);
        });
        root_ui().pop_skin();

        next_frame().await;
    }
}
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 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)
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
async fn main() {
    let ferris = load_texture("examples/rust.png").await.unwrap();
    let (color_picker_texture, color_picker_image) = color_picker_texture(200, 200);

    let mut fragment_shader = DEFAULT_FRAGMENT_SHADER.to_string();
    let mut vertex_shader = DEFAULT_VERTEX_SHADER.to_string();

    let pipeline_params = PipelineParams {
        depth_write: true,
        depth_test: Comparison::LessOrEqual,
        ..Default::default()
    };

    let mut material = load_material(
        ShaderSource::Glsl {
            vertex: &vertex_shader,
            fragment: &fragment_shader,
        },
        MaterialParams {
            pipeline_params,
            ..Default::default()
        },
    )
    .unwrap();
    let mut error: Option<String> = None;

    enum Mesh {
        Sphere,
        Cube,
        Plane,
    }
    let mut mesh = Mesh::Sphere;

    let mut camera = Camera3D {
        position: vec3(-15., 15., -5.),
        up: vec3(0., 1., 0.),
        target: vec3(0., 5., -5.),
        ..Default::default()
    };

    let mut colorpicker_window = false;
    let mut color_picking_uniform = None;

    let mut new_uniform_window = false;
    let mut new_uniform_name = String::new();
    let mut uniforms: Vec<(String, Uniform)> = vec![];

    loop {
        clear_background(WHITE);

        set_camera(&camera);

        draw_grid(
            20,
            1.,
            Color::new(0.55, 0.55, 0.55, 0.75),
            Color::new(0.75, 0.75, 0.75, 0.75),
        );

        gl_use_material(&material);
        match mesh {
            Mesh::Plane => draw_plane(vec3(0., 2., 0.), vec2(5., 5.), Some(&ferris), WHITE),
            Mesh::Sphere => draw_sphere(vec3(0., 6., 0.), 5., Some(&ferris), WHITE),
            Mesh::Cube => draw_cube(vec3(0., 5., 0.), vec3(10., 10., 10.), Some(&ferris), WHITE),
        }
        gl_use_default_material();

        set_default_camera();

        let mut need_update = false;

        widgets::Window::new(hash!(), vec2(20., 20.), vec2(470., 650.))
            .label("Shader")
            .ui(&mut *root_ui(), |ui| {
                ui.label(None, "Camera: ");
                ui.same_line(0.0);
                if ui.button(None, "Ortho") {
                    camera.projection = Projection::Orthographics;
                }
                ui.same_line(0.0);
                if ui.button(None, "Perspective") {
                    camera.projection = Projection::Perspective;
                }
                ui.label(None, "Mesh: ");
                ui.same_line(0.0);
                if ui.button(None, "Sphere") {
                    mesh = Mesh::Sphere;
                }
                ui.same_line(0.0);
                if ui.button(None, "Cube") {
                    mesh = Mesh::Cube;
                }
                ui.same_line(0.0);
                if ui.button(None, "Plane") {
                    mesh = Mesh::Plane;
                }

                ui.label(None, "Uniforms:");
                ui.separator();

                for (i, (name, uniform)) in uniforms.iter_mut().enumerate() {
                    ui.label(None, &format!("{}", name));
                    ui.same_line(120.0);

                    match uniform {
                        Uniform::Float1(x) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(200.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            if let Ok(x) = x.parse::<f32>() {
                                material.set_uniform(name, x);
                            }
                        }
                        Uniform::Float2(x, y) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(99.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(99.0, 19.0))
                                .filter_numbers()
                                .ui(ui, y);

                            if let (Ok(x), Ok(y)) = (x.parse::<f32>(), y.parse::<f32>()) {
                                material.set_uniform(name, (x, y));
                            }
                        }
                        Uniform::Float3(x, y, z) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, y);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, z);

                            if let (Ok(x), Ok(y), Ok(z)) =
                                (x.parse::<f32>(), y.parse::<f32>(), z.parse::<f32>())
                            {
                                material.set_uniform(name, (x, y, z));
                            }
                        }

                        Uniform::Color(color) => {
                            let mut canvas = ui.canvas();

                            let cursor = canvas.cursor();

                            canvas.rect(
                                Rect::new(cursor.x + 20.0, cursor.y, 50.0, 18.0),
                                Color::new(0.2, 0.2, 0.2, 1.0),
                                Color::new(color.x, color.y, color.z, 1.0),
                            );

                            if ui.button(None, "change") {
                                colorpicker_window = true;
                                color_picking_uniform = Some(name.to_owned());
                            }
                            material.set_uniform(name, (color.x, color.y, color.z));
                        }
                    }
                }
                ui.separator();
                if ui.button(None, "New uniform") {
                    new_uniform_window = true;
                }
                TreeNode::new(hash!(), "Fragment shader")
                    .init_unfolded()
                    .ui(ui, |ui| {
                        if ui.editbox(hash!(), vec2(440., 200.), &mut fragment_shader) {
                            need_update = true;
                        };
                    });
                ui.tree_node(hash!(), "Vertex shader", |ui| {
                    if ui.editbox(hash!(), vec2(440., 300.), &mut vertex_shader) {
                        need_update = true;
                    };
                });

                if let Some(ref error) = error {
                    Label::new(error).multiline(14.0).ui(ui);
                }
            });

        if new_uniform_window {
            widgets::Window::new(hash!(), vec2(100., 100.), vec2(200., 80.))
                .label("New uniform")
                .ui(&mut *root_ui(), |ui| {
                    if ui.active_window_focused() == false {
                        new_uniform_window = false;
                    }
                    ui.input_text(hash!(), "Name", &mut new_uniform_name);
                    let uniform_type = ui.combo_box(
                        hash!(),
                        "Type",
                        &["Float1", "Float2", "Float3", "Color"],
                        None,
                    );

                    if ui.button(None, "Add") {
                        if new_uniform_name.is_empty() == false {
                            let uniform = match uniform_type {
                                0 => Uniform::Float1("0".to_string()),
                                1 => Uniform::Float2("0".to_string(), "0".to_string()),
                                2 => Uniform::Float3(
                                    "0".to_string(),
                                    "0".to_string(),
                                    "0".to_string(),
                                ),
                                3 => Uniform::Color(vec3(0.0, 0.0, 0.0)),
                                _ => unreachable!(),
                            };
                            uniforms.push((new_uniform_name.clone(), uniform));
                            new_uniform_name.clear();
                            need_update = true;
                        }
                        new_uniform_window = false;
                    }

                    ui.same_line(0.0);
                    if ui.button(None, "Cancel") {
                        new_uniform_window = false;
                    }
                });
        }

        if colorpicker_window {
            colorpicker_window &= widgets::Window::new(hash!(), vec2(140., 100.), vec2(210., 240.))
                .label("Colorpicker")
                .ui(&mut *root_ui(), |ui| {
                    if ui.active_window_focused() == false {
                        colorpicker_window = false;
                    }

                    let mut canvas = ui.canvas();
                    let cursor = canvas.cursor();
                    let mouse = mouse_position();
                    let x = mouse.0 as i32 - cursor.x as i32;
                    let y = mouse.1 as i32 - (cursor.y as i32 + 20);

                    let color = color_picker_image
                        .get_pixel(x.max(0).min(199) as u32, y.max(0).min(199) as u32);

                    canvas.rect(
                        Rect::new(cursor.x, cursor.y, 200.0, 18.0),
                        Color::new(0.0, 0.0, 0.0, 1.0),
                        Color::new(color.r, color.g, color.b, 1.0),
                    );
                    canvas.image(
                        Rect::new(cursor.x, cursor.y + 20.0, 200.0, 200.0),
                        &color_picker_texture,
                    );

                    if x >= 0 && x < 200 && y >= 0 && y < 200 {
                        canvas.rect(
                            Rect::new(mouse.0 - 3.5, mouse.1 - 3.5, 7.0, 7.0),
                            Color::new(0.3, 0.3, 0.3, 1.0),
                            Color::new(1.0, 1.0, 1.0, 1.0),
                        );

                        if is_mouse_button_down(MouseButton::Left) {
                            colorpicker_window = false;
                            let uniform_name = color_picking_uniform.take().unwrap();

                            uniforms
                                .iter_mut()
                                .find(|(name, _)| name == &uniform_name)
                                .unwrap()
                                .1 = Uniform::Color(vec3(color.r, color.g, color.b));
                        }
                    }
                });
        }

        if need_update {
            let uniforms = uniforms
                .iter()
                .map(|(name, uniform)| (name.clone(), uniform.uniform_type()))
                .collect::<Vec<_>>();

            match load_material(
                ShaderSource::Glsl {
                    vertex: &vertex_shader,
                    fragment: &fragment_shader,
                },
                MaterialParams {
                    pipeline_params,
                    uniforms,
                    textures: vec![],
                },
            ) {
                Ok(new_material) => {
                    material = new_material;
                    error = None;
                }
                Err(err) => {
                    error = Some(format!("{:#?}", err));
                }
            }
        }

        next_frame().await
    }
}
source

pub 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)
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
async fn main() {
    prevent_quit();

    let mut show_exit_dialog = false;
    let mut user_decided_to_exit = false;

    loop {
        clear_background(GRAY);

        if is_quit_requested() {
            show_exit_dialog = true;
        }

        if show_exit_dialog {
            let dialog_size = vec2(200., 70.);
            let screen_size = vec2(screen_width(), screen_height());
            let dialog_position = screen_size / 2. - dialog_size / 2.;
            Window::new(hash!(), dialog_position, dialog_size).ui(&mut *root_ui(), |ui| {
                ui.label(None, "Do you really want to quit?");
                ui.separator();
                ui.same_line(60.);
                if ui.button(None, "Yes") {
                    user_decided_to_exit = true;
                }
                ui.same_line(120.);
                if ui.button(None, "No") {
                    show_exit_dialog = false;
                }
            });
        }

        if user_decided_to_exit {
            break;
        }

        next_frame().await
    }
}
More examples
Hide additional examples
examples/ui.rs (line 212)
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
async fn main() {
    let mut data = Data::new();

    let mut data0 = String::new();
    let mut data1 = String::new();

    let mut text0 = String::new();
    let mut text1 = String::new();

    let mut number0 = 0.;
    let mut number1 = 0.;

    let texture: Texture2D = load_texture("examples/ferris.png").await.unwrap();

    loop {
        clear_background(WHITE);

        widgets::Window::new(hash!(), vec2(400., 200.), vec2(320., 400.))
            .label("Shop")
            .titlebar(true)
            .ui(&mut *root_ui(), |ui| {
                for i in 0..30 {
                    Group::new(hash!("shop", i), Vec2::new(300., 80.)).ui(ui, |ui| {
                        ui.label(Vec2::new(10., 10.), &format!("Item N {}", i));
                        ui.label(Vec2::new(260., 40.), "10/10");
                        ui.label(Vec2::new(200., 58.), &format!("{} kr", 800));
                        if ui.button(Vec2::new(260., 55.), "buy") {
                            data.inventory.push(format!("Item {}", i));
                        }
                    });
                }
            });

        widgets::Window::new(hash!(), vec2(100., 220.), vec2(542., 430.))
            .label("Fitting window")
            .titlebar(true)
            .ui(&mut *root_ui(), |ui| {
                Group::new(hash!(), Vec2::new(230., 400.)).ui(ui, |ui| {
                    data.slots(ui);
                });
                Group::new(hash!(), Vec2::new(280., 400.)).ui(ui, |ui| {
                    data.inventory(ui);
                });
            });

        widgets::Window::new(hash!(), vec2(470., 50.), vec2(300., 300.))
            .label("Megaui Showcase Window")
            .ui(&mut *root_ui(), |ui| {
                ui.tree_node(hash!(), "input", |ui| {
                    ui.label(None, "Some random text");
                    if ui.button(None, "click me") {
                        println!("hi");
                    }

                    ui.separator();

                    ui.label(None, "Some other random text");
                    if ui.button(None, "other button") {
                        println!("hi2");
                    }

                    ui.separator();

                    ui.input_text(hash!(), "<- input text 1", &mut data0);
                    ui.input_text(hash!(), "<- input text 2", &mut data1);
                    ui.label(
                        None,
                        &format!("Text entered: \"{}\" and \"{}\"", data0, data1),
                    );

                    ui.separator();
                });
                ui.tree_node(hash!(), "buttons", |ui| {
                    widgets::Button::new(texture.clone())
                        .size(vec2(120., 70.))
                        .ui(ui);
                    ui.same_line(0.);
                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
                    widgets::Button::new("Button").size(vec2(120., 70.)).ui(ui);
                    ui.same_line(0.);
                    widgets::Button::new(texture.clone())
                        .size(vec2(120., 70.))
                        .ui(ui);
                });
                ui.tree_node(hash!(), "sliders", |ui| {
                    ui.slider(hash!(), "[-10 .. 10]", -10f32..10f32, &mut number0);
                    ui.slider(hash!(), "[0 .. 100]", 0f32..100f32, &mut number1);
                });
                ui.tree_node(hash!(), "editbox 1", |ui| {
                    ui.label(None, "This is editbox!");
                    ui.editbox(hash!(), vec2(285., 165.), &mut text0);
                });
                ui.tree_node(hash!(), "editbox 2", |ui| {
                    ui.label(None, "This is editbox!");
                    ui.editbox(hash!(), vec2(285., 165.), &mut text1);
                });
            });

        match data.fit_command.take() {
            Some(FittingCommand::Unfit { target_slot }) => data.set_item(target_slot, None),
            Some(FittingCommand::Fit { target_slot, item }) => {
                data.set_item(target_slot, Some(item));
            }
            Some(FittingCommand::Refit {
                target_slot,
                origin_slot,
            }) => {
                let origin_item = data
                    .slots
                    .iter()
                    .find_map(|(_, slot)| {
                        if slot.id == origin_slot {
                            Some(slot.item.clone())
                        } else {
                            None
                        }
                    })
                    .flatten();
                data.set_item(target_slot, origin_item);
                data.set_item(origin_slot, None);
            }
            None => {}
        };

        next_frame().await;
    }
}
examples/ui_skins.rs (line 225)
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
async fn main() {
    let skin1 = {
        let label_style = root_ui()
            .style_builder()
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 120, 255))
            .font_size(30)
            .build();

        let window_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/window_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(20.0, 20.0, 10.0, 10.0))
            .margin(RectOffset::new(-20.0, -30.0, 0.0, 0.0))
            .build();

        let button_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(37.0, 37.0, 5.0, 5.0))
            .margin(RectOffset::new(10.0, 10.0, 0.0, 0.0))
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_hovered_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_clicked_background.png"),
                    None,
                )
                .unwrap(),
            )
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 100, 255))
            .font_size(40)
            .build();

        let editbox_style = root_ui()
            .style_builder()
            .background_margin(RectOffset::new(0., 0., 0., 0.))
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .color_selected(Color::from_rgba(190, 190, 190, 255))
            .font_size(50)
            .build();

        Skin {
            editbox_style,
            window_style,
            button_style,
            label_style,
            ..root_ui().default_skin()
        }
    };

    let skin2 = {
        let label_style = root_ui()
            .style_builder()
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .font_size(25)
            .build();

        let window_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/window_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(52.0, 52.0, 52.0, 52.0))
            .margin(RectOffset::new(-30.0, 0.0, -30.0, 0.0))
            .build();

        let button_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(8.0, 8.0, 8.0, 8.0))
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_hovered_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_clicked_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 100, 255))
            .font_size(40)
            .build();

        let checkbox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_hovered_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_clicked_background.png"),
                    None,
                )
                .unwrap(),
            )
            .build();

        let editbox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/editbox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(2., 2., 2., 2.))
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .font_size(25)
            .build();

        let combobox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/combobox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(4., 25., 6., 6.))
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .color(Color::from_rgba(210, 210, 210, 255))
            .font_size(25)
            .build();

        Skin {
            window_style,
            button_style,
            label_style,
            checkbox_style,
            editbox_style,
            combobox_style,
            ..root_ui().default_skin()
        }
    };
    let default_skin = root_ui().default_skin().clone();

    let mut window1_skin = skin1.clone();
    let mut window2_skin = skin2.clone();

    let mut checkbox = false;
    let mut text = String::new();
    let mut number = 0.0f32;
    let mut combobox = 0;

    loop {
        clear_background(GRAY);

        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
            ui.label(None, "Window 1");

            if ui.button(None, "Skin 1") {
                window1_skin = skin1.clone();
            }
            if ui.button(None, "Skin 2") {
                window1_skin = skin2.clone();
            }
            if ui.button(None, "No Skin") {
                window1_skin = default_skin.clone();
            }
        });
        root_ui().same_line(0.);
        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
            ui.label(None, "Window 2");
            if ui.button(None, "Skin 1") {
                window2_skin = skin1.clone();
            }
            if ui.button(None, "Skin 2") {
                window2_skin = skin2.clone();
            }
            if ui.button(None, "No Skin") {
                window2_skin = default_skin.clone();
            }
        });

        root_ui().push_skin(&window1_skin);

        root_ui().window(hash!(), vec2(20., 250.), vec2(300., 300.), |ui| {
            widgets::Button::new("Play")
                .position(vec2(65.0, 15.0))
                .ui(ui);
            widgets::Button::new("Options")
                .position(vec2(40.0, 75.0))
                .ui(ui);

            widgets::Button::new("Quit")
                .position(vec2(65.0, 195.0))
                .ui(ui);
        });
        root_ui().pop_skin();

        root_ui().push_skin(&window2_skin);
        root_ui().window(hash!(), vec2(250., 20.), vec2(500., 250.), |ui| {
            ui.checkbox(hash!(), "Checkbox 1", &mut checkbox);
            ui.combo_box(
                hash!(),
                "Combobox",
                &["First option", "Second option"],
                &mut combobox,
            );
            ui.input_text(hash!(), "Text", &mut text);
            ui.drag(hash!(), "Drag", None, &mut number);

            widgets::Button::new("Apply")
                .position(vec2(80.0, 150.0))
                .ui(ui);
            widgets::Button::new("Cancel")
                .position(vec2(280.0, 150.0))
                .ui(ui);
        });
        root_ui().pop_skin();

        next_frame().await;
    }
}
examples/shadertoy.rs (line 122)
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
async fn main() {
    let ferris = load_texture("examples/rust.png").await.unwrap();
    let (color_picker_texture, color_picker_image) = color_picker_texture(200, 200);

    let mut fragment_shader = DEFAULT_FRAGMENT_SHADER.to_string();
    let mut vertex_shader = DEFAULT_VERTEX_SHADER.to_string();

    let pipeline_params = PipelineParams {
        depth_write: true,
        depth_test: Comparison::LessOrEqual,
        ..Default::default()
    };

    let mut material = load_material(
        ShaderSource::Glsl {
            vertex: &vertex_shader,
            fragment: &fragment_shader,
        },
        MaterialParams {
            pipeline_params,
            ..Default::default()
        },
    )
    .unwrap();
    let mut error: Option<String> = None;

    enum Mesh {
        Sphere,
        Cube,
        Plane,
    }
    let mut mesh = Mesh::Sphere;

    let mut camera = Camera3D {
        position: vec3(-15., 15., -5.),
        up: vec3(0., 1., 0.),
        target: vec3(0., 5., -5.),
        ..Default::default()
    };

    let mut colorpicker_window = false;
    let mut color_picking_uniform = None;

    let mut new_uniform_window = false;
    let mut new_uniform_name = String::new();
    let mut uniforms: Vec<(String, Uniform)> = vec![];

    loop {
        clear_background(WHITE);

        set_camera(&camera);

        draw_grid(
            20,
            1.,
            Color::new(0.55, 0.55, 0.55, 0.75),
            Color::new(0.75, 0.75, 0.75, 0.75),
        );

        gl_use_material(&material);
        match mesh {
            Mesh::Plane => draw_plane(vec3(0., 2., 0.), vec2(5., 5.), Some(&ferris), WHITE),
            Mesh::Sphere => draw_sphere(vec3(0., 6., 0.), 5., Some(&ferris), WHITE),
            Mesh::Cube => draw_cube(vec3(0., 5., 0.), vec3(10., 10., 10.), Some(&ferris), WHITE),
        }
        gl_use_default_material();

        set_default_camera();

        let mut need_update = false;

        widgets::Window::new(hash!(), vec2(20., 20.), vec2(470., 650.))
            .label("Shader")
            .ui(&mut *root_ui(), |ui| {
                ui.label(None, "Camera: ");
                ui.same_line(0.0);
                if ui.button(None, "Ortho") {
                    camera.projection = Projection::Orthographics;
                }
                ui.same_line(0.0);
                if ui.button(None, "Perspective") {
                    camera.projection = Projection::Perspective;
                }
                ui.label(None, "Mesh: ");
                ui.same_line(0.0);
                if ui.button(None, "Sphere") {
                    mesh = Mesh::Sphere;
                }
                ui.same_line(0.0);
                if ui.button(None, "Cube") {
                    mesh = Mesh::Cube;
                }
                ui.same_line(0.0);
                if ui.button(None, "Plane") {
                    mesh = Mesh::Plane;
                }

                ui.label(None, "Uniforms:");
                ui.separator();

                for (i, (name, uniform)) in uniforms.iter_mut().enumerate() {
                    ui.label(None, &format!("{}", name));
                    ui.same_line(120.0);

                    match uniform {
                        Uniform::Float1(x) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(200.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            if let Ok(x) = x.parse::<f32>() {
                                material.set_uniform(name, x);
                            }
                        }
                        Uniform::Float2(x, y) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(99.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(99.0, 19.0))
                                .filter_numbers()
                                .ui(ui, y);

                            if let (Ok(x), Ok(y)) = (x.parse::<f32>(), y.parse::<f32>()) {
                                material.set_uniform(name, (x, y));
                            }
                        }
                        Uniform::Float3(x, y, z) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, y);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, z);

                            if let (Ok(x), Ok(y), Ok(z)) =
                                (x.parse::<f32>(), y.parse::<f32>(), z.parse::<f32>())
                            {
                                material.set_uniform(name, (x, y, z));
                            }
                        }

                        Uniform::Color(color) => {
                            let mut canvas = ui.canvas();

                            let cursor = canvas.cursor();

                            canvas.rect(
                                Rect::new(cursor.x + 20.0, cursor.y, 50.0, 18.0),
                                Color::new(0.2, 0.2, 0.2, 1.0),
                                Color::new(color.x, color.y, color.z, 1.0),
                            );

                            if ui.button(None, "change") {
                                colorpicker_window = true;
                                color_picking_uniform = Some(name.to_owned());
                            }
                            material.set_uniform(name, (color.x, color.y, color.z));
                        }
                    }
                }
                ui.separator();
                if ui.button(None, "New uniform") {
                    new_uniform_window = true;
                }
                TreeNode::new(hash!(), "Fragment shader")
                    .init_unfolded()
                    .ui(ui, |ui| {
                        if ui.editbox(hash!(), vec2(440., 200.), &mut fragment_shader) {
                            need_update = true;
                        };
                    });
                ui.tree_node(hash!(), "Vertex shader", |ui| {
                    if ui.editbox(hash!(), vec2(440., 300.), &mut vertex_shader) {
                        need_update = true;
                    };
                });

                if let Some(ref error) = error {
                    Label::new(error).multiline(14.0).ui(ui);
                }
            });

        if new_uniform_window {
            widgets::Window::new(hash!(), vec2(100., 100.), vec2(200., 80.))
                .label("New uniform")
                .ui(&mut *root_ui(), |ui| {
                    if ui.active_window_focused() == false {
                        new_uniform_window = false;
                    }
                    ui.input_text(hash!(), "Name", &mut new_uniform_name);
                    let uniform_type = ui.combo_box(
                        hash!(),
                        "Type",
                        &["Float1", "Float2", "Float3", "Color"],
                        None,
                    );

                    if ui.button(None, "Add") {
                        if new_uniform_name.is_empty() == false {
                            let uniform = match uniform_type {
                                0 => Uniform::Float1("0".to_string()),
                                1 => Uniform::Float2("0".to_string(), "0".to_string()),
                                2 => Uniform::Float3(
                                    "0".to_string(),
                                    "0".to_string(),
                                    "0".to_string(),
                                ),
                                3 => Uniform::Color(vec3(0.0, 0.0, 0.0)),
                                _ => unreachable!(),
                            };
                            uniforms.push((new_uniform_name.clone(), uniform));
                            new_uniform_name.clear();
                            need_update = true;
                        }
                        new_uniform_window = false;
                    }

                    ui.same_line(0.0);
                    if ui.button(None, "Cancel") {
                        new_uniform_window = false;
                    }
                });
        }

        if colorpicker_window {
            colorpicker_window &= widgets::Window::new(hash!(), vec2(140., 100.), vec2(210., 240.))
                .label("Colorpicker")
                .ui(&mut *root_ui(), |ui| {
                    if ui.active_window_focused() == false {
                        colorpicker_window = false;
                    }

                    let mut canvas = ui.canvas();
                    let cursor = canvas.cursor();
                    let mouse = mouse_position();
                    let x = mouse.0 as i32 - cursor.x as i32;
                    let y = mouse.1 as i32 - (cursor.y as i32 + 20);

                    let color = color_picker_image
                        .get_pixel(x.max(0).min(199) as u32, y.max(0).min(199) as u32);

                    canvas.rect(
                        Rect::new(cursor.x, cursor.y, 200.0, 18.0),
                        Color::new(0.0, 0.0, 0.0, 1.0),
                        Color::new(color.r, color.g, color.b, 1.0),
                    );
                    canvas.image(
                        Rect::new(cursor.x, cursor.y + 20.0, 200.0, 200.0),
                        &color_picker_texture,
                    );

                    if x >= 0 && x < 200 && y >= 0 && y < 200 {
                        canvas.rect(
                            Rect::new(mouse.0 - 3.5, mouse.1 - 3.5, 7.0, 7.0),
                            Color::new(0.3, 0.3, 0.3, 1.0),
                            Color::new(1.0, 1.0, 1.0, 1.0),
                        );

                        if is_mouse_button_down(MouseButton::Left) {
                            colorpicker_window = false;
                            let uniform_name = color_picking_uniform.take().unwrap();

                            uniforms
                                .iter_mut()
                                .find(|(name, _)| name == &uniform_name)
                                .unwrap()
                                .1 = Uniform::Color(vec3(color.r, color.g, color.b));
                        }
                    }
                });
        }

        if need_update {
            let uniforms = uniforms
                .iter()
                .map(|(name, uniform)| (name.clone(), uniform.uniform_type()))
                .collect::<Vec<_>>();

            match load_material(
                ShaderSource::Glsl {
                    vertex: &vertex_shader,
                    fragment: &fragment_shader,
                },
                MaterialParams {
                    pipeline_params,
                    uniforms,
                    textures: vec![],
                },
            ) {
                Ok(new_material) => {
                    material = new_material;
                    error = None;
                }
                Err(err) => {
                    error = Some(format!("{:#?}", err));
                }
            }
        }

        next_frame().await
    }
}
source

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

Examples found in repository?
examples/shadertoy.rs (line 207)
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
async fn main() {
    let ferris = load_texture("examples/rust.png").await.unwrap();
    let (color_picker_texture, color_picker_image) = color_picker_texture(200, 200);

    let mut fragment_shader = DEFAULT_FRAGMENT_SHADER.to_string();
    let mut vertex_shader = DEFAULT_VERTEX_SHADER.to_string();

    let pipeline_params = PipelineParams {
        depth_write: true,
        depth_test: Comparison::LessOrEqual,
        ..Default::default()
    };

    let mut material = load_material(
        ShaderSource::Glsl {
            vertex: &vertex_shader,
            fragment: &fragment_shader,
        },
        MaterialParams {
            pipeline_params,
            ..Default::default()
        },
    )
    .unwrap();
    let mut error: Option<String> = None;

    enum Mesh {
        Sphere,
        Cube,
        Plane,
    }
    let mut mesh = Mesh::Sphere;

    let mut camera = Camera3D {
        position: vec3(-15., 15., -5.),
        up: vec3(0., 1., 0.),
        target: vec3(0., 5., -5.),
        ..Default::default()
    };

    let mut colorpicker_window = false;
    let mut color_picking_uniform = None;

    let mut new_uniform_window = false;
    let mut new_uniform_name = String::new();
    let mut uniforms: Vec<(String, Uniform)> = vec![];

    loop {
        clear_background(WHITE);

        set_camera(&camera);

        draw_grid(
            20,
            1.,
            Color::new(0.55, 0.55, 0.55, 0.75),
            Color::new(0.75, 0.75, 0.75, 0.75),
        );

        gl_use_material(&material);
        match mesh {
            Mesh::Plane => draw_plane(vec3(0., 2., 0.), vec2(5., 5.), Some(&ferris), WHITE),
            Mesh::Sphere => draw_sphere(vec3(0., 6., 0.), 5., Some(&ferris), WHITE),
            Mesh::Cube => draw_cube(vec3(0., 5., 0.), vec3(10., 10., 10.), Some(&ferris), WHITE),
        }
        gl_use_default_material();

        set_default_camera();

        let mut need_update = false;

        widgets::Window::new(hash!(), vec2(20., 20.), vec2(470., 650.))
            .label("Shader")
            .ui(&mut *root_ui(), |ui| {
                ui.label(None, "Camera: ");
                ui.same_line(0.0);
                if ui.button(None, "Ortho") {
                    camera.projection = Projection::Orthographics;
                }
                ui.same_line(0.0);
                if ui.button(None, "Perspective") {
                    camera.projection = Projection::Perspective;
                }
                ui.label(None, "Mesh: ");
                ui.same_line(0.0);
                if ui.button(None, "Sphere") {
                    mesh = Mesh::Sphere;
                }
                ui.same_line(0.0);
                if ui.button(None, "Cube") {
                    mesh = Mesh::Cube;
                }
                ui.same_line(0.0);
                if ui.button(None, "Plane") {
                    mesh = Mesh::Plane;
                }

                ui.label(None, "Uniforms:");
                ui.separator();

                for (i, (name, uniform)) in uniforms.iter_mut().enumerate() {
                    ui.label(None, &format!("{}", name));
                    ui.same_line(120.0);

                    match uniform {
                        Uniform::Float1(x) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(200.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            if let Ok(x) = x.parse::<f32>() {
                                material.set_uniform(name, x);
                            }
                        }
                        Uniform::Float2(x, y) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(99.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(99.0, 19.0))
                                .filter_numbers()
                                .ui(ui, y);

                            if let (Ok(x), Ok(y)) = (x.parse::<f32>(), y.parse::<f32>()) {
                                material.set_uniform(name, (x, y));
                            }
                        }
                        Uniform::Float3(x, y, z) => {
                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, x);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, y);

                            ui.same_line(0.0);

                            widgets::InputText::new(hash!(hash!(), i))
                                .size(vec2(65.0, 19.0))
                                .filter_numbers()
                                .ui(ui, z);

                            if let (Ok(x), Ok(y), Ok(z)) =
                                (x.parse::<f32>(), y.parse::<f32>(), z.parse::<f32>())
                            {
                                material.set_uniform(name, (x, y, z));
                            }
                        }

                        Uniform::Color(color) => {
                            let mut canvas = ui.canvas();

                            let cursor = canvas.cursor();

                            canvas.rect(
                                Rect::new(cursor.x + 20.0, cursor.y, 50.0, 18.0),
                                Color::new(0.2, 0.2, 0.2, 1.0),
                                Color::new(color.x, color.y, color.z, 1.0),
                            );

                            if ui.button(None, "change") {
                                colorpicker_window = true;
                                color_picking_uniform = Some(name.to_owned());
                            }
                            material.set_uniform(name, (color.x, color.y, color.z));
                        }
                    }
                }
                ui.separator();
                if ui.button(None, "New uniform") {
                    new_uniform_window = true;
                }
                TreeNode::new(hash!(), "Fragment shader")
                    .init_unfolded()
                    .ui(ui, |ui| {
                        if ui.editbox(hash!(), vec2(440., 200.), &mut fragment_shader) {
                            need_update = true;
                        };
                    });
                ui.tree_node(hash!(), "Vertex shader", |ui| {
                    if ui.editbox(hash!(), vec2(440., 300.), &mut vertex_shader) {
                        need_update = true;
                    };
                });

                if let Some(ref error) = error {
                    Label::new(error).multiline(14.0).ui(ui);
                }
            });

        if new_uniform_window {
            widgets::Window::new(hash!(), vec2(100., 100.), vec2(200., 80.))
                .label("New uniform")
                .ui(&mut *root_ui(), |ui| {
                    if ui.active_window_focused() == false {
                        new_uniform_window = false;
                    }
                    ui.input_text(hash!(), "Name", &mut new_uniform_name);
                    let uniform_type = ui.combo_box(
                        hash!(),
                        "Type",
                        &["Float1", "Float2", "Float3", "Color"],
                        None,
                    );

                    if ui.button(None, "Add") {
                        if new_uniform_name.is_empty() == false {
                            let uniform = match uniform_type {
                                0 => Uniform::Float1("0".to_string()),
                                1 => Uniform::Float2("0".to_string(), "0".to_string()),
                                2 => Uniform::Float3(
                                    "0".to_string(),
                                    "0".to_string(),
                                    "0".to_string(),
                                ),
                                3 => Uniform::Color(vec3(0.0, 0.0, 0.0)),
                                _ => unreachable!(),
                            };
                            uniforms.push((new_uniform_name.clone(), uniform));
                            new_uniform_name.clear();
                            need_update = true;
                        }
                        new_uniform_window = false;
                    }

                    ui.same_line(0.0);
                    if ui.button(None, "Cancel") {
                        new_uniform_window = false;
                    }
                });
        }

        if colorpicker_window {
            colorpicker_window &= widgets::Window::new(hash!(), vec2(140., 100.), vec2(210., 240.))
                .label("Colorpicker")
                .ui(&mut *root_ui(), |ui| {
                    if ui.active_window_focused() == false {
                        colorpicker_window = false;
                    }

                    let mut canvas = ui.canvas();
                    let cursor = canvas.cursor();
                    let mouse = mouse_position();
                    let x = mouse.0 as i32 - cursor.x as i32;
                    let y = mouse.1 as i32 - (cursor.y as i32 + 20);

                    let color = color_picker_image
                        .get_pixel(x.max(0).min(199) as u32, y.max(0).min(199) as u32);

                    canvas.rect(
                        Rect::new(cursor.x, cursor.y, 200.0, 18.0),
                        Color::new(0.0, 0.0, 0.0, 1.0),
                        Color::new(color.r, color.g, color.b, 1.0),
                    );
                    canvas.image(
                        Rect::new(cursor.x, cursor.y + 20.0, 200.0, 200.0),
                        &color_picker_texture,
                    );

                    if x >= 0 && x < 200 && y >= 0 && y < 200 {
                        canvas.rect(
                            Rect::new(mouse.0 - 3.5, mouse.1 - 3.5, 7.0, 7.0),
                            Color::new(0.3, 0.3, 0.3, 1.0),
                            Color::new(1.0, 1.0, 1.0, 1.0),
                        );

                        if is_mouse_button_down(MouseButton::Left) {
                            colorpicker_window = false;
                            let uniform_name = color_picking_uniform.take().unwrap();

                            uniforms
                                .iter_mut()
                                .find(|(name, _)| name == &uniform_name)
                                .unwrap()
                                .1 = Uniform::Color(vec3(color.r, color.g, color.b));
                        }
                    }
                });
        }

        if need_update {
            let uniforms = uniforms
                .iter()
                .map(|(name, uniform)| (name.clone(), uniform.uniform_type()))
                .collect::<Vec<_>>();

            match load_material(
                ShaderSource::Glsl {
                    vertex: &vertex_shader,
                    fragment: &fragment_shader,
                },
                MaterialParams {
                    pipeline_params,
                    uniforms,
                    textures: vec![],
                },
            ) {
                Ok(new_material) => {
                    material = new_material;
                    error = None;
                }
                Err(err) => {
                    error = Some(format!("{:#?}", err));
                }
            }
        }

        next_frame().await
    }
}
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 239)
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
async fn main() {
    let skin1 = {
        let label_style = root_ui()
            .style_builder()
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 120, 255))
            .font_size(30)
            .build();

        let window_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/window_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(20.0, 20.0, 10.0, 10.0))
            .margin(RectOffset::new(-20.0, -30.0, 0.0, 0.0))
            .build();

        let button_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(37.0, 37.0, 5.0, 5.0))
            .margin(RectOffset::new(10.0, 10.0, 0.0, 0.0))
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_hovered_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_clicked_background.png"),
                    None,
                )
                .unwrap(),
            )
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 100, 255))
            .font_size(40)
            .build();

        let editbox_style = root_ui()
            .style_builder()
            .background_margin(RectOffset::new(0., 0., 0., 0.))
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .color_selected(Color::from_rgba(190, 190, 190, 255))
            .font_size(50)
            .build();

        Skin {
            editbox_style,
            window_style,
            button_style,
            label_style,
            ..root_ui().default_skin()
        }
    };

    let skin2 = {
        let label_style = root_ui()
            .style_builder()
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .font_size(25)
            .build();

        let window_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/window_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(52.0, 52.0, 52.0, 52.0))
            .margin(RectOffset::new(-30.0, 0.0, -30.0, 0.0))
            .build();

        let button_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(8.0, 8.0, 8.0, 8.0))
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_hovered_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_clicked_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 100, 255))
            .font_size(40)
            .build();

        let checkbox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_hovered_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_clicked_background.png"),
                    None,
                )
                .unwrap(),
            )
            .build();

        let editbox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/editbox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(2., 2., 2., 2.))
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .font_size(25)
            .build();

        let combobox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/combobox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(4., 25., 6., 6.))
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .color(Color::from_rgba(210, 210, 210, 255))
            .font_size(25)
            .build();

        Skin {
            window_style,
            button_style,
            label_style,
            checkbox_style,
            editbox_style,
            combobox_style,
            ..root_ui().default_skin()
        }
    };
    let default_skin = root_ui().default_skin().clone();

    let mut window1_skin = skin1.clone();
    let mut window2_skin = skin2.clone();

    let mut checkbox = false;
    let mut text = String::new();
    let mut number = 0.0f32;
    let mut combobox = 0;

    loop {
        clear_background(GRAY);

        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
            ui.label(None, "Window 1");

            if ui.button(None, "Skin 1") {
                window1_skin = skin1.clone();
            }
            if ui.button(None, "Skin 2") {
                window1_skin = skin2.clone();
            }
            if ui.button(None, "No Skin") {
                window1_skin = default_skin.clone();
            }
        });
        root_ui().same_line(0.);
        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
            ui.label(None, "Window 2");
            if ui.button(None, "Skin 1") {
                window2_skin = skin1.clone();
            }
            if ui.button(None, "Skin 2") {
                window2_skin = skin2.clone();
            }
            if ui.button(None, "No Skin") {
                window2_skin = default_skin.clone();
            }
        });

        root_ui().push_skin(&window1_skin);

        root_ui().window(hash!(), vec2(20., 250.), vec2(300., 300.), |ui| {
            widgets::Button::new("Play")
                .position(vec2(65.0, 15.0))
                .ui(ui);
            widgets::Button::new("Options")
                .position(vec2(40.0, 75.0))
                .ui(ui);

            widgets::Button::new("Quit")
                .position(vec2(65.0, 195.0))
                .ui(ui);
        });
        root_ui().pop_skin();

        root_ui().push_skin(&window2_skin);
        root_ui().window(hash!(), vec2(250., 20.), vec2(500., 250.), |ui| {
            ui.checkbox(hash!(), "Checkbox 1", &mut checkbox);
            ui.combo_box(
                hash!(),
                "Combobox",
                &["First option", "Second option"],
                &mut combobox,
            );
            ui.input_text(hash!(), "Text", &mut text);
            ui.drag(hash!(), "Drag", None, &mut number);

            widgets::Button::new("Apply")
                .position(vec2(80.0, 150.0))
                .ui(ui);
            widgets::Button::new("Cancel")
                .position(vec2(280.0, 150.0))
                .ui(ui);
        });
        root_ui().pop_skin();

        next_frame().await;
    }
}
source

pub fn pop_skin(&mut self)

Examples found in repository?
examples/ui_skins.rs (line 253)
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
async fn main() {
    let skin1 = {
        let label_style = root_ui()
            .style_builder()
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 120, 255))
            .font_size(30)
            .build();

        let window_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/window_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(20.0, 20.0, 10.0, 10.0))
            .margin(RectOffset::new(-20.0, -30.0, 0.0, 0.0))
            .build();

        let button_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(37.0, 37.0, 5.0, 5.0))
            .margin(RectOffset::new(10.0, 10.0, 0.0, 0.0))
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_hovered_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_clicked_background.png"),
                    None,
                )
                .unwrap(),
            )
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 100, 255))
            .font_size(40)
            .build();

        let editbox_style = root_ui()
            .style_builder()
            .background_margin(RectOffset::new(0., 0., 0., 0.))
            .font(include_bytes!("../examples/ui_assets/HTOWERT.TTF"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .color_selected(Color::from_rgba(190, 190, 190, 255))
            .font_size(50)
            .build();

        Skin {
            editbox_style,
            window_style,
            button_style,
            label_style,
            ..root_ui().default_skin()
        }
    };

    let skin2 = {
        let label_style = root_ui()
            .style_builder()
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .font_size(25)
            .build();

        let window_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/window_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(52.0, 52.0, 52.0, 52.0))
            .margin(RectOffset::new(-30.0, 0.0, -30.0, 0.0))
            .build();

        let button_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(8.0, 8.0, 8.0, 8.0))
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_hovered_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/button_clicked_background_2.png"),
                    None,
                )
                .unwrap(),
            )
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(180, 180, 100, 255))
            .font_size(40)
            .build();

        let checkbox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_hovered(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_hovered_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_clicked(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/checkbox_clicked_background.png"),
                    None,
                )
                .unwrap(),
            )
            .build();

        let editbox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/editbox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(2., 2., 2., 2.))
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .font_size(25)
            .build();

        let combobox_style = root_ui()
            .style_builder()
            .background(
                Image::from_file_with_format(
                    include_bytes!("../examples/ui_assets/combobox_background.png"),
                    None,
                )
                .unwrap(),
            )
            .background_margin(RectOffset::new(4., 25., 6., 6.))
            .font(include_bytes!("../examples/ui_assets/MinimalPixel v2.ttf"))
            .unwrap()
            .text_color(Color::from_rgba(120, 120, 120, 255))
            .color(Color::from_rgba(210, 210, 210, 255))
            .font_size(25)
            .build();

        Skin {
            window_style,
            button_style,
            label_style,
            checkbox_style,
            editbox_style,
            combobox_style,
            ..root_ui().default_skin()
        }
    };
    let default_skin = root_ui().default_skin().clone();

    let mut window1_skin = skin1.clone();
    let mut window2_skin = skin2.clone();

    let mut checkbox = false;
    let mut text = String::new();
    let mut number = 0.0f32;
    let mut combobox = 0;

    loop {
        clear_background(GRAY);

        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
            ui.label(None, "Window 1");

            if ui.button(None, "Skin 1") {
                window1_skin = skin1.clone();
            }
            if ui.button(None, "Skin 2") {
                window1_skin = skin2.clone();
            }
            if ui.button(None, "No Skin") {
                window1_skin = default_skin.clone();
            }
        });
        root_ui().same_line(0.);
        root_ui().group(hash!(), vec2(70.0, 100.0), |ui| {
            ui.label(None, "Window 2");
            if ui.button(None, "Skin 1") {
                window2_skin = skin1.clone();
            }
            if ui.button(None, "Skin 2") {
                window2_skin = skin2.clone();
            }
            if ui.button(None, "No Skin") {
                window2_skin = default_skin.clone();
            }
        });

        root_ui().push_skin(&window1_skin);

        root_ui().window(hash!(), vec2(20., 250.), vec2(300., 300.), |ui| {
            widgets::Button::new("Play")
                .position(vec2(65.0, 15.0))
                .ui(ui);
            widgets::Button::new("Options")
                .position(vec2(40.0, 75.0))
                .ui(ui);

            widgets::Button::new("Quit")
                .position(vec2(65.0, 195.0))
                .ui(ui);
        });
        root_ui().pop_skin();

        root_ui().push_skin(&window2_skin);
        root_ui().window(hash!(), vec2(250., 20.), vec2(500., 250.), |ui| {
            ui.checkbox(hash!(), "Checkbox 1", &mut checkbox);
            ui.combo_box(
                hash!(),
                "Combobox",
                &["First option", "Second option"],
                &mut combobox,
            );
            ui.input_text(hash!(), "Text", &mut text);
            ui.drag(hash!(), "Drag", None, &mut number);

            widgets::Button::new("Apply")
                .position(vec2(80.0, 150.0))
                .ui(ui);
            widgets::Button::new("Cancel")
                .position(vec2(280.0, 150.0))
                .ui(ui);
        });
        root_ui().pop_skin();

        next_frame().await;
    }
}

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 !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.

§

impl<S> FromSample<S> for S

§

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.

§

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

§

fn to_sample_(self) -> U

source§

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

§

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>,

§

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.
§

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