worldorbit 2.5.16 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -15
- package/dist/browser/core/dist/index.js +1228 -110
- package/dist/browser/editor/dist/index.js +1896 -180
- package/dist/browser/markdown/dist/index.js +1071 -99
- package/dist/browser/viewer/dist/index.js +1127 -113
- package/dist/unpkg/core/dist/index.js +1228 -110
- package/dist/unpkg/editor/dist/index.js +1896 -180
- package/dist/unpkg/markdown/dist/index.js +1071 -99
- package/dist/unpkg/viewer/dist/index.js +1127 -113
- package/dist/unpkg/worldorbit-core.min.js +12 -12
- package/dist/unpkg/worldorbit-editor.min.js +295 -203
- package/dist/unpkg/worldorbit-markdown.min.js +66 -58
- package/dist/unpkg/worldorbit-viewer.min.js +84 -76
- package/dist/unpkg/worldorbit.js +1304 -124
- package/dist/unpkg/worldorbit.min.js +88 -80
- package/package.json +1 -1
- package/packages/core/dist/atlas-edit.js +75 -1
- package/packages/core/dist/atlas-validate.js +211 -8
- package/packages/core/dist/draft-parse.js +401 -22
- package/packages/core/dist/draft.d.ts +5 -2
- package/packages/core/dist/draft.js +103 -8
- package/packages/core/dist/format.js +99 -6
- package/packages/core/dist/load.js +9 -2
- package/packages/core/dist/normalize.js +1 -0
- package/packages/core/dist/scene.js +400 -64
- package/packages/core/dist/types.d.ts +60 -4
- package/packages/editor/dist/editor.js +702 -65
- package/packages/editor/dist/types.d.ts +3 -1
- package/packages/viewer/dist/atlas-state.js +11 -2
- package/packages/viewer/dist/atlas-viewer.js +19 -7
- package/packages/viewer/dist/render.js +31 -2
- package/packages/viewer/dist/theme.js +1 -0
- package/packages/viewer/dist/tooltip.js +9 -0
- package/packages/viewer/dist/types.d.ts +12 -2
- package/packages/viewer/dist/viewer.js +28 -1
|
@@ -565,6 +565,7 @@ var WorldOrbit = (() => {
|
|
|
565
565
|
system,
|
|
566
566
|
groups: [],
|
|
567
567
|
relations: [],
|
|
568
|
+
events: [],
|
|
568
569
|
objects
|
|
569
570
|
};
|
|
570
571
|
}
|
|
@@ -944,12 +945,16 @@ var WorldOrbit = (() => {
|
|
|
944
945
|
const height = frame.height;
|
|
945
946
|
const padding = frame.padding;
|
|
946
947
|
const layoutPreset = resolveLayoutPreset(document2);
|
|
947
|
-
const
|
|
948
|
+
const schemaProjection = resolveProjection(document2, options.projection);
|
|
949
|
+
const camera = normalizeViewCamera(options.camera ?? null);
|
|
950
|
+
const renderProjection = resolveRenderProjection(schemaProjection, camera);
|
|
948
951
|
const scaleModel = resolveScaleModel(layoutPreset, options.scaleModel);
|
|
949
952
|
const spacingFactor = layoutPresetSpacing(layoutPreset);
|
|
950
953
|
const systemId = document2.system?.id ?? null;
|
|
951
|
-
const
|
|
952
|
-
const
|
|
954
|
+
const activeEventId = options.activeEventId ?? null;
|
|
955
|
+
const effectiveObjects = createEffectiveObjects(document2.objects, document2.events ?? [], activeEventId);
|
|
956
|
+
const objectMap = new Map(effectiveObjects.map((object) => [object.id, object]));
|
|
957
|
+
const relationships = buildSceneRelationships(effectiveObjects, objectMap);
|
|
953
958
|
const positions = /* @__PURE__ */ new Map();
|
|
954
959
|
const orbitDrafts = [];
|
|
955
960
|
const leaderDrafts = [];
|
|
@@ -958,7 +963,7 @@ var WorldOrbit = (() => {
|
|
|
958
963
|
const atObjects = [];
|
|
959
964
|
const surfaceChildren = /* @__PURE__ */ new Map();
|
|
960
965
|
const orbitChildren = /* @__PURE__ */ new Map();
|
|
961
|
-
for (const object of
|
|
966
|
+
for (const object of effectiveObjects) {
|
|
962
967
|
const placement = object.placement;
|
|
963
968
|
if (!placement) {
|
|
964
969
|
rootObjects.push(object);
|
|
@@ -985,7 +990,7 @@ var WorldOrbit = (() => {
|
|
|
985
990
|
surfaceChildren,
|
|
986
991
|
objectMap,
|
|
987
992
|
spacingFactor,
|
|
988
|
-
projection,
|
|
993
|
+
projection: renderProjection,
|
|
989
994
|
scaleModel
|
|
990
995
|
};
|
|
991
996
|
const primaryRoot = rootObjects.find((object) => object.type === "star") ?? rootObjects[0] ?? null;
|
|
@@ -997,7 +1002,7 @@ var WorldOrbit = (() => {
|
|
|
997
1002
|
const rootRingRadius = Math.min(width, height) * 0.28 * spacingFactor * scaleModel.orbitDistanceMultiplier;
|
|
998
1003
|
secondaryRoots.forEach((object, index) => {
|
|
999
1004
|
const angle = angleForIndex(index, secondaryRoots.length, -Math.PI / 2);
|
|
1000
|
-
const offset = projectPolarOffset(angle, rootRingRadius,
|
|
1005
|
+
const offset = projectPolarOffset(angle, rootRingRadius, renderProjection, 1);
|
|
1001
1006
|
placeObject(object, centerX + offset.x, centerY + offset.y, 0, positions, orbitDrafts, leaderDrafts, context);
|
|
1002
1007
|
});
|
|
1003
1008
|
}
|
|
@@ -1053,38 +1058,48 @@ var WorldOrbit = (() => {
|
|
|
1053
1058
|
const objects = [...positions.values()].map((position) => createSceneObject(position, scaleModel, relationships));
|
|
1054
1059
|
const orbitVisuals = orbitDrafts.map((draft) => createOrbitVisual(draft, relationships.groupIds.get(draft.object.id) ?? null));
|
|
1055
1060
|
const leaders = leaderDrafts.map((draft) => createLeaderLine(draft));
|
|
1056
|
-
const labels = createSceneLabels(objects, height, scaleModel.labelMultiplier);
|
|
1061
|
+
const labels = createSceneLabels(objects, width, height, scaleModel.labelMultiplier);
|
|
1057
1062
|
const relations = createSceneRelations(document2, objects);
|
|
1058
|
-
const
|
|
1059
|
-
const
|
|
1063
|
+
const events = createSceneEvents(document2.events ?? [], objects, activeEventId);
|
|
1064
|
+
const layers = createSceneLayers(orbitVisuals, relations, events, leaders, objects, labels);
|
|
1065
|
+
const groups = createSceneGroups(objects, orbitVisuals, leaders, labels, relationships, scaleModel.labelMultiplier);
|
|
1060
1066
|
const semanticGroups = createSceneSemanticGroups(document2, objects);
|
|
1061
|
-
const viewpoints = createSceneViewpoints(document2,
|
|
1062
|
-
const contentBounds = calculateContentBounds(width, height, objects, orbitVisuals, leaders, labels);
|
|
1067
|
+
const viewpoints = createSceneViewpoints(document2, schemaProjection, frame.preset, relationships, objectMap);
|
|
1068
|
+
const contentBounds = calculateContentBounds(width, height, objects, orbitVisuals, leaders, labels, scaleModel.labelMultiplier);
|
|
1063
1069
|
return {
|
|
1064
1070
|
width,
|
|
1065
1071
|
height,
|
|
1066
1072
|
padding,
|
|
1067
1073
|
renderPreset: frame.preset,
|
|
1068
|
-
projection,
|
|
1074
|
+
projection: schemaProjection,
|
|
1075
|
+
renderProjection,
|
|
1076
|
+
camera,
|
|
1069
1077
|
scaleModel,
|
|
1070
1078
|
title: String(document2.system?.title ?? document2.system?.properties.title ?? document2.system?.id ?? "WorldOrbit") || "WorldOrbit",
|
|
1071
|
-
subtitle:
|
|
1079
|
+
subtitle: buildSceneSubtitle(schemaProjection, renderProjection, layoutPreset, camera),
|
|
1072
1080
|
systemId,
|
|
1073
|
-
viewMode:
|
|
1081
|
+
viewMode: schemaProjection,
|
|
1074
1082
|
layoutPreset,
|
|
1075
1083
|
metadata: {
|
|
1076
1084
|
format: document2.format,
|
|
1077
1085
|
version: document2.version,
|
|
1078
|
-
view:
|
|
1086
|
+
view: schemaProjection,
|
|
1087
|
+
renderProjection,
|
|
1079
1088
|
scale: String(document2.system?.properties.scale ?? layoutPreset),
|
|
1080
1089
|
units: String(document2.system?.properties.units ?? "mixed"),
|
|
1081
|
-
preset: frame.preset ?? "custom"
|
|
1090
|
+
preset: frame.preset ?? "custom",
|
|
1091
|
+
...camera?.azimuth !== null ? { "camera.azimuth": String(camera?.azimuth) } : {},
|
|
1092
|
+
...camera?.elevation !== null ? { "camera.elevation": String(camera?.elevation) } : {},
|
|
1093
|
+
...camera?.roll !== null ? { "camera.roll": String(camera?.roll) } : {},
|
|
1094
|
+
...camera?.distance !== null ? { "camera.distance": String(camera?.distance) } : {}
|
|
1082
1095
|
},
|
|
1083
1096
|
contentBounds,
|
|
1084
1097
|
layers,
|
|
1085
1098
|
groups,
|
|
1086
1099
|
semanticGroups,
|
|
1087
1100
|
viewpoints,
|
|
1101
|
+
events,
|
|
1102
|
+
activeEventId,
|
|
1088
1103
|
objects,
|
|
1089
1104
|
orbitVisuals,
|
|
1090
1105
|
relations,
|
|
@@ -1103,6 +1118,56 @@ var WorldOrbit = (() => {
|
|
|
1103
1118
|
y: center.y + dx * sin + dy * cos
|
|
1104
1119
|
};
|
|
1105
1120
|
}
|
|
1121
|
+
function createEffectiveObjects(objects, events, activeEventId) {
|
|
1122
|
+
const cloned = objects.map((object) => structuredClone(object));
|
|
1123
|
+
if (!activeEventId) {
|
|
1124
|
+
return cloned;
|
|
1125
|
+
}
|
|
1126
|
+
const activeEvent = events.find((event) => event.id === activeEventId);
|
|
1127
|
+
if (!activeEvent) {
|
|
1128
|
+
return cloned;
|
|
1129
|
+
}
|
|
1130
|
+
const objectMap = new Map(cloned.map((object) => [object.id, object]));
|
|
1131
|
+
const referencedIds = /* @__PURE__ */ new Set([
|
|
1132
|
+
...activeEvent.targetObjectId ? [activeEvent.targetObjectId] : [],
|
|
1133
|
+
...activeEvent.participantObjectIds,
|
|
1134
|
+
...activeEvent.positions.map((pose) => pose.objectId)
|
|
1135
|
+
]);
|
|
1136
|
+
for (const objectId of referencedIds) {
|
|
1137
|
+
const object = objectMap.get(objectId);
|
|
1138
|
+
if (!object) {
|
|
1139
|
+
continue;
|
|
1140
|
+
}
|
|
1141
|
+
if (activeEvent.epoch) {
|
|
1142
|
+
object.epoch = activeEvent.epoch;
|
|
1143
|
+
}
|
|
1144
|
+
if (activeEvent.referencePlane) {
|
|
1145
|
+
object.referencePlane = activeEvent.referencePlane;
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
for (const pose of activeEvent.positions) {
|
|
1149
|
+
const object = objectMap.get(pose.objectId);
|
|
1150
|
+
if (!object) {
|
|
1151
|
+
continue;
|
|
1152
|
+
}
|
|
1153
|
+
if (pose.placement) {
|
|
1154
|
+
object.placement = structuredClone(pose.placement);
|
|
1155
|
+
}
|
|
1156
|
+
if (pose.inner) {
|
|
1157
|
+
object.properties.inner = { ...pose.inner };
|
|
1158
|
+
}
|
|
1159
|
+
if (pose.outer) {
|
|
1160
|
+
object.properties.outer = { ...pose.outer };
|
|
1161
|
+
}
|
|
1162
|
+
if (pose.epoch) {
|
|
1163
|
+
object.epoch = pose.epoch;
|
|
1164
|
+
}
|
|
1165
|
+
if (pose.referencePlane) {
|
|
1166
|
+
object.referencePlane = pose.referencePlane;
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
return cloned;
|
|
1170
|
+
}
|
|
1106
1171
|
function resolveLayoutPreset(document2) {
|
|
1107
1172
|
const rawScale = String(document2.system?.properties.scale ?? "balanced").toLowerCase();
|
|
1108
1173
|
switch (rawScale) {
|
|
@@ -1139,10 +1204,59 @@ var WorldOrbit = (() => {
|
|
|
1139
1204
|
}
|
|
1140
1205
|
}
|
|
1141
1206
|
function resolveProjection(document2, projection) {
|
|
1142
|
-
if (projection === "topdown" || projection === "isometric") {
|
|
1207
|
+
if (projection === "topdown" || projection === "isometric" || projection === "orthographic" || projection === "perspective") {
|
|
1143
1208
|
return projection;
|
|
1144
1209
|
}
|
|
1145
|
-
|
|
1210
|
+
const documentView = String(document2.system?.properties.view ?? "topdown").toLowerCase();
|
|
1211
|
+
return parseViewProjection(documentView) ?? "topdown";
|
|
1212
|
+
}
|
|
1213
|
+
function resolveRenderProjection(projection, camera) {
|
|
1214
|
+
switch (projection) {
|
|
1215
|
+
case "topdown":
|
|
1216
|
+
return "topdown";
|
|
1217
|
+
case "isometric":
|
|
1218
|
+
return "isometric";
|
|
1219
|
+
case "orthographic":
|
|
1220
|
+
return camera && (camera.azimuth !== null || camera.elevation !== null || camera.roll !== null) ? "isometric" : "topdown";
|
|
1221
|
+
case "perspective":
|
|
1222
|
+
return "isometric";
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
function normalizeViewCamera(camera) {
|
|
1226
|
+
if (!camera) {
|
|
1227
|
+
return null;
|
|
1228
|
+
}
|
|
1229
|
+
const normalized = {
|
|
1230
|
+
azimuth: normalizeFiniteCameraValue(camera.azimuth),
|
|
1231
|
+
elevation: normalizeFiniteCameraValue(camera.elevation),
|
|
1232
|
+
roll: normalizeFiniteCameraValue(camera.roll),
|
|
1233
|
+
distance: normalizePositiveCameraDistance(camera.distance)
|
|
1234
|
+
};
|
|
1235
|
+
return normalized.azimuth !== null || normalized.elevation !== null || normalized.roll !== null || normalized.distance !== null ? normalized : null;
|
|
1236
|
+
}
|
|
1237
|
+
function normalizeFiniteCameraValue(value) {
|
|
1238
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
1239
|
+
}
|
|
1240
|
+
function normalizePositiveCameraDistance(value) {
|
|
1241
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : null;
|
|
1242
|
+
}
|
|
1243
|
+
function buildSceneSubtitle(projection, renderProjection, layoutPreset, camera) {
|
|
1244
|
+
const parts = [`${capitalizeLabel(projection)} view`, `${capitalizeLabel(layoutPreset)} layout`];
|
|
1245
|
+
if (projection !== renderProjection) {
|
|
1246
|
+
parts.push(`2D ${renderProjection} fallback`);
|
|
1247
|
+
}
|
|
1248
|
+
if (camera) {
|
|
1249
|
+
const cameraParts = [
|
|
1250
|
+
camera.azimuth !== null ? `az ${camera.azimuth}` : null,
|
|
1251
|
+
camera.elevation !== null ? `el ${camera.elevation}` : null,
|
|
1252
|
+
camera.roll !== null ? `roll ${camera.roll}` : null,
|
|
1253
|
+
camera.distance !== null ? `dist ${camera.distance}` : null
|
|
1254
|
+
].filter(Boolean);
|
|
1255
|
+
if (cameraParts.length > 0) {
|
|
1256
|
+
parts.push(`camera ${cameraParts.join(" / ")}`);
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
return parts.join(" - ");
|
|
1146
1260
|
}
|
|
1147
1261
|
function resolveScaleModel(layoutPreset, overrides) {
|
|
1148
1262
|
const defaults = defaultScaleModel(layoutPreset);
|
|
@@ -1258,24 +1372,14 @@ var WorldOrbit = (() => {
|
|
|
1258
1372
|
hidden: draft.object.properties.hidden === true
|
|
1259
1373
|
};
|
|
1260
1374
|
}
|
|
1261
|
-
function createSceneLabels(objects, sceneHeight, labelMultiplier) {
|
|
1375
|
+
function createSceneLabels(objects, sceneWidth, sceneHeight, labelMultiplier) {
|
|
1262
1376
|
const labels = [];
|
|
1263
1377
|
const occupied = [];
|
|
1264
|
-
const
|
|
1378
|
+
const objectMap = new Map(objects.map((object) => [object.objectId, object]));
|
|
1379
|
+
const visibleObjects = [...objects].filter((object) => !object.hidden && object.object.renderHints?.renderLabel !== false).sort(compareLabelPlacementOrder);
|
|
1265
1380
|
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);
|
|
1381
|
+
const placement = selectLabelPlacement(object, objectMap, occupied, sceneWidth, sceneHeight, labelMultiplier) ?? createLabelPlacement(object, defaultVerticalDirection(object, objectMap.get(object.parentId ?? "") ?? null, sceneHeight), 0, labelMultiplier);
|
|
1382
|
+
occupied.push(createLabelRect(object, placement, labelMultiplier));
|
|
1279
1383
|
labels.push({
|
|
1280
1384
|
renderId: `${object.renderId}-label`,
|
|
1281
1385
|
objectId: object.objectId,
|
|
@@ -1284,17 +1388,128 @@ var WorldOrbit = (() => {
|
|
|
1284
1388
|
semanticGroupIds: [...object.semanticGroupIds],
|
|
1285
1389
|
label: object.label,
|
|
1286
1390
|
secondaryLabel: object.secondaryLabel,
|
|
1287
|
-
x:
|
|
1288
|
-
y: labelY,
|
|
1289
|
-
secondaryY,
|
|
1290
|
-
textAnchor:
|
|
1291
|
-
direction: direction
|
|
1391
|
+
x: placement.x,
|
|
1392
|
+
y: placement.labelY,
|
|
1393
|
+
secondaryY: placement.secondaryY,
|
|
1394
|
+
textAnchor: placement.textAnchor,
|
|
1395
|
+
direction: placement.direction,
|
|
1292
1396
|
hidden: object.hidden
|
|
1293
1397
|
});
|
|
1294
1398
|
}
|
|
1295
1399
|
return labels;
|
|
1296
1400
|
}
|
|
1297
|
-
function
|
|
1401
|
+
function compareLabelPlacementOrder(left, right) {
|
|
1402
|
+
const priorityDiff = labelPlacementPriority(left) - labelPlacementPriority(right);
|
|
1403
|
+
if (priorityDiff !== 0) {
|
|
1404
|
+
return priorityDiff;
|
|
1405
|
+
}
|
|
1406
|
+
const renderPriorityDiff = (right.object.renderHints?.renderPriority ?? 0) - (left.object.renderHints?.renderPriority ?? 0);
|
|
1407
|
+
if (renderPriorityDiff !== 0) {
|
|
1408
|
+
return renderPriorityDiff;
|
|
1409
|
+
}
|
|
1410
|
+
return left.sortKey - right.sortKey;
|
|
1411
|
+
}
|
|
1412
|
+
function labelPlacementPriority(object) {
|
|
1413
|
+
switch (object.object.type) {
|
|
1414
|
+
case "star":
|
|
1415
|
+
return 0;
|
|
1416
|
+
case "planet":
|
|
1417
|
+
return 1;
|
|
1418
|
+
case "moon":
|
|
1419
|
+
return 2;
|
|
1420
|
+
case "belt":
|
|
1421
|
+
case "ring":
|
|
1422
|
+
return 3;
|
|
1423
|
+
case "asteroid":
|
|
1424
|
+
case "comet":
|
|
1425
|
+
return 4;
|
|
1426
|
+
case "structure":
|
|
1427
|
+
case "phenomenon":
|
|
1428
|
+
return 5;
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
function selectLabelPlacement(object, objectMap, occupied, sceneWidth, sceneHeight, labelMultiplier) {
|
|
1432
|
+
for (const direction of preferredLabelDirections(object, objectMap, sceneWidth, sceneHeight)) {
|
|
1433
|
+
const maxAttempts = direction === "left" || direction === "right" ? 4 : 6;
|
|
1434
|
+
for (let attempt = 0; attempt <= maxAttempts; attempt += 1) {
|
|
1435
|
+
const placement = createLabelPlacement(object, direction, attempt, labelMultiplier);
|
|
1436
|
+
const rect = createLabelRect(object, placement, labelMultiplier);
|
|
1437
|
+
if (!occupied.some((entry) => rectsOverlap(entry, rect))) {
|
|
1438
|
+
return placement;
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
return null;
|
|
1443
|
+
}
|
|
1444
|
+
function preferredLabelDirections(object, objectMap, sceneWidth, sceneHeight) {
|
|
1445
|
+
const parent = object.parentId ? objectMap.get(object.parentId) ?? null : null;
|
|
1446
|
+
const vertical = defaultVerticalDirection(object, parent, sceneHeight);
|
|
1447
|
+
const oppositeVertical = vertical === "below" ? "above" : "below";
|
|
1448
|
+
const horizontal = defaultHorizontalDirection(object, parent, sceneWidth);
|
|
1449
|
+
const oppositeHorizontal = horizontal === "right" ? "left" : "right";
|
|
1450
|
+
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";
|
|
1451
|
+
return preferHorizontal ? [horizontal, vertical, oppositeHorizontal, oppositeVertical] : [vertical, horizontal, oppositeVertical, oppositeHorizontal];
|
|
1452
|
+
}
|
|
1453
|
+
function defaultVerticalDirection(object, parent, sceneHeight) {
|
|
1454
|
+
if (parent && Math.abs(object.y - parent.y) > 6) {
|
|
1455
|
+
return object.y >= parent.y ? "below" : "above";
|
|
1456
|
+
}
|
|
1457
|
+
return object.y > sceneHeight * 0.62 ? "above" : "below";
|
|
1458
|
+
}
|
|
1459
|
+
function defaultHorizontalDirection(object, parent, sceneWidth) {
|
|
1460
|
+
if (parent && Math.abs(object.x - parent.x) > 6) {
|
|
1461
|
+
return object.x >= parent.x ? "right" : "left";
|
|
1462
|
+
}
|
|
1463
|
+
return object.x >= sceneWidth / 2 ? "right" : "left";
|
|
1464
|
+
}
|
|
1465
|
+
function createLabelPlacement(object, direction, attempt, labelMultiplier) {
|
|
1466
|
+
const step = 14 * labelMultiplier;
|
|
1467
|
+
switch (direction) {
|
|
1468
|
+
case "above": {
|
|
1469
|
+
const labelY = object.y - (object.radius + 18 * labelMultiplier + attempt * step);
|
|
1470
|
+
return {
|
|
1471
|
+
x: object.x,
|
|
1472
|
+
labelY,
|
|
1473
|
+
secondaryY: labelY - 16 * labelMultiplier,
|
|
1474
|
+
textAnchor: "middle",
|
|
1475
|
+
direction
|
|
1476
|
+
};
|
|
1477
|
+
}
|
|
1478
|
+
case "below": {
|
|
1479
|
+
const labelY = object.y + object.radius + 18 * labelMultiplier + attempt * step;
|
|
1480
|
+
return {
|
|
1481
|
+
x: object.x,
|
|
1482
|
+
labelY,
|
|
1483
|
+
secondaryY: labelY + 16 * labelMultiplier,
|
|
1484
|
+
textAnchor: "middle",
|
|
1485
|
+
direction
|
|
1486
|
+
};
|
|
1487
|
+
}
|
|
1488
|
+
case "left": {
|
|
1489
|
+
const x = object.x - (object.visualRadius + 16 * labelMultiplier + attempt * step);
|
|
1490
|
+
const labelY = object.y - 4 * labelMultiplier;
|
|
1491
|
+
return {
|
|
1492
|
+
x,
|
|
1493
|
+
labelY,
|
|
1494
|
+
secondaryY: labelY + 16 * labelMultiplier,
|
|
1495
|
+
textAnchor: "end",
|
|
1496
|
+
direction
|
|
1497
|
+
};
|
|
1498
|
+
}
|
|
1499
|
+
case "right": {
|
|
1500
|
+
const x = object.x + object.visualRadius + 16 * labelMultiplier + attempt * step;
|
|
1501
|
+
const labelY = object.y - 4 * labelMultiplier;
|
|
1502
|
+
return {
|
|
1503
|
+
x,
|
|
1504
|
+
labelY,
|
|
1505
|
+
secondaryY: labelY + 16 * labelMultiplier,
|
|
1506
|
+
textAnchor: "start",
|
|
1507
|
+
direction
|
|
1508
|
+
};
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
function createSceneLayers(orbitVisuals, relations, events, leaders, objects, labels) {
|
|
1298
1513
|
const backOrbitIds = orbitVisuals.filter((visual) => !visual.hidden && Boolean(visual.backArcPath)).map((visual) => visual.renderId);
|
|
1299
1514
|
const frontOrbitIds = orbitVisuals.filter((visual) => !visual.hidden).map((visual) => visual.renderId);
|
|
1300
1515
|
return [
|
|
@@ -1309,6 +1524,10 @@ var WorldOrbit = (() => {
|
|
|
1309
1524
|
id: "relations",
|
|
1310
1525
|
renderIds: relations.filter((relation) => !relation.hidden).map((relation) => relation.renderId)
|
|
1311
1526
|
},
|
|
1527
|
+
{
|
|
1528
|
+
id: "events",
|
|
1529
|
+
renderIds: events.filter((event) => !event.hidden).map((event) => event.renderId)
|
|
1530
|
+
},
|
|
1312
1531
|
{
|
|
1313
1532
|
id: "objects",
|
|
1314
1533
|
renderIds: objects.filter((object) => !object.hidden).map((object) => object.renderId)
|
|
@@ -1320,7 +1539,7 @@ var WorldOrbit = (() => {
|
|
|
1320
1539
|
{ id: "metadata", renderIds: ["wo-title", "wo-subtitle", "wo-meta"] }
|
|
1321
1540
|
];
|
|
1322
1541
|
}
|
|
1323
|
-
function createSceneGroups(objects, orbitVisuals, leaders, labels, relationships) {
|
|
1542
|
+
function createSceneGroups(objects, orbitVisuals, leaders, labels, relationships, labelMultiplier) {
|
|
1324
1543
|
const groups = /* @__PURE__ */ new Map();
|
|
1325
1544
|
const ensureGroup = (groupId) => {
|
|
1326
1545
|
if (!groupId) {
|
|
@@ -1369,7 +1588,7 @@ var WorldOrbit = (() => {
|
|
|
1369
1588
|
}
|
|
1370
1589
|
}
|
|
1371
1590
|
for (const group of groups.values()) {
|
|
1372
|
-
group.contentBounds = calculateGroupBounds(group, objects, orbitVisuals, leaders, labels);
|
|
1591
|
+
group.contentBounds = calculateGroupBounds(group, objects, orbitVisuals, leaders, labels, labelMultiplier);
|
|
1373
1592
|
}
|
|
1374
1593
|
return [...groups.values()].sort((left, right) => left.label.localeCompare(right.label));
|
|
1375
1594
|
}
|
|
@@ -1403,6 +1622,29 @@ var WorldOrbit = (() => {
|
|
|
1403
1622
|
};
|
|
1404
1623
|
}).sort((left, right) => left.relation.id.localeCompare(right.relation.id));
|
|
1405
1624
|
}
|
|
1625
|
+
function createSceneEvents(events, objects, activeEventId) {
|
|
1626
|
+
const objectMap = new Map(objects.map((object) => [object.objectId, object]));
|
|
1627
|
+
return events.map((event) => {
|
|
1628
|
+
const objectIds = [.../* @__PURE__ */ new Set([
|
|
1629
|
+
...event.targetObjectId ? [event.targetObjectId] : [],
|
|
1630
|
+
...event.participantObjectIds
|
|
1631
|
+
])];
|
|
1632
|
+
const positions = objectIds.map((objectId) => objectMap.get(objectId)).filter(Boolean);
|
|
1633
|
+
const centroidX = positions.length > 0 ? positions.reduce((sum, object) => sum + object.x, 0) / positions.length : 0;
|
|
1634
|
+
const centroidY = positions.length > 0 ? positions.reduce((sum, object) => sum + object.y, 0) / positions.length : 0;
|
|
1635
|
+
return {
|
|
1636
|
+
renderId: `${createRenderId(event.id)}-event`,
|
|
1637
|
+
eventId: event.id,
|
|
1638
|
+
event,
|
|
1639
|
+
objectIds,
|
|
1640
|
+
participantIds: [...event.participantObjectIds],
|
|
1641
|
+
targetObjectId: event.targetObjectId,
|
|
1642
|
+
x: centroidX,
|
|
1643
|
+
y: centroidY,
|
|
1644
|
+
hidden: event.hidden || positions.length === 0 || positions.every((object) => object.hidden) || activeEventId !== null && event.id !== activeEventId
|
|
1645
|
+
};
|
|
1646
|
+
}).sort((left, right) => left.event.id.localeCompare(right.event.id));
|
|
1647
|
+
}
|
|
1406
1648
|
function createSceneViewpoints(document2, projection, preset, relationships, objectMap) {
|
|
1407
1649
|
const generatedOverview = createGeneratedOverviewViewpoint(document2, projection, preset);
|
|
1408
1650
|
const drafts = /* @__PURE__ */ new Map();
|
|
@@ -1450,13 +1692,18 @@ var WorldOrbit = (() => {
|
|
|
1450
1692
|
function createGeneratedOverviewViewpoint(document2, projection, preset) {
|
|
1451
1693
|
const title = document2.system?.title ?? document2.system?.properties.title;
|
|
1452
1694
|
const label = title ? `${String(title)} Overview` : "Overview";
|
|
1695
|
+
const camera = normalizeViewCamera(null);
|
|
1696
|
+
const renderProjection = resolveRenderProjection(projection, camera);
|
|
1453
1697
|
return {
|
|
1454
1698
|
id: "overview",
|
|
1455
1699
|
label,
|
|
1456
1700
|
summary: "Fit the whole system with the current atlas defaults.",
|
|
1457
1701
|
objectId: null,
|
|
1458
1702
|
selectedObjectId: null,
|
|
1703
|
+
eventIds: [],
|
|
1459
1704
|
projection,
|
|
1705
|
+
renderProjection,
|
|
1706
|
+
camera,
|
|
1460
1707
|
preset,
|
|
1461
1708
|
rotationDeg: 0,
|
|
1462
1709
|
scale: null,
|
|
@@ -1492,6 +1739,9 @@ var WorldOrbit = (() => {
|
|
|
1492
1739
|
draft.select = normalizedValue;
|
|
1493
1740
|
}
|
|
1494
1741
|
return;
|
|
1742
|
+
case "events":
|
|
1743
|
+
draft.eventIds = splitListValue(normalizedValue);
|
|
1744
|
+
return;
|
|
1495
1745
|
case "projection":
|
|
1496
1746
|
case "view":
|
|
1497
1747
|
draft.projection = parseViewProjection(normalizedValue) ?? projection;
|
|
@@ -1503,6 +1753,30 @@ var WorldOrbit = (() => {
|
|
|
1503
1753
|
case "angle":
|
|
1504
1754
|
draft.rotationDeg = parseFiniteNumber(normalizedValue) ?? draft.rotationDeg ?? 0;
|
|
1505
1755
|
return;
|
|
1756
|
+
case "camera.azimuth":
|
|
1757
|
+
draft.camera = {
|
|
1758
|
+
...draft.camera ?? createEmptyViewCamera(),
|
|
1759
|
+
azimuth: parseFiniteNumber(normalizedValue)
|
|
1760
|
+
};
|
|
1761
|
+
return;
|
|
1762
|
+
case "camera.elevation":
|
|
1763
|
+
draft.camera = {
|
|
1764
|
+
...draft.camera ?? createEmptyViewCamera(),
|
|
1765
|
+
elevation: parseFiniteNumber(normalizedValue)
|
|
1766
|
+
};
|
|
1767
|
+
return;
|
|
1768
|
+
case "camera.roll":
|
|
1769
|
+
draft.camera = {
|
|
1770
|
+
...draft.camera ?? createEmptyViewCamera(),
|
|
1771
|
+
roll: parseFiniteNumber(normalizedValue)
|
|
1772
|
+
};
|
|
1773
|
+
return;
|
|
1774
|
+
case "camera.distance":
|
|
1775
|
+
draft.camera = {
|
|
1776
|
+
...draft.camera ?? createEmptyViewCamera(),
|
|
1777
|
+
distance: parsePositiveNumber(normalizedValue)
|
|
1778
|
+
};
|
|
1779
|
+
return;
|
|
1506
1780
|
case "zoom":
|
|
1507
1781
|
case "scale":
|
|
1508
1782
|
draft.scale = parsePositiveNumber(normalizedValue);
|
|
@@ -1542,13 +1816,19 @@ var WorldOrbit = (() => {
|
|
|
1542
1816
|
const selectedObjectId = draft.select && objectMap.has(draft.select) ? draft.select : objectId;
|
|
1543
1817
|
const filter = normalizeViewpointFilter(draft.filter);
|
|
1544
1818
|
const label = draft.label?.trim() || humanizeIdentifier(draft.id);
|
|
1819
|
+
const resolvedProjection = draft.projection ?? projection;
|
|
1820
|
+
const camera = normalizeViewCamera(draft.camera ?? null);
|
|
1821
|
+
const renderProjection = resolveRenderProjection(resolvedProjection, camera);
|
|
1545
1822
|
return {
|
|
1546
1823
|
id: draft.id,
|
|
1547
1824
|
label,
|
|
1548
1825
|
summary: draft.summary?.trim() || createViewpointSummary(label, objectId, filter),
|
|
1549
1826
|
objectId,
|
|
1550
1827
|
selectedObjectId,
|
|
1551
|
-
|
|
1828
|
+
eventIds: [...new Set(draft.eventIds ?? [])],
|
|
1829
|
+
projection: resolvedProjection,
|
|
1830
|
+
renderProjection,
|
|
1831
|
+
camera,
|
|
1552
1832
|
preset: draft.preset ?? preset,
|
|
1553
1833
|
rotationDeg: draft.rotationDeg ?? 0,
|
|
1554
1834
|
scale: draft.scale ?? null,
|
|
@@ -1565,6 +1845,14 @@ var WorldOrbit = (() => {
|
|
|
1565
1845
|
groupIds: []
|
|
1566
1846
|
};
|
|
1567
1847
|
}
|
|
1848
|
+
function createEmptyViewCamera() {
|
|
1849
|
+
return {
|
|
1850
|
+
azimuth: null,
|
|
1851
|
+
elevation: null,
|
|
1852
|
+
roll: null,
|
|
1853
|
+
distance: null
|
|
1854
|
+
};
|
|
1855
|
+
}
|
|
1568
1856
|
function normalizeViewpointFilter(filter) {
|
|
1569
1857
|
if (!filter) {
|
|
1570
1858
|
return null;
|
|
@@ -1578,7 +1866,18 @@ var WorldOrbit = (() => {
|
|
|
1578
1866
|
return normalized.query || normalized.objectTypes.length > 0 || normalized.tags.length > 0 || normalized.groupIds.length > 0 ? normalized : null;
|
|
1579
1867
|
}
|
|
1580
1868
|
function parseViewProjection(value) {
|
|
1581
|
-
|
|
1869
|
+
switch (value.toLowerCase()) {
|
|
1870
|
+
case "topdown":
|
|
1871
|
+
return "topdown";
|
|
1872
|
+
case "isometric":
|
|
1873
|
+
return "isometric";
|
|
1874
|
+
case "orthographic":
|
|
1875
|
+
return "orthographic";
|
|
1876
|
+
case "perspective":
|
|
1877
|
+
return "perspective";
|
|
1878
|
+
default:
|
|
1879
|
+
return null;
|
|
1880
|
+
}
|
|
1582
1881
|
}
|
|
1583
1882
|
function parseRenderPreset(value) {
|
|
1584
1883
|
const normalized = value.toLowerCase();
|
|
@@ -1605,7 +1904,7 @@ var WorldOrbit = (() => {
|
|
|
1605
1904
|
next["orbits-front"] = enabled;
|
|
1606
1905
|
continue;
|
|
1607
1906
|
}
|
|
1608
|
-
if (rawLayer === "background" || rawLayer === "guides" || rawLayer === "orbits-back" || rawLayer === "orbits-front" || rawLayer === "relations" || rawLayer === "objects" || rawLayer === "labels" || rawLayer === "metadata") {
|
|
1907
|
+
if (rawLayer === "background" || rawLayer === "guides" || rawLayer === "orbits-back" || rawLayer === "orbits-front" || rawLayer === "relations" || rawLayer === "events" || rawLayer === "objects" || rawLayer === "labels" || rawLayer === "metadata") {
|
|
1609
1908
|
next[rawLayer] = enabled;
|
|
1610
1909
|
}
|
|
1611
1910
|
}
|
|
@@ -1616,7 +1915,7 @@ var WorldOrbit = (() => {
|
|
|
1616
1915
|
}
|
|
1617
1916
|
function parseViewpointGroups(value, document2, relationships, objectMap) {
|
|
1618
1917
|
return splitListValue(value).map((entry) => {
|
|
1619
|
-
if (document2.schemaVersion === "2.1" || document2.groups.some((group) => group.id === entry)) {
|
|
1918
|
+
if (document2.schemaVersion === "2.1" || document2.schemaVersion === "2.5" || document2.groups.some((group) => group.id === entry)) {
|
|
1620
1919
|
return entry;
|
|
1621
1920
|
}
|
|
1622
1921
|
if (entry.startsWith("wo-") && entry.endsWith("-group")) {
|
|
@@ -1653,7 +1952,7 @@ var WorldOrbit = (() => {
|
|
|
1653
1952
|
}
|
|
1654
1953
|
return parts.join(" - ");
|
|
1655
1954
|
}
|
|
1656
|
-
function calculateContentBounds(width, height, objects, orbitVisuals, leaders, labels) {
|
|
1955
|
+
function calculateContentBounds(width, height, objects, orbitVisuals, leaders, labels, labelMultiplier) {
|
|
1657
1956
|
let minX = Number.POSITIVE_INFINITY;
|
|
1658
1957
|
let minY = Number.POSITIVE_INFINITY;
|
|
1659
1958
|
let maxX = Number.NEGATIVE_INFINITY;
|
|
@@ -1683,7 +1982,7 @@ var WorldOrbit = (() => {
|
|
|
1683
1982
|
for (const label of labels) {
|
|
1684
1983
|
if (label.hidden)
|
|
1685
1984
|
continue;
|
|
1686
|
-
includeLabelBounds(label, include);
|
|
1985
|
+
includeLabelBounds(label, include, labelMultiplier);
|
|
1687
1986
|
}
|
|
1688
1987
|
if (!Number.isFinite(minX) || !Number.isFinite(minY)) {
|
|
1689
1988
|
return createBounds(0, 0, width, height);
|
|
@@ -1721,13 +2020,10 @@ var WorldOrbit = (() => {
|
|
|
1721
2020
|
include(object.x - object.visualRadius - 24, object.y - object.visualRadius - 16);
|
|
1722
2021
|
include(object.x + object.visualRadius + 24, object.y + object.visualRadius + 36);
|
|
1723
2022
|
}
|
|
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);
|
|
2023
|
+
function includeLabelBounds(label, include, labelMultiplier) {
|
|
2024
|
+
const bounds = createLabelRectFromText(label.x, label.y, label.secondaryY, label.textAnchor, label.direction, label.label, label.secondaryLabel, labelMultiplier);
|
|
2025
|
+
include(bounds.left, bounds.top);
|
|
2026
|
+
include(bounds.right, bounds.bottom);
|
|
1731
2027
|
}
|
|
1732
2028
|
function placeObject(object, x, y, depth, positions, orbitDrafts, leaderDrafts, context) {
|
|
1733
2029
|
if (positions.has(object.id)) {
|
|
@@ -2117,7 +2413,7 @@ var WorldOrbit = (() => {
|
|
|
2117
2413
|
return null;
|
|
2118
2414
|
}
|
|
2119
2415
|
}
|
|
2120
|
-
function calculateGroupBounds(group, objects, orbitVisuals, leaders, labels) {
|
|
2416
|
+
function calculateGroupBounds(group, objects, orbitVisuals, leaders, labels, labelMultiplier) {
|
|
2121
2417
|
let minX = Number.POSITIVE_INFINITY;
|
|
2122
2418
|
let minY = Number.POSITIVE_INFINITY;
|
|
2123
2419
|
let maxX = Number.NEGATIVE_INFINITY;
|
|
@@ -2146,7 +2442,7 @@ var WorldOrbit = (() => {
|
|
|
2146
2442
|
}
|
|
2147
2443
|
for (const label of labels) {
|
|
2148
2444
|
if (!label.hidden && group.labelIds.includes(label.objectId)) {
|
|
2149
|
-
includeLabelBounds(label, include);
|
|
2445
|
+
includeLabelBounds(label, include, labelMultiplier);
|
|
2150
2446
|
}
|
|
2151
2447
|
}
|
|
2152
2448
|
if (!Number.isFinite(minX) || !Number.isFinite(minY)) {
|
|
@@ -2171,12 +2467,28 @@ var WorldOrbit = (() => {
|
|
|
2171
2467
|
}
|
|
2172
2468
|
return current.id;
|
|
2173
2469
|
}
|
|
2174
|
-
function createLabelRect(
|
|
2470
|
+
function createLabelRect(object, placement, labelMultiplier) {
|
|
2471
|
+
return createLabelRectFromText(placement.x, placement.labelY, placement.secondaryY, placement.textAnchor, placement.direction, object.label, object.secondaryLabel, labelMultiplier);
|
|
2472
|
+
}
|
|
2473
|
+
function createLabelRectFromText(x, labelY, secondaryY, textAnchor, direction, label, secondaryLabel, labelMultiplier) {
|
|
2474
|
+
const labelHalfWidth = estimateLabelHalfWidthFromText(label, secondaryLabel, labelMultiplier);
|
|
2475
|
+
const labelWidth = labelHalfWidth * 2;
|
|
2476
|
+
const topPadding = direction === "above" ? 18 : 12;
|
|
2477
|
+
const bottomPadding = direction === "above" ? 8 : 12;
|
|
2478
|
+
let left = x - labelHalfWidth;
|
|
2479
|
+
let right = x + labelHalfWidth;
|
|
2480
|
+
if (textAnchor === "start") {
|
|
2481
|
+
left = x;
|
|
2482
|
+
right = x + labelWidth;
|
|
2483
|
+
} else if (textAnchor === "end") {
|
|
2484
|
+
left = x - labelWidth;
|
|
2485
|
+
right = x;
|
|
2486
|
+
}
|
|
2175
2487
|
return {
|
|
2176
|
-
left
|
|
2177
|
-
right
|
|
2178
|
-
top: Math.min(labelY, secondaryY) -
|
|
2179
|
-
bottom: Math.max(labelY, secondaryY) +
|
|
2488
|
+
left,
|
|
2489
|
+
right,
|
|
2490
|
+
top: Math.min(labelY, secondaryY) - topPadding,
|
|
2491
|
+
bottom: Math.max(labelY, secondaryY) + bottomPadding
|
|
2180
2492
|
};
|
|
2181
2493
|
}
|
|
2182
2494
|
function rectsOverlap(left, right) {
|
|
@@ -2363,11 +2675,6 @@ var WorldOrbit = (() => {
|
|
|
2363
2675
|
function customColorFor(value) {
|
|
2364
2676
|
return typeof value === "string" && value.trim() ? value : void 0;
|
|
2365
2677
|
}
|
|
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
2678
|
function estimateLabelHalfWidthFromText(label, secondaryLabel, labelMultiplier) {
|
|
2372
2679
|
const primaryWidth = label.length * 4.6 * labelMultiplier + 18;
|
|
2373
2680
|
const secondaryWidth = secondaryLabel.length * 3.9 * labelMultiplier + 18;
|
|
@@ -2401,12 +2708,13 @@ var WorldOrbit = (() => {
|
|
|
2401
2708
|
}
|
|
2402
2709
|
return {
|
|
2403
2710
|
format: "worldorbit",
|
|
2404
|
-
version: "2.
|
|
2405
|
-
schemaVersion: "2.
|
|
2711
|
+
version: "2.5",
|
|
2712
|
+
schemaVersion: "2.5",
|
|
2406
2713
|
sourceVersion: document2.version,
|
|
2407
2714
|
system,
|
|
2408
2715
|
groups: structuredClone(document2.groups ?? []),
|
|
2409
2716
|
relations: structuredClone(document2.relations ?? []),
|
|
2717
|
+
events: structuredClone(document2.events ?? []),
|
|
2410
2718
|
objects: document2.objects.map(cloneWorldOrbitObject),
|
|
2411
2719
|
diagnostics
|
|
2412
2720
|
};
|
|
@@ -2414,7 +2722,7 @@ var WorldOrbit = (() => {
|
|
|
2414
2722
|
function upgradeDocumentToDraftV2(document2, options = {}) {
|
|
2415
2723
|
return convertAtlasDocumentToLegacyDraft(upgradeDocumentToV2(document2, options));
|
|
2416
2724
|
}
|
|
2417
|
-
function materializeAtlasDocument(document2) {
|
|
2725
|
+
function materializeAtlasDocument(document2, options = {}) {
|
|
2418
2726
|
const system = document2.system ? {
|
|
2419
2727
|
type: "system",
|
|
2420
2728
|
id: document2.system.id,
|
|
@@ -2425,6 +2733,8 @@ var WorldOrbit = (() => {
|
|
|
2425
2733
|
properties: materializeDraftSystemProperties(document2.system),
|
|
2426
2734
|
info: materializeDraftSystemInfo(document2.system)
|
|
2427
2735
|
} : null;
|
|
2736
|
+
const objects = document2.objects.map(cloneWorldOrbitObject);
|
|
2737
|
+
applyEventPoseOverrides(objects, document2.events ?? [], options.activeEventId ?? null);
|
|
2428
2738
|
return {
|
|
2429
2739
|
format: "worldorbit",
|
|
2430
2740
|
version: "1.0",
|
|
@@ -2432,7 +2742,8 @@ var WorldOrbit = (() => {
|
|
|
2432
2742
|
system,
|
|
2433
2743
|
groups: structuredClone(document2.groups ?? []),
|
|
2434
2744
|
relations: structuredClone(document2.relations ?? []),
|
|
2435
|
-
|
|
2745
|
+
events: document2.events.map(cloneWorldOrbitEvent),
|
|
2746
|
+
objects
|
|
2436
2747
|
};
|
|
2437
2748
|
}
|
|
2438
2749
|
function createDraftSystem(document2, defaults, atlasMetadata, annotations, diagnostics, preset) {
|
|
@@ -2454,8 +2765,9 @@ var WorldOrbit = (() => {
|
|
|
2454
2765
|
};
|
|
2455
2766
|
}
|
|
2456
2767
|
function createDraftDefaults(document2, preset, projection) {
|
|
2768
|
+
const rawView = typeof document2.system?.properties.view === "string" ? document2.system.properties.view.toLowerCase() : null;
|
|
2457
2769
|
return {
|
|
2458
|
-
view:
|
|
2770
|
+
view: rawView === "topdown" || rawView === "isometric" || rawView === "orthographic" || rawView === "perspective" ? rawView : projection,
|
|
2459
2771
|
scale: typeof document2.system?.properties.scale === "string" ? document2.system.properties.scale : null,
|
|
2460
2772
|
units: typeof document2.system?.properties.units === "string" ? document2.system.properties.units : null,
|
|
2461
2773
|
preset,
|
|
@@ -2557,10 +2869,12 @@ var WorldOrbit = (() => {
|
|
|
2557
2869
|
summary: viewpoint.summary,
|
|
2558
2870
|
focusObjectId: viewpoint.objectId,
|
|
2559
2871
|
selectedObjectId: viewpoint.selectedObjectId,
|
|
2872
|
+
events: [...viewpoint.eventIds],
|
|
2560
2873
|
projection: viewpoint.projection,
|
|
2561
2874
|
preset: viewpoint.preset,
|
|
2562
2875
|
zoom: viewpoint.scale,
|
|
2563
2876
|
rotationDeg: viewpoint.rotationDeg,
|
|
2877
|
+
camera: viewpoint.camera ? { ...viewpoint.camera } : null,
|
|
2564
2878
|
layers: { ...viewpoint.layers },
|
|
2565
2879
|
filter: viewpoint.filter ? {
|
|
2566
2880
|
query: viewpoint.filter.query,
|
|
@@ -2589,6 +2903,75 @@ var WorldOrbit = (() => {
|
|
|
2589
2903
|
info: { ...object.info }
|
|
2590
2904
|
};
|
|
2591
2905
|
}
|
|
2906
|
+
function cloneWorldOrbitEvent(event) {
|
|
2907
|
+
return {
|
|
2908
|
+
...event,
|
|
2909
|
+
participantObjectIds: [...event.participantObjectIds],
|
|
2910
|
+
tags: [...event.tags],
|
|
2911
|
+
positions: event.positions.map(cloneWorldOrbitEventPose)
|
|
2912
|
+
};
|
|
2913
|
+
}
|
|
2914
|
+
function cloneWorldOrbitEventPose(pose) {
|
|
2915
|
+
return {
|
|
2916
|
+
objectId: pose.objectId,
|
|
2917
|
+
placement: clonePlacement(pose.placement),
|
|
2918
|
+
inner: pose.inner ? { ...pose.inner } : void 0,
|
|
2919
|
+
outer: pose.outer ? { ...pose.outer } : void 0,
|
|
2920
|
+
epoch: pose.epoch ?? null,
|
|
2921
|
+
referencePlane: pose.referencePlane ?? null
|
|
2922
|
+
};
|
|
2923
|
+
}
|
|
2924
|
+
function clonePlacement(placement) {
|
|
2925
|
+
return placement ? structuredClone(placement) : null;
|
|
2926
|
+
}
|
|
2927
|
+
function applyEventPoseOverrides(objects, events, activeEventId) {
|
|
2928
|
+
if (!activeEventId) {
|
|
2929
|
+
return;
|
|
2930
|
+
}
|
|
2931
|
+
const event = events.find((entry) => entry.id === activeEventId);
|
|
2932
|
+
if (!event) {
|
|
2933
|
+
return;
|
|
2934
|
+
}
|
|
2935
|
+
const objectMap = new Map(objects.map((object) => [object.id, object]));
|
|
2936
|
+
const referencedIds = /* @__PURE__ */ new Set([
|
|
2937
|
+
...event.targetObjectId ? [event.targetObjectId] : [],
|
|
2938
|
+
...event.participantObjectIds,
|
|
2939
|
+
...event.positions.map((pose) => pose.objectId)
|
|
2940
|
+
]);
|
|
2941
|
+
for (const objectId of referencedIds) {
|
|
2942
|
+
const object = objectMap.get(objectId);
|
|
2943
|
+
if (!object) {
|
|
2944
|
+
continue;
|
|
2945
|
+
}
|
|
2946
|
+
if (event.epoch) {
|
|
2947
|
+
object.epoch = event.epoch;
|
|
2948
|
+
}
|
|
2949
|
+
if (event.referencePlane) {
|
|
2950
|
+
object.referencePlane = event.referencePlane;
|
|
2951
|
+
}
|
|
2952
|
+
}
|
|
2953
|
+
for (const pose of event.positions) {
|
|
2954
|
+
const object = objectMap.get(pose.objectId);
|
|
2955
|
+
if (!object) {
|
|
2956
|
+
continue;
|
|
2957
|
+
}
|
|
2958
|
+
if (pose.placement) {
|
|
2959
|
+
object.placement = clonePlacement(pose.placement);
|
|
2960
|
+
}
|
|
2961
|
+
if (pose.inner) {
|
|
2962
|
+
object.properties.inner = { ...pose.inner };
|
|
2963
|
+
}
|
|
2964
|
+
if (pose.outer) {
|
|
2965
|
+
object.properties.outer = { ...pose.outer };
|
|
2966
|
+
}
|
|
2967
|
+
if (pose.epoch) {
|
|
2968
|
+
object.epoch = pose.epoch;
|
|
2969
|
+
}
|
|
2970
|
+
if (pose.referencePlane) {
|
|
2971
|
+
object.referencePlane = pose.referencePlane;
|
|
2972
|
+
}
|
|
2973
|
+
}
|
|
2974
|
+
}
|
|
2592
2975
|
function cloneProperties(properties) {
|
|
2593
2976
|
const next = {};
|
|
2594
2977
|
for (const [key, value] of Object.entries(properties)) {
|
|
@@ -2670,6 +3053,18 @@ var WorldOrbit = (() => {
|
|
|
2670
3053
|
if (viewpoint.rotationDeg !== 0) {
|
|
2671
3054
|
info2[`${prefix}.rotation`] = String(viewpoint.rotationDeg);
|
|
2672
3055
|
}
|
|
3056
|
+
if (viewpoint.camera?.azimuth !== null) {
|
|
3057
|
+
info2[`${prefix}.camera.azimuth`] = String(viewpoint.camera?.azimuth);
|
|
3058
|
+
}
|
|
3059
|
+
if (viewpoint.camera?.elevation !== null) {
|
|
3060
|
+
info2[`${prefix}.camera.elevation`] = String(viewpoint.camera?.elevation);
|
|
3061
|
+
}
|
|
3062
|
+
if (viewpoint.camera?.roll !== null) {
|
|
3063
|
+
info2[`${prefix}.camera.roll`] = String(viewpoint.camera?.roll);
|
|
3064
|
+
}
|
|
3065
|
+
if (viewpoint.camera?.distance !== null) {
|
|
3066
|
+
info2[`${prefix}.camera.distance`] = String(viewpoint.camera?.distance);
|
|
3067
|
+
}
|
|
2673
3068
|
const serializedLayers = serializeViewpointLayers(viewpoint.layers);
|
|
2674
3069
|
if (serializedLayers) {
|
|
2675
3070
|
info2[`${prefix}.layers`] = serializedLayers;
|
|
@@ -2686,6 +3081,9 @@ var WorldOrbit = (() => {
|
|
|
2686
3081
|
if ((viewpoint.filter?.groupIds.length ?? 0) > 0) {
|
|
2687
3082
|
info2[`${prefix}.groups`] = viewpoint.filter?.groupIds.join(" ") ?? "";
|
|
2688
3083
|
}
|
|
3084
|
+
if (viewpoint.events.length > 0) {
|
|
3085
|
+
info2[`${prefix}.events`] = viewpoint.events.join(" ");
|
|
3086
|
+
}
|
|
2689
3087
|
}
|
|
2690
3088
|
for (const annotation of system.annotations) {
|
|
2691
3089
|
const prefix = `annotation.${annotation.id}`;
|
|
@@ -2710,7 +3108,7 @@ var WorldOrbit = (() => {
|
|
|
2710
3108
|
if (orbitFront !== void 0 || orbitBack !== void 0) {
|
|
2711
3109
|
tokens.push(orbitFront !== false || orbitBack !== false ? "orbits" : "-orbits");
|
|
2712
3110
|
}
|
|
2713
|
-
for (const key of ["background", "guides", "relations", "objects", "labels", "metadata"]) {
|
|
3111
|
+
for (const key of ["background", "guides", "relations", "events", "objects", "labels", "metadata"]) {
|
|
2714
3112
|
if (layers[key] !== void 0) {
|
|
2715
3113
|
tokens.push(layers[key] ? key : `-${key}`);
|
|
2716
3114
|
}
|
|
@@ -2763,26 +3161,26 @@ var WorldOrbit = (() => {
|
|
|
2763
3161
|
];
|
|
2764
3162
|
function formatDocument(document2, options = {}) {
|
|
2765
3163
|
const schema = options.schema ?? "auto";
|
|
2766
|
-
const useDraft = schema === "2.0" || schema === "2.1" || schema === "2.0-draft" || document2.version === "2.0" || document2.version === "2.1" || document2.version === "2.0-draft";
|
|
3164
|
+
const useDraft = schema === "2.0" || schema === "2.1" || schema === "2.5" || schema === "2.0-draft" || document2.version === "2.0" || document2.version === "2.1" || document2.version === "2.5" || document2.version === "2.0-draft";
|
|
2767
3165
|
if (useDraft) {
|
|
2768
3166
|
if (schema === "2.0-draft") {
|
|
2769
|
-
const legacyDraftDocument = document2.version === "2.0-draft" ? document2 : document2.version === "2.0" || document2.version === "2.1" ? {
|
|
3167
|
+
const legacyDraftDocument = document2.version === "2.0-draft" ? document2 : document2.version === "2.0" || document2.version === "2.1" || document2.version === "2.5" ? {
|
|
2770
3168
|
...document2,
|
|
2771
3169
|
version: "2.0-draft",
|
|
2772
3170
|
schemaVersion: "2.0-draft"
|
|
2773
3171
|
} : upgradeDocumentToDraftV2(document2);
|
|
2774
3172
|
return formatDraftDocument(legacyDraftDocument);
|
|
2775
3173
|
}
|
|
2776
|
-
const atlasDocument = document2.version === "2.0" || document2.version === "2.1" ? document2 : document2.version === "2.0-draft" ? {
|
|
3174
|
+
const atlasDocument = document2.version === "2.0" || document2.version === "2.1" || document2.version === "2.5" ? document2 : document2.version === "2.0-draft" ? {
|
|
2777
3175
|
...document2,
|
|
2778
3176
|
version: "2.0",
|
|
2779
3177
|
schemaVersion: "2.0"
|
|
2780
3178
|
} : upgradeDocumentToV2(document2);
|
|
2781
|
-
if (schema === "2.1" && atlasDocument.version !==
|
|
3179
|
+
if ((schema === "2.0" || schema === "2.1" || schema === "2.5") && atlasDocument.version !== schema) {
|
|
2782
3180
|
return formatAtlasDocument({
|
|
2783
3181
|
...atlasDocument,
|
|
2784
|
-
version:
|
|
2785
|
-
schemaVersion:
|
|
3182
|
+
version: schema,
|
|
3183
|
+
schemaVersion: schema
|
|
2786
3184
|
});
|
|
2787
3185
|
}
|
|
2788
3186
|
return formatAtlasDocument(atlasDocument);
|
|
@@ -2814,6 +3212,10 @@ var WorldOrbit = (() => {
|
|
|
2814
3212
|
lines.push("");
|
|
2815
3213
|
lines.push(...formatAtlasRelation(relation));
|
|
2816
3214
|
}
|
|
3215
|
+
for (const event of [...document2.events].sort(compareIdLike)) {
|
|
3216
|
+
lines.push("");
|
|
3217
|
+
lines.push(...formatAtlasEvent(event));
|
|
3218
|
+
}
|
|
2817
3219
|
const sortedObjects = [...document2.objects].sort(compareObjects);
|
|
2818
3220
|
if (sortedObjects.length > 0 && lines.at(-1) !== "") {
|
|
2819
3221
|
lines.push("");
|
|
@@ -2844,6 +3246,10 @@ var WorldOrbit = (() => {
|
|
|
2844
3246
|
lines.push("");
|
|
2845
3247
|
lines.push(...formatAtlasRelation(relation));
|
|
2846
3248
|
}
|
|
3249
|
+
for (const event of [...legacy.events].sort(compareIdLike)) {
|
|
3250
|
+
lines.push("");
|
|
3251
|
+
lines.push(...formatAtlasEvent(event));
|
|
3252
|
+
}
|
|
2847
3253
|
const sortedObjects = [...legacy.objects].sort(compareObjects);
|
|
2848
3254
|
if (sortedObjects.length > 0 && lines.at(-1) !== "") {
|
|
2849
3255
|
lines.push("");
|
|
@@ -3051,10 +3457,28 @@ var WorldOrbit = (() => {
|
|
|
3051
3457
|
if (viewpoint.rotationDeg !== 0) {
|
|
3052
3458
|
lines.push(` rotation ${viewpoint.rotationDeg}`);
|
|
3053
3459
|
}
|
|
3460
|
+
if (viewpoint.camera && hasCameraValues(viewpoint.camera)) {
|
|
3461
|
+
lines.push(" camera");
|
|
3462
|
+
if (viewpoint.camera.azimuth !== null) {
|
|
3463
|
+
lines.push(` azimuth ${viewpoint.camera.azimuth}`);
|
|
3464
|
+
}
|
|
3465
|
+
if (viewpoint.camera.elevation !== null) {
|
|
3466
|
+
lines.push(` elevation ${viewpoint.camera.elevation}`);
|
|
3467
|
+
}
|
|
3468
|
+
if (viewpoint.camera.roll !== null) {
|
|
3469
|
+
lines.push(` roll ${viewpoint.camera.roll}`);
|
|
3470
|
+
}
|
|
3471
|
+
if (viewpoint.camera.distance !== null) {
|
|
3472
|
+
lines.push(` distance ${viewpoint.camera.distance}`);
|
|
3473
|
+
}
|
|
3474
|
+
}
|
|
3054
3475
|
const layerTokens = formatDraftLayers(viewpoint.layers);
|
|
3055
3476
|
if (layerTokens.length > 0) {
|
|
3056
3477
|
lines.push(` layers ${layerTokens.join(" ")}`);
|
|
3057
3478
|
}
|
|
3479
|
+
if (viewpoint.events.length > 0) {
|
|
3480
|
+
lines.push(` events ${viewpoint.events.join(" ")}`);
|
|
3481
|
+
}
|
|
3058
3482
|
if (viewpoint.filter) {
|
|
3059
3483
|
lines.push(" filter");
|
|
3060
3484
|
if (viewpoint.filter.query) {
|
|
@@ -3127,6 +3551,65 @@ var WorldOrbit = (() => {
|
|
|
3127
3551
|
}
|
|
3128
3552
|
return lines;
|
|
3129
3553
|
}
|
|
3554
|
+
function formatAtlasEvent(event) {
|
|
3555
|
+
const lines = [`event ${event.id}`, ` kind ${quoteIfNeeded(event.kind)}`];
|
|
3556
|
+
if (event.label) {
|
|
3557
|
+
lines.push(` label ${quoteIfNeeded(event.label)}`);
|
|
3558
|
+
}
|
|
3559
|
+
if (event.summary) {
|
|
3560
|
+
lines.push(` summary ${quoteIfNeeded(event.summary)}`);
|
|
3561
|
+
}
|
|
3562
|
+
if (event.targetObjectId) {
|
|
3563
|
+
lines.push(` target ${event.targetObjectId}`);
|
|
3564
|
+
}
|
|
3565
|
+
if (event.participantObjectIds.length > 0) {
|
|
3566
|
+
lines.push(` participants ${event.participantObjectIds.join(" ")}`);
|
|
3567
|
+
}
|
|
3568
|
+
if (event.timing) {
|
|
3569
|
+
lines.push(` timing ${quoteIfNeeded(event.timing)}`);
|
|
3570
|
+
}
|
|
3571
|
+
if (event.visibility) {
|
|
3572
|
+
lines.push(` visibility ${quoteIfNeeded(event.visibility)}`);
|
|
3573
|
+
}
|
|
3574
|
+
if (event.epoch) {
|
|
3575
|
+
lines.push(` epoch ${quoteIfNeeded(event.epoch)}`);
|
|
3576
|
+
}
|
|
3577
|
+
if (event.referencePlane) {
|
|
3578
|
+
lines.push(` referencePlane ${quoteIfNeeded(event.referencePlane)}`);
|
|
3579
|
+
}
|
|
3580
|
+
if (event.tags.length > 0) {
|
|
3581
|
+
lines.push(` tags ${event.tags.map(quoteIfNeeded).join(" ")}`);
|
|
3582
|
+
}
|
|
3583
|
+
if (event.color) {
|
|
3584
|
+
lines.push(` color ${quoteIfNeeded(event.color)}`);
|
|
3585
|
+
}
|
|
3586
|
+
if (event.hidden) {
|
|
3587
|
+
lines.push(" hidden true");
|
|
3588
|
+
}
|
|
3589
|
+
if (event.positions.length > 0) {
|
|
3590
|
+
lines.push("");
|
|
3591
|
+
lines.push(" positions");
|
|
3592
|
+
for (const pose of [...event.positions].sort(comparePoseObjectId)) {
|
|
3593
|
+
lines.push(` pose ${pose.objectId}`);
|
|
3594
|
+
for (const fieldLine of formatEventPoseFields(pose)) {
|
|
3595
|
+
lines.push(` ${fieldLine}`);
|
|
3596
|
+
}
|
|
3597
|
+
}
|
|
3598
|
+
}
|
|
3599
|
+
return lines;
|
|
3600
|
+
}
|
|
3601
|
+
function formatEventPoseFields(pose) {
|
|
3602
|
+
return [
|
|
3603
|
+
...formatPlacement(pose.placement),
|
|
3604
|
+
...pose.epoch ? [`epoch ${quoteIfNeeded(pose.epoch)}`] : [],
|
|
3605
|
+
...pose.referencePlane ? [`referencePlane ${quoteIfNeeded(pose.referencePlane)}`] : [],
|
|
3606
|
+
...formatOptionalUnit("inner", pose.inner),
|
|
3607
|
+
...formatOptionalUnit("outer", pose.outer)
|
|
3608
|
+
];
|
|
3609
|
+
}
|
|
3610
|
+
function hasCameraValues(camera) {
|
|
3611
|
+
return camera.azimuth !== null || camera.elevation !== null || camera.roll !== null || camera.distance !== null;
|
|
3612
|
+
}
|
|
3130
3613
|
function formatValue(value) {
|
|
3131
3614
|
if (Array.isArray(value)) {
|
|
3132
3615
|
return value.map((item) => quoteIfNeeded(item)).join(" ");
|
|
@@ -3168,7 +3651,7 @@ var WorldOrbit = (() => {
|
|
|
3168
3651
|
if (orbitFront !== void 0 || orbitBack !== void 0) {
|
|
3169
3652
|
tokens.push(orbitFront !== false || orbitBack !== false ? "orbits" : "-orbits");
|
|
3170
3653
|
}
|
|
3171
|
-
for (const key of ["background", "guides", "relations", "objects", "labels", "metadata"]) {
|
|
3654
|
+
for (const key of ["background", "guides", "relations", "events", "objects", "labels", "metadata"]) {
|
|
3172
3655
|
if (layers[key] !== void 0) {
|
|
3173
3656
|
tokens.push(layers[key] ? key : `-${key}`);
|
|
3174
3657
|
}
|
|
@@ -3196,6 +3679,9 @@ var WorldOrbit = (() => {
|
|
|
3196
3679
|
function compareIdLike(left, right) {
|
|
3197
3680
|
return left.id.localeCompare(right.id);
|
|
3198
3681
|
}
|
|
3682
|
+
function comparePoseObjectId(left, right) {
|
|
3683
|
+
return left.objectId.localeCompare(right.objectId);
|
|
3684
|
+
}
|
|
3199
3685
|
function objectTypeIndex(objectType) {
|
|
3200
3686
|
switch (objectType) {
|
|
3201
3687
|
case "star":
|
|
@@ -3391,6 +3877,7 @@ var WorldOrbit = (() => {
|
|
|
3391
3877
|
const diagnostics = [];
|
|
3392
3878
|
const objectMap = new Map(document2.objects.map((object) => [object.id, object]));
|
|
3393
3879
|
const groupIds = new Set(document2.groups.map((group) => group.id));
|
|
3880
|
+
const eventIds = new Set(document2.events.map((event) => event.id));
|
|
3394
3881
|
if (!document2.system) {
|
|
3395
3882
|
diagnostics.push(error("validate.system.required", "Atlas documents must declare exactly one system."));
|
|
3396
3883
|
}
|
|
@@ -3400,6 +3887,7 @@ var WorldOrbit = (() => {
|
|
|
3400
3887
|
["viewpoint", document2.system?.viewpoints.map((viewpoint) => viewpoint.id) ?? []],
|
|
3401
3888
|
["annotation", document2.system?.annotations.map((annotation) => annotation.id) ?? []],
|
|
3402
3889
|
["relation", document2.relations.map((relation) => relation.id)],
|
|
3890
|
+
["event", document2.events.map((event) => event.id)],
|
|
3403
3891
|
["object", document2.objects.map((object) => object.id)]
|
|
3404
3892
|
]) {
|
|
3405
3893
|
for (const id of ids) {
|
|
@@ -3415,11 +3903,14 @@ var WorldOrbit = (() => {
|
|
|
3415
3903
|
validateRelation(relation, objectMap, diagnostics);
|
|
3416
3904
|
}
|
|
3417
3905
|
for (const viewpoint of document2.system?.viewpoints ?? []) {
|
|
3418
|
-
|
|
3906
|
+
validateViewpoint(viewpoint, groupIds, eventIds, sourceSchemaVersion, diagnostics, objectMap);
|
|
3419
3907
|
}
|
|
3420
3908
|
for (const object of document2.objects) {
|
|
3421
3909
|
validateObject(object, document2.system, objectMap, groupIds, diagnostics);
|
|
3422
3910
|
}
|
|
3911
|
+
for (const event of document2.events) {
|
|
3912
|
+
validateEvent(event, document2.system, objectMap, diagnostics);
|
|
3913
|
+
}
|
|
3423
3914
|
return diagnostics;
|
|
3424
3915
|
}
|
|
3425
3916
|
function validateRelation(relation, objectMap, diagnostics) {
|
|
@@ -3437,15 +3928,24 @@ var WorldOrbit = (() => {
|
|
|
3437
3928
|
diagnostics.push(error("validate.relation.kind.required", `Relation "${relation.id}" is missing a "kind" value.`));
|
|
3438
3929
|
}
|
|
3439
3930
|
}
|
|
3440
|
-
function
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3931
|
+
function validateViewpoint(viewpoint, groupIds, eventIds, sourceSchemaVersion, diagnostics, objectMap) {
|
|
3932
|
+
const filter = viewpoint.filter;
|
|
3933
|
+
if (sourceSchemaVersion === "2.1" || sourceSchemaVersion === "2.5") {
|
|
3934
|
+
if (filter) {
|
|
3935
|
+
for (const groupId of filter.groupIds) {
|
|
3936
|
+
if (!groupIds.has(groupId)) {
|
|
3937
|
+
diagnostics.push(warn("validate.viewpoint.group.unknown", `Unknown group "${groupId}" in viewpoint "${viewpoint.id}".`, void 0, `viewpoint.${viewpoint.id}.groups`));
|
|
3938
|
+
}
|
|
3939
|
+
}
|
|
3940
|
+
}
|
|
3941
|
+
for (const eventId of viewpoint.events ?? []) {
|
|
3942
|
+
if (!eventIds.has(eventId)) {
|
|
3943
|
+
diagnostics.push(warn("validate.viewpoint.event.unknown", `Unknown event "${eventId}" in viewpoint "${viewpoint.id}".`, void 0, `viewpoint.${viewpoint.id}.events`));
|
|
3944
|
+
}
|
|
3447
3945
|
}
|
|
3448
3946
|
}
|
|
3947
|
+
validateProjection(viewpoint.projection, diagnostics, `viewpoint.${viewpoint.id}.projection`, viewpoint.id);
|
|
3948
|
+
validateCamera(viewpoint.camera, viewpoint.projection, viewpoint.rotationDeg, diagnostics, viewpoint.id, viewpoint.focusObjectId, viewpoint.selectedObjectId, filter, objectMap);
|
|
3449
3949
|
}
|
|
3450
3950
|
function validateObject(object, system, objectMap, groupIds, diagnostics) {
|
|
3451
3951
|
const placement = object.placement;
|
|
@@ -3458,6 +3958,12 @@ var WorldOrbit = (() => {
|
|
|
3458
3958
|
}
|
|
3459
3959
|
}
|
|
3460
3960
|
}
|
|
3961
|
+
if (typeof object.epoch === "string" && !object.epoch.trim()) {
|
|
3962
|
+
diagnostics.push(warn("validate.epoch.empty", `Object "${object.id}" defines an empty epoch string.`, object.id, "epoch"));
|
|
3963
|
+
}
|
|
3964
|
+
if (typeof object.referencePlane === "string" && !object.referencePlane.trim()) {
|
|
3965
|
+
diagnostics.push(warn("validate.referencePlane.empty", `Object "${object.id}" defines an empty reference plane string.`, object.id, "referencePlane"));
|
|
3966
|
+
}
|
|
3461
3967
|
if (orbitPlacement) {
|
|
3462
3968
|
if (!objectMap.has(orbitPlacement.target)) {
|
|
3463
3969
|
diagnostics.push(error("validate.orbit.target.unknown", `Unknown placement target "${orbitPlacement.target}" on "${object.id}".`, object.id, "orbit"));
|
|
@@ -3529,6 +4035,122 @@ var WorldOrbit = (() => {
|
|
|
3529
4035
|
}
|
|
3530
4036
|
}
|
|
3531
4037
|
}
|
|
4038
|
+
function validateEvent(event, system, objectMap, diagnostics) {
|
|
4039
|
+
const fieldPrefix = `event.${event.id}`;
|
|
4040
|
+
const referencedIds = /* @__PURE__ */ new Set();
|
|
4041
|
+
if (!event.kind.trim()) {
|
|
4042
|
+
diagnostics.push(error("validate.event.kind.required", `Event "${event.id}" is missing a "kind" value.`, void 0, `${fieldPrefix}.kind`));
|
|
4043
|
+
}
|
|
4044
|
+
if (typeof event.epoch === "string" && !event.epoch.trim()) {
|
|
4045
|
+
diagnostics.push(warn("validate.event.epoch.empty", `Event "${event.id}" defines an empty epoch string.`, void 0, `${fieldPrefix}.epoch`));
|
|
4046
|
+
}
|
|
4047
|
+
if (typeof event.referencePlane === "string" && !event.referencePlane.trim()) {
|
|
4048
|
+
diagnostics.push(warn("validate.event.referencePlane.empty", `Event "${event.id}" defines an empty reference plane string.`, void 0, `${fieldPrefix}.referencePlane`));
|
|
4049
|
+
}
|
|
4050
|
+
if (!event.targetObjectId && event.participantObjectIds.length === 0) {
|
|
4051
|
+
diagnostics.push(error("validate.event.references.required", `Event "${event.id}" must define a "target" or at least one participant.`, void 0, `${fieldPrefix}.participants`));
|
|
4052
|
+
}
|
|
4053
|
+
if (event.targetObjectId) {
|
|
4054
|
+
referencedIds.add(event.targetObjectId);
|
|
4055
|
+
if (!objectMap.has(event.targetObjectId)) {
|
|
4056
|
+
diagnostics.push(error("validate.event.target.unknown", `Unknown event target "${event.targetObjectId}" on "${event.id}".`, void 0, `${fieldPrefix}.target`));
|
|
4057
|
+
}
|
|
4058
|
+
}
|
|
4059
|
+
const seenParticipants = /* @__PURE__ */ new Set();
|
|
4060
|
+
for (const participantId of event.participantObjectIds) {
|
|
4061
|
+
referencedIds.add(participantId);
|
|
4062
|
+
if (seenParticipants.has(participantId)) {
|
|
4063
|
+
diagnostics.push(warn("validate.event.participants.duplicate", `Event "${event.id}" repeats participant "${participantId}".`, void 0, `${fieldPrefix}.participants`));
|
|
4064
|
+
continue;
|
|
4065
|
+
}
|
|
4066
|
+
seenParticipants.add(participantId);
|
|
4067
|
+
if (!objectMap.has(participantId)) {
|
|
4068
|
+
diagnostics.push(error("validate.event.participants.unknown", `Unknown event participant "${participantId}" on "${event.id}".`, void 0, `${fieldPrefix}.participants`));
|
|
4069
|
+
}
|
|
4070
|
+
}
|
|
4071
|
+
if (event.targetObjectId && event.participantObjectIds.length > 0 && !event.participantObjectIds.includes(event.targetObjectId)) {
|
|
4072
|
+
diagnostics.push(warn("validate.event.target.notParticipant", `Event "${event.id}" defines a target outside its participants list.`, void 0, `${fieldPrefix}.target`));
|
|
4073
|
+
}
|
|
4074
|
+
if (event.positions.length === 0) {
|
|
4075
|
+
diagnostics.push(warn("validate.event.positions.missing", `Event "${event.id}" has no positions block and cannot drive a scene snapshot.`, void 0, `${fieldPrefix}.positions`));
|
|
4076
|
+
}
|
|
4077
|
+
if (/(?:^|[-_])(solar-eclipse|lunar-eclipse|transit|occultation)(?:$|[-_])/.test(event.kind) && referencedIds.size < 3) {
|
|
4078
|
+
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`));
|
|
4079
|
+
}
|
|
4080
|
+
const poseIds = /* @__PURE__ */ new Set();
|
|
4081
|
+
for (const pose of event.positions) {
|
|
4082
|
+
const poseFieldPrefix = `${fieldPrefix}.pose.${pose.objectId}`;
|
|
4083
|
+
if (poseIds.has(pose.objectId)) {
|
|
4084
|
+
diagnostics.push(error("validate.event.pose.duplicate", `Event "${event.id}" defines "${pose.objectId}" more than once in positions.`, void 0, poseFieldPrefix));
|
|
4085
|
+
continue;
|
|
4086
|
+
}
|
|
4087
|
+
poseIds.add(pose.objectId);
|
|
4088
|
+
const object = objectMap.get(pose.objectId);
|
|
4089
|
+
if (!object) {
|
|
4090
|
+
diagnostics.push(error("validate.event.pose.object.unknown", `Unknown event pose object "${pose.objectId}" on "${event.id}".`, void 0, poseFieldPrefix));
|
|
4091
|
+
continue;
|
|
4092
|
+
}
|
|
4093
|
+
if (!referencedIds.has(pose.objectId)) {
|
|
4094
|
+
diagnostics.push(warn("validate.event.pose.unreferenced", `Event pose "${pose.objectId}" on "${event.id}" is not listed in target/participants.`, void 0, poseFieldPrefix));
|
|
4095
|
+
}
|
|
4096
|
+
validateEventPose(pose, object, event, system, objectMap, diagnostics, poseFieldPrefix, event.id);
|
|
4097
|
+
}
|
|
4098
|
+
const missingPoseIds = [...referencedIds].filter((objectId) => !poseIds.has(objectId));
|
|
4099
|
+
if (event.positions.length > 0 && missingPoseIds.length > 0) {
|
|
4100
|
+
diagnostics.push(warn("validate.event.positions.partial", `Event "${event.id}" leaves ${missingPoseIds.length} referenced object(s) on their base placement.`, void 0, `${fieldPrefix}.positions`));
|
|
4101
|
+
}
|
|
4102
|
+
}
|
|
4103
|
+
function validateEventPose(pose, object, event, system, objectMap, diagnostics, fieldPrefix, eventId) {
|
|
4104
|
+
const placement = pose.placement;
|
|
4105
|
+
if (!placement) {
|
|
4106
|
+
diagnostics.push(error("validate.event.pose.placement.required", `Event "${eventId}" pose "${pose.objectId}" is missing a placement mode.`, void 0, fieldPrefix));
|
|
4107
|
+
return;
|
|
4108
|
+
}
|
|
4109
|
+
if (placement.mode === "orbit") {
|
|
4110
|
+
if (!objectMap.has(placement.target)) {
|
|
4111
|
+
diagnostics.push(error("validate.event.pose.orbit.target.unknown", `Unknown event orbit target "${placement.target}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.orbit`));
|
|
4112
|
+
}
|
|
4113
|
+
if (placement.distance && placement.semiMajor) {
|
|
4114
|
+
diagnostics.push(error("validate.event.pose.orbit.distanceConflict", `Event "${eventId}" pose "${pose.objectId}" cannot declare both "distance" and "semiMajor".`, void 0, `${fieldPrefix}.distance`));
|
|
4115
|
+
}
|
|
4116
|
+
if (placement.phase && !resolveEffectiveEpoch(system, object, event, pose)) {
|
|
4117
|
+
diagnostics.push(warn("validate.event.pose.phase.epochMissing", `Event "${eventId}" pose "${pose.objectId}" sets "phase" without an effective epoch.`, void 0, `${fieldPrefix}.phase`));
|
|
4118
|
+
}
|
|
4119
|
+
if (placement.inclination && !resolveEffectiveReferencePlane(system, object, event, pose)) {
|
|
4120
|
+
diagnostics.push(warn("validate.event.pose.inclination.referencePlaneMissing", `Event "${eventId}" pose "${pose.objectId}" sets "inclination" without an effective reference plane.`, void 0, `${fieldPrefix}.inclination`));
|
|
4121
|
+
}
|
|
4122
|
+
if (placement.period && !massInSolar(objectMap.get(placement.target)?.properties.mass)) {
|
|
4123
|
+
diagnostics.push(warn("validate.event.pose.period.massMissing", `Event "${eventId}" pose "${pose.objectId}" sets "period" but its central mass cannot be derived.`, void 0, `${fieldPrefix}.period`));
|
|
4124
|
+
}
|
|
4125
|
+
return;
|
|
4126
|
+
}
|
|
4127
|
+
if (placement.mode === "surface") {
|
|
4128
|
+
const target = objectMap.get(placement.target);
|
|
4129
|
+
if (!target) {
|
|
4130
|
+
diagnostics.push(error("validate.event.pose.surface.target.unknown", `Unknown event surface target "${placement.target}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.surface`));
|
|
4131
|
+
} else if (!SURFACE_TARGET_TYPES2.has(target.type)) {
|
|
4132
|
+
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`));
|
|
4133
|
+
}
|
|
4134
|
+
return;
|
|
4135
|
+
}
|
|
4136
|
+
if (placement.mode === "at") {
|
|
4137
|
+
if (object.type !== "structure" && object.type !== "phenomenon") {
|
|
4138
|
+
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`));
|
|
4139
|
+
}
|
|
4140
|
+
const reference = placement.reference;
|
|
4141
|
+
if (reference.kind === "named" && !objectMap.has(reference.name)) {
|
|
4142
|
+
diagnostics.push(error("validate.event.pose.at.target.unknown", `Unknown event at-reference target "${placement.target}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.at`));
|
|
4143
|
+
} else if (reference.kind === "anchor" && !objectMap.has(reference.objectId)) {
|
|
4144
|
+
diagnostics.push(error("validate.event.pose.anchor.target.unknown", `Unknown event anchor target "${reference.objectId}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.at`));
|
|
4145
|
+
} else if (reference.kind === "lagrange") {
|
|
4146
|
+
if (!objectMap.has(reference.primary)) {
|
|
4147
|
+
diagnostics.push(error("validate.event.pose.lagrange.primary.unknown", `Unknown event Lagrange target "${reference.primary}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.at`));
|
|
4148
|
+
} else if (reference.secondary && !objectMap.has(reference.secondary)) {
|
|
4149
|
+
diagnostics.push(error("validate.event.pose.lagrange.secondary.unknown", `Unknown event Lagrange target "${reference.secondary}" on "${eventId}:${pose.objectId}".`, void 0, `${fieldPrefix}.at`));
|
|
4150
|
+
}
|
|
4151
|
+
}
|
|
4152
|
+
}
|
|
4153
|
+
}
|
|
3532
4154
|
function validateAtTarget(object, objectMap, diagnostics) {
|
|
3533
4155
|
const reference = object.placement?.mode === "at" ? object.placement.reference : null;
|
|
3534
4156
|
if (!reference) {
|
|
@@ -3634,6 +4256,52 @@ var WorldOrbit = (() => {
|
|
|
3634
4256
|
return null;
|
|
3635
4257
|
}
|
|
3636
4258
|
}
|
|
4259
|
+
function validateProjection(projection, diagnostics, field, viewpointId) {
|
|
4260
|
+
if (projection !== "topdown" && projection !== "isometric" && projection !== "orthographic" && projection !== "perspective") {
|
|
4261
|
+
diagnostics.push(error("validate.viewpoint.projection.invalid", `Unknown projection "${String(projection)}" in viewpoint "${viewpointId}".`, void 0, field));
|
|
4262
|
+
}
|
|
4263
|
+
}
|
|
4264
|
+
function validateCamera(camera, projection, rotationDeg, diagnostics, viewpointId, focusObjectId, selectedObjectId, filter, objectMap) {
|
|
4265
|
+
if (!camera) {
|
|
4266
|
+
return;
|
|
4267
|
+
}
|
|
4268
|
+
const prefix = `viewpoint.${viewpointId}.camera`;
|
|
4269
|
+
for (const [key, value] of [
|
|
4270
|
+
["azimuth", camera.azimuth],
|
|
4271
|
+
["elevation", camera.elevation],
|
|
4272
|
+
["roll", camera.roll],
|
|
4273
|
+
["distance", camera.distance]
|
|
4274
|
+
]) {
|
|
4275
|
+
if (value !== null && (!Number.isFinite(value) || key === "distance" && value <= 0)) {
|
|
4276
|
+
diagnostics.push(error("validate.viewpoint.camera.invalid", `Invalid camera ${key} "${String(value)}" in viewpoint "${viewpointId}".`, void 0, `${prefix}.${key}`));
|
|
4277
|
+
}
|
|
4278
|
+
}
|
|
4279
|
+
if (camera.distance !== null && projection !== "perspective") {
|
|
4280
|
+
diagnostics.push(warn("validate.viewpoint.camera.distance.partialEffect", `Camera "distance" only has a semantic effect in perspective viewpoints; "${viewpointId}" uses "${projection}".`, void 0, `${prefix}.distance`));
|
|
4281
|
+
}
|
|
4282
|
+
if (projection === "topdown" && (camera.elevation !== null || camera.roll !== null)) {
|
|
4283
|
+
diagnostics.push(warn("validate.viewpoint.camera.topdownPartial", `Camera elevation/roll on topdown viewpoint "${viewpointId}" are currently stored for future 3D use and only partially affect 2D rendering.`, void 0, prefix));
|
|
4284
|
+
}
|
|
4285
|
+
if (projection === "isometric" && camera.elevation !== null) {
|
|
4286
|
+
diagnostics.push(info("validate.viewpoint.camera.isometricStored", `Camera elevation on isometric viewpoint "${viewpointId}" is preserved semantically for future 3D rendering.`, void 0, `${prefix}.elevation`));
|
|
4287
|
+
}
|
|
4288
|
+
if (camera.azimuth !== null && camera.azimuth !== 0 && rotationDeg !== 0) {
|
|
4289
|
+
diagnostics.push(warn("validate.viewpoint.rotation.cameraOverlap", `Viewpoint "${viewpointId}" uses camera.azimuth; keep "rotation" only for 2D screen rotation to avoid ambiguity.`, void 0, `${prefix}.azimuth`));
|
|
4290
|
+
}
|
|
4291
|
+
const hasAnchor = focusObjectId !== null && objectMap.has(focusObjectId) || selectedObjectId !== null && objectMap.has(selectedObjectId) || !!filter;
|
|
4292
|
+
if (!hasAnchor) {
|
|
4293
|
+
diagnostics.push(info("validate.viewpoint.camera.anchorMissing", `Viewpoint "${viewpointId}" stores camera settings without a focus object, selection, or filter anchor.`, void 0, prefix));
|
|
4294
|
+
}
|
|
4295
|
+
}
|
|
4296
|
+
function resolveEffectiveEpoch(system, object, event, pose) {
|
|
4297
|
+
return normalizeOptionalContextString(pose?.epoch) ?? normalizeOptionalContextString(event?.epoch) ?? normalizeOptionalContextString(object.epoch) ?? normalizeOptionalContextString(system?.epoch) ?? null;
|
|
4298
|
+
}
|
|
4299
|
+
function resolveEffectiveReferencePlane(system, object, event, pose) {
|
|
4300
|
+
return normalizeOptionalContextString(pose?.referencePlane) ?? normalizeOptionalContextString(event?.referencePlane) ?? normalizeOptionalContextString(object.referencePlane) ?? normalizeOptionalContextString(system?.referencePlane) ?? null;
|
|
4301
|
+
}
|
|
4302
|
+
function normalizeOptionalContextString(value) {
|
|
4303
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
4304
|
+
}
|
|
3637
4305
|
function toleranceForField(object, field) {
|
|
3638
4306
|
const tolerance = object.tolerances?.find((entry) => entry.field === field)?.value;
|
|
3639
4307
|
if (typeof tolerance === "number") {
|
|
@@ -3729,6 +4397,23 @@ var WorldOrbit = (() => {
|
|
|
3729
4397
|
});
|
|
3730
4398
|
}
|
|
3731
4399
|
var DRAFT_OBJECT_FIELD_KEYS = new Set(DRAFT_OBJECT_FIELD_SPECS.keys());
|
|
4400
|
+
var EVENT_POSE_FIELD_KEYS = /* @__PURE__ */ new Set([
|
|
4401
|
+
"orbit",
|
|
4402
|
+
"distance",
|
|
4403
|
+
"semiMajor",
|
|
4404
|
+
"eccentricity",
|
|
4405
|
+
"period",
|
|
4406
|
+
"angle",
|
|
4407
|
+
"inclination",
|
|
4408
|
+
"phase",
|
|
4409
|
+
"at",
|
|
4410
|
+
"surface",
|
|
4411
|
+
"free",
|
|
4412
|
+
"inner",
|
|
4413
|
+
"outer",
|
|
4414
|
+
"epoch",
|
|
4415
|
+
"referencePlane"
|
|
4416
|
+
]);
|
|
3732
4417
|
function parseWorldOrbitAtlas(source) {
|
|
3733
4418
|
return parseAtlasSource(source);
|
|
3734
4419
|
}
|
|
@@ -3743,12 +4428,15 @@ var WorldOrbit = (() => {
|
|
|
3743
4428
|
const objectNodes = [];
|
|
3744
4429
|
const groups = [];
|
|
3745
4430
|
const relations = [];
|
|
4431
|
+
const events = [];
|
|
4432
|
+
const eventPoseNodes = /* @__PURE__ */ new Map();
|
|
3746
4433
|
let sawDefaults = false;
|
|
3747
4434
|
let sawAtlas = false;
|
|
3748
4435
|
const viewpointIds = /* @__PURE__ */ new Set();
|
|
3749
4436
|
const annotationIds = /* @__PURE__ */ new Set();
|
|
3750
4437
|
const groupIds = /* @__PURE__ */ new Set();
|
|
3751
4438
|
const relationIds = /* @__PURE__ */ new Set();
|
|
4439
|
+
const eventIds = /* @__PURE__ */ new Set();
|
|
3752
4440
|
for (let index = 0; index < lines.length; index++) {
|
|
3753
4441
|
const rawLine = lines[index];
|
|
3754
4442
|
const lineNumber = index + 1;
|
|
@@ -3766,7 +4454,7 @@ var WorldOrbit = (() => {
|
|
|
3766
4454
|
if (!sawSchemaHeader) {
|
|
3767
4455
|
sourceSchemaVersion = assertDraftSchemaHeader(tokens, lineNumber);
|
|
3768
4456
|
sawSchemaHeader = true;
|
|
3769
|
-
if (prepared.comments.length > 0 && sourceSchemaVersion
|
|
4457
|
+
if (prepared.comments.length > 0 && isSchemaOlderThan(sourceSchemaVersion, "2.1")) {
|
|
3770
4458
|
diagnostics.push({
|
|
3771
4459
|
code: "parse.schema21.commentCompatibility",
|
|
3772
4460
|
severity: "warning",
|
|
@@ -3779,7 +4467,7 @@ var WorldOrbit = (() => {
|
|
|
3779
4467
|
continue;
|
|
3780
4468
|
}
|
|
3781
4469
|
if (indent === 0) {
|
|
3782
|
-
section = startTopLevelSection(tokens, lineNumber, sourceSchemaVersion, diagnostics, system, objectNodes, groups, relations, viewpointIds, annotationIds, groupIds, relationIds, { sawDefaults, sawAtlas });
|
|
4470
|
+
section = startTopLevelSection(tokens, lineNumber, sourceSchemaVersion, diagnostics, system, objectNodes, groups, relations, events, eventPoseNodes, viewpointIds, annotationIds, groupIds, relationIds, eventIds, { sawDefaults, sawAtlas });
|
|
3783
4471
|
if (section.kind === "system") {
|
|
3784
4472
|
system = section.system;
|
|
3785
4473
|
} else if (section.kind === "defaults") {
|
|
@@ -3798,6 +4486,7 @@ var WorldOrbit = (() => {
|
|
|
3798
4486
|
throw new WorldOrbitError('Missing required atlas schema header "schema 2.0"');
|
|
3799
4487
|
}
|
|
3800
4488
|
const objects = objectNodes.map((node) => normalizeDraftObject(node, sourceSchemaVersion, diagnostics));
|
|
4489
|
+
const normalizedEvents = events.map((event) => normalizeDraftEvent(event, eventPoseNodes.get(event.id) ?? []));
|
|
3801
4490
|
const outputVersion = forcedOutputVersion ?? (sourceSchemaVersion === "2.0-draft" ? "2.0" : sourceSchemaVersion);
|
|
3802
4491
|
const baseDocument = {
|
|
3803
4492
|
format: "worldorbit",
|
|
@@ -3805,6 +4494,7 @@ var WorldOrbit = (() => {
|
|
|
3805
4494
|
system,
|
|
3806
4495
|
groups,
|
|
3807
4496
|
relations,
|
|
4497
|
+
events: normalizedEvents,
|
|
3808
4498
|
objects,
|
|
3809
4499
|
diagnostics
|
|
3810
4500
|
};
|
|
@@ -3834,13 +4524,13 @@ var WorldOrbit = (() => {
|
|
|
3834
4524
|
return document2;
|
|
3835
4525
|
}
|
|
3836
4526
|
function assertDraftSchemaHeader(tokens, line) {
|
|
3837
|
-
if (tokens.length !== 2 || tokens[0].value.toLowerCase() !== "schema" || !["2.0-draft", "2.0", "2.1"].includes(tokens[1].value.toLowerCase())) {
|
|
3838
|
-
throw new WorldOrbitError('Expected atlas header "schema 2.0", "schema 2.1", or legacy "schema 2.0-draft"', line, tokens[0]?.column ?? 1);
|
|
4527
|
+
if (tokens.length !== 2 || tokens[0].value.toLowerCase() !== "schema" || !["2.0-draft", "2.0", "2.1", "2.5"].includes(tokens[1].value.toLowerCase())) {
|
|
4528
|
+
throw new WorldOrbitError('Expected atlas header "schema 2.0", "schema 2.1", "schema 2.5", or legacy "schema 2.0-draft"', line, tokens[0]?.column ?? 1);
|
|
3839
4529
|
}
|
|
3840
4530
|
const version = tokens[1].value.toLowerCase();
|
|
3841
|
-
return version === "2.1" ? "2.1" : version === "2.0-draft" ? "2.0-draft" : "2.0";
|
|
4531
|
+
return version === "2.5" ? "2.5" : version === "2.1" ? "2.1" : version === "2.0-draft" ? "2.0-draft" : "2.0";
|
|
3842
4532
|
}
|
|
3843
|
-
function startTopLevelSection(tokens, line, sourceSchemaVersion, diagnostics, system, objectNodes, groups, relations, viewpointIds, annotationIds, groupIds, relationIds, flags) {
|
|
4533
|
+
function startTopLevelSection(tokens, line, sourceSchemaVersion, diagnostics, system, objectNodes, groups, relations, events, eventPoseNodes, viewpointIds, annotationIds, groupIds, relationIds, eventIds, flags) {
|
|
3844
4534
|
const keyword = tokens[0]?.value.toLowerCase();
|
|
3845
4535
|
switch (keyword) {
|
|
3846
4536
|
case "system":
|
|
@@ -3858,6 +4548,8 @@ var WorldOrbit = (() => {
|
|
|
3858
4548
|
return {
|
|
3859
4549
|
kind: "defaults",
|
|
3860
4550
|
system,
|
|
4551
|
+
sourceSchemaVersion,
|
|
4552
|
+
diagnostics,
|
|
3861
4553
|
seenFields: /* @__PURE__ */ new Set()
|
|
3862
4554
|
};
|
|
3863
4555
|
case "atlas":
|
|
@@ -3877,7 +4569,7 @@ var WorldOrbit = (() => {
|
|
|
3877
4569
|
if (!system) {
|
|
3878
4570
|
throw new WorldOrbitError('Atlas section "viewpoint" requires a preceding system declaration', line, tokens[0].column);
|
|
3879
4571
|
}
|
|
3880
|
-
return startViewpointSection(tokens, line, system, viewpointIds);
|
|
4572
|
+
return startViewpointSection(tokens, line, system, viewpointIds, sourceSchemaVersion, diagnostics);
|
|
3881
4573
|
case "annotation":
|
|
3882
4574
|
if (!system) {
|
|
3883
4575
|
throw new WorldOrbitError('Atlas section "annotation" requires a preceding system declaration', line, tokens[0].column);
|
|
@@ -3889,6 +4581,9 @@ var WorldOrbit = (() => {
|
|
|
3889
4581
|
case "relation":
|
|
3890
4582
|
warnIfSchema21Feature(sourceSchemaVersion, diagnostics, "relation", { line, column: tokens[0].column });
|
|
3891
4583
|
return startRelationSection(tokens, line, relations, relationIds);
|
|
4584
|
+
case "event":
|
|
4585
|
+
warnIfSchema21Feature(sourceSchemaVersion, diagnostics, "event", { line, column: tokens[0].column });
|
|
4586
|
+
return startEventSection(tokens, line, events, eventPoseNodes, eventIds, sourceSchemaVersion, diagnostics);
|
|
3892
4587
|
case "object":
|
|
3893
4588
|
return startObjectSection(tokens, line, sourceSchemaVersion, diagnostics, objectNodes);
|
|
3894
4589
|
default:
|
|
@@ -3925,7 +4620,7 @@ var WorldOrbit = (() => {
|
|
|
3925
4620
|
seenFields: /* @__PURE__ */ new Set()
|
|
3926
4621
|
};
|
|
3927
4622
|
}
|
|
3928
|
-
function startViewpointSection(tokens, line, system, viewpointIds) {
|
|
4623
|
+
function startViewpointSection(tokens, line, system, viewpointIds, sourceSchemaVersion, diagnostics) {
|
|
3929
4624
|
if (tokens.length !== 2) {
|
|
3930
4625
|
throw new WorldOrbitError("Invalid viewpoint declaration", line, tokens[0]?.column ?? 1);
|
|
3931
4626
|
}
|
|
@@ -3942,10 +4637,12 @@ var WorldOrbit = (() => {
|
|
|
3942
4637
|
summary: "",
|
|
3943
4638
|
focusObjectId: null,
|
|
3944
4639
|
selectedObjectId: null,
|
|
4640
|
+
events: [],
|
|
3945
4641
|
projection: system.defaults.view,
|
|
3946
4642
|
preset: system.defaults.preset,
|
|
3947
4643
|
zoom: null,
|
|
3948
4644
|
rotationDeg: 0,
|
|
4645
|
+
camera: null,
|
|
3949
4646
|
layers: {},
|
|
3950
4647
|
filter: null
|
|
3951
4648
|
};
|
|
@@ -3954,10 +4651,15 @@ var WorldOrbit = (() => {
|
|
|
3954
4651
|
return {
|
|
3955
4652
|
kind: "viewpoint",
|
|
3956
4653
|
viewpoint,
|
|
4654
|
+
sourceSchemaVersion,
|
|
4655
|
+
diagnostics,
|
|
3957
4656
|
seenFields: /* @__PURE__ */ new Set(),
|
|
3958
4657
|
inFilter: false,
|
|
3959
4658
|
filterIndent: null,
|
|
3960
|
-
seenFilterFields: /* @__PURE__ */ new Set()
|
|
4659
|
+
seenFilterFields: /* @__PURE__ */ new Set(),
|
|
4660
|
+
inCamera: false,
|
|
4661
|
+
cameraIndent: null,
|
|
4662
|
+
seenCameraFields: /* @__PURE__ */ new Set()
|
|
3961
4663
|
};
|
|
3962
4664
|
}
|
|
3963
4665
|
function startAnnotationSection(tokens, line, system, annotationIds) {
|
|
@@ -4044,6 +4746,51 @@ var WorldOrbit = (() => {
|
|
|
4044
4746
|
seenFields: /* @__PURE__ */ new Set()
|
|
4045
4747
|
};
|
|
4046
4748
|
}
|
|
4749
|
+
function startEventSection(tokens, line, events, eventPoseNodes, eventIds, sourceSchemaVersion, diagnostics) {
|
|
4750
|
+
if (tokens.length !== 2) {
|
|
4751
|
+
throw new WorldOrbitError("Invalid event declaration", line, tokens[0]?.column ?? 1);
|
|
4752
|
+
}
|
|
4753
|
+
const id = normalizeIdentifier2(tokens[1].value);
|
|
4754
|
+
if (!id) {
|
|
4755
|
+
throw new WorldOrbitError("Event id must not be empty", line, tokens[1].column);
|
|
4756
|
+
}
|
|
4757
|
+
if (eventIds.has(id)) {
|
|
4758
|
+
throw new WorldOrbitError(`Duplicate event id "${id}"`, line, tokens[1].column);
|
|
4759
|
+
}
|
|
4760
|
+
const event = {
|
|
4761
|
+
id,
|
|
4762
|
+
kind: "",
|
|
4763
|
+
label: humanizeIdentifier3(id),
|
|
4764
|
+
summary: null,
|
|
4765
|
+
targetObjectId: null,
|
|
4766
|
+
participantObjectIds: [],
|
|
4767
|
+
timing: null,
|
|
4768
|
+
visibility: null,
|
|
4769
|
+
epoch: null,
|
|
4770
|
+
referencePlane: null,
|
|
4771
|
+
tags: [],
|
|
4772
|
+
color: null,
|
|
4773
|
+
hidden: false,
|
|
4774
|
+
positions: []
|
|
4775
|
+
};
|
|
4776
|
+
const rawPoses = [];
|
|
4777
|
+
events.push(event);
|
|
4778
|
+
eventPoseNodes.set(id, rawPoses);
|
|
4779
|
+
eventIds.add(id);
|
|
4780
|
+
return {
|
|
4781
|
+
kind: "event",
|
|
4782
|
+
event,
|
|
4783
|
+
sourceSchemaVersion,
|
|
4784
|
+
diagnostics,
|
|
4785
|
+
seenFields: /* @__PURE__ */ new Set(),
|
|
4786
|
+
rawPoses,
|
|
4787
|
+
inPositions: false,
|
|
4788
|
+
positionsIndent: null,
|
|
4789
|
+
activePose: null,
|
|
4790
|
+
poseIndent: null,
|
|
4791
|
+
activePoseSeenFields: /* @__PURE__ */ new Set()
|
|
4792
|
+
};
|
|
4793
|
+
}
|
|
4047
4794
|
function startObjectSection(tokens, line, sourceSchemaVersion, diagnostics, objectNodes) {
|
|
4048
4795
|
if (tokens.length < 3) {
|
|
4049
4796
|
throw new WorldOrbitError("Invalid atlas object declaration", line, tokens[0]?.column ?? 1);
|
|
@@ -4100,6 +4847,9 @@ var WorldOrbit = (() => {
|
|
|
4100
4847
|
case "relation":
|
|
4101
4848
|
applyRelationField(section, tokens, line);
|
|
4102
4849
|
return;
|
|
4850
|
+
case "event":
|
|
4851
|
+
applyEventField(section, indent, tokens, line);
|
|
4852
|
+
return;
|
|
4103
4853
|
case "object":
|
|
4104
4854
|
applyObjectField(section, indent, tokens, line);
|
|
4105
4855
|
return;
|
|
@@ -4142,6 +4892,12 @@ var WorldOrbit = (() => {
|
|
|
4142
4892
|
const value = joinFieldValue(tokens, line);
|
|
4143
4893
|
switch (key) {
|
|
4144
4894
|
case "view":
|
|
4895
|
+
if (isSchema25Projection(value)) {
|
|
4896
|
+
warnIfSchema25Feature(section.sourceSchemaVersion, section.diagnostics, "defaults.view", {
|
|
4897
|
+
line,
|
|
4898
|
+
column: tokens[0].column
|
|
4899
|
+
});
|
|
4900
|
+
}
|
|
4145
4901
|
section.system.defaults.view = parseProjectionValue(value, line, tokens[0].column);
|
|
4146
4902
|
return;
|
|
4147
4903
|
case "scale":
|
|
@@ -4181,14 +4937,36 @@ var WorldOrbit = (() => {
|
|
|
4181
4937
|
throw new WorldOrbitError(`Unknown atlas field "${tokens[0].value}"`, line, tokens[0].column);
|
|
4182
4938
|
}
|
|
4183
4939
|
function applyViewpointField2(section, indent, tokens, line) {
|
|
4940
|
+
if (section.inCamera && indent <= (section.cameraIndent ?? 0)) {
|
|
4941
|
+
section.inCamera = false;
|
|
4942
|
+
section.cameraIndent = null;
|
|
4943
|
+
}
|
|
4184
4944
|
if (section.inFilter && indent <= (section.filterIndent ?? 0)) {
|
|
4185
4945
|
section.inFilter = false;
|
|
4186
4946
|
section.filterIndent = null;
|
|
4187
4947
|
}
|
|
4948
|
+
if (section.inCamera) {
|
|
4949
|
+
applyViewpointCameraField(section, tokens, line);
|
|
4950
|
+
return;
|
|
4951
|
+
}
|
|
4188
4952
|
if (section.inFilter) {
|
|
4189
4953
|
applyViewpointFilterField(section, tokens, line);
|
|
4190
4954
|
return;
|
|
4191
4955
|
}
|
|
4956
|
+
if (tokens.length === 1 && tokens[0].value.toLowerCase() === "camera") {
|
|
4957
|
+
warnIfSchema25Feature(section.sourceSchemaVersion, section.diagnostics, "viewpoint.camera", {
|
|
4958
|
+
line,
|
|
4959
|
+
column: tokens[0].column
|
|
4960
|
+
});
|
|
4961
|
+
if (section.seenFields.has("camera")) {
|
|
4962
|
+
throw new WorldOrbitError('Duplicate viewpoint field "camera"', line, tokens[0].column);
|
|
4963
|
+
}
|
|
4964
|
+
section.seenFields.add("camera");
|
|
4965
|
+
section.inCamera = true;
|
|
4966
|
+
section.cameraIndent = indent;
|
|
4967
|
+
section.viewpoint.camera = section.viewpoint.camera ?? createEmptyViewCamera2();
|
|
4968
|
+
return;
|
|
4969
|
+
}
|
|
4192
4970
|
if (tokens.length === 1 && tokens[0].value.toLowerCase() === "filter") {
|
|
4193
4971
|
if (section.seenFields.has("filter")) {
|
|
4194
4972
|
throw new WorldOrbitError('Duplicate viewpoint field "filter"', line, tokens[0].column);
|
|
@@ -4214,6 +4992,12 @@ var WorldOrbit = (() => {
|
|
|
4214
4992
|
section.viewpoint.selectedObjectId = value;
|
|
4215
4993
|
return;
|
|
4216
4994
|
case "projection":
|
|
4995
|
+
if (isSchema25Projection(value)) {
|
|
4996
|
+
warnIfSchema25Feature(section.sourceSchemaVersion, section.diagnostics, "projection", {
|
|
4997
|
+
line,
|
|
4998
|
+
column: tokens[0].column
|
|
4999
|
+
});
|
|
5000
|
+
}
|
|
4217
5001
|
section.viewpoint.projection = parseProjectionValue(value, line, tokens[0].column);
|
|
4218
5002
|
return;
|
|
4219
5003
|
case "preset":
|
|
@@ -4225,13 +5009,49 @@ var WorldOrbit = (() => {
|
|
|
4225
5009
|
case "rotation":
|
|
4226
5010
|
section.viewpoint.rotationDeg = parseFiniteNumber2(value, line, tokens[0].column, "rotation");
|
|
4227
5011
|
return;
|
|
5012
|
+
case "camera":
|
|
5013
|
+
warnIfSchema25Feature(section.sourceSchemaVersion, section.diagnostics, "viewpoint.camera", {
|
|
5014
|
+
line,
|
|
5015
|
+
column: tokens[0].column
|
|
5016
|
+
});
|
|
5017
|
+
section.viewpoint.camera = parseInlineViewCamera(tokens.slice(1), line, section.viewpoint.camera);
|
|
5018
|
+
return;
|
|
4228
5019
|
case "layers":
|
|
4229
|
-
section.viewpoint.layers = parseLayerTokens(tokens.slice(1), line);
|
|
5020
|
+
section.viewpoint.layers = parseLayerTokens(tokens.slice(1), line, section.sourceSchemaVersion, section.diagnostics);
|
|
5021
|
+
return;
|
|
5022
|
+
case "events":
|
|
5023
|
+
warnIfSchema21Feature(section.sourceSchemaVersion, section.diagnostics, "viewpoint.events", {
|
|
5024
|
+
line,
|
|
5025
|
+
column: tokens[0].column
|
|
5026
|
+
});
|
|
5027
|
+
section.viewpoint.events = parseTokenList(tokens.slice(1), line, "events");
|
|
4230
5028
|
return;
|
|
4231
5029
|
default:
|
|
4232
5030
|
throw new WorldOrbitError(`Unknown viewpoint field "${tokens[0].value}"`, line, tokens[0].column);
|
|
4233
5031
|
}
|
|
4234
5032
|
}
|
|
5033
|
+
function applyViewpointCameraField(section, tokens, line) {
|
|
5034
|
+
const key = requireUniqueField(tokens, section.seenCameraFields, line);
|
|
5035
|
+
const value = joinFieldValue(tokens, line);
|
|
5036
|
+
const camera = section.viewpoint.camera ?? createEmptyViewCamera2();
|
|
5037
|
+
switch (key) {
|
|
5038
|
+
case "azimuth":
|
|
5039
|
+
camera.azimuth = parseFiniteNumber2(value, line, tokens[0].column, "camera.azimuth");
|
|
5040
|
+
break;
|
|
5041
|
+
case "elevation":
|
|
5042
|
+
camera.elevation = parseFiniteNumber2(value, line, tokens[0].column, "camera.elevation");
|
|
5043
|
+
break;
|
|
5044
|
+
case "roll":
|
|
5045
|
+
camera.roll = parseFiniteNumber2(value, line, tokens[0].column, "camera.roll");
|
|
5046
|
+
break;
|
|
5047
|
+
case "distance":
|
|
5048
|
+
camera.distance = parsePositiveNumber2(value, line, tokens[0].column, "camera.distance");
|
|
5049
|
+
break;
|
|
5050
|
+
default:
|
|
5051
|
+
throw new WorldOrbitError(`Unknown viewpoint camera field "${tokens[0].value}"`, line, tokens[0].column);
|
|
5052
|
+
}
|
|
5053
|
+
section.viewpoint.camera = camera;
|
|
5054
|
+
}
|
|
4235
5055
|
function applyViewpointFilterField(section, tokens, line) {
|
|
4236
5056
|
const key = requireUniqueField(tokens, section.seenFilterFields, line);
|
|
4237
5057
|
const filter = section.viewpoint.filter ?? createEmptyViewpointFilter2();
|
|
@@ -4331,6 +5151,126 @@ var WorldOrbit = (() => {
|
|
|
4331
5151
|
throw new WorldOrbitError(`Unknown relation field "${tokens[0].value}"`, line, tokens[0].column);
|
|
4332
5152
|
}
|
|
4333
5153
|
}
|
|
5154
|
+
function applyEventField(section, indent, tokens, line) {
|
|
5155
|
+
if (section.activePose && indent <= (section.poseIndent ?? 0)) {
|
|
5156
|
+
section.activePose = null;
|
|
5157
|
+
section.poseIndent = null;
|
|
5158
|
+
section.activePoseSeenFields.clear();
|
|
5159
|
+
}
|
|
5160
|
+
if (!section.activePose && section.inPositions && indent <= (section.positionsIndent ?? 0)) {
|
|
5161
|
+
section.inPositions = false;
|
|
5162
|
+
section.positionsIndent = null;
|
|
5163
|
+
}
|
|
5164
|
+
if (section.activePose) {
|
|
5165
|
+
if (tokens[0]?.value === "epoch" || tokens[0]?.value === "referencePlane") {
|
|
5166
|
+
warnIfSchema25Feature(section.sourceSchemaVersion, section.diagnostics, `pose.${tokens[0].value}`, {
|
|
5167
|
+
line,
|
|
5168
|
+
column: tokens[0]?.column ?? 1
|
|
5169
|
+
});
|
|
5170
|
+
}
|
|
5171
|
+
section.activePose.fields.push(parseEventPoseField(tokens, line, section.activePoseSeenFields));
|
|
5172
|
+
return;
|
|
5173
|
+
}
|
|
5174
|
+
if (section.inPositions) {
|
|
5175
|
+
if (tokens.length !== 2 || tokens[0].value.toLowerCase() !== "pose") {
|
|
5176
|
+
throw new WorldOrbitError(`Unknown event positions field "${tokens[0].value}"`, line, tokens[0]?.column ?? 1);
|
|
5177
|
+
}
|
|
5178
|
+
const objectId = tokens[1].value;
|
|
5179
|
+
if (!objectId.trim()) {
|
|
5180
|
+
throw new WorldOrbitError("Event pose object id must not be empty", line, tokens[1].column);
|
|
5181
|
+
}
|
|
5182
|
+
const rawPose = {
|
|
5183
|
+
objectId,
|
|
5184
|
+
fields: [],
|
|
5185
|
+
location: { line, column: tokens[0].column }
|
|
5186
|
+
};
|
|
5187
|
+
section.rawPoses.push(rawPose);
|
|
5188
|
+
section.activePose = rawPose;
|
|
5189
|
+
section.poseIndent = indent;
|
|
5190
|
+
section.activePoseSeenFields = /* @__PURE__ */ new Set();
|
|
5191
|
+
return;
|
|
5192
|
+
}
|
|
5193
|
+
if (tokens.length === 1 && tokens[0].value.toLowerCase() === "positions") {
|
|
5194
|
+
if (section.seenFields.has("positions")) {
|
|
5195
|
+
throw new WorldOrbitError('Duplicate event field "positions"', line, tokens[0].column);
|
|
5196
|
+
}
|
|
5197
|
+
section.seenFields.add("positions");
|
|
5198
|
+
section.inPositions = true;
|
|
5199
|
+
section.positionsIndent = indent;
|
|
5200
|
+
return;
|
|
5201
|
+
}
|
|
5202
|
+
const key = requireUniqueField(tokens, section.seenFields, line);
|
|
5203
|
+
switch (key) {
|
|
5204
|
+
case "kind":
|
|
5205
|
+
section.event.kind = joinFieldValue(tokens, line);
|
|
5206
|
+
return;
|
|
5207
|
+
case "label":
|
|
5208
|
+
section.event.label = joinFieldValue(tokens, line);
|
|
5209
|
+
return;
|
|
5210
|
+
case "summary":
|
|
5211
|
+
section.event.summary = joinFieldValue(tokens, line);
|
|
5212
|
+
return;
|
|
5213
|
+
case "target":
|
|
5214
|
+
section.event.targetObjectId = joinFieldValue(tokens, line);
|
|
5215
|
+
return;
|
|
5216
|
+
case "participants":
|
|
5217
|
+
section.event.participantObjectIds = parseTokenList(tokens.slice(1), line, "participants");
|
|
5218
|
+
return;
|
|
5219
|
+
case "timing":
|
|
5220
|
+
section.event.timing = joinFieldValue(tokens, line);
|
|
5221
|
+
return;
|
|
5222
|
+
case "visibility":
|
|
5223
|
+
section.event.visibility = joinFieldValue(tokens, line);
|
|
5224
|
+
return;
|
|
5225
|
+
case "epoch":
|
|
5226
|
+
warnIfSchema25Feature(section.sourceSchemaVersion, section.diagnostics, "event.epoch", {
|
|
5227
|
+
line,
|
|
5228
|
+
column: tokens[0].column
|
|
5229
|
+
});
|
|
5230
|
+
section.event.epoch = joinFieldValue(tokens, line);
|
|
5231
|
+
return;
|
|
5232
|
+
case "referenceplane":
|
|
5233
|
+
warnIfSchema25Feature(section.sourceSchemaVersion, section.diagnostics, "event.referencePlane", {
|
|
5234
|
+
line,
|
|
5235
|
+
column: tokens[0].column
|
|
5236
|
+
});
|
|
5237
|
+
section.event.referencePlane = joinFieldValue(tokens, line);
|
|
5238
|
+
return;
|
|
5239
|
+
case "tags":
|
|
5240
|
+
section.event.tags = parseTokenList(tokens.slice(1), line, "tags");
|
|
5241
|
+
return;
|
|
5242
|
+
case "color":
|
|
5243
|
+
section.event.color = joinFieldValue(tokens, line);
|
|
5244
|
+
return;
|
|
5245
|
+
case "hidden":
|
|
5246
|
+
section.event.hidden = parseAtlasBoolean(joinFieldValue(tokens, line), "hidden", {
|
|
5247
|
+
line,
|
|
5248
|
+
column: tokens[0].column
|
|
5249
|
+
});
|
|
5250
|
+
return;
|
|
5251
|
+
default:
|
|
5252
|
+
throw new WorldOrbitError(`Unknown event field "${tokens[0].value}"`, line, tokens[0].column);
|
|
5253
|
+
}
|
|
5254
|
+
}
|
|
5255
|
+
function parseEventPoseField(tokens, line, seenFields) {
|
|
5256
|
+
if (tokens.length < 2) {
|
|
5257
|
+
throw new WorldOrbitError("Invalid event pose field line", line, tokens[0]?.column ?? 1);
|
|
5258
|
+
}
|
|
5259
|
+
const key = tokens[0].value;
|
|
5260
|
+
if (!EVENT_POSE_FIELD_KEYS.has(key)) {
|
|
5261
|
+
throw new WorldOrbitError(`Unknown event pose field "${key}"`, line, tokens[0].column);
|
|
5262
|
+
}
|
|
5263
|
+
if (seenFields.has(key)) {
|
|
5264
|
+
throw new WorldOrbitError(`Duplicate event pose field "${key}"`, line, tokens[0].column);
|
|
5265
|
+
}
|
|
5266
|
+
seenFields.add(key);
|
|
5267
|
+
return {
|
|
5268
|
+
type: "field",
|
|
5269
|
+
key,
|
|
5270
|
+
values: tokens.slice(1).map((token) => token.value),
|
|
5271
|
+
location: { line, column: tokens[0].column }
|
|
5272
|
+
};
|
|
5273
|
+
}
|
|
4334
5274
|
function applyObjectField(section, indent, tokens, line) {
|
|
4335
5275
|
if (section.activeBlock && indent <= (section.blockIndent ?? 0)) {
|
|
4336
5276
|
section.activeBlock = null;
|
|
@@ -4389,7 +5329,7 @@ var WorldOrbit = (() => {
|
|
|
4389
5329
|
function parseObjectTypeTokens(tokens, line) {
|
|
4390
5330
|
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
5331
|
}
|
|
4392
|
-
function parseLayerTokens(tokens, line) {
|
|
5332
|
+
function parseLayerTokens(tokens, line, sourceSchemaVersion, diagnostics) {
|
|
4393
5333
|
const layers = {};
|
|
4394
5334
|
for (const token of parseTokenList(tokens, line, "layers")) {
|
|
4395
5335
|
const enabled = !token.startsWith("-") && !token.startsWith("!");
|
|
@@ -4399,7 +5339,13 @@ var WorldOrbit = (() => {
|
|
|
4399
5339
|
layers["orbits-front"] = enabled;
|
|
4400
5340
|
continue;
|
|
4401
5341
|
}
|
|
4402
|
-
if (raw === "background" || raw === "guides" || raw === "orbits-back" || raw === "orbits-front" || raw === "relations" || raw === "objects" || raw === "labels" || raw === "metadata") {
|
|
5342
|
+
if (raw === "background" || raw === "guides" || raw === "orbits-back" || raw === "orbits-front" || raw === "relations" || raw === "events" || raw === "objects" || raw === "labels" || raw === "metadata") {
|
|
5343
|
+
if (raw === "events" && sourceSchemaVersion && diagnostics) {
|
|
5344
|
+
warnIfSchema21Feature(sourceSchemaVersion, diagnostics, "layers.events", {
|
|
5345
|
+
line,
|
|
5346
|
+
column: tokens[0]?.column ?? 1
|
|
5347
|
+
});
|
|
5348
|
+
}
|
|
4403
5349
|
layers[raw] = enabled;
|
|
4404
5350
|
}
|
|
4405
5351
|
}
|
|
@@ -4417,11 +5363,15 @@ var WorldOrbit = (() => {
|
|
|
4417
5363
|
}
|
|
4418
5364
|
function parseProjectionValue(value, line, column) {
|
|
4419
5365
|
const normalized = value.toLowerCase();
|
|
4420
|
-
if (normalized !== "topdown" && normalized !== "isometric") {
|
|
5366
|
+
if (normalized !== "topdown" && normalized !== "isometric" && normalized !== "orthographic" && normalized !== "perspective") {
|
|
4421
5367
|
throw new WorldOrbitError(`Unknown projection "${value}"`, line, column);
|
|
4422
5368
|
}
|
|
4423
5369
|
return normalized;
|
|
4424
5370
|
}
|
|
5371
|
+
function isSchema25Projection(value) {
|
|
5372
|
+
const normalized = value.toLowerCase();
|
|
5373
|
+
return normalized === "orthographic" || normalized === "perspective";
|
|
5374
|
+
}
|
|
4425
5375
|
function parsePresetValue(value, line, column) {
|
|
4426
5376
|
const normalized = value.toLowerCase();
|
|
4427
5377
|
if (normalized === "diagram" || normalized === "presentation" || normalized === "atlas-card" || normalized === "markdown") {
|
|
@@ -4451,6 +5401,48 @@ var WorldOrbit = (() => {
|
|
|
4451
5401
|
groupIds: []
|
|
4452
5402
|
};
|
|
4453
5403
|
}
|
|
5404
|
+
function createEmptyViewCamera2() {
|
|
5405
|
+
return {
|
|
5406
|
+
azimuth: null,
|
|
5407
|
+
elevation: null,
|
|
5408
|
+
roll: null,
|
|
5409
|
+
distance: null
|
|
5410
|
+
};
|
|
5411
|
+
}
|
|
5412
|
+
function parseInlineViewCamera(tokens, line, current) {
|
|
5413
|
+
if (tokens.length === 0 || tokens.length % 2 !== 0) {
|
|
5414
|
+
throw new WorldOrbitError('Field "camera" expects "<field> <value>" pairs', line, tokens[0]?.column ?? 1);
|
|
5415
|
+
}
|
|
5416
|
+
const camera = current ? { ...current } : createEmptyViewCamera2();
|
|
5417
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5418
|
+
for (let index = 0; index < tokens.length; index += 2) {
|
|
5419
|
+
const fieldToken = tokens[index];
|
|
5420
|
+
const valueToken = tokens[index + 1];
|
|
5421
|
+
const key = fieldToken.value.toLowerCase();
|
|
5422
|
+
if (seen.has(key)) {
|
|
5423
|
+
throw new WorldOrbitError(`Duplicate viewpoint camera field "${fieldToken.value}"`, line, fieldToken.column);
|
|
5424
|
+
}
|
|
5425
|
+
seen.add(key);
|
|
5426
|
+
const value = valueToken.value;
|
|
5427
|
+
switch (key) {
|
|
5428
|
+
case "azimuth":
|
|
5429
|
+
camera.azimuth = parseFiniteNumber2(value, line, fieldToken.column, "camera.azimuth");
|
|
5430
|
+
break;
|
|
5431
|
+
case "elevation":
|
|
5432
|
+
camera.elevation = parseFiniteNumber2(value, line, fieldToken.column, "camera.elevation");
|
|
5433
|
+
break;
|
|
5434
|
+
case "roll":
|
|
5435
|
+
camera.roll = parseFiniteNumber2(value, line, fieldToken.column, "camera.roll");
|
|
5436
|
+
break;
|
|
5437
|
+
case "distance":
|
|
5438
|
+
camera.distance = parsePositiveNumber2(value, line, fieldToken.column, "camera.distance");
|
|
5439
|
+
break;
|
|
5440
|
+
default:
|
|
5441
|
+
throw new WorldOrbitError(`Unknown viewpoint camera field "${fieldToken.value}"`, line, fieldToken.column);
|
|
5442
|
+
}
|
|
5443
|
+
}
|
|
5444
|
+
return camera;
|
|
5445
|
+
}
|
|
4454
5446
|
function parseInlineObjectFields(tokens, line, objectType, sourceSchemaVersion, diagnostics) {
|
|
4455
5447
|
const fields = [];
|
|
4456
5448
|
let index = 0;
|
|
@@ -4538,7 +5530,7 @@ var WorldOrbit = (() => {
|
|
|
4538
5530
|
}
|
|
4539
5531
|
function normalizeDraftObject(node, sourceSchemaVersion, diagnostics) {
|
|
4540
5532
|
const fieldMap = collectDraftFields(node.fields);
|
|
4541
|
-
const placement =
|
|
5533
|
+
const placement = extractPlacementFromFieldMap(fieldMap);
|
|
4542
5534
|
const properties = normalizeDraftProperties(node.objectType, fieldMap);
|
|
4543
5535
|
const groups = parseOptionalTokenList(fieldMap.get("groups")?.[0]);
|
|
4544
5536
|
const epoch = parseOptionalJoinedValue(fieldMap.get("epoch")?.[0]);
|
|
@@ -4583,21 +5575,41 @@ var WorldOrbit = (() => {
|
|
|
4583
5575
|
object.tolerances = tolerances;
|
|
4584
5576
|
if (typedBlocks && Object.keys(typedBlocks).length > 0)
|
|
4585
5577
|
object.typedBlocks = typedBlocks;
|
|
4586
|
-
if (sourceSchemaVersion
|
|
5578
|
+
if (isSchemaOlderThan(sourceSchemaVersion, "2.1")) {
|
|
4587
5579
|
if (object.groups || object.epoch || object.referencePlane || object.tidalLock !== void 0 || object.resonance || object.renderHints || object.deriveRules?.length || object.validationRules?.length || object.lockedFields?.length || object.tolerances?.length || object.typedBlocks) {
|
|
4588
5580
|
warnIfSchema21Feature(sourceSchemaVersion, diagnostics, node.id, node.location);
|
|
4589
5581
|
}
|
|
4590
5582
|
}
|
|
4591
5583
|
return object;
|
|
4592
5584
|
}
|
|
4593
|
-
function
|
|
5585
|
+
function normalizeDraftEvent(event, rawPoses) {
|
|
5586
|
+
return {
|
|
5587
|
+
...event,
|
|
5588
|
+
participantObjectIds: [...new Set(event.participantObjectIds)],
|
|
5589
|
+
tags: [...new Set(event.tags)],
|
|
5590
|
+
positions: rawPoses.map((pose) => normalizeDraftEventPose(pose))
|
|
5591
|
+
};
|
|
5592
|
+
}
|
|
5593
|
+
function normalizeDraftEventPose(rawPose) {
|
|
5594
|
+
const fieldMap = collectDraftFields(rawPose.fields, "event-pose");
|
|
5595
|
+
const placement = extractPlacementFromFieldMap(fieldMap);
|
|
5596
|
+
return {
|
|
5597
|
+
objectId: rawPose.objectId,
|
|
5598
|
+
placement,
|
|
5599
|
+
inner: parseOptionalUnitField(fieldMap.get("inner")?.[0], "inner"),
|
|
5600
|
+
outer: parseOptionalUnitField(fieldMap.get("outer")?.[0], "outer"),
|
|
5601
|
+
epoch: parseOptionalJoinedValue(fieldMap.get("epoch")?.[0]),
|
|
5602
|
+
referencePlane: parseOptionalJoinedValue(fieldMap.get("referencePlane")?.[0])
|
|
5603
|
+
};
|
|
5604
|
+
}
|
|
5605
|
+
function collectDraftFields(fields, _mode = "object") {
|
|
4594
5606
|
const grouped = /* @__PURE__ */ new Map();
|
|
4595
5607
|
for (const field of fields) {
|
|
4596
5608
|
const spec = getDraftObjectFieldSpec(field.key);
|
|
4597
|
-
if (!spec) {
|
|
5609
|
+
if (!spec && !EVENT_POSE_FIELD_KEYS.has(field.key)) {
|
|
4598
5610
|
throw WorldOrbitError.fromLocation(`Unknown field "${field.key}"`, field.location);
|
|
4599
5611
|
}
|
|
4600
|
-
if (!spec
|
|
5612
|
+
if (!spec?.allowRepeat && grouped.has(field.key)) {
|
|
4601
5613
|
throw WorldOrbitError.fromLocation(`Duplicate field "${field.key}"`, field.location);
|
|
4602
5614
|
}
|
|
4603
5615
|
const existing = grouped.get(field.key) ?? [];
|
|
@@ -4606,7 +5618,7 @@ var WorldOrbit = (() => {
|
|
|
4606
5618
|
}
|
|
4607
5619
|
return grouped;
|
|
4608
5620
|
}
|
|
4609
|
-
function
|
|
5621
|
+
function extractPlacementFromFieldMap(fieldMap) {
|
|
4610
5622
|
const orbitField = fieldMap.get("orbit")?.[0];
|
|
4611
5623
|
const atField = fieldMap.get("at")?.[0];
|
|
4612
5624
|
const surfaceField = fieldMap.get("surface")?.[0];
|
|
@@ -4774,7 +5786,7 @@ var WorldOrbit = (() => {
|
|
|
4774
5786
|
}
|
|
4775
5787
|
}
|
|
4776
5788
|
function warnIfSchema21Feature(sourceSchemaVersion, diagnostics, featureName, location) {
|
|
4777
|
-
if (sourceSchemaVersion
|
|
5789
|
+
if (!isSchemaOlderThan(sourceSchemaVersion, "2.1")) {
|
|
4778
5790
|
return;
|
|
4779
5791
|
}
|
|
4780
5792
|
diagnostics.push({
|
|
@@ -4786,6 +5798,34 @@ var WorldOrbit = (() => {
|
|
|
4786
5798
|
column: location.column
|
|
4787
5799
|
});
|
|
4788
5800
|
}
|
|
5801
|
+
function warnIfSchema25Feature(sourceSchemaVersion, diagnostics, featureName, location) {
|
|
5802
|
+
if (!isSchemaOlderThan(sourceSchemaVersion, "2.5")) {
|
|
5803
|
+
return;
|
|
5804
|
+
}
|
|
5805
|
+
diagnostics.push({
|
|
5806
|
+
code: "parse.schema25.featureCompatibility",
|
|
5807
|
+
severity: "warning",
|
|
5808
|
+
source: "parse",
|
|
5809
|
+
message: `Feature "${featureName}" requires schema 2.5; parsed in compatibility mode because the document header is "schema ${sourceSchemaVersion}".`,
|
|
5810
|
+
line: location.line,
|
|
5811
|
+
column: location.column
|
|
5812
|
+
});
|
|
5813
|
+
}
|
|
5814
|
+
function isSchemaOlderThan(sourceSchemaVersion, requiredVersion) {
|
|
5815
|
+
return schemaVersionRank(sourceSchemaVersion) < schemaVersionRank(requiredVersion);
|
|
5816
|
+
}
|
|
5817
|
+
function schemaVersionRank(version) {
|
|
5818
|
+
switch (version) {
|
|
5819
|
+
case "2.0-draft":
|
|
5820
|
+
return 0;
|
|
5821
|
+
case "2.0":
|
|
5822
|
+
return 1;
|
|
5823
|
+
case "2.1":
|
|
5824
|
+
return 2;
|
|
5825
|
+
case "2.5":
|
|
5826
|
+
return 3;
|
|
5827
|
+
}
|
|
5828
|
+
}
|
|
4789
5829
|
function preprocessAtlasSource(source) {
|
|
4790
5830
|
const chars = [...source];
|
|
4791
5831
|
const comments = [];
|
|
@@ -4873,7 +5913,7 @@ var WorldOrbit = (() => {
|
|
|
4873
5913
|
}
|
|
4874
5914
|
|
|
4875
5915
|
// packages/core/dist/atlas-edit.js
|
|
4876
|
-
function createEmptyAtlasDocument(systemId = "WorldOrbit", version = "2.
|
|
5916
|
+
function createEmptyAtlasDocument(systemId = "WorldOrbit", version = "2.5") {
|
|
4877
5917
|
return {
|
|
4878
5918
|
format: "worldorbit",
|
|
4879
5919
|
version,
|
|
@@ -4899,6 +5939,7 @@ var WorldOrbit = (() => {
|
|
|
4899
5939
|
},
|
|
4900
5940
|
groups: [],
|
|
4901
5941
|
relations: [],
|
|
5942
|
+
events: [],
|
|
4902
5943
|
objects: [],
|
|
4903
5944
|
diagnostics: []
|
|
4904
5945
|
};
|
|
@@ -4916,6 +5957,10 @@ var WorldOrbit = (() => {
|
|
|
4916
5957
|
return path.key ? document2.system?.atlasMetadata[path.key] ?? null : null;
|
|
4917
5958
|
case "group":
|
|
4918
5959
|
return path.id ? findGroup(document2, path.id) : null;
|
|
5960
|
+
case "event":
|
|
5961
|
+
return path.id ? findEvent(document2, path.id) : null;
|
|
5962
|
+
case "event-pose":
|
|
5963
|
+
return path.id && path.key ? findEventPose(document2, path.id, path.key) : null;
|
|
4919
5964
|
case "object":
|
|
4920
5965
|
return path.id ? findObject(document2, path.id) : null;
|
|
4921
5966
|
case "viewpoint":
|
|
@@ -4945,6 +5990,19 @@ var WorldOrbit = (() => {
|
|
|
4945
5990
|
next.groups = next.groups.filter((group) => group.id !== path.id);
|
|
4946
5991
|
}
|
|
4947
5992
|
return next;
|
|
5993
|
+
case "event":
|
|
5994
|
+
if (path.id) {
|
|
5995
|
+
next.events = next.events.filter((event) => event.id !== path.id);
|
|
5996
|
+
}
|
|
5997
|
+
return next;
|
|
5998
|
+
case "event-pose":
|
|
5999
|
+
if (path.id && path.key) {
|
|
6000
|
+
const event = findEvent(next, path.id);
|
|
6001
|
+
if (event) {
|
|
6002
|
+
event.positions = event.positions.filter((pose) => pose.objectId !== path.key);
|
|
6003
|
+
}
|
|
6004
|
+
}
|
|
6005
|
+
return next;
|
|
4948
6006
|
case "viewpoint":
|
|
4949
6007
|
if (path.id) {
|
|
4950
6008
|
system.viewpoints = system.viewpoints.filter((viewpoint) => viewpoint.id !== path.id);
|
|
@@ -5013,6 +6071,22 @@ var WorldOrbit = (() => {
|
|
|
5013
6071
|
};
|
|
5014
6072
|
}
|
|
5015
6073
|
}
|
|
6074
|
+
if (diagnostic.field?.startsWith("event.")) {
|
|
6075
|
+
const parts = diagnostic.field.split(".");
|
|
6076
|
+
if (parts[1] && findEvent(document2, parts[1])) {
|
|
6077
|
+
if (parts[2] === "pose" && parts[3] && findEventPose(document2, parts[1], parts[3])) {
|
|
6078
|
+
return {
|
|
6079
|
+
kind: "event-pose",
|
|
6080
|
+
id: parts[1],
|
|
6081
|
+
key: parts[3]
|
|
6082
|
+
};
|
|
6083
|
+
}
|
|
6084
|
+
return {
|
|
6085
|
+
kind: "event",
|
|
6086
|
+
id: parts[1]
|
|
6087
|
+
};
|
|
6088
|
+
}
|
|
6089
|
+
}
|
|
5016
6090
|
if (diagnostic.field && diagnostic.field in ensureSystem(document2).atlasMetadata) {
|
|
5017
6091
|
return {
|
|
5018
6092
|
kind: "metadata",
|
|
@@ -5044,6 +6118,12 @@ var WorldOrbit = (() => {
|
|
|
5044
6118
|
function findRelation(document2, relationId) {
|
|
5045
6119
|
return document2.relations.find((relation) => relation.id === relationId) ?? null;
|
|
5046
6120
|
}
|
|
6121
|
+
function findEvent(document2, eventId) {
|
|
6122
|
+
return document2.events.find((event) => event.id === eventId) ?? null;
|
|
6123
|
+
}
|
|
6124
|
+
function findEventPose(document2, eventId, objectId) {
|
|
6125
|
+
return findEvent(document2, eventId)?.positions.find((pose) => pose.objectId === objectId) ?? null;
|
|
6126
|
+
}
|
|
5047
6127
|
function findViewpoint(system, viewpointId) {
|
|
5048
6128
|
return system?.viewpoints.find((viewpoint) => viewpoint.id === viewpointId) ?? null;
|
|
5049
6129
|
}
|
|
@@ -5052,8 +6132,9 @@ var WorldOrbit = (() => {
|
|
|
5052
6132
|
}
|
|
5053
6133
|
|
|
5054
6134
|
// packages/core/dist/load.js
|
|
5055
|
-
var ATLAS_SCHEMA_PATTERN = /^schema\s+2(?:\.0|\.1)?$/i;
|
|
6135
|
+
var ATLAS_SCHEMA_PATTERN = /^schema\s+2(?:\.0|\.1|\.5)?$/i;
|
|
5056
6136
|
var ATLAS_SCHEMA_21_PATTERN = /^schema\s+2\.1$/i;
|
|
6137
|
+
var ATLAS_SCHEMA_25_PATTERN = /^schema\s+2\.5$/i;
|
|
5057
6138
|
var LEGACY_DRAFT_SCHEMA_PATTERN = /^schema\s+2\.0-draft$/i;
|
|
5058
6139
|
function detectWorldOrbitSchemaVersion(source) {
|
|
5059
6140
|
for (const line of stripCommentsForSchemaDetection(source).split(/\r?\n/)) {
|
|
@@ -5067,6 +6148,9 @@ var WorldOrbit = (() => {
|
|
|
5067
6148
|
if (ATLAS_SCHEMA_21_PATTERN.test(trimmed)) {
|
|
5068
6149
|
return "2.1";
|
|
5069
6150
|
}
|
|
6151
|
+
if (ATLAS_SCHEMA_25_PATTERN.test(trimmed)) {
|
|
6152
|
+
return "2.5";
|
|
6153
|
+
}
|
|
5070
6154
|
if (ATLAS_SCHEMA_PATTERN.test(trimmed)) {
|
|
5071
6155
|
return "2.0";
|
|
5072
6156
|
}
|
|
@@ -5127,7 +6211,7 @@ var WorldOrbit = (() => {
|
|
|
5127
6211
|
}
|
|
5128
6212
|
function loadWorldOrbitSourceWithDiagnostics(source) {
|
|
5129
6213
|
const schemaVersion = detectWorldOrbitSchemaVersion(source);
|
|
5130
|
-
if (schemaVersion === "2.0" || schemaVersion === "2.0-draft" || schemaVersion === "2.1") {
|
|
6214
|
+
if (schemaVersion === "2.0" || schemaVersion === "2.0-draft" || schemaVersion === "2.1" || schemaVersion === "2.5") {
|
|
5131
6215
|
return loadAtlasSourceWithDiagnostics(source, schemaVersion);
|
|
5132
6216
|
}
|
|
5133
6217
|
let ast;
|
|
@@ -5221,6 +6305,7 @@ var WorldOrbit = (() => {
|
|
|
5221
6305
|
background: true,
|
|
5222
6306
|
guides: true,
|
|
5223
6307
|
relations: true,
|
|
6308
|
+
events: true,
|
|
5224
6309
|
orbits: true,
|
|
5225
6310
|
objects: true,
|
|
5226
6311
|
labels: true,
|
|
@@ -5367,14 +6452,17 @@ var WorldOrbit = (() => {
|
|
|
5367
6452
|
}
|
|
5368
6453
|
function createAtlasStateSnapshot(viewerState, renderOptions, filter, viewpointId) {
|
|
5369
6454
|
return {
|
|
5370
|
-
version: "2.
|
|
6455
|
+
version: "2.5",
|
|
5371
6456
|
viewpointId,
|
|
6457
|
+
activeEventId: renderOptions.activeEventId ?? null,
|
|
5372
6458
|
viewerState: { ...viewerState },
|
|
5373
6459
|
renderOptions: {
|
|
5374
6460
|
preset: renderOptions.preset,
|
|
5375
6461
|
projection: renderOptions.projection,
|
|
6462
|
+
camera: renderOptions.camera ? { ...renderOptions.camera } : null,
|
|
5376
6463
|
layers: renderOptions.layers ? { ...renderOptions.layers } : void 0,
|
|
5377
|
-
scaleModel: renderOptions.scaleModel ? { ...renderOptions.scaleModel } : void 0
|
|
6464
|
+
scaleModel: renderOptions.scaleModel ? { ...renderOptions.scaleModel } : void 0,
|
|
6465
|
+
activeEventId: renderOptions.activeEventId ?? null
|
|
5378
6466
|
},
|
|
5379
6467
|
filter: normalizeViewerFilter(filter)
|
|
5380
6468
|
};
|
|
@@ -5385,8 +6473,9 @@ var WorldOrbit = (() => {
|
|
|
5385
6473
|
function deserializeViewerAtlasState(serialized) {
|
|
5386
6474
|
const raw = JSON.parse(decodeURIComponent(serialized));
|
|
5387
6475
|
return {
|
|
5388
|
-
version: "2.0",
|
|
6476
|
+
version: raw.version === "2.0" ? "2.0" : "2.5",
|
|
5389
6477
|
viewpointId: raw.viewpointId ?? null,
|
|
6478
|
+
activeEventId: raw.activeEventId ?? raw.renderOptions?.activeEventId ?? null,
|
|
5390
6479
|
viewerState: {
|
|
5391
6480
|
scale: raw.viewerState?.scale ?? 1,
|
|
5392
6481
|
rotationDeg: raw.viewerState?.rotationDeg ?? 0,
|
|
@@ -5397,8 +6486,10 @@ var WorldOrbit = (() => {
|
|
|
5397
6486
|
renderOptions: {
|
|
5398
6487
|
preset: raw.renderOptions?.preset,
|
|
5399
6488
|
projection: raw.renderOptions?.projection,
|
|
6489
|
+
camera: raw.renderOptions?.camera ? { ...raw.renderOptions.camera } : null,
|
|
5400
6490
|
layers: raw.renderOptions?.layers ? { ...raw.renderOptions.layers } : void 0,
|
|
5401
|
-
scaleModel: raw.renderOptions?.scaleModel ? { ...raw.renderOptions.scaleModel } : void 0
|
|
6491
|
+
scaleModel: raw.renderOptions?.scaleModel ? { ...raw.renderOptions.scaleModel } : void 0,
|
|
6492
|
+
activeEventId: raw.activeEventId ?? raw.renderOptions?.activeEventId ?? null
|
|
5402
6493
|
},
|
|
5403
6494
|
filter: normalizeViewerFilter(raw.filter ?? null)
|
|
5404
6495
|
};
|
|
@@ -5413,8 +6504,10 @@ var WorldOrbit = (() => {
|
|
|
5413
6504
|
viewerState: { ...atlasState.viewerState },
|
|
5414
6505
|
renderOptions: {
|
|
5415
6506
|
...atlasState.renderOptions,
|
|
6507
|
+
camera: atlasState.renderOptions.camera ? { ...atlasState.renderOptions.camera } : null,
|
|
5416
6508
|
layers: atlasState.renderOptions.layers ? { ...atlasState.renderOptions.layers } : void 0,
|
|
5417
|
-
scaleModel: atlasState.renderOptions.scaleModel ? { ...atlasState.renderOptions.scaleModel } : void 0
|
|
6509
|
+
scaleModel: atlasState.renderOptions.scaleModel ? { ...atlasState.renderOptions.scaleModel } : void 0,
|
|
6510
|
+
activeEventId: atlasState.renderOptions.activeEventId ?? null
|
|
5418
6511
|
},
|
|
5419
6512
|
filter: atlasState.filter ? { ...atlasState.filter } : null
|
|
5420
6513
|
}
|
|
@@ -5432,6 +6525,7 @@ var WorldOrbit = (() => {
|
|
|
5432
6525
|
background: viewpoint.layers.background,
|
|
5433
6526
|
guides: viewpoint.layers.guides,
|
|
5434
6527
|
relations: viewpoint.layers.relations,
|
|
6528
|
+
events: viewpoint.layers.events,
|
|
5435
6529
|
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
6530
|
objects: viewpoint.layers.objects,
|
|
5437
6531
|
labels: viewpoint.layers.labels,
|
|
@@ -5718,6 +6812,7 @@ var WorldOrbit = (() => {
|
|
|
5718
6812
|
const orbitMarkup = layers.orbits ? renderOrbitLayer(scene, visibleObjectIds, layers.structures) : { back: "", front: "" };
|
|
5719
6813
|
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
6814
|
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("") : "";
|
|
6815
|
+
const eventMarkup = layers.events ? scene.events.filter((event) => !event.hidden).map((event) => renderSceneEventOverlay(scene, event, visibleObjectIds, theme)).join("") : "";
|
|
5721
6816
|
const objectMarkup = layers.objects ? visibleObjects.map((object) => renderSceneObject(object, options.selectedObjectId ?? null, theme)).join("") : "";
|
|
5722
6817
|
const labelMarkup = layers.labels ? visibleLabels.map((label) => renderSceneLabel(scene, label, options.selectedObjectId ?? null)).join("") : "";
|
|
5723
6818
|
const metadataMarkup = layers.metadata ? `<text class="wo-title" x="56" y="64">${escapeXml(scene.title)}</text>
|
|
@@ -5753,6 +6848,9 @@ var WorldOrbit = (() => {
|
|
|
5753
6848
|
.wo-orbit-front { opacity: 0.9; }
|
|
5754
6849
|
.wo-orbit-band { stroke: ${theme.orbitBand}; stroke-linecap: round; }
|
|
5755
6850
|
.wo-relation { stroke: ${theme.relation}; stroke-width: 2; stroke-dasharray: 10 6; }
|
|
6851
|
+
.wo-event-line { stroke: ${theme.accent}; stroke-width: 1.6; stroke-dasharray: 5 5; opacity: 0.72; }
|
|
6852
|
+
.wo-event-node { fill: ${theme.accent}; stroke: ${theme.selected}; stroke-width: 1.4; opacity: 0.92; }
|
|
6853
|
+
.wo-event-label { fill: ${theme.accent}; font-family: ${theme.fontFamily}; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; }
|
|
5756
6854
|
.wo-leader { stroke: ${theme.leader}; stroke-width: 1.5; stroke-dasharray: 6 5; }
|
|
5757
6855
|
.wo-label { fill: ${theme.ink}; font-family: ${theme.fontFamily}; font-weight: 600; letter-spacing: 0.02em; }
|
|
5758
6856
|
.wo-label-secondary { fill: ${theme.muted}; font-family: ${theme.fontFamily}; font-weight: 500; }
|
|
@@ -5787,6 +6885,7 @@ var WorldOrbit = (() => {
|
|
|
5787
6885
|
${layers.orbits ? `<g data-layer-id="orbits-back">${orbitMarkup.back}</g>` : ""}
|
|
5788
6886
|
${layers.guides ? `<g data-layer-id="guides">${leaderMarkup}</g>` : ""}
|
|
5789
6887
|
${layers.relations ? `<g data-layer-id="relations">${relationMarkup}</g>` : ""}
|
|
6888
|
+
${layers.events ? `<g data-layer-id="events">${eventMarkup}</g>` : ""}
|
|
5790
6889
|
${layers.objects ? `<g data-layer-id="objects">${objectMarkup}</g>` : ""}
|
|
5791
6890
|
${layers.orbits ? `<g data-layer-id="orbits-front">${orbitMarkup.front}</g>` : ""}
|
|
5792
6891
|
${layers.labels ? `<g data-layer-id="labels">${labelMarkup}</g>` : ""}
|
|
@@ -5794,6 +6893,20 @@ var WorldOrbit = (() => {
|
|
|
5794
6893
|
</g>
|
|
5795
6894
|
</g>
|
|
5796
6895
|
</svg>`;
|
|
6896
|
+
}
|
|
6897
|
+
function renderSceneEventOverlay(scene, event, visibleObjectIds, theme) {
|
|
6898
|
+
const participants = event.objectIds.filter((objectId) => visibleObjectIds.has(objectId)).map((objectId) => scene.objects.find((object) => object.objectId === objectId && !object.hidden)).filter(Boolean);
|
|
6899
|
+
if (participants.length === 0) {
|
|
6900
|
+
return "";
|
|
6901
|
+
}
|
|
6902
|
+
const stroke = event.event.color || theme.accent;
|
|
6903
|
+
const label = event.event.label || event.event.id;
|
|
6904
|
+
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("");
|
|
6905
|
+
return `<g class="wo-event" data-render-id="${escapeXml(event.renderId)}" data-event-id="${escapeAttribute(event.eventId)}">
|
|
6906
|
+
${lineMarkup}
|
|
6907
|
+
<circle class="wo-event-node" cx="${event.x}" cy="${event.y}" r="5" fill="${escapeAttribute(stroke)}" />
|
|
6908
|
+
<text class="wo-event-label" x="${event.x}" y="${event.y - 10}" text-anchor="middle" font-size="10">${escapeXml(label)}</text>
|
|
6909
|
+
</g>`;
|
|
5797
6910
|
}
|
|
5798
6911
|
function renderOrbitLayer(scene, visibleObjectIds, includeStructures) {
|
|
5799
6912
|
const backParts = [];
|
|
@@ -6376,6 +7489,13 @@ var WorldOrbit = (() => {
|
|
|
6376
7489
|
value: `${details.object.resonance.targetObjectId} ${details.object.resonance.ratio}`
|
|
6377
7490
|
});
|
|
6378
7491
|
}
|
|
7492
|
+
if (details.relatedEvents.length > 0) {
|
|
7493
|
+
fields.set("events", {
|
|
7494
|
+
key: "events",
|
|
7495
|
+
label: "Events",
|
|
7496
|
+
value: details.relatedEvents.map((event) => event.event.label || event.event.id).join(", ")
|
|
7497
|
+
});
|
|
7498
|
+
}
|
|
6379
7499
|
if (placement?.mode === "at") {
|
|
6380
7500
|
fields.set("placement", {
|
|
6381
7501
|
key: "placement",
|
|
@@ -6480,6 +7600,7 @@ var WorldOrbit = (() => {
|
|
|
6480
7600
|
padding: options.padding,
|
|
6481
7601
|
preset: options.preset,
|
|
6482
7602
|
projection: options.projection,
|
|
7603
|
+
camera: options.camera ? { ...options.camera } : null,
|
|
6483
7604
|
scaleModel: options.scaleModel ? { ...options.scaleModel } : void 0,
|
|
6484
7605
|
theme: options.theme,
|
|
6485
7606
|
layers: options.layers,
|
|
@@ -6768,6 +7889,11 @@ var WorldOrbit = (() => {
|
|
|
6768
7889
|
if (currentInput.kind !== "scene" && viewpoint.projection !== scene.projection) {
|
|
6769
7890
|
nextRenderOptions.projection = viewpoint.projection;
|
|
6770
7891
|
}
|
|
7892
|
+
if (viewpoint.camera) {
|
|
7893
|
+
nextRenderOptions.camera = { ...viewpoint.camera };
|
|
7894
|
+
} else if (renderOptions.camera) {
|
|
7895
|
+
nextRenderOptions.camera = null;
|
|
7896
|
+
}
|
|
6771
7897
|
if (viewpointLayers) {
|
|
6772
7898
|
nextRenderOptions.layers = viewpointLayers;
|
|
6773
7899
|
}
|
|
@@ -6790,6 +7916,12 @@ var WorldOrbit = (() => {
|
|
|
6790
7916
|
emitAtlasStateChange();
|
|
6791
7917
|
return true;
|
|
6792
7918
|
},
|
|
7919
|
+
getActiveEventId() {
|
|
7920
|
+
return renderOptions.activeEventId ?? null;
|
|
7921
|
+
},
|
|
7922
|
+
setActiveEvent(id) {
|
|
7923
|
+
api.setRenderOptions({ activeEventId: id });
|
|
7924
|
+
},
|
|
6793
7925
|
search(query, limit = 12) {
|
|
6794
7926
|
return searchSceneObjects(scene, query, limit);
|
|
6795
7927
|
},
|
|
@@ -7054,6 +8186,7 @@ var WorldOrbit = (() => {
|
|
|
7054
8186
|
orbit: scene.orbitVisuals.find((orbit) => orbit.objectId === renderObject.objectId && !orbit.hidden) ?? null,
|
|
7055
8187
|
relatedOrbits: scene.orbitVisuals.filter((orbit) => !orbit.hidden && (orbit.objectId === renderObject.objectId || renderObject.ancestorIds.includes(orbit.objectId) || renderObject.childIds.includes(orbit.objectId))),
|
|
7056
8188
|
relations: scene.relations.filter((relation) => !relation.hidden && (relation.fromObjectId === renderObject.objectId || relation.toObjectId === renderObject.objectId)),
|
|
8189
|
+
relatedEvents: scene.events.filter((event) => !event.hidden && (event.targetObjectId === renderObject.objectId || event.objectIds.includes(renderObject.objectId))),
|
|
7057
8190
|
parent: getObjectById(renderObject.parentId),
|
|
7058
8191
|
children: renderObject.childIds.map((childId) => getObjectById(childId)).filter(Boolean),
|
|
7059
8192
|
ancestors: renderObject.ancestorIds.map((ancestorId) => getObjectById(ancestorId)).filter(Boolean),
|
|
@@ -7367,16 +8500,19 @@ var WorldOrbit = (() => {
|
|
|
7367
8500
|
function cloneRenderOptions(renderOptions) {
|
|
7368
8501
|
return {
|
|
7369
8502
|
...renderOptions,
|
|
8503
|
+
camera: renderOptions.camera ? { ...renderOptions.camera } : null,
|
|
7370
8504
|
filter: renderOptions.filter ? { ...renderOptions.filter } : void 0,
|
|
7371
8505
|
scaleModel: renderOptions.scaleModel ? { ...renderOptions.scaleModel } : void 0,
|
|
7372
8506
|
layers: renderOptions.layers ? { ...renderOptions.layers } : void 0,
|
|
7373
|
-
theme: renderOptions.theme && typeof renderOptions.theme === "object" ? { ...renderOptions.theme } : renderOptions.theme
|
|
8507
|
+
theme: renderOptions.theme && typeof renderOptions.theme === "object" ? { ...renderOptions.theme } : renderOptions.theme,
|
|
8508
|
+
activeEventId: renderOptions.activeEventId ?? null
|
|
7374
8509
|
};
|
|
7375
8510
|
}
|
|
7376
8511
|
function mergeRenderOptions(current, next) {
|
|
7377
8512
|
return {
|
|
7378
8513
|
...current,
|
|
7379
8514
|
...next,
|
|
8515
|
+
camera: next.camera !== void 0 ? next.camera ? { ...next.camera } : null : current.camera ? { ...current.camera } : null,
|
|
7380
8516
|
filter: next.filter !== void 0 ? normalizeViewerFilter(next.filter) : current.filter ? { ...current.filter } : void 0,
|
|
7381
8517
|
scaleModel: next.scaleModel ? {
|
|
7382
8518
|
...current.scaleModel ?? {},
|
|
@@ -7390,7 +8526,7 @@ var WorldOrbit = (() => {
|
|
|
7390
8526
|
};
|
|
7391
8527
|
}
|
|
7392
8528
|
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;
|
|
8529
|
+
return options.width !== void 0 || options.height !== void 0 || options.padding !== void 0 || options.preset !== void 0 || options.projection !== void 0 || options.camera !== void 0 || options.scaleModel !== void 0 || options.activeEventId !== void 0;
|
|
7394
8530
|
}
|
|
7395
8531
|
function resolveSourceRenderOptions(loaded, renderOptions) {
|
|
7396
8532
|
const atlasDocument = loaded.atlasDocument ?? loaded.draftDocument;
|
|
@@ -7701,7 +8837,11 @@ var WorldOrbit = (() => {
|
|
|
7701
8837
|
var FIELD_HELP = {
|
|
7702
8838
|
"defaults-view": {
|
|
7703
8839
|
description: "Sets the default camera projection for the atlas.",
|
|
7704
|
-
references: [
|
|
8840
|
+
references: [
|
|
8841
|
+
"Topdown = map-like",
|
|
8842
|
+
"Isometric = angled overview",
|
|
8843
|
+
"Orthographic/Perspective = 3D-ready semantic views"
|
|
8844
|
+
]
|
|
7705
8845
|
},
|
|
7706
8846
|
"defaults-scale": {
|
|
7707
8847
|
description: "Chooses the overall spacing/style preset used by the renderer.",
|
|
@@ -7713,15 +8853,71 @@ var WorldOrbit = (() => {
|
|
|
7713
8853
|
},
|
|
7714
8854
|
"viewpoint-projection": {
|
|
7715
8855
|
description: "Overrides the projection for this saved viewpoint.",
|
|
7716
|
-
references: [
|
|
8856
|
+
references: [
|
|
8857
|
+
"Topdown = flat orbital map",
|
|
8858
|
+
"Isometric = angled scene",
|
|
8859
|
+
"Orthographic/Perspective = stored with current 2D fallback"
|
|
8860
|
+
]
|
|
7717
8861
|
},
|
|
7718
8862
|
"viewpoint-zoom": {
|
|
7719
8863
|
description: "Controls how closely this viewpoint frames the system.",
|
|
7720
8864
|
references: ["1 = scene fit", "2+ = close-up"]
|
|
7721
8865
|
},
|
|
7722
8866
|
"viewpoint-rotation": {
|
|
7723
|
-
description: "
|
|
7724
|
-
references: ["90deg = quarter turn", "
|
|
8867
|
+
description: "Legacy 2D screen rotation. This is separate from the Schema 2.5 camera block.",
|
|
8868
|
+
references: ["90deg = quarter turn", "Use camera.azimuth for semantic view direction"]
|
|
8869
|
+
},
|
|
8870
|
+
"viewpoint-camera-azimuth": {
|
|
8871
|
+
description: "Horizontal camera direction in degrees for Schema 2.5 viewpoints.",
|
|
8872
|
+
references: ["0 = forward/default", "90 = quarter orbit around the scene"]
|
|
8873
|
+
},
|
|
8874
|
+
"viewpoint-camera-elevation": {
|
|
8875
|
+
description: "Vertical camera tilt in degrees for 3D-ready viewpoints.",
|
|
8876
|
+
references: ["0 = level", "30 = gentle look down"]
|
|
8877
|
+
},
|
|
8878
|
+
"viewpoint-camera-roll": {
|
|
8879
|
+
description: "Rolls the camera around its forward axis.",
|
|
8880
|
+
references: ["0 = upright", "15 = slight bank"]
|
|
8881
|
+
},
|
|
8882
|
+
"viewpoint-camera-distance": {
|
|
8883
|
+
description: "Semantic camera distance for perspective viewpoints.",
|
|
8884
|
+
references: ["4 = close", "12 = wide framing"]
|
|
8885
|
+
},
|
|
8886
|
+
"viewpoint-events": {
|
|
8887
|
+
description: "Lists event IDs that this viewpoint should feature in its detail panel.",
|
|
8888
|
+
references: ["solar-eclipse-naar", "transit-window conjunction"]
|
|
8889
|
+
},
|
|
8890
|
+
"event-kind": {
|
|
8891
|
+
description: "Short semantic event type for tooling and viewer overlays.",
|
|
8892
|
+
references: ["solar-eclipse", "lunar-eclipse", "transit"]
|
|
8893
|
+
},
|
|
8894
|
+
"event-target": {
|
|
8895
|
+
description: "Primary object this event is centered on.",
|
|
8896
|
+
references: ["Naar", "Seyra"]
|
|
8897
|
+
},
|
|
8898
|
+
"event-participants": {
|
|
8899
|
+
description: "Objects that participate in the event snapshot or description.",
|
|
8900
|
+
references: ["Iyath Naar Seyra", "Naar Seyra Orun"]
|
|
8901
|
+
},
|
|
8902
|
+
"event-timing": {
|
|
8903
|
+
description: "Free-text timing note for the event.",
|
|
8904
|
+
references: ['"Every late bloom season"', '"At local midyear"']
|
|
8905
|
+
},
|
|
8906
|
+
"event-visibility": {
|
|
8907
|
+
description: "Notes where or how the event is visible.",
|
|
8908
|
+
references: ['"Visible from Naar"', '"Southern hemisphere only"']
|
|
8909
|
+
},
|
|
8910
|
+
"event-epoch": {
|
|
8911
|
+
description: "Optional event-wide epoch that event poses inherit unless they override it.",
|
|
8912
|
+
references: ['"JY-0001.0"', '"Naar bloom cycle year 18"']
|
|
8913
|
+
},
|
|
8914
|
+
"event-referencePlane": {
|
|
8915
|
+
description: "Optional event-wide reference plane for all poses in this snapshot.",
|
|
8916
|
+
references: ["ecliptic", "naar-equatorial"]
|
|
8917
|
+
},
|
|
8918
|
+
"event-viewpoints": {
|
|
8919
|
+
description: "Viewpoint IDs that should list this event prominently.",
|
|
8920
|
+
references: ["naar-system", "overview inner-system"]
|
|
7725
8921
|
},
|
|
7726
8922
|
"placement-target": {
|
|
7727
8923
|
description: "Names the body or reference this object is attached to.",
|
|
@@ -7759,6 +8955,14 @@ var WorldOrbit = (() => {
|
|
|
7759
8955
|
description: "Starting position of the object along its orbit.",
|
|
7760
8956
|
references: ["0deg = start position", "180deg = opposite side"]
|
|
7761
8957
|
},
|
|
8958
|
+
"pose-epoch": {
|
|
8959
|
+
description: "Overrides the effective epoch for this pose only.",
|
|
8960
|
+
references: ['"JY-0001.0"', "Falls back to event, object, then system"]
|
|
8961
|
+
},
|
|
8962
|
+
"pose-referencePlane": {
|
|
8963
|
+
description: "Overrides the effective reference plane for this pose only.",
|
|
8964
|
+
references: ["naar-equatorial", "Falls back to event, object, then system"]
|
|
8965
|
+
},
|
|
7762
8966
|
"prop-radius": {
|
|
7763
8967
|
description: "Visual body size or real-world-inspired radius value.",
|
|
7764
8968
|
references: ["1re = Earth radius", "1sol = Sun radius"]
|
|
@@ -7841,12 +9045,23 @@ var WorldOrbit = (() => {
|
|
|
7841
9045
|
minimap: true,
|
|
7842
9046
|
tooltipMode: "hover",
|
|
7843
9047
|
onSelectionChange(selectedObject) {
|
|
9048
|
+
const activeEventId = selection ? selectionEventId(selection) : null;
|
|
7844
9049
|
if (ignoreViewerSelection || !selectedObject) {
|
|
7845
|
-
if (!ignoreViewerSelection
|
|
7846
|
-
|
|
9050
|
+
if (!ignoreViewerSelection) {
|
|
9051
|
+
if (selection?.kind === "event-pose" && selection.id) {
|
|
9052
|
+
setSelection({ kind: "event", id: selection.id }, false, true);
|
|
9053
|
+
} else if (selection?.kind === "object") {
|
|
9054
|
+
setSelection(activeEventId ? { kind: "event", id: activeEventId } : null, false, true);
|
|
9055
|
+
} else if (selection?.kind === "event" && selection.id) {
|
|
9056
|
+
setSelection({ kind: "event", id: selection.id }, false, true);
|
|
9057
|
+
}
|
|
7847
9058
|
}
|
|
7848
9059
|
return;
|
|
7849
9060
|
}
|
|
9061
|
+
if (activeEventId && findEventPose2(atlasDocument, activeEventId, selectedObject.objectId)) {
|
|
9062
|
+
setSelection({ kind: "event-pose", id: activeEventId, key: selectedObject.objectId }, false, true);
|
|
9063
|
+
return;
|
|
9064
|
+
}
|
|
7850
9065
|
setSelection({ kind: "object", id: selectedObject.objectId }, false, true);
|
|
7851
9066
|
},
|
|
7852
9067
|
onViewChange() {
|
|
@@ -7856,6 +9071,7 @@ var WorldOrbit = (() => {
|
|
|
7856
9071
|
toolbar.addEventListener("click", handleToolbarClick);
|
|
7857
9072
|
outline.addEventListener("click", handleOutlineClick);
|
|
7858
9073
|
overlay.addEventListener("pointerdown", handleOverlayPointerDown);
|
|
9074
|
+
inspector?.addEventListener("click", handleInspectorClick);
|
|
7859
9075
|
inspector?.addEventListener("input", handleInspectorInput);
|
|
7860
9076
|
inspector?.addEventListener("change", handleInspectorChange);
|
|
7861
9077
|
sourcePane?.addEventListener("input", handleSourceInput);
|
|
@@ -7930,6 +9146,30 @@ var WorldOrbit = (() => {
|
|
|
7930
9146
|
replaceAtlasDocument(nextDocument, true, { kind: "object", id });
|
|
7931
9147
|
return id;
|
|
7932
9148
|
},
|
|
9149
|
+
addEvent() {
|
|
9150
|
+
const id = createUniqueId("event", atlasDocument.events.map((event) => event.id));
|
|
9151
|
+
const created = {
|
|
9152
|
+
id,
|
|
9153
|
+
kind: "",
|
|
9154
|
+
label: humanizeIdentifier4(id),
|
|
9155
|
+
summary: null,
|
|
9156
|
+
targetObjectId: null,
|
|
9157
|
+
participantObjectIds: [],
|
|
9158
|
+
timing: null,
|
|
9159
|
+
visibility: null,
|
|
9160
|
+
epoch: null,
|
|
9161
|
+
referencePlane: null,
|
|
9162
|
+
tags: [],
|
|
9163
|
+
color: null,
|
|
9164
|
+
hidden: false,
|
|
9165
|
+
positions: []
|
|
9166
|
+
};
|
|
9167
|
+
const nextDocument = cloneAtlasDocument(atlasDocument);
|
|
9168
|
+
nextDocument.events.push(created);
|
|
9169
|
+
nextDocument.events.sort(compareEvents);
|
|
9170
|
+
replaceAtlasDocument(nextDocument, true, { kind: "event", id });
|
|
9171
|
+
return id;
|
|
9172
|
+
},
|
|
7933
9173
|
addViewpoint() {
|
|
7934
9174
|
const id = createUniqueId("viewpoint", atlasDocument.system?.viewpoints.map((viewpoint) => viewpoint.id) ?? []);
|
|
7935
9175
|
const created = {
|
|
@@ -7938,10 +9178,12 @@ var WorldOrbit = (() => {
|
|
|
7938
9178
|
summary: "",
|
|
7939
9179
|
focusObjectId: null,
|
|
7940
9180
|
selectedObjectId: null,
|
|
9181
|
+
events: [],
|
|
7941
9182
|
projection: atlasDocument.system?.defaults.view ?? "topdown",
|
|
7942
9183
|
preset: atlasDocument.system?.defaults.preset ?? null,
|
|
7943
9184
|
zoom: null,
|
|
7944
9185
|
rotationDeg: 0,
|
|
9186
|
+
camera: null,
|
|
7945
9187
|
layers: {},
|
|
7946
9188
|
filter: null
|
|
7947
9189
|
};
|
|
@@ -7998,6 +9240,7 @@ var WorldOrbit = (() => {
|
|
|
7998
9240
|
toolbar.removeEventListener("click", handleToolbarClick);
|
|
7999
9241
|
outline.removeEventListener("click", handleOutlineClick);
|
|
8000
9242
|
overlay.removeEventListener("pointerdown", handleOverlayPointerDown);
|
|
9243
|
+
inspector?.removeEventListener("click", handleInspectorClick);
|
|
8001
9244
|
inspector?.removeEventListener("input", handleInspectorInput);
|
|
8002
9245
|
inspector?.removeEventListener("change", handleInspectorChange);
|
|
8003
9246
|
sourcePane?.removeEventListener("input", handleSourceInput);
|
|
@@ -8043,7 +9286,7 @@ var WorldOrbit = (() => {
|
|
|
8043
9286
|
}
|
|
8044
9287
|
function getCurrentSourceForExport() {
|
|
8045
9288
|
if (dragState?.changed) {
|
|
8046
|
-
return
|
|
9289
|
+
return formatAtlasSource(atlasDocument);
|
|
8047
9290
|
}
|
|
8048
9291
|
return canonicalSource;
|
|
8049
9292
|
}
|
|
@@ -8082,7 +9325,7 @@ var WorldOrbit = (() => {
|
|
|
8082
9325
|
}
|
|
8083
9326
|
clearSourceInputTimer();
|
|
8084
9327
|
atlasDocument = cloneAtlasDocument(nextDocument);
|
|
8085
|
-
canonicalSource =
|
|
9328
|
+
canonicalSource = formatAtlasSource(atlasDocument);
|
|
8086
9329
|
if (!preserveSourceText) {
|
|
8087
9330
|
sourceText = canonicalSource;
|
|
8088
9331
|
}
|
|
@@ -8123,10 +9366,10 @@ var WorldOrbit = (() => {
|
|
|
8123
9366
|
if (commitHistory) {
|
|
8124
9367
|
history.push(createHistoryEntry());
|
|
8125
9368
|
future.length = 0;
|
|
8126
|
-
sourceText =
|
|
9369
|
+
sourceText = formatAtlasSource(nextDocument);
|
|
8127
9370
|
}
|
|
8128
9371
|
atlasDocument = cloneAtlasDocument(nextDocument);
|
|
8129
|
-
canonicalSource =
|
|
9372
|
+
canonicalSource = formatAtlasSource(atlasDocument);
|
|
8130
9373
|
diagnostics = mergeDiagnostics(loadedDiagnostics, collectDocumentDiagnostics(atlasDocument));
|
|
8131
9374
|
selection = normalizeSelection(selection);
|
|
8132
9375
|
syncViewer({
|
|
@@ -8145,11 +9388,13 @@ var WorldOrbit = (() => {
|
|
|
8145
9388
|
const previousState = viewer.getState();
|
|
8146
9389
|
const currentRenderOptions = viewer.getRenderOptions();
|
|
8147
9390
|
const nextPreset = atlasDocument.system?.defaults.preset ?? "atlas-card";
|
|
9391
|
+
const nextActiveEventId = selection ? selectionEventId(selection) : null;
|
|
8148
9392
|
ignoreViewerSelection = true;
|
|
8149
|
-
if (currentRenderOptions.preset !== nextPreset || currentRenderOptions.projection !== "document") {
|
|
9393
|
+
if (currentRenderOptions.preset !== nextPreset || currentRenderOptions.projection !== "document" || (currentRenderOptions.activeEventId ?? null) !== nextActiveEventId) {
|
|
8150
9394
|
viewer.setRenderOptions({
|
|
8151
9395
|
preset: nextPreset,
|
|
8152
|
-
projection: "document"
|
|
9396
|
+
projection: "document",
|
|
9397
|
+
activeEventId: nextActiveEventId
|
|
8153
9398
|
});
|
|
8154
9399
|
}
|
|
8155
9400
|
viewer.setDocument(materializeAtlasDocument(atlasDocument));
|
|
@@ -8158,10 +9403,12 @@ var WorldOrbit = (() => {
|
|
|
8158
9403
|
} else if (options2.preserveCamera !== false) {
|
|
8159
9404
|
viewer.setState({
|
|
8160
9405
|
...previousState,
|
|
8161
|
-
selectedObjectId: selection?.kind === "object" ? selection.id ?? null : null
|
|
9406
|
+
selectedObjectId: selection?.kind === "object" ? selection.id ?? null : selection?.kind === "event-pose" ? selection.key ?? null : null
|
|
8162
9407
|
});
|
|
8163
9408
|
} else if (selection?.kind === "object" && selection.id) {
|
|
8164
9409
|
viewer.focusObject(selection.id);
|
|
9410
|
+
} else if (selection?.kind === "event-pose" && selection.key) {
|
|
9411
|
+
viewer.focusObject(selection.key);
|
|
8165
9412
|
}
|
|
8166
9413
|
ignoreViewerSelection = false;
|
|
8167
9414
|
}
|
|
@@ -8180,8 +9427,11 @@ var WorldOrbit = (() => {
|
|
|
8180
9427
|
selection = normalizeSelection(nextSelection);
|
|
8181
9428
|
if (syncViewerSelection) {
|
|
8182
9429
|
ignoreViewerSelection = true;
|
|
9430
|
+
viewer.setRenderOptions({ activeEventId: selection ? selectionEventId(selection) : null });
|
|
8183
9431
|
if (selection?.kind === "object" && selection.id) {
|
|
8184
9432
|
viewer.focusObject(selection.id);
|
|
9433
|
+
} else if (selection?.kind === "event-pose" && selection.key) {
|
|
9434
|
+
viewer.focusObject(selection.key);
|
|
8185
9435
|
} else if (selection?.kind === "viewpoint" && selection.id) {
|
|
8186
9436
|
viewer.goToViewpoint(selection.id);
|
|
8187
9437
|
}
|
|
@@ -8231,6 +9481,7 @@ var WorldOrbit = (() => {
|
|
|
8231
9481
|
${OBJECT_TYPES.map((type) => `<option value="${escapeHtml3(type)}"${type === objectType ? " selected" : ""}>${escapeHtml3(humanizeIdentifier4(type))}</option>`).join("")}
|
|
8232
9482
|
</select>
|
|
8233
9483
|
<button type="button" data-editor-action="add-object">Add object</button>
|
|
9484
|
+
<button type="button" data-editor-action="add-event">Add event</button>
|
|
8234
9485
|
<button type="button" data-editor-action="add-viewpoint">Add viewpoint</button>
|
|
8235
9486
|
<button type="button" data-editor-action="add-annotation">Add annotation</button>
|
|
8236
9487
|
<button type="button" data-editor-action="add-metadata">Add metadata</button>
|
|
@@ -8265,6 +9516,10 @@ var WorldOrbit = (() => {
|
|
|
8265
9516
|
<h3>Annotations</h3>
|
|
8266
9517
|
${(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
9518
|
</div>
|
|
9519
|
+
<div class="wo-editor-outline-section">
|
|
9520
|
+
<h3>Events</h3>
|
|
9521
|
+
${atlasDocument.events.length > 0 ? atlasDocument.events.map((eventEntry) => renderEventOutlineItems(eventEntry, activeKey, diagnosticBuckets)).join("") : `<p class="wo-editor-empty">No events yet.</p>`}
|
|
9522
|
+
</div>
|
|
8268
9523
|
<div class="wo-editor-outline-section">
|
|
8269
9524
|
<h3>Objects</h3>
|
|
8270
9525
|
${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 +9557,7 @@ var WorldOrbit = (() => {
|
|
|
8302
9557
|
selection: selection ? { path: { ...selection } } : null,
|
|
8303
9558
|
system: atlasDocument.system,
|
|
8304
9559
|
viewpoints: atlasDocument.system?.viewpoints ?? [],
|
|
9560
|
+
events: atlasDocument.events,
|
|
8305
9561
|
objects: atlasDocument.objects
|
|
8306
9562
|
};
|
|
8307
9563
|
if (!selection) {
|
|
@@ -8330,6 +9586,16 @@ var WorldOrbit = (() => {
|
|
|
8330
9586
|
applyInspectorSectionState(inspector, inspectorSectionState);
|
|
8331
9587
|
decorateInspectorDiagnostics(selection, diagnostics);
|
|
8332
9588
|
return;
|
|
9589
|
+
case "event":
|
|
9590
|
+
inspector.innerHTML = diagnosticSummary + renderEventInspector(formState, selection.id ?? "");
|
|
9591
|
+
applyInspectorSectionState(inspector, inspectorSectionState);
|
|
9592
|
+
decorateInspectorDiagnostics(selection, diagnostics);
|
|
9593
|
+
return;
|
|
9594
|
+
case "event-pose":
|
|
9595
|
+
inspector.innerHTML = diagnosticSummary + renderEventPoseInspector(formState, selection.id ?? "", selection.key ?? "");
|
|
9596
|
+
applyInspectorSectionState(inspector, inspectorSectionState);
|
|
9597
|
+
decorateInspectorDiagnostics(selection, diagnostics);
|
|
9598
|
+
return;
|
|
8333
9599
|
case "annotation":
|
|
8334
9600
|
inspector.innerHTML = diagnosticSummary + renderAnnotationInspector(formState, selection.id ?? "");
|
|
8335
9601
|
applyInspectorSectionState(inspector, inspectorSectionState);
|
|
@@ -8362,10 +9628,11 @@ var WorldOrbit = (() => {
|
|
|
8362
9628
|
return;
|
|
8363
9629
|
}
|
|
8364
9630
|
overlay.innerHTML = "";
|
|
8365
|
-
|
|
9631
|
+
const selectedObjectId = selection?.kind === "object" ? selection.id ?? null : selection?.kind === "event-pose" ? selection.key ?? null : null;
|
|
9632
|
+
if (!selectedObjectId) {
|
|
8366
9633
|
return;
|
|
8367
9634
|
}
|
|
8368
|
-
const details = viewer.getObjectDetails(
|
|
9635
|
+
const details = viewer.getObjectDetails(selectedObjectId);
|
|
8369
9636
|
if (!details) {
|
|
8370
9637
|
return;
|
|
8371
9638
|
}
|
|
@@ -8477,6 +9744,9 @@ var WorldOrbit = (() => {
|
|
|
8477
9744
|
case "add-viewpoint":
|
|
8478
9745
|
api.addViewpoint();
|
|
8479
9746
|
return;
|
|
9747
|
+
case "add-event":
|
|
9748
|
+
api.addEvent();
|
|
9749
|
+
return;
|
|
8480
9750
|
case "add-annotation":
|
|
8481
9751
|
api.addAnnotation();
|
|
8482
9752
|
return;
|
|
@@ -8511,6 +9781,32 @@ var WorldOrbit = (() => {
|
|
|
8511
9781
|
key: button.dataset.pathKey || void 0
|
|
8512
9782
|
}, true, true);
|
|
8513
9783
|
}
|
|
9784
|
+
function handleInspectorClick(event) {
|
|
9785
|
+
const pathButton = event.target?.closest("[data-path-kind]");
|
|
9786
|
+
if (pathButton) {
|
|
9787
|
+
setSelection({
|
|
9788
|
+
kind: pathButton.dataset.pathKind,
|
|
9789
|
+
id: pathButton.dataset.pathId || void 0,
|
|
9790
|
+
key: pathButton.dataset.pathKey || void 0
|
|
9791
|
+
}, true, true);
|
|
9792
|
+
return;
|
|
9793
|
+
}
|
|
9794
|
+
const actionButton = event.target?.closest("[data-editor-action]");
|
|
9795
|
+
if (!actionButton) {
|
|
9796
|
+
return;
|
|
9797
|
+
}
|
|
9798
|
+
if (actionButton.dataset.editorAction === "add-event-pose") {
|
|
9799
|
+
const eventId = actionButton.dataset.editorEventId || (selection?.kind === "event" || selection?.kind === "event-pose" ? selection.id ?? "" : "");
|
|
9800
|
+
if (!eventId) {
|
|
9801
|
+
return;
|
|
9802
|
+
}
|
|
9803
|
+
const nextDocument = addEventPose(atlasDocument, eventId);
|
|
9804
|
+
const createdEvent = nextDocument.events.find((entry) => entry.id === eventId);
|
|
9805
|
+
const createdPose = createdEvent?.positions.at(-1) ?? createdEvent?.positions[0];
|
|
9806
|
+
replaceAtlasDocument(nextDocument, true, createdPose ? { kind: "event-pose", id: eventId, key: createdPose.objectId } : { kind: "event", id: eventId });
|
|
9807
|
+
return;
|
|
9808
|
+
}
|
|
9809
|
+
}
|
|
8514
9810
|
function handleInspectorInput() {
|
|
8515
9811
|
applyInspectorState(false);
|
|
8516
9812
|
}
|
|
@@ -8534,6 +9830,12 @@ var WorldOrbit = (() => {
|
|
|
8534
9830
|
case "viewpoint":
|
|
8535
9831
|
replaceAtlasDocument(buildViewpointDocumentFromInspector(selection.id ?? ""), commitHistory, selection, false);
|
|
8536
9832
|
return;
|
|
9833
|
+
case "event":
|
|
9834
|
+
replaceAtlasDocument(buildEventDocumentFromInspector(selection.id ?? ""), commitHistory, selection, false);
|
|
9835
|
+
return;
|
|
9836
|
+
case "event-pose":
|
|
9837
|
+
replaceAtlasDocument(buildEventPoseDocumentFromInspector(selection.id ?? "", selection.key ?? ""), commitHistory, selection, false);
|
|
9838
|
+
return;
|
|
8537
9839
|
case "annotation":
|
|
8538
9840
|
replaceAtlasDocument(buildAnnotationDocumentFromInspector(selection.id ?? ""), commitHistory, selection, false);
|
|
8539
9841
|
return;
|
|
@@ -8602,6 +9904,7 @@ var WorldOrbit = (() => {
|
|
|
8602
9904
|
kind,
|
|
8603
9905
|
objectId,
|
|
8604
9906
|
pointerId: event.pointerId,
|
|
9907
|
+
path: selection ? { ...selection } : { kind: "object", id: objectId },
|
|
8605
9908
|
startedFrom: createHistoryEntry(),
|
|
8606
9909
|
changed: false,
|
|
8607
9910
|
orbitRadiusContext: kind === "orbit-radius" && details ? createOrbitRadiusDragContext(atlasDocument, viewer.getScene(), details) : null
|
|
@@ -8610,7 +9913,7 @@ var WorldOrbit = (() => {
|
|
|
8610
9913
|
event.preventDefault();
|
|
8611
9914
|
}
|
|
8612
9915
|
function handleWindowPointerMove(event) {
|
|
8613
|
-
if (!dragState || dragState.pointerId !== event.pointerId || selection
|
|
9916
|
+
if (!dragState || dragState.pointerId !== event.pointerId || !selection || selectionKey(selection) !== selectionKey(dragState.path)) {
|
|
8614
9917
|
return;
|
|
8615
9918
|
}
|
|
8616
9919
|
const details = viewer.getObjectDetails(dragState.objectId);
|
|
@@ -8622,27 +9925,27 @@ var WorldOrbit = (() => {
|
|
|
8622
9925
|
switch (dragState.kind) {
|
|
8623
9926
|
case "orbit-phase":
|
|
8624
9927
|
if (details.object.placement?.mode === "orbit" && details.orbit) {
|
|
8625
|
-
nextDocument = updateOrbitPhase(atlasDocument, dragState.objectId, details, pointer);
|
|
9928
|
+
nextDocument = updateOrbitPhase(atlasDocument, dragState.path, dragState.objectId, details, pointer);
|
|
8626
9929
|
}
|
|
8627
9930
|
break;
|
|
8628
9931
|
case "orbit-radius":
|
|
8629
9932
|
if (details.object.placement?.mode === "orbit" && details.orbit) {
|
|
8630
|
-
nextDocument = updateOrbitRadius(atlasDocument, dragState.objectId, details, pointer, dragState.orbitRadiusContext ?? null);
|
|
9933
|
+
nextDocument = updateOrbitRadius(atlasDocument, dragState.path, dragState.objectId, details, pointer, dragState.orbitRadiusContext ?? null);
|
|
8631
9934
|
}
|
|
8632
9935
|
break;
|
|
8633
9936
|
case "at-reference":
|
|
8634
9937
|
if (details.object.placement?.mode === "at") {
|
|
8635
|
-
nextDocument = updateAtReference(atlasDocument, dragState.objectId, viewer.getScene(), pointer);
|
|
9938
|
+
nextDocument = updateAtReference(atlasDocument, dragState.path, dragState.objectId, viewer.getScene(), pointer);
|
|
8636
9939
|
}
|
|
8637
9940
|
break;
|
|
8638
9941
|
case "surface-target":
|
|
8639
9942
|
if (details.object.placement?.mode === "surface") {
|
|
8640
|
-
nextDocument = updateSurfaceTarget(atlasDocument, dragState.objectId, viewer.getScene(), pointer);
|
|
9943
|
+
nextDocument = updateSurfaceTarget(atlasDocument, dragState.path, dragState.objectId, viewer.getScene(), pointer);
|
|
8641
9944
|
}
|
|
8642
9945
|
break;
|
|
8643
9946
|
case "free-distance":
|
|
8644
9947
|
if (details.object.placement?.mode === "free") {
|
|
8645
|
-
nextDocument = updateFreeDistance(atlasDocument, dragState.objectId, viewer.getScene(), details, pointer);
|
|
9948
|
+
nextDocument = updateFreeDistance(atlasDocument, dragState.path, dragState.objectId, viewer.getScene(), details, pointer);
|
|
8646
9949
|
}
|
|
8647
9950
|
break;
|
|
8648
9951
|
}
|
|
@@ -8674,7 +9977,7 @@ var WorldOrbit = (() => {
|
|
|
8674
9977
|
}
|
|
8675
9978
|
history.push(dragState.startedFrom);
|
|
8676
9979
|
future.length = 0;
|
|
8677
|
-
canonicalSource =
|
|
9980
|
+
canonicalSource = formatAtlasSource(atlasDocument);
|
|
8678
9981
|
sourceText = canonicalSource;
|
|
8679
9982
|
dragState = null;
|
|
8680
9983
|
renderAll();
|
|
@@ -8772,15 +10075,18 @@ var WorldOrbit = (() => {
|
|
|
8772
10075
|
preset: readOptionalTextInput(form, "viewpoint-preset") ?? null,
|
|
8773
10076
|
zoom: parseNullableNumber(readOptionalTextInput(form, "viewpoint-zoom")),
|
|
8774
10077
|
rotationDeg: parseNullableNumber(readOptionalTextInput(form, "viewpoint-rotation")) ?? 0,
|
|
10078
|
+
camera: buildViewCameraFromForm(form),
|
|
8775
10079
|
layers: {
|
|
8776
10080
|
background: readCheckbox(form, "layer-background"),
|
|
8777
10081
|
guides: readCheckbox(form, "layer-guides"),
|
|
8778
10082
|
"orbits-back": readCheckbox(form, "layer-orbits-back"),
|
|
8779
10083
|
"orbits-front": readCheckbox(form, "layer-orbits-front"),
|
|
10084
|
+
events: readCheckbox(form, "layer-events"),
|
|
8780
10085
|
objects: readCheckbox(form, "layer-objects"),
|
|
8781
10086
|
labels: readCheckbox(form, "layer-labels"),
|
|
8782
10087
|
metadata: readCheckbox(form, "layer-metadata")
|
|
8783
10088
|
},
|
|
10089
|
+
events: splitTokens(readOptionalTextInput(form, "viewpoint-events")),
|
|
8784
10090
|
filter: {
|
|
8785
10091
|
query: readOptionalTextInput(form, "filter-query"),
|
|
8786
10092
|
objectTypes: parseObjectTypes(readOptionalTextInput(form, "filter-object-types")),
|
|
@@ -8794,6 +10100,70 @@ var WorldOrbit = (() => {
|
|
|
8794
10100
|
}
|
|
8795
10101
|
return nextDocument;
|
|
8796
10102
|
}
|
|
10103
|
+
function buildEventDocumentFromInspector(currentId) {
|
|
10104
|
+
const nextDocument = cloneAtlasDocument(atlasDocument);
|
|
10105
|
+
const form = inspector?.querySelector("form[data-editor-form='event']");
|
|
10106
|
+
const current = nextDocument.events.find((entry) => entry.id === currentId);
|
|
10107
|
+
if (!form || !current) {
|
|
10108
|
+
return nextDocument;
|
|
10109
|
+
}
|
|
10110
|
+
const nextId = readTextInput(form, "event-id") || current.id;
|
|
10111
|
+
const replacement = {
|
|
10112
|
+
...current,
|
|
10113
|
+
id: nextId,
|
|
10114
|
+
kind: readTextInput(form, "event-kind"),
|
|
10115
|
+
label: readTextInput(form, "event-label") || current.label,
|
|
10116
|
+
summary: readOptionalTextInput(form, "event-summary"),
|
|
10117
|
+
targetObjectId: readOptionalTextInput(form, "event-target"),
|
|
10118
|
+
participantObjectIds: splitTokens(readOptionalTextInput(form, "event-participants")),
|
|
10119
|
+
timing: readOptionalTextInput(form, "event-timing"),
|
|
10120
|
+
visibility: readOptionalTextInput(form, "event-visibility"),
|
|
10121
|
+
epoch: readOptionalTextInput(form, "event-epoch"),
|
|
10122
|
+
referencePlane: readOptionalTextInput(form, "event-referencePlane"),
|
|
10123
|
+
tags: splitTokens(readOptionalTextInput(form, "event-tags")),
|
|
10124
|
+
color: readOptionalTextInput(form, "event-color"),
|
|
10125
|
+
hidden: readCheckbox(form, "event-hidden")
|
|
10126
|
+
};
|
|
10127
|
+
nextDocument.events = nextDocument.events.filter((entry) => entry.id !== current.id).concat(replacement).sort(compareEvents);
|
|
10128
|
+
syncEventViewpointReferences(nextDocument, current.id, replacement.id, splitTokens(readOptionalTextInput(form, "event-viewpoints")));
|
|
10129
|
+
if (current.id !== replacement.id) {
|
|
10130
|
+
selection = { kind: "event", id: replacement.id };
|
|
10131
|
+
}
|
|
10132
|
+
return nextDocument;
|
|
10133
|
+
}
|
|
10134
|
+
function buildEventPoseDocumentFromInspector(eventId, objectId) {
|
|
10135
|
+
const nextDocument = cloneAtlasDocument(atlasDocument);
|
|
10136
|
+
const form = inspector?.querySelector("form[data-editor-form='event-pose']");
|
|
10137
|
+
const eventEntry = nextDocument.events.find((entry) => entry.id === eventId);
|
|
10138
|
+
const currentPose = eventEntry?.positions.find((entry) => entry.objectId === objectId);
|
|
10139
|
+
if (!form || !eventEntry || !currentPose) {
|
|
10140
|
+
return nextDocument;
|
|
10141
|
+
}
|
|
10142
|
+
const nextObjectId = readTextInput(form, "pose-object-id") || currentPose.objectId;
|
|
10143
|
+
const replacement = {
|
|
10144
|
+
objectId: nextObjectId,
|
|
10145
|
+
placement: buildPlacementFromPoseForm(form, currentPose),
|
|
10146
|
+
epoch: readOptionalTextInput(form, "pose-epoch"),
|
|
10147
|
+
referencePlane: readOptionalTextInput(form, "pose-referencePlane")
|
|
10148
|
+
};
|
|
10149
|
+
const inner = parseOptionalUnit(readOptionalTextInput(form, "prop-inner"));
|
|
10150
|
+
const outer = parseOptionalUnit(readOptionalTextInput(form, "prop-outer"));
|
|
10151
|
+
if (inner) {
|
|
10152
|
+
replacement.inner = inner;
|
|
10153
|
+
}
|
|
10154
|
+
if (outer) {
|
|
10155
|
+
replacement.outer = outer;
|
|
10156
|
+
}
|
|
10157
|
+
eventEntry.positions = eventEntry.positions.filter((entry) => entry.objectId !== currentPose.objectId).concat(replacement).sort(compareEventPoses);
|
|
10158
|
+
if (eventEntry.targetObjectId !== replacement.objectId && !eventEntry.participantObjectIds.includes(replacement.objectId)) {
|
|
10159
|
+
eventEntry.participantObjectIds.push(replacement.objectId);
|
|
10160
|
+
eventEntry.participantObjectIds.sort((left, right) => left.localeCompare(right));
|
|
10161
|
+
}
|
|
10162
|
+
if (currentPose.objectId !== replacement.objectId) {
|
|
10163
|
+
selection = { kind: "event-pose", id: eventId, key: replacement.objectId };
|
|
10164
|
+
}
|
|
10165
|
+
return nextDocument;
|
|
10166
|
+
}
|
|
8797
10167
|
function buildAnnotationDocumentFromInspector(currentId) {
|
|
8798
10168
|
const nextDocument = cloneAtlasDocument(atlasDocument);
|
|
8799
10169
|
const form = inspector?.querySelector("form[data-editor-form='annotation']");
|
|
@@ -8986,7 +10356,7 @@ var WorldOrbit = (() => {
|
|
|
8986
10356
|
const atlasDocument2 = cloneAtlasDocument(options.atlasDocument);
|
|
8987
10357
|
return {
|
|
8988
10358
|
atlasDocument: atlasDocument2,
|
|
8989
|
-
source:
|
|
10359
|
+
source: formatAtlasSource(atlasDocument2),
|
|
8990
10360
|
diagnostics: collectDocumentDiagnostics(atlasDocument2)
|
|
8991
10361
|
};
|
|
8992
10362
|
}
|
|
@@ -8996,7 +10366,7 @@ var WorldOrbit = (() => {
|
|
|
8996
10366
|
const atlasDocument2 = loaded.value.atlasDocument ?? upgradeDocumentToV2(loaded.value.document);
|
|
8997
10367
|
return {
|
|
8998
10368
|
atlasDocument: atlasDocument2,
|
|
8999
|
-
source:
|
|
10369
|
+
source: formatAtlasSource(atlasDocument2),
|
|
9000
10370
|
diagnostics: mergeDiagnostics(resolveAtlasDiagnostics(atlasDocument2, loaded.diagnostics), collectDocumentDiagnostics(atlasDocument2))
|
|
9001
10371
|
};
|
|
9002
10372
|
}
|
|
@@ -9004,10 +10374,13 @@ var WorldOrbit = (() => {
|
|
|
9004
10374
|
const atlasDocument = createEmptyAtlasDocument("WorldOrbit");
|
|
9005
10375
|
return {
|
|
9006
10376
|
atlasDocument,
|
|
9007
|
-
source:
|
|
10377
|
+
source: formatAtlasSource(atlasDocument),
|
|
9008
10378
|
diagnostics: collectDocumentDiagnostics(atlasDocument)
|
|
9009
10379
|
};
|
|
9010
10380
|
}
|
|
10381
|
+
function formatAtlasSource(document2) {
|
|
10382
|
+
return formatDocument(document2, { schema: document2.version });
|
|
10383
|
+
}
|
|
9011
10384
|
function buildEditorMarkup() {
|
|
9012
10385
|
const previewOpen = shouldPreviewSectionBeOpenByDefault();
|
|
9013
10386
|
return `<section class="wo-editor-shell">
|
|
@@ -9122,6 +10495,12 @@ var WorldOrbit = (() => {
|
|
|
9122
10495
|
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
10496
|
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
10497
|
}
|
|
10498
|
+
function renderEventOutlineItems(eventEntry, activeKey, diagnosticBuckets) {
|
|
10499
|
+
return `<div class="wo-editor-outline-group">
|
|
10500
|
+
${renderOutlineButton({ kind: "event", id: eventEntry.id }, eventEntry.label || eventEntry.id, activeKey, diagnosticBuckets)}
|
|
10501
|
+
${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>` : ""}
|
|
10502
|
+
</div>`;
|
|
10503
|
+
}
|
|
9125
10504
|
function renderSystemInspector(formState) {
|
|
9126
10505
|
return `<form class="wo-editor-form" data-editor-form="system">
|
|
9127
10506
|
<h2>System</h2>
|
|
@@ -9135,7 +10514,9 @@ var WorldOrbit = (() => {
|
|
|
9135
10514
|
<h2>Defaults</h2>
|
|
9136
10515
|
${renderInspectorSection("defaults", "basics", "Basics", `${renderSelectField("Projection", "defaults-view", [
|
|
9137
10516
|
["topdown", "Topdown"],
|
|
9138
|
-
["isometric", "Isometric"]
|
|
10517
|
+
["isometric", "Isometric"],
|
|
10518
|
+
["orthographic", "Orthographic"],
|
|
10519
|
+
["perspective", "Perspective"]
|
|
9139
10520
|
], defaults?.view ?? "topdown")}
|
|
9140
10521
|
${renderTextField("Scale preset", "defaults-scale", defaults?.scale ?? "")}
|
|
9141
10522
|
${renderTextField("Units", "defaults-units", defaults?.units ?? "")}
|
|
@@ -9171,7 +10552,9 @@ var WorldOrbit = (() => {
|
|
|
9171
10552
|
${renderTextField("Selected object", "viewpoint-select", viewpoint.selectedObjectId ?? "")}
|
|
9172
10553
|
${renderSelectField("Projection", "viewpoint-projection", [
|
|
9173
10554
|
["topdown", "Topdown"],
|
|
9174
|
-
["isometric", "Isometric"]
|
|
10555
|
+
["isometric", "Isometric"],
|
|
10556
|
+
["orthographic", "Orthographic"],
|
|
10557
|
+
["perspective", "Perspective"]
|
|
9175
10558
|
], viewpoint.projection)}
|
|
9176
10559
|
${renderSelectField("Preset", "viewpoint-preset", [
|
|
9177
10560
|
["", "Document default"],
|
|
@@ -9182,12 +10565,18 @@ var WorldOrbit = (() => {
|
|
|
9182
10565
|
], viewpoint.preset ?? "")}
|
|
9183
10566
|
${renderTextField("Zoom", "viewpoint-zoom", viewpoint.zoom === null ? "" : String(viewpoint.zoom))}
|
|
9184
10567
|
${renderTextField("Rotation", "viewpoint-rotation", String(viewpoint.rotationDeg))}`, true)}
|
|
10568
|
+
${renderInspectorSection("viewpoint", "camera", "Camera", `${renderTextField("Azimuth", "viewpoint-camera-azimuth", viewpoint.camera?.azimuth === null || viewpoint.camera?.azimuth === void 0 ? "" : String(viewpoint.camera.azimuth))}
|
|
10569
|
+
${renderTextField("Elevation", "viewpoint-camera-elevation", viewpoint.camera?.elevation === null || viewpoint.camera?.elevation === void 0 ? "" : String(viewpoint.camera.elevation))}
|
|
10570
|
+
${renderTextField("Roll", "viewpoint-camera-roll", viewpoint.camera?.roll === null || viewpoint.camera?.roll === void 0 ? "" : String(viewpoint.camera.roll))}
|
|
10571
|
+
${renderTextField("Distance", "viewpoint-camera-distance", viewpoint.camera?.distance === null || viewpoint.camera?.distance === void 0 ? "" : String(viewpoint.camera.distance))}
|
|
10572
|
+
<p class="wo-editor-inline-note">Rotation stays a 2D screen-rotation hint. The camera block stores Schema 2.5 view direction and framing.</p>`)}
|
|
9185
10573
|
${renderInspectorSection("viewpoint", "layers", "Layers", `<fieldset class="wo-editor-fieldset">
|
|
9186
10574
|
<legend>Layers</legend>
|
|
9187
10575
|
${renderCheckboxField("Background", "layer-background", viewpoint.layers.background !== false)}
|
|
9188
10576
|
${renderCheckboxField("Guides", "layer-guides", viewpoint.layers.guides !== false)}
|
|
9189
10577
|
${renderCheckboxField("Orbits back", "layer-orbits-back", viewpoint.layers["orbits-back"] !== false)}
|
|
9190
10578
|
${renderCheckboxField("Orbits front", "layer-orbits-front", viewpoint.layers["orbits-front"] !== false)}
|
|
10579
|
+
${renderCheckboxField("Events", "layer-events", viewpoint.layers.events !== false)}
|
|
9191
10580
|
${renderCheckboxField("Objects", "layer-objects", viewpoint.layers.objects !== false)}
|
|
9192
10581
|
${renderCheckboxField("Labels", "layer-labels", viewpoint.layers.labels !== false)}
|
|
9193
10582
|
${renderCheckboxField("Metadata", "layer-metadata", viewpoint.layers.metadata !== false)}
|
|
@@ -9195,7 +10584,75 @@ var WorldOrbit = (() => {
|
|
|
9195
10584
|
${renderInspectorSection("viewpoint", "filter", "Filter", `${renderTextField("Filter query", "filter-query", viewpoint.filter?.query ?? "")}
|
|
9196
10585
|
${renderTextField("Filter object types", "filter-object-types", viewpoint.filter?.objectTypes.join(" ") ?? "")}
|
|
9197
10586
|
${renderTextField("Filter tags", "filter-tags", viewpoint.filter?.tags.join(" ") ?? "")}
|
|
9198
|
-
${renderTextField("Filter groups", "filter-groups", viewpoint.filter?.groupIds.join(" ") ?? "")}
|
|
10587
|
+
${renderTextField("Filter groups", "filter-groups", viewpoint.filter?.groupIds.join(" ") ?? "")}
|
|
10588
|
+
${renderTextField("Events", "viewpoint-events", viewpoint.events.join(" "))}`)}
|
|
10589
|
+
</form>`;
|
|
10590
|
+
}
|
|
10591
|
+
function renderEventInspector(formState, id) {
|
|
10592
|
+
const eventEntry = formState.events.find((entry) => entry.id === id);
|
|
10593
|
+
if (!eventEntry) {
|
|
10594
|
+
return `<p class="wo-editor-empty">Event not found.</p>`;
|
|
10595
|
+
}
|
|
10596
|
+
const linkedViewpoints = formState.viewpoints.filter((viewpoint) => viewpoint.events.includes(eventEntry.id)).map((viewpoint) => viewpoint.id).join(" ");
|
|
10597
|
+
return `<form class="wo-editor-form" data-editor-form="event">
|
|
10598
|
+
<h2>Event</h2>
|
|
10599
|
+
${renderInspectorSection("event", "basics", "Basics", `${renderTextField("ID", "event-id", eventEntry.id)}
|
|
10600
|
+
${renderTextField("Kind", "event-kind", eventEntry.kind)}
|
|
10601
|
+
${renderTextField("Label", "event-label", eventEntry.label)}
|
|
10602
|
+
${renderTextAreaField("Summary", "event-summary", eventEntry.summary ?? "")}
|
|
10603
|
+
${renderTextField("Target object", "event-target", eventEntry.targetObjectId ?? "")}
|
|
10604
|
+
${renderTextField("Participants", "event-participants", eventEntry.participantObjectIds.join(" "))}
|
|
10605
|
+
${renderTextField("Timing", "event-timing", eventEntry.timing ?? "")}
|
|
10606
|
+
${renderTextField("Visibility", "event-visibility", eventEntry.visibility ?? "")}
|
|
10607
|
+
${renderTextField("Epoch", "event-epoch", eventEntry.epoch ?? "")}
|
|
10608
|
+
${renderTextField("Reference plane", "event-referencePlane", eventEntry.referencePlane ?? "")}
|
|
10609
|
+
${renderTextField("Tags", "event-tags", eventEntry.tags.join(" "))}
|
|
10610
|
+
${renderTextField("Color", "event-color", eventEntry.color ?? "")}
|
|
10611
|
+
${renderCheckboxField("Hidden", "event-hidden", eventEntry.hidden === true)}`, true)}
|
|
10612
|
+
${renderInspectorSection("event", "viewpoints", "Viewpoints", `${renderTextField("Viewpoints", "event-viewpoints", linkedViewpoints)}`)}
|
|
10613
|
+
${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>`}
|
|
10614
|
+
<div class="wo-editor-inline-actions">
|
|
10615
|
+
<button type="button" data-editor-action="add-event-pose" data-editor-event-id="${escapeHtml3(eventEntry.id)}">Add pose</button>
|
|
10616
|
+
</div>`)}
|
|
10617
|
+
</form>`;
|
|
10618
|
+
}
|
|
10619
|
+
function renderEventPoseInspector(formState, eventId, objectId) {
|
|
10620
|
+
const eventEntry = formState.events.find((entry) => entry.id === eventId);
|
|
10621
|
+
const pose = eventEntry?.positions.find((entry) => entry.objectId === objectId);
|
|
10622
|
+
if (!eventEntry || !pose) {
|
|
10623
|
+
return `<p class="wo-editor-empty">Event pose not found.</p>`;
|
|
10624
|
+
}
|
|
10625
|
+
const placementMode = pose.placement?.mode ?? "";
|
|
10626
|
+
const placementTarget = pose.placement?.mode === "orbit" || pose.placement?.mode === "surface" || pose.placement?.mode === "at" ? pose.placement.target : "";
|
|
10627
|
+
const freeValue = pose.placement?.mode === "free" ? pose.placement.distance ? formatUnitValue3(pose.placement.distance) : pose.placement.descriptor ?? "" : "";
|
|
10628
|
+
return `<form class="wo-editor-form" data-editor-form="event-pose">
|
|
10629
|
+
<h2>Event Pose</h2>
|
|
10630
|
+
<p class="wo-editor-inline-note">Event <strong>${escapeHtml3(eventEntry.label || eventEntry.id)}</strong></p>
|
|
10631
|
+
${renderInspectorSection("event-pose", "identity", "Identity", `${renderTextField("Object", "pose-object-id", pose.objectId)}
|
|
10632
|
+
<div class="wo-editor-inline-actions">
|
|
10633
|
+
<button type="button" data-path-kind="event" data-path-id="${escapeHtml3(eventEntry.id)}">Select event</button>
|
|
10634
|
+
</div>`, true)}
|
|
10635
|
+
${renderInspectorSection("event-pose", "placement", "Placement", `${renderSelectField("Placement mode", "placement-mode", [
|
|
10636
|
+
["", "None"],
|
|
10637
|
+
["orbit", "Orbit"],
|
|
10638
|
+
["at", "At"],
|
|
10639
|
+
["surface", "Surface"],
|
|
10640
|
+
["free", "Free"]
|
|
10641
|
+
], placementMode)}
|
|
10642
|
+
${renderTextField("Placement target", "placement-target", placementTarget)}
|
|
10643
|
+
${renderTextField("Free value", "placement-free", freeValue)}
|
|
10644
|
+
${renderTextField("Distance", "placement-distance", pose.placement?.mode === "orbit" && pose.placement.distance ? formatUnitValue3(pose.placement.distance) : "")}
|
|
10645
|
+
${renderTextField("Semi-major", "placement-semiMajor", pose.placement?.mode === "orbit" && pose.placement.semiMajor ? formatUnitValue3(pose.placement.semiMajor) : "")}
|
|
10646
|
+
${renderTextField("Eccentricity", "placement-eccentricity", pose.placement?.mode === "orbit" && pose.placement.eccentricity !== void 0 ? String(pose.placement.eccentricity) : "")}
|
|
10647
|
+
${renderTextField("Period", "placement-period", pose.placement?.mode === "orbit" && pose.placement.period ? formatUnitValue3(pose.placement.period) : "")}
|
|
10648
|
+
${renderTextField("Angle", "placement-angle", pose.placement?.mode === "orbit" && pose.placement.angle ? formatUnitValue3(pose.placement.angle) : "")}
|
|
10649
|
+
${renderTextField("Inclination", "placement-inclination", pose.placement?.mode === "orbit" && pose.placement.inclination ? formatUnitValue3(pose.placement.inclination) : "")}
|
|
10650
|
+
${renderTextField("Phase", "placement-phase", pose.placement?.mode === "orbit" && pose.placement.phase ? formatUnitValue3(pose.placement.phase) : "")}
|
|
10651
|
+
${renderTextField("Inner", "prop-inner", pose.inner ? formatUnitValue3(pose.inner) : "")}
|
|
10652
|
+
${renderTextField("Outer", "prop-outer", pose.outer ? formatUnitValue3(pose.outer) : "")}`, true)}
|
|
10653
|
+
${renderInspectorSection("event-pose", "context", "Context", `${renderTextField("Epoch", "pose-epoch", pose.epoch ?? "")}
|
|
10654
|
+
${renderTextField("Reference plane", "pose-referencePlane", pose.referencePlane ?? "")}
|
|
10655
|
+
<p class="wo-editor-inline-note">Falls back to event, then object, then system context when left empty.</p>`)}
|
|
9199
10656
|
</form>`;
|
|
9200
10657
|
}
|
|
9201
10658
|
function renderAnnotationInspector(formState, id) {
|
|
@@ -9300,13 +10757,19 @@ var WorldOrbit = (() => {
|
|
|
9300
10757
|
return form.elements.namedItem(name)?.checked ?? false;
|
|
9301
10758
|
}
|
|
9302
10759
|
function buildPlacementFromForm(form, current) {
|
|
10760
|
+
return buildPlacementFromValues(form, current.placement, current.id);
|
|
10761
|
+
}
|
|
10762
|
+
function buildPlacementFromPoseForm(form, current) {
|
|
10763
|
+
return buildPlacementFromValues(form, current.placement, current.objectId);
|
|
10764
|
+
}
|
|
10765
|
+
function buildPlacementFromValues(form, currentPlacement, fallbackTarget) {
|
|
9303
10766
|
const mode = readTextInput(form, "placement-mode");
|
|
9304
10767
|
const target = readOptionalTextInput(form, "placement-target");
|
|
9305
10768
|
switch (mode) {
|
|
9306
10769
|
case "orbit":
|
|
9307
10770
|
return {
|
|
9308
10771
|
mode,
|
|
9309
|
-
target: target ?? (
|
|
10772
|
+
target: target ?? (currentPlacement?.mode === "orbit" ? currentPlacement.target : fallbackTarget),
|
|
9310
10773
|
distance: parseOptionalUnit(readOptionalTextInput(form, "placement-distance")),
|
|
9311
10774
|
semiMajor: parseOptionalUnit(readOptionalTextInput(form, "placement-semiMajor")),
|
|
9312
10775
|
eccentricity: parseNullableNumber(readOptionalTextInput(form, "placement-eccentricity")) ?? void 0,
|
|
@@ -9318,13 +10781,13 @@ var WorldOrbit = (() => {
|
|
|
9318
10781
|
case "at":
|
|
9319
10782
|
return {
|
|
9320
10783
|
mode,
|
|
9321
|
-
target: target ??
|
|
9322
|
-
reference: parseAtReferenceString(target ??
|
|
10784
|
+
target: target ?? fallbackTarget,
|
|
10785
|
+
reference: parseAtReferenceString(target ?? fallbackTarget)
|
|
9323
10786
|
};
|
|
9324
10787
|
case "surface":
|
|
9325
10788
|
return {
|
|
9326
10789
|
mode,
|
|
9327
|
-
target: target ??
|
|
10790
|
+
target: target ?? fallbackTarget
|
|
9328
10791
|
};
|
|
9329
10792
|
case "free": {
|
|
9330
10793
|
const freeValue = readOptionalTextInput(form, "placement-free");
|
|
@@ -9374,6 +10837,15 @@ var WorldOrbit = (() => {
|
|
|
9374
10837
|
const parsed = Number(value);
|
|
9375
10838
|
return Number.isFinite(parsed) ? parsed : null;
|
|
9376
10839
|
}
|
|
10840
|
+
function buildViewCameraFromForm(form) {
|
|
10841
|
+
const camera = {
|
|
10842
|
+
azimuth: parseNullableNumber(readOptionalTextInput(form, "viewpoint-camera-azimuth")),
|
|
10843
|
+
elevation: parseNullableNumber(readOptionalTextInput(form, "viewpoint-camera-elevation")),
|
|
10844
|
+
roll: parseNullableNumber(readOptionalTextInput(form, "viewpoint-camera-roll")),
|
|
10845
|
+
distance: parseNullableNumber(readOptionalTextInput(form, "viewpoint-camera-distance"))
|
|
10846
|
+
};
|
|
10847
|
+
return camera.azimuth !== null || camera.elevation !== null || camera.roll !== null || camera.distance !== null ? camera : null;
|
|
10848
|
+
}
|
|
9377
10849
|
function parseObjectTypes(value) {
|
|
9378
10850
|
const tokens = splitTokens(value);
|
|
9379
10851
|
return tokens.filter((token) => OBJECT_TYPES.includes(token));
|
|
@@ -9455,9 +10927,48 @@ var WorldOrbit = (() => {
|
|
|
9455
10927
|
annotation.sourceObjectId = toId;
|
|
9456
10928
|
}
|
|
9457
10929
|
}
|
|
10930
|
+
for (const eventEntry of document2.events) {
|
|
10931
|
+
if (eventEntry.targetObjectId === fromId) {
|
|
10932
|
+
eventEntry.targetObjectId = toId;
|
|
10933
|
+
}
|
|
10934
|
+
eventEntry.participantObjectIds = eventEntry.participantObjectIds.map((entry) => entry === fromId ? toId : entry);
|
|
10935
|
+
for (const pose of eventEntry.positions) {
|
|
10936
|
+
if (pose.objectId === fromId) {
|
|
10937
|
+
pose.objectId = toId;
|
|
10938
|
+
}
|
|
10939
|
+
if (pose.placement?.mode === "orbit" && pose.placement.target === fromId) {
|
|
10940
|
+
pose.placement.target = toId;
|
|
10941
|
+
}
|
|
10942
|
+
if (pose.placement?.mode === "surface" && pose.placement.target === fromId) {
|
|
10943
|
+
pose.placement.target = toId;
|
|
10944
|
+
}
|
|
10945
|
+
if (pose.placement?.mode === "at") {
|
|
10946
|
+
const reference = pose.placement.reference;
|
|
10947
|
+
if (reference.kind === "anchor" && reference.objectId === fromId) {
|
|
10948
|
+
reference.objectId = toId;
|
|
10949
|
+
}
|
|
10950
|
+
if (reference.kind === "lagrange") {
|
|
10951
|
+
if (reference.primary === fromId) {
|
|
10952
|
+
reference.primary = toId;
|
|
10953
|
+
}
|
|
10954
|
+
if (reference.secondary === fromId) {
|
|
10955
|
+
reference.secondary = toId;
|
|
10956
|
+
}
|
|
10957
|
+
}
|
|
10958
|
+
pose.placement.target = formatAtReference2(reference);
|
|
10959
|
+
}
|
|
10960
|
+
}
|
|
10961
|
+
eventEntry.positions.sort(compareEventPoses);
|
|
10962
|
+
}
|
|
9458
10963
|
}
|
|
9459
10964
|
function removeSelectedNode(document2, selection) {
|
|
9460
10965
|
const next = removeAtlasDocumentNode(document2, selection);
|
|
10966
|
+
if (selection.kind === "event" && selection.id) {
|
|
10967
|
+
for (const viewpoint of next.system?.viewpoints ?? []) {
|
|
10968
|
+
viewpoint.events = viewpoint.events.filter((eventId) => eventId !== selection.id);
|
|
10969
|
+
}
|
|
10970
|
+
return next;
|
|
10971
|
+
}
|
|
9461
10972
|
if (selection.kind !== "object" || !selection.id) {
|
|
9462
10973
|
return next;
|
|
9463
10974
|
}
|
|
@@ -9492,9 +11003,45 @@ var WorldOrbit = (() => {
|
|
|
9492
11003
|
annotation.sourceObjectId = null;
|
|
9493
11004
|
}
|
|
9494
11005
|
}
|
|
11006
|
+
for (const eventEntry of next.events) {
|
|
11007
|
+
if (eventEntry.targetObjectId === selection.id) {
|
|
11008
|
+
eventEntry.targetObjectId = null;
|
|
11009
|
+
}
|
|
11010
|
+
eventEntry.participantObjectIds = eventEntry.participantObjectIds.filter((entry) => entry !== selection.id);
|
|
11011
|
+
eventEntry.positions = eventEntry.positions.filter((entry) => entry.objectId !== selection.id);
|
|
11012
|
+
for (const pose of eventEntry.positions) {
|
|
11013
|
+
if (pose.placement?.mode === "orbit" && pose.placement.target === selection.id) {
|
|
11014
|
+
pose.placement = null;
|
|
11015
|
+
}
|
|
11016
|
+
if (pose.placement?.mode === "surface" && pose.placement.target === selection.id) {
|
|
11017
|
+
pose.placement = null;
|
|
11018
|
+
}
|
|
11019
|
+
if (pose.placement?.mode === "at") {
|
|
11020
|
+
const reference = pose.placement.reference;
|
|
11021
|
+
const touchesSelection = reference.kind === "anchor" && reference.objectId === selection.id || reference.kind === "lagrange" && (reference.primary === selection.id || reference.secondary === selection.id);
|
|
11022
|
+
if (touchesSelection) {
|
|
11023
|
+
pose.placement = null;
|
|
11024
|
+
}
|
|
11025
|
+
}
|
|
11026
|
+
}
|
|
11027
|
+
}
|
|
9495
11028
|
return next;
|
|
9496
11029
|
}
|
|
9497
|
-
function
|
|
11030
|
+
function findEditablePlacementOwner(document2, path, objectId) {
|
|
11031
|
+
if (path.kind === "event-pose" && path.id && path.key) {
|
|
11032
|
+
const pose = findEventPose2(document2, path.id, path.key);
|
|
11033
|
+
if (pose?.placement) {
|
|
11034
|
+
return { placement: pose.placement };
|
|
11035
|
+
}
|
|
11036
|
+
return null;
|
|
11037
|
+
}
|
|
11038
|
+
const object = findObject2(document2, objectId);
|
|
11039
|
+
if (object?.placement) {
|
|
11040
|
+
return { placement: object.placement };
|
|
11041
|
+
}
|
|
11042
|
+
return null;
|
|
11043
|
+
}
|
|
11044
|
+
function updateOrbitPhase(document2, path, objectId, details, pointer) {
|
|
9498
11045
|
const orbit = details.orbit;
|
|
9499
11046
|
if (!orbit || details.object.placement?.mode !== "orbit") {
|
|
9500
11047
|
return document2;
|
|
@@ -9505,17 +11052,17 @@ var WorldOrbit = (() => {
|
|
|
9505
11052
|
const radians = Math.atan2((unrotated.y - orbit.cy) / Math.max(ry, 1), (unrotated.x - orbit.cx) / Math.max(rx, 1));
|
|
9506
11053
|
const phaseDeg = normalizeDegrees(radians * 180 / Math.PI);
|
|
9507
11054
|
const next = cloneAtlasDocument(document2);
|
|
9508
|
-
const
|
|
9509
|
-
if (!
|
|
11055
|
+
const placementOwner = findEditablePlacementOwner(next, path, objectId);
|
|
11056
|
+
if (!placementOwner || placementOwner.placement.mode !== "orbit") {
|
|
9510
11057
|
return document2;
|
|
9511
11058
|
}
|
|
9512
|
-
|
|
11059
|
+
placementOwner.placement.phase = {
|
|
9513
11060
|
value: roundNumber(phaseDeg, 2),
|
|
9514
11061
|
unit: "deg"
|
|
9515
11062
|
};
|
|
9516
11063
|
return next;
|
|
9517
11064
|
}
|
|
9518
|
-
function updateOrbitRadius(document2, objectId, details, pointer, dragContext) {
|
|
11065
|
+
function updateOrbitRadius(document2, path, objectId, details, pointer, dragContext) {
|
|
9519
11066
|
const orbit = details.orbit;
|
|
9520
11067
|
if (!orbit || details.object.placement?.mode !== "orbit" || !dragContext) {
|
|
9521
11068
|
return document2;
|
|
@@ -9525,47 +11072,47 @@ var WorldOrbit = (() => {
|
|
|
9525
11072
|
const nextBaseRadius = Math.max(nextDisplayedRadius - dragContext.radiusOffsetPx, dragContext.innerPx);
|
|
9526
11073
|
const nextMetric = orbitRadiusPxToMetric(nextBaseRadius, dragContext.innerPx, dragContext.stepPx);
|
|
9527
11074
|
const next = cloneAtlasDocument(document2);
|
|
9528
|
-
const
|
|
9529
|
-
if (!
|
|
11075
|
+
const placementOwner = findEditablePlacementOwner(next, path, objectId);
|
|
11076
|
+
if (!placementOwner || placementOwner.placement.mode !== "orbit") {
|
|
9530
11077
|
return document2;
|
|
9531
11078
|
}
|
|
9532
|
-
const currentValue =
|
|
11079
|
+
const currentValue = placementOwner.placement.semiMajor ?? placementOwner.placement.distance ?? {
|
|
9533
11080
|
value: 1,
|
|
9534
11081
|
unit: "au"
|
|
9535
11082
|
};
|
|
9536
11083
|
const scaled = distanceMetricToUnitValue(Math.max(nextMetric, 0), dragContext.preferredUnit ?? currentValue.unit);
|
|
9537
|
-
if (
|
|
9538
|
-
|
|
11084
|
+
if (placementOwner.placement.semiMajor) {
|
|
11085
|
+
placementOwner.placement.semiMajor = scaled;
|
|
9539
11086
|
} else {
|
|
9540
|
-
|
|
11087
|
+
placementOwner.placement.distance = scaled;
|
|
9541
11088
|
}
|
|
9542
11089
|
return next;
|
|
9543
11090
|
}
|
|
9544
|
-
function updateAtReference(document2, objectId, scene, pointer) {
|
|
11091
|
+
function updateAtReference(document2, path, objectId, scene, pointer) {
|
|
9545
11092
|
const candidate = findNearestAtCandidate(scene, objectId, pointer);
|
|
9546
11093
|
if (!candidate) {
|
|
9547
11094
|
return document2;
|
|
9548
11095
|
}
|
|
9549
11096
|
const next = cloneAtlasDocument(document2);
|
|
9550
|
-
const
|
|
9551
|
-
if (!
|
|
11097
|
+
const placementOwner = findEditablePlacementOwner(next, path, objectId);
|
|
11098
|
+
if (!placementOwner || placementOwner.placement.mode !== "at") {
|
|
9552
11099
|
return document2;
|
|
9553
11100
|
}
|
|
9554
|
-
|
|
9555
|
-
|
|
11101
|
+
placementOwner.placement.reference = candidate.reference;
|
|
11102
|
+
placementOwner.placement.target = formatAtReference2(candidate.reference);
|
|
9556
11103
|
return next;
|
|
9557
11104
|
}
|
|
9558
|
-
function updateSurfaceTarget(document2, objectId, scene, pointer) {
|
|
11105
|
+
function updateSurfaceTarget(document2, path, objectId, scene, pointer) {
|
|
9559
11106
|
const target = findNearestSceneObject(scene, objectId, pointer, (entry) => SURFACE_TARGET_TYPES3.has(entry.object.type));
|
|
9560
11107
|
if (!target) {
|
|
9561
11108
|
return document2;
|
|
9562
11109
|
}
|
|
9563
11110
|
const next = cloneAtlasDocument(document2);
|
|
9564
|
-
const
|
|
9565
|
-
if (!
|
|
11111
|
+
const placementOwner = findEditablePlacementOwner(next, path, objectId);
|
|
11112
|
+
if (!placementOwner || placementOwner.placement.mode !== "surface") {
|
|
9566
11113
|
return document2;
|
|
9567
11114
|
}
|
|
9568
|
-
|
|
11115
|
+
placementOwner.placement.target = target.objectId;
|
|
9569
11116
|
return next;
|
|
9570
11117
|
}
|
|
9571
11118
|
function createOrbitRadiusDragContext(document2, scene, details) {
|
|
@@ -9573,7 +11120,7 @@ var WorldOrbit = (() => {
|
|
|
9573
11120
|
return null;
|
|
9574
11121
|
}
|
|
9575
11122
|
const targetId = details.object.placement.target;
|
|
9576
|
-
const siblingCount =
|
|
11123
|
+
const siblingCount = scene.objects.filter((entry) => entry.object.placement?.mode === "orbit" && entry.object.placement.target === targetId && !entry.hidden).length;
|
|
9577
11124
|
const spacingFactor = layoutPresetSpacingForScene(scene.layoutPreset);
|
|
9578
11125
|
const stepPx = (siblingCount > 2 ? 54 : 64) * spacingFactor * scene.scaleModel.orbitDistanceMultiplier;
|
|
9579
11126
|
const innerPx = details.parent.radius + 56 * spacingFactor * scene.scaleModel.orbitDistanceMultiplier;
|
|
@@ -9588,28 +11135,28 @@ var WorldOrbit = (() => {
|
|
|
9588
11135
|
preferredUnit: currentValue?.unit ?? null
|
|
9589
11136
|
};
|
|
9590
11137
|
}
|
|
9591
|
-
function updateFreeDistance(document2, objectId, scene, details, pointer) {
|
|
11138
|
+
function updateFreeDistance(document2, path, objectId, scene, details, pointer) {
|
|
9592
11139
|
if (details.object.placement?.mode !== "free") {
|
|
9593
11140
|
return document2;
|
|
9594
11141
|
}
|
|
9595
11142
|
const railX = scene.width - scene.padding - 140;
|
|
9596
11143
|
const offsetPx = Math.max(0, railX - pointer.x);
|
|
9597
11144
|
const next = cloneAtlasDocument(document2);
|
|
9598
|
-
const
|
|
9599
|
-
if (!
|
|
11145
|
+
const placementOwner = findEditablePlacementOwner(next, path, objectId);
|
|
11146
|
+
if (!placementOwner || placementOwner.placement.mode !== "free") {
|
|
9600
11147
|
return document2;
|
|
9601
11148
|
}
|
|
9602
|
-
const preferredUnit = normalizeFreeDistanceUnit(
|
|
11149
|
+
const preferredUnit = normalizeFreeDistanceUnit(placementOwner.placement.distance?.unit ?? null);
|
|
9603
11150
|
const metric = offsetPx / Math.max(FREE_DISTANCE_PIXEL_FACTOR * scene.scaleModel.freePlacementMultiplier, 1);
|
|
9604
11151
|
if (metric < 0.01) {
|
|
9605
|
-
|
|
9606
|
-
if (!
|
|
9607
|
-
delete
|
|
11152
|
+
placementOwner.placement.distance = void 0;
|
|
11153
|
+
if (!placementOwner.placement.descriptor) {
|
|
11154
|
+
delete placementOwner.placement.descriptor;
|
|
9608
11155
|
}
|
|
9609
11156
|
return next;
|
|
9610
11157
|
}
|
|
9611
|
-
|
|
9612
|
-
delete
|
|
11158
|
+
placementOwner.placement.distance = distanceMetricToUnitValue(metric, preferredUnit);
|
|
11159
|
+
delete placementOwner.placement.descriptor;
|
|
9613
11160
|
return next;
|
|
9614
11161
|
}
|
|
9615
11162
|
function findNearestSceneObject(scene, selectedObjectId, pointer, predicate = () => true) {
|
|
@@ -9881,9 +11428,85 @@ var WorldOrbit = (() => {
|
|
|
9881
11428
|
return ["viewpoint-zoom"];
|
|
9882
11429
|
case "rotationDeg":
|
|
9883
11430
|
return ["viewpoint-rotation"];
|
|
11431
|
+
case "camera":
|
|
11432
|
+
return [
|
|
11433
|
+
"viewpoint-camera-azimuth",
|
|
11434
|
+
"viewpoint-camera-elevation",
|
|
11435
|
+
"viewpoint-camera-roll",
|
|
11436
|
+
"viewpoint-camera-distance"
|
|
11437
|
+
];
|
|
11438
|
+
case "camera.azimuth":
|
|
11439
|
+
return ["viewpoint-camera-azimuth"];
|
|
11440
|
+
case "camera.elevation":
|
|
11441
|
+
return ["viewpoint-camera-elevation"];
|
|
11442
|
+
case "camera.roll":
|
|
11443
|
+
return ["viewpoint-camera-roll"];
|
|
11444
|
+
case "camera.distance":
|
|
11445
|
+
return ["viewpoint-camera-distance"];
|
|
11446
|
+
case "events":
|
|
11447
|
+
return ["viewpoint-events"];
|
|
11448
|
+
default:
|
|
11449
|
+
return [];
|
|
11450
|
+
}
|
|
11451
|
+
case "event":
|
|
11452
|
+
switch (field) {
|
|
11453
|
+
case "id":
|
|
11454
|
+
return ["event-id"];
|
|
11455
|
+
case "kind":
|
|
11456
|
+
return ["event-kind"];
|
|
11457
|
+
case "label":
|
|
11458
|
+
return ["event-label"];
|
|
11459
|
+
case "summary":
|
|
11460
|
+
return ["event-summary"];
|
|
11461
|
+
case "targetObjectId":
|
|
11462
|
+
case "target":
|
|
11463
|
+
return ["event-target"];
|
|
11464
|
+
case "participantObjectIds":
|
|
11465
|
+
case "participants":
|
|
11466
|
+
return ["event-participants"];
|
|
11467
|
+
case "timing":
|
|
11468
|
+
return ["event-timing"];
|
|
11469
|
+
case "visibility":
|
|
11470
|
+
return ["event-visibility"];
|
|
11471
|
+
case "epoch":
|
|
11472
|
+
return ["event-epoch"];
|
|
11473
|
+
case "referencePlane":
|
|
11474
|
+
return ["event-referencePlane"];
|
|
11475
|
+
case "tags":
|
|
11476
|
+
return ["event-tags"];
|
|
11477
|
+
case "color":
|
|
11478
|
+
return ["event-color"];
|
|
11479
|
+
case "hidden":
|
|
11480
|
+
return ["event-hidden"];
|
|
9884
11481
|
default:
|
|
9885
11482
|
return [];
|
|
9886
11483
|
}
|
|
11484
|
+
case "event-pose":
|
|
11485
|
+
if (field === "objectId") {
|
|
11486
|
+
return ["pose-object-id"];
|
|
11487
|
+
}
|
|
11488
|
+
if (field === "placement") {
|
|
11489
|
+
return ["placement-mode"];
|
|
11490
|
+
}
|
|
11491
|
+
if (field === "reference" || field === "target") {
|
|
11492
|
+
return ["placement-target"];
|
|
11493
|
+
}
|
|
11494
|
+
if (field === "descriptor") {
|
|
11495
|
+
return ["placement-free"];
|
|
11496
|
+
}
|
|
11497
|
+
if (PLACEMENT_DIAGNOSTIC_FIELDS.has(field)) {
|
|
11498
|
+
return [`placement-${field}`];
|
|
11499
|
+
}
|
|
11500
|
+
if (field === "inner" || field === "outer") {
|
|
11501
|
+
return [`prop-${field}`];
|
|
11502
|
+
}
|
|
11503
|
+
if (field === "epoch") {
|
|
11504
|
+
return ["pose-epoch"];
|
|
11505
|
+
}
|
|
11506
|
+
if (field === "referencePlane") {
|
|
11507
|
+
return ["pose-referencePlane"];
|
|
11508
|
+
}
|
|
11509
|
+
return [];
|
|
9887
11510
|
case "annotation":
|
|
9888
11511
|
switch (field) {
|
|
9889
11512
|
case "id":
|
|
@@ -9969,6 +11592,10 @@ var WorldOrbit = (() => {
|
|
|
9969
11592
|
return `Metadata: ${path.key ?? ""}`;
|
|
9970
11593
|
case "group":
|
|
9971
11594
|
return `Group: ${path.id ?? ""}`;
|
|
11595
|
+
case "event":
|
|
11596
|
+
return `Event: ${path.id ?? ""}`;
|
|
11597
|
+
case "event-pose":
|
|
11598
|
+
return `Event Pose: ${path.id ?? ""} / ${path.key ?? ""}`;
|
|
9972
11599
|
case "object":
|
|
9973
11600
|
return `Object: ${path.id ?? ""}`;
|
|
9974
11601
|
case "viewpoint":
|
|
@@ -9980,11 +11607,70 @@ var WorldOrbit = (() => {
|
|
|
9980
11607
|
}
|
|
9981
11608
|
}
|
|
9982
11609
|
function selectionKey(path) {
|
|
9983
|
-
return path ? `${path.kind}:${path.id ?? path.key ?? ""}` : null;
|
|
11610
|
+
return path ? `${path.kind}:${path.id ?? ""}:${path.key ?? ""}` : null;
|
|
11611
|
+
}
|
|
11612
|
+
function selectionEventId(path) {
|
|
11613
|
+
if (!path) {
|
|
11614
|
+
return null;
|
|
11615
|
+
}
|
|
11616
|
+
return path.kind === "event" || path.kind === "event-pose" ? path.id ?? null : null;
|
|
9984
11617
|
}
|
|
9985
11618
|
function compareObjects2(left, right) {
|
|
9986
11619
|
return left.id.localeCompare(right.id);
|
|
9987
11620
|
}
|
|
11621
|
+
function compareEvents(left, right) {
|
|
11622
|
+
return left.id.localeCompare(right.id);
|
|
11623
|
+
}
|
|
11624
|
+
function compareEventPoses(left, right) {
|
|
11625
|
+
return left.objectId.localeCompare(right.objectId);
|
|
11626
|
+
}
|
|
11627
|
+
function findEvent2(document2, eventId) {
|
|
11628
|
+
return document2.events.find((entry) => entry.id === eventId) ?? null;
|
|
11629
|
+
}
|
|
11630
|
+
function findEventPose2(document2, eventId, objectId) {
|
|
11631
|
+
return findEvent2(document2, eventId)?.positions.find((entry) => entry.objectId === objectId) ?? null;
|
|
11632
|
+
}
|
|
11633
|
+
function findObject2(document2, objectId) {
|
|
11634
|
+
return document2.objects.find((entry) => entry.id === objectId) ?? null;
|
|
11635
|
+
}
|
|
11636
|
+
function addEventPose(document2, eventId) {
|
|
11637
|
+
const next = cloneAtlasDocument(document2);
|
|
11638
|
+
const eventEntry = next.events.find((entry) => entry.id === eventId);
|
|
11639
|
+
if (!eventEntry) {
|
|
11640
|
+
return document2;
|
|
11641
|
+
}
|
|
11642
|
+
const baseObject = next.objects.find((object) => !eventEntry.positions.some((pose) => pose.objectId === object.id)) ?? next.objects[0];
|
|
11643
|
+
if (!baseObject) {
|
|
11644
|
+
return document2;
|
|
11645
|
+
}
|
|
11646
|
+
if (eventEntry.targetObjectId !== baseObject.id && !eventEntry.participantObjectIds.includes(baseObject.id)) {
|
|
11647
|
+
eventEntry.participantObjectIds.push(baseObject.id);
|
|
11648
|
+
eventEntry.participantObjectIds.sort((left, right) => left.localeCompare(right));
|
|
11649
|
+
}
|
|
11650
|
+
eventEntry.positions.push(createEventPoseFromObject(baseObject));
|
|
11651
|
+
eventEntry.positions.sort(compareEventPoses);
|
|
11652
|
+
return next;
|
|
11653
|
+
}
|
|
11654
|
+
function createEventPoseFromObject(object) {
|
|
11655
|
+
return {
|
|
11656
|
+
objectId: object.id,
|
|
11657
|
+
placement: object.placement ? structuredClone(object.placement) : null,
|
|
11658
|
+
inner: readUnitValue(object.properties.inner),
|
|
11659
|
+
outer: readUnitValue(object.properties.outer)
|
|
11660
|
+
};
|
|
11661
|
+
}
|
|
11662
|
+
function syncEventViewpointReferences(document2, previousEventId, nextEventId, viewpointIds) {
|
|
11663
|
+
const desired = new Set(viewpointIds);
|
|
11664
|
+
for (const viewpoint of document2.system?.viewpoints ?? []) {
|
|
11665
|
+
const currentIds = new Set(viewpoint.events);
|
|
11666
|
+
currentIds.delete(previousEventId);
|
|
11667
|
+
currentIds.delete(nextEventId);
|
|
11668
|
+
if (desired.has(viewpoint.id)) {
|
|
11669
|
+
currentIds.add(nextEventId);
|
|
11670
|
+
}
|
|
11671
|
+
viewpoint.events = [...currentIds].sort((left, right) => left.localeCompare(right));
|
|
11672
|
+
}
|
|
11673
|
+
}
|
|
9988
11674
|
function createUniqueId(prefix, existing) {
|
|
9989
11675
|
const safePrefix = prefix.trim() || "item";
|
|
9990
11676
|
let counter = 1;
|
|
@@ -10013,6 +11699,9 @@ var WorldOrbit = (() => {
|
|
|
10013
11699
|
function readUnitProperty(value) {
|
|
10014
11700
|
return value && typeof value === "object" && "value" in value ? formatUnitValue3(value) : "";
|
|
10015
11701
|
}
|
|
11702
|
+
function readUnitValue(value) {
|
|
11703
|
+
return value && typeof value === "object" && "value" in value ? value : void 0;
|
|
11704
|
+
}
|
|
10016
11705
|
function readNumberProperty(value) {
|
|
10017
11706
|
return typeof value === "number" ? String(value) : "";
|
|
10018
11707
|
}
|
|
@@ -10318,6 +12007,12 @@ var WorldOrbit = (() => {
|
|
|
10318
12007
|
.wo-editor-overlay-diagnostic-warning { border: 1px solid rgba(240, 180, 100, 0.24); }
|
|
10319
12008
|
.wo-editor-outline { display: grid; gap: 14px; }
|
|
10320
12009
|
.wo-editor-outline-section { display: grid; gap: 8px; }
|
|
12010
|
+
.wo-editor-outline-group { display: grid; gap: 6px; }
|
|
12011
|
+
.wo-editor-outline-children {
|
|
12012
|
+
display: grid;
|
|
12013
|
+
gap: 6px;
|
|
12014
|
+
padding-left: 16px;
|
|
12015
|
+
}
|
|
10321
12016
|
.wo-editor-outline-section h3 {
|
|
10322
12017
|
margin: 0;
|
|
10323
12018
|
color: rgba(237,246,255,0.68);
|
|
@@ -10357,6 +12052,27 @@ var WorldOrbit = (() => {
|
|
|
10357
12052
|
background: rgba(255, 120, 120, 0.18);
|
|
10358
12053
|
color: #ffb2b2;
|
|
10359
12054
|
}
|
|
12055
|
+
.wo-editor-inline-list { display: grid; gap: 8px; }
|
|
12056
|
+
.wo-editor-inline-actions {
|
|
12057
|
+
display: flex;
|
|
12058
|
+
flex-wrap: wrap;
|
|
12059
|
+
gap: 10px;
|
|
12060
|
+
margin-top: 12px;
|
|
12061
|
+
}
|
|
12062
|
+
.wo-editor-inline-actions button {
|
|
12063
|
+
border: 1px solid rgba(255,255,255,0.14);
|
|
12064
|
+
border-radius: 999px;
|
|
12065
|
+
background: rgba(255,255,255,0.06);
|
|
12066
|
+
color: #edf6ff;
|
|
12067
|
+
cursor: pointer;
|
|
12068
|
+
font: 600 12px/1.2 "Segoe UI Variable", "Segoe UI", sans-serif;
|
|
12069
|
+
padding: 8px 12px;
|
|
12070
|
+
}
|
|
12071
|
+
.wo-editor-inline-note {
|
|
12072
|
+
margin: 0 0 12px;
|
|
12073
|
+
color: rgba(237,246,255,0.72);
|
|
12074
|
+
font: 500 12px/1.5 "Segoe UI Variable", "Segoe UI", sans-serif;
|
|
12075
|
+
}
|
|
10360
12076
|
.wo-editor-diagnostics { display: grid; gap: 10px; }
|
|
10361
12077
|
.wo-editor-diagnostic {
|
|
10362
12078
|
display: grid;
|