@crystaldesign/real-time-viewer-next 26.12.0-beta.2 → 26.12.0-beta.20
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/build/esm/{DeckCutoutSubsystem-5d0fb500.js → DeckCutoutSubsystem-34516143.js} +3 -1
- package/build/esm/{SunLensflare-9cbd6d72.js → SunLensflare-55ce48ee.js} +1 -1
- package/build/esm/{WaterSurface-715ff751.js → WaterSurface-ff270e38.js} +1 -1
- package/build/esm/{index-cc012549.js → index-8c31a811.js} +162 -43
- package/build/esm/index.js +1 -1
- package/build/types/real-time-viewer-next/src/RealTimeRendererNext.d.ts +5 -0
- package/build/types/real-time-viewer-next/src/RealTimeRendererNext.d.ts.map +1 -1
- package/build/types/real-time-viewer-next/src/core/SceneRenderer.d.ts.map +1 -1
- package/build/types/real-time-viewer-next/src/core/camera/useMaterialFade.d.ts.map +1 -1
- package/build/types/real-time-viewer-next/src/core/environment/deckCutout/collectDeckTriangles.d.ts.map +1 -1
- package/build/types/real-time-viewer-next/src/core/materials/fadeState.d.ts +23 -0
- package/build/types/real-time-viewer-next/src/core/materials/fadeState.d.ts.map +1 -0
- package/build/types/real-time-viewer-next/src/core/materials/fadeState.test.d.ts +2 -0
- package/build/types/real-time-viewer-next/src/core/materials/fadeState.test.d.ts.map +1 -0
- package/build/types/real-time-viewer-next/src/core/useFrameloopVisibility.d.ts +2 -1
- package/build/types/real-time-viewer-next/src/core/useFrameloopVisibility.d.ts.map +1 -1
- package/build/types/real-time-viewer-next/src/core/water/CausticReceiver.d.ts.map +1 -1
- package/build/types/real-time-viewer-next/src/hooks/useAssembledScene.d.ts.map +1 -1
- package/build/types/real-time-viewer-next/src/hooks/useHostPropsSync.d.ts +2 -2
- package/build/types/real-time-viewer-next/src/hooks/useHostPropsSync.d.ts.map +1 -1
- package/build/types/real-time-viewer-next/src/loadingGates.d.ts +5 -3
- package/build/types/real-time-viewer-next/src/loadingGates.d.ts.map +1 -1
- package/build/types/real-time-viewer-next/src/store/slices/glGeneration.d.ts +7 -0
- package/build/types/real-time-viewer-next/src/store/slices/glGeneration.d.ts.map +1 -1
- package/build/types/real-time-viewer-next/src/utils/hashString.d.ts +6 -0
- package/build/types/real-time-viewer-next/src/utils/hashString.d.ts.map +1 -0
- package/build/types/real-time-viewer-next/src/utils/suspense.d.ts.map +1 -1
- package/build/umd/964.real-time-viewer-next.umd.min.js +1 -1
- package/build/umd/real-time-viewer-next.umd.min.js +1 -1
- package/build/umd/report.html +1 -1
- package/package.json +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { p as parseElementKey, u as useStableEnvSlice, a as useRTVStore, b as bootPhase, D as DECK_COLLAR_LOAD_ID } from './index-
|
|
1
|
+
import { p as parseElementKey, u as useStableEnvSlice, a as useRTVStore, b as bootPhase, c as adoptPristineFadeState, D as DECK_COLLAR_LOAD_ID } from './index-8c31a811.js';
|
|
2
2
|
import { useRef, useEffect, useMemo, useState, useCallback } from 'react';
|
|
3
3
|
import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
|
|
4
4
|
import _defineProperty from '@babel/runtime/helpers/defineProperty';
|
|
@@ -2000,6 +2000,8 @@ function meshesMatching(root, patterns) {
|
|
|
2000
2000
|
*/
|
|
2001
2001
|
function cloneDeckMaterial(source) {
|
|
2002
2002
|
var clone = source.clone();
|
|
2003
|
+
// The deck is sampled while the 2D→3D fade may still be driving its material.
|
|
2004
|
+
adoptPristineFadeState(clone);
|
|
2003
2005
|
if (clone instanceof MeshStandardMaterial) {
|
|
2004
2006
|
clone.aoMap = null;
|
|
2005
2007
|
clone.lightMap = null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
|
|
2
|
-
import {
|
|
2
|
+
import { g as flushPendingBVH, h as collectCollisionTargets } from './index-8c31a811.js';
|
|
3
3
|
import { useMemo, useEffect, useRef } from 'react';
|
|
4
4
|
import { Billboard } from '@react-three/drei';
|
|
5
5
|
import { useThree, useFrame } from '@react-three/fiber';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
|
|
2
|
-
import { w as withRenderTarget, s as setCausticReceiversSuspended,
|
|
2
|
+
import { w as withRenderTarget, s as setCausticReceiversSuspended, d as waterUniforms, e as disableWaterUniforms, a as useRTVStore, F as FRAME_ORDER, f as sunAnglesToDirection, l as lightingSunTowardDirection } from './index-8c31a811.js';
|
|
3
3
|
import { useRef, useMemo, useEffect, useCallback, useState } from 'react';
|
|
4
4
|
import { useThree, useFrame } from '@react-three/fiber';
|
|
5
5
|
import { Vector3, WebGLRenderTarget, HalfFloatType, RGBAFormat, LinearFilter, OrthographicCamera, ShaderMaterial, DoubleSide, MeshStandardMaterial, Box3, NoToneMapping, Frustum, Matrix4, Vector4, Vector2, Plane, Scene, Mesh, PlaneGeometry, ClampToEdgeWrapping, UnsignedByteType, LinearMipmapLinearFilter, MeshBasicMaterial, Color } from 'three';
|
|
@@ -60,6 +60,21 @@ if (typeof __webpack_public_path__ !== 'undefined') {
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Two independent 32-bit hashes (djb2 + sdbm) plus the length, for callers that keep a digest of a
|
|
65
|
+
* string instead of the string itself. A collision would have to hit all three at once.
|
|
66
|
+
*/
|
|
67
|
+
function hashString(text) {
|
|
68
|
+
var h1 = 5381;
|
|
69
|
+
var h2 = 0;
|
|
70
|
+
for (var i = 0; i < text.length; i++) {
|
|
71
|
+
var c = text.charCodeAt(i);
|
|
72
|
+
h1 = (h1 << 5) + h1 + c | 0;
|
|
73
|
+
h2 = c + (h2 << 6) + (h2 << 16) - h2 | 0;
|
|
74
|
+
}
|
|
75
|
+
return "".concat(text.length, ":").concat(h1, ":").concat(h2);
|
|
76
|
+
}
|
|
77
|
+
|
|
63
78
|
function _createForOfIteratorHelper$J(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray$J(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
|
|
64
79
|
function _unsupportedIterableToArray$J(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray$J(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray$J(r, a) : void 0; } }
|
|
65
80
|
function _arrayLikeToArray$J(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
@@ -68,20 +83,11 @@ var cache = new Map();
|
|
|
68
83
|
var generation = 0;
|
|
69
84
|
|
|
70
85
|
/**
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
* unbounded — hashed keys keep the map's key memory flat.
|
|
86
|
+
* A raw product-material key carries the full mat-list (tens of KB) and distinct configurations
|
|
87
|
+
* are unbounded — hashed keys keep the map's key memory flat.
|
|
74
88
|
*/
|
|
75
89
|
function hashKeys(keys) {
|
|
76
|
-
|
|
77
|
-
var h1 = 5381;
|
|
78
|
-
var h2 = 0;
|
|
79
|
-
for (var i = 0; i < serialized.length; i++) {
|
|
80
|
-
var c = serialized.charCodeAt(i);
|
|
81
|
-
h1 = (h1 << 5) + h1 + c | 0;
|
|
82
|
-
h2 = c + (h2 << 6) + (h2 << 16) - h2 | 0;
|
|
83
|
-
}
|
|
84
|
-
return "".concat(h1, ":").concat(h2);
|
|
90
|
+
return hashString(JSON.stringify(keys));
|
|
85
91
|
}
|
|
86
92
|
|
|
87
93
|
/**
|
|
@@ -1055,6 +1061,12 @@ var createGLGenerationSlice = function createGLGenerationSlice(set, get) {
|
|
|
1055
1061
|
glContextLost: lost
|
|
1056
1062
|
});
|
|
1057
1063
|
},
|
|
1064
|
+
renderStopped: false,
|
|
1065
|
+
setRenderStopped: function setRenderStopped(stopped) {
|
|
1066
|
+
if (get().renderStopped !== stopped) set({
|
|
1067
|
+
renderStopped: stopped
|
|
1068
|
+
});
|
|
1069
|
+
},
|
|
1058
1070
|
glContextLossLoop: false,
|
|
1059
1071
|
registerContextRestore: function registerContextRestore() {
|
|
1060
1072
|
var now = Date.now();
|
|
@@ -4422,7 +4434,7 @@ var chunk$2;
|
|
|
4422
4434
|
/** Memoized so the preload and the lazy mount share ONE chunk request. */
|
|
4423
4435
|
function loadChunk$2() {
|
|
4424
4436
|
var _chunk;
|
|
4425
|
-
return (_chunk = chunk$2) !== null && _chunk !== void 0 ? _chunk : chunk$2 = import('./WaterSurface-
|
|
4437
|
+
return (_chunk = chunk$2) !== null && _chunk !== void 0 ? _chunk : chunk$2 = import('./WaterSurface-ff270e38.js');
|
|
4426
4438
|
}
|
|
4427
4439
|
|
|
4428
4440
|
/**
|
|
@@ -4457,7 +4469,7 @@ var chunk$1;
|
|
|
4457
4469
|
/** Memoized so the preload and the lazy mount share ONE chunk request. */
|
|
4458
4470
|
function loadChunk$1() {
|
|
4459
4471
|
var _chunk;
|
|
4460
|
-
return (_chunk = chunk$1) !== null && _chunk !== void 0 ? _chunk : chunk$1 = import('./DeckCutoutSubsystem-
|
|
4472
|
+
return (_chunk = chunk$1) !== null && _chunk !== void 0 ? _chunk : chunk$1 = import('./DeckCutoutSubsystem-34516143.js');
|
|
4461
4473
|
}
|
|
4462
4474
|
|
|
4463
4475
|
/**
|
|
@@ -4502,7 +4514,7 @@ var chunk;
|
|
|
4502
4514
|
/** Memoized so the preload and the lazy mount share ONE chunk request. */
|
|
4503
4515
|
function loadChunk() {
|
|
4504
4516
|
var _chunk;
|
|
4505
|
-
return (_chunk = chunk) !== null && _chunk !== void 0 ? _chunk : chunk = import('./SunLensflare-
|
|
4517
|
+
return (_chunk = chunk) !== null && _chunk !== void 0 ? _chunk : chunk = import('./SunLensflare-55ce48ee.js');
|
|
4506
4518
|
}
|
|
4507
4519
|
|
|
4508
4520
|
/**
|
|
@@ -8422,6 +8434,48 @@ function dropFailedMaps(mat) {
|
|
|
8422
8434
|
}
|
|
8423
8435
|
}
|
|
8424
8436
|
|
|
8437
|
+
/** A material's state before a fade started driving it. */
|
|
8438
|
+
|
|
8439
|
+
var FADE_ORIGINAL_KEY = 'rtvFadeOriginal';
|
|
8440
|
+
|
|
8441
|
+
/**
|
|
8442
|
+
* The 2D↔3D fade (`useMaterialFade`) drives `opacity` / `transparent` on every mesh material in
|
|
8443
|
+
* the scene, so while it runs a material's live values are transient. The pre-fade state travels
|
|
8444
|
+
* ON the material: `Material.clone()` copies `userData`, so a clone taken mid-fade — the deck
|
|
8445
|
+
* collar sampling the deck, a caustic-receiver patch of a shared article material — carries the
|
|
8446
|
+
* state it has to return to instead of freezing the faded values as its own.
|
|
8447
|
+
*/
|
|
8448
|
+
function stampFadeOriginal(mat, original) {
|
|
8449
|
+
mat.userData[FADE_ORIGINAL_KEY] = {
|
|
8450
|
+
opacity: original.opacity,
|
|
8451
|
+
transparent: original.transparent
|
|
8452
|
+
};
|
|
8453
|
+
}
|
|
8454
|
+
function readFadeOriginal(mat) {
|
|
8455
|
+
var stamped = mat.userData[FADE_ORIGINAL_KEY];
|
|
8456
|
+
if (typeof (stamped === null || stamped === void 0 ? void 0 : stamped.opacity) !== 'number' || typeof (stamped === null || stamped === void 0 ? void 0 : stamped.transparent) !== 'boolean') return null;
|
|
8457
|
+
return {
|
|
8458
|
+
opacity: stamped.opacity,
|
|
8459
|
+
transparent: stamped.transparent
|
|
8460
|
+
};
|
|
8461
|
+
}
|
|
8462
|
+
function clearFadeOriginal(mat) {
|
|
8463
|
+
delete mat.userData[FADE_ORIGINAL_KEY];
|
|
8464
|
+
}
|
|
8465
|
+
|
|
8466
|
+
/**
|
|
8467
|
+
* Put a fresh clone back into its source's pre-fade state. A clone that keeps the faded values is
|
|
8468
|
+
* restored TO them when the fade ends (they read as its original) — or, mounted after the fade
|
|
8469
|
+
* already ended, is never restored at all.
|
|
8470
|
+
*/
|
|
8471
|
+
function adoptPristineFadeState(mat) {
|
|
8472
|
+
var original = readFadeOriginal(mat);
|
|
8473
|
+
if (!original) return;
|
|
8474
|
+
mat.opacity = original.opacity;
|
|
8475
|
+
mat.transparent = original.transparent;
|
|
8476
|
+
clearFadeOriginal(mat);
|
|
8477
|
+
}
|
|
8478
|
+
|
|
8425
8479
|
function _createForOfIteratorHelper$t(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray$t(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
|
|
8426
8480
|
function _unsupportedIterableToArray$t(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray$t(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray$t(r, a) : void 0; } }
|
|
8427
8481
|
function _arrayLikeToArray$t(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
@@ -8512,6 +8566,8 @@ var FRAGMENT_OUTPUT_REPLACEMENT = /* glsl */"\n #ifdef OPAQUE\n diffuseColor
|
|
|
8512
8566
|
function patchMaterialAsCausticReceiver(source, uniforms) {
|
|
8513
8567
|
var _userData;
|
|
8514
8568
|
var patched = source.clone();
|
|
8569
|
+
// A shared source can be mid-fade, or left faded by a switch to 2D, when the receiver is patched.
|
|
8570
|
+
adoptPristineFadeState(patched);
|
|
8515
8571
|
|
|
8516
8572
|
// One uniform set per receiver material, seeded from the singleton;
|
|
8517
8573
|
// `refreshCausticReceiverUniforms` keeps them current.
|
|
@@ -13907,10 +13963,16 @@ function useMaterialFade() {
|
|
|
13907
13963
|
var mats = Array.isArray(mesh.material) ? mesh.material : [mesh.material];
|
|
13908
13964
|
mats.forEach(function (mat) {
|
|
13909
13965
|
if (!originals.has(mat)) {
|
|
13910
|
-
|
|
13966
|
+
var _readFadeOriginal;
|
|
13967
|
+
// A material can enter the fade already stamped: a clone of a fading material
|
|
13968
|
+
// (`Material.clone()` copies `userData`) or a cached material an earlier fade left
|
|
13969
|
+
// faded. Its live values are transient then — the stamp is the state to return to.
|
|
13970
|
+
var original = (_readFadeOriginal = readFadeOriginal(mat)) !== null && _readFadeOriginal !== void 0 ? _readFadeOriginal : {
|
|
13911
13971
|
opacity: mat.opacity,
|
|
13912
13972
|
transparent: mat.transparent
|
|
13913
|
-
}
|
|
13973
|
+
};
|
|
13974
|
+
originals.set(mat, original);
|
|
13975
|
+
stampFadeOriginal(mat, original);
|
|
13914
13976
|
// Only the `transparent` flip changes the compiled program — recompile once when a
|
|
13915
13977
|
// material enters the fade, not on every per-frame opacity write.
|
|
13916
13978
|
mat.transparent = true;
|
|
@@ -13929,6 +13991,7 @@ function useMaterialFade() {
|
|
|
13929
13991
|
mat.transparent = orig.transparent;
|
|
13930
13992
|
mat.needsUpdate = true;
|
|
13931
13993
|
}
|
|
13994
|
+
clearFadeOriginal(mat);
|
|
13932
13995
|
});
|
|
13933
13996
|
originals.clear();
|
|
13934
13997
|
}, []);
|
|
@@ -22119,7 +22182,8 @@ var LOG$5 = getLogger('RealTimeViewer', 'FrameloopVisibility');
|
|
|
22119
22182
|
* visibility (pause when invisible) and the profile's `maxFps` cap.
|
|
22120
22183
|
*
|
|
22121
22184
|
* Visibility toggles `frameloop` between the env-resolved value and `'never'`
|
|
22122
|
-
* on tab hide / window blur
|
|
22185
|
+
* on tab hide / window blur, and while the host's `stopRender` holds
|
|
22186
|
+
* (`renderStopped`).
|
|
22123
22187
|
*
|
|
22124
22188
|
* The FPS cap is gated at the renderer level, not via `frameloop` — we wrap
|
|
22125
22189
|
* `gl.render` and throttle only the final present:
|
|
@@ -22266,9 +22330,14 @@ function useFrameloopVisibility() {
|
|
|
22266
22330
|
var active = !hidden && focused;
|
|
22267
22331
|
var _useRTVStore$getState = useRTVStore$1.getState(),
|
|
22268
22332
|
isCapturing = _useRTVStore$getState.isCapturing,
|
|
22269
|
-
glContextLost = _useRTVStore$getState.glContextLost
|
|
22270
|
-
|
|
22271
|
-
|
|
22333
|
+
glContextLost = _useRTVStore$getState.glContextLost,
|
|
22334
|
+
renderStopped = _useRTVStore$getState.renderStopped,
|
|
22335
|
+
isSceneLoading = _useRTVStore$getState.isSceneLoading;
|
|
22336
|
+
// A host-stopped render pauses the loop, except while a scene load is in flight: the boot
|
|
22337
|
+
// gates end from `useFrame` (environment GLB placement), so a viewer covered mid-boot would
|
|
22338
|
+
// otherwise hold the loading overlay until it is shown again. A capture keeps rendering
|
|
22339
|
+
// regardless of visibility. A lost context overrides everything.
|
|
22340
|
+
var shouldRun = (active && (!renderStopped || isSceneLoading) || isCapturing) && !glContextLost;
|
|
22272
22341
|
var next = shouldRun ? envFrameloop : 'never';
|
|
22273
22342
|
if (next === lastApplied) return;
|
|
22274
22343
|
lastApplied = next;
|
|
@@ -22281,7 +22350,8 @@ function useFrameloopVisibility() {
|
|
|
22281
22350
|
hidden: hidden,
|
|
22282
22351
|
focused: focused,
|
|
22283
22352
|
isCapturing: isCapturing,
|
|
22284
|
-
glContextLost: glContextLost
|
|
22353
|
+
glContextLost: glContextLost,
|
|
22354
|
+
renderStopped: renderStopped
|
|
22285
22355
|
});
|
|
22286
22356
|
state.setFrameloop(next);
|
|
22287
22357
|
if (next === 'demand') state.invalidate();
|
|
@@ -22321,6 +22391,11 @@ function useFrameloopVisibility() {
|
|
|
22321
22391
|
}, function () {
|
|
22322
22392
|
return apply('glContextLost-change');
|
|
22323
22393
|
});
|
|
22394
|
+
var unsubRenderStopped = useRTVStore$1.subscribe(function (s) {
|
|
22395
|
+
return "".concat(s.renderStopped, "|").concat(s.isSceneLoading);
|
|
22396
|
+
}, function () {
|
|
22397
|
+
return apply('renderStopped-change');
|
|
22398
|
+
});
|
|
22324
22399
|
return function () {
|
|
22325
22400
|
document.removeEventListener('visibilitychange', onVis);
|
|
22326
22401
|
window.removeEventListener('blur', onBlur);
|
|
@@ -22330,6 +22405,7 @@ function useFrameloopVisibility() {
|
|
|
22330
22405
|
window.clearInterval(pollId);
|
|
22331
22406
|
unsubCapturing();
|
|
22332
22407
|
unsubContextLost();
|
|
22408
|
+
unsubRenderStopped();
|
|
22333
22409
|
uninstallCap();
|
|
22334
22410
|
// Don't force `'always'` on teardown — the next mount or the next
|
|
22335
22411
|
// env change will set the correct value, and slamming `'always'`
|
|
@@ -22686,17 +22762,22 @@ function SceneRenderer() {
|
|
|
22686
22762
|
window.addEventListener('pagehide', onPageHide, {
|
|
22687
22763
|
once: true
|
|
22688
22764
|
});
|
|
22689
|
-
|
|
22765
|
+
var cleanup = function cleanup() {
|
|
22690
22766
|
for (var _i = 0, _auditTimers = auditTimers; _i < _auditTimers.length; _i++) {
|
|
22691
22767
|
var timer = _auditTimers[_i];
|
|
22692
22768
|
window.clearTimeout(timer);
|
|
22693
22769
|
}
|
|
22694
|
-
//
|
|
22770
|
+
// Neither this canvas' deadline nor its listeners may outlive it: R3F force-loses the context
|
|
22771
|
+
// ~500 ms after the Canvas unmounts, and a listener still attached would flag that teardown as
|
|
22772
|
+
// a device loss — pausing the successor canvas and tripping the breaker 12 s later.
|
|
22695
22773
|
window.clearTimeout(restoreDeadline);
|
|
22774
|
+
canvas.removeEventListener('webglcontextlost', onContextLost, false);
|
|
22775
|
+
canvas.removeEventListener('webglcontextrestored', onContextRestored, false);
|
|
22696
22776
|
window.removeEventListener('pagehide', onPageHide);
|
|
22697
22777
|
};
|
|
22778
|
+
canvasCleanupRef.current = cleanup;
|
|
22698
22779
|
var restoreDeadline = 0;
|
|
22699
|
-
|
|
22780
|
+
var onContextLost = function onContextLost(event) {
|
|
22700
22781
|
event.preventDefault();
|
|
22701
22782
|
CONTEXT_LOG.warn('WebGL context lost — preventing default to allow restore');
|
|
22702
22783
|
// Pause the frameloop (see `useFrameloopVisibility`): rendering against the dead context
|
|
@@ -22709,8 +22790,8 @@ function SceneRenderer() {
|
|
|
22709
22790
|
restoreDeadline = window.setTimeout(function () {
|
|
22710
22791
|
if (useRTVStore$1.getState().glContextLost) useRTVStore$1.getState().tripContextLossBreaker('no restore within 12s');
|
|
22711
22792
|
}, 12000);
|
|
22712
|
-
}
|
|
22713
|
-
|
|
22793
|
+
};
|
|
22794
|
+
var onContextRestored = function onContextRestored() {
|
|
22714
22795
|
window.clearTimeout(restoreDeadline);
|
|
22715
22796
|
CONTEXT_LOG.warn('WebGL context restored — rebuilding render-target-backed resources');
|
|
22716
22797
|
useRTVStore$1.getState().logGLContextEvent('context restored — rebuilding');
|
|
@@ -22728,13 +22809,18 @@ function SceneRenderer() {
|
|
|
22728
22809
|
evictEquirectMasters();
|
|
22729
22810
|
evictGLTFCache();
|
|
22730
22811
|
evictEnvironmentGLBs();
|
|
22812
|
+
// Tear this canvas down before the swap: R3F force-loses its context ~500 ms after the unmount,
|
|
22813
|
+
// and the successor's onCreated (which also runs this) waits for a debounced size measurement first.
|
|
22814
|
+
cleanup();
|
|
22731
22815
|
useRTVStore$1.getState().bumpGLGeneration();
|
|
22732
22816
|
// Shrink the outgoing canvas once React swapped it out.
|
|
22733
22817
|
window.setTimeout(function () {
|
|
22734
22818
|
canvas.width = 1;
|
|
22735
22819
|
canvas.height = 1;
|
|
22736
22820
|
}, 0);
|
|
22737
|
-
}
|
|
22821
|
+
};
|
|
22822
|
+
canvas.addEventListener('webglcontextlost', onContextLost, false);
|
|
22823
|
+
canvas.addEventListener('webglcontextrestored', onContextRestored, false);
|
|
22738
22824
|
}, []);
|
|
22739
22825
|
var _useRTVAnalyzerCompon = useRTVAnalyzerComponents(),
|
|
22740
22826
|
DebugPanel = _useRTVAnalyzerCompon.DebugPanel,
|
|
@@ -23178,17 +23264,22 @@ function SceneLoadingDivaBridge() {
|
|
|
23178
23264
|
|
|
23179
23265
|
/**
|
|
23180
23266
|
* Hides the whole viewer (the canvas + everything it renders) while the scene
|
|
23181
|
-
* loads, so the user never sees a half-built scene pop in
|
|
23182
|
-
*
|
|
23183
|
-
*
|
|
23267
|
+
* loads, so the user never sees a half-built scene pop in, and while the host
|
|
23268
|
+
* has stopped rendering (`stopRender` → `renderStopped`). Uses `visibility`
|
|
23269
|
+
* (not unmount / `display:none`) so the canvas keeps its size and its context:
|
|
23270
|
+
* an in-flight GLB finishes decoding + fires `endSceneLoad`, which reveals it
|
|
23271
|
+
* in place, and a paused viewer resumes without a reboot.
|
|
23184
23272
|
*/
|
|
23185
23273
|
function SceneVisibilityGate(_ref) {
|
|
23186
23274
|
var children = _ref.children;
|
|
23187
23275
|
var isSceneLoading = useRTVStore$1(function (s) {
|
|
23188
23276
|
return s.isSceneLoading;
|
|
23189
23277
|
});
|
|
23278
|
+
var renderStopped = useRTVStore$1(function (s) {
|
|
23279
|
+
return s.renderStopped;
|
|
23280
|
+
});
|
|
23190
23281
|
return /*#__PURE__*/jsx("div", {
|
|
23191
|
-
className: isSceneLoading ? "".concat(gate, " ").concat(hidden) : gate,
|
|
23282
|
+
className: isSceneLoading || renderStopped ? "".concat(gate, " ").concat(hidden) : gate,
|
|
23192
23283
|
children: children
|
|
23193
23284
|
});
|
|
23194
23285
|
}
|
|
@@ -23380,21 +23471,43 @@ function useAssembledScene(_ref) {
|
|
|
23380
23471
|
return null;
|
|
23381
23472
|
}
|
|
23382
23473
|
}, [hqRenderScriptProp]);
|
|
23474
|
+
|
|
23475
|
+
// Scenes are compared by content, not by script string: the host re-emits the script for every
|
|
23476
|
+
// render request (a different `_id`, render size or camera per request), and a new `ParsedScene`
|
|
23477
|
+
// object alone re-runs every scene consumer — article-version bump, BVH, shadow rebuild, deck
|
|
23478
|
+
// re-measure and collar rebuild — for a scene that did not change.
|
|
23479
|
+
var lastParsedRef = useRef(null);
|
|
23383
23480
|
var parsed = useMemo(function () {
|
|
23481
|
+
var _lastParsedRef$curren;
|
|
23384
23482
|
if (!externalHqs) return null;
|
|
23385
23483
|
var parseStartedAt = bootClockMs();
|
|
23484
|
+
var scene;
|
|
23485
|
+
// The parse alone is guarded: nothing below may turn a scene that parsed fine into a blank viewer.
|
|
23386
23486
|
try {
|
|
23387
|
-
|
|
23388
|
-
bootPhase('parse done', {
|
|
23389
|
-
ms: Math.round(bootClockMs() - parseStartedAt),
|
|
23390
|
-
geoAssets: scene.geoAssets.length,
|
|
23391
|
-
matAssets: scene.matAssets.length
|
|
23392
|
-
});
|
|
23393
|
-
return scene;
|
|
23487
|
+
scene = parseRenderScript(externalHqs, config.archiveBaseUrl);
|
|
23394
23488
|
} catch (err) {
|
|
23395
23489
|
LOG$2.error(err instanceof Error ? err : new Error(String(err)));
|
|
23396
23490
|
return null;
|
|
23397
23491
|
}
|
|
23492
|
+
// A digest, not the serialized scene: the full text of a pool scene would sit in this ref for
|
|
23493
|
+
// the page's lifetime.
|
|
23494
|
+
var signature = hashString(JSON.stringify(scene));
|
|
23495
|
+
if (((_lastParsedRef$curren = lastParsedRef.current) === null || _lastParsedRef$curren === void 0 ? void 0 : _lastParsedRef$curren.signature) === signature) {
|
|
23496
|
+
bootPhase('parse done (scene unchanged)', {
|
|
23497
|
+
ms: Math.round(bootClockMs() - parseStartedAt)
|
|
23498
|
+
});
|
|
23499
|
+
return lastParsedRef.current.scene;
|
|
23500
|
+
}
|
|
23501
|
+
lastParsedRef.current = {
|
|
23502
|
+
scene: scene,
|
|
23503
|
+
signature: signature
|
|
23504
|
+
};
|
|
23505
|
+
bootPhase('parse done', {
|
|
23506
|
+
ms: Math.round(bootClockMs() - parseStartedAt),
|
|
23507
|
+
geoAssets: scene.geoAssets.length,
|
|
23508
|
+
matAssets: scene.matAssets.length
|
|
23509
|
+
});
|
|
23510
|
+
return scene;
|
|
23398
23511
|
}, [externalHqs, config.archiveBaseUrl]);
|
|
23399
23512
|
|
|
23400
23513
|
// The first-article hold (see the id's doc). Begun before any reveal can happen (the seeded
|
|
@@ -23879,7 +23992,8 @@ function useHostPropsSync(_ref2) {
|
|
|
23879
23992
|
elementsInfo = _ref2.elementsInfo,
|
|
23880
23993
|
selectedElementId = _ref2.selectedElementId,
|
|
23881
23994
|
selectedAccessoryKey = _ref2.selectedAccessoryKey,
|
|
23882
|
-
callbacks = _ref2.callbacks
|
|
23995
|
+
callbacks = _ref2.callbacks,
|
|
23996
|
+
stopRender = _ref2.stopRender;
|
|
23883
23997
|
var setViewMode = useRTVStore$1(function (s) {
|
|
23884
23998
|
return s.setViewMode;
|
|
23885
23999
|
});
|
|
@@ -23916,6 +24030,9 @@ function useHostPropsSync(_ref2) {
|
|
|
23916
24030
|
var setShowDimensionLines = useRTVStore$1(function (s) {
|
|
23917
24031
|
return s.setShowDimensionLines;
|
|
23918
24032
|
});
|
|
24033
|
+
var setRenderStopped = useRTVStore$1(function (s) {
|
|
24034
|
+
return s.setRenderStopped;
|
|
24035
|
+
});
|
|
23919
24036
|
var sceneElementCount = useRTVStore$1(function (s) {
|
|
23920
24037
|
return s.elements.length;
|
|
23921
24038
|
});
|
|
@@ -23972,6 +24089,9 @@ function useHostPropsSync(_ref2) {
|
|
|
23972
24089
|
useEffect(function () {
|
|
23973
24090
|
setShowDimensionLines(!!showDimensionLines);
|
|
23974
24091
|
}, [setShowDimensionLines, showDimensionLines]);
|
|
24092
|
+
useEffect(function () {
|
|
24093
|
+
setRenderStopped(!!stopRender);
|
|
24094
|
+
}, [setRenderStopped, stopRender]);
|
|
23975
24095
|
useEffect(function () {
|
|
23976
24096
|
if (focusElementId != null) {
|
|
23977
24097
|
focusElementById(focusElementId);
|
|
@@ -24001,7 +24121,6 @@ function useHostPropsSync(_ref2) {
|
|
|
24001
24121
|
var RealTimeRendererNext = /*#__PURE__*/memo(function (props) {
|
|
24002
24122
|
var scene2d = props.scene2d,
|
|
24003
24123
|
viewMode = props.viewMode,
|
|
24004
|
-
stopRender = props.stopRender,
|
|
24005
24124
|
analyzerComponents = props.analyzerComponents;
|
|
24006
24125
|
var unsupported = useRTVStore$1(function (s) {
|
|
24007
24126
|
return s.unsupported;
|
|
@@ -24024,7 +24143,7 @@ var RealTimeRendererNext = /*#__PURE__*/memo(function (props) {
|
|
|
24024
24143
|
// must not unmount (killing the WebGL context) meanwhile — the visibility gate keeps it hidden
|
|
24025
24144
|
// until the boot loads resolve.
|
|
24026
24145
|
var hasAnything = hasStoreScene || parsed || scene2d || viewMode === '2d';
|
|
24027
|
-
if (
|
|
24146
|
+
if (!hasAnything) return null;
|
|
24028
24147
|
|
|
24029
24148
|
// Tier-0 fallback: render nothing rather than a broken WebGL context.
|
|
24030
24149
|
if (unsupported) return null;
|
|
@@ -25154,4 +25273,4 @@ var internals = /*#__PURE__*/Object.freeze({
|
|
|
25154
25273
|
mergePresetBundle: mergePresetBundle
|
|
25155
25274
|
});
|
|
25156
25275
|
|
|
25157
|
-
export { DECK_COLLAR_LOAD_ID as D, ENVIRONMENT_CONFIG as E, FRAME_ORDER as F, RealTimeRendererNext as R, WHITE_ROOM_PRESET as W, useRTVStore$1 as a, bootPhase as b,
|
|
25276
|
+
export { DECK_COLLAR_LOAD_ID as D, ENVIRONMENT_CONFIG as E, FRAME_ORDER as F, RealTimeRendererNext as R, WHITE_ROOM_PRESET as W, useRTVStore$1 as a, bootPhase as b, adoptPristineFadeState as c, waterUniforms as d, disableWaterUniforms as e, sunAnglesToDirection as f, flushPendingBVH as g, collectCollisionTargets as h, internals as i, emitConfig as j, lightingSunTowardDirection as l, parseElementKey as p, setCausticReceiversSuspended as s, useStableEnvSlice as u, withRenderTarget as w };
|
package/build/esm/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { E as ENVIRONMENT_CONFIG, W as WHITE_ROOM_PRESET, R as default,
|
|
1
|
+
export { E as ENVIRONMENT_CONFIG, W as WHITE_ROOM_PRESET, R as default, j as emitConfig, i as internals, a as useRTVStore } from './index-8c31a811.js';
|
|
2
2
|
import 'react';
|
|
3
3
|
import '@react-three/fiber';
|
|
4
4
|
import 'three';
|
|
@@ -19,6 +19,11 @@ export interface RTVNextProps {
|
|
|
19
19
|
scene2d?: RTVScene2D;
|
|
20
20
|
viewMode?: '3d' | '2d';
|
|
21
21
|
config: RTVConfig;
|
|
22
|
+
/**
|
|
23
|
+
* Pauses the viewer instead of unmounting it: the frameloop stops and the stage is hidden, while
|
|
24
|
+
* the assembled scene, every cache and the WebGL context stay alive for an instant return. A host
|
|
25
|
+
* that does not want the viewer to boot at all simply does not mount it.
|
|
26
|
+
*/
|
|
22
27
|
stopRender?: boolean;
|
|
23
28
|
callbacks?: RTVCallbacks;
|
|
24
29
|
analyzerComponents?: RTVAnalyzerComponentMap;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RealTimeRendererNext.d.ts","sourceRoot":"","sources":["../../../../src/RealTimeRendererNext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAe,MAAM,OAAO,CAAC;AAGpC,OAAO,EAAe,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AACzE,OAAO,EAAuB,KAAK,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAIzF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE5D,iGAAiG;AACjG,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,WAAW,CAAC,EAAE,cAAc,CAAC;IAC7B,mGAAmG;IACnG,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,SAAS,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,YAAY,CAAC;IACzB,kBAAkB,CAAC,EAAE,uBAAuB,CAAC;IAC7C,6FAA6F;IAC7F,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,2FAA2F;IAC3F,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAC/C,4FAA4F;IAC5F,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,gGAAgG;IAChG,iBAAiB,CAAC,EAAE,OAAO,wBAAwB,EAAE,iBAAiB,EAAE,CAAC;IACzE,6FAA6F;IAC7F,oBAAoB,CAAC,EAAE,OAAO,wBAAwB,EAAE,oBAAoB,EAAE,CAAC;IAC/E;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,+FAA+F;IAC/F,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,qGAAqG;IACrG,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,yFAAyF;IACzF,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,QAAA,MAAM,oBAAoB,oCAAgB,YAAY,8BAoCpD,CAAC;AAEH,eAAe,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"RealTimeRendererNext.d.ts","sourceRoot":"","sources":["../../../../src/RealTimeRendererNext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAe,MAAM,OAAO,CAAC;AAGpC,OAAO,EAAe,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AACzE,OAAO,EAAuB,KAAK,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAIzF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE5D,iGAAiG;AACjG,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,WAAW,CAAC,EAAE,cAAc,CAAC;IAC7B,mGAAmG;IACnG,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,SAAS,CAAC;IAClB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,YAAY,CAAC;IACzB,kBAAkB,CAAC,EAAE,uBAAuB,CAAC;IAC7C,6FAA6F;IAC7F,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,2FAA2F;IAC3F,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAC/C,4FAA4F;IAC5F,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,gGAAgG;IAChG,iBAAiB,CAAC,EAAE,OAAO,wBAAwB,EAAE,iBAAiB,EAAE,CAAC;IACzE,6FAA6F;IAC7F,oBAAoB,CAAC,EAAE,OAAO,wBAAwB,EAAE,oBAAoB,EAAE,CAAC;IAC/E;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,+FAA+F;IAC/F,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,qGAAqG;IACrG,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,yFAAyF;IACzF,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,QAAA,MAAM,oBAAoB,oCAAgB,YAAY,8BAoCpD,CAAC;AAEH,eAAe,oBAAoB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SceneRenderer.d.ts","sourceRoot":"","sources":["../../../../../src/core/SceneRenderer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA6E,MAAM,OAAO,CAAC;AA4ClG,wBAAgB,aAAa,
|
|
1
|
+
{"version":3,"file":"SceneRenderer.d.ts","sourceRoot":"","sources":["../../../../../src/core/SceneRenderer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA6E,MAAM,OAAO,CAAC;AA4ClG,wBAAgB,aAAa,sBAmQ5B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMaterialFade.d.ts","sourceRoot":"","sources":["../../../../../../src/core/camera/useMaterialFade.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useMaterialFade.d.ts","sourceRoot":"","sources":["../../../../../../src/core/camera/useMaterialFade.ts"],"names":[],"mappings":"AAMA,wBAAgB,eAAe;kCAKjB,MAAM;;EA0CnB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collectDeckTriangles.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/environment/deckCutout/collectDeckTriangles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmD,KAAK,QAAQ,EAAE,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjH,OAAO,EAA2D,KAAK,QAAQ,EAAE,KAAK,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"collectDeckTriangles.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/environment/deckCutout/collectDeckTriangles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmD,KAAK,QAAQ,EAAE,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjH,OAAO,EAA2D,KAAK,QAAQ,EAAE,KAAK,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAK/I;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,QAAQ,CAAC;AAOzC,8EAA8E;AAC9E,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,kGAAkG;IAClG,aAAa,EAAE,MAAM,CAAC;IACtB,0HAA0H;IAC1H,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC1B,yGAAyG;IACzG,SAAS,EAAE,YAAY,GAAG,IAAI,CAAC;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,aAAa,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACxC,iGAAiG;IACjG,aAAa,EAAE,MAAM,CAAC;IACtB,2FAA2F;IAC3F,KAAK,EAAE,QAAQ,GAAG,IAAI,CAAC;IACvB;;;;OAIG;IACH,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAC3E;AAED,yFAAyF;AACzF,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,CAOzE;AAoBD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,GAAG,QAAQ,EAAE,GAAG,MAAM,CAI5E;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,IAAI,EAAE,EACd,SAAS,EAAE,IAAI,EACf,aAAa,EAAE,MAAM,GACpB;IACD,SAAS,EAAE,YAAY,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACpE,GAAG,IAAI,CAoEP;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG;IAAE,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAA;CAAE,CAyB9H;AAED,oIAAoI;AACpI,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,GAAG,MAAM,CAElE;AAED,mEAAmE;AACnE,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,OAAO,GAAG,MAAM,EAAE,CAoB3F"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Material } from 'three';
|
|
2
|
+
/** A material's state before a fade started driving it. */
|
|
3
|
+
export interface MaterialFadeOriginal {
|
|
4
|
+
opacity: number;
|
|
5
|
+
transparent: boolean;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* The 2D↔3D fade (`useMaterialFade`) drives `opacity` / `transparent` on every mesh material in
|
|
9
|
+
* the scene, so while it runs a material's live values are transient. The pre-fade state travels
|
|
10
|
+
* ON the material: `Material.clone()` copies `userData`, so a clone taken mid-fade — the deck
|
|
11
|
+
* collar sampling the deck, a caustic-receiver patch of a shared article material — carries the
|
|
12
|
+
* state it has to return to instead of freezing the faded values as its own.
|
|
13
|
+
*/
|
|
14
|
+
export declare function stampFadeOriginal(mat: Material, original: MaterialFadeOriginal): void;
|
|
15
|
+
export declare function readFadeOriginal(mat: Material): MaterialFadeOriginal | null;
|
|
16
|
+
export declare function clearFadeOriginal(mat: Material): void;
|
|
17
|
+
/**
|
|
18
|
+
* Put a fresh clone back into its source's pre-fade state. A clone that keeps the faded values is
|
|
19
|
+
* restored TO them when the fade ends (they read as its original) — or, mounted after the fade
|
|
20
|
+
* already ended, is never restored at all.
|
|
21
|
+
*/
|
|
22
|
+
export declare function adoptPristineFadeState(mat: Material): void;
|
|
23
|
+
//# sourceMappingURL=fadeState.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fadeState.d.ts","sourceRoot":"","sources":["../../../../../../src/core/materials/fadeState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEtC,2DAA2D;AAC3D,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;CACtB;AAID;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,oBAAoB,GAAG,IAAI,CAErF;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,QAAQ,GAAG,oBAAoB,GAAG,IAAI,CAI3E;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI,CAErD;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI,CAM1D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fadeState.test.d.ts","sourceRoot":"","sources":["../../../../../../src/core/materials/fadeState.test.ts"],"names":[],"mappings":""}
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* visibility (pause when invisible) and the profile's `maxFps` cap.
|
|
4
4
|
*
|
|
5
5
|
* Visibility toggles `frameloop` between the env-resolved value and `'never'`
|
|
6
|
-
* on tab hide / window blur
|
|
6
|
+
* on tab hide / window blur, and while the host's `stopRender` holds
|
|
7
|
+
* (`renderStopped`).
|
|
7
8
|
*
|
|
8
9
|
* The FPS cap is gated at the renderer level, not via `frameloop` — we wrap
|
|
9
10
|
* `gl.render` and throttle only the final present:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFrameloopVisibility.d.ts","sourceRoot":"","sources":["../../../../../src/core/useFrameloopVisibility.tsx"],"names":[],"mappings":"AAQA
|
|
1
|
+
{"version":3,"file":"useFrameloopVisibility.d.ts","sourceRoot":"","sources":["../../../../../src/core/useFrameloopVisibility.tsx"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,sBAAsB,SAmMrC;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,SAG5C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CausticReceiver.d.ts","sourceRoot":"","sources":["../../../../../../src/core/water/CausticReceiver.ts"],"names":[],"mappings":"AA4BA,OAAO,EAAE,oBAAoB,EAAoB,MAAM,OAAO,CAAC;AAE/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"CausticReceiver.d.ts","sourceRoot":"","sources":["../../../../../../src/core/water/CausticReceiver.ts"],"names":[],"mappings":"AA4BA,OAAO,EAAE,oBAAoB,EAAoB,MAAM,OAAO,CAAC;AAE/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAKrD;;;;;GAKG;AACH,QAAA,MAAM,qBAAqB,gCAAgC,CAAC;AAE5D;;;;GAIG;AACH,KAAK,uBAAuB,GAAG,oBAAoB,GAAG;IACpD,CAAC,qBAAqB,CAAC,CAAC,EAAE,IAAI,CAAC;CAChC,CAAC;AAUF;;;;;;;GAOG;AACH,wBAAgB,4BAA4B,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CAErE;AAsKD;;;;;;;;GAQG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,oBAAoB,EAAE,QAAQ,EAAE,aAAa,GAAG,uBAAuB,CAsE7H;AAED;;;;;GAKG;AACH,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,oBAAoB,EAAE,QAAQ,EAAE,aAAa,GAAG,IAAI,CAwC5G;AAwBD,mGAAmG;AACnG,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,oBAAoB,EAAE,QAAQ,EAAE,aAAa,GAAG,oBAAoB,CAQlH;AAED,gGAAgG;AAChG,wBAAgB,yBAAyB,IAAI,IAAI,CAGhD;AAED,kGAAkG;AAClG,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI,CAQzE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAssembledScene.d.ts","sourceRoot":"","sources":["../../../../../src/hooks/useAssembledScene.ts"],"names":[],"mappings":"AAEA,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"useAssembledScene.d.ts","sourceRoot":"","sources":["../../../../../src/hooks/useAssembledScene.ts"],"names":[],"mappings":"AAEA,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAMlF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAsB5D,KAAK,mBAAmB,GAAG,IAAI,CAAC,YAAY,EAAE,gBAAgB,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,CAAC,CAAC;AAEpG;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,cAAc,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,mBAAmB,GAAG,WAAW,GAAG,IAAI,CAuG5I"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { RTVNextProps } from '../RealTimeRendererNext';
|
|
2
2
|
type HostConfigProps = Pick<RTVNextProps, 'config' | 'callbacks'>;
|
|
3
|
-
type HostUiProps = Pick<RTVNextProps, 'viewMode' | 'plannerMode' | 'freePlacesOnGrids' | 'plannedPlacesOnGrids' | 'catalogInfo' | 'armedAccessoryCodex' | 'draggedAccessoryCodex' | 'showDimensionLines' | 'focusElementId' | 'elementsInfo' | 'selectedElementId' | 'selectedAccessoryKey' | 'callbacks'>;
|
|
3
|
+
type HostUiProps = Pick<RTVNextProps, 'viewMode' | 'plannerMode' | 'freePlacesOnGrids' | 'plannedPlacesOnGrids' | 'catalogInfo' | 'armedAccessoryCodex' | 'draggedAccessoryCodex' | 'showDimensionLines' | 'focusElementId' | 'elementsInfo' | 'selectedElementId' | 'selectedAccessoryKey' | 'callbacks' | 'stopRender'>;
|
|
4
4
|
/**
|
|
5
5
|
* Installs the host's config + callbacks and kicks off device-tier detection.
|
|
6
6
|
*
|
|
@@ -15,6 +15,6 @@ export declare function useHostConfigSync({ config, callbacks }: HostConfigProps
|
|
|
15
15
|
* controlled-selection setters act on the scene that landed in the store
|
|
16
16
|
* earlier in the same flush.
|
|
17
17
|
*/
|
|
18
|
-
export declare function useHostPropsSync({ viewMode, plannerMode, freePlacesOnGrids, plannedPlacesOnGrids, catalogInfo, armedAccessoryCodex, draggedAccessoryCodex, showDimensionLines, focusElementId, elementsInfo, selectedElementId, selectedAccessoryKey, callbacks, }: HostUiProps): void;
|
|
18
|
+
export declare function useHostPropsSync({ viewMode, plannerMode, freePlacesOnGrids, plannedPlacesOnGrids, catalogInfo, armedAccessoryCodex, draggedAccessoryCodex, showDimensionLines, focusElementId, elementsInfo, selectedElementId, selectedAccessoryKey, callbacks, stopRender, }: HostUiProps): void;
|
|
19
19
|
export {};
|
|
20
20
|
//# sourceMappingURL=useHostPropsSync.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useHostPropsSync.d.ts","sourceRoot":"","sources":["../../../../../src/hooks/useHostPropsSync.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAK5D,KAAK,eAAe,GAAG,IAAI,CAAC,YAAY,EAAE,QAAQ,GAAG,WAAW,CAAC,CAAC;AA2BlE,KAAK,WAAW,GAAG,IAAI,CACrB,YAAY,EACV,UAAU,GACV,aAAa,GACb,mBAAmB,GACnB,sBAAsB,GACtB,aAAa,GACb,qBAAqB,GACrB,uBAAuB,GACvB,oBAAoB,GACpB,gBAAgB,GAChB,cAAc,GACd,mBAAmB,GACnB,sBAAsB,GACtB,WAAW,
|
|
1
|
+
{"version":3,"file":"useHostPropsSync.d.ts","sourceRoot":"","sources":["../../../../../src/hooks/useHostPropsSync.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAK5D,KAAK,eAAe,GAAG,IAAI,CAAC,YAAY,EAAE,QAAQ,GAAG,WAAW,CAAC,CAAC;AA2BlE,KAAK,WAAW,GAAG,IAAI,CACrB,YAAY,EACV,UAAU,GACV,aAAa,GACb,mBAAmB,GACnB,sBAAsB,GACtB,aAAa,GACb,qBAAqB,GACrB,uBAAuB,GACvB,oBAAoB,GACpB,gBAAgB,GAChB,cAAc,GACd,mBAAmB,GACnB,sBAAsB,GACtB,WAAW,GACX,YAAY,CACf,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,eAAe,QAsCvE;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,WAAW,EACX,iBAAiB,EACjB,oBAAoB,EACpB,WAAW,EACX,mBAAmB,EACnB,qBAAqB,EACrB,kBAAkB,EAClB,cAAc,EACd,YAAY,EACZ,iBAAiB,EACjB,oBAAoB,EACpB,SAAS,EACT,UAAU,GACX,EAAE,WAAW,QAiGb"}
|
|
@@ -8,9 +8,11 @@ import React, { type ReactNode } from 'react';
|
|
|
8
8
|
export declare function SceneLoadingDivaBridge(): null;
|
|
9
9
|
/**
|
|
10
10
|
* Hides the whole viewer (the canvas + everything it renders) while the scene
|
|
11
|
-
* loads, so the user never sees a half-built scene pop in
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* loads, so the user never sees a half-built scene pop in, and while the host
|
|
12
|
+
* has stopped rendering (`stopRender` → `renderStopped`). Uses `visibility`
|
|
13
|
+
* (not unmount / `display:none`) so the canvas keeps its size and its context:
|
|
14
|
+
* an in-flight GLB finishes decoding + fires `endSceneLoad`, which reveals it
|
|
15
|
+
* in place, and a paused viewer resumes without a reboot.
|
|
14
16
|
*/
|
|
15
17
|
export declare function SceneVisibilityGate({ children }: {
|
|
16
18
|
children: ReactNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadingGates.d.ts","sourceRoot":"","sources":["../../../../src/loadingGates.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAqB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAOjE;;;;;GAKG;AACH,wBAAgB,sBAAsB,SA6BrC;AAED
|
|
1
|
+
{"version":3,"file":"loadingGates.d.ts","sourceRoot":"","sources":["../../../../src/loadingGates.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAqB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAOjE;;;;;GAKG;AACH,wBAAgB,sBAAsB,SA6BrC;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,qBAIxE;AAED;gFACgF;AAChF,qBAAa,oBAAqB,SAAQ,KAAK,CAAC,SAAS,CAAC;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,EAAE;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,CAAC;IACrG,KAAK;;MAAqB;IAC1B,MAAM,CAAC,wBAAwB;;;IAG/B,iBAAiB;IAGjB,MAAM;CAGP"}
|
|
@@ -16,6 +16,13 @@ export interface GLGenerationSlice {
|
|
|
16
16
|
/** True between context lost and restored — the frameloop controller pauses while set. */
|
|
17
17
|
glContextLost: boolean;
|
|
18
18
|
setGLContextLost: (lost: boolean) => void;
|
|
19
|
+
/**
|
|
20
|
+
* Host `stopRender`: the viewer stays mounted with its scene and WebGL context, the frameloop
|
|
21
|
+
* pauses (`useFrameloopVisibility`) and `SceneVisibilityGate` hides the stage. A capture or a
|
|
22
|
+
* scene load in flight still gets frames — both need them to finish, and someone waits on them.
|
|
23
|
+
*/
|
|
24
|
+
renderStopped: boolean;
|
|
25
|
+
setRenderStopped: (stopped: boolean) => void;
|
|
19
26
|
/** Breaker: repeated losses in a short window swap the viewer to the error page instead of remount-thrash. */
|
|
20
27
|
glContextLossLoop: boolean;
|
|
21
28
|
/** Called from the `webglcontextrestored` handler; trips {@link glContextLossLoop} on repeats. */
|