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
path: root/rigify
diff options
context:
space:
mode:
Diffstat (limited to 'rigify')
-rw-r--r--rigify/__init__.py37
-rw-r--r--rigify/base_rig.py10
-rw-r--r--rigify/generate.py46
-rw-r--r--rigify/metarigs/Animals/bird.py189
-rw-r--r--rigify/metarigs/Animals/cat.py147
-rw-r--r--rigify/metarigs/Animals/horse.py192
-rw-r--r--rigify/metarigs/Animals/shark.py277
-rw-r--r--rigify/metarigs/Animals/wolf.py155
-rw-r--r--rigify/metarigs/Basic/basic_human.py19
-rw-r--r--rigify/metarigs/Basic/basic_quadruped.py123
-rw-r--r--rigify/metarigs/human.py43
-rw-r--r--rigify/rig_ui_template.py30
-rw-r--r--rigify/rigs/basic/copy_chain.py33
-rw-r--r--rigify/rigs/basic/pivot.py236
-rw-r--r--rigify/rigs/basic/super_copy.py108
-rw-r--r--rigify/rigs/chain_rigs.py6
-rw-r--r--rigify/rigs/experimental/super_chain.py8
-rw-r--r--rigify/rigs/limbs/arm.py69
-rw-r--r--rigify/rigs/limbs/leg.py190
-rw-r--r--rigify/rigs/limbs/limb_rigs.py97
-rw-r--r--rigify/rigs/limbs/paw.py8
-rw-r--r--rigify/rigs/limbs/simple_tentacle.py2
-rw-r--r--rigify/rigs/limbs/super_finger.py42
-rw-r--r--rigify/rigs/limbs/super_palm.py3
-rw-r--r--rigify/rigs/spines/basic_spine.py145
-rw-r--r--rigify/rigs/spines/basic_tail.py7
-rw-r--r--rigify/rigs/spines/spine_rigs.py60
-rw-r--r--rigify/rigs/spines/super_head.py5
-rw-r--r--rigify/rigs/spines/super_spine.py4
-rw-r--r--rigify/ui.py43
-rw-r--r--rigify/utils/animation.py212
-rw-r--r--rigify/utils/bones.py14
-rw-r--r--rigify/utils/components.py87
-rw-r--r--rigify/utils/layers.py13
-rw-r--r--rigify/utils/misc.py8
-rw-r--r--rigify/utils/rig.py1
-rw-r--r--rigify/utils/switch_parent.py118
-rw-r--r--rigify/utils/widgets_basic.py2
38 files changed, 1869 insertions, 920 deletions
diff --git a/rigify/__init__.py b/rigify/__init__.py
index 803c19c0..8363d037 100644
--- a/rigify/__init__.py
+++ b/rigify/__init__.py
@@ -20,7 +20,7 @@
bl_info = {
"name": "Rigify",
- "version": (0, 6, 0),
+ "version": (0, 6, 1),
"author": "Nathan Vegdahl, Lucio Rossi, Ivan Cappiello, Alexander Gavrilov",
"blender": (2, 81, 0),
"description": "Automatic rigging from building-block components",
@@ -520,7 +520,7 @@ def register():
IDStore.rigify_types = CollectionProperty(type=RigifyName)
IDStore.rigify_active_type = IntProperty(name="Rigify Active Type", description="The selected rig type")
- IDStore.rigify_advanced_generation = BoolProperty(name="Advanced Options",
+ bpy.types.Armature.rigify_advanced_generation = BoolProperty(name="Advanced Options",
description="Enables/disables advanced options for Rigify rig generation",
default=False)
@@ -528,27 +528,26 @@ def register():
if self.rigify_generate_mode == 'new':
self.rigify_force_widget_update = False
- IDStore.rigify_generate_mode = EnumProperty(name="Rigify Generate Rig Mode",
+ bpy.types.Armature.rigify_generate_mode = EnumProperty(name="Rigify Generate Rig Mode",
description="'Generate Rig' mode. In 'overwrite' mode the features of the target rig will be updated as defined by the metarig. In 'new' mode a new rig will be created as defined by the metarig. Current mode",
update=update_mode,
items=( ('overwrite', 'overwrite', ''),
('new', 'new', '')))
- IDStore.rigify_force_widget_update = BoolProperty(name="Force Widget Update",
+ bpy.types.Armature.rigify_force_widget_update = BoolProperty(name="Force Widget Update",
description="Forces Rigify to delete and rebuild all the rig widgets. if unset, only missing widgets will be created",
default=False)
- IDStore.rigify_target_rigs = CollectionProperty(type=RigifyName)
- IDStore.rigify_target_rig = StringProperty(name="Rigify Target Rig",
+ bpy.types.Armature.rigify_target_rig = PointerProperty(type=bpy.types.Object,
+ name="Rigify Target Rig",
description="Defines which rig to overwrite. If unset, a new one called 'rig' will be created",
- default="")
+ poll=lambda self, obj: obj.type == 'ARMATURE' and obj.data is not self)
- IDStore.rigify_rig_uis = CollectionProperty(type=RigifyName)
- IDStore.rigify_rig_ui = StringProperty(name="Rigify Target Rig UI",
- description="Defines the UI to overwrite. It should always be the same as the target rig. If unset, 'rig_ui.py' will be used",
- default="")
+ bpy.types.Armature.rigify_rig_ui = PointerProperty(type=bpy.types.Text,
+ name="Rigify Target Rig UI",
+ description="Defines the UI to overwrite. If unset, 'rig_ui.py' will be used")
- IDStore.rigify_rig_basename = StringProperty(name="Rigify Rig Name",
+ bpy.types.Armature.rigify_rig_basename = StringProperty(name="Rigify Rig Name",
description="Defines the name of the Rig. If unset, in 'new' mode 'rig' will be used, in 'overwrite' mode the target rig name will be used",
default="")
@@ -602,19 +601,17 @@ def unregister():
del ArmStore.rigify_colors_index
del ArmStore.rigify_colors_lock
del ArmStore.rigify_theme_to_add
+ del ArmStore.rigify_advanced_generation
+ del ArmStore.rigify_generate_mode
+ del ArmStore.rigify_force_widget_update
+ del ArmStore.rigify_target_rig
+ del ArmStore.rigify_rig_ui
+ del ArmStore.rigify_rig_basename
IDStore = bpy.types.WindowManager
del IDStore.rigify_collection
del IDStore.rigify_types
del IDStore.rigify_active_type
- del IDStore.rigify_advanced_generation
- del IDStore.rigify_generate_mode
- del IDStore.rigify_force_widget_update
- del IDStore.rigify_target_rig
- del IDStore.rigify_target_rigs
- del IDStore.rigify_rig_uis
- del IDStore.rigify_rig_ui
- del IDStore.rigify_rig_basename
del IDStore.rigify_transfer_only_selected
# Classes.
diff --git a/rigify/base_rig.py b/rigify/base_rig.py
index 6b01c43a..b7a5d08c 100644
--- a/rigify/base_rig.py
+++ b/rigify/base_rig.py
@@ -258,6 +258,16 @@ class RigUtility(BoneUtilityMixin, MechanismUtilityMixin):
self.owner.register_new_bone(new_name, old_name)
+class RigComponent(GenerateCallbackHost, RigUtility):
+ """Base class for utility classes that generate part of a rig using callbacks."""
+ def __init__(self, owner):
+ super().__init__(owner)
+
+ self.owner.rigify_sub_objects = objects = self.owner.rigify_sub_objects or []
+
+ objects.append(self)
+
+
#=============================================
# Rig Stage Decorators
#=============================================
diff --git a/rigify/generate.py b/rigify/generate.py
index 0d02c5c2..8e3ca0f0 100644
--- a/rigify/generate.py
+++ b/rigify/generate.py
@@ -69,36 +69,45 @@ class Generator(base_generate.BaseGenerator):
def __create_rig_object(self):
scene = self.scene
id_store = self.id_store
+ meta_data = self.metarig.data
# Check if the generated rig already exists, so we can
# regenerate in the same object. If not, create a new
# object to generate the rig in.
print("Fetch rig.")
- if id_store.rigify_generate_mode == 'overwrite':
- name = id_store.rigify_target_rig or "rig"
- try:
+ self.rig_new_name = name = meta_data.rigify_rig_basename or "rig"
+
+ obj = None
+
+ if meta_data.rigify_generate_mode == 'overwrite':
+ obj = meta_data.rigify_target_rig
+
+ if not obj and name in scene.objects:
obj = scene.objects[name]
- self.rig_old_name = name
- obj.name = self.rig_new_name or name
+
+ if obj:
+ self.rig_old_name = obj.name
+
+ obj.name = name
+ obj.data.name = obj.name
rig_collections = filter_layer_collections_by_object(self.usable_collections, obj)
self.layer_collection = (rig_collections + [self.layer_collection])[0]
self.collection = self.layer_collection.collection
- except KeyError:
- self.rig_old_name = name
- name = self.rig_new_name or name
- obj = bpy.data.objects.new(name, bpy.data.armatures.new(name))
- obj.display_type = 'WIRE'
- self.collection.objects.link(obj)
- else:
- name = self.rig_new_name or "rig"
- obj = bpy.data.objects.new(name, bpy.data.armatures.new(name)) # in case name 'rig' exists it will be rig.001
+ elif name in bpy.data.objects:
+ obj = bpy.data.objects[name]
+
+ if not obj:
+ obj = bpy.data.objects.new(name, bpy.data.armatures.new(name))
obj.display_type = 'WIRE'
self.collection.objects.link(obj)
- id_store.rigify_target_rig = obj.name
+ elif obj.name not in self.collection.objects: # rig exists but was deleted
+ self.collection.objects.link(obj)
+
+ meta_data.rigify_target_rig = obj
obj.data.pose_position = 'POSE'
self.obj = obj
@@ -114,8 +123,8 @@ class Generator(base_generate.BaseGenerator):
self.widget_collection = ensure_widget_collection(context)
# Remove wgts if force update is set
- wgts_group_name = "WGTS_" + (self.rig_old_name or obj.name)
- if wgts_group_name in scene.objects and id_store.rigify_force_widget_update:
+ wgts_group_name = "WGTS_" + (self.rig_old_name or self.obj.name)
+ if wgts_group_name in scene.objects and self.metarig.data.rigify_force_widget_update:
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.select_all(action='DESELECT')
for wgt in bpy.data.objects[wgts_group_name].children:
@@ -327,9 +336,6 @@ class Generator(base_generate.BaseGenerator):
#------------------------------------------
# Create/find the rig object and set it up
- if id_store.rigify_rig_basename:
- self.rig_new_name = id_store.rigify_rig_basename + "_rig"
-
obj = self.__create_rig_object()
# Get rid of anim data in case the rig already existed
diff --git a/rigify/metarigs/Animals/bird.py b/rigify/metarigs/Animals/bird.py
index a3331c29..eee6b38b 100644
--- a/rigify/metarigs/Animals/bird.py
+++ b/rigify/metarigs/Animals/bird.py
@@ -165,47 +165,19 @@ def create(obj):
bones = {}
- bone = arm.edit_bones.new('spine')
- bone.head[:] = -0.0000, 0.1371, 0.0894
- bone.tail[:] = -0.0000, 0.1039, 0.0907
+ bone = arm.edit_bones.new('spine.003')
+ bone.head[:] = -0.0000, 0.0451, 0.0845
+ bone.tail[:] = -0.0000, 0.0192, 0.0888
bone.roll = 0.0000
bone.use_connect = False
- bones['spine'] = bone.name
- bone = arm.edit_bones.new('spine.001')
- bone.head[:] = -0.0000, 0.1039, 0.0907
+ bones['spine.003'] = bone.name
+ bone = arm.edit_bones.new('spine.002')
+ bone.head[:] = -0.0000, 0.0451, 0.0845
bone.tail[:] = -0.0000, 0.0757, 0.0880
bone.roll = 0.0000
- bone.use_connect = True
- bone.parent = arm.edit_bones[bones['spine']]
- bones['spine.001'] = bone.name
- bone = arm.edit_bones.new('t_feather.L')
- bone.head[:] = 0.0112, 0.1017, 0.0907
- bone.tail[:] = 0.0167, 0.1345, 0.0894
- bone.roll = 0.0032
- bone.use_connect = False
- bone.parent = arm.edit_bones[bones['spine']]
- bones['t_feather.L'] = bone.name
- bone = arm.edit_bones.new('t_feather.R')
- bone.head[:] = -0.0112, 0.1017, 0.0907
- bone.tail[:] = -0.0167, 0.1345, 0.0894
- bone.roll = -0.0032
bone.use_connect = False
- bone.parent = arm.edit_bones[bones['spine']]
- bones['t_feather.R'] = bone.name
- bone = arm.edit_bones.new('spine.002')
- bone.head[:] = -0.0000, 0.0757, 0.0880
- bone.tail[:] = -0.0000, 0.0451, 0.0845
- bone.roll = 0.0000
- bone.use_connect = True
- bone.parent = arm.edit_bones[bones['spine.001']]
+ bone.parent = arm.edit_bones[bones['spine.003']]
bones['spine.002'] = bone.name
- bone = arm.edit_bones.new('spine.003')
- bone.head[:] = -0.0000, 0.0451, 0.0845
- bone.tail[:] = -0.0000, 0.0192, 0.0888
- bone.roll = 0.0000
- bone.use_connect = True
- bone.parent = arm.edit_bones[bones['spine.002']]
- bones['spine.003'] = bone.name
bone = arm.edit_bones.new('spine.004')
bone.head[:] = -0.0000, 0.0192, 0.0888
bone.tail[:] = -0.0000, -0.0106, 0.0979
@@ -213,6 +185,13 @@ def create(obj):
bone.use_connect = True
bone.parent = arm.edit_bones[bones['spine.003']]
bones['spine.004'] = bone.name
+ bone = arm.edit_bones.new('spine.001')
+ bone.head[:] = -0.0000, 0.0757, 0.0880
+ bone.tail[:] = -0.0000, 0.1039, 0.0907
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['spine.002']]
+ bones['spine.001'] = bone.name
bone = arm.edit_bones.new('spine.005')
bone.head[:] = -0.0000, -0.0106, 0.0979
bone.tail[:] = -0.0000, -0.0298, 0.1158
@@ -248,6 +227,13 @@ def create(obj):
bone.use_connect = False
bone.parent = arm.edit_bones[bones['spine.004']]
bones['thigh.R'] = bone.name
+ bone = arm.edit_bones.new('spine')
+ bone.head[:] = -0.0000, 0.1039, 0.0907
+ bone.tail[:] = -0.0000, 0.1371, 0.0894
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['spine.001']]
+ bones['spine'] = bone.name
bone = arm.edit_bones.new('shoulder.L')
bone.head[:] = 0.0014, -0.0217, 0.0893
bone.tail[:] = 0.0076, -0.0020, 0.1179
@@ -283,6 +269,20 @@ def create(obj):
bone.use_connect = True
bone.parent = arm.edit_bones[bones['thigh.R']]
bones['shin.R'] = bone.name
+ bone = arm.edit_bones.new('t_feather.L')
+ bone.head[:] = 0.0112, 0.1017, 0.0907
+ bone.tail[:] = 0.0167, 0.1345, 0.0894
+ bone.roll = 0.0032
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['spine']]
+ bones['t_feather.L'] = bone.name
+ bone = arm.edit_bones.new('t_feather.R')
+ bone.head[:] = -0.0112, 0.1017, 0.0907
+ bone.tail[:] = -0.0167, 0.1345, 0.0894
+ bone.roll = -0.0032
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['spine']]
+ bones['t_feather.R'] = bone.name
bone = arm.edit_bones.new('Wing.L')
bone.head[:] = 0.0089, 0.0141, 0.1157
bone.tail[:] = 0.0485, 0.0107, 0.1163
@@ -294,7 +294,7 @@ def create(obj):
bone.head[:] = -0.0000, -0.0417, 0.1348
bone.tail[:] = -0.0000, -0.0458, 0.1429
bone.roll = 0.0001
- bone.use_connect = True
+ bone.use_connect = False
bone.parent = arm.edit_bones[bones['spine.006']]
bones['neck.001'] = bone.name
bone = arm.edit_bones.new('Wing.R')
@@ -691,8 +691,8 @@ def create(obj):
bones['tongue.003.L'] = bone.name
bpy.ops.object.mode_set(mode='OBJECT')
- pbone = obj.pose.bones[bones['spine']]
- pbone.rigify_type = 'spines.super_spine'
+ pbone = obj.pose.bones[bones['spine.003']]
+ pbone.rigify_type = 'spines.basic_spine'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
@@ -700,70 +700,38 @@ def create(obj):
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
try:
- pbone.rigify_parameters.use_tail = True
- except AttributeError:
- pass
- try:
- pbone.rigify_parameters.tail_pos = 3
+ pbone.rigify_parameters.pivot_pos = 1
except AttributeError:
pass
try:
- pbone.rigify_parameters.pivot_pos = 4
- except AttributeError:
- pass
- try:
- pbone.rigify_parameters.neck_pos = 8
- except AttributeError:
- pass
- try:
- pbone.rigify_parameters.copy_rotation_axes = [True, False, True]
+ pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
try:
- pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ pbone.rigify_parameters.fk_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
- pbone = obj.pose.bones[bones['spine.001']]
- pbone.rigify_type = ''
+ pbone = obj.pose.bones[bones['spine.002']]
+ pbone.rigify_type = 'spines.basic_tail'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
- pbone = obj.pose.bones[bones['t_feather.L']]
- pbone.rigify_type = 'basic.super_copy'
- pbone.lock_location = (False, False, False)
- pbone.lock_rotation = (False, False, False)
- pbone.lock_rotation_w = False
- pbone.lock_scale = (False, False, False)
- pbone.rotation_mode = 'QUATERNION'
- pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False]
try:
- pbone.rigify_parameters.make_widget = False
+ pbone.rigify_parameters.copy_rotation_axes = [True, False, True]
except AttributeError:
pass
- pbone = obj.pose.bones[bones['t_feather.R']]
- pbone.rigify_type = 'basic.super_copy'
- pbone.lock_location = (False, False, False)
- pbone.lock_rotation = (False, False, False)
- pbone.lock_rotation_w = False
- pbone.lock_scale = (False, False, False)
- pbone.rotation_mode = 'QUATERNION'
- pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False]
try:
- pbone.rigify_parameters.make_widget = False
+ pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
- pbone = obj.pose.bones[bones['spine.002']]
- pbone.rigify_type = ''
- pbone.lock_location = (False, False, False)
- pbone.lock_rotation = (False, False, False)
- pbone.lock_rotation_w = False
- pbone.lock_scale = (False, False, False)
- pbone.rotation_mode = 'QUATERNION'
- pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
- pbone = obj.pose.bones[bones['spine.003']]
+ try:
+ pbone.rigify_parameters.connect_chain = True
+ except AttributeError:
+ pass
+ pbone = obj.pose.bones[bones['spine.004']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
@@ -771,7 +739,7 @@ def create(obj):
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
- pbone = obj.pose.bones[bones['spine.004']]
+ pbone = obj.pose.bones[bones['spine.001']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
@@ -859,6 +827,14 @@ def create(obj):
pbone.rigify_parameters.fk_layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
+ pbone = obj.pose.bones[bones['spine']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
pbone = obj.pose.bones[bones['shoulder.L']]
pbone.rigify_type = 'basic.super_copy'
pbone.lock_location = (False, False, False)
@@ -907,6 +883,30 @@ def create(obj):
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ pbone = obj.pose.bones[bones['t_feather.L']]
+ pbone.rigify_type = 'basic.super_copy'
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False]
+ try:
+ pbone.rigify_parameters.make_widget = False
+ except AttributeError:
+ pass
+ pbone = obj.pose.bones[bones['t_feather.R']]
+ pbone.rigify_type = 'basic.super_copy'
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False]
+ try:
+ pbone.rigify_parameters.make_widget = False
+ except AttributeError:
+ pass
pbone = obj.pose.bones[bones['Wing.L']]
pbone.rigify_type = 'limbs.simple_tentacle'
pbone.lock_location = (False, False, False)
@@ -914,20 +914,31 @@ def create(obj):
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
- pbone.rigify_parameters.copy_rotation_axes = [False, False, False]
pbone.bone.layers = [False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
try:
+ pbone.rigify_parameters.copy_rotation_axes = [False, False, False]
+ except AttributeError:
+ pass
+ try:
pbone.rigify_parameters.tweak_layers = [False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
pbone = obj.pose.bones[bones['neck.001']]
- pbone.rigify_type = ''
+ pbone.rigify_type = 'spines.super_head'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ try:
+ pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ except AttributeError:
+ pass
+ try:
+ pbone.rigify_parameters.connect_chain = True
+ except AttributeError:
+ pass
pbone = obj.pose.bones[bones['Wing.R']]
pbone.rigify_type = 'limbs.simple_tentacle'
pbone.lock_location = (False, False, False)
@@ -935,9 +946,12 @@ def create(obj):
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
- pbone.rigify_parameters.copy_rotation_axes = [False, False, False]
pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
try:
+ pbone.rigify_parameters.copy_rotation_axes = [False, False, False]
+ except AttributeError:
+ pass
+ try:
pbone.rigify_parameters.tweak_layers = [False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
@@ -1488,9 +1502,12 @@ def create(obj):
bone.select = True
bone.select_head = True
bone.select_tail = True
+ bone.bbone_x = bone.bbone_z = bone.length * 0.05
arm.edit_bones.active = bone
arm.layers = [(x in [0, 3, 7, 10, 13, 16, 21, 24]) for x in range(32)]
+ return bones
+
if __name__ == "__main__":
create(bpy.context.active_object)
diff --git a/rigify/metarigs/Animals/cat.py b/rigify/metarigs/Animals/cat.py
index a065c432..66321116 100644
--- a/rigify/metarigs/Animals/cat.py
+++ b/rigify/metarigs/Animals/cat.py
@@ -165,40 +165,19 @@ def create(obj):
bones = {}
- bone = arm.edit_bones.new('tail.004')
- bone.head[:] = -0.0000, 0.5531, 0.2488
- bone.tail[:] = -0.0000, 0.4543, 0.2321
- bone.roll = 0.0000
- bone.use_connect = False
- bones['tail.004'] = bone.name
- bone = arm.edit_bones.new('tail.003')
- bone.head[:] = -0.0000, 0.4543, 0.2321
- bone.tail[:] = -0.0000, 0.3513, 0.2284
- bone.roll = 0.0000
- bone.use_connect = True
- bone.parent = arm.edit_bones[bones['tail.004']]
- bones['tail.003'] = bone.name
- bone = arm.edit_bones.new('tail.002')
- bone.head[:] = -0.0000, 0.3513, 0.2284
- bone.tail[:] = -0.0000, 0.2460, 0.2324
- bone.roll = 0.0000
- bone.use_connect = True
- bone.parent = arm.edit_bones[bones['tail.003']]
- bones['tail.002'] = bone.name
- bone = arm.edit_bones.new('tail.001')
- bone.head[:] = -0.0000, 0.2460, 0.2324
- bone.tail[:] = 0.0000, 0.1499, 0.2500
- bone.roll = 0.0000
- bone.use_connect = True
- bone.parent = arm.edit_bones[bones['tail.002']]
- bones['tail.001'] = bone.name
bone = arm.edit_bones.new('spine')
bone.head[:] = 0.0000, 0.1499, 0.2500
bone.tail[:] = 0.0000, 0.0769, 0.2272
bone.roll = 0.0000
- bone.use_connect = True
- bone.parent = arm.edit_bones[bones['tail.001']]
+ bone.use_connect = False
bones['spine'] = bone.name
+ bone = arm.edit_bones.new('tail.001')
+ bone.head[:] = 0.0000, 0.1499, 0.2500
+ bone.tail[:] = -0.0000, 0.2460, 0.2324
+ bone.roll = 0.0000
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['spine']]
+ bones['tail.001'] = bone.name
bone = arm.edit_bones.new('spine.001')
bone.head[:] = 0.0000, 0.0769, 0.2272
bone.tail[:] = 0.0000, 0.0180, 0.2240
@@ -227,6 +206,13 @@ def create(obj):
bone.use_connect = False
bone.parent = arm.edit_bones[bones['spine']]
bones['pelvis.C'] = bone.name
+ bone = arm.edit_bones.new('tail.002')
+ bone.head[:] = -0.0000, 0.2460, 0.2324
+ bone.tail[:] = -0.0000, 0.3513, 0.2284
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['tail.001']]
+ bones['tail.002'] = bone.name
bone = arm.edit_bones.new('spine.002')
bone.head[:] = 0.0000, 0.0180, 0.2240
bone.tail[:] = 0.0000, -0.0513, 0.2271
@@ -248,6 +234,13 @@ def create(obj):
bone.use_connect = False
bone.parent = arm.edit_bones[bones['pelvis.R']]
bones['thigh.R'] = bone.name
+ bone = arm.edit_bones.new('tail.003')
+ bone.head[:] = -0.0000, 0.3513, 0.2284
+ bone.tail[:] = -0.0000, 0.4543, 0.2321
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['tail.002']]
+ bones['tail.003'] = bone.name
bone = arm.edit_bones.new('spine.003')
bone.head[:] = 0.0000, -0.0513, 0.2271
bone.tail[:] = 0.0000, -0.1571, 0.2355
@@ -276,11 +269,18 @@ def create(obj):
bone.use_connect = True
bone.parent = arm.edit_bones[bones['thigh.R']]
bones['shin.R'] = bone.name
+ bone = arm.edit_bones.new('tail.004')
+ bone.head[:] = -0.0000, 0.4543, 0.2321
+ bone.tail[:] = -0.0000, 0.5531, 0.2488
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['tail.003']]
+ bones['tail.004'] = bone.name
bone = arm.edit_bones.new('spine.004')
bone.head[:] = 0.0000, -0.1571, 0.2355
bone.tail[:] = 0.0000, -0.1736, 0.2395
bone.roll = 0.0000
- bone.use_connect = True
+ bone.use_connect = False
bone.parent = arm.edit_bones[bones['spine.003']]
bones['spine.004'] = bone.name
bone = arm.edit_bones.new('Breast.C')
@@ -1384,52 +1384,24 @@ def create(obj):
bones['brow.T.R.003'] = bone.name
bpy.ops.object.mode_set(mode='OBJECT')
- pbone = obj.pose.bones[bones['tail.004']]
- pbone.rigify_type = 'spines.super_spine'
+ pbone = obj.pose.bones[bones['spine']]
+ pbone.rigify_type = 'spines.basic_spine'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
- pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False]
- try:
- pbone.rigify_parameters.use_tail = True
- except AttributeError:
- pass
- try:
- pbone.rigify_parameters.pivot_pos = 6
- except AttributeError:
- pass
- try:
- pbone.rigify_parameters.neck_pos = 9
- except AttributeError:
- pass
+ pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
try:
- pbone.rigify_parameters.tail_pos = 4
+ pbone.rigify_parameters.tweak_layers = [False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
try:
- pbone.rigify_parameters.copy_rotation_axes = [True, True, True]
+ pbone.rigify_parameters.fk_layers = [False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
- pbone = obj.pose.bones[bones['tail.003']]
- pbone.rigify_type = ''
- pbone.lock_location = (False, False, False)
- pbone.lock_rotation = (False, False, False)
- pbone.lock_rotation_w = False
- pbone.lock_scale = (False, False, False)
- pbone.rotation_mode = 'QUATERNION'
- pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False]
- pbone = obj.pose.bones[bones['tail.002']]
- pbone.rigify_type = ''
- pbone.lock_location = (False, False, False)
- pbone.lock_rotation = (False, False, False)
- pbone.lock_rotation_w = False
- pbone.lock_scale = (False, False, False)
- pbone.rotation_mode = 'QUATERNION'
- pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False]
pbone = obj.pose.bones[bones['tail.001']]
- pbone.rigify_type = ''
+ pbone.rigify_type = 'spines.basic_tail'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
@@ -1437,23 +1409,15 @@ def create(obj):
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False]
try:
- pbone.rigify_parameters.tweak_layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False]
+ pbone.rigify_parameters.tweak_layers = [False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
- pbone = obj.pose.bones[bones['spine']]
- pbone.rigify_type = ''
- pbone.lock_location = (False, False, False)
- pbone.lock_rotation = (False, False, False)
- pbone.lock_rotation_w = False
- pbone.lock_scale = (False, False, False)
- pbone.rotation_mode = 'QUATERNION'
- pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
try:
- pbone.rigify_parameters.neck_pos = 5
+ pbone.rigify_parameters.copy_rotation_axes = [True, True, True]
except AttributeError:
pass
try:
- pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ pbone.rigify_parameters.connect_chain = True
except AttributeError:
pass
pbone = obj.pose.bones[bones['spine.001']]
@@ -1504,6 +1468,14 @@ def create(obj):
pbone.rigify_parameters.make_control = False
except AttributeError:
pass
+ pbone = obj.pose.bones[bones['tail.002']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False]
pbone = obj.pose.bones[bones['spine.002']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
@@ -1556,6 +1528,14 @@ def create(obj):
pbone.rigify_parameters.tweak_layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
+ pbone = obj.pose.bones[bones['tail.003']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False]
pbone = obj.pose.bones[bones['spine.003']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
@@ -1588,14 +1568,26 @@ def create(obj):
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
- pbone = obj.pose.bones[bones['spine.004']]
+ pbone = obj.pose.bones[bones['tail.004']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
+ pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False]
+ pbone = obj.pose.bones[bones['spine.004']]
+ pbone.rigify_type = 'spines.super_head'
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ try:
+ pbone.rigify_parameters.connect_chain = True
+ except AttributeError:
+ pass
pbone = obj.pose.bones[bones['Breast.C']]
pbone.rigify_type = 'basic.super_copy'
pbone.lock_location = (False, False, False)
@@ -2983,9 +2975,12 @@ def create(obj):
bone.select = True
bone.select_head = True
bone.select_tail = True
+ bone.bbone_x = bone.bbone_z = bone.length * 0.05
arm.edit_bones.active = bone
arm.layers = [(x in [0, 3, 5, 7, 10, 13, 16, 19]) for x in range(32)]
+ return bones
+
if __name__ == "__main__":
create(bpy.context.active_object)
diff --git a/rigify/metarigs/Animals/horse.py b/rigify/metarigs/Animals/horse.py
index 358a9ceb..6c94a19d 100644
--- a/rigify/metarigs/Animals/horse.py
+++ b/rigify/metarigs/Animals/horse.py
@@ -163,60 +163,38 @@ def create(obj):
arm.rigify_layers[28].selset = False
arm.rigify_layers[28].group = 1
-
bones = {}
- bone = arm.edit_bones.new('spine')
- bone.head[:] = -0.0000, 1.7610, 1.1153
- bone.tail[:] = -0.0000, 1.5754, 1.1088
- bone.roll = -0.0000
- bone.use_connect = False
- bones['spine'] = bone.name
- bone = arm.edit_bones.new('spine.001')
- bone.head[:] = -0.0000, 1.5754, 1.1088
- bone.tail[:] = -0.0000, 1.3779, 1.1589
- bone.roll = -0.0000
- bone.use_connect = True
- bone.parent = arm.edit_bones[bones['spine']]
- bones['spine.001'] = bone.name
- bone = arm.edit_bones.new('spine.002')
- bone.head[:] = -0.0000, 1.3779, 1.1589
- bone.tail[:] = -0.0000, 1.1423, 1.3128
- bone.roll = -0.0000
- bone.use_connect = True
- bone.parent = arm.edit_bones[bones['spine.001']]
- bones['spine.002'] = bone.name
- bone = arm.edit_bones.new('spine.003')
- bone.head[:] = -0.0000, 1.1423, 1.3128
- bone.tail[:] = -0.0000, 1.0291, 1.4191
- bone.roll = -0.0000
- bone.use_connect = True
- bone.parent = arm.edit_bones[bones['spine.002']]
- bones['spine.003'] = bone.name
- bone = arm.edit_bones.new('spine.004')
- bone.head[:] = -0.0000, 1.0291, 1.4191
- bone.tail[:] = -0.0000, 0.9228, 1.4526
- bone.roll = -0.0000
- bone.use_connect = True
- bone.parent = arm.edit_bones[bones['spine.003']]
- bones['spine.004'] = bone.name
bone = arm.edit_bones.new('spine.005')
bone.head[:] = -0.0000, 0.9228, 1.4526
bone.tail[:] = -0.0000, 0.6989, 1.4910
bone.roll = -0.0000
- bone.use_connect = True
- bone.parent = arm.edit_bones[bones['spine.004']]
+ bone.use_connect = False
bones['spine.005'] = bone.name
+ bone = arm.edit_bones.new('spine.004')
+ bone.head[:] = -0.0000, 0.9228, 1.4526
+ bone.tail[:] = -0.0000, 1.0291, 1.4191
+ bone.roll = -0.0000
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['spine.005']]
+ bones['spine.004'] = bone.name
bone = arm.edit_bones.new('spine.006')
bone.head[:] = -0.0000, 0.6989, 1.4910
- bone.tail[:] = -0.0000, 0.3824, 1.3801
+ bone.tail[:] = 0.0000, 0.3824, 1.3801
bone.roll = -0.0000
bone.use_connect = True
bone.parent = arm.edit_bones[bones['spine.005']]
bones['spine.006'] = bone.name
+ bone = arm.edit_bones.new('spine.003')
+ bone.head[:] = -0.0000, 1.0291, 1.4191
+ bone.tail[:] = -0.0000, 1.1423, 1.3128
+ bone.roll = -0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['spine.004']]
+ bones['spine.003'] = bone.name
bone = arm.edit_bones.new('spine.007')
- bone.head[:] = -0.0000, 0.3824, 1.3801
- bone.tail[:] = -0.0000, 0.1316, 1.3086
+ bone.head[:] = 0.0000, 0.3824, 1.3801
+ bone.tail[:] = 0.0000, 0.1316, 1.3086
bone.roll = 0.0000
bone.use_connect = True
bone.parent = arm.edit_bones[bones['spine.006']]
@@ -256,9 +234,16 @@ def create(obj):
bone.use_connect = False
bone.parent = arm.edit_bones[bones['spine.006']]
bones['pelvis'] = bone.name
+ bone = arm.edit_bones.new('spine.002')
+ bone.head[:] = -0.0000, 1.1423, 1.3128
+ bone.tail[:] = -0.0000, 1.3779, 1.1589
+ bone.roll = -0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['spine.003']]
+ bones['spine.002'] = bone.name
bone = arm.edit_bones.new('spine.008')
- bone.head[:] = -0.0000, 0.1316, 1.3086
- bone.tail[:] = -0.0000, -0.1712, 1.2964
+ bone.head[:] = 0.0000, 0.1316, 1.3086
+ bone.tail[:] = 0.0000, -0.1712, 1.2964
bone.roll = 0.0000
bone.use_connect = True
bone.parent = arm.edit_bones[bones['spine.007']]
@@ -277,9 +262,16 @@ def create(obj):
bone.use_connect = True
bone.parent = arm.edit_bones[bones['thigh.R']]
bones['shin.R'] = bone.name
+ bone = arm.edit_bones.new('spine.001')
+ bone.head[:] = -0.0000, 1.3779, 1.1589
+ bone.tail[:] = -0.0000, 1.5754, 1.1088
+ bone.roll = -0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['spine.002']]
+ bones['spine.001'] = bone.name
bone = arm.edit_bones.new('spine.009')
- bone.head[:] = -0.0000, -0.1712, 1.2964
- bone.tail[:] = -0.0000, -0.4908, 1.3031
+ bone.head[:] = 0.0000, -0.1712, 1.2964
+ bone.tail[:] = 0.0000, -0.4908, 1.3031
bone.roll = 0.0000
bone.use_connect = True
bone.parent = arm.edit_bones[bones['spine.008']]
@@ -305,9 +297,16 @@ def create(obj):
bone.use_connect = True
bone.parent = arm.edit_bones[bones['shin.R']]
bones['foot.R'] = bone.name
+ bone = arm.edit_bones.new('spine')
+ bone.head[:] = -0.0000, 1.5754, 1.1088
+ bone.tail[:] = -0.0000, 1.7610, 1.1153
+ bone.roll = -0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['spine.001']]
+ bones['spine'] = bone.name
bone = arm.edit_bones.new('spine.010')
- bone.head[:] = -0.0000, -0.4908, 1.3031
- bone.tail[:] = -0.0000, -0.7593, 1.3786
+ bone.head[:] = 0.0000, -0.4908, 1.3031
+ bone.tail[:] = 0.0000, -0.7593, 1.3786
bone.roll = 0.0000
bone.use_connect = True
bone.parent = arm.edit_bones[bones['spine.009']]
@@ -362,10 +361,10 @@ def create(obj):
bone.parent = arm.edit_bones[bones['foot.R']]
bones['r_toe.R'] = bone.name
bone = arm.edit_bones.new('spine.011')
- bone.head[:] = -0.0000, -0.7593, 1.3786
- bone.tail[:] = -0.0000, -0.9004, 1.5475
+ bone.head[:] = 0.0000, -0.7593, 1.3786
+ bone.tail[:] = 0.0000, -0.9004, 1.5475
bone.roll = 0.0000
- bone.use_connect = True
+ bone.use_connect = False
bone.parent = arm.edit_bones[bones['spine.010']]
bones['spine.011'] = bone.name
bone = arm.edit_bones.new('hair_base.05')
@@ -629,8 +628,8 @@ def create(obj):
bones['jaw.001'] = bone.name
bpy.ops.object.mode_set(mode='OBJECT')
- pbone = obj.pose.bones[bones['spine']]
- pbone.rigify_type = 'spines.super_spine'
+ pbone = obj.pose.bones[bones['spine.005']]
+ pbone.rigify_type = 'spines.basic_spine'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
@@ -638,7 +637,7 @@ def create(obj):
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False]
try:
- pbone.rigify_parameters.neck_pos = 12
+ pbone.rigify_parameters.pivot_pos = 3
except AttributeError:
pass
try:
@@ -646,37 +645,37 @@ def create(obj):
except AttributeError:
pass
try:
- pbone.rigify_parameters.use_tail = True
+ pbone.rigify_parameters.fk_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
+ pbone = obj.pose.bones[bones['spine.004']]
+ pbone.rigify_type = 'spines.basic_tail'
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False]
try:
- pbone.rigify_parameters.pivot_pos = 8
+ pbone.rigify_parameters.copy_rotation_axes = [True, False, True]
except AttributeError:
pass
try:
- pbone.rigify_parameters.tail_pos = 5
+ pbone.rigify_parameters.connect_chain = True
except AttributeError:
pass
try:
- pbone.rigify_parameters.copy_rotation_axes = [True, False, True]
+ pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
- pbone = obj.pose.bones[bones['spine.001']]
- pbone.rigify_type = ''
- pbone.lock_location = (False, False, False)
- pbone.lock_rotation = (False, False, False)
- pbone.lock_rotation_w = False
- pbone.lock_scale = (False, False, False)
- pbone.rotation_mode = 'QUATERNION'
- pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False]
- pbone = obj.pose.bones[bones['spine.002']]
+ pbone = obj.pose.bones[bones['spine.006']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
- pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False]
+ pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
pbone = obj.pose.bones[bones['spine.003']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
@@ -685,30 +684,6 @@ def create(obj):
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False]
- pbone = obj.pose.bones[bones['spine.004']]
- pbone.rigify_type = ''
- pbone.lock_location = (False, False, False)
- pbone.lock_rotation = (False, False, False)
- pbone.lock_rotation_w = False
- pbone.lock_scale = (False, False, False)
- pbone.rotation_mode = 'QUATERNION'
- pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False]
- pbone = obj.pose.bones[bones['spine.005']]
- pbone.rigify_type = ''
- pbone.lock_location = (False, False, False)
- pbone.lock_rotation = (False, False, False)
- pbone.lock_rotation_w = False
- pbone.lock_scale = (False, False, False)
- pbone.rotation_mode = 'QUATERNION'
- pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False]
- pbone = obj.pose.bones[bones['spine.006']]
- pbone.rigify_type = ''
- pbone.lock_location = (False, False, False)
- pbone.lock_rotation = (False, False, False)
- pbone.lock_rotation_w = False
- pbone.lock_scale = (False, False, False)
- pbone.rotation_mode = 'QUATERNION'
- pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
pbone = obj.pose.bones[bones['spine.007']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
@@ -805,6 +780,14 @@ def create(obj):
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ pbone = obj.pose.bones[bones['spine.002']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False]
pbone = obj.pose.bones[bones['spine.008']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
@@ -829,6 +812,14 @@ def create(obj):
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ pbone = obj.pose.bones[bones['spine.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False]
pbone = obj.pose.bones[bones['spine.009']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
@@ -861,6 +852,14 @@ def create(obj):
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ pbone = obj.pose.bones[bones['spine']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False]
pbone = obj.pose.bones[bones['spine.010']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
@@ -934,13 +933,21 @@ def create(obj):
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
pbone = obj.pose.bones[bones['spine.011']]
- pbone.rigify_type = ''
+ pbone.rigify_type = 'spines.super_head'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ try:
+ pbone.rigify_parameters.connect_chain = True
+ except AttributeError:
+ pass
+ try:
+ pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ except AttributeError:
+ pass
pbone = obj.pose.bones[bones['hair_base.05']]
pbone.rigify_type = 'limbs.super_finger'
pbone.lock_location = (False, False, False)
@@ -1364,9 +1371,12 @@ def create(obj):
bone.select = True
bone.select_head = True
bone.select_tail = True
+ bone.bbone_x = bone.bbone_z = bone.length * 0.05
arm.edit_bones.active = bone
arm.layers = [(x in [0, 3, 4, 7, 10, 13, 16, 19, 21]) for x in range(32)]
+ return bones
+
if __name__ == "__main__":
create(bpy.context.active_object)
diff --git a/rigify/metarigs/Animals/shark.py b/rigify/metarigs/Animals/shark.py
index 1ee1d0d9..8b72a965 100644
--- a/rigify/metarigs/Animals/shark.py
+++ b/rigify/metarigs/Animals/shark.py
@@ -165,40 +165,40 @@ def create(obj):
bones = {}
- bone = arm.edit_bones.new('spine')
- bone.head[:] = -0.0000, 1.3362, 0.4776
- bone.tail[:] = -0.0000, 1.0816, 0.4540
- bone.roll = 0.0000
+ bone = arm.edit_bones.new('spine.003')
+ bone.head[:] = -0.0000, 0.3182, 0.4031
+ bone.tail[:] = -0.0000, 0.0152, 0.3904
+ bone.roll = 0.0001
bone.use_connect = False
- bones['spine'] = bone.name
- bone = arm.edit_bones.new('spine.001')
- bone.head[:] = -0.0000, 1.0816, 0.4540
+ bones['spine.003'] = bone.name
+ bone = arm.edit_bones.new('spine.002')
+ bone.head[:] = -0.0000, 0.3182, 0.4031
bone.tail[:] = -0.0000, 0.7152, 0.4305
bone.roll = -0.0000
- bone.use_connect = True
- bone.parent = arm.edit_bones[bones['spine']]
- bones['spine.001'] = bone.name
- bone = arm.edit_bones.new('back_fin.T.Bk')
- bone.head[:] = 0.0000, 1.2501, 0.5345
- bone.tail[:] = 0.0000, 1.5211, 0.7594
- bone.roll = 0.0000
- bone.use_connect = False
- bone.parent = arm.edit_bones[bones['spine']]
- bones['back_fin.T.Bk'] = bone.name
- bone = arm.edit_bones.new('back_fin.B.Bk')
- bone.head[:] = 0.0000, 1.2305, 0.4158
- bone.tail[:] = 0.0000, 1.3289, 0.2452
- bone.roll = 0.0000
bone.use_connect = False
- bone.parent = arm.edit_bones[bones['spine']]
- bones['back_fin.B.Bk'] = bone.name
- bone = arm.edit_bones.new('spine.002')
+ bone.parent = arm.edit_bones[bones['spine.003']]
+ bones['spine.002'] = bone.name
+ bone = arm.edit_bones.new('spine.001')
bone.head[:] = -0.0000, 0.7152, 0.4305
- bone.tail[:] = -0.0000, 0.3182, 0.4031
+ bone.tail[:] = -0.0000, 1.0816, 0.4540
bone.roll = -0.0000
bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['spine.002']]
+ bones['spine.001'] = bone.name
+ bone = arm.edit_bones.new('spine.008')
+ bone.head[:] = -0.0000, 0.0152, 0.3904
+ bone.tail[:] = 0.0000, -0.3259, 0.3967
+ bone.roll = 0.0001
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['spine.003']]
+ bones['spine.008'] = bone.name
+ bone = arm.edit_bones.new('spine')
+ bone.head[:] = -0.0000, 1.0816, 0.4540
+ bone.tail[:] = -0.0000, 1.3362, 0.4776
+ bone.roll = 0.0000
+ bone.use_connect = True
bone.parent = arm.edit_bones[bones['spine.001']]
- bones['spine.002'] = bone.name
+ bones['spine'] = bone.name
bone = arm.edit_bones.new('mid_fin.Top')
bone.head[:] = 0.0000, 0.7296, 0.5396
bone.tail[:] = 0.0000, 0.7709, 0.6351
@@ -213,41 +213,6 @@ def create(obj):
bone.use_connect = False
bone.parent = arm.edit_bones[bones['spine.001']]
bones['mid_fin.Bot'] = bone.name
- bone = arm.edit_bones.new('back_fin.T.001.Bk')
- bone.head[:] = 0.0000, 1.5211, 0.7594
- bone.tail[:] = 0.0000, 1.7667, 0.9633
- bone.roll = 0.0000
- bone.use_connect = True
- bone.parent = arm.edit_bones[bones['back_fin.T.Bk']]
- bones['back_fin.T.001.Bk'] = bone.name
- bone = arm.edit_bones.new('back_fin.B.001.Bk')
- bone.head[:] = 0.0000, 1.3289, 0.2452
- bone.tail[:] = 0.0000, 1.3818, 0.1513
- bone.roll = 0.0000
- bone.use_connect = True
- bone.parent = arm.edit_bones[bones['back_fin.B.Bk']]
- bones['back_fin.B.001.Bk'] = bone.name
- bone = arm.edit_bones.new('spine.003')
- bone.head[:] = -0.0000, 0.3182, 0.4031
- bone.tail[:] = -0.0000, 0.0152, 0.3904
- bone.roll = 0.0001
- bone.use_connect = True
- bone.parent = arm.edit_bones[bones['spine.002']]
- bones['spine.003'] = bone.name
- bone = arm.edit_bones.new('back_fin.T.002.Bk')
- bone.head[:] = 0.0000, 1.7667, 0.9633
- bone.tail[:] = 0.0000, 1.9489, 1.1145
- bone.roll = 0.0000
- bone.use_connect = True
- bone.parent = arm.edit_bones[bones['back_fin.T.001.Bk']]
- bones['back_fin.T.002.Bk'] = bone.name
- bone = arm.edit_bones.new('spine.008')
- bone.head[:] = -0.0000, 0.0152, 0.3904
- bone.tail[:] = 0.0000, -0.3259, 0.3967
- bone.roll = 0.0001
- bone.use_connect = True
- bone.parent = arm.edit_bones[bones['spine.003']]
- bones['spine.008'] = bone.name
bone = arm.edit_bones.new('spine.004')
bone.head[:] = 0.0000, -0.3259, 0.3967
bone.tail[:] = 0.0000, -0.5947, 0.4044
@@ -269,6 +234,20 @@ def create(obj):
bone.use_connect = False
bone.parent = arm.edit_bones[bones['spine.008']]
bones['chest_fin.Bot.R'] = bone.name
+ bone = arm.edit_bones.new('back_fin.T.Bk')
+ bone.head[:] = 0.0000, 1.2501, 0.5345
+ bone.tail[:] = 0.0000, 1.5211, 0.7594
+ bone.roll = 0.0000
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['spine']]
+ bones['back_fin.T.Bk'] = bone.name
+ bone = arm.edit_bones.new('back_fin.B.Bk')
+ bone.head[:] = 0.0000, 1.2305, 0.4158
+ bone.tail[:] = 0.0000, 1.3289, 0.2452
+ bone.roll = 0.0000
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['spine']]
+ bones['back_fin.B.Bk'] = bone.name
bone = arm.edit_bones.new('spine.005')
bone.head[:] = 0.0000, -0.5947, 0.4044
bone.tail[:] = 0.0000, -1.2084, 0.4328
@@ -283,11 +262,25 @@ def create(obj):
bone.use_connect = False
bone.parent = arm.edit_bones[bones['spine.004']]
bones['top_fin'] = bone.name
+ bone = arm.edit_bones.new('back_fin.T.001.Bk')
+ bone.head[:] = 0.0000, 1.5211, 0.7594
+ bone.tail[:] = 0.0000, 1.7667, 0.9633
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['back_fin.T.Bk']]
+ bones['back_fin.T.001.Bk'] = bone.name
+ bone = arm.edit_bones.new('back_fin.B.001.Bk')
+ bone.head[:] = 0.0000, 1.3289, 0.2452
+ bone.tail[:] = 0.0000, 1.3818, 0.1513
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['back_fin.B.Bk']]
+ bones['back_fin.B.001.Bk'] = bone.name
bone = arm.edit_bones.new('spine.006')
bone.head[:] = 0.0000, -1.2084, 0.4328
bone.tail[:] = 0.0000, -1.5634, 0.4275
bone.roll = -0.0000
- bone.use_connect = True
+ bone.use_connect = False
bone.parent = arm.edit_bones[bones['spine.005']]
bones['spine.006'] = bone.name
bone = arm.edit_bones.new('shoulder.L')
@@ -311,6 +304,13 @@ def create(obj):
bone.use_connect = True
bone.parent = arm.edit_bones[bones['top_fin']]
bones['top_fin.001'] = bone.name
+ bone = arm.edit_bones.new('back_fin.T.002.Bk')
+ bone.head[:] = 0.0000, 1.7667, 0.9633
+ bone.tail[:] = 0.0000, 1.9489, 1.1145
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['back_fin.T.001.Bk']]
+ bones['back_fin.T.002.Bk'] = bone.name
bone = arm.edit_bones.new('spine.007')
bone.head[:] = 0.0000, -1.5634, 0.4275
bone.tail[:] = 0.0000, -2.0661, 0.4364
@@ -411,8 +411,8 @@ def create(obj):
bones['jaw.003.R'] = bone.name
bpy.ops.object.mode_set(mode='OBJECT')
- pbone = obj.pose.bones[bones['spine']]
- pbone.rigify_type = 'spines.super_spine'
+ pbone = obj.pose.bones[bones['spine.002']]
+ pbone.rigify_type = 'spines.basic_tail'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
@@ -420,70 +420,34 @@ def create(obj):
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
try:
- pbone.rigify_parameters.neck_pos = 8
- except AttributeError:
- pass
- try:
pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
try:
- pbone.rigify_parameters.tail_pos = 3
- except AttributeError:
- pass
- try:
- pbone.rigify_parameters.pivot_pos = 5
- except AttributeError:
- pass
- try:
- pbone.rigify_parameters.use_tail = True
+ pbone.rigify_parameters.connect_chain = True
except AttributeError:
pass
try:
pbone.rigify_parameters.copy_rotation_axes = [True, False, True]
except AttributeError:
pass
- pbone = obj.pose.bones[bones['spine.001']]
- pbone.rigify_type = ''
- pbone.lock_location = (False, False, False)
- pbone.lock_rotation = (False, False, False)
- pbone.lock_rotation_w = False
- pbone.lock_scale = (False, False, False)
- pbone.rotation_mode = 'QUATERNION'
- pbone.bone.layers = [False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
- pbone = obj.pose.bones[bones['back_fin.T.Bk']]
- pbone.rigify_type = 'limbs.super_finger'
- pbone.lock_location = (False, False, False)
- pbone.lock_rotation = (False, False, False)
- pbone.lock_rotation_w = False
- pbone.lock_scale = (False, False, False)
- pbone.rotation_mode = 'QUATERNION'
- pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
- try:
- pbone.rigify_parameters.tweak_layers = [False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
- except AttributeError:
- pass
- try:
- pbone.rigify_parameters.primary_rotation_axis = "Z"
- except AttributeError:
- pass
- pbone = obj.pose.bones[bones['back_fin.B.Bk']]
- pbone.rigify_type = 'limbs.super_finger'
+ pbone = obj.pose.bones[bones['spine.003']]
+ pbone.rigify_type = 'spines.basic_spine'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
- pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
try:
- pbone.rigify_parameters.tweak_layers = [False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
try:
- pbone.rigify_parameters.primary_rotation_axis = "Z"
+ pbone.rigify_parameters.fk_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
- pbone = obj.pose.bones[bones['spine.002']]
+ pbone = obj.pose.bones[bones['spine.001']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
@@ -491,23 +455,23 @@ def create(obj):
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
- pbone = obj.pose.bones[bones['mid_fin.Top']]
+ pbone = obj.pose.bones[bones['spine.008']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
- pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
- pbone = obj.pose.bones[bones['mid_fin.Bot']]
+ pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ pbone = obj.pose.bones[bones['spine']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
- pbone.bone.layers = [False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
- pbone = obj.pose.bones[bones['back_fin.T.001.Bk']]
+ pbone.bone.layers = [False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ pbone = obj.pose.bones[bones['mid_fin.Top']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
@@ -515,15 +479,15 @@ def create(obj):
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
- pbone = obj.pose.bones[bones['back_fin.B.001.Bk']]
+ pbone = obj.pose.bones[bones['mid_fin.Bot']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
- pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
- pbone = obj.pose.bones[bones['spine.003']]
+ pbone.bone.layers = [False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ pbone = obj.pose.bones[bones['spine.004']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
@@ -531,32 +495,32 @@ def create(obj):
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
- pbone = obj.pose.bones[bones['back_fin.T.002.Bk']]
- pbone.rigify_type = ''
+ pbone = obj.pose.bones[bones['chest_fin.Bot.L']]
+ pbone.rigify_type = 'basic.super_copy'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
- pbone = obj.pose.bones[bones['spine.008']]
- pbone.rigify_type = ''
- pbone.lock_location = (False, False, False)
- pbone.lock_rotation = (False, False, False)
- pbone.lock_rotation_w = False
- pbone.lock_scale = (False, False, False)
- pbone.rotation_mode = 'QUATERNION'
- pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
- pbone = obj.pose.bones[bones['spine.004']]
- pbone.rigify_type = ''
+ try:
+ pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ except AttributeError:
+ pass
+ pbone = obj.pose.bones[bones['chest_fin.Bot.R']]
+ pbone.rigify_type = 'basic.super_copy'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
- pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
- pbone = obj.pose.bones[bones['chest_fin.Bot.L']]
- pbone.rigify_type = 'basic.super_copy'
+ pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ try:
+ pbone.rigify_parameters.tweak_layers = [False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ except AttributeError:
+ pass
+ pbone = obj.pose.bones[bones['back_fin.T.Bk']]
+ pbone.rigify_type = 'limbs.super_finger'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
@@ -564,11 +528,15 @@ def create(obj):
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
try:
- pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ pbone.rigify_parameters.tweak_layers = [False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
- pbone = obj.pose.bones[bones['chest_fin.Bot.R']]
- pbone.rigify_type = 'basic.super_copy'
+ try:
+ pbone.rigify_parameters.primary_rotation_axis = "Z"
+ except AttributeError:
+ pass
+ pbone = obj.pose.bones[bones['back_fin.B.Bk']]
+ pbone.rigify_type = 'limbs.super_finger'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
@@ -576,7 +544,11 @@ def create(obj):
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
try:
- pbone.rigify_parameters.tweak_layers = [False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ pbone.rigify_parameters.tweak_layers = [False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ except AttributeError:
+ pass
+ try:
+ pbone.rigify_parameters.primary_rotation_axis = "Z"
except AttributeError:
pass
pbone = obj.pose.bones[bones['spine.005']]
@@ -599,14 +571,38 @@ def create(obj):
pbone.rigify_parameters.tweak_layers = [False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
- pbone = obj.pose.bones[bones['spine.006']]
+ pbone = obj.pose.bones[bones['back_fin.T.001.Bk']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ pbone = obj.pose.bones[bones['back_fin.B.001.Bk']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
+ pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ pbone = obj.pose.bones[bones['spine.006']]
+ pbone.rigify_type = 'spines.super_head'
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ try:
+ pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ except AttributeError:
+ pass
+ try:
+ pbone.rigify_parameters.connect_chain = True
+ except AttributeError:
+ pass
pbone = obj.pose.bones[bones['shoulder.L']]
pbone.rigify_type = 'basic.super_copy'
pbone.lock_location = (False, False, False)
@@ -639,6 +635,14 @@ def create(obj):
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ pbone = obj.pose.bones[bones['back_fin.T.002.Bk']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
pbone = obj.pose.bones[bones['spine.007']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
@@ -786,9 +790,12 @@ def create(obj):
bone.select = True
bone.select_head = True
bone.select_tail = True
+ bone.bbone_x = bone.bbone_z = bone.length * 0.05
arm.edit_bones.active = bone
arm.layers = [(x in [0, 3, 5, 6, 8, 10]) for x in range(32)]
+ return bones
+
if __name__ == "__main__":
create(bpy.context.active_object)
diff --git a/rigify/metarigs/Animals/wolf.py b/rigify/metarigs/Animals/wolf.py
index 4cccf085..f6150c54 100644
--- a/rigify/metarigs/Animals/wolf.py
+++ b/rigify/metarigs/Animals/wolf.py
@@ -165,40 +165,19 @@ def create(obj):
bones = {}
- bone = arm.edit_bones.new('spine')
- bone.head[:] = 0.0000, 1.1044, 0.7633
- bone.tail[:] = 0.0000, 0.9624, 0.7412
- bone.roll = 0.0000
- bone.use_connect = False
- bones['spine'] = bone.name
- bone = arm.edit_bones.new('spine.001')
- bone.head[:] = 0.0000, 0.9624, 0.7412
- bone.tail[:] = 0.0000, 0.7755, 0.7418
- bone.roll = 0.0000
- bone.use_connect = True
- bone.parent = arm.edit_bones[bones['spine']]
- bones['spine.001'] = bone.name
- bone = arm.edit_bones.new('spine.002')
- bone.head[:] = 0.0000, 0.7755, 0.7418
- bone.tail[:] = 0.0000, 0.5547, 0.7568
- bone.roll = 0.0000
- bone.use_connect = True
- bone.parent = arm.edit_bones[bones['spine.001']]
- bones['spine.002'] = bone.name
- bone = arm.edit_bones.new('spine.003')
- bone.head[:] = 0.0000, 0.5547, 0.7568
- bone.tail[:] = 0.0000, 0.4418, 0.7954
- bone.roll = 0.0000
- bone.use_connect = True
- bone.parent = arm.edit_bones[bones['spine.002']]
- bones['spine.003'] = bone.name
bone = arm.edit_bones.new('spine.004')
bone.head[:] = 0.0000, 0.4418, 0.7954
bone.tail[:] = 0.0000, 0.3546, 0.8059
bone.roll = 0.0000
- bone.use_connect = True
- bone.parent = arm.edit_bones[bones['spine.003']]
+ bone.use_connect = False
bones['spine.004'] = bone.name
+ bone = arm.edit_bones.new('spine.003')
+ bone.head[:] = 0.0000, 0.4418, 0.7954
+ bone.tail[:] = 0.0000, 0.5547, 0.7568
+ bone.roll = 0.0000
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['spine.004']]
+ bones['spine.003'] = bone.name
bone = arm.edit_bones.new('spine.005')
bone.head[:] = 0.0000, 0.3546, 0.8059
bone.tail[:] = 0.0000, 0.1803, 0.7782
@@ -206,6 +185,13 @@ def create(obj):
bone.use_connect = True
bone.parent = arm.edit_bones[bones['spine.004']]
bones['spine.005'] = bone.name
+ bone = arm.edit_bones.new('spine.002')
+ bone.head[:] = 0.0000, 0.5547, 0.7568
+ bone.tail[:] = 0.0000, 0.7755, 0.7418
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['spine.003']]
+ bones['spine.002'] = bone.name
bone = arm.edit_bones.new('spine.006')
bone.head[:] = 0.0000, 0.1803, 0.7782
bone.tail[:] = 0.0000, 0.0319, 0.7731
@@ -241,6 +227,13 @@ def create(obj):
bone.use_connect = False
bone.parent = arm.edit_bones[bones['spine.005']]
bones['thigh.R'] = bone.name
+ bone = arm.edit_bones.new('spine.001')
+ bone.head[:] = 0.0000, 0.7755, 0.7418
+ bone.tail[:] = 0.0000, 0.9624, 0.7412
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['spine.002']]
+ bones['spine.001'] = bone.name
bone = arm.edit_bones.new('spine.007')
bone.head[:] = 0.0000, 0.0319, 0.7731
bone.tail[:] = 0.0000, -0.0980, 0.7945
@@ -262,6 +255,13 @@ def create(obj):
bone.use_connect = True
bone.parent = arm.edit_bones[bones['thigh.R']]
bones['shin.R'] = bone.name
+ bone = arm.edit_bones.new('spine')
+ bone.head[:] = 0.0000, 0.9624, 0.7412
+ bone.tail[:] = 0.0000, 1.1044, 0.7633
+ bone.roll = 0.0000
+ bone.use_connect = True
+ bone.parent = arm.edit_bones[bones['spine.001']]
+ bones['spine'] = bone.name
bone = arm.edit_bones.new('spine.008')
bone.head[:] = 0.0000, -0.0980, 0.7945
bone.tail[:] = 0.0000, -0.3618, 0.8375
@@ -287,7 +287,7 @@ def create(obj):
bone.head[:] = 0.0000, -0.3618, 0.8375
bone.tail[:] = 0.0000, -0.4253, 0.8585
bone.roll = 0.0000
- bone.use_connect = True
+ bone.use_connect = False
bone.parent = arm.edit_bones[bones['spine.008']]
bones['spine.009'] = bone.name
bone = arm.edit_bones.new('shoulder.L')
@@ -1496,63 +1496,63 @@ def create(obj):
bones['brow.T.R.003'] = bone.name
bpy.ops.object.mode_set(mode='OBJECT')
- pbone = obj.pose.bones[bones['spine']]
- pbone.rigify_type = 'spines.super_spine'
+ pbone = obj.pose.bones[bones['spine.004']]
+ pbone.rigify_type = 'spines.basic_spine'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
- pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False]
+ pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
try:
- pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ pbone.rigify_parameters.pivot_pos = 4
except AttributeError:
pass
try:
- pbone.rigify_parameters.use_tail = True
+ pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
try:
- pbone.rigify_parameters.tail_pos = 4
+ pbone.rigify_parameters.fk_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
+ pbone = obj.pose.bones[bones['spine.003']]
+ pbone.rigify_type = 'spines.basic_tail'
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False]
try:
- pbone.rigify_parameters.pivot_pos = 8
+ pbone.rigify_parameters.copy_rotation_axes = [True, False, True]
except AttributeError:
pass
try:
- pbone.rigify_parameters.neck_pos = 10
+ pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
try:
- pbone.rigify_parameters.copy_rotation_axes = [True, False, True]
+ pbone.rigify_parameters.connect_chain = True
except AttributeError:
pass
- pbone = obj.pose.bones[bones['spine.001']]
- pbone.rigify_type = ''
- pbone.lock_location = (False, False, False)
- pbone.lock_rotation = (False, False, False)
- pbone.lock_rotation_w = False
- pbone.lock_scale = (False, False, False)
- pbone.rotation_mode = 'QUATERNION'
- pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False]
- pbone = obj.pose.bones[bones['spine.002']]
+ pbone = obj.pose.bones[bones['spine.005']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
- pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False]
+ pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
try:
- pbone.rigify_parameters.tweak_extra_layers = False
+ pbone.rigify_parameters.neck_pos = 5
except AttributeError:
pass
try:
- pbone.rigify_parameters.tweak_layers = [False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False]
+ pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
- pbone = obj.pose.bones[bones['spine.003']]
+ pbone = obj.pose.bones[bones['spine.002']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
@@ -1560,28 +1560,8 @@ def create(obj):
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False]
- pbone = obj.pose.bones[bones['spine.004']]
- pbone.rigify_type = ''
- pbone.lock_location = (False, False, False)
- pbone.lock_rotation = (False, False, False)
- pbone.lock_rotation_w = False
- pbone.lock_scale = (False, False, False)
- pbone.rotation_mode = 'QUATERNION'
- pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
- pbone = obj.pose.bones[bones['spine.005']]
- pbone.rigify_type = ''
- pbone.lock_location = (False, False, False)
- pbone.lock_rotation = (False, False, False)
- pbone.lock_rotation_w = False
- pbone.lock_scale = (False, False, False)
- pbone.rotation_mode = 'QUATERNION'
- pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
try:
- pbone.rigify_parameters.neck_pos = 5
- except AttributeError:
- pass
- try:
- pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ pbone.rigify_parameters.tweak_layers = [False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
pbone = obj.pose.bones[bones['spine.006']]
@@ -1656,6 +1636,14 @@ def create(obj):
pbone.rigify_parameters.limb_type = "paw"
except AttributeError:
pass
+ pbone = obj.pose.bones[bones['spine.001']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False]
pbone = obj.pose.bones[bones['spine.007']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
@@ -1680,6 +1668,14 @@ def create(obj):
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ pbone = obj.pose.bones[bones['spine']]
+ pbone.rigify_type = ''
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+ pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False]
pbone = obj.pose.bones[bones['spine.008']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
@@ -1705,13 +1701,21 @@ def create(obj):
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
pbone = obj.pose.bones[bones['spine.009']]
- pbone.rigify_type = ''
+ pbone.rigify_type = 'spines.super_head'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ try:
+ pbone.rigify_parameters.connect_chain = True
+ except AttributeError:
+ pass
+ try:
+ pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ except AttributeError:
+ pass
pbone = obj.pose.bones[bones['shoulder.L']]
pbone.rigify_type = 'basic.super_copy'
pbone.lock_location = (False, False, False)
@@ -3219,9 +3223,12 @@ def create(obj):
bone.select = True
bone.select_head = True
bone.select_tail = True
+ bone.bbone_x = bone.bbone_z = bone.length * 0.05
arm.edit_bones.active = bone
arm.layers = [(x in [0, 3, 4, 5, 7, 10, 13, 16, 19]) for x in range(32)]
+ return bones
+
if __name__ == "__main__":
create(bpy.context.active_object)
diff --git a/rigify/metarigs/Basic/basic_human.py b/rigify/metarigs/Basic/basic_human.py
index 01367a7b..01017cf4 100644
--- a/rigify/metarigs/Basic/basic_human.py
+++ b/rigify/metarigs/Basic/basic_human.py
@@ -252,7 +252,7 @@ def create(obj):
bone.head[:] = 0.0000, 0.0114, 1.6582
bone.tail[:] = 0.0000, -0.0130, 1.7197
bone.roll = 0.0000
- bone.use_connect = True
+ bone.use_connect = False
bone.parent = arm.edit_bones[bones['spine.003']]
bones['spine.004'] = bone.name
bone = arm.edit_bones.new('shoulder.L')
@@ -370,7 +370,7 @@ def create(obj):
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones[bones['spine']]
- pbone.rigify_type = 'spines.super_spine'
+ pbone.rigify_type = 'spines.basic_spine'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
@@ -378,11 +378,11 @@ def create(obj):
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
try:
- pbone.rigify_parameters.neck_pos = 5
+ pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
try:
- pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ pbone.rigify_parameters.fk_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
pbone = obj.pose.bones[bones['spine.001']]
@@ -506,13 +506,21 @@ def create(obj):
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
pbone = obj.pose.bones[bones['spine.004']]
- pbone.rigify_type = ''
+ pbone.rigify_type = 'spines.super_head'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ try:
+ pbone.rigify_parameters.connect_chain = True
+ except AttributeError:
+ pass
+ try:
+ pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ except AttributeError:
+ pass
pbone = obj.pose.bones[bones['shoulder.L']]
pbone.rigify_type = 'basic.super_copy'
pbone.lock_location = (False, False, False)
@@ -676,6 +684,7 @@ def create(obj):
bone.select = True
bone.select_head = True
bone.select_tail = True
+ bone.bbone_x = bone.bbone_z = bone.length * 0.05
arm.edit_bones.active = bone
arm.layers = [(x in [3, 7, 10, 13, 16]) for x in range(32)]
diff --git a/rigify/metarigs/Basic/basic_quadruped.py b/rigify/metarigs/Basic/basic_quadruped.py
index 5aa9f657..5282df25 100644
--- a/rigify/metarigs/Basic/basic_quadruped.py
+++ b/rigify/metarigs/Basic/basic_quadruped.py
@@ -165,40 +165,40 @@ def create(obj):
bones = {}
- bone = arm.edit_bones.new('spine')
- bone.head[:] = 0.0000, 1.1044, 0.7633
- bone.tail[:] = 0.0000, 0.9624, 0.7412
+ bone = arm.edit_bones.new('spine.004')
+ bone.head[:] = 0.0000, 0.4418, 0.7954
+ bone.tail[:] = 0.0000, 0.3546, 0.8059
bone.roll = 0.0000
bone.use_connect = False
- bones['spine'] = bone.name
- bone = arm.edit_bones.new('spine.001')
- bone.head[:] = 0.0000, 0.9624, 0.7412
- bone.tail[:] = 0.0000, 0.7755, 0.7418
+ bones['spine.004'] = bone.name
+ bone = arm.edit_bones.new('spine.003')
+ bone.head[:] = 0.0000, 0.4418, 0.7954
+ bone.tail[:] = 0.0000, 0.5547, 0.7568
bone.roll = 0.0000
- bone.use_connect = True
- bone.parent = arm.edit_bones[bones['spine']]
- bones['spine.001'] = bone.name
+ bone.use_connect = False
+ bone.parent = arm.edit_bones[bones['spine.004']]
+ bones['spine.003'] = bone.name
bone = arm.edit_bones.new('spine.002')
- bone.head[:] = 0.0000, 0.7755, 0.7418
- bone.tail[:] = 0.0000, 0.5547, 0.7568
+ bone.head[:] = 0.0000, 0.5547, 0.7568
+ bone.tail[:] = 0.0000, 0.7755, 0.7418
bone.roll = 0.0000
bone.use_connect = True
- bone.parent = arm.edit_bones[bones['spine.001']]
+ bone.parent = arm.edit_bones[bones['spine.003']]
bones['spine.002'] = bone.name
- bone = arm.edit_bones.new('spine.003')
- bone.head[:] = 0.0000, 0.5547, 0.7568
- bone.tail[:] = 0.0000, 0.4418, 0.7954
+ bone = arm.edit_bones.new('spine.001')
+ bone.head[:] = 0.0000, 0.7755, 0.7418
+ bone.tail[:] = 0.0000, 0.9624, 0.7412
bone.roll = 0.0000
bone.use_connect = True
bone.parent = arm.edit_bones[bones['spine.002']]
- bones['spine.003'] = bone.name
- bone = arm.edit_bones.new('spine.004')
- bone.head[:] = 0.0000, 0.4418, 0.7954
- bone.tail[:] = 0.0000, 0.3546, 0.8059
+ bones['spine.001'] = bone.name
+ bone = arm.edit_bones.new('spine')
+ bone.head[:] = 0.0000, 0.9624, 0.7412
+ bone.tail[:] = 0.0000, 1.1044, 0.7633
bone.roll = 0.0000
bone.use_connect = True
- bone.parent = arm.edit_bones[bones['spine.003']]
- bones['spine.004'] = bone.name
+ bone.parent = arm.edit_bones[bones['spine.001']]
+ bones['spine'] = bone.name
bone = arm.edit_bones.new('spine.005')
bone.head[:] = 0.0000, 0.3546, 0.8059
bone.tail[:] = 0.0000, 0.1803, 0.7782
@@ -287,7 +287,7 @@ def create(obj):
bone.head[:] = 0.0000, -0.3618, 0.8375
bone.tail[:] = 0.0000, -0.4253, 0.8585
bone.roll = 0.0000
- bone.use_connect = True
+ bone.use_connect = False
bone.parent = arm.edit_bones[bones['spine.008']]
bones['spine.009'] = bone.name
bone = arm.edit_bones.new('shoulder.L')
@@ -405,37 +405,13 @@ def create(obj):
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones[bones['spine']]
- pbone.rigify_type = 'spines.super_spine'
+ pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False]
- try:
- pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
- except AttributeError:
- pass
- try:
- pbone.rigify_parameters.use_tail = True
- except AttributeError:
- pass
- try:
- pbone.rigify_parameters.tail_pos = 4
- except AttributeError:
- pass
- try:
- pbone.rigify_parameters.pivot_pos = 8
- except AttributeError:
- pass
- try:
- pbone.rigify_parameters.neck_pos = 10
- except AttributeError:
- pass
- try:
- pbone.rigify_parameters.copy_rotation_axes = [True, False, True]
- except AttributeError:
- pass
pbone = obj.pose.bones[bones['spine.001']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
@@ -452,30 +428,42 @@ def create(obj):
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False]
- try:
- pbone.rigify_parameters.tweak_extra_layers = False
- except AttributeError:
- pass
- try:
- pbone.rigify_parameters.tweak_layers = [False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False]
- except AttributeError:
- pass
pbone = obj.pose.bones[bones['spine.003']]
- pbone.rigify_type = ''
+ pbone.rigify_type = 'spines.basic_tail'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False]
+ try:
+ pbone.rigify_parameters.connect_chain = True
+ except AttributeError:
+ pass
+ try:
+ pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ except AttributeError:
+ pass
pbone = obj.pose.bones[bones['spine.004']]
- pbone.rigify_type = ''
+ pbone.rigify_type = 'spines.basic_spine'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ try:
+ pbone.rigify_parameters.pivot_pos = 4
+ except AttributeError:
+ pass
+ try:
+ pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ except AttributeError:
+ pass
+ try:
+ pbone.rigify_parameters.fk_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ except AttributeError:
+ pass
pbone = obj.pose.bones[bones['spine.005']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
@@ -484,14 +472,6 @@ def create(obj):
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
- try:
- pbone.rigify_parameters.neck_pos = 5
- except AttributeError:
- pass
- try:
- pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
- except AttributeError:
- pass
pbone = obj.pose.bones[bones['spine.006']]
pbone.rigify_type = ''
pbone.lock_location = (False, False, False)
@@ -613,13 +593,21 @@ def create(obj):
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
pbone = obj.pose.bones[bones['spine.009']]
- pbone.rigify_type = ''
+ pbone.rigify_type = 'spines.super_head'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ try:
+ pbone.rigify_parameters.connect_chain = True
+ except AttributeError:
+ pass
+ try:
+ pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ except AttributeError:
+ pass
pbone = obj.pose.bones[bones['shoulder.L']]
pbone.rigify_type = 'basic.super_copy'
pbone.lock_location = (False, False, False)
@@ -811,6 +799,7 @@ def create(obj):
bone.select = True
bone.select_head = True
bone.select_tail = True
+ bone.bbone_x = bone.bbone_z = bone.length * 0.05
arm.edit_bones.active = bone
arm.layers = [(x in [3, 4, 7, 10, 13, 16, 19]) for x in range(32)]
diff --git a/rigify/metarigs/human.py b/rigify/metarigs/human.py
index bbba8eed..e4279982 100644
--- a/rigify/metarigs/human.py
+++ b/rigify/metarigs/human.py
@@ -70,10 +70,10 @@ def create(obj):
arm.rigify_layers[5].row = 5
arm.rigify_layers[5].selset = False
arm.rigify_layers[5].group = 6
- arm.rigify_layers[6].name = "Fingers (Tweak)"
+ arm.rigify_layers[6].name = "Fingers (Detail)"
arm.rigify_layers[6].row = 6
arm.rigify_layers[6].selset = False
- arm.rigify_layers[6].group = 4
+ arm.rigify_layers[6].group = 5
arm.rigify_layers[7].name = "Arm.L (IK)"
arm.rigify_layers[7].row = 7
arm.rigify_layers[7].selset = False
@@ -252,7 +252,7 @@ def create(obj):
bone.head[:] = 0.0000, 0.0114, 1.6582
bone.tail[:] = 0.0000, -0.0130, 1.7197
bone.roll = 0.0000
- bone.use_connect = True
+ bone.use_connect = False
bone.parent = arm.edit_bones[bones['spine.003']]
bones['spine.004'] = bone.name
bone = arm.edit_bones.new('shoulder.L')
@@ -1280,7 +1280,7 @@ def create(obj):
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones[bones['spine']]
- pbone.rigify_type = 'spines.super_spine'
+ pbone.rigify_type = 'spines.basic_spine'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
@@ -1288,11 +1288,11 @@ def create(obj):
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
try:
- pbone.rigify_parameters.neck_pos = 5
+ pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
try:
- pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ pbone.rigify_parameters.fk_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
pbone = obj.pose.bones[bones['spine.001']]
@@ -1416,13 +1416,21 @@ def create(obj):
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
pbone = obj.pose.bones[bones['spine.004']]
- pbone.rigify_type = ''
+ pbone.rigify_type = 'spines.super_head'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ try:
+ pbone.rigify_parameters.connect_chain = True
+ except AttributeError:
+ pass
+ try:
+ pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+ except AttributeError:
+ pass
pbone = obj.pose.bones[bones['shoulder.L']]
pbone.rigify_type = 'basic.super_copy'
pbone.lock_location = (False, False, False)
@@ -1956,7 +1964,7 @@ def create(obj):
pbone.rotation_mode = 'QUATERNION'
pbone.bone.layers = [True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
pbone = obj.pose.bones[bones['f_index.01.L']]
- pbone.rigify_type = 'limbs.simple_tentacle'
+ pbone.rigify_type = 'limbs.super_finger'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
@@ -1972,7 +1980,7 @@ def create(obj):
except AttributeError:
pass
pbone = obj.pose.bones[bones['thumb.01.L']]
- pbone.rigify_type = 'limbs.simple_tentacle'
+ pbone.rigify_type = 'limbs.super_finger'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
@@ -1988,7 +1996,7 @@ def create(obj):
except AttributeError:
pass
pbone = obj.pose.bones[bones['f_middle.01.L']]
- pbone.rigify_type = 'limbs.simple_tentacle'
+ pbone.rigify_type = 'limbs.super_finger'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
@@ -2004,7 +2012,7 @@ def create(obj):
except AttributeError:
pass
pbone = obj.pose.bones[bones['f_ring.01.L']]
- pbone.rigify_type = 'limbs.simple_tentacle'
+ pbone.rigify_type = 'limbs.super_finger'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
@@ -2020,7 +2028,7 @@ def create(obj):
except AttributeError:
pass
pbone = obj.pose.bones[bones['f_pinky.01.L']]
- pbone.rigify_type = 'limbs.simple_tentacle'
+ pbone.rigify_type = 'limbs.super_finger'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
@@ -2036,7 +2044,7 @@ def create(obj):
except AttributeError:
pass
pbone = obj.pose.bones[bones['f_index.01.R']]
- pbone.rigify_type = 'limbs.simple_tentacle'
+ pbone.rigify_type = 'limbs.super_finger'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
@@ -2052,7 +2060,7 @@ def create(obj):
except AttributeError:
pass
pbone = obj.pose.bones[bones['thumb.01.R']]
- pbone.rigify_type = 'limbs.simple_tentacle'
+ pbone.rigify_type = 'limbs.super_finger'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
@@ -2068,7 +2076,7 @@ def create(obj):
except AttributeError:
pass
pbone = obj.pose.bones[bones['f_middle.01.R']]
- pbone.rigify_type = 'limbs.simple_tentacle'
+ pbone.rigify_type = 'limbs.super_finger'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
@@ -2084,7 +2092,7 @@ def create(obj):
except AttributeError:
pass
pbone = obj.pose.bones[bones['f_ring.01.R']]
- pbone.rigify_type = 'limbs.simple_tentacle'
+ pbone.rigify_type = 'limbs.super_finger'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
@@ -2100,7 +2108,7 @@ def create(obj):
except AttributeError:
pass
pbone = obj.pose.bones[bones['f_pinky.01.R']]
- pbone.rigify_type = 'limbs.simple_tentacle'
+ pbone.rigify_type = 'limbs.super_finger'
pbone.lock_location = (False, False, False)
pbone.lock_rotation = (False, False, False)
pbone.lock_rotation_w = False
@@ -2710,6 +2718,7 @@ def create(obj):
bone.select = True
bone.select_head = True
bone.select_tail = True
+ bone.bbone_x = bone.bbone_z = bone.length * 0.05
arm.edit_bones.active = bone
arm.layers = [(x in [0, 3, 5, 7, 10, 13, 16]) for x in range(32)]
diff --git a/rigify/rig_ui_template.py b/rigify/rig_ui_template.py
index d7c2e870..bb5a9cbd 100644
--- a/rigify/rig_ui_template.py
+++ b/rigify/rig_ui_template.py
@@ -36,6 +36,7 @@ UI_IMPORTS = [
'import math',
'import json',
'import collections',
+ 'import traceback',
'from math import pi',
'from bpy.props import StringProperty',
'from mathutils import Euler, Matrix, Quaternion, Vector',
@@ -1147,7 +1148,6 @@ class ScriptGenerator(base_generate.GeneratorPlugin):
def finalize(self):
metarig = self.generator.metarig
- id_store = self.generator.id_store
rig_id = self.generator.rig_id
vis_layers = self.obj.data.layers
@@ -1162,23 +1162,27 @@ class ScriptGenerator(base_generate.GeneratorPlugin):
layer_layout += [(l.name, l.row)]
# Generate the UI script
- if id_store.rigify_generate_mode == 'overwrite':
- rig_ui_name = id_store.rigify_rig_ui or 'rig_ui.py'
+ if metarig.data.rigify_rig_basename:
+ rig_ui_name = metarig.data.rigify_rig_basename + '_rig_ui.py'
else:
rig_ui_name = 'rig_ui.py'
- if id_store.rigify_generate_mode == 'overwrite' and rig_ui_name in bpy.data.texts.keys():
- script = bpy.data.texts[rig_ui_name]
- script.clear()
- else:
- script = bpy.data.texts.new("rig_ui.py")
+ script = None
+
+ if metarig.data.rigify_generate_mode == 'overwrite':
+ script = metarig.data.rigify_rig_ui
+
+ if not script and rig_ui_name in bpy.data.texts:
+ script = bpy.data.texts[rig_ui_name]
+
+ if script:
+ script.clear()
+ script.name = rig_ui_name
- rig_ui_old_name = ""
- if id_store.rigify_rig_basename:
- rig_ui_old_name = script.name
- script.name = id_store.rigify_rig_basename + "_rig_ui.py"
+ if script is None:
+ script = bpy.data.texts.new(rig_ui_name)
- id_store.rigify_rig_ui = script.name
+ metarig.data.rigify_rig_ui = script
for s in OrderedDict.fromkeys(self.ui_imports):
script.write(s + "\n")
diff --git a/rigify/rigs/basic/copy_chain.py b/rigify/rigs/basic/copy_chain.py
index 5145d735..a3920ced 100644
--- a/rigify/rigs/basic/copy_chain.py
+++ b/rigify/rigs/basic/copy_chain.py
@@ -22,9 +22,10 @@ import bpy
from ..chain_rigs import SimpleChainRig
+from ...utils.layers import DEF_LAYER
from ...utils.errors import MetarigError
from ...utils.rig import connected_children_names
-from ...utils.naming import strip_org, make_deformer_name
+from ...utils.naming import make_derived_name
from ...utils.widgets_basic import create_bone_widget
from ...base_rig import BaseRig, stage
@@ -41,7 +42,12 @@ class Rig(SimpleChainRig):
""" Gather and validate data about the rig.
"""
self.make_controls = self.params.make_controls
- self.make_deforms = self.params.make_deforms
+
+ deform = self.params.make_deforms
+ rename = self.params.rename_to_deform
+
+ self.make_deforms = deform and not rename
+ self.rename_deforms = deform and rename
##############################
# Control chain
@@ -92,6 +98,20 @@ class Rig(SimpleChainRig):
if self.make_deforms:
super().rig_deform_chain()
+ ##############################
+ # Rename To Deform
+
+ def finalize(self):
+ if self.rename_deform:
+ new_names = [ self.rename_bone(name, make_derived_name(name, 'def')) for name in self.bones.org ]
+
+ for name in new_names:
+ bone = self.get_bone(name).bone
+ bone.use_deform = True
+ bone.layers = DEF_LAYER
+
+ ##############################
+ # Parameter UI
@classmethod
def add_parameters(self, params):
@@ -101,6 +121,11 @@ class Rig(SimpleChainRig):
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")
+ params.rename_to_deform = bpy.props.BoolProperty(
+ name = "Rename To Deform",
+ default = False,
+ description = "Rename the original bone itself to use as deform bone (advanced feature)"
+ )
@classmethod
def parameters_ui(self, layout, params):
@@ -111,6 +136,10 @@ class Rig(SimpleChainRig):
r = layout.row()
r.prop(params, "make_deforms")
+ if params.make_deforms:
+ r = layout.row()
+ r.prop(params, "rename_to_deform")
+
def create_sample(obj):
""" Create a sample metarig for this rig type.
diff --git a/rigify/rigs/basic/pivot.py b/rigify/rigs/basic/pivot.py
new file mode 100644
index 00000000..e5d31659
--- /dev/null
+++ b/rigify/rigs/basic/pivot.py
@@ -0,0 +1,236 @@
+#====================== BEGIN GPL LICENSE BLOCK ======================
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+#======================= END GPL LICENSE BLOCK ========================
+
+# <pep8 compliant>
+
+import bpy
+
+from ...base_rig import BaseRig
+
+from ...utils.naming import make_derived_name
+from ...utils.bones import set_bone_widget_transform
+from ...utils.widgets_basic import create_cube_widget, create_pivot_widget
+from ...utils.switch_parent import SwitchParentBuilder
+
+
+class Rig(BaseRig):
+ """ A rig providing a rotation pivot control that can be moved. """
+ def find_org_bones(self, pose_bone):
+ return pose_bone.name
+
+
+ def initialize(self):
+ self.make_control = self.params.make_extra_control
+ self.make_pivot = self.params.make_control or not self.make_control
+ self.make_deform = self.params.make_extra_deform
+
+
+ def generate_bones(self):
+ org = self.bones.org
+
+ if self.make_control:
+ self.bones.ctrl.master = name = self.copy_bone(org, make_derived_name(org, 'ctrl'), parent=True)
+
+ if self.make_pivot:
+ self.bones.ctrl.pivot = self.copy_bone(org, make_derived_name(org, 'ctrl', '_pivot'))
+
+ if self.params.make_parent_switch:
+ self.build_parent_switch(name)
+
+ if self.params.register_parent:
+ self.register_parent(name, self.get_parent_tags())
+
+ else:
+ self.bones.ctrl.pivot = self.copy_bone(org, make_derived_name(org, 'ctrl'), parent=True)
+
+ if self.make_deform:
+ self.bones.deform = self.copy_bone(org, make_derived_name(org, 'def'), bbone=True)
+
+
+ def build_parent_switch(self, master_name):
+ pbuilder = SwitchParentBuilder(self.generator)
+
+ org_parent = self.get_bone_parent(self.bones.org)
+ parents = [org_parent] if org_parent else []
+
+ pbuilder.build_child(
+ self, master_name,
+ context_rig=self.rigify_parent, allow_self=True,
+ prop_name="Parent ({})".format(master_name),
+ extra_parents=parents, select_parent=org_parent,
+ controls=lambda: self.bones.ctrl.flatten()
+ )
+
+ def get_parent_tags(self):
+ tags = {t.strip() for t in self.params.register_parent_tags.split(',')}
+
+ if self.params.make_parent_switch:
+ tags.add('child')
+
+ tags.discard('')
+ return tags
+
+ def register_parent(self, master_name, tags):
+ pbuilder = SwitchParentBuilder(self.generator)
+
+ inject = self.rigify_parent if 'injected' in tags else None
+
+ pbuilder.register_parent(
+ self, self.bones.org, name=master_name,
+ inject_into=inject, tags=tags
+ )
+
+
+ def parent_bones(self):
+ ctrl = self.bones.ctrl
+
+ if self.make_pivot:
+ if self.make_control:
+ self.set_bone_parent(ctrl.pivot, ctrl.master, use_connect=False)
+
+ self.set_bone_parent(self.bones.org, ctrl.pivot, use_connect=False)
+
+ else:
+ self.set_bone_parent(self.bones.org, ctrl.master, use_connect=False)
+
+ if self.make_deform:
+ self.set_bone_parent(self.bones.deform, self.bones.org, use_connect=False)
+
+
+ def configure_bones(self):
+ if self.make_control:
+ self.copy_bone_properties(self.bones.org, self.bones.ctrl.master)
+
+ else:
+ self.copy_bone_properties(self.bones.org, self.bones.ctrl.pivot)
+
+
+ def rig_bones(self):
+ if self.make_pivot:
+ self.make_constraint(
+ self.bones.org, 'COPY_LOCATION', self.bones.ctrl.pivot,
+ space='LOCAL', invert_xyz=(True,)*3
+ )
+
+
+ def generate_widgets(self):
+ if self.make_pivot:
+ create_pivot_widget(self.obj, self.bones.ctrl.pivot, square=True, axis_size=2.0)
+
+ if self.make_control:
+ set_bone_widget_transform(self.obj, self.bones.ctrl.master, self.bones.org)
+
+ create_cube_widget(self.obj, self.bones.ctrl.master, radius=0.5)
+
+
+ @classmethod
+ def add_parameters(self, params):
+ params.make_control = bpy.props.BoolProperty(
+ name = "Control",
+ default = True,
+ description = "Create a control bone for the copy"
+ )
+
+ params.make_parent_switch = bpy.props.BoolProperty(
+ name = "Switchable Parent",
+ default = False,
+ description = "Allow switching the parent of the master control"
+ )
+
+ params.register_parent = bpy.props.BoolProperty(
+ name = "Register Parent",
+ default = False,
+ description = "Register the control as a switchable parent candidate"
+ )
+
+ params.register_parent_tags = bpy.props.StringProperty(
+ name = "Parent Tags",
+ default = "",
+ description = "Comma-separated tags to use for the registered parent"
+ )
+
+ params.make_extra_control = bpy.props.BoolProperty(
+ name = "Extra Control",
+ default = False,
+ description = "Create an optional control"
+ )
+
+ params.make_extra_deform = bpy.props.BoolProperty(
+ name = "Extra Deform",
+ default = False,
+ description = "Create an optional deform bone"
+ )
+
+
+ @classmethod
+ def parameters_ui(self, layout, params):
+ r = layout.row()
+ r.prop(params, "make_extra_control", text="Master Control")
+
+ if params.make_extra_control:
+ layout.prop(params, "make_parent_switch")
+ layout.prop(params, "register_parent")
+
+ r = layout.row()
+ r.active = params.register_parent
+ r.prop(params, "register_parent_tags", text="Tags")
+
+ layout.prop(params, "make_control", text="Pivot Control")
+
+ r = layout.row()
+ r.prop(params, "make_extra_deform", text="Deform Bone")
+
+
+def create_sample(obj):
+ """ Create a sample metarig for this rig type.
+ """
+ # generated by rigify.utils.write_metarig
+ bpy.ops.object.mode_set(mode='EDIT')
+ arm = obj.data
+
+ bones = {}
+
+ bone = arm.edit_bones.new('pivot')
+ bone.head[:] = 0.0000, 0.0000, 0.0000
+ bone.tail[:] = 0.0000, 0.5000, 0.0000
+ bone.roll = 0.0000
+ bone.use_connect = False
+ bones['pivot'] = bone.name
+
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pbone = obj.pose.bones[bones['pivot']]
+ pbone.rigify_type = 'basic.pivot'
+ pbone.lock_location = (False, False, False)
+ pbone.lock_rotation = (False, False, False)
+ pbone.lock_rotation_w = False
+ pbone.lock_scale = (False, False, False)
+ pbone.rotation_mode = 'QUATERNION'
+
+ bpy.ops.object.mode_set(mode='EDIT')
+ for bone in arm.edit_bones:
+ bone.select = False
+ bone.select_head = False
+ bone.select_tail = False
+ for b in bones:
+ bone = arm.edit_bones[bones[b]]
+ bone.select = True
+ bone.select_head = True
+ bone.select_tail = True
+ arm.edit_bones.active = bone
+
+ return bones
diff --git a/rigify/rigs/basic/super_copy.py b/rigify/rigs/basic/super_copy.py
index 5abbf22e..f55dce68 100644
--- a/rigify/rigs/basic/super_copy.py
+++ b/rigify/rigs/basic/super_copy.py
@@ -22,9 +22,12 @@ import bpy
from ...base_rig import BaseRig
+from ...utils.layers import DEF_LAYER
from ...utils.naming import strip_org, make_deformer_name
from ...utils.widgets_basic import create_bone_widget, create_circle_widget
+from itertools import repeat
+
class Rig(BaseRig):
""" A "copy" rig. All it does is duplicate the original bone and
@@ -43,7 +46,14 @@ class Rig(BaseRig):
self.make_control = self.params.make_control
self.make_widget = self.params.make_widget
- self.make_deform = self.params.make_deform
+
+ deform = self.params.make_deform
+ rename = self.params.rename_to_deform
+
+ self.make_deform = deform and not rename
+ self.rename_deform = deform and rename
+
+ self.relink = self.params.relink_constraints
def generate_bones(self):
@@ -64,6 +74,18 @@ class Rig(BaseRig):
if self.make_deform:
self.set_bone_parent(bones.deform, bones.org, use_connect=False)
+ if self.relink:
+ self.generator.disable_auto_parent(bones.org)
+
+ parent_spec = self.params.parent_bone
+ if parent_spec:
+ old_parent = self.get_bone_parent(bones.org)
+ new_parent = self.find_relink_target(parent_spec, old_parent or '') or None
+ self.set_bone_parent(bones.org, new_parent)
+
+ if self.make_control:
+ self.set_bone_parent(bones.ctrl, new_parent)
+
def configure_bones(self):
bones = self.bones
@@ -75,9 +97,53 @@ class Rig(BaseRig):
def rig_bones(self):
bones = self.bones
+ if self.relink:
+ for con in self.get_bone(bones.org).constraints:
+ parts = con.name.split('@')
+
+ if len(parts) > 1:
+ self.relink_constraint(con, parts[1:])
+
if self.make_control:
# Constrain the original bone.
- self.make_constraint(bones.org, 'COPY_TRANSFORMS', bones.ctrl)
+ self.make_constraint(bones.org, 'COPY_TRANSFORMS', bones.ctrl, insert_index=0)
+
+ def relink_constraint(self, con, specs):
+ if con.type == 'ARMATURE':
+ if len(specs) == 1:
+ specs = repeat(specs[0])
+ elif len(specs) != len(con.specs):
+ self.report_error("Constraint {} actually has {} targets", con.name, len(con.targets))
+
+ for tgt, spec in zip(con.targets, specs):
+ tgt.subtarget = self.find_relink_target(spec, tgt.subtarget)
+
+ else:
+ if len(specs) > 1:
+ self.report_error("Only the Armature constraint can have multiple '@' targets: {}", con.name)
+
+ con.subtarget = self.find_relink_target(specs[0], con.subtarget)
+
+ def find_relink_target(self, spec, old_target):
+ if spec == '':
+ return old_target
+ elif spec in {'DEF', 'MCH'}:
+ spec = spec + '-' + strip_org(old_target)
+
+ if spec not in self.obj.pose.bones:
+ # Hack: allow referring to copy rigs using Rename To Deform as DEF
+ if old_target.startswith('ORG-') and spec == make_deformer_name(strip_org(old_target)):
+ from . import copy_chain
+
+ owner = self.generator.bone_owners.get(old_target)
+
+ if ((isinstance(owner, Rig) and owner.rename_deform) or
+ (isinstance(owner, copy_chain.Rig) and owner.rename_deforms)):
+ return old_target
+
+ self.report_error("Cannot find bone '{}' for relinking", spec)
+
+ return spec
def generate_widgets(self):
@@ -91,6 +157,15 @@ class Rig(BaseRig):
create_bone_widget(self.obj, bones.ctrl)
+ def finalize(self):
+ if self.rename_deform:
+ new_name = self.rename_bone(self.bones.org, make_deformer_name(self.org_name))
+
+ bone = self.get_bone(new_name).bone
+ bone.use_deform = True
+ bone.layers = DEF_LAYER
+
+
@classmethod
def add_parameters(self, params):
""" Add the parameters of this rig type to the
@@ -114,6 +189,24 @@ class Rig(BaseRig):
description = "Create a deform bone for the copy"
)
+ params.rename_to_deform = bpy.props.BoolProperty(
+ name = "Rename To Deform",
+ default = False,
+ description = "Rename the original bone itself to use as deform bone (advanced feature)"
+ )
+
+ 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 '@DEF' or '@MCH' to simply prepend 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 DEF or MCH will prepend the prefix instead"
+ )
+
@classmethod
def parameters_ui(self, layout, params):
@@ -127,6 +220,17 @@ class Rig(BaseRig):
r = layout.row()
r.prop(params, "make_deform")
+ if params.make_deform:
+ r = layout.row()
+ r.prop(params, "rename_to_deform")
+
+ r = layout.row()
+ r.prop(params, "relink_constraints")
+
+ if params.relink_constraints:
+ r = layout.row()
+ r.prop(params, "parent_bone")
+
def create_sample(obj):
""" Create a sample metarig for this rig type.
diff --git a/rigify/rigs/chain_rigs.py b/rigify/rigs/chain_rigs.py
index 3f53cd69..fc070eb1 100644
--- a/rigify/rigs/chain_rigs.py
+++ b/rigify/rigs/chain_rigs.py
@@ -82,10 +82,10 @@ class SimpleChainRig(BaseRig):
@stage.generate_widgets
def make_control_widgets(self):
- for ctrl in self.bones.ctrl.fk:
- self.make_control_widget(ctrl)
+ for args in zip(count(0), self.bones.ctrl.fk):
+ self.make_control_widget(*args)
- def make_control_widget(self, ctrl):
+ def make_control_widget(self, i, ctrl):
create_bone_widget(self.obj, ctrl)
##############################
diff --git a/rigify/rigs/experimental/super_chain.py b/rigify/rigs/experimental/super_chain.py
index df0facdf..3f7ca5d6 100644
--- a/rigify/rigs/experimental/super_chain.py
+++ b/rigify/rigs/experimental/super_chain.py
@@ -714,10 +714,10 @@ def add_parameters(params):
)
params.bbones = bpy.props.IntProperty(
- name='bbone segments',
- default=10,
- min=1,
- description='Number of segments'
+ name = 'B-Bone Segments',
+ default = 10,
+ min = 1,
+ description = 'Number of B-Bone segments'
)
params.wgt_offset = bpy.props.FloatProperty(
diff --git a/rigify/rigs/limbs/arm.py b/rigify/rigs/limbs/arm.py
index 98a3c50f..e79edc5c 100644
--- a/rigify/rigs/limbs/arm.py
+++ b/rigify/rigs/limbs/arm.py
@@ -21,12 +21,15 @@
import bpy
from itertools import count
+from mathutils import Matrix
-from ...utils.bones import BoneDict, compute_chain_x_axis, align_bone_x_axis, align_bone_z_axis
+from ...utils.bones import put_bone, compute_chain_x_axis, align_bone_x_axis, align_bone_z_axis
from ...utils.naming import make_derived_name
from ...utils.misc import map_list
+from ...utils.widgets import adjust_widget_transform_mesh
from ..widgets import create_hand_widget
+from ...utils.widgets_basic import create_circle_widget
from ...base_rig import stage
@@ -42,6 +45,8 @@ class Rig(BaseLimbRig):
super().initialize()
+ self.make_wrist_pivot = self.params.make_ik_wrist_pivot
+
def prepare_bones(self):
orgs = self.bones.org.main
@@ -62,16 +67,76 @@ class Rig(BaseLimbRig):
def register_switch_parents(self, pbuilder):
super().register_switch_parents(pbuilder)
- pbuilder.register_parent(self, self.bones.org.main[2], exclude_self=True)
+ pbuilder.register_parent(self, self.bones.org.main[2], exclude_self=True, tags={'limb_end'})
def make_ik_ctrl_widget(self, ctrl):
create_hand_widget(self.obj, ctrl)
####################################################
+ # Palm Pivot
+
+ def get_ik_input_bone(self):
+ if self.make_wrist_pivot:
+ return self.bones.mch.ik_wrist
+ else:
+ return self.get_ik_control_output()
+
+ def get_extra_ik_controls(self):
+ controls = super().get_extra_ik_controls()
+ if self.make_wrist_pivot:
+ controls += [self.bones.ctrl.ik_wrist]
+ return controls
+
+ @stage.generate_bones
+ def make_wrist_pivot_control(self):
+ if self.make_wrist_pivot:
+ org = self.bones.org.main[2]
+ self.bones.ctrl.ik_wrist = self.make_wrist_pivot_bone(org)
+ self.bones.mch.ik_wrist = self.copy_bone(org, make_derived_name(org, 'mch', '_ik_wrist'), scale=0.25)
+
+ def make_wrist_pivot_bone(self, org):
+ name = self.copy_bone(org, make_derived_name(org, 'ctrl', '_ik_wrist'), scale=0.5)
+ put_bone(self.obj, name, self.get_bone(org).tail)
+ return name
+
+ @stage.parent_bones
+ def parent_wrist_pivot_control(self):
+ if self.make_wrist_pivot:
+ ctrl = self.bones.ctrl.ik_wrist
+ self.set_bone_parent(ctrl, self.get_ik_control_output())
+ self.set_bone_parent(self.bones.mch.ik_wrist, ctrl)
+
+ @stage.generate_widgets
+ def make_wrist_pivot_widget(self):
+ if self.make_wrist_pivot:
+ ctrl = self.bones.ctrl.ik_wrist
+
+ if self.main_axis == 'x':
+ obj = create_circle_widget(self.obj, ctrl, head_tail=-0.3, head_tail_x=0.5)
+ else:
+ obj = create_circle_widget(self.obj, ctrl, head_tail=0.5, head_tail_x=-0.3)
+
+ if obj:
+ org_bone = self.get_bone(self.bones.org.main[2])
+ offset = org_bone.head - self.get_bone(ctrl).head
+ adjust_widget_transform_mesh(obj, Matrix.Translation(offset))
+
+ ####################################################
# Settings
@classmethod
+ def add_parameters(self, params):
+ super().add_parameters(params)
+
+ params.make_ik_wrist_pivot = bpy.props.BoolProperty(
+ name="IK Wrist Pivot", default=False,
+ description="Make an extra IK hand control pivoting around the tip of the hand"
+ )
+
+ @classmethod
def parameters_ui(self, layout, params):
+ layout.prop(params, "make_ik_wrist_pivot")
+
super().parameters_ui(layout, params, 'Hand')
diff --git a/rigify/rigs/limbs/leg.py b/rigify/rigs/limbs/leg.py
index dbdd20cb..b409d009 100644
--- a/rigify/rigs/limbs/leg.py
+++ b/rigify/rigs/limbs/leg.py
@@ -22,13 +22,14 @@ import bpy
import math
from itertools import count
-from mathutils import Vector
+from mathutils import Vector, Matrix
from ...utils.rig import is_rig_base_bone
from ...utils.bones import align_chain_x_axis, align_bone_x_axis, align_bone_y_axis, align_bone_z_axis
from ...utils.bones import align_bone_to_axis, flip_bone, put_bone, align_bone_orientation
from ...utils.naming import make_derived_name
-from ...utils.misc import map_list
+from ...utils.misc import map_list, matrix_from_axis_roll, matrix_from_axis_pair
+from ...utils.widgets import adjust_widget_transform_mesh
from ..widgets import create_foot_widget, create_ballsocket_widget
@@ -62,10 +63,18 @@ class Rig(BaseLimbRig):
super().initialize()
+ self.pivot_type = self.params.foot_pivot_type
+ self.heel_euler_order = 'ZXY' if self.main_axis == 'x' else 'XZY'
+
+ assert self.pivot_type in {'ANKLE', 'TOE', 'ANKLE_TOE'}
+
def prepare_bones(self):
orgs = self.bones.org.main
+ foot = self.get_bone(orgs[2])
- foot_x = self.vector_without_z(self.get_bone(orgs[2]).y_axis).cross((0, 0, -1))
+ ik_y_axis = (0, 1, 0)
+ foot_y_axis = -self.vector_without_z(foot.y_axis)
+ foot_x = foot_y_axis.cross((0, 0, 1))
if self.params.rotation_axis == 'automatic':
align_chain_x_axis(self.obj, orgs[0:2])
@@ -84,6 +93,12 @@ class Rig(BaseLimbRig):
align_bone_z_axis(self.obj, orgs[2], foot_x)
align_bone_z_axis(self.obj, orgs[3], -foot_x)
+ else:
+ ik_y_axis = foot_y_axis
+
+ # Orientation of the IK main and roll control bones
+ self.ik_matrix = matrix_from_axis_roll(ik_y_axis, 0)
+ self.roll_matrix = matrix_from_axis_pair(ik_y_axis, foot_x, self.main_axis)
####################################################
# EXTRA BONES
@@ -92,6 +107,8 @@ class Rig(BaseLimbRig):
# heel:
# Heel location marker bone
# ctrl:
+ # ik_spin:
+ # Toe spin control.
# heel:
# Foot roll control
# mch:
@@ -104,31 +121,71 @@ class Rig(BaseLimbRig):
# IK controls
def get_extra_ik_controls(self):
- return [self.bones.ctrl.heel]
+ controls = super().get_extra_ik_controls() + [self.bones.ctrl.heel]
+ if self.pivot_type == 'ANKLE_TOE':
+ controls += [self.bones.ctrl.ik_spin]
+ return controls
def make_ik_control_bone(self, orgs):
name = self.copy_bone(orgs[2], make_derived_name(orgs[2], 'ctrl', '_ik'))
-
- if self.params.rotation_axis == 'automatic' or self.params.auto_align_extremity:
- align_bone_to_axis(self.obj, name, 'y', flip=True)
-
+ if self.pivot_type == 'TOE':
+ put_bone(self.obj, name, self.get_bone(name).tail, matrix=self.ik_matrix)
else:
- flip_bone(self.obj, name)
-
- bone = self.get_bone(name)
- bone.tail[2] = bone.head[2]
- bone.roll = 0
-
+ put_bone(self.obj, name, None, matrix=self.ik_matrix)
return name
+ def build_ik_pivot(self, ik_name, **args):
+ heel_bone = self.get_bone(self.bones.org.heel)
+ args = {
+ 'position': (heel_bone.head + heel_bone.tail)/2,
+ **args
+ }
+ return super().build_ik_pivot(ik_name, **args)
+
def register_switch_parents(self, pbuilder):
super().register_switch_parents(pbuilder)
- pbuilder.register_parent(self, self.bones.org.main[2], exclude_self=True)
+ pbuilder.register_parent(self, self.bones.org.main[2], exclude_self=True, tags={'limb_end'})
def make_ik_ctrl_widget(self, ctrl):
- create_foot_widget(self.obj, ctrl)
+ obj = create_foot_widget(self.obj, ctrl)
+ if self.pivot_type != 'TOE':
+ ctrl = self.get_bone(ctrl)
+ org = self.get_bone(self.bones.org.main[2])
+ offset = org.tail - (ctrl.custom_shape_transform or ctrl).head
+ adjust_widget_transform_mesh(obj, Matrix.Translation(offset))
+
+ ####################################################
+ # IK pivot controls
+
+ def get_ik_pivot_output(self):
+ if self.pivot_type == 'ANKLE_TOE':
+ return self.bones.ctrl.ik_spin
+ else:
+ return self.get_ik_control_output()
+
+ @stage.generate_bones
+ def make_ik_pivot_controls(self):
+ if self.pivot_type == 'ANKLE_TOE':
+ self.bones.ctrl.ik_spin = self.make_ik_spin_bone(self.bones.org.main)
+
+ def make_ik_spin_bone(self, orgs):
+ name = self.copy_bone(orgs[2], make_derived_name(orgs[2], 'ctrl', '_spin_ik'))
+ put_bone(self.obj, name, self.get_bone(orgs[3]).head, matrix=self.ik_matrix, scale=0.5)
+ return name
+
+ @stage.parent_bones
+ def parent_ik_pivot_controls(self):
+ if self.pivot_type == 'ANKLE_TOE':
+ self.set_bone_parent(self.bones.ctrl.ik_spin, self.get_ik_control_output())
+
+ @stage.generate_widgets
+ def make_ik_spin_control_widget(self):
+ if self.pivot_type == 'ANKLE_TOE':
+ obj = create_ballsocket_widget(self.obj, self.bones.ctrl.ik_spin, size=0.75)
+ rotfix = Matrix.Rotation(math.pi/2, 4, self.main_axis.upper())
+ adjust_widget_transform_mesh(obj, rotfix, local=True)
####################################################
# Heel control
@@ -136,25 +193,19 @@ class Rig(BaseLimbRig):
@stage.generate_bones
def make_heel_control_bone(self):
org = self.bones.org.main[2]
- name = self.copy_bone(org, make_derived_name(org, 'ctrl', '_heel_ik'), scale=1/2)
+ name = self.copy_bone(org, make_derived_name(org, 'ctrl', '_heel_ik'))
+ put_bone(self.obj, name, None, matrix=self.roll_matrix, scale=0.5)
self.bones.ctrl.heel = name
- self.align_roll_bone(org, name, -self.vector_without_z(self.get_bone(org).vector))
-
@stage.parent_bones
def parent_heel_control_bone(self):
- self.set_bone_parent(self.bones.ctrl.heel, self.bones.ctrl.ik)
+ self.set_bone_parent(self.bones.ctrl.heel, self.get_ik_pivot_output(), inherit_scale='AVERAGE')
@stage.configure_bones
def configure_heel_control_bone(self):
bone = self.get_bone(self.bones.ctrl.heel)
bone.lock_location = True, True, True
-
- if self.main_axis == 'x':
- bone.lock_rotation = False, False, True
- else:
- bone.lock_rotation = True, False, False
-
+ bone.rotation_mode = self.heel_euler_order
bone.lock_scale = True, True, True
@stage.generate_widgets
@@ -173,34 +224,27 @@ class Rig(BaseLimbRig):
def make_roll_mch_bones(self, foot, toe, heel):
foot_bone = self.get_bone(foot)
heel_bone = self.get_bone(heel)
- axis = -self.vector_without_z(foot_bone.vector)
-
- roll1 = self.copy_bone(foot, make_derived_name(heel, 'mch', '_roll1'))
- flip_bone(self.obj, roll1)
- self.align_roll_bone(foot, roll1, -foot_bone.vector)
+ heel_middle = (heel_bone.head + heel_bone.tail) / 2
- roll2 = self.copy_bone(toe, make_derived_name(heel, 'mch', '_roll2'), scale=1/4)
-
- put_bone(self.obj, roll2, (heel_bone.head + heel_bone.tail) / 2)
- self.align_roll_bone(foot, roll2, -axis)
+ result = self.copy_bone(foot, make_derived_name(foot, 'mch', '_roll'), scale=0.25)
+ roll1 = self.copy_bone(toe, make_derived_name(heel, 'mch', '_roll1'), scale=0.3)
+ roll2 = self.copy_bone(toe, make_derived_name(heel, 'mch', '_roll2'), scale=0.3)
rock1 = self.copy_bone(heel, make_derived_name(heel, 'mch', '_rock1'))
-
- align_bone_to_axis(self.obj, rock1, 'y', roll=0, length=heel_bone.length/2, flip=True)
- align_bone_y_axis(self.obj, rock1, axis)
-
rock2 = self.copy_bone(heel, make_derived_name(heel, 'mch', '_rock2'))
- align_bone_to_axis(self.obj, rock2, 'y', roll=0, length=heel_bone.length/2)
- align_bone_y_axis(self.obj, rock2, axis)
+ put_bone(self.obj, roll1, None, matrix=self.roll_matrix)
+ put_bone(self.obj, roll2, heel_middle, matrix=self.roll_matrix)
+ put_bone(self.obj, rock1, heel_bone.tail, matrix=self.roll_matrix, scale=0.5)
+ put_bone(self.obj, rock2, heel_bone.head, matrix=self.roll_matrix, scale=0.5)
- return [ rock2, rock1, roll2, roll1 ]
+ return [ rock2, rock1, roll2, roll1, result ]
@stage.parent_bones
def parent_roll_mch_chain(self):
chain = self.bones.mch.heel
- self.set_bone_parent(chain[0], self.bones.ctrl.ik)
+ self.set_bone_parent(chain[0], self.get_ik_pivot_output())
self.parent_bone_chain(chain)
@stage.rig_bones
@@ -208,28 +252,37 @@ class Rig(BaseLimbRig):
self.rig_roll_mch_bones(self.bones.mch.heel, self.bones.ctrl.heel, self.bones.org.heel)
def rig_roll_mch_bones(self, chain, heel, org_heel):
- rock2, rock1, roll2, roll1 = chain
+ rock2, rock1, roll2, roll1, result = chain
+
+ # This order is required for correct working of the constraints
+ for bone in chain:
+ self.get_bone(bone).rotation_mode = self.heel_euler_order
- self.make_constraint(roll1, 'COPY_ROTATION', heel, space='LOCAL')
- self.make_constraint(roll2, 'COPY_ROTATION', heel, space='LOCAL')
+ self.make_constraint(roll1, 'COPY_ROTATION', heel, space='POSE')
if self.main_axis == 'x':
- self.make_constraint(roll1, 'LIMIT_ROTATION', use_limit_x=True, max_x=DEG_360, space='LOCAL')
- self.make_constraint(roll2, 'LIMIT_ROTATION', use_limit_xyz=ALL_TRUE, min_x=-DEG_360, space='LOCAL')
+ self.make_constraint(roll2, 'COPY_ROTATION', heel, space='LOCAL', use_xyz=(True, False, False))
+ self.make_constraint(roll2, 'LIMIT_ROTATION', min_x=-DEG_360, space='LOCAL')
else:
- self.make_constraint(roll1, 'LIMIT_ROTATION', use_limit_z=True, max_z=DEG_360, space='LOCAL')
- self.make_constraint(roll2, 'LIMIT_ROTATION', use_limit_xyz=ALL_TRUE, min_z=-DEG_360, space='LOCAL')
+ self.make_constraint(roll2, 'COPY_ROTATION', heel, space='LOCAL', use_xyz=(False, False, True))
+ self.make_constraint(roll2, 'LIMIT_ROTATION', min_z=-DEG_360, space='LOCAL')
direction = self.get_main_axis(self.get_bone(heel)).dot(self.get_bone(org_heel).vector)
if direction < 0:
rock2, rock1 = rock1, rock2
- self.make_constraint(rock1, 'COPY_ROTATION', heel, space='LOCAL')
- self.make_constraint(rock2, 'COPY_ROTATION', heel, space='LOCAL')
+ self.make_constraint(
+ rock1, 'COPY_ROTATION', heel, space='LOCAL',
+ use_xyz=(False, True, False),
+ )
+ self.make_constraint(
+ rock2, 'COPY_ROTATION', heel, space='LOCAL',
+ use_xyz=(False, True, False),
+ )
- self.make_constraint(rock1, 'LIMIT_ROTATION', use_limit_xyz=ALL_TRUE, max_y=DEG_360, space='LOCAL')
- self.make_constraint(rock2, 'LIMIT_ROTATION', use_limit_xyz=ALL_TRUE, min_y=-DEG_360, space='LOCAL')
+ self.make_constraint(rock1, 'LIMIT_ROTATION', max_y=DEG_360, space='LOCAL')
+ self.make_constraint(rock2, 'LIMIT_ROTATION', min_y=-DEG_360, space='LOCAL')
####################################################
@@ -237,7 +290,7 @@ class Rig(BaseLimbRig):
def parent_fk_parent_bone(self, i, parent_mch, prev_ctrl, org, prev_org):
if i == 3:
- align_bone_orientation(self.obj, parent_mch, self.bones.mch.heel[-2])
+ align_bone_orientation(self.obj, parent_mch, self.bones.mch.heel[2])
self.set_bone_parent(parent_mch, prev_org, use_connect=True)
@@ -246,7 +299,7 @@ class Rig(BaseLimbRig):
def rig_fk_parent_bone(self, i, parent_mch, org):
if i == 3:
- con = self.make_constraint(parent_mch, 'COPY_TRANSFORMS', self.bones.mch.heel[-2])
+ con = self.make_constraint(parent_mch, 'COPY_TRANSFORMS', self.bones.mch.heel[2])
self.make_driver(con, 'influence', variables=[(self.prop_bone, 'IK_FK')], polynomial=[1.0, -1.0])
@@ -257,8 +310,6 @@ class Rig(BaseLimbRig):
####################################################
# IK system MCH
- ik_input_head_tail = 1.0
-
def get_ik_input_bone(self):
return self.bones.mch.heel[-1]
@@ -266,14 +317,35 @@ class Rig(BaseLimbRig):
def parent_ik_mch_chain(self):
super().parent_ik_mch_chain()
- self.set_bone_parent(self.bones.mch.ik_target, self.bones.ctrl.heel)
+ self.set_bone_parent(self.bones.mch.ik_target, self.bones.mch.heel[-1])
####################################################
# Settings
@classmethod
+ def add_parameters(self, params):
+ super().add_parameters(params)
+
+ items = [
+ ('ANKLE', 'Ankle',
+ 'The foots pivots at the ankle'),
+ ('TOE', 'Toe',
+ 'The foot pivots around the base of the toe'),
+ ('ANKLE_TOE', 'Ankle and Toe',
+ 'The foots pivots at the ankle, with extra toe pivot'),
+ ]
+
+ params.foot_pivot_type = bpy.props.EnumProperty(
+ items = items,
+ name = "Foot Pivot",
+ default = 'ANKLE_TOE'
+ )
+
+ @classmethod
def parameters_ui(self, layout, params):
+ layout.prop(params, 'foot_pivot_type')
+
super().parameters_ui(layout, params, 'Foot')
diff --git a/rigify/rigs/limbs/limb_rigs.py b/rigify/rigs/limbs/limb_rigs.py
index 81079c05..f1eb8639 100644
--- a/rigify/rigs/limbs/limb_rigs.py
+++ b/rigify/rigs/limbs/limb_rigs.py
@@ -23,12 +23,12 @@ import json
from ...utils.animation import add_generic_snap_fk_to_ik, add_fk_ik_snap_buttons
from ...utils.rig import connected_children_names
-from ...utils.bones import BoneDict, put_bone, compute_chain_x_axis, align_bone_orientation
-from ...utils.bones import align_bone_x_axis, align_bone_y_axis, align_bone_z_axis
+from ...utils.bones import BoneDict, put_bone, compute_chain_x_axis, align_bone_orientation, set_bone_widget_transform
from ...utils.naming import strip_org, make_derived_name
from ...utils.layers import ControlLayersOption
from ...utils.misc import pairwise_nozip, padnone, map_list
from ...utils.switch_parent import SwitchParentBuilder
+from ...utils.components import CustomPivotControl
from ...base_rig import stage, BaseRig
@@ -64,6 +64,7 @@ class BaseLimbRig(BaseRig):
self.segments = self.params.segments
self.bbone_segments = self.params.bbones
+ self.use_ik_pivot = self.params.make_custom_pivot
rot_axis = self.params.rotation_axis
@@ -124,15 +125,6 @@ class BaseLimbRig(BaseRig):
bone = self.get_bone(org)
return bone.head + bone.vector * (seg / self.segments)
- def align_roll_bone(self, org, name, y_axis):
- if y_axis:
- align_bone_y_axis(self.obj, name, y_axis)
-
- if self.main_axis == 'x':
- align_bone_x_axis(self.obj, name, self.get_bone(org).x_axis)
- else:
- align_bone_z_axis(self.obj, name, self.get_bone(org).z_axis)
-
@staticmethod
def vector_without_z(vector):
return Vector((vector[0], vector[1], 0))
@@ -154,6 +146,8 @@ class BaseLimbRig(BaseRig):
# IK controls
# ik_vispole
# IK pole visualization.
+ # ik_pivot
+ # Custom IK pivot (optional).
# mch:
# master:
# Parent of the master control.
@@ -161,6 +155,8 @@ class BaseLimbRig(BaseRig):
# FK follow behavior.
# fk[]:
# FK chain parents (or None)
+ # ik_pivot
+ # Custom IK pivot result (optional).
# ik_stretch
# IK stretch switch implementation.
# ik_target
@@ -328,22 +324,30 @@ class BaseLimbRig(BaseRig):
# IK controls
def get_extra_ik_controls(self):
- return []
+ if self.component_ik_pivot:
+ return [self.component_ik_pivot.control]
+ else:
+ return []
def get_all_ik_controls(self):
ctrl = self.bones.ctrl
- return [ctrl.ik_base, ctrl.ik_pole, ctrl.ik] + self.get_extra_ik_controls()
+ controls = [ctrl.ik_base, ctrl.ik_pole, ctrl.ik]
+ return controls + self.get_extra_ik_controls()
@stage.generate_bones
def make_ik_controls(self):
orgs = self.bones.org.main
- self.bones.ctrl.ik_base = self.copy_bone(orgs[0], make_derived_name(orgs[0], 'ctrl', '_ik'))
+ self.bones.ctrl.ik_base = self.make_ik_base_bone(orgs)
self.bones.ctrl.ik_pole = self.make_ik_pole_bone(orgs)
- self.bones.ctrl.ik = self.make_ik_control_bone(orgs)
+ self.bones.ctrl.ik = ik_name = self.make_ik_control_bone(orgs)
+ self.component_ik_pivot = self.build_ik_pivot(ik_name)
self.build_ik_parent_switch(SwitchParentBuilder(self.generator))
+ def make_ik_base_bone(self, orgs):
+ return self.copy_bone(orgs[0], make_derived_name(orgs[0], 'ctrl', '_ik'))
+
def make_ik_pole_bone(self, orgs):
name = self.copy_bone(orgs[0], make_derived_name(orgs[0], 'ctrl', '_ik_target'))
@@ -357,10 +361,25 @@ class BaseLimbRig(BaseRig):
def make_ik_control_bone(self, orgs):
return self.copy_bone(orgs[2], make_derived_name(orgs[2], 'ctrl', '_ik'))
+ def build_ik_pivot(self, ik_name, **args):
+ if self.use_ik_pivot:
+ return CustomPivotControl(self, 'ik_pivot', ik_name, parent=ik_name, **args)
+
+ def get_ik_control_output(self):
+ if self.component_ik_pivot:
+ return self.component_ik_pivot.output
+ else:
+ return self.bones.ctrl.ik
+
def register_switch_parents(self, pbuilder):
if self.rig_parent_bone:
pbuilder.register_parent(self, self.rig_parent_bone)
+ pbuilder.register_parent(
+ self, self.get_ik_control_output, name=self.bones.ctrl.ik,
+ exclude_self=True, tags={'limb_ik', 'child'},
+ )
+
def build_ik_parent_switch(self, pbuilder):
ctrl = self.bones.ctrl
@@ -398,9 +417,13 @@ class BaseLimbRig(BaseRig):
@stage.generate_widgets
def make_ik_control_widgets(self):
- self.make_ik_base_widget(self.bones.ctrl.ik_base)
- self.make_ik_pole_widget(self.bones.ctrl.ik_pole)
- self.make_ik_ctrl_widget(self.bones.ctrl.ik)
+ ctrl = self.bones.ctrl
+
+ set_bone_widget_transform(self.obj, ctrl.ik, self.get_ik_control_output())
+
+ self.make_ik_base_widget(ctrl.ik_base)
+ self.make_ik_pole_widget(ctrl.ik_pole)
+ self.make_ik_ctrl_widget(ctrl.ik)
def make_ik_base_widget(self, ctrl):
if self.main_axis == 'x':
@@ -453,7 +476,7 @@ class BaseLimbRig(BaseRig):
ik_input_head_tail = 0.0
def get_ik_input_bone(self):
- return self.bones.ctrl.ik
+ return self.get_ik_control_output()
def get_ik_output_chain(self):
return [self.bones.ctrl.ik_base, self.bones.mch.ik_end, self.bones.mch.ik_target]
@@ -670,7 +693,13 @@ class BaseLimbRig(BaseRig):
@stage.parent_bones
def parent_tweak_mch_chain(self):
- for mch, entry in zip(self.bones.mch.tweak, self.segment_table_tweak):
+ for args in zip(count(0), self.bones.mch.tweak, self.segment_table_tweak):
+ self.parent_tweak_mch_bone(*args)
+
+ def parent_tweak_mch_bone(self, i, mch, entry):
+ if i == 0:
+ self.set_bone_parent(mch, self.rig_parent_bone, inherit_scale='FIX_SHEAR')
+ else:
self.set_bone_parent(mch, entry.org)
@stage.rig_bones
@@ -694,6 +723,10 @@ class BaseLimbRig(BaseRig):
elif entry.seg_idx is not None:
self.make_constraint(tweak, 'COPY_SCALE', 'root', use_make_uniform=True)
+ if i == 0:
+ self.make_constraint(tweak, 'COPY_LOCATION', entry.org)
+ self.make_constraint(tweak, 'DAMPED_TRACK', entry.org, head_tail=1)
+
####################################################
# Deform chain
@@ -786,17 +819,23 @@ class BaseLimbRig(BaseRig):
)
params.segments = bpy.props.IntProperty(
- name = 'limb segments',
+ name = 'Limb Segments',
default = 2,
min = 1,
- description = 'Number of segments'
+ description = 'Number of limb segments'
)
params.bbones = bpy.props.IntProperty(
- name = 'bbone segments',
+ name = 'B-Bone Segments',
default = 10,
min = 1,
- description = 'Number of segments'
+ description = 'Number of B-Bone segments'
+ )
+
+ params.make_custom_pivot = bpy.props.BoolProperty(
+ name = "Custom Pivot Control",
+ default = False,
+ description = "Create a rotation pivot control that can be repositioned arbitrarily"
)
# Setting up extra layers for the FK and tweak
@@ -820,6 +859,8 @@ class BaseLimbRig(BaseRig):
r = layout.row()
r.prop(params, "bbones")
+ layout.prop(params, 'make_custom_pivot', text="Custom IK Pivot")
+
ControlLayersOption.FK.parameters_ui(layout, params)
ControlLayersOption.TWEAK.parameters_ui(layout, params)
@@ -843,8 +884,6 @@ class RigifyLimbIk2FkBase:
ctrl_bones: StringProperty(name="IK Controls")
extra_ctrls: StringProperty(name="Extra IK Controls")
- keyflags = None
-
def init_execute(self, context):
if self.fk_bones:
self.fk_bone_list = json.loads(self.fk_bones)
@@ -921,13 +960,11 @@ class RigifyLimbIk2FkBase:
class POSE_OT_rigify_limb_ik2fk(RigifyLimbIk2FkBase, RigifySingleUpdateMixin, bpy.types.Operator):
bl_idname = "pose.rigify_limb_ik2fk_" + rig_id
bl_label = "Snap IK->FK"
- bl_options = {'UNDO', 'INTERNAL'}
bl_description = "Snap the IK chain to FK result"
class POSE_OT_rigify_limb_ik2fk_bake(RigifyLimbIk2FkBase, RigifyBakeKeyframesMixin, bpy.types.Operator):
bl_idname = "pose.rigify_limb_ik2fk_bake_" + rig_id
bl_label = "Apply Snap IK->FK To Keyframes"
- bl_options = {'UNDO', 'INTERNAL'}
bl_description = "Snap the IK chain keyframes to FK result"
def execute_scan_curves(self, context, obj):
@@ -968,8 +1005,6 @@ SCRIPT_UTILITIES_OP_TOGGLE_POLE = SCRIPT_UTILITIES_OP_SNAP_IK_FK + ['''
class RigifyLimbTogglePoleBase(RigifyLimbIk2FkBase):
use_pole: bpy.props.BoolProperty(name="Use Pole Vector")
- keyflags_switch = None
-
def save_frame_state(self, context, obj):
return get_chain_transform_matrices(obj, self.ik_bone_list)
@@ -1007,13 +1042,11 @@ class RigifyLimbTogglePoleBase(RigifyLimbIk2FkBase):
class POSE_OT_rigify_limb_toggle_pole(RigifyLimbTogglePoleBase, RigifySingleUpdateMixin, bpy.types.Operator):
bl_idname = "pose.rigify_limb_toggle_pole_" + rig_id
bl_label = "Toggle Pole"
- bl_options = {'UNDO', 'INTERNAL'}
bl_description = "Switch the IK chain between pole and rotation"
class POSE_OT_rigify_limb_toggle_pole_bake(RigifyLimbTogglePoleBase, RigifyBakeKeyframesMixin, bpy.types.Operator):
bl_idname = "pose.rigify_limb_toggle_pole_bake_" + rig_id
bl_label = "Apply Toggle Pole To Keyframes"
- bl_options = {'UNDO', 'INTERNAL'}
bl_description = "Switch the IK chain between pole and rotation over a frame range"
def execute_scan_curves(self, context, obj):
diff --git a/rigify/rigs/limbs/paw.py b/rigify/rigs/limbs/paw.py
index f8cb1f9f..28374eec 100644
--- a/rigify/rigs/limbs/paw.py
+++ b/rigify/rigs/limbs/paw.py
@@ -84,7 +84,7 @@ class Rig(BaseLimbRig):
# IK controls
def get_extra_ik_controls(self):
- return [self.bones.ctrl.heel]
+ return super().get_extra_ik_controls() + [self.bones.ctrl.heel]
def make_ik_control_bone(self, orgs):
name = self.copy_bone(orgs[3], make_derived_name(orgs[2], 'ctrl', '_ik'))
@@ -107,7 +107,7 @@ class Rig(BaseLimbRig):
def register_switch_parents(self, pbuilder):
super().register_switch_parents(pbuilder)
- pbuilder.register_parent(self, self.bones.org.main[3], exclude_self=True)
+ pbuilder.register_parent(self, self.bones.org.main[3], exclude_self=True, tags={'limb_end'})
def make_ik_ctrl_widget(self, ctrl):
create_foot_widget(self.obj, ctrl)
@@ -126,7 +126,7 @@ class Rig(BaseLimbRig):
@stage.parent_bones
def parent_heel_control_bone(self):
- self.set_bone_parent(self.bones.ctrl.heel, self.bones.ctrl.ik)
+ self.set_bone_parent(self.bones.ctrl.heel, self.get_ik_control_output())
@stage.configure_bones
def configure_heel_control_bone(self):
@@ -150,7 +150,7 @@ class Rig(BaseLimbRig):
def parent_fk_parent_bone(self, i, parent_mch, prev_ctrl, org, prev_org):
if i == 3:
self.set_bone_parent(parent_mch, prev_org, use_connect=True)
- self.set_bone_parent(self.bones.mch.toe_socket, self.bones.ctrl.ik)
+ self.set_bone_parent(self.bones.mch.toe_socket, self.get_ik_control_output())
else:
super().parent_fk_parent_bone(i, parent_mch, prev_ctrl, org, prev_org)
diff --git a/rigify/rigs/limbs/simple_tentacle.py b/rigify/rigs/limbs/simple_tentacle.py
index 10bdd2b5..25d26e86 100644
--- a/rigify/rigs/limbs/simple_tentacle.py
+++ b/rigify/rigs/limbs/simple_tentacle.py
@@ -78,7 +78,7 @@ class Rig(TweakChainRig):
)
# Widgets
- def make_control_widget(self, ctrl):
+ def make_control_widget(self, i, ctrl):
create_circle_widget(self.obj, ctrl, radius=0.3, head_tail=0.5)
diff --git a/rigify/rigs/limbs/super_finger.py b/rigify/rigs/limbs/super_finger.py
index 1a9171a7..0b3fcd8a 100644
--- a/rigify/rigs/limbs/super_finger.py
+++ b/rigify/rigs/limbs/super_finger.py
@@ -24,11 +24,12 @@ import re
from itertools import count
from ...utils.errors import MetarigError
-from ...utils.bones import flip_bone, align_chain_x_axis
+from ...utils.bones import put_bone, flip_bone, align_chain_x_axis, set_bone_widget_transform
from ...utils.naming import make_derived_name
from ...utils.widgets import create_widget
from ...utils.widgets_basic import create_circle_widget
from ...utils.misc import map_list
+from ...utils.layers import ControlLayersOption
from ...base_rig import stage
@@ -40,7 +41,7 @@ class Rig(SimpleChainRig):
def initialize(self):
super().initialize()
- self.bbone_segments = 8
+ self.bbone_segments = self.params.bbones
self.first_parent = self.get_bone_parent(self.bones.org[0])
def prepare_bones(self):
@@ -116,6 +117,8 @@ class Rig(SimpleChainRig):
for args in zip(count(0), self.bones.ctrl.fk, self.bones.org + [None]):
self.configure_control_bone(*args)
+ ControlLayersOption.TWEAK.assign(self.params, self.obj, self.bones.ctrl.fk)
+
def configure_control_bone(self, i, ctrl, org):
if org:
self.copy_bone_properties(org, ctrl)
@@ -125,11 +128,13 @@ class Rig(SimpleChainRig):
bone.lock_rotation = (True, True, True)
bone.lock_scale = (True, True, True)
- def make_control_widget(self, ctrl):
+ def make_control_widget(self, i, ctrl):
if ctrl == self.bones.ctrl.fk[-1]:
# Tip control
create_circle_widget(self.obj, ctrl, radius=0.3, head_tail=0.0)
else:
+ set_bone_widget_transform(self.obj, ctrl, self.bones.org[i])
+
create_circle_widget(self.obj, ctrl, radius=0.3, head_tail=0.5)
##############################
@@ -234,11 +239,12 @@ class Rig(SimpleChainRig):
def configure_master_properties(self):
master = self.bones.ctrl.master
- self.make_property(master, 'finger_curve', 0.0, description="Rubber hose finger cartoon effect")
+ if self.bbone_segments > 1:
+ self.make_property(master, 'finger_curve', 0.0, description="Rubber hose finger cartoon effect")
- # Create UI
- panel = self.script.panel_with_selected_check(self, self.bones.ctrl.flatten())
- panel.custom_prop(master, 'finger_curve', text="Curvature", slider=True)
+ # Create UI
+ panel = self.script.panel_with_selected_check(self, self.bones.ctrl.flatten())
+ panel.custom_prop(master, 'finger_curve', text="Curvature", slider=True)
def rig_deform_bone(self, i, deform, org):
master = self.bones.ctrl.master
@@ -246,8 +252,9 @@ class Rig(SimpleChainRig):
self.make_constraint(deform, 'COPY_TRANSFORMS', org)
- self.make_driver(bone.bone, 'bbone_easein', variables=[(master, 'finger_curve')])
- self.make_driver(bone.bone, 'bbone_easeout', variables=[(master, 'finger_curve')])
+ if self.bbone_segments > 1:
+ self.make_driver(bone.bone, 'bbone_easein', variables=[(master, 'finger_curve')])
+ self.make_driver(bone.bone, 'bbone_easeout', variables=[(master, 'finger_curve')])
###############
# OPTIONS
@@ -261,6 +268,15 @@ class Rig(SimpleChainRig):
('-X', '-X manual', ''), ('-Y', '-Y manual', ''), ('-Z', '-Z manual', '')]
params.primary_rotation_axis = bpy.props.EnumProperty(items=items, name="Primary Rotation Axis", default='automatic')
+ params.bbones = bpy.props.IntProperty(
+ name = 'B-Bone Segments',
+ default = 10,
+ min = 1,
+ description = 'Number of B-Bone segments'
+ )
+
+ ControlLayersOption.TWEAK.add_parameters(params)
+
@classmethod
def parameters_ui(self, layout, params):
""" Create the ui for the rig parameters.
@@ -269,6 +285,10 @@ class Rig(SimpleChainRig):
r.label(text="Bend rotation axis:")
r.prop(params, "primary_rotation_axis", text="")
+ layout.prop(params, 'bbones')
+
+ ControlLayersOption.TWEAK.parameters_ui(layout, params)
+
def create_sample(obj):
# generated by rigify.utils.write_metarig
@@ -321,10 +341,6 @@ def create_sample(obj):
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
try:
- pbone.rigify_parameters.separate_extra_layers = True
- except AttributeError:
- pass
- try:
pbone.rigify_parameters.extra_layers = [False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
except AttributeError:
pass
diff --git a/rigify/rigs/limbs/super_palm.py b/rigify/rigs/limbs/super_palm.py
index 8bcbabf8..9c03b2fe 100644
--- a/rigify/rigs/limbs/super_palm.py
+++ b/rigify/rigs/limbs/super_palm.py
@@ -24,6 +24,7 @@ import re
from math import cos, pi
from itertools import count, repeat
+from rigify.utils.rig import is_rig_base_bone
from rigify.utils.naming import strip_org, make_derived_name
from rigify.utils.widgets import create_widget
from rigify.utils.misc import map_list
@@ -43,7 +44,7 @@ def bone_siblings(obj, bone):
bones = []
for b in parent.children:
- if b.name != bone:
+ if b.name != bone and not is_rig_base_bone(obj, b.name):
bones += [b.name]
return bones
diff --git a/rigify/rigs/spines/basic_spine.py b/rigify/rigs/spines/basic_spine.py
index 269889cf..c2905463 100644
--- a/rigify/rigs/spines/basic_spine.py
+++ b/rigify/rigs/spines/basic_spine.py
@@ -19,13 +19,16 @@
# <pep8 compliant>
import bpy
+import math
from itertools import count, repeat
+from mathutils import Matrix
from ...utils.errors import MetarigError
from ...utils.layers import ControlLayersOption
-from ...utils.naming import strip_org, make_deformer_name, make_mechanism_name
-from ...utils.bones import BoneDict, put_bone, align_bone_to_axis
+from ...utils.naming import strip_org, make_deformer_name, make_mechanism_name, make_derived_name
+from ...utils.bones import BoneDict, put_bone, align_bone_to_axis, align_bone_orientation, set_bone_widget_transform
+from ...utils.widgets import adjust_widget_transform_mesh
from ...utils.widgets_basic import create_circle_widget
from ...utils.misc import map_list
@@ -43,6 +46,7 @@ class Rig(BaseSpineRig):
# Check if user provided the pivot position
self.pivot_pos = self.params.pivot_pos
+ self.use_fk = self.params.make_fk_controls
if not (0 < self.pivot_pos < len(self.bones.org)):
self.raise_error("Please specify a valid pivot bone position.")
@@ -55,6 +59,9 @@ class Rig(BaseSpineRig):
# ctrl:
# master, hips, chest:
# Main controls.
+ # fk:
+ # chest[], hips[]:
+ # FK controls.
# tweak[]:
# Tweak control chain.
# mch:
@@ -73,19 +80,15 @@ class Rig(BaseSpineRig):
####################################################
# Master control bone
- @stage.generate_bones
- def make_master_control(self):
- super().make_master_control()
-
- # Put the main control in the middle of the hip bone
- base_bone = self.get_bone(self.bones.org[0])
- put_bone(self.obj, self.bones.ctrl.master, (base_bone.head + base_bone.tail) / 2)
+ def get_master_control_pos(self, orgs):
+ base_bone = self.get_bone(orgs[0])
+ return (base_bone.head + base_bone.tail) / 2
####################################################
# Main control bones
@stage.generate_bones
- def make_control_chain(self):
+ def make_end_control_bones(self):
orgs = self.bones.org
pivot = self.pivot_pos
@@ -103,33 +106,90 @@ class Rig(BaseSpineRig):
return name
@stage.parent_bones
- def parent_control_chain(self):
+ def parent_end_control_bones(self):
ctrl = self.bones.ctrl
- self.set_bone_parent(ctrl.hips, ctrl.master)
- self.set_bone_parent(ctrl.chest, ctrl.master)
-
- @stage.configure_bones
- def configure_control_chain(self):
- pass
+ pivot = self.get_master_control_output()
+ self.set_bone_parent(ctrl.hips, pivot)
+ self.set_bone_parent(ctrl.chest, pivot)
@stage.generate_widgets
- def make_control_widgets(self):
+ def make_end_control_widgets(self):
ctrl = self.bones.ctrl
mch = self.bones.mch
- self.make_control_widget(ctrl.hips, mch.wgt_hips)
- self.make_control_widget(ctrl.chest, mch.wgt_chest)
+ self.make_end_control_widget(ctrl.hips, mch.wgt_hips)
+ self.make_end_control_widget(ctrl.chest, mch.wgt_chest)
+
+ def make_end_control_widget(self, ctrl, wgt_mch):
+ shape_bone = self.get_bone(wgt_mch)
+ is_horizontal = abs(shape_bone.z_axis.normalized().y) < 0.7
- def make_control_widget(self, ctrl, wgt_mch):
- self.get_bone(ctrl).custom_shape_transform = self.get_bone(wgt_mch)
+ set_bone_widget_transform(self.obj, ctrl, wgt_mch)
- create_circle_widget(
+ obj = create_circle_widget(
self.obj, ctrl,
- radius=1.0,
+ radius=1.2 if is_horizontal else 1.1,
head_tail=0.0,
head_tail_x=1.0,
with_line=False,
)
+ if is_horizontal:
+ # Tilt the widget toward the ground for horizontal (animal) spines
+ angle = math.copysign(28, shape_bone.x_axis.x)
+ rotmat = Matrix.Rotation(math.radians(angle), 4, 'X')
+ adjust_widget_transform_mesh(obj, rotmat, local=True)
+
+ ####################################################
+ # FK control bones
+
+ @stage.generate_bones
+ def make_control_chain(self):
+ if self.use_fk:
+ orgs = self.bones.org
+ self.bones.ctrl.fk = self.fk_result = BoneDict(
+ hips = map_list(self.make_control_bone, count(0), orgs[0:self.pivot_pos], repeat(True)),
+ chest = map_list(self.make_control_bone, count(self.pivot_pos), orgs[self.pivot_pos:], repeat(False)),
+ )
+
+ def make_control_bone(self, i, org, is_hip):
+ name = self.copy_bone(org, make_derived_name(org, 'ctrl', '_fk'), parent=False)
+ if is_hip:
+ put_bone(self.obj, name, self.get_bone(name).tail)
+ return name
+
+ @stage.parent_bones
+ def parent_control_chain(self):
+ if self.use_fk:
+ chain = self.bones.mch.chain
+ fk = self.bones.ctrl.fk
+ for child, parent in zip(fk.hips, chain.hips):
+ self.set_bone_parent(child, parent)
+ for child, parent in zip(fk.chest, chain.chest):
+ self.set_bone_parent(child, parent)
+
+ @stage.configure_bones
+ def configure_control_chain(self):
+ if self.use_fk:
+ fk = self.bones.ctrl.fk
+ for args in zip(count(0), fk.hips + fk.chest, self.bones.org):
+ self.configure_control_bone(*args)
+
+ ControlLayersOption.FK.assign_rig(self, fk.hips + fk.chest)
+
+ @stage.generate_widgets
+ def make_control_widgets(self):
+ if self.use_fk:
+ fk = self.bones.ctrl.fk
+ for ctrl in fk.hips:
+ self.make_control_widget(ctrl, True)
+ for ctrl in fk.chest:
+ self.make_control_widget(ctrl, False)
+
+ def make_control_widget(self, ctrl, is_hip):
+ obj = create_circle_widget(self.obj, ctrl, radius=1.0, head_tail=0.5)
+ if is_hip:
+ adjust_widget_transform_mesh(obj, Matrix.Diagonal((1, -1, 1, 1)), local=True)
+
####################################################
# MCH bones associated with main controls
@@ -153,16 +213,16 @@ class Rig(BaseSpineRig):
@stage.parent_bones
def parent_mch_control_bones(self):
mch = self.bones.mch
- self.set_bone_parent(mch.pivot, mch.chain.chest[0])
- self.set_bone_parent(mch.wgt_hips, mch.chain.hips[0])
- self.set_bone_parent(mch.wgt_chest, mch.chain.chest[-1])
+ fk = self.fk_result
+ self.set_bone_parent(mch.pivot, fk.chest[0])
+ self.set_bone_parent(mch.wgt_hips, fk.hips[0])
+ self.set_bone_parent(mch.wgt_chest, fk.chest[-1])
+ align_bone_orientation(self.obj, mch.pivot, fk.hips[-1])
@stage.rig_bones
def rig_mch_control_bones(self):
mch = self.bones.mch
- # Is it actually intending to compute average of these, or is this really intentional?
- # This effectively adds rotations of the hip and chest controls.
- self.make_constraint(mch.pivot, 'COPY_TRANSFORMS', mch.chain.hips[-1], space='LOCAL')
+ self.make_constraint(mch.pivot, 'COPY_TRANSFORMS', self.fk_result.hips[-1], influence=0.5)
####################################################
# MCH chain for distributing hip & chest transform
@@ -174,6 +234,8 @@ class Rig(BaseSpineRig):
hips = map_list(self.make_mch_bone, orgs[0:self.pivot_pos], repeat(True)),
chest = map_list(self.make_mch_bone, orgs[self.pivot_pos:], repeat(False)),
)
+ if not self.use_fk:
+ self.fk_result = self.bones.mch.chain
def make_mch_bone(self, org, is_hip):
name = self.copy_bone(org, make_mechanism_name(strip_org(org)), parent=False)
@@ -182,10 +244,13 @@ class Rig(BaseSpineRig):
@stage.parent_bones
def parent_mch_chain(self):
- master = self.bones.ctrl.master
+ master = self.get_master_control_output()
chain = self.bones.mch.chain
- self.parent_bone_chain([master, *reversed(chain.hips)])
- self.parent_bone_chain([master, *chain.chest])
+ fk = self.fk_result
+ for child, parent in zip(reversed(chain.hips), [master, *reversed(fk.hips)]):
+ self.set_bone_parent(child, parent)
+ for child, parent in zip(chain.chest, [master, *fk.chest]):
+ self.set_bone_parent(child, parent)
@stage.rig_bones
def rig_mch_chain(self):
@@ -205,7 +270,7 @@ class Rig(BaseSpineRig):
@stage.parent_bones
def parent_tweak_chain(self):
mch = self.bones.mch
- chain = mch.chain
+ chain = self.fk_result
parents = [chain.hips[0], *chain.hips[0:-1], mch.pivot, *chain.chest[1:], chain.chest[-1]]
for args in zip(self.bones.ctrl.tweak, parents):
self.set_bone_parent(*args)
@@ -224,6 +289,13 @@ class Rig(BaseSpineRig):
super().add_parameters(params)
+ params.make_fk_controls = bpy.props.BoolProperty(
+ name="FK Controls", default=True,
+ description="Generate an FK control chain"
+ )
+
+ ControlLayersOption.FK.add_parameters(params)
+
@classmethod
def parameters_ui(self, layout, params):
r = layout.row()
@@ -231,6 +303,11 @@ class Rig(BaseSpineRig):
super().parameters_ui(layout, params)
+ layout.prop(params, 'make_fk_controls')
+
+ if params.make_fk_controls:
+ ControlLayersOption.FK.parameters_ui(layout, params)
+
def create_sample(obj):
# generated by rigify.utils.write_metarig
diff --git a/rigify/rigs/spines/basic_tail.py b/rigify/rigs/spines/basic_tail.py
index 845c3ca3..be054e7d 100644
--- a/rigify/rigs/spines/basic_tail.py
+++ b/rigify/rigs/spines/basic_tail.py
@@ -23,7 +23,8 @@ import bpy
from itertools import count
from ...utils.naming import strip_org, make_derived_name
-from ...utils.bones import put_bone, flip_bone, is_same_position, connect_bbone_chain_handles, align_bone_orientation
+from ...utils.bones import put_bone, flip_bone, is_same_position, connect_bbone_chain_handles
+from ...utils.bones import align_bone_orientation, set_bone_widget_transform
from ...utils.widgets_basic import create_circle_widget
from ...utils.layers import ControlLayersOption
from ...utils.misc import map_list
@@ -69,7 +70,7 @@ class Rig(BaseHeadTailRig):
@stage.generate_widgets
def make_master_control_widget(self):
bone = self.bones.ctrl.master
- self.get_bone(bone).custom_shape_transform = self.get_bone(self.bones.ctrl.tweak[-1])
+ set_bone_widget_transform(self.obj, bone, self.bones.ctrl.tweak[-1])
create_ballsocket_widget(self.obj, bone, size=0.7)
####################################################
@@ -94,7 +95,7 @@ class Rig(BaseHeadTailRig):
)
# Widgets
- def make_control_widget(self, ctrl):
+ def make_control_widget(self, i, ctrl):
create_circle_widget(self.obj, ctrl, radius=0.5, head_tail=0.75)
####################################################
diff --git a/rigify/rigs/spines/spine_rigs.py b/rigify/rigs/spines/spine_rigs.py
index 6628289f..070a6bd3 100644
--- a/rigify/rigs/spines/spine_rigs.py
+++ b/rigify/rigs/spines/spine_rigs.py
@@ -24,9 +24,10 @@ from itertools import count
from ...utils.layers import ControlLayersOption
from ...utils.naming import make_derived_name
-from ...utils.bones import align_bone_orientation, align_bone_to_axis
+from ...utils.bones import align_bone_orientation, align_bone_to_axis, put_bone, set_bone_widget_transform
from ...utils.widgets_basic import create_cube_widget
from ...utils.switch_parent import SwitchParentBuilder
+from ...utils.components import CustomPivotControl
from ...base_rig import stage
@@ -44,6 +45,7 @@ class BaseSpineRig(TweakChainRig):
if len(self.bones.org) < 3:
self.raise_error("Input to rig type must be a chain of 3 or more bones.")
+ self.use_torso_pivot = self.params.make_custom_pivot
self.length = sum([self.get_bone(b).length for b in self.bones.org])
####################################################
@@ -52,6 +54,11 @@ class BaseSpineRig(TweakChainRig):
# ctrl:
# master
# Main control.
+ # master_pivot
+ # Custom pivot under the master control.
+ # mch:
+ # master_pivot
+ # Final output of the custom pivot.
#
####################################################
@@ -60,17 +67,43 @@ class BaseSpineRig(TweakChainRig):
@stage.generate_bones
def make_master_control(self):
- self.bones.ctrl.master = name = self.copy_bone(self.bones.org[0], 'torso')
+ self.bones.ctrl.master = name = self.make_master_control_bone(self.bones.org)
+ self.component_torso_pivot = self.build_master_pivot(name)
+ self.build_parent_switch(name)
+
+ def get_master_control_pos(self, orgs):
+ return self.get_bone(orgs[0]).head
+
+ def make_master_control_bone(self, orgs):
+ name = self.copy_bone(orgs[0], 'torso')
+ put_bone(self.obj, name, self.get_master_control_pos(orgs))
align_bone_to_axis(self.obj, name, 'y', length=self.length * 0.6)
+ return name
- self.build_parent_switch(name)
+ def build_master_pivot(self, master_name, **args):
+ if self.use_torso_pivot:
+ return CustomPivotControl(
+ self, 'master_pivot', master_name, parent=master_name, **args
+ )
+
+ def get_master_control_output(self):
+ if self.component_torso_pivot:
+ return self.component_torso_pivot.output
+ else:
+ return self.bones.ctrl.master
def build_parent_switch(self, master_name):
pbuilder = SwitchParentBuilder(self.generator)
- pbuilder.register_parent(self, master_name, name='Torso')
+
+ org_parent = self.get_bone_parent(self.bones.org[0])
+ parents = [org_parent] if org_parent else []
+
+ pbuilder.register_parent(self, self.get_master_control_output, name='Torso', tags={'torso', 'child'})
+
pbuilder.build_child(
self, master_name, exclude_self=True,
+ extra_parents=parents, select_parent=org_parent,
prop_id='torso_parent', prop_name='Torso Parent',
controls=lambda: self.bones.flatten('ctrl'),
)
@@ -78,8 +111,8 @@ class BaseSpineRig(TweakChainRig):
self.register_parent_bones(pbuilder)
def register_parent_bones(self, pbuilder):
- pbuilder.register_parent(self, self.bones.org[0], name='Hips', exclude_self=True)
- pbuilder.register_parent(self, self.bones.org[-1], name='Chest', exclude_self=True)
+ pbuilder.register_parent(self, self.bones.org[0], name='Hips', exclude_self=True, tags={'hips'})
+ pbuilder.register_parent(self, self.bones.org[-1], name='Chest', exclude_self=True, tags={'chest'})
@stage.parent_bones
def parent_master_control(self):
@@ -91,10 +124,9 @@ class BaseSpineRig(TweakChainRig):
@stage.generate_widgets
def make_master_control_widget(self):
- create_cube_widget(
- self.obj, self.bones.ctrl.master,
- radius=0.5,
- )
+ master = self.bones.ctrl.master
+ set_bone_widget_transform(self.obj, master, self.get_master_control_output())
+ create_cube_widget(self.obj, master, radius=0.5)
####################################################
# Tweak bones
@@ -117,11 +149,19 @@ class BaseSpineRig(TweakChainRig):
@classmethod
def add_parameters(self, params):
+ params.make_custom_pivot = bpy.props.BoolProperty(
+ name = "Custom Pivot Control",
+ default = False,
+ description = "Create a rotation pivot control that can be repositioned arbitrarily"
+ )
+
# Setting up extra layers for the FK and tweak
ControlLayersOption.TWEAK.add_parameters(params)
@classmethod
def parameters_ui(self, layout, params):
+ layout.prop(params, 'make_custom_pivot')
+
ControlLayersOption.TWEAK.parameters_ui(layout, params)
diff --git a/rigify/rigs/spines/super_head.py b/rigify/rigs/spines/super_head.py
index 9b85e5b5..15f011f7 100644
--- a/rigify/rigs/spines/super_head.py
+++ b/rigify/rigs/spines/super_head.py
@@ -322,7 +322,10 @@ class Rig(BaseHeadTailRig):
def register_parent_bones(self):
rig = self.rigify_parent or self
builder = SwitchParentBuilder(self.generator)
- builder.register_parent(rig, self.bones.org[-1], name='Head', exclude_self=True)
+ builder.register_parent(
+ self, self.bones.org[-1], name='Head',
+ inject_into=rig, exclude_self=True, tags={'head'},
+ )
@stage.configure_bones
def configure_bbone_chain(self):
diff --git a/rigify/rigs/spines/super_spine.py b/rigify/rigs/spines/super_spine.py
index 5ed1588e..86021c84 100644
--- a/rigify/rigs/spines/super_spine.py
+++ b/rigify/rigs/spines/super_spine.py
@@ -81,7 +81,7 @@ class Rig(SubstitutionRig, BoneUtilityMixin):
bpy.ops.object.mode_set(mode='OBJECT')
# Create the parts
- self.assign_params(spine_orgs[0], params_copy, pivot_pos=pivot_pos)
+ self.assign_params(spine_orgs[0], params_copy, pivot_pos=pivot_pos, make_fk_controls=False)
result = [ self.instantiate_rig(basic_spine.Rig, spine_orgs[0]) ]
@@ -133,6 +133,8 @@ def add_parameters(params):
def parameters_ui(layout, params):
""" Create the ui for the rig parameters."""
+ layout.label(text="Note: this combined rig is deprecated.", icon='INFO')
+
r = layout.row(align=True)
r.prop(params, "use_head", toggle=True, text="Head")
r.prop(params, "use_tail", toggle=True, text="Tail")
diff --git a/rigify/ui.py b/rigify/ui.py
index caac09ab..005aed80 100644
--- a/rigify/ui.py
+++ b/rigify/ui.py
@@ -77,6 +77,7 @@ class DATA_PT_rigify_buttons(bpy.types.Panel):
id_store = C.window_manager
if obj.mode in {'POSE', 'OBJECT'}:
+ armature_id_store = C.object.data
WARNING = "Warning: Some features may change after generation"
show_warning = False
@@ -127,7 +128,7 @@ class DATA_PT_rigify_buttons(bpy.types.Panel):
row.enabled = enable_generate_and_advanced
- if id_store.rigify_advanced_generation:
+ if armature_id_store.rigify_advanced_generation:
icon = 'UNLOCKED'
else:
icon = 'LOCKED'
@@ -135,12 +136,12 @@ class DATA_PT_rigify_buttons(bpy.types.Panel):
col = layout.column()
col.enabled = enable_generate_and_advanced
row = col.row()
- row.prop(id_store, "rigify_advanced_generation", toggle=True, icon=icon)
+ row.prop(armature_id_store, "rigify_advanced_generation", toggle=True, icon=icon)
- if id_store.rigify_advanced_generation:
+ if armature_id_store.rigify_advanced_generation:
row = col.row(align=True)
- row.prop(id_store, "rigify_generate_mode", expand=True)
+ row.prop(armature_id_store, "rigify_generate_mode", expand=True)
main_row = col.row(align=True).split(factor=0.3)
col1 = main_row.column()
@@ -148,41 +149,25 @@ class DATA_PT_rigify_buttons(bpy.types.Panel):
col1.label(text="Rig Name")
row = col1.row()
row.label(text="Target Rig")
- row.enabled = (id_store.rigify_generate_mode == "overwrite")
+ row.enabled = (armature_id_store.rigify_generate_mode == "overwrite")
row = col1.row()
row.label(text="Target UI")
- row.enabled = (id_store.rigify_generate_mode == "overwrite")
+ row.enabled = (armature_id_store.rigify_generate_mode == "overwrite")
row = col2.row(align=True)
- row.prop(id_store, "rigify_rig_basename", text="", icon="SORTALPHA")
+ row.prop(armature_id_store, "rigify_rig_basename", text="", icon="SORTALPHA")
row = col2.row(align=True)
- for i in range(0, len(id_store.rigify_target_rigs)):
- id_store.rigify_target_rigs.remove(0)
-
- for ob in context.scene.objects:
- if type(ob.data) == bpy.types.Armature and "rig_id" in ob.data:
- id_store.rigify_target_rigs.add()
- id_store.rigify_target_rigs[-1].name = ob.name
-
- row.prop_search(id_store, "rigify_target_rig", id_store, "rigify_target_rigs", text="",
- icon='OUTLINER_OB_ARMATURE')
- row.enabled = (id_store.rigify_generate_mode == "overwrite")
-
- for i in range(0, len(id_store.rigify_rig_uis)):
- id_store.rigify_rig_uis.remove(0)
-
- for t in bpy.data.texts:
- id_store.rigify_rig_uis.add()
- id_store.rigify_rig_uis[-1].name = t.name
+ row.prop(armature_id_store, "rigify_target_rig", text="")
+ row.enabled = (armature_id_store.rigify_generate_mode == "overwrite")
row = col2.row()
- row.prop_search(id_store, "rigify_rig_ui", id_store, "rigify_rig_uis", text="", icon='TEXT')
- row.enabled = (id_store.rigify_generate_mode == "overwrite")
+ row.prop(armature_id_store, "rigify_rig_ui", text="", icon='TEXT')
+ row.enabled = (armature_id_store.rigify_generate_mode == "overwrite")
row = col.row()
- row.prop(id_store, "rigify_force_widget_update")
- if id_store.rigify_generate_mode == 'new':
+ row.prop(armature_id_store, "rigify_force_widget_update")
+ if armature_id_store.rigify_generate_mode == 'new':
row.enabled = False
elif obj.mode == 'EDIT':
diff --git a/rigify/utils/animation.py b/rigify/utils/animation.py
index 62042923..1355a0b6 100644
--- a/rigify/utils/animation.py
+++ b/rigify/utils/animation.py
@@ -377,20 +377,24 @@ TRANSFORM_PROPS_ROTATION = frozenset(['rotation_euler', 'rotation_quaternion', '
TRANSFORM_PROPS_SCALE = frozenset(['scale'])
TRANSFORM_PROPS_ALL = frozenset(TRANSFORM_PROPS_LOCATION | TRANSFORM_PROPS_ROTATION | TRANSFORM_PROPS_SCALE)
-class ActionCurveTable(object):
+def transform_props_with_locks(lock_location, lock_rotation, lock_scale):
+ props = set()
+ if not lock_location:
+ props |= TRANSFORM_PROPS_LOCATION
+ if not lock_rotation:
+ props |= TRANSFORM_PROPS_ROTATION
+ if not lock_scale:
+ props |= TRANSFORM_PROPS_SCALE
+ return props
+
+class FCurveTable(object):
"Table for efficient lookup of FCurves by properties."
- def __init__(self, action):
- from collections import defaultdict
- self.action = find_action(action)
- self.curve_map = defaultdict(dict)
- self.index_action()
+ def __init__(self):
+ self.curve_map = collections.defaultdict(dict)
- def index_action(self):
- if not self.action:
- return
-
- for curve in self.action.fcurves:
+ def index_curves(self, curves):
+ for curve in curves:
index = curve.array_index
if index < 0:
index = 0
@@ -412,6 +416,24 @@ class ActionCurveTable(object):
def get_custom_prop_curves(self, ptr, prop):
return self.get_prop_curves(ptr, rna_idprop_quote_path(prop))
+
+class ActionCurveTable(FCurveTable):
+ "Table for efficient lookup of Action FCurves by properties."
+
+ def __init__(self, action):
+ super().__init__()
+ self.action = find_action(action)
+ if self.action:
+ self.index_curves(self.action.fcurves)
+
+class DriverCurveTable(FCurveTable):
+ "Table for efficient lookup of Driver FCurves by properties."
+
+ def __init__(self, object):
+ super().__init__()
+ self.anim_data = object.animation_data
+ if self.anim_data:
+ self.index_curves(self.anim_data.drivers)
''']
exec(SCRIPT_UTILITIES_CURVES[-1])
@@ -495,7 +517,23 @@ SCRIPT_UTILITIES_BAKE = SCRIPT_UTILITIES_KEYING + SCRIPT_UTILITIES_CURVES + ['''
# Keyframe baking operator framework ##
#######################################
-class RigifyBakeKeyframesMixin:
+class RigifyOperatorMixinBase:
+ bl_options = {'UNDO', 'INTERNAL'}
+
+ def init_invoke(self, context):
+ "Override to initialize the operator before invoke."
+
+ def init_execute(self, context):
+ "Override to initialize the operator before execute."
+
+ def before_save_state(self, context, rig):
+ "Override to prepare for saving state."
+
+ def after_save_state(self, context, rig):
+ "Override to undo before_save_state."
+
+
+class RigifyBakeKeyframesMixin(RigifyOperatorMixinBase):
"""Basic framework for an operator that updates a set of keyed frames."""
# Utilities
@@ -566,6 +604,7 @@ class RigifyBakeKeyframesMixin:
self.bake_state = dict()
self.keyflags = get_keying_flags(context)
+ self.keyflags_switch = None
if context.window_manager.rigify_transfer_use_all_keys:
self.bake_add_curve_frames(self.bake_curve_table.curve_map)
@@ -604,9 +643,15 @@ class RigifyBakeKeyframesMixin:
scene = context.scene
saved_state = self.bake_state
- for frame in self.bake_frames:
- scene.frame_set(frame)
- saved_state[frame] = self.save_frame_state(context, rig)
+ try:
+ self.before_save_state(context, rig)
+
+ for frame in self.bake_frames:
+ scene.frame_set(frame)
+ saved_state[frame] = self.save_frame_state(context, rig)
+
+ finally:
+ self.after_save_state(context, rig)
def bake_clean_curves_in_range(self, context, curves):
"Deletes all keys from the given curves in the bake range."
@@ -648,10 +693,6 @@ class RigifyBakeKeyframesMixin:
"Override to execute code one time before the bake apply frame scan."
pass
- def init_execute(self, context):
- "Override to initialize the operator."
- pass
-
def execute(self, context):
self.init_execute(context)
self.bake_init(context)
@@ -661,18 +702,20 @@ class RigifyBakeKeyframesMixin:
if self.report_bake_empty():
return {'CANCELLED'}
- self.bake_save_state(context)
+ try:
+ self.bake_save_state(context)
- range, range_raw = self.bake_clean_curves_in_range(context, curves)
+ range, range_raw = self.bake_clean_curves_in_range(context, curves)
- self.execute_before_apply(context, self.bake_rig, range, range_raw)
+ self.execute_before_apply(context, self.bake_rig, range, range_raw)
- self.bake_apply_state(context)
- return {'FINISHED'}
+ self.bake_apply_state(context)
- def init_invoke(self, context):
- "Override to initialize the operator."
- pass
+ except Exception as e:
+ traceback.print_exc()
+ self.report({'ERROR'}, 'Exception: ' + str(e))
+
+ return {'FINISHED'}
def invoke(self, context, event):
self.init_invoke(context)
@@ -683,22 +726,29 @@ class RigifyBakeKeyframesMixin:
return context.window_manager.invoke_confirm(self, event)
-class RigifySingleUpdateMixin:
+class RigifySingleUpdateMixin(RigifyOperatorMixinBase):
"""Basic framework for an operator that updates only the current frame."""
- def init_execute(self, context):
- pass
-
def execute(self, context):
self.init_execute(context)
obj = context.active_object
self.keyflags = get_autokey_flags(context, ignore_keyset=True)
self.keyflags_switch = add_flags_if_set(self.keyflags, {'INSERTKEY_AVAILABLE'})
- self.apply_frame_state(context, obj, self.save_frame_state(context, obj))
- return {'FINISHED'}
- def init_invoke(self, context):
- pass
+ try:
+ try:
+ self.before_save_state(context, obj)
+ state = self.save_frame_state(context, obj)
+ finally:
+ self.after_save_state(context, obj)
+
+ self.apply_frame_state(context, obj, state)
+
+ except Exception as e:
+ traceback.print_exc()
+ self.report({'ERROR'}, 'Exception: ' + str(e))
+
+ return {'FINISHED'}
def invoke(self, context, event):
self.init_invoke(context)
@@ -773,51 +823,59 @@ def add_clear_keyframes_button(panel, *, bones=[], label='', text=''):
# Generic Snap FK to IK operator ##
###################################
-SCRIPT_REGISTER_OP_SNAP_FK_IK = ['POSE_OT_rigify_generic_fk2ik', 'POSE_OT_rigify_generic_fk2ik_bake']
+SCRIPT_REGISTER_OP_SNAP = ['POSE_OT_rigify_generic_snap', 'POSE_OT_rigify_generic_snap_bake']
-SCRIPT_UTILITIES_OP_SNAP_FK_IK = ['''
-###########################
-## Generic Snap FK to IK ##
-###########################
+SCRIPT_UTILITIES_OP_SNAP = ['''
+#############################
+## Generic Snap (FK to IK) ##
+#############################
-class RigifyGenericFk2IkBase:
- fk_bones: StringProperty(name="FK Bone Chain")
- ik_bones: StringProperty(name="IK Result Bone Chain")
- ctrl_bones: StringProperty(name="IK Controls")
+class RigifyGenericSnapBase:
+ input_bones: StringProperty(name="Input Chain")
+ output_bones: StringProperty(name="Output Chain")
+ ctrl_bones: StringProperty(name="Input Controls")
+ tooltip: StringProperty(name="Tooltip", default="FK to IK")
+ locks: bpy.props.BoolVectorProperty(name="Locked", size=3, default=[False,False,False])
undo_copy_scale: bpy.props.BoolProperty(name="Undo Copy Scale", default=False)
- keyflags = None
-
def init_execute(self, context):
- self.fk_bone_list = json.loads(self.fk_bones)
- self.ik_bone_list = json.loads(self.ik_bones)
+ self.input_bone_list = json.loads(self.input_bones)
+ self.output_bone_list = json.loads(self.output_bones)
self.ctrl_bone_list = json.loads(self.ctrl_bones)
def save_frame_state(self, context, obj):
- return get_chain_transform_matrices(obj, self.ik_bone_list)
+ return get_chain_transform_matrices(obj, self.input_bone_list)
def apply_frame_state(self, context, obj, matrices):
set_chain_transforms_from_matrices(
- context, obj, self.fk_bone_list, matrices,
- undo_copy_scale=self.undo_copy_scale, keyflags=self.keyflags
+ context, obj, self.output_bone_list, matrices,
+ undo_copy_scale=self.undo_copy_scale, keyflags=self.keyflags,
+ no_loc=self.locks[0], no_rot=self.locks[1], no_scale=self.locks[2],
)
-class POSE_OT_rigify_generic_fk2ik(RigifyGenericFk2IkBase, RigifySingleUpdateMixin, bpy.types.Operator):
- bl_idname = "pose.rigify_generic_fk2ik_" + rig_id
- bl_label = "Snap FK->IK"
- bl_options = {'UNDO', 'INTERNAL'}
- bl_description = "Snap the FK chain to IK result"
+class POSE_OT_rigify_generic_snap(RigifyGenericSnapBase, RigifySingleUpdateMixin, bpy.types.Operator):
+ bl_idname = "pose.rigify_generic_snap_" + rig_id
+ bl_label = "Snap Bones"
+ bl_description = "Snap on the current frame"
-class POSE_OT_rigify_generic_fk2ik_bake(RigifyGenericFk2IkBase, RigifyBakeKeyframesMixin, bpy.types.Operator):
- bl_idname = "pose.rigify_generic_fk2ik_bake_" + rig_id
- bl_label = "Apply Snap FK->IK To Keyframes"
- bl_options = {'UNDO', 'INTERNAL'}
- bl_description = "Snap the FK chain keyframes to IK result"
+ @classmethod
+ def description(cls, context, props):
+ return "Snap " + props.tooltip + " on the current frame"
+
+class POSE_OT_rigify_generic_snap_bake(RigifyGenericSnapBase, RigifyBakeKeyframesMixin, bpy.types.Operator):
+ bl_idname = "pose.rigify_generic_snap_bake_" + rig_id
+ bl_label = "Apply Snap To Keyframes"
+ bl_description = "Apply snap to keyframes"
+
+ @classmethod
+ def description(cls, context, props):
+ return "Apply snap " + props.tooltip + " to keyframes"
def execute_scan_curves(self, context, obj):
+ props = transform_props_with_locks(*self.locks)
self.bake_add_bone_frames(self.ctrl_bone_list, TRANSFORM_PROPS_ALL)
- return self.bake_get_all_bone_curves(self.fk_bone_list, TRANSFORM_PROPS_ALL)
+ return self.bake_get_all_bone_curves(self.output_bone_list, props)
''']
def add_fk_ik_snap_buttons(panel, op_single, op_bake, *, label=None, rig_name='', properties=None, clear_bones=None, compact=None):
@@ -840,25 +898,37 @@ def add_fk_ik_snap_buttons(panel, op_single, op_bake, *, label=None, rig_name=''
row.operator(op_bake, text='Action', icon='ACTION_TWEAK', properties=properties)
add_clear_keyframes_button(row, bones=clear_bones, text='Clear')
-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(panel, *, output_bones=[], input_bones=[], input_ctrl_bones=[], label='Snap', rig_name='', undo_copy_scale=False, compact=None, clear=True, locks=None, tooltip=None):
panel.use_bake_settings()
- panel.script.add_utilities(SCRIPT_UTILITIES_OP_SNAP_FK_IK)
- panel.script.register_classes(SCRIPT_REGISTER_OP_SNAP_FK_IK)
+ panel.script.add_utilities(SCRIPT_UTILITIES_OP_SNAP)
+ panel.script.register_classes(SCRIPT_REGISTER_OP_SNAP)
op_props = {
- 'fk_bones': json.dumps(fk_bones),
- 'ik_bones': json.dumps(ik_bones),
- 'ctrl_bones': json.dumps(ik_ctrl_bones),
- 'undo_copy_scale': undo_copy_scale,
+ 'output_bones': json.dumps(output_bones),
+ 'input_bones': json.dumps(input_bones),
+ 'ctrl_bones': json.dumps(input_ctrl_bones or input_bones),
}
- clear_bones = fk_bones if clear else None
+ if undo_copy_scale:
+ op_props['undo_copy_scale'] = undo_copy_scale
+ if locks is not None:
+ op_props['locks'] = tuple(locks[0:3])
+ if tooltip is not None:
+ op_props['tooltip'] = tooltip
+
+ clear_bones = output_bones if clear else None
add_fk_ik_snap_buttons(
- panel, 'pose.rigify_generic_fk2ik_{rig_id}', 'pose.rigify_generic_fk2ik_bake_{rig_id}',
+ panel, 'pose.rigify_generic_snap_{rig_id}', 'pose.rigify_generic_snap_bake_{rig_id}',
label=label, rig_name=rig_name, properties=op_props, clear_bones=clear_bones, compact=compact,
)
+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):
+ 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
+ )
+
###############################
# Module register/unregister ##
###############################
diff --git a/rigify/utils/bones.py b/rigify/utils/bones.py
index 6a09cee1..854d4428 100644
--- a/rigify/utils/bones.py
+++ b/rigify/utils/bones.py
@@ -657,3 +657,17 @@ def align_bone_to_axis(obj, bone_name, axis, *, length=None, roll=0, flip=False)
bone_e.tail = bone_e.head + vec
bone_e.roll = roll
+
+
+def set_bone_widget_transform(obj, bone_name, transform_bone, use_size=True, scale=1.0):
+ assert obj.mode != 'EDIT'
+
+ bone = obj.pose.bones[bone_name]
+
+ if transform_bone and transform_bone != bone_name:
+ bone.custom_shape_transform = obj.pose.bones[transform_bone]
+ else:
+ bone.custom_shape_transform = None
+
+ bone.use_custom_shape_bone_size = use_size
+ bone.custom_shape_scale = scale
diff --git a/rigify/utils/components.py b/rigify/utils/components.py
new file mode 100644
index 00000000..5c1ebcb6
--- /dev/null
+++ b/rigify/utils/components.py
@@ -0,0 +1,87 @@
+import bpy
+
+from .naming import make_derived_name
+from .bones import put_bone, copy_bone_position, align_bone_orientation
+from .widgets_basic import create_pivot_widget
+from .misc import force_lazy
+
+from ..base_rig import RigComponent, stage
+
+
+class CustomPivotControl(RigComponent):
+ """
+ A utility that generates a pivot control with a custom position.
+
+ Generates a control bone, and a MCH output bone.
+ """
+
+ def __init__(
+ self, rig, id_name, org_bone, *,
+ name=None, parent=None, position=None, matrix=None,
+ scale=1.0, scale_mch=None,
+ move_to=None, align_to=None, snap_to=None,
+ widget_axis=1.5, widget_cap=1.0, widget_square=True,
+ ):
+ super().__init__(rig)
+
+ assert rig.generator.stage == 'generate_bones'
+
+ self.bones = rig.bones
+ self.id_name = id_name
+
+ self.parent = parent
+ self.scale = scale or 1
+ self.scale_mch = scale_mch or (self.scale * 0.7)
+ self.move_to = move_to
+ self.align_to = align_to
+ self.snap_to = snap_to
+ self.widget_axis = widget_axis
+ self.widget_cap = widget_cap
+ self.widget_square = widget_square
+
+ name = name or make_derived_name(org_bone, 'ctrl', '_pivot')
+
+ self.do_make_bones(org_bone, name, position, matrix)
+
+ @property
+ def control(self):
+ return self.ctrl
+
+ @property
+ def output(self):
+ return self.mch
+
+ def do_make_bones(self, org, name, position, matrix):
+ self.bones.ctrl[self.id_name] = self.ctrl = self.copy_bone(org, name, parent=not self.parent, scale=self.scale)
+ self.bones.mch[self.id_name] = self.mch = self.copy_bone(org, make_derived_name(name, 'mch'), scale=self.scale_mch)
+
+ if position or matrix:
+ put_bone(self.obj, self.ctrl, position, matrix=matrix)
+ put_bone(self.obj, self.mch, position, matrix=matrix)
+
+ def parent_bones(self):
+ if self.snap_to:
+ bone = force_lazy(self.snap_to)
+ copy_bone_position(self.obj, bone, self.ctrl, scale=self.scale)
+ copy_bone_position(self.obj, bone, self.mch, scale=self.scale_mch)
+
+ if self.move_to:
+ pos = self.get_bone(force_lazy(self.move_to)).head
+ put_bone(self.obj, self.ctrl, pos)
+ put_bone(self.obj, self.mch, pos)
+
+ if self.align_to:
+ self.align_to = force_lazy(self.align_to)
+ align_bone_orientation(self.obj, self.ctrl, self.align_to)
+ align_bone_orientation(self.obj, self.mch, self.align_to)
+
+ if self.parent:
+ self.set_bone_parent(self.ctrl, force_lazy(self.parent))
+
+ self.set_bone_parent(self.mch, self.ctrl)
+
+ def rig_bones(self):
+ self.make_constraint(self.mch, 'COPY_LOCATION', self.ctrl, space='LOCAL', invert_xyz=(True,)*3)
+
+ def generate_widgets(self):
+ create_pivot_widget(self.obj, self.ctrl, axis_size=self.widget_axis, cap_size=self.widget_cap, square=self.widget_square)
diff --git a/rigify/utils/layers.py b/rigify/utils/layers.py
index 7a1bcef8..0cbd41f8 100644
--- a/rigify/utils/layers.py
+++ b/rigify/utils/layers.py
@@ -71,7 +71,7 @@ class ControlLayersOption:
self.toggle_option = self.name+'_layers_extra'
self.layers_option = self.name+'_layers'
- self.toggle_name = toggle_name if toggle_name else self.toggle_option
+ self.toggle_name = toggle_name if toggle_name else "Assign " + self.name.title() + " Layers"
def get(self, params):
if getattr(params, self.toggle_option):
@@ -122,10 +122,15 @@ class ControlLayersOption:
setattr(params, self.layers_option, prop_layers)
def parameters_ui(self, layout, params):
- r = layout.row()
- r.prop(params, self.toggle_option)
- r.active = getattr(params, self.toggle_option)
+ box = layout.box()
+ box.prop(params, self.toggle_option)
+ active = getattr(params, self.toggle_option)
+
+ if not active:
+ return
+
+ r = box.row()
col = r.column(align=True)
row = col.row(align=True)
diff --git a/rigify/utils/misc.py b/rigify/utils/misc.py
index 64367bb7..20fd6a08 100644
--- a/rigify/utils/misc.py
+++ b/rigify/utils/misc.py
@@ -156,6 +156,14 @@ def map_apply(func, *inputs):
# Misc
#=============================================
+
+def force_lazy(value):
+ if callable(value):
+ return value()
+ else:
+ return value
+
+
def copy_attributes(a, b):
keys = dir(a)
for key in keys:
diff --git a/rigify/utils/rig.py b/rigify/utils/rig.py
index 8c646ab5..0c07cfe6 100644
--- a/rigify/utils/rig.py
+++ b/rigify/utils/rig.py
@@ -283,6 +283,7 @@ def write_metarig(obj, layers=False, func_name="create", groups=False):
code.append(" bone.select = True")
code.append(" bone.select_head = True")
code.append(" bone.select_tail = True")
+ code.append(" bone.bbone_x = bone.bbone_z = bone.length * 0.05")
code.append(" arm.edit_bones.active = bone")
# Set appropriate layers visible
diff --git a/rigify/utils/switch_parent.py b/rigify/utils/switch_parent.py
index c26f5e74..61721266 100644
--- a/rigify/utils/switch_parent.py
+++ b/rigify/utils/switch_parent.py
@@ -8,7 +8,7 @@ import json
from .errors import MetarigError
from .naming import strip_prefix, make_derived_name
from .mechanism import MechanismUtilityMixin
-from .misc import map_list, map_apply
+from .misc import map_list, map_apply, force_lazy
from ..base_rig import *
from ..base_generate import GeneratorPlugin
@@ -16,11 +16,6 @@ from ..base_generate import GeneratorPlugin
from collections import defaultdict
from itertools import count, repeat, chain
-def _auto_call(value):
- if callable(value):
- return value()
- else:
- return value
def _rig_is_child(rig, parent):
if parent is None:
@@ -56,7 +51,7 @@ class SwitchParentBuilder(GeneratorPlugin, MechanismUtilityMixin):
##############################
# API
- def register_parent(self, rig, bone, *, name=None, is_global=False, exclude_self=False):
+ def register_parent(self, rig, bone, *, name=None, is_global=False, exclude_self=False, inject_into=None, tags=None):
"""
Registers a bone of the specified rig as a possible parent.
@@ -66,6 +61,8 @@ class SwitchParentBuilder(GeneratorPlugin, MechanismUtilityMixin):
name Name of the parent for mouse-over hint.
is_global The parent is accessible to all rigs, instead of just children of owner.
exclude_self The parent is invisible to the owner rig itself.
+ inject_into Make this parent available to children of the specified rig.
+ tags Set of tags to use for default parent selection.
Lazy creation:
The bone parameter may be a function creating the bone on demand and
@@ -74,10 +71,19 @@ class SwitchParentBuilder(GeneratorPlugin, MechanismUtilityMixin):
assert not self.frozen
assert isinstance(bone, str) or callable(bone)
+ assert callable(bone) or _rig_is_child(rig, self.generator.bone_owners[bone])
+ assert _rig_is_child(rig, inject_into)
+
+ real_rig = rig
+
+ if inject_into and inject_into is not rig:
+ rig = inject_into
+ tags = (tags or set()) | {'injected'}
entry = {
- 'rig': rig, 'bone': bone, 'name': name,
- 'is_global': is_global, 'exclude_self': exclude_self, 'used': False,
+ 'rig': rig, 'bone': bone, 'name': name, 'tags': tags,
+ 'is_global': is_global, 'exclude_self': exclude_self,
+ 'real_rig': real_rig, 'used': False,
}
if is_global:
@@ -96,9 +102,13 @@ class SwitchParentBuilder(GeneratorPlugin, MechanismUtilityMixin):
extra_parents List of bone names or (name, user_name) pairs to use as additional parents.
use_parent_mch Create an intermediate MCH bone for the constraints and parent the child to it.
select_parent Select the specified bone instead of the last one.
+ select_tags List of parent tags to try for default selection.
ignore_global Ignore the is_global flag of potential parents.
exclude_self Ignore parents registered by the rig itself.
- context_rig Rig to use for selecting parents.
+ allow_self Ignore the 'exclude_self' setting of the parent.
+ context_rig Rig to use for selecting parents; defaults to rig.
+ no_implicit Only use parents listed as extra_parents.
+ only_selected Like no_implicit, but allow the 'default' selected parent.
prop_bone Name of the bone to add the property to.
prop_id Actual name of the control property.
@@ -160,7 +170,10 @@ class SwitchParentBuilder(GeneratorPlugin, MechanismUtilityMixin):
child_option_table = {
'extra_parents': None,
'prop_bone': None, 'prop_id': None, 'prop_name': None, 'controls': None,
- 'select_parent': None, 'ignore_global': False, 'exclude_self': False, 'context_rig': None,
+ 'select_parent': None, 'ignore_global': False,
+ 'exclude_self': False, 'allow_self': False,
+ 'context_rig': None, 'select_tags': None,
+ 'no_implicit': False, 'only_selected': False,
'ctrl_bone': None,
'no_fix_location': False, 'no_fix_rotation': False, 'no_fix_scale': False,
'copy_location': None, 'copy_rotation': None, 'copy_scale': None,
@@ -199,16 +212,23 @@ class SwitchParentBuilder(GeneratorPlugin, MechanismUtilityMixin):
parents = []
for parent in self.get_rig_parent_candidates(child_rig):
+ parent_rig = parent['rig']
+
+ # Exclude injected parents
+ if parent['real_rig'] is not parent_rig:
+ if _rig_is_child(parent_rig, child_rig):
+ continue
+
if parent['rig'] is child_rig:
- if parent['exclude_self'] or child['exclude_self']:
+ if (parent['exclude_self'] and not child['allow_self']) or child['exclude_self']:
continue
elif parent['is_global'] and not child['ignore_global']:
# Can't use parents from own children, even if global (cycle risk)
- if _rig_is_child(parent['rig'], child_rig):
+ if _rig_is_child(parent_rig, child_rig):
continue
else:
# Required to be a child of the parent's rig
- if not _rig_is_child(child_rig, parent['rig']):
+ if not _rig_is_child(child_rig, parent_rig):
continue
parent['used'] = True
@@ -219,7 +239,7 @@ class SwitchParentBuilder(GeneratorPlugin, MechanismUtilityMixin):
# Call lazy creation for parents
for parent in self.parent_list:
if parent['used']:
- parent['bone'] = _auto_call(parent['bone'])
+ parent['bone'] = force_lazy(parent['bone'])
def parent_bones(self):
for child in self.child_list:
@@ -248,34 +268,68 @@ class SwitchParentBuilder(GeneratorPlugin, MechanismUtilityMixin):
# Build the final list of parent bone names
parent_map = dict()
+ parent_tags = defaultdict(set)
for parent in child['parents']:
if parent['bone'] not in parent_map:
parent_map[parent['bone']] = parent['name']
+ if parent['tags']:
+ parent_tags[parent['bone']] |= parent['tags']
last_main_parent_bone = child['parents'][-1]['bone']
- num_main_parents = len(parent_map.items())
+ extra_parents = set()
- for parent in _auto_call(child['extra_parents'] or []):
+ for parent in force_lazy(child['extra_parents'] or []):
if not isinstance(parent, tuple):
parent = (parent, None)
+ extra_parents.add(parent[0])
if parent[0] not in parent_map:
parent_map[parent[0]] = parent[1]
+ for parent in parent_map:
+ if parent in self.child_map:
+ parent_tags[parent] |= {'child'}
+
parent_bones = list(parent_map.items())
- child['parent_bones'] = parent_bones
# Find which bone to select
- select_bone = _auto_call(child['select_parent']) or last_main_parent_bone
- select_index = num_main_parents
+ select_bone = force_lazy(child['select_parent']) or last_main_parent_bone
+ select_tags = force_lazy(child['select_tags']) or []
+
+ if child['no_implicit']:
+ assert len(extra_parents) > 0
+ parent_bones = [ item for item in parent_bones if item[0] in extra_parents ]
+ if last_main_parent_bone not in extra_parents:
+ last_main_parent_bone = parent_bones[-1][0]
+
+ for tag in select_tags:
+ tag_set = tag if isinstance(tag, set) else {tag}
+ matching = [
+ bone for (bone, _) in parent_bones
+ if not tag_set.isdisjoint(parent_tags[bone])
+ ]
+ if len(matching) > 0:
+ select_bone = matching[-1]
+ break
+
+ if select_bone not in parent_map:
+ print("RIGIFY ERROR: Can't find bone '%s' to select as default parent of '%s'\n" % (select_bone, bone))
+ select_bone = last_main_parent_bone
+
+ if child['only_selected']:
+ filter_set = { select_bone, *extra_parents }
+ parent_bones = [ item for item in parent_bones if item[0] in filter_set ]
try:
select_index = 1 + next(i for i, (bone, _) in enumerate(parent_bones) if bone == select_bone)
except StopIteration:
- print("RIGIFY ERROR: Can't find bone '%s' to select as default parent of '%s'\n" % (select_bone, bone))
+ select_index = len(parent_bones)
+ print("RIGIFY ERROR: Invalid default parent '%s' of '%s'\n" % (select_bone, bone))
+
+ child['parent_bones'] = parent_bones
# Create the controlling property
- prop_bone = child['prop_bone'] = _auto_call(child['prop_bone']) or bone
+ prop_bone = child['prop_bone'] = force_lazy(child['prop_bone']) or bone
prop_name = child['prop_name'] or child['prop_id'] or 'Parent Switch'
prop_id = child['prop_id'] = child['prop_id'] or 'parent_switch'
@@ -294,12 +348,12 @@ class SwitchParentBuilder(GeneratorPlugin, MechanismUtilityMixin):
no_fix = [ child[n] for n in ['no_fix_location', 'no_fix_rotation', 'no_fix_scale'] ]
- child['copy'] = [ _auto_call(child[n]) for n in ['copy_location', 'copy_rotation', 'copy_scale'] ]
+ child['copy'] = [ force_lazy(child[n]) for n in ['copy_location', 'copy_rotation', 'copy_scale'] ]
locks = tuple(bool(nofix or copy) for nofix, copy in zip(no_fix, child['copy']))
# Create the script for the property
- controls = _auto_call(child['controls']) or set([prop_bone, bone])
+ controls = force_lazy(child['controls']) or set([prop_bone, bone])
script = self.generator.script
panel = script.panel_with_selected_check(child['rig'], controls)
@@ -377,9 +431,6 @@ class RigifySwitchParentBase:
items=lambda s,c: RigifySwitchParentBase.parent_items
)
- keyflags = None
- keyflags_switch = None
-
def save_frame_state(self, context, obj):
return get_transform_matrix(obj, self.bone, with_constraints=False)
@@ -398,16 +449,6 @@ class RigifySwitchParentBase:
no_loc=self.locks[0], no_rot=self.locks[1], no_scale=self.locks[2]
)
- def get_bone_props(self):
- props = set()
- if not self.locks[0]:
- props |= TRANSFORM_PROPS_LOCATION
- if not self.locks[1]:
- props |= TRANSFORM_PROPS_ROTATION
- if not self.locks[2]:
- props |= TRANSFORM_PROPS_SCALE
- return props
-
def init_invoke(self, context):
pose = context.active_object.pose
@@ -440,11 +481,10 @@ class POSE_OT_rigify_switch_parent(RigifySwitchParentBase, RigifySingleUpdateMix
class POSE_OT_rigify_switch_parent_bake(RigifySwitchParentBase, RigifyBakeKeyframesMixin, bpy.types.Operator):
bl_idname = "pose.rigify_switch_parent_bake_" + rig_id
bl_label = "Apply Switch Parent To Keyframes"
- bl_options = {'UNDO', 'INTERNAL'}
bl_description = "Switch parent over a frame range, adjusting keys to preserve the bone position and orientation"
def execute_scan_curves(self, context, obj):
- return self.bake_add_bone_frames(self.bone, self.get_bone_props())
+ return self.bake_add_bone_frames(self.bone, transform_props_with_locks(*self.locks))
def execute_before_apply(self, context, obj, range, range_raw):
self.bake_replace_custom_prop_keys_constant(self.prop_bone, self.prop_id, int(self.selected))
diff --git a/rigify/utils/widgets_basic.py b/rigify/utils/widgets_basic.py
index 2848e5bf..8aab5d7b 100644
--- a/rigify/utils/widgets_basic.py
+++ b/rigify/utils/widgets_basic.py
@@ -129,7 +129,7 @@ def create_bone_widget(rig, bone_name, r1=0.1, l1=0.0, r2=0.04, l2=1.0, bone_tra
mesh.update()
-def create_pivot_widget(rig, bone_name, axis_size=1.0, cap_size=1.0, square=False, bone_transform_name=None):
+def create_pivot_widget(rig, bone_name, axis_size=1.0, cap_size=1.0, square=True, bone_transform_name=None):
"""Creates a widget similar to Plain Axes empty, but with a cross or
a square on the end of each axis line.
"""