use super::finish;
use crate::MainWindow;
use indicatrix::{
geometry::meet_solver::SolvedTier,
optics::{LightingPreset, materials::GemMaterial},
};
use indicatrix_cut_core::Design;
use indicatrix_editor::{
material_lookup::{EditorMaterialLookup, resolved_gem_material},
retarget::metrics::measure_column,
verdict::{SolveFacts, VerdictInputs, gather},
};
use std::{
panic::{AssertUnwindSafe, catch_unwind},
sync::Arc,
};
pub(super) struct Job {
pub(super) design: Design,
pub(super) solved: Option<Vec<SolvedTier>>,
pub(super) n_d: f64,
pub(super) lighting: LightingPreset,
pub(super) custom: Option<Arc<Vec<GemMaterial>>>,
pub(super) serial: u64,
pub(super) ui_weak: slint::Weak<MainWindow>,
}
fn design_gem(design: &Design, custom: &[GemMaterial]) -> Option<GemMaterial> {
let material = &design.material;
(material.name.is_some() || material.refractive_index_override.is_some())
.then(|| resolved_gem_material(material, &EditorMaterialLookup::new(custom)))
}
pub(super) fn compute(
design: &Design,
solved: Option<&[SolvedTier]>,
n_d: f64,
lighting: LightingPreset,
custom: Option<&[GemMaterial]>,
) -> VerdictInputs {
let inputs = gather(design, solved, n_d, None);
if inputs.solve != SolveFacts::Closed {
return inputs;
}
let (Some(solved), Some(custom)) = (solved, custom) else {
return inputs;
};
let Some(gem) = design_gem(design, custom) else {
return inputs;
};
let planes = design.planes_from_solved(solved);
let column = measure_column(&planes, &gem, lighting);
inputs.with_optics(Some(column))
}
pub(super) fn spawn(job: Job) {
std::thread::spawn(move || {
let Job {
design,
solved,
n_d,
lighting,
custom,
serial,
ui_weak,
} = job;
let had_solution = solved.is_some();
let outcome = catch_unwind(AssertUnwindSafe(|| {
compute(
&design,
solved.as_deref(),
n_d,
lighting,
custom.as_deref().map(Vec::as_slice),
)
}));
let _ = ui_weak.upgrade_in_event_loop(move |ui| {
finish(&ui, serial, had_solution, outcome.ok());
});
});
}