# Scenery Scripting -- API Reference (v0.2.0) Complete JavaScript scripting API for building AR experiences in Scenery: every type, method, and signature. Sibling bundle (concepts, how-to, worked examples): https://scenery.app/docs/scripting/guide/llms-full.txt Global instances available in every script without declaration: - `experience` -- `Experience` - `scene` -- `Scene` - `environment` -- `Environment` - `http` -- `HTTP client (promisified). Methods: get(url, options?), post(url, body, options?), request(url, options). All return Promise<{status, data}>` - `websocket` -- `WebSocket client. Methods: connect(url, options?) returns WebSocket` - `httpClient` -- `HTTPClient (low-level, callback-based -- prefer `http` instead)` - `webSocketManager` -- `WebSocketManager (low-level -- prefer `websocket` instead)` Any docs page is also available as raw markdown by appending `.md` -- e.g. https://scenery.app/docs/scripting/api/mesh.md, https://scenery.app/docs/scripting/guide/examples.md. Authoritative for runtime v0.2.0. If an API is not listed here, it does not exist in this version -- do not invent signatures. --- # ARX Scripting API Reference Auto-generated documentation for the ARX scripting runtime. ## Table of Contents - [Swift JSExport APIs](#swift-jsexport-apis) - [Runtime Classes](#runtime-classes) - [Runtime Functions](#runtime-functions) - [Static Extensions](#static-extensions) ## Swift JSExport APIs ### `ARRaycastResult` Result from scene.raycastAR() when ray intersects real-world surfaces **Properties:** - `worldTransform`: `Transform` - World transform matrix at hit location - `target`: `string` - Type of target that was hit: "existingPlaneGeometry", "existingPlaneInfinite", "estimatedPlane" - `targetAlignment`: `string` - Surface alignment: "horizontal", "vertical", "any" - `anchor`: `AnchorData` - Associated plane anchor if hit was on a tracked plane (nil for estimated surfaces) ### `Action` **Properties:** - `id`: `string` - `kind`: `string` **Methods:** ### `AnchorData` **Properties:** - `id`: `string` - Unique identifier for this anchor - `kind`: `string` - Anchor type: "plane", "hand", "face", "image", "world", "geo", "mesh" - `name`: `string` - Optional name for this anchor - `worldTransform`: `Transform` - World-space transform matrix for anchor position and orientation - `isTracked`: `boolean` - Whether this anchor is currently being tracked (image, face, hand anchors) - `alignment`: `string` - Plane alignment: "horizontal" or "vertical" (plane anchors only) - `classification`: `string` - Plane classification: "floor", "ceiling", "wall", "table", "seat", "window", "door" (plane anchors only) - `width`: `number` - Plane width in meters (plane anchors only) - `height`: `number` - Plane height in meters (plane anchors only) - `referenceImageName`: `string` - Reference image name from ARReferenceImage (image anchors only) - `estimatedScaleFactor`: `number` - Estimated scale factor of detected image (image anchors only) - `chirality`: `string` - Hand chirality: "left" or "right" (hand anchors only, visionOS) - `joints`: `Array` - Hand joint transforms by name - `orderedJointTransforms`: `Array` - Ordered joint transforms for skeletal animation (hand anchors only) - `blendShapes`: `Array` - Blend shape coefficients for facial expressions - `leftEyeTransform`: `Transform` - Left eye transform in face coordinate space (face anchors only) - `rightEyeTransform`: `Transform` - Right eye transform in face coordinate space (face anchors only) - `lookAtPoint`: `Vector3` - Estimated gaze direction point in face coordinate space (face anchors only) - `latitude`: `number` - Geographic latitude in degrees (geo anchors only, iOS) - `longitude`: `number` - Geographic longitude in degrees (geo anchors only, iOS) - `altitude`: `number` - Altitude in meters (geo anchors only, iOS) ### `AudioStream` Streaming audio player for real-time audio playback Used for continuous audio streams like OpenAI Realtime API **Properties:** - `isDrained`: `boolean` - Whether the audio buffer has finished playing Use this to wait for playback to complete before resuming microphone **Methods:** - `append(base64: string)` → `void` - Append base64-encoded audio data to the stream buffer - `stop()` → `void` - Stop playback and release resources ### `BoundingBox` Axis-aligned bounding box for collision and visibility testing **Properties:** - `min`: `Vector3` - Minimum corner of the box - `max`: `Vector3` - Maximum corner of the box - `center`: `Vector3` - Center point of the box - `extents`: `Vector3` - Half-size extents from center - `boundingRadius`: `number` - Radius of bounding sphere - `isEmpty`: `boolean` - Whether the box has zero volume **Methods:** - `create(min: Vector3, max: Vector3)` → `BoundingBox` - Create a bounding box from min/max corners - `createEmpty()` → `BoundingBox` - Create an empty bounding box - `contains(box: BoundingBox, point: Vector3)` → `boolean` - Check if a point is inside the box - `containsBox(box1: BoundingBox, box2: BoundingBox)` → `boolean` - Check if one box fully contains another - `intersects(box1: BoundingBox, box2: BoundingBox)` → `boolean` - Check if two boxes intersect **Runtime Extensions:** - `contains(point: Vector3)` → `boolean` - Check if point is inside bounding box - `containsBox(other: BoundingBox)` → `boolean` - Check if another bounding box is fully contained - `intersects(other: BoundingBox)` → `boolean` - Check if bounding boxes intersect ### `CollisionCastHit` Result from scene.raycast() when ray intersects an entity or scene mesh **Properties:** - `type`: `string` - Hit type - "representation" or "sceneMesh" - `representation`: `RepresentationEntity` - The entity that was hit (nil for scene mesh hits) - `position`: `Vector3` - World-space position where ray hit the entity - `normal`: `Vector3` - Surface normal at hit point - `distance`: `number` - Distance from ray origin to hit point - `shapeIndex`: `number | null` - Index of the shape within the entity that was hit (iOS 18+) - `faceIndex`: `number | null` - Index of the triangle face that was hit (iOS 18+, mesh collisions only) - `uv`: `Vector2` - Barycentric UV coordinate on the triangle (iOS 18+, mesh collisions only) ### `Color` RGBA color with components in 0-1 range **Properties:** - `r`: `number` - Red component (0-1) - `g`: `number` - Green component (0-1) - `b`: `number` - Blue component (0-1) - `a`: `number` - Alpha component (0-1) **Methods:** - `create(r: number, g: number, b: number, a: number)` → `Color` - Create a color from RGBA values - `lerp(c1: Color, c2: Color, t: number)` → `Color` - Linearly interpolate between two colors **Runtime Extensions:** - `lerp(other: Color, t: number)` → `Color` - Linearly interpolate to another color ### `Buffer` Raw GPU buffer wrapping a typed scratch region for compute kernels. Use for things meshes + textures don't model: atomic counters, lookup tables (e.g. marching cubes' triangle / edge tables), per-particle state, scratch arrays between kernel passes. **Properties:** - `id`: `string` - Stable handle id assigned at construction. Surfaces in the scripting manager's live-set; used by `destroy()` to release the experience-lifetime retention. - `elementType`: `string` - Element type as a scripting string (`"float32"`, `"uint32"`, `"uint8"`, `"atomic_uint"`). - `length`: `number` - Number of elements (not bytes). - `byteLength`: `number` - Total byte length -- `length * elementSize`. **Methods:** - `readSync()` → `any` - Read the buffer contents back to JS as a TypedArray. Triggers a command-buffer wait if a compute dispatch is in flight against the buffer -- use sparingly (typical pattern: read atomic counters after dispatch to size a downstream draw call). - `writeSync(data: any)` → `void` - Write a TypedArray's contents into the buffer (CPU → GPU). Useful for seeding lookup tables, atomic counter resets, particle initial state. Length must match the buffer's declared element count; shorter writes leave the tail untouched. - `destroy()` → `void` - Release the underlying GPU buffer immediately. ### `Kernel` Opaque handle to a compiled GPU compute kernel. Returned by `Kernel.fromSource(...)` / `Kernel.fromAsset(...)`. Two dispatch entry points: `kernel.run({...})` for standalone compute (texture / buffer I/O, no mesh involvement) and `mesh.runCompute(kernel, options)` when the kernel writes mesh-attribute buffers. **Properties:** - `id`: `string` - Stable handle id assigned at construction. Surfaces in the scripting manager's live-set; used by `destroy()` to release the experience-lifetime retention. - `functionName`: `string` - Display name of the kernel's entry-point function. **Methods:** - `destroy()` → `void` - Release the kernel's GPU resources (compiled library + pipeline state) immediately. Use in hot loops where JSC's non-deterministic GC would otherwise stretch the lifetime. Normal scripts don't need to call this -- ARC handles cleanup when the kernel goes out of scope. Calling `mesh.runCompute(...)` or `kernel.run(...)` against a destroyed kernel warns and aborts the dispatch. - `run(options: any)` → `void` - Dispatch the kernel against textures and / or `Buffer` handles -- no mesh involvement. Use for compute passes that don't write mesh attribute buffers (texture generation, particle simulation pre-pass, any "pure compute" kernel that doesn't displace geometry). ### `Mesh` Scriptable dynamic mesh with CPU-driven vertex and index updates. **Properties:** - `vertexCapacity`: `number` - Maximum vertex count the mesh was allocated for. Read-only -- the underlying buffer is sized at creation. To grow, create a new mesh. - `indexCapacity`: `number` - Maximum index count the mesh was allocated for. - `partCount`: `number` - Number of parts (draw ranges) on the mesh. - `drawCount`: `number` - Convenience getter/setter for single-part meshes. - `attributes`: `any` - Read-only summary of the mesh's attribute layout: an object keyed by attribute name with `{ semantic, format, storage }` fields. Useful for introspection ("does this mesh have a 'speed' attribute?") and for cross-engine devs who reach for `geometry.attributes` reflexively. **Methods:** - `writeVertices(name: string, vertexOffset: number, data: any)` → `void` - Write packed elements of a single named attribute. - `writeIndices(indexOffset: number, data: any)` → `void` - Write indices starting at slot `indexOffset`. - `updatePart(partIndex: number, options: any)` → `void` - Update a part's metadata. - `replaceParts(parts: any)` → `void` - Replace the entire parts list. Use for dynamic-part-count meshes where each frame's GPU dispatch produces a variable triangle count (marching cubes, fluid surface, voxel terrain). Pair with an atomic counter in `outputBuffers` to size the part: - `setBounds(bounds: any)` → `void` - Update the bounds of part 0. - `recomputeBounds(partIndex: number)` → `any` - Recompute and apply min/max bounds for a part from its written vertex positions. - `runCompute(kernel: any, options: any)` → `void` - Dispatch a compute kernel against this mesh's `storage: compute` attribute buffers, optionally the index buffer, plus arbitrary input / output buffers and textures. The renderer waits on the dispatch's command buffer before sampling the mesh. ### `TextureBinding` Marker token returned by `texture.read` / `texture.write`. Carries the backing texture and the role so dispatch knows whether to bind the texture as a kernel read source or write target. **Methods:** ### `Texture` A GPU texture created and managed at runtime. Construct one from an image or video source (`Texture.image(...)`, `Texture.video(...)`), the live camera feed (`Texture.cameraFeed()`), or a compute kernel that writes its pixels (`Texture.compute(...)`). **Properties:** - `id`: `string` - Texture id -- matches `dynamicTexture.id`. Stable for the lifetime of the texture; surfaces in material `TextureReference.dynamic` references. - `width`: `number` - `height`: `number` - `depth`: `number` - Depth (slices) for 3D textures, layer count for arrays. `1` for flat 2D / cubemap-face textures. - `textureType`: `string` - Texture dimensionality: `"2d"`, `"3d"`, `"cube"`, `"2dArray"`, `"cubeArray"`. - `pixelFormat`: `string` - Engine-agnostic pixel format name (e.g. `"rgba32Float"`). - `read`: `TextureBinding` - Token tagged as "read into kernel" -- pass to a kernel's `inputTextures` map. - `write`: `TextureBinding` - Token tagged as "write from kernel" -- pass to a kernel's `outputTextures` map. **Methods:** - `generateMipmaps()` → `void` - Generate the mipmap chain. Runs a synchronous GPU mipmap-generation pass against the texture's command queue. Requires the texture was allocated with `mipmapLevelCount > 1`. No-op on textures without a mip chain. - `destroy()` → `void` - Release the texture's GPU memory immediately. ### `ObjectEntity` Entity in the scene **Properties:** - `id`: `string` - Unique entity identifier - `representation`: `RepresentationEntity` - Primary representation (visual/model) **Methods:** - `findRepresentation(query: any)` → `RepresentationEntity` - Find a representation by ID or name **Runtime Extensions:** - `on(type: string, options: Object | function, listener: function)` → `string` - Register an entity event listener - `off(eventId: string)` → `void` - Remove an entity event listener - `once(type: string, options: Object | function, listener: function)` → `string` - Register a one-time entity event listener - `playAudio(source: string, options: Object)` → `Promise` - Play audio asset on this entity - `playAudioBuffer(base64: string, options: Object)` → `Promise` - Play audio buffer on this entity - `stopAudio()` → `Promise` - Stop audio playback on this entity - `setMaterials(materials: Array)` → `Promise` - Set materials on this entity's representation - `setMaterial(options: Object)` → `Promise` - Set material on this entity's representation - `createAudioStream(options: Object)` → `AudioStream` - Create a streaming audio player on this entity - `waitUntilReady()` → `Promise` - Wait until this entity's primary representation has finished loading. Convenience that proxies to `entity.representation.waitUntilReady()`. Resolves immediately if there's no primary representation. - `remove()` → `Promise` - Remove this entity from the scene - `clone(options: Object, options.position: Vector3, options.rotation: Rotation, options.scale: Vector3, options.anchor: Object, options.enabled: boolean, options.id: string)` → `Promise` - Deep-copy this object and add the copy to the scene. The copy carries fresh ids, so it behaves like any other object -- attach events, move it, remove it independently. Pose overrides merge into the copy's transform, so an omitted field keeps this object's value. If this object was authored "disabled by default" (a common template pattern), the copy is added hidden with its physics body off until you `toggle(true)` it -- so a batch can be revealed together on one frame. Cloning rejects past 512 live copies of one source object. That ceiling exists only to stop a runaway loop (`while (true) clone()`) from exhausting memory -- reaching it means a bug, not a budget. Remove copies you no longer need with `entity.remove()`. - `toggle(enabled: boolean)` → `Promise` - Enable or disable this entity's representation - `play(animation: Animation)` → `Promise` - Play an animation on this entity's representation - `followPath(path: Path, options: Object, options.repeat: boolean | number)` → `void` - Move this entity along a path from scene.createPath(...). - `toggleAnimations(options: Object, options.play: boolean, options.animationIds: Array)` → `Promise` - Toggle (pause/resume) animations on this entity's representation - `stopAnimations(options: Object, options.transitionDuration: number)` → `Promise` - Stop and remove animations from this entity's representation - `animateTo(properties: Object, properties.position: Vector3, properties.rotation: Rotation, properties.scale: Vector3, properties.transform: Transform, properties.opacity: number, duration: number, options: Object, options.timingFunction: string | Object, options.delay: number, options.repeatCount: number, options.repeatMode: string)` → `Promise` - Animate this entity's representation to target properties - `animateFromTo(fromProperties: Object, toProperties: Object, duration: number, options: Object)` → `Promise` - Animate this entity's representation from starting to target properties - `animateBy(properties: Object, duration: number, options: Object)` → `Promise` - Animate this entity's representation by relative values (additive animation) - `applyImpulse(impulse: Vector3, options: Object)` → `Promise` - Push this object with a one-off force. Proxies to the primary representation. - `applyAngularImpulse(impulse: Vector3, options: Object)` → `Promise` - Spin this object with a one-off rotational force. Proxies to the primary representation. - `setPhysicsMode(mode: string)` → `void` - Set the physics body mode at runtime. Proxies to the primary representation. - `setVelocity(velocity: Vector3)` → `void` - Set the world-space linear velocity of this object's physics body. Proxies to the primary representation. - `setAngularVelocity(angularVelocity: Vector3)` → `void` - Set the world-space angular velocity of this object's physics body (axis-angle, radians per second). Proxies to the primary representation. - `setInstances(transforms: Object | Array)` → `void` - GPU-instance this object's mesh -- draw one copy per transform. Proxies to the primary representation. Pass `Instances.transforms([...])` or a bare array of `Transform` / `Vector3`. Rendering-only; gate with `environment.features.has('instancing')`. - `clearInstances()` → `void` - Remove instancing from this object, reverting to the single base mesh. Proxies to the primary representation. ### `RepresentationEntity` Visual representation of an entity (model, shape, etc.) **Properties:** - `id`: `string` - Unique representation identifier - `entity`: `ObjectEntity` - Parent entity - `opacity`: `number` - Opacity (0-1) - `isEnabled`: `boolean` - Whether this representation is enabled/visible - `position`: `Vector3` - Local position relative to parent. - `rotation`: `Rotation` - Local rotation as quaternion. Assign a whole `Rotation`; per-component quaternion mutation is not meaningful, so use `rotation`/`eulerAngles` assignment or animateTo. - `eulerAngles`: `Vector3` - Local rotation as euler angles (radians). - `scale`: `Vector3` - Local scale - `transform`: `Transform` - Local transform (position, rotation, scale combined) - `worldPosition`: `Vector3` - World-space position - `worldRotation`: `Rotation` - World-space rotation as quaternion - `worldEulerAngles`: `Vector3` - World-space rotation as euler angles (radians) - `worldScale`: `Vector3` - World-space scale - `worldTransform`: `Transform` - World-space transform - `boundingBox`: `BoundingBox` - Local bounding box - `worldBoundingBox`: `BoundingBox` - World-space bounding box - `rootView`: `UIView` - Root view of the panel content. Nil unless this representation's kind is `.userInterface`. - `mesh`: `Mesh` - Dynamic mesh handle for this representation. Nil unless the kind is `.dynamicMesh`. Use this to write vertex/index buffers and update per-part bounds from a script. Bulk-copy semantics -- one call moves many vertices, no per-element overhead. **Methods:** - `findRepresentation(query: any)` → `RepresentationEntity` - Find a child representation by ID or name - `findChild(name: string, recursive: any)` → `Entity` - Find a nested entity by name within the model hierarchy - `getChildNames()` → `Array` - List all nested entity names (for discovery) - `toggleWithAnimation(enable: boolean)` → `void` - Toggle visibility with fade animation - `findView(query: any)` → `UIView` - Find a view in this representation's UI tree by ID or name - `bindMaterialParameter(parameterName: string, variableId: string, options: any)` → `void` - Bind a material parameter to a variable for automatic updates - `unbindMaterialParameter(parameterName: string, options: any)` → `void` - Remove a variable binding from a material parameter - `setPhysicsMode(mode: string)` → `void` - Set the physics body mode at runtime: `"static"`, `"kinematic"`, or `"dynamic"`. - `setVelocity(velocity: Vector3)` → `void` - Set the world-space linear velocity of this representation's physics body. - `setAngularVelocity(angularVelocity: Vector3)` → `void` - Set the world-space angular velocity of this representation's physics body (axis-angle, radians per second). The linear velocity is preserved. The rotational counterpart of `setVelocity` -- e.g. give a thrown object spin. - `setInstances(transforms: any)` → `void` - GPU-instance this representation's mesh -- draw one copy per transform, at a fraction of the cost of real entities. Pass `Instances.transforms([...])` (or a bare array of `Transform` / `Vector3`, where a `Vector3` places a copy at that position). Applies to every mesh in the representation. - `followPath(path: Path, options: any)` → `void` - Move this entity along a path (from `scene.createPath`). - `clearInstances()` → `void` - Remove instancing from this representation, reverting to the single base mesh. **Runtime Extensions:** - `on(type: string, options: Object | function, listener: function)` → `string` - Register an event listener on this representation - `off(eventId: string)` → `void` - Remove an event listener from this representation - `once(type: string, options: Object | function, listener: function)` → `string` - Register a one-time event listener on this representation - `playAudio(source: string, options: Object, options.gain: number, options.loops: boolean, options.inputMode: string)` → `Promise` - Play audio asset on this representation - `stopAudio()` → `Promise` - Stop audio playback on this representation - `playAudioBuffer(base64: string, options: Object, options.sampleRate: number, options.channels: number, options.format: string, options.gain: number)` → `Promise` - Play audio buffer spatially on this representation - `createAudioStream(options: Object, options.sampleRate: number, options.channels: number, options.format: string)` → `AudioStream` - Create a streaming audio player on this representation - `waitUntilReady()` → `Promise` - Wait until this representation's model assets have finished loading and been attached to the scene. Many setup calls -- `bindMaterialParameter`, transform reads, animation triggers -- depend on the model being present. On `onWillAppear` the representation proxy exists but the model itself usually hasn't been attached yet, and calling those methods too early silently no-ops. Await this before any model-dependent setup. - `toggle(enabled: boolean)` → `Promise` - Enable or disable this representation - `play(animation: Animation)` → `Promise` - Play an animation on this representation - `toggleAnimations(options: Object, options.play: boolean, options.animationIds: Array)` → `Promise` - Toggle (pause/resume) animations on this representation - `stopAnimations(options: Object, options.transitionDuration: number)` → `Promise` - Stop and remove animations from this representation - `animateTo(properties: Object, duration: number, options: Object)` → `Promise` - Animate this representation to target properties - `animateFromTo(fromProperties: Object, toProperties: Object, duration: number, options: Object)` → `Promise` - Animate this representation from starting to target properties - `animateBy(properties: Object, duration: number, options: Object)` → `Promise` - Animate this representation by relative values - `setBlendShapeWeights(weights: Object | number, options: Object, options.modelName: string, options.weightSetIndex: number, options.weightSetId: string)` → `void` - Update blend shape weights on this representation (for models with morph targets/blend shapes) - `resetBlendShapeWeights(options: Object)` → `void` - Reset all blend shape weights to zero - `setMaterials(materials: Array, materials[].id: string, materials[].target: Object, materials[].target.type: string, materials[].target.models: Array, materials[].target.materialSlots: Array)` → `Promise` - Set materials on this representation - `setMaterial(options: Object, options.id: string, options.target: Object, options.target.type: string, options.target.models: Array, options.target.materialSlots: Array)` → `Promise` - Set material on this representation - `applyImpulse(impulse: Vector3, options: Object, options.space: string | Object, options.at: Vector3 | string)` → `Promise` - Push this representation with a one-off force. The object needs a dynamic physics body -- see `t.physics({ mode: 'dynamic' })`. - `applyAngularImpulse(impulse: Vector3, options: Object, options.space: string | Object)` → `Promise` - Spin this representation with a one-off rotational force. The rotational counterpart of `applyImpulse`. There is no application point -- an angular impulse acts on the body as a whole. ### `Entity` Generic entity within a model hierarchy (bones, groups, nested models) **Properties:** - `name`: `string` - Entity name - `isEnabled`: `boolean` - Whether this entity is enabled/visible - `opacity`: `number` - Opacity (0-1) - `position`: `Vector3` - Local position relative to parent - `rotation`: `Rotation` - Local rotation as quaternion - `scale`: `Vector3` - Local scale - `transform`: `Transform` - Local transform (position, rotation, scale combined) - `worldPosition`: `Vector3` - World-space position - `worldRotation`: `Rotation` - World-space rotation - `worldTransform`: `Transform` - World-space transform - `jointNames`: `Array` - Joint names for skeletal animation (empty if not a skeletal model) - `jointTransforms`: `Array` - Joint transforms array (parallel to jointNames) - `children`: `Array` - Direct child entities **Methods:** - `findChild(name: string, recursive: any)` → `Entity` - Find a child entity by name - `setInstances(transforms: any)` → `void` - GPU-instance this node's mesh -- draw one copy per transform. Pass `Instances.transforms([...])` (or a bare array of `Transform` / `Vector3`). Rendering-only (no physics / collision / identity). Gate with `environment.features.has('instancing')` (iOS 26 / visionOS 26 / macOS 26+). - `clearInstances()` → `void` - Remove instancing from this node, reverting to the single base mesh. ### `EnvironmentFeatures` Capability registry exposed at `environment.features`. **Methods:** - `has(name: string)` → `boolean` - Whether the named feature is supported on the current platform and runtime version. Unknown names return `false` (WebGPU `Set.has` semantic). - `list()` → `Array` - Every feature string currently supported on this device/runtime. Useful for debugging ("why isn't my branch firing?") and for reflecting the capability set into telemetry. ### `Environment` **Properties:** - `hostingPlatform`: `string` - The platform running the experience: "iOS", "macOS", "visionOS", or "web" - `deviceCategory`: `string` - The device form factor: "handheld" (iPhone, iPad), "spatial" (Apple Vision Pro and other headsets), or "desktop" (Mac, desktop web). Prefer this over `hostingPlatform` when branching on the *interaction model* rather than the exact OS -- e.g. screen gestures exist on handheld and desktop but not spatial, where input is the user's eyes and hands. - `systemOSVersion`: `string` - Operating system version string, e.g. "18.0" or "2.0" - `locale`: `string` - User's locale in BCP 47 format, e.g. "en-US", "de-DE" - `isEditing`: `boolean` - `true` when the experience is running inside the Scenery editor's scene preview, `false` during normal playback. Lets scripts gate debug overlays, skip intros, or auto-fill placeholder state while the author is iterating. - `features`: `EnvironmentFeatures` - Runtime + device capability registry. Authors query by string -- `environment.features.has('compute')` -- to branch on whether the current platform supports a given feature. Mirrors WebGPU's `adapter.features.has(...)` shape so portable scripts read the same on both backends. - `location`: `Location` - The user's device location. Coarse reads ride the base grant; the precise tier is opted into explicitly. See `LocationJSExports`. **Methods:** ### `Experience` **Properties:** - `currentScene`: `Scene` - The current scene - `environment`: `Environment` - Environment information (platform, OS version, locale) - `sharedActivity`: `SharedActivity` - Shared activity state (SharePlay, WebSocket, or other shared session protocols) **Methods:** - `setVariable(id: string, value: any, options: any)` → `void` - Set an experience-scoped variable (persists across scene transitions) - `getVariable(id: string)` → `any` - Get an experience-scoped variable - `transitionToScene(id: string)` → `void` - Transition to another scene ### `HTTPClient` HTTP client for making network requests Supports GET, POST, and custom requests with authentication **Methods:** - `get(url: string, callback: any)` → `void` - Make a GET request - `post(url: string, body: string, callback: any)` → `void` - Make a POST request - `request(url: string, options: Array, callback: any)` → `void` - Make a custom HTTP request ### `Location` The user's device location, exposed to scripting as `environment.location`. Coarse reads ride the base grant; precise accuracy is an explicit opt-in. **Properties:** - `authorizationStatus`: `string` - Current authorization: "notDetermined" | "denied" | "restricted" | "granted". - `accuracyAuthorization`: `string` - Current accuracy authorization: "full" | "reduced" | "unknown". **Methods:** **Runtime Extensions:** - `requestAccess()` → `Promise` - Request base location access. Prompts once if undetermined; resolves the resulting authorization status. Reads never prompt on their own. - `current(options: Object)` → `Promise` - Read the current location once. - `requestPreciseAccess(options: Object)` → `Promise` - Request precise (full) accuracy. Shows a confirmation carrying `options.reason` (once per run), then the OS accuracy prompt. Resolves whether precise is now active. - `watch(onPosition: any, options: Object)` → `any` - Observe location continuously. `onPosition` receives a GeoCoordinate. - `on(event: string, callback: function)` → `any` - Subscribe to a location event. Supported: 'authorizationchange' → callback(status). ### `Microphone` Microphone audio streaming Access via `scene.microphone` **Properties:** - `onData`: `any` - Callback for audio data chunks (base64-encoded PCM16) - `onError`: `any` - Callback for errors (permission denied, etc.) - `isStreaming`: `boolean` - Whether the microphone is currently streaming **Methods:** - `start()` → `void` - Start capturing audio - `stop()` → `void` - Stop capturing audio - `configure(options: Array)` → `void` - Configure microphone settings ### `Path` Runtime path handle returned by `scene.createPath(...)`. Read-only spline queries; consumed by `entity.followPath(...)`. Not persisted (v1). **Properties:** - `length`: `number` - Total arc length of the path, in meters. **Methods:** - `point(t: number)` → `Vector3` - Position at parameter `t` (0...1 across the whole path). - `pointAtDistance(d: number)` → `Vector3` - Position at arc-length distance `d` (0...`length`) -- constant-speed spacing. - `tangent(t: number)` → `Vector3` - Unit tangent (direction of travel) at parameter `t`. ### `Ray` A ray with origin and direction, useful for raycasting **Properties:** - `origin`: `Vector3` - Ray starting point in world space - `direction`: `Vector3` - Normalized ray direction ### `Rotation` Rotation represented as a quaternion **Properties:** - `quaternion`: `Vector4` - Quaternion components (x, y, z, w) - `eulerAngles`: `Vector3` - Euler angles in radians (x, y, z) **Methods:** - `create()` → `Rotation` - Create identity rotation (no rotation) - `slerp(r1: Rotation, r2: Rotation, t: number)` → `Rotation` - Spherically interpolate between two rotations - `multiply(r1: Rotation, r2: Rotation)` → `Rotation` - Multiply two rotations (compose) - `inverse(r: Rotation)` → `Rotation` - Get the inverse (conjugate) of a rotation **Runtime Extensions:** - `slerp(other: Rotation, t: number)` → `Rotation` - Spherically interpolate to another rotation - `multiply(other: Rotation)` → `Rotation` - Multiply (compose) with another rotation - `inverse()` → `Rotation` - Get the inverse of this rotation ### `Scene` **Properties:** - `id`: `string` - Scene identifier - `time`: `number` - Time elapsed since scene started (seconds) - `microphone`: `Microphone` - Microphone audio streaming - `cameraTransform`: `Transform` - Current camera transform in world space - `viewportSize`: `Vector2` - Viewport size in points (iOS only) **Methods:** - `setVariable(id: string, value: any, options: any)` → `void` - Set a scene-scoped variable (cleared on scene transition) - `getVariable(id: string)` → `any` - Get a scene-scoped variable - `findEntity(query: any)` → `ObjectEntity` - Find an entity by ID or name - `triggerCustomEvent(query: any)` → `void` - Trigger one or more custom-trigger events. - `getCustomEvents()` → `Array` - List custom-trigger scene events on the current segment. Useful for debug panels that enumerate triggerable events at runtime. Each entry has the event's `id`, optional `name` (omitted when unset), and `isEnabled` flag. System events (tap, render, screenTap, schedule, etc.) are not included -- those are handled by the engine, not scripted. - `getAnchors(kind: string)` → `Array` - Get detected AR anchors - `projectToScreen(worldPosition: Vector3)` → `Vector2` - Convert world position to normalized screen coordinates (iOS only) - `screenToRay(normalizedPosition: Vector2)` → `Ray` - Convert normalized screen coordinates to a ray for raycasting (iOS only) - `raycast(origin: Vector3, direction: Vector3)` → `Array` - Cast ray through scene entities and scene mesh - `raycastAR(origin: Vector3, direction: Vector3, target: string, alignment: string)` → `Array` - Cast ray against AR planes (iOS only) - `createPath(options: any)` → `Path` - Create a catmull-rom path from control points. - `createAudioStream(options: Array)` → `AudioStream` - Create a streaming audio player **Runtime Extensions:** - `getMaterial(id: string)` → `Material` - Fetch a material from the experience's material library by id, hydrated into a live `Material` you can inspect, `.clone()`, and edit. Use the get → `.clone()` → tweak → apply pattern to override a library material on a single object without mutating the library entry. - `getObjectDescriptor(nameOrId: string | Object)` → `ObjectDescriptor | null` - Read an authored object's descriptor so a script can adjust it before it is displayed. Returns an editable ObjectDescriptor (the recipe) -- distinct from `findEntity`, which returns the live entity once it's in the scene. Edit it with the usual chainable methods (`.material`, `.gestures`, `.asset`, `.representation`, ...), then either `scene.setObjectDescriptor(...)` to update it in place, or `.clone()` + `scene.createEntity(...)` to spawn a variant. Ordering: run the edit + set BEFORE the object's Display Element action, in the same event (top level or a Sequence -- not inside a Group, which runs concurrently), and keep the set synchronous (no `await` before it). - `setObjectDescriptor(descriptor: ObjectDescriptor)` → `boolean` - Write an edited descriptor back into the current scene, keyed by its id. Takes effect the next time the object is displayed (edit before its first Display Element for the clean path). If the object is already displayed, the change lands but `displayElement` won't re-apply it -- remove and re-display to see it. - `on(type: string, options: Object | function, listener: function)` → `string` - Register a scene event listener - `off(eventId: string)` → `void` - Remove a scene event listener - `preload(sources: string | Array, options: Object, options.type: string)` → `Promise` - Warm one or more assets so their first use doesn't hitch -- the decode / GPU upload happens now (e.g. during scene setup) instead of on the frame you first play or show them. - `once(type: string, options: Object | function, listener: function)` → `string` - Register a one-time scene event listener - `createEntity(descriptor: ObjectDescriptor)` → `Promise` - Create an object in the scene. - `runAction(action: Action)` → `Promise` - Run an action and wait for completion. - `playAudioBuffer(base64: string, options: Object, options.sampleRate: number, options.channels: number, options.format: string, options.gain: number, options.elementId: string, options.representationId: string)` → `Promise` - Play audio from PCM buffer data - `toggle(entities: Array, isEnabled: boolean)` → `Promise` - Reveal or hide a batch of objects in a single frame. Calling `entity.toggle(true)` in a loop enables each object on its own frame -- so physics bodies start at different times and a stack settles against its half-built self. This runs one grouped action instead, so every object reveals and every physics body starts together. Pairs with cloning a disabled template: clone the batch (each copy stays hidden, physics off), then `scene.toggle(copies, true)` to bring them all up at once. - `playAnimation(objectOrId: string | ObjectEntity, animation: Object, representationId: string)` → `Promise` - Play animation on object - `animateTo(objectOrId: string | ObjectEntity, properties: Object, duration: number, options: Object)` → `Promise` - Animate object to target properties - `animateFromTo(objectOrId: string | ObjectEntity, fromProperties: Object, toProperties: Object, duration: number, options: Object)` → `Promise` - Animate object from starting to target properties - `animateBy(objectOrId: string | ObjectEntity, properties: Object, duration: number, options: Object)` → `Promise` - Animate object by relative values - `emitHaptic(feedback: string | Object)` → `Promise` - Play haptic feedback on the viewer's device. Haptics are device-level rather than positional -- they play on the device no matter which object triggered them -- so this lives on the scene rather than on an entity. Devices without a haptic engine ignore it. - `createSurfaceInput(options: Object, options.target: RepresentationEntity, options.project: string, options.plane: Object, options.plane.axis: string, options.plane.offset: number, options.maxDistance: number)` → `any` - Platform-adaptive surface interaction. Returns a live input source that yields interaction points on a surface, in that surface's LOCAL frame, using whatever input the platform offers -- fingertips on Apple Vision Pro (hand tracking), screen taps / drags on iPhone / iPad / Mac. Your logic reads the same points either way and never branches on platform. Read `input.points` once per frame inside `scene.on('render', ...)`, and call `input.stop()` when done (it tears down the gesture subscriptions). ### `SharedActivity` Shared activity state for multi-user sessions (SharePlay, WebSocket, etc.) **Properties:** - `isActive`: `boolean` - Whether a shared activity session is currently active - `isOwner`: `boolean` - Whether the local participant is the session owner (presenter) - `participantCount`: `number` - Number of remote participants (excludes local participant) - `onMessage`: `any` - Called when a script message is received from another participant - `onOwnershipChanged`: `any` - Called when session ownership changes (session start, transfer, owner leaves, session end) **Methods:** - `send(data: any)` → `boolean` - Send data to all participants (reliable delivery). - `sendFrequent(data: any)` → `boolean` - Send data to all participants (unreliable delivery, suitable for high-frequency updates). ### `Transform` 4x4 transformation matrix representing position, rotation, and scale **Properties:** - `position`: `Vector3` - Position vector - `rotation`: `Rotation` - Rotation quaternion - `scale`: `Vector3` - Scale vector **Methods:** - `create()` → `Transform` - Create identity transform (position: 0,0,0, rotation: identity, scale: 1,1,1) - `createWith(position: Vector3, rotation: Rotation, scale: Vector3)` → `Transform` - Create transform with specific values - `transformPoint(transform: Transform, point: Vector3)` → `Vector3` - Transform a point by this matrix - `transformVector(transform: Transform, vector: Vector3)` → `Vector3` - Transform a direction vector (ignores position) - `multiply(t1: Transform, t2: Transform)` → `Transform` - Multiply two transforms (combine transformations) - `inverse(transform: Transform)` → `Transform` - Get inverse transform **Runtime Extensions:** - `transformPoint(point: Vector3)` → `Vector3` - Transform a point - `transformVector(vector: Vector3)` → `Vector3` - Transform a vector - `multiply(other: Transform)` → `Transform` - Multiply with another transform - `inverse()` → `Transform` - Get inverse transform ### `UIView` A view node inside a UI panel. **Properties:** - `id`: `string` - Stable view ID set in the experience model. - `name`: `string` - Optional human-readable name (mirrors `representation.name`). - `kind`: `string` - View kind as a string: "label", "button", "slider", "toggle", "textField", "stepper", "segmentedControl", "progressView", "image", "divider", "shape", "hStack", "vStack", "zStack", "spacer", "webView". **Methods:** - `getProperty(name: string)` → `any` - Read a property by key - `setProperty(name: string, value: any)` → `void` - Write a property by key. Live-updates the rendered view; for input controls bound via `.reference`, also writes back to the bound variable so observers see the change. No view tree rebuild. - `bindProperty(propertyName: string, variableName: string, options: any)` → `void` - Bind a property to an experience variable at runtime. Variable changes flow into the live view; for input controls, user input flows back into the variable. Calling `bindProperty` again on the same property replaces the existing binding. Does not mutate the saved model -- bindings live with this proxy and dissolve when JS releases it (or when the panel rebuilds). - `unbindProperty(propertyName: string)` → `void` - Remove a runtime binding installed via `bindProperty`. The property keeps its current displayed value but no longer reacts to the variable; user input on the property no longer writes back. No-op if no binding exists for `propertyName`. ### `ValueAnimation` Value animations with spring and curve timing **Properties:** - `isPlaying`: `boolean` - Whether the animation is currently playing **Methods:** - `start()` → `void` - Start or resume the animation - `stop()` → `void` - Pause the animation (can be resumed with start()) - `destroy()` → `void` - Stop and clean up the animation permanently ### `Vector2` 2D vector for screen coordinates, UV mapping, and 2D math **Properties:** - `x`: `number` - X component - `y`: `number` - Y component **Methods:** - `create(x: number, y: number)` → `Vector2` - Create a Vector2 - `zero()` → `Vector2` - Zero vector (0, 0) - `one()` → `Vector2` - One vector (1, 1) - `lerp(v1: Vector2, v2: Vector2, t: number)` → `Vector2` - Linearly interpolate between two vectors - `distance(v1: Vector2, v2: Vector2)` → `number` - Distance between two vectors - `dot(v1: Vector2, v2: Vector2)` → `number` - Dot product of two vectors - `normalize(v: Vector2)` → `Vector2` - Normalize a vector (unit length) - `length(v: Vector2)` → `number` - Length of a vector ### `Vector3` 3D vector for positions, directions, and scales **Properties:** - `x`: `number` - X component - `y`: `number` - Y component - `z`: `number` - Z component **Methods:** - `create(x: number, y: number, z: number)` → `Vector3` - Create a Vector3 - `zero()` → `Vector3` - Zero vector (0, 0, 0) - `one()` → `Vector3` - One vector (1, 1, 1) - `lerp(v1: Vector3, v2: Vector3, t: number)` → `Vector3` - Linearly interpolate between two vectors - `distance(v1: Vector3, v2: Vector3)` → `number` - Distance between two vectors - `dot(v1: Vector3, v2: Vector3)` → `number` - Dot product of two vectors - `cross(v1: Vector3, v2: Vector3)` → `Vector3` - Cross product of two vectors - `normalize(v: Vector3)` → `Vector3` - Normalize a vector (unit length) - `length(v: Vector3)` → `number` - Length of a vector - `angleBetween(v1: Vector3, v2: Vector3)` → `number` - Angle between two vectors in radians **Runtime Extensions:** - `add(other: Vector3)` → `Vector3` - Add two vectors - `subtract(other: Vector3)` → `Vector3` - Subtract a vector from this vector - `multiply(scalar: number)` → `Vector3` - Multiply vector by scalar - `divide(scalar: number)` → `Vector3` - Divide vector by scalar - `dot(other: Vector3)` → `number` - Calculate dot product with another vector - `cross(other: Vector3)` → `Vector3` - Calculate cross product with another vector - `length()` → `number` - Get length of vector - `normalize()` → `Vector3` - Get normalized vector - `distanceTo(other: Vector3)` → `number` - Calculate distance to another vector - `lerp(other: Vector3, t: number)` → `Vector3` - Linearly interpolate to another vector - `angleTo(other: Vector3)` → `number` - Calculate angle to another vector ### `Vector4` 4D vector for quaternions, colors, and homogeneous coordinates **Properties:** - `x`: `number` - X component - `y`: `number` - Y component - `z`: `number` - Z component - `w`: `number` - W component **Methods:** - `create(x: number, y: number, z: number, w: number)` → `Vector4` - Create a Vector4 ### `WebSocket` WebSocket connection for real-time communication **Properties:** - `onOpen`: `any` - Called when connection opens - `onClose`: `any` - Called when connection closes - `onMessage`: `any` - Called when message received (event.data contains the message) - `onError`: `any` - Called on error (event.error contains the Error) **Methods:** - `send(message: string)` → `void` - Send a message - `close()` → `void` - Close the connection ### `WebSocketManager` WebSocket connection manager Access via `websocket.connect()` **Methods:** - `connect(url: string, options: Array)` → `WebSocket` - Create a new WebSocket connection ## Runtime Classes ### `Anchor` Anchor types for object placement **Static Methods:** - `Anchor.position(xOrVector: Vector3 | number, y: number, z: number)` → `Object` - Anchor at fixed world position - `Anchor.geoLocation(latitude: number, longitude: number, altitude: number)` → `any` - Anchor at geographic location - `Anchor.camera(xOrVector: Vector3 | number, y: number, z: number, lerpFactor: number)` → `any` - Anchor relative to camera - `Anchor.currentPOV(xOrVector: Vector3 | number, y: number, z: number, resetRotation: boolean)` → `Object` - Anchor at user's current point of view (captures current camera position) - `Anchor.screenSpace(options: Object, options.alignment: string, options.insets: number | Object, options.respectsSafeArea: boolean)` → `Object` - Anchor a UI panel in screen space -- a flat 2D overlay pinned to a screen edge or corner, rather than a plane placed in the world. Use for HUDs and controls that should stay put wherever the viewer looks. - `Anchor.horizontalPlane(classification: string, minWidth: number, minHeight: number)` → `Object` - Anchor on detected horizontal plane (floor, table, etc.) - `Anchor.verticalPlane(classification: string, minWidth: number, minHeight: number)` → `any` - Anchor on vertical plane - `Anchor.hand(chirality: string, joint: string, trackingScope: string, lerpFactor: number, providesDiscoveryHint: boolean)` → `Object` - Anchor to user's hand (visionOS hand tracking) - `Anchor.image(imageUrl: string, physicalWidth: number, identifier: string, orientation: string, tracksContinuously: boolean, hideIfTrackingLost: boolean, providesDiscoveryHint: boolean)` → `Object` - Anchor to image marker (image tracking) ### `Material` Chainable builder for an inline material. Six kinds: `unlit`, `pbr`, `occlusion`, `customShader`, `materialX`, `video`. Use the matching factory (`Material.unlit({...})`, etc.) or `new Material(kind)`. Properties map to the underlying material data model with web-standard names: - Colors: `color`, `emissive`, `sheenColor`, `specularColor` -- flat tint. - Maps: `map`, `emissiveMap`, `roughnessMap`, `metalnessMap`, `normalMap`, `aoMap`, `specularMap`, `sheenMap`, `clearcoatMap`, `alphaMap` -- textures accept either a URL/asset-id string or `{ texture, scale }`. - Scalars: `roughness`, `metalness`, `clearcoat`, `opacity`, `emissiveIntensity`. - Rendering: `opaque`, `transparent`, `opacityThreshold`, `blendMode`, `faceCulling`, `wireframe`, `writesDepth`, `readsDepth`. **Static Methods:** - `Material.unlit(opts: Object)` → `Material` - Flat-shaded material. Renders the surface color regardless of scene lighting -- useful for UI, billboards, vertex-colored point clouds, etc. - `Material.pbr(opts: Object)` → `Material` - Physically-Based material -- the realistic-rendering default for surfaces that should respond to scene lighting. - `Material.occlusion(opts: Object)` → `Material` - Occlusion material -- invisible itself but hides geometry behind it. Use for matte holdouts, real-world geometry masks, portals. - `Material.customShader(opts: Object)` → `Material` - Custom shader material -- author-supplied surface shader and/or geometry modifier from a compiled shader library. - `Material.materialX(opts: Object)` → `Material` - ShaderGraph material from a bundled `.usdz`. Reference by file path plus the `/Root/` path inside. - `Material.video()` → `Material` - Video texture material. Use `.videoSource(urlOrId)` for the playback source and `.videoOptions({ loops, streamContent, volume })` for playback config. **Instance Methods:** - `opacity()` → `any` - Material opacity. Values < 1 also flip `isOpaque` to `false` so the blending state matches. - `materialXAsset()` → `any` - MaterialX (ShaderGraph): URL or asset id of the .usdz, plus the path to the material inside it (e.g. `"/Root/MyMaterial"`). - `setParameter(name: string, value: any, typeHint: Object)` → `Material` - Set a constant value on a shader parameter. Works on `customShader` and `materialX` kinds -- routes to the right options blob automatically. Warns and no-ops on kinds without shader parameters. For runtime variable bindings, use `entity.representation.bindMaterialParameter(name, variableId, opts?)`. - `clone()` → `any` - Deep-copy the material with a fresh `id`. Use for the get → clone → tweak → apply pattern when overriding a library material for a single entity without mutating the library entry. - `toString()` → `any` - Useful per-kind summary for `console.log(mat)` -- includes kind, id, name, and the meaningful state set on the material (channel colors, scalar values, shader params, etc.) so authors can see "what's on this material" at a glance. For the full serialized shape, use `JSON.stringify(mat, null, 2)`. ### `Instances` Instance-data handles for `rep.setInstances(...)` / `entity.setInstances(...)` -- GPU mesh instancing draws one copy of a mesh per transform, far cheaper than real entities. Instances are rendering-only (no physics, collision, or per-instance identity); use `clone()` for objects the user interacts with. Gate with `environment.features.has('instancing')`. **Static Methods:** - `Instances.transforms(list: Array)` → `Object` - Build an instance-data handle from a list of transforms. Each entry is a `Transform` (full pose) or a `Vector3` (a copy placed at that position). A bare array is also accepted -- `setInstances([...])` is sugar for `setInstances(Instances.transforms([...]))`. ### `Texture` GPU-only / runtime-managed texture. Authors construct via the static factories below; the returned handle is opaque and passes to material parameters (future) and compute kernel `inputTextures` / `outputTextures` maps (today, for `Texture.compute(...)` only). **Static Methods:** - `Texture.compute(options: Object, options.pixelFormat: string, options.textureType: string, options.width: number, options.height: number, options.depth: number, options.arrayLength: number, options.mipmapLevelCount: number, options.semantic: string, options.usage: Array)` → `Promise` - Allocate a GPU-only texture written by a compute kernel. Supports 2D, 3D, cube, and array textures with optional mipmap chains. Async because the dynamic-texture asset-provider funnel allocates the underlying GPU resource and registers it in the runtime's manager cache (so material binding finds the same instance later). Authors `await` once at allocation; subsequent kernel dispatches are sync. - `Texture.image(urlOrId: string, options: Object, options.semantic: string)` → `Promise` - Static image-asset texture. Reads an image asset (PNG / JPG / etc.) from the experience's asset library or an absolute URL and binds it as a sampleable texture -- typical use is a hand-painted normal map or albedo map fed to `Material.pbr({ normalMap: tex })`. - `Texture.video(urlOrId: string, options: Object, options.semantic: string, options.loops: boolean, options.autoplays: boolean, options.volume: number, options.streamContent: boolean, options.isShared: boolean)` → `Promise` - Video-asset texture. Plays a video file (mp4 / mov) as a sampleable texture and binds it to a material -- typical use is a looping background, an animated diorama, or a UI-overlay video sticker. The video starts playing automatically by default. Pass `{ autoplays: false }` and call `videoTexture.play()` later when the entity becomes visible. - `Texture.cameraFeed(options: Object, options.semantic: string)` → `Promise` - Live camera feed as a sampleable texture. Binds the device's camera capture as a regular texture handle -- typical uses are first-person portal effects, augmented-reality color grading on detected planes, or piping the feed into a compute kernel for a real-time filter. Available on iOS / iPadOS only -- Mac Catalyst and visionOS don't expose the AR camera capture. Always gate with `environment.features.has('cameraFeed')`. ### `Kernel` Opaque handle to a compiled GPU compute kernel. Authors construct via `Kernel.fromSource(...)` or `Kernel.fromAsset(...)`, then pass to `mesh.runCompute(kernel, options)`. **Static Methods:** - `Kernel.fromSource(options: Object, options.source: string, options.functionName: string)` → `Promise` - Compile a compute kernel from inline MSL source. Handy for prototypes and tests; production scripts should prefer `Kernel.fromAsset(...)` so the source lives in the experience's asset library. - `Kernel.fromAsset(options: Object, options.assetId: string, options.functionName: string)` → `Promise` - Compile a compute kernel from a shader-library asset declared in the experience's asset library. ### `Buffer` Raw GPU buffer for compute kernels. Construct via the static factories below; pass the handle to `mesh.runCompute(...)`'s `inputBuffers` / `outputBuffers` maps to bind it as a kernel argument. **Static Methods:** - `Buffer.float32(length: number, initialValue: number)` → `Buffer | null` - Allocate a Float32-typed GPU buffer. - `Buffer.uint32(length: number, initialValue: number)` → `Buffer | null` - Allocate a Uint32-typed GPU buffer. - `Buffer.uint8(length: number, initialValue: number)` → `Buffer | null` - Allocate a Uint8-typed GPU buffer. - `Buffer.atomic(initialValue: number)` → `Buffer | null` - Allocate a single-element atomic-uint counter -- common pattern for marching-cubes' triangle emitter, particle compaction, etc. ### `ObjectTraits` Builder object passed to the compatibility-only `.traits(t => ...)` callback. New code should skip this entirely and use the direct descriptor methods (`.physics(...)`, `.material(...)`, `.shadow(...)`, `.gestures(...)`, `.transform(...)`, `.opacity(...)`, `.fittingBox(...)`, `.pivot(...)`), which expose the same configuration and chain. **Instance Methods:** - `transform(transform: Transform)` → `ObjectTraits` - Set initial transform - `fittingBox(size: number)` → `ObjectTraits` - Scale model to fit within a cubic bounding box - `pivot(pivot: string)` → `ObjectTraits` - Set pivot adjustment - `opacity(opacity: number)` → `ObjectTraits` - Set opacity adjustment - `shadow(options: Object, options.directional: boolean, options.grounding: boolean | Object)` → `ObjectTraits` - Configure how this object interacts with the scene's two shadow systems. Mirrors `t.physics({...})` / `t.gestures({...})`: pass only the keys you want to change. - `material(materialOrId: string | Material, target: Object, target.type: string, target.models: Array, target.materialSlots: Array)` → `ObjectTraits` - Apply a material -- either a library reference by ID or an inline Material instance. - `physics(options: Object, options.mode: string, options.shape: string, options.mass: number, options.gravity: boolean, options.linearDamping: number, options.angularDamping: number, options.friction: number, options.restitution: number, options.translationLock: Object, options.rotationLock: Object)` → `ObjectTraits` - Give the object a physics body so it can collide, fall, and be pushed. Mirrors the editor's Physics inspector, so anything set here stays visible and editable there. Sub-groups are written only when you supply at least one of their keys -- `t.physics({ mode: 'static' })` produces a plain static body with no mass, damping, or material overrides. Physics also needs scene-level setup: enable the floor mesh and scene mesh collisions in the scene's settings, or bodies will fall forever. - `gestures(options: Object, options.drag: Object | boolean, options.rotate: Object | boolean, options.resize: Object | boolean, options.releaseBehavior: string, options.momentumScale: number, options.angularMomentumScale: number, options.disableAudio: boolean)` → `ObjectTraits` - Let the user move, rotate or resize this object with a gesture, and choose what happens when they let go. Omit a gesture to leave it disabled -- an object with no gestures configured cannot be manipulated at all. - `set(path: string, value: any)` → `ObjectTraits` - Directly set a property path in traits - `build()` → `Object` - Build and return the traits object ### `ObjectDescriptor` Descriptor for creating scene objects dynamically **Instance Methods:** - `name(value: string)` → `ObjectDescriptor` - Set the object name - `anchor(anchor: Object)` → `ObjectDescriptor` - Set the anchor - `asset(urlOrId: string)` → `ObjectDescriptor` - Set / replace the object's **source asset**, kind-routed to the right field (`model` → the model asset, image / video / GIF → the media source). Same-kind swap only -- it does **not** change the object's kind: pointing a model at a video URL gives a broken model, not a video (use `.representation(...)` to change kind). Warns for kinds with no source (primitive, container). Accepts an HTTPS URL or an asset id from the project. - `representation(sourceDescriptor: ObjectDescriptor)` → `ObjectDescriptor` - Fully replace this object's visual **representation** with the one from a freshly built descriptor (`createBox`, `createModel`, `createVideo`, ...) -- the clean way to change kind (model → primitive, model → video). Keeps this object's identity and wiring: its id, representation id, anchor (placement), and events. Takes the source's `kind` **and its traits** -- configure the new look via the factory chain, e.g. `d.representation(createBox(0.1,0.1,0.1).gestures({ drag: true }))`. Note: the authored **transform trait** rides inside the old kind and is dropped by the swap ("keeps placement" means the anchor, not the transform) -- re-apply via the source chain if needed. Element-level fields on the source (`.name()`, `.anchor()`, events) are ignored; only its representation is taken. - `clone()` → `ObjectDescriptor` - Deep-copy this descriptor with a **fresh id graph** (element id + every nested representation id + events), so it can be added alongside the original without an id collision. Use it to spawn variants of an authored object: `scene.getObjectDescriptor({ name: 'can' }).clone().transform({ position: p })`, then `scene.createEntity(...)`. The copy inherits the original's events (re-wired to the copy); clear them with `copy.data.events = []` if unwanted. - `traits(configureFn: function)` → `ObjectDescriptor` - Configure traits via a callback. Traits already on the descriptor (e.g. from `createMesh({ materials: [...] })`) are preserved -- calls add on top. - `physics(options: Object)` → `ObjectDescriptor` - Give this object a physics body. See ObjectTraits.physics for the full options. - `gestures(options: Object)` → `ObjectDescriptor` - Enable manipulation gestures (drag / rotate / resize). See ObjectTraits.gestures. - `material(materialOrId: string | Material, target: Object)` → `ObjectDescriptor` - Apply a material -- a library id or an inline `Material`. See ObjectTraits.material. - `shadow(options: Object)` → `ObjectDescriptor` - Configure the object's shadows (directional + grounding). See ObjectTraits.shadow. - `transform(transform: Object)` → `ObjectDescriptor` - Set the object's transform (position / rotation / scale). See ObjectTraits.transform. - `opacity(opacity: number)` → `ObjectDescriptor` - Set the object's opacity (0-1). See ObjectTraits.opacity. - `fittingBox(size: number)` → `ObjectDescriptor` - Scale a model to fit a box of the given size. See ObjectTraits.fittingBox. - `pivot(pivot: string)` → `ObjectDescriptor` - Adjust the model's pivot. See ObjectTraits.pivot. ### `EntityAnimation` Entity animation factory - create animation descriptors for use with entity.play() **Static Methods:** - `EntityAnimation.to(toProperties: Object, duration: number, options: Object)` → `EntityAnimation` - Animate to target properties - `EntityAnimation.fromTo(fromProperties: Object, toProperties: Object, duration: number, options: Object)` → `EntityAnimation` - Animate from starting to target properties - `EntityAnimation.by(byProperties: Object, duration: number, options: Object)` → `EntityAnimation` - Animate by relative values - `EntityAnimation.fromBy(fromProperties: Object, byProperties: Object, duration: number, options: Object)` → `EntityAnimation` - Animate from starting properties by relative values - `EntityAnimation.spin(revolutions: number, duration: number, options: Object, options.axis: Array)` → `EntityAnimation` - Spin animation - rotate around local axis - `EntityAnimation.orbit(config: Object, config.axis: Array | Vector3, config.rotationCount: number, config.clockwise: boolean, config.orientToPath: boolean, config.startTransform: Object, duration: number, options: Object)` → `EntityAnimation` - Orbit animation - rotate around a point - `EntityAnimation.keyframes(frames: Array, duration: number, options: Object, options.tweenMode: string)` → `EntityAnimation` - Keyframe animation - animate through multiple property states - `EntityAnimation.model(name: string, options: Object, options.trimStart: number, options.trimEnd: number, options.duration: number)` → `EntityAnimation` - Play embedded model animation (USDZ animations) - `EntityAnimation.group(animations: Array, options: Object)` → `EntityAnimation` - Group multiple animations to play together - `EntityAnimation.emphasize(style: string, duration: number, options: Object)` → `EntityAnimation` - Emphasize animation - attention-grabbing effect ### `GeoCoordinate` A geographic coordinate. Construct one for a point of interest, or receive a live fix from `environment.location.current()` (which additionally populates `horizontalAccuracy` and `timestamp`). **Instance Methods:** - `distanceTo(other: GeoCoordinate)` → `number` - Great-circle distance to another coordinate, in metres (haversine, 6371 km). - `bearingTo(other: GeoCoordinate)` → `number` - Initial great-circle bearing to another coordinate, in degrees (0-360, from north). ## Runtime Functions - `wait(seconds: number)` → `Promise` - Wait for specified seconds - `animateValue(options: Object, options.from: number | Vector2 | Vector3 | Vector4 | Color | Rotation, options.to: number | Vector2 | Vector3 | Vector4 | Color | Rotation, options.duration: number, options.curve: string, options.spring: Object, options.spring.duration: number, options.spring.bounce: number, options.bezier: Array, options.delay: number, options.repeatCount: number, options.reverseOnRepeat: boolean, options.autoStart: boolean, options.onUpdate: function, options.onComplete: function)` → `ValueAnimation` - Create and start a value animation Automatically interpolates between from/to values based on their type. Supports numbers, Vector2, Vector3, Vector4, Color, and Rotation. Rotations use spherical interpolation (slerp) automatically. Animations clean up automatically when complete. For infinite animations, call destroy() to stop, or they clean up when the scene ends. - `createBox(width: number, height: number, depth: number, cornerRadius: number, options: Object)` → `ObjectDescriptor` - Create a box primitive descriptor - `createSphere(radius: number, options: Object)` → `ObjectDescriptor` - Create a sphere primitive - `createPlane(orientation: string | number, width: number, height: number, cornerRadius: number)` → `ObjectDescriptor` - Create a plane primitive - `createModel(urlOrId: string, options: Object)` → `ObjectDescriptor` - Create a 3D model object descriptor - `createMedia(kind: string, urlOrId: string, width: number, aspectRatio: number, options: Object, options.cornerRadius: number, options.doubleSided: boolean, options.showLoading: boolean, options.immersive: boolean, options.video: Object, options.video.volume: number, options.video.loops: boolean, options.video.stream: boolean)` → `ObjectDescriptor` - Create a visual media object (image, video, or animated GIF) - `createImage(urlOrId: string, width: number, aspectRatio: number, options: Object)` → `ObjectDescriptor` - Create an image - `createVideo(urlOrId: string, width: number, aspectRatio: number, options: Object)` → `ObjectDescriptor` - Create a video - `createAnimatedGif(urlOrId: string, width: number, aspectRatio: number, options: Object)` → `ObjectDescriptor` - Create an animated GIF - `createContainer(children: Array)` → `ObjectDescriptor` - Create a container/composition - `createPanel(content: Object, options: Object, options.panelSize: any | any | Array | any)` → `any` - Build a UI panel descriptor wrapping the given root view. Pass to `scene.createEntity(panel)` to instantiate. - `createMesh(opts: Object, opts.vertexCapacity: number, opts.indexCapacity: number, opts.indexType: string, opts.attributes: Object, opts.parts: Array, opts.materials: Array, opts.interleavedGroups: Array>)` → `ObjectDescriptor` - Create a scriptable dynamic mesh with CPU-driven vertex/index updates. Returns an ObjectDescriptor -- pass to `scene.createEntity(...)`. After the entity loads, reach the mesh via `entity.representation.mesh` and write buffer data with `mesh.writeVertices(...)` / `mesh.writeIndices(...)`. Bytes flow straight from `Float32Array` / `Uint32Array` into the GPU-side buffer -- single memcpy per call, no per-element overhead. ## Static Extensions ### `Rotation` - `Rotation.quaternion(x: number, y: number, z: number, w: number)` → `Rotation` - Create a rotation from quaternion components ### `Color` - `Color.rgb(r: number, g: number, b: number)` → `Color` - Create a color from RGB values (alpha defaults to 1) - `Color.hex(hex: string)` → `Color | null` - Create a color from hex string - `Color.hsl(h: number, s: number, l: number)` → `Color` - Create a color from HSL values - `Color.white()` → `Color` - White color (1, 1, 1, 1) - `Color.black()` → `Color` - Black color (0, 0, 0, 1) - `Color.red()` → `Color` - Red color (1, 0, 0, 1) - `Color.green()` → `Color` - Green color (0, 1, 0, 1) - `Color.blue()` → `Color` - Blue color (0, 0, 1, 1) - `Color.clear()` → `Color` - Transparent color (0, 0, 0, 0) ### `Math` - `Math.toRadians(degrees: number)` → `number` - Convert degrees to radians - `Math.toDegrees(radians: number)` → `number` - Convert radians to degrees - `Math.lerp(a: number, b: number, t: number)` → `number` - Linear interpolation between two values - `Math.clamp(value: number, min: number, max: number)` → `number` - Clamp value between min and max - `Math.map(value: number, inMin: number, inMax: number, outMin: number, outMax: number)` → `number` - Map value from one range to another - `Math.fract(x: number)` → `number` - Get fractional part of number - `Math.smoothstep(edge0: number, edge1: number, x: number)` → `number` - Smooth interpolation with easing