@relu-interactives/spatial-ecs 0.3.5 → 0.3.6

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 (44) hide show
  1. package/dist/{System-vrU46Vuw.d.cts → System-TmC2EijF.d.cts} +2 -2
  2. package/dist/{System-vrU46Vuw.d.ts → System-TmC2EijF.d.ts} +2 -2
  3. package/dist/{XRRig-2686IqLQ.d.cts → XRInteractor-CCUzSqg9.d.ts} +96 -2
  4. package/dist/{XRRig-D2QURXl1.d.ts → XRInteractor-I2q6TKtF.d.cts} +96 -2
  5. package/dist/{chunk-4BZYK3JP.js → chunk-FQTOC7HK.js} +135 -88
  6. package/dist/chunk-FQTOC7HK.js.map +1 -0
  7. package/dist/{chunk-2LVFGVWI.js → chunk-JRJ3CL5H.js} +3 -3
  8. package/dist/{chunk-2LVFGVWI.js.map → chunk-JRJ3CL5H.js.map} +1 -1
  9. package/dist/{chunk-6QC2PJLD.js → chunk-N4GKZ7IV.js} +29 -3
  10. package/dist/chunk-N4GKZ7IV.js.map +1 -0
  11. package/dist/{chunk-G53MZVKQ.js → chunk-WRJ2K3LZ.js} +285 -39
  12. package/dist/chunk-WRJ2K3LZ.js.map +1 -0
  13. package/dist/components/index.cjs +26 -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/factories/index.cjs +185 -112
  19. package/dist/factories/index.cjs.map +1 -1
  20. package/dist/factories/index.d.cts +7 -3
  21. package/dist/factories/index.d.ts +7 -3
  22. package/dist/factories/index.js +3 -3
  23. package/dist/{index-BtKOaHfY.d.ts → index-BltjPEhg.d.cts} +10 -3
  24. package/dist/{index-B-CViRMx.d.ts → index-BpbmZuOz.d.ts} +43 -14
  25. package/dist/{index-BvCmmuJ0.d.cts → index-C5FrDt3z.d.cts} +43 -14
  26. package/dist/{index-Xu238jLn.d.cts → index-W8pUajCW.d.ts} +10 -3
  27. package/dist/index.cjs +602 -279
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.cts +35 -9
  30. package/dist/index.d.ts +35 -9
  31. package/dist/index.js +8 -8
  32. package/dist/systems/index.cjs +304 -34
  33. package/dist/systems/index.cjs.map +1 -1
  34. package/dist/systems/index.d.cts +2 -2
  35. package/dist/systems/index.d.ts +2 -2
  36. package/dist/systems/index.js +3 -3
  37. package/dist/types.d.cts +1 -1
  38. package/dist/types.d.ts +1 -1
  39. package/dist/worldSnapshotUtils.d.cts +1 -1
  40. package/dist/worldSnapshotUtils.d.ts +1 -1
  41. package/package.json +1 -1
  42. package/dist/chunk-4BZYK3JP.js.map +0 -1
  43. package/dist/chunk-6QC2PJLD.js.map +0 -1
  44. package/dist/chunk-G53MZVKQ.js.map +0 -1
package/dist/index.d.cts CHANGED
@@ -1,12 +1,12 @@
1
- import { k as EcsSystem, C as Component, W as WorldEntityView, T as TransformComponent, l as World, S as SpawnPrefabSource, m as SpawnPrefabOptions, n as ComponentClass, o as ParentLookup, p as EcsEntityKind, O as ObjectManagementSystem, q as SubtreeSnapshot, r as EntityId, s as ExternalRefWarning } from './System-vrU46Vuw.cjs';
2
- export { A as AssetInput, t as CheckboxInput, u as ColorInput, v as ComponentFactory, w as ComponentInput, x as ComponentKind, y as DropdownInput, z as DropdownOption, B as EcsComponentFactoryKind, F as EcsEntityEditorKind, G as EntityInput, H as FloatInput, I as InputSystem, J as IntersectionResult, K as KeyboardKey, L as KeyboardKeys, M as MouseButton, N as PREFAB_FILE_VERSION, Q as PREFAB_FILE_VERSION_NESTED, R as PrefabAsset, U as RemapSnapshotOptions, X as RenderSystem, Y as SelectionListener, Z as SliderInput, _ as TextInput, $ as ToggleInput, a0 as TransformSyncSystem, a1 as Vec3, a2 as Vector2Input, a3 as Vector3Input, a4 as clearPrefabCache, a5 as despawnPrefab, a6 as loadPrefab, a7 as parsePrefabAsset, a8 as prefabFileVersionFor, a9 as remapSnapshotEntityIds, aa as setPrefabAssetUrlResolver, ab as spawnPrefab } from './System-vrU46Vuw.cjs';
1
+ import { k as EcsSystem, C as Component, W as WorldEntityView, T as TransformComponent, l as World, S as SpawnPrefabSource, m as SpawnPrefabOptions, n as ComponentClass, o as ParentLookup, p as EcsEntityKind, O as ObjectManagementSystem, q as SubtreeSnapshot, r as EntityId, s as ExternalRefWarning } from './System-TmC2EijF.cjs';
2
+ export { A as AssetInput, t as CheckboxInput, u as ColorInput, v as ComponentFactory, w as ComponentInput, x as ComponentKind, y as DropdownInput, z as DropdownOption, B as EcsComponentFactoryKind, F as EcsEntityEditorKind, G as EntityInput, H as FloatInput, I as InputSystem, J as IntersectionResult, K as KeyboardKey, L as KeyboardKeys, M as MouseButton, N as PREFAB_FILE_VERSION, Q as PREFAB_FILE_VERSION_NESTED, R as PrefabAsset, U as RemapSnapshotOptions, X as RenderSystem, Y as SelectionListener, Z as SliderInput, _ as TextInput, $ as ToggleInput, a0 as TransformSyncSystem, a1 as Vec3, a2 as Vector2Input, a3 as Vector3Input, a4 as clearPrefabCache, a5 as despawnPrefab, a6 as loadPrefab, a7 as parsePrefabAsset, a8 as prefabFileVersionFor, a9 as remapSnapshotEntityIds, aa as setPrefabAssetUrlResolver, ab as spawnPrefab } from './System-TmC2EijF.cjs';
3
3
  import * as THREE from 'three';
4
- import { O as Object3DRef } from './XRRig-2686IqLQ.cjs';
5
- export { ag as AnimationStateCallbacks, ah as AnimationStateMachine, ai as AnimationStateManager, aj as StateMachine } from './XRRig-2686IqLQ.cjs';
6
- import { X as XrCapabilities, a as XrInputState } from './index-BvCmmuJ0.cjs';
7
- export { A as AnimationSystem, b as AudioSystem, C as CameraSyncSystem, E as EnvironmentSyncSystem, I as InstancedMeshSystem, L as LightSyncSystem, M as MaterialSyncSystem, c as MeshGeometrySystem, d as ModuleLoader, N as NO_XR_CAPABILITIES, O as ObjectVisibilitySystem, P as PhysicsSyncSystem, e as PostprocessingSyncSystem, S as SCRIPT_OBJECT_ROOT_FLAG, f as ScriptBehaviourSystem, g as ScriptObjectSystem, h as SelectionContext, V as VRTeleportAreaSystem, i as VideoSystem, j as XRControllerVisualSystem, k as XRInputSystem, l as XRInteractionSystem, m as XRLocomotionSystem, n as XRSessionSystem, o as XRTeleportVisualSystem, p as XrHandedness, q as XrInputKind, r as readXrCapabilities } from './index-BvCmmuJ0.cjs';
8
- export { i as CoreComponents } from './index-Xu238jLn.cjs';
9
- 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, createXRInteractableComponent, createXRRigComponent, registerDefaultComponentFactories, registerDefaultFactories } from './factories/index.cjs';
4
+ import { O as Object3DRef, af as XrHandPreset } from './XRInteractor-I2q6TKtF.cjs';
5
+ export { an as AnimationStateCallbacks, ao as AnimationStateMachine, ap as AnimationStateManager, aq as StateMachine } from './XRInteractor-I2q6TKtF.cjs';
6
+ import { X as XrCapabilities, a as XrInputState } from './index-C5FrDt3z.cjs';
7
+ export { A as AnimationSystem, b as AudioSystem, C as CameraSyncSystem, E as EnvironmentSyncSystem, I as InstancedMeshSystem, L as LightSyncSystem, M as MaterialSyncSystem, c as MeshGeometrySystem, d as ModuleLoader, N as NO_XR_CAPABILITIES, O as ObjectVisibilitySystem, P as PhysicsSyncSystem, e as PostprocessingSyncSystem, S as SCRIPT_OBJECT_ROOT_FLAG, f as ScriptBehaviourSystem, g as ScriptObjectSystem, h as SelectionContext, V as VRTeleportAreaSystem, i as VideoSystem, j as XRControllerVisualSystem, k as XRInputSystem, l as XRInteractionSystem, m as XRLocomotionSystem, n as XRSessionSystem, o as XRTeleportVisualSystem, p as XrHandedness, q as XrInputKind, r as readXrCapabilities } from './index-C5FrDt3z.cjs';
8
+ export { i as CoreComponents } from './index-BltjPEhg.cjs';
9
+ 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, createXRInteractableComponent, createXRInteractorComponent, createXRInteractorSideComponent, createXRRigComponent, registerDefaultComponentFactories, registerDefaultFactories } from './factories/index.cjs';
10
10
  import { GLTF } from 'three/examples/jsm/loaders/GLTFLoader.js';
11
11
  import '@dimforge/rapier3d-compat';
12
12
 
@@ -430,6 +430,8 @@ type ComponentValueMaps = {
430
430
  xrRigValues: Map<number, unknown>;
431
431
  vrTeleportAreaValues: Map<number, unknown>;
432
432
  xrInteractableValues: Map<number, unknown>;
433
+ xrInteractorValues: Map<number, unknown>;
434
+ xrInteractorSideValues: Map<number, unknown>;
433
435
  instancedMeshValues: Map<number, unknown>;
434
436
  instanceSlotValues: Map<number, unknown>;
435
437
  prefabNodeValues: Map<number, unknown>;
@@ -784,4 +786,28 @@ declare function sampleTeleportArc(origin: THREE.Vector3, direction: THREE.Vecto
784
786
  */
785
787
  declare function arcGroundCrossing(points: THREE.Vector3[], groundY: number): THREE.Vector3 | null;
786
788
 
787
- export { ADDED_NODE_MARKER_COMPONENT, ARC_GRAVITY, ARC_MAX_TIME, ARC_SPEED, ARC_STEPS, type ApplyPrefabToSnapshotResult, Behaviour, Component, type ComponentValueMaps, EcsEntityKind, EcsSystem, type EcsWorldComponentSnapshot, type EcsWorldStateSnapshotLike, EntityId, ExternalRefWarning, HYDRATABLE_ENTITY_KINDS, type HydrateOptions, type HydrateWorldFromSnapshotResult, type InstantiateSubtreeResult, NODE_KEY_SEPARATOR, type NestedRegion, type NodeKeyMaps, type NodeMaps, OVERRIDE_DIFF_EXCLUDED_COMPONENTS, OVERRIDE_ROOT_EXCLUDED_COMPONENTS, ObjectManagementSystem, ParentLookup, SHARED_MODEL_RESOURCE_FLAG, ScriptObject, type SerializeEntitySubtreeResult, SpawnPrefabOptions, SpawnPrefabSource, SubtreeSnapshot, World, WorldEntityView, XrCapabilities, XrInputState, applyPrefabToSnapshotInstances, arcGroundCrossing, buildComponentValueMaps, buildNodeKeyMapsFromSnapshot, buildNodeMapsFromSnapshot, canonicalizeComponentValue, clearModelCache, collectDiffPaths, collectDirectPrefabDependencies, collectEntitySubtree, collectSnapshotSubtreeIds, computeInstanceOverrides, decanonicalizeComponentValue, encodeOverride, findSnapshotRootEntityIds, findTopLevelNestedRegions, groupOverridePaths, hydrateWorldFromSnapshot, hydrateWorldFromSnapshotDetailed, indexSnapshotByEntity, instantiateSubtree, loadSharedGltf, mergeComponentValue, parseOverride, resolveDracoDecoderPath, restoreComponentState, restorePostCreateComponents, sampleTeleportArc, serializeEntitySubtree, setDracoDecoderPath };
789
+ /**
790
+ * Materials for tracked-hand meshes.
791
+ *
792
+ * three's `XRHandModelFactory` builds the joint geometry but gives it a plain
793
+ * default material, so hands look identical in every experience. These presets
794
+ * let an author pick a look in one click, with `custom` deferring entirely to
795
+ * the colour/opacity/emissive fields.
796
+ */
797
+ type HandMaterialOptions = {
798
+ color: string;
799
+ opacity: number;
800
+ emissiveIntensity: number;
801
+ };
802
+ /**
803
+ * Build the material for a preset.
804
+ *
805
+ * Returns a fresh material each call — hands are per-session and disposed with
806
+ * the interactor, and sharing one instance across presets would make switching
807
+ * leak state between them.
808
+ */
809
+ declare function createHandMaterial(preset: XrHandPreset, options: HandMaterialOptions): THREE.Material;
810
+ /** Apply a preset material to every mesh under a hand model. */
811
+ declare function applyHandMaterial(root: THREE.Object3D, material: THREE.Material): void;
812
+
813
+ export { ADDED_NODE_MARKER_COMPONENT, ARC_GRAVITY, ARC_MAX_TIME, ARC_SPEED, ARC_STEPS, type ApplyPrefabToSnapshotResult, Behaviour, Component, type ComponentValueMaps, EcsEntityKind, EcsSystem, type EcsWorldComponentSnapshot, type EcsWorldStateSnapshotLike, EntityId, ExternalRefWarning, HYDRATABLE_ENTITY_KINDS, type HandMaterialOptions, type HydrateOptions, type HydrateWorldFromSnapshotResult, type InstantiateSubtreeResult, NODE_KEY_SEPARATOR, type NestedRegion, type NodeKeyMaps, type NodeMaps, OVERRIDE_DIFF_EXCLUDED_COMPONENTS, OVERRIDE_ROOT_EXCLUDED_COMPONENTS, ObjectManagementSystem, ParentLookup, SHARED_MODEL_RESOURCE_FLAG, ScriptObject, type SerializeEntitySubtreeResult, SpawnPrefabOptions, SpawnPrefabSource, SubtreeSnapshot, World, WorldEntityView, XrCapabilities, XrInputState, applyHandMaterial, applyPrefabToSnapshotInstances, arcGroundCrossing, buildComponentValueMaps, buildNodeKeyMapsFromSnapshot, buildNodeMapsFromSnapshot, canonicalizeComponentValue, clearModelCache, collectDiffPaths, collectDirectPrefabDependencies, collectEntitySubtree, collectSnapshotSubtreeIds, computeInstanceOverrides, createHandMaterial, decanonicalizeComponentValue, encodeOverride, findSnapshotRootEntityIds, findTopLevelNestedRegions, groupOverridePaths, hydrateWorldFromSnapshot, hydrateWorldFromSnapshotDetailed, indexSnapshotByEntity, instantiateSubtree, loadSharedGltf, mergeComponentValue, parseOverride, resolveDracoDecoderPath, restoreComponentState, restorePostCreateComponents, sampleTeleportArc, serializeEntitySubtree, setDracoDecoderPath };
package/dist/index.d.ts CHANGED
@@ -1,12 +1,12 @@
1
- import { k as EcsSystem, C as Component, W as WorldEntityView, T as TransformComponent, l as World, S as SpawnPrefabSource, m as SpawnPrefabOptions, n as ComponentClass, o as ParentLookup, p as EcsEntityKind, O as ObjectManagementSystem, q as SubtreeSnapshot, r as EntityId, s as ExternalRefWarning } from './System-vrU46Vuw.js';
2
- export { A as AssetInput, t as CheckboxInput, u as ColorInput, v as ComponentFactory, w as ComponentInput, x as ComponentKind, y as DropdownInput, z as DropdownOption, B as EcsComponentFactoryKind, F as EcsEntityEditorKind, G as EntityInput, H as FloatInput, I as InputSystem, J as IntersectionResult, K as KeyboardKey, L as KeyboardKeys, M as MouseButton, N as PREFAB_FILE_VERSION, Q as PREFAB_FILE_VERSION_NESTED, R as PrefabAsset, U as RemapSnapshotOptions, X as RenderSystem, Y as SelectionListener, Z as SliderInput, _ as TextInput, $ as ToggleInput, a0 as TransformSyncSystem, a1 as Vec3, a2 as Vector2Input, a3 as Vector3Input, a4 as clearPrefabCache, a5 as despawnPrefab, a6 as loadPrefab, a7 as parsePrefabAsset, a8 as prefabFileVersionFor, a9 as remapSnapshotEntityIds, aa as setPrefabAssetUrlResolver, ab as spawnPrefab } from './System-vrU46Vuw.js';
1
+ import { k as EcsSystem, C as Component, W as WorldEntityView, T as TransformComponent, l as World, S as SpawnPrefabSource, m as SpawnPrefabOptions, n as ComponentClass, o as ParentLookup, p as EcsEntityKind, O as ObjectManagementSystem, q as SubtreeSnapshot, r as EntityId, s as ExternalRefWarning } from './System-TmC2EijF.js';
2
+ export { A as AssetInput, t as CheckboxInput, u as ColorInput, v as ComponentFactory, w as ComponentInput, x as ComponentKind, y as DropdownInput, z as DropdownOption, B as EcsComponentFactoryKind, F as EcsEntityEditorKind, G as EntityInput, H as FloatInput, I as InputSystem, J as IntersectionResult, K as KeyboardKey, L as KeyboardKeys, M as MouseButton, N as PREFAB_FILE_VERSION, Q as PREFAB_FILE_VERSION_NESTED, R as PrefabAsset, U as RemapSnapshotOptions, X as RenderSystem, Y as SelectionListener, Z as SliderInput, _ as TextInput, $ as ToggleInput, a0 as TransformSyncSystem, a1 as Vec3, a2 as Vector2Input, a3 as Vector3Input, a4 as clearPrefabCache, a5 as despawnPrefab, a6 as loadPrefab, a7 as parsePrefabAsset, a8 as prefabFileVersionFor, a9 as remapSnapshotEntityIds, aa as setPrefabAssetUrlResolver, ab as spawnPrefab } from './System-TmC2EijF.js';
3
3
  import * as THREE from 'three';
4
- import { O as Object3DRef } from './XRRig-D2QURXl1.js';
5
- export { ag as AnimationStateCallbacks, ah as AnimationStateMachine, ai as AnimationStateManager, aj as StateMachine } from './XRRig-D2QURXl1.js';
6
- import { X as XrCapabilities, a as XrInputState } from './index-B-CViRMx.js';
7
- export { A as AnimationSystem, b as AudioSystem, C as CameraSyncSystem, E as EnvironmentSyncSystem, I as InstancedMeshSystem, L as LightSyncSystem, M as MaterialSyncSystem, c as MeshGeometrySystem, d as ModuleLoader, N as NO_XR_CAPABILITIES, O as ObjectVisibilitySystem, P as PhysicsSyncSystem, e as PostprocessingSyncSystem, S as SCRIPT_OBJECT_ROOT_FLAG, f as ScriptBehaviourSystem, g as ScriptObjectSystem, h as SelectionContext, V as VRTeleportAreaSystem, i as VideoSystem, j as XRControllerVisualSystem, k as XRInputSystem, l as XRInteractionSystem, m as XRLocomotionSystem, n as XRSessionSystem, o as XRTeleportVisualSystem, p as XrHandedness, q as XrInputKind, r as readXrCapabilities } from './index-B-CViRMx.js';
8
- export { i as CoreComponents } from './index-BtKOaHfY.js';
9
- 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, createXRInteractableComponent, createXRRigComponent, registerDefaultComponentFactories, registerDefaultFactories } from './factories/index.js';
4
+ import { O as Object3DRef, af as XrHandPreset } from './XRInteractor-CCUzSqg9.js';
5
+ export { an as AnimationStateCallbacks, ao as AnimationStateMachine, ap as AnimationStateManager, aq as StateMachine } from './XRInteractor-CCUzSqg9.js';
6
+ import { X as XrCapabilities, a as XrInputState } from './index-BpbmZuOz.js';
7
+ export { A as AnimationSystem, b as AudioSystem, C as CameraSyncSystem, E as EnvironmentSyncSystem, I as InstancedMeshSystem, L as LightSyncSystem, M as MaterialSyncSystem, c as MeshGeometrySystem, d as ModuleLoader, N as NO_XR_CAPABILITIES, O as ObjectVisibilitySystem, P as PhysicsSyncSystem, e as PostprocessingSyncSystem, S as SCRIPT_OBJECT_ROOT_FLAG, f as ScriptBehaviourSystem, g as ScriptObjectSystem, h as SelectionContext, V as VRTeleportAreaSystem, i as VideoSystem, j as XRControllerVisualSystem, k as XRInputSystem, l as XRInteractionSystem, m as XRLocomotionSystem, n as XRSessionSystem, o as XRTeleportVisualSystem, p as XrHandedness, q as XrInputKind, r as readXrCapabilities } from './index-BpbmZuOz.js';
8
+ export { i as CoreComponents } from './index-W8pUajCW.js';
9
+ 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, createXRInteractableComponent, createXRInteractorComponent, createXRInteractorSideComponent, createXRRigComponent, registerDefaultComponentFactories, registerDefaultFactories } from './factories/index.js';
10
10
  import { GLTF } from 'three/examples/jsm/loaders/GLTFLoader.js';
11
11
  import '@dimforge/rapier3d-compat';
12
12
 
@@ -430,6 +430,8 @@ type ComponentValueMaps = {
430
430
  xrRigValues: Map<number, unknown>;
431
431
  vrTeleportAreaValues: Map<number, unknown>;
432
432
  xrInteractableValues: Map<number, unknown>;
433
+ xrInteractorValues: Map<number, unknown>;
434
+ xrInteractorSideValues: Map<number, unknown>;
433
435
  instancedMeshValues: Map<number, unknown>;
434
436
  instanceSlotValues: Map<number, unknown>;
435
437
  prefabNodeValues: Map<number, unknown>;
@@ -784,4 +786,28 @@ declare function sampleTeleportArc(origin: THREE.Vector3, direction: THREE.Vecto
784
786
  */
785
787
  declare function arcGroundCrossing(points: THREE.Vector3[], groundY: number): THREE.Vector3 | null;
786
788
 
787
- export { ADDED_NODE_MARKER_COMPONENT, ARC_GRAVITY, ARC_MAX_TIME, ARC_SPEED, ARC_STEPS, type ApplyPrefabToSnapshotResult, Behaviour, Component, type ComponentValueMaps, EcsEntityKind, EcsSystem, type EcsWorldComponentSnapshot, type EcsWorldStateSnapshotLike, EntityId, ExternalRefWarning, HYDRATABLE_ENTITY_KINDS, type HydrateOptions, type HydrateWorldFromSnapshotResult, type InstantiateSubtreeResult, NODE_KEY_SEPARATOR, type NestedRegion, type NodeKeyMaps, type NodeMaps, OVERRIDE_DIFF_EXCLUDED_COMPONENTS, OVERRIDE_ROOT_EXCLUDED_COMPONENTS, ObjectManagementSystem, ParentLookup, SHARED_MODEL_RESOURCE_FLAG, ScriptObject, type SerializeEntitySubtreeResult, SpawnPrefabOptions, SpawnPrefabSource, SubtreeSnapshot, World, WorldEntityView, XrCapabilities, XrInputState, applyPrefabToSnapshotInstances, arcGroundCrossing, buildComponentValueMaps, buildNodeKeyMapsFromSnapshot, buildNodeMapsFromSnapshot, canonicalizeComponentValue, clearModelCache, collectDiffPaths, collectDirectPrefabDependencies, collectEntitySubtree, collectSnapshotSubtreeIds, computeInstanceOverrides, decanonicalizeComponentValue, encodeOverride, findSnapshotRootEntityIds, findTopLevelNestedRegions, groupOverridePaths, hydrateWorldFromSnapshot, hydrateWorldFromSnapshotDetailed, indexSnapshotByEntity, instantiateSubtree, loadSharedGltf, mergeComponentValue, parseOverride, resolveDracoDecoderPath, restoreComponentState, restorePostCreateComponents, sampleTeleportArc, serializeEntitySubtree, setDracoDecoderPath };
789
+ /**
790
+ * Materials for tracked-hand meshes.
791
+ *
792
+ * three's `XRHandModelFactory` builds the joint geometry but gives it a plain
793
+ * default material, so hands look identical in every experience. These presets
794
+ * let an author pick a look in one click, with `custom` deferring entirely to
795
+ * the colour/opacity/emissive fields.
796
+ */
797
+ type HandMaterialOptions = {
798
+ color: string;
799
+ opacity: number;
800
+ emissiveIntensity: number;
801
+ };
802
+ /**
803
+ * Build the material for a preset.
804
+ *
805
+ * Returns a fresh material each call — hands are per-session and disposed with
806
+ * the interactor, and sharing one instance across presets would make switching
807
+ * leak state between them.
808
+ */
809
+ declare function createHandMaterial(preset: XrHandPreset, options: HandMaterialOptions): THREE.Material;
810
+ /** Apply a preset material to every mesh under a hand model. */
811
+ declare function applyHandMaterial(root: THREE.Object3D, material: THREE.Material): void;
812
+
813
+ export { ADDED_NODE_MARKER_COMPONENT, ARC_GRAVITY, ARC_MAX_TIME, ARC_SPEED, ARC_STEPS, type ApplyPrefabToSnapshotResult, Behaviour, Component, type ComponentValueMaps, EcsEntityKind, EcsSystem, type EcsWorldComponentSnapshot, type EcsWorldStateSnapshotLike, EntityId, ExternalRefWarning, HYDRATABLE_ENTITY_KINDS, type HandMaterialOptions, type HydrateOptions, type HydrateWorldFromSnapshotResult, type InstantiateSubtreeResult, NODE_KEY_SEPARATOR, type NestedRegion, type NodeKeyMaps, type NodeMaps, OVERRIDE_DIFF_EXCLUDED_COMPONENTS, OVERRIDE_ROOT_EXCLUDED_COMPONENTS, ObjectManagementSystem, ParentLookup, SHARED_MODEL_RESOURCE_FLAG, ScriptObject, type SerializeEntitySubtreeResult, SpawnPrefabOptions, SpawnPrefabSource, SubtreeSnapshot, World, WorldEntityView, XrCapabilities, XrInputState, applyHandMaterial, applyPrefabToSnapshotInstances, arcGroundCrossing, buildComponentValueMaps, buildNodeKeyMapsFromSnapshot, buildNodeMapsFromSnapshot, canonicalizeComponentValue, clearModelCache, collectDiffPaths, collectDirectPrefabDependencies, collectEntitySubtree, collectSnapshotSubtreeIds, computeInstanceOverrides, createHandMaterial, decanonicalizeComponentValue, encodeOverride, findSnapshotRootEntityIds, findTopLevelNestedRegions, groupOverridePaths, hydrateWorldFromSnapshot, hydrateWorldFromSnapshotDetailed, indexSnapshotByEntity, instantiateSubtree, loadSharedGltf, mergeComponentValue, parseOverride, resolveDracoDecoderPath, restoreComponentState, restorePostCreateComponents, sampleTeleportArc, serializeEntitySubtree, setDracoDecoderPath };
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
- import { MeshGeometrySystem, InstancedMeshSystem, EnvironmentSyncSystem, PostprocessingSyncSystem, LightSyncSystem, MaterialSyncSystem, VRTeleportAreaSystem, PhysicsSyncSystem, AnimationSystem, AudioSystem, VideoSystem, CameraSyncSystem, TransformSyncSystem, ObjectVisibilitySystem, RenderSystem, spawnPrefab, despawnPrefab, buildNodeKeyMapsFromSnapshot, indexSnapshotByEntity, findTopLevelNestedRegions, collectSnapshotSubtreeIds, groupOverridePaths, OVERRIDE_DIFF_EXCLUDED_COMPONENTS, OVERRIDE_ROOT_EXCLUDED_COMPONENTS, canonicalizeComponentValue, mergeComponentValue, decanonicalizeComponentValue, computeInstanceOverrides, collectEntitySubtree, ADDED_NODE_MARKER_COMPONENT } from './chunk-G53MZVKQ.js';
2
- export { ADDED_NODE_MARKER_COMPONENT, ARC_GRAVITY, ARC_MAX_TIME, ARC_SPEED, ARC_STEPS, AnimationSystem, AudioSystem, Behaviour, CameraSyncSystem, EnvironmentSyncSystem, HYDRATABLE_ENTITY_KINDS, InputSystem, InstancedMeshSystem, KeyboardKeys, LightSyncSystem, MaterialSyncSystem, MeshGeometrySystem, NODE_KEY_SEPARATOR, NO_XR_CAPABILITIES, OVERRIDE_DIFF_EXCLUDED_COMPONENTS, OVERRIDE_ROOT_EXCLUDED_COMPONENTS, ObjectVisibilitySystem, PREFAB_FILE_VERSION, PREFAB_FILE_VERSION_NESTED, PhysicsSyncSystem, PostprocessingSyncSystem, RenderSystem, SCRIPT_OBJECT_ROOT_FLAG, ScriptBehaviourSystem, ScriptObject, ScriptObjectSystem, TransformSyncSystem, VRTeleportAreaSystem, VideoSystem, XRControllerVisualSystem, XRInputSystem, XRInteractionSystem, XRLocomotionSystem, XRSessionSystem, XRTeleportVisualSystem, arcGroundCrossing, buildComponentValueMaps, buildNodeKeyMapsFromSnapshot, buildNodeMapsFromSnapshot, canonicalizeComponentValue, clearPrefabCache, collectDiffPaths, collectEntitySubtree, collectSnapshotSubtreeIds, computeInstanceOverrides, decanonicalizeComponentValue, despawnPrefab, encodeOverride, findSnapshotRootEntityIds, findTopLevelNestedRegions, groupOverridePaths, hydrateWorldFromSnapshot, hydrateWorldFromSnapshotDetailed, indexSnapshotByEntity, instantiateSubtree, loadPrefab, mergeComponentValue, parseOverride, parsePrefabAsset, prefabFileVersionFor, readXrCapabilities, restoreComponentState, restorePostCreateComponents, sampleTeleportArc, setPrefabAssetUrlResolver, spawnPrefab } from './chunk-G53MZVKQ.js';
3
- import { registerDefaultFactories } from './chunk-4BZYK3JP.js';
4
- export { createAnimationComponent, createAudioComponent, createCameraComponent, createEntityTypeComponent, createEnvironmentComponent, createImageComponent, createImageTargetAnchorComponent, createImageTargetComponent, createInstanceSlotComponent, createInstancedMeshComponent, createLightComponent, createMaterialComponent, createMeshComponent, createMeshGeometryComponent, createModelComponent, createNameComponent, createObject3DRefComponent, createParentIdComponent, createPhysicsComponent, createPostprocessingComponent, createScriptComponent, createScriptObjectComponent, createSelectableComponent, createSelectionTransformStateComponent, createSpriteComponent, createTransformComponent, createVRTeleportAreaComponent, createVideoComponent, createXRInteractableComponent, createXRRigComponent, registerDefaultComponentFactories, registerDefaultFactories } from './chunk-4BZYK3JP.js';
5
- import { ObjectManagementSystem } from './chunk-2LVFGVWI.js';
6
- export { ObjectManagementSystem, SHARED_MODEL_RESOURCE_FLAG, clearModelCache, loadSharedGltf, resolveDracoDecoderPath, setDracoDecoderPath } from './chunk-2LVFGVWI.js';
7
- import { SelectionTransformState, Object3DRef, Name, EntityType, ParentId, Environment, Postprocessing, ScriptComponent } from './chunk-6QC2PJLD.js';
8
- export { AnimationStateMachine, AnimationStateManager, components_exports as CoreComponents } from './chunk-6QC2PJLD.js';
1
+ import { MeshGeometrySystem, InstancedMeshSystem, EnvironmentSyncSystem, PostprocessingSyncSystem, LightSyncSystem, MaterialSyncSystem, VRTeleportAreaSystem, PhysicsSyncSystem, AnimationSystem, AudioSystem, VideoSystem, CameraSyncSystem, TransformSyncSystem, ObjectVisibilitySystem, RenderSystem, spawnPrefab, despawnPrefab, buildNodeKeyMapsFromSnapshot, indexSnapshotByEntity, findTopLevelNestedRegions, collectSnapshotSubtreeIds, groupOverridePaths, OVERRIDE_DIFF_EXCLUDED_COMPONENTS, OVERRIDE_ROOT_EXCLUDED_COMPONENTS, canonicalizeComponentValue, mergeComponentValue, decanonicalizeComponentValue, computeInstanceOverrides, collectEntitySubtree, ADDED_NODE_MARKER_COMPONENT } from './chunk-WRJ2K3LZ.js';
2
+ export { ADDED_NODE_MARKER_COMPONENT, ARC_GRAVITY, ARC_MAX_TIME, ARC_SPEED, ARC_STEPS, AnimationSystem, AudioSystem, Behaviour, CameraSyncSystem, EnvironmentSyncSystem, HYDRATABLE_ENTITY_KINDS, InputSystem, InstancedMeshSystem, KeyboardKeys, LightSyncSystem, MaterialSyncSystem, MeshGeometrySystem, NODE_KEY_SEPARATOR, NO_XR_CAPABILITIES, OVERRIDE_DIFF_EXCLUDED_COMPONENTS, OVERRIDE_ROOT_EXCLUDED_COMPONENTS, ObjectVisibilitySystem, PREFAB_FILE_VERSION, PREFAB_FILE_VERSION_NESTED, PhysicsSyncSystem, PostprocessingSyncSystem, RenderSystem, SCRIPT_OBJECT_ROOT_FLAG, ScriptBehaviourSystem, ScriptObject, ScriptObjectSystem, TransformSyncSystem, VRTeleportAreaSystem, VideoSystem, XRControllerVisualSystem, XRInputSystem, XRInteractionSystem, XRLocomotionSystem, XRSessionSystem, XRTeleportVisualSystem, applyHandMaterial, arcGroundCrossing, buildComponentValueMaps, buildNodeKeyMapsFromSnapshot, buildNodeMapsFromSnapshot, canonicalizeComponentValue, clearPrefabCache, collectDiffPaths, collectEntitySubtree, collectSnapshotSubtreeIds, computeInstanceOverrides, createHandMaterial, decanonicalizeComponentValue, despawnPrefab, encodeOverride, findSnapshotRootEntityIds, findTopLevelNestedRegions, groupOverridePaths, hydrateWorldFromSnapshot, hydrateWorldFromSnapshotDetailed, indexSnapshotByEntity, instantiateSubtree, loadPrefab, mergeComponentValue, parseOverride, parsePrefabAsset, prefabFileVersionFor, readXrCapabilities, restoreComponentState, restorePostCreateComponents, sampleTeleportArc, setPrefabAssetUrlResolver, spawnPrefab } from './chunk-WRJ2K3LZ.js';
3
+ import { registerDefaultFactories } from './chunk-FQTOC7HK.js';
4
+ export { createAnimationComponent, createAudioComponent, createCameraComponent, createEntityTypeComponent, createEnvironmentComponent, createImageComponent, createImageTargetAnchorComponent, createImageTargetComponent, createInstanceSlotComponent, createInstancedMeshComponent, createLightComponent, createMaterialComponent, createMeshComponent, createMeshGeometryComponent, createModelComponent, createNameComponent, createObject3DRefComponent, createParentIdComponent, createPhysicsComponent, createPostprocessingComponent, createScriptComponent, createScriptObjectComponent, createSelectableComponent, createSelectionTransformStateComponent, createSpriteComponent, createTransformComponent, createVRTeleportAreaComponent, createVideoComponent, createXRInteractableComponent, createXRInteractorComponent, createXRInteractorSideComponent, createXRRigComponent, registerDefaultComponentFactories, registerDefaultFactories } from './chunk-FQTOC7HK.js';
5
+ import { ObjectManagementSystem } from './chunk-JRJ3CL5H.js';
6
+ export { ObjectManagementSystem, SHARED_MODEL_RESOURCE_FLAG, clearModelCache, loadSharedGltf, resolveDracoDecoderPath, setDracoDecoderPath } from './chunk-JRJ3CL5H.js';
7
+ import { SelectionTransformState, Object3DRef, Name, EntityType, ParentId, Environment, Postprocessing, ScriptComponent } from './chunk-N4GKZ7IV.js';
8
+ export { AnimationStateMachine, AnimationStateManager, components_exports as CoreComponents } from './chunk-N4GKZ7IV.js';
9
9
  import './chunk-QHILSPT4.js';
10
10
  import { normalizeDebugValue, DEBUG_CHANGE_IGNORED_SYSTEMS, cloneHistoryValue } from './chunk-OWQSESTO.js';
11
11
  import { __name } from './chunk-OY7ZODZP.js';
@@ -2109,6 +2109,7 @@ var XRInteractableComponent = _XRInteractableComponent;
2109
2109
  var _XRRigComponent = class _XRRigComponent extends Component {
2110
2110
  constructor(options) {
2111
2111
  super();
2112
+ this.trackingOrigin = options?.trackingOrigin ?? "floor";
2112
2113
  this.locomotion = options?.locomotion ?? "teleport";
2113
2114
  this.moveSpeed = options?.moveSpeed ?? 2;
2114
2115
  this.snapTurn = options?.snapTurn ?? true;
@@ -2119,6 +2120,29 @@ var _XRRigComponent = class _XRRigComponent extends Component {
2119
2120
  __name(_XRRigComponent, "XRRigComponent");
2120
2121
  var XRRigComponent = _XRRigComponent;
2121
2122
 
2123
+ // core/components/XRInteractor.ts
2124
+ var _XRInteractorComponent = class _XRInteractorComponent extends Component {
2125
+ constructor(options) {
2126
+ super();
2127
+ this.interactorType = options?.interactorType ?? "both";
2128
+ this.handPreset = options?.handPreset ?? "default";
2129
+ this.handColor = options?.handColor ?? "#e8b48a";
2130
+ this.handOpacity = options?.handOpacity ?? 1;
2131
+ this.handEmissiveIntensity = options?.handEmissiveIntensity ?? 0;
2132
+ this.showRay = options?.showRay ?? true;
2133
+ }
2134
+ };
2135
+ __name(_XRInteractorComponent, "XRInteractorComponent");
2136
+ var XRInteractorComponent = _XRInteractorComponent;
2137
+ var _XRInteractorSideComponent = class _XRInteractorSideComponent extends Component {
2138
+ constructor(options) {
2139
+ super();
2140
+ this.side = options?.side ?? "left";
2141
+ }
2142
+ };
2143
+ __name(_XRInteractorSideComponent, "XRInteractorSideComponent");
2144
+ var XRInteractorSideComponent = _XRInteractorSideComponent;
2145
+
2122
2146
  // core/utils/dracoDecoderPath.ts
2123
2147
  var LOCAL_DRACO_DECODER_RELATIVE_PATH = "./assets/draco/";
2124
2148
  var DRACO_DECODER_CDN_PATH = "https://www.gstatic.com/draco/versioned/decoders/1.5.7/";
@@ -4913,6 +4937,14 @@ function buildComponentValueMaps(snapshot) {
4913
4937
  snapshot.components,
4914
4938
  "XRInteractableComponent"
4915
4939
  ),
4940
+ xrInteractorValues: readByComponent(
4941
+ snapshot.components,
4942
+ "XRInteractorComponent"
4943
+ ),
4944
+ xrInteractorSideValues: readByComponent(
4945
+ snapshot.components,
4946
+ "XRInteractorSideComponent"
4947
+ ),
4916
4948
  instancedMeshValues: readByComponent(snapshot.components, "InstancedMeshComponent"),
4917
4949
  instanceSlotValues: readByComponent(snapshot.components, "InstanceSlotComponent"),
4918
4950
  prefabNodeValues: readByComponent(snapshot.components, "PrefabNode"),
@@ -5099,6 +5131,60 @@ function restorePostCreateComponents(world, objectManagementSystem, targetEntity
5099
5131
  }
5100
5132
  }
5101
5133
  }
5134
+ {
5135
+ const sourceInteractor = asRecord3(
5136
+ values.xrInteractorValues.get(sourceEntityId)
5137
+ );
5138
+ const interactor = world.getComponent(targetEntityId, XRInteractorComponent);
5139
+ if (sourceInteractor && interactor) {
5140
+ if (typeof sourceInteractor.interactorType === "string") {
5141
+ interactor.interactorType = sourceInteractor.interactorType;
5142
+ }
5143
+ if (typeof sourceInteractor.handPreset === "string") {
5144
+ interactor.handPreset = sourceInteractor.handPreset;
5145
+ }
5146
+ if (typeof sourceInteractor.handColor === "string") {
5147
+ interactor.handColor = sourceInteractor.handColor;
5148
+ }
5149
+ if (typeof sourceInteractor.handOpacity === "number") {
5150
+ interactor.handOpacity = sourceInteractor.handOpacity;
5151
+ }
5152
+ if (typeof sourceInteractor.handEmissiveIntensity === "number") {
5153
+ interactor.handEmissiveIntensity = sourceInteractor.handEmissiveIntensity;
5154
+ }
5155
+ if (typeof sourceInteractor.showRay === "boolean") {
5156
+ interactor.showRay = sourceInteractor.showRay;
5157
+ }
5158
+ }
5159
+ }
5160
+ {
5161
+ const sourceSide = asRecord3(
5162
+ values.xrInteractorSideValues.get(sourceEntityId)
5163
+ );
5164
+ if (sourceSide && typeof sourceSide.side === "string") {
5165
+ const existing = world.getComponent(
5166
+ targetEntityId,
5167
+ XRInteractorSideComponent
5168
+ );
5169
+ if (existing) {
5170
+ existing.side = sourceSide.side;
5171
+ } else {
5172
+ world.addComponent(
5173
+ targetEntityId,
5174
+ new XRInteractorSideComponent({
5175
+ side: sourceSide.side
5176
+ })
5177
+ );
5178
+ }
5179
+ }
5180
+ }
5181
+ {
5182
+ const sourceRigOrigin = asRecord3(values.xrRigValues.get(sourceEntityId));
5183
+ const rigForOrigin = world.getComponent(targetEntityId, XRRigComponent);
5184
+ if (sourceRigOrigin && rigForOrigin && typeof sourceRigOrigin.trackingOrigin === "string") {
5185
+ rigForOrigin.trackingOrigin = sourceRigOrigin.trackingOrigin;
5186
+ }
5187
+ }
5102
5188
  {
5103
5189
  const imComponent = world.getComponent(targetEntityId, InstancedMeshComponent);
5104
5190
  if (imComponent && imComponent.instanceEntityIds.length > 0) {
@@ -5688,6 +5774,7 @@ var HYDRATABLE_ENTITY_KINDS = /* @__PURE__ */ new Set([
5688
5774
  "instanceSlot",
5689
5775
  "scriptObject",
5690
5776
  "xrRig",
5777
+ "xrInteractor",
5691
5778
  "teleportArea"
5692
5779
  ]);
5693
5780
 
@@ -7698,6 +7785,9 @@ var _XRInputSystem = class _XRInputSystem {
7698
7785
  state.hasAxes = false;
7699
7786
  state.buttons = [];
7700
7787
  }
7788
+ }
7789
+ for (const record of this.records.values()) {
7790
+ const state = record.state;
7701
7791
  if (record.pendingSelectStart) {
7702
7792
  state.select = true;
7703
7793
  state.selectStart = true;
@@ -8126,6 +8216,8 @@ var _XRSessionSystem = class _XRSessionSystem {
8126
8216
  constructor(inputSystem) {
8127
8217
  this.presenting = false;
8128
8218
  this.capabilities = NO_XR_CAPABILITIES;
8219
+ /** Y compensation applied when a floor-relative space was requested but not granted. */
8220
+ this.appliedOriginOffset = 0;
8129
8221
  this.inputSystem = inputSystem ?? null;
8130
8222
  }
8131
8223
  update(world) {
@@ -8149,11 +8241,59 @@ var _XRSessionSystem = class _XRSessionSystem {
8149
8241
  if (session && this.inputSystem) {
8150
8242
  this.inputSystem.attachSession(session);
8151
8243
  }
8244
+ this.applyTrackingOrigin(world, session ?? null);
8152
8245
  this.forEachBehaviour(world, (behaviour) => {
8153
8246
  behaviour.onXRSessionStart(this.capabilities);
8154
8247
  });
8155
8248
  }
8249
+ /**
8250
+ * Apply the rig's authored tracking origin, and compensate when the device
8251
+ * cannot honour it.
8252
+ *
8253
+ * `floor` (`local-floor`) puts Y=0 on the user's real floor, which is what a
8254
+ * scene authored standing on the ground expects. `eye` (`local`) puts Y=0 at
8255
+ * the headset, for seated experiences.
8256
+ *
8257
+ * The compensation matters: `local-floor` is only ever REQUESTED as an
8258
+ * optional feature (requiring it would make `requestSession` reject outright
8259
+ * on devices that lack it). When it isn't granted, the runtime silently falls
8260
+ * back to `local` — the origin jumps to head height and a floor-authored
8261
+ * scene swallows the user, which is exactly the "I'm standing under the
8262
+ * building" symptom. Offsetting the rig down by the eye height restores the
8263
+ * intended floor relationship instead of leaving it broken.
8264
+ */
8265
+ applyTrackingOrigin(world, session) {
8266
+ const rigEntityId = world.query(XRRigComponent, TransformComponent)[0];
8267
+ if (typeof rigEntityId !== "number") return;
8268
+ const rig = world.getComponent(rigEntityId, XRRigComponent);
8269
+ const transform = world.getComponent(rigEntityId, TransformComponent);
8270
+ if (!rig || !transform) return;
8271
+ const renderer = world.getRenderer();
8272
+ const wantsFloor = rig.trackingOrigin === "floor";
8273
+ try {
8274
+ renderer.xr.setReferenceSpaceType(wantsFloor ? "local-floor" : "local");
8275
+ } catch {
8276
+ }
8277
+ const granted = session?.enabledFeatures;
8278
+ const floorGranted = Array.isArray(granted) ? granted.includes("local-floor") : (
8279
+ // No report at all: trust the request, since a wrong offset is worse
8280
+ // than none on devices that did honour it.
8281
+ true
8282
+ );
8283
+ this.appliedOriginOffset = wantsFloor && !floorGranted ? rig.fallbackEyeHeight : 0;
8284
+ if (this.appliedOriginOffset !== 0) {
8285
+ transform.position.y -= this.appliedOriginOffset;
8286
+ }
8287
+ }
8156
8288
  handleSessionEnd(world) {
8289
+ if (this.appliedOriginOffset !== 0) {
8290
+ const rigEntityId = world.query(XRRigComponent, TransformComponent)[0];
8291
+ if (typeof rigEntityId === "number") {
8292
+ const transform = world.getComponent(rigEntityId, TransformComponent);
8293
+ if (transform) transform.position.y += this.appliedOriginOffset;
8294
+ }
8295
+ this.appliedOriginOffset = 0;
8296
+ }
8157
8297
  this.capabilities = NO_XR_CAPABILITIES;
8158
8298
  this.inputSystem?.detachSession();
8159
8299
  this.forEachBehaviour(world, (behaviour) => {
@@ -8247,17 +8387,74 @@ var _VRTeleportAreaSystem = class _VRTeleportAreaSystem {
8247
8387
  };
8248
8388
  __name(_VRTeleportAreaSystem, "VRTeleportAreaSystem");
8249
8389
  var VRTeleportAreaSystem = _VRTeleportAreaSystem;
8390
+ function createHandMaterial(preset, options) {
8391
+ const color = new THREE14__namespace.Color(options.color);
8392
+ switch (preset) {
8393
+ case "ghost":
8394
+ return new THREE14__namespace.MeshBasicMaterial({
8395
+ color,
8396
+ transparent: true,
8397
+ opacity: Math.min(1, Math.max(0.05, options.opacity * 0.45)),
8398
+ depthWrite: false,
8399
+ side: THREE14__namespace.DoubleSide
8400
+ });
8401
+ case "neon":
8402
+ return new THREE14__namespace.MeshStandardMaterial({
8403
+ color,
8404
+ emissive: color,
8405
+ emissiveIntensity: Math.max(0.5, options.emissiveIntensity || 2),
8406
+ roughness: 0.35,
8407
+ metalness: 0,
8408
+ transparent: options.opacity < 1,
8409
+ opacity: options.opacity
8410
+ });
8411
+ case "skeleton":
8412
+ return new THREE14__namespace.MeshBasicMaterial({
8413
+ color,
8414
+ wireframe: true,
8415
+ transparent: true,
8416
+ opacity: options.opacity
8417
+ });
8418
+ case "custom":
8419
+ case "default":
8420
+ return new THREE14__namespace.MeshStandardMaterial({
8421
+ color,
8422
+ roughness: 0.85,
8423
+ metalness: 0,
8424
+ emissive: color,
8425
+ emissiveIntensity: Math.max(0, options.emissiveIntensity),
8426
+ transparent: options.opacity < 1,
8427
+ opacity: options.opacity,
8428
+ side: THREE14__namespace.DoubleSide
8429
+ });
8430
+ default: {
8431
+ return new THREE14__namespace.MeshStandardMaterial({ color });
8432
+ }
8433
+ }
8434
+ }
8435
+ __name(createHandMaterial, "createHandMaterial");
8436
+ function applyHandMaterial(root, material) {
8437
+ root.traverse((child) => {
8438
+ const mesh = child;
8439
+ if (!mesh.isMesh) return;
8440
+ mesh.material = material;
8441
+ });
8442
+ }
8443
+ __name(applyHandMaterial, "applyHandMaterial");
8444
+ var SLOTS = [
8445
+ { index: 0, side: "left" },
8446
+ { index: 1, side: "right" }
8447
+ ];
8250
8448
  var _XRControllerVisualSystem = class _XRControllerVisualSystem {
8251
8449
  constructor(options) {
8252
8450
  this.controllerModelFactory = new XRControllerModelFactory_js.XRControllerModelFactory();
8253
8451
  this.handModelFactory = new XRHandModelFactory_js.XRHandModelFactory();
8254
8452
  this.group = new THREE14__namespace.Group();
8255
- this.built = false;
8453
+ this.slots = /* @__PURE__ */ new Map();
8256
8454
  this.attachedTo = null;
8257
- /** Index → whether we've already attached visuals for that slot. */
8258
- this.ready = /* @__PURE__ */ new Set();
8259
- this.rays = [];
8260
- this.slots = options?.slots ?? 2;
8455
+ /** Last applied preset signature, so materials rebuild only on real change. */
8456
+ this.handStyleSignature = "";
8457
+ this.handMaterial = null;
8261
8458
  this.interactionSystem = options?.interactionSystem ?? null;
8262
8459
  this.group.name = "XRControllerVisuals";
8263
8460
  this.group.userData.ecsPreviewHidden = true;
@@ -8266,39 +8463,111 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
8266
8463
  const renderer = world.getRenderer();
8267
8464
  if (!renderer.xr?.enabled) return;
8268
8465
  this.ensureAttached(world);
8269
- this.updateRayVisibility();
8270
- if (this.built) return;
8271
- for (let index = 0; index < this.slots; index += 1) {
8272
- if (this.ready.has(index)) continue;
8466
+ this.ensureSlots(world);
8467
+ const interactor = this.resolveInteractor(world);
8468
+ const type = interactor?.interactorType ?? "both";
8469
+ const showControllers = type === "controllers" || type === "both";
8470
+ const showHands = type === "hands" || type === "both";
8471
+ this.syncHandMaterial(interactor);
8472
+ for (const { index, side } of SLOTS) {
8473
+ const visuals = this.slots.get(index);
8474
+ if (!visuals) continue;
8475
+ visuals.controllerModel.visible = showControllers;
8476
+ visuals.handModel.visible = showHands;
8477
+ visuals.ray.visible = this.shouldShowRay(interactor);
8478
+ if (showHands && this.handMaterial) {
8479
+ applyHandMaterial(visuals.handModel, this.handMaterial);
8480
+ }
8481
+ this.syncCustomContent(world, visuals, side);
8482
+ }
8483
+ }
8484
+ /** The scene's interactor config, if one was authored. */
8485
+ resolveInteractor(world) {
8486
+ const entityId = world.query(XRInteractorComponent)[0];
8487
+ if (typeof entityId !== "number") return null;
8488
+ return world.getComponent(entityId, XRInteractorComponent) ?? null;
8489
+ }
8490
+ /**
8491
+ * Re-parent the author's left/right interactor content onto the tracked grip
8492
+ * space so it follows the hand.
8493
+ *
8494
+ * `ObjectManagementSystem` reconciles ECS objects back under their ParentId
8495
+ * every frame, so this re-attach has to be re-asserted — the same coexistence
8496
+ * dance the AR anchor system performs.
8497
+ */
8498
+ syncCustomContent(world, visuals, side) {
8499
+ let content = null;
8500
+ for (const entityId of world.query(
8501
+ XRInteractorSideComponent,
8502
+ Object3DRef
8503
+ )) {
8504
+ const slot = world.getComponent(entityId, XRInteractorSideComponent);
8505
+ if (slot?.side !== side) continue;
8506
+ content = world.getComponent(entityId, Object3DRef)?.object ?? null;
8507
+ break;
8508
+ }
8509
+ if (!content) {
8510
+ visuals.attachedCustom = null;
8511
+ return;
8512
+ }
8513
+ if (content.parent !== visuals.grip) {
8514
+ visuals.grip.add(content);
8515
+ }
8516
+ visuals.attachedCustom = content;
8517
+ }
8518
+ /** Rebuild the hand material only when the authored style actually changes. */
8519
+ syncHandMaterial(interactor) {
8520
+ const preset = interactor?.handPreset ?? "default";
8521
+ const color = interactor?.handColor ?? "#e8b48a";
8522
+ const opacity = interactor?.handOpacity ?? 1;
8523
+ const emissive = interactor?.handEmissiveIntensity ?? 0;
8524
+ const signature = `${preset}:${color}:${opacity}:${emissive}`;
8525
+ if (signature === this.handStyleSignature && this.handMaterial) return;
8526
+ this.handStyleSignature = signature;
8527
+ this.handMaterial?.dispose();
8528
+ this.handMaterial = createHandMaterial(preset, {
8529
+ color,
8530
+ opacity,
8531
+ emissiveIntensity: emissive
8532
+ });
8533
+ }
8534
+ /**
8535
+ * The ray is meaningful only when it points at something. Authors can turn it
8536
+ * off entirely; otherwise it appears on hover/grab so it isn't permanent
8537
+ * clutter implying the whole scene is clickable.
8538
+ */
8539
+ shouldShowRay(interactor) {
8540
+ if (interactor && !interactor.showRay) return false;
8541
+ if (!this.interactionSystem) return true;
8542
+ return this.interactionSystem.getHoveredEntityId() !== null || this.interactionSystem.isGrabbing();
8543
+ }
8544
+ /** Lazily build per-slot visuals; the device reports profiles late. */
8545
+ ensureSlots(world) {
8546
+ const renderer = world.getRenderer();
8547
+ for (const { index } of SLOTS) {
8548
+ if (this.slots.has(index)) continue;
8273
8549
  const controller = renderer.xr.getController(index);
8274
8550
  const grip = renderer.xr.getControllerGrip(index);
8275
8551
  const hand = renderer.xr.getHand(index);
8276
8552
  if (!controller || !grip || !hand) continue;
8277
8553
  const ray = this.createRay();
8278
- this.rays.push(ray);
8279
8554
  controller.add(ray);
8280
- this.group.add(controller);
8281
- grip.add(this.controllerModelFactory.createControllerModel(grip));
8282
- this.group.add(grip);
8283
- hand.add(this.handModelFactory.createHandModel(hand, "mesh"));
8284
- this.group.add(hand);
8285
- this.ready.add(index);
8286
- }
8287
- if (this.ready.size >= this.slots) {
8288
- this.built = true;
8555
+ const controllerModel = this.controllerModelFactory.createControllerModel(grip);
8556
+ grip.add(controllerModel);
8557
+ const handModel = this.handModelFactory.createHandModel(hand, "mesh");
8558
+ hand.add(handModel);
8559
+ this.group.add(controller, grip, hand);
8560
+ this.slots.set(index, {
8561
+ controller,
8562
+ grip,
8563
+ hand,
8564
+ ray,
8565
+ controllerModel,
8566
+ handModel,
8567
+ attachedCustom: null
8568
+ });
8289
8569
  }
8290
8570
  }
8291
- /**
8292
- * Show the aim ray only when it is meaningful: hovering something
8293
- * interactive, or mid-grab. A permanently-drawn ray is visual noise, and it
8294
- * implies everything is clickable when most of the scene is not. Teleport
8295
- * aiming has its own arc, so the straight ray stays hidden for that.
8296
- */
8297
- updateRayVisibility() {
8298
- if (!this.interactionSystem) return;
8299
- const active = this.interactionSystem.getHoveredEntityId() !== null || this.interactionSystem.isGrabbing();
8300
- for (const ray of this.rays) ray.visible = active;
8301
- }
8302
8571
  /**
8303
8572
  * Parent the visuals to the XR rig when there is one, so locomotion moves the
8304
8573
  * hands with the player. Falls back to the scene root.
@@ -8324,7 +8593,7 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
8324
8593
  const line = new THREE14__namespace.Line(geometry, material);
8325
8594
  line.name = "XRPointerRay";
8326
8595
  line.renderOrder = 999;
8327
- line.visible = this.interactionSystem === null;
8596
+ line.visible = false;
8328
8597
  return line;
8329
8598
  }
8330
8599
  dispose() {
@@ -8340,9 +8609,10 @@ var _XRControllerVisualSystem = class _XRControllerVisualSystem {
8340
8609
  }
8341
8610
  });
8342
8611
  this.group.clear();
8343
- this.rays.length = 0;
8344
- this.ready.clear();
8345
- this.built = false;
8612
+ this.slots.clear();
8613
+ this.handMaterial?.dispose();
8614
+ this.handMaterial = null;
8615
+ this.handStyleSignature = "";
8346
8616
  this.attachedTo = null;
8347
8617
  }
8348
8618
  };