feat(select): offer the selection modes at "Select objects"

Only Previous and Last were on offer, so Window, Crossing, Fence, the two
polygons and All could not be reached at all -- and with no keyboard to
type them into, the buttons were the only way in.

Window and Crossing fix the sense of the next box. Dragging derives that
from the direction the corner travels and would overwrite it the moment
the corner moved, so the derivation stands down while a keyword holds it.
Add and Remove decide what a pick does for the rest of the round: Remove
subtracts the way Shift already does, rather than through PICKADD, which
decides whether a pick *replaces* the set and so would have wiped
everything gathered so far. Both are dropped when the next command
starts, since neither outlives the selection that asked for them.

Fence and the polygons are picked point by point, which TRIM and EXTEND
already ask for. That gesture -- the points, the rubber-banded dashed
preview, whether the path closes -- moves into one place both bind to,
and the two preview builders duplicated in trim.rs go with it.

A fence is not the polygon test with crossing set: that closes the point
list and counts whatever lies inside, so a line drawn past a row of
objects would take everything behind it too. It gets a hit test that only
counts a real intersection, and skips the area-based geometry entirely.

The lasso gathered its hits from wires, hatches, block hatches, meshes and
block meshes inline; the new modes need the same list, and a second copy
would drift. Both now come through `Scene::path_hit_handles`.

Closes #596

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Hakan SevenandClaude Opus 5 committed 2026-08-07 13:32:11 +03:00
1 parent 22890a9411
commit 5c5c7606a1
12 files changed
+613 -151

No files matched your search

+9
View File
@@ -1034,6 +1034,15 @@ pub enum CmdResult {
CancelForSpaceChange,
/// End the selection-gather phase and re-dispatch the named command
/// with the gathered handles installed as the active scene selection.
/// Select by a path the user picked point by point. `closed` polygons take
/// what they enclose, or merely touch when `crossing`; an open fence takes
/// only what it actually cuts. The host owns the hit test, so the command
/// hands over the geometry rather than the answer. (#596)
SelectByPath {
path: Vec<[f64; 2]>,
closed: bool,
crossing: bool,
},
Relaunch(String, Vec<Handle>),
/// End the command and dispatch the given command string. Used by an
/// interactive front-end that gathered its arguments step-by-step and