Animation

class dazpy.DazAnimation(figure, frame_range, bones, frames)[source]

Bases: object

A captured animation clip: bone rotations (and optionally morphs) for every frame in the play range.

Created with capture(); saved/loaded with save() / load().

Bones are stored as a parallel-list encoding — a single ordered bones list of names, and per-frame rotations arrays aligned to that index — so payload size grows with bones × frames rather than with a full dict per frame.

Typical workflow:

from dazpy import DazScene, DazAnimation

scene  = DazScene()
figure = scene.find_skeleton_by_label("Genesis 9")

anim = DazAnimation.capture(figure, include_morphs=True)
anim.save("walk.json")

JSON schema (same as the animation_frame_dump.py output):

{
  "figure": "Genesis 9",
  "frame_range": {"start": 0, "end": 90},
  "bones": ["hip", "rForeArm", ...],
  "frames": [
    {"frame": 0, "rotations": [[x,y,z], ...], "morphs": {"PHMSmile": 0.5}},
    ...
  ]
}
Parameters:
  • figure (str) – The label of the figure.

  • frame_range (dict) – {"start": int, "end": int} in frames.

  • bones (list[str]) – Ordered list of bone names matching rotations columns.

  • frames (list[dict]) – Per-frame data; each entry has "frame", "rotations", and "morphs" keys.

classmethod capture(skeleton, include_morphs=False)[source]

Capture the full animation of skeleton in a single HTTP call.

Scrubs every frame in the scene’s play range server-side (no Python round-trip per frame). The timeline is restored to its original frame before the call returns.

When include_morphs is True, the script first identifies which geometry morphs and node-level properties actually vary across the timeline (channels that are keyed but static are excluded), then records their values per frame.

Parameters:
  • skeleton (DazSkeleton) – The figure to capture.

  • include_morphs (bool) – Also capture animated morph and property channels.

Returns:

A new DazAnimation.

Raises:

NodeNotFoundError – If the skeleton is not found.

Return type:

DazAnimation

classmethod load(path)[source]

Load an animation from a JSON file.

Accepts files produced by save() and by the original animation_frame_dump.py example script.

Parameters:

path (str | Path) – Path to the JSON file.

Returns:

A new DazAnimation.

Return type:

DazAnimation

save(path)[source]

Write this animation to a JSON file.

Parameters:

path (str | Path) – Destination path. Parent directories must exist.

to_dict()[source]

Return the animation as a plain dict (same schema as the JSON file).

clip(start, end)[source]

Return a new animation containing only frames in [start, end].

start and end are scene frame numbers (the "frame" value stored in each frame, not Python list indices). Both endpoints are inclusive.

Parameters:
  • start (int) – First scene frame to include.

  • end (int) – Last scene frame to include.

Returns:

A new DazAnimation with the same bones but a subset of frames.

Return type:

DazAnimation

blend(other, t)[source]

Blend this animation with other frame by frame.

Each frame’s bone rotations and morph values are linearly interpolated between self (t=0) and other (t=1). This is a pure-Python operation — no HTTP round-trip.

If the two clips have different frame counts, the result is truncated to the shorter clip. Frame numbers are taken from self.

Parameters:
  • other (DazAnimation) – The target animation.

  • t (float) – Blend factor — 0.0 = self, 1.0 = other.

Returns:

A new DazAnimation at the interpolated position.

Raises:

ValueError – If self and other have different bone lists.

Return type:

DazAnimation

as_pose(frame_index=0)[source]

Extract a single frame as a DazPose.

Bone rotations are stored sparsely — only bones with at least one non-zero component are included. Morph values are copied as-is.

This is a pure-Python operation — no HTTP round-trip.

Parameters:

frame_index (int) – 0-based index into frames.

Returns:

A new DazPose.

Return type:

DazPose

apply(skeleton, frame_index=0)[source]

Apply a single frame of this animation to skeleton.

Equivalent to anim.as_pose(frame_index).apply(skeleton) — one HTTP call that sets only the channels present in the frame.

Parameters:
  • skeleton (DazSkeleton) – The figure to pose.

  • frame_index (int) – 0-based index into frames. Defaults to 0.

append(other)[source]

Concatenate other immediately after this animation.

The other clip’s frame numbers are shifted so it starts on the frame following this animation’s last frame. The figure label and bone list are taken from self.

This is a pure-Python operation — no HTTP round-trip.

Parameters:

other (DazAnimation) – The animation to append.

Returns:

A new DazAnimation containing all frames from both clips.

Raises:

ValueError – If self and other have different bone lists.

Return type:

DazAnimation

property frame_count: int

Number of captured frames.

property bone_count: int

Number of bones in the skeleton at capture time.