@displayxr/inline3d 1.6.0 → 1.6.1
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 +38 -0
- package/index.d.ts +9 -0
- package/js/inline3d-model.js +3 -0
- package/js/inline3d-splat.js +3 -0
- package/js/inline3d-viewer.js +21 -2
- package/js/inline3d.js +138 -6
- package/package.json +1 -1
- package/viewer.d.ts +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,44 @@ 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.6.1 — 2026-09-09
|
|
9
|
+
|
|
10
|
+
Touches the **core tier** (`.`) with a behaviour fix only — no API changes — and the **preview tier**
|
|
11
|
+
(`./viewer`, `./splat`, `./model`) with one additive option. A page that ignores everything below
|
|
12
|
+
renders identically while it is weaving; the changes only decide what a canvas shows once nothing
|
|
13
|
+
weaves it any more.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- **A canvas nothing is weaving can no longer be left holding a raw side-by-side pair**
|
|
18
|
+
([#28](https://github.com/DisplayXR/displayxr-web/issues/28), field report
|
|
19
|
+
[browser-pvt#99](https://github.com/DisplayXR/displayxr-browser-pvt/issues/99)). Every fallback in
|
|
20
|
+
this SDK was decided once at boot, so four paths ended with a tile showing a flat squeezed
|
|
21
|
+
left|right pair, permanently — the symptom users report as "3D element shows SBS", usually on a
|
|
22
|
+
slow connection:
|
|
23
|
+
- session `end` tore down without the mono repaint `_deactivate` does — every image and video
|
|
24
|
+
canvas kept its last SBS frame; teardown, deactivate and a failed activate now share one
|
|
25
|
+
`_paintMono`;
|
|
26
|
+
- an image whose download landed **after** teardown painted a fresh SBS pair into a canvas with no
|
|
27
|
+
layer — `_paint` now forces the mono branch (and a 1:1 buffer) whenever the manager is stopped or
|
|
28
|
+
the window has no live layer, whatever `win.sbs` says;
|
|
29
|
+
- a throwing `new XRDisplayLayer()` was swallowed silently and left the canvas as it was — it now
|
|
30
|
+
warns once per window (with the error) and repaints mono; still no retry;
|
|
31
|
+
- a buffering video (`readyState < 2`) skipped its paint entirely, so its canvas layer went idle and
|
|
32
|
+
could drop out of the browser's aggregated frame — it now re-commits its last decoded frame with
|
|
33
|
+
an identity blit.
|
|
34
|
+
- **One throwing scene no longer stops the windows after it from repainting.** `onFrame` is contained
|
|
35
|
+
per window and warned about once; an un-redrawn canvas is exactly what the browser's weave join
|
|
36
|
+
loses.
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
- **`addScene({ onLayerLost })`** (preview tier): called once when a scene window's layer goes away
|
|
41
|
+
for good (session end, or the layer could not be created) — not when a lazy tile scrolls off. The
|
|
42
|
+
SDK does not own a scene canvas's pixels, so this is how it tells the owner to go flat.
|
|
43
|
+
`SceneViewer.onLayerLost` is the ready-made handler (`startMono()`), and `./splat` / `./model` wire
|
|
44
|
+
it for you.
|
|
45
|
+
|
|
8
46
|
## 1.6.0 — 2026-09-08
|
|
9
47
|
|
|
10
48
|
Touches the **preview tier** (`./viewer`) and fixes a **documentation error in the core tier**.
|
package/index.d.ts
CHANGED
|
@@ -179,6 +179,15 @@ export interface SceneOptions extends TileOptions {
|
|
|
179
179
|
viewRig?: XRViewRigInit;
|
|
180
180
|
/** Element whose visibility drives the lazy create/close lifecycle (defaults to the canvas). */
|
|
181
181
|
observe?: Element;
|
|
182
|
+
/**
|
|
183
|
+
* Called once when this window's weave layer goes away for good — the session ended, or the
|
|
184
|
+
* layer could not be created. You own a scene canvas's pixels, so this is the SDK's only way
|
|
185
|
+
* to tell you that the side-by-side pair in it is no longer being woven and is now just
|
|
186
|
+
* squeezed 2D on the page: take the canvas flat here (`SceneViewer.startMono`, or your own
|
|
187
|
+
* mono path). NOT called when a lazy tile merely scrolls off screen — that layer is coming
|
|
188
|
+
* back. A throw is caught and warned about.
|
|
189
|
+
*/
|
|
190
|
+
onLayerLost?: () => void;
|
|
182
191
|
}
|
|
183
192
|
|
|
184
193
|
/** The per-frame render callback passed to {@link Inline3D.addScene}. */
|
package/js/inline3d-model.js
CHANGED
|
@@ -393,6 +393,9 @@ export function addModel(wall, canvas, src, opts = {}) {
|
|
|
393
393
|
if (wall && wall.supported) {
|
|
394
394
|
handle = wall.addScene(canvas, viewer.onFrame, {
|
|
395
395
|
virtualDisplayHeight,
|
|
396
|
+
// The layer can go away for good (the session ends, the constructor refuses): take the
|
|
397
|
+
// canvas flat rather than leave its last side-by-side frame on the page (web#28).
|
|
398
|
+
onLayerLost: viewer.onLayerLost,
|
|
396
399
|
...(observe ? { observe } : {}),
|
|
397
400
|
});
|
|
398
401
|
} else {
|
package/js/inline3d-splat.js
CHANGED
|
@@ -228,6 +228,9 @@ export function addSplat(wall, canvas, src, opts = {}) {
|
|
|
228
228
|
if (wall && wall.supported) {
|
|
229
229
|
handle = wall.addScene(canvas, viewer.onFrame, {
|
|
230
230
|
virtualDisplayHeight,
|
|
231
|
+
// The layer can go away for good (the session ends, the constructor refuses): take the
|
|
232
|
+
// canvas flat rather than leave its last side-by-side frame on the page (web#28).
|
|
233
|
+
onLayerLost: viewer.onLayerLost,
|
|
231
234
|
...(observe ? { observe } : {}),
|
|
232
235
|
});
|
|
233
236
|
} else {
|
package/js/inline3d-viewer.js
CHANGED
|
@@ -28,7 +28,11 @@
|
|
|
28
28
|
// viewer.content.add(myMesh);
|
|
29
29
|
// viewer.fitTo(center, extent); // model-space bounds of the subject
|
|
30
30
|
// const wall = await createInline3D();
|
|
31
|
-
// if (wall.supported)
|
|
31
|
+
// if (wall.supported)
|
|
32
|
+
// wall.addScene(canvas, viewer.onFrame, {
|
|
33
|
+
// virtualDisplayHeight: 0.18,
|
|
34
|
+
// onLayerLost: viewer.onLayerLost, // the session ended: go flat rather than show raw SBS
|
|
35
|
+
// });
|
|
32
36
|
// else viewer.startMono();
|
|
33
37
|
//
|
|
34
38
|
// WHY FRAMING IS SCENE-GRAPH WORK AND NOT A RIG FIELD. The native display rig
|
|
@@ -269,8 +273,23 @@ export class SceneViewer {
|
|
|
269
273
|
if (orbit) this._bindOrbit();
|
|
270
274
|
this._resize();
|
|
271
275
|
|
|
272
|
-
// Bound so
|
|
276
|
+
// Bound so they can be passed straight to addScene without a wrapper closure.
|
|
273
277
|
this.onFrame = this.onFrame.bind(this);
|
|
278
|
+
this.onLayerLost = this.onLayerLost.bind(this);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* The weave layer went away for good — pass this to `wall.addScene(canvas, viewer.onFrame,
|
|
283
|
+
* { onLayerLost: viewer.onLayerLost })` (`./splat` and `./model` do it for you).
|
|
284
|
+
*
|
|
285
|
+
* Without it the canvas keeps its last woven side-by-side frame on screen as ordinary squeezed
|
|
286
|
+
* 2D, because `_mode` stays `'3d'` and every mono fallback in this SDK is a one-shot decision
|
|
287
|
+
* made at boot (web#28). Going mono here is safe even if a tile is later re-woven: `onFrame`
|
|
288
|
+
* calls `stopMono()` on the first 3D frame it gets.
|
|
289
|
+
*/
|
|
290
|
+
onLayerLost() {
|
|
291
|
+
if (this._disposed) return;
|
|
292
|
+
this.startMono();
|
|
274
293
|
}
|
|
275
294
|
|
|
276
295
|
/**
|
package/js/inline3d.js
CHANGED
|
@@ -860,6 +860,12 @@ class Inline3D {
|
|
|
860
860
|
* falls back to `virtualDisplayHeight` if one was given (that pair is the one reason
|
|
861
861
|
* to pass both) — either way the window still weaves.
|
|
862
862
|
* @param {Element} [opts.observe=canvas] element whose visibility gates lazy create/close.
|
|
863
|
+
* @param {() => void} [opts.onLayerLost] called once when this window's weave layer goes away
|
|
864
|
+
* for good — the session ended, or the layer could not be created. YOU own a scene
|
|
865
|
+
* canvas's pixels, so this is the SDK's only way to tell you that the side-by-side pair
|
|
866
|
+
* in it is no longer being woven and is now just squeezed 2D on the page; take the
|
|
867
|
+
* canvas flat here (`SceneViewer.startMono`, or your own mono path). NOT called when a
|
|
868
|
+
* lazy tile merely scrolls off screen — that layer is coming back. Errors are caught.
|
|
863
869
|
* @returns {{remove():void}}
|
|
864
870
|
*/
|
|
865
871
|
addScene(canvas, onFrame, opts = {}) {
|
|
@@ -1746,6 +1752,12 @@ class Inline3D {
|
|
|
1746
1752
|
img: null,
|
|
1747
1753
|
video: null,
|
|
1748
1754
|
onFrame: null,
|
|
1755
|
+
// Scene windows only (addScene's `onLayerLost`): the layer went away for good. See
|
|
1756
|
+
// _notifyLayerLost — `layerLostSent` keeps it one-shot per loss. Read from the options
|
|
1757
|
+
// HERE rather than after `_register` returns, because a non-lazy window activates (and can
|
|
1758
|
+
// therefore already fail to build its layer) inside this call.
|
|
1759
|
+
onLayerLost: typeof opts.onLayerLost === 'function' ? opts.onLayerLost : null,
|
|
1760
|
+
layerLostSent: false,
|
|
1749
1761
|
ready: null,
|
|
1750
1762
|
ownsBuffer: kind !== 'scene',
|
|
1751
1763
|
cornerRadius: opts.cornerRadius || 0,
|
|
@@ -1844,10 +1856,27 @@ class Inline3D {
|
|
|
1844
1856
|
? { virtualDisplayHeight: win.virtualDisplayHeight }
|
|
1845
1857
|
: {};
|
|
1846
1858
|
win.layer = new XRDisplayLayer(this.session, win.canvas, init);
|
|
1847
|
-
} catch {
|
|
1859
|
+
} catch (err) {
|
|
1848
1860
|
win.layer = null;
|
|
1861
|
+
// Say so, once per window, and take the canvas flat. Swallowed silently this was
|
|
1862
|
+
// undiagnosable in the field AND left a re-activated tile holding the SBS pair it wove
|
|
1863
|
+
// with last time — nothing repaints it, and the IntersectionObserver does not re-fire
|
|
1864
|
+
// while the tile stays intersecting. No retry: a constructor that refused this canvas will
|
|
1865
|
+
// refuse it again, and a retry loop would run per frame with nothing to report (web#28).
|
|
1866
|
+
if (!win.layerFailWarned) {
|
|
1867
|
+
win.layerFailWarned = true;
|
|
1868
|
+
console.warn(
|
|
1869
|
+
'[inline3d] new XRDisplayLayer() failed for this window — it will show FLAT 2D ' +
|
|
1870
|
+
'instead of woven 3D, and the SDK will not retry. The canvas has been repainted ' +
|
|
1871
|
+
'mono so it cannot be left holding a raw side-by-side pair.',
|
|
1872
|
+
err
|
|
1873
|
+
);
|
|
1874
|
+
}
|
|
1875
|
+
this._paintMono(win);
|
|
1876
|
+
this._notifyLayerLost(win);
|
|
1849
1877
|
return;
|
|
1850
1878
|
}
|
|
1879
|
+
win.layerLostSent = false; // a live layer again: a future loss is worth reporting again
|
|
1851
1880
|
// Nothing about the hardware state is re-asserted here, and that is the point: the panel's
|
|
1852
1881
|
// mode is the DISPLAY's, it survives a tile scrolling away, and this SDK never requests it
|
|
1853
1882
|
// behind the page's back. The rig went into the init above already flattened if a 1-view
|
|
@@ -1898,9 +1927,47 @@ class Inline3D {
|
|
|
1898
1927
|
win.layer = null;
|
|
1899
1928
|
}
|
|
1900
1929
|
// Leave a flat (left-eye-only) frame so an off-screen image/video still shows 2D.
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1930
|
+
//
|
|
1931
|
+
// A SCENE is deliberately NOT notified here (see _notifyLayerLost): its layer is coming
|
|
1932
|
+
// back the moment the tile scrolls into view again, and `SceneViewer.onFrame` takes the
|
|
1933
|
+
// backing store back to SBS by itself — collapsing on every scroll would make the lazy
|
|
1934
|
+
// lifecycle visible as a mode change.
|
|
1935
|
+
this._paintMono(win);
|
|
1936
|
+
}
|
|
1937
|
+
|
|
1938
|
+
/**
|
|
1939
|
+
* Take a window whose layer is gone back to the ONE state a canvas nothing weaves may be left
|
|
1940
|
+
* in: a flat, left-eye-only frame in a 1:1 buffer (web#28).
|
|
1941
|
+
*
|
|
1942
|
+
* Shared by _deactivate, _teardown and the _activate failure path precisely so the three
|
|
1943
|
+
* cannot drift — _teardown used to skip it entirely, which left every image and video tile on
|
|
1944
|
+
* the page holding its last side-by-side frame, forever, the moment the session ended.
|
|
1945
|
+
* Scene canvases are the page's pixels and are handled by _notifyLayerLost instead.
|
|
1946
|
+
*/
|
|
1947
|
+
_paintMono(win) {
|
|
1948
|
+
if (!win.ownsBuffer || win.kind === 'scene') return;
|
|
1949
|
+
this._sizeBuffer(win, /*sbs*/ false);
|
|
1950
|
+
this._paint(win, null);
|
|
1951
|
+
}
|
|
1952
|
+
|
|
1953
|
+
/**
|
|
1954
|
+
* The scene half of the same problem. The SDK does not own a scene canvas's backing store, so
|
|
1955
|
+
* the most it can do is SAY the layer went away and let the owner take itself flat —
|
|
1956
|
+
* `SceneViewer` wires its `startMono()` here (`addScene({ onLayerLost })`), and `./splat` and
|
|
1957
|
+
* `./model` do that for you. Without it a scene tile keeps its last woven side-by-side frame
|
|
1958
|
+
* on screen after the session ends, because every mono fallback in this SDK and its samples is
|
|
1959
|
+
* a one-shot `!supported` branch decided at boot.
|
|
1960
|
+
*
|
|
1961
|
+
* One-shot per loss and never allowed to throw: this runs inside teardown, where a page
|
|
1962
|
+
* callback that raises must not strand the windows behind it.
|
|
1963
|
+
*/
|
|
1964
|
+
_notifyLayerLost(win) {
|
|
1965
|
+
if (win.kind !== 'scene' || typeof win.onLayerLost !== 'function' || win.layerLostSent) return;
|
|
1966
|
+
win.layerLostSent = true;
|
|
1967
|
+
try {
|
|
1968
|
+
win.onLayerLost();
|
|
1969
|
+
} catch (err) {
|
|
1970
|
+
console.warn('[inline3d] a scene window\'s onLayerLost callback threw', err);
|
|
1904
1971
|
}
|
|
1905
1972
|
}
|
|
1906
1973
|
|
|
@@ -2208,9 +2275,28 @@ class Inline3D {
|
|
|
2208
2275
|
|
|
2209
2276
|
_paint(win, _views) {
|
|
2210
2277
|
if (win.kind === 'scene' || !win.ctx) return;
|
|
2278
|
+
// NOTHING IS WEAVING THIS CANVAS (web#28, browser-pvt#99). A dead manager or a window with
|
|
2279
|
+
// no layer means the browser is not consuming this canvas as a stereo pair any more — so an
|
|
2280
|
+
// SBS paint here puts the raw squeezed left|right pair on screen as ordinary 2D page
|
|
2281
|
+
// content, permanently, because nothing ever repaints it. The path that makes this a FIELD
|
|
2282
|
+
// bug rather than a theoretical one is a slow download: `addImage`'s load resolves after the
|
|
2283
|
+
// session ended and calls `win.repaint()` straight into a canvas whose layer is gone.
|
|
2284
|
+
// Forced here rather than at each call site because the call sites are the async ones.
|
|
2285
|
+
// The buffer comes with it — the mono branch below stretches ONE eye across the whole
|
|
2286
|
+
// backing store, so leaving a 2:1 store would show a double-width half-image.
|
|
2287
|
+
const live = this._running && !!win.layer;
|
|
2288
|
+
if (!live && win.sbs) this._sizeBuffer(win, /*sbs*/ false);
|
|
2211
2289
|
const src = win.kind === 'video' ? win.video : win.img;
|
|
2212
2290
|
if (!src) return;
|
|
2213
|
-
if (win.kind === 'video' && (src.readyState || 0) < 2)
|
|
2291
|
+
if (win.kind === 'video' && (src.readyState || 0) < 2) {
|
|
2292
|
+
// Buffering: no new frame to draw, and drawing an unready <video> is a no-op per spec (it
|
|
2293
|
+
// would leave the clearRect below as the only thing that happened, i.e. blank the tile).
|
|
2294
|
+
// Skipping the paint entirely is what the old code did, and that is its own bug — see
|
|
2295
|
+
// _frame: a canvas that is not redrawn can have its layer dropped from the aggregated
|
|
2296
|
+
// frame. So re-commit what the canvas already holds instead.
|
|
2297
|
+
if (live) this._recommitLastFrame(win);
|
|
2298
|
+
return;
|
|
2299
|
+
}
|
|
2214
2300
|
const c = win.canvas;
|
|
2215
2301
|
const ctx = win.ctx;
|
|
2216
2302
|
const srcW = src.videoWidth || src.naturalWidth || src.width;
|
|
@@ -2234,6 +2320,30 @@ class Inline3D {
|
|
|
2234
2320
|
}
|
|
2235
2321
|
}
|
|
2236
2322
|
|
|
2323
|
+
/**
|
|
2324
|
+
* Re-commit the pixels the canvas already holds, unchanged — the cheapest "last decoded frame"
|
|
2325
|
+
* there is, because the last decoded frame is already in the backing store.
|
|
2326
|
+
*
|
|
2327
|
+
* Drawing the canvas onto itself is one same-size blit that dirties the canvas (which is the
|
|
2328
|
+
* whole point: see the every-frame-repaint note in _frame), and `globalCompositeOperation =
|
|
2329
|
+
* 'copy'` is what makes it a true identity — source-over would composite a feathered buffer's
|
|
2330
|
+
* transparent edges onto themselves and darken the ramp a little more every stalled frame.
|
|
2331
|
+
* Only ever reached while a source has nothing new, so a healthy video never pays for it.
|
|
2332
|
+
*/
|
|
2333
|
+
_recommitLastFrame(win) {
|
|
2334
|
+
const c = win.canvas;
|
|
2335
|
+
if (!c.width || !c.height) return;
|
|
2336
|
+
const ctx = win.ctx;
|
|
2337
|
+
try {
|
|
2338
|
+
ctx.save();
|
|
2339
|
+
ctx.globalCompositeOperation = 'copy';
|
|
2340
|
+
ctx.drawImage(c, 0, 0);
|
|
2341
|
+
ctx.restore();
|
|
2342
|
+
} catch {
|
|
2343
|
+
/* a context that refuses a self-blit: leave the stale pixels rather than blank the tile */
|
|
2344
|
+
}
|
|
2345
|
+
}
|
|
2346
|
+
|
|
2237
2347
|
/**
|
|
2238
2348
|
* Arm the next session frame. `force` starts a NEW loop even though one is nominally
|
|
2239
2349
|
* pending: each loop carries an id and only the current id re-arms, so a stalled
|
|
@@ -2293,7 +2403,22 @@ class Inline3D {
|
|
|
2293
2403
|
);
|
|
2294
2404
|
}
|
|
2295
2405
|
}
|
|
2296
|
-
|
|
2406
|
+
// Contained, and warned about once. A scene that throws (a texture that 404s, a
|
|
2407
|
+
// decoder that gives up) used to abort this loop body for every window AFTER it in the
|
|
2408
|
+
// map — and an un-redrawn canvas can have its layer dropped from the aggregated frame
|
|
2409
|
+
// (see the note below), so one broken tile took its neighbours' weave with it (web#28).
|
|
2410
|
+
try {
|
|
2411
|
+
win.onFrame(views, win.layer, f);
|
|
2412
|
+
} catch (err) {
|
|
2413
|
+
if (!win.frameThrewWarned) {
|
|
2414
|
+
win.frameThrewWarned = true;
|
|
2415
|
+
console.warn(
|
|
2416
|
+
"[inline3d] a scene window's onFrame threw; this window will keep whatever it " +
|
|
2417
|
+
'last drew, and the other windows carry on. Further throws from it are silent.',
|
|
2418
|
+
err
|
|
2419
|
+
);
|
|
2420
|
+
}
|
|
2421
|
+
}
|
|
2297
2422
|
}
|
|
2298
2423
|
} else {
|
|
2299
2424
|
// Repaint image AND video every frame. The weave reads each window's
|
|
@@ -2430,6 +2555,13 @@ class Inline3D {
|
|
|
2430
2555
|
}
|
|
2431
2556
|
win.layer = null;
|
|
2432
2557
|
}
|
|
2558
|
+
// The repaint _deactivate has always done, which this path used to skip (web#28). Closing
|
|
2559
|
+
// the layer also clears the browser's tracked rect, so from here nothing suppresses these
|
|
2560
|
+
// canvases and nothing will ever repaint them either — whatever is in the backing store
|
|
2561
|
+
// when the session ends is what the page shows from now on. A side-by-side pair is the one
|
|
2562
|
+
// thing that must not be. AFTER the close, so the flat frame is the last thing committed.
|
|
2563
|
+
this._paintMono(win);
|
|
2564
|
+
this._notifyLayerLost(win);
|
|
2433
2565
|
}
|
|
2434
2566
|
this._windows.clear();
|
|
2435
2567
|
// Page listeners go with the session that fed them: a manager whose session has ended will
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@displayxr/inline3d",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.1",
|
|
4
4
|
"description": "Turn any HTML <canvas> into a glasses-free-3D window on a DisplayXR display, inside an ordinary web page. Dependency-free; progressive enhancement (falls back to plain 2D everywhere else).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./index.d.ts",
|
package/viewer.d.ts
CHANGED
|
@@ -139,6 +139,12 @@ export declare class SceneViewer {
|
|
|
139
139
|
* frame either way, so the tile never goes dark and never smears (web#12).
|
|
140
140
|
*/
|
|
141
141
|
onFrame(views: readonly XRView[], layer: object): void;
|
|
142
|
+
/**
|
|
143
|
+
* The weave layer went away for good — pass to `addScene(canvas, viewer.onFrame,
|
|
144
|
+
* { onLayerLost: viewer.onLayerLost })` so the tile goes flat instead of showing its last
|
|
145
|
+
* side-by-side frame as squeezed 2D. Pre-bound; `./splat` and `./model` wire it for you.
|
|
146
|
+
*/
|
|
147
|
+
onLayerLost(): void;
|
|
142
148
|
|
|
143
149
|
/** Supply the ./three glue so the 3D path can build its eye camera. Returns `this`. */
|
|
144
150
|
useEyeCamera(EyeCameraClass: unknown, EdgeFeatherClass?: unknown): this;
|