use super::{
design_mesh::MeshLibrary,
render::{Pixels, RenderRequest, SharedPick, ViewRenderer},
scene::{FitInputs, RoughMesh, Scene, SceneKind, StoneDraw, build_fit_scene},
};
use crate::{
RoughPlannerWindow,
gui::{latest_worker::LatestWorker, rough_plan::host::on_host},
};
use indicatrix_cut_core::rough_plan::RoughLayout;
use slint::Weak;
use std::{
collections::BTreeMap,
sync::{
Arc,
atomic::{AtomicBool, Ordering},
},
};
pub(super) struct BuildRequest {
pub(super) ticket: u64,
pub(super) epoch: u64,
pub(super) layout: RoughLayout,
pub(super) rough: Arc<RoughMesh>,
pub(super) titles: BTreeMap<i64, String>,
pub(super) mesh_ids: BTreeMap<i64, StoneDraw>,
}
fn report_failure(window: &Weak<RoughPlannerWindow>) {
let _ = window.upgrade_in_event_loop(move |_window| {
on_host(super::draw_failed);
});
}
#[must_use]
pub(super) fn spawn_render_worker(
window: Weak<RoughPlannerWindow>,
picks: SharedPick,
) -> LatestWorker<RenderRequest> {
let mut renderer = ViewRenderer::default();
let rebuild = Arc::new(AtomicBool::new(false));
let panicked = Arc::clone(&rebuild);
let failed_window = window.clone();
LatestWorker::spawn_with_panic_hook(
"rough-view",
move |request: RenderRequest| {
if rebuild.swap(false, Ordering::AcqRel) {
renderer = ViewRenderer::default();
}
let generation = request.generation;
let pixels: Pixels = renderer.render(&request, Some(&picks));
let _ = window.upgrade_in_event_loop(move |_window| {
on_host(|host| super::frame_ready(host, generation, pixels));
});
},
move || {
panicked.store(true, Ordering::Release);
report_failure(&failed_window);
},
)
}
#[must_use]
pub(super) fn spawn_build_worker(
window: Weak<RoughPlannerWindow>,
meshes: Arc<MeshLibrary>,
) -> LatestWorker<BuildRequest> {
let failed_window = window.clone();
LatestWorker::spawn_with_panic_hook(
"rough-view-scene",
move |request: BuildRequest| {
meshes.refresh(request.epoch);
let fit = build_fit_scene(
&FitInputs {
layout: &request.layout,
rough: &request.rough,
titles: &request.titles,
mesh_ids: &request.mesh_ids,
},
&*meshes,
);
let scene = Arc::new(Scene::new(SceneKind::Fit(Box::new(fit))));
let ticket = request.ticket;
let _ = window.upgrade_in_event_loop(move |_window| {
on_host(|host| super::scene_ready(host, ticket, scene));
});
},
move || report_failure(&failed_window),
)
}