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

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Gavrilov <angavrilov@gmail.com>2019-09-14 09:15:14 +0300
committerAlexander Gavrilov <angavrilov@gmail.com>2019-09-14 09:30:00 +0300
commit9b693a6be0aa2b0b4825d30ac5034655dce9c0dd (patch)
tree2875d325828db8e5f447419dcacfdeab1951af63
parent3423174b37a0784dc12035ff3f2fb536835099e1 (diff)
Rigify: update super_chain from the latest 2.79 version by MAD.
Differential Revision: https://developer.blender.org/D4624
-rw-r--r--rigify/rigs/experimental/super_chain.py246
-rw-r--r--rigify/utils/widgets.py31
-rw-r--r--rigify/utils/widgets_basic.py12
3 files changed, 232 insertions, 57 deletions
diff --git a/rigify/rigs/experimental/super_chain.py b/rigify/rigs/experimental/super_chain.py
index 592441fe..fd6569c1 100644
--- a/rigify/rigs/experimental/super_chain.py
+++ b/rigify/rigs/experimental/super_chain.py
@@ -3,9 +3,9 @@ from mathutils import Vector
from ...utils import copy_bone, put_bone, org, align_bone_y_axis, align_bone_x_axis, align_bone_z_axis
from ...utils import strip_org, make_deformer_name, connected_children_names
from ...utils import create_chain_widget
-from ...utils import make_mechanism_name, create_cube_widget
+from ...utils import make_mechanism_name
from ...utils import ControlLayersOption
-from ...utils.mechanism import make_property, make_driver
+from rna_prop_ui import rna_idprop_ui_prop_get
from ..limbs.limb_utils import get_bone_name
@@ -114,7 +114,13 @@ class Rig:
self.obj.data.bones[def_bones[-1]].bbone_easeout = 1.0
bpy.ops.object.mode_set(mode='EDIT')
- return def_bones
+ conv_def = ""
+ if self.params.conv_bone and self.params.conv_def:
+ b = org(self.params.conv_bone)
+ conv_def = make_deformer_name(strip_org(b))
+ conv_def = copy_bone(self.obj, b, conv_def)
+
+ return def_bones, conv_def
def create_chain(self):
org_bones = self.org_bones
@@ -147,28 +153,23 @@ class Rig:
eb[mch_name].length /= 4
put_bone(self.obj, mch_name, eb[b].head - (eb[mch_name].tail - eb[mch_name].head))
align_bone_z_axis(self.obj, mch_name, eb[b].z_axis)
- if '.' in mch_name:
- mch_rev_name = mch_name.split('.')[0] + '_reverse.' + mch_name.split('.')[1]
- else:
- mch_rev_name = mch_name + '_reverse'
- mch_rev_name = copy_bone(self.obj, org(b), mch_rev_name)
- eb[mch_rev_name].length /= 4
- eb[mch_rev_name].tail = eb[mch_name].head
- align_bone_z_axis(self.obj, mch_rev_name, eb[b].z_axis)
mch += [mch_name]
- mch += [mch_rev_name]
- break
-
- mch_name = copy_bone(self.obj, org(b), make_mechanism_name(strip_org(b)))
- eb[mch_name].length /= 4
-
- mch += [mch_name]
-
- if b == org_bones[-1]: # Add extra
mch_name = copy_bone(self.obj, org(b), make_mechanism_name(strip_org(b)))
eb[mch_name].length /= 4
put_bone(self.obj, mch_name, eb[b].tail)
mch += [mch_name]
+ break
+ else:
+ mch_name = copy_bone(self.obj, org(b), make_mechanism_name(strip_org(b)))
+ eb[mch_name].length /= 4
+
+ mch += [mch_name]
+
+ if b == org_bones[-1]: # Add extra
+ mch_name = copy_bone(self.obj, org(b), make_mechanism_name(strip_org(b)))
+ eb[mch_name].length /= 4
+ put_bone(self.obj, mch_name, eb[b].tail)
+ mch += [mch_name]
# Tweak & Ctrl bones
v = eb[org_bones[-1]].tail - eb[org_bones[0]].head # Create a vector from head of first ORG to tail of last
@@ -193,7 +194,7 @@ class Rig:
align_bone_x_axis(self.obj, name, eb[org(b)].x_axis)
ctrl += [name]
else:
- name = get_bone_name(b, 'ctrl', 'tweak')
+ name = 'tweak_' + strip_org(b)
name = copy_bone(self.obj, org(b), name)
twk += [name]
@@ -238,12 +239,16 @@ class Rig:
conv_twk = ''
# Convergence tweak
if self.params.conv_bone:
- conv_twk = get_bone_name(self.params.conv_bone, 'ctrl', 'tweak')
+ conv_twk = 'tweak_' + strip_org(self.params.conv_bone)
if not(conv_twk in eb.keys()):
conv_twk = copy_bone(self.obj, org(self.params.conv_bone), conv_twk)
for b in org_bones:
+
+ if self.SINGLE_BONE:
+ break
+
# Mch controls
suffix = ''
if '.L' in b:
@@ -252,7 +257,7 @@ class Rig:
suffix = '.R'
mch_ctrl_name = "MCH-CTRL-" + strip_org(b).split('.')[0] + suffix
- mch_ctrl_name = copy_bone(self.obj, twk[0], mch_ctrl_name)
+ mch_ctrl_name = copy_bone(self.obj, twk[0] if twk else ctrl[0], mch_ctrl_name)
eb[mch_ctrl_name].length /= 6
@@ -262,7 +267,7 @@ class Rig:
if b == org_bones[-1]: # Add extra
mch_ctrl_name = "MCH-CTRL-" + strip_org(b).split('.')[0] + suffix
- mch_ctrl_name = copy_bone(self.obj, twk[0], mch_ctrl_name)
+ mch_ctrl_name = copy_bone(self.obj, twk[0] if twk else ctrl[0], mch_ctrl_name)
eb[mch_ctrl_name].length /= 6
@@ -289,6 +294,9 @@ class Rig:
if i > 0: # For all bones but the first (which has no parent)
eb[b].parent = eb[bones['def'][i-1]] # to previous
eb[b].use_connect = True
+ elif self.SINGLE_BONE:
+ eb[b].parent = eb[bones['chain']['mch'][0]]
+ eb[b].use_connect = True
# Todo check case when sup_chain is in bigger rig
eb[bones['def'][0]].parent = eb[bones['chain']['mch'][0]]
@@ -297,9 +305,9 @@ class Rig:
eb[twk].parent = eb[bones['chain']['mch_ctrl'][i+1]]
eb[twk].use_inherit_scale = False
- eb[bones['chain']['ctrl'][0]].parent = eb[bones['chain']['mch_ctrl'][0]]
+ eb[bones['chain']['ctrl'][0]].parent = eb[bones['chain']['mch_ctrl'][0]] if bones['chain']['mch_ctrl'] else None
eb[bones['chain']['ctrl'][0]].use_inherit_scale = False
- eb[bones['chain']['ctrl'][1]].parent = eb[bones['chain']['mch_ctrl'][-1]]
+ eb[bones['chain']['ctrl'][1]].parent = eb[bones['chain']['mch_ctrl'][-1]] if bones['chain']['mch_ctrl'] else None
eb[bones['chain']['ctrl'][1]].use_inherit_scale = False
if 'pivot' in bones.keys():
@@ -314,9 +322,13 @@ class Rig:
eb[mch].parent = eb[bones['chain']['tweak'][i-1]]
if 'parent' in bones.keys():
- eb[bones['chain']['mch_auto']].parent = eb[bones['parent']]
- eb[bones['chain']['mch_ctrl'][0]].parent = eb[bones['parent']]
- eb[bones['chain']['mch_ctrl'][-1]].parent = eb[bones['parent']]
+ if self.SINGLE_BONE:
+ eb[bones['chain']['ctrl'][0]].parent = eb[bones['parent']]
+ eb[bones['chain']['ctrl'][-1]].parent = eb[bones['parent']]
+ else:
+ eb[bones['chain']['mch_auto']].parent = eb[bones['parent']]
+ eb[bones['chain']['mch_ctrl'][0]].parent = eb[bones['parent']]
+ eb[bones['chain']['mch_ctrl'][-1]].parent = eb[bones['parent']]
for i, mch_ctrl in enumerate(bones['chain']['mch_ctrl'][1:-1]):
eb[mch_ctrl].parent = eb[bones['chain']['mch_auto']]
@@ -326,14 +338,11 @@ class Rig:
if bones['chain']['conv']:
eb[bones['chain']['ctrl'][-1]].parent = eb[bones['chain']['conv']]
+ eb[bones['chain']['conv']].parent = eb[bones['chain']['conv']].parent
if self.SINGLE_BONE:
- eb[bones['chain']['ctrl'][0]].parent = None
- eb[bones['chain']['ctrl'][-1]].parent = None
- eb[bones['chain']['mch_ctrl'][0]].parent = eb[bones['chain']['ctrl'][0]]
- eb[bones['chain']['mch_ctrl'][-1]].parent = eb[bones['chain']['ctrl'][-1]]
- eb[bones['chain']['mch'][0]].parent = eb[bones['chain']['mch'][1]]
- eb[bones['chain']['mch'][1]].parent = eb[bones['chain']['mch_ctrl'][0]]
+ eb[bones['chain']['mch'][0]].parent = eb[bones['chain']['ctrl'][0]]
+ eb[bones['chain']['mch'][1]].parent = eb[bones['chain']['ctrl'][1]]
return
@@ -351,7 +360,6 @@ class Rig:
setattr(const, p, constraint[p])
def constrain_bones(self, bones):
- # DEF bones
deform = bones['def']
mch = bones['chain']['mch']
@@ -359,6 +367,17 @@ class Rig:
ctrls = bones['chain']['ctrl']
tweaks = [ctrls[0]] + bones['chain']['tweak'] + [ctrls[-1]]
+ # ORG bones
+ for i, org_bone in enumerate(self.org_bones):
+ self.make_constraint(org_bone, {
+ 'constraint': 'COPY_TRANSFORMS',
+ 'subtarget': tweaks[i],
+ 'owner_space': 'WORLD',
+ 'target_space': 'WORLD'
+ })
+
+ # DEF bones
+
for i, d in enumerate(deform):
if len(deform) > 1:
@@ -374,6 +393,14 @@ class Rig:
'subtarget': tweaks[i+1]
})
+ if bones['conv_def']:
+ self.make_constraint(bones['conv_def'], {
+ 'constraint': 'COPY_TRANSFORMS',
+ 'subtarget': bones['chain']['conv'],
+ 'owner_space': 'POSE',
+ 'target_space': 'POSE'
+ })
+
if 'pivot' in bones.keys():
step = 2/(len(self.org_bones))
for i, b in enumerate(mch_ctrl):
@@ -441,7 +468,7 @@ class Rig:
ctrl_start = pb[bones['chain']['ctrl'][0]]
ctrl_end = pb[bones['chain']['ctrl'][-1]]
mch_start = pb[bones['chain']['mch'][0]]
- mch_end = pb[bones['chain']['mch_ctrl'][-1]]
+ mch_end = pb[bones['chain']['mch_ctrl'][-1]] if bones['chain']['mch_ctrl'] else pb[bones['chain']['mch'][-1]]
if 'bbone_custom_handle_start' in dir(def_pb) and 'bbone_custom_handle_end' in dir(def_pb):
if not self.SINGLE_BONE:
@@ -498,19 +525,25 @@ class Rig:
# Assigning a widget to main ctrl bone
if 'pivot' in bones.keys():
- create_cube_widget(
+ create_chain_widget(
self.obj,
bones['pivot']['ctrl'],
+ cube=True,
radius=0.15,
- bone_transform_name=None
+ bone_transform_name=None,
+ axis=self.params.wgt_align_axis,
+ offset=self.params.wgt_offset*pb[bones['chain']['ctrl'][0]].length
)
for bone in bones['chain']['tweak']:
- create_cube_widget(
+ create_chain_widget(
self.obj,
bone,
+ cube=True,
radius=0.2,
- bone_transform_name=None
+ bone_transform_name=None,
+ axis=self.params.wgt_align_axis,
+ offset=self.params.wgt_offset*pb[bones['chain']['ctrl'][0]].length
)
create_chain_widget(
@@ -518,23 +551,34 @@ class Rig:
bones['chain']['ctrl'][0],
invert=False,
radius=0.3,
- bone_transform_name=None
+ bone_transform_name=None,
+ axis=self.params.wgt_align_axis,
+ offset=self.params.wgt_offset*pb[bones['chain']['ctrl'][0]].length
)
+ invert_last = True
+ if self.params.wgt_align_axis is not 'y' or '-y':
+ invert_last = False
+
create_chain_widget(
self.obj,
bones['chain']['ctrl'][-1],
- invert=True,
+ invert=invert_last,
radius=0.3,
- bone_transform_name=None
+ bone_transform_name=None,
+ axis=self.params.wgt_align_axis,
+ offset=self.params.wgt_offset*pb[bones['chain']['ctrl'][0]].length
)
if bones['chain']['conv']:
- create_cube_widget(
+ create_chain_widget(
self.obj,
bones['chain']['conv'],
+ cube=True,
radius=0.5,
- bone_transform_name=None
+ bone_transform_name=None,
+ axis=self.params.wgt_align_axis,
+ offset=self.params.wgt_offset*pb[bones['chain']['ctrl'][0]].length
)
# Assigning layers to tweaks and ctrls
@@ -542,6 +586,39 @@ class Rig:
return
+ def aggregate_ctrls(self, bones):
+
+ if not self.params.cluster_ctrls:
+ return
+
+ other_ctrls = []
+ all_ctrls = []
+ eb = self.obj.data.edit_bones
+
+ head_start = eb[bones['chain']['ctrl'][0]].head
+ head_tip = eb[bones['chain']['ctrl'][-1]].head
+
+ all_ctrls.extend(bones['chain']['ctrl'])
+ all_ctrls.extend(bones['chain']['tweak'])
+ all_ctrls.extend(bones['chain']['conv'])
+ for bname in eb.keys():
+ if bname not in all_ctrls and (bname.startswith('tweak') or 'ctrl' in bname):
+ other_ctrls.append(bname)
+
+ for bname in other_ctrls:
+ if eb[bname].head == head_start:
+ for child in eb[bones['chain']['ctrl'][0]].children:
+ child.parent = eb[bname]
+ eb.remove(eb[bones['chain']['ctrl'][0]])
+ bones['chain']['ctrl'][0] = bname
+ break
+
+ for bname in other_ctrls:
+ if eb[bname].head == head_tip:
+ eb.remove(eb[bones['chain']['ctrl'][-1]])
+ bones['chain']['ctrl'][-1] = bname
+ break
+
def generate(self):
bpy.ops.object.mode_set(mode='EDIT')
@@ -549,19 +626,27 @@ class Rig:
bones = {}
if eb[self.org_bones[0]].parent:
- bones['parent'] = eb[self.org_bones[0]].parent.name
+ def_name = make_deformer_name(strip_org(eb[self.org_bones[0]].parent.name))
+ if self.params.def_parenting and def_name in eb.keys():
+ bones['parent'] = def_name
+ else:
+ bones['parent'] = eb[self.org_bones[0]].parent.name
# Clear parents for org bones
for bone in self.org_bones[0:]:
eb[bone].use_connect = False
eb[bone].parent = None
- bones['def'] = self.create_deform()
+ bones['def'], bones['conv_def'] = self.create_deform()
if len(self.org_bones) > 2:
bones['pivot'] = self.create_pivot()
bones['chain'] = self.create_chain()
self.parent_bones(bones)
+
+ # ctrls snapping pass
+ self.aggregate_ctrls(bones)
+
self.constrain_bones(bones)
self.stick_to_bendy_bones(bones)
self.locks_and_widgets(bones)
@@ -576,22 +661,57 @@ def add_parameters(params):
items = [
('auto', 'Auto', ''),
- ('x', 'X', ''),
- ('y', 'Y', ''),
- ('z', 'Z', '')
+ ('x', 'X-Global', ''),
+ ('y', 'Y-Global', ''),
+ ('z', 'Z-Global', '')
]
params.tweak_axis = bpy.props.EnumProperty(
items=items,
- name="Tweak Axis",
+ name="Orient y-axis to",
+ description="Targets all ctrls y-axis to defined axis (global space)",
default='auto'
)
+ axes = [
+ ('x', 'X', ''),
+ ('y', 'Y', ''),
+ ('z', 'Z', ''),
+ ('-x', '-X', ''),
+ ('-y', '-Y', ''),
+ ('-z', '-Z', '')
+ ]
+
+ params.wgt_align_axis = bpy.props.EnumProperty(
+ items=axes,
+ name="Custom Widget orient",
+ description="Targets custom WGTs to defined axis (global space)",
+ default='y'
+ )
+
params.conv_bone = bpy.props.StringProperty(
name='Convergence bone',
default=''
)
+ params.conv_def = bpy.props.BoolProperty(
+ name="Add DEF on convergence",
+ default=False,
+ description=""
+ )
+
+ params.def_parenting = bpy.props.BoolProperty(
+ name="Prefer DEF parenting",
+ default=False,
+ description=""
+ )
+
+ params.cluster_ctrls = bpy.props.BoolProperty(
+ name="Cluster controls",
+ default=False,
+ description="Clusterize controls in the same position"
+ )
+
params.bbones = bpy.props.IntProperty(
name='bbone segments',
default=10,
@@ -599,6 +719,13 @@ def add_parameters(params):
description='Number of segments'
)
+ params.wgt_offset = bpy.props.FloatProperty(
+ name='Widget Offset',
+ default=0.0,
+ min=-10.0,
+ max=10.0
+ )
+
ControlLayersOption.TWEAK.add_parameters(params)
@@ -613,11 +740,26 @@ def parameters_ui(layout, params):
row.prop(params, "tweak_axis")
r = layout.row()
+ r.prop(params, "wgt_align_axis")
+
+ r = layout.row()
+ r.prop(params, "wgt_offset")
+
+ r = layout.row()
r.prop(params, "bbones")
r = layout.row()
r.prop_search(params, 'conv_bone', pb, "bones", text="Convergence Bone")
+ r = layout.row()
+ r.prop(params, 'conv_def')
+
+ r = layout.row()
+ r.prop(params, 'def_parenting')
+
+ r = layout.row()
+ r.prop(params, 'cluster_ctrls')
+
ControlLayersOption.TWEAK.parameters_ui(layout, params)
diff --git a/rigify/utils/widgets.py b/rigify/utils/widgets.py
index fad1065a..6d83264a 100644
--- a/rigify/utils/widgets.py
+++ b/rigify/utils/widgets.py
@@ -21,6 +21,8 @@
import bpy
import math
+from mathutils import Matrix
+
from .errors import MetarigError
from .collections import ensure_widget_collection
@@ -132,13 +134,39 @@ def create_circle_polygon(number_verts, axis, radius=1.0, head_tail=0.0):
return verts, edges
+def adjust_widget_axis(obj, axis='y', offset=0.0):
+ mesh = obj.data
+
+ if axis[0] == '-':
+ s = -1.0
+ axis = axis[1]
+ else:
+ s = 1.0
+
+ trans_matrix = Matrix.Translation((0.0, offset, 0.0))
+ rot_matrix = Matrix.Diagonal((1.0, s, 1.0, 1.0))
+
+ if axis == "x":
+ rot_matrix = Matrix.Rotation(-s*math.pi/2, 4, 'Z')
+ trans_matrix = Matrix.Translation((offset, 0.0, 0.0))
+
+ elif axis == "z":
+ rot_matrix = Matrix.Rotation(s*math.pi/2, 4, 'X')
+ trans_matrix = Matrix.Translation((0.0, 0.0, offset))
+
+ matrix = trans_matrix @ rot_matrix
+
+ for vert in mesh.vertices:
+ vert.co = matrix @ vert.co
+
+
def write_widget(obj):
""" Write a mesh object as a python script for widget use.
"""
script = ""
script += "def create_thing_widget(rig, bone_name, size=1.0, bone_transform_name=None):\n"
script += " obj = create_widget(rig, bone_name, bone_transform_name)\n"
- script += " if obj != None:\n"
+ script += " if obj is not None:\n"
# Vertices
script += " verts = ["
@@ -168,7 +196,6 @@ def write_widget(obj):
script += "\n mesh = obj.data\n"
script += " mesh.from_pydata(verts, edges, faces)\n"
script += " mesh.update()\n"
- script += " mesh.update()\n"
script += " return obj\n"
script += " else:\n"
script += " return None\n"
diff --git a/rigify/utils/widgets_basic.py b/rigify/utils/widgets_basic.py
index de04aecc..bb60237c 100644
--- a/rigify/utils/widgets_basic.py
+++ b/rigify/utils/widgets_basic.py
@@ -67,13 +67,16 @@ def create_cube_widget(rig, bone_name, radius=0.5, bone_transform_name=None):
mesh.update()
-def create_chain_widget(rig, bone_name, radius=0.5, invert=False, bone_transform_name=None):
+def create_chain_widget(rig, bone_name, cube=False, radius=0.5, invert=False, bone_transform_name=None, axis="y", offset=0.0):
"""Creates a basic chain widget
"""
obj = create_widget(rig, bone_name, bone_transform_name)
- if obj != None:
+ if obj is not None:
r = radius
- rh = radius/2
+ if cube:
+ rh = r
+ else:
+ rh = radius/2
if invert:
verts = [(rh, rh, rh), (r, -r, r), (-r, -r, r), (-rh, rh, rh), (rh, rh, -rh), (r, -r, -r), (-r, -r, -r), (-rh, rh, -rh)]
else:
@@ -82,6 +85,9 @@ def create_chain_widget(rig, bone_name, radius=0.5, invert=False, bone_transform
mesh = obj.data
mesh.from_pydata(verts, edges, [])
mesh.update()
+ from .widgets import adjust_widget_axis
+ adjust_widget_axis(obj, axis=axis, offset=offset)
+ return obj
def create_sphere_widget(rig, bone_name, bone_transform_name=None):