dh.object
Extension: .dh-obj
Type ID: dh.object
An object is a reusable building block: an accessory, outfit, prop, or any composable piece. Objects define what they are through a list of patches, ordered operations that import models, assign materials, set transforms, and more.
dh.avatar extends this type.
Properties
Section titled “Properties”| Property | Type | Required | Description |
|---|---|---|---|
$type | "dh.object" | no | Type identifier |
name | string | no | Display name |
description | string | no | Description |
inherits | string | no | Barcode of the object to inherit from |
patches | array | no | Ordered list of patches to apply |
The type is inferred from the file extension, so
$typeis not needed in source files. The compiler adds it automatically during builds.
Example
Section titled “Example”{ "name": "Cat Ears", "patches": [ { "$type": "dh.import-model", "path": "models/ears.glb" }, { "$type": "dh.set-material", "target": "Ears", "slot": 0, "path": "materials/fur.dh-mat" } ]}Target Paths
Section titled “Target Paths”Many patches use a target property to reference objects in the hierarchy. These are hierarchical paths using the object names from imported models:
"Body": a root-level object named Body"Armature": a root-level armature"Armature/Hips/Spine": nested path through the hierarchy
Target paths are resolved after all imports, so you can reference objects from any previously-imported model.
Patch Reference
Section titled “Patch Reference”Patches are applied in order. Each patch has a $type that identifies what it does.
dh.import-model
Section titled “dh.import-model”Import a 3D model file into the hierarchy.
| Property | Type | Required | Description |
|---|---|---|---|
$type | "dh.import-model" | yes | |
path | string | yes | Model file path (.glb or .fbx, relative to pallet root) |
as | string | no | Rename the import root object |
{ "$type": "dh.import-model", "path": "models/body.glb", "as": "MainBody"}FBX files are automatically converted to GLB via Blender during compilation.
dh.import-object
Section titled “dh.import-object”Import another dh.object definition, bringing in all of its patches.
| Property | Type | Required | Description |
|---|---|---|---|
$type | "dh.import-object" | yes | |
path | string | yes | Object definition path (relative or barcode) |
as | string | no | Rename the import root |
parent | string | no | Parent object path to attach under |
{ "$type": "dh.import-object", "path": "accessories/glasses/glasses.dh-obj", "parent": "Head"}Cross-pallet import:
{ "$type": "dh.import-object", "path": "io.mltn.accessories:glasses/glasses.dh-obj"}dh.remove-object
Section titled “dh.remove-object”Remove an object from the hierarchy. If the target doesn’t exist, a warning is logged but no error is raised.
| Property | Type | Required | Description |
|---|---|---|---|
$type | "dh.remove-object" | yes | |
target | string | yes | Hierarchical path of the object to remove |
{ "$type": "dh.remove-object", "target": "Armature/Hips/TailBone"}dh.set-material
Section titled “dh.set-material”Assign a dh.material to a specific material slot on a mesh.
| Property | Type | Required | Description |
|---|---|---|---|
$type | "dh.set-material" | yes | |
target | string | yes | Target mesh path |
slot | int | yes | Material slot index (0-based) |
path | string | yes | Material definition path (relative or barcode) |
{ "$type": "dh.set-material", "target": "Body", "slot": 0, "path": "materials/skin.dh-mat"}dh.set-blendshape
Section titled “dh.set-blendshape”Set the value of a blendshape (morph target) on a mesh.
| Property | Type | Required | Description |
|---|---|---|---|
$type | "dh.set-blendshape" | yes | |
target | string | yes | Target mesh path |
blendshape | string | yes | Blendshape name |
value | float | yes | Value (typically 0.0 – 1.0) |
{ "$type": "dh.set-blendshape", "target": "Body", "blendshape": "smile", "value": 0.75}dh.set-transform
Section titled “dh.set-transform”Set position, rotation, and/or scale on an object. Only the properties you specify are changed.
| Property | Type | Required | Description |
|---|---|---|---|
$type | "dh.set-transform" | yes | |
target | string | yes | Target object path |
position | [x, y, z] | no | Position in local space |
rotation | [x, y, z] | no | Rotation in degrees (Euler) |
scale | number or [x, y, z] | no | Scale (single number = uniform) |
{ "$type": "dh.set-transform", "target": "Glasses", "position": [0, 0.1, 0.05], "scale": [1.1, 1.1, 1.1]}A single number for scale is treated as uniform scale on all axes. "scale": 1.1 is equivalent to "scale": [1.1, 1.1, 1.1].
{ "$type": "dh.set-transform", "target": "Glasses", "scale": 1.1}dh.set-parent
Section titled “dh.set-parent”Move an object under a new parent in the hierarchy.
| Property | Type | Required | Description |
|---|---|---|---|
$type | "dh.set-parent" | yes | |
target | string | yes | Object to reparent |
parent | string | yes | New parent object path |
first | bool | no | If true, makes it the first child (default: false) |
{ "$type": "dh.set-parent", "target": "HairAccessory", "parent": "Head", "first": true}dh.set-rig
Section titled “dh.set-rig”Apply a dh.rig definition to an armature, mapping standard bone names to model-specific bone names.
| Property | Type | Required | Description |
|---|---|---|---|
$type | "dh.set-rig" | yes | |
target | string | yes | Armature/skeleton root path |
path | string | yes | Rig definition path (relative or barcode) |
mesh | string | no | Hierarchy path to the target SkinnedMeshRenderer for visemes/eyelids |
{ "$type": "dh.set-rig", "target": "Armature", "path": "rigs/humanoid.dh-rig", "mesh": "Body"}dh.armature-link
Section titled “dh.armature-link”Link a source armature or object to a target armature. Two modes depending on whether the source has a rig:
Bone-to-bone matching: when the source has a DigitalHeavenRig, bones are matched by standard name. Use this to merge clothing armatures with body armatures.
Single-bone attachment: when the source has no rig, it attaches to a specific bone on the target. Requires the bone property.
| Property | Type | Required | Description |
|---|---|---|---|
$type | "dh.armature-link" | yes | |
target | string | yes | Target armature path (must have a rig applied via dh.set-rig) |
source | string | yes | Source object or armature path |
bone | string | no | Target bone name (required for rig-less sources) |
align | bool | no | Align source transform with target bone (default: true) |
Bone-to-bone example:
{ "$type": "dh.armature-link", "target": "Armature", "source": "OutfitArmature"}Single-bone attachment:
{ "$type": "dh.armature-link", "target": "Armature", "source": "Backpack", "bone": "Chest", "align": false}When align is true (default), the source’s local transform is reset to match the target bone. Set it to false to preserve the source’s original transform.
dh.set-spring-bones
Section titled “dh.set-spring-bones”Add spring bone physics to a bone chain for secondary motion (hair, tails, ears, skirts, etc.). Automatically discovers all child bones from the target root and simulates them using Verlet integration.
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
$type | "dh.set-spring-bones" | yes | ||
target | string | yes | Path to the root bone of the chain | |
ignore | string[] | no | Child transform names to exclude (along with their descendants) | |
stiffness | float | no | 0.3 | Pull toward animated pose (0 = floppy, 1 = locked) |
damping | float | no | 0.7 | Oscillation decay (0 = bouncy, 1 = no motion) |
gravity | float | no | 0.0 | Downward pull strength in world space |
{ "$type": "dh.set-spring-bones", "target": "Body/Armature/Tail1", "stiffness": 0.2, "gravity": 0.3}Multiple chains on the same avatar:
// In the patches array:{ "$type": "dh.set-spring-bones", "target": "Body/Armature/Tail1", "stiffness": 0.2, "gravity": 0.3 },{ "$type": "dh.set-spring-bones", "target": "Body/Armature/EarL1" },{ "$type": "dh.set-spring-bones", "target": "Body/Armature/EarR1" }Excluding specific children:
{ "$type": "dh.set-spring-bones", "target": "Body/Armature/Tail1", "ignore": ["Tail_IK_Target", "Tail_Collider"]}Game mods for platforms with native bone physics (DynamicBone, VRCPhysBone, etc.) can read the spring bone data and translate it to native components, disabling the built-in solver.