Animation
- class dazpy.DazAnimation(figure, frame_range, bones, frames)[source]
Bases:
objectA captured animation clip: bone rotations (and optionally morphs) for every frame in the play range.
Created with
capture(); saved/loaded withsave()/load().Bones are stored as a parallel-list encoding — a single ordered
boneslist of names, and per-framerotationsarrays 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.pyoutput):{ "figure": "Genesis 9", "frame_range": {"start": 0, "end": 90}, "bones": ["hip", "rForeArm", ...], "frames": [ {"frame": 0, "rotations": [[x,y,z], ...], "morphs": {"PHMSmile": 0.5}}, ... ] }
- Parameters:
- 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:
- classmethod load(path)[source]
Load an animation from a JSON file.
Accepts files produced by
save()and by the originalanimation_frame_dump.pyexample script.- Parameters:
- Returns:
A new
DazAnimation.- Return type:
- 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:
- Returns:
A new
DazAnimationwith the same bones but a subset of frames.- Return type:
- 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
DazAnimationat the interpolated position.- Raises:
ValueError – If self and other have different bone lists.
- Return type:
- 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.
- 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
DazAnimationcontaining all frames from both clips.- Raises:
ValueError – If self and other have different bone lists.
- Return type: