diff options
author | Alexander Gavrilov <angavrilov@gmail.com> | 2019-03-30 22:00:55 +0300 |
---|---|---|
committer | Alexander Gavrilov <angavrilov@gmail.com> | 2019-09-14 09:29:26 +0300 |
commit | 3423174b37a0784dc12035ff3f2fb536835099e1 (patch) | |
tree | 3a54580902cdebdef5ebacd6099e86cc79ba75b3 /rigify/rigs/basic/copy_chain.py | |
parent | 12af8a28c14b608e9b9b08568d981273c86590c1 (diff) |
Rigify: redesign generate.py and introduce a base rig class.
The main goals are to provide an official way for rigs to
interact in a structured way, and to remove mode switching
within rigs.
This involves introducing a base class for rigs that holds
rig-to-rig and rig-to-bone references, converting the main
generator into a class and passing it to rigs, and splitting
the single generate method into multiple passes.
For backward compatibility, old rigs are automatically handled
via a wrapper that translates between old and new API.
In addition, a way to create objects that receive the generate
callbacks that aren't rigs is introduced via the GeneratorPlugin
class. The UI script generation code is converted into a plugin.
Making generic rig 'template' classes that are intended to be
subclassed in specific rigs involves splitting operations done
in each stage into multiple methods that can be overridden
separately. The main callback thus ends up simply calling a
sequence of other methods.
To make such code cleaner it's better to allow registering
those methods as new callbacks that would be automatically
called by the system. This can be done via decorators.
A new metaclass used for all rig and generate plugin classes
builds and validates a table of all decorated methods, and
allows calling them all together with the main callback.
A new way to switch parents for IK bones based on the new
features is introduced, and used in the existing limb rigs.
Reviewers: icappiello campbellbarton
Differential Revision: https://developer.blender.org/D4624
Diffstat (limited to 'rigify/rigs/basic/copy_chain.py')
-rw-r--r-- | rigify/rigs/basic/copy_chain.py | 176 |
1 files changed, 74 insertions, 102 deletions
diff --git a/rigify/rigs/basic/copy_chain.py b/rigify/rigs/basic/copy_chain.py index 4e426284..5145d735 100644 --- a/rigify/rigs/basic/copy_chain.py +++ b/rigify/rigs/basic/copy_chain.py @@ -20,124 +20,96 @@ import bpy -from ...utils import MetarigError -from ...utils import copy_bone -from ...utils import connected_children_names -from ...utils import strip_org, make_deformer_name -from ...utils import create_bone_widget +from ..chain_rigs import SimpleChainRig +from ...utils.errors import MetarigError +from ...utils.rig import connected_children_names +from ...utils.naming import strip_org, make_deformer_name +from ...utils.widgets_basic import create_bone_widget -class Rig: +from ...base_rig import BaseRig, stage + + +class Rig(SimpleChainRig): """ A "copy_chain" rig. All it does is duplicate the original bone chain and constrain it. This is a control and deformation rig. - """ - def __init__(self, obj, bone_name, params): + def initialize(self): + super().initialize() + """ Gather and validate data about the rig. """ - self.obj = obj - self.org_bones = [bone_name] + connected_children_names(obj, bone_name) - self.params = params - self.make_controls = params.make_controls - self.make_deforms = params.make_deforms + self.make_controls = self.params.make_controls + self.make_deforms = self.params.make_deforms - if len(self.org_bones) <= 1: - raise MetarigError("RIGIFY ERROR: Bone '%s': input to rig type must be a chain of 2 or more bones" % (strip_org(bone_name))) + ############################## + # Control chain - def generate(self): - """ Generate the rig. - Do NOT modify any of the original bones, except for adding constraints. - The main armature should be selected and active before this is called. + @stage.generate_bones + def make_control_chain(self): + if self.make_controls: + super().make_control_chain() - """ - bpy.ops.object.mode_set(mode='EDIT') - - # Create the deformation and control bone chains. - # Just copies of the original chain. - def_chain = [] - ctrl_chain = [] - for i in range(len(self.org_bones)): - name = self.org_bones[i] - - # Control bone - if self.make_controls: - # Copy - ctrl_bone = copy_bone(self.obj, name) - eb = self.obj.data.edit_bones - ctrl_bone_e = eb[ctrl_bone] - # Name - ctrl_bone_e.name = strip_org(name) - # Parenting - if i == 0: - # First bone - ctrl_bone_e.parent = eb[self.org_bones[0]].parent - else: - # The rest - ctrl_bone_e.parent = eb[ctrl_chain[-1]] - # Add to list - ctrl_chain += [ctrl_bone_e.name] - else: - ctrl_chain += [None] - - # Deformation bone - if self.make_deforms: - # Copy - def_bone = copy_bone(self.obj, name) - eb = self.obj.data.edit_bones - def_bone_e = eb[def_bone] - # Name - def_bone_e.name = make_deformer_name(strip_org(name)) - # Parenting - if i == 0: - # First bone - def_bone_e.parent = eb[self.org_bones[0]].parent - else: - # The rest - def_bone_e.parent = eb[def_chain[-1]] - # Add to list - def_chain += [def_bone_e.name] - else: - def_chain += [None] - - bpy.ops.object.mode_set(mode='OBJECT') - pb = self.obj.pose.bones - - # Constraints for org and def - for org, ctrl, defrm in zip(self.org_bones, ctrl_chain, def_chain): - if self.make_controls: - con = pb[org].constraints.new('COPY_TRANSFORMS') - con.name = "copy_transforms" - con.target = self.obj - con.subtarget = ctrl - - if self.make_deforms: - con = pb[defrm].constraints.new('COPY_TRANSFORMS') - con.name = "copy_transforms" - con.target = self.obj - con.subtarget = org - - # Create control widgets + @stage.parent_bones + def parent_control_chain(self): if self.make_controls: - for bone in ctrl_chain: - create_bone_widget(self.obj, bone) + super().parent_control_chain() + @stage.configure_bones + def configure_control_chain(self): + if self.make_controls: + super().configure_control_chain() -def add_parameters(params): - """ Add the parameters of this rig type to the - RigifyParameters PropertyGroup - """ - params.make_controls = bpy.props.BoolProperty(name="Controls", default=True, description="Create control bones for the copy") - params.make_deforms = bpy.props.BoolProperty(name="Deform", default=True, description="Create deform bones for the copy") + @stage.generate_widgets + def make_control_widgets(self): + if self.make_controls: + super().make_control_widgets() + ############################## + # ORG chain -def parameters_ui(layout, params): - """ Create the ui for the rig parameters. - """ - r = layout.row() - r.prop(params, "make_controls") - r = layout.row() - r.prop(params, "make_deforms") + @stage.rig_bones + def rig_org_chain(self): + if self.make_controls: + super().rig_org_chain() + + ############################## + # Deform chain + + @stage.generate_bones + def make_deform_chain(self): + if self.make_deforms: + super().make_deform_chain() + + @stage.parent_bones + def parent_deform_chain(self): + if self.make_deforms: + super().parent_deform_chain() + + @stage.rig_bones + def rig_deform_chain(self): + if self.make_deforms: + super().rig_deform_chain() + + + @classmethod + def add_parameters(self, params): + """ Add the parameters of this rig type to the + RigifyParameters PropertyGroup + """ + params.make_controls = bpy.props.BoolProperty(name="Controls", default=True, description="Create control bones for the copy") + params.make_deforms = bpy.props.BoolProperty(name="Deform", default=True, description="Create deform bones for the copy") + + + @classmethod + def parameters_ui(self, layout, params): + """ Create the ui for the rig parameters. + """ + r = layout.row() + r.prop(params, "make_controls") + r = layout.row() + r.prop(params, "make_deforms") def create_sample(obj): |