@iwsdk/core 1.0.0-rc.1 → 1.0.0-rc.2

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 (50) hide show
  1. package/dist/gaze/gaze-system.d.ts +207 -0
  2. package/dist/gaze/gaze-system.d.ts.map +1 -0
  3. package/dist/gaze/gaze-system.js +168 -0
  4. package/dist/gaze/gaze-system.js.map +1 -0
  5. package/dist/gaze/index.d.ts +8 -0
  6. package/dist/gaze/index.d.ts.map +1 -0
  7. package/dist/grab/grab-helpers.d.ts +7 -6
  8. package/dist/grab/grab-helpers.d.ts.map +1 -1
  9. package/dist/grab/grab-helpers.js +12 -7
  10. package/dist/grab/grab-helpers.js.map +1 -1
  11. package/dist/grab/grab-system.d.ts.map +1 -1
  12. package/dist/grab/grab-system.js +2 -1
  13. package/dist/grab/grab-system.js.map +1 -1
  14. package/dist/grab/handles.d.ts +10 -1
  15. package/dist/grab/handles.d.ts.map +1 -1
  16. package/dist/grab/handles.js +29 -6
  17. package/dist/grab/handles.js.map +1 -1
  18. package/dist/index.d.ts +1 -0
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +1 -0
  21. package/dist/index.js.map +1 -1
  22. package/dist/init/world-initializer.d.ts +49 -0
  23. package/dist/init/world-initializer.d.ts.map +1 -1
  24. package/dist/init/world-initializer.js +21 -8
  25. package/dist/init/world-initializer.js.map +1 -1
  26. package/dist/init/xr.d.ts +14 -0
  27. package/dist/init/xr.d.ts.map +1 -1
  28. package/dist/init/xr.js +19 -0
  29. package/dist/init/xr.js.map +1 -1
  30. package/dist/input/input-system.d.ts +3 -0
  31. package/dist/input/input-system.d.ts.map +1 -1
  32. package/dist/input/input-system.js +72 -6
  33. package/dist/input/input-system.js.map +1 -1
  34. package/dist/input/state-tags.d.ts.map +1 -1
  35. package/dist/input/state-tags.js +2 -0
  36. package/dist/input/state-tags.js.map +1 -1
  37. package/dist/project/normalize.d.ts.map +1 -1
  38. package/dist/project/normalize.js +11 -0
  39. package/dist/project/normalize.js.map +1 -1
  40. package/dist/project/types.d.ts +32 -2
  41. package/dist/project/types.d.ts.map +1 -1
  42. package/dist/project/types.js.map +1 -1
  43. package/dist/project/validation.d.ts.map +1 -1
  44. package/dist/project/validation.js +65 -1
  45. package/dist/project/validation.js.map +1 -1
  46. package/dist/schemas/iwsdk-project.v1.schema.json +45 -3
  47. package/dist/version.d.ts +1 -1
  48. package/dist/version.js +1 -1
  49. package/dist/version.js.map +1 -1
  50. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"grab-system.js","sources":["../../src/grab/grab-system.ts"],"sourcesContent":["/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { HandleStore } from '@pmndrs/handle';\nimport { PointerEventsMap } from '@pmndrs/pointer-events';\nimport { Types } from '../ecs/component.js';\nimport { Entity } from '../ecs/entity.js';\nimport { createSystem } from '../ecs/system.js';\nimport { LevelTag } from '../level/index.js';\nimport {\n Object3D,\n Object3DEventMap,\n Vector3,\n Quaternion,\n} from '../runtime/index.js';\nimport { DistanceGrabbable } from './distance-grabbable.js';\nimport { cancelGrabHandle, findHolderHand } from './grab-helpers.js';\nimport { warnIfNoRaycastableMesh } from './grab-warnings.js';\nimport { Grabbed } from './grabbed.js';\nimport { DistanceGrabHandle, MovementMode, Handle } from './handles.js';\nimport { OneHandGrabbable } from './one-hand-grabbable.js';\nimport { TwoHandsGrabbable } from './two-hands-grabbable.js';\n\n/**\n * Manages interactive object grabbing and manipulation for VR/AR experiences.\n *\n * @remarks\n * - Uses the `@pmndrs/handle` library for precise multitouch manipulation.\n * - Automatically creates handle instances for entities with grabbable components.\n * - Supports three types of grab interactions: one‑hand, two‑hand, and distance grabbing.\n * - Automatically cleans up handle instances when grabbable components are removed.\n *\n * @example Basic grab system setup\n * ```ts\n * // Add to your world to enable grab interactions\n * world.addSystem(GrabSystem)\n *\n * // Create a grabbable box\n * const box = world.createEntity()\n * box.addComponent(OneHandGrabbable, {})\n * ```\n *\n * @example Two‑handed manipulation\n * ```ts\n * // Create an object that can be scaled with two hands\n * const sculpture = world.createEntity()\n * sculpture.addComponent(TwoHandsGrabbable, {\n * scaleMin: [0.5, 0.5, 0.5],\n * scaleMax: [3, 3, 3]\n * })\n * ```\n *\n * @category Grab\n * @see {@link OneHandGrabbable}\n * @see {@link TwoHandsGrabbable}\n * @see {@link DistanceGrabbable}\n */\nexport class GrabSystem extends createSystem(\n {\n oneHandGrabbables: {\n required: [OneHandGrabbable],\n },\n twoHandsGrabbables: {\n required: [TwoHandsGrabbable],\n },\n distanceGrabbables: {\n required: [DistanceGrabbable],\n },\n handles: {\n required: [Handle],\n },\n },\n {\n /**\n * Controls whether hand pinch gestures are forwarded as squeeze events for grab interactions.\n * Set to `false` to disable pinch-to-grab and require the physical squeeze button instead.\n * @default false\n */\n useHandPinchForGrab: { type: Types.Boolean, default: false },\n },\n) {\n init() {\n // Ensure Handle component is registered in the world before queries rely on it\n if (!Handle.bitmask) {\n this.world.registerComponent(Handle);\n }\n if (!Grabbed.bitmask) {\n this.world.registerComponent(Grabbed);\n }\n\n // Reactive handle creation per grabbable type\n this.queries.oneHandGrabbables.subscribe('qualify', (entity) => {\n this.initializeOneHandHandle(entity);\n });\n this.queries.twoHandsGrabbables.subscribe('qualify', (entity) => {\n this.initializeTwoHandsHandle(entity);\n });\n this.queries.distanceGrabbables.subscribe('qualify', (entity) => {\n this.initializeDistanceHandle(entity);\n });\n\n // Unified cleanup for any handle\n this.queries.handles.subscribe('disqualify', (entity) => {\n const h = Handle.data.instance[entity.index] as\n | HandleStore<unknown>\n | undefined;\n if (h) {\n try {\n h.cancel();\n } catch {}\n }\n if (entity.object3D) {\n entity.object3D.pointerEventsType = 'all';\n }\n });\n\n // Initial pass for already-eligible entities (qualify doesn't fire retroactively)\n this.queries.oneHandGrabbables.entities.forEach((e) =>\n this.initializeOneHandHandle(e),\n );\n this.queries.twoHandsGrabbables.entities.forEach((e) =>\n this.initializeTwoHandsHandle(e),\n );\n this.queries.distanceGrabbables.entities.forEach((e) =>\n this.initializeDistanceHandle(e),\n );\n\n // Enable grab sub-pointer per hand when GrabSystem is active\n this.input.xr.multiPointers.left.toggleSubPointer('grab', true);\n this.input.xr.multiPointers.right.toggleSubPointer('grab', true);\n }\n\n update(delta: number, time: number): void {\n // Forward hand pinch events to squeeze for grab interactions\n // Only forward if the system-level useHandPinchForGrab flag is enabled\n if (this.config.useHandPinchForGrab) {\n (['left', 'right'] as const).forEach((handedness) => {\n if (this.input.xr.isPrimary('hand', handedness)) {\n const timeStamp = time * 1000;\n if (this.input.xr.gamepads[handedness]?.getSelectStart()) {\n this.input.xr.multiPointers[handedness].routeDown(\n 'squeeze',\n 'grab',\n {\n timeStamp,\n },\n );\n }\n if (this.input.xr.gamepads[handedness]?.getSelectEnd()) {\n this.input.xr.multiPointers[handedness].routeUp('squeeze', 'grab', {\n timeStamp,\n });\n }\n }\n });\n }\n\n // Unified handle updates\n this.queries.handles.entities.forEach((entity) => {\n const h = Handle.data.instance[entity.index] as\n | HandleStore<unknown>\n | undefined;\n if (h) {\n h.update(delta);\n // Manage Grabbed tag based on active grab state\n if (h.inputState.size > 0) {\n if (!entity.hasComponent(Grabbed)) {\n entity.addComponent(Grabbed);\n }\n } else if (entity.hasComponent(Grabbed)) {\n entity.removeComponent(Grabbed);\n }\n }\n });\n }\n\n /**\n * Force-release `entity` if it is currently being held.\n *\n * @remarks\n * Cancels every active pointer on the entity's grab handle, which causes\n * `update()` on the next frame to remove the {@link Grabbed} tag. Safe to\n * call when the entity is not held or has never been grabbable — a no-op\n * in those cases.\n *\n * Useful for game-state changes that need to drop held items: level resets,\n * weapon swaps, death/respawn, cinematics, etc.\n *\n * @example\n * ```ts\n * const grab = world.getSystem(GrabSystem);\n * grab.forceRelease(weaponEntity);\n * ```\n */\n forceRelease(entity: Entity): void {\n cancelGrabHandle(\n Handle.data.instance[entity.index] as HandleStore<unknown> | undefined,\n );\n }\n\n /**\n * Identify which controller is currently holding `entity`.\n *\n * @returns `'left'` or `'right'` when a single hand holds the entity,\n * `null` when the entity is not held (or has no grab handle).\n *\n * @remarks\n * For two-handed grabs (both controllers active on the same entity), the\n * left hand is reported. Callers needing per-hand state for two-handed\n * interactions should track grab/release events themselves rather than\n * polling this method.\n *\n * Useful for hand-aware behaviors: recoil/animation that should react to\n * the holding controller, hand-specific UI prompts, etc.\n *\n * @example\n * ```ts\n * const grab = world.getSystem(GrabSystem);\n * const hand = grab.getHolderHand(gunEntity);\n * if (hand) {\n * playRecoilOn(hand);\n * }\n * ```\n */\n getHolderHand(entity: Entity): 'left' | 'right' | null {\n const left = this.input.xr.multiPointers.left;\n const right = this.input.xr.multiPointers.right;\n return findHolderHand(\n Handle.data.instance[entity.index] as HandleStore<unknown> | undefined,\n // Near grabs capture via the `grab` sub-pointer; distance grabs capture\n // via `ray` (see `initializeDistanceHandle` setting\n // `pointerEventsType = { deny: 'grab' }`). Check both per hand so\n // distance-held entities don't silently report `null`.\n [left.getPointer('grab').id, left.getPointer('ray').id],\n [right.getPointer('grab').id, right.getPointer('ray').id],\n );\n }\n\n private initializeOneHandHandle(entity: Entity) {\n if (entity.hasComponent(Handle)) {\n return;\n }\n const object = entity.object3D;\n if (!(object instanceof Object3D)) {\n return;\n }\n warnIfNoRaycastableMesh(entity, 'OneHandGrabbable');\n const obj = object as Object3D<PointerEventsMap & Object3DEventMap>;\n const rotateMax = entity.getVectorView(OneHandGrabbable, 'rotateMax');\n const rotateMin = entity.getVectorView(OneHandGrabbable, 'rotateMin');\n const translateMax = entity.getVectorView(OneHandGrabbable, 'translateMax');\n const translateMin = entity.getVectorView(OneHandGrabbable, 'translateMin');\n const handle = new HandleStore(obj, () => ({\n rotate: entity.getValue(OneHandGrabbable, 'rotate')\n ? {\n x: [rotateMin[0], rotateMax[0]] as [number, number],\n y: [rotateMin[1], rotateMax[1]] as [number, number],\n z: [rotateMin[2], rotateMax[2]] as [number, number],\n }\n : false,\n translate: entity.getValue(OneHandGrabbable, 'translate')\n ? {\n x: [translateMin[0], translateMax[0]] as [number, number],\n y: [translateMin[1], translateMax[1]] as [number, number],\n z: [translateMin[2], translateMax[2]] as [number, number],\n }\n : false,\n projectRays: false,\n multitouch: false,\n }));\n handle.bind(obj);\n obj.pointerEventsType = { deny: 'ray' };\n entity.addComponent(Handle, { instance: handle });\n }\n\n private initializeTwoHandsHandle(entity: Entity) {\n if (entity.hasComponent(Handle)) {\n return;\n }\n const object = entity.object3D;\n if (!(object instanceof Object3D)) {\n return;\n }\n warnIfNoRaycastableMesh(entity, 'TwoHandsGrabbable');\n const obj = object as Object3D<PointerEventsMap & Object3DEventMap>;\n const rotateMax = entity.getVectorView(TwoHandsGrabbable, 'rotateMax');\n const rotateMin = entity.getVectorView(TwoHandsGrabbable, 'rotateMin');\n const translateMax = entity.getVectorView(\n TwoHandsGrabbable,\n 'translateMax',\n );\n const translateMin = entity.getVectorView(\n TwoHandsGrabbable,\n 'translateMin',\n );\n const scaleMax = entity.getVectorView(TwoHandsGrabbable, 'scaleMax');\n const scaleMin = entity.getVectorView(TwoHandsGrabbable, 'scaleMin');\n const handle = new HandleStore(obj, () => ({\n rotate: entity.getValue(TwoHandsGrabbable, 'rotate')\n ? {\n x: [rotateMin[0], rotateMax[0]] as [number, number],\n y: [rotateMin[1], rotateMax[1]] as [number, number],\n z: [rotateMin[2], rotateMax[2]] as [number, number],\n }\n : false,\n translate: entity.getValue(TwoHandsGrabbable, 'translate')\n ? {\n x: [translateMin[0], translateMax[0]] as [number, number],\n y: [translateMin[1], translateMax[1]] as [number, number],\n z: [translateMin[2], translateMax[2]] as [number, number],\n }\n : false,\n scale: entity.getValue(TwoHandsGrabbable, 'scale')\n ? {\n x: [scaleMin[0], scaleMax[0]] as [number, number],\n y: [scaleMin[1], scaleMax[1]] as [number, number],\n z: [scaleMin[2], scaleMax[2]] as [number, number],\n }\n : false,\n projectRays: false,\n multitouch: true,\n }));\n handle.bind(obj);\n obj.pointerEventsType = { deny: 'ray' };\n entity.addComponent(Handle, { instance: handle });\n }\n\n private initializeDistanceHandle(entity: Entity) {\n if (entity.hasComponent(Handle)) {\n return;\n }\n const object = entity.object3D;\n if (!(object instanceof Object3D)) {\n return;\n }\n warnIfNoRaycastableMesh(entity, 'DistanceGrabbable');\n const obj = object as Object3D<PointerEventsMap & Object3DEventMap>;\n const rootEntity = entity.hasComponent(LevelTag)\n ? this.world.activeLevel.value\n : this.world.sceneEntity;\n const rotateMax = entity.getVectorView(DistanceGrabbable, 'rotateMax');\n const rotateMin = entity.getVectorView(DistanceGrabbable, 'rotateMin');\n const translateMax = entity.getVectorView(\n DistanceGrabbable,\n 'translateMax',\n );\n const translateMin = entity.getVectorView(\n DistanceGrabbable,\n 'translateMin',\n );\n const scaleMax = entity.getVectorView(DistanceGrabbable, 'scaleMax');\n const scaleMin = entity.getVectorView(DistanceGrabbable, 'scaleMin');\n const movementMode = entity.getValue(DistanceGrabbable, 'movementMode');\n const returnToOrigin = Boolean(\n entity.getValue(DistanceGrabbable, 'returnToOrigin'),\n );\n const detachOnGrab = Boolean(\n entity.getValue(DistanceGrabbable, 'detachOnGrab'),\n );\n const targetPosOffset = entity.getVectorView(\n DistanceGrabbable,\n 'targetPositionOffset',\n );\n const targetQuatOffset = entity.getVectorView(\n DistanceGrabbable,\n 'targetQuaternionOffset',\n );\n const opts = () => ({\n rotate: entity.getValue(DistanceGrabbable, 'rotate')\n ? {\n x: [rotateMin[0], rotateMax[0]] as [number, number],\n y: [rotateMin[1], rotateMax[1]] as [number, number],\n z: [rotateMin[2], rotateMax[2]] as [number, number],\n }\n : false,\n translate:\n movementMode === MovementMode.RotateAtSource\n ? ('as-rotate' as const)\n : entity.getValue(DistanceGrabbable, 'translate')\n ? {\n x: [translateMin[0], translateMax[0]] as [number, number],\n y: [translateMin[1], translateMax[1]] as [number, number],\n z: [translateMin[2], translateMax[2]] as [number, number],\n }\n : false,\n scale:\n movementMode === MovementMode.RotateAtSource\n ? false\n : entity.getValue(DistanceGrabbable, 'scale')\n ? {\n x: [scaleMin[0], scaleMax[0]] as [number, number],\n y: [scaleMin[1], scaleMax[1]] as [number, number],\n z: [scaleMin[2], scaleMax[2]] as [number, number],\n }\n : false,\n projectRays: false,\n });\n const handle = new DistanceGrabHandle(\n obj,\n rootEntity.object3D!,\n opts,\n movementMode!,\n returnToOrigin,\n entity.getValue(DistanceGrabbable, 'moveSpeedFactor') ?? 0.1,\n new Vector3(targetPosOffset[0], targetPosOffset[1], targetPosOffset[2]),\n new Quaternion(\n targetQuatOffset[0],\n targetQuatOffset[1],\n targetQuatOffset[2],\n targetQuatOffset[3],\n ),\n detachOnGrab,\n );\n handle.bind(obj);\n obj.pointerEventsType = { deny: 'grab' };\n entity.addComponent(Handle, { instance: handle });\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"grab-system.js","sources":["../../src/grab/grab-system.ts"],"sourcesContent":["/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { HandleStore } from '@pmndrs/handle';\nimport { PointerEventsMap } from '@pmndrs/pointer-events';\nimport { Types } from '../ecs/component.js';\nimport { Entity } from '../ecs/entity.js';\nimport { createSystem } from '../ecs/system.js';\nimport { LevelTag } from '../level/index.js';\nimport {\n Object3D,\n Object3DEventMap,\n Vector3,\n Quaternion,\n} from '../runtime/index.js';\nimport { DistanceGrabbable } from './distance-grabbable.js';\nimport { cancelGrabHandle, findHolderHand } from './grab-helpers.js';\nimport { warnIfNoRaycastableMesh } from './grab-warnings.js';\nimport { Grabbed } from './grabbed.js';\nimport { DistanceGrabHandle, MovementMode, Handle } from './handles.js';\nimport { OneHandGrabbable } from './one-hand-grabbable.js';\nimport { TwoHandsGrabbable } from './two-hands-grabbable.js';\n\n/**\n * Manages interactive object grabbing and manipulation for VR/AR experiences.\n *\n * @remarks\n * - Uses the `@pmndrs/handle` library for precise multitouch manipulation.\n * - Automatically creates handle instances for entities with grabbable components.\n * - Supports three types of grab interactions: one‑hand, two‑hand, and distance grabbing.\n * - Automatically cleans up handle instances when grabbable components are removed.\n *\n * @example Basic grab system setup\n * ```ts\n * // Add to your world to enable grab interactions\n * world.addSystem(GrabSystem)\n *\n * // Create a grabbable box\n * const box = world.createEntity()\n * box.addComponent(OneHandGrabbable, {})\n * ```\n *\n * @example Two‑handed manipulation\n * ```ts\n * // Create an object that can be scaled with two hands\n * const sculpture = world.createEntity()\n * sculpture.addComponent(TwoHandsGrabbable, {\n * scaleMin: [0.5, 0.5, 0.5],\n * scaleMax: [3, 3, 3]\n * })\n * ```\n *\n * @category Grab\n * @see {@link OneHandGrabbable}\n * @see {@link TwoHandsGrabbable}\n * @see {@link DistanceGrabbable}\n */\nexport class GrabSystem extends createSystem(\n {\n oneHandGrabbables: {\n required: [OneHandGrabbable],\n },\n twoHandsGrabbables: {\n required: [TwoHandsGrabbable],\n },\n distanceGrabbables: {\n required: [DistanceGrabbable],\n },\n handles: {\n required: [Handle],\n },\n },\n {\n /**\n * Controls whether hand pinch gestures are forwarded as squeeze events for grab interactions.\n * Set to `false` to disable pinch-to-grab and require the physical squeeze button instead.\n * @default false\n */\n useHandPinchForGrab: { type: Types.Boolean, default: false },\n },\n) {\n init() {\n // Ensure Handle component is registered in the world before queries rely on it\n if (!Handle.bitmask) {\n this.world.registerComponent(Handle);\n }\n if (!Grabbed.bitmask) {\n this.world.registerComponent(Grabbed);\n }\n\n // Reactive handle creation per grabbable type\n this.queries.oneHandGrabbables.subscribe('qualify', (entity) => {\n this.initializeOneHandHandle(entity);\n });\n this.queries.twoHandsGrabbables.subscribe('qualify', (entity) => {\n this.initializeTwoHandsHandle(entity);\n });\n this.queries.distanceGrabbables.subscribe('qualify', (entity) => {\n this.initializeDistanceHandle(entity);\n });\n\n // Unified cleanup for any handle\n this.queries.handles.subscribe('disqualify', (entity) => {\n const h = Handle.data.instance[entity.index] as\n | HandleStore<unknown>\n | undefined;\n if (h) {\n try {\n h.cancel();\n } catch {}\n }\n if (entity.object3D) {\n entity.object3D.pointerEventsType = 'all';\n }\n });\n\n // Initial pass for already-eligible entities (qualify doesn't fire retroactively)\n this.queries.oneHandGrabbables.entities.forEach((e) =>\n this.initializeOneHandHandle(e),\n );\n this.queries.twoHandsGrabbables.entities.forEach((e) =>\n this.initializeTwoHandsHandle(e),\n );\n this.queries.distanceGrabbables.entities.forEach((e) =>\n this.initializeDistanceHandle(e),\n );\n\n // Enable grab sub-pointer per hand when GrabSystem is active\n this.input.xr.multiPointers.left.toggleSubPointer('grab', true);\n this.input.xr.multiPointers.right.toggleSubPointer('grab', true);\n }\n\n update(delta: number, time: number): void {\n // Forward hand pinch events to squeeze for grab interactions\n // Only forward if the system-level useHandPinchForGrab flag is enabled\n if (this.config.useHandPinchForGrab) {\n (['left', 'right'] as const).forEach((handedness) => {\n if (this.input.xr.isPrimary('hand', handedness)) {\n const timeStamp = time * 1000;\n if (this.input.xr.gamepads[handedness]?.getSelectStart()) {\n this.input.xr.multiPointers[handedness].routeDown(\n 'squeeze',\n 'grab',\n {\n timeStamp,\n },\n );\n }\n if (this.input.xr.gamepads[handedness]?.getSelectEnd()) {\n this.input.xr.multiPointers[handedness].routeUp('squeeze', 'grab', {\n timeStamp,\n });\n }\n }\n });\n }\n\n // Unified handle updates\n this.queries.handles.entities.forEach((entity) => {\n const h = Handle.data.instance[entity.index] as\n | HandleStore<unknown>\n | undefined;\n if (h) {\n h.update(delta);\n // Manage Grabbed tag based on active grab state\n if (h.inputState.size > 0) {\n if (!entity.hasComponent(Grabbed)) {\n entity.addComponent(Grabbed);\n }\n } else if (entity.hasComponent(Grabbed)) {\n entity.removeComponent(Grabbed);\n }\n }\n });\n }\n\n /**\n * Force-release `entity` if it is currently being held.\n *\n * @remarks\n * Cancels every active pointer on the entity's grab handle, which causes\n * `update()` on the next frame to remove the {@link Grabbed} tag. Safe to\n * call when the entity is not held or has never been grabbable — a no-op\n * in those cases.\n *\n * Useful for game-state changes that need to drop held items: level resets,\n * weapon swaps, death/respawn, cinematics, etc.\n *\n * @example\n * ```ts\n * const grab = world.getSystem(GrabSystem);\n * grab.forceRelease(weaponEntity);\n * ```\n */\n forceRelease(entity: Entity): void {\n cancelGrabHandle(\n Handle.data.instance[entity.index] as HandleStore<unknown> | undefined,\n );\n }\n\n /**\n * Identify which controller is currently holding `entity`.\n *\n * @returns `'left'` or `'right'` when a single hand holds the entity,\n * `null` when the entity is not held (or has no grab handle).\n *\n * @remarks\n * For two-handed grabs (both controllers active on the same entity), the\n * left hand is reported. Callers needing per-hand state for two-handed\n * interactions should track grab/release events themselves rather than\n * polling this method.\n *\n * Useful for hand-aware behaviors: recoil/animation that should react to\n * the holding controller, hand-specific UI prompts, etc.\n *\n * @example\n * ```ts\n * const grab = world.getSystem(GrabSystem);\n * const hand = grab.getHolderHand(gunEntity);\n * if (hand) {\n * playRecoilOn(hand);\n * }\n * ```\n */\n getHolderHand(entity: Entity): 'left' | 'right' | null {\n const left = this.input.xr.multiPointers.left;\n const right = this.input.xr.multiPointers.right;\n const gaze = this.input.xr.gazePointer;\n return findHolderHand(\n Handle.data.instance[entity.index] as HandleStore<unknown> | undefined,\n // Near grabs capture via the `grab` sub-pointer; distance grabs capture\n // via `ray` (see `initializeDistanceHandle` setting\n // `pointerEventsType = { deny: 'grab' }`). Check both per hand so\n // distance-held entities don't silently report `null`.\n [left.getPointer('grab').id, left.getPointer('ray').id],\n [right.getPointer('grab').id, right.getPointer('ray').id],\n gaze.pointer.id,\n gaze.getHeldByHand(),\n );\n }\n\n private initializeOneHandHandle(entity: Entity) {\n if (entity.hasComponent(Handle)) {\n return;\n }\n const object = entity.object3D;\n if (!(object instanceof Object3D)) {\n return;\n }\n warnIfNoRaycastableMesh(entity, 'OneHandGrabbable');\n const obj = object as Object3D<PointerEventsMap & Object3DEventMap>;\n const rotateMax = entity.getVectorView(OneHandGrabbable, 'rotateMax');\n const rotateMin = entity.getVectorView(OneHandGrabbable, 'rotateMin');\n const translateMax = entity.getVectorView(OneHandGrabbable, 'translateMax');\n const translateMin = entity.getVectorView(OneHandGrabbable, 'translateMin');\n const handle = new HandleStore(obj, () => ({\n rotate: entity.getValue(OneHandGrabbable, 'rotate')\n ? {\n x: [rotateMin[0], rotateMax[0]] as [number, number],\n y: [rotateMin[1], rotateMax[1]] as [number, number],\n z: [rotateMin[2], rotateMax[2]] as [number, number],\n }\n : false,\n translate: entity.getValue(OneHandGrabbable, 'translate')\n ? {\n x: [translateMin[0], translateMax[0]] as [number, number],\n y: [translateMin[1], translateMax[1]] as [number, number],\n z: [translateMin[2], translateMax[2]] as [number, number],\n }\n : false,\n projectRays: false,\n multitouch: false,\n }));\n handle.bind(obj);\n obj.pointerEventsType = { deny: 'ray' };\n entity.addComponent(Handle, { instance: handle });\n }\n\n private initializeTwoHandsHandle(entity: Entity) {\n if (entity.hasComponent(Handle)) {\n return;\n }\n const object = entity.object3D;\n if (!(object instanceof Object3D)) {\n return;\n }\n warnIfNoRaycastableMesh(entity, 'TwoHandsGrabbable');\n const obj = object as Object3D<PointerEventsMap & Object3DEventMap>;\n const rotateMax = entity.getVectorView(TwoHandsGrabbable, 'rotateMax');\n const rotateMin = entity.getVectorView(TwoHandsGrabbable, 'rotateMin');\n const translateMax = entity.getVectorView(\n TwoHandsGrabbable,\n 'translateMax',\n );\n const translateMin = entity.getVectorView(\n TwoHandsGrabbable,\n 'translateMin',\n );\n const scaleMax = entity.getVectorView(TwoHandsGrabbable, 'scaleMax');\n const scaleMin = entity.getVectorView(TwoHandsGrabbable, 'scaleMin');\n const handle = new HandleStore(obj, () => ({\n rotate: entity.getValue(TwoHandsGrabbable, 'rotate')\n ? {\n x: [rotateMin[0], rotateMax[0]] as [number, number],\n y: [rotateMin[1], rotateMax[1]] as [number, number],\n z: [rotateMin[2], rotateMax[2]] as [number, number],\n }\n : false,\n translate: entity.getValue(TwoHandsGrabbable, 'translate')\n ? {\n x: [translateMin[0], translateMax[0]] as [number, number],\n y: [translateMin[1], translateMax[1]] as [number, number],\n z: [translateMin[2], translateMax[2]] as [number, number],\n }\n : false,\n scale: entity.getValue(TwoHandsGrabbable, 'scale')\n ? {\n x: [scaleMin[0], scaleMax[0]] as [number, number],\n y: [scaleMin[1], scaleMax[1]] as [number, number],\n z: [scaleMin[2], scaleMax[2]] as [number, number],\n }\n : false,\n projectRays: false,\n multitouch: true,\n }));\n handle.bind(obj);\n obj.pointerEventsType = { deny: 'ray' };\n entity.addComponent(Handle, { instance: handle });\n }\n\n private initializeDistanceHandle(entity: Entity) {\n if (entity.hasComponent(Handle)) {\n return;\n }\n const object = entity.object3D;\n if (!(object instanceof Object3D)) {\n return;\n }\n warnIfNoRaycastableMesh(entity, 'DistanceGrabbable');\n const obj = object as Object3D<PointerEventsMap & Object3DEventMap>;\n const rootEntity = entity.hasComponent(LevelTag)\n ? this.world.activeLevel.value\n : this.world.sceneEntity;\n const rotateMax = entity.getVectorView(DistanceGrabbable, 'rotateMax');\n const rotateMin = entity.getVectorView(DistanceGrabbable, 'rotateMin');\n const translateMax = entity.getVectorView(\n DistanceGrabbable,\n 'translateMax',\n );\n const translateMin = entity.getVectorView(\n DistanceGrabbable,\n 'translateMin',\n );\n const scaleMax = entity.getVectorView(DistanceGrabbable, 'scaleMax');\n const scaleMin = entity.getVectorView(DistanceGrabbable, 'scaleMin');\n const movementMode = entity.getValue(DistanceGrabbable, 'movementMode');\n const returnToOrigin = Boolean(\n entity.getValue(DistanceGrabbable, 'returnToOrigin'),\n );\n const detachOnGrab = Boolean(\n entity.getValue(DistanceGrabbable, 'detachOnGrab'),\n );\n const targetPosOffset = entity.getVectorView(\n DistanceGrabbable,\n 'targetPositionOffset',\n );\n const targetQuatOffset = entity.getVectorView(\n DistanceGrabbable,\n 'targetQuaternionOffset',\n );\n const opts = () => ({\n rotate: entity.getValue(DistanceGrabbable, 'rotate')\n ? {\n x: [rotateMin[0], rotateMax[0]] as [number, number],\n y: [rotateMin[1], rotateMax[1]] as [number, number],\n z: [rotateMin[2], rotateMax[2]] as [number, number],\n }\n : false,\n translate:\n movementMode === MovementMode.RotateAtSource\n ? ('as-rotate' as const)\n : entity.getValue(DistanceGrabbable, 'translate')\n ? {\n x: [translateMin[0], translateMax[0]] as [number, number],\n y: [translateMin[1], translateMax[1]] as [number, number],\n z: [translateMin[2], translateMax[2]] as [number, number],\n }\n : false,\n scale:\n movementMode === MovementMode.RotateAtSource\n ? false\n : entity.getValue(DistanceGrabbable, 'scale')\n ? {\n x: [scaleMin[0], scaleMax[0]] as [number, number],\n y: [scaleMin[1], scaleMax[1]] as [number, number],\n z: [scaleMin[2], scaleMax[2]] as [number, number],\n }\n : false,\n projectRays: false,\n });\n const handle = new DistanceGrabHandle(\n obj,\n rootEntity.object3D!,\n opts,\n movementMode!,\n returnToOrigin,\n entity.getValue(DistanceGrabbable, 'moveSpeedFactor') ?? 0.1,\n new Vector3(targetPosOffset[0], targetPosOffset[1], targetPosOffset[2]),\n new Quaternion(\n targetQuatOffset[0],\n targetQuatOffset[1],\n targetQuatOffset[2],\n targetQuatOffset[3],\n ),\n detachOnGrab,\n );\n handle.bind(obj);\n obj.pointerEventsType = { deny: 'grab' };\n entity.addComponent(Handle, { instance: handle });\n }\n}\n"],"names":[],"mappings":"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"}
@@ -55,7 +55,16 @@ export declare class DistanceGrabHandle<T> extends HandleStore<T> {
55
55
  constructor(target_: Object3D | {
56
56
  current?: Object3D | null;
57
57
  }, sceneRoot_: Object3D, getOptions: (() => HandleOptions<T>) | undefined, movementMode: string, returnToOrigin: boolean, moveSpeedFactor: number | undefined, targetPosOffset: Vector3 | undefined, targetQuatOffset: Quaternion | undefined, detachOnGrab: boolean);
58
- update(time: number): void;
58
+ /**
59
+ * Bind the handle and treat pointer cancellation as an interrupted release.
60
+ *
61
+ * Older @pmndrs/handle releases only listen for pointerup. Far-ray
62
+ * suppression correctly emits pointercancel, so bridge that event to the
63
+ * handle's pointer-up path. This releases only the cancelled pointer and is
64
+ * harmless if a newer dependency also handles pointercancel natively.
65
+ */
66
+ bind(handle: Object3D): () => void;
67
+ update(delta: number): void;
59
68
  protected apply(target: Object3D): T;
60
69
  }
61
70
  //# sourceMappingURL=handles.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"handles.d.ts","sourceRoot":"","sources":["../../src/grab/handles.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,KAAK,EAAmB,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAS,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAE3E,eAAO,MAAM,MAAM;;;;;EAMlB,CAAC;AAEF,iEAAiE;AACjE,eAAO,MAAM,YAAY;IACvB,oFAAoF;;IAEpF,qEAAqE;;IAErE,qFAAqF;;IAErF,8DAA8D;;CAE/D,CAAC;AAEF,qBAAa,kBAAkB,CAAC,CAAC,CAAE,SAAQ,WAAW,CAAC,CAAC,CAAC;IAmBrD,QAAQ,CAAC,OAAO,EAAE,QAAQ,GAAG;QAAE,OAAO,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAA;KAAE;IAC1D,QAAQ,CAAC,UAAU,EAAE,QAAQ;aACb,UAAU,EAAE,MAAM,aAAa,CAAC,CAAC,CAAC;aAClC,YAAY,EAAE,MAAM;aACpB,cAAc,EAAE,OAAO;aACvB,eAAe,EAAE,MAAM;aACvB,eAAe,EAAE,OAAO;aACxB,gBAAgB,EAAE,UAAU;aAC5B,YAAY,EAAE,OAAO;IA1BvC,OAAO,CAAC,qBAAqB,CAAsB;IACnD,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,oBAAoB,CAAS;IACrC,OAAO,CAAC,kBAAkB,CAAyB;IACnD,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAiB;IACtD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAoB;IAC3D,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAe;IACpD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAiB;IACnD,OAAO,CAAC,MAAM,CAAC,cAAc,CAAS;IACtC,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAO;IACtC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAiB;IACpC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAoB;IAC3C,OAAO,CAAC,MAAM,CAAC,UAAU,CAAiB;IAC1C,OAAO,CAAC,MAAM,CAAC,WAAW,CAAoB;IAC9C,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAiB;IAChD,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAoB;gBAGzC,OAAO,EAAE,QAAQ,GAAG;QAAE,OAAO,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAA;KAAE,EACjD,UAAU,EAAE,QAAQ,EACb,UAAU,GAAE,MAAM,aAAa,CAAC,CAAC,CAAC,aAAa,EAC/C,YAAY,EAAE,MAAM,EACpB,cAAc,EAAE,OAAO,EACvB,eAAe,EAAE,MAAM,YAAM,EAC7B,eAAe,EAAE,OAAO,YAAuB,EAC/C,gBAAgB,EAAE,UAAU,YAA6B,EACzD,YAAY,EAAE,OAAO;IAOvC,MAAM,CAAC,IAAI,EAAE,MAAM;IAmJnB,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,QAAQ,GAAG,CAAC;CAyCrC"}
1
+ {"version":3,"file":"handles.d.ts","sourceRoot":"","sources":["../../src/grab/handles.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAK5D,OAAO,EAAE,KAAK,EAAmB,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAEL,QAAQ,EAER,UAAU,EACV,OAAO,EACR,MAAM,qBAAqB,CAAC;AAE7B,eAAO,MAAM,MAAM;;;;;EAMlB,CAAC;AAEF,iEAAiE;AACjE,eAAO,MAAM,YAAY;IACvB,oFAAoF;;IAEpF,qEAAqE;;IAErE,qFAAqF;;IAErF,8DAA8D;;CAE/D,CAAC;AAEF,qBAAa,kBAAkB,CAAC,CAAC,CAAE,SAAQ,WAAW,CAAC,CAAC,CAAC;IAmBrD,QAAQ,CAAC,OAAO,EAAE,QAAQ,GAAG;QAAE,OAAO,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAA;KAAE;IAC1D,QAAQ,CAAC,UAAU,EAAE,QAAQ;aACb,UAAU,EAAE,MAAM,aAAa,CAAC,CAAC,CAAC;aAClC,YAAY,EAAE,MAAM;aACpB,cAAc,EAAE,OAAO;aACvB,eAAe,EAAE,MAAM;aACvB,eAAe,EAAE,OAAO;aACxB,gBAAgB,EAAE,UAAU;aAC5B,YAAY,EAAE,OAAO;IA1BvC,OAAO,CAAC,qBAAqB,CAAsB;IACnD,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,oBAAoB,CAAS;IACrC,OAAO,CAAC,kBAAkB,CAAyB;IACnD,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAiB;IACtD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAoB;IAC3D,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAe;IACpD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAiB;IACnD,OAAO,CAAC,MAAM,CAAC,cAAc,CAAS;IACtC,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAO;IACtC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAiB;IACpC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAoB;IAC3C,OAAO,CAAC,MAAM,CAAC,UAAU,CAAiB;IAC1C,OAAO,CAAC,MAAM,CAAC,WAAW,CAAoB;IAC9C,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAiB;IAChD,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAoB;gBAGzC,OAAO,EAAE,QAAQ,GAAG;QAAE,OAAO,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAA;KAAE,EACjD,UAAU,EAAE,QAAQ,EACb,UAAU,GAAE,MAAM,aAAa,CAAC,CAAC,CAAC,aAAa,EAC/C,YAAY,EAAE,MAAM,EACpB,cAAc,EAAE,OAAO,EACvB,eAAe,EAAE,MAAM,YAAM,EAC7B,eAAe,EAAE,OAAO,YAAuB,EAC/C,gBAAgB,EAAE,UAAU,YAA6B,EACzD,YAAY,EAAE,OAAO;IAOvC;;;;;;;OAOG;IACM,IAAI,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,IAAI;IAkB3C,MAAM,CAAC,KAAK,EAAE,MAAM;IAmJpB,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,QAAQ,GAAG,CAAC;CAyCrC"}
@@ -44,7 +44,30 @@ class DistanceGrabHandle extends HandleStore {
44
44
  this.returnTargetScale = new Vector3();
45
45
  this.targetQuatOffset.normalize();
46
46
  }
47
- update(time) {
47
+ /**
48
+ * Bind the handle and treat pointer cancellation as an interrupted release.
49
+ *
50
+ * Older @pmndrs/handle releases only listen for pointerup. Far-ray
51
+ * suppression correctly emits pointercancel, so bridge that event to the
52
+ * handle's pointer-up path. This releases only the cancelled pointer and is
53
+ * harmless if a newer dependency also handles pointercancel natively.
54
+ */
55
+ bind(handle) {
56
+ const unbind = super.bind(handle);
57
+ const pointerTarget = handle;
58
+ const onPointerCancel = (event) => {
59
+ if (!this.capturedObjects.has(event.pointerId)) {
60
+ return;
61
+ }
62
+ this.handlers.onPointerUp(event);
63
+ };
64
+ pointerTarget.addEventListener('pointercancel', onPointerCancel);
65
+ return () => {
66
+ pointerTarget.removeEventListener('pointercancel', onPointerCancel);
67
+ unbind();
68
+ };
69
+ }
70
+ update(delta) {
48
71
  var _a;
49
72
  const target = this.getTarget();
50
73
  if (this.inputState.size === 0) {
@@ -69,7 +92,7 @@ class DistanceGrabHandle extends HandleStore {
69
92
  }
70
93
  if (this.movementMode === MovementMode.RotateAtSource ||
71
94
  this.movementMode === MovementMode.MoveFromTarget) {
72
- super.update(time);
95
+ super.update(delta);
73
96
  return;
74
97
  }
75
98
  const pointerAmount = this.inputState.size;
@@ -84,10 +107,10 @@ class DistanceGrabHandle extends HandleStore {
84
107
  const [p1] = this.inputState.values();
85
108
  const current = p1.pointerWorldOrigin;
86
109
  if (this.previousPointerOrigin != undefined) {
87
- const delta = DistanceGrabHandle._tmp
110
+ const originDelta = DistanceGrabHandle._tmp
88
111
  .copy(current)
89
112
  .sub(this.previousPointerOrigin);
90
- DistanceGrabHandle._posHelper.add(delta);
113
+ DistanceGrabHandle._posHelper.add(originDelta);
91
114
  }
92
115
  else {
93
116
  this.previousPointerOrigin = new Vector3().copy(current);
@@ -110,7 +133,7 @@ class DistanceGrabHandle extends HandleStore {
110
133
  .copy(pointerQuaternion)
111
134
  .multiply(this.targetQuatOffset);
112
135
  const distance = targetPosition.distanceTo(DistanceGrabHandle._posHelper);
113
- const rawInterpolationAlpha = this.moveSpeedFactor * time * DistanceGrabHandle.MOVE_SPEED_SCALE;
136
+ const rawInterpolationAlpha = this.moveSpeedFactor * delta * DistanceGrabHandle.MOVE_SPEED_SCALE;
114
137
  // Invalid timing/config input must never poison the target transform.
115
138
  // Freeze on NaN; clamp finite values and infinities to the valid lerp range.
116
139
  const interpolationAlpha = Number.isNaN(rawInterpolationAlpha)
@@ -161,7 +184,7 @@ class DistanceGrabHandle extends HandleStore {
161
184
  quaternion,
162
185
  rotation,
163
186
  scale,
164
- time,
187
+ time: delta,
165
188
  });
166
189
  this.outputState.memo = this.apply(target);
167
190
  this.latestMoveEvent = undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"handles.js","sources":["../../src/grab/handles.ts"],"sourcesContent":["/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { HandleOptions, HandleStore } from '@pmndrs/handle';\nimport { Types, createComponent } from '../ecs/component.js';\nimport { Euler, Object3D, Quaternion, Vector3 } from '../runtime/index.js';\n\nexport const Handle = createComponent(\n 'Handle',\n {\n instance: { type: Types.Object, default: undefined },\n },\n 'Internal component storing an active interaction handle instance',\n);\n\n/** MovementMode for {@link DistanceGrabbable}. @category Grab */\nexport const MovementMode = {\n /** Object smoothly moves with the ray cast end point of the grabbing controller. */\n MoveFromTarget: 'MoveFromTarget',\n /** Object smoothly moves toward the input source that's grabbing. */\n MoveTowardsTarget: 'MoveTowardsTarget',\n /** Object moves relative to controller delta movement while maintaining distance. */\n MoveAtSource: 'MoveAtSource',\n /** Object rotates in place without translation or scaling. */\n RotateAtSource: 'RotateAtSource',\n};\n\nexport class DistanceGrabHandle<T> extends HandleStore<T> {\n private previousPointerOrigin: Vector3 | undefined;\n private isSnapped: boolean = false;\n private returnOriginCaptured = false;\n private returnTargetParent: Object3D | null = null;\n private readonly returnTargetPosition = new Vector3();\n private readonly returnTargetQuaternion = new Quaternion();\n private readonly returnTargetRotation = new Euler();\n private readonly returnTargetScale = new Vector3();\n private static SNAP_THRESHOLD = 0.005;\n private static MOVE_SPEED_SCALE = 100;\n private static _tmp = new Vector3();\n private static _tmpQuat = new Quaternion();\n private static _posHelper = new Vector3();\n private static _quatHelper = new Quaternion();\n private static _offsetPosHelper = new Vector3();\n private static _offsetQuatHelper = new Quaternion();\n\n constructor(\n readonly target_: Object3D | { current?: Object3D | null },\n readonly sceneRoot_: Object3D,\n public readonly getOptions: () => HandleOptions<T> = () => ({}),\n public readonly movementMode: string,\n public readonly returnToOrigin: boolean,\n public readonly moveSpeedFactor: number = 0.1,\n public readonly targetPosOffset: Vector3 = new Vector3(0, 0, 0),\n public readonly targetQuatOffset: Quaternion = new Quaternion(0, 0, 0, 1),\n public readonly detachOnGrab: boolean,\n ) {\n super(target_, getOptions);\n\n this.targetQuatOffset.normalize();\n }\n\n update(time: number) {\n const target = this.getTarget();\n\n if (this.inputState.size === 0) {\n // No active pointers: the grab was released, cancelled, or\n // force-released. Clear transient snap state so the next grab starts\n // unsnapped. This replaces the constructor's 'pointerup' DOM listener,\n // which was never removed (a listener leak) and also missed\n // forceRelease()/cancel() (which don't fire a DOM pointerup).\n this.isSnapped = false;\n }\n\n if (\n target == null ||\n this.inputState.size === 0 ||\n (this.latestMoveEvent == null &&\n (this.getOptions().alwaysUpdate ?? false) === false)\n ) {\n if (this.previousPointerOrigin != undefined) {\n this.previousPointerOrigin = undefined;\n }\n return;\n }\n\n if (this.detachOnGrab && target.parent != this.sceneRoot_) {\n this.sceneRoot_.attach(target);\n }\n\n if (\n this.movementMode === MovementMode.RotateAtSource ||\n this.movementMode === MovementMode.MoveFromTarget\n ) {\n super.update(time);\n return;\n }\n\n const pointerAmount = this.inputState.size;\n target.getWorldPosition(DistanceGrabHandle._posHelper);\n target.getWorldQuaternion(DistanceGrabHandle._quatHelper);\n const position = target.position;\n const quaternion = target.quaternion;\n const rotation = target.rotation;\n const scale = target.scale;\n\n switch (this.movementMode) {\n case MovementMode.MoveAtSource: {\n const [p1] = this.inputState.values();\n const current = p1.pointerWorldOrigin;\n if (this.previousPointerOrigin != undefined) {\n const delta = DistanceGrabHandle._tmp\n .copy(current)\n .sub(this.previousPointerOrigin);\n DistanceGrabHandle._posHelper.add(delta);\n } else {\n this.previousPointerOrigin = new Vector3().copy(current);\n }\n // Update stored previous for next frame\n this.previousPointerOrigin!.copy(current);\n break;\n }\n case MovementMode.MoveTowardsTarget: {\n const [p1] = this.inputState.values();\n const pointerOrigin = p1.pointerWorldOrigin;\n const pointerQuaternion = p1.pointerWorldQuaternion;\n\n // Calculate target position by applying position offset in pointer's local space\n const targetPosition = DistanceGrabHandle._offsetPosHelper\n .copy(this.targetPosOffset)\n .applyQuaternion(pointerQuaternion)\n .add(pointerOrigin);\n\n // Calculate target rotation by multiplying pointer rotation with rotation offset\n const targetQuaternion = DistanceGrabHandle._offsetQuatHelper\n .copy(pointerQuaternion)\n .multiply(this.targetQuatOffset);\n\n const distance = targetPosition.distanceTo(\n DistanceGrabHandle._posHelper,\n );\n const rawInterpolationAlpha =\n this.moveSpeedFactor * time * DistanceGrabHandle.MOVE_SPEED_SCALE;\n // Invalid timing/config input must never poison the target transform.\n // Freeze on NaN; clamp finite values and infinities to the valid lerp range.\n const interpolationAlpha = Number.isNaN(rawInterpolationAlpha)\n ? 0\n : Math.min(1, Math.max(0, rawInterpolationAlpha));\n\n if (!this.isSnapped && distance > DistanceGrabHandle.SNAP_THRESHOLD) {\n DistanceGrabHandle._posHelper.lerp(\n targetPosition,\n interpolationAlpha,\n );\n DistanceGrabHandle._quatHelper.slerp(\n targetQuaternion,\n interpolationAlpha,\n );\n } else {\n if (!this.isSnapped) {\n this.isSnapped = true;\n }\n DistanceGrabHandle._posHelper.copy(targetPosition);\n DistanceGrabHandle._quatHelper.copy(targetQuaternion);\n }\n\n break;\n }\n }\n\n // Convert world space transforms to local space\n if (target.parent) {\n // Get parent's inverse world matrix\n const parentWorldMatrixInverse = target.parent.matrixWorld\n .clone()\n .invert();\n\n // Transform desired world position to local space\n position\n .copy(DistanceGrabHandle._posHelper)\n .applyMatrix4(parentWorldMatrixInverse);\n\n // Transform desired world quaternion to local space\n const parentWorldQuaternionInverse = target.parent\n .getWorldQuaternion(DistanceGrabHandle._tmpQuat)\n .invert();\n quaternion\n .copy(DistanceGrabHandle._quatHelper)\n .premultiply(parentWorldQuaternionInverse);\n } else {\n // No parent, world space = local space\n position.copy(DistanceGrabHandle._posHelper);\n quaternion.copy(DistanceGrabHandle._quatHelper);\n }\n\n // Always apply during drag; if returnToOrigin is true,\n // the override in apply() will snap back on release.\n this.outputState.update(this.latestMoveEvent, {\n pointerAmount,\n position,\n quaternion,\n rotation,\n scale,\n time,\n });\n this.outputState.memo = this.apply(target);\n this.latestMoveEvent = undefined;\n }\n\n protected apply(target: Object3D): T {\n if (\n this.returnToOrigin &&\n this.inputState.size === 1 &&\n this.outputState.first &&\n !this.returnOriginCaptured\n ) {\n this.returnTargetParent = target.parent;\n this.returnTargetPosition.copy(target.position);\n this.returnTargetQuaternion.copy(target.quaternion);\n this.returnTargetRotation.copy(target.rotation);\n this.returnTargetScale.copy(target.scale);\n this.returnOriginCaptured = true;\n }\n\n // HandleStore intentionally saves a new manipulation baseline whenever a\n // second pointer joins or one pointer leaves. Return-to-origin needs the\n // transform from the start of the whole gesture, not a handoff baseline.\n if (\n this.returnToOrigin &&\n this.outputState.last &&\n this.returnOriginCaptured\n ) {\n if (this.detachOnGrab && target.parent !== this.returnTargetParent) {\n if (this.returnTargetParent == null) {\n target.removeFromParent();\n } else {\n this.returnTargetParent.add(target);\n }\n }\n target.position.copy(this.returnTargetPosition);\n target.rotation.order = this.returnTargetRotation.order;\n target.quaternion.copy(this.returnTargetQuaternion);\n target.scale.copy(this.returnTargetScale);\n this.returnTargetParent = null;\n this.returnOriginCaptured = false;\n // Do not call super.apply to avoid re-applying the drag transform.\n return undefined as unknown as T;\n }\n return super.apply(target);\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"handles.js","sources":["../../src/grab/handles.ts"],"sourcesContent":["/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { HandleOptions, HandleStore } from '@pmndrs/handle';\nimport type {\n PointerEvent as PmndrsPointerEvent,\n PointerEventsMap,\n} from '@pmndrs/pointer-events';\nimport { Types, createComponent } from '../ecs/component.js';\nimport {\n Euler,\n Object3D,\n type Object3DEventMap,\n Quaternion,\n Vector3,\n} from '../runtime/index.js';\n\nexport const Handle = createComponent(\n 'Handle',\n {\n instance: { type: Types.Object, default: undefined },\n },\n 'Internal component storing an active interaction handle instance',\n);\n\n/** MovementMode for {@link DistanceGrabbable}. @category Grab */\nexport const MovementMode = {\n /** Object smoothly moves with the ray cast end point of the grabbing controller. */\n MoveFromTarget: 'MoveFromTarget',\n /** Object smoothly moves toward the input source that's grabbing. */\n MoveTowardsTarget: 'MoveTowardsTarget',\n /** Object moves relative to controller delta movement while maintaining distance. */\n MoveAtSource: 'MoveAtSource',\n /** Object rotates in place without translation or scaling. */\n RotateAtSource: 'RotateAtSource',\n};\n\nexport class DistanceGrabHandle<T> extends HandleStore<T> {\n private previousPointerOrigin: Vector3 | undefined;\n private isSnapped: boolean = false;\n private returnOriginCaptured = false;\n private returnTargetParent: Object3D | null = null;\n private readonly returnTargetPosition = new Vector3();\n private readonly returnTargetQuaternion = new Quaternion();\n private readonly returnTargetRotation = new Euler();\n private readonly returnTargetScale = new Vector3();\n private static SNAP_THRESHOLD = 0.005;\n private static MOVE_SPEED_SCALE = 100;\n private static _tmp = new Vector3();\n private static _tmpQuat = new Quaternion();\n private static _posHelper = new Vector3();\n private static _quatHelper = new Quaternion();\n private static _offsetPosHelper = new Vector3();\n private static _offsetQuatHelper = new Quaternion();\n\n constructor(\n readonly target_: Object3D | { current?: Object3D | null },\n readonly sceneRoot_: Object3D,\n public readonly getOptions: () => HandleOptions<T> = () => ({}),\n public readonly movementMode: string,\n public readonly returnToOrigin: boolean,\n public readonly moveSpeedFactor: number = 0.1,\n public readonly targetPosOffset: Vector3 = new Vector3(0, 0, 0),\n public readonly targetQuatOffset: Quaternion = new Quaternion(0, 0, 0, 1),\n public readonly detachOnGrab: boolean,\n ) {\n super(target_, getOptions);\n\n this.targetQuatOffset.normalize();\n }\n\n /**\n * Bind the handle and treat pointer cancellation as an interrupted release.\n *\n * Older @pmndrs/handle releases only listen for pointerup. Far-ray\n * suppression correctly emits pointercancel, so bridge that event to the\n * handle's pointer-up path. This releases only the cancelled pointer and is\n * harmless if a newer dependency also handles pointercancel natively.\n */\n override bind(handle: Object3D): () => void {\n const unbind = super.bind(handle);\n const pointerTarget = handle as Object3D<\n PointerEventsMap & Object3DEventMap\n >;\n const onPointerCancel = (event: PmndrsPointerEvent) => {\n if (!this.capturedObjects.has(event.pointerId)) {\n return;\n }\n this.handlers.onPointerUp(event);\n };\n pointerTarget.addEventListener('pointercancel', onPointerCancel);\n return () => {\n pointerTarget.removeEventListener('pointercancel', onPointerCancel);\n unbind();\n };\n }\n\n update(delta: number) {\n const target = this.getTarget();\n\n if (this.inputState.size === 0) {\n // No active pointers: the grab was released, cancelled, or\n // force-released. Clear transient snap state so the next grab starts\n // unsnapped. This replaces the constructor's 'pointerup' DOM listener,\n // which was never removed (a listener leak) and also missed\n // forceRelease()/cancel() (which don't fire a DOM pointerup).\n this.isSnapped = false;\n }\n\n if (\n target == null ||\n this.inputState.size === 0 ||\n (this.latestMoveEvent == null &&\n (this.getOptions().alwaysUpdate ?? false) === false)\n ) {\n if (this.previousPointerOrigin != undefined) {\n this.previousPointerOrigin = undefined;\n }\n return;\n }\n\n if (this.detachOnGrab && target.parent != this.sceneRoot_) {\n this.sceneRoot_.attach(target);\n }\n\n if (\n this.movementMode === MovementMode.RotateAtSource ||\n this.movementMode === MovementMode.MoveFromTarget\n ) {\n super.update(delta);\n return;\n }\n\n const pointerAmount = this.inputState.size;\n target.getWorldPosition(DistanceGrabHandle._posHelper);\n target.getWorldQuaternion(DistanceGrabHandle._quatHelper);\n const position = target.position;\n const quaternion = target.quaternion;\n const rotation = target.rotation;\n const scale = target.scale;\n\n switch (this.movementMode) {\n case MovementMode.MoveAtSource: {\n const [p1] = this.inputState.values();\n const current = p1.pointerWorldOrigin;\n if (this.previousPointerOrigin != undefined) {\n const originDelta = DistanceGrabHandle._tmp\n .copy(current)\n .sub(this.previousPointerOrigin);\n DistanceGrabHandle._posHelper.add(originDelta);\n } else {\n this.previousPointerOrigin = new Vector3().copy(current);\n }\n // Update stored previous for next frame\n this.previousPointerOrigin!.copy(current);\n break;\n }\n case MovementMode.MoveTowardsTarget: {\n const [p1] = this.inputState.values();\n const pointerOrigin = p1.pointerWorldOrigin;\n const pointerQuaternion = p1.pointerWorldQuaternion;\n\n // Calculate target position by applying position offset in pointer's local space\n const targetPosition = DistanceGrabHandle._offsetPosHelper\n .copy(this.targetPosOffset)\n .applyQuaternion(pointerQuaternion)\n .add(pointerOrigin);\n\n // Calculate target rotation by multiplying pointer rotation with rotation offset\n const targetQuaternion = DistanceGrabHandle._offsetQuatHelper\n .copy(pointerQuaternion)\n .multiply(this.targetQuatOffset);\n\n const distance = targetPosition.distanceTo(\n DistanceGrabHandle._posHelper,\n );\n const rawInterpolationAlpha =\n this.moveSpeedFactor * delta * DistanceGrabHandle.MOVE_SPEED_SCALE;\n // Invalid timing/config input must never poison the target transform.\n // Freeze on NaN; clamp finite values and infinities to the valid lerp range.\n const interpolationAlpha = Number.isNaN(rawInterpolationAlpha)\n ? 0\n : Math.min(1, Math.max(0, rawInterpolationAlpha));\n\n if (!this.isSnapped && distance > DistanceGrabHandle.SNAP_THRESHOLD) {\n DistanceGrabHandle._posHelper.lerp(\n targetPosition,\n interpolationAlpha,\n );\n DistanceGrabHandle._quatHelper.slerp(\n targetQuaternion,\n interpolationAlpha,\n );\n } else {\n if (!this.isSnapped) {\n this.isSnapped = true;\n }\n DistanceGrabHandle._posHelper.copy(targetPosition);\n DistanceGrabHandle._quatHelper.copy(targetQuaternion);\n }\n\n break;\n }\n }\n\n // Convert world space transforms to local space\n if (target.parent) {\n // Get parent's inverse world matrix\n const parentWorldMatrixInverse = target.parent.matrixWorld\n .clone()\n .invert();\n\n // Transform desired world position to local space\n position\n .copy(DistanceGrabHandle._posHelper)\n .applyMatrix4(parentWorldMatrixInverse);\n\n // Transform desired world quaternion to local space\n const parentWorldQuaternionInverse = target.parent\n .getWorldQuaternion(DistanceGrabHandle._tmpQuat)\n .invert();\n quaternion\n .copy(DistanceGrabHandle._quatHelper)\n .premultiply(parentWorldQuaternionInverse);\n } else {\n // No parent, world space = local space\n position.copy(DistanceGrabHandle._posHelper);\n quaternion.copy(DistanceGrabHandle._quatHelper);\n }\n\n // Always apply during drag; if returnToOrigin is true,\n // the override in apply() will snap back on release.\n this.outputState.update(this.latestMoveEvent, {\n pointerAmount,\n position,\n quaternion,\n rotation,\n scale,\n time: delta,\n });\n this.outputState.memo = this.apply(target);\n this.latestMoveEvent = undefined;\n }\n\n protected apply(target: Object3D): T {\n if (\n this.returnToOrigin &&\n this.inputState.size === 1 &&\n this.outputState.first &&\n !this.returnOriginCaptured\n ) {\n this.returnTargetParent = target.parent;\n this.returnTargetPosition.copy(target.position);\n this.returnTargetQuaternion.copy(target.quaternion);\n this.returnTargetRotation.copy(target.rotation);\n this.returnTargetScale.copy(target.scale);\n this.returnOriginCaptured = true;\n }\n\n // HandleStore intentionally saves a new manipulation baseline whenever a\n // second pointer joins or one pointer leaves. Return-to-origin needs the\n // transform from the start of the whole gesture, not a handoff baseline.\n if (\n this.returnToOrigin &&\n this.outputState.last &&\n this.returnOriginCaptured\n ) {\n if (this.detachOnGrab && target.parent !== this.returnTargetParent) {\n if (this.returnTargetParent == null) {\n target.removeFromParent();\n } else {\n this.returnTargetParent.add(target);\n }\n }\n target.position.copy(this.returnTargetPosition);\n target.rotation.order = this.returnTargetRotation.order;\n target.quaternion.copy(this.returnTargetQuaternion);\n target.scale.copy(this.returnTargetScale);\n this.returnTargetParent = null;\n this.returnOriginCaptured = false;\n // Do not call super.apply to avoid re-applying the drag transform.\n return undefined as unknown as T;\n }\n return super.apply(target);\n }\n}\n"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -15,6 +15,7 @@ export * from './ui/index.js';
15
15
  export * from './init/index.js';
16
16
  export * from './grab/index.js';
17
17
  export * from './input/index.js';
18
+ export * from './gaze/index.js';
18
19
  export * from './environment/index.js';
19
20
  export * from './level/index.js';
20
21
  export * from './scene-understanding/index.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AAGnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,OAAO,KAAK,KAAK,MAAM,eAAe,CAAC;AACvC,OAAO,EACL,MAAM,EACN,MAAM,EACN,QAAQ,EACR,KAAK,EACL,SAAS,EACT,MAAM,GACP,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,EAAE,OAAO,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,wBAAwB,CAAC;AACvC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AAGnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,OAAO,KAAK,KAAK,MAAM,eAAe,CAAC;AACvC,OAAO,EACL,MAAM,EACN,MAAM,EACN,QAAQ,EACR,KAAK,EACL,SAAS,EACT,MAAM,GACP,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,EAAE,OAAO,EAAE,CAAC"}
package/dist/index.js CHANGED
@@ -39,6 +39,7 @@ export { CanvasPointerSystem } from './input/canvas-pointer-system.js';
39
39
  export { StatefulKeyboard } from './input/stateful-keyboard.js';
40
40
  export { BrowserGamepadAxis, BrowserGamepadButton, StatefulBrowserGamepad } from './input/stateful-browser-gamepad.js';
41
41
  export { Hovered, Interactable, PokeInteractable, Pressed, RayInteractable } from './input/state-tags.js';
42
+ export { GazeSystem } from './gaze/gaze-system.js';
42
43
  export { DomeTexture } from './environment/dome-texture.js';
43
44
  export { DomeGradient } from './environment/dome-gradient.js';
44
45
  export { IBLTexture } from './environment/ibl-texture.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { VERSION as EliCSVersion } from 'elics';\nimport { REVISION } from 'three';\nimport { VERSION } from './version.js';\n\nexport * from './runtime/index.js';\nexport * from './ecs/index.js';\nexport * from './transform/index.js';\nexport * from './asset/index.js';\nexport * from './locomotion/index.js';\nexport * from './visibility/index.js';\nexport * from './ui/index.js';\nexport * from './init/index.js';\nexport * from './grab/index.js';\nexport * from './input/index.js';\nexport * from './environment/index.js';\nexport * from './level/index.js';\nexport * from './scene-understanding/index.js';\nexport * from './environment-raycast/index.js';\nexport * from './audio/index.js';\nexport * from './physics/index.js';\nexport * from './camera/index.js';\nexport * from './depth/index.js';\nexport * from './layers/index.js';\nexport * from './lighting/index.js';\nexport * from './mcp/index.js';\nexport * from './project/index.js';\n\n// re-exports\nexport * from '@iwsdk/xr-input';\nexport * from '@iwsdk/locomotor';\nexport * as UIKit from '@pmndrs/uikit';\nexport {\n signal,\n effect,\n computed,\n batch,\n untracked,\n Signal,\n} from '@preact/signals-core';\nexport type { ReadonlySignal } from '@preact/signals-core';\n\nexport { VERSION };\n\nconsole.log(` \n▄▄▄▄▄▄ ▄▄ ▄▄ ▄▄▄▄ ▄▄▄▄▄ ▄▄ ▄▄▄ \n▀▀██▀▀ ██ ██ ▄█▀▀▀▀█ ██▀▀▀██ ██ ██▀ \n ██ ▀█▄ ██ ▄█▀ ██▄ ██ ██ ██▄██ \n ██ ██ ██ ██ ▀████▄ ██ ██ █████ \n ██ ███▀▀███ ▀██ ██ ██ ██ ██▄ \n▄▄██▄▄ ███ ███ █▄▄▄▄▄█▀ ██▄▄▄██ ██ ██▄ \n▀▀▀▀▀▀ ▀▀▀ ▀▀▀ ▀▀▀▀▀ ▀▀▀▀▀ ▀▀ ▀▀ \n===============================================\nImmersive Web SDK v${VERSION}\nThree.js r${REVISION}\nEliCS v${EliCSVersion}`);\n"],"names":["EliCSVersion"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;;AAKG;AA6CH,OAAO,CAAC,GAAG,CAAC,CAAA;;;;;;;;;qBASS,OAAO;YAChB,QAAQ;SACXA,SAAY,CAAA,CAAE,CAAC;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { VERSION as EliCSVersion } from 'elics';\nimport { REVISION } from 'three';\nimport { VERSION } from './version.js';\n\nexport * from './runtime/index.js';\nexport * from './ecs/index.js';\nexport * from './transform/index.js';\nexport * from './asset/index.js';\nexport * from './locomotion/index.js';\nexport * from './visibility/index.js';\nexport * from './ui/index.js';\nexport * from './init/index.js';\nexport * from './grab/index.js';\nexport * from './input/index.js';\nexport * from './gaze/index.js';\nexport * from './environment/index.js';\nexport * from './level/index.js';\nexport * from './scene-understanding/index.js';\nexport * from './environment-raycast/index.js';\nexport * from './audio/index.js';\nexport * from './physics/index.js';\nexport * from './camera/index.js';\nexport * from './depth/index.js';\nexport * from './layers/index.js';\nexport * from './lighting/index.js';\nexport * from './mcp/index.js';\nexport * from './project/index.js';\n\n// re-exports\nexport * from '@iwsdk/xr-input';\nexport * from '@iwsdk/locomotor';\nexport * as UIKit from '@pmndrs/uikit';\nexport {\n signal,\n effect,\n computed,\n batch,\n untracked,\n Signal,\n} from '@preact/signals-core';\nexport type { ReadonlySignal } from '@preact/signals-core';\n\nexport { VERSION };\n\nconsole.log(` \n▄▄▄▄▄▄ ▄▄ ▄▄ ▄▄▄▄ ▄▄▄▄▄ ▄▄ ▄▄▄ \n▀▀██▀▀ ██ ██ ▄█▀▀▀▀█ ██▀▀▀██ ██ ██▀ \n ██ ▀█▄ ██ ▄█▀ ██▄ ██ ██ ██▄██ \n ██ ██ ██ ██ ▀████▄ ██ ██ █████ \n ██ ███▀▀███ ▀██ ██ ██ ██ ██▄ \n▄▄██▄▄ ███ ███ █▄▄▄▄▄█▀ ██▄▄▄██ ██ ██▄ \n▀▀▀▀▀▀ ▀▀▀ ▀▀▀ ▀▀▀▀▀ ▀▀▀▀▀ ▀▀ ▀▀ \n===============================================\nImmersive Web SDK v${VERSION}\nThree.js r${REVISION}\nEliCS v${EliCSVersion}`);\n"],"names":["EliCSVersion"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;;AAKG;AA8CH,OAAO,CAAC,GAAG,CAAC,CAAA;;;;;;;;;qBASS,OAAO;YAChB,QAAQ;SACXA,SAAY,CAAA,CAAE,CAAC;;;;"}
@@ -84,6 +84,33 @@ export type WorldOptions = {
84
84
  grabbing?: boolean | {
85
85
  useHandPinchForGrab?: boolean;
86
86
  };
87
+ /**
88
+ * Tuning for gaze + pinch input. `GazeSystem` registration is driven by the
89
+ * `xr.features.gazeTracking` session feature, not by this entry — this only
90
+ * overrides the system's defaults when gaze is already active.
91
+ */
92
+ gaze?: {
93
+ /** Half-angle of the gaze selection cone, in degrees. @defaultValue 5 */
94
+ coneAngle?: number;
95
+ /** Maximum gaze cone distance in meters. @defaultValue 30 */
96
+ maxRayLength?: number;
97
+ /** Dwell consensus window in seconds; `0` disables it. @defaultValue 0.15 */
98
+ dwellWindowSeconds?: number;
99
+ /** 1€ filter min cutoff. @defaultValue 1.5 */
100
+ filterMinCutoff?: number;
101
+ /** 1€ filter beta. @defaultValue 0.05 */
102
+ filterBeta?: number;
103
+ /** Yield to near touch/grab pointers when they're active. @defaultValue true */
104
+ suppressWhenDirectPointerActive?: boolean;
105
+ /** Drag from the pinching hand's ray space once selected. @defaultValue true */
106
+ pointerTransformFollowsHand?: boolean;
107
+ /** Emit `[iwsdk][gaze]` console diagnostics. @defaultValue true */
108
+ logDiagnostics?: boolean;
109
+ /** Show a developer-only gaze hit reticle. @defaultValue false */
110
+ showDebugReticle?: boolean;
111
+ /** Keep gaze mode active briefly after tracking becomes invalid. @defaultValue 5 */
112
+ trackingLossGraceSeconds?: number;
113
+ };
87
114
  /** Physics simulation (Havok). Boolean or config. @defaultValue false */
88
115
  physics?: boolean | {
89
116
  /** Run the physics engine in a Web Worker. @defaultValue true */
@@ -180,6 +207,28 @@ export declare function extractConfiguration(options: WorldOptions): {
180
207
  readonly grabbing: boolean | {
181
208
  useHandPinchForGrab?: boolean;
182
209
  };
210
+ readonly gaze: {
211
+ /** Half-angle of the gaze selection cone, in degrees. @defaultValue 5 */
212
+ coneAngle?: number;
213
+ /** Maximum gaze cone distance in meters. @defaultValue 30 */
214
+ maxRayLength?: number;
215
+ /** Dwell consensus window in seconds; `0` disables it. @defaultValue 0.15 */
216
+ dwellWindowSeconds?: number;
217
+ /** 1€ filter min cutoff. @defaultValue 1.5 */
218
+ filterMinCutoff?: number;
219
+ /** 1€ filter beta. @defaultValue 0.05 */
220
+ filterBeta?: number;
221
+ /** Yield to near touch/grab pointers when they're active. @defaultValue true */
222
+ suppressWhenDirectPointerActive?: boolean;
223
+ /** Drag from the pinching hand's ray space once selected. @defaultValue true */
224
+ pointerTransformFollowsHand?: boolean;
225
+ /** Emit `[iwsdk][gaze]` console diagnostics. @defaultValue true */
226
+ logDiagnostics?: boolean;
227
+ /** Show a developer-only gaze hit reticle. @defaultValue false */
228
+ showDebugReticle?: boolean;
229
+ /** Keep gaze mode active briefly after tracking becomes invalid. @defaultValue 5 */
230
+ trackingLossGraceSeconds?: number;
231
+ } | undefined;
183
232
  readonly physics: boolean | {
184
233
  /** Run the physics engine in a Web Worker. @defaultValue true */
185
234
  useWorker?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"world-initializer.d.ts","sourceRoot":"","sources":["../../src/init/world-initializer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"world-initializer.d.ts","sourceRoot":"","sources":["../../src/init/world-initializer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAEL,aAAa,EAEd,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,KAAK,EAAmB,MAAM,iBAAiB,CAAC;AAczD,OAAO,EACL,yBAAyB,EAO1B,MAAM,mBAAmB,CAAC;AAmB3B,OAAO,EACL,KAAK,yBAAyB,EAE9B,aAAa,EACd,MAAM,wBAAwB,CAAC;AAoBhC,OAAO,EAOL,WAAW,EACX,mBAAmB,EACnB,UAAU,EAEX,MAAM,gBAAgB,CAAC;AAOxB,OAAO,EAEL,WAAW,EACX,SAAS,EAGV,MAAM,SAAS,CAAC;AAEjB;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,wDAAwD;IACxD,MAAM,CAAC,EAAE,aAAa,CAAC;IAEvB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAE/B,kHAAkH;IAClH,KAAK,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAC;IAElC;;;;OAIG;IACH,EAAE,CAAC,EAAE,KAAK,GAAG,CAAC,SAAS,GAAG;QAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAA;KAAE,CAAC,CAAC;IAElE,uCAAuC;IACvC,MAAM,CAAC,EAAE;QACP,wDAAwD;QACxD,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,6CAA6C;QAC7C,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,4CAA4C;QAC5C,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,iDAAiD;QACjD,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,sDAAsD;QACtD,MAAM,CAAC,EAAE;YACP,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;YACpC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;YACpC,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;YAC9C,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;SACnC,CAAC;KACH,CAAC;IAEF,2DAA2D;IAC3D,KAAK,CAAC,EAAE;QACN;;;WAGG;QACH,mBAAmB,CAAC,EAAE,yBAAyB,CAAC;KACjD,CAAC;IAEF,8BAA8B;IAC9B,QAAQ,CAAC,EAAE;QACT,+EAA+E;QAC/E,UAAU,CAAC,EACP,OAAO,GACP;YACE,SAAS,CAAC,EAAE,OAAO,CAAC;YACpB,qBAAqB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;YACjD,kBAAkB,CAAC,EAAE,MAAM,CAAC;YAC5B,aAAa,CAAC,EAAE,aAAa,CAAC;YAC9B,qDAAqD;YACrD,aAAa,CAAC,EAAE,OAAO,CAAC;YACxB;;;;;;;eAOG;YACH,eAAe,CAAC,EAAE,yBAAyB,CAAC;SAC7C,CAAC;QACN,6DAA6D;QAC7D,QAAQ,CAAC,EAAE,OAAO,GAAG;YAAE,mBAAmB,CAAC,EAAE,OAAO,CAAA;SAAE,CAAC;QACvD;;;;WAIG;QACH,IAAI,CAAC,EAAE;YACL,yEAAyE;YACzE,SAAS,CAAC,EAAE,MAAM,CAAC;YACnB,6DAA6D;YAC7D,YAAY,CAAC,EAAE,MAAM,CAAC;YACtB,6EAA6E;YAC7E,kBAAkB,CAAC,EAAE,MAAM,CAAC;YAC5B,8CAA8C;YAC9C,eAAe,CAAC,EAAE,MAAM,CAAC;YACzB,yCAAyC;YACzC,UAAU,CAAC,EAAE,MAAM,CAAC;YACpB,gFAAgF;YAChF,+BAA+B,CAAC,EAAE,OAAO,CAAC;YAC1C,gFAAgF;YAChF,2BAA2B,CAAC,EAAE,OAAO,CAAC;YACtC,mEAAmE;YACnE,cAAc,CAAC,EAAE,OAAO,CAAC;YACzB,kEAAkE;YAClE,gBAAgB,CAAC,EAAE,OAAO,CAAC;YAC3B,oFAAoF;YACpF,wBAAwB,CAAC,EAAE,MAAM,CAAC;SACnC,CAAC;QACF,yEAAyE;QACzE,OAAO,CAAC,EACJ,OAAO,GACP;YACE,iEAAiE;YACjE,SAAS,CAAC,EAAE,OAAO,CAAC;YACpB,kFAAkF;YAClF,eAAe,CAAC,EAAE,MAAM,CAAC;YACzB,6EAA6E;YAC7E,aAAa,CAAC,EAAE,OAAO,CAAC;SACzB,CAAC;QACN,0FAA0F;QAC1F,kBAAkB,CAAC,EAAE,OAAO,GAAG;YAAE,aAAa,CAAC,EAAE,OAAO,CAAA;SAAE,CAAC;QAC3D,sFAAsF;QACtF,kBAAkB,CAAC,EAAE,OAAO,CAAC;QAC7B,6DAA6D;QAC7D,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,6FAA6F;QAC7F,SAAS,CAAC,EACN,OAAO,GACP;YACE,2DAA2D;YAC3D,iBAAiB,CAAC,EAAE,OAAO,CAAC;YAC5B,qEAAqE;YACrE,GAAG,CAAC,EAAE,UAAU,CAAC;YACjB,oEAAoE;YACpE,aAAa,CAAC,EAAE,mBAAmB,EAAE,CAAC;YACtC,oBAAoB,CAAC,EAAE,WAAW,CAAC;SACpC,CAAC;KACP,CAAC;CACH,CAAC;AAMF;;;;;;;GAOG;AACH;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE,WAAW,EACtB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,KAAK,CAAC,CA6FhB;AAiCD;;GAEG;AACH,mFAAmF;AACnF,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY;;;;;mBA9PzC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;mBACxB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;qBACtB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;iBACpC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;;;;;;;;;;;;;;;;;wBAmBjB,OAAO;oCACK,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;iCAC3B,MAAM;4BACX,aAAa;YAC7B,qDAAqD;4BACrC,OAAO;YACvB;;;;;;;eAOG;8BACe,yBAAyB;;;kCAGJ,OAAO;;;YAOlD,yEAAyE;wBAC7D,MAAM;YAClB,6DAA6D;2BAC9C,MAAM;YACrB,6EAA6E;iCACxD,MAAM;YAC3B,8CAA8C;8BAC5B,MAAM;YACxB,yCAAyC;yBAC5B,MAAM;YACnB,gFAAgF;8CAC9C,OAAO;YACzC,gFAAgF;0CAClD,OAAO;YACrC,mEAAmE;6BAClD,OAAO;YACxB,kEAAkE;+BAC/C,OAAO;YAC1B,oFAAoF;uCACzD,MAAM;;;YAM7B,iEAAiE;wBACrD,OAAO;YACnB,kFAAkF;8BAChE,MAAM;YACxB,6EAA6E;4BAC7D,OAAO;;;4BAGoB,OAAO;;;;;YASlD,2DAA2D;gCACvC,OAAO;YAC3B,qEAAqE;kBAC/D,UAAU;YAChB,oEAAoE;4BACpD,mBAAmB,EAAE;mCACd,WAAW;;;EA2M3C"}
@@ -21,6 +21,7 @@ import { IBLGradient } from '../environment/ibl-gradient.js';
21
21
  import { EnvironmentSystem } from '../environment/environment-system.js';
22
22
  import { EnvironmentRaycastSystem } from '../environment-raycast/environment-raycast.js';
23
23
  import { EnvironmentRaycastTarget } from '../environment-raycast/raycast-target.js';
24
+ import { GazeSystem } from '../gaze/gaze-system.js';
24
25
  import '../grab/index.js';
25
26
  import { InputSystem } from '../input/input-system.js';
26
27
  import { InputManager } from '../input/input-manager.js';
@@ -190,7 +191,7 @@ function registerApplicationComponents(world, components) {
190
191
  */
191
192
  /** @internal Exported for focused policy tests; not part of the package barrel. */
192
193
  function extractConfiguration(options) {
193
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6;
194
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7;
194
195
  const xrOptions = options.xr === false ? undefined : options.xr;
195
196
  const spatialUI = (_a = options.features) === null || _a === void 0 ? void 0 : _a.spatialUI;
196
197
  const legacyForwardHtmlEvents = typeof spatialUI === 'object' && spatialUI
@@ -220,11 +221,12 @@ function extractConfiguration(options) {
220
221
  features: {
221
222
  locomotion: (_u = (_t = options.features) === null || _t === void 0 ? void 0 : _t.locomotion) !== null && _u !== void 0 ? _u : false,
222
223
  grabbing: (_w = (_v = options.features) === null || _v === void 0 ? void 0 : _v.grabbing) !== null && _w !== void 0 ? _w : false,
223
- physics: (_y = (_x = options.features) === null || _x === void 0 ? void 0 : _x.physics) !== null && _y !== void 0 ? _y : false,
224
- sceneUnderstanding: (_0 = (_z = options.features) === null || _z === void 0 ? void 0 : _z.sceneUnderstanding) !== null && _0 !== void 0 ? _0 : false,
225
- environmentRaycast: (_2 = (_1 = options.features) === null || _1 === void 0 ? void 0 : _1.environmentRaycast) !== null && _2 !== void 0 ? _2 : false,
226
- camera: (_4 = (_3 = options.features) === null || _3 === void 0 ? void 0 : _3.camera) !== null && _4 !== void 0 ? _4 : false,
227
- spatialUI: (_6 = (_5 = options.features) === null || _5 === void 0 ? void 0 : _5.spatialUI) !== null && _6 !== void 0 ? _6 : true,
224
+ gaze: (_x = options.features) === null || _x === void 0 ? void 0 : _x.gaze,
225
+ physics: (_z = (_y = options.features) === null || _y === void 0 ? void 0 : _y.physics) !== null && _z !== void 0 ? _z : false,
226
+ sceneUnderstanding: (_1 = (_0 = options.features) === null || _0 === void 0 ? void 0 : _0.sceneUnderstanding) !== null && _1 !== void 0 ? _1 : false,
227
+ environmentRaycast: (_3 = (_2 = options.features) === null || _2 === void 0 ? void 0 : _2.environmentRaycast) !== null && _3 !== void 0 ? _3 : false,
228
+ camera: (_5 = (_4 = options.features) === null || _4 === void 0 ? void 0 : _4.camera) !== null && _5 !== void 0 ? _5 : false,
229
+ spatialUI: (_7 = (_6 = options.features) === null || _6 === void 0 ? void 0 : _6.spatialUI) !== null && _7 !== void 0 ? _7 : true,
228
230
  },
229
231
  };
230
232
  }
@@ -420,7 +422,7 @@ function registerAdditionalSystems(world) {
420
422
  world.registerComponent(AudioSource).registerSystem(AudioSystem);
421
423
  }
422
424
  async function registerFeatureSystems(world, config) {
423
- var _a;
425
+ var _a, _b, _c;
424
426
  const locomotion = config.features.locomotion;
425
427
  const locomotionEnabled = !!locomotion;
426
428
  const grabbing = config.features.grabbing;
@@ -461,6 +463,17 @@ async function registerFeatureSystems(world, config) {
461
463
  configData: world.input.canvasPointerEvents,
462
464
  });
463
465
  }
466
+ // GazeSystem activates when the gazeTracking feature flag is set (or its
467
+ // deprecated eyeTracking alias). Far rays remain active until tracked gaze
468
+ // is usable. Gating
469
+ // registration keeps the runtime cost out of apps that don't need gaze UI.
470
+ if (((_a = config.xr.features) === null || _a === void 0 ? void 0 : _a.gazeTracking) || ((_b = config.xr.features) === null || _b === void 0 ? void 0 : _b.eyeTracking)) {
471
+ const gaze = config.features.gaze;
472
+ const gazeOpts = gaze
473
+ ? Object.fromEntries(Object.entries(gaze).filter(([, v]) => v !== undefined))
474
+ : undefined;
475
+ world.registerSystem(GazeSystem, { priority: -4, configData: gazeOpts });
476
+ }
464
477
  if (grabbingEnabled) {
465
478
  const grabOpts = typeof grabbing === 'object' && grabbing
466
479
  ? Object.fromEntries(Object.entries({
@@ -519,7 +532,7 @@ async function registerFeatureSystems(world, config) {
519
532
  world.registerComponent(CameraSource).registerSystem(CameraSystem);
520
533
  }
521
534
  // WebXR composition layers (quad/cylinder)
522
- if (config.xr.enabled && ((_a = config.xr.features) === null || _a === void 0 ? void 0 : _a.layers)) {
535
+ if (config.xr.enabled && ((_c = config.xr.features) === null || _c === void 0 ? void 0 : _c.layers)) {
523
536
  world
524
537
  .registerComponent(XRQuadLayer)
525
538
  .registerComponent(XRCylinderLayer)