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
@@ -434,7 +434,7 @@ pub fn commands(app: &SolveApp, k: &Sm, inputs: &[SelInput], extra: &Map<String,
|
||||
2 => {
|
||||
let ids: Vec<String> =
|
||||
items(inputs, 0).iter().filter_map(|x| if let Sel::SketchCurve { id } = x { Some(id.clone()) } else { None }).collect();
|
||||
let st = s.model.state();
|
||||
let st = s.world_state();
|
||||
let sketch = st
|
||||
.sketches
|
||||
.iter()
|
||||
@@ -475,7 +475,7 @@ pub fn commands(app: &SolveApp, k: &Sm, inputs: &[SelInput], extra: &Map<String,
|
||||
let mut p = json!({"angle": angle, "position": FOLD_POSITIONS.get(*position).copied().unwrap_or("centerline"), "flip": flip});
|
||||
match items(inputs, 0).first() {
|
||||
Some(Sel::SketchCurve { id }) => {
|
||||
let st = s.model.state();
|
||||
let st = s.world_state();
|
||||
let sketch = st
|
||||
.sketches
|
||||
.iter()
|
||||
@@ -543,7 +543,7 @@ pub fn commands(app: &SolveApp, k: &Sm, inputs: &[SelInput], extra: &Map<String,
|
||||
/// The dialog editing a sheet metal feature, filled from it.
|
||||
pub fn for_feature(app: &SolveApp, kind: &FeatureKind) -> Option<(Kind, Vec<SelInput>, Map<String, Value>)> {
|
||||
let s = &app.session;
|
||||
let st = s.model.state();
|
||||
let st = s.world_state();
|
||||
let rule_index = |r: &Option<String>| r.as_ref().and_then(|n| rule_list(app).iter().position(|x| &x.name == n)).map_or(0, |i| i + 1);
|
||||
let mut extra = Map::new();
|
||||
let (k, items): (Sm, Vec<Sel>) = match kind {
|
||||
@@ -654,7 +654,7 @@ pub fn arrow(app: &SolveApp, d: &Dialog) -> Option<Vec3> {
|
||||
_ => return None,
|
||||
};
|
||||
let Sel::Edge { body, index, point } = d.inputs.first()?.items.first()? else { return None };
|
||||
let st = app.session.model.state();
|
||||
let st = app.session.world_state();
|
||||
let m = st.body(body)?.mesh();
|
||||
let faces = m.edge_faces.get(*index)?;
|
||||
let area = |f: u32| -> f64 {
|
||||
|
||||
Reference in new issue
Block a user