65 lines
2.6 KiB
Rust
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()
|
|
}
|
|
}
|