Picks on a moved or pasted component build where it is shown (#558) (#610)

Construction axes, points and planes resolve their picks against the model as their component sees it (in the root, every placement, pasted instances too), and a Hole picked on another component's body cuts that body. components-arm 355 -> 502/594 and joints-hinge 304/390 -> 371/408 in the action matrix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
bherbruckandClaude Opus 5.5 authored and GitHub committed 2026-10-13 04:12:24 -04:00
1 parent 083ddf7722
commit 2a434d59c3
5 files changed
+208 -133

No files matched your search

+16 -3
View File
@@ -3453,13 +3453,15 @@ fn eval_feature(doc: &Document, vals: &BTreeMap<String, Value>, f: &Feature, st:
let fst = crate::state_in_face_anchor_frame(doc, st, anchor, f.component)?;
doc.resolve_attached_plane(vals, plane, f.component, st, &fst)?
}
None => doc.resolve_plane_in(vals, plane, 0, Some(st))?,
// Picks on bodies of other (moved) components are where those bodies are shown.
None => doc.resolve_plane_in(vals, plane, 0, Some(&construction_state(doc, st, f.component)))?,
};
st.construct.push(crate::construct::Construct { feature: f.id, name: f.name.clone(), geom: crate::construct::ConstructGeom::Plane(pl) });
Ok(())
}
FeatureKind::ConstructionAxis { def } => {
let (origin, dir) = crate::construct::resolve_axis(&crate::construct::Ctx { doc, vals, st, depth: 0 }, def)?;
let (origin, dir) =
crate::construct::resolve_axis(&crate::construct::Ctx { doc, vals, st: &construction_state(doc, st, f.component), depth: 0 }, def)?;
st.construct.push(crate::construct::Construct {
feature: f.id,
name: f.name.clone(),
@@ -3468,7 +3470,8 @@ fn eval_feature(doc: &Document, vals: &BTreeMap<String, Value>, f: &Feature, st:
Ok(())
}
FeatureKind::ConstructionPoint { def } => {
let p = crate::construct::resolve_point(&crate::construct::Ctx { doc, vals, st, depth: 0 }, def)?;
let p =
crate::construct::resolve_point(&crate::construct::Ctx { doc, vals, st: &construction_state(doc, st, f.component), depth: 0 }, def)?;
st.construct.push(crate::construct::Construct { feature: f.id, name: f.name.clone(), geom: crate::construct::ConstructGeom::Point(p) });
Ok(())
}
@@ -3925,6 +3928,16 @@ fn unique_body_name(st: &ModelState, base: &str) -> String {
/// it are moved into its frame (through both placements), so a sketch on another component's
/// face finds the face where it is shown and projects its edges there. The model itself when
/// every placement agrees (the usual case).
/// What construction geometry of component `comp` is built on: the model as that component sees
/// it, other components' bodies where they are placed. In the root, every placement of a
/// component (its pasted instances too) is there, as the viewport shows it.
fn construction_state<'a>(doc: &Document, st: &'a ModelState, comp: u64) -> std::borrow::Cow<'a, ModelState> {
if comp == 0 && !doc.occurrences.is_empty() {
return std::borrow::Cow::Owned(world_state(doc, st));
}
state_in_frame(doc, st, comp)
}
pub fn state_in_frame<'a>(doc: &Document, st: &'a ModelState, comp: u64) -> std::borrow::Cow<'a, ModelState> {
state_in_frame_at(doc, st, comp, doc.component_transform(comp))
}