worldorbit 2.5.16 → 2.5.17
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 +1 -1
- package/dist/browser/core/dist/index.js +750 -73
- package/dist/browser/editor/dist/index.js +1303 -135
- package/dist/browser/markdown/dist/index.js +631 -72
- package/dist/browser/viewer/dist/index.js +658 -77
- package/dist/unpkg/core/dist/index.js +750 -73
- package/dist/unpkg/editor/dist/index.js +1303 -135
- package/dist/unpkg/markdown/dist/index.js +631 -72
- package/dist/unpkg/viewer/dist/index.js +658 -77
- package/dist/unpkg/worldorbit-core.min.js +12 -12
- package/dist/unpkg/worldorbit-editor.min.js +284 -202
- package/dist/unpkg/worldorbit-markdown.min.js +66 -58
- package/dist/unpkg/worldorbit-viewer.min.js +76 -68
- package/dist/unpkg/worldorbit.js +797 -78
- package/dist/unpkg/worldorbit.min.js +80 -72
- package/package.json +1 -1
- package/packages/core/dist/atlas-edit.js +74 -0
- package/packages/core/dist/atlas-validate.js +122 -8
- package/packages/core/dist/draft-parse.js +212 -8
- package/packages/core/dist/draft.d.ts +5 -2
- package/packages/core/dist/draft.js +59 -3
- package/packages/core/dist/format.js +63 -1
- package/packages/core/dist/normalize.js +1 -0
- package/packages/core/dist/scene.js +248 -46
- package/packages/core/dist/types.d.ts +41 -2
- package/packages/editor/dist/editor.js +597 -61
- package/packages/editor/dist/types.d.ts +3 -1
- package/packages/viewer/dist/atlas-state.js +6 -0
- package/packages/viewer/dist/atlas-viewer.js +1 -0
- package/packages/viewer/dist/render.js +31 -2
- package/packages/viewer/dist/theme.js +1 -0
- package/packages/viewer/dist/tooltip.js +9 -0
- package/packages/viewer/dist/types.d.ts +8 -1
- package/packages/viewer/dist/viewer.js +12 -1
|
@@ -61,6 +61,7 @@ var WorldOrbit = (() => {
|
|
|
61
61
|
background: true,
|
|
62
62
|
guides: true,
|
|
63
63
|
relations: true,
|
|
64
|
+
events: true,
|
|
64
65
|
orbits: true,
|
|
65
66
|
objects: true,
|
|
66
67
|
labels: true,
|
|
@@ -212,12 +213,14 @@ var WorldOrbit = (() => {
|
|
|
212
213
|
return {
|
|
213
214
|
version: "2.0",
|
|
214
215
|
viewpointId,
|
|
216
|
+
activeEventId: renderOptions.activeEventId ?? null,
|
|
215
217
|
viewerState: { ...viewerState },
|
|
216
218
|
renderOptions: {
|
|
217
219
|
preset: renderOptions.preset,
|
|
218
220
|
projection: renderOptions.projection,
|
|
219
221
|
layers: renderOptions.layers ? { ...renderOptions.layers } : void 0,
|
|
220
|
-
scaleModel: renderOptions.scaleModel ? { ...renderOptions.scaleModel } : void 0
|
|
222
|
+
scaleModel: renderOptions.scaleModel ? { ...renderOptions.scaleModel } : void 0,
|
|
223
|
+
activeEventId: renderOptions.activeEventId ?? null
|
|
221
224
|
},
|
|
222
225
|
filter: normalizeViewerFilter(filter)
|
|
223
226
|
};
|
|
@@ -230,6 +233,7 @@ var WorldOrbit = (() => {
|
|
|
230
233
|
return {
|
|
231
234
|
version: "2.0",
|
|
232
235
|
viewpointId: raw.viewpointId ?? null,
|
|
236
|
+
activeEventId: raw.activeEventId ?? raw.renderOptions?.activeEventId ?? null,
|
|
233
237
|
viewerState: {
|
|
234
238
|
scale: raw.viewerState?.scale ?? 1,
|
|
235
239
|
rotationDeg: raw.viewerState?.rotationDeg ?? 0,
|
|
@@ -241,7 +245,8 @@ var WorldOrbit = (() => {
|
|
|
241
245
|
preset: raw.renderOptions?.preset,
|
|
242
246
|
projection: raw.renderOptions?.projection,
|
|
243
247
|
layers: raw.renderOptions?.layers ? { ...raw.renderOptions.layers } : void 0,
|
|
244
|
-
scaleModel: raw.renderOptions?.scaleModel ? { ...raw.renderOptions.scaleModel } : void 0
|
|
248
|
+
scaleModel: raw.renderOptions?.scaleModel ? { ...raw.renderOptions.scaleModel } : void 0,
|
|
249
|
+
activeEventId: raw.activeEventId ?? raw.renderOptions?.activeEventId ?? null
|
|
245
250
|
},
|
|
246
251
|
filter: normalizeViewerFilter(raw.filter ?? null)
|
|
247
252
|
};
|
|
@@ -257,7 +262,8 @@ var WorldOrbit = (() => {
|
|
|
257
262
|
renderOptions: {
|
|
258
263
|
...atlasState.renderOptions,
|
|
259
264
|
layers: atlasState.renderOptions.layers ? { ...atlasState.renderOptions.layers } : void 0,
|
|
260
|
-
scaleModel: atlasState.renderOptions.scaleModel ? { ...atlasState.renderOptions.scaleModel } : void 0
|
|
265
|
+
scaleModel: atlasState.renderOptions.scaleModel ? { ...atlasState.renderOptions.scaleModel } : void 0,
|
|
266
|
+
activeEventId: atlasState.renderOptions.activeEventId ?? null
|
|
261
267
|
},
|
|
262
268
|
filter: atlasState.filter ? { ...atlasState.filter } : null
|
|
263
269
|
}
|
|
@@ -275,6 +281,7 @@ var WorldOrbit = (() => {
|
|
|
275
281
|
background: viewpoint.layers.background,
|
|
276
282
|
guides: viewpoint.layers.guides,
|
|
277
283
|
relations: viewpoint.layers.relations,
|
|
284
|
+
events: viewpoint.layers.events,
|
|
278
285
|
orbits: viewpoint.layers["orbits-front"] === void 0 && viewpoint.layers["orbits-back"] === void 0 ? void 0 : viewpoint.layers["orbits-front"] !== false || viewpoint.layers["orbits-back"] !== false,
|
|
279
286
|
objects: viewpoint.layers.objects,
|
|
280
287
|
labels: viewpoint.layers.labels,
|
|
@@ -922,6 +929,7 @@ var WorldOrbit = (() => {
|
|
|
922
929
|
system,
|
|
923
930
|
groups: [],
|
|
924
931
|
relations: [],
|
|
932
|
+
events: [],
|
|
925
933
|
objects
|
|
926
934
|
};
|
|
927
935
|
}
|
|
@@ -1305,8 +1313,10 @@ var WorldOrbit = (() => {
|
|
|
1305
1313
|
const scaleModel = resolveScaleModel(layoutPreset, options.scaleModel);
|
|
1306
1314
|
const spacingFactor = layoutPresetSpacing(layoutPreset);
|
|
1307
1315
|
const systemId = document2.system?.id ?? null;
|
|
1308
|
-
const
|
|
1309
|
-
const
|
|
1316
|
+
const activeEventId = options.activeEventId ?? null;
|
|
1317
|
+
const effectiveObjects = createEffectiveObjects(document2.objects, document2.events ?? [], activeEventId);
|
|
1318
|
+
const objectMap = new Map(effectiveObjects.map((object) => [object.id, object]));
|
|
1319
|
+
const relationships = buildSceneRelationships(effectiveObjects, objectMap);
|
|
1310
1320
|
const positions = /* @__PURE__ */ new Map();
|
|
1311
1321
|
const orbitDrafts = [];
|
|
1312
1322
|
const leaderDrafts = [];
|
|
@@ -1315,7 +1325,7 @@ var WorldOrbit = (() => {
|
|
|
1315
1325
|
const atObjects = [];
|
|
1316
1326
|
const surfaceChildren = /* @__PURE__ */ new Map();
|
|
1317
1327
|
const orbitChildren = /* @__PURE__ */ new Map();
|
|
1318
|
-
for (const object of
|
|
1328
|
+
for (const object of effectiveObjects) {
|
|
1319
1329
|
const placement = object.placement;
|
|
1320
1330
|
if (!placement) {
|
|
1321
1331
|
rootObjects.push(object);
|
|
@@ -1410,13 +1420,14 @@ var WorldOrbit = (() => {
|
|
|
1410
1420
|
const objects = [...positions.values()].map((position) => createSceneObject(position, scaleModel, relationships));
|
|
1411
1421
|
const orbitVisuals = orbitDrafts.map((draft) => createOrbitVisual(draft, relationships.groupIds.get(draft.object.id) ?? null));
|
|
1412
1422
|
const leaders = leaderDrafts.map((draft) => createLeaderLine(draft));
|
|
1413
|
-
const labels = createSceneLabels(objects, height, scaleModel.labelMultiplier);
|
|
1423
|
+
const labels = createSceneLabels(objects, width, height, scaleModel.labelMultiplier);
|
|
1414
1424
|
const relations = createSceneRelations(document2, objects);
|
|
1415
|
-
const
|
|
1416
|
-
const
|
|
1425
|
+
const events = createSceneEvents(document2.events ?? [], objects, activeEventId);
|
|
1426
|
+
const layers = createSceneLayers(orbitVisuals, relations, events, leaders, objects, labels);
|
|
1427
|
+
const groups = createSceneGroups(objects, orbitVisuals, leaders, labels, relationships, scaleModel.labelMultiplier);
|
|
1417
1428
|
const semanticGroups = createSceneSemanticGroups(document2, objects);
|
|
1418
1429
|
const viewpoints = createSceneViewpoints(document2, projection, frame.preset, relationships, objectMap);
|
|
1419
|
-
const contentBounds = calculateContentBounds(width, height, objects, orbitVisuals, leaders, labels);
|
|
1430
|
+
const contentBounds = calculateContentBounds(width, height, objects, orbitVisuals, leaders, labels, scaleModel.labelMultiplier);
|
|
1420
1431
|
return {
|
|
1421
1432
|
width,
|
|
1422
1433
|
height,
|
|
@@ -1442,6 +1453,8 @@ var WorldOrbit = (() => {
|
|
|
1442
1453
|
groups,
|
|
1443
1454
|
semanticGroups,
|
|
1444
1455
|
viewpoints,
|
|
1456
|
+
events,
|
|
1457
|
+
activeEventId,
|
|
1445
1458
|
objects,
|
|
1446
1459
|
orbitVisuals,
|
|
1447
1460
|
relations,
|
|
@@ -1460,6 +1473,35 @@ var WorldOrbit = (() => {
|
|
|
1460
1473
|
y: center.y + dx * sin + dy * cos
|
|
1461
1474
|
};
|
|
1462
1475
|
}
|
|
1476
|
+
function createEffectiveObjects(objects, events, activeEventId) {
|
|
1477
|
+
const cloned = objects.map((object) => structuredClone(object));
|
|
1478
|
+
if (!activeEventId) {
|
|
1479
|
+
return cloned;
|
|
1480
|
+
}
|
|
1481
|
+
const activeEvent = events.find((event) => event.id === activeEventId);
|
|
1482
|
+
if (!activeEvent) {
|
|
1483
|
+
return cloned;
|
|
1484
|
+
}
|
|
1485
|
+
const objectMap = new Map(cloned.map((object) => [object.id, object]));
|
|
1486
|
+
for (const pose of activeEvent.positions) {
|
|
1487
|
+
const object = objectMap.get(pose.objectId);
|
|
1488
|
+
if (!object) {
|
|
1489
|
+
continue;
|
|
1490
|
+
}
|
|
1491
|
+
object.placement = pose.placement ? structuredClone(pose.placement) : null;
|
|
1492
|
+
if (pose.inner) {
|
|
1493
|
+
object.properties.inner = { ...pose.inner };
|
|
1494
|
+
} else {
|
|
1495
|
+
delete object.properties.inner;
|
|
1496
|
+
}
|
|
1497
|
+
if (pose.outer) {
|
|
1498
|
+
object.properties.outer = { ...pose.outer };
|
|
1499
|
+
} else {
|
|
1500
|
+
delete object.properties.outer;
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
return cloned;
|
|
1504
|
+
}
|
|
1463
1505
|
function resolveLayoutPreset(document2) {
|
|
1464
1506
|
const rawScale = String(document2.system?.properties.scale ?? "balanced").toLowerCase();
|
|
1465
1507
|
switch (rawScale) {
|
|
@@ -1615,24 +1657,14 @@ var WorldOrbit = (() => {
|
|
|
1615
1657
|
hidden: draft.object.properties.hidden === true
|
|
1616
1658
|
};
|
|
1617
1659
|
}
|
|
1618
|
-
function createSceneLabels(objects, sceneHeight, labelMultiplier) {
|
|
1660
|
+
function createSceneLabels(objects, sceneWidth, sceneHeight, labelMultiplier) {
|
|
1619
1661
|
const labels = [];
|
|
1620
1662
|
const occupied = [];
|
|
1621
|
-
const
|
|
1663
|
+
const objectMap = new Map(objects.map((object) => [object.objectId, object]));
|
|
1664
|
+
const visibleObjects = [...objects].filter((object) => !object.hidden && object.object.renderHints?.renderLabel !== false).sort(compareLabelPlacementOrder);
|
|
1622
1665
|
for (const object of visibleObjects) {
|
|
1623
|
-
const
|
|
1624
|
-
|
|
1625
|
-
let labelY = object.y + direction * (object.radius + 18 * labelMultiplier);
|
|
1626
|
-
let secondaryY = labelY + direction * (16 * labelMultiplier);
|
|
1627
|
-
let bounds = createLabelRect(object.x, labelY, secondaryY, labelHalfWidth, direction);
|
|
1628
|
-
let attempts = 0;
|
|
1629
|
-
while (occupied.some((entry) => rectsOverlap(entry, bounds)) && attempts < 10) {
|
|
1630
|
-
labelY += direction * 14 * labelMultiplier;
|
|
1631
|
-
secondaryY += direction * 14 * labelMultiplier;
|
|
1632
|
-
bounds = createLabelRect(object.x, labelY, secondaryY, labelHalfWidth, direction);
|
|
1633
|
-
attempts += 1;
|
|
1634
|
-
}
|
|
1635
|
-
occupied.push(bounds);
|
|
1666
|
+
const placement = selectLabelPlacement(object, objectMap, occupied, sceneWidth, sceneHeight, labelMultiplier) ?? createLabelPlacement(object, defaultVerticalDirection(object, objectMap.get(object.parentId ?? "") ?? null, sceneHeight), 0, labelMultiplier);
|
|
1667
|
+
occupied.push(createLabelRect(object, placement, labelMultiplier));
|
|
1636
1668
|
labels.push({
|
|
1637
1669
|
renderId: `${object.renderId}-label`,
|
|
1638
1670
|
objectId: object.objectId,
|
|
@@ -1641,17 +1673,128 @@ var WorldOrbit = (() => {
|
|
|
1641
1673
|
semanticGroupIds: [...object.semanticGroupIds],
|
|
1642
1674
|
label: object.label,
|
|
1643
1675
|
secondaryLabel: object.secondaryLabel,
|
|
1644
|
-
x:
|
|
1645
|
-
y: labelY,
|
|
1646
|
-
secondaryY,
|
|
1647
|
-
textAnchor:
|
|
1648
|
-
direction: direction
|
|
1676
|
+
x: placement.x,
|
|
1677
|
+
y: placement.labelY,
|
|
1678
|
+
secondaryY: placement.secondaryY,
|
|
1679
|
+
textAnchor: placement.textAnchor,
|
|
1680
|
+
direction: placement.direction,
|
|
1649
1681
|
hidden: object.hidden
|
|
1650
1682
|
});
|
|
1651
1683
|
}
|
|
1652
1684
|
return labels;
|
|
1653
1685
|
}
|
|
1654
|
-
function
|
|
1686
|
+
function compareLabelPlacementOrder(left, right) {
|
|
1687
|
+
const priorityDiff = labelPlacementPriority(left) - labelPlacementPriority(right);
|
|
1688
|
+
if (priorityDiff !== 0) {
|
|
1689
|
+
return priorityDiff;
|
|
1690
|
+
}
|
|
1691
|
+
const renderPriorityDiff = (right.object.renderHints?.renderPriority ?? 0) - (left.object.renderHints?.renderPriority ?? 0);
|
|
1692
|
+
if (renderPriorityDiff !== 0) {
|
|
1693
|
+
return renderPriorityDiff;
|
|
1694
|
+
}
|
|
1695
|
+
return left.sortKey - right.sortKey;
|
|
1696
|
+
}
|
|
1697
|
+
function labelPlacementPriority(object) {
|
|
1698
|
+
switch (object.object.type) {
|
|
1699
|
+
case "star":
|
|
1700
|
+
return 0;
|
|
1701
|
+
case "planet":
|
|
1702
|
+
return 1;
|
|
1703
|
+
case "moon":
|
|
1704
|
+
return 2;
|
|
1705
|
+
case "belt":
|
|
1706
|
+
case "ring":
|
|
1707
|
+
return 3;
|
|
1708
|
+
case "asteroid":
|
|
1709
|
+
case "comet":
|
|
1710
|
+
return 4;
|
|
1711
|
+
case "structure":
|
|
1712
|
+
case "phenomenon":
|
|
1713
|
+
return 5;
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
function selectLabelPlacement(object, objectMap, occupied, sceneWidth, sceneHeight, labelMultiplier) {
|
|
1717
|
+
for (const direction of preferredLabelDirections(object, objectMap, sceneWidth, sceneHeight)) {
|
|
1718
|
+
const maxAttempts = direction === "left" || direction === "right" ? 4 : 6;
|
|
1719
|
+
for (let attempt = 0; attempt <= maxAttempts; attempt += 1) {
|
|
1720
|
+
const placement = createLabelPlacement(object, direction, attempt, labelMultiplier);
|
|
1721
|
+
const rect = createLabelRect(object, placement, labelMultiplier);
|
|
1722
|
+
if (!occupied.some((entry) => rectsOverlap(entry, rect))) {
|
|
1723
|
+
return placement;
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1727
|
+
return null;
|
|
1728
|
+
}
|
|
1729
|
+
function preferredLabelDirections(object, objectMap, sceneWidth, sceneHeight) {
|
|
1730
|
+
const parent = object.parentId ? objectMap.get(object.parentId) ?? null : null;
|
|
1731
|
+
const vertical = defaultVerticalDirection(object, parent, sceneHeight);
|
|
1732
|
+
const oppositeVertical = vertical === "below" ? "above" : "below";
|
|
1733
|
+
const horizontal = defaultHorizontalDirection(object, parent, sceneWidth);
|
|
1734
|
+
const oppositeHorizontal = horizontal === "right" ? "left" : "right";
|
|
1735
|
+
const preferHorizontal = object.object.type === "structure" || object.object.type === "phenomenon" || object.object.placement?.mode === "at" || object.object.placement?.mode === "surface" || object.object.placement?.mode === "free";
|
|
1736
|
+
return preferHorizontal ? [horizontal, vertical, oppositeHorizontal, oppositeVertical] : [vertical, horizontal, oppositeVertical, oppositeHorizontal];
|
|
1737
|
+
}
|
|
1738
|
+
function defaultVerticalDirection(object, parent, sceneHeight) {
|
|
1739
|
+
if (parent && Math.abs(object.y - parent.y) > 6) {
|
|
1740
|
+
return object.y >= parent.y ? "below" : "above";
|
|
1741
|
+
}
|
|
1742
|
+
return object.y > sceneHeight * 0.62 ? "above" : "below";
|
|
1743
|
+
}
|
|
1744
|
+
function defaultHorizontalDirection(object, parent, sceneWidth) {
|
|
1745
|
+
if (parent && Math.abs(object.x - parent.x) > 6) {
|
|
1746
|
+
return object.x >= parent.x ? "right" : "left";
|
|
1747
|
+
}
|
|
1748
|
+
return object.x >= sceneWidth / 2 ? "right" : "left";
|
|
1749
|
+
}
|
|
1750
|
+
function createLabelPlacement(object, direction, attempt, labelMultiplier) {
|
|
1751
|
+
const step = 14 * labelMultiplier;
|
|
1752
|
+
switch (direction) {
|
|
1753
|
+
case "above": {
|
|
1754
|
+
const labelY = object.y - (object.radius + 18 * labelMultiplier + attempt * step);
|
|
1755
|
+
return {
|
|
1756
|
+
x: object.x,
|
|
1757
|
+
labelY,
|
|
1758
|
+
secondaryY: labelY - 16 * labelMultiplier,
|
|
1759
|
+
textAnchor: "middle",
|
|
1760
|
+
direction
|
|
1761
|
+
};
|
|
1762
|
+
}
|
|
1763
|
+
case "below": {
|
|
1764
|
+
const labelY = object.y + object.radius + 18 * labelMultiplier + attempt * step;
|
|
1765
|
+
return {
|
|
1766
|
+
x: object.x,
|
|
1767
|
+
labelY,
|
|
1768
|
+
secondaryY: labelY + 16 * labelMultiplier,
|
|
1769
|
+
textAnchor: "middle",
|
|
1770
|
+
direction
|
|
1771
|
+
};
|
|
1772
|
+
}
|
|
1773
|
+
case "left": {
|
|
1774
|
+
const x = object.x - (object.visualRadius + 16 * labelMultiplier + attempt * step);
|
|
1775
|
+
const labelY = object.y - 4 * labelMultiplier;
|
|
1776
|
+
return {
|
|
1777
|
+
x,
|
|
1778
|
+
labelY,
|
|
1779
|
+
secondaryY: labelY + 16 * labelMultiplier,
|
|
1780
|
+
textAnchor: "end",
|
|
1781
|
+
direction
|
|
1782
|
+
};
|
|
1783
|
+
}
|
|
1784
|
+
case "right": {
|
|
1785
|
+
const x = object.x + object.visualRadius + 16 * labelMultiplier + attempt * step;
|
|
1786
|
+
const labelY = object.y - 4 * labelMultiplier;
|
|
1787
|
+
return {
|
|
1788
|
+
x,
|
|
1789
|
+
labelY,
|
|
1790
|
+
secondaryY: labelY + 16 * labelMultiplier,
|
|
1791
|
+
textAnchor: "start",
|
|
1792
|
+
direction
|
|
1793
|
+
};
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
1797
|
+
function createSceneLayers(orbitVisuals, relations, events, leaders, objects, labels) {
|
|
1655
1798
|
const backOrbitIds = orbitVisuals.filter((visual) => !visual.hidden && Boolean(visual.backArcPath)).map((visual) => visual.renderId);
|
|
1656
1799
|
const frontOrbitIds = orbitVisuals.filter((visual) => !visual.hidden).map((visual) => visual.renderId);
|
|
1657
1800
|
return [
|
|
@@ -1666,6 +1809,10 @@ var WorldOrbit = (() => {
|
|
|
1666
1809
|
id: "relations",
|
|
1667
1810
|
renderIds: relations.filter((relation) => !relation.hidden).map((relation) => relation.renderId)
|
|
1668
1811
|
},
|
|
1812
|
+
{
|
|
1813
|
+
id: "events",
|
|
1814
|
+
renderIds: events.filter((event) => !event.hidden).map((event) => event.renderId)
|
|
1815
|
+
},
|
|
1669
1816
|
{
|
|
1670
1817
|
id: "objects",
|
|
1671
1818
|
renderIds: objects.filter((object) => !object.hidden).map((object) => object.renderId)
|
|
@@ -1677,7 +1824,7 @@ var WorldOrbit = (() => {
|
|
|
1677
1824
|
{ id: "metadata", renderIds: ["wo-title", "wo-subtitle", "wo-meta"] }
|
|
1678
1825
|
];
|
|
1679
1826
|
}
|
|
1680
|
-
function createSceneGroups(objects, orbitVisuals, leaders, labels, relationships) {
|
|
1827
|
+
function createSceneGroups(objects, orbitVisuals, leaders, labels, relationships, labelMultiplier) {
|
|
1681
1828
|
const groups = /* @__PURE__ */ new Map();
|
|
1682
1829
|
const ensureGroup = (groupId) => {
|
|
1683
1830
|
if (!groupId) {
|
|
@@ -1726,7 +1873,7 @@ var WorldOrbit = (() => {
|
|
|
1726
1873
|
}
|
|
1727
1874
|
}
|
|
1728
1875
|
for (const group of groups.values()) {
|
|
1729
|
-
group.contentBounds = calculateGroupBounds(group, objects, orbitVisuals, leaders, labels);
|
|
1876
|
+
group.contentBounds = calculateGroupBounds(group, objects, orbitVisuals, leaders, labels, labelMultiplier);
|
|
1730
1877
|
}
|
|
1731
1878
|
return [...groups.values()].sort((left, right) => left.label.localeCompare(right.label));
|
|
1732
1879
|
}
|
|
@@ -1760,6 +1907,29 @@ var WorldOrbit = (() => {
|
|
|
1760
1907
|
};
|
|
1761
1908
|
}).sort((left, right) => left.relation.id.localeCompare(right.relation.id));
|
|
1762
1909
|
}
|
|
1910
|
+
function createSceneEvents(events, objects, activeEventId) {
|
|
1911
|
+
const objectMap = new Map(objects.map((object) => [object.objectId, object]));
|
|
1912
|
+
return events.map((event) => {
|
|
1913
|
+
const objectIds = [.../* @__PURE__ */ new Set([
|
|
1914
|
+
...event.targetObjectId ? [event.targetObjectId] : [],
|
|
1915
|
+
...event.participantObjectIds
|
|
1916
|
+
])];
|
|
1917
|
+
const positions = objectIds.map((objectId) => objectMap.get(objectId)).filter(Boolean);
|
|
1918
|
+
const centroidX = positions.length > 0 ? positions.reduce((sum, object) => sum + object.x, 0) / positions.length : 0;
|
|
1919
|
+
const centroidY = positions.length > 0 ? positions.reduce((sum, object) => sum + object.y, 0) / positions.length : 0;
|
|
1920
|
+
return {
|
|
1921
|
+
renderId: `${createRenderId(event.id)}-event`,
|
|
1922
|
+
eventId: event.id,
|
|
1923
|
+
event,
|
|
1924
|
+
objectIds,
|
|
1925
|
+
participantIds: [...event.participantObjectIds],
|
|
1926
|
+
targetObjectId: event.targetObjectId,
|
|
1927
|
+
x: centroidX,
|
|
1928
|
+
y: centroidY,
|
|
1929
|
+
hidden: event.hidden || positions.length === 0 || positions.every((object) => object.hidden) || activeEventId !== null && event.id !== activeEventId
|
|
1930
|
+
};
|
|
1931
|
+
}).sort((left, right) => left.event.id.localeCompare(right.event.id));
|
|
1932
|
+
}
|
|
1763
1933
|
function createSceneViewpoints(document2, projection, preset, relationships, objectMap) {
|
|
1764
1934
|
const generatedOverview = createGeneratedOverviewViewpoint(document2, projection, preset);
|
|
1765
1935
|
const drafts = /* @__PURE__ */ new Map();
|
|
@@ -1813,6 +1983,7 @@ var WorldOrbit = (() => {
|
|
|
1813
1983
|
summary: "Fit the whole system with the current atlas defaults.",
|
|
1814
1984
|
objectId: null,
|
|
1815
1985
|
selectedObjectId: null,
|
|
1986
|
+
eventIds: [],
|
|
1816
1987
|
projection,
|
|
1817
1988
|
preset,
|
|
1818
1989
|
rotationDeg: 0,
|
|
@@ -1849,6 +2020,9 @@ var WorldOrbit = (() => {
|
|
|
1849
2020
|
draft.select = normalizedValue;
|
|
1850
2021
|
}
|
|
1851
2022
|
return;
|
|
2023
|
+
case "events":
|
|
2024
|
+
draft.eventIds = splitListValue(normalizedValue);
|
|
2025
|
+
return;
|
|
1852
2026
|
case "projection":
|
|
1853
2027
|
case "view":
|
|
1854
2028
|
draft.projection = parseViewProjection(normalizedValue) ?? projection;
|
|
@@ -1905,6 +2079,7 @@ var WorldOrbit = (() => {
|
|
|
1905
2079
|
summary: draft.summary?.trim() || createViewpointSummary(label, objectId, filter),
|
|
1906
2080
|
objectId,
|
|
1907
2081
|
selectedObjectId,
|
|
2082
|
+
eventIds: [...new Set(draft.eventIds ?? [])],
|
|
1908
2083
|
projection: draft.projection ?? projection,
|
|
1909
2084
|
preset: draft.preset ?? preset,
|
|
1910
2085
|
rotationDeg: draft.rotationDeg ?? 0,
|
|
@@ -1962,7 +2137,7 @@ var WorldOrbit = (() => {
|
|
|
1962
2137
|
next["orbits-front"] = enabled;
|
|
1963
2138
|
continue;
|
|
1964
2139
|
}
|
|
1965
|
-
if (rawLayer === "background" || rawLayer === "guides" || rawLayer === "orbits-back" || rawLayer === "orbits-front" || rawLayer === "relations" || rawLayer === "objects" || rawLayer === "labels" || rawLayer === "metadata") {
|
|
2140
|
+
if (rawLayer === "background" || rawLayer === "guides" || rawLayer === "orbits-back" || rawLayer === "orbits-front" || rawLayer === "relations" || rawLayer === "events" || rawLayer === "objects" || rawLayer === "labels" || rawLayer === "metadata") {
|
|
1966
2141
|
next[rawLayer] = enabled;
|
|
1967
2142
|
}
|
|
1968
2143
|
}
|
|
@@ -2010,7 +2185,7 @@ var WorldOrbit = (() => {
|
|
|
2010
2185
|
}
|
|
2011
2186
|
return parts.join(" - ");
|
|
2012
2187
|
}
|
|
2013
|
-
function calculateContentBounds(width, height, objects, orbitVisuals, leaders, labels) {
|
|
2188
|
+
function calculateContentBounds(width, height, objects, orbitVisuals, leaders, labels, labelMultiplier) {
|
|
2014
2189
|
let minX = Number.POSITIVE_INFINITY;
|
|
2015
2190
|
let minY = Number.POSITIVE_INFINITY;
|
|
2016
2191
|
let maxX = Number.NEGATIVE_INFINITY;
|
|
@@ -2040,7 +2215,7 @@ var WorldOrbit = (() => {
|
|
|
2040
2215
|
for (const label of labels) {
|
|
2041
2216
|
if (label.hidden)
|
|
2042
2217
|
continue;
|
|
2043
|
-
includeLabelBounds(label, include);
|
|
2218
|
+
includeLabelBounds(label, include, labelMultiplier);
|
|
2044
2219
|
}
|
|
2045
2220
|
if (!Number.isFinite(minX) || !Number.isFinite(minY)) {
|
|
2046
2221
|
return createBounds(0, 0, width, height);
|
|
@@ -2078,13 +2253,10 @@ var WorldOrbit = (() => {
|
|
|
2078
2253
|
include(object.x - object.visualRadius - 24, object.y - object.visualRadius - 16);
|
|
2079
2254
|
include(object.x + object.visualRadius + 24, object.y + object.visualRadius + 36);
|
|
2080
2255
|
}
|
|
2081
|
-
function includeLabelBounds(label, include) {
|
|
2082
|
-
const
|
|
2083
|
-
|
|
2084
|
-
include(
|
|
2085
|
-
include(label.x + labelHalfWidth, label.y + 8);
|
|
2086
|
-
include(label.x - labelHalfWidth, label.secondaryY - 14);
|
|
2087
|
-
include(label.x + labelHalfWidth, label.secondaryY + 8);
|
|
2256
|
+
function includeLabelBounds(label, include, labelMultiplier) {
|
|
2257
|
+
const bounds = createLabelRectFromText(label.x, label.y, label.secondaryY, label.textAnchor, label.direction, label.label, label.secondaryLabel, labelMultiplier);
|
|
2258
|
+
include(bounds.left, bounds.top);
|
|
2259
|
+
include(bounds.right, bounds.bottom);
|
|
2088
2260
|
}
|
|
2089
2261
|
function placeObject(object, x, y, depth, positions, orbitDrafts, leaderDrafts, context) {
|
|
2090
2262
|
if (positions.has(object.id)) {
|
|
@@ -2474,7 +2646,7 @@ var WorldOrbit = (() => {
|
|
|
2474
2646
|
return null;
|
|
2475
2647
|
}
|
|
2476
2648
|
}
|
|
2477
|
-
function calculateGroupBounds(group, objects, orbitVisuals, leaders, labels) {
|
|
2649
|
+
function calculateGroupBounds(group, objects, orbitVisuals, leaders, labels, labelMultiplier) {
|
|
2478
2650
|
let minX = Number.POSITIVE_INFINITY;
|
|
2479
2651
|
let minY = Number.POSITIVE_INFINITY;
|
|
2480
2652
|
let maxX = Number.NEGATIVE_INFINITY;
|
|
@@ -2503,7 +2675,7 @@ var WorldOrbit = (() => {
|
|
|
2503
2675
|
}
|
|
2504
2676
|
for (const label of labels) {
|
|
2505
2677
|
if (!label.hidden && group.labelIds.includes(label.objectId)) {
|
|
2506
|
-
includeLabelBounds(label, include);
|
|
2678
|
+
includeLabelBounds(label, include, labelMultiplier);
|
|
2507
2679
|
}
|
|
2508
2680
|
}
|
|
2509
2681
|
if (!Number.isFinite(minX) || !Number.isFinite(minY)) {
|
|
@@ -2528,12 +2700,28 @@ var WorldOrbit = (() => {
|
|
|
2528
2700
|
}
|
|
2529
2701
|
return current.id;
|
|
2530
2702
|
}
|
|
2531
|
-
function createLabelRect(
|
|
2703
|
+
function createLabelRect(object, placement, labelMultiplier) {
|
|
2704
|
+
return createLabelRectFromText(placement.x, placement.labelY, placement.secondaryY, placement.textAnchor, placement.direction, object.label, object.secondaryLabel, labelMultiplier);
|
|
2705
|
+
}
|
|
2706
|
+
function createLabelRectFromText(x, labelY, secondaryY, textAnchor, direction, label, secondaryLabel, labelMultiplier) {
|
|
2707
|
+
const labelHalfWidth = estimateLabelHalfWidthFromText(label, secondaryLabel, labelMultiplier);
|
|
2708
|
+
const labelWidth = labelHalfWidth * 2;
|
|
2709
|
+
const topPadding = direction === "above" ? 18 : 12;
|
|
2710
|
+
const bottomPadding = direction === "above" ? 8 : 12;
|
|
2711
|
+
let left = x - labelHalfWidth;
|
|
2712
|
+
let right = x + labelHalfWidth;
|
|
2713
|
+
if (textAnchor === "start") {
|
|
2714
|
+
left = x;
|
|
2715
|
+
right = x + labelWidth;
|
|
2716
|
+
} else if (textAnchor === "end") {
|
|
2717
|
+
left = x - labelWidth;
|
|
2718
|
+
right = x;
|
|
2719
|
+
}
|
|
2532
2720
|
return {
|
|
2533
|
-
left
|
|
2534
|
-
right
|
|
2535
|
-
top: Math.min(labelY, secondaryY) -
|
|
2536
|
-
bottom: Math.max(labelY, secondaryY) +
|
|
2721
|
+
left,
|
|
2722
|
+
right,
|
|
2723
|
+
top: Math.min(labelY, secondaryY) - topPadding,
|
|
2724
|
+
bottom: Math.max(labelY, secondaryY) + bottomPadding
|
|
2537
2725
|
};
|
|
2538
2726
|
}
|
|
2539
2727
|
function rectsOverlap(left, right) {
|
|
@@ -2720,11 +2908,6 @@ var WorldOrbit = (() => {
|
|
|
2720
2908
|
function customColorFor(value) {
|
|
2721
2909
|
return typeof value === "string" && value.trim() ? value : void 0;
|
|
2722
2910
|
}
|
|
2723
|
-
function estimateLabelHalfWidth(object, labelMultiplier) {
|
|
2724
|
-
const primaryWidth = object.label.length * 4.6 * labelMultiplier + 18;
|
|
2725
|
-
const secondaryWidth = object.secondaryLabel.length * 3.9 * labelMultiplier + 18;
|
|
2726
|
-
return Math.max(primaryWidth, secondaryWidth, object.visualRadius + 18);
|
|
2727
|
-
}
|
|
2728
2911
|
function estimateLabelHalfWidthFromText(label, secondaryLabel, labelMultiplier) {
|
|
2729
2912
|
const primaryWidth = label.length * 4.6 * labelMultiplier + 18;
|
|
2730
2913
|
const secondaryWidth = secondaryLabel.length * 3.9 * labelMultiplier + 18;
|
|
@@ -2741,7 +2924,7 @@ var WorldOrbit = (() => {
|
|
|
2741
2924
|
}
|
|
2742
2925
|
|
|
2743
2926
|
// packages/core/dist/draft.js
|
|
2744
|
-
function materializeAtlasDocument(document2) {
|
|
2927
|
+
function materializeAtlasDocument(document2, options = {}) {
|
|
2745
2928
|
const system = document2.system ? {
|
|
2746
2929
|
type: "system",
|
|
2747
2930
|
id: document2.system.id,
|
|
@@ -2752,6 +2935,8 @@ var WorldOrbit = (() => {
|
|
|
2752
2935
|
properties: materializeDraftSystemProperties(document2.system),
|
|
2753
2936
|
info: materializeDraftSystemInfo(document2.system)
|
|
2754
2937
|
} : null;
|
|
2938
|
+
const objects = document2.objects.map(cloneWorldOrbitObject);
|
|
2939
|
+
applyEventPoseOverrides(objects, document2.events ?? [], options.activeEventId ?? null);
|
|
2755
2940
|
return {
|
|
2756
2941
|
format: "worldorbit",
|
|
2757
2942
|
version: "1.0",
|
|
@@ -2759,7 +2944,8 @@ var WorldOrbit = (() => {
|
|
|
2759
2944
|
system,
|
|
2760
2945
|
groups: structuredClone(document2.groups ?? []),
|
|
2761
2946
|
relations: structuredClone(document2.relations ?? []),
|
|
2762
|
-
|
|
2947
|
+
events: document2.events.map(cloneWorldOrbitEvent),
|
|
2948
|
+
objects
|
|
2763
2949
|
};
|
|
2764
2950
|
}
|
|
2765
2951
|
function cloneWorldOrbitObject(object) {
|
|
@@ -2781,6 +2967,52 @@ var WorldOrbit = (() => {
|
|
|
2781
2967
|
info: { ...object.info }
|
|
2782
2968
|
};
|
|
2783
2969
|
}
|
|
2970
|
+
function cloneWorldOrbitEvent(event) {
|
|
2971
|
+
return {
|
|
2972
|
+
...event,
|
|
2973
|
+
participantObjectIds: [...event.participantObjectIds],
|
|
2974
|
+
tags: [...event.tags],
|
|
2975
|
+
positions: event.positions.map(cloneWorldOrbitEventPose)
|
|
2976
|
+
};
|
|
2977
|
+
}
|
|
2978
|
+
function cloneWorldOrbitEventPose(pose) {
|
|
2979
|
+
return {
|
|
2980
|
+
objectId: pose.objectId,
|
|
2981
|
+
placement: clonePlacement(pose.placement),
|
|
2982
|
+
inner: pose.inner ? { ...pose.inner } : void 0,
|
|
2983
|
+
outer: pose.outer ? { ...pose.outer } : void 0
|
|
2984
|
+
};
|
|
2985
|
+
}
|
|
2986
|
+
function clonePlacement(placement) {
|
|
2987
|
+
return placement ? structuredClone(placement) : null;
|
|
2988
|
+
}
|
|
2989
|
+
function applyEventPoseOverrides(objects, events, activeEventId) {
|
|
2990
|
+
if (!activeEventId) {
|
|
2991
|
+
return;
|
|
2992
|
+
}
|
|
2993
|
+
const event = events.find((entry) => entry.id === activeEventId);
|
|
2994
|
+
if (!event) {
|
|
2995
|
+
return;
|
|
2996
|
+
}
|
|
2997
|
+
const objectMap = new Map(objects.map((object) => [object.id, object]));
|
|
2998
|
+
for (const pose of event.positions) {
|
|
2999
|
+
const object = objectMap.get(pose.objectId);
|
|
3000
|
+
if (!object) {
|
|
3001
|
+
continue;
|
|
3002
|
+
}
|
|
3003
|
+
object.placement = clonePlacement(pose.placement);
|
|
3004
|
+
if (pose.inner) {
|
|
3005
|
+
object.properties.inner = { ...pose.inner };
|
|
3006
|
+
} else {
|
|
3007
|
+
delete object.properties.inner;
|
|
3008
|
+
}
|
|
3009
|
+
if (pose.outer) {
|
|
3010
|
+
object.properties.outer = { ...pose.outer };
|
|
3011
|
+
} else {
|
|
3012
|
+
delete object.properties.outer;
|
|
3013
|
+
}
|
|
3014
|
+
}
|
|
3015
|
+
}
|
|
2784
3016
|
function cloneProperties(properties) {
|
|
2785
3017
|
const next = {};
|
|
2786
3018
|
for (const [key, value] of Object.entries(properties)) {
|
|
@@ -2869,6 +3101,9 @@ var WorldOrbit = (() => {
|
|
|
2869
3101
|
if ((viewpoint.filter?.groupIds.length ?? 0) > 0) {
|
|
2870
3102
|
info2[`${prefix}.groups`] = viewpoint.filter?.groupIds.join(" ") ?? "";
|
|
2871
3103
|
}
|
|
3104
|
+
if (viewpoint.events.length > 0) {
|
|
3105
|
+
info2[`${prefix}.events`] = viewpoint.events.join(" ");
|
|
3106
|
+
}
|
|
2872
3107
|
}
|
|
2873
3108
|
for (const annotation of system.annotations) {
|
|
2874
3109
|
const prefix = `annotation.${annotation.id}`;
|
|
@@ -2893,7 +3128,7 @@ var WorldOrbit = (() => {
|
|
|
2893
3128
|
if (orbitFront !== void 0 || orbitBack !== void 0) {
|
|
2894
3129
|
tokens.push(orbitFront !== false || orbitBack !== false ? "orbits" : "-orbits");
|
|
2895
3130
|
}
|
|
2896
|
-
for (const key of ["background", "guides", "relations", "objects", "labels", "metadata"]) {
|
|
3131
|
+
for (const key of ["background", "guides", "relations", "events", "objects", "labels", "metadata"]) {
|
|
2897
3132
|
if (layers[key] !== void 0) {
|
|
2898
3133
|
tokens.push(layers[key] ? key : `-${key}`);
|
|
2899
3134
|
}
|
|
@@ -3067,6 +3302,7 @@ var WorldOrbit = (() => {
|
|
|
3067
3302
|
const diagnostics = [];
|
|
3068
3303
|
const objectMap = new Map(document2.objects.map((object) => [object.id, object]));
|
|
3069
3304
|
const groupIds = new Set(document2.groups.map((group) => group.id));
|
|
3305
|
+
const eventIds = new Set(document2.events.map((event) => event.id));
|
|
3070
3306
|
if (!document2.system) {
|
|
3071
3307
|
diagnostics.push(error("validate.system.required", "Atlas documents must declare exactly one system."));
|
|
3072
3308
|
}
|
|
@@ -3076,6 +3312,7 @@ var WorldOrbit = (() => {
|
|
|
3076
3312
|
["viewpoint", document2.system?.viewpoints.map((viewpoint) => viewpoint.id) ?? []],
|
|
3077
3313
|
["annotation", document2.system?.annotations.map((annotation) => annotation.id) ?? []],
|
|
3078
3314
|
["relation", document2.relations.map((relation) => relation.id)],
|
|
3315
|
+
["event", document2.events.map((event) => event.id)],
|
|
3079
3316
|
["object", document2.objects.map((object) => object.id)]
|
|
3080
3317
|
]) {
|
|
3081
3318
|
for (const id of ids) {
|
|
@@ -3091,11 +3328,14 @@ var WorldOrbit = (() => {
|
|
|
3091
3328
|
validateRelation(relation, objectMap, diagnostics);
|
|
3092
3329
|
}
|
|
3093
3330
|
for (const viewpoint of document2.system?.viewpoints ?? []) {
|
|
3094
|
-
|
|
3331
|
+
validateViewpoint(viewpoint.filter, viewpoint.events ?? [], groupIds, eventIds, sourceSchemaVersion, diagnostics, viewpoint.id);
|
|
3095
3332
|
}
|
|
3096
3333
|
for (const object of document2.objects) {
|
|
3097
3334
|
validateObject(object, document2.system, objectMap, groupIds, diagnostics);
|
|
3098
3335
|
}
|
|
3336
|
+
for (const event of document2.events) {
|
|
3337
|
+
validateEvent(event, objectMap, diagnostics);
|
|
3338
|
+
}
|
|
3099
3339
|
return diagnostics;
|
|
3100
3340
|
}
|
|
3101
3341
|
function validateRelation(relation, objectMap, diagnostics) {
|
|
@@ -3113,13 +3353,19 @@ var WorldOrbit = (() => {
|
|
|
3113
3353
|
diagnostics.push(error("validate.relation.kind.required", `Relation "${relation.id}" is missing a "kind" value.`));
|
|
3114
3354
|
}
|
|
3115
3355
|
}
|
|
3116
|
-
function
|
|
3117
|
-
if (
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3356
|
+
function validateViewpoint(filter, eventRefs, groupIds, eventIds, sourceSchemaVersion, diagnostics, viewpointId) {
|
|
3357
|
+
if (sourceSchemaVersion === "2.1") {
|
|
3358
|
+
if (filter) {
|
|
3359
|
+
for (const groupId of filter.groupIds) {
|
|
3360
|
+
if (!groupIds.has(groupId)) {
|
|
3361
|
+
diagnostics.push(warn("validate.viewpoint.group.unknown", `Unknown group "${groupId}" in viewpoint "${viewpointId}".`, void 0, `viewpoint.${viewpointId}.groups`));
|
|
3362
|
+
}
|
|
3363
|
+
}
|
|
3364
|
+
}
|
|
3365
|
+
for (const eventId of eventRefs) {
|
|
3366
|
+
if (!eventIds.has(eventId)) {
|
|
3367
|
+
diagnostics.push(warn("validate.viewpoint.event.unknown", `Unknown event "${eventId}" in viewpoint "${viewpointId}".`, void 0, `viewpoint.${viewpointId}.events`));
|
|
3368
|
+
}
|
|
3123
3369
|
}
|
|
3124
3370
|
}
|
|
3125
3371
|
}
|
|
@@ -3205,6 +3451,103 @@ var WorldOrbit = (() => {
|
|
|
3205
3451
|
}
|
|
3206
3452
|
}
|
|
3207
3453
|
}
|
|
3454
|
+
function validateEvent(event, objectMap, diagnostics) {
|
|
3455
|
+
const fieldPrefix = `event.${event.id}`;
|
|
3456
|
+
const referencedIds = /* @__PURE__ */ new Set();
|
|
3457
|
+
if (!event.kind.trim()) {
|
|
3458
|
+
diagnostics.push(error("validate.event.kind.required", `Event "${event.id}" is missing a "kind" value.`, void 0, `${fieldPrefix}.kind`));
|
|
3459
|
+
}
|
|
3460
|
+
if (!event.targetObjectId && event.participantObjectIds.length === 0) {
|
|
3461
|
+
diagnostics.push(error("validate.event.references.required", `Event "${event.id}" must define a "target" or at least one participant.`, void 0, `${fieldPrefix}.participants`));
|
|
3462
|
+
}
|
|
3463
|
+
if (event.targetObjectId) {
|
|
3464
|
+
referencedIds.add(event.targetObjectId);
|
|
3465
|
+
if (!objectMap.has(event.targetObjectId)) {
|
|
3466
|
+
diagnostics.push(error("validate.event.target.unknown", `Unknown event target "${event.targetObjectId}" on "${event.id}".`, void 0, `${fieldPrefix}.target`));
|
|
3467
|
+
}
|
|
3468
|
+
}
|
|
3469
|
+
const seenParticipants = /* @__PURE__ */ new Set();
|
|
3470
|
+
for (const participantId of event.participantObjectIds) {
|
|
3471
|
+
referencedIds.add(participantId);
|
|
3472
|
+
if (seenParticipants.has(participantId)) {
|
|
3473
|
+
diagnostics.push(warn("validate.event.participants.duplicate", `Event "${event.id}" repeats participant "${participantId}".`, void 0, `${fieldPrefix}.participants`));
|
|
3474
|
+
continue;
|
|
3475
|
+
}
|
|
3476
|
+
seenParticipants.add(participantId);
|
|
3477
|
+
if (!objectMap.has(participantId)) {
|
|
3478
|
+
diagnostics.push(error("validate.event.participants.unknown", `Unknown event participant "${participantId}" on "${event.id}".`, void 0, `${fieldPrefix}.participants`));
|
|
3479
|
+
}
|
|
3480
|
+
}
|
|
3481
|
+
if (event.targetObjectId && event.participantObjectIds.length > 0 && !event.participantObjectIds.includes(event.targetObjectId)) {
|
|
3482
|
+
diagnostics.push(warn("validate.event.target.notParticipant", `Event "${event.id}" defines a target outside its participants list.`, void 0, `${fieldPrefix}.target`));
|
|
3483
|
+
}
|
|
3484
|
+
if (event.positions.length === 0) {
|
|
3485
|
+
diagnostics.push(warn("validate.event.positions.missing", `Event "${event.id}" has no positions block and cannot drive a scene snapshot.`, void 0, `${fieldPrefix}.positions`));
|
|
3486
|
+
}
|
|
3487
|
+
if (/(?:^|[-_])(solar-eclipse|lunar-eclipse|transit|occultation)(?:$|[-_])/.test(event.kind) && referencedIds.size < 3) {
|
|
3488
|
+
diagnostics.push(warn("validate.event.kind.participants", `Event "${event.id}" looks like an eclipse or transit but references fewer than three bodies.`, void 0, `${fieldPrefix}.participants`));
|
|
3489
|
+
}
|
|
3490
|
+
const poseIds = /* @__PURE__ */ new Set();
|
|
3491
|
+
for (const pose of event.positions) {
|
|
3492
|
+
const poseFieldPrefix = `${fieldPrefix}.pose.${pose.objectId}`;
|
|
3493
|
+
if (poseIds.has(pose.objectId)) {
|
|
3494
|
+
diagnostics.push(error("validate.event.pose.duplicate", `Event "${event.id}" defines "${pose.objectId}" more than once in positions.`, void 0, poseFieldPrefix));
|
|
3495
|
+
continue;
|
|
3496
|
+
}
|
|
3497
|
+
poseIds.add(pose.objectId);
|
|
3498
|
+
const object = objectMap.get(pose.objectId);
|
|
3499
|
+
if (!object) {
|
|
3500
|
+
diagnostics.push(error("validate.event.pose.object.unknown", `Unknown event pose object "${pose.objectId}" on "${event.id}".`, void 0, poseFieldPrefix));
|
|
3501
|
+
continue;
|
|
3502
|
+
}
|
|
3503
|
+
if (!referencedIds.has(pose.objectId)) {
|
|
3504
|
+
diagnostics.push(warn("validate.event.pose.unreferenced", `Event pose "${pose.objectId}" on "${event.id}" is not listed in target/participants.`, void 0, poseFieldPrefix));
|
|
3505
|
+
}
|
|
3506
|
+
validateEventPose(pose, object, objectMap, diagnostics, poseFieldPrefix, event.id);
|
|
3507
|
+
}
|
|
3508
|
+
}
|
|
3509
|
+
function validateEventPose(pose, object, objectMap, diagnostics, fieldPrefix, eventId) {
|
|
3510
|
+
const placement = pose.placement;
|
|
3511
|
+
if (!placement) {
|
|
3512
|
+
diagnostics.push(error("validate.event.pose.placement.required", `Event "${eventId}" pose "${pose.objectId}" is missing a placement mode.`, void 0, fieldPrefix));
|
|
3513
|
+
return;
|
|
3514
|
+
}
|
|
3515
|
+
if (placement.mode === "orbit") {
|
|
3516
|
+
if (!objectMap.has(placement.target)) {
|
|
3517
|
+
diagnostics.push(error("validate.event.pose.orbit.target.unknown", `Unknown event orbit target "${placement.target}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.orbit`));
|
|
3518
|
+
}
|
|
3519
|
+
if (placement.distance && placement.semiMajor) {
|
|
3520
|
+
diagnostics.push(error("validate.event.pose.orbit.distanceConflict", `Event "${eventId}" pose "${pose.objectId}" cannot declare both "distance" and "semiMajor".`, void 0, `${fieldPrefix}.distance`));
|
|
3521
|
+
}
|
|
3522
|
+
return;
|
|
3523
|
+
}
|
|
3524
|
+
if (placement.mode === "surface") {
|
|
3525
|
+
const target = objectMap.get(placement.target);
|
|
3526
|
+
if (!target) {
|
|
3527
|
+
diagnostics.push(error("validate.event.pose.surface.target.unknown", `Unknown event surface target "${placement.target}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.surface`));
|
|
3528
|
+
} else if (!SURFACE_TARGET_TYPES2.has(target.type)) {
|
|
3529
|
+
diagnostics.push(error("validate.event.pose.surface.target.invalid", `Event surface target "${placement.target}" on "${eventId}:${pose.objectId}" is not surface-capable.`, void 0, `${fieldPrefix}.surface`));
|
|
3530
|
+
}
|
|
3531
|
+
return;
|
|
3532
|
+
}
|
|
3533
|
+
if (placement.mode === "at") {
|
|
3534
|
+
if (object.type !== "structure" && object.type !== "phenomenon") {
|
|
3535
|
+
diagnostics.push(error("validate.event.pose.at.objectType", `Only structures and phenomena may use "at" placement in events; found "${object.type}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.at`));
|
|
3536
|
+
}
|
|
3537
|
+
const reference = placement.reference;
|
|
3538
|
+
if (reference.kind === "named" && !objectMap.has(reference.name)) {
|
|
3539
|
+
diagnostics.push(error("validate.event.pose.at.target.unknown", `Unknown event at-reference target "${placement.target}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.at`));
|
|
3540
|
+
} else if (reference.kind === "anchor" && !objectMap.has(reference.objectId)) {
|
|
3541
|
+
diagnostics.push(error("validate.event.pose.anchor.target.unknown", `Unknown event anchor target "${reference.objectId}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.at`));
|
|
3542
|
+
} else if (reference.kind === "lagrange") {
|
|
3543
|
+
if (!objectMap.has(reference.primary)) {
|
|
3544
|
+
diagnostics.push(error("validate.event.pose.lagrange.primary.unknown", `Unknown event Lagrange target "${reference.primary}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.at`));
|
|
3545
|
+
} else if (reference.secondary && !objectMap.has(reference.secondary)) {
|
|
3546
|
+
diagnostics.push(error("validate.event.pose.lagrange.secondary.unknown", `Unknown event Lagrange target "${reference.secondary}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.at`));
|
|
3547
|
+
}
|
|
3548
|
+
}
|
|
3549
|
+
}
|
|
3550
|
+
}
|
|
3208
3551
|
function validateAtTarget(object, objectMap, diagnostics) {
|
|
3209
3552
|
const reference = object.placement?.mode === "at" ? object.placement.reference : null;
|
|
3210
3553
|
if (!reference) {
|
|
@@ -3405,6 +3748,21 @@ var WorldOrbit = (() => {
|
|
|
3405
3748
|
});
|
|
3406
3749
|
}
|
|
3407
3750
|
var DRAFT_OBJECT_FIELD_KEYS = new Set(DRAFT_OBJECT_FIELD_SPECS.keys());
|
|
3751
|
+
var EVENT_POSE_FIELD_KEYS = /* @__PURE__ */ new Set([
|
|
3752
|
+
"orbit",
|
|
3753
|
+
"distance",
|
|
3754
|
+
"semiMajor",
|
|
3755
|
+
"eccentricity",
|
|
3756
|
+
"period",
|
|
3757
|
+
"angle",
|
|
3758
|
+
"inclination",
|
|
3759
|
+
"phase",
|
|
3760
|
+
"at",
|
|
3761
|
+
"surface",
|
|
3762
|
+
"free",
|
|
3763
|
+
"inner",
|
|
3764
|
+
"outer"
|
|
3765
|
+
]);
|
|
3408
3766
|
function parseWorldOrbitAtlas(source) {
|
|
3409
3767
|
return parseAtlasSource(source);
|
|
3410
3768
|
}
|
|
@@ -3419,12 +3777,15 @@ var WorldOrbit = (() => {
|
|
|
3419
3777
|
const objectNodes = [];
|
|
3420
3778
|
const groups = [];
|
|
3421
3779
|
const relations = [];
|
|
3780
|
+
const events = [];
|
|
3781
|
+
const eventPoseNodes = /* @__PURE__ */ new Map();
|
|
3422
3782
|
let sawDefaults = false;
|
|
3423
3783
|
let sawAtlas = false;
|
|
3424
3784
|
const viewpointIds = /* @__PURE__ */ new Set();
|
|
3425
3785
|
const annotationIds = /* @__PURE__ */ new Set();
|
|
3426
3786
|
const groupIds = /* @__PURE__ */ new Set();
|
|
3427
3787
|
const relationIds = /* @__PURE__ */ new Set();
|
|
3788
|
+
const eventIds = /* @__PURE__ */ new Set();
|
|
3428
3789
|
for (let index = 0; index < lines.length; index++) {
|
|
3429
3790
|
const rawLine = lines[index];
|
|
3430
3791
|
const lineNumber = index + 1;
|
|
@@ -3455,7 +3816,7 @@ var WorldOrbit = (() => {
|
|
|
3455
3816
|
continue;
|
|
3456
3817
|
}
|
|
3457
3818
|
if (indent === 0) {
|
|
3458
|
-
section = startTopLevelSection(tokens, lineNumber, sourceSchemaVersion, diagnostics, system, objectNodes, groups, relations, viewpointIds, annotationIds, groupIds, relationIds, { sawDefaults, sawAtlas });
|
|
3819
|
+
section = startTopLevelSection(tokens, lineNumber, sourceSchemaVersion, diagnostics, system, objectNodes, groups, relations, events, eventPoseNodes, viewpointIds, annotationIds, groupIds, relationIds, eventIds, { sawDefaults, sawAtlas });
|
|
3459
3820
|
if (section.kind === "system") {
|
|
3460
3821
|
system = section.system;
|
|
3461
3822
|
} else if (section.kind === "defaults") {
|
|
@@ -3474,6 +3835,7 @@ var WorldOrbit = (() => {
|
|
|
3474
3835
|
throw new WorldOrbitError('Missing required atlas schema header "schema 2.0"');
|
|
3475
3836
|
}
|
|
3476
3837
|
const objects = objectNodes.map((node) => normalizeDraftObject(node, sourceSchemaVersion, diagnostics));
|
|
3838
|
+
const normalizedEvents = events.map((event) => normalizeDraftEvent(event, eventPoseNodes.get(event.id) ?? []));
|
|
3477
3839
|
const outputVersion = forcedOutputVersion ?? (sourceSchemaVersion === "2.0-draft" ? "2.0" : sourceSchemaVersion);
|
|
3478
3840
|
const baseDocument = {
|
|
3479
3841
|
format: "worldorbit",
|
|
@@ -3481,6 +3843,7 @@ var WorldOrbit = (() => {
|
|
|
3481
3843
|
system,
|
|
3482
3844
|
groups,
|
|
3483
3845
|
relations,
|
|
3846
|
+
events: normalizedEvents,
|
|
3484
3847
|
objects,
|
|
3485
3848
|
diagnostics
|
|
3486
3849
|
};
|
|
@@ -3516,7 +3879,7 @@ var WorldOrbit = (() => {
|
|
|
3516
3879
|
const version = tokens[1].value.toLowerCase();
|
|
3517
3880
|
return version === "2.1" ? "2.1" : version === "2.0-draft" ? "2.0-draft" : "2.0";
|
|
3518
3881
|
}
|
|
3519
|
-
function startTopLevelSection(tokens, line, sourceSchemaVersion, diagnostics, system, objectNodes, groups, relations, viewpointIds, annotationIds, groupIds, relationIds, flags) {
|
|
3882
|
+
function startTopLevelSection(tokens, line, sourceSchemaVersion, diagnostics, system, objectNodes, groups, relations, events, eventPoseNodes, viewpointIds, annotationIds, groupIds, relationIds, eventIds, flags) {
|
|
3520
3883
|
const keyword = tokens[0]?.value.toLowerCase();
|
|
3521
3884
|
switch (keyword) {
|
|
3522
3885
|
case "system":
|
|
@@ -3553,7 +3916,7 @@ var WorldOrbit = (() => {
|
|
|
3553
3916
|
if (!system) {
|
|
3554
3917
|
throw new WorldOrbitError('Atlas section "viewpoint" requires a preceding system declaration', line, tokens[0].column);
|
|
3555
3918
|
}
|
|
3556
|
-
return startViewpointSection(tokens, line, system, viewpointIds);
|
|
3919
|
+
return startViewpointSection(tokens, line, system, viewpointIds, sourceSchemaVersion, diagnostics);
|
|
3557
3920
|
case "annotation":
|
|
3558
3921
|
if (!system) {
|
|
3559
3922
|
throw new WorldOrbitError('Atlas section "annotation" requires a preceding system declaration', line, tokens[0].column);
|
|
@@ -3565,6 +3928,9 @@ var WorldOrbit = (() => {
|
|
|
3565
3928
|
case "relation":
|
|
3566
3929
|
warnIfSchema21Feature(sourceSchemaVersion, diagnostics, "relation", { line, column: tokens[0].column });
|
|
3567
3930
|
return startRelationSection(tokens, line, relations, relationIds);
|
|
3931
|
+
case "event":
|
|
3932
|
+
warnIfSchema21Feature(sourceSchemaVersion, diagnostics, "event", { line, column: tokens[0].column });
|
|
3933
|
+
return startEventSection(tokens, line, events, eventPoseNodes, eventIds, sourceSchemaVersion, diagnostics);
|
|
3568
3934
|
case "object":
|
|
3569
3935
|
return startObjectSection(tokens, line, sourceSchemaVersion, diagnostics, objectNodes);
|
|
3570
3936
|
default:
|
|
@@ -3601,7 +3967,7 @@ var WorldOrbit = (() => {
|
|
|
3601
3967
|
seenFields: /* @__PURE__ */ new Set()
|
|
3602
3968
|
};
|
|
3603
3969
|
}
|
|
3604
|
-
function startViewpointSection(tokens, line, system, viewpointIds) {
|
|
3970
|
+
function startViewpointSection(tokens, line, system, viewpointIds, sourceSchemaVersion, diagnostics) {
|
|
3605
3971
|
if (tokens.length !== 2) {
|
|
3606
3972
|
throw new WorldOrbitError("Invalid viewpoint declaration", line, tokens[0]?.column ?? 1);
|
|
3607
3973
|
}
|
|
@@ -3618,6 +3984,7 @@ var WorldOrbit = (() => {
|
|
|
3618
3984
|
summary: "",
|
|
3619
3985
|
focusObjectId: null,
|
|
3620
3986
|
selectedObjectId: null,
|
|
3987
|
+
events: [],
|
|
3621
3988
|
projection: system.defaults.view,
|
|
3622
3989
|
preset: system.defaults.preset,
|
|
3623
3990
|
zoom: null,
|
|
@@ -3630,6 +3997,8 @@ var WorldOrbit = (() => {
|
|
|
3630
3997
|
return {
|
|
3631
3998
|
kind: "viewpoint",
|
|
3632
3999
|
viewpoint,
|
|
4000
|
+
sourceSchemaVersion,
|
|
4001
|
+
diagnostics,
|
|
3633
4002
|
seenFields: /* @__PURE__ */ new Set(),
|
|
3634
4003
|
inFilter: false,
|
|
3635
4004
|
filterIndent: null,
|
|
@@ -3720,6 +4089,49 @@ var WorldOrbit = (() => {
|
|
|
3720
4089
|
seenFields: /* @__PURE__ */ new Set()
|
|
3721
4090
|
};
|
|
3722
4091
|
}
|
|
4092
|
+
function startEventSection(tokens, line, events, eventPoseNodes, eventIds, sourceSchemaVersion, diagnostics) {
|
|
4093
|
+
if (tokens.length !== 2) {
|
|
4094
|
+
throw new WorldOrbitError("Invalid event declaration", line, tokens[0]?.column ?? 1);
|
|
4095
|
+
}
|
|
4096
|
+
const id = normalizeIdentifier(tokens[1].value);
|
|
4097
|
+
if (!id) {
|
|
4098
|
+
throw new WorldOrbitError("Event id must not be empty", line, tokens[1].column);
|
|
4099
|
+
}
|
|
4100
|
+
if (eventIds.has(id)) {
|
|
4101
|
+
throw new WorldOrbitError(`Duplicate event id "${id}"`, line, tokens[1].column);
|
|
4102
|
+
}
|
|
4103
|
+
const event = {
|
|
4104
|
+
id,
|
|
4105
|
+
kind: "",
|
|
4106
|
+
label: humanizeIdentifier2(id),
|
|
4107
|
+
summary: null,
|
|
4108
|
+
targetObjectId: null,
|
|
4109
|
+
participantObjectIds: [],
|
|
4110
|
+
timing: null,
|
|
4111
|
+
visibility: null,
|
|
4112
|
+
tags: [],
|
|
4113
|
+
color: null,
|
|
4114
|
+
hidden: false,
|
|
4115
|
+
positions: []
|
|
4116
|
+
};
|
|
4117
|
+
const rawPoses = [];
|
|
4118
|
+
events.push(event);
|
|
4119
|
+
eventPoseNodes.set(id, rawPoses);
|
|
4120
|
+
eventIds.add(id);
|
|
4121
|
+
return {
|
|
4122
|
+
kind: "event",
|
|
4123
|
+
event,
|
|
4124
|
+
sourceSchemaVersion,
|
|
4125
|
+
diagnostics,
|
|
4126
|
+
seenFields: /* @__PURE__ */ new Set(),
|
|
4127
|
+
rawPoses,
|
|
4128
|
+
inPositions: false,
|
|
4129
|
+
positionsIndent: null,
|
|
4130
|
+
activePose: null,
|
|
4131
|
+
poseIndent: null,
|
|
4132
|
+
activePoseSeenFields: /* @__PURE__ */ new Set()
|
|
4133
|
+
};
|
|
4134
|
+
}
|
|
3723
4135
|
function startObjectSection(tokens, line, sourceSchemaVersion, diagnostics, objectNodes) {
|
|
3724
4136
|
if (tokens.length < 3) {
|
|
3725
4137
|
throw new WorldOrbitError("Invalid atlas object declaration", line, tokens[0]?.column ?? 1);
|
|
@@ -3776,6 +4188,9 @@ var WorldOrbit = (() => {
|
|
|
3776
4188
|
case "relation":
|
|
3777
4189
|
applyRelationField(section, tokens, line);
|
|
3778
4190
|
return;
|
|
4191
|
+
case "event":
|
|
4192
|
+
applyEventField(section, indent, tokens, line);
|
|
4193
|
+
return;
|
|
3779
4194
|
case "object":
|
|
3780
4195
|
applyObjectField(section, indent, tokens, line);
|
|
3781
4196
|
return;
|
|
@@ -3902,7 +4317,14 @@ var WorldOrbit = (() => {
|
|
|
3902
4317
|
section.viewpoint.rotationDeg = parseFiniteNumber2(value, line, tokens[0].column, "rotation");
|
|
3903
4318
|
return;
|
|
3904
4319
|
case "layers":
|
|
3905
|
-
section.viewpoint.layers = parseLayerTokens(tokens.slice(1), line);
|
|
4320
|
+
section.viewpoint.layers = parseLayerTokens(tokens.slice(1), line, section.sourceSchemaVersion, section.diagnostics);
|
|
4321
|
+
return;
|
|
4322
|
+
case "events":
|
|
4323
|
+
warnIfSchema21Feature(section.sourceSchemaVersion, section.diagnostics, "viewpoint.events", {
|
|
4324
|
+
line,
|
|
4325
|
+
column: tokens[0].column
|
|
4326
|
+
});
|
|
4327
|
+
section.viewpoint.events = parseTokenList(tokens.slice(1), line, "events");
|
|
3906
4328
|
return;
|
|
3907
4329
|
default:
|
|
3908
4330
|
throw new WorldOrbitError(`Unknown viewpoint field "${tokens[0].value}"`, line, tokens[0].column);
|
|
@@ -4007,6 +4429,106 @@ var WorldOrbit = (() => {
|
|
|
4007
4429
|
throw new WorldOrbitError(`Unknown relation field "${tokens[0].value}"`, line, tokens[0].column);
|
|
4008
4430
|
}
|
|
4009
4431
|
}
|
|
4432
|
+
function applyEventField(section, indent, tokens, line) {
|
|
4433
|
+
if (section.activePose && indent <= (section.poseIndent ?? 0)) {
|
|
4434
|
+
section.activePose = null;
|
|
4435
|
+
section.poseIndent = null;
|
|
4436
|
+
section.activePoseSeenFields.clear();
|
|
4437
|
+
}
|
|
4438
|
+
if (!section.activePose && section.inPositions && indent <= (section.positionsIndent ?? 0)) {
|
|
4439
|
+
section.inPositions = false;
|
|
4440
|
+
section.positionsIndent = null;
|
|
4441
|
+
}
|
|
4442
|
+
if (section.activePose) {
|
|
4443
|
+
section.activePose.fields.push(parseEventPoseField(tokens, line, section.activePoseSeenFields));
|
|
4444
|
+
return;
|
|
4445
|
+
}
|
|
4446
|
+
if (section.inPositions) {
|
|
4447
|
+
if (tokens.length !== 2 || tokens[0].value.toLowerCase() !== "pose") {
|
|
4448
|
+
throw new WorldOrbitError(`Unknown event positions field "${tokens[0].value}"`, line, tokens[0]?.column ?? 1);
|
|
4449
|
+
}
|
|
4450
|
+
const objectId = tokens[1].value;
|
|
4451
|
+
if (!objectId.trim()) {
|
|
4452
|
+
throw new WorldOrbitError("Event pose object id must not be empty", line, tokens[1].column);
|
|
4453
|
+
}
|
|
4454
|
+
const rawPose = {
|
|
4455
|
+
objectId,
|
|
4456
|
+
fields: [],
|
|
4457
|
+
location: { line, column: tokens[0].column }
|
|
4458
|
+
};
|
|
4459
|
+
section.rawPoses.push(rawPose);
|
|
4460
|
+
section.activePose = rawPose;
|
|
4461
|
+
section.poseIndent = indent;
|
|
4462
|
+
section.activePoseSeenFields = /* @__PURE__ */ new Set();
|
|
4463
|
+
return;
|
|
4464
|
+
}
|
|
4465
|
+
if (tokens.length === 1 && tokens[0].value.toLowerCase() === "positions") {
|
|
4466
|
+
if (section.seenFields.has("positions")) {
|
|
4467
|
+
throw new WorldOrbitError('Duplicate event field "positions"', line, tokens[0].column);
|
|
4468
|
+
}
|
|
4469
|
+
section.seenFields.add("positions");
|
|
4470
|
+
section.inPositions = true;
|
|
4471
|
+
section.positionsIndent = indent;
|
|
4472
|
+
return;
|
|
4473
|
+
}
|
|
4474
|
+
const key = requireUniqueField(tokens, section.seenFields, line);
|
|
4475
|
+
switch (key) {
|
|
4476
|
+
case "kind":
|
|
4477
|
+
section.event.kind = joinFieldValue(tokens, line);
|
|
4478
|
+
return;
|
|
4479
|
+
case "label":
|
|
4480
|
+
section.event.label = joinFieldValue(tokens, line);
|
|
4481
|
+
return;
|
|
4482
|
+
case "summary":
|
|
4483
|
+
section.event.summary = joinFieldValue(tokens, line);
|
|
4484
|
+
return;
|
|
4485
|
+
case "target":
|
|
4486
|
+
section.event.targetObjectId = joinFieldValue(tokens, line);
|
|
4487
|
+
return;
|
|
4488
|
+
case "participants":
|
|
4489
|
+
section.event.participantObjectIds = parseTokenList(tokens.slice(1), line, "participants");
|
|
4490
|
+
return;
|
|
4491
|
+
case "timing":
|
|
4492
|
+
section.event.timing = joinFieldValue(tokens, line);
|
|
4493
|
+
return;
|
|
4494
|
+
case "visibility":
|
|
4495
|
+
section.event.visibility = joinFieldValue(tokens, line);
|
|
4496
|
+
return;
|
|
4497
|
+
case "tags":
|
|
4498
|
+
section.event.tags = parseTokenList(tokens.slice(1), line, "tags");
|
|
4499
|
+
return;
|
|
4500
|
+
case "color":
|
|
4501
|
+
section.event.color = joinFieldValue(tokens, line);
|
|
4502
|
+
return;
|
|
4503
|
+
case "hidden":
|
|
4504
|
+
section.event.hidden = parseAtlasBoolean(joinFieldValue(tokens, line), "hidden", {
|
|
4505
|
+
line,
|
|
4506
|
+
column: tokens[0].column
|
|
4507
|
+
});
|
|
4508
|
+
return;
|
|
4509
|
+
default:
|
|
4510
|
+
throw new WorldOrbitError(`Unknown event field "${tokens[0].value}"`, line, tokens[0].column);
|
|
4511
|
+
}
|
|
4512
|
+
}
|
|
4513
|
+
function parseEventPoseField(tokens, line, seenFields) {
|
|
4514
|
+
if (tokens.length < 2) {
|
|
4515
|
+
throw new WorldOrbitError("Invalid event pose field line", line, tokens[0]?.column ?? 1);
|
|
4516
|
+
}
|
|
4517
|
+
const key = tokens[0].value;
|
|
4518
|
+
if (!EVENT_POSE_FIELD_KEYS.has(key)) {
|
|
4519
|
+
throw new WorldOrbitError(`Unknown event pose field "${key}"`, line, tokens[0].column);
|
|
4520
|
+
}
|
|
4521
|
+
if (seenFields.has(key)) {
|
|
4522
|
+
throw new WorldOrbitError(`Duplicate event pose field "${key}"`, line, tokens[0].column);
|
|
4523
|
+
}
|
|
4524
|
+
seenFields.add(key);
|
|
4525
|
+
return {
|
|
4526
|
+
type: "field",
|
|
4527
|
+
key,
|
|
4528
|
+
values: tokens.slice(1).map((token) => token.value),
|
|
4529
|
+
location: { line, column: tokens[0].column }
|
|
4530
|
+
};
|
|
4531
|
+
}
|
|
4010
4532
|
function applyObjectField(section, indent, tokens, line) {
|
|
4011
4533
|
if (section.activeBlock && indent <= (section.blockIndent ?? 0)) {
|
|
4012
4534
|
section.activeBlock = null;
|
|
@@ -4065,7 +4587,7 @@ var WorldOrbit = (() => {
|
|
|
4065
4587
|
function parseObjectTypeTokens(tokens, line) {
|
|
4066
4588
|
return parseTokenList(tokens, line, "objectTypes").filter((value) => value === "star" || value === "planet" || value === "moon" || value === "belt" || value === "asteroid" || value === "comet" || value === "ring" || value === "structure" || value === "phenomenon");
|
|
4067
4589
|
}
|
|
4068
|
-
function parseLayerTokens(tokens, line) {
|
|
4590
|
+
function parseLayerTokens(tokens, line, sourceSchemaVersion, diagnostics) {
|
|
4069
4591
|
const layers = {};
|
|
4070
4592
|
for (const token of parseTokenList(tokens, line, "layers")) {
|
|
4071
4593
|
const enabled = !token.startsWith("-") && !token.startsWith("!");
|
|
@@ -4075,7 +4597,13 @@ var WorldOrbit = (() => {
|
|
|
4075
4597
|
layers["orbits-front"] = enabled;
|
|
4076
4598
|
continue;
|
|
4077
4599
|
}
|
|
4078
|
-
if (raw === "background" || raw === "guides" || raw === "orbits-back" || raw === "orbits-front" || raw === "relations" || raw === "objects" || raw === "labels" || raw === "metadata") {
|
|
4600
|
+
if (raw === "background" || raw === "guides" || raw === "orbits-back" || raw === "orbits-front" || raw === "relations" || raw === "events" || raw === "objects" || raw === "labels" || raw === "metadata") {
|
|
4601
|
+
if (raw === "events" && sourceSchemaVersion && diagnostics) {
|
|
4602
|
+
warnIfSchema21Feature(sourceSchemaVersion, diagnostics, "layers.events", {
|
|
4603
|
+
line,
|
|
4604
|
+
column: tokens[0]?.column ?? 1
|
|
4605
|
+
});
|
|
4606
|
+
}
|
|
4079
4607
|
layers[raw] = enabled;
|
|
4080
4608
|
}
|
|
4081
4609
|
}
|
|
@@ -4214,7 +4742,7 @@ var WorldOrbit = (() => {
|
|
|
4214
4742
|
}
|
|
4215
4743
|
function normalizeDraftObject(node, sourceSchemaVersion, diagnostics) {
|
|
4216
4744
|
const fieldMap = collectDraftFields(node.fields);
|
|
4217
|
-
const placement =
|
|
4745
|
+
const placement = extractPlacementFromFieldMap(fieldMap);
|
|
4218
4746
|
const properties = normalizeDraftProperties(node.objectType, fieldMap);
|
|
4219
4747
|
const groups = parseOptionalTokenList(fieldMap.get("groups")?.[0]);
|
|
4220
4748
|
const epoch = parseOptionalJoinedValue(fieldMap.get("epoch")?.[0]);
|
|
@@ -4266,6 +4794,24 @@ var WorldOrbit = (() => {
|
|
|
4266
4794
|
}
|
|
4267
4795
|
return object;
|
|
4268
4796
|
}
|
|
4797
|
+
function normalizeDraftEvent(event, rawPoses) {
|
|
4798
|
+
return {
|
|
4799
|
+
...event,
|
|
4800
|
+
participantObjectIds: [...new Set(event.participantObjectIds)],
|
|
4801
|
+
tags: [...new Set(event.tags)],
|
|
4802
|
+
positions: rawPoses.map((pose) => normalizeDraftEventPose(pose))
|
|
4803
|
+
};
|
|
4804
|
+
}
|
|
4805
|
+
function normalizeDraftEventPose(rawPose) {
|
|
4806
|
+
const fieldMap = collectDraftFields(rawPose.fields);
|
|
4807
|
+
const placement = extractPlacementFromFieldMap(fieldMap);
|
|
4808
|
+
return {
|
|
4809
|
+
objectId: rawPose.objectId,
|
|
4810
|
+
placement,
|
|
4811
|
+
inner: parseOptionalUnitField(fieldMap.get("inner")?.[0], "inner"),
|
|
4812
|
+
outer: parseOptionalUnitField(fieldMap.get("outer")?.[0], "outer")
|
|
4813
|
+
};
|
|
4814
|
+
}
|
|
4269
4815
|
function collectDraftFields(fields) {
|
|
4270
4816
|
const grouped = /* @__PURE__ */ new Map();
|
|
4271
4817
|
for (const field of fields) {
|
|
@@ -4282,7 +4828,7 @@ var WorldOrbit = (() => {
|
|
|
4282
4828
|
}
|
|
4283
4829
|
return grouped;
|
|
4284
4830
|
}
|
|
4285
|
-
function
|
|
4831
|
+
function extractPlacementFromFieldMap(fieldMap) {
|
|
4286
4832
|
const orbitField = fieldMap.get("orbit")?.[0];
|
|
4287
4833
|
const atField = fieldMap.get("at")?.[0];
|
|
4288
4834
|
const surfaceField = fieldMap.get("surface")?.[0];
|
|
@@ -4893,6 +5439,7 @@ var WorldOrbit = (() => {
|
|
|
4893
5439
|
const orbitMarkup = layers.orbits ? renderOrbitLayer(scene, visibleObjectIds, layers.structures) : { back: "", front: "" };
|
|
4894
5440
|
const leaderMarkup = layers.guides ? scene.leaders.filter((leader) => !leader.hidden).filter((leader) => visibleObjectIds.has(leader.objectId)).filter((leader) => layers.structures || !isStructureLike(leader.object)).map((leader) => `<line class="wo-leader wo-leader-${leader.mode}" x1="${leader.x1}" y1="${leader.y1}" x2="${leader.x2}" y2="${leader.y2}" data-render-id="${escapeXml(leader.renderId)}" data-group-id="${escapeAttribute(leader.groupId ?? "")}" />`).join("") : "";
|
|
4895
5441
|
const relationMarkup = layers.relations ? scene.relations.filter((relation) => !relation.hidden).filter((relation) => visibleObjectIds.has(relation.fromObjectId) && visibleObjectIds.has(relation.toObjectId)).map((relation) => `<line class="wo-relation" x1="${relation.x1}" y1="${relation.y1}" x2="${relation.x2}" y2="${relation.y2}" data-render-id="${escapeXml(relation.renderId)}" data-relation-id="${escapeAttribute(relation.relationId)}" />`).join("") : "";
|
|
5442
|
+
const eventMarkup = layers.events ? scene.events.filter((event) => !event.hidden).map((event) => renderSceneEventOverlay(scene, event, visibleObjectIds, theme)).join("") : "";
|
|
4896
5443
|
const objectMarkup = layers.objects ? visibleObjects.map((object) => renderSceneObject(object, options.selectedObjectId ?? null, theme)).join("") : "";
|
|
4897
5444
|
const labelMarkup = layers.labels ? visibleLabels.map((label) => renderSceneLabel(scene, label, options.selectedObjectId ?? null)).join("") : "";
|
|
4898
5445
|
const metadataMarkup = layers.metadata ? `<text class="wo-title" x="56" y="64">${escapeXml(scene.title)}</text>
|
|
@@ -4928,6 +5475,9 @@ var WorldOrbit = (() => {
|
|
|
4928
5475
|
.wo-orbit-front { opacity: 0.9; }
|
|
4929
5476
|
.wo-orbit-band { stroke: ${theme.orbitBand}; stroke-linecap: round; }
|
|
4930
5477
|
.wo-relation { stroke: ${theme.relation}; stroke-width: 2; stroke-dasharray: 10 6; }
|
|
5478
|
+
.wo-event-line { stroke: ${theme.accent}; stroke-width: 1.6; stroke-dasharray: 5 5; opacity: 0.72; }
|
|
5479
|
+
.wo-event-node { fill: ${theme.accent}; stroke: ${theme.selected}; stroke-width: 1.4; opacity: 0.92; }
|
|
5480
|
+
.wo-event-label { fill: ${theme.accent}; font-family: ${theme.fontFamily}; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; }
|
|
4931
5481
|
.wo-leader { stroke: ${theme.leader}; stroke-width: 1.5; stroke-dasharray: 6 5; }
|
|
4932
5482
|
.wo-label { fill: ${theme.ink}; font-family: ${theme.fontFamily}; font-weight: 600; letter-spacing: 0.02em; }
|
|
4933
5483
|
.wo-label-secondary { fill: ${theme.muted}; font-family: ${theme.fontFamily}; font-weight: 500; }
|
|
@@ -4962,6 +5512,7 @@ var WorldOrbit = (() => {
|
|
|
4962
5512
|
${layers.orbits ? `<g data-layer-id="orbits-back">${orbitMarkup.back}</g>` : ""}
|
|
4963
5513
|
${layers.guides ? `<g data-layer-id="guides">${leaderMarkup}</g>` : ""}
|
|
4964
5514
|
${layers.relations ? `<g data-layer-id="relations">${relationMarkup}</g>` : ""}
|
|
5515
|
+
${layers.events ? `<g data-layer-id="events">${eventMarkup}</g>` : ""}
|
|
4965
5516
|
${layers.objects ? `<g data-layer-id="objects">${objectMarkup}</g>` : ""}
|
|
4966
5517
|
${layers.orbits ? `<g data-layer-id="orbits-front">${orbitMarkup.front}</g>` : ""}
|
|
4967
5518
|
${layers.labels ? `<g data-layer-id="labels">${labelMarkup}</g>` : ""}
|
|
@@ -4969,6 +5520,20 @@ var WorldOrbit = (() => {
|
|
|
4969
5520
|
</g>
|
|
4970
5521
|
</g>
|
|
4971
5522
|
</svg>`;
|
|
5523
|
+
}
|
|
5524
|
+
function renderSceneEventOverlay(scene, event, visibleObjectIds, theme) {
|
|
5525
|
+
const participants = event.objectIds.filter((objectId) => visibleObjectIds.has(objectId)).map((objectId) => scene.objects.find((object) => object.objectId === objectId && !object.hidden)).filter(Boolean);
|
|
5526
|
+
if (participants.length === 0) {
|
|
5527
|
+
return "";
|
|
5528
|
+
}
|
|
5529
|
+
const stroke = event.event.color || theme.accent;
|
|
5530
|
+
const label = event.event.label || event.event.id;
|
|
5531
|
+
const lineMarkup = participants.map((object) => `<line class="wo-event-line" x1="${event.x}" y1="${event.y}" x2="${object.x}" y2="${object.y}" stroke="${escapeAttribute(stroke)}" data-event-id="${escapeAttribute(event.eventId)}" data-object-id="${escapeAttribute(object.objectId)}" />`).join("");
|
|
5532
|
+
return `<g class="wo-event" data-render-id="${escapeXml(event.renderId)}" data-event-id="${escapeAttribute(event.eventId)}">
|
|
5533
|
+
${lineMarkup}
|
|
5534
|
+
<circle class="wo-event-node" cx="${event.x}" cy="${event.y}" r="5" fill="${escapeAttribute(stroke)}" />
|
|
5535
|
+
<text class="wo-event-label" x="${event.x}" y="${event.y - 10}" text-anchor="middle" font-size="10">${escapeXml(label)}</text>
|
|
5536
|
+
</g>`;
|
|
4972
5537
|
}
|
|
4973
5538
|
function renderDocumentToSvg(document2, options = {}) {
|
|
4974
5539
|
return renderSceneToSvg(renderDocumentToScene(document2, options), options);
|
|
@@ -5568,6 +6133,13 @@ var WorldOrbit = (() => {
|
|
|
5568
6133
|
value: `${details.object.resonance.targetObjectId} ${details.object.resonance.ratio}`
|
|
5569
6134
|
});
|
|
5570
6135
|
}
|
|
6136
|
+
if (details.relatedEvents.length > 0) {
|
|
6137
|
+
fields.set("events", {
|
|
6138
|
+
key: "events",
|
|
6139
|
+
label: "Events",
|
|
6140
|
+
value: details.relatedEvents.map((event) => event.event.label || event.event.id).join(", ")
|
|
6141
|
+
});
|
|
6142
|
+
}
|
|
5571
6143
|
if (placement?.mode === "at") {
|
|
5572
6144
|
fields.set("placement", {
|
|
5573
6145
|
key: "placement",
|
|
@@ -5982,6 +6554,12 @@ var WorldOrbit = (() => {
|
|
|
5982
6554
|
emitAtlasStateChange();
|
|
5983
6555
|
return true;
|
|
5984
6556
|
},
|
|
6557
|
+
getActiveEventId() {
|
|
6558
|
+
return renderOptions.activeEventId ?? null;
|
|
6559
|
+
},
|
|
6560
|
+
setActiveEvent(id) {
|
|
6561
|
+
api.setRenderOptions({ activeEventId: id });
|
|
6562
|
+
},
|
|
5985
6563
|
search(query, limit = 12) {
|
|
5986
6564
|
return searchSceneObjects(scene, query, limit);
|
|
5987
6565
|
},
|
|
@@ -6246,6 +6824,7 @@ var WorldOrbit = (() => {
|
|
|
6246
6824
|
orbit: scene.orbitVisuals.find((orbit) => orbit.objectId === renderObject.objectId && !orbit.hidden) ?? null,
|
|
6247
6825
|
relatedOrbits: scene.orbitVisuals.filter((orbit) => !orbit.hidden && (orbit.objectId === renderObject.objectId || renderObject.ancestorIds.includes(orbit.objectId) || renderObject.childIds.includes(orbit.objectId))),
|
|
6248
6826
|
relations: scene.relations.filter((relation) => !relation.hidden && (relation.fromObjectId === renderObject.objectId || relation.toObjectId === renderObject.objectId)),
|
|
6827
|
+
relatedEvents: scene.events.filter((event) => !event.hidden && (event.targetObjectId === renderObject.objectId || event.objectIds.includes(renderObject.objectId))),
|
|
6249
6828
|
parent: getObjectById(renderObject.parentId),
|
|
6250
6829
|
children: renderObject.childIds.map((childId) => getObjectById(childId)).filter(Boolean),
|
|
6251
6830
|
ancestors: renderObject.ancestorIds.map((ancestorId) => getObjectById(ancestorId)).filter(Boolean),
|
|
@@ -6562,7 +7141,8 @@ var WorldOrbit = (() => {
|
|
|
6562
7141
|
filter: renderOptions.filter ? { ...renderOptions.filter } : void 0,
|
|
6563
7142
|
scaleModel: renderOptions.scaleModel ? { ...renderOptions.scaleModel } : void 0,
|
|
6564
7143
|
layers: renderOptions.layers ? { ...renderOptions.layers } : void 0,
|
|
6565
|
-
theme: renderOptions.theme && typeof renderOptions.theme === "object" ? { ...renderOptions.theme } : renderOptions.theme
|
|
7144
|
+
theme: renderOptions.theme && typeof renderOptions.theme === "object" ? { ...renderOptions.theme } : renderOptions.theme,
|
|
7145
|
+
activeEventId: renderOptions.activeEventId ?? null
|
|
6566
7146
|
};
|
|
6567
7147
|
}
|
|
6568
7148
|
function mergeRenderOptions(current, next) {
|
|
@@ -6582,7 +7162,7 @@ var WorldOrbit = (() => {
|
|
|
6582
7162
|
};
|
|
6583
7163
|
}
|
|
6584
7164
|
function hasSceneAffectingRenderOptions(options) {
|
|
6585
|
-
return options.width !== void 0 || options.height !== void 0 || options.padding !== void 0 || options.preset !== void 0 || options.projection !== void 0 || options.scaleModel !== void 0;
|
|
7165
|
+
return options.width !== void 0 || options.height !== void 0 || options.padding !== void 0 || options.preset !== void 0 || options.projection !== void 0 || options.scaleModel !== void 0 || options.activeEventId !== void 0;
|
|
6586
7166
|
}
|
|
6587
7167
|
function resolveSourceRenderOptions2(loaded, renderOptions) {
|
|
6588
7168
|
const atlasDocument = loaded.atlasDocument ?? loaded.draftDocument;
|
|
@@ -7192,6 +7772,7 @@ var WorldOrbit = (() => {
|
|
|
7192
7772
|
groupCount: activeViewer.getScene().groups.length,
|
|
7193
7773
|
semanticGroupCount: activeViewer.getScene().semanticGroups.length,
|
|
7194
7774
|
relationCount: activeViewer.getScene().relations.length,
|
|
7775
|
+
eventCount: activeViewer.getScene().events.length,
|
|
7195
7776
|
viewpointCount: activeViewer.getScene().viewpoints.length
|
|
7196
7777
|
}
|
|
7197
7778
|
};
|