Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'rigify/base_generate.py')
-rw-r--r--rigify/base_generate.py150
1 files changed, 85 insertions, 65 deletions
diff --git a/rigify/base_generate.py b/rigify/base_generate.py
index 0765cc17..4894d931 100644
--- a/rigify/base_generate.py
+++ b/rigify/base_generate.py
@@ -5,19 +5,26 @@ import sys
import traceback
import collections
+from typing import Optional, TYPE_CHECKING, Collection, List
+from bpy.types import PoseBone, Bone
+
from .utils.errors import MetarigError, RaiseErrorMixin
from .utils.naming import random_id
from .utils.metaclass import SingletonPluginMetaclass
-from .utils.rig import list_bone_names_depth_first_sorted, get_rigify_type
-from .utils.misc import clone_parameters, assign_parameters
+from .utils.rig import list_bone_names_depth_first_sorted, get_rigify_type, get_rigify_params
+from .utils.misc import clone_parameters, assign_parameters, ArmatureObject
from . import base_rig
from itertools import count
-#=============================================
+if TYPE_CHECKING:
+ from .rig_ui_template import ScriptGenerator
+
+
+##############################################
# Generator Plugin
-#=============================================
+##############################################
class GeneratorPlugin(base_rig.GenerateCallbackHost, metaclass=SingletonPluginMetaclass):
@@ -39,68 +46,68 @@ class GeneratorPlugin(base_rig.GenerateCallbackHost, metaclass=SingletonPluginMe
priority = 0
- def __init__(self, generator):
+ def __init__(self, generator: 'BaseGenerator'):
self.generator = generator
self.obj = generator.obj
- def register_new_bone(self, new_name, old_name=None):
+ def register_new_bone(self, new_name: str, old_name: Optional[str] = None):
self.generator.bone_owners[new_name] = None
if old_name:
self.generator.derived_bones[old_name].add(new_name)
-#=============================================
+##############################################
# Rig Substitution Mechanism
-#=============================================
+##############################################
class SubstitutionRig(RaiseErrorMixin):
"""A proxy rig that replaces itself with one or more different rigs."""
- def __init__(self, generator, pose_bone):
+ def __init__(self, generator: 'BaseGenerator', pose_bone: PoseBone):
self.generator = generator
self.obj = generator.obj
self.base_bone = pose_bone.name
- self.params = pose_bone.rigify_parameters
+ self.params = get_rigify_params(pose_bone)
self.params_copy = clone_parameters(self.params)
def substitute(self):
# return [rig1, rig2...]
- raise NotImplementedException()
+ raise NotImplementedError
# Utility methods
- def register_new_bone(self, new_name, old_name=None):
+ def register_new_bone(self, new_name: str, old_name: Optional[str] = None):
pass
- def get_params(self, bone_name):
- return self.obj.pose.bones[bone_name].rigify_parameters
+ def get_params(self, bone_name: str):
+ return get_rigify_params(self.obj.pose.bones[bone_name])
- def assign_params(self, bone_name, param_dict=None, **params):
+ def assign_params(self, bone_name: str, param_dict=None, **params):
assign_parameters(self.get_params(bone_name), param_dict, **params)
- def instantiate_rig(self, rig_class, bone_name):
+ def instantiate_rig(self, rig_class: str | type, bone_name: str):
if isinstance(rig_class, str):
rig_class = self.generator.find_rig_class(rig_class)
return self.generator.instantiate_rig(rig_class, self.obj.pose.bones[bone_name])
-#=============================================
+##############################################
# Legacy Rig Wrapper
-#=============================================
+##############################################
class LegacyRig(base_rig.BaseRig):
"""Wrapper around legacy style rigs without a common base class"""
- def __init__(self, generator, pose_bone, wrapped_class):
+ def __init__(self, generator: 'BaseGenerator', pose_bone: PoseBone, wrapped_class: type):
self.wrapped_rig = None
self.wrapped_class = wrapped_class
super().__init__(generator, pose_bone)
- def find_org_bones(self, pose_bone):
+ def find_org_bones(self, pose_bone: PoseBone):
bone_name = pose_bone.name
if not self.wrapped_rig:
@@ -163,15 +170,41 @@ class LegacyRig(base_rig.BaseRig):
bpy.ops.object.mode_set(mode='OBJECT')
-#=============================================
+##############################################
# Base Generate Engine
-#=============================================
+##############################################
class BaseGenerator:
"""Base class for the main generator object. Contains rig and plugin management code."""
- instance = None
+ instance: Optional['BaseGenerator'] = None # static
+
+ context: bpy.types.Context
+ scene: bpy.types.Scene
+ view_layer: bpy.types.ViewLayer
+ layer_collection: bpy.types.LayerCollection
+ collection: bpy.types.Collection
+
+ metarig: ArmatureObject
+ obj: ArmatureObject
+
+ script: 'ScriptGenerator'
+
+ rig_list: List[base_rig.BaseRig]
+ root_rigs: List[base_rig.BaseRig]
+
+ bone_owners: dict[str, Optional[base_rig.BaseRig]]
+ derived_bones: dict[str, set[str]]
+
+ stage: Optional[str]
+ rig_id: str
+
+ widget_collection: bpy.types.Collection
+ use_mirror_widgets: bool
+ old_widget_table: dict[str, bpy.types.Object]
+ new_widget_table: dict[str, bpy.types.Object]
+ widget_mirror_mesh: dict[str, bpy.types.Mesh]
def __init__(self, context, metarig):
self.context = context
@@ -180,7 +213,6 @@ class BaseGenerator:
self.layer_collection = context.layer_collection
self.collection = self.layer_collection.collection
self.metarig = metarig
- self.obj = None
# List of all rig instances
self.rig_list = []
@@ -210,18 +242,16 @@ class BaseGenerator:
# Table of renamed ORG bones
self.org_rename_table = dict()
-
- def disable_auto_parent(self, bone_name):
+ def disable_auto_parent(self, bone_name: str):
"""Prevent automatically parenting the bone to root if parentless."""
self.noparent_bones.add(bone_name)
-
- def find_derived_bones(self, bone_name, *, by_owner=False, recursive=True):
+ def find_derived_bones(self, bone_name: str, *, by_owner=False, recursive=True) -> set[str]:
"""Find which bones were copied from the specified one."""
if by_owner:
owner = self.bone_owners.get(bone_name, None)
if not owner:
- return {}
+ return set()
table = owner.rigify_derived_bones
else:
@@ -231,7 +261,7 @@ class BaseGenerator:
result = set()
def rec(name):
- for child in table.get(name, {}):
+ for child in table.get(name, []):
result.add(child)
rec(child)
@@ -239,16 +269,15 @@ class BaseGenerator:
return result
else:
- return set(table.get(bone_name, {}))
+ return set(table.get(bone_name, []))
-
- def set_layer_group_priority(self, bone_name, layers, priority):
+ def set_layer_group_priority(self, bone_name: str,
+ layers: Collection[bool], priority: float):
for i, val in enumerate(layers):
if val:
self.layer_group_priorities[bone_name][i] = priority
-
- def rename_org_bone(self, old_name, new_name):
+ def rename_org_bone(self, old_name: str, new_name: str) -> str:
assert self.stage == 'instantiate'
assert old_name == self.org_rename_table.get(old_name, None)
assert old_name not in self.bone_owners
@@ -261,8 +290,8 @@ class BaseGenerator:
self.org_rename_table[old_name] = new_name
return new_name
-
- def __run_object_stage(self, method_name):
+ def __run_object_stage(self, method_name: str):
+ """Run a generation stage in Object mode."""
assert(self.context.active_object == self.obj)
assert(self.obj.mode == 'OBJECT')
num_bones = len(self.obj.data.bones)
@@ -287,8 +316,8 @@ class BaseGenerator:
assert(self.obj.mode == 'OBJECT')
assert(num_bones == len(self.obj.data.bones))
-
- def __run_edit_stage(self, method_name):
+ def __run_edit_stage(self, method_name: str):
+ """Run a generation stage in Edit mode."""
assert(self.context.active_object == self.obj)
assert(self.obj.mode == 'EDIT')
num_bones = len(self.obj.data.edit_bones)
@@ -313,15 +342,12 @@ class BaseGenerator:
assert(self.obj.mode == 'EDIT')
assert(num_bones == len(self.obj.data.edit_bones))
-
def invoke_initialize(self):
self.__run_object_stage('initialize')
-
def invoke_prepare_bones(self):
self.__run_edit_stage('prepare_bones')
-
def __auto_register_bones(self, bones, rig, plugin=None):
"""Find bones just added and not registered by this rig."""
for bone in bones:
@@ -332,10 +358,10 @@ class BaseGenerator:
rig.rigify_new_bones[name] = None
if not isinstance(rig, LegacyRig):
- print("WARNING: rig %s didn't register bone %s\n" % (self.describe_rig(rig), name))
+ print(f"WARNING: rig {self.describe_rig(rig)} "
+ f"didn't register bone {name}\n")
else:
- print("WARNING: plugin %s didn't register bone %s\n" % (plugin, name))
-
+ print(f"WARNING: plugin {plugin} didn't register bone {name}\n")
def invoke_generate_bones(self):
assert(self.context.active_object == self.obj)
@@ -363,36 +389,28 @@ class BaseGenerator:
self.__auto_register_bones(self.obj.data.edit_bones, None, plugin=self.plugin_list[i])
-
def invoke_parent_bones(self):
self.__run_edit_stage('parent_bones')
-
def invoke_configure_bones(self):
self.__run_object_stage('configure_bones')
-
def invoke_preapply_bones(self):
self.__run_object_stage('preapply_bones')
-
def invoke_apply_bones(self):
self.__run_edit_stage('apply_bones')
-
def invoke_rig_bones(self):
self.__run_object_stage('rig_bones')
-
def invoke_generate_widgets(self):
self.__run_object_stage('generate_widgets')
-
def invoke_finalize(self):
self.__run_object_stage('finalize')
-
- def instantiate_rig(self, rig_class, pose_bone):
+ def instantiate_rig(self, rig_class: type, pose_bone: PoseBone) -> base_rig.BaseRig:
assert not issubclass(rig_class, SubstitutionRig)
if issubclass(rig_class, base_rig.BaseRig):
@@ -400,12 +418,14 @@ class BaseGenerator:
else:
return LegacyRig(self, pose_bone, rig_class)
+ def find_rig_class(self, rig_type: str) -> type:
+ raise NotImplementedError
- def instantiate_rig_by_type(self, rig_type, pose_bone):
+ def instantiate_rig_by_type(self, rig_type: str, pose_bone: PoseBone):
return self.instantiate_rig(self.find_rig_class(rig_type), pose_bone)
-
- def describe_rig(self, rig):
+ # noinspection PyMethodMayBeStatic
+ def describe_rig(self, rig: base_rig.BaseRig) -> str:
base_bone = rig.base_bone
if isinstance(rig, LegacyRig):
@@ -413,7 +433,6 @@ class BaseGenerator:
return "%s (%s)" % (rig.__class__, base_bone)
-
def __create_rigs(self, bone_name, halt_on_missing):
"""Recursively walk bones and create rig instances."""
@@ -440,12 +459,14 @@ class BaseGenerator:
if org_name in self.bone_owners:
old_rig = self.describe_rig(self.bone_owners[org_name])
new_rig = self.describe_rig(rig)
- print("CONFLICT: bone %s is claimed by rigs %s and %s\n" % (org_name, old_rig, new_rig))
+ print(f"CONFLICT: bone {org_name} is claimed by rigs "
+ f"{old_rig} and {new_rig}\n")
self.bone_owners[org_name] = rig
except ImportError:
- message = "Rig Type Missing: python module for type '%s' not found (bone: %s)" % (rig_type, bone_name)
+ message = f"Rig Type Missing: python module for type '{rig_type}' "\
+ f"not found (bone: {bone_name})"
if halt_on_missing:
raise MetarigError(message)
else:
@@ -453,8 +474,8 @@ class BaseGenerator:
print('print_exc():')
traceback.print_exc(file=sys.stdout)
-
- def __build_rig_tree_rec(self, bone, current_rig, handled):
+ def __build_rig_tree_rec(self, bone: Bone, current_rig: Optional[base_rig.BaseRig],
+ handled: dict[base_rig.BaseRig, str]):
"""Recursively walk bones and connect rig instances into a tree."""
rig = self.bone_owners.get(bone.name)
@@ -474,8 +495,8 @@ class BaseGenerator:
handled[rig] = bone.name
elif rig.rigify_parent is not current_rig:
- raise MetarigError("CONFLICT: bone %s owned by rig %s has different parent rig from %s\n" %
- (bone.name, rig.base_bone, handled[rig]))
+ raise MetarigError("CONFLICT: bone {bone.name} owned by rig {rig.base_bone} "
+ f"has different parent rig from {handled[rig]}")
current_rig = rig
else:
@@ -487,7 +508,6 @@ class BaseGenerator:
for child in bone.children:
self.__build_rig_tree_rec(child, current_rig, handled)
-
def instantiate_rig_tree(self, halt_on_missing=False):
"""Create rig instances and connect them into a tree."""