Skip to Content
HooksuseObjectBindings

useObjectBindings

Own object-binding state and update general fields, materials, textures, transforms, metadata, and visibility from one hook.

Every setter uses a functional React state update. Consecutive calls in the same tick compose, including calls across material and visibility concerns.

Define typed bindings

Use defineObjectBindings instead of annotating the object as Record<string, ObjectBinding>. It validates every binding while preserving exact keys, IDs, action IDs, groups, and tags for autocomplete and reusable union types.

import { defineObjectBindings, type ObjectBindingActionId, type ObjectBindingKey, } from "@liveroom-tech/react-immersive"; const initialBindings = defineObjectBindings({ switch_a: { id: "switch-a", modelObjectId: "switch_a", type: "switch", group: "controls", tags: ["interactive"], actions: [ { id: "turn-on", label: "Turn On", type: "command" }, { id: "turn-off", label: "Turn Off", type: "command" }, ], }, }); type BindingKey = ObjectBindingKey<typeof initialBindings>; // "switch_a" type SwitchAction = ObjectBindingActionId<typeof initialBindings, "switch_a">; // "turn-on" | "turn-off"

defineObjectBindings returns the same object without cloning or changing it at runtime. BindingBuilder uses this helper in exported TypeScript files automatically.

Usage

import { ModelViewer, patchBindings, selectBindings, selectBindingKeys, useObjectBindings, } from "@liveroom-tech/react-immersive"; const { objectBindings, setObjectBindings, updateObjectBindings, selectObjectBindings, selectObjectBindingIds, setMaterial, setBaseColor, setTexture, clearTexture, copyMaterial, resetMaterial, getMaterial, setTransform, resetTransform, updateMetadata, hiddenObjects, hiddenObjectIds, hideObject, showObject, toggleObjectVisibility, isObjectHidden, clearHiddenObjects, } = useObjectBindings(initialBindings); <ModelViewer objectBindings={objectBindings} onObjectBindingsChange={setObjectBindings} ... />

Parameter

NameTypeDescription
initialBindingsRecord<string, ObjectBinding> | () => Record<string, ObjectBinding>Initial binding state or initializer

General patches

Patch one object, a group, or an atomic edit batch:

updateObjectBindings("body", { visible: false }); updateObjectBindings({ group: "wheels" }, { selectable: false }); updateObjectBindings([ { ids: "body", patch: { metadata: { state: "active" } } }, { ids: { tag: "lighting" }, patch: { visible: true } }, ]);

Nested objects are merged, arrays and tuples are replaced, and explicit undefined values clear fields. Identifiers resolve by binding map key, binding.id, then binding.modelObjectId.

Groups, tags, and selectors

Store a single group and any number of tags on each binding. BindingBuilder provides fields for both and includes them in exported bindings.

const initialBindings = { WheelFL: { id: "wheel-front-left", modelObjectId: "WheelFL", type: "wheel", group: "wheels", tags: ["exterior", "configurable"], }, }; setBaseColor({ group: "paint" }, "#ef4444"); hideObject({ tag: "optional" }); updateObjectBindings({ type: "wheel" }, { selectable: false }); const exterior = selectObjectBindings({ tag: "exterior" }); const wheelIds = selectObjectBindingIds({ type: "wheel" });

Group, tag, and type matching is exact and case-sensitive. All mutation helpers that previously accepted an identifier or identifier array also accept these selectors.

Material operations

setMaterial("body", { baseColor: "#ef4444", metalness: 0.7, roughness: 0.25, }); setBaseColor("body", "#2563eb"); setTexture({ group: "screens" }, "/images/dashboard.png"); setTexture("panel", "/images/panel-normal.png", "normal"); clearTexture("panel", "normal"); copyMaterial("wheel-front", { group: "wheels" }); const currentMaterial = getMaterial("body"); resetMaterial("body");

Material setters merge with existing material fields. resetMaterial removes the complete material override, while copyMaterial replaces each target’s complete override with an independent copy of the source material.

setTexture accepts either a URL or { path: url }. It targets the base-color texture by default. Its optional channel supports material maps such as normal, roughness, metalness, emissive, ao, and clearcoat.

Transform and metadata operations

setTransform("door-left", { position: [0, 1, 0], rotation: [0, Math.PI / 2, 0], scale: [1, 1, 1], }); resetTransform("door-left"); updateMetadata({ group: "lights" }, { state: "on", circuit: "a" });

Transforms are persistent local-space binding state. Rotations use radians. Missing transform fields retain the model-authored value, and resetTransform restores the complete model-authored local transform. Metadata updates merge recursively with existing metadata.

Visibility operations

hideObject("body"); showObject({ group: "wheels" }); toggleObjectVisibility("spoiler"); clearHiddenObjects(); const hidden = isObjectHidden("body");

hideObject, showObject, and toggleObjectVisibility accept one identifier, an identifier array, or a group, tag, or type selector. hiddenObjects and hiddenObjectIds are derived from the current binding state.

Returns

NameDescription
objectBindingsCurrent object-binding state
setObjectBindingsReact state dispatcher for controlled viewers
updateObjectBindingsUpdate one object, a group, or an atomic edit batch
selectObjectBindingsReturn bindings matching an identifier or selector
selectObjectBindingIdsReturn binding IDs matching an identifier or selector
setMaterialMerge material fields
setBaseColorSet the material base color
setTextureSet a base-color or material-map texture
clearTextureClear one texture channel
copyMaterialCopy one complete material override to targets
resetMaterialRemove the material override
getMaterialRead the current material override
setTransformMerge a persistent local transform
resetTransformRestore the model-authored local transform
updateMetadataMerge metadata fields
hiddenObjectsMap of hidden binding keys
hiddenObjectIdsIDs of currently hidden bindings
hideObjectHide one object or a group
showObjectShow one object or a group
toggleObjectVisibilityToggle each target’s current visibility
isObjectHiddenCheck whether an object is hidden
clearHiddenObjectsShow every bound object

Externally owned state

When a parent component or store owns the bindings, use the pure patchBindings utility instead:

const next = patchBindings(objectBindings, "body", { style: { material: { baseColor: "#ef4444" } }, }); const exterior = selectBindings(objectBindings, { tag: "exterior" }); const exteriorKeys = selectBindingKeys(objectBindings, { tag: "exterior" }); onObjectBindingsChange(next);

selectBindings and selectBindingKeys provide the same selector queries without React state ownership.