From 01e8af3348fac2babe3b5218dbe4ecdaa0e1eace Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sat, 12 Nov 2022 23:54:17 +0200 Subject: Rigify: annotate and fix warnings in basic rig components. Introduce a method to annotate types and names of entries in the `bones` container of rig components and apply it, and other type annotations, to a number of not very complex rig classes. - Introduce BaseRigMixin as a typed base class for mixins intended for use in rig classes (using BaseRig as a parent causes issues). - Introduce TypedBoneDict that does not suppress the unknown attribute analysis in PyCharm, and use it in a system of subclasses to annotate the bones in various rigs. BaseBoneDict is necessary because the annotation affects all subclasses, so TypedBoneDict cannot inherit from BoneDict with the annotation. - Add or adjust other type annotations of rig methods and utilities. - Fix other warnings, e.g. undeclared attributes, excessively long lines, whitespace style issues and typos. --- rigify/rigs/basic/raw_copy.py | 88 +++++++++++++++++++++++-------------------- 1 file changed, 48 insertions(+), 40 deletions(-) (limited to 'rigify/rigs/basic/raw_copy.py') diff --git a/rigify/rigs/basic/raw_copy.py b/rigify/rigs/basic/raw_copy.py index 6a6153a3..f22f7533 100644 --- a/rigify/rigs/basic/raw_copy.py +++ b/rigify/rigs/basic/raw_copy.py @@ -2,15 +2,17 @@ import bpy -from ...utils.naming import strip_org, strip_prefix, choose_derived_bone, is_control_bone +from bpy.types import Constraint, ArmatureConstraint, UILayout + +from ...utils.naming import choose_derived_bone, is_control_bone from ...utils.mechanism import copy_custom_properties_with_ui, move_all_constraints from ...utils.widgets import layout_widget_dropdown, create_registered_widget -from ...base_rig import BaseRig -from ...base_generate import SubstitutionRig +from ...base_rig import BaseRig, BaseRigMixin from itertools import repeat + ''' Due to T80764, bone name handling for 'limbs.raw_copy' was hard-coded in generate.py @@ -25,18 +27,18 @@ class Rig(SubstitutionRig): return [ self.instantiate_rig(InstanceRig, new_name) ] ''' -class RelinkConstraintsMixin: + +class RelinkConstraintsMixin(BaseRigMixin): """ Utilities for constraint relinking. """ - def relink_bone_constraints(self, bone_name): + def relink_bone_constraints(self, bone_name: str): if self.params.relink_constraints: for con in self.get_bone(bone_name).constraints: self.relink_single_constraint(con) - relink_unmarked_constraints = False - def relink_single_constraint(self, con): + def relink_single_constraint(self, con: Constraint): if self.params.relink_constraints: parts = con.name.split('@') @@ -45,13 +47,11 @@ class RelinkConstraintsMixin: elif self.relink_unmarked_constraints: self.relink_constraint(con, ['']) - - def relink_move_constraints(self, from_bone, to_bone, *, prefix=''): + def relink_move_constraints(self, from_bone: str, to_bone: str, *, prefix=''): if self.params.relink_constraints: move_all_constraints(self.obj, from_bone, to_bone, prefix=prefix) - - def relink_bone_parent(self, bone_name): + def relink_bone_parent(self, bone_name: str): if self.params.relink_constraints: self.generator.disable_auto_parent(bone_name) @@ -62,13 +62,13 @@ class RelinkConstraintsMixin: self.set_bone_parent(bone_name, new_parent) return new_parent - - def relink_constraint(self, con, specs): - if con.type == 'ARMATURE': + def relink_constraint(self, con: Constraint, specs: list[str]): + if isinstance(con, ArmatureConstraint): if len(specs) == 1: specs = repeat(specs[0]) elif len(specs) != len(con.targets): - self.raise_error("Constraint {} actually has {} targets", con.name, len(con.targets)) + self.raise_error("Constraint {} actually has {} targets", + con.name, len(con.targets)) for tgt, spec in zip(con.targets, specs): if tgt.target == self.obj: @@ -76,44 +76,49 @@ class RelinkConstraintsMixin: elif hasattr(con, 'subtarget'): if len(specs) > 1: - self.raise_error("Only the Armature constraint can have multiple '@' targets: {}", con.name) + self.raise_error("Only the Armature constraint can have multiple '@' targets: {}", + con.name) + # noinspection PyUnresolvedReferences if con.target == self.obj: con.subtarget = self.find_relink_target(specs[0], con.subtarget) - - def find_relink_target(self, spec, old_target): + def find_relink_target(self, spec: str, old_target: str): if spec == '': return old_target elif spec in {'CTRL', 'DEF', 'MCH'}: result = choose_derived_bone(self.generator, old_target, spec.lower()) if not result: - result = choose_derived_bone(self.generator, old_target, spec.lower(), by_owner=False) + result = choose_derived_bone(self.generator, old_target, + spec.lower(), by_owner=False) if not result: - self.raise_error("Cannot find derived {} bone of bone '{}' for relinking", spec, old_target) + self.raise_error("Cannot find derived {} bone of bone '{}' for relinking", + spec, old_target) return result else: if spec not in self.obj.pose.bones: self.raise_error("Cannot find bone '{}' for relinking", spec) return spec - @classmethod - def add_relink_constraints_params(self, params): + def add_relink_constraints_params(cls, params): params.relink_constraints = bpy.props.BoolProperty( - name = "Relink Constraints", - default = False, - description = "For constraints with names formed like 'base@bonename', use the part after '@' as the new subtarget after all bones are created. Use '@CTRL', '@DEF' or '@MCH' to simply replace the prefix" + name="Relink Constraints", + default=False, + description="For constraints with names formed like 'base@bonename', use the part " + "after '@' as the new subtarget after all bones are created. Use '@CTRL', " + "'@DEF' or '@MCH' to simply replace the prefix" ) params.parent_bone = bpy.props.StringProperty( - name = "Parent", - default = "", - description = "Replace the parent with a different bone after all bones are created. Using simply CTRL, DEF or MCH will replace the prefix instead" + name="Parent", + default="", + description="Replace the parent with a different bone after all bones are created. " + "Using simply CTRL, DEF or MCH will replace the prefix instead" ) @classmethod - def add_relink_constraints_ui(self, layout, params): + def add_relink_constraints_ui(cls, layout: UILayout, params): r = layout.row() r.prop(params, "relink_constraints") @@ -125,7 +130,11 @@ class RelinkConstraintsMixin: class Rig(BaseRig, RelinkConstraintsMixin): - def find_org_bones(self, pose_bone): + bones: BaseRig.ToplevelBones[str, BaseRig.CtrlBones, BaseRig.MchBones, str] + + relink: bool + + def find_org_bones(self, pose_bone) -> str: return pose_bone.name def initialize(self): @@ -149,23 +158,22 @@ class Rig(BaseRig, RelinkConstraintsMixin): create_registered_widget(self.obj, org, widget) @classmethod - def add_parameters(self, params): - self.add_relink_constraints_params(params) + def add_parameters(cls, params): + cls.add_relink_constraints_params(params) params.optional_widget_type = bpy.props.StringProperty( - name = "Widget Type", - default = '', - description = "Choose the type of the widget to create" + name="Widget Type", + default='', + description="Choose the type of the widget to create" ) - @classmethod - def parameters_ui(self, layout, params): + def parameters_ui(cls, layout, params): col = layout.column() col.label(text='This rig type does not add the ORG prefix.') col.label(text='Manually add ORG, MCH or DEF as needed.') - self.add_relink_constraints_ui(layout, params) + cls.add_relink_constraints_ui(layout, params) pbone = bpy.context.active_pose_bone @@ -173,8 +181,8 @@ class Rig(BaseRig, RelinkConstraintsMixin): layout_widget_dropdown(layout, params, "optional_widget_type") -#add_parameters = InstanceRig.add_parameters -#parameters_ui = InstanceRig.parameters_ui +# add_parameters = InstanceRig.add_parameters +# parameters_ui = InstanceRig.parameters_ui def create_sample(obj): -- cgit v1.2.3