@relu-interactives/spatial-ecs 0.2.25 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (276) hide show
  1. package/dist/{System-CYWZ_Zx5.d.cts → System-vrU46Vuw.d.cts} +16 -2
  2. package/dist/{System-CYWZ_Zx5.d.ts → System-vrU46Vuw.d.ts} +16 -2
  3. package/dist/{Video-AIQYTAAr.d.cts → XRRig-CAmf04NX.d.ts} +131 -4
  4. package/dist/{Video-DlZ4G9ig.d.ts → XRRig-Cu-EyliG.d.cts} +131 -4
  5. package/dist/{chunk-XFD74BQL.js → chunk-67WGASUJ.js} +3 -3
  6. package/dist/{chunk-XFD74BQL.js.map → chunk-67WGASUJ.js.map} +1 -1
  7. package/dist/{chunk-RJ4J5UEX.js → chunk-PCOZLCXS.js} +160 -83
  8. package/dist/chunk-PCOZLCXS.js.map +1 -0
  9. package/dist/{chunk-J6736FFO.js → chunk-U3MDYKPV.js} +90 -14
  10. package/dist/chunk-U3MDYKPV.js.map +1 -0
  11. package/dist/{chunk-3P3ZBP7K.js → chunk-VXUVNC7S.js} +634 -6
  12. package/dist/chunk-VXUVNC7S.js.map +1 -0
  13. package/dist/components/index.cjs +87 -11
  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/api/Behaviour/classes/Behaviour.md +98 -51
  19. package/dist/docs/api/Component/classes/Component.md +4 -1
  20. package/dist/docs/api/components/classes/AnimationComponent.md +26 -26
  21. package/dist/docs/api/components/classes/AudioComponent.md +19 -19
  22. package/dist/docs/api/components/classes/CameraComponent.md +14 -14
  23. package/dist/docs/api/components/classes/EntityType.md +4 -4
  24. package/dist/docs/api/components/classes/Environment.md +3 -3
  25. package/dist/docs/api/components/classes/ImageComponent.md +7 -7
  26. package/dist/docs/api/components/classes/ImageTarget.md +7 -7
  27. package/dist/docs/api/components/classes/ImageTargetAnchor.md +4 -4
  28. package/dist/docs/api/components/classes/InstanceSlotComponent.md +4 -4
  29. package/dist/docs/api/components/classes/InstancedMeshComponent.md +10 -10
  30. package/dist/docs/api/components/classes/LightComponent.md +6 -6
  31. package/dist/docs/api/components/classes/MaterialComponent.md +57 -11
  32. package/dist/docs/api/components/classes/MeshComponent.md +3 -3
  33. package/dist/docs/api/components/classes/MeshGeometryComponent.md +9 -9
  34. package/dist/docs/api/components/classes/ModelComponent.md +4 -4
  35. package/dist/docs/api/components/classes/Name.md +3 -3
  36. package/dist/docs/api/components/classes/Object3DRef.md +4 -4
  37. package/dist/docs/api/components/classes/ParentId.md +3 -3
  38. package/dist/docs/api/components/classes/PhysicsComponent.md +12 -13
  39. package/dist/docs/api/components/classes/Postprocessing.md +3 -3
  40. package/dist/docs/api/components/classes/PrefabInstance.md +80 -0
  41. package/dist/docs/api/components/classes/PrefabNode.md +54 -0
  42. package/dist/docs/api/components/classes/ScriptComponent.md +5 -5
  43. package/dist/docs/api/components/classes/ScriptObjectComponent.md +55 -0
  44. package/dist/docs/api/components/classes/Selectable.md +3 -3
  45. package/dist/docs/api/components/classes/SelectionTransformState.md +5 -5
  46. package/dist/docs/api/components/classes/SpriteComponent.md +7 -7
  47. package/dist/docs/api/components/classes/TransformComponent.md +12 -12
  48. package/dist/docs/api/components/classes/VideoComponent.md +28 -28
  49. package/dist/docs/api/components/functions/defaultMaterialValue.md +17 -0
  50. package/dist/docs/api/components/functions/normalizePhysicsState.md +1 -1
  51. package/dist/docs/api/components/functions/setPhysicsLiveRef.md +34 -0
  52. package/dist/docs/api/components/index.md +8 -1
  53. package/dist/docs/api/components/type-aliases/AnimationComponentOptions.md +9 -9
  54. package/dist/docs/api/components/type-aliases/CameraComponentOptions.md +13 -13
  55. package/dist/docs/api/components/type-aliases/CameraProjection.md +1 -1
  56. package/dist/docs/api/components/type-aliases/CameraRuntimeType.md +1 -1
  57. package/dist/docs/api/components/type-aliases/ColliderShape.md +1 -1
  58. package/dist/docs/api/components/type-aliases/ColliderState.md +20 -20
  59. package/dist/docs/api/components/type-aliases/CubeMeshParameters.md +4 -4
  60. package/dist/docs/api/components/type-aliases/EditableMeshObjectKind.md +1 -1
  61. package/dist/docs/api/components/type-aliases/EnvironmentFogState.md +8 -8
  62. package/dist/docs/api/components/type-aliases/EnvironmentFogType.md +1 -1
  63. package/dist/docs/api/components/type-aliases/EnvironmentGradientEffect.md +1 -1
  64. package/dist/docs/api/components/type-aliases/EnvironmentSkyboxState.md +7 -7
  65. package/dist/docs/api/components/type-aliases/EnvironmentSkyboxType.md +1 -1
  66. package/dist/docs/api/components/type-aliases/EnvironmentState.md +5 -5
  67. package/dist/docs/api/components/type-aliases/ImageTargetAnchorOptions.md +3 -3
  68. package/dist/docs/api/components/type-aliases/ImageTargetReference.md +7 -7
  69. package/dist/docs/api/components/type-aliases/InstanceTransform.md +13 -13
  70. package/dist/docs/api/components/type-aliases/InstancedMeshKind.md +1 -1
  71. package/dist/docs/api/components/type-aliases/LightValueState.md +11 -11
  72. package/dist/docs/api/components/type-aliases/MaterialTypeValue.md +1 -1
  73. package/dist/docs/api/components/type-aliases/MaterialValueState.md +28 -28
  74. package/dist/docs/api/components/type-aliases/MeshGeometryParameters.md +1 -1
  75. package/dist/docs/api/components/type-aliases/MeshGeometryParametersByKind.md +7 -7
  76. package/dist/docs/api/components/type-aliases/PhysicsState.md +3 -3
  77. package/dist/docs/api/components/type-aliases/PlaneMeshParameters.md +3 -3
  78. package/dist/docs/api/components/type-aliases/PostprocessingState.md +62 -62
  79. package/dist/docs/api/components/type-aliases/RadiusHeightMeshParameters.md +3 -3
  80. package/dist/docs/api/components/type-aliases/RadiusMeshParameters.md +2 -2
  81. package/dist/docs/api/components/type-aliases/RigidbodyState.md +17 -17
  82. package/dist/docs/api/components/type-aliases/RigidbodyType.md +1 -1
  83. package/dist/docs/api/components/type-aliases/ScriptEntry.md +8 -10
  84. package/dist/docs/api/components/type-aliases/ScriptObjectComponentInput.md +20 -0
  85. package/dist/docs/api/components/type-aliases/ScriptObjectRuntimeState.md +13 -0
  86. package/dist/docs/api/components/type-aliases/TextureFilteringValue.md +1 -1
  87. package/dist/docs/api/components/type-aliases/TransformData.md +4 -4
  88. package/dist/docs/api/components/type-aliases/TransformModeValue.md +1 -1
  89. package/dist/docs/api/components/type-aliases/TransformSpaceValue.md +1 -1
  90. package/dist/docs/api/components/type-aliases/Vec3.md +4 -4
  91. package/dist/docs/api/components/variables/DEFAULT_COLLIDER_STATE.md +1 -1
  92. package/dist/docs/api/components/variables/DEFAULT_ENVIRONMENT_STATE.md +1 -1
  93. package/dist/docs/api/components/variables/DEFAULT_INSTANCED_MESH_PARAMETERS.md +1 -1
  94. package/dist/docs/api/components/variables/DEFAULT_INSTANCE_TRANSFORM.md +1 -1
  95. package/dist/docs/api/components/variables/DEFAULT_MESH_GEOMETRY_PARAMETERS.md +1 -1
  96. package/dist/docs/api/components/variables/DEFAULT_PHYSICS_STATE.md +1 -1
  97. package/dist/docs/api/components/variables/DEFAULT_POSTPROCESSING_STATE.md +1 -1
  98. package/dist/docs/api/components/variables/DEFAULT_RIGIDBODY_STATE.md +1 -1
  99. package/dist/docs/api/index/classes/AnimationStateMachine.md +16 -16
  100. package/dist/docs/api/index/classes/AnimationStateManager.md +13 -13
  101. package/dist/docs/api/index/classes/AnimationSystem.md +3 -3
  102. package/dist/docs/api/index/classes/AudioSystem.md +4 -4
  103. package/dist/docs/api/index/classes/CameraSyncSystem.md +2 -2
  104. package/dist/docs/api/index/classes/EnvironmentSyncSystem.md +4 -4
  105. package/dist/docs/api/index/classes/InputSystem.md +33 -33
  106. package/dist/docs/api/index/classes/InstancedMeshSystem.md +2 -2
  107. package/dist/docs/api/index/classes/LightSyncSystem.md +2 -2
  108. package/dist/docs/api/index/classes/MaterialSyncSystem.md +3 -3
  109. package/dist/docs/api/index/classes/MeshGeometrySystem.md +2 -2
  110. package/dist/docs/api/index/classes/ObjectManagementSystem.md +14 -14
  111. package/dist/docs/api/index/classes/ObjectVisibilitySystem.md +2 -2
  112. package/dist/docs/api/index/classes/PhysicsSyncSystem.md +4 -4
  113. package/dist/docs/api/index/classes/PostprocessingSyncSystem.md +4 -4
  114. package/dist/docs/api/index/classes/RenderSystem.md +3 -3
  115. package/dist/docs/api/index/classes/ScriptBehaviourSystem.md +5 -5
  116. package/dist/docs/api/index/classes/ScriptObject.md +156 -0
  117. package/dist/docs/api/index/classes/ScriptObjectSystem.md +129 -0
  118. package/dist/docs/api/index/classes/TransformSyncSystem.md +2 -2
  119. package/dist/docs/api/index/classes/VideoSystem.md +4 -4
  120. package/dist/docs/api/index/classes/World.md +183 -86
  121. package/dist/docs/api/index/functions/applyPrefabToSnapshotInstances.md +32 -0
  122. package/dist/docs/api/index/functions/buildComponentValueMaps.md +23 -0
  123. package/dist/docs/api/index/functions/buildNodeKeyMapsFromSnapshot.md +25 -0
  124. package/dist/docs/api/index/functions/buildNodeMapsFromSnapshot.md +23 -0
  125. package/dist/docs/api/index/functions/canonicalizeComponentValue.md +38 -0
  126. package/dist/docs/api/index/functions/clearModelCache.md +26 -0
  127. package/dist/docs/api/index/functions/clearPrefabCache.md +25 -0
  128. package/dist/docs/api/index/functions/collectDiffPaths.md +38 -0
  129. package/dist/docs/api/index/functions/collectDirectPrefabDependencies.md +27 -0
  130. package/dist/docs/api/index/functions/collectEntitySubtree.md +29 -0
  131. package/dist/docs/api/index/functions/collectSnapshotSubtreeIds.md +26 -0
  132. package/dist/docs/api/index/functions/computeInstanceOverrides.md +44 -0
  133. package/dist/docs/api/index/functions/createAnimationComponent.md +1 -1
  134. package/dist/docs/api/index/functions/createAudioComponent.md +1 -1
  135. package/dist/docs/api/index/functions/createCameraComponent.md +1 -1
  136. package/dist/docs/api/index/functions/createEntityTypeComponent.md +2 -2
  137. package/dist/docs/api/index/functions/createEnvironmentComponent.md +1 -1
  138. package/dist/docs/api/index/functions/createImageComponent.md +1 -1
  139. package/dist/docs/api/index/functions/createImageTargetAnchorComponent.md +1 -1
  140. package/dist/docs/api/index/functions/createImageTargetComponent.md +1 -1
  141. package/dist/docs/api/index/functions/createInstanceSlotComponent.md +1 -1
  142. package/dist/docs/api/index/functions/createInstancedMeshComponent.md +1 -1
  143. package/dist/docs/api/index/functions/createLightComponent.md +1 -1
  144. package/dist/docs/api/index/functions/createMaterialComponent.md +1 -1
  145. package/dist/docs/api/index/functions/createMeshComponent.md +1 -1
  146. package/dist/docs/api/index/functions/createMeshGeometryComponent.md +1 -1
  147. package/dist/docs/api/index/functions/createModelComponent.md +1 -1
  148. package/dist/docs/api/index/functions/createNameComponent.md +1 -1
  149. package/dist/docs/api/index/functions/createObject3DRefComponent.md +1 -1
  150. package/dist/docs/api/index/functions/createParentIdComponent.md +1 -1
  151. package/dist/docs/api/index/functions/createPhysicsComponent.md +2 -4
  152. package/dist/docs/api/index/functions/createPostprocessingComponent.md +1 -1
  153. package/dist/docs/api/index/functions/createScriptComponent.md +1 -1
  154. package/dist/docs/api/index/functions/createScriptObjectComponent.md +28 -0
  155. package/dist/docs/api/index/functions/createSelectableComponent.md +1 -1
  156. package/dist/docs/api/index/functions/createSelectionTransformStateComponent.md +1 -1
  157. package/dist/docs/api/index/functions/createSpriteComponent.md +1 -1
  158. package/dist/docs/api/index/functions/createTransformComponent.md +1 -1
  159. package/dist/docs/api/index/functions/createVideoComponent.md +1 -1
  160. package/dist/docs/api/index/functions/decanonicalizeComponentValue.md +28 -0
  161. package/dist/docs/api/index/functions/despawnPrefab.md +32 -0
  162. package/dist/docs/api/index/functions/encodeOverride.md +28 -0
  163. package/dist/docs/api/index/functions/findSnapshotRootEntityIds.md +25 -0
  164. package/dist/docs/api/index/functions/findTopLevelNestedRegions.md +28 -0
  165. package/dist/docs/api/index/functions/groupOverridePaths.md +25 -0
  166. package/dist/docs/api/index/functions/hydrateWorldFromSnapshot.md +1 -1
  167. package/dist/docs/api/index/functions/hydrateWorldFromSnapshotDetailed.md +4 -2
  168. package/dist/docs/api/index/functions/indexSnapshotByEntity.md +25 -0
  169. package/dist/docs/api/index/functions/instantiateSubtree.md +32 -0
  170. package/dist/docs/api/index/functions/loadPrefab.md +28 -0
  171. package/dist/docs/api/index/functions/loadSharedGltf.md +29 -0
  172. package/dist/docs/api/index/functions/mergeComponentValue.md +32 -0
  173. package/dist/docs/api/index/functions/parseOverride.md +34 -0
  174. package/dist/docs/api/index/functions/parsePrefabAsset.md +25 -0
  175. package/dist/docs/api/index/functions/prefabFileVersionFor.md +25 -0
  176. package/dist/docs/api/index/functions/registerDefaultComponentFactories.md +1 -1
  177. package/dist/docs/api/index/functions/registerDefaultFactories.md +1 -1
  178. package/dist/docs/api/index/functions/remapSnapshotEntityIds.md +46 -0
  179. package/dist/docs/api/index/functions/resolveDracoDecoderPath.md +17 -0
  180. package/dist/docs/api/index/functions/restoreComponentState.md +34 -0
  181. package/dist/docs/api/index/functions/restorePostCreateComponents.md +36 -0
  182. package/dist/docs/api/index/functions/serializeEntitySubtree.md +35 -0
  183. package/dist/docs/api/index/functions/setDracoDecoderPath.md +30 -0
  184. package/dist/docs/api/index/functions/setPrefabAssetUrlResolver.md +30 -0
  185. package/dist/docs/api/index/functions/spawnPrefab.md +36 -0
  186. package/dist/docs/api/index/index.md +65 -0
  187. package/dist/docs/api/index/interfaces/EcsSystem.md +3 -3
  188. package/dist/docs/api/index/interfaces/StateMachine.md +13 -13
  189. package/dist/docs/api/index/type-aliases/AnimationStateCallbacks.md +4 -4
  190. package/dist/docs/api/index/type-aliases/ApplyPrefabToSnapshotResult.md +23 -0
  191. package/dist/docs/api/index/type-aliases/ComponentFactory.md +1 -1
  192. package/dist/docs/api/index/type-aliases/ComponentValueMaps.md +69 -0
  193. package/dist/docs/api/index/type-aliases/EcsComponentFactoryKind.md +2 -1
  194. package/dist/docs/api/index/type-aliases/EcsWorldComponentSnapshot.md +3 -3
  195. package/dist/docs/api/index/type-aliases/EcsWorldStateSnapshotLike.md +4 -4
  196. package/dist/docs/api/index/type-aliases/ExternalRefWarning.md +27 -0
  197. package/dist/docs/api/index/type-aliases/HydrateOptions.md +27 -0
  198. package/dist/docs/api/index/type-aliases/HydrateWorldFromSnapshotResult.md +7 -5
  199. package/dist/docs/api/index/type-aliases/InstantiateSubtreeResult.md +23 -0
  200. package/dist/docs/api/index/type-aliases/KeyboardKey.md +1 -1
  201. package/dist/docs/api/index/type-aliases/ModuleLoader.md +25 -0
  202. package/dist/docs/api/index/type-aliases/MouseButton.md +1 -1
  203. package/dist/docs/api/index/type-aliases/NestedRegion.md +27 -0
  204. package/dist/docs/api/index/type-aliases/NodeKeyMaps.md +30 -0
  205. package/dist/docs/api/index/type-aliases/NodeMaps.md +25 -0
  206. package/dist/docs/api/index/type-aliases/PrefabAsset.md +32 -0
  207. package/dist/docs/api/index/type-aliases/RemapSnapshotOptions.md +21 -0
  208. package/dist/docs/api/index/type-aliases/SelectionContext.md +4 -4
  209. package/dist/docs/api/index/type-aliases/SerializeEntitySubtreeResult.md +25 -0
  210. package/dist/docs/api/index/type-aliases/SpawnPrefabOptions.md +27 -0
  211. package/dist/docs/api/index/type-aliases/SpawnPrefabSource.md +19 -0
  212. package/dist/docs/api/index/type-aliases/SubtreeSnapshot.md +43 -0
  213. package/dist/docs/api/index/variables/ADDED_NODE_MARKER_COMPONENT.md +19 -0
  214. package/dist/docs/api/index/variables/HYDRATABLE_ENTITY_KINDS.md +1 -1
  215. package/dist/docs/api/index/variables/KeyboardKeys.md +89 -89
  216. package/dist/docs/api/index/variables/NODE_KEY_SEPARATOR.md +13 -0
  217. package/dist/docs/api/index/variables/OVERRIDE_DIFF_EXCLUDED_COMPONENTS.md +15 -0
  218. package/dist/docs/api/index/variables/OVERRIDE_ROOT_EXCLUDED_COMPONENTS.md +16 -0
  219. package/dist/docs/api/index/variables/PREFAB_FILE_VERSION.md +13 -0
  220. package/dist/docs/api/index/variables/PREFAB_FILE_VERSION_NESTED.md +15 -0
  221. package/dist/docs/api/index/variables/SCRIPT_OBJECT_ROOT_FLAG.md +15 -0
  222. package/dist/docs/api/index/variables/SHARED_MODEL_RESOURCE_FLAG.md +17 -0
  223. package/dist/docs/api/typedoc-sidebar.json +1 -1
  224. package/dist/docs/api/types/type-aliases/AssetInput.md +3 -3
  225. package/dist/docs/api/types/type-aliases/CheckboxInput.md +3 -3
  226. package/dist/docs/api/types/type-aliases/ColorInput.md +1 -1
  227. package/dist/docs/api/types/type-aliases/ComponentInput.md +4 -4
  228. package/dist/docs/api/types/type-aliases/ComponentKind.md +2 -1
  229. package/dist/docs/api/types/type-aliases/DropdownInput.md +3 -3
  230. package/dist/docs/api/types/type-aliases/DropdownOption.md +3 -3
  231. package/dist/docs/api/types/type-aliases/EcsEntityEditorKind.md +1 -1
  232. package/dist/docs/api/types/type-aliases/EcsEntityKind.md +3 -2
  233. package/dist/docs/api/types/type-aliases/EntityId.md +1 -1
  234. package/dist/docs/api/types/type-aliases/EntityInput.md +3 -3
  235. package/dist/docs/api/types/type-aliases/FloatInput.md +1 -1
  236. package/dist/docs/api/types/type-aliases/IntersectionResult.md +3 -3
  237. package/dist/docs/api/types/type-aliases/ParentLookup.md +3 -3
  238. package/dist/docs/api/types/type-aliases/SelectionListener.md +1 -1
  239. package/dist/docs/api/types/type-aliases/SliderInput.md +5 -5
  240. package/dist/docs/api/types/type-aliases/TextInput.md +1 -1
  241. package/dist/docs/api/types/type-aliases/ToggleInput.md +1 -1
  242. package/dist/docs/api/types/type-aliases/Vec3.md +1 -1
  243. package/dist/docs/api/types/type-aliases/Vector2Input.md +3 -3
  244. package/dist/docs/api/types/type-aliases/Vector3Input.md +4 -4
  245. package/dist/docs/api/types/type-aliases/WorldEntityView.md +1 -1
  246. package/dist/docs/guide/components/_sidebar.json +4 -0
  247. package/dist/docs/guide/components/material.md +1 -0
  248. package/dist/docs/guide/components/script-object.md +32 -0
  249. package/dist/factories/index.cjs +271 -118
  250. package/dist/factories/index.cjs.map +1 -1
  251. package/dist/factories/index.d.cts +9 -3
  252. package/dist/factories/index.d.ts +9 -3
  253. package/dist/factories/index.js +3 -3
  254. package/dist/{index-Gr8aCPRM.d.cts → index-CUFd71ri.d.cts} +12 -3
  255. package/dist/index-D84o_UA6.d.ts +488 -0
  256. package/dist/index-YYypJaVw.d.cts +488 -0
  257. package/dist/{index-BwiRJNIT.d.ts → index-w1oqWl_M.d.ts} +12 -3
  258. package/dist/index.cjs +1014 -208
  259. package/dist/index.cjs.map +1 -1
  260. package/dist/index.d.cts +42 -8
  261. package/dist/index.d.ts +42 -8
  262. package/dist/index.js +24 -8
  263. package/dist/index.js.map +1 -1
  264. package/dist/systems/index.cjs +717 -12
  265. package/dist/systems/index.cjs.map +1 -1
  266. package/dist/systems/index.d.cts +3 -278
  267. package/dist/systems/index.d.ts +3 -278
  268. package/dist/systems/index.js +3 -3
  269. package/dist/types.d.cts +1 -1
  270. package/dist/types.d.ts +1 -1
  271. package/dist/worldSnapshotUtils.d.cts +1 -1
  272. package/dist/worldSnapshotUtils.d.ts +1 -1
  273. package/package.json +4 -4
  274. package/dist/chunk-3P3ZBP7K.js.map +0 -1
  275. package/dist/chunk-J6736FFO.js.map +0 -1
  276. package/dist/chunk-RJ4J5UEX.js.map +0 -1
@@ -333,7 +333,7 @@ type EntityId = number;
333
333
  * maps to an object factory in `core/factories/objects/*` that creates the
334
334
  * baseline component set.
335
335
  */
336
- type EcsEntityKind = "cube" | "sphere" | "plane" | "capsule" | "cylinder" | "empty" | "model" | "image" | "imageTarget" | "sprite" | "audio" | "camera" | "video" | "ambientLight" | "directionalLight" | "pointLight" | "spotLight" | "areaLight" | "instancedMesh" | "instanceSlot" | "scriptObject";
336
+ type EcsEntityKind = "cube" | "sphere" | "plane" | "capsule" | "cylinder" | "empty" | "model" | "image" | "imageTarget" | "sprite" | "audio" | "camera" | "video" | "ambientLight" | "directionalLight" | "pointLight" | "spotLight" | "areaLight" | "instancedMesh" | "instanceSlot" | "scriptObject" | "xrRig" | "teleportArea";
337
337
  /** {@link EcsEntityKind} extended with editor-only utility entities (gizmos, helpers). */
338
338
  type EcsEntityEditorKind = EcsEntityKind | "editorUtility";
339
339
  /** Callback invoked when the selected entity changes. `null` indicates a deselection. */
@@ -612,7 +612,7 @@ type CreateContext = {
612
612
  isEditor?: boolean;
613
613
  };
614
614
  type EntityFactory = (context: CreateContext) => EntityId;
615
- type EcsComponentFactoryKind = "animation" | "audio" | "camera" | "environment" | "entityType" | "image" | "imageTargetAnchor" | "imageTarget" | "light" | "material" | "mesh" | "meshGeometry" | "model" | "name" | "object3DRef" | "parentId" | "physics" | "postprocessing" | "script" | "scriptObject" | "selectable" | "selectionTransformState" | "sprite" | "transform" | "video" | "instancedMesh";
615
+ type EcsComponentFactoryKind = "animation" | "audio" | "camera" | "environment" | "entityType" | "image" | "imageTargetAnchor" | "imageTarget" | "light" | "material" | "mesh" | "meshGeometry" | "model" | "name" | "object3DRef" | "parentId" | "physics" | "postprocessing" | "script" | "scriptObject" | "selectable" | "selectionTransformState" | "sprite" | "transform" | "video" | "instancedMesh" | "xrRig" | "vrTeleportArea" | "xrInteractable";
616
616
  type ComponentFactory = (world: World, entityId: EntityId, ...args: any[]) => unknown;
617
617
  declare class ObjectManagementSystem implements EcsSystem {
618
618
  private readonly scene;
@@ -952,6 +952,20 @@ declare class World {
952
952
  renderSystem: RenderSystem;
953
953
  };
954
954
  isEditorMode(): boolean;
955
+ /**
956
+ * `true` while an immersive WebXR session is actively presenting.
957
+ *
958
+ * While presenting, three's `WebXRManager` OWNS the render camera: each frame
959
+ * `updateUserCamera()` writes the headset pose into the camera's
960
+ * position/quaternion/scale and copies the XR projection (including a derived
961
+ * `fov`) onto it. Systems that also drive the camera must stand down for the
962
+ * duration, or they ping-pong with the headset every frame and defeat their
963
+ * own dirty-checks.
964
+ *
965
+ * Locomotion therefore moves the camera's PARENT (the XR rig) — three composes
966
+ * the head pose as `parent.matrixWorld × headPose`.
967
+ */
968
+ isXrPresenting(): boolean;
955
969
  /**
956
970
  * Pauses world simulation. While paused, `update()` skips all system ticks so
957
971
  * physics, animation, scripts, and rendering stop advancing. The last rendered
@@ -333,7 +333,7 @@ type EntityId = number;
333
333
  * maps to an object factory in `core/factories/objects/*` that creates the
334
334
  * baseline component set.
335
335
  */
336
- type EcsEntityKind = "cube" | "sphere" | "plane" | "capsule" | "cylinder" | "empty" | "model" | "image" | "imageTarget" | "sprite" | "audio" | "camera" | "video" | "ambientLight" | "directionalLight" | "pointLight" | "spotLight" | "areaLight" | "instancedMesh" | "instanceSlot" | "scriptObject";
336
+ type EcsEntityKind = "cube" | "sphere" | "plane" | "capsule" | "cylinder" | "empty" | "model" | "image" | "imageTarget" | "sprite" | "audio" | "camera" | "video" | "ambientLight" | "directionalLight" | "pointLight" | "spotLight" | "areaLight" | "instancedMesh" | "instanceSlot" | "scriptObject" | "xrRig" | "teleportArea";
337
337
  /** {@link EcsEntityKind} extended with editor-only utility entities (gizmos, helpers). */
338
338
  type EcsEntityEditorKind = EcsEntityKind | "editorUtility";
339
339
  /** Callback invoked when the selected entity changes. `null` indicates a deselection. */
@@ -612,7 +612,7 @@ type CreateContext = {
612
612
  isEditor?: boolean;
613
613
  };
614
614
  type EntityFactory = (context: CreateContext) => EntityId;
615
- type EcsComponentFactoryKind = "animation" | "audio" | "camera" | "environment" | "entityType" | "image" | "imageTargetAnchor" | "imageTarget" | "light" | "material" | "mesh" | "meshGeometry" | "model" | "name" | "object3DRef" | "parentId" | "physics" | "postprocessing" | "script" | "scriptObject" | "selectable" | "selectionTransformState" | "sprite" | "transform" | "video" | "instancedMesh";
615
+ type EcsComponentFactoryKind = "animation" | "audio" | "camera" | "environment" | "entityType" | "image" | "imageTargetAnchor" | "imageTarget" | "light" | "material" | "mesh" | "meshGeometry" | "model" | "name" | "object3DRef" | "parentId" | "physics" | "postprocessing" | "script" | "scriptObject" | "selectable" | "selectionTransformState" | "sprite" | "transform" | "video" | "instancedMesh" | "xrRig" | "vrTeleportArea" | "xrInteractable";
616
616
  type ComponentFactory = (world: World, entityId: EntityId, ...args: any[]) => unknown;
617
617
  declare class ObjectManagementSystem implements EcsSystem {
618
618
  private readonly scene;
@@ -952,6 +952,20 @@ declare class World {
952
952
  renderSystem: RenderSystem;
953
953
  };
954
954
  isEditorMode(): boolean;
955
+ /**
956
+ * `true` while an immersive WebXR session is actively presenting.
957
+ *
958
+ * While presenting, three's `WebXRManager` OWNS the render camera: each frame
959
+ * `updateUserCamera()` writes the headset pose into the camera's
960
+ * position/quaternion/scale and copies the XR projection (including a derived
961
+ * `fov`) onto it. Systems that also drive the camera must stand down for the
962
+ * duration, or they ping-pong with the headset every frame and defeat their
963
+ * own dirty-checks.
964
+ *
965
+ * Locomotion therefore moves the camera's PARENT (the XR rig) — three composes
966
+ * the head pose as `parent.matrixWorld × headPose`.
967
+ */
968
+ isXrPresenting(): boolean;
955
969
  /**
956
970
  * Pauses world simulation. While paused, `update()` skips all system ticks so
957
971
  * physics, animation, scripts, and rendering stop advancing. The last rendered
@@ -1,5 +1,5 @@
1
1
  import * as THREE from 'three';
2
- import { C as Component, p as EcsEntityKind, F as EcsEntityEditorKind, r as EntityId } from './System-CYWZ_Zx5.cjs';
2
+ import { C as Component, p as EcsEntityKind, F as EcsEntityEditorKind, r as EntityId } from './System-vrU46Vuw.js';
3
3
  import * as RAPIER from '@dimforge/rapier3d-compat';
4
4
 
5
5
  interface StateMachine {
@@ -172,8 +172,12 @@ declare class AnimationComponent extends Component {
172
172
  stopState(name?: string): boolean;
173
173
  }
174
174
 
175
- /** Runtime camera mode. `3d` is a free camera; `ar` is composited over a tracked image/face feed. */
176
- type CameraRuntimeType = "3d" | "ar";
175
+ /**
176
+ * Runtime camera mode. `3d` is a free camera; `ar` is composited over a tracked
177
+ * image/face feed; `xr` is driven by an immersive WebXR session (the headset
178
+ * owns the pose and projection — locomotion moves the camera's XR rig parent).
179
+ */
180
+ type CameraRuntimeType = "3d" | "ar" | "xr";
177
181
  /** Projection model. */
178
182
  type CameraProjection = "perspective" | "orthographic";
179
183
  /** Optional initializer for {@link CameraComponent}. Any field omitted falls back to the defaults documented on the component. */
@@ -1168,4 +1172,127 @@ declare class VideoComponent extends Component {
1168
1172
  stop(): void;
1169
1173
  }
1170
1174
 
1171
- export { SpriteComponent as $, AnimationComponent as A, MeshGeometryComponent as B, CameraComponent as C, DEFAULT_COLLIDER_STATE as D, type EditableMeshObjectKind as E, type MeshGeometryParameters as F, type MeshGeometryParametersByKind as G, ModelComponent as H, ImageComponent as I, type PhysicsState as J, type PlaneMeshParameters as K, LightComponent as L, MaterialComponent as M, Name as N, Object3DRef as O, PhysicsComponent as P, type RadiusMeshParameters as Q, type RadiusHeightMeshParameters as R, type RigidbodyState as S, type RigidbodyType as T, ScriptComponent as U, type ScriptEntry as V, ScriptObjectComponent as W, type ScriptObjectComponentInput as X, type ScriptObjectRuntimeState as Y, Selectable as Z, SelectionTransformState as _, type AnimationComponentOptions as a, type TextureFilteringValue as a0, type TransformModeValue as a1, type TransformSpaceValue as a2, VideoComponent as a3, defaultMaterialValue as a4, normalizePhysicsState as a5, setPhysicsLiveRef as a6, type AnimationStateCallbacks as a7, AnimationStateMachine as a8, AnimationStateManager as a9, type StateMachine as aa, AudioComponent as b, type CameraComponentOptions as c, type CameraProjection as d, type CameraRuntimeType as e, type ColliderShape as f, type ColliderState as g, type CubeMeshParameters as h, DEFAULT_INSTANCED_MESH_PARAMETERS as i, DEFAULT_INSTANCE_TRANSFORM as j, DEFAULT_MESH_GEOMETRY_PARAMETERS as k, DEFAULT_PHYSICS_STATE as l, DEFAULT_RIGIDBODY_STATE as m, EntityType as n, ImageTarget as o, ImageTargetAnchor as p, type ImageTargetAnchorOptions as q, type ImageTargetReference as r, InstanceSlotComponent as s, type InstanceTransform as t, InstancedMeshComponent as u, type InstancedMeshKind as v, type LightValueState as w, type MaterialTypeValue as x, type MaterialValueState as y, MeshComponent as z };
1175
+ /** Footprint of a teleport destination. */
1176
+ type VrTeleportShape = "plane" | "cylinder";
1177
+ /** Optional initializer for {@link VRTeleportAreaComponent}. */
1178
+ type VRTeleportAreaOptions = {
1179
+ /** Disable to keep the area authored but inert. */
1180
+ enabled?: boolean;
1181
+ /** Footprint shape. */
1182
+ shape?: VrTeleportShape;
1183
+ /** Full width in metres (`plane`), or diameter (`cylinder`). */
1184
+ width?: number;
1185
+ /** Full depth in metres. Ignored for `cylinder`, which uses `width`. */
1186
+ depth?: number;
1187
+ };
1188
+ /**
1189
+ * Marks an entity's surface as a valid teleport destination.
1190
+ *
1191
+ * Teleport is an allow-list, not a physics query: only entities carrying an
1192
+ * enabled area can be teleported onto. That keeps destinations deliberate —
1193
+ * authors decide where the player may stand rather than discovering that every
1194
+ * collider in the scene is walkable.
1195
+ *
1196
+ * @category Components
1197
+ */
1198
+ declare class VRTeleportAreaComponent extends Component {
1199
+ /** Whether this area currently accepts teleports. */
1200
+ enabled: boolean;
1201
+ /** Footprint shape. */
1202
+ shape: VrTeleportShape;
1203
+ /** Full width in metres (diameter for `cylinder`). */
1204
+ width: number;
1205
+ /** Full depth in metres (unused for `cylinder`). */
1206
+ depth: number;
1207
+ constructor(options?: VRTeleportAreaOptions);
1208
+ }
1209
+
1210
+ /**
1211
+ * How a grabbed entity behaves while held.
1212
+ *
1213
+ * `kinematic` snaps it to the hand and ignores physics — predictable, and the
1214
+ * right default. `physics` keeps the body simulated so it can collide while
1215
+ * held and carry momentum when thrown.
1216
+ */
1217
+ type XrGrabMode = "kinematic" | "physics";
1218
+ /** Optional initializer for {@link XRInteractableComponent}. */
1219
+ type XRInteractableOptions = {
1220
+ /** Disable to keep the entity authored but non-interactive. */
1221
+ enabled?: boolean;
1222
+ /** Can be picked up and held. */
1223
+ grabbable?: boolean;
1224
+ /** Can be hit by a pointer ray (hover + select), without being grabbable. */
1225
+ pointable?: boolean;
1226
+ /** Behaviour while held. */
1227
+ grabMode?: XrGrabMode;
1228
+ /** Emphasize the entity while a pointer is over it. */
1229
+ highlightOnHover?: boolean;
1230
+ };
1231
+ /**
1232
+ * Makes an entity respond to XR pointers and hands.
1233
+ *
1234
+ * Split into `pointable` and `grabbable` because they are genuinely different
1235
+ * affordances: a wall-mounted UI panel should receive select events without
1236
+ * being liftable, while a physics prop should be both. Interaction is opt-in
1237
+ * per entity so a scene's interactive surface is explicit.
1238
+ *
1239
+ * @category Components
1240
+ */
1241
+ declare class XRInteractableComponent extends Component {
1242
+ /** Whether this entity currently responds to XR input. */
1243
+ enabled: boolean;
1244
+ /** Can be picked up and held. */
1245
+ grabbable: boolean;
1246
+ /** Can be hit by a pointer ray. */
1247
+ pointable: boolean;
1248
+ /** Behaviour while held. */
1249
+ grabMode: XrGrabMode;
1250
+ /** Emphasize while hovered. */
1251
+ highlightOnHover: boolean;
1252
+ constructor(options?: XRInteractableOptions);
1253
+ }
1254
+
1255
+ /** How the player moves through the scene in an immersive session. */
1256
+ type XrLocomotionMode = "teleport" | "smooth" | "none";
1257
+ /** Optional initializer for {@link XRRigComponent}. */
1258
+ type XRRigOptions = {
1259
+ /** Movement style. Defaults to `teleport` — the most comfort-safe option. */
1260
+ locomotion?: XrLocomotionMode;
1261
+ /** Metres/second for `smooth` locomotion. */
1262
+ moveSpeed?: number;
1263
+ /** Rotate in fixed steps instead of continuously (greatly reduces nausea). */
1264
+ snapTurn?: boolean;
1265
+ /** Degrees per snap-turn step. */
1266
+ snapTurnDegrees?: number;
1267
+ /** Height in metres used when the device reports no floor-relative space. */
1268
+ fallbackEyeHeight?: number;
1269
+ };
1270
+ /**
1271
+ * Marks an entity as the XR rig — the player's movable origin.
1272
+ *
1273
+ * The rig exists because a WebXR headset owns the camera pose absolutely: three
1274
+ * composes the render camera as `rig.matrixWorld × headPose`, so the ONLY way
1275
+ * to move the player is to move the camera's parent. The camera entity must be
1276
+ * a child of this entity.
1277
+ *
1278
+ * Defaults are deliberately comfort-first — teleport locomotion with snap
1279
+ * turning is the combination least likely to cause motion sickness, and is what
1280
+ * every platform's design guidance recommends as the baseline.
1281
+ *
1282
+ * @category Components
1283
+ */
1284
+ declare class XRRigComponent extends Component {
1285
+ /** Movement style. */
1286
+ locomotion: XrLocomotionMode;
1287
+ /** Metres/second for `smooth` locomotion. */
1288
+ moveSpeed: number;
1289
+ /** Rotate in fixed steps rather than continuously. */
1290
+ snapTurn: boolean;
1291
+ /** Degrees per snap-turn step. */
1292
+ snapTurnDegrees: number;
1293
+ /** Eye height fallback for devices without a floor-relative reference space. */
1294
+ fallbackEyeHeight: number;
1295
+ constructor(options?: XRRigOptions);
1296
+ }
1297
+
1298
+ export { SpriteComponent as $, AnimationComponent as A, MeshGeometryComponent as B, CameraComponent as C, DEFAULT_COLLIDER_STATE as D, type EditableMeshObjectKind as E, type MeshGeometryParameters as F, type MeshGeometryParametersByKind as G, ModelComponent as H, ImageComponent as I, type PhysicsState as J, type PlaneMeshParameters as K, LightComponent as L, MaterialComponent as M, Name as N, Object3DRef as O, PhysicsComponent as P, type RadiusMeshParameters as Q, type RadiusHeightMeshParameters as R, type RigidbodyState as S, type RigidbodyType as T, ScriptComponent as U, type ScriptEntry as V, ScriptObjectComponent as W, type ScriptObjectComponentInput as X, type ScriptObjectRuntimeState as Y, Selectable as Z, SelectionTransformState as _, type AnimationComponentOptions as a, type TextureFilteringValue as a0, type TransformModeValue as a1, type TransformSpaceValue as a2, VRTeleportAreaComponent as a3, type VRTeleportAreaOptions as a4, VideoComponent as a5, type VrTeleportShape as a6, XRInteractableComponent as a7, type XRInteractableOptions as a8, XRRigComponent as a9, type XRRigOptions as aa, type XrGrabMode as ab, type XrLocomotionMode as ac, defaultMaterialValue as ad, normalizePhysicsState as ae, setPhysicsLiveRef as af, type AnimationStateCallbacks as ag, AnimationStateMachine as ah, AnimationStateManager as ai, type StateMachine as aj, AudioComponent as b, type CameraComponentOptions as c, type CameraProjection as d, type CameraRuntimeType as e, type ColliderShape as f, type ColliderState as g, type CubeMeshParameters as h, DEFAULT_INSTANCED_MESH_PARAMETERS as i, DEFAULT_INSTANCE_TRANSFORM as j, DEFAULT_MESH_GEOMETRY_PARAMETERS as k, DEFAULT_PHYSICS_STATE as l, DEFAULT_RIGIDBODY_STATE as m, EntityType as n, ImageTarget as o, ImageTargetAnchor as p, type ImageTargetAnchorOptions as q, type ImageTargetReference as r, InstanceSlotComponent as s, type InstanceTransform as t, InstancedMeshComponent as u, type InstancedMeshKind as v, type LightValueState as w, type MaterialTypeValue as x, type MaterialValueState as y, MeshComponent as z };
@@ -1,5 +1,5 @@
1
1
  import * as THREE from 'three';
2
- import { C as Component, p as EcsEntityKind, F as EcsEntityEditorKind, r as EntityId } from './System-CYWZ_Zx5.js';
2
+ import { C as Component, p as EcsEntityKind, F as EcsEntityEditorKind, r as EntityId } from './System-vrU46Vuw.cjs';
3
3
  import * as RAPIER from '@dimforge/rapier3d-compat';
4
4
 
5
5
  interface StateMachine {
@@ -172,8 +172,12 @@ declare class AnimationComponent extends Component {
172
172
  stopState(name?: string): boolean;
173
173
  }
174
174
 
175
- /** Runtime camera mode. `3d` is a free camera; `ar` is composited over a tracked image/face feed. */
176
- type CameraRuntimeType = "3d" | "ar";
175
+ /**
176
+ * Runtime camera mode. `3d` is a free camera; `ar` is composited over a tracked
177
+ * image/face feed; `xr` is driven by an immersive WebXR session (the headset
178
+ * owns the pose and projection — locomotion moves the camera's XR rig parent).
179
+ */
180
+ type CameraRuntimeType = "3d" | "ar" | "xr";
177
181
  /** Projection model. */
178
182
  type CameraProjection = "perspective" | "orthographic";
179
183
  /** Optional initializer for {@link CameraComponent}. Any field omitted falls back to the defaults documented on the component. */
@@ -1168,4 +1172,127 @@ declare class VideoComponent extends Component {
1168
1172
  stop(): void;
1169
1173
  }
1170
1174
 
1171
- export { SpriteComponent as $, AnimationComponent as A, MeshGeometryComponent as B, CameraComponent as C, DEFAULT_COLLIDER_STATE as D, type EditableMeshObjectKind as E, type MeshGeometryParameters as F, type MeshGeometryParametersByKind as G, ModelComponent as H, ImageComponent as I, type PhysicsState as J, type PlaneMeshParameters as K, LightComponent as L, MaterialComponent as M, Name as N, Object3DRef as O, PhysicsComponent as P, type RadiusMeshParameters as Q, type RadiusHeightMeshParameters as R, type RigidbodyState as S, type RigidbodyType as T, ScriptComponent as U, type ScriptEntry as V, ScriptObjectComponent as W, type ScriptObjectComponentInput as X, type ScriptObjectRuntimeState as Y, Selectable as Z, SelectionTransformState as _, type AnimationComponentOptions as a, type TextureFilteringValue as a0, type TransformModeValue as a1, type TransformSpaceValue as a2, VideoComponent as a3, defaultMaterialValue as a4, normalizePhysicsState as a5, setPhysicsLiveRef as a6, type AnimationStateCallbacks as a7, AnimationStateMachine as a8, AnimationStateManager as a9, type StateMachine as aa, AudioComponent as b, type CameraComponentOptions as c, type CameraProjection as d, type CameraRuntimeType as e, type ColliderShape as f, type ColliderState as g, type CubeMeshParameters as h, DEFAULT_INSTANCED_MESH_PARAMETERS as i, DEFAULT_INSTANCE_TRANSFORM as j, DEFAULT_MESH_GEOMETRY_PARAMETERS as k, DEFAULT_PHYSICS_STATE as l, DEFAULT_RIGIDBODY_STATE as m, EntityType as n, ImageTarget as o, ImageTargetAnchor as p, type ImageTargetAnchorOptions as q, type ImageTargetReference as r, InstanceSlotComponent as s, type InstanceTransform as t, InstancedMeshComponent as u, type InstancedMeshKind as v, type LightValueState as w, type MaterialTypeValue as x, type MaterialValueState as y, MeshComponent as z };
1175
+ /** Footprint of a teleport destination. */
1176
+ type VrTeleportShape = "plane" | "cylinder";
1177
+ /** Optional initializer for {@link VRTeleportAreaComponent}. */
1178
+ type VRTeleportAreaOptions = {
1179
+ /** Disable to keep the area authored but inert. */
1180
+ enabled?: boolean;
1181
+ /** Footprint shape. */
1182
+ shape?: VrTeleportShape;
1183
+ /** Full width in metres (`plane`), or diameter (`cylinder`). */
1184
+ width?: number;
1185
+ /** Full depth in metres. Ignored for `cylinder`, which uses `width`. */
1186
+ depth?: number;
1187
+ };
1188
+ /**
1189
+ * Marks an entity's surface as a valid teleport destination.
1190
+ *
1191
+ * Teleport is an allow-list, not a physics query: only entities carrying an
1192
+ * enabled area can be teleported onto. That keeps destinations deliberate —
1193
+ * authors decide where the player may stand rather than discovering that every
1194
+ * collider in the scene is walkable.
1195
+ *
1196
+ * @category Components
1197
+ */
1198
+ declare class VRTeleportAreaComponent extends Component {
1199
+ /** Whether this area currently accepts teleports. */
1200
+ enabled: boolean;
1201
+ /** Footprint shape. */
1202
+ shape: VrTeleportShape;
1203
+ /** Full width in metres (diameter for `cylinder`). */
1204
+ width: number;
1205
+ /** Full depth in metres (unused for `cylinder`). */
1206
+ depth: number;
1207
+ constructor(options?: VRTeleportAreaOptions);
1208
+ }
1209
+
1210
+ /**
1211
+ * How a grabbed entity behaves while held.
1212
+ *
1213
+ * `kinematic` snaps it to the hand and ignores physics — predictable, and the
1214
+ * right default. `physics` keeps the body simulated so it can collide while
1215
+ * held and carry momentum when thrown.
1216
+ */
1217
+ type XrGrabMode = "kinematic" | "physics";
1218
+ /** Optional initializer for {@link XRInteractableComponent}. */
1219
+ type XRInteractableOptions = {
1220
+ /** Disable to keep the entity authored but non-interactive. */
1221
+ enabled?: boolean;
1222
+ /** Can be picked up and held. */
1223
+ grabbable?: boolean;
1224
+ /** Can be hit by a pointer ray (hover + select), without being grabbable. */
1225
+ pointable?: boolean;
1226
+ /** Behaviour while held. */
1227
+ grabMode?: XrGrabMode;
1228
+ /** Emphasize the entity while a pointer is over it. */
1229
+ highlightOnHover?: boolean;
1230
+ };
1231
+ /**
1232
+ * Makes an entity respond to XR pointers and hands.
1233
+ *
1234
+ * Split into `pointable` and `grabbable` because they are genuinely different
1235
+ * affordances: a wall-mounted UI panel should receive select events without
1236
+ * being liftable, while a physics prop should be both. Interaction is opt-in
1237
+ * per entity so a scene's interactive surface is explicit.
1238
+ *
1239
+ * @category Components
1240
+ */
1241
+ declare class XRInteractableComponent extends Component {
1242
+ /** Whether this entity currently responds to XR input. */
1243
+ enabled: boolean;
1244
+ /** Can be picked up and held. */
1245
+ grabbable: boolean;
1246
+ /** Can be hit by a pointer ray. */
1247
+ pointable: boolean;
1248
+ /** Behaviour while held. */
1249
+ grabMode: XrGrabMode;
1250
+ /** Emphasize while hovered. */
1251
+ highlightOnHover: boolean;
1252
+ constructor(options?: XRInteractableOptions);
1253
+ }
1254
+
1255
+ /** How the player moves through the scene in an immersive session. */
1256
+ type XrLocomotionMode = "teleport" | "smooth" | "none";
1257
+ /** Optional initializer for {@link XRRigComponent}. */
1258
+ type XRRigOptions = {
1259
+ /** Movement style. Defaults to `teleport` — the most comfort-safe option. */
1260
+ locomotion?: XrLocomotionMode;
1261
+ /** Metres/second for `smooth` locomotion. */
1262
+ moveSpeed?: number;
1263
+ /** Rotate in fixed steps instead of continuously (greatly reduces nausea). */
1264
+ snapTurn?: boolean;
1265
+ /** Degrees per snap-turn step. */
1266
+ snapTurnDegrees?: number;
1267
+ /** Height in metres used when the device reports no floor-relative space. */
1268
+ fallbackEyeHeight?: number;
1269
+ };
1270
+ /**
1271
+ * Marks an entity as the XR rig — the player's movable origin.
1272
+ *
1273
+ * The rig exists because a WebXR headset owns the camera pose absolutely: three
1274
+ * composes the render camera as `rig.matrixWorld × headPose`, so the ONLY way
1275
+ * to move the player is to move the camera's parent. The camera entity must be
1276
+ * a child of this entity.
1277
+ *
1278
+ * Defaults are deliberately comfort-first — teleport locomotion with snap
1279
+ * turning is the combination least likely to cause motion sickness, and is what
1280
+ * every platform's design guidance recommends as the baseline.
1281
+ *
1282
+ * @category Components
1283
+ */
1284
+ declare class XRRigComponent extends Component {
1285
+ /** Movement style. */
1286
+ locomotion: XrLocomotionMode;
1287
+ /** Metres/second for `smooth` locomotion. */
1288
+ moveSpeed: number;
1289
+ /** Rotate in fixed steps rather than continuously. */
1290
+ snapTurn: boolean;
1291
+ /** Degrees per snap-turn step. */
1292
+ snapTurnDegrees: number;
1293
+ /** Eye height fallback for devices without a floor-relative reference space. */
1294
+ fallbackEyeHeight: number;
1295
+ constructor(options?: XRRigOptions);
1296
+ }
1297
+
1298
+ export { SpriteComponent as $, AnimationComponent as A, MeshGeometryComponent as B, CameraComponent as C, DEFAULT_COLLIDER_STATE as D, type EditableMeshObjectKind as E, type MeshGeometryParameters as F, type MeshGeometryParametersByKind as G, ModelComponent as H, ImageComponent as I, type PhysicsState as J, type PlaneMeshParameters as K, LightComponent as L, MaterialComponent as M, Name as N, Object3DRef as O, PhysicsComponent as P, type RadiusMeshParameters as Q, type RadiusHeightMeshParameters as R, type RigidbodyState as S, type RigidbodyType as T, ScriptComponent as U, type ScriptEntry as V, ScriptObjectComponent as W, type ScriptObjectComponentInput as X, type ScriptObjectRuntimeState as Y, Selectable as Z, SelectionTransformState as _, type AnimationComponentOptions as a, type TextureFilteringValue as a0, type TransformModeValue as a1, type TransformSpaceValue as a2, VRTeleportAreaComponent as a3, type VRTeleportAreaOptions as a4, VideoComponent as a5, type VrTeleportShape as a6, XRInteractableComponent as a7, type XRInteractableOptions as a8, XRRigComponent as a9, type XRRigOptions as aa, type XrGrabMode as ab, type XrLocomotionMode as ac, defaultMaterialValue as ad, normalizePhysicsState as ae, setPhysicsLiveRef as af, type AnimationStateCallbacks as ag, AnimationStateMachine as ah, AnimationStateManager as ai, type StateMachine as aj, AudioComponent as b, type CameraComponentOptions as c, type CameraProjection as d, type CameraRuntimeType as e, type ColliderShape as f, type ColliderState as g, type CubeMeshParameters as h, DEFAULT_INSTANCED_MESH_PARAMETERS as i, DEFAULT_INSTANCE_TRANSFORM as j, DEFAULT_MESH_GEOMETRY_PARAMETERS as k, DEFAULT_PHYSICS_STATE as l, DEFAULT_RIGIDBODY_STATE as m, EntityType as n, ImageTarget as o, ImageTargetAnchor as p, type ImageTargetAnchorOptions as q, type ImageTargetReference as r, InstanceSlotComponent as s, type InstanceTransform as t, InstancedMeshComponent as u, type InstancedMeshKind as v, type LightValueState as w, type MaterialTypeValue as x, type MaterialValueState as y, MeshComponent as z };
@@ -1,4 +1,4 @@
1
- import { TransformComponent, Object3DRef, ParentId } from './chunk-J6736FFO.js';
1
+ import { TransformComponent, Object3DRef, ParentId } from './chunk-U3MDYKPV.js';
2
2
  import { __name } from './chunk-OY7ZODZP.js';
3
3
  import * as THREE2 from 'three';
4
4
  import { clone } from 'three/examples/jsm/utils/SkeletonUtils.js';
@@ -311,5 +311,5 @@ function resolveDracoDecoderPath() {
311
311
  __name(resolveDracoDecoderPath, "resolveDracoDecoderPath");
312
312
 
313
313
  export { ObjectManagementSystem, SHARED_MODEL_RESOURCE_FLAG, applyTransform, clearModelCache, cloneModelScene, createTransform, loadSharedGltf, resolveDracoDecoderPath, setDracoDecoderPath };
314
- //# sourceMappingURL=chunk-XFD74BQL.js.map
315
- //# sourceMappingURL=chunk-XFD74BQL.js.map
314
+ //# sourceMappingURL=chunk-67WGASUJ.js.map
315
+ //# sourceMappingURL=chunk-67WGASUJ.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../core/utils/modelCache.ts","../core/systems/ObjectManagementSystem.ts","../core/utils/dracoDecoderPath.ts"],"names":["THREE","cloneWithSkeleton"],"mappings":"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","file":"chunk-XFD74BQL.js","sourcesContent":["import * as THREE from \"three\";\nimport type { GLTF } from \"three/examples/jsm/loaders/GLTFLoader.js\";\nimport { clone as cloneWithSkeleton } from \"three/examples/jsm/utils/SkeletonUtils.js\";\n\n/**\n * userData flag set on geometries/materials that back shared (cached) model\n * scenes. Entity disposal must skip these — other live clones and future\n * spawns reference the same GPU resources.\n */\nexport const SHARED_MODEL_RESOURCE_FLAG = \"spatialEcsSharedModelResource\";\n\nconst modelCache = new Map<string, Promise<GLTF>>();\n\nfunction markSharedResources(root: THREE.Object3D): void {\n root.traverse((child) => {\n if (!(child instanceof THREE.Mesh)) {\n return;\n }\n if (child.geometry) {\n child.geometry.userData[SHARED_MODEL_RESOURCE_FLAG] = true;\n }\n const materials = Array.isArray(child.material)\n ? child.material\n : [child.material];\n for (const material of materials) {\n if (material) {\n material.userData[SHARED_MODEL_RESOURCE_FLAG] = true;\n }\n }\n });\n}\n\n/**\n * Load a GLTF once per URL and share the parsed result, so repeated spawns of\n * the same model skip both the fetch and the parse. The cached scene must\n * never be mounted directly (an Object3D has a single parent) — mount a\n * cloneModelScene() of it. Failed loads are evicted so a retry re-fetches.\n */\nexport function loadSharedGltf(\n url: string,\n load: () => Promise<GLTF>,\n): Promise<GLTF> {\n let pending = modelCache.get(url);\n if (!pending) {\n pending = load().then((gltf) => {\n markSharedResources(gltf.scene);\n return gltf;\n });\n pending.catch(() => {\n modelCache.delete(url);\n });\n modelCache.set(url, pending);\n }\n return pending;\n}\n\n/**\n * Skeleton-aware clone of a cached model scene for mounting. Geometries and\n * materials are shared with the cached original (marked via\n * SHARED_MODEL_RESOURCE_FLAG); the object hierarchy — including rebound\n * skeletons for skinned meshes — is fresh per call.\n */\nexport function cloneModelScene(scene: THREE.Object3D): THREE.Object3D {\n return cloneWithSkeleton(scene);\n}\n\n/**\n * Forget cached models (one URL, or everything). Subsequent loads fetch and\n * parse anew. Does not dispose GPU resources — live clones may still use them.\n */\nexport function clearModelCache(url?: string): void {\n if (typeof url === \"string\") {\n modelCache.delete(url);\n return;\n }\n modelCache.clear();\n}\n","import * as THREE from \"three\";\n\nimport { Object3DRef } from \"../components/Object3DRef\";\nimport { ParentId } from \"../components/ParentId\";\nimport type { TransformData } from \"../components/Transform\";\nimport { TransformComponent } from \"../components/Transform\";\nimport type { EcsSystem } from \"../System\";\nimport { SHARED_MODEL_RESOURCE_FLAG } from \"../utils/modelCache\";\nimport type { World } from \"../World\";\nimport type { EntityId, EcsEntityKind } from \"../types\";\n\nexport type CreatePayload = {\n name?: string;\n transform?: TransformData;\n parentId?: EntityId | null;\n path?: string;\n options?: Record<string, unknown>;\n camera?: Record<string, unknown>;\n useWorldCamera?: boolean;\n};\n\nexport type CreateContext = {\n world: World;\n scene: THREE.Scene;\n camera: THREE.PerspectiveCamera;\n payload: CreatePayload;\n isEditor?: boolean;\n};\n\nexport type EntityFactory = (context: CreateContext) => EntityId;\n\nexport type EcsComponentFactoryKind =\n | \"animation\"\n | \"audio\"\n | \"camera\"\n | \"environment\"\n | \"entityType\"\n | \"image\"\n | \"imageTargetAnchor\"\n | \"imageTarget\"\n | \"light\"\n | \"material\"\n | \"mesh\"\n | \"meshGeometry\"\n | \"model\"\n | \"name\"\n | \"object3DRef\"\n | \"parentId\"\n | \"physics\"\n | \"postprocessing\"\n | \"script\"\n | \"scriptObject\"\n | \"selectable\"\n | \"selectionTransformState\"\n | \"sprite\"\n | \"transform\"\n | \"video\"\n | \"instancedMesh\";\n\nexport type ComponentFactory = (\n world: World,\n entityId: EntityId,\n ...args: any[]\n) => unknown;\n\ntype CreateRequest = {\n kind: EcsEntityKind;\n payload: CreatePayload;\n onCreated?: (entityId: EntityId) => void;\n};\n\nexport function createTransform(input?: TransformData): TransformComponent {\n return new TransformComponent(input);\n}\n\nexport function applyTransform(\n object: THREE.Object3D,\n transform: TransformComponent,\n): void {\n object.position.set(\n transform.position.x,\n transform.position.y,\n transform.position.z,\n );\n object.rotation.set(\n transform.rotation.x,\n transform.rotation.y,\n transform.rotation.z,\n );\n object.scale.set(transform.scale.x, transform.scale.y, transform.scale.z);\n}\n\nexport class ObjectManagementSystem implements EcsSystem {\n private readonly scene: THREE.Scene;\n private readonly camera: THREE.PerspectiveCamera;\n private readonly isEditor: boolean;\n private readonly registry = new Map<EcsEntityKind, EntityFactory>();\n private readonly componentRegistry = new Map<\n EcsComponentFactoryKind,\n ComponentFactory\n >();\n private readonly createQueue: CreateRequest[] = [];\n\n constructor(\n scene: THREE.Scene,\n camera: THREE.PerspectiveCamera,\n isEditor = false,\n ) {\n this.scene = scene;\n this.camera = camera;\n this.isEditor = isEditor;\n }\n\n register(kind: EcsEntityKind, factory: EntityFactory): void {\n this.registry.set(kind, factory);\n }\n\n registerComponentFactory(\n kind: EcsComponentFactoryKind,\n factory: ComponentFactory,\n ): void {\n this.componentRegistry.set(kind, factory);\n }\n\n getOrCreateAudioListener(): THREE.AudioListener {\n const existing = this.camera.userData.ecsAudioListener;\n if (existing instanceof THREE.AudioListener) {\n return existing;\n }\n\n const listener = new THREE.AudioListener();\n this.camera.add(listener);\n this.camera.userData.ecsAudioListener = listener;\n return listener;\n }\n\n isEditorMode(): boolean {\n return this.isEditor;\n }\n\n getComponentFactory(kind: EcsComponentFactoryKind): ComponentFactory | null {\n return this.componentRegistry.get(kind) ?? null;\n }\n\n createComponentNow(\n kind: EcsComponentFactoryKind,\n world: World,\n entityId: EntityId,\n ...args: any[]\n ): unknown {\n const factory = this.componentRegistry.get(kind);\n if (!factory) {\n throw new Error(`Unknown component kind: ${kind}`);\n }\n\n return factory(world, entityId, ...args);\n }\n\n requestCreate(\n kind: EcsEntityKind,\n payload: CreatePayload = {},\n onCreated?: (entityId: EntityId) => void,\n ): void {\n this.createQueue.push({ kind, payload, onCreated });\n }\n\n createNow(\n kind: EcsEntityKind,\n world: World,\n payload: CreatePayload = {},\n ): EntityId {\n const factory = this.registry.get(kind);\n if (!factory) {\n throw new Error(`Unknown object kind: ${kind}`);\n }\n\n const entityId = factory({\n world,\n scene: this.scene,\n camera: this.camera,\n payload,\n isEditor: this.isEditor,\n });\n\n const object = world.getComponent(entityId, Object3DRef)?.object;\n if (object) {\n object.userData.ecsKind = kind;\n }\n\n if (payload.parentId !== undefined) {\n world.addComponent(entityId, new ParentId(payload.parentId));\n }\n\n return entityId;\n }\n\n /**\n * Removes an entity from the ECS world and its associated `Object3D` from the\n * THREE.js scene graph.\n *\n * @param world - The world the entity belongs to.\n * @param entityId - The entity to remove.\n * @param dispose - When `true`, traverses the entity's `Object3D` subtree and\n * calls `.dispose()` on every `BufferGeometry` and `Material` found. Pass\n * `true` when the entity will not be reused and you want to free GPU memory\n * immediately (e.g. dynamically spawned objects). Defaults to `false`.\n * @returns `true` if the entity existed and was removed; `false` if the entity\n * was not found.\n *\n * @example\n * ```ts\n * // Remove from scene, keep GPU resources (safe if geometry is shared)\n * objects.deleteEntity(world, entityId);\n *\n * // Remove from scene and free GPU memory (use for one-off spawned objects)\n * objects.deleteEntity(world, entityId, true);\n * ```\n */\n deleteEntity(world: World, entityId: EntityId, dispose = false): boolean {\n if (!world.hasEntity(entityId)) {\n return false;\n }\n\n const object3d = world.getComponent(entityId, Object3DRef)?.object;\n if (object3d?.parent) {\n object3d.parent.remove(object3d);\n }\n\n if (dispose && object3d) {\n object3d.traverse((child) => {\n if (child instanceof THREE.Mesh) {\n // Resources backing shared (cached) model scenes are skipped —\n // other live clones and future spawns reference the same objects.\n if (!child.geometry?.userData?.[SHARED_MODEL_RESOURCE_FLAG]) {\n child.geometry?.dispose();\n }\n const materials = Array.isArray(child.material)\n ? child.material\n : [child.material];\n for (const mat of materials) {\n if (mat && !mat.userData?.[SHARED_MODEL_RESOURCE_FLAG]) {\n mat.dispose();\n }\n }\n }\n });\n }\n\n world.destroyEntity(entityId);\n return true;\n }\n\n setParent(\n world: World,\n entityId: EntityId,\n parentId: EntityId | null,\n options?: {\n preserveWorldTransform?: boolean;\n },\n ): boolean {\n if (!world.hasEntity(entityId)) {\n return false;\n }\n\n if (parentId !== null && !world.hasEntity(parentId)) {\n return false;\n }\n\n if (parentId === entityId) {\n return false;\n }\n\n let ancestor = parentId;\n while (ancestor !== null) {\n if (ancestor === entityId) {\n return false;\n }\n\n ancestor = world.getComponent(ancestor, ParentId)?.value ?? null;\n }\n\n const parentComponent = world.getComponent(entityId, ParentId);\n if (parentComponent) {\n if (parentComponent.value === parentId) {\n return false;\n }\n\n parentComponent.value = parentId;\n } else {\n world.addComponent(entityId, new ParentId(parentId));\n }\n\n const preserveWorldTransform = options?.preserveWorldTransform ?? true;\n if (preserveWorldTransform) {\n const object = world.getComponent(entityId, Object3DRef)?.object;\n const parentObject =\n parentId !== null\n ? world.getComponent(parentId, Object3DRef)?.object ?? null\n : null;\n\n if (object) {\n // Refresh matrixWorld before attach so world-space preservation is accurate.\n this.scene.updateMatrixWorld(true);\n\n if (parentObject && parentObject !== object) {\n parentObject.attach(object);\n } else {\n this.scene.attach(object);\n }\n\n object.updateMatrixWorld(true);\n this.syncTransformComponentFromObject(world, entityId, object);\n }\n }\n\n this.reconcileSceneFromWorld(world);\n return true;\n }\n\n private syncTransformComponentFromObject(\n world: World,\n entityId: EntityId,\n object: THREE.Object3D,\n ): void {\n const transform = world.getComponent(entityId, TransformComponent);\n if (!transform) {\n return;\n }\n\n transform.position.x = object.position.x;\n transform.position.y = object.position.y;\n transform.position.z = object.position.z;\n\n transform.rotation.x = object.rotation.x;\n transform.rotation.y = object.rotation.y;\n transform.rotation.z = object.rotation.z;\n\n transform.scale.x = object.scale.x;\n transform.scale.y = object.scale.y;\n transform.scale.z = object.scale.z;\n }\n\n reconcileSceneFromWorld(world: World): void {\n const worldObjects = new Map<EntityId, THREE.Object3D>();\n const entityIds = world.query(Object3DRef);\n\n for (const entityId of entityIds) {\n const object = world.getComponent(entityId, Object3DRef)?.object;\n if (!object) {\n continue;\n }\n\n worldObjects.set(entityId, object);\n }\n\n for (const child of [...this.scene.children]) {\n const entityId = child.userData?.entityId;\n if (typeof entityId === \"number\" && !world.hasEntity(entityId)) {\n this.scene.remove(child);\n }\n }\n\n for (const [entityId, object] of worldObjects.entries()) {\n const parentEntityId = world.getComponent(entityId, ParentId)?.value;\n const parentObject =\n typeof parentEntityId === \"number\"\n ? worldObjects.get(parentEntityId)\n : undefined;\n\n if (parentObject && parentObject !== object) {\n if (object.parent !== parentObject) {\n // Reconcile hierarchy from ParentId while keeping Transform as local source of truth.\n parentObject.add(object);\n object.updateMatrixWorld(true);\n }\n continue;\n }\n\n if (object.parent !== this.scene) {\n // Reconcile hierarchy from ParentId while keeping Transform as local source of truth.\n this.scene.add(object);\n object.updateMatrixWorld(true);\n }\n }\n }\n\n update(world: World): void {\n for (const request of this.createQueue.splice(0)) {\n const entityId = this.createNow(request.kind, world, request.payload);\n request.onCreated?.(entityId);\n }\n\n this.reconcileSceneFromWorld(world);\n }\n}\n","const LOCAL_DRACO_DECODER_RELATIVE_PATH = \"./assets/draco/\";\nexport const DRACO_DECODER_CDN_PATH =\n \"https://www.gstatic.com/draco/versioned/decoders/1.5.7/\";\n\nlet dracoDecoderPathOverride: string | null = null;\n\n/**\n * Override where the DRACO decoder files (draco_wasm_wrapper.js,\n * draco_decoder.wasm, draco_decoder.js) are fetched from. Embedding apps\n * whose bundlers relocate this package's chunks — making the default\n * import.meta.url resolution point at a location that is never populated —\n * should call this before any model loads. The path must end with \"/\".\n * Pass null to restore the default resolution.\n */\nexport function setDracoDecoderPath(path: string | null): void {\n dracoDecoderPathOverride = path;\n}\n\nfunction isBlockedBrowserFileUrl(url: string): boolean {\n return url.startsWith(\"file://\");\n}\n\nexport function resolveDracoDecoderPath(): string {\n if (dracoDecoderPathOverride) {\n return dracoDecoderPathOverride;\n }\n\n try {\n // Prefer vendored decoder assets shipped with this package.\n const resolvedPath = new URL(\n LOCAL_DRACO_DECODER_RELATIVE_PATH,\n import.meta.url,\n ).toString();\n\n // Browser loaders cannot fetch file:// resources from package install paths.\n // Fall back to CDN decoders when bundlers emit file URLs for node_modules assets.\n if (isBlockedBrowserFileUrl(resolvedPath)) {\n return DRACO_DECODER_CDN_PATH;\n }\n\n return resolvedPath;\n } catch {\n // Fallback keeps compatibility in runtimes that cannot resolve package-relative URLs.\n return DRACO_DECODER_CDN_PATH;\n }\n}\n"]}
1
+ {"version":3,"sources":["../core/utils/modelCache.ts","../core/systems/ObjectManagementSystem.ts","../core/utils/dracoDecoderPath.ts"],"names":["THREE","cloneWithSkeleton"],"mappings":";;;;;AASO,IAAM,0BAAA,GAA6B;AAE1C,IAAM,UAAA,uBAAiB,GAAA,EAA2B;AAElD,SAAS,oBAAoB,IAAA,EAA4B;AACvD,EAAA,IAAA,CAAK,QAAA,CAAS,CAAC,KAAA,KAAU;AACvB,IAAA,IAAI,EAAE,iBAAuBA,MAAA,CAAA,IAAA,CAAA,EAAO;AAClC,MAAA;AAAA,IACF;AACA,IAAA,IAAI,MAAM,QAAA,EAAU;AAClB,MAAA,KAAA,CAAM,QAAA,CAAS,QAAA,CAAS,0BAA0B,CAAA,GAAI,IAAA;AAAA,IACxD;AACA,IAAA,MAAM,SAAA,GAAY,KAAA,CAAM,OAAA,CAAQ,KAAA,CAAM,QAAQ,IAC1C,KAAA,CAAM,QAAA,GACN,CAAC,KAAA,CAAM,QAAQ,CAAA;AACnB,IAAA,KAAA,MAAW,YAAY,SAAA,EAAW;AAChC,MAAA,IAAI,QAAA,EAAU;AACZ,QAAA,QAAA,CAAS,QAAA,CAAS,0BAA0B,CAAA,GAAI,IAAA;AAAA,MAClD;AAAA,IACF;AAAA,EACF,CAAC,CAAA;AACH;AAjBS,MAAA,CAAA,mBAAA,EAAA,qBAAA,CAAA;AAyBF,SAAS,cAAA,CACd,KACA,IAAA,EACe;AACf,EAAA,IAAI,OAAA,GAAU,UAAA,CAAW,GAAA,CAAI,GAAG,CAAA;AAChC,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,OAAA,GAAU,IAAA,EAAK,CAAE,IAAA,CAAK,CAAC,IAAA,KAAS;AAC9B,MAAA,mBAAA,CAAoB,KAAK,KAAK,CAAA;AAC9B,MAAA,OAAO,IAAA;AAAA,IACT,CAAC,CAAA;AACD,IAAA,OAAA,CAAQ,MAAM,MAAM;AAClB,MAAA,UAAA,CAAW,OAAO,GAAG,CAAA;AAAA,IACvB,CAAC,CAAA;AACD,IAAA,UAAA,CAAW,GAAA,CAAI,KAAK,OAAO,CAAA;AAAA,EAC7B;AACA,EAAA,OAAO,OAAA;AACT;AAhBgB,MAAA,CAAA,cAAA,EAAA,gBAAA,CAAA;AAwBT,SAAS,gBAAgB,KAAA,EAAuC;AACrE,EAAA,OAAOC,MAAkB,KAAK,CAAA;AAChC;AAFgB,MAAA,CAAA,eAAA,EAAA,iBAAA,CAAA;AAQT,SAAS,gBAAgB,GAAA,EAAoB;AAClD,EAAA,IAAI,OAAO,QAAQ,QAAA,EAAU;AAC3B,IAAA,UAAA,CAAW,OAAO,GAAG,CAAA;AACrB,IAAA;AAAA,EACF;AACA,EAAA,UAAA,CAAW,KAAA,EAAM;AACnB;AANgB,MAAA,CAAA,eAAA,EAAA,iBAAA,CAAA;ACIT,SAAS,gBAAgB,KAAA,EAA2C;AACzE,EAAA,OAAO,IAAI,mBAAmB,KAAK,CAAA;AACrC;AAFgB,MAAA,CAAA,eAAA,EAAA,iBAAA,CAAA;AAIT,SAAS,cAAA,CACd,QACA,SAAA,EACM;AACN,EAAA,MAAA,CAAO,QAAA,CAAS,GAAA;AAAA,IACd,UAAU,QAAA,CAAS,CAAA;AAAA,IACnB,UAAU,QAAA,CAAS,CAAA;AAAA,IACnB,UAAU,QAAA,CAAS;AAAA,GACrB;AACA,EAAA,MAAA,CAAO,QAAA,CAAS,GAAA;AAAA,IACd,UAAU,QAAA,CAAS,CAAA;AAAA,IACnB,UAAU,QAAA,CAAS,CAAA;AAAA,IACnB,UAAU,QAAA,CAAS;AAAA,GACrB;AACA,EAAA,MAAA,CAAO,KAAA,CAAM,GAAA,CAAI,SAAA,CAAU,KAAA,CAAM,CAAA,EAAG,UAAU,KAAA,CAAM,CAAA,EAAG,SAAA,CAAU,KAAA,CAAM,CAAC,CAAA;AAC1E;AAfgB,MAAA,CAAA,cAAA,EAAA,gBAAA,CAAA;AAiBT,IAAM,uBAAA,GAAN,MAAM,uBAAA,CAA4C;AAAA,EAWvD,WAAA,CACE,KAAA,EACA,MAAA,EACA,QAAA,GAAW,KAAA,EACX;AAXF,IAAA,IAAA,CAAiB,QAAA,uBAAe,GAAA,EAAkC;AAClE,IAAA,IAAA,CAAiB,iBAAA,uBAAwB,GAAA,EAGvC;AACF,IAAA,IAAA,CAAiB,cAA+B,EAAC;AAO/C,IAAA,IAAA,CAAK,KAAA,GAAQ,KAAA;AACb,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,QAAA,GAAW,QAAA;AAAA,EAClB;AAAA,EAEA,QAAA,CAAS,MAAqB,OAAA,EAA8B;AAC1D,IAAA,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,IAAA,EAAM,OAAO,CAAA;AAAA,EACjC;AAAA,EAEA,wBAAA,CACE,MACA,OAAA,EACM;AACN,IAAA,IAAA,CAAK,iBAAA,CAAkB,GAAA,CAAI,IAAA,EAAM,OAAO,CAAA;AAAA,EAC1C;AAAA,EAEA,wBAAA,GAAgD;AAC9C,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,MAAA,CAAO,QAAA,CAAS,gBAAA;AACtC,IAAA,IAAI,oBAA0B,MAAA,CAAA,aAAA,EAAe;AAC3C,MAAA,OAAO,QAAA;AAAA,IACT;AAEA,IAAA,MAAM,QAAA,GAAW,IAAU,MAAA,CAAA,aAAA,EAAc;AACzC,IAAA,IAAA,CAAK,MAAA,CAAO,IAAI,QAAQ,CAAA;AACxB,IAAA,IAAA,CAAK,MAAA,CAAO,SAAS,gBAAA,GAAmB,QAAA;AACxC,IAAA,OAAO,QAAA;AAAA,EACT;AAAA,EAEA,YAAA,GAAwB;AACtB,IAAA,OAAO,IAAA,CAAK,QAAA;AAAA,EACd;AAAA,EAEA,oBAAoB,IAAA,EAAwD;AAC1E,IAAA,OAAO,IAAA,CAAK,iBAAA,CAAkB,GAAA,CAAI,IAAI,CAAA,IAAK,IAAA;AAAA,EAC7C;AAAA,EAEA,kBAAA,CACE,IAAA,EACA,KAAA,EACA,QAAA,EAAA,GACG,IAAA,EACM;AACT,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,iBAAA,CAAkB,GAAA,CAAI,IAAI,CAAA;AAC/C,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,wBAAA,EAA2B,IAAI,CAAA,CAAE,CAAA;AAAA,IACnD;AAEA,IAAA,OAAO,OAAA,CAAQ,KAAA,EAAO,QAAA,EAAU,GAAG,IAAI,CAAA;AAAA,EACzC;AAAA,EAEA,aAAA,CACE,IAAA,EACA,OAAA,GAAyB,IACzB,SAAA,EACM;AACN,IAAA,IAAA,CAAK,YAAY,IAAA,CAAK,EAAE,IAAA,EAAM,OAAA,EAAS,WAAW,CAAA;AAAA,EACpD;AAAA,EAEA,SAAA,CACE,IAAA,EACA,KAAA,EACA,OAAA,GAAyB,EAAC,EAChB;AACV,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,IAAI,CAAA;AACtC,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,qBAAA,EAAwB,IAAI,CAAA,CAAE,CAAA;AAAA,IAChD;AAEA,IAAA,MAAM,WAAW,OAAA,CAAQ;AAAA,MACvB,KAAA;AAAA,MACA,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,OAAA;AAAA,MACA,UAAU,IAAA,CAAK;AAAA,KAChB,CAAA;AAED,IAAA,MAAM,MAAA,GAAS,KAAA,CAAM,YAAA,CAAa,QAAA,EAAU,WAAW,CAAA,EAAG,MAAA;AAC1D,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,MAAA,CAAO,SAAS,OAAA,GAAU,IAAA;AAAA,IAC5B;AAEA,IAAA,IAAI,OAAA,CAAQ,aAAa,MAAA,EAAW;AAClC,MAAA,KAAA,CAAM,aAAa,QAAA,EAAU,IAAI,QAAA,CAAS,OAAA,CAAQ,QAAQ,CAAC,CAAA;AAAA,IAC7D;AAEA,IAAA,OAAO,QAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwBA,YAAA,CAAa,KAAA,EAAc,QAAA,EAAoB,OAAA,GAAU,KAAA,EAAgB;AACvE,IAAA,IAAI,CAAC,KAAA,CAAM,SAAA,CAAU,QAAQ,CAAA,EAAG;AAC9B,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,MAAM,QAAA,GAAW,KAAA,CAAM,YAAA,CAAa,QAAA,EAAU,WAAW,CAAA,EAAG,MAAA;AAC5D,IAAA,IAAI,UAAU,MAAA,EAAQ;AACpB,MAAA,QAAA,CAAS,MAAA,CAAO,OAAO,QAAQ,CAAA;AAAA,IACjC;AAEA,IAAA,IAAI,WAAW,QAAA,EAAU;AACvB,MAAA,QAAA,CAAS,QAAA,CAAS,CAAC,KAAA,KAAU;AAC3B,QAAA,IAAI,iBAAuB,MAAA,CAAA,IAAA,EAAM;AAG/B,UAAA,IAAI,CAAC,KAAA,CAAM,QAAA,EAAU,QAAA,GAAW,0BAA0B,CAAA,EAAG;AAC3D,YAAA,KAAA,CAAM,UAAU,OAAA,EAAQ;AAAA,UAC1B;AACA,UAAA,MAAM,SAAA,GAAY,KAAA,CAAM,OAAA,CAAQ,KAAA,CAAM,QAAQ,IAC1C,KAAA,CAAM,QAAA,GACN,CAAC,KAAA,CAAM,QAAQ,CAAA;AACnB,UAAA,KAAA,MAAW,OAAO,SAAA,EAAW;AAC3B,YAAA,IAAI,GAAA,IAAO,CAAC,GAAA,CAAI,QAAA,GAAW,0BAA0B,CAAA,EAAG;AACtD,cAAA,GAAA,CAAI,OAAA,EAAQ;AAAA,YACd;AAAA,UACF;AAAA,QACF;AAAA,MACF,CAAC,CAAA;AAAA,IACH;AAEA,IAAA,KAAA,CAAM,cAAc,QAAQ,CAAA;AAC5B,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,SAAA,CACE,KAAA,EACA,QAAA,EACA,QAAA,EACA,OAAA,EAGS;AACT,IAAA,IAAI,CAAC,KAAA,CAAM,SAAA,CAAU,QAAQ,CAAA,EAAG;AAC9B,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,IAAI,aAAa,IAAA,IAAQ,CAAC,KAAA,CAAM,SAAA,CAAU,QAAQ,CAAA,EAAG;AACnD,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,IAAI,aAAa,QAAA,EAAU;AACzB,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,IAAI,QAAA,GAAW,QAAA;AACf,IAAA,OAAO,aAAa,IAAA,EAAM;AACxB,MAAA,IAAI,aAAa,QAAA,EAAU;AACzB,QAAA,OAAO,KAAA;AAAA,MACT;AAEA,MAAA,QAAA,GAAW,KAAA,CAAM,YAAA,CAAa,QAAA,EAAU,QAAQ,GAAG,KAAA,IAAS,IAAA;AAAA,IAC9D;AAEA,IAAA,MAAM,eAAA,GAAkB,KAAA,CAAM,YAAA,CAAa,QAAA,EAAU,QAAQ,CAAA;AAC7D,IAAA,IAAI,eAAA,EAAiB;AACnB,MAAA,IAAI,eAAA,CAAgB,UAAU,QAAA,EAAU;AACtC,QAAA,OAAO,KAAA;AAAA,MACT;AAEA,MAAA,eAAA,CAAgB,KAAA,GAAQ,QAAA;AAAA,IAC1B,CAAA,MAAO;AACL,MAAA,KAAA,CAAM,YAAA,CAAa,QAAA,EAAU,IAAI,QAAA,CAAS,QAAQ,CAAC,CAAA;AAAA,IACrD;AAEA,IAAA,MAAM,sBAAA,GAAyB,SAAS,sBAAA,IAA0B,IAAA;AAClE,IAAA,IAAI,sBAAA,EAAwB;AAC1B,MAAA,MAAM,MAAA,GAAS,KAAA,CAAM,YAAA,CAAa,QAAA,EAAU,WAAW,CAAA,EAAG,MAAA;AAC1D,MAAA,MAAM,YAAA,GACJ,aAAa,IAAA,GACT,KAAA,CAAM,aAAa,QAAA,EAAU,WAAW,CAAA,EAAG,MAAA,IAAU,IAAA,GACrD,IAAA;AAEN,MAAA,IAAI,MAAA,EAAQ;AAEV,QAAA,IAAA,CAAK,KAAA,CAAM,kBAAkB,IAAI,CAAA;AAEjC,QAAA,IAAI,YAAA,IAAgB,iBAAiB,MAAA,EAAQ;AAC3C,UAAA,YAAA,CAAa,OAAO,MAAM,CAAA;AAAA,QAC5B,CAAA,MAAO;AACL,UAAA,IAAA,CAAK,KAAA,CAAM,OAAO,MAAM,CAAA;AAAA,QAC1B;AAEA,QAAA,MAAA,CAAO,kBAAkB,IAAI,CAAA;AAC7B,QAAA,IAAA,CAAK,gCAAA,CAAiC,KAAA,EAAO,QAAA,EAAU,MAAM,CAAA;AAAA,MAC/D;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,wBAAwB,KAAK,CAAA;AAClC,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEQ,gCAAA,CACN,KAAA,EACA,QAAA,EACA,MAAA,EACM;AACN,IAAA,MAAM,SAAA,GAAY,KAAA,CAAM,YAAA,CAAa,QAAA,EAAU,kBAAkB,CAAA;AACjE,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA;AAAA,IACF;AAEA,IAAA,SAAA,CAAU,QAAA,CAAS,CAAA,GAAI,MAAA,CAAO,QAAA,CAAS,CAAA;AACvC,IAAA,SAAA,CAAU,QAAA,CAAS,CAAA,GAAI,MAAA,CAAO,QAAA,CAAS,CAAA;AACvC,IAAA,SAAA,CAAU,QAAA,CAAS,CAAA,GAAI,MAAA,CAAO,QAAA,CAAS,CAAA;AAEvC,IAAA,SAAA,CAAU,QAAA,CAAS,CAAA,GAAI,MAAA,CAAO,QAAA,CAAS,CAAA;AACvC,IAAA,SAAA,CAAU,QAAA,CAAS,CAAA,GAAI,MAAA,CAAO,QAAA,CAAS,CAAA;AACvC,IAAA,SAAA,CAAU,QAAA,CAAS,CAAA,GAAI,MAAA,CAAO,QAAA,CAAS,CAAA;AAEvC,IAAA,SAAA,CAAU,KAAA,CAAM,CAAA,GAAI,MAAA,CAAO,KAAA,CAAM,CAAA;AACjC,IAAA,SAAA,CAAU,KAAA,CAAM,CAAA,GAAI,MAAA,CAAO,KAAA,CAAM,CAAA;AACjC,IAAA,SAAA,CAAU,KAAA,CAAM,CAAA,GAAI,MAAA,CAAO,KAAA,CAAM,CAAA;AAAA,EACnC;AAAA,EAEA,wBAAwB,KAAA,EAAoB;AAC1C,IAAA,MAAM,YAAA,uBAAmB,GAAA,EAA8B;AACvD,IAAA,MAAM,SAAA,GAAY,KAAA,CAAM,KAAA,CAAM,WAAW,CAAA;AAEzC,IAAA,KAAA,MAAW,YAAY,SAAA,EAAW;AAChC,MAAA,MAAM,MAAA,GAAS,KAAA,CAAM,YAAA,CAAa,QAAA,EAAU,WAAW,CAAA,EAAG,MAAA;AAC1D,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA;AAAA,MACF;AAEA,MAAA,YAAA,CAAa,GAAA,CAAI,UAAU,MAAM,CAAA;AAAA,IACnC;AAEA,IAAA,KAAA,MAAW,SAAS,CAAC,GAAG,IAAA,CAAK,KAAA,CAAM,QAAQ,CAAA,EAAG;AAC5C,MAAA,MAAM,QAAA,GAAW,MAAM,QAAA,EAAU,QAAA;AACjC,MAAA,IAAI,OAAO,QAAA,KAAa,QAAA,IAAY,CAAC,KAAA,CAAM,SAAA,CAAU,QAAQ,CAAA,EAAG;AAC9D,QAAA,IAAA,CAAK,KAAA,CAAM,OAAO,KAAK,CAAA;AAAA,MACzB;AAAA,IACF;AAEA,IAAA,KAAA,MAAW,CAAC,QAAA,EAAU,MAAM,CAAA,IAAK,YAAA,CAAa,SAAQ,EAAG;AACvD,MAAA,MAAM,cAAA,GAAiB,KAAA,CAAM,YAAA,CAAa,QAAA,EAAU,QAAQ,CAAA,EAAG,KAAA;AAC/D,MAAA,MAAM,eACJ,OAAO,cAAA,KAAmB,WACtB,YAAA,CAAa,GAAA,CAAI,cAAc,CAAA,GAC/B,MAAA;AAEN,MAAA,IAAI,YAAA,IAAgB,iBAAiB,MAAA,EAAQ;AAC3C,QAAA,IAAI,MAAA,CAAO,WAAW,YAAA,EAAc;AAElC,UAAA,YAAA,CAAa,IAAI,MAAM,CAAA;AACvB,UAAA,MAAA,CAAO,kBAAkB,IAAI,CAAA;AAAA,QAC/B;AACA,QAAA;AAAA,MACF;AAEA,MAAA,IAAI,MAAA,CAAO,MAAA,KAAW,IAAA,CAAK,KAAA,EAAO;AAEhC,QAAA,IAAA,CAAK,KAAA,CAAM,IAAI,MAAM,CAAA;AACrB,QAAA,MAAA,CAAO,kBAAkB,IAAI,CAAA;AAAA,MAC/B;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAO,KAAA,EAAoB;AACzB,IAAA,KAAA,MAAW,OAAA,IAAW,IAAA,CAAK,WAAA,CAAY,MAAA,CAAO,CAAC,CAAA,EAAG;AAChD,MAAA,MAAM,WAAW,IAAA,CAAK,SAAA,CAAU,QAAQ,IAAA,EAAM,KAAA,EAAO,QAAQ,OAAO,CAAA;AACpE,MAAA,OAAA,CAAQ,YAAY,QAAQ,CAAA;AAAA,IAC9B;AAEA,IAAA,IAAA,CAAK,wBAAwB,KAAK,CAAA;AAAA,EACpC;AACF,CAAA;AA9SyD,MAAA,CAAA,uBAAA,EAAA,wBAAA,CAAA;AAAlD,IAAM,sBAAA,GAAN;;;AC/FP,IAAM,iCAAA,GAAoC,iBAAA;AACnC,IAAM,sBAAA,GACX,yDAAA;AAEF,IAAI,wBAAA,GAA0C,IAAA;AAUvC,SAAS,oBAAoB,IAAA,EAA2B;AAC7D,EAAA,wBAAA,GAA2B,IAAA;AAC7B;AAFgB,MAAA,CAAA,mBAAA,EAAA,qBAAA,CAAA;AAIhB,SAAS,wBAAwB,GAAA,EAAsB;AACrD,EAAA,OAAO,GAAA,CAAI,WAAW,SAAS,CAAA;AACjC;AAFS,MAAA,CAAA,uBAAA,EAAA,yBAAA,CAAA;AAIF,SAAS,uBAAA,GAAkC;AAChD,EAAA,IAAI,wBAAA,EAA0B;AAC5B,IAAA,OAAO,wBAAA;AAAA,EACT;AAEA,EAAA,IAAI;AAEF,IAAA,MAAM,eAAe,IAAI,GAAA;AAAA,MACvB,iCAAA;AAAA,MACA,MAAA,CAAA,IAAA,CAAY;AAAA,MACZ,QAAA,EAAS;AAIX,IAAA,IAAI,uBAAA,CAAwB,YAAY,CAAA,EAAG;AACzC,MAAA,OAAO,sBAAA;AAAA,IACT;AAEA,IAAA,OAAO,YAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AAEN,IAAA,OAAO,sBAAA;AAAA,EACT;AACF;AAvBgB,MAAA,CAAA,uBAAA,EAAA,yBAAA,CAAA","file":"chunk-67WGASUJ.js","sourcesContent":["import * as THREE from \"three\";\nimport type { GLTF } from \"three/examples/jsm/loaders/GLTFLoader.js\";\nimport { clone as cloneWithSkeleton } from \"three/examples/jsm/utils/SkeletonUtils.js\";\n\n/**\n * userData flag set on geometries/materials that back shared (cached) model\n * scenes. Entity disposal must skip these — other live clones and future\n * spawns reference the same GPU resources.\n */\nexport const SHARED_MODEL_RESOURCE_FLAG = \"spatialEcsSharedModelResource\";\n\nconst modelCache = new Map<string, Promise<GLTF>>();\n\nfunction markSharedResources(root: THREE.Object3D): void {\n root.traverse((child) => {\n if (!(child instanceof THREE.Mesh)) {\n return;\n }\n if (child.geometry) {\n child.geometry.userData[SHARED_MODEL_RESOURCE_FLAG] = true;\n }\n const materials = Array.isArray(child.material)\n ? child.material\n : [child.material];\n for (const material of materials) {\n if (material) {\n material.userData[SHARED_MODEL_RESOURCE_FLAG] = true;\n }\n }\n });\n}\n\n/**\n * Load a GLTF once per URL and share the parsed result, so repeated spawns of\n * the same model skip both the fetch and the parse. The cached scene must\n * never be mounted directly (an Object3D has a single parent) — mount a\n * cloneModelScene() of it. Failed loads are evicted so a retry re-fetches.\n */\nexport function loadSharedGltf(\n url: string,\n load: () => Promise<GLTF>,\n): Promise<GLTF> {\n let pending = modelCache.get(url);\n if (!pending) {\n pending = load().then((gltf) => {\n markSharedResources(gltf.scene);\n return gltf;\n });\n pending.catch(() => {\n modelCache.delete(url);\n });\n modelCache.set(url, pending);\n }\n return pending;\n}\n\n/**\n * Skeleton-aware clone of a cached model scene for mounting. Geometries and\n * materials are shared with the cached original (marked via\n * SHARED_MODEL_RESOURCE_FLAG); the object hierarchy — including rebound\n * skeletons for skinned meshes — is fresh per call.\n */\nexport function cloneModelScene(scene: THREE.Object3D): THREE.Object3D {\n return cloneWithSkeleton(scene);\n}\n\n/**\n * Forget cached models (one URL, or everything). Subsequent loads fetch and\n * parse anew. Does not dispose GPU resources — live clones may still use them.\n */\nexport function clearModelCache(url?: string): void {\n if (typeof url === \"string\") {\n modelCache.delete(url);\n return;\n }\n modelCache.clear();\n}\n","import * as THREE from \"three\";\n\nimport { Object3DRef } from \"../components/Object3DRef\";\nimport { ParentId } from \"../components/ParentId\";\nimport type { TransformData } from \"../components/Transform\";\nimport { TransformComponent } from \"../components/Transform\";\nimport type { EcsSystem } from \"../System\";\nimport { SHARED_MODEL_RESOURCE_FLAG } from \"../utils/modelCache\";\nimport type { World } from \"../World\";\nimport type { EntityId, EcsEntityKind } from \"../types\";\n\nexport type CreatePayload = {\n name?: string;\n transform?: TransformData;\n parentId?: EntityId | null;\n path?: string;\n options?: Record<string, unknown>;\n camera?: Record<string, unknown>;\n useWorldCamera?: boolean;\n};\n\nexport type CreateContext = {\n world: World;\n scene: THREE.Scene;\n camera: THREE.PerspectiveCamera;\n payload: CreatePayload;\n isEditor?: boolean;\n};\n\nexport type EntityFactory = (context: CreateContext) => EntityId;\n\nexport type EcsComponentFactoryKind =\n | \"animation\"\n | \"audio\"\n | \"camera\"\n | \"environment\"\n | \"entityType\"\n | \"image\"\n | \"imageTargetAnchor\"\n | \"imageTarget\"\n | \"light\"\n | \"material\"\n | \"mesh\"\n | \"meshGeometry\"\n | \"model\"\n | \"name\"\n | \"object3DRef\"\n | \"parentId\"\n | \"physics\"\n | \"postprocessing\"\n | \"script\"\n | \"scriptObject\"\n | \"selectable\"\n | \"selectionTransformState\"\n | \"sprite\"\n | \"transform\"\n | \"video\"\n | \"instancedMesh\"\n | \"xrRig\"\n | \"vrTeleportArea\"\n | \"xrInteractable\";\n\nexport type ComponentFactory = (\n world: World,\n entityId: EntityId,\n ...args: any[]\n) => unknown;\n\ntype CreateRequest = {\n kind: EcsEntityKind;\n payload: CreatePayload;\n onCreated?: (entityId: EntityId) => void;\n};\n\nexport function createTransform(input?: TransformData): TransformComponent {\n return new TransformComponent(input);\n}\n\nexport function applyTransform(\n object: THREE.Object3D,\n transform: TransformComponent,\n): void {\n object.position.set(\n transform.position.x,\n transform.position.y,\n transform.position.z,\n );\n object.rotation.set(\n transform.rotation.x,\n transform.rotation.y,\n transform.rotation.z,\n );\n object.scale.set(transform.scale.x, transform.scale.y, transform.scale.z);\n}\n\nexport class ObjectManagementSystem implements EcsSystem {\n private readonly scene: THREE.Scene;\n private readonly camera: THREE.PerspectiveCamera;\n private readonly isEditor: boolean;\n private readonly registry = new Map<EcsEntityKind, EntityFactory>();\n private readonly componentRegistry = new Map<\n EcsComponentFactoryKind,\n ComponentFactory\n >();\n private readonly createQueue: CreateRequest[] = [];\n\n constructor(\n scene: THREE.Scene,\n camera: THREE.PerspectiveCamera,\n isEditor = false,\n ) {\n this.scene = scene;\n this.camera = camera;\n this.isEditor = isEditor;\n }\n\n register(kind: EcsEntityKind, factory: EntityFactory): void {\n this.registry.set(kind, factory);\n }\n\n registerComponentFactory(\n kind: EcsComponentFactoryKind,\n factory: ComponentFactory,\n ): void {\n this.componentRegistry.set(kind, factory);\n }\n\n getOrCreateAudioListener(): THREE.AudioListener {\n const existing = this.camera.userData.ecsAudioListener;\n if (existing instanceof THREE.AudioListener) {\n return existing;\n }\n\n const listener = new THREE.AudioListener();\n this.camera.add(listener);\n this.camera.userData.ecsAudioListener = listener;\n return listener;\n }\n\n isEditorMode(): boolean {\n return this.isEditor;\n }\n\n getComponentFactory(kind: EcsComponentFactoryKind): ComponentFactory | null {\n return this.componentRegistry.get(kind) ?? null;\n }\n\n createComponentNow(\n kind: EcsComponentFactoryKind,\n world: World,\n entityId: EntityId,\n ...args: any[]\n ): unknown {\n const factory = this.componentRegistry.get(kind);\n if (!factory) {\n throw new Error(`Unknown component kind: ${kind}`);\n }\n\n return factory(world, entityId, ...args);\n }\n\n requestCreate(\n kind: EcsEntityKind,\n payload: CreatePayload = {},\n onCreated?: (entityId: EntityId) => void,\n ): void {\n this.createQueue.push({ kind, payload, onCreated });\n }\n\n createNow(\n kind: EcsEntityKind,\n world: World,\n payload: CreatePayload = {},\n ): EntityId {\n const factory = this.registry.get(kind);\n if (!factory) {\n throw new Error(`Unknown object kind: ${kind}`);\n }\n\n const entityId = factory({\n world,\n scene: this.scene,\n camera: this.camera,\n payload,\n isEditor: this.isEditor,\n });\n\n const object = world.getComponent(entityId, Object3DRef)?.object;\n if (object) {\n object.userData.ecsKind = kind;\n }\n\n if (payload.parentId !== undefined) {\n world.addComponent(entityId, new ParentId(payload.parentId));\n }\n\n return entityId;\n }\n\n /**\n * Removes an entity from the ECS world and its associated `Object3D` from the\n * THREE.js scene graph.\n *\n * @param world - The world the entity belongs to.\n * @param entityId - The entity to remove.\n * @param dispose - When `true`, traverses the entity's `Object3D` subtree and\n * calls `.dispose()` on every `BufferGeometry` and `Material` found. Pass\n * `true` when the entity will not be reused and you want to free GPU memory\n * immediately (e.g. dynamically spawned objects). Defaults to `false`.\n * @returns `true` if the entity existed and was removed; `false` if the entity\n * was not found.\n *\n * @example\n * ```ts\n * // Remove from scene, keep GPU resources (safe if geometry is shared)\n * objects.deleteEntity(world, entityId);\n *\n * // Remove from scene and free GPU memory (use for one-off spawned objects)\n * objects.deleteEntity(world, entityId, true);\n * ```\n */\n deleteEntity(world: World, entityId: EntityId, dispose = false): boolean {\n if (!world.hasEntity(entityId)) {\n return false;\n }\n\n const object3d = world.getComponent(entityId, Object3DRef)?.object;\n if (object3d?.parent) {\n object3d.parent.remove(object3d);\n }\n\n if (dispose && object3d) {\n object3d.traverse((child) => {\n if (child instanceof THREE.Mesh) {\n // Resources backing shared (cached) model scenes are skipped —\n // other live clones and future spawns reference the same objects.\n if (!child.geometry?.userData?.[SHARED_MODEL_RESOURCE_FLAG]) {\n child.geometry?.dispose();\n }\n const materials = Array.isArray(child.material)\n ? child.material\n : [child.material];\n for (const mat of materials) {\n if (mat && !mat.userData?.[SHARED_MODEL_RESOURCE_FLAG]) {\n mat.dispose();\n }\n }\n }\n });\n }\n\n world.destroyEntity(entityId);\n return true;\n }\n\n setParent(\n world: World,\n entityId: EntityId,\n parentId: EntityId | null,\n options?: {\n preserveWorldTransform?: boolean;\n },\n ): boolean {\n if (!world.hasEntity(entityId)) {\n return false;\n }\n\n if (parentId !== null && !world.hasEntity(parentId)) {\n return false;\n }\n\n if (parentId === entityId) {\n return false;\n }\n\n let ancestor = parentId;\n while (ancestor !== null) {\n if (ancestor === entityId) {\n return false;\n }\n\n ancestor = world.getComponent(ancestor, ParentId)?.value ?? null;\n }\n\n const parentComponent = world.getComponent(entityId, ParentId);\n if (parentComponent) {\n if (parentComponent.value === parentId) {\n return false;\n }\n\n parentComponent.value = parentId;\n } else {\n world.addComponent(entityId, new ParentId(parentId));\n }\n\n const preserveWorldTransform = options?.preserveWorldTransform ?? true;\n if (preserveWorldTransform) {\n const object = world.getComponent(entityId, Object3DRef)?.object;\n const parentObject =\n parentId !== null\n ? world.getComponent(parentId, Object3DRef)?.object ?? null\n : null;\n\n if (object) {\n // Refresh matrixWorld before attach so world-space preservation is accurate.\n this.scene.updateMatrixWorld(true);\n\n if (parentObject && parentObject !== object) {\n parentObject.attach(object);\n } else {\n this.scene.attach(object);\n }\n\n object.updateMatrixWorld(true);\n this.syncTransformComponentFromObject(world, entityId, object);\n }\n }\n\n this.reconcileSceneFromWorld(world);\n return true;\n }\n\n private syncTransformComponentFromObject(\n world: World,\n entityId: EntityId,\n object: THREE.Object3D,\n ): void {\n const transform = world.getComponent(entityId, TransformComponent);\n if (!transform) {\n return;\n }\n\n transform.position.x = object.position.x;\n transform.position.y = object.position.y;\n transform.position.z = object.position.z;\n\n transform.rotation.x = object.rotation.x;\n transform.rotation.y = object.rotation.y;\n transform.rotation.z = object.rotation.z;\n\n transform.scale.x = object.scale.x;\n transform.scale.y = object.scale.y;\n transform.scale.z = object.scale.z;\n }\n\n reconcileSceneFromWorld(world: World): void {\n const worldObjects = new Map<EntityId, THREE.Object3D>();\n const entityIds = world.query(Object3DRef);\n\n for (const entityId of entityIds) {\n const object = world.getComponent(entityId, Object3DRef)?.object;\n if (!object) {\n continue;\n }\n\n worldObjects.set(entityId, object);\n }\n\n for (const child of [...this.scene.children]) {\n const entityId = child.userData?.entityId;\n if (typeof entityId === \"number\" && !world.hasEntity(entityId)) {\n this.scene.remove(child);\n }\n }\n\n for (const [entityId, object] of worldObjects.entries()) {\n const parentEntityId = world.getComponent(entityId, ParentId)?.value;\n const parentObject =\n typeof parentEntityId === \"number\"\n ? worldObjects.get(parentEntityId)\n : undefined;\n\n if (parentObject && parentObject !== object) {\n if (object.parent !== parentObject) {\n // Reconcile hierarchy from ParentId while keeping Transform as local source of truth.\n parentObject.add(object);\n object.updateMatrixWorld(true);\n }\n continue;\n }\n\n if (object.parent !== this.scene) {\n // Reconcile hierarchy from ParentId while keeping Transform as local source of truth.\n this.scene.add(object);\n object.updateMatrixWorld(true);\n }\n }\n }\n\n update(world: World): void {\n for (const request of this.createQueue.splice(0)) {\n const entityId = this.createNow(request.kind, world, request.payload);\n request.onCreated?.(entityId);\n }\n\n this.reconcileSceneFromWorld(world);\n }\n}\n","const LOCAL_DRACO_DECODER_RELATIVE_PATH = \"./assets/draco/\";\nexport const DRACO_DECODER_CDN_PATH =\n \"https://www.gstatic.com/draco/versioned/decoders/1.5.7/\";\n\nlet dracoDecoderPathOverride: string | null = null;\n\n/**\n * Override where the DRACO decoder files (draco_wasm_wrapper.js,\n * draco_decoder.wasm, draco_decoder.js) are fetched from. Embedding apps\n * whose bundlers relocate this package's chunks — making the default\n * import.meta.url resolution point at a location that is never populated —\n * should call this before any model loads. The path must end with \"/\".\n * Pass null to restore the default resolution.\n */\nexport function setDracoDecoderPath(path: string | null): void {\n dracoDecoderPathOverride = path;\n}\n\nfunction isBlockedBrowserFileUrl(url: string): boolean {\n return url.startsWith(\"file://\");\n}\n\nexport function resolveDracoDecoderPath(): string {\n if (dracoDecoderPathOverride) {\n return dracoDecoderPathOverride;\n }\n\n try {\n // Prefer vendored decoder assets shipped with this package.\n const resolvedPath = new URL(\n LOCAL_DRACO_DECODER_RELATIVE_PATH,\n import.meta.url,\n ).toString();\n\n // Browser loaders cannot fetch file:// resources from package install paths.\n // Fall back to CDN decoders when bundlers emit file URLs for node_modules assets.\n if (isBlockedBrowserFileUrl(resolvedPath)) {\n return DRACO_DECODER_CDN_PATH;\n }\n\n return resolvedPath;\n } catch {\n // Fallback keeps compatibility in runtimes that cannot resolve package-relative URLs.\n return DRACO_DECODER_CDN_PATH;\n }\n}\n"]}