@relu-interactives/spatial-ecs 0.3.11 → 0.3.13

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 (38) hide show
  1. package/dist/{XRHandPose-C-KJeYcJ.d.cts → XRHandPose-9mVZVU3K.d.cts} +32 -8
  2. package/dist/{XRHandPose-B6I4y1lj.d.ts → XRHandPose-To0260Lc.d.ts} +32 -8
  3. package/dist/{chunk-TXEGYR76.js → chunk-3LDQ4GVZ.js} +7 -5
  4. package/dist/chunk-3LDQ4GVZ.js.map +1 -0
  5. package/dist/{chunk-Y3AC3VZ2.js → chunk-CHZQ4NXP.js} +3 -3
  6. package/dist/{chunk-Y3AC3VZ2.js.map → chunk-CHZQ4NXP.js.map} +1 -1
  7. package/dist/{chunk-FSHRPY65.js → chunk-JHFBEMXM.js} +4 -4
  8. package/dist/{chunk-FSHRPY65.js.map → chunk-JHFBEMXM.js.map} +1 -1
  9. package/dist/{chunk-KLU2M43M.js → chunk-N2634D4W.js} +112 -29
  10. package/dist/chunk-N2634D4W.js.map +1 -0
  11. package/dist/components/index.cjs +5 -3
  12. package/dist/components/index.cjs.map +1 -1
  13. package/dist/components/index.d.cts +2 -2
  14. package/dist/components/index.d.ts +2 -2
  15. package/dist/components/index.js +1 -1
  16. package/dist/docs/guide/vr-and-hand-poses.md +5 -3
  17. package/dist/factories/index.cjs +5 -3
  18. package/dist/factories/index.cjs.map +1 -1
  19. package/dist/factories/index.d.cts +1 -1
  20. package/dist/factories/index.d.ts +1 -1
  21. package/dist/factories/index.js +3 -3
  22. package/dist/{index-DPRnnSI-.d.cts → index-BPKDsVF7.d.cts} +1 -1
  23. package/dist/{index-Bi_wIo1o.d.ts → index-BbXqWyEZ.d.ts} +34 -0
  24. package/dist/{index-CEZp7qLL.d.ts → index-Wzs-8FYa.d.ts} +1 -1
  25. package/dist/{index-jlgDou9W.d.cts → index-lqw8BM6E.d.cts} +34 -0
  26. package/dist/index.cjs +113 -28
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.cts +5 -5
  29. package/dist/index.d.ts +5 -5
  30. package/dist/index.js +8 -8
  31. package/dist/systems/index.cjs +113 -28
  32. package/dist/systems/index.cjs.map +1 -1
  33. package/dist/systems/index.d.cts +1 -1
  34. package/dist/systems/index.d.ts +1 -1
  35. package/dist/systems/index.js +3 -3
  36. package/package.json +1 -1
  37. package/dist/chunk-KLU2M43M.js.map +0 -1
  38. package/dist/chunk-TXEGYR76.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { A as AnimationComponent, b as AudioComponent, c as CameraComponentOptions, C as CameraComponent, T as RigidbodyState, g as ColliderState, P as PhysicsComponent, o as EntityType, I as ImageComponent, q as ImageTargetAnchor, p as ImageTarget, L as LightComponent, M as MaterialComponent, B as MeshComponent, F as MeshGeometryComponent, J as ModelComponent, N as Name, O as Object3DRef, W as ScriptEntry, V as ScriptComponent, Y as ScriptObjectComponentInput, X as ScriptObjectComponent, _ as Selectable, $ as SelectionTransformState, a0 as SpriteComponent, w as InstancedMeshKind, G as MeshGeometryParameters, v as InstancedMeshComponent, t as InstanceSlotComponent, a6 as VideoComponent, af as XRRigComponent, a4 as VRTeleportAreaComponent, a8 as XRHandPoseComponent, aa as XRInteractableComponent, ac as XRInteractorComponent, ae as XRInteractorSideComponent } from '../XRHandPose-C-KJeYcJ.cjs';
1
+ import { A as AnimationComponent, b as AudioComponent, c as CameraComponentOptions, C as CameraComponent, T as RigidbodyState, g as ColliderState, P as PhysicsComponent, o as EntityType, I as ImageComponent, q as ImageTargetAnchor, p as ImageTarget, L as LightComponent, M as MaterialComponent, B as MeshComponent, F as MeshGeometryComponent, J as ModelComponent, N as Name, O as Object3DRef, W as ScriptEntry, V as ScriptComponent, Y as ScriptObjectComponentInput, X as ScriptObjectComponent, _ as Selectable, $ as SelectionTransformState, a0 as SpriteComponent, w as InstancedMeshKind, G as MeshGeometryParameters, v as InstancedMeshComponent, t as InstanceSlotComponent, a6 as VideoComponent, af as XRRigComponent, a4 as VRTeleportAreaComponent, a8 as XRHandPoseComponent, aa as XRInteractableComponent, ac as XRInteractorComponent, ae as XRInteractorSideComponent } from '../XRHandPose-9mVZVU3K.cjs';
2
2
  import { l as World, g as EnvironmentState, E as Environment, P as ParentId, i as PostprocessingState, h as Postprocessing, T as TransformComponent, O as ObjectManagementSystem } from '../System-31wk-A0g.cjs';
3
3
  import * as THREE from 'three';
4
4
  import '@dimforge/rapier3d-compat';
@@ -1,4 +1,4 @@
1
- import { A as AnimationComponent, b as AudioComponent, c as CameraComponentOptions, C as CameraComponent, T as RigidbodyState, g as ColliderState, P as PhysicsComponent, o as EntityType, I as ImageComponent, q as ImageTargetAnchor, p as ImageTarget, L as LightComponent, M as MaterialComponent, B as MeshComponent, F as MeshGeometryComponent, J as ModelComponent, N as Name, O as Object3DRef, W as ScriptEntry, V as ScriptComponent, Y as ScriptObjectComponentInput, X as ScriptObjectComponent, _ as Selectable, $ as SelectionTransformState, a0 as SpriteComponent, w as InstancedMeshKind, G as MeshGeometryParameters, v as InstancedMeshComponent, t as InstanceSlotComponent, a6 as VideoComponent, af as XRRigComponent, a4 as VRTeleportAreaComponent, a8 as XRHandPoseComponent, aa as XRInteractableComponent, ac as XRInteractorComponent, ae as XRInteractorSideComponent } from '../XRHandPose-B6I4y1lj.js';
1
+ import { A as AnimationComponent, b as AudioComponent, c as CameraComponentOptions, C as CameraComponent, T as RigidbodyState, g as ColliderState, P as PhysicsComponent, o as EntityType, I as ImageComponent, q as ImageTargetAnchor, p as ImageTarget, L as LightComponent, M as MaterialComponent, B as MeshComponent, F as MeshGeometryComponent, J as ModelComponent, N as Name, O as Object3DRef, W as ScriptEntry, V as ScriptComponent, Y as ScriptObjectComponentInput, X as ScriptObjectComponent, _ as Selectable, $ as SelectionTransformState, a0 as SpriteComponent, w as InstancedMeshKind, G as MeshGeometryParameters, v as InstancedMeshComponent, t as InstanceSlotComponent, a6 as VideoComponent, af as XRRigComponent, a4 as VRTeleportAreaComponent, a8 as XRHandPoseComponent, aa as XRInteractableComponent, ac as XRInteractorComponent, ae as XRInteractorSideComponent } from '../XRHandPose-To0260Lc.js';
2
2
  import { l as World, g as EnvironmentState, E as Environment, P as ParentId, i as PostprocessingState, h as Postprocessing, T as TransformComponent, O as ObjectManagementSystem } from '../System-31wk-A0g.js';
3
3
  import * as THREE from 'three';
4
4
  import '@dimforge/rapier3d-compat';
@@ -1,6 +1,6 @@
1
- export { createAnimationComponent, createAudioComponent, createCameraComponent, createEntityTypeComponent, createEnvironmentComponent, createImageComponent, createImageTargetAnchorComponent, createImageTargetComponent, createInstanceSlotComponent, createInstancedMeshComponent, createLightComponent, createMaterialComponent, createMeshComponent, createMeshGeometryComponent, createModelComponent, createNameComponent, createObject3DRefComponent, createParentIdComponent, createPhysicsComponent, createPostprocessingComponent, createScriptComponent, createScriptObjectComponent, createSelectableComponent, createSelectionTransformStateComponent, createSpriteComponent, createTransformComponent, createVRTeleportAreaComponent, createVideoComponent, createXRHandPoseComponent, createXRInteractableComponent, createXRInteractorComponent, createXRInteractorSideComponent, createXRRigComponent, registerDefaultComponentFactories, registerDefaultFactories } from '../chunk-FSHRPY65.js';
2
- import '../chunk-Y3AC3VZ2.js';
3
- import '../chunk-TXEGYR76.js';
1
+ export { createAnimationComponent, createAudioComponent, createCameraComponent, createEntityTypeComponent, createEnvironmentComponent, createImageComponent, createImageTargetAnchorComponent, createImageTargetComponent, createInstanceSlotComponent, createInstancedMeshComponent, createLightComponent, createMaterialComponent, createMeshComponent, createMeshGeometryComponent, createModelComponent, createNameComponent, createObject3DRefComponent, createParentIdComponent, createPhysicsComponent, createPostprocessingComponent, createScriptComponent, createScriptObjectComponent, createSelectableComponent, createSelectionTransformStateComponent, createSpriteComponent, createTransformComponent, createVRTeleportAreaComponent, createVideoComponent, createXRHandPoseComponent, createXRInteractableComponent, createXRInteractorComponent, createXRInteractorSideComponent, createXRRigComponent, registerDefaultComponentFactories, registerDefaultFactories } from '../chunk-JHFBEMXM.js';
2
+ import '../chunk-CHZQ4NXP.js';
3
+ import '../chunk-3LDQ4GVZ.js';
4
4
  import '../chunk-OY7ZODZP.js';
5
5
  //# sourceMappingURL=index.js.map
6
6
  //# sourceMappingURL=index.js.map
@@ -1,4 +1,4 @@
1
- import { 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_RIGIDBODY_STATE, E as EditableMeshObjectKind, o as EntityType, I as ImageComponent, p as ImageTarget, q as ImageTargetAnchor, r as ImageTargetAnchorOptions, s as ImageTargetReference, t as InstanceSlotComponent, u as InstanceTransform, v as InstancedMeshComponent, w as InstancedMeshKind, L as LightComponent, x as LightValueState, M as MaterialComponent, y as MaterialTypeValue, z as MaterialValueState, B as MeshComponent, F as MeshGeometryComponent, G as MeshGeometryParameters, H as MeshGeometryParametersByKind, J as ModelComponent, N as Name, O as Object3DRef, P as PhysicsComponent, K as PhysicsState, Q as PlaneMeshParameters, R as RadiusHeightMeshParameters, S as RadiusMeshParameters, T as RigidbodyState, U as RigidbodyType, V as ScriptComponent, W as ScriptEntry, X as ScriptObjectComponent, Y as ScriptObjectComponentInput, Z as ScriptObjectRuntimeState, _ as Selectable, $ as SelectionTransformState, a0 as SpriteComponent, a1 as TextureFilteringValue, a2 as TransformModeValue, a3 as TransformSpaceValue, a4 as VRTeleportAreaComponent, a5 as VRTeleportAreaOptions, a6 as VideoComponent, a7 as VrTeleportShape, a8 as XRHandPoseComponent, a9 as XRHandPoseOptions, aa as XRInteractableComponent, ab as XRInteractableOptions, ac as XRInteractorComponent, ad as XRInteractorOptions, ae as XRInteractorSideComponent, af as XRRigComponent, ag as XRRigOptions, ah as XrAttachPoint, ai as XrDistanceGrabBehavior, aj as XrGrabGesture, ak as XrGrabHands, al as XrGrabReach, am as XrHandPoseEntry, an as XrHandPreset, ao as XrInteractorSide, ap as XrInteractorType, aq as XrLocomotionMode, ar as XrTrackingOrigin, as as XrTwoHandRotation, at as createAttachPoint, au as createHandPoseEntry, av as defaultMaterialValue, aw as handPoseDefinitionFor, ax as normalizePhysicsState, ay as setPhysicsLiveRef } from './XRHandPose-C-KJeYcJ.cjs';
1
+ import { 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_RIGIDBODY_STATE, E as EditableMeshObjectKind, o as EntityType, I as ImageComponent, p as ImageTarget, q as ImageTargetAnchor, r as ImageTargetAnchorOptions, s as ImageTargetReference, t as InstanceSlotComponent, u as InstanceTransform, v as InstancedMeshComponent, w as InstancedMeshKind, L as LightComponent, x as LightValueState, M as MaterialComponent, y as MaterialTypeValue, z as MaterialValueState, B as MeshComponent, F as MeshGeometryComponent, G as MeshGeometryParameters, H as MeshGeometryParametersByKind, J as ModelComponent, N as Name, O as Object3DRef, P as PhysicsComponent, K as PhysicsState, Q as PlaneMeshParameters, R as RadiusHeightMeshParameters, S as RadiusMeshParameters, T as RigidbodyState, U as RigidbodyType, V as ScriptComponent, W as ScriptEntry, X as ScriptObjectComponent, Y as ScriptObjectComponentInput, Z as ScriptObjectRuntimeState, _ as Selectable, $ as SelectionTransformState, a0 as SpriteComponent, a1 as TextureFilteringValue, a2 as TransformModeValue, a3 as TransformSpaceValue, a4 as VRTeleportAreaComponent, a5 as VRTeleportAreaOptions, a6 as VideoComponent, a7 as VrTeleportShape, a8 as XRHandPoseComponent, a9 as XRHandPoseOptions, aa as XRInteractableComponent, ab as XRInteractableOptions, ac as XRInteractorComponent, ad as XRInteractorOptions, ae as XRInteractorSideComponent, af as XRRigComponent, ag as XRRigOptions, ah as XrAttachPoint, ai as XrDistanceGrabBehavior, aj as XrGrabGesture, ak as XrGrabHands, al as XrGrabReach, am as XrHandPoseEntry, an as XrHandPreset, ao as XrInteractorSide, ap as XrInteractorType, aq as XrLocomotionMode, ar as XrTrackingOrigin, as as XrTwoHandRotation, at as createAttachPoint, au as createHandPoseEntry, av as defaultMaterialValue, aw as handPoseDefinitionFor, ax as normalizePhysicsState, ay as setPhysicsLiveRef } from './XRHandPose-9mVZVU3K.cjs';
2
2
  import { C as Component, 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-31wk-A0g.cjs';
3
3
 
4
4
  /**
@@ -500,6 +500,18 @@ declare class XRInteractionSystem implements EcsSystem {
500
500
  getHeldEntityIds(): Set<number>;
501
501
  /** True when any source is holding something. */
502
502
  isGrabbing(): boolean;
503
+ /**
504
+ * Whether this hand's primary action is committed to interaction.
505
+ *
506
+ * True while the hand holds something, and also while it merely HOVERS a
507
+ * grabbable — because the pinch that is about to grab must not be read as a
508
+ * teleport by the locomotion system. Without the hover half, the first pinch
509
+ * of a grab teleports the player, and so does the pinch that takes an object
510
+ * from the other hand.
511
+ */
512
+ isHandBusy(world: World, handedness: XrInputState["handedness"]): boolean;
513
+ /** True when THIS hand is holding something. */
514
+ isGrabbingWith(handedness: XrInputState["handedness"]): boolean;
503
515
  /**
504
516
  * How an entity is currently held.
505
517
  *
@@ -535,6 +547,16 @@ declare class XRLocomotionSystem implements EcsSystem {
535
547
  private readonly stickAiming;
536
548
  /** True once we've tried to self-heal camera parenting for this session. */
537
549
  private parentingChecked;
550
+ /**
551
+ * Optional; when wired, hands busy grabbing are excluded from teleport.
552
+ *
553
+ * On hand tracking the SAME pinch drives both grabbing and teleport aiming,
554
+ * so without this a user who picks something up is teleported at the same
555
+ * moment.
556
+ */
557
+ private interactionSystem;
558
+ /** Wire the interaction system so grabs suppress teleport on that hand. */
559
+ setInteractionSystem(interactionSystem: XRInteractionSystem | null): void;
538
560
  constructor(inputSystem: XRInputSystem);
539
561
  update(world: World, deltaTime: number): void;
540
562
  /**
@@ -648,6 +670,8 @@ declare class XRControllerVisualSystem implements EcsSystem {
648
670
  private readonly controllerModelFactory;
649
671
  private readonly handModelFactory;
650
672
  private readonly group;
673
+ /** Reused so a per-frame colour compare allocates nothing. */
674
+ private readonly rayColorScratch;
651
675
  private readonly slots;
652
676
  private readonly interactionSystem;
653
677
  /** Optional — lets each visual follow the source that is ACTUALLY live. */
@@ -686,6 +710,8 @@ declare class XRControllerVisualSystem implements EcsSystem {
686
710
  * clutter implying the whole scene is clickable.
687
711
  */
688
712
  private shouldShowRay;
713
+ /** Push the author's ray colour and thickness onto the mesh. */
714
+ private applyRayStyle;
689
715
  /**
690
716
  * Stop the ray at whatever it is pointing at.
691
717
  *
@@ -701,6 +727,14 @@ declare class XRControllerVisualSystem implements EcsSystem {
701
727
  * hands with the player. Falls back to the scene root.
702
728
  */
703
729
  private ensureAttached;
730
+ /**
731
+ * The pointer ray.
732
+ *
733
+ * A cylinder rather than a `THREE.Line`, because WebGL ignores `linewidth` —
734
+ * every line renders one pixel wide regardless, which is nearly invisible on a
735
+ * headset. A thin mesh is the only way to get a ray with real thickness
736
+ * without pulling in a line-rendering extension.
737
+ */
704
738
  private createRay;
705
739
  dispose(): void;
706
740
  }
@@ -1,4 +1,4 @@
1
- import { 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_RIGIDBODY_STATE, E as EditableMeshObjectKind, o as EntityType, I as ImageComponent, p as ImageTarget, q as ImageTargetAnchor, r as ImageTargetAnchorOptions, s as ImageTargetReference, t as InstanceSlotComponent, u as InstanceTransform, v as InstancedMeshComponent, w as InstancedMeshKind, L as LightComponent, x as LightValueState, M as MaterialComponent, y as MaterialTypeValue, z as MaterialValueState, B as MeshComponent, F as MeshGeometryComponent, G as MeshGeometryParameters, H as MeshGeometryParametersByKind, J as ModelComponent, N as Name, O as Object3DRef, P as PhysicsComponent, K as PhysicsState, Q as PlaneMeshParameters, R as RadiusHeightMeshParameters, S as RadiusMeshParameters, T as RigidbodyState, U as RigidbodyType, V as ScriptComponent, W as ScriptEntry, X as ScriptObjectComponent, Y as ScriptObjectComponentInput, Z as ScriptObjectRuntimeState, _ as Selectable, $ as SelectionTransformState, a0 as SpriteComponent, a1 as TextureFilteringValue, a2 as TransformModeValue, a3 as TransformSpaceValue, a4 as VRTeleportAreaComponent, a5 as VRTeleportAreaOptions, a6 as VideoComponent, a7 as VrTeleportShape, a8 as XRHandPoseComponent, a9 as XRHandPoseOptions, aa as XRInteractableComponent, ab as XRInteractableOptions, ac as XRInteractorComponent, ad as XRInteractorOptions, ae as XRInteractorSideComponent, af as XRRigComponent, ag as XRRigOptions, ah as XrAttachPoint, ai as XrDistanceGrabBehavior, aj as XrGrabGesture, ak as XrGrabHands, al as XrGrabReach, am as XrHandPoseEntry, an as XrHandPreset, ao as XrInteractorSide, ap as XrInteractorType, aq as XrLocomotionMode, ar as XrTrackingOrigin, as as XrTwoHandRotation, at as createAttachPoint, au as createHandPoseEntry, av as defaultMaterialValue, aw as handPoseDefinitionFor, ax as normalizePhysicsState, ay as setPhysicsLiveRef } from './XRHandPose-B6I4y1lj.js';
1
+ import { 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_RIGIDBODY_STATE, E as EditableMeshObjectKind, o as EntityType, I as ImageComponent, p as ImageTarget, q as ImageTargetAnchor, r as ImageTargetAnchorOptions, s as ImageTargetReference, t as InstanceSlotComponent, u as InstanceTransform, v as InstancedMeshComponent, w as InstancedMeshKind, L as LightComponent, x as LightValueState, M as MaterialComponent, y as MaterialTypeValue, z as MaterialValueState, B as MeshComponent, F as MeshGeometryComponent, G as MeshGeometryParameters, H as MeshGeometryParametersByKind, J as ModelComponent, N as Name, O as Object3DRef, P as PhysicsComponent, K as PhysicsState, Q as PlaneMeshParameters, R as RadiusHeightMeshParameters, S as RadiusMeshParameters, T as RigidbodyState, U as RigidbodyType, V as ScriptComponent, W as ScriptEntry, X as ScriptObjectComponent, Y as ScriptObjectComponentInput, Z as ScriptObjectRuntimeState, _ as Selectable, $ as SelectionTransformState, a0 as SpriteComponent, a1 as TextureFilteringValue, a2 as TransformModeValue, a3 as TransformSpaceValue, a4 as VRTeleportAreaComponent, a5 as VRTeleportAreaOptions, a6 as VideoComponent, a7 as VrTeleportShape, a8 as XRHandPoseComponent, a9 as XRHandPoseOptions, aa as XRInteractableComponent, ab as XRInteractableOptions, ac as XRInteractorComponent, ad as XRInteractorOptions, ae as XRInteractorSideComponent, af as XRRigComponent, ag as XRRigOptions, ah as XrAttachPoint, ai as XrDistanceGrabBehavior, aj as XrGrabGesture, ak as XrGrabHands, al as XrGrabReach, am as XrHandPoseEntry, an as XrHandPreset, ao as XrInteractorSide, ap as XrInteractorType, aq as XrLocomotionMode, ar as XrTrackingOrigin, as as XrTwoHandRotation, at as createAttachPoint, au as createHandPoseEntry, av as defaultMaterialValue, aw as handPoseDefinitionFor, ax as normalizePhysicsState, ay as setPhysicsLiveRef } from './XRHandPose-To0260Lc.js';
2
2
  import { C as Component, 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-31wk-A0g.js';
3
3
 
4
4
  /**
@@ -500,6 +500,18 @@ declare class XRInteractionSystem implements EcsSystem {
500
500
  getHeldEntityIds(): Set<number>;
501
501
  /** True when any source is holding something. */
502
502
  isGrabbing(): boolean;
503
+ /**
504
+ * Whether this hand's primary action is committed to interaction.
505
+ *
506
+ * True while the hand holds something, and also while it merely HOVERS a
507
+ * grabbable — because the pinch that is about to grab must not be read as a
508
+ * teleport by the locomotion system. Without the hover half, the first pinch
509
+ * of a grab teleports the player, and so does the pinch that takes an object
510
+ * from the other hand.
511
+ */
512
+ isHandBusy(world: World, handedness: XrInputState["handedness"]): boolean;
513
+ /** True when THIS hand is holding something. */
514
+ isGrabbingWith(handedness: XrInputState["handedness"]): boolean;
503
515
  /**
504
516
  * How an entity is currently held.
505
517
  *
@@ -535,6 +547,16 @@ declare class XRLocomotionSystem implements EcsSystem {
535
547
  private readonly stickAiming;
536
548
  /** True once we've tried to self-heal camera parenting for this session. */
537
549
  private parentingChecked;
550
+ /**
551
+ * Optional; when wired, hands busy grabbing are excluded from teleport.
552
+ *
553
+ * On hand tracking the SAME pinch drives both grabbing and teleport aiming,
554
+ * so without this a user who picks something up is teleported at the same
555
+ * moment.
556
+ */
557
+ private interactionSystem;
558
+ /** Wire the interaction system so grabs suppress teleport on that hand. */
559
+ setInteractionSystem(interactionSystem: XRInteractionSystem | null): void;
538
560
  constructor(inputSystem: XRInputSystem);
539
561
  update(world: World, deltaTime: number): void;
540
562
  /**
@@ -648,6 +670,8 @@ declare class XRControllerVisualSystem implements EcsSystem {
648
670
  private readonly controllerModelFactory;
649
671
  private readonly handModelFactory;
650
672
  private readonly group;
673
+ /** Reused so a per-frame colour compare allocates nothing. */
674
+ private readonly rayColorScratch;
651
675
  private readonly slots;
652
676
  private readonly interactionSystem;
653
677
  /** Optional — lets each visual follow the source that is ACTUALLY live. */
@@ -686,6 +710,8 @@ declare class XRControllerVisualSystem implements EcsSystem {
686
710
  * clutter implying the whole scene is clickable.
687
711
  */
688
712
  private shouldShowRay;
713
+ /** Push the author's ray colour and thickness onto the mesh. */
714
+ private applyRayStyle;
689
715
  /**
690
716
  * Stop the ray at whatever it is pointing at.
691
717
  *
@@ -701,6 +727,14 @@ declare class XRControllerVisualSystem implements EcsSystem {
701
727
  * hands with the player. Falls back to the scene root.
702
728
  */
703
729
  private ensureAttached;
730
+ /**
731
+ * The pointer ray.
732
+ *
733
+ * A cylinder rather than a `THREE.Line`, because WebGL ignores `linewidth` —
734
+ * every line renders one pixel wide regardless, which is nearly invisible on a
735
+ * headset. A thin mesh is the only way to get a ray with real thickness
736
+ * without pulling in a line-rendering extension.
737
+ */
704
738
  private createRay;
705
739
  dispose(): void;
706
740
  }
package/dist/index.cjs CHANGED
@@ -2852,8 +2852,8 @@ var _XRInteractableComponent = class _XRInteractableComponent extends Component
2852
2852
  this.attachPoints = (options?.attachPoints ?? []).map(
2853
2853
  (point) => createAttachPoint(point)
2854
2854
  );
2855
- this.throwOnRelease = options?.throwOnRelease ?? true;
2856
- this.throwStrength = options?.throwStrength ?? 1;
2855
+ this.applyVelocityOnRelease = options?.applyVelocityOnRelease ?? true;
2856
+ this.velocityScale = options?.velocityScale ?? 1;
2857
2857
  this.hoverBehavior = options?.hoverBehavior ?? "color";
2858
2858
  this.hoverColor = options?.hoverColor ?? "#4da3ff";
2859
2859
  this.hoverScale = options?.hoverScale ?? 1.06;
@@ -2890,7 +2890,9 @@ var _XRInteractorComponent = class _XRInteractorComponent extends Component {
2890
2890
  this.handColor = options?.handColor ?? "#e8b48a";
2891
2891
  this.handOpacity = options?.handOpacity ?? 1;
2892
2892
  this.handEmissiveIntensity = options?.handEmissiveIntensity ?? 0;
2893
- this.showRay = options?.showRay ?? true;
2893
+ this.rayVisibility = options?.rayVisibility ?? "interacting";
2894
+ this.rayColor = options?.rayColor ?? "#4da3ff";
2895
+ this.rayThickness = options?.rayThickness ?? 6e-3;
2894
2896
  }
2895
2897
  };
2896
2898
  __name(_XRInteractorComponent, "XRInteractorComponent");
@@ -4903,11 +4905,15 @@ function restorePostCreateComponents(world, objectManagementSystem, targetEntity
4903
4905
  )
4904
4906
  );
4905
4907
  }
4906
- if (typeof sourceInteractable.throwOnRelease === "boolean") {
4907
- interactable.throwOnRelease = sourceInteractable.throwOnRelease;
4908
+ if (typeof sourceInteractable.applyVelocityOnRelease === "boolean") {
4909
+ interactable.applyVelocityOnRelease = sourceInteractable.applyVelocityOnRelease;
4910
+ } else if (typeof sourceInteractable.throwOnRelease === "boolean") {
4911
+ interactable.applyVelocityOnRelease = sourceInteractable.throwOnRelease;
4908
4912
  }
4909
- if (typeof sourceInteractable.throwStrength === "number") {
4910
- interactable.throwStrength = sourceInteractable.throwStrength;
4913
+ if (typeof sourceInteractable.velocityScale === "number") {
4914
+ interactable.velocityScale = sourceInteractable.velocityScale;
4915
+ } else if (typeof sourceInteractable.throwStrength === "number") {
4916
+ interactable.velocityScale = sourceInteractable.throwStrength;
4911
4917
  }
4912
4918
  const grabPos = asRecord3(sourceInteractable.grabOffsetPosition);
4913
4919
  if (grabPos) {
@@ -4983,8 +4989,16 @@ function restorePostCreateComponents(world, objectManagementSystem, targetEntity
4983
4989
  if (typeof sourceInteractor.handEmissiveIntensity === "number") {
4984
4990
  interactor.handEmissiveIntensity = sourceInteractor.handEmissiveIntensity;
4985
4991
  }
4986
- if (typeof sourceInteractor.showRay === "boolean") {
4987
- interactor.showRay = sourceInteractor.showRay;
4992
+ if (typeof sourceInteractor.rayVisibility === "string") {
4993
+ interactor.rayVisibility = sourceInteractor.rayVisibility;
4994
+ } else if (typeof sourceInteractor.showRay === "boolean") {
4995
+ interactor.rayVisibility = sourceInteractor.showRay ? "interacting" : "never";
4996
+ }
4997
+ if (typeof sourceInteractor.rayColor === "string") {
4998
+ interactor.rayColor = sourceInteractor.rayColor;
4999
+ }
5000
+ if (typeof sourceInteractor.rayThickness === "number") {
5001
+ interactor.rayThickness = sourceInteractor.rayThickness;
4988
5002
  }
4989
5003
  }
4990
5004
  }
@@ -11627,8 +11641,8 @@ var _XRInteractionSystem = class _XRInteractionSystem {
11627
11641
  if (held.restoreBodyType !== null && physics) {
11628
11642
  physics.values.rigidbody.type = held.restoreBodyType;
11629
11643
  const dynamic = held.restoreBodyType === "dynamic";
11630
- if (dynamic && interactable?.throwOnRelease) {
11631
- const velocity = held.tracker.computeVelocity(this.elapsed).multiplyScalar(interactable.throwStrength);
11644
+ if (dynamic && interactable?.applyVelocityOnRelease) {
11645
+ const velocity = held.tracker.computeVelocity(this.elapsed).multiplyScalar(interactable.velocityScale);
11632
11646
  const spin = held.angularVelocity;
11633
11647
  setPhysicsLiveRef(physics, "pendingVelocity", {
11634
11648
  linear: { x: velocity.x, y: velocity.y, z: velocity.z },
@@ -11709,6 +11723,32 @@ var _XRInteractionSystem = class _XRInteractionSystem {
11709
11723
  isGrabbing() {
11710
11724
  return this.grabs.size > 0;
11711
11725
  }
11726
+ /**
11727
+ * Whether this hand's primary action is committed to interaction.
11728
+ *
11729
+ * True while the hand holds something, and also while it merely HOVERS a
11730
+ * grabbable — because the pinch that is about to grab must not be read as a
11731
+ * teleport by the locomotion system. Without the hover half, the first pinch
11732
+ * of a grab teleports the player, and so does the pinch that takes an object
11733
+ * from the other hand.
11734
+ */
11735
+ isHandBusy(world, handedness) {
11736
+ if (this.isGrabbingWith(handedness)) return true;
11737
+ const hover = this.getHoverFor(handedness);
11738
+ if (!hover) return false;
11739
+ const interactable = world.getComponent(
11740
+ hover.entityId,
11741
+ XRInteractableComponent
11742
+ );
11743
+ return Boolean(interactable?.enabled && interactable.grabbable);
11744
+ }
11745
+ /** True when THIS hand is holding something. */
11746
+ isGrabbingWith(handedness) {
11747
+ for (const input of this.grabs.keys()) {
11748
+ if (input.handedness === handedness) return true;
11749
+ }
11750
+ return false;
11751
+ }
11712
11752
  /**
11713
11753
  * How an entity is currently held.
11714
11754
  *
@@ -11792,8 +11832,20 @@ var _XRLocomotionSystem = class _XRLocomotionSystem {
11792
11832
  this.stickAiming = /* @__PURE__ */ new WeakSet();
11793
11833
  /** True once we've tried to self-heal camera parenting for this session. */
11794
11834
  this.parentingChecked = false;
11835
+ /**
11836
+ * Optional; when wired, hands busy grabbing are excluded from teleport.
11837
+ *
11838
+ * On hand tracking the SAME pinch drives both grabbing and teleport aiming,
11839
+ * so without this a user who picks something up is teleported at the same
11840
+ * moment.
11841
+ */
11842
+ this.interactionSystem = null;
11795
11843
  this.inputSystem = inputSystem;
11796
11844
  }
11845
+ /** Wire the interaction system so grabs suppress teleport on that hand. */
11846
+ setInteractionSystem(interactionSystem) {
11847
+ this.interactionSystem = interactionSystem;
11848
+ }
11797
11849
  update(world, deltaTime) {
11798
11850
  this.aimCurve = [];
11799
11851
  this.landingPoint = null;
@@ -11911,6 +11963,9 @@ var _XRLocomotionSystem = class _XRLocomotionSystem {
11911
11963
  applyTeleport(world, transform, inputs) {
11912
11964
  const targets = this.collectTeleportTargets(world);
11913
11965
  for (const input of inputs) {
11966
+ if (input.handedness !== "none" && this.interactionSystem?.isHandBusy(world, input.handedness)) {
11967
+ continue;
11968
+ }
11914
11969
  const source = input;
11915
11970
  const stick = this.readStickAim(input, source);
11916
11971
  const aiming = input.select || stick.aiming;
@@ -12268,6 +12323,7 @@ __name(applyHandMaterial, "applyHandMaterial");
12268
12323
 
12269
12324
  // core/systems/XRControllerVisualSystem.ts
12270
12325
  var RAY_LENGTH = 5;
12326
+ var RAY_RADIUS = 3e-3;
12271
12327
  var SLOTS = [
12272
12328
  { index: 0, side: "left" },
12273
12329
  { index: 1, side: "right" }
@@ -12277,6 +12333,8 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
12277
12333
  this.controllerModelFactory = new XRControllerModelFactory_js.XRControllerModelFactory();
12278
12334
  this.handModelFactory = new XRHandModelFactory_js.XRHandModelFactory();
12279
12335
  this.group = new THREE51__namespace.Group();
12336
+ /** Reused so a per-frame colour compare allocates nothing. */
12337
+ this.rayColorScratch = new THREE51__namespace.Color();
12280
12338
  this.slots = /* @__PURE__ */ new Map();
12281
12339
  this.attachedTo = null;
12282
12340
  /** Last applied preset signature, so materials rebuild only on real change. */
@@ -12305,8 +12363,9 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
12305
12363
  const hasHand = liveKind === null || liveKind === "hand";
12306
12364
  visuals.controllerModel.visible = showControllers && hasController;
12307
12365
  visuals.handModel.visible = showHands && hasHand;
12308
- visuals.ray.visible = this.shouldShowRay(interactor);
12366
+ visuals.ray.visible = this.shouldShowRay(interactor, side);
12309
12367
  this.fitRayToHover(visuals.ray, side);
12368
+ this.applyRayStyle(visuals.ray, interactor);
12310
12369
  if (showHands && this.handMaterial) {
12311
12370
  applyHandMaterial(visuals.handModel, this.handMaterial);
12312
12371
  }
@@ -12382,10 +12441,26 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
12382
12441
  * off entirely; otherwise it appears on hover/grab so it isn't permanent
12383
12442
  * clutter implying the whole scene is clickable.
12384
12443
  */
12385
- shouldShowRay(interactor) {
12386
- if (interactor && !interactor.showRay) return false;
12444
+ shouldShowRay(interactor, side) {
12445
+ const visibility = interactor?.rayVisibility ?? "interacting";
12446
+ if (visibility === "never") return false;
12447
+ if (visibility === "always") return true;
12387
12448
  if (!this.interactionSystem) return true;
12388
- return this.interactionSystem.getHoveredEntityId() !== null || this.interactionSystem.isGrabbing();
12449
+ if (this.interactionSystem.isGrabbingWith(side)) return false;
12450
+ return this.interactionSystem.getHoverFor(side) !== null;
12451
+ }
12452
+ /** Push the author's ray colour and thickness onto the mesh. */
12453
+ applyRayStyle(ray, interactor) {
12454
+ if (!interactor) return;
12455
+ const material = ray.material;
12456
+ if (material?.color && !material.color.equals(this.rayColorScratch.set(interactor.rayColor))) {
12457
+ material.color.copy(this.rayColorScratch);
12458
+ }
12459
+ const radius = Math.max(5e-4, interactor.rayThickness / 2) / RAY_RADIUS;
12460
+ if (ray.scale.x !== radius) {
12461
+ ray.scale.x = radius;
12462
+ ray.scale.y = radius;
12463
+ }
12389
12464
  }
12390
12465
  /**
12391
12466
  * Stop the ray at whatever it is pointing at.
@@ -12397,7 +12472,7 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
12397
12472
  fitRayToHover(ray, side) {
12398
12473
  const hover = this.interactionSystem?.getHoverFor(side) ?? null;
12399
12474
  const length = hover && Number.isFinite(hover.distance) && hover.distance > 0 ? Math.min(hover.distance, RAY_LENGTH) : RAY_LENGTH;
12400
- ray.scale.z = length / RAY_LENGTH;
12475
+ ray.scale.z = length;
12401
12476
  }
12402
12477
  /** Lazily build per-slot visuals; the device reports profiles late. */
12403
12478
  ensureSlots(world) {
@@ -12437,22 +12512,32 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
12437
12512
  target.add(this.group);
12438
12513
  this.attachedTo = target;
12439
12514
  }
12515
+ /**
12516
+ * The pointer ray.
12517
+ *
12518
+ * A cylinder rather than a `THREE.Line`, because WebGL ignores `linewidth` —
12519
+ * every line renders one pixel wide regardless, which is nearly invisible on a
12520
+ * headset. A thin mesh is the only way to get a ray with real thickness
12521
+ * without pulling in a line-rendering extension.
12522
+ */
12440
12523
  createRay() {
12441
- const geometry = new THREE51__namespace.BufferGeometry().setFromPoints([
12442
- new THREE51__namespace.Vector3(0, 0, 0),
12443
- new THREE51__namespace.Vector3(0, 0, -RAY_LENGTH)
12444
- ]);
12445
- const material = new THREE51__namespace.LineBasicMaterial({
12524
+ const geometry = new THREE51__namespace.CylinderGeometry(RAY_RADIUS, RAY_RADIUS, 1, 8, 1);
12525
+ geometry.rotateX(-Math.PI / 2);
12526
+ geometry.translate(0, 0, -0.5);
12527
+ const material = new THREE51__namespace.MeshBasicMaterial({
12446
12528
  color: "#4da3ff",
12447
12529
  transparent: true,
12448
- opacity: 0.6,
12449
- depthTest: false
12530
+ opacity: 0.75,
12531
+ depthTest: false,
12532
+ depthWrite: false
12450
12533
  });
12451
- const line = new THREE51__namespace.Line(geometry, material);
12452
- line.name = "XRPointerRay";
12453
- line.renderOrder = 999;
12454
- line.visible = false;
12455
- return line;
12534
+ const mesh = new THREE51__namespace.Mesh(geometry, material);
12535
+ mesh.name = "XRPointerRay";
12536
+ mesh.renderOrder = 999;
12537
+ mesh.visible = false;
12538
+ mesh.raycast = () => {
12539
+ };
12540
+ return mesh;
12456
12541
  }
12457
12542
  dispose() {
12458
12543
  this.group.removeFromParent();