@ericchen1990/pano-view 3.3.0 → 3.4.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/README.md +30 -6
- package/README.zh-CN.md +9 -3
- package/dist/index.cjs +1267 -904
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +12 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.mjs +995 -632
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +6 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -3446,7 +3446,9 @@ function KeyboardControls({
|
|
|
3446
3446
|
return;
|
|
3447
3447
|
}
|
|
3448
3448
|
const previousTabIndex = element.getAttribute("tabindex");
|
|
3449
|
+
const previousOutline = element.style.outline;
|
|
3449
3450
|
element.tabIndex = 0;
|
|
3451
|
+
element.style.outline = "none";
|
|
3450
3452
|
const syncKeyboardActive = () => {
|
|
3451
3453
|
let continuous = false;
|
|
3452
3454
|
for (const action of pressedRef.current) {
|
|
@@ -3530,6 +3532,7 @@ function KeyboardControls({
|
|
|
3530
3532
|
} else {
|
|
3531
3533
|
element.setAttribute("tabindex", previousTabIndex);
|
|
3532
3534
|
}
|
|
3535
|
+
element.style.outline = previousOutline;
|
|
3533
3536
|
clearPressed();
|
|
3534
3537
|
};
|
|
3535
3538
|
}, [controlsRef, enabled, gl, keyMap]);
|
|
@@ -9700,7 +9703,7 @@ function usePanoViewer() {
|
|
|
9700
9703
|
|
|
9701
9704
|
// src/sphere-tile/sphere-tile.tsx
|
|
9702
9705
|
var import_fiber16 = require("@react-three/fiber");
|
|
9703
|
-
var
|
|
9706
|
+
var import_react40 = require("react");
|
|
9704
9707
|
var import_three14 = require("three");
|
|
9705
9708
|
|
|
9706
9709
|
// src/asset-url.ts
|
|
@@ -9968,6 +9971,27 @@ function PanoBasicMaterial({
|
|
|
9968
9971
|
);
|
|
9969
9972
|
}
|
|
9970
9973
|
|
|
9974
|
+
// src/scene-detail.tsx
|
|
9975
|
+
var import_react37 = require("react");
|
|
9976
|
+
var SceneDetailContext = (0, import_react37.createContext)(null);
|
|
9977
|
+
function useSceneDetailReporter() {
|
|
9978
|
+
return (0, import_react37.useContext)(SceneDetailContext);
|
|
9979
|
+
}
|
|
9980
|
+
function viewTilesAreDrawable(textures) {
|
|
9981
|
+
return textures.length > 0 && textures.every((texture) => texture != null);
|
|
9982
|
+
}
|
|
9983
|
+
function publishSceneDetail(reporter, lastToken, ready) {
|
|
9984
|
+
if (!reporter) {
|
|
9985
|
+
return;
|
|
9986
|
+
}
|
|
9987
|
+
const token = `${reporter.generation}:${ready ? 1 : 0}`;
|
|
9988
|
+
if (lastToken.current === token) {
|
|
9989
|
+
return;
|
|
9990
|
+
}
|
|
9991
|
+
lastToken.current = token;
|
|
9992
|
+
reporter.report(ready);
|
|
9993
|
+
}
|
|
9994
|
+
|
|
9971
9995
|
// src/tile/texture-manager.ts
|
|
9972
9996
|
var import_three11 = require("three");
|
|
9973
9997
|
var EMPTY_TEXTURE_SNAPSHOT = {
|
|
@@ -10195,9 +10219,9 @@ var TileTextureManager = class {
|
|
|
10195
10219
|
|
|
10196
10220
|
// src/tile/texture-manager-context.tsx
|
|
10197
10221
|
var import_fiber15 = require("@react-three/fiber");
|
|
10198
|
-
var
|
|
10222
|
+
var import_react38 = require("react");
|
|
10199
10223
|
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
10200
|
-
var TileTextureManagerContext = (0,
|
|
10224
|
+
var TileTextureManagerContext = (0, import_react38.createContext)(null);
|
|
10201
10225
|
function TileTextureManagerProvider({
|
|
10202
10226
|
children,
|
|
10203
10227
|
maxTextureMemoryMb = 128,
|
|
@@ -10205,7 +10229,7 @@ function TileTextureManagerProvider({
|
|
|
10205
10229
|
}) {
|
|
10206
10230
|
const gl = (0, import_fiber15.useThree)((state) => state.gl);
|
|
10207
10231
|
const anisotropy = gl.capabilities.getMaxAnisotropy();
|
|
10208
|
-
const manager = (0,
|
|
10232
|
+
const manager = (0, import_react38.useMemo)(
|
|
10209
10233
|
() => new TileTextureManager({
|
|
10210
10234
|
anisotropy,
|
|
10211
10235
|
maxBytes: Math.max(1, maxTextureMemoryMb) * 1024 * 1024,
|
|
@@ -10214,24 +10238,24 @@ function TileTextureManagerProvider({
|
|
|
10214
10238
|
}),
|
|
10215
10239
|
[anisotropy, maxConcurrentLoads, maxTextureMemoryMb]
|
|
10216
10240
|
);
|
|
10217
|
-
(0,
|
|
10241
|
+
(0, import_react38.useEffect)(() => {
|
|
10218
10242
|
manager.resume();
|
|
10219
10243
|
return () => manager.dispose();
|
|
10220
10244
|
}, [manager]);
|
|
10221
10245
|
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TileTextureManagerContext.Provider, { value: manager, children });
|
|
10222
10246
|
}
|
|
10223
10247
|
function useSharedTileTextureManager() {
|
|
10224
|
-
return (0,
|
|
10248
|
+
return (0, import_react38.useContext)(TileTextureManagerContext);
|
|
10225
10249
|
}
|
|
10226
10250
|
|
|
10227
10251
|
// src/tile/texture-hooks.ts
|
|
10228
|
-
var
|
|
10252
|
+
var import_react39 = require("react");
|
|
10229
10253
|
var import_three12 = require("three");
|
|
10230
10254
|
function usePreviewTexture(url, anisotropy, onError) {
|
|
10231
|
-
const [texture, setTexture] = (0,
|
|
10232
|
-
const onErrorRef = (0,
|
|
10255
|
+
const [texture, setTexture] = (0, import_react39.useState)(null);
|
|
10256
|
+
const onErrorRef = (0, import_react39.useRef)(onError);
|
|
10233
10257
|
onErrorRef.current = onError;
|
|
10234
|
-
(0,
|
|
10258
|
+
(0, import_react39.useEffect)(() => {
|
|
10235
10259
|
if (!url) {
|
|
10236
10260
|
setTexture(null);
|
|
10237
10261
|
return;
|
|
@@ -10268,7 +10292,7 @@ function usePreviewTexture(url, anisotropy, onError) {
|
|
|
10268
10292
|
active = false;
|
|
10269
10293
|
};
|
|
10270
10294
|
}, [anisotropy, url]);
|
|
10271
|
-
(0,
|
|
10295
|
+
(0, import_react39.useEffect)(
|
|
10272
10296
|
() => () => {
|
|
10273
10297
|
texture?.dispose();
|
|
10274
10298
|
},
|
|
@@ -10277,14 +10301,14 @@ function usePreviewTexture(url, anisotropy, onError) {
|
|
|
10277
10301
|
return texture;
|
|
10278
10302
|
}
|
|
10279
10303
|
function useManagedTexture(manager, key, url, address) {
|
|
10280
|
-
const [managedState, setManagedState] = (0,
|
|
10304
|
+
const [managedState, setManagedState] = (0, import_react39.useState)(() => ({
|
|
10281
10305
|
manager,
|
|
10282
10306
|
key,
|
|
10283
10307
|
url,
|
|
10284
10308
|
snapshot: manager.getSnapshot(key)
|
|
10285
10309
|
}));
|
|
10286
10310
|
const snapshot = managedState.manager === manager && managedState.key === key && managedState.url === url ? managedState.snapshot : manager.getSnapshot(key);
|
|
10287
|
-
(0,
|
|
10311
|
+
(0, import_react39.useEffect)(
|
|
10288
10312
|
() => manager.acquire(key, url, address, (nextSnapshot) => {
|
|
10289
10313
|
setManagedState({
|
|
10290
10314
|
manager,
|
|
@@ -10427,13 +10451,22 @@ function preferredSphereLevel(levels, height, dpr, verticalFov) {
|
|
|
10427
10451
|
|
|
10428
10452
|
// src/sphere-tile/sphere-tile.tsx
|
|
10429
10453
|
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
10454
|
+
function sphereTileViewShouldRefresh(input) {
|
|
10455
|
+
if (input.loadModeChanged || input.managerChanged) {
|
|
10456
|
+
return true;
|
|
10457
|
+
}
|
|
10458
|
+
if (input.elapsedMs < 100 || input.viewUnchanged) {
|
|
10459
|
+
return false;
|
|
10460
|
+
}
|
|
10461
|
+
return true;
|
|
10462
|
+
}
|
|
10430
10463
|
function SpherePatch({
|
|
10431
10464
|
address,
|
|
10432
10465
|
texture,
|
|
10433
10466
|
yawOffset,
|
|
10434
10467
|
preview = false
|
|
10435
10468
|
}) {
|
|
10436
|
-
const geometry = (0,
|
|
10469
|
+
const geometry = (0, import_react40.useMemo)(
|
|
10437
10470
|
() => sphereTileGeometry(
|
|
10438
10471
|
address,
|
|
10439
10472
|
yawOffset,
|
|
@@ -10441,7 +10474,7 @@ function SpherePatch({
|
|
|
10441
10474
|
),
|
|
10442
10475
|
[address, yawOffset, preview]
|
|
10443
10476
|
);
|
|
10444
|
-
(0,
|
|
10477
|
+
(0, import_react40.useEffect)(() => () => geometry.dispose(), [geometry]);
|
|
10445
10478
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
10446
10479
|
"mesh",
|
|
10447
10480
|
{
|
|
@@ -10460,7 +10493,7 @@ function SpherePatch({
|
|
|
10460
10493
|
}
|
|
10461
10494
|
);
|
|
10462
10495
|
}
|
|
10463
|
-
var ManagedPatch = (0,
|
|
10496
|
+
var ManagedPatch = (0, import_react40.memo)(function ManagedPatch2({
|
|
10464
10497
|
address,
|
|
10465
10498
|
manager,
|
|
10466
10499
|
resolveUrl,
|
|
@@ -10474,7 +10507,7 @@ var ManagedPatch = (0, import_react39.memo)(function ManagedPatch2({
|
|
|
10474
10507
|
url,
|
|
10475
10508
|
address
|
|
10476
10509
|
);
|
|
10477
|
-
(0,
|
|
10510
|
+
(0, import_react40.useEffect)(() => {
|
|
10478
10511
|
if (snapshot.texture) ready();
|
|
10479
10512
|
}, [snapshot.texture, ready]);
|
|
10480
10513
|
return snapshot.texture ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
@@ -10512,7 +10545,7 @@ function SphereTileSource({
|
|
|
10512
10545
|
anisotropy,
|
|
10513
10546
|
onPreviewError
|
|
10514
10547
|
);
|
|
10515
|
-
const callbacks = (0,
|
|
10548
|
+
const callbacks = (0, import_react40.useRef)({
|
|
10516
10549
|
onReady,
|
|
10517
10550
|
onLoadProgress,
|
|
10518
10551
|
onTileError,
|
|
@@ -10524,7 +10557,7 @@ function SphereTileSource({
|
|
|
10524
10557
|
1,
|
|
10525
10558
|
Number.isFinite(maxTextureMemoryMb) ? maxTextureMemoryMb : 128
|
|
10526
10559
|
) * 1024 * 1024;
|
|
10527
|
-
const ownedManager = (0,
|
|
10560
|
+
const ownedManager = (0, import_react40.useMemo)(
|
|
10528
10561
|
() => new TileTextureManager({
|
|
10529
10562
|
anisotropy,
|
|
10530
10563
|
maxBytes: ownedBudget,
|
|
@@ -10545,17 +10578,17 @@ function SphereTileSource({
|
|
|
10545
10578
|
);
|
|
10546
10579
|
const manager = sharedManager ?? ownedManager;
|
|
10547
10580
|
const budget = manager.memoryBudgetBytes;
|
|
10548
|
-
const readyRef = (0,
|
|
10549
|
-
const ready = (0,
|
|
10581
|
+
const readyRef = (0, import_react40.useRef)(false);
|
|
10582
|
+
const ready = (0, import_react40.useCallback)(() => {
|
|
10550
10583
|
if (!readyRef.current) {
|
|
10551
10584
|
readyRef.current = true;
|
|
10552
10585
|
callbacks.current.onReady?.();
|
|
10553
10586
|
}
|
|
10554
10587
|
}, []);
|
|
10555
|
-
(0,
|
|
10588
|
+
(0, import_react40.useEffect)(() => {
|
|
10556
10589
|
if (preview) ready();
|
|
10557
10590
|
}, [preview, ready]);
|
|
10558
|
-
(0,
|
|
10591
|
+
(0, import_react40.useEffect)(() => {
|
|
10559
10592
|
manager.resume();
|
|
10560
10593
|
return () => {
|
|
10561
10594
|
if (manager === ownedManager) {
|
|
@@ -10565,14 +10598,14 @@ function SphereTileSource({
|
|
|
10565
10598
|
queueMicrotask(() => manager.releaseUnused());
|
|
10566
10599
|
};
|
|
10567
10600
|
}, [manager, ownedManager]);
|
|
10568
|
-
const resolveUrl = (0,
|
|
10601
|
+
const resolveUrl = (0, import_react40.useMemo)(
|
|
10569
10602
|
() => (address) => resolveAssetUrl(
|
|
10570
10603
|
baseUrl,
|
|
10571
10604
|
resolveTileUrl ? resolveTileUrl(address) : resolveSphereTemplateUrl(urlTemplate, address, indexBase)
|
|
10572
10605
|
),
|
|
10573
10606
|
[baseUrl, resolveTileUrl, urlTemplate, indexBase]
|
|
10574
10607
|
);
|
|
10575
|
-
const candidates = (0,
|
|
10608
|
+
const candidates = (0, import_react40.useMemo)(
|
|
10576
10609
|
() => config.levels.map(
|
|
10577
10610
|
(level, index) => sphereTileAddresses(level, index, config.tileSize).map((address) => ({
|
|
10578
10611
|
address,
|
|
@@ -10581,12 +10614,17 @@ function SphereTileSource({
|
|
|
10581
10614
|
),
|
|
10582
10615
|
[config, yawOffset]
|
|
10583
10616
|
);
|
|
10584
|
-
const previewAddress = (0,
|
|
10617
|
+
const previewAddress = (0, import_react40.useMemo)(
|
|
10585
10618
|
() => sphereTileAddresses({ width: 2, height: 1 }, 0, 2)[0],
|
|
10586
10619
|
[]
|
|
10587
10620
|
);
|
|
10588
|
-
const [layers, setLayers] = (0,
|
|
10589
|
-
const
|
|
10621
|
+
const [layers, setLayers] = (0, import_react40.useState)([]);
|
|
10622
|
+
const detailReporter = useSceneDetailReporter();
|
|
10623
|
+
const detailReporterRef = (0, import_react40.useRef)(detailReporter);
|
|
10624
|
+
detailReporterRef.current = detailReporter;
|
|
10625
|
+
const detailTokenRef = (0, import_react40.useRef)("");
|
|
10626
|
+
const targetKeysRef = (0, import_react40.useRef)([]);
|
|
10627
|
+
const scratch = (0, import_react40.useMemo)(
|
|
10590
10628
|
() => ({
|
|
10591
10629
|
camera: new import_three14.PerspectiveCamera(),
|
|
10592
10630
|
frustum: new import_three14.Frustum(),
|
|
@@ -10607,53 +10645,72 @@ function SphereTileSource({
|
|
|
10607
10645
|
(0, import_fiber16.useFrame)(() => {
|
|
10608
10646
|
if (!(camera instanceof import_three14.PerspectiveCamera)) return;
|
|
10609
10647
|
const now = performance.now(), dpr = gl.getPixelRatio();
|
|
10610
|
-
const
|
|
10611
|
-
|
|
10612
|
-
|
|
10613
|
-
|
|
10614
|
-
|
|
10615
|
-
|
|
10616
|
-
|
|
10617
|
-
|
|
10618
|
-
|
|
10619
|
-
|
|
10620
|
-
|
|
10621
|
-
|
|
10622
|
-
|
|
10623
|
-
|
|
10624
|
-
|
|
10625
|
-
|
|
10626
|
-
scratch.
|
|
10627
|
-
scratch.
|
|
10628
|
-
|
|
10629
|
-
|
|
10630
|
-
|
|
10631
|
-
|
|
10632
|
-
|
|
10633
|
-
|
|
10634
|
-
|
|
10635
|
-
({ bounds }) => scratch.frustum.intersectsBox(bounds)
|
|
10636
|
-
).map(({ address }) => address);
|
|
10637
|
-
const bytes = addresses.reduce(
|
|
10638
|
-
(total, address) => total + address.width * address.height * 4,
|
|
10639
|
-
0
|
|
10648
|
+
const managerChanged = scratch.manager !== manager;
|
|
10649
|
+
const loadModeChanged = scratch.loadMode !== loadMode;
|
|
10650
|
+
const viewUnchanged = scratch.fov === camera.fov && scratch.width === size.width && scratch.height === size.height && scratch.dpr === dpr && scratch.quaternion.angleTo(camera.quaternion) < 1e-4;
|
|
10651
|
+
if (sphereTileViewShouldRefresh({
|
|
10652
|
+
loadModeChanged,
|
|
10653
|
+
managerChanged,
|
|
10654
|
+
elapsedMs: now - scratch.time,
|
|
10655
|
+
viewUnchanged
|
|
10656
|
+
})) {
|
|
10657
|
+
const reset = managerChanged || loadModeChanged;
|
|
10658
|
+
scratch.time = now;
|
|
10659
|
+
scratch.fov = camera.fov;
|
|
10660
|
+
scratch.width = size.width;
|
|
10661
|
+
scratch.height = size.height;
|
|
10662
|
+
scratch.dpr = dpr;
|
|
10663
|
+
scratch.quaternion.copy(camera.quaternion);
|
|
10664
|
+
scratch.manager = manager;
|
|
10665
|
+
scratch.loadMode = loadMode;
|
|
10666
|
+
scratch.camera.copy(camera, false);
|
|
10667
|
+
scratch.camera.fov = Math.min(179, camera.fov + 8);
|
|
10668
|
+
scratch.camera.updateProjectionMatrix();
|
|
10669
|
+
scratch.camera.updateMatrixWorld();
|
|
10670
|
+
scratch.matrix.multiplyMatrices(
|
|
10671
|
+
scratch.camera.projectionMatrix,
|
|
10672
|
+
scratch.camera.matrixWorldInverse
|
|
10640
10673
|
);
|
|
10641
|
-
|
|
10642
|
-
|
|
10643
|
-
|
|
10674
|
+
scratch.frustum.setFromProjectionMatrix(scratch.matrix);
|
|
10675
|
+
let level = loadMode === "preview" ? -1 : loadMode === "base" ? 0 : preferredSphereLevel(config.levels, size.height, dpr, camera.fov);
|
|
10676
|
+
const next = [];
|
|
10677
|
+
let residentBytes = 0;
|
|
10678
|
+
for (let index = 0; index <= level; index++) {
|
|
10679
|
+
const addresses = candidates[index].filter(
|
|
10680
|
+
({ bounds }) => scratch.frustum.intersectsBox(bounds)
|
|
10681
|
+
).map(({ address }) => address);
|
|
10682
|
+
const bytes = addresses.reduce(
|
|
10683
|
+
(total, address) => total + address.width * address.height * 4,
|
|
10684
|
+
0
|
|
10685
|
+
);
|
|
10686
|
+
if (residentBytes + bytes > budget) {
|
|
10687
|
+
level = index - 1;
|
|
10688
|
+
break;
|
|
10689
|
+
}
|
|
10690
|
+
residentBytes += bytes;
|
|
10691
|
+
next.push({ level: index, addresses });
|
|
10692
|
+
}
|
|
10693
|
+
const targetLayer = loadMode === "full" ? next[next.length - 1] : void 0;
|
|
10694
|
+
targetKeysRef.current = targetLayer ? targetLayer.addresses.map(
|
|
10695
|
+
(address) => `${resolveUrl(address)}\0${sphereTileKey(address)}`
|
|
10696
|
+
) : [];
|
|
10697
|
+
if (level !== scratch.level) {
|
|
10698
|
+
scratch.level = level;
|
|
10699
|
+
if (level >= 0) callbacks.current.onLevelChange?.(level);
|
|
10700
|
+
}
|
|
10701
|
+
const token = next.map((layer) => layer.addresses.map(sphereTileKey).join(",")).join(";");
|
|
10702
|
+
if (token !== scratch.token || reset) {
|
|
10703
|
+
scratch.token = token;
|
|
10704
|
+
setLayers(next);
|
|
10644
10705
|
}
|
|
10645
|
-
residentBytes += bytes;
|
|
10646
|
-
next.push({ level: index, addresses });
|
|
10647
|
-
}
|
|
10648
|
-
if (level !== scratch.level) {
|
|
10649
|
-
scratch.level = level;
|
|
10650
|
-
if (level >= 0) callbacks.current.onLevelChange?.(level);
|
|
10651
|
-
}
|
|
10652
|
-
const token = next.map((layer) => layer.addresses.map(sphereTileKey).join(",")).join(";");
|
|
10653
|
-
if (token !== scratch.token || reset) {
|
|
10654
|
-
scratch.token = token;
|
|
10655
|
-
setLayers(next);
|
|
10656
10706
|
}
|
|
10707
|
+
publishSceneDetail(
|
|
10708
|
+
detailReporterRef.current,
|
|
10709
|
+
detailTokenRef,
|
|
10710
|
+
loadMode === "full" && viewTilesAreDrawable(
|
|
10711
|
+
targetKeysRef.current.map((key) => manager.getSnapshot(key).texture)
|
|
10712
|
+
)
|
|
10713
|
+
);
|
|
10657
10714
|
});
|
|
10658
10715
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("group", { visible, children: [
|
|
10659
10716
|
preview ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
@@ -10682,23 +10739,23 @@ function SphereTileSource({
|
|
|
10682
10739
|
}
|
|
10683
10740
|
function SphereTile({ multires, ...props }) {
|
|
10684
10741
|
const token = typeof multires === "string" ? multires : JSON.stringify(multires);
|
|
10685
|
-
const config = (0,
|
|
10742
|
+
const config = (0, import_react40.useMemo)(() => parseSphereMultires(multires), [token]);
|
|
10686
10743
|
const sourceKey = `${props.baseUrl}\0${token}\0${props.previewUrl}\0${props.urlTemplate ?? ""}\0${props.indexBase ?? 1}`;
|
|
10687
10744
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(SphereTileSource, { ...props, config }, sourceKey);
|
|
10688
10745
|
}
|
|
10689
10746
|
|
|
10690
10747
|
// src/sphere.tsx
|
|
10691
10748
|
var import_fiber17 = require("@react-three/fiber");
|
|
10692
|
-
var
|
|
10749
|
+
var import_react41 = require("react");
|
|
10693
10750
|
var import_three15 = require("three");
|
|
10694
10751
|
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
10695
10752
|
function useEquirectTexture(url, anisotropy, generateMipmaps, onLoad, onError) {
|
|
10696
|
-
const [texture, setTexture] = (0,
|
|
10697
|
-
const onLoadRef = (0,
|
|
10698
|
-
const onErrorRef = (0,
|
|
10753
|
+
const [texture, setTexture] = (0, import_react41.useState)(null);
|
|
10754
|
+
const onLoadRef = (0, import_react41.useRef)(onLoad);
|
|
10755
|
+
const onErrorRef = (0, import_react41.useRef)(onError);
|
|
10699
10756
|
onLoadRef.current = onLoad;
|
|
10700
10757
|
onErrorRef.current = onError;
|
|
10701
|
-
(0,
|
|
10758
|
+
(0, import_react41.useEffect)(() => {
|
|
10702
10759
|
if (!url) {
|
|
10703
10760
|
setTexture(null);
|
|
10704
10761
|
return;
|
|
@@ -10737,7 +10794,7 @@ function useEquirectTexture(url, anisotropy, generateMipmaps, onLoad, onError) {
|
|
|
10737
10794
|
active = false;
|
|
10738
10795
|
};
|
|
10739
10796
|
}, [anisotropy, generateMipmaps, url]);
|
|
10740
|
-
(0,
|
|
10797
|
+
(0, import_react41.useEffect)(
|
|
10741
10798
|
() => () => {
|
|
10742
10799
|
texture?.dispose();
|
|
10743
10800
|
},
|
|
@@ -10757,7 +10814,7 @@ function Sphere({
|
|
|
10757
10814
|
}) {
|
|
10758
10815
|
const gl = (0, import_fiber17.useThree)((state) => state.gl);
|
|
10759
10816
|
const anisotropy = gl.capabilities.getMaxAnisotropy();
|
|
10760
|
-
const resolvedPreviewUrl = (0,
|
|
10817
|
+
const resolvedPreviewUrl = (0, import_react41.useMemo)(
|
|
10761
10818
|
() => resolveUrlAgainstFile(src, previewUrl),
|
|
10762
10819
|
[previewUrl, src]
|
|
10763
10820
|
);
|
|
@@ -10776,11 +10833,21 @@ function Sphere({
|
|
|
10776
10833
|
onPreviewError
|
|
10777
10834
|
);
|
|
10778
10835
|
const displayTexture = texture ?? previewTexture;
|
|
10779
|
-
const readyRef = (0,
|
|
10780
|
-
|
|
10836
|
+
const readyRef = (0, import_react41.useRef)(false);
|
|
10837
|
+
const detailReporter = useSceneDetailReporter();
|
|
10838
|
+
(0, import_react41.useEffect)(() => {
|
|
10781
10839
|
readyRef.current = false;
|
|
10782
10840
|
}, [resolvedPreviewUrl, src]);
|
|
10783
|
-
(0,
|
|
10841
|
+
(0, import_react41.useEffect)(() => {
|
|
10842
|
+
if (!detailReporter) {
|
|
10843
|
+
return;
|
|
10844
|
+
}
|
|
10845
|
+
detailReporter.report(texture != null);
|
|
10846
|
+
return () => {
|
|
10847
|
+
detailReporter.report(false);
|
|
10848
|
+
};
|
|
10849
|
+
}, [detailReporter, texture]);
|
|
10850
|
+
(0, import_react41.useEffect)(() => {
|
|
10784
10851
|
if (!displayTexture || readyRef.current) {
|
|
10785
10852
|
return;
|
|
10786
10853
|
}
|
|
@@ -10812,7 +10879,7 @@ function Sphere({
|
|
|
10812
10879
|
|
|
10813
10880
|
// src/video/pano-video.tsx
|
|
10814
10881
|
var import_fiber18 = require("@react-three/fiber");
|
|
10815
|
-
var
|
|
10882
|
+
var import_react42 = require("react");
|
|
10816
10883
|
var import_three16 = require("three");
|
|
10817
10884
|
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
10818
10885
|
var EMPTY_TRACKS = [];
|
|
@@ -10899,10 +10966,10 @@ function applyEquirectangularLayout(texture, anisotropy) {
|
|
|
10899
10966
|
}
|
|
10900
10967
|
function usePosterTexture(poster, onError) {
|
|
10901
10968
|
const gl = (0, import_fiber18.useThree)((state) => state.gl);
|
|
10902
|
-
const [texture, setTexture] = (0,
|
|
10903
|
-
const onErrorRef = (0,
|
|
10969
|
+
const [texture, setTexture] = (0, import_react42.useState)(null);
|
|
10970
|
+
const onErrorRef = (0, import_react42.useRef)(onError);
|
|
10904
10971
|
onErrorRef.current = onError;
|
|
10905
|
-
(0,
|
|
10972
|
+
(0, import_react42.useEffect)(() => {
|
|
10906
10973
|
let active = true;
|
|
10907
10974
|
setTexture(null);
|
|
10908
10975
|
if (!poster) {
|
|
@@ -10939,7 +11006,7 @@ function usePosterTexture(poster, onError) {
|
|
|
10939
11006
|
active = false;
|
|
10940
11007
|
};
|
|
10941
11008
|
}, [gl, poster]);
|
|
10942
|
-
(0,
|
|
11009
|
+
(0, import_react42.useEffect)(
|
|
10943
11010
|
() => () => {
|
|
10944
11011
|
texture?.dispose();
|
|
10945
11012
|
},
|
|
@@ -10998,38 +11065,38 @@ function PanoVideo({
|
|
|
10998
11065
|
}) {
|
|
10999
11066
|
usePanoMediaActivationIntent(autoPlay);
|
|
11000
11067
|
const gl = (0, import_fiber18.useThree)((state) => state.gl);
|
|
11001
|
-
const host = (0,
|
|
11002
|
-
const overlay = (0,
|
|
11003
|
-
const variants = (0,
|
|
11068
|
+
const host = (0, import_react42.useContext)(PanoVideoHostContext);
|
|
11069
|
+
const overlay = (0, import_react42.useContext)(PanoChromeOverlayContext);
|
|
11070
|
+
const variants = (0, import_react42.useMemo)(
|
|
11004
11071
|
() => resolvePanoVideoVariants({ poster, src, variants: variantsProp }),
|
|
11005
11072
|
[poster, src, variantsProp]
|
|
11006
11073
|
);
|
|
11007
11074
|
const tracks = tracksProp ?? EMPTY_TRACKS;
|
|
11008
11075
|
const captionsEnabled = captions !== false;
|
|
11009
|
-
const captionAppearance = (0,
|
|
11076
|
+
const captionAppearance = (0, import_react42.useMemo)(
|
|
11010
11077
|
() => resolvePanoVideoCaptionAppearance(
|
|
11011
11078
|
typeof captions === "object" ? captions : void 0
|
|
11012
11079
|
),
|
|
11013
11080
|
[captions]
|
|
11014
11081
|
);
|
|
11015
|
-
const [variantId, setVariantId] = (0,
|
|
11082
|
+
const [variantId, setVariantId] = (0, import_react42.useState)(
|
|
11016
11083
|
() => resolvePanoVideoVariantId(variants, defaultVariantId)
|
|
11017
11084
|
);
|
|
11018
|
-
const [trackId, setTrackId] = (0,
|
|
11085
|
+
const [trackId, setTrackId] = (0, import_react42.useState)(
|
|
11019
11086
|
() => captionsEnabled ? defaultPanoVideoTrackId(tracks) : null
|
|
11020
11087
|
);
|
|
11021
|
-
const [ready, setReady] = (0,
|
|
11022
|
-
const autoPlayRef = (0,
|
|
11088
|
+
const [ready, setReady] = (0, import_react42.useState)(false);
|
|
11089
|
+
const autoPlayRef = (0, import_react42.useRef)(autoPlay);
|
|
11023
11090
|
autoPlayRef.current = autoPlay;
|
|
11024
|
-
const blockedRef = (0,
|
|
11025
|
-
const captionAppearanceOverrideRef = (0,
|
|
11091
|
+
const blockedRef = (0, import_react42.useRef)(false);
|
|
11092
|
+
const captionAppearanceOverrideRef = (0, import_react42.useRef)(
|
|
11026
11093
|
{}
|
|
11027
11094
|
);
|
|
11028
|
-
const mediaCapabilitiesRef = (0,
|
|
11095
|
+
const mediaCapabilitiesRef = (0, import_react42.useRef)({
|
|
11029
11096
|
volumeAdjustable: true,
|
|
11030
11097
|
playbackRates: [...DEFAULT_PANO_VIDEO_PLAYBACK_RATES]
|
|
11031
11098
|
});
|
|
11032
|
-
const storeRef = (0,
|
|
11099
|
+
const storeRef = (0, import_react42.useRef)(null);
|
|
11033
11100
|
if (!storeRef.current) {
|
|
11034
11101
|
storeRef.current = {
|
|
11035
11102
|
snapshot: {
|
|
@@ -11039,7 +11106,7 @@ function PanoVideo({
|
|
|
11039
11106
|
listeners: /* @__PURE__ */ new Set()
|
|
11040
11107
|
};
|
|
11041
11108
|
}
|
|
11042
|
-
const actionsRef = (0,
|
|
11109
|
+
const actionsRef = (0, import_react42.useRef)({
|
|
11043
11110
|
play: async () => {
|
|
11044
11111
|
},
|
|
11045
11112
|
pause: () => {
|
|
@@ -11059,19 +11126,19 @@ function PanoVideo({
|
|
|
11059
11126
|
setCaptionAppearance: (_appearance) => {
|
|
11060
11127
|
}
|
|
11061
11128
|
});
|
|
11062
|
-
const onLoadRef = (0,
|
|
11063
|
-
const onErrorRef = (0,
|
|
11064
|
-
const onPlaybackStateChangeRef = (0,
|
|
11065
|
-
const onEndedRef = (0,
|
|
11066
|
-
const onVariantChangeRef = (0,
|
|
11067
|
-
const onTrackChangeRef = (0,
|
|
11129
|
+
const onLoadRef = (0, import_react42.useRef)(onLoad);
|
|
11130
|
+
const onErrorRef = (0, import_react42.useRef)(onError);
|
|
11131
|
+
const onPlaybackStateChangeRef = (0, import_react42.useRef)(onPlaybackStateChange);
|
|
11132
|
+
const onEndedRef = (0, import_react42.useRef)(onEnded);
|
|
11133
|
+
const onVariantChangeRef = (0, import_react42.useRef)(onVariantChange);
|
|
11134
|
+
const onTrackChangeRef = (0, import_react42.useRef)(onTrackChange);
|
|
11068
11135
|
onLoadRef.current = onLoad;
|
|
11069
11136
|
onErrorRef.current = onError;
|
|
11070
11137
|
onPlaybackStateChangeRef.current = onPlaybackStateChange;
|
|
11071
11138
|
onEndedRef.current = onEnded;
|
|
11072
11139
|
onVariantChangeRef.current = onVariantChange;
|
|
11073
11140
|
onTrackChangeRef.current = onTrackChange;
|
|
11074
|
-
const resource = (0,
|
|
11141
|
+
const resource = (0, import_react42.useMemo)(() => {
|
|
11075
11142
|
if (typeof document === "undefined") {
|
|
11076
11143
|
return null;
|
|
11077
11144
|
}
|
|
@@ -11088,7 +11155,7 @@ function PanoVideo({
|
|
|
11088
11155
|
texture.generateMipmaps = false;
|
|
11089
11156
|
return { video, texture };
|
|
11090
11157
|
}, []);
|
|
11091
|
-
(0,
|
|
11158
|
+
(0, import_react42.useEffect)(
|
|
11092
11159
|
() => () => {
|
|
11093
11160
|
if (!resource) {
|
|
11094
11161
|
return;
|
|
@@ -11103,13 +11170,13 @@ function PanoVideo({
|
|
|
11103
11170
|
},
|
|
11104
11171
|
[resource]
|
|
11105
11172
|
);
|
|
11106
|
-
(0,
|
|
11173
|
+
(0, import_react42.useEffect)(() => {
|
|
11107
11174
|
if (!resource) {
|
|
11108
11175
|
return;
|
|
11109
11176
|
}
|
|
11110
11177
|
resource.texture.anisotropy = gl.capabilities.getMaxAnisotropy();
|
|
11111
11178
|
}, [gl, resource]);
|
|
11112
|
-
(0,
|
|
11179
|
+
(0, import_react42.useEffect)(() => {
|
|
11113
11180
|
if (!resource || !overlay?.overlayElement) {
|
|
11114
11181
|
return;
|
|
11115
11182
|
}
|
|
@@ -11132,7 +11199,7 @@ function PanoVideo({
|
|
|
11132
11199
|
activeVariant?.poster ?? poster,
|
|
11133
11200
|
onError
|
|
11134
11201
|
);
|
|
11135
|
-
const emitSnapshot = (0,
|
|
11202
|
+
const emitSnapshot = (0, import_react42.useCallback)(
|
|
11136
11203
|
(patch) => {
|
|
11137
11204
|
const store = storeRef.current;
|
|
11138
11205
|
const video = resource?.video;
|
|
@@ -11184,7 +11251,7 @@ function PanoVideo({
|
|
|
11184
11251
|
captionAppearance
|
|
11185
11252
|
]
|
|
11186
11253
|
);
|
|
11187
|
-
const controller = (0,
|
|
11254
|
+
const controller = (0, import_react42.useMemo)(
|
|
11188
11255
|
() => ({
|
|
11189
11256
|
subscribe: (onStoreChange) => {
|
|
11190
11257
|
const store = storeRef.current;
|
|
@@ -11236,7 +11303,7 @@ function PanoVideo({
|
|
|
11236
11303
|
}),
|
|
11237
11304
|
[]
|
|
11238
11305
|
);
|
|
11239
|
-
(0,
|
|
11306
|
+
(0, import_react42.useLayoutEffect)(() => {
|
|
11240
11307
|
if (!host || variants.length === 0) {
|
|
11241
11308
|
return;
|
|
11242
11309
|
}
|
|
@@ -11249,7 +11316,7 @@ function PanoVideo({
|
|
|
11249
11316
|
notifyPanoVideoHost(host);
|
|
11250
11317
|
};
|
|
11251
11318
|
}, [captionsEnabled, controller, controls, host, variants.length]);
|
|
11252
|
-
(0,
|
|
11319
|
+
(0, import_react42.useLayoutEffect)(() => {
|
|
11253
11320
|
if (!resource) {
|
|
11254
11321
|
return;
|
|
11255
11322
|
}
|
|
@@ -11262,10 +11329,10 @@ function PanoVideo({
|
|
|
11262
11329
|
};
|
|
11263
11330
|
emitSnapshot();
|
|
11264
11331
|
}, [emitSnapshot, playbackRates, resource]);
|
|
11265
|
-
(0,
|
|
11332
|
+
(0, import_react42.useEffect)(() => {
|
|
11266
11333
|
emitSnapshot();
|
|
11267
11334
|
}, [emitSnapshot]);
|
|
11268
|
-
(0,
|
|
11335
|
+
(0, import_react42.useEffect)(() => {
|
|
11269
11336
|
if (!resource || !activeVariant || !mediaKey) {
|
|
11270
11337
|
return;
|
|
11271
11338
|
}
|
|
@@ -11322,7 +11389,7 @@ function PanoVideo({
|
|
|
11322
11389
|
video.removeEventListener("error", handleError);
|
|
11323
11390
|
};
|
|
11324
11391
|
}, [mediaKey, resource]);
|
|
11325
|
-
(0,
|
|
11392
|
+
(0, import_react42.useEffect)(() => {
|
|
11326
11393
|
if (!resource) {
|
|
11327
11394
|
return;
|
|
11328
11395
|
}
|
|
@@ -11414,7 +11481,7 @@ function PanoVideo({
|
|
|
11414
11481
|
}
|
|
11415
11482
|
};
|
|
11416
11483
|
}, [emitSnapshot, resource]);
|
|
11417
|
-
(0,
|
|
11484
|
+
(0, import_react42.useEffect)(() => {
|
|
11418
11485
|
if (!resource) {
|
|
11419
11486
|
return;
|
|
11420
11487
|
}
|
|
@@ -11434,7 +11501,7 @@ function PanoVideo({
|
|
|
11434
11501
|
}
|
|
11435
11502
|
video.preload = preload;
|
|
11436
11503
|
}, [loop, muted, playsInline, preload, resource, volume]);
|
|
11437
|
-
(0,
|
|
11504
|
+
(0, import_react42.useEffect)(() => {
|
|
11438
11505
|
if (!resource) {
|
|
11439
11506
|
return;
|
|
11440
11507
|
}
|
|
@@ -11484,7 +11551,7 @@ function PanoVideo({
|
|
|
11484
11551
|
video.removeEventListener("ratechange", handleVolume);
|
|
11485
11552
|
};
|
|
11486
11553
|
}, [emitSnapshot, resource]);
|
|
11487
|
-
(0,
|
|
11554
|
+
(0, import_react42.useEffect)(() => {
|
|
11488
11555
|
if (!resource) {
|
|
11489
11556
|
return;
|
|
11490
11557
|
}
|
|
@@ -11519,7 +11586,7 @@ function PanoVideo({
|
|
|
11519
11586
|
video.textTracks.removeEventListener("change", applyModes);
|
|
11520
11587
|
};
|
|
11521
11588
|
}, [emitSnapshot, resource, trackId, tracks]);
|
|
11522
|
-
(0,
|
|
11589
|
+
(0, import_react42.useEffect)(() => {
|
|
11523
11590
|
if (!captionsEnabled) {
|
|
11524
11591
|
setTrackId(null);
|
|
11525
11592
|
return;
|
|
@@ -11554,9 +11621,9 @@ function PanoVideo({
|
|
|
11554
11621
|
}
|
|
11555
11622
|
|
|
11556
11623
|
// src/scenes.tsx
|
|
11557
|
-
var
|
|
11558
|
-
var
|
|
11559
|
-
var
|
|
11624
|
+
var import_fiber23 = require("@react-three/fiber");
|
|
11625
|
+
var import_react47 = require("react");
|
|
11626
|
+
var import_three24 = require("three");
|
|
11560
11627
|
|
|
11561
11628
|
// src/scene-transitions/presets.ts
|
|
11562
11629
|
var TRANSITION_DEFAULTS = {
|
|
@@ -11604,9 +11671,33 @@ function isSnapshotTransition(preset) {
|
|
|
11604
11671
|
return preset !== "none" && preset !== "particles";
|
|
11605
11672
|
}
|
|
11606
11673
|
|
|
11607
|
-
// src/scene-transitions/
|
|
11674
|
+
// src/scene-transitions/snapshot-hold.tsx
|
|
11608
11675
|
var import_fiber19 = require("@react-three/fiber");
|
|
11609
|
-
var
|
|
11676
|
+
var import_react43 = require("react");
|
|
11677
|
+
var import_three19 = require("three");
|
|
11678
|
+
|
|
11679
|
+
// src/scene-transitions/overlay-utils.ts
|
|
11680
|
+
var import_three17 = require("three");
|
|
11681
|
+
var OVERLAY_RENDER_ORDER = 1e4;
|
|
11682
|
+
var FULLSCREEN_PLANE = new import_three17.PlaneGeometry(1, 1);
|
|
11683
|
+
function isPerspectiveCamera(camera) {
|
|
11684
|
+
return camera.isPerspectiveCamera === true;
|
|
11685
|
+
}
|
|
11686
|
+
function placeFullscreenOverlay(mesh, camera, direction) {
|
|
11687
|
+
const distance = Math.max(camera.near * 1.1, 0.11);
|
|
11688
|
+
camera.getWorldDirection(direction);
|
|
11689
|
+
mesh.position.copy(camera.position).addScaledVector(direction, distance);
|
|
11690
|
+
mesh.quaternion.copy(camera.quaternion);
|
|
11691
|
+
const height = 2 * distance * Math.tan(camera.fov * Math.PI / 360);
|
|
11692
|
+
mesh.scale.set(height * camera.aspect, height, 1);
|
|
11693
|
+
}
|
|
11694
|
+
function overlayProgress(elapsedTime, duration, startTime) {
|
|
11695
|
+
const started = startTime ?? elapsedTime;
|
|
11696
|
+
const progress = duration === 0 ? 1 : Math.min(1, (elapsedTime - started) / duration);
|
|
11697
|
+
return { startTime: started, progress };
|
|
11698
|
+
}
|
|
11699
|
+
|
|
11700
|
+
// src/scene-transitions/snapshot-shaders.ts
|
|
11610
11701
|
var import_three18 = require("three");
|
|
11611
11702
|
|
|
11612
11703
|
// src/scene-transitions/glsl.ts
|
|
@@ -11639,227 +11730,65 @@ float fbm(vec2 p) {
|
|
|
11639
11730
|
}
|
|
11640
11731
|
`;
|
|
11641
11732
|
|
|
11642
|
-
// src/scene-transitions/
|
|
11643
|
-
var
|
|
11644
|
-
|
|
11645
|
-
|
|
11646
|
-
|
|
11647
|
-
|
|
11733
|
+
// src/scene-transitions/snapshot-shaders.ts
|
|
11734
|
+
var SNAPSHOT_VERTEX_SHADER = `
|
|
11735
|
+
varying vec2 vUv;
|
|
11736
|
+
void main() {
|
|
11737
|
+
vUv = uv;
|
|
11738
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
11739
|
+
}
|
|
11740
|
+
`;
|
|
11741
|
+
var HEADER = `
|
|
11742
|
+
uniform sampler2D map;
|
|
11743
|
+
uniform float progress;
|
|
11744
|
+
uniform vec2 resolution;
|
|
11745
|
+
varying vec2 vUv;
|
|
11746
|
+
${GLSL_COMMON}
|
|
11747
|
+
|
|
11748
|
+
vec2 aspectGrid(float rows) {
|
|
11749
|
+
float aspect = resolution.x / max(resolution.y, 1.0);
|
|
11750
|
+
return vec2(max(8.0, floor(rows * aspect)), rows);
|
|
11648
11751
|
}
|
|
11649
|
-
|
|
11650
|
-
|
|
11651
|
-
|
|
11652
|
-
mesh.position.copy(camera.position).addScaledVector(direction, distance);
|
|
11653
|
-
mesh.quaternion.copy(camera.quaternion);
|
|
11654
|
-
const height = 2 * distance * Math.tan(camera.fov * Math.PI / 360);
|
|
11655
|
-
mesh.scale.set(height * camera.aspect, height, 1);
|
|
11752
|
+
|
|
11753
|
+
vec2 gridCellId() {
|
|
11754
|
+
return floor(vUv * aspectGrid(16.0));
|
|
11656
11755
|
}
|
|
11657
|
-
|
|
11658
|
-
|
|
11659
|
-
|
|
11660
|
-
return
|
|
11756
|
+
|
|
11757
|
+
vec2 gridCellUv() {
|
|
11758
|
+
vec2 cells = aspectGrid(16.0);
|
|
11759
|
+
return (floor(vUv * cells) + 0.5) / cells;
|
|
11661
11760
|
}
|
|
11662
11761
|
|
|
11663
|
-
|
|
11664
|
-
|
|
11665
|
-
|
|
11666
|
-
|
|
11667
|
-
|
|
11668
|
-
|
|
11669
|
-
|
|
11670
|
-
|
|
11671
|
-
|
|
11672
|
-
|
|
11673
|
-
|
|
11762
|
+
float gridWipeAlpha(float spatialOrder, float t) {
|
|
11763
|
+
vec2 cells = aspectGrid(16.0);
|
|
11764
|
+
vec2 id = floor(vUv * cells);
|
|
11765
|
+
vec2 local = fract(vUv * cells);
|
|
11766
|
+
float order = mix(clamp(spatialOrder, 0.0, 1.0), hash(id), 0.12);
|
|
11767
|
+
float disappear = smoothstep(order, order + 0.16, t);
|
|
11768
|
+
float sc = mix(1.0, 0.18, disappear);
|
|
11769
|
+
vec2 scaled = 0.5 + (local - 0.5) / max(sc, 0.001);
|
|
11770
|
+
float inside = step(0.0, scaled.x) * step(scaled.x, 1.0) * step(0.0, scaled.y) * step(scaled.y, 1.0);
|
|
11771
|
+
return inside * (1.0 - disappear);
|
|
11772
|
+
}
|
|
11674
11773
|
|
|
11675
|
-
|
|
11676
|
-
|
|
11677
|
-
|
|
11678
|
-
float gy = floor(id / grid.x);
|
|
11679
|
-
vec2 cell = vec2(gx, gy);
|
|
11680
|
-
float h = hash(cell);
|
|
11681
|
-
float h2 = hash(cell + 19.2);
|
|
11682
|
-
float h3 = hash(cell + 7.7);
|
|
11683
|
-
vec2 randomDir = normalize(vec2(h, h2) * 2.0 - 1.0 + 1e-5);
|
|
11684
|
-
vec2 fromCenter = (cell + 0.5) / grid - 0.5 + 1e-5;
|
|
11685
|
-
vec2 dir = normalize(mix(randomDir, normalize(fromCenter), 0.65));
|
|
11686
|
-
float delay = h3 * 0.28;
|
|
11687
|
-
float lt = clamp((progress - delay) / max(1.0 - delay, 0.001), 0.0, 1.0);
|
|
11688
|
-
float explode = lt * lt;
|
|
11689
|
-
float scale = mix(1.0, 0.18, explode);
|
|
11690
|
-
float angle = (h * 2.0 - 1.0) * explode * 4.2;
|
|
11691
|
-
float ca = cos(angle);
|
|
11692
|
-
float sa = sin(angle);
|
|
11693
|
-
vec2 cellSize = 1.0 / grid;
|
|
11694
|
-
vec2 local = position.xy * cellSize * scale;
|
|
11695
|
-
vec2 rotated = vec2(local.x * ca - local.y * sa, local.x * sa + local.y * ca);
|
|
11696
|
-
vec2 planeCenter = (cell + 0.5) / grid - 0.5;
|
|
11697
|
-
vec2 exploded = planeCenter + dir * explode * 0.9;
|
|
11698
|
-
vec3 pos = vec3(exploded + rotated, -explode * 0.14);
|
|
11699
|
-
vUv = (cell + uv) / grid;
|
|
11700
|
-
vAlpha = 1.0 - explode;
|
|
11701
|
-
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
|
|
11702
|
-
}
|
|
11703
|
-
`;
|
|
11704
|
-
var PARTICLE_FRAGMENT_SHADER = `
|
|
11705
|
-
uniform sampler2D map;
|
|
11706
|
-
varying vec2 vUv;
|
|
11707
|
-
varying float vAlpha;
|
|
11774
|
+
float hexRound(float x) {
|
|
11775
|
+
return floor(x + 0.5);
|
|
11776
|
+
}
|
|
11708
11777
|
|
|
11709
|
-
|
|
11710
|
-
|
|
11711
|
-
|
|
11712
|
-
|
|
11713
|
-
|
|
11714
|
-
|
|
11715
|
-
|
|
11716
|
-
|
|
11717
|
-
|
|
11718
|
-
|
|
11719
|
-
if (
|
|
11720
|
-
|
|
11721
|
-
}
|
|
11722
|
-
geometry.setAttribute("position", quad.attributes.position.clone());
|
|
11723
|
-
geometry.setAttribute("uv", quad.attributes.uv.clone());
|
|
11724
|
-
const indexes = new Float32Array(PARTICLE_COUNT);
|
|
11725
|
-
for (let i = 0; i < PARTICLE_COUNT; i += 1) {
|
|
11726
|
-
indexes[i] = i;
|
|
11778
|
+
vec2 hexCellId(vec2 uv) {
|
|
11779
|
+
float aspect = resolution.x / max(resolution.y, 1.0);
|
|
11780
|
+
vec2 p = (uv - 0.5) * vec2(aspect, 1.0) * 12.0;
|
|
11781
|
+
float q = 1.1547005 * p.x;
|
|
11782
|
+
float r = -0.5773503 * p.x + p.y;
|
|
11783
|
+
vec3 cube = vec3(q, -q - r, r);
|
|
11784
|
+
vec3 rounded = vec3(hexRound(cube.x), hexRound(cube.y), hexRound(cube.z));
|
|
11785
|
+
vec3 diff = abs(rounded - cube);
|
|
11786
|
+
if (diff.x > diff.y && diff.x > diff.z) {
|
|
11787
|
+
rounded.x = -rounded.y - rounded.z;
|
|
11788
|
+
} else if (diff.y > diff.z) {
|
|
11789
|
+
rounded.y = -rounded.x - rounded.z;
|
|
11727
11790
|
}
|
|
11728
|
-
|
|
11729
|
-
geometry.instanceCount = PARTICLE_COUNT;
|
|
11730
|
-
quad.dispose();
|
|
11731
|
-
return geometry;
|
|
11732
|
-
}
|
|
11733
|
-
function ParticleOverlay({
|
|
11734
|
-
snapshot,
|
|
11735
|
-
transition,
|
|
11736
|
-
running,
|
|
11737
|
-
runId,
|
|
11738
|
-
onFinish
|
|
11739
|
-
}) {
|
|
11740
|
-
const { camera } = (0, import_fiber19.useThree)();
|
|
11741
|
-
const meshRef = (0, import_react42.useRef)(null);
|
|
11742
|
-
const startRef = (0, import_react42.useRef)(null);
|
|
11743
|
-
const finishedRef = (0, import_react42.useRef)(false);
|
|
11744
|
-
const directionRef = (0, import_react42.useRef)(new import_three18.Vector3());
|
|
11745
|
-
const geometry = (0, import_react42.useMemo)(() => createParticleGeometry(), []);
|
|
11746
|
-
const material = (0, import_react42.useMemo)(
|
|
11747
|
-
() => new import_three18.ShaderMaterial({
|
|
11748
|
-
transparent: true,
|
|
11749
|
-
depthTest: false,
|
|
11750
|
-
depthWrite: false,
|
|
11751
|
-
side: import_three18.DoubleSide,
|
|
11752
|
-
uniforms: {
|
|
11753
|
-
map: { value: snapshot.texture },
|
|
11754
|
-
progress: { value: 0 },
|
|
11755
|
-
grid: { value: new import_three18.Vector2(PARTICLE_GRID, PARTICLE_GRID) }
|
|
11756
|
-
},
|
|
11757
|
-
vertexShader: PARTICLE_VERTEX_SHADER,
|
|
11758
|
-
fragmentShader: PARTICLE_FRAGMENT_SHADER
|
|
11759
|
-
}),
|
|
11760
|
-
[snapshot.texture]
|
|
11761
|
-
);
|
|
11762
|
-
(0, import_react42.useEffect)(() => () => geometry.dispose(), [geometry]);
|
|
11763
|
-
(0, import_react42.useEffect)(() => () => material.dispose(), [material]);
|
|
11764
|
-
(0, import_react42.useEffect)(() => {
|
|
11765
|
-
startRef.current = null;
|
|
11766
|
-
finishedRef.current = false;
|
|
11767
|
-
material.uniforms.progress.value = 0;
|
|
11768
|
-
}, [material, runId]);
|
|
11769
|
-
(0, import_fiber19.useFrame)((state) => {
|
|
11770
|
-
const mesh = meshRef.current;
|
|
11771
|
-
if (!mesh || !isPerspectiveCamera(camera)) {
|
|
11772
|
-
return;
|
|
11773
|
-
}
|
|
11774
|
-
placeFullscreenOverlay(mesh, camera, directionRef.current);
|
|
11775
|
-
if (!running || finishedRef.current) {
|
|
11776
|
-
return;
|
|
11777
|
-
}
|
|
11778
|
-
const next = overlayProgress(state.clock.elapsedTime, transition.duration, startRef.current);
|
|
11779
|
-
startRef.current = next.startTime;
|
|
11780
|
-
material.uniforms.progress.value = next.progress;
|
|
11781
|
-
if (next.progress === 1) {
|
|
11782
|
-
finishedRef.current = true;
|
|
11783
|
-
onFinish();
|
|
11784
|
-
}
|
|
11785
|
-
});
|
|
11786
|
-
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
11787
|
-
"mesh",
|
|
11788
|
-
{
|
|
11789
|
-
ref: meshRef,
|
|
11790
|
-
frustumCulled: false,
|
|
11791
|
-
geometry,
|
|
11792
|
-
material,
|
|
11793
|
-
renderOrder: OVERLAY_RENDER_ORDER
|
|
11794
|
-
}
|
|
11795
|
-
);
|
|
11796
|
-
}
|
|
11797
|
-
|
|
11798
|
-
// src/scene-transitions/snapshot-overlay.tsx
|
|
11799
|
-
var import_fiber20 = require("@react-three/fiber");
|
|
11800
|
-
var import_react43 = require("react");
|
|
11801
|
-
var import_three20 = require("three");
|
|
11802
|
-
|
|
11803
|
-
// src/scene-transitions/snapshot-shaders.ts
|
|
11804
|
-
var import_three19 = require("three");
|
|
11805
|
-
var SNAPSHOT_VERTEX_SHADER = `
|
|
11806
|
-
varying vec2 vUv;
|
|
11807
|
-
void main() {
|
|
11808
|
-
vUv = uv;
|
|
11809
|
-
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
11810
|
-
}
|
|
11811
|
-
`;
|
|
11812
|
-
var HEADER = `
|
|
11813
|
-
uniform sampler2D map;
|
|
11814
|
-
uniform float progress;
|
|
11815
|
-
uniform vec2 resolution;
|
|
11816
|
-
varying vec2 vUv;
|
|
11817
|
-
${GLSL_COMMON}
|
|
11818
|
-
|
|
11819
|
-
vec2 aspectGrid(float rows) {
|
|
11820
|
-
float aspect = resolution.x / max(resolution.y, 1.0);
|
|
11821
|
-
return vec2(max(8.0, floor(rows * aspect)), rows);
|
|
11822
|
-
}
|
|
11823
|
-
|
|
11824
|
-
vec2 gridCellId() {
|
|
11825
|
-
return floor(vUv * aspectGrid(16.0));
|
|
11826
|
-
}
|
|
11827
|
-
|
|
11828
|
-
vec2 gridCellUv() {
|
|
11829
|
-
vec2 cells = aspectGrid(16.0);
|
|
11830
|
-
return (floor(vUv * cells) + 0.5) / cells;
|
|
11831
|
-
}
|
|
11832
|
-
|
|
11833
|
-
float gridWipeAlpha(float spatialOrder, float t) {
|
|
11834
|
-
vec2 cells = aspectGrid(16.0);
|
|
11835
|
-
vec2 id = floor(vUv * cells);
|
|
11836
|
-
vec2 local = fract(vUv * cells);
|
|
11837
|
-
float order = mix(clamp(spatialOrder, 0.0, 1.0), hash(id), 0.12);
|
|
11838
|
-
float disappear = smoothstep(order, order + 0.16, t);
|
|
11839
|
-
float sc = mix(1.0, 0.18, disappear);
|
|
11840
|
-
vec2 scaled = 0.5 + (local - 0.5) / max(sc, 0.001);
|
|
11841
|
-
float inside = step(0.0, scaled.x) * step(scaled.x, 1.0) * step(0.0, scaled.y) * step(scaled.y, 1.0);
|
|
11842
|
-
return inside * (1.0 - disappear);
|
|
11843
|
-
}
|
|
11844
|
-
|
|
11845
|
-
float hexRound(float x) {
|
|
11846
|
-
return floor(x + 0.5);
|
|
11847
|
-
}
|
|
11848
|
-
|
|
11849
|
-
vec2 hexCellId(vec2 uv) {
|
|
11850
|
-
float aspect = resolution.x / max(resolution.y, 1.0);
|
|
11851
|
-
vec2 p = (uv - 0.5) * vec2(aspect, 1.0) * 12.0;
|
|
11852
|
-
float q = 1.1547005 * p.x;
|
|
11853
|
-
float r = -0.5773503 * p.x + p.y;
|
|
11854
|
-
vec3 cube = vec3(q, -q - r, r);
|
|
11855
|
-
vec3 rounded = vec3(hexRound(cube.x), hexRound(cube.y), hexRound(cube.z));
|
|
11856
|
-
vec3 diff = abs(rounded - cube);
|
|
11857
|
-
if (diff.x > diff.y && diff.x > diff.z) {
|
|
11858
|
-
rounded.x = -rounded.y - rounded.z;
|
|
11859
|
-
} else if (diff.y > diff.z) {
|
|
11860
|
-
rounded.y = -rounded.x - rounded.z;
|
|
11861
|
-
}
|
|
11862
|
-
return rounded.xz;
|
|
11791
|
+
return rounded.xz;
|
|
11863
11792
|
}
|
|
11864
11793
|
`;
|
|
11865
11794
|
var FOOTER = `
|
|
@@ -12061,23 +11990,250 @@ var SNAPSHOT_FRAGMENT_SHADERS = {
|
|
|
12061
11990
|
`)
|
|
12062
11991
|
};
|
|
12063
11992
|
function createSnapshotMaterial(preset, texture) {
|
|
12064
|
-
return new
|
|
11993
|
+
return new import_three18.ShaderMaterial({
|
|
12065
11994
|
transparent: true,
|
|
12066
11995
|
depthTest: false,
|
|
12067
11996
|
depthWrite: false,
|
|
12068
|
-
side:
|
|
11997
|
+
side: import_three18.DoubleSide,
|
|
12069
11998
|
uniforms: {
|
|
12070
11999
|
map: { value: texture },
|
|
12071
12000
|
progress: { value: 0 },
|
|
12072
|
-
resolution: { value: new
|
|
12001
|
+
resolution: { value: new import_three18.Vector2(1, 1) }
|
|
12073
12002
|
},
|
|
12074
12003
|
vertexShader: SNAPSHOT_VERTEX_SHADER,
|
|
12075
12004
|
fragmentShader: SNAPSHOT_FRAGMENT_SHADERS[preset]
|
|
12076
12005
|
});
|
|
12077
12006
|
}
|
|
12078
12007
|
|
|
12079
|
-
// src/scene-transitions/snapshot-
|
|
12008
|
+
// src/scene-transitions/snapshot-hold.tsx
|
|
12009
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
12010
|
+
function SnapshotHold({ snapshot }) {
|
|
12011
|
+
const { camera, gl } = (0, import_fiber19.useThree)();
|
|
12012
|
+
const meshRef = (0, import_react43.useRef)(null);
|
|
12013
|
+
const directionRef = (0, import_react43.useRef)(new import_three19.Vector3());
|
|
12014
|
+
const material = (0, import_react43.useMemo)(
|
|
12015
|
+
() => createSnapshotMaterial("crossfade", snapshot.texture),
|
|
12016
|
+
[snapshot.texture]
|
|
12017
|
+
);
|
|
12018
|
+
(0, import_react43.useEffect)(() => () => material.dispose(), [material]);
|
|
12019
|
+
(0, import_fiber19.useFrame)(() => {
|
|
12020
|
+
const mesh = meshRef.current;
|
|
12021
|
+
if (!mesh || !isPerspectiveCamera(camera)) {
|
|
12022
|
+
return;
|
|
12023
|
+
}
|
|
12024
|
+
placeFullscreenOverlay(mesh, camera, directionRef.current);
|
|
12025
|
+
const context = gl.getContext();
|
|
12026
|
+
material.uniforms.resolution.value.set(
|
|
12027
|
+
context.drawingBufferWidth,
|
|
12028
|
+
context.drawingBufferHeight
|
|
12029
|
+
);
|
|
12030
|
+
material.uniforms.progress.value = 0;
|
|
12031
|
+
});
|
|
12032
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("mesh", { frustumCulled: false, ref: meshRef, renderOrder: OVERLAY_RENDER_ORDER, children: [
|
|
12033
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("primitive", { attach: "geometry", object: FULLSCREEN_PLANE }),
|
|
12034
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("primitive", { attach: "material", object: material })
|
|
12035
|
+
] });
|
|
12036
|
+
}
|
|
12037
|
+
|
|
12038
|
+
// src/scene-transition-policy.ts
|
|
12039
|
+
function pendingSceneUsesBaseLayer(phase, isPending) {
|
|
12040
|
+
return isPending && (phase === "preloading" || phase === "capturing");
|
|
12041
|
+
}
|
|
12042
|
+
function normalizeTransitionWaitMs(value) {
|
|
12043
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
12044
|
+
return 0;
|
|
12045
|
+
}
|
|
12046
|
+
return value;
|
|
12047
|
+
}
|
|
12048
|
+
function planDetailHold(input) {
|
|
12049
|
+
if (input.waitMs <= 0) {
|
|
12050
|
+
return null;
|
|
12051
|
+
}
|
|
12052
|
+
return {
|
|
12053
|
+
generation: input.generation,
|
|
12054
|
+
sceneId: input.sceneId,
|
|
12055
|
+
deadline: input.now + input.waitMs
|
|
12056
|
+
};
|
|
12057
|
+
}
|
|
12058
|
+
function acceptDetailWait(wait, signal) {
|
|
12059
|
+
if (!wait) {
|
|
12060
|
+
return { wait: null, start: false };
|
|
12061
|
+
}
|
|
12062
|
+
switch (signal.kind) {
|
|
12063
|
+
case "ready":
|
|
12064
|
+
if (signal.generation !== wait.generation || signal.sceneId !== wait.sceneId) {
|
|
12065
|
+
return { wait, start: false };
|
|
12066
|
+
}
|
|
12067
|
+
return { wait: null, start: true };
|
|
12068
|
+
case "timeout":
|
|
12069
|
+
if (signal.generation !== wait.generation || signal.now < wait.deadline) {
|
|
12070
|
+
return { wait, start: false };
|
|
12071
|
+
}
|
|
12072
|
+
return { wait: null, start: true };
|
|
12073
|
+
case "cancel":
|
|
12074
|
+
if (signal.generation !== wait.generation) {
|
|
12075
|
+
return { wait, start: false };
|
|
12076
|
+
}
|
|
12077
|
+
return { wait: null, start: false };
|
|
12078
|
+
default: {
|
|
12079
|
+
const exhaustive = signal;
|
|
12080
|
+
return exhaustive;
|
|
12081
|
+
}
|
|
12082
|
+
}
|
|
12083
|
+
}
|
|
12084
|
+
function phaseAfterSnapshot(preset, hold) {
|
|
12085
|
+
if (hold) {
|
|
12086
|
+
return "awaitingDetail";
|
|
12087
|
+
}
|
|
12088
|
+
if (preset === "none") {
|
|
12089
|
+
return "idle";
|
|
12090
|
+
}
|
|
12091
|
+
return "transitioning";
|
|
12092
|
+
}
|
|
12093
|
+
|
|
12094
|
+
// src/scene-transitions/particle-overlay.tsx
|
|
12095
|
+
var import_fiber20 = require("@react-three/fiber");
|
|
12096
|
+
var import_react44 = require("react");
|
|
12097
|
+
var import_three20 = require("three");
|
|
12080
12098
|
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
12099
|
+
var PARTICLE_GRID = 48;
|
|
12100
|
+
var PARTICLE_COUNT = PARTICLE_GRID * PARTICLE_GRID;
|
|
12101
|
+
var PARTICLE_VERTEX_SHADER = `
|
|
12102
|
+
attribute float instanceIndex;
|
|
12103
|
+
uniform float progress;
|
|
12104
|
+
uniform vec2 grid;
|
|
12105
|
+
varying vec2 vUv;
|
|
12106
|
+
varying float vAlpha;
|
|
12107
|
+
${GLSL_COMMON}
|
|
12108
|
+
|
|
12109
|
+
void main() {
|
|
12110
|
+
float id = instanceIndex;
|
|
12111
|
+
float gx = mod(id, grid.x);
|
|
12112
|
+
float gy = floor(id / grid.x);
|
|
12113
|
+
vec2 cell = vec2(gx, gy);
|
|
12114
|
+
float h = hash(cell);
|
|
12115
|
+
float h2 = hash(cell + 19.2);
|
|
12116
|
+
float h3 = hash(cell + 7.7);
|
|
12117
|
+
vec2 randomDir = normalize(vec2(h, h2) * 2.0 - 1.0 + 1e-5);
|
|
12118
|
+
vec2 fromCenter = (cell + 0.5) / grid - 0.5 + 1e-5;
|
|
12119
|
+
vec2 dir = normalize(mix(randomDir, normalize(fromCenter), 0.65));
|
|
12120
|
+
float delay = h3 * 0.28;
|
|
12121
|
+
float lt = clamp((progress - delay) / max(1.0 - delay, 0.001), 0.0, 1.0);
|
|
12122
|
+
float explode = lt * lt;
|
|
12123
|
+
float scale = mix(1.0, 0.18, explode);
|
|
12124
|
+
float angle = (h * 2.0 - 1.0) * explode * 4.2;
|
|
12125
|
+
float ca = cos(angle);
|
|
12126
|
+
float sa = sin(angle);
|
|
12127
|
+
vec2 cellSize = 1.0 / grid;
|
|
12128
|
+
vec2 local = position.xy * cellSize * scale;
|
|
12129
|
+
vec2 rotated = vec2(local.x * ca - local.y * sa, local.x * sa + local.y * ca);
|
|
12130
|
+
vec2 planeCenter = (cell + 0.5) / grid - 0.5;
|
|
12131
|
+
vec2 exploded = planeCenter + dir * explode * 0.9;
|
|
12132
|
+
vec3 pos = vec3(exploded + rotated, -explode * 0.14);
|
|
12133
|
+
vUv = (cell + uv) / grid;
|
|
12134
|
+
vAlpha = 1.0 - explode;
|
|
12135
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
|
|
12136
|
+
}
|
|
12137
|
+
`;
|
|
12138
|
+
var PARTICLE_FRAGMENT_SHADER = `
|
|
12139
|
+
uniform sampler2D map;
|
|
12140
|
+
varying vec2 vUv;
|
|
12141
|
+
varying float vAlpha;
|
|
12142
|
+
|
|
12143
|
+
void main() {
|
|
12144
|
+
vec4 old = texture2D(map, vUv);
|
|
12145
|
+
old.rgb *= 1.0 + 0.22 * (1.0 - vAlpha);
|
|
12146
|
+
gl_FragColor = vec4(old.rgb, old.a * vAlpha);
|
|
12147
|
+
#include <colorspace_fragment>
|
|
12148
|
+
}
|
|
12149
|
+
`;
|
|
12150
|
+
function createParticleGeometry() {
|
|
12151
|
+
const quad = new import_three20.PlaneGeometry(1, 1);
|
|
12152
|
+
const geometry = new import_three20.InstancedBufferGeometry();
|
|
12153
|
+
if (quad.index) {
|
|
12154
|
+
geometry.setIndex(quad.index.clone());
|
|
12155
|
+
}
|
|
12156
|
+
geometry.setAttribute("position", quad.attributes.position.clone());
|
|
12157
|
+
geometry.setAttribute("uv", quad.attributes.uv.clone());
|
|
12158
|
+
const indexes = new Float32Array(PARTICLE_COUNT);
|
|
12159
|
+
for (let i = 0; i < PARTICLE_COUNT; i += 1) {
|
|
12160
|
+
indexes[i] = i;
|
|
12161
|
+
}
|
|
12162
|
+
geometry.setAttribute("instanceIndex", new import_three20.InstancedBufferAttribute(indexes, 1));
|
|
12163
|
+
geometry.instanceCount = PARTICLE_COUNT;
|
|
12164
|
+
quad.dispose();
|
|
12165
|
+
return geometry;
|
|
12166
|
+
}
|
|
12167
|
+
function ParticleOverlay({
|
|
12168
|
+
snapshot,
|
|
12169
|
+
transition,
|
|
12170
|
+
running,
|
|
12171
|
+
runId,
|
|
12172
|
+
onFinish
|
|
12173
|
+
}) {
|
|
12174
|
+
const { camera } = (0, import_fiber20.useThree)();
|
|
12175
|
+
const meshRef = (0, import_react44.useRef)(null);
|
|
12176
|
+
const startRef = (0, import_react44.useRef)(null);
|
|
12177
|
+
const finishedRef = (0, import_react44.useRef)(false);
|
|
12178
|
+
const directionRef = (0, import_react44.useRef)(new import_three20.Vector3());
|
|
12179
|
+
const geometry = (0, import_react44.useMemo)(() => createParticleGeometry(), []);
|
|
12180
|
+
const material = (0, import_react44.useMemo)(
|
|
12181
|
+
() => new import_three20.ShaderMaterial({
|
|
12182
|
+
transparent: true,
|
|
12183
|
+
depthTest: false,
|
|
12184
|
+
depthWrite: false,
|
|
12185
|
+
side: import_three20.DoubleSide,
|
|
12186
|
+
uniforms: {
|
|
12187
|
+
map: { value: snapshot.texture },
|
|
12188
|
+
progress: { value: 0 },
|
|
12189
|
+
grid: { value: new import_three20.Vector2(PARTICLE_GRID, PARTICLE_GRID) }
|
|
12190
|
+
},
|
|
12191
|
+
vertexShader: PARTICLE_VERTEX_SHADER,
|
|
12192
|
+
fragmentShader: PARTICLE_FRAGMENT_SHADER
|
|
12193
|
+
}),
|
|
12194
|
+
[snapshot.texture]
|
|
12195
|
+
);
|
|
12196
|
+
(0, import_react44.useEffect)(() => () => geometry.dispose(), [geometry]);
|
|
12197
|
+
(0, import_react44.useEffect)(() => () => material.dispose(), [material]);
|
|
12198
|
+
(0, import_react44.useEffect)(() => {
|
|
12199
|
+
startRef.current = null;
|
|
12200
|
+
finishedRef.current = false;
|
|
12201
|
+
material.uniforms.progress.value = 0;
|
|
12202
|
+
}, [material, runId]);
|
|
12203
|
+
(0, import_fiber20.useFrame)((state) => {
|
|
12204
|
+
const mesh = meshRef.current;
|
|
12205
|
+
if (!mesh || !isPerspectiveCamera(camera)) {
|
|
12206
|
+
return;
|
|
12207
|
+
}
|
|
12208
|
+
placeFullscreenOverlay(mesh, camera, directionRef.current);
|
|
12209
|
+
if (!running || finishedRef.current) {
|
|
12210
|
+
return;
|
|
12211
|
+
}
|
|
12212
|
+
const next = overlayProgress(state.clock.elapsedTime, transition.duration, startRef.current);
|
|
12213
|
+
startRef.current = next.startTime;
|
|
12214
|
+
material.uniforms.progress.value = next.progress;
|
|
12215
|
+
if (next.progress === 1) {
|
|
12216
|
+
finishedRef.current = true;
|
|
12217
|
+
onFinish();
|
|
12218
|
+
}
|
|
12219
|
+
});
|
|
12220
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
12221
|
+
"mesh",
|
|
12222
|
+
{
|
|
12223
|
+
ref: meshRef,
|
|
12224
|
+
frustumCulled: false,
|
|
12225
|
+
geometry,
|
|
12226
|
+
material,
|
|
12227
|
+
renderOrder: OVERLAY_RENDER_ORDER
|
|
12228
|
+
}
|
|
12229
|
+
);
|
|
12230
|
+
}
|
|
12231
|
+
|
|
12232
|
+
// src/scene-transitions/snapshot-overlay.tsx
|
|
12233
|
+
var import_fiber21 = require("@react-three/fiber");
|
|
12234
|
+
var import_react45 = require("react");
|
|
12235
|
+
var import_three21 = require("three");
|
|
12236
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
12081
12237
|
function SnapshotOverlay({
|
|
12082
12238
|
snapshot,
|
|
12083
12239
|
transition,
|
|
@@ -12085,26 +12241,26 @@ function SnapshotOverlay({
|
|
|
12085
12241
|
runId,
|
|
12086
12242
|
onFinish
|
|
12087
12243
|
}) {
|
|
12088
|
-
const { camera, gl } = (0,
|
|
12089
|
-
const meshRef = (0,
|
|
12090
|
-
const startRef = (0,
|
|
12091
|
-
const finishedRef = (0,
|
|
12092
|
-
const directionRef = (0,
|
|
12093
|
-
const material = (0,
|
|
12244
|
+
const { camera, gl } = (0, import_fiber21.useThree)();
|
|
12245
|
+
const meshRef = (0, import_react45.useRef)(null);
|
|
12246
|
+
const startRef = (0, import_react45.useRef)(null);
|
|
12247
|
+
const finishedRef = (0, import_react45.useRef)(false);
|
|
12248
|
+
const directionRef = (0, import_react45.useRef)(new import_three21.Vector3());
|
|
12249
|
+
const material = (0, import_react45.useMemo)(() => {
|
|
12094
12250
|
if (!isSnapshotTransition(transition.preset)) {
|
|
12095
12251
|
return null;
|
|
12096
12252
|
}
|
|
12097
12253
|
return createSnapshotMaterial(transition.preset, snapshot.texture);
|
|
12098
12254
|
}, [snapshot.texture, transition.preset]);
|
|
12099
|
-
(0,
|
|
12100
|
-
(0,
|
|
12255
|
+
(0, import_react45.useEffect)(() => () => material?.dispose(), [material]);
|
|
12256
|
+
(0, import_react45.useEffect)(() => {
|
|
12101
12257
|
startRef.current = null;
|
|
12102
12258
|
finishedRef.current = false;
|
|
12103
12259
|
if (material) {
|
|
12104
12260
|
material.uniforms.progress.value = 0;
|
|
12105
12261
|
}
|
|
12106
12262
|
}, [material, runId]);
|
|
12107
|
-
(0,
|
|
12263
|
+
(0, import_fiber21.useFrame)((state) => {
|
|
12108
12264
|
const mesh = meshRef.current;
|
|
12109
12265
|
if (!mesh || !material || !isPerspectiveCamera(camera)) {
|
|
12110
12266
|
return;
|
|
@@ -12126,21 +12282,21 @@ function SnapshotOverlay({
|
|
|
12126
12282
|
if (!material) {
|
|
12127
12283
|
return null;
|
|
12128
12284
|
}
|
|
12129
|
-
return /* @__PURE__ */ (0,
|
|
12130
|
-
/* @__PURE__ */ (0,
|
|
12131
|
-
/* @__PURE__ */ (0,
|
|
12285
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("mesh", { ref: meshRef, renderOrder: OVERLAY_RENDER_ORDER, frustumCulled: false, children: [
|
|
12286
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("primitive", { attach: "geometry", object: FULLSCREEN_PLANE }),
|
|
12287
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("primitive", { attach: "material", object: material })
|
|
12132
12288
|
] });
|
|
12133
12289
|
}
|
|
12134
12290
|
|
|
12135
12291
|
// src/scene-transitions/transition-overlay.tsx
|
|
12136
|
-
var
|
|
12292
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
12137
12293
|
function TransitionOverlay(props) {
|
|
12138
12294
|
const { preset } = props.transition;
|
|
12139
12295
|
switch (preset) {
|
|
12140
12296
|
case "none":
|
|
12141
12297
|
return null;
|
|
12142
12298
|
case "particles":
|
|
12143
|
-
return /* @__PURE__ */ (0,
|
|
12299
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ParticleOverlay, { ...props });
|
|
12144
12300
|
case "crossfade":
|
|
12145
12301
|
case "zoom":
|
|
12146
12302
|
case "blackout":
|
|
@@ -12168,7 +12324,7 @@ function TransitionOverlay(props) {
|
|
|
12168
12324
|
case "zoomBlur":
|
|
12169
12325
|
case "hexDissolve":
|
|
12170
12326
|
case "filmBurn":
|
|
12171
|
-
return /* @__PURE__ */ (0,
|
|
12327
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SnapshotOverlay, { ...props });
|
|
12172
12328
|
default: {
|
|
12173
12329
|
const exhaustive = preset;
|
|
12174
12330
|
void exhaustive;
|
|
@@ -12178,12 +12334,12 @@ function TransitionOverlay(props) {
|
|
|
12178
12334
|
}
|
|
12179
12335
|
|
|
12180
12336
|
// src/tile/tile.tsx
|
|
12181
|
-
var
|
|
12182
|
-
var
|
|
12183
|
-
var
|
|
12337
|
+
var import_fiber22 = require("@react-three/fiber");
|
|
12338
|
+
var import_react46 = require("react");
|
|
12339
|
+
var import_three23 = require("three");
|
|
12184
12340
|
|
|
12185
12341
|
// src/tile/face-layout.ts
|
|
12186
|
-
var
|
|
12342
|
+
var import_three22 = require("three");
|
|
12187
12343
|
var CUBE_FACES = ["f", "r", "b", "l", "u", "d"];
|
|
12188
12344
|
var PREVIEW_FACE_ORDER = ["l", "f", "r", "b", "u", "d"];
|
|
12189
12345
|
var CUBE_RADIUS = DEFAULT_PANORAMA_RADIUS;
|
|
@@ -12234,8 +12390,8 @@ function getFaceQuaternion(face) {
|
|
|
12234
12390
|
return cached;
|
|
12235
12391
|
}
|
|
12236
12392
|
const transform = getFaceTransform(face);
|
|
12237
|
-
const quaternion = new
|
|
12238
|
-
new
|
|
12393
|
+
const quaternion = new import_three22.Quaternion().setFromEuler(
|
|
12394
|
+
new import_three22.Euler(...transform.rotation, "XYZ")
|
|
12239
12395
|
);
|
|
12240
12396
|
faceQuaternionCache.set(face, quaternion);
|
|
12241
12397
|
return quaternion;
|
|
@@ -12246,17 +12402,17 @@ function getTileBoundingBox(address, radius = CUBE_RADIUS) {
|
|
|
12246
12402
|
const halfWidth = local.width / 2;
|
|
12247
12403
|
const halfHeight = local.height / 2;
|
|
12248
12404
|
const quaternion = getFaceQuaternion(address.face);
|
|
12249
|
-
const position = new
|
|
12405
|
+
const position = new import_three22.Vector3(...transform.position);
|
|
12250
12406
|
const corners = [
|
|
12251
|
-
new
|
|
12252
|
-
new
|
|
12253
|
-
new
|
|
12254
|
-
new
|
|
12407
|
+
new import_three22.Vector3(local.x - halfWidth, local.y - halfHeight, 0),
|
|
12408
|
+
new import_three22.Vector3(local.x + halfWidth, local.y - halfHeight, 0),
|
|
12409
|
+
new import_three22.Vector3(local.x - halfWidth, local.y + halfHeight, 0),
|
|
12410
|
+
new import_three22.Vector3(local.x + halfWidth, local.y + halfHeight, 0)
|
|
12255
12411
|
];
|
|
12256
12412
|
for (const corner of corners) {
|
|
12257
12413
|
corner.applyQuaternion(quaternion).add(position);
|
|
12258
12414
|
}
|
|
12259
|
-
return new
|
|
12415
|
+
return new import_three22.Box3().setFromPoints(corners);
|
|
12260
12416
|
}
|
|
12261
12417
|
function makeTileAddress(face, level, faceSize, tileSize, col, row) {
|
|
12262
12418
|
const left = (col - 1) * tileSize;
|
|
@@ -12359,21 +12515,37 @@ function resolveTemplateUrl(template, address) {
|
|
|
12359
12515
|
}
|
|
12360
12516
|
|
|
12361
12517
|
// src/tile/tile.tsx
|
|
12362
|
-
var
|
|
12518
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
12363
12519
|
var MAX_LOD_UPDATE_INTERVAL_MS = 100;
|
|
12364
12520
|
var FAST_ROTATION_THRESHOLD_RADIANS = Math.PI / 180;
|
|
12365
12521
|
var FAST_FOV_THRESHOLD_DEGREES = 0.5;
|
|
12366
12522
|
var VIEW_CHANGE_EPSILON = 1e-4;
|
|
12523
|
+
function decideTileLodUpdate(input) {
|
|
12524
|
+
if (input.loadMode === "preview") {
|
|
12525
|
+
return false;
|
|
12526
|
+
}
|
|
12527
|
+
const loadModeChanged = input.loadMode !== input.trackedLoadMode;
|
|
12528
|
+
const viewChanged = input.visibilityDirty || loadModeChanged || input.viewportChanged || input.rotationDelta > VIEW_CHANGE_EPSILON || input.fovDelta > VIEW_CHANGE_EPSILON;
|
|
12529
|
+
if (!viewChanged) {
|
|
12530
|
+
return false;
|
|
12531
|
+
}
|
|
12532
|
+
const movingQuickly = input.rotationDelta >= FAST_ROTATION_THRESHOLD_RADIANS || input.fovDelta >= FAST_FOV_THRESHOLD_DEGREES;
|
|
12533
|
+
const immediate = input.visibilityDirty || loadModeChanged || input.viewportChanged || movingQuickly;
|
|
12534
|
+
if (!immediate && input.now - input.lastUpdateAt < MAX_LOD_UPDATE_INTERVAL_MS) {
|
|
12535
|
+
return false;
|
|
12536
|
+
}
|
|
12537
|
+
return true;
|
|
12538
|
+
}
|
|
12367
12539
|
var VISIBILITY_FOV_PADDING_DEGREES = 8;
|
|
12368
12540
|
var PREVIEW_RADIUS = CUBE_RADIUS + 0.05;
|
|
12369
|
-
var SHARED_TILE_GEOMETRY = new
|
|
12541
|
+
var SHARED_TILE_GEOMETRY = new import_three23.PlaneGeometry(1, 1);
|
|
12370
12542
|
function PreviewFace({
|
|
12371
12543
|
face,
|
|
12372
12544
|
texture,
|
|
12373
12545
|
faceOrder
|
|
12374
12546
|
}) {
|
|
12375
|
-
const geometry = (0,
|
|
12376
|
-
const nextGeometry = new
|
|
12547
|
+
const geometry = (0, import_react46.useMemo)(() => {
|
|
12548
|
+
const nextGeometry = new import_three23.PlaneGeometry(
|
|
12377
12549
|
PREVIEW_RADIUS * 2,
|
|
12378
12550
|
PREVIEW_RADIUS * 2
|
|
12379
12551
|
);
|
|
@@ -12387,21 +12559,21 @@ function PreviewFace({
|
|
|
12387
12559
|
uv.needsUpdate = true;
|
|
12388
12560
|
return nextGeometry;
|
|
12389
12561
|
}, [face, faceOrder]);
|
|
12390
|
-
(0,
|
|
12562
|
+
(0, import_react46.useEffect)(
|
|
12391
12563
|
() => () => {
|
|
12392
12564
|
geometry.dispose();
|
|
12393
12565
|
},
|
|
12394
12566
|
[geometry]
|
|
12395
12567
|
);
|
|
12396
12568
|
const transform = getFaceTransform(face, PREVIEW_RADIUS);
|
|
12397
|
-
return /* @__PURE__ */ (0,
|
|
12569
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
12398
12570
|
"mesh",
|
|
12399
12571
|
{
|
|
12400
12572
|
geometry,
|
|
12401
12573
|
position: transform.position,
|
|
12402
12574
|
renderOrder: -100,
|
|
12403
12575
|
rotation: transform.rotation,
|
|
12404
|
-
children: /* @__PURE__ */ (0,
|
|
12576
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
12405
12577
|
PanoBasicMaterial,
|
|
12406
12578
|
{
|
|
12407
12579
|
depthTest: false,
|
|
@@ -12417,7 +12589,7 @@ function PreviewCube({
|
|
|
12417
12589
|
texture,
|
|
12418
12590
|
faceOrder
|
|
12419
12591
|
}) {
|
|
12420
|
-
return CUBE_FACES.map((face) => /* @__PURE__ */ (0,
|
|
12592
|
+
return CUBE_FACES.map((face) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
12421
12593
|
PreviewFace,
|
|
12422
12594
|
{
|
|
12423
12595
|
face,
|
|
@@ -12427,7 +12599,7 @@ function PreviewCube({
|
|
|
12427
12599
|
face
|
|
12428
12600
|
));
|
|
12429
12601
|
}
|
|
12430
|
-
var TileMesh = (0,
|
|
12602
|
+
var TileMesh = (0, import_react46.memo)(function TileMesh2({
|
|
12431
12603
|
address,
|
|
12432
12604
|
manager,
|
|
12433
12605
|
renderOrder,
|
|
@@ -12441,14 +12613,14 @@ var TileMesh = (0, import_react44.memo)(function TileMesh2({
|
|
|
12441
12613
|
if (!snapshot.texture) {
|
|
12442
12614
|
return null;
|
|
12443
12615
|
}
|
|
12444
|
-
return /* @__PURE__ */ (0,
|
|
12616
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("group", { position: transform.position, rotation: transform.rotation, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
12445
12617
|
"mesh",
|
|
12446
12618
|
{
|
|
12447
12619
|
geometry: SHARED_TILE_GEOMETRY,
|
|
12448
12620
|
position: [layout.x, layout.y, 0],
|
|
12449
12621
|
renderOrder,
|
|
12450
12622
|
scale: [layout.width, layout.height, 1],
|
|
12451
|
-
children: /* @__PURE__ */ (0,
|
|
12623
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
12452
12624
|
PanoBasicMaterial,
|
|
12453
12625
|
{
|
|
12454
12626
|
depthTest: false,
|
|
@@ -12460,12 +12632,12 @@ var TileMesh = (0, import_react44.memo)(function TileMesh2({
|
|
|
12460
12632
|
}
|
|
12461
12633
|
) });
|
|
12462
12634
|
});
|
|
12463
|
-
var TileLayerMeshes = (0,
|
|
12635
|
+
var TileLayerMeshes = (0, import_react46.memo)(function TileLayerMeshes2({
|
|
12464
12636
|
layer,
|
|
12465
12637
|
manager,
|
|
12466
12638
|
resolveUrl
|
|
12467
12639
|
}) {
|
|
12468
|
-
return layer.addresses.map((address) => /* @__PURE__ */ (0,
|
|
12640
|
+
return layer.addresses.map((address) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
12469
12641
|
TileMesh,
|
|
12470
12642
|
{
|
|
12471
12643
|
address,
|
|
@@ -12565,8 +12737,8 @@ function parentAddresses(child, parentLevel, parentFaceSize, tileSize) {
|
|
|
12565
12737
|
return addresses;
|
|
12566
12738
|
}
|
|
12567
12739
|
function centerFacingAddress(candidates, camera) {
|
|
12568
|
-
const direction = camera.getWorldDirection(new
|
|
12569
|
-
const center = new
|
|
12740
|
+
const direction = camera.getWorldDirection(new import_three23.Vector3());
|
|
12741
|
+
const center = new import_three23.Vector3();
|
|
12570
12742
|
let bestCandidate = candidates[0];
|
|
12571
12743
|
let bestAlignment = -Infinity;
|
|
12572
12744
|
for (const candidate of candidates) {
|
|
@@ -12631,11 +12803,11 @@ function Tile({
|
|
|
12631
12803
|
onTileError,
|
|
12632
12804
|
onLevelChange
|
|
12633
12805
|
}) {
|
|
12634
|
-
const { camera, gl, size } = (0,
|
|
12635
|
-
const multiresConfig = (0,
|
|
12806
|
+
const { camera, gl, size } = (0, import_fiber22.useThree)();
|
|
12807
|
+
const multiresConfig = (0, import_react46.useMemo)(() => parseMultires(multires), [multires]);
|
|
12636
12808
|
const { levels, tileSize } = multiresConfig;
|
|
12637
12809
|
const multiresToken = `${tileSize}:${levels.join(",")}`;
|
|
12638
|
-
const candidatesByLevel = (0,
|
|
12810
|
+
const candidatesByLevel = (0, import_react46.useMemo)(
|
|
12639
12811
|
() => buildTileCandidates(levels, tileSize),
|
|
12640
12812
|
[levels, tileSize]
|
|
12641
12813
|
);
|
|
@@ -12647,13 +12819,13 @@ function Tile({
|
|
|
12647
12819
|
onPreviewError
|
|
12648
12820
|
);
|
|
12649
12821
|
const sharedManager = useSharedTileTextureManager();
|
|
12650
|
-
const progressRef = (0,
|
|
12651
|
-
const errorRef = (0,
|
|
12652
|
-
const levelChangeRef = (0,
|
|
12822
|
+
const progressRef = (0, import_react46.useRef)(onLoadProgress);
|
|
12823
|
+
const errorRef = (0, import_react46.useRef)(onTileError);
|
|
12824
|
+
const levelChangeRef = (0, import_react46.useRef)(onLevelChange);
|
|
12653
12825
|
progressRef.current = onLoadProgress;
|
|
12654
12826
|
errorRef.current = onTileError;
|
|
12655
12827
|
levelChangeRef.current = onLevelChange;
|
|
12656
|
-
const ownedManager = (0,
|
|
12828
|
+
const ownedManager = (0, import_react46.useMemo)(
|
|
12657
12829
|
() => new TileTextureManager({
|
|
12658
12830
|
anisotropy,
|
|
12659
12831
|
maxBytes: Math.max(1, maxTextureMemoryMb) * 1024 * 1024,
|
|
@@ -12674,7 +12846,7 @@ function Tile({
|
|
|
12674
12846
|
]
|
|
12675
12847
|
);
|
|
12676
12848
|
const manager = sharedManager ?? ownedManager;
|
|
12677
|
-
(0,
|
|
12849
|
+
(0, import_react46.useEffect)(() => {
|
|
12678
12850
|
manager.resume();
|
|
12679
12851
|
return () => {
|
|
12680
12852
|
if (manager === ownedManager) {
|
|
@@ -12684,11 +12856,11 @@ function Tile({
|
|
|
12684
12856
|
queueMicrotask(() => manager.releaseUnused());
|
|
12685
12857
|
};
|
|
12686
12858
|
}, [manager, ownedManager]);
|
|
12687
|
-
const readyRef = (0,
|
|
12688
|
-
(0,
|
|
12859
|
+
const readyRef = (0, import_react46.useRef)(false);
|
|
12860
|
+
(0, import_react46.useEffect)(() => {
|
|
12689
12861
|
readyRef.current = false;
|
|
12690
12862
|
}, [effectivePreviewUrl]);
|
|
12691
|
-
(0,
|
|
12863
|
+
(0, import_react46.useEffect)(() => {
|
|
12692
12864
|
if (!previewTexture || readyRef.current) {
|
|
12693
12865
|
return;
|
|
12694
12866
|
}
|
|
@@ -12696,31 +12868,37 @@ function Tile({
|
|
|
12696
12868
|
onReady?.();
|
|
12697
12869
|
}, [onReady, previewTexture]);
|
|
12698
12870
|
const template = urlTemplate ?? buildDefaultTileUrlTemplate();
|
|
12699
|
-
const resolveUrl = (0,
|
|
12871
|
+
const resolveUrl = (0, import_react46.useMemo)(
|
|
12700
12872
|
() => (address) => {
|
|
12701
12873
|
const relativePath = resolveTileUrl ? resolveTileUrl(address) : resolveTemplateUrl(template, address);
|
|
12702
12874
|
return resolveRelativeTileUrl(baseUrl, relativePath);
|
|
12703
12875
|
},
|
|
12704
12876
|
[baseUrl, resolveTileUrl, template]
|
|
12705
12877
|
);
|
|
12706
|
-
const [layers, setLayers] = (0,
|
|
12707
|
-
const layerTokenRef = (0,
|
|
12708
|
-
const currentLevelRef = (0,
|
|
12709
|
-
const lastUpdateAtRef = (0,
|
|
12710
|
-
const visibilityDirtyRef = (0,
|
|
12711
|
-
const lastVisibilityQuaternionRef = (0,
|
|
12712
|
-
const lastVisibilityFovRef = (0,
|
|
12713
|
-
const lastViewportRef = (0,
|
|
12714
|
-
const frustumRef = (0,
|
|
12715
|
-
const projectionMatrixRef = (0,
|
|
12716
|
-
const visibilityCameraRef = (0,
|
|
12717
|
-
(0,
|
|
12878
|
+
const [layers, setLayers] = (0, import_react46.useState)([]);
|
|
12879
|
+
const layerTokenRef = (0, import_react46.useRef)("");
|
|
12880
|
+
const currentLevelRef = (0, import_react46.useRef)(1);
|
|
12881
|
+
const lastUpdateAtRef = (0, import_react46.useRef)(-Infinity);
|
|
12882
|
+
const visibilityDirtyRef = (0, import_react46.useRef)(true);
|
|
12883
|
+
const lastVisibilityQuaternionRef = (0, import_react46.useRef)(camera.quaternion.clone());
|
|
12884
|
+
const lastVisibilityFovRef = (0, import_react46.useRef)(Number.NaN);
|
|
12885
|
+
const lastViewportRef = (0, import_react46.useRef)({ width: 0, height: 0, dpr: 0 });
|
|
12886
|
+
const frustumRef = (0, import_react46.useRef)(new import_three23.Frustum());
|
|
12887
|
+
const projectionMatrixRef = (0, import_react46.useRef)(new import_three23.Matrix4());
|
|
12888
|
+
const visibilityCameraRef = (0, import_react46.useRef)(new import_three23.PerspectiveCamera());
|
|
12889
|
+
const trackedLoadModeRef = (0, import_react46.useRef)(loadMode);
|
|
12890
|
+
const targetKeysRef = (0, import_react46.useRef)([]);
|
|
12891
|
+
const detailTokenRef = (0, import_react46.useRef)("");
|
|
12892
|
+
const detailReporter = useSceneDetailReporter();
|
|
12893
|
+
const detailReporterRef = (0, import_react46.useRef)(detailReporter);
|
|
12894
|
+
detailReporterRef.current = detailReporter;
|
|
12895
|
+
(0, import_react46.useEffect)(() => {
|
|
12718
12896
|
currentLevelRef.current = 1;
|
|
12719
12897
|
layerTokenRef.current = "";
|
|
12720
12898
|
visibilityDirtyRef.current = true;
|
|
12721
12899
|
setLayers([]);
|
|
12722
12900
|
}, [manager, multiresToken]);
|
|
12723
|
-
(0,
|
|
12901
|
+
(0, import_react46.useEffect)(() => {
|
|
12724
12902
|
if (loadMode !== "preview") {
|
|
12725
12903
|
return;
|
|
12726
12904
|
}
|
|
@@ -12734,11 +12912,14 @@ function Tile({
|
|
|
12734
12912
|
setLayers(nextLayers);
|
|
12735
12913
|
}
|
|
12736
12914
|
};
|
|
12737
|
-
(0,
|
|
12738
|
-
if (
|
|
12915
|
+
(0, import_fiber22.useFrame)(() => {
|
|
12916
|
+
if (!(camera instanceof import_three23.PerspectiveCamera)) {
|
|
12739
12917
|
return;
|
|
12740
12918
|
}
|
|
12741
|
-
if (
|
|
12919
|
+
if (loadMode === "preview") {
|
|
12920
|
+
trackedLoadModeRef.current = "preview";
|
|
12921
|
+
targetKeysRef.current = [];
|
|
12922
|
+
publishSceneDetail(detailReporterRef.current, detailTokenRef, false);
|
|
12742
12923
|
return;
|
|
12743
12924
|
}
|
|
12744
12925
|
const now = performance.now();
|
|
@@ -12749,60 +12930,75 @@ function Tile({
|
|
|
12749
12930
|
const fovDelta = Number.isFinite(lastVisibilityFovRef.current) ? Math.abs(camera.fov - lastVisibilityFovRef.current) : Infinity;
|
|
12750
12931
|
const lastViewport = lastViewportRef.current;
|
|
12751
12932
|
const viewportChanged = lastViewport.width !== size.width || lastViewport.height !== size.height || lastViewport.dpr !== pixelRatio;
|
|
12752
|
-
const
|
|
12753
|
-
|
|
12754
|
-
|
|
12755
|
-
|
|
12756
|
-
|
|
12757
|
-
|
|
12758
|
-
|
|
12759
|
-
|
|
12760
|
-
|
|
12761
|
-
|
|
12762
|
-
|
|
12763
|
-
|
|
12764
|
-
|
|
12765
|
-
|
|
12766
|
-
|
|
12767
|
-
|
|
12768
|
-
|
|
12769
|
-
|
|
12770
|
-
|
|
12771
|
-
|
|
12772
|
-
|
|
12773
|
-
|
|
12774
|
-
|
|
12775
|
-
|
|
12776
|
-
|
|
12777
|
-
camera
|
|
12778
|
-
|
|
12779
|
-
|
|
12780
|
-
|
|
12781
|
-
|
|
12782
|
-
|
|
12783
|
-
|
|
12784
|
-
|
|
12785
|
-
|
|
12786
|
-
|
|
12787
|
-
|
|
12788
|
-
|
|
12789
|
-
|
|
12790
|
-
|
|
12791
|
-
|
|
12933
|
+
const updateLod = decideTileLodUpdate({
|
|
12934
|
+
loadMode,
|
|
12935
|
+
trackedLoadMode: trackedLoadModeRef.current,
|
|
12936
|
+
now,
|
|
12937
|
+
lastUpdateAt: lastUpdateAtRef.current,
|
|
12938
|
+
visibilityDirty: visibilityDirtyRef.current,
|
|
12939
|
+
viewportChanged,
|
|
12940
|
+
rotationDelta,
|
|
12941
|
+
fovDelta
|
|
12942
|
+
});
|
|
12943
|
+
if (updateLod) {
|
|
12944
|
+
trackedLoadModeRef.current = loadMode;
|
|
12945
|
+
lastUpdateAtRef.current = now;
|
|
12946
|
+
const targetLevel = loadMode === "base" ? 1 : getPreferredLevel(
|
|
12947
|
+
levels,
|
|
12948
|
+
size.height,
|
|
12949
|
+
pixelRatio,
|
|
12950
|
+
camera.fov,
|
|
12951
|
+
currentLevelRef.current
|
|
12952
|
+
);
|
|
12953
|
+
if (targetLevel !== currentLevelRef.current) {
|
|
12954
|
+
currentLevelRef.current = targetLevel;
|
|
12955
|
+
levelChangeRef.current?.(targetLevel);
|
|
12956
|
+
}
|
|
12957
|
+
const visibilityCamera = visibilityCameraRef.current;
|
|
12958
|
+
visibilityCamera.copy(camera, false);
|
|
12959
|
+
visibilityCamera.fov = Math.min(
|
|
12960
|
+
179,
|
|
12961
|
+
camera.fov + VISIBILITY_FOV_PADDING_DEGREES
|
|
12962
|
+
);
|
|
12963
|
+
visibilityCamera.aspect = camera.aspect;
|
|
12964
|
+
updateVisibilityFrustum(
|
|
12965
|
+
visibilityCamera,
|
|
12966
|
+
projectionMatrixRef.current,
|
|
12967
|
+
frustumRef.current
|
|
12968
|
+
);
|
|
12969
|
+
const nextLayers = buildLayers(
|
|
12970
|
+
targetLevel,
|
|
12971
|
+
levels,
|
|
12972
|
+
tileSize,
|
|
12973
|
+
frustumRef.current,
|
|
12974
|
+
camera,
|
|
12975
|
+
candidatesByLevel
|
|
12976
|
+
);
|
|
12977
|
+
visibilityDirtyRef.current = false;
|
|
12978
|
+
lastVisibilityQuaternionRef.current.copy(camera.quaternion);
|
|
12979
|
+
lastVisibilityFovRef.current = camera.fov;
|
|
12980
|
+
lastViewportRef.current = {
|
|
12981
|
+
width: size.width,
|
|
12982
|
+
height: size.height,
|
|
12983
|
+
dpr: pixelRatio
|
|
12984
|
+
};
|
|
12985
|
+
const targetLayer = nextLayers.find((layer) => layer.level === targetLevel);
|
|
12986
|
+
targetKeysRef.current = loadMode === "full" ? (targetLayer?.addresses ?? []).map(
|
|
12987
|
+
(address) => `${resolveUrl(address)}\0${tileKey(address)}`
|
|
12988
|
+
) : [];
|
|
12989
|
+
commitLayers(nextLayers);
|
|
12990
|
+
}
|
|
12991
|
+
publishSceneDetail(
|
|
12992
|
+
detailReporterRef.current,
|
|
12993
|
+
detailTokenRef,
|
|
12994
|
+
loadMode === "full" && viewTilesAreDrawable(
|
|
12995
|
+
targetKeysRef.current.map((key) => manager.getSnapshot(key).texture)
|
|
12996
|
+
)
|
|
12792
12997
|
);
|
|
12793
|
-
visibilityDirtyRef.current = false;
|
|
12794
|
-
lastVisibilityQuaternionRef.current.copy(camera.quaternion);
|
|
12795
|
-
lastVisibilityFovRef.current = camera.fov;
|
|
12796
|
-
lastViewportRef.current = {
|
|
12797
|
-
width: size.width,
|
|
12798
|
-
height: size.height,
|
|
12799
|
-
dpr: pixelRatio
|
|
12800
|
-
};
|
|
12801
|
-
commitLayers(nextLayers);
|
|
12802
12998
|
});
|
|
12803
|
-
return /* @__PURE__ */ (0,
|
|
12804
|
-
previewTexture ? /* @__PURE__ */ (0,
|
|
12805
|
-
layers.map((layer) => /* @__PURE__ */ (0,
|
|
12999
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("group", { visible, children: [
|
|
13000
|
+
previewTexture ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PreviewCube, { texture: previewTexture, faceOrder: previewFaceOrder }) : null,
|
|
13001
|
+
layers.map((layer) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
12806
13002
|
TileLayerMeshes,
|
|
12807
13003
|
{
|
|
12808
13004
|
layer,
|
|
@@ -12815,7 +13011,7 @@ function Tile({
|
|
|
12815
13011
|
}
|
|
12816
13012
|
|
|
12817
13013
|
// src/scenes.tsx
|
|
12818
|
-
var
|
|
13014
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
12819
13015
|
function SceneSource({
|
|
12820
13016
|
scene,
|
|
12821
13017
|
visible,
|
|
@@ -12828,7 +13024,7 @@ function SceneSource({
|
|
|
12828
13024
|
}
|
|
12829
13025
|
switch (scene.type) {
|
|
12830
13026
|
case "sphere":
|
|
12831
|
-
return /* @__PURE__ */ (0,
|
|
13027
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
12832
13028
|
Sphere,
|
|
12833
13029
|
{
|
|
12834
13030
|
src: scene.src,
|
|
@@ -12841,7 +13037,7 @@ function SceneSource({
|
|
|
12841
13037
|
);
|
|
12842
13038
|
case "tile": {
|
|
12843
13039
|
const { id: _id, type: _type, ...tileProps } = scene;
|
|
12844
|
-
return /* @__PURE__ */ (0,
|
|
13040
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
12845
13041
|
Tile,
|
|
12846
13042
|
{
|
|
12847
13043
|
...tileProps,
|
|
@@ -12854,7 +13050,7 @@ function SceneSource({
|
|
|
12854
13050
|
}
|
|
12855
13051
|
case "sphereTile": {
|
|
12856
13052
|
const { id: _id, type: _type, ...tileProps } = scene;
|
|
12857
|
-
return /* @__PURE__ */ (0,
|
|
13053
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
12858
13054
|
SphereTile,
|
|
12859
13055
|
{
|
|
12860
13056
|
...tileProps,
|
|
@@ -12877,17 +13073,17 @@ function SnapshotCapture({
|
|
|
12877
13073
|
maxPixels,
|
|
12878
13074
|
onCaptured
|
|
12879
13075
|
}) {
|
|
12880
|
-
const { camera, gl, scene, size } = (0,
|
|
12881
|
-
const capturedRequestRef = (0,
|
|
12882
|
-
const renderTargetRef = (0,
|
|
12883
|
-
(0,
|
|
13076
|
+
const { camera, gl, scene, size } = (0, import_fiber23.useThree)();
|
|
13077
|
+
const capturedRequestRef = (0, import_react47.useRef)(0);
|
|
13078
|
+
const renderTargetRef = (0, import_react47.useRef)(null);
|
|
13079
|
+
(0, import_react47.useEffect)(
|
|
12884
13080
|
() => () => {
|
|
12885
13081
|
renderTargetRef.current?.dispose();
|
|
12886
13082
|
renderTargetRef.current = null;
|
|
12887
13083
|
},
|
|
12888
13084
|
[]
|
|
12889
13085
|
);
|
|
12890
|
-
(0,
|
|
13086
|
+
(0, import_fiber23.useFrame)(() => {
|
|
12891
13087
|
if (requestId === 0 || requestId === capturedRequestRef.current) {
|
|
12892
13088
|
return;
|
|
12893
13089
|
}
|
|
@@ -12897,14 +13093,14 @@ function SnapshotCapture({
|
|
|
12897
13093
|
const scale = Math.min(1, Math.sqrt(maxPixels / (sourceWidth * sourceHeight)));
|
|
12898
13094
|
const width = Math.max(1, Math.floor(sourceWidth * scale));
|
|
12899
13095
|
const height = Math.max(1, Math.floor(sourceHeight * scale));
|
|
12900
|
-
const nextTarget = new
|
|
13096
|
+
const nextTarget = new import_three24.WebGLRenderTarget(width, height, {
|
|
12901
13097
|
depthBuffer: false,
|
|
12902
13098
|
stencilBuffer: false
|
|
12903
13099
|
});
|
|
12904
|
-
nextTarget.texture.colorSpace =
|
|
13100
|
+
nextTarget.texture.colorSpace = import_three24.LinearSRGBColorSpace;
|
|
12905
13101
|
nextTarget.texture.generateMipmaps = false;
|
|
12906
|
-
nextTarget.texture.minFilter =
|
|
12907
|
-
nextTarget.texture.magFilter =
|
|
13102
|
+
nextTarget.texture.minFilter = import_three24.LinearFilter;
|
|
13103
|
+
nextTarget.texture.magFilter = import_three24.LinearFilter;
|
|
12908
13104
|
const previousTarget = gl.getRenderTarget();
|
|
12909
13105
|
gl.setRenderTarget(nextTarget);
|
|
12910
13106
|
gl.clear();
|
|
@@ -12935,53 +13131,90 @@ function ScenesController({
|
|
|
12935
13131
|
onTransitionEnd,
|
|
12936
13132
|
onTransitionError,
|
|
12937
13133
|
snapshotMaxPixels = 3686400,
|
|
13134
|
+
transitionWaitForDetailMs,
|
|
12938
13135
|
phaseRef: externalPhaseRef
|
|
12939
13136
|
}) {
|
|
12940
|
-
const controlsRef = (0,
|
|
13137
|
+
const controlsRef = (0, import_react47.useContext)(PanoramaViewContext);
|
|
12941
13138
|
const manager = useSharedTileTextureManager();
|
|
12942
|
-
const transition = (0,
|
|
13139
|
+
const transition = (0, import_react47.useMemo)(
|
|
12943
13140
|
() => resolveTransition(transitionInput),
|
|
12944
13141
|
[transitionInput]
|
|
12945
13142
|
);
|
|
12946
|
-
const sceneMap = (0,
|
|
13143
|
+
const sceneMap = (0, import_react47.useMemo)(
|
|
12947
13144
|
() => new Map(scenes.map((scene) => [scene.id, scene])),
|
|
12948
13145
|
[scenes]
|
|
12949
13146
|
);
|
|
12950
13147
|
const initialScene = sceneMap.get(activeSceneId) ?? null;
|
|
12951
|
-
const [slots, setSlots] = (0,
|
|
13148
|
+
const [slots, setSlots] = (0, import_react47.useState)([
|
|
12952
13149
|
initialScene,
|
|
12953
13150
|
null
|
|
12954
13151
|
]);
|
|
12955
|
-
const [activeSlot, setActiveSlot] = (0,
|
|
12956
|
-
const [liveSlot, setLiveSlot] = (0,
|
|
12957
|
-
const [pendingSlot, setPendingSlot] = (0,
|
|
12958
|
-
const [phase, setPhase] = (0,
|
|
12959
|
-
const [captureRequestId, setCaptureRequestId] = (0,
|
|
12960
|
-
const [transitionRunId, setTransitionRunId] = (0,
|
|
12961
|
-
const [snapshot, setSnapshot] = (0,
|
|
12962
|
-
const [recoveryKey, setRecoveryKey] = (0,
|
|
12963
|
-
const requestedSceneIdRef = (0,
|
|
12964
|
-
const captureReasonRef = (0,
|
|
12965
|
-
const interactionReleaseRef = (0,
|
|
12966
|
-
const slotsRef = (0,
|
|
12967
|
-
const phaseRef = (0,
|
|
12968
|
-
const liveSlotRef = (0,
|
|
12969
|
-
const transitionFromRef = (0,
|
|
12970
|
-
const readySceneRef = (0,
|
|
13152
|
+
const [activeSlot, setActiveSlot] = (0, import_react47.useState)(0);
|
|
13153
|
+
const [liveSlot, setLiveSlot] = (0, import_react47.useState)(0);
|
|
13154
|
+
const [pendingSlot, setPendingSlot] = (0, import_react47.useState)(null);
|
|
13155
|
+
const [phase, setPhase] = (0, import_react47.useState)(initialScene ? "idle" : "preloading");
|
|
13156
|
+
const [captureRequestId, setCaptureRequestId] = (0, import_react47.useState)(0);
|
|
13157
|
+
const [transitionRunId, setTransitionRunId] = (0, import_react47.useState)(0);
|
|
13158
|
+
const [snapshot, setSnapshot] = (0, import_react47.useState)(null);
|
|
13159
|
+
const [recoveryKey, setRecoveryKey] = (0, import_react47.useState)(0);
|
|
13160
|
+
const requestedSceneIdRef = (0, import_react47.useRef)(activeSceneId);
|
|
13161
|
+
const captureReasonRef = (0, import_react47.useRef)("start");
|
|
13162
|
+
const interactionReleaseRef = (0, import_react47.useRef)(null);
|
|
13163
|
+
const slotsRef = (0, import_react47.useRef)(slots);
|
|
13164
|
+
const phaseRef = (0, import_react47.useRef)(phase);
|
|
13165
|
+
const liveSlotRef = (0, import_react47.useRef)(liveSlot);
|
|
13166
|
+
const transitionFromRef = (0, import_react47.useRef)(initialScene);
|
|
13167
|
+
const readySceneRef = (0, import_react47.useRef)(null);
|
|
13168
|
+
const waitRef = (0, import_react47.useRef)(null);
|
|
13169
|
+
const waitTimerRef = (0, import_react47.useRef)(null);
|
|
13170
|
+
const detailGenerationRef = (0, import_react47.useRef)(0);
|
|
13171
|
+
const [detailGeneration, setDetailGeneration] = (0, import_react47.useState)(0);
|
|
13172
|
+
const mountedRef = (0, import_react47.useRef)(true);
|
|
13173
|
+
const waitForDetailMsRef = (0, import_react47.useRef)(0);
|
|
13174
|
+
waitForDetailMsRef.current = normalizeTransitionWaitMs(transitionWaitForDetailMs);
|
|
12971
13175
|
slotsRef.current = slots;
|
|
12972
13176
|
phaseRef.current = phase;
|
|
12973
13177
|
if (externalPhaseRef) {
|
|
12974
13178
|
externalPhaseRef.current = phase;
|
|
12975
13179
|
}
|
|
12976
13180
|
liveSlotRef.current = liveSlot;
|
|
12977
|
-
const releaseInteraction = (0,
|
|
13181
|
+
const releaseInteraction = (0, import_react47.useCallback)(() => {
|
|
12978
13182
|
interactionReleaseRef.current?.();
|
|
12979
13183
|
interactionReleaseRef.current = null;
|
|
12980
13184
|
}, []);
|
|
12981
|
-
const reportError = (0,
|
|
13185
|
+
const reportError = (0, import_react47.useCallback)((sceneId, error) => {
|
|
12982
13186
|
onTransitionError?.({ sceneId, error });
|
|
12983
13187
|
}, [onTransitionError]);
|
|
12984
|
-
const
|
|
13188
|
+
const clearDetailWait = (0, import_react47.useCallback)((bumpGeneration) => {
|
|
13189
|
+
if (waitTimerRef.current !== null) {
|
|
13190
|
+
clearTimeout(waitTimerRef.current);
|
|
13191
|
+
waitTimerRef.current = null;
|
|
13192
|
+
}
|
|
13193
|
+
const generation = waitRef.current?.generation;
|
|
13194
|
+
if (generation === void 0) {
|
|
13195
|
+
waitRef.current = null;
|
|
13196
|
+
} else {
|
|
13197
|
+
waitRef.current = acceptDetailWait(waitRef.current, {
|
|
13198
|
+
kind: "cancel",
|
|
13199
|
+
generation
|
|
13200
|
+
}).wait;
|
|
13201
|
+
}
|
|
13202
|
+
if (!bumpGeneration || !mountedRef.current) {
|
|
13203
|
+
return;
|
|
13204
|
+
}
|
|
13205
|
+
const nextGeneration = detailGenerationRef.current + 1;
|
|
13206
|
+
detailGenerationRef.current = nextGeneration;
|
|
13207
|
+
setDetailGeneration(nextGeneration);
|
|
13208
|
+
}, []);
|
|
13209
|
+
(0, import_react47.useEffect)(() => {
|
|
13210
|
+
mountedRef.current = true;
|
|
13211
|
+
return () => {
|
|
13212
|
+
mountedRef.current = false;
|
|
13213
|
+
clearDetailWait(false);
|
|
13214
|
+
};
|
|
13215
|
+
}, [clearDetailWait]);
|
|
13216
|
+
const startPreload = (0, import_react47.useCallback)((scene) => {
|
|
13217
|
+
clearDetailWait(true);
|
|
12985
13218
|
const nextSlot = 1 - liveSlotRef.current;
|
|
12986
13219
|
requestedSceneIdRef.current = scene.id;
|
|
12987
13220
|
setSlots((current) => {
|
|
@@ -12991,8 +13224,8 @@ function ScenesController({
|
|
|
12991
13224
|
});
|
|
12992
13225
|
setPendingSlot(nextSlot);
|
|
12993
13226
|
setPhase("preloading");
|
|
12994
|
-
}, []);
|
|
12995
|
-
(0,
|
|
13227
|
+
}, [clearDetailWait]);
|
|
13228
|
+
(0, import_react47.useEffect)(() => {
|
|
12996
13229
|
const requested = sceneMap.get(activeSceneId);
|
|
12997
13230
|
if (!requested) {
|
|
12998
13231
|
reportError(activeSceneId, new Error(`Unknown panorama scene: ${activeSceneId}`));
|
|
@@ -13007,22 +13240,23 @@ function ScenesController({
|
|
|
13007
13240
|
requestedSceneIdRef.current = requested.id;
|
|
13008
13241
|
return;
|
|
13009
13242
|
}
|
|
13010
|
-
if (phaseRef.current === "transitioning" || phaseRef.current === "capturing") {
|
|
13243
|
+
if (phaseRef.current === "transitioning" || phaseRef.current === "capturing" || phaseRef.current === "awaitingDetail") {
|
|
13011
13244
|
if (requestedSceneIdRef.current === requested.id) return;
|
|
13012
13245
|
requestedSceneIdRef.current = requested.id;
|
|
13013
13246
|
captureReasonRef.current = "interrupt";
|
|
13247
|
+
clearDetailWait(true);
|
|
13014
13248
|
setPhase("recapturing");
|
|
13015
13249
|
setCaptureRequestId((current) => current + 1);
|
|
13016
13250
|
return;
|
|
13017
13251
|
}
|
|
13018
13252
|
startPreload(requested);
|
|
13019
|
-
}, [activeSceneId, pendingSlot, reportError, sceneMap, startPreload]);
|
|
13020
|
-
const notifySceneReady = (0,
|
|
13253
|
+
}, [activeSceneId, clearDetailWait, pendingSlot, reportError, sceneMap, startPreload]);
|
|
13254
|
+
const notifySceneReady = (0, import_react47.useCallback)((scene) => {
|
|
13021
13255
|
if (!scene || readySceneRef.current === scene) return;
|
|
13022
13256
|
readySceneRef.current = scene;
|
|
13023
13257
|
onSceneReady?.(scene.id);
|
|
13024
13258
|
}, [onSceneReady]);
|
|
13025
|
-
const handleReady = (0,
|
|
13259
|
+
const handleReady = (0, import_react47.useCallback)((slot) => {
|
|
13026
13260
|
if (slot === liveSlotRef.current && pendingSlot === null && phaseRef.current === "idle") {
|
|
13027
13261
|
notifySceneReady(slotsRef.current[slot]);
|
|
13028
13262
|
return;
|
|
@@ -13030,7 +13264,7 @@ function ScenesController({
|
|
|
13030
13264
|
if (slot !== pendingSlot || phaseRef.current !== "preloading") {
|
|
13031
13265
|
return;
|
|
13032
13266
|
}
|
|
13033
|
-
if (transition.preset === "none") {
|
|
13267
|
+
if (transition.preset === "none" && waitForDetailMsRef.current === 0) {
|
|
13034
13268
|
const previousScene = slotsRef.current[liveSlotRef.current];
|
|
13035
13269
|
const nextScene = slotsRef.current[slot];
|
|
13036
13270
|
setSlots((current) => {
|
|
@@ -13058,64 +13292,167 @@ function ScenesController({
|
|
|
13058
13292
|
setPhase("capturing");
|
|
13059
13293
|
setCaptureRequestId((current) => current + 1);
|
|
13060
13294
|
}, [controlsRef, notifySceneReady, onTransitionEnd, pendingSlot, transition.preset]);
|
|
13061
|
-
const
|
|
13062
|
-
|
|
13063
|
-
|
|
13064
|
-
|
|
13065
|
-
|
|
13295
|
+
const finishTransition = (0, import_react47.useCallback)(() => {
|
|
13296
|
+
const nextSlot = pendingSlot;
|
|
13297
|
+
const previousScene = transitionFromRef.current;
|
|
13298
|
+
const nextScene = nextSlot === null ? null : slotsRef.current[nextSlot];
|
|
13299
|
+
if (nextSlot === null || !nextScene) {
|
|
13300
|
+
releaseInteraction();
|
|
13301
|
+
setPhase("idle");
|
|
13302
|
+
return;
|
|
13303
|
+
}
|
|
13304
|
+
setActiveSlot(nextSlot);
|
|
13305
|
+
setLiveSlot(nextSlot);
|
|
13306
|
+
setPendingSlot(null);
|
|
13307
|
+
setPhase("idle");
|
|
13308
|
+
const oldSnapshot = snapshot;
|
|
13309
|
+
setSnapshot(null);
|
|
13310
|
+
oldSnapshot?.dispose();
|
|
13311
|
+
releaseInteraction();
|
|
13312
|
+
if (previousScene) {
|
|
13313
|
+
onTransitionEnd?.({
|
|
13314
|
+
previousSceneId: previousScene.id,
|
|
13315
|
+
sceneId: nextScene.id,
|
|
13316
|
+
preset: transition.preset
|
|
13317
|
+
});
|
|
13318
|
+
}
|
|
13319
|
+
}, [onTransitionEnd, pendingSlot, releaseInteraction, snapshot, transition.preset]);
|
|
13320
|
+
const finishTransitionRef = (0, import_react47.useRef)(finishTransition);
|
|
13321
|
+
finishTransitionRef.current = finishTransition;
|
|
13322
|
+
const transitionRef = (0, import_react47.useRef)(transition);
|
|
13323
|
+
transitionRef.current = transition;
|
|
13324
|
+
const consumeDetailSignal = (0, import_react47.useCallback)((signal) => {
|
|
13325
|
+
const decision = acceptDetailWait(waitRef.current, signal);
|
|
13326
|
+
waitRef.current = decision.wait;
|
|
13327
|
+
if (!decision.start) {
|
|
13328
|
+
return;
|
|
13329
|
+
}
|
|
13330
|
+
if (waitTimerRef.current !== null) {
|
|
13331
|
+
clearTimeout(waitTimerRef.current);
|
|
13332
|
+
waitTimerRef.current = null;
|
|
13333
|
+
}
|
|
13334
|
+
if (!mountedRef.current) {
|
|
13335
|
+
return;
|
|
13336
|
+
}
|
|
13337
|
+
if (transitionRef.current.preset === "none") {
|
|
13338
|
+
finishTransitionRef.current();
|
|
13339
|
+
return;
|
|
13340
|
+
}
|
|
13341
|
+
setPhase("transitioning");
|
|
13342
|
+
setTransitionRunId((current) => current + 1);
|
|
13343
|
+
}, []);
|
|
13344
|
+
const handleCaptured = (0, import_react47.useCallback)((nextSnapshot) => {
|
|
13066
13345
|
if (captureReasonRef.current === "interrupt") {
|
|
13346
|
+
setSnapshot((current) => {
|
|
13347
|
+
current?.dispose();
|
|
13348
|
+
return nextSnapshot;
|
|
13349
|
+
});
|
|
13067
13350
|
startPreload(sceneMap.get(requestedSceneIdRef.current));
|
|
13068
13351
|
return;
|
|
13069
13352
|
}
|
|
13070
|
-
const sourceSlot = liveSlotRef.current;
|
|
13071
|
-
|
|
13072
|
-
|
|
13073
|
-
next
|
|
13074
|
-
|
|
13353
|
+
const sourceSlot = liveSlotRef.current;
|
|
13354
|
+
const incoming = pendingSlot === null ? null : slotsRef.current[pendingSlot];
|
|
13355
|
+
setSlots((current) => {
|
|
13356
|
+
const next = [...current];
|
|
13357
|
+
next[sourceSlot] = null;
|
|
13358
|
+
return next;
|
|
13359
|
+
});
|
|
13360
|
+
manager?.releaseUnused();
|
|
13361
|
+
if (pendingSlot !== null && incoming) {
|
|
13362
|
+
notifySceneReady(incoming);
|
|
13363
|
+
setLiveSlot(pendingSlot);
|
|
13364
|
+
}
|
|
13365
|
+
if (waitTimerRef.current !== null) {
|
|
13366
|
+
clearTimeout(waitTimerRef.current);
|
|
13367
|
+
waitTimerRef.current = null;
|
|
13368
|
+
}
|
|
13369
|
+
waitRef.current = null;
|
|
13370
|
+
let hold = null;
|
|
13371
|
+
if (incoming && waitForDetailMsRef.current > 0) {
|
|
13372
|
+
const now = performance.now();
|
|
13373
|
+
const generation = detailGenerationRef.current + 1;
|
|
13374
|
+
detailGenerationRef.current = generation;
|
|
13375
|
+
hold = planDetailHold({
|
|
13376
|
+
waitMs: waitForDetailMsRef.current,
|
|
13377
|
+
now,
|
|
13378
|
+
generation,
|
|
13379
|
+
sceneId: incoming.id
|
|
13380
|
+
});
|
|
13381
|
+
if (hold) {
|
|
13382
|
+
const deadline = hold.deadline;
|
|
13383
|
+
waitRef.current = hold;
|
|
13384
|
+
setDetailGeneration(generation);
|
|
13385
|
+
waitTimerRef.current = setTimeout(() => {
|
|
13386
|
+
consumeDetailSignal({
|
|
13387
|
+
kind: "timeout",
|
|
13388
|
+
generation,
|
|
13389
|
+
now: deadline
|
|
13390
|
+
});
|
|
13391
|
+
}, Math.max(0, deadline - performance.now()));
|
|
13392
|
+
}
|
|
13393
|
+
}
|
|
13394
|
+
const nextPhase = phaseAfterSnapshot(transition.preset, hold);
|
|
13395
|
+
if (nextPhase === "awaitingDetail") {
|
|
13396
|
+
setSnapshot((current) => {
|
|
13397
|
+
current?.dispose();
|
|
13398
|
+
return nextSnapshot;
|
|
13399
|
+
});
|
|
13400
|
+
setPhase("awaitingDetail");
|
|
13401
|
+
return;
|
|
13402
|
+
}
|
|
13403
|
+
if (nextPhase === "idle") {
|
|
13404
|
+
nextSnapshot.dispose();
|
|
13405
|
+
setSnapshot((current) => {
|
|
13406
|
+
current?.dispose();
|
|
13407
|
+
return null;
|
|
13408
|
+
});
|
|
13409
|
+
if (pendingSlot !== null) {
|
|
13410
|
+
setActiveSlot(pendingSlot);
|
|
13411
|
+
}
|
|
13412
|
+
setPendingSlot(null);
|
|
13413
|
+
setPhase("idle");
|
|
13414
|
+
releaseInteraction();
|
|
13415
|
+
const previousScene = transitionFromRef.current;
|
|
13416
|
+
if (previousScene && incoming) {
|
|
13417
|
+
onTransitionEnd?.({
|
|
13418
|
+
previousSceneId: previousScene.id,
|
|
13419
|
+
sceneId: incoming.id,
|
|
13420
|
+
preset: "none"
|
|
13421
|
+
});
|
|
13422
|
+
}
|
|
13423
|
+
return;
|
|
13424
|
+
}
|
|
13425
|
+
setSnapshot((current) => {
|
|
13426
|
+
current?.dispose();
|
|
13427
|
+
return nextSnapshot;
|
|
13075
13428
|
});
|
|
13076
|
-
manager?.releaseUnused();
|
|
13077
|
-
if (pendingSlot !== null) {
|
|
13078
|
-
notifySceneReady(slotsRef.current[pendingSlot]);
|
|
13079
|
-
setLiveSlot(pendingSlot);
|
|
13080
|
-
}
|
|
13081
13429
|
setPhase("transitioning");
|
|
13082
13430
|
setTransitionRunId((current) => current + 1);
|
|
13083
|
-
}, [
|
|
13084
|
-
|
|
13085
|
-
|
|
13086
|
-
|
|
13087
|
-
|
|
13088
|
-
|
|
13089
|
-
|
|
13090
|
-
|
|
13091
|
-
|
|
13092
|
-
|
|
13093
|
-
|
|
13094
|
-
|
|
13095
|
-
|
|
13096
|
-
|
|
13097
|
-
const oldSnapshot = snapshot;
|
|
13098
|
-
setSnapshot(null);
|
|
13099
|
-
oldSnapshot?.dispose();
|
|
13100
|
-
releaseInteraction();
|
|
13101
|
-
if (previousScene) {
|
|
13102
|
-
onTransitionEnd?.({
|
|
13103
|
-
previousSceneId: previousScene.id,
|
|
13104
|
-
sceneId: nextScene.id,
|
|
13105
|
-
preset: transition.preset
|
|
13106
|
-
});
|
|
13107
|
-
}
|
|
13108
|
-
}, [onTransitionEnd, pendingSlot, releaseInteraction, snapshot, transition.preset]);
|
|
13109
|
-
(0, import_react45.useEffect)(() => () => {
|
|
13431
|
+
}, [
|
|
13432
|
+
consumeDetailSignal,
|
|
13433
|
+
manager,
|
|
13434
|
+
notifySceneReady,
|
|
13435
|
+
onTransitionEnd,
|
|
13436
|
+
pendingSlot,
|
|
13437
|
+
releaseInteraction,
|
|
13438
|
+
sceneMap,
|
|
13439
|
+
startPreload,
|
|
13440
|
+
transition.preset
|
|
13441
|
+
]);
|
|
13442
|
+
const snapshotRef = (0, import_react47.useRef)(snapshot);
|
|
13443
|
+
snapshotRef.current = snapshot;
|
|
13444
|
+
(0, import_react47.useEffect)(() => () => {
|
|
13110
13445
|
releaseInteraction();
|
|
13111
|
-
|
|
13112
|
-
|
|
13113
|
-
|
|
13114
|
-
(0,
|
|
13446
|
+
snapshotRef.current?.dispose();
|
|
13447
|
+
snapshotRef.current = null;
|
|
13448
|
+
}, [releaseInteraction]);
|
|
13449
|
+
const { gl } = (0, import_fiber23.useThree)();
|
|
13450
|
+
(0, import_react47.useEffect)(() => {
|
|
13115
13451
|
const canvas = gl.domElement;
|
|
13116
13452
|
const onContextLost = (event) => {
|
|
13117
13453
|
event.preventDefault();
|
|
13118
13454
|
releaseInteraction();
|
|
13455
|
+
clearDetailWait(true);
|
|
13119
13456
|
manager?.dispose();
|
|
13120
13457
|
snapshot?.dispose();
|
|
13121
13458
|
setSnapshot(null);
|
|
@@ -13133,11 +13470,30 @@ function ScenesController({
|
|
|
13133
13470
|
canvas.removeEventListener("webglcontextlost", onContextLost);
|
|
13134
13471
|
canvas.removeEventListener("webglcontextrestored", onContextRestored);
|
|
13135
13472
|
};
|
|
13136
|
-
}, [gl, manager, releaseInteraction, snapshot]);
|
|
13473
|
+
}, [clearDetailWait, gl, manager, releaseInteraction, snapshot]);
|
|
13137
13474
|
const renderedScene = slots[liveSlot];
|
|
13138
13475
|
const snapshotVisible = snapshot !== null && (phase === "transitioning" || phase === "recapturing" || phase === "preloading");
|
|
13139
|
-
|
|
13140
|
-
|
|
13476
|
+
const slotSceneKey = `${slots[0]?.id ?? ""}
|
|
13477
|
+
${slots[1]?.id ?? ""}`;
|
|
13478
|
+
const detailReporters = (0, import_react47.useMemo)(() => {
|
|
13479
|
+
const [firstSceneId = "", secondSceneId = ""] = slotSceneKey.split("\n");
|
|
13480
|
+
const sceneIds = [firstSceneId, secondSceneId];
|
|
13481
|
+
return sceneIds.map((sceneId) => ({
|
|
13482
|
+
generation: detailGeneration,
|
|
13483
|
+
report: (ready) => {
|
|
13484
|
+
if (!ready || sceneId === "") {
|
|
13485
|
+
return;
|
|
13486
|
+
}
|
|
13487
|
+
consumeDetailSignal({
|
|
13488
|
+
kind: "ready",
|
|
13489
|
+
generation: detailGeneration,
|
|
13490
|
+
sceneId
|
|
13491
|
+
});
|
|
13492
|
+
}
|
|
13493
|
+
}));
|
|
13494
|
+
}, [consumeDetailSignal, detailGeneration, slotSceneKey]);
|
|
13495
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react47.Fragment, { children: [
|
|
13496
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
13141
13497
|
SnapshotCapture,
|
|
13142
13498
|
{
|
|
13143
13499
|
requestId: captureRequestId,
|
|
@@ -13149,23 +13505,30 @@ function ScenesController({
|
|
|
13149
13505
|
const source = slots[slot];
|
|
13150
13506
|
const isLive = slot === liveSlot;
|
|
13151
13507
|
const isPending = slot === pendingSlot;
|
|
13152
|
-
return /* @__PURE__ */ (0,
|
|
13153
|
-
|
|
13508
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
13509
|
+
SceneDetailContext.Provider,
|
|
13154
13510
|
{
|
|
13155
|
-
|
|
13156
|
-
|
|
13157
|
-
|
|
13158
|
-
|
|
13159
|
-
|
|
13160
|
-
|
|
13161
|
-
|
|
13511
|
+
value: detailReporters[slot],
|
|
13512
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
13513
|
+
SceneSource,
|
|
13514
|
+
{
|
|
13515
|
+
scene: source,
|
|
13516
|
+
visible: isLive,
|
|
13517
|
+
baseOnly: pendingSceneUsesBaseLayer(phase, isPending),
|
|
13518
|
+
onReady: () => handleReady(slot),
|
|
13519
|
+
onError: (error) => {
|
|
13520
|
+
if (source) {
|
|
13521
|
+
reportError(source.id, error);
|
|
13522
|
+
}
|
|
13523
|
+
}
|
|
13162
13524
|
}
|
|
13163
|
-
|
|
13525
|
+
)
|
|
13164
13526
|
},
|
|
13165
13527
|
`${slot}:${source?.id ?? "empty"}:${recoveryKey}`
|
|
13166
13528
|
);
|
|
13167
13529
|
}),
|
|
13168
|
-
|
|
13530
|
+
snapshot !== null && phase === "awaitingDetail" ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SnapshotHold, { snapshot }) : null,
|
|
13531
|
+
snapshotVisible ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
13169
13532
|
TransitionOverlay,
|
|
13170
13533
|
{
|
|
13171
13534
|
snapshot,
|
|
@@ -13188,11 +13551,11 @@ function Scenes({
|
|
|
13188
13551
|
...rest
|
|
13189
13552
|
}) {
|
|
13190
13553
|
const isControlled = controlledId !== void 0;
|
|
13191
|
-
const [internalId, setInternalId] = (0,
|
|
13554
|
+
const [internalId, setInternalId] = (0, import_react47.useState)(
|
|
13192
13555
|
() => controlledId ?? defaultActiveSceneId ?? scenes[0]?.id ?? ""
|
|
13193
13556
|
);
|
|
13194
13557
|
const resolvedId = isControlled ? controlledId : internalId;
|
|
13195
|
-
const requestSceneChange = (0,
|
|
13558
|
+
const requestSceneChange = (0, import_react47.useCallback)(
|
|
13196
13559
|
(id) => {
|
|
13197
13560
|
if (isControlled) {
|
|
13198
13561
|
onActiveSceneIdChange?.(id);
|
|
@@ -13202,13 +13565,13 @@ function Scenes({
|
|
|
13202
13565
|
},
|
|
13203
13566
|
[isControlled, onActiveSceneIdChange]
|
|
13204
13567
|
);
|
|
13205
|
-
const scenesRef = (0,
|
|
13568
|
+
const scenesRef = (0, import_react47.useRef)(scenes);
|
|
13206
13569
|
scenesRef.current = scenes;
|
|
13207
|
-
const resolvedIdRef = (0,
|
|
13570
|
+
const resolvedIdRef = (0, import_react47.useRef)(resolvedId);
|
|
13208
13571
|
resolvedIdRef.current = resolvedId;
|
|
13209
|
-
const host = (0,
|
|
13210
|
-
const phaseRef = (0,
|
|
13211
|
-
(0,
|
|
13572
|
+
const host = (0, import_react47.useContext)(ScenesHostContext);
|
|
13573
|
+
const phaseRef = (0, import_react47.useRef)("idle");
|
|
13574
|
+
(0, import_react47.useEffect)(() => {
|
|
13212
13575
|
if (!host) {
|
|
13213
13576
|
return;
|
|
13214
13577
|
}
|
|
@@ -13258,12 +13621,12 @@ function Scenes({
|
|
|
13258
13621
|
}
|
|
13259
13622
|
};
|
|
13260
13623
|
}, [host, requestSceneChange]);
|
|
13261
|
-
return /* @__PURE__ */ (0,
|
|
13624
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
13262
13625
|
TileTextureManagerProvider,
|
|
13263
13626
|
{
|
|
13264
13627
|
maxTextureMemoryMb,
|
|
13265
13628
|
maxConcurrentLoads: maxConcurrentTileLoads,
|
|
13266
|
-
children: /* @__PURE__ */ (0,
|
|
13629
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
13267
13630
|
ScenesController,
|
|
13268
13631
|
{
|
|
13269
13632
|
...rest,
|
|
@@ -13277,28 +13640,28 @@ function Scenes({
|
|
|
13277
13640
|
}
|
|
13278
13641
|
|
|
13279
13642
|
// src/hotspot/image-hotspot.tsx
|
|
13280
|
-
var
|
|
13281
|
-
var
|
|
13282
|
-
var
|
|
13643
|
+
var import_fiber26 = require("@react-three/fiber");
|
|
13644
|
+
var import_react51 = require("react");
|
|
13645
|
+
var import_three29 = require("three");
|
|
13283
13646
|
|
|
13284
13647
|
// src/hotspot/hotspot-anchor.tsx
|
|
13285
|
-
var
|
|
13286
|
-
var
|
|
13287
|
-
var
|
|
13648
|
+
var import_fiber25 = require("@react-three/fiber");
|
|
13649
|
+
var import_react50 = require("react");
|
|
13650
|
+
var import_three27 = require("three");
|
|
13288
13651
|
|
|
13289
13652
|
// src/hotspot/hotspot-tooltip.tsx
|
|
13290
|
-
var
|
|
13653
|
+
var import_react49 = require("react");
|
|
13291
13654
|
|
|
13292
13655
|
// src/webvr/stereo-html.tsx
|
|
13293
|
-
var
|
|
13294
|
-
var
|
|
13656
|
+
var import_fiber24 = require("@react-three/fiber");
|
|
13657
|
+
var import_react48 = require("react");
|
|
13295
13658
|
var import_client = require("react-dom/client");
|
|
13296
|
-
var
|
|
13297
|
-
var
|
|
13659
|
+
var import_three25 = require("three");
|
|
13660
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
13298
13661
|
function useFallbackStereoView() {
|
|
13299
|
-
const runtime = (0,
|
|
13662
|
+
const runtime = (0, import_react48.useContext)(WebVRRuntimeContext);
|
|
13300
13663
|
const host = runtime?.host ?? null;
|
|
13301
|
-
const fallback = (0,
|
|
13664
|
+
const fallback = (0, import_react48.useSyncExternalStore)(
|
|
13302
13665
|
(onStoreChange) => host ? subscribeWebVRHost(host, onStoreChange) : () => void 0,
|
|
13303
13666
|
() => isFallbackStereoMode(host?.snapshot.mode ?? null),
|
|
13304
13667
|
() => false
|
|
@@ -13313,10 +13676,10 @@ function ProjectedHtml({
|
|
|
13313
13676
|
stereoView,
|
|
13314
13677
|
eye
|
|
13315
13678
|
}) {
|
|
13316
|
-
const { camera, gl, events, size } = (0,
|
|
13317
|
-
const group = (0,
|
|
13318
|
-
const overlay = (0,
|
|
13319
|
-
const scratch = (0,
|
|
13679
|
+
const { camera, gl, events, size } = (0, import_fiber24.useThree)();
|
|
13680
|
+
const group = (0, import_react48.useRef)(null);
|
|
13681
|
+
const overlay = (0, import_react48.useRef)(null);
|
|
13682
|
+
const scratch = (0, import_react48.useRef)(new import_three25.Vector3());
|
|
13320
13683
|
const target = events.connected || gl.domElement.parentElement;
|
|
13321
13684
|
const updatePosition = () => {
|
|
13322
13685
|
const anchor = group.current;
|
|
@@ -13344,7 +13707,7 @@ function ProjectedHtml({
|
|
|
13344
13707
|
)
|
|
13345
13708
|
);
|
|
13346
13709
|
};
|
|
13347
|
-
(0,
|
|
13710
|
+
(0, import_react48.useLayoutEffect)(() => {
|
|
13348
13711
|
if (!target) return;
|
|
13349
13712
|
const element = document.createElement("div");
|
|
13350
13713
|
Object.assign(element.style, {
|
|
@@ -13362,9 +13725,9 @@ function ProjectedHtml({
|
|
|
13362
13725
|
queueMicrotask(() => root.unmount());
|
|
13363
13726
|
};
|
|
13364
13727
|
}, [target]);
|
|
13365
|
-
(0,
|
|
13728
|
+
(0, import_react48.useLayoutEffect)(() => {
|
|
13366
13729
|
overlay.current?.root.render(
|
|
13367
|
-
/* @__PURE__ */ (0,
|
|
13730
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
13368
13731
|
"div",
|
|
13369
13732
|
{
|
|
13370
13733
|
"aria-hidden": eye === "right" || void 0,
|
|
@@ -13375,19 +13738,19 @@ function ProjectedHtml({
|
|
|
13375
13738
|
);
|
|
13376
13739
|
updatePosition();
|
|
13377
13740
|
});
|
|
13378
|
-
(0,
|
|
13379
|
-
return /* @__PURE__ */ (0,
|
|
13741
|
+
(0, import_fiber24.useFrame)(updatePosition);
|
|
13742
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("group", { ref: group });
|
|
13380
13743
|
}
|
|
13381
13744
|
function PanoHtml(props) {
|
|
13382
13745
|
const stereoView = useFallbackStereoView();
|
|
13383
|
-
return stereoView ? /* @__PURE__ */ (0,
|
|
13384
|
-
/* @__PURE__ */ (0,
|
|
13385
|
-
/* @__PURE__ */ (0,
|
|
13386
|
-
] }) : /* @__PURE__ */ (0,
|
|
13746
|
+
return stereoView ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
13747
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ProjectedHtml, { ...props, stereoView, eye: "left" }),
|
|
13748
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ProjectedHtml, { ...props, stereoView, eye: "right" })
|
|
13749
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ProjectedHtml, { ...props });
|
|
13387
13750
|
}
|
|
13388
13751
|
|
|
13389
13752
|
// src/hotspot/hotspot-tooltip.tsx
|
|
13390
|
-
var
|
|
13753
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
13391
13754
|
var DEFAULT_HOTSPOT_TOOLTIP_OFFSET = 12;
|
|
13392
13755
|
var DEFAULT_HOTSPOT_TOOLTIP_APPEARANCE = {
|
|
13393
13756
|
background: "rgba(22, 22, 22, 0.72)",
|
|
@@ -13459,16 +13822,16 @@ function HotspotTooltip({
|
|
|
13459
13822
|
offset = DEFAULT_HOTSPOT_TOOLTIP_OFFSET,
|
|
13460
13823
|
appearance
|
|
13461
13824
|
}) {
|
|
13462
|
-
const [imageFailed, setImageFailed] = (0,
|
|
13463
|
-
(0,
|
|
13825
|
+
const [imageFailed, setImageFailed] = (0, import_react49.useState)(false);
|
|
13826
|
+
(0, import_react49.useEffect)(() => {
|
|
13464
13827
|
setImageFailed(false);
|
|
13465
13828
|
}, [content.image]);
|
|
13466
13829
|
const showImage = Boolean(content.image) && !imageFailed;
|
|
13467
|
-
const resolvedAppearance = (0,
|
|
13830
|
+
const resolvedAppearance = (0, import_react49.useMemo)(
|
|
13468
13831
|
() => resolveHotspotTooltipAppearance(appearance),
|
|
13469
13832
|
[appearance]
|
|
13470
13833
|
);
|
|
13471
|
-
const bubbleStyle = (0,
|
|
13834
|
+
const bubbleStyle = (0, import_react49.useMemo)(
|
|
13472
13835
|
() => ({
|
|
13473
13836
|
background: resolvedAppearance.background,
|
|
13474
13837
|
border: resolvedAppearance.border,
|
|
@@ -13490,8 +13853,8 @@ function HotspotTooltip({
|
|
|
13490
13853
|
if (!showImage && !content.text) {
|
|
13491
13854
|
return null;
|
|
13492
13855
|
}
|
|
13493
|
-
return /* @__PURE__ */ (0,
|
|
13494
|
-
showImage ? /* @__PURE__ */ (0,
|
|
13856
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(PanoHtml, { pointerEvents: "none", style: WRAPPER_STYLE, zIndexRange: [20, 10], children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "pano-hotspot-tooltip", role: "tooltip", style: bubbleStyle, children: [
|
|
13857
|
+
showImage ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
13495
13858
|
"img",
|
|
13496
13859
|
{
|
|
13497
13860
|
alt: content.imageAlt ?? content.text ?? "",
|
|
@@ -13500,7 +13863,7 @@ function HotspotTooltip({
|
|
|
13500
13863
|
src: content.image
|
|
13501
13864
|
}
|
|
13502
13865
|
) : null,
|
|
13503
|
-
content.text ? /* @__PURE__ */ (0,
|
|
13866
|
+
content.text ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
13504
13867
|
"p",
|
|
13505
13868
|
{
|
|
13506
13869
|
className: "pano-hotspot-tooltip-text",
|
|
@@ -13516,18 +13879,18 @@ function HotspotTooltip({
|
|
|
13516
13879
|
}
|
|
13517
13880
|
|
|
13518
13881
|
// src/hotspot/transform.ts
|
|
13519
|
-
var
|
|
13520
|
-
var LOCAL_FORWARD = new
|
|
13521
|
-
var CAMERA_POSITION = new
|
|
13882
|
+
var import_three26 = require("three");
|
|
13883
|
+
var LOCAL_FORWARD = new import_three26.Vector3(0, 0, 1);
|
|
13884
|
+
var CAMERA_POSITION = new import_three26.Vector3();
|
|
13522
13885
|
function applyHotspotTransform(group, camera, orientation2, surfaceQuaternion3, rotation, scaleMode, referenceFov, useAngularScale, worldWidth, worldHeight, distance) {
|
|
13523
13886
|
if (orientation2 === "billboard") {
|
|
13524
13887
|
group.quaternion.copy(camera.quaternion);
|
|
13525
13888
|
} else {
|
|
13526
13889
|
group.quaternion.copy(surfaceQuaternion3);
|
|
13527
13890
|
}
|
|
13528
|
-
group.rotateOnAxis(LOCAL_FORWARD,
|
|
13529
|
-
let scaleFactor = scaleMode === "fixed" && camera instanceof
|
|
13530
|
-
if (scaleMode === "fixed" && orientation2 === "billboard" && useAngularScale && camera instanceof
|
|
13891
|
+
group.rotateOnAxis(LOCAL_FORWARD, import_three26.MathUtils.degToRad(-rotation));
|
|
13892
|
+
let scaleFactor = scaleMode === "fixed" && camera instanceof import_three26.PerspectiveCamera ? fixedScaleFactor(camera.fov, referenceFov) : 1;
|
|
13893
|
+
if (scaleMode === "fixed" && orientation2 === "billboard" && useAngularScale && camera instanceof import_three26.PerspectiveCamera) {
|
|
13531
13894
|
group.updateWorldMatrix(true, false);
|
|
13532
13895
|
CAMERA_POSITION.setFromMatrixPosition(group.matrixWorld).applyMatrix4(
|
|
13533
13896
|
camera.matrixWorldInverse
|
|
@@ -13542,12 +13905,12 @@ function applyHotspotTransform(group, camera, orientation2, surfaceQuaternion3,
|
|
|
13542
13905
|
group.updateMatrixWorld();
|
|
13543
13906
|
}
|
|
13544
13907
|
function fixedScaleFactor(cameraFov, referenceFov) {
|
|
13545
|
-
const safeReferenceFov =
|
|
13546
|
-
return Math.tan(
|
|
13908
|
+
const safeReferenceFov = import_three26.MathUtils.clamp(referenceFov, 1, 179);
|
|
13909
|
+
return Math.tan(import_three26.MathUtils.degToRad(cameraFov) / 2) / Math.tan(import_three26.MathUtils.degToRad(safeReferenceFov) / 2);
|
|
13547
13910
|
}
|
|
13548
13911
|
|
|
13549
13912
|
// src/hotspot/hotspot-anchor.tsx
|
|
13550
|
-
var
|
|
13913
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
13551
13914
|
var DEFAULT_FLOATING_DISTANCE = 10;
|
|
13552
13915
|
var PANORAMA_RADIUS = DEFAULT_PANORAMA_RADIUS;
|
|
13553
13916
|
var PANORAMA_SURFACE_INSET = 4;
|
|
@@ -13555,27 +13918,27 @@ var DEFAULT_REFERENCE_FOV = 75;
|
|
|
13555
13918
|
var MIN_ANGULAR_SIZE = 0.01;
|
|
13556
13919
|
var MAX_ANGULAR_SIZE = 179;
|
|
13557
13920
|
var DRAG_EPSILON_DEGREES = 1e-3;
|
|
13558
|
-
var TOOLTIP_WORLD_BOX = new
|
|
13559
|
-
var TOOLTIP_LOCAL_BOX = new
|
|
13560
|
-
var TOOLTIP_CORNER = new
|
|
13561
|
-
var TOOLTIP_INVERSE = new
|
|
13562
|
-
var TOOLTIP_WORLD_CORNER = new
|
|
13563
|
-
var TOOLTIP_PROJECTED = new
|
|
13564
|
-
var TOOLTIP_RAY_ORIGIN = new
|
|
13565
|
-
var TOOLTIP_RAY_FAR = new
|
|
13566
|
-
var TOOLTIP_RAY_DIRECTION = new
|
|
13567
|
-
var TOOLTIP_RAY = new
|
|
13568
|
-
var TOOLTIP_PLANE = new
|
|
13569
|
-
var TOOLTIP_INTERSECTION = new
|
|
13570
|
-
var TOOLTIP_PLANE_NORMAL = new
|
|
13571
|
-
var TOOLTIP_PLANE_POINT = new
|
|
13921
|
+
var TOOLTIP_WORLD_BOX = new import_three27.Box3();
|
|
13922
|
+
var TOOLTIP_LOCAL_BOX = new import_three27.Box3();
|
|
13923
|
+
var TOOLTIP_CORNER = new import_three27.Vector3();
|
|
13924
|
+
var TOOLTIP_INVERSE = new import_three27.Matrix4();
|
|
13925
|
+
var TOOLTIP_WORLD_CORNER = new import_three27.Vector3();
|
|
13926
|
+
var TOOLTIP_PROJECTED = new import_three27.Vector3();
|
|
13927
|
+
var TOOLTIP_RAY_ORIGIN = new import_three27.Vector3();
|
|
13928
|
+
var TOOLTIP_RAY_FAR = new import_three27.Vector3();
|
|
13929
|
+
var TOOLTIP_RAY_DIRECTION = new import_three27.Vector3();
|
|
13930
|
+
var TOOLTIP_RAY = new import_three27.Ray();
|
|
13931
|
+
var TOOLTIP_PLANE = new import_three27.Plane();
|
|
13932
|
+
var TOOLTIP_INTERSECTION = new import_three27.Vector3();
|
|
13933
|
+
var TOOLTIP_PLANE_NORMAL = new import_three27.Vector3();
|
|
13934
|
+
var TOOLTIP_PLANE_POINT = new import_three27.Vector3();
|
|
13572
13935
|
var HOTSPOT_MODE_RENDERING = {
|
|
13573
13936
|
surface: { orientation: "surface", placement: "surface" },
|
|
13574
13937
|
billboard: { orientation: "billboard", placement: "floating" }
|
|
13575
13938
|
};
|
|
13576
13939
|
function angularSizeToWorldSize(size, radius) {
|
|
13577
|
-
const safeSize = Number.isFinite(size) ?
|
|
13578
|
-
return 2 * radius * Math.tan(
|
|
13940
|
+
const safeSize = Number.isFinite(size) ? import_three27.MathUtils.clamp(Math.abs(size), MIN_ANGULAR_SIZE, MAX_ANGULAR_SIZE) : MIN_ANGULAR_SIZE;
|
|
13941
|
+
return 2 * radius * Math.tan(import_three27.MathUtils.degToRad(safeSize) / 2);
|
|
13579
13942
|
}
|
|
13580
13943
|
function resolveScale(scale) {
|
|
13581
13944
|
return Number.isFinite(scale) && scale > 0 ? scale : 1;
|
|
@@ -13588,39 +13951,39 @@ function resolveDistance(placement, distance, width, height) {
|
|
|
13588
13951
|
if (!Number.isFinite(distance)) {
|
|
13589
13952
|
return DEFAULT_FLOATING_DISTANCE;
|
|
13590
13953
|
}
|
|
13591
|
-
return
|
|
13954
|
+
return import_three27.MathUtils.clamp(Math.abs(distance), 0.1, maximumDistance);
|
|
13592
13955
|
}
|
|
13593
13956
|
function maximumHotspotDistance(width, height) {
|
|
13594
|
-
const safeWidth =
|
|
13957
|
+
const safeWidth = import_three27.MathUtils.clamp(
|
|
13595
13958
|
Math.abs(Number.isFinite(width) ? width : MIN_ANGULAR_SIZE),
|
|
13596
13959
|
MIN_ANGULAR_SIZE,
|
|
13597
13960
|
MAX_ANGULAR_SIZE
|
|
13598
13961
|
);
|
|
13599
|
-
const safeHeight =
|
|
13962
|
+
const safeHeight = import_three27.MathUtils.clamp(
|
|
13600
13963
|
Math.abs(Number.isFinite(height) ? height : MIN_ANGULAR_SIZE),
|
|
13601
13964
|
MIN_ANGULAR_SIZE,
|
|
13602
13965
|
MAX_ANGULAR_SIZE
|
|
13603
13966
|
);
|
|
13604
13967
|
const cornerFactor = Math.hypot(
|
|
13605
13968
|
1,
|
|
13606
|
-
Math.tan(
|
|
13607
|
-
Math.tan(
|
|
13969
|
+
Math.tan(import_three27.MathUtils.degToRad(safeWidth) / 2),
|
|
13970
|
+
Math.tan(import_three27.MathUtils.degToRad(safeHeight) / 2)
|
|
13608
13971
|
);
|
|
13609
13972
|
return (PANORAMA_RADIUS - PANORAMA_SURFACE_INSET) / cornerFactor;
|
|
13610
13973
|
}
|
|
13611
13974
|
function createSurfaceQuaternion(position) {
|
|
13612
13975
|
const outward = panoPositionToVector3(position).normalize();
|
|
13613
13976
|
const inward = outward.clone().negate();
|
|
13614
|
-
const pitch =
|
|
13615
|
-
const yaw =
|
|
13616
|
-
const localUp = new
|
|
13977
|
+
const pitch = import_three27.MathUtils.degToRad(position.pitch);
|
|
13978
|
+
const yaw = import_three27.MathUtils.degToRad(position.yaw);
|
|
13979
|
+
const localUp = new import_three27.Vector3(
|
|
13617
13980
|
-Math.sin(pitch) * Math.sin(yaw),
|
|
13618
13981
|
Math.cos(pitch),
|
|
13619
13982
|
Math.sin(pitch) * Math.cos(yaw)
|
|
13620
13983
|
).normalize();
|
|
13621
13984
|
const localRight = localUp.clone().cross(inward).normalize();
|
|
13622
|
-
const basis = new
|
|
13623
|
-
return new
|
|
13985
|
+
const basis = new import_three27.Matrix4().makeBasis(localRight, localUp, inward);
|
|
13986
|
+
return new import_three27.Quaternion().setFromRotationMatrix(basis);
|
|
13624
13987
|
}
|
|
13625
13988
|
function makeInteractionEvent(id, position, event) {
|
|
13626
13989
|
return {
|
|
@@ -13633,7 +13996,7 @@ function makeInteractionEvent(id, position, event) {
|
|
|
13633
13996
|
function angularDistance(a, b) {
|
|
13634
13997
|
const aVector = panoPositionToVector3(a);
|
|
13635
13998
|
const bVector = panoPositionToVector3(b);
|
|
13636
|
-
return
|
|
13999
|
+
return import_three27.MathUtils.radToDeg(aVector.angleTo(bVector));
|
|
13637
14000
|
}
|
|
13638
14001
|
function isTooltipOpen(trigger, hovered, focused, pinned) {
|
|
13639
14002
|
switch (trigger) {
|
|
@@ -13864,24 +14227,24 @@ function HotspotAnchor({
|
|
|
13864
14227
|
onPositionChange,
|
|
13865
14228
|
onDragEnd
|
|
13866
14229
|
}) {
|
|
13867
|
-
const controlsRef = (0,
|
|
13868
|
-
const hotspotTargetRegistry = (0,
|
|
13869
|
-
const eventBus = (0,
|
|
14230
|
+
const controlsRef = (0, import_react50.useContext)(PanoramaViewContext);
|
|
14231
|
+
const hotspotTargetRegistry = (0, import_react50.useContext)(HotspotTargetRegistryContext);
|
|
14232
|
+
const eventBus = (0, import_react50.useContext)(PanoEventBusContext);
|
|
13870
14233
|
const cursorApi = usePanoCursor();
|
|
13871
|
-
const { camera, size } = (0,
|
|
13872
|
-
const groupRef = (0,
|
|
13873
|
-
const tooltipAnchorRef = (0,
|
|
13874
|
-
const dragStateRef = (0,
|
|
13875
|
-
const suppressNextClickRef = (0,
|
|
13876
|
-
const [hovered, setHovered] = (0,
|
|
13877
|
-
const [dragging, setDragging] = (0,
|
|
13878
|
-
const [pinned, setPinned] = (0,
|
|
13879
|
-
const tooltipContent = (0,
|
|
14234
|
+
const { camera, size } = (0, import_fiber25.useThree)();
|
|
14235
|
+
const groupRef = (0, import_react50.useRef)(null);
|
|
14236
|
+
const tooltipAnchorRef = (0, import_react50.useRef)(null);
|
|
14237
|
+
const dragStateRef = (0, import_react50.useRef)(null);
|
|
14238
|
+
const suppressNextClickRef = (0, import_react50.useRef)(false);
|
|
14239
|
+
const [hovered, setHovered] = (0, import_react50.useState)(false);
|
|
14240
|
+
const [dragging, setDragging] = (0, import_react50.useState)(false);
|
|
14241
|
+
const [pinned, setPinned] = (0, import_react50.useState)(false);
|
|
14242
|
+
const tooltipContent = (0, import_react50.useMemo)(
|
|
13880
14243
|
() => resolveHotspotTooltipContent(tooltip),
|
|
13881
14244
|
[tooltip]
|
|
13882
14245
|
);
|
|
13883
14246
|
const normalizedPosition = normalizePanoPosition(position);
|
|
13884
|
-
(0,
|
|
14247
|
+
(0, import_react50.useEffect)(() => {
|
|
13885
14248
|
if (!hotspotTargetRegistry) {
|
|
13886
14249
|
return;
|
|
13887
14250
|
}
|
|
@@ -13898,19 +14261,19 @@ function HotspotAnchor({
|
|
|
13898
14261
|
scaledWidth,
|
|
13899
14262
|
scaledHeight
|
|
13900
14263
|
);
|
|
13901
|
-
const worldPosition = (0,
|
|
14264
|
+
const worldPosition = (0, import_react50.useMemo)(
|
|
13902
14265
|
() => panoPositionToVector3(normalizedPosition, resolvedDistance),
|
|
13903
14266
|
[normalizedPosition.pitch, normalizedPosition.yaw, resolvedDistance]
|
|
13904
14267
|
);
|
|
13905
|
-
const surfaceQuaternion3 = (0,
|
|
14268
|
+
const surfaceQuaternion3 = (0, import_react50.useMemo)(
|
|
13906
14269
|
() => createSurfaceQuaternion(normalizedPosition),
|
|
13907
14270
|
[normalizedPosition.pitch, normalizedPosition.yaw]
|
|
13908
14271
|
);
|
|
13909
14272
|
const worldWidth = angularSizeToWorldSize(scaledWidth, resolvedDistance);
|
|
13910
14273
|
const worldHeight = angularSizeToWorldSize(scaledHeight, resolvedDistance);
|
|
13911
|
-
const focusGeometry = (0,
|
|
13912
|
-
const planeGeometry = new
|
|
13913
|
-
const geometry = new
|
|
14274
|
+
const focusGeometry = (0, import_react50.useMemo)(() => {
|
|
14275
|
+
const planeGeometry = new import_three27.PlaneGeometry(1, 1);
|
|
14276
|
+
const geometry = new import_three27.EdgesGeometry(planeGeometry);
|
|
13914
14277
|
planeGeometry.dispose();
|
|
13915
14278
|
return geometry;
|
|
13916
14279
|
}, []);
|
|
@@ -13935,14 +14298,14 @@ function HotspotAnchor({
|
|
|
13935
14298
|
});
|
|
13936
14299
|
const tooltipOpen = visible && tooltipContent !== null && isTooltipOpen(tooltipTrigger, hovered, focused, pinned);
|
|
13937
14300
|
const cursorClaimId = hotspotCursorClaimId(id);
|
|
13938
|
-
(0,
|
|
14301
|
+
(0, import_react50.useEffect)(
|
|
13939
14302
|
() => () => {
|
|
13940
14303
|
dragStateRef.current?.releaseInteractionLock();
|
|
13941
14304
|
dragStateRef.current = null;
|
|
13942
14305
|
},
|
|
13943
14306
|
[]
|
|
13944
14307
|
);
|
|
13945
|
-
(0,
|
|
14308
|
+
(0, import_react50.useEffect)(() => {
|
|
13946
14309
|
if (!cursorApi) {
|
|
13947
14310
|
return;
|
|
13948
14311
|
}
|
|
@@ -13964,14 +14327,14 @@ function HotspotAnchor({
|
|
|
13964
14327
|
hovered,
|
|
13965
14328
|
visible
|
|
13966
14329
|
]);
|
|
13967
|
-
(0,
|
|
14330
|
+
(0, import_react50.useEffect)(
|
|
13968
14331
|
() => () => {
|
|
13969
14332
|
cursorApi?.release(cursorClaimId);
|
|
13970
14333
|
},
|
|
13971
14334
|
[cursorApi, cursorClaimId]
|
|
13972
14335
|
);
|
|
13973
|
-
(0,
|
|
13974
|
-
(0,
|
|
14336
|
+
(0, import_react50.useEffect)(() => () => focusGeometry.dispose(), [focusGeometry]);
|
|
14337
|
+
(0, import_react50.useEffect)(() => {
|
|
13975
14338
|
if (tooltipTrigger !== "click") {
|
|
13976
14339
|
setPinned(false);
|
|
13977
14340
|
return;
|
|
@@ -13980,12 +14343,12 @@ function HotspotAnchor({
|
|
|
13980
14343
|
setPinned(false);
|
|
13981
14344
|
});
|
|
13982
14345
|
}, [eventBus, tooltipTrigger]);
|
|
13983
|
-
(0,
|
|
14346
|
+
(0, import_react50.useEffect)(() => {
|
|
13984
14347
|
if (tooltipTrigger !== "hover") {
|
|
13985
14348
|
setHovered(false);
|
|
13986
14349
|
}
|
|
13987
14350
|
}, [tooltipTrigger]);
|
|
13988
|
-
(0,
|
|
14351
|
+
(0, import_react50.useEffect)(() => {
|
|
13989
14352
|
if (acceptsPointer) {
|
|
13990
14353
|
return;
|
|
13991
14354
|
}
|
|
@@ -13998,7 +14361,7 @@ function HotspotAnchor({
|
|
|
13998
14361
|
dragStateRef.current = null;
|
|
13999
14362
|
setDragging(false);
|
|
14000
14363
|
}, [acceptsPointer]);
|
|
14001
|
-
(0,
|
|
14364
|
+
(0, import_react50.useLayoutEffect)(() => {
|
|
14002
14365
|
const group = groupRef.current;
|
|
14003
14366
|
if (!group) {
|
|
14004
14367
|
return;
|
|
@@ -14041,7 +14404,7 @@ function HotspotAnchor({
|
|
|
14041
14404
|
worldHeight,
|
|
14042
14405
|
worldWidth
|
|
14043
14406
|
]);
|
|
14044
|
-
(0,
|
|
14407
|
+
(0, import_fiber25.useFrame)((state) => {
|
|
14045
14408
|
const group = groupRef.current;
|
|
14046
14409
|
if (!group) {
|
|
14047
14410
|
return;
|
|
@@ -14100,7 +14463,7 @@ function HotspotAnchor({
|
|
|
14100
14463
|
setHovered(true);
|
|
14101
14464
|
}
|
|
14102
14465
|
};
|
|
14103
|
-
return /* @__PURE__ */ (0,
|
|
14466
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
14104
14467
|
"group",
|
|
14105
14468
|
{
|
|
14106
14469
|
ref: groupRef,
|
|
@@ -14177,18 +14540,18 @@ function HotspotAnchor({
|
|
|
14177
14540
|
} : void 0,
|
|
14178
14541
|
onPointerUp: acceptsPointer ? (event) => releasePointer(event, true) : void 0,
|
|
14179
14542
|
children: [
|
|
14180
|
-
focused ? focusContent ?? /* @__PURE__ */ (0,
|
|
14543
|
+
focused ? focusContent ?? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
14181
14544
|
"lineSegments",
|
|
14182
14545
|
{
|
|
14183
14546
|
geometry: focusGeometry,
|
|
14184
14547
|
position: [0, 0, 0.01],
|
|
14185
14548
|
renderOrder: renderOrder + 1,
|
|
14186
14549
|
scale: [1.12, 1.12, 1],
|
|
14187
|
-
children: /* @__PURE__ */ (0,
|
|
14550
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("lineBasicMaterial", { color: "#f5fbfc", depthTest: false })
|
|
14188
14551
|
}
|
|
14189
14552
|
) : null,
|
|
14190
14553
|
children,
|
|
14191
|
-
tooltipOpen && tooltipContent ? /* @__PURE__ */ (0,
|
|
14554
|
+
tooltipOpen && tooltipContent ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("group", { ref: tooltipAnchorRef, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
14192
14555
|
HotspotTooltip,
|
|
14193
14556
|
{
|
|
14194
14557
|
appearance: tooltipAppearance,
|
|
@@ -14203,10 +14566,10 @@ function HotspotAnchor({
|
|
|
14203
14566
|
}
|
|
14204
14567
|
|
|
14205
14568
|
// src/hotspot/hotspot-plane.tsx
|
|
14206
|
-
var
|
|
14207
|
-
var
|
|
14569
|
+
var import_three28 = require("three");
|
|
14570
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
14208
14571
|
var HOTSPOT_ALPHA_CUTOFF = 0.05;
|
|
14209
|
-
var SAMPLE_UV = new
|
|
14572
|
+
var SAMPLE_UV = new import_three28.Vector2();
|
|
14210
14573
|
var RAYCAST_HITS = [];
|
|
14211
14574
|
var IMAGE_DATA_CACHE = /* @__PURE__ */ new WeakMap();
|
|
14212
14575
|
function clampOpacity(opacity) {
|
|
@@ -14280,8 +14643,8 @@ function sampleTextureAlpha(texture, u, v) {
|
|
|
14280
14643
|
}
|
|
14281
14644
|
function hotspotPlaneRaycast(raycaster, intersects2) {
|
|
14282
14645
|
const material = Array.isArray(this.material) ? this.material[0] : this.material;
|
|
14283
|
-
if (!(material instanceof
|
|
14284
|
-
|
|
14646
|
+
if (!(material instanceof import_three28.MeshBasicMaterial)) {
|
|
14647
|
+
import_three28.Mesh.prototype.raycast.call(this, raycaster, intersects2);
|
|
14285
14648
|
return;
|
|
14286
14649
|
}
|
|
14287
14650
|
const cutoff = Math.max(material.alphaTest, HOTSPOT_ALPHA_CUTOFF);
|
|
@@ -14289,7 +14652,7 @@ function hotspotPlaneRaycast(raycaster, intersects2) {
|
|
|
14289
14652
|
return;
|
|
14290
14653
|
}
|
|
14291
14654
|
RAYCAST_HITS.length = 0;
|
|
14292
|
-
|
|
14655
|
+
import_three28.Mesh.prototype.raycast.call(this, raycaster, RAYCAST_HITS);
|
|
14293
14656
|
const map = material.map;
|
|
14294
14657
|
for (const hit of RAYCAST_HITS) {
|
|
14295
14658
|
if (!map || !hit.uv) {
|
|
@@ -14306,16 +14669,16 @@ function HotspotPlane({
|
|
|
14306
14669
|
map,
|
|
14307
14670
|
opacity
|
|
14308
14671
|
}) {
|
|
14309
|
-
return /* @__PURE__ */ (0,
|
|
14310
|
-
/* @__PURE__ */ (0,
|
|
14311
|
-
/* @__PURE__ */ (0,
|
|
14672
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("mesh", { raycast: hotspotPlaneRaycast, children: [
|
|
14673
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("planeGeometry", { args: [1, 1] }),
|
|
14674
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
14312
14675
|
PanoBasicMaterial,
|
|
14313
14676
|
{
|
|
14314
14677
|
target: "hotspot",
|
|
14315
14678
|
alphaTest: HOTSPOT_ALPHA_CUTOFF,
|
|
14316
14679
|
map,
|
|
14317
14680
|
opacity: map ? clampOpacity(opacity) : 0,
|
|
14318
|
-
side:
|
|
14681
|
+
side: import_three28.DoubleSide,
|
|
14319
14682
|
toneMapped: false,
|
|
14320
14683
|
transparent: true
|
|
14321
14684
|
}
|
|
@@ -14324,15 +14687,15 @@ function HotspotPlane({
|
|
|
14324
14687
|
}
|
|
14325
14688
|
|
|
14326
14689
|
// src/hotspot/image-hotspot.tsx
|
|
14327
|
-
var
|
|
14690
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
14328
14691
|
function useHotspotImageTexture(src, onLoad, onError) {
|
|
14329
|
-
const gl = (0,
|
|
14330
|
-
const [texture, setTexture] = (0,
|
|
14331
|
-
const onLoadRef = (0,
|
|
14332
|
-
const onErrorRef = (0,
|
|
14692
|
+
const gl = (0, import_fiber26.useThree)((state) => state.gl);
|
|
14693
|
+
const [texture, setTexture] = (0, import_react51.useState)(null);
|
|
14694
|
+
const onLoadRef = (0, import_react51.useRef)(onLoad);
|
|
14695
|
+
const onErrorRef = (0, import_react51.useRef)(onError);
|
|
14333
14696
|
onLoadRef.current = onLoad;
|
|
14334
14697
|
onErrorRef.current = onError;
|
|
14335
|
-
(0,
|
|
14698
|
+
(0, import_react51.useEffect)(() => {
|
|
14336
14699
|
let active = true;
|
|
14337
14700
|
setTexture(null);
|
|
14338
14701
|
if (!src) {
|
|
@@ -14340,7 +14703,7 @@ function useHotspotImageTexture(src, onLoad, onError) {
|
|
|
14340
14703
|
active = false;
|
|
14341
14704
|
};
|
|
14342
14705
|
}
|
|
14343
|
-
const loader = new
|
|
14706
|
+
const loader = new import_three29.TextureLoader();
|
|
14344
14707
|
loader.load(
|
|
14345
14708
|
src,
|
|
14346
14709
|
(loadedTexture) => {
|
|
@@ -14348,11 +14711,11 @@ function useHotspotImageTexture(src, onLoad, onError) {
|
|
|
14348
14711
|
loadedTexture.dispose();
|
|
14349
14712
|
return;
|
|
14350
14713
|
}
|
|
14351
|
-
loadedTexture.colorSpace =
|
|
14352
|
-
loadedTexture.wrapS =
|
|
14353
|
-
loadedTexture.wrapT =
|
|
14354
|
-
loadedTexture.magFilter =
|
|
14355
|
-
loadedTexture.minFilter =
|
|
14714
|
+
loadedTexture.colorSpace = import_three29.SRGBColorSpace;
|
|
14715
|
+
loadedTexture.wrapS = import_three29.ClampToEdgeWrapping;
|
|
14716
|
+
loadedTexture.wrapT = import_three29.ClampToEdgeWrapping;
|
|
14717
|
+
loadedTexture.magFilter = import_three29.LinearFilter;
|
|
14718
|
+
loadedTexture.minFilter = import_three29.LinearMipmapLinearFilter;
|
|
14356
14719
|
loadedTexture.generateMipmaps = true;
|
|
14357
14720
|
loadedTexture.anisotropy = gl.capabilities.getMaxAnisotropy();
|
|
14358
14721
|
loadedTexture.needsUpdate = true;
|
|
@@ -14370,7 +14733,7 @@ function useHotspotImageTexture(src, onLoad, onError) {
|
|
|
14370
14733
|
active = false;
|
|
14371
14734
|
};
|
|
14372
14735
|
}, [gl, src]);
|
|
14373
|
-
(0,
|
|
14736
|
+
(0, import_react51.useEffect)(
|
|
14374
14737
|
() => () => {
|
|
14375
14738
|
texture?.dispose();
|
|
14376
14739
|
},
|
|
@@ -14388,20 +14751,20 @@ function ImageHotspot({
|
|
|
14388
14751
|
...anchorProps
|
|
14389
14752
|
}) {
|
|
14390
14753
|
const texture = useHotspotImageTexture(src, onLoad, onError);
|
|
14391
|
-
return /* @__PURE__ */ (0,
|
|
14754
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(HotspotPlane, { map: texture, opacity }) });
|
|
14392
14755
|
}
|
|
14393
14756
|
|
|
14394
14757
|
// src/hotspot/polygon-hotspot.tsx
|
|
14395
|
-
var
|
|
14396
|
-
var
|
|
14758
|
+
var import_react53 = require("react");
|
|
14759
|
+
var import_three31 = require("three");
|
|
14397
14760
|
|
|
14398
14761
|
// src/hotspot/hotspot-stroke-line.tsx
|
|
14399
14762
|
var import_drei = require("@react-three/drei");
|
|
14400
|
-
var
|
|
14401
|
-
var
|
|
14402
|
-
var
|
|
14403
|
-
var
|
|
14404
|
-
var LINE_WORLD_POSITION = new
|
|
14763
|
+
var import_fiber27 = require("@react-three/fiber");
|
|
14764
|
+
var import_react52 = require("react");
|
|
14765
|
+
var import_three30 = require("three");
|
|
14766
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
14767
|
+
var LINE_WORLD_POSITION = new import_three30.Vector3();
|
|
14405
14768
|
function applyScreenSpaceDashScale(object, camera, viewportHeight) {
|
|
14406
14769
|
const material = object?.material;
|
|
14407
14770
|
if (!object || typeof material?.dashScale !== "number") {
|
|
@@ -14409,8 +14772,8 @@ function applyScreenSpaceDashScale(object, camera, viewportHeight) {
|
|
|
14409
14772
|
}
|
|
14410
14773
|
object.getWorldPosition(LINE_WORLD_POSITION);
|
|
14411
14774
|
const depth = Math.max(camera.position.distanceTo(LINE_WORLD_POSITION), 1);
|
|
14412
|
-
const fov = camera instanceof
|
|
14413
|
-
material.dashScale = viewportHeight / (2 * Math.tan(
|
|
14775
|
+
const fov = camera instanceof import_three30.PerspectiveCamera ? camera.fov : 75;
|
|
14776
|
+
material.dashScale = viewportHeight / (2 * Math.tan(import_three30.MathUtils.degToRad(fov) * 0.5) * depth);
|
|
14414
14777
|
}
|
|
14415
14778
|
function resolveDash(dashSize, gapSize) {
|
|
14416
14779
|
if (dashSize === void 0 || !Number.isFinite(dashSize) || dashSize <= 0) {
|
|
@@ -14431,22 +14794,22 @@ function HotspotStrokeLine({
|
|
|
14431
14794
|
dashSize,
|
|
14432
14795
|
gapSize
|
|
14433
14796
|
}) {
|
|
14434
|
-
const lineRef = (0,
|
|
14435
|
-
const { camera, size } = (0,
|
|
14797
|
+
const lineRef = (0, import_react52.useRef)(null);
|
|
14798
|
+
const { camera, size } = (0, import_fiber27.useThree)();
|
|
14436
14799
|
const dash = resolveDash(dashSize, gapSize);
|
|
14437
|
-
(0,
|
|
14800
|
+
(0, import_react52.useLayoutEffect)(() => {
|
|
14438
14801
|
if (!dash.dashed) {
|
|
14439
14802
|
return;
|
|
14440
14803
|
}
|
|
14441
14804
|
applyScreenSpaceDashScale(lineRef.current, camera, size.height);
|
|
14442
14805
|
}, [camera, dash.dashed, dash.dashSize, dash.gapSize, size.height]);
|
|
14443
|
-
(0,
|
|
14806
|
+
(0, import_fiber27.useFrame)((state) => {
|
|
14444
14807
|
if (!dash.dashed) {
|
|
14445
14808
|
return;
|
|
14446
14809
|
}
|
|
14447
14810
|
applyScreenSpaceDashScale(lineRef.current, state.camera, state.size.height);
|
|
14448
14811
|
});
|
|
14449
|
-
return /* @__PURE__ */ (0,
|
|
14812
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
14450
14813
|
import_drei.Line,
|
|
14451
14814
|
{
|
|
14452
14815
|
ref: lineRef,
|
|
@@ -14468,7 +14831,7 @@ function HotspotStrokeLine({
|
|
|
14468
14831
|
}
|
|
14469
14832
|
|
|
14470
14833
|
// src/hotspot/polygon-hotspot.tsx
|
|
14471
|
-
var
|
|
14834
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
14472
14835
|
var POLYGON_RADIUS = 990;
|
|
14473
14836
|
var MAX_FILL_SEGMENT_DEGREES = 7;
|
|
14474
14837
|
function cloneVertices(vertices) {
|
|
@@ -14503,7 +14866,7 @@ function intersects(a, b, c, d) {
|
|
|
14503
14866
|
}
|
|
14504
14867
|
function hasSelfIntersection(vertices) {
|
|
14505
14868
|
const points = vertices.map(
|
|
14506
|
-
(vertex) => new
|
|
14869
|
+
(vertex) => new import_three31.Vector2(vertex.unwrappedYaw, vertex.pitch)
|
|
14507
14870
|
);
|
|
14508
14871
|
for (let index = 0; index < points.length; index += 1) {
|
|
14509
14872
|
const nextIndex = (index + 1) % points.length;
|
|
@@ -14540,7 +14903,7 @@ function polygonContainsDirection(vertices, direction) {
|
|
|
14540
14903
|
}
|
|
14541
14904
|
function fitsHemisphere(vertices) {
|
|
14542
14905
|
const directions = vertices.map((vertex) => panoPositionToVector3(vertex).normalize());
|
|
14543
|
-
const candidates = [new
|
|
14906
|
+
const candidates = [new import_three31.Vector3()];
|
|
14544
14907
|
for (const direction of directions) {
|
|
14545
14908
|
candidates[0].add(direction);
|
|
14546
14909
|
candidates.push(direction.clone());
|
|
@@ -14564,7 +14927,7 @@ function validatePolygonVertices(vertices) {
|
|
|
14564
14927
|
if (hasSelfIntersection(unwrapped)) {
|
|
14565
14928
|
issues.push({ code: "self_intersection", message: "Polygon edges cannot cross." });
|
|
14566
14929
|
}
|
|
14567
|
-
if (polygonContainsDirection(normalized, new
|
|
14930
|
+
if (polygonContainsDirection(normalized, new import_three31.Vector3(0, 1, 0)) || polygonContainsDirection(normalized, new import_three31.Vector3(0, -1, 0))) {
|
|
14568
14931
|
issues.push({ code: "contains_pole", message: "Polygons cannot contain a panorama pole." });
|
|
14569
14932
|
}
|
|
14570
14933
|
if (!fitsHemisphere(normalized)) {
|
|
@@ -14575,7 +14938,7 @@ function validatePolygonVertices(vertices) {
|
|
|
14575
14938
|
function polygonCenter(vertices) {
|
|
14576
14939
|
const sum = vertices.reduce(
|
|
14577
14940
|
(total, vertex) => total.add(panoPositionToVector3(vertex).normalize()),
|
|
14578
|
-
new
|
|
14941
|
+
new import_three31.Vector3()
|
|
14579
14942
|
);
|
|
14580
14943
|
return sum.lengthSq() > 1e-8 ? vector3ToPanoPosition(sum) : normalizePanoPosition(vertices[0]);
|
|
14581
14944
|
}
|
|
@@ -14584,20 +14947,20 @@ function surfaceQuaternion(position) {
|
|
|
14584
14947
|
const inward = outward.clone().negate();
|
|
14585
14948
|
const pitch = position.pitch * Math.PI / 180;
|
|
14586
14949
|
const yaw = position.yaw * Math.PI / 180;
|
|
14587
|
-
const localUp = new
|
|
14950
|
+
const localUp = new import_three31.Vector3(
|
|
14588
14951
|
-Math.sin(pitch) * Math.sin(yaw),
|
|
14589
14952
|
Math.cos(pitch),
|
|
14590
14953
|
Math.sin(pitch) * Math.cos(yaw)
|
|
14591
14954
|
).normalize();
|
|
14592
|
-
return new
|
|
14593
|
-
new
|
|
14955
|
+
return new import_three31.Quaternion().setFromRotationMatrix(
|
|
14956
|
+
new import_three31.Matrix4().makeBasis(localUp.clone().cross(inward).normalize(), localUp, inward)
|
|
14594
14957
|
);
|
|
14595
14958
|
}
|
|
14596
14959
|
function makeWorldToLocal(center) {
|
|
14597
|
-
return new
|
|
14960
|
+
return new import_three31.Matrix4().compose(
|
|
14598
14961
|
panoPositionToVector3(center, POLYGON_RADIUS),
|
|
14599
14962
|
surfaceQuaternion(center),
|
|
14600
|
-
new
|
|
14963
|
+
new import_three31.Vector3(1, 1, 1)
|
|
14601
14964
|
).invert();
|
|
14602
14965
|
}
|
|
14603
14966
|
function projectedPoint(a, b, c, weightB, weightC, radius, worldToLocal) {
|
|
@@ -14652,8 +15015,8 @@ function addSubdividedTriangle(positions, indices, a, b, c, worldToLocal, steps)
|
|
|
14652
15015
|
}
|
|
14653
15016
|
function makeFillGeometry(vertices, center) {
|
|
14654
15017
|
const unwrapped = unwrapPolygonVertices(vertices);
|
|
14655
|
-
const contour = unwrapped.map((vertex) => new
|
|
14656
|
-
const triangles =
|
|
15018
|
+
const contour = unwrapped.map((vertex) => new import_three31.Vector2(vertex.unwrappedYaw, vertex.pitch));
|
|
15019
|
+
const triangles = import_three31.ShapeUtils.triangulateShape(contour, []);
|
|
14657
15020
|
const positions = [];
|
|
14658
15021
|
const indices = [];
|
|
14659
15022
|
const worldToLocal = makeWorldToLocal(center);
|
|
@@ -14669,7 +15032,7 @@ function makeFillGeometry(vertices, center) {
|
|
|
14669
15032
|
steps
|
|
14670
15033
|
);
|
|
14671
15034
|
}
|
|
14672
|
-
return new
|
|
15035
|
+
return new import_three31.BufferGeometry().setAttribute("position", new import_three31.Float32BufferAttribute(positions, 3)).setIndex(indices);
|
|
14673
15036
|
}
|
|
14674
15037
|
function makeStrokePositions(vertices, center) {
|
|
14675
15038
|
const points = [];
|
|
@@ -14724,24 +15087,24 @@ function PolygonHotspot({
|
|
|
14724
15087
|
onInvalid,
|
|
14725
15088
|
...anchorProps
|
|
14726
15089
|
}) {
|
|
14727
|
-
const issues = (0,
|
|
15090
|
+
const issues = (0, import_react53.useMemo)(() => validatePolygonVertices(vertices), [vertices]);
|
|
14728
15091
|
const valid = issues.length === 0;
|
|
14729
|
-
const center = (0,
|
|
14730
|
-
const fillGeometry = (0,
|
|
15092
|
+
const center = (0, import_react53.useMemo)(() => valid ? polygonCenter(vertices) : null, [valid, vertices]);
|
|
15093
|
+
const fillGeometry = (0, import_react53.useMemo)(
|
|
14731
15094
|
() => valid && center ? makeFillGeometry(vertices, center) : null,
|
|
14732
15095
|
[center, valid, vertices]
|
|
14733
15096
|
);
|
|
14734
|
-
const strokePoints = (0,
|
|
15097
|
+
const strokePoints = (0, import_react53.useMemo)(
|
|
14735
15098
|
() => valid && center ? makeStrokePositions(vertices, center) : null,
|
|
14736
15099
|
[center, valid, vertices]
|
|
14737
15100
|
);
|
|
14738
15101
|
const resolvedStrokeOpacity = Math.max(0, Math.min(strokeOpacity, 1));
|
|
14739
|
-
const startVerticesRef = (0,
|
|
15102
|
+
const startVerticesRef = (0, import_react53.useRef)(null);
|
|
14740
15103
|
const issuesKey = issues.map((issue) => issue.code).join(",");
|
|
14741
|
-
(0,
|
|
15104
|
+
(0, import_react53.useEffect)(() => {
|
|
14742
15105
|
if (!valid) onInvalid?.(issues);
|
|
14743
15106
|
}, [issues, issuesKey, onInvalid, valid]);
|
|
14744
|
-
(0,
|
|
15107
|
+
(0, import_react53.useEffect)(() => () => fillGeometry?.dispose(), [fillGeometry]);
|
|
14745
15108
|
if (!valid || !center || !fillGeometry || !strokePoints || strokePoints.length < 2) {
|
|
14746
15109
|
return null;
|
|
14747
15110
|
}
|
|
@@ -14756,7 +15119,7 @@ function PolygonHotspot({
|
|
|
14756
15119
|
startPosition: event.startPosition
|
|
14757
15120
|
});
|
|
14758
15121
|
};
|
|
14759
|
-
return /* @__PURE__ */ (0,
|
|
15122
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
14760
15123
|
HotspotAnchor,
|
|
14761
15124
|
{
|
|
14762
15125
|
...anchorProps,
|
|
@@ -14771,7 +15134,7 @@ function PolygonHotspot({
|
|
|
14771
15134
|
draggable,
|
|
14772
15135
|
interactive,
|
|
14773
15136
|
useAngularScale: false,
|
|
14774
|
-
focusContent: /* @__PURE__ */ (0,
|
|
15137
|
+
focusContent: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
14775
15138
|
HotspotStrokeLine,
|
|
14776
15139
|
{
|
|
14777
15140
|
color: "#75cbd3",
|
|
@@ -14793,17 +15156,17 @@ function PolygonHotspot({
|
|
|
14793
15156
|
startVerticesRef.current = null;
|
|
14794
15157
|
},
|
|
14795
15158
|
children: [
|
|
14796
|
-
/* @__PURE__ */ (0,
|
|
15159
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("mesh", { geometry: fillGeometry, renderOrder, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
14797
15160
|
"meshBasicMaterial",
|
|
14798
15161
|
{
|
|
14799
15162
|
color: fill,
|
|
14800
15163
|
depthWrite: false,
|
|
14801
15164
|
opacity: Math.max(0, Math.min(fillOpacity, 1)),
|
|
14802
|
-
side:
|
|
15165
|
+
side: import_three31.DoubleSide,
|
|
14803
15166
|
transparent: true
|
|
14804
15167
|
}
|
|
14805
15168
|
) }),
|
|
14806
|
-
/* @__PURE__ */ (0,
|
|
15169
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
14807
15170
|
HotspotStrokeLine,
|
|
14808
15171
|
{
|
|
14809
15172
|
color: stroke,
|
|
@@ -14821,9 +15184,9 @@ function PolygonHotspot({
|
|
|
14821
15184
|
}
|
|
14822
15185
|
|
|
14823
15186
|
// src/hotspot/polyline-hotspot.tsx
|
|
14824
|
-
var
|
|
14825
|
-
var
|
|
14826
|
-
var
|
|
15187
|
+
var import_react54 = require("react");
|
|
15188
|
+
var import_three32 = require("three");
|
|
15189
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
14827
15190
|
var POLYLINE_RADIUS = 990;
|
|
14828
15191
|
var MAX_SEGMENT_DEGREES = 7;
|
|
14829
15192
|
function cloneVertices2(vertices) {
|
|
@@ -14848,29 +15211,29 @@ function unwrapVertices(vertices) {
|
|
|
14848
15211
|
function polylineCenter(vertices) {
|
|
14849
15212
|
const sum = vertices.reduce(
|
|
14850
15213
|
(total, vertex) => total.add(panoPositionToVector3(vertex).normalize()),
|
|
14851
|
-
new
|
|
15214
|
+
new import_three32.Vector3()
|
|
14852
15215
|
);
|
|
14853
15216
|
return sum.lengthSq() > 1e-8 ? vector3ToPanoPosition(sum) : normalizePanoPosition(vertices[0]);
|
|
14854
15217
|
}
|
|
14855
15218
|
function surfaceQuaternion2(position) {
|
|
14856
15219
|
const outward = panoPositionToVector3(position).normalize();
|
|
14857
15220
|
const inward = outward.clone().negate();
|
|
14858
|
-
const pitch =
|
|
14859
|
-
const yaw =
|
|
14860
|
-
const localUp = new
|
|
15221
|
+
const pitch = import_three32.MathUtils.degToRad(position.pitch);
|
|
15222
|
+
const yaw = import_three32.MathUtils.degToRad(position.yaw);
|
|
15223
|
+
const localUp = new import_three32.Vector3(
|
|
14861
15224
|
-Math.sin(pitch) * Math.sin(yaw),
|
|
14862
15225
|
Math.cos(pitch),
|
|
14863
15226
|
Math.sin(pitch) * Math.cos(yaw)
|
|
14864
15227
|
).normalize();
|
|
14865
|
-
return new
|
|
14866
|
-
new
|
|
15228
|
+
return new import_three32.Quaternion().setFromRotationMatrix(
|
|
15229
|
+
new import_three32.Matrix4().makeBasis(localUp.clone().cross(inward).normalize(), localUp, inward)
|
|
14867
15230
|
);
|
|
14868
15231
|
}
|
|
14869
15232
|
function makeWorldToLocal2(center) {
|
|
14870
|
-
return new
|
|
15233
|
+
return new import_three32.Matrix4().compose(
|
|
14871
15234
|
panoPositionToVector3(center, POLYLINE_RADIUS),
|
|
14872
15235
|
surfaceQuaternion2(center),
|
|
14873
|
-
new
|
|
15236
|
+
new import_three32.Vector3(1, 1, 1)
|
|
14874
15237
|
).invert();
|
|
14875
15238
|
}
|
|
14876
15239
|
function subdivisionSteps(vertices) {
|
|
@@ -14885,7 +15248,7 @@ function subdivisionSteps(vertices) {
|
|
|
14885
15248
|
}
|
|
14886
15249
|
return Math.min(
|
|
14887
15250
|
8,
|
|
14888
|
-
Math.max(1, Math.ceil(
|
|
15251
|
+
Math.max(1, Math.ceil(import_three32.MathUtils.radToDeg(maxAngle) / MAX_SEGMENT_DEGREES))
|
|
14889
15252
|
);
|
|
14890
15253
|
}
|
|
14891
15254
|
function makeLinePositions(vertices, center) {
|
|
@@ -14940,16 +15303,16 @@ function PolylineHotspot({
|
|
|
14940
15303
|
onInvalid,
|
|
14941
15304
|
...anchorProps
|
|
14942
15305
|
}) {
|
|
14943
|
-
const issues = (0,
|
|
15306
|
+
const issues = (0, import_react54.useMemo)(() => validatePolylineVertices(vertices), [vertices]);
|
|
14944
15307
|
const valid = issues.length === 0;
|
|
14945
|
-
const center = (0,
|
|
14946
|
-
const linePoints = (0,
|
|
15308
|
+
const center = (0, import_react54.useMemo)(() => valid ? polylineCenter(vertices) : null, [valid, vertices]);
|
|
15309
|
+
const linePoints = (0, import_react54.useMemo)(
|
|
14947
15310
|
() => valid && center ? makeLinePositions(vertices, center) : null,
|
|
14948
15311
|
[center, valid, vertices]
|
|
14949
15312
|
);
|
|
14950
15313
|
const opacity = Math.max(0, Math.min(strokeOpacity, 1));
|
|
14951
|
-
const startVerticesRef = (0,
|
|
14952
|
-
(0,
|
|
15314
|
+
const startVerticesRef = (0, import_react54.useRef)(null);
|
|
15315
|
+
(0, import_react54.useEffect)(() => {
|
|
14953
15316
|
if (!valid) onInvalid?.(issues);
|
|
14954
15317
|
}, [issues, onInvalid, valid]);
|
|
14955
15318
|
if (!valid || !center || !linePoints || linePoints.length < 2) return null;
|
|
@@ -14963,7 +15326,7 @@ function PolylineHotspot({
|
|
|
14963
15326
|
startPosition: event.startPosition
|
|
14964
15327
|
});
|
|
14965
15328
|
};
|
|
14966
|
-
return /* @__PURE__ */ (0,
|
|
15329
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
14967
15330
|
HotspotAnchor,
|
|
14968
15331
|
{
|
|
14969
15332
|
...anchorProps,
|
|
@@ -14977,7 +15340,7 @@ function PolylineHotspot({
|
|
|
14977
15340
|
renderOrder,
|
|
14978
15341
|
draggable,
|
|
14979
15342
|
useAngularScale: false,
|
|
14980
|
-
focusContent: /* @__PURE__ */ (0,
|
|
15343
|
+
focusContent: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
14981
15344
|
HotspotStrokeLine,
|
|
14982
15345
|
{
|
|
14983
15346
|
color: "#75cbd3",
|
|
@@ -14998,7 +15361,7 @@ function PolylineHotspot({
|
|
|
14998
15361
|
emitVerticesChange(event, onDragEnd);
|
|
14999
15362
|
startVerticesRef.current = null;
|
|
15000
15363
|
},
|
|
15001
|
-
children: /* @__PURE__ */ (0,
|
|
15364
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
15002
15365
|
HotspotStrokeLine,
|
|
15003
15366
|
{
|
|
15004
15367
|
color: stroke,
|
|
@@ -15015,9 +15378,9 @@ function PolylineHotspot({
|
|
|
15015
15378
|
}
|
|
15016
15379
|
|
|
15017
15380
|
// src/hotspot/graphic-hotspot.tsx
|
|
15018
|
-
var
|
|
15019
|
-
var
|
|
15020
|
-
var
|
|
15381
|
+
var import_react55 = require("react");
|
|
15382
|
+
var import_three33 = require("three");
|
|
15383
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
15021
15384
|
var GRAPHIC_TEXTURE_SIZE = 512;
|
|
15022
15385
|
function resolveStrokeWidth(value) {
|
|
15023
15386
|
return Number.isFinite(value) ? Math.max(value, 0) : 8;
|
|
@@ -15195,23 +15558,23 @@ function createGraphicTexture(graphic, aspectWidth, aspectHeight) {
|
|
|
15195
15558
|
throw new Error("Canvas 2D is unavailable for this graphic hotspot.");
|
|
15196
15559
|
}
|
|
15197
15560
|
drawGraphic(context, graphic, aspectWidth, aspectHeight);
|
|
15198
|
-
const texture = new
|
|
15199
|
-
texture.colorSpace =
|
|
15200
|
-
texture.wrapS =
|
|
15201
|
-
texture.wrapT =
|
|
15202
|
-
texture.magFilter =
|
|
15203
|
-
texture.minFilter =
|
|
15561
|
+
const texture = new import_three33.CanvasTexture(canvas);
|
|
15562
|
+
texture.colorSpace = import_three33.SRGBColorSpace;
|
|
15563
|
+
texture.wrapS = import_three33.ClampToEdgeWrapping;
|
|
15564
|
+
texture.wrapT = import_three33.ClampToEdgeWrapping;
|
|
15565
|
+
texture.magFilter = import_three33.LinearFilter;
|
|
15566
|
+
texture.minFilter = import_three33.LinearMipmapLinearFilter;
|
|
15204
15567
|
texture.generateMipmaps = true;
|
|
15205
15568
|
texture.needsUpdate = true;
|
|
15206
15569
|
return texture;
|
|
15207
15570
|
}
|
|
15208
15571
|
function useGraphicTexture(graphic, aspectWidth, aspectHeight, onLoad, onError) {
|
|
15209
|
-
const [texture, setTexture] = (0,
|
|
15210
|
-
const onLoadRef = (0,
|
|
15211
|
-
const onErrorRef = (0,
|
|
15572
|
+
const [texture, setTexture] = (0, import_react55.useState)(null);
|
|
15573
|
+
const onLoadRef = (0, import_react55.useRef)(onLoad);
|
|
15574
|
+
const onErrorRef = (0, import_react55.useRef)(onError);
|
|
15212
15575
|
onLoadRef.current = onLoad;
|
|
15213
15576
|
onErrorRef.current = onError;
|
|
15214
|
-
(0,
|
|
15577
|
+
(0, import_react55.useEffect)(() => {
|
|
15215
15578
|
let nextTexture = null;
|
|
15216
15579
|
try {
|
|
15217
15580
|
nextTexture = createGraphicTexture(graphic, aspectWidth, aspectHeight);
|
|
@@ -15237,22 +15600,22 @@ function CanvasGraphicHotspot({
|
|
|
15237
15600
|
...anchorProps
|
|
15238
15601
|
}) {
|
|
15239
15602
|
const texture = useGraphicTexture(graphic, width, height, onLoad, onError);
|
|
15240
|
-
return /* @__PURE__ */ (0,
|
|
15603
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(HotspotPlane, { map: texture, opacity }) });
|
|
15241
15604
|
}
|
|
15242
15605
|
function GraphicHotspot(props) {
|
|
15243
15606
|
const { graphic, ...restProps } = props;
|
|
15244
15607
|
if (graphic.kind === "svg") {
|
|
15245
15608
|
const imageProps = restProps;
|
|
15246
|
-
return /* @__PURE__ */ (0,
|
|
15609
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ImageHotspot, { ...imageProps, src: graphic.src });
|
|
15247
15610
|
}
|
|
15248
|
-
return /* @__PURE__ */ (0,
|
|
15611
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CanvasGraphicHotspot, { ...restProps, graphic });
|
|
15249
15612
|
}
|
|
15250
15613
|
|
|
15251
15614
|
// src/hotspot/sequence-hotspot.tsx
|
|
15252
|
-
var
|
|
15253
|
-
var
|
|
15254
|
-
var
|
|
15255
|
-
var
|
|
15615
|
+
var import_fiber28 = require("@react-three/fiber");
|
|
15616
|
+
var import_react56 = require("react");
|
|
15617
|
+
var import_three34 = require("three");
|
|
15618
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
15256
15619
|
var DEFAULT_SEQUENCE_FPS = 12;
|
|
15257
15620
|
function resolveFps(value) {
|
|
15258
15621
|
return Number.isFinite(value) && value > 0 ? value : DEFAULT_SEQUENCE_FPS;
|
|
@@ -15266,13 +15629,13 @@ function useSpriteTexture({
|
|
|
15266
15629
|
onError,
|
|
15267
15630
|
onLoadProgress
|
|
15268
15631
|
}) {
|
|
15269
|
-
const gl = (0,
|
|
15270
|
-
const [texture, setTexture] = (0,
|
|
15271
|
-
const onErrorRef = (0,
|
|
15272
|
-
const onLoadProgressRef = (0,
|
|
15632
|
+
const gl = (0, import_fiber28.useThree)((state) => state.gl);
|
|
15633
|
+
const [texture, setTexture] = (0, import_react56.useState)(null);
|
|
15634
|
+
const onErrorRef = (0, import_react56.useRef)(onError);
|
|
15635
|
+
const onLoadProgressRef = (0, import_react56.useRef)(onLoadProgress);
|
|
15273
15636
|
onErrorRef.current = onError;
|
|
15274
15637
|
onLoadProgressRef.current = onLoadProgress;
|
|
15275
|
-
(0,
|
|
15638
|
+
(0, import_react56.useEffect)(() => {
|
|
15276
15639
|
let active = true;
|
|
15277
15640
|
setTexture(null);
|
|
15278
15641
|
if (!src) {
|
|
@@ -15281,7 +15644,7 @@ function useSpriteTexture({
|
|
|
15281
15644
|
active = false;
|
|
15282
15645
|
};
|
|
15283
15646
|
}
|
|
15284
|
-
const loader = new
|
|
15647
|
+
const loader = new import_three34.TextureLoader();
|
|
15285
15648
|
loader.load(
|
|
15286
15649
|
src,
|
|
15287
15650
|
(loadedTexture) => {
|
|
@@ -15289,11 +15652,11 @@ function useSpriteTexture({
|
|
|
15289
15652
|
loadedTexture.dispose();
|
|
15290
15653
|
return;
|
|
15291
15654
|
}
|
|
15292
|
-
loadedTexture.colorSpace =
|
|
15293
|
-
loadedTexture.wrapS =
|
|
15294
|
-
loadedTexture.wrapT =
|
|
15295
|
-
loadedTexture.magFilter =
|
|
15296
|
-
loadedTexture.minFilter =
|
|
15655
|
+
loadedTexture.colorSpace = import_three34.SRGBColorSpace;
|
|
15656
|
+
loadedTexture.wrapS = import_three34.ClampToEdgeWrapping;
|
|
15657
|
+
loadedTexture.wrapT = import_three34.ClampToEdgeWrapping;
|
|
15658
|
+
loadedTexture.magFilter = import_three34.LinearFilter;
|
|
15659
|
+
loadedTexture.minFilter = import_three34.LinearMipmapLinearFilter;
|
|
15297
15660
|
loadedTexture.generateMipmaps = true;
|
|
15298
15661
|
loadedTexture.anisotropy = gl.capabilities.getMaxAnisotropy();
|
|
15299
15662
|
loadedTexture.needsUpdate = true;
|
|
@@ -15313,7 +15676,7 @@ function useSpriteTexture({
|
|
|
15313
15676
|
active = false;
|
|
15314
15677
|
};
|
|
15315
15678
|
}, [gl, id, src]);
|
|
15316
|
-
(0,
|
|
15679
|
+
(0, import_react56.useEffect)(
|
|
15317
15680
|
() => () => {
|
|
15318
15681
|
texture?.dispose();
|
|
15319
15682
|
},
|
|
@@ -15342,24 +15705,24 @@ function SequenceHotspot({
|
|
|
15342
15705
|
const texture = useSpriteTexture({ id, src, onError, onLoadProgress });
|
|
15343
15706
|
const frameCount = resolveFrameCount(requestedFrameCount);
|
|
15344
15707
|
const safeFps = resolveFps(fps);
|
|
15345
|
-
const [frameIndex, setFrameIndex] = (0,
|
|
15346
|
-
const elapsedRef = (0,
|
|
15347
|
-
const frameIndexRef = (0,
|
|
15348
|
-
const endedRef = (0,
|
|
15349
|
-
const lastPlaybackStateRef = (0,
|
|
15350
|
-
const onFrameChangeRef = (0,
|
|
15351
|
-
const onPlaybackStateChangeRef = (0,
|
|
15352
|
-
const onEndedRef = (0,
|
|
15708
|
+
const [frameIndex, setFrameIndex] = (0, import_react56.useState)(0);
|
|
15709
|
+
const elapsedRef = (0, import_react56.useRef)(0);
|
|
15710
|
+
const frameIndexRef = (0, import_react56.useRef)(0);
|
|
15711
|
+
const endedRef = (0, import_react56.useRef)(false);
|
|
15712
|
+
const lastPlaybackStateRef = (0, import_react56.useRef)(null);
|
|
15713
|
+
const onFrameChangeRef = (0, import_react56.useRef)(onFrameChange);
|
|
15714
|
+
const onPlaybackStateChangeRef = (0, import_react56.useRef)(onPlaybackStateChange);
|
|
15715
|
+
const onEndedRef = (0, import_react56.useRef)(onEnded);
|
|
15353
15716
|
onFrameChangeRef.current = onFrameChange;
|
|
15354
15717
|
onPlaybackStateChangeRef.current = onPlaybackStateChange;
|
|
15355
15718
|
onEndedRef.current = onEnded;
|
|
15356
|
-
(0,
|
|
15719
|
+
(0, import_react56.useEffect)(() => {
|
|
15357
15720
|
elapsedRef.current = 0;
|
|
15358
15721
|
frameIndexRef.current = 0;
|
|
15359
15722
|
endedRef.current = false;
|
|
15360
15723
|
setFrameIndex(0);
|
|
15361
15724
|
}, [frameCount, frameDirection, src]);
|
|
15362
|
-
(0,
|
|
15725
|
+
(0, import_react56.useEffect)(() => {
|
|
15363
15726
|
if (!texture) {
|
|
15364
15727
|
return;
|
|
15365
15728
|
}
|
|
@@ -15373,13 +15736,13 @@ function SequenceHotspot({
|
|
|
15373
15736
|
);
|
|
15374
15737
|
texture.needsUpdate = true;
|
|
15375
15738
|
}, [frameCount, frameDirection, frameIndex, texture]);
|
|
15376
|
-
(0,
|
|
15739
|
+
(0, import_react56.useEffect)(() => {
|
|
15377
15740
|
if (!texture) {
|
|
15378
15741
|
return;
|
|
15379
15742
|
}
|
|
15380
15743
|
onFrameChangeRef.current?.({ id, index: 0, src });
|
|
15381
15744
|
}, [id, src, texture]);
|
|
15382
|
-
(0,
|
|
15745
|
+
(0, import_react56.useEffect)(() => {
|
|
15383
15746
|
if (!texture) {
|
|
15384
15747
|
return;
|
|
15385
15748
|
}
|
|
@@ -15398,7 +15761,7 @@ function SequenceHotspot({
|
|
|
15398
15761
|
onPlaybackStateChangeRef.current?.(nextState);
|
|
15399
15762
|
}
|
|
15400
15763
|
}, [playing, texture]);
|
|
15401
|
-
(0,
|
|
15764
|
+
(0, import_fiber28.useFrame)((_, deltaSeconds) => {
|
|
15402
15765
|
if (!texture || !playing || endedRef.current) {
|
|
15403
15766
|
return;
|
|
15404
15767
|
}
|
|
@@ -15428,14 +15791,14 @@ function SequenceHotspot({
|
|
|
15428
15791
|
onFrameChangeRef.current?.({ id, index: nextIndex, src });
|
|
15429
15792
|
}
|
|
15430
15793
|
});
|
|
15431
|
-
return /* @__PURE__ */ (0,
|
|
15794
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(HotspotAnchor, { ...anchorProps, id, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(HotspotPlane, { map: texture, opacity }) });
|
|
15432
15795
|
}
|
|
15433
15796
|
|
|
15434
15797
|
// src/hotspot/video-hotspot.tsx
|
|
15435
|
-
var
|
|
15436
|
-
var
|
|
15437
|
-
var
|
|
15438
|
-
var
|
|
15798
|
+
var import_fiber29 = require("@react-three/fiber");
|
|
15799
|
+
var import_react57 = require("react");
|
|
15800
|
+
var import_three35 = require("three");
|
|
15801
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
15439
15802
|
function clampVolume2(volume) {
|
|
15440
15803
|
if (!Number.isFinite(volume)) {
|
|
15441
15804
|
return 1;
|
|
@@ -15443,11 +15806,11 @@ function clampVolume2(volume) {
|
|
|
15443
15806
|
return Math.max(0, Math.min(volume, 1));
|
|
15444
15807
|
}
|
|
15445
15808
|
function usePosterTexture2(id, poster, onError) {
|
|
15446
|
-
const gl = (0,
|
|
15447
|
-
const [texture, setTexture] = (0,
|
|
15448
|
-
const onErrorRef = (0,
|
|
15809
|
+
const gl = (0, import_fiber29.useThree)((state) => state.gl);
|
|
15810
|
+
const [texture, setTexture] = (0, import_react57.useState)(null);
|
|
15811
|
+
const onErrorRef = (0, import_react57.useRef)(onError);
|
|
15449
15812
|
onErrorRef.current = onError;
|
|
15450
|
-
(0,
|
|
15813
|
+
(0, import_react57.useEffect)(() => {
|
|
15451
15814
|
let active = true;
|
|
15452
15815
|
setTexture(null);
|
|
15453
15816
|
if (!poster) {
|
|
@@ -15455,7 +15818,7 @@ function usePosterTexture2(id, poster, onError) {
|
|
|
15455
15818
|
active = false;
|
|
15456
15819
|
};
|
|
15457
15820
|
}
|
|
15458
|
-
const loader = new
|
|
15821
|
+
const loader = new import_three35.TextureLoader();
|
|
15459
15822
|
loader.load(
|
|
15460
15823
|
poster,
|
|
15461
15824
|
(loadedTexture) => {
|
|
@@ -15463,11 +15826,11 @@ function usePosterTexture2(id, poster, onError) {
|
|
|
15463
15826
|
loadedTexture.dispose();
|
|
15464
15827
|
return;
|
|
15465
15828
|
}
|
|
15466
|
-
loadedTexture.colorSpace =
|
|
15467
|
-
loadedTexture.wrapS =
|
|
15468
|
-
loadedTexture.wrapT =
|
|
15469
|
-
loadedTexture.magFilter =
|
|
15470
|
-
loadedTexture.minFilter =
|
|
15829
|
+
loadedTexture.colorSpace = import_three35.SRGBColorSpace;
|
|
15830
|
+
loadedTexture.wrapS = import_three35.ClampToEdgeWrapping;
|
|
15831
|
+
loadedTexture.wrapT = import_three35.ClampToEdgeWrapping;
|
|
15832
|
+
loadedTexture.magFilter = import_three35.LinearFilter;
|
|
15833
|
+
loadedTexture.minFilter = import_three35.LinearMipmapLinearFilter;
|
|
15471
15834
|
loadedTexture.generateMipmaps = true;
|
|
15472
15835
|
loadedTexture.anisotropy = gl.capabilities.getMaxAnisotropy();
|
|
15473
15836
|
loadedTexture.needsUpdate = true;
|
|
@@ -15484,7 +15847,7 @@ function usePosterTexture2(id, poster, onError) {
|
|
|
15484
15847
|
active = false;
|
|
15485
15848
|
};
|
|
15486
15849
|
}, [gl, id, poster]);
|
|
15487
|
-
(0,
|
|
15850
|
+
(0, import_react57.useEffect)(
|
|
15488
15851
|
() => () => {
|
|
15489
15852
|
texture?.dispose();
|
|
15490
15853
|
},
|
|
@@ -15502,14 +15865,14 @@ function useVideoResource({
|
|
|
15502
15865
|
poster,
|
|
15503
15866
|
src
|
|
15504
15867
|
}) {
|
|
15505
|
-
const [resource, setResource] = (0,
|
|
15506
|
-
const onEndedRef = (0,
|
|
15507
|
-
const onErrorRef = (0,
|
|
15508
|
-
const onPlaybackStateChangeRef = (0,
|
|
15868
|
+
const [resource, setResource] = (0, import_react57.useState)(null);
|
|
15869
|
+
const onEndedRef = (0, import_react57.useRef)(onEnded);
|
|
15870
|
+
const onErrorRef = (0, import_react57.useRef)(onError);
|
|
15871
|
+
const onPlaybackStateChangeRef = (0, import_react57.useRef)(onPlaybackStateChange);
|
|
15509
15872
|
onEndedRef.current = onEnded;
|
|
15510
15873
|
onErrorRef.current = onError;
|
|
15511
15874
|
onPlaybackStateChangeRef.current = onPlaybackStateChange;
|
|
15512
|
-
(0,
|
|
15875
|
+
(0, import_react57.useEffect)(() => {
|
|
15513
15876
|
if (!src) {
|
|
15514
15877
|
setResource(null);
|
|
15515
15878
|
return;
|
|
@@ -15526,12 +15889,12 @@ function useVideoResource({
|
|
|
15526
15889
|
video.setAttribute("webkit-playsinline", "true");
|
|
15527
15890
|
}
|
|
15528
15891
|
video.poster = poster ?? "";
|
|
15529
|
-
const texture = new
|
|
15530
|
-
texture.colorSpace =
|
|
15531
|
-
texture.wrapS =
|
|
15532
|
-
texture.wrapT =
|
|
15533
|
-
texture.magFilter =
|
|
15534
|
-
texture.minFilter =
|
|
15892
|
+
const texture = new import_three35.VideoTexture(video);
|
|
15893
|
+
texture.colorSpace = import_three35.SRGBColorSpace;
|
|
15894
|
+
texture.wrapS = import_three35.ClampToEdgeWrapping;
|
|
15895
|
+
texture.wrapT = import_three35.ClampToEdgeWrapping;
|
|
15896
|
+
texture.magFilter = import_three35.LinearFilter;
|
|
15897
|
+
texture.minFilter = import_three35.LinearFilter;
|
|
15535
15898
|
texture.generateMipmaps = false;
|
|
15536
15899
|
const notifyState = (state) => {
|
|
15537
15900
|
if (active) {
|
|
@@ -15616,11 +15979,11 @@ function VideoHotspot({
|
|
|
15616
15979
|
src
|
|
15617
15980
|
});
|
|
15618
15981
|
const posterTexture = usePosterTexture2(id, poster, onError);
|
|
15619
|
-
const onPlaybackErrorRef = (0,
|
|
15620
|
-
const onPlaybackStateChangeRef = (0,
|
|
15982
|
+
const onPlaybackErrorRef = (0, import_react57.useRef)(onPlaybackError);
|
|
15983
|
+
const onPlaybackStateChangeRef = (0, import_react57.useRef)(onPlaybackStateChange);
|
|
15621
15984
|
onPlaybackErrorRef.current = onPlaybackError;
|
|
15622
15985
|
onPlaybackStateChangeRef.current = onPlaybackStateChange;
|
|
15623
|
-
(0,
|
|
15986
|
+
(0, import_react57.useEffect)(() => {
|
|
15624
15987
|
if (!resource) {
|
|
15625
15988
|
return;
|
|
15626
15989
|
}
|
|
@@ -15637,7 +16000,7 @@ function VideoHotspot({
|
|
|
15637
16000
|
}
|
|
15638
16001
|
resource.video.preload = preload;
|
|
15639
16002
|
}, [loop, muted, playsInline, preload, resource, volume]);
|
|
15640
|
-
(0,
|
|
16003
|
+
(0, import_react57.useEffect)(() => {
|
|
15641
16004
|
if (!resource) {
|
|
15642
16005
|
return;
|
|
15643
16006
|
}
|
|
@@ -15660,14 +16023,14 @@ function VideoHotspot({
|
|
|
15660
16023
|
};
|
|
15661
16024
|
}, [playing, resource]);
|
|
15662
16025
|
const activeTexture = resource?.ready ? resource.texture : posterTexture;
|
|
15663
|
-
return /* @__PURE__ */ (0,
|
|
16026
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(HotspotAnchor, { ...anchorProps, id, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(HotspotPlane, { map: activeTexture, opacity }) });
|
|
15664
16027
|
}
|
|
15665
16028
|
|
|
15666
16029
|
// src/hotspot/audio-hotspot.tsx
|
|
15667
|
-
var
|
|
15668
|
-
var
|
|
15669
|
-
var
|
|
15670
|
-
var
|
|
16030
|
+
var import_fiber30 = require("@react-three/fiber");
|
|
16031
|
+
var import_react58 = require("react");
|
|
16032
|
+
var import_three36 = require("three");
|
|
16033
|
+
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
15671
16034
|
var SPEAKER_TEXTURE_SIZE = 512;
|
|
15672
16035
|
function paintSpeakerBody(context, center) {
|
|
15673
16036
|
context.fillStyle = "#f5fbfc";
|
|
@@ -15720,19 +16083,19 @@ function createSpeakerTexture(state) {
|
|
|
15720
16083
|
return exhaustive;
|
|
15721
16084
|
}
|
|
15722
16085
|
}
|
|
15723
|
-
const texture = new
|
|
15724
|
-
texture.colorSpace =
|
|
15725
|
-
texture.wrapS =
|
|
15726
|
-
texture.wrapT =
|
|
15727
|
-
texture.magFilter =
|
|
15728
|
-
texture.minFilter =
|
|
16086
|
+
const texture = new import_three36.CanvasTexture(canvas);
|
|
16087
|
+
texture.colorSpace = import_three36.SRGBColorSpace;
|
|
16088
|
+
texture.wrapS = import_three36.ClampToEdgeWrapping;
|
|
16089
|
+
texture.wrapT = import_three36.ClampToEdgeWrapping;
|
|
16090
|
+
texture.magFilter = import_three36.LinearFilter;
|
|
16091
|
+
texture.minFilter = import_three36.LinearMipmapLinearFilter;
|
|
15729
16092
|
texture.generateMipmaps = true;
|
|
15730
16093
|
texture.needsUpdate = true;
|
|
15731
16094
|
return texture;
|
|
15732
16095
|
}
|
|
15733
16096
|
function useSpeakerTextures(enabled) {
|
|
15734
|
-
const [textures, setTextures] = (0,
|
|
15735
|
-
(0,
|
|
16097
|
+
const [textures, setTextures] = (0, import_react58.useState)({ playing: null, stopped: null });
|
|
16098
|
+
(0, import_react58.useEffect)(() => {
|
|
15736
16099
|
if (!enabled) {
|
|
15737
16100
|
setTextures({ playing: null, stopped: null });
|
|
15738
16101
|
return;
|
|
@@ -15748,11 +16111,11 @@ function useSpeakerTextures(enabled) {
|
|
|
15748
16111
|
return textures;
|
|
15749
16112
|
}
|
|
15750
16113
|
function useIconTexture(icon, enabled, onError, id) {
|
|
15751
|
-
const gl = (0,
|
|
15752
|
-
const [texture, setTexture] = (0,
|
|
15753
|
-
const onErrorRef = (0,
|
|
16114
|
+
const gl = (0, import_fiber30.useThree)((state) => state.gl);
|
|
16115
|
+
const [texture, setTexture] = (0, import_react58.useState)(null);
|
|
16116
|
+
const onErrorRef = (0, import_react58.useRef)(onError);
|
|
15754
16117
|
onErrorRef.current = onError;
|
|
15755
|
-
(0,
|
|
16118
|
+
(0, import_react58.useEffect)(() => {
|
|
15756
16119
|
let active = true;
|
|
15757
16120
|
setTexture(null);
|
|
15758
16121
|
if (!enabled || !icon) {
|
|
@@ -15760,7 +16123,7 @@ function useIconTexture(icon, enabled, onError, id) {
|
|
|
15760
16123
|
active = false;
|
|
15761
16124
|
};
|
|
15762
16125
|
}
|
|
15763
|
-
const loader = new
|
|
16126
|
+
const loader = new import_three36.TextureLoader();
|
|
15764
16127
|
loader.load(
|
|
15765
16128
|
icon,
|
|
15766
16129
|
(loadedTexture) => {
|
|
@@ -15768,11 +16131,11 @@ function useIconTexture(icon, enabled, onError, id) {
|
|
|
15768
16131
|
loadedTexture.dispose();
|
|
15769
16132
|
return;
|
|
15770
16133
|
}
|
|
15771
|
-
loadedTexture.colorSpace =
|
|
15772
|
-
loadedTexture.wrapS =
|
|
15773
|
-
loadedTexture.wrapT =
|
|
15774
|
-
loadedTexture.magFilter =
|
|
15775
|
-
loadedTexture.minFilter =
|
|
16134
|
+
loadedTexture.colorSpace = import_three36.SRGBColorSpace;
|
|
16135
|
+
loadedTexture.wrapS = import_three36.ClampToEdgeWrapping;
|
|
16136
|
+
loadedTexture.wrapT = import_three36.ClampToEdgeWrapping;
|
|
16137
|
+
loadedTexture.magFilter = import_three36.LinearFilter;
|
|
16138
|
+
loadedTexture.minFilter = import_three36.LinearMipmapLinearFilter;
|
|
15776
16139
|
loadedTexture.generateMipmaps = true;
|
|
15777
16140
|
loadedTexture.anisotropy = gl.capabilities.getMaxAnisotropy();
|
|
15778
16141
|
loadedTexture.needsUpdate = true;
|
|
@@ -15789,7 +16152,7 @@ function useIconTexture(icon, enabled, onError, id) {
|
|
|
15789
16152
|
active = false;
|
|
15790
16153
|
};
|
|
15791
16154
|
}, [enabled, gl, icon, id]);
|
|
15792
|
-
(0,
|
|
16155
|
+
(0, import_react58.useEffect)(
|
|
15793
16156
|
() => () => {
|
|
15794
16157
|
texture?.dispose();
|
|
15795
16158
|
},
|
|
@@ -15808,13 +16171,13 @@ function useAudioHowl({
|
|
|
15808
16171
|
playing,
|
|
15809
16172
|
src
|
|
15810
16173
|
}) {
|
|
15811
|
-
const [howl, setHowl] = (0,
|
|
15812
|
-
const playingRef = (0,
|
|
15813
|
-
const loopRef = (0,
|
|
15814
|
-
const onEndedRef = (0,
|
|
15815
|
-
const onErrorRef = (0,
|
|
15816
|
-
const onPlaybackErrorRef = (0,
|
|
15817
|
-
const onPlaybackStateChangeRef = (0,
|
|
16174
|
+
const [howl, setHowl] = (0, import_react58.useState)(null);
|
|
16175
|
+
const playingRef = (0, import_react58.useRef)(playing);
|
|
16176
|
+
const loopRef = (0, import_react58.useRef)(loop ?? false);
|
|
16177
|
+
const onEndedRef = (0, import_react58.useRef)(onEnded);
|
|
16178
|
+
const onErrorRef = (0, import_react58.useRef)(onError);
|
|
16179
|
+
const onPlaybackErrorRef = (0, import_react58.useRef)(onPlaybackError);
|
|
16180
|
+
const onPlaybackStateChangeRef = (0, import_react58.useRef)(onPlaybackStateChange);
|
|
15818
16181
|
playingRef.current = playing;
|
|
15819
16182
|
loopRef.current = loop ?? false;
|
|
15820
16183
|
onEndedRef.current = onEnded;
|
|
@@ -15822,7 +16185,7 @@ function useAudioHowl({
|
|
|
15822
16185
|
onPlaybackErrorRef.current = onPlaybackError;
|
|
15823
16186
|
onPlaybackStateChangeRef.current = onPlaybackStateChange;
|
|
15824
16187
|
const sourcesKey = sourceList(src).join("\0");
|
|
15825
|
-
(0,
|
|
16188
|
+
(0, import_react58.useEffect)(() => {
|
|
15826
16189
|
const sources = sourcesKey.length > 0 ? sourcesKey.split("\0") : [];
|
|
15827
16190
|
if (sources.length === 0) {
|
|
15828
16191
|
setHowl(null);
|
|
@@ -15859,7 +16222,7 @@ function useAudioHowl({
|
|
|
15859
16222
|
handle.dispose();
|
|
15860
16223
|
};
|
|
15861
16224
|
}, [crossOrigin, id, sourcesKey]);
|
|
15862
|
-
(0,
|
|
16225
|
+
(0, import_react58.useEffect)(() => {
|
|
15863
16226
|
howl?.loop(loop ?? false);
|
|
15864
16227
|
}, [howl, loop]);
|
|
15865
16228
|
return howl;
|
|
@@ -15887,7 +16250,7 @@ function AudioHotspot({
|
|
|
15887
16250
|
...anchorProps
|
|
15888
16251
|
}) {
|
|
15889
16252
|
usePanoMediaActivationIntent(playing);
|
|
15890
|
-
const camera = (0,
|
|
16253
|
+
const camera = (0, import_fiber30.useThree)((state) => state.camera);
|
|
15891
16254
|
const howl = useAudioHowl({
|
|
15892
16255
|
crossOrigin,
|
|
15893
16256
|
id,
|
|
@@ -15903,15 +16266,15 @@ function AudioHotspot({
|
|
|
15903
16266
|
const stoppedIconTexture = useIconTexture(icon, marker, onError, id);
|
|
15904
16267
|
const playingIconTexture = useIconTexture(playingIcon, marker, onError, id);
|
|
15905
16268
|
const markerTexture = playing ? playingIconTexture ?? stoppedIconTexture ?? speakerTextures.playing : stoppedIconTexture ?? speakerTextures.stopped;
|
|
15906
|
-
const playingRef = (0,
|
|
16269
|
+
const playingRef = (0, import_react58.useRef)(playing);
|
|
15907
16270
|
playingRef.current = playing;
|
|
15908
|
-
const mutedRef = (0,
|
|
15909
|
-
const volumeRef = (0,
|
|
15910
|
-
const rangeRef = (0,
|
|
16271
|
+
const mutedRef = (0, import_react58.useRef)(muted);
|
|
16272
|
+
const volumeRef = (0, import_react58.useRef)(volume);
|
|
16273
|
+
const rangeRef = (0, import_react58.useRef)(range);
|
|
15911
16274
|
mutedRef.current = muted;
|
|
15912
16275
|
volumeRef.current = volume;
|
|
15913
16276
|
rangeRef.current = range;
|
|
15914
|
-
(0,
|
|
16277
|
+
(0, import_react58.useEffect)(() => {
|
|
15915
16278
|
if (!howl) {
|
|
15916
16279
|
return;
|
|
15917
16280
|
}
|
|
@@ -15921,7 +16284,7 @@ function AudioHotspot({
|
|
|
15921
16284
|
}
|
|
15922
16285
|
howl.play();
|
|
15923
16286
|
}, [howl, playing]);
|
|
15924
|
-
(0,
|
|
16287
|
+
(0, import_react58.useEffect)(() => {
|
|
15925
16288
|
if (!howl || !pauseWhenHidden) {
|
|
15926
16289
|
return;
|
|
15927
16290
|
}
|
|
@@ -15939,7 +16302,7 @@ function AudioHotspot({
|
|
|
15939
16302
|
document.removeEventListener("visibilitychange", handleVisibility);
|
|
15940
16303
|
};
|
|
15941
16304
|
}, [howl, pauseWhenHidden]);
|
|
15942
|
-
(0,
|
|
16305
|
+
(0, import_fiber30.useFrame)(() => {
|
|
15943
16306
|
if (!howl) {
|
|
15944
16307
|
return;
|
|
15945
16308
|
}
|
|
@@ -15952,13 +16315,13 @@ function AudioHotspot({
|
|
|
15952
16315
|
howl.mute(mutedRef.current);
|
|
15953
16316
|
howl.volume(clampAudioVolume(volumeRef.current) * spatial.gain);
|
|
15954
16317
|
});
|
|
15955
|
-
return /* @__PURE__ */ (0,
|
|
16318
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(HotspotAnchor, { ...anchorProps, id, height, width, children: marker ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(HotspotPlane, { map: markerTexture, opacity }) : null });
|
|
15956
16319
|
}
|
|
15957
16320
|
|
|
15958
16321
|
// src/hotspot/text-hotspot.tsx
|
|
15959
|
-
var
|
|
15960
|
-
var
|
|
15961
|
-
var
|
|
16322
|
+
var import_react59 = require("react");
|
|
16323
|
+
var import_three37 = require("three");
|
|
16324
|
+
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
15962
16325
|
var TEXT_TEXTURE_LONG_SIDE = 1024;
|
|
15963
16326
|
var DEFAULT_FONT_FAMILY = "system-ui, sans-serif";
|
|
15964
16327
|
var DEFAULT_FONT_SIZE = 96;
|
|
@@ -16167,23 +16530,23 @@ function createTextTexture(text, width, height, style) {
|
|
|
16167
16530
|
throw new Error("Canvas 2D is unavailable for this text hotspot.");
|
|
16168
16531
|
}
|
|
16169
16532
|
drawTextHotspot(context, canvasWidth, canvasHeight, text, style);
|
|
16170
|
-
const texture = new
|
|
16171
|
-
texture.colorSpace =
|
|
16172
|
-
texture.wrapS =
|
|
16173
|
-
texture.wrapT =
|
|
16174
|
-
texture.magFilter =
|
|
16175
|
-
texture.minFilter =
|
|
16533
|
+
const texture = new import_three37.CanvasTexture(canvas);
|
|
16534
|
+
texture.colorSpace = import_three37.SRGBColorSpace;
|
|
16535
|
+
texture.wrapS = import_three37.ClampToEdgeWrapping;
|
|
16536
|
+
texture.wrapT = import_three37.ClampToEdgeWrapping;
|
|
16537
|
+
texture.magFilter = import_three37.LinearFilter;
|
|
16538
|
+
texture.minFilter = import_three37.LinearMipmapLinearFilter;
|
|
16176
16539
|
texture.generateMipmaps = true;
|
|
16177
16540
|
texture.needsUpdate = true;
|
|
16178
16541
|
return texture;
|
|
16179
16542
|
}
|
|
16180
16543
|
function useTextTexture(text, width, height, style, onLoad, onError) {
|
|
16181
|
-
const [texture, setTexture] = (0,
|
|
16182
|
-
const onLoadRef = (0,
|
|
16183
|
-
const onErrorRef = (0,
|
|
16544
|
+
const [texture, setTexture] = (0, import_react59.useState)(null);
|
|
16545
|
+
const onLoadRef = (0, import_react59.useRef)(onLoad);
|
|
16546
|
+
const onErrorRef = (0, import_react59.useRef)(onError);
|
|
16184
16547
|
onLoadRef.current = onLoad;
|
|
16185
16548
|
onErrorRef.current = onError;
|
|
16186
|
-
(0,
|
|
16549
|
+
(0, import_react59.useEffect)(() => {
|
|
16187
16550
|
let cancelled = false;
|
|
16188
16551
|
let nextTexture = null;
|
|
16189
16552
|
const run = async () => {
|
|
@@ -16276,13 +16639,13 @@ function TextHotspot({
|
|
|
16276
16639
|
whiteSpace
|
|
16277
16640
|
};
|
|
16278
16641
|
const texture = useTextTexture(text, width, height, style, onLoad, onError);
|
|
16279
|
-
return /* @__PURE__ */ (0,
|
|
16642
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(HotspotPlane, { map: texture, opacity }) });
|
|
16280
16643
|
}
|
|
16281
16644
|
|
|
16282
16645
|
// src/hotspot/iframe-hotspot.tsx
|
|
16283
16646
|
var import_drei2 = require("@react-three/drei");
|
|
16284
|
-
var
|
|
16285
|
-
var
|
|
16647
|
+
var import_three38 = require("three");
|
|
16648
|
+
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
16286
16649
|
var IFRAME_LONG_SIDE = 800;
|
|
16287
16650
|
var CSS3D_DISTANCE_FACTOR = 400;
|
|
16288
16651
|
var DEFAULT_SANDBOX = "allow-scripts allow-popups allow-forms";
|
|
@@ -16339,7 +16702,7 @@ function IframeHotspot({
|
|
|
16339
16702
|
interactive,
|
|
16340
16703
|
pointerEvents
|
|
16341
16704
|
);
|
|
16342
|
-
return /* @__PURE__ */ (0,
|
|
16705
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
16343
16706
|
HotspotAnchor,
|
|
16344
16707
|
{
|
|
16345
16708
|
...anchorProps,
|
|
@@ -16348,20 +16711,20 @@ function IframeHotspot({
|
|
|
16348
16711
|
pointerEvents,
|
|
16349
16712
|
width,
|
|
16350
16713
|
children: [
|
|
16351
|
-
/* @__PURE__ */ (0,
|
|
16352
|
-
/* @__PURE__ */ (0,
|
|
16353
|
-
/* @__PURE__ */ (0,
|
|
16714
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("mesh", { children: [
|
|
16715
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("planeGeometry", { args: [1, 1] }),
|
|
16716
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
16354
16717
|
"meshBasicMaterial",
|
|
16355
16718
|
{
|
|
16356
16719
|
depthWrite: false,
|
|
16357
16720
|
opacity: 0,
|
|
16358
|
-
side:
|
|
16721
|
+
side: import_three38.DoubleSide,
|
|
16359
16722
|
toneMapped: false,
|
|
16360
16723
|
transparent: true
|
|
16361
16724
|
}
|
|
16362
16725
|
)
|
|
16363
16726
|
] }),
|
|
16364
|
-
/* @__PURE__ */ (0,
|
|
16727
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
16365
16728
|
import_drei2.Html,
|
|
16366
16729
|
{
|
|
16367
16730
|
distanceFactor: CSS3D_DISTANCE_FACTOR,
|
|
@@ -16376,7 +16739,7 @@ function IframeHotspot({
|
|
|
16376
16739
|
},
|
|
16377
16740
|
transform: true,
|
|
16378
16741
|
zIndexRange: [10, 0],
|
|
16379
|
-
children: /* @__PURE__ */ (0,
|
|
16742
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
16380
16743
|
"iframe",
|
|
16381
16744
|
{
|
|
16382
16745
|
allow,
|