@relu-interactives/spatial-ecs 0.2.17 → 0.2.20

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 (54) hide show
  1. package/dist/{System-BeuJ1xt5.d.cts → System-BjwOBx81.d.cts} +146 -1
  2. package/dist/{System-BeuJ1xt5.d.ts → System-BjwOBx81.d.ts} +146 -1
  3. package/dist/{Video-D4B-z74P.d.cts → Video-B8yVI1tF.d.cts} +17 -3
  4. package/dist/{Video-Cym2C52L.d.ts → Video-B9z5AtIf.d.ts} +17 -3
  5. package/dist/{chunk-EPK6MA7X.js → chunk-67MFQDHX.js} +1646 -8
  6. package/dist/chunk-67MFQDHX.js.map +1 -0
  7. package/dist/{chunk-GRUK5TNL.js → chunk-DY4ETMP2.js} +3 -3
  8. package/dist/{chunk-GRUK5TNL.js.map → chunk-DY4ETMP2.js.map} +1 -1
  9. package/dist/{chunk-CJW6K3CL.js → chunk-HUHN6IFD.js} +62 -5
  10. package/dist/chunk-HUHN6IFD.js.map +1 -0
  11. package/dist/{chunk-FTIQQK62.js → chunk-Z6OMYEXU.js} +42 -3
  12. package/dist/chunk-Z6OMYEXU.js.map +1 -0
  13. package/dist/{chunk-R2WMVXZZ.js → chunk-ZXGHKX7N.js} +5 -3
  14. package/dist/chunk-ZXGHKX7N.js.map +1 -0
  15. package/dist/components/index.cjs +39 -0
  16. package/dist/components/index.cjs.map +1 -1
  17. package/dist/components/index.d.cts +3 -2
  18. package/dist/components/index.d.ts +3 -2
  19. package/dist/components/index.js +1 -1
  20. package/dist/docs/guide/components/material.md +4 -0
  21. package/dist/docs/guide/components/physics.md +10 -0
  22. package/dist/docs/guide/getting-started/editor/assets-browser.md +1 -1
  23. package/dist/docs/guide/prefabs.md +133 -0
  24. package/dist/docs/guide/world-api.md +1 -1
  25. package/dist/factories/index.cjs +136 -64
  26. package/dist/factories/index.cjs.map +1 -1
  27. package/dist/factories/index.d.cts +5 -4
  28. package/dist/factories/index.d.ts +5 -4
  29. package/dist/factories/index.js +3 -3
  30. package/dist/{index-BoJ3_6a3.d.ts → index-BBI2YdCu.d.ts} +60 -4
  31. package/dist/{index-BfoOC2CG.d.cts → index-LHLKpJhZ.d.cts} +60 -4
  32. package/dist/index.cjs +5978 -4972
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.d.cts +215 -7
  35. package/dist/index.d.ts +215 -7
  36. package/dist/index.js +203 -960
  37. package/dist/index.js.map +1 -1
  38. package/dist/systems/index.cjs +1367 -0
  39. package/dist/systems/index.cjs.map +1 -1
  40. package/dist/systems/index.d.cts +2 -2
  41. package/dist/systems/index.d.ts +2 -2
  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.cjs +3 -1
  46. package/dist/worldSnapshotUtils.cjs.map +1 -1
  47. package/dist/worldSnapshotUtils.d.cts +1 -1
  48. package/dist/worldSnapshotUtils.d.ts +1 -1
  49. package/dist/worldSnapshotUtils.js +1 -1
  50. package/package.json +4 -2
  51. package/dist/chunk-CJW6K3CL.js.map +0 -1
  52. package/dist/chunk-EPK6MA7X.js.map +0 -1
  53. package/dist/chunk-FTIQQK62.js.map +0 -1
  54. package/dist/chunk-R2WMVXZZ.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,13 +1,13 @@
1
- import { MeshGeometrySystem, InstancedMeshSystem, EnvironmentSyncSystem, PostprocessingSyncSystem, LightSyncSystem, MaterialSyncSystem, PhysicsSyncSystem, AnimationSystem, AudioSystem, VideoSystem, CameraSyncSystem, TransformSyncSystem, ObjectVisibilitySystem, RenderSystem } from './chunk-EPK6MA7X.js';
2
- export { AnimationSystem, AudioSystem, Behaviour, CameraSyncSystem, EnvironmentSyncSystem, InputSystem, InstancedMeshSystem, KeyboardKeys, LightSyncSystem, MaterialSyncSystem, MeshGeometrySystem, ObjectVisibilitySystem, PhysicsSyncSystem, PostprocessingSyncSystem, RenderSystem, ScriptBehaviourSystem, TransformSyncSystem, VideoSystem } from './chunk-EPK6MA7X.js';
3
- import { registerDefaultFactories } from './chunk-CJW6K3CL.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-CJW6K3CL.js';
5
- import { ObjectManagementSystem, applyTransform } from './chunk-GRUK5TNL.js';
6
- export { ObjectManagementSystem, SHARED_MODEL_RESOURCE_FLAG, clearModelCache, loadSharedGltf, resolveDracoDecoderPath, setDracoDecoderPath } from './chunk-GRUK5TNL.js';
7
- import { SelectionTransformState, Object3DRef, Name, EntityType, ParentId, Environment, Postprocessing, ScriptComponent, InstancedMeshComponent, InstanceSlotComponent, AnimationComponent, TransformComponent, ModelComponent, ImageComponent, SpriteComponent, VideoComponent, AudioComponent, CameraComponent, ImageTarget, LightComponent, MaterialComponent, MeshGeometryComponent, Selectable, PhysicsComponent } from './chunk-FTIQQK62.js';
8
- export { AnimationStateMachine, AnimationStateManager, components_exports as CoreComponents } from './chunk-FTIQQK62.js';
1
+ import { MeshGeometrySystem, InstancedMeshSystem, EnvironmentSyncSystem, PostprocessingSyncSystem, LightSyncSystem, MaterialSyncSystem, PhysicsSyncSystem, AnimationSystem, AudioSystem, VideoSystem, CameraSyncSystem, TransformSyncSystem, ObjectVisibilitySystem, RenderSystem, spawnPrefab, despawnPrefab, collectEntitySubtree } from './chunk-67MFQDHX.js';
2
+ export { AnimationSystem, AudioSystem, Behaviour, CameraSyncSystem, EnvironmentSyncSystem, HYDRATABLE_ENTITY_KINDS, InputSystem, InstancedMeshSystem, KeyboardKeys, LightSyncSystem, MaterialSyncSystem, MeshGeometrySystem, OVERRIDE_DIFF_EXCLUDED_COMPONENTS, OVERRIDE_ROOT_EXCLUDED_COMPONENTS, ObjectVisibilitySystem, PREFAB_FILE_VERSION, PhysicsSyncSystem, PostprocessingSyncSystem, RenderSystem, ScriptBehaviourSystem, TransformSyncSystem, VideoSystem, buildComponentValueMaps, buildNodeMapsFromSnapshot, canonicalizeComponentValue, clearPrefabCache, collectDiffPaths, collectEntitySubtree, computeInstanceOverrides, decanonicalizeComponentValue, despawnPrefab, encodeOverride, findSnapshotRootEntityIds, groupOverridePaths, hydrateWorldFromSnapshot, hydrateWorldFromSnapshotDetailed, indexSnapshotByEntity, instantiateSubtree, loadPrefab, mergeComponentValue, parseOverride, parsePrefabAsset, restoreComponentState, restorePostCreateComponents, setPrefabAssetUrlResolver, spawnPrefab } from './chunk-67MFQDHX.js';
3
+ import { registerDefaultFactories } from './chunk-HUHN6IFD.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-HUHN6IFD.js';
5
+ import { ObjectManagementSystem } from './chunk-DY4ETMP2.js';
6
+ export { ObjectManagementSystem, SHARED_MODEL_RESOURCE_FLAG, clearModelCache, loadSharedGltf, resolveDracoDecoderPath, setDracoDecoderPath } from './chunk-DY4ETMP2.js';
7
+ import { SelectionTransformState, Object3DRef, Name, EntityType, ParentId, Environment, Postprocessing, ScriptComponent } from './chunk-Z6OMYEXU.js';
8
+ export { AnimationStateMachine, AnimationStateManager, components_exports as CoreComponents } from './chunk-Z6OMYEXU.js';
9
9
  import './chunk-QHILSPT4.js';
10
- import { normalizeDebugValue, DEBUG_CHANGE_IGNORED_SYSTEMS, cloneHistoryValue } from './chunk-R2WMVXZZ.js';
10
+ import { normalizeDebugValue, DEBUG_CHANGE_IGNORED_SYSTEMS, cloneHistoryValue } from './chunk-ZXGHKX7N.js';
11
11
  import { __name } from './chunk-OY7ZODZP.js';
12
12
  export { Component } from './chunk-OY7ZODZP.js';
13
13
  import * as THREE from 'three';
@@ -574,6 +574,18 @@ var _World = class _World {
574
574
  }
575
575
  return this.getEntityById(parentIdComponent.value);
576
576
  }
577
+ /**
578
+ * Instantiate a prefab asset into this world at runtime — see
579
+ * {@link spawnPrefab}. Convenience wrapper so scripts and embedding apps
580
+ * can spawn without reaching for the object management system.
581
+ */
582
+ spawnPrefab(source, options) {
583
+ return spawnPrefab(this, source, options);
584
+ }
585
+ /** Remove a spawned prefab instance (root + descendants). */
586
+ despawnPrefab(rootEntityId) {
587
+ return despawnPrefab(this, rootEntityId);
588
+ }
577
589
  getObjectManagementSystem() {
578
590
  if (this.objectManagementSystem) return this.objectManagementSystem;
579
591
  const objectManagementSystem = this.systems.find(
@@ -847,6 +859,33 @@ var _World = class _World {
847
859
  getDebugSignature(maxDepth = 3) {
848
860
  return JSON.stringify(this.getDebugSnapshot(maxDepth));
849
861
  }
862
+ /**
863
+ * Serialize ONLY the given entities into the same columnar
864
+ * `{entities, components}` shape as {@link getDebugSnapshot} (no systems,
865
+ * no selection). Used by prefab/scene subtree serialization.
866
+ */
867
+ getEntitiesSnapshot(entityIds, maxDepth = 10) {
868
+ const idSet = new Set(entityIds);
869
+ const components = [...this.components.entries()].map(([componentClass, store]) => {
870
+ return {
871
+ component: componentClass.name,
872
+ entries: [...store.entries()].filter(([entityId]) => idSet.has(entityId)).map(([entityId, component]) => {
873
+ return {
874
+ entityId,
875
+ value: normalizeDebugValue(component, {
876
+ seen: /* @__PURE__ */ new WeakSet(),
877
+ depth: 0,
878
+ maxDepth
879
+ })
880
+ };
881
+ }).sort((a, b) => a.entityId - b.entityId)
882
+ };
883
+ }).filter(({ entries }) => entries.length > 0).sort((a, b) => a.component.localeCompare(b.component));
884
+ return {
885
+ entities: [...this.entities].filter((entityId) => idSet.has(entityId)).sort((a, b) => a - b),
886
+ components
887
+ };
888
+ }
850
889
  createHistorySnapshot() {
851
890
  return {
852
891
  selectedEntityId: this.getSelectedEntity(),
@@ -905,980 +944,184 @@ var _World = class _World {
905
944
  __name(_World, "World");
906
945
  var World = _World;
907
946
 
908
- // core/hydration/readers.ts
909
- function asRecord(value) {
910
- if (!value || typeof value !== "object") {
911
- return null;
912
- }
913
- return value;
914
- }
915
- __name(asRecord, "asRecord");
916
- function readString(value) {
917
- if (typeof value === "string") {
918
- return value;
919
- }
920
- const record = asRecord(value);
921
- if (!record) {
922
- return null;
923
- }
924
- return typeof record.value === "string" ? record.value : null;
925
- }
926
- __name(readString, "readString");
927
- function readTransform(value) {
928
- const record = asRecord(value);
929
- if (!record) {
930
- return void 0;
931
- }
932
- const position = asRecord(record.position);
933
- const rotation = asRecord(record.rotation);
934
- const scale = asRecord(record.scale);
935
- return {
936
- position: position ? {
937
- x: typeof position.x === "number" ? position.x : void 0,
938
- y: typeof position.y === "number" ? position.y : void 0,
939
- z: typeof position.z === "number" ? position.z : void 0
940
- } : void 0,
941
- rotation: rotation ? {
942
- x: typeof rotation.x === "number" ? rotation.x : void 0,
943
- y: typeof rotation.y === "number" ? rotation.y : void 0,
944
- z: typeof rotation.z === "number" ? rotation.z : void 0
945
- } : void 0,
946
- scale: scale ? {
947
- x: typeof scale.x === "number" ? scale.x : void 0,
948
- y: typeof scale.y === "number" ? scale.y : void 0,
949
- z: typeof scale.z === "number" ? scale.z : void 0
950
- } : void 0
951
- };
952
- }
953
- __name(readTransform, "readTransform");
954
- function readByComponent(components, componentName) {
955
- const component = components.find((entry) => entry.component === componentName);
956
- const map = /* @__PURE__ */ new Map();
957
- if (!component) {
958
- return map;
959
- }
960
- for (const entry of component.entries) {
961
- map.set(entry.entityId, entry.value);
962
- }
963
- return map;
964
- }
965
- __name(readByComponent, "readByComponent");
966
- function readBoolean(value) {
967
- return typeof value === "boolean" ? value : void 0;
968
- }
969
- __name(readBoolean, "readBoolean");
970
- function readNumber(value) {
971
- return typeof value === "number" ? value : void 0;
972
- }
973
- __name(readNumber, "readNumber");
974
-
975
- // core/hydration/componentValues.ts
976
- function buildComponentValueMaps(snapshot) {
977
- return {
978
- object3DRefValues: readByComponent(snapshot.components, "Object3DRef"),
979
- nameValues: readByComponent(snapshot.components, "Name"),
980
- transformValues: readByComponent(snapshot.components, "TransformComponent"),
981
- modelValues: readByComponent(snapshot.components, "ModelComponent"),
982
- imageValues: readByComponent(snapshot.components, "ImageComponent"),
983
- spriteValues: readByComponent(snapshot.components, "SpriteComponent"),
984
- videoValues: readByComponent(snapshot.components, "VideoComponent"),
985
- cameraValues: readByComponent(snapshot.components, "CameraComponent"),
986
- environmentValues: readByComponent(snapshot.components, "Environment"),
987
- postprocessingValues: readByComponent(snapshot.components, "Postprocessing"),
988
- audioValues: readByComponent(snapshot.components, "AudioComponent"),
989
- imageTargetValues: readByComponent(snapshot.components, "ImageTarget"),
990
- lightValues: readByComponent(snapshot.components, "LightComponent"),
991
- materialValues: readByComponent(snapshot.components, "MaterialComponent"),
992
- meshGeometryValues: readByComponent(snapshot.components, "MeshGeometryComponent"),
993
- selectableValues: readByComponent(snapshot.components, "Selectable"),
994
- physicsValues: readByComponent(snapshot.components, "PhysicsComponent"),
995
- animationValues: readByComponent(snapshot.components, "AnimationComponent"),
996
- imageTargetAnchorValues: readByComponent(snapshot.components, "ImageTargetAnchor"),
997
- scriptValues: readByComponent(snapshot.components, "ScriptComponent"),
998
- instancedMeshValues: readByComponent(snapshot.components, "InstancedMeshComponent"),
999
- instanceSlotValues: readByComponent(snapshot.components, "InstanceSlotComponent")
1000
- };
1001
- }
1002
- __name(buildComponentValueMaps, "buildComponentValueMaps");
1003
-
1004
- // core/hydration/parentLinks.ts
1005
- function applyParentLinks(snapshot, idMap, objectManagementSystem, world) {
1006
- const parentValues = readByComponent(snapshot.components, "ParentId");
1007
- for (const [sourceEntityId, parentValue] of parentValues.entries()) {
1008
- const targetEntityId = idMap.get(sourceEntityId);
1009
- if (targetEntityId === void 0) {
947
+ // core/prefab/snapshotIdUtils.ts
948
+ var asRecord = /* @__PURE__ */ __name((value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : null, "asRecord");
949
+ function remapScriptData(data, idMap, nullExternal, onExternal) {
950
+ const result = {};
951
+ for (const [key, value] of Object.entries(data)) {
952
+ const record = asRecord(value);
953
+ if (!record) {
954
+ result[key] = value;
1010
955
  continue;
1011
956
  }
1012
- const parentRecord = asRecord(parentValue);
1013
- const sourceParentId = parentRecord && typeof parentRecord.value === "number" ? parentRecord.value : null;
1014
- if (sourceParentId === null) {
1015
- objectManagementSystem.setParent(world, targetEntityId, null, {
1016
- preserveWorldTransform: false
1017
- });
957
+ if (record.type === "entity" && typeof record.value === "number") {
958
+ const mapped = idMap.get(record.value);
959
+ if (mapped !== void 0) {
960
+ result[key] = { ...record, value: mapped };
961
+ } else {
962
+ onExternal(`data/${key}`, record.value);
963
+ result[key] = nullExternal ? { ...record, value: null } : value;
964
+ }
1018
965
  continue;
1019
966
  }
1020
- const mappedParentId = idMap.get(sourceParentId);
1021
- objectManagementSystem.setParent(world, targetEntityId, mappedParentId ?? null, {
1022
- preserveWorldTransform: false
1023
- });
1024
- }
1025
- }
1026
- __name(applyParentLinks, "applyParentLinks");
1027
-
1028
- // core/hydration/postCreateComponents.ts
1029
- function remapEntityRefsInScriptData(data, idMap) {
1030
- const result = {};
1031
- for (const [key, value] of Object.entries(data)) {
1032
- if (value !== null && typeof value === "object" && !Array.isArray(value)) {
1033
- const v = value;
1034
- if (v.type === "entity" && typeof v.value === "number") {
1035
- result[key] = { ...v, value: idMap.get(v.value) ?? v.value };
1036
- } else if (v.type === "component" && v.value !== null && typeof v.value === "object" && !Array.isArray(v.value) && typeof v.value.entityId === "number") {
1037
- const ref = v.value;
967
+ const componentRef = asRecord(record.value);
968
+ if (record.type === "component" && componentRef && typeof componentRef.entityId === "number") {
969
+ const mapped = idMap.get(componentRef.entityId);
970
+ if (mapped !== void 0) {
1038
971
  result[key] = {
1039
- ...v,
1040
- value: { ...ref, entityId: idMap.get(ref.entityId) ?? ref.entityId }
972
+ ...record,
973
+ value: { ...componentRef, entityId: mapped }
1041
974
  };
1042
975
  } else {
1043
- result[key] = value;
976
+ onExternal(`data/${key}`, componentRef.entityId);
977
+ result[key] = nullExternal ? { ...record, value: null } : value;
1044
978
  }
1045
- } else {
1046
- result[key] = value;
979
+ continue;
1047
980
  }
981
+ result[key] = value;
1048
982
  }
1049
983
  return result;
1050
984
  }
1051
- __name(remapEntityRefsInScriptData, "remapEntityRefsInScriptData");
1052
- function restorePostCreateComponents(world, objectManagementSystem, targetEntityId, sourceEntityId, entityType, values, idMap) {
1053
- const objectRef = world.getComponent(targetEntityId, Object3DRef)?.object ?? null;
1054
- const sourceAudio = asRecord(values.audioValues.get(sourceEntityId));
1055
- if (sourceAudio && entityType !== "audio") {
1056
- const sourceOptions = asRecord(sourceAudio.options) ?? {};
1057
- objectManagementSystem.createComponentNow(
1058
- "audio",
1059
- world,
1060
- targetEntityId,
1061
- typeof sourceAudio.path === "string" ? sourceAudio.path : "",
1062
- sourceOptions,
1063
- {
1064
- object: objectRef,
1065
- listener: objectManagementSystem.getOrCreateAudioListener(),
1066
- isEditor: objectManagementSystem.isEditorMode()
1067
- }
1068
- );
1069
- }
1070
- const sourceImageTarget = asRecord(values.imageTargetValues.get(sourceEntityId));
1071
- if (sourceImageTarget && entityType !== "imageTarget") {
1072
- objectManagementSystem.createComponentNow(
1073
- "imageTarget",
1074
- world,
1075
- targetEntityId,
1076
- {
1077
- targets: Array.isArray(sourceImageTarget.targets) ? sourceImageTarget.targets : [],
1078
- compiledTargetUrl: typeof sourceImageTarget.compiledTargetUrl === "string" ? sourceImageTarget.compiledTargetUrl : void 0,
1079
- compiledTargetDir: typeof sourceImageTarget.compiledTargetDir === "string" ? sourceImageTarget.compiledTargetDir : void 0
985
+ __name(remapScriptData, "remapScriptData");
986
+ function remapSnapshotEntityIds(snapshot, idMap, options) {
987
+ const nullExternal = options?.externalRefPolicy === "null";
988
+ const warnings = [];
989
+ const entities = snapshot.entities.map(
990
+ (entityId) => idMap.get(entityId) ?? entityId
991
+ );
992
+ const components = snapshot.components.map((block) => {
993
+ const entries = block.entries.map((entry) => {
994
+ const sourceEntityId = entry.entityId;
995
+ const mappedEntityId = idMap.get(sourceEntityId) ?? sourceEntityId;
996
+ const warn = /* @__PURE__ */ __name((path, targetId) => {
997
+ warnings.push({
998
+ entityId: sourceEntityId,
999
+ component: block.component,
1000
+ path,
1001
+ targetId
1002
+ });
1003
+ }, "warn");
1004
+ let value = structuredClone(entry.value);
1005
+ const record = asRecord(value);
1006
+ if (block.component === "ParentId" && record) {
1007
+ if (typeof record.value === "number") {
1008
+ const mapped = idMap.get(record.value);
1009
+ if (mapped !== void 0) {
1010
+ record.value = mapped;
1011
+ } else {
1012
+ warn("value", record.value);
1013
+ if (nullExternal) {
1014
+ record.value = null;
1015
+ }
1016
+ }
1017
+ }
1018
+ } else if (block.component === "ScriptComponent" && record) {
1019
+ if (Array.isArray(record.entries)) {
1020
+ record.entries = record.entries.map((rawEntry, index) => {
1021
+ const entryRecord = asRecord(rawEntry);
1022
+ if (!entryRecord) {
1023
+ return rawEntry;
1024
+ }
1025
+ const data = asRecord(entryRecord.data);
1026
+ if (!data) {
1027
+ return rawEntry;
1028
+ }
1029
+ return {
1030
+ ...entryRecord,
1031
+ data: remapScriptData(
1032
+ data,
1033
+ idMap,
1034
+ nullExternal,
1035
+ (path, target) => warn(`entries/${index}/${path}`, target)
1036
+ )
1037
+ };
1038
+ });
1039
+ }
1040
+ } else if (block.component === "InstancedMeshComponent" && record) {
1041
+ if (Array.isArray(record.instanceEntityIds)) {
1042
+ const remapped = [];
1043
+ record.instanceEntityIds.forEach((rawId, index) => {
1044
+ if (typeof rawId !== "number") {
1045
+ return;
1046
+ }
1047
+ const mapped = idMap.get(rawId);
1048
+ if (mapped !== void 0) {
1049
+ remapped.push(mapped);
1050
+ } else {
1051
+ warn(`instanceEntityIds/${index}`, rawId);
1052
+ if (!nullExternal) {
1053
+ remapped.push(rawId);
1054
+ }
1055
+ }
1056
+ });
1057
+ record.instanceEntityIds = remapped;
1058
+ }
1059
+ } else if (block.component === "InstanceSlotComponent" && record) {
1060
+ if (typeof record.groupEntityId === "number" && record.groupEntityId !== -1) {
1061
+ const mapped = idMap.get(record.groupEntityId);
1062
+ if (mapped !== void 0) {
1063
+ record.groupEntityId = mapped;
1064
+ } else {
1065
+ warn("groupEntityId", record.groupEntityId);
1066
+ if (nullExternal) {
1067
+ record.groupEntityId = -1;
1068
+ }
1069
+ }
1070
+ }
1080
1071
  }
1081
- );
1082
- }
1083
- const sourceImageTargetAnchor = asRecord(values.imageTargetAnchorValues.get(sourceEntityId));
1084
- if (sourceImageTargetAnchor) {
1085
- const mappedTargetId = typeof sourceImageTargetAnchor.targetId === "number" && Number.isFinite(sourceImageTargetAnchor.targetId) ? sourceImageTargetAnchor.targetId : null;
1086
- objectManagementSystem.createComponentNow("imageTargetAnchor", world, targetEntityId, {
1087
- targetId: mappedTargetId,
1088
- targetUrl: typeof sourceImageTargetAnchor.targetUrl === "string" ? sourceImageTargetAnchor.targetUrl : void 0
1072
+ value = record ?? value;
1073
+ return { entityId: mappedEntityId, value };
1089
1074
  });
1090
- }
1091
- const sourceScript = asRecord(values.scriptValues.get(sourceEntityId));
1092
- if (sourceScript) {
1093
- const entries = Array.isArray(sourceScript.entries) ? sourceScript.entries.map((entry) => asRecord(entry)).filter((entry) => Boolean(entry)).map((entry) => {
1094
- const runtimeState = entry.runtimeState === "idle" || entry.runtimeState === "loading" || entry.runtimeState === "ready" || entry.runtimeState === "error" ? entry.runtimeState : void 0;
1095
- return {
1096
- entityId: targetEntityId,
1097
- className: typeof entry.className === "string" ? entry.className : "",
1098
- scriptUrl: typeof entry.scriptUrl === "string" ? entry.scriptUrl : "",
1099
- enabled: typeof entry.enabled === "boolean" ? entry.enabled : true,
1100
- data: entry.data && typeof entry.data === "object" && !Array.isArray(entry.data) ? remapEntityRefsInScriptData(entry.data, idMap) : {},
1101
- runtimeState,
1102
- runtimeMessage: typeof entry.runtimeMessage === "string" ? entry.runtimeMessage : void 0
1103
- };
1104
- }).filter((entry) => entry.className || entry.scriptUrl) : [];
1105
- if (!entries.length) {
1106
- return;
1107
- }
1108
- world.addComponent(
1109
- targetEntityId,
1110
- new ScriptComponent(entries)
1111
- );
1112
- }
1113
- {
1114
- const imComponent = world.getComponent(targetEntityId, InstancedMeshComponent);
1115
- if (imComponent && imComponent.instanceEntityIds.length > 0) {
1116
- imComponent.instanceEntityIds = imComponent.instanceEntityIds.map(
1117
- (oldId) => idMap.get(oldId) ?? oldId
1118
- );
1119
- }
1120
- }
1121
- {
1122
- const slotComponent = world.getComponent(targetEntityId, InstanceSlotComponent);
1123
- if (slotComponent && slotComponent.groupEntityId !== -1) {
1124
- slotComponent.groupEntityId = idMap.get(slotComponent.groupEntityId) ?? slotComponent.groupEntityId;
1125
- }
1126
- }
1075
+ return { component: block.component, entries };
1076
+ });
1077
+ return { snapshot: { entities, components }, warnings };
1127
1078
  }
1128
- __name(restorePostCreateComponents, "restorePostCreateComponents");
1079
+ __name(remapSnapshotEntityIds, "remapSnapshotEntityIds");
1129
1080
 
1130
- // core/hydration/animation.ts
1131
- function readAnimationClipName(value) {
1132
- if (typeof value === "string") {
1133
- return value;
1134
- }
1135
- const record = asRecord(value);
1136
- if (!record) {
1137
- return null;
1138
- }
1139
- if (typeof record.name === "string") {
1140
- return record.name;
1141
- }
1142
- return null;
1143
- }
1144
- __name(readAnimationClipName, "readAnimationClipName");
1145
- function readAnimationStates(value) {
1146
- if (!Array.isArray(value)) {
1147
- return [];
1148
- }
1149
- const states = [];
1150
- for (const entry of value) {
1151
- const state = asRecord(entry);
1152
- if (!state) {
1153
- continue;
1154
- }
1155
- const name = typeof state.name === "string" ? state.name : null;
1156
- const clip = readAnimationClipName(state.clip);
1157
- if (!name || !clip) {
1158
- continue;
1159
- }
1160
- states.push({
1161
- name,
1162
- clip,
1163
- clipId: typeof state.clipId === "string" ? state.clipId : void 0,
1164
- loop: typeof state.loop === "boolean" ? state.loop : false
1165
- });
1166
- }
1167
- return states;
1168
- }
1169
- __name(readAnimationStates, "readAnimationStates");
1170
- function readAnimationClipSources(value) {
1171
- if (!Array.isArray(value)) {
1172
- return [];
1173
- }
1174
- const seen = /* @__PURE__ */ new Set();
1175
- const sources = [];
1176
- for (const entry of value) {
1177
- if (typeof entry !== "string") {
1178
- continue;
1179
- }
1180
- const trimmed = entry.trim();
1181
- if (!trimmed || seen.has(trimmed)) {
1182
- continue;
1081
+ // core/prefab/serializeEntitySubtree.ts
1082
+ var SUBTREE_EXCLUDED_COMPONENTS = /* @__PURE__ */ new Set([
1083
+ "Environment",
1084
+ "Postprocessing",
1085
+ "SelectionTransformState",
1086
+ "PrefabInstance"
1087
+ ]);
1088
+ function serializeEntitySubtree(world, rootId, options) {
1089
+ const orderedIds = collectEntitySubtree(world, [rootId]);
1090
+ const raw = world.getEntitiesSnapshot(orderedIds, options?.maxDepth ?? 10);
1091
+ const strippedComponents = [];
1092
+ const components = raw.components.filter((block) => {
1093
+ if (SUBTREE_EXCLUDED_COMPONENTS.has(block.component)) {
1094
+ strippedComponents.push(block.component);
1095
+ return false;
1183
1096
  }
1184
- seen.add(trimmed);
1185
- sources.push(trimmed);
1186
- }
1187
- return sources;
1188
- }
1189
- __name(readAnimationClipSources, "readAnimationClipSources");
1190
- function toAnimationOptions(sourceAnimation) {
1191
- const paused = readBoolean(sourceAnimation.paused);
1192
- const reverse = readBoolean(sourceAnimation.reverse);
1193
- const timeScale = readNumber(sourceAnimation.timeScale);
1194
- const crossFadeDuration = readNumber(sourceAnimation.crossFadeDuration);
1195
- const states = readAnimationStates(sourceAnimation.states);
1196
- const externalClipSources = readAnimationClipSources(
1197
- sourceAnimation.externalClipSources
1097
+ return true;
1098
+ });
1099
+ const idMap = /* @__PURE__ */ new Map();
1100
+ orderedIds.forEach((liveId, index) => {
1101
+ idMap.set(liveId, index + 1);
1102
+ });
1103
+ const { snapshot, warnings } = remapSnapshotEntityIds(
1104
+ { entities: orderedIds.slice(), components },
1105
+ idMap,
1106
+ { externalRefPolicy: "null" }
1198
1107
  );
1199
- const activeStateName = typeof sourceAnimation.activeStateName === "string" ? sourceAnimation.activeStateName : typeof sourceAnimation.activeState === "string" ? sourceAnimation.activeState : typeof sourceAnimation.active?.name === "string" ? sourceAnimation.active.name ?? null : null;
1200
- return {
1201
- paused,
1202
- reverse,
1203
- timeScale,
1204
- crossFadeDuration,
1205
- states,
1206
- externalClipSources,
1207
- activeState: activeStateName
1208
- };
1209
- }
1210
- __name(toAnimationOptions, "toAnimationOptions");
1211
- function restoreAnimationComponent(world, objectManagementSystem, targetEntityId, sourceAnimation) {
1212
- const options = toAnimationOptions(sourceAnimation);
1213
- let animation = world.getComponent(targetEntityId, AnimationComponent);
1214
- if (!animation) {
1215
- objectManagementSystem.createComponentNow(
1216
- "animation",
1217
- world,
1218
- targetEntityId,
1219
- options
1220
- );
1221
- animation = world.getComponent(targetEntityId, AnimationComponent);
1222
- }
1223
- if (!animation) {
1224
- return;
1225
- }
1226
- const availableClips = Array.isArray(sourceAnimation.availableClips) ? sourceAnimation.availableClips.filter(
1227
- (clip) => typeof clip === "string" && clip.length > 0
1228
- ) : [];
1229
- if (availableClips.length > 0) {
1230
- animation.availableClips = [...availableClips];
1231
- }
1232
- if (Array.isArray(options.externalClipSources)) {
1233
- animation.setExternalClipSources(options.externalClipSources);
1234
- }
1235
- const states = options.states ?? [];
1236
- const hasClips = Array.isArray(animation.clips) && animation.clips.length > 0;
1237
- if (!hasClips) {
1238
- animation.__pendingHydratedOptions = options;
1239
- if (typeof options.reverse === "boolean") {
1240
- animation.reverse = options.reverse;
1241
- }
1242
- if (typeof options.timeScale === "number") {
1243
- animation.timeScale = options.timeScale;
1244
- }
1245
- if (typeof options.crossFadeDuration === "number") {
1246
- animation.crossFadeDuration = options.crossFadeDuration;
1247
- }
1248
- if (typeof options.paused === "boolean") {
1249
- animation.paused = options.paused;
1250
- }
1251
- return;
1252
- }
1253
- if (states.length > 0) {
1254
- animation.setStates(states);
1255
- }
1256
- if (typeof options.reverse === "boolean") {
1257
- animation.reverse = options.reverse;
1258
- }
1259
- if (typeof options.timeScale === "number") {
1260
- animation.timeScale = options.timeScale;
1261
- }
1262
- if (typeof options.crossFadeDuration === "number") {
1263
- animation.crossFadeDuration = options.crossFadeDuration;
1264
- }
1265
- if (typeof options.activeState === "string" && options.activeState.length > 0) {
1266
- animation.setActiveState(options.activeState, !options.paused);
1267
- }
1268
- if (typeof options.paused === "boolean") {
1269
- if (options.paused) {
1270
- animation.pauseState();
1271
- } else if (typeof options.activeState === "string" && options.activeState.length > 0) {
1272
- animation.playState(options.activeState);
1273
- }
1274
- }
1275
- }
1276
- __name(restoreAnimationComponent, "restoreAnimationComponent");
1277
-
1278
- // core/hydration/restoreComponentState.ts
1279
- function readEnvironmentState(value) {
1280
- const record = asRecord(value);
1281
- if (!record) {
1282
- return null;
1283
- }
1284
- const nestedValues = asRecord(record.values);
1285
- if (nestedValues) {
1286
- return nestedValues;
1287
- }
1288
- return record;
1289
- }
1290
- __name(readEnvironmentState, "readEnvironmentState");
1291
- function readPostprocessingState(value) {
1292
- const record = asRecord(value);
1293
- if (!record) {
1294
- return null;
1295
- }
1296
- const nestedValues = asRecord(record.values);
1297
- if (nestedValues) {
1298
- return nestedValues;
1299
- }
1300
- return record;
1301
- }
1302
- __name(readPostprocessingState, "readPostprocessingState");
1303
- function restoreComponentState(world, objectManagementSystem, targetEntityId, sourceEntityId, entityType, values) {
1304
- const sourceName = readString(values.nameValues.get(sourceEntityId));
1305
- if (sourceName !== null) {
1306
- const nameComponent = world.getComponent(targetEntityId, Name);
1307
- if (nameComponent) {
1308
- nameComponent.value = sourceName;
1309
- }
1310
- }
1311
- const sourceObject3DRef = asRecord(values.object3DRefValues.get(sourceEntityId));
1312
- if (sourceObject3DRef) {
1313
- const object3DRefComponent = world.getComponent(targetEntityId, Object3DRef);
1314
- const visibility = readBoolean(sourceObject3DRef.visibility);
1315
- if (object3DRefComponent && typeof visibility === "boolean") {
1316
- object3DRefComponent.visibility = visibility;
1317
- }
1318
- }
1319
- const sourceTransform = readTransform(values.transformValues.get(sourceEntityId));
1320
- if (sourceTransform) {
1321
- const transformComponent = world.getComponent(targetEntityId, TransformComponent);
1322
- if (transformComponent) {
1323
- if (typeof sourceTransform.position?.x === "number") {
1324
- transformComponent.position.x = sourceTransform.position.x;
1325
- }
1326
- if (typeof sourceTransform.position?.y === "number") {
1327
- transformComponent.position.y = sourceTransform.position.y;
1328
- }
1329
- if (typeof sourceTransform.position?.z === "number") {
1330
- transformComponent.position.z = sourceTransform.position.z;
1331
- }
1332
- if (typeof sourceTransform.rotation?.x === "number") {
1333
- transformComponent.rotation.x = sourceTransform.rotation.x;
1334
- }
1335
- if (typeof sourceTransform.rotation?.y === "number") {
1336
- transformComponent.rotation.y = sourceTransform.rotation.y;
1337
- }
1338
- if (typeof sourceTransform.rotation?.z === "number") {
1339
- transformComponent.rotation.z = sourceTransform.rotation.z;
1340
- }
1341
- if (typeof sourceTransform.scale?.x === "number") {
1342
- transformComponent.scale.x = sourceTransform.scale.x;
1343
- }
1344
- if (typeof sourceTransform.scale?.y === "number") {
1345
- transformComponent.scale.y = sourceTransform.scale.y;
1346
- }
1347
- if (typeof sourceTransform.scale?.z === "number") {
1348
- transformComponent.scale.z = sourceTransform.scale.z;
1349
- }
1350
- }
1351
- }
1352
- const sourceModel = asRecord(values.modelValues.get(sourceEntityId));
1353
- if (sourceModel) {
1354
- const modelComponent = world.getComponent(targetEntityId, ModelComponent);
1355
- if (modelComponent && typeof sourceModel.path === "string") {
1356
- modelComponent.path = sourceModel.path;
1357
- }
1358
- }
1359
- const sourceImage = asRecord(values.imageValues.get(sourceEntityId));
1360
- if (sourceImage) {
1361
- const imageComponent = world.getComponent(targetEntityId, ImageComponent);
1362
- if (imageComponent) {
1363
- if (typeof sourceImage.path === "string") {
1364
- imageComponent.path = sourceImage.path;
1365
- }
1366
- const width = readNumber(sourceImage.width);
1367
- if (typeof width === "number") {
1368
- imageComponent.width = width;
1369
- }
1370
- const height = readNumber(sourceImage.height);
1371
- if (typeof height === "number") {
1372
- imageComponent.height = height;
1373
- }
1374
- }
1375
- }
1376
- const sourceSprite = asRecord(values.spriteValues.get(sourceEntityId));
1377
- if (sourceSprite) {
1378
- const spriteComponent = world.getComponent(targetEntityId, SpriteComponent);
1379
- if (spriteComponent) {
1380
- if (typeof sourceSprite.path === "string") {
1381
- spriteComponent.path = sourceSprite.path;
1382
- }
1383
- const width = readNumber(sourceSprite.width);
1384
- if (typeof width === "number") {
1385
- spriteComponent.width = width;
1386
- }
1387
- const height = readNumber(sourceSprite.height);
1388
- if (typeof height === "number") {
1389
- spriteComponent.height = height;
1390
- }
1391
- }
1392
- }
1393
- const sourceVideo = asRecord(values.videoValues.get(sourceEntityId));
1394
- if (sourceVideo) {
1395
- const videoComponent = world.getComponent(targetEntityId, VideoComponent);
1396
- if (videoComponent) {
1397
- if (typeof sourceVideo.path === "string") {
1398
- videoComponent.path = sourceVideo.path;
1399
- }
1400
- const videoOptions = asRecord(sourceVideo.options);
1401
- if (videoOptions) {
1402
- videoComponent.options = {
1403
- ...videoComponent.options,
1404
- ...videoOptions
1405
- };
1406
- }
1407
- }
1408
- }
1409
- const sourceAudio = asRecord(values.audioValues.get(sourceEntityId));
1410
- if (sourceAudio && entityType === "audio") {
1411
- const audioComponent = world.getComponent(targetEntityId, AudioComponent);
1412
- if (audioComponent) {
1413
- if (typeof sourceAudio.path === "string") {
1414
- audioComponent.path = sourceAudio.path;
1415
- }
1416
- const audioOptions = asRecord(sourceAudio.options);
1417
- if (audioOptions) {
1418
- audioComponent.options = {
1419
- ...audioComponent.options,
1420
- ...audioOptions
1421
- };
1422
- }
1423
- }
1424
- }
1425
- const sourceCamera = asRecord(values.cameraValues.get(sourceEntityId));
1426
- if (sourceCamera) {
1427
- const cameraComponent = world.getComponent(targetEntityId, CameraComponent);
1428
- if (cameraComponent) {
1429
- if (sourceCamera.projection === "orthographic" || sourceCamera.projection === "perspective") {
1430
- cameraComponent.projection = sourceCamera.projection;
1431
- }
1432
- if (sourceCamera.type === "3d" || sourceCamera.type === "ar") {
1433
- cameraComponent.type = sourceCamera.type;
1434
- }
1435
- if (typeof sourceCamera.isDefault === "boolean") {
1436
- cameraComponent.isDefault = sourceCamera.isDefault;
1437
- }
1438
- const fov = readNumber(sourceCamera.fov);
1439
- if (typeof fov === "number") {
1440
- cameraComponent.fov = fov;
1441
- }
1442
- const near = readNumber(sourceCamera.near);
1443
- if (typeof near === "number") {
1444
- cameraComponent.near = near;
1445
- }
1446
- const far = readNumber(sourceCamera.far);
1447
- if (typeof far === "number") {
1448
- cameraComponent.far = far;
1449
- }
1450
- const left = readNumber(sourceCamera.left);
1451
- if (typeof left === "number") {
1452
- cameraComponent.left = left;
1453
- }
1454
- const right = readNumber(sourceCamera.right);
1455
- if (typeof right === "number") {
1456
- cameraComponent.right = right;
1457
- }
1458
- const top = readNumber(sourceCamera.top);
1459
- if (typeof top === "number") {
1460
- cameraComponent.top = top;
1461
- }
1462
- const bottom = readNumber(sourceCamera.bottom);
1463
- if (typeof bottom === "number") {
1464
- cameraComponent.bottom = bottom;
1465
- }
1466
- const zoom = readNumber(sourceCamera.zoom);
1467
- if (typeof zoom === "number") {
1468
- cameraComponent.zoom = zoom;
1469
- }
1470
- }
1471
- }
1472
- const sourceEnvironment = readEnvironmentState(
1473
- values.environmentValues.get(sourceEntityId)
1108
+ const rootFileId = 1;
1109
+ const parentBlock = snapshot.components.find(
1110
+ (block) => block.component === "ParentId"
1474
1111
  );
1475
- if (sourceEnvironment) {
1476
- let environmentComponent = world.getComponent(targetEntityId, Environment);
1477
- if (!environmentComponent) {
1478
- objectManagementSystem.createComponentNow(
1479
- "environment",
1480
- world,
1481
- targetEntityId,
1482
- sourceEnvironment
1483
- );
1484
- environmentComponent = world.getComponent(targetEntityId, Environment);
1485
- }
1486
- if (environmentComponent) {
1487
- environmentComponent.values = new Environment({
1488
- ...environmentComponent.values,
1489
- ...sourceEnvironment
1490
- }).values;
1491
- }
1492
- }
1493
- const sourcePostprocessing = readPostprocessingState(
1494
- values.postprocessingValues.get(sourceEntityId)
1112
+ const rootParentEntry = parentBlock?.entries.find(
1113
+ (entry) => entry.entityId === rootFileId
1495
1114
  );
1496
- if (sourcePostprocessing) {
1497
- let postprocessingComponent = world.getComponent(targetEntityId, Postprocessing);
1498
- if (!postprocessingComponent) {
1499
- objectManagementSystem.createComponentNow(
1500
- "postprocessing",
1501
- world,
1502
- targetEntityId,
1503
- sourcePostprocessing
1504
- );
1505
- postprocessingComponent = world.getComponent(targetEntityId, Postprocessing);
1506
- }
1507
- if (postprocessingComponent) {
1508
- postprocessingComponent.values = new Postprocessing({
1509
- ...postprocessingComponent.values,
1510
- ...sourcePostprocessing
1511
- }).values;
1512
- }
1513
- }
1514
- const sourceImageTarget = asRecord(values.imageTargetValues.get(sourceEntityId));
1515
- if (sourceImageTarget && entityType === "imageTarget") {
1516
- const imageTargetComponent = world.getComponent(targetEntityId, ImageTarget);
1517
- if (imageTargetComponent) {
1518
- imageTargetComponent.targets = Array.isArray(sourceImageTarget.targets) ? sourceImageTarget.targets : [];
1519
- imageTargetComponent.compiledTargetUrl = typeof sourceImageTarget.compiledTargetUrl === "string" ? sourceImageTarget.compiledTargetUrl : void 0;
1520
- imageTargetComponent.compiledTargetDir = typeof sourceImageTarget.compiledTargetDir === "string" ? sourceImageTarget.compiledTargetDir : void 0;
1521
- }
1522
- }
1523
- const sourceLight = asRecord(values.lightValues.get(sourceEntityId));
1524
- if (sourceLight) {
1525
- const lightComponent = world.getComponent(targetEntityId, LightComponent);
1526
- const sourceValues = asRecord(sourceLight.values);
1527
- if (lightComponent && sourceValues) {
1528
- lightComponent.values = {
1529
- ...lightComponent.values,
1530
- ...sourceValues
1531
- };
1532
- }
1533
- }
1534
- const sourceMaterial = asRecord(values.materialValues.get(sourceEntityId));
1535
- if (sourceMaterial) {
1536
- const materialComponent = world.getComponent(targetEntityId, MaterialComponent);
1537
- const sourceValues = sourceMaterial.values;
1538
- if (materialComponent && Array.isArray(sourceValues)) {
1539
- materialComponent.values = sourceValues;
1540
- }
1115
+ if (rootParentEntry && rootParentEntry.value !== null && typeof rootParentEntry.value === "object") {
1116
+ rootParentEntry.value.value = null;
1541
1117
  }
1542
- const sourceMeshGeometry = asRecord(values.meshGeometryValues.get(sourceEntityId));
1543
- if (sourceMeshGeometry) {
1544
- const meshGeometryComponent = world.getComponent(
1545
- targetEntityId,
1546
- MeshGeometryComponent
1547
- );
1548
- if (meshGeometryComponent) {
1549
- const parameters = asRecord(sourceMeshGeometry.parameters);
1550
- if (parameters) {
1551
- meshGeometryComponent.parameters = parameters;
1552
- }
1553
- if (typeof sourceMeshGeometry.modelName === "string") {
1554
- meshGeometryComponent.modelName = sourceMeshGeometry.modelName;
1555
- }
1556
- if (typeof sourceMeshGeometry.castShadow === "boolean") {
1557
- meshGeometryComponent.castShadow = sourceMeshGeometry.castShadow;
1558
- }
1559
- if (typeof sourceMeshGeometry.receiveShadow === "boolean") {
1560
- meshGeometryComponent.receiveShadow = sourceMeshGeometry.receiveShadow;
1561
- }
1562
- }
1563
- }
1564
- const sourceSelectable = asRecord(values.selectableValues.get(sourceEntityId));
1565
- if (sourceSelectable) {
1566
- const enabled = readBoolean(sourceSelectable.enabled);
1567
- let selectable = world.getComponent(targetEntityId, Selectable);
1568
- if (!selectable) {
1569
- objectManagementSystem.createComponentNow(
1570
- "selectable",
1571
- world,
1572
- targetEntityId,
1573
- enabled ?? true
1574
- );
1575
- selectable = world.getComponent(targetEntityId, Selectable);
1576
- }
1577
- if (selectable && typeof enabled === "boolean") {
1578
- selectable.enabled = enabled;
1579
- }
1580
- }
1581
- const sourcePhysics = asRecord(values.physicsValues.get(sourceEntityId));
1582
- if (sourcePhysics) {
1583
- const physicsValues = asRecord(sourcePhysics.values) ?? sourcePhysics;
1584
- let physics = world.getComponent(targetEntityId, PhysicsComponent);
1585
- if (!physics) {
1586
- objectManagementSystem.createComponentNow(
1587
- "physics",
1588
- world,
1589
- targetEntityId,
1590
- physicsValues
1591
- );
1592
- physics = world.getComponent(targetEntityId, PhysicsComponent);
1593
- }
1594
- if (physics) {
1595
- physics.setValues({
1596
- rigidbody: asRecord(physicsValues.rigidbody) ?? {},
1597
- collider: asRecord(physicsValues.collider) ?? {}
1598
- });
1599
- }
1600
- }
1601
- const sourceAnimation = asRecord(values.animationValues.get(sourceEntityId));
1602
- if (sourceAnimation) {
1603
- restoreAnimationComponent(
1604
- world,
1605
- objectManagementSystem,
1606
- targetEntityId,
1607
- sourceAnimation
1608
- );
1609
- }
1610
- const sourceInstancedMesh = asRecord(values.instancedMeshValues.get(sourceEntityId));
1611
- if (sourceInstancedMesh) {
1612
- const imComponent = world.getComponent(targetEntityId, InstancedMeshComponent);
1613
- if (imComponent) {
1614
- if (typeof sourceInstancedMesh.meshKind === "string") {
1615
- imComponent.meshKind = sourceInstancedMesh.meshKind;
1616
- }
1617
- if (typeof sourceInstancedMesh.modelPath === "string") {
1618
- imComponent.modelPath = sourceInstancedMesh.modelPath;
1619
- }
1620
- const parameters = asRecord(sourceInstancedMesh.meshParameters);
1621
- if (parameters) {
1622
- imComponent.meshParameters = parameters;
1623
- }
1624
- if (typeof sourceInstancedMesh.castShadow === "boolean") {
1625
- imComponent.castShadow = sourceInstancedMesh.castShadow;
1626
- }
1627
- if (typeof sourceInstancedMesh.receiveShadow === "boolean") {
1628
- imComponent.receiveShadow = sourceInstancedMesh.receiveShadow;
1629
- }
1630
- if (Array.isArray(sourceInstancedMesh.instanceEntityIds)) {
1631
- imComponent.instanceEntityIds = sourceInstancedMesh.instanceEntityIds;
1632
- }
1633
- imComponent.instancedMesh = null;
1634
- }
1635
- }
1636
- const sourceInstanceSlot = asRecord(values.instanceSlotValues.get(sourceEntityId));
1637
- if (sourceInstanceSlot) {
1638
- const slotComponent = world.getComponent(targetEntityId, InstanceSlotComponent);
1639
- if (slotComponent) {
1640
- if (typeof sourceInstanceSlot.slotIndex === "number") {
1641
- slotComponent.slotIndex = sourceInstanceSlot.slotIndex;
1642
- }
1643
- }
1644
- }
1645
- }
1646
- __name(restoreComponentState, "restoreComponentState");
1647
-
1648
- // core/hydration/types.ts
1649
- var HYDRATABLE_ENTITY_KINDS = /* @__PURE__ */ new Set([
1650
- "cube",
1651
- "sphere",
1652
- "plane",
1653
- "capsule",
1654
- "cylinder",
1655
- "empty",
1656
- "model",
1657
- "image",
1658
- "imageTarget",
1659
- "sprite",
1660
- "audio",
1661
- "camera",
1662
- "video",
1663
- "ambientLight",
1664
- "directionalLight",
1665
- "pointLight",
1666
- "spotLight",
1667
- "areaLight",
1668
- "instancedMesh",
1669
- "instanceSlot"
1670
- ]);
1671
-
1672
- // core/hydration/hydrateWorld.ts
1673
- function buildEntityCreationPayload(sourceEntityId, kind, componentValues) {
1674
- const payload = {
1675
- name: readString(componentValues.nameValues.get(sourceEntityId)) ?? void 0,
1676
- transform: readTransform(componentValues.transformValues.get(sourceEntityId))
1677
- };
1678
- if (kind === "model") {
1679
- const model = asRecord(componentValues.modelValues.get(sourceEntityId));
1680
- if (typeof model?.path === "string") {
1681
- payload.path = model.path;
1682
- }
1683
- }
1684
- if (kind === "image") {
1685
- const image = asRecord(componentValues.imageValues.get(sourceEntityId));
1686
- if (typeof image?.path === "string") {
1687
- payload.path = image.path;
1688
- }
1689
- }
1690
- if (kind === "sprite") {
1691
- const sprite = asRecord(componentValues.spriteValues.get(sourceEntityId));
1692
- if (typeof sprite?.path === "string") {
1693
- payload.path = sprite.path;
1694
- }
1695
- }
1696
- if (kind === "video") {
1697
- const video = asRecord(componentValues.videoValues.get(sourceEntityId));
1698
- if (typeof video?.path === "string") {
1699
- payload.path = video.path;
1700
- }
1701
- const videoOptions = asRecord(video?.options);
1702
- if (videoOptions) {
1703
- payload.options = videoOptions;
1704
- }
1705
- }
1706
- if (kind === "audio") {
1707
- const audio = asRecord(componentValues.audioValues.get(sourceEntityId));
1708
- if (typeof audio?.path === "string") {
1709
- payload.path = audio.path;
1710
- }
1711
- const audioOptions = asRecord(audio?.options);
1712
- if (audioOptions) {
1713
- payload.options = audioOptions;
1714
- }
1715
- }
1716
- if (kind === "camera") {
1717
- const camera = asRecord(componentValues.cameraValues.get(sourceEntityId));
1718
- if (camera) {
1719
- const projection = camera.projection === "orthographic" || camera.projection === "perspective" ? camera.projection : void 0;
1720
- const type = camera.type === "3d" || camera.type === "ar" ? camera.type : void 0;
1721
- payload.options = {
1722
- isDefault: typeof camera.isDefault === "boolean" ? camera.isDefault : void 0,
1723
- projection,
1724
- type,
1725
- fov: typeof camera.fov === "number" ? camera.fov : void 0,
1726
- near: typeof camera.near === "number" ? camera.near : void 0,
1727
- far: typeof camera.far === "number" ? camera.far : void 0,
1728
- left: typeof camera.left === "number" ? camera.left : void 0,
1729
- right: typeof camera.right === "number" ? camera.right : void 0,
1730
- top: typeof camera.top === "number" ? camera.top : void 0,
1731
- bottom: typeof camera.bottom === "number" ? camera.bottom : void 0,
1732
- zoom: typeof camera.zoom === "number" ? camera.zoom : void 0
1733
- };
1734
- }
1735
- }
1736
- if (kind === "imageTarget") {
1737
- const imageTarget = asRecord(componentValues.imageTargetValues.get(sourceEntityId));
1738
- if (imageTarget) {
1739
- payload.options = {
1740
- targets: Array.isArray(imageTarget.targets) ? imageTarget.targets : [],
1741
- compiledTargetUrl: typeof imageTarget.compiledTargetUrl === "string" ? imageTarget.compiledTargetUrl : void 0,
1742
- compiledTargetDir: typeof imageTarget.compiledTargetDir === "string" ? imageTarget.compiledTargetDir : void 0
1743
- };
1744
- }
1745
- }
1746
- if (kind === "instancedMesh") {
1747
- const im = asRecord(componentValues.instancedMeshValues.get(sourceEntityId));
1748
- if (im) {
1749
- payload.options = {
1750
- meshKind: typeof im.meshKind === "string" ? im.meshKind : "cube",
1751
- modelPath: typeof im.modelPath === "string" ? im.modelPath : void 0,
1752
- meshParameters: asRecord(im.meshParameters) ?? void 0,
1753
- castShadow: typeof im.castShadow === "boolean" ? im.castShadow : false,
1754
- receiveShadow: typeof im.receiveShadow === "boolean" ? im.receiveShadow : false,
1755
- // New format: signal the factory to skip child entity creation.
1756
- // Old format (instances[]): pass through for migration — factory will
1757
- // create slot entities from the legacy InstanceTransform array.
1758
- ...Array.isArray(im.instanceEntityIds) ? { instanceEntityIds: im.instanceEntityIds } : Array.isArray(im.instances) ? { instances: im.instances } : {}
1759
- };
1760
- }
1761
- }
1762
- if (kind === "instanceSlot") {
1763
- const slot = asRecord(componentValues.instanceSlotValues.get(sourceEntityId));
1764
- if (slot) {
1765
- payload.options = {
1766
- groupEntityId: typeof slot.groupEntityId === "number" ? slot.groupEntityId : -1,
1767
- slotIndex: typeof slot.slotIndex === "number" ? slot.slotIndex : 0
1768
- };
1769
- }
1770
- }
1771
- return payload;
1772
- }
1773
- __name(buildEntityCreationPayload, "buildEntityCreationPayload");
1774
- function resolvePrimaryCameraSourceEntityId(snapshot, componentValues, entityTypeValues) {
1775
- let firstCameraSourceEntityId = null;
1776
- for (const sourceEntityId of snapshot.entities) {
1777
- const entityType = readString(entityTypeValues.get(sourceEntityId));
1778
- if (entityType !== "camera") {
1779
- continue;
1780
- }
1781
- if (firstCameraSourceEntityId === null) {
1782
- firstCameraSourceEntityId = sourceEntityId;
1783
- }
1784
- const cameraValue = asRecord(componentValues.cameraValues.get(sourceEntityId));
1785
- if (cameraValue?.isDefault === true) {
1786
- return sourceEntityId;
1787
- }
1788
- }
1789
- return firstCameraSourceEntityId;
1790
- }
1791
- __name(resolvePrimaryCameraSourceEntityId, "resolvePrimaryCameraSourceEntityId");
1792
- function applyLocalTransformsAfterHierarchyRestore(world) {
1793
- const transformEntities = world.query(TransformComponent, Object3DRef);
1794
- for (const entityId of transformEntities) {
1795
- const transform = world.getComponent(entityId, TransformComponent);
1796
- const object = world.getComponent(entityId, Object3DRef)?.object;
1797
- if (!transform || !object) {
1798
- continue;
1799
- }
1800
- applyTransform(object, transform);
1801
- object.updateMatrixWorld(true);
1802
- }
1803
- }
1804
- __name(applyLocalTransformsAfterHierarchyRestore, "applyLocalTransformsAfterHierarchyRestore");
1805
- function hydrateWorldFromSnapshotDetailed(snapshot, world, objectManagementSystem) {
1806
- if (!snapshot || !snapshot.entities.length) {
1807
- return {
1808
- restoredCount: 0,
1809
- selectedEntityId: null
1810
- };
1811
- }
1812
- const entityTypeValues = readByComponent(snapshot.components, "EntityType");
1813
- const componentValues = buildComponentValueMaps(snapshot);
1814
- const primaryCameraSourceEntityId = resolvePrimaryCameraSourceEntityId(
1815
- snapshot,
1816
- componentValues,
1817
- entityTypeValues
1118
+ const filteredWarnings = warnings.filter(
1119
+ (warning) => !(warning.component === "ParentId" && warning.entityId === rootId)
1818
1120
  );
1819
- const idMap = /* @__PURE__ */ new Map();
1820
- for (const sourceEntityId of snapshot.entities) {
1821
- const entityTypeValue = entityTypeValues.get(sourceEntityId);
1822
- const entityType = readString(entityTypeValue);
1823
- if (!entityType || !HYDRATABLE_ENTITY_KINDS.has(entityType)) {
1824
- continue;
1825
- }
1826
- const kind = entityType;
1827
- const payload = buildEntityCreationPayload(sourceEntityId, kind, componentValues);
1828
- if (kind === "camera" && sourceEntityId === primaryCameraSourceEntityId) {
1829
- payload.useWorldCamera = true;
1830
- const options = asRecord(payload.options);
1831
- payload.options = {
1832
- ...options ?? {},
1833
- isDefault: true
1834
- };
1835
- }
1836
- const createdEntityId = objectManagementSystem.createNow(kind, world, payload);
1837
- idMap.set(sourceEntityId, createdEntityId);
1838
- }
1839
- for (const sourceEntityId of snapshot.entities) {
1840
- const targetEntityId = idMap.get(sourceEntityId);
1841
- if (targetEntityId === void 0) {
1842
- continue;
1843
- }
1844
- const entityType = readString(entityTypeValues.get(sourceEntityId));
1845
- restoreComponentState(
1846
- world,
1847
- objectManagementSystem,
1848
- targetEntityId,
1849
- sourceEntityId,
1850
- entityType,
1851
- componentValues
1852
- );
1853
- restorePostCreateComponents(
1854
- world,
1855
- objectManagementSystem,
1856
- targetEntityId,
1857
- sourceEntityId,
1858
- entityType,
1859
- componentValues,
1860
- idMap
1861
- );
1862
- }
1863
- applyParentLinks(snapshot, idMap, objectManagementSystem, world);
1864
- objectManagementSystem.reconcileSceneFromWorld(world);
1865
- applyLocalTransformsAfterHierarchyRestore(world);
1866
- const selectedEntityId = typeof snapshot.selectedEntityId === "number" ? idMap.get(snapshot.selectedEntityId) ?? null : null;
1867
- return {
1868
- restoredCount: idMap.size,
1869
- selectedEntityId
1870
- };
1871
- }
1872
- __name(hydrateWorldFromSnapshotDetailed, "hydrateWorldFromSnapshotDetailed");
1873
- function hydrateWorldFromSnapshot(snapshot, world, objectManagementSystem) {
1874
- return hydrateWorldFromSnapshotDetailed(
1875
- snapshot,
1876
- world,
1877
- objectManagementSystem
1878
- ).restoredCount;
1121
+ return { snapshot, warnings: filteredWarnings, strippedComponents };
1879
1122
  }
1880
- __name(hydrateWorldFromSnapshot, "hydrateWorldFromSnapshot");
1123
+ __name(serializeEntitySubtree, "serializeEntitySubtree");
1881
1124
 
1882
- export { HYDRATABLE_ENTITY_KINDS, World, hydrateWorldFromSnapshot, hydrateWorldFromSnapshotDetailed };
1125
+ export { World, remapSnapshotEntityIds, serializeEntitySubtree };
1883
1126
  //# sourceMappingURL=index.js.map
1884
1127
  //# sourceMappingURL=index.js.map