use crate::{
MainWindow, SettingsModel, ViewportModel,
bridge::render_thread::{RenderContext, resolve_material},
gui::{
is_c_axis_override_available,
optics::crystal_optics::{
crystal_system_from_index, is_biaxial, optical_character_from_index, save_gem_material,
},
refresh_material_options, show_toast,
},
};
use indicatrix::optics::materials::GemMaterial;
use indicatrix_vault::db::sqlite::Database;
use slint::{ComponentHandle, SharedString};
use std::sync::{Arc, Mutex};
pub(in crate::gui) fn setup_custom_material_callbacks(
ui: &MainWindow,
render_ctx: &Arc<Mutex<RenderContext>>,
db: &Arc<Mutex<Database>>,
) {
let render_ctx_save = render_ctx.clone();
let db_save = db.clone();
let ui_weak_save = ui.as_weak();
ui.global::<ViewportModel>().on_save_custom_material(
move |name: SharedString,
ri: f32,
disp: f32,
biref: f32,
color_idx: i32,
crystal_system_idx: i32,
optical_character_idx: i32,
biaxial_delta_beta_alpha: f32| {
let abs_rgb = match color_idx {
1 => [2.8f32, 1.2, 0.1], 2 => [0.1f32, 2.5, 2.2], 3 => [2.2f32, 0.2, 2.0], 4 => [1.8f32, 1.6, 0.2], 5 => [0.2f32, 0.4, 2.8], 6 => [0.4f32, 2.2, 1.6], 7 => [0.2f32, 0.6, 1.8], 8 => [1.2f32, 0.4, 0.1], _ => [0.0f32, 0.0, 0.0], };
let mut new_mat = GemMaterial::new_custom(&name, ri, disp, biref, abs_rgb);
if let Some(cs) = crystal_system_from_index(crystal_system_idx) {
new_mat.crystal_system = cs;
}
if let Some(oc) = optical_character_from_index(optical_character_idx) {
new_mat.optical_character = oc;
}
new_mat.biaxial_delta_beta_alpha =
is_biaxial(new_mat.optical_character).then_some(biaxial_delta_beta_alpha);
let _ = save_gem_material(&db_save.lock().unwrap(), &new_mat, ri, disp, biref, abs_rgb);
let c_axis_available = is_c_axis_override_available(&new_mat);
let mut ctx = render_ctx_save.lock().unwrap();
let materials = Arc::make_mut(&mut ctx.custom_materials);
if let Some(pos) = materials
.iter()
.position(|m| m.name.eq_ignore_ascii_case(&name))
{
materials[pos] = new_mat;
} else {
materials.push(new_mat);
}
ctx.material_name = name.to_string();
ctx.dirty = true;
let custom_list = ctx.custom_materials.clone();
drop(ctx);
if let Some(ui) = ui_weak_save.upgrade() {
refresh_material_options(&ui, &custom_list);
ui.global::<SettingsModel>()
.set_c_axis_override_available(c_axis_available);
show_toast(
&ui,
&format!("Saved and applied custom material '{name}'"),
"success",
);
}
},
);
let render_ctx_del = render_ctx.clone();
let db_del = db.clone();
let ui_weak_del = ui.as_weak();
ui.global::<ViewportModel>()
.on_delete_custom_material(move |name: SharedString| {
let _ = db_del.lock().unwrap().delete_custom_material(&name);
let mut ctx = render_ctx_del.lock().unwrap();
Arc::make_mut(&mut ctx.custom_materials)
.retain(|m| !m.name.eq_ignore_ascii_case(&name));
if ctx.material_name.eq_ignore_ascii_case(&name) {
ctx.material_name = "Diamond".to_string();
}
ctx.dirty = true;
let c_axis_available = is_c_axis_override_available(&resolve_material(
&GemMaterial::all_materials(),
&ctx.custom_materials,
&ctx.material_name,
));
let custom_list = ctx.custom_materials.clone();
drop(ctx);
if let Some(ui) = ui_weak_del.upgrade() {
refresh_material_options(&ui, &custom_list);
ui.global::<SettingsModel>()
.set_c_axis_override_available(c_axis_available);
show_toast(&ui, &format!("Deleted material '{name}'"), "info");
}
});
}