worldorbit 2.5.16 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -15
- package/dist/browser/core/dist/index.js +1228 -110
- package/dist/browser/editor/dist/index.js +1896 -180
- package/dist/browser/markdown/dist/index.js +1071 -99
- package/dist/browser/viewer/dist/index.js +1127 -113
- package/dist/unpkg/core/dist/index.js +1228 -110
- package/dist/unpkg/editor/dist/index.js +1896 -180
- package/dist/unpkg/markdown/dist/index.js +1071 -99
- package/dist/unpkg/viewer/dist/index.js +1127 -113
- package/dist/unpkg/worldorbit-core.min.js +12 -12
- package/dist/unpkg/worldorbit-editor.min.js +295 -203
- package/dist/unpkg/worldorbit-markdown.min.js +66 -58
- package/dist/unpkg/worldorbit-viewer.min.js +84 -76
- package/dist/unpkg/worldorbit.js +1304 -124
- package/dist/unpkg/worldorbit.min.js +88 -80
- package/package.json +1 -1
- package/packages/core/dist/atlas-edit.js +75 -1
- package/packages/core/dist/atlas-validate.js +211 -8
- package/packages/core/dist/draft-parse.js +401 -22
- package/packages/core/dist/draft.d.ts +5 -2
- package/packages/core/dist/draft.js +103 -8
- package/packages/core/dist/format.js +99 -6
- package/packages/core/dist/load.js +9 -2
- package/packages/core/dist/normalize.js +1 -0
- package/packages/core/dist/scene.js +400 -64
- package/packages/core/dist/types.d.ts +60 -4
- package/packages/editor/dist/editor.js +702 -65
- package/packages/editor/dist/types.d.ts +3 -1
- package/packages/viewer/dist/atlas-state.js +11 -2
- package/packages/viewer/dist/atlas-viewer.js +19 -7
- 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 +12 -2
- package/packages/viewer/dist/viewer.js +28 -1
package/dist/unpkg/worldorbit.js
CHANGED
|
@@ -647,6 +647,7 @@ var WorldOrbit = (() => {
|
|
|
647
647
|
system,
|
|
648
648
|
groups: [],
|
|
649
649
|
relations: [],
|
|
650
|
+
events: [],
|
|
650
651
|
objects
|
|
651
652
|
};
|
|
652
653
|
}
|
|
@@ -1100,12 +1101,16 @@ var WorldOrbit = (() => {
|
|
|
1100
1101
|
const height = frame.height;
|
|
1101
1102
|
const padding = frame.padding;
|
|
1102
1103
|
const layoutPreset = resolveLayoutPreset(document2);
|
|
1103
|
-
const
|
|
1104
|
+
const schemaProjection = resolveProjection(document2, options.projection);
|
|
1105
|
+
const camera = normalizeViewCamera(options.camera ?? null);
|
|
1106
|
+
const renderProjection = resolveRenderProjection(schemaProjection, camera);
|
|
1104
1107
|
const scaleModel = resolveScaleModel(layoutPreset, options.scaleModel);
|
|
1105
1108
|
const spacingFactor = layoutPresetSpacing(layoutPreset);
|
|
1106
1109
|
const systemId = document2.system?.id ?? null;
|
|
1107
|
-
const
|
|
1108
|
-
const
|
|
1110
|
+
const activeEventId = options.activeEventId ?? null;
|
|
1111
|
+
const effectiveObjects = createEffectiveObjects(document2.objects, document2.events ?? [], activeEventId);
|
|
1112
|
+
const objectMap = new Map(effectiveObjects.map((object) => [object.id, object]));
|
|
1113
|
+
const relationships = buildSceneRelationships(effectiveObjects, objectMap);
|
|
1109
1114
|
const positions = /* @__PURE__ */ new Map();
|
|
1110
1115
|
const orbitDrafts = [];
|
|
1111
1116
|
const leaderDrafts = [];
|
|
@@ -1114,7 +1119,7 @@ var WorldOrbit = (() => {
|
|
|
1114
1119
|
const atObjects = [];
|
|
1115
1120
|
const surfaceChildren = /* @__PURE__ */ new Map();
|
|
1116
1121
|
const orbitChildren = /* @__PURE__ */ new Map();
|
|
1117
|
-
for (const object of
|
|
1122
|
+
for (const object of effectiveObjects) {
|
|
1118
1123
|
const placement = object.placement;
|
|
1119
1124
|
if (!placement) {
|
|
1120
1125
|
rootObjects.push(object);
|
|
@@ -1141,7 +1146,7 @@ var WorldOrbit = (() => {
|
|
|
1141
1146
|
surfaceChildren,
|
|
1142
1147
|
objectMap,
|
|
1143
1148
|
spacingFactor,
|
|
1144
|
-
projection,
|
|
1149
|
+
projection: renderProjection,
|
|
1145
1150
|
scaleModel
|
|
1146
1151
|
};
|
|
1147
1152
|
const primaryRoot = rootObjects.find((object) => object.type === "star") ?? rootObjects[0] ?? null;
|
|
@@ -1153,7 +1158,7 @@ var WorldOrbit = (() => {
|
|
|
1153
1158
|
const rootRingRadius = Math.min(width, height) * 0.28 * spacingFactor * scaleModel.orbitDistanceMultiplier;
|
|
1154
1159
|
secondaryRoots.forEach((object, index) => {
|
|
1155
1160
|
const angle = angleForIndex(index, secondaryRoots.length, -Math.PI / 2);
|
|
1156
|
-
const offset = projectPolarOffset(angle, rootRingRadius,
|
|
1161
|
+
const offset = projectPolarOffset(angle, rootRingRadius, renderProjection, 1);
|
|
1157
1162
|
placeObject(object, centerX + offset.x, centerY + offset.y, 0, positions, orbitDrafts, leaderDrafts, context);
|
|
1158
1163
|
});
|
|
1159
1164
|
}
|
|
@@ -1209,38 +1214,48 @@ var WorldOrbit = (() => {
|
|
|
1209
1214
|
const objects = [...positions.values()].map((position) => createSceneObject(position, scaleModel, relationships));
|
|
1210
1215
|
const orbitVisuals = orbitDrafts.map((draft) => createOrbitVisual(draft, relationships.groupIds.get(draft.object.id) ?? null));
|
|
1211
1216
|
const leaders = leaderDrafts.map((draft) => createLeaderLine(draft));
|
|
1212
|
-
const labels = createSceneLabels(objects, height, scaleModel.labelMultiplier);
|
|
1217
|
+
const labels = createSceneLabels(objects, width, height, scaleModel.labelMultiplier);
|
|
1213
1218
|
const relations = createSceneRelations(document2, objects);
|
|
1214
|
-
const
|
|
1215
|
-
const
|
|
1219
|
+
const events = createSceneEvents(document2.events ?? [], objects, activeEventId);
|
|
1220
|
+
const layers = createSceneLayers(orbitVisuals, relations, events, leaders, objects, labels);
|
|
1221
|
+
const groups = createSceneGroups(objects, orbitVisuals, leaders, labels, relationships, scaleModel.labelMultiplier);
|
|
1216
1222
|
const semanticGroups = createSceneSemanticGroups(document2, objects);
|
|
1217
|
-
const viewpoints = createSceneViewpoints(document2,
|
|
1218
|
-
const contentBounds = calculateContentBounds(width, height, objects, orbitVisuals, leaders, labels);
|
|
1223
|
+
const viewpoints = createSceneViewpoints(document2, schemaProjection, frame.preset, relationships, objectMap);
|
|
1224
|
+
const contentBounds = calculateContentBounds(width, height, objects, orbitVisuals, leaders, labels, scaleModel.labelMultiplier);
|
|
1219
1225
|
return {
|
|
1220
1226
|
width,
|
|
1221
1227
|
height,
|
|
1222
1228
|
padding,
|
|
1223
1229
|
renderPreset: frame.preset,
|
|
1224
|
-
projection,
|
|
1230
|
+
projection: schemaProjection,
|
|
1231
|
+
renderProjection,
|
|
1232
|
+
camera,
|
|
1225
1233
|
scaleModel,
|
|
1226
1234
|
title: String(document2.system?.title ?? document2.system?.properties.title ?? document2.system?.id ?? "WorldOrbit") || "WorldOrbit",
|
|
1227
|
-
subtitle:
|
|
1235
|
+
subtitle: buildSceneSubtitle(schemaProjection, renderProjection, layoutPreset, camera),
|
|
1228
1236
|
systemId,
|
|
1229
|
-
viewMode:
|
|
1237
|
+
viewMode: schemaProjection,
|
|
1230
1238
|
layoutPreset,
|
|
1231
1239
|
metadata: {
|
|
1232
1240
|
format: document2.format,
|
|
1233
1241
|
version: document2.version,
|
|
1234
|
-
view:
|
|
1242
|
+
view: schemaProjection,
|
|
1243
|
+
renderProjection,
|
|
1235
1244
|
scale: String(document2.system?.properties.scale ?? layoutPreset),
|
|
1236
1245
|
units: String(document2.system?.properties.units ?? "mixed"),
|
|
1237
|
-
preset: frame.preset ?? "custom"
|
|
1246
|
+
preset: frame.preset ?? "custom",
|
|
1247
|
+
...camera?.azimuth !== null ? { "camera.azimuth": String(camera?.azimuth) } : {},
|
|
1248
|
+
...camera?.elevation !== null ? { "camera.elevation": String(camera?.elevation) } : {},
|
|
1249
|
+
...camera?.roll !== null ? { "camera.roll": String(camera?.roll) } : {},
|
|
1250
|
+
...camera?.distance !== null ? { "camera.distance": String(camera?.distance) } : {}
|
|
1238
1251
|
},
|
|
1239
1252
|
contentBounds,
|
|
1240
1253
|
layers,
|
|
1241
1254
|
groups,
|
|
1242
1255
|
semanticGroups,
|
|
1243
1256
|
viewpoints,
|
|
1257
|
+
events,
|
|
1258
|
+
activeEventId,
|
|
1244
1259
|
objects,
|
|
1245
1260
|
orbitVisuals,
|
|
1246
1261
|
relations,
|
|
@@ -1259,6 +1274,56 @@ var WorldOrbit = (() => {
|
|
|
1259
1274
|
y: center.y + dx * sin + dy * cos
|
|
1260
1275
|
};
|
|
1261
1276
|
}
|
|
1277
|
+
function createEffectiveObjects(objects, events, activeEventId) {
|
|
1278
|
+
const cloned = objects.map((object) => structuredClone(object));
|
|
1279
|
+
if (!activeEventId) {
|
|
1280
|
+
return cloned;
|
|
1281
|
+
}
|
|
1282
|
+
const activeEvent = events.find((event) => event.id === activeEventId);
|
|
1283
|
+
if (!activeEvent) {
|
|
1284
|
+
return cloned;
|
|
1285
|
+
}
|
|
1286
|
+
const objectMap = new Map(cloned.map((object) => [object.id, object]));
|
|
1287
|
+
const referencedIds = /* @__PURE__ */ new Set([
|
|
1288
|
+
...activeEvent.targetObjectId ? [activeEvent.targetObjectId] : [],
|
|
1289
|
+
...activeEvent.participantObjectIds,
|
|
1290
|
+
...activeEvent.positions.map((pose) => pose.objectId)
|
|
1291
|
+
]);
|
|
1292
|
+
for (const objectId of referencedIds) {
|
|
1293
|
+
const object = objectMap.get(objectId);
|
|
1294
|
+
if (!object) {
|
|
1295
|
+
continue;
|
|
1296
|
+
}
|
|
1297
|
+
if (activeEvent.epoch) {
|
|
1298
|
+
object.epoch = activeEvent.epoch;
|
|
1299
|
+
}
|
|
1300
|
+
if (activeEvent.referencePlane) {
|
|
1301
|
+
object.referencePlane = activeEvent.referencePlane;
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
for (const pose of activeEvent.positions) {
|
|
1305
|
+
const object = objectMap.get(pose.objectId);
|
|
1306
|
+
if (!object) {
|
|
1307
|
+
continue;
|
|
1308
|
+
}
|
|
1309
|
+
if (pose.placement) {
|
|
1310
|
+
object.placement = structuredClone(pose.placement);
|
|
1311
|
+
}
|
|
1312
|
+
if (pose.inner) {
|
|
1313
|
+
object.properties.inner = { ...pose.inner };
|
|
1314
|
+
}
|
|
1315
|
+
if (pose.outer) {
|
|
1316
|
+
object.properties.outer = { ...pose.outer };
|
|
1317
|
+
}
|
|
1318
|
+
if (pose.epoch) {
|
|
1319
|
+
object.epoch = pose.epoch;
|
|
1320
|
+
}
|
|
1321
|
+
if (pose.referencePlane) {
|
|
1322
|
+
object.referencePlane = pose.referencePlane;
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
return cloned;
|
|
1326
|
+
}
|
|
1262
1327
|
function resolveLayoutPreset(document2) {
|
|
1263
1328
|
const rawScale = String(document2.system?.properties.scale ?? "balanced").toLowerCase();
|
|
1264
1329
|
switch (rawScale) {
|
|
@@ -1295,10 +1360,59 @@ var WorldOrbit = (() => {
|
|
|
1295
1360
|
}
|
|
1296
1361
|
}
|
|
1297
1362
|
function resolveProjection(document2, projection) {
|
|
1298
|
-
if (projection === "topdown" || projection === "isometric") {
|
|
1363
|
+
if (projection === "topdown" || projection === "isometric" || projection === "orthographic" || projection === "perspective") {
|
|
1299
1364
|
return projection;
|
|
1300
1365
|
}
|
|
1301
|
-
|
|
1366
|
+
const documentView = String(document2.system?.properties.view ?? "topdown").toLowerCase();
|
|
1367
|
+
return parseViewProjection(documentView) ?? "topdown";
|
|
1368
|
+
}
|
|
1369
|
+
function resolveRenderProjection(projection, camera) {
|
|
1370
|
+
switch (projection) {
|
|
1371
|
+
case "topdown":
|
|
1372
|
+
return "topdown";
|
|
1373
|
+
case "isometric":
|
|
1374
|
+
return "isometric";
|
|
1375
|
+
case "orthographic":
|
|
1376
|
+
return camera && (camera.azimuth !== null || camera.elevation !== null || camera.roll !== null) ? "isometric" : "topdown";
|
|
1377
|
+
case "perspective":
|
|
1378
|
+
return "isometric";
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
function normalizeViewCamera(camera) {
|
|
1382
|
+
if (!camera) {
|
|
1383
|
+
return null;
|
|
1384
|
+
}
|
|
1385
|
+
const normalized = {
|
|
1386
|
+
azimuth: normalizeFiniteCameraValue(camera.azimuth),
|
|
1387
|
+
elevation: normalizeFiniteCameraValue(camera.elevation),
|
|
1388
|
+
roll: normalizeFiniteCameraValue(camera.roll),
|
|
1389
|
+
distance: normalizePositiveCameraDistance(camera.distance)
|
|
1390
|
+
};
|
|
1391
|
+
return normalized.azimuth !== null || normalized.elevation !== null || normalized.roll !== null || normalized.distance !== null ? normalized : null;
|
|
1392
|
+
}
|
|
1393
|
+
function normalizeFiniteCameraValue(value) {
|
|
1394
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
1395
|
+
}
|
|
1396
|
+
function normalizePositiveCameraDistance(value) {
|
|
1397
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : null;
|
|
1398
|
+
}
|
|
1399
|
+
function buildSceneSubtitle(projection, renderProjection, layoutPreset, camera) {
|
|
1400
|
+
const parts = [`${capitalizeLabel(projection)} view`, `${capitalizeLabel(layoutPreset)} layout`];
|
|
1401
|
+
if (projection !== renderProjection) {
|
|
1402
|
+
parts.push(`2D ${renderProjection} fallback`);
|
|
1403
|
+
}
|
|
1404
|
+
if (camera) {
|
|
1405
|
+
const cameraParts = [
|
|
1406
|
+
camera.azimuth !== null ? `az ${camera.azimuth}` : null,
|
|
1407
|
+
camera.elevation !== null ? `el ${camera.elevation}` : null,
|
|
1408
|
+
camera.roll !== null ? `roll ${camera.roll}` : null,
|
|
1409
|
+
camera.distance !== null ? `dist ${camera.distance}` : null
|
|
1410
|
+
].filter(Boolean);
|
|
1411
|
+
if (cameraParts.length > 0) {
|
|
1412
|
+
parts.push(`camera ${cameraParts.join(" / ")}`);
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
return parts.join(" - ");
|
|
1302
1416
|
}
|
|
1303
1417
|
function resolveScaleModel(layoutPreset, overrides) {
|
|
1304
1418
|
const defaults = defaultScaleModel(layoutPreset);
|
|
@@ -1414,24 +1528,14 @@ var WorldOrbit = (() => {
|
|
|
1414
1528
|
hidden: draft.object.properties.hidden === true
|
|
1415
1529
|
};
|
|
1416
1530
|
}
|
|
1417
|
-
function createSceneLabels(objects, sceneHeight, labelMultiplier) {
|
|
1531
|
+
function createSceneLabels(objects, sceneWidth, sceneHeight, labelMultiplier) {
|
|
1418
1532
|
const labels = [];
|
|
1419
1533
|
const occupied = [];
|
|
1420
|
-
const
|
|
1534
|
+
const objectMap = new Map(objects.map((object) => [object.objectId, object]));
|
|
1535
|
+
const visibleObjects = [...objects].filter((object) => !object.hidden && object.object.renderHints?.renderLabel !== false).sort(compareLabelPlacementOrder);
|
|
1421
1536
|
for (const object of visibleObjects) {
|
|
1422
|
-
const
|
|
1423
|
-
|
|
1424
|
-
let labelY = object.y + direction * (object.radius + 18 * labelMultiplier);
|
|
1425
|
-
let secondaryY = labelY + direction * (16 * labelMultiplier);
|
|
1426
|
-
let bounds = createLabelRect(object.x, labelY, secondaryY, labelHalfWidth, direction);
|
|
1427
|
-
let attempts = 0;
|
|
1428
|
-
while (occupied.some((entry) => rectsOverlap(entry, bounds)) && attempts < 10) {
|
|
1429
|
-
labelY += direction * 14 * labelMultiplier;
|
|
1430
|
-
secondaryY += direction * 14 * labelMultiplier;
|
|
1431
|
-
bounds = createLabelRect(object.x, labelY, secondaryY, labelHalfWidth, direction);
|
|
1432
|
-
attempts += 1;
|
|
1433
|
-
}
|
|
1434
|
-
occupied.push(bounds);
|
|
1537
|
+
const placement = selectLabelPlacement(object, objectMap, occupied, sceneWidth, sceneHeight, labelMultiplier) ?? createLabelPlacement(object, defaultVerticalDirection(object, objectMap.get(object.parentId ?? "") ?? null, sceneHeight), 0, labelMultiplier);
|
|
1538
|
+
occupied.push(createLabelRect(object, placement, labelMultiplier));
|
|
1435
1539
|
labels.push({
|
|
1436
1540
|
renderId: `${object.renderId}-label`,
|
|
1437
1541
|
objectId: object.objectId,
|
|
@@ -1440,17 +1544,128 @@ var WorldOrbit = (() => {
|
|
|
1440
1544
|
semanticGroupIds: [...object.semanticGroupIds],
|
|
1441
1545
|
label: object.label,
|
|
1442
1546
|
secondaryLabel: object.secondaryLabel,
|
|
1443
|
-
x:
|
|
1444
|
-
y: labelY,
|
|
1445
|
-
secondaryY,
|
|
1446
|
-
textAnchor:
|
|
1447
|
-
direction: direction
|
|
1547
|
+
x: placement.x,
|
|
1548
|
+
y: placement.labelY,
|
|
1549
|
+
secondaryY: placement.secondaryY,
|
|
1550
|
+
textAnchor: placement.textAnchor,
|
|
1551
|
+
direction: placement.direction,
|
|
1448
1552
|
hidden: object.hidden
|
|
1449
1553
|
});
|
|
1450
1554
|
}
|
|
1451
1555
|
return labels;
|
|
1452
1556
|
}
|
|
1453
|
-
function
|
|
1557
|
+
function compareLabelPlacementOrder(left, right) {
|
|
1558
|
+
const priorityDiff = labelPlacementPriority(left) - labelPlacementPriority(right);
|
|
1559
|
+
if (priorityDiff !== 0) {
|
|
1560
|
+
return priorityDiff;
|
|
1561
|
+
}
|
|
1562
|
+
const renderPriorityDiff = (right.object.renderHints?.renderPriority ?? 0) - (left.object.renderHints?.renderPriority ?? 0);
|
|
1563
|
+
if (renderPriorityDiff !== 0) {
|
|
1564
|
+
return renderPriorityDiff;
|
|
1565
|
+
}
|
|
1566
|
+
return left.sortKey - right.sortKey;
|
|
1567
|
+
}
|
|
1568
|
+
function labelPlacementPriority(object) {
|
|
1569
|
+
switch (object.object.type) {
|
|
1570
|
+
case "star":
|
|
1571
|
+
return 0;
|
|
1572
|
+
case "planet":
|
|
1573
|
+
return 1;
|
|
1574
|
+
case "moon":
|
|
1575
|
+
return 2;
|
|
1576
|
+
case "belt":
|
|
1577
|
+
case "ring":
|
|
1578
|
+
return 3;
|
|
1579
|
+
case "asteroid":
|
|
1580
|
+
case "comet":
|
|
1581
|
+
return 4;
|
|
1582
|
+
case "structure":
|
|
1583
|
+
case "phenomenon":
|
|
1584
|
+
return 5;
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
function selectLabelPlacement(object, objectMap, occupied, sceneWidth, sceneHeight, labelMultiplier) {
|
|
1588
|
+
for (const direction of preferredLabelDirections(object, objectMap, sceneWidth, sceneHeight)) {
|
|
1589
|
+
const maxAttempts = direction === "left" || direction === "right" ? 4 : 6;
|
|
1590
|
+
for (let attempt = 0; attempt <= maxAttempts; attempt += 1) {
|
|
1591
|
+
const placement = createLabelPlacement(object, direction, attempt, labelMultiplier);
|
|
1592
|
+
const rect = createLabelRect(object, placement, labelMultiplier);
|
|
1593
|
+
if (!occupied.some((entry) => rectsOverlap(entry, rect))) {
|
|
1594
|
+
return placement;
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
return null;
|
|
1599
|
+
}
|
|
1600
|
+
function preferredLabelDirections(object, objectMap, sceneWidth, sceneHeight) {
|
|
1601
|
+
const parent = object.parentId ? objectMap.get(object.parentId) ?? null : null;
|
|
1602
|
+
const vertical = defaultVerticalDirection(object, parent, sceneHeight);
|
|
1603
|
+
const oppositeVertical = vertical === "below" ? "above" : "below";
|
|
1604
|
+
const horizontal = defaultHorizontalDirection(object, parent, sceneWidth);
|
|
1605
|
+
const oppositeHorizontal = horizontal === "right" ? "left" : "right";
|
|
1606
|
+
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";
|
|
1607
|
+
return preferHorizontal ? [horizontal, vertical, oppositeHorizontal, oppositeVertical] : [vertical, horizontal, oppositeVertical, oppositeHorizontal];
|
|
1608
|
+
}
|
|
1609
|
+
function defaultVerticalDirection(object, parent, sceneHeight) {
|
|
1610
|
+
if (parent && Math.abs(object.y - parent.y) > 6) {
|
|
1611
|
+
return object.y >= parent.y ? "below" : "above";
|
|
1612
|
+
}
|
|
1613
|
+
return object.y > sceneHeight * 0.62 ? "above" : "below";
|
|
1614
|
+
}
|
|
1615
|
+
function defaultHorizontalDirection(object, parent, sceneWidth) {
|
|
1616
|
+
if (parent && Math.abs(object.x - parent.x) > 6) {
|
|
1617
|
+
return object.x >= parent.x ? "right" : "left";
|
|
1618
|
+
}
|
|
1619
|
+
return object.x >= sceneWidth / 2 ? "right" : "left";
|
|
1620
|
+
}
|
|
1621
|
+
function createLabelPlacement(object, direction, attempt, labelMultiplier) {
|
|
1622
|
+
const step = 14 * labelMultiplier;
|
|
1623
|
+
switch (direction) {
|
|
1624
|
+
case "above": {
|
|
1625
|
+
const labelY = object.y - (object.radius + 18 * labelMultiplier + attempt * step);
|
|
1626
|
+
return {
|
|
1627
|
+
x: object.x,
|
|
1628
|
+
labelY,
|
|
1629
|
+
secondaryY: labelY - 16 * labelMultiplier,
|
|
1630
|
+
textAnchor: "middle",
|
|
1631
|
+
direction
|
|
1632
|
+
};
|
|
1633
|
+
}
|
|
1634
|
+
case "below": {
|
|
1635
|
+
const labelY = object.y + object.radius + 18 * labelMultiplier + attempt * step;
|
|
1636
|
+
return {
|
|
1637
|
+
x: object.x,
|
|
1638
|
+
labelY,
|
|
1639
|
+
secondaryY: labelY + 16 * labelMultiplier,
|
|
1640
|
+
textAnchor: "middle",
|
|
1641
|
+
direction
|
|
1642
|
+
};
|
|
1643
|
+
}
|
|
1644
|
+
case "left": {
|
|
1645
|
+
const x = object.x - (object.visualRadius + 16 * labelMultiplier + attempt * step);
|
|
1646
|
+
const labelY = object.y - 4 * labelMultiplier;
|
|
1647
|
+
return {
|
|
1648
|
+
x,
|
|
1649
|
+
labelY,
|
|
1650
|
+
secondaryY: labelY + 16 * labelMultiplier,
|
|
1651
|
+
textAnchor: "end",
|
|
1652
|
+
direction
|
|
1653
|
+
};
|
|
1654
|
+
}
|
|
1655
|
+
case "right": {
|
|
1656
|
+
const x = object.x + object.visualRadius + 16 * labelMultiplier + attempt * step;
|
|
1657
|
+
const labelY = object.y - 4 * labelMultiplier;
|
|
1658
|
+
return {
|
|
1659
|
+
x,
|
|
1660
|
+
labelY,
|
|
1661
|
+
secondaryY: labelY + 16 * labelMultiplier,
|
|
1662
|
+
textAnchor: "start",
|
|
1663
|
+
direction
|
|
1664
|
+
};
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1668
|
+
function createSceneLayers(orbitVisuals, relations, events, leaders, objects, labels) {
|
|
1454
1669
|
const backOrbitIds = orbitVisuals.filter((visual) => !visual.hidden && Boolean(visual.backArcPath)).map((visual) => visual.renderId);
|
|
1455
1670
|
const frontOrbitIds = orbitVisuals.filter((visual) => !visual.hidden).map((visual) => visual.renderId);
|
|
1456
1671
|
return [
|
|
@@ -1465,6 +1680,10 @@ var WorldOrbit = (() => {
|
|
|
1465
1680
|
id: "relations",
|
|
1466
1681
|
renderIds: relations.filter((relation) => !relation.hidden).map((relation) => relation.renderId)
|
|
1467
1682
|
},
|
|
1683
|
+
{
|
|
1684
|
+
id: "events",
|
|
1685
|
+
renderIds: events.filter((event) => !event.hidden).map((event) => event.renderId)
|
|
1686
|
+
},
|
|
1468
1687
|
{
|
|
1469
1688
|
id: "objects",
|
|
1470
1689
|
renderIds: objects.filter((object) => !object.hidden).map((object) => object.renderId)
|
|
@@ -1476,7 +1695,7 @@ var WorldOrbit = (() => {
|
|
|
1476
1695
|
{ id: "metadata", renderIds: ["wo-title", "wo-subtitle", "wo-meta"] }
|
|
1477
1696
|
];
|
|
1478
1697
|
}
|
|
1479
|
-
function createSceneGroups(objects, orbitVisuals, leaders, labels, relationships) {
|
|
1698
|
+
function createSceneGroups(objects, orbitVisuals, leaders, labels, relationships, labelMultiplier) {
|
|
1480
1699
|
const groups = /* @__PURE__ */ new Map();
|
|
1481
1700
|
const ensureGroup = (groupId) => {
|
|
1482
1701
|
if (!groupId) {
|
|
@@ -1525,7 +1744,7 @@ var WorldOrbit = (() => {
|
|
|
1525
1744
|
}
|
|
1526
1745
|
}
|
|
1527
1746
|
for (const group of groups.values()) {
|
|
1528
|
-
group.contentBounds = calculateGroupBounds(group, objects, orbitVisuals, leaders, labels);
|
|
1747
|
+
group.contentBounds = calculateGroupBounds(group, objects, orbitVisuals, leaders, labels, labelMultiplier);
|
|
1529
1748
|
}
|
|
1530
1749
|
return [...groups.values()].sort((left, right) => left.label.localeCompare(right.label));
|
|
1531
1750
|
}
|
|
@@ -1559,6 +1778,29 @@ var WorldOrbit = (() => {
|
|
|
1559
1778
|
};
|
|
1560
1779
|
}).sort((left, right) => left.relation.id.localeCompare(right.relation.id));
|
|
1561
1780
|
}
|
|
1781
|
+
function createSceneEvents(events, objects, activeEventId) {
|
|
1782
|
+
const objectMap = new Map(objects.map((object) => [object.objectId, object]));
|
|
1783
|
+
return events.map((event) => {
|
|
1784
|
+
const objectIds = [.../* @__PURE__ */ new Set([
|
|
1785
|
+
...event.targetObjectId ? [event.targetObjectId] : [],
|
|
1786
|
+
...event.participantObjectIds
|
|
1787
|
+
])];
|
|
1788
|
+
const positions = objectIds.map((objectId) => objectMap.get(objectId)).filter(Boolean);
|
|
1789
|
+
const centroidX = positions.length > 0 ? positions.reduce((sum, object) => sum + object.x, 0) / positions.length : 0;
|
|
1790
|
+
const centroidY = positions.length > 0 ? positions.reduce((sum, object) => sum + object.y, 0) / positions.length : 0;
|
|
1791
|
+
return {
|
|
1792
|
+
renderId: `${createRenderId(event.id)}-event`,
|
|
1793
|
+
eventId: event.id,
|
|
1794
|
+
event,
|
|
1795
|
+
objectIds,
|
|
1796
|
+
participantIds: [...event.participantObjectIds],
|
|
1797
|
+
targetObjectId: event.targetObjectId,
|
|
1798
|
+
x: centroidX,
|
|
1799
|
+
y: centroidY,
|
|
1800
|
+
hidden: event.hidden || positions.length === 0 || positions.every((object) => object.hidden) || activeEventId !== null && event.id !== activeEventId
|
|
1801
|
+
};
|
|
1802
|
+
}).sort((left, right) => left.event.id.localeCompare(right.event.id));
|
|
1803
|
+
}
|
|
1562
1804
|
function createSceneViewpoints(document2, projection, preset, relationships, objectMap) {
|
|
1563
1805
|
const generatedOverview = createGeneratedOverviewViewpoint(document2, projection, preset);
|
|
1564
1806
|
const drafts = /* @__PURE__ */ new Map();
|
|
@@ -1606,13 +1848,18 @@ var WorldOrbit = (() => {
|
|
|
1606
1848
|
function createGeneratedOverviewViewpoint(document2, projection, preset) {
|
|
1607
1849
|
const title = document2.system?.title ?? document2.system?.properties.title;
|
|
1608
1850
|
const label = title ? `${String(title)} Overview` : "Overview";
|
|
1851
|
+
const camera = normalizeViewCamera(null);
|
|
1852
|
+
const renderProjection = resolveRenderProjection(projection, camera);
|
|
1609
1853
|
return {
|
|
1610
1854
|
id: "overview",
|
|
1611
1855
|
label,
|
|
1612
1856
|
summary: "Fit the whole system with the current atlas defaults.",
|
|
1613
1857
|
objectId: null,
|
|
1614
1858
|
selectedObjectId: null,
|
|
1859
|
+
eventIds: [],
|
|
1615
1860
|
projection,
|
|
1861
|
+
renderProjection,
|
|
1862
|
+
camera,
|
|
1616
1863
|
preset,
|
|
1617
1864
|
rotationDeg: 0,
|
|
1618
1865
|
scale: null,
|
|
@@ -1648,6 +1895,9 @@ var WorldOrbit = (() => {
|
|
|
1648
1895
|
draft.select = normalizedValue;
|
|
1649
1896
|
}
|
|
1650
1897
|
return;
|
|
1898
|
+
case "events":
|
|
1899
|
+
draft.eventIds = splitListValue(normalizedValue);
|
|
1900
|
+
return;
|
|
1651
1901
|
case "projection":
|
|
1652
1902
|
case "view":
|
|
1653
1903
|
draft.projection = parseViewProjection(normalizedValue) ?? projection;
|
|
@@ -1659,6 +1909,30 @@ var WorldOrbit = (() => {
|
|
|
1659
1909
|
case "angle":
|
|
1660
1910
|
draft.rotationDeg = parseFiniteNumber(normalizedValue) ?? draft.rotationDeg ?? 0;
|
|
1661
1911
|
return;
|
|
1912
|
+
case "camera.azimuth":
|
|
1913
|
+
draft.camera = {
|
|
1914
|
+
...draft.camera ?? createEmptyViewCamera(),
|
|
1915
|
+
azimuth: parseFiniteNumber(normalizedValue)
|
|
1916
|
+
};
|
|
1917
|
+
return;
|
|
1918
|
+
case "camera.elevation":
|
|
1919
|
+
draft.camera = {
|
|
1920
|
+
...draft.camera ?? createEmptyViewCamera(),
|
|
1921
|
+
elevation: parseFiniteNumber(normalizedValue)
|
|
1922
|
+
};
|
|
1923
|
+
return;
|
|
1924
|
+
case "camera.roll":
|
|
1925
|
+
draft.camera = {
|
|
1926
|
+
...draft.camera ?? createEmptyViewCamera(),
|
|
1927
|
+
roll: parseFiniteNumber(normalizedValue)
|
|
1928
|
+
};
|
|
1929
|
+
return;
|
|
1930
|
+
case "camera.distance":
|
|
1931
|
+
draft.camera = {
|
|
1932
|
+
...draft.camera ?? createEmptyViewCamera(),
|
|
1933
|
+
distance: parsePositiveNumber(normalizedValue)
|
|
1934
|
+
};
|
|
1935
|
+
return;
|
|
1662
1936
|
case "zoom":
|
|
1663
1937
|
case "scale":
|
|
1664
1938
|
draft.scale = parsePositiveNumber(normalizedValue);
|
|
@@ -1698,13 +1972,19 @@ var WorldOrbit = (() => {
|
|
|
1698
1972
|
const selectedObjectId = draft.select && objectMap.has(draft.select) ? draft.select : objectId;
|
|
1699
1973
|
const filter = normalizeViewpointFilter(draft.filter);
|
|
1700
1974
|
const label = draft.label?.trim() || humanizeIdentifier(draft.id);
|
|
1975
|
+
const resolvedProjection = draft.projection ?? projection;
|
|
1976
|
+
const camera = normalizeViewCamera(draft.camera ?? null);
|
|
1977
|
+
const renderProjection = resolveRenderProjection(resolvedProjection, camera);
|
|
1701
1978
|
return {
|
|
1702
1979
|
id: draft.id,
|
|
1703
1980
|
label,
|
|
1704
1981
|
summary: draft.summary?.trim() || createViewpointSummary(label, objectId, filter),
|
|
1705
1982
|
objectId,
|
|
1706
1983
|
selectedObjectId,
|
|
1707
|
-
|
|
1984
|
+
eventIds: [...new Set(draft.eventIds ?? [])],
|
|
1985
|
+
projection: resolvedProjection,
|
|
1986
|
+
renderProjection,
|
|
1987
|
+
camera,
|
|
1708
1988
|
preset: draft.preset ?? preset,
|
|
1709
1989
|
rotationDeg: draft.rotationDeg ?? 0,
|
|
1710
1990
|
scale: draft.scale ?? null,
|
|
@@ -1721,6 +2001,14 @@ var WorldOrbit = (() => {
|
|
|
1721
2001
|
groupIds: []
|
|
1722
2002
|
};
|
|
1723
2003
|
}
|
|
2004
|
+
function createEmptyViewCamera() {
|
|
2005
|
+
return {
|
|
2006
|
+
azimuth: null,
|
|
2007
|
+
elevation: null,
|
|
2008
|
+
roll: null,
|
|
2009
|
+
distance: null
|
|
2010
|
+
};
|
|
2011
|
+
}
|
|
1724
2012
|
function normalizeViewpointFilter(filter) {
|
|
1725
2013
|
if (!filter) {
|
|
1726
2014
|
return null;
|
|
@@ -1734,7 +2022,18 @@ var WorldOrbit = (() => {
|
|
|
1734
2022
|
return normalized.query || normalized.objectTypes.length > 0 || normalized.tags.length > 0 || normalized.groupIds.length > 0 ? normalized : null;
|
|
1735
2023
|
}
|
|
1736
2024
|
function parseViewProjection(value) {
|
|
1737
|
-
|
|
2025
|
+
switch (value.toLowerCase()) {
|
|
2026
|
+
case "topdown":
|
|
2027
|
+
return "topdown";
|
|
2028
|
+
case "isometric":
|
|
2029
|
+
return "isometric";
|
|
2030
|
+
case "orthographic":
|
|
2031
|
+
return "orthographic";
|
|
2032
|
+
case "perspective":
|
|
2033
|
+
return "perspective";
|
|
2034
|
+
default:
|
|
2035
|
+
return null;
|
|
2036
|
+
}
|
|
1738
2037
|
}
|
|
1739
2038
|
function parseRenderPreset(value) {
|
|
1740
2039
|
const normalized = value.toLowerCase();
|
|
@@ -1761,7 +2060,7 @@ var WorldOrbit = (() => {
|
|
|
1761
2060
|
next["orbits-front"] = enabled;
|
|
1762
2061
|
continue;
|
|
1763
2062
|
}
|
|
1764
|
-
if (rawLayer === "background" || rawLayer === "guides" || rawLayer === "orbits-back" || rawLayer === "orbits-front" || rawLayer === "relations" || rawLayer === "objects" || rawLayer === "labels" || rawLayer === "metadata") {
|
|
2063
|
+
if (rawLayer === "background" || rawLayer === "guides" || rawLayer === "orbits-back" || rawLayer === "orbits-front" || rawLayer === "relations" || rawLayer === "events" || rawLayer === "objects" || rawLayer === "labels" || rawLayer === "metadata") {
|
|
1765
2064
|
next[rawLayer] = enabled;
|
|
1766
2065
|
}
|
|
1767
2066
|
}
|
|
@@ -1772,7 +2071,7 @@ var WorldOrbit = (() => {
|
|
|
1772
2071
|
}
|
|
1773
2072
|
function parseViewpointGroups(value, document2, relationships, objectMap) {
|
|
1774
2073
|
return splitListValue(value).map((entry) => {
|
|
1775
|
-
if (document2.schemaVersion === "2.1" || document2.groups.some((group) => group.id === entry)) {
|
|
2074
|
+
if (document2.schemaVersion === "2.1" || document2.schemaVersion === "2.5" || document2.groups.some((group) => group.id === entry)) {
|
|
1776
2075
|
return entry;
|
|
1777
2076
|
}
|
|
1778
2077
|
if (entry.startsWith("wo-") && entry.endsWith("-group")) {
|
|
@@ -1809,7 +2108,7 @@ var WorldOrbit = (() => {
|
|
|
1809
2108
|
}
|
|
1810
2109
|
return parts.join(" - ");
|
|
1811
2110
|
}
|
|
1812
|
-
function calculateContentBounds(width, height, objects, orbitVisuals, leaders, labels) {
|
|
2111
|
+
function calculateContentBounds(width, height, objects, orbitVisuals, leaders, labels, labelMultiplier) {
|
|
1813
2112
|
let minX = Number.POSITIVE_INFINITY;
|
|
1814
2113
|
let minY = Number.POSITIVE_INFINITY;
|
|
1815
2114
|
let maxX = Number.NEGATIVE_INFINITY;
|
|
@@ -1839,7 +2138,7 @@ var WorldOrbit = (() => {
|
|
|
1839
2138
|
for (const label of labels) {
|
|
1840
2139
|
if (label.hidden)
|
|
1841
2140
|
continue;
|
|
1842
|
-
includeLabelBounds(label, include);
|
|
2141
|
+
includeLabelBounds(label, include, labelMultiplier);
|
|
1843
2142
|
}
|
|
1844
2143
|
if (!Number.isFinite(minX) || !Number.isFinite(minY)) {
|
|
1845
2144
|
return createBounds(0, 0, width, height);
|
|
@@ -1877,13 +2176,10 @@ var WorldOrbit = (() => {
|
|
|
1877
2176
|
include(object.x - object.visualRadius - 24, object.y - object.visualRadius - 16);
|
|
1878
2177
|
include(object.x + object.visualRadius + 24, object.y + object.visualRadius + 36);
|
|
1879
2178
|
}
|
|
1880
|
-
function includeLabelBounds(label, include) {
|
|
1881
|
-
const
|
|
1882
|
-
|
|
1883
|
-
include(
|
|
1884
|
-
include(label.x + labelHalfWidth, label.y + 8);
|
|
1885
|
-
include(label.x - labelHalfWidth, label.secondaryY - 14);
|
|
1886
|
-
include(label.x + labelHalfWidth, label.secondaryY + 8);
|
|
2179
|
+
function includeLabelBounds(label, include, labelMultiplier) {
|
|
2180
|
+
const bounds = createLabelRectFromText(label.x, label.y, label.secondaryY, label.textAnchor, label.direction, label.label, label.secondaryLabel, labelMultiplier);
|
|
2181
|
+
include(bounds.left, bounds.top);
|
|
2182
|
+
include(bounds.right, bounds.bottom);
|
|
1887
2183
|
}
|
|
1888
2184
|
function placeObject(object, x, y, depth, positions, orbitDrafts, leaderDrafts, context) {
|
|
1889
2185
|
if (positions.has(object.id)) {
|
|
@@ -2273,7 +2569,7 @@ var WorldOrbit = (() => {
|
|
|
2273
2569
|
return null;
|
|
2274
2570
|
}
|
|
2275
2571
|
}
|
|
2276
|
-
function calculateGroupBounds(group, objects, orbitVisuals, leaders, labels) {
|
|
2572
|
+
function calculateGroupBounds(group, objects, orbitVisuals, leaders, labels, labelMultiplier) {
|
|
2277
2573
|
let minX = Number.POSITIVE_INFINITY;
|
|
2278
2574
|
let minY = Number.POSITIVE_INFINITY;
|
|
2279
2575
|
let maxX = Number.NEGATIVE_INFINITY;
|
|
@@ -2302,7 +2598,7 @@ var WorldOrbit = (() => {
|
|
|
2302
2598
|
}
|
|
2303
2599
|
for (const label of labels) {
|
|
2304
2600
|
if (!label.hidden && group.labelIds.includes(label.objectId)) {
|
|
2305
|
-
includeLabelBounds(label, include);
|
|
2601
|
+
includeLabelBounds(label, include, labelMultiplier);
|
|
2306
2602
|
}
|
|
2307
2603
|
}
|
|
2308
2604
|
if (!Number.isFinite(minX) || !Number.isFinite(minY)) {
|
|
@@ -2327,12 +2623,28 @@ var WorldOrbit = (() => {
|
|
|
2327
2623
|
}
|
|
2328
2624
|
return current.id;
|
|
2329
2625
|
}
|
|
2330
|
-
function createLabelRect(
|
|
2626
|
+
function createLabelRect(object, placement, labelMultiplier) {
|
|
2627
|
+
return createLabelRectFromText(placement.x, placement.labelY, placement.secondaryY, placement.textAnchor, placement.direction, object.label, object.secondaryLabel, labelMultiplier);
|
|
2628
|
+
}
|
|
2629
|
+
function createLabelRectFromText(x, labelY, secondaryY, textAnchor, direction, label, secondaryLabel, labelMultiplier) {
|
|
2630
|
+
const labelHalfWidth = estimateLabelHalfWidthFromText(label, secondaryLabel, labelMultiplier);
|
|
2631
|
+
const labelWidth = labelHalfWidth * 2;
|
|
2632
|
+
const topPadding = direction === "above" ? 18 : 12;
|
|
2633
|
+
const bottomPadding = direction === "above" ? 8 : 12;
|
|
2634
|
+
let left = x - labelHalfWidth;
|
|
2635
|
+
let right = x + labelHalfWidth;
|
|
2636
|
+
if (textAnchor === "start") {
|
|
2637
|
+
left = x;
|
|
2638
|
+
right = x + labelWidth;
|
|
2639
|
+
} else if (textAnchor === "end") {
|
|
2640
|
+
left = x - labelWidth;
|
|
2641
|
+
right = x;
|
|
2642
|
+
}
|
|
2331
2643
|
return {
|
|
2332
|
-
left
|
|
2333
|
-
right
|
|
2334
|
-
top: Math.min(labelY, secondaryY) -
|
|
2335
|
-
bottom: Math.max(labelY, secondaryY) +
|
|
2644
|
+
left,
|
|
2645
|
+
right,
|
|
2646
|
+
top: Math.min(labelY, secondaryY) - topPadding,
|
|
2647
|
+
bottom: Math.max(labelY, secondaryY) + bottomPadding
|
|
2336
2648
|
};
|
|
2337
2649
|
}
|
|
2338
2650
|
function rectsOverlap(left, right) {
|
|
@@ -2519,11 +2831,6 @@ var WorldOrbit = (() => {
|
|
|
2519
2831
|
function customColorFor(value) {
|
|
2520
2832
|
return typeof value === "string" && value.trim() ? value : void 0;
|
|
2521
2833
|
}
|
|
2522
|
-
function estimateLabelHalfWidth(object, labelMultiplier) {
|
|
2523
|
-
const primaryWidth = object.label.length * 4.6 * labelMultiplier + 18;
|
|
2524
|
-
const secondaryWidth = object.secondaryLabel.length * 3.9 * labelMultiplier + 18;
|
|
2525
|
-
return Math.max(primaryWidth, secondaryWidth, object.visualRadius + 18);
|
|
2526
|
-
}
|
|
2527
2834
|
function estimateLabelHalfWidthFromText(label, secondaryLabel, labelMultiplier) {
|
|
2528
2835
|
const primaryWidth = label.length * 4.6 * labelMultiplier + 18;
|
|
2529
2836
|
const secondaryWidth = secondaryLabel.length * 3.9 * labelMultiplier + 18;
|
|
@@ -2557,12 +2864,13 @@ var WorldOrbit = (() => {
|
|
|
2557
2864
|
}
|
|
2558
2865
|
return {
|
|
2559
2866
|
format: "worldorbit",
|
|
2560
|
-
version: "2.
|
|
2561
|
-
schemaVersion: "2.
|
|
2867
|
+
version: "2.5",
|
|
2868
|
+
schemaVersion: "2.5",
|
|
2562
2869
|
sourceVersion: document2.version,
|
|
2563
2870
|
system,
|
|
2564
2871
|
groups: structuredClone(document2.groups ?? []),
|
|
2565
2872
|
relations: structuredClone(document2.relations ?? []),
|
|
2873
|
+
events: structuredClone(document2.events ?? []),
|
|
2566
2874
|
objects: document2.objects.map(cloneWorldOrbitObject),
|
|
2567
2875
|
diagnostics
|
|
2568
2876
|
};
|
|
@@ -2570,7 +2878,7 @@ var WorldOrbit = (() => {
|
|
|
2570
2878
|
function upgradeDocumentToDraftV2(document2, options = {}) {
|
|
2571
2879
|
return convertAtlasDocumentToLegacyDraft(upgradeDocumentToV2(document2, options));
|
|
2572
2880
|
}
|
|
2573
|
-
function materializeAtlasDocument(document2) {
|
|
2881
|
+
function materializeAtlasDocument(document2, options = {}) {
|
|
2574
2882
|
const system = document2.system ? {
|
|
2575
2883
|
type: "system",
|
|
2576
2884
|
id: document2.system.id,
|
|
@@ -2581,6 +2889,8 @@ var WorldOrbit = (() => {
|
|
|
2581
2889
|
properties: materializeDraftSystemProperties(document2.system),
|
|
2582
2890
|
info: materializeDraftSystemInfo(document2.system)
|
|
2583
2891
|
} : null;
|
|
2892
|
+
const objects = document2.objects.map(cloneWorldOrbitObject);
|
|
2893
|
+
applyEventPoseOverrides(objects, document2.events ?? [], options.activeEventId ?? null);
|
|
2584
2894
|
return {
|
|
2585
2895
|
format: "worldorbit",
|
|
2586
2896
|
version: "1.0",
|
|
@@ -2588,7 +2898,8 @@ var WorldOrbit = (() => {
|
|
|
2588
2898
|
system,
|
|
2589
2899
|
groups: structuredClone(document2.groups ?? []),
|
|
2590
2900
|
relations: structuredClone(document2.relations ?? []),
|
|
2591
|
-
|
|
2901
|
+
events: document2.events.map(cloneWorldOrbitEvent),
|
|
2902
|
+
objects
|
|
2592
2903
|
};
|
|
2593
2904
|
}
|
|
2594
2905
|
function materializeDraftDocument(document2) {
|
|
@@ -2613,8 +2924,9 @@ var WorldOrbit = (() => {
|
|
|
2613
2924
|
};
|
|
2614
2925
|
}
|
|
2615
2926
|
function createDraftDefaults(document2, preset, projection) {
|
|
2927
|
+
const rawView = typeof document2.system?.properties.view === "string" ? document2.system.properties.view.toLowerCase() : null;
|
|
2616
2928
|
return {
|
|
2617
|
-
view:
|
|
2929
|
+
view: rawView === "topdown" || rawView === "isometric" || rawView === "orthographic" || rawView === "perspective" ? rawView : projection,
|
|
2618
2930
|
scale: typeof document2.system?.properties.scale === "string" ? document2.system.properties.scale : null,
|
|
2619
2931
|
units: typeof document2.system?.properties.units === "string" ? document2.system.properties.units : null,
|
|
2620
2932
|
preset,
|
|
@@ -2716,10 +3028,12 @@ var WorldOrbit = (() => {
|
|
|
2716
3028
|
summary: viewpoint.summary,
|
|
2717
3029
|
focusObjectId: viewpoint.objectId,
|
|
2718
3030
|
selectedObjectId: viewpoint.selectedObjectId,
|
|
3031
|
+
events: [...viewpoint.eventIds],
|
|
2719
3032
|
projection: viewpoint.projection,
|
|
2720
3033
|
preset: viewpoint.preset,
|
|
2721
3034
|
zoom: viewpoint.scale,
|
|
2722
3035
|
rotationDeg: viewpoint.rotationDeg,
|
|
3036
|
+
camera: viewpoint.camera ? { ...viewpoint.camera } : null,
|
|
2723
3037
|
layers: { ...viewpoint.layers },
|
|
2724
3038
|
filter: viewpoint.filter ? {
|
|
2725
3039
|
query: viewpoint.filter.query,
|
|
@@ -2748,6 +3062,75 @@ var WorldOrbit = (() => {
|
|
|
2748
3062
|
info: { ...object.info }
|
|
2749
3063
|
};
|
|
2750
3064
|
}
|
|
3065
|
+
function cloneWorldOrbitEvent(event) {
|
|
3066
|
+
return {
|
|
3067
|
+
...event,
|
|
3068
|
+
participantObjectIds: [...event.participantObjectIds],
|
|
3069
|
+
tags: [...event.tags],
|
|
3070
|
+
positions: event.positions.map(cloneWorldOrbitEventPose)
|
|
3071
|
+
};
|
|
3072
|
+
}
|
|
3073
|
+
function cloneWorldOrbitEventPose(pose) {
|
|
3074
|
+
return {
|
|
3075
|
+
objectId: pose.objectId,
|
|
3076
|
+
placement: clonePlacement(pose.placement),
|
|
3077
|
+
inner: pose.inner ? { ...pose.inner } : void 0,
|
|
3078
|
+
outer: pose.outer ? { ...pose.outer } : void 0,
|
|
3079
|
+
epoch: pose.epoch ?? null,
|
|
3080
|
+
referencePlane: pose.referencePlane ?? null
|
|
3081
|
+
};
|
|
3082
|
+
}
|
|
3083
|
+
function clonePlacement(placement) {
|
|
3084
|
+
return placement ? structuredClone(placement) : null;
|
|
3085
|
+
}
|
|
3086
|
+
function applyEventPoseOverrides(objects, events, activeEventId) {
|
|
3087
|
+
if (!activeEventId) {
|
|
3088
|
+
return;
|
|
3089
|
+
}
|
|
3090
|
+
const event = events.find((entry) => entry.id === activeEventId);
|
|
3091
|
+
if (!event) {
|
|
3092
|
+
return;
|
|
3093
|
+
}
|
|
3094
|
+
const objectMap = new Map(objects.map((object) => [object.id, object]));
|
|
3095
|
+
const referencedIds = /* @__PURE__ */ new Set([
|
|
3096
|
+
...event.targetObjectId ? [event.targetObjectId] : [],
|
|
3097
|
+
...event.participantObjectIds,
|
|
3098
|
+
...event.positions.map((pose) => pose.objectId)
|
|
3099
|
+
]);
|
|
3100
|
+
for (const objectId of referencedIds) {
|
|
3101
|
+
const object = objectMap.get(objectId);
|
|
3102
|
+
if (!object) {
|
|
3103
|
+
continue;
|
|
3104
|
+
}
|
|
3105
|
+
if (event.epoch) {
|
|
3106
|
+
object.epoch = event.epoch;
|
|
3107
|
+
}
|
|
3108
|
+
if (event.referencePlane) {
|
|
3109
|
+
object.referencePlane = event.referencePlane;
|
|
3110
|
+
}
|
|
3111
|
+
}
|
|
3112
|
+
for (const pose of event.positions) {
|
|
3113
|
+
const object = objectMap.get(pose.objectId);
|
|
3114
|
+
if (!object) {
|
|
3115
|
+
continue;
|
|
3116
|
+
}
|
|
3117
|
+
if (pose.placement) {
|
|
3118
|
+
object.placement = clonePlacement(pose.placement);
|
|
3119
|
+
}
|
|
3120
|
+
if (pose.inner) {
|
|
3121
|
+
object.properties.inner = { ...pose.inner };
|
|
3122
|
+
}
|
|
3123
|
+
if (pose.outer) {
|
|
3124
|
+
object.properties.outer = { ...pose.outer };
|
|
3125
|
+
}
|
|
3126
|
+
if (pose.epoch) {
|
|
3127
|
+
object.epoch = pose.epoch;
|
|
3128
|
+
}
|
|
3129
|
+
if (pose.referencePlane) {
|
|
3130
|
+
object.referencePlane = pose.referencePlane;
|
|
3131
|
+
}
|
|
3132
|
+
}
|
|
3133
|
+
}
|
|
2751
3134
|
function cloneProperties(properties) {
|
|
2752
3135
|
const next = {};
|
|
2753
3136
|
for (const [key, value] of Object.entries(properties)) {
|
|
@@ -2829,6 +3212,18 @@ var WorldOrbit = (() => {
|
|
|
2829
3212
|
if (viewpoint.rotationDeg !== 0) {
|
|
2830
3213
|
info2[`${prefix}.rotation`] = String(viewpoint.rotationDeg);
|
|
2831
3214
|
}
|
|
3215
|
+
if (viewpoint.camera?.azimuth !== null) {
|
|
3216
|
+
info2[`${prefix}.camera.azimuth`] = String(viewpoint.camera?.azimuth);
|
|
3217
|
+
}
|
|
3218
|
+
if (viewpoint.camera?.elevation !== null) {
|
|
3219
|
+
info2[`${prefix}.camera.elevation`] = String(viewpoint.camera?.elevation);
|
|
3220
|
+
}
|
|
3221
|
+
if (viewpoint.camera?.roll !== null) {
|
|
3222
|
+
info2[`${prefix}.camera.roll`] = String(viewpoint.camera?.roll);
|
|
3223
|
+
}
|
|
3224
|
+
if (viewpoint.camera?.distance !== null) {
|
|
3225
|
+
info2[`${prefix}.camera.distance`] = String(viewpoint.camera?.distance);
|
|
3226
|
+
}
|
|
2832
3227
|
const serializedLayers = serializeViewpointLayers(viewpoint.layers);
|
|
2833
3228
|
if (serializedLayers) {
|
|
2834
3229
|
info2[`${prefix}.layers`] = serializedLayers;
|
|
@@ -2845,6 +3240,9 @@ var WorldOrbit = (() => {
|
|
|
2845
3240
|
if ((viewpoint.filter?.groupIds.length ?? 0) > 0) {
|
|
2846
3241
|
info2[`${prefix}.groups`] = viewpoint.filter?.groupIds.join(" ") ?? "";
|
|
2847
3242
|
}
|
|
3243
|
+
if (viewpoint.events.length > 0) {
|
|
3244
|
+
info2[`${prefix}.events`] = viewpoint.events.join(" ");
|
|
3245
|
+
}
|
|
2848
3246
|
}
|
|
2849
3247
|
for (const annotation of system.annotations) {
|
|
2850
3248
|
const prefix = `annotation.${annotation.id}`;
|
|
@@ -2869,7 +3267,7 @@ var WorldOrbit = (() => {
|
|
|
2869
3267
|
if (orbitFront !== void 0 || orbitBack !== void 0) {
|
|
2870
3268
|
tokens.push(orbitFront !== false || orbitBack !== false ? "orbits" : "-orbits");
|
|
2871
3269
|
}
|
|
2872
|
-
for (const key of ["background", "guides", "relations", "objects", "labels", "metadata"]) {
|
|
3270
|
+
for (const key of ["background", "guides", "relations", "events", "objects", "labels", "metadata"]) {
|
|
2873
3271
|
if (layers[key] !== void 0) {
|
|
2874
3272
|
tokens.push(layers[key] ? key : `-${key}`);
|
|
2875
3273
|
}
|
|
@@ -2922,26 +3320,26 @@ var WorldOrbit = (() => {
|
|
|
2922
3320
|
];
|
|
2923
3321
|
function formatDocument(document2, options = {}) {
|
|
2924
3322
|
const schema = options.schema ?? "auto";
|
|
2925
|
-
const useDraft = schema === "2.0" || schema === "2.1" || schema === "2.0-draft" || document2.version === "2.0" || document2.version === "2.1" || document2.version === "2.0-draft";
|
|
3323
|
+
const useDraft = schema === "2.0" || schema === "2.1" || schema === "2.5" || schema === "2.0-draft" || document2.version === "2.0" || document2.version === "2.1" || document2.version === "2.5" || document2.version === "2.0-draft";
|
|
2926
3324
|
if (useDraft) {
|
|
2927
3325
|
if (schema === "2.0-draft") {
|
|
2928
|
-
const legacyDraftDocument = document2.version === "2.0-draft" ? document2 : document2.version === "2.0" || document2.version === "2.1" ? {
|
|
3326
|
+
const legacyDraftDocument = document2.version === "2.0-draft" ? document2 : document2.version === "2.0" || document2.version === "2.1" || document2.version === "2.5" ? {
|
|
2929
3327
|
...document2,
|
|
2930
3328
|
version: "2.0-draft",
|
|
2931
3329
|
schemaVersion: "2.0-draft"
|
|
2932
3330
|
} : upgradeDocumentToDraftV2(document2);
|
|
2933
3331
|
return formatDraftDocument(legacyDraftDocument);
|
|
2934
3332
|
}
|
|
2935
|
-
const atlasDocument = document2.version === "2.0" || document2.version === "2.1" ? document2 : document2.version === "2.0-draft" ? {
|
|
3333
|
+
const atlasDocument = document2.version === "2.0" || document2.version === "2.1" || document2.version === "2.5" ? document2 : document2.version === "2.0-draft" ? {
|
|
2936
3334
|
...document2,
|
|
2937
3335
|
version: "2.0",
|
|
2938
3336
|
schemaVersion: "2.0"
|
|
2939
3337
|
} : upgradeDocumentToV2(document2);
|
|
2940
|
-
if (schema === "2.1" && atlasDocument.version !==
|
|
3338
|
+
if ((schema === "2.0" || schema === "2.1" || schema === "2.5") && atlasDocument.version !== schema) {
|
|
2941
3339
|
return formatAtlasDocument({
|
|
2942
3340
|
...atlasDocument,
|
|
2943
|
-
version:
|
|
2944
|
-
schemaVersion:
|
|
3341
|
+
version: schema,
|
|
3342
|
+
schemaVersion: schema
|
|
2945
3343
|
});
|
|
2946
3344
|
}
|
|
2947
3345
|
return formatAtlasDocument(atlasDocument);
|
|
@@ -2973,6 +3371,10 @@ var WorldOrbit = (() => {
|
|
|
2973
3371
|
lines.push("");
|
|
2974
3372
|
lines.push(...formatAtlasRelation(relation));
|
|
2975
3373
|
}
|
|
3374
|
+
for (const event of [...document2.events].sort(compareIdLike)) {
|
|
3375
|
+
lines.push("");
|
|
3376
|
+
lines.push(...formatAtlasEvent(event));
|
|
3377
|
+
}
|
|
2976
3378
|
const sortedObjects = [...document2.objects].sort(compareObjects);
|
|
2977
3379
|
if (sortedObjects.length > 0 && lines.at(-1) !== "") {
|
|
2978
3380
|
lines.push("");
|
|
@@ -3003,6 +3405,10 @@ var WorldOrbit = (() => {
|
|
|
3003
3405
|
lines.push("");
|
|
3004
3406
|
lines.push(...formatAtlasRelation(relation));
|
|
3005
3407
|
}
|
|
3408
|
+
for (const event of [...legacy.events].sort(compareIdLike)) {
|
|
3409
|
+
lines.push("");
|
|
3410
|
+
lines.push(...formatAtlasEvent(event));
|
|
3411
|
+
}
|
|
3006
3412
|
const sortedObjects = [...legacy.objects].sort(compareObjects);
|
|
3007
3413
|
if (sortedObjects.length > 0 && lines.at(-1) !== "") {
|
|
3008
3414
|
lines.push("");
|
|
@@ -3210,10 +3616,28 @@ var WorldOrbit = (() => {
|
|
|
3210
3616
|
if (viewpoint.rotationDeg !== 0) {
|
|
3211
3617
|
lines.push(` rotation ${viewpoint.rotationDeg}`);
|
|
3212
3618
|
}
|
|
3619
|
+
if (viewpoint.camera && hasCameraValues(viewpoint.camera)) {
|
|
3620
|
+
lines.push(" camera");
|
|
3621
|
+
if (viewpoint.camera.azimuth !== null) {
|
|
3622
|
+
lines.push(` azimuth ${viewpoint.camera.azimuth}`);
|
|
3623
|
+
}
|
|
3624
|
+
if (viewpoint.camera.elevation !== null) {
|
|
3625
|
+
lines.push(` elevation ${viewpoint.camera.elevation}`);
|
|
3626
|
+
}
|
|
3627
|
+
if (viewpoint.camera.roll !== null) {
|
|
3628
|
+
lines.push(` roll ${viewpoint.camera.roll}`);
|
|
3629
|
+
}
|
|
3630
|
+
if (viewpoint.camera.distance !== null) {
|
|
3631
|
+
lines.push(` distance ${viewpoint.camera.distance}`);
|
|
3632
|
+
}
|
|
3633
|
+
}
|
|
3213
3634
|
const layerTokens = formatDraftLayers(viewpoint.layers);
|
|
3214
3635
|
if (layerTokens.length > 0) {
|
|
3215
3636
|
lines.push(` layers ${layerTokens.join(" ")}`);
|
|
3216
3637
|
}
|
|
3638
|
+
if (viewpoint.events.length > 0) {
|
|
3639
|
+
lines.push(` events ${viewpoint.events.join(" ")}`);
|
|
3640
|
+
}
|
|
3217
3641
|
if (viewpoint.filter) {
|
|
3218
3642
|
lines.push(" filter");
|
|
3219
3643
|
if (viewpoint.filter.query) {
|
|
@@ -3286,6 +3710,65 @@ var WorldOrbit = (() => {
|
|
|
3286
3710
|
}
|
|
3287
3711
|
return lines;
|
|
3288
3712
|
}
|
|
3713
|
+
function formatAtlasEvent(event) {
|
|
3714
|
+
const lines = [`event ${event.id}`, ` kind ${quoteIfNeeded(event.kind)}`];
|
|
3715
|
+
if (event.label) {
|
|
3716
|
+
lines.push(` label ${quoteIfNeeded(event.label)}`);
|
|
3717
|
+
}
|
|
3718
|
+
if (event.summary) {
|
|
3719
|
+
lines.push(` summary ${quoteIfNeeded(event.summary)}`);
|
|
3720
|
+
}
|
|
3721
|
+
if (event.targetObjectId) {
|
|
3722
|
+
lines.push(` target ${event.targetObjectId}`);
|
|
3723
|
+
}
|
|
3724
|
+
if (event.participantObjectIds.length > 0) {
|
|
3725
|
+
lines.push(` participants ${event.participantObjectIds.join(" ")}`);
|
|
3726
|
+
}
|
|
3727
|
+
if (event.timing) {
|
|
3728
|
+
lines.push(` timing ${quoteIfNeeded(event.timing)}`);
|
|
3729
|
+
}
|
|
3730
|
+
if (event.visibility) {
|
|
3731
|
+
lines.push(` visibility ${quoteIfNeeded(event.visibility)}`);
|
|
3732
|
+
}
|
|
3733
|
+
if (event.epoch) {
|
|
3734
|
+
lines.push(` epoch ${quoteIfNeeded(event.epoch)}`);
|
|
3735
|
+
}
|
|
3736
|
+
if (event.referencePlane) {
|
|
3737
|
+
lines.push(` referencePlane ${quoteIfNeeded(event.referencePlane)}`);
|
|
3738
|
+
}
|
|
3739
|
+
if (event.tags.length > 0) {
|
|
3740
|
+
lines.push(` tags ${event.tags.map(quoteIfNeeded).join(" ")}`);
|
|
3741
|
+
}
|
|
3742
|
+
if (event.color) {
|
|
3743
|
+
lines.push(` color ${quoteIfNeeded(event.color)}`);
|
|
3744
|
+
}
|
|
3745
|
+
if (event.hidden) {
|
|
3746
|
+
lines.push(" hidden true");
|
|
3747
|
+
}
|
|
3748
|
+
if (event.positions.length > 0) {
|
|
3749
|
+
lines.push("");
|
|
3750
|
+
lines.push(" positions");
|
|
3751
|
+
for (const pose of [...event.positions].sort(comparePoseObjectId)) {
|
|
3752
|
+
lines.push(` pose ${pose.objectId}`);
|
|
3753
|
+
for (const fieldLine of formatEventPoseFields(pose)) {
|
|
3754
|
+
lines.push(` ${fieldLine}`);
|
|
3755
|
+
}
|
|
3756
|
+
}
|
|
3757
|
+
}
|
|
3758
|
+
return lines;
|
|
3759
|
+
}
|
|
3760
|
+
function formatEventPoseFields(pose) {
|
|
3761
|
+
return [
|
|
3762
|
+
...formatPlacement(pose.placement),
|
|
3763
|
+
...pose.epoch ? [`epoch ${quoteIfNeeded(pose.epoch)}`] : [],
|
|
3764
|
+
...pose.referencePlane ? [`referencePlane ${quoteIfNeeded(pose.referencePlane)}`] : [],
|
|
3765
|
+
...formatOptionalUnit("inner", pose.inner),
|
|
3766
|
+
...formatOptionalUnit("outer", pose.outer)
|
|
3767
|
+
];
|
|
3768
|
+
}
|
|
3769
|
+
function hasCameraValues(camera) {
|
|
3770
|
+
return camera.azimuth !== null || camera.elevation !== null || camera.roll !== null || camera.distance !== null;
|
|
3771
|
+
}
|
|
3289
3772
|
function formatValue(value) {
|
|
3290
3773
|
if (Array.isArray(value)) {
|
|
3291
3774
|
return value.map((item) => quoteIfNeeded(item)).join(" ");
|
|
@@ -3327,7 +3810,7 @@ var WorldOrbit = (() => {
|
|
|
3327
3810
|
if (orbitFront !== void 0 || orbitBack !== void 0) {
|
|
3328
3811
|
tokens.push(orbitFront !== false || orbitBack !== false ? "orbits" : "-orbits");
|
|
3329
3812
|
}
|
|
3330
|
-
for (const key of ["background", "guides", "relations", "objects", "labels", "metadata"]) {
|
|
3813
|
+
for (const key of ["background", "guides", "relations", "events", "objects", "labels", "metadata"]) {
|
|
3331
3814
|
if (layers[key] !== void 0) {
|
|
3332
3815
|
tokens.push(layers[key] ? key : `-${key}`);
|
|
3333
3816
|
}
|
|
@@ -3355,6 +3838,9 @@ var WorldOrbit = (() => {
|
|
|
3355
3838
|
function compareIdLike(left, right) {
|
|
3356
3839
|
return left.id.localeCompare(right.id);
|
|
3357
3840
|
}
|
|
3841
|
+
function comparePoseObjectId(left, right) {
|
|
3842
|
+
return left.objectId.localeCompare(right.objectId);
|
|
3843
|
+
}
|
|
3358
3844
|
function objectTypeIndex(objectType) {
|
|
3359
3845
|
switch (objectType) {
|
|
3360
3846
|
case "star":
|
|
@@ -3550,6 +4036,7 @@ var WorldOrbit = (() => {
|
|
|
3550
4036
|
const diagnostics = [];
|
|
3551
4037
|
const objectMap = new Map(document2.objects.map((object) => [object.id, object]));
|
|
3552
4038
|
const groupIds = new Set(document2.groups.map((group) => group.id));
|
|
4039
|
+
const eventIds = new Set(document2.events.map((event) => event.id));
|
|
3553
4040
|
if (!document2.system) {
|
|
3554
4041
|
diagnostics.push(error("validate.system.required", "Atlas documents must declare exactly one system."));
|
|
3555
4042
|
}
|
|
@@ -3559,6 +4046,7 @@ var WorldOrbit = (() => {
|
|
|
3559
4046
|
["viewpoint", document2.system?.viewpoints.map((viewpoint) => viewpoint.id) ?? []],
|
|
3560
4047
|
["annotation", document2.system?.annotations.map((annotation) => annotation.id) ?? []],
|
|
3561
4048
|
["relation", document2.relations.map((relation) => relation.id)],
|
|
4049
|
+
["event", document2.events.map((event) => event.id)],
|
|
3562
4050
|
["object", document2.objects.map((object) => object.id)]
|
|
3563
4051
|
]) {
|
|
3564
4052
|
for (const id of ids) {
|
|
@@ -3574,11 +4062,14 @@ var WorldOrbit = (() => {
|
|
|
3574
4062
|
validateRelation(relation, objectMap, diagnostics);
|
|
3575
4063
|
}
|
|
3576
4064
|
for (const viewpoint of document2.system?.viewpoints ?? []) {
|
|
3577
|
-
|
|
4065
|
+
validateViewpoint(viewpoint, groupIds, eventIds, sourceSchemaVersion, diagnostics, objectMap);
|
|
3578
4066
|
}
|
|
3579
4067
|
for (const object of document2.objects) {
|
|
3580
4068
|
validateObject(object, document2.system, objectMap, groupIds, diagnostics);
|
|
3581
4069
|
}
|
|
4070
|
+
for (const event of document2.events) {
|
|
4071
|
+
validateEvent(event, document2.system, objectMap, diagnostics);
|
|
4072
|
+
}
|
|
3582
4073
|
return diagnostics;
|
|
3583
4074
|
}
|
|
3584
4075
|
function validateRelation(relation, objectMap, diagnostics) {
|
|
@@ -3596,15 +4087,24 @@ var WorldOrbit = (() => {
|
|
|
3596
4087
|
diagnostics.push(error("validate.relation.kind.required", `Relation "${relation.id}" is missing a "kind" value.`));
|
|
3597
4088
|
}
|
|
3598
4089
|
}
|
|
3599
|
-
function
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
4090
|
+
function validateViewpoint(viewpoint, groupIds, eventIds, sourceSchemaVersion, diagnostics, objectMap) {
|
|
4091
|
+
const filter = viewpoint.filter;
|
|
4092
|
+
if (sourceSchemaVersion === "2.1" || sourceSchemaVersion === "2.5") {
|
|
4093
|
+
if (filter) {
|
|
4094
|
+
for (const groupId of filter.groupIds) {
|
|
4095
|
+
if (!groupIds.has(groupId)) {
|
|
4096
|
+
diagnostics.push(warn("validate.viewpoint.group.unknown", `Unknown group "${groupId}" in viewpoint "${viewpoint.id}".`, void 0, `viewpoint.${viewpoint.id}.groups`));
|
|
4097
|
+
}
|
|
4098
|
+
}
|
|
4099
|
+
}
|
|
4100
|
+
for (const eventId of viewpoint.events ?? []) {
|
|
4101
|
+
if (!eventIds.has(eventId)) {
|
|
4102
|
+
diagnostics.push(warn("validate.viewpoint.event.unknown", `Unknown event "${eventId}" in viewpoint "${viewpoint.id}".`, void 0, `viewpoint.${viewpoint.id}.events`));
|
|
4103
|
+
}
|
|
3606
4104
|
}
|
|
3607
4105
|
}
|
|
4106
|
+
validateProjection(viewpoint.projection, diagnostics, `viewpoint.${viewpoint.id}.projection`, viewpoint.id);
|
|
4107
|
+
validateCamera(viewpoint.camera, viewpoint.projection, viewpoint.rotationDeg, diagnostics, viewpoint.id, viewpoint.focusObjectId, viewpoint.selectedObjectId, filter, objectMap);
|
|
3608
4108
|
}
|
|
3609
4109
|
function validateObject(object, system, objectMap, groupIds, diagnostics) {
|
|
3610
4110
|
const placement = object.placement;
|
|
@@ -3617,6 +4117,12 @@ var WorldOrbit = (() => {
|
|
|
3617
4117
|
}
|
|
3618
4118
|
}
|
|
3619
4119
|
}
|
|
4120
|
+
if (typeof object.epoch === "string" && !object.epoch.trim()) {
|
|
4121
|
+
diagnostics.push(warn("validate.epoch.empty", `Object "${object.id}" defines an empty epoch string.`, object.id, "epoch"));
|
|
4122
|
+
}
|
|
4123
|
+
if (typeof object.referencePlane === "string" && !object.referencePlane.trim()) {
|
|
4124
|
+
diagnostics.push(warn("validate.referencePlane.empty", `Object "${object.id}" defines an empty reference plane string.`, object.id, "referencePlane"));
|
|
4125
|
+
}
|
|
3620
4126
|
if (orbitPlacement) {
|
|
3621
4127
|
if (!objectMap.has(orbitPlacement.target)) {
|
|
3622
4128
|
diagnostics.push(error("validate.orbit.target.unknown", `Unknown placement target "${orbitPlacement.target}" on "${object.id}".`, object.id, "orbit"));
|
|
@@ -3688,6 +4194,122 @@ var WorldOrbit = (() => {
|
|
|
3688
4194
|
}
|
|
3689
4195
|
}
|
|
3690
4196
|
}
|
|
4197
|
+
function validateEvent(event, system, objectMap, diagnostics) {
|
|
4198
|
+
const fieldPrefix = `event.${event.id}`;
|
|
4199
|
+
const referencedIds = /* @__PURE__ */ new Set();
|
|
4200
|
+
if (!event.kind.trim()) {
|
|
4201
|
+
diagnostics.push(error("validate.event.kind.required", `Event "${event.id}" is missing a "kind" value.`, void 0, `${fieldPrefix}.kind`));
|
|
4202
|
+
}
|
|
4203
|
+
if (typeof event.epoch === "string" && !event.epoch.trim()) {
|
|
4204
|
+
diagnostics.push(warn("validate.event.epoch.empty", `Event "${event.id}" defines an empty epoch string.`, void 0, `${fieldPrefix}.epoch`));
|
|
4205
|
+
}
|
|
4206
|
+
if (typeof event.referencePlane === "string" && !event.referencePlane.trim()) {
|
|
4207
|
+
diagnostics.push(warn("validate.event.referencePlane.empty", `Event "${event.id}" defines an empty reference plane string.`, void 0, `${fieldPrefix}.referencePlane`));
|
|
4208
|
+
}
|
|
4209
|
+
if (!event.targetObjectId && event.participantObjectIds.length === 0) {
|
|
4210
|
+
diagnostics.push(error("validate.event.references.required", `Event "${event.id}" must define a "target" or at least one participant.`, void 0, `${fieldPrefix}.participants`));
|
|
4211
|
+
}
|
|
4212
|
+
if (event.targetObjectId) {
|
|
4213
|
+
referencedIds.add(event.targetObjectId);
|
|
4214
|
+
if (!objectMap.has(event.targetObjectId)) {
|
|
4215
|
+
diagnostics.push(error("validate.event.target.unknown", `Unknown event target "${event.targetObjectId}" on "${event.id}".`, void 0, `${fieldPrefix}.target`));
|
|
4216
|
+
}
|
|
4217
|
+
}
|
|
4218
|
+
const seenParticipants = /* @__PURE__ */ new Set();
|
|
4219
|
+
for (const participantId of event.participantObjectIds) {
|
|
4220
|
+
referencedIds.add(participantId);
|
|
4221
|
+
if (seenParticipants.has(participantId)) {
|
|
4222
|
+
diagnostics.push(warn("validate.event.participants.duplicate", `Event "${event.id}" repeats participant "${participantId}".`, void 0, `${fieldPrefix}.participants`));
|
|
4223
|
+
continue;
|
|
4224
|
+
}
|
|
4225
|
+
seenParticipants.add(participantId);
|
|
4226
|
+
if (!objectMap.has(participantId)) {
|
|
4227
|
+
diagnostics.push(error("validate.event.participants.unknown", `Unknown event participant "${participantId}" on "${event.id}".`, void 0, `${fieldPrefix}.participants`));
|
|
4228
|
+
}
|
|
4229
|
+
}
|
|
4230
|
+
if (event.targetObjectId && event.participantObjectIds.length > 0 && !event.participantObjectIds.includes(event.targetObjectId)) {
|
|
4231
|
+
diagnostics.push(warn("validate.event.target.notParticipant", `Event "${event.id}" defines a target outside its participants list.`, void 0, `${fieldPrefix}.target`));
|
|
4232
|
+
}
|
|
4233
|
+
if (event.positions.length === 0) {
|
|
4234
|
+
diagnostics.push(warn("validate.event.positions.missing", `Event "${event.id}" has no positions block and cannot drive a scene snapshot.`, void 0, `${fieldPrefix}.positions`));
|
|
4235
|
+
}
|
|
4236
|
+
if (/(?:^|[-_])(solar-eclipse|lunar-eclipse|transit|occultation)(?:$|[-_])/.test(event.kind) && referencedIds.size < 3) {
|
|
4237
|
+
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`));
|
|
4238
|
+
}
|
|
4239
|
+
const poseIds = /* @__PURE__ */ new Set();
|
|
4240
|
+
for (const pose of event.positions) {
|
|
4241
|
+
const poseFieldPrefix = `${fieldPrefix}.pose.${pose.objectId}`;
|
|
4242
|
+
if (poseIds.has(pose.objectId)) {
|
|
4243
|
+
diagnostics.push(error("validate.event.pose.duplicate", `Event "${event.id}" defines "${pose.objectId}" more than once in positions.`, void 0, poseFieldPrefix));
|
|
4244
|
+
continue;
|
|
4245
|
+
}
|
|
4246
|
+
poseIds.add(pose.objectId);
|
|
4247
|
+
const object = objectMap.get(pose.objectId);
|
|
4248
|
+
if (!object) {
|
|
4249
|
+
diagnostics.push(error("validate.event.pose.object.unknown", `Unknown event pose object "${pose.objectId}" on "${event.id}".`, void 0, poseFieldPrefix));
|
|
4250
|
+
continue;
|
|
4251
|
+
}
|
|
4252
|
+
if (!referencedIds.has(pose.objectId)) {
|
|
4253
|
+
diagnostics.push(warn("validate.event.pose.unreferenced", `Event pose "${pose.objectId}" on "${event.id}" is not listed in target/participants.`, void 0, poseFieldPrefix));
|
|
4254
|
+
}
|
|
4255
|
+
validateEventPose(pose, object, event, system, objectMap, diagnostics, poseFieldPrefix, event.id);
|
|
4256
|
+
}
|
|
4257
|
+
const missingPoseIds = [...referencedIds].filter((objectId) => !poseIds.has(objectId));
|
|
4258
|
+
if (event.positions.length > 0 && missingPoseIds.length > 0) {
|
|
4259
|
+
diagnostics.push(warn("validate.event.positions.partial", `Event "${event.id}" leaves ${missingPoseIds.length} referenced object(s) on their base placement.`, void 0, `${fieldPrefix}.positions`));
|
|
4260
|
+
}
|
|
4261
|
+
}
|
|
4262
|
+
function validateEventPose(pose, object, event, system, objectMap, diagnostics, fieldPrefix, eventId) {
|
|
4263
|
+
const placement = pose.placement;
|
|
4264
|
+
if (!placement) {
|
|
4265
|
+
diagnostics.push(error("validate.event.pose.placement.required", `Event "${eventId}" pose "${pose.objectId}" is missing a placement mode.`, void 0, fieldPrefix));
|
|
4266
|
+
return;
|
|
4267
|
+
}
|
|
4268
|
+
if (placement.mode === "orbit") {
|
|
4269
|
+
if (!objectMap.has(placement.target)) {
|
|
4270
|
+
diagnostics.push(error("validate.event.pose.orbit.target.unknown", `Unknown event orbit target "${placement.target}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.orbit`));
|
|
4271
|
+
}
|
|
4272
|
+
if (placement.distance && placement.semiMajor) {
|
|
4273
|
+
diagnostics.push(error("validate.event.pose.orbit.distanceConflict", `Event "${eventId}" pose "${pose.objectId}" cannot declare both "distance" and "semiMajor".`, void 0, `${fieldPrefix}.distance`));
|
|
4274
|
+
}
|
|
4275
|
+
if (placement.phase && !resolveEffectiveEpoch(system, object, event, pose)) {
|
|
4276
|
+
diagnostics.push(warn("validate.event.pose.phase.epochMissing", `Event "${eventId}" pose "${pose.objectId}" sets "phase" without an effective epoch.`, void 0, `${fieldPrefix}.phase`));
|
|
4277
|
+
}
|
|
4278
|
+
if (placement.inclination && !resolveEffectiveReferencePlane(system, object, event, pose)) {
|
|
4279
|
+
diagnostics.push(warn("validate.event.pose.inclination.referencePlaneMissing", `Event "${eventId}" pose "${pose.objectId}" sets "inclination" without an effective reference plane.`, void 0, `${fieldPrefix}.inclination`));
|
|
4280
|
+
}
|
|
4281
|
+
if (placement.period && !massInSolar(objectMap.get(placement.target)?.properties.mass)) {
|
|
4282
|
+
diagnostics.push(warn("validate.event.pose.period.massMissing", `Event "${eventId}" pose "${pose.objectId}" sets "period" but its central mass cannot be derived.`, void 0, `${fieldPrefix}.period`));
|
|
4283
|
+
}
|
|
4284
|
+
return;
|
|
4285
|
+
}
|
|
4286
|
+
if (placement.mode === "surface") {
|
|
4287
|
+
const target = objectMap.get(placement.target);
|
|
4288
|
+
if (!target) {
|
|
4289
|
+
diagnostics.push(error("validate.event.pose.surface.target.unknown", `Unknown event surface target "${placement.target}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.surface`));
|
|
4290
|
+
} else if (!SURFACE_TARGET_TYPES2.has(target.type)) {
|
|
4291
|
+
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`));
|
|
4292
|
+
}
|
|
4293
|
+
return;
|
|
4294
|
+
}
|
|
4295
|
+
if (placement.mode === "at") {
|
|
4296
|
+
if (object.type !== "structure" && object.type !== "phenomenon") {
|
|
4297
|
+
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`));
|
|
4298
|
+
}
|
|
4299
|
+
const reference = placement.reference;
|
|
4300
|
+
if (reference.kind === "named" && !objectMap.has(reference.name)) {
|
|
4301
|
+
diagnostics.push(error("validate.event.pose.at.target.unknown", `Unknown event at-reference target "${placement.target}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.at`));
|
|
4302
|
+
} else if (reference.kind === "anchor" && !objectMap.has(reference.objectId)) {
|
|
4303
|
+
diagnostics.push(error("validate.event.pose.anchor.target.unknown", `Unknown event anchor target "${reference.objectId}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.at`));
|
|
4304
|
+
} else if (reference.kind === "lagrange") {
|
|
4305
|
+
if (!objectMap.has(reference.primary)) {
|
|
4306
|
+
diagnostics.push(error("validate.event.pose.lagrange.primary.unknown", `Unknown event Lagrange target "${reference.primary}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.at`));
|
|
4307
|
+
} else if (reference.secondary && !objectMap.has(reference.secondary)) {
|
|
4308
|
+
diagnostics.push(error("validate.event.pose.lagrange.secondary.unknown", `Unknown event Lagrange target "${reference.secondary}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.at`));
|
|
4309
|
+
}
|
|
4310
|
+
}
|
|
4311
|
+
}
|
|
4312
|
+
}
|
|
3691
4313
|
function validateAtTarget(object, objectMap, diagnostics) {
|
|
3692
4314
|
const reference = object.placement?.mode === "at" ? object.placement.reference : null;
|
|
3693
4315
|
if (!reference) {
|
|
@@ -3793,6 +4415,52 @@ var WorldOrbit = (() => {
|
|
|
3793
4415
|
return null;
|
|
3794
4416
|
}
|
|
3795
4417
|
}
|
|
4418
|
+
function validateProjection(projection, diagnostics, field, viewpointId) {
|
|
4419
|
+
if (projection !== "topdown" && projection !== "isometric" && projection !== "orthographic" && projection !== "perspective") {
|
|
4420
|
+
diagnostics.push(error("validate.viewpoint.projection.invalid", `Unknown projection "${String(projection)}" in viewpoint "${viewpointId}".`, void 0, field));
|
|
4421
|
+
}
|
|
4422
|
+
}
|
|
4423
|
+
function validateCamera(camera, projection, rotationDeg, diagnostics, viewpointId, focusObjectId, selectedObjectId, filter, objectMap) {
|
|
4424
|
+
if (!camera) {
|
|
4425
|
+
return;
|
|
4426
|
+
}
|
|
4427
|
+
const prefix = `viewpoint.${viewpointId}.camera`;
|
|
4428
|
+
for (const [key, value] of [
|
|
4429
|
+
["azimuth", camera.azimuth],
|
|
4430
|
+
["elevation", camera.elevation],
|
|
4431
|
+
["roll", camera.roll],
|
|
4432
|
+
["distance", camera.distance]
|
|
4433
|
+
]) {
|
|
4434
|
+
if (value !== null && (!Number.isFinite(value) || key === "distance" && value <= 0)) {
|
|
4435
|
+
diagnostics.push(error("validate.viewpoint.camera.invalid", `Invalid camera ${key} "${String(value)}" in viewpoint "${viewpointId}".`, void 0, `${prefix}.${key}`));
|
|
4436
|
+
}
|
|
4437
|
+
}
|
|
4438
|
+
if (camera.distance !== null && projection !== "perspective") {
|
|
4439
|
+
diagnostics.push(warn("validate.viewpoint.camera.distance.partialEffect", `Camera "distance" only has a semantic effect in perspective viewpoints; "${viewpointId}" uses "${projection}".`, void 0, `${prefix}.distance`));
|
|
4440
|
+
}
|
|
4441
|
+
if (projection === "topdown" && (camera.elevation !== null || camera.roll !== null)) {
|
|
4442
|
+
diagnostics.push(warn("validate.viewpoint.camera.topdownPartial", `Camera elevation/roll on topdown viewpoint "${viewpointId}" are currently stored for future 3D use and only partially affect 2D rendering.`, void 0, prefix));
|
|
4443
|
+
}
|
|
4444
|
+
if (projection === "isometric" && camera.elevation !== null) {
|
|
4445
|
+
diagnostics.push(info("validate.viewpoint.camera.isometricStored", `Camera elevation on isometric viewpoint "${viewpointId}" is preserved semantically for future 3D rendering.`, void 0, `${prefix}.elevation`));
|
|
4446
|
+
}
|
|
4447
|
+
if (camera.azimuth !== null && camera.azimuth !== 0 && rotationDeg !== 0) {
|
|
4448
|
+
diagnostics.push(warn("validate.viewpoint.rotation.cameraOverlap", `Viewpoint "${viewpointId}" uses camera.azimuth; keep "rotation" only for 2D screen rotation to avoid ambiguity.`, void 0, `${prefix}.azimuth`));
|
|
4449
|
+
}
|
|
4450
|
+
const hasAnchor = focusObjectId !== null && objectMap.has(focusObjectId) || selectedObjectId !== null && objectMap.has(selectedObjectId) || !!filter;
|
|
4451
|
+
if (!hasAnchor) {
|
|
4452
|
+
diagnostics.push(info("validate.viewpoint.camera.anchorMissing", `Viewpoint "${viewpointId}" stores camera settings without a focus object, selection, or filter anchor.`, void 0, prefix));
|
|
4453
|
+
}
|
|
4454
|
+
}
|
|
4455
|
+
function resolveEffectiveEpoch(system, object, event, pose) {
|
|
4456
|
+
return normalizeOptionalContextString(pose?.epoch) ?? normalizeOptionalContextString(event?.epoch) ?? normalizeOptionalContextString(object.epoch) ?? normalizeOptionalContextString(system?.epoch) ?? null;
|
|
4457
|
+
}
|
|
4458
|
+
function resolveEffectiveReferencePlane(system, object, event, pose) {
|
|
4459
|
+
return normalizeOptionalContextString(pose?.referencePlane) ?? normalizeOptionalContextString(event?.referencePlane) ?? normalizeOptionalContextString(object.referencePlane) ?? normalizeOptionalContextString(system?.referencePlane) ?? null;
|
|
4460
|
+
}
|
|
4461
|
+
function normalizeOptionalContextString(value) {
|
|
4462
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
4463
|
+
}
|
|
3796
4464
|
function toleranceForField(object, field) {
|
|
3797
4465
|
const tolerance = object.tolerances?.find((entry) => entry.field === field)?.value;
|
|
3798
4466
|
if (typeof tolerance === "number") {
|
|
@@ -3888,6 +4556,23 @@ var WorldOrbit = (() => {
|
|
|
3888
4556
|
});
|
|
3889
4557
|
}
|
|
3890
4558
|
var DRAFT_OBJECT_FIELD_KEYS = new Set(DRAFT_OBJECT_FIELD_SPECS.keys());
|
|
4559
|
+
var EVENT_POSE_FIELD_KEYS = /* @__PURE__ */ new Set([
|
|
4560
|
+
"orbit",
|
|
4561
|
+
"distance",
|
|
4562
|
+
"semiMajor",
|
|
4563
|
+
"eccentricity",
|
|
4564
|
+
"period",
|
|
4565
|
+
"angle",
|
|
4566
|
+
"inclination",
|
|
4567
|
+
"phase",
|
|
4568
|
+
"at",
|
|
4569
|
+
"surface",
|
|
4570
|
+
"free",
|
|
4571
|
+
"inner",
|
|
4572
|
+
"outer",
|
|
4573
|
+
"epoch",
|
|
4574
|
+
"referencePlane"
|
|
4575
|
+
]);
|
|
3891
4576
|
function parseWorldOrbitAtlas(source) {
|
|
3892
4577
|
return parseAtlasSource(source);
|
|
3893
4578
|
}
|
|
@@ -3905,12 +4590,15 @@ var WorldOrbit = (() => {
|
|
|
3905
4590
|
const objectNodes = [];
|
|
3906
4591
|
const groups = [];
|
|
3907
4592
|
const relations = [];
|
|
4593
|
+
const events = [];
|
|
4594
|
+
const eventPoseNodes = /* @__PURE__ */ new Map();
|
|
3908
4595
|
let sawDefaults = false;
|
|
3909
4596
|
let sawAtlas = false;
|
|
3910
4597
|
const viewpointIds = /* @__PURE__ */ new Set();
|
|
3911
4598
|
const annotationIds = /* @__PURE__ */ new Set();
|
|
3912
4599
|
const groupIds = /* @__PURE__ */ new Set();
|
|
3913
4600
|
const relationIds = /* @__PURE__ */ new Set();
|
|
4601
|
+
const eventIds = /* @__PURE__ */ new Set();
|
|
3914
4602
|
for (let index = 0; index < lines.length; index++) {
|
|
3915
4603
|
const rawLine = lines[index];
|
|
3916
4604
|
const lineNumber = index + 1;
|
|
@@ -3928,7 +4616,7 @@ var WorldOrbit = (() => {
|
|
|
3928
4616
|
if (!sawSchemaHeader) {
|
|
3929
4617
|
sourceSchemaVersion = assertDraftSchemaHeader(tokens, lineNumber);
|
|
3930
4618
|
sawSchemaHeader = true;
|
|
3931
|
-
if (prepared.comments.length > 0 && sourceSchemaVersion
|
|
4619
|
+
if (prepared.comments.length > 0 && isSchemaOlderThan(sourceSchemaVersion, "2.1")) {
|
|
3932
4620
|
diagnostics.push({
|
|
3933
4621
|
code: "parse.schema21.commentCompatibility",
|
|
3934
4622
|
severity: "warning",
|
|
@@ -3941,7 +4629,7 @@ var WorldOrbit = (() => {
|
|
|
3941
4629
|
continue;
|
|
3942
4630
|
}
|
|
3943
4631
|
if (indent === 0) {
|
|
3944
|
-
section = startTopLevelSection(tokens, lineNumber, sourceSchemaVersion, diagnostics, system, objectNodes, groups, relations, viewpointIds, annotationIds, groupIds, relationIds, { sawDefaults, sawAtlas });
|
|
4632
|
+
section = startTopLevelSection(tokens, lineNumber, sourceSchemaVersion, diagnostics, system, objectNodes, groups, relations, events, eventPoseNodes, viewpointIds, annotationIds, groupIds, relationIds, eventIds, { sawDefaults, sawAtlas });
|
|
3945
4633
|
if (section.kind === "system") {
|
|
3946
4634
|
system = section.system;
|
|
3947
4635
|
} else if (section.kind === "defaults") {
|
|
@@ -3960,6 +4648,7 @@ var WorldOrbit = (() => {
|
|
|
3960
4648
|
throw new WorldOrbitError('Missing required atlas schema header "schema 2.0"');
|
|
3961
4649
|
}
|
|
3962
4650
|
const objects = objectNodes.map((node) => normalizeDraftObject(node, sourceSchemaVersion, diagnostics));
|
|
4651
|
+
const normalizedEvents = events.map((event) => normalizeDraftEvent(event, eventPoseNodes.get(event.id) ?? []));
|
|
3963
4652
|
const outputVersion = forcedOutputVersion ?? (sourceSchemaVersion === "2.0-draft" ? "2.0" : sourceSchemaVersion);
|
|
3964
4653
|
const baseDocument = {
|
|
3965
4654
|
format: "worldorbit",
|
|
@@ -3967,6 +4656,7 @@ var WorldOrbit = (() => {
|
|
|
3967
4656
|
system,
|
|
3968
4657
|
groups,
|
|
3969
4658
|
relations,
|
|
4659
|
+
events: normalizedEvents,
|
|
3970
4660
|
objects,
|
|
3971
4661
|
diagnostics
|
|
3972
4662
|
};
|
|
@@ -3996,13 +4686,13 @@ var WorldOrbit = (() => {
|
|
|
3996
4686
|
return document2;
|
|
3997
4687
|
}
|
|
3998
4688
|
function assertDraftSchemaHeader(tokens, line) {
|
|
3999
|
-
if (tokens.length !== 2 || tokens[0].value.toLowerCase() !== "schema" || !["2.0-draft", "2.0", "2.1"].includes(tokens[1].value.toLowerCase())) {
|
|
4000
|
-
throw new WorldOrbitError('Expected atlas header "schema 2.0", "schema 2.1", or legacy "schema 2.0-draft"', line, tokens[0]?.column ?? 1);
|
|
4689
|
+
if (tokens.length !== 2 || tokens[0].value.toLowerCase() !== "schema" || !["2.0-draft", "2.0", "2.1", "2.5"].includes(tokens[1].value.toLowerCase())) {
|
|
4690
|
+
throw new WorldOrbitError('Expected atlas header "schema 2.0", "schema 2.1", "schema 2.5", or legacy "schema 2.0-draft"', line, tokens[0]?.column ?? 1);
|
|
4001
4691
|
}
|
|
4002
4692
|
const version = tokens[1].value.toLowerCase();
|
|
4003
|
-
return version === "2.1" ? "2.1" : version === "2.0-draft" ? "2.0-draft" : "2.0";
|
|
4693
|
+
return version === "2.5" ? "2.5" : version === "2.1" ? "2.1" : version === "2.0-draft" ? "2.0-draft" : "2.0";
|
|
4004
4694
|
}
|
|
4005
|
-
function startTopLevelSection(tokens, line, sourceSchemaVersion, diagnostics, system, objectNodes, groups, relations, viewpointIds, annotationIds, groupIds, relationIds, flags) {
|
|
4695
|
+
function startTopLevelSection(tokens, line, sourceSchemaVersion, diagnostics, system, objectNodes, groups, relations, events, eventPoseNodes, viewpointIds, annotationIds, groupIds, relationIds, eventIds, flags) {
|
|
4006
4696
|
const keyword = tokens[0]?.value.toLowerCase();
|
|
4007
4697
|
switch (keyword) {
|
|
4008
4698
|
case "system":
|
|
@@ -4020,6 +4710,8 @@ var WorldOrbit = (() => {
|
|
|
4020
4710
|
return {
|
|
4021
4711
|
kind: "defaults",
|
|
4022
4712
|
system,
|
|
4713
|
+
sourceSchemaVersion,
|
|
4714
|
+
diagnostics,
|
|
4023
4715
|
seenFields: /* @__PURE__ */ new Set()
|
|
4024
4716
|
};
|
|
4025
4717
|
case "atlas":
|
|
@@ -4039,7 +4731,7 @@ var WorldOrbit = (() => {
|
|
|
4039
4731
|
if (!system) {
|
|
4040
4732
|
throw new WorldOrbitError('Atlas section "viewpoint" requires a preceding system declaration', line, tokens[0].column);
|
|
4041
4733
|
}
|
|
4042
|
-
return startViewpointSection(tokens, line, system, viewpointIds);
|
|
4734
|
+
return startViewpointSection(tokens, line, system, viewpointIds, sourceSchemaVersion, diagnostics);
|
|
4043
4735
|
case "annotation":
|
|
4044
4736
|
if (!system) {
|
|
4045
4737
|
throw new WorldOrbitError('Atlas section "annotation" requires a preceding system declaration', line, tokens[0].column);
|
|
@@ -4051,6 +4743,9 @@ var WorldOrbit = (() => {
|
|
|
4051
4743
|
case "relation":
|
|
4052
4744
|
warnIfSchema21Feature(sourceSchemaVersion, diagnostics, "relation", { line, column: tokens[0].column });
|
|
4053
4745
|
return startRelationSection(tokens, line, relations, relationIds);
|
|
4746
|
+
case "event":
|
|
4747
|
+
warnIfSchema21Feature(sourceSchemaVersion, diagnostics, "event", { line, column: tokens[0].column });
|
|
4748
|
+
return startEventSection(tokens, line, events, eventPoseNodes, eventIds, sourceSchemaVersion, diagnostics);
|
|
4054
4749
|
case "object":
|
|
4055
4750
|
return startObjectSection(tokens, line, sourceSchemaVersion, diagnostics, objectNodes);
|
|
4056
4751
|
default:
|
|
@@ -4087,7 +4782,7 @@ var WorldOrbit = (() => {
|
|
|
4087
4782
|
seenFields: /* @__PURE__ */ new Set()
|
|
4088
4783
|
};
|
|
4089
4784
|
}
|
|
4090
|
-
function startViewpointSection(tokens, line, system, viewpointIds) {
|
|
4785
|
+
function startViewpointSection(tokens, line, system, viewpointIds, sourceSchemaVersion, diagnostics) {
|
|
4091
4786
|
if (tokens.length !== 2) {
|
|
4092
4787
|
throw new WorldOrbitError("Invalid viewpoint declaration", line, tokens[0]?.column ?? 1);
|
|
4093
4788
|
}
|
|
@@ -4104,10 +4799,12 @@ var WorldOrbit = (() => {
|
|
|
4104
4799
|
summary: "",
|
|
4105
4800
|
focusObjectId: null,
|
|
4106
4801
|
selectedObjectId: null,
|
|
4802
|
+
events: [],
|
|
4107
4803
|
projection: system.defaults.view,
|
|
4108
4804
|
preset: system.defaults.preset,
|
|
4109
4805
|
zoom: null,
|
|
4110
4806
|
rotationDeg: 0,
|
|
4807
|
+
camera: null,
|
|
4111
4808
|
layers: {},
|
|
4112
4809
|
filter: null
|
|
4113
4810
|
};
|
|
@@ -4116,10 +4813,15 @@ var WorldOrbit = (() => {
|
|
|
4116
4813
|
return {
|
|
4117
4814
|
kind: "viewpoint",
|
|
4118
4815
|
viewpoint,
|
|
4816
|
+
sourceSchemaVersion,
|
|
4817
|
+
diagnostics,
|
|
4119
4818
|
seenFields: /* @__PURE__ */ new Set(),
|
|
4120
4819
|
inFilter: false,
|
|
4121
4820
|
filterIndent: null,
|
|
4122
|
-
seenFilterFields: /* @__PURE__ */ new Set()
|
|
4821
|
+
seenFilterFields: /* @__PURE__ */ new Set(),
|
|
4822
|
+
inCamera: false,
|
|
4823
|
+
cameraIndent: null,
|
|
4824
|
+
seenCameraFields: /* @__PURE__ */ new Set()
|
|
4123
4825
|
};
|
|
4124
4826
|
}
|
|
4125
4827
|
function startAnnotationSection(tokens, line, system, annotationIds) {
|
|
@@ -4206,6 +4908,51 @@ var WorldOrbit = (() => {
|
|
|
4206
4908
|
seenFields: /* @__PURE__ */ new Set()
|
|
4207
4909
|
};
|
|
4208
4910
|
}
|
|
4911
|
+
function startEventSection(tokens, line, events, eventPoseNodes, eventIds, sourceSchemaVersion, diagnostics) {
|
|
4912
|
+
if (tokens.length !== 2) {
|
|
4913
|
+
throw new WorldOrbitError("Invalid event declaration", line, tokens[0]?.column ?? 1);
|
|
4914
|
+
}
|
|
4915
|
+
const id = normalizeIdentifier2(tokens[1].value);
|
|
4916
|
+
if (!id) {
|
|
4917
|
+
throw new WorldOrbitError("Event id must not be empty", line, tokens[1].column);
|
|
4918
|
+
}
|
|
4919
|
+
if (eventIds.has(id)) {
|
|
4920
|
+
throw new WorldOrbitError(`Duplicate event id "${id}"`, line, tokens[1].column);
|
|
4921
|
+
}
|
|
4922
|
+
const event = {
|
|
4923
|
+
id,
|
|
4924
|
+
kind: "",
|
|
4925
|
+
label: humanizeIdentifier3(id),
|
|
4926
|
+
summary: null,
|
|
4927
|
+
targetObjectId: null,
|
|
4928
|
+
participantObjectIds: [],
|
|
4929
|
+
timing: null,
|
|
4930
|
+
visibility: null,
|
|
4931
|
+
epoch: null,
|
|
4932
|
+
referencePlane: null,
|
|
4933
|
+
tags: [],
|
|
4934
|
+
color: null,
|
|
4935
|
+
hidden: false,
|
|
4936
|
+
positions: []
|
|
4937
|
+
};
|
|
4938
|
+
const rawPoses = [];
|
|
4939
|
+
events.push(event);
|
|
4940
|
+
eventPoseNodes.set(id, rawPoses);
|
|
4941
|
+
eventIds.add(id);
|
|
4942
|
+
return {
|
|
4943
|
+
kind: "event",
|
|
4944
|
+
event,
|
|
4945
|
+
sourceSchemaVersion,
|
|
4946
|
+
diagnostics,
|
|
4947
|
+
seenFields: /* @__PURE__ */ new Set(),
|
|
4948
|
+
rawPoses,
|
|
4949
|
+
inPositions: false,
|
|
4950
|
+
positionsIndent: null,
|
|
4951
|
+
activePose: null,
|
|
4952
|
+
poseIndent: null,
|
|
4953
|
+
activePoseSeenFields: /* @__PURE__ */ new Set()
|
|
4954
|
+
};
|
|
4955
|
+
}
|
|
4209
4956
|
function startObjectSection(tokens, line, sourceSchemaVersion, diagnostics, objectNodes) {
|
|
4210
4957
|
if (tokens.length < 3) {
|
|
4211
4958
|
throw new WorldOrbitError("Invalid atlas object declaration", line, tokens[0]?.column ?? 1);
|
|
@@ -4262,6 +5009,9 @@ var WorldOrbit = (() => {
|
|
|
4262
5009
|
case "relation":
|
|
4263
5010
|
applyRelationField(section, tokens, line);
|
|
4264
5011
|
return;
|
|
5012
|
+
case "event":
|
|
5013
|
+
applyEventField(section, indent, tokens, line);
|
|
5014
|
+
return;
|
|
4265
5015
|
case "object":
|
|
4266
5016
|
applyObjectField(section, indent, tokens, line);
|
|
4267
5017
|
return;
|
|
@@ -4304,6 +5054,12 @@ var WorldOrbit = (() => {
|
|
|
4304
5054
|
const value = joinFieldValue(tokens, line);
|
|
4305
5055
|
switch (key) {
|
|
4306
5056
|
case "view":
|
|
5057
|
+
if (isSchema25Projection(value)) {
|
|
5058
|
+
warnIfSchema25Feature(section.sourceSchemaVersion, section.diagnostics, "defaults.view", {
|
|
5059
|
+
line,
|
|
5060
|
+
column: tokens[0].column
|
|
5061
|
+
});
|
|
5062
|
+
}
|
|
4307
5063
|
section.system.defaults.view = parseProjectionValue(value, line, tokens[0].column);
|
|
4308
5064
|
return;
|
|
4309
5065
|
case "scale":
|
|
@@ -4343,14 +5099,36 @@ var WorldOrbit = (() => {
|
|
|
4343
5099
|
throw new WorldOrbitError(`Unknown atlas field "${tokens[0].value}"`, line, tokens[0].column);
|
|
4344
5100
|
}
|
|
4345
5101
|
function applyViewpointField2(section, indent, tokens, line) {
|
|
5102
|
+
if (section.inCamera && indent <= (section.cameraIndent ?? 0)) {
|
|
5103
|
+
section.inCamera = false;
|
|
5104
|
+
section.cameraIndent = null;
|
|
5105
|
+
}
|
|
4346
5106
|
if (section.inFilter && indent <= (section.filterIndent ?? 0)) {
|
|
4347
5107
|
section.inFilter = false;
|
|
4348
5108
|
section.filterIndent = null;
|
|
4349
5109
|
}
|
|
5110
|
+
if (section.inCamera) {
|
|
5111
|
+
applyViewpointCameraField(section, tokens, line);
|
|
5112
|
+
return;
|
|
5113
|
+
}
|
|
4350
5114
|
if (section.inFilter) {
|
|
4351
5115
|
applyViewpointFilterField(section, tokens, line);
|
|
4352
5116
|
return;
|
|
4353
5117
|
}
|
|
5118
|
+
if (tokens.length === 1 && tokens[0].value.toLowerCase() === "camera") {
|
|
5119
|
+
warnIfSchema25Feature(section.sourceSchemaVersion, section.diagnostics, "viewpoint.camera", {
|
|
5120
|
+
line,
|
|
5121
|
+
column: tokens[0].column
|
|
5122
|
+
});
|
|
5123
|
+
if (section.seenFields.has("camera")) {
|
|
5124
|
+
throw new WorldOrbitError('Duplicate viewpoint field "camera"', line, tokens[0].column);
|
|
5125
|
+
}
|
|
5126
|
+
section.seenFields.add("camera");
|
|
5127
|
+
section.inCamera = true;
|
|
5128
|
+
section.cameraIndent = indent;
|
|
5129
|
+
section.viewpoint.camera = section.viewpoint.camera ?? createEmptyViewCamera2();
|
|
5130
|
+
return;
|
|
5131
|
+
}
|
|
4354
5132
|
if (tokens.length === 1 && tokens[0].value.toLowerCase() === "filter") {
|
|
4355
5133
|
if (section.seenFields.has("filter")) {
|
|
4356
5134
|
throw new WorldOrbitError('Duplicate viewpoint field "filter"', line, tokens[0].column);
|
|
@@ -4376,6 +5154,12 @@ var WorldOrbit = (() => {
|
|
|
4376
5154
|
section.viewpoint.selectedObjectId = value;
|
|
4377
5155
|
return;
|
|
4378
5156
|
case "projection":
|
|
5157
|
+
if (isSchema25Projection(value)) {
|
|
5158
|
+
warnIfSchema25Feature(section.sourceSchemaVersion, section.diagnostics, "projection", {
|
|
5159
|
+
line,
|
|
5160
|
+
column: tokens[0].column
|
|
5161
|
+
});
|
|
5162
|
+
}
|
|
4379
5163
|
section.viewpoint.projection = parseProjectionValue(value, line, tokens[0].column);
|
|
4380
5164
|
return;
|
|
4381
5165
|
case "preset":
|
|
@@ -4387,13 +5171,49 @@ var WorldOrbit = (() => {
|
|
|
4387
5171
|
case "rotation":
|
|
4388
5172
|
section.viewpoint.rotationDeg = parseFiniteNumber2(value, line, tokens[0].column, "rotation");
|
|
4389
5173
|
return;
|
|
5174
|
+
case "camera":
|
|
5175
|
+
warnIfSchema25Feature(section.sourceSchemaVersion, section.diagnostics, "viewpoint.camera", {
|
|
5176
|
+
line,
|
|
5177
|
+
column: tokens[0].column
|
|
5178
|
+
});
|
|
5179
|
+
section.viewpoint.camera = parseInlineViewCamera(tokens.slice(1), line, section.viewpoint.camera);
|
|
5180
|
+
return;
|
|
4390
5181
|
case "layers":
|
|
4391
|
-
section.viewpoint.layers = parseLayerTokens(tokens.slice(1), line);
|
|
5182
|
+
section.viewpoint.layers = parseLayerTokens(tokens.slice(1), line, section.sourceSchemaVersion, section.diagnostics);
|
|
5183
|
+
return;
|
|
5184
|
+
case "events":
|
|
5185
|
+
warnIfSchema21Feature(section.sourceSchemaVersion, section.diagnostics, "viewpoint.events", {
|
|
5186
|
+
line,
|
|
5187
|
+
column: tokens[0].column
|
|
5188
|
+
});
|
|
5189
|
+
section.viewpoint.events = parseTokenList(tokens.slice(1), line, "events");
|
|
4392
5190
|
return;
|
|
4393
5191
|
default:
|
|
4394
5192
|
throw new WorldOrbitError(`Unknown viewpoint field "${tokens[0].value}"`, line, tokens[0].column);
|
|
4395
5193
|
}
|
|
4396
5194
|
}
|
|
5195
|
+
function applyViewpointCameraField(section, tokens, line) {
|
|
5196
|
+
const key = requireUniqueField(tokens, section.seenCameraFields, line);
|
|
5197
|
+
const value = joinFieldValue(tokens, line);
|
|
5198
|
+
const camera = section.viewpoint.camera ?? createEmptyViewCamera2();
|
|
5199
|
+
switch (key) {
|
|
5200
|
+
case "azimuth":
|
|
5201
|
+
camera.azimuth = parseFiniteNumber2(value, line, tokens[0].column, "camera.azimuth");
|
|
5202
|
+
break;
|
|
5203
|
+
case "elevation":
|
|
5204
|
+
camera.elevation = parseFiniteNumber2(value, line, tokens[0].column, "camera.elevation");
|
|
5205
|
+
break;
|
|
5206
|
+
case "roll":
|
|
5207
|
+
camera.roll = parseFiniteNumber2(value, line, tokens[0].column, "camera.roll");
|
|
5208
|
+
break;
|
|
5209
|
+
case "distance":
|
|
5210
|
+
camera.distance = parsePositiveNumber2(value, line, tokens[0].column, "camera.distance");
|
|
5211
|
+
break;
|
|
5212
|
+
default:
|
|
5213
|
+
throw new WorldOrbitError(`Unknown viewpoint camera field "${tokens[0].value}"`, line, tokens[0].column);
|
|
5214
|
+
}
|
|
5215
|
+
section.viewpoint.camera = camera;
|
|
5216
|
+
}
|
|
4397
5217
|
function applyViewpointFilterField(section, tokens, line) {
|
|
4398
5218
|
const key = requireUniqueField(tokens, section.seenFilterFields, line);
|
|
4399
5219
|
const filter = section.viewpoint.filter ?? createEmptyViewpointFilter2();
|
|
@@ -4493,6 +5313,126 @@ var WorldOrbit = (() => {
|
|
|
4493
5313
|
throw new WorldOrbitError(`Unknown relation field "${tokens[0].value}"`, line, tokens[0].column);
|
|
4494
5314
|
}
|
|
4495
5315
|
}
|
|
5316
|
+
function applyEventField(section, indent, tokens, line) {
|
|
5317
|
+
if (section.activePose && indent <= (section.poseIndent ?? 0)) {
|
|
5318
|
+
section.activePose = null;
|
|
5319
|
+
section.poseIndent = null;
|
|
5320
|
+
section.activePoseSeenFields.clear();
|
|
5321
|
+
}
|
|
5322
|
+
if (!section.activePose && section.inPositions && indent <= (section.positionsIndent ?? 0)) {
|
|
5323
|
+
section.inPositions = false;
|
|
5324
|
+
section.positionsIndent = null;
|
|
5325
|
+
}
|
|
5326
|
+
if (section.activePose) {
|
|
5327
|
+
if (tokens[0]?.value === "epoch" || tokens[0]?.value === "referencePlane") {
|
|
5328
|
+
warnIfSchema25Feature(section.sourceSchemaVersion, section.diagnostics, `pose.${tokens[0].value}`, {
|
|
5329
|
+
line,
|
|
5330
|
+
column: tokens[0]?.column ?? 1
|
|
5331
|
+
});
|
|
5332
|
+
}
|
|
5333
|
+
section.activePose.fields.push(parseEventPoseField(tokens, line, section.activePoseSeenFields));
|
|
5334
|
+
return;
|
|
5335
|
+
}
|
|
5336
|
+
if (section.inPositions) {
|
|
5337
|
+
if (tokens.length !== 2 || tokens[0].value.toLowerCase() !== "pose") {
|
|
5338
|
+
throw new WorldOrbitError(`Unknown event positions field "${tokens[0].value}"`, line, tokens[0]?.column ?? 1);
|
|
5339
|
+
}
|
|
5340
|
+
const objectId = tokens[1].value;
|
|
5341
|
+
if (!objectId.trim()) {
|
|
5342
|
+
throw new WorldOrbitError("Event pose object id must not be empty", line, tokens[1].column);
|
|
5343
|
+
}
|
|
5344
|
+
const rawPose = {
|
|
5345
|
+
objectId,
|
|
5346
|
+
fields: [],
|
|
5347
|
+
location: { line, column: tokens[0].column }
|
|
5348
|
+
};
|
|
5349
|
+
section.rawPoses.push(rawPose);
|
|
5350
|
+
section.activePose = rawPose;
|
|
5351
|
+
section.poseIndent = indent;
|
|
5352
|
+
section.activePoseSeenFields = /* @__PURE__ */ new Set();
|
|
5353
|
+
return;
|
|
5354
|
+
}
|
|
5355
|
+
if (tokens.length === 1 && tokens[0].value.toLowerCase() === "positions") {
|
|
5356
|
+
if (section.seenFields.has("positions")) {
|
|
5357
|
+
throw new WorldOrbitError('Duplicate event field "positions"', line, tokens[0].column);
|
|
5358
|
+
}
|
|
5359
|
+
section.seenFields.add("positions");
|
|
5360
|
+
section.inPositions = true;
|
|
5361
|
+
section.positionsIndent = indent;
|
|
5362
|
+
return;
|
|
5363
|
+
}
|
|
5364
|
+
const key = requireUniqueField(tokens, section.seenFields, line);
|
|
5365
|
+
switch (key) {
|
|
5366
|
+
case "kind":
|
|
5367
|
+
section.event.kind = joinFieldValue(tokens, line);
|
|
5368
|
+
return;
|
|
5369
|
+
case "label":
|
|
5370
|
+
section.event.label = joinFieldValue(tokens, line);
|
|
5371
|
+
return;
|
|
5372
|
+
case "summary":
|
|
5373
|
+
section.event.summary = joinFieldValue(tokens, line);
|
|
5374
|
+
return;
|
|
5375
|
+
case "target":
|
|
5376
|
+
section.event.targetObjectId = joinFieldValue(tokens, line);
|
|
5377
|
+
return;
|
|
5378
|
+
case "participants":
|
|
5379
|
+
section.event.participantObjectIds = parseTokenList(tokens.slice(1), line, "participants");
|
|
5380
|
+
return;
|
|
5381
|
+
case "timing":
|
|
5382
|
+
section.event.timing = joinFieldValue(tokens, line);
|
|
5383
|
+
return;
|
|
5384
|
+
case "visibility":
|
|
5385
|
+
section.event.visibility = joinFieldValue(tokens, line);
|
|
5386
|
+
return;
|
|
5387
|
+
case "epoch":
|
|
5388
|
+
warnIfSchema25Feature(section.sourceSchemaVersion, section.diagnostics, "event.epoch", {
|
|
5389
|
+
line,
|
|
5390
|
+
column: tokens[0].column
|
|
5391
|
+
});
|
|
5392
|
+
section.event.epoch = joinFieldValue(tokens, line);
|
|
5393
|
+
return;
|
|
5394
|
+
case "referenceplane":
|
|
5395
|
+
warnIfSchema25Feature(section.sourceSchemaVersion, section.diagnostics, "event.referencePlane", {
|
|
5396
|
+
line,
|
|
5397
|
+
column: tokens[0].column
|
|
5398
|
+
});
|
|
5399
|
+
section.event.referencePlane = joinFieldValue(tokens, line);
|
|
5400
|
+
return;
|
|
5401
|
+
case "tags":
|
|
5402
|
+
section.event.tags = parseTokenList(tokens.slice(1), line, "tags");
|
|
5403
|
+
return;
|
|
5404
|
+
case "color":
|
|
5405
|
+
section.event.color = joinFieldValue(tokens, line);
|
|
5406
|
+
return;
|
|
5407
|
+
case "hidden":
|
|
5408
|
+
section.event.hidden = parseAtlasBoolean(joinFieldValue(tokens, line), "hidden", {
|
|
5409
|
+
line,
|
|
5410
|
+
column: tokens[0].column
|
|
5411
|
+
});
|
|
5412
|
+
return;
|
|
5413
|
+
default:
|
|
5414
|
+
throw new WorldOrbitError(`Unknown event field "${tokens[0].value}"`, line, tokens[0].column);
|
|
5415
|
+
}
|
|
5416
|
+
}
|
|
5417
|
+
function parseEventPoseField(tokens, line, seenFields) {
|
|
5418
|
+
if (tokens.length < 2) {
|
|
5419
|
+
throw new WorldOrbitError("Invalid event pose field line", line, tokens[0]?.column ?? 1);
|
|
5420
|
+
}
|
|
5421
|
+
const key = tokens[0].value;
|
|
5422
|
+
if (!EVENT_POSE_FIELD_KEYS.has(key)) {
|
|
5423
|
+
throw new WorldOrbitError(`Unknown event pose field "${key}"`, line, tokens[0].column);
|
|
5424
|
+
}
|
|
5425
|
+
if (seenFields.has(key)) {
|
|
5426
|
+
throw new WorldOrbitError(`Duplicate event pose field "${key}"`, line, tokens[0].column);
|
|
5427
|
+
}
|
|
5428
|
+
seenFields.add(key);
|
|
5429
|
+
return {
|
|
5430
|
+
type: "field",
|
|
5431
|
+
key,
|
|
5432
|
+
values: tokens.slice(1).map((token) => token.value),
|
|
5433
|
+
location: { line, column: tokens[0].column }
|
|
5434
|
+
};
|
|
5435
|
+
}
|
|
4496
5436
|
function applyObjectField(section, indent, tokens, line) {
|
|
4497
5437
|
if (section.activeBlock && indent <= (section.blockIndent ?? 0)) {
|
|
4498
5438
|
section.activeBlock = null;
|
|
@@ -4551,7 +5491,7 @@ var WorldOrbit = (() => {
|
|
|
4551
5491
|
function parseObjectTypeTokens(tokens, line) {
|
|
4552
5492
|
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");
|
|
4553
5493
|
}
|
|
4554
|
-
function parseLayerTokens(tokens, line) {
|
|
5494
|
+
function parseLayerTokens(tokens, line, sourceSchemaVersion, diagnostics) {
|
|
4555
5495
|
const layers = {};
|
|
4556
5496
|
for (const token of parseTokenList(tokens, line, "layers")) {
|
|
4557
5497
|
const enabled = !token.startsWith("-") && !token.startsWith("!");
|
|
@@ -4561,7 +5501,13 @@ var WorldOrbit = (() => {
|
|
|
4561
5501
|
layers["orbits-front"] = enabled;
|
|
4562
5502
|
continue;
|
|
4563
5503
|
}
|
|
4564
|
-
if (raw === "background" || raw === "guides" || raw === "orbits-back" || raw === "orbits-front" || raw === "relations" || raw === "objects" || raw === "labels" || raw === "metadata") {
|
|
5504
|
+
if (raw === "background" || raw === "guides" || raw === "orbits-back" || raw === "orbits-front" || raw === "relations" || raw === "events" || raw === "objects" || raw === "labels" || raw === "metadata") {
|
|
5505
|
+
if (raw === "events" && sourceSchemaVersion && diagnostics) {
|
|
5506
|
+
warnIfSchema21Feature(sourceSchemaVersion, diagnostics, "layers.events", {
|
|
5507
|
+
line,
|
|
5508
|
+
column: tokens[0]?.column ?? 1
|
|
5509
|
+
});
|
|
5510
|
+
}
|
|
4565
5511
|
layers[raw] = enabled;
|
|
4566
5512
|
}
|
|
4567
5513
|
}
|
|
@@ -4579,11 +5525,15 @@ var WorldOrbit = (() => {
|
|
|
4579
5525
|
}
|
|
4580
5526
|
function parseProjectionValue(value, line, column) {
|
|
4581
5527
|
const normalized = value.toLowerCase();
|
|
4582
|
-
if (normalized !== "topdown" && normalized !== "isometric") {
|
|
5528
|
+
if (normalized !== "topdown" && normalized !== "isometric" && normalized !== "orthographic" && normalized !== "perspective") {
|
|
4583
5529
|
throw new WorldOrbitError(`Unknown projection "${value}"`, line, column);
|
|
4584
5530
|
}
|
|
4585
5531
|
return normalized;
|
|
4586
5532
|
}
|
|
5533
|
+
function isSchema25Projection(value) {
|
|
5534
|
+
const normalized = value.toLowerCase();
|
|
5535
|
+
return normalized === "orthographic" || normalized === "perspective";
|
|
5536
|
+
}
|
|
4587
5537
|
function parsePresetValue(value, line, column) {
|
|
4588
5538
|
const normalized = value.toLowerCase();
|
|
4589
5539
|
if (normalized === "diagram" || normalized === "presentation" || normalized === "atlas-card" || normalized === "markdown") {
|
|
@@ -4613,6 +5563,48 @@ var WorldOrbit = (() => {
|
|
|
4613
5563
|
groupIds: []
|
|
4614
5564
|
};
|
|
4615
5565
|
}
|
|
5566
|
+
function createEmptyViewCamera2() {
|
|
5567
|
+
return {
|
|
5568
|
+
azimuth: null,
|
|
5569
|
+
elevation: null,
|
|
5570
|
+
roll: null,
|
|
5571
|
+
distance: null
|
|
5572
|
+
};
|
|
5573
|
+
}
|
|
5574
|
+
function parseInlineViewCamera(tokens, line, current) {
|
|
5575
|
+
if (tokens.length === 0 || tokens.length % 2 !== 0) {
|
|
5576
|
+
throw new WorldOrbitError('Field "camera" expects "<field> <value>" pairs', line, tokens[0]?.column ?? 1);
|
|
5577
|
+
}
|
|
5578
|
+
const camera = current ? { ...current } : createEmptyViewCamera2();
|
|
5579
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5580
|
+
for (let index = 0; index < tokens.length; index += 2) {
|
|
5581
|
+
const fieldToken = tokens[index];
|
|
5582
|
+
const valueToken = tokens[index + 1];
|
|
5583
|
+
const key = fieldToken.value.toLowerCase();
|
|
5584
|
+
if (seen.has(key)) {
|
|
5585
|
+
throw new WorldOrbitError(`Duplicate viewpoint camera field "${fieldToken.value}"`, line, fieldToken.column);
|
|
5586
|
+
}
|
|
5587
|
+
seen.add(key);
|
|
5588
|
+
const value = valueToken.value;
|
|
5589
|
+
switch (key) {
|
|
5590
|
+
case "azimuth":
|
|
5591
|
+
camera.azimuth = parseFiniteNumber2(value, line, fieldToken.column, "camera.azimuth");
|
|
5592
|
+
break;
|
|
5593
|
+
case "elevation":
|
|
5594
|
+
camera.elevation = parseFiniteNumber2(value, line, fieldToken.column, "camera.elevation");
|
|
5595
|
+
break;
|
|
5596
|
+
case "roll":
|
|
5597
|
+
camera.roll = parseFiniteNumber2(value, line, fieldToken.column, "camera.roll");
|
|
5598
|
+
break;
|
|
5599
|
+
case "distance":
|
|
5600
|
+
camera.distance = parsePositiveNumber2(value, line, fieldToken.column, "camera.distance");
|
|
5601
|
+
break;
|
|
5602
|
+
default:
|
|
5603
|
+
throw new WorldOrbitError(`Unknown viewpoint camera field "${fieldToken.value}"`, line, fieldToken.column);
|
|
5604
|
+
}
|
|
5605
|
+
}
|
|
5606
|
+
return camera;
|
|
5607
|
+
}
|
|
4616
5608
|
function parseInlineObjectFields(tokens, line, objectType, sourceSchemaVersion, diagnostics) {
|
|
4617
5609
|
const fields = [];
|
|
4618
5610
|
let index = 0;
|
|
@@ -4700,7 +5692,7 @@ var WorldOrbit = (() => {
|
|
|
4700
5692
|
}
|
|
4701
5693
|
function normalizeDraftObject(node, sourceSchemaVersion, diagnostics) {
|
|
4702
5694
|
const fieldMap = collectDraftFields(node.fields);
|
|
4703
|
-
const placement =
|
|
5695
|
+
const placement = extractPlacementFromFieldMap(fieldMap);
|
|
4704
5696
|
const properties = normalizeDraftProperties(node.objectType, fieldMap);
|
|
4705
5697
|
const groups = parseOptionalTokenList(fieldMap.get("groups")?.[0]);
|
|
4706
5698
|
const epoch = parseOptionalJoinedValue(fieldMap.get("epoch")?.[0]);
|
|
@@ -4745,21 +5737,41 @@ var WorldOrbit = (() => {
|
|
|
4745
5737
|
object.tolerances = tolerances;
|
|
4746
5738
|
if (typedBlocks && Object.keys(typedBlocks).length > 0)
|
|
4747
5739
|
object.typedBlocks = typedBlocks;
|
|
4748
|
-
if (sourceSchemaVersion
|
|
5740
|
+
if (isSchemaOlderThan(sourceSchemaVersion, "2.1")) {
|
|
4749
5741
|
if (object.groups || object.epoch || object.referencePlane || object.tidalLock !== void 0 || object.resonance || object.renderHints || object.deriveRules?.length || object.validationRules?.length || object.lockedFields?.length || object.tolerances?.length || object.typedBlocks) {
|
|
4750
5742
|
warnIfSchema21Feature(sourceSchemaVersion, diagnostics, node.id, node.location);
|
|
4751
5743
|
}
|
|
4752
5744
|
}
|
|
4753
5745
|
return object;
|
|
4754
5746
|
}
|
|
4755
|
-
function
|
|
5747
|
+
function normalizeDraftEvent(event, rawPoses) {
|
|
5748
|
+
return {
|
|
5749
|
+
...event,
|
|
5750
|
+
participantObjectIds: [...new Set(event.participantObjectIds)],
|
|
5751
|
+
tags: [...new Set(event.tags)],
|
|
5752
|
+
positions: rawPoses.map((pose) => normalizeDraftEventPose(pose))
|
|
5753
|
+
};
|
|
5754
|
+
}
|
|
5755
|
+
function normalizeDraftEventPose(rawPose) {
|
|
5756
|
+
const fieldMap = collectDraftFields(rawPose.fields, "event-pose");
|
|
5757
|
+
const placement = extractPlacementFromFieldMap(fieldMap);
|
|
5758
|
+
return {
|
|
5759
|
+
objectId: rawPose.objectId,
|
|
5760
|
+
placement,
|
|
5761
|
+
inner: parseOptionalUnitField(fieldMap.get("inner")?.[0], "inner"),
|
|
5762
|
+
outer: parseOptionalUnitField(fieldMap.get("outer")?.[0], "outer"),
|
|
5763
|
+
epoch: parseOptionalJoinedValue(fieldMap.get("epoch")?.[0]),
|
|
5764
|
+
referencePlane: parseOptionalJoinedValue(fieldMap.get("referencePlane")?.[0])
|
|
5765
|
+
};
|
|
5766
|
+
}
|
|
5767
|
+
function collectDraftFields(fields, _mode = "object") {
|
|
4756
5768
|
const grouped = /* @__PURE__ */ new Map();
|
|
4757
5769
|
for (const field of fields) {
|
|
4758
5770
|
const spec = getDraftObjectFieldSpec(field.key);
|
|
4759
|
-
if (!spec) {
|
|
5771
|
+
if (!spec && !EVENT_POSE_FIELD_KEYS.has(field.key)) {
|
|
4760
5772
|
throw WorldOrbitError.fromLocation(`Unknown field "${field.key}"`, field.location);
|
|
4761
5773
|
}
|
|
4762
|
-
if (!spec
|
|
5774
|
+
if (!spec?.allowRepeat && grouped.has(field.key)) {
|
|
4763
5775
|
throw WorldOrbitError.fromLocation(`Duplicate field "${field.key}"`, field.location);
|
|
4764
5776
|
}
|
|
4765
5777
|
const existing = grouped.get(field.key) ?? [];
|
|
@@ -4768,7 +5780,7 @@ var WorldOrbit = (() => {
|
|
|
4768
5780
|
}
|
|
4769
5781
|
return grouped;
|
|
4770
5782
|
}
|
|
4771
|
-
function
|
|
5783
|
+
function extractPlacementFromFieldMap(fieldMap) {
|
|
4772
5784
|
const orbitField = fieldMap.get("orbit")?.[0];
|
|
4773
5785
|
const atField = fieldMap.get("at")?.[0];
|
|
4774
5786
|
const surfaceField = fieldMap.get("surface")?.[0];
|
|
@@ -4936,7 +5948,7 @@ var WorldOrbit = (() => {
|
|
|
4936
5948
|
}
|
|
4937
5949
|
}
|
|
4938
5950
|
function warnIfSchema21Feature(sourceSchemaVersion, diagnostics, featureName, location) {
|
|
4939
|
-
if (sourceSchemaVersion
|
|
5951
|
+
if (!isSchemaOlderThan(sourceSchemaVersion, "2.1")) {
|
|
4940
5952
|
return;
|
|
4941
5953
|
}
|
|
4942
5954
|
diagnostics.push({
|
|
@@ -4948,6 +5960,34 @@ var WorldOrbit = (() => {
|
|
|
4948
5960
|
column: location.column
|
|
4949
5961
|
});
|
|
4950
5962
|
}
|
|
5963
|
+
function warnIfSchema25Feature(sourceSchemaVersion, diagnostics, featureName, location) {
|
|
5964
|
+
if (!isSchemaOlderThan(sourceSchemaVersion, "2.5")) {
|
|
5965
|
+
return;
|
|
5966
|
+
}
|
|
5967
|
+
diagnostics.push({
|
|
5968
|
+
code: "parse.schema25.featureCompatibility",
|
|
5969
|
+
severity: "warning",
|
|
5970
|
+
source: "parse",
|
|
5971
|
+
message: `Feature "${featureName}" requires schema 2.5; parsed in compatibility mode because the document header is "schema ${sourceSchemaVersion}".`,
|
|
5972
|
+
line: location.line,
|
|
5973
|
+
column: location.column
|
|
5974
|
+
});
|
|
5975
|
+
}
|
|
5976
|
+
function isSchemaOlderThan(sourceSchemaVersion, requiredVersion) {
|
|
5977
|
+
return schemaVersionRank(sourceSchemaVersion) < schemaVersionRank(requiredVersion);
|
|
5978
|
+
}
|
|
5979
|
+
function schemaVersionRank(version) {
|
|
5980
|
+
switch (version) {
|
|
5981
|
+
case "2.0-draft":
|
|
5982
|
+
return 0;
|
|
5983
|
+
case "2.0":
|
|
5984
|
+
return 1;
|
|
5985
|
+
case "2.1":
|
|
5986
|
+
return 2;
|
|
5987
|
+
case "2.5":
|
|
5988
|
+
return 3;
|
|
5989
|
+
}
|
|
5990
|
+
}
|
|
4951
5991
|
function preprocessAtlasSource(source) {
|
|
4952
5992
|
const chars = [...source];
|
|
4953
5993
|
const comments = [];
|
|
@@ -5035,7 +6075,7 @@ var WorldOrbit = (() => {
|
|
|
5035
6075
|
}
|
|
5036
6076
|
|
|
5037
6077
|
// packages/core/dist/atlas-edit.js
|
|
5038
|
-
function createEmptyAtlasDocument(systemId = "WorldOrbit", version = "2.
|
|
6078
|
+
function createEmptyAtlasDocument(systemId = "WorldOrbit", version = "2.5") {
|
|
5039
6079
|
return {
|
|
5040
6080
|
format: "worldorbit",
|
|
5041
6081
|
version,
|
|
@@ -5061,6 +6101,7 @@ var WorldOrbit = (() => {
|
|
|
5061
6101
|
},
|
|
5062
6102
|
groups: [],
|
|
5063
6103
|
relations: [],
|
|
6104
|
+
events: [],
|
|
5064
6105
|
objects: [],
|
|
5065
6106
|
diagnostics: []
|
|
5066
6107
|
};
|
|
@@ -5087,6 +6128,12 @@ var WorldOrbit = (() => {
|
|
|
5087
6128
|
for (const relation of [...document2.relations].sort(compareIdLike2)) {
|
|
5088
6129
|
paths.push({ kind: "relation", id: relation.id });
|
|
5089
6130
|
}
|
|
6131
|
+
for (const event of [...document2.events].sort(compareIdLike2)) {
|
|
6132
|
+
paths.push({ kind: "event", id: event.id });
|
|
6133
|
+
for (const pose of [...event.positions].sort(comparePoseObjectId2)) {
|
|
6134
|
+
paths.push({ kind: "event-pose", id: event.id, key: pose.objectId });
|
|
6135
|
+
}
|
|
6136
|
+
}
|
|
5090
6137
|
for (const object of [...document2.objects].sort(compareIdLike2)) {
|
|
5091
6138
|
paths.push({ kind: "object", id: object.id });
|
|
5092
6139
|
}
|
|
@@ -5102,6 +6149,10 @@ var WorldOrbit = (() => {
|
|
|
5102
6149
|
return path.key ? document2.system?.atlasMetadata[path.key] ?? null : null;
|
|
5103
6150
|
case "group":
|
|
5104
6151
|
return path.id ? findGroup(document2, path.id) : null;
|
|
6152
|
+
case "event":
|
|
6153
|
+
return path.id ? findEvent(document2, path.id) : null;
|
|
6154
|
+
case "event-pose":
|
|
6155
|
+
return path.id && path.key ? findEventPose(document2, path.id, path.key) : null;
|
|
5105
6156
|
case "object":
|
|
5106
6157
|
return path.id ? findObject(document2, path.id) : null;
|
|
5107
6158
|
case "viewpoint":
|
|
@@ -5141,6 +6192,18 @@ var WorldOrbit = (() => {
|
|
|
5141
6192
|
}
|
|
5142
6193
|
upsertById(next.groups, value);
|
|
5143
6194
|
return next;
|
|
6195
|
+
case "event":
|
|
6196
|
+
if (!path.id) {
|
|
6197
|
+
throw new Error('Event updates require an "id" value.');
|
|
6198
|
+
}
|
|
6199
|
+
upsertById(next.events, value);
|
|
6200
|
+
return next;
|
|
6201
|
+
case "event-pose":
|
|
6202
|
+
if (!path.id || !path.key) {
|
|
6203
|
+
throw new Error('Event pose updates require an event "id" and pose "key" value.');
|
|
6204
|
+
}
|
|
6205
|
+
upsertEventPose(next.events, path.id, value);
|
|
6206
|
+
return next;
|
|
5144
6207
|
case "object":
|
|
5145
6208
|
if (!path.id) {
|
|
5146
6209
|
throw new Error('Object updates require an "id" value.');
|
|
@@ -5189,6 +6252,19 @@ var WorldOrbit = (() => {
|
|
|
5189
6252
|
next.groups = next.groups.filter((group) => group.id !== path.id);
|
|
5190
6253
|
}
|
|
5191
6254
|
return next;
|
|
6255
|
+
case "event":
|
|
6256
|
+
if (path.id) {
|
|
6257
|
+
next.events = next.events.filter((event) => event.id !== path.id);
|
|
6258
|
+
}
|
|
6259
|
+
return next;
|
|
6260
|
+
case "event-pose":
|
|
6261
|
+
if (path.id && path.key) {
|
|
6262
|
+
const event = findEvent(next, path.id);
|
|
6263
|
+
if (event) {
|
|
6264
|
+
event.positions = event.positions.filter((pose) => pose.objectId !== path.key);
|
|
6265
|
+
}
|
|
6266
|
+
}
|
|
6267
|
+
return next;
|
|
5192
6268
|
case "viewpoint":
|
|
5193
6269
|
if (path.id) {
|
|
5194
6270
|
system.viewpoints = system.viewpoints.filter((viewpoint) => viewpoint.id !== path.id);
|
|
@@ -5257,6 +6333,22 @@ var WorldOrbit = (() => {
|
|
|
5257
6333
|
};
|
|
5258
6334
|
}
|
|
5259
6335
|
}
|
|
6336
|
+
if (diagnostic.field?.startsWith("event.")) {
|
|
6337
|
+
const parts = diagnostic.field.split(".");
|
|
6338
|
+
if (parts[1] && findEvent(document2, parts[1])) {
|
|
6339
|
+
if (parts[2] === "pose" && parts[3] && findEventPose(document2, parts[1], parts[3])) {
|
|
6340
|
+
return {
|
|
6341
|
+
kind: "event-pose",
|
|
6342
|
+
id: parts[1],
|
|
6343
|
+
key: parts[3]
|
|
6344
|
+
};
|
|
6345
|
+
}
|
|
6346
|
+
return {
|
|
6347
|
+
kind: "event",
|
|
6348
|
+
id: parts[1]
|
|
6349
|
+
};
|
|
6350
|
+
}
|
|
6351
|
+
}
|
|
5260
6352
|
if (diagnostic.field && diagnostic.field in ensureSystem(document2).atlasMetadata) {
|
|
5261
6353
|
return {
|
|
5262
6354
|
kind: "metadata",
|
|
@@ -5288,6 +6380,12 @@ var WorldOrbit = (() => {
|
|
|
5288
6380
|
function findRelation(document2, relationId) {
|
|
5289
6381
|
return document2.relations.find((relation) => relation.id === relationId) ?? null;
|
|
5290
6382
|
}
|
|
6383
|
+
function findEvent(document2, eventId) {
|
|
6384
|
+
return document2.events.find((event) => event.id === eventId) ?? null;
|
|
6385
|
+
}
|
|
6386
|
+
function findEventPose(document2, eventId, objectId) {
|
|
6387
|
+
return findEvent(document2, eventId)?.positions.find((pose) => pose.objectId === objectId) ?? null;
|
|
6388
|
+
}
|
|
5291
6389
|
function findViewpoint(system, viewpointId) {
|
|
5292
6390
|
return system?.viewpoints.find((viewpoint) => viewpoint.id === viewpointId) ?? null;
|
|
5293
6391
|
}
|
|
@@ -5303,13 +6401,30 @@ var WorldOrbit = (() => {
|
|
|
5303
6401
|
}
|
|
5304
6402
|
items[index] = value;
|
|
5305
6403
|
}
|
|
6404
|
+
function upsertEventPose(events, eventId, value) {
|
|
6405
|
+
const event = events.find((entry) => entry.id === eventId);
|
|
6406
|
+
if (!event) {
|
|
6407
|
+
throw new Error(`Unknown event "${eventId}" for pose update.`);
|
|
6408
|
+
}
|
|
6409
|
+
const index = event.positions.findIndex((entry) => entry.objectId === value.objectId);
|
|
6410
|
+
if (index === -1) {
|
|
6411
|
+
event.positions.push(value);
|
|
6412
|
+
event.positions.sort(comparePoseObjectId2);
|
|
6413
|
+
return;
|
|
6414
|
+
}
|
|
6415
|
+
event.positions[index] = value;
|
|
6416
|
+
}
|
|
5306
6417
|
function compareIdLike2(left, right) {
|
|
5307
6418
|
return left.id.localeCompare(right.id);
|
|
5308
6419
|
}
|
|
6420
|
+
function comparePoseObjectId2(left, right) {
|
|
6421
|
+
return left.objectId.localeCompare(right.objectId);
|
|
6422
|
+
}
|
|
5309
6423
|
|
|
5310
6424
|
// packages/core/dist/load.js
|
|
5311
|
-
var ATLAS_SCHEMA_PATTERN = /^schema\s+2(?:\.0|\.1)?$/i;
|
|
6425
|
+
var ATLAS_SCHEMA_PATTERN = /^schema\s+2(?:\.0|\.1|\.5)?$/i;
|
|
5312
6426
|
var ATLAS_SCHEMA_21_PATTERN = /^schema\s+2\.1$/i;
|
|
6427
|
+
var ATLAS_SCHEMA_25_PATTERN = /^schema\s+2\.5$/i;
|
|
5313
6428
|
var LEGACY_DRAFT_SCHEMA_PATTERN = /^schema\s+2\.0-draft$/i;
|
|
5314
6429
|
function detectWorldOrbitSchemaVersion(source) {
|
|
5315
6430
|
for (const line of stripCommentsForSchemaDetection(source).split(/\r?\n/)) {
|
|
@@ -5323,6 +6438,9 @@ var WorldOrbit = (() => {
|
|
|
5323
6438
|
if (ATLAS_SCHEMA_21_PATTERN.test(trimmed)) {
|
|
5324
6439
|
return "2.1";
|
|
5325
6440
|
}
|
|
6441
|
+
if (ATLAS_SCHEMA_25_PATTERN.test(trimmed)) {
|
|
6442
|
+
return "2.5";
|
|
6443
|
+
}
|
|
5326
6444
|
if (ATLAS_SCHEMA_PATTERN.test(trimmed)) {
|
|
5327
6445
|
return "2.0";
|
|
5328
6446
|
}
|
|
@@ -5383,7 +6501,7 @@ var WorldOrbit = (() => {
|
|
|
5383
6501
|
}
|
|
5384
6502
|
function loadWorldOrbitSourceWithDiagnostics(source) {
|
|
5385
6503
|
const schemaVersion = detectWorldOrbitSchemaVersion(source);
|
|
5386
|
-
if (schemaVersion === "2.0" || schemaVersion === "2.0-draft" || schemaVersion === "2.1") {
|
|
6504
|
+
if (schemaVersion === "2.0" || schemaVersion === "2.0-draft" || schemaVersion === "2.1" || schemaVersion === "2.5") {
|
|
5387
6505
|
return loadAtlasSourceWithDiagnostics(source, schemaVersion);
|
|
5388
6506
|
}
|
|
5389
6507
|
let ast;
|
|
@@ -5540,6 +6658,7 @@ var WorldOrbit = (() => {
|
|
|
5540
6658
|
background: true,
|
|
5541
6659
|
guides: true,
|
|
5542
6660
|
relations: true,
|
|
6661
|
+
events: true,
|
|
5543
6662
|
orbits: true,
|
|
5544
6663
|
objects: true,
|
|
5545
6664
|
labels: true,
|
|
@@ -5689,14 +6808,17 @@ var WorldOrbit = (() => {
|
|
|
5689
6808
|
}
|
|
5690
6809
|
function createAtlasStateSnapshot(viewerState, renderOptions, filter, viewpointId) {
|
|
5691
6810
|
return {
|
|
5692
|
-
version: "2.
|
|
6811
|
+
version: "2.5",
|
|
5693
6812
|
viewpointId,
|
|
6813
|
+
activeEventId: renderOptions.activeEventId ?? null,
|
|
5694
6814
|
viewerState: { ...viewerState },
|
|
5695
6815
|
renderOptions: {
|
|
5696
6816
|
preset: renderOptions.preset,
|
|
5697
6817
|
projection: renderOptions.projection,
|
|
6818
|
+
camera: renderOptions.camera ? { ...renderOptions.camera } : null,
|
|
5698
6819
|
layers: renderOptions.layers ? { ...renderOptions.layers } : void 0,
|
|
5699
|
-
scaleModel: renderOptions.scaleModel ? { ...renderOptions.scaleModel } : void 0
|
|
6820
|
+
scaleModel: renderOptions.scaleModel ? { ...renderOptions.scaleModel } : void 0,
|
|
6821
|
+
activeEventId: renderOptions.activeEventId ?? null
|
|
5700
6822
|
},
|
|
5701
6823
|
filter: normalizeViewerFilter(filter)
|
|
5702
6824
|
};
|
|
@@ -5707,8 +6829,9 @@ var WorldOrbit = (() => {
|
|
|
5707
6829
|
function deserializeViewerAtlasState(serialized) {
|
|
5708
6830
|
const raw = JSON.parse(decodeURIComponent(serialized));
|
|
5709
6831
|
return {
|
|
5710
|
-
version: "2.0",
|
|
6832
|
+
version: raw.version === "2.0" ? "2.0" : "2.5",
|
|
5711
6833
|
viewpointId: raw.viewpointId ?? null,
|
|
6834
|
+
activeEventId: raw.activeEventId ?? raw.renderOptions?.activeEventId ?? null,
|
|
5712
6835
|
viewerState: {
|
|
5713
6836
|
scale: raw.viewerState?.scale ?? 1,
|
|
5714
6837
|
rotationDeg: raw.viewerState?.rotationDeg ?? 0,
|
|
@@ -5719,8 +6842,10 @@ var WorldOrbit = (() => {
|
|
|
5719
6842
|
renderOptions: {
|
|
5720
6843
|
preset: raw.renderOptions?.preset,
|
|
5721
6844
|
projection: raw.renderOptions?.projection,
|
|
6845
|
+
camera: raw.renderOptions?.camera ? { ...raw.renderOptions.camera } : null,
|
|
5722
6846
|
layers: raw.renderOptions?.layers ? { ...raw.renderOptions.layers } : void 0,
|
|
5723
|
-
scaleModel: raw.renderOptions?.scaleModel ? { ...raw.renderOptions.scaleModel } : void 0
|
|
6847
|
+
scaleModel: raw.renderOptions?.scaleModel ? { ...raw.renderOptions.scaleModel } : void 0,
|
|
6848
|
+
activeEventId: raw.activeEventId ?? raw.renderOptions?.activeEventId ?? null
|
|
5724
6849
|
},
|
|
5725
6850
|
filter: normalizeViewerFilter(raw.filter ?? null)
|
|
5726
6851
|
};
|
|
@@ -5735,8 +6860,10 @@ var WorldOrbit = (() => {
|
|
|
5735
6860
|
viewerState: { ...atlasState.viewerState },
|
|
5736
6861
|
renderOptions: {
|
|
5737
6862
|
...atlasState.renderOptions,
|
|
6863
|
+
camera: atlasState.renderOptions.camera ? { ...atlasState.renderOptions.camera } : null,
|
|
5738
6864
|
layers: atlasState.renderOptions.layers ? { ...atlasState.renderOptions.layers } : void 0,
|
|
5739
|
-
scaleModel: atlasState.renderOptions.scaleModel ? { ...atlasState.renderOptions.scaleModel } : void 0
|
|
6865
|
+
scaleModel: atlasState.renderOptions.scaleModel ? { ...atlasState.renderOptions.scaleModel } : void 0,
|
|
6866
|
+
activeEventId: atlasState.renderOptions.activeEventId ?? null
|
|
5740
6867
|
},
|
|
5741
6868
|
filter: atlasState.filter ? { ...atlasState.filter } : null
|
|
5742
6869
|
}
|
|
@@ -5754,6 +6881,7 @@ var WorldOrbit = (() => {
|
|
|
5754
6881
|
background: viewpoint.layers.background,
|
|
5755
6882
|
guides: viewpoint.layers.guides,
|
|
5756
6883
|
relations: viewpoint.layers.relations,
|
|
6884
|
+
events: viewpoint.layers.events,
|
|
5757
6885
|
orbits: viewpoint.layers["orbits-front"] === void 0 && viewpoint.layers["orbits-back"] === void 0 ? void 0 : viewpoint.layers["orbits-front"] !== false || viewpoint.layers["orbits-back"] !== false,
|
|
5758
6886
|
objects: viewpoint.layers.objects,
|
|
5759
6887
|
labels: viewpoint.layers.labels,
|
|
@@ -6040,6 +7168,7 @@ var WorldOrbit = (() => {
|
|
|
6040
7168
|
const orbitMarkup = layers.orbits ? renderOrbitLayer(scene, visibleObjectIds, layers.structures) : { back: "", front: "" };
|
|
6041
7169
|
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("") : "";
|
|
6042
7170
|
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("") : "";
|
|
7171
|
+
const eventMarkup = layers.events ? scene.events.filter((event) => !event.hidden).map((event) => renderSceneEventOverlay(scene, event, visibleObjectIds, theme)).join("") : "";
|
|
6043
7172
|
const objectMarkup = layers.objects ? visibleObjects.map((object) => renderSceneObject(object, options.selectedObjectId ?? null, theme)).join("") : "";
|
|
6044
7173
|
const labelMarkup = layers.labels ? visibleLabels.map((label) => renderSceneLabel(scene, label, options.selectedObjectId ?? null)).join("") : "";
|
|
6045
7174
|
const metadataMarkup = layers.metadata ? `<text class="wo-title" x="56" y="64">${escapeXml(scene.title)}</text>
|
|
@@ -6075,6 +7204,9 @@ var WorldOrbit = (() => {
|
|
|
6075
7204
|
.wo-orbit-front { opacity: 0.9; }
|
|
6076
7205
|
.wo-orbit-band { stroke: ${theme.orbitBand}; stroke-linecap: round; }
|
|
6077
7206
|
.wo-relation { stroke: ${theme.relation}; stroke-width: 2; stroke-dasharray: 10 6; }
|
|
7207
|
+
.wo-event-line { stroke: ${theme.accent}; stroke-width: 1.6; stroke-dasharray: 5 5; opacity: 0.72; }
|
|
7208
|
+
.wo-event-node { fill: ${theme.accent}; stroke: ${theme.selected}; stroke-width: 1.4; opacity: 0.92; }
|
|
7209
|
+
.wo-event-label { fill: ${theme.accent}; font-family: ${theme.fontFamily}; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; }
|
|
6078
7210
|
.wo-leader { stroke: ${theme.leader}; stroke-width: 1.5; stroke-dasharray: 6 5; }
|
|
6079
7211
|
.wo-label { fill: ${theme.ink}; font-family: ${theme.fontFamily}; font-weight: 600; letter-spacing: 0.02em; }
|
|
6080
7212
|
.wo-label-secondary { fill: ${theme.muted}; font-family: ${theme.fontFamily}; font-weight: 500; }
|
|
@@ -6109,6 +7241,7 @@ var WorldOrbit = (() => {
|
|
|
6109
7241
|
${layers.orbits ? `<g data-layer-id="orbits-back">${orbitMarkup.back}</g>` : ""}
|
|
6110
7242
|
${layers.guides ? `<g data-layer-id="guides">${leaderMarkup}</g>` : ""}
|
|
6111
7243
|
${layers.relations ? `<g data-layer-id="relations">${relationMarkup}</g>` : ""}
|
|
7244
|
+
${layers.events ? `<g data-layer-id="events">${eventMarkup}</g>` : ""}
|
|
6112
7245
|
${layers.objects ? `<g data-layer-id="objects">${objectMarkup}</g>` : ""}
|
|
6113
7246
|
${layers.orbits ? `<g data-layer-id="orbits-front">${orbitMarkup.front}</g>` : ""}
|
|
6114
7247
|
${layers.labels ? `<g data-layer-id="labels">${labelMarkup}</g>` : ""}
|
|
@@ -6116,6 +7249,20 @@ var WorldOrbit = (() => {
|
|
|
6116
7249
|
</g>
|
|
6117
7250
|
</g>
|
|
6118
7251
|
</svg>`;
|
|
7252
|
+
}
|
|
7253
|
+
function renderSceneEventOverlay(scene, event, visibleObjectIds, theme) {
|
|
7254
|
+
const participants = event.objectIds.filter((objectId) => visibleObjectIds.has(objectId)).map((objectId) => scene.objects.find((object) => object.objectId === objectId && !object.hidden)).filter(Boolean);
|
|
7255
|
+
if (participants.length === 0) {
|
|
7256
|
+
return "";
|
|
7257
|
+
}
|
|
7258
|
+
const stroke = event.event.color || theme.accent;
|
|
7259
|
+
const label = event.event.label || event.event.id;
|
|
7260
|
+
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("");
|
|
7261
|
+
return `<g class="wo-event" data-render-id="${escapeXml(event.renderId)}" data-event-id="${escapeAttribute(event.eventId)}">
|
|
7262
|
+
${lineMarkup}
|
|
7263
|
+
<circle class="wo-event-node" cx="${event.x}" cy="${event.y}" r="5" fill="${escapeAttribute(stroke)}" />
|
|
7264
|
+
<text class="wo-event-label" x="${event.x}" y="${event.y - 10}" text-anchor="middle" font-size="10">${escapeXml(label)}</text>
|
|
7265
|
+
</g>`;
|
|
6119
7266
|
}
|
|
6120
7267
|
function renderDocumentToSvg(document2, options = {}) {
|
|
6121
7268
|
return renderSceneToSvg(renderDocumentToScene(document2, options), options);
|
|
@@ -6715,6 +7862,13 @@ var WorldOrbit = (() => {
|
|
|
6715
7862
|
value: `${details.object.resonance.targetObjectId} ${details.object.resonance.ratio}`
|
|
6716
7863
|
});
|
|
6717
7864
|
}
|
|
7865
|
+
if (details.relatedEvents.length > 0) {
|
|
7866
|
+
fields.set("events", {
|
|
7867
|
+
key: "events",
|
|
7868
|
+
label: "Events",
|
|
7869
|
+
value: details.relatedEvents.map((event) => event.event.label || event.event.id).join(", ")
|
|
7870
|
+
});
|
|
7871
|
+
}
|
|
6718
7872
|
if (placement?.mode === "at") {
|
|
6719
7873
|
fields.set("placement", {
|
|
6720
7874
|
key: "placement",
|
|
@@ -6819,6 +7973,7 @@ var WorldOrbit = (() => {
|
|
|
6819
7973
|
padding: options.padding,
|
|
6820
7974
|
preset: options.preset,
|
|
6821
7975
|
projection: options.projection,
|
|
7976
|
+
camera: options.camera ? { ...options.camera } : null,
|
|
6822
7977
|
scaleModel: options.scaleModel ? { ...options.scaleModel } : void 0,
|
|
6823
7978
|
theme: options.theme,
|
|
6824
7979
|
layers: options.layers,
|
|
@@ -7107,6 +8262,11 @@ var WorldOrbit = (() => {
|
|
|
7107
8262
|
if (currentInput.kind !== "scene" && viewpoint.projection !== scene.projection) {
|
|
7108
8263
|
nextRenderOptions.projection = viewpoint.projection;
|
|
7109
8264
|
}
|
|
8265
|
+
if (viewpoint.camera) {
|
|
8266
|
+
nextRenderOptions.camera = { ...viewpoint.camera };
|
|
8267
|
+
} else if (renderOptions.camera) {
|
|
8268
|
+
nextRenderOptions.camera = null;
|
|
8269
|
+
}
|
|
7110
8270
|
if (viewpointLayers) {
|
|
7111
8271
|
nextRenderOptions.layers = viewpointLayers;
|
|
7112
8272
|
}
|
|
@@ -7129,6 +8289,12 @@ var WorldOrbit = (() => {
|
|
|
7129
8289
|
emitAtlasStateChange();
|
|
7130
8290
|
return true;
|
|
7131
8291
|
},
|
|
8292
|
+
getActiveEventId() {
|
|
8293
|
+
return renderOptions.activeEventId ?? null;
|
|
8294
|
+
},
|
|
8295
|
+
setActiveEvent(id) {
|
|
8296
|
+
api.setRenderOptions({ activeEventId: id });
|
|
8297
|
+
},
|
|
7132
8298
|
search(query, limit = 12) {
|
|
7133
8299
|
return searchSceneObjects(scene, query, limit);
|
|
7134
8300
|
},
|
|
@@ -7393,6 +8559,7 @@ var WorldOrbit = (() => {
|
|
|
7393
8559
|
orbit: scene.orbitVisuals.find((orbit) => orbit.objectId === renderObject.objectId && !orbit.hidden) ?? null,
|
|
7394
8560
|
relatedOrbits: scene.orbitVisuals.filter((orbit) => !orbit.hidden && (orbit.objectId === renderObject.objectId || renderObject.ancestorIds.includes(orbit.objectId) || renderObject.childIds.includes(orbit.objectId))),
|
|
7395
8561
|
relations: scene.relations.filter((relation) => !relation.hidden && (relation.fromObjectId === renderObject.objectId || relation.toObjectId === renderObject.objectId)),
|
|
8562
|
+
relatedEvents: scene.events.filter((event) => !event.hidden && (event.targetObjectId === renderObject.objectId || event.objectIds.includes(renderObject.objectId))),
|
|
7396
8563
|
parent: getObjectById(renderObject.parentId),
|
|
7397
8564
|
children: renderObject.childIds.map((childId) => getObjectById(childId)).filter(Boolean),
|
|
7398
8565
|
ancestors: renderObject.ancestorIds.map((ancestorId) => getObjectById(ancestorId)).filter(Boolean),
|
|
@@ -7706,16 +8873,19 @@ var WorldOrbit = (() => {
|
|
|
7706
8873
|
function cloneRenderOptions(renderOptions) {
|
|
7707
8874
|
return {
|
|
7708
8875
|
...renderOptions,
|
|
8876
|
+
camera: renderOptions.camera ? { ...renderOptions.camera } : null,
|
|
7709
8877
|
filter: renderOptions.filter ? { ...renderOptions.filter } : void 0,
|
|
7710
8878
|
scaleModel: renderOptions.scaleModel ? { ...renderOptions.scaleModel } : void 0,
|
|
7711
8879
|
layers: renderOptions.layers ? { ...renderOptions.layers } : void 0,
|
|
7712
|
-
theme: renderOptions.theme && typeof renderOptions.theme === "object" ? { ...renderOptions.theme } : renderOptions.theme
|
|
8880
|
+
theme: renderOptions.theme && typeof renderOptions.theme === "object" ? { ...renderOptions.theme } : renderOptions.theme,
|
|
8881
|
+
activeEventId: renderOptions.activeEventId ?? null
|
|
7713
8882
|
};
|
|
7714
8883
|
}
|
|
7715
8884
|
function mergeRenderOptions(current, next) {
|
|
7716
8885
|
return {
|
|
7717
8886
|
...current,
|
|
7718
8887
|
...next,
|
|
8888
|
+
camera: next.camera !== void 0 ? next.camera ? { ...next.camera } : null : current.camera ? { ...current.camera } : null,
|
|
7719
8889
|
filter: next.filter !== void 0 ? normalizeViewerFilter(next.filter) : current.filter ? { ...current.filter } : void 0,
|
|
7720
8890
|
scaleModel: next.scaleModel ? {
|
|
7721
8891
|
...current.scaleModel ?? {},
|
|
@@ -7729,7 +8899,7 @@ var WorldOrbit = (() => {
|
|
|
7729
8899
|
};
|
|
7730
8900
|
}
|
|
7731
8901
|
function hasSceneAffectingRenderOptions(options) {
|
|
7732
|
-
return options.width !== void 0 || options.height !== void 0 || options.padding !== void 0 || options.preset !== void 0 || options.projection !== void 0 || options.scaleModel !== void 0;
|
|
8902
|
+
return options.width !== void 0 || options.height !== void 0 || options.padding !== void 0 || options.preset !== void 0 || options.projection !== void 0 || options.camera !== void 0 || options.scaleModel !== void 0 || options.activeEventId !== void 0;
|
|
7733
8903
|
}
|
|
7734
8904
|
function resolveSourceRenderOptions2(loaded, renderOptions) {
|
|
7735
8905
|
const atlasDocument = loaded.atlasDocument ?? loaded.draftDocument;
|
|
@@ -8326,6 +9496,8 @@ var WorldOrbit = (() => {
|
|
|
8326
9496
|
}
|
|
8327
9497
|
function buildInspectorSnapshot() {
|
|
8328
9498
|
const activeViewer = requireViewer();
|
|
9499
|
+
const scene = activeViewer.getScene();
|
|
9500
|
+
const camera = scene.camera;
|
|
8329
9501
|
return {
|
|
8330
9502
|
selection: activeViewer.getSelectionDetails(),
|
|
8331
9503
|
activeViewpoint: activeViewer.getActiveViewpoint(),
|
|
@@ -8333,13 +9505,21 @@ var WorldOrbit = (() => {
|
|
|
8333
9505
|
atlasState: activeViewer.getAtlasState(),
|
|
8334
9506
|
visibleObjectIds: activeViewer.getVisibleObjects().map((object) => object.objectId),
|
|
8335
9507
|
scene: {
|
|
8336
|
-
title:
|
|
8337
|
-
projection:
|
|
8338
|
-
|
|
8339
|
-
|
|
8340
|
-
|
|
8341
|
-
|
|
8342
|
-
|
|
9508
|
+
title: scene.title,
|
|
9509
|
+
projection: scene.projection,
|
|
9510
|
+
renderProjection: scene.renderProjection,
|
|
9511
|
+
camera: camera ? {
|
|
9512
|
+
azimuth: camera.azimuth,
|
|
9513
|
+
elevation: camera.elevation,
|
|
9514
|
+
roll: camera.roll,
|
|
9515
|
+
distance: camera.distance
|
|
9516
|
+
} : null,
|
|
9517
|
+
renderPreset: scene.renderPreset,
|
|
9518
|
+
groupCount: scene.groups.length,
|
|
9519
|
+
semanticGroupCount: scene.semanticGroups.length,
|
|
9520
|
+
relationCount: scene.relations.length,
|
|
9521
|
+
eventCount: scene.events.length,
|
|
9522
|
+
viewpointCount: scene.viewpoints.length
|
|
8343
9523
|
}
|
|
8344
9524
|
};
|
|
8345
9525
|
}
|