or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

built-in-components.mdcore-entity-system.mdgeometry-materials.mdindex.mdprimitive-elements.mdsystems-utilities.mdvr-ar-controllers.md
tile.json

vr-ar-controllers.mddocs/

VR/AR Controllers

20+ VR/AR controller components supporting major headsets and platforms including Oculus, HTC Vive, Windows Mixed Reality, and hand tracking.

Capabilities

Hand Controls

Generic hand tracking and controller management.

interface HandControlsComponent {
  hand: 'left' | 'right'; // Which hand to track
  handModelStyle: 'lowPoly' | 'highPoly' | 'toon'; // Hand model style
  color: string; // Hand model color
  handModelSrc: string; // Custom hand model URL
}

Usage Examples:

<a-entity hand-controls="hand: left; handModelStyle: lowPoly; color: #ffcccc"></a-entity>
<a-entity hand-controls="hand: right; handModelStyle: highPoly"></a-entity>

Tracked Controls (Base)

Base component for all tracked controller types.

interface TrackedControlsComponent {
  controller: number; // Controller index
  id: string; // Controller ID pattern to match
  hand: 'left' | 'right'; // Controller hand
  idPrefix: string; // Controller ID prefix
  orientationOffset: string; // Orientation offset "x y z"
  positional: boolean; // Enable positional tracking
  rotationOffset: string; // Rotation offset "x y z"
  armModel: boolean; // Enable arm model for 3DOF controllers
}

Oculus Touch Controls

Oculus Rift and Quest Touch controller support.

interface OculusTouchControlsComponent {
  hand: 'left' | 'right'; // Controller hand
  model: boolean; // Show controller model (default: true)
  orientationOffset: string; // Orientation offset
  rotationOffset: string; // Rotation offset
}

Usage Examples:

<a-entity oculus-touch-controls="hand: left"></a-entity>
<a-entity oculus-touch-controls="hand: right; model: false"></a-entity>

<!-- Button and axis events -->
<a-entity 
  oculus-touch-controls="hand: right"
  listeners="
    triggerdown: onTriggerDown;
    triggerup: onTriggerUp;
    gripdown: onGripDown;
    thumbstickmoved: onThumbstickMoved;
    xbuttondown: onXButtonDown;
    ybuttondown: onYButtonDown;
  ">
</a-entity>

HTC Vive Controls

HTC Vive controller and wand support.

interface ViveControlsComponent {
  hand: 'left' | 'right'; // Controller hand
  model: boolean; // Show controller model
  orientationOffset: string; // Orientation offset
  rotationOffset: string; // Rotation offset
}

Usage Examples:

<a-entity vive-controls="hand: left"></a-entity>
<a-entity vive-controls="hand: right"></a-entity>

<!-- Vive controller events -->
<a-entity
  vive-controls="hand: right"
  listeners="
    triggerdown: onTriggerDown;
    trackpaddown: onTrackpadDown;
    trackpadtouchstart: onTrackpadTouchStart;
    menudown: onMenuDown;
    gripdown: onGripDown;
  ">
</a-entity>

Windows Mixed Reality Controls

Windows Mixed Reality motion controller support.

interface WindowsMotionControlsComponent {
  hand: 'left' | 'right'; // Controller hand
  model: boolean; // Show controller model
  hideDisconnected: boolean; // Hide when disconnected
}

Usage Examples:

<a-entity windows-motion-controls="hand: left"></a-entity>
<a-entity windows-motion-controls="hand: right; hideDisconnected: true"></a-entity>

Mobile VR Controls

Mobile VR headset controller support.

Daydream Controls

Google Daydream controller support.

interface DaydreamControlsComponent {
  hand: 'left' | 'right'; // Controller hand (default: 'right')
  model: boolean; // Show controller model
  armModel: boolean; // Enable arm model
  orientationOffset: string; // Orientation offset
  rotationOffset: string; // Rotation offset
}

Gear VR Controls

Samsung Gear VR controller support.

interface GearVRControlsComponent {
  hand: 'left' | 'right'; // Controller hand (default: 'right')
  model: boolean; // Show controller model
  armModel: boolean; // Enable arm model
  orientationOffset: string; // Orientation offset
  rotationOffset: string; // Rotation offset
}

Oculus Go Controls

Oculus Go controller support.

interface OculusGoControlsComponent {
  hand: 'left' | 'right'; // Controller hand (default: 'right')
  model: boolean; // Show controller model
  armModel: boolean; // Enable arm model
  orientationOffset: string; // Orientation offset
  rotationOffset: string; // Rotation offset
}

Usage Examples:

<!-- Mobile VR controllers -->
<a-entity daydream-controls="hand: right; armModel: true"></a-entity>
<a-entity gearvr-controls="hand: right; model: true"></a-entity>
<a-entity oculus-go-controls="hand: right"></a-entity>

Advanced VR Controllers

Valve Index Controls

Valve Index Knuckles controller support with finger tracking.

interface ValveIndexControlsComponent {
  hand: 'left' | 'right'; // Controller hand
  model: boolean; // Show controller model
  orientationOffset: string; // Orientation offset
  rotationOffset: string; // Rotation offset
}

Magic Leap Controls

Magic Leap One controller support.

interface MagicLeapControlsComponent {
  hand: 'left' | 'right'; // Controller hand
  model: boolean; // Show controller model
  orientationOffset: string; // Orientation offset
  rotationOffset: string; // Rotation offset
}

HP Mixed Reality Controls

HP Reverb and other HP Mixed Reality controller support.

interface HPMixedRealityControlsComponent {
  hand: 'left' | 'right'; // Controller hand
  model: boolean; // Show controller model
  hideDisconnected: boolean; // Hide when disconnected
}

Usage Examples:

<a-entity valve-index-controls="hand: left"></a-entity>
<a-entity valve-index-controls="hand: right"></a-entity>

<a-entity magicleap-controls="hand: right"></a-entity>

<a-entity hp-mixed-reality-controls="hand: left"></a-entity>
<a-entity hp-mixed-reality-controls="hand: right"></a-entity>

Generic Tracked Controller

Fallback component for unknown or generic tracked controllers.

interface GenericTrackedControllerControlsComponent {
  hand: 'left' | 'right'; // Controller hand
  model: boolean; // Show controller model
  orientationOffset: string; // Orientation offset
  rotationOffset: string; // Rotation offset
}

Hand Tracking Controls

Native hand tracking support for devices with hand tracking capabilities.

interface HandTrackingControlsComponent {
  hand: 'left' | 'right'; // Which hand to track
  modelStyle: 'mesh' | 'dots' | 'boxes'; // Hand visualization style
  modelColor: string; // Hand model color
}

Usage Examples:

<a-entity hand-tracking-controls="hand: left; modelStyle: mesh"></a-entity>
<a-entity hand-tracking-controls="hand: right; modelStyle: dots; modelColor: #ff6666"></a-entity>

Laser Controls

Laser pointer interaction for VR controllers.

interface LaserControlsComponent {
  hand: 'left' | 'right'; // Controller hand
  model: boolean; // Show controller model
  defaultModel: boolean; // Use default model
  defaultModelColor: string; // Default model color
  defaultModelOpacity: number; // Default model opacity
}

Usage Examples:

<a-entity laser-controls="hand: right"></a-entity>
<a-entity laser-controls="hand: left; defaultModelColor: red"></a-entity>

<!-- With raycaster for interaction -->
<a-entity 
  laser-controls="hand: right"
  raycaster="objects: .clickable; showLine: true">
</a-entity>

Controller Events

All controller components emit standardized events for button presses, axis changes, and connection status.

Common Button Events

// Button press events (fired when button is pressed down)
interface ButtonDownEvents {
  'triggerdown': CustomEvent; // Primary trigger
  'gripdown': CustomEvent; // Grip/squeeze button
  'trackpaddown': CustomEvent; // Trackpad click
  'thumbstickdown': CustomEvent; // Thumbstick click
  'menudown': CustomEvent; // Menu button
  'systemdown': CustomEvent; // System button
}

// Button release events (fired when button is released)
interface ButtonUpEvents {
  'triggerup': CustomEvent;
  'gripup': CustomEvent;
  'trackpadup': CustomEvent;
  'thumbstickup': CustomEvent;
  'menuup': CustomEvent;
  'systemup': CustomEvent;
}

// Touch events (for touch-sensitive buttons)
interface TouchEvents {
  'trackpadtouchstart': CustomEvent;
  'trackpadtouchend': CustomEvent;
  'thumbsticktouchstart': CustomEvent;
  'thumbsticktouchend': CustomEvent;
}

Axis Events

// Axis movement events
interface AxisEvents {
  'trackpadmoved': CustomEvent<{ x: number; y: number }>; // Trackpad axis
  'thumbstickmoved': CustomEvent<{ x: number; y: number }>; // Thumbstick axis
  'triggerchanged': CustomEvent<{ value: number }>; // Trigger value (0-1)
  'gripchanged': CustomEvent<{ value: number }>; // Grip value (0-1)
}

Connection Events

// Controller connection events
interface ConnectionEvents {
  'controllerconnected': CustomEvent; // Controller connected
  'controllerdisconnected': CustomEvent; // Controller disconnected
}

Platform-Specific Button Mappings

Oculus Touch

// Oculus Touch specific events
interface OculusTouchEvents {
  // Left controller
  'xbuttondown': CustomEvent; // X button
  'xbuttonup': CustomEvent;
  'ybuttondown': CustomEvent; // Y button
  'ybuttonup': CustomEvent;
  
  // Right controller  
  'abuttondown': CustomEvent; // A button
  'abuttonup': CustomEvent;
  'bbuttondown': CustomEvent; // B button
  'bbuttonup': CustomEvent;
  
  // Touch events
  'xbuttontouchstart': CustomEvent;
  'xbuttontouchend': CustomEvent;
  'ybuttontouchstart': CustomEvent;
  'ybuttontouchend': CustomEvent;
  'abuttontouchstart': CustomEvent;
  'abuttontouchend': CustomEvent;
  'bbuttontouchstart': CustomEvent;
  'bbuttontouchend': CustomEvent;
}

HTC Vive

// Vive controller specific events
interface ViveControllerEvents {
  'trackpaddown': CustomEvent; // Trackpad click
  'trackpadup': CustomEvent;
  'trackpadtouchstart': CustomEvent; // Trackpad touch
  'trackpadtouchend': CustomEvent;
  'trackpadmoved': CustomEvent<{ x: number; y: number }>;
  'menudown': CustomEvent; // Menu button
  'menuup': CustomEvent;
}

Usage Examples

Basic Controller Setup

<a-scene>
  <!-- VR camera rig -->
  <a-entity id="cameraRig" position="0 1.6 3">
    <a-camera look-controls wasd-controls></a-camera>
    
    <!-- Oculus Touch controllers -->
    <a-entity oculus-touch-controls="hand: left" id="leftController"></a-entity>
    <a-entity oculus-touch-controls="hand: right" id="rightController"></a-entity>
    
    <!-- Vive controllers (alternative) -->
    <!-- <a-entity vive-controls="hand: left"></a-entity> -->
    <!-- <a-entity vive-controls="hand: right"></a-entity> -->
  </a-entity>
  
  <!-- Scene content -->
  <a-box class="clickable" position="0 0.5 -3" color="red"></a-box>
</a-scene>

Interactive Controller Events

<a-entity 
  id="rightController"
  oculus-touch-controls="hand: right"
  raycaster="objects: .clickable; showLine: true">
</a-entity>

<script>
  const rightController = document.querySelector('#rightController');
  
  // Button press handlers
  rightController.addEventListener('triggerdown', function(evt) {
    console.log('Trigger pressed');
    // Perform action like shooting or grabbing
  });
  
  rightController.addEventListener('abuttondown', function(evt) {
    console.log('A button pressed');
    // Toggle menu or perform secondary action
  });
  
  rightController.addEventListener('thumbstickmoved', function(evt) {
    const { x, y } = evt.detail;
    console.log('Thumbstick moved:', x, y);
    // Use for locomotion or navigation
  });
  
  // Interaction events from raycaster
  rightController.addEventListener('raycaster-intersection', function(evt) {
    const intersectedEl = evt.detail.els[0];
    console.log('Pointing at:', intersectedEl);
    intersectedEl.setAttribute('material', 'color', 'blue');
  });
  
  rightController.addEventListener('raycaster-intersection-cleared', function(evt) {
    const clearedEl = evt.detail.clearedEls[0];
    if (clearedEl) {
      clearedEl.setAttribute('material', 'color', 'red');
    }
  });
</script>

Hand Tracking Example

<a-scene>
  <!-- Hand tracking entities -->
  <a-entity 
    hand-tracking-controls="hand: left"
    id="leftHand">
  </a-entity>
  
  <a-entity 
    hand-tracking-controls="hand: right" 
    id="rightHand">
  </a-entity>
  
  <!-- Interactable objects -->
  <a-box 
    class="grabbable"
    position="0 1 -2" 
    grabbable>
  </a-box>
</a-scene>

<script>
  // Hand tracking events
  document.querySelector('#rightHand').addEventListener('pinchstarted', function(evt) {
    console.log('Pinch gesture started');
  });
  
  document.querySelector('#rightHand').addEventListener('pinchended', function(evt) {
    console.log('Pinch gesture ended');
  });
</script>

Laser Pointer Interaction

<a-entity 
  id="rightLaser"
  laser-controls="hand: right"
  raycaster="objects: .clickable; showLine: true; lineColor: red; lineOpacity: 0.75">
</a-entity>

<!-- Clickable objects -->
<a-box class="clickable" position="-2 1 -3" color="blue"></a-box>
<a-sphere class="clickable" position="0 1 -3" color="green"></a-sphere>
<a-cylinder class="clickable" position="2 1 -3" color="yellow"></a-cylinder>

<script>
  const laser = document.querySelector('#rightLaser');
  
  laser.addEventListener('triggerdown', function(evt) {
    // Get the intersected element
    const raycaster = laser.components.raycaster;
    const intersection = raycaster.intersectedEls[0];
    
    if (intersection) {
      // Animate clicked object
      intersection.setAttribute('animation', {
        property: 'scale',
        to: '1.2 1.2 1.2',
        dur: 200,
        dir: 'alternate',
        loop: 1
      });
    }
  });
</script>