@hraness/slopcamera 3.2.8 → 3.3.1

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 (150) hide show
  1. package/README.md +29 -9
  2. package/apps/desktop/application/context.ts +6 -0
  3. package/apps/desktop/application/default-registry.ts +26 -0
  4. package/apps/desktop/application/operation.ts +14 -1
  5. package/apps/desktop/application/operations/index.ts +4 -0
  6. package/apps/desktop/application/operations/spatial-behavior.ts +151 -0
  7. package/apps/desktop/application/operations/spatial-direction.ts +222 -0
  8. package/apps/desktop/application/operations/spatial-rendered-audit.ts +174 -0
  9. package/apps/desktop/application/operations/spatial-review.ts +194 -0
  10. package/apps/desktop/application/operations/spatial-scene.ts +25 -1
  11. package/apps/desktop/application/registry.ts +2 -2
  12. package/apps/desktop/application/spatial-asset-admission.ts +201 -0
  13. package/apps/desktop/application/spatial-assets.ts +160 -31
  14. package/apps/desktop/application/spatial-render.ts +217 -20
  15. package/apps/desktop/application/spatial-rendered-audit.ts +273 -0
  16. package/apps/desktop/application/spatial-review.ts +361 -0
  17. package/apps/desktop/application/spatial-spz.ts +48 -3
  18. package/apps/desktop/application/spatial-world-import.ts +26 -5
  19. package/apps/desktop/application/spatial-world-metadata.ts +105 -0
  20. package/apps/desktop/cli/args.ts +514 -11
  21. package/apps/desktop/cli/capability-manifest.ts +374 -0
  22. package/apps/desktop/cli/cinema-renderer.ts +608 -0
  23. package/apps/desktop/cli/command-host-resources.ts +29 -1
  24. package/apps/desktop/cli/commands.ts +1188 -4
  25. package/apps/desktop/cli/gateway-review-provider.ts +334 -0
  26. package/apps/desktop/cli/help.ts +172 -6
  27. package/apps/desktop/cli/main.ts +3 -3
  28. package/apps/desktop/cli/portable-surface.ts +6 -1
  29. package/apps/desktop/cli/spatial-asset-service.ts +124 -0
  30. package/apps/desktop/cli/spatial-design-service.ts +237 -0
  31. package/apps/desktop/cli/spatial-generate-service.ts +370 -0
  32. package/apps/desktop/cli/spatial-scene-service.ts +268 -4
  33. package/apps/desktop/cli/workflow-code.ts +1 -1
  34. package/apps/desktop/code/semantic-builder.ts +24 -0
  35. package/apps/desktop/contracts/cinema.ts +736 -0
  36. package/apps/desktop/contracts/index.ts +1 -0
  37. package/apps/desktop/contracts/spatial-asset.ts +16 -0
  38. package/apps/desktop/contracts/spatial-world.ts +26 -3
  39. package/apps/desktop/core/cinema-plan.ts +1320 -0
  40. package/apps/desktop/core/index.ts +1 -0
  41. package/apps/desktop/core/storage.ts +75 -0
  42. package/apps/desktop/dist/cli/main.js +725 -273
  43. package/apps/desktop/html-overlay/spatial.ts +619 -57
  44. package/apps/desktop/workflows/cinematic-world.ts +127 -0
  45. package/apps/desktop/workflows/index.ts +6 -0
  46. package/dist/cli.js +25 -429
  47. package/dist/code/advanced.js +1 -269
  48. package/dist/code/index.js +16 -2239
  49. package/dist/generate.js +1 -23
  50. package/dist/host-resources.js +1 -25
  51. package/dist/index-0bbesn4m.js +35 -0
  52. package/dist/index-296qhpf2.js +3 -0
  53. package/dist/index-3cxf2c58.js +3 -0
  54. package/dist/index-77fjfg9f.js +3 -0
  55. package/dist/index-80a36bc0.js +3 -0
  56. package/dist/index-a3vvs3rf.js +3 -0
  57. package/dist/index-b3geqczn.js +5 -0
  58. package/dist/index-cgpkyjqa.js +3 -0
  59. package/dist/index-f0ptv8dm.js +7 -0
  60. package/dist/index-grk47tgs.js +3 -0
  61. package/dist/index-qry58nj2.js +10 -0
  62. package/dist/index.js +1 -226
  63. package/dist/operations.js +1 -28
  64. package/dist/skill-install-gx7afxsd.js +2 -0
  65. package/dist/vectorize/worker.js +1 -141
  66. package/dist/workflow.js +1 -15
  67. package/docs/README.md +5 -1
  68. package/package.json +7 -5
  69. package/skills/slopcamera/SKILL.md +6 -1
  70. package/skills/slopcamera/references/directed-scenes.md +22 -2
  71. package/skills/slopcamera/references/gateway-media.md +15 -1
  72. package/skills/slopcamera/references/image-galleries.md +166 -0
  73. package/skills/slopcamera/references/install.md +1 -1
  74. package/skills/slopcamera/references/parametric-design.md +14 -0
  75. package/skills/slopcamera/references/scene-building.md +32 -0
  76. package/skills/slopcamera/references/social-collage-banners.md +204 -0
  77. package/skills/slopcamera/references/workflows-sdk.md +3 -3
  78. package/skills/slopcamera/scripts/compose-social-collage-banner.ts +728 -0
  79. package/src/capability-manifest.ts +361 -0
  80. package/src/cli.ts +222 -4
  81. package/src/code/canonical-json.ts +9 -0
  82. package/src/generate.ts +2 -2
  83. package/src/icon.ts +1111 -0
  84. package/src/image-gallery.ts +1049 -0
  85. package/src/index.ts +11 -0
  86. package/src/mcp/boundary.ts +11 -11
  87. package/src/mcp/index.ts +3 -0
  88. package/src/mcp/server.ts +2 -1
  89. package/src/mcp/tools.ts +1642 -130
  90. package/src/mcp/types.ts +19 -0
  91. package/src/operations.ts +412 -0
  92. package/src/portable-capability-manifest.ts +67 -0
  93. package/src/scene-gallery.ts +184 -0
  94. package/src/spatial-scene/asset-admission.ts +183 -0
  95. package/src/spatial-scene/audit-rendered.ts +692 -0
  96. package/src/spatial-scene/audit.ts +617 -0
  97. package/src/spatial-scene/behavior-audit.ts +252 -0
  98. package/src/spatial-scene/behavior-bake.ts +233 -0
  99. package/src/spatial-scene/behavior-fns.ts +585 -0
  100. package/src/spatial-scene/behavior-gallery.ts +109 -0
  101. package/src/spatial-scene/behavior-stdlib.ts +323 -0
  102. package/src/spatial-scene/behavior-trace.ts +325 -0
  103. package/src/spatial-scene/behavior.ts +618 -0
  104. package/src/spatial-scene/build.ts +632 -0
  105. package/src/spatial-scene/camera-rig.ts +125 -0
  106. package/src/spatial-scene/camera-track.ts +4 -2
  107. package/src/spatial-scene/character.ts +124 -0
  108. package/src/spatial-scene/contracts.ts +75 -7
  109. package/src/spatial-scene/design-templates.ts +351 -0
  110. package/src/spatial-scene/design.ts +327 -0
  111. package/src/spatial-scene/direction-compile.ts +584 -0
  112. package/src/spatial-scene/direction.ts +122 -0
  113. package/src/spatial-scene/effects.ts +149 -0
  114. package/src/spatial-scene/evaluate.ts +109 -29
  115. package/src/spatial-scene/gallery.ts +277 -0
  116. package/src/spatial-scene/generate.ts +239 -0
  117. package/src/spatial-scene/geometry-native.ts +165 -0
  118. package/src/spatial-scene/geometry.ts +1216 -0
  119. package/src/spatial-scene/gltf.ts +600 -77
  120. package/src/spatial-scene/identity.ts +55 -2
  121. package/src/spatial-scene/index.ts +36 -0
  122. package/src/spatial-scene/inspect.ts +35 -6
  123. package/src/spatial-scene/material-lighting.ts +609 -0
  124. package/src/spatial-scene/math.ts +21 -4
  125. package/src/spatial-scene/motion-evidence.ts +88 -0
  126. package/src/spatial-scene/parametric.ts +765 -0
  127. package/src/spatial-scene/particle-preparation.ts +183 -0
  128. package/src/spatial-scene/particle.ts +195 -0
  129. package/src/spatial-scene/patch.ts +109 -15
  130. package/src/spatial-scene/performance.ts +1613 -0
  131. package/src/spatial-scene/probe.ts +137 -0
  132. package/src/spatial-scene/recipe-pack.ts +86 -0
  133. package/src/spatial-scene/render-effects.ts +240 -0
  134. package/src/spatial-scene/review.ts +639 -0
  135. package/src/spatial-scene/simulation-bake.ts +206 -0
  136. package/src/spatial-scene/simulation.ts +187 -0
  137. package/src/spatial-scene/solve.ts +366 -0
  138. package/src/spatial-scene/temporal-audit.ts +354 -0
  139. package/src/version.ts +1 -1
  140. package/dist/index-42zsesc1.js +0 -2257
  141. package/dist/index-7131pg1c.js +0 -1820
  142. package/dist/index-7308egqr.js +0 -48
  143. package/dist/index-8txs6fkn.js +0 -712
  144. package/dist/index-fava6pge.js +0 -192
  145. package/dist/index-h1k0fnjq.js +0 -2363
  146. package/dist/index-r7gdhmsp.js +0 -424
  147. package/dist/index-sh6xbav6.js +0 -1219
  148. package/dist/index-z1w83f81.js +0 -4
  149. package/dist/index-zfnddgay.js +0 -2029
  150. package/dist/skill-install-dh0ntqba.js +0 -10
@@ -7,6 +7,7 @@ import {
7
7
  type SpatialAnimation, type SpatialAssetManifest, type SpatialEntity,
8
8
  type SpatialOverride, type SpatialSceneV1,
9
9
  } from "./contracts.js"
10
+ import { pbrMaterialMapAssetIds } from "./material-lighting.js"
10
11
 
11
12
  export class SpatialSceneError extends SlopcameraCodeError {
12
13
  readonly path: string
@@ -96,7 +97,21 @@ export function generatedSpatialEntityId(generatorId: string, key: string): stri
96
97
  }
97
98
 
98
99
  function normalizeEntity(entity: SpatialEntity): SpatialEntity {
99
- if (entity.kind === "mesh") return { ...entity, material: { ...entity.material, color: entity.material.color.toLowerCase() } }
100
+ if (entity.kind === "mesh") {
101
+ const material = entity.material
102
+ if (material.kind === "pbr") {
103
+ const emissive = material.emissive !== undefined
104
+ ? { ...material.emissive, color: material.emissive.color.toLowerCase() } : undefined
105
+ const sheen = material.sheen !== undefined
106
+ ? { ...material.sheen, color: material.sheen.color.toLowerCase() } : undefined
107
+ return { ...entity, material: { ...material, color: material.color.toLowerCase(),
108
+ ...(emissive === undefined ? {} : { emissive }),
109
+ ...(sheen === undefined ? {} : { sheen }) } }
110
+ }
111
+ const emissive = material.kind === "standard" && material.emissive !== undefined
112
+ ? { ...material.emissive, color: material.emissive.color.toLowerCase() } : undefined
113
+ return { ...entity, material: { ...material, color: material.color.toLowerCase(), ...(emissive === undefined ? {} : { emissive }) } }
114
+ }
100
115
  if (entity.kind === "text" || entity.kind === "light") return { ...entity, color: entity.color.toLowerCase() }
101
116
  return entity
102
117
  }
@@ -176,7 +191,7 @@ export function parseSpatialScene(input: unknown): SpatialSceneV1 {
176
191
  cameras: sortSpatialBy(parsed.cameras, item => item.cameraId),
177
192
  assets: sortSpatialBy(parsed.assets.map(normalizeAsset).map(asset => ({ ...asset, dependencies: [...asset.dependencies].sort(compare) })), item => item.assetId),
178
193
  animations: sortSpatialBy(parsed.animations, item => item.channelId),
179
- generators: sortSpatialBy(parsed.generators.map(generator => ({ ...generator, editableKeys: sortSpatialBy(generator.editableKeys.map(item => ({ ...item, properties: [...item.properties].sort(compare) })), item => item.key) })), item => item.generatorId),
194
+ generators: sortSpatialBy(parsed.generators.map(generator => ({ ...generator, editableKeys: sortSpatialBy(generator.editableKeys.map(item => ({ ...item, properties: [...item.properties].sort(compare) })), item => item.key), ...(generator.assets === undefined ? {} : { assets: [...generator.assets].sort(compare) }) })), item => item.generatorId),
180
195
  overrides: sortSpatialBy(parsed.overrides.map(item => item.property === "color" ? { ...item, value: item.value.toLowerCase() } : item), item => `${item.entityId}:${item.property}`),
181
196
  }
182
197
  const entities = unique(scene.entities, entity => entity.entityId, "entities")
@@ -195,6 +210,26 @@ export function parseSpatialScene(input: unknown): SpatialSceneV1 {
195
210
  }
196
211
  spatialTopologicalIds(new Map(scene.assets.map(asset => [asset.assetId, asset.dependencies])), "asset dependencies")
197
212
  spatialTopologicalIds(new Map(scene.entities.map(entity => [entity.entityId, entity.parentId === null ? [] : [entity.parentId]])), "entity hierarchy")
213
+ // Generator-owned assets: each declared id must exist, carry a generated or
214
+ // derived provenance, and belong to exactly one generator. Owned assets may
215
+ // be referenced only by that generator's retained entities.
216
+ const ownedAssets = new Map<string, string>()
217
+ for (const generator of scene.generators) {
218
+ unique(generator.assets ?? [], id => id, "generator assets")
219
+ for (const assetId of generator.assets ?? []) {
220
+ const asset = requireReference(assets, assetId, "generator asset")
221
+ if (asset.provenance.source !== "generated" && asset.provenance.source !== "derived") throw new SpatialSceneError("invalid-data", `Generator-owned asset ${assetId} requires generated or derived provenance.`, "generators")
222
+ const owner = ownedAssets.get(assetId)
223
+ if (owner !== undefined && owner !== generator.generatorId) throw new SpatialSceneError("invalid-data", `Asset ${assetId} is owned by more than one generator.`, "generators")
224
+ ownedAssets.set(assetId, generator.generatorId)
225
+ }
226
+ }
227
+ const checkAssetOwnership = (entity: SpatialEntity, assetId: string, path: string) => {
228
+ const owner = ownedAssets.get(assetId)
229
+ if (owner !== undefined && (entity.origin.kind !== "generated" || entity.origin.generatorId !== owner)) {
230
+ throw new SpatialSceneError("invalid-data", `Entity ${entity.entityId} references an asset owned by another generator.`, path)
231
+ }
232
+ }
198
233
  const generatedKeys = new Set<string>()
199
234
  for (const entity of scene.entities) {
200
235
  if (entity.placement.kind === "view") requireReference(cameras, entity.placement.cameraId, "placement")
@@ -211,10 +246,28 @@ export function parseSpatialScene(input: unknown): SpatialSceneV1 {
211
246
  if (generatedKeys.has(identity)) throw new SpatialSceneError("invalid-data", "Duplicate generator output key.", "origin")
212
247
  generatedKeys.add(identity)
213
248
  }
249
+ if (entity.kind === "environment" && (entity.placement.kind !== "world" || entity.parentId !== null)) {
250
+ throw new SpatialSceneError("invalid-data", "Environment entities must be unparented world entities.", "placement")
251
+ }
252
+ if (entity.kind === "mesh" && entity.material.kind !== "pbr" && entity.material.map !== undefined) {
253
+ if (entity.geometry.kind === "asset") throw new SpatialSceneError("invalid-data", "Material maps apply to authored procedural geometry only.", "entities")
254
+ checkAssetOwnership(entity, entity.material.map, "entity asset")
255
+ const mapAsset = requireReference(assets, entity.material.map, "entity asset")
256
+ if (mapAsset.interpretation.kind !== "image") throw new SpatialSceneError("invalid-data", `Entity ${entity.entityId} material map requires an image asset.`, "entity asset")
257
+ }
258
+ if (entity.kind === "mesh" && entity.material.kind === "pbr") {
259
+ if (entity.geometry.kind === "asset") throw new SpatialSceneError("invalid-data", "PBR material maps apply to authored procedural geometry only.", "entities")
260
+ for (const mapAssetId of pbrMaterialMapAssetIds(entity.material)) {
261
+ const mapAsset = requireReference(assets, mapAssetId, "entity pbr map asset")
262
+ if (mapAsset.interpretation.kind !== "image") throw new SpatialSceneError("invalid-data", `Entity ${entity.entityId} PBR map requires an image asset, got ${mapAsset.interpretation.kind}.`, "entity pbr map")
263
+ }
264
+ }
214
265
  const reference = entity.kind === "mesh" && entity.geometry.kind === "asset" ? { assetId: entity.geometry.assetId, kind: "gltf" }
215
266
  : entity.kind === "text" ? { assetId: entity.fontAssetId, kind: "font" }
267
+ : entity.kind === "environment" ? { assetId: entity.assetId, kind: "image" }
216
268
  : "assetId" in entity ? { assetId: entity.assetId, kind: entity.kind } : undefined
217
269
  if (reference) {
270
+ checkAssetOwnership(entity, reference.assetId, "entity asset")
218
271
  const asset = requireReference(assets, reference.assetId, "entity asset")
219
272
  if (asset.interpretation.kind !== reference.kind) throw new SpatialSceneError("invalid-data", `Entity ${entity.entityId} requires a ${reference.kind} asset.`, "entity asset")
220
273
  if (entity.kind === "video" && asset.interpretation.kind === "video" && entity.sourceOffsetUs >= asset.interpretation.durationUs) throw new SpatialSceneError("invalid-data", "Video source offset must precede its duration.", "sourceOffsetUs")
@@ -1,10 +1,46 @@
1
1
  export * from "./contracts.js"
2
+ export * from "./asset-admission.js"
2
3
  export * from "./identity.js"
3
4
  export * from "./patch.js"
4
5
  export * from "./inspect.js"
5
6
  export * from "./evaluate.js"
7
+ export * from "./audit.js"
8
+ export * from "./audit-rendered.js"
9
+ export * from "./review.js"
6
10
  export * from "./math.js"
7
11
  export * from "./time.js"
8
12
  export * from "./authoring.js"
13
+ export * from "./probe.js"
14
+ export * from "./build.js"
15
+ export * from "./solve.js"
16
+ export * from "./generate.js"
9
17
  export * from "./gltf.js"
10
18
  export * from "./camera-track.js"
19
+ export * from "./camera-rig.js"
20
+ export * from "./character.js"
21
+ export * from "./material-lighting.js"
22
+ export * from "./performance.js"
23
+ export * from "./geometry.js"
24
+ export * from "./geometry-native.js"
25
+ export * from "./parametric.js"
26
+ export * from "./design.js"
27
+ export * from "./design-templates.js"
28
+ export * from "./effects.js"
29
+ export * from "./render-effects.js"
30
+ export * from "./particle.js"
31
+ export * from "./particle-preparation.js"
32
+ export * from "./simulation.js"
33
+ export * from "./motion-evidence.js"
34
+ export * from "./direction.js"
35
+ export * from "./direction-compile.js"
36
+ export * from "./temporal-audit.js"
37
+ export * from "./gallery.js"
38
+ export * from "./recipe-pack.js"
39
+ export * from "./simulation-bake.js"
40
+ export * from "./behavior.js"
41
+ export * from "./behavior-fns.js"
42
+ export * from "./behavior-trace.js"
43
+ export * from "./behavior-bake.js"
44
+ export * from "./behavior-gallery.js"
45
+ export * from "./behavior-stdlib.js"
46
+ export * from "./behavior-audit.js"
@@ -2,12 +2,16 @@ import { deepFreezeJson } from "../code/json-snapshot.js"
2
2
  import type { SpatialEntity, SpatialOverride, SpatialSceneV1 } from "./contracts.js"
3
3
  import { evaluateSpatialScene } from "./evaluate.js"
4
4
  import { parseSpatialScene, spatialAssetClosureDigests, spatialPropertySupported, spatialValueSha256 } from "./identity.js"
5
- import { transformBounds, type Bounds, type Vec3 } from "./math.js"
5
+ import { pbrMaterialMapAssetIds } from "./material-lighting.js"
6
+ import { composeTransform, multiplyTransforms, transformBounds, type Bounds, type Vec3 } from "./math.js"
6
7
 
7
8
  export type SpatialInspectedBounds =
8
9
  | { readonly status: "authored-enclosure"; readonly coordinateDomain: SpatialEntity["placement"]; readonly atTimeUs: 0; readonly bounds: Bounds }
9
10
  | { readonly status: "unknown"; readonly reason: "requires-asset-decoding" | "requires-text-layout" | "no-surface" }
10
11
 
12
+ /** Authored-edit surface beyond the override properties: patch operations own these controls. */
13
+ export type SpatialEditableControl = SpatialOverride["property"] | "emissive" | "instances" | "castShadow" | "receiveShadow" | "spot" | "shadow"
14
+
11
15
  export interface SpatialSceneInspection {
12
16
  readonly sceneId: string
13
17
  readonly sceneSha256: string
@@ -19,7 +23,7 @@ export interface SpatialSceneInspection {
19
23
  readonly origin: SpatialEntity["origin"]
20
24
  readonly parentId: string | null
21
25
  readonly placement: SpatialEntity["placement"]
22
- readonly editableControls: readonly SpatialOverride["property"][]
26
+ readonly editableControls: readonly SpatialEditableControl[]
23
27
  readonly animatedProperties: readonly string[]
24
28
  readonly assetIds: readonly string[]
25
29
  readonly bounds: SpatialInspectedBounds
@@ -53,14 +57,39 @@ export function inspectSpatialScene(input: unknown): SpatialSceneInspection {
53
57
  sceneId: scene.sceneId, sceneSha256: spatialValueSha256(scene), durationUs: scene.durationUs,
54
58
  entities: snapshot.entities.map(({ entity, worldMatrix }) => {
55
59
  const origin = entity.origin
56
- const declared = origin.kind === "generated"
60
+ const declared: readonly SpatialEditableControl[] = origin.kind === "generated"
57
61
  ? scene.generators.find(generator => generator.generatorId === origin.generatorId)!.editableKeys.find(item => item.key === origin.key)?.properties ?? []
58
- : (["color", "opacity", "transform"] as const).filter(property => spatialPropertySupported(entity, property))
62
+ : [
63
+ ...(["color", "opacity", "transform"] as const).filter(property => spatialPropertySupported(entity, property)),
64
+ ...(entity.kind === "mesh" ? [
65
+ ...((entity.material.kind === "standard" || entity.material.kind === "pbr") && spatialPropertySupported(entity, "color") ? ["emissive" as const] : []),
66
+ "instances" as const, "castShadow" as const, "receiveShadow" as const,
67
+ ] : []),
68
+ ...(entity.kind === "light" ? [
69
+ ...(entity.light === "spot" ? ["spot" as const] : []),
70
+ ...(entity.light !== "ambient" ? ["shadow" as const] : []),
71
+ ] : []),
72
+ ]
59
73
  const animatedProperties = scene.animations.filter(channel => channel.targetId === entity.entityId).map(channel => channel.property)
60
74
  const editableControls = declared.filter(property => !animatedProperties.some(animated => animated === property || (property === "transform" && ["position", "rotation", "scale"].includes(animated))))
61
75
  const local = localBounds(entity)
62
- const bounds: SpatialInspectedBounds = "status" in local ? local : { status: "authored-enclosure", coordinateDomain: entity.placement, atTimeUs: 0, bounds: transformBounds(worldMatrix, local) }
63
- const assetIds = entity.kind === "mesh" && entity.geometry.kind === "asset" ? [entity.geometry.assetId] : entity.kind === "text" ? [entity.fontAssetId] : "assetId" in entity ? [entity.assetId] : []
76
+ const localDomains: Bounds[] = "status" in local ? []
77
+ : entity.kind === "mesh" && entity.instances !== undefined
78
+ ? entity.instances.map(instance => transformBounds(multiplyTransforms(worldMatrix, composeTransform(instance)), local))
79
+ : [transformBounds(worldMatrix, local)]
80
+ const bounds: SpatialInspectedBounds = "status" in local ? local : {
81
+ status: "authored-enclosure", coordinateDomain: entity.placement, atTimeUs: 0,
82
+ bounds: localDomains.reduce((union, next) => ({
83
+ min: union.min.map((value, axis) => Math.min(value, next.min[axis]!)) as unknown as Bounds["min"],
84
+ max: union.max.map((value, axis) => Math.max(value, next.max[axis]!)) as unknown as Bounds["max"],
85
+ })),
86
+ }
87
+ const meshMapIds = entity.kind === "mesh"
88
+ ? entity.material.kind === "pbr" ? pbrMaterialMapAssetIds(entity.material) : entity.material.map === undefined ? [] : [entity.material.map]
89
+ : []
90
+ const assetIds = entity.kind === "mesh"
91
+ ? [...entity.geometry.kind === "asset" ? [entity.geometry.assetId] : [], ...meshMapIds]
92
+ : entity.kind === "text" ? [entity.fontAssetId] : "assetId" in entity ? [entity.assetId] : []
64
93
  return { entityId: entity.entityId, name: entity.name, kind: entity.kind, origin, parentId: entity.parentId, placement: entity.placement, editableControls, animatedProperties, assetIds, bounds }
65
94
  }),
66
95
  cameras: scene.cameras, assets: scene.assets.map(manifest => ({ assetId: manifest.assetId, manifestSha256: digests[manifest.assetId]!, manifest })), generators: scene.generators,