worldorbit 3.0.5 → 3.0.7
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 +2 -2
- package/dist/browser/viewer/dist/embed.js +86 -13
- package/dist/browser/viewer/dist/runtime-3d.js +396 -117
- package/dist/browser/viewer/dist/theme.js +27 -0
- package/dist/browser/viewer/dist/types.d.ts +17 -0
- package/dist/browser/viewer/dist/viewer.js +268 -12
- package/dist/unpkg/viewer/dist/embed.js +86 -13
- package/dist/unpkg/viewer/dist/runtime-3d.js +396 -117
- package/dist/unpkg/viewer/dist/theme.js +27 -0
- package/dist/unpkg/viewer/dist/types.d.ts +17 -0
- package/dist/unpkg/viewer/dist/viewer.js +268 -12
- package/dist/unpkg/worldorbit-editor.min.js +368 -314
- package/dist/unpkg/worldorbit-markdown.min.js +13 -13
- package/dist/unpkg/worldorbit-viewer.min.js +272 -218
- package/dist/unpkg/worldorbit.js +735 -127
- package/dist/unpkg/worldorbit.min.js +265 -211
- package/package.json +1 -1
- package/packages/viewer/dist/embed.js +86 -13
- package/packages/viewer/dist/runtime-3d.js +396 -117
- package/packages/viewer/dist/theme.js +27 -0
- package/packages/viewer/dist/types.d.ts +17 -0
- package/packages/viewer/dist/viewer.js +268 -12
|
@@ -30,6 +30,15 @@ const THEME_PRESETS = {
|
|
|
30
30
|
starCore: "#ffcc67",
|
|
31
31
|
starStroke: "rgba(255, 245, 203, 0.85)",
|
|
32
32
|
starGlow: "#ffe8a3",
|
|
33
|
+
spaceFog: "#07131d",
|
|
34
|
+
starfield: "rgba(226, 239, 255, 0.9)",
|
|
35
|
+
starfieldDim: "rgba(164, 194, 228, 0.45)",
|
|
36
|
+
objectSpecular: "#f5f8ff",
|
|
37
|
+
orbitOpacity: 0.34,
|
|
38
|
+
orbitBandOpacity: 0.24,
|
|
39
|
+
selectionHalo: "rgba(255, 214, 139, 0.9)",
|
|
40
|
+
atmosphere: "rgba(143, 202, 255, 0.4)",
|
|
41
|
+
cometTail: "rgba(193, 243, 255, 0.7)",
|
|
33
42
|
fontFamily: "\"Segoe UI Variable\", \"Bahnschrift\", sans-serif",
|
|
34
43
|
displayFont: "\"Bahnschrift\", \"Segoe UI Variable\", sans-serif"
|
|
35
44
|
},
|
|
@@ -53,6 +62,15 @@ const THEME_PRESETS = {
|
|
|
53
62
|
starCore: "#e5f98c",
|
|
54
63
|
starStroke: "rgba(246, 255, 217, 0.9)",
|
|
55
64
|
starGlow: "#fffab4",
|
|
65
|
+
spaceFog: "#071723",
|
|
66
|
+
starfield: "rgba(220, 255, 245, 0.9)",
|
|
67
|
+
starfieldDim: "rgba(124, 212, 195, 0.42)",
|
|
68
|
+
objectSpecular: "#ecfffb",
|
|
69
|
+
orbitOpacity: 0.3,
|
|
70
|
+
orbitBandOpacity: 0.22,
|
|
71
|
+
selectionHalo: "rgba(120, 255, 215, 0.85)",
|
|
72
|
+
atmosphere: "rgba(120, 255, 215, 0.32)",
|
|
73
|
+
cometTail: "rgba(181, 255, 236, 0.68)",
|
|
56
74
|
fontFamily: "\"Segoe UI Variable\", \"Bahnschrift\", sans-serif",
|
|
57
75
|
displayFont: "\"Bahnschrift\", \"Segoe UI Variable\", sans-serif"
|
|
58
76
|
},
|
|
@@ -76,6 +94,15 @@ const THEME_PRESETS = {
|
|
|
76
94
|
starCore: "#ffb766",
|
|
77
95
|
starStroke: "rgba(255, 236, 205, 0.88)",
|
|
78
96
|
starGlow: "#ffe2ad",
|
|
97
|
+
spaceFog: "#1c0d12",
|
|
98
|
+
starfield: "rgba(255, 232, 214, 0.88)",
|
|
99
|
+
starfieldDim: "rgba(255, 176, 138, 0.38)",
|
|
100
|
+
objectSpecular: "#fff0e6",
|
|
101
|
+
orbitOpacity: 0.3,
|
|
102
|
+
orbitBandOpacity: 0.24,
|
|
103
|
+
selectionHalo: "rgba(255, 178, 125, 0.85)",
|
|
104
|
+
atmosphere: "rgba(255, 190, 140, 0.26)",
|
|
105
|
+
cometTail: "rgba(255, 214, 173, 0.62)",
|
|
79
106
|
fontFamily: "\"Segoe UI Variable\", \"Bahnschrift\", sans-serif",
|
|
80
107
|
displayFont: "\"Bahnschrift\", \"Segoe UI Variable\", sans-serif"
|
|
81
108
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { CoordinatePoint, RenderOrbitVisual, RenderProjectionFallback, RenderPresetName, RenderSceneEvent, RenderSceneGroup, RenderSceneLabel, RenderScaleModel, RenderScene, RenderSceneObject, RenderSceneViewpoint, SceneRenderOptions, SpatialScene, ViewProjection, WorldOrbitObject, WorldOrbitDocument, WorldOrbitViewCamera } from "@worldorbit/core";
|
|
2
2
|
export type WorldOrbitThemeName = "atlas" | "nightglass" | "ember";
|
|
3
3
|
export type WorldOrbitViewMode = "2d" | "3d";
|
|
4
|
+
export type WorldOrbit3DQuality = "low" | "balanced" | "high";
|
|
5
|
+
export type WorldOrbit3DStyle = "symbolic" | "cinematic";
|
|
4
6
|
export type WorldOrbitEmbedMode = "static" | "interactive" | "interactive-2d" | "interactive-3d";
|
|
5
7
|
export type TooltipMode = "hover" | "pinned" | "disabled";
|
|
6
8
|
export interface WorldOrbitTheme {
|
|
@@ -23,6 +25,15 @@ export interface WorldOrbitTheme {
|
|
|
23
25
|
starCore: string;
|
|
24
26
|
starStroke: string;
|
|
25
27
|
starGlow: string;
|
|
28
|
+
spaceFog: string;
|
|
29
|
+
starfield: string;
|
|
30
|
+
starfieldDim: string;
|
|
31
|
+
objectSpecular: string;
|
|
32
|
+
orbitOpacity: number;
|
|
33
|
+
orbitBandOpacity: number;
|
|
34
|
+
selectionHalo: string;
|
|
35
|
+
atmosphere: string;
|
|
36
|
+
cometTail: string;
|
|
26
37
|
fontFamily: string;
|
|
27
38
|
displayFont: string;
|
|
28
39
|
}
|
|
@@ -64,6 +75,8 @@ export interface ViewerRenderOptions extends Omit<SvgRenderOptions, "selectedObj
|
|
|
64
75
|
projection?: "document" | ViewProjection;
|
|
65
76
|
scaleModel?: Partial<RenderScaleModel>;
|
|
66
77
|
viewMode?: WorldOrbitViewMode;
|
|
78
|
+
quality?: WorldOrbit3DQuality;
|
|
79
|
+
style3d?: WorldOrbit3DStyle;
|
|
67
80
|
}
|
|
68
81
|
export interface ViewerState {
|
|
69
82
|
scale: number;
|
|
@@ -118,6 +131,8 @@ export interface ViewerAtlasState {
|
|
|
118
131
|
scaleModel?: Partial<RenderScaleModel>;
|
|
119
132
|
activeEventId?: string | null;
|
|
120
133
|
viewMode?: WorldOrbitViewMode;
|
|
134
|
+
quality?: WorldOrbit3DQuality;
|
|
135
|
+
style3d?: WorldOrbit3DStyle;
|
|
121
136
|
};
|
|
122
137
|
filter: ViewerFilter | null;
|
|
123
138
|
}
|
|
@@ -274,6 +289,8 @@ export interface WorldOrbitEmbedPayload {
|
|
|
274
289
|
subtitle?: string;
|
|
275
290
|
preset?: SceneRenderOptions["preset"];
|
|
276
291
|
viewMode?: WorldOrbitViewMode;
|
|
292
|
+
quality?: WorldOrbit3DQuality;
|
|
293
|
+
style3d?: WorldOrbit3DStyle;
|
|
277
294
|
initialViewpointId?: string;
|
|
278
295
|
initialSelectionObjectId?: string;
|
|
279
296
|
initialFilter?: ViewerFilter | null;
|
|
@@ -45,6 +45,8 @@ export function createInteractiveViewer(container, options) {
|
|
|
45
45
|
preset: options.preset,
|
|
46
46
|
projection: options.projection,
|
|
47
47
|
viewMode: options.viewMode ?? "2d",
|
|
48
|
+
quality: options.quality ?? "balanced",
|
|
49
|
+
style3d: options.style3d ?? "symbolic",
|
|
48
50
|
camera: options.camera ? { ...options.camera } : null,
|
|
49
51
|
scaleModel: options.scaleModel ? { ...options.scaleModel } : undefined,
|
|
50
52
|
theme: options.theme,
|
|
@@ -66,6 +68,7 @@ export function createInteractiveViewer(container, options) {
|
|
|
66
68
|
let cameraRoot = null;
|
|
67
69
|
let runtime3d = null;
|
|
68
70
|
let minimapRoot = null;
|
|
71
|
+
let labelRoot = null;
|
|
69
72
|
let tooltipRoot = null;
|
|
70
73
|
let suppressClick = false;
|
|
71
74
|
let activePointerId = null;
|
|
@@ -90,7 +93,7 @@ export function createInteractiveViewer(container, options) {
|
|
|
90
93
|
if (previousTabIndex === null) {
|
|
91
94
|
container.tabIndex = 0;
|
|
92
95
|
}
|
|
93
|
-
|
|
96
|
+
installViewerOverlayStyles();
|
|
94
97
|
container.classList.add("wo-viewer-container");
|
|
95
98
|
container.style.touchAction = behavior.touch ? "none" : previousTouchAction;
|
|
96
99
|
if (!container.style.position) {
|
|
@@ -671,6 +674,8 @@ export function createInteractiveViewer(container, options) {
|
|
|
671
674
|
stopAnimationLoop();
|
|
672
675
|
runtime3d?.destroy();
|
|
673
676
|
runtime3d = null;
|
|
677
|
+
labelRoot?.remove();
|
|
678
|
+
labelRoot = null;
|
|
674
679
|
tooltipRoot?.remove();
|
|
675
680
|
tooltipRoot = null;
|
|
676
681
|
minimapRoot?.remove();
|
|
@@ -704,6 +709,7 @@ export function createInteractiveViewer(container, options) {
|
|
|
704
709
|
svgElement = null;
|
|
705
710
|
cameraRoot = null;
|
|
706
711
|
minimapRoot = null;
|
|
712
|
+
labelRoot = null;
|
|
707
713
|
tooltipRoot = null;
|
|
708
714
|
if (is3DView()) {
|
|
709
715
|
spatialScene = spatialScene ?? renderSpatialSceneFromInput(currentInput, renderOptions, providedSpatialScene);
|
|
@@ -723,6 +729,10 @@ export function createInteractiveViewer(container, options) {
|
|
|
723
729
|
minimapRoot.dataset.worldorbitMinimapRoot = "true";
|
|
724
730
|
container.append(minimapRoot);
|
|
725
731
|
}
|
|
732
|
+
labelRoot = document.createElement("div");
|
|
733
|
+
labelRoot.className = "wo-viewer-label-root";
|
|
734
|
+
labelRoot.dataset.worldorbitLabelRoot = "true";
|
|
735
|
+
container.append(labelRoot);
|
|
726
736
|
if (behavior.tooltipMode !== "disabled") {
|
|
727
737
|
tooltipRoot = document.createElement("div");
|
|
728
738
|
tooltipRoot.className = "wo-viewer-tooltip-root";
|
|
@@ -734,6 +744,7 @@ export function createInteractiveViewer(container, options) {
|
|
|
734
744
|
if (!is3DView() && (!svgElement || !cameraRoot)) {
|
|
735
745
|
throw new Error("Interactive viewer could not locate the rendered SVG camera root.");
|
|
736
746
|
}
|
|
747
|
+
suppressStaticLabelLayers();
|
|
737
748
|
state = resetView
|
|
738
749
|
? is3DView()
|
|
739
750
|
? { ...DEFAULT_VIEWER_STATE }
|
|
@@ -783,14 +794,15 @@ export function createInteractiveViewer(container, options) {
|
|
|
783
794
|
return;
|
|
784
795
|
}
|
|
785
796
|
cameraRoot.setAttribute("transform", composeViewerTransform(scene, state));
|
|
797
|
+
updateScreenLabels();
|
|
786
798
|
updateMinimap();
|
|
787
799
|
updateTooltip();
|
|
788
800
|
}
|
|
789
801
|
function applySelection(objectId, emitCallback = true) {
|
|
790
802
|
if (!is3DView() && state.selectedObjectId) {
|
|
791
|
-
container
|
|
792
|
-
.
|
|
793
|
-
|
|
803
|
+
for (const element of container.querySelectorAll(`[data-object-id="${cssEscape(state.selectedObjectId)}"]`)) {
|
|
804
|
+
element.classList.remove("wo-object-selected");
|
|
805
|
+
}
|
|
794
806
|
}
|
|
795
807
|
state = {
|
|
796
808
|
...state,
|
|
@@ -799,9 +811,9 @@ export function createInteractiveViewer(container, options) {
|
|
|
799
811
|
: null,
|
|
800
812
|
};
|
|
801
813
|
if (!is3DView() && state.selectedObjectId) {
|
|
802
|
-
container
|
|
803
|
-
.
|
|
804
|
-
|
|
814
|
+
for (const element of container.querySelectorAll(`[data-object-id="${cssEscape(state.selectedObjectId)}"]`)) {
|
|
815
|
+
element.classList.add("wo-object-selected");
|
|
816
|
+
}
|
|
805
817
|
}
|
|
806
818
|
syncAtlasHighlights();
|
|
807
819
|
updateTooltip();
|
|
@@ -1160,15 +1172,18 @@ export function createInteractiveViewer(container, options) {
|
|
|
1160
1172
|
};
|
|
1161
1173
|
}
|
|
1162
1174
|
function project2DTooltipPoint(renderObject) {
|
|
1163
|
-
if (!svgElement) {
|
|
1164
|
-
return null;
|
|
1165
|
-
}
|
|
1166
1175
|
const anchor = {
|
|
1167
1176
|
x: renderObject.anchorX ?? renderObject.x,
|
|
1168
1177
|
y: renderObject.anchorY ??
|
|
1169
1178
|
renderObject.y - Math.max(renderObject.visualRadius, renderObject.radius),
|
|
1170
1179
|
};
|
|
1171
|
-
|
|
1180
|
+
return project2DScenePointToContainer(anchor);
|
|
1181
|
+
}
|
|
1182
|
+
function project2DScenePointToContainer(point) {
|
|
1183
|
+
if (!svgElement) {
|
|
1184
|
+
return null;
|
|
1185
|
+
}
|
|
1186
|
+
const viewportPoint = projectWorldPoint(point);
|
|
1172
1187
|
const svgRect = svgElement.getBoundingClientRect();
|
|
1173
1188
|
const containerRect = container.getBoundingClientRect();
|
|
1174
1189
|
return {
|
|
@@ -1274,9 +1289,192 @@ export function createInteractiveViewer(container, options) {
|
|
|
1274
1289
|
state,
|
|
1275
1290
|
timeSeconds: animationState.timeSeconds,
|
|
1276
1291
|
});
|
|
1292
|
+
updateScreenLabels();
|
|
1277
1293
|
updateMinimap();
|
|
1278
1294
|
updateTooltip();
|
|
1279
1295
|
}
|
|
1296
|
+
function suppressStaticLabelLayers() {
|
|
1297
|
+
if (is3DView()) {
|
|
1298
|
+
return;
|
|
1299
|
+
}
|
|
1300
|
+
container
|
|
1301
|
+
.querySelector('[data-layer-id="labels"]')
|
|
1302
|
+
?.setAttribute("display", "none");
|
|
1303
|
+
for (const element of container.querySelectorAll(".wo-event-label")) {
|
|
1304
|
+
element.setAttribute("display", "none");
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
function updateScreenLabels() {
|
|
1308
|
+
if (!labelRoot) {
|
|
1309
|
+
return;
|
|
1310
|
+
}
|
|
1311
|
+
const descriptors = buildScreenLabelDescriptors();
|
|
1312
|
+
labelRoot.replaceChildren(...descriptors.map((descriptor) => createScreenLabelElement(descriptor)));
|
|
1313
|
+
labelRoot.hidden = descriptors.length === 0;
|
|
1314
|
+
}
|
|
1315
|
+
function buildScreenLabelDescriptors() {
|
|
1316
|
+
const descriptors = [];
|
|
1317
|
+
const visibleObjectIds = getVisibleObjectIds();
|
|
1318
|
+
if (layerEnabled("labels")) {
|
|
1319
|
+
for (const label of scene.labels) {
|
|
1320
|
+
if (label.hidden || !visibleObjectIds.has(label.objectId)) {
|
|
1321
|
+
continue;
|
|
1322
|
+
}
|
|
1323
|
+
if (is3DView() && !shouldRender3DLabel(label.objectId, visibleObjectIds)) {
|
|
1324
|
+
continue;
|
|
1325
|
+
}
|
|
1326
|
+
const point = is3DView()
|
|
1327
|
+
? runtime3d?.projectObjectToContainer(label.objectId) ?? null
|
|
1328
|
+
: project2DScenePointToContainer({ x: label.x, y: label.y });
|
|
1329
|
+
if (!point) {
|
|
1330
|
+
continue;
|
|
1331
|
+
}
|
|
1332
|
+
descriptors.push({
|
|
1333
|
+
key: `object:${label.renderId}`,
|
|
1334
|
+
kind: "object",
|
|
1335
|
+
point: is3DView()
|
|
1336
|
+
? { x: point.x, y: point.y - 18 }
|
|
1337
|
+
: point,
|
|
1338
|
+
textAnchor: label.textAnchor,
|
|
1339
|
+
objectId: label.objectId,
|
|
1340
|
+
primaryText: label.label,
|
|
1341
|
+
secondaryText: label.secondaryLabel,
|
|
1342
|
+
secondaryOffset: Math.max(label.secondaryY - label.y, 12),
|
|
1343
|
+
});
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
if (!is3DView() && layerEnabled("events")) {
|
|
1347
|
+
for (const event of scene.events) {
|
|
1348
|
+
if (event.hidden || !isEventVisible(event, visibleObjectIds)) {
|
|
1349
|
+
continue;
|
|
1350
|
+
}
|
|
1351
|
+
const point = project2DScenePointToContainer({ x: event.x, y: event.y - 10 });
|
|
1352
|
+
if (!point) {
|
|
1353
|
+
continue;
|
|
1354
|
+
}
|
|
1355
|
+
descriptors.push({
|
|
1356
|
+
key: `event:${event.renderId}`,
|
|
1357
|
+
kind: "event",
|
|
1358
|
+
point,
|
|
1359
|
+
textAnchor: "middle",
|
|
1360
|
+
primaryText: event.event.label || event.event.id,
|
|
1361
|
+
});
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
return descriptors;
|
|
1365
|
+
}
|
|
1366
|
+
function isEventVisible(event, visibleObjectIds) {
|
|
1367
|
+
return event.objectIds.some((objectId) => visibleObjectIds.has(objectId));
|
|
1368
|
+
}
|
|
1369
|
+
function shouldRender3DLabel(objectId, visibleObjectIds) {
|
|
1370
|
+
if (!is3DView()) {
|
|
1371
|
+
return true;
|
|
1372
|
+
}
|
|
1373
|
+
if (objectId === state.selectedObjectId || objectId === hoveredObjectId) {
|
|
1374
|
+
return true;
|
|
1375
|
+
}
|
|
1376
|
+
const object = getObjectById(objectId);
|
|
1377
|
+
if (!object || object.hidden || !visibleObjectIds.has(objectId)) {
|
|
1378
|
+
return false;
|
|
1379
|
+
}
|
|
1380
|
+
if (object.object.type === "star") {
|
|
1381
|
+
return true;
|
|
1382
|
+
}
|
|
1383
|
+
const selected = state.selectedObjectId ? buildObjectDetails(state.selectedObjectId) : null;
|
|
1384
|
+
const hovered = hoveredObjectId ? buildObjectDetails(hoveredObjectId) : null;
|
|
1385
|
+
const selectedFocus = selected
|
|
1386
|
+
? new Set([
|
|
1387
|
+
selected.objectId,
|
|
1388
|
+
...selected.renderObject.ancestorIds,
|
|
1389
|
+
...selected.renderObject.childIds,
|
|
1390
|
+
])
|
|
1391
|
+
: null;
|
|
1392
|
+
const hoveredFocus = hovered
|
|
1393
|
+
? new Set([
|
|
1394
|
+
hovered.objectId,
|
|
1395
|
+
...hovered.renderObject.ancestorIds,
|
|
1396
|
+
...hovered.renderObject.childIds,
|
|
1397
|
+
])
|
|
1398
|
+
: null;
|
|
1399
|
+
if (selectedFocus?.has(objectId) || hoveredFocus?.has(objectId)) {
|
|
1400
|
+
return true;
|
|
1401
|
+
}
|
|
1402
|
+
if (object.semanticGroupIds.length > 0 && object.visualRadius >= 12) {
|
|
1403
|
+
return true;
|
|
1404
|
+
}
|
|
1405
|
+
return object.childIds.length > 0 && object.visualRadius >= 10;
|
|
1406
|
+
}
|
|
1407
|
+
function createScreenLabelElement(descriptor) {
|
|
1408
|
+
const element = document.createElement("div");
|
|
1409
|
+
element.className = `wo-viewer-label wo-viewer-label-${descriptor.kind}`;
|
|
1410
|
+
element.dataset.worldorbitScreenLabel = "true";
|
|
1411
|
+
element.dataset.labelKey = descriptor.key;
|
|
1412
|
+
element.dataset.anchor = descriptor.textAnchor;
|
|
1413
|
+
element.style.left = `${descriptor.point.x}px`;
|
|
1414
|
+
element.style.top = `${descriptor.point.y}px`;
|
|
1415
|
+
if (descriptor.objectId) {
|
|
1416
|
+
element.dataset.objectId = descriptor.objectId;
|
|
1417
|
+
for (const className of resolveScreenLabelClasses(descriptor.objectId)) {
|
|
1418
|
+
element.classList.add(className);
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
const primary = document.createElement("span");
|
|
1422
|
+
primary.className = "wo-viewer-label-primary";
|
|
1423
|
+
if (descriptor.kind === "object") {
|
|
1424
|
+
primary.style.fontSize = `${14 * scene.scaleModel.labelMultiplier}px`;
|
|
1425
|
+
}
|
|
1426
|
+
primary.textContent = descriptor.primaryText;
|
|
1427
|
+
element.append(primary);
|
|
1428
|
+
if (descriptor.secondaryText) {
|
|
1429
|
+
const secondary = document.createElement("span");
|
|
1430
|
+
secondary.className = "wo-viewer-label-secondary";
|
|
1431
|
+
secondary.style.fontSize = `${11 * scene.scaleModel.labelMultiplier}px`;
|
|
1432
|
+
secondary.style.marginTop = `${Math.max(descriptor.secondaryOffset ?? 12, 10) - 10}px`;
|
|
1433
|
+
secondary.textContent = descriptor.secondaryText;
|
|
1434
|
+
element.append(secondary);
|
|
1435
|
+
}
|
|
1436
|
+
return element;
|
|
1437
|
+
}
|
|
1438
|
+
function layerEnabled(id) {
|
|
1439
|
+
return renderOptions.layers?.[id] !== false;
|
|
1440
|
+
}
|
|
1441
|
+
function resolveScreenLabelClasses(objectId) {
|
|
1442
|
+
const classes = [];
|
|
1443
|
+
const selectedDetails = buildObjectDetails(state.selectedObjectId);
|
|
1444
|
+
const hoveredDetails = buildObjectDetails(hoveredObjectId);
|
|
1445
|
+
if (state.selectedObjectId === objectId) {
|
|
1446
|
+
classes.push("wo-object-selected");
|
|
1447
|
+
}
|
|
1448
|
+
if (selectedDetails) {
|
|
1449
|
+
const selectedChain = new Set([
|
|
1450
|
+
selectedDetails.objectId,
|
|
1451
|
+
...selectedDetails.renderObject.childIds,
|
|
1452
|
+
...selectedDetails.renderObject.ancestorIds,
|
|
1453
|
+
]);
|
|
1454
|
+
const selectedAncestors = new Set(selectedDetails.ancestors.map((ancestor) => ancestor.objectId));
|
|
1455
|
+
if (selectedChain.has(objectId)) {
|
|
1456
|
+
classes.push("wo-chain-selected");
|
|
1457
|
+
}
|
|
1458
|
+
if (selectedAncestors.has(objectId)) {
|
|
1459
|
+
classes.push("wo-ancestor-selected");
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
if (hoveredDetails) {
|
|
1463
|
+
const hoveredChain = new Set([
|
|
1464
|
+
hoveredDetails.objectId,
|
|
1465
|
+
...hoveredDetails.renderObject.childIds,
|
|
1466
|
+
...hoveredDetails.renderObject.ancestorIds,
|
|
1467
|
+
]);
|
|
1468
|
+
const hoveredAncestors = new Set(hoveredDetails.ancestors.map((ancestor) => ancestor.objectId));
|
|
1469
|
+
if (hoveredChain.has(objectId)) {
|
|
1470
|
+
classes.push("wo-chain-hover");
|
|
1471
|
+
}
|
|
1472
|
+
if (hoveredAncestors.has(objectId)) {
|
|
1473
|
+
classes.push("wo-ancestor-hover");
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
return classes;
|
|
1477
|
+
}
|
|
1280
1478
|
function create3DFocusState(objectId) {
|
|
1281
1479
|
const target = spatialScene?.focusTargets.find((entry) => entry.objectId === objectId);
|
|
1282
1480
|
if (!target) {
|
|
@@ -1345,6 +1543,8 @@ function cloneRenderOptions(renderOptions) {
|
|
|
1345
1543
|
: renderOptions.theme,
|
|
1346
1544
|
activeEventId: renderOptions.activeEventId ?? null,
|
|
1347
1545
|
viewMode: renderOptions.viewMode ?? "2d",
|
|
1546
|
+
quality: renderOptions.quality ?? "balanced",
|
|
1547
|
+
style3d: renderOptions.style3d ?? "symbolic",
|
|
1348
1548
|
};
|
|
1349
1549
|
}
|
|
1350
1550
|
function mergeRenderOptions(current, next) {
|
|
@@ -1383,6 +1583,8 @@ function mergeRenderOptions(current, next) {
|
|
|
1383
1583
|
? { ...next.theme }
|
|
1384
1584
|
: next.theme ?? current.theme,
|
|
1385
1585
|
viewMode: next.viewMode ?? current.viewMode ?? "2d",
|
|
1586
|
+
quality: next.quality ?? current.quality ?? "balanced",
|
|
1587
|
+
style3d: next.style3d ?? current.style3d ?? "symbolic",
|
|
1386
1588
|
};
|
|
1387
1589
|
}
|
|
1388
1590
|
function hasSceneAffectingRenderOptions(options) {
|
|
@@ -1557,7 +1759,7 @@ function cssEscape(value) {
|
|
|
1557
1759
|
}
|
|
1558
1760
|
return value.replace(/["\\]/g, "\\$&");
|
|
1559
1761
|
}
|
|
1560
|
-
function
|
|
1762
|
+
function installViewerOverlayStyles() {
|
|
1561
1763
|
if (typeof document === "undefined" || document.getElementById(TOOLTIP_STYLE_ID)) {
|
|
1562
1764
|
return;
|
|
1563
1765
|
}
|
|
@@ -1592,6 +1794,60 @@ function installViewerTooltipStyles() {
|
|
|
1592
1794
|
height: 100%;
|
|
1593
1795
|
min-height: 320px;
|
|
1594
1796
|
}
|
|
1797
|
+
.wo-viewer-label-root {
|
|
1798
|
+
position: absolute;
|
|
1799
|
+
inset: 0;
|
|
1800
|
+
z-index: 8;
|
|
1801
|
+
pointer-events: none;
|
|
1802
|
+
overflow: hidden;
|
|
1803
|
+
}
|
|
1804
|
+
.wo-viewer-label {
|
|
1805
|
+
position: absolute;
|
|
1806
|
+
display: grid;
|
|
1807
|
+
gap: 2px;
|
|
1808
|
+
padding: 4px 8px;
|
|
1809
|
+
border-radius: 999px;
|
|
1810
|
+
background: linear-gradient(180deg, rgba(5, 16, 26, 0.72), rgba(5, 16, 26, 0.38));
|
|
1811
|
+
border: 1px solid rgba(164, 194, 228, 0.16);
|
|
1812
|
+
color: #edf6ff;
|
|
1813
|
+
font-family: "Segoe UI Variable", "Segoe UI", sans-serif;
|
|
1814
|
+
line-height: 1.15;
|
|
1815
|
+
text-shadow: 0 1px 2px rgba(7, 16, 25, 0.65), 0 0 18px rgba(7, 16, 25, 0.18);
|
|
1816
|
+
white-space: nowrap;
|
|
1817
|
+
}
|
|
1818
|
+
.wo-viewer-label[data-anchor="middle"] { transform: translate(-50%, 0); }
|
|
1819
|
+
.wo-viewer-label[data-anchor="end"] { transform: translate(-100%, 0); }
|
|
1820
|
+
.wo-viewer-label-primary {
|
|
1821
|
+
font-size: 14px;
|
|
1822
|
+
font-weight: 600;
|
|
1823
|
+
letter-spacing: 0.02em;
|
|
1824
|
+
}
|
|
1825
|
+
.wo-viewer-label-secondary {
|
|
1826
|
+
font-size: 11px;
|
|
1827
|
+
font-weight: 500;
|
|
1828
|
+
color: rgba(237, 246, 255, 0.72);
|
|
1829
|
+
}
|
|
1830
|
+
.wo-viewer-label-event {
|
|
1831
|
+
color: #ffce8a;
|
|
1832
|
+
text-transform: uppercase;
|
|
1833
|
+
letter-spacing: 0.04em;
|
|
1834
|
+
}
|
|
1835
|
+
.wo-viewer-label-event .wo-viewer-label-primary {
|
|
1836
|
+
font-size: 10px;
|
|
1837
|
+
font-weight: 700;
|
|
1838
|
+
}
|
|
1839
|
+
.wo-viewer-label.wo-object-selected .wo-viewer-label-primary,
|
|
1840
|
+
.wo-viewer-label.wo-chain-selected .wo-viewer-label-primary,
|
|
1841
|
+
.wo-viewer-label.wo-chain-hover .wo-viewer-label-primary {
|
|
1842
|
+
color: #ffce8a;
|
|
1843
|
+
}
|
|
1844
|
+
.wo-viewer-label.wo-object-selected .wo-viewer-label-secondary {
|
|
1845
|
+
color: #8fcaff;
|
|
1846
|
+
}
|
|
1847
|
+
.wo-viewer-label.wo-ancestor-selected .wo-viewer-label-primary,
|
|
1848
|
+
.wo-viewer-label.wo-ancestor-hover .wo-viewer-label-primary {
|
|
1849
|
+
opacity: 0.82;
|
|
1850
|
+
}
|
|
1595
1851
|
.wo-viewer-tooltip-root {
|
|
1596
1852
|
position: absolute;
|
|
1597
1853
|
z-index: 12;
|