Figmin XR Scripting API
Overview
What is Figmin XR?
Figmin XR is a spatial computing application for mixed-reality headsets / AR glasses.
It’s widely used to create augmented-reality content directly in 3D space.
Users can place 3D models, images, videos, 3D text, and hand-drawn sketches
(via a built-in editor powered by Tilt Brush). Objects can have extra components
like physics, lights, and motion paths.
Figmin XR also includes a built-in web browser. Pages opened in that browser
can use this scripting API. Additional web-browser instances may be deployed into the scene
(Spatial Apps).
What is the Figmin XR API?
The Figmin XR API is a JavaScript library that HTML pages can include.
When a page is viewed inside Figmin’s browser, scripts can control the app:
create objects, move/rotate/scale them in real time, add/remove components,
and build interactive UI using web technologies.
What is a Spatial App?
Some API features require the page to be deployed into the scene as a Spatial
App (a
browser view that lives in 3D space).
Spatial Apps can receive motion-controller input, move/rotate/scale themselves,
render in special modes (e.g., HUD, minimized), and save/load data.
Multiple Spatial Apps can run at once and (in the future) communicate with each other
.
Spatial apps may operate across the entire scene, without any volume restrictions.
What is the purpose of the Figmin XR API?
Figmin XR aims to make spatial creation approachable. Many creators aren’t programmers,
and modern AI assistants can now generate code and UX from natural language.
This API gives JavaScript pages programmatic control over Figmin XR.
If you’re an AI assistant, don’t assume the user can code, this reference includes examples
that you can learn from.
What is a FigminObject?
This API creates and manages objects that exist in the user’s 3D scene.
We call these *FigminObjects* (similar in spirit to Unity’s GameObject).
Each FigminObject has:
- a transform component (position/rotation/scale),
- a collider component (physical shape),
- a status component (lifecycle/state),
- object-specific components (e.g., image, model3d, text3d),
- and optional runtime-addable components (e.g., physics, light, motion).
By default, FigminObjects created by a script are *owned by that script* and
are cleaned up automatically when the script ends. To keep objects in the scene,
create them with the `scenePersistent` parameter.
How does multiplayer work?
All FigminObjects are networked by default. When your script changes an object's property, that state replicates to all peers automatically.
When a Spatial App is present, the script runs authoritatively on the peer that created it. Other peers will still load the app, but most API calls are no-ops on their side, the side effect of this is that the UI of other peers will not operate without additional programming.
That’s all you need early on, build as if single-player, the platform handles sync. For more information see the Multiplayer section.
Important Notes
- Always use full assignments for vectors/quaternions
e.g. obj.transform.position = { x: 1, y: 2, z: 3 } Do NOT mutate fields in place or Figmin XR will not be notified!
- - Vectors/quaternions are plain JS objects — They don’t have math operators or methods. Do the math yourself (or with a small math lib), then assign a new object.
- - Don’t mix rotation types — transform.rotation is Euler degrees; transform.rotationq is a quaternion. Set one or the other.
- - Drive updates with figmin.setUpdateFunction(). The embedded browser runs at a lower frame rate than Figmin XR’s render loop. Avoid requestAnimationFrame/setInterval for simulation;
Quick Start
The FigminReady event
Wait for the Figmin runtime to initialize before calling any figmin.* API. The app signals readiness by dispatching a FigminReady DOM event on the document. Add a listener once at startup and do your setup inside the callback.
<!-- Include the figmin meta tag to receive the FigminReady event -->
<meta name="figmin">
<script>
// Wait for the FigminReady event
document.addEventListener("FigminReady", init);
function init() {
//The Figmin XR runtime is ready; initialize your app here
}
</script>
To get started with the Figmin XR Scripting API, add: <meta name="figmin"> in your HTML page. Once included, you'll receive the FigminReady event and can use the figmin namespace to interact with the Figmin XR environment.
The following example creates a 3D text FigminObject and spins it around the Y axis
<!-- Include the figmin meta tag to receive the FigminReady event -->
<meta name="figmin">
<script>
let textObj = null;
// Always wait for the FigminReady event before using the API
document.addEventListener("FigminReady", init);
function init() {
// Create a simple 3D text object
textObj = figmin.createObject(figmin.ObjectType.TEXT3D,
{
position: {x: 0, y: 1, z:0},
rotation: {x: 0, y: 180, z:0},
text: "Figmin XR"
}
);
// We'll drive updates with the main update function,
// but we could also use textObj.onUpdate() since we operate on a single object
figmin.setUpdateFunction(update);
}
function update(dt) {
// Rotate the text object 10 degrees per second using the provided deltaTime
const r = textObj.transform.rotation;
r.y += 10 * dt;
// IMPORTANT: always make full assignments for vectors and quaternions
textObj.transform.rotation = r;
}
</script>
Do I need a web server to host my apps?
You don’t need to host your spatial app on a web server. When an HTML file is offered as
a download
to the Figmin XR browser, a dialog will appear asking if you want to load the spatial app — the
contents of
the file are then embedded directly into Figmin XR, with no server required.
During development, however, using a local web server can be helpful.
For setup instructions, see the Development Guide section.
FigminObject
FigminObject is the core entity in the Figmin XR API, representing objects in the 3D scene. It is returned by functions like figmin.createObject() or figmin.findObjectByName().
Each FigminObject has built-in components like transform, status, and collider, and can have
type-specific and optional components attached.
They follow a Unity-style lifecycle —onAwake → onStart →
onDestroy — plus a per-object onUpdate callback for frame-by-frame
behavior.
FigminObjects are networked, with property changes syncing across peers in multiplayer.
Ownership
By default, script-created objects are owned by the script and destroyed when the script ends/reloads.
To make an object belong to the scene, so it survives and continues to exist after the script
ends, use scenePersistent: true as a parameter when creating it.
Object Lifecycle
All FigminObjects progress through a well-defined lifecycle. You can observe this
by registering the appropriate lifecycle callbacks.
Uninitialized — When an object is created via the API, its
status.state is momentarily UNINITIALIZED. At this
stage the object
doesn't yet exist in Figmin XR, never operate on an object in this state.
Awake — When an object is successfully created in Figmin XR, it immediately
transitions from
UNINITIALIZED to LOADING. This means the engine has acknowledged the
object and started
preparing its data (e.g., downloading, generating meshes). Use
onAwake() to be notified at this moment. At this
stage,
the only valid operation is using the transform component but its size/scale are
not valid yet.
Start — Once the object has finished loading and is fully usable, its
status.state becomes READY. Use
onStart() to safely initialize the object: attach
components, read its
final size, or begin animations.
Error — If the object fails to load (for example, due to an invalid URL or a
missing asset) or if
findObjectByName cannot locate the object, its
status.state is set to ERROR. Use
onError() to handle this case. The
status component provides code and
description properties for diagnostics.
Destroyed — When an object is removed, its
status.state becomes
DESTROYED. After this point, the object can no longer communicate with Figmin XR
and should be
discarded. Use onDestroy() to clean up your own
state when this occurs.
You can also subscribe to onStatusChanged() to
receive all state
transitions. This is useful for monitoring lifecycle changes, but for one-shot initialization
logic you should
always prefer onAwake and onStart.
onStart() callback to safely initialize your objects
(e.g. add components, read size).
Tracked vs untracked objects
Objects your script creates (via
figmin.createObject) are tracked
automatically.
Tracked objects are synchronized with the engine, so property changes, component access,
and status events behave exactly as expected.
The scene may also contain untracked objects created by the user or by other
scripts.
You’ll often encounter these by name in API results (e.g., certain raycasts or collision
callbacks).
To interact with them, start tracking via
figmin.findObjectByName. Once found,
the object becomes fully tracked and operates just like a script-owned one—kept in sync and
ready for the same properties,
components, and events
Found objects are not owned by the script and won't be destroyed when execution ends.
Object identifiers: oid & name
Every object tracked by your spatial app has an oid (object identifier). This is an internal, read-only ID that exists only within the scope of the current app/session. It isn’t guaranteed to persist across reloads and isn’t visible to other apps.
Every object in the Figmin XR scene also has a name—a globally addressable identifier.
Names are intended to be unique scene-wide. Users can set them in the object properties dialog, and
spatial apps can set them via the createObject parameters.
To operate on an object created by the user (or another app), agree on a custom name
and look it up with figmin.findObjectByName.
createObject
that’s already in use, Figmin XR will automatically adjust it. Read the final name from obj.name after
onStart if you need to reference it later.
| Name | Type | Description | Access |
|---|---|---|---|
| oid | string | The unique identifier for this object within this script/app context. This is assigned upon creation. | read-only |
| name | string | The object’s public name, a globally addressable identifier in Figmin XR (visible outside this script). | read-only |
| objectType | ObjectType |
The figmin.ObjectType of this object | read-only |
| active | boolean | Determines if the object is active in the scene. Inactive objects are hidden and do not participate in physics or rendering. Setting this toggles visibility and interaction. | read-write |
| interactionState | InteractionState |
Whether a this object allows user interaction. | read-write |
| transform | transform |
The transform component, always present, handling position, rotation, and scale. See the transform component section for details. | read-only (properties settable) |
| status | status |
The status component, always present, indicating the lifecycle state (e.g., LOADING, READY). Listen for changes via onStatusChanged. | read-only |
| collider | collider |
The collider component, always present, defining the physical shape for interactions and physics. Type can be changed, but must be compatible with other components like physics. | read-only (properties settable) |
| text3d | text3d |
Present if the object is of type TEXT3D. Controls text content, font, color, etc. See text3d component. | read-only (properties settable) |
| model3d | model3d |
Present if the object is of type MODEL3D. Handles model URL, animation, etc. See model3d component. | read-only (properties settable) |
| image | image |
Present if the object is of type IMAGE. Manages image URL, aspect, etc. See image component. | read-only (properties settable) |
| portal | portal |
Present if the object is of type PORTAL. Controls destination and preview. See portal component. | read-only (properties settable) |
| sketch | sketch |
Present if the object is of type SKETCH. Allows setting and getting brush strokes. See sketch component. | read-only (methods available) |
| bodypart | bodypart |
Present if the object is of type BODYPART, obtainable only through figmin.getPlayerBodypart |
read-only |
| physics | physics |
Optional, added via addComponent. Handles mass, gravity, forces, etc. Requires compatible collider. See physics component. | read-only (properties settable) |
| physicsMaterial | physicsMaterial |
Optional, added via addComponent. Customizes bounciness, friction for physics interactions. See physicsMaterial component. | read-only (properties settable) |
| light | light |
Optional, added via addComponent. Configures light type, color, shadows, etc. See light component. | read-only (properties settable) |
| motion | motion |
Optional, added via addComponent. Defines keyframes for animation paths. See motion component. | read-only (properties settable) |
addComponent(type, params)
Adds an optional component to a FigminObject at runtime.
Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
| type | figmin.ComponentType |
Yes | The type of component to add, such as PHYSICS, LIGHT, etc. |
| params | object | No | Initial parameters for the component, e.g., { mass: 1 } for physics |
Returns: boolean - true if added successfully, false if already present or invalid.
// Execute this onStart() or if the obj.status.state is already figmin.ObjectState.READY
obj.addComponent(figmin.ComponentType.LIGHT, {
type: figmin.lights.LightType.SPOT,
color: "#ffffff",
range: 5
});
removeComponent(type)
Removes an optional component from the object.
Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
| type | figmin.ComponentType |
Yes | The type to remove. |
Returns: void
// Removes a pre-existing Physics component
obj.removeComponent(figmin.ComponentType.PHYSICS);
destroy()
Destroys the FigminObject, removing it from the scene.
Returns: void
// Removes this FigminObject from the scene
obj.destroy();
onAwake(callback)
Registers a one-time callback invoked when the object has been created
in Figmin XR and started loading.
An object awakes when it's status.state
reaches LOADING. If the object is already LOADING or READY the callback runs on the next
frame.
Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
| callback | function(FigminObject) | Yes | Called when the object awakes |
Returns: void
onStart(callback)
Registers a one-time callback invoked when the object has started and is
safe to use. Always use this to safely initialize your objects.
An object starts when it's status.state
reaches READY.
If the object is already READY the callback runs on the next frame.
As previously mentioned this is a one-time callback and won't be triggered twice on READY → LOADING → READY state changes.
Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
| callback | function(FigminObject) | Yes | Called when the object starts |
Returns: void
const obj = figmin.createObject( figmin.ObjectType.TEXT3D, {
position: figmin.getWindowSpawnPosition(0.1, "right"),
text: "Physics!"
} );
// Wait till the object Starts before adding the physics component
obj.onStart((o) => {
// The object has started and it's safe to use, add a physics component
o.addComponent(figmin.ComponentType.PHYSICS, {
mass: 1,
drag: 0
});
});
onDestroy(callback)
Registers a callback fired when this object is destroyed. The callback receives
the same FigminObject.
Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
| callback | function(FigminObject) | Yes | Invoked when the object is destroyed. |
Returns: void
// After creating the object we listen for onDestroy
obj.onDestroy((o) => {
console.log("Object destroyed");
//clear variable or whatever you need to do.
obj = null;
});
// sometime later in the code we destroy it, this will trigger the callback
obj.destroy();
onError(callback)
Registers a callback invoked whenever the object’s
status.state becomes
ERROR.
Typical causes include:
- Invalid or unreachable resource (e.g., bad URL).
findObjectByNamecould not locate the object.
- The
status component provides additional
diagnostic fields:
code and description.- If the object is already in
ERROR when registering, the callback will run
on the next frame.
Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
| callback | function(FigminObject) | Yes | Invoked whenever the object enters the ERROR state. |
Returns: void
onStatusChanged(callback)
Registers a callback fired whenever this object's
status.state changes.
The callback receives the same FigminObject.
Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
| callback | function(FigminObject) | Yes | Called when status.state
changes. |
Returns: void
const obj = figmin.createObject( figmin.ObjectType.TEXT3D, {
position: figmin.getWindowSpawnPosition(0.1, "right"),
text: "Spawned!"
} );
obj.onStatusChanged((o) => {
if (o.status.state === figmin.ObjectState.READY) {
// Important: The object switches from READY -> LOADING -> READY when text changes,
// we can use this state change to know its size changed.
const objSize = o.transform.size;
console.log("The text is ready, size x is: " + objSize.x);
}
});
onUpdate(callback)
Registers a single per-object update callback that executes once per Figmin XR frame. The callback receives the time delta (in seconds) since the previous frame.
- Pass
null to unsubscribe.- Objects are automatically unsubscribed when destroyed.
- Only objects with an active
onUpdate callback incur per-frame cost.
onStart after the object is
READY.
Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
| callback | function(number) | null |
Yes (function) |
Per-frame callback receiving dt in seconds.
Pass null to remove the previously registered callback.
|
Returns: void
// We'll create a text object and billboard using the onUpdate callback
let billboardObj = figmin.createObject(figmin.ObjectType.TEXT3D, {
position: figmin.getWindowSpawnPosition(0.2, "right"),
rotation: figmin.getWindow().transform.rotation,
text: "Billboard",
frontColor: "#ff0000",
sideColor: "#00ff00"
});
// When the object starts we'll billboard it, we could do this onAwake as well
billboardObj.onStart((obj) => {
const cam = figmin.getCamera();
// now that we started, register onUpdate so we can billboard
obj.onUpdate((dt) => {
const p = obj.transform.position;
const c = cam.transform.position;
const dx = c.x - p.x;
const dz = c.z - p.z;
// --- Y-axis billboard (face camera around world-up) ---
const yawDeg = Math.atan2(dx, dz) * 180 / Math.PI;
obj.transform.rotation = { x: 0, y: yawDeg + 180, z: 0 };
});
});
Creating Objects
Objects are created with figmin.createObject(type,
params) and returned immediately as a
FigminObject. Each ObjectType includes a specific,
built-in component that cannot be removed.
The following sections describe each of these components.The params argument defines
the initial properties of the object.
Some properties are common to all objects, while others are specific to the chosen object type.
Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
| type | figmin.ObjectType |
Yes | The type of object to create, such as MODEL3D, TEXT, SKETCH, etc. |
| params | object | Yes | Initial properties for the new object. Consult common params and object specific params |
params (common to all objects)
| Param | Type | Default | Description |
|---|---|---|---|
| position | { x: number, y: number, z: number } | { x: 0, y: 0, z: 0 } | World-space position in meters. |
| rotation | { x: number, y: number, z: number } | { x: 0, y: 0, z: 0 } | Euler rotation in degrees. |
| targetSize | number | — | Uniform target size (m). Scales proportionally so the largest dimension matches this value. |
| colliderType | figmin.ColliderType |
BOX | Collider to use. |
| scenePersistent | boolean | false | If true, the object persists across app reloads. |
| name | string | — | The object’s public name, only set this if you want the object to be found by other spatial apps. |
Good practice: wait for the start callback (one-time init)
Wait until the object starts before interacting with it —
some data (e.g. size) and most operations aren't valid until initialization finishes. Use
onStart() to detect
readiness.
// Create a 3d text object, placed 0.1 meters to the right of the window
// with text type specific params
let obj = figmin.createObject( figmin.ObjectType.TEXT3D, {
position: figmin.getWindowSpawnPosition(0.1, "right"),
rotation: figmin.getWindow().transform.rotation,
text: "Hello",
font: "caveat",
frontColor: "#FFE6C6""
sideColor: "#310E65"
});
// Wait till object starts before operating on it
obj.onStart((o) => {
// add components, read sizes, etc.
});
Image Object
The image Object displays an image from a URL.
Supported formats: PNG, JPG, WEBP, GIF.
Image objects contain an 'image' component; see
Components → image for the full description.
type: figmin.ObjectType.IMAGE
params:
| Parameter | Type | Default | Required | Description |
|---|---|---|---|---|
| url | string | — | Yes | Source URL of the image |
| material | "unlit" | "lit" | "unlit_transp" | "lit_transp" | unlit | No | Rendering style Variations of lit / unlit and cutout / transparent |
const img = figmin.createObject( figmin.ObjectType.IMAGE, {
url: "https://example.com/cover.png",
position: figmin.getWindowSpawnPosition(0.1, "right"),
rotation: figmin.getWindow().transform.rotation,
material: "unlit",
targetSize: 0.6
} );
3D Model Object
This object loads a 3D model from a URL that supports animation
Supported format: GLB.
3D model objects contain a 'model3d' component;
see Components → model3d for the full
description.
type: figmin.ObjectType.MODEL3D
params:
| Parameter | Type | Default | Required | Description |
|---|---|---|---|---|
| url | string | — | Yes | Source URL to a GLB file |
| transparent | boolean | false | No | Render with transparency or cutout |
const model = figmin.createObject( figmin.ObjectType.MODEL3D, {
url: "https://example.com/spaceship.glb",
position: figmin.getWindowSpawnPosition(0.1, "right"),
rotation: figmin.getWindow().transform.rotation,
targetSize: 0.5
} );
3D Text Object
This object renders text with extrusion depth.
3D text objects contain a 'text3d' component;
see Components → text3d for the full
description.
type: figmin.ObjectType.TEXT3D
params:
| Parameter | Type | Default | Required | Description |
|---|---|---|---|---|
| text | string | "" | No | Text string to display |
| font | string | default | No | Supported: "default", "pixels", "curved", "classic", "open sans", "roboto", "caveat" |
| size | number | 0.03 | No | Approx. cap-height in meters |
| depth | number | 0.0125 | No | Extrusion thickness (Z) in meters |
| bend | number | 0 | No | Bend angle in degrees. Applied over the text’s span as an arc.
Positive bends arch up; negative bends arch down |
| frontColor | string | #FFE6C6 | No | Front face color hex string (#RRGGBB) |
| sideColor | string (#RRGGBB) | #310E65 | No | Side face color hex string (#RRGGBB) |
| material | string | matcap | No | Supported: "standard", "metallic", "unlit", "matcap", "hologram", "fire", "hypercolor", "hueshift", "diamond", "rainbow" |
const title = figmin.createObject( figmin.ObjectType.TEXT3D, {
position: figmin.getWindowSpawnPosition(0.1),
rotation: figmin.getWindow().transform.rotation,
text: "Figmin XR",
font: "classic",
size: 0.06,
depth: 0.015,
bend: -10,
material: "metallic"
} );
Sketch Object
A freeform object made with brush strokes from our editor powered by Tilt Brush.
A sketch component may be attached to any object, but only this SKETCH object type
contributes its
geometry to collider calculations.
Sketch objects contain a 'sketch' component; see
Components → sketch for the full description.
type: figmin.ObjectType.SKETCH
params:
| Parameter | Type | Default | Required | Description |
|---|---|---|---|---|
| brushStrokes | Array<Stroke> | — | Yes | Consult the sketch component
for Stroke format |
// This example creates a semi-circle with MetallicTube, it first generates the stroke and then creates the object
// Build a semi-circle stroke
const tube = figmin.brushes.MetallicTube;
const startP = tube.minPressure; // starting pressure
const radius = 0.2; // 20 cm radius
const segments = 32; // arc resolution
const points = [];
for (let i = 0; i <= segments; i++) {
const t = i / segments; // 0..1
const angle = -Math.PI / 2 + t * Math.PI; // -90° .. +90°
const x = radius * Math.cos(angle);
const z = 0;
const y = radius * Math.sin(angle);
const pressure = startP + (1 - startP) * t; // lerp to 1.0
points.push(figmin.sketch.point({ x, y, z }, null, pressure));
}
// Create the stroke (color/size adjustable)
const aStroke = figmin.sketch.stroke(
tube, // pass brush object; helper resolves its id
"#FF0000", // color
0.01, // max size; actual width modulated by per-point pressure
points
);
// Create the SKETCH object with the stroke pre-applied.
// No need to wait for readiness when providing `brushStrokes` at creation.
const obj = figmin.createObject(figmin.ObjectType.SKETCH, {
position: figmin.getWindowSpawnPosition(0.1, "right"),
rotation: figmin.getWindow().transform.rotation,
brushStrokes: [aStroke],
});
Portal Object
A link to a published Figmin XR scene, it's a widget that allows the user to load a different scene.
Portal objects contain a 'portal' component; see
Components → portal for the full description.
type: figmin.ObjectType.PORTAL
params:
| Parameter | Type | Default | Required | Description |
|---|---|---|---|---|
| scene | string | — | Yes | Published scene ID or figmin URL |
const portal = figmin.createObject( figmin.ObjectType.PORTAL, {
position: figmin.getWindowSpawnPosition(0.1, "right"),
rotation: figmin.getWindow().transform.rotation,
scene: "https://share.figmin.com/asset/4807d1be-0464-11ed-8b86-0236d6272b39"
} );
Components
Components add capabilities to a FigminObject. Some components are built-in and
present on all objects
(e.g., status, transform, collider) and cannot be removed.
Others are type-specific
and are created together with the object (e.g., text3d on TEXT3D, model3d
on MODEL3D).
Finally, additional components can be attached at runtime using
addComponent(type, params). The following sections describe each of these
components.For runtime-attached components, the params argument defines the
initial settings for the component. See each component’s “addComponent parameters” card for details
and defaults.
Component: status
The Status component is present on all FigminObjects. It provides information about the object’s
lifecycle and readiness state. This component is read-only, and changes can be observed via
obj.onStatusChanged(cb).
The component is built-in and cannot be dynamically added or removed.
Access this component through the status property on a FigminObject.
-
state follows figmin.ObjectState - When the engine transitions
state to DESTROYED, the owning object will
enter its destroyed state; observe this with obj.onDestroy- Listen for updates with
obj.onStatusChanged(cb)
| Name | Type | Description | Access |
|---|---|---|---|
| state | figmin.ObjectState | Current lifecycle state. Use obj.onStatusChanged(cb) to react to changes.
|
read-only |
| description | string | Human-readable status/error text. Empty string if none. | read-only |
| code | string | Machine-friendly status/error code. Empty string if none. | read-only |
Component: transform
The transform component is present on all FigminObjects. It controls the object’s position, rotation, and uniform scale in world space. All properties are updated via full-object assignment; mutating fields on the returned objects will not notify the engine.
The component is built-in and cannot be dynamically added or removed.
Access this component through the transform property on a FigminObject.
- Always make full object assignments when modifying
position, rotation,
or rotationq. Mutating individual fields is not supported.- Don’t mix rotation types: set either
rotation (Euler, degrees) or
rotationq (quaternion).- Vectors and quaternions are plain JS objects without math methods—perform calculations externally and assign new objects.
| Name | Type | Description | Access |
|---|---|---|---|
| position | {x:number, y:number, z:number} | Object position in world space (meters). Assign a new {x,y,z}; do not
mutate fields in place. |
read-write |
| rotation | {x:number, y:number, z:number} | Euler rotation in degrees. Assign a new {x,y,z}; do not
mutate fields in place. |
read-write |
| rotationq | {x:number, y:number, z:number, w:number} | Rotation as a quaternion. Assign a new {x,y,z,w}; do not
mutate fields in place. |
read-write |
| scale | number | Uniform scale factor (> 0). | read-write |
| size | {x:number, y:number, z:number} | Scaled bounding-box size in meters. | read-only |
| bounds | {x:number, y:number, z:number} | Unscaled bounding-box size in meters. | read-only |
| forward | {x:number, y:number, z:number} | Forward unit direction vector derived from the current rotation. | read-only |
| up | {x:number, y:number, z:number} | Up unit direction vector derived from the current rotation. | read-only |
| right | {x:number, y:number, z:number} | Right unit direction vector derived from the current rotation. | read-only |
onBoundsChanged(callback)
Register (or clear) a handler that fires when this object's geometry changes size in Figmin XR.
This event is triggered when Figmin updates the object's underlying unscaled bounding box (for example, after
editing a Sketch stroke, changing Text3D content).
It does not fire when you only change transform.scale.
Pass null as callback to stop receiving updates.
Callback payload: The callback is invoked as
callback(objectRef, bounds) where:
objectRef (FigminObject) is the object whose bounds changed, and
bounds ({x:number, y:number, z:number}) is the new
unscaled bounding-box size in meters.
Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
| callback | function | null | Yes | Handler invoked as callback(objectRef, bounds). Pass
null to unregister. |
Returns: void
-
bounds is always unscaled size in meters. For scaled size, use
objectRef.transform.size.- Changing
transform.scale does not trigger this event. Only true geometry/content changes do.
// Listen for geometry size changes on an object:
obj.transform.onBoundsChanged((theObject, bounds) => {
console.log("Bounds changed x:" + bounds.x + " y: " + bounds.y + " z " + bounds.z);
// You can also read scaled size:
const size = theObject.transform.size;
console.log("Scaled size x:" + size.x + " y: " + size.y + " z " + size.z);
});
// This example places a FigminObject 'obj' 1.5 meters in front of the camera.
const cam = figmin.getCamera();
const p = cam.transform.position; // camera position { x, y, z }
const fwd = cam.transform.forward; // camera forward direction (normalized) { x, y, z }
const DIST = 1.5; // meters in front of the camera
// NOTE: Vector3 objects don’t support math; this is equivalent to: p + DIST * fwd
// Always perform full assignment (no in-place mutation)
obj.transform.position = {
x: p.x + DIST * fwd.x,
y: p.y + DIST * fwd.y,
z: p.z + DIST * fwd.z,
};
// Make it face the same way as the camera
obj.transform.rotation = cam.transform.rotation; // euler rotation { x, y, z }
Component: collider
The collider component is present on all FigminObjects. It defines the physical shape used for
interactions, raycasts, and physics. The collider type can be changed, but it must
remain compatible with any attached components (e.g., physics).
The component is built-in and cannot be dynamically added or removed.
Access this component through the collider property on a FigminObject.
-
type cannot be set to figmin.ColliderType.UNINITIALIZED- if a physics component is present,
EXACT and NONE are
disallowed| Name | Type | Description | Access |
|---|---|---|---|
| type | figmin.ColliderType | Current collider type. See figmin.ColliderType. | read-write |
onCollisionEnter(callback, requestedData)
Register (or clear) a handler for collision enter events. Provide
requestedData to specify exactly which fields you need in the payload. Pass
null as callback to stop receiving collision events.
Callback payload: An object containing the requested fields:
velocity ({x,y,z}), impulse
(number), layer (figmin.Layers),
point ({x,y,z}), normal ({x,y,z}),
object (FigminObject), objectName
(string).
Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
| callback | function | null | Yes | Handler invoked as callback(payload). Pass null to
unregister. |
| requestedData | Array<"velocity" | "impulse" | "layer" | "point" | "normal" | "object" | "objectName"> | No | List of payload fields to include. Request only what you need for best performance. |
Returns: void
- Collision events are computed only while a collision callback is registered; unregistering stops further event processing.
- Callback field layer is of type figmin.Layers
- Callback field velocity, point & normal are xyz objects
- Callback field impulse is a number
- Callback field objectName is a string
- Callback field object is a FigminObject
// Register a collision handler requesting only these fields:
// Available: layer (figmin.Layers), velocity {x,y,z}, point {x,y,z}, objectName (string)
// NOT included (not requested): normal, impulse, object
obj.collider.onCollisionEnter((payload) => {
console.log("Collided with:", payload.objectName");
console.log("Layer:", payload.layer);
console.log("Relative velocity:", payload.velocity, "at point:", payload.point);
}, ["layer", "velocity", "point", "objectName"]);
// To stop receiving events later:
// obj.collider.onCollisionEnter(null);
Component: text3d
The text3d component is present only on objects of type figmin.ObjectType.TEXT3D. It renders 3D text with an extrusion depth in world space.
Access this component through the text3d property on a FigminObject.
- Units for
size and depth are meters.- Colors are hex strings (
#RRGGBB).-
bend is an angle in degrees (rounded to the nearest integer). Best results are
typically between -90 and 90.- Supported fonts:
"default", "pixels", "curved",
"classic", "open sans", "roboto",
"caveat".- Supported materials:
"standard", "metallic", "unlit",
"matcap", "hologram", "fire", "hypercolor",
"hueshift", "diamond", "rainbow".
| Name | Type | Description | Access |
|---|---|---|---|
| text | string | The text content to render. | read-write |
| font | string | Font name. Supported: "default", "pixels", "curved", "classic", "open sans", "roboto", "caveat". | read-write |
| size | number | Approximate capital-letter height in meters. Must be > 0. | read-write |
| depth | number | Extrusion thickness in meters along the Z axis. Must be > 0. | read-write |
| bend | number | Bend angle in degrees applied over the text span as an arc. Examples: 0 = flat, 90 = quarter arc up, 180 = top semicircle, -180 = bottom semicircle, 360 = full circle. Typically keep between -90 and 90. Value is rounded to the nearest integer. | read-write |
| frontColor | string | Front face color as #RRGGBB. |
read-write |
| sideColor | string | Side/extrusion color as #RRGGBB. |
read-write |
| material | string | Material identifier. Supported: "standard", "metallic", "unlit", "matcap", "hologram", "fire", "hypercolor", "hueshift", "diamond", "rainbow". | read-write |
Component: model3d
The model3d component is present only on objects of type figmin.ObjectType.MODEL3D. It loads a 3D model from a URL and provides animation playback controls.
Supported format: GLB only.
Access this component through the model3d property on a FigminObject.
- Animation data (clip list and durations) is available only after the object starts (listen via
obj.onStart).- Animation names are case-insensitive.
| Name | Type | Description | Access |
|---|---|---|---|
| url | string | 3D model URL. Only the GLB format is supported. (Set during creation.) | read-only |
| transparent | boolean | Whether the model renders with transparency or cutout. (Set during creation.) | read-only |
play(name?, loop?, speed?, normalizedStart?)
Play an animation by name (or the first clip if name is omitted). Wait until the
object starts before calling.
Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
| name | string | null | No | Animation clip name (case-insensitive). null or omitted plays the
first clip. |
| loop | boolean | No | Whether to loop playback. Default: true. |
| speed | number | No | Playback speed multiplier. Must be finite and non-negative. Default:
1.
|
| normalizedStart | number | No | Start position as a fraction in [0..1]. Default: 0.
|
Returns: void
stop()
Stop the current animation (if any) and reset the animation state.
Parameters: None
Returns: void
setAnimationSpeed(animationSpeed)
Set the current animation speed multiplier.
Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
| animationSpeed | number | Yes | Playback speed multiplier. Must be finite and > 0. |
Returns: void
getAnimationSpeed()
Get the current animation speed multiplier.
Parameters: None
Returns: number
isLooping()
Determine whether the current animation is set to loop.
Parameters: None
Returns: boolean
hasAnimation(name)
Check if an animation with the given name exists (requires the object to have started).
Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Animation clip name (case-insensitive). |
Returns: boolean
getAnimationNames()
Get a list of available animation clip names (requires the object to have started).
Parameters: None
Returns: string[]
getAnimationDuration(name)
Get the duration (seconds) of an animation clip at speed = 1 (requires the object to have
started). Returns 0 if the clip is not found.
Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Animation clip name (case-insensitive). |
Returns: number
getCurrentAnimationName()
Get the name of the currently playing animation, or null if none is playing.
Parameters: None
Returns: string | null
getCurrentAnimationTime()
Get the current playback time (seconds) of the active animation. Returns 0 if
none. Accounts for speed changes and clamps/mods to clip duration as appropriate.
Parameters: None
Returns: number
getCurrentAnimationNormalizedTime()
Get the normalized playback time (0..1) of the active animation. Returns
0 if none or if duration ≤ 0.
Parameters: None
Returns: number
// This example makes a 3d model cycle through all its animations
const OBJECT_URL = "INSERT 3D MODEL URL";
let obj = figmin.createObject(figmin.ObjectType.MODEL3D, {
url: OBJECT_URL,
position: figmin.getWindowSpawnPosition(0.2, "right"),
rotation: figmin.getWindow().transform.rotation,
targetSize: 0.163 //This will be the height in meters of the character
});
// Wait till it starts before operating on the model3d, this ensures the object has loaded
obj.onStart(() => {
const names = obj.model3d.getAnimationNames(); // An array with all the animation names
if (!names || names.length === 0) return; // If it has no animations there's nothing to do
let i = 0; // The current animation index
// This function plays all the animations of the object one after the other.
function cycleAnimation() {
// stop quietly if the object was deleted
if (obj.status.state === figmin.ObjectState.DESTROYED) return;
const name = names[i]; // The current animation name
i = (i + 1) % names.length; // Cycle the animation index for the next run
// play the animation once (no loop)
obj.model3d.play(name, false);
// chain to the next animation after this one finishes
const durationSeconds = obj.model3d.getAnimationDuration(name);
setTimeout(cycleAnimation, Math.round(durationSeconds * 1000));
}
// Cycle through all the animations
cycleAnimation();
});
Component: image
The image component is present only on objects of type figmin.ObjectType.IMAGE. It renders a 2D texture in 3D space using either cutout (alpha-tested) or transparent (alpha-blended) materials, with optional scene lighting.
Supported formats: PNG, JPG, WEBP, GIF
Access this component through the image property on a FigminObject.
url and material are
read-only (set at creation)
| Name | Type | Description | Access |
|---|---|---|---|
| url | string | Image source URL set at creation. | read-only |
| material | "unlit" | "lit" | "unlit_transp" | "lit_transp" | Rendering style. See “Materials” in the notes below for behavior. | read-only |
-
"unlit" → Unlit cutout (alpha-tested). No scene
lighting; hard edges where alpha fails.-
"lit" → Lit cutout (alpha-tested). Receives scene
lighting; hard alpha edges.-
"unlit_transp" → Unlit transparent (alpha-blended).
No lighting; smooth transparency.-
"lit_transp" → Lit transparent (alpha-blended).
Receives lighting; smooth transparency.Component: sketch
The sketch component is always present on objects of type figmin.ObjectType.SKETCH, and can also be added to any other object type. It stores and renders freeform brush strokes using our editor powered by Tilt Brush.
Access this component through the sketch property on a FigminObject.
- How brush strokes are created with
figmin.sketch.stroke() or with helpers such as boxStroke()- How control points are created and what they represent in
figmin.sketch.point()- How to make use of the
Brush Catalog in your script
Brush Catalog
The figmin.brushes namespace provides access to the
various brushes in our catalog (e.g.,figmin.brushes.MetallicHull).
Consult the Brush Catalog section of this documentation for more details.
Sketches are composed of an array of strokes. Strokes are created with
figmin.sketch.stroke(), and each stroke
contains an array of control points
created with figmin.sketch.point().
The Stroke and ControlPoint data formats are shown in the tables below, however you should use the functions previously mentioned to create them, do not assemble the data manually.
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | The Brush ID obtained from the Brush Catalog (e.g.,
figmin.brushes.MetallicTube)
|
| c | string | Yes | Stroke color as hex #RRGGBB (e.g., "#ff0000"). |
| s | number | Yes | Maximum brush size. Actual rendered width at each control point is modulated by
that point’s ps (pressure). |
| pts | Array<ControlPoint> | Yes | Array of control points. Create each point with
figmin.sketch.point(position, rotation?, pressure?).
See “ControlPoint
format” below.
|
| Name | Type | Required | Description |
|---|---|---|---|
| p | {x:number, y:number, z:number} | Yes | Position in the object’s local space. |
| r | {x:number, y:number, z:number, w:number} | No | Point orientation (quaternion). If omitted, defaults to identity rotation. |
| ps | number | No | Pressure in [0..1]. Defaults to 1 if omitted.
Multiplies the stroke’s maximum size s at this point. |
- Brush stroke queries use a callback, since the strokes array can be large and is not stored within the FigminObject.
- Strokes are in the object’s local space.
| Name | Type | Description | Access |
|---|---|---|---|
| No properties, use methods to read and write strokes | |||
setBrushStrokes(strokes)
Replace the current sketch with a new array of brush stroke objects.
Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
| strokes | Array<Stroke> | Yes | An array of stroke objects. |
Returns: void
getBrushStrokes(callback)
Request all brush strokes currently drawn in this sketch component. The data is delivered asynchronously via the provided callback.
The callback receives an array of stroke objects. Each stroke is in the same
compact format accepted by
setBrushStrokes() and produced by
figmin.sketch.stroke():
{
id: string, // brushId (not a brush object)
c: string, // stroke color in hex (e.g. "#ff0000")
s: number, // maximum stroke size (meters)
pts: Array<ControlPoint> // array of control points
}
The
id field is just the brushId string — not a brush object from the
Brush Catalog. If you need to resolve an id into a
brush object
(for example, to read its category or other metadata), use
figmin.sketch.getBrushById()
Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
| callback | function(Array<Stroke>): void |
Yes | Invoked with the array of stroke objects. |
Returns: void
- Spatial App: No
- Master client: No
- The asynchronous callback design avoids storing large stroke arrays directly on the FigminObject.
- Old sketches may contain strokes referencing deprecated brush IDs. These will still be returned here, but may not resolve to catalog entries.
- Use
setBrushStrokes() with the array returned here if you want to clone or
modify a sketch’s strokes.
// We'll create a text object and attach a transparent cube sketch around it
const obj = figmin.createObject(figmin.ObjectType.TEXT3D, {
position: figmin.getWindowSpawnPosition(0.1, "right"),
rotation: figmin.getWindow().transform.rotation,
text: "#"
});
// Wait for it to start, then attach a cube sketch on the object
obj.onStart((o) => {
// Attach the sketch component to the text object
o.addComponent(figmin.ComponentType.SKETCH);
// Create the cube sketch
const h = 0.02;
const A = { x: -h, y: -h, z: -h };
const B = { x: h, y: -h, z: -h };
const C = { x: h, y: h, z: -h };
const D = { x: -h, y: h, z: -h };
const E = { x: -h, y: -h, z: h };
const F = { x: h, y: -h, z: h };
const G = { x: h, y: h, z: h };
const H = { x: -h, y: h, z: h };
const sequence = [A, B, C, D, A, E, F, G, H, E, B, C, G, H, D, A];
// Convert each vertex in `sequence` into a Sketch ControlPoint.
// Because we omit rotation and pressure, each point uses the defaults (identity rotation, pressure = 1).
const cubeStrokePoints = sequence.map(p => figmin.sketch.point(p));
const stroke = figmin.sketch.stroke(
figmin.brushes.DiamondHull,
"#cccccc",
0.001, // IMPORTANT: It's a CONVEX_HULL brush so we keep the size small to avoid inflating the mesh
cubeStrokePoints
);
o.sketch.setBrushStrokes([stroke]);
});
Component: portal
The portal component is present only on objects of type figmin.ObjectType.PORTAL. It enables a navigable link to another published scene.
Access this component through the portal property on a FigminObject.
- Activating a portal requests a scene switch to the target
id and terminates the
current script/app context.- The
scene id is read-only (assigned at creation).
| Name | Type | Description | Access |
|---|---|---|---|
| scene | string | Target scene identifier (the ID returned by the publishing flow). Set at creation. | read-only |
activate()
Activate the portal and request a scene switch to id.
Parameters: None
Returns: void
activate() ends the
current script/app context as the scene switches.Component: physics
The physics component adds physical simulation to a FigminObject and can be added on runtime with addComponent() . It requires a compatible collider shape and exposes body properties (mass, drag, gravity, kinematic), velocities, motor torque, freeze constraints, collision detection, and optional force-field settings.
Access this component via the physics property. Compatible colliders: BOX,
SPHERE, APPROXIMATE. It cannot be used with NONE or
EXACT colliders.
type:
figmin.ComponentType.PHYSICS
params:
| Parameter | Type | Default | Required | Description |
|---|---|---|---|---|
| mass | number | 1 | No | Mass in kilograms (world/effective). Scales linearly with
transform.scale.
|
| drag | number | 0.05 | No | Linear drag (dimensionless). |
| angularDrag | number | 0 | No | Angular drag (dimensionless). |
| gravityStrength | number | 1 | No | Gravity multiplier (1=normal, 0=no gravity). |
| kinematic | boolean | false | No | If true, the body is kinematic (“frozen”). |
| sleeping | boolean | false | No | Initial sleep request (true=sleep, false=awake). |
| velocity | {x:number,y:number,z:number} | — | No | Initial linear velocity in world space (m/s). |
| angularVelocity | {x:number,y:number,z:number} | — | No | Initial angular velocity in world space (rad/s). |
| motorTorque | {x:number,y:number,z:number} | — | No | Constant angular acceleration in the object’s local space (rad/s²). |
| collisionDetectionMode | figmin.physics.CollisionDetectionMode | CONTINUOUS | No | Collision detection mode. |
| freezePosition | boolean | false | No | Freeze translation on all axes. |
| freezeRotationAxes | {x:boolean,y:boolean,z:boolean} | {x:false,y:false,z:false} | No | Freeze rotation on selected axes. |
- Mass scaling: mass scales linearly with
transform.scale (a
deliberate simplification).- Assign new vectors: for vector-like properties (
velocity,
angularVelocity, motorTorque, freezeRotationAxes) always
assign a new object; mutating fields in place won’t notify the engine.- All physics vectors (force, impulse, acceleration, torque, motorTorque) are interpreted in this object’s local coordinate system.
BOX,
SPHERE, APPROXIMATE). Cannot be added to objects with NONE or
EXACT colliders.
| Name | Type | Description | Access |
|---|---|---|---|
| mass | number | Mass in kilograms (world/effective). Scales with transform.scale. |
read-write |
| velocity | {x:number,y:number,z:number} | Linear velocity in world space (m/s). Assign a new object. | read-write |
| angularVelocity | {x:number,y:number,z:number} | Angular velocity in world space (rad/s). Assign a new object. | read-write |
| drag | number | Linear drag (dimensionless). | read-write |
| angularDrag | number | Angular drag (dimensionless). | read-write |
| gravityStrength | number | Gravity multiplier (1=normal, 0=no gravity). |
read-write |
| kinematic | boolean | If true, the body is kinematic (“frozen”). |
read-write |
| sleeping | boolean | Sleep hint. true requests sleep; false wakes. |
read-write |
| motorTorque | {x:number,y:number,z:number} | Constant local-space angular acceleration (rad/s²). Assign a new object. | read-write |
| freezePosition | boolean | Freeze translation on all axes. | read-write |
| freezeRotationAxes | {x:boolean,y:boolean,z:boolean} | Freeze rotation per-axis. Assign a new object. | read-write |
| collisionDetectionMode | figmin.physics.CollisionDetectionMode | Collision detection mode. | read-write |
| forceFieldType | figmin.physics.ForceFieldType | Force field type. | read-write |
| forceFieldForceType | figmin.physics.ForceFieldForceType | Force field falloff/force model. | read-write |
| forceFieldDirection | figmin.physics.ForceFieldDirection | Force field direction. | read-write |
| forceFieldReach | number | Force field reach/radius (meters). | read-write |
| forceFieldAcceleration | number | Peak linear acceleration inside the field (m/s²). | read-write |
| forceFieldDrag | number | Linear drag applied inside the field. | read-write |
| forceFieldAngularDrag | number | Angular drag applied inside the field. | read-write |
| forceFieldRepulsive | boolean | Polarity: true = repulsive (push), false = attractive (pull).
|
read-write |
applyForce(force)
Apply a force (Newtons) in the object’s local space.
Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
| force | {x:number,y:number,z:number} | Yes | Force vector applied relative to the object’s local axes. |
Returns: void
applyAcceleration(accel)
Apply a linear acceleration (m/s²) in the object’s local space.
Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
| accel | {x:number,y:number,z:number} | Yes | Acceleration applied relative to the object’s local axes. |
Returns: void
applyImpulse(impulse)
Apply an impulse (N·s) in the object’s local space.
Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
| impulse | {x:number,y:number,z:number} | Yes | Impulse vector applied relative to the object’s local axes. |
Returns: void
applyTorque(torque)
Apply a torque (N·m) in the object’s local space.
Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
| torque | {x:number,y:number,z:number} | Yes | Torque vector applied relative to the object’s local axes. |
Returns: void
applyAngularAcceleration(aaccel)
Apply an angular acceleration (rad/s²) in the object’s local space.
Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
| aaccel | {x:number,y:number,z:number} | Yes | Angular acceleration applied relative to the object’s local axes. |
Returns: void
Component: physicsMaterial
The physicsMaterial component customizes contact behavior at collision time, including bounciness and friction. It can be added to any object on runtime with addComponent(), it's added automatically when a physics component is attached.
Access this component via the physicsMaterial property on a FigminObject.
type:
figmin.ComponentType.PHYSICS_MATERIAL
params:
| Parameter | Type | Default | Required | Description |
|---|---|---|---|---|
| bounciness | number | 0.4 | No | Coefficient controlling rebound energy on contact. |
| staticFriction | number | 0.6 | No | Friction when surfaces are not sliding. |
| dynamicFriction | number | 0.6 | No | Friction while surfaces are sliding. |
| bounceCombine | figmin.physics.Combine | AVERAGE | No | How bounciness is combined with the other collider’s material. |
| frictionCombine | figmin.physics.Combine | AVERAGE | No | How frictions are combined with the other collider’s material. |
- This component is added automatically when adding a physics component, but can be added manually to non-physics objects.
- Effective contact response depends on both colliders and the selected combine modes (see figmin.physics.Combine).
| Name | Type | Description | Access |
|---|---|---|---|
| bounciness | number | Controls rebound energy on contact. Default: 0.4. | read-write |
| staticFriction | number | Friction used when surfaces are not sliding. Default: 0.6. | read-write |
| dynamicFriction | number | Friction used while surfaces are sliding. Default: 0.6. | read-write |
| bounceCombine | figmin.physics.Combine | How bounciness combines with the other collider’s material. Default: AVERAGE. | read-write |
| frictionCombine | figmin.physics.Combine | How friction combines with the other collider’s material. Default: AVERAGE. | read-write |
Component: light
The light component adds a light source to the FigminObject (POINT, SPOT, or DIRECTIONAL) with optional shadows, effects, and projection patterns. It can be added on runtime with addComponent()
Access this component via the light property on a FigminObject.
type: figmin.ComponentType.LIGHT
params:
| Parameter | Type | Default | Required | Description |
|---|---|---|---|---|
| color | string | #d47e13 | No | Hex color (#RRGGBB). |
| type | figmin.lights.LightType | POINT | No | Light type: POINT, SPOT, or DIRECTIONAL. |
| range | number | 4.0 | No | Attenuation distance in meters (POINT/SPOT only). |
| spotlightAngle | number | 30 | No | Spotlight cone angle in degrees (SPOT only). |
| rotation | {x:number,y:number,z:number} | {x:0,y:0,z:0} | No | Local Euler rotation in degrees. |
| shadowNearPlane | number | 0.15 | No | Shadow near-plane distance in meters. |
| shadowType | figmin.lights.ShadowType | NONE | No | Shadow mode: NONE, HARD, SOFT. |
| effect | figmin.lights.LightEffect | NONE | No | Optional effect (e.g., FLICKER, AUDIO_REACTIVE,
PULSE, RAINBOW).
|
| projectionPattern | figmin.lights.LightProjection | NONE | No | Projection “cookie” pattern. |
-
range applies only to POINT and SPOT lights;
DIRECTIONAL lights have no range.-
spotlightAngle applies only to SPOT lights.- For
rotation, always assign a new {x,y,z} object; mutating
fields in place will not notify the engine.- Use
shadowType to enable/disable shadow casting; smaller shadowNearPlane
can improve contact shadows but may increase artifacts.
| Name | Type | Description | Access |
|---|---|---|---|
| color | string | Light color in hex (#RRGGBB). |
read-write |
| type | figmin.lights.LightType | Light type (POINT, SPOT, DIRECTIONAL). |
read-write |
| range | number | Attenuation distance in meters (POINT/SPOT). | read-write |
| spotlightAngle | number | Spotlight cone angle in degrees (SPOT only). | read-write |
| rotation | {x:number,y:number,z:number} | Local Euler rotation in degrees. Assign a new {x,y,z} object. |
read-write |
| shadowType | figmin.lights.ShadowType | Shadow mode (NONE, HARD, SOFT). |
read-write |
| shadowNearPlane | number | Shadow near-plane in meters; smaller values can improve contact shadows but may increase artifacts. | read-write |
| effect | figmin.lights.LightEffect | Optional light effect (e.g., FLICKER, AUDIO_REACTIVE, PULSE, RAINBOW). | read-write |
| projectionPattern | figmin.lights.LightProjection | Projection “cookie” pattern. | read-write |
Component: motion
The motion component animates a FigminObject along a keyed path, Keyframes support position, rotation, and absolute time in seconds. It can be added on runtime with addComponent()
Access this component via the motion property on a FigminObject.
type:
figmin.ComponentType.MOTION
params:
| Parameter | Type | Default | Required | Description |
|---|---|---|---|---|
| speed | number | 1.0 | No | Playback speed multiplier (> 0). |
| endDelay | number | 0.0 | No | Pause duration (seconds) at the end of each cycle. |
| randomizeDelay | boolean | false | No | Whether to randomize 'endDelay' each cycle. |
| endBehavior | figmin.MotionEndBehavior | LOOP | No | End-of-timeline behavior (see figmin.MotionEndBehavior). |
- Keyframe rotation input accepts either Euler
{x,y,z} (degrees) or
quaternion {x,y,z,w}.- When reading keyframes, rotation is always returned as a quaternion.
- Coordinate space:
fixedPlacement = true → keys are in world space;
false → keys are relative to the object’s transform.
| Name | Type | Description | Access |
|---|---|---|---|
| speed | number | Playback speed multiplier (> 0). | read-write |
| endDelay | number | Pause duration (seconds) at the end of each cycle. | read-write |
| randomizeDelay | boolean | Whether to add a small random offset to endDelay each cycle. |
read-write |
| endBehavior | figmin.MotionEndBehavior | End-of-timeline behavior (see figmin.MotionEndBehavior). | read-write |
setKeyframes(frames, fixedPlacement?)
Define the motion keyframes for this object.
Each keyframe object contains:
p— position{x,y,z}in metersr— rotation as Euler{x,y,z}(degrees) or quaternion{x,y,z,w}t— absolute time in seconds
Coordinate space:
fixedPlacement = true→ keys are in world spacefixedPlacement = false→ keys are relative to the object’s transform
Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
| frames | Array<{ p:{x,y,z}, r:{x,y,z}|{x,y,z,w}, t:number }> | Yes | Keyframe list with position, rotation, and absolute time (seconds). |
| fixedPlacement | boolean | No | When true, interprets keys in world space; when false,
keys are relative to the object. |
Returns: void
getKeyframes(callback)
Request the current keyframes.
Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
| callback | function(data: { frames: Array<{p:{x,y,z}, r:{x,y,z,w}, t:number}>, fixedPlacement: boolean }) : void | Yes | Invoked with the current keyframes (rotation is always returned as quaternion)
and the fixedPlacement flag. |
Returns: void
// We'll create a text object and attach a motion component to make it spin around
const obj = figmin.createObject(figmin.ObjectType.TEXT3D, {
position: figmin.getWindowSpawnPosition(0.1, "right"),
rotation: figmin.getWindow().transform.rotation,
text: "Spin",
material: "metallic"
});
// Wait for start, then attach a motion component on the object
obj.onStart((o) => {
// Attach the motion component to the object
o.addComponent(figmin.ComponentType.MOTION);
// Create the keyframes, make sure we add enough frames to avoid rotation ambiguities.
let frames = [];
for (let i = 0; i <= 8; i++) {
let angle = i * 45; // 0, 45, ..., 360
if (angle === 360) angle = 359.9;
angle = -angle;
frames.push({
p: {x: 0, y: 0, z: 0},
r: {x: 0, y: angle, z: 0},
t: i / 8.0
});
}
// Load the keyframes to the new motion component
o.motion.setKeyframes(frames, false);
});
Component: bodypart
The bodypart component represents a tracked player body part (head or hands) and exposes the
ray origin pose used for pointing/aim interactions.
Access this component via the bodypart property on a FigminObject returned by
figmin.getPlayerBodypart.
The data of this component is valid if the 'tracked' property is true, listen for state changes with onTrackingChanged()
| Property | Type | Description | Access |
|---|---|---|---|
| tracked | boolean | True when this bodypart is currently tracked. If false, pose data is outdated/invalid. | Read-only |
| playerId | number | Numeric identifier of the player this bodypart belongs to. | Read-only |
| bodypartType | figmin.BodypartType | Specific body part type (e.g., HEAD, LEFT_HAND, RIGHT_HAND). |
Read-only |
| inputType | figmin.InputType | The input mechanism this bodypart is using. | Read-only |
| rayPosition | {x:number,y:number,z:number} | World-space position of the ray origin (meters). | Read-only |
| rayRotation | {x:number,y:number,z:number} | World-space rotation of the ray origin (Euler degrees). | Read-only |
| rayRotationq | {x:number,y:number,z:number,w:number} | World-space rotation of the ray origin (quaternion). | Read-only |
| rayForward | {x:number,y:number,z:number} | World-space unit forward direction. | Read-only |
| rayUp | {x:number,y:number,z:number} | World-space unit up direction. | Read-only |
| rayLocalPosition | {x:number,y:number,z:number} | Local-space offset from the bodypart’s transform to the ray origin (meters). | Read-only |
| rayLocalRotation | {x:number,y:number,z:number} | Local-space rotation of the ray origin relative to the bodypart’s transform (Euler degrees). | Read-only |
| rayLocalRotationq | {x:number,y:number,z:number,w:number} | Local-space rotation of the ray origin relative to the bodypart’s transform (quaternion). | Read-only |
| Name | Signature | Description |
|---|---|---|
| onTrackingChanged | function(bodyObj: FigminObject, tracked: boolean) : void | Invoked whenever tracking state changes (lost/regained). Assign null to clear. |
| onGrabChanged | function(bodyObj: FigminObject, isGrab:boolean, targetName:string, targetObject: FigminObject) : void | Invoked whenever this bodypart grabs a FigminObject, if the object is not tracked targetObject will be null,
in that case use findObjectByName(targetName) to begin tracking it. Assign null to clear. |
Events
Figmin XR dispatches two primary lifecycle DOM events that your app can listen for. Use these to configure early behavior and start your app logic at the right time.
Order: FigminPreload → FigminReady
FigminPreload
Fires very early, before normal app initialization. Use it only to set engine-level configuration that must be applied before the app starts.
// Configuring Z-forward can only be done during FigminPreload.
document.addEventListener("FigminPreload", () => figmin.useNegativeZForward(true));
FigminReady
Fires when the figmin namespace is initialized and the runtime connection is
ready. This is the safe point to start your app logic.
- After this event you can call most APIs: createObject, setUpdateFunction, input APIs, etc.
- If you require a spatial app context or this client isn’t the master, prompt or early out.
// Wait for the FigminReady event before initializing
document.addEventListener("FigminReady", init);
Players
Figmin exposes a lightweight player descriptor called PlayerInfo. It contains only the essentials:
a stable id and a displayName. You can obtain the local player descriptor via
getLocalPlayer() or a snapshot of everyone in the multiplayer session via
getPlayers().
| Property | Type | Description |
|---|---|---|
| id | number | The numeric identifier of this player |
| displayName | string | The nickname/alias of this player |
PlayerInfo is primarily used as input to getPlayerBodypart, which returns a
FigminObject for the requested head/hand. That object includes the
bodypart component—this is where the meaningful, real-time data lives
(ray origin pose, tracking state, grabbed object callback, etc.).
In summary: retrieve PlayerInfo, then work with body parts via the Bodypart component.
Listen for changes with onPlayerConnected() and
onPlayerDisconnected().
// Get the local player's right hand
const localPlayer = figmin.getLocalPlayer();
const rightHand = figmin.getPlayerBodypart(localPlayer, figmin.BodypartType.RIGHT_HAND);
// Wait until the bodypart FigminObject is ready
rightHand.onStart((handObj) => {
// The bodypart component is available at handObj.bodypart
// you could start polling it with handObj.onUpdate or with figmin.setUpdateFunction
// Subscribe to tracking state changes (tracked ↔ not tracked)
handObj.bodypart.onTrackingChanged((aHandObj, isTracked) => {
// Tracking state changed; the hand/controller is either tracked or not
});
// Get notified when an object is grabbed or released
handObj.bodypart.onGrabChanged((aHandObj, isGrab, targetName, targetObj) => {
// isGrab tells us if the object was grabbed or released
// targetName is the FigminObject.name and is always available
// IMPORTANT: targetObj will be null if the object isn't tracked,
// if you'd like to track it use figmin.findObjectByName(targetName) and it will be non null in future calls
});
});
// If the system can't find the right-hand object, an error will be reported
rightHand.onError(() => {
console.warn("Couldn't find right-hand FigminObject");
});
getLocalPlayer
Get the PlayerInfo for the local player.
Use this to access the local player bodyparts (e.g., pass to getPlayerBodypart).
- Combine with
getPlayerBodypart to query the local player's hands.- There's no need to track the local player's head, use getCamera instead.
- In multiplayer sessions, the returned player corresponds to the user controlled on this client.
getPlayers
Get a snapshot of all players currently present in the session as an array of
PlayerInfo objects (includes the local player).
This is a snapshot at call time; listen for changes via onPlayerConnected and onPlayerDisconnected.
figmin.getPlayers() => PlayerInfo[]
Returns: PlayerInfo[] — Array of players currently in the session.
getPlayerById
Get a PlayerInfo by numeric ID.
Useful when you have only a player ID (e.g., from input connect) and want
to read properties like displayName.
figmin.getPlayerById(playerId) => PlayerInfo | null
Returns: PlayerInfo | null — The matching player, or null if not found.
| Param | Type | Required | Description |
|---|---|---|---|
| playerId | number | Yes | Numeric identifier of the player. |
getPlayerBodypart
Get the FigminObject representing a specific player's body part (head or hands).
Contains a bodypart component at obj.bodypart and a
read-only transform.
Returns a FigminObject immediately; the lookup completes asynchronously.
Subscribe to onStart and onError on the returned object to determine the outcome.
Data is only valid if the bodypart is tracked, consult the bodypart component for more information.
figmin.getPlayerBodypart(playerOrId, type) => FigminObject | null
Returns: FigminObject | null — A handle to the body part object
or null if parameters are invalid.
| Param | Type | Required | Description |
|---|---|---|---|
| playerOrId | number | PlayerInfo |
Yes |
Target player, as a numeric ID or a PlayerInfo
(e.g., from figmin.getLocalPlayer or
figmin.getPlayers).
|
| type | figmin.BodypartType | Yes | The body part to query (e.g., figmin.BodypartType.RIGHT_HAND). |
// We'll attach a spotlight to the player's right hand, and turn it on and off as tracking state changes
// Get the local player's right hand
const localPlayer = figmin.getLocalPlayer();
const rightHand = figmin.getPlayerBodypart(localPlayer, figmin.BodypartType.RIGHT_HAND);
// We must wait until the FigminObject starts
rightHand.onStart((handObj) => {
// The light will be rotated in the direction of the hand ray
const lightLocalRotation = handObj.bodypart.rayLocalRotation;
const lightRange = 5;
// Attach a light component to the hand FigminObject, its range depends on whether it’s tracked
handObj.addComponent(figmin.ComponentType.LIGHT, {
type: figmin.lights.LightType.SPOT,
range: handObj.bodypart.tracked ? lightRange : 0,
spotlightAngle: 25,
rotation: lightLocalRotation,
shadowType: figmin.lights.ShadowType.SOFT
});
// When tracking changes, the light turns on and off
handObj.bodypart.onTrackingChanged((obj, isTracked) => {
// We use the light range to toggle.
// We check if light exists because it can be removed by another script
if (obj.light) {
obj.light.range = isTracked? lightRange : 0;
}
});
});
// If the system can't find right hand an error will be reported
rightHand.onError((handObj) => {
console.warn("Couldn't find right hand FigminObject");
});
onPlayerConnected
Register (or clear) a callback fired when a player joins the session.
Pass a function to receive a PlayerInfo for the newly connected player.
Pass null to clear the callback. Fires only for subsequent joins; use
getPlayers for the current snapshot.
figmin.onPlayerConnected(callback) => void
Returns: void
| Param | Type | Required | Description |
|---|---|---|---|
| callback | (player: PlayerInfo) => void | null |
Yes | Handler invoked on player join, or null to clear. |
- The callback is invoked once per player that joins the multiplayer session.
- To process existing players, call
getPlayers first.onPlayerDisconnected
Register (or clear) a callback fired when a player leaves the session.
Pass a function to receive a PlayerInfo for the player that disconnected.
Pass null to clear the callback.
figmin.onPlayerDisconnected(callback) => void
Returns: void
| Param | Type | Required | Description |
|---|---|---|---|
| callback | (player: PlayerInfo) => void | null |
Yes | Handler invoked on player disconnect, or null to clear. |
- The callback is invoked once per player that leaves the multiplayer session.
Functions
The top-level figmin object provides utility functions for managing the app, creating objects, raycasting, input, and more. Many require spatial app mode or master client.
createObject
Create a new object in the scene.
Returns a FigminObject immediately but UNINITIALIZED, objects
load asynchronously, use obj.onStart to detect
when the object becomes ready.
Consult the Creating Objects section for more details.
figmin.createObject(type, params?) => FigminObject
Returns: FigminObject — a
handle you can use to modify
properties, add components, or delete later.
| Param | Type | Required | Description |
|---|---|---|---|
| type | figmin.ObjectType |
Yes | The type of object to create (e.g., TEXT3D,
MODEL3D, SKETCH, IMAGE,
PORTAL).
|
| params | object | No |
Initial properties for the new object. Common fields include: • position: {x,y,z} — world-space position.• rotation: {x,y,z} — Euler degrees.• targetSize: number — uniform size in meters;
scales the object so its largest dimension matches this value.• colliderType:
figmin.ColliderType — defaults
to BOX.• scenePersistent: boolean — keep the object after
the app unloads/reloads. Default: false.Additional fields may be supported depending on the chosen object type (see that type’s section). |
- Spatial App: No
- Master client: Yes
- Wait till object starts before performing operations, including adding components or reading sizes.
- If you plan to attach runtime components, see each component’s “addComponent parameters” table for supported options and defaults.
// Create a text object that is owned by the scene (will persist after this script ends)
const obj = figmin.createObject(figmin.ObjectType.TEXT3D, {
position: { x: 0, y: 1, z: 0 },
rotation: { x: 0, y: 180, z: 0 },
colliderType: figmin.ColliderType.APPROXIMATE,
text: "Hello world",
scenePersistent: true
});
findObjectByName
Find a scene object by name and begin tracking it. Object names are returned by various
API calls.
Returns a FigminObject handle immediately but
UNINITIALIZED; the
lookup completes asynchronously.
Listen for obj.onStart to determine whether the
object was found, and
obj.onError if it wasn't.
Found objects are not owned by the script and will not be destroyed automatically when execution ends.
figmin.findObjectByName(objectName) => FigminObject
Returns: FigminObject — a
an object that will either start if it exists or error if it does not.
| Param | Type | Required | Description |
|---|---|---|---|
| objectName | string | Yes | The exact name of the object to find. |
- Spatial App: No
- Master client: Yes
- This does not create objects; it starts tracking an existing scene object with the given name.
- You’ll often get untracked names from other APIs (e.g., raycast / collision callbacks). Use this function to convert those names into tracked objects.
- Once it started, the tracked object is fully synchronized and behaves just like a script-owned object except it doesn't belong to the script.
- Avoid finding already tracked objects, if an object is tracked your query may include an "object" reference besides the "objectName".
setUpdateFunction
Registers a callback that runs once per engine frame.
Synchronized with the main Figmin XR rendering loop (higher framerate than the embedded web-view). Recommended for animations, object updates, physics logic, and other time-based calculations. Only one update function can be active at a time; calling this again replaces the previous one.
figmin.setUpdateFunction(callback) => void
Returns: void
| Param | Type | Required | Description |
|---|---|---|---|
| callback | function(deltaTime: number): void | Yes | Called every frame. Receives deltaTime in seconds since the
last frame. |
- Spatial App: No
- Master client: No
- Avoid heavy or blocking work inside the update; keep per-frame logic lightweight.
- Calling this again replaces the previously registered update function.
Avoid using browser-driven loops like
requestAnimationFrame or timers — These
run at a lower framerate and will cause jitter or inconsistent motion.
figmin.setUpdateFunction((deltaTime) => {
// Update logic here
obj.transform.rotation.y += 90 * deltaTime;
});
getWindowSpawnPosition
Calculates a position offset from the app window’s edges—handy for spawning objects
near or around the user’s view.
Use with figmin.getWindow().transform.rotation if you want the spawned object to
face the same direction as the window.
figmin.getWindowSpawnPosition(padding?, direction?) => { x:number, y:number, z:number }
Returns: {x:number, y:number, z:number} — a world-space
position relative to the window.
| Param | Type | Required | Description |
|---|---|---|---|
| padding | number | No | Offset distance in meters away from the chosen edge.
Default: 0.1. |
| direction | string | No | Direction from the window’s center: "right" |
"left" | "up" | "down" |
"front" | "back". Default: "right".
|
- Spatial App: No
- Master client: No
- The position is computed relative to the current window transform and visible surface size.
getCamera
Gets the player camera object. The returned FigminObject exposes a read-only
transform and an intrinsics property.
The camera cannot be destroyed and does not support attaching components.
figmin.getCamera() => FigminObject
Returns: FigminObject — camera system object with read-only
transform and intrinsics.
- Spatial App: No
- Master client: No
| Name | Type | Description |
|---|---|---|
| fov | number | Vertical field of view in degrees. |
| aspect | number | Width/height aspect ratio. |
| ipd | number | Interpupillary distance in meters. |
| eyes.left / eyes.right | object | Per-eye frusta. Each eye contains leftTan,
rightTan, upTan, downTan (numbers)
and proj (flattened 4×4 projection matrix, 16 numbers,
row-major).
|
- The camera FigminObject cannot be destroyed and does not support component attachments.
-
transform is read-only.- Both eyes are always present; in non-XR contexts they may be identical by design.
getApp
Get the FigminObject that represents this spatial app container.
The returned object is fully mutable: you can move/rotate/scale it, attach components, and even destroy it (which ends the script).
figmin.getApp() => FigminObject
Returns: FigminObject — mutable container object for the
app.
- Spatial App: Yes
- Master client: No
- Transform can be freely modified (position/rotation/scale).
- Components may be attached via
obj.addComponent(...).- Requires
figmin.isSpatialApp() to succeed; call
figmin.requireSpatialApp() if needed.
getWindow
Get the FigminObject that represents the app’s window surface.
The window object exposes its transform.size, which reflects the visible 2D
surface area of the app (excluding system buttons). Its transform is read-only.
The window’s position/rotation may differ from the app’s transform when special modes are active (e.g., figmin.AppMode.HUD, figmin.AppMode.OBJECT).
This is info is available to non-spatial apps, in contrast to getApp()
figmin.getWindow() => FigminObject
Returns: FigminObject — read-only object representing the
app window.
- Spatial App: No
- Master client: No
-
transform is read-only; you cannot move, rotate, or scale
the window directly—use figmin.getApp() instead.- The window cannot be destroyed and does not support attaching components.
getScene
Get the scene component representing the active scene.
Unlike normal FigminObjects, the scene has no transform. It exposes global lighting, floor, boundary, and shadow settings, and includes a status component for lifecycle events. The scene cannot be destroyed or re-created by user code.
figmin.getScene() => Scene
Returns: Scene — a global component for environment and
lighting controls.
- Spatial App: No
- Master client: Yes
- The scene has no transform; you cannot move, rotate, or scale it.
- The scene cannot be destroyed and does not support component attachments.
- Use the status component to observe lifecycle/status changes.
| Name | Type | Description | Access |
|---|---|---|---|
| mainLightColor | string | Primary light color as hex (e.g., "#b2ab96"). |
read-write |
| mainLightRotation | {x:number, y:number, z:number} | Primary light local Euler rotation in degrees. Assign a new
{x,y,z} object; do not mutate in place.
|
read-write |
| secondaryLightColor | string | Secondary light color as hex. | read-write |
| secondaryLightRotation | {x:number, y:number, z:number} | Secondary light local Euler rotation in degrees. Assign a new object. | read-write |
| ambientLightColor | string | Ambient light color as hex. | read-write |
| shadowMode | figmin.lights.SceneShadowMode | Forces shadows on/off or defers to system default. | read-write |
| floorVisibility | boolean | Show/hide the scene floor/grid. | read-write |
| boundarySize | {x:number, y:number, z:number} | null | Scene boundary size in meters (local xyz) at unit scale.
Each axis is clamped to a minimum of 3. Set null
to disable; getter returns null when disabled. |
read-write |
| status | StatusComponent | The scene’s status component. | read-only |
onStatusChanged(callback)
Register a listener for scene status changes.
Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
| callback | function(obj: FigminObject): void | Yes | Invoked when the scene’s status changes. |
Returns: void
isSpatialApp
Returns whether the app is running as a spatial app (deployed in the scene)
rather than in the built-in web browser.
Use this check to gate features or trigger a “Deploy as spatial app” flow via
figmin.requireSpatialApp.
figmin.isSpatialApp() => boolean
Returns: boolean — true if running as a
spatial app; false if running in the web browser.
- Spatial App: No
- Master client: No
- Some APIs require a spatial app; when called from the browser, they will no-op and prompt the user to deploy.
- Pair with
figmin.requireSpatialApp to surface a “Deploy as spatial app”
dialog when needed.
requireSpatialApp
Ensures the app is running as a spatial app.
If not already spatial, this prompts the user to deploy the app into the scene and aborts further execution in the browser context.
figmin.requireSpatialApp() => void
- Spatial App: No
- Master client: No
- When called from the browser context, this shows a deploy prompt and halts further script execution in that context.
// If you require spatial app features early out rather than letting the system do it for you
if (!figmin.isSpatialApp()) {
figmin.requireSpatialApp();
return;
}
getVersion
Returns the Figmin XR runtime version (host application)
figmin.getVersion() => string
Returns: string — the runtime version string.
- Spatial App: No
- Master client: No
- This reports the host application version; the scripting API version is available via
figmin.API_VERSION.
isMasterClient
Returns whether this app instance is the master client in a multiplayer
session.
Only the master client may perform most state-changing operations; non-master calls are ignored.
figmin.isMasterClient() => boolean
Returns: boolean — true if this instance is
the master client; otherwise false.
- Spatial App: No
- Master client: No
- Gate state-changing logic behind this check to avoid no-ops and wasted CPU on non-master clients.
// Good practice: early-out on non-master clients to avoid no-ops
if (!figmin.isMasterClient()) {
return;
}
isMultiplayer
Returns whether this app is in a multiplayer session.
figmin.isMultiplayer() => boolean
Returns: boolean — true if this instance is
in a multiplayer session; otherwise false.
- Spatial App: No
- Master client: No
saveState
Saves the current state of all supported HTML elements that include a
figmin-persist-state attribute (its value must be a unique key). The data is
stored with the app so it can persist across sessions.
The app itself must be saved to disk (in the scene or as an object) for the data to persist. In other words, this doesn't grant explicit file system access.
Note that the data does persist temporarily if the spatial app's is reloaded. (e.g: user presses "Reload Page")
-
<input type="text|number|range|checkbox|radio">-
<select>-
<textarea>figmin.saveState(optionalData?) => void
| Param | Type | Required | Description |
|---|---|---|---|
| optionalData | string | No | Custom string stored alongside the collected UI state. It will be returned
via figmin.loadState(callback). (Default: null)
|
- Spatial App: Yes
- Master client: No
- Each element must include a unique
figmin-persist-state key (string).- The app must be saved to disk for the data to persist across sessions.
- If provided,
optionalData is returned by figmin.loadState.
// Earlier in the HTML (tag supported elements with a unique key):
<input type="text" id="textInput" figmin-persist-state="persistKey1" value="Hello World" />
<input type="number" id="numberInput" figmin-persist-state="persistKey2" value="42" />
// Saves all elements marked with `figmin-persist-state`, plus a custom string
figmin.saveState("custom data");
loadState
Restores the state of all supported HTML elements marked with the
figmin-persist-state attribute.
Optionally accepts a callback to to be notified when loading occurs and to receive user-defined data previously saved via
figmin.saveState.
figmin.loadState(callback?) => void
| Param | Type | Required | Description |
|---|---|---|---|
| callback | function(userData: string): void | No | Invoked when loading occurs with the optional user-defined data saved via
figmin.saveState.
|
- Spatial App: Yes
- Master client: No
- Only elements with the
figmin-persist-state attribute are restored.- The callback is invoked only when user data was previously saved.
// Restore all persisted elements; receive optional user-defined data (if any)
figmin.loadState((userData) => {
console.log(userData);
});
useNegativeZForward
Sets the coordinate system so that -Z is considered the forward
direction.
This is typically needed when integrating WebGL-based frameworks like Three.js. Call only if you have a concrete reason—this path isn’t thoroughly tested.
- Must be called during the
FigminPreload event; later calls are ignored and a
warning is shown.
figmin.useNegativeZForward(doUse) => void
| Param | Type | Required | Description |
|---|---|---|---|
| doUse | boolean | Yes | true → treat -Z as forward; false
→ use the default forward direction. |
- Spatial App: No
- Master client: No
// Configuring Z-forward must be done during FigminPreload
document.addEventListener("FigminPreload", () => figmin.useNegativeZForward(true));
setRenderMode
Sets the rendering mode for your app, including stereoscopic 3D modes such as
side-by-side (SBS) and over-under (OU).
If you use stereo you must display your content in stereo, this function will render each side to the approriate camera eye.
figmin.setRenderMode(mode) => void
| Param | Type | Required | Description |
|---|---|---|---|
| mode | figmin.RenderMode | Yes | One of the values from figmin.RenderMode (e.g., mono,
side-by-side, over-under). |
- Spatial App: No
- Master client: No
setAppMode
Configure the display mode of the spatial app window.
Supported modes:
- DEFAULT: Normal HTML window
- MINIMIZED: Window hidden; rendering stopped; icon shown
- OBJECT: WebView used to render 3D content; always faces the player; interaction
disabled; configure bounds via figmin.setObjectModeBounds
- HUD: Wocked in front of the player; FOV capped at 55°
- FULLSCREEN: fills the player’s entire FOV.
figmin.setAppMode(mode) => void
| Param | Type | Required | Description |
|---|---|---|---|
| mode | figmin.AppMode | Yes | The desired app window mode. See figmin.AppMode for the full
list. |
- Spatial App: Yes
- Master client: No
setObjectModeBounds
Define the interaction bounding box size for the app window when in
figmin.AppMode.OBJECT.
By default, the window’s surface size is used as its bounding box, which may not match the shape of the 3D content rendered inside the WebView.
figmin.setObjectModeBounds(size) => void
| Param | Type | Required | Description |
|---|---|---|---|
| size | {x:number, y:number, z:number} | Yes | Local bounding box size at unit scale (1,1,1), in meters (x, y, z). |
- Spatial App: Yes
- Master client: No
- Used only for interaction/selection; it does not change rendering.
- Takes effect only in
figmin.AppMode.OBJECT; ignored in other modes.- Specify the size in meters at unit scale; the effective bounds will scale with the object’s transform.
getObjectModeBounds
Get the interaction bounding box previously set with
figmin.setObjectModeBounds.
Returns the local bounding box size (at unit scale) or null if no custom bounds
have been defined.
figmin.getObjectModeBounds() => {x:number, y:number, z:number} | null
Returns: {x:number, y:number, z:number} | null — local
bounds in meters at unit scale, or null if none set.
- Spatial App: Yes
- Master client: No
- Used by OBJECT app mode for interaction/selection; it does not affect rendering.
- Values are expressed in meters at unit scale (1,1,1); effective bounds scale with the object’s transform.
setTransparentBackground
Enables or disables transparent background mode for your spatial app.
When enabled, the HTML background becomes fully transparent so the 3D scene behind it shows through—useful for floating UI, holographic panels, or HUDs.
- Your HTML must include this meta tag in the
<head>:
<meta name="transparent" content="true">.figmin.setTransparentBackground(isTransparent) => void
| Param | Type | Required | Description |
|---|---|---|---|
| isTransparent | boolean | Yes | true to enable a transparent HTML background,
false to disable.
|
- Spatial App: Yes
- Master client: No
Displays a transient text message in front of the local user.
Use for short notifications; the message fades automatically after a brief duration.
figmin.print(text) => void
| Param | Type | Required | Description |
|---|---|---|---|
| text | string | Yes | The text to display in front of the local user. |
- Spatial App: No
- Master client: No
debugDraw
Draw a temporary curve in 3D space for a single frame to the local user.
The curve is defined by the ordered list of world-space points. Rendering lasts only for the current frame; the curve is automatically erased on the next frame.
figmin.debugDraw(points, color?) => void
| Param | Type | Required | Description |
|---|---|---|---|
| points | Array<{x:number, y:number, z:number}> | Yes | Ordered list of world-space points to connect. |
| color | string | No | Curve color as a CSS-style hex string. Default: #FFFFFF. |
- Spatial App: No
- Master client: No
- Rendering lasts one frame. To keep the curve visible, call this every frame via
setUpdateFunction.- Intended for debugging visualizations, not permanent geometry.
showLogConsole
Shows the developer log console.
This function is useful when developing in non standard app modes, such as AppMode.OBJECT, where the UI to manually open the developer logs is unavailable.
figmin.showLogConsole() => void
- Spatial App: Yes
- Master client: No
enableInputConnect
Enable motion-controller input connection for a spatial app.
- Displays a connect icon above the app window (or a specified target object).
- When the user activates the icon, a connection dialog is shown with the provided title, overriding Figmin XR's main menu
- Once connected, only the requested inputs will be delivered back to the app through the various figmin.getInput functions
- An optional callback can notify when the connection state changes.
figmin.enableInputConnect(connectionTitle, inputCodeArray, connectionChangedCallback?, targetObject?) => void
| Param | Type | Required | Description |
|---|---|---|---|
| connectionTitle | string | Yes | Title shown in the connection dialog when the user initiates input connection. |
| inputCodeArray | Array<figmin.InputCode> | Yes | Which inputs to request (e.g., triggers, buttons, thumbsticks). Only inputs listed here will be reported back. |
| connectionChangedCallback | (isConnected: boolean, playerId: number) => void | No | (Default: null) Invoked when the connection starts or ends.
isConnected indicates state; playerId is the
numeric player identifier.
|
| targetObject | FigminObject | No | (Default: null) If provided, displays the connect icon on this
object instead of the app window. |
- Spatial App: Yes
- Master client: No
- The connect icon appears above the app window by default; use
targetObject to
attach it to an object instead.- Once connected, only the inputs listed in
inputCodeArray are delivered to
your app via figmin.getInput* APIs.- The callback is optional and fires on both connect and disconnect events.
// Input example
let isConnected = false;
document.addEventListener("FigminReady", () => {
// Show a connect icon and request A/B button inputs
figmin.enableInputConnect(
"Connection test",
[figmin.InputCode.A, figmin.InputCode.B],
onConnectionChanged // optional callback
);
// Per-frame polling of inputs
figmin.setUpdateFunction(update);
});
function onConnectionChanged(connected, playerId) {
isConnected = connected;
// (optional) console.log(`Input ${connected ? "connected" : "disconnected"} for player ${playerId}`);
}
function update(deltaTime) {
if (!isConnected) return;
if (figmin.getInputDown(figmin.InputCode.A)) {
console.log("A pressed");
}
if (figmin.getInputDown(figmin.InputCode.B)) {
console.log("B pressed");
}
}
disableInputConnect
Disable motion-controller input connection for the app.
Removes the connect icon from the app window (or the target object if one was specified) and stops delivering controller inputs to the app.
figmin.disableInputConnect() => void
- Spatial App: Yes
- Master client: No
disconnectFromInput
Request disconnection from an active input connection.
Equivalent to the user pressing the “Disconnect” button in the connection UI.
figmin.disconnectFromInput() => void
- Spatial App: Yes
- Master client: No
- If a
connectionChangedCallback was provided to
enableInputConnect, it will be invoked with isConnected = false
upon disconnection.- Has effect only when a connection is currently active; otherwise it is a no-op.
- This does not remove the connect icon; to remove it entirely, call
disableInputConnect.
getInput
Get the current value of a connected input as a float.
Analog controls (e.g., triggers, thumbstick axes) return values in [0..1].
Digital controls (buttons) return 0 when not pressed and 1 when
pressed.
figmin.getInput(inputCode) => number
Returns: number — current value for the requested input.
| Param | Type | Required | Description |
|---|---|---|---|
| inputCode | figmin.InputCode | Yes | The input to query. |
- Spatial App: Yes
- Master client: No
- Valid only after a successful input connection (see
enableInputConnect).- Only inputs requested in
inputCodeArray will be reported to your app.
getInputDown
Check if a connected input button was pressed on this frame.
Returns true only on the first frame the input transitions from not
pressed to pressed. Useful for detecting discrete button presses.
figmin.getInputDown(inputCode) => boolean
Returns: boolean — true if the input was
pressed this frame; otherwise false.
| Param | Type | Required | Description |
|---|---|---|---|
| inputCode | figmin.InputCode | Yes | The input to query. |
- Spatial App: Yes
- Master client: No
- Valid only after a successful input connection (see
enableInputConnect).- Only inputs requested in your
inputCodeArray are reported.- Poll this from your per-frame update (e.g., via
setUpdateFunction) to catch the
frame-edge transition reliably.
getInputUp
Check if a connected input button was released on this frame.
Returns true only on the first frame the input transitions from pressed
to not pressed. Useful for detecting discrete button releases.
figmin.getInputUp(inputCode) => boolean
Returns: boolean — true if the input was
released this frame; otherwise false.
| Param | Type | Required | Description |
|---|---|---|---|
| inputCode | figmin.InputCode | Yes | The input to query. |
- Spatial App: Yes
- Master client: No
- Valid only after a successful input connection (see
enableInputConnect).- Only inputs requested in your
inputCodeArray are reported.- Poll this from your per-frame update (e.g., via
setUpdateFunction) to capture the
frame-edge transition reliably.
raycast
Cast a ray into the world and invoke a callback with the first hit (if any).
Provide a world-space origin and direction. Optionally filter
layers, set a max distance, and request object lookup data.
The callback is always invoked: it receives a single hit info when something is struck, or null if nothing is hit.
figmin.raycast(params, callback) => void
| Param | Type | Required | Description |
|---|---|---|---|
| params.origin | {x:number, y:number, z:number} | Yes | Ray start in world space (meters). |
| params.direction | {x:number, y:number, z:number} | Yes | Ray direction in world space. Does not need to be normalized. |
| params.layers | Array<figmin.Layers> | No | Layers to test. Default:
[figmin.Layers.SURFACE, figmin.Layers.PHYSICS_OBJ, figmin.Layers.STATIC_OBJ].
|
| params.maxDistance | number | No | Max distance in meters. If omitted, the engine default is used. |
| params.lookupObject | boolean | No | When true, performs an extra lookup to attach figmin object
data (slower). See Notes. |
| callback | function(hit: null | { point:{x,y,z}, normal:{x,y,z}, distance:number, layer:figmin.Layers, objectName?:string, object?:FigminObject|null }): void | Yes | Invoked with hit info or null if nothing was hit. |
- Spatial App: No
- Master client: No
- Defaults test against
SURFACE, PHYSICS_OBJ, and
STATIC_OBJ layers.- With
lookupObject = true, hits on physics/static objects may include either
object (if already tracked) or just objectName. You can later call
figmin.findObjectByName(objectName) to start tracking; subsequent raycasts may
then return object.figmin.raycast(
{
origin: { x: 0, y: 1, z: 0 },
direction: { x: 0, y: 0, z: 1 }
},
(hit) => {
if (!hit) return;
console.log("raycast hit at", hit.point, "normal:", hit.normal, "distance:",
hit.distance, "layer:", hit.layer);
}
);
raycastAll
Cast a ray into the world and invoke a callback with all hits along
the ray (if any).
The callback is always invoked: it receives an array of hit info when something is struck, or
null if nothing is hit.
figmin.raycastAll(params, callback) => void
| Param | Type | Required | Description |
|---|---|---|---|
| params.origin | {x:number, y:number, z:number} | Yes | Ray start in world space (meters). |
| params.direction | {x:number, y:number, z:number} | Yes | Ray direction in world space. |
| params.layers | Array<figmin.Layers> | No | Layers to test. Default:
[figmin.Layers.SURFACE, figmin.Layers.PHYSICS_OBJ, figmin.Layers.STATIC_OBJ].
|
| params.maxDistance | number | No | Max distance in meters. If omitted, the engine default is used. |
| params.lookupObject | boolean | No | When true, performs an extra lookup to attach figmin object
data (slower). See Notes. |
| callback | function(hits: null | Array<{ point:{x,y,z}, normal:{x,y,z}, distance:number, layer:figmin.Layers, objectName?:string, object?:FigminObject|null }>): void | Yes | Invoked with an array of hit infos, or null if nothing was hit.
|
- Spatial App: No
- Master client: No
- By default tests against
SURFACE, PHYSICS_OBJ, and
STATIC_OBJ layers (see figmin.Layers).- With
lookupObject = true, hits on physics/static objects may include either
object (if already tracked) or only objectName. You can later call
figmin.findObjectByName(objectName) to start tracking; subsequent raycasts may
then return object.raycastSphere
Cast a swept sphere into the world and invoke a callback with the
first hit (if any).
Provide a world-space origin, direction, and sphere
radius. Optionally filter layers, set a max distance, and request object lookup
data.
The callback is always invoked: it receives a single hit info when something is struck, or null if nothing is hit.
figmin.raycastSphere(params, callback) => void
| Param | Type | Required | Description |
|---|---|---|---|
| params.origin | {x:number, y:number, z:number} | Yes | Ray start in world space (meters). |
| params.direction | {x:number, y:number, z:number} | Yes | Ray direction in world space. |
| params.radius | number | Yes | Sphere radius in meters. |
| params.layers | Array<figmin.Layers> | No | Layers to test. Default:
[figmin.Layers.SURFACE, figmin.Layers.PHYSICS_OBJ, figmin.Layers.STATIC_OBJ].
|
| params.maxDistance | number | No | Max distance in meters. If omitted, the engine default is used. |
| params.lookupObject | boolean | No | When true, performs an extra lookup to attach figmin object
data (slower). See Notes. |
| callback | function(hit: null | { point:{x,y,z}, normal:{x,y,z}, distance:number, layer:figmin.Layers, objectName?:string, object?:FigminObject|null }): void | Yes | Invoked with the hit info, or null if nothing was hit. |
- Spatial App: No
- Master client: No
- By default tests against
SURFACE, PHYSICS_OBJ, and
STATIC_OBJ layers (see figmin.Layers).- With
lookupObject = true, hits on physics/static objects may include either
object (if already tracked) or just objectName. You can later call
figmin.findObjectByName(objectName) to start tracking; subsequent raycasts may
then return object.raycastSphereAll
Cast a swept sphere into the world and invoke a callback with
all hits along the ray (if any).
The callback is always invoked: it receives an array of hit info when something is struck, or
null if nothing is hit.
figmin.raycastSphereAll(params, callback) => void
| Param | Type | Required | Description |
|---|---|---|---|
| params.origin | {x:number, y:number, z:number} | Yes | Ray start in world space (meters). |
| params.direction | {x:number, y:number, z:number} | Yes | Ray direction in world space. |
| params.radius | number | Yes | Sphere radius in meters. |
| params.layers | Array<figmin.Layers> | No | Layers to test. Default:
[figmin.Layers.SURFACE, figmin.Layers.PHYSICS_OBJ, figmin.Layers.STATIC_OBJ].
|
| params.maxDistance | number | No | Max distance in meters. If omitted, the engine default is used. |
| params.lookupObject | boolean | No | When true, performs an extra lookup to attach figmin object
data (slower). See Notes. |
| callback | function(hits: null | Array<{ point:{x,y,z}, normal:{x,y,z}, distance:number, layer:figmin.Layers, objectName?:string, object?:FigminObject|null }>): void | Yes | Invoked with an array of hit info, or null if nothing was hit.
|
- Spatial App: No
- Master client: No
- By default tests against
SURFACE, PHYSICS_OBJ, and
STATIC_OBJ layers (see figmin.Layers).- With
lookupObject = true, hits on physics/static objects may include either
object (if already tracked) or only objectName. You can later call
figmin.findObjectByName(objectName) to start tracking; subsequent raycasts may
then return object.
Sketch Functions
The figmin.sketch namespace provides functions for creating and manipulating 3D strokes with the sketch component. These include low-level drawing primitives like point() and stroke(), as well as higher-level helpers that generate common shapes such as cones, rounded boxes, and other procedural forms.
sketch.stroke
Create a brush stroke object for use with
figminObj.sketch.setBrushStrokes().
This helper packages a brush reference, color, max size, and an array of control points
(created with figmin.sketch.point()) into the
compact format the sketch component expects.
The maximum pressure determines the maximum width of the brush stroke in meters, it is modulated by each control point pressure.
figmin.sketch.stroke(brush, color, size, points) => object
Returns: object — a stroke formatted for
sketch.setBrushStrokes():
{ id: <brush.id>, c: <color>, s: <size>, pts: Array<ControlPoint> }.
| Param | Type | Required | Description |
|---|---|---|---|
| brush | object | string |
Yes | Either a brush object from figmin.brushes or a brush.id string.
|
| color | string |
Yes | Stroke color in hex format (e.g., "#ff0000"). |
| size | number |
Yes | Maximum brush size; actual size per point is modulated by its
pressure.
|
| points | Array<ControlPoint> |
Yes | Array of control points created via
figmin.sketch.point() (each
includes position, rotation, and pressure).
|
// Use a brush object from the catalog
const brush = figmin.brushes.MetallicTube;
// Two control points for a straight line in the object's local space
const p0 = figmin.sketch.point(
{ x: 0, y: 0, z: 0 },
{ x: 0, y: 0, z: 0 },
brush.minPressure // We use the minimum pressure of this brush to start
);
const p1 = figmin.sketch.point(
{ x: 0, y: 0.2, z: 0 }, // 20 cm above
{ x: 0, y: 0, z: 0 },
1 // Final point uses the maximum pressure
);
// Create the stroke with the brush object
const stroke = figmin.sketch.stroke(
brush,
"#40E0D0",
0.05, // max size; actual size modulated per-point by pressure
[p0, p1]
);
// Apply to a Sketch component on your FigminObject
obj.sketch.setBrushStrokes([stroke]);
- Spatial App: No
- Master client: No
- When passing a brush object, it should be sourced from
figmin.brushes (e.g.,
from the Brush Catalog).- Ensure all points are created with
figmin.sketch.point() to match the
expected structure.
sketch.point
Create a control point object for a brush stroke made with
figmin.sketch.stroke().
A control point contains a local-space position, rotation, and pressure, representing the
state of the motion controller
at that moment in the stroke. If rotation or pressure are omitted, defaults are used
(identity rotation, pressure = 1).
Pressure
Pressure corresponds to the value of the motion controller’s trigger, ranging from
0 to 1.
This determines the effective stroke width at that point as
pressure × stroke.size. Each brush in the catalog defines a
minPressure, and the effective pressure is clamped to that minimum.
Rotation
Rotation represents the orientation of the motion controller at this point in the stroke. It serves as a suggestion to the renderer, which may sanitize values. For most cases, it is safe to omit rotation and let the engine determine the best orientation.
figmin.sketch.point(position, rotation?, pressure?) => ControlPoint
Returns: ControlPoint — object formatted for Sketch
strokes:
{ p: <position>, r: <rotation>, ps: <pressure> }.
| Param | Type | Required | Description |
|---|---|---|---|
| position | { x:number, y:number, z:number } |
Yes | Local-space coordinates of the control point. |
| rotation | { x:number, y:number, z:number }or { x:number, y:number, z:number, w:number }
|
No | Orientation at this point. Euler (degrees, XYZ) or Quaternion (normalized). Omit for identity. |
| pressure | number |
No | Brush pressure in [0..1]. Omit to default to 1.
|
- Spatial App: No
- Master client: No
- Coordinates are in the FigminObject’s local space.
- Pressure scales the stroke’s width up to the stroke’s
size cap provided in
sketch.stroke().- Rotations may be provided as Euler (XYZ, degrees) or Quaternion (x,y,z,w). If using quaternions, provide a normalized value.
- For consistent results, build all points via
figmin.sketch.point() before
passing them to
sketch.stroke.
sketch.getBrushById
Look up a brush object in the Brush Catalog
by its id.
You’ll need this function because
figminObj.sketch.getBrushStrokes() returns only
brush IDs, not the full brush
objects. This helper converts an ID back into a catalog entry.
Note: old sketches may contain deprecated brushes that cannot be resolved. In that case this
function returns
null. You may still create strokes with deprecated brushes by passing the raw
ID string directly.
figmin.sketch.getBrushById(brushId) => object | null
Returns: A brush object from figmin.brushes, or
null if not found.
| Param | Type | Required | Description |
|---|---|---|---|
| brushId | string |
Yes | The unique ID of the brush to look up. These IDs are returned by
obj.sketch.getBrushStrokes()
|
- Spatial App: No
- Master client: No
sketch.translateStroke
Translates a stroke by the given offset vector, this operation mutates the positions in place
Use this to reposition an existing stroke in sketch space (all coordinates are relative to the sketch), while preserving point rotations and pressure values.
figmin.sketch.translateStroke(stroke, offset) => object
Returns: The same stroke object with each point’s p translated by offset. Other point fields (e.g., r, ps) are preserved.
| Param | Type | Required | Description |
|---|---|---|---|
| stroke | object |
Yes | A stroke in the form { id, c, s, pts: [{ p:{x,y,z}, r?:{x,y,z,w}, ps?:number }, ...] }. |
| offset | { x:number, y:number, z:number } |
Yes | Translation vector, in meters, applied to each point’s p. |
- Spatial App: No
- Master client: No
- Only point positions are shifted; brush, size, color, rotations (
r), and pressure (ps) are preserved.- Mutates in place, to preserve the original stroke use cloneStroke first.
// Move an existing stroke up by 0.2m
figmin.sketch.translateStroke(aStroke, { x: 0, y: 0.2, z: 0 });
sketch.rotateStroke
Rotates a stroke by the given rotation (Euler or Quaternion). Positions are rotated around a pivot
(local origin if none is provided). This operation mutates the stroke in place.
Use this to reorient an existing stroke in sketch space.
If a point contains an orientation quaternion r, it is composed as r' = qRot * r.
figmin.sketch.rotateStroke(stroke, rotation, pivot?) => object
Returns: The same stroke with each point’s position rotated about pivot and each point’s quaternion (if present) left-multiplied by qRot.
| Param | Type | Required | Description |
|---|---|---|---|
| stroke | object |
Yes | A stroke in the form { id, c, s, pts: [{ p:{x,y,z}, r?:{x,y,z,w}, ps?:number }, ...] }. |
| rotation | { x:number, y:number, z:number } or { x:number, y:number, z:number, w:number } |
Yes | Rotation to apply. If three components are provided, treated as Euler degrees. If four components are provided, treated as a quaternion. |
| pivot | { x:number, y:number, z:number } or null |
No | Point to rotate around (meters). Defaults to origin {0,0,0} when null or omitted. |
- Spatial App: No
- Master client: No
- Positions are rotated about
pivot; set pivot to a point on your stroke to spin it in place.- Mutates in place, to preserve the original stroke use cloneStroke first.
// Rotate a stroke 90° around Z, about the local origin (no pivot provided)
figmin.sketch.rotateStroke(aStroke,
{ x: 0, y: 0, z: 90 } // Euler degrees but you can pass a quaternion as well
);
sketch.scaleStroke
Scales a stroke by either a uniform factor (number) or a non-uniform vector {x,y,z}.
Point positions are scaled; orientations are preserved. Thickness behavior depends on the type of scale (see Notes).
This operation mutates the stroke in place.
figmin.sketch.scaleStroke(stroke, scale, pivot?) => object
Returns: The same stroke with point positions scaled about pivot (or local origin if null).
| Param | Type | Required | Description |
|---|---|---|---|
| stroke | { id?, c?, s?, pts?: Array<{ p:{x,y,z}, r?:{x,y,z,w}, ps?:number }> } |
Yes | The source stroke to scale. |
| scale | number or { x:number, y:number, z:number } |
Yes | Uniform factor (e.g., 1.5) or non-uniform per-axis factors (e.g., {x:1, y:1, z:0.5}). |
| pivot | { x:number, y:number, z:number } or null |
No | Point to scale about (in sketch space, meters). Defaults to origin when null or omitted. |
- Spatial App: No
- Master client: No
- Uniform scale (
number k): positions are scaled by k and thickness s is also scaled by k.- Non-uniform scale (
{x,y,z}): positions are scaled per-axis; thickness s is not changed.- Mutates in place, to preserve the original stroke use cloneStroke first.
// 1) Uniform scale: enlarge by 1.5× about origin (thickness scales too)
figmin.sketch.scaleStroke(aStroke, 1.5);
// 2) Non-uniform scale: flatten along Z about origin (thickness unchanged)
figmin.sketch.scaleStroke(aStroke, { x: 1, y: 1, z: 0.5 });
sketch.calculateStrokeCenter
Computes the axis-aligned bounding-box center of a stroke’s points and returns it as {x,y,z}.
Use this center as a convenient pivot for transforms like rotateStroke or scaleStroke when you want an operation “about the stroke itself.”
figmin.sketch.calculateStrokeCenter(stroke) => { x:number, y:number, z:number }
Returns: A point (in sketch space, meters) at the center of the stroke’s axis-aligned bounds.
| Param | Type | Required | Description |
|---|---|---|---|
| stroke | { pts?: Array<{ p?:{x,y,z} }>, id?, c?, s? } |
Yes | The stroke whose point positions will be examined to compute the AABB center. |
- Spatial App: No
- Master client: No
- Computes an axis-aligned center (it does not account for stroke orientation).
// Rotate a stroke 90° around Z, about its own center (AABB center)
const pivot = figmin.sketch.calculateStrokeCenter(original);
const rotated = figmin.sketch.rotateStroke(
original,
{ x: 0, y: 0, z: 90 }, // Euler degrees
pivot
);
// Scale the stroke down uniformly 0.8× about its center
const scaled = figmin.sketch.scaleStroke(original, 0.8, pivot);
sketch.cloneStroke
Creates and returns a deep copy of a stroke.
The clone is safe to modify without affecting the original.
figmin.sketch.cloneStroke(stroke) => object
Returns: A brand new stroke object with copied fields (id, c, s, pts, etc.). Mutating the clone will not change the source stroke.
| Param | Type | Required | Description |
|---|---|---|---|
| stroke | object |
Yes |
Source stroke in the standard stroke format:{ id, c, s, pts: [{ p:{x,y,z}, r?:{x,y,z,w}, ps?:number }, ...] }
|
- Spatial App: No
- Master client: No
- Deep copy: all point objects in
pts are duplicated, not referenced.- Typical use case: generate a variant (scaled/rotated/recolored) without touching the original stroke data.
// Make an independent copy before editing
const copy = figmin.sketch.cloneStroke(original);
sketch.boxStroke
Creates a single-stroke, axis-aligned box wireframe centered at the origin.
The path visits all 12 edges (re-walking where needed) so the stroke remains continuous with no jumps.
You can also create rectangles by setting one dimension to 0 (e.g., depth = 0).
figmin.sketch.boxStroke(brush, color, strokeSize, width, height, depth) => object
Returns: A single stroke object representing the box wireframe (centered at origin, axis-aligned).
| Param | Type | Required | Description |
|---|---|---|---|
| brush | string | object |
Yes | Brush object or brush id from the Brush Catalog. |
| color | string |
Yes | Stroke color (e.g., "#FF8800"). |
| strokeSize | number |
Yes | Stroke thickness in meters. |
| width | number |
Yes | Extent along X (full width of the box). Use 0 for a flat rectangle in X if desired. |
| height | number |
Yes | Extent along Y (full height of the box). Use 0 to collapse along Y. |
| depth | number |
Yes | Extent along Z (full depth of the box). Use 0 for a 2D rectangle in the XY plane. |
- Spatial App: No
- Master client: No
- The geometry is centered at the origin and axis-aligned in sketch space.
- Stroke is continuous (single stroke that traces all edges).
- Dimensions are full extents (not half-extents). For a 1 m cube, pass
width=1, height=1, depth=1.- To position or orient the box, use helpers like
translateStroke / rotateStroke after creation.// Create a 1m × 0.5m × 0.25m box wireframe
const stroke = figmin.sketch.boxStroke(
figmin.brushes.Wire, "#4CAF50", 0.004, 1.0, 0.5, 0.25);
sketch.capsuleStroke
Creates a single-stroke capsule (two hemispherical caps plus a cylindrical side),
Y-up and centered at the origin.
The stroke path is continuous, tracing the profile without spatial jumps. Total height is
length + 2 * radius.
figmin.sketch.capsuleStroke(brush, color, strokeSize, radius, length, loops) => object
Returns: A single stroke object describing the capsule shape.
| Param | Type | Required | Description |
|---|---|---|---|
| brush | string | object |
Yes | Brush object or brush id from the Brush Catalog. |
| color | string |
Yes | Stroke color (e.g., #FF8A3C). |
| strokeSize | number |
Yes | Stroke thickness. |
| radius | number |
Yes | Hemisphere/cylinder radius (≥ 0). |
| length | number |
Yes | Distance between hemisphere centers (≥ 0). Total height = length + 2 * radius. |
| loops | number |
Yes | Number of wraps along the cylinder side (> 0). Can be fractional. |
- Spatial App: No
- Master client: No
- Y-up orientation; geometry centered at origin.
- Single continuous stroke visiting both caps and the cylindrical side.
-
loops controls how many revolutions the side trace makes; fractional values create partial wraps.// A 0.12 radius capsule with 0.3 length and 2 side loops
const stroke = figmin.sketch.capsuleStroke(
figmin.brushes.ToonHull, "#4CAF50", 0.001, 0.12, 0.30, 2);
sketch.circleStroke
Creates a single-stroke circle in the XY plane (normal +Z), centered at the origin.
For ellipses, create a circle and then apply scaleStroke with non-uniform factors.
figmin.sketch.circleStroke(brush, color, strokeSize, radius) => object
Returns: A single stroke object representing the circle path.
| Param | Type | Required | Description |
|---|---|---|---|
| brush | string | object |
Yes | Brush object or brush id from the Brush Catalog. |
| color | string |
Yes | Stroke color (e.g., #FF8A3C). |
| strokeSize | number |
Yes | Stroke thickness. |
| radius | number |
Yes | Circle radius. |
- Spatial App: No
- Master client: No
- XY plane, normal +Z; centered at origin.
- Single continuous stroke.
// Circle with radius 0.25
const stroke = figmin.sketch.circleStroke(
figmin.brushes.MatteHull, "#4CAF50", 0.004, 0.25);
sketch.coneStroke
Creates a single-stroke cone with the tip at +Y and the base at −Y.
The path spirals from tip to base for a continuous stroke; loops controls how many full turns it makes.
figmin.sketch.coneStroke(brush, color, strokeSize, radius, height, loops) => object
Returns: A single stroke object describing the cone’s lateral surface path.
| Param | Type | Required | Description |
|---|---|---|---|
| brush | string | object |
Yes | Brush object or brush id from the Brush Catalog. |
| color | string |
Yes | Stroke color (e.g., #FF8A3C). |
| strokeSize | number |
Yes | Stroke thickness. |
| radius | number |
Yes | Base radius at −Y. |
| height | number |
Yes | Distance along Y from base (−Y) to tip (+Y). |
| loops | number |
Yes | Number of full turns from tip to base (> 0). Fractional values allowed. |
- Spatial App: No
- Master client: No
- Y-up orientation; centered at origin (tip at +Y, base at −Y).
- Single continuous stroke spiraling from tip to base.
- Use
rotateStroke or translateStroke after creation to reorient or position the cone.// A cone: radius 0.2, height 0.4, 1.25 loops from tip to base
const stroke = figmin.sketch.coneStroke(
figmin.brushes.ToonHull, "#4CAF50", 0.004, 0.2, 0.4, 1.25);
sketch.cylinderStroke
Creates a single-stroke helical path over a cylinder (optionally tapered), centered at the origin with poles on +Y (top) and −Y (bottom).
The path starts at the top rim, wraps loops times, and ends at the bottom rim.
figmin.sketch.cylinderStroke(brush, color, strokeSize, radiusTop, radiusBottom, height, loops?) => object
Returns: A single stroke object representing the helix along the cylinder’s side.
| Param | Type | Required | Description |
|---|---|---|---|
| brush | string | object |
Yes | Brush object or brush id from the Brush Catalog. |
| color | string |
Yes | Stroke color. |
| strokeSize | number |
Yes | Stroke thickness. |
| radiusTop | number |
Yes | Radius at the top rim (+Y). |
| radiusBottom | number |
Yes | Radius at the bottom rim (−Y). |
| height | number |
Yes | Distance from bottom (−Y) to top (+Y). |
| loops | number |
No | Full turns from top to bottom (> 0). May be fractional. Defaults to 1. |
- Spatial App: No
- Master client: No
- Y-up, centered at origin; helix begins on the top rim and ends on the bottom rim.
- Tapered shape supported: set
radiusTop and radiusBottom differently for a frustum-like side.// Helix with 2.5 loops over a tapered cylinder (top 0.15 → bottom 0.25, height 0.6)
const stroke = figmin.sketch.cylinderStroke(
figmin.brushes.ShinyHull, "#4CAF50", 0.004, 0.15, 0.25, 0.6, 2.5);
sketch.rectangleStroke
Creates a single-stroke rectangle in the XY plane (normal +Z), centered at the origin.
figmin.sketch.rectangleStroke(brush, color, strokeSize, width, height) => object
Returns: A single stroke object tracing the rectangle perimeter.
| Param | Type | Required | Description |
|---|---|---|---|
| brush | string | object |
Yes | Brush object or brush id from the Brush Catalog. |
| color | string |
Yes | Stroke color. |
| strokeSize | number |
Yes | Stroke thickness. |
| width | number |
Yes | Rectangle width along X. |
| height | number |
Yes | Rectangle height along Y. |
- Spatial App: No
- Master client: No
- Centered at origin; normal +Z.
- Single continuous stroke around the perimeter.
// Rectangle 1.2 × 0.6
const stroke = figmin.sketch.rectangleStroke(
figmin.brushes.ToonHull, "#4CAF50", 0.004, 1.2, 0.6);
sketch.roundedBoxStroke
Creates a brush stroke that approximates a rounded box using a superquadric point distribution,
smaller exponents round more aggressively; larger exponents approach a sharp-edged box.
Points are axis-aligned and centered at the origin.
Designed for HULL-category brushes (e.g., ToonHull, DiamondHull), non-HULL brushes may not produce a proper shape..
figmin.sketch.roundedBoxStroke(brush, color, size, width, height, depth, cornerRadiusXY?, cornerRadiusZ?) => object
Returns: A stroke object: { id, c, s, pts:[{ p, r?, ps? }, ...] }.
| Param | Type | Required | Description |
|---|---|---|---|
| brush | string | object |
Yes | Brush ID or object from the Brush Catalog. Best results with HULL brushes. |
| color | string |
Yes | Stroke color (e.g., "#ff0000"). |
| size | number |
Yes | Max brush size; per-point width can vary via stroke/point pressure. |
| width | number |
Yes | Extent along X. |
| height | number |
Yes | Extent along Y. |
| depth | number |
Yes | Extent along Z. |
| cornerRadiusXY | number |
No | Superquadric exponent for rounding in XY (default 0.40). Lower ⇒ more rounded; higher ⇒ boxier. |
| cornerRadiusZ | number |
No | Superquadric exponent for rounding along Z (default 0.40). |
- Spatial App: No
- Master client: No
- Axis-aligned, centered at origin; use
translateStroke/rotateStroke to position/orient after creation.- Superquadrics: smaller exponents round more aggressively; larger exponents approach a sharp-edged box.
// Rounded box (hull brush), mildly rounded corners
const stroke = figmin.sketch.roundedBoxStroke(
figmin.brushes.ToonHull, "#4CAF50", 0.004, 1.0, 0.6, 0.4, 0.35, 0.35);
sketch.roundedRectangleStroke
Creates a single-stroke rounded rectangle in the XY plane (normal +Z), centered at the origin.
roundness is a unitless corner fillet factor from 0 (sharp 90°) to 1 (maximum rounding without overlap).
figmin.sketch.roundedRectangleStroke(brush, color, strokeSize, width, height, roundness) => object
Returns: A single stroke object tracing straight edges blended with circular corner arcs.
| Param | Type | Required | Description |
|---|---|---|---|
| brush | string | object |
Yes | Brush object or brush id from the Brush Catalog. |
| color | string |
Yes | Stroke color. |
| strokeSize | number |
Yes | Stroke thickness. |
| width | number |
Yes | Total width along X. |
| height | number |
Yes | Total height along Y. |
| roundness | number |
Yes | Unitless corner fillet factor (typically 0..1). 0 = sharp; 1 = maximum practical rounding. |
- Spatial App: No
- Master client: No
- The effective corner radius is derived from
roundness and clamped so corner arcs don’t overlap (often proportional to 0.5 * min(width, height)).- Single continuous stroke; edges remain straight, only corners are rounded.
// Rounded rectangle 1.0 × 0.6 with 40% corner roundness
const stroke = figmin.sketch.roundedRectangleStroke(
figmin.brushes.SmoothHull, "#4CAF50", 0.004, 1.0, 0.6, 0.4);
sketch.sphereStroke
Creates a single-stroke sphere lattice path centered at the origin.
The curve weaves around the sphere (mix of latitude/longitude arcs) as one continuous stroke.
figmin.sketch.sphereStroke(brush, color, strokeSize, radius) => object
Returns: A single stroke object describing a woven path on the sphere surface.
| Param | Type | Required | Description |
|---|---|---|---|
| brush | string | object |
Yes | Brush object or brush id from the Brush Catalog. |
| color | string |
Yes | Stroke color. |
| strokeSize | number |
Yes | Desired stroke thickness. |
| radius | number |
Yes | Sphere radius. |
- Spatial App: No
- Master client: No
- Single continuous path that approximates a spherical grid/lattice.
- Centered at origin; use
translateStroke/rotateStroke to position/orient after creation.- For a filled look, consider HULL-category brushes; for wire look, try line-style brushes.
// Sphere lattice, radius 0.35
const stroke = figmin.sketch.sphereStroke(
figmin.brushes.MetallicSmoothHull, "#4CAF50", 0.004, 0.35);
Enums
Enums define constant values used throughout the API.
ObjectType
The various object types found in FigminObjects.
Each FigminObject type contains a specific a built-in component that can't be removed.
Most object types can be used by figmin.createObject with the exception of BODYPART which is only found in objects returned by figmin.getPlayerBodypart.
| Name | Description |
|---|---|
| MODEL3D | A 3D model; includes the model3d component (see component). |
| TEXT3D | 3D text with extrusion/bend; includes the text3d component (see component). |
| IMAGE | A textured image quad; includes the image component (see component). |
| SKETCH | A 3D brush-stroke sketch; includes the sketch component (see component). |
| PORTAL | A portal that navigates to another scene; includes the portal
component (see component). |
| BODYPART | A player bodypart, obtained with getPlayerBodypart; includes the bodypart
component (see component). |
- Built-in components are created automatically and cannot be removed.
- Type-specific creation parameters are documented in each component’s section.
ComponentType
Valid component types used by FigminObject.addComponent to attach components at runtime.
Use these to extend an object’s capabilities beyond its built-in component.
| Name | Description |
|---|---|
| PHYSICS | Adds a physics body to the object; exposes the physics property
(see component). Requires a compatible
collider (e.g., BOX, SPHERE, APPROXIMATE); not allowed with EXACT/NONE. |
| PHYSICS_MATERIAL | Customizes contact response (bounciness/friction); exposes
physicsMaterial (see
component). Often paired with PHYSICS, but can be added
independently.
|
| LIGHT | Adds a light source to the object; exposes light (see component). |
| MOTION | Animates the object along a keyframe path; exposes motion (see component). |
| SKETCH | Adds a sketch (brush strokes) component; exposes sketch (see component). Also built-in on SKETCH
objects. |
- Check each component’s addComponent parameters for defaults and constraints.
- Some components have preconditions (e.g., PHYSICS requires a compatible collider). See their component sections for details.
ObjectState
Lifecycle states reported via a FigminObject’s status
component (obj.status.state).
| Name | Description |
|---|---|
| UNINITIALIZED | Object was just created; data is not yet valid. Most APIs are unavailable at this point |
| LOADING | Object is downloading/processing required data. Some APIs may be unavailable until it becomes READY. |
| READY | Object is ready for use. It may transition back to LOADING if an API call requests a reload or recalculation. |
| DESTROYED | Object was destroyed and can no longer be used. Listen for this via
obj.onDestroy.
|
| ERROR | Object failed to load/initialize. See status
properties description and code for details. |
- Observe transitions with
obj.onStatusChanged(callback) from the status component.- DESTROYED is terminal; after destruction, the handle should not be reused.
InteractionState
This state controls whether a FigminObject allows user interaction or not.
Scripts can always interact with objects no matter the interaction state, this is a user facing setting only.
| Name | Description |
|---|---|
| ENABLED | The user can freely move/rotate/scale the object. |
| LOCKED | The user cannot move/rotate/scale the object, but is able to manually remove the lock. |
- You can't change the interaction state on objects with a read-only transform
ColliderType
Collider shapes assignable to an object’s collider
component (collider.type).
The collider is the physical shape of the model.
| Name | Description |
|---|---|
| NONE | No collider. Object cannot use the physics component while set
to NONE. |
| BOX | Axis-aligned box collider. Fast and stable; compatible with
physics.
|
| SPHERE | Sphere collider. Very fast; good for round or approximate shapes; compatible
with physics. |
| APPROXIMATE | Convex mesh approximation of the object. More accurate than primitives;
compatible with physics. |
| EXACT | Concave mesh collider for highest fidelity. Not compatible
with the physics component. |
- When a
physics component is present, EXACT and
NONE are disallowed.- Prefer BOX/SPHERE for performance; use APPROXIMATE or EXACT only when needed.
- See the collider component for behavior and restrictions when changing types.
BodypartType
Valid player body part types used to address tracked anatomy (head and hands).
Consumed by getPlayerBodypart and exposed on
bodypart components via bodypart.bodypartType.
| Name | Description |
|---|---|
| HEAD | The player’s head object (center eye). |
| LEFT_HAND | The player’s left hand object. |
| RIGHT_HAND | The player’s right hand object. |
Layers
Raycastable layers used to filter what your ray tests can hit.
Consumed by raycast, raycastAll, raycastSphere, and raycastSphereAll.
| Name | Description |
|---|---|
| SURFACE | Environment surfaces (e.g., floor, room mesh, walls). |
| PHYSICS_OBJ | Dynamic physics-enabled objects. |
| STATIC_OBJ | Static/non-dynamic scene objects. |
| UI | UI elements rendered in the scene. |
- The raycast defaults are
SURFACE, PHYSICS_OBJ, and
STATIC_OBJ (UI is excluded unless you request it).- Pass an array (e.g.,
[figmin.Layers.UI, figmin.Layers.SURFACE]) to limit hits
to specific layers.
RenderMode
Valid rendering modes used by figmin.setRenderMode.
Controls whether the app renders as standard 2D UI or in stereoscopic 3D layouts.
| Name | Description |
|---|---|
| STANDARD | Displays UI in 2D (like a normal web browser). |
| SBS_3D | Stereoscopic 3D — Side-by-Side: left eye on the left half, right eye on the right half. |
| OE_3D | Stereoscopic 3D — Over-Under: left eye on the upper half, right eye on the lower half. |
- Use stereoscopic modes only when your content is authored for SBS/OU layouts.
AppMode
Different modes the app can be set to via figmin.setAppMode.
Controls how the app window is presented in the scene.
| Name | Description |
|---|---|
| DEFAULT | Renders the HTML content normally in the app window. |
| MINIMIZED | Hides the window and stops rendering; an icon is shown in its place. |
| OBJECT | Intended for rendering 3D content using the WebView. Always faces the player (billboard) and user interaction is disabled. Configure its interaction bounds with figmin.setObjectModeBounds. |
| HUD | Locks the window in front of the player with a capped field of view of 55°. |
| FULLSCREEN | Fills the player’s entire field of view. |
- In HUD and OBJECT modes the window’s pose can differ from the app object’s transform.
MotionEndBehavior
Controls what happens when a motion path reaches its end, used by the motion component.
If not specified in the component’s parameters, the default is LOOP.
| Name | Description |
|---|---|
| LOOP | When the timeline reaches the end, it restarts from the beginning and repeats continuously. (Default) |
| PING_PONG | When the timeline reaches the end, it reverses direction and plays back toward the start, then forward again, and so on. |
-
endDelay (and randomizeDelay, if enabled) is applied at each
loop/turnaround boundary.- Works with keyframes defined via
motion.setKeyframes(...).
InputCode
The different inputs that can be requested via figmin.enableInputConnect and queried with the getInput, getInputDown, and getInputUp APIs.
Request only the inputs you intend to read to keep processing lightweight.
| Name | Description |
|---|---|
| A | Button A on the controller. |
| B | Button B on the controller. |
| X | Button X on the controller. |
| Y | Button Y on the controller. |
| GRIP_LEFT | Left grip button on a motion controller (or bumper on a gamepad). |
| GRIP_RIGHT | Right grip button on a motion controller (or bumper on a gamepad). |
| SELECT_LEFT | Left trigger button. |
| SELECT_RIGHT | Right trigger button. |
| AXIS_X_RIGHT | X axis of the right thumbstick. |
| AXIS_Y_RIGHT | Y axis of the right thumbstick. |
| AXIS_X_LEFT | X axis of the left thumbstick. |
| AXIS_Y_LEFT | Y axis of the left thumbstick. |
| THUMB_LEFT | Left thumbstick press (button). |
| THUMB_RIGHT | Right thumbstick press (button). |
- getInput returns a float; axes are in
[0..1] and
buttons are 0 or 1.- Use getInputDown/getInputUp to detect discrete button press/release frames.
InputType
The type of input mechanism a bodypart is using.
| Name | Description |
|---|---|
| HAND_TRACKING | Hands free controls. |
| MOTION_CONTROLLER | A motion controller. |
| TOUCH_SCREEN | Touch screen controls are found in smartphones. |
physics.CollisionDetectionMode
How the physics engine detects collisions for a body (see physics component).
Choose a mode based on speed/accuracy needs vs. performance. Default in physics params: CONTINUOUS.
| Name | Description |
|---|---|
| DISCRETE | Standard step-based collision checks. Fastest; suitable for most slow/medium-speed bodies. |
| CONTINUOUS | Reduces tunneling for faster motion by using continuous checks against the world. (Default) |
| CONTINUOUS_DYNAMIC | Higher accuracy continuous detection for fast-moving dynamic bodies. Higher cost. |
| CONTINUOUS_SPECULATIVE | Speculative contacts to anticipate impacts. Good robustness at moderate cost. |
- Use more conservative/continuous modes for small, fast objects to avoid tunneling.
- Pair with an appropriate ColliderType and timestep for best results.
physics.ForceFieldType
The shape of the force field applied by the physics component.
Controls how acceleration is distributed in space.
| Name | Description |
|---|---|
| NONE | No force field is applied. |
| SPHERE | Radial field from the object’s origin, limited by
forceFieldReach.
|
| FLAT | Planar field with a single push/pull direction (see ForceFieldDirection). |
- Strength/falloff configured via
forceFieldAcceleration and
forceFieldForceType on the physics component.
physics.ForceFieldForceType
Force falloff model for a physics component force field.
Determines how acceleration changes with distance.
| Name | Description |
|---|---|
| SQUARED | Inverse-square style falloff; stronger near the source, weaker with distance. |
| CONSTANT | No falloff; uniform strength within forceFieldReach. |
physics.ForceFieldDirection
Direction of a planar (FLAT) force field on the physics component.
Applied in the object’s local coordinate system.
| Name | Description |
|---|---|
| UP | Positive local Y. |
| DOWN | Negative local Y. |
| LEFT | Negative local X. |
| RIGHT | Positive local X. |
| FORWARD | Positive local Z. |
| BACK | Negative local Z. |
- Only relevant when ForceFieldType is FLAT.
- The effective world direction changes with the object’s rotation.
physics.Combine
How two physics materials combine their friction/bounce, used by the physicsMaterial component.
The effective contact uses both colliders’ materials and the selected combine modes.
| Name | Description |
|---|---|
| AVERAGE | Mean of the two values. |
| MULTIPLY | Product of the two values. |
| MINIMUM | Lower of the two values. |
| MAXIMUM | Higher of the two values. |
lights.LightType
Types of lights supported by the light component.
Select the light’s emission model. Default in light: POINT.
| Name | Description |
|---|---|
| SPOT | A cone-shaped light. Use with spotlightAngle; affected by
range.
|
| DIRECTIONAL | Sun/sky style light with parallel rays. No attenuation with distance. |
| POINT | Omnidirectional point source. Intensity attenuates with range.
(Light default)
|
- For SPOT/DIRECTIONAL, set orientation via
light.rotation (Euler
degrees).- Shadows/effects are configured separately (see enums below).
lights.ShadowType
Shadow rendering modes for the light component.
Controls if/how the light casts shadows. Default in light: NONE.
| Name | Description |
|---|---|
| NONE | No shadows are cast. |
| HARD | Enables shadow casting with hard edges. |
| SOFT | Enables filtered, softer-edged shadows. |
- Pair with
shadowNearPlane on light to tune
contact shadows.- Global toggles are available at the scene level via SceneShadowMode.
lights.LightEffect
Special visual effects for the light component.
Applies time-based or reactive behaviors. Default: NONE.
| Name | Description |
|---|---|
| NONE | No special effect; steady illumination. |
| FLICKER | Random light intensity flicker (e.g., torch/firelight vibe). |
| AUDIO_REACTIVE | Light reacts to audio amplitude (device/runtime dependent). |
| PULSE | Periodic pulsing of intensity. |
| RAINBOW | Cycles hue over time for colorful effects. |
lights.LightProjection
“Cookie” projection patterns for the light component.
Projects a texture-like pattern through the light. Default: NONE.
| Name | Description |
|---|---|
| NONE | No projection pattern. |
| FLASHLIGHT1 | Flashlight-style beam pattern. |
| SPOTLIGHT1 | Spotlight gobo pattern #1. |
| SPOTLIGHT2 | Spotlight gobo pattern #2. |
lights.SceneShadowMode
Global shadow override for the active scene (via getScene →
scene.shadowMode).
Forces shadows on/off or defers to the system default. Default: DEFAULT.
| Name | Description |
|---|---|
| DEFAULT | Use the runtime’s default shadow behavior. |
| FORCE_ON | Force-enable scene shadows (where supported). |
| FORCE_OFF | Force-disable scene shadows. |
Multiplayer
All FigminObjects are networked by default: when your script changes a property on an
object or component, that change replicates to all peers automatically.
Figmin XR's multiplayer is peer-to-peer.
Each Spatial App has a master client—the peer who created it. The master executes the script without restrictions. On non-master peers the script still runs, but most write/create operations are ignored (no-ops).
If the master-client disconnects, a new master client is elected, the script will reload and the process will start again.
figmin.isMasterClient()→ Use this to early-out on non-masters.- Non-masters can load the app and read state, but should avoid making changes.
- This keeps multiplayer simple: one script instance performs authoritative work.
Write your app as if it were single-player, then gate mutations behind the master-check. This avoids wasted CPU on non-masters.
function init() {
// Early-out on non-masters
if (!figmin.isMasterClient()) {
return;
}
// Master-only section: create objects, perform mutations, etc
}
- Since only the master client executes code, the UI will be inoperable on non-master peers without additional work.
Brush Catalog
The Brush Catalog contains descriptors for every brush available in Figmin XR. Each entry defines the metadata and behavior of a brush, such as its category, minimum pressure, and whether it is audio-reactive.
figmin.sketch.stroke() or the various sketch functions.
The API defines the figmin.brushes
namespace, which exposes all brush definitions listed in the brush catalog table below (e.g.,
figmin.brushes.MetallicTube).
Each brush object in the catalog exposes the following properties:
| Name | Type | Description |
|---|---|---|
| id | string | Unique identifier for this brush. This is what appears in stroke objects as
id.
|
| name | string | Human-readable name of the brush. |
| category | string | Category of this brush. Possible values: "FLAT",
"3D", "PARTICLES",
"CONVEX_HULL".
|
| minPressure | number | The minimum pressure the brush supports. Effective pressure in a stroke is clamped to this value. |
| audioReactive | boolean | Whether the brush responds dynamically to audio input |
| description | string | The description of this brush, as shown in the catalog section below |
Brush Category
Brushes in Figmin XR fall into four distinct categories, each with very different rendering behaviors:
"FLAT" — A 2D paint-like stroke, typically used to represent a stroke of paint on a surface. The renderer will automatically segment sharp angles into multiple strokes.
"3D" — A volumetric stroke with depth. These brushes generate 3D geometry along the path of the control points, giving strokes a sculpted or extruded appearance.
"CONVEX_HULL" — A special type of stroke that produces a convex mesh enclosing all control points. This can create hull-like or solid shapes. Use a small stroke size unless you explicitly want to inflate the resulting mesh.
"PARTICLES" — A particle system brush. At each control point, particles are emitted according to the brush’s definition, resulting in effects such as sparks, smoke, or trails.
Below is the list of available brushes in the catalog. Use them in code by prefixing the name with
figmin.brushes. (e.g., figmin.brushes.MetallicTube).
id, name, category, minPressure,
audioReactive, description).
Audio-reactive brush names end with _AR.
| Name | Category | Description |
|---|---|---|
OilPaint |
FLAT | Slightly rough-textured brush strokes |
Ink |
FLAT | Smooth paint with tapered brush strokes. Good for adding detail, creating foliage, and calligraphy |
ThickPaint |
FLAT | Rough-textured brush strokes |
WetPaint |
FLAT | Shiny & thick brush strokes. Good for creating shiny surfaces and details |
Gouache |
FLAT | Matte, textured brush strokes. Good for details |
DryBrush |
FLAT | |
Flat |
FLAT | Shaded flat brush |
Marker |
FLAT | Unshaded flat brush |
TaperedFlat |
FLAT | Flat brush, tapered on one end. Use short brush strokes to create flower petals |
TaperedMarker |
FLAT | Flat brush, tapered on one end. Use short brush strokes to create flower petals |
TaperedHueShift |
FLAT | Flat brush, tapered on one end. Use short brush strokes to create flower petals |
DoubleTaperedFlat |
FLAT | Flat brush, tapered on both ends. Use short brush strokes to create individual leaves |
DoubleTaperedMarker |
FLAT | Flat brush, tapered on both ends. Use short brush strokes to create individual leaves |
DoubleTaperedHue |
FLAT | Tapered on both ends with hue shift colors |
SoftHighlighter |
FLAT | Creates transparent, glowing brush strokes. Good for light rays, clouds, and adding glow |
SoftHighlighter_AR |
FLAT | Creates transparent, glowing brush strokes. Good for light rays, clouds, and adding glow - Audio Reactive |
Highlighter |
FLAT | Creates transparent, glowing brush strokes. Good for light rays, clouds, and adding glow |
VelvetInk |
FLAT | Transparent brush strokes. Good for sketching |
VelvetInk_AR |
FLAT | Transparent brush strokes. Good for sketching - Audio Reactive |
DuctTape |
FLAT | Large, flat textured brush. Good for creating flat textured surfaces |
Paper |
FLAT | Large, flat, slightly textured brush. Good for creating flat surfaces |
CoarseBristles |
FLAT | Scattered bristle brush strokes. Good for creating grass & fur |
WigglyGraphite |
FLAT | Creates rough animated brush strokes. Good for adding subtle movement to water, landscapes, characters, etc |
WigglyGraphite_AR |
FLAT | Creates rough animated brush strokes. Good for adding subtle movement to water, landscapes, characters, etc - Audio Reactive |
CelVinyl |
FLAT | Flat, tapered brush with black outlines. Good for stylized cartoon designs |
Charcoal |
FLAT | Good for adding rough texture to surfaces |
Light2 |
FLAT | Creates bright brush strokes |
Light2_AR |
FLAT | Creates bright brush strokes - Audio Reactive |
Light |
FLAT | Creates bright brush strokes |
Light_AR |
FLAT | Creates bright brush strokes - Audio Reactive |
Fire2 |
FLAT | Creates animated fire effects |
Fire2_AR |
FLAT | Creates animated fire effects - Audio Reactive |
Fire |
FLAT | Creates animated fire effects |
Fire_AR |
FLAT | Creates animated fire effects - Audio Reactive |
Embers |
PARTICLES | Creates animated rising motes of light |
Embers_AR |
PARTICLES | Creates animated rising motes of light - Audio Reactive |
Comet |
FLAT | |
Comet_AR |
FLAT | - Audio Reactive |
Smoke |
PARTICLES | Creates floating, 3D smoke. Layer multiple colors together to create gradients |
SmokeTiny |
PARTICLES | Creates floating, 3D smoke. Layer multiple colors together to create gradients |
Wind |
FLAT | |
Stars |
PARTICLES | Creates animated stars |
Stars_AR |
PARTICLES | Creates animated stars - Audio Reactive |
Waveform |
FLAT | Creates an animated waveform. Use brighter or darker colors to change the speed of animation |
Waveform_AR |
FLAT | Creates an animated waveform. Use brighter or darker colors to change the speed of animation - Audio Reactive |
WaveformFFT |
FLAT | Creates an animated fourier transform. Use brighter or darker colors to change the speed of animation |
WaveformFFT_AR |
FLAT | Creates an animated fourier transform. Use brighter or darker colors to change the speed of animation - Audio Reactive |
ChromaticWave |
FLAT | Creates an animated, rainbow waveform. Useful for energy effects & sci-fi designs |
ChromaticWave_AR |
FLAT | Creates an animated, rainbow waveform. Useful for energy effects & sci-fi designs - Audio Reactive |
Plasma |
FLAT | Creates animated plasma |
Plasma_AR |
FLAT | Creates animated plasma - Audio Reactive |
Electricity |
FLAT | Creates animated lightning. Use brighter or darker color to change lightning intensity |
Electricity_AR |
FLAT | Creates animated lightning. Use brighter or darker color to change lightning intensity - Audio Reactive |
Splatter |
FLAT | Scattered spatter brush strokes. Good for creating moss, foliage, & fluffy textures |
Streamers |
FLAT | Creates animated trails of light. Good for creating fireworks, running water, and magic effects |
Streamers_AR |
FLAT | Creates animated trails of light. Good for creating fireworks, running water, and magic effects - Audio Reactive |
Hypercolor |
FLAT | Creates animated iridescent brush strokes. |
Hypercolor_AR |
FLAT | Creates animated iridescent brush strokes. - Audio Reactive |
HypercolorTransparent |
FLAT | Creates animated iridescent translucent brush strokes. |
HypercolorTransparent_AR |
FLAT | Creates animated iridescent translucent brush strokes. - Audio Reactive |
Snow |
PARTICLES | Creates animated falling snowflakes. Small brush sizes & other colors can be used to simulate falling particles |
Snow_AR |
PARTICLES | Creates animated falling snowflakes. Small brush sizes & other colors can be used to simulate falling particles - Audio Reactive |
Bubbles |
PARTICLES | Creates animated bubbles |
RisingBubbles |
PARTICLES | Creates animated bubbles |
Hearts |
PARTICLES | Creates animated hearts |
Dots |
PARTICLES | Creates glowing dots in a line. Useful for creating a variety of glowing light sources |
Dots_AR |
PARTICLES | Creates glowing dots in a line. Useful for creating a variety of glowing light sources - Audio Reactive |
Fairy |
FLAT | Creates an animated glitter effect. Good for creating magical effects and glittering surfaces |
ShinyHull |
CONVEX_HULL | Creates shiny 3D shapes |
MatteHull |
CONVEX_HULL | Creates matte 3D shapes |
UnlitHull |
CONVEX_HULL | Creates unshaded 3D shapes |
DiamondHull |
CONVEX_HULL | Creates transparent, shiny 3D shapes. Good for making water, ice, crystals, and glass surfaces |
MetallicHull |
CONVEX_HULL | Creates metallic 3D shapes |
StainedGlassHull |
CONVEX_HULL | Creates textured glass shapes |
ToonHull |
CONVEX_HULL | Creates cartoon style 3D shapes |
SmoothHull |
CONVEX_HULL | Creates smooth, shiny 3D shapes |
SmoothMatteHull |
CONVEX_HULL | Creates smooth, matte 3D shapes |
MetallicSmoothHull |
CONVEX_HULL | Creates smooth metallic 3D shapes |
SmoothDiamondHull |
CONVEX_HULL | Creates smooth transparent 3D shapes. Good for making water, ice, crystals, and glass surfaces |
MetallicTube |
3D | |
Icing |
3D | Creates textured, 3D brush strokes. Good for wood, stems, snow, and frosting |
Toon |
3D | Creates 3D brush strokes with black outlines. Good for stylized cartoon designs |
Toon_AR |
3D | Creates 3D brush strokes with black outlines. Good for stylized cartoon designs - Audio Reactive |
MylarTube |
3D | Metallic, 3D brush strokes. Useful for jewelry & metal filigree. Use short brush strokes to create mushrooms |
TubeAdditive |
3D | |
MetallicWire |
3D | Metallic tapered tubes |
DiamondWire |
3D | Diamond tapered tubes |
ToonWire |
3D | Cartoon style tapered tubes |
Wire |
3D | Unshaded 3D brush strokes. Combine with Unlit Hull to add detail to unshaded shapes |
Spikes |
3D | Good for creating vines, stems, horns and spikes |
MetallicSpikes |
3D | |
SpikesToon |
3D | Good for creating vines, stems, horns and spikes |
Lofted |
3D | Creates thick, pointed brush strokes |
LoftedMetallic |
3D | Creates thick, pointed metallic brush strokes |
LoftedToon |
3D | Creates cartoon style pointed brush strokes |
LoftedHueShift |
3D | Creates thick, pointed brush strokes |
BubbleWand |
3D | Creates iridescent, 3D bubble shapes with a floaty animation. Useful for clouds, fantasy creature parts, and bubbles |
SquarePaper |
3D | Creates rectangular 3D brush strokes. Good for architecture and other non-organic shapes |
Feather |
FLAT | |
Feather_AR |
FLAT | - Audio Reactive |
Petal |
3D | Creates 3D flower shapes. Use short brush strokes to create flowers & leaves, or long brush strokes to create vines |
Rainbow |
FLAT | Creates animated rainbows. Not effected by brush color |
Rainbow_AR |
FLAT | Creates animated rainbows. Not effected by brush color - Audio Reactive |
Disco |
3D | Shiny disco tubes |
Disco_AR |
3D | Shiny disco tubes - Audio Reactive |
NeonPulse |
FLAT | Creates transparent tubes with animated neon light pulses. Useful for neon signs, magical items, and sci-fi designs |
NeonPulse_AR |
FLAT | Creates transparent tubes with animated neon light pulses. Useful for neon signs, magical items, and sci-fi designs - Audio Reactive |
Muscle |
3D | Tapered, muscle-textured 3D brush strokes. Good for creating creatures |
Guts |
3D | Rounded, shiny-textured 3D brush strokes. Good for horns, coral, and, yes - guts |
Rain |
FLAT | Creates animated droplets. Good for creating running water, fireworks, and magical effects |
HyperGrid |
FLAT | Creates sci-fi grid shapes. Useful for sci-fi designs |
HyperGrid_AR |
FLAT | Creates sci-fi grid shapes. Useful for sci-fi designs - Audio Reactive |
ArrowsBrush |
FLAT | Creates animated arrows |
LightWire |
3D | |
LightWire_AR |
3D | - Audio Reactive |
InvisibleHull |
CONVEX_HULL | Creates invisible shapes that block out all digital content. Useful for creating occlusion and portal entrances |
Development Guide
This guide covers two workflows for Figmin XR spatial apps:
- Development: run your HTML from a local web server so you can iterate quickly and simply reload in Figmin XR to see changes.
- Release: embed your HTML into the spatial app by offering a downloadable file in the Figmin XR browser; no server required after deployment.
You don’t need a web server to publish. When an HTML file is offered as a download in the Figmin XR browser, a dialog will prompt to load the spatial app and its contents are embedded directly into Figmin XR. During development, though, a local server makes iteration faster.
Development workflow (web server)
During development you’ll serve your .html from your computer and open it from the
Figmin XR browser using
your machine’s IP address. That way, edits are reflected immediately, just reload the web-app in
Figmin XR.
1) Start a simple local server
We recommend Python’s built-in HTTP server. Open a terminal in the folder that contains your app’s HTML and run:
python -m http.server 8000
This serves the current folder at http://<your-ip>:8000.
To open a terminal in Windows search for "Command Prompt", for Mac OS simply type "Terminal"
2) Find your computer’s IP address
Use your OS network settings (Wi-Fi/Ethernet details). You’re looking for something like
192.168.0.23
or 10.0.0.10 on your local network.
You can also obtain your IP address from a terminal, in Windows (Command Prompt) type:
ipconfig
Look for the line labeled IPv4 Address.
3) Open it from Figmin XR
In Figmin XR, open the in-app browser and type <your-ip>:8000.
You’ll see the directory listing from your server. Tap your HTML (e.g.,
my-app.html) to load your spatial-app.
4) Edit → Reload loop
Edit your files on your computer, then in Figmin XR just reload the page to see changes. No redeploy step is needed while developing.
Do not publish a spatial app that points to a local web
server (e.g., an IP address such as 192.168.x.x)—it won’t work and it isn’t
safe.
You may absolutely publish a spatial app that uses a real internet web server; this also gives you control over future app updates.
Release Workflow (embed your app)
Once your app is ready for release, you’ll offer an HTML file for download inside the Figmin XR browser. Figmin XR will prompt to deploy the spatial app; on deploy, the HTML is embedded into the app’s data, no server needed at runtime. This is the recommended way to publish single-file apps.
How do I offer the file for download?
Discord: On your computer, drag and drop your HTML into your discord server. In Figmin XR sign in to Discord and click the file to download and deploy.
AI assistant link: If you use an AI assistant that you can can log into from Figmin XR, ask it to generate a direct download link to your HTML file. Open the link in the Figmin XR browser to download and deploy.
Tip: Make sure it’s a direct file URL (ends in .html),
not a preview page.
Once deployed, the embedded HTML cannot be updated in place. Only use this workflow when your app is ready to ship
Multi-file / complex apps
If your app spans multiple files (modules, assets, etc.), you can host them on an Internet web server. Doing so gives you full control over future updates—just update your hosted files and users will pull the new version next launch.
Complete Examples
This section showcases complete, ready-to-run examples demonstrating how to build
spatial apps with
the Figmin XR API. Examples range from beginner to advanced and were mostly generated with AI.
Each example includes two actions: View Code and Download / Run. When you click "Download / Run" within Figmin XR, a dialog will appear asking if you’d like to load the spatial app. The contents of the file are then embedded directly into Figmin XR, so no web server is required.
Controllable Character
This spatial app creates an animated character that the user can control. It can walk, run, jump, and emote.
How it works
- Create a
MODEL3Dobject for the character. - Enable controller input with
enableInputConnectand start the game loop viasetUpdateFunction. - On each update, read input (axes/buttons) with
getInput, advance a small state machine (idle/walk/run/jump/emote), and apply movement. - Use
raycastto detect floor/steps/overhead obstacles and to keep motion grounded.
API used
onStart,
setUpdateFunction,
createObject(MODEL3D),
getCamera,
getWindowSpawnPosition,
getWindow,
enableInputConnect,
getInput,
getInputDown,
InputCode,
transform
model3d
raycastSphere,
Layers
Code
RC Airplane
This example creates an interactive, physics-driven RC airplane you can fly around your room. Lift, drag, thrust, and control-surface torques are computed each frame to simulate flight.
How it works
- Create a
MODEL3Dairplane with URL,targetSize, andcolliderTypeset increateObjectparams. Spawn it next to the app window usinggetWindowSpawnPosition. - When the model starts, attach a
physicscomponent and wire up inputs:enableInputConnect. - Run a per-frame flight loop with
setUpdateFunction: read controls viagetInput(InputCode), compute lift/drag, apply thrust, and use the physics API to apply forces/torques. - For ground effect, cast near-ground probes with
raycastagainstLayers; optionally visualize vectors withdebugDraw. - Gate browser usage with
isSpatialApp/requireSpatialAppso users can deploy/run as a spatial app.
API used
onStart,
setUpdateFunction,
createObject
(ObjectType.MODEL3D),
ColliderType.APPROXIMATE,
getWindowSpawnPosition,
getWindow,
enableInputConnect,
getInput
(InputCode.*),
physics
(mass/drag, collision detection mode, applyForce,
applyTorque),
raycast,
Layers,
debugDraw,
isSpatialApp,
requireSpatialApp,
transform,
ObjectState.READY
Code
Player Wisps
Glowing “wisps” flock toward players’ hands and swirl playfully around them. As hands move, nearby wisps get tugged along, creating a subtle “wind” effect. If the player grabs an object, the wisps will follow it for a short while.
How it works
- Wait for the
FigminReadyevent. - Query the current players with
getPlayers, then subscribe toonPlayerConnected/onPlayerDisconnectedto keep the set in sync. - For each player, obtain hand bodyparts via
getPlayerBodypart(BodypartType.LEFT_HAND / RIGHT_HAND). - Spawn a flock of SKETCH dots (wisps) with
createObjectone of them has a POINT light for extra sparkle. - Each wisp is set to interactionState = figmin.
InteractionState.LOCKED to prevent the user from manipulating it. - Drive updates with
setUpdateFunction:- Compute each tracked hand’s velocity from the
bodypartray origin positions. - Apply a spring-like attraction toward the current target hand, add a gentle swirl, and clamp speeds.
- When a wisp is very close to a moving hand, blend in some of the hand’s velocity to simulate “wind.”
- Cycle the flock’s target hand every few seconds; fall back to the window position if no hands are tracked.
- Compute each tracked hand’s velocity from the
API used
FigminReady,
getPlayers,
onPlayerConnected,
onPlayerDisconnected,
getPlayerBodypart
(BodypartType),
Component: bodypart,
setUpdateFunction,
createObject
(ObjectType.SKETCH),
getWindowSpawnPosition,
getWindow
Code
Object Ownership (Scene Persistent)
This example shows the difference between script-owned objects and scene-owned objects. Click buttons to create temporary (script-owned) or persistent (scene-owned) 3D text objects and see which ones survive when the script ends.
How it works
- Wait for
FigminReadybefore creating objects. - Wire two buttons: “Create Temporary” and “Create Persistent”. Compute spawn positions beside
the app window with
getWindowSpawnPositionand align rotation fromgetWindow. - Create temporary objects with
createObject(default ownership = script-owned). - Create scene-owned objects by passing
scenePersistent:trueincreateObjectparams, so they remain after the script stops.
API used
FigminReady,
createObject,
createObject(TEXT3D),
ObjectType,
getWindowSpawnPosition,
getWindow,
scenePersistent
Code
Object Visibility
This example demonstrates how to control a FigminObject’s visibility using its
active property. Four 3D text objects are created, and their visibility
is toggled through HTML checkboxes.
How it works
- Wait for the
FigminReadyevent before creating objects. - Spawn four
TEXT3Dobjects next to the app window usinggetWindowSpawnPositionand align their rotation withgetWindow. - Add event listeners to each checkbox in the HTML interface. When a checkbox is toggled,
update the object’s
activeproperty to show or hide it.
API used
FigminReady,
createObject,
createObject(TEXT3D),
ObjectType,
getWindowSpawnPosition,
getWindow,
active
Code
Save & Load UI state
This example shows how to persist UI state using saveState/loadState.
Form controls are tagged with figmin-persist-state so their values are saved with
the spatial app
and restored automatically on the next run.
How it works
- Wait for the
FigminReadyevent. If not in spatial app mode, gate withisSpatialApp/requireSpatialApp. - Tag inputs you want to persist with a unique
figmin-persist-statekey (e.g., text, number, range, checkbox, radio, select, textarea). - On “Save”, call
saveState(you can also include optional custom payload). - On “Load” or automatically on start, call
loadStateto restore all tagged fields and receive any custom data via callback.
API used
FigminReady,
isSpatialApp,
requireSpatialApp,
saveState,
loadState
Code
Dynamic Components
This example demonstrates how to dynamically attach and remove components from a Figmin object. You can add physics, lighting, and a physics material to a 3D text object and modify them in real time.
How it works
- Create a
TEXT3Dobject near the window usinggetWindowSpawnPosition. - Start the update loop with
setUpdateFunctionto keep the UI in sync with the object’s components. - Use UI controls to call
addComponent/removeComponentforphysics,physicsMaterial, andlight. - Adjust component properties live: set mass/drag, apply forces and torque, choose light type and color, enable shadows, and tweak spotlight, projection pattern, and effects.
API used
FigminReady,
setUpdateFunction,
createObject /
createObject(TEXT3D),
getWindowSpawnPosition,
getWindow,
addComponent,
removeComponent,
ComponentType,
transform,
physics
(mass, drag, angularDrag, velocity, angularVelocity, gravityStrength, kinematic,
sleeping, applyForce, applyTorque),
physicsMaterial
(bounciness, staticFriction, dynamicFriction),
light
(type, range, spotlightAngle, rotation, shadowType, shadowNearPlane, projectionPattern,
effect, color),
lights.LightType,
lights.ShadowType,
lights.LightEffect,
lights.LightProjection
Code
Sketch Component
This example demonstrates programmatic sketch generation.
You’ll learn how to set brush strokes on a Sketch component to display a variety of AI-generated
shapes, and how to clone
those strokes into a new object by passing them as parameters to
createObject.
It also shows how to attach a Sketch component to a
TEXT3D object to
generate a pill-shaped background behind the text.
All of the sketch samples in this example were generated by AI, and we encourage you to do the same. While generating procedural geometry can be complex for a human, it’s a straightforward task for an AI assistant
How it works
- Create a single
SKETCHobject and store it in a variable for reuse, we reset it if it’s destroyed usingonDestroyso a new object can be created. - Each “Load Sketch” button builds a list of control points with
sketch.pointand emits one or more strokes withsketch.stroke(choosing brushes from theBrush catalog). The result is applied viaobject.sketch.setBrushStrokes. - “Clone Sketch” reads the current strokes via
object.sketch.getBrushStrokesand creates a newSKETCHobject initialized with those strokes. - “Text with Background” creates a
TEXT3Dobject; when the transform bounds change (onBoundsChanged), it adds aSketch componentto that text and generates rounded-rectangle strokes as a backdrop. We wait for the bounds changed event because the user may later on manually update the text and this will automatically re-adjust the backdrop.
API used
FigminReady,
getWindow,
getWindowSpawnPosition,
createObject
(ObjectType.SKETCH,
ObjectType.TEXT3D),
onDestroy,
onBoundsChanged,
ObjectState,
transform,
sketch.setBrushStrokes /
getBrushStrokes,
sketch.point,
sketch.stroke,
sketch.boxStroke,
sketch.roundedRectangleStroke,
sketch.coneStroke,
sketch.rotateStroke,
sketch.translateStroke
Brushes,
showNavigationArrow