Skeleton & Bones

DazSkeleton

class dazpy.DazSkeleton(client, identifier)[source]

Bases: DazNode

Proxy for a DzSkeleton (a rigged figure such as Genesis 9).

Extends DazNode with bone-access helpers.

bones()[source]

Return all bones in this skeleton.

bone_metadata()[source]

Return bulk metadata for every bone in one HTTP call.

This is the live-facing efficiency path used by the interaction adapter. It avoids one request per bone when building rig profiles.

find_bone(name)[source]

Find a bone by its internal name.

Parameters:

name (str) – The getName() string of the bone. Naming conventions differ by figure generation: Genesis 9 uses snake_case (e.g. "r_forearm"); Genesis 3/8 uses "rForearmBend"/"lForearmBend"; Genesis 1/2 uses "rForeArm"/"lForeArm". Use bones() to list every bone name for the loaded figure.

Returns:

A DazBone proxy.

Raises:

NodeNotFoundError – If no bone with that name exists.

Return type:

DazBone

find_bone_by_label(label)[source]

Find a bone by its user-visible label.

Parameters:

label (str) – The getLabel() string of the bone.

Returns:

A DazBone proxy.

Raises:

NodeNotFoundError – If no bone with that label exists.

Return type:

DazBone

num_bones()[source]

Return the total number of bones in this skeleton.

bone_rotations()[source]

Return Euler rotations for every bone in one HTTP call.

Equivalent to calling local_euler on every bone returned by bones(), but rounds-trips only once.

Returns:

{bone_name: (x, y, z)} in degrees for every bone.

Return type:

dict[str, tuple[float, float, float]]

set_bone_rotations(data)[source]

Set Euler rotations for any subset of bones in one HTTP call.

Only the bones named in data are modified; all others are unchanged. Equivalent to calling set_local_rotation() per bone, but rounds-trips only once.

Parameters:

data (dict[str, tuple | list]) – {bone_name: (x, y, z)} or {bone_name: [x, y, z]}, angles in degrees. Bones not in this dict are left as-is.

evaluate_pose(rotations, effector_bone_names)[source]

Apply candidate rotations, read effector world positions, then restore.

The figure is left in its original state after this call. Use this to ask “if I posed these bones this way, where would the effectors end up?” without committing anything to the scene.

Parameters:
  • rotations (dict[str, tuple | list]) – {bone_name: (x, y, z)} candidate rotation set in degrees. Only the listed bones are temporarily modified.

  • effector_bone_names (list[str]) – Bone names whose world-space position should be returned after applying rotations.

Returns:

{bone_name: (x, y, z)} world-space positions for each requested effector bone. Bones not found in the skeleton are omitted.

Return type:

dict[str, tuple[float, float, float]]

evaluate_pose_jacobian(chain_bone_names, effector_bone_name, step_degrees=1.0)[source]

Compute the IK Jacobian for a bone chain server-side in one HTTP call.

For each bone in chain_bone_names and each of its three rotation axes, this perturbs the bone by step_degrees, reads the effector world position, and restores the original rotation. The figure is left unchanged.

Parameters:
  • chain_bone_names (list[str]) – Ordered list of bone names in the IK chain (root → effector direction).

  • effector_bone_name (str) – The bone whose world position is the IK goal.

  • step_degrees (float) – Perturbation size in degrees (default 1.0).

Returns:

  • "base_position"[x, y, z] world position of the effector before any perturbation.

  • "columns" — list of [dx, dy, dz] Jacobian columns, one per (bone × axis) pair, ordered as bone0_x, bone0_y, bone0_z, bone1_x, . Each column is the normalized position change (trial_pos - base_pos) / step_degrees.

Returns None if the effector bone cannot be found.

Return type:

A dict with keys

morph_values(nonzero_only=False)[source]

Return the current value of every DzMorph modifier in one HTTP call.

Parameters:

nonzero_only (bool) – When True, exclude morphs whose value is effectively zero (abs(v) <= 0.0001). Useful for sparse logging.

Returns:

{morph_name: float} for all (or non-zero) morphs.

Return type:

dict[str, float]

set_morph_values(data)[source]

Set the value of any subset of morphs in one HTTP call.

Only morphs named in data are modified; all others are unchanged.

Parameters:

data (dict[str, float]) – {morph_name: float} mapping. Morphs not in this dict are left at their current value.

hand_to_target(target_point, *, source_anchor='r_hand', max_iterations=12, step_degrees=1.0, damping=0.25, tolerance=0.15)[source]

Align a hand anchor toward a world-space target point.

foot_to_target(target_point, *, source_anchor='r_foot', max_iterations=12, step_degrees=1.0, damping=0.25, tolerance=0.15)[source]

Align a foot anchor toward a world-space target point.

bake_bone_rotations(start=None, end=None, bone_names=None)[source]

Bake bone rotation keyframes for every frame in the range.

Scrubs the timeline server-side. For each frame, the current evaluated X/Y/Z rotation of every bone (including IK, constraints, and driven keys) is stamped as an explicit keyframe via insertKey. After baking, the animation plays back without requiring any of the original drivers.

The original frame is restored before the call returns.

Parameters:
  • start (int | None) – First frame to bake. None → play-range start.

  • end (int | None) – Last frame to bake. None → play-range end.

  • bone_names (list[str] | None) – Subset of bone names to bake. None → all bones.

Returns:

{"frames_baked": int, "bones_baked": int}

Raises:

NodeNotFoundError – If the skeleton is not found.

Return type:

dict

bake_morphs(start=None, end=None, morph_names=None)[source]

Bake morph channel keyframes for every frame in the range.

For each frame, the current value of every DzMorph modifier is stamped as an explicit keyframe via insertKey.

The original frame is restored before the call returns.

Parameters:
  • start (int | None) – First frame to bake. None → play-range start.

  • end (int | None) – Last frame to bake. None → play-range end.

  • morph_names (list[str] | None) – Subset of morph names to bake. None → all morphs.

Returns:

{"frames_baked": int, "morphs_baked": int}

Return type:

dict

bake(start=None, end=None, bone_names=None, include_morphs=False, morph_names=None)[source]

Bake bone rotations and optionally morphs in a single HTTP call.

Combines bake_bone_rotations() and bake_morphs() into one server-side loop so the timeline is only scrubbed once.

Parameters:
  • start (int | None) – First frame to bake. None → play-range start.

  • end (int | None) – Last frame to bake. None → play-range end.

  • bone_names (list[str] | None) – Bones to bake. None → all bones.

  • include_morphs (bool) – Also bake DzMorph channels.

  • morph_names (list[str] | None) – Morphs to bake (only used when include_morphs is True). None → all morphs.

Returns:

{"frames_baked": int, "bones_baked": int, "morphs_baked": int}

Return type:

dict

follow_target()[source]

Return the IK follow-target skeleton, or None if not set.

DazBone

class dazpy.DazBone(client, identifier)[source]

Bases: DazNode

Proxy for a DzBone (a single joint within a DazSkeleton).

Extends DazNode with bone-specific rotation helpers.

property local_euler: tuple[float, float, float] | None

Local-space rotation as an (x, y, z) tuple of Euler angles in degrees.

Reads the same rotation controls written by set_local_rotation(), so the two are exact inverses.

Returns:

(x, y, z) in degrees, or None if the bone cannot be found.

property local_rotation: dict | None

Local-space rotation as {"x", "y", "z", "w"} quaternion (read-only).

set_local_rotation(x, y, z)[source]

Set the bone’s local rotation using Euler angles in degrees.

Parameters:
  • x (float) – Rotation around the local X axis.

  • y (float) – Rotation around the local Y axis.

  • z (float) – Rotation around the local Z axis.

property local_position: dict | None

Local-space position as {"x", "y", "z"} (read-only).

property rotation_order: str | None

Rotation order string (e.g. "XYZ"), or None.

get_skeleton()[source]

Return the parent DazSkeleton, or None.