@ericchen1990/pano-view 3.1.2 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -0
- package/README.zh-CN.md +53 -0
- package/dist/index.cjs +2085 -1618
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +172 -81
- package/dist/index.d.ts +172 -81
- package/dist/index.mjs +1465 -995
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
package/dist/index.mjs
CHANGED
|
@@ -2311,6 +2311,9 @@ function isMediaActivationEvent(event) {
|
|
|
2311
2311
|
return false;
|
|
2312
2312
|
}
|
|
2313
2313
|
}
|
|
2314
|
+
function isAutoplayPolicyError(error) {
|
|
2315
|
+
return typeof error === "object" && error !== null && "name" in error && error.name === "NotAllowedError";
|
|
2316
|
+
}
|
|
2314
2317
|
|
|
2315
2318
|
// src/audio/howl.ts
|
|
2316
2319
|
import_howler.Howler.autoUnlock = true;
|
|
@@ -3742,7 +3745,9 @@ var DEFAULT_PANO_FILTER_INTENSITY = 1;
|
|
|
3742
3745
|
var DEFAULT_PANO_FILTER_SNAPSHOT = {
|
|
3743
3746
|
preset: "none",
|
|
3744
3747
|
intensity: DEFAULT_PANO_FILTER_INTENSITY,
|
|
3745
|
-
enabled: true
|
|
3748
|
+
enabled: true,
|
|
3749
|
+
colorMatrix: null,
|
|
3750
|
+
colorMatrixScope: "panorama"
|
|
3746
3751
|
};
|
|
3747
3752
|
function clampPanoFilterIntensity(value) {
|
|
3748
3753
|
if (!Number.isFinite(value)) {
|
|
@@ -3751,15 +3756,17 @@ function clampPanoFilterIntensity(value) {
|
|
|
3751
3756
|
return Math.max(0, Math.min(value, 1));
|
|
3752
3757
|
}
|
|
3753
3758
|
function resolvePanoFilterSnapshot(input) {
|
|
3759
|
+
if (input.colorMatrix && (input.colorMatrix.length !== 20 || input.colorMatrix.some((value) => !Number.isFinite(value)))) {
|
|
3760
|
+
throw new Error("colorMatrix must contain 20 finite numbers");
|
|
3761
|
+
}
|
|
3754
3762
|
return {
|
|
3763
|
+
colorMatrix: input.colorMatrix ? [...input.colorMatrix] : null,
|
|
3764
|
+
colorMatrixScope: input.colorMatrixScope ?? "panorama",
|
|
3755
3765
|
preset: input.preset ?? "none",
|
|
3756
3766
|
intensity: clampPanoFilterIntensity(input.intensity),
|
|
3757
3767
|
enabled: input.enabled !== false
|
|
3758
3768
|
};
|
|
3759
3769
|
}
|
|
3760
|
-
function isPanoFilterActive(snapshot) {
|
|
3761
|
-
return snapshot.enabled && snapshot.preset !== "none";
|
|
3762
|
-
}
|
|
3763
3770
|
|
|
3764
3771
|
// src/pano-filter/host.ts
|
|
3765
3772
|
var PanoFilterHostContext = createContext7(null);
|
|
@@ -3856,7 +3863,7 @@ function hasPanoMediaActivationIntent(host) {
|
|
|
3856
3863
|
return host.intents.size > 0;
|
|
3857
3864
|
}
|
|
3858
3865
|
function needsMediaGesture() {
|
|
3859
|
-
if (typeof navigator !== "undefined" && navigator.userActivation?.
|
|
3866
|
+
if (typeof navigator !== "undefined" && navigator.userActivation?.isActive) {
|
|
3860
3867
|
return false;
|
|
3861
3868
|
}
|
|
3862
3869
|
if (import_howler2.Howler.ctx?.state === "running") {
|
|
@@ -7189,10 +7196,6 @@ var PanoViewer = forwardRef2(
|
|
|
7189
7196
|
if (!shouldActivateMedia) {
|
|
7190
7197
|
return;
|
|
7191
7198
|
}
|
|
7192
|
-
if (!needsMediaGesture()) {
|
|
7193
|
-
void activateMedia();
|
|
7194
|
-
return;
|
|
7195
|
-
}
|
|
7196
7199
|
let cancelled = false;
|
|
7197
7200
|
let activating = false;
|
|
7198
7201
|
const removeListeners = () => {
|
|
@@ -7200,32 +7203,69 @@ var PanoViewer = forwardRef2(
|
|
|
7200
7203
|
window.removeEventListener("pointerup", handleGesture, true);
|
|
7201
7204
|
window.removeEventListener("keydown", handleGesture, true);
|
|
7202
7205
|
};
|
|
7203
|
-
const
|
|
7204
|
-
if (
|
|
7206
|
+
const completeIfUnlocked = (requestedVideo, videoOk) => {
|
|
7207
|
+
if (cancelled || !isPanoAudioUnlocked()) {
|
|
7208
|
+
return;
|
|
7209
|
+
}
|
|
7210
|
+
if (requestedVideo && videoHost.controller && !videoOk) {
|
|
7211
|
+
return;
|
|
7212
|
+
}
|
|
7213
|
+
removeListeners();
|
|
7214
|
+
setMediaActivated(true);
|
|
7215
|
+
};
|
|
7216
|
+
const tryActivate = () => {
|
|
7217
|
+
if (activating || cancelled) {
|
|
7205
7218
|
return;
|
|
7206
7219
|
}
|
|
7207
7220
|
activating = true;
|
|
7221
|
+
let videoPlay;
|
|
7222
|
+
const controls2 = {
|
|
7223
|
+
resumeAudio: mediaActivationControls.resumeAudio,
|
|
7224
|
+
playVideo: (options) => {
|
|
7225
|
+
const result = mediaActivationControls.playVideo(options);
|
|
7226
|
+
videoPlay = result;
|
|
7227
|
+
return result;
|
|
7228
|
+
},
|
|
7229
|
+
playBackgroundAudio: mediaActivationControls.playBackgroundAudio
|
|
7230
|
+
};
|
|
7208
7231
|
try {
|
|
7209
|
-
const resume =
|
|
7210
|
-
|
|
7211
|
-
|
|
7212
|
-
|
|
7232
|
+
const resume = controls2.resumeAudio();
|
|
7233
|
+
mediaActivationOptions?.onActivate?.(controls2);
|
|
7234
|
+
const requestedVideo = videoPlay !== void 0;
|
|
7235
|
+
void Promise.all([resume, videoPlay ?? Promise.resolve(true)]).then(
|
|
7236
|
+
([, videoOk]) => {
|
|
7237
|
+
completeIfUnlocked(requestedVideo, videoOk);
|
|
7238
|
+
},
|
|
7239
|
+
() => {
|
|
7240
|
+
completeIfUnlocked(requestedVideo, false);
|
|
7213
7241
|
}
|
|
7214
|
-
|
|
7215
|
-
setMediaActivated(true);
|
|
7216
|
-
});
|
|
7242
|
+
);
|
|
7217
7243
|
} finally {
|
|
7218
7244
|
activating = false;
|
|
7219
7245
|
}
|
|
7220
7246
|
};
|
|
7247
|
+
const handleGesture = (event) => {
|
|
7248
|
+
if (!isMediaActivationEvent(event)) {
|
|
7249
|
+
return;
|
|
7250
|
+
}
|
|
7251
|
+
tryActivate();
|
|
7252
|
+
};
|
|
7221
7253
|
window.addEventListener("pointerdown", handleGesture, { capture: true });
|
|
7222
7254
|
window.addEventListener("pointerup", handleGesture, { capture: true });
|
|
7223
7255
|
window.addEventListener("keydown", handleGesture, { capture: true });
|
|
7256
|
+
if (!needsMediaGesture()) {
|
|
7257
|
+
tryActivate();
|
|
7258
|
+
}
|
|
7224
7259
|
return () => {
|
|
7225
7260
|
cancelled = true;
|
|
7226
7261
|
removeListeners();
|
|
7227
7262
|
};
|
|
7228
|
-
}, [
|
|
7263
|
+
}, [
|
|
7264
|
+
mediaActivationControls,
|
|
7265
|
+
mediaActivationOptions,
|
|
7266
|
+
shouldActivateMedia,
|
|
7267
|
+
videoHost
|
|
7268
|
+
]);
|
|
7229
7269
|
const fallbackViewRef = useRef13(DEFAULT_VIEW);
|
|
7230
7270
|
const normalizedMinFov = Math.max(1, Math.min(minFov, maxFov - 1));
|
|
7231
7271
|
const normalizedMaxFov = Math.min(
|
|
@@ -8004,15 +8044,23 @@ import { useContext as useContext17, useEffect as useEffect15, useMemo as useMem
|
|
|
8004
8044
|
function PanoFilter({
|
|
8005
8045
|
preset = "none",
|
|
8006
8046
|
intensity,
|
|
8007
|
-
enabled = true
|
|
8047
|
+
enabled = true,
|
|
8048
|
+
colorMatrix,
|
|
8049
|
+
colorMatrixScope
|
|
8008
8050
|
}) {
|
|
8009
8051
|
const host = useContext17(PanoFilterHostContext);
|
|
8010
8052
|
if (!host) {
|
|
8011
8053
|
throw new Error("<PanoFilter> must be rendered inside <PanoViewer>.");
|
|
8012
8054
|
}
|
|
8013
8055
|
const snapshot = useMemo9(
|
|
8014
|
-
() => resolvePanoFilterSnapshot({
|
|
8015
|
-
|
|
8056
|
+
() => resolvePanoFilterSnapshot({
|
|
8057
|
+
preset,
|
|
8058
|
+
intensity,
|
|
8059
|
+
enabled,
|
|
8060
|
+
colorMatrix,
|
|
8061
|
+
colorMatrixScope
|
|
8062
|
+
}),
|
|
8063
|
+
[enabled, intensity, preset, colorMatrix, colorMatrixScope]
|
|
8016
8064
|
);
|
|
8017
8065
|
useEffect15(() => {
|
|
8018
8066
|
claimPanoFilter(host);
|
|
@@ -9666,18 +9714,10 @@ function usePanoViewer() {
|
|
|
9666
9714
|
return useMemo12(() => ({ ref, ...handle }), [handle]);
|
|
9667
9715
|
}
|
|
9668
9716
|
|
|
9669
|
-
// src/sphere.tsx
|
|
9670
|
-
import { useThree as useThree13 } from "@react-three/fiber";
|
|
9671
|
-
import { useEffect as
|
|
9672
|
-
import {
|
|
9673
|
-
BackSide as BackSide2,
|
|
9674
|
-
LinearFilter,
|
|
9675
|
-
LinearMipmapLinearFilter,
|
|
9676
|
-
MathUtils as MathUtils5,
|
|
9677
|
-
RepeatWrapping,
|
|
9678
|
-
SRGBColorSpace,
|
|
9679
|
-
TextureLoader
|
|
9680
|
-
} from "three";
|
|
9717
|
+
// src/sphere-tile/sphere-tile.tsx
|
|
9718
|
+
import { useFrame as useFrame9, useThree as useThree13 } from "@react-three/fiber";
|
|
9719
|
+
import { memo, useCallback as useCallback9, useEffect as useEffect22, useMemo as useMemo14, useRef as useRef23, useState as useState10 } from "react";
|
|
9720
|
+
import { BackSide as BackSide2, Frustum, Matrix4 as Matrix42, PerspectiveCamera as PerspectiveCamera3 } from "three";
|
|
9681
9721
|
|
|
9682
9722
|
// src/asset-url.ts
|
|
9683
9723
|
function isAbsoluteAssetUrl(url) {
|
|
@@ -9702,6 +9742,10 @@ function resolveUrlAgainstFile(fileUrl, path) {
|
|
|
9702
9742
|
|
|
9703
9743
|
// src/pano-filter/pano-basic-material.tsx
|
|
9704
9744
|
import { useLayoutEffect as useLayoutEffect2, useMemo as useMemo13, useRef as useRef21 } from "react";
|
|
9745
|
+
import {
|
|
9746
|
+
Matrix4,
|
|
9747
|
+
Vector4 as Vector42
|
|
9748
|
+
} from "three";
|
|
9705
9749
|
|
|
9706
9750
|
// src/pano-filter/shaders.ts
|
|
9707
9751
|
var GLSL_FILTER_COMMON = `
|
|
@@ -9850,212 +9894,944 @@ ${applyPanoFilterFunction(panoFilterBody(preset))}`
|
|
|
9850
9894
|
diffuseColor.rgb = mix(diffuseColor.rgb, applyPanoFilter(diffuseColor.rgb), clamp(uPanoFilterIntensity, 0.0, 1.0));`
|
|
9851
9895
|
);
|
|
9852
9896
|
}
|
|
9897
|
+
function injectPanoColorMatrixShader(shader) {
|
|
9898
|
+
shader.fragmentShader = shader.fragmentShader.replace(
|
|
9899
|
+
"#include <common>",
|
|
9900
|
+
`#include <common>
|
|
9901
|
+
uniform mat4 uPanoColorMatrix;
|
|
9902
|
+
uniform vec4 uPanoColorOffset;
|
|
9903
|
+
uniform float uPanoColorMatrixIntensity;`
|
|
9904
|
+
).replace(
|
|
9905
|
+
"#include <colorspace_fragment>",
|
|
9906
|
+
`#include <colorspace_fragment>
|
|
9907
|
+
gl_FragColor = mix(gl_FragColor, clamp(uPanoColorMatrix * gl_FragColor + uPanoColorOffset, 0.0, 1.0), uPanoColorMatrixIntensity);`
|
|
9908
|
+
);
|
|
9909
|
+
}
|
|
9853
9910
|
|
|
9854
9911
|
// src/pano-filter/pano-basic-material.tsx
|
|
9855
9912
|
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
9913
|
+
function matrixUniforms(matrix) {
|
|
9914
|
+
return {
|
|
9915
|
+
matrix: new Matrix4().set(
|
|
9916
|
+
matrix[0],
|
|
9917
|
+
matrix[1],
|
|
9918
|
+
matrix[2],
|
|
9919
|
+
matrix[3],
|
|
9920
|
+
matrix[5],
|
|
9921
|
+
matrix[6],
|
|
9922
|
+
matrix[7],
|
|
9923
|
+
matrix[8],
|
|
9924
|
+
matrix[10],
|
|
9925
|
+
matrix[11],
|
|
9926
|
+
matrix[12],
|
|
9927
|
+
matrix[13],
|
|
9928
|
+
matrix[15],
|
|
9929
|
+
matrix[16],
|
|
9930
|
+
matrix[17],
|
|
9931
|
+
matrix[18]
|
|
9932
|
+
),
|
|
9933
|
+
offset: new Vector42(matrix[4], matrix[9], matrix[14], matrix[19])
|
|
9934
|
+
};
|
|
9935
|
+
}
|
|
9856
9936
|
function PanoBasicMaterial({
|
|
9857
|
-
|
|
9858
|
-
|
|
9859
|
-
depthTest,
|
|
9860
|
-
depthWrite,
|
|
9861
|
-
toneMapped = false
|
|
9937
|
+
target = "panorama",
|
|
9938
|
+
...props
|
|
9862
9939
|
}) {
|
|
9863
9940
|
const snapshot = usePanoFilterSnapshot();
|
|
9864
|
-
const
|
|
9865
|
-
const
|
|
9866
|
-
const
|
|
9867
|
-
|
|
9868
|
-
|
|
9869
|
-
const
|
|
9941
|
+
const preset = snapshot.enabled && target === "panorama" ? snapshot.preset : "none";
|
|
9942
|
+
const matrix = snapshot.enabled && (target === "panorama" || snapshot.colorMatrixScope === "all") ? snapshot.colorMatrix : null;
|
|
9943
|
+
const hasMatrix = matrix !== null;
|
|
9944
|
+
const currentRef = useRef21({ matrix, intensity: snapshot.intensity });
|
|
9945
|
+
currentRef.current = { matrix, intensity: snapshot.intensity };
|
|
9946
|
+
const shaderRef = useRef21(null);
|
|
9870
9947
|
const onBeforeCompile = useMemo13(() => {
|
|
9871
|
-
if (!active || preset === "none") {
|
|
9872
|
-
return void 0;
|
|
9873
|
-
}
|
|
9874
9948
|
const compile = (shader) => {
|
|
9875
|
-
|
|
9876
|
-
|
|
9877
|
-
|
|
9878
|
-
|
|
9879
|
-
|
|
9880
|
-
if (
|
|
9881
|
-
|
|
9949
|
+
shaderRef.current = shader;
|
|
9950
|
+
if (preset !== "none") {
|
|
9951
|
+
injectPanoFilterShader(shader, preset);
|
|
9952
|
+
shader.uniforms.uPanoFilterIntensity.value = currentRef.current.intensity;
|
|
9953
|
+
}
|
|
9954
|
+
if (hasMatrix && currentRef.current.matrix) {
|
|
9955
|
+
injectPanoColorMatrixShader(shader);
|
|
9956
|
+
const values = matrixUniforms(currentRef.current.matrix);
|
|
9957
|
+
shader.uniforms.uPanoColorMatrix = { value: values.matrix };
|
|
9958
|
+
shader.uniforms.uPanoColorOffset = { value: values.offset };
|
|
9959
|
+
shader.uniforms.uPanoColorMatrixIntensity = {
|
|
9960
|
+
value: currentRef.current.intensity
|
|
9961
|
+
};
|
|
9882
9962
|
}
|
|
9883
9963
|
};
|
|
9884
|
-
compile.toString = () => `pano-filter:${preset}`;
|
|
9964
|
+
compile.toString = () => `pano-filter:${preset}:matrix:${hasMatrix}`;
|
|
9885
9965
|
return compile;
|
|
9886
|
-
}, [
|
|
9887
|
-
useLayoutEffect2(() => {
|
|
9888
|
-
if (!active) {
|
|
9889
|
-
intensityUniformRef.current = null;
|
|
9890
|
-
}
|
|
9891
|
-
const material = materialRef.current;
|
|
9892
|
-
if (!material) {
|
|
9893
|
-
return;
|
|
9894
|
-
}
|
|
9895
|
-
material.needsUpdate = true;
|
|
9896
|
-
}, [active, preset]);
|
|
9966
|
+
}, [preset, hasMatrix]);
|
|
9897
9967
|
useLayoutEffect2(() => {
|
|
9898
|
-
|
|
9899
|
-
|
|
9900
|
-
|
|
9901
|
-
|
|
9968
|
+
const shader = shaderRef.current;
|
|
9969
|
+
if (!shader) return;
|
|
9970
|
+
if (shader.uniforms.uPanoFilterIntensity)
|
|
9971
|
+
shader.uniforms.uPanoFilterIntensity.value = snapshot.intensity;
|
|
9972
|
+
if (shader.uniforms.uPanoColorMatrix && matrix) {
|
|
9973
|
+
const values = matrixUniforms(matrix);
|
|
9974
|
+
shader.uniforms.uPanoColorMatrix.value = values.matrix;
|
|
9975
|
+
shader.uniforms.uPanoColorOffset.value = values.offset;
|
|
9976
|
+
shader.uniforms.uPanoColorMatrixIntensity.value = snapshot.intensity;
|
|
9977
|
+
}
|
|
9978
|
+
}, [matrix, snapshot.intensity]);
|
|
9902
9979
|
return /* @__PURE__ */ jsx14(
|
|
9903
9980
|
"meshBasicMaterial",
|
|
9904
9981
|
{
|
|
9905
|
-
|
|
9906
|
-
|
|
9907
|
-
|
|
9908
|
-
map,
|
|
9909
|
-
onBeforeCompile,
|
|
9910
|
-
side,
|
|
9911
|
-
toneMapped
|
|
9982
|
+
toneMapped: false,
|
|
9983
|
+
...props,
|
|
9984
|
+
onBeforeCompile
|
|
9912
9985
|
},
|
|
9913
|
-
|
|
9986
|
+
`${preset}:${hasMatrix}`
|
|
9914
9987
|
);
|
|
9915
9988
|
}
|
|
9916
9989
|
|
|
9917
|
-
// src/
|
|
9918
|
-
import {
|
|
9919
|
-
|
|
9920
|
-
|
|
9921
|
-
|
|
9922
|
-
|
|
9923
|
-
|
|
9924
|
-
|
|
9925
|
-
|
|
9926
|
-
|
|
9927
|
-
|
|
9928
|
-
|
|
9990
|
+
// src/tile/texture-manager.ts
|
|
9991
|
+
import {
|
|
9992
|
+
ClampToEdgeWrapping,
|
|
9993
|
+
LinearFilter,
|
|
9994
|
+
SRGBColorSpace,
|
|
9995
|
+
TextureLoader
|
|
9996
|
+
} from "three";
|
|
9997
|
+
var EMPTY_TEXTURE_SNAPSHOT = {
|
|
9998
|
+
status: "idle",
|
|
9999
|
+
texture: null,
|
|
10000
|
+
error: null
|
|
10001
|
+
};
|
|
10002
|
+
var TileTextureManager = class {
|
|
10003
|
+
constructor(options) {
|
|
10004
|
+
this.loader = new TextureLoader();
|
|
10005
|
+
this.entries = /* @__PURE__ */ new Map();
|
|
10006
|
+
this.queue = [];
|
|
10007
|
+
this.activeLoads = 0;
|
|
10008
|
+
this.totalBytes = 0;
|
|
10009
|
+
this.requested = 0;
|
|
10010
|
+
this.loaded = 0;
|
|
10011
|
+
this.failed = 0;
|
|
10012
|
+
this.disposed = false;
|
|
10013
|
+
this.generation = 0;
|
|
10014
|
+
this.options = options;
|
|
10015
|
+
}
|
|
10016
|
+
resume() {
|
|
10017
|
+
this.disposed = false;
|
|
10018
|
+
this.drain();
|
|
10019
|
+
}
|
|
10020
|
+
getSnapshot(key) {
|
|
10021
|
+
const entry = this.entries.get(key);
|
|
10022
|
+
return entry ? this.snapshot(entry) : EMPTY_TEXTURE_SNAPSHOT;
|
|
10023
|
+
}
|
|
10024
|
+
acquire(key, url, address, listener) {
|
|
10025
|
+
let entry = this.entries.get(key);
|
|
10026
|
+
if (!entry) {
|
|
10027
|
+
entry = {
|
|
10028
|
+
key,
|
|
10029
|
+
url,
|
|
10030
|
+
address,
|
|
10031
|
+
status: "idle",
|
|
10032
|
+
texture: null,
|
|
10033
|
+
error: null,
|
|
10034
|
+
refs: 0,
|
|
10035
|
+
listeners: /* @__PURE__ */ new Set(),
|
|
10036
|
+
lastUsed: performance.now(),
|
|
10037
|
+
bytes: 0
|
|
10038
|
+
};
|
|
10039
|
+
this.entries.set(key, entry);
|
|
9929
10040
|
}
|
|
9930
|
-
|
|
9931
|
-
|
|
9932
|
-
|
|
9933
|
-
|
|
9934
|
-
|
|
9935
|
-
|
|
9936
|
-
|
|
9937
|
-
|
|
9938
|
-
|
|
9939
|
-
|
|
9940
|
-
|
|
9941
|
-
|
|
9942
|
-
|
|
9943
|
-
|
|
9944
|
-
|
|
9945
|
-
|
|
9946
|
-
|
|
9947
|
-
|
|
9948
|
-
|
|
9949
|
-
setTexture(loadedTexture);
|
|
9950
|
-
onLoadRef.current?.(loadedTexture);
|
|
9951
|
-
},
|
|
9952
|
-
void 0,
|
|
9953
|
-
(error) => {
|
|
9954
|
-
if (active) {
|
|
9955
|
-
setTexture(null);
|
|
9956
|
-
onErrorRef.current?.(error);
|
|
10041
|
+
entry.refs += 1;
|
|
10042
|
+
entry.lastUsed = performance.now();
|
|
10043
|
+
entry.listeners.add(listener);
|
|
10044
|
+
listener(this.snapshot(entry));
|
|
10045
|
+
if (entry.status === "idle") {
|
|
10046
|
+
entry.status = "queued";
|
|
10047
|
+
this.queue.push(entry);
|
|
10048
|
+
this.requested += 1;
|
|
10049
|
+
this.emitProgress();
|
|
10050
|
+
this.drain();
|
|
10051
|
+
}
|
|
10052
|
+
return () => {
|
|
10053
|
+
entry.listeners.delete(listener);
|
|
10054
|
+
entry.refs = Math.max(0, entry.refs - 1);
|
|
10055
|
+
entry.lastUsed = performance.now();
|
|
10056
|
+
if (entry.refs === 0 && entry.status === "queued") {
|
|
10057
|
+
const queueIndex = this.queue.indexOf(entry);
|
|
10058
|
+
if (queueIndex >= 0) {
|
|
10059
|
+
this.queue.splice(queueIndex, 1);
|
|
9957
10060
|
}
|
|
10061
|
+
entry.status = "idle";
|
|
10062
|
+
this.entries.delete(entry.key);
|
|
10063
|
+
this.requested = Math.max(0, this.requested - 1);
|
|
10064
|
+
this.emitProgress();
|
|
10065
|
+
this.drain();
|
|
10066
|
+
return;
|
|
9958
10067
|
}
|
|
9959
|
-
|
|
9960
|
-
return () => {
|
|
9961
|
-
active = false;
|
|
10068
|
+
this.evict();
|
|
9962
10069
|
};
|
|
9963
|
-
}
|
|
9964
|
-
|
|
9965
|
-
|
|
9966
|
-
|
|
9967
|
-
|
|
9968
|
-
|
|
9969
|
-
|
|
9970
|
-
|
|
9971
|
-
}
|
|
9972
|
-
function Sphere({
|
|
9973
|
-
src,
|
|
9974
|
-
previewUrl,
|
|
9975
|
-
yawOffset = 0,
|
|
9976
|
-
onReady,
|
|
9977
|
-
onLoad,
|
|
9978
|
-
onError,
|
|
9979
|
-
onPreviewError,
|
|
9980
|
-
visible = true
|
|
9981
|
-
}) {
|
|
9982
|
-
const gl = useThree13((state) => state.gl);
|
|
9983
|
-
const anisotropy = gl.capabilities.getMaxAnisotropy();
|
|
9984
|
-
const resolvedPreviewUrl = useMemo14(
|
|
9985
|
-
() => resolveUrlAgainstFile(src, previewUrl),
|
|
9986
|
-
[previewUrl, src]
|
|
9987
|
-
);
|
|
9988
|
-
const texture = useEquirectTexture(
|
|
9989
|
-
src,
|
|
9990
|
-
anisotropy,
|
|
9991
|
-
true,
|
|
9992
|
-
onLoad,
|
|
9993
|
-
onError
|
|
9994
|
-
);
|
|
9995
|
-
const previewTexture = useEquirectTexture(
|
|
9996
|
-
texture ? null : resolvedPreviewUrl,
|
|
9997
|
-
anisotropy,
|
|
9998
|
-
false,
|
|
9999
|
-
void 0,
|
|
10000
|
-
onPreviewError
|
|
10001
|
-
);
|
|
10002
|
-
const displayTexture = texture ?? previewTexture;
|
|
10003
|
-
const readyRef = useRef22(false);
|
|
10004
|
-
useEffect21(() => {
|
|
10005
|
-
readyRef.current = false;
|
|
10006
|
-
}, [resolvedPreviewUrl, src]);
|
|
10007
|
-
useEffect21(() => {
|
|
10008
|
-
if (!displayTexture || readyRef.current) {
|
|
10009
|
-
return;
|
|
10070
|
+
}
|
|
10071
|
+
dispose() {
|
|
10072
|
+
this.disposed = true;
|
|
10073
|
+
this.generation += 1;
|
|
10074
|
+
this.queue.length = 0;
|
|
10075
|
+
for (const entry of this.entries.values()) {
|
|
10076
|
+
entry.texture?.dispose();
|
|
10077
|
+
entry.listeners.clear();
|
|
10010
10078
|
}
|
|
10011
|
-
|
|
10012
|
-
|
|
10013
|
-
}, [displayTexture, onReady]);
|
|
10014
|
-
if (!displayTexture) {
|
|
10015
|
-
return null;
|
|
10079
|
+
this.entries.clear();
|
|
10080
|
+
this.totalBytes = 0;
|
|
10016
10081
|
}
|
|
10017
|
-
|
|
10018
|
-
|
|
10019
|
-
|
|
10020
|
-
|
|
10021
|
-
|
|
10022
|
-
|
|
10023
|
-
|
|
10024
|
-
|
|
10025
|
-
|
|
10026
|
-
|
|
10027
|
-
|
|
10028
|
-
|
|
10029
|
-
|
|
10030
|
-
}
|
|
10031
|
-
)
|
|
10032
|
-
]
|
|
10082
|
+
/**
|
|
10083
|
+
* Releases textures that are no longer rendered by any Tile instance.
|
|
10084
|
+
* Scene transitions call this after the outgoing panorama has been
|
|
10085
|
+
* snapshotted, so the incoming scene never competes with stale GPU tiles.
|
|
10086
|
+
*/
|
|
10087
|
+
releaseUnused() {
|
|
10088
|
+
for (const entry of Array.from(this.entries.values())) {
|
|
10089
|
+
if (entry.refs > 0) {
|
|
10090
|
+
continue;
|
|
10091
|
+
}
|
|
10092
|
+
entry.texture?.dispose();
|
|
10093
|
+
this.totalBytes -= entry.bytes;
|
|
10094
|
+
this.entries.delete(entry.key);
|
|
10033
10095
|
}
|
|
10034
|
-
|
|
10096
|
+
this.totalBytes = Math.max(0, this.totalBytes);
|
|
10097
|
+
}
|
|
10098
|
+
snapshot(entry) {
|
|
10099
|
+
return {
|
|
10100
|
+
status: entry.status,
|
|
10101
|
+
texture: entry.texture,
|
|
10102
|
+
error: entry.error
|
|
10103
|
+
};
|
|
10104
|
+
}
|
|
10105
|
+
notify(entry) {
|
|
10106
|
+
const snapshot = this.snapshot(entry);
|
|
10107
|
+
for (const listener of entry.listeners) {
|
|
10108
|
+
listener(snapshot);
|
|
10109
|
+
}
|
|
10110
|
+
}
|
|
10111
|
+
emitProgress() {
|
|
10112
|
+
this.options.onProgress?.({
|
|
10113
|
+
requested: this.requested,
|
|
10114
|
+
loaded: this.loaded,
|
|
10115
|
+
failed: this.failed,
|
|
10116
|
+
active: this.activeLoads,
|
|
10117
|
+
queued: this.queue.length
|
|
10118
|
+
});
|
|
10119
|
+
}
|
|
10120
|
+
drain() {
|
|
10121
|
+
while (!this.disposed && this.activeLoads < this.options.concurrency && this.queue.length > 0) {
|
|
10122
|
+
const entry = this.queue.shift();
|
|
10123
|
+
if (entry.refs === 0) {
|
|
10124
|
+
entry.status = "idle";
|
|
10125
|
+
this.entries.delete(entry.key);
|
|
10126
|
+
this.requested = Math.max(0, this.requested - 1);
|
|
10127
|
+
continue;
|
|
10128
|
+
}
|
|
10129
|
+
entry.status = "loading";
|
|
10130
|
+
this.activeLoads += 1;
|
|
10131
|
+
this.notify(entry);
|
|
10132
|
+
this.emitProgress();
|
|
10133
|
+
void this.loadAndFinish(entry);
|
|
10134
|
+
}
|
|
10135
|
+
}
|
|
10136
|
+
async load(entry, generation) {
|
|
10137
|
+
let lastError = null;
|
|
10138
|
+
for (let attempt = 0; attempt <= this.options.retryCount; attempt += 1) {
|
|
10139
|
+
if (this.disposed || generation !== this.generation) return;
|
|
10140
|
+
try {
|
|
10141
|
+
const texture = await this.loader.loadAsync(entry.url);
|
|
10142
|
+
if (this.disposed || generation !== this.generation) {
|
|
10143
|
+
texture.dispose();
|
|
10144
|
+
return;
|
|
10145
|
+
}
|
|
10146
|
+
this.configureTexture(texture);
|
|
10147
|
+
entry.texture = texture;
|
|
10148
|
+
entry.status = "loaded";
|
|
10149
|
+
entry.error = null;
|
|
10150
|
+
entry.bytes = entry.address.width * entry.address.height * 4;
|
|
10151
|
+
entry.lastUsed = performance.now();
|
|
10152
|
+
this.totalBytes += entry.bytes;
|
|
10153
|
+
this.loaded += 1;
|
|
10154
|
+
this.notify(entry);
|
|
10155
|
+
return;
|
|
10156
|
+
} catch (error) {
|
|
10157
|
+
lastError = error;
|
|
10158
|
+
}
|
|
10159
|
+
}
|
|
10160
|
+
if (!this.disposed && generation === this.generation) {
|
|
10161
|
+
entry.status = "error";
|
|
10162
|
+
entry.error = lastError;
|
|
10163
|
+
this.failed += 1;
|
|
10164
|
+
this.notify(entry);
|
|
10165
|
+
this.options.onError?.({
|
|
10166
|
+
address: entry.address,
|
|
10167
|
+
url: entry.url,
|
|
10168
|
+
error: lastError
|
|
10169
|
+
});
|
|
10170
|
+
}
|
|
10171
|
+
}
|
|
10172
|
+
configureTexture(texture) {
|
|
10173
|
+
texture.colorSpace = SRGBColorSpace;
|
|
10174
|
+
texture.wrapS = ClampToEdgeWrapping;
|
|
10175
|
+
texture.wrapT = ClampToEdgeWrapping;
|
|
10176
|
+
texture.magFilter = LinearFilter;
|
|
10177
|
+
texture.minFilter = LinearFilter;
|
|
10178
|
+
texture.generateMipmaps = false;
|
|
10179
|
+
texture.anisotropy = Math.min(4, this.options.anisotropy);
|
|
10180
|
+
texture.needsUpdate = true;
|
|
10181
|
+
}
|
|
10182
|
+
evict() {
|
|
10183
|
+
if (this.totalBytes <= this.options.maxBytes) {
|
|
10184
|
+
return;
|
|
10185
|
+
}
|
|
10186
|
+
const candidates = Array.from(this.entries.values()).filter((entry) => entry.refs === 0 && entry.texture).sort((a, b) => a.lastUsed - b.lastUsed);
|
|
10187
|
+
for (const entry of candidates) {
|
|
10188
|
+
if (this.totalBytes <= this.options.maxBytes) {
|
|
10189
|
+
break;
|
|
10190
|
+
}
|
|
10191
|
+
entry.texture?.dispose();
|
|
10192
|
+
this.totalBytes -= entry.bytes;
|
|
10193
|
+
this.entries.delete(entry.key);
|
|
10194
|
+
}
|
|
10195
|
+
this.totalBytes = Math.max(0, this.totalBytes);
|
|
10196
|
+
}
|
|
10197
|
+
finishLoad(generation) {
|
|
10198
|
+
this.activeLoads = Math.max(0, this.activeLoads - 1);
|
|
10199
|
+
if (!this.disposed && generation === this.generation) {
|
|
10200
|
+
this.emitProgress();
|
|
10201
|
+
this.evict();
|
|
10202
|
+
}
|
|
10203
|
+
if (!this.disposed) {
|
|
10204
|
+
this.drain();
|
|
10205
|
+
}
|
|
10206
|
+
}
|
|
10207
|
+
async loadAndFinish(entry) {
|
|
10208
|
+
const generation = this.generation;
|
|
10209
|
+
try {
|
|
10210
|
+
await this.load(entry, generation);
|
|
10211
|
+
} finally {
|
|
10212
|
+
this.finishLoad(generation);
|
|
10213
|
+
}
|
|
10214
|
+
}
|
|
10215
|
+
};
|
|
10216
|
+
|
|
10217
|
+
// src/tile/texture-hooks.ts
|
|
10218
|
+
import { useEffect as useEffect21, useRef as useRef22, useState as useState9 } from "react";
|
|
10219
|
+
import {
|
|
10220
|
+
ClampToEdgeWrapping as ClampToEdgeWrapping2,
|
|
10221
|
+
LinearFilter as LinearFilter2,
|
|
10222
|
+
SRGBColorSpace as SRGBColorSpace2,
|
|
10223
|
+
TextureLoader as TextureLoader2
|
|
10224
|
+
} from "three";
|
|
10225
|
+
function usePreviewTexture(url, anisotropy, onError) {
|
|
10226
|
+
const [texture, setTexture] = useState9(null);
|
|
10227
|
+
const onErrorRef = useRef22(onError);
|
|
10228
|
+
onErrorRef.current = onError;
|
|
10229
|
+
useEffect21(() => {
|
|
10230
|
+
if (!url) {
|
|
10231
|
+
setTexture(null);
|
|
10232
|
+
return;
|
|
10233
|
+
}
|
|
10234
|
+
let active = true;
|
|
10235
|
+
const loader = new TextureLoader2();
|
|
10236
|
+
setTexture(null);
|
|
10237
|
+
loader.load(
|
|
10238
|
+
url,
|
|
10239
|
+
(loadedTexture) => {
|
|
10240
|
+
if (!active) {
|
|
10241
|
+
loadedTexture.dispose();
|
|
10242
|
+
return;
|
|
10243
|
+
}
|
|
10244
|
+
loadedTexture.colorSpace = SRGBColorSpace2;
|
|
10245
|
+
loadedTexture.wrapS = ClampToEdgeWrapping2;
|
|
10246
|
+
loadedTexture.wrapT = ClampToEdgeWrapping2;
|
|
10247
|
+
loadedTexture.magFilter = LinearFilter2;
|
|
10248
|
+
loadedTexture.minFilter = LinearFilter2;
|
|
10249
|
+
loadedTexture.generateMipmaps = false;
|
|
10250
|
+
loadedTexture.anisotropy = Math.min(4, anisotropy);
|
|
10251
|
+
loadedTexture.needsUpdate = true;
|
|
10252
|
+
setTexture(loadedTexture);
|
|
10253
|
+
},
|
|
10254
|
+
void 0,
|
|
10255
|
+
(error) => {
|
|
10256
|
+
if (active) {
|
|
10257
|
+
setTexture(null);
|
|
10258
|
+
onErrorRef.current?.(error);
|
|
10259
|
+
}
|
|
10260
|
+
}
|
|
10261
|
+
);
|
|
10262
|
+
return () => {
|
|
10263
|
+
active = false;
|
|
10264
|
+
};
|
|
10265
|
+
}, [anisotropy, url]);
|
|
10266
|
+
useEffect21(
|
|
10267
|
+
() => () => {
|
|
10268
|
+
texture?.dispose();
|
|
10269
|
+
},
|
|
10270
|
+
[texture]
|
|
10271
|
+
);
|
|
10272
|
+
return texture;
|
|
10273
|
+
}
|
|
10274
|
+
function useManagedTexture(manager, key, url, address) {
|
|
10275
|
+
const [managedState, setManagedState] = useState9(() => ({
|
|
10276
|
+
manager,
|
|
10277
|
+
key,
|
|
10278
|
+
url,
|
|
10279
|
+
snapshot: manager.getSnapshot(key)
|
|
10280
|
+
}));
|
|
10281
|
+
const snapshot = managedState.manager === manager && managedState.key === key && managedState.url === url ? managedState.snapshot : manager.getSnapshot(key);
|
|
10282
|
+
useEffect21(
|
|
10283
|
+
() => manager.acquire(key, url, address, (nextSnapshot) => {
|
|
10284
|
+
setManagedState({
|
|
10285
|
+
manager,
|
|
10286
|
+
key,
|
|
10287
|
+
url,
|
|
10288
|
+
snapshot: nextSnapshot
|
|
10289
|
+
});
|
|
10290
|
+
}),
|
|
10291
|
+
[key, manager, url]
|
|
10292
|
+
);
|
|
10293
|
+
return snapshot;
|
|
10035
10294
|
}
|
|
10036
10295
|
|
|
10037
|
-
// src/
|
|
10296
|
+
// src/sphere-tile/layout.ts
|
|
10297
|
+
import {
|
|
10298
|
+
Box3,
|
|
10299
|
+
BufferGeometry,
|
|
10300
|
+
Float32BufferAttribute,
|
|
10301
|
+
MathUtils as MathUtils5,
|
|
10302
|
+
Vector3 as Vector38
|
|
10303
|
+
} from "three";
|
|
10304
|
+
function positiveInteger(value, name) {
|
|
10305
|
+
if (!Number.isSafeInteger(value) || value <= 0) {
|
|
10306
|
+
throw new Error(`${name} must be a positive safe integer`);
|
|
10307
|
+
}
|
|
10308
|
+
return value;
|
|
10309
|
+
}
|
|
10310
|
+
function parseSphereMultires(input) {
|
|
10311
|
+
const parts = typeof input === "string" ? input.split(",").map((part) => part.trim()) : null;
|
|
10312
|
+
const tileSize = positiveInteger(
|
|
10313
|
+
parts ? Number(parts[0]) : input.tileSize,
|
|
10314
|
+
"tileSize"
|
|
10315
|
+
);
|
|
10316
|
+
const levels = parts ? parts.slice(1).map((part) => {
|
|
10317
|
+
const match = /^(\d+)\s*x\s*(\d+)$/i.exec(part);
|
|
10318
|
+
if (!match)
|
|
10319
|
+
throw new Error("sphere multires levels must use widthxheight");
|
|
10320
|
+
return { width: Number(match[1]), height: Number(match[2]) };
|
|
10321
|
+
}) : input.levels.map((level) => ({ ...level }));
|
|
10322
|
+
if (levels.length === 0)
|
|
10323
|
+
throw new Error("sphere multires needs at least one level");
|
|
10324
|
+
levels.forEach((level, index) => {
|
|
10325
|
+
positiveInteger(level.width, "level width");
|
|
10326
|
+
positiveInteger(level.height, "level height");
|
|
10327
|
+
if (Math.abs(level.width - level.height * 2) > 2)
|
|
10328
|
+
throw new Error("sphere levels must be full 2:1 equirectangular images");
|
|
10329
|
+
const previous = levels[index - 1];
|
|
10330
|
+
if (previous && (level.width <= previous.width || level.height <= previous.height)) {
|
|
10331
|
+
throw new Error("sphere multires dimensions must be strictly ascending");
|
|
10332
|
+
}
|
|
10333
|
+
});
|
|
10334
|
+
return { tileSize, levels };
|
|
10335
|
+
}
|
|
10336
|
+
function resolveSphereTemplateUrl(template, address, indexBase = 1) {
|
|
10337
|
+
return template.replace(/%l/g, String(address.level + indexBase)).replace(
|
|
10338
|
+
/%(0*)([hxucvywr])/g,
|
|
10339
|
+
(_match, zeroes, placeholder) => String(
|
|
10340
|
+
("hxuc".includes(placeholder) ? address.col : address.row) + indexBase
|
|
10341
|
+
).padStart(zeroes.length + 1, "0")
|
|
10342
|
+
);
|
|
10343
|
+
}
|
|
10344
|
+
function sphereTileKey(address) {
|
|
10345
|
+
return `${address.level}/${address.row}/${address.col}`;
|
|
10346
|
+
}
|
|
10347
|
+
function sphereTileAddresses(size, level, tileSize) {
|
|
10348
|
+
const addresses = [];
|
|
10349
|
+
for (let row = 0; row < Math.ceil(size.height / tileSize); row++) {
|
|
10350
|
+
for (let col = 0; col < Math.ceil(size.width / tileSize); col++) {
|
|
10351
|
+
addresses.push({
|
|
10352
|
+
level,
|
|
10353
|
+
col,
|
|
10354
|
+
row,
|
|
10355
|
+
imageWidth: size.width,
|
|
10356
|
+
imageHeight: size.height,
|
|
10357
|
+
tileSize,
|
|
10358
|
+
width: Math.min(tileSize, size.width - col * tileSize),
|
|
10359
|
+
height: Math.min(tileSize, size.height - row * tileSize)
|
|
10360
|
+
});
|
|
10361
|
+
}
|
|
10362
|
+
}
|
|
10363
|
+
return addresses;
|
|
10364
|
+
}
|
|
10365
|
+
function sphereTileRange(address) {
|
|
10366
|
+
return {
|
|
10367
|
+
left: address.col * address.tileSize / address.imageWidth,
|
|
10368
|
+
right: (address.col * address.tileSize + address.width) / address.imageWidth,
|
|
10369
|
+
top: address.row * address.tileSize / address.imageHeight,
|
|
10370
|
+
bottom: (address.row * address.tileSize + address.height) / address.imageHeight
|
|
10371
|
+
};
|
|
10372
|
+
}
|
|
10373
|
+
function spherePoint(u, v, yawOffset = 0, radius = DEFAULT_PANORAMA_RADIUS) {
|
|
10374
|
+
const yaw = (u - 0.5) * Math.PI * 2 + MathUtils5.degToRad(yawOffset);
|
|
10375
|
+
const pitch = (0.5 - v) * Math.PI;
|
|
10376
|
+
return new Vector38(
|
|
10377
|
+
Math.sin(yaw) * Math.cos(pitch) * radius,
|
|
10378
|
+
Math.sin(pitch) * radius,
|
|
10379
|
+
-Math.cos(yaw) * Math.cos(pitch) * radius
|
|
10380
|
+
);
|
|
10381
|
+
}
|
|
10382
|
+
function sphereTileBounds(address, yawOffset) {
|
|
10383
|
+
const { left, right, top, bottom } = sphereTileRange(address);
|
|
10384
|
+
const us = [left, right];
|
|
10385
|
+
for (let i = -4; i <= 8; i++) {
|
|
10386
|
+
const u = 0.5 + (i * 90 - yawOffset % 360) / 360;
|
|
10387
|
+
if (u > left && u < right) us.push(u);
|
|
10388
|
+
}
|
|
10389
|
+
const vs = top < 0.5 && bottom > 0.5 ? [top, 0.5, bottom] : [top, bottom];
|
|
10390
|
+
return new Box3().setFromPoints(
|
|
10391
|
+
us.flatMap((u) => vs.map((v) => spherePoint(u, v, yawOffset)))
|
|
10392
|
+
);
|
|
10393
|
+
}
|
|
10394
|
+
function sphereTileGeometry(address, yawOffset, radius = DEFAULT_PANORAMA_RADIUS) {
|
|
10395
|
+
const { left, right, top, bottom } = sphereTileRange(address);
|
|
10396
|
+
const columns = Math.max(2, Math.ceil((right - left) * 360 / 3));
|
|
10397
|
+
const rows = Math.max(2, Math.ceil((bottom - top) * 180 / 3));
|
|
10398
|
+
const positions = [], uvs = [], indices = [];
|
|
10399
|
+
for (let row = 0; row <= rows; row++) {
|
|
10400
|
+
for (let col = 0; col <= columns; col++) {
|
|
10401
|
+
const u = col / columns, v = row / rows;
|
|
10402
|
+
const point = spherePoint(
|
|
10403
|
+
left + (right - left) * u,
|
|
10404
|
+
top + (bottom - top) * v,
|
|
10405
|
+
yawOffset,
|
|
10406
|
+
radius
|
|
10407
|
+
);
|
|
10408
|
+
positions.push(point.x, point.y, point.z);
|
|
10409
|
+
uvs.push(u, 1 - v);
|
|
10410
|
+
if (row < rows && col < columns) {
|
|
10411
|
+
const a = row * (columns + 1) + col, b = a + 1, c = a + columns + 1, d = c + 1;
|
|
10412
|
+
indices.push(a, b, c, b, d, c);
|
|
10413
|
+
}
|
|
10414
|
+
}
|
|
10415
|
+
}
|
|
10416
|
+
const geometry = new BufferGeometry();
|
|
10417
|
+
geometry.setAttribute("position", new Float32BufferAttribute(positions, 3));
|
|
10418
|
+
geometry.setAttribute("uv", new Float32BufferAttribute(uvs, 2));
|
|
10419
|
+
geometry.setIndex(indices);
|
|
10420
|
+
geometry.computeBoundingSphere();
|
|
10421
|
+
return geometry;
|
|
10422
|
+
}
|
|
10423
|
+
function preferredSphereLevel(levels, height, dpr, verticalFov) {
|
|
10424
|
+
const needed = height * dpr * 180 / Math.max(1, verticalFov);
|
|
10425
|
+
const index = levels.findIndex((level) => level.height >= needed);
|
|
10426
|
+
return index < 0 ? levels.length - 1 : index;
|
|
10427
|
+
}
|
|
10428
|
+
|
|
10429
|
+
// src/sphere-tile/sphere-tile.tsx
|
|
10430
|
+
import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
10431
|
+
function SpherePatch({
|
|
10432
|
+
address,
|
|
10433
|
+
texture,
|
|
10434
|
+
yawOffset,
|
|
10435
|
+
preview = false
|
|
10436
|
+
}) {
|
|
10437
|
+
const geometry = useMemo14(
|
|
10438
|
+
() => sphereTileGeometry(
|
|
10439
|
+
address,
|
|
10440
|
+
yawOffset,
|
|
10441
|
+
DEFAULT_PANORAMA_RADIUS + (preview ? 0.05 : 0)
|
|
10442
|
+
),
|
|
10443
|
+
[address, yawOffset, preview]
|
|
10444
|
+
);
|
|
10445
|
+
useEffect22(() => () => geometry.dispose(), [geometry]);
|
|
10446
|
+
return /* @__PURE__ */ jsx15(
|
|
10447
|
+
"mesh",
|
|
10448
|
+
{
|
|
10449
|
+
geometry,
|
|
10450
|
+
renderOrder: preview ? -1e3 : -900 + address.level,
|
|
10451
|
+
children: /* @__PURE__ */ jsx15(
|
|
10452
|
+
PanoBasicMaterial,
|
|
10453
|
+
{
|
|
10454
|
+
map: texture,
|
|
10455
|
+
side: BackSide2,
|
|
10456
|
+
depthTest: false,
|
|
10457
|
+
depthWrite: false,
|
|
10458
|
+
toneMapped: false
|
|
10459
|
+
}
|
|
10460
|
+
)
|
|
10461
|
+
}
|
|
10462
|
+
);
|
|
10463
|
+
}
|
|
10464
|
+
var ManagedPatch = memo(function ManagedPatch2({
|
|
10465
|
+
address,
|
|
10466
|
+
manager,
|
|
10467
|
+
resolveUrl,
|
|
10468
|
+
yawOffset,
|
|
10469
|
+
ready
|
|
10470
|
+
}) {
|
|
10471
|
+
const url = resolveUrl(address);
|
|
10472
|
+
const snapshot = useManagedTexture(
|
|
10473
|
+
manager,
|
|
10474
|
+
`${url}\0${sphereTileKey(address)}`,
|
|
10475
|
+
url,
|
|
10476
|
+
address
|
|
10477
|
+
);
|
|
10478
|
+
useEffect22(() => {
|
|
10479
|
+
if (snapshot.texture) ready();
|
|
10480
|
+
}, [snapshot.texture, ready]);
|
|
10481
|
+
return snapshot.texture ? /* @__PURE__ */ jsx15(
|
|
10482
|
+
SpherePatch,
|
|
10483
|
+
{
|
|
10484
|
+
address,
|
|
10485
|
+
texture: snapshot.texture,
|
|
10486
|
+
yawOffset
|
|
10487
|
+
}
|
|
10488
|
+
) : null;
|
|
10489
|
+
});
|
|
10490
|
+
function SphereTileSource({
|
|
10491
|
+
config,
|
|
10492
|
+
baseUrl,
|
|
10493
|
+
previewUrl,
|
|
10494
|
+
urlTemplate = "tiles/%l/%h_%v.webp",
|
|
10495
|
+
indexBase = 1,
|
|
10496
|
+
resolveTileUrl,
|
|
10497
|
+
yawOffset = 0,
|
|
10498
|
+
maxTextureMemoryMb = 128,
|
|
10499
|
+
maxConcurrentLoads = 4,
|
|
10500
|
+
retryCount = 1,
|
|
10501
|
+
loadMode = "full",
|
|
10502
|
+
visible = true,
|
|
10503
|
+
onReady,
|
|
10504
|
+
onPreviewError,
|
|
10505
|
+
onLoadProgress,
|
|
10506
|
+
onTileError,
|
|
10507
|
+
onLevelChange
|
|
10508
|
+
}) {
|
|
10509
|
+
const { camera, gl, size } = useThree13();
|
|
10510
|
+
const anisotropy = gl.capabilities.getMaxAnisotropy();
|
|
10511
|
+
const preview = usePreviewTexture(
|
|
10512
|
+
resolveAssetUrl(baseUrl, previewUrl),
|
|
10513
|
+
anisotropy,
|
|
10514
|
+
onPreviewError
|
|
10515
|
+
);
|
|
10516
|
+
const callbacks = useRef23({
|
|
10517
|
+
onReady,
|
|
10518
|
+
onLoadProgress,
|
|
10519
|
+
onTileError,
|
|
10520
|
+
onLevelChange
|
|
10521
|
+
});
|
|
10522
|
+
callbacks.current = { onReady, onLoadProgress, onTileError, onLevelChange };
|
|
10523
|
+
const budget = Math.max(
|
|
10524
|
+
1,
|
|
10525
|
+
Number.isFinite(maxTextureMemoryMb) ? maxTextureMemoryMb : 128
|
|
10526
|
+
) * 1024 * 1024;
|
|
10527
|
+
const manager = useMemo14(
|
|
10528
|
+
() => new TileTextureManager({
|
|
10529
|
+
anisotropy,
|
|
10530
|
+
maxBytes: budget,
|
|
10531
|
+
concurrency: Math.max(
|
|
10532
|
+
1,
|
|
10533
|
+
Math.floor(
|
|
10534
|
+
Number.isFinite(maxConcurrentLoads) ? maxConcurrentLoads : 4
|
|
10535
|
+
)
|
|
10536
|
+
),
|
|
10537
|
+
retryCount: Math.max(
|
|
10538
|
+
0,
|
|
10539
|
+
Math.floor(Number.isFinite(retryCount) ? retryCount : 1)
|
|
10540
|
+
),
|
|
10541
|
+
onProgress: (progress) => callbacks.current.onLoadProgress?.(progress),
|
|
10542
|
+
onError: (error) => callbacks.current.onTileError?.(error)
|
|
10543
|
+
}),
|
|
10544
|
+
[anisotropy, budget, maxConcurrentLoads, retryCount]
|
|
10545
|
+
);
|
|
10546
|
+
const readyRef = useRef23(false);
|
|
10547
|
+
const ready = useCallback9(() => {
|
|
10548
|
+
if (!readyRef.current) {
|
|
10549
|
+
readyRef.current = true;
|
|
10550
|
+
callbacks.current.onReady?.();
|
|
10551
|
+
}
|
|
10552
|
+
}, []);
|
|
10553
|
+
useEffect22(() => {
|
|
10554
|
+
if (preview) ready();
|
|
10555
|
+
}, [preview, ready]);
|
|
10556
|
+
useEffect22(() => {
|
|
10557
|
+
manager.resume();
|
|
10558
|
+
return () => manager.dispose();
|
|
10559
|
+
}, [manager]);
|
|
10560
|
+
const resolveUrl = useMemo14(
|
|
10561
|
+
() => (address) => resolveAssetUrl(
|
|
10562
|
+
baseUrl,
|
|
10563
|
+
resolveTileUrl ? resolveTileUrl(address) : resolveSphereTemplateUrl(urlTemplate, address, indexBase)
|
|
10564
|
+
),
|
|
10565
|
+
[baseUrl, resolveTileUrl, urlTemplate, indexBase]
|
|
10566
|
+
);
|
|
10567
|
+
const candidates = useMemo14(
|
|
10568
|
+
() => config.levels.map(
|
|
10569
|
+
(level, index) => sphereTileAddresses(level, index, config.tileSize).map((address) => ({
|
|
10570
|
+
address,
|
|
10571
|
+
bounds: sphereTileBounds(address, yawOffset)
|
|
10572
|
+
}))
|
|
10573
|
+
),
|
|
10574
|
+
[config, yawOffset]
|
|
10575
|
+
);
|
|
10576
|
+
const previewAddress = useMemo14(
|
|
10577
|
+
() => sphereTileAddresses({ width: 2, height: 1 }, 0, 2)[0],
|
|
10578
|
+
[]
|
|
10579
|
+
);
|
|
10580
|
+
const [layers, setLayers] = useState10([]);
|
|
10581
|
+
const scratch = useMemo14(
|
|
10582
|
+
() => ({
|
|
10583
|
+
camera: new PerspectiveCamera3(),
|
|
10584
|
+
frustum: new Frustum(),
|
|
10585
|
+
matrix: new Matrix42(),
|
|
10586
|
+
quaternion: camera.quaternion.clone(),
|
|
10587
|
+
fov: NaN,
|
|
10588
|
+
width: 0,
|
|
10589
|
+
height: 0,
|
|
10590
|
+
dpr: 0,
|
|
10591
|
+
time: -Infinity,
|
|
10592
|
+
token: "",
|
|
10593
|
+
level: -1,
|
|
10594
|
+
loadMode: "",
|
|
10595
|
+
manager: null
|
|
10596
|
+
}),
|
|
10597
|
+
[camera, candidates]
|
|
10598
|
+
);
|
|
10599
|
+
useFrame9(() => {
|
|
10600
|
+
if (!(camera instanceof PerspectiveCamera3)) return;
|
|
10601
|
+
const now = performance.now(), dpr = gl.getPixelRatio();
|
|
10602
|
+
const reset = scratch.manager !== manager || scratch.loadMode !== loadMode;
|
|
10603
|
+
if (!reset && (now - scratch.time < 100 || scratch.fov === camera.fov && scratch.width === size.width && scratch.height === size.height && scratch.dpr === dpr && scratch.quaternion.angleTo(camera.quaternion) < 1e-4))
|
|
10604
|
+
return;
|
|
10605
|
+
scratch.time = now;
|
|
10606
|
+
scratch.fov = camera.fov;
|
|
10607
|
+
scratch.width = size.width;
|
|
10608
|
+
scratch.height = size.height;
|
|
10609
|
+
scratch.dpr = dpr;
|
|
10610
|
+
scratch.quaternion.copy(camera.quaternion);
|
|
10611
|
+
scratch.manager = manager;
|
|
10612
|
+
scratch.loadMode = loadMode;
|
|
10613
|
+
scratch.camera.copy(camera, false);
|
|
10614
|
+
scratch.camera.fov = Math.min(179, camera.fov + 8);
|
|
10615
|
+
scratch.camera.updateProjectionMatrix();
|
|
10616
|
+
scratch.camera.updateMatrixWorld();
|
|
10617
|
+
scratch.matrix.multiplyMatrices(
|
|
10618
|
+
scratch.camera.projectionMatrix,
|
|
10619
|
+
scratch.camera.matrixWorldInverse
|
|
10620
|
+
);
|
|
10621
|
+
scratch.frustum.setFromProjectionMatrix(scratch.matrix);
|
|
10622
|
+
let level = loadMode === "preview" ? -1 : loadMode === "base" ? 0 : preferredSphereLevel(config.levels, size.height, dpr, camera.fov);
|
|
10623
|
+
const next = [];
|
|
10624
|
+
let residentBytes = 0;
|
|
10625
|
+
for (let index = 0; index <= level; index++) {
|
|
10626
|
+
const addresses = candidates[index].filter(
|
|
10627
|
+
({ bounds }) => scratch.frustum.intersectsBox(bounds)
|
|
10628
|
+
).map(({ address }) => address);
|
|
10629
|
+
const bytes = addresses.reduce(
|
|
10630
|
+
(total, address) => total + address.width * address.height * 4,
|
|
10631
|
+
0
|
|
10632
|
+
);
|
|
10633
|
+
if (residentBytes + bytes > budget) {
|
|
10634
|
+
level = index - 1;
|
|
10635
|
+
break;
|
|
10636
|
+
}
|
|
10637
|
+
residentBytes += bytes;
|
|
10638
|
+
next.push({ level: index, addresses });
|
|
10639
|
+
}
|
|
10640
|
+
if (level !== scratch.level) {
|
|
10641
|
+
scratch.level = level;
|
|
10642
|
+
if (level >= 0) callbacks.current.onLevelChange?.(level);
|
|
10643
|
+
}
|
|
10644
|
+
const token = next.map((layer) => layer.addresses.map(sphereTileKey).join(",")).join(";");
|
|
10645
|
+
if (token !== scratch.token || reset) {
|
|
10646
|
+
scratch.token = token;
|
|
10647
|
+
setLayers(next);
|
|
10648
|
+
}
|
|
10649
|
+
});
|
|
10650
|
+
return /* @__PURE__ */ jsxs9("group", { visible, children: [
|
|
10651
|
+
preview ? /* @__PURE__ */ jsx15(
|
|
10652
|
+
SpherePatch,
|
|
10653
|
+
{
|
|
10654
|
+
address: previewAddress,
|
|
10655
|
+
texture: preview,
|
|
10656
|
+
yawOffset,
|
|
10657
|
+
preview: true
|
|
10658
|
+
}
|
|
10659
|
+
) : null,
|
|
10660
|
+
loadMode !== "preview" ? layers.flatMap(
|
|
10661
|
+
(layer) => layer.addresses.map((address) => /* @__PURE__ */ jsx15(
|
|
10662
|
+
ManagedPatch,
|
|
10663
|
+
{
|
|
10664
|
+
address,
|
|
10665
|
+
manager,
|
|
10666
|
+
resolveUrl,
|
|
10667
|
+
yawOffset,
|
|
10668
|
+
ready
|
|
10669
|
+
},
|
|
10670
|
+
sphereTileKey(address)
|
|
10671
|
+
))
|
|
10672
|
+
) : null
|
|
10673
|
+
] });
|
|
10674
|
+
}
|
|
10675
|
+
function SphereTile({ multires, ...props }) {
|
|
10676
|
+
const token = typeof multires === "string" ? multires : JSON.stringify(multires);
|
|
10677
|
+
const config = useMemo14(() => parseSphereMultires(multires), [token]);
|
|
10678
|
+
const sourceKey = `${props.baseUrl}\0${token}\0${props.previewUrl}\0${props.urlTemplate ?? ""}\0${props.indexBase ?? 1}`;
|
|
10679
|
+
return /* @__PURE__ */ jsx15(SphereTileSource, { ...props, config }, sourceKey);
|
|
10680
|
+
}
|
|
10681
|
+
|
|
10682
|
+
// src/sphere.tsx
|
|
10038
10683
|
import { useThree as useThree14 } from "@react-three/fiber";
|
|
10684
|
+
import { useEffect as useEffect23, useMemo as useMemo15, useRef as useRef24, useState as useState11 } from "react";
|
|
10685
|
+
import {
|
|
10686
|
+
BackSide as BackSide3,
|
|
10687
|
+
LinearFilter as LinearFilter3,
|
|
10688
|
+
LinearMipmapLinearFilter,
|
|
10689
|
+
MathUtils as MathUtils6,
|
|
10690
|
+
RepeatWrapping,
|
|
10691
|
+
SRGBColorSpace as SRGBColorSpace3,
|
|
10692
|
+
TextureLoader as TextureLoader3
|
|
10693
|
+
} from "three";
|
|
10694
|
+
import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
10695
|
+
function useEquirectTexture(url, anisotropy, generateMipmaps, onLoad, onError) {
|
|
10696
|
+
const [texture, setTexture] = useState11(null);
|
|
10697
|
+
const onLoadRef = useRef24(onLoad);
|
|
10698
|
+
const onErrorRef = useRef24(onError);
|
|
10699
|
+
onLoadRef.current = onLoad;
|
|
10700
|
+
onErrorRef.current = onError;
|
|
10701
|
+
useEffect23(() => {
|
|
10702
|
+
if (!url) {
|
|
10703
|
+
setTexture(null);
|
|
10704
|
+
return;
|
|
10705
|
+
}
|
|
10706
|
+
let active = true;
|
|
10707
|
+
const loader = new TextureLoader3();
|
|
10708
|
+
setTexture(null);
|
|
10709
|
+
loader.load(
|
|
10710
|
+
url,
|
|
10711
|
+
(loadedTexture) => {
|
|
10712
|
+
if (!active) {
|
|
10713
|
+
loadedTexture.dispose();
|
|
10714
|
+
return;
|
|
10715
|
+
}
|
|
10716
|
+
loadedTexture.colorSpace = SRGBColorSpace3;
|
|
10717
|
+
loadedTexture.wrapS = RepeatWrapping;
|
|
10718
|
+
loadedTexture.repeat.x = -1;
|
|
10719
|
+
loadedTexture.offset.x = 1;
|
|
10720
|
+
loadedTexture.anisotropy = anisotropy;
|
|
10721
|
+
loadedTexture.magFilter = LinearFilter3;
|
|
10722
|
+
loadedTexture.minFilter = generateMipmaps ? LinearMipmapLinearFilter : LinearFilter3;
|
|
10723
|
+
loadedTexture.generateMipmaps = generateMipmaps;
|
|
10724
|
+
loadedTexture.needsUpdate = true;
|
|
10725
|
+
setTexture(loadedTexture);
|
|
10726
|
+
onLoadRef.current?.(loadedTexture);
|
|
10727
|
+
},
|
|
10728
|
+
void 0,
|
|
10729
|
+
(error) => {
|
|
10730
|
+
if (active) {
|
|
10731
|
+
setTexture(null);
|
|
10732
|
+
onErrorRef.current?.(error);
|
|
10733
|
+
}
|
|
10734
|
+
}
|
|
10735
|
+
);
|
|
10736
|
+
return () => {
|
|
10737
|
+
active = false;
|
|
10738
|
+
};
|
|
10739
|
+
}, [anisotropy, generateMipmaps, url]);
|
|
10740
|
+
useEffect23(
|
|
10741
|
+
() => () => {
|
|
10742
|
+
texture?.dispose();
|
|
10743
|
+
},
|
|
10744
|
+
[texture]
|
|
10745
|
+
);
|
|
10746
|
+
return texture;
|
|
10747
|
+
}
|
|
10748
|
+
function Sphere({
|
|
10749
|
+
src,
|
|
10750
|
+
previewUrl,
|
|
10751
|
+
yawOffset = 0,
|
|
10752
|
+
onReady,
|
|
10753
|
+
onLoad,
|
|
10754
|
+
onError,
|
|
10755
|
+
onPreviewError,
|
|
10756
|
+
visible = true
|
|
10757
|
+
}) {
|
|
10758
|
+
const gl = useThree14((state) => state.gl);
|
|
10759
|
+
const anisotropy = gl.capabilities.getMaxAnisotropy();
|
|
10760
|
+
const resolvedPreviewUrl = useMemo15(
|
|
10761
|
+
() => resolveUrlAgainstFile(src, previewUrl),
|
|
10762
|
+
[previewUrl, src]
|
|
10763
|
+
);
|
|
10764
|
+
const texture = useEquirectTexture(
|
|
10765
|
+
src,
|
|
10766
|
+
anisotropy,
|
|
10767
|
+
true,
|
|
10768
|
+
onLoad,
|
|
10769
|
+
onError
|
|
10770
|
+
);
|
|
10771
|
+
const previewTexture = useEquirectTexture(
|
|
10772
|
+
texture ? null : resolvedPreviewUrl,
|
|
10773
|
+
anisotropy,
|
|
10774
|
+
false,
|
|
10775
|
+
void 0,
|
|
10776
|
+
onPreviewError
|
|
10777
|
+
);
|
|
10778
|
+
const displayTexture = texture ?? previewTexture;
|
|
10779
|
+
const readyRef = useRef24(false);
|
|
10780
|
+
useEffect23(() => {
|
|
10781
|
+
readyRef.current = false;
|
|
10782
|
+
}, [resolvedPreviewUrl, src]);
|
|
10783
|
+
useEffect23(() => {
|
|
10784
|
+
if (!displayTexture || readyRef.current) {
|
|
10785
|
+
return;
|
|
10786
|
+
}
|
|
10787
|
+
readyRef.current = true;
|
|
10788
|
+
onReady?.();
|
|
10789
|
+
}, [displayTexture, onReady]);
|
|
10790
|
+
if (!displayTexture) {
|
|
10791
|
+
return null;
|
|
10792
|
+
}
|
|
10793
|
+
return /* @__PURE__ */ jsxs10(
|
|
10794
|
+
"mesh",
|
|
10795
|
+
{
|
|
10796
|
+
rotation: [0, MathUtils6.degToRad(90 + yawOffset), 0],
|
|
10797
|
+
visible,
|
|
10798
|
+
children: [
|
|
10799
|
+
/* @__PURE__ */ jsx16("sphereGeometry", { args: [DEFAULT_PANORAMA_RADIUS, 128, 64] }),
|
|
10800
|
+
/* @__PURE__ */ jsx16(
|
|
10801
|
+
PanoBasicMaterial,
|
|
10802
|
+
{
|
|
10803
|
+
map: displayTexture,
|
|
10804
|
+
side: BackSide3,
|
|
10805
|
+
toneMapped: false
|
|
10806
|
+
}
|
|
10807
|
+
)
|
|
10808
|
+
]
|
|
10809
|
+
}
|
|
10810
|
+
);
|
|
10811
|
+
}
|
|
10812
|
+
|
|
10813
|
+
// src/video/pano-video.tsx
|
|
10814
|
+
import { useThree as useThree15 } from "@react-three/fiber";
|
|
10039
10815
|
import {
|
|
10040
|
-
useCallback as
|
|
10816
|
+
useCallback as useCallback10,
|
|
10041
10817
|
useContext as useContext21,
|
|
10042
|
-
useEffect as
|
|
10818
|
+
useEffect as useEffect24,
|
|
10043
10819
|
useLayoutEffect as useLayoutEffect3,
|
|
10044
|
-
useMemo as
|
|
10045
|
-
useRef as
|
|
10046
|
-
useState as
|
|
10820
|
+
useMemo as useMemo16,
|
|
10821
|
+
useRef as useRef25,
|
|
10822
|
+
useState as useState12
|
|
10047
10823
|
} from "react";
|
|
10048
10824
|
import {
|
|
10049
|
-
BackSide as
|
|
10050
|
-
LinearFilter as
|
|
10825
|
+
BackSide as BackSide4,
|
|
10826
|
+
LinearFilter as LinearFilter4,
|
|
10051
10827
|
LinearMipmapLinearFilter as LinearMipmapLinearFilter2,
|
|
10052
|
-
MathUtils as
|
|
10828
|
+
MathUtils as MathUtils7,
|
|
10053
10829
|
RepeatWrapping as RepeatWrapping2,
|
|
10054
|
-
SRGBColorSpace as
|
|
10055
|
-
TextureLoader as
|
|
10830
|
+
SRGBColorSpace as SRGBColorSpace4,
|
|
10831
|
+
TextureLoader as TextureLoader4,
|
|
10056
10832
|
VideoTexture
|
|
10057
10833
|
} from "three";
|
|
10058
|
-
import { Fragment as Fragment5, jsx as
|
|
10834
|
+
import { Fragment as Fragment5, jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
10059
10835
|
var EMPTY_TRACKS = [];
|
|
10060
10836
|
var EMPTY_RATES = DEFAULT_PANO_VIDEO_PLAYBACK_RATES;
|
|
10061
10837
|
function createEmptySnapshot() {
|
|
@@ -10131,7 +10907,7 @@ function findTextTrack(video, tracks, trackId) {
|
|
|
10131
10907
|
return list.length > 0 ? list[0] : null;
|
|
10132
10908
|
}
|
|
10133
10909
|
function applyEquirectangularLayout(texture, anisotropy) {
|
|
10134
|
-
texture.colorSpace =
|
|
10910
|
+
texture.colorSpace = SRGBColorSpace4;
|
|
10135
10911
|
texture.wrapS = RepeatWrapping2;
|
|
10136
10912
|
texture.repeat.x = -1;
|
|
10137
10913
|
texture.offset.x = 1;
|
|
@@ -10139,11 +10915,11 @@ function applyEquirectangularLayout(texture, anisotropy) {
|
|
|
10139
10915
|
texture.needsUpdate = true;
|
|
10140
10916
|
}
|
|
10141
10917
|
function usePosterTexture(poster, onError) {
|
|
10142
|
-
const gl =
|
|
10143
|
-
const [texture, setTexture] =
|
|
10144
|
-
const onErrorRef =
|
|
10918
|
+
const gl = useThree15((state) => state.gl);
|
|
10919
|
+
const [texture, setTexture] = useState12(null);
|
|
10920
|
+
const onErrorRef = useRef25(onError);
|
|
10145
10921
|
onErrorRef.current = onError;
|
|
10146
|
-
|
|
10922
|
+
useEffect24(() => {
|
|
10147
10923
|
let active = true;
|
|
10148
10924
|
setTexture(null);
|
|
10149
10925
|
if (!poster) {
|
|
@@ -10151,7 +10927,7 @@ function usePosterTexture(poster, onError) {
|
|
|
10151
10927
|
active = false;
|
|
10152
10928
|
};
|
|
10153
10929
|
}
|
|
10154
|
-
const loader = new
|
|
10930
|
+
const loader = new TextureLoader4();
|
|
10155
10931
|
loader.load(
|
|
10156
10932
|
poster,
|
|
10157
10933
|
(loadedTexture) => {
|
|
@@ -10164,7 +10940,7 @@ function usePosterTexture(poster, onError) {
|
|
|
10164
10940
|
gl.capabilities.getMaxAnisotropy()
|
|
10165
10941
|
);
|
|
10166
10942
|
loadedTexture.wrapT = RepeatWrapping2;
|
|
10167
|
-
loadedTexture.magFilter =
|
|
10943
|
+
loadedTexture.magFilter = LinearFilter4;
|
|
10168
10944
|
loadedTexture.minFilter = LinearMipmapLinearFilter2;
|
|
10169
10945
|
loadedTexture.generateMipmaps = true;
|
|
10170
10946
|
setTexture(loadedTexture);
|
|
@@ -10180,7 +10956,7 @@ function usePosterTexture(poster, onError) {
|
|
|
10180
10956
|
active = false;
|
|
10181
10957
|
};
|
|
10182
10958
|
}, [gl, poster]);
|
|
10183
|
-
|
|
10959
|
+
useEffect24(
|
|
10184
10960
|
() => () => {
|
|
10185
10961
|
texture?.dispose();
|
|
10186
10962
|
},
|
|
@@ -10238,39 +11014,39 @@ function PanoVideo({
|
|
|
10238
11014
|
onTrackChange
|
|
10239
11015
|
}) {
|
|
10240
11016
|
usePanoMediaActivationIntent(autoPlay);
|
|
10241
|
-
const gl =
|
|
11017
|
+
const gl = useThree15((state) => state.gl);
|
|
10242
11018
|
const host = useContext21(PanoVideoHostContext);
|
|
10243
11019
|
const overlay = useContext21(PanoChromeOverlayContext);
|
|
10244
|
-
const variants =
|
|
11020
|
+
const variants = useMemo16(
|
|
10245
11021
|
() => resolvePanoVideoVariants({ poster, src, variants: variantsProp }),
|
|
10246
11022
|
[poster, src, variantsProp]
|
|
10247
11023
|
);
|
|
10248
11024
|
const tracks = tracksProp ?? EMPTY_TRACKS;
|
|
10249
11025
|
const captionsEnabled = captions !== false;
|
|
10250
|
-
const captionAppearance =
|
|
11026
|
+
const captionAppearance = useMemo16(
|
|
10251
11027
|
() => resolvePanoVideoCaptionAppearance(
|
|
10252
11028
|
typeof captions === "object" ? captions : void 0
|
|
10253
11029
|
),
|
|
10254
11030
|
[captions]
|
|
10255
11031
|
);
|
|
10256
|
-
const [variantId, setVariantId] =
|
|
11032
|
+
const [variantId, setVariantId] = useState12(
|
|
10257
11033
|
() => resolvePanoVideoVariantId(variants, defaultVariantId)
|
|
10258
11034
|
);
|
|
10259
|
-
const [trackId, setTrackId] =
|
|
11035
|
+
const [trackId, setTrackId] = useState12(
|
|
10260
11036
|
() => captionsEnabled ? defaultPanoVideoTrackId(tracks) : null
|
|
10261
11037
|
);
|
|
10262
|
-
const [ready, setReady] =
|
|
10263
|
-
const autoPlayRef =
|
|
11038
|
+
const [ready, setReady] = useState12(false);
|
|
11039
|
+
const autoPlayRef = useRef25(autoPlay);
|
|
10264
11040
|
autoPlayRef.current = autoPlay;
|
|
10265
|
-
const blockedRef =
|
|
10266
|
-
const captionAppearanceOverrideRef =
|
|
11041
|
+
const blockedRef = useRef25(false);
|
|
11042
|
+
const captionAppearanceOverrideRef = useRef25(
|
|
10267
11043
|
{}
|
|
10268
11044
|
);
|
|
10269
|
-
const mediaCapabilitiesRef =
|
|
11045
|
+
const mediaCapabilitiesRef = useRef25({
|
|
10270
11046
|
volumeAdjustable: true,
|
|
10271
11047
|
playbackRates: [...DEFAULT_PANO_VIDEO_PLAYBACK_RATES]
|
|
10272
11048
|
});
|
|
10273
|
-
const storeRef =
|
|
11049
|
+
const storeRef = useRef25(null);
|
|
10274
11050
|
if (!storeRef.current) {
|
|
10275
11051
|
storeRef.current = {
|
|
10276
11052
|
snapshot: {
|
|
@@ -10280,7 +11056,7 @@ function PanoVideo({
|
|
|
10280
11056
|
listeners: /* @__PURE__ */ new Set()
|
|
10281
11057
|
};
|
|
10282
11058
|
}
|
|
10283
|
-
const actionsRef =
|
|
11059
|
+
const actionsRef = useRef25({
|
|
10284
11060
|
play: async () => {
|
|
10285
11061
|
},
|
|
10286
11062
|
pause: () => {
|
|
@@ -10300,19 +11076,19 @@ function PanoVideo({
|
|
|
10300
11076
|
setCaptionAppearance: (_appearance) => {
|
|
10301
11077
|
}
|
|
10302
11078
|
});
|
|
10303
|
-
const onLoadRef =
|
|
10304
|
-
const onErrorRef =
|
|
10305
|
-
const onPlaybackStateChangeRef =
|
|
10306
|
-
const onEndedRef =
|
|
10307
|
-
const onVariantChangeRef =
|
|
10308
|
-
const onTrackChangeRef =
|
|
11079
|
+
const onLoadRef = useRef25(onLoad);
|
|
11080
|
+
const onErrorRef = useRef25(onError);
|
|
11081
|
+
const onPlaybackStateChangeRef = useRef25(onPlaybackStateChange);
|
|
11082
|
+
const onEndedRef = useRef25(onEnded);
|
|
11083
|
+
const onVariantChangeRef = useRef25(onVariantChange);
|
|
11084
|
+
const onTrackChangeRef = useRef25(onTrackChange);
|
|
10309
11085
|
onLoadRef.current = onLoad;
|
|
10310
11086
|
onErrorRef.current = onError;
|
|
10311
11087
|
onPlaybackStateChangeRef.current = onPlaybackStateChange;
|
|
10312
11088
|
onEndedRef.current = onEnded;
|
|
10313
11089
|
onVariantChangeRef.current = onVariantChange;
|
|
10314
11090
|
onTrackChangeRef.current = onTrackChange;
|
|
10315
|
-
const resource =
|
|
11091
|
+
const resource = useMemo16(() => {
|
|
10316
11092
|
if (typeof document === "undefined") {
|
|
10317
11093
|
return null;
|
|
10318
11094
|
}
|
|
@@ -10324,12 +11100,12 @@ function PanoVideo({
|
|
|
10324
11100
|
video.preload = "metadata";
|
|
10325
11101
|
const texture = new VideoTexture(video);
|
|
10326
11102
|
applyEquirectangularLayout(texture, 1);
|
|
10327
|
-
texture.magFilter =
|
|
10328
|
-
texture.minFilter =
|
|
11103
|
+
texture.magFilter = LinearFilter4;
|
|
11104
|
+
texture.minFilter = LinearFilter4;
|
|
10329
11105
|
texture.generateMipmaps = false;
|
|
10330
11106
|
return { video, texture };
|
|
10331
11107
|
}, []);
|
|
10332
|
-
|
|
11108
|
+
useEffect24(
|
|
10333
11109
|
() => () => {
|
|
10334
11110
|
if (!resource) {
|
|
10335
11111
|
return;
|
|
@@ -10344,13 +11120,13 @@ function PanoVideo({
|
|
|
10344
11120
|
},
|
|
10345
11121
|
[resource]
|
|
10346
11122
|
);
|
|
10347
|
-
|
|
11123
|
+
useEffect24(() => {
|
|
10348
11124
|
if (!resource) {
|
|
10349
11125
|
return;
|
|
10350
11126
|
}
|
|
10351
11127
|
resource.texture.anisotropy = gl.capabilities.getMaxAnisotropy();
|
|
10352
11128
|
}, [gl, resource]);
|
|
10353
|
-
|
|
11129
|
+
useEffect24(() => {
|
|
10354
11130
|
if (!resource || !overlay?.overlayElement) {
|
|
10355
11131
|
return;
|
|
10356
11132
|
}
|
|
@@ -10373,7 +11149,7 @@ function PanoVideo({
|
|
|
10373
11149
|
activeVariant?.poster ?? poster,
|
|
10374
11150
|
onError
|
|
10375
11151
|
);
|
|
10376
|
-
const emitSnapshot =
|
|
11152
|
+
const emitSnapshot = useCallback10(
|
|
10377
11153
|
(patch) => {
|
|
10378
11154
|
const store = storeRef.current;
|
|
10379
11155
|
const video = resource?.video;
|
|
@@ -10425,7 +11201,7 @@ function PanoVideo({
|
|
|
10425
11201
|
captionAppearance
|
|
10426
11202
|
]
|
|
10427
11203
|
);
|
|
10428
|
-
const controller =
|
|
11204
|
+
const controller = useMemo16(
|
|
10429
11205
|
() => ({
|
|
10430
11206
|
subscribe: (onStoreChange) => {
|
|
10431
11207
|
const store = storeRef.current;
|
|
@@ -10503,10 +11279,10 @@ function PanoVideo({
|
|
|
10503
11279
|
};
|
|
10504
11280
|
emitSnapshot();
|
|
10505
11281
|
}, [emitSnapshot, playbackRates, resource]);
|
|
10506
|
-
|
|
11282
|
+
useEffect24(() => {
|
|
10507
11283
|
emitSnapshot();
|
|
10508
11284
|
}, [emitSnapshot]);
|
|
10509
|
-
|
|
11285
|
+
useEffect24(() => {
|
|
10510
11286
|
if (!resource || !activeVariant || !mediaKey) {
|
|
10511
11287
|
return;
|
|
10512
11288
|
}
|
|
@@ -10563,7 +11339,7 @@ function PanoVideo({
|
|
|
10563
11339
|
video.removeEventListener("error", handleError);
|
|
10564
11340
|
};
|
|
10565
11341
|
}, [mediaKey, resource]);
|
|
10566
|
-
|
|
11342
|
+
useEffect24(() => {
|
|
10567
11343
|
if (!resource) {
|
|
10568
11344
|
return;
|
|
10569
11345
|
}
|
|
@@ -10574,8 +11350,10 @@ function PanoVideo({
|
|
|
10574
11350
|
try {
|
|
10575
11351
|
await video.play();
|
|
10576
11352
|
} catch (error) {
|
|
10577
|
-
|
|
10578
|
-
|
|
11353
|
+
if (isAutoplayPolicyError(error)) {
|
|
11354
|
+
blockedRef.current = true;
|
|
11355
|
+
onPlaybackStateChangeRef.current?.("blocked");
|
|
11356
|
+
}
|
|
10579
11357
|
onErrorRef.current?.({ source: "video", error });
|
|
10580
11358
|
emitSnapshot();
|
|
10581
11359
|
}
|
|
@@ -10653,7 +11431,7 @@ function PanoVideo({
|
|
|
10653
11431
|
}
|
|
10654
11432
|
};
|
|
10655
11433
|
}, [emitSnapshot, resource]);
|
|
10656
|
-
|
|
11434
|
+
useEffect24(() => {
|
|
10657
11435
|
if (!resource) {
|
|
10658
11436
|
return;
|
|
10659
11437
|
}
|
|
@@ -10673,7 +11451,7 @@ function PanoVideo({
|
|
|
10673
11451
|
}
|
|
10674
11452
|
video.preload = preload;
|
|
10675
11453
|
}, [loop, muted, playsInline, preload, resource, volume]);
|
|
10676
|
-
|
|
11454
|
+
useEffect24(() => {
|
|
10677
11455
|
if (!resource) {
|
|
10678
11456
|
return;
|
|
10679
11457
|
}
|
|
@@ -10723,7 +11501,7 @@ function PanoVideo({
|
|
|
10723
11501
|
video.removeEventListener("ratechange", handleVolume);
|
|
10724
11502
|
};
|
|
10725
11503
|
}, [emitSnapshot, resource]);
|
|
10726
|
-
|
|
11504
|
+
useEffect24(() => {
|
|
10727
11505
|
if (!resource) {
|
|
10728
11506
|
return;
|
|
10729
11507
|
}
|
|
@@ -10758,7 +11536,7 @@ function PanoVideo({
|
|
|
10758
11536
|
video.textTracks.removeEventListener("change", applyModes);
|
|
10759
11537
|
};
|
|
10760
11538
|
}, [emitSnapshot, resource, trackId, tracks]);
|
|
10761
|
-
|
|
11539
|
+
useEffect24(() => {
|
|
10762
11540
|
if (!captionsEnabled) {
|
|
10763
11541
|
setTrackId(null);
|
|
10764
11542
|
return;
|
|
@@ -10769,39 +11547,39 @@ function PanoVideo({
|
|
|
10769
11547
|
if (variants.length === 0) {
|
|
10770
11548
|
return null;
|
|
10771
11549
|
}
|
|
10772
|
-
return /* @__PURE__ */
|
|
10773
|
-
activeTexture ? /* @__PURE__ */
|
|
11550
|
+
return /* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
11551
|
+
activeTexture ? /* @__PURE__ */ jsxs11(
|
|
10774
11552
|
"mesh",
|
|
10775
11553
|
{
|
|
10776
|
-
rotation: [0,
|
|
11554
|
+
rotation: [0, MathUtils7.degToRad(90 + yawOffset), 0],
|
|
10777
11555
|
visible,
|
|
10778
11556
|
children: [
|
|
10779
|
-
/* @__PURE__ */
|
|
10780
|
-
/* @__PURE__ */
|
|
11557
|
+
/* @__PURE__ */ jsx17("sphereGeometry", { args: [DEFAULT_PANORAMA_RADIUS, 128, 64] }),
|
|
11558
|
+
/* @__PURE__ */ jsx17(
|
|
10781
11559
|
PanoBasicMaterial,
|
|
10782
11560
|
{
|
|
10783
11561
|
map: activeTexture,
|
|
10784
|
-
side:
|
|
11562
|
+
side: BackSide4,
|
|
10785
11563
|
toneMapped: false
|
|
10786
11564
|
}
|
|
10787
11565
|
)
|
|
10788
11566
|
]
|
|
10789
11567
|
}
|
|
10790
11568
|
) : null,
|
|
10791
|
-
captionsEnabled ? /* @__PURE__ */
|
|
11569
|
+
captionsEnabled ? /* @__PURE__ */ jsx17(PanoVideoCaptions, { appearance: typeof captions === "object" ? captions : void 0 }) : null
|
|
10792
11570
|
] });
|
|
10793
11571
|
}
|
|
10794
11572
|
|
|
10795
11573
|
// src/scenes.tsx
|
|
10796
|
-
import { useFrame as
|
|
11574
|
+
import { useFrame as useFrame13, useThree as useThree20 } from "@react-three/fiber";
|
|
10797
11575
|
import {
|
|
10798
11576
|
Fragment as Fragment6,
|
|
10799
|
-
useCallback as
|
|
11577
|
+
useCallback as useCallback11,
|
|
10800
11578
|
useContext as useContext23,
|
|
10801
|
-
useEffect as
|
|
10802
|
-
useMemo as
|
|
10803
|
-
useRef as
|
|
10804
|
-
useState as
|
|
11579
|
+
useEffect as useEffect29,
|
|
11580
|
+
useMemo as useMemo21,
|
|
11581
|
+
useRef as useRef29,
|
|
11582
|
+
useState as useState14
|
|
10805
11583
|
} from "react";
|
|
10806
11584
|
import {
|
|
10807
11585
|
LinearSRGBColorSpace,
|
|
@@ -10856,8 +11634,8 @@ function isSnapshotTransition(preset) {
|
|
|
10856
11634
|
}
|
|
10857
11635
|
|
|
10858
11636
|
// src/scene-transitions/particle-overlay.tsx
|
|
10859
|
-
import { useFrame as
|
|
10860
|
-
import { useEffect as
|
|
11637
|
+
import { useFrame as useFrame10, useThree as useThree16 } from "@react-three/fiber";
|
|
11638
|
+
import { useEffect as useEffect25, useMemo as useMemo17, useRef as useRef26 } from "react";
|
|
10861
11639
|
import {
|
|
10862
11640
|
DoubleSide as DoubleSide2,
|
|
10863
11641
|
InstancedBufferAttribute,
|
|
@@ -10865,7 +11643,7 @@ import {
|
|
|
10865
11643
|
PlaneGeometry as PlaneGeometry3,
|
|
10866
11644
|
ShaderMaterial as ShaderMaterial2,
|
|
10867
11645
|
Vector2 as Vector24,
|
|
10868
|
-
Vector3 as
|
|
11646
|
+
Vector3 as Vector310
|
|
10869
11647
|
} from "three";
|
|
10870
11648
|
|
|
10871
11649
|
// src/scene-transitions/glsl.ts
|
|
@@ -10920,7 +11698,7 @@ function overlayProgress(elapsedTime, duration, startTime) {
|
|
|
10920
11698
|
}
|
|
10921
11699
|
|
|
10922
11700
|
// src/scene-transitions/particle-overlay.tsx
|
|
10923
|
-
import { jsx as
|
|
11701
|
+
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
10924
11702
|
var PARTICLE_GRID = 48;
|
|
10925
11703
|
var PARTICLE_COUNT = PARTICLE_GRID * PARTICLE_GRID;
|
|
10926
11704
|
var PARTICLE_VERTEX_SHADER = `
|
|
@@ -10996,13 +11774,13 @@ function ParticleOverlay({
|
|
|
10996
11774
|
runId,
|
|
10997
11775
|
onFinish
|
|
10998
11776
|
}) {
|
|
10999
|
-
const { camera } =
|
|
11000
|
-
const meshRef =
|
|
11001
|
-
const startRef =
|
|
11002
|
-
const finishedRef =
|
|
11003
|
-
const directionRef =
|
|
11004
|
-
const geometry =
|
|
11005
|
-
const material =
|
|
11777
|
+
const { camera } = useThree16();
|
|
11778
|
+
const meshRef = useRef26(null);
|
|
11779
|
+
const startRef = useRef26(null);
|
|
11780
|
+
const finishedRef = useRef26(false);
|
|
11781
|
+
const directionRef = useRef26(new Vector310());
|
|
11782
|
+
const geometry = useMemo17(() => createParticleGeometry(), []);
|
|
11783
|
+
const material = useMemo17(
|
|
11006
11784
|
() => new ShaderMaterial2({
|
|
11007
11785
|
transparent: true,
|
|
11008
11786
|
depthTest: false,
|
|
@@ -11018,14 +11796,14 @@ function ParticleOverlay({
|
|
|
11018
11796
|
}),
|
|
11019
11797
|
[snapshot.texture]
|
|
11020
11798
|
);
|
|
11021
|
-
|
|
11022
|
-
|
|
11023
|
-
|
|
11799
|
+
useEffect25(() => () => geometry.dispose(), [geometry]);
|
|
11800
|
+
useEffect25(() => () => material.dispose(), [material]);
|
|
11801
|
+
useEffect25(() => {
|
|
11024
11802
|
startRef.current = null;
|
|
11025
11803
|
finishedRef.current = false;
|
|
11026
11804
|
material.uniforms.progress.value = 0;
|
|
11027
11805
|
}, [material, runId]);
|
|
11028
|
-
|
|
11806
|
+
useFrame10((state) => {
|
|
11029
11807
|
const mesh = meshRef.current;
|
|
11030
11808
|
if (!mesh || !isPerspectiveCamera(camera)) {
|
|
11031
11809
|
return;
|
|
@@ -11042,7 +11820,7 @@ function ParticleOverlay({
|
|
|
11042
11820
|
onFinish();
|
|
11043
11821
|
}
|
|
11044
11822
|
});
|
|
11045
|
-
return /* @__PURE__ */
|
|
11823
|
+
return /* @__PURE__ */ jsx18(
|
|
11046
11824
|
"mesh",
|
|
11047
11825
|
{
|
|
11048
11826
|
ref: meshRef,
|
|
@@ -11055,9 +11833,9 @@ function ParticleOverlay({
|
|
|
11055
11833
|
}
|
|
11056
11834
|
|
|
11057
11835
|
// src/scene-transitions/snapshot-overlay.tsx
|
|
11058
|
-
import { useFrame as
|
|
11059
|
-
import { useEffect as
|
|
11060
|
-
import { Vector3 as
|
|
11836
|
+
import { useFrame as useFrame11, useThree as useThree17 } from "@react-three/fiber";
|
|
11837
|
+
import { useEffect as useEffect26, useMemo as useMemo18, useRef as useRef27 } from "react";
|
|
11838
|
+
import { Vector3 as Vector311 } from "three";
|
|
11061
11839
|
|
|
11062
11840
|
// src/scene-transitions/snapshot-shaders.ts
|
|
11063
11841
|
import { DoubleSide as DoubleSide3, ShaderMaterial as ShaderMaterial3, Vector2 as Vector25 } from "three";
|
|
@@ -11336,7 +12114,7 @@ function createSnapshotMaterial(preset, texture) {
|
|
|
11336
12114
|
}
|
|
11337
12115
|
|
|
11338
12116
|
// src/scene-transitions/snapshot-overlay.tsx
|
|
11339
|
-
import { jsx as
|
|
12117
|
+
import { jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
11340
12118
|
function SnapshotOverlay({
|
|
11341
12119
|
snapshot,
|
|
11342
12120
|
transition,
|
|
@@ -11344,26 +12122,26 @@ function SnapshotOverlay({
|
|
|
11344
12122
|
runId,
|
|
11345
12123
|
onFinish
|
|
11346
12124
|
}) {
|
|
11347
|
-
const { camera, gl } =
|
|
11348
|
-
const meshRef =
|
|
11349
|
-
const startRef =
|
|
11350
|
-
const finishedRef =
|
|
11351
|
-
const directionRef =
|
|
11352
|
-
const material =
|
|
12125
|
+
const { camera, gl } = useThree17();
|
|
12126
|
+
const meshRef = useRef27(null);
|
|
12127
|
+
const startRef = useRef27(null);
|
|
12128
|
+
const finishedRef = useRef27(false);
|
|
12129
|
+
const directionRef = useRef27(new Vector311());
|
|
12130
|
+
const material = useMemo18(() => {
|
|
11353
12131
|
if (!isSnapshotTransition(transition.preset)) {
|
|
11354
12132
|
return null;
|
|
11355
12133
|
}
|
|
11356
12134
|
return createSnapshotMaterial(transition.preset, snapshot.texture);
|
|
11357
12135
|
}, [snapshot.texture, transition.preset]);
|
|
11358
|
-
|
|
11359
|
-
|
|
12136
|
+
useEffect26(() => () => material?.dispose(), [material]);
|
|
12137
|
+
useEffect26(() => {
|
|
11360
12138
|
startRef.current = null;
|
|
11361
12139
|
finishedRef.current = false;
|
|
11362
12140
|
if (material) {
|
|
11363
12141
|
material.uniforms.progress.value = 0;
|
|
11364
12142
|
}
|
|
11365
12143
|
}, [material, runId]);
|
|
11366
|
-
|
|
12144
|
+
useFrame11((state) => {
|
|
11367
12145
|
const mesh = meshRef.current;
|
|
11368
12146
|
if (!mesh || !material || !isPerspectiveCamera(camera)) {
|
|
11369
12147
|
return;
|
|
@@ -11385,21 +12163,21 @@ function SnapshotOverlay({
|
|
|
11385
12163
|
if (!material) {
|
|
11386
12164
|
return null;
|
|
11387
12165
|
}
|
|
11388
|
-
return /* @__PURE__ */
|
|
11389
|
-
/* @__PURE__ */
|
|
11390
|
-
/* @__PURE__ */
|
|
12166
|
+
return /* @__PURE__ */ jsxs12("mesh", { ref: meshRef, renderOrder: OVERLAY_RENDER_ORDER, frustumCulled: false, children: [
|
|
12167
|
+
/* @__PURE__ */ jsx19("primitive", { attach: "geometry", object: FULLSCREEN_PLANE }),
|
|
12168
|
+
/* @__PURE__ */ jsx19("primitive", { attach: "material", object: material })
|
|
11391
12169
|
] });
|
|
11392
12170
|
}
|
|
11393
12171
|
|
|
11394
12172
|
// src/scene-transitions/transition-overlay.tsx
|
|
11395
|
-
import { jsx as
|
|
12173
|
+
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
11396
12174
|
function TransitionOverlay(props) {
|
|
11397
12175
|
const { preset } = props.transition;
|
|
11398
12176
|
switch (preset) {
|
|
11399
12177
|
case "none":
|
|
11400
12178
|
return null;
|
|
11401
12179
|
case "particles":
|
|
11402
|
-
return /* @__PURE__ */
|
|
12180
|
+
return /* @__PURE__ */ jsx20(ParticleOverlay, { ...props });
|
|
11403
12181
|
case "crossfade":
|
|
11404
12182
|
case "zoom":
|
|
11405
12183
|
case "blackout":
|
|
@@ -11427,7 +12205,7 @@ function TransitionOverlay(props) {
|
|
|
11427
12205
|
case "zoomBlur":
|
|
11428
12206
|
case "hexDissolve":
|
|
11429
12207
|
case "filmBurn":
|
|
11430
|
-
return /* @__PURE__ */
|
|
12208
|
+
return /* @__PURE__ */ jsx20(SnapshotOverlay, { ...props });
|
|
11431
12209
|
default: {
|
|
11432
12210
|
const exhaustive = preset;
|
|
11433
12211
|
void exhaustive;
|
|
@@ -11437,242 +12215,14 @@ function TransitionOverlay(props) {
|
|
|
11437
12215
|
}
|
|
11438
12216
|
|
|
11439
12217
|
// src/tile/texture-manager-context.tsx
|
|
11440
|
-
import { useThree as
|
|
12218
|
+
import { useThree as useThree18 } from "@react-three/fiber";
|
|
11441
12219
|
import {
|
|
11442
12220
|
createContext as createContext15,
|
|
11443
12221
|
useContext as useContext22,
|
|
11444
|
-
useEffect as
|
|
11445
|
-
useMemo as
|
|
12222
|
+
useEffect as useEffect27,
|
|
12223
|
+
useMemo as useMemo19
|
|
11446
12224
|
} from "react";
|
|
11447
|
-
|
|
11448
|
-
// src/tile/texture-manager.ts
|
|
11449
|
-
import {
|
|
11450
|
-
ClampToEdgeWrapping,
|
|
11451
|
-
LinearFilter as LinearFilter3,
|
|
11452
|
-
SRGBColorSpace as SRGBColorSpace3,
|
|
11453
|
-
TextureLoader as TextureLoader3
|
|
11454
|
-
} from "three";
|
|
11455
|
-
var EMPTY_TEXTURE_SNAPSHOT = {
|
|
11456
|
-
status: "idle",
|
|
11457
|
-
texture: null,
|
|
11458
|
-
error: null
|
|
11459
|
-
};
|
|
11460
|
-
var TileTextureManager = class {
|
|
11461
|
-
constructor(options) {
|
|
11462
|
-
this.loader = new TextureLoader3();
|
|
11463
|
-
this.entries = /* @__PURE__ */ new Map();
|
|
11464
|
-
this.queue = [];
|
|
11465
|
-
this.activeLoads = 0;
|
|
11466
|
-
this.totalBytes = 0;
|
|
11467
|
-
this.requested = 0;
|
|
11468
|
-
this.loaded = 0;
|
|
11469
|
-
this.failed = 0;
|
|
11470
|
-
this.disposed = false;
|
|
11471
|
-
this.generation = 0;
|
|
11472
|
-
this.options = options;
|
|
11473
|
-
}
|
|
11474
|
-
resume() {
|
|
11475
|
-
this.disposed = false;
|
|
11476
|
-
this.drain();
|
|
11477
|
-
}
|
|
11478
|
-
getSnapshot(key) {
|
|
11479
|
-
const entry = this.entries.get(key);
|
|
11480
|
-
return entry ? this.snapshot(entry) : EMPTY_TEXTURE_SNAPSHOT;
|
|
11481
|
-
}
|
|
11482
|
-
acquire(key, url, address, listener) {
|
|
11483
|
-
let entry = this.entries.get(key);
|
|
11484
|
-
if (!entry) {
|
|
11485
|
-
entry = {
|
|
11486
|
-
key,
|
|
11487
|
-
url,
|
|
11488
|
-
address,
|
|
11489
|
-
status: "idle",
|
|
11490
|
-
texture: null,
|
|
11491
|
-
error: null,
|
|
11492
|
-
refs: 0,
|
|
11493
|
-
listeners: /* @__PURE__ */ new Set(),
|
|
11494
|
-
lastUsed: performance.now(),
|
|
11495
|
-
bytes: 0
|
|
11496
|
-
};
|
|
11497
|
-
this.entries.set(key, entry);
|
|
11498
|
-
}
|
|
11499
|
-
entry.refs += 1;
|
|
11500
|
-
entry.lastUsed = performance.now();
|
|
11501
|
-
entry.listeners.add(listener);
|
|
11502
|
-
listener(this.snapshot(entry));
|
|
11503
|
-
if (entry.status === "idle") {
|
|
11504
|
-
entry.status = "queued";
|
|
11505
|
-
this.queue.push(entry);
|
|
11506
|
-
this.requested += 1;
|
|
11507
|
-
this.emitProgress();
|
|
11508
|
-
this.drain();
|
|
11509
|
-
}
|
|
11510
|
-
return () => {
|
|
11511
|
-
entry.listeners.delete(listener);
|
|
11512
|
-
entry.refs = Math.max(0, entry.refs - 1);
|
|
11513
|
-
entry.lastUsed = performance.now();
|
|
11514
|
-
if (entry.refs === 0 && entry.status === "queued") {
|
|
11515
|
-
const queueIndex = this.queue.indexOf(entry);
|
|
11516
|
-
if (queueIndex >= 0) {
|
|
11517
|
-
this.queue.splice(queueIndex, 1);
|
|
11518
|
-
}
|
|
11519
|
-
entry.status = "idle";
|
|
11520
|
-
this.entries.delete(entry.key);
|
|
11521
|
-
this.requested = Math.max(0, this.requested - 1);
|
|
11522
|
-
this.emitProgress();
|
|
11523
|
-
this.drain();
|
|
11524
|
-
return;
|
|
11525
|
-
}
|
|
11526
|
-
this.evict();
|
|
11527
|
-
};
|
|
11528
|
-
}
|
|
11529
|
-
dispose() {
|
|
11530
|
-
this.disposed = true;
|
|
11531
|
-
this.generation += 1;
|
|
11532
|
-
this.queue.length = 0;
|
|
11533
|
-
for (const entry of this.entries.values()) {
|
|
11534
|
-
entry.texture?.dispose();
|
|
11535
|
-
entry.listeners.clear();
|
|
11536
|
-
}
|
|
11537
|
-
this.entries.clear();
|
|
11538
|
-
this.totalBytes = 0;
|
|
11539
|
-
}
|
|
11540
|
-
/**
|
|
11541
|
-
* Releases textures that are no longer rendered by any Tile instance.
|
|
11542
|
-
* Scene transitions call this after the outgoing panorama has been
|
|
11543
|
-
* snapshotted, so the incoming scene never competes with stale GPU tiles.
|
|
11544
|
-
*/
|
|
11545
|
-
releaseUnused() {
|
|
11546
|
-
for (const entry of Array.from(this.entries.values())) {
|
|
11547
|
-
if (entry.refs > 0) {
|
|
11548
|
-
continue;
|
|
11549
|
-
}
|
|
11550
|
-
entry.texture?.dispose();
|
|
11551
|
-
this.totalBytes -= entry.bytes;
|
|
11552
|
-
this.entries.delete(entry.key);
|
|
11553
|
-
}
|
|
11554
|
-
this.totalBytes = Math.max(0, this.totalBytes);
|
|
11555
|
-
}
|
|
11556
|
-
snapshot(entry) {
|
|
11557
|
-
return {
|
|
11558
|
-
status: entry.status,
|
|
11559
|
-
texture: entry.texture,
|
|
11560
|
-
error: entry.error
|
|
11561
|
-
};
|
|
11562
|
-
}
|
|
11563
|
-
notify(entry) {
|
|
11564
|
-
const snapshot = this.snapshot(entry);
|
|
11565
|
-
for (const listener of entry.listeners) {
|
|
11566
|
-
listener(snapshot);
|
|
11567
|
-
}
|
|
11568
|
-
}
|
|
11569
|
-
emitProgress() {
|
|
11570
|
-
this.options.onProgress?.({
|
|
11571
|
-
requested: this.requested,
|
|
11572
|
-
loaded: this.loaded,
|
|
11573
|
-
failed: this.failed,
|
|
11574
|
-
active: this.activeLoads,
|
|
11575
|
-
queued: this.queue.length
|
|
11576
|
-
});
|
|
11577
|
-
}
|
|
11578
|
-
drain() {
|
|
11579
|
-
while (!this.disposed && this.activeLoads < this.options.concurrency && this.queue.length > 0) {
|
|
11580
|
-
const entry = this.queue.shift();
|
|
11581
|
-
if (entry.refs === 0) {
|
|
11582
|
-
entry.status = "idle";
|
|
11583
|
-
this.entries.delete(entry.key);
|
|
11584
|
-
this.requested = Math.max(0, this.requested - 1);
|
|
11585
|
-
continue;
|
|
11586
|
-
}
|
|
11587
|
-
entry.status = "loading";
|
|
11588
|
-
this.activeLoads += 1;
|
|
11589
|
-
this.notify(entry);
|
|
11590
|
-
this.emitProgress();
|
|
11591
|
-
void this.loadAndFinish(entry);
|
|
11592
|
-
}
|
|
11593
|
-
}
|
|
11594
|
-
async load(entry, generation) {
|
|
11595
|
-
let lastError = null;
|
|
11596
|
-
for (let attempt = 0; attempt <= this.options.retryCount; attempt += 1) {
|
|
11597
|
-
try {
|
|
11598
|
-
const texture = await this.loader.loadAsync(entry.url);
|
|
11599
|
-
if (this.disposed || generation !== this.generation) {
|
|
11600
|
-
texture.dispose();
|
|
11601
|
-
return;
|
|
11602
|
-
}
|
|
11603
|
-
this.configureTexture(texture);
|
|
11604
|
-
entry.texture = texture;
|
|
11605
|
-
entry.status = "loaded";
|
|
11606
|
-
entry.error = null;
|
|
11607
|
-
entry.bytes = entry.address.width * entry.address.height * 4;
|
|
11608
|
-
entry.lastUsed = performance.now();
|
|
11609
|
-
this.totalBytes += entry.bytes;
|
|
11610
|
-
this.loaded += 1;
|
|
11611
|
-
this.notify(entry);
|
|
11612
|
-
return;
|
|
11613
|
-
} catch (error) {
|
|
11614
|
-
lastError = error;
|
|
11615
|
-
}
|
|
11616
|
-
}
|
|
11617
|
-
if (!this.disposed && generation === this.generation) {
|
|
11618
|
-
entry.status = "error";
|
|
11619
|
-
entry.error = lastError;
|
|
11620
|
-
this.failed += 1;
|
|
11621
|
-
this.notify(entry);
|
|
11622
|
-
this.options.onError?.({
|
|
11623
|
-
address: entry.address,
|
|
11624
|
-
url: entry.url,
|
|
11625
|
-
error: lastError
|
|
11626
|
-
});
|
|
11627
|
-
}
|
|
11628
|
-
}
|
|
11629
|
-
configureTexture(texture) {
|
|
11630
|
-
texture.colorSpace = SRGBColorSpace3;
|
|
11631
|
-
texture.wrapS = ClampToEdgeWrapping;
|
|
11632
|
-
texture.wrapT = ClampToEdgeWrapping;
|
|
11633
|
-
texture.magFilter = LinearFilter3;
|
|
11634
|
-
texture.minFilter = LinearFilter3;
|
|
11635
|
-
texture.generateMipmaps = false;
|
|
11636
|
-
texture.anisotropy = Math.min(4, this.options.anisotropy);
|
|
11637
|
-
texture.needsUpdate = true;
|
|
11638
|
-
}
|
|
11639
|
-
evict() {
|
|
11640
|
-
if (this.totalBytes <= this.options.maxBytes) {
|
|
11641
|
-
return;
|
|
11642
|
-
}
|
|
11643
|
-
const candidates = Array.from(this.entries.values()).filter((entry) => entry.refs === 0 && entry.texture).sort((a, b) => a.lastUsed - b.lastUsed);
|
|
11644
|
-
for (const entry of candidates) {
|
|
11645
|
-
if (this.totalBytes <= this.options.maxBytes) {
|
|
11646
|
-
break;
|
|
11647
|
-
}
|
|
11648
|
-
entry.texture?.dispose();
|
|
11649
|
-
this.totalBytes -= entry.bytes;
|
|
11650
|
-
this.entries.delete(entry.key);
|
|
11651
|
-
}
|
|
11652
|
-
this.totalBytes = Math.max(0, this.totalBytes);
|
|
11653
|
-
}
|
|
11654
|
-
finishLoad(generation) {
|
|
11655
|
-
this.activeLoads = Math.max(0, this.activeLoads - 1);
|
|
11656
|
-
if (!this.disposed && generation === this.generation) {
|
|
11657
|
-
this.emitProgress();
|
|
11658
|
-
this.evict();
|
|
11659
|
-
}
|
|
11660
|
-
if (!this.disposed) {
|
|
11661
|
-
this.drain();
|
|
11662
|
-
}
|
|
11663
|
-
}
|
|
11664
|
-
async loadAndFinish(entry) {
|
|
11665
|
-
const generation = this.generation;
|
|
11666
|
-
try {
|
|
11667
|
-
await this.load(entry, generation);
|
|
11668
|
-
} finally {
|
|
11669
|
-
this.finishLoad(generation);
|
|
11670
|
-
}
|
|
11671
|
-
}
|
|
11672
|
-
};
|
|
11673
|
-
|
|
11674
|
-
// src/tile/texture-manager-context.tsx
|
|
11675
|
-
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
12225
|
+
import { jsx as jsx21 } from "react/jsx-runtime";
|
|
11676
12226
|
var TileTextureManagerContext = createContext15(
|
|
11677
12227
|
null
|
|
11678
12228
|
);
|
|
@@ -11681,9 +12231,9 @@ function TileTextureManagerProvider({
|
|
|
11681
12231
|
maxTextureMemoryMb = 128,
|
|
11682
12232
|
maxConcurrentLoads = 4
|
|
11683
12233
|
}) {
|
|
11684
|
-
const gl =
|
|
12234
|
+
const gl = useThree18((state) => state.gl);
|
|
11685
12235
|
const anisotropy = gl.capabilities.getMaxAnisotropy();
|
|
11686
|
-
const manager =
|
|
12236
|
+
const manager = useMemo19(
|
|
11687
12237
|
() => new TileTextureManager({
|
|
11688
12238
|
anisotropy,
|
|
11689
12239
|
maxBytes: Math.max(1, maxTextureMemoryMb) * 1024 * 1024,
|
|
@@ -11692,43 +12242,33 @@ function TileTextureManagerProvider({
|
|
|
11692
12242
|
}),
|
|
11693
12243
|
[anisotropy, maxConcurrentLoads, maxTextureMemoryMb]
|
|
11694
12244
|
);
|
|
11695
|
-
|
|
12245
|
+
useEffect27(() => {
|
|
11696
12246
|
manager.resume();
|
|
11697
12247
|
return () => manager.dispose();
|
|
11698
12248
|
}, [manager]);
|
|
11699
|
-
return /* @__PURE__ */
|
|
12249
|
+
return /* @__PURE__ */ jsx21(TileTextureManagerContext.Provider, { value: manager, children });
|
|
11700
12250
|
}
|
|
11701
12251
|
function useSharedTileTextureManager() {
|
|
11702
12252
|
return useContext22(TileTextureManagerContext);
|
|
11703
12253
|
}
|
|
11704
12254
|
|
|
11705
12255
|
// src/tile/tile.tsx
|
|
11706
|
-
import { useFrame as
|
|
11707
|
-
import {
|
|
11708
|
-
memo,
|
|
11709
|
-
useEffect as useEffect26,
|
|
11710
|
-
useMemo as useMemo19,
|
|
11711
|
-
useRef as useRef26,
|
|
11712
|
-
useState as useState11
|
|
11713
|
-
} from "react";
|
|
12256
|
+
import { useFrame as useFrame12, useThree as useThree19 } from "@react-three/fiber";
|
|
12257
|
+
import { memo as memo2, useEffect as useEffect28, useMemo as useMemo20, useRef as useRef28, useState as useState13 } from "react";
|
|
11714
12258
|
import {
|
|
11715
|
-
|
|
11716
|
-
|
|
11717
|
-
LinearFilter as LinearFilter4,
|
|
11718
|
-
Matrix4,
|
|
12259
|
+
Frustum as Frustum2,
|
|
12260
|
+
Matrix4 as Matrix43,
|
|
11719
12261
|
PlaneGeometry as PlaneGeometry4,
|
|
11720
|
-
PerspectiveCamera as
|
|
11721
|
-
|
|
11722
|
-
TextureLoader as TextureLoader4,
|
|
11723
|
-
Vector3 as Vector312
|
|
12262
|
+
PerspectiveCamera as PerspectiveCamera5,
|
|
12263
|
+
Vector3 as Vector313
|
|
11724
12264
|
} from "three";
|
|
11725
12265
|
|
|
11726
12266
|
// src/tile/face-layout.ts
|
|
11727
12267
|
import {
|
|
11728
|
-
Box3,
|
|
12268
|
+
Box3 as Box32,
|
|
11729
12269
|
Euler as Euler3,
|
|
11730
12270
|
Quaternion as Quaternion2,
|
|
11731
|
-
Vector3 as
|
|
12271
|
+
Vector3 as Vector312
|
|
11732
12272
|
} from "three";
|
|
11733
12273
|
var CUBE_FACES = ["f", "r", "b", "l", "u", "d"];
|
|
11734
12274
|
var PREVIEW_FACE_ORDER = ["l", "f", "r", "b", "u", "d"];
|
|
@@ -11792,17 +12332,17 @@ function getTileBoundingBox(address, radius = CUBE_RADIUS) {
|
|
|
11792
12332
|
const halfWidth = local.width / 2;
|
|
11793
12333
|
const halfHeight = local.height / 2;
|
|
11794
12334
|
const quaternion = getFaceQuaternion(address.face);
|
|
11795
|
-
const position = new
|
|
12335
|
+
const position = new Vector312(...transform.position);
|
|
11796
12336
|
const corners = [
|
|
11797
|
-
new
|
|
11798
|
-
new
|
|
11799
|
-
new
|
|
11800
|
-
new
|
|
12337
|
+
new Vector312(local.x - halfWidth, local.y - halfHeight, 0),
|
|
12338
|
+
new Vector312(local.x + halfWidth, local.y - halfHeight, 0),
|
|
12339
|
+
new Vector312(local.x - halfWidth, local.y + halfHeight, 0),
|
|
12340
|
+
new Vector312(local.x + halfWidth, local.y + halfHeight, 0)
|
|
11801
12341
|
];
|
|
11802
12342
|
for (const corner of corners) {
|
|
11803
12343
|
corner.applyQuaternion(quaternion).add(position);
|
|
11804
12344
|
}
|
|
11805
|
-
return new
|
|
12345
|
+
return new Box32().setFromPoints(corners);
|
|
11806
12346
|
}
|
|
11807
12347
|
function makeTileAddress(face, level, faceSize, tileSize, col, row) {
|
|
11808
12348
|
const left = (col - 1) * tileSize;
|
|
@@ -11849,7 +12389,7 @@ function previewAtlasVRange(face, faceOrder = PREVIEW_FACE_ORDER) {
|
|
|
11849
12389
|
}
|
|
11850
12390
|
|
|
11851
12391
|
// src/tile/multires.ts
|
|
11852
|
-
function
|
|
12392
|
+
function positiveInteger2(value, name) {
|
|
11853
12393
|
if (!Number.isFinite(value) || value <= 0 || !Number.isInteger(value)) {
|
|
11854
12394
|
throw new Error(`${name} must be a positive integer, received ${String(value)}`);
|
|
11855
12395
|
}
|
|
@@ -11865,13 +12405,13 @@ function ascendingLevels(levels) {
|
|
|
11865
12405
|
}
|
|
11866
12406
|
function parseMultires(multires) {
|
|
11867
12407
|
if (typeof multires !== "string") {
|
|
11868
|
-
const tileSize2 =
|
|
12408
|
+
const tileSize2 = positiveInteger2(multires.tileSize, "multires.tileSize");
|
|
11869
12409
|
if (multires.levels.length === 0) {
|
|
11870
12410
|
throw new Error("multires.levels must contain at least one face size");
|
|
11871
12411
|
}
|
|
11872
12412
|
const levels2 = ascendingLevels(
|
|
11873
12413
|
multires.levels.map(
|
|
11874
|
-
(level, index) =>
|
|
12414
|
+
(level, index) => positiveInteger2(level, `multires.levels[${index}]`)
|
|
11875
12415
|
)
|
|
11876
12416
|
);
|
|
11877
12417
|
return { tileSize: tileSize2, levels: levels2 };
|
|
@@ -11882,10 +12422,10 @@ function parseMultires(multires) {
|
|
|
11882
12422
|
"multires must contain a tile size followed by at least one face size"
|
|
11883
12423
|
);
|
|
11884
12424
|
}
|
|
11885
|
-
const tileSize =
|
|
12425
|
+
const tileSize = positiveInteger2(values[0], "multires tile size");
|
|
11886
12426
|
const levels = ascendingLevels(
|
|
11887
12427
|
values.slice(1).map(
|
|
11888
|
-
(level, index) =>
|
|
12428
|
+
(level, index) => positiveInteger2(level, `multires level ${index + 1}`)
|
|
11889
12429
|
)
|
|
11890
12430
|
);
|
|
11891
12431
|
return { tileSize, levels };
|
|
@@ -11905,7 +12445,7 @@ function resolveTemplateUrl(template, address) {
|
|
|
11905
12445
|
}
|
|
11906
12446
|
|
|
11907
12447
|
// src/tile/tile.tsx
|
|
11908
|
-
import { jsx as
|
|
12448
|
+
import { jsx as jsx22, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
11909
12449
|
var MAX_LOD_UPDATE_INTERVAL_MS = 100;
|
|
11910
12450
|
var FAST_ROTATION_THRESHOLD_RADIANS = Math.PI / 180;
|
|
11911
12451
|
var FAST_FOV_THRESHOLD_DEGREES = 0.5;
|
|
@@ -11913,61 +12453,12 @@ var VIEW_CHANGE_EPSILON = 1e-4;
|
|
|
11913
12453
|
var VISIBILITY_FOV_PADDING_DEGREES = 8;
|
|
11914
12454
|
var PREVIEW_RADIUS = CUBE_RADIUS + 0.05;
|
|
11915
12455
|
var SHARED_TILE_GEOMETRY = new PlaneGeometry4(1, 1);
|
|
11916
|
-
function usePreviewTexture(url, anisotropy, onError) {
|
|
11917
|
-
const [texture, setTexture] = useState11(null);
|
|
11918
|
-
const onErrorRef = useRef26(onError);
|
|
11919
|
-
onErrorRef.current = onError;
|
|
11920
|
-
useEffect26(() => {
|
|
11921
|
-
if (!url) {
|
|
11922
|
-
setTexture(null);
|
|
11923
|
-
return;
|
|
11924
|
-
}
|
|
11925
|
-
let active = true;
|
|
11926
|
-
const loader = new TextureLoader4();
|
|
11927
|
-
setTexture(null);
|
|
11928
|
-
loader.load(
|
|
11929
|
-
url,
|
|
11930
|
-
(loadedTexture) => {
|
|
11931
|
-
if (!active) {
|
|
11932
|
-
loadedTexture.dispose();
|
|
11933
|
-
return;
|
|
11934
|
-
}
|
|
11935
|
-
loadedTexture.colorSpace = SRGBColorSpace4;
|
|
11936
|
-
loadedTexture.wrapS = ClampToEdgeWrapping2;
|
|
11937
|
-
loadedTexture.wrapT = ClampToEdgeWrapping2;
|
|
11938
|
-
loadedTexture.magFilter = LinearFilter4;
|
|
11939
|
-
loadedTexture.minFilter = LinearFilter4;
|
|
11940
|
-
loadedTexture.generateMipmaps = false;
|
|
11941
|
-
loadedTexture.anisotropy = Math.min(4, anisotropy);
|
|
11942
|
-
loadedTexture.needsUpdate = true;
|
|
11943
|
-
setTexture(loadedTexture);
|
|
11944
|
-
},
|
|
11945
|
-
void 0,
|
|
11946
|
-
(error) => {
|
|
11947
|
-
if (active) {
|
|
11948
|
-
setTexture(null);
|
|
11949
|
-
onErrorRef.current?.(error);
|
|
11950
|
-
}
|
|
11951
|
-
}
|
|
11952
|
-
);
|
|
11953
|
-
return () => {
|
|
11954
|
-
active = false;
|
|
11955
|
-
};
|
|
11956
|
-
}, [anisotropy, url]);
|
|
11957
|
-
useEffect26(
|
|
11958
|
-
() => () => {
|
|
11959
|
-
texture?.dispose();
|
|
11960
|
-
},
|
|
11961
|
-
[texture]
|
|
11962
|
-
);
|
|
11963
|
-
return texture;
|
|
11964
|
-
}
|
|
11965
12456
|
function PreviewFace({
|
|
11966
12457
|
face,
|
|
11967
12458
|
texture,
|
|
11968
12459
|
faceOrder
|
|
11969
12460
|
}) {
|
|
11970
|
-
const geometry =
|
|
12461
|
+
const geometry = useMemo20(() => {
|
|
11971
12462
|
const nextGeometry = new PlaneGeometry4(
|
|
11972
12463
|
PREVIEW_RADIUS * 2,
|
|
11973
12464
|
PREVIEW_RADIUS * 2
|
|
@@ -11977,29 +12468,26 @@ function PreviewFace({
|
|
|
11977
12468
|
const inset = scale / 512;
|
|
11978
12469
|
for (let index = 0; index < uv.count; index += 1) {
|
|
11979
12470
|
const sourceV = uv.getY(index);
|
|
11980
|
-
uv.setY(
|
|
11981
|
-
index,
|
|
11982
|
-
offset + inset + sourceV * Math.max(0, scale - inset * 2)
|
|
11983
|
-
);
|
|
12471
|
+
uv.setY(index, offset + inset + sourceV * Math.max(0, scale - inset * 2));
|
|
11984
12472
|
}
|
|
11985
12473
|
uv.needsUpdate = true;
|
|
11986
12474
|
return nextGeometry;
|
|
11987
12475
|
}, [face, faceOrder]);
|
|
11988
|
-
|
|
12476
|
+
useEffect28(
|
|
11989
12477
|
() => () => {
|
|
11990
12478
|
geometry.dispose();
|
|
11991
12479
|
},
|
|
11992
12480
|
[geometry]
|
|
11993
12481
|
);
|
|
11994
12482
|
const transform = getFaceTransform(face, PREVIEW_RADIUS);
|
|
11995
|
-
return /* @__PURE__ */
|
|
12483
|
+
return /* @__PURE__ */ jsx22(
|
|
11996
12484
|
"mesh",
|
|
11997
12485
|
{
|
|
11998
12486
|
geometry,
|
|
11999
12487
|
position: transform.position,
|
|
12000
12488
|
renderOrder: -100,
|
|
12001
12489
|
rotation: transform.rotation,
|
|
12002
|
-
children: /* @__PURE__ */
|
|
12490
|
+
children: /* @__PURE__ */ jsx22(
|
|
12003
12491
|
PanoBasicMaterial,
|
|
12004
12492
|
{
|
|
12005
12493
|
depthTest: false,
|
|
@@ -12015,7 +12503,7 @@ function PreviewCube({
|
|
|
12015
12503
|
texture,
|
|
12016
12504
|
faceOrder
|
|
12017
12505
|
}) {
|
|
12018
|
-
return CUBE_FACES.map((face) => /* @__PURE__ */
|
|
12506
|
+
return CUBE_FACES.map((face) => /* @__PURE__ */ jsx22(
|
|
12019
12507
|
PreviewFace,
|
|
12020
12508
|
{
|
|
12021
12509
|
face,
|
|
@@ -12025,28 +12513,7 @@ function PreviewCube({
|
|
|
12025
12513
|
face
|
|
12026
12514
|
));
|
|
12027
12515
|
}
|
|
12028
|
-
|
|
12029
|
-
const [managedState, setManagedState] = useState11(() => ({
|
|
12030
|
-
manager,
|
|
12031
|
-
key,
|
|
12032
|
-
url,
|
|
12033
|
-
snapshot: manager.getSnapshot(key)
|
|
12034
|
-
}));
|
|
12035
|
-
const snapshot = managedState.manager === manager && managedState.key === key && managedState.url === url ? managedState.snapshot : manager.getSnapshot(key);
|
|
12036
|
-
useEffect26(
|
|
12037
|
-
() => manager.acquire(key, url, address, (nextSnapshot) => {
|
|
12038
|
-
setManagedState({
|
|
12039
|
-
manager,
|
|
12040
|
-
key,
|
|
12041
|
-
url,
|
|
12042
|
-
snapshot: nextSnapshot
|
|
12043
|
-
});
|
|
12044
|
-
}),
|
|
12045
|
-
[key, manager, url]
|
|
12046
|
-
);
|
|
12047
|
-
return snapshot;
|
|
12048
|
-
}
|
|
12049
|
-
var TileMesh = memo(function TileMesh2({
|
|
12516
|
+
var TileMesh = memo2(function TileMesh2({
|
|
12050
12517
|
address,
|
|
12051
12518
|
manager,
|
|
12052
12519
|
renderOrder,
|
|
@@ -12060,14 +12527,14 @@ var TileMesh = memo(function TileMesh2({
|
|
|
12060
12527
|
if (!snapshot.texture) {
|
|
12061
12528
|
return null;
|
|
12062
12529
|
}
|
|
12063
|
-
return /* @__PURE__ */
|
|
12530
|
+
return /* @__PURE__ */ jsx22("group", { position: transform.position, rotation: transform.rotation, children: /* @__PURE__ */ jsx22(
|
|
12064
12531
|
"mesh",
|
|
12065
12532
|
{
|
|
12066
12533
|
geometry: SHARED_TILE_GEOMETRY,
|
|
12067
12534
|
position: [layout.x, layout.y, 0],
|
|
12068
12535
|
renderOrder,
|
|
12069
12536
|
scale: [layout.width, layout.height, 1],
|
|
12070
|
-
children: /* @__PURE__ */
|
|
12537
|
+
children: /* @__PURE__ */ jsx22(
|
|
12071
12538
|
PanoBasicMaterial,
|
|
12072
12539
|
{
|
|
12073
12540
|
depthTest: false,
|
|
@@ -12079,12 +12546,12 @@ var TileMesh = memo(function TileMesh2({
|
|
|
12079
12546
|
}
|
|
12080
12547
|
) });
|
|
12081
12548
|
});
|
|
12082
|
-
var TileLayerMeshes =
|
|
12549
|
+
var TileLayerMeshes = memo2(function TileLayerMeshes2({
|
|
12083
12550
|
layer,
|
|
12084
12551
|
manager,
|
|
12085
12552
|
resolveUrl
|
|
12086
12553
|
}) {
|
|
12087
|
-
return layer.addresses.map((address) => /* @__PURE__ */
|
|
12554
|
+
return layer.addresses.map((address) => /* @__PURE__ */ jsx22(
|
|
12088
12555
|
TileMesh,
|
|
12089
12556
|
{
|
|
12090
12557
|
address,
|
|
@@ -12184,8 +12651,8 @@ function parentAddresses(child, parentLevel, parentFaceSize, tileSize) {
|
|
|
12184
12651
|
return addresses;
|
|
12185
12652
|
}
|
|
12186
12653
|
function centerFacingAddress(candidates, camera) {
|
|
12187
|
-
const direction = camera.getWorldDirection(new
|
|
12188
|
-
const center = new
|
|
12654
|
+
const direction = camera.getWorldDirection(new Vector313());
|
|
12655
|
+
const center = new Vector313();
|
|
12189
12656
|
let bestCandidate = candidates[0];
|
|
12190
12657
|
let bestAlignment = -Infinity;
|
|
12191
12658
|
for (const candidate of candidates) {
|
|
@@ -12230,9 +12697,7 @@ function buildLayers(targetLevel, levels, tileSize, frustum, camera, candidatesB
|
|
|
12230
12697
|
}));
|
|
12231
12698
|
}
|
|
12232
12699
|
function layerToken(layers) {
|
|
12233
|
-
return layers.map(
|
|
12234
|
-
(layer) => `${layer.level}:${layer.addresses.map(tileKey).join(",")}`
|
|
12235
|
-
).join("|");
|
|
12700
|
+
return layers.map((layer) => `${layer.level}:${layer.addresses.map(tileKey).join(",")}`).join("|");
|
|
12236
12701
|
}
|
|
12237
12702
|
function Tile({
|
|
12238
12703
|
baseUrl,
|
|
@@ -12252,11 +12717,11 @@ function Tile({
|
|
|
12252
12717
|
onTileError,
|
|
12253
12718
|
onLevelChange
|
|
12254
12719
|
}) {
|
|
12255
|
-
const { camera, gl, size } =
|
|
12256
|
-
const multiresConfig =
|
|
12720
|
+
const { camera, gl, size } = useThree19();
|
|
12721
|
+
const multiresConfig = useMemo20(() => parseMultires(multires), [multires]);
|
|
12257
12722
|
const { levels, tileSize } = multiresConfig;
|
|
12258
12723
|
const multiresToken = `${tileSize}:${levels.join(",")}`;
|
|
12259
|
-
const candidatesByLevel =
|
|
12724
|
+
const candidatesByLevel = useMemo20(
|
|
12260
12725
|
() => buildTileCandidates(levels, tileSize),
|
|
12261
12726
|
[levels, tileSize]
|
|
12262
12727
|
);
|
|
@@ -12268,13 +12733,13 @@ function Tile({
|
|
|
12268
12733
|
onPreviewError
|
|
12269
12734
|
);
|
|
12270
12735
|
const sharedManager = useSharedTileTextureManager();
|
|
12271
|
-
const progressRef =
|
|
12272
|
-
const errorRef =
|
|
12273
|
-
const levelChangeRef =
|
|
12736
|
+
const progressRef = useRef28(onLoadProgress);
|
|
12737
|
+
const errorRef = useRef28(onTileError);
|
|
12738
|
+
const levelChangeRef = useRef28(onLevelChange);
|
|
12274
12739
|
progressRef.current = onLoadProgress;
|
|
12275
12740
|
errorRef.current = onTileError;
|
|
12276
12741
|
levelChangeRef.current = onLevelChange;
|
|
12277
|
-
const ownedManager =
|
|
12742
|
+
const ownedManager = useMemo20(
|
|
12278
12743
|
() => new TileTextureManager({
|
|
12279
12744
|
anisotropy,
|
|
12280
12745
|
maxBytes: Math.max(1, maxTextureMemoryMb) * 1024 * 1024,
|
|
@@ -12295,7 +12760,7 @@ function Tile({
|
|
|
12295
12760
|
]
|
|
12296
12761
|
);
|
|
12297
12762
|
const manager = sharedManager ?? ownedManager;
|
|
12298
|
-
|
|
12763
|
+
useEffect28(() => {
|
|
12299
12764
|
manager.resume();
|
|
12300
12765
|
return () => {
|
|
12301
12766
|
if (manager === ownedManager) {
|
|
@@ -12305,11 +12770,11 @@ function Tile({
|
|
|
12305
12770
|
queueMicrotask(() => manager.releaseUnused());
|
|
12306
12771
|
};
|
|
12307
12772
|
}, [manager, ownedManager]);
|
|
12308
|
-
const readyRef =
|
|
12309
|
-
|
|
12773
|
+
const readyRef = useRef28(false);
|
|
12774
|
+
useEffect28(() => {
|
|
12310
12775
|
readyRef.current = false;
|
|
12311
12776
|
}, [effectivePreviewUrl]);
|
|
12312
|
-
|
|
12777
|
+
useEffect28(() => {
|
|
12313
12778
|
if (!previewTexture || readyRef.current) {
|
|
12314
12779
|
return;
|
|
12315
12780
|
}
|
|
@@ -12317,31 +12782,31 @@ function Tile({
|
|
|
12317
12782
|
onReady?.();
|
|
12318
12783
|
}, [onReady, previewTexture]);
|
|
12319
12784
|
const template = urlTemplate ?? buildDefaultTileUrlTemplate();
|
|
12320
|
-
const resolveUrl =
|
|
12785
|
+
const resolveUrl = useMemo20(
|
|
12321
12786
|
() => (address) => {
|
|
12322
12787
|
const relativePath = resolveTileUrl ? resolveTileUrl(address) : resolveTemplateUrl(template, address);
|
|
12323
12788
|
return resolveRelativeTileUrl(baseUrl, relativePath);
|
|
12324
12789
|
},
|
|
12325
12790
|
[baseUrl, resolveTileUrl, template]
|
|
12326
12791
|
);
|
|
12327
|
-
const [layers, setLayers] =
|
|
12328
|
-
const layerTokenRef =
|
|
12329
|
-
const currentLevelRef =
|
|
12330
|
-
const lastUpdateAtRef =
|
|
12331
|
-
const visibilityDirtyRef =
|
|
12332
|
-
const lastVisibilityQuaternionRef =
|
|
12333
|
-
const lastVisibilityFovRef =
|
|
12334
|
-
const lastViewportRef =
|
|
12335
|
-
const frustumRef =
|
|
12336
|
-
const projectionMatrixRef =
|
|
12337
|
-
const visibilityCameraRef =
|
|
12338
|
-
|
|
12792
|
+
const [layers, setLayers] = useState13([]);
|
|
12793
|
+
const layerTokenRef = useRef28("");
|
|
12794
|
+
const currentLevelRef = useRef28(1);
|
|
12795
|
+
const lastUpdateAtRef = useRef28(-Infinity);
|
|
12796
|
+
const visibilityDirtyRef = useRef28(true);
|
|
12797
|
+
const lastVisibilityQuaternionRef = useRef28(camera.quaternion.clone());
|
|
12798
|
+
const lastVisibilityFovRef = useRef28(Number.NaN);
|
|
12799
|
+
const lastViewportRef = useRef28({ width: 0, height: 0, dpr: 0 });
|
|
12800
|
+
const frustumRef = useRef28(new Frustum2());
|
|
12801
|
+
const projectionMatrixRef = useRef28(new Matrix43());
|
|
12802
|
+
const visibilityCameraRef = useRef28(new PerspectiveCamera5());
|
|
12803
|
+
useEffect28(() => {
|
|
12339
12804
|
currentLevelRef.current = 1;
|
|
12340
12805
|
layerTokenRef.current = "";
|
|
12341
12806
|
visibilityDirtyRef.current = true;
|
|
12342
12807
|
setLayers([]);
|
|
12343
12808
|
}, [manager, multiresToken]);
|
|
12344
|
-
|
|
12809
|
+
useEffect28(() => {
|
|
12345
12810
|
if (loadMode !== "preview") {
|
|
12346
12811
|
return;
|
|
12347
12812
|
}
|
|
@@ -12355,11 +12820,11 @@ function Tile({
|
|
|
12355
12820
|
setLayers(nextLayers);
|
|
12356
12821
|
}
|
|
12357
12822
|
};
|
|
12358
|
-
|
|
12823
|
+
useFrame12(() => {
|
|
12359
12824
|
if (loadMode === "preview") {
|
|
12360
12825
|
return;
|
|
12361
12826
|
}
|
|
12362
|
-
if (!(camera instanceof
|
|
12827
|
+
if (!(camera instanceof PerspectiveCamera5)) {
|
|
12363
12828
|
return;
|
|
12364
12829
|
}
|
|
12365
12830
|
const now = performance.now();
|
|
@@ -12421,15 +12886,9 @@ function Tile({
|
|
|
12421
12886
|
};
|
|
12422
12887
|
commitLayers(nextLayers);
|
|
12423
12888
|
});
|
|
12424
|
-
return /* @__PURE__ */
|
|
12425
|
-
previewTexture ? /* @__PURE__ */
|
|
12426
|
-
|
|
12427
|
-
{
|
|
12428
|
-
texture: previewTexture,
|
|
12429
|
-
faceOrder: previewFaceOrder
|
|
12430
|
-
}
|
|
12431
|
-
) : null,
|
|
12432
|
-
layers.map((layer) => /* @__PURE__ */ jsx21(
|
|
12889
|
+
return /* @__PURE__ */ jsxs13("group", { visible, children: [
|
|
12890
|
+
previewTexture ? /* @__PURE__ */ jsx22(PreviewCube, { texture: previewTexture, faceOrder: previewFaceOrder }) : null,
|
|
12891
|
+
layers.map((layer) => /* @__PURE__ */ jsx22(
|
|
12433
12892
|
TileLayerMeshes,
|
|
12434
12893
|
{
|
|
12435
12894
|
layer,
|
|
@@ -12442,7 +12901,7 @@ function Tile({
|
|
|
12442
12901
|
}
|
|
12443
12902
|
|
|
12444
12903
|
// src/scenes.tsx
|
|
12445
|
-
import { jsx as
|
|
12904
|
+
import { jsx as jsx23, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
12446
12905
|
function SceneSource({
|
|
12447
12906
|
scene,
|
|
12448
12907
|
visible,
|
|
@@ -12455,7 +12914,7 @@ function SceneSource({
|
|
|
12455
12914
|
}
|
|
12456
12915
|
switch (scene.type) {
|
|
12457
12916
|
case "sphere":
|
|
12458
|
-
return /* @__PURE__ */
|
|
12917
|
+
return /* @__PURE__ */ jsx23(
|
|
12459
12918
|
Sphere,
|
|
12460
12919
|
{
|
|
12461
12920
|
src: scene.src,
|
|
@@ -12468,7 +12927,7 @@ function SceneSource({
|
|
|
12468
12927
|
);
|
|
12469
12928
|
case "tile": {
|
|
12470
12929
|
const { id: _id, type: _type, ...tileProps } = scene;
|
|
12471
|
-
return /* @__PURE__ */
|
|
12930
|
+
return /* @__PURE__ */ jsx23(
|
|
12472
12931
|
Tile,
|
|
12473
12932
|
{
|
|
12474
12933
|
...tileProps,
|
|
@@ -12491,17 +12950,17 @@ function SnapshotCapture({
|
|
|
12491
12950
|
maxPixels,
|
|
12492
12951
|
onCaptured
|
|
12493
12952
|
}) {
|
|
12494
|
-
const { camera, gl, scene, size } =
|
|
12495
|
-
const capturedRequestRef =
|
|
12496
|
-
const renderTargetRef =
|
|
12497
|
-
|
|
12953
|
+
const { camera, gl, scene, size } = useThree20();
|
|
12954
|
+
const capturedRequestRef = useRef29(0);
|
|
12955
|
+
const renderTargetRef = useRef29(null);
|
|
12956
|
+
useEffect29(
|
|
12498
12957
|
() => () => {
|
|
12499
12958
|
renderTargetRef.current?.dispose();
|
|
12500
12959
|
renderTargetRef.current = null;
|
|
12501
12960
|
},
|
|
12502
12961
|
[]
|
|
12503
12962
|
);
|
|
12504
|
-
|
|
12963
|
+
useFrame13(() => {
|
|
12505
12964
|
if (requestId === 0 || requestId === capturedRequestRef.current) {
|
|
12506
12965
|
return;
|
|
12507
12966
|
}
|
|
@@ -12552,48 +13011,48 @@ function ScenesController({
|
|
|
12552
13011
|
}) {
|
|
12553
13012
|
const controlsRef = useContext23(PanoramaViewContext);
|
|
12554
13013
|
const manager = useSharedTileTextureManager();
|
|
12555
|
-
const transition =
|
|
13014
|
+
const transition = useMemo21(
|
|
12556
13015
|
() => resolveTransition(transitionInput),
|
|
12557
13016
|
[transitionInput]
|
|
12558
13017
|
);
|
|
12559
|
-
const sceneMap =
|
|
13018
|
+
const sceneMap = useMemo21(
|
|
12560
13019
|
() => new Map(scenes.map((scene) => [scene.id, scene])),
|
|
12561
13020
|
[scenes]
|
|
12562
13021
|
);
|
|
12563
13022
|
const initialScene = sceneMap.get(activeSceneId) ?? null;
|
|
12564
|
-
const [slots, setSlots] =
|
|
13023
|
+
const [slots, setSlots] = useState14([
|
|
12565
13024
|
initialScene,
|
|
12566
13025
|
null
|
|
12567
13026
|
]);
|
|
12568
|
-
const [activeSlot, setActiveSlot] =
|
|
12569
|
-
const [liveSlot, setLiveSlot] =
|
|
12570
|
-
const [pendingSlot, setPendingSlot] =
|
|
12571
|
-
const [phase, setPhase] =
|
|
12572
|
-
const [captureRequestId, setCaptureRequestId] =
|
|
12573
|
-
const [transitionRunId, setTransitionRunId] =
|
|
12574
|
-
const [snapshot, setSnapshot] =
|
|
12575
|
-
const [recoveryKey, setRecoveryKey] =
|
|
12576
|
-
const requestedSceneIdRef =
|
|
12577
|
-
const captureReasonRef =
|
|
12578
|
-
const interactionReleaseRef =
|
|
12579
|
-
const slotsRef =
|
|
12580
|
-
const phaseRef =
|
|
12581
|
-
const liveSlotRef =
|
|
12582
|
-
const transitionFromRef =
|
|
13027
|
+
const [activeSlot, setActiveSlot] = useState14(0);
|
|
13028
|
+
const [liveSlot, setLiveSlot] = useState14(0);
|
|
13029
|
+
const [pendingSlot, setPendingSlot] = useState14(null);
|
|
13030
|
+
const [phase, setPhase] = useState14(initialScene ? "idle" : "preloading");
|
|
13031
|
+
const [captureRequestId, setCaptureRequestId] = useState14(0);
|
|
13032
|
+
const [transitionRunId, setTransitionRunId] = useState14(0);
|
|
13033
|
+
const [snapshot, setSnapshot] = useState14(null);
|
|
13034
|
+
const [recoveryKey, setRecoveryKey] = useState14(0);
|
|
13035
|
+
const requestedSceneIdRef = useRef29(activeSceneId);
|
|
13036
|
+
const captureReasonRef = useRef29("start");
|
|
13037
|
+
const interactionReleaseRef = useRef29(null);
|
|
13038
|
+
const slotsRef = useRef29(slots);
|
|
13039
|
+
const phaseRef = useRef29(phase);
|
|
13040
|
+
const liveSlotRef = useRef29(liveSlot);
|
|
13041
|
+
const transitionFromRef = useRef29(initialScene);
|
|
12583
13042
|
slotsRef.current = slots;
|
|
12584
13043
|
phaseRef.current = phase;
|
|
12585
13044
|
if (externalPhaseRef) {
|
|
12586
13045
|
externalPhaseRef.current = phase;
|
|
12587
13046
|
}
|
|
12588
13047
|
liveSlotRef.current = liveSlot;
|
|
12589
|
-
const releaseInteraction =
|
|
13048
|
+
const releaseInteraction = useCallback11(() => {
|
|
12590
13049
|
interactionReleaseRef.current?.();
|
|
12591
13050
|
interactionReleaseRef.current = null;
|
|
12592
13051
|
}, []);
|
|
12593
|
-
const reportError =
|
|
13052
|
+
const reportError = useCallback11((sceneId, error) => {
|
|
12594
13053
|
onTransitionError?.({ sceneId, error });
|
|
12595
13054
|
}, [onTransitionError]);
|
|
12596
|
-
const startPreload =
|
|
13055
|
+
const startPreload = useCallback11((scene) => {
|
|
12597
13056
|
const nextSlot = 1 - liveSlotRef.current;
|
|
12598
13057
|
requestedSceneIdRef.current = scene.id;
|
|
12599
13058
|
setSlots((current) => {
|
|
@@ -12604,7 +13063,7 @@ function ScenesController({
|
|
|
12604
13063
|
setPendingSlot(nextSlot);
|
|
12605
13064
|
setPhase("preloading");
|
|
12606
13065
|
}, []);
|
|
12607
|
-
|
|
13066
|
+
useEffect29(() => {
|
|
12608
13067
|
const requested = sceneMap.get(activeSceneId);
|
|
12609
13068
|
if (!requested) {
|
|
12610
13069
|
reportError(activeSceneId, new Error(`Unknown panorama scene: ${activeSceneId}`));
|
|
@@ -12628,7 +13087,7 @@ function ScenesController({
|
|
|
12628
13087
|
}
|
|
12629
13088
|
startPreload(requested);
|
|
12630
13089
|
}, [activeSceneId, pendingSlot, reportError, sceneMap, startPreload]);
|
|
12631
|
-
const handleReady =
|
|
13090
|
+
const handleReady = useCallback11((slot) => {
|
|
12632
13091
|
if (slot !== pendingSlot || phaseRef.current !== "preloading") {
|
|
12633
13092
|
return;
|
|
12634
13093
|
}
|
|
@@ -12659,7 +13118,7 @@ function ScenesController({
|
|
|
12659
13118
|
setPhase("capturing");
|
|
12660
13119
|
setCaptureRequestId((current) => current + 1);
|
|
12661
13120
|
}, [controlsRef, onTransitionEnd, pendingSlot, transition.preset]);
|
|
12662
|
-
const handleCaptured =
|
|
13121
|
+
const handleCaptured = useCallback11((nextSnapshot) => {
|
|
12663
13122
|
setSnapshot((current) => {
|
|
12664
13123
|
current?.dispose();
|
|
12665
13124
|
return nextSnapshot;
|
|
@@ -12681,7 +13140,7 @@ function ScenesController({
|
|
|
12681
13140
|
setPhase("transitioning");
|
|
12682
13141
|
setTransitionRunId((current) => current + 1);
|
|
12683
13142
|
}, [manager, pendingSlot, sceneMap, startPreload]);
|
|
12684
|
-
const finishTransition =
|
|
13143
|
+
const finishTransition = useCallback11(() => {
|
|
12685
13144
|
const nextSlot = pendingSlot;
|
|
12686
13145
|
const previousScene = transitionFromRef.current;
|
|
12687
13146
|
const nextScene = nextSlot === null ? null : slotsRef.current[nextSlot];
|
|
@@ -12706,12 +13165,12 @@ function ScenesController({
|
|
|
12706
13165
|
});
|
|
12707
13166
|
}
|
|
12708
13167
|
}, [onTransitionEnd, pendingSlot, releaseInteraction, snapshot, transition.preset]);
|
|
12709
|
-
|
|
13168
|
+
useEffect29(() => () => {
|
|
12710
13169
|
releaseInteraction();
|
|
12711
13170
|
snapshot?.dispose();
|
|
12712
13171
|
}, [releaseInteraction, snapshot]);
|
|
12713
|
-
const { gl } =
|
|
12714
|
-
|
|
13172
|
+
const { gl } = useThree20();
|
|
13173
|
+
useEffect29(() => {
|
|
12715
13174
|
const canvas = gl.domElement;
|
|
12716
13175
|
const onContextLost = (event) => {
|
|
12717
13176
|
event.preventDefault();
|
|
@@ -12735,8 +13194,8 @@ function ScenesController({
|
|
|
12735
13194
|
}, [gl, manager, releaseInteraction, snapshot]);
|
|
12736
13195
|
const renderedScene = slots[liveSlot];
|
|
12737
13196
|
const snapshotVisible = snapshot !== null && (phase === "transitioning" || phase === "recapturing" || phase === "preloading");
|
|
12738
|
-
return /* @__PURE__ */
|
|
12739
|
-
/* @__PURE__ */
|
|
13197
|
+
return /* @__PURE__ */ jsxs14(Fragment6, { children: [
|
|
13198
|
+
/* @__PURE__ */ jsx23(
|
|
12740
13199
|
SnapshotCapture,
|
|
12741
13200
|
{
|
|
12742
13201
|
requestId: captureRequestId,
|
|
@@ -12748,7 +13207,7 @@ function ScenesController({
|
|
|
12748
13207
|
const source = slots[slot];
|
|
12749
13208
|
const isLive = slot === liveSlot;
|
|
12750
13209
|
const isPending = slot === pendingSlot;
|
|
12751
|
-
return /* @__PURE__ */
|
|
13210
|
+
return /* @__PURE__ */ jsx23(
|
|
12752
13211
|
SceneSource,
|
|
12753
13212
|
{
|
|
12754
13213
|
scene: source,
|
|
@@ -12764,7 +13223,7 @@ function ScenesController({
|
|
|
12764
13223
|
`${slot}:${source?.id ?? "empty"}:${recoveryKey}`
|
|
12765
13224
|
);
|
|
12766
13225
|
}),
|
|
12767
|
-
snapshotVisible ? /* @__PURE__ */
|
|
13226
|
+
snapshotVisible ? /* @__PURE__ */ jsx23(
|
|
12768
13227
|
TransitionOverlay,
|
|
12769
13228
|
{
|
|
12770
13229
|
snapshot,
|
|
@@ -12787,11 +13246,11 @@ function Scenes({
|
|
|
12787
13246
|
...rest
|
|
12788
13247
|
}) {
|
|
12789
13248
|
const isControlled = controlledId !== void 0;
|
|
12790
|
-
const [internalId, setInternalId] =
|
|
13249
|
+
const [internalId, setInternalId] = useState14(
|
|
12791
13250
|
() => controlledId ?? defaultActiveSceneId ?? scenes[0]?.id ?? ""
|
|
12792
13251
|
);
|
|
12793
13252
|
const resolvedId = isControlled ? controlledId : internalId;
|
|
12794
|
-
const requestSceneChange =
|
|
13253
|
+
const requestSceneChange = useCallback11(
|
|
12795
13254
|
(id) => {
|
|
12796
13255
|
if (isControlled) {
|
|
12797
13256
|
onActiveSceneIdChange?.(id);
|
|
@@ -12801,13 +13260,13 @@ function Scenes({
|
|
|
12801
13260
|
},
|
|
12802
13261
|
[isControlled, onActiveSceneIdChange]
|
|
12803
13262
|
);
|
|
12804
|
-
const scenesRef =
|
|
13263
|
+
const scenesRef = useRef29(scenes);
|
|
12805
13264
|
scenesRef.current = scenes;
|
|
12806
|
-
const resolvedIdRef =
|
|
13265
|
+
const resolvedIdRef = useRef29(resolvedId);
|
|
12807
13266
|
resolvedIdRef.current = resolvedId;
|
|
12808
13267
|
const host = useContext23(ScenesHostContext);
|
|
12809
|
-
const phaseRef =
|
|
12810
|
-
|
|
13268
|
+
const phaseRef = useRef29("idle");
|
|
13269
|
+
useEffect29(() => {
|
|
12811
13270
|
if (!host) {
|
|
12812
13271
|
return;
|
|
12813
13272
|
}
|
|
@@ -12857,12 +13316,12 @@ function Scenes({
|
|
|
12857
13316
|
}
|
|
12858
13317
|
};
|
|
12859
13318
|
}, [host, requestSceneChange]);
|
|
12860
|
-
return /* @__PURE__ */
|
|
13319
|
+
return /* @__PURE__ */ jsx23(
|
|
12861
13320
|
TileTextureManagerProvider,
|
|
12862
13321
|
{
|
|
12863
13322
|
maxTextureMemoryMb,
|
|
12864
13323
|
maxConcurrentLoads: maxConcurrentTileLoads,
|
|
12865
|
-
children: /* @__PURE__ */
|
|
13324
|
+
children: /* @__PURE__ */ jsx23(
|
|
12866
13325
|
ScenesController,
|
|
12867
13326
|
{
|
|
12868
13327
|
...rest,
|
|
@@ -12876,8 +13335,8 @@ function Scenes({
|
|
|
12876
13335
|
}
|
|
12877
13336
|
|
|
12878
13337
|
// src/hotspot/image-hotspot.tsx
|
|
12879
|
-
import { useThree as
|
|
12880
|
-
import { useEffect as
|
|
13338
|
+
import { useThree as useThree22 } from "@react-three/fiber";
|
|
13339
|
+
import { useEffect as useEffect32, useRef as useRef31, useState as useState17 } from "react";
|
|
12881
13340
|
import {
|
|
12882
13341
|
ClampToEdgeWrapping as ClampToEdgeWrapping3,
|
|
12883
13342
|
LinearFilter as LinearFilter6,
|
|
@@ -12887,35 +13346,35 @@ import {
|
|
|
12887
13346
|
} from "three";
|
|
12888
13347
|
|
|
12889
13348
|
// src/hotspot/hotspot-anchor.tsx
|
|
12890
|
-
import { useFrame as
|
|
13349
|
+
import { useFrame as useFrame14, useThree as useThree21 } from "@react-three/fiber";
|
|
12891
13350
|
import {
|
|
12892
13351
|
useContext as useContext25,
|
|
12893
|
-
useEffect as
|
|
13352
|
+
useEffect as useEffect31,
|
|
12894
13353
|
useLayoutEffect as useLayoutEffect4,
|
|
12895
|
-
useMemo as
|
|
12896
|
-
useRef as
|
|
12897
|
-
useState as
|
|
13354
|
+
useMemo as useMemo23,
|
|
13355
|
+
useRef as useRef30,
|
|
13356
|
+
useState as useState16
|
|
12898
13357
|
} from "react";
|
|
12899
13358
|
import {
|
|
12900
|
-
Box3 as
|
|
13359
|
+
Box3 as Box34,
|
|
12901
13360
|
EdgesGeometry,
|
|
12902
|
-
MathUtils as
|
|
12903
|
-
Matrix4 as
|
|
13361
|
+
MathUtils as MathUtils8,
|
|
13362
|
+
Matrix4 as Matrix44,
|
|
12904
13363
|
Plane,
|
|
12905
13364
|
PlaneGeometry as PlaneGeometry5,
|
|
12906
|
-
PerspectiveCamera as
|
|
13365
|
+
PerspectiveCamera as PerspectiveCamera6,
|
|
12907
13366
|
Quaternion as Quaternion3,
|
|
12908
13367
|
Ray,
|
|
12909
|
-
Vector3 as
|
|
13368
|
+
Vector3 as Vector314
|
|
12910
13369
|
} from "three";
|
|
12911
13370
|
|
|
12912
13371
|
// src/hotspot/hotspot-tooltip.tsx
|
|
12913
|
-
import { useEffect as
|
|
13372
|
+
import { useEffect as useEffect30, useMemo as useMemo22, useState as useState15 } from "react";
|
|
12914
13373
|
|
|
12915
13374
|
// src/webvr/stereo-html.tsx
|
|
12916
13375
|
import { Html } from "@react-three/drei";
|
|
12917
13376
|
import { useContext as useContext24, useSyncExternalStore as useSyncExternalStore7 } from "react";
|
|
12918
|
-
import { Fragment as Fragment7, jsx as
|
|
13377
|
+
import { Fragment as Fragment7, jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
12919
13378
|
function useFallbackStereoView() {
|
|
12920
13379
|
const runtime = useContext24(WebVRRuntimeContext);
|
|
12921
13380
|
const host = runtime?.host ?? null;
|
|
@@ -12940,10 +13399,10 @@ function stereoCalculatePosition(eye, stereoView) {
|
|
|
12940
13399
|
function PanoHtml({ children, ...htmlProps }) {
|
|
12941
13400
|
const stereoView = useFallbackStereoView();
|
|
12942
13401
|
if (!stereoView) {
|
|
12943
|
-
return /* @__PURE__ */
|
|
13402
|
+
return /* @__PURE__ */ jsx24(Html, { ...htmlProps, children });
|
|
12944
13403
|
}
|
|
12945
|
-
return /* @__PURE__ */
|
|
12946
|
-
/* @__PURE__ */
|
|
13404
|
+
return /* @__PURE__ */ jsxs15(Fragment7, { children: [
|
|
13405
|
+
/* @__PURE__ */ jsx24(
|
|
12947
13406
|
Html,
|
|
12948
13407
|
{
|
|
12949
13408
|
...htmlProps,
|
|
@@ -12951,7 +13410,7 @@ function PanoHtml({ children, ...htmlProps }) {
|
|
|
12951
13410
|
children
|
|
12952
13411
|
}
|
|
12953
13412
|
),
|
|
12954
|
-
/* @__PURE__ */
|
|
13413
|
+
/* @__PURE__ */ jsx24(
|
|
12955
13414
|
Html,
|
|
12956
13415
|
{
|
|
12957
13416
|
...htmlProps,
|
|
@@ -12964,7 +13423,7 @@ function PanoHtml({ children, ...htmlProps }) {
|
|
|
12964
13423
|
}
|
|
12965
13424
|
|
|
12966
13425
|
// src/hotspot/hotspot-tooltip.tsx
|
|
12967
|
-
import { jsx as
|
|
13426
|
+
import { jsx as jsx25, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
12968
13427
|
var DEFAULT_HOTSPOT_TOOLTIP_OFFSET = 12;
|
|
12969
13428
|
var DEFAULT_HOTSPOT_TOOLTIP_APPEARANCE = {
|
|
12970
13429
|
background: "rgba(22, 22, 22, 0.72)",
|
|
@@ -12973,7 +13432,10 @@ var DEFAULT_HOTSPOT_TOOLTIP_APPEARANCE = {
|
|
|
12973
13432
|
borderRadius: 8,
|
|
12974
13433
|
shadow: "0 8px 24px rgba(0, 0, 0, 0.35)",
|
|
12975
13434
|
padding: 8,
|
|
12976
|
-
fontSize: 12
|
|
13435
|
+
fontSize: 12,
|
|
13436
|
+
fontFamily: "inherit",
|
|
13437
|
+
lineHeight: 1.4,
|
|
13438
|
+
letterSpacing: "normal"
|
|
12977
13439
|
};
|
|
12978
13440
|
var WRAPPER_STYLE = {
|
|
12979
13441
|
pointerEvents: "none"
|
|
@@ -13033,16 +13495,16 @@ function HotspotTooltip({
|
|
|
13033
13495
|
offset = DEFAULT_HOTSPOT_TOOLTIP_OFFSET,
|
|
13034
13496
|
appearance
|
|
13035
13497
|
}) {
|
|
13036
|
-
const [imageFailed, setImageFailed] =
|
|
13037
|
-
|
|
13498
|
+
const [imageFailed, setImageFailed] = useState15(false);
|
|
13499
|
+
useEffect30(() => {
|
|
13038
13500
|
setImageFailed(false);
|
|
13039
13501
|
}, [content.image]);
|
|
13040
13502
|
const showImage = Boolean(content.image) && !imageFailed;
|
|
13041
|
-
const resolvedAppearance =
|
|
13503
|
+
const resolvedAppearance = useMemo22(
|
|
13042
13504
|
() => resolveHotspotTooltipAppearance(appearance),
|
|
13043
13505
|
[appearance]
|
|
13044
13506
|
);
|
|
13045
|
-
const bubbleStyle =
|
|
13507
|
+
const bubbleStyle = useMemo22(
|
|
13046
13508
|
() => ({
|
|
13047
13509
|
background: resolvedAppearance.background,
|
|
13048
13510
|
border: resolvedAppearance.border,
|
|
@@ -13050,6 +13512,9 @@ function HotspotTooltip({
|
|
|
13050
13512
|
boxShadow: resolvedAppearance.shadow,
|
|
13051
13513
|
color: resolvedAppearance.color,
|
|
13052
13514
|
fontSize: toCssLength(resolvedAppearance.fontSize),
|
|
13515
|
+
fontFamily: resolvedAppearance.fontFamily,
|
|
13516
|
+
lineHeight: resolvedAppearance.lineHeight,
|
|
13517
|
+
letterSpacing: resolvedAppearance.letterSpacing,
|
|
13053
13518
|
padding: toCssLength(resolvedAppearance.padding),
|
|
13054
13519
|
transform: tooltipBubbleTransform(
|
|
13055
13520
|
placement,
|
|
@@ -13061,30 +13526,33 @@ function HotspotTooltip({
|
|
|
13061
13526
|
if (!showImage && !content.text) {
|
|
13062
13527
|
return null;
|
|
13063
13528
|
}
|
|
13064
|
-
return /* @__PURE__ */
|
|
13065
|
-
|
|
13066
|
-
|
|
13067
|
-
|
|
13068
|
-
|
|
13069
|
-
|
|
13070
|
-
|
|
13071
|
-
|
|
13072
|
-
|
|
13073
|
-
|
|
13074
|
-
|
|
13075
|
-
|
|
13076
|
-
|
|
13077
|
-
|
|
13078
|
-
|
|
13079
|
-
|
|
13080
|
-
|
|
13081
|
-
|
|
13082
|
-
|
|
13083
|
-
|
|
13529
|
+
return /* @__PURE__ */ jsx25(PanoHtml, { pointerEvents: "none", style: WRAPPER_STYLE, zIndexRange: [20, 10], children: /* @__PURE__ */ jsxs16("div", { className: "pano-hotspot-tooltip", role: "tooltip", style: bubbleStyle, children: [
|
|
13530
|
+
showImage ? /* @__PURE__ */ jsx25(
|
|
13531
|
+
"img",
|
|
13532
|
+
{
|
|
13533
|
+
alt: content.imageAlt ?? content.text ?? "",
|
|
13534
|
+
className: "pano-hotspot-tooltip-image",
|
|
13535
|
+
onError: () => setImageFailed(true),
|
|
13536
|
+
src: content.image
|
|
13537
|
+
}
|
|
13538
|
+
) : null,
|
|
13539
|
+
content.text ? /* @__PURE__ */ jsx25(
|
|
13540
|
+
"p",
|
|
13541
|
+
{
|
|
13542
|
+
className: "pano-hotspot-tooltip-text",
|
|
13543
|
+
style: {
|
|
13544
|
+
lineHeight: "inherit",
|
|
13545
|
+
letterSpacing: "inherit",
|
|
13546
|
+
fontFamily: "inherit"
|
|
13547
|
+
},
|
|
13548
|
+
children: content.text
|
|
13549
|
+
}
|
|
13550
|
+
) : null
|
|
13551
|
+
] }) });
|
|
13084
13552
|
}
|
|
13085
13553
|
|
|
13086
13554
|
// src/hotspot/hotspot-anchor.tsx
|
|
13087
|
-
import { jsx as
|
|
13555
|
+
import { jsx as jsx26, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
13088
13556
|
var DEFAULT_FLOATING_DISTANCE = 10;
|
|
13089
13557
|
var PANORAMA_RADIUS = DEFAULT_PANORAMA_RADIUS;
|
|
13090
13558
|
var PANORAMA_SURFACE_INSET = 4;
|
|
@@ -13092,28 +13560,28 @@ var DEFAULT_REFERENCE_FOV = 75;
|
|
|
13092
13560
|
var MIN_ANGULAR_SIZE = 0.01;
|
|
13093
13561
|
var MAX_ANGULAR_SIZE = 179;
|
|
13094
13562
|
var DRAG_EPSILON_DEGREES = 1e-3;
|
|
13095
|
-
var LOCAL_FORWARD = new
|
|
13096
|
-
var TOOLTIP_WORLD_BOX = new
|
|
13097
|
-
var TOOLTIP_LOCAL_BOX = new
|
|
13098
|
-
var TOOLTIP_CORNER = new
|
|
13099
|
-
var TOOLTIP_INVERSE = new
|
|
13100
|
-
var TOOLTIP_WORLD_CORNER = new
|
|
13101
|
-
var TOOLTIP_PROJECTED = new
|
|
13102
|
-
var TOOLTIP_RAY_ORIGIN = new
|
|
13103
|
-
var TOOLTIP_RAY_FAR = new
|
|
13104
|
-
var TOOLTIP_RAY_DIRECTION = new
|
|
13563
|
+
var LOCAL_FORWARD = new Vector314(0, 0, 1);
|
|
13564
|
+
var TOOLTIP_WORLD_BOX = new Box34();
|
|
13565
|
+
var TOOLTIP_LOCAL_BOX = new Box34();
|
|
13566
|
+
var TOOLTIP_CORNER = new Vector314();
|
|
13567
|
+
var TOOLTIP_INVERSE = new Matrix44();
|
|
13568
|
+
var TOOLTIP_WORLD_CORNER = new Vector314();
|
|
13569
|
+
var TOOLTIP_PROJECTED = new Vector314();
|
|
13570
|
+
var TOOLTIP_RAY_ORIGIN = new Vector314();
|
|
13571
|
+
var TOOLTIP_RAY_FAR = new Vector314();
|
|
13572
|
+
var TOOLTIP_RAY_DIRECTION = new Vector314();
|
|
13105
13573
|
var TOOLTIP_RAY = new Ray();
|
|
13106
13574
|
var TOOLTIP_PLANE = new Plane();
|
|
13107
|
-
var TOOLTIP_INTERSECTION = new
|
|
13108
|
-
var TOOLTIP_PLANE_NORMAL = new
|
|
13109
|
-
var TOOLTIP_PLANE_POINT = new
|
|
13575
|
+
var TOOLTIP_INTERSECTION = new Vector314();
|
|
13576
|
+
var TOOLTIP_PLANE_NORMAL = new Vector314();
|
|
13577
|
+
var TOOLTIP_PLANE_POINT = new Vector314();
|
|
13110
13578
|
var HOTSPOT_MODE_RENDERING = {
|
|
13111
13579
|
surface: { orientation: "surface", placement: "surface" },
|
|
13112
13580
|
billboard: { orientation: "billboard", placement: "floating" }
|
|
13113
13581
|
};
|
|
13114
13582
|
function angularSizeToWorldSize(size, radius) {
|
|
13115
|
-
const safeSize = Number.isFinite(size) ?
|
|
13116
|
-
return 2 * radius * Math.tan(
|
|
13583
|
+
const safeSize = Number.isFinite(size) ? MathUtils8.clamp(Math.abs(size), MIN_ANGULAR_SIZE, MAX_ANGULAR_SIZE) : MIN_ANGULAR_SIZE;
|
|
13584
|
+
return 2 * radius * Math.tan(MathUtils8.degToRad(safeSize) / 2);
|
|
13117
13585
|
}
|
|
13118
13586
|
function resolveScale(scale) {
|
|
13119
13587
|
return Number.isFinite(scale) && scale > 0 ? scale : 1;
|
|
@@ -13126,7 +13594,7 @@ function resolveDistance(placement, distance, width, height) {
|
|
|
13126
13594
|
if (!Number.isFinite(distance)) {
|
|
13127
13595
|
return DEFAULT_FLOATING_DISTANCE;
|
|
13128
13596
|
}
|
|
13129
|
-
return
|
|
13597
|
+
return MathUtils8.clamp(Math.abs(distance), 0.1, maximumDistance);
|
|
13130
13598
|
}
|
|
13131
13599
|
function applyHotspotTransform(group, camera, orientation2, surfaceQuaternion3, rotation, scaleMode, referenceFov, useAngularScale, worldWidth, worldHeight) {
|
|
13132
13600
|
if (orientation2 === "billboard") {
|
|
@@ -13134,8 +13602,8 @@ function applyHotspotTransform(group, camera, orientation2, surfaceQuaternion3,
|
|
|
13134
13602
|
} else {
|
|
13135
13603
|
group.quaternion.copy(surfaceQuaternion3);
|
|
13136
13604
|
}
|
|
13137
|
-
group.rotateOnAxis(LOCAL_FORWARD,
|
|
13138
|
-
const scaleFactor = scaleMode === "fixed" && camera instanceof
|
|
13605
|
+
group.rotateOnAxis(LOCAL_FORWARD, MathUtils8.degToRad(-rotation));
|
|
13606
|
+
const scaleFactor = scaleMode === "fixed" && camera instanceof PerspectiveCamera6 ? fixedScaleFactor(camera.fov, referenceFov) : 1;
|
|
13139
13607
|
group.scale.set(
|
|
13140
13608
|
(useAngularScale ? worldWidth : 1) * scaleFactor,
|
|
13141
13609
|
(useAngularScale ? worldHeight : 1) * scaleFactor,
|
|
@@ -13144,39 +13612,39 @@ function applyHotspotTransform(group, camera, orientation2, surfaceQuaternion3,
|
|
|
13144
13612
|
group.updateMatrixWorld();
|
|
13145
13613
|
}
|
|
13146
13614
|
function maximumHotspotDistance(width, height) {
|
|
13147
|
-
const safeWidth =
|
|
13615
|
+
const safeWidth = MathUtils8.clamp(
|
|
13148
13616
|
Math.abs(Number.isFinite(width) ? width : MIN_ANGULAR_SIZE),
|
|
13149
13617
|
MIN_ANGULAR_SIZE,
|
|
13150
13618
|
MAX_ANGULAR_SIZE
|
|
13151
13619
|
);
|
|
13152
|
-
const safeHeight =
|
|
13620
|
+
const safeHeight = MathUtils8.clamp(
|
|
13153
13621
|
Math.abs(Number.isFinite(height) ? height : MIN_ANGULAR_SIZE),
|
|
13154
13622
|
MIN_ANGULAR_SIZE,
|
|
13155
13623
|
MAX_ANGULAR_SIZE
|
|
13156
13624
|
);
|
|
13157
13625
|
const cornerFactor = Math.hypot(
|
|
13158
13626
|
1,
|
|
13159
|
-
Math.tan(
|
|
13160
|
-
Math.tan(
|
|
13627
|
+
Math.tan(MathUtils8.degToRad(safeWidth) / 2),
|
|
13628
|
+
Math.tan(MathUtils8.degToRad(safeHeight) / 2)
|
|
13161
13629
|
);
|
|
13162
13630
|
return (PANORAMA_RADIUS - PANORAMA_SURFACE_INSET) / cornerFactor;
|
|
13163
13631
|
}
|
|
13164
13632
|
function fixedScaleFactor(cameraFov, referenceFov) {
|
|
13165
|
-
const safeReferenceFov =
|
|
13166
|
-
return Math.tan(
|
|
13633
|
+
const safeReferenceFov = MathUtils8.clamp(referenceFov, 1, 179);
|
|
13634
|
+
return Math.tan(MathUtils8.degToRad(cameraFov) / 2) / Math.tan(MathUtils8.degToRad(safeReferenceFov) / 2);
|
|
13167
13635
|
}
|
|
13168
13636
|
function createSurfaceQuaternion(position) {
|
|
13169
13637
|
const outward = panoPositionToVector3(position).normalize();
|
|
13170
13638
|
const inward = outward.clone().negate();
|
|
13171
|
-
const pitch =
|
|
13172
|
-
const yaw =
|
|
13173
|
-
const localUp = new
|
|
13639
|
+
const pitch = MathUtils8.degToRad(position.pitch);
|
|
13640
|
+
const yaw = MathUtils8.degToRad(position.yaw);
|
|
13641
|
+
const localUp = new Vector314(
|
|
13174
13642
|
-Math.sin(pitch) * Math.sin(yaw),
|
|
13175
13643
|
Math.cos(pitch),
|
|
13176
13644
|
Math.sin(pitch) * Math.cos(yaw)
|
|
13177
13645
|
).normalize();
|
|
13178
13646
|
const localRight = localUp.clone().cross(inward).normalize();
|
|
13179
|
-
const basis = new
|
|
13647
|
+
const basis = new Matrix44().makeBasis(localRight, localUp, inward);
|
|
13180
13648
|
return new Quaternion3().setFromRotationMatrix(basis);
|
|
13181
13649
|
}
|
|
13182
13650
|
function makeInteractionEvent(id, position, event) {
|
|
@@ -13190,7 +13658,7 @@ function makeInteractionEvent(id, position, event) {
|
|
|
13190
13658
|
function angularDistance(a, b) {
|
|
13191
13659
|
const aVector = panoPositionToVector3(a);
|
|
13192
13660
|
const bVector = panoPositionToVector3(b);
|
|
13193
|
-
return
|
|
13661
|
+
return MathUtils8.radToDeg(aVector.angleTo(bVector));
|
|
13194
13662
|
}
|
|
13195
13663
|
function isTooltipOpen(trigger, hovered, focused, pinned) {
|
|
13196
13664
|
switch (trigger) {
|
|
@@ -13425,20 +13893,20 @@ function HotspotAnchor({
|
|
|
13425
13893
|
const hotspotTargetRegistry = useContext25(HotspotTargetRegistryContext);
|
|
13426
13894
|
const eventBus = useContext25(PanoEventBusContext);
|
|
13427
13895
|
const cursorApi = usePanoCursor();
|
|
13428
|
-
const { camera, size } =
|
|
13429
|
-
const groupRef =
|
|
13430
|
-
const tooltipAnchorRef =
|
|
13431
|
-
const dragStateRef =
|
|
13432
|
-
const suppressNextClickRef =
|
|
13433
|
-
const [hovered, setHovered] =
|
|
13434
|
-
const [dragging, setDragging] =
|
|
13435
|
-
const [pinned, setPinned] =
|
|
13436
|
-
const tooltipContent =
|
|
13896
|
+
const { camera, size } = useThree21();
|
|
13897
|
+
const groupRef = useRef30(null);
|
|
13898
|
+
const tooltipAnchorRef = useRef30(null);
|
|
13899
|
+
const dragStateRef = useRef30(null);
|
|
13900
|
+
const suppressNextClickRef = useRef30(false);
|
|
13901
|
+
const [hovered, setHovered] = useState16(false);
|
|
13902
|
+
const [dragging, setDragging] = useState16(false);
|
|
13903
|
+
const [pinned, setPinned] = useState16(false);
|
|
13904
|
+
const tooltipContent = useMemo23(
|
|
13437
13905
|
() => resolveHotspotTooltipContent(tooltip),
|
|
13438
13906
|
[tooltip]
|
|
13439
13907
|
);
|
|
13440
13908
|
const normalizedPosition = normalizePanoPosition(position);
|
|
13441
|
-
|
|
13909
|
+
useEffect31(() => {
|
|
13442
13910
|
if (!hotspotTargetRegistry) {
|
|
13443
13911
|
return;
|
|
13444
13912
|
}
|
|
@@ -13455,17 +13923,17 @@ function HotspotAnchor({
|
|
|
13455
13923
|
scaledWidth,
|
|
13456
13924
|
scaledHeight
|
|
13457
13925
|
);
|
|
13458
|
-
const worldPosition =
|
|
13926
|
+
const worldPosition = useMemo23(
|
|
13459
13927
|
() => panoPositionToVector3(normalizedPosition, resolvedDistance),
|
|
13460
13928
|
[normalizedPosition.pitch, normalizedPosition.yaw, resolvedDistance]
|
|
13461
13929
|
);
|
|
13462
|
-
const surfaceQuaternion3 =
|
|
13930
|
+
const surfaceQuaternion3 = useMemo23(
|
|
13463
13931
|
() => createSurfaceQuaternion(normalizedPosition),
|
|
13464
13932
|
[normalizedPosition.pitch, normalizedPosition.yaw]
|
|
13465
13933
|
);
|
|
13466
13934
|
const worldWidth = angularSizeToWorldSize(scaledWidth, resolvedDistance);
|
|
13467
13935
|
const worldHeight = angularSizeToWorldSize(scaledHeight, resolvedDistance);
|
|
13468
|
-
const focusGeometry =
|
|
13936
|
+
const focusGeometry = useMemo23(() => {
|
|
13469
13937
|
const planeGeometry = new PlaneGeometry5(1, 1);
|
|
13470
13938
|
const geometry = new EdgesGeometry(planeGeometry);
|
|
13471
13939
|
planeGeometry.dispose();
|
|
@@ -13492,14 +13960,14 @@ function HotspotAnchor({
|
|
|
13492
13960
|
});
|
|
13493
13961
|
const tooltipOpen = visible && tooltipContent !== null && isTooltipOpen(tooltipTrigger, hovered, focused, pinned);
|
|
13494
13962
|
const cursorClaimId = hotspotCursorClaimId(id);
|
|
13495
|
-
|
|
13963
|
+
useEffect31(
|
|
13496
13964
|
() => () => {
|
|
13497
13965
|
dragStateRef.current?.releaseInteractionLock();
|
|
13498
13966
|
dragStateRef.current = null;
|
|
13499
13967
|
},
|
|
13500
13968
|
[]
|
|
13501
13969
|
);
|
|
13502
|
-
|
|
13970
|
+
useEffect31(() => {
|
|
13503
13971
|
if (!cursorApi) {
|
|
13504
13972
|
return;
|
|
13505
13973
|
}
|
|
@@ -13521,14 +13989,14 @@ function HotspotAnchor({
|
|
|
13521
13989
|
hovered,
|
|
13522
13990
|
visible
|
|
13523
13991
|
]);
|
|
13524
|
-
|
|
13992
|
+
useEffect31(
|
|
13525
13993
|
() => () => {
|
|
13526
13994
|
cursorApi?.release(cursorClaimId);
|
|
13527
13995
|
},
|
|
13528
13996
|
[cursorApi, cursorClaimId]
|
|
13529
13997
|
);
|
|
13530
|
-
|
|
13531
|
-
|
|
13998
|
+
useEffect31(() => () => focusGeometry.dispose(), [focusGeometry]);
|
|
13999
|
+
useEffect31(() => {
|
|
13532
14000
|
if (tooltipTrigger !== "click") {
|
|
13533
14001
|
setPinned(false);
|
|
13534
14002
|
return;
|
|
@@ -13537,12 +14005,12 @@ function HotspotAnchor({
|
|
|
13537
14005
|
setPinned(false);
|
|
13538
14006
|
});
|
|
13539
14007
|
}, [eventBus, tooltipTrigger]);
|
|
13540
|
-
|
|
14008
|
+
useEffect31(() => {
|
|
13541
14009
|
if (tooltipTrigger !== "hover") {
|
|
13542
14010
|
setHovered(false);
|
|
13543
14011
|
}
|
|
13544
14012
|
}, [tooltipTrigger]);
|
|
13545
|
-
|
|
14013
|
+
useEffect31(() => {
|
|
13546
14014
|
if (acceptsPointer) {
|
|
13547
14015
|
return;
|
|
13548
14016
|
}
|
|
@@ -13596,7 +14064,7 @@ function HotspotAnchor({
|
|
|
13596
14064
|
worldHeight,
|
|
13597
14065
|
worldWidth
|
|
13598
14066
|
]);
|
|
13599
|
-
|
|
14067
|
+
useFrame14((state) => {
|
|
13600
14068
|
const group = groupRef.current;
|
|
13601
14069
|
if (!group) {
|
|
13602
14070
|
return;
|
|
@@ -13654,7 +14122,7 @@ function HotspotAnchor({
|
|
|
13654
14122
|
setHovered(true);
|
|
13655
14123
|
}
|
|
13656
14124
|
};
|
|
13657
|
-
return /* @__PURE__ */
|
|
14125
|
+
return /* @__PURE__ */ jsxs17(
|
|
13658
14126
|
"group",
|
|
13659
14127
|
{
|
|
13660
14128
|
ref: groupRef,
|
|
@@ -13731,18 +14199,18 @@ function HotspotAnchor({
|
|
|
13731
14199
|
} : void 0,
|
|
13732
14200
|
onPointerUp: acceptsPointer ? (event) => releasePointer(event, true) : void 0,
|
|
13733
14201
|
children: [
|
|
13734
|
-
focused ? focusContent ?? /* @__PURE__ */
|
|
14202
|
+
focused ? focusContent ?? /* @__PURE__ */ jsx26(
|
|
13735
14203
|
"lineSegments",
|
|
13736
14204
|
{
|
|
13737
14205
|
geometry: focusGeometry,
|
|
13738
14206
|
position: [0, 0, 0.01],
|
|
13739
14207
|
renderOrder: renderOrder + 1,
|
|
13740
14208
|
scale: [1.12, 1.12, 1],
|
|
13741
|
-
children: /* @__PURE__ */
|
|
14209
|
+
children: /* @__PURE__ */ jsx26("lineBasicMaterial", { color: "#f5fbfc", depthTest: false })
|
|
13742
14210
|
}
|
|
13743
14211
|
) : null,
|
|
13744
14212
|
children,
|
|
13745
|
-
tooltipOpen && tooltipContent ? /* @__PURE__ */
|
|
14213
|
+
tooltipOpen && tooltipContent ? /* @__PURE__ */ jsx26("group", { ref: tooltipAnchorRef, children: /* @__PURE__ */ jsx26(
|
|
13746
14214
|
HotspotTooltip,
|
|
13747
14215
|
{
|
|
13748
14216
|
appearance: tooltipAppearance,
|
|
@@ -13763,7 +14231,7 @@ import {
|
|
|
13763
14231
|
MeshBasicMaterial,
|
|
13764
14232
|
Vector2 as Vector26
|
|
13765
14233
|
} from "three";
|
|
13766
|
-
import { jsx as
|
|
14234
|
+
import { jsx as jsx27, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
13767
14235
|
var HOTSPOT_ALPHA_CUTOFF = 0.05;
|
|
13768
14236
|
var SAMPLE_UV = new Vector26();
|
|
13769
14237
|
var RAYCAST_HITS = [];
|
|
@@ -13865,11 +14333,12 @@ function HotspotPlane({
|
|
|
13865
14333
|
map,
|
|
13866
14334
|
opacity
|
|
13867
14335
|
}) {
|
|
13868
|
-
return /* @__PURE__ */
|
|
13869
|
-
/* @__PURE__ */
|
|
13870
|
-
/* @__PURE__ */
|
|
13871
|
-
|
|
14336
|
+
return /* @__PURE__ */ jsxs18("mesh", { raycast: hotspotPlaneRaycast, children: [
|
|
14337
|
+
/* @__PURE__ */ jsx27("planeGeometry", { args: [1, 1] }),
|
|
14338
|
+
/* @__PURE__ */ jsx27(
|
|
14339
|
+
PanoBasicMaterial,
|
|
13872
14340
|
{
|
|
14341
|
+
target: "hotspot",
|
|
13873
14342
|
alphaTest: HOTSPOT_ALPHA_CUTOFF,
|
|
13874
14343
|
alphaToCoverage: true,
|
|
13875
14344
|
map,
|
|
@@ -13883,15 +14352,15 @@ function HotspotPlane({
|
|
|
13883
14352
|
}
|
|
13884
14353
|
|
|
13885
14354
|
// src/hotspot/image-hotspot.tsx
|
|
13886
|
-
import { jsx as
|
|
14355
|
+
import { jsx as jsx28 } from "react/jsx-runtime";
|
|
13887
14356
|
function useHotspotImageTexture(src, onLoad, onError) {
|
|
13888
|
-
const gl =
|
|
13889
|
-
const [texture, setTexture] =
|
|
13890
|
-
const onLoadRef =
|
|
13891
|
-
const onErrorRef =
|
|
14357
|
+
const gl = useThree22((state) => state.gl);
|
|
14358
|
+
const [texture, setTexture] = useState17(null);
|
|
14359
|
+
const onLoadRef = useRef31(onLoad);
|
|
14360
|
+
const onErrorRef = useRef31(onError);
|
|
13892
14361
|
onLoadRef.current = onLoad;
|
|
13893
14362
|
onErrorRef.current = onError;
|
|
13894
|
-
|
|
14363
|
+
useEffect32(() => {
|
|
13895
14364
|
let active = true;
|
|
13896
14365
|
setTexture(null);
|
|
13897
14366
|
if (!src) {
|
|
@@ -13929,7 +14398,7 @@ function useHotspotImageTexture(src, onLoad, onError) {
|
|
|
13929
14398
|
active = false;
|
|
13930
14399
|
};
|
|
13931
14400
|
}, [gl, src]);
|
|
13932
|
-
|
|
14401
|
+
useEffect32(
|
|
13933
14402
|
() => () => {
|
|
13934
14403
|
texture?.dispose();
|
|
13935
14404
|
},
|
|
@@ -13947,33 +14416,33 @@ function ImageHotspot({
|
|
|
13947
14416
|
...anchorProps
|
|
13948
14417
|
}) {
|
|
13949
14418
|
const texture = useHotspotImageTexture(src, onLoad, onError);
|
|
13950
|
-
return /* @__PURE__ */
|
|
14419
|
+
return /* @__PURE__ */ jsx28(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ jsx28(HotspotPlane, { map: texture, opacity }) });
|
|
13951
14420
|
}
|
|
13952
14421
|
|
|
13953
14422
|
// src/hotspot/polygon-hotspot.tsx
|
|
13954
|
-
import { useEffect as
|
|
14423
|
+
import { useEffect as useEffect33, useMemo as useMemo24, useRef as useRef33 } from "react";
|
|
13955
14424
|
import {
|
|
13956
|
-
BufferGeometry,
|
|
14425
|
+
BufferGeometry as BufferGeometry2,
|
|
13957
14426
|
DoubleSide as DoubleSide5,
|
|
13958
|
-
Float32BufferAttribute,
|
|
13959
|
-
Matrix4 as
|
|
14427
|
+
Float32BufferAttribute as Float32BufferAttribute2,
|
|
14428
|
+
Matrix4 as Matrix45,
|
|
13960
14429
|
Quaternion as Quaternion4,
|
|
13961
14430
|
ShapeUtils,
|
|
13962
14431
|
Vector2 as Vector27,
|
|
13963
|
-
Vector3 as
|
|
14432
|
+
Vector3 as Vector316
|
|
13964
14433
|
} from "three";
|
|
13965
14434
|
|
|
13966
14435
|
// src/hotspot/hotspot-stroke-line.tsx
|
|
13967
14436
|
import { Line } from "@react-three/drei";
|
|
13968
|
-
import { useFrame as
|
|
13969
|
-
import { useLayoutEffect as useLayoutEffect5, useRef as
|
|
14437
|
+
import { useFrame as useFrame15, useThree as useThree23 } from "@react-three/fiber";
|
|
14438
|
+
import { useLayoutEffect as useLayoutEffect5, useRef as useRef32 } from "react";
|
|
13970
14439
|
import {
|
|
13971
|
-
MathUtils as
|
|
13972
|
-
PerspectiveCamera as
|
|
13973
|
-
Vector3 as
|
|
14440
|
+
MathUtils as MathUtils9,
|
|
14441
|
+
PerspectiveCamera as PerspectiveCamera7,
|
|
14442
|
+
Vector3 as Vector315
|
|
13974
14443
|
} from "three";
|
|
13975
|
-
import { jsx as
|
|
13976
|
-
var LINE_WORLD_POSITION = new
|
|
14444
|
+
import { jsx as jsx29 } from "react/jsx-runtime";
|
|
14445
|
+
var LINE_WORLD_POSITION = new Vector315();
|
|
13977
14446
|
function applyScreenSpaceDashScale(object, camera, viewportHeight) {
|
|
13978
14447
|
const material = object?.material;
|
|
13979
14448
|
if (!object || typeof material?.dashScale !== "number") {
|
|
@@ -13981,8 +14450,8 @@ function applyScreenSpaceDashScale(object, camera, viewportHeight) {
|
|
|
13981
14450
|
}
|
|
13982
14451
|
object.getWorldPosition(LINE_WORLD_POSITION);
|
|
13983
14452
|
const depth = Math.max(camera.position.distanceTo(LINE_WORLD_POSITION), 1);
|
|
13984
|
-
const fov = camera instanceof
|
|
13985
|
-
material.dashScale = viewportHeight / (2 * Math.tan(
|
|
14453
|
+
const fov = camera instanceof PerspectiveCamera7 ? camera.fov : 75;
|
|
14454
|
+
material.dashScale = viewportHeight / (2 * Math.tan(MathUtils9.degToRad(fov) * 0.5) * depth);
|
|
13986
14455
|
}
|
|
13987
14456
|
function resolveDash(dashSize, gapSize) {
|
|
13988
14457
|
if (dashSize === void 0 || !Number.isFinite(dashSize) || dashSize <= 0) {
|
|
@@ -14003,8 +14472,8 @@ function HotspotStrokeLine({
|
|
|
14003
14472
|
dashSize,
|
|
14004
14473
|
gapSize
|
|
14005
14474
|
}) {
|
|
14006
|
-
const lineRef =
|
|
14007
|
-
const { camera, size } =
|
|
14475
|
+
const lineRef = useRef32(null);
|
|
14476
|
+
const { camera, size } = useThree23();
|
|
14008
14477
|
const dash = resolveDash(dashSize, gapSize);
|
|
14009
14478
|
useLayoutEffect5(() => {
|
|
14010
14479
|
if (!dash.dashed) {
|
|
@@ -14012,13 +14481,13 @@ function HotspotStrokeLine({
|
|
|
14012
14481
|
}
|
|
14013
14482
|
applyScreenSpaceDashScale(lineRef.current, camera, size.height);
|
|
14014
14483
|
}, [camera, dash.dashed, dash.dashSize, dash.gapSize, size.height]);
|
|
14015
|
-
|
|
14484
|
+
useFrame15((state) => {
|
|
14016
14485
|
if (!dash.dashed) {
|
|
14017
14486
|
return;
|
|
14018
14487
|
}
|
|
14019
14488
|
applyScreenSpaceDashScale(lineRef.current, state.camera, state.size.height);
|
|
14020
14489
|
});
|
|
14021
|
-
return /* @__PURE__ */
|
|
14490
|
+
return /* @__PURE__ */ jsx29(
|
|
14022
14491
|
Line,
|
|
14023
14492
|
{
|
|
14024
14493
|
ref: lineRef,
|
|
@@ -14040,7 +14509,7 @@ function HotspotStrokeLine({
|
|
|
14040
14509
|
}
|
|
14041
14510
|
|
|
14042
14511
|
// src/hotspot/polygon-hotspot.tsx
|
|
14043
|
-
import { jsx as
|
|
14512
|
+
import { jsx as jsx30, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
14044
14513
|
var POLYGON_RADIUS = 990;
|
|
14045
14514
|
var MAX_FILL_SEGMENT_DEGREES = 7;
|
|
14046
14515
|
function cloneVertices(vertices) {
|
|
@@ -14112,7 +14581,7 @@ function polygonContainsDirection(vertices, direction) {
|
|
|
14112
14581
|
}
|
|
14113
14582
|
function fitsHemisphere(vertices) {
|
|
14114
14583
|
const directions = vertices.map((vertex) => panoPositionToVector3(vertex).normalize());
|
|
14115
|
-
const candidates = [new
|
|
14584
|
+
const candidates = [new Vector316()];
|
|
14116
14585
|
for (const direction of directions) {
|
|
14117
14586
|
candidates[0].add(direction);
|
|
14118
14587
|
candidates.push(direction.clone());
|
|
@@ -14136,7 +14605,7 @@ function validatePolygonVertices(vertices) {
|
|
|
14136
14605
|
if (hasSelfIntersection(unwrapped)) {
|
|
14137
14606
|
issues.push({ code: "self_intersection", message: "Polygon edges cannot cross." });
|
|
14138
14607
|
}
|
|
14139
|
-
if (polygonContainsDirection(normalized, new
|
|
14608
|
+
if (polygonContainsDirection(normalized, new Vector316(0, 1, 0)) || polygonContainsDirection(normalized, new Vector316(0, -1, 0))) {
|
|
14140
14609
|
issues.push({ code: "contains_pole", message: "Polygons cannot contain a panorama pole." });
|
|
14141
14610
|
}
|
|
14142
14611
|
if (!fitsHemisphere(normalized)) {
|
|
@@ -14147,7 +14616,7 @@ function validatePolygonVertices(vertices) {
|
|
|
14147
14616
|
function polygonCenter(vertices) {
|
|
14148
14617
|
const sum = vertices.reduce(
|
|
14149
14618
|
(total, vertex) => total.add(panoPositionToVector3(vertex).normalize()),
|
|
14150
|
-
new
|
|
14619
|
+
new Vector316()
|
|
14151
14620
|
);
|
|
14152
14621
|
return sum.lengthSq() > 1e-8 ? vector3ToPanoPosition(sum) : normalizePanoPosition(vertices[0]);
|
|
14153
14622
|
}
|
|
@@ -14156,20 +14625,20 @@ function surfaceQuaternion(position) {
|
|
|
14156
14625
|
const inward = outward.clone().negate();
|
|
14157
14626
|
const pitch = position.pitch * Math.PI / 180;
|
|
14158
14627
|
const yaw = position.yaw * Math.PI / 180;
|
|
14159
|
-
const localUp = new
|
|
14628
|
+
const localUp = new Vector316(
|
|
14160
14629
|
-Math.sin(pitch) * Math.sin(yaw),
|
|
14161
14630
|
Math.cos(pitch),
|
|
14162
14631
|
Math.sin(pitch) * Math.cos(yaw)
|
|
14163
14632
|
).normalize();
|
|
14164
14633
|
return new Quaternion4().setFromRotationMatrix(
|
|
14165
|
-
new
|
|
14634
|
+
new Matrix45().makeBasis(localUp.clone().cross(inward).normalize(), localUp, inward)
|
|
14166
14635
|
);
|
|
14167
14636
|
}
|
|
14168
14637
|
function makeWorldToLocal(center) {
|
|
14169
|
-
return new
|
|
14638
|
+
return new Matrix45().compose(
|
|
14170
14639
|
panoPositionToVector3(center, POLYGON_RADIUS),
|
|
14171
14640
|
surfaceQuaternion(center),
|
|
14172
|
-
new
|
|
14641
|
+
new Vector316(1, 1, 1)
|
|
14173
14642
|
).invert();
|
|
14174
14643
|
}
|
|
14175
14644
|
function projectedPoint(a, b, c, weightB, weightC, radius, worldToLocal) {
|
|
@@ -14241,7 +14710,7 @@ function makeFillGeometry(vertices, center) {
|
|
|
14241
14710
|
steps
|
|
14242
14711
|
);
|
|
14243
14712
|
}
|
|
14244
|
-
return new
|
|
14713
|
+
return new BufferGeometry2().setAttribute("position", new Float32BufferAttribute2(positions, 3)).setIndex(indices);
|
|
14245
14714
|
}
|
|
14246
14715
|
function makeStrokePositions(vertices, center) {
|
|
14247
14716
|
const points = [];
|
|
@@ -14296,24 +14765,24 @@ function PolygonHotspot({
|
|
|
14296
14765
|
onInvalid,
|
|
14297
14766
|
...anchorProps
|
|
14298
14767
|
}) {
|
|
14299
|
-
const issues =
|
|
14768
|
+
const issues = useMemo24(() => validatePolygonVertices(vertices), [vertices]);
|
|
14300
14769
|
const valid = issues.length === 0;
|
|
14301
|
-
const center =
|
|
14302
|
-
const fillGeometry =
|
|
14770
|
+
const center = useMemo24(() => valid ? polygonCenter(vertices) : null, [valid, vertices]);
|
|
14771
|
+
const fillGeometry = useMemo24(
|
|
14303
14772
|
() => valid && center ? makeFillGeometry(vertices, center) : null,
|
|
14304
14773
|
[center, valid, vertices]
|
|
14305
14774
|
);
|
|
14306
|
-
const strokePoints =
|
|
14775
|
+
const strokePoints = useMemo24(
|
|
14307
14776
|
() => valid && center ? makeStrokePositions(vertices, center) : null,
|
|
14308
14777
|
[center, valid, vertices]
|
|
14309
14778
|
);
|
|
14310
14779
|
const resolvedStrokeOpacity = Math.max(0, Math.min(strokeOpacity, 1));
|
|
14311
|
-
const startVerticesRef =
|
|
14780
|
+
const startVerticesRef = useRef33(null);
|
|
14312
14781
|
const issuesKey = issues.map((issue) => issue.code).join(",");
|
|
14313
|
-
|
|
14782
|
+
useEffect33(() => {
|
|
14314
14783
|
if (!valid) onInvalid?.(issues);
|
|
14315
14784
|
}, [issues, issuesKey, onInvalid, valid]);
|
|
14316
|
-
|
|
14785
|
+
useEffect33(() => () => fillGeometry?.dispose(), [fillGeometry]);
|
|
14317
14786
|
if (!valid || !center || !fillGeometry || !strokePoints || strokePoints.length < 2) {
|
|
14318
14787
|
return null;
|
|
14319
14788
|
}
|
|
@@ -14328,7 +14797,7 @@ function PolygonHotspot({
|
|
|
14328
14797
|
startPosition: event.startPosition
|
|
14329
14798
|
});
|
|
14330
14799
|
};
|
|
14331
|
-
return /* @__PURE__ */
|
|
14800
|
+
return /* @__PURE__ */ jsxs19(
|
|
14332
14801
|
HotspotAnchor,
|
|
14333
14802
|
{
|
|
14334
14803
|
...anchorProps,
|
|
@@ -14343,7 +14812,7 @@ function PolygonHotspot({
|
|
|
14343
14812
|
draggable,
|
|
14344
14813
|
interactive,
|
|
14345
14814
|
useAngularScale: false,
|
|
14346
|
-
focusContent: /* @__PURE__ */
|
|
14815
|
+
focusContent: /* @__PURE__ */ jsx30(
|
|
14347
14816
|
HotspotStrokeLine,
|
|
14348
14817
|
{
|
|
14349
14818
|
color: "#75cbd3",
|
|
@@ -14365,7 +14834,7 @@ function PolygonHotspot({
|
|
|
14365
14834
|
startVerticesRef.current = null;
|
|
14366
14835
|
},
|
|
14367
14836
|
children: [
|
|
14368
|
-
/* @__PURE__ */
|
|
14837
|
+
/* @__PURE__ */ jsx30("mesh", { geometry: fillGeometry, renderOrder, children: /* @__PURE__ */ jsx30(
|
|
14369
14838
|
"meshBasicMaterial",
|
|
14370
14839
|
{
|
|
14371
14840
|
color: fill,
|
|
@@ -14375,7 +14844,7 @@ function PolygonHotspot({
|
|
|
14375
14844
|
transparent: true
|
|
14376
14845
|
}
|
|
14377
14846
|
) }),
|
|
14378
|
-
/* @__PURE__ */
|
|
14847
|
+
/* @__PURE__ */ jsx30(
|
|
14379
14848
|
HotspotStrokeLine,
|
|
14380
14849
|
{
|
|
14381
14850
|
color: stroke,
|
|
@@ -14393,14 +14862,14 @@ function PolygonHotspot({
|
|
|
14393
14862
|
}
|
|
14394
14863
|
|
|
14395
14864
|
// src/hotspot/polyline-hotspot.tsx
|
|
14396
|
-
import { useEffect as
|
|
14865
|
+
import { useEffect as useEffect34, useMemo as useMemo25, useRef as useRef34 } from "react";
|
|
14397
14866
|
import {
|
|
14398
|
-
MathUtils as
|
|
14399
|
-
Matrix4 as
|
|
14867
|
+
MathUtils as MathUtils10,
|
|
14868
|
+
Matrix4 as Matrix46,
|
|
14400
14869
|
Quaternion as Quaternion5,
|
|
14401
|
-
Vector3 as
|
|
14870
|
+
Vector3 as Vector317
|
|
14402
14871
|
} from "three";
|
|
14403
|
-
import { jsx as
|
|
14872
|
+
import { jsx as jsx31 } from "react/jsx-runtime";
|
|
14404
14873
|
var POLYLINE_RADIUS = 990;
|
|
14405
14874
|
var MAX_SEGMENT_DEGREES = 7;
|
|
14406
14875
|
function cloneVertices2(vertices) {
|
|
@@ -14425,29 +14894,29 @@ function unwrapVertices(vertices) {
|
|
|
14425
14894
|
function polylineCenter(vertices) {
|
|
14426
14895
|
const sum = vertices.reduce(
|
|
14427
14896
|
(total, vertex) => total.add(panoPositionToVector3(vertex).normalize()),
|
|
14428
|
-
new
|
|
14897
|
+
new Vector317()
|
|
14429
14898
|
);
|
|
14430
14899
|
return sum.lengthSq() > 1e-8 ? vector3ToPanoPosition(sum) : normalizePanoPosition(vertices[0]);
|
|
14431
14900
|
}
|
|
14432
14901
|
function surfaceQuaternion2(position) {
|
|
14433
14902
|
const outward = panoPositionToVector3(position).normalize();
|
|
14434
14903
|
const inward = outward.clone().negate();
|
|
14435
|
-
const pitch =
|
|
14436
|
-
const yaw =
|
|
14437
|
-
const localUp = new
|
|
14904
|
+
const pitch = MathUtils10.degToRad(position.pitch);
|
|
14905
|
+
const yaw = MathUtils10.degToRad(position.yaw);
|
|
14906
|
+
const localUp = new Vector317(
|
|
14438
14907
|
-Math.sin(pitch) * Math.sin(yaw),
|
|
14439
14908
|
Math.cos(pitch),
|
|
14440
14909
|
Math.sin(pitch) * Math.cos(yaw)
|
|
14441
14910
|
).normalize();
|
|
14442
14911
|
return new Quaternion5().setFromRotationMatrix(
|
|
14443
|
-
new
|
|
14912
|
+
new Matrix46().makeBasis(localUp.clone().cross(inward).normalize(), localUp, inward)
|
|
14444
14913
|
);
|
|
14445
14914
|
}
|
|
14446
14915
|
function makeWorldToLocal2(center) {
|
|
14447
|
-
return new
|
|
14916
|
+
return new Matrix46().compose(
|
|
14448
14917
|
panoPositionToVector3(center, POLYLINE_RADIUS),
|
|
14449
14918
|
surfaceQuaternion2(center),
|
|
14450
|
-
new
|
|
14919
|
+
new Vector317(1, 1, 1)
|
|
14451
14920
|
).invert();
|
|
14452
14921
|
}
|
|
14453
14922
|
function subdivisionSteps(vertices) {
|
|
@@ -14462,7 +14931,7 @@ function subdivisionSteps(vertices) {
|
|
|
14462
14931
|
}
|
|
14463
14932
|
return Math.min(
|
|
14464
14933
|
8,
|
|
14465
|
-
Math.max(1, Math.ceil(
|
|
14934
|
+
Math.max(1, Math.ceil(MathUtils10.radToDeg(maxAngle) / MAX_SEGMENT_DEGREES))
|
|
14466
14935
|
);
|
|
14467
14936
|
}
|
|
14468
14937
|
function makeLinePositions(vertices, center) {
|
|
@@ -14517,16 +14986,16 @@ function PolylineHotspot({
|
|
|
14517
14986
|
onInvalid,
|
|
14518
14987
|
...anchorProps
|
|
14519
14988
|
}) {
|
|
14520
|
-
const issues =
|
|
14989
|
+
const issues = useMemo25(() => validatePolylineVertices(vertices), [vertices]);
|
|
14521
14990
|
const valid = issues.length === 0;
|
|
14522
|
-
const center =
|
|
14523
|
-
const linePoints =
|
|
14991
|
+
const center = useMemo25(() => valid ? polylineCenter(vertices) : null, [valid, vertices]);
|
|
14992
|
+
const linePoints = useMemo25(
|
|
14524
14993
|
() => valid && center ? makeLinePositions(vertices, center) : null,
|
|
14525
14994
|
[center, valid, vertices]
|
|
14526
14995
|
);
|
|
14527
14996
|
const opacity = Math.max(0, Math.min(strokeOpacity, 1));
|
|
14528
|
-
const startVerticesRef =
|
|
14529
|
-
|
|
14997
|
+
const startVerticesRef = useRef34(null);
|
|
14998
|
+
useEffect34(() => {
|
|
14530
14999
|
if (!valid) onInvalid?.(issues);
|
|
14531
15000
|
}, [issues, onInvalid, valid]);
|
|
14532
15001
|
if (!valid || !center || !linePoints || linePoints.length < 2) return null;
|
|
@@ -14540,7 +15009,7 @@ function PolylineHotspot({
|
|
|
14540
15009
|
startPosition: event.startPosition
|
|
14541
15010
|
});
|
|
14542
15011
|
};
|
|
14543
|
-
return /* @__PURE__ */
|
|
15012
|
+
return /* @__PURE__ */ jsx31(
|
|
14544
15013
|
HotspotAnchor,
|
|
14545
15014
|
{
|
|
14546
15015
|
...anchorProps,
|
|
@@ -14554,7 +15023,7 @@ function PolylineHotspot({
|
|
|
14554
15023
|
renderOrder,
|
|
14555
15024
|
draggable,
|
|
14556
15025
|
useAngularScale: false,
|
|
14557
|
-
focusContent: /* @__PURE__ */
|
|
15026
|
+
focusContent: /* @__PURE__ */ jsx31(
|
|
14558
15027
|
HotspotStrokeLine,
|
|
14559
15028
|
{
|
|
14560
15029
|
color: "#75cbd3",
|
|
@@ -14575,7 +15044,7 @@ function PolylineHotspot({
|
|
|
14575
15044
|
emitVerticesChange(event, onDragEnd);
|
|
14576
15045
|
startVerticesRef.current = null;
|
|
14577
15046
|
},
|
|
14578
|
-
children: /* @__PURE__ */
|
|
15047
|
+
children: /* @__PURE__ */ jsx31(
|
|
14579
15048
|
HotspotStrokeLine,
|
|
14580
15049
|
{
|
|
14581
15050
|
color: stroke,
|
|
@@ -14592,7 +15061,7 @@ function PolylineHotspot({
|
|
|
14592
15061
|
}
|
|
14593
15062
|
|
|
14594
15063
|
// src/hotspot/graphic-hotspot.tsx
|
|
14595
|
-
import { useEffect as
|
|
15064
|
+
import { useEffect as useEffect35, useRef as useRef35, useState as useState18 } from "react";
|
|
14596
15065
|
import {
|
|
14597
15066
|
CanvasTexture,
|
|
14598
15067
|
ClampToEdgeWrapping as ClampToEdgeWrapping4,
|
|
@@ -14600,7 +15069,7 @@ import {
|
|
|
14600
15069
|
LinearMipmapLinearFilter as LinearMipmapLinearFilter4,
|
|
14601
15070
|
SRGBColorSpace as SRGBColorSpace6
|
|
14602
15071
|
} from "three";
|
|
14603
|
-
import { jsx as
|
|
15072
|
+
import { jsx as jsx32 } from "react/jsx-runtime";
|
|
14604
15073
|
var GRAPHIC_TEXTURE_SIZE = 512;
|
|
14605
15074
|
function resolveStrokeWidth(value) {
|
|
14606
15075
|
return Number.isFinite(value) ? Math.max(value, 0) : 8;
|
|
@@ -14789,12 +15258,12 @@ function createGraphicTexture(graphic, aspectWidth, aspectHeight) {
|
|
|
14789
15258
|
return texture;
|
|
14790
15259
|
}
|
|
14791
15260
|
function useGraphicTexture(graphic, aspectWidth, aspectHeight, onLoad, onError) {
|
|
14792
|
-
const [texture, setTexture] =
|
|
14793
|
-
const onLoadRef =
|
|
14794
|
-
const onErrorRef =
|
|
15261
|
+
const [texture, setTexture] = useState18(null);
|
|
15262
|
+
const onLoadRef = useRef35(onLoad);
|
|
15263
|
+
const onErrorRef = useRef35(onError);
|
|
14795
15264
|
onLoadRef.current = onLoad;
|
|
14796
15265
|
onErrorRef.current = onError;
|
|
14797
|
-
|
|
15266
|
+
useEffect35(() => {
|
|
14798
15267
|
let nextTexture = null;
|
|
14799
15268
|
try {
|
|
14800
15269
|
nextTexture = createGraphicTexture(graphic, aspectWidth, aspectHeight);
|
|
@@ -14820,20 +15289,20 @@ function CanvasGraphicHotspot({
|
|
|
14820
15289
|
...anchorProps
|
|
14821
15290
|
}) {
|
|
14822
15291
|
const texture = useGraphicTexture(graphic, width, height, onLoad, onError);
|
|
14823
|
-
return /* @__PURE__ */
|
|
15292
|
+
return /* @__PURE__ */ jsx32(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ jsx32(HotspotPlane, { map: texture, opacity }) });
|
|
14824
15293
|
}
|
|
14825
15294
|
function GraphicHotspot(props) {
|
|
14826
15295
|
const { graphic, ...restProps } = props;
|
|
14827
15296
|
if (graphic.kind === "svg") {
|
|
14828
15297
|
const imageProps = restProps;
|
|
14829
|
-
return /* @__PURE__ */
|
|
15298
|
+
return /* @__PURE__ */ jsx32(ImageHotspot, { ...imageProps, src: graphic.src });
|
|
14830
15299
|
}
|
|
14831
|
-
return /* @__PURE__ */
|
|
15300
|
+
return /* @__PURE__ */ jsx32(CanvasGraphicHotspot, { ...restProps, graphic });
|
|
14832
15301
|
}
|
|
14833
15302
|
|
|
14834
15303
|
// src/hotspot/sequence-hotspot.tsx
|
|
14835
|
-
import { useFrame as
|
|
14836
|
-
import { useEffect as
|
|
15304
|
+
import { useFrame as useFrame16, useThree as useThree24 } from "@react-three/fiber";
|
|
15305
|
+
import { useEffect as useEffect36, useRef as useRef36, useState as useState19 } from "react";
|
|
14837
15306
|
import {
|
|
14838
15307
|
ClampToEdgeWrapping as ClampToEdgeWrapping5,
|
|
14839
15308
|
LinearFilter as LinearFilter8,
|
|
@@ -14841,7 +15310,7 @@ import {
|
|
|
14841
15310
|
SRGBColorSpace as SRGBColorSpace7,
|
|
14842
15311
|
TextureLoader as TextureLoader6
|
|
14843
15312
|
} from "three";
|
|
14844
|
-
import { jsx as
|
|
15313
|
+
import { jsx as jsx33 } from "react/jsx-runtime";
|
|
14845
15314
|
var DEFAULT_SEQUENCE_FPS = 12;
|
|
14846
15315
|
function resolveFps(value) {
|
|
14847
15316
|
return Number.isFinite(value) && value > 0 ? value : DEFAULT_SEQUENCE_FPS;
|
|
@@ -14855,13 +15324,13 @@ function useSpriteTexture({
|
|
|
14855
15324
|
onError,
|
|
14856
15325
|
onLoadProgress
|
|
14857
15326
|
}) {
|
|
14858
|
-
const gl =
|
|
14859
|
-
const [texture, setTexture] =
|
|
14860
|
-
const onErrorRef =
|
|
14861
|
-
const onLoadProgressRef =
|
|
15327
|
+
const gl = useThree24((state) => state.gl);
|
|
15328
|
+
const [texture, setTexture] = useState19(null);
|
|
15329
|
+
const onErrorRef = useRef36(onError);
|
|
15330
|
+
const onLoadProgressRef = useRef36(onLoadProgress);
|
|
14862
15331
|
onErrorRef.current = onError;
|
|
14863
15332
|
onLoadProgressRef.current = onLoadProgress;
|
|
14864
|
-
|
|
15333
|
+
useEffect36(() => {
|
|
14865
15334
|
let active = true;
|
|
14866
15335
|
setTexture(null);
|
|
14867
15336
|
if (!src) {
|
|
@@ -14902,7 +15371,7 @@ function useSpriteTexture({
|
|
|
14902
15371
|
active = false;
|
|
14903
15372
|
};
|
|
14904
15373
|
}, [gl, id, src]);
|
|
14905
|
-
|
|
15374
|
+
useEffect36(
|
|
14906
15375
|
() => () => {
|
|
14907
15376
|
texture?.dispose();
|
|
14908
15377
|
},
|
|
@@ -14931,24 +15400,24 @@ function SequenceHotspot({
|
|
|
14931
15400
|
const texture = useSpriteTexture({ id, src, onError, onLoadProgress });
|
|
14932
15401
|
const frameCount = resolveFrameCount(requestedFrameCount);
|
|
14933
15402
|
const safeFps = resolveFps(fps);
|
|
14934
|
-
const [frameIndex, setFrameIndex] =
|
|
14935
|
-
const elapsedRef =
|
|
14936
|
-
const frameIndexRef =
|
|
14937
|
-
const endedRef =
|
|
14938
|
-
const lastPlaybackStateRef =
|
|
14939
|
-
const onFrameChangeRef =
|
|
14940
|
-
const onPlaybackStateChangeRef =
|
|
14941
|
-
const onEndedRef =
|
|
15403
|
+
const [frameIndex, setFrameIndex] = useState19(0);
|
|
15404
|
+
const elapsedRef = useRef36(0);
|
|
15405
|
+
const frameIndexRef = useRef36(0);
|
|
15406
|
+
const endedRef = useRef36(false);
|
|
15407
|
+
const lastPlaybackStateRef = useRef36(null);
|
|
15408
|
+
const onFrameChangeRef = useRef36(onFrameChange);
|
|
15409
|
+
const onPlaybackStateChangeRef = useRef36(onPlaybackStateChange);
|
|
15410
|
+
const onEndedRef = useRef36(onEnded);
|
|
14942
15411
|
onFrameChangeRef.current = onFrameChange;
|
|
14943
15412
|
onPlaybackStateChangeRef.current = onPlaybackStateChange;
|
|
14944
15413
|
onEndedRef.current = onEnded;
|
|
14945
|
-
|
|
15414
|
+
useEffect36(() => {
|
|
14946
15415
|
elapsedRef.current = 0;
|
|
14947
15416
|
frameIndexRef.current = 0;
|
|
14948
15417
|
endedRef.current = false;
|
|
14949
15418
|
setFrameIndex(0);
|
|
14950
15419
|
}, [frameCount, frameDirection, src]);
|
|
14951
|
-
|
|
15420
|
+
useEffect36(() => {
|
|
14952
15421
|
if (!texture) {
|
|
14953
15422
|
return;
|
|
14954
15423
|
}
|
|
@@ -14962,13 +15431,13 @@ function SequenceHotspot({
|
|
|
14962
15431
|
);
|
|
14963
15432
|
texture.needsUpdate = true;
|
|
14964
15433
|
}, [frameCount, frameDirection, frameIndex, texture]);
|
|
14965
|
-
|
|
15434
|
+
useEffect36(() => {
|
|
14966
15435
|
if (!texture) {
|
|
14967
15436
|
return;
|
|
14968
15437
|
}
|
|
14969
15438
|
onFrameChangeRef.current?.({ id, index: 0, src });
|
|
14970
15439
|
}, [id, src, texture]);
|
|
14971
|
-
|
|
15440
|
+
useEffect36(() => {
|
|
14972
15441
|
if (!texture) {
|
|
14973
15442
|
return;
|
|
14974
15443
|
}
|
|
@@ -14987,7 +15456,7 @@ function SequenceHotspot({
|
|
|
14987
15456
|
onPlaybackStateChangeRef.current?.(nextState);
|
|
14988
15457
|
}
|
|
14989
15458
|
}, [playing, texture]);
|
|
14990
|
-
|
|
15459
|
+
useFrame16((_, deltaSeconds) => {
|
|
14991
15460
|
if (!texture || !playing || endedRef.current) {
|
|
14992
15461
|
return;
|
|
14993
15462
|
}
|
|
@@ -15017,12 +15486,12 @@ function SequenceHotspot({
|
|
|
15017
15486
|
onFrameChangeRef.current?.({ id, index: nextIndex, src });
|
|
15018
15487
|
}
|
|
15019
15488
|
});
|
|
15020
|
-
return /* @__PURE__ */
|
|
15489
|
+
return /* @__PURE__ */ jsx33(HotspotAnchor, { ...anchorProps, id, height, width, children: /* @__PURE__ */ jsx33(HotspotPlane, { map: texture, opacity }) });
|
|
15021
15490
|
}
|
|
15022
15491
|
|
|
15023
15492
|
// src/hotspot/video-hotspot.tsx
|
|
15024
|
-
import { useThree as
|
|
15025
|
-
import { useEffect as
|
|
15493
|
+
import { useThree as useThree25 } from "@react-three/fiber";
|
|
15494
|
+
import { useEffect as useEffect37, useRef as useRef37, useState as useState20 } from "react";
|
|
15026
15495
|
import {
|
|
15027
15496
|
ClampToEdgeWrapping as ClampToEdgeWrapping6,
|
|
15028
15497
|
LinearFilter as LinearFilter9,
|
|
@@ -15031,7 +15500,7 @@ import {
|
|
|
15031
15500
|
TextureLoader as TextureLoader7,
|
|
15032
15501
|
VideoTexture as VideoTexture2
|
|
15033
15502
|
} from "three";
|
|
15034
|
-
import { jsx as
|
|
15503
|
+
import { jsx as jsx34 } from "react/jsx-runtime";
|
|
15035
15504
|
function clampVolume2(volume) {
|
|
15036
15505
|
if (!Number.isFinite(volume)) {
|
|
15037
15506
|
return 1;
|
|
@@ -15039,11 +15508,11 @@ function clampVolume2(volume) {
|
|
|
15039
15508
|
return Math.max(0, Math.min(volume, 1));
|
|
15040
15509
|
}
|
|
15041
15510
|
function usePosterTexture2(id, poster, onError) {
|
|
15042
|
-
const gl =
|
|
15043
|
-
const [texture, setTexture] =
|
|
15044
|
-
const onErrorRef =
|
|
15511
|
+
const gl = useThree25((state) => state.gl);
|
|
15512
|
+
const [texture, setTexture] = useState20(null);
|
|
15513
|
+
const onErrorRef = useRef37(onError);
|
|
15045
15514
|
onErrorRef.current = onError;
|
|
15046
|
-
|
|
15515
|
+
useEffect37(() => {
|
|
15047
15516
|
let active = true;
|
|
15048
15517
|
setTexture(null);
|
|
15049
15518
|
if (!poster) {
|
|
@@ -15080,7 +15549,7 @@ function usePosterTexture2(id, poster, onError) {
|
|
|
15080
15549
|
active = false;
|
|
15081
15550
|
};
|
|
15082
15551
|
}, [gl, id, poster]);
|
|
15083
|
-
|
|
15552
|
+
useEffect37(
|
|
15084
15553
|
() => () => {
|
|
15085
15554
|
texture?.dispose();
|
|
15086
15555
|
},
|
|
@@ -15098,14 +15567,14 @@ function useVideoResource({
|
|
|
15098
15567
|
poster,
|
|
15099
15568
|
src
|
|
15100
15569
|
}) {
|
|
15101
|
-
const [resource, setResource] =
|
|
15102
|
-
const onEndedRef =
|
|
15103
|
-
const onErrorRef =
|
|
15104
|
-
const onPlaybackStateChangeRef =
|
|
15570
|
+
const [resource, setResource] = useState20(null);
|
|
15571
|
+
const onEndedRef = useRef37(onEnded);
|
|
15572
|
+
const onErrorRef = useRef37(onError);
|
|
15573
|
+
const onPlaybackStateChangeRef = useRef37(onPlaybackStateChange);
|
|
15105
15574
|
onEndedRef.current = onEnded;
|
|
15106
15575
|
onErrorRef.current = onError;
|
|
15107
15576
|
onPlaybackStateChangeRef.current = onPlaybackStateChange;
|
|
15108
|
-
|
|
15577
|
+
useEffect37(() => {
|
|
15109
15578
|
if (!src) {
|
|
15110
15579
|
setResource(null);
|
|
15111
15580
|
return;
|
|
@@ -15212,11 +15681,11 @@ function VideoHotspot({
|
|
|
15212
15681
|
src
|
|
15213
15682
|
});
|
|
15214
15683
|
const posterTexture = usePosterTexture2(id, poster, onError);
|
|
15215
|
-
const onPlaybackErrorRef =
|
|
15216
|
-
const onPlaybackStateChangeRef =
|
|
15684
|
+
const onPlaybackErrorRef = useRef37(onPlaybackError);
|
|
15685
|
+
const onPlaybackStateChangeRef = useRef37(onPlaybackStateChange);
|
|
15217
15686
|
onPlaybackErrorRef.current = onPlaybackError;
|
|
15218
15687
|
onPlaybackStateChangeRef.current = onPlaybackStateChange;
|
|
15219
|
-
|
|
15688
|
+
useEffect37(() => {
|
|
15220
15689
|
if (!resource) {
|
|
15221
15690
|
return;
|
|
15222
15691
|
}
|
|
@@ -15233,7 +15702,7 @@ function VideoHotspot({
|
|
|
15233
15702
|
}
|
|
15234
15703
|
resource.video.preload = preload;
|
|
15235
15704
|
}, [loop, muted, playsInline, preload, resource, volume]);
|
|
15236
|
-
|
|
15705
|
+
useEffect37(() => {
|
|
15237
15706
|
if (!resource) {
|
|
15238
15707
|
return;
|
|
15239
15708
|
}
|
|
@@ -15256,12 +15725,12 @@ function VideoHotspot({
|
|
|
15256
15725
|
};
|
|
15257
15726
|
}, [playing, resource]);
|
|
15258
15727
|
const activeTexture = resource?.ready ? resource.texture : posterTexture;
|
|
15259
|
-
return /* @__PURE__ */
|
|
15728
|
+
return /* @__PURE__ */ jsx34(HotspotAnchor, { ...anchorProps, id, height, width, children: /* @__PURE__ */ jsx34(HotspotPlane, { map: activeTexture, opacity }) });
|
|
15260
15729
|
}
|
|
15261
15730
|
|
|
15262
15731
|
// src/hotspot/audio-hotspot.tsx
|
|
15263
|
-
import { useFrame as
|
|
15264
|
-
import { useEffect as
|
|
15732
|
+
import { useFrame as useFrame17, useThree as useThree26 } from "@react-three/fiber";
|
|
15733
|
+
import { useEffect as useEffect38, useRef as useRef38, useState as useState21 } from "react";
|
|
15265
15734
|
import {
|
|
15266
15735
|
CanvasTexture as CanvasTexture2,
|
|
15267
15736
|
ClampToEdgeWrapping as ClampToEdgeWrapping7,
|
|
@@ -15270,7 +15739,7 @@ import {
|
|
|
15270
15739
|
SRGBColorSpace as SRGBColorSpace9,
|
|
15271
15740
|
TextureLoader as TextureLoader8
|
|
15272
15741
|
} from "three";
|
|
15273
|
-
import { jsx as
|
|
15742
|
+
import { jsx as jsx35 } from "react/jsx-runtime";
|
|
15274
15743
|
var SPEAKER_TEXTURE_SIZE = 512;
|
|
15275
15744
|
function paintSpeakerBody(context, center) {
|
|
15276
15745
|
context.fillStyle = "#f5fbfc";
|
|
@@ -15334,8 +15803,8 @@ function createSpeakerTexture(state) {
|
|
|
15334
15803
|
return texture;
|
|
15335
15804
|
}
|
|
15336
15805
|
function useSpeakerTextures(enabled) {
|
|
15337
|
-
const [textures, setTextures] =
|
|
15338
|
-
|
|
15806
|
+
const [textures, setTextures] = useState21({ playing: null, stopped: null });
|
|
15807
|
+
useEffect38(() => {
|
|
15339
15808
|
if (!enabled) {
|
|
15340
15809
|
setTextures({ playing: null, stopped: null });
|
|
15341
15810
|
return;
|
|
@@ -15351,11 +15820,11 @@ function useSpeakerTextures(enabled) {
|
|
|
15351
15820
|
return textures;
|
|
15352
15821
|
}
|
|
15353
15822
|
function useIconTexture(icon, enabled, onError, id) {
|
|
15354
|
-
const gl =
|
|
15355
|
-
const [texture, setTexture] =
|
|
15356
|
-
const onErrorRef =
|
|
15823
|
+
const gl = useThree26((state) => state.gl);
|
|
15824
|
+
const [texture, setTexture] = useState21(null);
|
|
15825
|
+
const onErrorRef = useRef38(onError);
|
|
15357
15826
|
onErrorRef.current = onError;
|
|
15358
|
-
|
|
15827
|
+
useEffect38(() => {
|
|
15359
15828
|
let active = true;
|
|
15360
15829
|
setTexture(null);
|
|
15361
15830
|
if (!enabled || !icon) {
|
|
@@ -15392,7 +15861,7 @@ function useIconTexture(icon, enabled, onError, id) {
|
|
|
15392
15861
|
active = false;
|
|
15393
15862
|
};
|
|
15394
15863
|
}, [enabled, gl, icon, id]);
|
|
15395
|
-
|
|
15864
|
+
useEffect38(
|
|
15396
15865
|
() => () => {
|
|
15397
15866
|
texture?.dispose();
|
|
15398
15867
|
},
|
|
@@ -15411,13 +15880,13 @@ function useAudioHowl({
|
|
|
15411
15880
|
playing,
|
|
15412
15881
|
src
|
|
15413
15882
|
}) {
|
|
15414
|
-
const [howl, setHowl] =
|
|
15415
|
-
const playingRef =
|
|
15416
|
-
const loopRef =
|
|
15417
|
-
const onEndedRef =
|
|
15418
|
-
const onErrorRef =
|
|
15419
|
-
const onPlaybackErrorRef =
|
|
15420
|
-
const onPlaybackStateChangeRef =
|
|
15883
|
+
const [howl, setHowl] = useState21(null);
|
|
15884
|
+
const playingRef = useRef38(playing);
|
|
15885
|
+
const loopRef = useRef38(loop ?? false);
|
|
15886
|
+
const onEndedRef = useRef38(onEnded);
|
|
15887
|
+
const onErrorRef = useRef38(onError);
|
|
15888
|
+
const onPlaybackErrorRef = useRef38(onPlaybackError);
|
|
15889
|
+
const onPlaybackStateChangeRef = useRef38(onPlaybackStateChange);
|
|
15421
15890
|
playingRef.current = playing;
|
|
15422
15891
|
loopRef.current = loop ?? false;
|
|
15423
15892
|
onEndedRef.current = onEnded;
|
|
@@ -15425,7 +15894,7 @@ function useAudioHowl({
|
|
|
15425
15894
|
onPlaybackErrorRef.current = onPlaybackError;
|
|
15426
15895
|
onPlaybackStateChangeRef.current = onPlaybackStateChange;
|
|
15427
15896
|
const sourcesKey = sourceList(src).join("\0");
|
|
15428
|
-
|
|
15897
|
+
useEffect38(() => {
|
|
15429
15898
|
const sources = sourcesKey.length > 0 ? sourcesKey.split("\0") : [];
|
|
15430
15899
|
if (sources.length === 0) {
|
|
15431
15900
|
setHowl(null);
|
|
@@ -15462,7 +15931,7 @@ function useAudioHowl({
|
|
|
15462
15931
|
handle.dispose();
|
|
15463
15932
|
};
|
|
15464
15933
|
}, [crossOrigin, id, sourcesKey]);
|
|
15465
|
-
|
|
15934
|
+
useEffect38(() => {
|
|
15466
15935
|
howl?.loop(loop ?? false);
|
|
15467
15936
|
}, [howl, loop]);
|
|
15468
15937
|
return howl;
|
|
@@ -15490,7 +15959,7 @@ function AudioHotspot({
|
|
|
15490
15959
|
...anchorProps
|
|
15491
15960
|
}) {
|
|
15492
15961
|
usePanoMediaActivationIntent(playing);
|
|
15493
|
-
const camera =
|
|
15962
|
+
const camera = useThree26((state) => state.camera);
|
|
15494
15963
|
const howl = useAudioHowl({
|
|
15495
15964
|
crossOrigin,
|
|
15496
15965
|
id,
|
|
@@ -15506,15 +15975,15 @@ function AudioHotspot({
|
|
|
15506
15975
|
const stoppedIconTexture = useIconTexture(icon, marker, onError, id);
|
|
15507
15976
|
const playingIconTexture = useIconTexture(playingIcon, marker, onError, id);
|
|
15508
15977
|
const markerTexture = playing ? playingIconTexture ?? stoppedIconTexture ?? speakerTextures.playing : stoppedIconTexture ?? speakerTextures.stopped;
|
|
15509
|
-
const playingRef =
|
|
15978
|
+
const playingRef = useRef38(playing);
|
|
15510
15979
|
playingRef.current = playing;
|
|
15511
|
-
const mutedRef =
|
|
15512
|
-
const volumeRef =
|
|
15513
|
-
const rangeRef =
|
|
15980
|
+
const mutedRef = useRef38(muted);
|
|
15981
|
+
const volumeRef = useRef38(volume);
|
|
15982
|
+
const rangeRef = useRef38(range);
|
|
15514
15983
|
mutedRef.current = muted;
|
|
15515
15984
|
volumeRef.current = volume;
|
|
15516
15985
|
rangeRef.current = range;
|
|
15517
|
-
|
|
15986
|
+
useEffect38(() => {
|
|
15518
15987
|
if (!howl) {
|
|
15519
15988
|
return;
|
|
15520
15989
|
}
|
|
@@ -15524,7 +15993,7 @@ function AudioHotspot({
|
|
|
15524
15993
|
}
|
|
15525
15994
|
howl.play();
|
|
15526
15995
|
}, [howl, playing]);
|
|
15527
|
-
|
|
15996
|
+
useEffect38(() => {
|
|
15528
15997
|
if (!howl || !pauseWhenHidden) {
|
|
15529
15998
|
return;
|
|
15530
15999
|
}
|
|
@@ -15542,7 +16011,7 @@ function AudioHotspot({
|
|
|
15542
16011
|
document.removeEventListener("visibilitychange", handleVisibility);
|
|
15543
16012
|
};
|
|
15544
16013
|
}, [howl, pauseWhenHidden]);
|
|
15545
|
-
|
|
16014
|
+
useFrame17(() => {
|
|
15546
16015
|
if (!howl) {
|
|
15547
16016
|
return;
|
|
15548
16017
|
}
|
|
@@ -15555,11 +16024,11 @@ function AudioHotspot({
|
|
|
15555
16024
|
howl.mute(mutedRef.current);
|
|
15556
16025
|
howl.volume(clampAudioVolume(volumeRef.current) * spatial.gain);
|
|
15557
16026
|
});
|
|
15558
|
-
return /* @__PURE__ */
|
|
16027
|
+
return /* @__PURE__ */ jsx35(HotspotAnchor, { ...anchorProps, id, height, width, children: marker ? /* @__PURE__ */ jsx35(HotspotPlane, { map: markerTexture, opacity }) : null });
|
|
15559
16028
|
}
|
|
15560
16029
|
|
|
15561
16030
|
// src/hotspot/text-hotspot.tsx
|
|
15562
|
-
import { useEffect as
|
|
16031
|
+
import { useEffect as useEffect39, useRef as useRef39, useState as useState22 } from "react";
|
|
15563
16032
|
import {
|
|
15564
16033
|
CanvasTexture as CanvasTexture3,
|
|
15565
16034
|
ClampToEdgeWrapping as ClampToEdgeWrapping8,
|
|
@@ -15567,7 +16036,7 @@ import {
|
|
|
15567
16036
|
LinearMipmapLinearFilter as LinearMipmapLinearFilter8,
|
|
15568
16037
|
SRGBColorSpace as SRGBColorSpace10
|
|
15569
16038
|
} from "three";
|
|
15570
|
-
import { jsx as
|
|
16039
|
+
import { jsx as jsx36 } from "react/jsx-runtime";
|
|
15571
16040
|
var TEXT_TEXTURE_LONG_SIDE = 1024;
|
|
15572
16041
|
var DEFAULT_FONT_FAMILY = "system-ui, sans-serif";
|
|
15573
16042
|
var DEFAULT_FONT_SIZE = 96;
|
|
@@ -15787,12 +16256,12 @@ function createTextTexture(text, width, height, style) {
|
|
|
15787
16256
|
return texture;
|
|
15788
16257
|
}
|
|
15789
16258
|
function useTextTexture(text, width, height, style, onLoad, onError) {
|
|
15790
|
-
const [texture, setTexture] =
|
|
15791
|
-
const onLoadRef =
|
|
15792
|
-
const onErrorRef =
|
|
16259
|
+
const [texture, setTexture] = useState22(null);
|
|
16260
|
+
const onLoadRef = useRef39(onLoad);
|
|
16261
|
+
const onErrorRef = useRef39(onError);
|
|
15793
16262
|
onLoadRef.current = onLoad;
|
|
15794
16263
|
onErrorRef.current = onError;
|
|
15795
|
-
|
|
16264
|
+
useEffect39(() => {
|
|
15796
16265
|
let cancelled = false;
|
|
15797
16266
|
let nextTexture = null;
|
|
15798
16267
|
const run = async () => {
|
|
@@ -15885,13 +16354,13 @@ function TextHotspot({
|
|
|
15885
16354
|
whiteSpace
|
|
15886
16355
|
};
|
|
15887
16356
|
const texture = useTextTexture(text, width, height, style, onLoad, onError);
|
|
15888
|
-
return /* @__PURE__ */
|
|
16357
|
+
return /* @__PURE__ */ jsx36(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ jsx36(HotspotPlane, { map: texture, opacity }) });
|
|
15889
16358
|
}
|
|
15890
16359
|
|
|
15891
16360
|
// src/hotspot/iframe-hotspot.tsx
|
|
15892
16361
|
import { Html as Html2 } from "@react-three/drei";
|
|
15893
16362
|
import { DoubleSide as DoubleSide6 } from "three";
|
|
15894
|
-
import { jsx as
|
|
16363
|
+
import { jsx as jsx37, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
15895
16364
|
var IFRAME_LONG_SIDE = 800;
|
|
15896
16365
|
var CSS3D_DISTANCE_FACTOR = 400;
|
|
15897
16366
|
var DEFAULT_SANDBOX = "allow-scripts allow-popups allow-forms";
|
|
@@ -15948,7 +16417,7 @@ function IframeHotspot({
|
|
|
15948
16417
|
interactive,
|
|
15949
16418
|
pointerEvents
|
|
15950
16419
|
);
|
|
15951
|
-
return /* @__PURE__ */
|
|
16420
|
+
return /* @__PURE__ */ jsxs20(
|
|
15952
16421
|
HotspotAnchor,
|
|
15953
16422
|
{
|
|
15954
16423
|
...anchorProps,
|
|
@@ -15957,9 +16426,9 @@ function IframeHotspot({
|
|
|
15957
16426
|
pointerEvents,
|
|
15958
16427
|
width,
|
|
15959
16428
|
children: [
|
|
15960
|
-
/* @__PURE__ */
|
|
15961
|
-
/* @__PURE__ */
|
|
15962
|
-
/* @__PURE__ */
|
|
16429
|
+
/* @__PURE__ */ jsxs20("mesh", { children: [
|
|
16430
|
+
/* @__PURE__ */ jsx37("planeGeometry", { args: [1, 1] }),
|
|
16431
|
+
/* @__PURE__ */ jsx37(
|
|
15963
16432
|
"meshBasicMaterial",
|
|
15964
16433
|
{
|
|
15965
16434
|
depthWrite: false,
|
|
@@ -15970,7 +16439,7 @@ function IframeHotspot({
|
|
|
15970
16439
|
}
|
|
15971
16440
|
)
|
|
15972
16441
|
] }),
|
|
15973
|
-
/* @__PURE__ */
|
|
16442
|
+
/* @__PURE__ */ jsx37(
|
|
15974
16443
|
Html2,
|
|
15975
16444
|
{
|
|
15976
16445
|
distanceFactor: CSS3D_DISTANCE_FACTOR,
|
|
@@ -15985,7 +16454,7 @@ function IframeHotspot({
|
|
|
15985
16454
|
},
|
|
15986
16455
|
transform: true,
|
|
15987
16456
|
zIndexRange: [10, 0],
|
|
15988
|
-
children: /* @__PURE__ */
|
|
16457
|
+
children: /* @__PURE__ */ jsx37(
|
|
15989
16458
|
"iframe",
|
|
15990
16459
|
{
|
|
15991
16460
|
allow,
|
|
@@ -16037,6 +16506,7 @@ export {
|
|
|
16037
16506
|
Scenes,
|
|
16038
16507
|
SequenceHotspot,
|
|
16039
16508
|
Sphere,
|
|
16509
|
+
SphereTile,
|
|
16040
16510
|
TextHotspot,
|
|
16041
16511
|
Tile,
|
|
16042
16512
|
TouchControls,
|