@ericchen1990/pano-view 3.1.3 → 3.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -4
- package/README.zh-CN.md +55 -4
- package/dist/index.cjs +1413 -984
- 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 +1474 -1042
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -4
package/dist/index.mjs
CHANGED
|
@@ -3745,7 +3745,9 @@ var DEFAULT_PANO_FILTER_INTENSITY = 1;
|
|
|
3745
3745
|
var DEFAULT_PANO_FILTER_SNAPSHOT = {
|
|
3746
3746
|
preset: "none",
|
|
3747
3747
|
intensity: DEFAULT_PANO_FILTER_INTENSITY,
|
|
3748
|
-
enabled: true
|
|
3748
|
+
enabled: true,
|
|
3749
|
+
colorMatrix: null,
|
|
3750
|
+
colorMatrixScope: "panorama"
|
|
3749
3751
|
};
|
|
3750
3752
|
function clampPanoFilterIntensity(value) {
|
|
3751
3753
|
if (!Number.isFinite(value)) {
|
|
@@ -3754,15 +3756,17 @@ function clampPanoFilterIntensity(value) {
|
|
|
3754
3756
|
return Math.max(0, Math.min(value, 1));
|
|
3755
3757
|
}
|
|
3756
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
|
+
}
|
|
3757
3762
|
return {
|
|
3763
|
+
colorMatrix: input.colorMatrix ? [...input.colorMatrix] : null,
|
|
3764
|
+
colorMatrixScope: input.colorMatrixScope ?? "panorama",
|
|
3758
3765
|
preset: input.preset ?? "none",
|
|
3759
3766
|
intensity: clampPanoFilterIntensity(input.intensity),
|
|
3760
3767
|
enabled: input.enabled !== false
|
|
3761
3768
|
};
|
|
3762
3769
|
}
|
|
3763
|
-
function isPanoFilterActive(snapshot) {
|
|
3764
|
-
return snapshot.enabled && snapshot.preset !== "none";
|
|
3765
|
-
}
|
|
3766
3770
|
|
|
3767
3771
|
// src/pano-filter/host.ts
|
|
3768
3772
|
var PanoFilterHostContext = createContext7(null);
|
|
@@ -8040,15 +8044,23 @@ import { useContext as useContext17, useEffect as useEffect15, useMemo as useMem
|
|
|
8040
8044
|
function PanoFilter({
|
|
8041
8045
|
preset = "none",
|
|
8042
8046
|
intensity,
|
|
8043
|
-
enabled = true
|
|
8047
|
+
enabled = true,
|
|
8048
|
+
colorMatrix,
|
|
8049
|
+
colorMatrixScope
|
|
8044
8050
|
}) {
|
|
8045
8051
|
const host = useContext17(PanoFilterHostContext);
|
|
8046
8052
|
if (!host) {
|
|
8047
8053
|
throw new Error("<PanoFilter> must be rendered inside <PanoViewer>.");
|
|
8048
8054
|
}
|
|
8049
8055
|
const snapshot = useMemo9(
|
|
8050
|
-
() => resolvePanoFilterSnapshot({
|
|
8051
|
-
|
|
8056
|
+
() => resolvePanoFilterSnapshot({
|
|
8057
|
+
preset,
|
|
8058
|
+
intensity,
|
|
8059
|
+
enabled,
|
|
8060
|
+
colorMatrix,
|
|
8061
|
+
colorMatrixScope
|
|
8062
|
+
}),
|
|
8063
|
+
[enabled, intensity, preset, colorMatrix, colorMatrixScope]
|
|
8052
8064
|
);
|
|
8053
8065
|
useEffect15(() => {
|
|
8054
8066
|
claimPanoFilter(host);
|
|
@@ -9702,18 +9714,10 @@ function usePanoViewer() {
|
|
|
9702
9714
|
return useMemo12(() => ({ ref, ...handle }), [handle]);
|
|
9703
9715
|
}
|
|
9704
9716
|
|
|
9705
|
-
// src/sphere.tsx
|
|
9706
|
-
import { useThree as useThree13 } from "@react-three/fiber";
|
|
9707
|
-
import { useEffect as
|
|
9708
|
-
import {
|
|
9709
|
-
BackSide as BackSide2,
|
|
9710
|
-
LinearFilter,
|
|
9711
|
-
LinearMipmapLinearFilter,
|
|
9712
|
-
MathUtils as MathUtils5,
|
|
9713
|
-
RepeatWrapping,
|
|
9714
|
-
SRGBColorSpace,
|
|
9715
|
-
TextureLoader
|
|
9716
|
-
} 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";
|
|
9717
9721
|
|
|
9718
9722
|
// src/asset-url.ts
|
|
9719
9723
|
function isAbsoluteAssetUrl(url) {
|
|
@@ -9738,6 +9742,10 @@ function resolveUrlAgainstFile(fileUrl, path) {
|
|
|
9738
9742
|
|
|
9739
9743
|
// src/pano-filter/pano-basic-material.tsx
|
|
9740
9744
|
import { useLayoutEffect as useLayoutEffect2, useMemo as useMemo13, useRef as useRef21 } from "react";
|
|
9745
|
+
import {
|
|
9746
|
+
Matrix4,
|
|
9747
|
+
Vector4 as Vector42
|
|
9748
|
+
} from "three";
|
|
9741
9749
|
|
|
9742
9750
|
// src/pano-filter/shaders.ts
|
|
9743
9751
|
var GLSL_FILTER_COMMON = `
|
|
@@ -9886,264 +9894,996 @@ ${applyPanoFilterFunction(panoFilterBody(preset))}`
|
|
|
9886
9894
|
diffuseColor.rgb = mix(diffuseColor.rgb, applyPanoFilter(diffuseColor.rgb), clamp(uPanoFilterIntensity, 0.0, 1.0));`
|
|
9887
9895
|
);
|
|
9888
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
|
+
}
|
|
9889
9910
|
|
|
9890
9911
|
// src/pano-filter/pano-basic-material.tsx
|
|
9891
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
|
+
}
|
|
9892
9936
|
function PanoBasicMaterial({
|
|
9893
|
-
|
|
9894
|
-
|
|
9895
|
-
depthTest,
|
|
9896
|
-
depthWrite,
|
|
9897
|
-
toneMapped = false
|
|
9937
|
+
target = "panorama",
|
|
9938
|
+
...props
|
|
9898
9939
|
}) {
|
|
9899
9940
|
const snapshot = usePanoFilterSnapshot();
|
|
9900
|
-
const
|
|
9901
|
-
const
|
|
9902
|
-
const
|
|
9903
|
-
|
|
9904
|
-
|
|
9905
|
-
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);
|
|
9906
9947
|
const onBeforeCompile = useMemo13(() => {
|
|
9907
|
-
if (!active || preset === "none") {
|
|
9908
|
-
return void 0;
|
|
9909
|
-
}
|
|
9910
9948
|
const compile = (shader) => {
|
|
9911
|
-
|
|
9912
|
-
|
|
9913
|
-
|
|
9914
|
-
|
|
9915
|
-
|
|
9916
|
-
if (
|
|
9917
|
-
|
|
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
|
+
};
|
|
9918
9962
|
}
|
|
9919
9963
|
};
|
|
9920
|
-
compile.toString = () => `pano-filter:${preset}`;
|
|
9964
|
+
compile.toString = () => `pano-filter:${preset}:matrix:${hasMatrix}`;
|
|
9921
9965
|
return compile;
|
|
9922
|
-
}, [
|
|
9923
|
-
useLayoutEffect2(() => {
|
|
9924
|
-
if (!active) {
|
|
9925
|
-
intensityUniformRef.current = null;
|
|
9926
|
-
}
|
|
9927
|
-
const material = materialRef.current;
|
|
9928
|
-
if (!material) {
|
|
9929
|
-
return;
|
|
9930
|
-
}
|
|
9931
|
-
material.needsUpdate = true;
|
|
9932
|
-
}, [active, preset]);
|
|
9966
|
+
}, [preset, hasMatrix]);
|
|
9933
9967
|
useLayoutEffect2(() => {
|
|
9934
|
-
|
|
9935
|
-
|
|
9936
|
-
|
|
9937
|
-
|
|
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]);
|
|
9938
9979
|
return /* @__PURE__ */ jsx14(
|
|
9939
9980
|
"meshBasicMaterial",
|
|
9940
9981
|
{
|
|
9941
|
-
|
|
9942
|
-
|
|
9943
|
-
|
|
9944
|
-
map,
|
|
9945
|
-
onBeforeCompile,
|
|
9946
|
-
side,
|
|
9947
|
-
toneMapped
|
|
9948
|
-
},
|
|
9949
|
-
active ? preset : "none"
|
|
9950
|
-
);
|
|
9951
|
-
}
|
|
9952
|
-
|
|
9953
|
-
// src/sphere.tsx
|
|
9954
|
-
import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
9955
|
-
function useEquirectTexture(url, anisotropy, generateMipmaps, onLoad, onError) {
|
|
9956
|
-
const [texture, setTexture] = useState9(null);
|
|
9957
|
-
const onLoadRef = useRef22(onLoad);
|
|
9958
|
-
const onErrorRef = useRef22(onError);
|
|
9959
|
-
onLoadRef.current = onLoad;
|
|
9960
|
-
onErrorRef.current = onError;
|
|
9961
|
-
useEffect21(() => {
|
|
9962
|
-
if (!url) {
|
|
9963
|
-
setTexture(null);
|
|
9964
|
-
return;
|
|
9965
|
-
}
|
|
9966
|
-
let active = true;
|
|
9967
|
-
const loader = new TextureLoader();
|
|
9968
|
-
setTexture(null);
|
|
9969
|
-
loader.load(
|
|
9970
|
-
url,
|
|
9971
|
-
(loadedTexture) => {
|
|
9972
|
-
if (!active) {
|
|
9973
|
-
loadedTexture.dispose();
|
|
9974
|
-
return;
|
|
9975
|
-
}
|
|
9976
|
-
loadedTexture.colorSpace = SRGBColorSpace;
|
|
9977
|
-
loadedTexture.wrapS = RepeatWrapping;
|
|
9978
|
-
loadedTexture.repeat.x = -1;
|
|
9979
|
-
loadedTexture.offset.x = 1;
|
|
9980
|
-
loadedTexture.anisotropy = anisotropy;
|
|
9981
|
-
loadedTexture.magFilter = LinearFilter;
|
|
9982
|
-
loadedTexture.minFilter = generateMipmaps ? LinearMipmapLinearFilter : LinearFilter;
|
|
9983
|
-
loadedTexture.generateMipmaps = generateMipmaps;
|
|
9984
|
-
loadedTexture.needsUpdate = true;
|
|
9985
|
-
setTexture(loadedTexture);
|
|
9986
|
-
onLoadRef.current?.(loadedTexture);
|
|
9987
|
-
},
|
|
9988
|
-
void 0,
|
|
9989
|
-
(error) => {
|
|
9990
|
-
if (active) {
|
|
9991
|
-
setTexture(null);
|
|
9992
|
-
onErrorRef.current?.(error);
|
|
9993
|
-
}
|
|
9994
|
-
}
|
|
9995
|
-
);
|
|
9996
|
-
return () => {
|
|
9997
|
-
active = false;
|
|
9998
|
-
};
|
|
9999
|
-
}, [anisotropy, generateMipmaps, url]);
|
|
10000
|
-
useEffect21(
|
|
10001
|
-
() => () => {
|
|
10002
|
-
texture?.dispose();
|
|
9982
|
+
toneMapped: false,
|
|
9983
|
+
...props,
|
|
9984
|
+
onBeforeCompile
|
|
10003
9985
|
},
|
|
10004
|
-
|
|
10005
|
-
);
|
|
10006
|
-
return texture;
|
|
10007
|
-
}
|
|
10008
|
-
function Sphere({
|
|
10009
|
-
src,
|
|
10010
|
-
previewUrl,
|
|
10011
|
-
yawOffset = 0,
|
|
10012
|
-
onReady,
|
|
10013
|
-
onLoad,
|
|
10014
|
-
onError,
|
|
10015
|
-
onPreviewError,
|
|
10016
|
-
visible = true
|
|
10017
|
-
}) {
|
|
10018
|
-
const gl = useThree13((state) => state.gl);
|
|
10019
|
-
const anisotropy = gl.capabilities.getMaxAnisotropy();
|
|
10020
|
-
const resolvedPreviewUrl = useMemo14(
|
|
10021
|
-
() => resolveUrlAgainstFile(src, previewUrl),
|
|
10022
|
-
[previewUrl, src]
|
|
10023
|
-
);
|
|
10024
|
-
const texture = useEquirectTexture(
|
|
10025
|
-
src,
|
|
10026
|
-
anisotropy,
|
|
10027
|
-
true,
|
|
10028
|
-
onLoad,
|
|
10029
|
-
onError
|
|
10030
|
-
);
|
|
10031
|
-
const previewTexture = useEquirectTexture(
|
|
10032
|
-
texture ? null : resolvedPreviewUrl,
|
|
10033
|
-
anisotropy,
|
|
10034
|
-
false,
|
|
10035
|
-
void 0,
|
|
10036
|
-
onPreviewError
|
|
10037
|
-
);
|
|
10038
|
-
const displayTexture = texture ?? previewTexture;
|
|
10039
|
-
const readyRef = useRef22(false);
|
|
10040
|
-
useEffect21(() => {
|
|
10041
|
-
readyRef.current = false;
|
|
10042
|
-
}, [resolvedPreviewUrl, src]);
|
|
10043
|
-
useEffect21(() => {
|
|
10044
|
-
if (!displayTexture || readyRef.current) {
|
|
10045
|
-
return;
|
|
10046
|
-
}
|
|
10047
|
-
readyRef.current = true;
|
|
10048
|
-
onReady?.();
|
|
10049
|
-
}, [displayTexture, onReady]);
|
|
10050
|
-
if (!displayTexture) {
|
|
10051
|
-
return null;
|
|
10052
|
-
}
|
|
10053
|
-
return /* @__PURE__ */ jsxs9(
|
|
10054
|
-
"mesh",
|
|
10055
|
-
{
|
|
10056
|
-
rotation: [0, MathUtils5.degToRad(90 + yawOffset), 0],
|
|
10057
|
-
visible,
|
|
10058
|
-
children: [
|
|
10059
|
-
/* @__PURE__ */ jsx15("sphereGeometry", { args: [DEFAULT_PANORAMA_RADIUS, 128, 64] }),
|
|
10060
|
-
/* @__PURE__ */ jsx15(
|
|
10061
|
-
PanoBasicMaterial,
|
|
10062
|
-
{
|
|
10063
|
-
map: displayTexture,
|
|
10064
|
-
side: BackSide2,
|
|
10065
|
-
toneMapped: false
|
|
10066
|
-
}
|
|
10067
|
-
)
|
|
10068
|
-
]
|
|
10069
|
-
}
|
|
9986
|
+
`${preset}:${hasMatrix}`
|
|
10070
9987
|
);
|
|
10071
9988
|
}
|
|
10072
9989
|
|
|
10073
|
-
// src/
|
|
10074
|
-
import { useThree as useThree14 } from "@react-three/fiber";
|
|
10075
|
-
import {
|
|
10076
|
-
useCallback as useCallback9,
|
|
10077
|
-
useContext as useContext21,
|
|
10078
|
-
useEffect as useEffect22,
|
|
10079
|
-
useLayoutEffect as useLayoutEffect3,
|
|
10080
|
-
useMemo as useMemo15,
|
|
10081
|
-
useRef as useRef23,
|
|
10082
|
-
useState as useState10
|
|
10083
|
-
} from "react";
|
|
9990
|
+
// src/tile/texture-manager.ts
|
|
10084
9991
|
import {
|
|
10085
|
-
|
|
10086
|
-
LinearFilter
|
|
10087
|
-
|
|
10088
|
-
|
|
10089
|
-
RepeatWrapping as RepeatWrapping2,
|
|
10090
|
-
SRGBColorSpace as SRGBColorSpace2,
|
|
10091
|
-
TextureLoader as TextureLoader2,
|
|
10092
|
-
VideoTexture
|
|
9992
|
+
ClampToEdgeWrapping,
|
|
9993
|
+
LinearFilter,
|
|
9994
|
+
SRGBColorSpace,
|
|
9995
|
+
TextureLoader
|
|
10093
9996
|
} from "three";
|
|
10094
|
-
|
|
10095
|
-
|
|
10096
|
-
|
|
10097
|
-
|
|
10098
|
-
|
|
10099
|
-
|
|
10100
|
-
|
|
10101
|
-
|
|
10102
|
-
|
|
10103
|
-
|
|
10104
|
-
|
|
10105
|
-
|
|
10106
|
-
|
|
10107
|
-
|
|
10108
|
-
|
|
10109
|
-
|
|
10110
|
-
|
|
10111
|
-
|
|
10112
|
-
tracks: [],
|
|
10113
|
-
captionText: "",
|
|
10114
|
-
captionAppearance: DEFAULT_PANO_VIDEO_CAPTION_APPEARANCE,
|
|
10115
|
-
captionsEnabled: true,
|
|
10116
|
-
playbackRates: EMPTY_RATES,
|
|
10117
|
-
playbackState: "paused"
|
|
10118
|
-
};
|
|
10119
|
-
}
|
|
10120
|
-
function playbackStateFromVideo(video, blocked) {
|
|
10121
|
-
if (blocked) {
|
|
10122
|
-
return "blocked";
|
|
10123
|
-
}
|
|
10124
|
-
if (video.ended) {
|
|
10125
|
-
return "ended";
|
|
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;
|
|
10126
10015
|
}
|
|
10127
|
-
|
|
10128
|
-
|
|
10016
|
+
resume() {
|
|
10017
|
+
this.disposed = false;
|
|
10018
|
+
this.drain();
|
|
10129
10019
|
}
|
|
10130
|
-
|
|
10131
|
-
|
|
10132
|
-
|
|
10133
|
-
if (!track?.activeCues || track.activeCues.length === 0) {
|
|
10134
|
-
return "";
|
|
10020
|
+
getSnapshot(key) {
|
|
10021
|
+
const entry = this.entries.get(key);
|
|
10022
|
+
return entry ? this.snapshot(entry) : EMPTY_TEXTURE_SNAPSHOT;
|
|
10135
10023
|
}
|
|
10136
|
-
|
|
10137
|
-
|
|
10138
|
-
|
|
10139
|
-
|
|
10140
|
-
|
|
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);
|
|
10141
10040
|
}
|
|
10142
|
-
|
|
10143
|
-
|
|
10144
|
-
|
|
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();
|
|
10145
10051
|
}
|
|
10146
|
-
|
|
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);
|
|
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;
|
|
10067
|
+
}
|
|
10068
|
+
this.evict();
|
|
10069
|
+
};
|
|
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();
|
|
10078
|
+
}
|
|
10079
|
+
this.entries.clear();
|
|
10080
|
+
this.totalBytes = 0;
|
|
10081
|
+
}
|
|
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);
|
|
10095
|
+
}
|
|
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;
|
|
10294
|
+
}
|
|
10295
|
+
|
|
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
|
|
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";
|
|
10815
|
+
import {
|
|
10816
|
+
useCallback as useCallback10,
|
|
10817
|
+
useContext as useContext21,
|
|
10818
|
+
useEffect as useEffect24,
|
|
10819
|
+
useLayoutEffect as useLayoutEffect3,
|
|
10820
|
+
useMemo as useMemo16,
|
|
10821
|
+
useRef as useRef25,
|
|
10822
|
+
useState as useState12
|
|
10823
|
+
} from "react";
|
|
10824
|
+
import {
|
|
10825
|
+
BackSide as BackSide4,
|
|
10826
|
+
LinearFilter as LinearFilter4,
|
|
10827
|
+
LinearMipmapLinearFilter as LinearMipmapLinearFilter2,
|
|
10828
|
+
MathUtils as MathUtils7,
|
|
10829
|
+
RepeatWrapping as RepeatWrapping2,
|
|
10830
|
+
SRGBColorSpace as SRGBColorSpace4,
|
|
10831
|
+
TextureLoader as TextureLoader4,
|
|
10832
|
+
VideoTexture
|
|
10833
|
+
} from "three";
|
|
10834
|
+
import { Fragment as Fragment5, jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
10835
|
+
var EMPTY_TRACKS = [];
|
|
10836
|
+
var EMPTY_RATES = DEFAULT_PANO_VIDEO_PLAYBACK_RATES;
|
|
10837
|
+
function createEmptySnapshot() {
|
|
10838
|
+
return {
|
|
10839
|
+
ready: false,
|
|
10840
|
+
playing: false,
|
|
10841
|
+
blocked: false,
|
|
10842
|
+
ended: false,
|
|
10843
|
+
currentTime: 0,
|
|
10844
|
+
duration: 0,
|
|
10845
|
+
volume: 1,
|
|
10846
|
+
volumeAdjustable: true,
|
|
10847
|
+
muted: true,
|
|
10848
|
+
playbackRate: 1,
|
|
10849
|
+
variantId: "default",
|
|
10850
|
+
variants: [],
|
|
10851
|
+
trackId: null,
|
|
10852
|
+
tracks: [],
|
|
10853
|
+
captionText: "",
|
|
10854
|
+
captionAppearance: DEFAULT_PANO_VIDEO_CAPTION_APPEARANCE,
|
|
10855
|
+
captionsEnabled: true,
|
|
10856
|
+
playbackRates: EMPTY_RATES,
|
|
10857
|
+
playbackState: "paused"
|
|
10858
|
+
};
|
|
10859
|
+
}
|
|
10860
|
+
function playbackStateFromVideo(video, blocked) {
|
|
10861
|
+
if (blocked) {
|
|
10862
|
+
return "blocked";
|
|
10863
|
+
}
|
|
10864
|
+
if (video.ended) {
|
|
10865
|
+
return "ended";
|
|
10866
|
+
}
|
|
10867
|
+
if (!video.paused) {
|
|
10868
|
+
return "playing";
|
|
10869
|
+
}
|
|
10870
|
+
return "paused";
|
|
10871
|
+
}
|
|
10872
|
+
function collectCaptionText(track) {
|
|
10873
|
+
if (!track?.activeCues || track.activeCues.length === 0) {
|
|
10874
|
+
return "";
|
|
10875
|
+
}
|
|
10876
|
+
const parts = [];
|
|
10877
|
+
for (let index = 0; index < track.activeCues.length; index += 1) {
|
|
10878
|
+
const cue = track.activeCues[index];
|
|
10879
|
+
if (!cue) {
|
|
10880
|
+
continue;
|
|
10881
|
+
}
|
|
10882
|
+
const text = cueText(cue);
|
|
10883
|
+
if (text) {
|
|
10884
|
+
parts.push(text);
|
|
10885
|
+
}
|
|
10886
|
+
}
|
|
10147
10887
|
return parts.join("\n");
|
|
10148
10888
|
}
|
|
10149
10889
|
function findTextTrack(video, tracks, trackId) {
|
|
@@ -10167,7 +10907,7 @@ function findTextTrack(video, tracks, trackId) {
|
|
|
10167
10907
|
return list.length > 0 ? list[0] : null;
|
|
10168
10908
|
}
|
|
10169
10909
|
function applyEquirectangularLayout(texture, anisotropy) {
|
|
10170
|
-
texture.colorSpace =
|
|
10910
|
+
texture.colorSpace = SRGBColorSpace4;
|
|
10171
10911
|
texture.wrapS = RepeatWrapping2;
|
|
10172
10912
|
texture.repeat.x = -1;
|
|
10173
10913
|
texture.offset.x = 1;
|
|
@@ -10175,11 +10915,11 @@ function applyEquirectangularLayout(texture, anisotropy) {
|
|
|
10175
10915
|
texture.needsUpdate = true;
|
|
10176
10916
|
}
|
|
10177
10917
|
function usePosterTexture(poster, onError) {
|
|
10178
|
-
const gl =
|
|
10179
|
-
const [texture, setTexture] =
|
|
10180
|
-
const onErrorRef =
|
|
10918
|
+
const gl = useThree15((state) => state.gl);
|
|
10919
|
+
const [texture, setTexture] = useState12(null);
|
|
10920
|
+
const onErrorRef = useRef25(onError);
|
|
10181
10921
|
onErrorRef.current = onError;
|
|
10182
|
-
|
|
10922
|
+
useEffect24(() => {
|
|
10183
10923
|
let active = true;
|
|
10184
10924
|
setTexture(null);
|
|
10185
10925
|
if (!poster) {
|
|
@@ -10187,7 +10927,7 @@ function usePosterTexture(poster, onError) {
|
|
|
10187
10927
|
active = false;
|
|
10188
10928
|
};
|
|
10189
10929
|
}
|
|
10190
|
-
const loader = new
|
|
10930
|
+
const loader = new TextureLoader4();
|
|
10191
10931
|
loader.load(
|
|
10192
10932
|
poster,
|
|
10193
10933
|
(loadedTexture) => {
|
|
@@ -10200,7 +10940,7 @@ function usePosterTexture(poster, onError) {
|
|
|
10200
10940
|
gl.capabilities.getMaxAnisotropy()
|
|
10201
10941
|
);
|
|
10202
10942
|
loadedTexture.wrapT = RepeatWrapping2;
|
|
10203
|
-
loadedTexture.magFilter =
|
|
10943
|
+
loadedTexture.magFilter = LinearFilter4;
|
|
10204
10944
|
loadedTexture.minFilter = LinearMipmapLinearFilter2;
|
|
10205
10945
|
loadedTexture.generateMipmaps = true;
|
|
10206
10946
|
setTexture(loadedTexture);
|
|
@@ -10216,7 +10956,7 @@ function usePosterTexture(poster, onError) {
|
|
|
10216
10956
|
active = false;
|
|
10217
10957
|
};
|
|
10218
10958
|
}, [gl, poster]);
|
|
10219
|
-
|
|
10959
|
+
useEffect24(
|
|
10220
10960
|
() => () => {
|
|
10221
10961
|
texture?.dispose();
|
|
10222
10962
|
},
|
|
@@ -10274,39 +11014,39 @@ function PanoVideo({
|
|
|
10274
11014
|
onTrackChange
|
|
10275
11015
|
}) {
|
|
10276
11016
|
usePanoMediaActivationIntent(autoPlay);
|
|
10277
|
-
const gl =
|
|
11017
|
+
const gl = useThree15((state) => state.gl);
|
|
10278
11018
|
const host = useContext21(PanoVideoHostContext);
|
|
10279
11019
|
const overlay = useContext21(PanoChromeOverlayContext);
|
|
10280
|
-
const variants =
|
|
11020
|
+
const variants = useMemo16(
|
|
10281
11021
|
() => resolvePanoVideoVariants({ poster, src, variants: variantsProp }),
|
|
10282
11022
|
[poster, src, variantsProp]
|
|
10283
11023
|
);
|
|
10284
11024
|
const tracks = tracksProp ?? EMPTY_TRACKS;
|
|
10285
11025
|
const captionsEnabled = captions !== false;
|
|
10286
|
-
const captionAppearance =
|
|
11026
|
+
const captionAppearance = useMemo16(
|
|
10287
11027
|
() => resolvePanoVideoCaptionAppearance(
|
|
10288
11028
|
typeof captions === "object" ? captions : void 0
|
|
10289
11029
|
),
|
|
10290
11030
|
[captions]
|
|
10291
11031
|
);
|
|
10292
|
-
const [variantId, setVariantId] =
|
|
11032
|
+
const [variantId, setVariantId] = useState12(
|
|
10293
11033
|
() => resolvePanoVideoVariantId(variants, defaultVariantId)
|
|
10294
11034
|
);
|
|
10295
|
-
const [trackId, setTrackId] =
|
|
11035
|
+
const [trackId, setTrackId] = useState12(
|
|
10296
11036
|
() => captionsEnabled ? defaultPanoVideoTrackId(tracks) : null
|
|
10297
11037
|
);
|
|
10298
|
-
const [ready, setReady] =
|
|
10299
|
-
const autoPlayRef =
|
|
11038
|
+
const [ready, setReady] = useState12(false);
|
|
11039
|
+
const autoPlayRef = useRef25(autoPlay);
|
|
10300
11040
|
autoPlayRef.current = autoPlay;
|
|
10301
|
-
const blockedRef =
|
|
10302
|
-
const captionAppearanceOverrideRef =
|
|
11041
|
+
const blockedRef = useRef25(false);
|
|
11042
|
+
const captionAppearanceOverrideRef = useRef25(
|
|
10303
11043
|
{}
|
|
10304
11044
|
);
|
|
10305
|
-
const mediaCapabilitiesRef =
|
|
11045
|
+
const mediaCapabilitiesRef = useRef25({
|
|
10306
11046
|
volumeAdjustable: true,
|
|
10307
11047
|
playbackRates: [...DEFAULT_PANO_VIDEO_PLAYBACK_RATES]
|
|
10308
11048
|
});
|
|
10309
|
-
const storeRef =
|
|
11049
|
+
const storeRef = useRef25(null);
|
|
10310
11050
|
if (!storeRef.current) {
|
|
10311
11051
|
storeRef.current = {
|
|
10312
11052
|
snapshot: {
|
|
@@ -10316,7 +11056,7 @@ function PanoVideo({
|
|
|
10316
11056
|
listeners: /* @__PURE__ */ new Set()
|
|
10317
11057
|
};
|
|
10318
11058
|
}
|
|
10319
|
-
const actionsRef =
|
|
11059
|
+
const actionsRef = useRef25({
|
|
10320
11060
|
play: async () => {
|
|
10321
11061
|
},
|
|
10322
11062
|
pause: () => {
|
|
@@ -10336,19 +11076,19 @@ function PanoVideo({
|
|
|
10336
11076
|
setCaptionAppearance: (_appearance) => {
|
|
10337
11077
|
}
|
|
10338
11078
|
});
|
|
10339
|
-
const onLoadRef =
|
|
10340
|
-
const onErrorRef =
|
|
10341
|
-
const onPlaybackStateChangeRef =
|
|
10342
|
-
const onEndedRef =
|
|
10343
|
-
const onVariantChangeRef =
|
|
10344
|
-
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);
|
|
10345
11085
|
onLoadRef.current = onLoad;
|
|
10346
11086
|
onErrorRef.current = onError;
|
|
10347
11087
|
onPlaybackStateChangeRef.current = onPlaybackStateChange;
|
|
10348
11088
|
onEndedRef.current = onEnded;
|
|
10349
11089
|
onVariantChangeRef.current = onVariantChange;
|
|
10350
11090
|
onTrackChangeRef.current = onTrackChange;
|
|
10351
|
-
const resource =
|
|
11091
|
+
const resource = useMemo16(() => {
|
|
10352
11092
|
if (typeof document === "undefined") {
|
|
10353
11093
|
return null;
|
|
10354
11094
|
}
|
|
@@ -10360,12 +11100,12 @@ function PanoVideo({
|
|
|
10360
11100
|
video.preload = "metadata";
|
|
10361
11101
|
const texture = new VideoTexture(video);
|
|
10362
11102
|
applyEquirectangularLayout(texture, 1);
|
|
10363
|
-
texture.magFilter =
|
|
10364
|
-
texture.minFilter =
|
|
11103
|
+
texture.magFilter = LinearFilter4;
|
|
11104
|
+
texture.minFilter = LinearFilter4;
|
|
10365
11105
|
texture.generateMipmaps = false;
|
|
10366
11106
|
return { video, texture };
|
|
10367
11107
|
}, []);
|
|
10368
|
-
|
|
11108
|
+
useEffect24(
|
|
10369
11109
|
() => () => {
|
|
10370
11110
|
if (!resource) {
|
|
10371
11111
|
return;
|
|
@@ -10380,13 +11120,13 @@ function PanoVideo({
|
|
|
10380
11120
|
},
|
|
10381
11121
|
[resource]
|
|
10382
11122
|
);
|
|
10383
|
-
|
|
11123
|
+
useEffect24(() => {
|
|
10384
11124
|
if (!resource) {
|
|
10385
11125
|
return;
|
|
10386
11126
|
}
|
|
10387
11127
|
resource.texture.anisotropy = gl.capabilities.getMaxAnisotropy();
|
|
10388
11128
|
}, [gl, resource]);
|
|
10389
|
-
|
|
11129
|
+
useEffect24(() => {
|
|
10390
11130
|
if (!resource || !overlay?.overlayElement) {
|
|
10391
11131
|
return;
|
|
10392
11132
|
}
|
|
@@ -10409,7 +11149,7 @@ function PanoVideo({
|
|
|
10409
11149
|
activeVariant?.poster ?? poster,
|
|
10410
11150
|
onError
|
|
10411
11151
|
);
|
|
10412
|
-
const emitSnapshot =
|
|
11152
|
+
const emitSnapshot = useCallback10(
|
|
10413
11153
|
(patch) => {
|
|
10414
11154
|
const store = storeRef.current;
|
|
10415
11155
|
const video = resource?.video;
|
|
@@ -10461,7 +11201,7 @@ function PanoVideo({
|
|
|
10461
11201
|
captionAppearance
|
|
10462
11202
|
]
|
|
10463
11203
|
);
|
|
10464
|
-
const controller =
|
|
11204
|
+
const controller = useMemo16(
|
|
10465
11205
|
() => ({
|
|
10466
11206
|
subscribe: (onStoreChange) => {
|
|
10467
11207
|
const store = storeRef.current;
|
|
@@ -10539,10 +11279,10 @@ function PanoVideo({
|
|
|
10539
11279
|
};
|
|
10540
11280
|
emitSnapshot();
|
|
10541
11281
|
}, [emitSnapshot, playbackRates, resource]);
|
|
10542
|
-
|
|
11282
|
+
useEffect24(() => {
|
|
10543
11283
|
emitSnapshot();
|
|
10544
11284
|
}, [emitSnapshot]);
|
|
10545
|
-
|
|
11285
|
+
useEffect24(() => {
|
|
10546
11286
|
if (!resource || !activeVariant || !mediaKey) {
|
|
10547
11287
|
return;
|
|
10548
11288
|
}
|
|
@@ -10599,7 +11339,7 @@ function PanoVideo({
|
|
|
10599
11339
|
video.removeEventListener("error", handleError);
|
|
10600
11340
|
};
|
|
10601
11341
|
}, [mediaKey, resource]);
|
|
10602
|
-
|
|
11342
|
+
useEffect24(() => {
|
|
10603
11343
|
if (!resource) {
|
|
10604
11344
|
return;
|
|
10605
11345
|
}
|
|
@@ -10691,7 +11431,7 @@ function PanoVideo({
|
|
|
10691
11431
|
}
|
|
10692
11432
|
};
|
|
10693
11433
|
}, [emitSnapshot, resource]);
|
|
10694
|
-
|
|
11434
|
+
useEffect24(() => {
|
|
10695
11435
|
if (!resource) {
|
|
10696
11436
|
return;
|
|
10697
11437
|
}
|
|
@@ -10711,7 +11451,7 @@ function PanoVideo({
|
|
|
10711
11451
|
}
|
|
10712
11452
|
video.preload = preload;
|
|
10713
11453
|
}, [loop, muted, playsInline, preload, resource, volume]);
|
|
10714
|
-
|
|
11454
|
+
useEffect24(() => {
|
|
10715
11455
|
if (!resource) {
|
|
10716
11456
|
return;
|
|
10717
11457
|
}
|
|
@@ -10761,7 +11501,7 @@ function PanoVideo({
|
|
|
10761
11501
|
video.removeEventListener("ratechange", handleVolume);
|
|
10762
11502
|
};
|
|
10763
11503
|
}, [emitSnapshot, resource]);
|
|
10764
|
-
|
|
11504
|
+
useEffect24(() => {
|
|
10765
11505
|
if (!resource) {
|
|
10766
11506
|
return;
|
|
10767
11507
|
}
|
|
@@ -10796,7 +11536,7 @@ function PanoVideo({
|
|
|
10796
11536
|
video.textTracks.removeEventListener("change", applyModes);
|
|
10797
11537
|
};
|
|
10798
11538
|
}, [emitSnapshot, resource, trackId, tracks]);
|
|
10799
|
-
|
|
11539
|
+
useEffect24(() => {
|
|
10800
11540
|
if (!captionsEnabled) {
|
|
10801
11541
|
setTrackId(null);
|
|
10802
11542
|
return;
|
|
@@ -10807,39 +11547,39 @@ function PanoVideo({
|
|
|
10807
11547
|
if (variants.length === 0) {
|
|
10808
11548
|
return null;
|
|
10809
11549
|
}
|
|
10810
|
-
return /* @__PURE__ */
|
|
10811
|
-
activeTexture ? /* @__PURE__ */
|
|
11550
|
+
return /* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
11551
|
+
activeTexture ? /* @__PURE__ */ jsxs11(
|
|
10812
11552
|
"mesh",
|
|
10813
11553
|
{
|
|
10814
|
-
rotation: [0,
|
|
11554
|
+
rotation: [0, MathUtils7.degToRad(90 + yawOffset), 0],
|
|
10815
11555
|
visible,
|
|
10816
11556
|
children: [
|
|
10817
|
-
/* @__PURE__ */
|
|
10818
|
-
/* @__PURE__ */
|
|
11557
|
+
/* @__PURE__ */ jsx17("sphereGeometry", { args: [DEFAULT_PANORAMA_RADIUS, 128, 64] }),
|
|
11558
|
+
/* @__PURE__ */ jsx17(
|
|
10819
11559
|
PanoBasicMaterial,
|
|
10820
11560
|
{
|
|
10821
11561
|
map: activeTexture,
|
|
10822
|
-
side:
|
|
11562
|
+
side: BackSide4,
|
|
10823
11563
|
toneMapped: false
|
|
10824
11564
|
}
|
|
10825
11565
|
)
|
|
10826
11566
|
]
|
|
10827
11567
|
}
|
|
10828
11568
|
) : null,
|
|
10829
|
-
captionsEnabled ? /* @__PURE__ */
|
|
11569
|
+
captionsEnabled ? /* @__PURE__ */ jsx17(PanoVideoCaptions, { appearance: typeof captions === "object" ? captions : void 0 }) : null
|
|
10830
11570
|
] });
|
|
10831
11571
|
}
|
|
10832
11572
|
|
|
10833
11573
|
// src/scenes.tsx
|
|
10834
|
-
import { useFrame as
|
|
11574
|
+
import { useFrame as useFrame13, useThree as useThree20 } from "@react-three/fiber";
|
|
10835
11575
|
import {
|
|
10836
11576
|
Fragment as Fragment6,
|
|
10837
|
-
useCallback as
|
|
11577
|
+
useCallback as useCallback11,
|
|
10838
11578
|
useContext as useContext23,
|
|
10839
|
-
useEffect as
|
|
10840
|
-
useMemo as
|
|
10841
|
-
useRef as
|
|
10842
|
-
useState as
|
|
11579
|
+
useEffect as useEffect29,
|
|
11580
|
+
useMemo as useMemo21,
|
|
11581
|
+
useRef as useRef29,
|
|
11582
|
+
useState as useState14
|
|
10843
11583
|
} from "react";
|
|
10844
11584
|
import {
|
|
10845
11585
|
LinearSRGBColorSpace,
|
|
@@ -10894,8 +11634,8 @@ function isSnapshotTransition(preset) {
|
|
|
10894
11634
|
}
|
|
10895
11635
|
|
|
10896
11636
|
// src/scene-transitions/particle-overlay.tsx
|
|
10897
|
-
import { useFrame as
|
|
10898
|
-
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";
|
|
10899
11639
|
import {
|
|
10900
11640
|
DoubleSide as DoubleSide2,
|
|
10901
11641
|
InstancedBufferAttribute,
|
|
@@ -10903,7 +11643,7 @@ import {
|
|
|
10903
11643
|
PlaneGeometry as PlaneGeometry3,
|
|
10904
11644
|
ShaderMaterial as ShaderMaterial2,
|
|
10905
11645
|
Vector2 as Vector24,
|
|
10906
|
-
Vector3 as
|
|
11646
|
+
Vector3 as Vector310
|
|
10907
11647
|
} from "three";
|
|
10908
11648
|
|
|
10909
11649
|
// src/scene-transitions/glsl.ts
|
|
@@ -10958,7 +11698,7 @@ function overlayProgress(elapsedTime, duration, startTime) {
|
|
|
10958
11698
|
}
|
|
10959
11699
|
|
|
10960
11700
|
// src/scene-transitions/particle-overlay.tsx
|
|
10961
|
-
import { jsx as
|
|
11701
|
+
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
10962
11702
|
var PARTICLE_GRID = 48;
|
|
10963
11703
|
var PARTICLE_COUNT = PARTICLE_GRID * PARTICLE_GRID;
|
|
10964
11704
|
var PARTICLE_VERTEX_SHADER = `
|
|
@@ -11034,13 +11774,13 @@ function ParticleOverlay({
|
|
|
11034
11774
|
runId,
|
|
11035
11775
|
onFinish
|
|
11036
11776
|
}) {
|
|
11037
|
-
const { camera } =
|
|
11038
|
-
const meshRef =
|
|
11039
|
-
const startRef =
|
|
11040
|
-
const finishedRef =
|
|
11041
|
-
const directionRef =
|
|
11042
|
-
const geometry =
|
|
11043
|
-
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(
|
|
11044
11784
|
() => new ShaderMaterial2({
|
|
11045
11785
|
transparent: true,
|
|
11046
11786
|
depthTest: false,
|
|
@@ -11056,14 +11796,14 @@ function ParticleOverlay({
|
|
|
11056
11796
|
}),
|
|
11057
11797
|
[snapshot.texture]
|
|
11058
11798
|
);
|
|
11059
|
-
|
|
11060
|
-
|
|
11061
|
-
|
|
11799
|
+
useEffect25(() => () => geometry.dispose(), [geometry]);
|
|
11800
|
+
useEffect25(() => () => material.dispose(), [material]);
|
|
11801
|
+
useEffect25(() => {
|
|
11062
11802
|
startRef.current = null;
|
|
11063
11803
|
finishedRef.current = false;
|
|
11064
11804
|
material.uniforms.progress.value = 0;
|
|
11065
11805
|
}, [material, runId]);
|
|
11066
|
-
|
|
11806
|
+
useFrame10((state) => {
|
|
11067
11807
|
const mesh = meshRef.current;
|
|
11068
11808
|
if (!mesh || !isPerspectiveCamera(camera)) {
|
|
11069
11809
|
return;
|
|
@@ -11080,7 +11820,7 @@ function ParticleOverlay({
|
|
|
11080
11820
|
onFinish();
|
|
11081
11821
|
}
|
|
11082
11822
|
});
|
|
11083
|
-
return /* @__PURE__ */
|
|
11823
|
+
return /* @__PURE__ */ jsx18(
|
|
11084
11824
|
"mesh",
|
|
11085
11825
|
{
|
|
11086
11826
|
ref: meshRef,
|
|
@@ -11093,9 +11833,9 @@ function ParticleOverlay({
|
|
|
11093
11833
|
}
|
|
11094
11834
|
|
|
11095
11835
|
// src/scene-transitions/snapshot-overlay.tsx
|
|
11096
|
-
import { useFrame as
|
|
11097
|
-
import { useEffect as
|
|
11098
|
-
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";
|
|
11099
11839
|
|
|
11100
11840
|
// src/scene-transitions/snapshot-shaders.ts
|
|
11101
11841
|
import { DoubleSide as DoubleSide3, ShaderMaterial as ShaderMaterial3, Vector2 as Vector25 } from "three";
|
|
@@ -11374,7 +12114,7 @@ function createSnapshotMaterial(preset, texture) {
|
|
|
11374
12114
|
}
|
|
11375
12115
|
|
|
11376
12116
|
// src/scene-transitions/snapshot-overlay.tsx
|
|
11377
|
-
import { jsx as
|
|
12117
|
+
import { jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
11378
12118
|
function SnapshotOverlay({
|
|
11379
12119
|
snapshot,
|
|
11380
12120
|
transition,
|
|
@@ -11382,26 +12122,26 @@ function SnapshotOverlay({
|
|
|
11382
12122
|
runId,
|
|
11383
12123
|
onFinish
|
|
11384
12124
|
}) {
|
|
11385
|
-
const { camera, gl } =
|
|
11386
|
-
const meshRef =
|
|
11387
|
-
const startRef =
|
|
11388
|
-
const finishedRef =
|
|
11389
|
-
const directionRef =
|
|
11390
|
-
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(() => {
|
|
11391
12131
|
if (!isSnapshotTransition(transition.preset)) {
|
|
11392
12132
|
return null;
|
|
11393
12133
|
}
|
|
11394
12134
|
return createSnapshotMaterial(transition.preset, snapshot.texture);
|
|
11395
12135
|
}, [snapshot.texture, transition.preset]);
|
|
11396
|
-
|
|
11397
|
-
|
|
12136
|
+
useEffect26(() => () => material?.dispose(), [material]);
|
|
12137
|
+
useEffect26(() => {
|
|
11398
12138
|
startRef.current = null;
|
|
11399
12139
|
finishedRef.current = false;
|
|
11400
12140
|
if (material) {
|
|
11401
12141
|
material.uniforms.progress.value = 0;
|
|
11402
12142
|
}
|
|
11403
12143
|
}, [material, runId]);
|
|
11404
|
-
|
|
12144
|
+
useFrame11((state) => {
|
|
11405
12145
|
const mesh = meshRef.current;
|
|
11406
12146
|
if (!mesh || !material || !isPerspectiveCamera(camera)) {
|
|
11407
12147
|
return;
|
|
@@ -11423,21 +12163,21 @@ function SnapshotOverlay({
|
|
|
11423
12163
|
if (!material) {
|
|
11424
12164
|
return null;
|
|
11425
12165
|
}
|
|
11426
|
-
return /* @__PURE__ */
|
|
11427
|
-
/* @__PURE__ */
|
|
11428
|
-
/* @__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 })
|
|
11429
12169
|
] });
|
|
11430
12170
|
}
|
|
11431
12171
|
|
|
11432
12172
|
// src/scene-transitions/transition-overlay.tsx
|
|
11433
|
-
import { jsx as
|
|
12173
|
+
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
11434
12174
|
function TransitionOverlay(props) {
|
|
11435
12175
|
const { preset } = props.transition;
|
|
11436
12176
|
switch (preset) {
|
|
11437
12177
|
case "none":
|
|
11438
12178
|
return null;
|
|
11439
12179
|
case "particles":
|
|
11440
|
-
return /* @__PURE__ */
|
|
12180
|
+
return /* @__PURE__ */ jsx20(ParticleOverlay, { ...props });
|
|
11441
12181
|
case "crossfade":
|
|
11442
12182
|
case "zoom":
|
|
11443
12183
|
case "blackout":
|
|
@@ -11465,7 +12205,7 @@ function TransitionOverlay(props) {
|
|
|
11465
12205
|
case "zoomBlur":
|
|
11466
12206
|
case "hexDissolve":
|
|
11467
12207
|
case "filmBurn":
|
|
11468
|
-
return /* @__PURE__ */
|
|
12208
|
+
return /* @__PURE__ */ jsx20(SnapshotOverlay, { ...props });
|
|
11469
12209
|
default: {
|
|
11470
12210
|
const exhaustive = preset;
|
|
11471
12211
|
void exhaustive;
|
|
@@ -11475,242 +12215,14 @@ function TransitionOverlay(props) {
|
|
|
11475
12215
|
}
|
|
11476
12216
|
|
|
11477
12217
|
// src/tile/texture-manager-context.tsx
|
|
11478
|
-
import { useThree as
|
|
12218
|
+
import { useThree as useThree18 } from "@react-three/fiber";
|
|
11479
12219
|
import {
|
|
11480
12220
|
createContext as createContext15,
|
|
11481
12221
|
useContext as useContext22,
|
|
11482
|
-
useEffect as
|
|
11483
|
-
useMemo as
|
|
12222
|
+
useEffect as useEffect27,
|
|
12223
|
+
useMemo as useMemo19
|
|
11484
12224
|
} from "react";
|
|
11485
|
-
|
|
11486
|
-
// src/tile/texture-manager.ts
|
|
11487
|
-
import {
|
|
11488
|
-
ClampToEdgeWrapping,
|
|
11489
|
-
LinearFilter as LinearFilter3,
|
|
11490
|
-
SRGBColorSpace as SRGBColorSpace3,
|
|
11491
|
-
TextureLoader as TextureLoader3
|
|
11492
|
-
} from "three";
|
|
11493
|
-
var EMPTY_TEXTURE_SNAPSHOT = {
|
|
11494
|
-
status: "idle",
|
|
11495
|
-
texture: null,
|
|
11496
|
-
error: null
|
|
11497
|
-
};
|
|
11498
|
-
var TileTextureManager = class {
|
|
11499
|
-
constructor(options) {
|
|
11500
|
-
this.loader = new TextureLoader3();
|
|
11501
|
-
this.entries = /* @__PURE__ */ new Map();
|
|
11502
|
-
this.queue = [];
|
|
11503
|
-
this.activeLoads = 0;
|
|
11504
|
-
this.totalBytes = 0;
|
|
11505
|
-
this.requested = 0;
|
|
11506
|
-
this.loaded = 0;
|
|
11507
|
-
this.failed = 0;
|
|
11508
|
-
this.disposed = false;
|
|
11509
|
-
this.generation = 0;
|
|
11510
|
-
this.options = options;
|
|
11511
|
-
}
|
|
11512
|
-
resume() {
|
|
11513
|
-
this.disposed = false;
|
|
11514
|
-
this.drain();
|
|
11515
|
-
}
|
|
11516
|
-
getSnapshot(key) {
|
|
11517
|
-
const entry = this.entries.get(key);
|
|
11518
|
-
return entry ? this.snapshot(entry) : EMPTY_TEXTURE_SNAPSHOT;
|
|
11519
|
-
}
|
|
11520
|
-
acquire(key, url, address, listener) {
|
|
11521
|
-
let entry = this.entries.get(key);
|
|
11522
|
-
if (!entry) {
|
|
11523
|
-
entry = {
|
|
11524
|
-
key,
|
|
11525
|
-
url,
|
|
11526
|
-
address,
|
|
11527
|
-
status: "idle",
|
|
11528
|
-
texture: null,
|
|
11529
|
-
error: null,
|
|
11530
|
-
refs: 0,
|
|
11531
|
-
listeners: /* @__PURE__ */ new Set(),
|
|
11532
|
-
lastUsed: performance.now(),
|
|
11533
|
-
bytes: 0
|
|
11534
|
-
};
|
|
11535
|
-
this.entries.set(key, entry);
|
|
11536
|
-
}
|
|
11537
|
-
entry.refs += 1;
|
|
11538
|
-
entry.lastUsed = performance.now();
|
|
11539
|
-
entry.listeners.add(listener);
|
|
11540
|
-
listener(this.snapshot(entry));
|
|
11541
|
-
if (entry.status === "idle") {
|
|
11542
|
-
entry.status = "queued";
|
|
11543
|
-
this.queue.push(entry);
|
|
11544
|
-
this.requested += 1;
|
|
11545
|
-
this.emitProgress();
|
|
11546
|
-
this.drain();
|
|
11547
|
-
}
|
|
11548
|
-
return () => {
|
|
11549
|
-
entry.listeners.delete(listener);
|
|
11550
|
-
entry.refs = Math.max(0, entry.refs - 1);
|
|
11551
|
-
entry.lastUsed = performance.now();
|
|
11552
|
-
if (entry.refs === 0 && entry.status === "queued") {
|
|
11553
|
-
const queueIndex = this.queue.indexOf(entry);
|
|
11554
|
-
if (queueIndex >= 0) {
|
|
11555
|
-
this.queue.splice(queueIndex, 1);
|
|
11556
|
-
}
|
|
11557
|
-
entry.status = "idle";
|
|
11558
|
-
this.entries.delete(entry.key);
|
|
11559
|
-
this.requested = Math.max(0, this.requested - 1);
|
|
11560
|
-
this.emitProgress();
|
|
11561
|
-
this.drain();
|
|
11562
|
-
return;
|
|
11563
|
-
}
|
|
11564
|
-
this.evict();
|
|
11565
|
-
};
|
|
11566
|
-
}
|
|
11567
|
-
dispose() {
|
|
11568
|
-
this.disposed = true;
|
|
11569
|
-
this.generation += 1;
|
|
11570
|
-
this.queue.length = 0;
|
|
11571
|
-
for (const entry of this.entries.values()) {
|
|
11572
|
-
entry.texture?.dispose();
|
|
11573
|
-
entry.listeners.clear();
|
|
11574
|
-
}
|
|
11575
|
-
this.entries.clear();
|
|
11576
|
-
this.totalBytes = 0;
|
|
11577
|
-
}
|
|
11578
|
-
/**
|
|
11579
|
-
* Releases textures that are no longer rendered by any Tile instance.
|
|
11580
|
-
* Scene transitions call this after the outgoing panorama has been
|
|
11581
|
-
* snapshotted, so the incoming scene never competes with stale GPU tiles.
|
|
11582
|
-
*/
|
|
11583
|
-
releaseUnused() {
|
|
11584
|
-
for (const entry of Array.from(this.entries.values())) {
|
|
11585
|
-
if (entry.refs > 0) {
|
|
11586
|
-
continue;
|
|
11587
|
-
}
|
|
11588
|
-
entry.texture?.dispose();
|
|
11589
|
-
this.totalBytes -= entry.bytes;
|
|
11590
|
-
this.entries.delete(entry.key);
|
|
11591
|
-
}
|
|
11592
|
-
this.totalBytes = Math.max(0, this.totalBytes);
|
|
11593
|
-
}
|
|
11594
|
-
snapshot(entry) {
|
|
11595
|
-
return {
|
|
11596
|
-
status: entry.status,
|
|
11597
|
-
texture: entry.texture,
|
|
11598
|
-
error: entry.error
|
|
11599
|
-
};
|
|
11600
|
-
}
|
|
11601
|
-
notify(entry) {
|
|
11602
|
-
const snapshot = this.snapshot(entry);
|
|
11603
|
-
for (const listener of entry.listeners) {
|
|
11604
|
-
listener(snapshot);
|
|
11605
|
-
}
|
|
11606
|
-
}
|
|
11607
|
-
emitProgress() {
|
|
11608
|
-
this.options.onProgress?.({
|
|
11609
|
-
requested: this.requested,
|
|
11610
|
-
loaded: this.loaded,
|
|
11611
|
-
failed: this.failed,
|
|
11612
|
-
active: this.activeLoads,
|
|
11613
|
-
queued: this.queue.length
|
|
11614
|
-
});
|
|
11615
|
-
}
|
|
11616
|
-
drain() {
|
|
11617
|
-
while (!this.disposed && this.activeLoads < this.options.concurrency && this.queue.length > 0) {
|
|
11618
|
-
const entry = this.queue.shift();
|
|
11619
|
-
if (entry.refs === 0) {
|
|
11620
|
-
entry.status = "idle";
|
|
11621
|
-
this.entries.delete(entry.key);
|
|
11622
|
-
this.requested = Math.max(0, this.requested - 1);
|
|
11623
|
-
continue;
|
|
11624
|
-
}
|
|
11625
|
-
entry.status = "loading";
|
|
11626
|
-
this.activeLoads += 1;
|
|
11627
|
-
this.notify(entry);
|
|
11628
|
-
this.emitProgress();
|
|
11629
|
-
void this.loadAndFinish(entry);
|
|
11630
|
-
}
|
|
11631
|
-
}
|
|
11632
|
-
async load(entry, generation) {
|
|
11633
|
-
let lastError = null;
|
|
11634
|
-
for (let attempt = 0; attempt <= this.options.retryCount; attempt += 1) {
|
|
11635
|
-
try {
|
|
11636
|
-
const texture = await this.loader.loadAsync(entry.url);
|
|
11637
|
-
if (this.disposed || generation !== this.generation) {
|
|
11638
|
-
texture.dispose();
|
|
11639
|
-
return;
|
|
11640
|
-
}
|
|
11641
|
-
this.configureTexture(texture);
|
|
11642
|
-
entry.texture = texture;
|
|
11643
|
-
entry.status = "loaded";
|
|
11644
|
-
entry.error = null;
|
|
11645
|
-
entry.bytes = entry.address.width * entry.address.height * 4;
|
|
11646
|
-
entry.lastUsed = performance.now();
|
|
11647
|
-
this.totalBytes += entry.bytes;
|
|
11648
|
-
this.loaded += 1;
|
|
11649
|
-
this.notify(entry);
|
|
11650
|
-
return;
|
|
11651
|
-
} catch (error) {
|
|
11652
|
-
lastError = error;
|
|
11653
|
-
}
|
|
11654
|
-
}
|
|
11655
|
-
if (!this.disposed && generation === this.generation) {
|
|
11656
|
-
entry.status = "error";
|
|
11657
|
-
entry.error = lastError;
|
|
11658
|
-
this.failed += 1;
|
|
11659
|
-
this.notify(entry);
|
|
11660
|
-
this.options.onError?.({
|
|
11661
|
-
address: entry.address,
|
|
11662
|
-
url: entry.url,
|
|
11663
|
-
error: lastError
|
|
11664
|
-
});
|
|
11665
|
-
}
|
|
11666
|
-
}
|
|
11667
|
-
configureTexture(texture) {
|
|
11668
|
-
texture.colorSpace = SRGBColorSpace3;
|
|
11669
|
-
texture.wrapS = ClampToEdgeWrapping;
|
|
11670
|
-
texture.wrapT = ClampToEdgeWrapping;
|
|
11671
|
-
texture.magFilter = LinearFilter3;
|
|
11672
|
-
texture.minFilter = LinearFilter3;
|
|
11673
|
-
texture.generateMipmaps = false;
|
|
11674
|
-
texture.anisotropy = Math.min(4, this.options.anisotropy);
|
|
11675
|
-
texture.needsUpdate = true;
|
|
11676
|
-
}
|
|
11677
|
-
evict() {
|
|
11678
|
-
if (this.totalBytes <= this.options.maxBytes) {
|
|
11679
|
-
return;
|
|
11680
|
-
}
|
|
11681
|
-
const candidates = Array.from(this.entries.values()).filter((entry) => entry.refs === 0 && entry.texture).sort((a, b) => a.lastUsed - b.lastUsed);
|
|
11682
|
-
for (const entry of candidates) {
|
|
11683
|
-
if (this.totalBytes <= this.options.maxBytes) {
|
|
11684
|
-
break;
|
|
11685
|
-
}
|
|
11686
|
-
entry.texture?.dispose();
|
|
11687
|
-
this.totalBytes -= entry.bytes;
|
|
11688
|
-
this.entries.delete(entry.key);
|
|
11689
|
-
}
|
|
11690
|
-
this.totalBytes = Math.max(0, this.totalBytes);
|
|
11691
|
-
}
|
|
11692
|
-
finishLoad(generation) {
|
|
11693
|
-
this.activeLoads = Math.max(0, this.activeLoads - 1);
|
|
11694
|
-
if (!this.disposed && generation === this.generation) {
|
|
11695
|
-
this.emitProgress();
|
|
11696
|
-
this.evict();
|
|
11697
|
-
}
|
|
11698
|
-
if (!this.disposed) {
|
|
11699
|
-
this.drain();
|
|
11700
|
-
}
|
|
11701
|
-
}
|
|
11702
|
-
async loadAndFinish(entry) {
|
|
11703
|
-
const generation = this.generation;
|
|
11704
|
-
try {
|
|
11705
|
-
await this.load(entry, generation);
|
|
11706
|
-
} finally {
|
|
11707
|
-
this.finishLoad(generation);
|
|
11708
|
-
}
|
|
11709
|
-
}
|
|
11710
|
-
};
|
|
11711
|
-
|
|
11712
|
-
// src/tile/texture-manager-context.tsx
|
|
11713
|
-
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
12225
|
+
import { jsx as jsx21 } from "react/jsx-runtime";
|
|
11714
12226
|
var TileTextureManagerContext = createContext15(
|
|
11715
12227
|
null
|
|
11716
12228
|
);
|
|
@@ -11719,9 +12231,9 @@ function TileTextureManagerProvider({
|
|
|
11719
12231
|
maxTextureMemoryMb = 128,
|
|
11720
12232
|
maxConcurrentLoads = 4
|
|
11721
12233
|
}) {
|
|
11722
|
-
const gl =
|
|
12234
|
+
const gl = useThree18((state) => state.gl);
|
|
11723
12235
|
const anisotropy = gl.capabilities.getMaxAnisotropy();
|
|
11724
|
-
const manager =
|
|
12236
|
+
const manager = useMemo19(
|
|
11725
12237
|
() => new TileTextureManager({
|
|
11726
12238
|
anisotropy,
|
|
11727
12239
|
maxBytes: Math.max(1, maxTextureMemoryMb) * 1024 * 1024,
|
|
@@ -11730,43 +12242,33 @@ function TileTextureManagerProvider({
|
|
|
11730
12242
|
}),
|
|
11731
12243
|
[anisotropy, maxConcurrentLoads, maxTextureMemoryMb]
|
|
11732
12244
|
);
|
|
11733
|
-
|
|
12245
|
+
useEffect27(() => {
|
|
11734
12246
|
manager.resume();
|
|
11735
12247
|
return () => manager.dispose();
|
|
11736
12248
|
}, [manager]);
|
|
11737
|
-
return /* @__PURE__ */
|
|
12249
|
+
return /* @__PURE__ */ jsx21(TileTextureManagerContext.Provider, { value: manager, children });
|
|
11738
12250
|
}
|
|
11739
12251
|
function useSharedTileTextureManager() {
|
|
11740
12252
|
return useContext22(TileTextureManagerContext);
|
|
11741
12253
|
}
|
|
11742
12254
|
|
|
11743
12255
|
// src/tile/tile.tsx
|
|
11744
|
-
import { useFrame as
|
|
11745
|
-
import {
|
|
11746
|
-
memo,
|
|
11747
|
-
useEffect as useEffect26,
|
|
11748
|
-
useMemo as useMemo19,
|
|
11749
|
-
useRef as useRef26,
|
|
11750
|
-
useState as useState11
|
|
11751
|
-
} 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";
|
|
11752
12258
|
import {
|
|
11753
|
-
|
|
11754
|
-
|
|
11755
|
-
LinearFilter as LinearFilter4,
|
|
11756
|
-
Matrix4,
|
|
12259
|
+
Frustum as Frustum2,
|
|
12260
|
+
Matrix4 as Matrix43,
|
|
11757
12261
|
PlaneGeometry as PlaneGeometry4,
|
|
11758
|
-
PerspectiveCamera as
|
|
11759
|
-
|
|
11760
|
-
TextureLoader as TextureLoader4,
|
|
11761
|
-
Vector3 as Vector312
|
|
12262
|
+
PerspectiveCamera as PerspectiveCamera5,
|
|
12263
|
+
Vector3 as Vector313
|
|
11762
12264
|
} from "three";
|
|
11763
12265
|
|
|
11764
12266
|
// src/tile/face-layout.ts
|
|
11765
12267
|
import {
|
|
11766
|
-
Box3,
|
|
12268
|
+
Box3 as Box32,
|
|
11767
12269
|
Euler as Euler3,
|
|
11768
12270
|
Quaternion as Quaternion2,
|
|
11769
|
-
Vector3 as
|
|
12271
|
+
Vector3 as Vector312
|
|
11770
12272
|
} from "three";
|
|
11771
12273
|
var CUBE_FACES = ["f", "r", "b", "l", "u", "d"];
|
|
11772
12274
|
var PREVIEW_FACE_ORDER = ["l", "f", "r", "b", "u", "d"];
|
|
@@ -11830,17 +12332,17 @@ function getTileBoundingBox(address, radius = CUBE_RADIUS) {
|
|
|
11830
12332
|
const halfWidth = local.width / 2;
|
|
11831
12333
|
const halfHeight = local.height / 2;
|
|
11832
12334
|
const quaternion = getFaceQuaternion(address.face);
|
|
11833
|
-
const position = new
|
|
12335
|
+
const position = new Vector312(...transform.position);
|
|
11834
12336
|
const corners = [
|
|
11835
|
-
new
|
|
11836
|
-
new
|
|
11837
|
-
new
|
|
11838
|
-
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)
|
|
11839
12341
|
];
|
|
11840
12342
|
for (const corner of corners) {
|
|
11841
12343
|
corner.applyQuaternion(quaternion).add(position);
|
|
11842
12344
|
}
|
|
11843
|
-
return new
|
|
12345
|
+
return new Box32().setFromPoints(corners);
|
|
11844
12346
|
}
|
|
11845
12347
|
function makeTileAddress(face, level, faceSize, tileSize, col, row) {
|
|
11846
12348
|
const left = (col - 1) * tileSize;
|
|
@@ -11887,7 +12389,7 @@ function previewAtlasVRange(face, faceOrder = PREVIEW_FACE_ORDER) {
|
|
|
11887
12389
|
}
|
|
11888
12390
|
|
|
11889
12391
|
// src/tile/multires.ts
|
|
11890
|
-
function
|
|
12392
|
+
function positiveInteger2(value, name) {
|
|
11891
12393
|
if (!Number.isFinite(value) || value <= 0 || !Number.isInteger(value)) {
|
|
11892
12394
|
throw new Error(`${name} must be a positive integer, received ${String(value)}`);
|
|
11893
12395
|
}
|
|
@@ -11903,13 +12405,13 @@ function ascendingLevels(levels) {
|
|
|
11903
12405
|
}
|
|
11904
12406
|
function parseMultires(multires) {
|
|
11905
12407
|
if (typeof multires !== "string") {
|
|
11906
|
-
const tileSize2 =
|
|
12408
|
+
const tileSize2 = positiveInteger2(multires.tileSize, "multires.tileSize");
|
|
11907
12409
|
if (multires.levels.length === 0) {
|
|
11908
12410
|
throw new Error("multires.levels must contain at least one face size");
|
|
11909
12411
|
}
|
|
11910
12412
|
const levels2 = ascendingLevels(
|
|
11911
12413
|
multires.levels.map(
|
|
11912
|
-
(level, index) =>
|
|
12414
|
+
(level, index) => positiveInteger2(level, `multires.levels[${index}]`)
|
|
11913
12415
|
)
|
|
11914
12416
|
);
|
|
11915
12417
|
return { tileSize: tileSize2, levels: levels2 };
|
|
@@ -11920,10 +12422,10 @@ function parseMultires(multires) {
|
|
|
11920
12422
|
"multires must contain a tile size followed by at least one face size"
|
|
11921
12423
|
);
|
|
11922
12424
|
}
|
|
11923
|
-
const tileSize =
|
|
12425
|
+
const tileSize = positiveInteger2(values[0], "multires tile size");
|
|
11924
12426
|
const levels = ascendingLevels(
|
|
11925
12427
|
values.slice(1).map(
|
|
11926
|
-
(level, index) =>
|
|
12428
|
+
(level, index) => positiveInteger2(level, `multires level ${index + 1}`)
|
|
11927
12429
|
)
|
|
11928
12430
|
);
|
|
11929
12431
|
return { tileSize, levels };
|
|
@@ -11943,7 +12445,7 @@ function resolveTemplateUrl(template, address) {
|
|
|
11943
12445
|
}
|
|
11944
12446
|
|
|
11945
12447
|
// src/tile/tile.tsx
|
|
11946
|
-
import { jsx as
|
|
12448
|
+
import { jsx as jsx22, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
11947
12449
|
var MAX_LOD_UPDATE_INTERVAL_MS = 100;
|
|
11948
12450
|
var FAST_ROTATION_THRESHOLD_RADIANS = Math.PI / 180;
|
|
11949
12451
|
var FAST_FOV_THRESHOLD_DEGREES = 0.5;
|
|
@@ -11951,61 +12453,12 @@ var VIEW_CHANGE_EPSILON = 1e-4;
|
|
|
11951
12453
|
var VISIBILITY_FOV_PADDING_DEGREES = 8;
|
|
11952
12454
|
var PREVIEW_RADIUS = CUBE_RADIUS + 0.05;
|
|
11953
12455
|
var SHARED_TILE_GEOMETRY = new PlaneGeometry4(1, 1);
|
|
11954
|
-
function usePreviewTexture(url, anisotropy, onError) {
|
|
11955
|
-
const [texture, setTexture] = useState11(null);
|
|
11956
|
-
const onErrorRef = useRef26(onError);
|
|
11957
|
-
onErrorRef.current = onError;
|
|
11958
|
-
useEffect26(() => {
|
|
11959
|
-
if (!url) {
|
|
11960
|
-
setTexture(null);
|
|
11961
|
-
return;
|
|
11962
|
-
}
|
|
11963
|
-
let active = true;
|
|
11964
|
-
const loader = new TextureLoader4();
|
|
11965
|
-
setTexture(null);
|
|
11966
|
-
loader.load(
|
|
11967
|
-
url,
|
|
11968
|
-
(loadedTexture) => {
|
|
11969
|
-
if (!active) {
|
|
11970
|
-
loadedTexture.dispose();
|
|
11971
|
-
return;
|
|
11972
|
-
}
|
|
11973
|
-
loadedTexture.colorSpace = SRGBColorSpace4;
|
|
11974
|
-
loadedTexture.wrapS = ClampToEdgeWrapping2;
|
|
11975
|
-
loadedTexture.wrapT = ClampToEdgeWrapping2;
|
|
11976
|
-
loadedTexture.magFilter = LinearFilter4;
|
|
11977
|
-
loadedTexture.minFilter = LinearFilter4;
|
|
11978
|
-
loadedTexture.generateMipmaps = false;
|
|
11979
|
-
loadedTexture.anisotropy = Math.min(4, anisotropy);
|
|
11980
|
-
loadedTexture.needsUpdate = true;
|
|
11981
|
-
setTexture(loadedTexture);
|
|
11982
|
-
},
|
|
11983
|
-
void 0,
|
|
11984
|
-
(error) => {
|
|
11985
|
-
if (active) {
|
|
11986
|
-
setTexture(null);
|
|
11987
|
-
onErrorRef.current?.(error);
|
|
11988
|
-
}
|
|
11989
|
-
}
|
|
11990
|
-
);
|
|
11991
|
-
return () => {
|
|
11992
|
-
active = false;
|
|
11993
|
-
};
|
|
11994
|
-
}, [anisotropy, url]);
|
|
11995
|
-
useEffect26(
|
|
11996
|
-
() => () => {
|
|
11997
|
-
texture?.dispose();
|
|
11998
|
-
},
|
|
11999
|
-
[texture]
|
|
12000
|
-
);
|
|
12001
|
-
return texture;
|
|
12002
|
-
}
|
|
12003
12456
|
function PreviewFace({
|
|
12004
12457
|
face,
|
|
12005
12458
|
texture,
|
|
12006
12459
|
faceOrder
|
|
12007
12460
|
}) {
|
|
12008
|
-
const geometry =
|
|
12461
|
+
const geometry = useMemo20(() => {
|
|
12009
12462
|
const nextGeometry = new PlaneGeometry4(
|
|
12010
12463
|
PREVIEW_RADIUS * 2,
|
|
12011
12464
|
PREVIEW_RADIUS * 2
|
|
@@ -12015,29 +12468,26 @@ function PreviewFace({
|
|
|
12015
12468
|
const inset = scale / 512;
|
|
12016
12469
|
for (let index = 0; index < uv.count; index += 1) {
|
|
12017
12470
|
const sourceV = uv.getY(index);
|
|
12018
|
-
uv.setY(
|
|
12019
|
-
index,
|
|
12020
|
-
offset + inset + sourceV * Math.max(0, scale - inset * 2)
|
|
12021
|
-
);
|
|
12471
|
+
uv.setY(index, offset + inset + sourceV * Math.max(0, scale - inset * 2));
|
|
12022
12472
|
}
|
|
12023
12473
|
uv.needsUpdate = true;
|
|
12024
12474
|
return nextGeometry;
|
|
12025
12475
|
}, [face, faceOrder]);
|
|
12026
|
-
|
|
12476
|
+
useEffect28(
|
|
12027
12477
|
() => () => {
|
|
12028
12478
|
geometry.dispose();
|
|
12029
12479
|
},
|
|
12030
12480
|
[geometry]
|
|
12031
12481
|
);
|
|
12032
12482
|
const transform = getFaceTransform(face, PREVIEW_RADIUS);
|
|
12033
|
-
return /* @__PURE__ */
|
|
12483
|
+
return /* @__PURE__ */ jsx22(
|
|
12034
12484
|
"mesh",
|
|
12035
12485
|
{
|
|
12036
12486
|
geometry,
|
|
12037
12487
|
position: transform.position,
|
|
12038
12488
|
renderOrder: -100,
|
|
12039
12489
|
rotation: transform.rotation,
|
|
12040
|
-
children: /* @__PURE__ */
|
|
12490
|
+
children: /* @__PURE__ */ jsx22(
|
|
12041
12491
|
PanoBasicMaterial,
|
|
12042
12492
|
{
|
|
12043
12493
|
depthTest: false,
|
|
@@ -12053,7 +12503,7 @@ function PreviewCube({
|
|
|
12053
12503
|
texture,
|
|
12054
12504
|
faceOrder
|
|
12055
12505
|
}) {
|
|
12056
|
-
return CUBE_FACES.map((face) => /* @__PURE__ */
|
|
12506
|
+
return CUBE_FACES.map((face) => /* @__PURE__ */ jsx22(
|
|
12057
12507
|
PreviewFace,
|
|
12058
12508
|
{
|
|
12059
12509
|
face,
|
|
@@ -12063,28 +12513,7 @@ function PreviewCube({
|
|
|
12063
12513
|
face
|
|
12064
12514
|
));
|
|
12065
12515
|
}
|
|
12066
|
-
|
|
12067
|
-
const [managedState, setManagedState] = useState11(() => ({
|
|
12068
|
-
manager,
|
|
12069
|
-
key,
|
|
12070
|
-
url,
|
|
12071
|
-
snapshot: manager.getSnapshot(key)
|
|
12072
|
-
}));
|
|
12073
|
-
const snapshot = managedState.manager === manager && managedState.key === key && managedState.url === url ? managedState.snapshot : manager.getSnapshot(key);
|
|
12074
|
-
useEffect26(
|
|
12075
|
-
() => manager.acquire(key, url, address, (nextSnapshot) => {
|
|
12076
|
-
setManagedState({
|
|
12077
|
-
manager,
|
|
12078
|
-
key,
|
|
12079
|
-
url,
|
|
12080
|
-
snapshot: nextSnapshot
|
|
12081
|
-
});
|
|
12082
|
-
}),
|
|
12083
|
-
[key, manager, url]
|
|
12084
|
-
);
|
|
12085
|
-
return snapshot;
|
|
12086
|
-
}
|
|
12087
|
-
var TileMesh = memo(function TileMesh2({
|
|
12516
|
+
var TileMesh = memo2(function TileMesh2({
|
|
12088
12517
|
address,
|
|
12089
12518
|
manager,
|
|
12090
12519
|
renderOrder,
|
|
@@ -12098,14 +12527,14 @@ var TileMesh = memo(function TileMesh2({
|
|
|
12098
12527
|
if (!snapshot.texture) {
|
|
12099
12528
|
return null;
|
|
12100
12529
|
}
|
|
12101
|
-
return /* @__PURE__ */
|
|
12530
|
+
return /* @__PURE__ */ jsx22("group", { position: transform.position, rotation: transform.rotation, children: /* @__PURE__ */ jsx22(
|
|
12102
12531
|
"mesh",
|
|
12103
12532
|
{
|
|
12104
12533
|
geometry: SHARED_TILE_GEOMETRY,
|
|
12105
12534
|
position: [layout.x, layout.y, 0],
|
|
12106
12535
|
renderOrder,
|
|
12107
12536
|
scale: [layout.width, layout.height, 1],
|
|
12108
|
-
children: /* @__PURE__ */
|
|
12537
|
+
children: /* @__PURE__ */ jsx22(
|
|
12109
12538
|
PanoBasicMaterial,
|
|
12110
12539
|
{
|
|
12111
12540
|
depthTest: false,
|
|
@@ -12117,12 +12546,12 @@ var TileMesh = memo(function TileMesh2({
|
|
|
12117
12546
|
}
|
|
12118
12547
|
) });
|
|
12119
12548
|
});
|
|
12120
|
-
var TileLayerMeshes =
|
|
12549
|
+
var TileLayerMeshes = memo2(function TileLayerMeshes2({
|
|
12121
12550
|
layer,
|
|
12122
12551
|
manager,
|
|
12123
12552
|
resolveUrl
|
|
12124
12553
|
}) {
|
|
12125
|
-
return layer.addresses.map((address) => /* @__PURE__ */
|
|
12554
|
+
return layer.addresses.map((address) => /* @__PURE__ */ jsx22(
|
|
12126
12555
|
TileMesh,
|
|
12127
12556
|
{
|
|
12128
12557
|
address,
|
|
@@ -12222,8 +12651,8 @@ function parentAddresses(child, parentLevel, parentFaceSize, tileSize) {
|
|
|
12222
12651
|
return addresses;
|
|
12223
12652
|
}
|
|
12224
12653
|
function centerFacingAddress(candidates, camera) {
|
|
12225
|
-
const direction = camera.getWorldDirection(new
|
|
12226
|
-
const center = new
|
|
12654
|
+
const direction = camera.getWorldDirection(new Vector313());
|
|
12655
|
+
const center = new Vector313();
|
|
12227
12656
|
let bestCandidate = candidates[0];
|
|
12228
12657
|
let bestAlignment = -Infinity;
|
|
12229
12658
|
for (const candidate of candidates) {
|
|
@@ -12268,9 +12697,7 @@ function buildLayers(targetLevel, levels, tileSize, frustum, camera, candidatesB
|
|
|
12268
12697
|
}));
|
|
12269
12698
|
}
|
|
12270
12699
|
function layerToken(layers) {
|
|
12271
|
-
return layers.map(
|
|
12272
|
-
(layer) => `${layer.level}:${layer.addresses.map(tileKey).join(",")}`
|
|
12273
|
-
).join("|");
|
|
12700
|
+
return layers.map((layer) => `${layer.level}:${layer.addresses.map(tileKey).join(",")}`).join("|");
|
|
12274
12701
|
}
|
|
12275
12702
|
function Tile({
|
|
12276
12703
|
baseUrl,
|
|
@@ -12290,11 +12717,11 @@ function Tile({
|
|
|
12290
12717
|
onTileError,
|
|
12291
12718
|
onLevelChange
|
|
12292
12719
|
}) {
|
|
12293
|
-
const { camera, gl, size } =
|
|
12294
|
-
const multiresConfig =
|
|
12720
|
+
const { camera, gl, size } = useThree19();
|
|
12721
|
+
const multiresConfig = useMemo20(() => parseMultires(multires), [multires]);
|
|
12295
12722
|
const { levels, tileSize } = multiresConfig;
|
|
12296
12723
|
const multiresToken = `${tileSize}:${levels.join(",")}`;
|
|
12297
|
-
const candidatesByLevel =
|
|
12724
|
+
const candidatesByLevel = useMemo20(
|
|
12298
12725
|
() => buildTileCandidates(levels, tileSize),
|
|
12299
12726
|
[levels, tileSize]
|
|
12300
12727
|
);
|
|
@@ -12306,13 +12733,13 @@ function Tile({
|
|
|
12306
12733
|
onPreviewError
|
|
12307
12734
|
);
|
|
12308
12735
|
const sharedManager = useSharedTileTextureManager();
|
|
12309
|
-
const progressRef =
|
|
12310
|
-
const errorRef =
|
|
12311
|
-
const levelChangeRef =
|
|
12736
|
+
const progressRef = useRef28(onLoadProgress);
|
|
12737
|
+
const errorRef = useRef28(onTileError);
|
|
12738
|
+
const levelChangeRef = useRef28(onLevelChange);
|
|
12312
12739
|
progressRef.current = onLoadProgress;
|
|
12313
12740
|
errorRef.current = onTileError;
|
|
12314
12741
|
levelChangeRef.current = onLevelChange;
|
|
12315
|
-
const ownedManager =
|
|
12742
|
+
const ownedManager = useMemo20(
|
|
12316
12743
|
() => new TileTextureManager({
|
|
12317
12744
|
anisotropy,
|
|
12318
12745
|
maxBytes: Math.max(1, maxTextureMemoryMb) * 1024 * 1024,
|
|
@@ -12333,7 +12760,7 @@ function Tile({
|
|
|
12333
12760
|
]
|
|
12334
12761
|
);
|
|
12335
12762
|
const manager = sharedManager ?? ownedManager;
|
|
12336
|
-
|
|
12763
|
+
useEffect28(() => {
|
|
12337
12764
|
manager.resume();
|
|
12338
12765
|
return () => {
|
|
12339
12766
|
if (manager === ownedManager) {
|
|
@@ -12343,11 +12770,11 @@ function Tile({
|
|
|
12343
12770
|
queueMicrotask(() => manager.releaseUnused());
|
|
12344
12771
|
};
|
|
12345
12772
|
}, [manager, ownedManager]);
|
|
12346
|
-
const readyRef =
|
|
12347
|
-
|
|
12773
|
+
const readyRef = useRef28(false);
|
|
12774
|
+
useEffect28(() => {
|
|
12348
12775
|
readyRef.current = false;
|
|
12349
12776
|
}, [effectivePreviewUrl]);
|
|
12350
|
-
|
|
12777
|
+
useEffect28(() => {
|
|
12351
12778
|
if (!previewTexture || readyRef.current) {
|
|
12352
12779
|
return;
|
|
12353
12780
|
}
|
|
@@ -12355,31 +12782,31 @@ function Tile({
|
|
|
12355
12782
|
onReady?.();
|
|
12356
12783
|
}, [onReady, previewTexture]);
|
|
12357
12784
|
const template = urlTemplate ?? buildDefaultTileUrlTemplate();
|
|
12358
|
-
const resolveUrl =
|
|
12785
|
+
const resolveUrl = useMemo20(
|
|
12359
12786
|
() => (address) => {
|
|
12360
12787
|
const relativePath = resolveTileUrl ? resolveTileUrl(address) : resolveTemplateUrl(template, address);
|
|
12361
12788
|
return resolveRelativeTileUrl(baseUrl, relativePath);
|
|
12362
12789
|
},
|
|
12363
12790
|
[baseUrl, resolveTileUrl, template]
|
|
12364
12791
|
);
|
|
12365
|
-
const [layers, setLayers] =
|
|
12366
|
-
const layerTokenRef =
|
|
12367
|
-
const currentLevelRef =
|
|
12368
|
-
const lastUpdateAtRef =
|
|
12369
|
-
const visibilityDirtyRef =
|
|
12370
|
-
const lastVisibilityQuaternionRef =
|
|
12371
|
-
const lastVisibilityFovRef =
|
|
12372
|
-
const lastViewportRef =
|
|
12373
|
-
const frustumRef =
|
|
12374
|
-
const projectionMatrixRef =
|
|
12375
|
-
const visibilityCameraRef =
|
|
12376
|
-
|
|
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(() => {
|
|
12377
12804
|
currentLevelRef.current = 1;
|
|
12378
12805
|
layerTokenRef.current = "";
|
|
12379
12806
|
visibilityDirtyRef.current = true;
|
|
12380
12807
|
setLayers([]);
|
|
12381
12808
|
}, [manager, multiresToken]);
|
|
12382
|
-
|
|
12809
|
+
useEffect28(() => {
|
|
12383
12810
|
if (loadMode !== "preview") {
|
|
12384
12811
|
return;
|
|
12385
12812
|
}
|
|
@@ -12393,11 +12820,11 @@ function Tile({
|
|
|
12393
12820
|
setLayers(nextLayers);
|
|
12394
12821
|
}
|
|
12395
12822
|
};
|
|
12396
|
-
|
|
12823
|
+
useFrame12(() => {
|
|
12397
12824
|
if (loadMode === "preview") {
|
|
12398
12825
|
return;
|
|
12399
12826
|
}
|
|
12400
|
-
if (!(camera instanceof
|
|
12827
|
+
if (!(camera instanceof PerspectiveCamera5)) {
|
|
12401
12828
|
return;
|
|
12402
12829
|
}
|
|
12403
12830
|
const now = performance.now();
|
|
@@ -12459,15 +12886,9 @@ function Tile({
|
|
|
12459
12886
|
};
|
|
12460
12887
|
commitLayers(nextLayers);
|
|
12461
12888
|
});
|
|
12462
|
-
return /* @__PURE__ */
|
|
12463
|
-
previewTexture ? /* @__PURE__ */
|
|
12464
|
-
|
|
12465
|
-
{
|
|
12466
|
-
texture: previewTexture,
|
|
12467
|
-
faceOrder: previewFaceOrder
|
|
12468
|
-
}
|
|
12469
|
-
) : null,
|
|
12470
|
-
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(
|
|
12471
12892
|
TileLayerMeshes,
|
|
12472
12893
|
{
|
|
12473
12894
|
layer,
|
|
@@ -12480,7 +12901,7 @@ function Tile({
|
|
|
12480
12901
|
}
|
|
12481
12902
|
|
|
12482
12903
|
// src/scenes.tsx
|
|
12483
|
-
import { jsx as
|
|
12904
|
+
import { jsx as jsx23, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
12484
12905
|
function SceneSource({
|
|
12485
12906
|
scene,
|
|
12486
12907
|
visible,
|
|
@@ -12493,7 +12914,7 @@ function SceneSource({
|
|
|
12493
12914
|
}
|
|
12494
12915
|
switch (scene.type) {
|
|
12495
12916
|
case "sphere":
|
|
12496
|
-
return /* @__PURE__ */
|
|
12917
|
+
return /* @__PURE__ */ jsx23(
|
|
12497
12918
|
Sphere,
|
|
12498
12919
|
{
|
|
12499
12920
|
src: scene.src,
|
|
@@ -12506,7 +12927,7 @@ function SceneSource({
|
|
|
12506
12927
|
);
|
|
12507
12928
|
case "tile": {
|
|
12508
12929
|
const { id: _id, type: _type, ...tileProps } = scene;
|
|
12509
|
-
return /* @__PURE__ */
|
|
12930
|
+
return /* @__PURE__ */ jsx23(
|
|
12510
12931
|
Tile,
|
|
12511
12932
|
{
|
|
12512
12933
|
...tileProps,
|
|
@@ -12529,17 +12950,17 @@ function SnapshotCapture({
|
|
|
12529
12950
|
maxPixels,
|
|
12530
12951
|
onCaptured
|
|
12531
12952
|
}) {
|
|
12532
|
-
const { camera, gl, scene, size } =
|
|
12533
|
-
const capturedRequestRef =
|
|
12534
|
-
const renderTargetRef =
|
|
12535
|
-
|
|
12953
|
+
const { camera, gl, scene, size } = useThree20();
|
|
12954
|
+
const capturedRequestRef = useRef29(0);
|
|
12955
|
+
const renderTargetRef = useRef29(null);
|
|
12956
|
+
useEffect29(
|
|
12536
12957
|
() => () => {
|
|
12537
12958
|
renderTargetRef.current?.dispose();
|
|
12538
12959
|
renderTargetRef.current = null;
|
|
12539
12960
|
},
|
|
12540
12961
|
[]
|
|
12541
12962
|
);
|
|
12542
|
-
|
|
12963
|
+
useFrame13(() => {
|
|
12543
12964
|
if (requestId === 0 || requestId === capturedRequestRef.current) {
|
|
12544
12965
|
return;
|
|
12545
12966
|
}
|
|
@@ -12590,48 +13011,48 @@ function ScenesController({
|
|
|
12590
13011
|
}) {
|
|
12591
13012
|
const controlsRef = useContext23(PanoramaViewContext);
|
|
12592
13013
|
const manager = useSharedTileTextureManager();
|
|
12593
|
-
const transition =
|
|
13014
|
+
const transition = useMemo21(
|
|
12594
13015
|
() => resolveTransition(transitionInput),
|
|
12595
13016
|
[transitionInput]
|
|
12596
13017
|
);
|
|
12597
|
-
const sceneMap =
|
|
13018
|
+
const sceneMap = useMemo21(
|
|
12598
13019
|
() => new Map(scenes.map((scene) => [scene.id, scene])),
|
|
12599
13020
|
[scenes]
|
|
12600
13021
|
);
|
|
12601
13022
|
const initialScene = sceneMap.get(activeSceneId) ?? null;
|
|
12602
|
-
const [slots, setSlots] =
|
|
13023
|
+
const [slots, setSlots] = useState14([
|
|
12603
13024
|
initialScene,
|
|
12604
13025
|
null
|
|
12605
13026
|
]);
|
|
12606
|
-
const [activeSlot, setActiveSlot] =
|
|
12607
|
-
const [liveSlot, setLiveSlot] =
|
|
12608
|
-
const [pendingSlot, setPendingSlot] =
|
|
12609
|
-
const [phase, setPhase] =
|
|
12610
|
-
const [captureRequestId, setCaptureRequestId] =
|
|
12611
|
-
const [transitionRunId, setTransitionRunId] =
|
|
12612
|
-
const [snapshot, setSnapshot] =
|
|
12613
|
-
const [recoveryKey, setRecoveryKey] =
|
|
12614
|
-
const requestedSceneIdRef =
|
|
12615
|
-
const captureReasonRef =
|
|
12616
|
-
const interactionReleaseRef =
|
|
12617
|
-
const slotsRef =
|
|
12618
|
-
const phaseRef =
|
|
12619
|
-
const liveSlotRef =
|
|
12620
|
-
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);
|
|
12621
13042
|
slotsRef.current = slots;
|
|
12622
13043
|
phaseRef.current = phase;
|
|
12623
13044
|
if (externalPhaseRef) {
|
|
12624
13045
|
externalPhaseRef.current = phase;
|
|
12625
13046
|
}
|
|
12626
13047
|
liveSlotRef.current = liveSlot;
|
|
12627
|
-
const releaseInteraction =
|
|
13048
|
+
const releaseInteraction = useCallback11(() => {
|
|
12628
13049
|
interactionReleaseRef.current?.();
|
|
12629
13050
|
interactionReleaseRef.current = null;
|
|
12630
13051
|
}, []);
|
|
12631
|
-
const reportError =
|
|
13052
|
+
const reportError = useCallback11((sceneId, error) => {
|
|
12632
13053
|
onTransitionError?.({ sceneId, error });
|
|
12633
13054
|
}, [onTransitionError]);
|
|
12634
|
-
const startPreload =
|
|
13055
|
+
const startPreload = useCallback11((scene) => {
|
|
12635
13056
|
const nextSlot = 1 - liveSlotRef.current;
|
|
12636
13057
|
requestedSceneIdRef.current = scene.id;
|
|
12637
13058
|
setSlots((current) => {
|
|
@@ -12642,7 +13063,7 @@ function ScenesController({
|
|
|
12642
13063
|
setPendingSlot(nextSlot);
|
|
12643
13064
|
setPhase("preloading");
|
|
12644
13065
|
}, []);
|
|
12645
|
-
|
|
13066
|
+
useEffect29(() => {
|
|
12646
13067
|
const requested = sceneMap.get(activeSceneId);
|
|
12647
13068
|
if (!requested) {
|
|
12648
13069
|
reportError(activeSceneId, new Error(`Unknown panorama scene: ${activeSceneId}`));
|
|
@@ -12666,7 +13087,7 @@ function ScenesController({
|
|
|
12666
13087
|
}
|
|
12667
13088
|
startPreload(requested);
|
|
12668
13089
|
}, [activeSceneId, pendingSlot, reportError, sceneMap, startPreload]);
|
|
12669
|
-
const handleReady =
|
|
13090
|
+
const handleReady = useCallback11((slot) => {
|
|
12670
13091
|
if (slot !== pendingSlot || phaseRef.current !== "preloading") {
|
|
12671
13092
|
return;
|
|
12672
13093
|
}
|
|
@@ -12697,7 +13118,7 @@ function ScenesController({
|
|
|
12697
13118
|
setPhase("capturing");
|
|
12698
13119
|
setCaptureRequestId((current) => current + 1);
|
|
12699
13120
|
}, [controlsRef, onTransitionEnd, pendingSlot, transition.preset]);
|
|
12700
|
-
const handleCaptured =
|
|
13121
|
+
const handleCaptured = useCallback11((nextSnapshot) => {
|
|
12701
13122
|
setSnapshot((current) => {
|
|
12702
13123
|
current?.dispose();
|
|
12703
13124
|
return nextSnapshot;
|
|
@@ -12719,7 +13140,7 @@ function ScenesController({
|
|
|
12719
13140
|
setPhase("transitioning");
|
|
12720
13141
|
setTransitionRunId((current) => current + 1);
|
|
12721
13142
|
}, [manager, pendingSlot, sceneMap, startPreload]);
|
|
12722
|
-
const finishTransition =
|
|
13143
|
+
const finishTransition = useCallback11(() => {
|
|
12723
13144
|
const nextSlot = pendingSlot;
|
|
12724
13145
|
const previousScene = transitionFromRef.current;
|
|
12725
13146
|
const nextScene = nextSlot === null ? null : slotsRef.current[nextSlot];
|
|
@@ -12744,12 +13165,12 @@ function ScenesController({
|
|
|
12744
13165
|
});
|
|
12745
13166
|
}
|
|
12746
13167
|
}, [onTransitionEnd, pendingSlot, releaseInteraction, snapshot, transition.preset]);
|
|
12747
|
-
|
|
13168
|
+
useEffect29(() => () => {
|
|
12748
13169
|
releaseInteraction();
|
|
12749
13170
|
snapshot?.dispose();
|
|
12750
13171
|
}, [releaseInteraction, snapshot]);
|
|
12751
|
-
const { gl } =
|
|
12752
|
-
|
|
13172
|
+
const { gl } = useThree20();
|
|
13173
|
+
useEffect29(() => {
|
|
12753
13174
|
const canvas = gl.domElement;
|
|
12754
13175
|
const onContextLost = (event) => {
|
|
12755
13176
|
event.preventDefault();
|
|
@@ -12773,8 +13194,8 @@ function ScenesController({
|
|
|
12773
13194
|
}, [gl, manager, releaseInteraction, snapshot]);
|
|
12774
13195
|
const renderedScene = slots[liveSlot];
|
|
12775
13196
|
const snapshotVisible = snapshot !== null && (phase === "transitioning" || phase === "recapturing" || phase === "preloading");
|
|
12776
|
-
return /* @__PURE__ */
|
|
12777
|
-
/* @__PURE__ */
|
|
13197
|
+
return /* @__PURE__ */ jsxs14(Fragment6, { children: [
|
|
13198
|
+
/* @__PURE__ */ jsx23(
|
|
12778
13199
|
SnapshotCapture,
|
|
12779
13200
|
{
|
|
12780
13201
|
requestId: captureRequestId,
|
|
@@ -12786,7 +13207,7 @@ function ScenesController({
|
|
|
12786
13207
|
const source = slots[slot];
|
|
12787
13208
|
const isLive = slot === liveSlot;
|
|
12788
13209
|
const isPending = slot === pendingSlot;
|
|
12789
|
-
return /* @__PURE__ */
|
|
13210
|
+
return /* @__PURE__ */ jsx23(
|
|
12790
13211
|
SceneSource,
|
|
12791
13212
|
{
|
|
12792
13213
|
scene: source,
|
|
@@ -12802,7 +13223,7 @@ function ScenesController({
|
|
|
12802
13223
|
`${slot}:${source?.id ?? "empty"}:${recoveryKey}`
|
|
12803
13224
|
);
|
|
12804
13225
|
}),
|
|
12805
|
-
snapshotVisible ? /* @__PURE__ */
|
|
13226
|
+
snapshotVisible ? /* @__PURE__ */ jsx23(
|
|
12806
13227
|
TransitionOverlay,
|
|
12807
13228
|
{
|
|
12808
13229
|
snapshot,
|
|
@@ -12825,11 +13246,11 @@ function Scenes({
|
|
|
12825
13246
|
...rest
|
|
12826
13247
|
}) {
|
|
12827
13248
|
const isControlled = controlledId !== void 0;
|
|
12828
|
-
const [internalId, setInternalId] =
|
|
13249
|
+
const [internalId, setInternalId] = useState14(
|
|
12829
13250
|
() => controlledId ?? defaultActiveSceneId ?? scenes[0]?.id ?? ""
|
|
12830
13251
|
);
|
|
12831
13252
|
const resolvedId = isControlled ? controlledId : internalId;
|
|
12832
|
-
const requestSceneChange =
|
|
13253
|
+
const requestSceneChange = useCallback11(
|
|
12833
13254
|
(id) => {
|
|
12834
13255
|
if (isControlled) {
|
|
12835
13256
|
onActiveSceneIdChange?.(id);
|
|
@@ -12839,13 +13260,13 @@ function Scenes({
|
|
|
12839
13260
|
},
|
|
12840
13261
|
[isControlled, onActiveSceneIdChange]
|
|
12841
13262
|
);
|
|
12842
|
-
const scenesRef =
|
|
13263
|
+
const scenesRef = useRef29(scenes);
|
|
12843
13264
|
scenesRef.current = scenes;
|
|
12844
|
-
const resolvedIdRef =
|
|
13265
|
+
const resolvedIdRef = useRef29(resolvedId);
|
|
12845
13266
|
resolvedIdRef.current = resolvedId;
|
|
12846
13267
|
const host = useContext23(ScenesHostContext);
|
|
12847
|
-
const phaseRef =
|
|
12848
|
-
|
|
13268
|
+
const phaseRef = useRef29("idle");
|
|
13269
|
+
useEffect29(() => {
|
|
12849
13270
|
if (!host) {
|
|
12850
13271
|
return;
|
|
12851
13272
|
}
|
|
@@ -12895,12 +13316,12 @@ function Scenes({
|
|
|
12895
13316
|
}
|
|
12896
13317
|
};
|
|
12897
13318
|
}, [host, requestSceneChange]);
|
|
12898
|
-
return /* @__PURE__ */
|
|
13319
|
+
return /* @__PURE__ */ jsx23(
|
|
12899
13320
|
TileTextureManagerProvider,
|
|
12900
13321
|
{
|
|
12901
13322
|
maxTextureMemoryMb,
|
|
12902
13323
|
maxConcurrentLoads: maxConcurrentTileLoads,
|
|
12903
|
-
children: /* @__PURE__ */
|
|
13324
|
+
children: /* @__PURE__ */ jsx23(
|
|
12904
13325
|
ScenesController,
|
|
12905
13326
|
{
|
|
12906
13327
|
...rest,
|
|
@@ -12914,8 +13335,8 @@ function Scenes({
|
|
|
12914
13335
|
}
|
|
12915
13336
|
|
|
12916
13337
|
// src/hotspot/image-hotspot.tsx
|
|
12917
|
-
import { useThree as
|
|
12918
|
-
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";
|
|
12919
13340
|
import {
|
|
12920
13341
|
ClampToEdgeWrapping as ClampToEdgeWrapping3,
|
|
12921
13342
|
LinearFilter as LinearFilter6,
|
|
@@ -12925,35 +13346,35 @@ import {
|
|
|
12925
13346
|
} from "three";
|
|
12926
13347
|
|
|
12927
13348
|
// src/hotspot/hotspot-anchor.tsx
|
|
12928
|
-
import { useFrame as
|
|
13349
|
+
import { useFrame as useFrame14, useThree as useThree21 } from "@react-three/fiber";
|
|
12929
13350
|
import {
|
|
12930
13351
|
useContext as useContext25,
|
|
12931
|
-
useEffect as
|
|
13352
|
+
useEffect as useEffect31,
|
|
12932
13353
|
useLayoutEffect as useLayoutEffect4,
|
|
12933
|
-
useMemo as
|
|
12934
|
-
useRef as
|
|
12935
|
-
useState as
|
|
13354
|
+
useMemo as useMemo23,
|
|
13355
|
+
useRef as useRef30,
|
|
13356
|
+
useState as useState16
|
|
12936
13357
|
} from "react";
|
|
12937
13358
|
import {
|
|
12938
|
-
Box3 as
|
|
13359
|
+
Box3 as Box34,
|
|
12939
13360
|
EdgesGeometry,
|
|
12940
|
-
MathUtils as
|
|
12941
|
-
Matrix4 as
|
|
13361
|
+
MathUtils as MathUtils8,
|
|
13362
|
+
Matrix4 as Matrix44,
|
|
12942
13363
|
Plane,
|
|
12943
13364
|
PlaneGeometry as PlaneGeometry5,
|
|
12944
|
-
PerspectiveCamera as
|
|
13365
|
+
PerspectiveCamera as PerspectiveCamera6,
|
|
12945
13366
|
Quaternion as Quaternion3,
|
|
12946
13367
|
Ray,
|
|
12947
|
-
Vector3 as
|
|
13368
|
+
Vector3 as Vector314
|
|
12948
13369
|
} from "three";
|
|
12949
13370
|
|
|
12950
13371
|
// src/hotspot/hotspot-tooltip.tsx
|
|
12951
|
-
import { useEffect as
|
|
13372
|
+
import { useEffect as useEffect30, useMemo as useMemo22, useState as useState15 } from "react";
|
|
12952
13373
|
|
|
12953
13374
|
// src/webvr/stereo-html.tsx
|
|
12954
13375
|
import { Html } from "@react-three/drei";
|
|
12955
13376
|
import { useContext as useContext24, useSyncExternalStore as useSyncExternalStore7 } from "react";
|
|
12956
|
-
import { Fragment as Fragment7, jsx as
|
|
13377
|
+
import { Fragment as Fragment7, jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
12957
13378
|
function useFallbackStereoView() {
|
|
12958
13379
|
const runtime = useContext24(WebVRRuntimeContext);
|
|
12959
13380
|
const host = runtime?.host ?? null;
|
|
@@ -12978,10 +13399,10 @@ function stereoCalculatePosition(eye, stereoView) {
|
|
|
12978
13399
|
function PanoHtml({ children, ...htmlProps }) {
|
|
12979
13400
|
const stereoView = useFallbackStereoView();
|
|
12980
13401
|
if (!stereoView) {
|
|
12981
|
-
return /* @__PURE__ */
|
|
13402
|
+
return /* @__PURE__ */ jsx24(Html, { ...htmlProps, children });
|
|
12982
13403
|
}
|
|
12983
|
-
return /* @__PURE__ */
|
|
12984
|
-
/* @__PURE__ */
|
|
13404
|
+
return /* @__PURE__ */ jsxs15(Fragment7, { children: [
|
|
13405
|
+
/* @__PURE__ */ jsx24(
|
|
12985
13406
|
Html,
|
|
12986
13407
|
{
|
|
12987
13408
|
...htmlProps,
|
|
@@ -12989,7 +13410,7 @@ function PanoHtml({ children, ...htmlProps }) {
|
|
|
12989
13410
|
children
|
|
12990
13411
|
}
|
|
12991
13412
|
),
|
|
12992
|
-
/* @__PURE__ */
|
|
13413
|
+
/* @__PURE__ */ jsx24(
|
|
12993
13414
|
Html,
|
|
12994
13415
|
{
|
|
12995
13416
|
...htmlProps,
|
|
@@ -13002,7 +13423,7 @@ function PanoHtml({ children, ...htmlProps }) {
|
|
|
13002
13423
|
}
|
|
13003
13424
|
|
|
13004
13425
|
// src/hotspot/hotspot-tooltip.tsx
|
|
13005
|
-
import { jsx as
|
|
13426
|
+
import { jsx as jsx25, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
13006
13427
|
var DEFAULT_HOTSPOT_TOOLTIP_OFFSET = 12;
|
|
13007
13428
|
var DEFAULT_HOTSPOT_TOOLTIP_APPEARANCE = {
|
|
13008
13429
|
background: "rgba(22, 22, 22, 0.72)",
|
|
@@ -13011,7 +13432,10 @@ var DEFAULT_HOTSPOT_TOOLTIP_APPEARANCE = {
|
|
|
13011
13432
|
borderRadius: 8,
|
|
13012
13433
|
shadow: "0 8px 24px rgba(0, 0, 0, 0.35)",
|
|
13013
13434
|
padding: 8,
|
|
13014
|
-
fontSize: 12
|
|
13435
|
+
fontSize: 12,
|
|
13436
|
+
fontFamily: "inherit",
|
|
13437
|
+
lineHeight: 1.4,
|
|
13438
|
+
letterSpacing: "normal"
|
|
13015
13439
|
};
|
|
13016
13440
|
var WRAPPER_STYLE = {
|
|
13017
13441
|
pointerEvents: "none"
|
|
@@ -13071,16 +13495,16 @@ function HotspotTooltip({
|
|
|
13071
13495
|
offset = DEFAULT_HOTSPOT_TOOLTIP_OFFSET,
|
|
13072
13496
|
appearance
|
|
13073
13497
|
}) {
|
|
13074
|
-
const [imageFailed, setImageFailed] =
|
|
13075
|
-
|
|
13498
|
+
const [imageFailed, setImageFailed] = useState15(false);
|
|
13499
|
+
useEffect30(() => {
|
|
13076
13500
|
setImageFailed(false);
|
|
13077
13501
|
}, [content.image]);
|
|
13078
13502
|
const showImage = Boolean(content.image) && !imageFailed;
|
|
13079
|
-
const resolvedAppearance =
|
|
13503
|
+
const resolvedAppearance = useMemo22(
|
|
13080
13504
|
() => resolveHotspotTooltipAppearance(appearance),
|
|
13081
13505
|
[appearance]
|
|
13082
13506
|
);
|
|
13083
|
-
const bubbleStyle =
|
|
13507
|
+
const bubbleStyle = useMemo22(
|
|
13084
13508
|
() => ({
|
|
13085
13509
|
background: resolvedAppearance.background,
|
|
13086
13510
|
border: resolvedAppearance.border,
|
|
@@ -13088,6 +13512,9 @@ function HotspotTooltip({
|
|
|
13088
13512
|
boxShadow: resolvedAppearance.shadow,
|
|
13089
13513
|
color: resolvedAppearance.color,
|
|
13090
13514
|
fontSize: toCssLength(resolvedAppearance.fontSize),
|
|
13515
|
+
fontFamily: resolvedAppearance.fontFamily,
|
|
13516
|
+
lineHeight: resolvedAppearance.lineHeight,
|
|
13517
|
+
letterSpacing: resolvedAppearance.letterSpacing,
|
|
13091
13518
|
padding: toCssLength(resolvedAppearance.padding),
|
|
13092
13519
|
transform: tooltipBubbleTransform(
|
|
13093
13520
|
placement,
|
|
@@ -13099,30 +13526,33 @@ function HotspotTooltip({
|
|
|
13099
13526
|
if (!showImage && !content.text) {
|
|
13100
13527
|
return null;
|
|
13101
13528
|
}
|
|
13102
|
-
return /* @__PURE__ */
|
|
13103
|
-
|
|
13104
|
-
|
|
13105
|
-
|
|
13106
|
-
|
|
13107
|
-
|
|
13108
|
-
|
|
13109
|
-
|
|
13110
|
-
|
|
13111
|
-
|
|
13112
|
-
|
|
13113
|
-
|
|
13114
|
-
|
|
13115
|
-
|
|
13116
|
-
|
|
13117
|
-
|
|
13118
|
-
|
|
13119
|
-
|
|
13120
|
-
|
|
13121
|
-
|
|
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
|
+
] }) });
|
|
13122
13552
|
}
|
|
13123
13553
|
|
|
13124
13554
|
// src/hotspot/hotspot-anchor.tsx
|
|
13125
|
-
import { jsx as
|
|
13555
|
+
import { jsx as jsx26, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
13126
13556
|
var DEFAULT_FLOATING_DISTANCE = 10;
|
|
13127
13557
|
var PANORAMA_RADIUS = DEFAULT_PANORAMA_RADIUS;
|
|
13128
13558
|
var PANORAMA_SURFACE_INSET = 4;
|
|
@@ -13130,28 +13560,28 @@ var DEFAULT_REFERENCE_FOV = 75;
|
|
|
13130
13560
|
var MIN_ANGULAR_SIZE = 0.01;
|
|
13131
13561
|
var MAX_ANGULAR_SIZE = 179;
|
|
13132
13562
|
var DRAG_EPSILON_DEGREES = 1e-3;
|
|
13133
|
-
var LOCAL_FORWARD = new
|
|
13134
|
-
var TOOLTIP_WORLD_BOX = new
|
|
13135
|
-
var TOOLTIP_LOCAL_BOX = new
|
|
13136
|
-
var TOOLTIP_CORNER = new
|
|
13137
|
-
var TOOLTIP_INVERSE = new
|
|
13138
|
-
var TOOLTIP_WORLD_CORNER = new
|
|
13139
|
-
var TOOLTIP_PROJECTED = new
|
|
13140
|
-
var TOOLTIP_RAY_ORIGIN = new
|
|
13141
|
-
var TOOLTIP_RAY_FAR = new
|
|
13142
|
-
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();
|
|
13143
13573
|
var TOOLTIP_RAY = new Ray();
|
|
13144
13574
|
var TOOLTIP_PLANE = new Plane();
|
|
13145
|
-
var TOOLTIP_INTERSECTION = new
|
|
13146
|
-
var TOOLTIP_PLANE_NORMAL = new
|
|
13147
|
-
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();
|
|
13148
13578
|
var HOTSPOT_MODE_RENDERING = {
|
|
13149
13579
|
surface: { orientation: "surface", placement: "surface" },
|
|
13150
13580
|
billboard: { orientation: "billboard", placement: "floating" }
|
|
13151
13581
|
};
|
|
13152
13582
|
function angularSizeToWorldSize(size, radius) {
|
|
13153
|
-
const safeSize = Number.isFinite(size) ?
|
|
13154
|
-
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);
|
|
13155
13585
|
}
|
|
13156
13586
|
function resolveScale(scale) {
|
|
13157
13587
|
return Number.isFinite(scale) && scale > 0 ? scale : 1;
|
|
@@ -13164,7 +13594,7 @@ function resolveDistance(placement, distance, width, height) {
|
|
|
13164
13594
|
if (!Number.isFinite(distance)) {
|
|
13165
13595
|
return DEFAULT_FLOATING_DISTANCE;
|
|
13166
13596
|
}
|
|
13167
|
-
return
|
|
13597
|
+
return MathUtils8.clamp(Math.abs(distance), 0.1, maximumDistance);
|
|
13168
13598
|
}
|
|
13169
13599
|
function applyHotspotTransform(group, camera, orientation2, surfaceQuaternion3, rotation, scaleMode, referenceFov, useAngularScale, worldWidth, worldHeight) {
|
|
13170
13600
|
if (orientation2 === "billboard") {
|
|
@@ -13172,8 +13602,8 @@ function applyHotspotTransform(group, camera, orientation2, surfaceQuaternion3,
|
|
|
13172
13602
|
} else {
|
|
13173
13603
|
group.quaternion.copy(surfaceQuaternion3);
|
|
13174
13604
|
}
|
|
13175
|
-
group.rotateOnAxis(LOCAL_FORWARD,
|
|
13176
|
-
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;
|
|
13177
13607
|
group.scale.set(
|
|
13178
13608
|
(useAngularScale ? worldWidth : 1) * scaleFactor,
|
|
13179
13609
|
(useAngularScale ? worldHeight : 1) * scaleFactor,
|
|
@@ -13182,39 +13612,39 @@ function applyHotspotTransform(group, camera, orientation2, surfaceQuaternion3,
|
|
|
13182
13612
|
group.updateMatrixWorld();
|
|
13183
13613
|
}
|
|
13184
13614
|
function maximumHotspotDistance(width, height) {
|
|
13185
|
-
const safeWidth =
|
|
13615
|
+
const safeWidth = MathUtils8.clamp(
|
|
13186
13616
|
Math.abs(Number.isFinite(width) ? width : MIN_ANGULAR_SIZE),
|
|
13187
13617
|
MIN_ANGULAR_SIZE,
|
|
13188
13618
|
MAX_ANGULAR_SIZE
|
|
13189
13619
|
);
|
|
13190
|
-
const safeHeight =
|
|
13620
|
+
const safeHeight = MathUtils8.clamp(
|
|
13191
13621
|
Math.abs(Number.isFinite(height) ? height : MIN_ANGULAR_SIZE),
|
|
13192
13622
|
MIN_ANGULAR_SIZE,
|
|
13193
13623
|
MAX_ANGULAR_SIZE
|
|
13194
13624
|
);
|
|
13195
13625
|
const cornerFactor = Math.hypot(
|
|
13196
13626
|
1,
|
|
13197
|
-
Math.tan(
|
|
13198
|
-
Math.tan(
|
|
13627
|
+
Math.tan(MathUtils8.degToRad(safeWidth) / 2),
|
|
13628
|
+
Math.tan(MathUtils8.degToRad(safeHeight) / 2)
|
|
13199
13629
|
);
|
|
13200
13630
|
return (PANORAMA_RADIUS - PANORAMA_SURFACE_INSET) / cornerFactor;
|
|
13201
13631
|
}
|
|
13202
13632
|
function fixedScaleFactor(cameraFov, referenceFov) {
|
|
13203
|
-
const safeReferenceFov =
|
|
13204
|
-
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);
|
|
13205
13635
|
}
|
|
13206
13636
|
function createSurfaceQuaternion(position) {
|
|
13207
13637
|
const outward = panoPositionToVector3(position).normalize();
|
|
13208
13638
|
const inward = outward.clone().negate();
|
|
13209
|
-
const pitch =
|
|
13210
|
-
const yaw =
|
|
13211
|
-
const localUp = new
|
|
13639
|
+
const pitch = MathUtils8.degToRad(position.pitch);
|
|
13640
|
+
const yaw = MathUtils8.degToRad(position.yaw);
|
|
13641
|
+
const localUp = new Vector314(
|
|
13212
13642
|
-Math.sin(pitch) * Math.sin(yaw),
|
|
13213
13643
|
Math.cos(pitch),
|
|
13214
13644
|
Math.sin(pitch) * Math.cos(yaw)
|
|
13215
13645
|
).normalize();
|
|
13216
13646
|
const localRight = localUp.clone().cross(inward).normalize();
|
|
13217
|
-
const basis = new
|
|
13647
|
+
const basis = new Matrix44().makeBasis(localRight, localUp, inward);
|
|
13218
13648
|
return new Quaternion3().setFromRotationMatrix(basis);
|
|
13219
13649
|
}
|
|
13220
13650
|
function makeInteractionEvent(id, position, event) {
|
|
@@ -13228,7 +13658,7 @@ function makeInteractionEvent(id, position, event) {
|
|
|
13228
13658
|
function angularDistance(a, b) {
|
|
13229
13659
|
const aVector = panoPositionToVector3(a);
|
|
13230
13660
|
const bVector = panoPositionToVector3(b);
|
|
13231
|
-
return
|
|
13661
|
+
return MathUtils8.radToDeg(aVector.angleTo(bVector));
|
|
13232
13662
|
}
|
|
13233
13663
|
function isTooltipOpen(trigger, hovered, focused, pinned) {
|
|
13234
13664
|
switch (trigger) {
|
|
@@ -13463,20 +13893,20 @@ function HotspotAnchor({
|
|
|
13463
13893
|
const hotspotTargetRegistry = useContext25(HotspotTargetRegistryContext);
|
|
13464
13894
|
const eventBus = useContext25(PanoEventBusContext);
|
|
13465
13895
|
const cursorApi = usePanoCursor();
|
|
13466
|
-
const { camera, size } =
|
|
13467
|
-
const groupRef =
|
|
13468
|
-
const tooltipAnchorRef =
|
|
13469
|
-
const dragStateRef =
|
|
13470
|
-
const suppressNextClickRef =
|
|
13471
|
-
const [hovered, setHovered] =
|
|
13472
|
-
const [dragging, setDragging] =
|
|
13473
|
-
const [pinned, setPinned] =
|
|
13474
|
-
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(
|
|
13475
13905
|
() => resolveHotspotTooltipContent(tooltip),
|
|
13476
13906
|
[tooltip]
|
|
13477
13907
|
);
|
|
13478
13908
|
const normalizedPosition = normalizePanoPosition(position);
|
|
13479
|
-
|
|
13909
|
+
useEffect31(() => {
|
|
13480
13910
|
if (!hotspotTargetRegistry) {
|
|
13481
13911
|
return;
|
|
13482
13912
|
}
|
|
@@ -13493,17 +13923,17 @@ function HotspotAnchor({
|
|
|
13493
13923
|
scaledWidth,
|
|
13494
13924
|
scaledHeight
|
|
13495
13925
|
);
|
|
13496
|
-
const worldPosition =
|
|
13926
|
+
const worldPosition = useMemo23(
|
|
13497
13927
|
() => panoPositionToVector3(normalizedPosition, resolvedDistance),
|
|
13498
13928
|
[normalizedPosition.pitch, normalizedPosition.yaw, resolvedDistance]
|
|
13499
13929
|
);
|
|
13500
|
-
const surfaceQuaternion3 =
|
|
13930
|
+
const surfaceQuaternion3 = useMemo23(
|
|
13501
13931
|
() => createSurfaceQuaternion(normalizedPosition),
|
|
13502
13932
|
[normalizedPosition.pitch, normalizedPosition.yaw]
|
|
13503
13933
|
);
|
|
13504
13934
|
const worldWidth = angularSizeToWorldSize(scaledWidth, resolvedDistance);
|
|
13505
13935
|
const worldHeight = angularSizeToWorldSize(scaledHeight, resolvedDistance);
|
|
13506
|
-
const focusGeometry =
|
|
13936
|
+
const focusGeometry = useMemo23(() => {
|
|
13507
13937
|
const planeGeometry = new PlaneGeometry5(1, 1);
|
|
13508
13938
|
const geometry = new EdgesGeometry(planeGeometry);
|
|
13509
13939
|
planeGeometry.dispose();
|
|
@@ -13530,14 +13960,14 @@ function HotspotAnchor({
|
|
|
13530
13960
|
});
|
|
13531
13961
|
const tooltipOpen = visible && tooltipContent !== null && isTooltipOpen(tooltipTrigger, hovered, focused, pinned);
|
|
13532
13962
|
const cursorClaimId = hotspotCursorClaimId(id);
|
|
13533
|
-
|
|
13963
|
+
useEffect31(
|
|
13534
13964
|
() => () => {
|
|
13535
13965
|
dragStateRef.current?.releaseInteractionLock();
|
|
13536
13966
|
dragStateRef.current = null;
|
|
13537
13967
|
},
|
|
13538
13968
|
[]
|
|
13539
13969
|
);
|
|
13540
|
-
|
|
13970
|
+
useEffect31(() => {
|
|
13541
13971
|
if (!cursorApi) {
|
|
13542
13972
|
return;
|
|
13543
13973
|
}
|
|
@@ -13559,14 +13989,14 @@ function HotspotAnchor({
|
|
|
13559
13989
|
hovered,
|
|
13560
13990
|
visible
|
|
13561
13991
|
]);
|
|
13562
|
-
|
|
13992
|
+
useEffect31(
|
|
13563
13993
|
() => () => {
|
|
13564
13994
|
cursorApi?.release(cursorClaimId);
|
|
13565
13995
|
},
|
|
13566
13996
|
[cursorApi, cursorClaimId]
|
|
13567
13997
|
);
|
|
13568
|
-
|
|
13569
|
-
|
|
13998
|
+
useEffect31(() => () => focusGeometry.dispose(), [focusGeometry]);
|
|
13999
|
+
useEffect31(() => {
|
|
13570
14000
|
if (tooltipTrigger !== "click") {
|
|
13571
14001
|
setPinned(false);
|
|
13572
14002
|
return;
|
|
@@ -13575,12 +14005,12 @@ function HotspotAnchor({
|
|
|
13575
14005
|
setPinned(false);
|
|
13576
14006
|
});
|
|
13577
14007
|
}, [eventBus, tooltipTrigger]);
|
|
13578
|
-
|
|
14008
|
+
useEffect31(() => {
|
|
13579
14009
|
if (tooltipTrigger !== "hover") {
|
|
13580
14010
|
setHovered(false);
|
|
13581
14011
|
}
|
|
13582
14012
|
}, [tooltipTrigger]);
|
|
13583
|
-
|
|
14013
|
+
useEffect31(() => {
|
|
13584
14014
|
if (acceptsPointer) {
|
|
13585
14015
|
return;
|
|
13586
14016
|
}
|
|
@@ -13634,7 +14064,7 @@ function HotspotAnchor({
|
|
|
13634
14064
|
worldHeight,
|
|
13635
14065
|
worldWidth
|
|
13636
14066
|
]);
|
|
13637
|
-
|
|
14067
|
+
useFrame14((state) => {
|
|
13638
14068
|
const group = groupRef.current;
|
|
13639
14069
|
if (!group) {
|
|
13640
14070
|
return;
|
|
@@ -13692,7 +14122,7 @@ function HotspotAnchor({
|
|
|
13692
14122
|
setHovered(true);
|
|
13693
14123
|
}
|
|
13694
14124
|
};
|
|
13695
|
-
return /* @__PURE__ */
|
|
14125
|
+
return /* @__PURE__ */ jsxs17(
|
|
13696
14126
|
"group",
|
|
13697
14127
|
{
|
|
13698
14128
|
ref: groupRef,
|
|
@@ -13769,18 +14199,18 @@ function HotspotAnchor({
|
|
|
13769
14199
|
} : void 0,
|
|
13770
14200
|
onPointerUp: acceptsPointer ? (event) => releasePointer(event, true) : void 0,
|
|
13771
14201
|
children: [
|
|
13772
|
-
focused ? focusContent ?? /* @__PURE__ */
|
|
14202
|
+
focused ? focusContent ?? /* @__PURE__ */ jsx26(
|
|
13773
14203
|
"lineSegments",
|
|
13774
14204
|
{
|
|
13775
14205
|
geometry: focusGeometry,
|
|
13776
14206
|
position: [0, 0, 0.01],
|
|
13777
14207
|
renderOrder: renderOrder + 1,
|
|
13778
14208
|
scale: [1.12, 1.12, 1],
|
|
13779
|
-
children: /* @__PURE__ */
|
|
14209
|
+
children: /* @__PURE__ */ jsx26("lineBasicMaterial", { color: "#f5fbfc", depthTest: false })
|
|
13780
14210
|
}
|
|
13781
14211
|
) : null,
|
|
13782
14212
|
children,
|
|
13783
|
-
tooltipOpen && tooltipContent ? /* @__PURE__ */
|
|
14213
|
+
tooltipOpen && tooltipContent ? /* @__PURE__ */ jsx26("group", { ref: tooltipAnchorRef, children: /* @__PURE__ */ jsx26(
|
|
13784
14214
|
HotspotTooltip,
|
|
13785
14215
|
{
|
|
13786
14216
|
appearance: tooltipAppearance,
|
|
@@ -13801,7 +14231,7 @@ import {
|
|
|
13801
14231
|
MeshBasicMaterial,
|
|
13802
14232
|
Vector2 as Vector26
|
|
13803
14233
|
} from "three";
|
|
13804
|
-
import { jsx as
|
|
14234
|
+
import { jsx as jsx27, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
13805
14235
|
var HOTSPOT_ALPHA_CUTOFF = 0.05;
|
|
13806
14236
|
var SAMPLE_UV = new Vector26();
|
|
13807
14237
|
var RAYCAST_HITS = [];
|
|
@@ -13903,11 +14333,12 @@ function HotspotPlane({
|
|
|
13903
14333
|
map,
|
|
13904
14334
|
opacity
|
|
13905
14335
|
}) {
|
|
13906
|
-
return /* @__PURE__ */
|
|
13907
|
-
/* @__PURE__ */
|
|
13908
|
-
/* @__PURE__ */
|
|
13909
|
-
|
|
14336
|
+
return /* @__PURE__ */ jsxs18("mesh", { raycast: hotspotPlaneRaycast, children: [
|
|
14337
|
+
/* @__PURE__ */ jsx27("planeGeometry", { args: [1, 1] }),
|
|
14338
|
+
/* @__PURE__ */ jsx27(
|
|
14339
|
+
PanoBasicMaterial,
|
|
13910
14340
|
{
|
|
14341
|
+
target: "hotspot",
|
|
13911
14342
|
alphaTest: HOTSPOT_ALPHA_CUTOFF,
|
|
13912
14343
|
alphaToCoverage: true,
|
|
13913
14344
|
map,
|
|
@@ -13921,15 +14352,15 @@ function HotspotPlane({
|
|
|
13921
14352
|
}
|
|
13922
14353
|
|
|
13923
14354
|
// src/hotspot/image-hotspot.tsx
|
|
13924
|
-
import { jsx as
|
|
14355
|
+
import { jsx as jsx28 } from "react/jsx-runtime";
|
|
13925
14356
|
function useHotspotImageTexture(src, onLoad, onError) {
|
|
13926
|
-
const gl =
|
|
13927
|
-
const [texture, setTexture] =
|
|
13928
|
-
const onLoadRef =
|
|
13929
|
-
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);
|
|
13930
14361
|
onLoadRef.current = onLoad;
|
|
13931
14362
|
onErrorRef.current = onError;
|
|
13932
|
-
|
|
14363
|
+
useEffect32(() => {
|
|
13933
14364
|
let active = true;
|
|
13934
14365
|
setTexture(null);
|
|
13935
14366
|
if (!src) {
|
|
@@ -13967,7 +14398,7 @@ function useHotspotImageTexture(src, onLoad, onError) {
|
|
|
13967
14398
|
active = false;
|
|
13968
14399
|
};
|
|
13969
14400
|
}, [gl, src]);
|
|
13970
|
-
|
|
14401
|
+
useEffect32(
|
|
13971
14402
|
() => () => {
|
|
13972
14403
|
texture?.dispose();
|
|
13973
14404
|
},
|
|
@@ -13985,33 +14416,33 @@ function ImageHotspot({
|
|
|
13985
14416
|
...anchorProps
|
|
13986
14417
|
}) {
|
|
13987
14418
|
const texture = useHotspotImageTexture(src, onLoad, onError);
|
|
13988
|
-
return /* @__PURE__ */
|
|
14419
|
+
return /* @__PURE__ */ jsx28(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ jsx28(HotspotPlane, { map: texture, opacity }) });
|
|
13989
14420
|
}
|
|
13990
14421
|
|
|
13991
14422
|
// src/hotspot/polygon-hotspot.tsx
|
|
13992
|
-
import { useEffect as
|
|
14423
|
+
import { useEffect as useEffect33, useMemo as useMemo24, useRef as useRef33 } from "react";
|
|
13993
14424
|
import {
|
|
13994
|
-
BufferGeometry,
|
|
14425
|
+
BufferGeometry as BufferGeometry2,
|
|
13995
14426
|
DoubleSide as DoubleSide5,
|
|
13996
|
-
Float32BufferAttribute,
|
|
13997
|
-
Matrix4 as
|
|
14427
|
+
Float32BufferAttribute as Float32BufferAttribute2,
|
|
14428
|
+
Matrix4 as Matrix45,
|
|
13998
14429
|
Quaternion as Quaternion4,
|
|
13999
14430
|
ShapeUtils,
|
|
14000
14431
|
Vector2 as Vector27,
|
|
14001
|
-
Vector3 as
|
|
14432
|
+
Vector3 as Vector316
|
|
14002
14433
|
} from "three";
|
|
14003
14434
|
|
|
14004
14435
|
// src/hotspot/hotspot-stroke-line.tsx
|
|
14005
14436
|
import { Line } from "@react-three/drei";
|
|
14006
|
-
import { useFrame as
|
|
14007
|
-
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";
|
|
14008
14439
|
import {
|
|
14009
|
-
MathUtils as
|
|
14010
|
-
PerspectiveCamera as
|
|
14011
|
-
Vector3 as
|
|
14440
|
+
MathUtils as MathUtils9,
|
|
14441
|
+
PerspectiveCamera as PerspectiveCamera7,
|
|
14442
|
+
Vector3 as Vector315
|
|
14012
14443
|
} from "three";
|
|
14013
|
-
import { jsx as
|
|
14014
|
-
var LINE_WORLD_POSITION = new
|
|
14444
|
+
import { jsx as jsx29 } from "react/jsx-runtime";
|
|
14445
|
+
var LINE_WORLD_POSITION = new Vector315();
|
|
14015
14446
|
function applyScreenSpaceDashScale(object, camera, viewportHeight) {
|
|
14016
14447
|
const material = object?.material;
|
|
14017
14448
|
if (!object || typeof material?.dashScale !== "number") {
|
|
@@ -14019,8 +14450,8 @@ function applyScreenSpaceDashScale(object, camera, viewportHeight) {
|
|
|
14019
14450
|
}
|
|
14020
14451
|
object.getWorldPosition(LINE_WORLD_POSITION);
|
|
14021
14452
|
const depth = Math.max(camera.position.distanceTo(LINE_WORLD_POSITION), 1);
|
|
14022
|
-
const fov = camera instanceof
|
|
14023
|
-
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);
|
|
14024
14455
|
}
|
|
14025
14456
|
function resolveDash(dashSize, gapSize) {
|
|
14026
14457
|
if (dashSize === void 0 || !Number.isFinite(dashSize) || dashSize <= 0) {
|
|
@@ -14041,8 +14472,8 @@ function HotspotStrokeLine({
|
|
|
14041
14472
|
dashSize,
|
|
14042
14473
|
gapSize
|
|
14043
14474
|
}) {
|
|
14044
|
-
const lineRef =
|
|
14045
|
-
const { camera, size } =
|
|
14475
|
+
const lineRef = useRef32(null);
|
|
14476
|
+
const { camera, size } = useThree23();
|
|
14046
14477
|
const dash = resolveDash(dashSize, gapSize);
|
|
14047
14478
|
useLayoutEffect5(() => {
|
|
14048
14479
|
if (!dash.dashed) {
|
|
@@ -14050,13 +14481,13 @@ function HotspotStrokeLine({
|
|
|
14050
14481
|
}
|
|
14051
14482
|
applyScreenSpaceDashScale(lineRef.current, camera, size.height);
|
|
14052
14483
|
}, [camera, dash.dashed, dash.dashSize, dash.gapSize, size.height]);
|
|
14053
|
-
|
|
14484
|
+
useFrame15((state) => {
|
|
14054
14485
|
if (!dash.dashed) {
|
|
14055
14486
|
return;
|
|
14056
14487
|
}
|
|
14057
14488
|
applyScreenSpaceDashScale(lineRef.current, state.camera, state.size.height);
|
|
14058
14489
|
});
|
|
14059
|
-
return /* @__PURE__ */
|
|
14490
|
+
return /* @__PURE__ */ jsx29(
|
|
14060
14491
|
Line,
|
|
14061
14492
|
{
|
|
14062
14493
|
ref: lineRef,
|
|
@@ -14078,7 +14509,7 @@ function HotspotStrokeLine({
|
|
|
14078
14509
|
}
|
|
14079
14510
|
|
|
14080
14511
|
// src/hotspot/polygon-hotspot.tsx
|
|
14081
|
-
import { jsx as
|
|
14512
|
+
import { jsx as jsx30, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
14082
14513
|
var POLYGON_RADIUS = 990;
|
|
14083
14514
|
var MAX_FILL_SEGMENT_DEGREES = 7;
|
|
14084
14515
|
function cloneVertices(vertices) {
|
|
@@ -14150,7 +14581,7 @@ function polygonContainsDirection(vertices, direction) {
|
|
|
14150
14581
|
}
|
|
14151
14582
|
function fitsHemisphere(vertices) {
|
|
14152
14583
|
const directions = vertices.map((vertex) => panoPositionToVector3(vertex).normalize());
|
|
14153
|
-
const candidates = [new
|
|
14584
|
+
const candidates = [new Vector316()];
|
|
14154
14585
|
for (const direction of directions) {
|
|
14155
14586
|
candidates[0].add(direction);
|
|
14156
14587
|
candidates.push(direction.clone());
|
|
@@ -14174,7 +14605,7 @@ function validatePolygonVertices(vertices) {
|
|
|
14174
14605
|
if (hasSelfIntersection(unwrapped)) {
|
|
14175
14606
|
issues.push({ code: "self_intersection", message: "Polygon edges cannot cross." });
|
|
14176
14607
|
}
|
|
14177
|
-
if (polygonContainsDirection(normalized, new
|
|
14608
|
+
if (polygonContainsDirection(normalized, new Vector316(0, 1, 0)) || polygonContainsDirection(normalized, new Vector316(0, -1, 0))) {
|
|
14178
14609
|
issues.push({ code: "contains_pole", message: "Polygons cannot contain a panorama pole." });
|
|
14179
14610
|
}
|
|
14180
14611
|
if (!fitsHemisphere(normalized)) {
|
|
@@ -14185,7 +14616,7 @@ function validatePolygonVertices(vertices) {
|
|
|
14185
14616
|
function polygonCenter(vertices) {
|
|
14186
14617
|
const sum = vertices.reduce(
|
|
14187
14618
|
(total, vertex) => total.add(panoPositionToVector3(vertex).normalize()),
|
|
14188
|
-
new
|
|
14619
|
+
new Vector316()
|
|
14189
14620
|
);
|
|
14190
14621
|
return sum.lengthSq() > 1e-8 ? vector3ToPanoPosition(sum) : normalizePanoPosition(vertices[0]);
|
|
14191
14622
|
}
|
|
@@ -14194,20 +14625,20 @@ function surfaceQuaternion(position) {
|
|
|
14194
14625
|
const inward = outward.clone().negate();
|
|
14195
14626
|
const pitch = position.pitch * Math.PI / 180;
|
|
14196
14627
|
const yaw = position.yaw * Math.PI / 180;
|
|
14197
|
-
const localUp = new
|
|
14628
|
+
const localUp = new Vector316(
|
|
14198
14629
|
-Math.sin(pitch) * Math.sin(yaw),
|
|
14199
14630
|
Math.cos(pitch),
|
|
14200
14631
|
Math.sin(pitch) * Math.cos(yaw)
|
|
14201
14632
|
).normalize();
|
|
14202
14633
|
return new Quaternion4().setFromRotationMatrix(
|
|
14203
|
-
new
|
|
14634
|
+
new Matrix45().makeBasis(localUp.clone().cross(inward).normalize(), localUp, inward)
|
|
14204
14635
|
);
|
|
14205
14636
|
}
|
|
14206
14637
|
function makeWorldToLocal(center) {
|
|
14207
|
-
return new
|
|
14638
|
+
return new Matrix45().compose(
|
|
14208
14639
|
panoPositionToVector3(center, POLYGON_RADIUS),
|
|
14209
14640
|
surfaceQuaternion(center),
|
|
14210
|
-
new
|
|
14641
|
+
new Vector316(1, 1, 1)
|
|
14211
14642
|
).invert();
|
|
14212
14643
|
}
|
|
14213
14644
|
function projectedPoint(a, b, c, weightB, weightC, radius, worldToLocal) {
|
|
@@ -14279,7 +14710,7 @@ function makeFillGeometry(vertices, center) {
|
|
|
14279
14710
|
steps
|
|
14280
14711
|
);
|
|
14281
14712
|
}
|
|
14282
|
-
return new
|
|
14713
|
+
return new BufferGeometry2().setAttribute("position", new Float32BufferAttribute2(positions, 3)).setIndex(indices);
|
|
14283
14714
|
}
|
|
14284
14715
|
function makeStrokePositions(vertices, center) {
|
|
14285
14716
|
const points = [];
|
|
@@ -14334,24 +14765,24 @@ function PolygonHotspot({
|
|
|
14334
14765
|
onInvalid,
|
|
14335
14766
|
...anchorProps
|
|
14336
14767
|
}) {
|
|
14337
|
-
const issues =
|
|
14768
|
+
const issues = useMemo24(() => validatePolygonVertices(vertices), [vertices]);
|
|
14338
14769
|
const valid = issues.length === 0;
|
|
14339
|
-
const center =
|
|
14340
|
-
const fillGeometry =
|
|
14770
|
+
const center = useMemo24(() => valid ? polygonCenter(vertices) : null, [valid, vertices]);
|
|
14771
|
+
const fillGeometry = useMemo24(
|
|
14341
14772
|
() => valid && center ? makeFillGeometry(vertices, center) : null,
|
|
14342
14773
|
[center, valid, vertices]
|
|
14343
14774
|
);
|
|
14344
|
-
const strokePoints =
|
|
14775
|
+
const strokePoints = useMemo24(
|
|
14345
14776
|
() => valid && center ? makeStrokePositions(vertices, center) : null,
|
|
14346
14777
|
[center, valid, vertices]
|
|
14347
14778
|
);
|
|
14348
14779
|
const resolvedStrokeOpacity = Math.max(0, Math.min(strokeOpacity, 1));
|
|
14349
|
-
const startVerticesRef =
|
|
14780
|
+
const startVerticesRef = useRef33(null);
|
|
14350
14781
|
const issuesKey = issues.map((issue) => issue.code).join(",");
|
|
14351
|
-
|
|
14782
|
+
useEffect33(() => {
|
|
14352
14783
|
if (!valid) onInvalid?.(issues);
|
|
14353
14784
|
}, [issues, issuesKey, onInvalid, valid]);
|
|
14354
|
-
|
|
14785
|
+
useEffect33(() => () => fillGeometry?.dispose(), [fillGeometry]);
|
|
14355
14786
|
if (!valid || !center || !fillGeometry || !strokePoints || strokePoints.length < 2) {
|
|
14356
14787
|
return null;
|
|
14357
14788
|
}
|
|
@@ -14366,7 +14797,7 @@ function PolygonHotspot({
|
|
|
14366
14797
|
startPosition: event.startPosition
|
|
14367
14798
|
});
|
|
14368
14799
|
};
|
|
14369
|
-
return /* @__PURE__ */
|
|
14800
|
+
return /* @__PURE__ */ jsxs19(
|
|
14370
14801
|
HotspotAnchor,
|
|
14371
14802
|
{
|
|
14372
14803
|
...anchorProps,
|
|
@@ -14381,7 +14812,7 @@ function PolygonHotspot({
|
|
|
14381
14812
|
draggable,
|
|
14382
14813
|
interactive,
|
|
14383
14814
|
useAngularScale: false,
|
|
14384
|
-
focusContent: /* @__PURE__ */
|
|
14815
|
+
focusContent: /* @__PURE__ */ jsx30(
|
|
14385
14816
|
HotspotStrokeLine,
|
|
14386
14817
|
{
|
|
14387
14818
|
color: "#75cbd3",
|
|
@@ -14403,7 +14834,7 @@ function PolygonHotspot({
|
|
|
14403
14834
|
startVerticesRef.current = null;
|
|
14404
14835
|
},
|
|
14405
14836
|
children: [
|
|
14406
|
-
/* @__PURE__ */
|
|
14837
|
+
/* @__PURE__ */ jsx30("mesh", { geometry: fillGeometry, renderOrder, children: /* @__PURE__ */ jsx30(
|
|
14407
14838
|
"meshBasicMaterial",
|
|
14408
14839
|
{
|
|
14409
14840
|
color: fill,
|
|
@@ -14413,7 +14844,7 @@ function PolygonHotspot({
|
|
|
14413
14844
|
transparent: true
|
|
14414
14845
|
}
|
|
14415
14846
|
) }),
|
|
14416
|
-
/* @__PURE__ */
|
|
14847
|
+
/* @__PURE__ */ jsx30(
|
|
14417
14848
|
HotspotStrokeLine,
|
|
14418
14849
|
{
|
|
14419
14850
|
color: stroke,
|
|
@@ -14431,14 +14862,14 @@ function PolygonHotspot({
|
|
|
14431
14862
|
}
|
|
14432
14863
|
|
|
14433
14864
|
// src/hotspot/polyline-hotspot.tsx
|
|
14434
|
-
import { useEffect as
|
|
14865
|
+
import { useEffect as useEffect34, useMemo as useMemo25, useRef as useRef34 } from "react";
|
|
14435
14866
|
import {
|
|
14436
|
-
MathUtils as
|
|
14437
|
-
Matrix4 as
|
|
14867
|
+
MathUtils as MathUtils10,
|
|
14868
|
+
Matrix4 as Matrix46,
|
|
14438
14869
|
Quaternion as Quaternion5,
|
|
14439
|
-
Vector3 as
|
|
14870
|
+
Vector3 as Vector317
|
|
14440
14871
|
} from "three";
|
|
14441
|
-
import { jsx as
|
|
14872
|
+
import { jsx as jsx31 } from "react/jsx-runtime";
|
|
14442
14873
|
var POLYLINE_RADIUS = 990;
|
|
14443
14874
|
var MAX_SEGMENT_DEGREES = 7;
|
|
14444
14875
|
function cloneVertices2(vertices) {
|
|
@@ -14463,29 +14894,29 @@ function unwrapVertices(vertices) {
|
|
|
14463
14894
|
function polylineCenter(vertices) {
|
|
14464
14895
|
const sum = vertices.reduce(
|
|
14465
14896
|
(total, vertex) => total.add(panoPositionToVector3(vertex).normalize()),
|
|
14466
|
-
new
|
|
14897
|
+
new Vector317()
|
|
14467
14898
|
);
|
|
14468
14899
|
return sum.lengthSq() > 1e-8 ? vector3ToPanoPosition(sum) : normalizePanoPosition(vertices[0]);
|
|
14469
14900
|
}
|
|
14470
14901
|
function surfaceQuaternion2(position) {
|
|
14471
14902
|
const outward = panoPositionToVector3(position).normalize();
|
|
14472
14903
|
const inward = outward.clone().negate();
|
|
14473
|
-
const pitch =
|
|
14474
|
-
const yaw =
|
|
14475
|
-
const localUp = new
|
|
14904
|
+
const pitch = MathUtils10.degToRad(position.pitch);
|
|
14905
|
+
const yaw = MathUtils10.degToRad(position.yaw);
|
|
14906
|
+
const localUp = new Vector317(
|
|
14476
14907
|
-Math.sin(pitch) * Math.sin(yaw),
|
|
14477
14908
|
Math.cos(pitch),
|
|
14478
14909
|
Math.sin(pitch) * Math.cos(yaw)
|
|
14479
14910
|
).normalize();
|
|
14480
14911
|
return new Quaternion5().setFromRotationMatrix(
|
|
14481
|
-
new
|
|
14912
|
+
new Matrix46().makeBasis(localUp.clone().cross(inward).normalize(), localUp, inward)
|
|
14482
14913
|
);
|
|
14483
14914
|
}
|
|
14484
14915
|
function makeWorldToLocal2(center) {
|
|
14485
|
-
return new
|
|
14916
|
+
return new Matrix46().compose(
|
|
14486
14917
|
panoPositionToVector3(center, POLYLINE_RADIUS),
|
|
14487
14918
|
surfaceQuaternion2(center),
|
|
14488
|
-
new
|
|
14919
|
+
new Vector317(1, 1, 1)
|
|
14489
14920
|
).invert();
|
|
14490
14921
|
}
|
|
14491
14922
|
function subdivisionSteps(vertices) {
|
|
@@ -14500,7 +14931,7 @@ function subdivisionSteps(vertices) {
|
|
|
14500
14931
|
}
|
|
14501
14932
|
return Math.min(
|
|
14502
14933
|
8,
|
|
14503
|
-
Math.max(1, Math.ceil(
|
|
14934
|
+
Math.max(1, Math.ceil(MathUtils10.radToDeg(maxAngle) / MAX_SEGMENT_DEGREES))
|
|
14504
14935
|
);
|
|
14505
14936
|
}
|
|
14506
14937
|
function makeLinePositions(vertices, center) {
|
|
@@ -14555,16 +14986,16 @@ function PolylineHotspot({
|
|
|
14555
14986
|
onInvalid,
|
|
14556
14987
|
...anchorProps
|
|
14557
14988
|
}) {
|
|
14558
|
-
const issues =
|
|
14989
|
+
const issues = useMemo25(() => validatePolylineVertices(vertices), [vertices]);
|
|
14559
14990
|
const valid = issues.length === 0;
|
|
14560
|
-
const center =
|
|
14561
|
-
const linePoints =
|
|
14991
|
+
const center = useMemo25(() => valid ? polylineCenter(vertices) : null, [valid, vertices]);
|
|
14992
|
+
const linePoints = useMemo25(
|
|
14562
14993
|
() => valid && center ? makeLinePositions(vertices, center) : null,
|
|
14563
14994
|
[center, valid, vertices]
|
|
14564
14995
|
);
|
|
14565
14996
|
const opacity = Math.max(0, Math.min(strokeOpacity, 1));
|
|
14566
|
-
const startVerticesRef =
|
|
14567
|
-
|
|
14997
|
+
const startVerticesRef = useRef34(null);
|
|
14998
|
+
useEffect34(() => {
|
|
14568
14999
|
if (!valid) onInvalid?.(issues);
|
|
14569
15000
|
}, [issues, onInvalid, valid]);
|
|
14570
15001
|
if (!valid || !center || !linePoints || linePoints.length < 2) return null;
|
|
@@ -14578,7 +15009,7 @@ function PolylineHotspot({
|
|
|
14578
15009
|
startPosition: event.startPosition
|
|
14579
15010
|
});
|
|
14580
15011
|
};
|
|
14581
|
-
return /* @__PURE__ */
|
|
15012
|
+
return /* @__PURE__ */ jsx31(
|
|
14582
15013
|
HotspotAnchor,
|
|
14583
15014
|
{
|
|
14584
15015
|
...anchorProps,
|
|
@@ -14592,7 +15023,7 @@ function PolylineHotspot({
|
|
|
14592
15023
|
renderOrder,
|
|
14593
15024
|
draggable,
|
|
14594
15025
|
useAngularScale: false,
|
|
14595
|
-
focusContent: /* @__PURE__ */
|
|
15026
|
+
focusContent: /* @__PURE__ */ jsx31(
|
|
14596
15027
|
HotspotStrokeLine,
|
|
14597
15028
|
{
|
|
14598
15029
|
color: "#75cbd3",
|
|
@@ -14613,7 +15044,7 @@ function PolylineHotspot({
|
|
|
14613
15044
|
emitVerticesChange(event, onDragEnd);
|
|
14614
15045
|
startVerticesRef.current = null;
|
|
14615
15046
|
},
|
|
14616
|
-
children: /* @__PURE__ */
|
|
15047
|
+
children: /* @__PURE__ */ jsx31(
|
|
14617
15048
|
HotspotStrokeLine,
|
|
14618
15049
|
{
|
|
14619
15050
|
color: stroke,
|
|
@@ -14630,7 +15061,7 @@ function PolylineHotspot({
|
|
|
14630
15061
|
}
|
|
14631
15062
|
|
|
14632
15063
|
// src/hotspot/graphic-hotspot.tsx
|
|
14633
|
-
import { useEffect as
|
|
15064
|
+
import { useEffect as useEffect35, useRef as useRef35, useState as useState18 } from "react";
|
|
14634
15065
|
import {
|
|
14635
15066
|
CanvasTexture,
|
|
14636
15067
|
ClampToEdgeWrapping as ClampToEdgeWrapping4,
|
|
@@ -14638,7 +15069,7 @@ import {
|
|
|
14638
15069
|
LinearMipmapLinearFilter as LinearMipmapLinearFilter4,
|
|
14639
15070
|
SRGBColorSpace as SRGBColorSpace6
|
|
14640
15071
|
} from "three";
|
|
14641
|
-
import { jsx as
|
|
15072
|
+
import { jsx as jsx32 } from "react/jsx-runtime";
|
|
14642
15073
|
var GRAPHIC_TEXTURE_SIZE = 512;
|
|
14643
15074
|
function resolveStrokeWidth(value) {
|
|
14644
15075
|
return Number.isFinite(value) ? Math.max(value, 0) : 8;
|
|
@@ -14827,12 +15258,12 @@ function createGraphicTexture(graphic, aspectWidth, aspectHeight) {
|
|
|
14827
15258
|
return texture;
|
|
14828
15259
|
}
|
|
14829
15260
|
function useGraphicTexture(graphic, aspectWidth, aspectHeight, onLoad, onError) {
|
|
14830
|
-
const [texture, setTexture] =
|
|
14831
|
-
const onLoadRef =
|
|
14832
|
-
const onErrorRef =
|
|
15261
|
+
const [texture, setTexture] = useState18(null);
|
|
15262
|
+
const onLoadRef = useRef35(onLoad);
|
|
15263
|
+
const onErrorRef = useRef35(onError);
|
|
14833
15264
|
onLoadRef.current = onLoad;
|
|
14834
15265
|
onErrorRef.current = onError;
|
|
14835
|
-
|
|
15266
|
+
useEffect35(() => {
|
|
14836
15267
|
let nextTexture = null;
|
|
14837
15268
|
try {
|
|
14838
15269
|
nextTexture = createGraphicTexture(graphic, aspectWidth, aspectHeight);
|
|
@@ -14858,20 +15289,20 @@ function CanvasGraphicHotspot({
|
|
|
14858
15289
|
...anchorProps
|
|
14859
15290
|
}) {
|
|
14860
15291
|
const texture = useGraphicTexture(graphic, width, height, onLoad, onError);
|
|
14861
|
-
return /* @__PURE__ */
|
|
15292
|
+
return /* @__PURE__ */ jsx32(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ jsx32(HotspotPlane, { map: texture, opacity }) });
|
|
14862
15293
|
}
|
|
14863
15294
|
function GraphicHotspot(props) {
|
|
14864
15295
|
const { graphic, ...restProps } = props;
|
|
14865
15296
|
if (graphic.kind === "svg") {
|
|
14866
15297
|
const imageProps = restProps;
|
|
14867
|
-
return /* @__PURE__ */
|
|
15298
|
+
return /* @__PURE__ */ jsx32(ImageHotspot, { ...imageProps, src: graphic.src });
|
|
14868
15299
|
}
|
|
14869
|
-
return /* @__PURE__ */
|
|
15300
|
+
return /* @__PURE__ */ jsx32(CanvasGraphicHotspot, { ...restProps, graphic });
|
|
14870
15301
|
}
|
|
14871
15302
|
|
|
14872
15303
|
// src/hotspot/sequence-hotspot.tsx
|
|
14873
|
-
import { useFrame as
|
|
14874
|
-
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";
|
|
14875
15306
|
import {
|
|
14876
15307
|
ClampToEdgeWrapping as ClampToEdgeWrapping5,
|
|
14877
15308
|
LinearFilter as LinearFilter8,
|
|
@@ -14879,7 +15310,7 @@ import {
|
|
|
14879
15310
|
SRGBColorSpace as SRGBColorSpace7,
|
|
14880
15311
|
TextureLoader as TextureLoader6
|
|
14881
15312
|
} from "three";
|
|
14882
|
-
import { jsx as
|
|
15313
|
+
import { jsx as jsx33 } from "react/jsx-runtime";
|
|
14883
15314
|
var DEFAULT_SEQUENCE_FPS = 12;
|
|
14884
15315
|
function resolveFps(value) {
|
|
14885
15316
|
return Number.isFinite(value) && value > 0 ? value : DEFAULT_SEQUENCE_FPS;
|
|
@@ -14893,13 +15324,13 @@ function useSpriteTexture({
|
|
|
14893
15324
|
onError,
|
|
14894
15325
|
onLoadProgress
|
|
14895
15326
|
}) {
|
|
14896
|
-
const gl =
|
|
14897
|
-
const [texture, setTexture] =
|
|
14898
|
-
const onErrorRef =
|
|
14899
|
-
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);
|
|
14900
15331
|
onErrorRef.current = onError;
|
|
14901
15332
|
onLoadProgressRef.current = onLoadProgress;
|
|
14902
|
-
|
|
15333
|
+
useEffect36(() => {
|
|
14903
15334
|
let active = true;
|
|
14904
15335
|
setTexture(null);
|
|
14905
15336
|
if (!src) {
|
|
@@ -14940,7 +15371,7 @@ function useSpriteTexture({
|
|
|
14940
15371
|
active = false;
|
|
14941
15372
|
};
|
|
14942
15373
|
}, [gl, id, src]);
|
|
14943
|
-
|
|
15374
|
+
useEffect36(
|
|
14944
15375
|
() => () => {
|
|
14945
15376
|
texture?.dispose();
|
|
14946
15377
|
},
|
|
@@ -14969,24 +15400,24 @@ function SequenceHotspot({
|
|
|
14969
15400
|
const texture = useSpriteTexture({ id, src, onError, onLoadProgress });
|
|
14970
15401
|
const frameCount = resolveFrameCount(requestedFrameCount);
|
|
14971
15402
|
const safeFps = resolveFps(fps);
|
|
14972
|
-
const [frameIndex, setFrameIndex] =
|
|
14973
|
-
const elapsedRef =
|
|
14974
|
-
const frameIndexRef =
|
|
14975
|
-
const endedRef =
|
|
14976
|
-
const lastPlaybackStateRef =
|
|
14977
|
-
const onFrameChangeRef =
|
|
14978
|
-
const onPlaybackStateChangeRef =
|
|
14979
|
-
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);
|
|
14980
15411
|
onFrameChangeRef.current = onFrameChange;
|
|
14981
15412
|
onPlaybackStateChangeRef.current = onPlaybackStateChange;
|
|
14982
15413
|
onEndedRef.current = onEnded;
|
|
14983
|
-
|
|
15414
|
+
useEffect36(() => {
|
|
14984
15415
|
elapsedRef.current = 0;
|
|
14985
15416
|
frameIndexRef.current = 0;
|
|
14986
15417
|
endedRef.current = false;
|
|
14987
15418
|
setFrameIndex(0);
|
|
14988
15419
|
}, [frameCount, frameDirection, src]);
|
|
14989
|
-
|
|
15420
|
+
useEffect36(() => {
|
|
14990
15421
|
if (!texture) {
|
|
14991
15422
|
return;
|
|
14992
15423
|
}
|
|
@@ -15000,13 +15431,13 @@ function SequenceHotspot({
|
|
|
15000
15431
|
);
|
|
15001
15432
|
texture.needsUpdate = true;
|
|
15002
15433
|
}, [frameCount, frameDirection, frameIndex, texture]);
|
|
15003
|
-
|
|
15434
|
+
useEffect36(() => {
|
|
15004
15435
|
if (!texture) {
|
|
15005
15436
|
return;
|
|
15006
15437
|
}
|
|
15007
15438
|
onFrameChangeRef.current?.({ id, index: 0, src });
|
|
15008
15439
|
}, [id, src, texture]);
|
|
15009
|
-
|
|
15440
|
+
useEffect36(() => {
|
|
15010
15441
|
if (!texture) {
|
|
15011
15442
|
return;
|
|
15012
15443
|
}
|
|
@@ -15025,7 +15456,7 @@ function SequenceHotspot({
|
|
|
15025
15456
|
onPlaybackStateChangeRef.current?.(nextState);
|
|
15026
15457
|
}
|
|
15027
15458
|
}, [playing, texture]);
|
|
15028
|
-
|
|
15459
|
+
useFrame16((_, deltaSeconds) => {
|
|
15029
15460
|
if (!texture || !playing || endedRef.current) {
|
|
15030
15461
|
return;
|
|
15031
15462
|
}
|
|
@@ -15055,12 +15486,12 @@ function SequenceHotspot({
|
|
|
15055
15486
|
onFrameChangeRef.current?.({ id, index: nextIndex, src });
|
|
15056
15487
|
}
|
|
15057
15488
|
});
|
|
15058
|
-
return /* @__PURE__ */
|
|
15489
|
+
return /* @__PURE__ */ jsx33(HotspotAnchor, { ...anchorProps, id, height, width, children: /* @__PURE__ */ jsx33(HotspotPlane, { map: texture, opacity }) });
|
|
15059
15490
|
}
|
|
15060
15491
|
|
|
15061
15492
|
// src/hotspot/video-hotspot.tsx
|
|
15062
|
-
import { useThree as
|
|
15063
|
-
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";
|
|
15064
15495
|
import {
|
|
15065
15496
|
ClampToEdgeWrapping as ClampToEdgeWrapping6,
|
|
15066
15497
|
LinearFilter as LinearFilter9,
|
|
@@ -15069,7 +15500,7 @@ import {
|
|
|
15069
15500
|
TextureLoader as TextureLoader7,
|
|
15070
15501
|
VideoTexture as VideoTexture2
|
|
15071
15502
|
} from "three";
|
|
15072
|
-
import { jsx as
|
|
15503
|
+
import { jsx as jsx34 } from "react/jsx-runtime";
|
|
15073
15504
|
function clampVolume2(volume) {
|
|
15074
15505
|
if (!Number.isFinite(volume)) {
|
|
15075
15506
|
return 1;
|
|
@@ -15077,11 +15508,11 @@ function clampVolume2(volume) {
|
|
|
15077
15508
|
return Math.max(0, Math.min(volume, 1));
|
|
15078
15509
|
}
|
|
15079
15510
|
function usePosterTexture2(id, poster, onError) {
|
|
15080
|
-
const gl =
|
|
15081
|
-
const [texture, setTexture] =
|
|
15082
|
-
const onErrorRef =
|
|
15511
|
+
const gl = useThree25((state) => state.gl);
|
|
15512
|
+
const [texture, setTexture] = useState20(null);
|
|
15513
|
+
const onErrorRef = useRef37(onError);
|
|
15083
15514
|
onErrorRef.current = onError;
|
|
15084
|
-
|
|
15515
|
+
useEffect37(() => {
|
|
15085
15516
|
let active = true;
|
|
15086
15517
|
setTexture(null);
|
|
15087
15518
|
if (!poster) {
|
|
@@ -15118,7 +15549,7 @@ function usePosterTexture2(id, poster, onError) {
|
|
|
15118
15549
|
active = false;
|
|
15119
15550
|
};
|
|
15120
15551
|
}, [gl, id, poster]);
|
|
15121
|
-
|
|
15552
|
+
useEffect37(
|
|
15122
15553
|
() => () => {
|
|
15123
15554
|
texture?.dispose();
|
|
15124
15555
|
},
|
|
@@ -15136,14 +15567,14 @@ function useVideoResource({
|
|
|
15136
15567
|
poster,
|
|
15137
15568
|
src
|
|
15138
15569
|
}) {
|
|
15139
|
-
const [resource, setResource] =
|
|
15140
|
-
const onEndedRef =
|
|
15141
|
-
const onErrorRef =
|
|
15142
|
-
const onPlaybackStateChangeRef =
|
|
15570
|
+
const [resource, setResource] = useState20(null);
|
|
15571
|
+
const onEndedRef = useRef37(onEnded);
|
|
15572
|
+
const onErrorRef = useRef37(onError);
|
|
15573
|
+
const onPlaybackStateChangeRef = useRef37(onPlaybackStateChange);
|
|
15143
15574
|
onEndedRef.current = onEnded;
|
|
15144
15575
|
onErrorRef.current = onError;
|
|
15145
15576
|
onPlaybackStateChangeRef.current = onPlaybackStateChange;
|
|
15146
|
-
|
|
15577
|
+
useEffect37(() => {
|
|
15147
15578
|
if (!src) {
|
|
15148
15579
|
setResource(null);
|
|
15149
15580
|
return;
|
|
@@ -15250,11 +15681,11 @@ function VideoHotspot({
|
|
|
15250
15681
|
src
|
|
15251
15682
|
});
|
|
15252
15683
|
const posterTexture = usePosterTexture2(id, poster, onError);
|
|
15253
|
-
const onPlaybackErrorRef =
|
|
15254
|
-
const onPlaybackStateChangeRef =
|
|
15684
|
+
const onPlaybackErrorRef = useRef37(onPlaybackError);
|
|
15685
|
+
const onPlaybackStateChangeRef = useRef37(onPlaybackStateChange);
|
|
15255
15686
|
onPlaybackErrorRef.current = onPlaybackError;
|
|
15256
15687
|
onPlaybackStateChangeRef.current = onPlaybackStateChange;
|
|
15257
|
-
|
|
15688
|
+
useEffect37(() => {
|
|
15258
15689
|
if (!resource) {
|
|
15259
15690
|
return;
|
|
15260
15691
|
}
|
|
@@ -15271,7 +15702,7 @@ function VideoHotspot({
|
|
|
15271
15702
|
}
|
|
15272
15703
|
resource.video.preload = preload;
|
|
15273
15704
|
}, [loop, muted, playsInline, preload, resource, volume]);
|
|
15274
|
-
|
|
15705
|
+
useEffect37(() => {
|
|
15275
15706
|
if (!resource) {
|
|
15276
15707
|
return;
|
|
15277
15708
|
}
|
|
@@ -15294,12 +15725,12 @@ function VideoHotspot({
|
|
|
15294
15725
|
};
|
|
15295
15726
|
}, [playing, resource]);
|
|
15296
15727
|
const activeTexture = resource?.ready ? resource.texture : posterTexture;
|
|
15297
|
-
return /* @__PURE__ */
|
|
15728
|
+
return /* @__PURE__ */ jsx34(HotspotAnchor, { ...anchorProps, id, height, width, children: /* @__PURE__ */ jsx34(HotspotPlane, { map: activeTexture, opacity }) });
|
|
15298
15729
|
}
|
|
15299
15730
|
|
|
15300
15731
|
// src/hotspot/audio-hotspot.tsx
|
|
15301
|
-
import { useFrame as
|
|
15302
|
-
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";
|
|
15303
15734
|
import {
|
|
15304
15735
|
CanvasTexture as CanvasTexture2,
|
|
15305
15736
|
ClampToEdgeWrapping as ClampToEdgeWrapping7,
|
|
@@ -15308,7 +15739,7 @@ import {
|
|
|
15308
15739
|
SRGBColorSpace as SRGBColorSpace9,
|
|
15309
15740
|
TextureLoader as TextureLoader8
|
|
15310
15741
|
} from "three";
|
|
15311
|
-
import { jsx as
|
|
15742
|
+
import { jsx as jsx35 } from "react/jsx-runtime";
|
|
15312
15743
|
var SPEAKER_TEXTURE_SIZE = 512;
|
|
15313
15744
|
function paintSpeakerBody(context, center) {
|
|
15314
15745
|
context.fillStyle = "#f5fbfc";
|
|
@@ -15372,8 +15803,8 @@ function createSpeakerTexture(state) {
|
|
|
15372
15803
|
return texture;
|
|
15373
15804
|
}
|
|
15374
15805
|
function useSpeakerTextures(enabled) {
|
|
15375
|
-
const [textures, setTextures] =
|
|
15376
|
-
|
|
15806
|
+
const [textures, setTextures] = useState21({ playing: null, stopped: null });
|
|
15807
|
+
useEffect38(() => {
|
|
15377
15808
|
if (!enabled) {
|
|
15378
15809
|
setTextures({ playing: null, stopped: null });
|
|
15379
15810
|
return;
|
|
@@ -15389,11 +15820,11 @@ function useSpeakerTextures(enabled) {
|
|
|
15389
15820
|
return textures;
|
|
15390
15821
|
}
|
|
15391
15822
|
function useIconTexture(icon, enabled, onError, id) {
|
|
15392
|
-
const gl =
|
|
15393
|
-
const [texture, setTexture] =
|
|
15394
|
-
const onErrorRef =
|
|
15823
|
+
const gl = useThree26((state) => state.gl);
|
|
15824
|
+
const [texture, setTexture] = useState21(null);
|
|
15825
|
+
const onErrorRef = useRef38(onError);
|
|
15395
15826
|
onErrorRef.current = onError;
|
|
15396
|
-
|
|
15827
|
+
useEffect38(() => {
|
|
15397
15828
|
let active = true;
|
|
15398
15829
|
setTexture(null);
|
|
15399
15830
|
if (!enabled || !icon) {
|
|
@@ -15430,7 +15861,7 @@ function useIconTexture(icon, enabled, onError, id) {
|
|
|
15430
15861
|
active = false;
|
|
15431
15862
|
};
|
|
15432
15863
|
}, [enabled, gl, icon, id]);
|
|
15433
|
-
|
|
15864
|
+
useEffect38(
|
|
15434
15865
|
() => () => {
|
|
15435
15866
|
texture?.dispose();
|
|
15436
15867
|
},
|
|
@@ -15449,13 +15880,13 @@ function useAudioHowl({
|
|
|
15449
15880
|
playing,
|
|
15450
15881
|
src
|
|
15451
15882
|
}) {
|
|
15452
|
-
const [howl, setHowl] =
|
|
15453
|
-
const playingRef =
|
|
15454
|
-
const loopRef =
|
|
15455
|
-
const onEndedRef =
|
|
15456
|
-
const onErrorRef =
|
|
15457
|
-
const onPlaybackErrorRef =
|
|
15458
|
-
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);
|
|
15459
15890
|
playingRef.current = playing;
|
|
15460
15891
|
loopRef.current = loop ?? false;
|
|
15461
15892
|
onEndedRef.current = onEnded;
|
|
@@ -15463,7 +15894,7 @@ function useAudioHowl({
|
|
|
15463
15894
|
onPlaybackErrorRef.current = onPlaybackError;
|
|
15464
15895
|
onPlaybackStateChangeRef.current = onPlaybackStateChange;
|
|
15465
15896
|
const sourcesKey = sourceList(src).join("\0");
|
|
15466
|
-
|
|
15897
|
+
useEffect38(() => {
|
|
15467
15898
|
const sources = sourcesKey.length > 0 ? sourcesKey.split("\0") : [];
|
|
15468
15899
|
if (sources.length === 0) {
|
|
15469
15900
|
setHowl(null);
|
|
@@ -15500,7 +15931,7 @@ function useAudioHowl({
|
|
|
15500
15931
|
handle.dispose();
|
|
15501
15932
|
};
|
|
15502
15933
|
}, [crossOrigin, id, sourcesKey]);
|
|
15503
|
-
|
|
15934
|
+
useEffect38(() => {
|
|
15504
15935
|
howl?.loop(loop ?? false);
|
|
15505
15936
|
}, [howl, loop]);
|
|
15506
15937
|
return howl;
|
|
@@ -15528,7 +15959,7 @@ function AudioHotspot({
|
|
|
15528
15959
|
...anchorProps
|
|
15529
15960
|
}) {
|
|
15530
15961
|
usePanoMediaActivationIntent(playing);
|
|
15531
|
-
const camera =
|
|
15962
|
+
const camera = useThree26((state) => state.camera);
|
|
15532
15963
|
const howl = useAudioHowl({
|
|
15533
15964
|
crossOrigin,
|
|
15534
15965
|
id,
|
|
@@ -15544,15 +15975,15 @@ function AudioHotspot({
|
|
|
15544
15975
|
const stoppedIconTexture = useIconTexture(icon, marker, onError, id);
|
|
15545
15976
|
const playingIconTexture = useIconTexture(playingIcon, marker, onError, id);
|
|
15546
15977
|
const markerTexture = playing ? playingIconTexture ?? stoppedIconTexture ?? speakerTextures.playing : stoppedIconTexture ?? speakerTextures.stopped;
|
|
15547
|
-
const playingRef =
|
|
15978
|
+
const playingRef = useRef38(playing);
|
|
15548
15979
|
playingRef.current = playing;
|
|
15549
|
-
const mutedRef =
|
|
15550
|
-
const volumeRef =
|
|
15551
|
-
const rangeRef =
|
|
15980
|
+
const mutedRef = useRef38(muted);
|
|
15981
|
+
const volumeRef = useRef38(volume);
|
|
15982
|
+
const rangeRef = useRef38(range);
|
|
15552
15983
|
mutedRef.current = muted;
|
|
15553
15984
|
volumeRef.current = volume;
|
|
15554
15985
|
rangeRef.current = range;
|
|
15555
|
-
|
|
15986
|
+
useEffect38(() => {
|
|
15556
15987
|
if (!howl) {
|
|
15557
15988
|
return;
|
|
15558
15989
|
}
|
|
@@ -15562,7 +15993,7 @@ function AudioHotspot({
|
|
|
15562
15993
|
}
|
|
15563
15994
|
howl.play();
|
|
15564
15995
|
}, [howl, playing]);
|
|
15565
|
-
|
|
15996
|
+
useEffect38(() => {
|
|
15566
15997
|
if (!howl || !pauseWhenHidden) {
|
|
15567
15998
|
return;
|
|
15568
15999
|
}
|
|
@@ -15580,7 +16011,7 @@ function AudioHotspot({
|
|
|
15580
16011
|
document.removeEventListener("visibilitychange", handleVisibility);
|
|
15581
16012
|
};
|
|
15582
16013
|
}, [howl, pauseWhenHidden]);
|
|
15583
|
-
|
|
16014
|
+
useFrame17(() => {
|
|
15584
16015
|
if (!howl) {
|
|
15585
16016
|
return;
|
|
15586
16017
|
}
|
|
@@ -15593,11 +16024,11 @@ function AudioHotspot({
|
|
|
15593
16024
|
howl.mute(mutedRef.current);
|
|
15594
16025
|
howl.volume(clampAudioVolume(volumeRef.current) * spatial.gain);
|
|
15595
16026
|
});
|
|
15596
|
-
return /* @__PURE__ */
|
|
16027
|
+
return /* @__PURE__ */ jsx35(HotspotAnchor, { ...anchorProps, id, height, width, children: marker ? /* @__PURE__ */ jsx35(HotspotPlane, { map: markerTexture, opacity }) : null });
|
|
15597
16028
|
}
|
|
15598
16029
|
|
|
15599
16030
|
// src/hotspot/text-hotspot.tsx
|
|
15600
|
-
import { useEffect as
|
|
16031
|
+
import { useEffect as useEffect39, useRef as useRef39, useState as useState22 } from "react";
|
|
15601
16032
|
import {
|
|
15602
16033
|
CanvasTexture as CanvasTexture3,
|
|
15603
16034
|
ClampToEdgeWrapping as ClampToEdgeWrapping8,
|
|
@@ -15605,7 +16036,7 @@ import {
|
|
|
15605
16036
|
LinearMipmapLinearFilter as LinearMipmapLinearFilter8,
|
|
15606
16037
|
SRGBColorSpace as SRGBColorSpace10
|
|
15607
16038
|
} from "three";
|
|
15608
|
-
import { jsx as
|
|
16039
|
+
import { jsx as jsx36 } from "react/jsx-runtime";
|
|
15609
16040
|
var TEXT_TEXTURE_LONG_SIDE = 1024;
|
|
15610
16041
|
var DEFAULT_FONT_FAMILY = "system-ui, sans-serif";
|
|
15611
16042
|
var DEFAULT_FONT_SIZE = 96;
|
|
@@ -15825,12 +16256,12 @@ function createTextTexture(text, width, height, style) {
|
|
|
15825
16256
|
return texture;
|
|
15826
16257
|
}
|
|
15827
16258
|
function useTextTexture(text, width, height, style, onLoad, onError) {
|
|
15828
|
-
const [texture, setTexture] =
|
|
15829
|
-
const onLoadRef =
|
|
15830
|
-
const onErrorRef =
|
|
16259
|
+
const [texture, setTexture] = useState22(null);
|
|
16260
|
+
const onLoadRef = useRef39(onLoad);
|
|
16261
|
+
const onErrorRef = useRef39(onError);
|
|
15831
16262
|
onLoadRef.current = onLoad;
|
|
15832
16263
|
onErrorRef.current = onError;
|
|
15833
|
-
|
|
16264
|
+
useEffect39(() => {
|
|
15834
16265
|
let cancelled = false;
|
|
15835
16266
|
let nextTexture = null;
|
|
15836
16267
|
const run = async () => {
|
|
@@ -15923,13 +16354,13 @@ function TextHotspot({
|
|
|
15923
16354
|
whiteSpace
|
|
15924
16355
|
};
|
|
15925
16356
|
const texture = useTextTexture(text, width, height, style, onLoad, onError);
|
|
15926
|
-
return /* @__PURE__ */
|
|
16357
|
+
return /* @__PURE__ */ jsx36(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ jsx36(HotspotPlane, { map: texture, opacity }) });
|
|
15927
16358
|
}
|
|
15928
16359
|
|
|
15929
16360
|
// src/hotspot/iframe-hotspot.tsx
|
|
15930
16361
|
import { Html as Html2 } from "@react-three/drei";
|
|
15931
16362
|
import { DoubleSide as DoubleSide6 } from "three";
|
|
15932
|
-
import { jsx as
|
|
16363
|
+
import { jsx as jsx37, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
15933
16364
|
var IFRAME_LONG_SIDE = 800;
|
|
15934
16365
|
var CSS3D_DISTANCE_FACTOR = 400;
|
|
15935
16366
|
var DEFAULT_SANDBOX = "allow-scripts allow-popups allow-forms";
|
|
@@ -15986,7 +16417,7 @@ function IframeHotspot({
|
|
|
15986
16417
|
interactive,
|
|
15987
16418
|
pointerEvents
|
|
15988
16419
|
);
|
|
15989
|
-
return /* @__PURE__ */
|
|
16420
|
+
return /* @__PURE__ */ jsxs20(
|
|
15990
16421
|
HotspotAnchor,
|
|
15991
16422
|
{
|
|
15992
16423
|
...anchorProps,
|
|
@@ -15995,9 +16426,9 @@ function IframeHotspot({
|
|
|
15995
16426
|
pointerEvents,
|
|
15996
16427
|
width,
|
|
15997
16428
|
children: [
|
|
15998
|
-
/* @__PURE__ */
|
|
15999
|
-
/* @__PURE__ */
|
|
16000
|
-
/* @__PURE__ */
|
|
16429
|
+
/* @__PURE__ */ jsxs20("mesh", { children: [
|
|
16430
|
+
/* @__PURE__ */ jsx37("planeGeometry", { args: [1, 1] }),
|
|
16431
|
+
/* @__PURE__ */ jsx37(
|
|
16001
16432
|
"meshBasicMaterial",
|
|
16002
16433
|
{
|
|
16003
16434
|
depthWrite: false,
|
|
@@ -16008,7 +16439,7 @@ function IframeHotspot({
|
|
|
16008
16439
|
}
|
|
16009
16440
|
)
|
|
16010
16441
|
] }),
|
|
16011
|
-
/* @__PURE__ */
|
|
16442
|
+
/* @__PURE__ */ jsx37(
|
|
16012
16443
|
Html2,
|
|
16013
16444
|
{
|
|
16014
16445
|
distanceFactor: CSS3D_DISTANCE_FACTOR,
|
|
@@ -16023,7 +16454,7 @@ function IframeHotspot({
|
|
|
16023
16454
|
},
|
|
16024
16455
|
transform: true,
|
|
16025
16456
|
zIndexRange: [10, 0],
|
|
16026
|
-
children: /* @__PURE__ */
|
|
16457
|
+
children: /* @__PURE__ */ jsx37(
|
|
16027
16458
|
"iframe",
|
|
16028
16459
|
{
|
|
16029
16460
|
allow,
|
|
@@ -16075,6 +16506,7 @@ export {
|
|
|
16075
16506
|
Scenes,
|
|
16076
16507
|
SequenceHotspot,
|
|
16077
16508
|
Sphere,
|
|
16509
|
+
SphereTile,
|
|
16078
16510
|
TextHotspot,
|
|
16079
16511
|
Tile,
|
|
16080
16512
|
TouchControls,
|