A NeedleXRController wraps a connected XRInputDevice that is either a physical controller or a hand
You can access specific buttons using getButton and getStick
To get spatial data in rig space (position, rotation) use the gripPosition, gripQuaternion, rayPosition and rayQuaternion properties
To get spatial data in world space use the gripWorldPosition, gripWorldQuaternion, rayWorldPosition and rayWorldQuaternion properties
Inputs will also be emitted as pointer events on this.context.input - so you can receive controller inputs on objects using the appropriate input events on your components (e.g. onPointerDown, onPointerUp etc) - use the pointerType property to check if the event is from a controller or not

Implements

Constructors

Properties

emitEvents: boolean = true

When enabled the controller will create input events in the Needle Engine input system (e.g. when a button is pressed or the controller is moved)
You can disable this if you don't want inputs to go through the input system but be aware that this will result in onPointerDown component callbacks to not be invoked anymore for this XRController

emitPointerDownEvent: boolean = true

When enabled the controller will automatically emit pointer down events to the Needle Engine Input System.

true
emitPointerMoveEvent: boolean = true

When enabled the controller will automatically emit pointer move events to the Needle Engine Input System.

true
emitPointerUpEvent: boolean = true

When enabled the controller will automatically emit pointer up events to the Needle Engine Input System.

true
index: number = 0

the input source index

inputSource: XRInputSource
model: null | Object3D<Object3DEventMap> = null

Assigned the model that you use for rendering. This can be used as a hint for other components

pointerMoveAngleThreshold: number = 0.05

The angle threshold for pointer move events. This value is in radians.

0.05
pointerMoveDistanceThreshold: number = 0.03

The distance threshold for pointer move events. This value is in units in rig space

0.03

the Needle XR Session

Accessors

  • get connected(): boolean
  • Is the controller still connected?

    Returns boolean

  • get gamepad(): undefined | Gamepad
  • the input source gamepad giving raw access to the gamepad values
    You should usually use the getButton and getStick methods instead to get access to named buttons and sticks

    Returns undefined | Gamepad

  • get gripSpace(): undefined | XRSpace
  • shorthand for inputSource.gripSpace

    Returns undefined | XRSpace

  • get gripWorldPosition(): Vector3
  • Controller grip position in worldspace

    Returns Vector3

  • get handWristDotUp(): undefined | number
  • The dot product of the hand palm with the up vector. This is a number between -1 and 1, where 1 means the palm is directly up and -1 means the palm is directly down (upside down). This value is undefined if there's no hand

    Returns undefined | number

  • get hasHitTestSource(): undefined | XRTransientInputHitTestSource
  • Returns undefined | XRTransientInputHitTestSource

  • get hasSelectEvent(): boolean
  • Returns boolean

  • get isHand(): boolean
  • Returns boolean

    true if this is a hand (otherwise this is a controller)

  • get isHandUpsideDown(): boolean
  • Returns boolean

    true if the hand is upside down

  • get isLeft(): boolean
  • is left side. shorthand for side === 'left'

    Returns boolean

  • get isRight(): boolean
  • is right side. shorthand for side === 'right'

    Returns boolean

  • get isStylus(): boolean
  • is XR stylus, e.g. Logitech MX Ink

    Returns boolean

  • get isTeleportGesture(): undefined | boolean
  • Returns undefined | boolean

    true if the hand is upside down and we got a pinch down event this frame.

  • get isTracking(): boolean
  • Returns boolean

  • get layout(): undefined | InputDeviceLayout
  • The device input layout

    Returns undefined | InputDeviceLayout

  • get object(): IGameObject
  • The controller object space.
    You can use it to attach objects to the controller.
    Children will be automatically detached and put into the scene when the controller disconnects

    Returns IGameObject

  • get profiles(): string[]
  • The input source profiles

    Returns string[]

  • get ray(): Ray
  • The controller ray in worldspace

    Returns Ray

  • get rayWorldPosition(): Vector3
  • Controller ray position in worldspace (this value is calculated once per frame by default - call updateRayWorldPosition to force an update)

    Returns Vector3

  • get rayWorldQuaternion(): Quaternion
  • Controller ray rotation in wordspace (this value is calculated once per frame by default - call updateRayWorldQuaternion to force an update)

    Returns Quaternion

  • get side(): XRHandedness
  • If the controller if held in the left or right hand (or if it's a left or right hand)

    Returns XRHandedness

  • get targetRayMode(): XRTargetRayMode
  • shorthand for inputSource.targetRayMode

    Returns XRTargetRayMode

  • get targetRaySpace(): XRSpace
  • shorthand for inputSource.targetRaySpace

    Returns XRSpace

Methods

  • Make sure to cancel the hittest source once it's not needed anymore

    Returns void

  • Get a gesture state

    Parameters

    • key: "pinch"

    Returns null | NeedleGamepadButton

  • Get the hand joint pose from the current XRFrame. Results are cached for a frame to avoid calling getJointPose multiple times

    Parameters

    • joint: XRJointSpace
    • Optionalframe: XRFrame

    Returns undefined | null | XRJointPose

  • Perform a hit test against the XR planes or meshes. shorthand for xr.getHitTest(controller)

    Returns null | NeedleXRHitTestResult

    the hit test result (with position and rotation in worldspace) or null if no hit was found

  • The XRTransientInputHitTestSource can be used to perform hit tests with the controller ray against the real world.
    see https://developer.mozilla.org/en-US/docs/Web/API/XRSession/requestHitTestSourceForTransientInput for more information Requires the hit-test feature to be enabled in the XRSession

    NOTE: The hit test source should be cancelled once it's not needed anymore. Call cancelHitTestSource to do this

    Returns undefined | XRTransientInputHitTestSource

  • returns the URL of the default controller model

    Returns Promise<null | string>

  • Get the pointer id for a specific button of this input device.
    This is useful if you want to check if a button (e.g. trigger) is currently being in use which can be queried on the inputsystem.

    Parameters

    • button: number

    Returns number

    the pointer id for the button or undefined if the button is not supported

    const pointerId = controller.getPointerId("primary");
    if (pointerId !== undefined) {
    const isUsed = this.context.input.getPointerUsed(pointerId);
    console.log(controller.side, "used?", isUsed);
    }
  • Parameters

    • button: NeedleXRControllerButtonName

    Returns undefined | number

  • Called when the input source disconnects

    Returns void

  • Parameters

    • _evt: any

    Returns void

  • Returns void

  • Parameters

    • frame: XRFrame

    Returns void

  • Recalculates the ray world position

    Returns void

  • Recalculates the ray world quaternion

    Returns void