diff options
Diffstat (limited to 'rigify/utils')
-rw-r--r-- | rigify/utils/animation.py | 29 | ||||
-rw-r--r-- | rigify/utils/bones.py | 46 | ||||
-rw-r--r-- | rigify/utils/layers.py | 9 | ||||
-rw-r--r-- | rigify/utils/rig.py | 2 |
4 files changed, 61 insertions, 25 deletions
diff --git a/rigify/utils/animation.py b/rigify/utils/animation.py index 21aa2a89..6e0a9739 100644 --- a/rigify/utils/animation.py +++ b/rigify/utils/animation.py @@ -7,11 +7,15 @@ import math # noinspection PyUnresolvedReferences from mathutils import Matrix, Vector -from typing import Callable, Any, Collection, Iterator +from typing import TYPE_CHECKING, Callable, Any, Collection, Iterator, Optional, Sequence from bpy.types import Action, bpy_struct, FCurve import json +if TYPE_CHECKING: + from ..rig_ui_template import PanelLayout + + rig_id = None @@ -849,7 +853,7 @@ class POSE_OT_rigify_clear_keyframes(bpy.types.Operator): # noinspection PyDefaultArgument,PyUnusedLocal -def add_clear_keyframes_button(panel, *, bones=[], label='', text=''): +def add_clear_keyframes_button(panel: 'PanelLayout', *, bones: list[str] = [], label='', text=''): panel.use_bake_settings() panel.script.add_utilities(SCRIPT_UTILITIES_OP_CLEAR_KEYS) panel.script.register_classes(SCRIPT_REGISTER_OP_CLEAR_KEYS) @@ -921,8 +925,10 @@ class POSE_OT_rigify_generic_snap_bake(RigifyGenericSnapBase, RigifyBakeKeyframe '''] -def add_fk_ik_snap_buttons(panel, op_single, op_bake, *, label=None, rig_name='', properties=None, - clear_bones=None, compact=None): +def add_fk_ik_snap_buttons(panel: 'PanelLayout', op_single: str, op_bake: str, *, + label, rig_name='', properties: dict[str, Any], + clear_bones: Optional[list[str]] = None, + compact: Optional[bool] = None): assert label and properties if rig_name: @@ -944,8 +950,12 @@ def add_fk_ik_snap_buttons(panel, op_single, op_bake, *, label=None, rig_name='' # noinspection PyDefaultArgument -def add_generic_snap(panel, *, output_bones=[], input_bones=[], input_ctrl_bones=[], label='Snap', - rig_name='', undo_copy_scale=False, compact=None, clear=True, locks=None, tooltip=None): +def add_generic_snap(panel: 'PanelLayout', *, + output_bones: list[str] = [], input_bones: list[str] = [], + input_ctrl_bones: list[str] = [], label='Snap', + rig_name='', undo_copy_scale=False, compact: Optional[bool] = None, + clear=True, locks: Optional[Sequence[bool]] = None, + tooltip: Optional[str] = None): panel.use_bake_settings() panel.script.add_utilities(SCRIPT_UTILITIES_OP_SNAP) panel.script.register_classes(SCRIPT_REGISTER_OP_SNAP) @@ -972,8 +982,11 @@ def add_generic_snap(panel, *, output_bones=[], input_bones=[], input_ctrl_bones # noinspection PyDefaultArgument -def add_generic_snap_fk_to_ik(panel, *, fk_bones=[], ik_bones=[], ik_ctrl_bones=[], label='FK->IK', - rig_name='', undo_copy_scale=False, compact=None, clear=True): +def add_generic_snap_fk_to_ik(panel: 'PanelLayout', *, + fk_bones: list[str] = [], ik_bones: list[str] = [], + ik_ctrl_bones: list[str] = [], label='FK->IK', + rig_name='', undo_copy_scale=False, + compact: Optional[bool] = None, clear=True): add_generic_snap( panel, output_bones=fk_bones, input_bones=ik_bones, input_ctrl_bones=ik_ctrl_bones, label=label, rig_name=rig_name, undo_copy_scale=undo_copy_scale, compact=compact, clear=clear diff --git a/rigify/utils/bones.py b/rigify/utils/bones.py index 8419eb90..8c39e57b 100644 --- a/rigify/utils/bones.py +++ b/rigify/utils/bones.py @@ -4,7 +4,7 @@ import bpy import math from mathutils import Vector, Matrix -from typing import Optional, Callable +from typing import Optional, Callable, Iterable from .errors import MetarigError from .naming import get_name, make_derived_name, is_control_bone @@ -15,26 +15,24 @@ from .misc import pairwise, ArmatureObject # Bone collection ######################## -class BoneDict(dict): +class BaseBoneDict(dict): """ Special dictionary for holding bone names in a structured way. Allows access to contained items as attributes, and only accepts certain types of values. - - @DynamicAttrs """ @staticmethod def __sanitize_attr(key, value): - if hasattr(BoneDict, key): + if hasattr(BaseBoneDict, key): raise KeyError(f"Invalid BoneDict key: {key}") - if value is None or isinstance(value, (str, list, BoneDict)): + if value is None or isinstance(value, (str, list, BaseBoneDict)): return value if isinstance(value, dict): - return BoneDict(value) + return BaseBoneDict(value) raise ValueError(f"Invalid BoneDict value: {repr(value)}") @@ -42,7 +40,7 @@ class BoneDict(dict): super().__init__() for key, value in dict(*args, **kwargs).items(): - dict.__setitem__(self, key, BoneDict.__sanitize_attr(key, value)) + dict.__setitem__(self, key, BaseBoneDict.__sanitize_attr(key, value)) self.__dict__ = self @@ -50,13 +48,13 @@ class BoneDict(dict): return "BoneDict(%s)" % (dict.__repr__(self)) def __setitem__(self, key, value): - dict.__setitem__(self, key, BoneDict.__sanitize_attr(key, value)) + dict.__setitem__(self, key, BaseBoneDict.__sanitize_attr(key, value)) def update(self, *args, **kwargs): for key, value in dict(*args, **kwargs).items(): - dict.__setitem__(self, key, BoneDict.__sanitize_attr(key, value)) + dict.__setitem__(self, key, BaseBoneDict.__sanitize_attr(key, value)) - def flatten(self, key=None): + def flatten(self, key: Optional[str] = None): """Return all contained bones or a single key as a list.""" items = [self[key]] if key is not None else self.values() @@ -64,7 +62,7 @@ class BoneDict(dict): all_bones = [] for item in items: - if isinstance(item, BoneDict): + if isinstance(item, BaseBoneDict): all_bones.extend(item.flatten()) elif isinstance(item, list): all_bones.extend(item) @@ -74,6 +72,22 @@ class BoneDict(dict): return all_bones +class TypedBoneDict(BaseBoneDict): + # Omit DynamicAttrs to ensure usages of undeclared attributes are highlighted + pass + + +class BoneDict(BaseBoneDict): + """ + Special dictionary for holding bone names in a structured way. + + Allows access to contained items as attributes, and only + accepts certain types of values. + + @DynamicAttrs + """ + + ######################## # Bone manipulation ######################## @@ -220,7 +234,7 @@ def flip_bone(obj: ArmatureObject, bone_name: str): raise MetarigError("Cannot flip bones outside of edit mode") -def flip_bone_chain(obj: ArmatureObject, bone_names: list[str]): +def flip_bone_chain(obj: ArmatureObject, bone_names: Iterable[str]): """Flips a connected bone chain.""" assert obj.mode == 'EDIT' @@ -282,7 +296,7 @@ def put_bone(obj: ArmatureObject, bone_name: str, pos: Optional[Vector], *, raise MetarigError("Cannot 'put' bones outside of edit mode") -def disable_bbones(obj: ArmatureObject, bone_names: list[str]): +def disable_bbones(obj: ArmatureObject, bone_names: Iterable[str]): """Disables B-Bone segments on the specified bones.""" assert(obj.mode != 'EDIT') for bone in bone_names: @@ -440,7 +454,7 @@ class BoneUtilityMixin(object): bone.inherit_scale = inherit_scale bone.parent = (eb[parent_name] if parent_name else None) - def parent_bone_chain(self, bone_names: list[str], + def parent_bone_chain(self, bone_names: Iterable[str], use_connect: Optional[bool] = None, inherit_scale: Optional[str] = None): """Link bones into a chain with parenting. First bone may be None.""" @@ -453,7 +467,7 @@ class BoneUtilityMixin(object): # B-Bones ############################################## -def connect_bbone_chain_handles(obj: ArmatureObject, bone_names: list[str]): +def connect_bbone_chain_handles(obj: ArmatureObject, bone_names: Iterable[str]): assert obj.mode == 'EDIT' for prev_name, next_name in pairwise(bone_names): diff --git a/rigify/utils/layers.py b/rigify/utils/layers.py index d1f56e90..cb013ee1 100644 --- a/rigify/utils/layers.py +++ b/rigify/utils/layers.py @@ -151,6 +151,15 @@ class ControlLayersOption: layout_layer_buttons(box, params, self.layers_option, active_layers) + # Declarations for auto-completion + FK: 'ControlLayersOption' + TWEAK: 'ControlLayersOption' + EXTRA_IK: 'ControlLayersOption' + FACE_PRIMARY: 'ControlLayersOption' + FACE_SECONDARY: 'ControlLayersOption' + SKIN_PRIMARY: 'ControlLayersOption' + SKIN_SECONDARY: 'ControlLayersOption' + ControlLayersOption.FK = ControlLayersOption( 'fk', description="Layers for the FK controls to be on") diff --git a/rigify/utils/rig.py b/rigify/utils/rig.py index d8f88430..7fb399a3 100644 --- a/rigify/utils/rig.py +++ b/rigify/utils/rig.py @@ -6,7 +6,7 @@ import importlib.util import re from itertools import count -from typing import TYPE_CHECKING, Any, Optional, Sequence, Mapping +from typing import TYPE_CHECKING, Any, Optional, Sequence from bpy.types import bpy_struct, Constraint, Object, PoseBone, Bone, Armature # noinspection PyUnresolvedReferences |