Skip to main content

polyscope_ui/
quantity_ui.rs

1//! Quantity-specific UI builders.
2
3use egui::Ui;
4use glam::Vec3;
5use polyscope_core::quantity::ParamVizStyle;
6
7/// Builds UI for a scalar quantity.
8pub fn build_scalar_quantity_ui(
9    ui: &mut Ui,
10    name: &str,
11    enabled: &mut bool,
12    colormap: &mut String,
13    range_min: &mut f32,
14    range_max: &mut f32,
15    available_colormaps: &[&str],
16) -> bool {
17    let mut changed = false;
18
19    ui.horizontal(|ui| {
20        if ui.checkbox(enabled, name).changed() {
21            changed = true;
22        }
23    });
24
25    if *enabled {
26        ui.indent(name, |ui| {
27            // Colormap selector
28            egui::ComboBox::from_label("Colormap")
29                .selected_text(colormap.as_str())
30                .show_ui(ui, |ui| {
31                    for &cmap in available_colormaps {
32                        if ui
33                            .selectable_value(colormap, cmap.to_string(), cmap)
34                            .changed()
35                        {
36                            changed = true;
37                        }
38                    }
39                });
40
41            // Range controls
42            ui.horizontal(|ui| {
43                ui.label("Range:");
44                if ui
45                    .add(egui::DragValue::new(range_min).speed(0.01))
46                    .changed()
47                {
48                    changed = true;
49                }
50                ui.label("–");
51                if ui
52                    .add(egui::DragValue::new(range_max).speed(0.01))
53                    .changed()
54                {
55                    changed = true;
56                }
57            });
58        });
59    }
60
61    changed
62}
63
64/// Builds UI for a color quantity.
65pub fn build_color_quantity_ui(
66    ui: &mut Ui,
67    name: &str,
68    enabled: &mut bool,
69    num_colors: usize,
70) -> bool {
71    let mut changed = false;
72
73    ui.horizontal(|ui| {
74        if ui.checkbox(enabled, name).changed() {
75            changed = true;
76        }
77        ui.label(format!("({num_colors} colors)"));
78    });
79
80    changed
81}
82
83/// Builds UI for a vector quantity.
84pub fn build_vector_quantity_ui(
85    ui: &mut Ui,
86    name: &str,
87    enabled: &mut bool,
88    length_scale: &mut f32,
89    radius: &mut f32,
90    color: &mut [f32; 3],
91) -> bool {
92    let mut changed = false;
93
94    ui.horizontal(|ui| {
95        if ui.checkbox(enabled, name).changed() {
96            changed = true;
97        }
98    });
99
100    if *enabled {
101        ui.indent(name, |ui| {
102            egui::Grid::new(format!("{name}_vector_grid"))
103                .num_columns(2)
104                .show(ui, |ui| {
105                    ui.label("Length:");
106                    if ui
107                        .add(
108                            egui::DragValue::new(length_scale)
109                                .speed(0.001)
110                                .range(0.0001..=10.0),
111                        )
112                        .changed()
113                    {
114                        changed = true;
115                    }
116                    ui.end_row();
117
118                    ui.label("Radius:");
119                    if ui
120                        .add(
121                            egui::DragValue::new(radius)
122                                .speed(0.00001)
123                                .range(0.00001..=0.1),
124                        )
125                        .changed()
126                    {
127                        changed = true;
128                    }
129                    ui.end_row();
130
131                    ui.label("Color:");
132                    if ui.color_edit_button_rgb(color).changed() {
133                        changed = true;
134                    }
135                    ui.end_row();
136                });
137        });
138    }
139
140    changed
141}
142
143/// Builds UI for a parameterization quantity.
144pub fn build_parameterization_quantity_ui(
145    ui: &mut Ui,
146    name: &str,
147    enabled: &mut bool,
148    style: &mut ParamVizStyle,
149    checker_size: &mut f32,
150    checker_colors: &mut [Vec3; 2],
151) -> bool {
152    let mut changed = false;
153
154    ui.horizontal(|ui| {
155        if ui.checkbox(enabled, name).changed() {
156            changed = true;
157        }
158    });
159
160    if *enabled {
161        ui.indent(name, |ui| {
162            // Style selector
163            let style_label = match style {
164                ParamVizStyle::Checker => "Checker",
165                ParamVizStyle::Grid => "Grid",
166                ParamVizStyle::LocalCheck => "LocalCheck",
167                ParamVizStyle::LocalRad => "LocalRad",
168            };
169            egui::ComboBox::from_label("Style")
170                .selected_text(style_label)
171                .show_ui(ui, |ui| {
172                    if ui
173                        .selectable_value(style, ParamVizStyle::Checker, "Checker")
174                        .changed()
175                    {
176                        changed = true;
177                    }
178                    if ui
179                        .selectable_value(style, ParamVizStyle::Grid, "Grid")
180                        .changed()
181                    {
182                        changed = true;
183                    }
184                    if ui
185                        .selectable_value(style, ParamVizStyle::LocalCheck, "LocalCheck")
186                        .changed()
187                    {
188                        changed = true;
189                    }
190                    if ui
191                        .selectable_value(style, ParamVizStyle::LocalRad, "LocalRad")
192                        .changed()
193                    {
194                        changed = true;
195                    }
196                });
197
198            egui::Grid::new(format!("{name}_param_grid"))
199                .num_columns(2)
200                .show(ui, |ui| {
201                    ui.label("Checker size:");
202                    if ui
203                        .add(
204                            egui::DragValue::new(checker_size)
205                                .speed(0.005)
206                                .range(0.001..=10.0),
207                        )
208                        .changed()
209                    {
210                        changed = true;
211                    }
212                    ui.end_row();
213
214                    ui.label("Color 1:");
215                    let mut c = [
216                        checker_colors[0].x,
217                        checker_colors[0].y,
218                        checker_colors[0].z,
219                    ];
220                    if ui.color_edit_button_rgb(&mut c).changed() {
221                        checker_colors[0] = Vec3::new(c[0], c[1], c[2]);
222                        changed = true;
223                    }
224                    ui.end_row();
225
226                    ui.label("Color 2:");
227                    let mut c = [
228                        checker_colors[1].x,
229                        checker_colors[1].y,
230                        checker_colors[1].z,
231                    ];
232                    if ui.color_edit_button_rgb(&mut c).changed() {
233                        checker_colors[1] = Vec3::new(c[0], c[1], c[2]);
234                        changed = true;
235                    }
236                    ui.end_row();
237                });
238        });
239    }
240
241    changed
242}
243
244/// Builds UI for an intrinsic vector quantity.
245pub fn build_intrinsic_vector_quantity_ui(
246    ui: &mut Ui,
247    name: &str,
248    enabled: &mut bool,
249    length_scale: &mut f32,
250    radius: &mut f32,
251    color: &mut [f32; 3],
252    n_sym: &mut u32,
253) -> bool {
254    let mut changed = false;
255
256    ui.horizontal(|ui| {
257        if ui.checkbox(enabled, name).changed() {
258            changed = true;
259        }
260    });
261
262    if *enabled {
263        ui.indent(name, |ui| {
264            egui::Grid::new(format!("{name}_intrinsic_grid"))
265                .num_columns(2)
266                .show(ui, |ui| {
267                    ui.label("Length:");
268                    if ui
269                        .add(
270                            egui::DragValue::new(length_scale)
271                                .speed(0.001)
272                                .range(0.0001..=10.0),
273                        )
274                        .changed()
275                    {
276                        changed = true;
277                    }
278                    ui.end_row();
279
280                    ui.label("Radius:");
281                    if ui
282                        .add(
283                            egui::DragValue::new(radius)
284                                .speed(0.00001)
285                                .range(0.00001..=0.1),
286                        )
287                        .changed()
288                    {
289                        changed = true;
290                    }
291                    ui.end_row();
292
293                    ui.label("Color:");
294                    if ui.color_edit_button_rgb(color).changed() {
295                        changed = true;
296                    }
297                    ui.end_row();
298
299                    // Symmetry control
300                    ui.label("Symmetry:");
301                    let sym_label = match *n_sym {
302                        1 => "Vector (1)",
303                        2 => "Line (2)",
304                        4 => "Cross (4)",
305                        _ => "Custom",
306                    };
307                    egui::ComboBox::from_id_salt(format!("{name}_sym"))
308                        .selected_text(sym_label)
309                        .show_ui(ui, |ui| {
310                            if ui.selectable_value(n_sym, 1, "Vector (1)").changed() {
311                                changed = true;
312                            }
313                            if ui.selectable_value(n_sym, 2, "Line (2)").changed() {
314                                changed = true;
315                            }
316                            if ui.selectable_value(n_sym, 4, "Cross (4)").changed() {
317                                changed = true;
318                            }
319                        });
320                    ui.end_row();
321                });
322        });
323    }
324
325    changed
326}