Dragging sketch geometry snaps like Fusion: a dragged point (or a line dragged by its body, by its ends) snaps onto other points, line midpoints and curves, and letting go there adds the coincident, midpoint or point-on-curve constraint in the drag's undo step; it lines up horizontally and vertically with other points (dashed guides, no constraint). Snap distances in screen pixels; Ctrl or Alt held turns snapping off, also while drawing. Ring and Pt/Mid/On label on the snap. Scenario s42 (coincident and DOF, exact H alignment without a constraint, Ctrl-drag, undo, line body drag); ui.drag hold_end; synthetic drags keep their modifiers

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
This commit is contained in:
bherbruckandClaude Opus 5.5 committed 2026-10-08 18:00:42 +00:00
1 parent b8d00aea13
commit 305c1c9a9b
8 files changed
+616 -7

No files matched your search

+2 -2
View File
@@ -7,7 +7,7 @@
//! - `{"widget": "Revolute", "near"?: "Type"}`: click a dialog field, choice or button by its
//! text (with `near`: the one in that label's row)
//! - `{"click": AT, "double"?, "shift"?, "ctrl"?, "button"?}`, `{"move": AT}`,
//! `{"drag": [AT, AT], "shift"?, "steps"?}` where AT is `[x, y]` (screen), `{"world": [x,y,z]}`
//! `{"drag": [AT, AT], "shift"?, "ctrl"?, "steps"?}` where AT is `[x, y]` (screen), `{"world": [x,y,z]}`
//! or `{"sketch": [x,y]}` (the sketch being edited)
//! - `{"call": "ui.view", "params": {…}}`: any other control request (`fail: true` expects an
//! error)
@@ -321,7 +321,7 @@ impl Harness {
let [x0, y0] = self.at(d.get(0).unwrap_or(&Value::Null))?;
let [x1, y1] = self.at(d.get(1).unwrap_or(&Value::Null))?;
let steps = s.get("steps").cloned().unwrap_or(json!(8));
self.call("ui.drag", json!({"x0": x0, "y0": y0, "x1": x1, "y1": y1, "steps": steps, "shift": flag("shift")}))
self.call("ui.drag", json!({"x0": x0, "y0": y0, "x1": x1, "y1": y1, "steps": steps, "shift": flag("shift"), "ctrl": flag("ctrl")}))
} else if let Some(m) = s.get("call").and_then(Value::as_str) {
self.call(m, s.get("params").cloned().unwrap_or(json!({})))
} else if s.get("note").is_some() {