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.
Files changed (35) hide show
  1. package/README.md +81 -15
  2. package/dist/browser/core/dist/index.js +1228 -110
  3. package/dist/browser/editor/dist/index.js +1896 -180
  4. package/dist/browser/markdown/dist/index.js +1071 -99
  5. package/dist/browser/viewer/dist/index.js +1127 -113
  6. package/dist/unpkg/core/dist/index.js +1228 -110
  7. package/dist/unpkg/editor/dist/index.js +1896 -180
  8. package/dist/unpkg/markdown/dist/index.js +1071 -99
  9. package/dist/unpkg/viewer/dist/index.js +1127 -113
  10. package/dist/unpkg/worldorbit-core.min.js +12 -12
  11. package/dist/unpkg/worldorbit-editor.min.js +295 -203
  12. package/dist/unpkg/worldorbit-markdown.min.js +66 -58
  13. package/dist/unpkg/worldorbit-viewer.min.js +84 -76
  14. package/dist/unpkg/worldorbit.js +1304 -124
  15. package/dist/unpkg/worldorbit.min.js +88 -80
  16. package/package.json +1 -1
  17. package/packages/core/dist/atlas-edit.js +75 -1
  18. package/packages/core/dist/atlas-validate.js +211 -8
  19. package/packages/core/dist/draft-parse.js +401 -22
  20. package/packages/core/dist/draft.d.ts +5 -2
  21. package/packages/core/dist/draft.js +103 -8
  22. package/packages/core/dist/format.js +99 -6
  23. package/packages/core/dist/load.js +9 -2
  24. package/packages/core/dist/normalize.js +1 -0
  25. package/packages/core/dist/scene.js +400 -64
  26. package/packages/core/dist/types.d.ts +60 -4
  27. package/packages/editor/dist/editor.js +702 -65
  28. package/packages/editor/dist/types.d.ts +3 -1
  29. package/packages/viewer/dist/atlas-state.js +11 -2
  30. package/packages/viewer/dist/atlas-viewer.js +19 -7
  31. package/packages/viewer/dist/render.js +31 -2
  32. package/packages/viewer/dist/theme.js +1 -0
  33. package/packages/viewer/dist/tooltip.js +9 -0
  34. package/packages/viewer/dist/types.d.ts +12 -2
  35. package/packages/viewer/dist/viewer.js +28 -1
@@ -18,12 +18,13 @@ export function upgradeDocumentToV2(document, options = {}) {
18
18
  }
19
19
  return {
20
20
  format: "worldorbit",
21
- version: "2.0",
22
- schemaVersion: "2.0",
21
+ version: "2.5",
22
+ schemaVersion: "2.5",
23
23
  sourceVersion: document.version,
24
24
  system,
25
25
  groups: structuredClone(document.groups ?? []),
26
26
  relations: structuredClone(document.relations ?? []),
27
+ events: structuredClone(document.events ?? []),
27
28
  objects: document.objects.map(cloneWorldOrbitObject),
28
29
  diagnostics,
29
30
  };
@@ -31,7 +32,7 @@ export function upgradeDocumentToV2(document, options = {}) {
31
32
  export function upgradeDocumentToDraftV2(document, options = {}) {
32
33
  return convertAtlasDocumentToLegacyDraft(upgradeDocumentToV2(document, options));
33
34
  }
34
- export function materializeAtlasDocument(document) {
35
+ export function materializeAtlasDocument(document, options = {}) {
35
36
  const system = document.system
36
37
  ? {
37
38
  type: "system",
@@ -44,6 +45,8 @@ export function materializeAtlasDocument(document) {
44
45
  info: materializeDraftSystemInfo(document.system),
45
46
  }
46
47
  : null;
48
+ const objects = document.objects.map(cloneWorldOrbitObject);
49
+ applyEventPoseOverrides(objects, document.events ?? [], options.activeEventId ?? null);
47
50
  return {
48
51
  format: "worldorbit",
49
52
  version: "1.0",
@@ -51,7 +54,8 @@ export function materializeAtlasDocument(document) {
51
54
  system,
52
55
  groups: structuredClone(document.groups ?? []),
53
56
  relations: structuredClone(document.relations ?? []),
54
- objects: document.objects.map(cloneWorldOrbitObject),
57
+ events: document.events.map(cloneWorldOrbitEvent),
58
+ objects,
55
59
  };
56
60
  }
57
61
  export function materializeDraftDocument(document) {
@@ -78,10 +82,15 @@ function createDraftSystem(document, defaults, atlasMetadata, annotations, diagn
78
82
  };
79
83
  }
80
84
  function createDraftDefaults(document, preset, projection) {
85
+ const rawView = typeof document.system?.properties.view === "string"
86
+ ? document.system.properties.view.toLowerCase()
87
+ : null;
81
88
  return {
82
- view: typeof document.system?.properties.view === "string" &&
83
- document.system.properties.view.toLowerCase() === "topdown"
84
- ? "topdown"
89
+ view: rawView === "topdown" ||
90
+ rawView === "isometric" ||
91
+ rawView === "orthographic" ||
92
+ rawView === "perspective"
93
+ ? rawView
85
94
  : projection,
86
95
  scale: typeof document.system?.properties.scale === "string"
87
96
  ? document.system.properties.scale
@@ -195,10 +204,12 @@ function mapSceneViewpointToDraftViewpoint(viewpoint) {
195
204
  summary: viewpoint.summary,
196
205
  focusObjectId: viewpoint.objectId,
197
206
  selectedObjectId: viewpoint.selectedObjectId,
207
+ events: [...viewpoint.eventIds],
198
208
  projection: viewpoint.projection,
199
209
  preset: viewpoint.preset,
200
210
  zoom: viewpoint.scale,
201
211
  rotationDeg: viewpoint.rotationDeg,
212
+ camera: viewpoint.camera ? { ...viewpoint.camera } : null,
202
213
  layers: { ...viewpoint.layers },
203
214
  filter: viewpoint.filter
204
215
  ? {
@@ -239,6 +250,75 @@ function cloneWorldOrbitObject(object) {
239
250
  info: { ...object.info },
240
251
  };
241
252
  }
253
+ function cloneWorldOrbitEvent(event) {
254
+ return {
255
+ ...event,
256
+ participantObjectIds: [...event.participantObjectIds],
257
+ tags: [...event.tags],
258
+ positions: event.positions.map(cloneWorldOrbitEventPose),
259
+ };
260
+ }
261
+ function cloneWorldOrbitEventPose(pose) {
262
+ return {
263
+ objectId: pose.objectId,
264
+ placement: clonePlacement(pose.placement),
265
+ inner: pose.inner ? { ...pose.inner } : undefined,
266
+ outer: pose.outer ? { ...pose.outer } : undefined,
267
+ epoch: pose.epoch ?? null,
268
+ referencePlane: pose.referencePlane ?? null,
269
+ };
270
+ }
271
+ function clonePlacement(placement) {
272
+ return placement ? structuredClone(placement) : null;
273
+ }
274
+ function applyEventPoseOverrides(objects, events, activeEventId) {
275
+ if (!activeEventId) {
276
+ return;
277
+ }
278
+ const event = events.find((entry) => entry.id === activeEventId);
279
+ if (!event) {
280
+ return;
281
+ }
282
+ const objectMap = new Map(objects.map((object) => [object.id, object]));
283
+ const referencedIds = new Set([
284
+ ...(event.targetObjectId ? [event.targetObjectId] : []),
285
+ ...event.participantObjectIds,
286
+ ...event.positions.map((pose) => pose.objectId),
287
+ ]);
288
+ for (const objectId of referencedIds) {
289
+ const object = objectMap.get(objectId);
290
+ if (!object) {
291
+ continue;
292
+ }
293
+ if (event.epoch) {
294
+ object.epoch = event.epoch;
295
+ }
296
+ if (event.referencePlane) {
297
+ object.referencePlane = event.referencePlane;
298
+ }
299
+ }
300
+ for (const pose of event.positions) {
301
+ const object = objectMap.get(pose.objectId);
302
+ if (!object) {
303
+ continue;
304
+ }
305
+ if (pose.placement) {
306
+ object.placement = clonePlacement(pose.placement);
307
+ }
308
+ if (pose.inner) {
309
+ object.properties.inner = { ...pose.inner };
310
+ }
311
+ if (pose.outer) {
312
+ object.properties.outer = { ...pose.outer };
313
+ }
314
+ if (pose.epoch) {
315
+ object.epoch = pose.epoch;
316
+ }
317
+ if (pose.referencePlane) {
318
+ object.referencePlane = pose.referencePlane;
319
+ }
320
+ }
321
+ }
242
322
  function cloneProperties(properties) {
243
323
  const next = {};
244
324
  for (const [key, value] of Object.entries(properties)) {
@@ -331,6 +411,18 @@ function materializeDraftSystemInfo(system) {
331
411
  if (viewpoint.rotationDeg !== 0) {
332
412
  info[`${prefix}.rotation`] = String(viewpoint.rotationDeg);
333
413
  }
414
+ if (viewpoint.camera?.azimuth !== null) {
415
+ info[`${prefix}.camera.azimuth`] = String(viewpoint.camera?.azimuth);
416
+ }
417
+ if (viewpoint.camera?.elevation !== null) {
418
+ info[`${prefix}.camera.elevation`] = String(viewpoint.camera?.elevation);
419
+ }
420
+ if (viewpoint.camera?.roll !== null) {
421
+ info[`${prefix}.camera.roll`] = String(viewpoint.camera?.roll);
422
+ }
423
+ if (viewpoint.camera?.distance !== null) {
424
+ info[`${prefix}.camera.distance`] = String(viewpoint.camera?.distance);
425
+ }
334
426
  const serializedLayers = serializeViewpointLayers(viewpoint.layers);
335
427
  if (serializedLayers) {
336
428
  info[`${prefix}.layers`] = serializedLayers;
@@ -347,6 +439,9 @@ function materializeDraftSystemInfo(system) {
347
439
  if ((viewpoint.filter?.groupIds.length ?? 0) > 0) {
348
440
  info[`${prefix}.groups`] = viewpoint.filter?.groupIds.join(" ") ?? "";
349
441
  }
442
+ if (viewpoint.events.length > 0) {
443
+ info[`${prefix}.events`] = viewpoint.events.join(" ");
444
+ }
350
445
  }
351
446
  for (const annotation of system.annotations) {
352
447
  const prefix = `annotation.${annotation.id}`;
@@ -371,7 +466,7 @@ function serializeViewpointLayers(layers) {
371
466
  if (orbitFront !== undefined || orbitBack !== undefined) {
372
467
  tokens.push(orbitFront !== false || orbitBack !== false ? "orbits" : "-orbits");
373
468
  }
374
- for (const key of ["background", "guides", "relations", "objects", "labels", "metadata"]) {
469
+ for (const key of ["background", "guides", "relations", "events", "objects", "labels", "metadata"]) {
375
470
  if (layers[key] !== undefined) {
376
471
  tokens.push(layers[key] ? key : `-${key}`);
377
472
  }
@@ -38,15 +38,17 @@ export function formatDocument(document, options = {}) {
38
38
  const schema = options.schema ?? "auto";
39
39
  const useDraft = schema === "2.0" ||
40
40
  schema === "2.1" ||
41
+ schema === "2.5" ||
41
42
  schema === "2.0-draft" ||
42
43
  document.version === "2.0" ||
43
44
  document.version === "2.1" ||
45
+ document.version === "2.5" ||
44
46
  document.version === "2.0-draft";
45
47
  if (useDraft) {
46
48
  if (schema === "2.0-draft") {
47
49
  const legacyDraftDocument = document.version === "2.0-draft"
48
50
  ? document
49
- : document.version === "2.0" || document.version === "2.1"
51
+ : document.version === "2.0" || document.version === "2.1" || document.version === "2.5"
50
52
  ? {
51
53
  ...document,
52
54
  version: "2.0-draft",
@@ -55,7 +57,7 @@ export function formatDocument(document, options = {}) {
55
57
  : upgradeDocumentToDraftV2(document);
56
58
  return formatDraftDocument(legacyDraftDocument);
57
59
  }
58
- const atlasDocument = document.version === "2.0" || document.version === "2.1"
60
+ const atlasDocument = document.version === "2.0" || document.version === "2.1" || document.version === "2.5"
59
61
  ? document
60
62
  : document.version === "2.0-draft"
61
63
  ? {
@@ -64,11 +66,11 @@ export function formatDocument(document, options = {}) {
64
66
  schemaVersion: "2.0",
65
67
  }
66
68
  : upgradeDocumentToV2(document);
67
- if (schema === "2.1" && atlasDocument.version !== "2.1") {
69
+ if ((schema === "2.0" || schema === "2.1" || schema === "2.5") && atlasDocument.version !== schema) {
68
70
  return formatAtlasDocument({
69
71
  ...atlasDocument,
70
- version: "2.1",
71
- schemaVersion: "2.1",
72
+ version: schema,
73
+ schemaVersion: schema,
72
74
  });
73
75
  }
74
76
  return formatAtlasDocument(atlasDocument);
@@ -100,6 +102,10 @@ export function formatAtlasDocument(document) {
100
102
  lines.push("");
101
103
  lines.push(...formatAtlasRelation(relation));
102
104
  }
105
+ for (const event of [...document.events].sort(compareIdLike)) {
106
+ lines.push("");
107
+ lines.push(...formatAtlasEvent(event));
108
+ }
103
109
  const sortedObjects = [...document.objects].sort(compareObjects);
104
110
  if (sortedObjects.length > 0 && lines.at(-1) !== "") {
105
111
  lines.push("");
@@ -132,6 +138,10 @@ export function formatDraftDocument(document) {
132
138
  lines.push("");
133
139
  lines.push(...formatAtlasRelation(relation));
134
140
  }
141
+ for (const event of [...legacy.events].sort(compareIdLike)) {
142
+ lines.push("");
143
+ lines.push(...formatAtlasEvent(event));
144
+ }
135
145
  const sortedObjects = [...legacy.objects].sort(compareObjects);
136
146
  if (sortedObjects.length > 0 && lines.at(-1) !== "") {
137
147
  lines.push("");
@@ -341,10 +351,28 @@ function formatAtlasViewpoint(viewpoint) {
341
351
  if (viewpoint.rotationDeg !== 0) {
342
352
  lines.push(` rotation ${viewpoint.rotationDeg}`);
343
353
  }
354
+ if (viewpoint.camera && hasCameraValues(viewpoint.camera)) {
355
+ lines.push(" camera");
356
+ if (viewpoint.camera.azimuth !== null) {
357
+ lines.push(` azimuth ${viewpoint.camera.azimuth}`);
358
+ }
359
+ if (viewpoint.camera.elevation !== null) {
360
+ lines.push(` elevation ${viewpoint.camera.elevation}`);
361
+ }
362
+ if (viewpoint.camera.roll !== null) {
363
+ lines.push(` roll ${viewpoint.camera.roll}`);
364
+ }
365
+ if (viewpoint.camera.distance !== null) {
366
+ lines.push(` distance ${viewpoint.camera.distance}`);
367
+ }
368
+ }
344
369
  const layerTokens = formatDraftLayers(viewpoint.layers);
345
370
  if (layerTokens.length > 0) {
346
371
  lines.push(` layers ${layerTokens.join(" ")}`);
347
372
  }
373
+ if (viewpoint.events.length > 0) {
374
+ lines.push(` events ${viewpoint.events.join(" ")}`);
375
+ }
348
376
  if (viewpoint.filter) {
349
377
  lines.push(" filter");
350
378
  if (viewpoint.filter.query) {
@@ -417,6 +445,68 @@ function formatAtlasRelation(relation) {
417
445
  }
418
446
  return lines;
419
447
  }
448
+ function formatAtlasEvent(event) {
449
+ const lines = [`event ${event.id}`, ` kind ${quoteIfNeeded(event.kind)}`];
450
+ if (event.label) {
451
+ lines.push(` label ${quoteIfNeeded(event.label)}`);
452
+ }
453
+ if (event.summary) {
454
+ lines.push(` summary ${quoteIfNeeded(event.summary)}`);
455
+ }
456
+ if (event.targetObjectId) {
457
+ lines.push(` target ${event.targetObjectId}`);
458
+ }
459
+ if (event.participantObjectIds.length > 0) {
460
+ lines.push(` participants ${event.participantObjectIds.join(" ")}`);
461
+ }
462
+ if (event.timing) {
463
+ lines.push(` timing ${quoteIfNeeded(event.timing)}`);
464
+ }
465
+ if (event.visibility) {
466
+ lines.push(` visibility ${quoteIfNeeded(event.visibility)}`);
467
+ }
468
+ if (event.epoch) {
469
+ lines.push(` epoch ${quoteIfNeeded(event.epoch)}`);
470
+ }
471
+ if (event.referencePlane) {
472
+ lines.push(` referencePlane ${quoteIfNeeded(event.referencePlane)}`);
473
+ }
474
+ if (event.tags.length > 0) {
475
+ lines.push(` tags ${event.tags.map(quoteIfNeeded).join(" ")}`);
476
+ }
477
+ if (event.color) {
478
+ lines.push(` color ${quoteIfNeeded(event.color)}`);
479
+ }
480
+ if (event.hidden) {
481
+ lines.push(" hidden true");
482
+ }
483
+ if (event.positions.length > 0) {
484
+ lines.push("");
485
+ lines.push(" positions");
486
+ for (const pose of [...event.positions].sort(comparePoseObjectId)) {
487
+ lines.push(` pose ${pose.objectId}`);
488
+ for (const fieldLine of formatEventPoseFields(pose)) {
489
+ lines.push(` ${fieldLine}`);
490
+ }
491
+ }
492
+ }
493
+ return lines;
494
+ }
495
+ function formatEventPoseFields(pose) {
496
+ return [
497
+ ...formatPlacement(pose.placement),
498
+ ...(pose.epoch ? [`epoch ${quoteIfNeeded(pose.epoch)}`] : []),
499
+ ...(pose.referencePlane ? [`referencePlane ${quoteIfNeeded(pose.referencePlane)}`] : []),
500
+ ...formatOptionalUnit("inner", pose.inner),
501
+ ...formatOptionalUnit("outer", pose.outer),
502
+ ];
503
+ }
504
+ function hasCameraValues(camera) {
505
+ return (camera.azimuth !== null ||
506
+ camera.elevation !== null ||
507
+ camera.roll !== null ||
508
+ camera.distance !== null);
509
+ }
420
510
  function formatValue(value) {
421
511
  if (Array.isArray(value)) {
422
512
  return value.map((item) => quoteIfNeeded(item)).join(" ");
@@ -462,7 +552,7 @@ function formatDraftLayers(layers) {
462
552
  ? "orbits"
463
553
  : "-orbits");
464
554
  }
465
- for (const key of ["background", "guides", "relations", "objects", "labels", "metadata"]) {
555
+ for (const key of ["background", "guides", "relations", "events", "objects", "labels", "metadata"]) {
466
556
  if (layers[key] !== undefined) {
467
557
  tokens.push(layers[key] ? key : `-${key}`);
468
558
  }
@@ -490,6 +580,9 @@ function compareObjects(left, right) {
490
580
  function compareIdLike(left, right) {
491
581
  return left.id.localeCompare(right.id);
492
582
  }
583
+ function comparePoseObjectId(left, right) {
584
+ return left.objectId.localeCompare(right.objectId);
585
+ }
493
586
  function objectTypeIndex(objectType) {
494
587
  switch (objectType) {
495
588
  case "star":
@@ -5,8 +5,9 @@ import { WorldOrbitError } from "./errors.js";
5
5
  import { normalizeDocument } from "./normalize.js";
6
6
  import { parseWorldOrbit } from "./parse.js";
7
7
  import { validateDocument } from "./validate.js";
8
- const ATLAS_SCHEMA_PATTERN = /^schema\s+2(?:\.0|\.1)?$/i;
8
+ const ATLAS_SCHEMA_PATTERN = /^schema\s+2(?:\.0|\.1|\.5)?$/i;
9
9
  const ATLAS_SCHEMA_21_PATTERN = /^schema\s+2\.1$/i;
10
+ const ATLAS_SCHEMA_25_PATTERN = /^schema\s+2\.5$/i;
10
11
  const LEGACY_DRAFT_SCHEMA_PATTERN = /^schema\s+2\.0-draft$/i;
11
12
  export function detectWorldOrbitSchemaVersion(source) {
12
13
  for (const line of stripCommentsForSchemaDetection(source).split(/\r?\n/)) {
@@ -20,6 +21,9 @@ export function detectWorldOrbitSchemaVersion(source) {
20
21
  if (ATLAS_SCHEMA_21_PATTERN.test(trimmed)) {
21
22
  return "2.1";
22
23
  }
24
+ if (ATLAS_SCHEMA_25_PATTERN.test(trimmed)) {
25
+ return "2.5";
26
+ }
23
27
  if (ATLAS_SCHEMA_PATTERN.test(trimmed)) {
24
28
  return "2.0";
25
29
  }
@@ -80,7 +84,10 @@ export function loadWorldOrbitSource(source) {
80
84
  }
81
85
  export function loadWorldOrbitSourceWithDiagnostics(source) {
82
86
  const schemaVersion = detectWorldOrbitSchemaVersion(source);
83
- if (schemaVersion === "2.0" || schemaVersion === "2.0-draft" || schemaVersion === "2.1") {
87
+ if (schemaVersion === "2.0" ||
88
+ schemaVersion === "2.0-draft" ||
89
+ schemaVersion === "2.1" ||
90
+ schemaVersion === "2.5") {
84
91
  return loadAtlasSourceWithDiagnostics(source, schemaVersion);
85
92
  }
86
93
  let ast;
@@ -30,6 +30,7 @@ export function normalizeDocument(ast) {
30
30
  system,
31
31
  groups: [],
32
32
  relations: [],
33
+ events: [],
33
34
  objects,
34
35
  };
35
36
  }