feat(selection): port retail offscreen target indicator
This commit is contained in:
parent
ea4f52ec51
commit
ec1bb19609
9 changed files with 404 additions and 97 deletions
|
|
@ -4143,13 +4143,15 @@ play, so this should be scheduled soon after A8 rather than left as polish.
|
|||
|
||||
**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.
|
||||
category `0x10000009`, values `1..12`, to the four installed 12×12 corner
|
||||
surfaces and eight 24×24 off-screen direction surfaces; colorizes their
|
||||
grayscale masks with `gmRadarUI::GetBlipColor` equivalent colors; places them
|
||||
outside the exact Setup selection-sphere screen rectangle; and ports retail's
|
||||
8-pixel viewport clamp. The marker is available without devtools, remains
|
||||
visible through walls, has no marker-side distance cutoff, and uses the larger
|
||||
authored direction image when the live target leaves the viewport.
|
||||
Installed-DAT and layout conformance tests pin the assets, direction sectors,
|
||||
and placement.
|
||||
|
||||
**Description:** Per 2026-05-16 user feedback during the
|
||||
`SelectionSphere` indicator ship, the triangle apex direction
|
||||
|
|
|
|||
|
|
@ -524,7 +524,7 @@ behavior. Estimated 17–26 days focused work, 3–5 weeks calendar.
|
|||
- **✓ SHIPPED — UI Studio** (2026-06-26, branch `claude/hopeful-maxwell-214a12`, ~33693c6→HEAD). Standalone `AcDream.App ui-studio <datdir> [--layout 0xNNNN | --dump <slug>] [--screenshot <png>]` Silk tool that previews any panel through the **production renderer** (`RenderBootstrap.cs` + GameWindow untouched). Sources: 26-window retail dump (`docs/research/2026-06-25-retail-ui-layout-dump.json`) via `--dump`, or live dat import + fixtures via `--layout`. Interactive canvas (click-routing to `UiHost`, Interact/Inspect ImGui toggle), headless `--screenshot`. Architecture: `src/AcDream.App/Studio/` (`StudioWindow`, `PanelFbo`, `FixtureProvider`, `LayoutSource`) + `src/AcDream.App/Rendering/RenderBootstrap.cs`. ISSUES #156 (inventory all-black in studio) and #157 (GameWindow font resolver) filed.
|
||||
- **✓ SHIPPED — Importer dat-fidelity** (Fix A/B/C, 2026-06-26, same branch). **Boundary established: look = importer (font/justification/color from dat); state/behavior = runtime controller logic.** Fix A: justification property `0x14`/`0x15` → `UiText` Centered/RightAligned/VerticalJustify. Fix B: FontColor property `0x1B` → `UiText.DefaultColor`; character colors proved RUNTIME (no importer fix). Fix C: FontDid → per-element dat font via a resolver in `DatWidgetFactory` — **STUDIO path only**; GameWindow passes `null` (Issue #157). Fix 4 (UIState-group activation): INVESTIGATED — no importer fix exists; the dat has no Visible encoding; runtime `gm*UI` is correct.
|
||||
- **✓ SHIPPED — Wave 3.3 unified primary-click router.** `ItemInteractionController.OfferPrimaryClick` returns `NotActive` / `ConsumedSuccess` / `ConsumedRejected`; inventory, bags, main pack, paperdoll, toolbar, radar, and world clicks all offer target mode before local fallback. Rejected targets cannot drift selection or open/use the clicked object. Issue #197 and AP-107 retired; retained matrix and live ACE-provisioned healing gate user-confirmed. The 3-D doll routes through authored hit mask `0x100001D6` (resolved `UiButton` above viewport `0x100001D5`), and local health prefers authoritative private-vital state.
|
||||
- **✓ SHIPPED — retail world selection + complete SmartBox feedback (2026-07-17).** The projected Setup-sphere rectangle and independent physics-wall ray are deleted. The normal visible-mesh traversal now publishes server-object parts through their exact drawing-BSP spheres; `RetailWorldPicker` ports the camera-eye ray, per-part local transform, double-precision retail sphere solve, first visual-polygon hit in DAT order, one-sided/convex-edge rules, and global polygon-over-sphere arbitration. The retained gameplay UI resolves client-enum category `0x10000009` values `1..4` to the four installed 12×12 corner surfaces, colorizes them with the radar-blip color, and ports the exact Setup-sphere rectangle plus separate-edge 8-pixel viewport clamp. Successful select/use/targeted-use/drop clicks also run SmartBox's separate 0.8-second HIGH/LOW/HIGH/LOW material-lighting pulse with the exact retail luminosity/diffuse replacements before restoring authored rendering. Issues #70/#71 closed; AP-29/TS-16 retired. Research: `docs/research/2026-07-17-retail-world-selection-pseudocode.md`.
|
||||
- **✓ SHIPPED — retail world selection + complete SmartBox feedback (2026-07-18).** The projected Setup-sphere rectangle and independent physics-wall ray are deleted. The normal visible-mesh traversal now publishes server-object parts through their exact drawing-BSP spheres; `RetailWorldPicker` ports the camera-eye ray, per-part local transform, double-precision retail sphere solve, first visual-polygon hit in DAT order, one-sided/convex-edge rules, and global polygon-over-sphere arbitration. The retained gameplay UI resolves client-enum category `0x10000009` values `1..12` to the four installed 12×12 corner surfaces and eight 24×24 off-screen direction surfaces, colorizes them with the radar-blip color, and ports the exact Setup-sphere rectangle, through-wall/no-distance SmartBox callback, direction sectors, and 8-pixel viewport-edge clamp. Successful select/use/targeted-use/drop clicks also run SmartBox's separate 0.8-second HIGH/LOW/HIGH/LOW material-lighting pulse with the exact retail luminosity/diffuse replacements before restoring authored rendering. Issues #70/#71 closed; AP-29/TS-16 retired. Research: `docs/research/2026-07-17-retail-world-selection-pseudocode.md`.
|
||||
- **✓ SHIPPED — Wave 4.1 retail quick-slot input.** Bare `1..9` use toolbar slots 0..8, Ctrl+`1..9` selects them, Alt+`5..9` uses slots 13..17, and `0` creates a shortcut to the selected owned/eligible object in retail's first empty slot. `ToolbarInputController` is the focused semantic adapter; `ToolbarController` owns `UseShortcut` target-before-use/select ordering and auto-slot eligibility. Keybinding schema v2 migrates only the exact old default Ctrl+number chords, so custom bindings retain their chosen action. Full automated conformance and live user gate passed 2026-07-11.
|
||||
- **✓ SHIPPED — Wave 4.2 exact shortcut records.** One Core-owned `ShortcutEntry` preserves retail's signed `index_`, unsigned `objectID_`, and raw 32-bit `spellID_` through PlayerDescription parse, the nullable 18-slot session store, drag snapshots/reindexing, WorldSession, and exact 12-byte AddShortcut packing. The visible `gmToolbarUI` remains object-only; `favorite_spells_[8]` remains a separate future spell-bar source. AP-103 retired. Full automated conformance and live mutate→clean-relog persistence gate passed 2026-07-11.
|
||||
- **✓ SHIPPED — Wave 4.3a shortcut-alias boundary.** Drag feedback now preserves retail's neutral/accept/reject distinction. Inventory and paperdoll apply the `(DropItemFlags & 0xE) == 0` physical-item gate, so a toolbar alias can reorder within the toolbar but can never move, unwield, wield, or drop the object it references. Live equipped-helmet gate passed 2026-07-11: inventory drop removed only the shortcut.
|
||||
|
|
|
|||
|
|
@ -125,23 +125,70 @@ enum values `1..12`. Values `1..4` are the four on-screen corners.
|
|||
uses the active retail blit mode (`s_BlitMethod == 4`) to colorize the source
|
||||
art with the same color as the object's radar blip.
|
||||
|
||||
`VividTargetIndicator::OnDraw @ 0x004F62B0` (on-screen branch)
|
||||
`SmartBox::GetObjectBoundingBox @ 0x00452E20`
|
||||
|
||||
```text
|
||||
if disabled, no selected id, or selected part was not reported by this world draw:
|
||||
hide indicator
|
||||
resolve the selected id directly through CObjectMaint::GetObjectA
|
||||
if the object is absent:
|
||||
return ObjectNotFound
|
||||
|
||||
reset to Render::set_default_view
|
||||
push the object's position
|
||||
obtain CPhysicsObj::GetSelectionSphere
|
||||
if no sphere exists:
|
||||
use an origin-centered sphere with radius 0.1 world units
|
||||
|
||||
if Render::viewconeCheck says the sphere intersects the full viewport cone:
|
||||
project Render::GetViewerBBox's two corners
|
||||
return ObjectOnscreen and the resulting screen rectangle
|
||||
|
||||
target = normalized selection-sphere center in viewer-local coordinates
|
||||
if target is in front of the viewer:
|
||||
angle = (450 - degrees(atan2(target.screenRight, target.screenUp))) mod 360
|
||||
else:
|
||||
colorize the four DAT corner images with the selected radar-blip color
|
||||
obtain the selected object's SmartBox screen rectangle
|
||||
use the actual DAT corner width and height
|
||||
place the corner images just outside the rectangle
|
||||
clamp the assembled indicator to an 8-pixel viewport margin
|
||||
show the on-screen root and hide the off-screen root
|
||||
angle = (450 - degrees(atan2(target.screenRight, 0))) mod 360
|
||||
return ObjectOffscreen and angle
|
||||
```
|
||||
|
||||
The indicator is persistent selection presentation. Retail also has a separate,
|
||||
short-lived click confirmation owned by SmartBox; it is not implemented in
|
||||
`CPhysicsPart::Draw` or `ACCWeenieObject::SetSelected`.
|
||||
This path has no object-distance test and does not ask whether the selected
|
||||
object participated in the visible world draw. `set_default_view` also removes
|
||||
the per-portal view cone before the test. Consequently, a live selected object
|
||||
keeps its four corners through walls and at any distance for which it remains in
|
||||
the client object table.
|
||||
|
||||
`VividTargetIndicator::OnDraw @ 0x004F62B0`
|
||||
|
||||
```text
|
||||
if disabled, display-off, or selected id is zero:
|
||||
hide both roots
|
||||
else if status is ObjectOnscreen:
|
||||
colorize source images 1..4 with the selected radar-blip color
|
||||
use the actual DAT corner width and height
|
||||
place the corners just outside the SmartBox screen rectangle
|
||||
clamp the assembled indicator to an 8-pixel viewport margin
|
||||
show the on-screen root and hide the off-screen root
|
||||
else if status is ObjectOffscreen:
|
||||
choose one authored source image by angle:
|
||||
[338,360) or [0,23) -> 6
|
||||
[23,68) -> 7
|
||||
[68,113) -> 9
|
||||
[113,158) -> 12
|
||||
[158,203) -> 11
|
||||
[203,248) -> 10
|
||||
[248,293) -> 8
|
||||
[293,338) -> 5
|
||||
colorize it with the selected radar-blip color
|
||||
intersect the angle ray from viewport center with the screen edge
|
||||
center the image on that intersection
|
||||
clamp its top-left to the 8-pixel viewport margin
|
||||
hide the on-screen root and show the off-screen image
|
||||
```
|
||||
|
||||
Installed retail DAT verification pins images 1..4 at 12×12 pixels and images
|
||||
5..12 at 24×24 pixels. The larger off-screen marker is authored art, not a
|
||||
procedural arrow. The indicator is persistent selection presentation. Retail
|
||||
also has a separate, short-lived click confirmation owned by SmartBox; it is not
|
||||
implemented in `CPhysicsPart::Draw` or `ACCWeenieObject::SetSelected`.
|
||||
|
||||
## SmartBox click lighting pulse
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue