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

systems-utilities.mddocs/

Systems and Utilities

10 core systems managing rendering, lighting, cameras, and WebXR, plus comprehensive utility library with mathematical operations, device detection, and debugging tools.

Capabilities

System Registration

Register systems that manage global behavior and collections of entities.

/**
 * Register a new system
 * @param name - System name
 * @param definition - System definition object
 */
function registerSystem(name: string, definition: SystemDefinition): void;

interface SystemDefinition {
  /** Schema for system configuration */
  schema?: SchemaDefinition;
  /** Called when system is initialized */
  init?(): void;
  /** Called every frame */
  tick?(time: number, timeDelta: number): void;
  /** Called when system is removed */
  remove?(): void;
  /** Called when system starts playing */
  play?(): void;
  /** Called when system pauses */
  pause?(): void;
}

Usage Example:

// Register custom system
AFRAME.registerSystem('particle-system', {
  schema: {
    maxParticles: { default: 1000 },
    emissionRate: { default: 50 }
  },
  
  init: function() {
    this.particles = [];
    this.emitters = [];
  },
  
  tick: function(time, timeDelta) {
    // Update all particles
    this.updateParticles(timeDelta);
    this.emitParticles(timeDelta);
  }
});

Built-in Systems

Camera System

Manages camera entities and viewpoint switching.

interface CameraSystem {
  /** Currently active camera entity */
  activeCameraEl: AEntity;
  /** Set active camera */
  setActiveCamera(cameraEl: AEntity): void;
}

// Access camera system
const cameraSystem = document.querySelector('a-scene').systems.camera;

Light System

Manages lighting setup and shadow rendering.

interface LightSystem {
  /** Maximum number of lights */
  maxLights: number;
  /** Update light configuration */
  updateLights(): void;
}

Material System

Manages material instances and shader compilation.

interface MaterialSystem {
  /** Register material instance */
  registerMaterial(material: any): void;
  /** Unregister material instance */
  unregisterMaterial(material: any): void;
}

Geometry System

Manages geometry instances and caching.

interface GeometrySystem {
  /** Register geometry instance */
  registerGeometry(geometry: any): void;
  /** Unregister geometry instance */
  unregisterGeometry(geometry: any): void;
}

Renderer System

Core rendering system managing the Three.js renderer.

interface RendererSystem {
  /** Three.js renderer instance */
  renderer: THREE.WebGLRenderer;
  /** Render the scene */
  render(): void;
  /** Resize renderer */
  resize(): void;
}

WebXR System

Manages VR/AR session handling and WebXR API integration.

interface WebXRSystem {
  /** Check if VR is available */
  checkHeadsetConnected(): boolean;
  /** Get VR display */
  getVRDisplay(): VRDisplay | null;
  /** Enter VR mode */
  enterVR(): Promise<void>;
  /** Exit VR mode */
  exitVR(): Promise<void>;
}

Utility Functions

Coordinate Utilities

Parse and manipulate coordinate strings and vectors.

interface CoordinateUtils {
  /**
   * Parse coordinate string to object
   * @param value - Coordinate string like "1 2 3"
   * @returns Coordinate object with x, y, z properties
   */
  parse(value: string): { x: number; y: number; z: number };
  
  /**
   * Convert coordinate object to string
   * @param data - Coordinate object
   * @returns Coordinate string
   */
  stringify(data: { x: number; y: number; z: number }): string;
  
  /**
   * Check if value is a coordinate
   * @param value - Value to check
   * @returns True if value is coordinate-like
   */
  isCoordinates(value: any): boolean;
}

// Usage
const coords = AFRAME.utils.coordinates.parse('1 2 3'); // { x: 1, y: 2, z: 3 }
const str = AFRAME.utils.coordinates.stringify({ x: 1, y: 2, z: 3 }); // "1 2 3"

Device Detection

Detect device capabilities and platform information.

interface DeviceUtils {
  /** Check if running on mobile device */
  isMobile(): boolean;
  
  /** Check if running on iOS */
  isIOS(): boolean;
  
  /** Check if running in Oculus browser */
  isOculusBrowser(): boolean;
  
  /** Check if running in browser environment */
  isBrowserEnvironment: boolean;
  
  /** Check if device supports VR */
  checkHeadsetConnected(): boolean;
  
  /** Get device pixel ratio */
  getPixelRatio(): number;
}

// Usage
if (AFRAME.utils.device.isMobile()) {
  // Mobile-specific behavior
}

Debug Utilities

Debug logging and development tools.

/**
 * Create namespaced debug function
 * @param namespace - Debug namespace
 * @returns Debug logging function
 */
function debug(namespace: string): (message: string, ...args: any[]) => void;

// Usage
const debug = AFRAME.utils.debug('my-component');
debug('Component initialized');
debug('Data updated:', newData);

Object Utilities

Object manipulation and comparison utilities.

interface ObjectUtils {
  /**
   * Deep equality comparison
   * @param a - First object
   * @param b - Second object
   * @returns True if objects are deeply equal
   */
  deepEqual(a: any, b: any): boolean;
  
  /**
   * Calculate difference between objects
   * @param a - Original object
   * @param b - New object
   * @returns Object containing differences
   */
  diff(a: any, b: any): any;
  
  /**
   * Extend target object with source properties
   * @param target - Target object
   * @param source - Source object
   * @returns Extended target object
   */
  extend(target: any, source: any): any;
  
  /**
   * Deep extend target object with source properties
   * @param target - Target object
   * @param source - Source object
   * @returns Deep extended target object
   */
  extendDeep(target: any, source: any): any;
}

// Usage
const isEqual = AFRAME.utils.deepEqual(obj1, obj2);
const changes = AFRAME.utils.diff(oldData, newData);
const merged = AFRAME.utils.extend(target, source);

Function Binding

Function context binding utilities.

/**
 * Bind function to specific context
 * @param fn - Function to bind
 * @param ctx - Context object
 * @param args - Additional arguments
 * @returns Bound function
 */
function bind(fn: Function, ctx: any, ...args: any[]): Function;

// Usage
const boundFunction = AFRAME.utils.bind(this.handleClick, this);

Entity Utilities

Entity manipulation and query utilities.

interface EntityUtils {
  /**
   * Get entity by selector
   * @param selector - CSS selector
   * @param context - Search context element
   * @returns Entity element or null
   */
  getEntity(selector: string, context?: Element): AEntity | null;
  
  /**
   * Get all entities matching selector
   * @param selector - CSS selector
   * @param context - Search context element
   * @returns Array of entity elements
   */
  getEntities(selector: string, context?: Element): AEntity[];
  
  /**
   * Set entity data
   * @param entity - Entity element
   * @param componentName - Component name
   * @param data - Component data
   */
  setEntityData(entity: AEntity, componentName: string, data: any): void;
}

Material Utilities

Material creation and manipulation utilities.

interface MaterialUtils {
  /**
   * Create material from data
   * @param data - Material data
   * @returns Three.js material
   */
  createMaterial(data: any): THREE.Material;
  
  /**
   * Parse material string
   * @param str - Material string
   * @returns Parsed material data
   */
  parseMaterial(str: string): any;
}

Style Parser

Parse CSS-like style strings into objects.

interface StyleParser {
  /**
   * Parse style string to object
   * @param str - Style string like "color: red; opacity: 0.5"
   * @returns Parsed style object
   */
  parse(str: string): { [property: string]: any };
  
  /**
   * Convert style object to string
   * @param obj - Style object
   * @returns Style string
   */
  stringify(obj: { [property: string]: any }): string;
}

// Usage
const styles = AFRAME.utils.styleParser.parse('color: red; opacity: 0.5');
// { color: 'red', opacity: 0.5 }

Tracked Controls Utilities

Utilities for VR/AR controller handling.

interface TrackedControlsUtils {
  /**
   * Find matching controller
   * @param component - Controller component
   * @param idPrefix - Controller ID prefix
   * @returns Matching gamepad or null
   */
  findMatchingControllerWebVR(component: any, idPrefix: string): Gamepad | null;
  
  /**
   * Get controller for hand
   * @param hand - Hand identifier ('left' or 'right')
   * @returns Controller object or null
   */
  getControllerForHand(hand: 'left' | 'right'): any;
}

Pool Utilities

Object pooling for performance optimization.

interface PoolUtils {
  /**
   * Use object pool
   * @param Pool - Pool constructor
   * @param name - Pool name
   * @param definition - Pool definition
   */
  use(Pool: any, name: string, definition: any): void;
}

// Usage
AFRAME.utils.pool.use(THREE.Vector3, 'vector3', function() {
  return new THREE.Vector3();
});

Force Canvas Resize

Safari mobile-specific utility for canvas resizing.

/**
 * Force canvas resize on Safari mobile
 */
function forceCanvasResizeSafariMobile(): void;

Schema Utilities

Schema validation and property type system.

interface SchemaUtils {
  /**
   * Process schema validation
   * @param schema - Schema definition
   * @param data - Data to validate
   * @param debug - Enable debug mode
   * @returns Processed data
   */
  process(schema: SchemaDefinition, data: any, debug?: boolean): any;
  
  /**
   * Parse individual property
   * @param value - Property value
   * @param type - Property type
   * @returns Parsed value
   */
  parseProperty(value: any, type: string): any;
  
  /**
   * Stringify individual property
   * @param value - Property value
   * @param type - Property type
   * @returns Stringified value
   */
  stringifyProperty(value: any, type: string): string;
  
  /**
   * Parse property string
   * @param str - Property string
   * @param schema - Schema definition
   * @returns Parsed properties object
   */
  parseProperties(str: string, schema: SchemaDefinition): any;
  
  /**
   * Stringify properties object
   * @param data - Properties object
   * @param schema - Schema definition
   * @returns Properties string
   */
  stringifyProperties(data: any, schema: SchemaDefinition): string;
}

Property Types

Built-in property types for schema validation.

interface PropertyTypes {
  boolean: boolean;
  int: number;
  number: number;
  string: string;
  time: number; // Milliseconds
  vec2: { x: number; y: number };
  vec3: { x: number; y: number; z: number };
  vec4: { x: number; y: number; z: number; w: number };
  color: string; // Hex, RGB, HSL, or color name
  asset: string; // Asset URL or selector
  audio: string; // Audio asset reference
  map: string; // Texture map reference
  model: string; // 3D model reference
  selector: string; // CSS selector for single element
  selectorAll: string; // CSS selector for multiple elements
  src: string; // Source URL
  array: any[]; // Array of values
}

Usage Examples

Custom System

// Register a particle system
AFRAME.registerSystem('particles', {
  schema: {
    maxParticles: { default: 1000 },
    gravity: { default: -9.8 }
  },
  
  init: function() {
    this.particles = [];
    this.pool = [];
  },
  
  tick: function(time, timeDelta) {
    this.updateParticles(timeDelta / 1000);
    this.cullParticles();
  },
  
  createParticle: function(position, velocity) {
    let particle = this.pool.pop();
    if (!particle) {
      particle = { position: new THREE.Vector3(), velocity: new THREE.Vector3() };
    }
    
    particle.position.copy(position);
    particle.velocity.copy(velocity);
    particle.life = 1.0;
    
    this.particles.push(particle);
    return particle;
  }
});

Utility Usage

// Device detection
if (AFRAME.utils.device.isMobile()) {
  entityEl.setAttribute('material', 'shader', 'flat'); // Use flat shader on mobile
}

// Coordinate parsing
const position = AFRAME.utils.coordinates.parse('1 2 3');
entityEl.object3D.position.set(position.x, position.y, position.z);

// Debug logging
const debug = AFRAME.utils.debug('my-app');
debug('Entity created:', entityEl.id);

// Object comparison
const hasChanged = !AFRAME.utils.deepEqual(oldData, newData);
if (hasChanged) {
  component.update(oldData);
}

// Style parsing
const materialData = AFRAME.utils.styleParser.parse('color: red; metalness: 0.8');
entityEl.setAttribute('material', materialData);

Schema Validation

// Component with schema validation
AFRAME.registerComponent('custom-physics', {
  schema: {
    mass: { type: 'number', default: 1 },
    velocity: { type: 'vec3', default: { x: 0, y: 0, z: 0 } },
    friction: { type: 'number', default: 0.1, min: 0, max: 1 },
    material: { type: 'string', default: 'wood', oneOf: ['wood', 'metal', 'rubber'] }
  },
  
  init: function() {
    // this.data contains validated and parsed properties
    console.log('Mass:', this.data.mass);
    console.log('Velocity:', this.data.velocity);
  },
  
  update: function(oldData) {
    // Handle data changes
    if (this.data.mass !== oldData.mass) {
      this.updateMass();
    }
  }
});

Additional Utility Functions

A-Frame provides many additional utility functions for common development tasks.

Performance Utilities

/**
 * Throttle function calls to improve performance
 * @param fn - Function to throttle
 * @param interval - Minimum interval between calls (ms)
 * @param context - Optional context to bind function to
 * @returns Throttled function
 */
function throttle(fn: Function, interval: number, context?: any): Function;

/**
 * Throttle with trailing call to ensure final state convergence
 * @param fn - Function to throttle
 * @param interval - Minimum interval between calls (ms)  
 * @param context - Optional context to bind function to
 * @returns Throttled function
 */
function throttleLeadingAndTrailing(fn: Function, interval: number, context?: any): Function;

/**
 * Throttle using render loop timestamps for better performance
 * @param fn - Function to throttle (receives time, timeDelta)
 * @param interval - Minimum interval between calls (ms)
 * @param context - Optional context to bind function to
 * @returns Throttled function
 */
function throttleTick(fn: Function, interval: number, context?: any): Function;

/**
 * Debounce function calls - only execute after calls stop
 * @param fn - Function to debounce
 * @param wait - Wait time after last call (ms)
 * @param immediate - Call immediately on first invocation
 * @returns Debounced function
 */
function debounce(fn: Function, wait: number, immediate?: boolean): Function;

// Usage examples
const throttledUpdate = AFRAME.utils.throttle(updatePosition, 16); // ~60fps
const debouncedResize = AFRAME.utils.debounce(handleResize, 250);

String and Data Utilities

/**
 * Split string by delimiter with whitespace handling
 * @param str - String to split
 * @param delimiter - Delimiter character (default: ' ')
 * @returns Array of split strings
 */
function splitString(str: string, delimiter?: string): string[];

/**
 * Clone object using JSON serialization
 * @param obj - Object to clone
 * @returns Cloned object
 */
function clone(obj: any): any;

/**
 * Extract data attributes from DOM elements
 * @param el - DOM element
 * @param defaults - Default values object
 * @returns Extracted data object
 */
function getElData(el: Element, defaults?: any): any;

/**
 * Get URL query parameter value
 * @param name - Parameter name
 * @returns Parameter value or empty string
 */
function getUrlParameter(name: string): string;

// Usage examples
const parts = AFRAME.utils.splitString('1.5 2.0 3.5', ' '); // ['1.5', '2.0', '3.5']
const copy = AFRAME.utils.clone({ x: 1, y: 2 });
const config = AFRAME.utils.getElData(element, { width: 100, height: 50 });
const debug = AFRAME.utils.getUrlParameter('debug');

Environment Detection

/**
 * Check if running in iframe context
 * @returns True if in iframe
 */
function isIframed(): boolean;

/**
 * Find all scene elements in DOM tree
 * @param el - Root element to search from
 * @returns Array of scene elements
 */
function findAllScenes(el: Element): Element[];

/**
 * Check if keyboard event should be captured for shortcuts
 * @param event - Keyboard event
 * @returns True if event should be captured
 */
function shouldCaptureKeyEvent(event: KeyboardEvent): boolean;

// Usage examples
if (AFRAME.utils.isIframed()) {
  console.log('Running in iframe');
}

const scenes = AFRAME.utils.findAllScenes(document.body);

Canvas and Mobile Utilities

/**
 * Force canvas resize on Safari mobile to fix rendering issues
 * @param canvas - Canvas element to resize
 */
function forceCanvasResizeSafariMobile(canvas: HTMLCanvasElement): void;

// Usage
AFRAME.utils.forceCanvasResizeSafariMobile(scene.canvas);

Asset Loading Utilities

interface SrcLoaderUtils {
  /**
   * Parse src attribute for asset references
   * @param src - Source string (URL or asset reference)
   * @returns Parsed source information
   */
  parseSrc(src: string): any;
  
  /**
   * Validate asset source
   * @param src - Source to validate
   * @returns True if valid
   */
  validateSrc(src: string): boolean;
}

// Usage
const srcInfo = AFRAME.utils.srcLoader.parseSrc('#myTexture');