@ericchen1990/pano-view 0.2.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +304 -130
- package/dist/index.cjs +1587 -630
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +194 -62
- package/dist/index.d.ts +194 -62
- package/dist/index.mjs +1472 -502
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -1
package/dist/index.cjs
CHANGED
|
@@ -22,7 +22,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
22
22
|
var index_exports = {};
|
|
23
23
|
__export(index_exports, {
|
|
24
24
|
AutoRotate: () => AutoRotate,
|
|
25
|
+
DEFAULT_HOTSPOT_TOOLTIP_OFFSET: () => DEFAULT_HOTSPOT_TOOLTIP_OFFSET,
|
|
26
|
+
DEFAULT_PANO_CURSORS: () => DEFAULT_PANO_CURSORS,
|
|
25
27
|
GraphicHotspot: () => GraphicHotspot,
|
|
28
|
+
IframeHotspot: () => IframeHotspot,
|
|
26
29
|
ImageHotspot: () => ImageHotspot,
|
|
27
30
|
KeyboardControls: () => KeyboardControls,
|
|
28
31
|
MAX_HOTSPOT_PITCH: () => MAX_HOTSPOT_PITCH,
|
|
@@ -30,12 +33,13 @@ __export(index_exports, {
|
|
|
30
33
|
MouseControls: () => MouseControls,
|
|
31
34
|
PanoContextMenu: () => PanoContextMenu,
|
|
32
35
|
PanoEvents: () => PanoEvents,
|
|
33
|
-
|
|
34
|
-
PanoramaScenes: () => PanoramaScenes,
|
|
36
|
+
PanoViewer: () => PanoViewer,
|
|
35
37
|
PolygonHotspot: () => PolygonHotspot,
|
|
36
38
|
PolylineHotspot: () => PolylineHotspot,
|
|
39
|
+
Scenes: () => Scenes,
|
|
37
40
|
SequenceHotspot: () => SequenceHotspot,
|
|
38
41
|
Sphere: () => Sphere,
|
|
42
|
+
TextHotspot: () => TextHotspot,
|
|
39
43
|
Tile: () => Tile,
|
|
40
44
|
TouchControls: () => TouchControls,
|
|
41
45
|
VideoHotspot: () => VideoHotspot,
|
|
@@ -56,9 +60,9 @@ __export(index_exports, {
|
|
|
56
60
|
});
|
|
57
61
|
module.exports = __toCommonJS(index_exports);
|
|
58
62
|
|
|
59
|
-
// src/pano-
|
|
60
|
-
var
|
|
61
|
-
var
|
|
63
|
+
// src/pano-viewer.tsx
|
|
64
|
+
var import_fiber9 = require("@react-three/fiber");
|
|
65
|
+
var import_react13 = require("react");
|
|
62
66
|
|
|
63
67
|
// src/auto-rotate.tsx
|
|
64
68
|
var import_fiber2 = require("@react-three/fiber");
|
|
@@ -446,7 +450,7 @@ function AutoRotate({
|
|
|
446
450
|
const rotatingRef = (0, import_react3.useRef)(false);
|
|
447
451
|
const yawAccumulatedRef = (0, import_react3.useRef)(0);
|
|
448
452
|
if (!controlsRef) {
|
|
449
|
-
throw new Error("<AutoRotate> must be rendered inside <
|
|
453
|
+
throw new Error("<AutoRotate> must be rendered inside <PanoViewer>.");
|
|
450
454
|
}
|
|
451
455
|
(0, import_react3.useEffect)(() => {
|
|
452
456
|
elapsedRef.current = 0;
|
|
@@ -502,10 +506,46 @@ function AutoRotate({
|
|
|
502
506
|
return null;
|
|
503
507
|
}
|
|
504
508
|
|
|
505
|
-
// src/
|
|
509
|
+
// src/control-claims.ts
|
|
506
510
|
var import_react4 = require("react");
|
|
511
|
+
var ControlClaimsContext = (0, import_react4.createContext)(null);
|
|
512
|
+
var DefaultControlChannelContext = (0, import_react4.createContext)(false);
|
|
513
|
+
var CHANNEL_COMPONENT = {
|
|
514
|
+
mouse: "MouseControls",
|
|
515
|
+
touch: "TouchControls",
|
|
516
|
+
keyboard: "KeyboardControls"
|
|
517
|
+
};
|
|
518
|
+
function createControlClaims() {
|
|
519
|
+
return { mouse: 0, touch: 0, keyboard: 0 };
|
|
520
|
+
}
|
|
521
|
+
function resetControlClaims(claims) {
|
|
522
|
+
claims.mouse = 0;
|
|
523
|
+
claims.touch = 0;
|
|
524
|
+
claims.keyboard = 0;
|
|
525
|
+
}
|
|
526
|
+
function isProduction() {
|
|
527
|
+
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
528
|
+
return nodeEnv === "production";
|
|
529
|
+
}
|
|
530
|
+
function useClaimControlChannel(channel) {
|
|
531
|
+
const claims = (0, import_react4.useContext)(ControlClaimsContext);
|
|
532
|
+
const isDefault = (0, import_react4.useContext)(DefaultControlChannelContext);
|
|
533
|
+
if (!claims || isDefault) {
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
claims[channel] += 1;
|
|
537
|
+
if (!isProduction() && claims[channel] > 1) {
|
|
538
|
+
const name = CHANNEL_COMPONENT[channel];
|
|
539
|
+
console.warn(
|
|
540
|
+
`PanoViewer: multiple <${name}> instances are mounted. Render at most one per channel.`
|
|
541
|
+
);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
// src/hotspot/accessibility.tsx
|
|
546
|
+
var import_react5 = require("react");
|
|
507
547
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
508
|
-
var HotspotAccessibilityContext = (0,
|
|
548
|
+
var HotspotAccessibilityContext = (0, import_react5.createContext)(null);
|
|
509
549
|
var VISUALLY_HIDDEN_STYLE = {
|
|
510
550
|
border: 0,
|
|
511
551
|
clip: "rect(0 0 0 0)",
|
|
@@ -531,12 +571,12 @@ function useHotspotAccessibility({
|
|
|
531
571
|
ariaLabel,
|
|
532
572
|
onActivate
|
|
533
573
|
}) {
|
|
534
|
-
const registry = (0,
|
|
535
|
-
const [focused, setFocused] = (0,
|
|
536
|
-
const activateRef = (0,
|
|
574
|
+
const registry = (0, import_react5.useContext)(HotspotAccessibilityContext);
|
|
575
|
+
const [focused, setFocused] = (0, import_react5.useState)(false);
|
|
576
|
+
const activateRef = (0, import_react5.useRef)(onActivate);
|
|
537
577
|
const enabled = Boolean(onActivate);
|
|
538
578
|
activateRef.current = onActivate;
|
|
539
|
-
(0,
|
|
579
|
+
(0, import_react5.useEffect)(() => {
|
|
540
580
|
if (!enabled) {
|
|
541
581
|
setFocused(false);
|
|
542
582
|
return;
|
|
@@ -558,8 +598,8 @@ function useHotspotAccessibility({
|
|
|
558
598
|
return focused;
|
|
559
599
|
}
|
|
560
600
|
function useHotspotAccessibilityLayer() {
|
|
561
|
-
const [entries, setEntries] = (0,
|
|
562
|
-
const register = (0,
|
|
601
|
+
const [entries, setEntries] = (0, import_react5.useState)(() => /* @__PURE__ */ new Map());
|
|
602
|
+
const register = (0, import_react5.useCallback)(
|
|
563
603
|
(entry) => {
|
|
564
604
|
const token = Symbol(entry.id);
|
|
565
605
|
const nextEntry = { ...entry, token };
|
|
@@ -581,11 +621,11 @@ function useHotspotAccessibilityLayer() {
|
|
|
581
621
|
},
|
|
582
622
|
[]
|
|
583
623
|
);
|
|
584
|
-
const registry = (0,
|
|
624
|
+
const registry = (0, import_react5.useMemo)(
|
|
585
625
|
() => ({ register }),
|
|
586
626
|
[register]
|
|
587
627
|
);
|
|
588
|
-
const controls = (0,
|
|
628
|
+
const controls = (0, import_react5.useMemo)(
|
|
589
629
|
() => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { "aria-label": "Panorama hotspots", style: { pointerEvents: "none" }, children: Array.from(entries.values()).map((entry) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
590
630
|
"button",
|
|
591
631
|
{
|
|
@@ -612,7 +652,7 @@ function useHotspotAccessibilityLayer() {
|
|
|
612
652
|
|
|
613
653
|
// src/keyboard-controls.tsx
|
|
614
654
|
var import_fiber3 = require("@react-three/fiber");
|
|
615
|
-
var
|
|
655
|
+
var import_react6 = require("react");
|
|
616
656
|
var DEFAULT_ROTATE_SPEED = 60;
|
|
617
657
|
var DEFAULT_ZOOM_SPEED = 30;
|
|
618
658
|
var DEFAULT_SHIFT_MULTIPLIER = 3;
|
|
@@ -681,23 +721,24 @@ function KeyboardControls({
|
|
|
681
721
|
onPreviousScene,
|
|
682
722
|
onNextScene
|
|
683
723
|
}) {
|
|
684
|
-
|
|
724
|
+
useClaimControlChannel("keyboard");
|
|
725
|
+
const controlsRef = (0, import_react6.useContext)(PanoramaViewContext);
|
|
685
726
|
const { gl } = (0, import_fiber3.useThree)();
|
|
686
|
-
const pressedRef = (0,
|
|
687
|
-
const shiftHeldRef = (0,
|
|
688
|
-
const invertRef = (0,
|
|
689
|
-
const fovSpeedRef = (0,
|
|
690
|
-
const onPreviousSceneRef = (0,
|
|
691
|
-
const onNextSceneRef = (0,
|
|
692
|
-
const keyMap = (0,
|
|
727
|
+
const pressedRef = (0, import_react6.useRef)(/* @__PURE__ */ new Set());
|
|
728
|
+
const shiftHeldRef = (0, import_react6.useRef)(false);
|
|
729
|
+
const invertRef = (0, import_react6.useRef)(invert);
|
|
730
|
+
const fovSpeedRef = (0, import_react6.useRef)(fovSpeed);
|
|
731
|
+
const onPreviousSceneRef = (0, import_react6.useRef)(onPreviousScene);
|
|
732
|
+
const onNextSceneRef = (0, import_react6.useRef)(onNextScene);
|
|
733
|
+
const keyMap = (0, import_react6.useMemo)(() => resolveKeyMap(keys), [keys]);
|
|
693
734
|
if (!controlsRef) {
|
|
694
|
-
throw new Error("<KeyboardControls> must be rendered inside <
|
|
735
|
+
throw new Error("<KeyboardControls> must be rendered inside <PanoViewer>.");
|
|
695
736
|
}
|
|
696
737
|
invertRef.current = invert;
|
|
697
738
|
fovSpeedRef.current = fovSpeed;
|
|
698
739
|
onPreviousSceneRef.current = onPreviousScene;
|
|
699
740
|
onNextSceneRef.current = onNextScene;
|
|
700
|
-
(0,
|
|
741
|
+
(0, import_react6.useEffect)(() => {
|
|
701
742
|
const element = gl.domElement;
|
|
702
743
|
if (!enabled) {
|
|
703
744
|
pressedRef.current.clear();
|
|
@@ -838,7 +879,7 @@ function KeyboardControls({
|
|
|
838
879
|
|
|
839
880
|
// src/mouse-controls.tsx
|
|
840
881
|
var import_fiber4 = require("@react-three/fiber");
|
|
841
|
-
var
|
|
882
|
+
var import_react7 = require("react");
|
|
842
883
|
var DEFAULT_ROTATE_SPEED2 = 0.35;
|
|
843
884
|
var DEFAULT_ZOOM_SPEED2 = 0.08;
|
|
844
885
|
var BUTTON_FLAG = {
|
|
@@ -862,12 +903,13 @@ function MouseControls({
|
|
|
862
903
|
buttons,
|
|
863
904
|
fovSpeed
|
|
864
905
|
}) {
|
|
865
|
-
|
|
906
|
+
useClaimControlChannel("mouse");
|
|
907
|
+
const controlsRef = (0, import_react7.useContext)(PanoramaViewContext);
|
|
866
908
|
const { gl } = (0, import_fiber4.useThree)();
|
|
867
|
-
const pointersRef = (0,
|
|
909
|
+
const pointersRef = (0, import_react7.useRef)(
|
|
868
910
|
/* @__PURE__ */ new Map()
|
|
869
911
|
);
|
|
870
|
-
const optionsRef = (0,
|
|
912
|
+
const optionsRef = (0, import_react7.useRef)({
|
|
871
913
|
rotateSpeed,
|
|
872
914
|
zoomSpeed,
|
|
873
915
|
wheel,
|
|
@@ -875,7 +917,7 @@ function MouseControls({
|
|
|
875
917
|
fovSpeed
|
|
876
918
|
});
|
|
877
919
|
if (!controlsRef) {
|
|
878
|
-
throw new Error("<MouseControls> must be rendered inside <
|
|
920
|
+
throw new Error("<MouseControls> must be rendered inside <PanoViewer>.");
|
|
879
921
|
}
|
|
880
922
|
optionsRef.current = {
|
|
881
923
|
rotateSpeed,
|
|
@@ -884,7 +926,7 @@ function MouseControls({
|
|
|
884
926
|
invert,
|
|
885
927
|
fovSpeed
|
|
886
928
|
};
|
|
887
|
-
(0,
|
|
929
|
+
(0, import_react7.useEffect)(() => {
|
|
888
930
|
const element = gl.domElement;
|
|
889
931
|
const allowedButtons = resolveButtons(buttons);
|
|
890
932
|
const clearPointers = () => {
|
|
@@ -1008,12 +1050,12 @@ function MouseControls({
|
|
|
1008
1050
|
}
|
|
1009
1051
|
|
|
1010
1052
|
// src/pano-context-menu.tsx
|
|
1011
|
-
var
|
|
1053
|
+
var import_react8 = require("react");
|
|
1012
1054
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
1013
1055
|
var DEFAULT_ICON_SIZE = 16;
|
|
1014
1056
|
var MENU_EDGE_PADDING = 8;
|
|
1015
1057
|
var MIN_PANO_CONTEXT_MENU_BACKGROUND_OPACITY = 0.4;
|
|
1016
|
-
var PanoContextMenuOverlayContext = (0,
|
|
1058
|
+
var PanoContextMenuOverlayContext = (0, import_react8.createContext)(null);
|
|
1017
1059
|
var DEFAULT_APPEARANCE = {
|
|
1018
1060
|
background: "#161616",
|
|
1019
1061
|
color: "#f4f4f4",
|
|
@@ -1053,11 +1095,11 @@ function DefaultContextMenuPanel({
|
|
|
1053
1095
|
selectContext,
|
|
1054
1096
|
onRequestClose
|
|
1055
1097
|
}) {
|
|
1056
|
-
const menuRef = (0,
|
|
1057
|
-
const [activeIndex, setActiveIndex] = (0,
|
|
1098
|
+
const menuRef = (0, import_react8.useRef)(null);
|
|
1099
|
+
const [activeIndex, setActiveIndex] = (0, import_react8.useState)(0);
|
|
1058
1100
|
const resolved = { ...DEFAULT_APPEARANCE, ...appearance };
|
|
1059
1101
|
const iconSize = Number.isFinite(resolved.iconSize) ? Math.max(0, resolved.iconSize) : DEFAULT_ICON_SIZE;
|
|
1060
|
-
const visibleItems = (0,
|
|
1102
|
+
const visibleItems = (0, import_react8.useMemo)(
|
|
1061
1103
|
() => items.filter((item) => {
|
|
1062
1104
|
if (!isActionItem(item)) {
|
|
1063
1105
|
return true;
|
|
@@ -1066,7 +1108,7 @@ function DefaultContextMenuPanel({
|
|
|
1066
1108
|
}),
|
|
1067
1109
|
[items]
|
|
1068
1110
|
);
|
|
1069
|
-
const focusableIndices = (0,
|
|
1111
|
+
const focusableIndices = (0, import_react8.useMemo)(() => {
|
|
1070
1112
|
const indices = [];
|
|
1071
1113
|
visibleItems.forEach((item, index) => {
|
|
1072
1114
|
if (isActionItem(item) && !item.disabled) {
|
|
@@ -1075,7 +1117,7 @@ function DefaultContextMenuPanel({
|
|
|
1075
1117
|
});
|
|
1076
1118
|
return indices;
|
|
1077
1119
|
}, [visibleItems]);
|
|
1078
|
-
(0,
|
|
1120
|
+
(0, import_react8.useEffect)(() => {
|
|
1079
1121
|
const first = focusableIndices[0];
|
|
1080
1122
|
setActiveIndex(first ?? 0);
|
|
1081
1123
|
const frame = requestAnimationFrame(() => {
|
|
@@ -1086,7 +1128,7 @@ function DefaultContextMenuPanel({
|
|
|
1086
1128
|
});
|
|
1087
1129
|
return () => cancelAnimationFrame(frame);
|
|
1088
1130
|
}, [focusableIndices]);
|
|
1089
|
-
const activateItem = (0,
|
|
1131
|
+
const activateItem = (0, import_react8.useCallback)(
|
|
1090
1132
|
(item) => {
|
|
1091
1133
|
if (item.disabled) {
|
|
1092
1134
|
return;
|
|
@@ -1301,9 +1343,9 @@ function PositionedMenuShell({
|
|
|
1301
1343
|
overlayElement,
|
|
1302
1344
|
children
|
|
1303
1345
|
}) {
|
|
1304
|
-
const shellRef = (0,
|
|
1305
|
-
const [offset, setOffset] = (0,
|
|
1306
|
-
(0,
|
|
1346
|
+
const shellRef = (0, import_react8.useRef)(null);
|
|
1347
|
+
const [offset, setOffset] = (0, import_react8.useState)({ left: 0, top: 0 });
|
|
1348
|
+
(0, import_react8.useLayoutEffect)(() => {
|
|
1307
1349
|
const shell = shellRef.current;
|
|
1308
1350
|
if (!overlayElement || !shell) {
|
|
1309
1351
|
return;
|
|
@@ -1340,20 +1382,20 @@ function PositionedMenuShell({
|
|
|
1340
1382
|
);
|
|
1341
1383
|
}
|
|
1342
1384
|
function usePanoContextMenuOverlay() {
|
|
1343
|
-
const [session, setSession] = (0,
|
|
1344
|
-
const overlayRef = (0,
|
|
1345
|
-
const [overlayElement, setOverlayElement] = (0,
|
|
1385
|
+
const [session, setSession] = (0, import_react8.useState)(null);
|
|
1386
|
+
const overlayRef = (0, import_react8.useRef)(null);
|
|
1387
|
+
const [overlayElement, setOverlayElement] = (0, import_react8.useState)(
|
|
1346
1388
|
null
|
|
1347
1389
|
);
|
|
1348
|
-
const api = (0,
|
|
1390
|
+
const api = (0, import_react8.useMemo)(
|
|
1349
1391
|
() => ({ setSession, overlayRef }),
|
|
1350
1392
|
[]
|
|
1351
1393
|
);
|
|
1352
|
-
const setOverlayNode = (0,
|
|
1394
|
+
const setOverlayNode = (0, import_react8.useCallback)((node) => {
|
|
1353
1395
|
overlayRef.current = node;
|
|
1354
1396
|
setOverlayElement(node);
|
|
1355
1397
|
}, []);
|
|
1356
|
-
(0,
|
|
1398
|
+
(0, import_react8.useEffect)(() => {
|
|
1357
1399
|
if (!session) {
|
|
1358
1400
|
return;
|
|
1359
1401
|
}
|
|
@@ -1421,13 +1463,13 @@ function PanoContextMenu({
|
|
|
1421
1463
|
separatorClassName,
|
|
1422
1464
|
children
|
|
1423
1465
|
}) {
|
|
1424
|
-
const eventBus = (0,
|
|
1425
|
-
const controlsRef = (0,
|
|
1426
|
-
const overlayApi = (0,
|
|
1427
|
-
const actions = (0,
|
|
1428
|
-
const instanceId = (0,
|
|
1429
|
-
const sessionKeyRef = (0,
|
|
1430
|
-
const propsRef = (0,
|
|
1466
|
+
const eventBus = (0, import_react8.useContext)(PanoEventBusContext);
|
|
1467
|
+
const controlsRef = (0, import_react8.useContext)(PanoramaViewContext);
|
|
1468
|
+
const overlayApi = (0, import_react8.useContext)(PanoContextMenuOverlayContext);
|
|
1469
|
+
const actions = (0, import_react8.useContext)(PanoContextMenuActionsContext);
|
|
1470
|
+
const instanceId = (0, import_react8.useId)();
|
|
1471
|
+
const sessionKeyRef = (0, import_react8.useRef)(0);
|
|
1472
|
+
const propsRef = (0, import_react8.useRef)({
|
|
1431
1473
|
items,
|
|
1432
1474
|
prepend,
|
|
1433
1475
|
append,
|
|
@@ -1450,17 +1492,17 @@ function PanoContextMenu({
|
|
|
1450
1492
|
children
|
|
1451
1493
|
};
|
|
1452
1494
|
if (!eventBus || !controlsRef) {
|
|
1453
|
-
throw new Error("<PanoContextMenu> must be rendered inside <
|
|
1495
|
+
throw new Error("<PanoContextMenu> must be rendered inside <PanoViewer>.");
|
|
1454
1496
|
}
|
|
1455
1497
|
if (!overlayApi) {
|
|
1456
1498
|
throw new Error(
|
|
1457
|
-
"<PanoContextMenu> requires the
|
|
1499
|
+
"<PanoContextMenu> requires the PanoViewer context-menu overlay host."
|
|
1458
1500
|
);
|
|
1459
1501
|
}
|
|
1460
|
-
const close = (0,
|
|
1502
|
+
const close = (0, import_react8.useCallback)(() => {
|
|
1461
1503
|
overlayApi.setSession(null);
|
|
1462
1504
|
}, [overlayApi]);
|
|
1463
|
-
const openMenu = (0,
|
|
1505
|
+
const openMenu = (0, import_react8.useCallback)(
|
|
1464
1506
|
(event) => {
|
|
1465
1507
|
event.nativeEvent.preventDefault();
|
|
1466
1508
|
const view = controlsRef.current?.getView() ?? {
|
|
@@ -1509,7 +1551,7 @@ function PanoContextMenu({
|
|
|
1509
1551
|
},
|
|
1510
1552
|
[actions, close, controlsRef, instanceId, overlayApi]
|
|
1511
1553
|
);
|
|
1512
|
-
(0,
|
|
1554
|
+
(0, import_react8.useEffect)(() => {
|
|
1513
1555
|
const unsubscribeContextMenu = eventBus.subscribe(
|
|
1514
1556
|
"contextmenu",
|
|
1515
1557
|
openMenu
|
|
@@ -1688,11 +1730,156 @@ function composePanoContextMenuItems(props, presets) {
|
|
|
1688
1730
|
...resolvePanoContextMenuEntries(props.append ?? [], presets)
|
|
1689
1731
|
];
|
|
1690
1732
|
}
|
|
1691
|
-
var PanoContextMenuActionsContext = (0,
|
|
1733
|
+
var PanoContextMenuActionsContext = (0, import_react8.createContext)(null);
|
|
1692
1734
|
|
|
1693
|
-
// src/pano-
|
|
1735
|
+
// src/pano-cursor.tsx
|
|
1694
1736
|
var import_fiber5 = require("@react-three/fiber");
|
|
1695
|
-
var
|
|
1737
|
+
var import_react9 = require("react");
|
|
1738
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1739
|
+
var DEFAULT_PANO_CURSORS = {
|
|
1740
|
+
default: "grab",
|
|
1741
|
+
dragging: "grabbing",
|
|
1742
|
+
hotspot: "pointer",
|
|
1743
|
+
hotspotDragging: "move"
|
|
1744
|
+
};
|
|
1745
|
+
var PANO_DRAG_CLAIM_ID = "pano-cursor:dragging";
|
|
1746
|
+
var LAYER_PRIORITY = {
|
|
1747
|
+
dragging: 1,
|
|
1748
|
+
hotspot: 2,
|
|
1749
|
+
hotspotDragging: 3
|
|
1750
|
+
};
|
|
1751
|
+
var PanoCursorContext = (0, import_react9.createContext)(null);
|
|
1752
|
+
function usePanoCursor() {
|
|
1753
|
+
return (0, import_react9.useContext)(PanoCursorContext);
|
|
1754
|
+
}
|
|
1755
|
+
function hotspotCursorClaimId(id) {
|
|
1756
|
+
return `pano-cursor:hotspot:${id}`;
|
|
1757
|
+
}
|
|
1758
|
+
function resolveClaimCursor(claim, cursors) {
|
|
1759
|
+
switch (claim.layer) {
|
|
1760
|
+
case "dragging":
|
|
1761
|
+
return cursors.dragging;
|
|
1762
|
+
case "hotspot":
|
|
1763
|
+
return claim.cursor ?? cursors.hotspot;
|
|
1764
|
+
case "hotspotDragging":
|
|
1765
|
+
return claim.cursor ?? cursors.hotspotDragging;
|
|
1766
|
+
default: {
|
|
1767
|
+
const exhaustive = claim.layer;
|
|
1768
|
+
return exhaustive;
|
|
1769
|
+
}
|
|
1770
|
+
}
|
|
1771
|
+
}
|
|
1772
|
+
function resolveHighestCursor(claims, cursors) {
|
|
1773
|
+
let best = null;
|
|
1774
|
+
let bestPriority = 0;
|
|
1775
|
+
for (const claim of claims.values()) {
|
|
1776
|
+
const priority = LAYER_PRIORITY[claim.layer];
|
|
1777
|
+
if (priority >= bestPriority) {
|
|
1778
|
+
best = claim;
|
|
1779
|
+
bestPriority = priority;
|
|
1780
|
+
}
|
|
1781
|
+
}
|
|
1782
|
+
return best ? resolveClaimCursor(best, cursors) : cursors.default;
|
|
1783
|
+
}
|
|
1784
|
+
function resolvePanoCursors(value) {
|
|
1785
|
+
if (value === false) {
|
|
1786
|
+
return null;
|
|
1787
|
+
}
|
|
1788
|
+
if (value === true || value === void 0) {
|
|
1789
|
+
return DEFAULT_PANO_CURSORS;
|
|
1790
|
+
}
|
|
1791
|
+
return {
|
|
1792
|
+
default: value.default ?? DEFAULT_PANO_CURSORS.default,
|
|
1793
|
+
dragging: value.dragging ?? DEFAULT_PANO_CURSORS.dragging,
|
|
1794
|
+
hotspot: value.hotspot ?? DEFAULT_PANO_CURSORS.hotspot,
|
|
1795
|
+
hotspotDragging: value.hotspotDragging ?? DEFAULT_PANO_CURSORS.hotspotDragging
|
|
1796
|
+
};
|
|
1797
|
+
}
|
|
1798
|
+
function PanoCursorController({
|
|
1799
|
+
cursors,
|
|
1800
|
+
children
|
|
1801
|
+
}) {
|
|
1802
|
+
const { gl } = (0, import_fiber5.useThree)();
|
|
1803
|
+
const eventBus = (0, import_react9.useContext)(PanoEventBusContext);
|
|
1804
|
+
const claimsRef = (0, import_react9.useRef)(/* @__PURE__ */ new Map());
|
|
1805
|
+
const cursorsRef = (0, import_react9.useRef)(cursors);
|
|
1806
|
+
const appliedCursorRef = (0, import_react9.useRef)(null);
|
|
1807
|
+
cursorsRef.current = cursors;
|
|
1808
|
+
const applyCursor = (0, import_react9.useCallback)(() => {
|
|
1809
|
+
const next = resolveHighestCursor(claimsRef.current, cursorsRef.current);
|
|
1810
|
+
const element = gl.domElement;
|
|
1811
|
+
if (appliedCursorRef.current === next && element.style.cursor === next) {
|
|
1812
|
+
return;
|
|
1813
|
+
}
|
|
1814
|
+
element.style.cursor = next;
|
|
1815
|
+
appliedCursorRef.current = next;
|
|
1816
|
+
}, [gl]);
|
|
1817
|
+
const claim = (0, import_react9.useCallback)(
|
|
1818
|
+
(id, layer, cursor) => {
|
|
1819
|
+
claimsRef.current.set(id, { layer, cursor });
|
|
1820
|
+
applyCursor();
|
|
1821
|
+
},
|
|
1822
|
+
[applyCursor]
|
|
1823
|
+
);
|
|
1824
|
+
const release = (0, import_react9.useCallback)(
|
|
1825
|
+
(id) => {
|
|
1826
|
+
if (claimsRef.current.delete(id)) {
|
|
1827
|
+
applyCursor();
|
|
1828
|
+
}
|
|
1829
|
+
},
|
|
1830
|
+
[applyCursor]
|
|
1831
|
+
);
|
|
1832
|
+
const api = (0, import_react9.useMemo)(
|
|
1833
|
+
() => ({
|
|
1834
|
+
cursors,
|
|
1835
|
+
claim,
|
|
1836
|
+
release
|
|
1837
|
+
}),
|
|
1838
|
+
[claim, cursors, release]
|
|
1839
|
+
);
|
|
1840
|
+
(0, import_react9.useEffect)(() => {
|
|
1841
|
+
const element = gl.domElement;
|
|
1842
|
+
const previous = element.style.cursor;
|
|
1843
|
+
return () => {
|
|
1844
|
+
claimsRef.current.clear();
|
|
1845
|
+
appliedCursorRef.current = null;
|
|
1846
|
+
element.style.cursor = previous;
|
|
1847
|
+
};
|
|
1848
|
+
}, [gl]);
|
|
1849
|
+
(0, import_react9.useEffect)(() => {
|
|
1850
|
+
applyCursor();
|
|
1851
|
+
}, [applyCursor, cursors]);
|
|
1852
|
+
(0, import_react9.useEffect)(() => {
|
|
1853
|
+
if (!eventBus) {
|
|
1854
|
+
return;
|
|
1855
|
+
}
|
|
1856
|
+
const unsubscribeStart = eventBus.subscribe(
|
|
1857
|
+
"viewinteractionstart",
|
|
1858
|
+
(event) => {
|
|
1859
|
+
if (event.source !== "mouse") {
|
|
1860
|
+
return;
|
|
1861
|
+
}
|
|
1862
|
+
claim(PANO_DRAG_CLAIM_ID, "dragging");
|
|
1863
|
+
}
|
|
1864
|
+
);
|
|
1865
|
+
const unsubscribeEnd = eventBus.subscribe("viewinteractionend", (event) => {
|
|
1866
|
+
if (event.source !== "mouse") {
|
|
1867
|
+
return;
|
|
1868
|
+
}
|
|
1869
|
+
release(PANO_DRAG_CLAIM_ID);
|
|
1870
|
+
});
|
|
1871
|
+
return () => {
|
|
1872
|
+
unsubscribeStart();
|
|
1873
|
+
unsubscribeEnd();
|
|
1874
|
+
release(PANO_DRAG_CLAIM_ID);
|
|
1875
|
+
};
|
|
1876
|
+
}, [claim, eventBus, release]);
|
|
1877
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PanoCursorContext.Provider, { value: api, children });
|
|
1878
|
+
}
|
|
1879
|
+
|
|
1880
|
+
// src/pano-events.tsx
|
|
1881
|
+
var import_fiber6 = require("@react-three/fiber");
|
|
1882
|
+
var import_react10 = require("react");
|
|
1696
1883
|
var DEFAULT_IDLE_TIME_MS = 2e3;
|
|
1697
1884
|
function resolveIdleTime(value) {
|
|
1698
1885
|
return Number.isFinite(value) && value >= 0 ? value : DEFAULT_IDLE_TIME_MS;
|
|
@@ -1719,13 +1906,13 @@ function usePanoEvents({
|
|
|
1719
1906
|
onAutoRotateStop,
|
|
1720
1907
|
onAutoRotateOneRound
|
|
1721
1908
|
}) {
|
|
1722
|
-
const eventBus = (0,
|
|
1723
|
-
const controlsRef = (0,
|
|
1724
|
-
const { gl } = (0,
|
|
1909
|
+
const eventBus = (0, import_react10.useContext)(PanoEventBusContext);
|
|
1910
|
+
const controlsRef = (0, import_react10.useContext)(PanoramaViewContext);
|
|
1911
|
+
const { gl } = (0, import_fiber6.useThree)();
|
|
1725
1912
|
if (!eventBus || !controlsRef) {
|
|
1726
|
-
throw new Error("usePanoEvents must be used inside <
|
|
1913
|
+
throw new Error("usePanoEvents must be used inside <PanoViewer>.");
|
|
1727
1914
|
}
|
|
1728
|
-
const callbacksRef = (0,
|
|
1915
|
+
const callbacksRef = (0, import_react10.useRef)({
|
|
1729
1916
|
onViewChange,
|
|
1730
1917
|
onViewSettled,
|
|
1731
1918
|
onViewInteractionStart,
|
|
@@ -1767,15 +1954,15 @@ function usePanoEvents({
|
|
|
1767
1954
|
onAutoRotateStop,
|
|
1768
1955
|
onAutoRotateOneRound
|
|
1769
1956
|
};
|
|
1770
|
-
const idleElapsedRef = (0,
|
|
1771
|
-
const isIdleRef = (0,
|
|
1772
|
-
const idleTimeRef = (0,
|
|
1957
|
+
const idleElapsedRef = (0, import_react10.useRef)(0);
|
|
1958
|
+
const isIdleRef = (0, import_react10.useRef)(false);
|
|
1959
|
+
const idleTimeRef = (0, import_react10.useRef)(resolveIdleTime(idleTime));
|
|
1773
1960
|
idleTimeRef.current = resolveIdleTime(idleTime);
|
|
1774
|
-
(0,
|
|
1961
|
+
(0, import_react10.useEffect)(() => {
|
|
1775
1962
|
idleElapsedRef.current = 0;
|
|
1776
1963
|
isIdleRef.current = false;
|
|
1777
1964
|
}, [idleTime]);
|
|
1778
|
-
(0,
|
|
1965
|
+
(0, import_react10.useEffect)(() => {
|
|
1779
1966
|
const unsubscribers = [
|
|
1780
1967
|
eventBus.subscribe("viewchange", (view) => {
|
|
1781
1968
|
callbacksRef.current.onViewChange?.(view);
|
|
@@ -1823,7 +2010,7 @@ function usePanoEvents({
|
|
|
1823
2010
|
}
|
|
1824
2011
|
};
|
|
1825
2012
|
}, [eventBus]);
|
|
1826
|
-
(0,
|
|
2013
|
+
(0, import_react10.useEffect)(() => {
|
|
1827
2014
|
const element = gl.domElement;
|
|
1828
2015
|
const handleWheel = (nativeEvent) => {
|
|
1829
2016
|
callbacksRef.current.onWheel?.({
|
|
@@ -1836,7 +2023,7 @@ function usePanoEvents({
|
|
|
1836
2023
|
element.removeEventListener("wheel", handleWheel);
|
|
1837
2024
|
};
|
|
1838
2025
|
}, [gl]);
|
|
1839
|
-
(0,
|
|
2026
|
+
(0, import_react10.useEffect)(() => {
|
|
1840
2027
|
if (typeof document === "undefined") {
|
|
1841
2028
|
return;
|
|
1842
2029
|
}
|
|
@@ -1865,7 +2052,7 @@ function usePanoEvents({
|
|
|
1865
2052
|
document.removeEventListener("fullscreenchange", handleFullscreenChange);
|
|
1866
2053
|
};
|
|
1867
2054
|
}, [gl]);
|
|
1868
|
-
(0,
|
|
2055
|
+
(0, import_react10.useEffect)(() => {
|
|
1869
2056
|
const element = gl.domElement;
|
|
1870
2057
|
if (typeof ResizeObserver === "undefined") {
|
|
1871
2058
|
return;
|
|
@@ -1883,7 +2070,7 @@ function usePanoEvents({
|
|
|
1883
2070
|
observer.disconnect();
|
|
1884
2071
|
};
|
|
1885
2072
|
}, [gl]);
|
|
1886
|
-
(0,
|
|
2073
|
+
(0, import_fiber6.useFrame)((_, deltaSeconds) => {
|
|
1887
2074
|
const interacting = controlsRef.current?.isUserInteracting() ?? false;
|
|
1888
2075
|
if (interacting) {
|
|
1889
2076
|
idleElapsedRef.current = 0;
|
|
@@ -1906,8 +2093,8 @@ function PanoEvents(props) {
|
|
|
1906
2093
|
}
|
|
1907
2094
|
|
|
1908
2095
|
// src/panorama-event-surface.tsx
|
|
1909
|
-
var
|
|
1910
|
-
var
|
|
2096
|
+
var import_fiber7 = require("@react-three/fiber");
|
|
2097
|
+
var import_react11 = require("react");
|
|
1911
2098
|
var import_three3 = require("three");
|
|
1912
2099
|
|
|
1913
2100
|
// src/hotspot/coordinates.ts
|
|
@@ -1973,7 +2160,7 @@ var DEFAULT_PANORAMA_CAMERA_NEAR = 0.1;
|
|
|
1973
2160
|
var DEFAULT_PANORAMA_CAMERA_FAR = DEFAULT_PANORAMA_RADIUS * 2;
|
|
1974
2161
|
|
|
1975
2162
|
// src/panorama-event-surface.tsx
|
|
1976
|
-
var
|
|
2163
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
1977
2164
|
var EVENT_SURFACE_RADIUS = DEFAULT_PANORAMA_RADIUS - 1;
|
|
1978
2165
|
function makePanoramaPointerEvent(event) {
|
|
1979
2166
|
const nativeEvent = event.nativeEvent;
|
|
@@ -1988,9 +2175,9 @@ function makePanoramaPointerEvent(event) {
|
|
|
1988
2175
|
};
|
|
1989
2176
|
}
|
|
1990
2177
|
function PanoramaEventSurface() {
|
|
1991
|
-
const eventBus = (0,
|
|
1992
|
-
const { camera, gl } = (0,
|
|
1993
|
-
(0,
|
|
2178
|
+
const eventBus = (0, import_react11.useContext)(PanoEventBusContext);
|
|
2179
|
+
const { camera, gl } = (0, import_fiber7.useThree)();
|
|
2180
|
+
(0, import_react11.useEffect)(() => {
|
|
1994
2181
|
if (!eventBus) {
|
|
1995
2182
|
return;
|
|
1996
2183
|
}
|
|
@@ -2031,7 +2218,7 @@ function PanoramaEventSurface() {
|
|
|
2031
2218
|
event.stopPropagation();
|
|
2032
2219
|
eventBus.emit(type, makePanoramaPointerEvent(event));
|
|
2033
2220
|
};
|
|
2034
|
-
return /* @__PURE__ */ (0,
|
|
2221
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
2035
2222
|
"mesh",
|
|
2036
2223
|
{
|
|
2037
2224
|
renderOrder: -200,
|
|
@@ -2041,8 +2228,8 @@ function PanoramaEventSurface() {
|
|
|
2041
2228
|
onPointerUp: (event) => emit("pointerup", event),
|
|
2042
2229
|
onPointerMove: (event) => emit("pointermove", event),
|
|
2043
2230
|
children: [
|
|
2044
|
-
/* @__PURE__ */ (0,
|
|
2045
|
-
/* @__PURE__ */ (0,
|
|
2231
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("sphereGeometry", { args: [EVENT_SURFACE_RADIUS, 64, 32] }),
|
|
2232
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2046
2233
|
"meshBasicMaterial",
|
|
2047
2234
|
{
|
|
2048
2235
|
colorWrite: false,
|
|
@@ -2059,8 +2246,8 @@ function PanoramaEventSurface() {
|
|
|
2059
2246
|
}
|
|
2060
2247
|
|
|
2061
2248
|
// src/touch-controls.tsx
|
|
2062
|
-
var
|
|
2063
|
-
var
|
|
2249
|
+
var import_fiber8 = require("@react-three/fiber");
|
|
2250
|
+
var import_react12 = require("react");
|
|
2064
2251
|
var DEFAULT_ROTATE_SPEED3 = 0.35;
|
|
2065
2252
|
function resolveSpeed3(value, fallback) {
|
|
2066
2253
|
return Number.isFinite(value) && value >= 0 ? value : fallback;
|
|
@@ -2074,16 +2261,17 @@ function TouchControls({
|
|
|
2074
2261
|
invert = false,
|
|
2075
2262
|
pinchZoom = true
|
|
2076
2263
|
}) {
|
|
2077
|
-
|
|
2078
|
-
const
|
|
2079
|
-
const
|
|
2080
|
-
const
|
|
2081
|
-
const
|
|
2264
|
+
useClaimControlChannel("touch");
|
|
2265
|
+
const controlsRef = (0, import_react12.useContext)(PanoramaViewContext);
|
|
2266
|
+
const { gl } = (0, import_fiber8.useThree)();
|
|
2267
|
+
const pointersRef = (0, import_react12.useRef)(/* @__PURE__ */ new Map());
|
|
2268
|
+
const pinchDistanceRef = (0, import_react12.useRef)(null);
|
|
2269
|
+
const optionsRef = (0, import_react12.useRef)({ rotateSpeed, invert, pinchZoom });
|
|
2082
2270
|
if (!controlsRef) {
|
|
2083
|
-
throw new Error("<TouchControls> must be rendered inside <
|
|
2271
|
+
throw new Error("<TouchControls> must be rendered inside <PanoViewer>.");
|
|
2084
2272
|
}
|
|
2085
2273
|
optionsRef.current = { rotateSpeed, invert, pinchZoom };
|
|
2086
|
-
(0,
|
|
2274
|
+
(0, import_react12.useEffect)(() => {
|
|
2087
2275
|
const element = gl.domElement;
|
|
2088
2276
|
const clearPointers = () => {
|
|
2089
2277
|
for (const pointerId of pointersRef.current.keys()) {
|
|
@@ -2204,8 +2392,8 @@ function TouchControls({
|
|
|
2204
2392
|
return null;
|
|
2205
2393
|
}
|
|
2206
2394
|
|
|
2207
|
-
// src/pano-
|
|
2208
|
-
var
|
|
2395
|
+
// src/pano-viewer.tsx
|
|
2396
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
2209
2397
|
var DEFAULT_VIEW = {
|
|
2210
2398
|
yaw: 0,
|
|
2211
2399
|
pitch: 0,
|
|
@@ -2243,13 +2431,46 @@ function resolveContextMenuChannel(value) {
|
|
|
2243
2431
|
}
|
|
2244
2432
|
return { mount: true, props: { ...value } };
|
|
2245
2433
|
}
|
|
2246
|
-
|
|
2247
|
-
|
|
2434
|
+
function PanoCursorTree({
|
|
2435
|
+
cursors,
|
|
2436
|
+
children
|
|
2437
|
+
}) {
|
|
2438
|
+
if (!cursors) {
|
|
2439
|
+
return children;
|
|
2440
|
+
}
|
|
2441
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PanoCursorController, { cursors, children });
|
|
2442
|
+
}
|
|
2443
|
+
function DefaultControlChannels({
|
|
2444
|
+
userControlsEnabled,
|
|
2445
|
+
mouseChannel,
|
|
2446
|
+
touchChannel,
|
|
2447
|
+
keyboardChannel,
|
|
2448
|
+
fovSpeed
|
|
2449
|
+
}) {
|
|
2450
|
+
const claims = (0, import_react13.useContext)(ControlClaimsContext);
|
|
2451
|
+
if (!claims) {
|
|
2452
|
+
return null;
|
|
2453
|
+
}
|
|
2454
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(DefaultControlChannelContext.Provider, { value: true, children: [
|
|
2455
|
+
userControlsEnabled && mouseChannel.mount && claims.mouse === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MouseControls, { ...mouseChannel.props, fovSpeed }) : null,
|
|
2456
|
+
userControlsEnabled && touchChannel.mount && claims.touch === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TouchControls, { ...touchChannel.props }) : null,
|
|
2457
|
+
userControlsEnabled && keyboardChannel.mount && claims.keyboard === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2458
|
+
KeyboardControls,
|
|
2459
|
+
{
|
|
2460
|
+
...keyboardChannel.props,
|
|
2461
|
+
fovSpeed: keyboardChannel.props.fovSpeed ?? fovSpeed
|
|
2462
|
+
}
|
|
2463
|
+
) : null
|
|
2464
|
+
] });
|
|
2465
|
+
}
|
|
2466
|
+
var PanoViewer = (0, import_react13.forwardRef)(
|
|
2467
|
+
function PanoViewer2({
|
|
2248
2468
|
children,
|
|
2249
2469
|
initialView,
|
|
2250
2470
|
minFov = 30,
|
|
2251
2471
|
maxFov = 100,
|
|
2252
2472
|
controls = true,
|
|
2473
|
+
cursors,
|
|
2253
2474
|
contextMenu = true,
|
|
2254
2475
|
onViewChange,
|
|
2255
2476
|
onPanoramaClick,
|
|
@@ -2260,18 +2481,18 @@ var PanoView = (0, import_react11.forwardRef)(
|
|
|
2260
2481
|
"aria-label": ariaLabel = "Panorama viewer",
|
|
2261
2482
|
...divProps
|
|
2262
2483
|
}, ref) {
|
|
2263
|
-
const rootRef = (0,
|
|
2264
|
-
const controlsRef = (0,
|
|
2265
|
-
const eventBus = (0,
|
|
2484
|
+
const rootRef = (0, import_react13.useRef)(null);
|
|
2485
|
+
const controlsRef = (0, import_react13.useRef)(null);
|
|
2486
|
+
const eventBus = (0, import_react13.useMemo)(() => createPanoEventBus(), []);
|
|
2266
2487
|
const { controls: hotspotAccessibilityControls, registry } = useHotspotAccessibilityLayer();
|
|
2267
2488
|
const { api: contextMenuOverlayApi, overlay: contextMenuOverlay } = usePanoContextMenuOverlay();
|
|
2268
|
-
const fallbackViewRef = (0,
|
|
2489
|
+
const fallbackViewRef = (0, import_react13.useRef)(DEFAULT_VIEW);
|
|
2269
2490
|
const normalizedMinFov = Math.max(1, Math.min(minFov, maxFov - 1));
|
|
2270
2491
|
const normalizedMaxFov = Math.min(
|
|
2271
2492
|
179,
|
|
2272
2493
|
Math.max(maxFov, normalizedMinFov + 1)
|
|
2273
2494
|
);
|
|
2274
|
-
const normalizedInitialView = (0,
|
|
2495
|
+
const normalizedInitialView = (0, import_react13.useMemo)(
|
|
2275
2496
|
() => ({
|
|
2276
2497
|
yaw: initialView?.yaw ?? DEFAULT_VIEW.yaw,
|
|
2277
2498
|
pitch: clampPanoPitch(initialView?.pitch ?? DEFAULT_VIEW.pitch),
|
|
@@ -2289,8 +2510,10 @@ var PanoView = (0, import_react11.forwardRef)(
|
|
|
2289
2510
|
]
|
|
2290
2511
|
);
|
|
2291
2512
|
fallbackViewRef.current = normalizedInitialView;
|
|
2513
|
+
const controlClaims = (0, import_react13.useMemo)(() => createControlClaims(), []);
|
|
2514
|
+
resetControlClaims(controlClaims);
|
|
2292
2515
|
const controlsEnabled = controls !== false;
|
|
2293
|
-
const controlOptions = (0,
|
|
2516
|
+
const controlOptions = (0, import_react13.useMemo)(
|
|
2294
2517
|
() => typeof controls === "object" ? controls : {},
|
|
2295
2518
|
[controls]
|
|
2296
2519
|
);
|
|
@@ -2298,7 +2521,7 @@ var PanoView = (0, import_react11.forwardRef)(
|
|
|
2298
2521
|
const allModeInvert = controlOptions.invert === true;
|
|
2299
2522
|
const topRotateSpeed = controlOptions.rotateSpeed ?? DEFAULT_POINTER_ROTATE_SPEED;
|
|
2300
2523
|
const topZoomSpeed = controlOptions.zoomSpeed ?? DEFAULT_MOUSE_ZOOM_SPEED;
|
|
2301
|
-
const mouseChannel = (0,
|
|
2524
|
+
const mouseChannel = (0, import_react13.useMemo)(
|
|
2302
2525
|
() => resolveChannel(controlOptions.mouse, {
|
|
2303
2526
|
enabled: true,
|
|
2304
2527
|
rotateSpeed: topRotateSpeed,
|
|
@@ -2314,7 +2537,7 @@ var PanoView = (0, import_react11.forwardRef)(
|
|
|
2314
2537
|
topZoomSpeed
|
|
2315
2538
|
]
|
|
2316
2539
|
);
|
|
2317
|
-
const touchChannel = (0,
|
|
2540
|
+
const touchChannel = (0, import_react13.useMemo)(
|
|
2318
2541
|
() => resolveChannel(controlOptions.touch, {
|
|
2319
2542
|
enabled: true,
|
|
2320
2543
|
rotateSpeed: topRotateSpeed,
|
|
@@ -2323,13 +2546,13 @@ var PanoView = (0, import_react11.forwardRef)(
|
|
|
2323
2546
|
}),
|
|
2324
2547
|
[allModeInvert, controlOptions.touch, topRotateSpeed]
|
|
2325
2548
|
);
|
|
2326
|
-
const keyboardChannel = (0,
|
|
2549
|
+
const keyboardChannel = (0, import_react13.useMemo)(
|
|
2327
2550
|
() => resolveChannel(controlOptions.keyboard, {
|
|
2328
2551
|
enabled: true
|
|
2329
2552
|
}),
|
|
2330
2553
|
[controlOptions.keyboard]
|
|
2331
2554
|
);
|
|
2332
|
-
const toggleFullscreen = (0,
|
|
2555
|
+
const toggleFullscreen = (0, import_react13.useCallback)(async () => {
|
|
2333
2556
|
if (typeof document === "undefined") {
|
|
2334
2557
|
return;
|
|
2335
2558
|
}
|
|
@@ -2339,8 +2562,8 @@ var PanoView = (0, import_react11.forwardRef)(
|
|
|
2339
2562
|
}
|
|
2340
2563
|
await rootRef.current?.requestFullscreen?.();
|
|
2341
2564
|
}, []);
|
|
2342
|
-
const [isViewerFullscreen, setIsViewerFullscreen] = (0,
|
|
2343
|
-
(0,
|
|
2565
|
+
const [isViewerFullscreen, setIsViewerFullscreen] = (0, import_react13.useState)(false);
|
|
2566
|
+
(0, import_react13.useEffect)(() => {
|
|
2344
2567
|
if (typeof document === "undefined") {
|
|
2345
2568
|
return;
|
|
2346
2569
|
}
|
|
@@ -2361,7 +2584,7 @@ var PanoView = (0, import_react11.forwardRef)(
|
|
|
2361
2584
|
document.removeEventListener("fullscreenchange", syncFullscreen);
|
|
2362
2585
|
};
|
|
2363
2586
|
}, []);
|
|
2364
|
-
const contextMenuActions = (0,
|
|
2587
|
+
const contextMenuActions = (0, import_react13.useMemo)(
|
|
2365
2588
|
() => ({
|
|
2366
2589
|
reset: () => {
|
|
2367
2590
|
controlsRef.current?.reset();
|
|
@@ -2373,18 +2596,22 @@ var PanoView = (0, import_react11.forwardRef)(
|
|
|
2373
2596
|
}),
|
|
2374
2597
|
[isViewerFullscreen, toggleFullscreen]
|
|
2375
2598
|
);
|
|
2376
|
-
const contextMenuChannel = (0,
|
|
2599
|
+
const contextMenuChannel = (0, import_react13.useMemo)(
|
|
2377
2600
|
() => resolveContextMenuChannel(contextMenu),
|
|
2378
2601
|
[contextMenu]
|
|
2379
2602
|
);
|
|
2603
|
+
const resolvedCursors = (0, import_react13.useMemo)(
|
|
2604
|
+
() => resolvePanoCursors(cursors),
|
|
2605
|
+
[cursors]
|
|
2606
|
+
);
|
|
2380
2607
|
const legacyAutoRotateOptions = controlOptions;
|
|
2381
|
-
const [legacyAutoRotate, setLegacyAutoRotate] = (0,
|
|
2608
|
+
const [legacyAutoRotate, setLegacyAutoRotate] = (0, import_react13.useState)(
|
|
2382
2609
|
legacyAutoRotateOptions.autoRotate ?? false
|
|
2383
2610
|
);
|
|
2384
|
-
(0,
|
|
2611
|
+
(0, import_react13.useEffect)(() => {
|
|
2385
2612
|
setLegacyAutoRotate(legacyAutoRotateOptions.autoRotate ?? false);
|
|
2386
2613
|
}, [legacyAutoRotateOptions.autoRotate]);
|
|
2387
|
-
(0,
|
|
2614
|
+
(0, import_react13.useImperativeHandle)(
|
|
2388
2615
|
ref,
|
|
2389
2616
|
() => ({
|
|
2390
2617
|
getView: () => controlsRef.current?.getView() ?? { ...fallbackViewRef.current },
|
|
@@ -2404,7 +2631,7 @@ var PanoView = (0, import_react11.forwardRef)(
|
|
|
2404
2631
|
}),
|
|
2405
2632
|
[toggleFullscreen]
|
|
2406
2633
|
);
|
|
2407
|
-
const rootStyle = (0,
|
|
2634
|
+
const rootStyle = (0, import_react13.useMemo)(
|
|
2408
2635
|
() => ({
|
|
2409
2636
|
overflow: "hidden",
|
|
2410
2637
|
position: "relative",
|
|
@@ -2412,7 +2639,7 @@ var PanoView = (0, import_react11.forwardRef)(
|
|
|
2412
2639
|
}),
|
|
2413
2640
|
[style]
|
|
2414
2641
|
);
|
|
2415
|
-
return /* @__PURE__ */ (0,
|
|
2642
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
2416
2643
|
"div",
|
|
2417
2644
|
{
|
|
2418
2645
|
...divProps,
|
|
@@ -2420,8 +2647,8 @@ var PanoView = (0, import_react11.forwardRef)(
|
|
|
2420
2647
|
"aria-label": ariaLabel,
|
|
2421
2648
|
style: rootStyle,
|
|
2422
2649
|
children: [
|
|
2423
|
-
/* @__PURE__ */ (0,
|
|
2424
|
-
|
|
2650
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2651
|
+
import_fiber9.Canvas,
|
|
2425
2652
|
{
|
|
2426
2653
|
"aria-label": `${ariaLabel} canvas`,
|
|
2427
2654
|
camera: {
|
|
@@ -2443,16 +2670,16 @@ var PanoView = (0, import_react11.forwardRef)(
|
|
|
2443
2670
|
touchAction: userControlsEnabled ? "none" : "auto"
|
|
2444
2671
|
},
|
|
2445
2672
|
tabIndex: userControlsEnabled ? 0 : void 0,
|
|
2446
|
-
children: /* @__PURE__ */ (0,
|
|
2673
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(HotspotAccessibilityContext.Provider, { value: registry, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PanoEventBusContext.Provider, { value: eventBus, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PanoCursorTree, { cursors: resolvedCursors, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PanoramaViewContext.Provider, { value: controlsRef, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2447
2674
|
PanoContextMenuOverlayContext.Provider,
|
|
2448
2675
|
{
|
|
2449
2676
|
value: contextMenuOverlayApi,
|
|
2450
|
-
children: /* @__PURE__ */ (0,
|
|
2677
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
2451
2678
|
PanoContextMenuActionsContext.Provider,
|
|
2452
2679
|
{
|
|
2453
2680
|
value: contextMenuActions,
|
|
2454
2681
|
children: [
|
|
2455
|
-
/* @__PURE__ */ (0,
|
|
2682
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2456
2683
|
PanoramaViewRuntime,
|
|
2457
2684
|
{
|
|
2458
2685
|
ref: controlsRef,
|
|
@@ -2463,7 +2690,7 @@ var PanoView = (0, import_react11.forwardRef)(
|
|
|
2463
2690
|
options: controlOptions
|
|
2464
2691
|
}
|
|
2465
2692
|
),
|
|
2466
|
-
(onViewChange || onPanoramaClick || onPanoramaDoubleClick || onPanoramaPointerMove) && /* @__PURE__ */ (0,
|
|
2693
|
+
(onViewChange || onPanoramaClick || onPanoramaDoubleClick || onPanoramaPointerMove) && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2467
2694
|
PanoEvents,
|
|
2468
2695
|
{
|
|
2469
2696
|
onViewChange,
|
|
@@ -2472,36 +2699,33 @@ var PanoView = (0, import_react11.forwardRef)(
|
|
|
2472
2699
|
onPointerMove: onPanoramaPointerMove
|
|
2473
2700
|
}
|
|
2474
2701
|
),
|
|
2475
|
-
/* @__PURE__ */ (0,
|
|
2702
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2476
2703
|
AutoRotate,
|
|
2477
2704
|
{
|
|
2478
2705
|
enabled: legacyAutoRotate,
|
|
2479
2706
|
speed: legacyAutoRotateOptions.autoRotateSpeed
|
|
2480
2707
|
}
|
|
2481
2708
|
),
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
)
|
|
2497
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PanoramaEventSurface, {}),
|
|
2498
|
-
contextMenuChannel.mount ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PanoContextMenu, { ...contextMenuChannel.props }) : null,
|
|
2499
|
-
children
|
|
2709
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PanoramaEventSurface, {}),
|
|
2710
|
+
contextMenuChannel.mount ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PanoContextMenu, { ...contextMenuChannel.props }) : null,
|
|
2711
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(ControlClaimsContext.Provider, { value: controlClaims, children: [
|
|
2712
|
+
children,
|
|
2713
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2714
|
+
DefaultControlChannels,
|
|
2715
|
+
{
|
|
2716
|
+
fovSpeed: controlOptions.fovSpeed,
|
|
2717
|
+
keyboardChannel,
|
|
2718
|
+
mouseChannel,
|
|
2719
|
+
touchChannel,
|
|
2720
|
+
userControlsEnabled
|
|
2721
|
+
}
|
|
2722
|
+
)
|
|
2723
|
+
] })
|
|
2500
2724
|
]
|
|
2501
2725
|
}
|
|
2502
2726
|
)
|
|
2503
2727
|
}
|
|
2504
|
-
) }) }) })
|
|
2728
|
+
) }) }) }) })
|
|
2505
2729
|
}
|
|
2506
2730
|
),
|
|
2507
2731
|
contextMenuOverlay,
|
|
@@ -2513,10 +2737,10 @@ var PanoView = (0, import_react11.forwardRef)(
|
|
|
2513
2737
|
);
|
|
2514
2738
|
|
|
2515
2739
|
// src/sphere.tsx
|
|
2516
|
-
var
|
|
2517
|
-
var
|
|
2740
|
+
var import_fiber10 = require("@react-three/fiber");
|
|
2741
|
+
var import_react14 = require("react");
|
|
2518
2742
|
var import_three4 = require("three");
|
|
2519
|
-
var
|
|
2743
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
2520
2744
|
function Sphere({
|
|
2521
2745
|
src,
|
|
2522
2746
|
yawOffset = 0,
|
|
@@ -2524,13 +2748,13 @@ function Sphere({
|
|
|
2524
2748
|
onError,
|
|
2525
2749
|
visible = true
|
|
2526
2750
|
}) {
|
|
2527
|
-
const gl = (0,
|
|
2528
|
-
const [texture, setTexture] = (0,
|
|
2529
|
-
const onLoadRef = (0,
|
|
2530
|
-
const onErrorRef = (0,
|
|
2751
|
+
const gl = (0, import_fiber10.useThree)((state) => state.gl);
|
|
2752
|
+
const [texture, setTexture] = (0, import_react14.useState)(null);
|
|
2753
|
+
const onLoadRef = (0, import_react14.useRef)(onLoad);
|
|
2754
|
+
const onErrorRef = (0, import_react14.useRef)(onError);
|
|
2531
2755
|
onLoadRef.current = onLoad;
|
|
2532
2756
|
onErrorRef.current = onError;
|
|
2533
|
-
(0,
|
|
2757
|
+
(0, import_react14.useEffect)(() => {
|
|
2534
2758
|
let active = true;
|
|
2535
2759
|
const loader = new import_three4.TextureLoader();
|
|
2536
2760
|
setTexture(null);
|
|
@@ -2564,7 +2788,7 @@ function Sphere({
|
|
|
2564
2788
|
active = false;
|
|
2565
2789
|
};
|
|
2566
2790
|
}, [gl, src]);
|
|
2567
|
-
(0,
|
|
2791
|
+
(0, import_react14.useEffect)(
|
|
2568
2792
|
() => () => {
|
|
2569
2793
|
texture?.dispose();
|
|
2570
2794
|
},
|
|
@@ -2573,14 +2797,14 @@ function Sphere({
|
|
|
2573
2797
|
if (!texture) {
|
|
2574
2798
|
return null;
|
|
2575
2799
|
}
|
|
2576
|
-
return /* @__PURE__ */ (0,
|
|
2800
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
2577
2801
|
"mesh",
|
|
2578
2802
|
{
|
|
2579
2803
|
rotation: [0, import_three4.MathUtils.degToRad(90 + yawOffset), 0],
|
|
2580
2804
|
visible,
|
|
2581
2805
|
children: [
|
|
2582
|
-
/* @__PURE__ */ (0,
|
|
2583
|
-
/* @__PURE__ */ (0,
|
|
2806
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("sphereGeometry", { args: [DEFAULT_PANORAMA_RADIUS, 128, 64] }),
|
|
2807
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2584
2808
|
"meshBasicMaterial",
|
|
2585
2809
|
{
|
|
2586
2810
|
map: texture,
|
|
@@ -2593,14 +2817,14 @@ function Sphere({
|
|
|
2593
2817
|
);
|
|
2594
2818
|
}
|
|
2595
2819
|
|
|
2596
|
-
// src/
|
|
2597
|
-
var
|
|
2598
|
-
var
|
|
2820
|
+
// src/scenes.tsx
|
|
2821
|
+
var import_fiber13 = require("@react-three/fiber");
|
|
2822
|
+
var import_react17 = require("react");
|
|
2599
2823
|
var import_three8 = require("three");
|
|
2600
2824
|
|
|
2601
2825
|
// src/tile/texture-manager-context.tsx
|
|
2602
|
-
var
|
|
2603
|
-
var
|
|
2826
|
+
var import_fiber11 = require("@react-three/fiber");
|
|
2827
|
+
var import_react15 = require("react");
|
|
2604
2828
|
|
|
2605
2829
|
// src/tile/texture-manager.ts
|
|
2606
2830
|
var import_three5 = require("three");
|
|
@@ -2824,8 +3048,8 @@ var TileTextureManager = class {
|
|
|
2824
3048
|
};
|
|
2825
3049
|
|
|
2826
3050
|
// src/tile/texture-manager-context.tsx
|
|
2827
|
-
var
|
|
2828
|
-
var TileTextureManagerContext = (0,
|
|
3051
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
3052
|
+
var TileTextureManagerContext = (0, import_react15.createContext)(
|
|
2829
3053
|
null
|
|
2830
3054
|
);
|
|
2831
3055
|
function TileTextureManagerProvider({
|
|
@@ -2833,9 +3057,9 @@ function TileTextureManagerProvider({
|
|
|
2833
3057
|
maxTextureMemoryMb = 128,
|
|
2834
3058
|
maxConcurrentLoads = 4
|
|
2835
3059
|
}) {
|
|
2836
|
-
const gl = (0,
|
|
3060
|
+
const gl = (0, import_fiber11.useThree)((state) => state.gl);
|
|
2837
3061
|
const anisotropy = gl.capabilities.getMaxAnisotropy();
|
|
2838
|
-
const manager = (0,
|
|
3062
|
+
const manager = (0, import_react15.useMemo)(
|
|
2839
3063
|
() => new TileTextureManager({
|
|
2840
3064
|
anisotropy,
|
|
2841
3065
|
maxBytes: Math.max(1, maxTextureMemoryMb) * 1024 * 1024,
|
|
@@ -2844,19 +3068,19 @@ function TileTextureManagerProvider({
|
|
|
2844
3068
|
}),
|
|
2845
3069
|
[anisotropy, maxConcurrentLoads, maxTextureMemoryMb]
|
|
2846
3070
|
);
|
|
2847
|
-
(0,
|
|
3071
|
+
(0, import_react15.useEffect)(() => {
|
|
2848
3072
|
manager.resume();
|
|
2849
3073
|
return () => manager.dispose();
|
|
2850
3074
|
}, [manager]);
|
|
2851
|
-
return /* @__PURE__ */ (0,
|
|
3075
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TileTextureManagerContext.Provider, { value: manager, children });
|
|
2852
3076
|
}
|
|
2853
3077
|
function useSharedTileTextureManager() {
|
|
2854
|
-
return (0,
|
|
3078
|
+
return (0, import_react15.useContext)(TileTextureManagerContext);
|
|
2855
3079
|
}
|
|
2856
3080
|
|
|
2857
3081
|
// src/tile/tile.tsx
|
|
2858
|
-
var
|
|
2859
|
-
var
|
|
3082
|
+
var import_fiber12 = require("@react-three/fiber");
|
|
3083
|
+
var import_react16 = require("react");
|
|
2860
3084
|
var import_three7 = require("three");
|
|
2861
3085
|
|
|
2862
3086
|
// src/tile/face-layout.ts
|
|
@@ -3037,7 +3261,7 @@ function resolveTemplateUrl(template, address) {
|
|
|
3037
3261
|
}
|
|
3038
3262
|
|
|
3039
3263
|
// src/tile/tile.tsx
|
|
3040
|
-
var
|
|
3264
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
3041
3265
|
var MAX_LOD_UPDATE_INTERVAL_MS = 100;
|
|
3042
3266
|
var FAST_ROTATION_THRESHOLD_RADIANS = Math.PI / 180;
|
|
3043
3267
|
var FAST_FOV_THRESHOLD_DEGREES = 0.5;
|
|
@@ -3046,10 +3270,10 @@ var VISIBILITY_FOV_PADDING_DEGREES = 8;
|
|
|
3046
3270
|
var PREVIEW_RADIUS = CUBE_RADIUS + 0.05;
|
|
3047
3271
|
var SHARED_TILE_GEOMETRY = new import_three7.PlaneGeometry(1, 1);
|
|
3048
3272
|
function usePreviewTexture(url, anisotropy, onError) {
|
|
3049
|
-
const [texture, setTexture] = (0,
|
|
3050
|
-
const onErrorRef = (0,
|
|
3273
|
+
const [texture, setTexture] = (0, import_react16.useState)(null);
|
|
3274
|
+
const onErrorRef = (0, import_react16.useRef)(onError);
|
|
3051
3275
|
onErrorRef.current = onError;
|
|
3052
|
-
(0,
|
|
3276
|
+
(0, import_react16.useEffect)(() => {
|
|
3053
3277
|
if (!url) {
|
|
3054
3278
|
setTexture(null);
|
|
3055
3279
|
return;
|
|
@@ -3086,7 +3310,7 @@ function usePreviewTexture(url, anisotropy, onError) {
|
|
|
3086
3310
|
active = false;
|
|
3087
3311
|
};
|
|
3088
3312
|
}, [anisotropy, url]);
|
|
3089
|
-
(0,
|
|
3313
|
+
(0, import_react16.useEffect)(
|
|
3090
3314
|
() => () => {
|
|
3091
3315
|
texture?.dispose();
|
|
3092
3316
|
},
|
|
@@ -3099,7 +3323,7 @@ function PreviewFace({
|
|
|
3099
3323
|
texture,
|
|
3100
3324
|
faceOrder
|
|
3101
3325
|
}) {
|
|
3102
|
-
const geometry = (0,
|
|
3326
|
+
const geometry = (0, import_react16.useMemo)(() => {
|
|
3103
3327
|
const nextGeometry = new import_three7.PlaneGeometry(
|
|
3104
3328
|
PREVIEW_RADIUS * 2,
|
|
3105
3329
|
PREVIEW_RADIUS * 2
|
|
@@ -3117,21 +3341,21 @@ function PreviewFace({
|
|
|
3117
3341
|
uv.needsUpdate = true;
|
|
3118
3342
|
return nextGeometry;
|
|
3119
3343
|
}, [face, faceOrder]);
|
|
3120
|
-
(0,
|
|
3344
|
+
(0, import_react16.useEffect)(
|
|
3121
3345
|
() => () => {
|
|
3122
3346
|
geometry.dispose();
|
|
3123
3347
|
},
|
|
3124
3348
|
[geometry]
|
|
3125
3349
|
);
|
|
3126
3350
|
const transform = getFaceTransform(face, PREVIEW_RADIUS);
|
|
3127
|
-
return /* @__PURE__ */ (0,
|
|
3351
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3128
3352
|
"mesh",
|
|
3129
3353
|
{
|
|
3130
3354
|
geometry,
|
|
3131
3355
|
position: transform.position,
|
|
3132
3356
|
renderOrder: -100,
|
|
3133
3357
|
rotation: transform.rotation,
|
|
3134
|
-
children: /* @__PURE__ */ (0,
|
|
3358
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3135
3359
|
"meshBasicMaterial",
|
|
3136
3360
|
{
|
|
3137
3361
|
depthTest: false,
|
|
@@ -3147,7 +3371,7 @@ function PreviewCube({
|
|
|
3147
3371
|
texture,
|
|
3148
3372
|
faceOrder
|
|
3149
3373
|
}) {
|
|
3150
|
-
return CUBE_FACES.map((face) => /* @__PURE__ */ (0,
|
|
3374
|
+
return CUBE_FACES.map((face) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3151
3375
|
PreviewFace,
|
|
3152
3376
|
{
|
|
3153
3377
|
face,
|
|
@@ -3158,14 +3382,14 @@ function PreviewCube({
|
|
|
3158
3382
|
));
|
|
3159
3383
|
}
|
|
3160
3384
|
function useManagedTexture(manager, key, url, address) {
|
|
3161
|
-
const [managedState, setManagedState] = (0,
|
|
3385
|
+
const [managedState, setManagedState] = (0, import_react16.useState)(() => ({
|
|
3162
3386
|
manager,
|
|
3163
3387
|
key,
|
|
3164
3388
|
url,
|
|
3165
3389
|
snapshot: manager.getSnapshot(key)
|
|
3166
3390
|
}));
|
|
3167
3391
|
const snapshot = managedState.manager === manager && managedState.key === key && managedState.url === url ? managedState.snapshot : manager.getSnapshot(key);
|
|
3168
|
-
(0,
|
|
3392
|
+
(0, import_react16.useEffect)(
|
|
3169
3393
|
() => manager.acquire(key, url, address, (nextSnapshot) => {
|
|
3170
3394
|
setManagedState({
|
|
3171
3395
|
manager,
|
|
@@ -3178,7 +3402,7 @@ function useManagedTexture(manager, key, url, address) {
|
|
|
3178
3402
|
);
|
|
3179
3403
|
return snapshot;
|
|
3180
3404
|
}
|
|
3181
|
-
var TileMesh = (0,
|
|
3405
|
+
var TileMesh = (0, import_react16.memo)(function TileMesh2({
|
|
3182
3406
|
address,
|
|
3183
3407
|
manager,
|
|
3184
3408
|
renderOrder,
|
|
@@ -3192,14 +3416,14 @@ var TileMesh = (0, import_react14.memo)(function TileMesh2({
|
|
|
3192
3416
|
if (!snapshot.texture) {
|
|
3193
3417
|
return null;
|
|
3194
3418
|
}
|
|
3195
|
-
return /* @__PURE__ */ (0,
|
|
3419
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("group", { position: transform.position, rotation: transform.rotation, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3196
3420
|
"mesh",
|
|
3197
3421
|
{
|
|
3198
3422
|
geometry: SHARED_TILE_GEOMETRY,
|
|
3199
3423
|
position: [layout.x, layout.y, 0],
|
|
3200
3424
|
renderOrder,
|
|
3201
3425
|
scale: [layout.width, layout.height, 1],
|
|
3202
|
-
children: /* @__PURE__ */ (0,
|
|
3426
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3203
3427
|
"meshBasicMaterial",
|
|
3204
3428
|
{
|
|
3205
3429
|
depthTest: false,
|
|
@@ -3211,12 +3435,12 @@ var TileMesh = (0, import_react14.memo)(function TileMesh2({
|
|
|
3211
3435
|
}
|
|
3212
3436
|
) });
|
|
3213
3437
|
});
|
|
3214
|
-
var TileLayerMeshes = (0,
|
|
3438
|
+
var TileLayerMeshes = (0, import_react16.memo)(function TileLayerMeshes2({
|
|
3215
3439
|
layer,
|
|
3216
3440
|
manager,
|
|
3217
3441
|
resolveUrl
|
|
3218
3442
|
}) {
|
|
3219
|
-
return layer.addresses.map((address) => /* @__PURE__ */ (0,
|
|
3443
|
+
return layer.addresses.map((address) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3220
3444
|
TileMesh,
|
|
3221
3445
|
{
|
|
3222
3446
|
address,
|
|
@@ -3384,11 +3608,11 @@ function Tile({
|
|
|
3384
3608
|
onTileError,
|
|
3385
3609
|
onLevelChange
|
|
3386
3610
|
}) {
|
|
3387
|
-
const { camera, gl, size } = (0,
|
|
3388
|
-
const multiresConfig = (0,
|
|
3611
|
+
const { camera, gl, size } = (0, import_fiber12.useThree)();
|
|
3612
|
+
const multiresConfig = (0, import_react16.useMemo)(() => parseMultires(multires), [multires]);
|
|
3389
3613
|
const { levels, tileSize } = multiresConfig;
|
|
3390
3614
|
const multiresToken = `${tileSize}:${levels.join(",")}`;
|
|
3391
|
-
const candidatesByLevel = (0,
|
|
3615
|
+
const candidatesByLevel = (0, import_react16.useMemo)(
|
|
3392
3616
|
() => buildTileCandidates(levels, tileSize),
|
|
3393
3617
|
[levels, tileSize]
|
|
3394
3618
|
);
|
|
@@ -3400,13 +3624,13 @@ function Tile({
|
|
|
3400
3624
|
onPreviewError
|
|
3401
3625
|
);
|
|
3402
3626
|
const sharedManager = useSharedTileTextureManager();
|
|
3403
|
-
const progressRef = (0,
|
|
3404
|
-
const errorRef = (0,
|
|
3405
|
-
const levelChangeRef = (0,
|
|
3627
|
+
const progressRef = (0, import_react16.useRef)(onLoadProgress);
|
|
3628
|
+
const errorRef = (0, import_react16.useRef)(onTileError);
|
|
3629
|
+
const levelChangeRef = (0, import_react16.useRef)(onLevelChange);
|
|
3406
3630
|
progressRef.current = onLoadProgress;
|
|
3407
3631
|
errorRef.current = onTileError;
|
|
3408
3632
|
levelChangeRef.current = onLevelChange;
|
|
3409
|
-
const ownedManager = (0,
|
|
3633
|
+
const ownedManager = (0, import_react16.useMemo)(
|
|
3410
3634
|
() => new TileTextureManager({
|
|
3411
3635
|
anisotropy,
|
|
3412
3636
|
maxBytes: Math.max(1, maxTextureMemoryMb) * 1024 * 1024,
|
|
@@ -3427,7 +3651,7 @@ function Tile({
|
|
|
3427
3651
|
]
|
|
3428
3652
|
);
|
|
3429
3653
|
const manager = sharedManager ?? ownedManager;
|
|
3430
|
-
(0,
|
|
3654
|
+
(0, import_react16.useEffect)(() => {
|
|
3431
3655
|
manager.resume();
|
|
3432
3656
|
return () => {
|
|
3433
3657
|
if (manager === ownedManager) {
|
|
@@ -3437,11 +3661,11 @@ function Tile({
|
|
|
3437
3661
|
queueMicrotask(() => manager.releaseUnused());
|
|
3438
3662
|
};
|
|
3439
3663
|
}, [manager, ownedManager]);
|
|
3440
|
-
const readyRef = (0,
|
|
3441
|
-
(0,
|
|
3664
|
+
const readyRef = (0, import_react16.useRef)(false);
|
|
3665
|
+
(0, import_react16.useEffect)(() => {
|
|
3442
3666
|
readyRef.current = false;
|
|
3443
3667
|
}, [effectivePreviewUrl]);
|
|
3444
|
-
(0,
|
|
3668
|
+
(0, import_react16.useEffect)(() => {
|
|
3445
3669
|
if (!previewTexture || readyRef.current) {
|
|
3446
3670
|
return;
|
|
3447
3671
|
}
|
|
@@ -3449,31 +3673,31 @@ function Tile({
|
|
|
3449
3673
|
onReady?.();
|
|
3450
3674
|
}, [onReady, previewTexture]);
|
|
3451
3675
|
const template = urlTemplate ?? buildDefaultTileUrlTemplate();
|
|
3452
|
-
const resolveUrl = (0,
|
|
3676
|
+
const resolveUrl = (0, import_react16.useMemo)(
|
|
3453
3677
|
() => (address) => {
|
|
3454
3678
|
const relativePath = resolveTileUrl ? resolveTileUrl(address) : resolveTemplateUrl(template, address);
|
|
3455
3679
|
return resolveRelativeTileUrl(baseUrl, relativePath);
|
|
3456
3680
|
},
|
|
3457
3681
|
[baseUrl, resolveTileUrl, template]
|
|
3458
3682
|
);
|
|
3459
|
-
const [layers, setLayers] = (0,
|
|
3460
|
-
const layerTokenRef = (0,
|
|
3461
|
-
const currentLevelRef = (0,
|
|
3462
|
-
const lastUpdateAtRef = (0,
|
|
3463
|
-
const visibilityDirtyRef = (0,
|
|
3464
|
-
const lastVisibilityQuaternionRef = (0,
|
|
3465
|
-
const lastVisibilityFovRef = (0,
|
|
3466
|
-
const lastViewportRef = (0,
|
|
3467
|
-
const frustumRef = (0,
|
|
3468
|
-
const projectionMatrixRef = (0,
|
|
3469
|
-
const visibilityCameraRef = (0,
|
|
3470
|
-
(0,
|
|
3683
|
+
const [layers, setLayers] = (0, import_react16.useState)([]);
|
|
3684
|
+
const layerTokenRef = (0, import_react16.useRef)("");
|
|
3685
|
+
const currentLevelRef = (0, import_react16.useRef)(1);
|
|
3686
|
+
const lastUpdateAtRef = (0, import_react16.useRef)(-Infinity);
|
|
3687
|
+
const visibilityDirtyRef = (0, import_react16.useRef)(true);
|
|
3688
|
+
const lastVisibilityQuaternionRef = (0, import_react16.useRef)(camera.quaternion.clone());
|
|
3689
|
+
const lastVisibilityFovRef = (0, import_react16.useRef)(Number.NaN);
|
|
3690
|
+
const lastViewportRef = (0, import_react16.useRef)({ width: 0, height: 0, dpr: 0 });
|
|
3691
|
+
const frustumRef = (0, import_react16.useRef)(new import_three7.Frustum());
|
|
3692
|
+
const projectionMatrixRef = (0, import_react16.useRef)(new import_three7.Matrix4());
|
|
3693
|
+
const visibilityCameraRef = (0, import_react16.useRef)(new import_three7.PerspectiveCamera());
|
|
3694
|
+
(0, import_react16.useEffect)(() => {
|
|
3471
3695
|
currentLevelRef.current = 1;
|
|
3472
3696
|
layerTokenRef.current = "";
|
|
3473
3697
|
visibilityDirtyRef.current = true;
|
|
3474
3698
|
setLayers([]);
|
|
3475
3699
|
}, [manager, multiresToken]);
|
|
3476
|
-
(0,
|
|
3700
|
+
(0, import_react16.useEffect)(() => {
|
|
3477
3701
|
if (loadMode !== "preview") {
|
|
3478
3702
|
return;
|
|
3479
3703
|
}
|
|
@@ -3487,7 +3711,7 @@ function Tile({
|
|
|
3487
3711
|
setLayers(nextLayers);
|
|
3488
3712
|
}
|
|
3489
3713
|
};
|
|
3490
|
-
(0,
|
|
3714
|
+
(0, import_fiber12.useFrame)(() => {
|
|
3491
3715
|
if (loadMode === "preview") {
|
|
3492
3716
|
return;
|
|
3493
3717
|
}
|
|
@@ -3553,15 +3777,15 @@ function Tile({
|
|
|
3553
3777
|
};
|
|
3554
3778
|
commitLayers(nextLayers);
|
|
3555
3779
|
});
|
|
3556
|
-
return /* @__PURE__ */ (0,
|
|
3557
|
-
previewTexture ? /* @__PURE__ */ (0,
|
|
3780
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("group", { visible, children: [
|
|
3781
|
+
previewTexture ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3558
3782
|
PreviewCube,
|
|
3559
3783
|
{
|
|
3560
3784
|
texture: previewTexture,
|
|
3561
3785
|
faceOrder: previewFaceOrder
|
|
3562
3786
|
}
|
|
3563
3787
|
) : null,
|
|
3564
|
-
layers.map((layer) => /* @__PURE__ */ (0,
|
|
3788
|
+
layers.map((layer) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3565
3789
|
TileLayerMeshes,
|
|
3566
3790
|
{
|
|
3567
3791
|
layer,
|
|
@@ -3573,8 +3797,8 @@ function Tile({
|
|
|
3573
3797
|
] });
|
|
3574
3798
|
}
|
|
3575
3799
|
|
|
3576
|
-
// src/
|
|
3577
|
-
var
|
|
3800
|
+
// src/scenes.tsx
|
|
3801
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
3578
3802
|
var TRANSITION_DEFAULTS = {
|
|
3579
3803
|
none: { duration: 0, krpanoBlend: "NOBLEND" },
|
|
3580
3804
|
crossfade: { duration: 1, krpanoBlend: "BLEND(1.0, easeInCubic)" },
|
|
@@ -3624,7 +3848,7 @@ function SceneSource({
|
|
|
3624
3848
|
return null;
|
|
3625
3849
|
}
|
|
3626
3850
|
if (scene.type === "sphere") {
|
|
3627
|
-
return /* @__PURE__ */ (0,
|
|
3851
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3628
3852
|
Sphere,
|
|
3629
3853
|
{
|
|
3630
3854
|
src: scene.src,
|
|
@@ -3636,7 +3860,7 @@ function SceneSource({
|
|
|
3636
3860
|
);
|
|
3637
3861
|
}
|
|
3638
3862
|
const { id: _id, type: _type, ...tileProps } = scene;
|
|
3639
|
-
return /* @__PURE__ */ (0,
|
|
3863
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3640
3864
|
Tile,
|
|
3641
3865
|
{
|
|
3642
3866
|
...tileProps,
|
|
@@ -3652,17 +3876,17 @@ function SnapshotCapture({
|
|
|
3652
3876
|
maxPixels,
|
|
3653
3877
|
onCaptured
|
|
3654
3878
|
}) {
|
|
3655
|
-
const { camera, gl, scene, size } = (0,
|
|
3656
|
-
const capturedRequestRef = (0,
|
|
3657
|
-
const renderTargetRef = (0,
|
|
3658
|
-
(0,
|
|
3879
|
+
const { camera, gl, scene, size } = (0, import_fiber13.useThree)();
|
|
3880
|
+
const capturedRequestRef = (0, import_react17.useRef)(0);
|
|
3881
|
+
const renderTargetRef = (0, import_react17.useRef)(null);
|
|
3882
|
+
(0, import_react17.useEffect)(
|
|
3659
3883
|
() => () => {
|
|
3660
3884
|
renderTargetRef.current?.dispose();
|
|
3661
3885
|
renderTargetRef.current = null;
|
|
3662
3886
|
},
|
|
3663
3887
|
[]
|
|
3664
3888
|
);
|
|
3665
|
-
(0,
|
|
3889
|
+
(0, import_fiber13.useFrame)(() => {
|
|
3666
3890
|
if (requestId === 0 || requestId === capturedRequestRef.current) {
|
|
3667
3891
|
return;
|
|
3668
3892
|
}
|
|
@@ -3708,12 +3932,12 @@ function SnapshotOverlay({
|
|
|
3708
3932
|
runId,
|
|
3709
3933
|
onFinish
|
|
3710
3934
|
}) {
|
|
3711
|
-
const { camera, size } = (0,
|
|
3712
|
-
const meshRef = (0,
|
|
3713
|
-
const startRef = (0,
|
|
3714
|
-
const finishedRef = (0,
|
|
3715
|
-
const directionRef = (0,
|
|
3716
|
-
const material = (0,
|
|
3935
|
+
const { camera, size } = (0, import_fiber13.useThree)();
|
|
3936
|
+
const meshRef = (0, import_react17.useRef)(null);
|
|
3937
|
+
const startRef = (0, import_react17.useRef)(null);
|
|
3938
|
+
const finishedRef = (0, import_react17.useRef)(false);
|
|
3939
|
+
const directionRef = (0, import_react17.useRef)(new import_three8.Vector3());
|
|
3940
|
+
const material = (0, import_react17.useMemo)(
|
|
3717
3941
|
() => new import_three8.ShaderMaterial({
|
|
3718
3942
|
transparent: true,
|
|
3719
3943
|
depthTest: false,
|
|
@@ -3792,13 +4016,13 @@ function SnapshotOverlay({
|
|
|
3792
4016
|
}),
|
|
3793
4017
|
[snapshot.texture, transition.preset]
|
|
3794
4018
|
);
|
|
3795
|
-
(0,
|
|
3796
|
-
(0,
|
|
4019
|
+
(0, import_react17.useEffect)(() => () => material.dispose(), [material]);
|
|
4020
|
+
(0, import_react17.useEffect)(() => {
|
|
3797
4021
|
startRef.current = null;
|
|
3798
4022
|
finishedRef.current = false;
|
|
3799
4023
|
material.uniforms.progress.value = 0;
|
|
3800
4024
|
}, [material, runId]);
|
|
3801
|
-
(0,
|
|
4025
|
+
(0, import_fiber13.useFrame)((state) => {
|
|
3802
4026
|
const mesh = meshRef.current;
|
|
3803
4027
|
if (!mesh || !camera.isPerspectiveCamera) {
|
|
3804
4028
|
return;
|
|
@@ -3823,13 +4047,13 @@ function SnapshotOverlay({
|
|
|
3823
4047
|
onFinish();
|
|
3824
4048
|
}
|
|
3825
4049
|
});
|
|
3826
|
-
return /* @__PURE__ */ (0,
|
|
3827
|
-
/* @__PURE__ */ (0,
|
|
3828
|
-
/* @__PURE__ */ (0,
|
|
4050
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("mesh", { ref: meshRef, renderOrder: 1e4, frustumCulled: false, children: [
|
|
4051
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("primitive", { attach: "geometry", object: FULLSCREEN_PLANE }),
|
|
4052
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("primitive", { attach: "material", object: material })
|
|
3829
4053
|
] });
|
|
3830
4054
|
}
|
|
3831
4055
|
var FULLSCREEN_PLANE = new import_three8.PlaneGeometry(1, 1);
|
|
3832
|
-
function
|
|
4056
|
+
function ScenesController({
|
|
3833
4057
|
scenes,
|
|
3834
4058
|
activeSceneId,
|
|
3835
4059
|
transition: transitionInput,
|
|
@@ -3838,47 +4062,47 @@ function PanoramaScenesController({
|
|
|
3838
4062
|
onTransitionError,
|
|
3839
4063
|
snapshotMaxPixels = 3686400
|
|
3840
4064
|
}) {
|
|
3841
|
-
const controlsRef = (0,
|
|
4065
|
+
const controlsRef = (0, import_react17.useContext)(PanoramaViewContext);
|
|
3842
4066
|
const manager = useSharedTileTextureManager();
|
|
3843
|
-
const transition = (0,
|
|
4067
|
+
const transition = (0, import_react17.useMemo)(
|
|
3844
4068
|
() => resolveTransition(transitionInput),
|
|
3845
4069
|
[transitionInput]
|
|
3846
4070
|
);
|
|
3847
|
-
const sceneMap = (0,
|
|
4071
|
+
const sceneMap = (0, import_react17.useMemo)(
|
|
3848
4072
|
() => new Map(scenes.map((scene) => [scene.id, scene])),
|
|
3849
4073
|
[scenes]
|
|
3850
4074
|
);
|
|
3851
4075
|
const initialScene = sceneMap.get(activeSceneId) ?? null;
|
|
3852
|
-
const [slots, setSlots] = (0,
|
|
4076
|
+
const [slots, setSlots] = (0, import_react17.useState)([
|
|
3853
4077
|
initialScene,
|
|
3854
4078
|
null
|
|
3855
4079
|
]);
|
|
3856
|
-
const [activeSlot, setActiveSlot] = (0,
|
|
3857
|
-
const [liveSlot, setLiveSlot] = (0,
|
|
3858
|
-
const [pendingSlot, setPendingSlot] = (0,
|
|
3859
|
-
const [phase, setPhase] = (0,
|
|
3860
|
-
const [captureRequestId, setCaptureRequestId] = (0,
|
|
3861
|
-
const [transitionRunId, setTransitionRunId] = (0,
|
|
3862
|
-
const [snapshot, setSnapshot] = (0,
|
|
3863
|
-
const [recoveryKey, setRecoveryKey] = (0,
|
|
3864
|
-
const requestedSceneIdRef = (0,
|
|
3865
|
-
const captureReasonRef = (0,
|
|
3866
|
-
const interactionReleaseRef = (0,
|
|
3867
|
-
const slotsRef = (0,
|
|
3868
|
-
const phaseRef = (0,
|
|
3869
|
-
const liveSlotRef = (0,
|
|
3870
|
-
const transitionFromRef = (0,
|
|
4080
|
+
const [activeSlot, setActiveSlot] = (0, import_react17.useState)(0);
|
|
4081
|
+
const [liveSlot, setLiveSlot] = (0, import_react17.useState)(0);
|
|
4082
|
+
const [pendingSlot, setPendingSlot] = (0, import_react17.useState)(null);
|
|
4083
|
+
const [phase, setPhase] = (0, import_react17.useState)(initialScene ? "idle" : "preloading");
|
|
4084
|
+
const [captureRequestId, setCaptureRequestId] = (0, import_react17.useState)(0);
|
|
4085
|
+
const [transitionRunId, setTransitionRunId] = (0, import_react17.useState)(0);
|
|
4086
|
+
const [snapshot, setSnapshot] = (0, import_react17.useState)(null);
|
|
4087
|
+
const [recoveryKey, setRecoveryKey] = (0, import_react17.useState)(0);
|
|
4088
|
+
const requestedSceneIdRef = (0, import_react17.useRef)(activeSceneId);
|
|
4089
|
+
const captureReasonRef = (0, import_react17.useRef)("start");
|
|
4090
|
+
const interactionReleaseRef = (0, import_react17.useRef)(null);
|
|
4091
|
+
const slotsRef = (0, import_react17.useRef)(slots);
|
|
4092
|
+
const phaseRef = (0, import_react17.useRef)(phase);
|
|
4093
|
+
const liveSlotRef = (0, import_react17.useRef)(liveSlot);
|
|
4094
|
+
const transitionFromRef = (0, import_react17.useRef)(initialScene);
|
|
3871
4095
|
slotsRef.current = slots;
|
|
3872
4096
|
phaseRef.current = phase;
|
|
3873
4097
|
liveSlotRef.current = liveSlot;
|
|
3874
|
-
const releaseInteraction = (0,
|
|
4098
|
+
const releaseInteraction = (0, import_react17.useCallback)(() => {
|
|
3875
4099
|
interactionReleaseRef.current?.();
|
|
3876
4100
|
interactionReleaseRef.current = null;
|
|
3877
4101
|
}, []);
|
|
3878
|
-
const reportError = (0,
|
|
4102
|
+
const reportError = (0, import_react17.useCallback)((sceneId, error) => {
|
|
3879
4103
|
onTransitionError?.({ sceneId, error });
|
|
3880
4104
|
}, [onTransitionError]);
|
|
3881
|
-
const startPreload = (0,
|
|
4105
|
+
const startPreload = (0, import_react17.useCallback)((scene) => {
|
|
3882
4106
|
const nextSlot = 1 - liveSlotRef.current;
|
|
3883
4107
|
requestedSceneIdRef.current = scene.id;
|
|
3884
4108
|
setSlots((current) => {
|
|
@@ -3889,7 +4113,7 @@ function PanoramaScenesController({
|
|
|
3889
4113
|
setPendingSlot(nextSlot);
|
|
3890
4114
|
setPhase("preloading");
|
|
3891
4115
|
}, []);
|
|
3892
|
-
(0,
|
|
4116
|
+
(0, import_react17.useEffect)(() => {
|
|
3893
4117
|
const requested = sceneMap.get(activeSceneId);
|
|
3894
4118
|
if (!requested) {
|
|
3895
4119
|
reportError(activeSceneId, new Error(`Unknown panorama scene: ${activeSceneId}`));
|
|
@@ -3913,7 +4137,7 @@ function PanoramaScenesController({
|
|
|
3913
4137
|
}
|
|
3914
4138
|
startPreload(requested);
|
|
3915
4139
|
}, [activeSceneId, pendingSlot, reportError, sceneMap, startPreload]);
|
|
3916
|
-
const handleReady = (0,
|
|
4140
|
+
const handleReady = (0, import_react17.useCallback)((slot) => {
|
|
3917
4141
|
if (slot !== pendingSlot || phaseRef.current !== "preloading") {
|
|
3918
4142
|
return;
|
|
3919
4143
|
}
|
|
@@ -3944,7 +4168,7 @@ function PanoramaScenesController({
|
|
|
3944
4168
|
setPhase("capturing");
|
|
3945
4169
|
setCaptureRequestId((current) => current + 1);
|
|
3946
4170
|
}, [controlsRef, onTransitionEnd, pendingSlot, transition.preset]);
|
|
3947
|
-
const handleCaptured = (0,
|
|
4171
|
+
const handleCaptured = (0, import_react17.useCallback)((nextSnapshot) => {
|
|
3948
4172
|
setSnapshot((current) => {
|
|
3949
4173
|
current?.dispose();
|
|
3950
4174
|
return nextSnapshot;
|
|
@@ -3966,7 +4190,7 @@ function PanoramaScenesController({
|
|
|
3966
4190
|
setPhase("transitioning");
|
|
3967
4191
|
setTransitionRunId((current) => current + 1);
|
|
3968
4192
|
}, [manager, pendingSlot, sceneMap, startPreload]);
|
|
3969
|
-
const finishTransition = (0,
|
|
4193
|
+
const finishTransition = (0, import_react17.useCallback)(() => {
|
|
3970
4194
|
const nextSlot = pendingSlot;
|
|
3971
4195
|
const previousScene = transitionFromRef.current;
|
|
3972
4196
|
const nextScene = nextSlot === null ? null : slotsRef.current[nextSlot];
|
|
@@ -3991,12 +4215,12 @@ function PanoramaScenesController({
|
|
|
3991
4215
|
});
|
|
3992
4216
|
}
|
|
3993
4217
|
}, [onTransitionEnd, pendingSlot, releaseInteraction, snapshot, transition.preset]);
|
|
3994
|
-
(0,
|
|
4218
|
+
(0, import_react17.useEffect)(() => () => {
|
|
3995
4219
|
releaseInteraction();
|
|
3996
4220
|
snapshot?.dispose();
|
|
3997
4221
|
}, [releaseInteraction, snapshot]);
|
|
3998
|
-
const { gl } = (0,
|
|
3999
|
-
(0,
|
|
4222
|
+
const { gl } = (0, import_fiber13.useThree)();
|
|
4223
|
+
(0, import_react17.useEffect)(() => {
|
|
4000
4224
|
const canvas = gl.domElement;
|
|
4001
4225
|
const onContextLost = (event) => {
|
|
4002
4226
|
event.preventDefault();
|
|
@@ -4020,8 +4244,8 @@ function PanoramaScenesController({
|
|
|
4020
4244
|
}, [gl, manager, releaseInteraction, snapshot]);
|
|
4021
4245
|
const renderedScene = slots[liveSlot];
|
|
4022
4246
|
const snapshotVisible = snapshot !== null && (phase === "transitioning" || phase === "recapturing" || phase === "preloading");
|
|
4023
|
-
return /* @__PURE__ */ (0,
|
|
4024
|
-
/* @__PURE__ */ (0,
|
|
4247
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react17.Fragment, { children: [
|
|
4248
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4025
4249
|
SnapshotCapture,
|
|
4026
4250
|
{
|
|
4027
4251
|
requestId: captureRequestId,
|
|
@@ -4033,7 +4257,7 @@ function PanoramaScenesController({
|
|
|
4033
4257
|
const source = slots[slot];
|
|
4034
4258
|
const isLive = slot === liveSlot;
|
|
4035
4259
|
const isPending = slot === pendingSlot;
|
|
4036
|
-
return /* @__PURE__ */ (0,
|
|
4260
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4037
4261
|
SceneSource,
|
|
4038
4262
|
{
|
|
4039
4263
|
scene: source,
|
|
@@ -4049,7 +4273,7 @@ function PanoramaScenesController({
|
|
|
4049
4273
|
`${slot}:${source?.id ?? "empty"}:${recoveryKey}`
|
|
4050
4274
|
);
|
|
4051
4275
|
}),
|
|
4052
|
-
snapshotVisible ? /* @__PURE__ */ (0,
|
|
4276
|
+
snapshotVisible ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4053
4277
|
SnapshotOverlay,
|
|
4054
4278
|
{
|
|
4055
4279
|
snapshot,
|
|
@@ -4062,60 +4286,186 @@ function PanoramaScenesController({
|
|
|
4062
4286
|
phase === "idle" && renderedScene ? renderHotspots?.(renderedScene) : null
|
|
4063
4287
|
] });
|
|
4064
4288
|
}
|
|
4065
|
-
function
|
|
4289
|
+
function Scenes({
|
|
4066
4290
|
maxTextureMemoryMb,
|
|
4067
4291
|
maxConcurrentTileLoads,
|
|
4068
4292
|
...props
|
|
4069
4293
|
}) {
|
|
4070
|
-
return /* @__PURE__ */ (0,
|
|
4294
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4071
4295
|
TileTextureManagerProvider,
|
|
4072
4296
|
{
|
|
4073
4297
|
maxTextureMemoryMb,
|
|
4074
4298
|
maxConcurrentLoads: maxConcurrentTileLoads,
|
|
4075
|
-
children: /* @__PURE__ */ (0,
|
|
4299
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ScenesController, { ...props })
|
|
4076
4300
|
}
|
|
4077
4301
|
);
|
|
4078
4302
|
}
|
|
4079
4303
|
|
|
4080
4304
|
// src/hotspot/image-hotspot.tsx
|
|
4081
|
-
var
|
|
4082
|
-
var
|
|
4083
|
-
var
|
|
4305
|
+
var import_fiber15 = require("@react-three/fiber");
|
|
4306
|
+
var import_react20 = require("react");
|
|
4307
|
+
var import_three11 = require("three");
|
|
4084
4308
|
|
|
4085
4309
|
// src/hotspot/hotspot-anchor.tsx
|
|
4086
|
-
var
|
|
4087
|
-
var
|
|
4310
|
+
var import_fiber14 = require("@react-three/fiber");
|
|
4311
|
+
var import_react19 = require("react");
|
|
4088
4312
|
var import_three9 = require("three");
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
var
|
|
4092
|
-
var
|
|
4093
|
-
var
|
|
4094
|
-
var
|
|
4095
|
-
var
|
|
4096
|
-
var
|
|
4097
|
-
var
|
|
4098
|
-
|
|
4099
|
-
surface: { orientation: "surface", placement: "surface" },
|
|
4100
|
-
billboard: { orientation: "billboard", placement: "floating" }
|
|
4313
|
+
|
|
4314
|
+
// src/hotspot/hotspot-tooltip.tsx
|
|
4315
|
+
var import_drei = require("@react-three/drei");
|
|
4316
|
+
var import_react18 = require("react");
|
|
4317
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
4318
|
+
var TOOLTIP_MAX_WIDTH = 220;
|
|
4319
|
+
var TOOLTIP_IMAGE_MAX_HEIGHT = 120;
|
|
4320
|
+
var DEFAULT_HOTSPOT_TOOLTIP_OFFSET = 12;
|
|
4321
|
+
var WRAPPER_STYLE = {
|
|
4322
|
+
pointerEvents: "none"
|
|
4101
4323
|
};
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4324
|
+
var BUBBLE_STYLE = {
|
|
4325
|
+
background: "rgba(22, 22, 22, 0.72)",
|
|
4326
|
+
border: "1px solid rgba(46, 46, 46, 0.7)",
|
|
4327
|
+
borderRadius: 8,
|
|
4328
|
+
boxShadow: "0 8px 24px rgba(0, 0, 0, 0.35)",
|
|
4329
|
+
boxSizing: "border-box",
|
|
4330
|
+
color: "#f5fbfc",
|
|
4331
|
+
display: "flex",
|
|
4332
|
+
flexDirection: "column",
|
|
4333
|
+
gap: 8,
|
|
4334
|
+
padding: 8,
|
|
4335
|
+
pointerEvents: "none",
|
|
4336
|
+
whiteSpace: "nowrap"
|
|
4337
|
+
};
|
|
4338
|
+
var IMAGE_STYLE = {
|
|
4339
|
+
borderRadius: 4,
|
|
4340
|
+
display: "block",
|
|
4341
|
+
height: "auto",
|
|
4342
|
+
maxHeight: TOOLTIP_IMAGE_MAX_HEIGHT,
|
|
4343
|
+
maxWidth: TOOLTIP_MAX_WIDTH,
|
|
4344
|
+
objectFit: "contain"
|
|
4345
|
+
};
|
|
4346
|
+
var TEXT_STYLE = {
|
|
4347
|
+
fontFamily: "system-ui, sans-serif",
|
|
4348
|
+
fontSize: 12,
|
|
4349
|
+
lineHeight: 1.4,
|
|
4350
|
+
margin: 0,
|
|
4351
|
+
overflow: "visible",
|
|
4352
|
+
whiteSpace: "nowrap"
|
|
4353
|
+
};
|
|
4354
|
+
function resolveHotspotTooltipContent(tooltip) {
|
|
4355
|
+
if (tooltip == null) {
|
|
4356
|
+
return null;
|
|
4113
4357
|
}
|
|
4114
|
-
if (
|
|
4115
|
-
|
|
4358
|
+
if (typeof tooltip === "string") {
|
|
4359
|
+
const text2 = tooltip.trim();
|
|
4360
|
+
return text2 ? { text: text2 } : null;
|
|
4116
4361
|
}
|
|
4117
|
-
|
|
4118
|
-
|
|
4362
|
+
const text = tooltip.text?.trim();
|
|
4363
|
+
const image = tooltip.image?.trim();
|
|
4364
|
+
if (!text && !image) {
|
|
4365
|
+
return null;
|
|
4366
|
+
}
|
|
4367
|
+
const imageAlt = tooltip.imageAlt?.trim();
|
|
4368
|
+
return {
|
|
4369
|
+
image: image || void 0,
|
|
4370
|
+
imageAlt: imageAlt || void 0,
|
|
4371
|
+
text: text || void 0
|
|
4372
|
+
};
|
|
4373
|
+
}
|
|
4374
|
+
function resolveHotspotTooltipOffset(offset) {
|
|
4375
|
+
if (!Number.isFinite(offset)) {
|
|
4376
|
+
return DEFAULT_HOTSPOT_TOOLTIP_OFFSET;
|
|
4377
|
+
}
|
|
4378
|
+
return Math.max(0, offset);
|
|
4379
|
+
}
|
|
4380
|
+
function tooltipBubbleTransform(placement, offset) {
|
|
4381
|
+
const gap = `${offset}px`;
|
|
4382
|
+
switch (placement) {
|
|
4383
|
+
case "top":
|
|
4384
|
+
return `translate(-50%, calc(-100% - ${gap}))`;
|
|
4385
|
+
case "bottom":
|
|
4386
|
+
return `translate(-50%, ${gap})`;
|
|
4387
|
+
case "left":
|
|
4388
|
+
return `translate(calc(-100% - ${gap}), -50%)`;
|
|
4389
|
+
case "right":
|
|
4390
|
+
return `translate(${gap}, -50%)`;
|
|
4391
|
+
default: {
|
|
4392
|
+
const exhaustive = placement;
|
|
4393
|
+
return exhaustive;
|
|
4394
|
+
}
|
|
4395
|
+
}
|
|
4396
|
+
}
|
|
4397
|
+
function HotspotTooltip({
|
|
4398
|
+
content,
|
|
4399
|
+
placement = "top",
|
|
4400
|
+
offset = DEFAULT_HOTSPOT_TOOLTIP_OFFSET
|
|
4401
|
+
}) {
|
|
4402
|
+
const [imageFailed, setImageFailed] = (0, import_react18.useState)(false);
|
|
4403
|
+
(0, import_react18.useEffect)(() => {
|
|
4404
|
+
setImageFailed(false);
|
|
4405
|
+
}, [content.image]);
|
|
4406
|
+
const showImage = Boolean(content.image) && !imageFailed;
|
|
4407
|
+
const bubbleStyle = (0, import_react18.useMemo)(
|
|
4408
|
+
() => ({
|
|
4409
|
+
...BUBBLE_STYLE,
|
|
4410
|
+
transform: tooltipBubbleTransform(
|
|
4411
|
+
placement,
|
|
4412
|
+
resolveHotspotTooltipOffset(offset)
|
|
4413
|
+
)
|
|
4414
|
+
}),
|
|
4415
|
+
[offset, placement]
|
|
4416
|
+
);
|
|
4417
|
+
if (!showImage && !content.text) {
|
|
4418
|
+
return null;
|
|
4419
|
+
}
|
|
4420
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_drei.Html, { pointerEvents: "none", style: WRAPPER_STYLE, zIndexRange: [20, 10], children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { role: "tooltip", style: bubbleStyle, children: [
|
|
4421
|
+
showImage ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4422
|
+
"img",
|
|
4423
|
+
{
|
|
4424
|
+
alt: content.imageAlt ?? content.text ?? "",
|
|
4425
|
+
onError: () => setImageFailed(true),
|
|
4426
|
+
src: content.image,
|
|
4427
|
+
style: IMAGE_STYLE
|
|
4428
|
+
}
|
|
4429
|
+
) : null,
|
|
4430
|
+
content.text ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { style: TEXT_STYLE, children: content.text }) : null
|
|
4431
|
+
] }) });
|
|
4432
|
+
}
|
|
4433
|
+
|
|
4434
|
+
// src/hotspot/hotspot-anchor.tsx
|
|
4435
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
4436
|
+
var DEFAULT_FLOATING_DISTANCE = 10;
|
|
4437
|
+
var PANORAMA_RADIUS = DEFAULT_PANORAMA_RADIUS;
|
|
4438
|
+
var PANORAMA_SURFACE_INSET = 4;
|
|
4439
|
+
var DEFAULT_REFERENCE_FOV = 75;
|
|
4440
|
+
var MIN_ANGULAR_SIZE = 0.01;
|
|
4441
|
+
var MAX_ANGULAR_SIZE = 179;
|
|
4442
|
+
var DRAG_EPSILON_DEGREES = 1e-3;
|
|
4443
|
+
var LOCAL_FORWARD = new import_three9.Vector3(0, 0, 1);
|
|
4444
|
+
var TOOLTIP_WORLD_BOX = new import_three9.Box3();
|
|
4445
|
+
var TOOLTIP_LOCAL_BOX = new import_three9.Box3();
|
|
4446
|
+
var TOOLTIP_CORNER = new import_three9.Vector3();
|
|
4447
|
+
var TOOLTIP_INVERSE = new import_three9.Matrix4();
|
|
4448
|
+
var HOTSPOT_MODE_RENDERING = {
|
|
4449
|
+
surface: { orientation: "surface", placement: "surface" },
|
|
4450
|
+
billboard: { orientation: "billboard", placement: "floating" }
|
|
4451
|
+
};
|
|
4452
|
+
function angularSizeToWorldSize(size, radius) {
|
|
4453
|
+
const safeSize = Number.isFinite(size) ? import_three9.MathUtils.clamp(Math.abs(size), MIN_ANGULAR_SIZE, MAX_ANGULAR_SIZE) : MIN_ANGULAR_SIZE;
|
|
4454
|
+
return 2 * radius * Math.tan(import_three9.MathUtils.degToRad(safeSize) / 2);
|
|
4455
|
+
}
|
|
4456
|
+
function resolveScale(scale) {
|
|
4457
|
+
return Number.isFinite(scale) && scale > 0 ? scale : 1;
|
|
4458
|
+
}
|
|
4459
|
+
function resolveDistance(placement, distance, width, height) {
|
|
4460
|
+
const maximumDistance = maximumHotspotDistance(width, height);
|
|
4461
|
+
if (placement === "surface") {
|
|
4462
|
+
return maximumDistance;
|
|
4463
|
+
}
|
|
4464
|
+
if (!Number.isFinite(distance)) {
|
|
4465
|
+
return DEFAULT_FLOATING_DISTANCE;
|
|
4466
|
+
}
|
|
4467
|
+
return import_three9.MathUtils.clamp(Math.abs(distance), 0.1, maximumDistance);
|
|
4468
|
+
}
|
|
4119
4469
|
function maximumHotspotDistance(width, height) {
|
|
4120
4470
|
const safeWidth = import_three9.MathUtils.clamp(
|
|
4121
4471
|
Math.abs(Number.isFinite(width) ? width : MIN_ANGULAR_SIZE),
|
|
@@ -4165,6 +4515,100 @@ function angularDistance(a, b) {
|
|
|
4165
4515
|
const bVector = panoPositionToVector3(b);
|
|
4166
4516
|
return import_three9.MathUtils.radToDeg(aVector.angleTo(bVector));
|
|
4167
4517
|
}
|
|
4518
|
+
function isTooltipOpen(trigger, hovered, focused, pinned) {
|
|
4519
|
+
switch (trigger) {
|
|
4520
|
+
case "always":
|
|
4521
|
+
return true;
|
|
4522
|
+
case "hover":
|
|
4523
|
+
return hovered || focused;
|
|
4524
|
+
case "click":
|
|
4525
|
+
return pinned;
|
|
4526
|
+
default: {
|
|
4527
|
+
const exhaustive = trigger;
|
|
4528
|
+
return exhaustive;
|
|
4529
|
+
}
|
|
4530
|
+
}
|
|
4531
|
+
}
|
|
4532
|
+
function setTooltipAnchorOnUnitPlane(anchor, placement) {
|
|
4533
|
+
switch (placement) {
|
|
4534
|
+
case "top":
|
|
4535
|
+
anchor.position.set(0, 0.5, 0);
|
|
4536
|
+
return;
|
|
4537
|
+
case "bottom":
|
|
4538
|
+
anchor.position.set(0, -0.5, 0);
|
|
4539
|
+
return;
|
|
4540
|
+
case "left":
|
|
4541
|
+
anchor.position.set(-0.5, 0, 0);
|
|
4542
|
+
return;
|
|
4543
|
+
case "right":
|
|
4544
|
+
anchor.position.set(0.5, 0, 0);
|
|
4545
|
+
return;
|
|
4546
|
+
default: {
|
|
4547
|
+
const exhaustive = placement;
|
|
4548
|
+
return exhaustive;
|
|
4549
|
+
}
|
|
4550
|
+
}
|
|
4551
|
+
}
|
|
4552
|
+
function setTooltipAnchorOnLocalBox(anchor, placement, minX, maxX, minY, maxY) {
|
|
4553
|
+
switch (placement) {
|
|
4554
|
+
case "top":
|
|
4555
|
+
anchor.position.set((minX + maxX) / 2, maxY, 0);
|
|
4556
|
+
return;
|
|
4557
|
+
case "bottom":
|
|
4558
|
+
anchor.position.set((minX + maxX) / 2, minY, 0);
|
|
4559
|
+
return;
|
|
4560
|
+
case "left":
|
|
4561
|
+
anchor.position.set(minX, (minY + maxY) / 2, 0);
|
|
4562
|
+
return;
|
|
4563
|
+
case "right":
|
|
4564
|
+
anchor.position.set(maxX, (minY + maxY) / 2, 0);
|
|
4565
|
+
return;
|
|
4566
|
+
default: {
|
|
4567
|
+
const exhaustive = placement;
|
|
4568
|
+
return exhaustive;
|
|
4569
|
+
}
|
|
4570
|
+
}
|
|
4571
|
+
}
|
|
4572
|
+
function updateTooltipAnchor(anchor, group, placement, useAngularScale) {
|
|
4573
|
+
if (useAngularScale) {
|
|
4574
|
+
setTooltipAnchorOnUnitPlane(anchor, placement);
|
|
4575
|
+
return;
|
|
4576
|
+
}
|
|
4577
|
+
group.updateMatrixWorld(true);
|
|
4578
|
+
TOOLTIP_WORLD_BOX.makeEmpty();
|
|
4579
|
+
for (const child of group.children) {
|
|
4580
|
+
if (child === anchor) {
|
|
4581
|
+
continue;
|
|
4582
|
+
}
|
|
4583
|
+
TOOLTIP_WORLD_BOX.expandByObject(child);
|
|
4584
|
+
}
|
|
4585
|
+
if (TOOLTIP_WORLD_BOX.isEmpty()) {
|
|
4586
|
+
setTooltipAnchorOnUnitPlane(anchor, placement);
|
|
4587
|
+
return;
|
|
4588
|
+
}
|
|
4589
|
+
TOOLTIP_INVERSE.copy(group.matrixWorld).invert();
|
|
4590
|
+
TOOLTIP_LOCAL_BOX.makeEmpty();
|
|
4591
|
+
for (let x = 0; x <= 1; x += 1) {
|
|
4592
|
+
for (let y = 0; y <= 1; y += 1) {
|
|
4593
|
+
for (let z = 0; z <= 1; z += 1) {
|
|
4594
|
+
TOOLTIP_CORNER.set(
|
|
4595
|
+
x === 0 ? TOOLTIP_WORLD_BOX.min.x : TOOLTIP_WORLD_BOX.max.x,
|
|
4596
|
+
y === 0 ? TOOLTIP_WORLD_BOX.min.y : TOOLTIP_WORLD_BOX.max.y,
|
|
4597
|
+
z === 0 ? TOOLTIP_WORLD_BOX.min.z : TOOLTIP_WORLD_BOX.max.z
|
|
4598
|
+
).applyMatrix4(TOOLTIP_INVERSE);
|
|
4599
|
+
TOOLTIP_LOCAL_BOX.expandByPoint(TOOLTIP_CORNER);
|
|
4600
|
+
}
|
|
4601
|
+
}
|
|
4602
|
+
}
|
|
4603
|
+
setTooltipAnchorOnLocalBox(
|
|
4604
|
+
anchor,
|
|
4605
|
+
placement,
|
|
4606
|
+
TOOLTIP_LOCAL_BOX.min.x,
|
|
4607
|
+
TOOLTIP_LOCAL_BOX.max.x,
|
|
4608
|
+
TOOLTIP_LOCAL_BOX.min.y,
|
|
4609
|
+
TOOLTIP_LOCAL_BOX.max.y
|
|
4610
|
+
);
|
|
4611
|
+
}
|
|
4168
4612
|
function HotspotAnchor({
|
|
4169
4613
|
id,
|
|
4170
4614
|
position,
|
|
@@ -4184,7 +4628,12 @@ function HotspotAnchor({
|
|
|
4184
4628
|
visible = true,
|
|
4185
4629
|
draggable = false,
|
|
4186
4630
|
interactive = true,
|
|
4631
|
+
cursor,
|
|
4187
4632
|
ariaLabel,
|
|
4633
|
+
tooltip,
|
|
4634
|
+
tooltipTrigger = "always",
|
|
4635
|
+
tooltipPlacement = "top",
|
|
4636
|
+
tooltipOffset,
|
|
4188
4637
|
children,
|
|
4189
4638
|
onClick,
|
|
4190
4639
|
onHoverChange,
|
|
@@ -4192,10 +4641,20 @@ function HotspotAnchor({
|
|
|
4192
4641
|
onPositionChange,
|
|
4193
4642
|
onDragEnd
|
|
4194
4643
|
}) {
|
|
4195
|
-
const controlsRef = (0,
|
|
4196
|
-
const
|
|
4197
|
-
const
|
|
4198
|
-
const
|
|
4644
|
+
const controlsRef = (0, import_react19.useContext)(PanoramaViewContext);
|
|
4645
|
+
const eventBus = (0, import_react19.useContext)(PanoEventBusContext);
|
|
4646
|
+
const cursorApi = usePanoCursor();
|
|
4647
|
+
const groupRef = (0, import_react19.useRef)(null);
|
|
4648
|
+
const tooltipAnchorRef = (0, import_react19.useRef)(null);
|
|
4649
|
+
const dragStateRef = (0, import_react19.useRef)(null);
|
|
4650
|
+
const suppressNextClickRef = (0, import_react19.useRef)(false);
|
|
4651
|
+
const [hovered, setHovered] = (0, import_react19.useState)(false);
|
|
4652
|
+
const [dragging, setDragging] = (0, import_react19.useState)(false);
|
|
4653
|
+
const [pinned, setPinned] = (0, import_react19.useState)(false);
|
|
4654
|
+
const tooltipContent = (0, import_react19.useMemo)(
|
|
4655
|
+
() => resolveHotspotTooltipContent(tooltip),
|
|
4656
|
+
[tooltip]
|
|
4657
|
+
);
|
|
4199
4658
|
const normalizedPosition = normalizePanoPosition(position);
|
|
4200
4659
|
const rendering = internalOrientation && internalPlacement ? { orientation: internalOrientation, placement: internalPlacement } : HOTSPOT_MODE_RENDERING[mode];
|
|
4201
4660
|
const { orientation: orientation2, placement } = rendering;
|
|
@@ -4208,27 +4667,33 @@ function HotspotAnchor({
|
|
|
4208
4667
|
scaledWidth,
|
|
4209
4668
|
scaledHeight
|
|
4210
4669
|
);
|
|
4211
|
-
const worldPosition = (0,
|
|
4670
|
+
const worldPosition = (0, import_react19.useMemo)(
|
|
4212
4671
|
() => panoPositionToVector3(normalizedPosition, resolvedDistance),
|
|
4213
4672
|
[normalizedPosition.pitch, normalizedPosition.yaw, resolvedDistance]
|
|
4214
4673
|
);
|
|
4215
|
-
const surfaceQuaternion3 = (0,
|
|
4674
|
+
const surfaceQuaternion3 = (0, import_react19.useMemo)(
|
|
4216
4675
|
() => createSurfaceQuaternion(normalizedPosition),
|
|
4217
4676
|
[normalizedPosition.pitch, normalizedPosition.yaw]
|
|
4218
4677
|
);
|
|
4219
4678
|
const worldWidth = angularSizeToWorldSize(scaledWidth, resolvedDistance);
|
|
4220
4679
|
const worldHeight = angularSizeToWorldSize(scaledHeight, resolvedDistance);
|
|
4221
|
-
const focusGeometry = (0,
|
|
4680
|
+
const focusGeometry = (0, import_react19.useMemo)(() => {
|
|
4222
4681
|
const planeGeometry = new import_three9.PlaneGeometry(1, 1);
|
|
4223
4682
|
const geometry = new import_three9.EdgesGeometry(planeGeometry);
|
|
4224
4683
|
planeGeometry.dispose();
|
|
4225
4684
|
return geometry;
|
|
4226
4685
|
}, []);
|
|
4686
|
+
const canActivateFromKeyboard = Boolean(
|
|
4687
|
+
visible && interactive && (onClick || tooltipTrigger === "click")
|
|
4688
|
+
);
|
|
4227
4689
|
const focused = useHotspotAccessibility({
|
|
4228
4690
|
id,
|
|
4229
4691
|
ariaLabel,
|
|
4230
|
-
onActivate:
|
|
4231
|
-
|
|
4692
|
+
onActivate: canActivateFromKeyboard ? (event) => {
|
|
4693
|
+
if (tooltipTrigger === "click") {
|
|
4694
|
+
setPinned((current) => !current);
|
|
4695
|
+
}
|
|
4696
|
+
onClick?.({
|
|
4232
4697
|
id,
|
|
4233
4698
|
position: normalizedPosition,
|
|
4234
4699
|
source: "keyboard",
|
|
@@ -4236,15 +4701,59 @@ function HotspotAnchor({
|
|
|
4236
4701
|
});
|
|
4237
4702
|
} : void 0
|
|
4238
4703
|
});
|
|
4239
|
-
(
|
|
4704
|
+
const tooltipOpen = visible && tooltipContent !== null && isTooltipOpen(tooltipTrigger, hovered, focused, pinned);
|
|
4705
|
+
const cursorClaimId = hotspotCursorClaimId(id);
|
|
4706
|
+
(0, import_react19.useEffect)(
|
|
4240
4707
|
() => () => {
|
|
4241
4708
|
dragStateRef.current?.releaseInteractionLock();
|
|
4242
4709
|
dragStateRef.current = null;
|
|
4243
4710
|
},
|
|
4244
4711
|
[]
|
|
4245
4712
|
);
|
|
4246
|
-
(0,
|
|
4247
|
-
|
|
4713
|
+
(0, import_react19.useEffect)(() => {
|
|
4714
|
+
if (!cursorApi) {
|
|
4715
|
+
return;
|
|
4716
|
+
}
|
|
4717
|
+
if (interactive && visible && dragging) {
|
|
4718
|
+
cursorApi.claim(cursorClaimId, "hotspotDragging");
|
|
4719
|
+
return;
|
|
4720
|
+
}
|
|
4721
|
+
if (interactive && visible && hovered) {
|
|
4722
|
+
cursorApi.claim(cursorClaimId, "hotspot", cursor);
|
|
4723
|
+
return;
|
|
4724
|
+
}
|
|
4725
|
+
cursorApi.release(cursorClaimId);
|
|
4726
|
+
}, [
|
|
4727
|
+
cursor,
|
|
4728
|
+
cursorApi,
|
|
4729
|
+
cursorClaimId,
|
|
4730
|
+
dragging,
|
|
4731
|
+
hovered,
|
|
4732
|
+
interactive,
|
|
4733
|
+
visible
|
|
4734
|
+
]);
|
|
4735
|
+
(0, import_react19.useEffect)(
|
|
4736
|
+
() => () => {
|
|
4737
|
+
cursorApi?.release(cursorClaimId);
|
|
4738
|
+
},
|
|
4739
|
+
[cursorApi, cursorClaimId]
|
|
4740
|
+
);
|
|
4741
|
+
(0, import_react19.useEffect)(() => () => focusGeometry.dispose(), [focusGeometry]);
|
|
4742
|
+
(0, import_react19.useEffect)(() => {
|
|
4743
|
+
if (tooltipTrigger !== "click") {
|
|
4744
|
+
setPinned(false);
|
|
4745
|
+
return;
|
|
4746
|
+
}
|
|
4747
|
+
return eventBus?.subscribe("click", () => {
|
|
4748
|
+
setPinned(false);
|
|
4749
|
+
});
|
|
4750
|
+
}, [eventBus, tooltipTrigger]);
|
|
4751
|
+
(0, import_react19.useEffect)(() => {
|
|
4752
|
+
if (tooltipTrigger !== "hover") {
|
|
4753
|
+
setHovered(false);
|
|
4754
|
+
}
|
|
4755
|
+
}, [tooltipTrigger]);
|
|
4756
|
+
(0, import_fiber14.useFrame)(({ camera }) => {
|
|
4248
4757
|
if (!groupRef.current) {
|
|
4249
4758
|
return;
|
|
4250
4759
|
}
|
|
@@ -4263,6 +4772,14 @@ function HotspotAnchor({
|
|
|
4263
4772
|
(useAngularScale ? worldHeight : 1) * scaleFactor,
|
|
4264
4773
|
1
|
|
4265
4774
|
);
|
|
4775
|
+
if (tooltipOpen && tooltipAnchorRef.current) {
|
|
4776
|
+
updateTooltipAnchor(
|
|
4777
|
+
tooltipAnchorRef.current,
|
|
4778
|
+
groupRef.current,
|
|
4779
|
+
tooltipPlacement,
|
|
4780
|
+
useAngularScale
|
|
4781
|
+
);
|
|
4782
|
+
}
|
|
4266
4783
|
});
|
|
4267
4784
|
const stopPointerEvent = (event) => {
|
|
4268
4785
|
event.stopPropagation();
|
|
@@ -4289,8 +4806,12 @@ function HotspotAnchor({
|
|
|
4289
4806
|
suppressNextClickRef.current = dragState.moved;
|
|
4290
4807
|
dragState.releaseInteractionLock();
|
|
4291
4808
|
dragStateRef.current = null;
|
|
4809
|
+
setDragging(false);
|
|
4810
|
+
if (emitDragEnd) {
|
|
4811
|
+
setHovered(true);
|
|
4812
|
+
}
|
|
4292
4813
|
};
|
|
4293
|
-
return /* @__PURE__ */ (0,
|
|
4814
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
4294
4815
|
"group",
|
|
4295
4816
|
{
|
|
4296
4817
|
ref: groupRef,
|
|
@@ -4301,6 +4822,9 @@ function HotspotAnchor({
|
|
|
4301
4822
|
onClick: interactive ? (event) => {
|
|
4302
4823
|
stopPointerEvent(event);
|
|
4303
4824
|
if (!suppressNextClickRef.current) {
|
|
4825
|
+
if (tooltipTrigger === "click") {
|
|
4826
|
+
setPinned((current) => !current);
|
|
4827
|
+
}
|
|
4304
4828
|
onClick?.(makeInteractionEvent(id, normalizedPosition, event));
|
|
4305
4829
|
}
|
|
4306
4830
|
suppressNextClickRef.current = false;
|
|
@@ -4322,6 +4846,8 @@ function HotspotAnchor({
|
|
|
4322
4846
|
releaseInteractionLock,
|
|
4323
4847
|
moved: false
|
|
4324
4848
|
};
|
|
4849
|
+
setHovered(false);
|
|
4850
|
+
setDragging(true);
|
|
4325
4851
|
onDragStart?.({
|
|
4326
4852
|
...makeInteractionEvent(id, startPosition, event),
|
|
4327
4853
|
source: "pointer",
|
|
@@ -4344,6 +4870,7 @@ function HotspotAnchor({
|
|
|
4344
4870
|
} : void 0,
|
|
4345
4871
|
onPointerOut: interactive ? (event) => {
|
|
4346
4872
|
if (!dragStateRef.current) {
|
|
4873
|
+
setHovered(false);
|
|
4347
4874
|
onHoverChange?.(
|
|
4348
4875
|
false,
|
|
4349
4876
|
makeInteractionEvent(id, normalizedPosition, event)
|
|
@@ -4352,6 +4879,7 @@ function HotspotAnchor({
|
|
|
4352
4879
|
} : void 0,
|
|
4353
4880
|
onPointerOver: interactive ? (event) => {
|
|
4354
4881
|
if (!dragStateRef.current) {
|
|
4882
|
+
setHovered(true);
|
|
4355
4883
|
onHoverChange?.(
|
|
4356
4884
|
true,
|
|
4357
4885
|
makeInteractionEvent(id, normalizedPosition, event)
|
|
@@ -4360,38 +4888,161 @@ function HotspotAnchor({
|
|
|
4360
4888
|
} : void 0,
|
|
4361
4889
|
onPointerUp: interactive ? (event) => releasePointer(event, true) : void 0,
|
|
4362
4890
|
children: [
|
|
4363
|
-
focused ? focusContent ?? /* @__PURE__ */ (0,
|
|
4891
|
+
focused ? focusContent ?? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
4364
4892
|
"lineSegments",
|
|
4365
4893
|
{
|
|
4366
4894
|
geometry: focusGeometry,
|
|
4367
4895
|
position: [0, 0, 0.01],
|
|
4368
4896
|
renderOrder: renderOrder + 1,
|
|
4369
4897
|
scale: [1.12, 1.12, 1],
|
|
4370
|
-
children: /* @__PURE__ */ (0,
|
|
4898
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("lineBasicMaterial", { color: "#f5fbfc", depthTest: false })
|
|
4371
4899
|
}
|
|
4372
4900
|
) : null,
|
|
4373
|
-
children
|
|
4901
|
+
children,
|
|
4902
|
+
tooltipOpen && tooltipContent ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("group", { ref: tooltipAnchorRef, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
4903
|
+
HotspotTooltip,
|
|
4904
|
+
{
|
|
4905
|
+
content: tooltipContent,
|
|
4906
|
+
offset: resolveHotspotTooltipOffset(tooltipOffset),
|
|
4907
|
+
placement: tooltipPlacement
|
|
4908
|
+
}
|
|
4909
|
+
) }) : null
|
|
4374
4910
|
]
|
|
4375
4911
|
}
|
|
4376
4912
|
);
|
|
4377
4913
|
}
|
|
4378
4914
|
|
|
4379
|
-
// src/hotspot/
|
|
4380
|
-
var
|
|
4915
|
+
// src/hotspot/hotspot-plane.tsx
|
|
4916
|
+
var import_three10 = require("three");
|
|
4917
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
4918
|
+
var HOTSPOT_ALPHA_CUTOFF = 0.05;
|
|
4919
|
+
var SAMPLE_UV = new import_three10.Vector2();
|
|
4920
|
+
var RAYCAST_HITS = [];
|
|
4921
|
+
var IMAGE_DATA_CACHE = /* @__PURE__ */ new WeakMap();
|
|
4381
4922
|
function clampOpacity(opacity) {
|
|
4382
4923
|
if (!Number.isFinite(opacity)) {
|
|
4383
4924
|
return 1;
|
|
4384
4925
|
}
|
|
4385
4926
|
return Math.max(0, Math.min(opacity, 1));
|
|
4386
4927
|
}
|
|
4928
|
+
function isSampleableImage(image) {
|
|
4929
|
+
if (image instanceof HTMLImageElement) {
|
|
4930
|
+
return image.naturalWidth > 0 && image.naturalHeight > 0;
|
|
4931
|
+
}
|
|
4932
|
+
if (image instanceof HTMLCanvasElement) {
|
|
4933
|
+
return image.width > 0 && image.height > 0;
|
|
4934
|
+
}
|
|
4935
|
+
if (typeof OffscreenCanvas !== "undefined" && image instanceof OffscreenCanvas) {
|
|
4936
|
+
return image.width > 0 && image.height > 0;
|
|
4937
|
+
}
|
|
4938
|
+
if (typeof ImageBitmap !== "undefined" && image instanceof ImageBitmap) {
|
|
4939
|
+
return image.width > 0 && image.height > 0;
|
|
4940
|
+
}
|
|
4941
|
+
return false;
|
|
4942
|
+
}
|
|
4943
|
+
function imageSize(image) {
|
|
4944
|
+
if (image instanceof HTMLImageElement) {
|
|
4945
|
+
return { width: image.naturalWidth, height: image.naturalHeight };
|
|
4946
|
+
}
|
|
4947
|
+
return { width: image.width, height: image.height };
|
|
4948
|
+
}
|
|
4949
|
+
function readImageData(image) {
|
|
4950
|
+
const cached = IMAGE_DATA_CACHE.get(image);
|
|
4951
|
+
if (cached) {
|
|
4952
|
+
return cached;
|
|
4953
|
+
}
|
|
4954
|
+
const { width, height } = imageSize(image);
|
|
4955
|
+
const canvas = document.createElement("canvas");
|
|
4956
|
+
canvas.width = width;
|
|
4957
|
+
canvas.height = height;
|
|
4958
|
+
const context = canvas.getContext("2d", { willReadFrequently: true });
|
|
4959
|
+
if (!context) {
|
|
4960
|
+
return null;
|
|
4961
|
+
}
|
|
4962
|
+
try {
|
|
4963
|
+
context.drawImage(image, 0, 0);
|
|
4964
|
+
const data = context.getImageData(0, 0, width, height);
|
|
4965
|
+
IMAGE_DATA_CACHE.set(image, data);
|
|
4966
|
+
return data;
|
|
4967
|
+
} catch {
|
|
4968
|
+
return null;
|
|
4969
|
+
}
|
|
4970
|
+
}
|
|
4971
|
+
function sampleTextureAlpha(texture, u, v) {
|
|
4972
|
+
if (!isSampleableImage(texture.image)) {
|
|
4973
|
+
return null;
|
|
4974
|
+
}
|
|
4975
|
+
const data = readImageData(texture.image);
|
|
4976
|
+
if (!data) {
|
|
4977
|
+
return null;
|
|
4978
|
+
}
|
|
4979
|
+
SAMPLE_UV.set(u, v);
|
|
4980
|
+
texture.transformUv(SAMPLE_UV);
|
|
4981
|
+
const pixelX = Math.min(
|
|
4982
|
+
data.width - 1,
|
|
4983
|
+
Math.max(0, Math.floor(SAMPLE_UV.x * data.width))
|
|
4984
|
+
);
|
|
4985
|
+
const pixelY = Math.min(
|
|
4986
|
+
data.height - 1,
|
|
4987
|
+
Math.max(0, Math.floor(SAMPLE_UV.y * data.height))
|
|
4988
|
+
);
|
|
4989
|
+
return data.data[(pixelY * data.width + pixelX) * 4 + 3] / 255;
|
|
4990
|
+
}
|
|
4991
|
+
function hotspotPlaneRaycast(raycaster, intersects2) {
|
|
4992
|
+
const material = Array.isArray(this.material) ? this.material[0] : this.material;
|
|
4993
|
+
if (!(material instanceof import_three10.MeshBasicMaterial)) {
|
|
4994
|
+
import_three10.Mesh.prototype.raycast.call(this, raycaster, intersects2);
|
|
4995
|
+
return;
|
|
4996
|
+
}
|
|
4997
|
+
const cutoff = Math.max(material.alphaTest, HOTSPOT_ALPHA_CUTOFF);
|
|
4998
|
+
if (material.opacity < cutoff) {
|
|
4999
|
+
return;
|
|
5000
|
+
}
|
|
5001
|
+
RAYCAST_HITS.length = 0;
|
|
5002
|
+
import_three10.Mesh.prototype.raycast.call(this, raycaster, RAYCAST_HITS);
|
|
5003
|
+
const map = material.map;
|
|
5004
|
+
for (const hit of RAYCAST_HITS) {
|
|
5005
|
+
if (!map || !hit.uv) {
|
|
5006
|
+
intersects2.push(hit);
|
|
5007
|
+
continue;
|
|
5008
|
+
}
|
|
5009
|
+
const texelAlpha = sampleTextureAlpha(map, hit.uv.x, hit.uv.y);
|
|
5010
|
+
if (texelAlpha === null || texelAlpha * material.opacity >= cutoff) {
|
|
5011
|
+
intersects2.push(hit);
|
|
5012
|
+
}
|
|
5013
|
+
}
|
|
5014
|
+
}
|
|
5015
|
+
function HotspotPlane({
|
|
5016
|
+
map,
|
|
5017
|
+
opacity
|
|
5018
|
+
}) {
|
|
5019
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("mesh", { raycast: hotspotPlaneRaycast, children: [
|
|
5020
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("planeGeometry", { args: [1, 1] }),
|
|
5021
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
5022
|
+
"meshBasicMaterial",
|
|
5023
|
+
{
|
|
5024
|
+
alphaTest: HOTSPOT_ALPHA_CUTOFF,
|
|
5025
|
+
alphaToCoverage: true,
|
|
5026
|
+
map,
|
|
5027
|
+
opacity: map ? clampOpacity(opacity) : 0,
|
|
5028
|
+
side: import_three10.DoubleSide,
|
|
5029
|
+
toneMapped: false,
|
|
5030
|
+
transparent: true
|
|
5031
|
+
}
|
|
5032
|
+
)
|
|
5033
|
+
] });
|
|
5034
|
+
}
|
|
5035
|
+
|
|
5036
|
+
// src/hotspot/image-hotspot.tsx
|
|
5037
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
4387
5038
|
function useHotspotImageTexture(src, onLoad, onError) {
|
|
4388
|
-
const gl = (0,
|
|
4389
|
-
const [texture, setTexture] = (0,
|
|
4390
|
-
const onLoadRef = (0,
|
|
4391
|
-
const onErrorRef = (0,
|
|
5039
|
+
const gl = (0, import_fiber15.useThree)((state) => state.gl);
|
|
5040
|
+
const [texture, setTexture] = (0, import_react20.useState)(null);
|
|
5041
|
+
const onLoadRef = (0, import_react20.useRef)(onLoad);
|
|
5042
|
+
const onErrorRef = (0, import_react20.useRef)(onError);
|
|
4392
5043
|
onLoadRef.current = onLoad;
|
|
4393
5044
|
onErrorRef.current = onError;
|
|
4394
|
-
(0,
|
|
5045
|
+
(0, import_react20.useEffect)(() => {
|
|
4395
5046
|
let active = true;
|
|
4396
5047
|
setTexture(null);
|
|
4397
5048
|
if (!src) {
|
|
@@ -4399,7 +5050,7 @@ function useHotspotImageTexture(src, onLoad, onError) {
|
|
|
4399
5050
|
active = false;
|
|
4400
5051
|
};
|
|
4401
5052
|
}
|
|
4402
|
-
const loader = new
|
|
5053
|
+
const loader = new import_three11.TextureLoader();
|
|
4403
5054
|
loader.load(
|
|
4404
5055
|
src,
|
|
4405
5056
|
(loadedTexture) => {
|
|
@@ -4407,11 +5058,11 @@ function useHotspotImageTexture(src, onLoad, onError) {
|
|
|
4407
5058
|
loadedTexture.dispose();
|
|
4408
5059
|
return;
|
|
4409
5060
|
}
|
|
4410
|
-
loadedTexture.colorSpace =
|
|
4411
|
-
loadedTexture.wrapS =
|
|
4412
|
-
loadedTexture.wrapT =
|
|
4413
|
-
loadedTexture.magFilter =
|
|
4414
|
-
loadedTexture.minFilter =
|
|
5061
|
+
loadedTexture.colorSpace = import_three11.SRGBColorSpace;
|
|
5062
|
+
loadedTexture.wrapS = import_three11.ClampToEdgeWrapping;
|
|
5063
|
+
loadedTexture.wrapT = import_three11.ClampToEdgeWrapping;
|
|
5064
|
+
loadedTexture.magFilter = import_three11.LinearFilter;
|
|
5065
|
+
loadedTexture.minFilter = import_three11.LinearMipmapLinearFilter;
|
|
4415
5066
|
loadedTexture.generateMipmaps = true;
|
|
4416
5067
|
loadedTexture.anisotropy = gl.capabilities.getMaxAnisotropy();
|
|
4417
5068
|
loadedTexture.needsUpdate = true;
|
|
@@ -4429,7 +5080,7 @@ function useHotspotImageTexture(src, onLoad, onError) {
|
|
|
4429
5080
|
active = false;
|
|
4430
5081
|
};
|
|
4431
5082
|
}, [gl, src]);
|
|
4432
|
-
(0,
|
|
5083
|
+
(0, import_react20.useEffect)(
|
|
4433
5084
|
() => () => {
|
|
4434
5085
|
texture?.dispose();
|
|
4435
5086
|
},
|
|
@@ -4447,29 +5098,42 @@ function ImageHotspot({
|
|
|
4447
5098
|
...anchorProps
|
|
4448
5099
|
}) {
|
|
4449
5100
|
const texture = useHotspotImageTexture(src, onLoad, onError);
|
|
4450
|
-
return /* @__PURE__ */ (0,
|
|
4451
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("planeGeometry", { args: [1, 1] }),
|
|
4452
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4453
|
-
"meshBasicMaterial",
|
|
4454
|
-
{
|
|
4455
|
-
map: texture,
|
|
4456
|
-
opacity: texture ? clampOpacity(opacity) : 0,
|
|
4457
|
-
side: import_three10.DoubleSide,
|
|
4458
|
-
toneMapped: false,
|
|
4459
|
-
transparent: true
|
|
4460
|
-
}
|
|
4461
|
-
)
|
|
4462
|
-
] }) });
|
|
5101
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(HotspotPlane, { map: texture, opacity }) });
|
|
4463
5102
|
}
|
|
4464
5103
|
|
|
4465
5104
|
// src/hotspot/polygon-hotspot.tsx
|
|
4466
|
-
var
|
|
4467
|
-
var
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
var
|
|
4471
|
-
var
|
|
4472
|
-
|
|
5105
|
+
var import_react21 = require("react");
|
|
5106
|
+
var import_three12 = require("three");
|
|
5107
|
+
|
|
5108
|
+
// src/hotspot/hotspot-stroke-line.tsx
|
|
5109
|
+
var import_drei2 = require("@react-three/drei");
|
|
5110
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
5111
|
+
function HotspotStrokeLine({
|
|
5112
|
+
points,
|
|
5113
|
+
color,
|
|
5114
|
+
lineWidth,
|
|
5115
|
+
opacity,
|
|
5116
|
+
renderOrder
|
|
5117
|
+
}) {
|
|
5118
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
5119
|
+
import_drei2.Line,
|
|
5120
|
+
{
|
|
5121
|
+
alphaToCoverage: true,
|
|
5122
|
+
color,
|
|
5123
|
+
depthTest: true,
|
|
5124
|
+
depthWrite: false,
|
|
5125
|
+
lineWidth: Math.max(0.5, lineWidth),
|
|
5126
|
+
opacity,
|
|
5127
|
+
points,
|
|
5128
|
+
renderOrder,
|
|
5129
|
+
transparent: true,
|
|
5130
|
+
worldUnits: false
|
|
5131
|
+
}
|
|
5132
|
+
);
|
|
5133
|
+
}
|
|
5134
|
+
|
|
5135
|
+
// src/hotspot/polygon-hotspot.tsx
|
|
5136
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
4473
5137
|
var POLYGON_RADIUS = 990;
|
|
4474
5138
|
var MAX_FILL_SEGMENT_DEGREES = 7;
|
|
4475
5139
|
function cloneVertices(vertices) {
|
|
@@ -4504,7 +5168,7 @@ function intersects(a, b, c, d) {
|
|
|
4504
5168
|
}
|
|
4505
5169
|
function hasSelfIntersection(vertices) {
|
|
4506
5170
|
const points = vertices.map(
|
|
4507
|
-
(vertex) => new
|
|
5171
|
+
(vertex) => new import_three12.Vector2(vertex.unwrappedYaw, vertex.pitch)
|
|
4508
5172
|
);
|
|
4509
5173
|
for (let index = 0; index < points.length; index += 1) {
|
|
4510
5174
|
const nextIndex = (index + 1) % points.length;
|
|
@@ -4541,7 +5205,7 @@ function polygonContainsDirection(vertices, direction) {
|
|
|
4541
5205
|
}
|
|
4542
5206
|
function fitsHemisphere(vertices) {
|
|
4543
5207
|
const directions = vertices.map((vertex) => panoPositionToVector3(vertex).normalize());
|
|
4544
|
-
const candidates = [new
|
|
5208
|
+
const candidates = [new import_three12.Vector3()];
|
|
4545
5209
|
for (const direction of directions) {
|
|
4546
5210
|
candidates[0].add(direction);
|
|
4547
5211
|
candidates.push(direction.clone());
|
|
@@ -4565,7 +5229,7 @@ function validatePolygonVertices(vertices) {
|
|
|
4565
5229
|
if (hasSelfIntersection(unwrapped)) {
|
|
4566
5230
|
issues.push({ code: "self_intersection", message: "Polygon edges cannot cross." });
|
|
4567
5231
|
}
|
|
4568
|
-
if (polygonContainsDirection(normalized, new
|
|
5232
|
+
if (polygonContainsDirection(normalized, new import_three12.Vector3(0, 1, 0)) || polygonContainsDirection(normalized, new import_three12.Vector3(0, -1, 0))) {
|
|
4569
5233
|
issues.push({ code: "contains_pole", message: "Polygons cannot contain a panorama pole." });
|
|
4570
5234
|
}
|
|
4571
5235
|
if (!fitsHemisphere(normalized)) {
|
|
@@ -4576,7 +5240,7 @@ function validatePolygonVertices(vertices) {
|
|
|
4576
5240
|
function polygonCenter(vertices) {
|
|
4577
5241
|
const sum = vertices.reduce(
|
|
4578
5242
|
(total, vertex) => total.add(panoPositionToVector3(vertex).normalize()),
|
|
4579
|
-
new
|
|
5243
|
+
new import_three12.Vector3()
|
|
4580
5244
|
);
|
|
4581
5245
|
return sum.lengthSq() > 1e-8 ? vector3ToPanoPosition(sum) : normalizePanoPosition(vertices[0]);
|
|
4582
5246
|
}
|
|
@@ -4585,20 +5249,20 @@ function surfaceQuaternion(position) {
|
|
|
4585
5249
|
const inward = outward.clone().negate();
|
|
4586
5250
|
const pitch = position.pitch * Math.PI / 180;
|
|
4587
5251
|
const yaw = position.yaw * Math.PI / 180;
|
|
4588
|
-
const localUp = new
|
|
5252
|
+
const localUp = new import_three12.Vector3(
|
|
4589
5253
|
-Math.sin(pitch) * Math.sin(yaw),
|
|
4590
5254
|
Math.cos(pitch),
|
|
4591
5255
|
Math.sin(pitch) * Math.cos(yaw)
|
|
4592
5256
|
).normalize();
|
|
4593
|
-
return new
|
|
4594
|
-
new
|
|
5257
|
+
return new import_three12.Quaternion().setFromRotationMatrix(
|
|
5258
|
+
new import_three12.Matrix4().makeBasis(localUp.clone().cross(inward).normalize(), localUp, inward)
|
|
4595
5259
|
);
|
|
4596
5260
|
}
|
|
4597
5261
|
function makeWorldToLocal(center) {
|
|
4598
|
-
return new
|
|
5262
|
+
return new import_three12.Matrix4().compose(
|
|
4599
5263
|
panoPositionToVector3(center, POLYGON_RADIUS),
|
|
4600
5264
|
surfaceQuaternion(center),
|
|
4601
|
-
new
|
|
5265
|
+
new import_three12.Vector3(1, 1, 1)
|
|
4602
5266
|
).invert();
|
|
4603
5267
|
}
|
|
4604
5268
|
function projectedPoint(a, b, c, weightB, weightC, radius, worldToLocal) {
|
|
@@ -4653,8 +5317,8 @@ function addSubdividedTriangle(positions, indices, a, b, c, worldToLocal, steps)
|
|
|
4653
5317
|
}
|
|
4654
5318
|
function makeFillGeometry(vertices, center) {
|
|
4655
5319
|
const unwrapped = unwrapPolygonVertices(vertices);
|
|
4656
|
-
const contour = unwrapped.map((vertex) => new
|
|
4657
|
-
const triangles =
|
|
5320
|
+
const contour = unwrapped.map((vertex) => new import_three12.Vector2(vertex.unwrappedYaw, vertex.pitch));
|
|
5321
|
+
const triangles = import_three12.ShapeUtils.triangulateShape(contour, []);
|
|
4658
5322
|
const positions = [];
|
|
4659
5323
|
const indices = [];
|
|
4660
5324
|
const worldToLocal = makeWorldToLocal(center);
|
|
@@ -4670,10 +5334,10 @@ function makeFillGeometry(vertices, center) {
|
|
|
4670
5334
|
steps
|
|
4671
5335
|
);
|
|
4672
5336
|
}
|
|
4673
|
-
return new
|
|
5337
|
+
return new import_three12.BufferGeometry().setAttribute("position", new import_three12.Float32BufferAttribute(positions, 3)).setIndex(indices);
|
|
4674
5338
|
}
|
|
4675
5339
|
function makeStrokePositions(vertices, center) {
|
|
4676
|
-
const
|
|
5340
|
+
const points = [];
|
|
4677
5341
|
const worldToLocal = makeWorldToLocal(center);
|
|
4678
5342
|
const unwrapped = unwrapPolygonVertices(vertices);
|
|
4679
5343
|
const steps = polygonSubdivisionSteps(vertices);
|
|
@@ -4689,33 +5353,14 @@ function makeStrokePositions(vertices, center) {
|
|
|
4689
5353
|
},
|
|
4690
5354
|
POLYGON_RADIUS
|
|
4691
5355
|
).applyMatrix4(worldToLocal);
|
|
4692
|
-
|
|
5356
|
+
points.push([point.x, point.y, point.z]);
|
|
4693
5357
|
}
|
|
4694
5358
|
}
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
4700
|
-
geometry.setPositions(positions);
|
|
4701
|
-
const material = new import_LineMaterial.LineMaterial({
|
|
4702
|
-
color,
|
|
4703
|
-
depthTest: true,
|
|
4704
|
-
depthWrite: false,
|
|
4705
|
-
linewidth: Math.max(0.5, width),
|
|
4706
|
-
opacity,
|
|
4707
|
-
transparent: true,
|
|
4708
|
-
worldUnits: false,
|
|
4709
|
-
alphaToCoverage: true
|
|
4710
|
-
});
|
|
4711
|
-
const line = new import_Line2.Line2(geometry, material);
|
|
4712
|
-
line.computeLineDistances();
|
|
4713
|
-
return line;
|
|
4714
|
-
}
|
|
4715
|
-
function disposeStrokeLine(line) {
|
|
4716
|
-
if (!line) return;
|
|
4717
|
-
line.geometry.dispose();
|
|
4718
|
-
line.material.dispose();
|
|
5359
|
+
const first = points[0];
|
|
5360
|
+
if (first) {
|
|
5361
|
+
points.push(first);
|
|
5362
|
+
}
|
|
5363
|
+
return points;
|
|
4719
5364
|
}
|
|
4720
5365
|
function translateVertices(vertices, from, to) {
|
|
4721
5366
|
const yawOffset = normalizePanoYaw(to.yaw - from.yaw);
|
|
@@ -4742,45 +5387,27 @@ function PolygonHotspot({
|
|
|
4742
5387
|
onInvalid,
|
|
4743
5388
|
...anchorProps
|
|
4744
5389
|
}) {
|
|
4745
|
-
const
|
|
4746
|
-
const size = (0, import_fiber15.useThree)((state) => state.size);
|
|
4747
|
-
const issues = (0, import_react18.useMemo)(() => validatePolygonVertices(vertices), [vertices]);
|
|
5390
|
+
const issues = (0, import_react21.useMemo)(() => validatePolygonVertices(vertices), [vertices]);
|
|
4748
5391
|
const valid = issues.length === 0;
|
|
4749
|
-
const center = (0,
|
|
4750
|
-
const fillGeometry = (0,
|
|
5392
|
+
const center = (0, import_react21.useMemo)(() => valid ? polygonCenter(vertices) : null, [valid, vertices]);
|
|
5393
|
+
const fillGeometry = (0, import_react21.useMemo)(
|
|
4751
5394
|
() => valid && center ? makeFillGeometry(vertices, center) : null,
|
|
4752
5395
|
[center, valid, vertices]
|
|
4753
5396
|
);
|
|
4754
|
-
const
|
|
5397
|
+
const strokePoints = (0, import_react21.useMemo)(
|
|
4755
5398
|
() => valid && center ? makeStrokePositions(vertices, center) : null,
|
|
4756
5399
|
[center, valid, vertices]
|
|
4757
5400
|
);
|
|
4758
5401
|
const resolvedStrokeOpacity = Math.max(0, Math.min(strokeOpacity, 1));
|
|
4759
|
-
const
|
|
4760
|
-
const strokeLine = (0, import_react18.useMemo)(
|
|
4761
|
-
() => strokePositions ? makeStrokeLine(strokePositions, stroke, strokeWidth * devicePixelRatio, resolvedStrokeOpacity) : null,
|
|
4762
|
-
[devicePixelRatio, resolvedStrokeOpacity, stroke, strokePositions, strokeWidth]
|
|
4763
|
-
);
|
|
4764
|
-
const focusStrokeLine = (0, import_react18.useMemo)(
|
|
4765
|
-
() => strokePositions ? makeStrokeLine(strokePositions, "#75cbd3", (strokeWidth + 2) * devicePixelRatio, 1) : null,
|
|
4766
|
-
[devicePixelRatio, strokePositions, strokeWidth]
|
|
4767
|
-
);
|
|
4768
|
-
const startVerticesRef = (0, import_react18.useRef)(null);
|
|
5402
|
+
const startVerticesRef = (0, import_react21.useRef)(null);
|
|
4769
5403
|
const issuesKey = issues.map((issue) => issue.code).join(",");
|
|
4770
|
-
(0,
|
|
5404
|
+
(0, import_react21.useEffect)(() => {
|
|
4771
5405
|
if (!valid) onInvalid?.(issues);
|
|
4772
5406
|
}, [issues, issuesKey, onInvalid, valid]);
|
|
4773
|
-
(0,
|
|
4774
|
-
|
|
4775
|
-
|
|
4776
|
-
|
|
4777
|
-
const width = gl.domElement.width;
|
|
4778
|
-
const height = gl.domElement.height;
|
|
4779
|
-
for (const line of [strokeLine, focusStrokeLine]) {
|
|
4780
|
-
if (line) line.material.resolution.set(width, height);
|
|
4781
|
-
}
|
|
4782
|
-
}, [focusStrokeLine, gl, size.height, size.width, strokeLine]);
|
|
4783
|
-
if (!valid || !center || !fillGeometry || !strokeLine || !focusStrokeLine) return null;
|
|
5407
|
+
(0, import_react21.useEffect)(() => () => fillGeometry?.dispose(), [fillGeometry]);
|
|
5408
|
+
if (!valid || !center || !fillGeometry || !strokePoints || strokePoints.length < 2) {
|
|
5409
|
+
return null;
|
|
5410
|
+
}
|
|
4784
5411
|
const emitVerticesChange = (event, callback) => {
|
|
4785
5412
|
const startVertices = startVerticesRef.current ?? cloneVertices(vertices);
|
|
4786
5413
|
const nextVertices = translateVertices(startVertices, event.startPosition, event.position);
|
|
@@ -4792,7 +5419,7 @@ function PolygonHotspot({
|
|
|
4792
5419
|
startPosition: event.startPosition
|
|
4793
5420
|
});
|
|
4794
5421
|
};
|
|
4795
|
-
return /* @__PURE__ */ (0,
|
|
5422
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
4796
5423
|
HotspotAnchor,
|
|
4797
5424
|
{
|
|
4798
5425
|
...anchorProps,
|
|
@@ -4807,7 +5434,16 @@ function PolygonHotspot({
|
|
|
4807
5434
|
draggable,
|
|
4808
5435
|
interactive,
|
|
4809
5436
|
useAngularScale: false,
|
|
4810
|
-
focusContent: /* @__PURE__ */ (0,
|
|
5437
|
+
focusContent: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
5438
|
+
HotspotStrokeLine,
|
|
5439
|
+
{
|
|
5440
|
+
color: "#75cbd3",
|
|
5441
|
+
lineWidth: strokeWidth + 2,
|
|
5442
|
+
opacity: 1,
|
|
5443
|
+
points: strokePoints,
|
|
5444
|
+
renderOrder: renderOrder + 2
|
|
5445
|
+
}
|
|
5446
|
+
),
|
|
4811
5447
|
onDragStart: (event) => {
|
|
4812
5448
|
startVerticesRef.current = cloneVertices(vertices);
|
|
4813
5449
|
emitVerticesChange(event, onDragStart);
|
|
@@ -4818,30 +5454,35 @@ function PolygonHotspot({
|
|
|
4818
5454
|
startVerticesRef.current = null;
|
|
4819
5455
|
},
|
|
4820
5456
|
children: [
|
|
4821
|
-
/* @__PURE__ */ (0,
|
|
5457
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("mesh", { geometry: fillGeometry, renderOrder, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
4822
5458
|
"meshBasicMaterial",
|
|
4823
5459
|
{
|
|
4824
5460
|
color: fill,
|
|
4825
5461
|
depthWrite: false,
|
|
4826
5462
|
opacity: Math.max(0, Math.min(fillOpacity, 1)),
|
|
4827
|
-
side:
|
|
5463
|
+
side: import_three12.DoubleSide,
|
|
4828
5464
|
transparent: true
|
|
4829
5465
|
}
|
|
4830
5466
|
) }),
|
|
4831
|
-
/* @__PURE__ */ (0,
|
|
5467
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
5468
|
+
HotspotStrokeLine,
|
|
5469
|
+
{
|
|
5470
|
+
color: stroke,
|
|
5471
|
+
lineWidth: strokeWidth,
|
|
5472
|
+
opacity: resolvedStrokeOpacity,
|
|
5473
|
+
points: strokePoints,
|
|
5474
|
+
renderOrder: renderOrder + 1
|
|
5475
|
+
}
|
|
5476
|
+
)
|
|
4832
5477
|
]
|
|
4833
5478
|
}
|
|
4834
5479
|
);
|
|
4835
5480
|
}
|
|
4836
5481
|
|
|
4837
5482
|
// src/hotspot/polyline-hotspot.tsx
|
|
4838
|
-
var
|
|
4839
|
-
var
|
|
4840
|
-
var
|
|
4841
|
-
var import_Line22 = require("three/addons/lines/Line2.js");
|
|
4842
|
-
var import_LineGeometry2 = require("three/addons/lines/LineGeometry.js");
|
|
4843
|
-
var import_LineMaterial2 = require("three/addons/lines/LineMaterial.js");
|
|
4844
|
-
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
5483
|
+
var import_react22 = require("react");
|
|
5484
|
+
var import_three13 = require("three");
|
|
5485
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
4845
5486
|
var POLYLINE_RADIUS = 990;
|
|
4846
5487
|
var MAX_SEGMENT_DEGREES = 7;
|
|
4847
5488
|
function cloneVertices2(vertices) {
|
|
@@ -4866,29 +5507,29 @@ function unwrapVertices(vertices) {
|
|
|
4866
5507
|
function polylineCenter(vertices) {
|
|
4867
5508
|
const sum = vertices.reduce(
|
|
4868
5509
|
(total, vertex) => total.add(panoPositionToVector3(vertex).normalize()),
|
|
4869
|
-
new
|
|
5510
|
+
new import_three13.Vector3()
|
|
4870
5511
|
);
|
|
4871
5512
|
return sum.lengthSq() > 1e-8 ? vector3ToPanoPosition(sum) : normalizePanoPosition(vertices[0]);
|
|
4872
5513
|
}
|
|
4873
5514
|
function surfaceQuaternion2(position) {
|
|
4874
5515
|
const outward = panoPositionToVector3(position).normalize();
|
|
4875
5516
|
const inward = outward.clone().negate();
|
|
4876
|
-
const pitch =
|
|
4877
|
-
const yaw =
|
|
4878
|
-
const localUp = new
|
|
5517
|
+
const pitch = import_three13.MathUtils.degToRad(position.pitch);
|
|
5518
|
+
const yaw = import_three13.MathUtils.degToRad(position.yaw);
|
|
5519
|
+
const localUp = new import_three13.Vector3(
|
|
4879
5520
|
-Math.sin(pitch) * Math.sin(yaw),
|
|
4880
5521
|
Math.cos(pitch),
|
|
4881
5522
|
Math.sin(pitch) * Math.cos(yaw)
|
|
4882
5523
|
).normalize();
|
|
4883
|
-
return new
|
|
4884
|
-
new
|
|
5524
|
+
return new import_three13.Quaternion().setFromRotationMatrix(
|
|
5525
|
+
new import_three13.Matrix4().makeBasis(localUp.clone().cross(inward).normalize(), localUp, inward)
|
|
4885
5526
|
);
|
|
4886
5527
|
}
|
|
4887
5528
|
function makeWorldToLocal2(center) {
|
|
4888
|
-
return new
|
|
5529
|
+
return new import_three13.Matrix4().compose(
|
|
4889
5530
|
panoPositionToVector3(center, POLYLINE_RADIUS),
|
|
4890
5531
|
surfaceQuaternion2(center),
|
|
4891
|
-
new
|
|
5532
|
+
new import_three13.Vector3(1, 1, 1)
|
|
4892
5533
|
).invert();
|
|
4893
5534
|
}
|
|
4894
5535
|
function subdivisionSteps(vertices) {
|
|
@@ -4903,11 +5544,11 @@ function subdivisionSteps(vertices) {
|
|
|
4903
5544
|
}
|
|
4904
5545
|
return Math.min(
|
|
4905
5546
|
8,
|
|
4906
|
-
Math.max(1, Math.ceil(
|
|
5547
|
+
Math.max(1, Math.ceil(import_three13.MathUtils.radToDeg(maxAngle) / MAX_SEGMENT_DEGREES))
|
|
4907
5548
|
);
|
|
4908
5549
|
}
|
|
4909
5550
|
function makeLinePositions(vertices, center) {
|
|
4910
|
-
const
|
|
5551
|
+
const points = [];
|
|
4911
5552
|
const worldToLocal = makeWorldToLocal2(center);
|
|
4912
5553
|
const unwrapped = unwrapVertices(vertices);
|
|
4913
5554
|
const steps = subdivisionSteps(vertices);
|
|
@@ -4923,35 +5564,13 @@ function makeLinePositions(vertices, center) {
|
|
|
4923
5564
|
},
|
|
4924
5565
|
POLYLINE_RADIUS
|
|
4925
5566
|
).applyMatrix4(worldToLocal);
|
|
4926
|
-
|
|
5567
|
+
points.push([point.x, point.y, point.z]);
|
|
4927
5568
|
}
|
|
4928
5569
|
}
|
|
4929
5570
|
const last = unwrapped[unwrapped.length - 1];
|
|
4930
5571
|
const lastPoint = panoPositionToVector3(last, POLYLINE_RADIUS).applyMatrix4(worldToLocal);
|
|
4931
|
-
|
|
4932
|
-
return
|
|
4933
|
-
}
|
|
4934
|
-
function makeLine(positions, color, width, opacity) {
|
|
4935
|
-
const geometry = new import_LineGeometry2.LineGeometry();
|
|
4936
|
-
geometry.setPositions(positions);
|
|
4937
|
-
const material = new import_LineMaterial2.LineMaterial({
|
|
4938
|
-
color,
|
|
4939
|
-
depthTest: true,
|
|
4940
|
-
depthWrite: false,
|
|
4941
|
-
linewidth: Math.max(0.5, width),
|
|
4942
|
-
opacity,
|
|
4943
|
-
transparent: true,
|
|
4944
|
-
worldUnits: false,
|
|
4945
|
-
alphaToCoverage: true
|
|
4946
|
-
});
|
|
4947
|
-
const line = new import_Line22.Line2(geometry, material);
|
|
4948
|
-
line.computeLineDistances();
|
|
4949
|
-
return line;
|
|
4950
|
-
}
|
|
4951
|
-
function disposeLine(line) {
|
|
4952
|
-
if (!line) return;
|
|
4953
|
-
line.geometry.dispose();
|
|
4954
|
-
line.material.dispose();
|
|
5572
|
+
points.push([lastPoint.x, lastPoint.y, lastPoint.z]);
|
|
5573
|
+
return points;
|
|
4955
5574
|
}
|
|
4956
5575
|
function translateVertices2(vertices, from, to) {
|
|
4957
5576
|
const yawOffset = normalizePanoYaw(to.yaw - from.yaw);
|
|
@@ -4978,39 +5597,19 @@ function PolylineHotspot({
|
|
|
4978
5597
|
onInvalid,
|
|
4979
5598
|
...anchorProps
|
|
4980
5599
|
}) {
|
|
4981
|
-
const
|
|
4982
|
-
const size = (0, import_fiber16.useThree)((state) => state.size);
|
|
4983
|
-
const issues = (0, import_react19.useMemo)(() => validatePolylineVertices(vertices), [vertices]);
|
|
5600
|
+
const issues = (0, import_react22.useMemo)(() => validatePolylineVertices(vertices), [vertices]);
|
|
4984
5601
|
const valid = issues.length === 0;
|
|
4985
|
-
const center = (0,
|
|
4986
|
-
const
|
|
5602
|
+
const center = (0, import_react22.useMemo)(() => valid ? polylineCenter(vertices) : null, [valid, vertices]);
|
|
5603
|
+
const linePoints = (0, import_react22.useMemo)(
|
|
4987
5604
|
() => valid && center ? makeLinePositions(vertices, center) : null,
|
|
4988
5605
|
[center, valid, vertices]
|
|
4989
5606
|
);
|
|
4990
|
-
const devicePixelRatio = gl.getPixelRatio();
|
|
4991
5607
|
const opacity = Math.max(0, Math.min(strokeOpacity, 1));
|
|
4992
|
-
const
|
|
4993
|
-
|
|
4994
|
-
[devicePixelRatio, linePositions, opacity, stroke, strokeWidth]
|
|
4995
|
-
);
|
|
4996
|
-
const focusLine = (0, import_react19.useMemo)(
|
|
4997
|
-
() => linePositions ? makeLine(linePositions, "#75cbd3", (strokeWidth + 2) * devicePixelRatio, 1) : null,
|
|
4998
|
-
[devicePixelRatio, linePositions, strokeWidth]
|
|
4999
|
-
);
|
|
5000
|
-
const startVerticesRef = (0, import_react19.useRef)(null);
|
|
5001
|
-
(0, import_react19.useEffect)(() => {
|
|
5608
|
+
const startVerticesRef = (0, import_react22.useRef)(null);
|
|
5609
|
+
(0, import_react22.useEffect)(() => {
|
|
5002
5610
|
if (!valid) onInvalid?.(issues);
|
|
5003
5611
|
}, [issues, onInvalid, valid]);
|
|
5004
|
-
(
|
|
5005
|
-
(0, import_react19.useEffect)(() => () => disposeLine(focusLine), [focusLine]);
|
|
5006
|
-
(0, import_react19.useEffect)(() => {
|
|
5007
|
-
const width = gl.domElement.width;
|
|
5008
|
-
const height = gl.domElement.height;
|
|
5009
|
-
for (const nextLine of [line, focusLine]) {
|
|
5010
|
-
if (nextLine) nextLine.material.resolution.set(width, height);
|
|
5011
|
-
}
|
|
5012
|
-
}, [focusLine, gl, line, size.height, size.width]);
|
|
5013
|
-
if (!valid || !center || !line || !focusLine) return null;
|
|
5612
|
+
if (!valid || !center || !linePoints || linePoints.length < 2) return null;
|
|
5014
5613
|
const emitVerticesChange = (event, callback) => {
|
|
5015
5614
|
const startVertices = startVerticesRef.current ?? cloneVertices2(vertices);
|
|
5016
5615
|
callback?.({
|
|
@@ -5021,7 +5620,7 @@ function PolylineHotspot({
|
|
|
5021
5620
|
startPosition: event.startPosition
|
|
5022
5621
|
});
|
|
5023
5622
|
};
|
|
5024
|
-
return /* @__PURE__ */ (0,
|
|
5623
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
5025
5624
|
HotspotAnchor,
|
|
5026
5625
|
{
|
|
5027
5626
|
...anchorProps,
|
|
@@ -5035,7 +5634,16 @@ function PolylineHotspot({
|
|
|
5035
5634
|
renderOrder,
|
|
5036
5635
|
draggable,
|
|
5037
5636
|
useAngularScale: false,
|
|
5038
|
-
focusContent: /* @__PURE__ */ (0,
|
|
5637
|
+
focusContent: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
5638
|
+
HotspotStrokeLine,
|
|
5639
|
+
{
|
|
5640
|
+
color: "#75cbd3",
|
|
5641
|
+
lineWidth: strokeWidth + 2,
|
|
5642
|
+
opacity: 1,
|
|
5643
|
+
points: linePoints,
|
|
5644
|
+
renderOrder: renderOrder + 2
|
|
5645
|
+
}
|
|
5646
|
+
),
|
|
5039
5647
|
onDragStart: (event) => {
|
|
5040
5648
|
startVerticesRef.current = cloneVertices2(vertices);
|
|
5041
5649
|
emitVerticesChange(event, onDragStart);
|
|
@@ -5045,22 +5653,25 @@ function PolylineHotspot({
|
|
|
5045
5653
|
emitVerticesChange(event, onDragEnd);
|
|
5046
5654
|
startVerticesRef.current = null;
|
|
5047
5655
|
},
|
|
5048
|
-
children: /* @__PURE__ */ (0,
|
|
5656
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
5657
|
+
HotspotStrokeLine,
|
|
5658
|
+
{
|
|
5659
|
+
color: stroke,
|
|
5660
|
+
lineWidth: strokeWidth,
|
|
5661
|
+
opacity,
|
|
5662
|
+
points: linePoints,
|
|
5663
|
+
renderOrder: renderOrder + 1
|
|
5664
|
+
}
|
|
5665
|
+
)
|
|
5049
5666
|
}
|
|
5050
5667
|
);
|
|
5051
5668
|
}
|
|
5052
5669
|
|
|
5053
5670
|
// src/hotspot/graphic-hotspot.tsx
|
|
5054
|
-
var
|
|
5055
|
-
var
|
|
5056
|
-
var
|
|
5671
|
+
var import_react23 = require("react");
|
|
5672
|
+
var import_three14 = require("three");
|
|
5673
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
5057
5674
|
var GRAPHIC_TEXTURE_SIZE = 512;
|
|
5058
|
-
function clampOpacity2(opacity) {
|
|
5059
|
-
if (!Number.isFinite(opacity)) {
|
|
5060
|
-
return 1;
|
|
5061
|
-
}
|
|
5062
|
-
return Math.max(0, Math.min(opacity, 1));
|
|
5063
|
-
}
|
|
5064
5675
|
function resolveStrokeWidth(value) {
|
|
5065
5676
|
return Number.isFinite(value) ? Math.max(value, 0) : 8;
|
|
5066
5677
|
}
|
|
@@ -5237,23 +5848,23 @@ function createGraphicTexture(graphic, aspectWidth, aspectHeight) {
|
|
|
5237
5848
|
throw new Error("Canvas 2D is unavailable for this graphic hotspot.");
|
|
5238
5849
|
}
|
|
5239
5850
|
drawGraphic(context, graphic, aspectWidth, aspectHeight);
|
|
5240
|
-
const texture = new
|
|
5241
|
-
texture.colorSpace =
|
|
5242
|
-
texture.wrapS =
|
|
5243
|
-
texture.wrapT =
|
|
5244
|
-
texture.magFilter =
|
|
5245
|
-
texture.minFilter =
|
|
5851
|
+
const texture = new import_three14.CanvasTexture(canvas);
|
|
5852
|
+
texture.colorSpace = import_three14.SRGBColorSpace;
|
|
5853
|
+
texture.wrapS = import_three14.ClampToEdgeWrapping;
|
|
5854
|
+
texture.wrapT = import_three14.ClampToEdgeWrapping;
|
|
5855
|
+
texture.magFilter = import_three14.LinearFilter;
|
|
5856
|
+
texture.minFilter = import_three14.LinearMipmapLinearFilter;
|
|
5246
5857
|
texture.generateMipmaps = true;
|
|
5247
5858
|
texture.needsUpdate = true;
|
|
5248
5859
|
return texture;
|
|
5249
5860
|
}
|
|
5250
5861
|
function useGraphicTexture(graphic, aspectWidth, aspectHeight, onLoad, onError) {
|
|
5251
|
-
const [texture, setTexture] = (0,
|
|
5252
|
-
const onLoadRef = (0,
|
|
5253
|
-
const onErrorRef = (0,
|
|
5862
|
+
const [texture, setTexture] = (0, import_react23.useState)(null);
|
|
5863
|
+
const onLoadRef = (0, import_react23.useRef)(onLoad);
|
|
5864
|
+
const onErrorRef = (0, import_react23.useRef)(onError);
|
|
5254
5865
|
onLoadRef.current = onLoad;
|
|
5255
5866
|
onErrorRef.current = onError;
|
|
5256
|
-
(0,
|
|
5867
|
+
(0, import_react23.useEffect)(() => {
|
|
5257
5868
|
let nextTexture = null;
|
|
5258
5869
|
try {
|
|
5259
5870
|
nextTexture = createGraphicTexture(graphic, aspectWidth, aspectHeight);
|
|
@@ -5279,41 +5890,23 @@ function CanvasGraphicHotspot({
|
|
|
5279
5890
|
...anchorProps
|
|
5280
5891
|
}) {
|
|
5281
5892
|
const texture = useGraphicTexture(graphic, width, height, onLoad, onError);
|
|
5282
|
-
return /* @__PURE__ */ (0,
|
|
5283
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("planeGeometry", { args: [1, 1] }),
|
|
5284
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
5285
|
-
"meshBasicMaterial",
|
|
5286
|
-
{
|
|
5287
|
-
map: texture,
|
|
5288
|
-
opacity: texture ? clampOpacity2(opacity) : 0,
|
|
5289
|
-
side: import_three13.DoubleSide,
|
|
5290
|
-
toneMapped: false,
|
|
5291
|
-
transparent: true
|
|
5292
|
-
}
|
|
5293
|
-
)
|
|
5294
|
-
] }) });
|
|
5893
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(HotspotPlane, { map: texture, opacity }) });
|
|
5295
5894
|
}
|
|
5296
5895
|
function GraphicHotspot(props) {
|
|
5297
5896
|
const { graphic, ...restProps } = props;
|
|
5298
5897
|
if (graphic.kind === "svg") {
|
|
5299
5898
|
const imageProps = restProps;
|
|
5300
|
-
return /* @__PURE__ */ (0,
|
|
5899
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(ImageHotspot, { ...imageProps, src: graphic.src });
|
|
5301
5900
|
}
|
|
5302
|
-
return /* @__PURE__ */ (0,
|
|
5901
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(CanvasGraphicHotspot, { ...restProps, graphic });
|
|
5303
5902
|
}
|
|
5304
5903
|
|
|
5305
5904
|
// src/hotspot/sequence-hotspot.tsx
|
|
5306
|
-
var
|
|
5307
|
-
var
|
|
5308
|
-
var
|
|
5309
|
-
var
|
|
5905
|
+
var import_fiber16 = require("@react-three/fiber");
|
|
5906
|
+
var import_react24 = require("react");
|
|
5907
|
+
var import_three15 = require("three");
|
|
5908
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
5310
5909
|
var DEFAULT_SEQUENCE_FPS = 12;
|
|
5311
|
-
function clampOpacity3(opacity) {
|
|
5312
|
-
if (!Number.isFinite(opacity)) {
|
|
5313
|
-
return 1;
|
|
5314
|
-
}
|
|
5315
|
-
return Math.max(0, Math.min(opacity, 1));
|
|
5316
|
-
}
|
|
5317
5910
|
function resolveFps(value) {
|
|
5318
5911
|
return Number.isFinite(value) && value > 0 ? value : DEFAULT_SEQUENCE_FPS;
|
|
5319
5912
|
}
|
|
@@ -5326,13 +5919,13 @@ function useSpriteTexture({
|
|
|
5326
5919
|
onError,
|
|
5327
5920
|
onLoadProgress
|
|
5328
5921
|
}) {
|
|
5329
|
-
const gl = (0,
|
|
5330
|
-
const [texture, setTexture] = (0,
|
|
5331
|
-
const onErrorRef = (0,
|
|
5332
|
-
const onLoadProgressRef = (0,
|
|
5922
|
+
const gl = (0, import_fiber16.useThree)((state) => state.gl);
|
|
5923
|
+
const [texture, setTexture] = (0, import_react24.useState)(null);
|
|
5924
|
+
const onErrorRef = (0, import_react24.useRef)(onError);
|
|
5925
|
+
const onLoadProgressRef = (0, import_react24.useRef)(onLoadProgress);
|
|
5333
5926
|
onErrorRef.current = onError;
|
|
5334
5927
|
onLoadProgressRef.current = onLoadProgress;
|
|
5335
|
-
(0,
|
|
5928
|
+
(0, import_react24.useEffect)(() => {
|
|
5336
5929
|
let active = true;
|
|
5337
5930
|
setTexture(null);
|
|
5338
5931
|
if (!src) {
|
|
@@ -5341,7 +5934,7 @@ function useSpriteTexture({
|
|
|
5341
5934
|
active = false;
|
|
5342
5935
|
};
|
|
5343
5936
|
}
|
|
5344
|
-
const loader = new
|
|
5937
|
+
const loader = new import_three15.TextureLoader();
|
|
5345
5938
|
loader.load(
|
|
5346
5939
|
src,
|
|
5347
5940
|
(loadedTexture) => {
|
|
@@ -5349,11 +5942,11 @@ function useSpriteTexture({
|
|
|
5349
5942
|
loadedTexture.dispose();
|
|
5350
5943
|
return;
|
|
5351
5944
|
}
|
|
5352
|
-
loadedTexture.colorSpace =
|
|
5353
|
-
loadedTexture.wrapS =
|
|
5354
|
-
loadedTexture.wrapT =
|
|
5355
|
-
loadedTexture.magFilter =
|
|
5356
|
-
loadedTexture.minFilter =
|
|
5945
|
+
loadedTexture.colorSpace = import_three15.SRGBColorSpace;
|
|
5946
|
+
loadedTexture.wrapS = import_three15.ClampToEdgeWrapping;
|
|
5947
|
+
loadedTexture.wrapT = import_three15.ClampToEdgeWrapping;
|
|
5948
|
+
loadedTexture.magFilter = import_three15.LinearFilter;
|
|
5949
|
+
loadedTexture.minFilter = import_three15.LinearMipmapLinearFilter;
|
|
5357
5950
|
loadedTexture.generateMipmaps = true;
|
|
5358
5951
|
loadedTexture.anisotropy = gl.capabilities.getMaxAnisotropy();
|
|
5359
5952
|
loadedTexture.needsUpdate = true;
|
|
@@ -5373,7 +5966,7 @@ function useSpriteTexture({
|
|
|
5373
5966
|
active = false;
|
|
5374
5967
|
};
|
|
5375
5968
|
}, [gl, id, src]);
|
|
5376
|
-
(0,
|
|
5969
|
+
(0, import_react24.useEffect)(
|
|
5377
5970
|
() => () => {
|
|
5378
5971
|
texture?.dispose();
|
|
5379
5972
|
},
|
|
@@ -5402,24 +5995,24 @@ function SequenceHotspot({
|
|
|
5402
5995
|
const texture = useSpriteTexture({ id, src, onError, onLoadProgress });
|
|
5403
5996
|
const frameCount = resolveFrameCount(requestedFrameCount);
|
|
5404
5997
|
const safeFps = resolveFps(fps);
|
|
5405
|
-
const [frameIndex, setFrameIndex] = (0,
|
|
5406
|
-
const elapsedRef = (0,
|
|
5407
|
-
const frameIndexRef = (0,
|
|
5408
|
-
const endedRef = (0,
|
|
5409
|
-
const lastPlaybackStateRef = (0,
|
|
5410
|
-
const onFrameChangeRef = (0,
|
|
5411
|
-
const onPlaybackStateChangeRef = (0,
|
|
5412
|
-
const onEndedRef = (0,
|
|
5998
|
+
const [frameIndex, setFrameIndex] = (0, import_react24.useState)(0);
|
|
5999
|
+
const elapsedRef = (0, import_react24.useRef)(0);
|
|
6000
|
+
const frameIndexRef = (0, import_react24.useRef)(0);
|
|
6001
|
+
const endedRef = (0, import_react24.useRef)(false);
|
|
6002
|
+
const lastPlaybackStateRef = (0, import_react24.useRef)(null);
|
|
6003
|
+
const onFrameChangeRef = (0, import_react24.useRef)(onFrameChange);
|
|
6004
|
+
const onPlaybackStateChangeRef = (0, import_react24.useRef)(onPlaybackStateChange);
|
|
6005
|
+
const onEndedRef = (0, import_react24.useRef)(onEnded);
|
|
5413
6006
|
onFrameChangeRef.current = onFrameChange;
|
|
5414
6007
|
onPlaybackStateChangeRef.current = onPlaybackStateChange;
|
|
5415
6008
|
onEndedRef.current = onEnded;
|
|
5416
|
-
(0,
|
|
6009
|
+
(0, import_react24.useEffect)(() => {
|
|
5417
6010
|
elapsedRef.current = 0;
|
|
5418
6011
|
frameIndexRef.current = 0;
|
|
5419
6012
|
endedRef.current = false;
|
|
5420
6013
|
setFrameIndex(0);
|
|
5421
6014
|
}, [frameCount, frameDirection, src]);
|
|
5422
|
-
(0,
|
|
6015
|
+
(0, import_react24.useEffect)(() => {
|
|
5423
6016
|
if (!texture) {
|
|
5424
6017
|
return;
|
|
5425
6018
|
}
|
|
@@ -5433,13 +6026,13 @@ function SequenceHotspot({
|
|
|
5433
6026
|
);
|
|
5434
6027
|
texture.needsUpdate = true;
|
|
5435
6028
|
}, [frameCount, frameDirection, frameIndex, texture]);
|
|
5436
|
-
(0,
|
|
6029
|
+
(0, import_react24.useEffect)(() => {
|
|
5437
6030
|
if (!texture) {
|
|
5438
6031
|
return;
|
|
5439
6032
|
}
|
|
5440
6033
|
onFrameChangeRef.current?.({ id, index: 0, src });
|
|
5441
6034
|
}, [id, src, texture]);
|
|
5442
|
-
(0,
|
|
6035
|
+
(0, import_react24.useEffect)(() => {
|
|
5443
6036
|
if (!texture) {
|
|
5444
6037
|
return;
|
|
5445
6038
|
}
|
|
@@ -5458,7 +6051,7 @@ function SequenceHotspot({
|
|
|
5458
6051
|
onPlaybackStateChangeRef.current?.(nextState);
|
|
5459
6052
|
}
|
|
5460
6053
|
}, [playing, texture]);
|
|
5461
|
-
(0,
|
|
6054
|
+
(0, import_fiber16.useFrame)((_, deltaSeconds) => {
|
|
5462
6055
|
if (!texture || !playing || endedRef.current) {
|
|
5463
6056
|
return;
|
|
5464
6057
|
}
|
|
@@ -5488,32 +6081,14 @@ function SequenceHotspot({
|
|
|
5488
6081
|
onFrameChangeRef.current?.({ id, index: nextIndex, src });
|
|
5489
6082
|
}
|
|
5490
6083
|
});
|
|
5491
|
-
return /* @__PURE__ */ (0,
|
|
5492
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("planeGeometry", { args: [1, 1] }),
|
|
5493
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
5494
|
-
"meshBasicMaterial",
|
|
5495
|
-
{
|
|
5496
|
-
map: texture,
|
|
5497
|
-
opacity: texture ? clampOpacity3(opacity) : 0,
|
|
5498
|
-
side: import_three14.DoubleSide,
|
|
5499
|
-
toneMapped: false,
|
|
5500
|
-
transparent: true
|
|
5501
|
-
}
|
|
5502
|
-
)
|
|
5503
|
-
] }) });
|
|
6084
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(HotspotAnchor, { ...anchorProps, id, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(HotspotPlane, { map: texture, opacity }) });
|
|
5504
6085
|
}
|
|
5505
6086
|
|
|
5506
6087
|
// src/hotspot/video-hotspot.tsx
|
|
5507
|
-
var
|
|
5508
|
-
var
|
|
5509
|
-
var
|
|
5510
|
-
var
|
|
5511
|
-
function clampOpacity4(opacity) {
|
|
5512
|
-
if (!Number.isFinite(opacity)) {
|
|
5513
|
-
return 1;
|
|
5514
|
-
}
|
|
5515
|
-
return Math.max(0, Math.min(opacity, 1));
|
|
5516
|
-
}
|
|
6088
|
+
var import_fiber17 = require("@react-three/fiber");
|
|
6089
|
+
var import_react25 = require("react");
|
|
6090
|
+
var import_three16 = require("three");
|
|
6091
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
5517
6092
|
function clampVolume(volume) {
|
|
5518
6093
|
if (!Number.isFinite(volume)) {
|
|
5519
6094
|
return 1;
|
|
@@ -5521,11 +6096,11 @@ function clampVolume(volume) {
|
|
|
5521
6096
|
return Math.max(0, Math.min(volume, 1));
|
|
5522
6097
|
}
|
|
5523
6098
|
function usePosterTexture(id, poster, onError) {
|
|
5524
|
-
const gl = (0,
|
|
5525
|
-
const [texture, setTexture] = (0,
|
|
5526
|
-
const onErrorRef = (0,
|
|
6099
|
+
const gl = (0, import_fiber17.useThree)((state) => state.gl);
|
|
6100
|
+
const [texture, setTexture] = (0, import_react25.useState)(null);
|
|
6101
|
+
const onErrorRef = (0, import_react25.useRef)(onError);
|
|
5527
6102
|
onErrorRef.current = onError;
|
|
5528
|
-
(0,
|
|
6103
|
+
(0, import_react25.useEffect)(() => {
|
|
5529
6104
|
let active = true;
|
|
5530
6105
|
setTexture(null);
|
|
5531
6106
|
if (!poster) {
|
|
@@ -5533,7 +6108,7 @@ function usePosterTexture(id, poster, onError) {
|
|
|
5533
6108
|
active = false;
|
|
5534
6109
|
};
|
|
5535
6110
|
}
|
|
5536
|
-
const loader = new
|
|
6111
|
+
const loader = new import_three16.TextureLoader();
|
|
5537
6112
|
loader.load(
|
|
5538
6113
|
poster,
|
|
5539
6114
|
(loadedTexture) => {
|
|
@@ -5541,11 +6116,11 @@ function usePosterTexture(id, poster, onError) {
|
|
|
5541
6116
|
loadedTexture.dispose();
|
|
5542
6117
|
return;
|
|
5543
6118
|
}
|
|
5544
|
-
loadedTexture.colorSpace =
|
|
5545
|
-
loadedTexture.wrapS =
|
|
5546
|
-
loadedTexture.wrapT =
|
|
5547
|
-
loadedTexture.magFilter =
|
|
5548
|
-
loadedTexture.minFilter =
|
|
6119
|
+
loadedTexture.colorSpace = import_three16.SRGBColorSpace;
|
|
6120
|
+
loadedTexture.wrapS = import_three16.ClampToEdgeWrapping;
|
|
6121
|
+
loadedTexture.wrapT = import_three16.ClampToEdgeWrapping;
|
|
6122
|
+
loadedTexture.magFilter = import_three16.LinearFilter;
|
|
6123
|
+
loadedTexture.minFilter = import_three16.LinearMipmapLinearFilter;
|
|
5549
6124
|
loadedTexture.generateMipmaps = true;
|
|
5550
6125
|
loadedTexture.anisotropy = gl.capabilities.getMaxAnisotropy();
|
|
5551
6126
|
loadedTexture.needsUpdate = true;
|
|
@@ -5562,7 +6137,7 @@ function usePosterTexture(id, poster, onError) {
|
|
|
5562
6137
|
active = false;
|
|
5563
6138
|
};
|
|
5564
6139
|
}, [gl, id, poster]);
|
|
5565
|
-
(0,
|
|
6140
|
+
(0, import_react25.useEffect)(
|
|
5566
6141
|
() => () => {
|
|
5567
6142
|
texture?.dispose();
|
|
5568
6143
|
},
|
|
@@ -5580,14 +6155,14 @@ function useVideoResource({
|
|
|
5580
6155
|
poster,
|
|
5581
6156
|
src
|
|
5582
6157
|
}) {
|
|
5583
|
-
const [resource, setResource] = (0,
|
|
5584
|
-
const onEndedRef = (0,
|
|
5585
|
-
const onErrorRef = (0,
|
|
5586
|
-
const onPlaybackStateChangeRef = (0,
|
|
6158
|
+
const [resource, setResource] = (0, import_react25.useState)(null);
|
|
6159
|
+
const onEndedRef = (0, import_react25.useRef)(onEnded);
|
|
6160
|
+
const onErrorRef = (0, import_react25.useRef)(onError);
|
|
6161
|
+
const onPlaybackStateChangeRef = (0, import_react25.useRef)(onPlaybackStateChange);
|
|
5587
6162
|
onEndedRef.current = onEnded;
|
|
5588
6163
|
onErrorRef.current = onError;
|
|
5589
6164
|
onPlaybackStateChangeRef.current = onPlaybackStateChange;
|
|
5590
|
-
(0,
|
|
6165
|
+
(0, import_react25.useEffect)(() => {
|
|
5591
6166
|
if (!src) {
|
|
5592
6167
|
setResource(null);
|
|
5593
6168
|
return;
|
|
@@ -5599,12 +6174,12 @@ function useVideoResource({
|
|
|
5599
6174
|
}
|
|
5600
6175
|
video.playsInline = playsInline ?? true;
|
|
5601
6176
|
video.poster = poster ?? "";
|
|
5602
|
-
const texture = new
|
|
5603
|
-
texture.colorSpace =
|
|
5604
|
-
texture.wrapS =
|
|
5605
|
-
texture.wrapT =
|
|
5606
|
-
texture.magFilter =
|
|
5607
|
-
texture.minFilter =
|
|
6177
|
+
const texture = new import_three16.VideoTexture(video);
|
|
6178
|
+
texture.colorSpace = import_three16.SRGBColorSpace;
|
|
6179
|
+
texture.wrapS = import_three16.ClampToEdgeWrapping;
|
|
6180
|
+
texture.wrapT = import_three16.ClampToEdgeWrapping;
|
|
6181
|
+
texture.magFilter = import_three16.LinearFilter;
|
|
6182
|
+
texture.minFilter = import_three16.LinearFilter;
|
|
5608
6183
|
texture.generateMipmaps = false;
|
|
5609
6184
|
const notifyState = (state) => {
|
|
5610
6185
|
if (active) {
|
|
@@ -5688,11 +6263,11 @@ function VideoHotspot({
|
|
|
5688
6263
|
src
|
|
5689
6264
|
});
|
|
5690
6265
|
const posterTexture = usePosterTexture(id, poster, onError);
|
|
5691
|
-
const onPlaybackErrorRef = (0,
|
|
5692
|
-
const onPlaybackStateChangeRef = (0,
|
|
6266
|
+
const onPlaybackErrorRef = (0, import_react25.useRef)(onPlaybackError);
|
|
6267
|
+
const onPlaybackStateChangeRef = (0, import_react25.useRef)(onPlaybackStateChange);
|
|
5693
6268
|
onPlaybackErrorRef.current = onPlaybackError;
|
|
5694
6269
|
onPlaybackStateChangeRef.current = onPlaybackStateChange;
|
|
5695
|
-
(0,
|
|
6270
|
+
(0, import_react25.useEffect)(() => {
|
|
5696
6271
|
if (!resource) {
|
|
5697
6272
|
return;
|
|
5698
6273
|
}
|
|
@@ -5702,7 +6277,7 @@ function VideoHotspot({
|
|
|
5702
6277
|
resource.video.playsInline = playsInline;
|
|
5703
6278
|
resource.video.preload = preload;
|
|
5704
6279
|
}, [loop, muted, playsInline, preload, resource, volume]);
|
|
5705
|
-
(0,
|
|
6280
|
+
(0, import_react25.useEffect)(() => {
|
|
5706
6281
|
if (!resource) {
|
|
5707
6282
|
return;
|
|
5708
6283
|
}
|
|
@@ -5725,24 +6300,405 @@ function VideoHotspot({
|
|
|
5725
6300
|
};
|
|
5726
6301
|
}, [playing, resource]);
|
|
5727
6302
|
const activeTexture = resource?.ready ? resource.texture : posterTexture;
|
|
5728
|
-
return /* @__PURE__ */ (0,
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
6303
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(HotspotAnchor, { ...anchorProps, id, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(HotspotPlane, { map: activeTexture, opacity }) });
|
|
6304
|
+
}
|
|
6305
|
+
|
|
6306
|
+
// src/hotspot/text-hotspot.tsx
|
|
6307
|
+
var import_react26 = require("react");
|
|
6308
|
+
var import_three17 = require("three");
|
|
6309
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
6310
|
+
var TEXT_TEXTURE_LONG_SIDE = 1024;
|
|
6311
|
+
var DEFAULT_FONT_FAMILY = "system-ui, sans-serif";
|
|
6312
|
+
var DEFAULT_COLOR = "#f8fafc";
|
|
6313
|
+
var DEFAULT_BACKGROUND = "#111827";
|
|
6314
|
+
function clamp01(value, fallback) {
|
|
6315
|
+
if (!Number.isFinite(value)) {
|
|
6316
|
+
return fallback;
|
|
6317
|
+
}
|
|
6318
|
+
return Math.max(0, Math.min(value, 1));
|
|
6319
|
+
}
|
|
6320
|
+
function resolvePositive(value, fallback) {
|
|
6321
|
+
return Number.isFinite(value) && value > 0 ? value : fallback;
|
|
6322
|
+
}
|
|
6323
|
+
function resolveCornerRadius2(value) {
|
|
6324
|
+
return Number.isFinite(value) ? Math.max(0, Math.min(value, 0.5)) : 0.08;
|
|
6325
|
+
}
|
|
6326
|
+
function textureSize(width, height) {
|
|
6327
|
+
const safeWidth = resolvePositive(width, 1);
|
|
6328
|
+
const safeHeight = resolvePositive(height, 1);
|
|
6329
|
+
if (safeWidth >= safeHeight) {
|
|
6330
|
+
return {
|
|
6331
|
+
canvasWidth: TEXT_TEXTURE_LONG_SIDE,
|
|
6332
|
+
canvasHeight: Math.max(
|
|
6333
|
+
1,
|
|
6334
|
+
Math.round(TEXT_TEXTURE_LONG_SIDE * (safeHeight / safeWidth))
|
|
6335
|
+
)
|
|
6336
|
+
};
|
|
6337
|
+
}
|
|
6338
|
+
return {
|
|
6339
|
+
canvasWidth: Math.max(
|
|
6340
|
+
1,
|
|
6341
|
+
Math.round(TEXT_TEXTURE_LONG_SIDE * (safeWidth / safeHeight))
|
|
6342
|
+
),
|
|
6343
|
+
canvasHeight: TEXT_TEXTURE_LONG_SIDE
|
|
6344
|
+
};
|
|
6345
|
+
}
|
|
6346
|
+
function roundedRectanglePath2(context, x, y, width, height, radius) {
|
|
6347
|
+
const safeRadius = Math.max(
|
|
6348
|
+
0,
|
|
6349
|
+
Math.min(radius, width / 2, height / 2)
|
|
6350
|
+
);
|
|
6351
|
+
context.beginPath();
|
|
6352
|
+
if (safeRadius <= 0) {
|
|
6353
|
+
context.rect(x, y, width, height);
|
|
6354
|
+
return;
|
|
6355
|
+
}
|
|
6356
|
+
context.moveTo(x + safeRadius, y);
|
|
6357
|
+
context.lineTo(x + width - safeRadius, y);
|
|
6358
|
+
context.quadraticCurveTo(x + width, y, x + width, y + safeRadius);
|
|
6359
|
+
context.lineTo(x + width, y + height - safeRadius);
|
|
6360
|
+
context.quadraticCurveTo(
|
|
6361
|
+
x + width,
|
|
6362
|
+
y + height,
|
|
6363
|
+
x + width - safeRadius,
|
|
6364
|
+
y + height
|
|
6365
|
+
);
|
|
6366
|
+
context.lineTo(x + safeRadius, y + height);
|
|
6367
|
+
context.quadraticCurveTo(x, y + height, x, y + height - safeRadius);
|
|
6368
|
+
context.lineTo(x, y + safeRadius);
|
|
6369
|
+
context.quadraticCurveTo(x, y, x + safeRadius, y);
|
|
6370
|
+
context.closePath();
|
|
6371
|
+
}
|
|
6372
|
+
function wrapLine(context, line, maxWidth) {
|
|
6373
|
+
if (maxWidth <= 0 || context.measureText(line).width <= maxWidth) {
|
|
6374
|
+
return [line];
|
|
6375
|
+
}
|
|
6376
|
+
const lines = [];
|
|
6377
|
+
let current = "";
|
|
6378
|
+
for (const word of line.split(" ")) {
|
|
6379
|
+
const candidate = current ? `${current} ${word}` : word;
|
|
6380
|
+
if (context.measureText(candidate).width <= maxWidth) {
|
|
6381
|
+
current = candidate;
|
|
6382
|
+
continue;
|
|
6383
|
+
}
|
|
6384
|
+
if (current) {
|
|
6385
|
+
lines.push(current);
|
|
6386
|
+
}
|
|
6387
|
+
if (context.measureText(word).width <= maxWidth) {
|
|
6388
|
+
current = word;
|
|
6389
|
+
continue;
|
|
6390
|
+
}
|
|
6391
|
+
let chunk = "";
|
|
6392
|
+
for (const character of word) {
|
|
6393
|
+
const nextChunk = chunk + character;
|
|
6394
|
+
if (context.measureText(nextChunk).width <= maxWidth || chunk === "") {
|
|
6395
|
+
chunk = nextChunk;
|
|
6396
|
+
} else {
|
|
6397
|
+
lines.push(chunk);
|
|
6398
|
+
chunk = character;
|
|
6399
|
+
}
|
|
6400
|
+
}
|
|
6401
|
+
current = chunk;
|
|
6402
|
+
}
|
|
6403
|
+
if (current) {
|
|
6404
|
+
lines.push(current);
|
|
6405
|
+
}
|
|
6406
|
+
return lines.length > 0 ? lines : [""];
|
|
6407
|
+
}
|
|
6408
|
+
function wrapText(context, text, maxWidth, nowrap) {
|
|
6409
|
+
const paragraphs = text.split("\n");
|
|
6410
|
+
if (nowrap) {
|
|
6411
|
+
return paragraphs;
|
|
6412
|
+
}
|
|
6413
|
+
return paragraphs.flatMap((paragraph) => wrapLine(context, paragraph, maxWidth));
|
|
6414
|
+
}
|
|
6415
|
+
function drawTextHotspot(context, canvasWidth, canvasHeight, text, style) {
|
|
6416
|
+
const shortSide = Math.min(canvasWidth, canvasHeight);
|
|
6417
|
+
const padding = clamp01(style.padding, 0.08) * shortSide;
|
|
6418
|
+
const fontSize = Math.max(1, clamp01(style.fontSize, 0.18) * canvasHeight);
|
|
6419
|
+
const lineHeight = resolvePositive(style.lineHeight, 1.25) * fontSize;
|
|
6420
|
+
const align = style.align ?? "center";
|
|
6421
|
+
const verticalAlign = style.verticalAlign ?? "middle";
|
|
6422
|
+
const fontFamily = style.fontFamily?.trim() || DEFAULT_FONT_FAMILY;
|
|
6423
|
+
const fontWeight = style.fontWeight ?? 600;
|
|
6424
|
+
const fontStyle = style.fontStyle ?? "normal";
|
|
6425
|
+
const contentWidth = Math.max(1, canvasWidth - padding * 2);
|
|
6426
|
+
const contentHeight = Math.max(1, canvasHeight - padding * 2);
|
|
6427
|
+
context.clearRect(0, 0, canvasWidth, canvasHeight);
|
|
6428
|
+
const background = style.background ?? DEFAULT_BACKGROUND;
|
|
6429
|
+
if (background !== "") {
|
|
6430
|
+
roundedRectanglePath2(
|
|
6431
|
+
context,
|
|
6432
|
+
0,
|
|
6433
|
+
0,
|
|
6434
|
+
canvasWidth,
|
|
6435
|
+
canvasHeight,
|
|
6436
|
+
resolveCornerRadius2(style.borderRadius) * shortSide
|
|
6437
|
+
);
|
|
6438
|
+
context.save();
|
|
6439
|
+
context.globalAlpha = clamp01(style.backgroundOpacity, 0.72);
|
|
6440
|
+
context.fillStyle = background;
|
|
6441
|
+
context.fill();
|
|
6442
|
+
context.restore();
|
|
6443
|
+
}
|
|
6444
|
+
context.font = `${fontStyle} ${fontWeight} ${fontSize}px ${fontFamily}`;
|
|
6445
|
+
context.textAlign = align;
|
|
6446
|
+
context.textBaseline = "top";
|
|
6447
|
+
const lines = wrapText(
|
|
6448
|
+
context,
|
|
6449
|
+
text,
|
|
6450
|
+
contentWidth,
|
|
6451
|
+
(style.whiteSpace ?? "normal") === "nowrap"
|
|
6452
|
+
);
|
|
6453
|
+
const maxLines = Math.max(1, Math.floor(contentHeight / lineHeight));
|
|
6454
|
+
const visibleLines = lines.slice(0, maxLines);
|
|
6455
|
+
const blockHeight = visibleLines.length * lineHeight;
|
|
6456
|
+
let startY = padding;
|
|
6457
|
+
if (verticalAlign === "middle") {
|
|
6458
|
+
startY = padding + Math.max(0, (contentHeight - blockHeight) / 2);
|
|
6459
|
+
} else if (verticalAlign === "bottom") {
|
|
6460
|
+
startY = padding + Math.max(0, contentHeight - blockHeight);
|
|
6461
|
+
}
|
|
6462
|
+
const startX = align === "left" ? padding : align === "right" ? canvasWidth - padding : canvasWidth / 2;
|
|
6463
|
+
const color = style.color?.trim() || DEFAULT_COLOR;
|
|
6464
|
+
const strokeWidth = Number.isFinite(style.strokeWidth) ? Math.max(style.strokeWidth, 0) : 0;
|
|
6465
|
+
context.save();
|
|
6466
|
+
context.beginPath();
|
|
6467
|
+
context.rect(padding, padding, contentWidth, contentHeight);
|
|
6468
|
+
context.clip();
|
|
6469
|
+
visibleLines.forEach((line, index) => {
|
|
6470
|
+
const y = startY + index * lineHeight;
|
|
6471
|
+
if (style.stroke && strokeWidth > 0) {
|
|
6472
|
+
context.lineWidth = strokeWidth;
|
|
6473
|
+
context.strokeStyle = style.stroke;
|
|
6474
|
+
context.lineJoin = "round";
|
|
6475
|
+
context.miterLimit = 2;
|
|
6476
|
+
context.strokeText(line, startX, y);
|
|
6477
|
+
}
|
|
6478
|
+
context.fillStyle = color;
|
|
6479
|
+
context.fillText(line, startX, y);
|
|
6480
|
+
});
|
|
6481
|
+
context.restore();
|
|
6482
|
+
}
|
|
6483
|
+
function createTextTexture(text, width, height, style) {
|
|
6484
|
+
const { canvasWidth, canvasHeight } = textureSize(width, height);
|
|
6485
|
+
const canvas = document.createElement("canvas");
|
|
6486
|
+
canvas.width = canvasWidth;
|
|
6487
|
+
canvas.height = canvasHeight;
|
|
6488
|
+
const context = canvas.getContext("2d");
|
|
6489
|
+
if (!context) {
|
|
6490
|
+
throw new Error("Canvas 2D is unavailable for this text hotspot.");
|
|
6491
|
+
}
|
|
6492
|
+
drawTextHotspot(context, canvasWidth, canvasHeight, text, style);
|
|
6493
|
+
const texture = new import_three17.CanvasTexture(canvas);
|
|
6494
|
+
texture.colorSpace = import_three17.SRGBColorSpace;
|
|
6495
|
+
texture.wrapS = import_three17.ClampToEdgeWrapping;
|
|
6496
|
+
texture.wrapT = import_three17.ClampToEdgeWrapping;
|
|
6497
|
+
texture.magFilter = import_three17.LinearFilter;
|
|
6498
|
+
texture.minFilter = import_three17.LinearMipmapLinearFilter;
|
|
6499
|
+
texture.generateMipmaps = true;
|
|
6500
|
+
texture.needsUpdate = true;
|
|
6501
|
+
return texture;
|
|
6502
|
+
}
|
|
6503
|
+
function useTextTexture(text, width, height, style, onLoad, onError) {
|
|
6504
|
+
const [texture, setTexture] = (0, import_react26.useState)(null);
|
|
6505
|
+
const onLoadRef = (0, import_react26.useRef)(onLoad);
|
|
6506
|
+
const onErrorRef = (0, import_react26.useRef)(onError);
|
|
6507
|
+
onLoadRef.current = onLoad;
|
|
6508
|
+
onErrorRef.current = onError;
|
|
6509
|
+
(0, import_react26.useEffect)(() => {
|
|
6510
|
+
let nextTexture = null;
|
|
6511
|
+
try {
|
|
6512
|
+
nextTexture = createTextTexture(text, width, height, style);
|
|
6513
|
+
setTexture(nextTexture);
|
|
6514
|
+
onLoadRef.current?.(nextTexture);
|
|
6515
|
+
} catch (error) {
|
|
6516
|
+
setTexture(null);
|
|
6517
|
+
onErrorRef.current?.(error);
|
|
6518
|
+
}
|
|
6519
|
+
return () => {
|
|
6520
|
+
nextTexture?.dispose();
|
|
6521
|
+
};
|
|
6522
|
+
}, [
|
|
6523
|
+
height,
|
|
6524
|
+
style.align,
|
|
6525
|
+
style.background,
|
|
6526
|
+
style.backgroundOpacity,
|
|
6527
|
+
style.borderRadius,
|
|
6528
|
+
style.color,
|
|
6529
|
+
style.fontFamily,
|
|
6530
|
+
style.fontSize,
|
|
6531
|
+
style.fontStyle,
|
|
6532
|
+
style.fontWeight,
|
|
6533
|
+
style.lineHeight,
|
|
6534
|
+
style.padding,
|
|
6535
|
+
style.stroke,
|
|
6536
|
+
style.strokeWidth,
|
|
6537
|
+
style.verticalAlign,
|
|
6538
|
+
style.whiteSpace,
|
|
6539
|
+
text,
|
|
6540
|
+
width
|
|
6541
|
+
]);
|
|
6542
|
+
return texture;
|
|
6543
|
+
}
|
|
6544
|
+
function TextHotspot({
|
|
6545
|
+
text,
|
|
6546
|
+
width = 16,
|
|
6547
|
+
height = 6,
|
|
6548
|
+
opacity,
|
|
6549
|
+
fontFamily,
|
|
6550
|
+
fontSize,
|
|
6551
|
+
fontWeight,
|
|
6552
|
+
fontStyle,
|
|
6553
|
+
color,
|
|
6554
|
+
background,
|
|
6555
|
+
backgroundOpacity,
|
|
6556
|
+
padding,
|
|
6557
|
+
align,
|
|
6558
|
+
verticalAlign,
|
|
6559
|
+
lineHeight,
|
|
6560
|
+
whiteSpace,
|
|
6561
|
+
borderRadius,
|
|
6562
|
+
stroke,
|
|
6563
|
+
strokeWidth,
|
|
6564
|
+
onLoad,
|
|
6565
|
+
onError,
|
|
6566
|
+
...anchorProps
|
|
6567
|
+
}) {
|
|
6568
|
+
const style = {
|
|
6569
|
+
align,
|
|
6570
|
+
background,
|
|
6571
|
+
backgroundOpacity,
|
|
6572
|
+
borderRadius,
|
|
6573
|
+
color,
|
|
6574
|
+
fontFamily,
|
|
6575
|
+
fontSize,
|
|
6576
|
+
fontStyle,
|
|
6577
|
+
fontWeight,
|
|
6578
|
+
lineHeight,
|
|
6579
|
+
padding,
|
|
6580
|
+
stroke,
|
|
6581
|
+
strokeWidth,
|
|
6582
|
+
verticalAlign,
|
|
6583
|
+
whiteSpace
|
|
6584
|
+
};
|
|
6585
|
+
const texture = useTextTexture(text, width, height, style, onLoad, onError);
|
|
6586
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(HotspotPlane, { map: texture, opacity }) });
|
|
6587
|
+
}
|
|
6588
|
+
|
|
6589
|
+
// src/hotspot/iframe-hotspot.tsx
|
|
6590
|
+
var import_drei3 = require("@react-three/drei");
|
|
6591
|
+
var import_three18 = require("three");
|
|
6592
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
6593
|
+
var IFRAME_LONG_SIDE = 800;
|
|
6594
|
+
var CSS3D_DISTANCE_FACTOR = 400;
|
|
6595
|
+
var DEFAULT_SANDBOX = "allow-scripts allow-popups allow-forms";
|
|
6596
|
+
function clampOpacity2(opacity) {
|
|
6597
|
+
if (!Number.isFinite(opacity)) {
|
|
6598
|
+
return 1;
|
|
6599
|
+
}
|
|
6600
|
+
return Math.max(0, Math.min(opacity, 1));
|
|
6601
|
+
}
|
|
6602
|
+
function resolvePositive2(value, fallback) {
|
|
6603
|
+
return Number.isFinite(value) && value > 0 ? value : fallback;
|
|
6604
|
+
}
|
|
6605
|
+
function iframeCssSize(width, height) {
|
|
6606
|
+
const safeWidth = resolvePositive2(width, 1);
|
|
6607
|
+
const safeHeight = resolvePositive2(height, 1);
|
|
6608
|
+
if (safeWidth >= safeHeight) {
|
|
6609
|
+
return {
|
|
6610
|
+
cssWidth: IFRAME_LONG_SIDE,
|
|
6611
|
+
cssHeight: Math.max(
|
|
6612
|
+
1,
|
|
6613
|
+
Math.round(IFRAME_LONG_SIDE * (safeHeight / safeWidth))
|
|
6614
|
+
)
|
|
6615
|
+
};
|
|
6616
|
+
}
|
|
6617
|
+
return {
|
|
6618
|
+
cssWidth: Math.max(
|
|
6619
|
+
1,
|
|
6620
|
+
Math.round(IFRAME_LONG_SIDE * (safeWidth / safeHeight))
|
|
6621
|
+
),
|
|
6622
|
+
cssHeight: IFRAME_LONG_SIDE
|
|
6623
|
+
};
|
|
6624
|
+
}
|
|
6625
|
+
function IframeHotspot({
|
|
6626
|
+
src,
|
|
6627
|
+
title,
|
|
6628
|
+
sandbox = DEFAULT_SANDBOX,
|
|
6629
|
+
allow,
|
|
6630
|
+
referrerPolicy = "strict-origin-when-cross-origin",
|
|
6631
|
+
loading,
|
|
6632
|
+
pointerPolicy = "hotspot",
|
|
6633
|
+
background,
|
|
6634
|
+
opacity,
|
|
6635
|
+
width = 18,
|
|
6636
|
+
height = 12,
|
|
6637
|
+
onLoad,
|
|
6638
|
+
onError,
|
|
6639
|
+
...anchorProps
|
|
6640
|
+
}) {
|
|
6641
|
+
const { cssWidth, cssHeight } = iframeCssSize(width, height);
|
|
6642
|
+
const iframeTitle = title ?? anchorProps.ariaLabel;
|
|
6643
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(HotspotAnchor, { ...anchorProps, height, width, children: [
|
|
6644
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("mesh", { children: [
|
|
6645
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("planeGeometry", { args: [1, 1] }),
|
|
6646
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6647
|
+
"meshBasicMaterial",
|
|
6648
|
+
{
|
|
6649
|
+
depthWrite: false,
|
|
6650
|
+
opacity: 0,
|
|
6651
|
+
side: import_three18.DoubleSide,
|
|
6652
|
+
toneMapped: false,
|
|
6653
|
+
transparent: true
|
|
6654
|
+
}
|
|
6655
|
+
)
|
|
6656
|
+
] }),
|
|
6657
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6658
|
+
import_drei3.Html,
|
|
5732
6659
|
{
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
6660
|
+
distanceFactor: CSS3D_DISTANCE_FACTOR,
|
|
6661
|
+
pointerEvents: pointerPolicy === "content" ? "auto" : "none",
|
|
6662
|
+
scale: [1 / cssWidth, 1 / cssHeight, 1],
|
|
6663
|
+
style: {
|
|
6664
|
+
background: background ?? "transparent",
|
|
6665
|
+
height: cssHeight,
|
|
6666
|
+
opacity: clampOpacity2(opacity),
|
|
6667
|
+
overflow: "hidden",
|
|
6668
|
+
width: cssWidth
|
|
6669
|
+
},
|
|
6670
|
+
transform: true,
|
|
6671
|
+
zIndexRange: [10, 0],
|
|
6672
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6673
|
+
"iframe",
|
|
6674
|
+
{
|
|
6675
|
+
allow,
|
|
6676
|
+
loading,
|
|
6677
|
+
onError: (event) => onError?.(event.nativeEvent),
|
|
6678
|
+
onLoad,
|
|
6679
|
+
referrerPolicy,
|
|
6680
|
+
sandbox,
|
|
6681
|
+
src,
|
|
6682
|
+
style: {
|
|
6683
|
+
border: 0,
|
|
6684
|
+
display: "block",
|
|
6685
|
+
height: "100%",
|
|
6686
|
+
width: "100%"
|
|
6687
|
+
},
|
|
6688
|
+
title: iframeTitle
|
|
6689
|
+
}
|
|
6690
|
+
)
|
|
5738
6691
|
}
|
|
5739
6692
|
)
|
|
5740
|
-
] })
|
|
6693
|
+
] });
|
|
5741
6694
|
}
|
|
5742
6695
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5743
6696
|
0 && (module.exports = {
|
|
5744
6697
|
AutoRotate,
|
|
6698
|
+
DEFAULT_HOTSPOT_TOOLTIP_OFFSET,
|
|
6699
|
+
DEFAULT_PANO_CURSORS,
|
|
5745
6700
|
GraphicHotspot,
|
|
6701
|
+
IframeHotspot,
|
|
5746
6702
|
ImageHotspot,
|
|
5747
6703
|
KeyboardControls,
|
|
5748
6704
|
MAX_HOTSPOT_PITCH,
|
|
@@ -5750,12 +6706,13 @@ function VideoHotspot({
|
|
|
5750
6706
|
MouseControls,
|
|
5751
6707
|
PanoContextMenu,
|
|
5752
6708
|
PanoEvents,
|
|
5753
|
-
|
|
5754
|
-
PanoramaScenes,
|
|
6709
|
+
PanoViewer,
|
|
5755
6710
|
PolygonHotspot,
|
|
5756
6711
|
PolylineHotspot,
|
|
6712
|
+
Scenes,
|
|
5757
6713
|
SequenceHotspot,
|
|
5758
6714
|
Sphere,
|
|
6715
|
+
TextHotspot,
|
|
5759
6716
|
Tile,
|
|
5760
6717
|
TouchControls,
|
|
5761
6718
|
VideoHotspot,
|