use super::scaled_viewport_size;
use crate::{
EditorModel, MainWindow, SolidPreviewModel,
bridge::render_thread::RenderContext,
gui::{
editor::{
auto_solve,
manipulate::{frame_updates_mast_cache, note_committed_replan_submitted},
state::{
EditorState, apply_multi_selection, manufacturability_warnings_tagged_with,
push_multi_selected_count, push_tiers, status_text_and_is_problem_from_solved,
tier_items_from_solved_with_warnings, yield_report_texts_from_solved,
},
},
render::camera_lighting::contained_request_size,
solid_preview::{
cut_slider,
preview_state::{CameraPose, ReplanRequest, SolidLastSolved, SolidPreviewState},
},
},
};
use indicatrix::geometry::meet_solver::SolvedTier;
use indicatrix_cut_core::{Design, ManufacturabilityWarning};
use slint::{ComponentHandle, SharedString};
use std::{
collections::BTreeSet,
sync::{Arc, Mutex, PoisonError, atomic::Ordering as AtomicOrdering},
};
pub(in crate::gui::editor) fn submit_preview_replan(
ui: &MainWindow,
render_ctx: &Arc<Mutex<RenderContext>>,
preview_state: &Arc<SolidPreviewState>,
solid_last_solved: &SolidLastSolved,
state: &EditorState,
dirty: BTreeSet<usize>,
force_full_solve: bool,
) {
submit_preview_replan_for(
ui,
render_ctx,
preview_state,
solid_last_solved,
ReplanSource {
design: &state.design,
generation: state.generation.load(AtomicOrdering::Relaxed),
multi_selected: &state.multi_selected,
},
dirty,
force_full_solve,
);
}
#[derive(Clone, Copy)]
pub(in crate::gui::editor) struct ReplanSource<'a> {
pub(in crate::gui::editor) design: &'a Design,
pub(in crate::gui::editor) generation: u64,
pub(in crate::gui::editor) multi_selected: &'a BTreeSet<usize>,
}
pub(in crate::gui::editor) fn submit_preview_replan_for(
ui: &MainWindow,
render_ctx: &Arc<Mutex<RenderContext>>,
preview_state: &Arc<SolidPreviewState>,
solid_last_solved: &SolidLastSolved,
source: ReplanSource<'_>,
dirty: BTreeSet<usize>,
force_full_solve: bool,
) {
let generation = source.generation;
let last_solved = if force_full_solve {
None
} else {
solid_last_solved
.lock()
.unwrap_or_else(PoisonError::into_inner)
.as_ref()
.and_then(|(cached_generation, masts)| {
(*cached_generation == generation || *cached_generation + 1 == generation)
.then(|| masts.clone())
})
};
submit_preview_replan_chained(ui, render_ctx, preview_state, source, dirty, last_solved);
}
pub(in crate::gui::editor) fn submit_preview_replan_chained(
ui: &MainWindow,
render_ctx: &Arc<Mutex<RenderContext>>,
preview_state: &Arc<SolidPreviewState>,
source: ReplanSource<'_>,
dirty: BTreeSet<usize>,
last_solved: Option<Vec<SolvedTier>>,
) {
super::super::optimize_apply::cancel_ghost_preview();
let ReplanSource {
design,
generation,
multi_selected,
} = source;
let (camera, render_size, n_d) = {
let ctx = render_ctx
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
(
CameraPose {
yaw: ctx.yaw,
pitch: ctx.pitch,
distance: ctx.distance,
},
(ctx.width, ctx.height),
design.effective_refractive_index_with(&ctx.custom_materials),
)
};
let selected_tier = usize::try_from(ui.global::<EditorModel>().get_selected_tier_index())
.ok()
.filter(|&index| index < design.tiers.len() + design.concave_tiers.len());
let view_mode = ui.global::<SolidPreviewModel>().get_view_mode() as u8;
let size = contained_request_size(view_mode, scaled_viewport_size(ui), render_size);
let show_preform = ui.global::<SolidPreviewModel>().get_show_preform_planes();
let enlarged_panel = ui
.global::<SolidPreviewModel>()
.get_diagram_enlarged_panel();
let design_snapshot = Arc::new(design.clone());
if frame_updates_mast_cache(generation) {
note_committed_replan_submitted();
auto_solve::stash_current_design(
generation,
Arc::clone(&design_snapshot),
multi_selected.clone(),
);
}
let position_steps = if frame_updates_mast_cache(generation) {
cut_slider::sync_model(ui, design)
} else {
cut_slider::current_steps(ui, design)
};
preview_state.set_cut_steps(position_steps.filter(|_| view_mode != 3));
preview_state.request_replan(ReplanRequest {
design: Arc::clone(&design_snapshot),
dirty,
last_solved,
camera,
size,
selected_tier,
n_d,
view_mode,
generation,
show_preform,
enlarged_panel,
});
}
pub(in crate::gui::editor) fn push_solved_preview(
ui: &MainWindow,
design: &Design,
solved: &[SolvedTier],
multi_selected: &BTreeSet<usize>,
custom_materials: &[indicatrix::optics::materials::GemMaterial],
custom_sg: &[(String, f64)],
precomputed_warnings: Option<&[ManufacturabilityWarning]>,
) {
let n_d = design.effective_refractive_index_with(custom_materials);
push_tier_rows(
ui,
design,
solved,
multi_selected,
n_d,
precomputed_warnings,
);
let (status_text, is_problem) = status_text_and_is_problem_from_solved(design, solved);
ui.global::<EditorModel>()
.set_status_text(status_text.into());
ui.global::<EditorModel>().set_status_is_problem(is_problem);
ui.global::<EditorModel>()
.set_solve_state(if is_problem { "failed" } else { "solved" }.into());
crate::gui::editor::guide::check_design_progress(ui, design);
push_warning_list(ui, design, solved, precomputed_warnings);
let (vol_yield_text, carat_text, sg_used_text, fit_text) =
yield_report_texts_from_solved(design, solved, custom_sg);
ui.global::<EditorModel>()
.set_volumetric_yield_text(vol_yield_text.into());
ui.global::<EditorModel>()
.set_carat_weight_text(carat_text.into());
ui.global::<EditorModel>()
.set_specific_gravity_used_text(sg_used_text.into());
ui.global::<EditorModel>()
.set_preform_fit_warning(fit_text.into());
super::super::panel::push_proportion_verdicts_from_solved(ui, design, Some(solved), n_d);
}
pub(in crate::gui::editor) fn push_late_findings(
ui: &MainWindow,
design: &Design,
solved: &[SolvedTier],
multi_selected: &BTreeSet<usize>,
custom_materials: &[indicatrix::optics::materials::GemMaterial],
findings: &[ManufacturabilityWarning],
) {
let n_d = design.effective_refractive_index_with(custom_materials);
push_tier_rows(ui, design, solved, multi_selected, n_d, Some(findings));
push_warning_list(ui, design, solved, Some(findings));
}
fn push_tier_rows(
ui: &MainWindow,
design: &Design,
solved: &[SolvedTier],
multi_selected: &BTreeSet<usize>,
n_d: f64,
precomputed_warnings: Option<&[ManufacturabilityWarning]>,
) {
let mut tiers = tier_items_from_solved_with_warnings(design, solved, n_d, precomputed_warnings);
apply_multi_selection(&mut tiers, multi_selected);
push_tiers(ui, tiers);
push_multi_selected_count(ui, multi_selected.len());
}
fn push_warning_list(
ui: &MainWindow,
design: &Design,
solved: &[SolvedTier],
precomputed_warnings: Option<&[ManufacturabilityWarning]>,
) {
let tagged_warnings =
manufacturability_warnings_tagged_with(design, solved, precomputed_warnings);
let warning_tiers: Vec<i32> = tagged_warnings
.iter()
.map(|(index, _)| i32::try_from(*index).unwrap_or(i32::MAX))
.collect();
let warnings: Vec<SharedString> = tagged_warnings
.into_iter()
.map(|(_, text)| SharedString::from(text))
.collect();
super::super::state::push_rows(
&ui.global::<EditorModel>().get_manufacturability_warnings(),
warnings,
|model| {
ui.global::<EditorModel>()
.set_manufacturability_warnings(model);
},
);
super::super::state::push_rows(
&ui.global::<EditorModel>()
.get_manufacturability_warning_tiers(),
warning_tiers,
|model| {
ui.global::<EditorModel>()
.set_manufacturability_warning_tiers(model);
},
);
}