Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

- **WASM Alt+LMB rectangle select**: multi-select via Alt+left-drag works again. WASM never created `Occt_glfw_win`, so live modifier polling during mouse move always returned no Alt and OCCT rebound the gesture to orbit. `Occt_view` now keeps a non-owning `GLFWwindow*` for modifiers and cursor (desktop unchanged).

- **Alt+LMB rectangle select misses some solids**: after OCCT `SelectRectangle`, also select displayed document solids whose projected AABB intersects the rubber band. Fixes complex / STEP parts (often under Shape List groups) that stock sensitive-entity picking skipped while simple root boxes were selected. On WASM, map projections from OCCT window pixels into GLFW cursor space (canvas size can drift).

- **Shape List current group highlight**: the current group row no longer uses the same strong selection tint as AIS-selected solids. That made Alt-drag / cleared selection look like grouped shapes stayed selected when only the current-group marker was lit.

- **Sketch from face profile wire**: the dark-red originating-face boundary no longer stays drawn after leaving sketch mode (e.g. after Revolve returns to Normal). It follows sketch edge visibility and only appears while sketch tools (or polar duplicate) show the sketch.

- **`gui.hotkeys` load**: duplicate-chord cleanup no longer leaves two actions on the same key when the later row's factory chord is the colliding key (e.g. Move and Rotate both `"R"`). Earlier remaps that steal a later action's factory chord are restored to defaults so each binding stays unique.
Expand Down
26 changes: 19 additions & 7 deletions agents/drafts/issues/active/gh-220-wasm-alt-drag-multiselect.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
---
github_issue: 220
github_pr: 250
status: active
paired_draft: ../prs/active/gh-250-wasm-alt-drag-multiselect.md
---

# WASM: Alt + LMB drag does not multi-select shapes
Expand All @@ -21,18 +23,28 @@ See https://github.com/trailcode/EzyCad/issues/220

### Summary

Desktop: **Alt + LMB drag** rubber-band multi-selects shapes via OCCT `AIS_ViewController`. WASM: same gesture does not select multiple shapes.
Desktop: **Alt + LMB drag** rubber-band multi-selects shapes via OCCT `AIS_ViewController`. WASM: same gesture did not multi-select because live Alt was never polled (`m_occt_window` null on Emscripten). Follow-up: stock `SelectRectangle` also missed some complex / STEP solids; Shape List current-group tint looked like selection.

### Fix (working tree)

- Non-owning `GLFWwindow* m_glfw_window` for modifier/cursor polling on WASM.
- After `SelectRectangle`, select displayed solids whose projected AABB intersects the band (GLFW/OCCT size mapping on WASM).
- Shape List: AIS selection tint vs weaker current-group tint.
- Docs: `usage.md`, `usage-occt-view.md`, `gui.md`, CHANGELOG, plan.

### Acceptance criteria

- [ ] WASM Alt + LMB drag multi-selects like desktop
- [ ] Desktop unchanged
- [ ] Docs note Alt+drag (and any Web caveats)
- [ ] Plan updated: `agents/plans/wasm-alt-drag-multiselect.md`
- [x] Code path: WASM can poll Alt during drag (same as desktop)
- [x] Manual WASM: Alt + LMB drag multi-selects like desktop (incl. complex solids under groups)
- [x] Desktop gesture map unchanged
- [x] Docs note Alt+drag (and Web Alt caveat)
- [x] Plan updated: `agents/plans/wasm-alt-drag-multiselect.md`
- [x] PR opened: https://github.com/trailcode/EzyCad/pull/250 (`Fixes #220`)
- [ ] Close GitHub #220 (on PR merge)

### Related

- Issue: https://github.com/trailcode/EzyCad/issues/220
- Plan: `agents/plans/wasm-alt-drag-multiselect.md` (tracking on PR #219; bug not fixed there)
- PR: https://github.com/trailcode/EzyCad/pull/250
- Plan: `agents/plans/wasm-alt-drag-multiselect.md`
- Related: #93 / `gh-93-emscripten-web-hotkeys-followup.md`
- PR that added tracking: https://github.com/trailcode/EzyCad/pull/219
33 changes: 33 additions & 0 deletions agents/drafts/prs/active/gh-250-wasm-alt-drag-multiselect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
github_issue: 220
github_pr: 250
status: active
paired_draft: ../issues/active/gh-220-wasm-alt-drag-multiselect.md
---

# PR - Trailcode/wasm-box-select-fix

## Title

Fix WASM Alt+LMB rectangle multi-select (#220)

## Summary

- WASM Alt+LMB rubber-band multi-select via non-owning `GLFWwindow*` modifier/cursor polling.
- AABB screen-rect supplement after `SelectRectangle` (complex / STEP solids; WASM OCCT↔GLFW mapping).
- Shape List current-group tint distinct from AIS selection.
- Docs + plan updated.

## Related

- Issue: https://github.com/trailcode/EzyCad/issues/220
- PR: https://github.com/trailcode/EzyCad/pull/250
- Branch: `Trailcode/wasm-box-select-fix`
- Plan: `agents/plans/wasm-alt-drag-multiselect.md`

## Test Plan

- [x] Desktop Alt+LMB (incl. complex solids under groups)
- [x] WASM Alt+LMB; Ctrl+click still works
- [x] Shape List current-group vs selection tint
- [ ] CI / `Grouped_solids_stay_displayed_and_selectable`
2 changes: 1 addition & 1 deletion agents/plans/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,5 @@ sketch-mode-shape-faint (done; parallel UX)
| [shape-list-hierarchy-phase3.md](shape-list-hierarchy-phase3.md) | deferred | parent transform inheritance, Parts/planes, Boolean history (#214) |
| [assembly-inspection-mode.md](assembly-inspection-mode.md) | deferred | assembly idle/inspection mode, Part vs arrange context, Move semantics |
| [wasm-multithreading.md](wasm-multithreading.md) | planning | WASM/Emscripten pthreads, SharedArrayBuffer, parallel OCCT on web |
| [wasm-alt-drag-multiselect.md](wasm-alt-drag-multiselect.md) | planning | WASM Alt+LMB drag rectangle multi-select broken (#220) |
| [wasm-alt-drag-multiselect.md](wasm-alt-drag-multiselect.md) | implemented | WASM Alt+LMB multi-select (#220); AABB pick supplement; close issue when ready |
| [configurable-hotkeys.md](configurable-hotkeys.md) | done | remappable shortcuts, keybindings, `gui.hotkeys`, free Dimension off D |
67 changes: 26 additions & 41 deletions agents/plans/wasm-alt-drag-multiselect.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
status: planning
status: implemented
topic: wasm-alt-drag-multiselect
depends_on: []
blocks: []
Expand All @@ -16,58 +16,43 @@ github_issue: 220

On desktop, holding **Alt** and **left-dragging** in the 3D view activates OCCT `AIS_ViewController` rectangle selection (`SelectRectangle` / rubber band) and multi-selects shapes under the box.

On the WASM build the same gesture does **not** multi-select.
On the WASM build the same gesture did **not** multi-select (Alt never reached OCCT on mouse-move). Separately, stock `SelectRectangle` could miss complex / STEP solids even when simple root boxes were selected (desktop and web).

EzyCad already maps modifiers into OCCT flags:
## Root causes (confirmed)

- `Occt_view::key_flags_from_glfw_` — `GLFW_MOD_ALT` → `Aspect_VKeyFlags_ALT`
- Mouse press/release: `PressMouseButton` / `ReleaseMouseButton` with `theMods`
- Mouse move: `UpdateMousePosition(..., key_flags_from_glfw_window_(), ...)` which polls `glfwGetKey(... LEFT/RIGHT_ALT ...)`
1. **WASM Alt polling** — `init_window` skipped `Occt_glfw_win` (correct: `Close()` would destroy the shared canvas). `key_flags_from_glfw_window_()` always returned `NONE`, so OCCT rebound Alt+LMB `SelectRectangle` to orbit on the next move.
2. **Sensitive-entity miss** — OCCT rubber-band pick skipped some imported BREPs; fixed by projecting document-solid AABBs into screen space after `SelectRectangle`.
3. **WASM pixel space** — map projected corners from OCCT/`Wasm_Window` size into GLFW cursor space; keep canvas size synced before project.
4. **Shape List UX** — current-group row used the same strong tint as AIS selection (looked like grouped solids stayed selected).

Related input/hotkey tracking: [#93](https://github.com/trailcode/EzyCad/issues/93), draft `agents/drafts/issues/active/gh-93-emscripten-web-hotkeys-followup.md`. OCCT desktop vs wasm kit: [occt-wasm-dual-version](../conventions/occt-wasm-dual-version.md).
## Approach (landed)

## Goal
### Phase 1 — input path

Make **Alt + LMB drag** multi-select on WASM match desktop, without changing desktop gesture mapping or selection schemes.

## Likely causes (investigate in order)

1. **Alt not present on pointer events under Emscripten/GLFW** — browser menu focus, `preventDefault`, or incomplete `mods` on `glfwSetMouseButtonCallback`.
2. **`glfwGetKey(ALT)` false during drag** — rubber-band gesture needs Alt on move updates (`key_flags_from_glfw_window_`), not only on button press.
3. **ImGui / focus** — canvas loses keyboard focus when Alt is pressed; Alt never reaches GLFW.
4. **OCCT 7.9.3 wasm kit** — confirm default `MouseGestureMap` still binds Alt+LMB to select-rectangle (unlikely difference, but verify if input looks correct).

## Approach

### Phase 0 — reproduce and instrument

- [ ] Confirm desktop Alt+LMB rubber band still works.
- [ ] On WASM, log (temporary) `mods` on LMB press/release and Alt from `key_flags_from_glfw_window_` during drag.
- [ ] Note browser (Chrome/Firefox/Edge) and whether the OS/browser steals Alt.

### Phase 1 — fix input path

- [ ] Ensure Alt is forwarded for press, move, and release while the gesture is active (Emscripten/GLFW and/or synthetic modifier from `event.altKey` if GLFW is incomplete).
- [ ] Avoid focusing browser chrome on Alt when the canvas has focus (as far as the platform allows).
- [ ] Keep `GUI::on_mouse_button` / sketch `mods == 0` click paths unchanged for unmodified LMB.
- [x] Non-owning `GLFWwindow* m_glfw_window` for modifier/cursor polling (no owning `Occt_glfw_win` on WASM).
- [x] `handleSelectionPoly` + `select_shps_intersecting_screen_rect_` (overlap AABB; `Handle(...)` for OCCT 7.9.3 / 8).
- [x] Shape List: selection tint from AIS only; weaker tint for current group.

### Phase 2 — docs and parity

- [ ] Document Alt+drag multi-select in `docs/usage.md` and/or `docs/usage-occt-view.md`; call out any remaining Web limitation.
- [ ] Manual check: Ctrl+click multi-select still works on WASM if it already does; Alt+drag matches desktop.
- [ ] Close #220 when done; update this plan status.
- [x] `docs/usage.md`, `docs/usage-occt-view.md` (Alt+drag + web Alt caveat).
- [x] `src/doc/gui.md` (GLFW pointer, AABB supplement, Shape List tint).
- [x] `CHANGELOG.md` `[Unreleased]`.
- [x] Manual: native + WASM Alt+LMB (including complex solids under groups).
- [x] PR: https://github.com/trailcode/EzyCad/pull/250 (`Fixes #220`).
- [ ] Close #220 on merge.

## Out of scope

- WASM pthreads / parallel OCCT ([wasm-multithreading.md](wasm-multithreading.md)).
- Broader #93 hotkey parity beyond what this gesture needs.
- WASM pthreads ([wasm-multithreading.md](wasm-multithreading.md)).
- Broader #93 hotkey parity.
- Changing default OCCT mouse gesture map on desktop.

## Related code

| Area | Path |
| ---------------------------- | ----------------------------------------- |
| Modifier → OCCT flags | `src/gui_occt_view.cpp` (`key_flags_*`) |
| Mouse → view controller | `src/gui_occt_view.cpp` (`on_mouse_*`) |
| GLFW → GUI | `src/main.cpp`, `src/gui.cpp` |
| Draft | `agents/drafts/issues/active/gh-220-*.md` |
| Area | Path |
| ----------------------- | ------------------------------------------------------- |
| Modifier / cursor | `src/gui_occt_view.cpp` (`key_flags_*`, `cursor_position_`) |
| Rubber-band supplement | `handleSelectionPoly`, `select_shps_intersecting_screen_rect_` |
| Shape List tint | `src/gui.cpp` (`shape_list_`) |
| Draft | `agents/drafts/issues/active/gh-220-*.md` |
1 change: 1 addition & 0 deletions docs/usage-occt-view.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ EzyCad's 3D viewport uses **Open CASCADE Technology (OCCT)** for displaying soli
## Navigation

- **Orbit, pan, zoom** — See [Mouse Controls](usage.md#mouse-controls) in the usage guide.
- **Rectangle multi-select** — Hold <kbd>Alt</kbd> and left-drag to rubber-band select shapes (same Open CASCADE `AIS_ViewController` gesture as desktop). On the web build, click the canvas first if the browser steals <kbd>Alt</kbd> for its menu.
- **Num Lock** — <kbd>Num Lock</kbd> off is recommended for all <kbd>NumPad</kbd> view shortcuts (orbit, roll, zoom, axis snap). With <kbd>Num Lock</kbd> on, the OS may remap the keypad so those keys no longer match the docs; use main-row alternatives listed in [View navigation](usage.md#view-navigation).
- **View orbit / roll** — <kbd>NumPad 8</kbd>/<kbd>2</kbd>/<kbd>4</kbd>/<kbd>6</kbd> orbit (same axes as LMB drag); <kbd>Shift</kbd>+<kbd>NumPad 4</kbd>/<kbd>6</kbd>, <kbd>Shift</kbd>+main <kbd>4</kbd>/<kbd>6</kbd>, or <kbd>Shift</kbd>+<kbd>Left</kbd>/<kbd>Right</kbd> roll around the screen axis (repeat while held). Step size is **Settings → 3D view navigation** (**View rotation step**). See [View navigation](usage.md#view-navigation).
- **Zoom** — mouse wheel, **right-drag**, <kbd>NumPad +</kbd>/<kbd>-</kbd>, <kbd>Shift</kbd>+<kbd>=</kbd>, and main <kbd>-</kbd> share one path. Strength is **Zoom scroll scale** in Settings (`gui.view_zoom_scroll_scale`, default **4**). Hold <kbd>Shift</kbd> while zooming for a Blender-style finer step (**x0.1**). See [View Controls](usage.md#view-controls).
Expand Down
5 changes: 4 additions & 1 deletion docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -682,7 +682,7 @@ These tools are in the main toolbar (after the polar duplicate button). They are
**How to Use:**

1. Make sure you are in **Normal** (inspection) mode.
2. **Select two or more shapes** in the 3D viewer. Hold <kbd>Ctrl</kbd> (or the platform equivalent) to multi-select, or drag a selection box. Use the selection filter if you only want to pick whole solids.
2. **Select two or more shapes** in the 3D viewer. Hold <kbd>Ctrl</kbd> (or the platform equivalent) to multi-select, or hold <kbd>Alt</kbd> and drag a selection box. Use the selection filter if you only want to pick whole solids.
3. Click the appropriate toolbar button:
- ![Part_Cut](res/icons/Part_Cut.png) **Shape cut** for difference/subtract
- ![Part_Fuse](res/icons/Part_Fuse.png) **Shape fuse** for union
Expand Down Expand Up @@ -823,11 +823,14 @@ Open or close the **Lua** or **Python** consoles from **View -> Lua Console** or
| -------------------------------------------------------------------------------------: | ---------------------------------------------------------------------------------- |
| **Left Click** | Select object |
| **Left drag** | Orbit view |
| <kbd>Alt</kbd>+**Left drag** | Rectangle multi-select (shapes inside the box) |
| **Middle drag** | Pan view |
| **Right drag** | Zoom |
| **Scroll Wheel** | Zoom in/out (**Zoom scroll scale** in Settings; hold **Shift** for finer steps) |
| <kbd>NumPad +</kbd> / <kbd>NumPad -</kbd>, <kbd>Shift</kbd>+<kbd>=</kbd>, <kbd>-</kbd> | Zoom in/out ([keyboard](#view-navigation); settings scale; <kbd>Shift</kbd> finer) |

On the **web (WASM)** build, keep the canvas focused while holding <kbd>Alt</kbd>. Some browsers use <kbd>Alt</kbd> for the menu bar; if rectangle select fails, click the 3D view first, or use <kbd>Ctrl</kbd>+click to multi-select.

### View orbit (NumPad)

Press <kbd>NumPad 8</kbd>, <kbd>NumPad 2</kbd>, <kbd>NumPad 4</kbd>, or <kbd>NumPad 6</kbd> (without <kbd>Shift</kbd>) to orbit the camera in steps, using the same axes as **left-drag orbit** (Open CASCADE `AIS_ViewController` convention: yaw about camera up, pitch about camera side). <kbd>NumPad 8</kbd> / <kbd>NumPad 2</kbd> pitch up or down; <kbd>NumPad 4</kbd> / <kbd>NumPad 6</kbd> yaw left or right. The default step is **45** degrees per key press. **Num Lock off** is recommended so the keypad sends these **NumPad** codes (see [View navigation](#view-navigation) above).
Expand Down
Loading
Loading