@displayxr/inline3d 1.45.0 → 1.46.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,53 @@ entry points (`.`, `./three`) are frozen for 1.x, while the **scene subpaths** (
5
5
  `./splat`, `./model`) are a preview tier whose options may change in any release. Entries below say
6
6
  which tier they touch, because that is what tells you whether an upgrade can move your pixels.
7
7
 
8
+ ## 1.46.0 — 2026-10-14
9
+
10
+ ### Depth cursor: when the runtime draws the web cursor, hand it the depth (runtime ADR-046 Amendment 4)
11
+
12
+ Touches `./cursor-depth`, `./three` (`DepthCursor`), the core tile handle, and the preview tier
13
+ (`./model`, `./splat`, `./call`, `./camera`), all only under `cursor: 'depth'`.
14
+
15
+ - In a DisplayXR Browser whose runtime draws the web cursor (`XRDisplayLayer.getCursorDepthSupport()`
16
+ → `"runtime"`: Windows, `XR_DXR_cursor_depth` spec ≥ 8), the depth cursor draws **no sprite** and
17
+ never hides the CSS cursor. Each frame it calls `layer.setCursorDepth({ disparityPx, u, v })` with
18
+ the **raw** content disparity under the footprint in **device px between the outermost views**
19
+ (< 0 = in front; no margin, clamp or filter: the runtime applies the one policy), `{ u, v }` with no
20
+ `disparityPx` over the element with nothing 3D under it, and `setCursorDepth()` once to withdraw
21
+ (pointer off the element, 2D, teardown). The runtime draws the browser's own cursor (`grab`,
22
+ `pointer`, `url(…)`), lifted, softened and late-latched.
23
+ - `"none"`, an older browser, or any other browser: unchanged — the SDK sprite, its softening and
24
+ CSS-shape mirroring, exactly as before. The browser answers `"none"` until its weave session is
25
+ live, so a `"none"` is re-asked (below).
26
+ - The support probe: a `"none"` is re-asked every 2 s for the first 6 asks, then every 10 s with no
27
+ cap (`CURSOR_RUNTIME_SLOW_RETRY_MS`), so a weave session that reports late (tens of seconds on a
28
+ cold GPU) still hands the cursor to the runtime. A browser without the API is never probed.
29
+ - Covered: `DepthCursor` (pass `update(views, { layer })`; `./model`/`./splat` on three do it),
30
+ the PlayCanvas cursor (`./model`, `./splat`), and the stereo-pair cursor (`./call`, `./camera`,
31
+ through the tile handle; its matched output-px disparity → device px).
32
+ - New: `CursorRuntimeLink`, `cursorRuntimeCapable`, `cursorDisparityPx`, `CURSOR_RUNTIME_RETRY_MS`,
33
+ `CURSOR_RUNTIME_PROBES`, `CURSOR_RUNTIME_SLOW_RETRY_MS` (`./cursor-depth`); `CursorPlacement.contentDisparity` /
34
+ `contentDisparityPx` / `runtime`; tile handle `setCursorDepth()` / `getCursorDepthSupport()`;
35
+ `XRDisplayLayer.setCursorDepth?` / `getCursorDepthSupport?` and `XRCursorDepthInit` in the types.
36
+ `DepthCursor.update`'s second argument may now be `{ nowMs, layer }` (a number still works).
37
+ - Needs DisplayXR Browser with page API patch 0409 (browser-pvt #285) and runtime spec 8 (runtime
38
+ #2088); safe to ship earlier, since it only activates on `"runtime"`.
39
+
40
+
41
+ ## 1.45.1 — 2026-10-13
42
+
43
+ ### Fixed — `cursor: 'depth'` showed up under a finger (touch)
44
+
45
+ - On a touch device, dragging a finger over a scene drew the 3D cursor, though the browser shows no
46
+ cursor there. Since 1.44.0 the pointer took every `pointermove` / `pointerrawupdate` whatever
47
+ its `pointerType`. Now only a **mouse** or a **hovering pen** places the cursor. A touch or a pen
48
+ in contact clears it, including a tap that never moves (so no stale mouse hover stays up), and
49
+ the CSS cursor is never hidden for them. This covers every backend (three.js `./model`,
50
+ PlayCanvas `./model` / `./splat`, the `./call` / `./camera` pair cursor). They all share
51
+ `CursorPointer`.
52
+ - New `cursorPointerHovers(e)` in `./cursor-depth`. An event with no `pointerType` (synthetic)
53
+ counts as a mouse, as before.
54
+
8
55
  ## 1.45.0 — 2026-10-13
9
56
 
10
57
  ### Packaging
package/cursor-depth.d.ts CHANGED
@@ -146,6 +146,47 @@ export interface CursorPlacement {
146
146
  targetDisparity: number;
147
147
  /** Hybrid: true while the pointer is still and the sprite is held world-fixed. */
148
148
  anchored?: boolean;
149
+ /** The RAW content disparity under the footprint (baselines, < 0 in front), before the policy; null = nothing under it. */
150
+ contentDisparity?: number | null;
151
+ /** `contentDisparity` in device px between the outermost views (what `setCursorDepth` takes); null when unknown. */
152
+ contentDisparityPx?: number | null;
153
+ /** True when the runtime drew the cursor this frame (ADR-046 Amendment 4): `active` is then false — the SDK drew nothing. */
154
+ runtime?: boolean;
155
+ }
156
+
157
+ // ── The runtime draws the web cursor (runtime ADR-046 Amendment 4) ───────────────────────────
158
+
159
+ /** Re-ask a target that answered "none" at most this often (ms) while the cursor runs. */
160
+ export const CURSOR_RUNTIME_RETRY_MS: number;
161
+ /** At most this many support probes per target. */
162
+ export const CURSOR_RUNTIME_PROBES: number;
163
+ /** After the fast probes, a "none" is re-asked this often, without a cap (a late weave session). */
164
+ export const CURSOR_RUNTIME_SLOW_RETRY_MS: number;
165
+ /** Does `target` (an XRDisplayLayer, or a tile handle) have `setCursorDepth` + `getCursorDepthSupport`? */
166
+ export function cursorRuntimeCapable(target: unknown): boolean;
167
+ /** Baseline-unit content disparity → device px between the outermost views (`d × pxPerBaseline`); null when either is unknown. */
168
+ export function cursorDisparityPx(contentDisparity: number | null | undefined, pxPerBaseline: number | null | undefined): number | null;
169
+ /** Anything a depth can be handed to: an XRDisplayLayer, or a tile handle that forwards to one. */
170
+ export interface CursorDepthTarget {
171
+ setCursorDepth(depth?: { disparityPx?: number | null; u: number; v: number } | null): unknown;
172
+ getCursorDepthSupport(): Promise<string>;
173
+ }
174
+ /**
175
+ * The page half of a runtime-drawn cursor, used by every backend: per frame `bind(target)` (true =
176
+ * the runtime draws: draw no sprite, leave the CSS cursor alone), then `report(u, v, disparityPx)`
177
+ * while the pointer is over the element, `withdraw()` when not.
178
+ */
179
+ export class CursorRuntimeLink {
180
+ constructor();
181
+ readonly target: CursorDepthTarget | null;
182
+ /** The last depth sent (diagnostics), null after a withdrawal. */
183
+ readonly last: { u: number; v: number; disparityPx: number | null } | null;
184
+ readonly support: 'runtime' | 'none' | 'pending';
185
+ readonly drawing: boolean;
186
+ bind(target: CursorDepthTarget | null | undefined): boolean;
187
+ report(u: number, v: number, disparityPx: number | null): boolean;
188
+ withdraw(): void;
189
+ dispose(): void;
149
190
  }
150
191
 
151
192
  /** The whole pipeline with its filter state: one per cursor. Inactive with fewer than two views. */