use egui::Color32;
use egui_wgpu::RenderState;
use crate::core::colormap::{AutoscaleMode, ColormapName};
use crate::widget::colorbar::ColorBarWidget;
use crate::widget::scalar_field_view::ScalarFieldView;
const DEFAULT_NEW_ISO_COLOR: Color32 = Color32::from_rgb(255, 215, 0);
pub struct ScalarFieldProperties {
colormap_name: ColormapName,
autoscale_mode: AutoscaleMode,
}
impl Default for ScalarFieldProperties {
fn default() -> Self {
Self::new()
}
}
impl ScalarFieldProperties {
pub fn new() -> Self {
Self {
colormap_name: ColormapName::Viridis,
autoscale_mode: AutoscaleMode::MinMax,
}
}
pub fn colormap_name(&self) -> ColormapName {
self.colormap_name
}
pub fn ui(
&mut self,
ui: &mut egui::Ui,
view: &mut ScalarFieldView,
render_state: &RenderState,
) -> bool {
let mut changed = false;
ui.label("Cut plane");
let mut visible = view.field().cut_plane().is_visible();
if ui.checkbox(&mut visible, "Visible").changed() {
view.field_mut().cut_plane_mut().set_visible(visible);
changed = true;
}
let mut name = self.colormap_name;
egui::ComboBox::from_id_salt("scalar_field_cmap")
.selected_text(name.label())
.show_ui(ui, |ui| {
for n in ColormapName::ALL {
ui.selectable_value(&mut name, n, n.label());
}
});
if name != self.colormap_name {
self.colormap_name = name;
view.field_mut()
.cut_plane_mut()
.colormap_mut()
.set_name(name);
changed = true;
}
let (mut vmin, mut vmax) = {
let cm = view.field().cut_plane().colormap();
(cm.vmin, cm.vmax)
};
ui.horizontal(|ui| {
ui.label("Range");
let r_min = ui.add(egui::DragValue::new(&mut vmin).speed(0.01));
let r_max = ui.add(egui::DragValue::new(&mut vmax).speed(0.01));
if r_min.changed() || r_max.changed() {
let cm = view.field_mut().cut_plane_mut().colormap_mut();
cm.vmin = vmin;
cm.vmax = vmax;
changed = true;
}
});
ui.horizontal(|ui| {
egui::ComboBox::from_id_salt("scalar_field_autoscale")
.selected_text(self.autoscale_mode.label())
.show_ui(ui, |ui| {
for mode in AutoscaleMode::ALL {
ui.selectable_value(&mut self.autoscale_mode, mode, mode.label());
}
});
if ui.button("Autoscale").clicked() {
view.field_mut()
.autoscale_cut_plane_colormap(self.autoscale_mode);
changed = true;
}
});
let colorbar =
ColorBarWidget::new(view.field().cut_plane().colormap().clone()).with_legend("Data");
colorbar.ui(ui, egui::vec2(64.0, 160.0));
ui.separator();
ui.label("Iso-surfaces");
let isos: Vec<(f32, Color32)> = view
.field()
.isosurfaces()
.iter()
.map(|iso| (iso.level(), iso.color()))
.collect();
let mut level_edits: Vec<(usize, f32)> = Vec::new();
let mut color_edits: Vec<(usize, Color32)> = Vec::new();
let mut remove: Option<usize> = None;
for (i, (level, color)) in isos.iter().enumerate() {
ui.horizontal(|ui| {
ui.label(format!("#{i}"));
let mut lvl = *level;
if ui
.add(egui::DragValue::new(&mut lvl).speed(0.01))
.on_hover_text("Iso-level")
.changed()
{
level_edits.push((i, lvl));
}
let mut col = *color;
if ui.color_edit_button_srgba(&mut col).changed() {
color_edits.push((i, col));
}
if ui.button("Remove").clicked() {
remove = Some(i);
}
});
}
for (i, lvl) in level_edits {
if let Some(iso) = view.field_mut().isosurface_mut(i) {
iso.set_level(lvl);
changed = true;
}
}
for (i, col) in color_edits {
if let Some(iso) = view.field_mut().isosurface_mut(i) {
iso.set_color(col);
changed = true;
}
}
if let Some(i) = remove {
view.field_mut().remove_isosurface(i);
changed = true;
}
if ui.button("Add iso-surface").clicked() {
let level = view
.field()
.data_range()
.map(|(min, _, max)| 0.5 * (min + max))
.unwrap_or(0.5);
view.field_mut()
.add_isosurface(level, DEFAULT_NEW_ISO_COLOR);
changed = true;
}
if changed {
view.rebuild(render_state);
}
changed
}
}