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
@@ -212,7 +212,7 @@ fn touched_bodies(app: &SolveApp) -> Vec<String> {
|
||||
}
|
||||
|
||||
fn body_feature(app: &SolveApp, body: &str) -> Option<u64> {
|
||||
app.session.model.state().body(body).map(|b| b.feature)
|
||||
app.session.world_state().body(body).map(|b| b.feature)
|
||||
}
|
||||
|
||||
/// The bodies a target stands for.
|
||||
@@ -451,7 +451,7 @@ fn sketch_items(app: &SolveApp, id: u64) -> Vec<Item> {
|
||||
let profiles = !app.ui.hidden_profiles.contains(&id);
|
||||
let dims = app.ui.shown_dims.contains(&id);
|
||||
let editing = app.session.active_sketch == Some(id);
|
||||
let has_profiles = app.session.model.state().sketch(id).is_some_and(|s| !s.profiles.is_empty());
|
||||
let has_profiles = app.session.world_state().sketch(id).is_some_and(|s| !s.profiles.is_empty());
|
||||
vec![
|
||||
act("ui.extrudeSketch", "Extrude", "extrude").key("E").with(json!({ "sketch": id })).on(has_profiles && !editing),
|
||||
Item::sep(),
|
||||
@@ -540,7 +540,7 @@ fn component_items(app: &SolveApp, id: u64) -> Vec<Item> {
|
||||
fn sketch_entity_items(app: &SolveApp) -> Vec<Item> {
|
||||
use solvecraft_engine::sketch::CurveKind;
|
||||
let Some(sid) = app.session.active_sketch else { return Vec::new() };
|
||||
let st = app.session.model.state();
|
||||
let st = app.session.world_state();
|
||||
let Some(ss) = st.sketch(sid) else { return Vec::new() };
|
||||
let mut lines = Vec::new();
|
||||
let mut rounds = Vec::new();
|
||||
@@ -665,7 +665,7 @@ pub fn run_item(app: &mut SolveApp, item: &Item, at: Pos2) {
|
||||
app.ui.hidden_sketches.clear();
|
||||
}
|
||||
"ui.isolate" => {
|
||||
app.ui.hidden_bodies = app.session.model.state().bodies.iter().map(|b| b.name.clone()).filter(|b| !bodies.contains(b)).collect();
|
||||
app.ui.hidden_bodies = app.session.world_state().bodies.iter().map(|b| b.name.clone()).filter(|b| !bodies.contains(b)).collect();
|
||||
}
|
||||
"ui.lock" => {
|
||||
let locked = bodies.iter().all(|b| app.ui.locked_bodies.contains(b));
|
||||
@@ -844,7 +844,7 @@ pub fn run_item(app: &mut SolveApp, item: &Item, at: Pos2) {
|
||||
}
|
||||
"ui.extrudeSketch" => {
|
||||
if let Some(id) = id_of(&p, "sketch") {
|
||||
let n = app.session.model.state().sketch(id).map_or(0, |s| s.profiles.len());
|
||||
let n = app.session.world_state().sketch(id).map_or(0, |s| s.profiles.len());
|
||||
let items: Vec<Value> = (0..n).map(|i| json!({"type": "profile", "sketch": id, "index": i})).collect();
|
||||
let _ = app.run("select.set", json!({ "items": items }));
|
||||
app.start("Extrude");
|
||||
@@ -949,7 +949,7 @@ pub fn rename_selection(app: &mut SolveApp, at: Pos2) -> bool {
|
||||
|
||||
/// Add the edges that continue the selected edges smoothly to the selection.
|
||||
fn tangent_chain(app: &mut SolveApp) {
|
||||
let st = app.session.model.state();
|
||||
let st = app.session.world_state();
|
||||
let mut out: Vec<Sel> = Vec::new();
|
||||
for s in &app.session.selection {
|
||||
let Sel::Edge { body, index, .. } = s else { continue };
|
||||
|
||||
Reference in new issue
Block a user