worldorbit 2.5.16 → 2.5.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/browser/core/dist/index.js +750 -73
- package/dist/browser/editor/dist/index.js +1303 -135
- package/dist/browser/markdown/dist/index.js +631 -72
- package/dist/browser/viewer/dist/index.js +658 -77
- package/dist/unpkg/core/dist/index.js +750 -73
- package/dist/unpkg/editor/dist/index.js +1303 -135
- package/dist/unpkg/markdown/dist/index.js +631 -72
- package/dist/unpkg/viewer/dist/index.js +658 -77
- package/dist/unpkg/worldorbit-core.min.js +12 -12
- package/dist/unpkg/worldorbit-editor.min.js +284 -202
- package/dist/unpkg/worldorbit-markdown.min.js +66 -58
- package/dist/unpkg/worldorbit-viewer.min.js +76 -68
- package/dist/unpkg/worldorbit.js +797 -78
- package/dist/unpkg/worldorbit.min.js +80 -72
- package/package.json +1 -1
- package/packages/core/dist/atlas-edit.js +74 -0
- package/packages/core/dist/atlas-validate.js +122 -8
- package/packages/core/dist/draft-parse.js +212 -8
- package/packages/core/dist/draft.d.ts +5 -2
- package/packages/core/dist/draft.js +59 -3
- package/packages/core/dist/format.js +63 -1
- package/packages/core/dist/normalize.js +1 -0
- package/packages/core/dist/scene.js +248 -46
- package/packages/core/dist/types.d.ts +41 -2
- package/packages/editor/dist/editor.js +597 -61
- package/packages/editor/dist/types.d.ts +3 -1
- package/packages/viewer/dist/atlas-state.js +6 -0
- package/packages/viewer/dist/atlas-viewer.js +1 -0
- package/packages/viewer/dist/render.js +31 -2
- package/packages/viewer/dist/theme.js +1 -0
- package/packages/viewer/dist/tooltip.js +9 -0
- package/packages/viewer/dist/types.d.ts +8 -1
- package/packages/viewer/dist/viewer.js +12 -1
|
@@ -565,6 +565,7 @@ var WorldOrbit = (() => {
|
|
|
565
565
|
system,
|
|
566
566
|
groups: [],
|
|
567
567
|
relations: [],
|
|
568
|
+
events: [],
|
|
568
569
|
objects
|
|
569
570
|
};
|
|
570
571
|
}
|
|
@@ -948,8 +949,10 @@ var WorldOrbit = (() => {
|
|
|
948
949
|
const scaleModel = resolveScaleModel(layoutPreset, options.scaleModel);
|
|
949
950
|
const spacingFactor = layoutPresetSpacing(layoutPreset);
|
|
950
951
|
const systemId = document2.system?.id ?? null;
|
|
951
|
-
const
|
|
952
|
-
const
|
|
952
|
+
const activeEventId = options.activeEventId ?? null;
|
|
953
|
+
const effectiveObjects = createEffectiveObjects(document2.objects, document2.events ?? [], activeEventId);
|
|
954
|
+
const objectMap = new Map(effectiveObjects.map((object) => [object.id, object]));
|
|
955
|
+
const relationships = buildSceneRelationships(effectiveObjects, objectMap);
|
|
953
956
|
const positions = /* @__PURE__ */ new Map();
|
|
954
957
|
const orbitDrafts = [];
|
|
955
958
|
const leaderDrafts = [];
|
|
@@ -958,7 +961,7 @@ var WorldOrbit = (() => {
|
|
|
958
961
|
const atObjects = [];
|
|
959
962
|
const surfaceChildren = /* @__PURE__ */ new Map();
|
|
960
963
|
const orbitChildren = /* @__PURE__ */ new Map();
|
|
961
|
-
for (const object of
|
|
964
|
+
for (const object of effectiveObjects) {
|
|
962
965
|
const placement = object.placement;
|
|
963
966
|
if (!placement) {
|
|
964
967
|
rootObjects.push(object);
|
|
@@ -1053,13 +1056,14 @@ var WorldOrbit = (() => {
|
|
|
1053
1056
|
const objects = [...positions.values()].map((position) => createSceneObject(position, scaleModel, relationships));
|
|
1054
1057
|
const orbitVisuals = orbitDrafts.map((draft) => createOrbitVisual(draft, relationships.groupIds.get(draft.object.id) ?? null));
|
|
1055
1058
|
const leaders = leaderDrafts.map((draft) => createLeaderLine(draft));
|
|
1056
|
-
const labels = createSceneLabels(objects, height, scaleModel.labelMultiplier);
|
|
1059
|
+
const labels = createSceneLabels(objects, width, height, scaleModel.labelMultiplier);
|
|
1057
1060
|
const relations = createSceneRelations(document2, objects);
|
|
1058
|
-
const
|
|
1059
|
-
const
|
|
1061
|
+
const events = createSceneEvents(document2.events ?? [], objects, activeEventId);
|
|
1062
|
+
const layers = createSceneLayers(orbitVisuals, relations, events, leaders, objects, labels);
|
|
1063
|
+
const groups = createSceneGroups(objects, orbitVisuals, leaders, labels, relationships, scaleModel.labelMultiplier);
|
|
1060
1064
|
const semanticGroups = createSceneSemanticGroups(document2, objects);
|
|
1061
1065
|
const viewpoints = createSceneViewpoints(document2, projection, frame.preset, relationships, objectMap);
|
|
1062
|
-
const contentBounds = calculateContentBounds(width, height, objects, orbitVisuals, leaders, labels);
|
|
1066
|
+
const contentBounds = calculateContentBounds(width, height, objects, orbitVisuals, leaders, labels, scaleModel.labelMultiplier);
|
|
1063
1067
|
return {
|
|
1064
1068
|
width,
|
|
1065
1069
|
height,
|
|
@@ -1085,6 +1089,8 @@ var WorldOrbit = (() => {
|
|
|
1085
1089
|
groups,
|
|
1086
1090
|
semanticGroups,
|
|
1087
1091
|
viewpoints,
|
|
1092
|
+
events,
|
|
1093
|
+
activeEventId,
|
|
1088
1094
|
objects,
|
|
1089
1095
|
orbitVisuals,
|
|
1090
1096
|
relations,
|
|
@@ -1103,6 +1109,35 @@ var WorldOrbit = (() => {
|
|
|
1103
1109
|
y: center.y + dx * sin + dy * cos
|
|
1104
1110
|
};
|
|
1105
1111
|
}
|
|
1112
|
+
function createEffectiveObjects(objects, events, activeEventId) {
|
|
1113
|
+
const cloned = objects.map((object) => structuredClone(object));
|
|
1114
|
+
if (!activeEventId) {
|
|
1115
|
+
return cloned;
|
|
1116
|
+
}
|
|
1117
|
+
const activeEvent = events.find((event) => event.id === activeEventId);
|
|
1118
|
+
if (!activeEvent) {
|
|
1119
|
+
return cloned;
|
|
1120
|
+
}
|
|
1121
|
+
const objectMap = new Map(cloned.map((object) => [object.id, object]));
|
|
1122
|
+
for (const pose of activeEvent.positions) {
|
|
1123
|
+
const object = objectMap.get(pose.objectId);
|
|
1124
|
+
if (!object) {
|
|
1125
|
+
continue;
|
|
1126
|
+
}
|
|
1127
|
+
object.placement = pose.placement ? structuredClone(pose.placement) : null;
|
|
1128
|
+
if (pose.inner) {
|
|
1129
|
+
object.properties.inner = { ...pose.inner };
|
|
1130
|
+
} else {
|
|
1131
|
+
delete object.properties.inner;
|
|
1132
|
+
}
|
|
1133
|
+
if (pose.outer) {
|
|
1134
|
+
object.properties.outer = { ...pose.outer };
|
|
1135
|
+
} else {
|
|
1136
|
+
delete object.properties.outer;
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
return cloned;
|
|
1140
|
+
}
|
|
1106
1141
|
function resolveLayoutPreset(document2) {
|
|
1107
1142
|
const rawScale = String(document2.system?.properties.scale ?? "balanced").toLowerCase();
|
|
1108
1143
|
switch (rawScale) {
|
|
@@ -1258,24 +1293,14 @@ var WorldOrbit = (() => {
|
|
|
1258
1293
|
hidden: draft.object.properties.hidden === true
|
|
1259
1294
|
};
|
|
1260
1295
|
}
|
|
1261
|
-
function createSceneLabels(objects, sceneHeight, labelMultiplier) {
|
|
1296
|
+
function createSceneLabels(objects, sceneWidth, sceneHeight, labelMultiplier) {
|
|
1262
1297
|
const labels = [];
|
|
1263
1298
|
const occupied = [];
|
|
1264
|
-
const
|
|
1299
|
+
const objectMap = new Map(objects.map((object) => [object.objectId, object]));
|
|
1300
|
+
const visibleObjects = [...objects].filter((object) => !object.hidden && object.object.renderHints?.renderLabel !== false).sort(compareLabelPlacementOrder);
|
|
1265
1301
|
for (const object of visibleObjects) {
|
|
1266
|
-
const
|
|
1267
|
-
|
|
1268
|
-
let labelY = object.y + direction * (object.radius + 18 * labelMultiplier);
|
|
1269
|
-
let secondaryY = labelY + direction * (16 * labelMultiplier);
|
|
1270
|
-
let bounds = createLabelRect(object.x, labelY, secondaryY, labelHalfWidth, direction);
|
|
1271
|
-
let attempts = 0;
|
|
1272
|
-
while (occupied.some((entry) => rectsOverlap(entry, bounds)) && attempts < 10) {
|
|
1273
|
-
labelY += direction * 14 * labelMultiplier;
|
|
1274
|
-
secondaryY += direction * 14 * labelMultiplier;
|
|
1275
|
-
bounds = createLabelRect(object.x, labelY, secondaryY, labelHalfWidth, direction);
|
|
1276
|
-
attempts += 1;
|
|
1277
|
-
}
|
|
1278
|
-
occupied.push(bounds);
|
|
1302
|
+
const placement = selectLabelPlacement(object, objectMap, occupied, sceneWidth, sceneHeight, labelMultiplier) ?? createLabelPlacement(object, defaultVerticalDirection(object, objectMap.get(object.parentId ?? "") ?? null, sceneHeight), 0, labelMultiplier);
|
|
1303
|
+
occupied.push(createLabelRect(object, placement, labelMultiplier));
|
|
1279
1304
|
labels.push({
|
|
1280
1305
|
renderId: `${object.renderId}-label`,
|
|
1281
1306
|
objectId: object.objectId,
|
|
@@ -1284,17 +1309,128 @@ var WorldOrbit = (() => {
|
|
|
1284
1309
|
semanticGroupIds: [...object.semanticGroupIds],
|
|
1285
1310
|
label: object.label,
|
|
1286
1311
|
secondaryLabel: object.secondaryLabel,
|
|
1287
|
-
x:
|
|
1288
|
-
y: labelY,
|
|
1289
|
-
secondaryY,
|
|
1290
|
-
textAnchor:
|
|
1291
|
-
direction: direction
|
|
1312
|
+
x: placement.x,
|
|
1313
|
+
y: placement.labelY,
|
|
1314
|
+
secondaryY: placement.secondaryY,
|
|
1315
|
+
textAnchor: placement.textAnchor,
|
|
1316
|
+
direction: placement.direction,
|
|
1292
1317
|
hidden: object.hidden
|
|
1293
1318
|
});
|
|
1294
1319
|
}
|
|
1295
1320
|
return labels;
|
|
1296
1321
|
}
|
|
1297
|
-
function
|
|
1322
|
+
function compareLabelPlacementOrder(left, right) {
|
|
1323
|
+
const priorityDiff = labelPlacementPriority(left) - labelPlacementPriority(right);
|
|
1324
|
+
if (priorityDiff !== 0) {
|
|
1325
|
+
return priorityDiff;
|
|
1326
|
+
}
|
|
1327
|
+
const renderPriorityDiff = (right.object.renderHints?.renderPriority ?? 0) - (left.object.renderHints?.renderPriority ?? 0);
|
|
1328
|
+
if (renderPriorityDiff !== 0) {
|
|
1329
|
+
return renderPriorityDiff;
|
|
1330
|
+
}
|
|
1331
|
+
return left.sortKey - right.sortKey;
|
|
1332
|
+
}
|
|
1333
|
+
function labelPlacementPriority(object) {
|
|
1334
|
+
switch (object.object.type) {
|
|
1335
|
+
case "star":
|
|
1336
|
+
return 0;
|
|
1337
|
+
case "planet":
|
|
1338
|
+
return 1;
|
|
1339
|
+
case "moon":
|
|
1340
|
+
return 2;
|
|
1341
|
+
case "belt":
|
|
1342
|
+
case "ring":
|
|
1343
|
+
return 3;
|
|
1344
|
+
case "asteroid":
|
|
1345
|
+
case "comet":
|
|
1346
|
+
return 4;
|
|
1347
|
+
case "structure":
|
|
1348
|
+
case "phenomenon":
|
|
1349
|
+
return 5;
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
function selectLabelPlacement(object, objectMap, occupied, sceneWidth, sceneHeight, labelMultiplier) {
|
|
1353
|
+
for (const direction of preferredLabelDirections(object, objectMap, sceneWidth, sceneHeight)) {
|
|
1354
|
+
const maxAttempts = direction === "left" || direction === "right" ? 4 : 6;
|
|
1355
|
+
for (let attempt = 0; attempt <= maxAttempts; attempt += 1) {
|
|
1356
|
+
const placement = createLabelPlacement(object, direction, attempt, labelMultiplier);
|
|
1357
|
+
const rect = createLabelRect(object, placement, labelMultiplier);
|
|
1358
|
+
if (!occupied.some((entry) => rectsOverlap(entry, rect))) {
|
|
1359
|
+
return placement;
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
return null;
|
|
1364
|
+
}
|
|
1365
|
+
function preferredLabelDirections(object, objectMap, sceneWidth, sceneHeight) {
|
|
1366
|
+
const parent = object.parentId ? objectMap.get(object.parentId) ?? null : null;
|
|
1367
|
+
const vertical = defaultVerticalDirection(object, parent, sceneHeight);
|
|
1368
|
+
const oppositeVertical = vertical === "below" ? "above" : "below";
|
|
1369
|
+
const horizontal = defaultHorizontalDirection(object, parent, sceneWidth);
|
|
1370
|
+
const oppositeHorizontal = horizontal === "right" ? "left" : "right";
|
|
1371
|
+
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";
|
|
1372
|
+
return preferHorizontal ? [horizontal, vertical, oppositeHorizontal, oppositeVertical] : [vertical, horizontal, oppositeVertical, oppositeHorizontal];
|
|
1373
|
+
}
|
|
1374
|
+
function defaultVerticalDirection(object, parent, sceneHeight) {
|
|
1375
|
+
if (parent && Math.abs(object.y - parent.y) > 6) {
|
|
1376
|
+
return object.y >= parent.y ? "below" : "above";
|
|
1377
|
+
}
|
|
1378
|
+
return object.y > sceneHeight * 0.62 ? "above" : "below";
|
|
1379
|
+
}
|
|
1380
|
+
function defaultHorizontalDirection(object, parent, sceneWidth) {
|
|
1381
|
+
if (parent && Math.abs(object.x - parent.x) > 6) {
|
|
1382
|
+
return object.x >= parent.x ? "right" : "left";
|
|
1383
|
+
}
|
|
1384
|
+
return object.x >= sceneWidth / 2 ? "right" : "left";
|
|
1385
|
+
}
|
|
1386
|
+
function createLabelPlacement(object, direction, attempt, labelMultiplier) {
|
|
1387
|
+
const step = 14 * labelMultiplier;
|
|
1388
|
+
switch (direction) {
|
|
1389
|
+
case "above": {
|
|
1390
|
+
const labelY = object.y - (object.radius + 18 * labelMultiplier + attempt * step);
|
|
1391
|
+
return {
|
|
1392
|
+
x: object.x,
|
|
1393
|
+
labelY,
|
|
1394
|
+
secondaryY: labelY - 16 * labelMultiplier,
|
|
1395
|
+
textAnchor: "middle",
|
|
1396
|
+
direction
|
|
1397
|
+
};
|
|
1398
|
+
}
|
|
1399
|
+
case "below": {
|
|
1400
|
+
const labelY = object.y + object.radius + 18 * labelMultiplier + attempt * step;
|
|
1401
|
+
return {
|
|
1402
|
+
x: object.x,
|
|
1403
|
+
labelY,
|
|
1404
|
+
secondaryY: labelY + 16 * labelMultiplier,
|
|
1405
|
+
textAnchor: "middle",
|
|
1406
|
+
direction
|
|
1407
|
+
};
|
|
1408
|
+
}
|
|
1409
|
+
case "left": {
|
|
1410
|
+
const x = object.x - (object.visualRadius + 16 * labelMultiplier + attempt * step);
|
|
1411
|
+
const labelY = object.y - 4 * labelMultiplier;
|
|
1412
|
+
return {
|
|
1413
|
+
x,
|
|
1414
|
+
labelY,
|
|
1415
|
+
secondaryY: labelY + 16 * labelMultiplier,
|
|
1416
|
+
textAnchor: "end",
|
|
1417
|
+
direction
|
|
1418
|
+
};
|
|
1419
|
+
}
|
|
1420
|
+
case "right": {
|
|
1421
|
+
const x = object.x + object.visualRadius + 16 * labelMultiplier + attempt * step;
|
|
1422
|
+
const labelY = object.y - 4 * labelMultiplier;
|
|
1423
|
+
return {
|
|
1424
|
+
x,
|
|
1425
|
+
labelY,
|
|
1426
|
+
secondaryY: labelY + 16 * labelMultiplier,
|
|
1427
|
+
textAnchor: "start",
|
|
1428
|
+
direction
|
|
1429
|
+
};
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
function createSceneLayers(orbitVisuals, relations, events, leaders, objects, labels) {
|
|
1298
1434
|
const backOrbitIds = orbitVisuals.filter((visual) => !visual.hidden && Boolean(visual.backArcPath)).map((visual) => visual.renderId);
|
|
1299
1435
|
const frontOrbitIds = orbitVisuals.filter((visual) => !visual.hidden).map((visual) => visual.renderId);
|
|
1300
1436
|
return [
|
|
@@ -1309,6 +1445,10 @@ var WorldOrbit = (() => {
|
|
|
1309
1445
|
id: "relations",
|
|
1310
1446
|
renderIds: relations.filter((relation) => !relation.hidden).map((relation) => relation.renderId)
|
|
1311
1447
|
},
|
|
1448
|
+
{
|
|
1449
|
+
id: "events",
|
|
1450
|
+
renderIds: events.filter((event) => !event.hidden).map((event) => event.renderId)
|
|
1451
|
+
},
|
|
1312
1452
|
{
|
|
1313
1453
|
id: "objects",
|
|
1314
1454
|
renderIds: objects.filter((object) => !object.hidden).map((object) => object.renderId)
|
|
@@ -1320,7 +1460,7 @@ var WorldOrbit = (() => {
|
|
|
1320
1460
|
{ id: "metadata", renderIds: ["wo-title", "wo-subtitle", "wo-meta"] }
|
|
1321
1461
|
];
|
|
1322
1462
|
}
|
|
1323
|
-
function createSceneGroups(objects, orbitVisuals, leaders, labels, relationships) {
|
|
1463
|
+
function createSceneGroups(objects, orbitVisuals, leaders, labels, relationships, labelMultiplier) {
|
|
1324
1464
|
const groups = /* @__PURE__ */ new Map();
|
|
1325
1465
|
const ensureGroup = (groupId) => {
|
|
1326
1466
|
if (!groupId) {
|
|
@@ -1369,7 +1509,7 @@ var WorldOrbit = (() => {
|
|
|
1369
1509
|
}
|
|
1370
1510
|
}
|
|
1371
1511
|
for (const group of groups.values()) {
|
|
1372
|
-
group.contentBounds = calculateGroupBounds(group, objects, orbitVisuals, leaders, labels);
|
|
1512
|
+
group.contentBounds = calculateGroupBounds(group, objects, orbitVisuals, leaders, labels, labelMultiplier);
|
|
1373
1513
|
}
|
|
1374
1514
|
return [...groups.values()].sort((left, right) => left.label.localeCompare(right.label));
|
|
1375
1515
|
}
|
|
@@ -1403,6 +1543,29 @@ var WorldOrbit = (() => {
|
|
|
1403
1543
|
};
|
|
1404
1544
|
}).sort((left, right) => left.relation.id.localeCompare(right.relation.id));
|
|
1405
1545
|
}
|
|
1546
|
+
function createSceneEvents(events, objects, activeEventId) {
|
|
1547
|
+
const objectMap = new Map(objects.map((object) => [object.objectId, object]));
|
|
1548
|
+
return events.map((event) => {
|
|
1549
|
+
const objectIds = [.../* @__PURE__ */ new Set([
|
|
1550
|
+
...event.targetObjectId ? [event.targetObjectId] : [],
|
|
1551
|
+
...event.participantObjectIds
|
|
1552
|
+
])];
|
|
1553
|
+
const positions = objectIds.map((objectId) => objectMap.get(objectId)).filter(Boolean);
|
|
1554
|
+
const centroidX = positions.length > 0 ? positions.reduce((sum, object) => sum + object.x, 0) / positions.length : 0;
|
|
1555
|
+
const centroidY = positions.length > 0 ? positions.reduce((sum, object) => sum + object.y, 0) / positions.length : 0;
|
|
1556
|
+
return {
|
|
1557
|
+
renderId: `${createRenderId(event.id)}-event`,
|
|
1558
|
+
eventId: event.id,
|
|
1559
|
+
event,
|
|
1560
|
+
objectIds,
|
|
1561
|
+
participantIds: [...event.participantObjectIds],
|
|
1562
|
+
targetObjectId: event.targetObjectId,
|
|
1563
|
+
x: centroidX,
|
|
1564
|
+
y: centroidY,
|
|
1565
|
+
hidden: event.hidden || positions.length === 0 || positions.every((object) => object.hidden) || activeEventId !== null && event.id !== activeEventId
|
|
1566
|
+
};
|
|
1567
|
+
}).sort((left, right) => left.event.id.localeCompare(right.event.id));
|
|
1568
|
+
}
|
|
1406
1569
|
function createSceneViewpoints(document2, projection, preset, relationships, objectMap) {
|
|
1407
1570
|
const generatedOverview = createGeneratedOverviewViewpoint(document2, projection, preset);
|
|
1408
1571
|
const drafts = /* @__PURE__ */ new Map();
|
|
@@ -1456,6 +1619,7 @@ var WorldOrbit = (() => {
|
|
|
1456
1619
|
summary: "Fit the whole system with the current atlas defaults.",
|
|
1457
1620
|
objectId: null,
|
|
1458
1621
|
selectedObjectId: null,
|
|
1622
|
+
eventIds: [],
|
|
1459
1623
|
projection,
|
|
1460
1624
|
preset,
|
|
1461
1625
|
rotationDeg: 0,
|
|
@@ -1492,6 +1656,9 @@ var WorldOrbit = (() => {
|
|
|
1492
1656
|
draft.select = normalizedValue;
|
|
1493
1657
|
}
|
|
1494
1658
|
return;
|
|
1659
|
+
case "events":
|
|
1660
|
+
draft.eventIds = splitListValue(normalizedValue);
|
|
1661
|
+
return;
|
|
1495
1662
|
case "projection":
|
|
1496
1663
|
case "view":
|
|
1497
1664
|
draft.projection = parseViewProjection(normalizedValue) ?? projection;
|
|
@@ -1548,6 +1715,7 @@ var WorldOrbit = (() => {
|
|
|
1548
1715
|
summary: draft.summary?.trim() || createViewpointSummary(label, objectId, filter),
|
|
1549
1716
|
objectId,
|
|
1550
1717
|
selectedObjectId,
|
|
1718
|
+
eventIds: [...new Set(draft.eventIds ?? [])],
|
|
1551
1719
|
projection: draft.projection ?? projection,
|
|
1552
1720
|
preset: draft.preset ?? preset,
|
|
1553
1721
|
rotationDeg: draft.rotationDeg ?? 0,
|
|
@@ -1605,7 +1773,7 @@ var WorldOrbit = (() => {
|
|
|
1605
1773
|
next["orbits-front"] = enabled;
|
|
1606
1774
|
continue;
|
|
1607
1775
|
}
|
|
1608
|
-
if (rawLayer === "background" || rawLayer === "guides" || rawLayer === "orbits-back" || rawLayer === "orbits-front" || rawLayer === "relations" || rawLayer === "objects" || rawLayer === "labels" || rawLayer === "metadata") {
|
|
1776
|
+
if (rawLayer === "background" || rawLayer === "guides" || rawLayer === "orbits-back" || rawLayer === "orbits-front" || rawLayer === "relations" || rawLayer === "events" || rawLayer === "objects" || rawLayer === "labels" || rawLayer === "metadata") {
|
|
1609
1777
|
next[rawLayer] = enabled;
|
|
1610
1778
|
}
|
|
1611
1779
|
}
|
|
@@ -1653,7 +1821,7 @@ var WorldOrbit = (() => {
|
|
|
1653
1821
|
}
|
|
1654
1822
|
return parts.join(" - ");
|
|
1655
1823
|
}
|
|
1656
|
-
function calculateContentBounds(width, height, objects, orbitVisuals, leaders, labels) {
|
|
1824
|
+
function calculateContentBounds(width, height, objects, orbitVisuals, leaders, labels, labelMultiplier) {
|
|
1657
1825
|
let minX = Number.POSITIVE_INFINITY;
|
|
1658
1826
|
let minY = Number.POSITIVE_INFINITY;
|
|
1659
1827
|
let maxX = Number.NEGATIVE_INFINITY;
|
|
@@ -1683,7 +1851,7 @@ var WorldOrbit = (() => {
|
|
|
1683
1851
|
for (const label of labels) {
|
|
1684
1852
|
if (label.hidden)
|
|
1685
1853
|
continue;
|
|
1686
|
-
includeLabelBounds(label, include);
|
|
1854
|
+
includeLabelBounds(label, include, labelMultiplier);
|
|
1687
1855
|
}
|
|
1688
1856
|
if (!Number.isFinite(minX) || !Number.isFinite(minY)) {
|
|
1689
1857
|
return createBounds(0, 0, width, height);
|
|
@@ -1721,13 +1889,10 @@ var WorldOrbit = (() => {
|
|
|
1721
1889
|
include(object.x - object.visualRadius - 24, object.y - object.visualRadius - 16);
|
|
1722
1890
|
include(object.x + object.visualRadius + 24, object.y + object.visualRadius + 36);
|
|
1723
1891
|
}
|
|
1724
|
-
function includeLabelBounds(label, include) {
|
|
1725
|
-
const
|
|
1726
|
-
|
|
1727
|
-
include(
|
|
1728
|
-
include(label.x + labelHalfWidth, label.y + 8);
|
|
1729
|
-
include(label.x - labelHalfWidth, label.secondaryY - 14);
|
|
1730
|
-
include(label.x + labelHalfWidth, label.secondaryY + 8);
|
|
1892
|
+
function includeLabelBounds(label, include, labelMultiplier) {
|
|
1893
|
+
const bounds = createLabelRectFromText(label.x, label.y, label.secondaryY, label.textAnchor, label.direction, label.label, label.secondaryLabel, labelMultiplier);
|
|
1894
|
+
include(bounds.left, bounds.top);
|
|
1895
|
+
include(bounds.right, bounds.bottom);
|
|
1731
1896
|
}
|
|
1732
1897
|
function placeObject(object, x, y, depth, positions, orbitDrafts, leaderDrafts, context) {
|
|
1733
1898
|
if (positions.has(object.id)) {
|
|
@@ -2117,7 +2282,7 @@ var WorldOrbit = (() => {
|
|
|
2117
2282
|
return null;
|
|
2118
2283
|
}
|
|
2119
2284
|
}
|
|
2120
|
-
function calculateGroupBounds(group, objects, orbitVisuals, leaders, labels) {
|
|
2285
|
+
function calculateGroupBounds(group, objects, orbitVisuals, leaders, labels, labelMultiplier) {
|
|
2121
2286
|
let minX = Number.POSITIVE_INFINITY;
|
|
2122
2287
|
let minY = Number.POSITIVE_INFINITY;
|
|
2123
2288
|
let maxX = Number.NEGATIVE_INFINITY;
|
|
@@ -2146,7 +2311,7 @@ var WorldOrbit = (() => {
|
|
|
2146
2311
|
}
|
|
2147
2312
|
for (const label of labels) {
|
|
2148
2313
|
if (!label.hidden && group.labelIds.includes(label.objectId)) {
|
|
2149
|
-
includeLabelBounds(label, include);
|
|
2314
|
+
includeLabelBounds(label, include, labelMultiplier);
|
|
2150
2315
|
}
|
|
2151
2316
|
}
|
|
2152
2317
|
if (!Number.isFinite(minX) || !Number.isFinite(minY)) {
|
|
@@ -2171,12 +2336,28 @@ var WorldOrbit = (() => {
|
|
|
2171
2336
|
}
|
|
2172
2337
|
return current.id;
|
|
2173
2338
|
}
|
|
2174
|
-
function createLabelRect(
|
|
2339
|
+
function createLabelRect(object, placement, labelMultiplier) {
|
|
2340
|
+
return createLabelRectFromText(placement.x, placement.labelY, placement.secondaryY, placement.textAnchor, placement.direction, object.label, object.secondaryLabel, labelMultiplier);
|
|
2341
|
+
}
|
|
2342
|
+
function createLabelRectFromText(x, labelY, secondaryY, textAnchor, direction, label, secondaryLabel, labelMultiplier) {
|
|
2343
|
+
const labelHalfWidth = estimateLabelHalfWidthFromText(label, secondaryLabel, labelMultiplier);
|
|
2344
|
+
const labelWidth = labelHalfWidth * 2;
|
|
2345
|
+
const topPadding = direction === "above" ? 18 : 12;
|
|
2346
|
+
const bottomPadding = direction === "above" ? 8 : 12;
|
|
2347
|
+
let left = x - labelHalfWidth;
|
|
2348
|
+
let right = x + labelHalfWidth;
|
|
2349
|
+
if (textAnchor === "start") {
|
|
2350
|
+
left = x;
|
|
2351
|
+
right = x + labelWidth;
|
|
2352
|
+
} else if (textAnchor === "end") {
|
|
2353
|
+
left = x - labelWidth;
|
|
2354
|
+
right = x;
|
|
2355
|
+
}
|
|
2175
2356
|
return {
|
|
2176
|
-
left
|
|
2177
|
-
right
|
|
2178
|
-
top: Math.min(labelY, secondaryY) -
|
|
2179
|
-
bottom: Math.max(labelY, secondaryY) +
|
|
2357
|
+
left,
|
|
2358
|
+
right,
|
|
2359
|
+
top: Math.min(labelY, secondaryY) - topPadding,
|
|
2360
|
+
bottom: Math.max(labelY, secondaryY) + bottomPadding
|
|
2180
2361
|
};
|
|
2181
2362
|
}
|
|
2182
2363
|
function rectsOverlap(left, right) {
|
|
@@ -2363,11 +2544,6 @@ var WorldOrbit = (() => {
|
|
|
2363
2544
|
function customColorFor(value) {
|
|
2364
2545
|
return typeof value === "string" && value.trim() ? value : void 0;
|
|
2365
2546
|
}
|
|
2366
|
-
function estimateLabelHalfWidth(object, labelMultiplier) {
|
|
2367
|
-
const primaryWidth = object.label.length * 4.6 * labelMultiplier + 18;
|
|
2368
|
-
const secondaryWidth = object.secondaryLabel.length * 3.9 * labelMultiplier + 18;
|
|
2369
|
-
return Math.max(primaryWidth, secondaryWidth, object.visualRadius + 18);
|
|
2370
|
-
}
|
|
2371
2547
|
function estimateLabelHalfWidthFromText(label, secondaryLabel, labelMultiplier) {
|
|
2372
2548
|
const primaryWidth = label.length * 4.6 * labelMultiplier + 18;
|
|
2373
2549
|
const secondaryWidth = secondaryLabel.length * 3.9 * labelMultiplier + 18;
|
|
@@ -2407,6 +2583,7 @@ var WorldOrbit = (() => {
|
|
|
2407
2583
|
system,
|
|
2408
2584
|
groups: structuredClone(document2.groups ?? []),
|
|
2409
2585
|
relations: structuredClone(document2.relations ?? []),
|
|
2586
|
+
events: structuredClone(document2.events ?? []),
|
|
2410
2587
|
objects: document2.objects.map(cloneWorldOrbitObject),
|
|
2411
2588
|
diagnostics
|
|
2412
2589
|
};
|
|
@@ -2414,7 +2591,7 @@ var WorldOrbit = (() => {
|
|
|
2414
2591
|
function upgradeDocumentToDraftV2(document2, options = {}) {
|
|
2415
2592
|
return convertAtlasDocumentToLegacyDraft(upgradeDocumentToV2(document2, options));
|
|
2416
2593
|
}
|
|
2417
|
-
function materializeAtlasDocument(document2) {
|
|
2594
|
+
function materializeAtlasDocument(document2, options = {}) {
|
|
2418
2595
|
const system = document2.system ? {
|
|
2419
2596
|
type: "system",
|
|
2420
2597
|
id: document2.system.id,
|
|
@@ -2425,6 +2602,8 @@ var WorldOrbit = (() => {
|
|
|
2425
2602
|
properties: materializeDraftSystemProperties(document2.system),
|
|
2426
2603
|
info: materializeDraftSystemInfo(document2.system)
|
|
2427
2604
|
} : null;
|
|
2605
|
+
const objects = document2.objects.map(cloneWorldOrbitObject);
|
|
2606
|
+
applyEventPoseOverrides(objects, document2.events ?? [], options.activeEventId ?? null);
|
|
2428
2607
|
return {
|
|
2429
2608
|
format: "worldorbit",
|
|
2430
2609
|
version: "1.0",
|
|
@@ -2432,7 +2611,8 @@ var WorldOrbit = (() => {
|
|
|
2432
2611
|
system,
|
|
2433
2612
|
groups: structuredClone(document2.groups ?? []),
|
|
2434
2613
|
relations: structuredClone(document2.relations ?? []),
|
|
2435
|
-
|
|
2614
|
+
events: document2.events.map(cloneWorldOrbitEvent),
|
|
2615
|
+
objects
|
|
2436
2616
|
};
|
|
2437
2617
|
}
|
|
2438
2618
|
function createDraftSystem(document2, defaults, atlasMetadata, annotations, diagnostics, preset) {
|
|
@@ -2557,6 +2737,7 @@ var WorldOrbit = (() => {
|
|
|
2557
2737
|
summary: viewpoint.summary,
|
|
2558
2738
|
focusObjectId: viewpoint.objectId,
|
|
2559
2739
|
selectedObjectId: viewpoint.selectedObjectId,
|
|
2740
|
+
events: [...viewpoint.eventIds],
|
|
2560
2741
|
projection: viewpoint.projection,
|
|
2561
2742
|
preset: viewpoint.preset,
|
|
2562
2743
|
zoom: viewpoint.scale,
|
|
@@ -2589,6 +2770,52 @@ var WorldOrbit = (() => {
|
|
|
2589
2770
|
info: { ...object.info }
|
|
2590
2771
|
};
|
|
2591
2772
|
}
|
|
2773
|
+
function cloneWorldOrbitEvent(event) {
|
|
2774
|
+
return {
|
|
2775
|
+
...event,
|
|
2776
|
+
participantObjectIds: [...event.participantObjectIds],
|
|
2777
|
+
tags: [...event.tags],
|
|
2778
|
+
positions: event.positions.map(cloneWorldOrbitEventPose)
|
|
2779
|
+
};
|
|
2780
|
+
}
|
|
2781
|
+
function cloneWorldOrbitEventPose(pose) {
|
|
2782
|
+
return {
|
|
2783
|
+
objectId: pose.objectId,
|
|
2784
|
+
placement: clonePlacement(pose.placement),
|
|
2785
|
+
inner: pose.inner ? { ...pose.inner } : void 0,
|
|
2786
|
+
outer: pose.outer ? { ...pose.outer } : void 0
|
|
2787
|
+
};
|
|
2788
|
+
}
|
|
2789
|
+
function clonePlacement(placement) {
|
|
2790
|
+
return placement ? structuredClone(placement) : null;
|
|
2791
|
+
}
|
|
2792
|
+
function applyEventPoseOverrides(objects, events, activeEventId) {
|
|
2793
|
+
if (!activeEventId) {
|
|
2794
|
+
return;
|
|
2795
|
+
}
|
|
2796
|
+
const event = events.find((entry) => entry.id === activeEventId);
|
|
2797
|
+
if (!event) {
|
|
2798
|
+
return;
|
|
2799
|
+
}
|
|
2800
|
+
const objectMap = new Map(objects.map((object) => [object.id, object]));
|
|
2801
|
+
for (const pose of event.positions) {
|
|
2802
|
+
const object = objectMap.get(pose.objectId);
|
|
2803
|
+
if (!object) {
|
|
2804
|
+
continue;
|
|
2805
|
+
}
|
|
2806
|
+
object.placement = clonePlacement(pose.placement);
|
|
2807
|
+
if (pose.inner) {
|
|
2808
|
+
object.properties.inner = { ...pose.inner };
|
|
2809
|
+
} else {
|
|
2810
|
+
delete object.properties.inner;
|
|
2811
|
+
}
|
|
2812
|
+
if (pose.outer) {
|
|
2813
|
+
object.properties.outer = { ...pose.outer };
|
|
2814
|
+
} else {
|
|
2815
|
+
delete object.properties.outer;
|
|
2816
|
+
}
|
|
2817
|
+
}
|
|
2818
|
+
}
|
|
2592
2819
|
function cloneProperties(properties) {
|
|
2593
2820
|
const next = {};
|
|
2594
2821
|
for (const [key, value] of Object.entries(properties)) {
|
|
@@ -2686,6 +2913,9 @@ var WorldOrbit = (() => {
|
|
|
2686
2913
|
if ((viewpoint.filter?.groupIds.length ?? 0) > 0) {
|
|
2687
2914
|
info2[`${prefix}.groups`] = viewpoint.filter?.groupIds.join(" ") ?? "";
|
|
2688
2915
|
}
|
|
2916
|
+
if (viewpoint.events.length > 0) {
|
|
2917
|
+
info2[`${prefix}.events`] = viewpoint.events.join(" ");
|
|
2918
|
+
}
|
|
2689
2919
|
}
|
|
2690
2920
|
for (const annotation of system.annotations) {
|
|
2691
2921
|
const prefix = `annotation.${annotation.id}`;
|
|
@@ -2710,7 +2940,7 @@ var WorldOrbit = (() => {
|
|
|
2710
2940
|
if (orbitFront !== void 0 || orbitBack !== void 0) {
|
|
2711
2941
|
tokens.push(orbitFront !== false || orbitBack !== false ? "orbits" : "-orbits");
|
|
2712
2942
|
}
|
|
2713
|
-
for (const key of ["background", "guides", "relations", "objects", "labels", "metadata"]) {
|
|
2943
|
+
for (const key of ["background", "guides", "relations", "events", "objects", "labels", "metadata"]) {
|
|
2714
2944
|
if (layers[key] !== void 0) {
|
|
2715
2945
|
tokens.push(layers[key] ? key : `-${key}`);
|
|
2716
2946
|
}
|
|
@@ -2814,6 +3044,10 @@ var WorldOrbit = (() => {
|
|
|
2814
3044
|
lines.push("");
|
|
2815
3045
|
lines.push(...formatAtlasRelation(relation));
|
|
2816
3046
|
}
|
|
3047
|
+
for (const event of [...document2.events].sort(compareIdLike)) {
|
|
3048
|
+
lines.push("");
|
|
3049
|
+
lines.push(...formatAtlasEvent(event));
|
|
3050
|
+
}
|
|
2817
3051
|
const sortedObjects = [...document2.objects].sort(compareObjects);
|
|
2818
3052
|
if (sortedObjects.length > 0 && lines.at(-1) !== "") {
|
|
2819
3053
|
lines.push("");
|
|
@@ -2844,6 +3078,10 @@ var WorldOrbit = (() => {
|
|
|
2844
3078
|
lines.push("");
|
|
2845
3079
|
lines.push(...formatAtlasRelation(relation));
|
|
2846
3080
|
}
|
|
3081
|
+
for (const event of [...legacy.events].sort(compareIdLike)) {
|
|
3082
|
+
lines.push("");
|
|
3083
|
+
lines.push(...formatAtlasEvent(event));
|
|
3084
|
+
}
|
|
2847
3085
|
const sortedObjects = [...legacy.objects].sort(compareObjects);
|
|
2848
3086
|
if (sortedObjects.length > 0 && lines.at(-1) !== "") {
|
|
2849
3087
|
lines.push("");
|
|
@@ -3055,6 +3293,9 @@ var WorldOrbit = (() => {
|
|
|
3055
3293
|
if (layerTokens.length > 0) {
|
|
3056
3294
|
lines.push(` layers ${layerTokens.join(" ")}`);
|
|
3057
3295
|
}
|
|
3296
|
+
if (viewpoint.events.length > 0) {
|
|
3297
|
+
lines.push(` events ${viewpoint.events.join(" ")}`);
|
|
3298
|
+
}
|
|
3058
3299
|
if (viewpoint.filter) {
|
|
3059
3300
|
lines.push(" filter");
|
|
3060
3301
|
if (viewpoint.filter.query) {
|
|
@@ -3127,6 +3368,54 @@ var WorldOrbit = (() => {
|
|
|
3127
3368
|
}
|
|
3128
3369
|
return lines;
|
|
3129
3370
|
}
|
|
3371
|
+
function formatAtlasEvent(event) {
|
|
3372
|
+
const lines = [`event ${event.id}`, ` kind ${quoteIfNeeded(event.kind)}`];
|
|
3373
|
+
if (event.label) {
|
|
3374
|
+
lines.push(` label ${quoteIfNeeded(event.label)}`);
|
|
3375
|
+
}
|
|
3376
|
+
if (event.summary) {
|
|
3377
|
+
lines.push(` summary ${quoteIfNeeded(event.summary)}`);
|
|
3378
|
+
}
|
|
3379
|
+
if (event.targetObjectId) {
|
|
3380
|
+
lines.push(` target ${event.targetObjectId}`);
|
|
3381
|
+
}
|
|
3382
|
+
if (event.participantObjectIds.length > 0) {
|
|
3383
|
+
lines.push(` participants ${event.participantObjectIds.join(" ")}`);
|
|
3384
|
+
}
|
|
3385
|
+
if (event.timing) {
|
|
3386
|
+
lines.push(` timing ${quoteIfNeeded(event.timing)}`);
|
|
3387
|
+
}
|
|
3388
|
+
if (event.visibility) {
|
|
3389
|
+
lines.push(` visibility ${quoteIfNeeded(event.visibility)}`);
|
|
3390
|
+
}
|
|
3391
|
+
if (event.tags.length > 0) {
|
|
3392
|
+
lines.push(` tags ${event.tags.map(quoteIfNeeded).join(" ")}`);
|
|
3393
|
+
}
|
|
3394
|
+
if (event.color) {
|
|
3395
|
+
lines.push(` color ${quoteIfNeeded(event.color)}`);
|
|
3396
|
+
}
|
|
3397
|
+
if (event.hidden) {
|
|
3398
|
+
lines.push(" hidden true");
|
|
3399
|
+
}
|
|
3400
|
+
if (event.positions.length > 0) {
|
|
3401
|
+
lines.push("");
|
|
3402
|
+
lines.push(" positions");
|
|
3403
|
+
for (const pose of [...event.positions].sort(comparePoseObjectId)) {
|
|
3404
|
+
lines.push(` pose ${pose.objectId}`);
|
|
3405
|
+
for (const fieldLine of formatEventPoseFields(pose)) {
|
|
3406
|
+
lines.push(` ${fieldLine}`);
|
|
3407
|
+
}
|
|
3408
|
+
}
|
|
3409
|
+
}
|
|
3410
|
+
return lines;
|
|
3411
|
+
}
|
|
3412
|
+
function formatEventPoseFields(pose) {
|
|
3413
|
+
return [
|
|
3414
|
+
...formatPlacement(pose.placement),
|
|
3415
|
+
...formatOptionalUnit("inner", pose.inner),
|
|
3416
|
+
...formatOptionalUnit("outer", pose.outer)
|
|
3417
|
+
];
|
|
3418
|
+
}
|
|
3130
3419
|
function formatValue(value) {
|
|
3131
3420
|
if (Array.isArray(value)) {
|
|
3132
3421
|
return value.map((item) => quoteIfNeeded(item)).join(" ");
|
|
@@ -3168,7 +3457,7 @@ var WorldOrbit = (() => {
|
|
|
3168
3457
|
if (orbitFront !== void 0 || orbitBack !== void 0) {
|
|
3169
3458
|
tokens.push(orbitFront !== false || orbitBack !== false ? "orbits" : "-orbits");
|
|
3170
3459
|
}
|
|
3171
|
-
for (const key of ["background", "guides", "relations", "objects", "labels", "metadata"]) {
|
|
3460
|
+
for (const key of ["background", "guides", "relations", "events", "objects", "labels", "metadata"]) {
|
|
3172
3461
|
if (layers[key] !== void 0) {
|
|
3173
3462
|
tokens.push(layers[key] ? key : `-${key}`);
|
|
3174
3463
|
}
|
|
@@ -3196,6 +3485,9 @@ var WorldOrbit = (() => {
|
|
|
3196
3485
|
function compareIdLike(left, right) {
|
|
3197
3486
|
return left.id.localeCompare(right.id);
|
|
3198
3487
|
}
|
|
3488
|
+
function comparePoseObjectId(left, right) {
|
|
3489
|
+
return left.objectId.localeCompare(right.objectId);
|
|
3490
|
+
}
|
|
3199
3491
|
function objectTypeIndex(objectType) {
|
|
3200
3492
|
switch (objectType) {
|
|
3201
3493
|
case "star":
|
|
@@ -3391,6 +3683,7 @@ var WorldOrbit = (() => {
|
|
|
3391
3683
|
const diagnostics = [];
|
|
3392
3684
|
const objectMap = new Map(document2.objects.map((object) => [object.id, object]));
|
|
3393
3685
|
const groupIds = new Set(document2.groups.map((group) => group.id));
|
|
3686
|
+
const eventIds = new Set(document2.events.map((event) => event.id));
|
|
3394
3687
|
if (!document2.system) {
|
|
3395
3688
|
diagnostics.push(error("validate.system.required", "Atlas documents must declare exactly one system."));
|
|
3396
3689
|
}
|
|
@@ -3400,6 +3693,7 @@ var WorldOrbit = (() => {
|
|
|
3400
3693
|
["viewpoint", document2.system?.viewpoints.map((viewpoint) => viewpoint.id) ?? []],
|
|
3401
3694
|
["annotation", document2.system?.annotations.map((annotation) => annotation.id) ?? []],
|
|
3402
3695
|
["relation", document2.relations.map((relation) => relation.id)],
|
|
3696
|
+
["event", document2.events.map((event) => event.id)],
|
|
3403
3697
|
["object", document2.objects.map((object) => object.id)]
|
|
3404
3698
|
]) {
|
|
3405
3699
|
for (const id of ids) {
|
|
@@ -3415,11 +3709,14 @@ var WorldOrbit = (() => {
|
|
|
3415
3709
|
validateRelation(relation, objectMap, diagnostics);
|
|
3416
3710
|
}
|
|
3417
3711
|
for (const viewpoint of document2.system?.viewpoints ?? []) {
|
|
3418
|
-
|
|
3712
|
+
validateViewpoint(viewpoint.filter, viewpoint.events ?? [], groupIds, eventIds, sourceSchemaVersion, diagnostics, viewpoint.id);
|
|
3419
3713
|
}
|
|
3420
3714
|
for (const object of document2.objects) {
|
|
3421
3715
|
validateObject(object, document2.system, objectMap, groupIds, diagnostics);
|
|
3422
3716
|
}
|
|
3717
|
+
for (const event of document2.events) {
|
|
3718
|
+
validateEvent(event, objectMap, diagnostics);
|
|
3719
|
+
}
|
|
3423
3720
|
return diagnostics;
|
|
3424
3721
|
}
|
|
3425
3722
|
function validateRelation(relation, objectMap, diagnostics) {
|
|
@@ -3437,13 +3734,19 @@ var WorldOrbit = (() => {
|
|
|
3437
3734
|
diagnostics.push(error("validate.relation.kind.required", `Relation "${relation.id}" is missing a "kind" value.`));
|
|
3438
3735
|
}
|
|
3439
3736
|
}
|
|
3440
|
-
function
|
|
3441
|
-
if (
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3737
|
+
function validateViewpoint(filter, eventRefs, groupIds, eventIds, sourceSchemaVersion, diagnostics, viewpointId) {
|
|
3738
|
+
if (sourceSchemaVersion === "2.1") {
|
|
3739
|
+
if (filter) {
|
|
3740
|
+
for (const groupId of filter.groupIds) {
|
|
3741
|
+
if (!groupIds.has(groupId)) {
|
|
3742
|
+
diagnostics.push(warn("validate.viewpoint.group.unknown", `Unknown group "${groupId}" in viewpoint "${viewpointId}".`, void 0, `viewpoint.${viewpointId}.groups`));
|
|
3743
|
+
}
|
|
3744
|
+
}
|
|
3745
|
+
}
|
|
3746
|
+
for (const eventId of eventRefs) {
|
|
3747
|
+
if (!eventIds.has(eventId)) {
|
|
3748
|
+
diagnostics.push(warn("validate.viewpoint.event.unknown", `Unknown event "${eventId}" in viewpoint "${viewpointId}".`, void 0, `viewpoint.${viewpointId}.events`));
|
|
3749
|
+
}
|
|
3447
3750
|
}
|
|
3448
3751
|
}
|
|
3449
3752
|
}
|
|
@@ -3529,6 +3832,103 @@ var WorldOrbit = (() => {
|
|
|
3529
3832
|
}
|
|
3530
3833
|
}
|
|
3531
3834
|
}
|
|
3835
|
+
function validateEvent(event, objectMap, diagnostics) {
|
|
3836
|
+
const fieldPrefix = `event.${event.id}`;
|
|
3837
|
+
const referencedIds = /* @__PURE__ */ new Set();
|
|
3838
|
+
if (!event.kind.trim()) {
|
|
3839
|
+
diagnostics.push(error("validate.event.kind.required", `Event "${event.id}" is missing a "kind" value.`, void 0, `${fieldPrefix}.kind`));
|
|
3840
|
+
}
|
|
3841
|
+
if (!event.targetObjectId && event.participantObjectIds.length === 0) {
|
|
3842
|
+
diagnostics.push(error("validate.event.references.required", `Event "${event.id}" must define a "target" or at least one participant.`, void 0, `${fieldPrefix}.participants`));
|
|
3843
|
+
}
|
|
3844
|
+
if (event.targetObjectId) {
|
|
3845
|
+
referencedIds.add(event.targetObjectId);
|
|
3846
|
+
if (!objectMap.has(event.targetObjectId)) {
|
|
3847
|
+
diagnostics.push(error("validate.event.target.unknown", `Unknown event target "${event.targetObjectId}" on "${event.id}".`, void 0, `${fieldPrefix}.target`));
|
|
3848
|
+
}
|
|
3849
|
+
}
|
|
3850
|
+
const seenParticipants = /* @__PURE__ */ new Set();
|
|
3851
|
+
for (const participantId of event.participantObjectIds) {
|
|
3852
|
+
referencedIds.add(participantId);
|
|
3853
|
+
if (seenParticipants.has(participantId)) {
|
|
3854
|
+
diagnostics.push(warn("validate.event.participants.duplicate", `Event "${event.id}" repeats participant "${participantId}".`, void 0, `${fieldPrefix}.participants`));
|
|
3855
|
+
continue;
|
|
3856
|
+
}
|
|
3857
|
+
seenParticipants.add(participantId);
|
|
3858
|
+
if (!objectMap.has(participantId)) {
|
|
3859
|
+
diagnostics.push(error("validate.event.participants.unknown", `Unknown event participant "${participantId}" on "${event.id}".`, void 0, `${fieldPrefix}.participants`));
|
|
3860
|
+
}
|
|
3861
|
+
}
|
|
3862
|
+
if (event.targetObjectId && event.participantObjectIds.length > 0 && !event.participantObjectIds.includes(event.targetObjectId)) {
|
|
3863
|
+
diagnostics.push(warn("validate.event.target.notParticipant", `Event "${event.id}" defines a target outside its participants list.`, void 0, `${fieldPrefix}.target`));
|
|
3864
|
+
}
|
|
3865
|
+
if (event.positions.length === 0) {
|
|
3866
|
+
diagnostics.push(warn("validate.event.positions.missing", `Event "${event.id}" has no positions block and cannot drive a scene snapshot.`, void 0, `${fieldPrefix}.positions`));
|
|
3867
|
+
}
|
|
3868
|
+
if (/(?:^|[-_])(solar-eclipse|lunar-eclipse|transit|occultation)(?:$|[-_])/.test(event.kind) && referencedIds.size < 3) {
|
|
3869
|
+
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`));
|
|
3870
|
+
}
|
|
3871
|
+
const poseIds = /* @__PURE__ */ new Set();
|
|
3872
|
+
for (const pose of event.positions) {
|
|
3873
|
+
const poseFieldPrefix = `${fieldPrefix}.pose.${pose.objectId}`;
|
|
3874
|
+
if (poseIds.has(pose.objectId)) {
|
|
3875
|
+
diagnostics.push(error("validate.event.pose.duplicate", `Event "${event.id}" defines "${pose.objectId}" more than once in positions.`, void 0, poseFieldPrefix));
|
|
3876
|
+
continue;
|
|
3877
|
+
}
|
|
3878
|
+
poseIds.add(pose.objectId);
|
|
3879
|
+
const object = objectMap.get(pose.objectId);
|
|
3880
|
+
if (!object) {
|
|
3881
|
+
diagnostics.push(error("validate.event.pose.object.unknown", `Unknown event pose object "${pose.objectId}" on "${event.id}".`, void 0, poseFieldPrefix));
|
|
3882
|
+
continue;
|
|
3883
|
+
}
|
|
3884
|
+
if (!referencedIds.has(pose.objectId)) {
|
|
3885
|
+
diagnostics.push(warn("validate.event.pose.unreferenced", `Event pose "${pose.objectId}" on "${event.id}" is not listed in target/participants.`, void 0, poseFieldPrefix));
|
|
3886
|
+
}
|
|
3887
|
+
validateEventPose(pose, object, objectMap, diagnostics, poseFieldPrefix, event.id);
|
|
3888
|
+
}
|
|
3889
|
+
}
|
|
3890
|
+
function validateEventPose(pose, object, objectMap, diagnostics, fieldPrefix, eventId) {
|
|
3891
|
+
const placement = pose.placement;
|
|
3892
|
+
if (!placement) {
|
|
3893
|
+
diagnostics.push(error("validate.event.pose.placement.required", `Event "${eventId}" pose "${pose.objectId}" is missing a placement mode.`, void 0, fieldPrefix));
|
|
3894
|
+
return;
|
|
3895
|
+
}
|
|
3896
|
+
if (placement.mode === "orbit") {
|
|
3897
|
+
if (!objectMap.has(placement.target)) {
|
|
3898
|
+
diagnostics.push(error("validate.event.pose.orbit.target.unknown", `Unknown event orbit target "${placement.target}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.orbit`));
|
|
3899
|
+
}
|
|
3900
|
+
if (placement.distance && placement.semiMajor) {
|
|
3901
|
+
diagnostics.push(error("validate.event.pose.orbit.distanceConflict", `Event "${eventId}" pose "${pose.objectId}" cannot declare both "distance" and "semiMajor".`, void 0, `${fieldPrefix}.distance`));
|
|
3902
|
+
}
|
|
3903
|
+
return;
|
|
3904
|
+
}
|
|
3905
|
+
if (placement.mode === "surface") {
|
|
3906
|
+
const target = objectMap.get(placement.target);
|
|
3907
|
+
if (!target) {
|
|
3908
|
+
diagnostics.push(error("validate.event.pose.surface.target.unknown", `Unknown event surface target "${placement.target}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.surface`));
|
|
3909
|
+
} else if (!SURFACE_TARGET_TYPES2.has(target.type)) {
|
|
3910
|
+
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`));
|
|
3911
|
+
}
|
|
3912
|
+
return;
|
|
3913
|
+
}
|
|
3914
|
+
if (placement.mode === "at") {
|
|
3915
|
+
if (object.type !== "structure" && object.type !== "phenomenon") {
|
|
3916
|
+
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`));
|
|
3917
|
+
}
|
|
3918
|
+
const reference = placement.reference;
|
|
3919
|
+
if (reference.kind === "named" && !objectMap.has(reference.name)) {
|
|
3920
|
+
diagnostics.push(error("validate.event.pose.at.target.unknown", `Unknown event at-reference target "${placement.target}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.at`));
|
|
3921
|
+
} else if (reference.kind === "anchor" && !objectMap.has(reference.objectId)) {
|
|
3922
|
+
diagnostics.push(error("validate.event.pose.anchor.target.unknown", `Unknown event anchor target "${reference.objectId}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.at`));
|
|
3923
|
+
} else if (reference.kind === "lagrange") {
|
|
3924
|
+
if (!objectMap.has(reference.primary)) {
|
|
3925
|
+
diagnostics.push(error("validate.event.pose.lagrange.primary.unknown", `Unknown event Lagrange target "${reference.primary}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.at`));
|
|
3926
|
+
} else if (reference.secondary && !objectMap.has(reference.secondary)) {
|
|
3927
|
+
diagnostics.push(error("validate.event.pose.lagrange.secondary.unknown", `Unknown event Lagrange target "${reference.secondary}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.at`));
|
|
3928
|
+
}
|
|
3929
|
+
}
|
|
3930
|
+
}
|
|
3931
|
+
}
|
|
3532
3932
|
function validateAtTarget(object, objectMap, diagnostics) {
|
|
3533
3933
|
const reference = object.placement?.mode === "at" ? object.placement.reference : null;
|
|
3534
3934
|
if (!reference) {
|
|
@@ -3729,6 +4129,21 @@ var WorldOrbit = (() => {
|
|
|
3729
4129
|
});
|
|
3730
4130
|
}
|
|
3731
4131
|
var DRAFT_OBJECT_FIELD_KEYS = new Set(DRAFT_OBJECT_FIELD_SPECS.keys());
|
|
4132
|
+
var EVENT_POSE_FIELD_KEYS = /* @__PURE__ */ new Set([
|
|
4133
|
+
"orbit",
|
|
4134
|
+
"distance",
|
|
4135
|
+
"semiMajor",
|
|
4136
|
+
"eccentricity",
|
|
4137
|
+
"period",
|
|
4138
|
+
"angle",
|
|
4139
|
+
"inclination",
|
|
4140
|
+
"phase",
|
|
4141
|
+
"at",
|
|
4142
|
+
"surface",
|
|
4143
|
+
"free",
|
|
4144
|
+
"inner",
|
|
4145
|
+
"outer"
|
|
4146
|
+
]);
|
|
3732
4147
|
function parseWorldOrbitAtlas(source) {
|
|
3733
4148
|
return parseAtlasSource(source);
|
|
3734
4149
|
}
|
|
@@ -3743,12 +4158,15 @@ var WorldOrbit = (() => {
|
|
|
3743
4158
|
const objectNodes = [];
|
|
3744
4159
|
const groups = [];
|
|
3745
4160
|
const relations = [];
|
|
4161
|
+
const events = [];
|
|
4162
|
+
const eventPoseNodes = /* @__PURE__ */ new Map();
|
|
3746
4163
|
let sawDefaults = false;
|
|
3747
4164
|
let sawAtlas = false;
|
|
3748
4165
|
const viewpointIds = /* @__PURE__ */ new Set();
|
|
3749
4166
|
const annotationIds = /* @__PURE__ */ new Set();
|
|
3750
4167
|
const groupIds = /* @__PURE__ */ new Set();
|
|
3751
4168
|
const relationIds = /* @__PURE__ */ new Set();
|
|
4169
|
+
const eventIds = /* @__PURE__ */ new Set();
|
|
3752
4170
|
for (let index = 0; index < lines.length; index++) {
|
|
3753
4171
|
const rawLine = lines[index];
|
|
3754
4172
|
const lineNumber = index + 1;
|
|
@@ -3779,7 +4197,7 @@ var WorldOrbit = (() => {
|
|
|
3779
4197
|
continue;
|
|
3780
4198
|
}
|
|
3781
4199
|
if (indent === 0) {
|
|
3782
|
-
section = startTopLevelSection(tokens, lineNumber, sourceSchemaVersion, diagnostics, system, objectNodes, groups, relations, viewpointIds, annotationIds, groupIds, relationIds, { sawDefaults, sawAtlas });
|
|
4200
|
+
section = startTopLevelSection(tokens, lineNumber, sourceSchemaVersion, diagnostics, system, objectNodes, groups, relations, events, eventPoseNodes, viewpointIds, annotationIds, groupIds, relationIds, eventIds, { sawDefaults, sawAtlas });
|
|
3783
4201
|
if (section.kind === "system") {
|
|
3784
4202
|
system = section.system;
|
|
3785
4203
|
} else if (section.kind === "defaults") {
|
|
@@ -3798,6 +4216,7 @@ var WorldOrbit = (() => {
|
|
|
3798
4216
|
throw new WorldOrbitError('Missing required atlas schema header "schema 2.0"');
|
|
3799
4217
|
}
|
|
3800
4218
|
const objects = objectNodes.map((node) => normalizeDraftObject(node, sourceSchemaVersion, diagnostics));
|
|
4219
|
+
const normalizedEvents = events.map((event) => normalizeDraftEvent(event, eventPoseNodes.get(event.id) ?? []));
|
|
3801
4220
|
const outputVersion = forcedOutputVersion ?? (sourceSchemaVersion === "2.0-draft" ? "2.0" : sourceSchemaVersion);
|
|
3802
4221
|
const baseDocument = {
|
|
3803
4222
|
format: "worldorbit",
|
|
@@ -3805,6 +4224,7 @@ var WorldOrbit = (() => {
|
|
|
3805
4224
|
system,
|
|
3806
4225
|
groups,
|
|
3807
4226
|
relations,
|
|
4227
|
+
events: normalizedEvents,
|
|
3808
4228
|
objects,
|
|
3809
4229
|
diagnostics
|
|
3810
4230
|
};
|
|
@@ -3840,7 +4260,7 @@ var WorldOrbit = (() => {
|
|
|
3840
4260
|
const version = tokens[1].value.toLowerCase();
|
|
3841
4261
|
return version === "2.1" ? "2.1" : version === "2.0-draft" ? "2.0-draft" : "2.0";
|
|
3842
4262
|
}
|
|
3843
|
-
function startTopLevelSection(tokens, line, sourceSchemaVersion, diagnostics, system, objectNodes, groups, relations, viewpointIds, annotationIds, groupIds, relationIds, flags) {
|
|
4263
|
+
function startTopLevelSection(tokens, line, sourceSchemaVersion, diagnostics, system, objectNodes, groups, relations, events, eventPoseNodes, viewpointIds, annotationIds, groupIds, relationIds, eventIds, flags) {
|
|
3844
4264
|
const keyword = tokens[0]?.value.toLowerCase();
|
|
3845
4265
|
switch (keyword) {
|
|
3846
4266
|
case "system":
|
|
@@ -3877,7 +4297,7 @@ var WorldOrbit = (() => {
|
|
|
3877
4297
|
if (!system) {
|
|
3878
4298
|
throw new WorldOrbitError('Atlas section "viewpoint" requires a preceding system declaration', line, tokens[0].column);
|
|
3879
4299
|
}
|
|
3880
|
-
return startViewpointSection(tokens, line, system, viewpointIds);
|
|
4300
|
+
return startViewpointSection(tokens, line, system, viewpointIds, sourceSchemaVersion, diagnostics);
|
|
3881
4301
|
case "annotation":
|
|
3882
4302
|
if (!system) {
|
|
3883
4303
|
throw new WorldOrbitError('Atlas section "annotation" requires a preceding system declaration', line, tokens[0].column);
|
|
@@ -3889,6 +4309,9 @@ var WorldOrbit = (() => {
|
|
|
3889
4309
|
case "relation":
|
|
3890
4310
|
warnIfSchema21Feature(sourceSchemaVersion, diagnostics, "relation", { line, column: tokens[0].column });
|
|
3891
4311
|
return startRelationSection(tokens, line, relations, relationIds);
|
|
4312
|
+
case "event":
|
|
4313
|
+
warnIfSchema21Feature(sourceSchemaVersion, diagnostics, "event", { line, column: tokens[0].column });
|
|
4314
|
+
return startEventSection(tokens, line, events, eventPoseNodes, eventIds, sourceSchemaVersion, diagnostics);
|
|
3892
4315
|
case "object":
|
|
3893
4316
|
return startObjectSection(tokens, line, sourceSchemaVersion, diagnostics, objectNodes);
|
|
3894
4317
|
default:
|
|
@@ -3925,7 +4348,7 @@ var WorldOrbit = (() => {
|
|
|
3925
4348
|
seenFields: /* @__PURE__ */ new Set()
|
|
3926
4349
|
};
|
|
3927
4350
|
}
|
|
3928
|
-
function startViewpointSection(tokens, line, system, viewpointIds) {
|
|
4351
|
+
function startViewpointSection(tokens, line, system, viewpointIds, sourceSchemaVersion, diagnostics) {
|
|
3929
4352
|
if (tokens.length !== 2) {
|
|
3930
4353
|
throw new WorldOrbitError("Invalid viewpoint declaration", line, tokens[0]?.column ?? 1);
|
|
3931
4354
|
}
|
|
@@ -3942,6 +4365,7 @@ var WorldOrbit = (() => {
|
|
|
3942
4365
|
summary: "",
|
|
3943
4366
|
focusObjectId: null,
|
|
3944
4367
|
selectedObjectId: null,
|
|
4368
|
+
events: [],
|
|
3945
4369
|
projection: system.defaults.view,
|
|
3946
4370
|
preset: system.defaults.preset,
|
|
3947
4371
|
zoom: null,
|
|
@@ -3954,6 +4378,8 @@ var WorldOrbit = (() => {
|
|
|
3954
4378
|
return {
|
|
3955
4379
|
kind: "viewpoint",
|
|
3956
4380
|
viewpoint,
|
|
4381
|
+
sourceSchemaVersion,
|
|
4382
|
+
diagnostics,
|
|
3957
4383
|
seenFields: /* @__PURE__ */ new Set(),
|
|
3958
4384
|
inFilter: false,
|
|
3959
4385
|
filterIndent: null,
|
|
@@ -4044,6 +4470,49 @@ var WorldOrbit = (() => {
|
|
|
4044
4470
|
seenFields: /* @__PURE__ */ new Set()
|
|
4045
4471
|
};
|
|
4046
4472
|
}
|
|
4473
|
+
function startEventSection(tokens, line, events, eventPoseNodes, eventIds, sourceSchemaVersion, diagnostics) {
|
|
4474
|
+
if (tokens.length !== 2) {
|
|
4475
|
+
throw new WorldOrbitError("Invalid event declaration", line, tokens[0]?.column ?? 1);
|
|
4476
|
+
}
|
|
4477
|
+
const id = normalizeIdentifier2(tokens[1].value);
|
|
4478
|
+
if (!id) {
|
|
4479
|
+
throw new WorldOrbitError("Event id must not be empty", line, tokens[1].column);
|
|
4480
|
+
}
|
|
4481
|
+
if (eventIds.has(id)) {
|
|
4482
|
+
throw new WorldOrbitError(`Duplicate event id "${id}"`, line, tokens[1].column);
|
|
4483
|
+
}
|
|
4484
|
+
const event = {
|
|
4485
|
+
id,
|
|
4486
|
+
kind: "",
|
|
4487
|
+
label: humanizeIdentifier3(id),
|
|
4488
|
+
summary: null,
|
|
4489
|
+
targetObjectId: null,
|
|
4490
|
+
participantObjectIds: [],
|
|
4491
|
+
timing: null,
|
|
4492
|
+
visibility: null,
|
|
4493
|
+
tags: [],
|
|
4494
|
+
color: null,
|
|
4495
|
+
hidden: false,
|
|
4496
|
+
positions: []
|
|
4497
|
+
};
|
|
4498
|
+
const rawPoses = [];
|
|
4499
|
+
events.push(event);
|
|
4500
|
+
eventPoseNodes.set(id, rawPoses);
|
|
4501
|
+
eventIds.add(id);
|
|
4502
|
+
return {
|
|
4503
|
+
kind: "event",
|
|
4504
|
+
event,
|
|
4505
|
+
sourceSchemaVersion,
|
|
4506
|
+
diagnostics,
|
|
4507
|
+
seenFields: /* @__PURE__ */ new Set(),
|
|
4508
|
+
rawPoses,
|
|
4509
|
+
inPositions: false,
|
|
4510
|
+
positionsIndent: null,
|
|
4511
|
+
activePose: null,
|
|
4512
|
+
poseIndent: null,
|
|
4513
|
+
activePoseSeenFields: /* @__PURE__ */ new Set()
|
|
4514
|
+
};
|
|
4515
|
+
}
|
|
4047
4516
|
function startObjectSection(tokens, line, sourceSchemaVersion, diagnostics, objectNodes) {
|
|
4048
4517
|
if (tokens.length < 3) {
|
|
4049
4518
|
throw new WorldOrbitError("Invalid atlas object declaration", line, tokens[0]?.column ?? 1);
|
|
@@ -4100,6 +4569,9 @@ var WorldOrbit = (() => {
|
|
|
4100
4569
|
case "relation":
|
|
4101
4570
|
applyRelationField(section, tokens, line);
|
|
4102
4571
|
return;
|
|
4572
|
+
case "event":
|
|
4573
|
+
applyEventField(section, indent, tokens, line);
|
|
4574
|
+
return;
|
|
4103
4575
|
case "object":
|
|
4104
4576
|
applyObjectField(section, indent, tokens, line);
|
|
4105
4577
|
return;
|
|
@@ -4226,7 +4698,14 @@ var WorldOrbit = (() => {
|
|
|
4226
4698
|
section.viewpoint.rotationDeg = parseFiniteNumber2(value, line, tokens[0].column, "rotation");
|
|
4227
4699
|
return;
|
|
4228
4700
|
case "layers":
|
|
4229
|
-
section.viewpoint.layers = parseLayerTokens(tokens.slice(1), line);
|
|
4701
|
+
section.viewpoint.layers = parseLayerTokens(tokens.slice(1), line, section.sourceSchemaVersion, section.diagnostics);
|
|
4702
|
+
return;
|
|
4703
|
+
case "events":
|
|
4704
|
+
warnIfSchema21Feature(section.sourceSchemaVersion, section.diagnostics, "viewpoint.events", {
|
|
4705
|
+
line,
|
|
4706
|
+
column: tokens[0].column
|
|
4707
|
+
});
|
|
4708
|
+
section.viewpoint.events = parseTokenList(tokens.slice(1), line, "events");
|
|
4230
4709
|
return;
|
|
4231
4710
|
default:
|
|
4232
4711
|
throw new WorldOrbitError(`Unknown viewpoint field "${tokens[0].value}"`, line, tokens[0].column);
|
|
@@ -4331,6 +4810,106 @@ var WorldOrbit = (() => {
|
|
|
4331
4810
|
throw new WorldOrbitError(`Unknown relation field "${tokens[0].value}"`, line, tokens[0].column);
|
|
4332
4811
|
}
|
|
4333
4812
|
}
|
|
4813
|
+
function applyEventField(section, indent, tokens, line) {
|
|
4814
|
+
if (section.activePose && indent <= (section.poseIndent ?? 0)) {
|
|
4815
|
+
section.activePose = null;
|
|
4816
|
+
section.poseIndent = null;
|
|
4817
|
+
section.activePoseSeenFields.clear();
|
|
4818
|
+
}
|
|
4819
|
+
if (!section.activePose && section.inPositions && indent <= (section.positionsIndent ?? 0)) {
|
|
4820
|
+
section.inPositions = false;
|
|
4821
|
+
section.positionsIndent = null;
|
|
4822
|
+
}
|
|
4823
|
+
if (section.activePose) {
|
|
4824
|
+
section.activePose.fields.push(parseEventPoseField(tokens, line, section.activePoseSeenFields));
|
|
4825
|
+
return;
|
|
4826
|
+
}
|
|
4827
|
+
if (section.inPositions) {
|
|
4828
|
+
if (tokens.length !== 2 || tokens[0].value.toLowerCase() !== "pose") {
|
|
4829
|
+
throw new WorldOrbitError(`Unknown event positions field "${tokens[0].value}"`, line, tokens[0]?.column ?? 1);
|
|
4830
|
+
}
|
|
4831
|
+
const objectId = tokens[1].value;
|
|
4832
|
+
if (!objectId.trim()) {
|
|
4833
|
+
throw new WorldOrbitError("Event pose object id must not be empty", line, tokens[1].column);
|
|
4834
|
+
}
|
|
4835
|
+
const rawPose = {
|
|
4836
|
+
objectId,
|
|
4837
|
+
fields: [],
|
|
4838
|
+
location: { line, column: tokens[0].column }
|
|
4839
|
+
};
|
|
4840
|
+
section.rawPoses.push(rawPose);
|
|
4841
|
+
section.activePose = rawPose;
|
|
4842
|
+
section.poseIndent = indent;
|
|
4843
|
+
section.activePoseSeenFields = /* @__PURE__ */ new Set();
|
|
4844
|
+
return;
|
|
4845
|
+
}
|
|
4846
|
+
if (tokens.length === 1 && tokens[0].value.toLowerCase() === "positions") {
|
|
4847
|
+
if (section.seenFields.has("positions")) {
|
|
4848
|
+
throw new WorldOrbitError('Duplicate event field "positions"', line, tokens[0].column);
|
|
4849
|
+
}
|
|
4850
|
+
section.seenFields.add("positions");
|
|
4851
|
+
section.inPositions = true;
|
|
4852
|
+
section.positionsIndent = indent;
|
|
4853
|
+
return;
|
|
4854
|
+
}
|
|
4855
|
+
const key = requireUniqueField(tokens, section.seenFields, line);
|
|
4856
|
+
switch (key) {
|
|
4857
|
+
case "kind":
|
|
4858
|
+
section.event.kind = joinFieldValue(tokens, line);
|
|
4859
|
+
return;
|
|
4860
|
+
case "label":
|
|
4861
|
+
section.event.label = joinFieldValue(tokens, line);
|
|
4862
|
+
return;
|
|
4863
|
+
case "summary":
|
|
4864
|
+
section.event.summary = joinFieldValue(tokens, line);
|
|
4865
|
+
return;
|
|
4866
|
+
case "target":
|
|
4867
|
+
section.event.targetObjectId = joinFieldValue(tokens, line);
|
|
4868
|
+
return;
|
|
4869
|
+
case "participants":
|
|
4870
|
+
section.event.participantObjectIds = parseTokenList(tokens.slice(1), line, "participants");
|
|
4871
|
+
return;
|
|
4872
|
+
case "timing":
|
|
4873
|
+
section.event.timing = joinFieldValue(tokens, line);
|
|
4874
|
+
return;
|
|
4875
|
+
case "visibility":
|
|
4876
|
+
section.event.visibility = joinFieldValue(tokens, line);
|
|
4877
|
+
return;
|
|
4878
|
+
case "tags":
|
|
4879
|
+
section.event.tags = parseTokenList(tokens.slice(1), line, "tags");
|
|
4880
|
+
return;
|
|
4881
|
+
case "color":
|
|
4882
|
+
section.event.color = joinFieldValue(tokens, line);
|
|
4883
|
+
return;
|
|
4884
|
+
case "hidden":
|
|
4885
|
+
section.event.hidden = parseAtlasBoolean(joinFieldValue(tokens, line), "hidden", {
|
|
4886
|
+
line,
|
|
4887
|
+
column: tokens[0].column
|
|
4888
|
+
});
|
|
4889
|
+
return;
|
|
4890
|
+
default:
|
|
4891
|
+
throw new WorldOrbitError(`Unknown event field "${tokens[0].value}"`, line, tokens[0].column);
|
|
4892
|
+
}
|
|
4893
|
+
}
|
|
4894
|
+
function parseEventPoseField(tokens, line, seenFields) {
|
|
4895
|
+
if (tokens.length < 2) {
|
|
4896
|
+
throw new WorldOrbitError("Invalid event pose field line", line, tokens[0]?.column ?? 1);
|
|
4897
|
+
}
|
|
4898
|
+
const key = tokens[0].value;
|
|
4899
|
+
if (!EVENT_POSE_FIELD_KEYS.has(key)) {
|
|
4900
|
+
throw new WorldOrbitError(`Unknown event pose field "${key}"`, line, tokens[0].column);
|
|
4901
|
+
}
|
|
4902
|
+
if (seenFields.has(key)) {
|
|
4903
|
+
throw new WorldOrbitError(`Duplicate event pose field "${key}"`, line, tokens[0].column);
|
|
4904
|
+
}
|
|
4905
|
+
seenFields.add(key);
|
|
4906
|
+
return {
|
|
4907
|
+
type: "field",
|
|
4908
|
+
key,
|
|
4909
|
+
values: tokens.slice(1).map((token) => token.value),
|
|
4910
|
+
location: { line, column: tokens[0].column }
|
|
4911
|
+
};
|
|
4912
|
+
}
|
|
4334
4913
|
function applyObjectField(section, indent, tokens, line) {
|
|
4335
4914
|
if (section.activeBlock && indent <= (section.blockIndent ?? 0)) {
|
|
4336
4915
|
section.activeBlock = null;
|
|
@@ -4389,7 +4968,7 @@ var WorldOrbit = (() => {
|
|
|
4389
4968
|
function parseObjectTypeTokens(tokens, line) {
|
|
4390
4969
|
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");
|
|
4391
4970
|
}
|
|
4392
|
-
function parseLayerTokens(tokens, line) {
|
|
4971
|
+
function parseLayerTokens(tokens, line, sourceSchemaVersion, diagnostics) {
|
|
4393
4972
|
const layers = {};
|
|
4394
4973
|
for (const token of parseTokenList(tokens, line, "layers")) {
|
|
4395
4974
|
const enabled = !token.startsWith("-") && !token.startsWith("!");
|
|
@@ -4399,7 +4978,13 @@ var WorldOrbit = (() => {
|
|
|
4399
4978
|
layers["orbits-front"] = enabled;
|
|
4400
4979
|
continue;
|
|
4401
4980
|
}
|
|
4402
|
-
if (raw === "background" || raw === "guides" || raw === "orbits-back" || raw === "orbits-front" || raw === "relations" || raw === "objects" || raw === "labels" || raw === "metadata") {
|
|
4981
|
+
if (raw === "background" || raw === "guides" || raw === "orbits-back" || raw === "orbits-front" || raw === "relations" || raw === "events" || raw === "objects" || raw === "labels" || raw === "metadata") {
|
|
4982
|
+
if (raw === "events" && sourceSchemaVersion && diagnostics) {
|
|
4983
|
+
warnIfSchema21Feature(sourceSchemaVersion, diagnostics, "layers.events", {
|
|
4984
|
+
line,
|
|
4985
|
+
column: tokens[0]?.column ?? 1
|
|
4986
|
+
});
|
|
4987
|
+
}
|
|
4403
4988
|
layers[raw] = enabled;
|
|
4404
4989
|
}
|
|
4405
4990
|
}
|
|
@@ -4538,7 +5123,7 @@ var WorldOrbit = (() => {
|
|
|
4538
5123
|
}
|
|
4539
5124
|
function normalizeDraftObject(node, sourceSchemaVersion, diagnostics) {
|
|
4540
5125
|
const fieldMap = collectDraftFields(node.fields);
|
|
4541
|
-
const placement =
|
|
5126
|
+
const placement = extractPlacementFromFieldMap(fieldMap);
|
|
4542
5127
|
const properties = normalizeDraftProperties(node.objectType, fieldMap);
|
|
4543
5128
|
const groups = parseOptionalTokenList(fieldMap.get("groups")?.[0]);
|
|
4544
5129
|
const epoch = parseOptionalJoinedValue(fieldMap.get("epoch")?.[0]);
|
|
@@ -4590,6 +5175,24 @@ var WorldOrbit = (() => {
|
|
|
4590
5175
|
}
|
|
4591
5176
|
return object;
|
|
4592
5177
|
}
|
|
5178
|
+
function normalizeDraftEvent(event, rawPoses) {
|
|
5179
|
+
return {
|
|
5180
|
+
...event,
|
|
5181
|
+
participantObjectIds: [...new Set(event.participantObjectIds)],
|
|
5182
|
+
tags: [...new Set(event.tags)],
|
|
5183
|
+
positions: rawPoses.map((pose) => normalizeDraftEventPose(pose))
|
|
5184
|
+
};
|
|
5185
|
+
}
|
|
5186
|
+
function normalizeDraftEventPose(rawPose) {
|
|
5187
|
+
const fieldMap = collectDraftFields(rawPose.fields);
|
|
5188
|
+
const placement = extractPlacementFromFieldMap(fieldMap);
|
|
5189
|
+
return {
|
|
5190
|
+
objectId: rawPose.objectId,
|
|
5191
|
+
placement,
|
|
5192
|
+
inner: parseOptionalUnitField(fieldMap.get("inner")?.[0], "inner"),
|
|
5193
|
+
outer: parseOptionalUnitField(fieldMap.get("outer")?.[0], "outer")
|
|
5194
|
+
};
|
|
5195
|
+
}
|
|
4593
5196
|
function collectDraftFields(fields) {
|
|
4594
5197
|
const grouped = /* @__PURE__ */ new Map();
|
|
4595
5198
|
for (const field of fields) {
|
|
@@ -4606,7 +5209,7 @@ var WorldOrbit = (() => {
|
|
|
4606
5209
|
}
|
|
4607
5210
|
return grouped;
|
|
4608
5211
|
}
|
|
4609
|
-
function
|
|
5212
|
+
function extractPlacementFromFieldMap(fieldMap) {
|
|
4610
5213
|
const orbitField = fieldMap.get("orbit")?.[0];
|
|
4611
5214
|
const atField = fieldMap.get("at")?.[0];
|
|
4612
5215
|
const surfaceField = fieldMap.get("surface")?.[0];
|
|
@@ -4899,6 +5502,7 @@ var WorldOrbit = (() => {
|
|
|
4899
5502
|
},
|
|
4900
5503
|
groups: [],
|
|
4901
5504
|
relations: [],
|
|
5505
|
+
events: [],
|
|
4902
5506
|
objects: [],
|
|
4903
5507
|
diagnostics: []
|
|
4904
5508
|
};
|
|
@@ -4916,6 +5520,10 @@ var WorldOrbit = (() => {
|
|
|
4916
5520
|
return path.key ? document2.system?.atlasMetadata[path.key] ?? null : null;
|
|
4917
5521
|
case "group":
|
|
4918
5522
|
return path.id ? findGroup(document2, path.id) : null;
|
|
5523
|
+
case "event":
|
|
5524
|
+
return path.id ? findEvent(document2, path.id) : null;
|
|
5525
|
+
case "event-pose":
|
|
5526
|
+
return path.id && path.key ? findEventPose(document2, path.id, path.key) : null;
|
|
4919
5527
|
case "object":
|
|
4920
5528
|
return path.id ? findObject(document2, path.id) : null;
|
|
4921
5529
|
case "viewpoint":
|
|
@@ -4945,6 +5553,19 @@ var WorldOrbit = (() => {
|
|
|
4945
5553
|
next.groups = next.groups.filter((group) => group.id !== path.id);
|
|
4946
5554
|
}
|
|
4947
5555
|
return next;
|
|
5556
|
+
case "event":
|
|
5557
|
+
if (path.id) {
|
|
5558
|
+
next.events = next.events.filter((event) => event.id !== path.id);
|
|
5559
|
+
}
|
|
5560
|
+
return next;
|
|
5561
|
+
case "event-pose":
|
|
5562
|
+
if (path.id && path.key) {
|
|
5563
|
+
const event = findEvent(next, path.id);
|
|
5564
|
+
if (event) {
|
|
5565
|
+
event.positions = event.positions.filter((pose) => pose.objectId !== path.key);
|
|
5566
|
+
}
|
|
5567
|
+
}
|
|
5568
|
+
return next;
|
|
4948
5569
|
case "viewpoint":
|
|
4949
5570
|
if (path.id) {
|
|
4950
5571
|
system.viewpoints = system.viewpoints.filter((viewpoint) => viewpoint.id !== path.id);
|
|
@@ -5013,6 +5634,22 @@ var WorldOrbit = (() => {
|
|
|
5013
5634
|
};
|
|
5014
5635
|
}
|
|
5015
5636
|
}
|
|
5637
|
+
if (diagnostic.field?.startsWith("event.")) {
|
|
5638
|
+
const parts = diagnostic.field.split(".");
|
|
5639
|
+
if (parts[1] && findEvent(document2, parts[1])) {
|
|
5640
|
+
if (parts[2] === "pose" && parts[3] && findEventPose(document2, parts[1], parts[3])) {
|
|
5641
|
+
return {
|
|
5642
|
+
kind: "event-pose",
|
|
5643
|
+
id: parts[1],
|
|
5644
|
+
key: parts[3]
|
|
5645
|
+
};
|
|
5646
|
+
}
|
|
5647
|
+
return {
|
|
5648
|
+
kind: "event",
|
|
5649
|
+
id: parts[1]
|
|
5650
|
+
};
|
|
5651
|
+
}
|
|
5652
|
+
}
|
|
5016
5653
|
if (diagnostic.field && diagnostic.field in ensureSystem(document2).atlasMetadata) {
|
|
5017
5654
|
return {
|
|
5018
5655
|
kind: "metadata",
|
|
@@ -5044,6 +5681,12 @@ var WorldOrbit = (() => {
|
|
|
5044
5681
|
function findRelation(document2, relationId) {
|
|
5045
5682
|
return document2.relations.find((relation) => relation.id === relationId) ?? null;
|
|
5046
5683
|
}
|
|
5684
|
+
function findEvent(document2, eventId) {
|
|
5685
|
+
return document2.events.find((event) => event.id === eventId) ?? null;
|
|
5686
|
+
}
|
|
5687
|
+
function findEventPose(document2, eventId, objectId) {
|
|
5688
|
+
return findEvent(document2, eventId)?.positions.find((pose) => pose.objectId === objectId) ?? null;
|
|
5689
|
+
}
|
|
5047
5690
|
function findViewpoint(system, viewpointId) {
|
|
5048
5691
|
return system?.viewpoints.find((viewpoint) => viewpoint.id === viewpointId) ?? null;
|
|
5049
5692
|
}
|
|
@@ -5221,6 +5864,7 @@ var WorldOrbit = (() => {
|
|
|
5221
5864
|
background: true,
|
|
5222
5865
|
guides: true,
|
|
5223
5866
|
relations: true,
|
|
5867
|
+
events: true,
|
|
5224
5868
|
orbits: true,
|
|
5225
5869
|
objects: true,
|
|
5226
5870
|
labels: true,
|
|
@@ -5369,12 +6013,14 @@ var WorldOrbit = (() => {
|
|
|
5369
6013
|
return {
|
|
5370
6014
|
version: "2.0",
|
|
5371
6015
|
viewpointId,
|
|
6016
|
+
activeEventId: renderOptions.activeEventId ?? null,
|
|
5372
6017
|
viewerState: { ...viewerState },
|
|
5373
6018
|
renderOptions: {
|
|
5374
6019
|
preset: renderOptions.preset,
|
|
5375
6020
|
projection: renderOptions.projection,
|
|
5376
6021
|
layers: renderOptions.layers ? { ...renderOptions.layers } : void 0,
|
|
5377
|
-
scaleModel: renderOptions.scaleModel ? { ...renderOptions.scaleModel } : void 0
|
|
6022
|
+
scaleModel: renderOptions.scaleModel ? { ...renderOptions.scaleModel } : void 0,
|
|
6023
|
+
activeEventId: renderOptions.activeEventId ?? null
|
|
5378
6024
|
},
|
|
5379
6025
|
filter: normalizeViewerFilter(filter)
|
|
5380
6026
|
};
|
|
@@ -5387,6 +6033,7 @@ var WorldOrbit = (() => {
|
|
|
5387
6033
|
return {
|
|
5388
6034
|
version: "2.0",
|
|
5389
6035
|
viewpointId: raw.viewpointId ?? null,
|
|
6036
|
+
activeEventId: raw.activeEventId ?? raw.renderOptions?.activeEventId ?? null,
|
|
5390
6037
|
viewerState: {
|
|
5391
6038
|
scale: raw.viewerState?.scale ?? 1,
|
|
5392
6039
|
rotationDeg: raw.viewerState?.rotationDeg ?? 0,
|
|
@@ -5398,7 +6045,8 @@ var WorldOrbit = (() => {
|
|
|
5398
6045
|
preset: raw.renderOptions?.preset,
|
|
5399
6046
|
projection: raw.renderOptions?.projection,
|
|
5400
6047
|
layers: raw.renderOptions?.layers ? { ...raw.renderOptions.layers } : void 0,
|
|
5401
|
-
scaleModel: raw.renderOptions?.scaleModel ? { ...raw.renderOptions.scaleModel } : void 0
|
|
6048
|
+
scaleModel: raw.renderOptions?.scaleModel ? { ...raw.renderOptions.scaleModel } : void 0,
|
|
6049
|
+
activeEventId: raw.activeEventId ?? raw.renderOptions?.activeEventId ?? null
|
|
5402
6050
|
},
|
|
5403
6051
|
filter: normalizeViewerFilter(raw.filter ?? null)
|
|
5404
6052
|
};
|
|
@@ -5414,7 +6062,8 @@ var WorldOrbit = (() => {
|
|
|
5414
6062
|
renderOptions: {
|
|
5415
6063
|
...atlasState.renderOptions,
|
|
5416
6064
|
layers: atlasState.renderOptions.layers ? { ...atlasState.renderOptions.layers } : void 0,
|
|
5417
|
-
scaleModel: atlasState.renderOptions.scaleModel ? { ...atlasState.renderOptions.scaleModel } : void 0
|
|
6065
|
+
scaleModel: atlasState.renderOptions.scaleModel ? { ...atlasState.renderOptions.scaleModel } : void 0,
|
|
6066
|
+
activeEventId: atlasState.renderOptions.activeEventId ?? null
|
|
5418
6067
|
},
|
|
5419
6068
|
filter: atlasState.filter ? { ...atlasState.filter } : null
|
|
5420
6069
|
}
|
|
@@ -5432,6 +6081,7 @@ var WorldOrbit = (() => {
|
|
|
5432
6081
|
background: viewpoint.layers.background,
|
|
5433
6082
|
guides: viewpoint.layers.guides,
|
|
5434
6083
|
relations: viewpoint.layers.relations,
|
|
6084
|
+
events: viewpoint.layers.events,
|
|
5435
6085
|
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,
|
|
5436
6086
|
objects: viewpoint.layers.objects,
|
|
5437
6087
|
labels: viewpoint.layers.labels,
|
|
@@ -5718,6 +6368,7 @@ var WorldOrbit = (() => {
|
|
|
5718
6368
|
const orbitMarkup = layers.orbits ? renderOrbitLayer(scene, visibleObjectIds, layers.structures) : { back: "", front: "" };
|
|
5719
6369
|
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("") : "";
|
|
5720
6370
|
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("") : "";
|
|
6371
|
+
const eventMarkup = layers.events ? scene.events.filter((event) => !event.hidden).map((event) => renderSceneEventOverlay(scene, event, visibleObjectIds, theme)).join("") : "";
|
|
5721
6372
|
const objectMarkup = layers.objects ? visibleObjects.map((object) => renderSceneObject(object, options.selectedObjectId ?? null, theme)).join("") : "";
|
|
5722
6373
|
const labelMarkup = layers.labels ? visibleLabels.map((label) => renderSceneLabel(scene, label, options.selectedObjectId ?? null)).join("") : "";
|
|
5723
6374
|
const metadataMarkup = layers.metadata ? `<text class="wo-title" x="56" y="64">${escapeXml(scene.title)}</text>
|
|
@@ -5753,6 +6404,9 @@ var WorldOrbit = (() => {
|
|
|
5753
6404
|
.wo-orbit-front { opacity: 0.9; }
|
|
5754
6405
|
.wo-orbit-band { stroke: ${theme.orbitBand}; stroke-linecap: round; }
|
|
5755
6406
|
.wo-relation { stroke: ${theme.relation}; stroke-width: 2; stroke-dasharray: 10 6; }
|
|
6407
|
+
.wo-event-line { stroke: ${theme.accent}; stroke-width: 1.6; stroke-dasharray: 5 5; opacity: 0.72; }
|
|
6408
|
+
.wo-event-node { fill: ${theme.accent}; stroke: ${theme.selected}; stroke-width: 1.4; opacity: 0.92; }
|
|
6409
|
+
.wo-event-label { fill: ${theme.accent}; font-family: ${theme.fontFamily}; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; }
|
|
5756
6410
|
.wo-leader { stroke: ${theme.leader}; stroke-width: 1.5; stroke-dasharray: 6 5; }
|
|
5757
6411
|
.wo-label { fill: ${theme.ink}; font-family: ${theme.fontFamily}; font-weight: 600; letter-spacing: 0.02em; }
|
|
5758
6412
|
.wo-label-secondary { fill: ${theme.muted}; font-family: ${theme.fontFamily}; font-weight: 500; }
|
|
@@ -5787,6 +6441,7 @@ var WorldOrbit = (() => {
|
|
|
5787
6441
|
${layers.orbits ? `<g data-layer-id="orbits-back">${orbitMarkup.back}</g>` : ""}
|
|
5788
6442
|
${layers.guides ? `<g data-layer-id="guides">${leaderMarkup}</g>` : ""}
|
|
5789
6443
|
${layers.relations ? `<g data-layer-id="relations">${relationMarkup}</g>` : ""}
|
|
6444
|
+
${layers.events ? `<g data-layer-id="events">${eventMarkup}</g>` : ""}
|
|
5790
6445
|
${layers.objects ? `<g data-layer-id="objects">${objectMarkup}</g>` : ""}
|
|
5791
6446
|
${layers.orbits ? `<g data-layer-id="orbits-front">${orbitMarkup.front}</g>` : ""}
|
|
5792
6447
|
${layers.labels ? `<g data-layer-id="labels">${labelMarkup}</g>` : ""}
|
|
@@ -5794,6 +6449,20 @@ var WorldOrbit = (() => {
|
|
|
5794
6449
|
</g>
|
|
5795
6450
|
</g>
|
|
5796
6451
|
</svg>`;
|
|
6452
|
+
}
|
|
6453
|
+
function renderSceneEventOverlay(scene, event, visibleObjectIds, theme) {
|
|
6454
|
+
const participants = event.objectIds.filter((objectId) => visibleObjectIds.has(objectId)).map((objectId) => scene.objects.find((object) => object.objectId === objectId && !object.hidden)).filter(Boolean);
|
|
6455
|
+
if (participants.length === 0) {
|
|
6456
|
+
return "";
|
|
6457
|
+
}
|
|
6458
|
+
const stroke = event.event.color || theme.accent;
|
|
6459
|
+
const label = event.event.label || event.event.id;
|
|
6460
|
+
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("");
|
|
6461
|
+
return `<g class="wo-event" data-render-id="${escapeXml(event.renderId)}" data-event-id="${escapeAttribute(event.eventId)}">
|
|
6462
|
+
${lineMarkup}
|
|
6463
|
+
<circle class="wo-event-node" cx="${event.x}" cy="${event.y}" r="5" fill="${escapeAttribute(stroke)}" />
|
|
6464
|
+
<text class="wo-event-label" x="${event.x}" y="${event.y - 10}" text-anchor="middle" font-size="10">${escapeXml(label)}</text>
|
|
6465
|
+
</g>`;
|
|
5797
6466
|
}
|
|
5798
6467
|
function renderOrbitLayer(scene, visibleObjectIds, includeStructures) {
|
|
5799
6468
|
const backParts = [];
|
|
@@ -6376,6 +7045,13 @@ var WorldOrbit = (() => {
|
|
|
6376
7045
|
value: `${details.object.resonance.targetObjectId} ${details.object.resonance.ratio}`
|
|
6377
7046
|
});
|
|
6378
7047
|
}
|
|
7048
|
+
if (details.relatedEvents.length > 0) {
|
|
7049
|
+
fields.set("events", {
|
|
7050
|
+
key: "events",
|
|
7051
|
+
label: "Events",
|
|
7052
|
+
value: details.relatedEvents.map((event) => event.event.label || event.event.id).join(", ")
|
|
7053
|
+
});
|
|
7054
|
+
}
|
|
6379
7055
|
if (placement?.mode === "at") {
|
|
6380
7056
|
fields.set("placement", {
|
|
6381
7057
|
key: "placement",
|
|
@@ -6790,6 +7466,12 @@ var WorldOrbit = (() => {
|
|
|
6790
7466
|
emitAtlasStateChange();
|
|
6791
7467
|
return true;
|
|
6792
7468
|
},
|
|
7469
|
+
getActiveEventId() {
|
|
7470
|
+
return renderOptions.activeEventId ?? null;
|
|
7471
|
+
},
|
|
7472
|
+
setActiveEvent(id) {
|
|
7473
|
+
api.setRenderOptions({ activeEventId: id });
|
|
7474
|
+
},
|
|
6793
7475
|
search(query, limit = 12) {
|
|
6794
7476
|
return searchSceneObjects(scene, query, limit);
|
|
6795
7477
|
},
|
|
@@ -7054,6 +7736,7 @@ var WorldOrbit = (() => {
|
|
|
7054
7736
|
orbit: scene.orbitVisuals.find((orbit) => orbit.objectId === renderObject.objectId && !orbit.hidden) ?? null,
|
|
7055
7737
|
relatedOrbits: scene.orbitVisuals.filter((orbit) => !orbit.hidden && (orbit.objectId === renderObject.objectId || renderObject.ancestorIds.includes(orbit.objectId) || renderObject.childIds.includes(orbit.objectId))),
|
|
7056
7738
|
relations: scene.relations.filter((relation) => !relation.hidden && (relation.fromObjectId === renderObject.objectId || relation.toObjectId === renderObject.objectId)),
|
|
7739
|
+
relatedEvents: scene.events.filter((event) => !event.hidden && (event.targetObjectId === renderObject.objectId || event.objectIds.includes(renderObject.objectId))),
|
|
7057
7740
|
parent: getObjectById(renderObject.parentId),
|
|
7058
7741
|
children: renderObject.childIds.map((childId) => getObjectById(childId)).filter(Boolean),
|
|
7059
7742
|
ancestors: renderObject.ancestorIds.map((ancestorId) => getObjectById(ancestorId)).filter(Boolean),
|
|
@@ -7370,7 +8053,8 @@ var WorldOrbit = (() => {
|
|
|
7370
8053
|
filter: renderOptions.filter ? { ...renderOptions.filter } : void 0,
|
|
7371
8054
|
scaleModel: renderOptions.scaleModel ? { ...renderOptions.scaleModel } : void 0,
|
|
7372
8055
|
layers: renderOptions.layers ? { ...renderOptions.layers } : void 0,
|
|
7373
|
-
theme: renderOptions.theme && typeof renderOptions.theme === "object" ? { ...renderOptions.theme } : renderOptions.theme
|
|
8056
|
+
theme: renderOptions.theme && typeof renderOptions.theme === "object" ? { ...renderOptions.theme } : renderOptions.theme,
|
|
8057
|
+
activeEventId: renderOptions.activeEventId ?? null
|
|
7374
8058
|
};
|
|
7375
8059
|
}
|
|
7376
8060
|
function mergeRenderOptions(current, next) {
|
|
@@ -7390,7 +8074,7 @@ var WorldOrbit = (() => {
|
|
|
7390
8074
|
};
|
|
7391
8075
|
}
|
|
7392
8076
|
function hasSceneAffectingRenderOptions(options) {
|
|
7393
|
-
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;
|
|
8077
|
+
return options.width !== void 0 || options.height !== void 0 || options.padding !== void 0 || options.preset !== void 0 || options.projection !== void 0 || options.scaleModel !== void 0 || options.activeEventId !== void 0;
|
|
7394
8078
|
}
|
|
7395
8079
|
function resolveSourceRenderOptions(loaded, renderOptions) {
|
|
7396
8080
|
const atlasDocument = loaded.atlasDocument ?? loaded.draftDocument;
|
|
@@ -7723,6 +8407,34 @@ var WorldOrbit = (() => {
|
|
|
7723
8407
|
description: "Rotates the saved camera angle in degrees.",
|
|
7724
8408
|
references: ["90deg = quarter turn", "180deg = flip"]
|
|
7725
8409
|
},
|
|
8410
|
+
"viewpoint-events": {
|
|
8411
|
+
description: "Lists event IDs that this viewpoint should feature in its detail panel.",
|
|
8412
|
+
references: ["solar-eclipse-naar", "transit-window conjunction"]
|
|
8413
|
+
},
|
|
8414
|
+
"event-kind": {
|
|
8415
|
+
description: "Short semantic event type for tooling and viewer overlays.",
|
|
8416
|
+
references: ["solar-eclipse", "lunar-eclipse", "transit"]
|
|
8417
|
+
},
|
|
8418
|
+
"event-target": {
|
|
8419
|
+
description: "Primary object this event is centered on.",
|
|
8420
|
+
references: ["Naar", "Seyra"]
|
|
8421
|
+
},
|
|
8422
|
+
"event-participants": {
|
|
8423
|
+
description: "Objects that participate in the event snapshot or description.",
|
|
8424
|
+
references: ["Iyath Naar Seyra", "Naar Seyra Orun"]
|
|
8425
|
+
},
|
|
8426
|
+
"event-timing": {
|
|
8427
|
+
description: "Free-text timing note for the event.",
|
|
8428
|
+
references: ['"Every late bloom season"', '"At local midyear"']
|
|
8429
|
+
},
|
|
8430
|
+
"event-visibility": {
|
|
8431
|
+
description: "Notes where or how the event is visible.",
|
|
8432
|
+
references: ['"Visible from Naar"', '"Southern hemisphere only"']
|
|
8433
|
+
},
|
|
8434
|
+
"event-viewpoints": {
|
|
8435
|
+
description: "Viewpoint IDs that should list this event prominently.",
|
|
8436
|
+
references: ["naar-system", "overview inner-system"]
|
|
8437
|
+
},
|
|
7726
8438
|
"placement-target": {
|
|
7727
8439
|
description: "Names the body or reference this object is attached to.",
|
|
7728
8440
|
references: ["orbit Primary", "surface Homeworld", "at Naar:L4"]
|
|
@@ -7841,12 +8553,23 @@ var WorldOrbit = (() => {
|
|
|
7841
8553
|
minimap: true,
|
|
7842
8554
|
tooltipMode: "hover",
|
|
7843
8555
|
onSelectionChange(selectedObject) {
|
|
8556
|
+
const activeEventId = selection ? selectionEventId(selection) : null;
|
|
7844
8557
|
if (ignoreViewerSelection || !selectedObject) {
|
|
7845
|
-
if (!ignoreViewerSelection
|
|
7846
|
-
|
|
8558
|
+
if (!ignoreViewerSelection) {
|
|
8559
|
+
if (selection?.kind === "event-pose" && selection.id) {
|
|
8560
|
+
setSelection({ kind: "event", id: selection.id }, false, true);
|
|
8561
|
+
} else if (selection?.kind === "object") {
|
|
8562
|
+
setSelection(activeEventId ? { kind: "event", id: activeEventId } : null, false, true);
|
|
8563
|
+
} else if (selection?.kind === "event" && selection.id) {
|
|
8564
|
+
setSelection({ kind: "event", id: selection.id }, false, true);
|
|
8565
|
+
}
|
|
7847
8566
|
}
|
|
7848
8567
|
return;
|
|
7849
8568
|
}
|
|
8569
|
+
if (activeEventId && findEventPose2(atlasDocument, activeEventId, selectedObject.objectId)) {
|
|
8570
|
+
setSelection({ kind: "event-pose", id: activeEventId, key: selectedObject.objectId }, false, true);
|
|
8571
|
+
return;
|
|
8572
|
+
}
|
|
7850
8573
|
setSelection({ kind: "object", id: selectedObject.objectId }, false, true);
|
|
7851
8574
|
},
|
|
7852
8575
|
onViewChange() {
|
|
@@ -7856,6 +8579,7 @@ var WorldOrbit = (() => {
|
|
|
7856
8579
|
toolbar.addEventListener("click", handleToolbarClick);
|
|
7857
8580
|
outline.addEventListener("click", handleOutlineClick);
|
|
7858
8581
|
overlay.addEventListener("pointerdown", handleOverlayPointerDown);
|
|
8582
|
+
inspector?.addEventListener("click", handleInspectorClick);
|
|
7859
8583
|
inspector?.addEventListener("input", handleInspectorInput);
|
|
7860
8584
|
inspector?.addEventListener("change", handleInspectorChange);
|
|
7861
8585
|
sourcePane?.addEventListener("input", handleSourceInput);
|
|
@@ -7930,6 +8654,28 @@ var WorldOrbit = (() => {
|
|
|
7930
8654
|
replaceAtlasDocument(nextDocument, true, { kind: "object", id });
|
|
7931
8655
|
return id;
|
|
7932
8656
|
},
|
|
8657
|
+
addEvent() {
|
|
8658
|
+
const id = createUniqueId("event", atlasDocument.events.map((event) => event.id));
|
|
8659
|
+
const created = {
|
|
8660
|
+
id,
|
|
8661
|
+
kind: "",
|
|
8662
|
+
label: humanizeIdentifier4(id),
|
|
8663
|
+
summary: null,
|
|
8664
|
+
targetObjectId: null,
|
|
8665
|
+
participantObjectIds: [],
|
|
8666
|
+
timing: null,
|
|
8667
|
+
visibility: null,
|
|
8668
|
+
tags: [],
|
|
8669
|
+
color: null,
|
|
8670
|
+
hidden: false,
|
|
8671
|
+
positions: []
|
|
8672
|
+
};
|
|
8673
|
+
const nextDocument = cloneAtlasDocument(atlasDocument);
|
|
8674
|
+
nextDocument.events.push(created);
|
|
8675
|
+
nextDocument.events.sort(compareEvents);
|
|
8676
|
+
replaceAtlasDocument(nextDocument, true, { kind: "event", id });
|
|
8677
|
+
return id;
|
|
8678
|
+
},
|
|
7933
8679
|
addViewpoint() {
|
|
7934
8680
|
const id = createUniqueId("viewpoint", atlasDocument.system?.viewpoints.map((viewpoint) => viewpoint.id) ?? []);
|
|
7935
8681
|
const created = {
|
|
@@ -7938,6 +8684,7 @@ var WorldOrbit = (() => {
|
|
|
7938
8684
|
summary: "",
|
|
7939
8685
|
focusObjectId: null,
|
|
7940
8686
|
selectedObjectId: null,
|
|
8687
|
+
events: [],
|
|
7941
8688
|
projection: atlasDocument.system?.defaults.view ?? "topdown",
|
|
7942
8689
|
preset: atlasDocument.system?.defaults.preset ?? null,
|
|
7943
8690
|
zoom: null,
|
|
@@ -7998,6 +8745,7 @@ var WorldOrbit = (() => {
|
|
|
7998
8745
|
toolbar.removeEventListener("click", handleToolbarClick);
|
|
7999
8746
|
outline.removeEventListener("click", handleOutlineClick);
|
|
8000
8747
|
overlay.removeEventListener("pointerdown", handleOverlayPointerDown);
|
|
8748
|
+
inspector?.removeEventListener("click", handleInspectorClick);
|
|
8001
8749
|
inspector?.removeEventListener("input", handleInspectorInput);
|
|
8002
8750
|
inspector?.removeEventListener("change", handleInspectorChange);
|
|
8003
8751
|
sourcePane?.removeEventListener("input", handleSourceInput);
|
|
@@ -8043,7 +8791,7 @@ var WorldOrbit = (() => {
|
|
|
8043
8791
|
}
|
|
8044
8792
|
function getCurrentSourceForExport() {
|
|
8045
8793
|
if (dragState?.changed) {
|
|
8046
|
-
return
|
|
8794
|
+
return formatAtlasSource(atlasDocument);
|
|
8047
8795
|
}
|
|
8048
8796
|
return canonicalSource;
|
|
8049
8797
|
}
|
|
@@ -8082,7 +8830,7 @@ var WorldOrbit = (() => {
|
|
|
8082
8830
|
}
|
|
8083
8831
|
clearSourceInputTimer();
|
|
8084
8832
|
atlasDocument = cloneAtlasDocument(nextDocument);
|
|
8085
|
-
canonicalSource =
|
|
8833
|
+
canonicalSource = formatAtlasSource(atlasDocument);
|
|
8086
8834
|
if (!preserveSourceText) {
|
|
8087
8835
|
sourceText = canonicalSource;
|
|
8088
8836
|
}
|
|
@@ -8123,10 +8871,10 @@ var WorldOrbit = (() => {
|
|
|
8123
8871
|
if (commitHistory) {
|
|
8124
8872
|
history.push(createHistoryEntry());
|
|
8125
8873
|
future.length = 0;
|
|
8126
|
-
sourceText =
|
|
8874
|
+
sourceText = formatAtlasSource(nextDocument);
|
|
8127
8875
|
}
|
|
8128
8876
|
atlasDocument = cloneAtlasDocument(nextDocument);
|
|
8129
|
-
canonicalSource =
|
|
8877
|
+
canonicalSource = formatAtlasSource(atlasDocument);
|
|
8130
8878
|
diagnostics = mergeDiagnostics(loadedDiagnostics, collectDocumentDiagnostics(atlasDocument));
|
|
8131
8879
|
selection = normalizeSelection(selection);
|
|
8132
8880
|
syncViewer({
|
|
@@ -8145,11 +8893,13 @@ var WorldOrbit = (() => {
|
|
|
8145
8893
|
const previousState = viewer.getState();
|
|
8146
8894
|
const currentRenderOptions = viewer.getRenderOptions();
|
|
8147
8895
|
const nextPreset = atlasDocument.system?.defaults.preset ?? "atlas-card";
|
|
8896
|
+
const nextActiveEventId = selection ? selectionEventId(selection) : null;
|
|
8148
8897
|
ignoreViewerSelection = true;
|
|
8149
|
-
if (currentRenderOptions.preset !== nextPreset || currentRenderOptions.projection !== "document") {
|
|
8898
|
+
if (currentRenderOptions.preset !== nextPreset || currentRenderOptions.projection !== "document" || (currentRenderOptions.activeEventId ?? null) !== nextActiveEventId) {
|
|
8150
8899
|
viewer.setRenderOptions({
|
|
8151
8900
|
preset: nextPreset,
|
|
8152
|
-
projection: "document"
|
|
8901
|
+
projection: "document",
|
|
8902
|
+
activeEventId: nextActiveEventId
|
|
8153
8903
|
});
|
|
8154
8904
|
}
|
|
8155
8905
|
viewer.setDocument(materializeAtlasDocument(atlasDocument));
|
|
@@ -8158,10 +8908,12 @@ var WorldOrbit = (() => {
|
|
|
8158
8908
|
} else if (options2.preserveCamera !== false) {
|
|
8159
8909
|
viewer.setState({
|
|
8160
8910
|
...previousState,
|
|
8161
|
-
selectedObjectId: selection?.kind === "object" ? selection.id ?? null : null
|
|
8911
|
+
selectedObjectId: selection?.kind === "object" ? selection.id ?? null : selection?.kind === "event-pose" ? selection.key ?? null : null
|
|
8162
8912
|
});
|
|
8163
8913
|
} else if (selection?.kind === "object" && selection.id) {
|
|
8164
8914
|
viewer.focusObject(selection.id);
|
|
8915
|
+
} else if (selection?.kind === "event-pose" && selection.key) {
|
|
8916
|
+
viewer.focusObject(selection.key);
|
|
8165
8917
|
}
|
|
8166
8918
|
ignoreViewerSelection = false;
|
|
8167
8919
|
}
|
|
@@ -8180,8 +8932,11 @@ var WorldOrbit = (() => {
|
|
|
8180
8932
|
selection = normalizeSelection(nextSelection);
|
|
8181
8933
|
if (syncViewerSelection) {
|
|
8182
8934
|
ignoreViewerSelection = true;
|
|
8935
|
+
viewer.setRenderOptions({ activeEventId: selection ? selectionEventId(selection) : null });
|
|
8183
8936
|
if (selection?.kind === "object" && selection.id) {
|
|
8184
8937
|
viewer.focusObject(selection.id);
|
|
8938
|
+
} else if (selection?.kind === "event-pose" && selection.key) {
|
|
8939
|
+
viewer.focusObject(selection.key);
|
|
8185
8940
|
} else if (selection?.kind === "viewpoint" && selection.id) {
|
|
8186
8941
|
viewer.goToViewpoint(selection.id);
|
|
8187
8942
|
}
|
|
@@ -8231,6 +8986,7 @@ var WorldOrbit = (() => {
|
|
|
8231
8986
|
${OBJECT_TYPES.map((type) => `<option value="${escapeHtml3(type)}"${type === objectType ? " selected" : ""}>${escapeHtml3(humanizeIdentifier4(type))}</option>`).join("")}
|
|
8232
8987
|
</select>
|
|
8233
8988
|
<button type="button" data-editor-action="add-object">Add object</button>
|
|
8989
|
+
<button type="button" data-editor-action="add-event">Add event</button>
|
|
8234
8990
|
<button type="button" data-editor-action="add-viewpoint">Add viewpoint</button>
|
|
8235
8991
|
<button type="button" data-editor-action="add-annotation">Add annotation</button>
|
|
8236
8992
|
<button type="button" data-editor-action="add-metadata">Add metadata</button>
|
|
@@ -8265,6 +9021,10 @@ var WorldOrbit = (() => {
|
|
|
8265
9021
|
<h3>Annotations</h3>
|
|
8266
9022
|
${(atlasDocument.system?.annotations.length ?? 0) > 0 ? atlasDocument.system?.annotations.map((annotation) => renderOutlineButton({ kind: "annotation", id: annotation.id }, annotation.label, activeKey, diagnosticBuckets)).join("") : `<p class="wo-editor-empty">No annotations yet.</p>`}
|
|
8267
9023
|
</div>
|
|
9024
|
+
<div class="wo-editor-outline-section">
|
|
9025
|
+
<h3>Events</h3>
|
|
9026
|
+
${atlasDocument.events.length > 0 ? atlasDocument.events.map((eventEntry) => renderEventOutlineItems(eventEntry, activeKey, diagnosticBuckets)).join("") : `<p class="wo-editor-empty">No events yet.</p>`}
|
|
9027
|
+
</div>
|
|
8268
9028
|
<div class="wo-editor-outline-section">
|
|
8269
9029
|
<h3>Objects</h3>
|
|
8270
9030
|
${atlasDocument.objects.length > 0 ? atlasDocument.objects.map((object) => renderOutlineButton({ kind: "object", id: object.id }, `${object.id} - ${object.type}`, activeKey, diagnosticBuckets)).join("") : `<p class="wo-editor-empty">No objects yet.</p>`}
|
|
@@ -8302,6 +9062,7 @@ var WorldOrbit = (() => {
|
|
|
8302
9062
|
selection: selection ? { path: { ...selection } } : null,
|
|
8303
9063
|
system: atlasDocument.system,
|
|
8304
9064
|
viewpoints: atlasDocument.system?.viewpoints ?? [],
|
|
9065
|
+
events: atlasDocument.events,
|
|
8305
9066
|
objects: atlasDocument.objects
|
|
8306
9067
|
};
|
|
8307
9068
|
if (!selection) {
|
|
@@ -8330,6 +9091,16 @@ var WorldOrbit = (() => {
|
|
|
8330
9091
|
applyInspectorSectionState(inspector, inspectorSectionState);
|
|
8331
9092
|
decorateInspectorDiagnostics(selection, diagnostics);
|
|
8332
9093
|
return;
|
|
9094
|
+
case "event":
|
|
9095
|
+
inspector.innerHTML = diagnosticSummary + renderEventInspector(formState, selection.id ?? "");
|
|
9096
|
+
applyInspectorSectionState(inspector, inspectorSectionState);
|
|
9097
|
+
decorateInspectorDiagnostics(selection, diagnostics);
|
|
9098
|
+
return;
|
|
9099
|
+
case "event-pose":
|
|
9100
|
+
inspector.innerHTML = diagnosticSummary + renderEventPoseInspector(formState, selection.id ?? "", selection.key ?? "");
|
|
9101
|
+
applyInspectorSectionState(inspector, inspectorSectionState);
|
|
9102
|
+
decorateInspectorDiagnostics(selection, diagnostics);
|
|
9103
|
+
return;
|
|
8333
9104
|
case "annotation":
|
|
8334
9105
|
inspector.innerHTML = diagnosticSummary + renderAnnotationInspector(formState, selection.id ?? "");
|
|
8335
9106
|
applyInspectorSectionState(inspector, inspectorSectionState);
|
|
@@ -8362,10 +9133,11 @@ var WorldOrbit = (() => {
|
|
|
8362
9133
|
return;
|
|
8363
9134
|
}
|
|
8364
9135
|
overlay.innerHTML = "";
|
|
8365
|
-
|
|
9136
|
+
const selectedObjectId = selection?.kind === "object" ? selection.id ?? null : selection?.kind === "event-pose" ? selection.key ?? null : null;
|
|
9137
|
+
if (!selectedObjectId) {
|
|
8366
9138
|
return;
|
|
8367
9139
|
}
|
|
8368
|
-
const details = viewer.getObjectDetails(
|
|
9140
|
+
const details = viewer.getObjectDetails(selectedObjectId);
|
|
8369
9141
|
if (!details) {
|
|
8370
9142
|
return;
|
|
8371
9143
|
}
|
|
@@ -8477,6 +9249,9 @@ var WorldOrbit = (() => {
|
|
|
8477
9249
|
case "add-viewpoint":
|
|
8478
9250
|
api.addViewpoint();
|
|
8479
9251
|
return;
|
|
9252
|
+
case "add-event":
|
|
9253
|
+
api.addEvent();
|
|
9254
|
+
return;
|
|
8480
9255
|
case "add-annotation":
|
|
8481
9256
|
api.addAnnotation();
|
|
8482
9257
|
return;
|
|
@@ -8511,6 +9286,32 @@ var WorldOrbit = (() => {
|
|
|
8511
9286
|
key: button.dataset.pathKey || void 0
|
|
8512
9287
|
}, true, true);
|
|
8513
9288
|
}
|
|
9289
|
+
function handleInspectorClick(event) {
|
|
9290
|
+
const pathButton = event.target?.closest("[data-path-kind]");
|
|
9291
|
+
if (pathButton) {
|
|
9292
|
+
setSelection({
|
|
9293
|
+
kind: pathButton.dataset.pathKind,
|
|
9294
|
+
id: pathButton.dataset.pathId || void 0,
|
|
9295
|
+
key: pathButton.dataset.pathKey || void 0
|
|
9296
|
+
}, true, true);
|
|
9297
|
+
return;
|
|
9298
|
+
}
|
|
9299
|
+
const actionButton = event.target?.closest("[data-editor-action]");
|
|
9300
|
+
if (!actionButton) {
|
|
9301
|
+
return;
|
|
9302
|
+
}
|
|
9303
|
+
if (actionButton.dataset.editorAction === "add-event-pose") {
|
|
9304
|
+
const eventId = actionButton.dataset.editorEventId || (selection?.kind === "event" || selection?.kind === "event-pose" ? selection.id ?? "" : "");
|
|
9305
|
+
if (!eventId) {
|
|
9306
|
+
return;
|
|
9307
|
+
}
|
|
9308
|
+
const nextDocument = addEventPose(atlasDocument, eventId);
|
|
9309
|
+
const createdEvent = nextDocument.events.find((entry) => entry.id === eventId);
|
|
9310
|
+
const createdPose = createdEvent?.positions.at(-1) ?? createdEvent?.positions[0];
|
|
9311
|
+
replaceAtlasDocument(nextDocument, true, createdPose ? { kind: "event-pose", id: eventId, key: createdPose.objectId } : { kind: "event", id: eventId });
|
|
9312
|
+
return;
|
|
9313
|
+
}
|
|
9314
|
+
}
|
|
8514
9315
|
function handleInspectorInput() {
|
|
8515
9316
|
applyInspectorState(false);
|
|
8516
9317
|
}
|
|
@@ -8534,6 +9335,12 @@ var WorldOrbit = (() => {
|
|
|
8534
9335
|
case "viewpoint":
|
|
8535
9336
|
replaceAtlasDocument(buildViewpointDocumentFromInspector(selection.id ?? ""), commitHistory, selection, false);
|
|
8536
9337
|
return;
|
|
9338
|
+
case "event":
|
|
9339
|
+
replaceAtlasDocument(buildEventDocumentFromInspector(selection.id ?? ""), commitHistory, selection, false);
|
|
9340
|
+
return;
|
|
9341
|
+
case "event-pose":
|
|
9342
|
+
replaceAtlasDocument(buildEventPoseDocumentFromInspector(selection.id ?? "", selection.key ?? ""), commitHistory, selection, false);
|
|
9343
|
+
return;
|
|
8537
9344
|
case "annotation":
|
|
8538
9345
|
replaceAtlasDocument(buildAnnotationDocumentFromInspector(selection.id ?? ""), commitHistory, selection, false);
|
|
8539
9346
|
return;
|
|
@@ -8602,6 +9409,7 @@ var WorldOrbit = (() => {
|
|
|
8602
9409
|
kind,
|
|
8603
9410
|
objectId,
|
|
8604
9411
|
pointerId: event.pointerId,
|
|
9412
|
+
path: selection ? { ...selection } : { kind: "object", id: objectId },
|
|
8605
9413
|
startedFrom: createHistoryEntry(),
|
|
8606
9414
|
changed: false,
|
|
8607
9415
|
orbitRadiusContext: kind === "orbit-radius" && details ? createOrbitRadiusDragContext(atlasDocument, viewer.getScene(), details) : null
|
|
@@ -8610,7 +9418,7 @@ var WorldOrbit = (() => {
|
|
|
8610
9418
|
event.preventDefault();
|
|
8611
9419
|
}
|
|
8612
9420
|
function handleWindowPointerMove(event) {
|
|
8613
|
-
if (!dragState || dragState.pointerId !== event.pointerId || selection
|
|
9421
|
+
if (!dragState || dragState.pointerId !== event.pointerId || !selection || selectionKey(selection) !== selectionKey(dragState.path)) {
|
|
8614
9422
|
return;
|
|
8615
9423
|
}
|
|
8616
9424
|
const details = viewer.getObjectDetails(dragState.objectId);
|
|
@@ -8622,27 +9430,27 @@ var WorldOrbit = (() => {
|
|
|
8622
9430
|
switch (dragState.kind) {
|
|
8623
9431
|
case "orbit-phase":
|
|
8624
9432
|
if (details.object.placement?.mode === "orbit" && details.orbit) {
|
|
8625
|
-
nextDocument = updateOrbitPhase(atlasDocument, dragState.objectId, details, pointer);
|
|
9433
|
+
nextDocument = updateOrbitPhase(atlasDocument, dragState.path, dragState.objectId, details, pointer);
|
|
8626
9434
|
}
|
|
8627
9435
|
break;
|
|
8628
9436
|
case "orbit-radius":
|
|
8629
9437
|
if (details.object.placement?.mode === "orbit" && details.orbit) {
|
|
8630
|
-
nextDocument = updateOrbitRadius(atlasDocument, dragState.objectId, details, pointer, dragState.orbitRadiusContext ?? null);
|
|
9438
|
+
nextDocument = updateOrbitRadius(atlasDocument, dragState.path, dragState.objectId, details, pointer, dragState.orbitRadiusContext ?? null);
|
|
8631
9439
|
}
|
|
8632
9440
|
break;
|
|
8633
9441
|
case "at-reference":
|
|
8634
9442
|
if (details.object.placement?.mode === "at") {
|
|
8635
|
-
nextDocument = updateAtReference(atlasDocument, dragState.objectId, viewer.getScene(), pointer);
|
|
9443
|
+
nextDocument = updateAtReference(atlasDocument, dragState.path, dragState.objectId, viewer.getScene(), pointer);
|
|
8636
9444
|
}
|
|
8637
9445
|
break;
|
|
8638
9446
|
case "surface-target":
|
|
8639
9447
|
if (details.object.placement?.mode === "surface") {
|
|
8640
|
-
nextDocument = updateSurfaceTarget(atlasDocument, dragState.objectId, viewer.getScene(), pointer);
|
|
9448
|
+
nextDocument = updateSurfaceTarget(atlasDocument, dragState.path, dragState.objectId, viewer.getScene(), pointer);
|
|
8641
9449
|
}
|
|
8642
9450
|
break;
|
|
8643
9451
|
case "free-distance":
|
|
8644
9452
|
if (details.object.placement?.mode === "free") {
|
|
8645
|
-
nextDocument = updateFreeDistance(atlasDocument, dragState.objectId, viewer.getScene(), details, pointer);
|
|
9453
|
+
nextDocument = updateFreeDistance(atlasDocument, dragState.path, dragState.objectId, viewer.getScene(), details, pointer);
|
|
8646
9454
|
}
|
|
8647
9455
|
break;
|
|
8648
9456
|
}
|
|
@@ -8674,7 +9482,7 @@ var WorldOrbit = (() => {
|
|
|
8674
9482
|
}
|
|
8675
9483
|
history.push(dragState.startedFrom);
|
|
8676
9484
|
future.length = 0;
|
|
8677
|
-
canonicalSource =
|
|
9485
|
+
canonicalSource = formatAtlasSource(atlasDocument);
|
|
8678
9486
|
sourceText = canonicalSource;
|
|
8679
9487
|
dragState = null;
|
|
8680
9488
|
renderAll();
|
|
@@ -8777,10 +9585,12 @@ var WorldOrbit = (() => {
|
|
|
8777
9585
|
guides: readCheckbox(form, "layer-guides"),
|
|
8778
9586
|
"orbits-back": readCheckbox(form, "layer-orbits-back"),
|
|
8779
9587
|
"orbits-front": readCheckbox(form, "layer-orbits-front"),
|
|
9588
|
+
events: readCheckbox(form, "layer-events"),
|
|
8780
9589
|
objects: readCheckbox(form, "layer-objects"),
|
|
8781
9590
|
labels: readCheckbox(form, "layer-labels"),
|
|
8782
9591
|
metadata: readCheckbox(form, "layer-metadata")
|
|
8783
9592
|
},
|
|
9593
|
+
events: splitTokens(readOptionalTextInput(form, "viewpoint-events")),
|
|
8784
9594
|
filter: {
|
|
8785
9595
|
query: readOptionalTextInput(form, "filter-query"),
|
|
8786
9596
|
objectTypes: parseObjectTypes(readOptionalTextInput(form, "filter-object-types")),
|
|
@@ -8794,6 +9604,66 @@ var WorldOrbit = (() => {
|
|
|
8794
9604
|
}
|
|
8795
9605
|
return nextDocument;
|
|
8796
9606
|
}
|
|
9607
|
+
function buildEventDocumentFromInspector(currentId) {
|
|
9608
|
+
const nextDocument = cloneAtlasDocument(atlasDocument);
|
|
9609
|
+
const form = inspector?.querySelector("form[data-editor-form='event']");
|
|
9610
|
+
const current = nextDocument.events.find((entry) => entry.id === currentId);
|
|
9611
|
+
if (!form || !current) {
|
|
9612
|
+
return nextDocument;
|
|
9613
|
+
}
|
|
9614
|
+
const nextId = readTextInput(form, "event-id") || current.id;
|
|
9615
|
+
const replacement = {
|
|
9616
|
+
...current,
|
|
9617
|
+
id: nextId,
|
|
9618
|
+
kind: readTextInput(form, "event-kind"),
|
|
9619
|
+
label: readTextInput(form, "event-label") || current.label,
|
|
9620
|
+
summary: readOptionalTextInput(form, "event-summary"),
|
|
9621
|
+
targetObjectId: readOptionalTextInput(form, "event-target"),
|
|
9622
|
+
participantObjectIds: splitTokens(readOptionalTextInput(form, "event-participants")),
|
|
9623
|
+
timing: readOptionalTextInput(form, "event-timing"),
|
|
9624
|
+
visibility: readOptionalTextInput(form, "event-visibility"),
|
|
9625
|
+
tags: splitTokens(readOptionalTextInput(form, "event-tags")),
|
|
9626
|
+
color: readOptionalTextInput(form, "event-color"),
|
|
9627
|
+
hidden: readCheckbox(form, "event-hidden")
|
|
9628
|
+
};
|
|
9629
|
+
nextDocument.events = nextDocument.events.filter((entry) => entry.id !== current.id).concat(replacement).sort(compareEvents);
|
|
9630
|
+
syncEventViewpointReferences(nextDocument, current.id, replacement.id, splitTokens(readOptionalTextInput(form, "event-viewpoints")));
|
|
9631
|
+
if (current.id !== replacement.id) {
|
|
9632
|
+
selection = { kind: "event", id: replacement.id };
|
|
9633
|
+
}
|
|
9634
|
+
return nextDocument;
|
|
9635
|
+
}
|
|
9636
|
+
function buildEventPoseDocumentFromInspector(eventId, objectId) {
|
|
9637
|
+
const nextDocument = cloneAtlasDocument(atlasDocument);
|
|
9638
|
+
const form = inspector?.querySelector("form[data-editor-form='event-pose']");
|
|
9639
|
+
const eventEntry = nextDocument.events.find((entry) => entry.id === eventId);
|
|
9640
|
+
const currentPose = eventEntry?.positions.find((entry) => entry.objectId === objectId);
|
|
9641
|
+
if (!form || !eventEntry || !currentPose) {
|
|
9642
|
+
return nextDocument;
|
|
9643
|
+
}
|
|
9644
|
+
const nextObjectId = readTextInput(form, "pose-object-id") || currentPose.objectId;
|
|
9645
|
+
const replacement = {
|
|
9646
|
+
objectId: nextObjectId,
|
|
9647
|
+
placement: buildPlacementFromPoseForm(form, currentPose)
|
|
9648
|
+
};
|
|
9649
|
+
const inner = parseOptionalUnit(readOptionalTextInput(form, "prop-inner"));
|
|
9650
|
+
const outer = parseOptionalUnit(readOptionalTextInput(form, "prop-outer"));
|
|
9651
|
+
if (inner) {
|
|
9652
|
+
replacement.inner = inner;
|
|
9653
|
+
}
|
|
9654
|
+
if (outer) {
|
|
9655
|
+
replacement.outer = outer;
|
|
9656
|
+
}
|
|
9657
|
+
eventEntry.positions = eventEntry.positions.filter((entry) => entry.objectId !== currentPose.objectId).concat(replacement).sort(compareEventPoses);
|
|
9658
|
+
if (eventEntry.targetObjectId !== replacement.objectId && !eventEntry.participantObjectIds.includes(replacement.objectId)) {
|
|
9659
|
+
eventEntry.participantObjectIds.push(replacement.objectId);
|
|
9660
|
+
eventEntry.participantObjectIds.sort((left, right) => left.localeCompare(right));
|
|
9661
|
+
}
|
|
9662
|
+
if (currentPose.objectId !== replacement.objectId) {
|
|
9663
|
+
selection = { kind: "event-pose", id: eventId, key: replacement.objectId };
|
|
9664
|
+
}
|
|
9665
|
+
return nextDocument;
|
|
9666
|
+
}
|
|
8797
9667
|
function buildAnnotationDocumentFromInspector(currentId) {
|
|
8798
9668
|
const nextDocument = cloneAtlasDocument(atlasDocument);
|
|
8799
9669
|
const form = inspector?.querySelector("form[data-editor-form='annotation']");
|
|
@@ -8986,7 +9856,7 @@ var WorldOrbit = (() => {
|
|
|
8986
9856
|
const atlasDocument2 = cloneAtlasDocument(options.atlasDocument);
|
|
8987
9857
|
return {
|
|
8988
9858
|
atlasDocument: atlasDocument2,
|
|
8989
|
-
source:
|
|
9859
|
+
source: formatAtlasSource(atlasDocument2),
|
|
8990
9860
|
diagnostics: collectDocumentDiagnostics(atlasDocument2)
|
|
8991
9861
|
};
|
|
8992
9862
|
}
|
|
@@ -8996,7 +9866,7 @@ var WorldOrbit = (() => {
|
|
|
8996
9866
|
const atlasDocument2 = loaded.value.atlasDocument ?? upgradeDocumentToV2(loaded.value.document);
|
|
8997
9867
|
return {
|
|
8998
9868
|
atlasDocument: atlasDocument2,
|
|
8999
|
-
source:
|
|
9869
|
+
source: formatAtlasSource(atlasDocument2),
|
|
9000
9870
|
diagnostics: mergeDiagnostics(resolveAtlasDiagnostics(atlasDocument2, loaded.diagnostics), collectDocumentDiagnostics(atlasDocument2))
|
|
9001
9871
|
};
|
|
9002
9872
|
}
|
|
@@ -9004,10 +9874,13 @@ var WorldOrbit = (() => {
|
|
|
9004
9874
|
const atlasDocument = createEmptyAtlasDocument("WorldOrbit");
|
|
9005
9875
|
return {
|
|
9006
9876
|
atlasDocument,
|
|
9007
|
-
source:
|
|
9877
|
+
source: formatAtlasSource(atlasDocument),
|
|
9008
9878
|
diagnostics: collectDocumentDiagnostics(atlasDocument)
|
|
9009
9879
|
};
|
|
9010
9880
|
}
|
|
9881
|
+
function formatAtlasSource(document2) {
|
|
9882
|
+
return formatDocument(document2, { schema: document2.version });
|
|
9883
|
+
}
|
|
9011
9884
|
function buildEditorMarkup() {
|
|
9012
9885
|
const previewOpen = shouldPreviewSectionBeOpenByDefault();
|
|
9013
9886
|
return `<section class="wo-editor-shell">
|
|
@@ -9122,6 +9995,12 @@ var WorldOrbit = (() => {
|
|
|
9122
9995
|
const badge = bucket && (bucket.errors > 0 || bucket.warnings > 0) ? `<span class="wo-editor-outline-badge${bucket.errors > 0 ? " is-error" : " is-warning"}">${bucket.errors > 0 ? bucket.errors : bucket.warnings}</span>` : "";
|
|
9123
9996
|
return `<button type="button" class="wo-editor-outline-item${key === activeKey ? " is-active" : ""}" data-path-kind="${escapeHtml3(path.kind)}"${path.id ? ` data-path-id="${escapeHtml3(path.id)}"` : ""}${path.key ? ` data-path-key="${escapeHtml3(path.key)}"` : ""}><span>${escapeHtml3(label)}</span>${badge}</button>`;
|
|
9124
9997
|
}
|
|
9998
|
+
function renderEventOutlineItems(eventEntry, activeKey, diagnosticBuckets) {
|
|
9999
|
+
return `<div class="wo-editor-outline-group">
|
|
10000
|
+
${renderOutlineButton({ kind: "event", id: eventEntry.id }, eventEntry.label || eventEntry.id, activeKey, diagnosticBuckets)}
|
|
10001
|
+
${eventEntry.positions.length > 0 ? `<div class="wo-editor-outline-children">${[...eventEntry.positions].sort(compareEventPoses).map((pose) => renderOutlineButton({ kind: "event-pose", id: eventEntry.id, key: pose.objectId }, pose.objectId, activeKey, diagnosticBuckets)).join("")}</div>` : ""}
|
|
10002
|
+
</div>`;
|
|
10003
|
+
}
|
|
9125
10004
|
function renderSystemInspector(formState) {
|
|
9126
10005
|
return `<form class="wo-editor-form" data-editor-form="system">
|
|
9127
10006
|
<h2>System</h2>
|
|
@@ -9188,6 +10067,7 @@ var WorldOrbit = (() => {
|
|
|
9188
10067
|
${renderCheckboxField("Guides", "layer-guides", viewpoint.layers.guides !== false)}
|
|
9189
10068
|
${renderCheckboxField("Orbits back", "layer-orbits-back", viewpoint.layers["orbits-back"] !== false)}
|
|
9190
10069
|
${renderCheckboxField("Orbits front", "layer-orbits-front", viewpoint.layers["orbits-front"] !== false)}
|
|
10070
|
+
${renderCheckboxField("Events", "layer-events", viewpoint.layers.events !== false)}
|
|
9191
10071
|
${renderCheckboxField("Objects", "layer-objects", viewpoint.layers.objects !== false)}
|
|
9192
10072
|
${renderCheckboxField("Labels", "layer-labels", viewpoint.layers.labels !== false)}
|
|
9193
10073
|
${renderCheckboxField("Metadata", "layer-metadata", viewpoint.layers.metadata !== false)}
|
|
@@ -9195,7 +10075,70 @@ var WorldOrbit = (() => {
|
|
|
9195
10075
|
${renderInspectorSection("viewpoint", "filter", "Filter", `${renderTextField("Filter query", "filter-query", viewpoint.filter?.query ?? "")}
|
|
9196
10076
|
${renderTextField("Filter object types", "filter-object-types", viewpoint.filter?.objectTypes.join(" ") ?? "")}
|
|
9197
10077
|
${renderTextField("Filter tags", "filter-tags", viewpoint.filter?.tags.join(" ") ?? "")}
|
|
9198
|
-
${renderTextField("Filter groups", "filter-groups", viewpoint.filter?.groupIds.join(" ") ?? "")}
|
|
10078
|
+
${renderTextField("Filter groups", "filter-groups", viewpoint.filter?.groupIds.join(" ") ?? "")}
|
|
10079
|
+
${renderTextField("Events", "viewpoint-events", viewpoint.events.join(" "))}`)}
|
|
10080
|
+
</form>`;
|
|
10081
|
+
}
|
|
10082
|
+
function renderEventInspector(formState, id) {
|
|
10083
|
+
const eventEntry = formState.events.find((entry) => entry.id === id);
|
|
10084
|
+
if (!eventEntry) {
|
|
10085
|
+
return `<p class="wo-editor-empty">Event not found.</p>`;
|
|
10086
|
+
}
|
|
10087
|
+
const linkedViewpoints = formState.viewpoints.filter((viewpoint) => viewpoint.events.includes(eventEntry.id)).map((viewpoint) => viewpoint.id).join(" ");
|
|
10088
|
+
return `<form class="wo-editor-form" data-editor-form="event">
|
|
10089
|
+
<h2>Event</h2>
|
|
10090
|
+
${renderInspectorSection("event", "basics", "Basics", `${renderTextField("ID", "event-id", eventEntry.id)}
|
|
10091
|
+
${renderTextField("Kind", "event-kind", eventEntry.kind)}
|
|
10092
|
+
${renderTextField("Label", "event-label", eventEntry.label)}
|
|
10093
|
+
${renderTextAreaField("Summary", "event-summary", eventEntry.summary ?? "")}
|
|
10094
|
+
${renderTextField("Target object", "event-target", eventEntry.targetObjectId ?? "")}
|
|
10095
|
+
${renderTextField("Participants", "event-participants", eventEntry.participantObjectIds.join(" "))}
|
|
10096
|
+
${renderTextField("Timing", "event-timing", eventEntry.timing ?? "")}
|
|
10097
|
+
${renderTextField("Visibility", "event-visibility", eventEntry.visibility ?? "")}
|
|
10098
|
+
${renderTextField("Tags", "event-tags", eventEntry.tags.join(" "))}
|
|
10099
|
+
${renderTextField("Color", "event-color", eventEntry.color ?? "")}
|
|
10100
|
+
${renderCheckboxField("Hidden", "event-hidden", eventEntry.hidden === true)}`, true)}
|
|
10101
|
+
${renderInspectorSection("event", "viewpoints", "Viewpoints", `${renderTextField("Viewpoints", "event-viewpoints", linkedViewpoints)}`)}
|
|
10102
|
+
${renderInspectorSection("event", "positions", "Positions", `${eventEntry.positions.length > 0 ? `<div class="wo-editor-inline-list">${eventEntry.positions.map((pose) => renderOutlineButton({ kind: "event-pose", id: eventEntry.id, key: pose.objectId }, pose.objectId, null, /* @__PURE__ */ new Map())).join("")}</div>` : `<p class="wo-editor-empty">No event poses yet.</p>`}
|
|
10103
|
+
<div class="wo-editor-inline-actions">
|
|
10104
|
+
<button type="button" data-editor-action="add-event-pose" data-editor-event-id="${escapeHtml3(eventEntry.id)}">Add pose</button>
|
|
10105
|
+
</div>`)}
|
|
10106
|
+
</form>`;
|
|
10107
|
+
}
|
|
10108
|
+
function renderEventPoseInspector(formState, eventId, objectId) {
|
|
10109
|
+
const eventEntry = formState.events.find((entry) => entry.id === eventId);
|
|
10110
|
+
const pose = eventEntry?.positions.find((entry) => entry.objectId === objectId);
|
|
10111
|
+
if (!eventEntry || !pose) {
|
|
10112
|
+
return `<p class="wo-editor-empty">Event pose not found.</p>`;
|
|
10113
|
+
}
|
|
10114
|
+
const placementMode = pose.placement?.mode ?? "";
|
|
10115
|
+
const placementTarget = pose.placement?.mode === "orbit" || pose.placement?.mode === "surface" || pose.placement?.mode === "at" ? pose.placement.target : "";
|
|
10116
|
+
const freeValue = pose.placement?.mode === "free" ? pose.placement.distance ? formatUnitValue3(pose.placement.distance) : pose.placement.descriptor ?? "" : "";
|
|
10117
|
+
return `<form class="wo-editor-form" data-editor-form="event-pose">
|
|
10118
|
+
<h2>Event Pose</h2>
|
|
10119
|
+
<p class="wo-editor-inline-note">Event <strong>${escapeHtml3(eventEntry.label || eventEntry.id)}</strong></p>
|
|
10120
|
+
${renderInspectorSection("event-pose", "identity", "Identity", `${renderTextField("Object", "pose-object-id", pose.objectId)}
|
|
10121
|
+
<div class="wo-editor-inline-actions">
|
|
10122
|
+
<button type="button" data-path-kind="event" data-path-id="${escapeHtml3(eventEntry.id)}">Select event</button>
|
|
10123
|
+
</div>`, true)}
|
|
10124
|
+
${renderInspectorSection("event-pose", "placement", "Placement", `${renderSelectField("Placement mode", "placement-mode", [
|
|
10125
|
+
["", "None"],
|
|
10126
|
+
["orbit", "Orbit"],
|
|
10127
|
+
["at", "At"],
|
|
10128
|
+
["surface", "Surface"],
|
|
10129
|
+
["free", "Free"]
|
|
10130
|
+
], placementMode)}
|
|
10131
|
+
${renderTextField("Placement target", "placement-target", placementTarget)}
|
|
10132
|
+
${renderTextField("Free value", "placement-free", freeValue)}
|
|
10133
|
+
${renderTextField("Distance", "placement-distance", pose.placement?.mode === "orbit" && pose.placement.distance ? formatUnitValue3(pose.placement.distance) : "")}
|
|
10134
|
+
${renderTextField("Semi-major", "placement-semiMajor", pose.placement?.mode === "orbit" && pose.placement.semiMajor ? formatUnitValue3(pose.placement.semiMajor) : "")}
|
|
10135
|
+
${renderTextField("Eccentricity", "placement-eccentricity", pose.placement?.mode === "orbit" && pose.placement.eccentricity !== void 0 ? String(pose.placement.eccentricity) : "")}
|
|
10136
|
+
${renderTextField("Period", "placement-period", pose.placement?.mode === "orbit" && pose.placement.period ? formatUnitValue3(pose.placement.period) : "")}
|
|
10137
|
+
${renderTextField("Angle", "placement-angle", pose.placement?.mode === "orbit" && pose.placement.angle ? formatUnitValue3(pose.placement.angle) : "")}
|
|
10138
|
+
${renderTextField("Inclination", "placement-inclination", pose.placement?.mode === "orbit" && pose.placement.inclination ? formatUnitValue3(pose.placement.inclination) : "")}
|
|
10139
|
+
${renderTextField("Phase", "placement-phase", pose.placement?.mode === "orbit" && pose.placement.phase ? formatUnitValue3(pose.placement.phase) : "")}
|
|
10140
|
+
${renderTextField("Inner", "prop-inner", pose.inner ? formatUnitValue3(pose.inner) : "")}
|
|
10141
|
+
${renderTextField("Outer", "prop-outer", pose.outer ? formatUnitValue3(pose.outer) : "")}`, true)}
|
|
9199
10142
|
</form>`;
|
|
9200
10143
|
}
|
|
9201
10144
|
function renderAnnotationInspector(formState, id) {
|
|
@@ -9300,13 +10243,19 @@ var WorldOrbit = (() => {
|
|
|
9300
10243
|
return form.elements.namedItem(name)?.checked ?? false;
|
|
9301
10244
|
}
|
|
9302
10245
|
function buildPlacementFromForm(form, current) {
|
|
10246
|
+
return buildPlacementFromValues(form, current.placement, current.id);
|
|
10247
|
+
}
|
|
10248
|
+
function buildPlacementFromPoseForm(form, current) {
|
|
10249
|
+
return buildPlacementFromValues(form, current.placement, current.objectId);
|
|
10250
|
+
}
|
|
10251
|
+
function buildPlacementFromValues(form, currentPlacement, fallbackTarget) {
|
|
9303
10252
|
const mode = readTextInput(form, "placement-mode");
|
|
9304
10253
|
const target = readOptionalTextInput(form, "placement-target");
|
|
9305
10254
|
switch (mode) {
|
|
9306
10255
|
case "orbit":
|
|
9307
10256
|
return {
|
|
9308
10257
|
mode,
|
|
9309
|
-
target: target ?? (
|
|
10258
|
+
target: target ?? (currentPlacement?.mode === "orbit" ? currentPlacement.target : fallbackTarget),
|
|
9310
10259
|
distance: parseOptionalUnit(readOptionalTextInput(form, "placement-distance")),
|
|
9311
10260
|
semiMajor: parseOptionalUnit(readOptionalTextInput(form, "placement-semiMajor")),
|
|
9312
10261
|
eccentricity: parseNullableNumber(readOptionalTextInput(form, "placement-eccentricity")) ?? void 0,
|
|
@@ -9318,13 +10267,13 @@ var WorldOrbit = (() => {
|
|
|
9318
10267
|
case "at":
|
|
9319
10268
|
return {
|
|
9320
10269
|
mode,
|
|
9321
|
-
target: target ??
|
|
9322
|
-
reference: parseAtReferenceString(target ??
|
|
10270
|
+
target: target ?? fallbackTarget,
|
|
10271
|
+
reference: parseAtReferenceString(target ?? fallbackTarget)
|
|
9323
10272
|
};
|
|
9324
10273
|
case "surface":
|
|
9325
10274
|
return {
|
|
9326
10275
|
mode,
|
|
9327
|
-
target: target ??
|
|
10276
|
+
target: target ?? fallbackTarget
|
|
9328
10277
|
};
|
|
9329
10278
|
case "free": {
|
|
9330
10279
|
const freeValue = readOptionalTextInput(form, "placement-free");
|
|
@@ -9455,9 +10404,48 @@ var WorldOrbit = (() => {
|
|
|
9455
10404
|
annotation.sourceObjectId = toId;
|
|
9456
10405
|
}
|
|
9457
10406
|
}
|
|
10407
|
+
for (const eventEntry of document2.events) {
|
|
10408
|
+
if (eventEntry.targetObjectId === fromId) {
|
|
10409
|
+
eventEntry.targetObjectId = toId;
|
|
10410
|
+
}
|
|
10411
|
+
eventEntry.participantObjectIds = eventEntry.participantObjectIds.map((entry) => entry === fromId ? toId : entry);
|
|
10412
|
+
for (const pose of eventEntry.positions) {
|
|
10413
|
+
if (pose.objectId === fromId) {
|
|
10414
|
+
pose.objectId = toId;
|
|
10415
|
+
}
|
|
10416
|
+
if (pose.placement?.mode === "orbit" && pose.placement.target === fromId) {
|
|
10417
|
+
pose.placement.target = toId;
|
|
10418
|
+
}
|
|
10419
|
+
if (pose.placement?.mode === "surface" && pose.placement.target === fromId) {
|
|
10420
|
+
pose.placement.target = toId;
|
|
10421
|
+
}
|
|
10422
|
+
if (pose.placement?.mode === "at") {
|
|
10423
|
+
const reference = pose.placement.reference;
|
|
10424
|
+
if (reference.kind === "anchor" && reference.objectId === fromId) {
|
|
10425
|
+
reference.objectId = toId;
|
|
10426
|
+
}
|
|
10427
|
+
if (reference.kind === "lagrange") {
|
|
10428
|
+
if (reference.primary === fromId) {
|
|
10429
|
+
reference.primary = toId;
|
|
10430
|
+
}
|
|
10431
|
+
if (reference.secondary === fromId) {
|
|
10432
|
+
reference.secondary = toId;
|
|
10433
|
+
}
|
|
10434
|
+
}
|
|
10435
|
+
pose.placement.target = formatAtReference2(reference);
|
|
10436
|
+
}
|
|
10437
|
+
}
|
|
10438
|
+
eventEntry.positions.sort(compareEventPoses);
|
|
10439
|
+
}
|
|
9458
10440
|
}
|
|
9459
10441
|
function removeSelectedNode(document2, selection) {
|
|
9460
10442
|
const next = removeAtlasDocumentNode(document2, selection);
|
|
10443
|
+
if (selection.kind === "event" && selection.id) {
|
|
10444
|
+
for (const viewpoint of next.system?.viewpoints ?? []) {
|
|
10445
|
+
viewpoint.events = viewpoint.events.filter((eventId) => eventId !== selection.id);
|
|
10446
|
+
}
|
|
10447
|
+
return next;
|
|
10448
|
+
}
|
|
9461
10449
|
if (selection.kind !== "object" || !selection.id) {
|
|
9462
10450
|
return next;
|
|
9463
10451
|
}
|
|
@@ -9492,9 +10480,45 @@ var WorldOrbit = (() => {
|
|
|
9492
10480
|
annotation.sourceObjectId = null;
|
|
9493
10481
|
}
|
|
9494
10482
|
}
|
|
10483
|
+
for (const eventEntry of next.events) {
|
|
10484
|
+
if (eventEntry.targetObjectId === selection.id) {
|
|
10485
|
+
eventEntry.targetObjectId = null;
|
|
10486
|
+
}
|
|
10487
|
+
eventEntry.participantObjectIds = eventEntry.participantObjectIds.filter((entry) => entry !== selection.id);
|
|
10488
|
+
eventEntry.positions = eventEntry.positions.filter((entry) => entry.objectId !== selection.id);
|
|
10489
|
+
for (const pose of eventEntry.positions) {
|
|
10490
|
+
if (pose.placement?.mode === "orbit" && pose.placement.target === selection.id) {
|
|
10491
|
+
pose.placement = null;
|
|
10492
|
+
}
|
|
10493
|
+
if (pose.placement?.mode === "surface" && pose.placement.target === selection.id) {
|
|
10494
|
+
pose.placement = null;
|
|
10495
|
+
}
|
|
10496
|
+
if (pose.placement?.mode === "at") {
|
|
10497
|
+
const reference = pose.placement.reference;
|
|
10498
|
+
const touchesSelection = reference.kind === "anchor" && reference.objectId === selection.id || reference.kind === "lagrange" && (reference.primary === selection.id || reference.secondary === selection.id);
|
|
10499
|
+
if (touchesSelection) {
|
|
10500
|
+
pose.placement = null;
|
|
10501
|
+
}
|
|
10502
|
+
}
|
|
10503
|
+
}
|
|
10504
|
+
}
|
|
9495
10505
|
return next;
|
|
9496
10506
|
}
|
|
9497
|
-
function
|
|
10507
|
+
function findEditablePlacementOwner(document2, path, objectId) {
|
|
10508
|
+
if (path.kind === "event-pose" && path.id && path.key) {
|
|
10509
|
+
const pose = findEventPose2(document2, path.id, path.key);
|
|
10510
|
+
if (pose?.placement) {
|
|
10511
|
+
return { placement: pose.placement };
|
|
10512
|
+
}
|
|
10513
|
+
return null;
|
|
10514
|
+
}
|
|
10515
|
+
const object = findObject2(document2, objectId);
|
|
10516
|
+
if (object?.placement) {
|
|
10517
|
+
return { placement: object.placement };
|
|
10518
|
+
}
|
|
10519
|
+
return null;
|
|
10520
|
+
}
|
|
10521
|
+
function updateOrbitPhase(document2, path, objectId, details, pointer) {
|
|
9498
10522
|
const orbit = details.orbit;
|
|
9499
10523
|
if (!orbit || details.object.placement?.mode !== "orbit") {
|
|
9500
10524
|
return document2;
|
|
@@ -9505,17 +10529,17 @@ var WorldOrbit = (() => {
|
|
|
9505
10529
|
const radians = Math.atan2((unrotated.y - orbit.cy) / Math.max(ry, 1), (unrotated.x - orbit.cx) / Math.max(rx, 1));
|
|
9506
10530
|
const phaseDeg = normalizeDegrees(radians * 180 / Math.PI);
|
|
9507
10531
|
const next = cloneAtlasDocument(document2);
|
|
9508
|
-
const
|
|
9509
|
-
if (!
|
|
10532
|
+
const placementOwner = findEditablePlacementOwner(next, path, objectId);
|
|
10533
|
+
if (!placementOwner || placementOwner.placement.mode !== "orbit") {
|
|
9510
10534
|
return document2;
|
|
9511
10535
|
}
|
|
9512
|
-
|
|
10536
|
+
placementOwner.placement.phase = {
|
|
9513
10537
|
value: roundNumber(phaseDeg, 2),
|
|
9514
10538
|
unit: "deg"
|
|
9515
10539
|
};
|
|
9516
10540
|
return next;
|
|
9517
10541
|
}
|
|
9518
|
-
function updateOrbitRadius(document2, objectId, details, pointer, dragContext) {
|
|
10542
|
+
function updateOrbitRadius(document2, path, objectId, details, pointer, dragContext) {
|
|
9519
10543
|
const orbit = details.orbit;
|
|
9520
10544
|
if (!orbit || details.object.placement?.mode !== "orbit" || !dragContext) {
|
|
9521
10545
|
return document2;
|
|
@@ -9525,47 +10549,47 @@ var WorldOrbit = (() => {
|
|
|
9525
10549
|
const nextBaseRadius = Math.max(nextDisplayedRadius - dragContext.radiusOffsetPx, dragContext.innerPx);
|
|
9526
10550
|
const nextMetric = orbitRadiusPxToMetric(nextBaseRadius, dragContext.innerPx, dragContext.stepPx);
|
|
9527
10551
|
const next = cloneAtlasDocument(document2);
|
|
9528
|
-
const
|
|
9529
|
-
if (!
|
|
10552
|
+
const placementOwner = findEditablePlacementOwner(next, path, objectId);
|
|
10553
|
+
if (!placementOwner || placementOwner.placement.mode !== "orbit") {
|
|
9530
10554
|
return document2;
|
|
9531
10555
|
}
|
|
9532
|
-
const currentValue =
|
|
10556
|
+
const currentValue = placementOwner.placement.semiMajor ?? placementOwner.placement.distance ?? {
|
|
9533
10557
|
value: 1,
|
|
9534
10558
|
unit: "au"
|
|
9535
10559
|
};
|
|
9536
10560
|
const scaled = distanceMetricToUnitValue(Math.max(nextMetric, 0), dragContext.preferredUnit ?? currentValue.unit);
|
|
9537
|
-
if (
|
|
9538
|
-
|
|
10561
|
+
if (placementOwner.placement.semiMajor) {
|
|
10562
|
+
placementOwner.placement.semiMajor = scaled;
|
|
9539
10563
|
} else {
|
|
9540
|
-
|
|
10564
|
+
placementOwner.placement.distance = scaled;
|
|
9541
10565
|
}
|
|
9542
10566
|
return next;
|
|
9543
10567
|
}
|
|
9544
|
-
function updateAtReference(document2, objectId, scene, pointer) {
|
|
10568
|
+
function updateAtReference(document2, path, objectId, scene, pointer) {
|
|
9545
10569
|
const candidate = findNearestAtCandidate(scene, objectId, pointer);
|
|
9546
10570
|
if (!candidate) {
|
|
9547
10571
|
return document2;
|
|
9548
10572
|
}
|
|
9549
10573
|
const next = cloneAtlasDocument(document2);
|
|
9550
|
-
const
|
|
9551
|
-
if (!
|
|
10574
|
+
const placementOwner = findEditablePlacementOwner(next, path, objectId);
|
|
10575
|
+
if (!placementOwner || placementOwner.placement.mode !== "at") {
|
|
9552
10576
|
return document2;
|
|
9553
10577
|
}
|
|
9554
|
-
|
|
9555
|
-
|
|
10578
|
+
placementOwner.placement.reference = candidate.reference;
|
|
10579
|
+
placementOwner.placement.target = formatAtReference2(candidate.reference);
|
|
9556
10580
|
return next;
|
|
9557
10581
|
}
|
|
9558
|
-
function updateSurfaceTarget(document2, objectId, scene, pointer) {
|
|
10582
|
+
function updateSurfaceTarget(document2, path, objectId, scene, pointer) {
|
|
9559
10583
|
const target = findNearestSceneObject(scene, objectId, pointer, (entry) => SURFACE_TARGET_TYPES3.has(entry.object.type));
|
|
9560
10584
|
if (!target) {
|
|
9561
10585
|
return document2;
|
|
9562
10586
|
}
|
|
9563
10587
|
const next = cloneAtlasDocument(document2);
|
|
9564
|
-
const
|
|
9565
|
-
if (!
|
|
10588
|
+
const placementOwner = findEditablePlacementOwner(next, path, objectId);
|
|
10589
|
+
if (!placementOwner || placementOwner.placement.mode !== "surface") {
|
|
9566
10590
|
return document2;
|
|
9567
10591
|
}
|
|
9568
|
-
|
|
10592
|
+
placementOwner.placement.target = target.objectId;
|
|
9569
10593
|
return next;
|
|
9570
10594
|
}
|
|
9571
10595
|
function createOrbitRadiusDragContext(document2, scene, details) {
|
|
@@ -9573,7 +10597,7 @@ var WorldOrbit = (() => {
|
|
|
9573
10597
|
return null;
|
|
9574
10598
|
}
|
|
9575
10599
|
const targetId = details.object.placement.target;
|
|
9576
|
-
const siblingCount =
|
|
10600
|
+
const siblingCount = scene.objects.filter((entry) => entry.object.placement?.mode === "orbit" && entry.object.placement.target === targetId && !entry.hidden).length;
|
|
9577
10601
|
const spacingFactor = layoutPresetSpacingForScene(scene.layoutPreset);
|
|
9578
10602
|
const stepPx = (siblingCount > 2 ? 54 : 64) * spacingFactor * scene.scaleModel.orbitDistanceMultiplier;
|
|
9579
10603
|
const innerPx = details.parent.radius + 56 * spacingFactor * scene.scaleModel.orbitDistanceMultiplier;
|
|
@@ -9588,28 +10612,28 @@ var WorldOrbit = (() => {
|
|
|
9588
10612
|
preferredUnit: currentValue?.unit ?? null
|
|
9589
10613
|
};
|
|
9590
10614
|
}
|
|
9591
|
-
function updateFreeDistance(document2, objectId, scene, details, pointer) {
|
|
10615
|
+
function updateFreeDistance(document2, path, objectId, scene, details, pointer) {
|
|
9592
10616
|
if (details.object.placement?.mode !== "free") {
|
|
9593
10617
|
return document2;
|
|
9594
10618
|
}
|
|
9595
10619
|
const railX = scene.width - scene.padding - 140;
|
|
9596
10620
|
const offsetPx = Math.max(0, railX - pointer.x);
|
|
9597
10621
|
const next = cloneAtlasDocument(document2);
|
|
9598
|
-
const
|
|
9599
|
-
if (!
|
|
10622
|
+
const placementOwner = findEditablePlacementOwner(next, path, objectId);
|
|
10623
|
+
if (!placementOwner || placementOwner.placement.mode !== "free") {
|
|
9600
10624
|
return document2;
|
|
9601
10625
|
}
|
|
9602
|
-
const preferredUnit = normalizeFreeDistanceUnit(
|
|
10626
|
+
const preferredUnit = normalizeFreeDistanceUnit(placementOwner.placement.distance?.unit ?? null);
|
|
9603
10627
|
const metric = offsetPx / Math.max(FREE_DISTANCE_PIXEL_FACTOR * scene.scaleModel.freePlacementMultiplier, 1);
|
|
9604
10628
|
if (metric < 0.01) {
|
|
9605
|
-
|
|
9606
|
-
if (!
|
|
9607
|
-
delete
|
|
10629
|
+
placementOwner.placement.distance = void 0;
|
|
10630
|
+
if (!placementOwner.placement.descriptor) {
|
|
10631
|
+
delete placementOwner.placement.descriptor;
|
|
9608
10632
|
}
|
|
9609
10633
|
return next;
|
|
9610
10634
|
}
|
|
9611
|
-
|
|
9612
|
-
delete
|
|
10635
|
+
placementOwner.placement.distance = distanceMetricToUnitValue(metric, preferredUnit);
|
|
10636
|
+
delete placementOwner.placement.descriptor;
|
|
9613
10637
|
return next;
|
|
9614
10638
|
}
|
|
9615
10639
|
function findNearestSceneObject(scene, selectedObjectId, pointer, predicate = () => true) {
|
|
@@ -9881,9 +10905,60 @@ var WorldOrbit = (() => {
|
|
|
9881
10905
|
return ["viewpoint-zoom"];
|
|
9882
10906
|
case "rotationDeg":
|
|
9883
10907
|
return ["viewpoint-rotation"];
|
|
10908
|
+
case "events":
|
|
10909
|
+
return ["viewpoint-events"];
|
|
9884
10910
|
default:
|
|
9885
10911
|
return [];
|
|
9886
10912
|
}
|
|
10913
|
+
case "event":
|
|
10914
|
+
switch (field) {
|
|
10915
|
+
case "id":
|
|
10916
|
+
return ["event-id"];
|
|
10917
|
+
case "kind":
|
|
10918
|
+
return ["event-kind"];
|
|
10919
|
+
case "label":
|
|
10920
|
+
return ["event-label"];
|
|
10921
|
+
case "summary":
|
|
10922
|
+
return ["event-summary"];
|
|
10923
|
+
case "targetObjectId":
|
|
10924
|
+
case "target":
|
|
10925
|
+
return ["event-target"];
|
|
10926
|
+
case "participantObjectIds":
|
|
10927
|
+
case "participants":
|
|
10928
|
+
return ["event-participants"];
|
|
10929
|
+
case "timing":
|
|
10930
|
+
return ["event-timing"];
|
|
10931
|
+
case "visibility":
|
|
10932
|
+
return ["event-visibility"];
|
|
10933
|
+
case "tags":
|
|
10934
|
+
return ["event-tags"];
|
|
10935
|
+
case "color":
|
|
10936
|
+
return ["event-color"];
|
|
10937
|
+
case "hidden":
|
|
10938
|
+
return ["event-hidden"];
|
|
10939
|
+
default:
|
|
10940
|
+
return [];
|
|
10941
|
+
}
|
|
10942
|
+
case "event-pose":
|
|
10943
|
+
if (field === "objectId") {
|
|
10944
|
+
return ["pose-object-id"];
|
|
10945
|
+
}
|
|
10946
|
+
if (field === "placement") {
|
|
10947
|
+
return ["placement-mode"];
|
|
10948
|
+
}
|
|
10949
|
+
if (field === "reference" || field === "target") {
|
|
10950
|
+
return ["placement-target"];
|
|
10951
|
+
}
|
|
10952
|
+
if (field === "descriptor") {
|
|
10953
|
+
return ["placement-free"];
|
|
10954
|
+
}
|
|
10955
|
+
if (PLACEMENT_DIAGNOSTIC_FIELDS.has(field)) {
|
|
10956
|
+
return [`placement-${field}`];
|
|
10957
|
+
}
|
|
10958
|
+
if (field === "inner" || field === "outer") {
|
|
10959
|
+
return [`prop-${field}`];
|
|
10960
|
+
}
|
|
10961
|
+
return [];
|
|
9887
10962
|
case "annotation":
|
|
9888
10963
|
switch (field) {
|
|
9889
10964
|
case "id":
|
|
@@ -9969,6 +11044,10 @@ var WorldOrbit = (() => {
|
|
|
9969
11044
|
return `Metadata: ${path.key ?? ""}`;
|
|
9970
11045
|
case "group":
|
|
9971
11046
|
return `Group: ${path.id ?? ""}`;
|
|
11047
|
+
case "event":
|
|
11048
|
+
return `Event: ${path.id ?? ""}`;
|
|
11049
|
+
case "event-pose":
|
|
11050
|
+
return `Event Pose: ${path.id ?? ""} / ${path.key ?? ""}`;
|
|
9972
11051
|
case "object":
|
|
9973
11052
|
return `Object: ${path.id ?? ""}`;
|
|
9974
11053
|
case "viewpoint":
|
|
@@ -9980,11 +11059,70 @@ var WorldOrbit = (() => {
|
|
|
9980
11059
|
}
|
|
9981
11060
|
}
|
|
9982
11061
|
function selectionKey(path) {
|
|
9983
|
-
return path ? `${path.kind}:${path.id ?? path.key ?? ""}` : null;
|
|
11062
|
+
return path ? `${path.kind}:${path.id ?? ""}:${path.key ?? ""}` : null;
|
|
11063
|
+
}
|
|
11064
|
+
function selectionEventId(path) {
|
|
11065
|
+
if (!path) {
|
|
11066
|
+
return null;
|
|
11067
|
+
}
|
|
11068
|
+
return path.kind === "event" || path.kind === "event-pose" ? path.id ?? null : null;
|
|
9984
11069
|
}
|
|
9985
11070
|
function compareObjects2(left, right) {
|
|
9986
11071
|
return left.id.localeCompare(right.id);
|
|
9987
11072
|
}
|
|
11073
|
+
function compareEvents(left, right) {
|
|
11074
|
+
return left.id.localeCompare(right.id);
|
|
11075
|
+
}
|
|
11076
|
+
function compareEventPoses(left, right) {
|
|
11077
|
+
return left.objectId.localeCompare(right.objectId);
|
|
11078
|
+
}
|
|
11079
|
+
function findEvent2(document2, eventId) {
|
|
11080
|
+
return document2.events.find((entry) => entry.id === eventId) ?? null;
|
|
11081
|
+
}
|
|
11082
|
+
function findEventPose2(document2, eventId, objectId) {
|
|
11083
|
+
return findEvent2(document2, eventId)?.positions.find((entry) => entry.objectId === objectId) ?? null;
|
|
11084
|
+
}
|
|
11085
|
+
function findObject2(document2, objectId) {
|
|
11086
|
+
return document2.objects.find((entry) => entry.id === objectId) ?? null;
|
|
11087
|
+
}
|
|
11088
|
+
function addEventPose(document2, eventId) {
|
|
11089
|
+
const next = cloneAtlasDocument(document2);
|
|
11090
|
+
const eventEntry = next.events.find((entry) => entry.id === eventId);
|
|
11091
|
+
if (!eventEntry) {
|
|
11092
|
+
return document2;
|
|
11093
|
+
}
|
|
11094
|
+
const baseObject = next.objects.find((object) => !eventEntry.positions.some((pose) => pose.objectId === object.id)) ?? next.objects[0];
|
|
11095
|
+
if (!baseObject) {
|
|
11096
|
+
return document2;
|
|
11097
|
+
}
|
|
11098
|
+
if (eventEntry.targetObjectId !== baseObject.id && !eventEntry.participantObjectIds.includes(baseObject.id)) {
|
|
11099
|
+
eventEntry.participantObjectIds.push(baseObject.id);
|
|
11100
|
+
eventEntry.participantObjectIds.sort((left, right) => left.localeCompare(right));
|
|
11101
|
+
}
|
|
11102
|
+
eventEntry.positions.push(createEventPoseFromObject(baseObject));
|
|
11103
|
+
eventEntry.positions.sort(compareEventPoses);
|
|
11104
|
+
return next;
|
|
11105
|
+
}
|
|
11106
|
+
function createEventPoseFromObject(object) {
|
|
11107
|
+
return {
|
|
11108
|
+
objectId: object.id,
|
|
11109
|
+
placement: object.placement ? structuredClone(object.placement) : null,
|
|
11110
|
+
inner: readUnitValue(object.properties.inner),
|
|
11111
|
+
outer: readUnitValue(object.properties.outer)
|
|
11112
|
+
};
|
|
11113
|
+
}
|
|
11114
|
+
function syncEventViewpointReferences(document2, previousEventId, nextEventId, viewpointIds) {
|
|
11115
|
+
const desired = new Set(viewpointIds);
|
|
11116
|
+
for (const viewpoint of document2.system?.viewpoints ?? []) {
|
|
11117
|
+
const currentIds = new Set(viewpoint.events);
|
|
11118
|
+
currentIds.delete(previousEventId);
|
|
11119
|
+
currentIds.delete(nextEventId);
|
|
11120
|
+
if (desired.has(viewpoint.id)) {
|
|
11121
|
+
currentIds.add(nextEventId);
|
|
11122
|
+
}
|
|
11123
|
+
viewpoint.events = [...currentIds].sort((left, right) => left.localeCompare(right));
|
|
11124
|
+
}
|
|
11125
|
+
}
|
|
9988
11126
|
function createUniqueId(prefix, existing) {
|
|
9989
11127
|
const safePrefix = prefix.trim() || "item";
|
|
9990
11128
|
let counter = 1;
|
|
@@ -10013,6 +11151,9 @@ var WorldOrbit = (() => {
|
|
|
10013
11151
|
function readUnitProperty(value) {
|
|
10014
11152
|
return value && typeof value === "object" && "value" in value ? formatUnitValue3(value) : "";
|
|
10015
11153
|
}
|
|
11154
|
+
function readUnitValue(value) {
|
|
11155
|
+
return value && typeof value === "object" && "value" in value ? value : void 0;
|
|
11156
|
+
}
|
|
10016
11157
|
function readNumberProperty(value) {
|
|
10017
11158
|
return typeof value === "number" ? String(value) : "";
|
|
10018
11159
|
}
|
|
@@ -10318,6 +11459,12 @@ var WorldOrbit = (() => {
|
|
|
10318
11459
|
.wo-editor-overlay-diagnostic-warning { border: 1px solid rgba(240, 180, 100, 0.24); }
|
|
10319
11460
|
.wo-editor-outline { display: grid; gap: 14px; }
|
|
10320
11461
|
.wo-editor-outline-section { display: grid; gap: 8px; }
|
|
11462
|
+
.wo-editor-outline-group { display: grid; gap: 6px; }
|
|
11463
|
+
.wo-editor-outline-children {
|
|
11464
|
+
display: grid;
|
|
11465
|
+
gap: 6px;
|
|
11466
|
+
padding-left: 16px;
|
|
11467
|
+
}
|
|
10321
11468
|
.wo-editor-outline-section h3 {
|
|
10322
11469
|
margin: 0;
|
|
10323
11470
|
color: rgba(237,246,255,0.68);
|
|
@@ -10357,6 +11504,27 @@ var WorldOrbit = (() => {
|
|
|
10357
11504
|
background: rgba(255, 120, 120, 0.18);
|
|
10358
11505
|
color: #ffb2b2;
|
|
10359
11506
|
}
|
|
11507
|
+
.wo-editor-inline-list { display: grid; gap: 8px; }
|
|
11508
|
+
.wo-editor-inline-actions {
|
|
11509
|
+
display: flex;
|
|
11510
|
+
flex-wrap: wrap;
|
|
11511
|
+
gap: 10px;
|
|
11512
|
+
margin-top: 12px;
|
|
11513
|
+
}
|
|
11514
|
+
.wo-editor-inline-actions button {
|
|
11515
|
+
border: 1px solid rgba(255,255,255,0.14);
|
|
11516
|
+
border-radius: 999px;
|
|
11517
|
+
background: rgba(255,255,255,0.06);
|
|
11518
|
+
color: #edf6ff;
|
|
11519
|
+
cursor: pointer;
|
|
11520
|
+
font: 600 12px/1.2 "Segoe UI Variable", "Segoe UI", sans-serif;
|
|
11521
|
+
padding: 8px 12px;
|
|
11522
|
+
}
|
|
11523
|
+
.wo-editor-inline-note {
|
|
11524
|
+
margin: 0 0 12px;
|
|
11525
|
+
color: rgba(237,246,255,0.72);
|
|
11526
|
+
font: 500 12px/1.5 "Segoe UI Variable", "Segoe UI", sans-serif;
|
|
11527
|
+
}
|
|
10360
11528
|
.wo-editor-diagnostics { display: grid; gap: 10px; }
|
|
10361
11529
|
.wo-editor-diagnostic {
|
|
10362
11530
|
display: grid;
|