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
|
@@ -568,6 +568,7 @@ var WorldOrbit = (() => {
|
|
|
568
568
|
system,
|
|
569
569
|
groups: [],
|
|
570
570
|
relations: [],
|
|
571
|
+
events: [],
|
|
571
572
|
objects
|
|
572
573
|
};
|
|
573
574
|
}
|
|
@@ -951,8 +952,10 @@ var WorldOrbit = (() => {
|
|
|
951
952
|
const scaleModel = resolveScaleModel(layoutPreset, options.scaleModel);
|
|
952
953
|
const spacingFactor = layoutPresetSpacing(layoutPreset);
|
|
953
954
|
const systemId = document2.system?.id ?? null;
|
|
954
|
-
const
|
|
955
|
-
const
|
|
955
|
+
const activeEventId = options.activeEventId ?? null;
|
|
956
|
+
const effectiveObjects = createEffectiveObjects(document2.objects, document2.events ?? [], activeEventId);
|
|
957
|
+
const objectMap = new Map(effectiveObjects.map((object) => [object.id, object]));
|
|
958
|
+
const relationships = buildSceneRelationships(effectiveObjects, objectMap);
|
|
956
959
|
const positions = /* @__PURE__ */ new Map();
|
|
957
960
|
const orbitDrafts = [];
|
|
958
961
|
const leaderDrafts = [];
|
|
@@ -961,7 +964,7 @@ var WorldOrbit = (() => {
|
|
|
961
964
|
const atObjects = [];
|
|
962
965
|
const surfaceChildren = /* @__PURE__ */ new Map();
|
|
963
966
|
const orbitChildren = /* @__PURE__ */ new Map();
|
|
964
|
-
for (const object of
|
|
967
|
+
for (const object of effectiveObjects) {
|
|
965
968
|
const placement = object.placement;
|
|
966
969
|
if (!placement) {
|
|
967
970
|
rootObjects.push(object);
|
|
@@ -1056,13 +1059,14 @@ var WorldOrbit = (() => {
|
|
|
1056
1059
|
const objects = [...positions.values()].map((position) => createSceneObject(position, scaleModel, relationships));
|
|
1057
1060
|
const orbitVisuals = orbitDrafts.map((draft) => createOrbitVisual(draft, relationships.groupIds.get(draft.object.id) ?? null));
|
|
1058
1061
|
const leaders = leaderDrafts.map((draft) => createLeaderLine(draft));
|
|
1059
|
-
const labels = createSceneLabels(objects, height, scaleModel.labelMultiplier);
|
|
1062
|
+
const labels = createSceneLabels(objects, width, height, scaleModel.labelMultiplier);
|
|
1060
1063
|
const relations = createSceneRelations(document2, objects);
|
|
1061
|
-
const
|
|
1062
|
-
const
|
|
1064
|
+
const events = createSceneEvents(document2.events ?? [], objects, activeEventId);
|
|
1065
|
+
const layers = createSceneLayers(orbitVisuals, relations, events, leaders, objects, labels);
|
|
1066
|
+
const groups = createSceneGroups(objects, orbitVisuals, leaders, labels, relationships, scaleModel.labelMultiplier);
|
|
1063
1067
|
const semanticGroups = createSceneSemanticGroups(document2, objects);
|
|
1064
1068
|
const viewpoints = createSceneViewpoints(document2, projection, frame.preset, relationships, objectMap);
|
|
1065
|
-
const contentBounds = calculateContentBounds(width, height, objects, orbitVisuals, leaders, labels);
|
|
1069
|
+
const contentBounds = calculateContentBounds(width, height, objects, orbitVisuals, leaders, labels, scaleModel.labelMultiplier);
|
|
1066
1070
|
return {
|
|
1067
1071
|
width,
|
|
1068
1072
|
height,
|
|
@@ -1088,6 +1092,8 @@ var WorldOrbit = (() => {
|
|
|
1088
1092
|
groups,
|
|
1089
1093
|
semanticGroups,
|
|
1090
1094
|
viewpoints,
|
|
1095
|
+
events,
|
|
1096
|
+
activeEventId,
|
|
1091
1097
|
objects,
|
|
1092
1098
|
orbitVisuals,
|
|
1093
1099
|
relations,
|
|
@@ -1095,6 +1101,35 @@ var WorldOrbit = (() => {
|
|
|
1095
1101
|
labels
|
|
1096
1102
|
};
|
|
1097
1103
|
}
|
|
1104
|
+
function createEffectiveObjects(objects, events, activeEventId) {
|
|
1105
|
+
const cloned = objects.map((object) => structuredClone(object));
|
|
1106
|
+
if (!activeEventId) {
|
|
1107
|
+
return cloned;
|
|
1108
|
+
}
|
|
1109
|
+
const activeEvent = events.find((event) => event.id === activeEventId);
|
|
1110
|
+
if (!activeEvent) {
|
|
1111
|
+
return cloned;
|
|
1112
|
+
}
|
|
1113
|
+
const objectMap = new Map(cloned.map((object) => [object.id, object]));
|
|
1114
|
+
for (const pose of activeEvent.positions) {
|
|
1115
|
+
const object = objectMap.get(pose.objectId);
|
|
1116
|
+
if (!object) {
|
|
1117
|
+
continue;
|
|
1118
|
+
}
|
|
1119
|
+
object.placement = pose.placement ? structuredClone(pose.placement) : null;
|
|
1120
|
+
if (pose.inner) {
|
|
1121
|
+
object.properties.inner = { ...pose.inner };
|
|
1122
|
+
} else {
|
|
1123
|
+
delete object.properties.inner;
|
|
1124
|
+
}
|
|
1125
|
+
if (pose.outer) {
|
|
1126
|
+
object.properties.outer = { ...pose.outer };
|
|
1127
|
+
} else {
|
|
1128
|
+
delete object.properties.outer;
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
return cloned;
|
|
1132
|
+
}
|
|
1098
1133
|
function resolveLayoutPreset(document2) {
|
|
1099
1134
|
const rawScale = String(document2.system?.properties.scale ?? "balanced").toLowerCase();
|
|
1100
1135
|
switch (rawScale) {
|
|
@@ -1250,24 +1285,14 @@ var WorldOrbit = (() => {
|
|
|
1250
1285
|
hidden: draft.object.properties.hidden === true
|
|
1251
1286
|
};
|
|
1252
1287
|
}
|
|
1253
|
-
function createSceneLabels(objects, sceneHeight, labelMultiplier) {
|
|
1288
|
+
function createSceneLabels(objects, sceneWidth, sceneHeight, labelMultiplier) {
|
|
1254
1289
|
const labels = [];
|
|
1255
1290
|
const occupied = [];
|
|
1256
|
-
const
|
|
1291
|
+
const objectMap = new Map(objects.map((object) => [object.objectId, object]));
|
|
1292
|
+
const visibleObjects = [...objects].filter((object) => !object.hidden && object.object.renderHints?.renderLabel !== false).sort(compareLabelPlacementOrder);
|
|
1257
1293
|
for (const object of visibleObjects) {
|
|
1258
|
-
const
|
|
1259
|
-
|
|
1260
|
-
let labelY = object.y + direction * (object.radius + 18 * labelMultiplier);
|
|
1261
|
-
let secondaryY = labelY + direction * (16 * labelMultiplier);
|
|
1262
|
-
let bounds = createLabelRect(object.x, labelY, secondaryY, labelHalfWidth, direction);
|
|
1263
|
-
let attempts = 0;
|
|
1264
|
-
while (occupied.some((entry) => rectsOverlap(entry, bounds)) && attempts < 10) {
|
|
1265
|
-
labelY += direction * 14 * labelMultiplier;
|
|
1266
|
-
secondaryY += direction * 14 * labelMultiplier;
|
|
1267
|
-
bounds = createLabelRect(object.x, labelY, secondaryY, labelHalfWidth, direction);
|
|
1268
|
-
attempts += 1;
|
|
1269
|
-
}
|
|
1270
|
-
occupied.push(bounds);
|
|
1294
|
+
const placement = selectLabelPlacement(object, objectMap, occupied, sceneWidth, sceneHeight, labelMultiplier) ?? createLabelPlacement(object, defaultVerticalDirection(object, objectMap.get(object.parentId ?? "") ?? null, sceneHeight), 0, labelMultiplier);
|
|
1295
|
+
occupied.push(createLabelRect(object, placement, labelMultiplier));
|
|
1271
1296
|
labels.push({
|
|
1272
1297
|
renderId: `${object.renderId}-label`,
|
|
1273
1298
|
objectId: object.objectId,
|
|
@@ -1276,17 +1301,128 @@ var WorldOrbit = (() => {
|
|
|
1276
1301
|
semanticGroupIds: [...object.semanticGroupIds],
|
|
1277
1302
|
label: object.label,
|
|
1278
1303
|
secondaryLabel: object.secondaryLabel,
|
|
1279
|
-
x:
|
|
1280
|
-
y: labelY,
|
|
1281
|
-
secondaryY,
|
|
1282
|
-
textAnchor:
|
|
1283
|
-
direction: direction
|
|
1304
|
+
x: placement.x,
|
|
1305
|
+
y: placement.labelY,
|
|
1306
|
+
secondaryY: placement.secondaryY,
|
|
1307
|
+
textAnchor: placement.textAnchor,
|
|
1308
|
+
direction: placement.direction,
|
|
1284
1309
|
hidden: object.hidden
|
|
1285
1310
|
});
|
|
1286
1311
|
}
|
|
1287
1312
|
return labels;
|
|
1288
1313
|
}
|
|
1289
|
-
function
|
|
1314
|
+
function compareLabelPlacementOrder(left, right) {
|
|
1315
|
+
const priorityDiff = labelPlacementPriority(left) - labelPlacementPriority(right);
|
|
1316
|
+
if (priorityDiff !== 0) {
|
|
1317
|
+
return priorityDiff;
|
|
1318
|
+
}
|
|
1319
|
+
const renderPriorityDiff = (right.object.renderHints?.renderPriority ?? 0) - (left.object.renderHints?.renderPriority ?? 0);
|
|
1320
|
+
if (renderPriorityDiff !== 0) {
|
|
1321
|
+
return renderPriorityDiff;
|
|
1322
|
+
}
|
|
1323
|
+
return left.sortKey - right.sortKey;
|
|
1324
|
+
}
|
|
1325
|
+
function labelPlacementPriority(object) {
|
|
1326
|
+
switch (object.object.type) {
|
|
1327
|
+
case "star":
|
|
1328
|
+
return 0;
|
|
1329
|
+
case "planet":
|
|
1330
|
+
return 1;
|
|
1331
|
+
case "moon":
|
|
1332
|
+
return 2;
|
|
1333
|
+
case "belt":
|
|
1334
|
+
case "ring":
|
|
1335
|
+
return 3;
|
|
1336
|
+
case "asteroid":
|
|
1337
|
+
case "comet":
|
|
1338
|
+
return 4;
|
|
1339
|
+
case "structure":
|
|
1340
|
+
case "phenomenon":
|
|
1341
|
+
return 5;
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
function selectLabelPlacement(object, objectMap, occupied, sceneWidth, sceneHeight, labelMultiplier) {
|
|
1345
|
+
for (const direction of preferredLabelDirections(object, objectMap, sceneWidth, sceneHeight)) {
|
|
1346
|
+
const maxAttempts = direction === "left" || direction === "right" ? 4 : 6;
|
|
1347
|
+
for (let attempt = 0; attempt <= maxAttempts; attempt += 1) {
|
|
1348
|
+
const placement = createLabelPlacement(object, direction, attempt, labelMultiplier);
|
|
1349
|
+
const rect = createLabelRect(object, placement, labelMultiplier);
|
|
1350
|
+
if (!occupied.some((entry) => rectsOverlap(entry, rect))) {
|
|
1351
|
+
return placement;
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
return null;
|
|
1356
|
+
}
|
|
1357
|
+
function preferredLabelDirections(object, objectMap, sceneWidth, sceneHeight) {
|
|
1358
|
+
const parent = object.parentId ? objectMap.get(object.parentId) ?? null : null;
|
|
1359
|
+
const vertical = defaultVerticalDirection(object, parent, sceneHeight);
|
|
1360
|
+
const oppositeVertical = vertical === "below" ? "above" : "below";
|
|
1361
|
+
const horizontal = defaultHorizontalDirection(object, parent, sceneWidth);
|
|
1362
|
+
const oppositeHorizontal = horizontal === "right" ? "left" : "right";
|
|
1363
|
+
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";
|
|
1364
|
+
return preferHorizontal ? [horizontal, vertical, oppositeHorizontal, oppositeVertical] : [vertical, horizontal, oppositeVertical, oppositeHorizontal];
|
|
1365
|
+
}
|
|
1366
|
+
function defaultVerticalDirection(object, parent, sceneHeight) {
|
|
1367
|
+
if (parent && Math.abs(object.y - parent.y) > 6) {
|
|
1368
|
+
return object.y >= parent.y ? "below" : "above";
|
|
1369
|
+
}
|
|
1370
|
+
return object.y > sceneHeight * 0.62 ? "above" : "below";
|
|
1371
|
+
}
|
|
1372
|
+
function defaultHorizontalDirection(object, parent, sceneWidth) {
|
|
1373
|
+
if (parent && Math.abs(object.x - parent.x) > 6) {
|
|
1374
|
+
return object.x >= parent.x ? "right" : "left";
|
|
1375
|
+
}
|
|
1376
|
+
return object.x >= sceneWidth / 2 ? "right" : "left";
|
|
1377
|
+
}
|
|
1378
|
+
function createLabelPlacement(object, direction, attempt, labelMultiplier) {
|
|
1379
|
+
const step = 14 * labelMultiplier;
|
|
1380
|
+
switch (direction) {
|
|
1381
|
+
case "above": {
|
|
1382
|
+
const labelY = object.y - (object.radius + 18 * labelMultiplier + attempt * step);
|
|
1383
|
+
return {
|
|
1384
|
+
x: object.x,
|
|
1385
|
+
labelY,
|
|
1386
|
+
secondaryY: labelY - 16 * labelMultiplier,
|
|
1387
|
+
textAnchor: "middle",
|
|
1388
|
+
direction
|
|
1389
|
+
};
|
|
1390
|
+
}
|
|
1391
|
+
case "below": {
|
|
1392
|
+
const labelY = object.y + object.radius + 18 * labelMultiplier + attempt * step;
|
|
1393
|
+
return {
|
|
1394
|
+
x: object.x,
|
|
1395
|
+
labelY,
|
|
1396
|
+
secondaryY: labelY + 16 * labelMultiplier,
|
|
1397
|
+
textAnchor: "middle",
|
|
1398
|
+
direction
|
|
1399
|
+
};
|
|
1400
|
+
}
|
|
1401
|
+
case "left": {
|
|
1402
|
+
const x = object.x - (object.visualRadius + 16 * labelMultiplier + attempt * step);
|
|
1403
|
+
const labelY = object.y - 4 * labelMultiplier;
|
|
1404
|
+
return {
|
|
1405
|
+
x,
|
|
1406
|
+
labelY,
|
|
1407
|
+
secondaryY: labelY + 16 * labelMultiplier,
|
|
1408
|
+
textAnchor: "end",
|
|
1409
|
+
direction
|
|
1410
|
+
};
|
|
1411
|
+
}
|
|
1412
|
+
case "right": {
|
|
1413
|
+
const x = object.x + object.visualRadius + 16 * labelMultiplier + attempt * step;
|
|
1414
|
+
const labelY = object.y - 4 * labelMultiplier;
|
|
1415
|
+
return {
|
|
1416
|
+
x,
|
|
1417
|
+
labelY,
|
|
1418
|
+
secondaryY: labelY + 16 * labelMultiplier,
|
|
1419
|
+
textAnchor: "start",
|
|
1420
|
+
direction
|
|
1421
|
+
};
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
function createSceneLayers(orbitVisuals, relations, events, leaders, objects, labels) {
|
|
1290
1426
|
const backOrbitIds = orbitVisuals.filter((visual) => !visual.hidden && Boolean(visual.backArcPath)).map((visual) => visual.renderId);
|
|
1291
1427
|
const frontOrbitIds = orbitVisuals.filter((visual) => !visual.hidden).map((visual) => visual.renderId);
|
|
1292
1428
|
return [
|
|
@@ -1301,6 +1437,10 @@ var WorldOrbit = (() => {
|
|
|
1301
1437
|
id: "relations",
|
|
1302
1438
|
renderIds: relations.filter((relation) => !relation.hidden).map((relation) => relation.renderId)
|
|
1303
1439
|
},
|
|
1440
|
+
{
|
|
1441
|
+
id: "events",
|
|
1442
|
+
renderIds: events.filter((event) => !event.hidden).map((event) => event.renderId)
|
|
1443
|
+
},
|
|
1304
1444
|
{
|
|
1305
1445
|
id: "objects",
|
|
1306
1446
|
renderIds: objects.filter((object) => !object.hidden).map((object) => object.renderId)
|
|
@@ -1312,7 +1452,7 @@ var WorldOrbit = (() => {
|
|
|
1312
1452
|
{ id: "metadata", renderIds: ["wo-title", "wo-subtitle", "wo-meta"] }
|
|
1313
1453
|
];
|
|
1314
1454
|
}
|
|
1315
|
-
function createSceneGroups(objects, orbitVisuals, leaders, labels, relationships) {
|
|
1455
|
+
function createSceneGroups(objects, orbitVisuals, leaders, labels, relationships, labelMultiplier) {
|
|
1316
1456
|
const groups = /* @__PURE__ */ new Map();
|
|
1317
1457
|
const ensureGroup = (groupId) => {
|
|
1318
1458
|
if (!groupId) {
|
|
@@ -1361,7 +1501,7 @@ var WorldOrbit = (() => {
|
|
|
1361
1501
|
}
|
|
1362
1502
|
}
|
|
1363
1503
|
for (const group of groups.values()) {
|
|
1364
|
-
group.contentBounds = calculateGroupBounds(group, objects, orbitVisuals, leaders, labels);
|
|
1504
|
+
group.contentBounds = calculateGroupBounds(group, objects, orbitVisuals, leaders, labels, labelMultiplier);
|
|
1365
1505
|
}
|
|
1366
1506
|
return [...groups.values()].sort((left, right) => left.label.localeCompare(right.label));
|
|
1367
1507
|
}
|
|
@@ -1395,6 +1535,29 @@ var WorldOrbit = (() => {
|
|
|
1395
1535
|
};
|
|
1396
1536
|
}).sort((left, right) => left.relation.id.localeCompare(right.relation.id));
|
|
1397
1537
|
}
|
|
1538
|
+
function createSceneEvents(events, objects, activeEventId) {
|
|
1539
|
+
const objectMap = new Map(objects.map((object) => [object.objectId, object]));
|
|
1540
|
+
return events.map((event) => {
|
|
1541
|
+
const objectIds = [.../* @__PURE__ */ new Set([
|
|
1542
|
+
...event.targetObjectId ? [event.targetObjectId] : [],
|
|
1543
|
+
...event.participantObjectIds
|
|
1544
|
+
])];
|
|
1545
|
+
const positions = objectIds.map((objectId) => objectMap.get(objectId)).filter(Boolean);
|
|
1546
|
+
const centroidX = positions.length > 0 ? positions.reduce((sum, object) => sum + object.x, 0) / positions.length : 0;
|
|
1547
|
+
const centroidY = positions.length > 0 ? positions.reduce((sum, object) => sum + object.y, 0) / positions.length : 0;
|
|
1548
|
+
return {
|
|
1549
|
+
renderId: `${createRenderId(event.id)}-event`,
|
|
1550
|
+
eventId: event.id,
|
|
1551
|
+
event,
|
|
1552
|
+
objectIds,
|
|
1553
|
+
participantIds: [...event.participantObjectIds],
|
|
1554
|
+
targetObjectId: event.targetObjectId,
|
|
1555
|
+
x: centroidX,
|
|
1556
|
+
y: centroidY,
|
|
1557
|
+
hidden: event.hidden || positions.length === 0 || positions.every((object) => object.hidden) || activeEventId !== null && event.id !== activeEventId
|
|
1558
|
+
};
|
|
1559
|
+
}).sort((left, right) => left.event.id.localeCompare(right.event.id));
|
|
1560
|
+
}
|
|
1398
1561
|
function createSceneViewpoints(document2, projection, preset, relationships, objectMap) {
|
|
1399
1562
|
const generatedOverview = createGeneratedOverviewViewpoint(document2, projection, preset);
|
|
1400
1563
|
const drafts = /* @__PURE__ */ new Map();
|
|
@@ -1448,6 +1611,7 @@ var WorldOrbit = (() => {
|
|
|
1448
1611
|
summary: "Fit the whole system with the current atlas defaults.",
|
|
1449
1612
|
objectId: null,
|
|
1450
1613
|
selectedObjectId: null,
|
|
1614
|
+
eventIds: [],
|
|
1451
1615
|
projection,
|
|
1452
1616
|
preset,
|
|
1453
1617
|
rotationDeg: 0,
|
|
@@ -1484,6 +1648,9 @@ var WorldOrbit = (() => {
|
|
|
1484
1648
|
draft.select = normalizedValue;
|
|
1485
1649
|
}
|
|
1486
1650
|
return;
|
|
1651
|
+
case "events":
|
|
1652
|
+
draft.eventIds = splitListValue(normalizedValue);
|
|
1653
|
+
return;
|
|
1487
1654
|
case "projection":
|
|
1488
1655
|
case "view":
|
|
1489
1656
|
draft.projection = parseViewProjection(normalizedValue) ?? projection;
|
|
@@ -1540,6 +1707,7 @@ var WorldOrbit = (() => {
|
|
|
1540
1707
|
summary: draft.summary?.trim() || createViewpointSummary(label, objectId, filter),
|
|
1541
1708
|
objectId,
|
|
1542
1709
|
selectedObjectId,
|
|
1710
|
+
eventIds: [...new Set(draft.eventIds ?? [])],
|
|
1543
1711
|
projection: draft.projection ?? projection,
|
|
1544
1712
|
preset: draft.preset ?? preset,
|
|
1545
1713
|
rotationDeg: draft.rotationDeg ?? 0,
|
|
@@ -1597,7 +1765,7 @@ var WorldOrbit = (() => {
|
|
|
1597
1765
|
next["orbits-front"] = enabled;
|
|
1598
1766
|
continue;
|
|
1599
1767
|
}
|
|
1600
|
-
if (rawLayer === "background" || rawLayer === "guides" || rawLayer === "orbits-back" || rawLayer === "orbits-front" || rawLayer === "relations" || rawLayer === "objects" || rawLayer === "labels" || rawLayer === "metadata") {
|
|
1768
|
+
if (rawLayer === "background" || rawLayer === "guides" || rawLayer === "orbits-back" || rawLayer === "orbits-front" || rawLayer === "relations" || rawLayer === "events" || rawLayer === "objects" || rawLayer === "labels" || rawLayer === "metadata") {
|
|
1601
1769
|
next[rawLayer] = enabled;
|
|
1602
1770
|
}
|
|
1603
1771
|
}
|
|
@@ -1645,7 +1813,7 @@ var WorldOrbit = (() => {
|
|
|
1645
1813
|
}
|
|
1646
1814
|
return parts.join(" - ");
|
|
1647
1815
|
}
|
|
1648
|
-
function calculateContentBounds(width, height, objects, orbitVisuals, leaders, labels) {
|
|
1816
|
+
function calculateContentBounds(width, height, objects, orbitVisuals, leaders, labels, labelMultiplier) {
|
|
1649
1817
|
let minX = Number.POSITIVE_INFINITY;
|
|
1650
1818
|
let minY = Number.POSITIVE_INFINITY;
|
|
1651
1819
|
let maxX = Number.NEGATIVE_INFINITY;
|
|
@@ -1675,7 +1843,7 @@ var WorldOrbit = (() => {
|
|
|
1675
1843
|
for (const label of labels) {
|
|
1676
1844
|
if (label.hidden)
|
|
1677
1845
|
continue;
|
|
1678
|
-
includeLabelBounds(label, include);
|
|
1846
|
+
includeLabelBounds(label, include, labelMultiplier);
|
|
1679
1847
|
}
|
|
1680
1848
|
if (!Number.isFinite(minX) || !Number.isFinite(minY)) {
|
|
1681
1849
|
return createBounds(0, 0, width, height);
|
|
@@ -1713,13 +1881,10 @@ var WorldOrbit = (() => {
|
|
|
1713
1881
|
include(object.x - object.visualRadius - 24, object.y - object.visualRadius - 16);
|
|
1714
1882
|
include(object.x + object.visualRadius + 24, object.y + object.visualRadius + 36);
|
|
1715
1883
|
}
|
|
1716
|
-
function includeLabelBounds(label, include) {
|
|
1717
|
-
const
|
|
1718
|
-
|
|
1719
|
-
include(
|
|
1720
|
-
include(label.x + labelHalfWidth, label.y + 8);
|
|
1721
|
-
include(label.x - labelHalfWidth, label.secondaryY - 14);
|
|
1722
|
-
include(label.x + labelHalfWidth, label.secondaryY + 8);
|
|
1884
|
+
function includeLabelBounds(label, include, labelMultiplier) {
|
|
1885
|
+
const bounds = createLabelRectFromText(label.x, label.y, label.secondaryY, label.textAnchor, label.direction, label.label, label.secondaryLabel, labelMultiplier);
|
|
1886
|
+
include(bounds.left, bounds.top);
|
|
1887
|
+
include(bounds.right, bounds.bottom);
|
|
1723
1888
|
}
|
|
1724
1889
|
function placeObject(object, x, y, depth, positions, orbitDrafts, leaderDrafts, context) {
|
|
1725
1890
|
if (positions.has(object.id)) {
|
|
@@ -2109,7 +2274,7 @@ var WorldOrbit = (() => {
|
|
|
2109
2274
|
return null;
|
|
2110
2275
|
}
|
|
2111
2276
|
}
|
|
2112
|
-
function calculateGroupBounds(group, objects, orbitVisuals, leaders, labels) {
|
|
2277
|
+
function calculateGroupBounds(group, objects, orbitVisuals, leaders, labels, labelMultiplier) {
|
|
2113
2278
|
let minX = Number.POSITIVE_INFINITY;
|
|
2114
2279
|
let minY = Number.POSITIVE_INFINITY;
|
|
2115
2280
|
let maxX = Number.NEGATIVE_INFINITY;
|
|
@@ -2138,7 +2303,7 @@ var WorldOrbit = (() => {
|
|
|
2138
2303
|
}
|
|
2139
2304
|
for (const label of labels) {
|
|
2140
2305
|
if (!label.hidden && group.labelIds.includes(label.objectId)) {
|
|
2141
|
-
includeLabelBounds(label, include);
|
|
2306
|
+
includeLabelBounds(label, include, labelMultiplier);
|
|
2142
2307
|
}
|
|
2143
2308
|
}
|
|
2144
2309
|
if (!Number.isFinite(minX) || !Number.isFinite(minY)) {
|
|
@@ -2163,12 +2328,28 @@ var WorldOrbit = (() => {
|
|
|
2163
2328
|
}
|
|
2164
2329
|
return current.id;
|
|
2165
2330
|
}
|
|
2166
|
-
function createLabelRect(
|
|
2331
|
+
function createLabelRect(object, placement, labelMultiplier) {
|
|
2332
|
+
return createLabelRectFromText(placement.x, placement.labelY, placement.secondaryY, placement.textAnchor, placement.direction, object.label, object.secondaryLabel, labelMultiplier);
|
|
2333
|
+
}
|
|
2334
|
+
function createLabelRectFromText(x, labelY, secondaryY, textAnchor, direction, label, secondaryLabel, labelMultiplier) {
|
|
2335
|
+
const labelHalfWidth = estimateLabelHalfWidthFromText(label, secondaryLabel, labelMultiplier);
|
|
2336
|
+
const labelWidth = labelHalfWidth * 2;
|
|
2337
|
+
const topPadding = direction === "above" ? 18 : 12;
|
|
2338
|
+
const bottomPadding = direction === "above" ? 8 : 12;
|
|
2339
|
+
let left = x - labelHalfWidth;
|
|
2340
|
+
let right = x + labelHalfWidth;
|
|
2341
|
+
if (textAnchor === "start") {
|
|
2342
|
+
left = x;
|
|
2343
|
+
right = x + labelWidth;
|
|
2344
|
+
} else if (textAnchor === "end") {
|
|
2345
|
+
left = x - labelWidth;
|
|
2346
|
+
right = x;
|
|
2347
|
+
}
|
|
2167
2348
|
return {
|
|
2168
|
-
left
|
|
2169
|
-
right
|
|
2170
|
-
top: Math.min(labelY, secondaryY) -
|
|
2171
|
-
bottom: Math.max(labelY, secondaryY) +
|
|
2349
|
+
left,
|
|
2350
|
+
right,
|
|
2351
|
+
top: Math.min(labelY, secondaryY) - topPadding,
|
|
2352
|
+
bottom: Math.max(labelY, secondaryY) + bottomPadding
|
|
2172
2353
|
};
|
|
2173
2354
|
}
|
|
2174
2355
|
function rectsOverlap(left, right) {
|
|
@@ -2355,11 +2536,6 @@ var WorldOrbit = (() => {
|
|
|
2355
2536
|
function customColorFor(value) {
|
|
2356
2537
|
return typeof value === "string" && value.trim() ? value : void 0;
|
|
2357
2538
|
}
|
|
2358
|
-
function estimateLabelHalfWidth(object, labelMultiplier) {
|
|
2359
|
-
const primaryWidth = object.label.length * 4.6 * labelMultiplier + 18;
|
|
2360
|
-
const secondaryWidth = object.secondaryLabel.length * 3.9 * labelMultiplier + 18;
|
|
2361
|
-
return Math.max(primaryWidth, secondaryWidth, object.visualRadius + 18);
|
|
2362
|
-
}
|
|
2363
2539
|
function estimateLabelHalfWidthFromText(label, secondaryLabel, labelMultiplier) {
|
|
2364
2540
|
const primaryWidth = label.length * 4.6 * labelMultiplier + 18;
|
|
2365
2541
|
const secondaryWidth = secondaryLabel.length * 3.9 * labelMultiplier + 18;
|
|
@@ -2376,7 +2552,7 @@ var WorldOrbit = (() => {
|
|
|
2376
2552
|
}
|
|
2377
2553
|
|
|
2378
2554
|
// packages/core/dist/draft.js
|
|
2379
|
-
function materializeAtlasDocument(document2) {
|
|
2555
|
+
function materializeAtlasDocument(document2, options = {}) {
|
|
2380
2556
|
const system = document2.system ? {
|
|
2381
2557
|
type: "system",
|
|
2382
2558
|
id: document2.system.id,
|
|
@@ -2387,6 +2563,8 @@ var WorldOrbit = (() => {
|
|
|
2387
2563
|
properties: materializeDraftSystemProperties(document2.system),
|
|
2388
2564
|
info: materializeDraftSystemInfo(document2.system)
|
|
2389
2565
|
} : null;
|
|
2566
|
+
const objects = document2.objects.map(cloneWorldOrbitObject);
|
|
2567
|
+
applyEventPoseOverrides(objects, document2.events ?? [], options.activeEventId ?? null);
|
|
2390
2568
|
return {
|
|
2391
2569
|
format: "worldorbit",
|
|
2392
2570
|
version: "1.0",
|
|
@@ -2394,7 +2572,8 @@ var WorldOrbit = (() => {
|
|
|
2394
2572
|
system,
|
|
2395
2573
|
groups: structuredClone(document2.groups ?? []),
|
|
2396
2574
|
relations: structuredClone(document2.relations ?? []),
|
|
2397
|
-
|
|
2575
|
+
events: document2.events.map(cloneWorldOrbitEvent),
|
|
2576
|
+
objects
|
|
2398
2577
|
};
|
|
2399
2578
|
}
|
|
2400
2579
|
function cloneWorldOrbitObject(object) {
|
|
@@ -2416,6 +2595,52 @@ var WorldOrbit = (() => {
|
|
|
2416
2595
|
info: { ...object.info }
|
|
2417
2596
|
};
|
|
2418
2597
|
}
|
|
2598
|
+
function cloneWorldOrbitEvent(event) {
|
|
2599
|
+
return {
|
|
2600
|
+
...event,
|
|
2601
|
+
participantObjectIds: [...event.participantObjectIds],
|
|
2602
|
+
tags: [...event.tags],
|
|
2603
|
+
positions: event.positions.map(cloneWorldOrbitEventPose)
|
|
2604
|
+
};
|
|
2605
|
+
}
|
|
2606
|
+
function cloneWorldOrbitEventPose(pose) {
|
|
2607
|
+
return {
|
|
2608
|
+
objectId: pose.objectId,
|
|
2609
|
+
placement: clonePlacement(pose.placement),
|
|
2610
|
+
inner: pose.inner ? { ...pose.inner } : void 0,
|
|
2611
|
+
outer: pose.outer ? { ...pose.outer } : void 0
|
|
2612
|
+
};
|
|
2613
|
+
}
|
|
2614
|
+
function clonePlacement(placement) {
|
|
2615
|
+
return placement ? structuredClone(placement) : null;
|
|
2616
|
+
}
|
|
2617
|
+
function applyEventPoseOverrides(objects, events, activeEventId) {
|
|
2618
|
+
if (!activeEventId) {
|
|
2619
|
+
return;
|
|
2620
|
+
}
|
|
2621
|
+
const event = events.find((entry) => entry.id === activeEventId);
|
|
2622
|
+
if (!event) {
|
|
2623
|
+
return;
|
|
2624
|
+
}
|
|
2625
|
+
const objectMap = new Map(objects.map((object) => [object.id, object]));
|
|
2626
|
+
for (const pose of event.positions) {
|
|
2627
|
+
const object = objectMap.get(pose.objectId);
|
|
2628
|
+
if (!object) {
|
|
2629
|
+
continue;
|
|
2630
|
+
}
|
|
2631
|
+
object.placement = clonePlacement(pose.placement);
|
|
2632
|
+
if (pose.inner) {
|
|
2633
|
+
object.properties.inner = { ...pose.inner };
|
|
2634
|
+
} else {
|
|
2635
|
+
delete object.properties.inner;
|
|
2636
|
+
}
|
|
2637
|
+
if (pose.outer) {
|
|
2638
|
+
object.properties.outer = { ...pose.outer };
|
|
2639
|
+
} else {
|
|
2640
|
+
delete object.properties.outer;
|
|
2641
|
+
}
|
|
2642
|
+
}
|
|
2643
|
+
}
|
|
2419
2644
|
function cloneProperties(properties) {
|
|
2420
2645
|
const next = {};
|
|
2421
2646
|
for (const [key, value] of Object.entries(properties)) {
|
|
@@ -2504,6 +2729,9 @@ var WorldOrbit = (() => {
|
|
|
2504
2729
|
if ((viewpoint.filter?.groupIds.length ?? 0) > 0) {
|
|
2505
2730
|
info2[`${prefix}.groups`] = viewpoint.filter?.groupIds.join(" ") ?? "";
|
|
2506
2731
|
}
|
|
2732
|
+
if (viewpoint.events.length > 0) {
|
|
2733
|
+
info2[`${prefix}.events`] = viewpoint.events.join(" ");
|
|
2734
|
+
}
|
|
2507
2735
|
}
|
|
2508
2736
|
for (const annotation of system.annotations) {
|
|
2509
2737
|
const prefix = `annotation.${annotation.id}`;
|
|
@@ -2528,7 +2756,7 @@ var WorldOrbit = (() => {
|
|
|
2528
2756
|
if (orbitFront !== void 0 || orbitBack !== void 0) {
|
|
2529
2757
|
tokens.push(orbitFront !== false || orbitBack !== false ? "orbits" : "-orbits");
|
|
2530
2758
|
}
|
|
2531
|
-
for (const key of ["background", "guides", "relations", "objects", "labels", "metadata"]) {
|
|
2759
|
+
for (const key of ["background", "guides", "relations", "events", "objects", "labels", "metadata"]) {
|
|
2532
2760
|
if (layers[key] !== void 0) {
|
|
2533
2761
|
tokens.push(layers[key] ? key : `-${key}`);
|
|
2534
2762
|
}
|
|
@@ -2702,6 +2930,7 @@ var WorldOrbit = (() => {
|
|
|
2702
2930
|
const diagnostics = [];
|
|
2703
2931
|
const objectMap = new Map(document2.objects.map((object) => [object.id, object]));
|
|
2704
2932
|
const groupIds = new Set(document2.groups.map((group) => group.id));
|
|
2933
|
+
const eventIds = new Set(document2.events.map((event) => event.id));
|
|
2705
2934
|
if (!document2.system) {
|
|
2706
2935
|
diagnostics.push(error("validate.system.required", "Atlas documents must declare exactly one system."));
|
|
2707
2936
|
}
|
|
@@ -2711,6 +2940,7 @@ var WorldOrbit = (() => {
|
|
|
2711
2940
|
["viewpoint", document2.system?.viewpoints.map((viewpoint) => viewpoint.id) ?? []],
|
|
2712
2941
|
["annotation", document2.system?.annotations.map((annotation) => annotation.id) ?? []],
|
|
2713
2942
|
["relation", document2.relations.map((relation) => relation.id)],
|
|
2943
|
+
["event", document2.events.map((event) => event.id)],
|
|
2714
2944
|
["object", document2.objects.map((object) => object.id)]
|
|
2715
2945
|
]) {
|
|
2716
2946
|
for (const id of ids) {
|
|
@@ -2726,11 +2956,14 @@ var WorldOrbit = (() => {
|
|
|
2726
2956
|
validateRelation(relation, objectMap, diagnostics);
|
|
2727
2957
|
}
|
|
2728
2958
|
for (const viewpoint of document2.system?.viewpoints ?? []) {
|
|
2729
|
-
|
|
2959
|
+
validateViewpoint(viewpoint.filter, viewpoint.events ?? [], groupIds, eventIds, sourceSchemaVersion, diagnostics, viewpoint.id);
|
|
2730
2960
|
}
|
|
2731
2961
|
for (const object of document2.objects) {
|
|
2732
2962
|
validateObject(object, document2.system, objectMap, groupIds, diagnostics);
|
|
2733
2963
|
}
|
|
2964
|
+
for (const event of document2.events) {
|
|
2965
|
+
validateEvent(event, objectMap, diagnostics);
|
|
2966
|
+
}
|
|
2734
2967
|
return diagnostics;
|
|
2735
2968
|
}
|
|
2736
2969
|
function validateRelation(relation, objectMap, diagnostics) {
|
|
@@ -2748,13 +2981,19 @@ var WorldOrbit = (() => {
|
|
|
2748
2981
|
diagnostics.push(error("validate.relation.kind.required", `Relation "${relation.id}" is missing a "kind" value.`));
|
|
2749
2982
|
}
|
|
2750
2983
|
}
|
|
2751
|
-
function
|
|
2752
|
-
if (
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2984
|
+
function validateViewpoint(filter, eventRefs, groupIds, eventIds, sourceSchemaVersion, diagnostics, viewpointId) {
|
|
2985
|
+
if (sourceSchemaVersion === "2.1") {
|
|
2986
|
+
if (filter) {
|
|
2987
|
+
for (const groupId of filter.groupIds) {
|
|
2988
|
+
if (!groupIds.has(groupId)) {
|
|
2989
|
+
diagnostics.push(warn("validate.viewpoint.group.unknown", `Unknown group "${groupId}" in viewpoint "${viewpointId}".`, void 0, `viewpoint.${viewpointId}.groups`));
|
|
2990
|
+
}
|
|
2991
|
+
}
|
|
2992
|
+
}
|
|
2993
|
+
for (const eventId of eventRefs) {
|
|
2994
|
+
if (!eventIds.has(eventId)) {
|
|
2995
|
+
diagnostics.push(warn("validate.viewpoint.event.unknown", `Unknown event "${eventId}" in viewpoint "${viewpointId}".`, void 0, `viewpoint.${viewpointId}.events`));
|
|
2996
|
+
}
|
|
2758
2997
|
}
|
|
2759
2998
|
}
|
|
2760
2999
|
}
|
|
@@ -2840,6 +3079,103 @@ var WorldOrbit = (() => {
|
|
|
2840
3079
|
}
|
|
2841
3080
|
}
|
|
2842
3081
|
}
|
|
3082
|
+
function validateEvent(event, objectMap, diagnostics) {
|
|
3083
|
+
const fieldPrefix = `event.${event.id}`;
|
|
3084
|
+
const referencedIds = /* @__PURE__ */ new Set();
|
|
3085
|
+
if (!event.kind.trim()) {
|
|
3086
|
+
diagnostics.push(error("validate.event.kind.required", `Event "${event.id}" is missing a "kind" value.`, void 0, `${fieldPrefix}.kind`));
|
|
3087
|
+
}
|
|
3088
|
+
if (!event.targetObjectId && event.participantObjectIds.length === 0) {
|
|
3089
|
+
diagnostics.push(error("validate.event.references.required", `Event "${event.id}" must define a "target" or at least one participant.`, void 0, `${fieldPrefix}.participants`));
|
|
3090
|
+
}
|
|
3091
|
+
if (event.targetObjectId) {
|
|
3092
|
+
referencedIds.add(event.targetObjectId);
|
|
3093
|
+
if (!objectMap.has(event.targetObjectId)) {
|
|
3094
|
+
diagnostics.push(error("validate.event.target.unknown", `Unknown event target "${event.targetObjectId}" on "${event.id}".`, void 0, `${fieldPrefix}.target`));
|
|
3095
|
+
}
|
|
3096
|
+
}
|
|
3097
|
+
const seenParticipants = /* @__PURE__ */ new Set();
|
|
3098
|
+
for (const participantId of event.participantObjectIds) {
|
|
3099
|
+
referencedIds.add(participantId);
|
|
3100
|
+
if (seenParticipants.has(participantId)) {
|
|
3101
|
+
diagnostics.push(warn("validate.event.participants.duplicate", `Event "${event.id}" repeats participant "${participantId}".`, void 0, `${fieldPrefix}.participants`));
|
|
3102
|
+
continue;
|
|
3103
|
+
}
|
|
3104
|
+
seenParticipants.add(participantId);
|
|
3105
|
+
if (!objectMap.has(participantId)) {
|
|
3106
|
+
diagnostics.push(error("validate.event.participants.unknown", `Unknown event participant "${participantId}" on "${event.id}".`, void 0, `${fieldPrefix}.participants`));
|
|
3107
|
+
}
|
|
3108
|
+
}
|
|
3109
|
+
if (event.targetObjectId && event.participantObjectIds.length > 0 && !event.participantObjectIds.includes(event.targetObjectId)) {
|
|
3110
|
+
diagnostics.push(warn("validate.event.target.notParticipant", `Event "${event.id}" defines a target outside its participants list.`, void 0, `${fieldPrefix}.target`));
|
|
3111
|
+
}
|
|
3112
|
+
if (event.positions.length === 0) {
|
|
3113
|
+
diagnostics.push(warn("validate.event.positions.missing", `Event "${event.id}" has no positions block and cannot drive a scene snapshot.`, void 0, `${fieldPrefix}.positions`));
|
|
3114
|
+
}
|
|
3115
|
+
if (/(?:^|[-_])(solar-eclipse|lunar-eclipse|transit|occultation)(?:$|[-_])/.test(event.kind) && referencedIds.size < 3) {
|
|
3116
|
+
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`));
|
|
3117
|
+
}
|
|
3118
|
+
const poseIds = /* @__PURE__ */ new Set();
|
|
3119
|
+
for (const pose of event.positions) {
|
|
3120
|
+
const poseFieldPrefix = `${fieldPrefix}.pose.${pose.objectId}`;
|
|
3121
|
+
if (poseIds.has(pose.objectId)) {
|
|
3122
|
+
diagnostics.push(error("validate.event.pose.duplicate", `Event "${event.id}" defines "${pose.objectId}" more than once in positions.`, void 0, poseFieldPrefix));
|
|
3123
|
+
continue;
|
|
3124
|
+
}
|
|
3125
|
+
poseIds.add(pose.objectId);
|
|
3126
|
+
const object = objectMap.get(pose.objectId);
|
|
3127
|
+
if (!object) {
|
|
3128
|
+
diagnostics.push(error("validate.event.pose.object.unknown", `Unknown event pose object "${pose.objectId}" on "${event.id}".`, void 0, poseFieldPrefix));
|
|
3129
|
+
continue;
|
|
3130
|
+
}
|
|
3131
|
+
if (!referencedIds.has(pose.objectId)) {
|
|
3132
|
+
diagnostics.push(warn("validate.event.pose.unreferenced", `Event pose "${pose.objectId}" on "${event.id}" is not listed in target/participants.`, void 0, poseFieldPrefix));
|
|
3133
|
+
}
|
|
3134
|
+
validateEventPose(pose, object, objectMap, diagnostics, poseFieldPrefix, event.id);
|
|
3135
|
+
}
|
|
3136
|
+
}
|
|
3137
|
+
function validateEventPose(pose, object, objectMap, diagnostics, fieldPrefix, eventId) {
|
|
3138
|
+
const placement = pose.placement;
|
|
3139
|
+
if (!placement) {
|
|
3140
|
+
diagnostics.push(error("validate.event.pose.placement.required", `Event "${eventId}" pose "${pose.objectId}" is missing a placement mode.`, void 0, fieldPrefix));
|
|
3141
|
+
return;
|
|
3142
|
+
}
|
|
3143
|
+
if (placement.mode === "orbit") {
|
|
3144
|
+
if (!objectMap.has(placement.target)) {
|
|
3145
|
+
diagnostics.push(error("validate.event.pose.orbit.target.unknown", `Unknown event orbit target "${placement.target}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.orbit`));
|
|
3146
|
+
}
|
|
3147
|
+
if (placement.distance && placement.semiMajor) {
|
|
3148
|
+
diagnostics.push(error("validate.event.pose.orbit.distanceConflict", `Event "${eventId}" pose "${pose.objectId}" cannot declare both "distance" and "semiMajor".`, void 0, `${fieldPrefix}.distance`));
|
|
3149
|
+
}
|
|
3150
|
+
return;
|
|
3151
|
+
}
|
|
3152
|
+
if (placement.mode === "surface") {
|
|
3153
|
+
const target = objectMap.get(placement.target);
|
|
3154
|
+
if (!target) {
|
|
3155
|
+
diagnostics.push(error("validate.event.pose.surface.target.unknown", `Unknown event surface target "${placement.target}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.surface`));
|
|
3156
|
+
} else if (!SURFACE_TARGET_TYPES2.has(target.type)) {
|
|
3157
|
+
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`));
|
|
3158
|
+
}
|
|
3159
|
+
return;
|
|
3160
|
+
}
|
|
3161
|
+
if (placement.mode === "at") {
|
|
3162
|
+
if (object.type !== "structure" && object.type !== "phenomenon") {
|
|
3163
|
+
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`));
|
|
3164
|
+
}
|
|
3165
|
+
const reference = placement.reference;
|
|
3166
|
+
if (reference.kind === "named" && !objectMap.has(reference.name)) {
|
|
3167
|
+
diagnostics.push(error("validate.event.pose.at.target.unknown", `Unknown event at-reference target "${placement.target}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.at`));
|
|
3168
|
+
} else if (reference.kind === "anchor" && !objectMap.has(reference.objectId)) {
|
|
3169
|
+
diagnostics.push(error("validate.event.pose.anchor.target.unknown", `Unknown event anchor target "${reference.objectId}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.at`));
|
|
3170
|
+
} else if (reference.kind === "lagrange") {
|
|
3171
|
+
if (!objectMap.has(reference.primary)) {
|
|
3172
|
+
diagnostics.push(error("validate.event.pose.lagrange.primary.unknown", `Unknown event Lagrange target "${reference.primary}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.at`));
|
|
3173
|
+
} else if (reference.secondary && !objectMap.has(reference.secondary)) {
|
|
3174
|
+
diagnostics.push(error("validate.event.pose.lagrange.secondary.unknown", `Unknown event Lagrange target "${reference.secondary}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.at`));
|
|
3175
|
+
}
|
|
3176
|
+
}
|
|
3177
|
+
}
|
|
3178
|
+
}
|
|
2843
3179
|
function validateAtTarget(object, objectMap, diagnostics) {
|
|
2844
3180
|
const reference = object.placement?.mode === "at" ? object.placement.reference : null;
|
|
2845
3181
|
if (!reference) {
|
|
@@ -3040,6 +3376,21 @@ var WorldOrbit = (() => {
|
|
|
3040
3376
|
});
|
|
3041
3377
|
}
|
|
3042
3378
|
var DRAFT_OBJECT_FIELD_KEYS = new Set(DRAFT_OBJECT_FIELD_SPECS.keys());
|
|
3379
|
+
var EVENT_POSE_FIELD_KEYS = /* @__PURE__ */ new Set([
|
|
3380
|
+
"orbit",
|
|
3381
|
+
"distance",
|
|
3382
|
+
"semiMajor",
|
|
3383
|
+
"eccentricity",
|
|
3384
|
+
"period",
|
|
3385
|
+
"angle",
|
|
3386
|
+
"inclination",
|
|
3387
|
+
"phase",
|
|
3388
|
+
"at",
|
|
3389
|
+
"surface",
|
|
3390
|
+
"free",
|
|
3391
|
+
"inner",
|
|
3392
|
+
"outer"
|
|
3393
|
+
]);
|
|
3043
3394
|
function parseWorldOrbitAtlas(source) {
|
|
3044
3395
|
return parseAtlasSource(source);
|
|
3045
3396
|
}
|
|
@@ -3054,12 +3405,15 @@ var WorldOrbit = (() => {
|
|
|
3054
3405
|
const objectNodes = [];
|
|
3055
3406
|
const groups = [];
|
|
3056
3407
|
const relations = [];
|
|
3408
|
+
const events = [];
|
|
3409
|
+
const eventPoseNodes = /* @__PURE__ */ new Map();
|
|
3057
3410
|
let sawDefaults = false;
|
|
3058
3411
|
let sawAtlas = false;
|
|
3059
3412
|
const viewpointIds = /* @__PURE__ */ new Set();
|
|
3060
3413
|
const annotationIds = /* @__PURE__ */ new Set();
|
|
3061
3414
|
const groupIds = /* @__PURE__ */ new Set();
|
|
3062
3415
|
const relationIds = /* @__PURE__ */ new Set();
|
|
3416
|
+
const eventIds = /* @__PURE__ */ new Set();
|
|
3063
3417
|
for (let index = 0; index < lines.length; index++) {
|
|
3064
3418
|
const rawLine = lines[index];
|
|
3065
3419
|
const lineNumber = index + 1;
|
|
@@ -3090,7 +3444,7 @@ var WorldOrbit = (() => {
|
|
|
3090
3444
|
continue;
|
|
3091
3445
|
}
|
|
3092
3446
|
if (indent === 0) {
|
|
3093
|
-
section = startTopLevelSection(tokens, lineNumber, sourceSchemaVersion, diagnostics, system, objectNodes, groups, relations, viewpointIds, annotationIds, groupIds, relationIds, { sawDefaults, sawAtlas });
|
|
3447
|
+
section = startTopLevelSection(tokens, lineNumber, sourceSchemaVersion, diagnostics, system, objectNodes, groups, relations, events, eventPoseNodes, viewpointIds, annotationIds, groupIds, relationIds, eventIds, { sawDefaults, sawAtlas });
|
|
3094
3448
|
if (section.kind === "system") {
|
|
3095
3449
|
system = section.system;
|
|
3096
3450
|
} else if (section.kind === "defaults") {
|
|
@@ -3109,6 +3463,7 @@ var WorldOrbit = (() => {
|
|
|
3109
3463
|
throw new WorldOrbitError('Missing required atlas schema header "schema 2.0"');
|
|
3110
3464
|
}
|
|
3111
3465
|
const objects = objectNodes.map((node) => normalizeDraftObject(node, sourceSchemaVersion, diagnostics));
|
|
3466
|
+
const normalizedEvents = events.map((event) => normalizeDraftEvent(event, eventPoseNodes.get(event.id) ?? []));
|
|
3112
3467
|
const outputVersion = forcedOutputVersion ?? (sourceSchemaVersion === "2.0-draft" ? "2.0" : sourceSchemaVersion);
|
|
3113
3468
|
const baseDocument = {
|
|
3114
3469
|
format: "worldorbit",
|
|
@@ -3116,6 +3471,7 @@ var WorldOrbit = (() => {
|
|
|
3116
3471
|
system,
|
|
3117
3472
|
groups,
|
|
3118
3473
|
relations,
|
|
3474
|
+
events: normalizedEvents,
|
|
3119
3475
|
objects,
|
|
3120
3476
|
diagnostics
|
|
3121
3477
|
};
|
|
@@ -3151,7 +3507,7 @@ var WorldOrbit = (() => {
|
|
|
3151
3507
|
const version = tokens[1].value.toLowerCase();
|
|
3152
3508
|
return version === "2.1" ? "2.1" : version === "2.0-draft" ? "2.0-draft" : "2.0";
|
|
3153
3509
|
}
|
|
3154
|
-
function startTopLevelSection(tokens, line, sourceSchemaVersion, diagnostics, system, objectNodes, groups, relations, viewpointIds, annotationIds, groupIds, relationIds, flags) {
|
|
3510
|
+
function startTopLevelSection(tokens, line, sourceSchemaVersion, diagnostics, system, objectNodes, groups, relations, events, eventPoseNodes, viewpointIds, annotationIds, groupIds, relationIds, eventIds, flags) {
|
|
3155
3511
|
const keyword = tokens[0]?.value.toLowerCase();
|
|
3156
3512
|
switch (keyword) {
|
|
3157
3513
|
case "system":
|
|
@@ -3188,7 +3544,7 @@ var WorldOrbit = (() => {
|
|
|
3188
3544
|
if (!system) {
|
|
3189
3545
|
throw new WorldOrbitError('Atlas section "viewpoint" requires a preceding system declaration', line, tokens[0].column);
|
|
3190
3546
|
}
|
|
3191
|
-
return startViewpointSection(tokens, line, system, viewpointIds);
|
|
3547
|
+
return startViewpointSection(tokens, line, system, viewpointIds, sourceSchemaVersion, diagnostics);
|
|
3192
3548
|
case "annotation":
|
|
3193
3549
|
if (!system) {
|
|
3194
3550
|
throw new WorldOrbitError('Atlas section "annotation" requires a preceding system declaration', line, tokens[0].column);
|
|
@@ -3200,6 +3556,9 @@ var WorldOrbit = (() => {
|
|
|
3200
3556
|
case "relation":
|
|
3201
3557
|
warnIfSchema21Feature(sourceSchemaVersion, diagnostics, "relation", { line, column: tokens[0].column });
|
|
3202
3558
|
return startRelationSection(tokens, line, relations, relationIds);
|
|
3559
|
+
case "event":
|
|
3560
|
+
warnIfSchema21Feature(sourceSchemaVersion, diagnostics, "event", { line, column: tokens[0].column });
|
|
3561
|
+
return startEventSection(tokens, line, events, eventPoseNodes, eventIds, sourceSchemaVersion, diagnostics);
|
|
3203
3562
|
case "object":
|
|
3204
3563
|
return startObjectSection(tokens, line, sourceSchemaVersion, diagnostics, objectNodes);
|
|
3205
3564
|
default:
|
|
@@ -3236,7 +3595,7 @@ var WorldOrbit = (() => {
|
|
|
3236
3595
|
seenFields: /* @__PURE__ */ new Set()
|
|
3237
3596
|
};
|
|
3238
3597
|
}
|
|
3239
|
-
function startViewpointSection(tokens, line, system, viewpointIds) {
|
|
3598
|
+
function startViewpointSection(tokens, line, system, viewpointIds, sourceSchemaVersion, diagnostics) {
|
|
3240
3599
|
if (tokens.length !== 2) {
|
|
3241
3600
|
throw new WorldOrbitError("Invalid viewpoint declaration", line, tokens[0]?.column ?? 1);
|
|
3242
3601
|
}
|
|
@@ -3253,6 +3612,7 @@ var WorldOrbit = (() => {
|
|
|
3253
3612
|
summary: "",
|
|
3254
3613
|
focusObjectId: null,
|
|
3255
3614
|
selectedObjectId: null,
|
|
3615
|
+
events: [],
|
|
3256
3616
|
projection: system.defaults.view,
|
|
3257
3617
|
preset: system.defaults.preset,
|
|
3258
3618
|
zoom: null,
|
|
@@ -3265,6 +3625,8 @@ var WorldOrbit = (() => {
|
|
|
3265
3625
|
return {
|
|
3266
3626
|
kind: "viewpoint",
|
|
3267
3627
|
viewpoint,
|
|
3628
|
+
sourceSchemaVersion,
|
|
3629
|
+
diagnostics,
|
|
3268
3630
|
seenFields: /* @__PURE__ */ new Set(),
|
|
3269
3631
|
inFilter: false,
|
|
3270
3632
|
filterIndent: null,
|
|
@@ -3355,6 +3717,49 @@ var WorldOrbit = (() => {
|
|
|
3355
3717
|
seenFields: /* @__PURE__ */ new Set()
|
|
3356
3718
|
};
|
|
3357
3719
|
}
|
|
3720
|
+
function startEventSection(tokens, line, events, eventPoseNodes, eventIds, sourceSchemaVersion, diagnostics) {
|
|
3721
|
+
if (tokens.length !== 2) {
|
|
3722
|
+
throw new WorldOrbitError("Invalid event declaration", line, tokens[0]?.column ?? 1);
|
|
3723
|
+
}
|
|
3724
|
+
const id = normalizeIdentifier(tokens[1].value);
|
|
3725
|
+
if (!id) {
|
|
3726
|
+
throw new WorldOrbitError("Event id must not be empty", line, tokens[1].column);
|
|
3727
|
+
}
|
|
3728
|
+
if (eventIds.has(id)) {
|
|
3729
|
+
throw new WorldOrbitError(`Duplicate event id "${id}"`, line, tokens[1].column);
|
|
3730
|
+
}
|
|
3731
|
+
const event = {
|
|
3732
|
+
id,
|
|
3733
|
+
kind: "",
|
|
3734
|
+
label: humanizeIdentifier2(id),
|
|
3735
|
+
summary: null,
|
|
3736
|
+
targetObjectId: null,
|
|
3737
|
+
participantObjectIds: [],
|
|
3738
|
+
timing: null,
|
|
3739
|
+
visibility: null,
|
|
3740
|
+
tags: [],
|
|
3741
|
+
color: null,
|
|
3742
|
+
hidden: false,
|
|
3743
|
+
positions: []
|
|
3744
|
+
};
|
|
3745
|
+
const rawPoses = [];
|
|
3746
|
+
events.push(event);
|
|
3747
|
+
eventPoseNodes.set(id, rawPoses);
|
|
3748
|
+
eventIds.add(id);
|
|
3749
|
+
return {
|
|
3750
|
+
kind: "event",
|
|
3751
|
+
event,
|
|
3752
|
+
sourceSchemaVersion,
|
|
3753
|
+
diagnostics,
|
|
3754
|
+
seenFields: /* @__PURE__ */ new Set(),
|
|
3755
|
+
rawPoses,
|
|
3756
|
+
inPositions: false,
|
|
3757
|
+
positionsIndent: null,
|
|
3758
|
+
activePose: null,
|
|
3759
|
+
poseIndent: null,
|
|
3760
|
+
activePoseSeenFields: /* @__PURE__ */ new Set()
|
|
3761
|
+
};
|
|
3762
|
+
}
|
|
3358
3763
|
function startObjectSection(tokens, line, sourceSchemaVersion, diagnostics, objectNodes) {
|
|
3359
3764
|
if (tokens.length < 3) {
|
|
3360
3765
|
throw new WorldOrbitError("Invalid atlas object declaration", line, tokens[0]?.column ?? 1);
|
|
@@ -3411,6 +3816,9 @@ var WorldOrbit = (() => {
|
|
|
3411
3816
|
case "relation":
|
|
3412
3817
|
applyRelationField(section, tokens, line);
|
|
3413
3818
|
return;
|
|
3819
|
+
case "event":
|
|
3820
|
+
applyEventField(section, indent, tokens, line);
|
|
3821
|
+
return;
|
|
3414
3822
|
case "object":
|
|
3415
3823
|
applyObjectField(section, indent, tokens, line);
|
|
3416
3824
|
return;
|
|
@@ -3537,7 +3945,14 @@ var WorldOrbit = (() => {
|
|
|
3537
3945
|
section.viewpoint.rotationDeg = parseFiniteNumber2(value, line, tokens[0].column, "rotation");
|
|
3538
3946
|
return;
|
|
3539
3947
|
case "layers":
|
|
3540
|
-
section.viewpoint.layers = parseLayerTokens(tokens.slice(1), line);
|
|
3948
|
+
section.viewpoint.layers = parseLayerTokens(tokens.slice(1), line, section.sourceSchemaVersion, section.diagnostics);
|
|
3949
|
+
return;
|
|
3950
|
+
case "events":
|
|
3951
|
+
warnIfSchema21Feature(section.sourceSchemaVersion, section.diagnostics, "viewpoint.events", {
|
|
3952
|
+
line,
|
|
3953
|
+
column: tokens[0].column
|
|
3954
|
+
});
|
|
3955
|
+
section.viewpoint.events = parseTokenList(tokens.slice(1), line, "events");
|
|
3541
3956
|
return;
|
|
3542
3957
|
default:
|
|
3543
3958
|
throw new WorldOrbitError(`Unknown viewpoint field "${tokens[0].value}"`, line, tokens[0].column);
|
|
@@ -3642,6 +4057,106 @@ var WorldOrbit = (() => {
|
|
|
3642
4057
|
throw new WorldOrbitError(`Unknown relation field "${tokens[0].value}"`, line, tokens[0].column);
|
|
3643
4058
|
}
|
|
3644
4059
|
}
|
|
4060
|
+
function applyEventField(section, indent, tokens, line) {
|
|
4061
|
+
if (section.activePose && indent <= (section.poseIndent ?? 0)) {
|
|
4062
|
+
section.activePose = null;
|
|
4063
|
+
section.poseIndent = null;
|
|
4064
|
+
section.activePoseSeenFields.clear();
|
|
4065
|
+
}
|
|
4066
|
+
if (!section.activePose && section.inPositions && indent <= (section.positionsIndent ?? 0)) {
|
|
4067
|
+
section.inPositions = false;
|
|
4068
|
+
section.positionsIndent = null;
|
|
4069
|
+
}
|
|
4070
|
+
if (section.activePose) {
|
|
4071
|
+
section.activePose.fields.push(parseEventPoseField(tokens, line, section.activePoseSeenFields));
|
|
4072
|
+
return;
|
|
4073
|
+
}
|
|
4074
|
+
if (section.inPositions) {
|
|
4075
|
+
if (tokens.length !== 2 || tokens[0].value.toLowerCase() !== "pose") {
|
|
4076
|
+
throw new WorldOrbitError(`Unknown event positions field "${tokens[0].value}"`, line, tokens[0]?.column ?? 1);
|
|
4077
|
+
}
|
|
4078
|
+
const objectId = tokens[1].value;
|
|
4079
|
+
if (!objectId.trim()) {
|
|
4080
|
+
throw new WorldOrbitError("Event pose object id must not be empty", line, tokens[1].column);
|
|
4081
|
+
}
|
|
4082
|
+
const rawPose = {
|
|
4083
|
+
objectId,
|
|
4084
|
+
fields: [],
|
|
4085
|
+
location: { line, column: tokens[0].column }
|
|
4086
|
+
};
|
|
4087
|
+
section.rawPoses.push(rawPose);
|
|
4088
|
+
section.activePose = rawPose;
|
|
4089
|
+
section.poseIndent = indent;
|
|
4090
|
+
section.activePoseSeenFields = /* @__PURE__ */ new Set();
|
|
4091
|
+
return;
|
|
4092
|
+
}
|
|
4093
|
+
if (tokens.length === 1 && tokens[0].value.toLowerCase() === "positions") {
|
|
4094
|
+
if (section.seenFields.has("positions")) {
|
|
4095
|
+
throw new WorldOrbitError('Duplicate event field "positions"', line, tokens[0].column);
|
|
4096
|
+
}
|
|
4097
|
+
section.seenFields.add("positions");
|
|
4098
|
+
section.inPositions = true;
|
|
4099
|
+
section.positionsIndent = indent;
|
|
4100
|
+
return;
|
|
4101
|
+
}
|
|
4102
|
+
const key = requireUniqueField(tokens, section.seenFields, line);
|
|
4103
|
+
switch (key) {
|
|
4104
|
+
case "kind":
|
|
4105
|
+
section.event.kind = joinFieldValue(tokens, line);
|
|
4106
|
+
return;
|
|
4107
|
+
case "label":
|
|
4108
|
+
section.event.label = joinFieldValue(tokens, line);
|
|
4109
|
+
return;
|
|
4110
|
+
case "summary":
|
|
4111
|
+
section.event.summary = joinFieldValue(tokens, line);
|
|
4112
|
+
return;
|
|
4113
|
+
case "target":
|
|
4114
|
+
section.event.targetObjectId = joinFieldValue(tokens, line);
|
|
4115
|
+
return;
|
|
4116
|
+
case "participants":
|
|
4117
|
+
section.event.participantObjectIds = parseTokenList(tokens.slice(1), line, "participants");
|
|
4118
|
+
return;
|
|
4119
|
+
case "timing":
|
|
4120
|
+
section.event.timing = joinFieldValue(tokens, line);
|
|
4121
|
+
return;
|
|
4122
|
+
case "visibility":
|
|
4123
|
+
section.event.visibility = joinFieldValue(tokens, line);
|
|
4124
|
+
return;
|
|
4125
|
+
case "tags":
|
|
4126
|
+
section.event.tags = parseTokenList(tokens.slice(1), line, "tags");
|
|
4127
|
+
return;
|
|
4128
|
+
case "color":
|
|
4129
|
+
section.event.color = joinFieldValue(tokens, line);
|
|
4130
|
+
return;
|
|
4131
|
+
case "hidden":
|
|
4132
|
+
section.event.hidden = parseAtlasBoolean(joinFieldValue(tokens, line), "hidden", {
|
|
4133
|
+
line,
|
|
4134
|
+
column: tokens[0].column
|
|
4135
|
+
});
|
|
4136
|
+
return;
|
|
4137
|
+
default:
|
|
4138
|
+
throw new WorldOrbitError(`Unknown event field "${tokens[0].value}"`, line, tokens[0].column);
|
|
4139
|
+
}
|
|
4140
|
+
}
|
|
4141
|
+
function parseEventPoseField(tokens, line, seenFields) {
|
|
4142
|
+
if (tokens.length < 2) {
|
|
4143
|
+
throw new WorldOrbitError("Invalid event pose field line", line, tokens[0]?.column ?? 1);
|
|
4144
|
+
}
|
|
4145
|
+
const key = tokens[0].value;
|
|
4146
|
+
if (!EVENT_POSE_FIELD_KEYS.has(key)) {
|
|
4147
|
+
throw new WorldOrbitError(`Unknown event pose field "${key}"`, line, tokens[0].column);
|
|
4148
|
+
}
|
|
4149
|
+
if (seenFields.has(key)) {
|
|
4150
|
+
throw new WorldOrbitError(`Duplicate event pose field "${key}"`, line, tokens[0].column);
|
|
4151
|
+
}
|
|
4152
|
+
seenFields.add(key);
|
|
4153
|
+
return {
|
|
4154
|
+
type: "field",
|
|
4155
|
+
key,
|
|
4156
|
+
values: tokens.slice(1).map((token) => token.value),
|
|
4157
|
+
location: { line, column: tokens[0].column }
|
|
4158
|
+
};
|
|
4159
|
+
}
|
|
3645
4160
|
function applyObjectField(section, indent, tokens, line) {
|
|
3646
4161
|
if (section.activeBlock && indent <= (section.blockIndent ?? 0)) {
|
|
3647
4162
|
section.activeBlock = null;
|
|
@@ -3700,7 +4215,7 @@ var WorldOrbit = (() => {
|
|
|
3700
4215
|
function parseObjectTypeTokens(tokens, line) {
|
|
3701
4216
|
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");
|
|
3702
4217
|
}
|
|
3703
|
-
function parseLayerTokens(tokens, line) {
|
|
4218
|
+
function parseLayerTokens(tokens, line, sourceSchemaVersion, diagnostics) {
|
|
3704
4219
|
const layers = {};
|
|
3705
4220
|
for (const token of parseTokenList(tokens, line, "layers")) {
|
|
3706
4221
|
const enabled = !token.startsWith("-") && !token.startsWith("!");
|
|
@@ -3710,7 +4225,13 @@ var WorldOrbit = (() => {
|
|
|
3710
4225
|
layers["orbits-front"] = enabled;
|
|
3711
4226
|
continue;
|
|
3712
4227
|
}
|
|
3713
|
-
if (raw === "background" || raw === "guides" || raw === "orbits-back" || raw === "orbits-front" || raw === "relations" || raw === "objects" || raw === "labels" || raw === "metadata") {
|
|
4228
|
+
if (raw === "background" || raw === "guides" || raw === "orbits-back" || raw === "orbits-front" || raw === "relations" || raw === "events" || raw === "objects" || raw === "labels" || raw === "metadata") {
|
|
4229
|
+
if (raw === "events" && sourceSchemaVersion && diagnostics) {
|
|
4230
|
+
warnIfSchema21Feature(sourceSchemaVersion, diagnostics, "layers.events", {
|
|
4231
|
+
line,
|
|
4232
|
+
column: tokens[0]?.column ?? 1
|
|
4233
|
+
});
|
|
4234
|
+
}
|
|
3714
4235
|
layers[raw] = enabled;
|
|
3715
4236
|
}
|
|
3716
4237
|
}
|
|
@@ -3849,7 +4370,7 @@ var WorldOrbit = (() => {
|
|
|
3849
4370
|
}
|
|
3850
4371
|
function normalizeDraftObject(node, sourceSchemaVersion, diagnostics) {
|
|
3851
4372
|
const fieldMap = collectDraftFields(node.fields);
|
|
3852
|
-
const placement =
|
|
4373
|
+
const placement = extractPlacementFromFieldMap(fieldMap);
|
|
3853
4374
|
const properties = normalizeDraftProperties(node.objectType, fieldMap);
|
|
3854
4375
|
const groups = parseOptionalTokenList(fieldMap.get("groups")?.[0]);
|
|
3855
4376
|
const epoch = parseOptionalJoinedValue(fieldMap.get("epoch")?.[0]);
|
|
@@ -3901,6 +4422,24 @@ var WorldOrbit = (() => {
|
|
|
3901
4422
|
}
|
|
3902
4423
|
return object;
|
|
3903
4424
|
}
|
|
4425
|
+
function normalizeDraftEvent(event, rawPoses) {
|
|
4426
|
+
return {
|
|
4427
|
+
...event,
|
|
4428
|
+
participantObjectIds: [...new Set(event.participantObjectIds)],
|
|
4429
|
+
tags: [...new Set(event.tags)],
|
|
4430
|
+
positions: rawPoses.map((pose) => normalizeDraftEventPose(pose))
|
|
4431
|
+
};
|
|
4432
|
+
}
|
|
4433
|
+
function normalizeDraftEventPose(rawPose) {
|
|
4434
|
+
const fieldMap = collectDraftFields(rawPose.fields);
|
|
4435
|
+
const placement = extractPlacementFromFieldMap(fieldMap);
|
|
4436
|
+
return {
|
|
4437
|
+
objectId: rawPose.objectId,
|
|
4438
|
+
placement,
|
|
4439
|
+
inner: parseOptionalUnitField(fieldMap.get("inner")?.[0], "inner"),
|
|
4440
|
+
outer: parseOptionalUnitField(fieldMap.get("outer")?.[0], "outer")
|
|
4441
|
+
};
|
|
4442
|
+
}
|
|
3904
4443
|
function collectDraftFields(fields) {
|
|
3905
4444
|
const grouped = /* @__PURE__ */ new Map();
|
|
3906
4445
|
for (const field of fields) {
|
|
@@ -3917,7 +4456,7 @@ var WorldOrbit = (() => {
|
|
|
3917
4456
|
}
|
|
3918
4457
|
return grouped;
|
|
3919
4458
|
}
|
|
3920
|
-
function
|
|
4459
|
+
function extractPlacementFromFieldMap(fieldMap) {
|
|
3921
4460
|
const orbitField = fieldMap.get("orbit")?.[0];
|
|
3922
4461
|
const atField = fieldMap.get("at")?.[0];
|
|
3923
4462
|
const surfaceField = fieldMap.get("surface")?.[0];
|
|
@@ -4353,6 +4892,7 @@ var WorldOrbit = (() => {
|
|
|
4353
4892
|
background: true,
|
|
4354
4893
|
guides: true,
|
|
4355
4894
|
relations: true,
|
|
4895
|
+
events: true,
|
|
4356
4896
|
orbits: true,
|
|
4357
4897
|
objects: true,
|
|
4358
4898
|
labels: true,
|
|
@@ -4556,6 +5096,7 @@ var WorldOrbit = (() => {
|
|
|
4556
5096
|
const orbitMarkup = layers.orbits ? renderOrbitLayer(scene, visibleObjectIds, layers.structures) : { back: "", front: "" };
|
|
4557
5097
|
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("") : "";
|
|
4558
5098
|
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("") : "";
|
|
5099
|
+
const eventMarkup = layers.events ? scene.events.filter((event) => !event.hidden).map((event) => renderSceneEventOverlay(scene, event, visibleObjectIds, theme)).join("") : "";
|
|
4559
5100
|
const objectMarkup = layers.objects ? visibleObjects.map((object) => renderSceneObject(object, options.selectedObjectId ?? null, theme)).join("") : "";
|
|
4560
5101
|
const labelMarkup = layers.labels ? visibleLabels.map((label) => renderSceneLabel(scene, label, options.selectedObjectId ?? null)).join("") : "";
|
|
4561
5102
|
const metadataMarkup = layers.metadata ? `<text class="wo-title" x="56" y="64">${escapeXml(scene.title)}</text>
|
|
@@ -4591,6 +5132,9 @@ var WorldOrbit = (() => {
|
|
|
4591
5132
|
.wo-orbit-front { opacity: 0.9; }
|
|
4592
5133
|
.wo-orbit-band { stroke: ${theme.orbitBand}; stroke-linecap: round; }
|
|
4593
5134
|
.wo-relation { stroke: ${theme.relation}; stroke-width: 2; stroke-dasharray: 10 6; }
|
|
5135
|
+
.wo-event-line { stroke: ${theme.accent}; stroke-width: 1.6; stroke-dasharray: 5 5; opacity: 0.72; }
|
|
5136
|
+
.wo-event-node { fill: ${theme.accent}; stroke: ${theme.selected}; stroke-width: 1.4; opacity: 0.92; }
|
|
5137
|
+
.wo-event-label { fill: ${theme.accent}; font-family: ${theme.fontFamily}; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; }
|
|
4594
5138
|
.wo-leader { stroke: ${theme.leader}; stroke-width: 1.5; stroke-dasharray: 6 5; }
|
|
4595
5139
|
.wo-label { fill: ${theme.ink}; font-family: ${theme.fontFamily}; font-weight: 600; letter-spacing: 0.02em; }
|
|
4596
5140
|
.wo-label-secondary { fill: ${theme.muted}; font-family: ${theme.fontFamily}; font-weight: 500; }
|
|
@@ -4625,6 +5169,7 @@ var WorldOrbit = (() => {
|
|
|
4625
5169
|
${layers.orbits ? `<g data-layer-id="orbits-back">${orbitMarkup.back}</g>` : ""}
|
|
4626
5170
|
${layers.guides ? `<g data-layer-id="guides">${leaderMarkup}</g>` : ""}
|
|
4627
5171
|
${layers.relations ? `<g data-layer-id="relations">${relationMarkup}</g>` : ""}
|
|
5172
|
+
${layers.events ? `<g data-layer-id="events">${eventMarkup}</g>` : ""}
|
|
4628
5173
|
${layers.objects ? `<g data-layer-id="objects">${objectMarkup}</g>` : ""}
|
|
4629
5174
|
${layers.orbits ? `<g data-layer-id="orbits-front">${orbitMarkup.front}</g>` : ""}
|
|
4630
5175
|
${layers.labels ? `<g data-layer-id="labels">${labelMarkup}</g>` : ""}
|
|
@@ -4632,6 +5177,20 @@ var WorldOrbit = (() => {
|
|
|
4632
5177
|
</g>
|
|
4633
5178
|
</g>
|
|
4634
5179
|
</svg>`;
|
|
5180
|
+
}
|
|
5181
|
+
function renderSceneEventOverlay(scene, event, visibleObjectIds, theme) {
|
|
5182
|
+
const participants = event.objectIds.filter((objectId) => visibleObjectIds.has(objectId)).map((objectId) => scene.objects.find((object) => object.objectId === objectId && !object.hidden)).filter(Boolean);
|
|
5183
|
+
if (participants.length === 0) {
|
|
5184
|
+
return "";
|
|
5185
|
+
}
|
|
5186
|
+
const stroke = event.event.color || theme.accent;
|
|
5187
|
+
const label = event.event.label || event.event.id;
|
|
5188
|
+
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("");
|
|
5189
|
+
return `<g class="wo-event" data-render-id="${escapeXml(event.renderId)}" data-event-id="${escapeAttribute(event.eventId)}">
|
|
5190
|
+
${lineMarkup}
|
|
5191
|
+
<circle class="wo-event-node" cx="${event.x}" cy="${event.y}" r="5" fill="${escapeAttribute(stroke)}" />
|
|
5192
|
+
<text class="wo-event-label" x="${event.x}" y="${event.y - 10}" text-anchor="middle" font-size="10">${escapeXml(label)}</text>
|
|
5193
|
+
</g>`;
|
|
4635
5194
|
}
|
|
4636
5195
|
function renderOrbitLayer(scene, visibleObjectIds, includeStructures) {
|
|
4637
5196
|
const backParts = [];
|