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
|
@@ -615,6 +615,7 @@ var WorldOrbit = (() => {
|
|
|
615
615
|
system,
|
|
616
616
|
groups: [],
|
|
617
617
|
relations: [],
|
|
618
|
+
events: [],
|
|
618
619
|
objects
|
|
619
620
|
};
|
|
620
621
|
}
|
|
@@ -1072,8 +1073,10 @@ var WorldOrbit = (() => {
|
|
|
1072
1073
|
const scaleModel = resolveScaleModel(layoutPreset, options.scaleModel);
|
|
1073
1074
|
const spacingFactor = layoutPresetSpacing(layoutPreset);
|
|
1074
1075
|
const systemId = document.system?.id ?? null;
|
|
1075
|
-
const
|
|
1076
|
-
const
|
|
1076
|
+
const activeEventId = options.activeEventId ?? null;
|
|
1077
|
+
const effectiveObjects = createEffectiveObjects(document.objects, document.events ?? [], activeEventId);
|
|
1078
|
+
const objectMap = new Map(effectiveObjects.map((object) => [object.id, object]));
|
|
1079
|
+
const relationships = buildSceneRelationships(effectiveObjects, objectMap);
|
|
1077
1080
|
const positions = /* @__PURE__ */ new Map();
|
|
1078
1081
|
const orbitDrafts = [];
|
|
1079
1082
|
const leaderDrafts = [];
|
|
@@ -1082,7 +1085,7 @@ var WorldOrbit = (() => {
|
|
|
1082
1085
|
const atObjects = [];
|
|
1083
1086
|
const surfaceChildren = /* @__PURE__ */ new Map();
|
|
1084
1087
|
const orbitChildren = /* @__PURE__ */ new Map();
|
|
1085
|
-
for (const object of
|
|
1088
|
+
for (const object of effectiveObjects) {
|
|
1086
1089
|
const placement = object.placement;
|
|
1087
1090
|
if (!placement) {
|
|
1088
1091
|
rootObjects.push(object);
|
|
@@ -1177,13 +1180,14 @@ var WorldOrbit = (() => {
|
|
|
1177
1180
|
const objects = [...positions.values()].map((position) => createSceneObject(position, scaleModel, relationships));
|
|
1178
1181
|
const orbitVisuals = orbitDrafts.map((draft) => createOrbitVisual(draft, relationships.groupIds.get(draft.object.id) ?? null));
|
|
1179
1182
|
const leaders = leaderDrafts.map((draft) => createLeaderLine(draft));
|
|
1180
|
-
const labels = createSceneLabels(objects, height, scaleModel.labelMultiplier);
|
|
1183
|
+
const labels = createSceneLabels(objects, width, height, scaleModel.labelMultiplier);
|
|
1181
1184
|
const relations = createSceneRelations(document, objects);
|
|
1182
|
-
const
|
|
1183
|
-
const
|
|
1185
|
+
const events = createSceneEvents(document.events ?? [], objects, activeEventId);
|
|
1186
|
+
const layers = createSceneLayers(orbitVisuals, relations, events, leaders, objects, labels);
|
|
1187
|
+
const groups = createSceneGroups(objects, orbitVisuals, leaders, labels, relationships, scaleModel.labelMultiplier);
|
|
1184
1188
|
const semanticGroups = createSceneSemanticGroups(document, objects);
|
|
1185
1189
|
const viewpoints = createSceneViewpoints(document, projection, frame.preset, relationships, objectMap);
|
|
1186
|
-
const contentBounds = calculateContentBounds(width, height, objects, orbitVisuals, leaders, labels);
|
|
1190
|
+
const contentBounds = calculateContentBounds(width, height, objects, orbitVisuals, leaders, labels, scaleModel.labelMultiplier);
|
|
1187
1191
|
return {
|
|
1188
1192
|
width,
|
|
1189
1193
|
height,
|
|
@@ -1209,6 +1213,8 @@ var WorldOrbit = (() => {
|
|
|
1209
1213
|
groups,
|
|
1210
1214
|
semanticGroups,
|
|
1211
1215
|
viewpoints,
|
|
1216
|
+
events,
|
|
1217
|
+
activeEventId,
|
|
1212
1218
|
objects,
|
|
1213
1219
|
orbitVisuals,
|
|
1214
1220
|
relations,
|
|
@@ -1227,6 +1233,35 @@ var WorldOrbit = (() => {
|
|
|
1227
1233
|
y: center.y + dx * sin + dy * cos
|
|
1228
1234
|
};
|
|
1229
1235
|
}
|
|
1236
|
+
function createEffectiveObjects(objects, events, activeEventId) {
|
|
1237
|
+
const cloned = objects.map((object) => structuredClone(object));
|
|
1238
|
+
if (!activeEventId) {
|
|
1239
|
+
return cloned;
|
|
1240
|
+
}
|
|
1241
|
+
const activeEvent = events.find((event) => event.id === activeEventId);
|
|
1242
|
+
if (!activeEvent) {
|
|
1243
|
+
return cloned;
|
|
1244
|
+
}
|
|
1245
|
+
const objectMap = new Map(cloned.map((object) => [object.id, object]));
|
|
1246
|
+
for (const pose of activeEvent.positions) {
|
|
1247
|
+
const object = objectMap.get(pose.objectId);
|
|
1248
|
+
if (!object) {
|
|
1249
|
+
continue;
|
|
1250
|
+
}
|
|
1251
|
+
object.placement = pose.placement ? structuredClone(pose.placement) : null;
|
|
1252
|
+
if (pose.inner) {
|
|
1253
|
+
object.properties.inner = { ...pose.inner };
|
|
1254
|
+
} else {
|
|
1255
|
+
delete object.properties.inner;
|
|
1256
|
+
}
|
|
1257
|
+
if (pose.outer) {
|
|
1258
|
+
object.properties.outer = { ...pose.outer };
|
|
1259
|
+
} else {
|
|
1260
|
+
delete object.properties.outer;
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
return cloned;
|
|
1264
|
+
}
|
|
1230
1265
|
function resolveLayoutPreset(document) {
|
|
1231
1266
|
const rawScale = String(document.system?.properties.scale ?? "balanced").toLowerCase();
|
|
1232
1267
|
switch (rawScale) {
|
|
@@ -1382,24 +1417,14 @@ var WorldOrbit = (() => {
|
|
|
1382
1417
|
hidden: draft.object.properties.hidden === true
|
|
1383
1418
|
};
|
|
1384
1419
|
}
|
|
1385
|
-
function createSceneLabels(objects, sceneHeight, labelMultiplier) {
|
|
1420
|
+
function createSceneLabels(objects, sceneWidth, sceneHeight, labelMultiplier) {
|
|
1386
1421
|
const labels = [];
|
|
1387
1422
|
const occupied = [];
|
|
1388
|
-
const
|
|
1423
|
+
const objectMap = new Map(objects.map((object) => [object.objectId, object]));
|
|
1424
|
+
const visibleObjects = [...objects].filter((object) => !object.hidden && object.object.renderHints?.renderLabel !== false).sort(compareLabelPlacementOrder);
|
|
1389
1425
|
for (const object of visibleObjects) {
|
|
1390
|
-
const
|
|
1391
|
-
|
|
1392
|
-
let labelY = object.y + direction * (object.radius + 18 * labelMultiplier);
|
|
1393
|
-
let secondaryY = labelY + direction * (16 * labelMultiplier);
|
|
1394
|
-
let bounds = createLabelRect(object.x, labelY, secondaryY, labelHalfWidth, direction);
|
|
1395
|
-
let attempts = 0;
|
|
1396
|
-
while (occupied.some((entry) => rectsOverlap(entry, bounds)) && attempts < 10) {
|
|
1397
|
-
labelY += direction * 14 * labelMultiplier;
|
|
1398
|
-
secondaryY += direction * 14 * labelMultiplier;
|
|
1399
|
-
bounds = createLabelRect(object.x, labelY, secondaryY, labelHalfWidth, direction);
|
|
1400
|
-
attempts += 1;
|
|
1401
|
-
}
|
|
1402
|
-
occupied.push(bounds);
|
|
1426
|
+
const placement = selectLabelPlacement(object, objectMap, occupied, sceneWidth, sceneHeight, labelMultiplier) ?? createLabelPlacement(object, defaultVerticalDirection(object, objectMap.get(object.parentId ?? "") ?? null, sceneHeight), 0, labelMultiplier);
|
|
1427
|
+
occupied.push(createLabelRect(object, placement, labelMultiplier));
|
|
1403
1428
|
labels.push({
|
|
1404
1429
|
renderId: `${object.renderId}-label`,
|
|
1405
1430
|
objectId: object.objectId,
|
|
@@ -1408,17 +1433,128 @@ var WorldOrbit = (() => {
|
|
|
1408
1433
|
semanticGroupIds: [...object.semanticGroupIds],
|
|
1409
1434
|
label: object.label,
|
|
1410
1435
|
secondaryLabel: object.secondaryLabel,
|
|
1411
|
-
x:
|
|
1412
|
-
y: labelY,
|
|
1413
|
-
secondaryY,
|
|
1414
|
-
textAnchor:
|
|
1415
|
-
direction: direction
|
|
1436
|
+
x: placement.x,
|
|
1437
|
+
y: placement.labelY,
|
|
1438
|
+
secondaryY: placement.secondaryY,
|
|
1439
|
+
textAnchor: placement.textAnchor,
|
|
1440
|
+
direction: placement.direction,
|
|
1416
1441
|
hidden: object.hidden
|
|
1417
1442
|
});
|
|
1418
1443
|
}
|
|
1419
1444
|
return labels;
|
|
1420
1445
|
}
|
|
1421
|
-
function
|
|
1446
|
+
function compareLabelPlacementOrder(left, right) {
|
|
1447
|
+
const priorityDiff = labelPlacementPriority(left) - labelPlacementPriority(right);
|
|
1448
|
+
if (priorityDiff !== 0) {
|
|
1449
|
+
return priorityDiff;
|
|
1450
|
+
}
|
|
1451
|
+
const renderPriorityDiff = (right.object.renderHints?.renderPriority ?? 0) - (left.object.renderHints?.renderPriority ?? 0);
|
|
1452
|
+
if (renderPriorityDiff !== 0) {
|
|
1453
|
+
return renderPriorityDiff;
|
|
1454
|
+
}
|
|
1455
|
+
return left.sortKey - right.sortKey;
|
|
1456
|
+
}
|
|
1457
|
+
function labelPlacementPriority(object) {
|
|
1458
|
+
switch (object.object.type) {
|
|
1459
|
+
case "star":
|
|
1460
|
+
return 0;
|
|
1461
|
+
case "planet":
|
|
1462
|
+
return 1;
|
|
1463
|
+
case "moon":
|
|
1464
|
+
return 2;
|
|
1465
|
+
case "belt":
|
|
1466
|
+
case "ring":
|
|
1467
|
+
return 3;
|
|
1468
|
+
case "asteroid":
|
|
1469
|
+
case "comet":
|
|
1470
|
+
return 4;
|
|
1471
|
+
case "structure":
|
|
1472
|
+
case "phenomenon":
|
|
1473
|
+
return 5;
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
function selectLabelPlacement(object, objectMap, occupied, sceneWidth, sceneHeight, labelMultiplier) {
|
|
1477
|
+
for (const direction of preferredLabelDirections(object, objectMap, sceneWidth, sceneHeight)) {
|
|
1478
|
+
const maxAttempts = direction === "left" || direction === "right" ? 4 : 6;
|
|
1479
|
+
for (let attempt = 0; attempt <= maxAttempts; attempt += 1) {
|
|
1480
|
+
const placement = createLabelPlacement(object, direction, attempt, labelMultiplier);
|
|
1481
|
+
const rect = createLabelRect(object, placement, labelMultiplier);
|
|
1482
|
+
if (!occupied.some((entry) => rectsOverlap(entry, rect))) {
|
|
1483
|
+
return placement;
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
return null;
|
|
1488
|
+
}
|
|
1489
|
+
function preferredLabelDirections(object, objectMap, sceneWidth, sceneHeight) {
|
|
1490
|
+
const parent = object.parentId ? objectMap.get(object.parentId) ?? null : null;
|
|
1491
|
+
const vertical = defaultVerticalDirection(object, parent, sceneHeight);
|
|
1492
|
+
const oppositeVertical = vertical === "below" ? "above" : "below";
|
|
1493
|
+
const horizontal = defaultHorizontalDirection(object, parent, sceneWidth);
|
|
1494
|
+
const oppositeHorizontal = horizontal === "right" ? "left" : "right";
|
|
1495
|
+
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";
|
|
1496
|
+
return preferHorizontal ? [horizontal, vertical, oppositeHorizontal, oppositeVertical] : [vertical, horizontal, oppositeVertical, oppositeHorizontal];
|
|
1497
|
+
}
|
|
1498
|
+
function defaultVerticalDirection(object, parent, sceneHeight) {
|
|
1499
|
+
if (parent && Math.abs(object.y - parent.y) > 6) {
|
|
1500
|
+
return object.y >= parent.y ? "below" : "above";
|
|
1501
|
+
}
|
|
1502
|
+
return object.y > sceneHeight * 0.62 ? "above" : "below";
|
|
1503
|
+
}
|
|
1504
|
+
function defaultHorizontalDirection(object, parent, sceneWidth) {
|
|
1505
|
+
if (parent && Math.abs(object.x - parent.x) > 6) {
|
|
1506
|
+
return object.x >= parent.x ? "right" : "left";
|
|
1507
|
+
}
|
|
1508
|
+
return object.x >= sceneWidth / 2 ? "right" : "left";
|
|
1509
|
+
}
|
|
1510
|
+
function createLabelPlacement(object, direction, attempt, labelMultiplier) {
|
|
1511
|
+
const step = 14 * labelMultiplier;
|
|
1512
|
+
switch (direction) {
|
|
1513
|
+
case "above": {
|
|
1514
|
+
const labelY = object.y - (object.radius + 18 * labelMultiplier + attempt * step);
|
|
1515
|
+
return {
|
|
1516
|
+
x: object.x,
|
|
1517
|
+
labelY,
|
|
1518
|
+
secondaryY: labelY - 16 * labelMultiplier,
|
|
1519
|
+
textAnchor: "middle",
|
|
1520
|
+
direction
|
|
1521
|
+
};
|
|
1522
|
+
}
|
|
1523
|
+
case "below": {
|
|
1524
|
+
const labelY = object.y + object.radius + 18 * labelMultiplier + attempt * step;
|
|
1525
|
+
return {
|
|
1526
|
+
x: object.x,
|
|
1527
|
+
labelY,
|
|
1528
|
+
secondaryY: labelY + 16 * labelMultiplier,
|
|
1529
|
+
textAnchor: "middle",
|
|
1530
|
+
direction
|
|
1531
|
+
};
|
|
1532
|
+
}
|
|
1533
|
+
case "left": {
|
|
1534
|
+
const x = object.x - (object.visualRadius + 16 * labelMultiplier + attempt * step);
|
|
1535
|
+
const labelY = object.y - 4 * labelMultiplier;
|
|
1536
|
+
return {
|
|
1537
|
+
x,
|
|
1538
|
+
labelY,
|
|
1539
|
+
secondaryY: labelY + 16 * labelMultiplier,
|
|
1540
|
+
textAnchor: "end",
|
|
1541
|
+
direction
|
|
1542
|
+
};
|
|
1543
|
+
}
|
|
1544
|
+
case "right": {
|
|
1545
|
+
const x = object.x + object.visualRadius + 16 * labelMultiplier + attempt * step;
|
|
1546
|
+
const labelY = object.y - 4 * labelMultiplier;
|
|
1547
|
+
return {
|
|
1548
|
+
x,
|
|
1549
|
+
labelY,
|
|
1550
|
+
secondaryY: labelY + 16 * labelMultiplier,
|
|
1551
|
+
textAnchor: "start",
|
|
1552
|
+
direction
|
|
1553
|
+
};
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
function createSceneLayers(orbitVisuals, relations, events, leaders, objects, labels) {
|
|
1422
1558
|
const backOrbitIds = orbitVisuals.filter((visual) => !visual.hidden && Boolean(visual.backArcPath)).map((visual) => visual.renderId);
|
|
1423
1559
|
const frontOrbitIds = orbitVisuals.filter((visual) => !visual.hidden).map((visual) => visual.renderId);
|
|
1424
1560
|
return [
|
|
@@ -1433,6 +1569,10 @@ var WorldOrbit = (() => {
|
|
|
1433
1569
|
id: "relations",
|
|
1434
1570
|
renderIds: relations.filter((relation) => !relation.hidden).map((relation) => relation.renderId)
|
|
1435
1571
|
},
|
|
1572
|
+
{
|
|
1573
|
+
id: "events",
|
|
1574
|
+
renderIds: events.filter((event) => !event.hidden).map((event) => event.renderId)
|
|
1575
|
+
},
|
|
1436
1576
|
{
|
|
1437
1577
|
id: "objects",
|
|
1438
1578
|
renderIds: objects.filter((object) => !object.hidden).map((object) => object.renderId)
|
|
@@ -1444,7 +1584,7 @@ var WorldOrbit = (() => {
|
|
|
1444
1584
|
{ id: "metadata", renderIds: ["wo-title", "wo-subtitle", "wo-meta"] }
|
|
1445
1585
|
];
|
|
1446
1586
|
}
|
|
1447
|
-
function createSceneGroups(objects, orbitVisuals, leaders, labels, relationships) {
|
|
1587
|
+
function createSceneGroups(objects, orbitVisuals, leaders, labels, relationships, labelMultiplier) {
|
|
1448
1588
|
const groups = /* @__PURE__ */ new Map();
|
|
1449
1589
|
const ensureGroup = (groupId) => {
|
|
1450
1590
|
if (!groupId) {
|
|
@@ -1493,7 +1633,7 @@ var WorldOrbit = (() => {
|
|
|
1493
1633
|
}
|
|
1494
1634
|
}
|
|
1495
1635
|
for (const group of groups.values()) {
|
|
1496
|
-
group.contentBounds = calculateGroupBounds(group, objects, orbitVisuals, leaders, labels);
|
|
1636
|
+
group.contentBounds = calculateGroupBounds(group, objects, orbitVisuals, leaders, labels, labelMultiplier);
|
|
1497
1637
|
}
|
|
1498
1638
|
return [...groups.values()].sort((left, right) => left.label.localeCompare(right.label));
|
|
1499
1639
|
}
|
|
@@ -1527,6 +1667,29 @@ var WorldOrbit = (() => {
|
|
|
1527
1667
|
};
|
|
1528
1668
|
}).sort((left, right) => left.relation.id.localeCompare(right.relation.id));
|
|
1529
1669
|
}
|
|
1670
|
+
function createSceneEvents(events, objects, activeEventId) {
|
|
1671
|
+
const objectMap = new Map(objects.map((object) => [object.objectId, object]));
|
|
1672
|
+
return events.map((event) => {
|
|
1673
|
+
const objectIds = [.../* @__PURE__ */ new Set([
|
|
1674
|
+
...event.targetObjectId ? [event.targetObjectId] : [],
|
|
1675
|
+
...event.participantObjectIds
|
|
1676
|
+
])];
|
|
1677
|
+
const positions = objectIds.map((objectId) => objectMap.get(objectId)).filter(Boolean);
|
|
1678
|
+
const centroidX = positions.length > 0 ? positions.reduce((sum, object) => sum + object.x, 0) / positions.length : 0;
|
|
1679
|
+
const centroidY = positions.length > 0 ? positions.reduce((sum, object) => sum + object.y, 0) / positions.length : 0;
|
|
1680
|
+
return {
|
|
1681
|
+
renderId: `${createRenderId(event.id)}-event`,
|
|
1682
|
+
eventId: event.id,
|
|
1683
|
+
event,
|
|
1684
|
+
objectIds,
|
|
1685
|
+
participantIds: [...event.participantObjectIds],
|
|
1686
|
+
targetObjectId: event.targetObjectId,
|
|
1687
|
+
x: centroidX,
|
|
1688
|
+
y: centroidY,
|
|
1689
|
+
hidden: event.hidden || positions.length === 0 || positions.every((object) => object.hidden) || activeEventId !== null && event.id !== activeEventId
|
|
1690
|
+
};
|
|
1691
|
+
}).sort((left, right) => left.event.id.localeCompare(right.event.id));
|
|
1692
|
+
}
|
|
1530
1693
|
function createSceneViewpoints(document, projection, preset, relationships, objectMap) {
|
|
1531
1694
|
const generatedOverview = createGeneratedOverviewViewpoint(document, projection, preset);
|
|
1532
1695
|
const drafts = /* @__PURE__ */ new Map();
|
|
@@ -1580,6 +1743,7 @@ var WorldOrbit = (() => {
|
|
|
1580
1743
|
summary: "Fit the whole system with the current atlas defaults.",
|
|
1581
1744
|
objectId: null,
|
|
1582
1745
|
selectedObjectId: null,
|
|
1746
|
+
eventIds: [],
|
|
1583
1747
|
projection,
|
|
1584
1748
|
preset,
|
|
1585
1749
|
rotationDeg: 0,
|
|
@@ -1616,6 +1780,9 @@ var WorldOrbit = (() => {
|
|
|
1616
1780
|
draft.select = normalizedValue;
|
|
1617
1781
|
}
|
|
1618
1782
|
return;
|
|
1783
|
+
case "events":
|
|
1784
|
+
draft.eventIds = splitListValue(normalizedValue);
|
|
1785
|
+
return;
|
|
1619
1786
|
case "projection":
|
|
1620
1787
|
case "view":
|
|
1621
1788
|
draft.projection = parseViewProjection(normalizedValue) ?? projection;
|
|
@@ -1672,6 +1839,7 @@ var WorldOrbit = (() => {
|
|
|
1672
1839
|
summary: draft.summary?.trim() || createViewpointSummary(label, objectId, filter),
|
|
1673
1840
|
objectId,
|
|
1674
1841
|
selectedObjectId,
|
|
1842
|
+
eventIds: [...new Set(draft.eventIds ?? [])],
|
|
1675
1843
|
projection: draft.projection ?? projection,
|
|
1676
1844
|
preset: draft.preset ?? preset,
|
|
1677
1845
|
rotationDeg: draft.rotationDeg ?? 0,
|
|
@@ -1729,7 +1897,7 @@ var WorldOrbit = (() => {
|
|
|
1729
1897
|
next["orbits-front"] = enabled;
|
|
1730
1898
|
continue;
|
|
1731
1899
|
}
|
|
1732
|
-
if (rawLayer === "background" || rawLayer === "guides" || rawLayer === "orbits-back" || rawLayer === "orbits-front" || rawLayer === "relations" || rawLayer === "objects" || rawLayer === "labels" || rawLayer === "metadata") {
|
|
1900
|
+
if (rawLayer === "background" || rawLayer === "guides" || rawLayer === "orbits-back" || rawLayer === "orbits-front" || rawLayer === "relations" || rawLayer === "events" || rawLayer === "objects" || rawLayer === "labels" || rawLayer === "metadata") {
|
|
1733
1901
|
next[rawLayer] = enabled;
|
|
1734
1902
|
}
|
|
1735
1903
|
}
|
|
@@ -1777,7 +1945,7 @@ var WorldOrbit = (() => {
|
|
|
1777
1945
|
}
|
|
1778
1946
|
return parts.join(" - ");
|
|
1779
1947
|
}
|
|
1780
|
-
function calculateContentBounds(width, height, objects, orbitVisuals, leaders, labels) {
|
|
1948
|
+
function calculateContentBounds(width, height, objects, orbitVisuals, leaders, labels, labelMultiplier) {
|
|
1781
1949
|
let minX = Number.POSITIVE_INFINITY;
|
|
1782
1950
|
let minY = Number.POSITIVE_INFINITY;
|
|
1783
1951
|
let maxX = Number.NEGATIVE_INFINITY;
|
|
@@ -1807,7 +1975,7 @@ var WorldOrbit = (() => {
|
|
|
1807
1975
|
for (const label of labels) {
|
|
1808
1976
|
if (label.hidden)
|
|
1809
1977
|
continue;
|
|
1810
|
-
includeLabelBounds(label, include);
|
|
1978
|
+
includeLabelBounds(label, include, labelMultiplier);
|
|
1811
1979
|
}
|
|
1812
1980
|
if (!Number.isFinite(minX) || !Number.isFinite(minY)) {
|
|
1813
1981
|
return createBounds(0, 0, width, height);
|
|
@@ -1845,13 +2013,10 @@ var WorldOrbit = (() => {
|
|
|
1845
2013
|
include(object.x - object.visualRadius - 24, object.y - object.visualRadius - 16);
|
|
1846
2014
|
include(object.x + object.visualRadius + 24, object.y + object.visualRadius + 36);
|
|
1847
2015
|
}
|
|
1848
|
-
function includeLabelBounds(label, include) {
|
|
1849
|
-
const
|
|
1850
|
-
|
|
1851
|
-
include(
|
|
1852
|
-
include(label.x + labelHalfWidth, label.y + 8);
|
|
1853
|
-
include(label.x - labelHalfWidth, label.secondaryY - 14);
|
|
1854
|
-
include(label.x + labelHalfWidth, label.secondaryY + 8);
|
|
2016
|
+
function includeLabelBounds(label, include, labelMultiplier) {
|
|
2017
|
+
const bounds = createLabelRectFromText(label.x, label.y, label.secondaryY, label.textAnchor, label.direction, label.label, label.secondaryLabel, labelMultiplier);
|
|
2018
|
+
include(bounds.left, bounds.top);
|
|
2019
|
+
include(bounds.right, bounds.bottom);
|
|
1855
2020
|
}
|
|
1856
2021
|
function placeObject(object, x, y, depth, positions, orbitDrafts, leaderDrafts, context) {
|
|
1857
2022
|
if (positions.has(object.id)) {
|
|
@@ -2241,7 +2406,7 @@ var WorldOrbit = (() => {
|
|
|
2241
2406
|
return null;
|
|
2242
2407
|
}
|
|
2243
2408
|
}
|
|
2244
|
-
function calculateGroupBounds(group, objects, orbitVisuals, leaders, labels) {
|
|
2409
|
+
function calculateGroupBounds(group, objects, orbitVisuals, leaders, labels, labelMultiplier) {
|
|
2245
2410
|
let minX = Number.POSITIVE_INFINITY;
|
|
2246
2411
|
let minY = Number.POSITIVE_INFINITY;
|
|
2247
2412
|
let maxX = Number.NEGATIVE_INFINITY;
|
|
@@ -2270,7 +2435,7 @@ var WorldOrbit = (() => {
|
|
|
2270
2435
|
}
|
|
2271
2436
|
for (const label of labels) {
|
|
2272
2437
|
if (!label.hidden && group.labelIds.includes(label.objectId)) {
|
|
2273
|
-
includeLabelBounds(label, include);
|
|
2438
|
+
includeLabelBounds(label, include, labelMultiplier);
|
|
2274
2439
|
}
|
|
2275
2440
|
}
|
|
2276
2441
|
if (!Number.isFinite(minX) || !Number.isFinite(minY)) {
|
|
@@ -2295,12 +2460,28 @@ var WorldOrbit = (() => {
|
|
|
2295
2460
|
}
|
|
2296
2461
|
return current.id;
|
|
2297
2462
|
}
|
|
2298
|
-
function createLabelRect(
|
|
2463
|
+
function createLabelRect(object, placement, labelMultiplier) {
|
|
2464
|
+
return createLabelRectFromText(placement.x, placement.labelY, placement.secondaryY, placement.textAnchor, placement.direction, object.label, object.secondaryLabel, labelMultiplier);
|
|
2465
|
+
}
|
|
2466
|
+
function createLabelRectFromText(x, labelY, secondaryY, textAnchor, direction, label, secondaryLabel, labelMultiplier) {
|
|
2467
|
+
const labelHalfWidth = estimateLabelHalfWidthFromText(label, secondaryLabel, labelMultiplier);
|
|
2468
|
+
const labelWidth = labelHalfWidth * 2;
|
|
2469
|
+
const topPadding = direction === "above" ? 18 : 12;
|
|
2470
|
+
const bottomPadding = direction === "above" ? 8 : 12;
|
|
2471
|
+
let left = x - labelHalfWidth;
|
|
2472
|
+
let right = x + labelHalfWidth;
|
|
2473
|
+
if (textAnchor === "start") {
|
|
2474
|
+
left = x;
|
|
2475
|
+
right = x + labelWidth;
|
|
2476
|
+
} else if (textAnchor === "end") {
|
|
2477
|
+
left = x - labelWidth;
|
|
2478
|
+
right = x;
|
|
2479
|
+
}
|
|
2299
2480
|
return {
|
|
2300
|
-
left
|
|
2301
|
-
right
|
|
2302
|
-
top: Math.min(labelY, secondaryY) -
|
|
2303
|
-
bottom: Math.max(labelY, secondaryY) +
|
|
2481
|
+
left,
|
|
2482
|
+
right,
|
|
2483
|
+
top: Math.min(labelY, secondaryY) - topPadding,
|
|
2484
|
+
bottom: Math.max(labelY, secondaryY) + bottomPadding
|
|
2304
2485
|
};
|
|
2305
2486
|
}
|
|
2306
2487
|
function rectsOverlap(left, right) {
|
|
@@ -2487,11 +2668,6 @@ var WorldOrbit = (() => {
|
|
|
2487
2668
|
function customColorFor(value) {
|
|
2488
2669
|
return typeof value === "string" && value.trim() ? value : void 0;
|
|
2489
2670
|
}
|
|
2490
|
-
function estimateLabelHalfWidth(object, labelMultiplier) {
|
|
2491
|
-
const primaryWidth = object.label.length * 4.6 * labelMultiplier + 18;
|
|
2492
|
-
const secondaryWidth = object.secondaryLabel.length * 3.9 * labelMultiplier + 18;
|
|
2493
|
-
return Math.max(primaryWidth, secondaryWidth, object.visualRadius + 18);
|
|
2494
|
-
}
|
|
2495
2671
|
function estimateLabelHalfWidthFromText(label, secondaryLabel, labelMultiplier) {
|
|
2496
2672
|
const primaryWidth = label.length * 4.6 * labelMultiplier + 18;
|
|
2497
2673
|
const secondaryWidth = secondaryLabel.length * 3.9 * labelMultiplier + 18;
|
|
@@ -2531,6 +2707,7 @@ var WorldOrbit = (() => {
|
|
|
2531
2707
|
system,
|
|
2532
2708
|
groups: structuredClone(document.groups ?? []),
|
|
2533
2709
|
relations: structuredClone(document.relations ?? []),
|
|
2710
|
+
events: structuredClone(document.events ?? []),
|
|
2534
2711
|
objects: document.objects.map(cloneWorldOrbitObject),
|
|
2535
2712
|
diagnostics
|
|
2536
2713
|
};
|
|
@@ -2538,7 +2715,7 @@ var WorldOrbit = (() => {
|
|
|
2538
2715
|
function upgradeDocumentToDraftV2(document, options = {}) {
|
|
2539
2716
|
return convertAtlasDocumentToLegacyDraft(upgradeDocumentToV2(document, options));
|
|
2540
2717
|
}
|
|
2541
|
-
function materializeAtlasDocument(document) {
|
|
2718
|
+
function materializeAtlasDocument(document, options = {}) {
|
|
2542
2719
|
const system = document.system ? {
|
|
2543
2720
|
type: "system",
|
|
2544
2721
|
id: document.system.id,
|
|
@@ -2549,6 +2726,8 @@ var WorldOrbit = (() => {
|
|
|
2549
2726
|
properties: materializeDraftSystemProperties(document.system),
|
|
2550
2727
|
info: materializeDraftSystemInfo(document.system)
|
|
2551
2728
|
} : null;
|
|
2729
|
+
const objects = document.objects.map(cloneWorldOrbitObject);
|
|
2730
|
+
applyEventPoseOverrides(objects, document.events ?? [], options.activeEventId ?? null);
|
|
2552
2731
|
return {
|
|
2553
2732
|
format: "worldorbit",
|
|
2554
2733
|
version: "1.0",
|
|
@@ -2556,7 +2735,8 @@ var WorldOrbit = (() => {
|
|
|
2556
2735
|
system,
|
|
2557
2736
|
groups: structuredClone(document.groups ?? []),
|
|
2558
2737
|
relations: structuredClone(document.relations ?? []),
|
|
2559
|
-
|
|
2738
|
+
events: document.events.map(cloneWorldOrbitEvent),
|
|
2739
|
+
objects
|
|
2560
2740
|
};
|
|
2561
2741
|
}
|
|
2562
2742
|
function materializeDraftDocument(document) {
|
|
@@ -2684,6 +2864,7 @@ var WorldOrbit = (() => {
|
|
|
2684
2864
|
summary: viewpoint.summary,
|
|
2685
2865
|
focusObjectId: viewpoint.objectId,
|
|
2686
2866
|
selectedObjectId: viewpoint.selectedObjectId,
|
|
2867
|
+
events: [...viewpoint.eventIds],
|
|
2687
2868
|
projection: viewpoint.projection,
|
|
2688
2869
|
preset: viewpoint.preset,
|
|
2689
2870
|
zoom: viewpoint.scale,
|
|
@@ -2716,6 +2897,52 @@ var WorldOrbit = (() => {
|
|
|
2716
2897
|
info: { ...object.info }
|
|
2717
2898
|
};
|
|
2718
2899
|
}
|
|
2900
|
+
function cloneWorldOrbitEvent(event) {
|
|
2901
|
+
return {
|
|
2902
|
+
...event,
|
|
2903
|
+
participantObjectIds: [...event.participantObjectIds],
|
|
2904
|
+
tags: [...event.tags],
|
|
2905
|
+
positions: event.positions.map(cloneWorldOrbitEventPose)
|
|
2906
|
+
};
|
|
2907
|
+
}
|
|
2908
|
+
function cloneWorldOrbitEventPose(pose) {
|
|
2909
|
+
return {
|
|
2910
|
+
objectId: pose.objectId,
|
|
2911
|
+
placement: clonePlacement(pose.placement),
|
|
2912
|
+
inner: pose.inner ? { ...pose.inner } : void 0,
|
|
2913
|
+
outer: pose.outer ? { ...pose.outer } : void 0
|
|
2914
|
+
};
|
|
2915
|
+
}
|
|
2916
|
+
function clonePlacement(placement) {
|
|
2917
|
+
return placement ? structuredClone(placement) : null;
|
|
2918
|
+
}
|
|
2919
|
+
function applyEventPoseOverrides(objects, events, activeEventId) {
|
|
2920
|
+
if (!activeEventId) {
|
|
2921
|
+
return;
|
|
2922
|
+
}
|
|
2923
|
+
const event = events.find((entry) => entry.id === activeEventId);
|
|
2924
|
+
if (!event) {
|
|
2925
|
+
return;
|
|
2926
|
+
}
|
|
2927
|
+
const objectMap = new Map(objects.map((object) => [object.id, object]));
|
|
2928
|
+
for (const pose of event.positions) {
|
|
2929
|
+
const object = objectMap.get(pose.objectId);
|
|
2930
|
+
if (!object) {
|
|
2931
|
+
continue;
|
|
2932
|
+
}
|
|
2933
|
+
object.placement = clonePlacement(pose.placement);
|
|
2934
|
+
if (pose.inner) {
|
|
2935
|
+
object.properties.inner = { ...pose.inner };
|
|
2936
|
+
} else {
|
|
2937
|
+
delete object.properties.inner;
|
|
2938
|
+
}
|
|
2939
|
+
if (pose.outer) {
|
|
2940
|
+
object.properties.outer = { ...pose.outer };
|
|
2941
|
+
} else {
|
|
2942
|
+
delete object.properties.outer;
|
|
2943
|
+
}
|
|
2944
|
+
}
|
|
2945
|
+
}
|
|
2719
2946
|
function cloneProperties(properties) {
|
|
2720
2947
|
const next = {};
|
|
2721
2948
|
for (const [key, value] of Object.entries(properties)) {
|
|
@@ -2813,6 +3040,9 @@ var WorldOrbit = (() => {
|
|
|
2813
3040
|
if ((viewpoint.filter?.groupIds.length ?? 0) > 0) {
|
|
2814
3041
|
info2[`${prefix}.groups`] = viewpoint.filter?.groupIds.join(" ") ?? "";
|
|
2815
3042
|
}
|
|
3043
|
+
if (viewpoint.events.length > 0) {
|
|
3044
|
+
info2[`${prefix}.events`] = viewpoint.events.join(" ");
|
|
3045
|
+
}
|
|
2816
3046
|
}
|
|
2817
3047
|
for (const annotation of system.annotations) {
|
|
2818
3048
|
const prefix = `annotation.${annotation.id}`;
|
|
@@ -2837,7 +3067,7 @@ var WorldOrbit = (() => {
|
|
|
2837
3067
|
if (orbitFront !== void 0 || orbitBack !== void 0) {
|
|
2838
3068
|
tokens.push(orbitFront !== false || orbitBack !== false ? "orbits" : "-orbits");
|
|
2839
3069
|
}
|
|
2840
|
-
for (const key of ["background", "guides", "relations", "objects", "labels", "metadata"]) {
|
|
3070
|
+
for (const key of ["background", "guides", "relations", "events", "objects", "labels", "metadata"]) {
|
|
2841
3071
|
if (layers[key] !== void 0) {
|
|
2842
3072
|
tokens.push(layers[key] ? key : `-${key}`);
|
|
2843
3073
|
}
|
|
@@ -2941,6 +3171,10 @@ var WorldOrbit = (() => {
|
|
|
2941
3171
|
lines.push("");
|
|
2942
3172
|
lines.push(...formatAtlasRelation(relation));
|
|
2943
3173
|
}
|
|
3174
|
+
for (const event of [...document.events].sort(compareIdLike)) {
|
|
3175
|
+
lines.push("");
|
|
3176
|
+
lines.push(...formatAtlasEvent(event));
|
|
3177
|
+
}
|
|
2944
3178
|
const sortedObjects = [...document.objects].sort(compareObjects);
|
|
2945
3179
|
if (sortedObjects.length > 0 && lines.at(-1) !== "") {
|
|
2946
3180
|
lines.push("");
|
|
@@ -2971,6 +3205,10 @@ var WorldOrbit = (() => {
|
|
|
2971
3205
|
lines.push("");
|
|
2972
3206
|
lines.push(...formatAtlasRelation(relation));
|
|
2973
3207
|
}
|
|
3208
|
+
for (const event of [...legacy.events].sort(compareIdLike)) {
|
|
3209
|
+
lines.push("");
|
|
3210
|
+
lines.push(...formatAtlasEvent(event));
|
|
3211
|
+
}
|
|
2974
3212
|
const sortedObjects = [...legacy.objects].sort(compareObjects);
|
|
2975
3213
|
if (sortedObjects.length > 0 && lines.at(-1) !== "") {
|
|
2976
3214
|
lines.push("");
|
|
@@ -3182,6 +3420,9 @@ var WorldOrbit = (() => {
|
|
|
3182
3420
|
if (layerTokens.length > 0) {
|
|
3183
3421
|
lines.push(` layers ${layerTokens.join(" ")}`);
|
|
3184
3422
|
}
|
|
3423
|
+
if (viewpoint.events.length > 0) {
|
|
3424
|
+
lines.push(` events ${viewpoint.events.join(" ")}`);
|
|
3425
|
+
}
|
|
3185
3426
|
if (viewpoint.filter) {
|
|
3186
3427
|
lines.push(" filter");
|
|
3187
3428
|
if (viewpoint.filter.query) {
|
|
@@ -3254,6 +3495,54 @@ var WorldOrbit = (() => {
|
|
|
3254
3495
|
}
|
|
3255
3496
|
return lines;
|
|
3256
3497
|
}
|
|
3498
|
+
function formatAtlasEvent(event) {
|
|
3499
|
+
const lines = [`event ${event.id}`, ` kind ${quoteIfNeeded(event.kind)}`];
|
|
3500
|
+
if (event.label) {
|
|
3501
|
+
lines.push(` label ${quoteIfNeeded(event.label)}`);
|
|
3502
|
+
}
|
|
3503
|
+
if (event.summary) {
|
|
3504
|
+
lines.push(` summary ${quoteIfNeeded(event.summary)}`);
|
|
3505
|
+
}
|
|
3506
|
+
if (event.targetObjectId) {
|
|
3507
|
+
lines.push(` target ${event.targetObjectId}`);
|
|
3508
|
+
}
|
|
3509
|
+
if (event.participantObjectIds.length > 0) {
|
|
3510
|
+
lines.push(` participants ${event.participantObjectIds.join(" ")}`);
|
|
3511
|
+
}
|
|
3512
|
+
if (event.timing) {
|
|
3513
|
+
lines.push(` timing ${quoteIfNeeded(event.timing)}`);
|
|
3514
|
+
}
|
|
3515
|
+
if (event.visibility) {
|
|
3516
|
+
lines.push(` visibility ${quoteIfNeeded(event.visibility)}`);
|
|
3517
|
+
}
|
|
3518
|
+
if (event.tags.length > 0) {
|
|
3519
|
+
lines.push(` tags ${event.tags.map(quoteIfNeeded).join(" ")}`);
|
|
3520
|
+
}
|
|
3521
|
+
if (event.color) {
|
|
3522
|
+
lines.push(` color ${quoteIfNeeded(event.color)}`);
|
|
3523
|
+
}
|
|
3524
|
+
if (event.hidden) {
|
|
3525
|
+
lines.push(" hidden true");
|
|
3526
|
+
}
|
|
3527
|
+
if (event.positions.length > 0) {
|
|
3528
|
+
lines.push("");
|
|
3529
|
+
lines.push(" positions");
|
|
3530
|
+
for (const pose of [...event.positions].sort(comparePoseObjectId)) {
|
|
3531
|
+
lines.push(` pose ${pose.objectId}`);
|
|
3532
|
+
for (const fieldLine of formatEventPoseFields(pose)) {
|
|
3533
|
+
lines.push(` ${fieldLine}`);
|
|
3534
|
+
}
|
|
3535
|
+
}
|
|
3536
|
+
}
|
|
3537
|
+
return lines;
|
|
3538
|
+
}
|
|
3539
|
+
function formatEventPoseFields(pose) {
|
|
3540
|
+
return [
|
|
3541
|
+
...formatPlacement(pose.placement),
|
|
3542
|
+
...formatOptionalUnit("inner", pose.inner),
|
|
3543
|
+
...formatOptionalUnit("outer", pose.outer)
|
|
3544
|
+
];
|
|
3545
|
+
}
|
|
3257
3546
|
function formatValue(value) {
|
|
3258
3547
|
if (Array.isArray(value)) {
|
|
3259
3548
|
return value.map((item) => quoteIfNeeded(item)).join(" ");
|
|
@@ -3295,7 +3584,7 @@ var WorldOrbit = (() => {
|
|
|
3295
3584
|
if (orbitFront !== void 0 || orbitBack !== void 0) {
|
|
3296
3585
|
tokens.push(orbitFront !== false || orbitBack !== false ? "orbits" : "-orbits");
|
|
3297
3586
|
}
|
|
3298
|
-
for (const key of ["background", "guides", "relations", "objects", "labels", "metadata"]) {
|
|
3587
|
+
for (const key of ["background", "guides", "relations", "events", "objects", "labels", "metadata"]) {
|
|
3299
3588
|
if (layers[key] !== void 0) {
|
|
3300
3589
|
tokens.push(layers[key] ? key : `-${key}`);
|
|
3301
3590
|
}
|
|
@@ -3323,6 +3612,9 @@ var WorldOrbit = (() => {
|
|
|
3323
3612
|
function compareIdLike(left, right) {
|
|
3324
3613
|
return left.id.localeCompare(right.id);
|
|
3325
3614
|
}
|
|
3615
|
+
function comparePoseObjectId(left, right) {
|
|
3616
|
+
return left.objectId.localeCompare(right.objectId);
|
|
3617
|
+
}
|
|
3326
3618
|
function objectTypeIndex(objectType) {
|
|
3327
3619
|
switch (objectType) {
|
|
3328
3620
|
case "star":
|
|
@@ -3518,6 +3810,7 @@ var WorldOrbit = (() => {
|
|
|
3518
3810
|
const diagnostics = [];
|
|
3519
3811
|
const objectMap = new Map(document.objects.map((object) => [object.id, object]));
|
|
3520
3812
|
const groupIds = new Set(document.groups.map((group) => group.id));
|
|
3813
|
+
const eventIds = new Set(document.events.map((event) => event.id));
|
|
3521
3814
|
if (!document.system) {
|
|
3522
3815
|
diagnostics.push(error("validate.system.required", "Atlas documents must declare exactly one system."));
|
|
3523
3816
|
}
|
|
@@ -3527,6 +3820,7 @@ var WorldOrbit = (() => {
|
|
|
3527
3820
|
["viewpoint", document.system?.viewpoints.map((viewpoint) => viewpoint.id) ?? []],
|
|
3528
3821
|
["annotation", document.system?.annotations.map((annotation) => annotation.id) ?? []],
|
|
3529
3822
|
["relation", document.relations.map((relation) => relation.id)],
|
|
3823
|
+
["event", document.events.map((event) => event.id)],
|
|
3530
3824
|
["object", document.objects.map((object) => object.id)]
|
|
3531
3825
|
]) {
|
|
3532
3826
|
for (const id of ids) {
|
|
@@ -3542,11 +3836,14 @@ var WorldOrbit = (() => {
|
|
|
3542
3836
|
validateRelation(relation, objectMap, diagnostics);
|
|
3543
3837
|
}
|
|
3544
3838
|
for (const viewpoint of document.system?.viewpoints ?? []) {
|
|
3545
|
-
|
|
3839
|
+
validateViewpoint(viewpoint.filter, viewpoint.events ?? [], groupIds, eventIds, sourceSchemaVersion, diagnostics, viewpoint.id);
|
|
3546
3840
|
}
|
|
3547
3841
|
for (const object of document.objects) {
|
|
3548
3842
|
validateObject(object, document.system, objectMap, groupIds, diagnostics);
|
|
3549
3843
|
}
|
|
3844
|
+
for (const event of document.events) {
|
|
3845
|
+
validateEvent(event, objectMap, diagnostics);
|
|
3846
|
+
}
|
|
3550
3847
|
return diagnostics;
|
|
3551
3848
|
}
|
|
3552
3849
|
function validateRelation(relation, objectMap, diagnostics) {
|
|
@@ -3564,13 +3861,19 @@ var WorldOrbit = (() => {
|
|
|
3564
3861
|
diagnostics.push(error("validate.relation.kind.required", `Relation "${relation.id}" is missing a "kind" value.`));
|
|
3565
3862
|
}
|
|
3566
3863
|
}
|
|
3567
|
-
function
|
|
3568
|
-
if (
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3864
|
+
function validateViewpoint(filter, eventRefs, groupIds, eventIds, sourceSchemaVersion, diagnostics, viewpointId) {
|
|
3865
|
+
if (sourceSchemaVersion === "2.1") {
|
|
3866
|
+
if (filter) {
|
|
3867
|
+
for (const groupId of filter.groupIds) {
|
|
3868
|
+
if (!groupIds.has(groupId)) {
|
|
3869
|
+
diagnostics.push(warn("validate.viewpoint.group.unknown", `Unknown group "${groupId}" in viewpoint "${viewpointId}".`, void 0, `viewpoint.${viewpointId}.groups`));
|
|
3870
|
+
}
|
|
3871
|
+
}
|
|
3872
|
+
}
|
|
3873
|
+
for (const eventId of eventRefs) {
|
|
3874
|
+
if (!eventIds.has(eventId)) {
|
|
3875
|
+
diagnostics.push(warn("validate.viewpoint.event.unknown", `Unknown event "${eventId}" in viewpoint "${viewpointId}".`, void 0, `viewpoint.${viewpointId}.events`));
|
|
3876
|
+
}
|
|
3574
3877
|
}
|
|
3575
3878
|
}
|
|
3576
3879
|
}
|
|
@@ -3656,6 +3959,103 @@ var WorldOrbit = (() => {
|
|
|
3656
3959
|
}
|
|
3657
3960
|
}
|
|
3658
3961
|
}
|
|
3962
|
+
function validateEvent(event, objectMap, diagnostics) {
|
|
3963
|
+
const fieldPrefix = `event.${event.id}`;
|
|
3964
|
+
const referencedIds = /* @__PURE__ */ new Set();
|
|
3965
|
+
if (!event.kind.trim()) {
|
|
3966
|
+
diagnostics.push(error("validate.event.kind.required", `Event "${event.id}" is missing a "kind" value.`, void 0, `${fieldPrefix}.kind`));
|
|
3967
|
+
}
|
|
3968
|
+
if (!event.targetObjectId && event.participantObjectIds.length === 0) {
|
|
3969
|
+
diagnostics.push(error("validate.event.references.required", `Event "${event.id}" must define a "target" or at least one participant.`, void 0, `${fieldPrefix}.participants`));
|
|
3970
|
+
}
|
|
3971
|
+
if (event.targetObjectId) {
|
|
3972
|
+
referencedIds.add(event.targetObjectId);
|
|
3973
|
+
if (!objectMap.has(event.targetObjectId)) {
|
|
3974
|
+
diagnostics.push(error("validate.event.target.unknown", `Unknown event target "${event.targetObjectId}" on "${event.id}".`, void 0, `${fieldPrefix}.target`));
|
|
3975
|
+
}
|
|
3976
|
+
}
|
|
3977
|
+
const seenParticipants = /* @__PURE__ */ new Set();
|
|
3978
|
+
for (const participantId of event.participantObjectIds) {
|
|
3979
|
+
referencedIds.add(participantId);
|
|
3980
|
+
if (seenParticipants.has(participantId)) {
|
|
3981
|
+
diagnostics.push(warn("validate.event.participants.duplicate", `Event "${event.id}" repeats participant "${participantId}".`, void 0, `${fieldPrefix}.participants`));
|
|
3982
|
+
continue;
|
|
3983
|
+
}
|
|
3984
|
+
seenParticipants.add(participantId);
|
|
3985
|
+
if (!objectMap.has(participantId)) {
|
|
3986
|
+
diagnostics.push(error("validate.event.participants.unknown", `Unknown event participant "${participantId}" on "${event.id}".`, void 0, `${fieldPrefix}.participants`));
|
|
3987
|
+
}
|
|
3988
|
+
}
|
|
3989
|
+
if (event.targetObjectId && event.participantObjectIds.length > 0 && !event.participantObjectIds.includes(event.targetObjectId)) {
|
|
3990
|
+
diagnostics.push(warn("validate.event.target.notParticipant", `Event "${event.id}" defines a target outside its participants list.`, void 0, `${fieldPrefix}.target`));
|
|
3991
|
+
}
|
|
3992
|
+
if (event.positions.length === 0) {
|
|
3993
|
+
diagnostics.push(warn("validate.event.positions.missing", `Event "${event.id}" has no positions block and cannot drive a scene snapshot.`, void 0, `${fieldPrefix}.positions`));
|
|
3994
|
+
}
|
|
3995
|
+
if (/(?:^|[-_])(solar-eclipse|lunar-eclipse|transit|occultation)(?:$|[-_])/.test(event.kind) && referencedIds.size < 3) {
|
|
3996
|
+
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`));
|
|
3997
|
+
}
|
|
3998
|
+
const poseIds = /* @__PURE__ */ new Set();
|
|
3999
|
+
for (const pose of event.positions) {
|
|
4000
|
+
const poseFieldPrefix = `${fieldPrefix}.pose.${pose.objectId}`;
|
|
4001
|
+
if (poseIds.has(pose.objectId)) {
|
|
4002
|
+
diagnostics.push(error("validate.event.pose.duplicate", `Event "${event.id}" defines "${pose.objectId}" more than once in positions.`, void 0, poseFieldPrefix));
|
|
4003
|
+
continue;
|
|
4004
|
+
}
|
|
4005
|
+
poseIds.add(pose.objectId);
|
|
4006
|
+
const object = objectMap.get(pose.objectId);
|
|
4007
|
+
if (!object) {
|
|
4008
|
+
diagnostics.push(error("validate.event.pose.object.unknown", `Unknown event pose object "${pose.objectId}" on "${event.id}".`, void 0, poseFieldPrefix));
|
|
4009
|
+
continue;
|
|
4010
|
+
}
|
|
4011
|
+
if (!referencedIds.has(pose.objectId)) {
|
|
4012
|
+
diagnostics.push(warn("validate.event.pose.unreferenced", `Event pose "${pose.objectId}" on "${event.id}" is not listed in target/participants.`, void 0, poseFieldPrefix));
|
|
4013
|
+
}
|
|
4014
|
+
validateEventPose(pose, object, objectMap, diagnostics, poseFieldPrefix, event.id);
|
|
4015
|
+
}
|
|
4016
|
+
}
|
|
4017
|
+
function validateEventPose(pose, object, objectMap, diagnostics, fieldPrefix, eventId) {
|
|
4018
|
+
const placement = pose.placement;
|
|
4019
|
+
if (!placement) {
|
|
4020
|
+
diagnostics.push(error("validate.event.pose.placement.required", `Event "${eventId}" pose "${pose.objectId}" is missing a placement mode.`, void 0, fieldPrefix));
|
|
4021
|
+
return;
|
|
4022
|
+
}
|
|
4023
|
+
if (placement.mode === "orbit") {
|
|
4024
|
+
if (!objectMap.has(placement.target)) {
|
|
4025
|
+
diagnostics.push(error("validate.event.pose.orbit.target.unknown", `Unknown event orbit target "${placement.target}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.orbit`));
|
|
4026
|
+
}
|
|
4027
|
+
if (placement.distance && placement.semiMajor) {
|
|
4028
|
+
diagnostics.push(error("validate.event.pose.orbit.distanceConflict", `Event "${eventId}" pose "${pose.objectId}" cannot declare both "distance" and "semiMajor".`, void 0, `${fieldPrefix}.distance`));
|
|
4029
|
+
}
|
|
4030
|
+
return;
|
|
4031
|
+
}
|
|
4032
|
+
if (placement.mode === "surface") {
|
|
4033
|
+
const target = objectMap.get(placement.target);
|
|
4034
|
+
if (!target) {
|
|
4035
|
+
diagnostics.push(error("validate.event.pose.surface.target.unknown", `Unknown event surface target "${placement.target}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.surface`));
|
|
4036
|
+
} else if (!SURFACE_TARGET_TYPES2.has(target.type)) {
|
|
4037
|
+
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`));
|
|
4038
|
+
}
|
|
4039
|
+
return;
|
|
4040
|
+
}
|
|
4041
|
+
if (placement.mode === "at") {
|
|
4042
|
+
if (object.type !== "structure" && object.type !== "phenomenon") {
|
|
4043
|
+
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`));
|
|
4044
|
+
}
|
|
4045
|
+
const reference = placement.reference;
|
|
4046
|
+
if (reference.kind === "named" && !objectMap.has(reference.name)) {
|
|
4047
|
+
diagnostics.push(error("validate.event.pose.at.target.unknown", `Unknown event at-reference target "${placement.target}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.at`));
|
|
4048
|
+
} else if (reference.kind === "anchor" && !objectMap.has(reference.objectId)) {
|
|
4049
|
+
diagnostics.push(error("validate.event.pose.anchor.target.unknown", `Unknown event anchor target "${reference.objectId}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.at`));
|
|
4050
|
+
} else if (reference.kind === "lagrange") {
|
|
4051
|
+
if (!objectMap.has(reference.primary)) {
|
|
4052
|
+
diagnostics.push(error("validate.event.pose.lagrange.primary.unknown", `Unknown event Lagrange target "${reference.primary}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.at`));
|
|
4053
|
+
} else if (reference.secondary && !objectMap.has(reference.secondary)) {
|
|
4054
|
+
diagnostics.push(error("validate.event.pose.lagrange.secondary.unknown", `Unknown event Lagrange target "${reference.secondary}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.at`));
|
|
4055
|
+
}
|
|
4056
|
+
}
|
|
4057
|
+
}
|
|
4058
|
+
}
|
|
3659
4059
|
function validateAtTarget(object, objectMap, diagnostics) {
|
|
3660
4060
|
const reference = object.placement?.mode === "at" ? object.placement.reference : null;
|
|
3661
4061
|
if (!reference) {
|
|
@@ -3856,6 +4256,21 @@ var WorldOrbit = (() => {
|
|
|
3856
4256
|
});
|
|
3857
4257
|
}
|
|
3858
4258
|
var DRAFT_OBJECT_FIELD_KEYS = new Set(DRAFT_OBJECT_FIELD_SPECS.keys());
|
|
4259
|
+
var EVENT_POSE_FIELD_KEYS = /* @__PURE__ */ new Set([
|
|
4260
|
+
"orbit",
|
|
4261
|
+
"distance",
|
|
4262
|
+
"semiMajor",
|
|
4263
|
+
"eccentricity",
|
|
4264
|
+
"period",
|
|
4265
|
+
"angle",
|
|
4266
|
+
"inclination",
|
|
4267
|
+
"phase",
|
|
4268
|
+
"at",
|
|
4269
|
+
"surface",
|
|
4270
|
+
"free",
|
|
4271
|
+
"inner",
|
|
4272
|
+
"outer"
|
|
4273
|
+
]);
|
|
3859
4274
|
function parseWorldOrbitAtlas(source) {
|
|
3860
4275
|
return parseAtlasSource(source);
|
|
3861
4276
|
}
|
|
@@ -3873,12 +4288,15 @@ var WorldOrbit = (() => {
|
|
|
3873
4288
|
const objectNodes = [];
|
|
3874
4289
|
const groups = [];
|
|
3875
4290
|
const relations = [];
|
|
4291
|
+
const events = [];
|
|
4292
|
+
const eventPoseNodes = /* @__PURE__ */ new Map();
|
|
3876
4293
|
let sawDefaults = false;
|
|
3877
4294
|
let sawAtlas = false;
|
|
3878
4295
|
const viewpointIds = /* @__PURE__ */ new Set();
|
|
3879
4296
|
const annotationIds = /* @__PURE__ */ new Set();
|
|
3880
4297
|
const groupIds = /* @__PURE__ */ new Set();
|
|
3881
4298
|
const relationIds = /* @__PURE__ */ new Set();
|
|
4299
|
+
const eventIds = /* @__PURE__ */ new Set();
|
|
3882
4300
|
for (let index = 0; index < lines.length; index++) {
|
|
3883
4301
|
const rawLine = lines[index];
|
|
3884
4302
|
const lineNumber = index + 1;
|
|
@@ -3909,7 +4327,7 @@ var WorldOrbit = (() => {
|
|
|
3909
4327
|
continue;
|
|
3910
4328
|
}
|
|
3911
4329
|
if (indent === 0) {
|
|
3912
|
-
section = startTopLevelSection(tokens, lineNumber, sourceSchemaVersion, diagnostics, system, objectNodes, groups, relations, viewpointIds, annotationIds, groupIds, relationIds, { sawDefaults, sawAtlas });
|
|
4330
|
+
section = startTopLevelSection(tokens, lineNumber, sourceSchemaVersion, diagnostics, system, objectNodes, groups, relations, events, eventPoseNodes, viewpointIds, annotationIds, groupIds, relationIds, eventIds, { sawDefaults, sawAtlas });
|
|
3913
4331
|
if (section.kind === "system") {
|
|
3914
4332
|
system = section.system;
|
|
3915
4333
|
} else if (section.kind === "defaults") {
|
|
@@ -3928,6 +4346,7 @@ var WorldOrbit = (() => {
|
|
|
3928
4346
|
throw new WorldOrbitError('Missing required atlas schema header "schema 2.0"');
|
|
3929
4347
|
}
|
|
3930
4348
|
const objects = objectNodes.map((node) => normalizeDraftObject(node, sourceSchemaVersion, diagnostics));
|
|
4349
|
+
const normalizedEvents = events.map((event) => normalizeDraftEvent(event, eventPoseNodes.get(event.id) ?? []));
|
|
3931
4350
|
const outputVersion = forcedOutputVersion ?? (sourceSchemaVersion === "2.0-draft" ? "2.0" : sourceSchemaVersion);
|
|
3932
4351
|
const baseDocument = {
|
|
3933
4352
|
format: "worldorbit",
|
|
@@ -3935,6 +4354,7 @@ var WorldOrbit = (() => {
|
|
|
3935
4354
|
system,
|
|
3936
4355
|
groups,
|
|
3937
4356
|
relations,
|
|
4357
|
+
events: normalizedEvents,
|
|
3938
4358
|
objects,
|
|
3939
4359
|
diagnostics
|
|
3940
4360
|
};
|
|
@@ -3970,7 +4390,7 @@ var WorldOrbit = (() => {
|
|
|
3970
4390
|
const version = tokens[1].value.toLowerCase();
|
|
3971
4391
|
return version === "2.1" ? "2.1" : version === "2.0-draft" ? "2.0-draft" : "2.0";
|
|
3972
4392
|
}
|
|
3973
|
-
function startTopLevelSection(tokens, line, sourceSchemaVersion, diagnostics, system, objectNodes, groups, relations, viewpointIds, annotationIds, groupIds, relationIds, flags) {
|
|
4393
|
+
function startTopLevelSection(tokens, line, sourceSchemaVersion, diagnostics, system, objectNodes, groups, relations, events, eventPoseNodes, viewpointIds, annotationIds, groupIds, relationIds, eventIds, flags) {
|
|
3974
4394
|
const keyword = tokens[0]?.value.toLowerCase();
|
|
3975
4395
|
switch (keyword) {
|
|
3976
4396
|
case "system":
|
|
@@ -4007,7 +4427,7 @@ var WorldOrbit = (() => {
|
|
|
4007
4427
|
if (!system) {
|
|
4008
4428
|
throw new WorldOrbitError('Atlas section "viewpoint" requires a preceding system declaration', line, tokens[0].column);
|
|
4009
4429
|
}
|
|
4010
|
-
return startViewpointSection(tokens, line, system, viewpointIds);
|
|
4430
|
+
return startViewpointSection(tokens, line, system, viewpointIds, sourceSchemaVersion, diagnostics);
|
|
4011
4431
|
case "annotation":
|
|
4012
4432
|
if (!system) {
|
|
4013
4433
|
throw new WorldOrbitError('Atlas section "annotation" requires a preceding system declaration', line, tokens[0].column);
|
|
@@ -4019,6 +4439,9 @@ var WorldOrbit = (() => {
|
|
|
4019
4439
|
case "relation":
|
|
4020
4440
|
warnIfSchema21Feature(sourceSchemaVersion, diagnostics, "relation", { line, column: tokens[0].column });
|
|
4021
4441
|
return startRelationSection(tokens, line, relations, relationIds);
|
|
4442
|
+
case "event":
|
|
4443
|
+
warnIfSchema21Feature(sourceSchemaVersion, diagnostics, "event", { line, column: tokens[0].column });
|
|
4444
|
+
return startEventSection(tokens, line, events, eventPoseNodes, eventIds, sourceSchemaVersion, diagnostics);
|
|
4022
4445
|
case "object":
|
|
4023
4446
|
return startObjectSection(tokens, line, sourceSchemaVersion, diagnostics, objectNodes);
|
|
4024
4447
|
default:
|
|
@@ -4055,7 +4478,7 @@ var WorldOrbit = (() => {
|
|
|
4055
4478
|
seenFields: /* @__PURE__ */ new Set()
|
|
4056
4479
|
};
|
|
4057
4480
|
}
|
|
4058
|
-
function startViewpointSection(tokens, line, system, viewpointIds) {
|
|
4481
|
+
function startViewpointSection(tokens, line, system, viewpointIds, sourceSchemaVersion, diagnostics) {
|
|
4059
4482
|
if (tokens.length !== 2) {
|
|
4060
4483
|
throw new WorldOrbitError("Invalid viewpoint declaration", line, tokens[0]?.column ?? 1);
|
|
4061
4484
|
}
|
|
@@ -4072,6 +4495,7 @@ var WorldOrbit = (() => {
|
|
|
4072
4495
|
summary: "",
|
|
4073
4496
|
focusObjectId: null,
|
|
4074
4497
|
selectedObjectId: null,
|
|
4498
|
+
events: [],
|
|
4075
4499
|
projection: system.defaults.view,
|
|
4076
4500
|
preset: system.defaults.preset,
|
|
4077
4501
|
zoom: null,
|
|
@@ -4084,6 +4508,8 @@ var WorldOrbit = (() => {
|
|
|
4084
4508
|
return {
|
|
4085
4509
|
kind: "viewpoint",
|
|
4086
4510
|
viewpoint,
|
|
4511
|
+
sourceSchemaVersion,
|
|
4512
|
+
diagnostics,
|
|
4087
4513
|
seenFields: /* @__PURE__ */ new Set(),
|
|
4088
4514
|
inFilter: false,
|
|
4089
4515
|
filterIndent: null,
|
|
@@ -4174,6 +4600,49 @@ var WorldOrbit = (() => {
|
|
|
4174
4600
|
seenFields: /* @__PURE__ */ new Set()
|
|
4175
4601
|
};
|
|
4176
4602
|
}
|
|
4603
|
+
function startEventSection(tokens, line, events, eventPoseNodes, eventIds, sourceSchemaVersion, diagnostics) {
|
|
4604
|
+
if (tokens.length !== 2) {
|
|
4605
|
+
throw new WorldOrbitError("Invalid event declaration", line, tokens[0]?.column ?? 1);
|
|
4606
|
+
}
|
|
4607
|
+
const id = normalizeIdentifier2(tokens[1].value);
|
|
4608
|
+
if (!id) {
|
|
4609
|
+
throw new WorldOrbitError("Event id must not be empty", line, tokens[1].column);
|
|
4610
|
+
}
|
|
4611
|
+
if (eventIds.has(id)) {
|
|
4612
|
+
throw new WorldOrbitError(`Duplicate event id "${id}"`, line, tokens[1].column);
|
|
4613
|
+
}
|
|
4614
|
+
const event = {
|
|
4615
|
+
id,
|
|
4616
|
+
kind: "",
|
|
4617
|
+
label: humanizeIdentifier3(id),
|
|
4618
|
+
summary: null,
|
|
4619
|
+
targetObjectId: null,
|
|
4620
|
+
participantObjectIds: [],
|
|
4621
|
+
timing: null,
|
|
4622
|
+
visibility: null,
|
|
4623
|
+
tags: [],
|
|
4624
|
+
color: null,
|
|
4625
|
+
hidden: false,
|
|
4626
|
+
positions: []
|
|
4627
|
+
};
|
|
4628
|
+
const rawPoses = [];
|
|
4629
|
+
events.push(event);
|
|
4630
|
+
eventPoseNodes.set(id, rawPoses);
|
|
4631
|
+
eventIds.add(id);
|
|
4632
|
+
return {
|
|
4633
|
+
kind: "event",
|
|
4634
|
+
event,
|
|
4635
|
+
sourceSchemaVersion,
|
|
4636
|
+
diagnostics,
|
|
4637
|
+
seenFields: /* @__PURE__ */ new Set(),
|
|
4638
|
+
rawPoses,
|
|
4639
|
+
inPositions: false,
|
|
4640
|
+
positionsIndent: null,
|
|
4641
|
+
activePose: null,
|
|
4642
|
+
poseIndent: null,
|
|
4643
|
+
activePoseSeenFields: /* @__PURE__ */ new Set()
|
|
4644
|
+
};
|
|
4645
|
+
}
|
|
4177
4646
|
function startObjectSection(tokens, line, sourceSchemaVersion, diagnostics, objectNodes) {
|
|
4178
4647
|
if (tokens.length < 3) {
|
|
4179
4648
|
throw new WorldOrbitError("Invalid atlas object declaration", line, tokens[0]?.column ?? 1);
|
|
@@ -4230,6 +4699,9 @@ var WorldOrbit = (() => {
|
|
|
4230
4699
|
case "relation":
|
|
4231
4700
|
applyRelationField(section, tokens, line);
|
|
4232
4701
|
return;
|
|
4702
|
+
case "event":
|
|
4703
|
+
applyEventField(section, indent, tokens, line);
|
|
4704
|
+
return;
|
|
4233
4705
|
case "object":
|
|
4234
4706
|
applyObjectField(section, indent, tokens, line);
|
|
4235
4707
|
return;
|
|
@@ -4356,7 +4828,14 @@ var WorldOrbit = (() => {
|
|
|
4356
4828
|
section.viewpoint.rotationDeg = parseFiniteNumber2(value, line, tokens[0].column, "rotation");
|
|
4357
4829
|
return;
|
|
4358
4830
|
case "layers":
|
|
4359
|
-
section.viewpoint.layers = parseLayerTokens(tokens.slice(1), line);
|
|
4831
|
+
section.viewpoint.layers = parseLayerTokens(tokens.slice(1), line, section.sourceSchemaVersion, section.diagnostics);
|
|
4832
|
+
return;
|
|
4833
|
+
case "events":
|
|
4834
|
+
warnIfSchema21Feature(section.sourceSchemaVersion, section.diagnostics, "viewpoint.events", {
|
|
4835
|
+
line,
|
|
4836
|
+
column: tokens[0].column
|
|
4837
|
+
});
|
|
4838
|
+
section.viewpoint.events = parseTokenList(tokens.slice(1), line, "events");
|
|
4360
4839
|
return;
|
|
4361
4840
|
default:
|
|
4362
4841
|
throw new WorldOrbitError(`Unknown viewpoint field "${tokens[0].value}"`, line, tokens[0].column);
|
|
@@ -4461,6 +4940,106 @@ var WorldOrbit = (() => {
|
|
|
4461
4940
|
throw new WorldOrbitError(`Unknown relation field "${tokens[0].value}"`, line, tokens[0].column);
|
|
4462
4941
|
}
|
|
4463
4942
|
}
|
|
4943
|
+
function applyEventField(section, indent, tokens, line) {
|
|
4944
|
+
if (section.activePose && indent <= (section.poseIndent ?? 0)) {
|
|
4945
|
+
section.activePose = null;
|
|
4946
|
+
section.poseIndent = null;
|
|
4947
|
+
section.activePoseSeenFields.clear();
|
|
4948
|
+
}
|
|
4949
|
+
if (!section.activePose && section.inPositions && indent <= (section.positionsIndent ?? 0)) {
|
|
4950
|
+
section.inPositions = false;
|
|
4951
|
+
section.positionsIndent = null;
|
|
4952
|
+
}
|
|
4953
|
+
if (section.activePose) {
|
|
4954
|
+
section.activePose.fields.push(parseEventPoseField(tokens, line, section.activePoseSeenFields));
|
|
4955
|
+
return;
|
|
4956
|
+
}
|
|
4957
|
+
if (section.inPositions) {
|
|
4958
|
+
if (tokens.length !== 2 || tokens[0].value.toLowerCase() !== "pose") {
|
|
4959
|
+
throw new WorldOrbitError(`Unknown event positions field "${tokens[0].value}"`, line, tokens[0]?.column ?? 1);
|
|
4960
|
+
}
|
|
4961
|
+
const objectId = tokens[1].value;
|
|
4962
|
+
if (!objectId.trim()) {
|
|
4963
|
+
throw new WorldOrbitError("Event pose object id must not be empty", line, tokens[1].column);
|
|
4964
|
+
}
|
|
4965
|
+
const rawPose = {
|
|
4966
|
+
objectId,
|
|
4967
|
+
fields: [],
|
|
4968
|
+
location: { line, column: tokens[0].column }
|
|
4969
|
+
};
|
|
4970
|
+
section.rawPoses.push(rawPose);
|
|
4971
|
+
section.activePose = rawPose;
|
|
4972
|
+
section.poseIndent = indent;
|
|
4973
|
+
section.activePoseSeenFields = /* @__PURE__ */ new Set();
|
|
4974
|
+
return;
|
|
4975
|
+
}
|
|
4976
|
+
if (tokens.length === 1 && tokens[0].value.toLowerCase() === "positions") {
|
|
4977
|
+
if (section.seenFields.has("positions")) {
|
|
4978
|
+
throw new WorldOrbitError('Duplicate event field "positions"', line, tokens[0].column);
|
|
4979
|
+
}
|
|
4980
|
+
section.seenFields.add("positions");
|
|
4981
|
+
section.inPositions = true;
|
|
4982
|
+
section.positionsIndent = indent;
|
|
4983
|
+
return;
|
|
4984
|
+
}
|
|
4985
|
+
const key = requireUniqueField(tokens, section.seenFields, line);
|
|
4986
|
+
switch (key) {
|
|
4987
|
+
case "kind":
|
|
4988
|
+
section.event.kind = joinFieldValue(tokens, line);
|
|
4989
|
+
return;
|
|
4990
|
+
case "label":
|
|
4991
|
+
section.event.label = joinFieldValue(tokens, line);
|
|
4992
|
+
return;
|
|
4993
|
+
case "summary":
|
|
4994
|
+
section.event.summary = joinFieldValue(tokens, line);
|
|
4995
|
+
return;
|
|
4996
|
+
case "target":
|
|
4997
|
+
section.event.targetObjectId = joinFieldValue(tokens, line);
|
|
4998
|
+
return;
|
|
4999
|
+
case "participants":
|
|
5000
|
+
section.event.participantObjectIds = parseTokenList(tokens.slice(1), line, "participants");
|
|
5001
|
+
return;
|
|
5002
|
+
case "timing":
|
|
5003
|
+
section.event.timing = joinFieldValue(tokens, line);
|
|
5004
|
+
return;
|
|
5005
|
+
case "visibility":
|
|
5006
|
+
section.event.visibility = joinFieldValue(tokens, line);
|
|
5007
|
+
return;
|
|
5008
|
+
case "tags":
|
|
5009
|
+
section.event.tags = parseTokenList(tokens.slice(1), line, "tags");
|
|
5010
|
+
return;
|
|
5011
|
+
case "color":
|
|
5012
|
+
section.event.color = joinFieldValue(tokens, line);
|
|
5013
|
+
return;
|
|
5014
|
+
case "hidden":
|
|
5015
|
+
section.event.hidden = parseAtlasBoolean(joinFieldValue(tokens, line), "hidden", {
|
|
5016
|
+
line,
|
|
5017
|
+
column: tokens[0].column
|
|
5018
|
+
});
|
|
5019
|
+
return;
|
|
5020
|
+
default:
|
|
5021
|
+
throw new WorldOrbitError(`Unknown event field "${tokens[0].value}"`, line, tokens[0].column);
|
|
5022
|
+
}
|
|
5023
|
+
}
|
|
5024
|
+
function parseEventPoseField(tokens, line, seenFields) {
|
|
5025
|
+
if (tokens.length < 2) {
|
|
5026
|
+
throw new WorldOrbitError("Invalid event pose field line", line, tokens[0]?.column ?? 1);
|
|
5027
|
+
}
|
|
5028
|
+
const key = tokens[0].value;
|
|
5029
|
+
if (!EVENT_POSE_FIELD_KEYS.has(key)) {
|
|
5030
|
+
throw new WorldOrbitError(`Unknown event pose field "${key}"`, line, tokens[0].column);
|
|
5031
|
+
}
|
|
5032
|
+
if (seenFields.has(key)) {
|
|
5033
|
+
throw new WorldOrbitError(`Duplicate event pose field "${key}"`, line, tokens[0].column);
|
|
5034
|
+
}
|
|
5035
|
+
seenFields.add(key);
|
|
5036
|
+
return {
|
|
5037
|
+
type: "field",
|
|
5038
|
+
key,
|
|
5039
|
+
values: tokens.slice(1).map((token) => token.value),
|
|
5040
|
+
location: { line, column: tokens[0].column }
|
|
5041
|
+
};
|
|
5042
|
+
}
|
|
4464
5043
|
function applyObjectField(section, indent, tokens, line) {
|
|
4465
5044
|
if (section.activeBlock && indent <= (section.blockIndent ?? 0)) {
|
|
4466
5045
|
section.activeBlock = null;
|
|
@@ -4519,7 +5098,7 @@ var WorldOrbit = (() => {
|
|
|
4519
5098
|
function parseObjectTypeTokens(tokens, line) {
|
|
4520
5099
|
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");
|
|
4521
5100
|
}
|
|
4522
|
-
function parseLayerTokens(tokens, line) {
|
|
5101
|
+
function parseLayerTokens(tokens, line, sourceSchemaVersion, diagnostics) {
|
|
4523
5102
|
const layers = {};
|
|
4524
5103
|
for (const token of parseTokenList(tokens, line, "layers")) {
|
|
4525
5104
|
const enabled = !token.startsWith("-") && !token.startsWith("!");
|
|
@@ -4529,7 +5108,13 @@ var WorldOrbit = (() => {
|
|
|
4529
5108
|
layers["orbits-front"] = enabled;
|
|
4530
5109
|
continue;
|
|
4531
5110
|
}
|
|
4532
|
-
if (raw === "background" || raw === "guides" || raw === "orbits-back" || raw === "orbits-front" || raw === "relations" || raw === "objects" || raw === "labels" || raw === "metadata") {
|
|
5111
|
+
if (raw === "background" || raw === "guides" || raw === "orbits-back" || raw === "orbits-front" || raw === "relations" || raw === "events" || raw === "objects" || raw === "labels" || raw === "metadata") {
|
|
5112
|
+
if (raw === "events" && sourceSchemaVersion && diagnostics) {
|
|
5113
|
+
warnIfSchema21Feature(sourceSchemaVersion, diagnostics, "layers.events", {
|
|
5114
|
+
line,
|
|
5115
|
+
column: tokens[0]?.column ?? 1
|
|
5116
|
+
});
|
|
5117
|
+
}
|
|
4533
5118
|
layers[raw] = enabled;
|
|
4534
5119
|
}
|
|
4535
5120
|
}
|
|
@@ -4668,7 +5253,7 @@ var WorldOrbit = (() => {
|
|
|
4668
5253
|
}
|
|
4669
5254
|
function normalizeDraftObject(node, sourceSchemaVersion, diagnostics) {
|
|
4670
5255
|
const fieldMap = collectDraftFields(node.fields);
|
|
4671
|
-
const placement =
|
|
5256
|
+
const placement = extractPlacementFromFieldMap(fieldMap);
|
|
4672
5257
|
const properties = normalizeDraftProperties(node.objectType, fieldMap);
|
|
4673
5258
|
const groups = parseOptionalTokenList(fieldMap.get("groups")?.[0]);
|
|
4674
5259
|
const epoch = parseOptionalJoinedValue(fieldMap.get("epoch")?.[0]);
|
|
@@ -4720,6 +5305,24 @@ var WorldOrbit = (() => {
|
|
|
4720
5305
|
}
|
|
4721
5306
|
return object;
|
|
4722
5307
|
}
|
|
5308
|
+
function normalizeDraftEvent(event, rawPoses) {
|
|
5309
|
+
return {
|
|
5310
|
+
...event,
|
|
5311
|
+
participantObjectIds: [...new Set(event.participantObjectIds)],
|
|
5312
|
+
tags: [...new Set(event.tags)],
|
|
5313
|
+
positions: rawPoses.map((pose) => normalizeDraftEventPose(pose))
|
|
5314
|
+
};
|
|
5315
|
+
}
|
|
5316
|
+
function normalizeDraftEventPose(rawPose) {
|
|
5317
|
+
const fieldMap = collectDraftFields(rawPose.fields);
|
|
5318
|
+
const placement = extractPlacementFromFieldMap(fieldMap);
|
|
5319
|
+
return {
|
|
5320
|
+
objectId: rawPose.objectId,
|
|
5321
|
+
placement,
|
|
5322
|
+
inner: parseOptionalUnitField(fieldMap.get("inner")?.[0], "inner"),
|
|
5323
|
+
outer: parseOptionalUnitField(fieldMap.get("outer")?.[0], "outer")
|
|
5324
|
+
};
|
|
5325
|
+
}
|
|
4723
5326
|
function collectDraftFields(fields) {
|
|
4724
5327
|
const grouped = /* @__PURE__ */ new Map();
|
|
4725
5328
|
for (const field of fields) {
|
|
@@ -4736,7 +5339,7 @@ var WorldOrbit = (() => {
|
|
|
4736
5339
|
}
|
|
4737
5340
|
return grouped;
|
|
4738
5341
|
}
|
|
4739
|
-
function
|
|
5342
|
+
function extractPlacementFromFieldMap(fieldMap) {
|
|
4740
5343
|
const orbitField = fieldMap.get("orbit")?.[0];
|
|
4741
5344
|
const atField = fieldMap.get("at")?.[0];
|
|
4742
5345
|
const surfaceField = fieldMap.get("surface")?.[0];
|
|
@@ -5029,6 +5632,7 @@ var WorldOrbit = (() => {
|
|
|
5029
5632
|
},
|
|
5030
5633
|
groups: [],
|
|
5031
5634
|
relations: [],
|
|
5635
|
+
events: [],
|
|
5032
5636
|
objects: [],
|
|
5033
5637
|
diagnostics: []
|
|
5034
5638
|
};
|
|
@@ -5055,6 +5659,12 @@ var WorldOrbit = (() => {
|
|
|
5055
5659
|
for (const relation of [...document.relations].sort(compareIdLike2)) {
|
|
5056
5660
|
paths.push({ kind: "relation", id: relation.id });
|
|
5057
5661
|
}
|
|
5662
|
+
for (const event of [...document.events].sort(compareIdLike2)) {
|
|
5663
|
+
paths.push({ kind: "event", id: event.id });
|
|
5664
|
+
for (const pose of [...event.positions].sort(comparePoseObjectId2)) {
|
|
5665
|
+
paths.push({ kind: "event-pose", id: event.id, key: pose.objectId });
|
|
5666
|
+
}
|
|
5667
|
+
}
|
|
5058
5668
|
for (const object of [...document.objects].sort(compareIdLike2)) {
|
|
5059
5669
|
paths.push({ kind: "object", id: object.id });
|
|
5060
5670
|
}
|
|
@@ -5070,6 +5680,10 @@ var WorldOrbit = (() => {
|
|
|
5070
5680
|
return path.key ? document.system?.atlasMetadata[path.key] ?? null : null;
|
|
5071
5681
|
case "group":
|
|
5072
5682
|
return path.id ? findGroup(document, path.id) : null;
|
|
5683
|
+
case "event":
|
|
5684
|
+
return path.id ? findEvent(document, path.id) : null;
|
|
5685
|
+
case "event-pose":
|
|
5686
|
+
return path.id && path.key ? findEventPose(document, path.id, path.key) : null;
|
|
5073
5687
|
case "object":
|
|
5074
5688
|
return path.id ? findObject(document, path.id) : null;
|
|
5075
5689
|
case "viewpoint":
|
|
@@ -5109,6 +5723,18 @@ var WorldOrbit = (() => {
|
|
|
5109
5723
|
}
|
|
5110
5724
|
upsertById(next.groups, value);
|
|
5111
5725
|
return next;
|
|
5726
|
+
case "event":
|
|
5727
|
+
if (!path.id) {
|
|
5728
|
+
throw new Error('Event updates require an "id" value.');
|
|
5729
|
+
}
|
|
5730
|
+
upsertById(next.events, value);
|
|
5731
|
+
return next;
|
|
5732
|
+
case "event-pose":
|
|
5733
|
+
if (!path.id || !path.key) {
|
|
5734
|
+
throw new Error('Event pose updates require an event "id" and pose "key" value.');
|
|
5735
|
+
}
|
|
5736
|
+
upsertEventPose(next.events, path.id, value);
|
|
5737
|
+
return next;
|
|
5112
5738
|
case "object":
|
|
5113
5739
|
if (!path.id) {
|
|
5114
5740
|
throw new Error('Object updates require an "id" value.');
|
|
@@ -5157,6 +5783,19 @@ var WorldOrbit = (() => {
|
|
|
5157
5783
|
next.groups = next.groups.filter((group) => group.id !== path.id);
|
|
5158
5784
|
}
|
|
5159
5785
|
return next;
|
|
5786
|
+
case "event":
|
|
5787
|
+
if (path.id) {
|
|
5788
|
+
next.events = next.events.filter((event) => event.id !== path.id);
|
|
5789
|
+
}
|
|
5790
|
+
return next;
|
|
5791
|
+
case "event-pose":
|
|
5792
|
+
if (path.id && path.key) {
|
|
5793
|
+
const event = findEvent(next, path.id);
|
|
5794
|
+
if (event) {
|
|
5795
|
+
event.positions = event.positions.filter((pose) => pose.objectId !== path.key);
|
|
5796
|
+
}
|
|
5797
|
+
}
|
|
5798
|
+
return next;
|
|
5160
5799
|
case "viewpoint":
|
|
5161
5800
|
if (path.id) {
|
|
5162
5801
|
system.viewpoints = system.viewpoints.filter((viewpoint) => viewpoint.id !== path.id);
|
|
@@ -5225,6 +5864,22 @@ var WorldOrbit = (() => {
|
|
|
5225
5864
|
};
|
|
5226
5865
|
}
|
|
5227
5866
|
}
|
|
5867
|
+
if (diagnostic.field?.startsWith("event.")) {
|
|
5868
|
+
const parts = diagnostic.field.split(".");
|
|
5869
|
+
if (parts[1] && findEvent(document, parts[1])) {
|
|
5870
|
+
if (parts[2] === "pose" && parts[3] && findEventPose(document, parts[1], parts[3])) {
|
|
5871
|
+
return {
|
|
5872
|
+
kind: "event-pose",
|
|
5873
|
+
id: parts[1],
|
|
5874
|
+
key: parts[3]
|
|
5875
|
+
};
|
|
5876
|
+
}
|
|
5877
|
+
return {
|
|
5878
|
+
kind: "event",
|
|
5879
|
+
id: parts[1]
|
|
5880
|
+
};
|
|
5881
|
+
}
|
|
5882
|
+
}
|
|
5228
5883
|
if (diagnostic.field && diagnostic.field in ensureSystem(document).atlasMetadata) {
|
|
5229
5884
|
return {
|
|
5230
5885
|
kind: "metadata",
|
|
@@ -5256,6 +5911,12 @@ var WorldOrbit = (() => {
|
|
|
5256
5911
|
function findRelation(document, relationId) {
|
|
5257
5912
|
return document.relations.find((relation) => relation.id === relationId) ?? null;
|
|
5258
5913
|
}
|
|
5914
|
+
function findEvent(document, eventId) {
|
|
5915
|
+
return document.events.find((event) => event.id === eventId) ?? null;
|
|
5916
|
+
}
|
|
5917
|
+
function findEventPose(document, eventId, objectId) {
|
|
5918
|
+
return findEvent(document, eventId)?.positions.find((pose) => pose.objectId === objectId) ?? null;
|
|
5919
|
+
}
|
|
5259
5920
|
function findViewpoint(system, viewpointId) {
|
|
5260
5921
|
return system?.viewpoints.find((viewpoint) => viewpoint.id === viewpointId) ?? null;
|
|
5261
5922
|
}
|
|
@@ -5271,9 +5932,25 @@ var WorldOrbit = (() => {
|
|
|
5271
5932
|
}
|
|
5272
5933
|
items[index] = value;
|
|
5273
5934
|
}
|
|
5935
|
+
function upsertEventPose(events, eventId, value) {
|
|
5936
|
+
const event = events.find((entry) => entry.id === eventId);
|
|
5937
|
+
if (!event) {
|
|
5938
|
+
throw new Error(`Unknown event "${eventId}" for pose update.`);
|
|
5939
|
+
}
|
|
5940
|
+
const index = event.positions.findIndex((entry) => entry.objectId === value.objectId);
|
|
5941
|
+
if (index === -1) {
|
|
5942
|
+
event.positions.push(value);
|
|
5943
|
+
event.positions.sort(comparePoseObjectId2);
|
|
5944
|
+
return;
|
|
5945
|
+
}
|
|
5946
|
+
event.positions[index] = value;
|
|
5947
|
+
}
|
|
5274
5948
|
function compareIdLike2(left, right) {
|
|
5275
5949
|
return left.id.localeCompare(right.id);
|
|
5276
5950
|
}
|
|
5951
|
+
function comparePoseObjectId2(left, right) {
|
|
5952
|
+
return left.objectId.localeCompare(right.objectId);
|
|
5953
|
+
}
|
|
5277
5954
|
|
|
5278
5955
|
// packages/core/dist/load.js
|
|
5279
5956
|
var ATLAS_SCHEMA_PATTERN = /^schema\s+2(?:\.0|\.1)?$/i;
|