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__.py12
-rw-r--r--rigify/generate.py11
-rw-r--r--rigify/metarigs/Animals/horse.py8
-rw-r--r--rigify/metarigs/Animals/wolf.py12
-rw-r--r--rigify/rig_ui_template.py3
-rw-r--r--rigify/rigs/limbs/limb_rigs.py50
-rw-r--r--rigify/rigs/spines/super_head.py2
-rw-r--r--rigify/ui.py16
-rw-r--r--rigify/utils/collections.py2
-rw-r--r--rigify/utils/node_merger.py4
-rw-r--r--rigify/utils/widgets.py3
11 files changed, 88 insertions, 35 deletions
diff --git a/rigify/__init__.py b/rigify/__init__.py
index 10e90b4c..386c8055 100644
--- a/rigify/__init__.py
+++ b/rigify/__init__.py
@@ -539,8 +539,8 @@ def register():
IDStore.rigify_types = CollectionProperty(type=RigifyName)
IDStore.rigify_active_type = IntProperty(name="Rigify Active Type", description="The selected rig type")
- 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",
+ bpy.types.Armature.rigify_force_widget_update = BoolProperty(name="Overwrite Widget Meshes",
+ description="Forces Rigify to delete and rebuild all of the rig widget objects. By default, already existing widgets are reused as-is to facilitate manual editing",
default=False)
bpy.types.Armature.rigify_mirror_widgets = BoolProperty(name="Mirror Widgets",
@@ -550,14 +550,18 @@ def register():
name="Widgets Collection",
description="Defines which collection to place widget objects in. If unset, a new one will be created based on the name of the rig")
+ bpy.types.Armature.rigify_rig_basename = StringProperty(name="Rigify Rig Name",
+ description="Optional. If specified, this name will be used for the newly generated rig, widget collection and script. Otherwise, a name is generated based on the name of the metarig object by replacing 'metarig' with 'rig', 'META' with 'RIG', or prefixing with 'RIG-'. When updating an already generated rig its name is never changed",
+ default="")
+
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",
+ description="Defines which rig to overwrite. If unset, a new one will be created with name based on the Rig Name option or the name of the metarig",
poll=lambda self, obj: obj.type == 'ARMATURE' and obj.data is not self)
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")
+ description="Defines the UI to overwrite. If unset, a new one will be created and named based on the name of the rig")
bpy.types.Armature.rigify_finalize_script = PointerProperty(type=bpy.types.Text,
name="Finalize Script",
diff --git a/rigify/generate.py b/rigify/generate.py
index 3acc2e40..8a2aa942 100644
--- a/rigify/generate.py
+++ b/rigify/generate.py
@@ -65,7 +65,9 @@ class Generator(base_generate.BaseGenerator):
target_rig = meta_data.rigify_target_rig
if not target_rig:
- if "metarig" in self.metarig.name:
+ if meta_data.rigify_rig_basename:
+ rig_new_name = meta_data.rigify_rig_basename
+ elif "metarig" in self.metarig.name:
rig_new_name = self.metarig.name.replace("metarig", "rig")
elif "META" in self.metarig.name:
rig_new_name = self.metarig.name.replace("META", "RIG")
@@ -76,7 +78,7 @@ class Generator(base_generate.BaseGenerator):
target_rig.display_type = 'WIRE'
# If the object is already added to the scene, switch to its collection
- if target_rig.name in self.context.scene.collection.all_objects:
+ if target_rig in list(self.context.scene.collection.all_objects):
self.__switch_to_usable_collection(target_rig)
else:
# Otherwise, add to the selected collection or the metarig collection if unusable
@@ -117,11 +119,14 @@ class Generator(base_generate.BaseGenerator):
wgts_group_name = "WGTS_" + self.obj.name
old_collection = bpy.data.collections.get(wgts_group_name)
+ if old_collection and old_collection.library:
+ old_collection = None
+
if not old_collection:
# Update the old 'Widgets' collection
legacy_collection = bpy.data.collections.get('Widgets')
- if legacy_collection and wgts_group_name in legacy_collection.objects:
+ if legacy_collection and wgts_group_name in legacy_collection.objects and not legacy_collection.library:
legacy_collection.name = wgts_group_name
old_collection = legacy_collection
diff --git a/rigify/metarigs/Animals/horse.py b/rigify/metarigs/Animals/horse.py
index cd393c5c..c9be9d54 100644
--- a/rigify/metarigs/Animals/horse.py
+++ b/rigify/metarigs/Animals/horse.py
@@ -618,28 +618,28 @@ def create(obj):
bone.tail = 0.1990, -1.4668, 1.7420
bone.roll = 0.0000
bone.use_connect = False
- bone.parent = arm.edit_bones[bones['ear.L']]
+ bone.parent = arm.edit_bones[bones['head']]
bones['eye.L'] = bone.name
bone = arm.edit_bones.new('nose.L')
bone.head = 0.0450, -1.6240, 1.4228
bone.tail = 0.1039, -1.6613, 1.4269
bone.roll = 0.0000
bone.use_connect = False
- bone.parent = arm.edit_bones[bones['ear.L']]
+ bone.parent = arm.edit_bones[bones['head']]
bones['nose.L'] = bone.name
bone = arm.edit_bones.new('eye.R')
bone.head = -0.0988, -1.4596, 1.7351
bone.tail = -0.1990, -1.4668, 1.7420
bone.roll = -0.0000
bone.use_connect = False
- bone.parent = arm.edit_bones[bones['ear.L']]
+ bone.parent = arm.edit_bones[bones['head']]
bones['eye.R'] = bone.name
bone = arm.edit_bones.new('nose.R')
bone.head = -0.0450, -1.6240, 1.4228
bone.tail = -0.1039, -1.6613, 1.4269
bone.roll = -0.0000
bone.use_connect = False
- bone.parent = arm.edit_bones[bones['ear.L']]
+ bone.parent = arm.edit_bones[bones['head']]
bones['nose.R'] = bone.name
bone = arm.edit_bones.new('ear.R.001')
bone.head = -0.1056, -1.4118, 1.9537
diff --git a/rigify/metarigs/Animals/wolf.py b/rigify/metarigs/Animals/wolf.py
index a2ade910..87d74c87 100644
--- a/rigify/metarigs/Animals/wolf.py
+++ b/rigify/metarigs/Animals/wolf.py
@@ -169,7 +169,7 @@ def create(obj):
bone = arm.edit_bones.new('spine.004')
bone.head = 0.0000, 0.4085, 0.7928
- bone.tail = 0.0000, 0.2416, 0.7928
+ bone.tail = 0.0000, 0.2416, 0.7927
bone.roll = 0.0000
bone.use_connect = False
bones['spine.004'] = bone.name
@@ -181,7 +181,7 @@ def create(obj):
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.2416, 0.7928
+ bone.head = 0.0000, 0.2416, 0.7927
bone.tail = 0.0000, 0.1202, 0.7773
bone.roll = 0.0000
bone.use_connect = True
@@ -189,14 +189,14 @@ def create(obj):
bones['spine.005'] = bone.name
bone = arm.edit_bones.new('spine.002')
bone.head = 0.0000, 0.5555, 0.7567
- bone.tail = 0.0000, 0.7816, 0.7412
+ bone.tail = 0.0000, 0.7816, 0.7411
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.1202, 0.7773
- bone.tail = 0.0000, 0.0096, 0.7773
+ bone.tail = 0.0000, 0.0096, 0.7772
bone.roll = 0.0000
bone.use_connect = True
bone.parent = arm.edit_bones[bones['spine.005']]
@@ -230,14 +230,14 @@ def create(obj):
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.7816, 0.7412
+ bone.head = 0.0000, 0.7816, 0.7411
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.0096, 0.7773
+ bone.head = 0.0000, 0.0096, 0.7772
bone.tail = 0.0000, -0.0980, 0.7945
bone.roll = 0.0000
bone.use_connect = True
diff --git a/rigify/rig_ui_template.py b/rigify/rig_ui_template.py
index b98907ee..d581805f 100644
--- a/rigify/rig_ui_template.py
+++ b/rigify/rig_ui_template.py
@@ -1159,7 +1159,8 @@ class ScriptGenerator(base_generate.GeneratorPlugin):
if script:
script.clear()
else:
- script = bpy.data.texts.new("rig_ui.py")
+ script_name = self.generator.obj.name + "_ui.py"
+ script = bpy.data.texts.new(script_name)
metarig.data.rigify_rig_ui = script
for s in OrderedDict.fromkeys(self.ui_imports):
diff --git a/rigify/rigs/limbs/limb_rigs.py b/rigify/rigs/limbs/limb_rigs.py
index fa20dd31..a094e176 100644
--- a/rigify/rigs/limbs/limb_rigs.py
+++ b/rigify/rigs/limbs/limb_rigs.py
@@ -52,6 +52,7 @@ class BaseLimbRig(BaseRig):
self.segments = self.params.segments
self.bbone_segments = self.params.bbones
self.use_ik_pivot = self.params.make_custom_pivot
+ self.use_uniform_scale = self.params.limb_uniform_scale
rot_axis = self.params.rotation_axis
@@ -144,6 +145,8 @@ class BaseLimbRig(BaseRig):
# FK chain parents (or None)
# ik_pivot
# Custom IK pivot result (optional).
+ # ik_scale
+ # Helper bone that implements uniform scaling.
# ik_swing
# Bone that tracks ik_target to manually handle limb swing.
# ik_target
@@ -178,14 +181,15 @@ class BaseLimbRig(BaseRig):
bone = self.get_bone(self.bones.ctrl.master)
bone.lock_location = (True, True, True)
bone.lock_rotation = (True, True, True)
- bone.lock_scale = (False, False, False)
+ bone.lock_scale = (not self.use_uniform_scale,) * 3
bone.lock_rotation_w = True
@stage.rig_bones
def rig_master_control(self):
mch = self.bones.mch
self.make_constraint(mch.master, 'COPY_SCALE', 'root', use_make_uniform=True)
- self.make_constraint(mch.master, 'COPY_SCALE', self.bones.ctrl.master, use_offset=True, space='LOCAL')
+ if self.use_uniform_scale:
+ self.make_constraint(mch.master, 'COPY_SCALE', self.bones.ctrl.master, use_offset=True, space='LOCAL')
@stage.generate_widgets
def make_master_control_widget(self):
@@ -221,10 +225,12 @@ class BaseLimbRig(BaseRig):
mch = self.bones.mch.follow
self.make_constraint(mch, 'COPY_SCALE', 'root', use_make_uniform=True)
- self.make_constraint(
- mch, 'COPY_SCALE', self.bones.ctrl.master,
- use_make_uniform=True, use_offset=True, space='LOCAL'
- )
+
+ if self.use_uniform_scale:
+ self.make_constraint(
+ mch, 'COPY_SCALE', self.bones.ctrl.master,
+ use_make_uniform=True, use_offset=True, space='LOCAL'
+ )
con = self.make_constraint(mch, 'COPY_ROTATION', 'root')
@@ -361,9 +367,12 @@ class BaseLimbRig(BaseRig):
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 = ik_name = self.make_ik_control_bone(orgs)
+ self.bones.ctrl.ik = ik_name = parent = self.make_ik_control_bone(orgs)
+
+ if self.use_uniform_scale:
+ self.bones.mch.ik_scale = parent = self.make_ik_scale_bone(ik_name, orgs)
- self.component_ik_pivot = self.build_ik_pivot(ik_name)
+ self.component_ik_pivot = self.build_ik_pivot(ik_name, parent=parent)
self.build_ik_parent_switch(SwitchParentBuilder(self.generator))
def make_ik_base_bone(self, orgs):
@@ -382,13 +391,18 @@ class BaseLimbRig(BaseRig):
def make_ik_control_bone(self, orgs):
return self.copy_bone(orgs[2], make_derived_name(orgs[2], 'ctrl', '_ik'))
+ def make_ik_scale_bone(self, ctrl, orgs):
+ return self.copy_bone(ctrl, make_derived_name(orgs[2], 'mch', '_ik_scale'), scale=1/2)
+
def build_ik_pivot(self, ik_name, **args):
if self.use_ik_pivot:
- return CustomPivotControl(self, 'ik_pivot', ik_name, parent=ik_name, **args)
+ return CustomPivotControl(self, 'ik_pivot', ik_name, **args)
def get_ik_control_output(self):
if self.component_ik_pivot:
return self.component_ik_pivot.output
+ elif self.use_uniform_scale:
+ return self.bones.mch.ik_scale
else:
return self.bones.ctrl.ik
@@ -430,6 +444,9 @@ class BaseLimbRig(BaseRig):
else:
self.set_bone_parent(self.bones.ctrl.ik_base, self.bones.mch.ik_swing)
+ if self.use_uniform_scale:
+ self.set_bone_parent(self.bones.mch.ik_scale, self.bones.ctrl.ik)
+
self.set_ik_local_location(self.bones.ctrl.ik)
self.set_ik_local_location(self.bones.ctrl.ik_pole)
@@ -445,11 +462,13 @@ class BaseLimbRig(BaseRig):
@stage.rig_bones
def rig_ik_controls(self):
self.rig_hide_pole_control(self.bones.ctrl.ik_pole)
- self.rig_ik_control_scale(self.bones.ctrl.ik)
- def rig_ik_control_scale(self, ctrl):
+ if self.use_uniform_scale:
+ self.rig_ik_control_scale(self.bones.mch.ik_scale)
+
+ def rig_ik_control_scale(self, mch):
self.make_constraint(
- ctrl, 'COPY_SCALE', self.bones.ctrl.master,
+ mch, 'COPY_SCALE', self.bones.ctrl.master,
use_make_uniform=True, use_offset=True, space='LOCAL',
)
@@ -937,6 +956,12 @@ class BaseLimbRig(BaseRig):
description = "Specifies the value of the Local Location option for IK controls, which decides if the location channels are aligned to the local control orientation or world",
)
+ params.limb_uniform_scale = bpy.props.BoolProperty(
+ name = "Support Uniform Scaling",
+ default = False,
+ description = "Support uniformly scaling the limb via the gear control at the base"
+ )
+
# Setting up extra layers for the FK and tweak
ControlLayersOption.FK.add_parameters(params)
ControlLayersOption.TWEAK.add_parameters(params)
@@ -958,6 +983,7 @@ class BaseLimbRig(BaseRig):
r = layout.row()
r.prop(params, "bbones")
+ layout.prop(params, 'limb_uniform_scale')
layout.prop(params, 'make_custom_pivot', text="Custom IK Pivot")
layout.prop(params, 'ik_local_location')
diff --git a/rigify/rigs/spines/super_head.py b/rigify/rigs/spines/super_head.py
index e2932ad2..49f1ce3e 100644
--- a/rigify/rigs/spines/super_head.py
+++ b/rigify/rigs/spines/super_head.py
@@ -292,6 +292,8 @@ class Rig(BaseHeadTailRig):
influence=nfactor, space='LOCAL'
)
+ self.make_constraint(mch, 'COPY_SCALE', ctrl.neck)
+
####################################################
# Tweak bones
diff --git a/rigify/ui.py b/rigify/ui.py
index 68cfd330..8b719a3f 100644
--- a/rigify/ui.py
+++ b/rigify/ui.py
@@ -137,10 +137,20 @@ class DATA_PT_rigify_advanced(bpy.types.Panel):
armature_id_store = context.object.data
col = layout.column()
- col.row().prop(armature_id_store, "rigify_target_rig", text="Target Rig")
- col.row().prop(armature_id_store, "rigify_rig_ui", text="Rig UI Script")
+
+ row = col.row()
+ row.active = not armature_id_store.rigify_target_rig
+ row.prop(armature_id_store, "rigify_rig_basename", text="Rig Name")
+
+ col.separator()
+
+ col2 = col.box().column()
+ col2.label(text="Overwrite Existing:")
+ col2.row().prop(armature_id_store, "rigify_target_rig", text="Target Rig")
+ col2.row().prop(armature_id_store, "rigify_rig_ui", text="Rig UI Script")
+ col2.row().prop(armature_id_store, "rigify_widgets_collection")
+
col.separator()
- col.row().prop(armature_id_store, "rigify_widgets_collection")
col.row().prop(armature_id_store, "rigify_force_widget_update")
col.row().prop(armature_id_store, "rigify_mirror_widgets")
col.separator()
diff --git a/rigify/utils/collections.py b/rigify/utils/collections.py
index 8a299a9b..9eeaac51 100644
--- a/rigify/utils/collections.py
+++ b/rigify/utils/collections.py
@@ -53,7 +53,7 @@ def ensure_collection(context, collection_name, hidden=False) -> bpy.types.Colle
active_collection = active_layer_coll.collection
collection = bpy.data.collections.get(collection_name)
- if not collection:
+ if not collection or collection.library:
# Create the collection
collection = bpy.data.collections.new(collection_name)
collection.hide_viewport = hidden
diff --git a/rigify/utils/node_merger.py b/rigify/utils/node_merger.py
index 617b99df..2da48ada 100644
--- a/rigify/utils/node_merger.py
+++ b/rigify/utils/node_merger.py
@@ -73,7 +73,9 @@ class NodeMerger(GeneratorPlugin):
while pending:
added = set()
for j in pending:
- for co, idx, dist in tree.find_range(nodes[j].point, self.epsilon):
+ point = nodes[j].point
+ eps = max(1, point.length) * self.epsilon
+ for co, idx, dist in tree.find_range(point, eps):
added.add(idx)
pending = added.difference(merge_set)
merge_set.update(added)
diff --git a/rigify/utils/widgets.py b/rigify/utils/widgets.py
index e02f3387..5a16065b 100644
--- a/rigify/utils/widgets.py
+++ b/rigify/utils/widgets.py
@@ -86,6 +86,9 @@ def create_widget(rig, bone_name, bone_transform_name=None, *, widget_name=None,
if not obj:
# Search the scene by name
obj = scene.objects.get(obj_name)
+ if obj and obj.library:
+ local_objs = [obj for obj in scene.objects if obj.name == obj_name and not obj.library]
+ obj = local_objs[0] if local_objs else None
if obj:
# Record the generated widget