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:
authorThomas Larsson <thomas_larsson_01@hotmail.com>2011-07-04 21:22:49 +0400
committerThomas Larsson <thomas_larsson_01@hotmail.com>2011-07-04 21:22:49 +0400
commita6f0452eb818c5d8604f6cac5c9226c5d4400a59 (patch)
treea10ccc83dfc5ca2e686b9850a01a73d973e269a9 /io_import_scene_mhx.py
parent54f552eec3d7712bc932249c5aa0cd79c2772615 (diff)
Mhx importer v 1.5.0: can now use Rigify.
Diffstat (limited to 'io_import_scene_mhx.py')
-rw-r--r--io_import_scene_mhx.py415
1 files changed, 328 insertions, 87 deletions
diff --git a/io_import_scene_mhx.py b/io_import_scene_mhx.py
index e861fcf8..201d2f94 100644
--- a/io_import_scene_mhx.py
+++ b/io_import_scene_mhx.py
@@ -26,7 +26,7 @@
"""
Abstract
MHX (MakeHuman eXchange format) importer for Blender 2.5x.
-Version 1.4.0
+Version 1.5.0
This script should be distributed with Blender.
If not, place it in the .blender/scripts/addons dir
@@ -39,9 +39,9 @@ Alternatively, run the script in the script editor (Alt-P), and access from the
bl_info = {
'name': 'Import: MakeHuman (.mhx)',
'author': 'Thomas Larsson',
- 'version': (1, 4, 0),
- "blender": (2, 5, 7),
- "api": 35774,
+ 'version': (1, 5, 0),
+ "blender": (2, 5, 8),
+ "api": 37702,
'location': "File > Import > MakeHuman (.mhx)",
'description': 'Import files in the MakeHuman eXchange format (.mhx)',
'warning': '',
@@ -51,9 +51,9 @@ bl_info = {
'category': 'Import-Export'}
MAJOR_VERSION = 1
-MINOR_VERSION = 4
+MINOR_VERSION = 5
SUB_VERSION = 0
-BLENDER_VERSION = (2, 57, 0)
+BLENDER_VERSION = (2, 58, 0)
#
#
@@ -114,7 +114,8 @@ T_Rigify = 0x1000
T_Opcns = 0x2000
T_Symm = 0x4000
-toggle = T_EnforceVersion + T_Replace + T_Mesh + T_Armature + T_Face + T_Shape + T_Proxy + T_Clothes
+toggle = (T_EnforceVersion + T_Replace + T_Mesh + T_Armature +
+ T_Face + T_Shape + T_Proxy + T_Clothes + T_Rigify)
#
# Blender versions
@@ -481,6 +482,12 @@ def parse(tokens):
hideLayers(val)
elif key == "CorrectRig":
correctRig(val)
+ elif key == "Rigify":
+ rig = loadedData['Object'][val[0]]
+ rig['MhxRigify'] = True
+ bpy.context.scene.objects.active = rig
+ if toggle & T_Rigify:
+ rigifyMhx(bpy.context, rig)
elif key == 'AnimationData':
try:
ob = loadedData['Object'][val[0]]
@@ -1532,11 +1539,6 @@ def parseArmature (args, tokens):
obname = args[1]
mode = args[2]
- if mode == 'Rigify':
- toggle |= T_Rigify
- return parseRigify(amtname, obname, tokens)
-
- toggle &= ~T_Rigify
amt = bpy.data.armatures.new(amtname)
ob = createObject('ARMATURE', obname, amt, amtname)
@@ -1574,52 +1576,6 @@ def parseArmature (args, tokens):
defaultKey(key, val, sub, "amt", ['MetaRig'], globals(), locals())
bpy.ops.object.mode_set(mode='OBJECT')
return amt
-
-#
-# parseRigify(amtname, obname, tokens):
-#
-
-def parseRigify(amtname, obname, tokens):
- (key,val,sub) = tokens[0]
- if key != 'MetaRig':
- raise NameError("Expected MetaRig")
- typ = val[0]
- if typ == "human":
- bpy.ops.object.armature_human_advanced_add()
- else:
- bpy.ops.pose.metarig_sample_add(type = typ)
- ob = bpy.context.scene.objects.active
- amt = ob.data
- loadedData['Rigify'][obname] = ob
- loadedData['Armature'][amtname] = amt
- loadedData['Object'][obname] = ob
- print("Rigify object", ob, amt)
-
- bpy.ops.object.mode_set(mode='OBJECT')
- bpy.ops.object.mode_set(mode='EDIT')
-
- heads = {}
- tails = {}
- for (bname, bone) in amt.edit_bones.items():
- heads[bname] = 10*theScale*bone.head
- tails[bname] = 10*theScale*bone.tail
-
- for (key, val, sub) in tokens:
- if key == 'Bone':
- bname = val[0]
- print("Bone", bname)
- try:
- bone = amt.edit_bones[bname]
- except:
- print("Did not find bone %s" % bname)
- bone = None
- print(" -> ", bone)
- if bone:
- parseBone(bone, amt, sub, heads, tails)
- else:
- defaultKey(key, val, sub, "amt", ['MetaRig'], globals(), locals())
- bpy.ops.object.mode_set(mode='OBJECT')
- return amt
#
# parseBone(bone, amt, tokens, heads, tails):
@@ -1654,8 +1610,6 @@ def parseBone(bone, amt, tokens, heads, tails):
def parsePose (args, tokens):
global todo
- if toggle & T_Rigify:
- return
name = args[0]
ob = loadedData['Object'][name]
bpy.context.scene.objects.active = ob
@@ -2084,21 +2038,6 @@ def postProcess(args):
ob = None
if toggle & T_Diamond == 0 and ob:
deleteDiamonds(ob)
- if toggle & T_Rigify and False:
- for rig in loadedData['Rigify'].values():
- bpy.context.scene.objects.active = rig
- print("Rigify", rig)
- bpy.ops.pose.metarig_generate()
- print("Metarig generated")
- #bpy.context.scene.objects.unlink(rig)
-
- rig = bpy.context.scene.objects.active
- print("Rigged", rig, bpy.context.object)
- ob = loadedData['Object'][human]
- mod = ob.modifiers[0]
- print(ob, mod, mod.object)
- mod.object = rig
- print("Rig changed", mod.object)
return
#
@@ -2611,9 +2550,321 @@ def writeDefaults():
fp.close()
return
+###################################################################################
+#
+# Postprocessing of rigify rig
+#
+# rigifyMhx(context, mhx):
+#
+###################################################################################
+
+def rigifyMhx(context, mhx):
+ print("Modifying MHX rig to Rigify")
+ # Delete widgets
+ scn = context.scene
+ for ob in scn.objects:
+ if ob.type == 'MESH' and ob.name[0:3] == "WGT":
+ scn.objects.unlink(ob)
+
+ # Save mhx bone locations
+ name = mhx.name
+ heads = {}
+ tails = {}
+ rolls = {}
+ parents = {}
+ extras = {}
+ bpy.ops.object.mode_set(mode='EDIT')
+
+ newParents = {
+ 'head' : 'DEF-head',
+ 'ribs' : 'DEF-ribs',
+ 'upper_arm.L' : 'DEF-upper_arm.L.02',
+ 'thigh.L' : 'DEF-thigh.L.02',
+ 'upper_arm.R' : 'DEF-upper_arm.R.02',
+ 'thigh.R' : 'DEF-thigh.R.02',
+ }
+
+ for eb in mhx.data.edit_bones:
+ heads[eb.name] = eb.head.copy()
+ tails[eb.name] = eb.tail.copy()
+ rolls[eb.name] = eb.roll
+ if eb.parent:
+ par = eb.parent.name
+ print(eb.name, par)
+ try:
+ parents[eb.name] = newParents[par]
+ except:
+ parents[eb.name] = par
+ else:
+ parents[eb.name] = None
+ extras[eb.name] = not eb.layers[16]
+ bpy.ops.object.mode_set(mode='OBJECT')
+
+ # Find corresponding meshes. Can be several (clothes etc.)
+ meshes = []
+ for ob in scn.objects:
+ for mod in ob.modifiers:
+ if (mod.type == 'ARMATURE' and mod.object == mhx):
+ meshes.append((ob, mod))
+ if meshes == []:
+ raise NameError("Did not find matching mesh")
+
+ # Rename Head vertex group
+ for (mesh, mod) in meshes:
+ try:
+ vg = mesh.vertex_groups['DfmHead']
+ vg.name = 'DEF-head'
+ except:
+ pass
+
+ # Change rigify bone locations
+ scn.objects.active = None
+ try:
+ bpy.ops.object.armature_human_advanced_add()
+ success = True
+ except:
+ success = False
+ if not success:
+ raise NameError("Unable to create advanced human. Make sure that the Rigify add-on is enabled. It is found under Rigging.")
+ return
+
+ rigify = context.object
+ bpy.ops.object.mode_set(mode='EDIT')
+ for eb in rigify.data.edit_bones:
+ eb.head = heads[eb.name]
+ eb.tail = tails[eb.name]
+ eb.roll = rolls[eb.name]
+ extras[eb.name] = False
+
+ fingerPlanes = [
+ ('UP-thumb.L', 'thumb.01.L', 'thumb.03.L', ['thumb.02.L']),
+ ('UP-index.L', 'finger_index.01.L', 'finger_index.03.L', ['finger_index.02.L']),
+ ('UP-middle.L', 'finger_middle.01.L', 'finger_middle.03.L', ['finger_middle.02.L']),
+ ('UP-ring.L', 'finger_ring.01.L', 'finger_ring.03.L', ['finger_ring.02.L']),
+ ('UP-pinky.L', 'finger_pinky.01.L', 'finger_pinky.03.L', ['finger_pinky.02.L']),
+ ('UP-thumb.R', 'thumb.01.R', 'thumb.03.R', ['thumb.02.R']),
+ ('UP-index.R', 'finger_index.01.R', 'finger_index.03.R', ['finger_index.02.R']),
+ ('UP-middle.R', 'finger_middle.01.R', 'finger_middle.03.R', ['finger_middle.02.R']),
+ ('UP-ring.R', 'finger_ring.01.R', 'finger_ring.03.R', ['finger_ring.02.R']),
+ ('UP-pinky.R', 'finger_pinky.01.R', 'finger_pinky.03.R', ['finger_pinky.02.R']),
+ ]
+
+ for (upbone, first, last, middles) in fingerPlanes:
+ extras[upbone] = False
+ #lineateChain(upbone, first, last, middles, 0.01, rigify, heads, tails)
+
+ ikPlanes = [
+ ('UP-leg.L', 'thigh.L', 'shin.L'),
+ ('UP-arm.L', 'upper_arm.L', 'forearm.L'),
+ ('UP-leg.R', 'thigh.R', 'shin.R'),
+ ('UP-arm.R', 'upper_arm.R', 'forearm.R'),
+ ]
+
+ for (upbone, first, last) in ikPlanes:
+ extras[upbone] = False
+ lineateChain(upbone, first, last, [], 0.1, rigify, heads, tails)
+
+ bpy.ops.object.mode_set(mode='OBJECT')
+
+ # Generate meta rig
+ bpy.ops.pose.rigify_generate()
+ scn.objects.unlink(rigify)
+ meta = context.object
+ meta.name = name+"Meta"
+ meta.show_x_ray = True
+ for (mesh, mod) in meshes:
+ mod.object = meta
+
+ # Parent widgets under empty
+ empty = bpy.data.objects.new("Widgets", None)
+ scn.objects.link(empty)
+ empty.layers = 20*[False]
+ empty.layers[19] = True
+ for ob in scn.objects:
+ if ob.type == 'MESH' and ob.name[0:4] == "WGT-" and not ob.parent:
+ ob.parent = empty
+
+ # Copy extra bones to meta rig
+ bpy.ops.object.mode_set(mode='EDIT')
+ for name in heads.keys():
+ if extras[name]:
+ eb = meta.data.edit_bones.new(name)
+ eb.head = heads[name]
+ eb.tail = tails[name]
+ eb.roll = rolls[name]
+ for name in heads.keys():
+ if extras[name] and parents[name]:
+ eb = meta.data.edit_bones[name]
+ eb.parent = meta.data.edit_bones[parents[name]]
+
+ # Copy constraints etc.
+ bpy.ops.object.mode_set(mode='POSE')
+ for name in heads.keys():
+ if extras[name]:
+ pb1 = mhx.pose.bones[name]
+ pb2 = meta.pose.bones[name]
+ pb2.custom_shape = pb1.custom_shape
+ pb2.lock_location = pb1.lock_location
+ pb2.lock_rotation = pb1.lock_rotation
+ pb2.lock_scale = pb1.lock_scale
+ b1 = pb1.bone
+ b2 = pb2.bone
+ b2.use_deform = b1.use_deform
+ b2.hide_select = b1.hide_select
+ b2.show_wire = b1.show_wire
+ layers = 32*[False]
+ if b1.layers[8]:
+ layers[28] = True
+ else:
+ layers[29] = True
+ if b1.layers[10]:
+ layers[2] = True
+ b2.layers = layers
+ for cns1 in pb1.constraints:
+ cns2 = copyConstraint(cns1, pb1, pb2, mhx, meta)
+ if cns2.type == 'CHILD_OF':
+ meta.data.bones.active = pb2.bone
+ bpy.ops.constraint.childof_set_inverse(constraint=cns2.name, owner='BONE')
+
+ # Create animation data
+ if mhx.animation_data:
+ for fcu in mhx.animation_data.drivers:
+ meta.animation_data.drivers.from_existing(src_driver=fcu)
+
+ fixDrivers(meta.animation_data, mhx, meta)
+ for (mesh, mod) in meshes:
+ skeys = mesh.data.shape_keys
+ if skeys:
+ fixDrivers(skeys.animation_data, mhx, meta)
+
+ scn.objects.unlink(mhx)
+ print("Rigify rig complete")
+ return
+
+#
+# lineateChain(upbone, first, last, middles, minDist, rigify, heads, tails):
+# lineate(pt, start, minDist, normal, offVector):
+#
+
+def lineateChain(upbone, first, last, middles, minDist, rigify, heads, tails):
+ fb = rigify.data.edit_bones[first]
+ lb = rigify.data.edit_bones[last]
+ uhead = heads[upbone]
+ utail = tails[upbone]
+ tang = lb.tail - fb.head
+ tangent = tang/tang.length
+ up = (uhead+utail)/2 - fb.head
+ norm = up - tangent*tangent.dot(up)
+ normal = norm/norm.length
+ offVector = tangent.cross(normal)
+ vec = utail - uhead
+ fb.tail = lineate(fb.tail, fb.head, minDist, normal, offVector)
+ lb.head = lineate(lb.head, fb.head, minDist, normal, offVector)
+ for bone in middles:
+ mb = rigify.data.edit_bones[bone]
+ mb.head = lineate(mb.head, fb.head, minDist, normal, offVector)
+ mb.tail = lineate(mb.tail, fb.head, minDist, normal, offVector)
+ return
+
+def lineate(pt, start, minDist, normal, offVector):
+ diff = pt - start
+ diff = diff - offVector*offVector.dot(diff)
+ dist = diff.dot(normal)
+ if dist < minDist:
+ diff += (minDist - dist)*normal
+ return start + diff
+
+#
+# fixDrivers(adata, mhx, meta):
+#
+
+def fixDrivers(adata, mhx, meta):
+ if not adata:
+ return
+ for fcu in adata.drivers:
+ for var in fcu.driver.variables:
+ for targ in var.targets:
+ if targ.id == mhx:
+ targ.id = meta
+ return
+
+#
+# copyConstraint(cns1, pb1, pb2, mhx, meta):
+#
+
+def copyConstraint(cns1, pb1, pb2, mhx, meta):
+ substitute = {
+ 'Head' : 'DEF-head',
+ 'MasterFloor' : 'root',
+ 'upper_arm.L' : 'DEF-upper_arm.L.01',
+ 'upper_arm.R' : 'DEF-upper_arm.R.01',
+ 'thigh.L' : 'DEF-thigh.L.01',
+ 'thigh.R' : 'DEF-thigh.R.01',
+ 'shin.L' : 'DEF-shin.L.01',
+ 'shin.R' : 'DEF-shin.R.01'
+ }
+
+ cns2 = pb2.constraints.new(cns1.type)
+ for prop in dir(cns1):
+ if prop == 'target':
+ if cns1.target == mhx:
+ cns2.target = meta
+ else:
+ cns2.target = cns1.target
+ elif prop == 'subtarget':
+ try:
+ cns2.subtarget = substitute[cns1.subtarget]
+ except:
+ cns2.subtarget = cns1.subtarget
+ elif prop[0] != '_':
+ try:
+ expr = "cns2.%s = cns1.%s" % (prop, prop)
+ #print(pb1.name, expr)
+ exec(expr)
+ except:
+ pass
+ return cns2
+
+#
+# class OBJECT_OT_RigifyMhxButton(bpy.types.Operator):
+#
+
+class OBJECT_OT_RigifyMhxButton(bpy.types.Operator):
+ bl_idname = "mhxrig.rigify_mhx"
+ bl_label = "Rigify MHX rig"
+
+ def execute(self, context):
+ rigifyMhx(context, context.object)
+ return{'FINISHED'}
+
+#
+# class RigifyMhxPanel(bpy.types.Panel):
+#
+
+class RigifyMhxPanel(bpy.types.Panel):
+ bl_label = "Rigify MHX"
+ bl_space_type = "VIEW_3D"
+ bl_region_type = "UI"
+
+ @classmethod
+ def poll(cls, context):
+ if context.object:
+ try:
+ return context.object['MhxRigify']
+ except:
+ return False
+ return False
+
+ def draw(self, context):
+ layout = self.layout
+ layout.operator("mhxrig.rigify_mhx")
+ return
+
+###################################################################################
#
# User interface
#
+###################################################################################
DEBUG = False
from bpy.props import StringProperty, FloatProperty, EnumProperty, BoolProperty
@@ -2633,8 +2884,8 @@ MhxBoolProps = [
("shape", "Body shapes", "Include body shapekeys", T_Shape),
("symm", "Symmetric shapes", "Keep shapekeys symmetric", T_Symm),
("diamond", "Diamonds", "Keep joint diamonds", T_Diamond),
- ("bend", "Bend joints", "Bend joints for better IK", T_Bend),
- #("opcns", "Operator constraints", "Only for Aligorith", T_Opcns),
+ ("rigify", "Rigify", "Create rigify control rig", T_Rigify),
+ #("bend", "Bend joints", "Bend joints for better IK", T_Bend),
]
class ImportMhx(bpy.types.Operator, ImportHelper):
@@ -2702,16 +2953,6 @@ if __name__ == "__main__":
pass
register()
-#
-# Testing
-#
-"""
-#readMhxFile("C:/Documents and Settings/xxxxxxxxxxxxxxxxxxxx/Mina dokument/makehuman/exports/foo-25.mhx", 'Classic')
-readMhxFile("/home/thomas/makehuman/exports/foo-25.mhx", 1.0)
-
-#toggle = T_Replace + T_Mesh + T_Armature + T_MHX
-#readMhxFile("/home/thomas/myblends/test.mhx", 1.0)
-"""