Components are frames (user bug #4)
What a component holds moves with its occurrence, and picks in the world land in the
component's frame:
- Sketches and construction planes show where their component is placed (free move, joint
drive, Capture Position); sketch.inspect reports sketch points in the world.
- frames.rs maps a command's world picks into the frame of the body they lie on (through the
inverse of its placement: a moved component or a pasted instance), points that make new
geometry into the active component's frame, and directions with them; instance body names
("Body1 (Pin:2)") become the component's body. Fillet/chamfer edges, shell/offset/draft
faces, face extrude/revolve, sketch on face, holes, sheet metal and plastic picks, primitives,
appearance faces, analyses. Once per command (not again for commands run by commands); the
active-frame fallback stays for commands without a table. Nothing changes while every
placement is the identity.
- component.move_bodies keeps a body where it is in the world (Document.body_offsets: from the
new component's frame to the one it was made in; renames and deleted components follow).
- The UI reads the placed model (Session::world_state) for display, picking, sketch editing and
dialogs; live previews use it once anything is placed.
Tests (engine): sketches and construction planes move (and turn) with the component; world
picks fillet, sketch, hole and make boxes in a moved component; a pick on a pasted instance;
move_bodies keeps the world place there and back; a sketch on a face follows a Move feature.
QA's s34 now runs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
This commit is contained in:
1 parent
c0725ebc86
commit
7a2eb059c4
30 files changed
+669
-72
No files matched your search
@@ -156,7 +156,9 @@ fn delete(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
}
|
||||
d.components.retain(|c| !gone.contains(&c.id));
|
||||
d.occurrences.retain(|o| !gone.contains(&o.component) && !gone.contains(&o.parent));
|
||||
let moved_out: Vec<String> = d.body_components.iter().filter(|(_, c)| gone.contains(c)).map(|(b, _)| b.clone()).collect();
|
||||
d.body_components.retain(|_, c| !gone.contains(c));
|
||||
d.body_offsets.retain(|b, _| !moved_out.contains(b));
|
||||
if gone.contains(&s.active_component) {
|
||||
s.active_component = 0;
|
||||
}
|
||||
@@ -174,10 +176,23 @@ fn move_bodies(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
for b in &bodies {
|
||||
let feature = st.body(b).map(|x| x.feature).unwrap_or(0);
|
||||
let own = s.doc.feature(feature).map(|f| f.component).unwrap_or(0);
|
||||
// The body keeps its place in the world: where it is shown now (its component's frame and
|
||||
// any earlier offset), seen from the new component's frame.
|
||||
let from = s.doc.body_component(b, feature);
|
||||
let now = solvecraft_doc::mat_mul(&s.doc.component_transform(from), s.doc.body_offsets.get(b).unwrap_or(&solvecraft_doc::IDENTITY));
|
||||
let offset = solvecraft_doc::mat_inverse(&s.doc.component_transform(to))
|
||||
.map(|inv| solvecraft_doc::mat_mul(&inv, &now))
|
||||
.unwrap_or(solvecraft_doc::IDENTITY);
|
||||
let doc = s.doc_mut();
|
||||
if own == to {
|
||||
s.doc_mut().body_components.remove(b);
|
||||
doc.body_components.remove(b);
|
||||
} else {
|
||||
s.doc_mut().body_components.insert(b.clone(), to);
|
||||
doc.body_components.insert(b.clone(), to);
|
||||
}
|
||||
if solvecraft_doc::is_identity(&offset) {
|
||||
doc.body_offsets.remove(b);
|
||||
} else {
|
||||
doc.body_offsets.insert(b.clone(), offset);
|
||||
}
|
||||
}
|
||||
Ok(json!({"bodies": bodies, "component": to}))
|
||||
@@ -355,7 +370,8 @@ fn revert(s: &mut Session, _p: &Value) -> Result<Value> {
|
||||
|
||||
/// The active component's frame from world coordinates (for new features' geometry).
|
||||
pub fn to_active_frame(s: &Session, kind: &mut FeatureKind) {
|
||||
if s.active_component == 0 {
|
||||
// Commands whose picks `frames` maps are already in their frames.
|
||||
if s.active_component == 0 || crate::frames::mapped() {
|
||||
return;
|
||||
}
|
||||
let m = s.doc.component_transform(s.active_component);
|
||||
|
||||
Reference in new issue
Block a user