worldorbit 3.2.0 → 3.2.2

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 (103) hide show
  1. package/dist/browser/core/dist/scene.js +98 -16
  2. package/dist/browser/core/dist/spatial-scene.js +1 -0
  3. package/dist/browser/core/dist/types.d.ts +3 -0
  4. package/dist/browser/editor/dist/editor.js +55 -12
  5. package/dist/browser/obsidian-plugin/dist/diagnostics.d.ts +3 -0
  6. package/dist/browser/obsidian-plugin/dist/diagnostics.js +23 -0
  7. package/dist/browser/obsidian-plugin/dist/examples.d.ts +3 -0
  8. package/dist/browser/obsidian-plugin/dist/examples.js +77 -0
  9. package/dist/browser/obsidian-plugin/dist/index.d.ts +9 -0
  10. package/dist/browser/obsidian-plugin/dist/index.js +8 -0
  11. package/dist/browser/obsidian-plugin/dist/main.d.ts +2 -0
  12. package/dist/browser/obsidian-plugin/dist/main.js +2 -0
  13. package/dist/browser/obsidian-plugin/dist/navigation.d.ts +6 -0
  14. package/dist/browser/obsidian-plugin/dist/navigation.js +44 -0
  15. package/dist/browser/obsidian-plugin/dist/plugin.d.ts +8 -0
  16. package/dist/browser/obsidian-plugin/dist/plugin.js +508 -0
  17. package/dist/browser/obsidian-plugin/dist/positions.d.ts +7 -0
  18. package/dist/browser/obsidian-plugin/dist/positions.js +14 -0
  19. package/dist/browser/obsidian-plugin/dist/settings.d.ts +2 -0
  20. package/dist/browser/obsidian-plugin/dist/settings.js +5 -0
  21. package/dist/browser/obsidian-plugin/dist/theme.d.ts +2 -0
  22. package/dist/browser/obsidian-plugin/dist/theme.js +31 -0
  23. package/dist/browser/obsidian-plugin/dist/types.d.ts +42 -0
  24. package/dist/browser/obsidian-plugin/dist/types.js +1 -0
  25. package/dist/browser/obsidian-plugin/dist/viewer-host.d.ts +14 -0
  26. package/dist/browser/obsidian-plugin/dist/viewer-host.js +110 -0
  27. package/dist/browser/viewer/dist/atlas-state.js +3 -0
  28. package/dist/browser/viewer/dist/index.d.ts +1 -0
  29. package/dist/browser/viewer/dist/index.js +1 -0
  30. package/dist/browser/viewer/dist/interactive-2d.d.ts +21 -0
  31. package/dist/browser/viewer/dist/interactive-2d.js +201 -0
  32. package/dist/browser/viewer/dist/render.d.ts +1 -1
  33. package/dist/browser/viewer/dist/render.js +2 -1
  34. package/dist/browser/viewer/dist/types.d.ts +1 -0
  35. package/dist/browser/viewer/dist/viewer-state.d.ts +1 -1
  36. package/dist/browser/viewer/dist/viewer-state.js +1 -1
  37. package/dist/browser/viewer/dist/viewer.js +2 -0
  38. package/dist/obsidian-plugin/LICENSE +21 -0
  39. package/dist/obsidian-plugin/README.md +124 -0
  40. package/dist/obsidian-plugin/main.js +108 -0
  41. package/dist/obsidian-plugin/manifest.json +9 -0
  42. package/dist/obsidian-plugin/obsidian_scsh_1.png +0 -0
  43. package/dist/obsidian-plugin/obsidian_scsh_2.png +0 -0
  44. package/dist/obsidian-plugin/styles.css +164 -0
  45. package/dist/unpkg/core/dist/scene.js +98 -16
  46. package/dist/unpkg/core/dist/spatial-scene.js +1 -0
  47. package/dist/unpkg/core/dist/types.d.ts +3 -0
  48. package/dist/unpkg/editor/dist/editor.js +55 -12
  49. package/dist/unpkg/obsidian-plugin/dist/diagnostics.d.ts +3 -0
  50. package/dist/unpkg/obsidian-plugin/dist/diagnostics.js +23 -0
  51. package/dist/unpkg/obsidian-plugin/dist/examples.d.ts +3 -0
  52. package/dist/unpkg/obsidian-plugin/dist/examples.js +77 -0
  53. package/dist/unpkg/obsidian-plugin/dist/index.d.ts +9 -0
  54. package/dist/unpkg/obsidian-plugin/dist/index.js +8 -0
  55. package/dist/unpkg/obsidian-plugin/dist/main.d.ts +2 -0
  56. package/dist/unpkg/obsidian-plugin/dist/main.js +2 -0
  57. package/dist/unpkg/obsidian-plugin/dist/navigation.d.ts +6 -0
  58. package/dist/unpkg/obsidian-plugin/dist/navigation.js +44 -0
  59. package/dist/unpkg/obsidian-plugin/dist/plugin.d.ts +8 -0
  60. package/dist/unpkg/obsidian-plugin/dist/plugin.js +508 -0
  61. package/dist/unpkg/obsidian-plugin/dist/positions.d.ts +7 -0
  62. package/dist/unpkg/obsidian-plugin/dist/positions.js +14 -0
  63. package/dist/unpkg/obsidian-plugin/dist/settings.d.ts +2 -0
  64. package/dist/unpkg/obsidian-plugin/dist/settings.js +5 -0
  65. package/dist/unpkg/obsidian-plugin/dist/theme.d.ts +2 -0
  66. package/dist/unpkg/obsidian-plugin/dist/theme.js +31 -0
  67. package/dist/unpkg/obsidian-plugin/dist/types.d.ts +42 -0
  68. package/dist/unpkg/obsidian-plugin/dist/types.js +1 -0
  69. package/dist/unpkg/obsidian-plugin/dist/viewer-host.d.ts +14 -0
  70. package/dist/unpkg/obsidian-plugin/dist/viewer-host.js +110 -0
  71. package/dist/unpkg/viewer/dist/atlas-state.js +3 -0
  72. package/dist/unpkg/viewer/dist/index.d.ts +1 -0
  73. package/dist/unpkg/viewer/dist/index.js +1 -0
  74. package/dist/unpkg/viewer/dist/interactive-2d.d.ts +21 -0
  75. package/dist/unpkg/viewer/dist/interactive-2d.js +201 -0
  76. package/dist/unpkg/viewer/dist/render.d.ts +1 -1
  77. package/dist/unpkg/viewer/dist/render.js +2 -1
  78. package/dist/unpkg/viewer/dist/types.d.ts +1 -0
  79. package/dist/unpkg/viewer/dist/viewer-state.d.ts +1 -1
  80. package/dist/unpkg/viewer/dist/viewer-state.js +1 -1
  81. package/dist/unpkg/viewer/dist/viewer.js +2 -0
  82. package/dist/unpkg/worldorbit-core.min.js +12 -12
  83. package/dist/unpkg/worldorbit-editor.min.js +342 -342
  84. package/dist/unpkg/worldorbit-markdown.min.js +23 -23
  85. package/dist/unpkg/worldorbit-viewer.min.js +197 -197
  86. package/dist/unpkg/worldorbit.js +297 -21
  87. package/dist/unpkg/worldorbit.min.js +201 -201
  88. package/package.json +18 -1
  89. package/packages/core/dist/scene.js +98 -16
  90. package/packages/core/dist/spatial-scene.js +1 -0
  91. package/packages/core/dist/types.d.ts +3 -0
  92. package/packages/editor/dist/editor.js +55 -12
  93. package/packages/viewer/dist/atlas-state.js +3 -0
  94. package/packages/viewer/dist/index.d.ts +1 -0
  95. package/packages/viewer/dist/index.js +1 -0
  96. package/packages/viewer/dist/interactive-2d.d.ts +21 -0
  97. package/packages/viewer/dist/interactive-2d.js +201 -0
  98. package/packages/viewer/dist/render.d.ts +1 -1
  99. package/packages/viewer/dist/render.js +2 -1
  100. package/packages/viewer/dist/types.d.ts +1 -0
  101. package/packages/viewer/dist/viewer-state.d.ts +1 -1
  102. package/packages/viewer/dist/viewer-state.js +1 -1
  103. package/packages/viewer/dist/viewer.js +2 -0
@@ -30712,6 +30712,7 @@ void main() {
30712
30712
  createEmbedPayload: () => createEmbedPayload,
30713
30713
  createEmptyAtlasDocument: () => createEmptyAtlasDocument,
30714
30714
  createInteractiveViewer: () => createInteractiveViewer,
30715
+ createInteractiveViewer2D: () => createInteractiveViewer2D,
30715
30716
  createWorldOrbitEmbedMarkup: () => createWorldOrbitEmbedMarkup,
30716
30717
  defineWorldOrbitViewerElement: () => defineWorldOrbitViewerElement,
30717
30718
  deserializeViewerAtlasState: () => deserializeViewerAtlasState,
@@ -31873,11 +31874,12 @@ void main() {
31873
31874
  const schemaProjection = resolveProjection(document2, options.projection);
31874
31875
  const camera = normalizeViewCamera(options.camera ?? null);
31875
31876
  const renderProjection = resolveRenderProjection(schemaProjection, camera);
31876
- const scaleModel = resolveScaleModel(layoutPreset, options.scaleModel);
31877
31877
  const spacingFactor = layoutPresetSpacing(layoutPreset);
31878
+ const scaleModel = resolveScaleModel(layoutPreset, options.scaleModel, options.bodyScaleMode);
31878
31879
  const systemId = document2.system?.id ?? null;
31879
31880
  const activeEventId = options.activeEventId ?? null;
31880
31881
  const effectiveObjects = createEffectiveObjects(document2.objects, document2.events ?? [], activeEventId);
31882
+ const sceneMetricScale = resolveSceneMetricScale(effectiveObjects, width, height, padding, spacingFactor, scaleModel);
31881
31883
  const objectMap = new Map(effectiveObjects.map((object) => [object.id, object]));
31882
31884
  const relationships = buildSceneRelationships(effectiveObjects, objectMap);
31883
31885
  const positions = /* @__PURE__ */ new Map();
@@ -31916,7 +31918,8 @@ void main() {
31916
31918
  objectMap,
31917
31919
  spacingFactor,
31918
31920
  projection: renderProjection,
31919
- scaleModel
31921
+ scaleModel,
31922
+ sceneMetricScale
31920
31923
  };
31921
31924
  const primaryRoot = rootObjects.find((object) => object.type === "star") ?? rootObjects[0] ?? null;
31922
31925
  if (primaryRoot) {
@@ -31932,14 +31935,14 @@ void main() {
31932
31935
  });
31933
31936
  }
31934
31937
  freeObjects.forEach((object, index) => {
31935
- const x = width - padding - 140 - freePlacementOffsetPx(object.placement?.mode === "free" ? object.placement.distance : void 0, scaleModel);
31938
+ const x = width - padding - 140 - freePlacementOffsetPx(object.placement?.mode === "free" ? object.placement.distance : void 0, scaleModel, sceneMetricScale);
31936
31939
  const rowStep = Math.max(76, (height - padding * 2 - 180) / Math.max(1, freeObjects.length) * spacingFactor) * scaleModel.freePlacementMultiplier;
31937
31940
  const y = padding + 92 + index * rowStep;
31938
31941
  positions.set(object.id, {
31939
31942
  object,
31940
31943
  x,
31941
31944
  y,
31942
- radius: visualRadiusFor(object, 0, scaleModel),
31945
+ radius: visualRadiusFor(object, 0, scaleModel, sceneMetricScale),
31943
31946
  sortKey: computeSortKey(x, y, 0)
31944
31947
  });
31945
31948
  leaderDrafts.push({
@@ -31962,7 +31965,7 @@ void main() {
31962
31965
  object,
31963
31966
  x: resolved.x,
31964
31967
  y: resolved.y,
31965
- radius: visualRadiusFor(object, 2, scaleModel),
31968
+ radius: visualRadiusFor(object, 2, scaleModel, sceneMetricScale),
31966
31969
  sortKey: computeSortKey(resolved.x, resolved.y, 2),
31967
31970
  anchorX: resolved.anchorX,
31968
31971
  anchorY: resolved.anchorY
@@ -32013,6 +32016,7 @@ void main() {
32013
32016
  scale: String(document2.system?.properties.scale ?? layoutPreset),
32014
32017
  units: String(document2.system?.properties.units ?? "mixed"),
32015
32018
  preset: frame.preset ?? "custom",
32019
+ "body.scaleMode": scaleModel.bodyScaleMode,
32016
32020
  ...camera?.azimuth !== null ? { "camera.azimuth": String(camera?.azimuth) } : {},
32017
32021
  ...camera?.elevation !== null ? { "camera.elevation": String(camera?.elevation) } : {},
32018
32022
  ...camera?.roll !== null ? { "camera.roll": String(camera?.roll) } : {},
@@ -32183,10 +32187,11 @@ void main() {
32183
32187
  }
32184
32188
  return parts.join(" - ");
32185
32189
  }
32186
- function resolveScaleModel(layoutPreset, overrides) {
32190
+ function resolveScaleModel(layoutPreset, overrides, bodyScaleMode) {
32187
32191
  const defaults = defaultScaleModel(layoutPreset);
32188
32192
  return {
32189
32193
  ...defaults,
32194
+ ...bodyScaleMode ? { bodyScaleMode } : {},
32190
32195
  ...overrides
32191
32196
  };
32192
32197
  }
@@ -32200,7 +32205,8 @@ void main() {
32200
32205
  freePlacementMultiplier: 0.9,
32201
32206
  ringThicknessMultiplier: 0.92,
32202
32207
  minBodyRadius: 4,
32203
- maxBodyRadius: 36
32208
+ maxBodyRadius: 36,
32209
+ bodyScaleMode: "readable"
32204
32210
  };
32205
32211
  case "presentation":
32206
32212
  return {
@@ -32210,7 +32216,8 @@ void main() {
32210
32216
  freePlacementMultiplier: 1.05,
32211
32217
  ringThicknessMultiplier: 1.16,
32212
32218
  minBodyRadius: 5,
32213
- maxBodyRadius: 48
32219
+ maxBodyRadius: 48,
32220
+ bodyScaleMode: "readable"
32214
32221
  };
32215
32222
  default:
32216
32223
  return {
@@ -32220,7 +32227,8 @@ void main() {
32220
32227
  freePlacementMultiplier: 1,
32221
32228
  ringThicknessMultiplier: 1,
32222
32229
  minBodyRadius: 4,
32223
- maxBodyRadius: 40
32230
+ maxBodyRadius: 40,
32231
+ bodyScaleMode: "readable"
32224
32232
  };
32225
32233
  }
32226
32234
  }
@@ -32234,6 +32242,48 @@ void main() {
32234
32242
  return 1;
32235
32243
  }
32236
32244
  }
32245
+ function resolveSceneMetricScale(objects, width, height, padding, spacingFactor, scaleModel) {
32246
+ const orbitMetrics = [];
32247
+ const bodyMetrics = [];
32248
+ for (const object of objects) {
32249
+ const radiusMetric = objectRadiusMetric(object);
32250
+ if (radiusMetric !== null && radiusMetric > 0) {
32251
+ bodyMetrics.push(radiusMetric);
32252
+ }
32253
+ const placement = object.placement;
32254
+ if (!placement) {
32255
+ continue;
32256
+ }
32257
+ if (placement.mode === "orbit") {
32258
+ const orbitMetricValue = toDistanceMetric(placement.semiMajor ?? placement.distance ?? null);
32259
+ if (orbitMetricValue !== null && orbitMetricValue > 0) {
32260
+ orbitMetrics.push(orbitMetricValue);
32261
+ }
32262
+ continue;
32263
+ }
32264
+ if (placement.mode === "free") {
32265
+ const freeMetric = toDistanceMetric(placement.distance ?? null);
32266
+ if (freeMetric !== null && freeMetric > 0) {
32267
+ orbitMetrics.push(freeMetric);
32268
+ }
32269
+ }
32270
+ }
32271
+ const maxDistanceMetric = Math.max(...orbitMetrics, 0);
32272
+ const maxBodyMetric = Math.max(...bodyMetrics, 0);
32273
+ const baseMetric = Math.max(maxDistanceMetric, maxBodyMetric * 6, 0);
32274
+ const referenceMetric = baseMetric + Math.max(Math.sqrt(baseMetric), maxBodyMetric * 2, maxDistanceMetric > 0 ? 0.25 : 0);
32275
+ if (referenceMetric <= 0) {
32276
+ return {
32277
+ pixelsPerMetric: null,
32278
+ hasExplicitScale: false
32279
+ };
32280
+ }
32281
+ const availableRadius = Math.max(Math.min(width, height) / 2 - padding - 24, 120) * spacingFactor * scaleModel.orbitDistanceMultiplier;
32282
+ return {
32283
+ pixelsPerMetric: availableRadius / referenceMetric,
32284
+ hasExplicitScale: true
32285
+ };
32286
+ }
32237
32287
  function createSceneObject(position, scaleModel, relationships) {
32238
32288
  const { object, x, y, radius, sortKey, anchorX, anchorY } = position;
32239
32289
  const renderPriority = object.renderHints?.renderPriority ?? 0;
@@ -32958,7 +33008,7 @@ void main() {
32958
33008
  object,
32959
33009
  x,
32960
33010
  y,
32961
- radius: visualRadiusFor(object, depth, context.scaleModel),
33011
+ radius: visualRadiusFor(object, depth, context.scaleModel, context.sceneMetricScale),
32962
33012
  sortKey: computeSortKey(x, y, depth)
32963
33013
  });
32964
33014
  placeOrbitingChildren(object, positions, orbitDrafts, leaderDrafts, context, depth + 1);
@@ -32969,7 +33019,7 @@ void main() {
32969
33019
  return;
32970
33020
  }
32971
33021
  const orbiting = [...context.orbitChildren.get(object.id) ?? []].sort(compareOrbiting);
32972
- const orbitMetricContext = computeOrbitMetricContext(orbiting, parent.radius, context.spacingFactor, context.scaleModel);
33022
+ const orbitMetricContext = computeOrbitMetricContext(orbiting, parent.radius, context.spacingFactor, context.scaleModel, context.sceneMetricScale);
32973
33023
  const orbitRadiiPx = resolveOrbitRadiiPx(orbiting, orbitMetricContext);
32974
33024
  orbiting.forEach((child, index) => {
32975
33025
  const orbitGeometry = resolveOrbitGeometry(child, index, orbiting.length, parent, orbitMetricContext, orbitRadiiPx[index] ?? orbitMetricContext.innerPx, context);
@@ -33004,7 +33054,7 @@ void main() {
33004
33054
  object: child,
33005
33055
  x,
33006
33056
  y,
33007
- radius: visualRadiusFor(child, depth + 1, context.scaleModel),
33057
+ radius: visualRadiusFor(child, depth + 1, context.scaleModel, context.sceneMetricScale),
33008
33058
  sortKey: computeSortKey(x, y, depth + 1),
33009
33059
  anchorX,
33010
33060
  anchorY
@@ -33033,10 +33083,11 @@ void main() {
33033
33083
  return 1;
33034
33084
  return left.id.localeCompare(right.id);
33035
33085
  }
33036
- function computeOrbitMetricContext(objects, parentRadius, spacingFactor, scaleModel) {
33086
+ function computeOrbitMetricContext(objects, parentRadius, spacingFactor, scaleModel, sceneMetricScale) {
33037
33087
  const metrics = objects.map((object) => orbitMetric(object));
33038
33088
  const presentMetrics = metrics.filter((value) => value !== null);
33039
- const innerPx = parentRadius + 56 * spacingFactor * scaleModel.orbitDistanceMultiplier;
33089
+ const minimumGapPx = scaleModel.bodyScaleMode === "strict" ? Math.max(2, 8 * spacingFactor * scaleModel.orbitDistanceMultiplier) : (objects.length > 2 ? 54 : 64) * spacingFactor * scaleModel.orbitDistanceMultiplier * 0.42;
33090
+ const innerPx = parentRadius + Math.max(minimumGapPx * 1.2, 24 * spacingFactor);
33040
33091
  const stepPx = (objects.length > 2 ? 54 : 64) * spacingFactor * scaleModel.orbitDistanceMultiplier;
33041
33092
  if (presentMetrics.length === 0) {
33042
33093
  return {
@@ -33047,7 +33098,8 @@ void main() {
33047
33098
  innerPx,
33048
33099
  stepPx,
33049
33100
  pixelSpread: Math.max(stepPx * Math.max(objects.length - 1, 1), stepPx),
33050
- minimumGapPx: stepPx * 0.42
33101
+ minimumGapPx,
33102
+ pixelsPerMetric: sceneMetricScale.pixelsPerMetric
33051
33103
  };
33052
33104
  }
33053
33105
  const minMetric = Math.min(...presentMetrics);
@@ -33061,7 +33113,8 @@ void main() {
33061
33113
  innerPx,
33062
33114
  stepPx,
33063
33115
  pixelSpread: Math.max(stepPx * Math.max(objects.length - 1, 1), stepPx),
33064
- minimumGapPx: stepPx * 0.42
33116
+ minimumGapPx,
33117
+ pixelsPerMetric: sceneMetricScale.pixelsPerMetric
33065
33118
  };
33066
33119
  }
33067
33120
  function resolveOrbitGeometry(object, index, count, parent, metricContext, orbitRadiusPx, context) {
@@ -33113,6 +33166,9 @@ void main() {
33113
33166
  };
33114
33167
  }
33115
33168
  function resolveOrbitRadiusPx(metric, metricContext) {
33169
+ if (metricContext.pixelsPerMetric !== null) {
33170
+ return metric * metricContext.pixelsPerMetric;
33171
+ }
33116
33172
  return metricContext.innerPx + metricContext.stepPx * log2(Math.max(metric, 0) + 1);
33117
33173
  }
33118
33174
  function resolveOrbitRadiiPx(objects, metricContext) {
@@ -33147,6 +33203,10 @@ void main() {
33147
33203
  const outerMetric = toDistanceMetric(toUnitValue(object.properties.outer));
33148
33204
  if (innerMetric !== null && outerMetric !== null) {
33149
33205
  const thicknessMetric = Math.abs(outerMetric - innerMetric);
33206
+ if (metricContext.pixelsPerMetric !== null) {
33207
+ const thicknessPx = thicknessMetric * metricContext.pixelsPerMetric;
33208
+ return scaleModel.bodyScaleMode === "strict" ? Math.max(thicknessPx * scaleModel.ringThicknessMultiplier, 1) : clampNumber(Math.max(thicknessPx * scaleModel.ringThicknessMultiplier, 8), 8, 54);
33209
+ }
33150
33210
  if (metricContext.metricSpread > 0) {
33151
33211
  return clampNumber(thicknessMetric / metricContext.metricSpread * metricContext.pixelSpread * scaleModel.ringThicknessMultiplier, 8, 54);
33152
33212
  }
@@ -33426,8 +33486,8 @@ void main() {
33426
33486
  }
33427
33487
  return positions.get(object.placement.target);
33428
33488
  }
33429
- function visualRadiusFor(object, depth, scaleModel) {
33430
- const explicitRadius = toVisualSizeMetric(object.properties.radius, scaleModel);
33489
+ function visualRadiusFor(object, depth, scaleModel, sceneMetricScale) {
33490
+ const explicitRadius = toVisualSizeMetric(object.properties.radius, scaleModel, sceneMetricScale);
33431
33491
  if (explicitRadius !== null) {
33432
33492
  return explicitRadius;
33433
33493
  }
@@ -33492,18 +33552,27 @@ void main() {
33492
33552
  return value.value;
33493
33553
  }
33494
33554
  }
33495
- function freePlacementOffsetPx(distance, scaleModel) {
33555
+ function freePlacementOffsetPx(distance, scaleModel, sceneMetricScale) {
33496
33556
  const metric = toDistanceMetric(distance ?? null);
33497
33557
  if (metric === null || metric <= 0) {
33498
33558
  return 0;
33499
33559
  }
33560
+ if (sceneMetricScale.pixelsPerMetric !== null) {
33561
+ const scaled = metric * sceneMetricScale.pixelsPerMetric * scaleModel.freePlacementMultiplier;
33562
+ return scaleModel.bodyScaleMode === "strict" ? Math.max(scaled, 0) : clampNumber(scaled, 0, 420);
33563
+ }
33500
33564
  return clampNumber(metric * 96 * scaleModel.freePlacementMultiplier, 0, 420);
33501
33565
  }
33502
- function toVisualSizeMetric(value, scaleModel) {
33566
+ function toVisualSizeMetric(value, scaleModel, sceneMetricScale) {
33503
33567
  const unitValue = toUnitValue(value);
33504
33568
  if (!unitValue) {
33505
33569
  return null;
33506
33570
  }
33571
+ const physicalMetric = toDistanceMetric(unitValue);
33572
+ if (sceneMetricScale.pixelsPerMetric !== null && physicalMetric !== null && physicalMetric > 0) {
33573
+ const scaled = physicalMetric * sceneMetricScale.pixelsPerMetric * scaleModel.bodyRadiusMultiplier;
33574
+ return scaleModel.bodyScaleMode === "strict" ? Math.max(scaled, 0.1) : clampNumber(Math.max(scaled, scaleModel.minBodyRadius), scaleModel.minBodyRadius, scaleModel.maxBodyRadius);
33575
+ }
33507
33576
  let size;
33508
33577
  switch (unitValue.unit) {
33509
33578
  case "sol":
@@ -33521,6 +33590,9 @@ void main() {
33521
33590
  }
33522
33591
  return clampNumber(size * scaleModel.bodyRadiusMultiplier, scaleModel.minBodyRadius, scaleModel.maxBodyRadius);
33523
33592
  }
33593
+ function objectRadiusMetric(object) {
33594
+ return toDistanceMetric(toUnitValue(object.properties.radius));
33595
+ }
33524
33596
  function toUnitValue(value) {
33525
33597
  if (!value || typeof value !== "object" || !("value" in value)) {
33526
33598
  return null;
@@ -33629,6 +33701,7 @@ void main() {
33629
33701
  projection: options.projection,
33630
33702
  camera: options.camera,
33631
33703
  scaleModel: options.scaleModel,
33704
+ bodyScaleMode: options.bodyScaleMode,
33632
33705
  activeEventId: options.activeEventId
33633
33706
  };
33634
33707
  const scene = renderDocumentToScene(document2, renderOptions);
@@ -38040,6 +38113,7 @@ void main() {
38040
38113
  camera: renderOptions.camera ? { ...renderOptions.camera } : null,
38041
38114
  layers: renderOptions.layers ? { ...renderOptions.layers } : void 0,
38042
38115
  scaleModel: renderOptions.scaleModel ? { ...renderOptions.scaleModel } : void 0,
38116
+ bodyScaleMode: renderOptions.bodyScaleMode,
38043
38117
  activeEventId: renderOptions.activeEventId ?? null,
38044
38118
  viewMode: renderOptions.viewMode ?? "2d"
38045
38119
  },
@@ -38068,6 +38142,7 @@ void main() {
38068
38142
  camera: raw.renderOptions?.camera ? { ...raw.renderOptions.camera } : null,
38069
38143
  layers: raw.renderOptions?.layers ? { ...raw.renderOptions.layers } : void 0,
38070
38144
  scaleModel: raw.renderOptions?.scaleModel ? { ...raw.renderOptions.scaleModel } : void 0,
38145
+ bodyScaleMode: raw.renderOptions?.bodyScaleMode,
38071
38146
  activeEventId: raw.activeEventId ?? raw.renderOptions?.activeEventId ?? null,
38072
38147
  viewMode: raw.renderOptions?.viewMode ?? "2d"
38073
38148
  },
@@ -38087,6 +38162,7 @@ void main() {
38087
38162
  camera: atlasState.renderOptions.camera ? { ...atlasState.renderOptions.camera } : null,
38088
38163
  layers: atlasState.renderOptions.layers ? { ...atlasState.renderOptions.layers } : void 0,
38089
38164
  scaleModel: atlasState.renderOptions.scaleModel ? { ...atlasState.renderOptions.scaleModel } : void 0,
38165
+ bodyScaleMode: atlasState.renderOptions.bodyScaleMode,
38090
38166
  activeEventId: atlasState.renderOptions.activeEventId ?? null,
38091
38167
  viewMode: atlasState.renderOptions.viewMode ?? "2d"
38092
38168
  },
@@ -39922,6 +39998,7 @@ void main() {
39922
39998
  padding: options.padding,
39923
39999
  preset: options.preset,
39924
40000
  projection: options.projection,
40001
+ bodyScaleMode: options.bodyScaleMode,
39925
40002
  viewMode: options.viewMode ?? "2d",
39926
40003
  quality: options.quality ?? "balanced",
39927
40004
  style3d: options.style3d ?? "symbolic",
@@ -41346,7 +41423,7 @@ void main() {
41346
41423
  };
41347
41424
  }
41348
41425
  function hasSceneAffectingRenderOptions(options) {
41349
- 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;
41426
+ 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.bodyScaleMode !== void 0 || options.activeEventId !== void 0;
41350
41427
  }
41351
41428
  function resolveSourceRenderOptions2(loaded, renderOptions) {
41352
41429
  const atlasDocument = loaded.atlasDocument ?? loaded.draftDocument;
@@ -42427,6 +42504,205 @@ void main() {
42427
42504
  function parseSource(source) {
42428
42505
  return loadWorldOrbitSource(source).document;
42429
42506
  }
42507
+
42508
+ // packages/viewer/dist/interactive-2d.js
42509
+ var DEFAULT_VIEWER_LIMITS2 = {
42510
+ minScale: 0.2,
42511
+ maxScale: 8,
42512
+ fitPadding: 48
42513
+ };
42514
+ function createInteractiveViewer2D(container, scene, options = {}) {
42515
+ const constraints = {
42516
+ minScale: options.minScale ?? DEFAULT_VIEWER_LIMITS2.minScale,
42517
+ maxScale: options.maxScale ?? DEFAULT_VIEWER_LIMITS2.maxScale,
42518
+ fitPadding: options.fitPadding ?? DEFAULT_VIEWER_LIMITS2.fitPadding
42519
+ };
42520
+ const behavior = {
42521
+ pointer: options.pointer ?? true,
42522
+ touch: options.touch ?? true,
42523
+ selection: options.selection ?? true
42524
+ };
42525
+ let renderOptions = {
42526
+ width: options.width,
42527
+ height: options.height,
42528
+ padding: options.padding,
42529
+ preset: options.preset,
42530
+ theme: options.theme,
42531
+ layers: options.layers,
42532
+ subtitle: options.subtitle,
42533
+ pointer: behavior.pointer,
42534
+ touch: behavior.touch,
42535
+ selection: behavior.selection,
42536
+ minScale: constraints.minScale,
42537
+ maxScale: constraints.maxScale,
42538
+ fitPadding: constraints.fitPadding
42539
+ };
42540
+ let state = fitViewerState(scene, DEFAULT_VIEWER_STATE, constraints);
42541
+ let svgElement = null;
42542
+ let cameraRoot = null;
42543
+ let destroyed = false;
42544
+ let activePointerId = null;
42545
+ let lastPointerClientPoint = null;
42546
+ let dragDistance = 0;
42547
+ const previousTabIndex = container.getAttribute("tabindex");
42548
+ const previousTouchAction = container.style.touchAction;
42549
+ if (previousTabIndex === null) {
42550
+ container.tabIndex = 0;
42551
+ }
42552
+ container.classList.add("wo-viewer-container");
42553
+ container.style.touchAction = behavior.touch ? "none" : previousTouchAction;
42554
+ const handleWheel = (event) => {
42555
+ if (!behavior.pointer || destroyed || !svgElement) {
42556
+ return;
42557
+ }
42558
+ event.preventDefault();
42559
+ container.focus();
42560
+ const anchor = getScenePointFromClient(event.clientX, event.clientY);
42561
+ const factor = clamp2(Math.exp(-event.deltaY * 2e-3), 0.6, 1.6);
42562
+ updateState(zoomViewerStateAt(scene, state, factor, anchor, constraints));
42563
+ };
42564
+ const handlePointerDown = (event) => {
42565
+ if (destroyed) {
42566
+ return;
42567
+ }
42568
+ const isTouch = event.pointerType === "touch";
42569
+ if (isTouch && !behavior.touch || !isTouch && !behavior.pointer) {
42570
+ return;
42571
+ }
42572
+ if (!isTouch && event.button !== 0) {
42573
+ return;
42574
+ }
42575
+ activePointerId = event.pointerId;
42576
+ lastPointerClientPoint = { x: event.clientX, y: event.clientY };
42577
+ dragDistance = 0;
42578
+ container.setPointerCapture?.(event.pointerId);
42579
+ container.focus();
42580
+ };
42581
+ const handlePointerMove = (event) => {
42582
+ if (destroyed || activePointerId !== event.pointerId || !lastPointerClientPoint) {
42583
+ return;
42584
+ }
42585
+ const rect = svgElement?.getBoundingClientRect();
42586
+ if (!rect || rect.width <= 0 || rect.height <= 0) {
42587
+ return;
42588
+ }
42589
+ const dx = event.clientX - lastPointerClientPoint.x;
42590
+ const dy = event.clientY - lastPointerClientPoint.y;
42591
+ lastPointerClientPoint = { x: event.clientX, y: event.clientY };
42592
+ dragDistance += Math.hypot(dx, dy);
42593
+ updateState(panViewerState(state, dx * (scene.width / rect.width), dy * (scene.height / rect.height)));
42594
+ };
42595
+ const stopPointer = (event) => {
42596
+ if (activePointerId !== event.pointerId) {
42597
+ return;
42598
+ }
42599
+ activePointerId = null;
42600
+ lastPointerClientPoint = null;
42601
+ container.releasePointerCapture?.(event.pointerId);
42602
+ };
42603
+ const handleClick = (event) => {
42604
+ if (destroyed || !behavior.selection || dragDistance > 6) {
42605
+ return;
42606
+ }
42607
+ const objectEl = event.target?.closest(".wo-object[data-object-id]");
42608
+ if (!objectEl) {
42609
+ return;
42610
+ }
42611
+ updateState({
42612
+ ...state,
42613
+ selectedObjectId: objectEl.dataset.objectId ?? null
42614
+ });
42615
+ renderSvg();
42616
+ };
42617
+ container.addEventListener("wheel", handleWheel, { passive: false });
42618
+ container.addEventListener("pointerdown", handlePointerDown);
42619
+ container.addEventListener("pointermove", handlePointerMove);
42620
+ container.addEventListener("pointerup", stopPointer);
42621
+ container.addEventListener("pointercancel", stopPointer);
42622
+ container.addEventListener("click", handleClick);
42623
+ renderSvg();
42624
+ return {
42625
+ getState() {
42626
+ return { ...state };
42627
+ },
42628
+ setState(nextState) {
42629
+ updateState({
42630
+ ...state,
42631
+ ...nextState
42632
+ });
42633
+ if ("selectedObjectId" in nextState) {
42634
+ renderSvg();
42635
+ }
42636
+ },
42637
+ setRenderOptions(nextOptions) {
42638
+ renderOptions = {
42639
+ ...renderOptions,
42640
+ ...nextOptions
42641
+ };
42642
+ renderSvg();
42643
+ },
42644
+ fitToSystem() {
42645
+ updateState(fitViewerState(scene, state, constraints));
42646
+ },
42647
+ destroy() {
42648
+ if (destroyed) {
42649
+ return;
42650
+ }
42651
+ destroyed = true;
42652
+ container.removeEventListener("wheel", handleWheel);
42653
+ container.removeEventListener("pointerdown", handlePointerDown);
42654
+ container.removeEventListener("pointermove", handlePointerMove);
42655
+ container.removeEventListener("pointerup", stopPointer);
42656
+ container.removeEventListener("pointercancel", stopPointer);
42657
+ container.removeEventListener("click", handleClick);
42658
+ if (previousTabIndex === null) {
42659
+ container.removeAttribute("tabindex");
42660
+ }
42661
+ container.style.touchAction = previousTouchAction;
42662
+ container.replaceChildren();
42663
+ svgElement = null;
42664
+ cameraRoot = null;
42665
+ }
42666
+ };
42667
+ function renderSvg() {
42668
+ if (destroyed) {
42669
+ return;
42670
+ }
42671
+ container.innerHTML = renderSceneToSvg(scene, {
42672
+ width: renderOptions.width,
42673
+ height: renderOptions.height,
42674
+ padding: renderOptions.padding,
42675
+ preset: renderOptions.preset,
42676
+ theme: renderOptions.theme,
42677
+ layers: renderOptions.layers,
42678
+ subtitle: renderOptions.subtitle,
42679
+ selectedObjectId: state.selectedObjectId
42680
+ });
42681
+ svgElement = container.querySelector("svg");
42682
+ cameraRoot = container.querySelector(`[data-worldorbit-camera-root="${WORLD_LAYER_ID}"]`);
42683
+ applyTransform();
42684
+ }
42685
+ function applyTransform() {
42686
+ cameraRoot?.setAttribute("transform", composeViewerTransform(scene, state));
42687
+ }
42688
+ function updateState(nextState) {
42689
+ state = nextState;
42690
+ applyTransform();
42691
+ }
42692
+ function getScenePointFromClient(clientX, clientY) {
42693
+ const rect = svgElement?.getBoundingClientRect();
42694
+ if (!rect || rect.width <= 0 || rect.height <= 0) {
42695
+ return { x: scene.width / 2, y: scene.height / 2 };
42696
+ }
42697
+ return {
42698
+ x: (clientX - rect.left) / rect.width * scene.width,
42699
+ y: (clientY - rect.top) / rect.height * scene.height
42700
+ };
42701
+ }
42702
+ }
42703
+ function clamp2(value, min, max) {
42704
+ return Math.min(Math.max(value, min), max);
42705
+ }
42430
42706
  return __toCommonJS(worldorbit_esm_exports);
42431
42707
  })();
42432
42708
  /**