@relu-interactives/spatial-ecs 0.2.21 → 0.2.23

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 (50) hide show
  1. package/dist/{System-me3iAcMF.d.cts → System-CYWZ_Zx5.d.cts} +4 -3
  2. package/dist/{System-me3iAcMF.d.ts → System-CYWZ_Zx5.d.ts} +4 -3
  3. package/dist/{Video-DHnxjGhW.d.ts → Video-C1IOat7L.d.ts} +38 -9
  4. package/dist/{Video-U9hAnf9y.d.cts → Video-ppAXaKt0.d.cts} +38 -9
  5. package/dist/{chunk-K6KMKKJ6.js → chunk-52CHDPRQ.js} +118 -92
  6. package/dist/chunk-52CHDPRQ.js.map +1 -0
  7. package/dist/{chunk-5U3YS4JD.js → chunk-7BEZBIVB.js} +428 -65
  8. package/dist/chunk-7BEZBIVB.js.map +1 -0
  9. package/dist/{chunk-V7BNVTJW.js → chunk-JHCPRVBC.js} +25 -4
  10. package/dist/chunk-JHCPRVBC.js.map +1 -0
  11. package/dist/{chunk-AXRCGF63.js → chunk-WKGCC7YL.js} +3 -3
  12. package/dist/{chunk-AXRCGF63.js.map → chunk-WKGCC7YL.js.map} +1 -1
  13. package/dist/components/index.cjs +22 -1
  14. package/dist/components/index.cjs.map +1 -1
  15. package/dist/components/index.d.cts +3 -3
  16. package/dist/components/index.d.ts +3 -3
  17. package/dist/components/index.js +1 -1
  18. package/dist/docs/guide/authoring-a-behaviour.md +3 -40
  19. package/dist/docs/guide/authoring-a-script-object.md +115 -0
  20. package/dist/docs/guide/behaviour-lifecycle.md +4 -4
  21. package/dist/docs/guide/spawning/script-object.md +36 -0
  22. package/dist/docs/guide/systems/_sidebar.json +4 -0
  23. package/dist/docs/guide/systems/script-behaviour-system.md +1 -17
  24. package/dist/docs/guide/systems/script-object-system.md +44 -0
  25. package/dist/factories/index.cjs +164 -117
  26. package/dist/factories/index.cjs.map +1 -1
  27. package/dist/factories/index.d.cts +5 -3
  28. package/dist/factories/index.d.ts +5 -3
  29. package/dist/factories/index.js +3 -3
  30. package/dist/{index-D7FSg0Au.d.ts → index-Cu2Pt7wN.d.cts} +6 -3
  31. package/dist/{index-CZo5I5Gs.d.cts → index-DdiWu1b6.d.ts} +6 -3
  32. package/dist/index.cjs +684 -265
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.d.cts +117 -28
  35. package/dist/index.d.ts +117 -28
  36. package/dist/index.js +13 -8
  37. package/dist/index.js.map +1 -1
  38. package/dist/systems/index.cjs +410 -36
  39. package/dist/systems/index.cjs.map +1 -1
  40. package/dist/systems/index.d.cts +44 -3
  41. package/dist/systems/index.d.ts +44 -3
  42. package/dist/systems/index.js +3 -3
  43. package/dist/types.d.cts +1 -1
  44. package/dist/types.d.ts +1 -1
  45. package/dist/worldSnapshotUtils.d.cts +1 -1
  46. package/dist/worldSnapshotUtils.d.ts +1 -1
  47. package/package.json +1 -1
  48. package/dist/chunk-5U3YS4JD.js.map +0 -1
  49. package/dist/chunk-K6KMKKJ6.js.map +0 -1
  50. package/dist/chunk-V7BNVTJW.js.map +0 -1
package/dist/index.d.cts CHANGED
@@ -1,11 +1,11 @@
1
- import { k as EcsSystem, C as Component, W as WorldEntityView, T as TransformComponent, l as World, S as SpawnPrefabSource, m as SpawnPrefabOptions, n as ComponentClass, o as ParentLookup, p as EcsEntityKind, O as ObjectManagementSystem, q as SubtreeSnapshot, r as EntityId, s as ExternalRefWarning } from './System-me3iAcMF.cjs';
2
- export { A as AssetInput, t as CheckboxInput, u as ColorInput, v as ComponentFactory, w as ComponentInput, x as ComponentKind, y as DropdownInput, z as DropdownOption, B as EcsComponentFactoryKind, F as EcsEntityEditorKind, G as EntityInput, H as FloatInput, I as InputSystem, J as IntersectionResult, K as KeyboardKey, L as KeyboardKeys, M as MouseButton, N as PREFAB_FILE_VERSION, Q as PREFAB_FILE_VERSION_NESTED, R as PrefabAsset, U as RemapSnapshotOptions, X as RenderSystem, Y as SelectionListener, Z as SliderInput, _ as TextInput, $ as ToggleInput, a0 as TransformSyncSystem, a1 as Vec3, a2 as Vector2Input, a3 as Vector3Input, a4 as clearPrefabCache, a5 as despawnPrefab, a6 as loadPrefab, a7 as parsePrefabAsset, a8 as prefabFileVersionFor, a9 as remapSnapshotEntityIds, aa as setPrefabAssetUrlResolver, ab as spawnPrefab } from './System-me3iAcMF.cjs';
1
+ import { k as EcsSystem, C as Component, W as WorldEntityView, T as TransformComponent, l as World, S as SpawnPrefabSource, m as SpawnPrefabOptions, n as ComponentClass, o as ParentLookup, p as EcsEntityKind, O as ObjectManagementSystem, q as SubtreeSnapshot, r as EntityId, s as ExternalRefWarning } from './System-CYWZ_Zx5.cjs';
2
+ export { A as AssetInput, t as CheckboxInput, u as ColorInput, v as ComponentFactory, w as ComponentInput, x as ComponentKind, y as DropdownInput, z as DropdownOption, B as EcsComponentFactoryKind, F as EcsEntityEditorKind, G as EntityInput, H as FloatInput, I as InputSystem, J as IntersectionResult, K as KeyboardKey, L as KeyboardKeys, M as MouseButton, N as PREFAB_FILE_VERSION, Q as PREFAB_FILE_VERSION_NESTED, R as PrefabAsset, U as RemapSnapshotOptions, X as RenderSystem, Y as SelectionListener, Z as SliderInput, _ as TextInput, $ as ToggleInput, a0 as TransformSyncSystem, a1 as Vec3, a2 as Vector2Input, a3 as Vector3Input, a4 as clearPrefabCache, a5 as despawnPrefab, a6 as loadPrefab, a7 as parsePrefabAsset, a8 as prefabFileVersionFor, a9 as remapSnapshotEntityIds, aa as setPrefabAssetUrlResolver, ab as spawnPrefab } from './System-CYWZ_Zx5.cjs';
3
3
  import * as THREE from 'three';
4
- import { O as Object3DRef } from './Video-U9hAnf9y.cjs';
5
- export { a3 as AnimationStateCallbacks, a4 as AnimationStateMachine, a5 as AnimationStateManager, a6 as StateMachine } from './Video-U9hAnf9y.cjs';
6
- export { i as CoreComponents } from './index-CZo5I5Gs.cjs';
7
- export { AnimationSystem, AudioSystem, CameraSyncSystem, EnvironmentSyncSystem, InstancedMeshSystem, LightSyncSystem, MaterialSyncSystem, MeshGeometrySystem, ObjectVisibilitySystem, PhysicsSyncSystem, PostprocessingSyncSystem, ScriptBehaviourSystem, SelectionContext, VideoSystem } from './systems/index.cjs';
8
- export { createAnimationComponent, createAudioComponent, createCameraComponent, createEntityTypeComponent, createEnvironmentComponent, createImageComponent, createImageTargetAnchorComponent, createImageTargetComponent, createInstanceSlotComponent, createInstancedMeshComponent, createLightComponent, createMaterialComponent, createMeshComponent, createMeshGeometryComponent, createModelComponent, createNameComponent, createObject3DRefComponent, createParentIdComponent, createPhysicsComponent, createPostprocessingComponent, createScriptComponent, createSelectableComponent, createSelectionTransformStateComponent, createSpriteComponent, createTransformComponent, createVideoComponent, registerDefaultComponentFactories, registerDefaultFactories } from './factories/index.cjs';
4
+ import { O as Object3DRef } from './Video-ppAXaKt0.cjs';
5
+ export { a6 as AnimationStateCallbacks, a7 as AnimationStateMachine, a8 as AnimationStateManager, a9 as StateMachine } from './Video-ppAXaKt0.cjs';
6
+ export { i as CoreComponents } from './index-Cu2Pt7wN.cjs';
7
+ export { AnimationSystem, AudioSystem, CameraSyncSystem, EnvironmentSyncSystem, InstancedMeshSystem, LightSyncSystem, MaterialSyncSystem, MeshGeometrySystem, ModuleLoader, ObjectVisibilitySystem, PhysicsSyncSystem, PostprocessingSyncSystem, SCRIPT_OBJECT_ROOT_FLAG, ScriptBehaviourSystem, ScriptObjectSystem, SelectionContext, VideoSystem } from './systems/index.cjs';
8
+ export { createAnimationComponent, createAudioComponent, createCameraComponent, createEntityTypeComponent, createEnvironmentComponent, createImageComponent, createImageTargetAnchorComponent, createImageTargetComponent, createInstanceSlotComponent, createInstancedMeshComponent, createLightComponent, createMaterialComponent, createMeshComponent, createMeshGeometryComponent, createModelComponent, createNameComponent, createObject3DRefComponent, createParentIdComponent, createPhysicsComponent, createPostprocessingComponent, createScriptComponent, createScriptObjectComponent, createSelectableComponent, createSelectionTransformStateComponent, createSpriteComponent, createTransformComponent, createVideoComponent, registerDefaultComponentFactories, registerDefaultFactories } from './factories/index.cjs';
9
9
  import { GLTF } from 'three/examples/jsm/loaders/GLTFLoader.js';
10
10
  import '@dimforge/rapier3d-compat';
11
11
 
@@ -25,15 +25,10 @@ interface CustomEcsSystem extends EcsSystem {
25
25
  * Override {@link Behaviour.onUpdate} for per-frame logic — never override
26
26
  * {@link Behaviour.update}, which is the engine-managed entry point.
27
27
  *
28
- * **Editor scripts**: By default, `Behaviour` subclasses do not run inside the
29
- * editor. Set `executeInEditor: true` on the script entry in the inspector to
30
- * enable the full lifecycle (`init` → `onUpdate` → `dispose`) while the editor
31
- * is open. This gives direct access to the Three.js scene, camera, and renderer
32
- * via {@link World.getScene}, {@link World.getCamera}, and
33
- * {@link World.getRenderer} — useful for custom shaders, procedural geometry,
34
- * grass, and any Three.js feature the editor's object palette does not expose.
35
- * Avoid mutating ECS component state every frame in editor mode, as it creates
36
- * undo history entries on every tick.
28
+ * **Editor vs runtime**: `Behaviour` subclasses run ONLY at preview/runtime —
29
+ * they never execute in the editor. For a visual that must render and animate
30
+ * inside the editor (custom shaders, procedural geometry, grass, anything the
31
+ * object palette can't produce), use {@link ScriptObject} instead.
37
32
  *
38
33
  * The runtime recognizes a script by its **default export** plus the
39
34
  * inherited static marker `__reluBehaviourClass`. Do not override the marker.
@@ -248,21 +243,13 @@ declare class Behaviour implements CustomEcsSystem {
248
243
  /**
249
244
  * Called once before the first {@link Behaviour.onUpdate}. Override to
250
245
  * default and validate {@link Behaviour.data}, cache references, or set
251
- * initial state.
252
- *
253
- * @remarks
254
- * Also called in editor mode when `executeInEditor` is `true` on the script
255
- * entry.
246
+ * initial state. Runs at preview/runtime only — never in the editor.
256
247
  */
257
248
  protected init(): void;
258
249
  /**
259
250
  * Called every frame while the script is enabled. Override with the
260
- * script's main per-frame logic.
261
- *
262
- * @remarks
263
- * Also called every frame in editor mode when `executeInEditor` is `true`.
264
- * Access the Three.js scene with `this.world.getScene()` for editor-only
265
- * rendering work such as custom shaders or procedural geometry.
251
+ * script's main per-frame logic. Runs at preview/runtime only — never in the
252
+ * editor (use {@link ScriptObject} for editor-visible visuals).
266
253
  */
267
254
  protected onUpdate(): void;
268
255
  /** Called when the editor selects this entity. Optional UX hook. */
@@ -285,6 +272,105 @@ declare class Behaviour implements CustomEcsSystem {
285
272
  onTargetLost(target: WorldEntityView): void;
286
273
  }
287
274
 
275
+ /**
276
+ * Base class for **script objects** — entities whose THREE.js visual is built
277
+ * entirely by user code (procedural geometry, shaders, particle systems,
278
+ * anything the editor can't author natively).
279
+ *
280
+ * The critical difference from {@link Behaviour}: a `ScriptObject` runs in the
281
+ * **editor AND at runtime** — `build()` and `update()` execute identically in
282
+ * both. `ScriptObjectSystem` loads the module, instantiates the class, calls
283
+ * `build()` to get the visual, attaches it under the entity's Object3D, and
284
+ * ticks `update()` every frame. **Do NOT gate anything on
285
+ * `world.isEditorMode()`** — running everywhere is the whole point. Use
286
+ * {@link Behaviour} for gameplay logic that must NOT run in the editor.
287
+ *
288
+ * Subclasses are resolved by the inherited static marker
289
+ * `__reluScriptObjectClass` (survives bundler identity splits). Do not override
290
+ * the marker.
291
+ *
292
+ * @example
293
+ * ```ts
294
+ * import { ScriptObject, type ColorInput } from "@relu-interactives/spatial-ecs";
295
+ * import * as THREE from "three";
296
+ *
297
+ * export default class GlowOrb extends ScriptObject {
298
+ * declare data: { color: ColorInput };
299
+ * private mat!: THREE.MeshStandardMaterial;
300
+ *
301
+ * build(): THREE.Object3D {
302
+ * this.data.color ??= { type: "color", value: "#66ccff" };
303
+ * this.mat = new THREE.MeshStandardMaterial({
304
+ * color: this.data.color.value,
305
+ * emissive: this.data.color.value,
306
+ * });
307
+ * return new THREE.Mesh(new THREE.SphereGeometry(0.5, 32, 32), this.mat);
308
+ * }
309
+ *
310
+ * update(dt: number): void {
311
+ * this.mat.emissiveIntensity = 0.5 + 0.5 * Math.sin(performance.now() * 0.002);
312
+ * }
313
+ *
314
+ * dispose(): void {
315
+ * this.mat.dispose();
316
+ * }
317
+ * }
318
+ * ```
319
+ *
320
+ * @category Scripting
321
+ */
322
+ declare class ScriptObject {
323
+ /**
324
+ * Static marker used by `ScriptObjectSystem` to detect `ScriptObject`
325
+ * subclasses even when a bundler ships a second copy of the package into the
326
+ * script blob (breaking `instanceof`). Do NOT override.
327
+ */
328
+ static readonly __reluScriptObjectClass: true;
329
+ /**
330
+ * The script's data payload (the `ScriptObjectComponent.data`). Declare a
331
+ * concrete shape on subclasses with `declare data: MyShape` for type safety.
332
+ * Use the same typed input envelopes as Behaviours (`ColorInput`,
333
+ * `SliderInput`, `EntityInput`, …) to get inspector fields.
334
+ */
335
+ data: Record<string, unknown>;
336
+ /** The owning ECS world. */
337
+ world: World;
338
+ /** The entity this script object is bound to. */
339
+ entityId: number;
340
+ /**
341
+ * The Object3D returned by {@link ScriptObject.build}. Assigned by
342
+ * `ScriptObjectSystem` after `build()` runs; `null` until then.
343
+ */
344
+ root: THREE.Object3D | null;
345
+ /**
346
+ * Engine-managed constructor. `ScriptObjectSystem` instantiates subclasses
347
+ * with the owning world, the entity id, and the component's `data`. User code
348
+ * should not call this directly.
349
+ */
350
+ constructor(world: World, entityId: number, data?: Record<string, unknown>);
351
+ /**
352
+ * REQUIRED — build and return the visual root. Called once by
353
+ * `ScriptObjectSystem` after construction. The returned object is attached
354
+ * under the entity's Object3D (so it inherits the entity transform, selection
355
+ * and visibility). Subclasses MUST override.
356
+ */
357
+ build(): THREE.Object3D;
358
+ /**
359
+ * OPTIONAL — per-frame hook. Runs in the editor AND at runtime (e.g. advance
360
+ * a shader time uniform, procedural animation). Keep per-frame work on local
361
+ * THREE state / uniforms — do NOT write ECS components every frame (that
362
+ * churns the editor's undo history).
363
+ */
364
+ update?(deltaTime: number): void;
365
+ /**
366
+ * OPTIONAL — free any GPU resources this script created (geometries,
367
+ * materials, textures, render targets). Called by `ScriptObjectSystem` when
368
+ * the object is removed, disabled, or reloaded. THREE `dispose()` is
369
+ * idempotent, so double-dispose is safe.
370
+ */
371
+ dispose?(): void;
372
+ }
373
+
288
374
  type ComponentValueMaps = {
289
375
  object3DRefValues: Map<number, unknown>;
290
376
  nameValues: Map<number, unknown>;
@@ -306,6 +392,7 @@ type ComponentValueMaps = {
306
392
  animationValues: Map<number, unknown>;
307
393
  imageTargetAnchorValues: Map<number, unknown>;
308
394
  scriptValues: Map<number, unknown>;
395
+ scriptObjectValues: Map<number, unknown>;
309
396
  instancedMeshValues: Map<number, unknown>;
310
397
  instanceSlotValues: Map<number, unknown>;
311
398
  prefabNodeValues: Map<number, unknown>;
@@ -540,6 +627,8 @@ declare function indexSnapshotByEntity(snapshot: SubtreeSnapshot): Map<number, M
540
627
  * - entity-id fields → `{$node}` (internal) or raw id (external)
541
628
  * - ScriptComponent entries keep only `{className, scriptUrl, enabled, data}`
542
629
  * (entityId/runtimeState/runtimeMessage are per-instance transients)
630
+ * - ScriptObjectComponent keeps only `{scriptUrl, className, enabled, data}`
631
+ * (runtimeState/runtimeMessage are per-instance transients)
543
632
  * - Object3DRef keeps only `{visibility}` (the rest is a live object ref)
544
633
  *
545
634
  * Keep the id-bearing field list in sync with `snapshotIdUtils.ts`.
@@ -617,4 +706,4 @@ declare function serializeEntitySubtree(world: World, rootId: EntityId, options?
617
706
  maxDepth?: number;
618
707
  }): SerializeEntitySubtreeResult;
619
708
 
620
- export { ADDED_NODE_MARKER_COMPONENT, type ApplyPrefabToSnapshotResult, Behaviour, Component, type ComponentValueMaps, EcsEntityKind, EcsSystem, type EcsWorldComponentSnapshot, type EcsWorldStateSnapshotLike, EntityId, ExternalRefWarning, HYDRATABLE_ENTITY_KINDS, type HydrateOptions, type HydrateWorldFromSnapshotResult, type InstantiateSubtreeResult, NODE_KEY_SEPARATOR, type NestedRegion, type NodeKeyMaps, type NodeMaps, OVERRIDE_DIFF_EXCLUDED_COMPONENTS, OVERRIDE_ROOT_EXCLUDED_COMPONENTS, ObjectManagementSystem, ParentLookup, SHARED_MODEL_RESOURCE_FLAG, type SerializeEntitySubtreeResult, SpawnPrefabOptions, SpawnPrefabSource, SubtreeSnapshot, World, WorldEntityView, applyPrefabToSnapshotInstances, buildComponentValueMaps, buildNodeKeyMapsFromSnapshot, buildNodeMapsFromSnapshot, canonicalizeComponentValue, clearModelCache, collectDiffPaths, collectDirectPrefabDependencies, collectEntitySubtree, collectSnapshotSubtreeIds, computeInstanceOverrides, decanonicalizeComponentValue, encodeOverride, findSnapshotRootEntityIds, findTopLevelNestedRegions, groupOverridePaths, hydrateWorldFromSnapshot, hydrateWorldFromSnapshotDetailed, indexSnapshotByEntity, instantiateSubtree, loadSharedGltf, mergeComponentValue, parseOverride, resolveDracoDecoderPath, restoreComponentState, restorePostCreateComponents, serializeEntitySubtree, setDracoDecoderPath };
709
+ export { ADDED_NODE_MARKER_COMPONENT, type ApplyPrefabToSnapshotResult, Behaviour, Component, type ComponentValueMaps, EcsEntityKind, EcsSystem, type EcsWorldComponentSnapshot, type EcsWorldStateSnapshotLike, EntityId, ExternalRefWarning, HYDRATABLE_ENTITY_KINDS, type HydrateOptions, type HydrateWorldFromSnapshotResult, type InstantiateSubtreeResult, NODE_KEY_SEPARATOR, type NestedRegion, type NodeKeyMaps, type NodeMaps, OVERRIDE_DIFF_EXCLUDED_COMPONENTS, OVERRIDE_ROOT_EXCLUDED_COMPONENTS, ObjectManagementSystem, ParentLookup, SHARED_MODEL_RESOURCE_FLAG, ScriptObject, type SerializeEntitySubtreeResult, SpawnPrefabOptions, SpawnPrefabSource, SubtreeSnapshot, World, WorldEntityView, applyPrefabToSnapshotInstances, buildComponentValueMaps, buildNodeKeyMapsFromSnapshot, buildNodeMapsFromSnapshot, canonicalizeComponentValue, clearModelCache, collectDiffPaths, collectDirectPrefabDependencies, collectEntitySubtree, collectSnapshotSubtreeIds, computeInstanceOverrides, decanonicalizeComponentValue, encodeOverride, findSnapshotRootEntityIds, findTopLevelNestedRegions, groupOverridePaths, hydrateWorldFromSnapshot, hydrateWorldFromSnapshotDetailed, indexSnapshotByEntity, instantiateSubtree, loadSharedGltf, mergeComponentValue, parseOverride, resolveDracoDecoderPath, restoreComponentState, restorePostCreateComponents, serializeEntitySubtree, setDracoDecoderPath };
package/dist/index.d.ts CHANGED
@@ -1,11 +1,11 @@
1
- import { k as EcsSystem, C as Component, W as WorldEntityView, T as TransformComponent, l as World, S as SpawnPrefabSource, m as SpawnPrefabOptions, n as ComponentClass, o as ParentLookup, p as EcsEntityKind, O as ObjectManagementSystem, q as SubtreeSnapshot, r as EntityId, s as ExternalRefWarning } from './System-me3iAcMF.js';
2
- export { A as AssetInput, t as CheckboxInput, u as ColorInput, v as ComponentFactory, w as ComponentInput, x as ComponentKind, y as DropdownInput, z as DropdownOption, B as EcsComponentFactoryKind, F as EcsEntityEditorKind, G as EntityInput, H as FloatInput, I as InputSystem, J as IntersectionResult, K as KeyboardKey, L as KeyboardKeys, M as MouseButton, N as PREFAB_FILE_VERSION, Q as PREFAB_FILE_VERSION_NESTED, R as PrefabAsset, U as RemapSnapshotOptions, X as RenderSystem, Y as SelectionListener, Z as SliderInput, _ as TextInput, $ as ToggleInput, a0 as TransformSyncSystem, a1 as Vec3, a2 as Vector2Input, a3 as Vector3Input, a4 as clearPrefabCache, a5 as despawnPrefab, a6 as loadPrefab, a7 as parsePrefabAsset, a8 as prefabFileVersionFor, a9 as remapSnapshotEntityIds, aa as setPrefabAssetUrlResolver, ab as spawnPrefab } from './System-me3iAcMF.js';
1
+ import { k as EcsSystem, C as Component, W as WorldEntityView, T as TransformComponent, l as World, S as SpawnPrefabSource, m as SpawnPrefabOptions, n as ComponentClass, o as ParentLookup, p as EcsEntityKind, O as ObjectManagementSystem, q as SubtreeSnapshot, r as EntityId, s as ExternalRefWarning } from './System-CYWZ_Zx5.js';
2
+ export { A as AssetInput, t as CheckboxInput, u as ColorInput, v as ComponentFactory, w as ComponentInput, x as ComponentKind, y as DropdownInput, z as DropdownOption, B as EcsComponentFactoryKind, F as EcsEntityEditorKind, G as EntityInput, H as FloatInput, I as InputSystem, J as IntersectionResult, K as KeyboardKey, L as KeyboardKeys, M as MouseButton, N as PREFAB_FILE_VERSION, Q as PREFAB_FILE_VERSION_NESTED, R as PrefabAsset, U as RemapSnapshotOptions, X as RenderSystem, Y as SelectionListener, Z as SliderInput, _ as TextInput, $ as ToggleInput, a0 as TransformSyncSystem, a1 as Vec3, a2 as Vector2Input, a3 as Vector3Input, a4 as clearPrefabCache, a5 as despawnPrefab, a6 as loadPrefab, a7 as parsePrefabAsset, a8 as prefabFileVersionFor, a9 as remapSnapshotEntityIds, aa as setPrefabAssetUrlResolver, ab as spawnPrefab } from './System-CYWZ_Zx5.js';
3
3
  import * as THREE from 'three';
4
- import { O as Object3DRef } from './Video-DHnxjGhW.js';
5
- export { a3 as AnimationStateCallbacks, a4 as AnimationStateMachine, a5 as AnimationStateManager, a6 as StateMachine } from './Video-DHnxjGhW.js';
6
- export { i as CoreComponents } from './index-D7FSg0Au.js';
7
- export { AnimationSystem, AudioSystem, CameraSyncSystem, EnvironmentSyncSystem, InstancedMeshSystem, LightSyncSystem, MaterialSyncSystem, MeshGeometrySystem, ObjectVisibilitySystem, PhysicsSyncSystem, PostprocessingSyncSystem, ScriptBehaviourSystem, SelectionContext, VideoSystem } from './systems/index.js';
8
- export { createAnimationComponent, createAudioComponent, createCameraComponent, createEntityTypeComponent, createEnvironmentComponent, createImageComponent, createImageTargetAnchorComponent, createImageTargetComponent, createInstanceSlotComponent, createInstancedMeshComponent, createLightComponent, createMaterialComponent, createMeshComponent, createMeshGeometryComponent, createModelComponent, createNameComponent, createObject3DRefComponent, createParentIdComponent, createPhysicsComponent, createPostprocessingComponent, createScriptComponent, createSelectableComponent, createSelectionTransformStateComponent, createSpriteComponent, createTransformComponent, createVideoComponent, registerDefaultComponentFactories, registerDefaultFactories } from './factories/index.js';
4
+ import { O as Object3DRef } from './Video-C1IOat7L.js';
5
+ export { a6 as AnimationStateCallbacks, a7 as AnimationStateMachine, a8 as AnimationStateManager, a9 as StateMachine } from './Video-C1IOat7L.js';
6
+ export { i as CoreComponents } from './index-DdiWu1b6.js';
7
+ export { AnimationSystem, AudioSystem, CameraSyncSystem, EnvironmentSyncSystem, InstancedMeshSystem, LightSyncSystem, MaterialSyncSystem, MeshGeometrySystem, ModuleLoader, ObjectVisibilitySystem, PhysicsSyncSystem, PostprocessingSyncSystem, SCRIPT_OBJECT_ROOT_FLAG, ScriptBehaviourSystem, ScriptObjectSystem, SelectionContext, VideoSystem } from './systems/index.js';
8
+ export { createAnimationComponent, createAudioComponent, createCameraComponent, createEntityTypeComponent, createEnvironmentComponent, createImageComponent, createImageTargetAnchorComponent, createImageTargetComponent, createInstanceSlotComponent, createInstancedMeshComponent, createLightComponent, createMaterialComponent, createMeshComponent, createMeshGeometryComponent, createModelComponent, createNameComponent, createObject3DRefComponent, createParentIdComponent, createPhysicsComponent, createPostprocessingComponent, createScriptComponent, createScriptObjectComponent, createSelectableComponent, createSelectionTransformStateComponent, createSpriteComponent, createTransformComponent, createVideoComponent, registerDefaultComponentFactories, registerDefaultFactories } from './factories/index.js';
9
9
  import { GLTF } from 'three/examples/jsm/loaders/GLTFLoader.js';
10
10
  import '@dimforge/rapier3d-compat';
11
11
 
@@ -25,15 +25,10 @@ interface CustomEcsSystem extends EcsSystem {
25
25
  * Override {@link Behaviour.onUpdate} for per-frame logic — never override
26
26
  * {@link Behaviour.update}, which is the engine-managed entry point.
27
27
  *
28
- * **Editor scripts**: By default, `Behaviour` subclasses do not run inside the
29
- * editor. Set `executeInEditor: true` on the script entry in the inspector to
30
- * enable the full lifecycle (`init` → `onUpdate` → `dispose`) while the editor
31
- * is open. This gives direct access to the Three.js scene, camera, and renderer
32
- * via {@link World.getScene}, {@link World.getCamera}, and
33
- * {@link World.getRenderer} — useful for custom shaders, procedural geometry,
34
- * grass, and any Three.js feature the editor's object palette does not expose.
35
- * Avoid mutating ECS component state every frame in editor mode, as it creates
36
- * undo history entries on every tick.
28
+ * **Editor vs runtime**: `Behaviour` subclasses run ONLY at preview/runtime —
29
+ * they never execute in the editor. For a visual that must render and animate
30
+ * inside the editor (custom shaders, procedural geometry, grass, anything the
31
+ * object palette can't produce), use {@link ScriptObject} instead.
37
32
  *
38
33
  * The runtime recognizes a script by its **default export** plus the
39
34
  * inherited static marker `__reluBehaviourClass`. Do not override the marker.
@@ -248,21 +243,13 @@ declare class Behaviour implements CustomEcsSystem {
248
243
  /**
249
244
  * Called once before the first {@link Behaviour.onUpdate}. Override to
250
245
  * default and validate {@link Behaviour.data}, cache references, or set
251
- * initial state.
252
- *
253
- * @remarks
254
- * Also called in editor mode when `executeInEditor` is `true` on the script
255
- * entry.
246
+ * initial state. Runs at preview/runtime only — never in the editor.
256
247
  */
257
248
  protected init(): void;
258
249
  /**
259
250
  * Called every frame while the script is enabled. Override with the
260
- * script's main per-frame logic.
261
- *
262
- * @remarks
263
- * Also called every frame in editor mode when `executeInEditor` is `true`.
264
- * Access the Three.js scene with `this.world.getScene()` for editor-only
265
- * rendering work such as custom shaders or procedural geometry.
251
+ * script's main per-frame logic. Runs at preview/runtime only — never in the
252
+ * editor (use {@link ScriptObject} for editor-visible visuals).
266
253
  */
267
254
  protected onUpdate(): void;
268
255
  /** Called when the editor selects this entity. Optional UX hook. */
@@ -285,6 +272,105 @@ declare class Behaviour implements CustomEcsSystem {
285
272
  onTargetLost(target: WorldEntityView): void;
286
273
  }
287
274
 
275
+ /**
276
+ * Base class for **script objects** — entities whose THREE.js visual is built
277
+ * entirely by user code (procedural geometry, shaders, particle systems,
278
+ * anything the editor can't author natively).
279
+ *
280
+ * The critical difference from {@link Behaviour}: a `ScriptObject` runs in the
281
+ * **editor AND at runtime** — `build()` and `update()` execute identically in
282
+ * both. `ScriptObjectSystem` loads the module, instantiates the class, calls
283
+ * `build()` to get the visual, attaches it under the entity's Object3D, and
284
+ * ticks `update()` every frame. **Do NOT gate anything on
285
+ * `world.isEditorMode()`** — running everywhere is the whole point. Use
286
+ * {@link Behaviour} for gameplay logic that must NOT run in the editor.
287
+ *
288
+ * Subclasses are resolved by the inherited static marker
289
+ * `__reluScriptObjectClass` (survives bundler identity splits). Do not override
290
+ * the marker.
291
+ *
292
+ * @example
293
+ * ```ts
294
+ * import { ScriptObject, type ColorInput } from "@relu-interactives/spatial-ecs";
295
+ * import * as THREE from "three";
296
+ *
297
+ * export default class GlowOrb extends ScriptObject {
298
+ * declare data: { color: ColorInput };
299
+ * private mat!: THREE.MeshStandardMaterial;
300
+ *
301
+ * build(): THREE.Object3D {
302
+ * this.data.color ??= { type: "color", value: "#66ccff" };
303
+ * this.mat = new THREE.MeshStandardMaterial({
304
+ * color: this.data.color.value,
305
+ * emissive: this.data.color.value,
306
+ * });
307
+ * return new THREE.Mesh(new THREE.SphereGeometry(0.5, 32, 32), this.mat);
308
+ * }
309
+ *
310
+ * update(dt: number): void {
311
+ * this.mat.emissiveIntensity = 0.5 + 0.5 * Math.sin(performance.now() * 0.002);
312
+ * }
313
+ *
314
+ * dispose(): void {
315
+ * this.mat.dispose();
316
+ * }
317
+ * }
318
+ * ```
319
+ *
320
+ * @category Scripting
321
+ */
322
+ declare class ScriptObject {
323
+ /**
324
+ * Static marker used by `ScriptObjectSystem` to detect `ScriptObject`
325
+ * subclasses even when a bundler ships a second copy of the package into the
326
+ * script blob (breaking `instanceof`). Do NOT override.
327
+ */
328
+ static readonly __reluScriptObjectClass: true;
329
+ /**
330
+ * The script's data payload (the `ScriptObjectComponent.data`). Declare a
331
+ * concrete shape on subclasses with `declare data: MyShape` for type safety.
332
+ * Use the same typed input envelopes as Behaviours (`ColorInput`,
333
+ * `SliderInput`, `EntityInput`, …) to get inspector fields.
334
+ */
335
+ data: Record<string, unknown>;
336
+ /** The owning ECS world. */
337
+ world: World;
338
+ /** The entity this script object is bound to. */
339
+ entityId: number;
340
+ /**
341
+ * The Object3D returned by {@link ScriptObject.build}. Assigned by
342
+ * `ScriptObjectSystem` after `build()` runs; `null` until then.
343
+ */
344
+ root: THREE.Object3D | null;
345
+ /**
346
+ * Engine-managed constructor. `ScriptObjectSystem` instantiates subclasses
347
+ * with the owning world, the entity id, and the component's `data`. User code
348
+ * should not call this directly.
349
+ */
350
+ constructor(world: World, entityId: number, data?: Record<string, unknown>);
351
+ /**
352
+ * REQUIRED — build and return the visual root. Called once by
353
+ * `ScriptObjectSystem` after construction. The returned object is attached
354
+ * under the entity's Object3D (so it inherits the entity transform, selection
355
+ * and visibility). Subclasses MUST override.
356
+ */
357
+ build(): THREE.Object3D;
358
+ /**
359
+ * OPTIONAL — per-frame hook. Runs in the editor AND at runtime (e.g. advance
360
+ * a shader time uniform, procedural animation). Keep per-frame work on local
361
+ * THREE state / uniforms — do NOT write ECS components every frame (that
362
+ * churns the editor's undo history).
363
+ */
364
+ update?(deltaTime: number): void;
365
+ /**
366
+ * OPTIONAL — free any GPU resources this script created (geometries,
367
+ * materials, textures, render targets). Called by `ScriptObjectSystem` when
368
+ * the object is removed, disabled, or reloaded. THREE `dispose()` is
369
+ * idempotent, so double-dispose is safe.
370
+ */
371
+ dispose?(): void;
372
+ }
373
+
288
374
  type ComponentValueMaps = {
289
375
  object3DRefValues: Map<number, unknown>;
290
376
  nameValues: Map<number, unknown>;
@@ -306,6 +392,7 @@ type ComponentValueMaps = {
306
392
  animationValues: Map<number, unknown>;
307
393
  imageTargetAnchorValues: Map<number, unknown>;
308
394
  scriptValues: Map<number, unknown>;
395
+ scriptObjectValues: Map<number, unknown>;
309
396
  instancedMeshValues: Map<number, unknown>;
310
397
  instanceSlotValues: Map<number, unknown>;
311
398
  prefabNodeValues: Map<number, unknown>;
@@ -540,6 +627,8 @@ declare function indexSnapshotByEntity(snapshot: SubtreeSnapshot): Map<number, M
540
627
  * - entity-id fields → `{$node}` (internal) or raw id (external)
541
628
  * - ScriptComponent entries keep only `{className, scriptUrl, enabled, data}`
542
629
  * (entityId/runtimeState/runtimeMessage are per-instance transients)
630
+ * - ScriptObjectComponent keeps only `{scriptUrl, className, enabled, data}`
631
+ * (runtimeState/runtimeMessage are per-instance transients)
543
632
  * - Object3DRef keeps only `{visibility}` (the rest is a live object ref)
544
633
  *
545
634
  * Keep the id-bearing field list in sync with `snapshotIdUtils.ts`.
@@ -617,4 +706,4 @@ declare function serializeEntitySubtree(world: World, rootId: EntityId, options?
617
706
  maxDepth?: number;
618
707
  }): SerializeEntitySubtreeResult;
619
708
 
620
- export { ADDED_NODE_MARKER_COMPONENT, type ApplyPrefabToSnapshotResult, Behaviour, Component, type ComponentValueMaps, EcsEntityKind, EcsSystem, type EcsWorldComponentSnapshot, type EcsWorldStateSnapshotLike, EntityId, ExternalRefWarning, HYDRATABLE_ENTITY_KINDS, type HydrateOptions, type HydrateWorldFromSnapshotResult, type InstantiateSubtreeResult, NODE_KEY_SEPARATOR, type NestedRegion, type NodeKeyMaps, type NodeMaps, OVERRIDE_DIFF_EXCLUDED_COMPONENTS, OVERRIDE_ROOT_EXCLUDED_COMPONENTS, ObjectManagementSystem, ParentLookup, SHARED_MODEL_RESOURCE_FLAG, type SerializeEntitySubtreeResult, SpawnPrefabOptions, SpawnPrefabSource, SubtreeSnapshot, World, WorldEntityView, applyPrefabToSnapshotInstances, buildComponentValueMaps, buildNodeKeyMapsFromSnapshot, buildNodeMapsFromSnapshot, canonicalizeComponentValue, clearModelCache, collectDiffPaths, collectDirectPrefabDependencies, collectEntitySubtree, collectSnapshotSubtreeIds, computeInstanceOverrides, decanonicalizeComponentValue, encodeOverride, findSnapshotRootEntityIds, findTopLevelNestedRegions, groupOverridePaths, hydrateWorldFromSnapshot, hydrateWorldFromSnapshotDetailed, indexSnapshotByEntity, instantiateSubtree, loadSharedGltf, mergeComponentValue, parseOverride, resolveDracoDecoderPath, restoreComponentState, restorePostCreateComponents, serializeEntitySubtree, setDracoDecoderPath };
709
+ export { ADDED_NODE_MARKER_COMPONENT, type ApplyPrefabToSnapshotResult, Behaviour, Component, type ComponentValueMaps, EcsEntityKind, EcsSystem, type EcsWorldComponentSnapshot, type EcsWorldStateSnapshotLike, EntityId, ExternalRefWarning, HYDRATABLE_ENTITY_KINDS, type HydrateOptions, type HydrateWorldFromSnapshotResult, type InstantiateSubtreeResult, NODE_KEY_SEPARATOR, type NestedRegion, type NodeKeyMaps, type NodeMaps, OVERRIDE_DIFF_EXCLUDED_COMPONENTS, OVERRIDE_ROOT_EXCLUDED_COMPONENTS, ObjectManagementSystem, ParentLookup, SHARED_MODEL_RESOURCE_FLAG, ScriptObject, type SerializeEntitySubtreeResult, SpawnPrefabOptions, SpawnPrefabSource, SubtreeSnapshot, World, WorldEntityView, applyPrefabToSnapshotInstances, buildComponentValueMaps, buildNodeKeyMapsFromSnapshot, buildNodeMapsFromSnapshot, canonicalizeComponentValue, clearModelCache, collectDiffPaths, collectDirectPrefabDependencies, collectEntitySubtree, collectSnapshotSubtreeIds, computeInstanceOverrides, decanonicalizeComponentValue, encodeOverride, findSnapshotRootEntityIds, findTopLevelNestedRegions, groupOverridePaths, hydrateWorldFromSnapshot, hydrateWorldFromSnapshotDetailed, indexSnapshotByEntity, instantiateSubtree, loadSharedGltf, mergeComponentValue, parseOverride, resolveDracoDecoderPath, restoreComponentState, restorePostCreateComponents, serializeEntitySubtree, setDracoDecoderPath };
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
- import { MeshGeometrySystem, InstancedMeshSystem, EnvironmentSyncSystem, PostprocessingSyncSystem, LightSyncSystem, MaterialSyncSystem, PhysicsSyncSystem, AnimationSystem, AudioSystem, VideoSystem, CameraSyncSystem, TransformSyncSystem, ObjectVisibilitySystem, RenderSystem, spawnPrefab, despawnPrefab, buildNodeKeyMapsFromSnapshot, indexSnapshotByEntity, findTopLevelNestedRegions, collectSnapshotSubtreeIds, groupOverridePaths, OVERRIDE_DIFF_EXCLUDED_COMPONENTS, OVERRIDE_ROOT_EXCLUDED_COMPONENTS, canonicalizeComponentValue, mergeComponentValue, decanonicalizeComponentValue, computeInstanceOverrides, collectEntitySubtree, ADDED_NODE_MARKER_COMPONENT } from './chunk-5U3YS4JD.js';
2
- export { ADDED_NODE_MARKER_COMPONENT, AnimationSystem, AudioSystem, Behaviour, CameraSyncSystem, EnvironmentSyncSystem, HYDRATABLE_ENTITY_KINDS, InputSystem, InstancedMeshSystem, KeyboardKeys, LightSyncSystem, MaterialSyncSystem, MeshGeometrySystem, NODE_KEY_SEPARATOR, OVERRIDE_DIFF_EXCLUDED_COMPONENTS, OVERRIDE_ROOT_EXCLUDED_COMPONENTS, ObjectVisibilitySystem, PREFAB_FILE_VERSION, PREFAB_FILE_VERSION_NESTED, PhysicsSyncSystem, PostprocessingSyncSystem, RenderSystem, ScriptBehaviourSystem, TransformSyncSystem, VideoSystem, buildComponentValueMaps, buildNodeKeyMapsFromSnapshot, buildNodeMapsFromSnapshot, canonicalizeComponentValue, clearPrefabCache, collectDiffPaths, collectEntitySubtree, collectSnapshotSubtreeIds, computeInstanceOverrides, decanonicalizeComponentValue, despawnPrefab, encodeOverride, findSnapshotRootEntityIds, findTopLevelNestedRegions, groupOverridePaths, hydrateWorldFromSnapshot, hydrateWorldFromSnapshotDetailed, indexSnapshotByEntity, instantiateSubtree, loadPrefab, mergeComponentValue, parseOverride, parsePrefabAsset, prefabFileVersionFor, restoreComponentState, restorePostCreateComponents, setPrefabAssetUrlResolver, spawnPrefab } from './chunk-5U3YS4JD.js';
3
- import { registerDefaultFactories } from './chunk-K6KMKKJ6.js';
4
- export { createAnimationComponent, createAudioComponent, createCameraComponent, createEntityTypeComponent, createEnvironmentComponent, createImageComponent, createImageTargetAnchorComponent, createImageTargetComponent, createInstanceSlotComponent, createInstancedMeshComponent, createLightComponent, createMaterialComponent, createMeshComponent, createMeshGeometryComponent, createModelComponent, createNameComponent, createObject3DRefComponent, createParentIdComponent, createPhysicsComponent, createPostprocessingComponent, createScriptComponent, createSelectableComponent, createSelectionTransformStateComponent, createSpriteComponent, createTransformComponent, createVideoComponent, registerDefaultComponentFactories, registerDefaultFactories } from './chunk-K6KMKKJ6.js';
5
- import { ObjectManagementSystem } from './chunk-AXRCGF63.js';
6
- export { ObjectManagementSystem, SHARED_MODEL_RESOURCE_FLAG, clearModelCache, loadSharedGltf, resolveDracoDecoderPath, setDracoDecoderPath } from './chunk-AXRCGF63.js';
7
- import { SelectionTransformState, Object3DRef, Name, EntityType, ParentId, Environment, Postprocessing, ScriptComponent } from './chunk-V7BNVTJW.js';
8
- export { AnimationStateMachine, AnimationStateManager, components_exports as CoreComponents } from './chunk-V7BNVTJW.js';
1
+ import { MeshGeometrySystem, InstancedMeshSystem, EnvironmentSyncSystem, PostprocessingSyncSystem, LightSyncSystem, MaterialSyncSystem, PhysicsSyncSystem, AnimationSystem, AudioSystem, VideoSystem, CameraSyncSystem, TransformSyncSystem, ObjectVisibilitySystem, RenderSystem, spawnPrefab, despawnPrefab, buildNodeKeyMapsFromSnapshot, indexSnapshotByEntity, findTopLevelNestedRegions, collectSnapshotSubtreeIds, groupOverridePaths, OVERRIDE_DIFF_EXCLUDED_COMPONENTS, OVERRIDE_ROOT_EXCLUDED_COMPONENTS, canonicalizeComponentValue, mergeComponentValue, decanonicalizeComponentValue, computeInstanceOverrides, collectEntitySubtree, ADDED_NODE_MARKER_COMPONENT } from './chunk-7BEZBIVB.js';
2
+ export { ADDED_NODE_MARKER_COMPONENT, AnimationSystem, AudioSystem, Behaviour, CameraSyncSystem, EnvironmentSyncSystem, HYDRATABLE_ENTITY_KINDS, InputSystem, InstancedMeshSystem, KeyboardKeys, LightSyncSystem, MaterialSyncSystem, MeshGeometrySystem, NODE_KEY_SEPARATOR, OVERRIDE_DIFF_EXCLUDED_COMPONENTS, OVERRIDE_ROOT_EXCLUDED_COMPONENTS, ObjectVisibilitySystem, PREFAB_FILE_VERSION, PREFAB_FILE_VERSION_NESTED, PhysicsSyncSystem, PostprocessingSyncSystem, RenderSystem, SCRIPT_OBJECT_ROOT_FLAG, ScriptBehaviourSystem, ScriptObject, ScriptObjectSystem, TransformSyncSystem, VideoSystem, buildComponentValueMaps, buildNodeKeyMapsFromSnapshot, buildNodeMapsFromSnapshot, canonicalizeComponentValue, clearPrefabCache, collectDiffPaths, collectEntitySubtree, collectSnapshotSubtreeIds, computeInstanceOverrides, decanonicalizeComponentValue, despawnPrefab, encodeOverride, findSnapshotRootEntityIds, findTopLevelNestedRegions, groupOverridePaths, hydrateWorldFromSnapshot, hydrateWorldFromSnapshotDetailed, indexSnapshotByEntity, instantiateSubtree, loadPrefab, mergeComponentValue, parseOverride, parsePrefabAsset, prefabFileVersionFor, restoreComponentState, restorePostCreateComponents, setPrefabAssetUrlResolver, spawnPrefab } from './chunk-7BEZBIVB.js';
3
+ import { registerDefaultFactories } from './chunk-52CHDPRQ.js';
4
+ export { createAnimationComponent, createAudioComponent, createCameraComponent, createEntityTypeComponent, createEnvironmentComponent, createImageComponent, createImageTargetAnchorComponent, createImageTargetComponent, createInstanceSlotComponent, createInstancedMeshComponent, createLightComponent, createMaterialComponent, createMeshComponent, createMeshGeometryComponent, createModelComponent, createNameComponent, createObject3DRefComponent, createParentIdComponent, createPhysicsComponent, createPostprocessingComponent, createScriptComponent, createScriptObjectComponent, createSelectableComponent, createSelectionTransformStateComponent, createSpriteComponent, createTransformComponent, createVideoComponent, registerDefaultComponentFactories, registerDefaultFactories } from './chunk-52CHDPRQ.js';
5
+ import { ObjectManagementSystem } from './chunk-WKGCC7YL.js';
6
+ export { ObjectManagementSystem, SHARED_MODEL_RESOURCE_FLAG, clearModelCache, loadSharedGltf, resolveDracoDecoderPath, setDracoDecoderPath } from './chunk-WKGCC7YL.js';
7
+ import { SelectionTransformState, Object3DRef, Name, EntityType, ParentId, Environment, Postprocessing, ScriptComponent } from './chunk-JHCPRVBC.js';
8
+ export { AnimationStateMachine, AnimationStateManager, components_exports as CoreComponents } from './chunk-JHCPRVBC.js';
9
9
  import './chunk-QHILSPT4.js';
10
10
  import { normalizeDebugValue, DEBUG_CHANGE_IGNORED_SYSTEMS, cloneHistoryValue } from './chunk-ZXGHKX7N.js';
11
11
  import { __name } from './chunk-OY7ZODZP.js';
@@ -1037,6 +1037,11 @@ function remapSnapshotEntityIds(snapshot, idMap, options) {
1037
1037
  };
1038
1038
  });
1039
1039
  }
1040
+ } else if (block.component === "ScriptObjectComponent" && record) {
1041
+ const data = asRecord(record.data);
1042
+ if (data) {
1043
+ record.data = remapScriptData(data, idMap, nullExternal, warn);
1044
+ }
1040
1045
  } else if (block.component === "InstancedMeshComponent" && record) {
1041
1046
  if (Array.isArray(record.instanceEntityIds)) {
1042
1047
  const remapped = [];