@relu-interactives/spatial-ecs 0.3.21 → 0.4.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 (46) hide show
  1. package/dist/{System-BhnLw0fZ.d.cts → System-ln4Q7Eot.d.cts} +15 -1
  2. package/dist/{System-BhnLw0fZ.d.ts → System-ln4Q7Eot.d.ts} +15 -1
  3. package/dist/{XRHandPose-CrzI57JA.d.ts → XRHandPose-BImIa4ZS.d.ts} +82 -2
  4. package/dist/{XRHandPose-CLl4MiHx.d.cts → XRHandPose-CxPv-LBo.d.cts} +82 -2
  5. package/dist/{chunk-H6DQ7JRE.js → chunk-4AK4I3QF.js} +33 -3
  6. package/dist/chunk-4AK4I3QF.js.map +1 -0
  7. package/dist/{chunk-D6KXWNYT.js → chunk-4DWZK4X4.js} +3 -3
  8. package/dist/{chunk-D6KXWNYT.js.map → chunk-4DWZK4X4.js.map} +1 -1
  9. package/dist/{chunk-CDSE7476.js → chunk-LAOFCFEI.js} +554 -5
  10. package/dist/chunk-LAOFCFEI.js.map +1 -0
  11. package/dist/{chunk-P42OE3RU.js → chunk-SGADE55G.js} +14 -5
  12. package/dist/chunk-SGADE55G.js.map +1 -0
  13. package/dist/components/index.cjs +30 -0
  14. package/dist/components/index.cjs.map +1 -1
  15. package/dist/components/index.d.cts +3 -3
  16. package/dist/components/index.d.ts +3 -3
  17. package/dist/components/index.js +1 -1
  18. package/dist/docs/guide/mixed-reality.md +120 -0
  19. package/dist/factories/index.cjs +26 -0
  20. package/dist/factories/index.cjs.map +1 -1
  21. package/dist/factories/index.d.cts +5 -3
  22. package/dist/factories/index.d.ts +5 -3
  23. package/dist/factories/index.js +3 -3
  24. package/dist/{index-C2I5PxCI.d.cts → index-CBdnIyI8.d.cts} +94 -2
  25. package/dist/{index-g777AmFv.d.cts → index-CQsHUez3.d.cts} +42 -4
  26. package/dist/{index-JRcoel9F.d.ts → index-CuGqxuk-.d.ts} +42 -4
  27. package/dist/{index-6l4hn2Sh.d.ts → index-n7SeH119.d.ts} +94 -2
  28. package/dist/index.cjs +610 -0
  29. package/dist/index.cjs.map +1 -1
  30. package/dist/index.d.cts +9 -8
  31. package/dist/index.d.ts +9 -8
  32. package/dist/index.js +26 -8
  33. package/dist/index.js.map +1 -1
  34. package/dist/systems/index.cjs +580 -0
  35. package/dist/systems/index.cjs.map +1 -1
  36. package/dist/systems/index.d.cts +2 -2
  37. package/dist/systems/index.d.ts +2 -2
  38. package/dist/systems/index.js +3 -3
  39. package/dist/types.d.cts +1 -1
  40. package/dist/types.d.ts +1 -1
  41. package/dist/worldSnapshotUtils.d.cts +1 -1
  42. package/dist/worldSnapshotUtils.d.ts +1 -1
  43. package/package.json +1 -1
  44. package/dist/chunk-CDSE7476.js.map +0 -1
  45. package/dist/chunk-H6DQ7JRE.js.map +0 -1
  46. package/dist/chunk-P42OE3RU.js.map +0 -1
@@ -1,6 +1,6 @@
1
- export { A as AnimationComponent, a as AnimationComponentOptions, b as AudioComponent, C as CameraComponent, c as CameraComponentOptions, d as CameraProjection, e as CameraRuntimeType, f as ColliderShape, g as ColliderState, h as CubeMeshParameters, D as DEFAULT_COLLIDER_STATE, i as DEFAULT_INSTANCED_MESH_PARAMETERS, j as DEFAULT_INSTANCE_TRANSFORM, k as DEFAULT_MESH_GEOMETRY_PARAMETERS, l as DEFAULT_PHYSICS_STATE, m as DEFAULT_POSE_CURLS, n as DEFAULT_POSE_DIRECTIONS, o as DEFAULT_RIGIDBODY_STATE, E as EditableMeshObjectKind, p as EntityType, I as ImageComponent, q as ImageTarget, r as ImageTargetAnchor, s as ImageTargetAnchorOptions, t as ImageTargetReference, u as InstanceSlotComponent, v as InstanceTransform, w as InstancedMeshComponent, x as InstancedMeshKind, L as LightComponent, y as LightValueState, M as MaterialComponent, z as MaterialTypeValue, B as MaterialValueState, F as MeshComponent, G as MeshGeometryComponent, H as MeshGeometryParameters, J as MeshGeometryParametersByKind, K as ModelComponent, N as Name, O as Object3DRef, P as PhysicsComponent, Q as PhysicsState, R as PlaneMeshParameters, S as RadiusHeightMeshParameters, T as RadiusMeshParameters, U as RigidbodyState, V as RigidbodyType, W as ScriptComponent, X as ScriptEntry, Y as ScriptObjectComponent, Z as ScriptObjectComponentInput, _ as ScriptObjectRuntimeState, $ as Selectable, a0 as SelectionTransformState, a1 as SpriteComponent, a2 as TextureFilteringValue, a3 as TransformModeValue, a4 as TransformSpaceValue, a5 as VRTeleportAreaComponent, a6 as VRTeleportAreaOptions, a7 as VideoComponent, a8 as VrTeleportShape, a9 as XRHandPoseComponent, aa as XRHandPoseOptions, ab as XRInteractableComponent, ac as XRInteractableOptions, ad as XRInteractorComponent, ae as XRInteractorOptions, af as XRInteractorSideComponent, ag as XRRigComponent, ah as XRRigOptions, ai as XrAttachPoint, aj as XrDistanceGrabBehavior, ak as XrGrabGesture, al as XrGrabHands, am as XrGrabReach, an as XrHandPoseEntry, ao as XrHandPreset, ap as XrInteractorSide, aq as XrInteractorType, ar as XrLocomotionMode, as as XrTrackingOrigin, at as XrTwoHandRotation, au as createAttachPoint, av as createHandPoseEntry, aw as defaultMaterialValue, ax as handPoseDefinitionFor, ay as normalizePhysicsState, az as setPhysicsLiveRef } from '../XRHandPose-CLl4MiHx.cjs';
2
- export { D as DEFAULT_ENVIRONMENT_STATE, a as DEFAULT_POSTPROCESSING_STATE, E as Environment, b as EnvironmentFogState, c as EnvironmentFogType, d as EnvironmentGradientEffect, e as EnvironmentSkyboxState, f as EnvironmentSkyboxType, g as EnvironmentState, P as ParentId, h as Postprocessing, i as PostprocessingState, T as TransformComponent, j as TransformData, V as Vec3 } from '../System-BhnLw0fZ.cjs';
3
- export { P as PrefabInstance, a as PrefabNode } from '../index-g777AmFv.cjs';
1
+ export { A as AnimationComponent, a as AnimationComponentOptions, b as AudioComponent, C as CameraComponent, c as CameraComponentOptions, d as CameraProjection, e as CameraRuntimeType, f as ColliderShape, g as ColliderState, h as CubeMeshParameters, D as DEFAULT_COLLIDER_STATE, i as DEFAULT_INSTANCED_MESH_PARAMETERS, j as DEFAULT_INSTANCE_TRANSFORM, k as DEFAULT_MESH_GEOMETRY_PARAMETERS, l as DEFAULT_PHYSICS_STATE, m as DEFAULT_POSE_CURLS, n as DEFAULT_POSE_DIRECTIONS, o as DEFAULT_RIGIDBODY_STATE, E as EditableMeshObjectKind, p as EntityType, I as ImageComponent, q as ImageTarget, r as ImageTargetAnchor, s as ImageTargetAnchorOptions, t as ImageTargetReference, u as InstanceSlotComponent, v as InstanceTransform, w as InstancedMeshComponent, x as InstancedMeshKind, L as LightComponent, y as LightValueState, M as MaterialComponent, z as MaterialTypeValue, B as MaterialValueState, F as MeshComponent, G as MeshGeometryComponent, H as MeshGeometryParameters, J as MeshGeometryParametersByKind, K as ModelComponent, N as Name, O as Object3DRef, P as PhysicsComponent, Q as PhysicsState, R as PlaneMeshParameters, S as RadiusHeightMeshParameters, T as RadiusMeshParameters, U as RigidbodyState, V as RigidbodyType, W as ScriptComponent, X as ScriptEntry, Y as ScriptObjectComponent, Z as ScriptObjectComponentInput, _ as ScriptObjectRuntimeState, $ as Selectable, a0 as SelectionTransformState, a1 as SpriteComponent, a2 as TextureFilteringValue, a3 as TransformModeValue, a4 as TransformSpaceValue, a5 as VRTeleportAreaComponent, a6 as VRTeleportAreaOptions, a7 as VideoComponent, a8 as VrTeleportShape, a9 as XRAnchorComponent, aa as XRAnchorOptions, ab as XRHandPoseComponent, ac as XRHandPoseOptions, ad as XRInteractableComponent, ae as XRInteractableOptions, af as XRInteractorComponent, ag as XRInteractorOptions, ah as XRInteractorSideComponent, ai as XRRigComponent, aj as XRRigOptions, ak as XrAttachPoint, al as XrDistanceGrabBehavior, am as XrEnvironmentPhysics, an as XrGrabGesture, ao as XrGrabHands, ap as XrGrabReach, aq as XrHandPoseEntry, ar as XrHandPreset, as as XrInteractorSide, at as XrInteractorType, au as XrLocomotionMode, av as XrTrackingOrigin, aw as XrTwoHandRotation, ax as createAttachPoint, ay as createHandPoseEntry, az as defaultMaterialValue, aA as handPoseDefinitionFor, aB as normalizePhysicsState, aC as setPhysicsLiveRef } from '../XRHandPose-CxPv-LBo.cjs';
2
+ export { D as DEFAULT_ENVIRONMENT_STATE, a as DEFAULT_POSTPROCESSING_STATE, E as Environment, b as EnvironmentFogState, c as EnvironmentFogType, d as EnvironmentGradientEffect, e as EnvironmentSkyboxState, f as EnvironmentSkyboxType, g as EnvironmentState, P as ParentId, h as Postprocessing, i as PostprocessingState, T as TransformComponent, j as TransformData, V as Vec3 } from '../System-ln4Q7Eot.cjs';
3
+ export { P as PrefabInstance, a as PrefabNode, X as XREnvironmentComponent, b as XrEnvironmentKind, c as XrEnvironmentOrientation } from '../index-CQsHUez3.cjs';
4
4
  import 'three';
5
5
  import '@dimforge/rapier3d-compat';
6
6
  import '../handPose-DlcTtqgx.cjs';
@@ -1,6 +1,6 @@
1
- export { A as AnimationComponent, a as AnimationComponentOptions, b as AudioComponent, C as CameraComponent, c as CameraComponentOptions, d as CameraProjection, e as CameraRuntimeType, f as ColliderShape, g as ColliderState, h as CubeMeshParameters, D as DEFAULT_COLLIDER_STATE, i as DEFAULT_INSTANCED_MESH_PARAMETERS, j as DEFAULT_INSTANCE_TRANSFORM, k as DEFAULT_MESH_GEOMETRY_PARAMETERS, l as DEFAULT_PHYSICS_STATE, m as DEFAULT_POSE_CURLS, n as DEFAULT_POSE_DIRECTIONS, o as DEFAULT_RIGIDBODY_STATE, E as EditableMeshObjectKind, p as EntityType, I as ImageComponent, q as ImageTarget, r as ImageTargetAnchor, s as ImageTargetAnchorOptions, t as ImageTargetReference, u as InstanceSlotComponent, v as InstanceTransform, w as InstancedMeshComponent, x as InstancedMeshKind, L as LightComponent, y as LightValueState, M as MaterialComponent, z as MaterialTypeValue, B as MaterialValueState, F as MeshComponent, G as MeshGeometryComponent, H as MeshGeometryParameters, J as MeshGeometryParametersByKind, K as ModelComponent, N as Name, O as Object3DRef, P as PhysicsComponent, Q as PhysicsState, R as PlaneMeshParameters, S as RadiusHeightMeshParameters, T as RadiusMeshParameters, U as RigidbodyState, V as RigidbodyType, W as ScriptComponent, X as ScriptEntry, Y as ScriptObjectComponent, Z as ScriptObjectComponentInput, _ as ScriptObjectRuntimeState, $ as Selectable, a0 as SelectionTransformState, a1 as SpriteComponent, a2 as TextureFilteringValue, a3 as TransformModeValue, a4 as TransformSpaceValue, a5 as VRTeleportAreaComponent, a6 as VRTeleportAreaOptions, a7 as VideoComponent, a8 as VrTeleportShape, a9 as XRHandPoseComponent, aa as XRHandPoseOptions, ab as XRInteractableComponent, ac as XRInteractableOptions, ad as XRInteractorComponent, ae as XRInteractorOptions, af as XRInteractorSideComponent, ag as XRRigComponent, ah as XRRigOptions, ai as XrAttachPoint, aj as XrDistanceGrabBehavior, ak as XrGrabGesture, al as XrGrabHands, am as XrGrabReach, an as XrHandPoseEntry, ao as XrHandPreset, ap as XrInteractorSide, aq as XrInteractorType, ar as XrLocomotionMode, as as XrTrackingOrigin, at as XrTwoHandRotation, au as createAttachPoint, av as createHandPoseEntry, aw as defaultMaterialValue, ax as handPoseDefinitionFor, ay as normalizePhysicsState, az as setPhysicsLiveRef } from '../XRHandPose-CrzI57JA.js';
2
- export { D as DEFAULT_ENVIRONMENT_STATE, a as DEFAULT_POSTPROCESSING_STATE, E as Environment, b as EnvironmentFogState, c as EnvironmentFogType, d as EnvironmentGradientEffect, e as EnvironmentSkyboxState, f as EnvironmentSkyboxType, g as EnvironmentState, P as ParentId, h as Postprocessing, i as PostprocessingState, T as TransformComponent, j as TransformData, V as Vec3 } from '../System-BhnLw0fZ.js';
3
- export { P as PrefabInstance, a as PrefabNode } from '../index-JRcoel9F.js';
1
+ export { A as AnimationComponent, a as AnimationComponentOptions, b as AudioComponent, C as CameraComponent, c as CameraComponentOptions, d as CameraProjection, e as CameraRuntimeType, f as ColliderShape, g as ColliderState, h as CubeMeshParameters, D as DEFAULT_COLLIDER_STATE, i as DEFAULT_INSTANCED_MESH_PARAMETERS, j as DEFAULT_INSTANCE_TRANSFORM, k as DEFAULT_MESH_GEOMETRY_PARAMETERS, l as DEFAULT_PHYSICS_STATE, m as DEFAULT_POSE_CURLS, n as DEFAULT_POSE_DIRECTIONS, o as DEFAULT_RIGIDBODY_STATE, E as EditableMeshObjectKind, p as EntityType, I as ImageComponent, q as ImageTarget, r as ImageTargetAnchor, s as ImageTargetAnchorOptions, t as ImageTargetReference, u as InstanceSlotComponent, v as InstanceTransform, w as InstancedMeshComponent, x as InstancedMeshKind, L as LightComponent, y as LightValueState, M as MaterialComponent, z as MaterialTypeValue, B as MaterialValueState, F as MeshComponent, G as MeshGeometryComponent, H as MeshGeometryParameters, J as MeshGeometryParametersByKind, K as ModelComponent, N as Name, O as Object3DRef, P as PhysicsComponent, Q as PhysicsState, R as PlaneMeshParameters, S as RadiusHeightMeshParameters, T as RadiusMeshParameters, U as RigidbodyState, V as RigidbodyType, W as ScriptComponent, X as ScriptEntry, Y as ScriptObjectComponent, Z as ScriptObjectComponentInput, _ as ScriptObjectRuntimeState, $ as Selectable, a0 as SelectionTransformState, a1 as SpriteComponent, a2 as TextureFilteringValue, a3 as TransformModeValue, a4 as TransformSpaceValue, a5 as VRTeleportAreaComponent, a6 as VRTeleportAreaOptions, a7 as VideoComponent, a8 as VrTeleportShape, a9 as XRAnchorComponent, aa as XRAnchorOptions, ab as XRHandPoseComponent, ac as XRHandPoseOptions, ad as XRInteractableComponent, ae as XRInteractableOptions, af as XRInteractorComponent, ag as XRInteractorOptions, ah as XRInteractorSideComponent, ai as XRRigComponent, aj as XRRigOptions, ak as XrAttachPoint, al as XrDistanceGrabBehavior, am as XrEnvironmentPhysics, an as XrGrabGesture, ao as XrGrabHands, ap as XrGrabReach, aq as XrHandPoseEntry, ar as XrHandPreset, as as XrInteractorSide, at as XrInteractorType, au as XrLocomotionMode, av as XrTrackingOrigin, aw as XrTwoHandRotation, ax as createAttachPoint, ay as createHandPoseEntry, az as defaultMaterialValue, aA as handPoseDefinitionFor, aB as normalizePhysicsState, aC as setPhysicsLiveRef } from '../XRHandPose-BImIa4ZS.js';
2
+ export { D as DEFAULT_ENVIRONMENT_STATE, a as DEFAULT_POSTPROCESSING_STATE, E as Environment, b as EnvironmentFogState, c as EnvironmentFogType, d as EnvironmentGradientEffect, e as EnvironmentSkyboxState, f as EnvironmentSkyboxType, g as EnvironmentState, P as ParentId, h as Postprocessing, i as PostprocessingState, T as TransformComponent, j as TransformData, V as Vec3 } from '../System-ln4Q7Eot.js';
3
+ export { P as PrefabInstance, a as PrefabNode, X as XREnvironmentComponent, b as XrEnvironmentKind, c as XrEnvironmentOrientation } from '../index-CuGqxuk-.js';
4
4
  import 'three';
5
5
  import '@dimforge/rapier3d-compat';
6
6
  import '../handPose-DlcTtqgx.js';
@@ -1,4 +1,4 @@
1
- export { AnimationComponent, AudioComponent, CameraComponent, DEFAULT_COLLIDER_STATE, DEFAULT_ENVIRONMENT_STATE, DEFAULT_INSTANCED_MESH_PARAMETERS, DEFAULT_INSTANCE_TRANSFORM, DEFAULT_MESH_GEOMETRY_PARAMETERS, DEFAULT_PHYSICS_STATE, DEFAULT_POSE_CURLS, DEFAULT_POSE_DIRECTIONS, DEFAULT_POSTPROCESSING_STATE, DEFAULT_RIGIDBODY_STATE, EntityType, Environment, ImageComponent, ImageTarget, ImageTargetAnchor, InstanceSlotComponent, InstancedMeshComponent, LightComponent, MaterialComponent, MeshComponent, MeshGeometryComponent, ModelComponent, Name, Object3DRef, ParentId, PhysicsComponent, Postprocessing, PrefabInstance, PrefabNode, ScriptComponent, ScriptObjectComponent, Selectable, SelectionTransformState, SpriteComponent, TransformComponent, VRTeleportAreaComponent, VideoComponent, XRHandPoseComponent, XRInteractableComponent, XRInteractorComponent, XRInteractorSideComponent, XRRigComponent, createAttachPoint, createHandPoseEntry, defaultMaterialValue, handPoseDefinitionFor, normalizePhysicsState, setPhysicsLiveRef } from '../chunk-H6DQ7JRE.js';
1
+ export { AnimationComponent, AudioComponent, CameraComponent, DEFAULT_COLLIDER_STATE, DEFAULT_ENVIRONMENT_STATE, DEFAULT_INSTANCED_MESH_PARAMETERS, DEFAULT_INSTANCE_TRANSFORM, DEFAULT_MESH_GEOMETRY_PARAMETERS, DEFAULT_PHYSICS_STATE, DEFAULT_POSE_CURLS, DEFAULT_POSE_DIRECTIONS, DEFAULT_POSTPROCESSING_STATE, DEFAULT_RIGIDBODY_STATE, EntityType, Environment, ImageComponent, ImageTarget, ImageTargetAnchor, InstanceSlotComponent, InstancedMeshComponent, LightComponent, MaterialComponent, MeshComponent, MeshGeometryComponent, ModelComponent, Name, Object3DRef, ParentId, PhysicsComponent, Postprocessing, PrefabInstance, PrefabNode, ScriptComponent, ScriptObjectComponent, Selectable, SelectionTransformState, SpriteComponent, TransformComponent, VRTeleportAreaComponent, VideoComponent, XRAnchorComponent, XREnvironmentComponent, XRHandPoseComponent, XRInteractableComponent, XRInteractorComponent, XRInteractorSideComponent, XRRigComponent, createAttachPoint, createHandPoseEntry, defaultMaterialValue, handPoseDefinitionFor, normalizePhysicsState, setPhysicsLiveRef } from '../chunk-4AK4I3QF.js';
2
2
  import '../chunk-OY7ZODZP.js';
3
3
  //# sourceMappingURL=index.js.map
4
4
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,120 @@
1
+ # Mixed Reality
2
+
3
+ An XR project runs as **virtual** reality or **mixed** reality. The difference is
4
+ one field on the XR rig — `passthrough` — and everything else follows from it.
5
+
6
+ With passthrough on, the experience composites over the user's real room instead
7
+ of a virtual background. Turn it on in the inspector (XR Rig → Mixed Reality), or
8
+ from a script by authoring the rig.
9
+
10
+ Mixed reality is a **Quest and Android XR** capability. Safari on visionOS grants
11
+ `immersive-ar` to no web page at all, so a passthrough project falls back to an
12
+ ordinary VR session there rather than failing to start.
13
+
14
+ ## What the rig controls
15
+
16
+ | Field | What it does |
17
+ | --- | --- |
18
+ | `passthrough` | Show the real room. The VR/MR switch. |
19
+ | `depthOcclusion` | Real objects hide virtual ones. |
20
+ | `environmentPhysics` | Give the real room physics colliders. |
21
+ | `environmentDebug` | Draw the detected room as a wireframe, on-device. |
22
+ | `hitTest` | Let scripts raycast against the real room. |
23
+ | `anchors` | Pin content to a real-world spot. |
24
+
25
+ Everything except `passthrough` is off by default, and that is deliberate: plane
26
+ detection, mesh detection and depth sensing each make the headset ask the user
27
+ for permission to share a scan of their room. Turn on only what you use.
28
+
29
+ ## Physics against the real room
30
+
31
+ Set `environmentPhysics` and the room becomes solid:
32
+
33
+ - `"planes"` — the flat surfaces the headset detects (floor, walls, desks).
34
+ Cheaper, and available on more devices.
35
+ - `"mesh"` — the full room scan, including furniture. Far more faithful, but
36
+ only where the runtime provides one.
37
+ - `"auto"` — the mesh where the device has one, falling back to planes.
38
+ - `"none"` (default) — objects pass straight through the room.
39
+
40
+ Each detected surface becomes an ordinary entity, so it goes through the same
41
+ physics as everything else: a dynamic rigidbody dropped in a mixed-reality scene
42
+ lands on the real floor with no extra code.
43
+
44
+ ## Finding the real room from a script
45
+
46
+ Detected surfaces carry `XREnvironmentComponent`, so they are queryable like any
47
+ other entity. `semanticLabel` is what the runtime called the surface — commonly
48
+ `floor`, `wall`, `ceiling`, `table`, `desk` — and is `null` on runtimes that
49
+ classify nothing, so always handle that case.
50
+
51
+ ```ts
52
+ import { Behaviour } from "@relu-interactives/spatial-ecs";
53
+ import {
54
+ TransformComponent,
55
+ XREnvironmentComponent,
56
+ } from "@relu-interactives/spatial-ecs/components";
57
+
58
+ export default class FloorReporter extends Behaviour {
59
+ onUpdate() {
60
+ for (const entityId of this.world.query(XREnvironmentComponent)) {
61
+ const surface = this.world.getComponent(entityId, XREnvironmentComponent);
62
+ if (surface?.semanticLabel !== "floor") continue;
63
+
64
+ const transform = this.world.getComponent(entityId, TransformComponent);
65
+ if (transform) console.log("real floor at y =", transform.position.y);
66
+ }
67
+ }
68
+ }
69
+ ```
70
+
71
+ Surfaces appear over the first few seconds of a session and are revised as the
72
+ headset re-scans, so query them each frame rather than caching a list at start-up.
73
+
74
+ ## Reacting to what the device granted
75
+
76
+ Every mixed-reality feature is requested OPTIONALLY — requiring one would make
77
+ `requestSession` reject outright on any headset that lacks it, which would mean
78
+ shipping a build that refuses to start. So check what you actually got:
79
+
80
+ ```ts
81
+ import { Behaviour, type XrCapabilities } from "@relu-interactives/spatial-ecs";
82
+
83
+ export default class RoomAware extends Behaviour {
84
+ onXRSessionStart(capabilities: XrCapabilities) {
85
+ if (capabilities.mode !== "immersive-ar") {
86
+ // Fell back to VR — draw the virtual environment instead.
87
+ return;
88
+ }
89
+ if (!capabilities.planeDetection && !capabilities.meshDetection) {
90
+ // Passthrough, but no room geometry: keep content within arm's reach.
91
+ }
92
+ }
93
+ }
94
+ ```
95
+
96
+ ## Anchors
97
+
98
+ A headset keeps revising where it thinks the room is. Content at fixed scene
99
+ coordinates does not move with those corrections, so a vase carefully placed on a
100
+ real table slowly slides off it.
101
+
102
+ Add `XRAnchorComponent` (inspector: Add Component → XR → World Anchor) and the
103
+ entity is pinned to the real world instead: the runtime owns its pose from then
104
+ on, and it stays put relative to the room.
105
+
106
+ Because the anchor owns the transform, moving the entity by script or physics has
107
+ no lasting effect — disable the component first, move it, then re-enable.
108
+
109
+ Anchors last for the session only. Persisting one across launches needs
110
+ `requestPersistentHandle`, which is a draft extension and not supported here.
111
+
112
+ ## Notes
113
+
114
+ - **Never paint an opaque background.** A skybox covers the whole framebuffer, so
115
+ it hides the room completely and looks exactly like passthrough having failed.
116
+ The engine withholds the skybox automatically while a passthrough session runs.
117
+ - **Blend mode is fixed for a session.** `passthrough` is read when the session
118
+ starts; it cannot be toggled mid-session. Ending and re-entering is the only way.
119
+ - **Room geometry arrives late.** Nothing is detected on the first frame. Write
120
+ logic that copes with an empty room and fills in over a few seconds.
@@ -2254,6 +2254,12 @@ var _XRRigComponent = class _XRRigComponent extends Component {
2254
2254
  this.teleportArcColor = options?.teleportArcColor ?? "#4da3ff";
2255
2255
  this.teleportArcInvalidColor = options?.teleportArcInvalidColor ?? "#ff5a5a";
2256
2256
  this.teleportArcThickness = options?.teleportArcThickness ?? 0.012;
2257
+ this.passthrough = options?.passthrough ?? false;
2258
+ this.depthOcclusion = options?.depthOcclusion ?? false;
2259
+ this.environmentPhysics = options?.environmentPhysics ?? "none";
2260
+ this.environmentDebug = options?.environmentDebug ?? false;
2261
+ this.hitTest = options?.hitTest ?? false;
2262
+ this.anchors = options?.anchors ?? false;
2257
2263
  }
2258
2264
  };
2259
2265
  __name(_XRRigComponent, "XRRigComponent");
@@ -2337,6 +2343,24 @@ function createXRHandPoseComponent(world, entityId, ...args) {
2337
2343
  }
2338
2344
  __name(createXRHandPoseComponent, "createXRHandPoseComponent");
2339
2345
 
2346
+ // core/components/XRAnchor.ts
2347
+ var _XRAnchorComponent = class _XRAnchorComponent extends Component {
2348
+ constructor(options) {
2349
+ super();
2350
+ this.enabled = options?.enabled ?? true;
2351
+ }
2352
+ };
2353
+ __name(_XRAnchorComponent, "XRAnchorComponent");
2354
+ var XRAnchorComponent = _XRAnchorComponent;
2355
+
2356
+ // core/factories/components/XRAnchorFactory.ts
2357
+ function createXRAnchorComponent(world, entityId, ...args) {
2358
+ const component = new XRAnchorComponent(...args);
2359
+ world.addComponent(entityId, component);
2360
+ return component;
2361
+ }
2362
+ __name(createXRAnchorComponent, "createXRAnchorComponent");
2363
+
2340
2364
  // core/components/XRInteractable.ts
2341
2365
  var _XRInteractableComponent = class _XRInteractableComponent extends Component {
2342
2366
  constructor(options) {
@@ -2448,6 +2472,7 @@ function registerDefaultComponentFactories(objectManagementSystem) {
2448
2472
  objectManagementSystem.registerComponentFactory("xrRig", createXRRigComponent);
2449
2473
  objectManagementSystem.registerComponentFactory("vrTeleportArea", createVRTeleportAreaComponent);
2450
2474
  objectManagementSystem.registerComponentFactory("xrHandPose", createXRHandPoseComponent);
2475
+ objectManagementSystem.registerComponentFactory("xrAnchor", createXRAnchorComponent);
2451
2476
  objectManagementSystem.registerComponentFactory("xrInteractable", createXRInteractableComponent);
2452
2477
  objectManagementSystem.registerComponentFactory("xrInteractor", createXRInteractorComponent);
2453
2478
  objectManagementSystem.registerComponentFactory("xrInteractorSide", createXRInteractorSideComponent);
@@ -3776,6 +3801,7 @@ exports.createSpriteComponent = createSpriteComponent;
3776
3801
  exports.createTransformComponent = createTransformComponent;
3777
3802
  exports.createVRTeleportAreaComponent = createVRTeleportAreaComponent;
3778
3803
  exports.createVideoComponent = createVideoComponent;
3804
+ exports.createXRAnchorComponent = createXRAnchorComponent;
3779
3805
  exports.createXRHandPoseComponent = createXRHandPoseComponent;
3780
3806
  exports.createXRInteractableComponent = createXRInteractableComponent;
3781
3807
  exports.createXRInteractorComponent = createXRInteractorComponent;