feat(selection): port retail polygon picking and vivid marker

Replace the projected Setup-sphere rectangle and independent physics-wall ray with retail's render-coupled picker: only visible server-object parts participate, each exact drawing sphere broad-phases the camera-eye ray, and first-in-DAT-order visual polygon hits globally outrank sphere fallbacks.

Replace the devtools-only procedural triangles with the retained gameplay VividTargetIndicator using retail client-enum surfaces 1..4, radar-blip colorization, Setup selection-sphere framing, and the exact eight-pixel viewport clamp.

Release build succeeds with zero warnings and all 5,886 tests pass with five intentional skips.

Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-17 21:32:51 +02:00
parent 0f82a08f0a
commit 146a963aeb
26 changed files with 1302 additions and 1340 deletions

View file

@ -4077,11 +4077,23 @@ or +small fix if different. Not blocking M1.
## #71 — WorldPicker Stage B — polygon refine for retail-accurate clicks
**Status:** OPEN
**Status:** DONE 2026-07-17
**Severity:** MEDIUM (Stage A now causes real play mis-picks through open doors/windows)
**Filed:** 2026-05-16
**Component:** selection / picker
**Resolution:** Replaced the projected `Setup.SelectionSphere` rectangle and
independent collision-polygon wall ray with the retail render-coupled path.
`WbDrawDispatcher` now publishes only server-object parts which survive the
normal visible draw and each part's drawing-sphere view-cone check.
`RetailWorldPicker` transforms the ray into each part,
uses `GfxObj.DrawingBSP.Root.BoundingSphere` as broadphase, scans visual
polygons in DAT order, keeps only the first polygon hit per part, and gives
every polygon hit global priority over sphere-only fallbacks. The obsolete
picker overloads and cell occluder were deleted. Conformance tests pin
single-sided rejection, first-polygon ordering, affine scale, fallback, and
global arbitration.
**Description:** Retail's mouse picker does two-tier sphere-then-polygon
selection (`acclient_2013_pseudo_c.txt:0x0054c740`
`Render::GfxObjUnderSelectionRay`):
@ -4124,11 +4136,21 @@ play, so this should be scheduled soon after A8 rather than left as polish.
## #70 — Triangle apex/size — final retail-feel UX pass
**Status:** OPEN
**Status:** DONE 2026-07-17
**Severity:** LOW (cosmetic — indicator already retail-anchored, this is final-feel polish)
**Filed:** 2026-05-16
**Component:** ui / target indicator
**Resolution:** Deleted the procedural ImGui triangles and mounted a retained
gameplay-UI `VividTargetIndicatorController`. It resolves retail client-enum
category `0x10000009`, values `1..4`, to the four installed 12×12 RenderSurface
corners; colorizes their grayscale masks with `gmRadarUI::GetBlipColor`
equivalent colors; places them outside the exact Setup selection-sphere screen
rectangle; and ports retail's separate-edge 8-pixel viewport clamp. The marker
is available without devtools and follows only targets reported by the normal
world draw. Installed-DAT and layout conformance tests pin the assets and
placement.
**Description:** Per 2026-05-16 user feedback during the
`SelectionSphere` indicator ship, the triangle apex direction
(flipped to point inward at the target) and sprite size (currently
@ -4141,8 +4163,8 @@ shape and size come from the dat, not constants.
either (a) blit the exact bitmap, or (b) pick a procedural size +
shape that matches it pixel-for-pixel at standard zoom.
**Files:** [TargetIndicatorPanel.cs](src/AcDream.App/UI/TargetIndicatorPanel.cs)
`TriangleSize` constant + the four `AddTriangleFilled` calls.
**Files:** [VividTargetIndicatorController.cs](src/AcDream.App/UI/Layout/VividTargetIndicatorController.cs)
exact retained-UI DAT surface resolution, colorization, and placement.
**Estimated scope:** Small (~1-2 hours, mostly dat exploration).
Not blocking M1.
@ -7798,6 +7820,13 @@ cell structs. Entities behind walls from the camera's perspective are no
longer selectable. Screen-rect occlusion tests verify the filter across
several hit/miss scenarios.
**Superseded 2026-07-17:** The full retail render-coupled polygon picker
(#71) removed this independent collision-BSP occluder. Retail inherits
occlusion from the normal portal/viewcone draw traversal; maintaining a second
ray against physics polygons could both hide drawn targets and admit undrawn
ones. The original commits remain useful history, but this is no longer the
runtime mechanism.
---
## #77 — [DONE 2026-05-18 · 3be7000] Auto-walk doesn't engage at walking range; pickup at walking range overshoots and snaps back