Files
OneCAD/crates/ui-egui/src/browser_model.rs
T

65 lines
2.6 KiB
Rust

//! Model-only browser queries, reused while navigating. Resolving a placement walks the
//! definition's bodies; doing that for every offscreen row and folder made large imports
//! quadratic on every frame. Keep the document and evaluated state alive with the index so
//! neither a new document nor a later allocation can accidentally reuse its answers.
use std::collections::{BTreeMap, HashMap};
use std::sync::Arc;
use solidcraft_engine::Session;
use solidcraft_engine::doc::{Document, FeatureKind, Mat, ModelState};
use solidcraft_engine::occurrences::OccurrencePlacement;
pub(super) struct Model {
doc: Arc<Document>,
state: Arc<ModelState>,
pending_moves: BTreeMap<u64, Mat>,
pub bodies: HashMap<u64, Vec<usize>>,
pub sketches: HashMap<u64, Vec<usize>>,
pub planes: HashMap<u64, Vec<usize>>,
pub children: HashMap<u64, Vec<u64>>,
placements: HashMap<Vec<u64>, Option<Arc<OccurrencePlacement>>>,
}
impl Model {
pub fn new(session: &Session) -> Self {
let state = session.model.state();
let mut bodies: HashMap<u64, Vec<usize>> = HashMap::new();
for (i, body) in state.bodies.iter().enumerate() {
bodies.entry(session.doc.model_body_component(body)).or_default().push(i);
}
let mut sketches: HashMap<u64, Vec<usize>> = HashMap::new();
let mut planes: HashMap<u64, Vec<usize>> = HashMap::new();
for (i, feature) in session.doc.features.iter().enumerate() {
let index = match feature.kind {
FeatureKind::Sketch { .. } => &mut sketches,
FeatureKind::ConstructionPlane { .. } => &mut planes,
_ => continue,
};
index.entry(feature.component).or_default().push(i);
}
let mut children: HashMap<u64, Vec<u64>> = HashMap::new();
for occurrence in &session.doc.occurrences {
children.entry(occurrence.parent).or_default().push(occurrence.id);
}
Self {
doc: session.doc.clone(),
state,
pending_moves: session.pending_moves.clone(),
bodies,
sketches,
planes,
children,
placements: HashMap::new(),
}
}
pub fn matches(&self, session: &Session) -> bool {
Arc::ptr_eq(&self.doc, &session.doc) && Arc::ptr_eq(&self.state, &session.model.state()) && self.pending_moves == session.pending_moves
}
pub fn placement(&mut self, session: &Session, path: &[u64]) -> Option<Arc<OccurrencePlacement>> {
self.placements.entry(path.to_vec()).or_insert_with(|| session.occurrence_placement(path).ok().map(Arc::new)).clone()
}
}