Source code for dazpy._bone

from __future__ import annotations

from ._element import DazElement
from ._node import DazNode, NodeIdentifier
from ._script_builder import ScriptBuilder


[docs] class DazBone(DazNode): """Proxy for a ``DzBone`` (a single joint within a :class:`~dazpy.DazSkeleton`). Extends :class:`~dazpy.DazNode` with bone-specific rotation helpers. """ @classmethod def _from_locator(cls, client: "DazClient", locator: str, name: str) -> "DazBone": # noqa: F821 """Construct a DazBone from a pre-built skeleton-relative locator.""" bone = object.__new__(cls) DazElement.__init__(bone, client, locator) object.__setattr__(bone, "_identifier", NodeIdentifier(name)) return bone def _nb(self, body: str) -> str: return ScriptBuilder.node_body_from_locator(self._locator, body) @property def local_euler(self) -> 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 :meth:`set_local_rotation`, so the two are exact inverses. Returns: ``(x, y, z)`` in degrees, or ``None`` if the bone cannot be found. """ result = self._client.execute(self._nb( "return [_node.getXRotControl().getValue(), " "_node.getYRotControl().getValue(), " "_node.getZRotControl().getValue()];" )).value if result is None: return None return (result[0], result[1], result[2]) @property def local_rotation(self) -> dict | None: """Local-space rotation as ``{"x", "y", "z", "w"}`` quaternion (read-only).""" return self._client.execute(self._nb( "var r = _node.getLocalRot(); return {x: r.x, y: r.y, z: r.z, w: r.w};" )).value
[docs] def set_local_rotation(self, x: float, y: float, z: float) -> None: """Set the bone's local rotation using Euler angles in degrees. Args: x: Rotation around the local X axis. y: Rotation around the local Y axis. z: Rotation around the local Z axis. """ self._client.execute(self._nb( f"_node.getXRotControl().setValue({float(x)}); " f"_node.getYRotControl().setValue({float(y)}); " f"_node.getZRotControl().setValue({float(z)});" ))
@property def local_position(self) -> dict | None: """Local-space position as ``{"x", "y", "z"}`` (read-only).""" return self._client.execute(self._nb( "var p = _node.getLocalPos(); return {x: p.x, y: p.y, z: p.z};" )).value @property def rotation_order(self) -> str | None: """Rotation order string (e.g. ``"XYZ"``), or ``None``.""" return self._client.execute(self._nb( "return _node.getRotationOrder();" )).value
[docs] def get_skeleton(self) -> "DazSkeleton | None": # noqa: F821 """Return the parent :class:`~dazpy.DazSkeleton`, or ``None``.""" from ._skeleton import DazSkeleton name = self._client.execute(self._nb( "var s = _node.getSkeleton(); return s ? s.getName() : null;" )).value if name is None: return None return DazSkeleton(self._client, NodeIdentifier(name))