[Bf-extensions-cvs] [ad222633] master: Rigify: annotate and fix warnings in skin rigs.
Alexander Gavrilov
noreply at git.blender.org
Mon Nov 21 00:24:22 CET 2022
Commit: ad22263327d99f828772922daaa00505f528df0a
Author: Alexander Gavrilov
Date: Wed Nov 16 19:29:03 2022 +0200
Branches: master
https://developer.blender.org/rBAad22263327d99f828772922daaa00505f528df0a
Rigify: annotate and fix warnings in skin rigs.
- Extract an even more bare version of ControlBoneParentBase that can
act as a common superclass of no-op parent builders like Org.
- Introduce ControlBoneParentBase.replace_nested for proper polymorphism.
- Introduce BaseSkinNode.control_node to fix armature parent builder.
- Annotate types and fix warnings in all skin and new face rigs.
This should cause no behavior changes. Now rigify/rigs/ is warning free.
===================================================================
M rigify/rigs/face/basic_tongue.py
M rigify/rigs/face/skin_eye.py
M rigify/rigs/face/skin_jaw.py
M rigify/rigs/skin/anchor.py
M rigify/rigs/skin/basic_chain.py
M rigify/rigs/skin/glue.py
M rigify/rigs/skin/skin_nodes.py
M rigify/rigs/skin/skin_parents.py
M rigify/rigs/skin/skin_rigs.py
M rigify/rigs/skin/stretchy_chain.py
M rigify/rigs/skin/transform/basic.py
M rigify/utils/misc.py
M rigify/utils/node_merger.py
===================================================================
diff --git a/rigify/rigs/face/basic_tongue.py b/rigify/rigs/face/basic_tongue.py
index 62a31022..3acfc624 100644
--- a/rigify/rigs/face/basic_tongue.py
+++ b/rigify/rigs/face/basic_tongue.py
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-or-later
import bpy
-import math
from itertools import count
@@ -17,7 +16,7 @@ from ..widgets import create_jaw_widget
class Rig(TweakChainRig):
- """Basic tongue from the original PitchiPoy face rig."""
+ """Basic tongue from the original PitchiPoy face rig.""" # noqa
min_chain_length = 3
@@ -28,15 +27,19 @@ class Rig(TweakChainRig):
####################################################
# BONES
- #
- # ctrl:
- # master:
- # Master control.
- # mch:
- # follow[]:
- # Partial follow master bones.
- #
- ####################################################
+
+ class CtrlBones(TweakChainRig.CtrlBones):
+ master: str # Master control.
+
+ class MchBones(TweakChainRig.MchBones):
+ follow: list[str] # Partial follow master bones.
+
+ bones: TweakChainRig.ToplevelBones[
+ list[str],
+ 'Rig.CtrlBones',
+ 'Rig.MchBones',
+ list[str]
+ ]
####################################################
# Control chain
@@ -71,7 +74,7 @@ class Rig(TweakChainRig):
def make_follow_chain(self):
self.bones.mch.follow = map_list(self.make_mch_follow_bone, count(1), self.bones.org[1:])
- def make_mch_follow_bone(self, i, org):
+ def make_mch_follow_bone(self, _i: int, org: str):
name = self.copy_bone(org, make_derived_name(org, 'mch'))
copy_bone_position(self.obj, self.base_bone, name)
flip_bone(self.obj, name)
@@ -104,7 +107,7 @@ class Rig(TweakChainRig):
# SETTINGS
@classmethod
- def add_parameters(self, params):
+ def add_parameters(cls, params):
params.bbones = bpy.props.IntProperty(
name='B-Bone Segments',
default=10,
@@ -115,7 +118,7 @@ class Rig(TweakChainRig):
ControlLayersOption.SKIN_PRIMARY.add_parameters(params)
@classmethod
- def parameters_ui(self, layout, params):
+ def parameters_ui(cls, layout, params):
layout.prop(params, 'bbones')
ControlLayersOption.SKIN_PRIMARY.parameters_ui(layout, params)
diff --git a/rigify/rigs/face/skin_eye.py b/rigify/rigs/face/skin_eye.py
index 154b555c..b02fc9f0 100644
--- a/rigify/rigs/face/skin_eye.py
+++ b/rigify/rigs/face/skin_eye.py
@@ -2,24 +2,26 @@
import bpy
import math
-import functools
import mathutils
-from itertools import count
+from typing import Optional
+
+from bpy.types import PoseBone
from mathutils import Vector, Matrix
+from ...rig_ui_template import PanelLayout
from ...utils.naming import make_derived_name, mirror_name, change_name_side, Side, SideZ
-from ...utils.bones import align_bone_z_axis, put_bone
+from ...utils.bones import align_bone_z_axis, put_bone, TypedBoneDict
from ...utils.widgets import (widget_generator, generate_circle_geometry,
generate_circle_hull_geometry)
from ...utils.widgets_basic import create_circle_widget
from ...utils.switch_parent import SwitchParentBuilder
-from ...utils.misc import map_list, matrix_from_axis_pair, LazyRef
+from ...utils.misc import matrix_from_axis_pair, LazyRef
from ...base_rig import stage, RigComponent
-from ..skin.skin_nodes import ControlBoneNode
-from ..skin.skin_parents import ControlBoneParentOffset
+from ..skin.skin_nodes import ControlBoneNode, BaseSkinNode
+from ..skin.skin_parents import ControlBoneParentOffset, ControlBoneParentBase
from ..skin.skin_rigs import BaseSkinRig
from ..skin.basic_chain import Rig as BasicChainRig
@@ -31,11 +33,20 @@ class Rig(BaseSkinRig):
connect at their ends using T/B symmetry.
"""
- def find_org_bones(self, bone):
+ def find_org_bones(self, bone: PoseBone) -> str:
return bone.name
cluster_control = None
+ center: Vector
+ axis: Vector
+
+ eye_corner_nodes: list[ControlBoneNode]
+ eye_corner_matrix: Optional[Matrix]
+ eye_corner_range: tuple[float, float]
+
+ child_chains: list[BasicChainRig]
+
def initialize(self):
super().initialize()
@@ -58,10 +69,11 @@ class Rig(BaseSkinRig):
####################################################
# UTILITIES
- def is_eye_control_node(self, node):
+ def is_eye_control_node(self, node: ControlBoneNode) -> bool:
return node.rig in self.child_chains and node.is_master_node
- def is_eye_corner_node(self, node):
+ # noinspection PyMethodMayBeStatic
+ def is_eye_corner_node(self, node: ControlBoneNode) -> bool:
# Corners are nodes where the two T and B chains merge
sides = set(n.name_split.side_z for n in node.get_merged_siblings())
return {SideZ.BOTTOM, SideZ.TOP}.issubset(sides)
@@ -82,67 +94,68 @@ class Rig(BaseSkinRig):
self.eye_corner_matrix = matrix.inverted()
# Compute signed angles from space_axis to the eye corners
- amin, amax = self.eye_corner_range = list(
- sorted(map(self.get_eye_corner_angle, self.eye_corner_nodes)))
+ angle_min, angle_max = sorted(map(self.get_eye_corner_angle, self.eye_corner_nodes))
+
+ self.eye_corner_range = (angle_min, angle_max)
- if not (amin <= 0 <= amax):
+ if not (angle_min <= 0 <= angle_max):
self.raise_error('Bad relative angles of eye corners: {}..{}',
- math.degrees(amin), math.degrees(amax))
+ math.degrees(angle_min), math.degrees(angle_max))
- def get_eye_corner_angle(self, node):
+ def get_eye_corner_angle(self, node: ControlBoneNode) -> float:
"""Compute a signed Z rotation angle from the eye axis to the node."""
pt = self.eye_corner_matrix @ node.point
return math.atan2(pt.x, pt.y)
- def get_master_control_position(self):
+ def get_master_control_position(self) -> Vector:
"""Compute suitable position for the master control."""
self.init_eye_corner_space()
# Place the control between the two corners on the eye axis
- pcorners = [node.point for node in self.eye_corner_nodes]
+ corner_points = [node.point for node in self.eye_corner_nodes]
point, _ = mathutils.geometry.intersect_line_line(
- self.center, self.center + self.axis, pcorners[0], pcorners[1]
+ self.center, self.center + self.axis, corner_points[0], corner_points[1]
)
return point
- def get_lid_follow_influence(self, node):
+ def get_lid_follow_influence(self, node: ControlBoneNode):
"""Compute the influence factor of the eye movement on this eyelid control node."""
self.init_eye_corner_space()
# Interpolate from axis to corners based on Z angle
angle = self.get_eye_corner_angle(node)
- amin, amax = self.eye_corner_range
+ angle_min, angle_max = self.eye_corner_range
- if amin < angle < 0:
- return 1 - min(1, angle/amin) ** 2
- elif 0 < angle < amax:
- return 1 - min(1, angle/amax) ** 2
+ if angle_min < angle < 0:
+ return 1 - min(1.0, angle/angle_min) ** 2
+ elif 0 < angle < angle_max:
+ return 1 - min(1.0, angle/angle_max) ** 2
else:
return 0
####################################################
# BONES
- #
- # ctrl:
- # master:
- # Parent control for moving the whole eye.
- # target:
- # Individual target this eye aims for.
- # mch:
- # master:
- # Bone that rotates to track ctrl.target.
- # track:
- # Bone that translates to follow mch.master tail.
- # deform:
- # master:
- # Deform mirror of ctrl.master.
- # eye:
- # Deform bone that rotates with mch.master.
- # iris:
- # Iris deform bone at master tail that scales with ctrl.target
- #
- ####################################################
+
+ class CtrlBones(BaseSkinRig.CtrlBones):
+ master: str # Parent control for moving the whole eye.
+ target: str # Individual target this eye aims for.
+
+ class MchBones(BaseSkinRig.MchBones):
+ master: str # Bone that rotates to track ctrl.target.
+ track: str # Bone that translates to follow mch.master tail.
+
+ class DeformBones(TypedBoneDict):
+ master: str # Deform mirror of ctrl.master.
+ eye: str # Deform bone that rotates with mch.master.
+ iris: str # Iris deform bone at master tail that scales with ctrl.target
+
+ bones: BaseSkinRig.ToplevelBones[
+ str,
+ 'Rig.CtrlBones',
+ 'Rig.MchBones',
+ 'Rig.DeformBones'
+ ]
####################################################
# CHILD CHAINS
@@ -154,13 +167,16 @@ class Rig(BaseSkinRig):
for child in self.child_chains:
self.patch_chain(child)
- def patch_chain(self, child):
+ def patch_chain(self, child: BasicChainRig):
return EyelidChainPatch(child, self)
####################################################
# CONTROL NODES
- def extend_control_node_parent(self, parent, node):
+ def extend_control_node_parent(self, parent, node: BaseSkinNode):
+ if not isinstance(node, ControlBoneNode):
+ return parent
+
if self.is_eye_control_node(node):
if self.is_eye_corner_node(node):
# Remember corners for later computations
@@ -172,7 +188,7 @@ class Rig(BaseSkinRig):
return parent
- def extend_mid_node_parent(self, parent, node):
+ def extend_mid_node_parent(self, parent: ControlBoneParentBase, node: ControlBoneNode):
parent = ControlBoneParentOffset(self, node, parent)
# Add movement of the eye to the eyelid controls
@@ -183,6 +199,7 @@ class Rig(BaseSkinRig):
# If Limit Distance
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-extensions-cvs
mailing list