From 36ff1e8011076098d194722d03988f9a297c93e0 Mon Sep 17 00:00:00 2001 From: Thomas Larsson Date: Thu, 4 Jul 2013 11:42:15 +0000 Subject: FK-IK snapping now works (more or less) with both the alpha7 and alpha8 meshes. --- io_import_scene_mhx.py | 1062 +++++++++++++++++++++++++----------------------- 1 file changed, 552 insertions(+), 510 deletions(-) (limited to 'io_import_scene_mhx.py') diff --git a/io_import_scene_mhx.py b/io_import_scene_mhx.py index 79065155..2e1c4428 100644 --- a/io_import_scene_mhx.py +++ b/io_import_scene_mhx.py @@ -38,8 +38,8 @@ 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, 15, 4), - "blender": (2, 67, 0), + 'version': (1, 16, 0), + "blender": (2, 67, 1), 'location': "File > Import > MakeHuman (.mhx)", 'description': 'Import files in the MakeHuman eXchange format (.mhx)', 'warning': '', @@ -49,9 +49,12 @@ bl_info = { 'category': 'Import-Export'} MAJOR_VERSION = 1 -MINOR_VERSION = 15 +MINOR_VERSION = 16 FROM_VERSION = 13 -SUB_VERSION = 3 +SUB_VERSION = 0 + +majorVersion = MAJOR_VERSION +minorVersion = MINOR_VERSION # # @@ -117,9 +120,9 @@ T_Rigify = 0x1000 T_Opcns = 0x2000 T_Symm = 0x4000 -DefaultToggle = ( T_EnforceVersion + T_Mesh + T_Armature + +DefaultToggle = ( T_EnforceVersion + T_Mesh + T_Armature + T_Shapekeys + T_ShapeDrivers + T_Proxy + T_Clothes + T_Rigify ) - + toggle = DefaultToggle toggleSettings = toggle @@ -146,7 +149,7 @@ def initLoadedData(): 'Image' : {}, 'MaterialTextureSlot' : {}, 'Texture' : {}, - + 'Bone' : {}, 'BoneGroup' : {}, 'Rigify' : {}, @@ -165,7 +168,7 @@ def initLoadedData(): 'MaterialSlot' : {}, } return - + def reinitGlobalData(): global loadedData for key in [ @@ -233,7 +236,7 @@ def readMhxFile(filePath): file= open(fileName, "rU") print( "Tokenizing" ) lineNo = 0 - for line in file: + for line in file: # print(line) lineSplit= line.split() lineNo += 1 @@ -287,11 +290,11 @@ def readMhxFile(filePath): file.close() if level != 0: - MyError("Tokenizer error (%d).\nThe mhx file has been corrupted.\nTry to export it again from MakeHuman." % level) + MyError("Tokenizer error (%d).\nThe mhx file has been corrupted.\nTry to export it again from MakeHuman." % level) scn = clearScene() print( "Parsing" ) parse(tokens) - + for (expr, glbals, lcals) in todo: try: print("Doing %s" % expr) @@ -305,7 +308,7 @@ def readMhxFile(filePath): scn.objects.active = theArmature theArmature.MhAlpha8 = not alpha7 #bpy.ops.wm.properties_edit(data_path="object", property="MhxRig", value=theArmature["MhxRig"]) - + time2 = time.clock() msg = "File %s loaded in %g s" % (fileName, time2-time1) if nErrors: @@ -369,11 +372,14 @@ ifResult = False def parse(tokens): global MHX249, ifResult, theScale, defaultScale, One - - for (key, val, sub) in tokens: + global majorVersion, minorVersion + + for (key, val, sub) in tokens: data = None if key == 'MHX': - checkMhxVersion(int(val[0]), int(val[1])) + majorVersion = int(val[0]) + minorVersion = int(val[1]) + checkMhxVersion(majorVersion, minorVersion) elif key == 'MHX249': MHX249 = eval(val[0]) print("Blender 2.49 compatibility mode is %s\n" % MHX249) @@ -387,12 +393,12 @@ def parse(tokens): print(msg) elif key == 'error': msg = concatList(val) - MyError(msg) + MyError(msg) elif key == 'NoScale': if eval(val[0]): theScale = 1.0 else: - theScale = defaultScale + theScale = defaultScale One = 1.0/theScale elif key == "Object": parseObject(val, sub) @@ -461,9 +467,9 @@ def parse(tokens): MyError("ShapeKeys object %s does not exist" % val[0]) if ob: bpy.context.scene.objects.active = ob - parseShapeKeys(ob, ob.data, val, sub) + parseShapeKeys(ob, ob.data, val, sub) else: - data = parseDefaultType(key, val, sub) + data = parseDefaultType(key, val, sub) # # parseDefaultType(typ, args, tokens): @@ -485,7 +491,7 @@ def parseDefaultType(typ, args, tokens): for (key, val, sub) in tokens: defaultKey(key, val, sub, 'data', [], globals(), locals()) return data - + # # concatList(elts) # @@ -515,7 +521,7 @@ def parseAction(args, tokens): for (key, val, sub) in tokens: if key == 'FCurve': prepareActionFCurve(ob, created, val, sub) - + act = ob.animation_data.action loadedData['Action'][name] = act if act is None: @@ -523,7 +529,7 @@ def parseAction(args, tokens): return act act.name = name print("Action", name, act, ob) - + for (key, val, sub) in tokens: if key == 'FCurve': fcu = parseActionFCurve(act, ob, val, sub) @@ -533,7 +539,7 @@ def parseAction(args, tokens): bpy.ops.object.mode_set(mode='OBJECT') return act -def prepareActionFCurve(ob, created, args, tokens): +def prepareActionFCurve(ob, created, args, tokens): dataPath = args[0] index = args[1] (expr, channel) = channelFromDataPath(dataPath, index) @@ -635,12 +641,12 @@ def parseKeyFramePoint(pt, args, tokens): def parseAnimationData(rna, args, tokens): if not eval(args[1]): return - if rna.animation_data is None: + if rna.animation_data is None: rna.animation_data_create() adata = rna.animation_data for (key, val, sub) in tokens: if key == 'FCurve': - fcu = parseAnimDataFCurve(adata, rna, val, sub) + fcu = parseAnimDataFCurve(adata, rna, val, sub) else: defaultKey(key, val, sub, 'adata', [], globals(), locals()) return adata @@ -687,7 +693,7 @@ def parseDriver(adata, dataPath, index, rna, args, tokens): for n in range(len(words)-1): expr += "." + words[n] expr += ".driver_add('%s', index)" % channel - + fcu = eval(expr) drv = fcu.driver drv.type = args[0] @@ -743,7 +749,7 @@ def parseDriverTarget(var, nTarget, rna, args, tokens): defaultKey(key, val, sub, 'targ', [], globals(), locals()) return targ - + # # parseMaterial(args, ext, tokens): # parseMTex(mat, args, tokens): @@ -778,7 +784,7 @@ def parseMaterial(args, tokens): else: exclude = ['specular_intensity', 'tangent_shading'] defaultKey(key, val, sub, 'mat', [], globals(), locals()) - + return mat def parseMTex(mat, args, tokens): @@ -804,7 +810,7 @@ def parseTexture(args, tokens): name = args[0] tex = bpy.data.textures.new(name=name, type=args[1]) loadedData['Texture'][name] = tex - + for (key, val, sub) in tokens: if key == 'Image': try: @@ -838,7 +844,7 @@ def parseRamp(data, args, tokens): n += 1 else: defaultKey(key, val, sub, "tex", ['use_nodes', 'use_textures', 'contrast'], globals(), locals()) - + def parseSSS(mat, args, tokens): sss = mat.subsurface_scattering for (key, val, sub) in tokens: @@ -921,7 +927,7 @@ def loadImage(relFilepath): print( "No such file: %s" % filepath.encode('utf-8','strict') ) return None - + def parseImage(args, tokens): global todo imgName = args[0] @@ -946,7 +952,7 @@ def parseImage(args, tokens): # createObject(type, name, data, datName): # setObjectAndData(args, typ): # - + def parseObject(args, tokens): if verbosity > 2: print( "Parsing object %s" % args ) @@ -960,7 +966,7 @@ def parseObject(args, tokens): linkObject(ob, None) else: try: - data = loadedData[typ.capitalize()][datName] + data = loadedData[typ.capitalize()][datName] except: MyError("Failed to find data: %s %s %s" % (name, typ, datName)) return @@ -989,7 +995,7 @@ def parseObject(args, tokens): parseDefault(ob.field, sub, {}, []) else: defaultKey(key, val, sub, "ob", ['type', 'data'], globals(), locals()) - + if bpy.context.object == ob: if ob.type == 'MESH': bpy.ops.object.shade_smooth() @@ -998,13 +1004,13 @@ def parseObject(args, tokens): return def createObject(typ, name, data, datName): - # print( "Creating object %s %s %s" % (typ, name, data) ) + # print( "Creating object %s %s %s" % (typ, name, data) ) ob = bpy.data.objects.new(name, data) if data: loadedData[typ.capitalize()][datName] = data loadedData['Object'][name] = ob return ob - + def linkObject(ob, data): #print("Data", data, ob.data) if data and ob.data is None: @@ -1051,7 +1057,7 @@ def parseModifier(ob, args, tokens): hookAssignNth(mod, int(val[1]), True, ob.data.vertices) else: MyError("Unknown hook %s" % val) - else: + else: defaultKey(key, val, sub, 'mod', [], globals(), locals()) return mod @@ -1173,14 +1179,14 @@ def parseMesh (args, tokens): me.from_pydata(verts, edges, []) me.update() linkObject(ob, me) - + if faces: try: me.polygons BMeshAware = True except: BMeshAware = False - + mats = [] nuvlayers = 0 for (key, val, sub) in tokens: @@ -1191,14 +1197,14 @@ def parseMesh (args, tokens): parseUvTextureBMesh(val, sub, me) else: parseUvTextureNoBMesh(val, sub, me) - elif key == 'MeshColorLayer': + elif key == 'MeshColorLayer': parseVertColorLayer(val, sub, me) elif key == 'VertexGroup': parseVertexGroup(ob, me, val, sub) elif key == 'ShapeKeys': parseShapeKeys(ob, me, val, sub) elif key == 'Material': - try: + try: mat = loadedData['Material'][val[0]] except: mat = None @@ -1219,7 +1225,7 @@ def parseMesh (args, tokens): # parseVerts(tokens): # parseEdges(tokens): # parseFaces(tokens): -# parseFaces2(tokens, me): +# parseFaces2(tokens, me): # def parseVerts(tokens): @@ -1235,8 +1241,8 @@ def parseEdges(tokens): if key == 'e': edges.append((int(val[0]), int(val[1]))) return edges - -def parseFaces(tokens): + +def parseFaces(tokens): faces = [] for (key, val, sub) in tokens: if key == 'f': @@ -1247,7 +1253,7 @@ def parseFaces(tokens): faces.append(face) return faces -def parseFaces2BMesh(tokens, me): +def parseFaces2BMesh(tokens, me): n = 0 for (key, val, sub) in tokens: if key == 'ft': @@ -1277,7 +1283,7 @@ def parseFaces2BMesh(tokens, me): f.use_smooth = smooth return -def parseFaces2NoBMesh(tokens, me): +def parseFaces2NoBMesh(tokens, me): n = 0 for (key, val, sub) in tokens: if key == 'ft': @@ -1319,7 +1325,7 @@ def parseUvTextureBMesh(args, tokens, me): uvtex = me.uv_textures[-1] uvtex.name = name uvloop = me.uv_layers[-1] - loadedData['MeshTextureFaceLayer'][name] = uvloop + loadedData['MeshTextureFaceLayer'][name] = uvloop for (key, val, sub) in tokens: if key == 'Data': parseUvTexDataBMesh(val, sub, uvloop.data) @@ -1362,7 +1368,7 @@ def parseUvTexDataNoBMesh(args, tokens, data): data[n].uv3 = (float(val[4]), float(val[5])) if len(val) > 6: data[n].uv4 = (float(val[6]), float(val[7])) - n += 1 + n += 1 return # @@ -1390,7 +1396,7 @@ def parseVertColorData(args, tokens, data): data[n].color2 = eval(val[1]) data[n].color3 = eval(val[2]) data[n].color4 = eval(val[3]) - n += 1 + n += 1 return @@ -1451,10 +1457,10 @@ def parseShapeKeys(ob, me, args, tokens): if name in ["REST", "ETC"]: name = name.capitalize() prop = "Mhv" + name - parseUnits(prop, ob, sub) + parseUnits(prop, ob, sub) ob.active_shape_key_index = 0 - + def parseUnits(prop, ob, sub): string = "" for words in sub: @@ -1502,9 +1508,9 @@ def addShapeKey(ob, name, vgroup, tokens): else: defaultKey(key, val, sub, "skey", [], globals(), locals()) - return + return + - # # parseArmature (obName, args, tokens) # @@ -1513,14 +1519,14 @@ def parseArmature (args, tokens): global toggle, theArmature if verbosity > 2: print( "Parsing armature %s" % args ) - + amtname = args[0] obname = args[1] mode = args[2] - + amt = bpy.data.armatures.new(amtname) - ob = createObject('ARMATURE', obname, amt, amtname) - linkObject(ob, amt) + ob = createObject('ARMATURE', obname, amt, amtname) + linkObject(ob, amt) theArmature = ob bpy.ops.object.mode_set(mode='OBJECT') @@ -1553,9 +1559,9 @@ def parseArmature (args, tokens): else: defaultKey(key, val, sub, "amt", ['MetaRig'], globals(), locals()) bpy.ops.object.mode_set(mode='OBJECT') - + return amt - + # # parseBone(bone, amt, tokens, heads, tails): # @@ -1586,7 +1592,7 @@ def parsePose (args, tokens): ob = loadedData['Object'][name] bpy.context.scene.objects.active = ob bpy.ops.object.mode_set(mode='POSE') - pbones = ob.pose.bones + pbones = ob.pose.bones nGrps = 0 for (key, val, sub) in tokens: if key == 'Posebone': @@ -1630,14 +1636,14 @@ def parsePoseBone(pbones, ob, args, tokens): name = args[0] pb = pbones[name] amt = ob.data - amt.bones.active = pb.bone + amt.bones.active = pb.bone for (key, val, sub) in tokens: if key == 'Constraint': - amt.bones.active = pb.bone + amt.bones.active = pb.bone cns = parseConstraint(pb.constraints, pb, val, sub) elif key == 'bpyops': - amt.bones.active = pb.bone + amt.bones.active = pb.bone expr = "bpy.ops.%s" % val[0] print(expr) exec(expr) @@ -1655,7 +1661,7 @@ def parsePoseBone(pbones, ob, args, tokens): #bpy.ops.object.mode_set(mode='OBJECT') amt.bones[name].hide = eval(val[0]) #bpy.ops.object.mode_set(mode='POSE') - + else: defaultKey(key, val, sub, "pb", [], globals(), locals()) #print("pb %s done" % name) @@ -1669,7 +1675,7 @@ def parseArray(data, exts, args): exec(expr) n += 1 return - + # # parseConstraint(constraints, pb, args, tokens) # @@ -1779,13 +1785,13 @@ def parseSpline(cu, args, tokens): else: defaultKey(key, val, sub, "spline", [], globals(), locals()) return - + def parseBezier(bez, args, tokens): bez.co = eval(args[0]) - bez.co = theScale*bez.co - bez.handle1 = eval(args[1]) + bez.co = theScale*bez.co + bez.handle1 = eval(args[1]) bez.handle1_type = args[2] - bez.handle2 = eval(args[3]) + bez.handle2 = eval(args[3]) bez.handle2_type = args[4] return @@ -1804,7 +1810,7 @@ def parseLattice (args, tokens): if verbosity > 2: print( "Parsing lattice %s" % args ) bpy.ops.object.add(type='LATTICE') - lat = setObjectAndData(args, 'Lattice') + lat = setObjectAndData(args, 'Lattice') for (key, val, sub) in tokens: if key == 'Points': parseLatticePoints(val, sub, lat.points) @@ -1834,7 +1840,7 @@ def parseLamp (args, tokens): if verbosity > 2: print( "Parsing lamp %s" % args ) bpy.ops.object.add(type='LAMP') - lamp = setObjectAndData(args, 'Lamp') + lamp = setObjectAndData(args, 'Lamp') for (key, val, sub) in tokens: if key == 'FalloffCurve': parseFalloffCurve(lamp.falloff_curve, val, sub) @@ -1930,9 +1936,9 @@ def parseScene (args, tokens): elif key == 'RenderSettings': parseRenderSettings(scn.render, sub, []) elif key == 'ToolSettings': - subkeys = {'ImagePaint' : "image_paint", - 'Sculpt' : "sculpt", - 'VertexPaint' : "vertex_paint", + subkeys = {'ImagePaint' : "image_paint", + 'Sculpt' : "sculpt", + 'VertexPaint' : "vertex_paint", 'WeightPaint' : "weight_paint" } parseDefault(scn.tool_settings, sub, subkeys, []) elif key == 'UnitSettings': @@ -1975,7 +1981,7 @@ def parseDefineProperty(args, tokens): def correctRig(args): human = args[0] - print("CorrectRig %s" % human) + print("CorrectRig %s" % human) try: ob = loadedData['Object'][human] except: @@ -2003,7 +2009,7 @@ def correctRig(args): for (pb, cns, inf) in cnslist: cns.influence = inf return - + # # postProcess(args) @@ -2011,14 +2017,14 @@ def correctRig(args): def postProcess(args): human = args[0] - print("Postprocess %s" % human) + print("Postprocess %s" % human) try: ob = loadedData['Object'][human] except: ob = None if toggle & T_Diamond == 0 and ob: - deleteDiamonds(ob) - return + deleteDiamonds(ob) + return # # deleteDiamonds(ob) @@ -2042,17 +2048,17 @@ def deleteDiamonds(ob): break if invisioNum < 0: print("WARNING: Nu Invisio material found. Cannot delete helper geometry") - elif BMeshAware: - for f in me.polygons: + elif BMeshAware: + for f in me.polygons: if f.material_index >= invisioNum: for vn in f.vertices: me.vertices[vn].select = True - else: - for f in me.faces: + else: + for f in me.faces: if f.material_index >= invisioNum: for vn in f.vertices: me.vertices[vn].select = True - if BMeshAware and toggle&T_CrashSafe: + if BMeshAware and toggle&T_CrashSafe: theMessage = "\n *** WARNING ***\nHelper deletion turned off due to Blender crash.\nHelpers can be deleted by deleting all selected vertices in Edit mode\n **********\n" print(theMessage) else: @@ -2063,7 +2069,7 @@ def deleteDiamonds(ob): bpy.ops.object.mode_set(mode='OBJECT') print("Back to object mode") return - + # # defaultKey(ext, args, tokens, var, exclude, glbals, lcals): # @@ -2073,7 +2079,7 @@ theProperty = None def propNames(string): global alpha7 #string = string.encode('utf-8', 'strict') - + # Alpha 7 compatibility if string[0:2] == "&_": string = "Mhf"+string[2:] @@ -2087,7 +2093,7 @@ def propNames(string): elif len(string) > 4 and string[0:4] == "Hide": string = "Mhh"+string[4:] alpha7 = True - + if string[0] == "_": return None,None elif (len(string) > 3 and @@ -2096,28 +2102,28 @@ def propNames(string): return name, '["%s"]' % name else: return string, '["%s"]' % string - + def defProp(args, var, glbals, lcals): proptype = args[0] name = propNames(args[1])[0] - value = args[2] + value = args[2] rest = 'description="%s"' % args[3].replace("_", " ") if len(args) > 4: rest += ", " + args[4] - + if name: #expr = 'bpy.types.Object.%s = %sProperty(%s)' % (name, proptype, rest) expr = '%s["%s"] = %s' % (var, name, value) exec(expr, glbals, lcals) - + def defNewProp(name, proptype, rest): expr = 'bpy.types.Object.%s = %sProperty(%s)' % (name, proptype, rest) print(expr) exec(expr) - + def setProperty(args, var, glbals, lcals): global theProperty tip = "" @@ -2126,7 +2132,7 @@ def setProperty(args, var, glbals, lcals): if name: expr = '%s["%s"] = %s' % (var, name, value) exec(expr, glbals, lcals) - + if len(args) > 2: tip = 'description="%s"' % args[2].replace("_", " ") if value in ["True", "False"]: @@ -2158,7 +2164,7 @@ def defaultKey(ext, args, tokens, var, exclude, glbals, lcals): global todo if ext == 'Property': - return setProperty(args, var, glbals, lcals) + return setProperty(args, var, glbals, lcals) elif ext == 'PropKeys': return defineProperty(args) elif ext == 'DefProp': @@ -2169,7 +2175,7 @@ def defaultKey(ext, args, tokens, var, exclude, glbals, lcals): print(expr) exec(expr) return - + nvar = "%s.%s" % (var, ext) #print(ext) if ext in exclude: @@ -2178,7 +2184,7 @@ def defaultKey(ext, args, tokens, var, exclude, glbals, lcals): if len(args) == 0: MyError("Key length 0: %s" % ext) - + rnaType = args[0] if rnaType == 'Add': print("*** Cannot Add yet ***") @@ -2195,7 +2201,7 @@ def defaultKey(ext, args, tokens, var, exclude, glbals, lcals): try: data = eval(nvar, glbals, lcals) except: - data = None + data = None # print("Old structrna", nvar, data) if data is None: @@ -2209,7 +2215,7 @@ def defaultKey(ext, args, tokens, var, exclude, glbals, lcals): rna = eval(var,glbals,lcals) data = eval(creator) except: - data = None + data = None # print("New struct", nvar, typ, data) if rnaType == 'Define': @@ -2235,9 +2241,9 @@ def defaultKey(ext, args, tokens, var, exclude, glbals, lcals): exec(expr, glbals, lcals) if len(args) > 0: expr = "%s[0] = %s" % (nvar, args[1]) - exec(expr, glbals, lcals) + exec(expr, glbals, lcals) return - + elif rnaType == 'List': data = [] for (key, val, sub) in tokens: @@ -2249,7 +2255,7 @@ def defaultKey(ext, args, tokens, var, exclude, glbals, lcals): i = 0 n = len(tokens) for (key, val, sub) in tokens: - if key == 'row': + if key == 'row': for j in range(n): expr = "%s[%d][%d] = %g" % (nvar, i, j, float(val[j])) exec(expr, glbals, lcals) @@ -2291,7 +2297,7 @@ def pushOnTodoList(var, expr, glbals, lcals): todo.append((expr, glbals, lcals)) return - + # # parseBoolArray(mask): # @@ -2299,7 +2305,7 @@ def pushOnTodoList(var, expr, glbals, lcals): def parseBoolArray(mask): list = [] for c in mask: - if c == '0': + if c == '0': list.append(False) else: list.append(True) @@ -2312,7 +2318,7 @@ def parseMatrix(args, tokens): matrix = mathutils.Matrix() i = 0 for (key, val, sub) in tokens: - if key == 'row': + if key == 'row': matrix[i][0] = float(val[0]) matrix[i][1] = float(val[1]) matrix[i][2] = float(val[2]) @@ -2325,7 +2331,7 @@ def parseMatrix(args, tokens): # def parseDefault(data, tokens, subkeys, exclude): - for (key, val, sub) in tokens: + for (key, val, sub) in tokens: if key in subkeys.keys(): for (key2, val2, sub2) in sub: defaultKey(key2, val2, sub2, "data.%s" % subkeys[key], [], globals(), locals()) @@ -2337,7 +2343,7 @@ def parseCollection(data, tokens, exclude): # -# Utilities +# Utilities # # @@ -2367,7 +2373,7 @@ def Bool(string): return False else: MyError("Bool %s?" % string) -""" +""" # # invalid(condition): # @@ -2384,11 +2390,11 @@ def invalid(condition): return True - + # # clearScene(context): # - + def clearScene(): global toggle scn = bpy.context.scene @@ -2448,7 +2454,7 @@ def hideLayers(args): ob.hide = True ob.hide_render = True - if boneLayers: + if boneLayers: human = args[1] try: ob = loadedData['Object'][human] @@ -2469,7 +2475,7 @@ def hideLayers(args): b.hide = True return - + # # readDefaults(): @@ -2489,14 +2495,14 @@ def readDefaults(): print('Cannot open "%s" for reading' % path) return bver = '' - for line in fp: + for line in fp: words = line.split() if len(words) >= 3: try: toggle = int(words[0],16) theScale = float(words[1]) except: - print('Configuration file "%s" is corrupt' % path) + print('Configuration file "%s" is corrupt' % path) fp.close() toggleSettings = toggle return @@ -2530,7 +2536,7 @@ class RigifyBone: self.realname2 = None self.fkname = None self.ikname = None - + self.head = eb.head.copy() self.tail = eb.tail.copy() self.roll = eb.roll @@ -2539,17 +2545,17 @@ class RigifyBone: self.child = None self.connect = False self.original = False - self.extra = (eb.name in ["spine-1"]) - + self.extra = (eb.name in ["spine-1"]) + def __repr__(self): return ("" % (self.name, self.realname, self.realname1)) - - + + def rigifyMhx(context): from collections import OrderedDict print("Modifying MHX rig to Rigify") - scn = context.scene + scn = context.scene ob = context.object if ob.type == 'ARMATURE': rig = ob @@ -2561,25 +2567,25 @@ def rigifyMhx(context): raise NameError("Rigify: %s is neither an armature nor has armature parent" % ob) rig.MhxRigify = True scn.objects.active = rig - + group = None for grp in bpy.data.groups: if rig.name in grp.objects: group = grp break - print("Group: %s" % group) - - # Setup info about MHX bones + print("Group: %s" % group) + + # Setup info about MHX bones bones = OrderedDict() bpy.ops.object.mode_set(mode='EDIT') for eb in rig.data.edit_bones: bone = bones[eb.name] = RigifyBone(eb) - if eb.parent: + if eb.parent: bone.parent = eb.parent.name bones[bone.parent].child = eb.name - bpy.ops.object.mode_set(mode='OBJECT') - - # Create metarig + bpy.ops.object.mode_set(mode='OBJECT') + + # Create metarig try: bpy.ops.object.armature_human_metarig_add() except AttributeError: @@ -2589,12 +2595,12 @@ def rigifyMhx(context): bpy.ops.object.scale_clear() bpy.ops.transform.resize(value=(100, 100, 100)) bpy.ops.object.transform_apply(location=False, rotation=False, scale=True) - - # Fit metarig to default MHX rig + + # Fit metarig to default MHX rig meta = context.object bpy.ops.object.mode_set(mode='EDIT') extra = [] - for bone in bones.values(): + for bone in bones.values(): try: eb = meta.data.edit_bones[bone.name] except KeyError: @@ -2619,25 +2625,25 @@ def rigifyMhx(context): parent.tail = bones[bone.parent].tail eb.parent = parent eb.use_connect = True - + # Add rigify properties to extra bones bpy.ops.object.mode_set(mode='OBJECT') for bname in extra: pb = meta.pose.bones[bname] - pb["rigify_type"] = "" - - # Generate rigify rig + pb["rigify_type"] = "" + + # Generate rigify rig bpy.ops.pose.rigify_generate() gen = context.object print("Generated", gen) scn.objects.unlink(meta) del meta - + for bone in bones.values(): if bone.original: setBoneName(bone, gen) - - # Add extra bone to generated rig + + # Add extra bone to generated rig bpy.ops.object.mode_set(mode='EDIT') layers = 32*[False] layers[1] = True @@ -2671,38 +2677,38 @@ def rigifyMhx(context): pb.rotation_mode = db.rotation_mode for cns1 in db.constraints: cns2 = pb.constraints.new(cns1.type) - fixConstraint(cns1, cns2, gen, bones) - - # Add MHX properties + fixConstraint(cns1, cns2, gen, bones) + + # Add MHX properties for key in rig.keys(): gen[key] = rig[key] - - # Copy MHX bone drivers + + # Copy MHX bone drivers if rig.animation_data: for fcu1 in rig.animation_data.drivers: rna,channel = fcu1.data_path.rsplit(".", 1) pb = eval("gen.%s" % rna) fcu2 = pb.driver_add(channel, fcu1.array_index) - copyDriver(fcu1, fcu2, gen) + copyDriver(fcu1, fcu2, gen) # Copy MHX morph drivers and change armature modifier for ob in rig.children: if ob.type == 'MESH': ob.parent = gen - + if ob.data.animation_data: for fcu in ob.data.animation_data.drivers: print(ob, fcu.data_path) - changeDriverTarget(fcu, gen) - + changeDriverTarget(fcu, gen) + if ob.data.shape_keys and ob.data.shape_keys.animation_data: for fcu in ob.data.shape_keys.animation_data.drivers: print(skey, fcu.data_path) - changeDriverTarget(fcu, gen) - + changeDriverTarget(fcu, gen) + for mod in ob.modifiers: if mod.type == 'ARMATURE' and mod.object == rig: - mod.object = gen + mod.object = gen if group: group.objects.link(gen) @@ -2717,19 +2723,19 @@ def rigifyMhx(context): if ob.type == 'MESH' and ob.name[0:4] == "WGT-" and not ob.parent: ob.parent = empty grp.objects.link(ob) - - #Clean up + + #Clean up gen.show_x_ray = True gen.data.draw_type = 'STICK' - gen.MhxRigify = False + gen.MhxRigify = False name = rig.name scn.objects.unlink(rig) del rig gen.name = name bpy.ops.object.mode_set(mode='POSE') print("MHX rig %s successfully rigified" % name) - - + + def setBoneName(bone, gen): fkname = bone.name.replace(".", ".fk.") @@ -2747,7 +2753,7 @@ def setBoneName(bone, gen): return except KeyError: pass - + defname1 = "DEF-" + bone.name + ".01" try: gen.data.bones[defname1] @@ -2781,7 +2787,7 @@ def fixConstraint(cns1, cns2, gen, bones): exec(expr) cns2.target = gen - + if cns1.type == 'STRETCH_TO': bone = bones[cns1.subtarget] if bone.realname: @@ -2810,7 +2816,7 @@ def fixConstraint(cns1, cns2, gen, bones): def copyDriver(fcu1, fcu2, id): drv1 = fcu1.driver drv2 = fcu2.driver - + for var1 in drv1.variables: var2 = drv2.variables.new() var2.name = var1.name @@ -2819,7 +2825,7 @@ def copyDriver(fcu1, fcu2, id): targ2 = var2.targets[0] targ2.id = id targ2.data_path = targ1.data_path - + drv2.type = drv1.type drv2.expression = drv1.expression drv2.show_debug_info = drv1.show_debug_info @@ -2828,8 +2834,8 @@ def copyDriver(fcu1, fcu2, id): def changeDriverTarget(fcu, id): for var in fcu.driver.variables: targ = var.targets[0] - targ.id = id - + targ.id = id + # # class OBJECT_OT_RigifyMhxButton(bpy.types.Operator): @@ -2842,8 +2848,8 @@ class OBJECT_OT_RigifyMhxButton(bpy.types.Operator): def execute(self, context): rigifyMhx(context) - return{'FINISHED'} - + return{'FINISHED'} + # # class RigifyMhxPanel(bpy.types.Panel): # @@ -2852,7 +2858,7 @@ 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: @@ -2893,7 +2899,7 @@ class ErrorOperator(bpy.types.Operator): def draw(self, context): global theErrorLines - for line in theErrorLines: + for line in theErrorLines: self.layout.label(line) def MyError(message): @@ -2961,14 +2967,14 @@ class ImportMhx(bpy.types.Operator, ImportHelper): filename_ext = ".mhx" filter_glob = StringProperty(default="*.mhx", options={'HIDDEN'}) filepath = StringProperty(subtype='FILE_PATH') - + scale = FloatProperty(name="Scale", description="Default meter, decimeter = 1.0", default = theScale) advanced = BoolProperty(name="Advanced settings", description="Use advanced import settings", default=False) for (prop, name, desc, flag) in MhxBoolProps: expr = '%s = BoolProperty(name="%s", description="%s", default=(toggleSettings&%s != 0))' % (prop, name, desc, flag) exec(expr) - - + + def draw(self, context): layout = self.layout layout.prop(self, "scale") @@ -2977,7 +2983,7 @@ class ImportMhx(bpy.types.Operator, ImportHelper): for (prop, name, desc, flag) in MhxBoolProps: layout.prop(self, prop) - + def execute(self, context): global toggle, toggleSettings, theScale, MhxBoolProps if not self.advanced: @@ -3015,11 +3021,11 @@ class ImportMhx(bpy.types.Operator, ImportHelper): return {'RUNNING_MODAL'} -################################################################################### +################################################################################### # # Lipsync panel # -################################################################################### +################################################################################### # # visemes @@ -3027,297 +3033,297 @@ class ImportMhx(bpy.types.Operator, ImportHelper): """ stopStaringVisemes = ({ 'Rest' : [ - ('PMouth', (0,0)), - ('PUpLip', (0,-0.1)), - ('PLoLip', (0,0.1)), - ('PJaw', (0,0.05)), - ('PTongue', (0,0.0))], + ('PMouth', (0,0)), + ('PUpLip', (0,-0.1)), + ('PLoLip', (0,0.1)), + ('PJaw', (0,0.05)), + ('PTongue', (0,0.0))], 'Etc' : [ ('PMouth', (0,0)), ('PUpLip', (0,-0.1)), ('PLoLip', (0,0.1)), ('PJaw', (0,0.15)), - ('PTongue', (0,0.0))], + ('PTongue', (0,0.0))], 'MBP' : [('PMouth', (-0.3,0)), ('PUpLip', (0,1)), ('PLoLip', (0,0)), ('PJaw', (0,0.1)), - ('PTongue', (0,0.0))], + ('PTongue', (0,0.0))], 'OO' : [('PMouth', (-1.5,0)), ('PUpLip', (0,0)), ('PLoLip', (0,0)), ('PJaw', (0,0.2)), - ('PTongue', (0,0.0))], + ('PTongue', (0,0.0))], 'O' : [('PMouth', (-1.1,0)), ('PUpLip', (0,0)), ('PLoLip', (0,0)), ('PJaw', (0,0.5)), - ('PTongue', (0,0.0))], + ('PTongue', (0,0.0))], 'R' : [('PMouth', (-0.9,0)), ('PUpLip', (0,-0.2)), ('PLoLip', (0,0.2)), ('PJaw', (0,0.2)), - ('PTongue', (0,0.0))], + ('PTongue', (0,0.0))], 'FV' : [('PMouth', (0,0)), ('PUpLip', (0,0)), ('PLoLip', (0,-0.8)), ('PJaw', (0,0.1)), - ('PTongue', (0,0.0))], + ('PTongue', (0,0.0))], 'S' : [('PMouth', (0,0)), ('PUpLip', (0,-0.2)), ('PLoLip', (0,0.2)), ('PJaw', (0,0.05)), - ('PTongue', (0,0.0))], + ('PTongue', (0,0.0))], 'SH' : [('PMouth', (-0.6,0)), ('PUpLip', (0,-0.5)), ('PLoLip', (0,0.5)), ('PJaw', (0,0)), - ('PTongue', (0,0.0))], + ('PTongue', (0,0.0))], 'EE' : [('PMouth', (0.3,0)), ('PUpLip', (0,-0.3)), ('PLoLip', (0,0.3)), ('PJaw', (0,0.025)), - ('PTongue', (0,0.0))], + ('PTongue', (0,0.0))], 'AH' : [('PMouth', (-0.1,0)), ('PUpLip', (0,-0.4)), ('PLoLip', (0,0)), ('PJaw', (0,0.35)), - ('PTongue', (0,0.0))], + ('PTongue', (0,0.0))], 'EH' : [('PMouth', (0.1,0)), ('PUpLip', (0,-0.2)), ('PLoLip', (0,0.2)), ('PJaw', (0,0.2)), - ('PTongue', (0,0.0))], + ('PTongue', (0,0.0))], 'TH' : [('PMouth', (0,0)), ('PUpLip', (0,-0.5)), ('PLoLip', (0,0.5)), ('PJaw', (-0.2,0.1)), - ('PTongue', (0,-0.6))], + ('PTongue', (0,-0.6))], 'L' : [('PMouth', (0,0)), ('PUpLip', (0,-0.2)), ('PLoLip', (0,0.2)), ('PJaw', (0.2,0.2)), - ('PTongue', (0,-0.8))], + ('PTongue', (0,-0.8))], 'G' : [('PMouth', (0,0)), ('PUpLip', (0,-0.1)), ('PLoLip', (0,0.1)), ('PJaw', (-0.3,0.1)), - ('PTongue', (0,-0.6))], + ('PTongue', (0,-0.6))], - 'Blink' : [('PUpLid', (0,1.0)), ('PLoLid', (0,-1.0))], - 'Unblink' : [('PUpLid', (0,0)), ('PLoLid', (0,0))], + 'Blink' : [('PUpLid', (0,1.0)), ('PLoLid', (0,-1.0))], + 'Unblink' : [('PUpLid', (0,0)), ('PLoLid', (0,0))], }) bodyLanguageVisemes = ({ 'Rest' : [ - ('MouthWidth_L', 0), - ('MouthWidth_R', 0), - ('MouthNarrow_L', 0), - ('MouthNarrow_R', 0), - ('LipsPart', 0.6), - ('UpLipsMidHeight', 0), - ('LoLipsMidHeight', 0), + ('MouthWidth_L', 0), + ('MouthWidth_R', 0), + ('MouthNarrow_L', 0), + ('MouthNarrow_R', 0), + ('LipsPart', 0.6), + ('UpLipsMidHeight', 0), + ('LoLipsMidHeight', 0), ('LoLipsIn', 0), - ('MouthOpen', 0), + ('MouthOpen', 0), ('TongueBackHeight', 0), ('TongueHeight', 0), - ], + ], 'Etc' : [ - ('MouthWidth_L', 0), - ('MouthWidth_R', 0), - ('MouthNarrow_L', 0), - ('MouthNarrow_R', 0), - ('LipsPart', 0.4), - ('UpLipsMidHeight', 0), - ('LoLipsMidHeight', 0), + ('MouthWidth_L', 0), + ('MouthWidth_R', 0), + ('MouthNarrow_L', 0), + ('MouthNarrow_R', 0), + ('LipsPart', 0.4), + ('UpLipsMidHeight', 0), + ('LoLipsMidHeight', 0), ('LoLipsIn', 0), - ('MouthOpen', 0), + ('MouthOpen', 0), ('TongueBackHeight', 0), ('TongueHeight', 0), - ], + ], 'MBP' : [ - ('MouthWidth_L', 0), - ('MouthWidth_R', 0), - ('MouthNarrow_L', 0), - ('MouthNarrow_R', 0), - ('LipsPart', 0), - ('UpLipsMidHeight', 0), - ('LoLipsMidHeight', 0), + ('MouthWidth_L', 0), + ('MouthWidth_R', 0), + ('MouthNarrow_L', 0), + ('MouthNarrow_R', 0), + ('LipsPart', 0), + ('UpLipsMidHeight', 0), + ('LoLipsMidHeight', 0), ('LoLipsIn', 0), - ('MouthOpen', 0), + ('MouthOpen', 0), ('TongueBackHeight', 0), ('TongueHeight', 0), - ], + ], 'OO' : [ - ('MouthWidth_L', 0), - ('MouthWidth_R', 0), - ('MouthNarrow_L', 1.0), - ('MouthNarrow_R', 1.0), - ('LipsPart', 0), - ('UpLipsMidHeight', 0), - ('LoLipsMidHeight', 0), + ('MouthWidth_L', 0), + ('MouthWidth_R', 0), + ('MouthNarrow_L', 1.0), + ('MouthNarrow_R', 1.0), + ('LipsPart', 0), + ('UpLipsMidHeight', 0), + ('LoLipsMidHeight', 0), ('LoLipsIn', 0), - ('MouthOpen', 0.4), + ('MouthOpen', 0.4), ('TongueBackHeight', 0), ('TongueHeight', 0), - ], + ], 'O' : [ - ('MouthWidth_L', 0), - ('MouthWidth_R', 0), - ('MouthNarrow_L', 0.9), - ('MouthNarrow_R', 0.9), - ('LipsPart', 0), - ('UpLipsMidHeight', 0), - ('LoLipsMidHeight', 0), + ('MouthWidth_L', 0), + ('MouthWidth_R', 0), + ('MouthNarrow_L', 0.9), + ('MouthNarrow_R', 0.9), + ('LipsPart', 0), + ('UpLipsMidHeight', 0), + ('LoLipsMidHeight', 0), ('LoLipsIn', 0), - ('MouthOpen', 0.8), + ('MouthOpen', 0.8), ('TongueBackHeight', 0), ('TongueHeight', 0), - ], + ], 'R' : [ - ('MouthWidth_L', 0), - ('MouthWidth_R', 0), - ('MouthNarrow_L', 0.5), - ('MouthNarrow_R', 0.5), - ('LipsPart', 0), - ('UpLipsMidHeight', 0.2), - ('LoLipsMidHeight', -0.2), + ('MouthWidth_L', 0), + ('MouthWidth_R', 0), + ('MouthNarrow_L', 0.5), + ('MouthNarrow_R', 0.5), + ('LipsPart', 0), + ('UpLipsMidHeight', 0.2), + ('LoLipsMidHeight', -0.2), ('LoLipsIn', 0), - ('MouthOpen', 0), + ('MouthOpen', 0), ('TongueBackHeight', 0), ('TongueHeight', 0), - ], + ], 'FV' : [ - ('MouthWidth_L', 0.2), - ('MouthWidth_R', 0.2), - ('MouthNarrow_L', 0), - ('MouthNarrow_R', 0), - ('LipsPart', 1.0), - ('UpLipsMidHeight', 0), - ('LoLipsMidHeight', 0.3), + ('MouthWidth_L', 0.2), + ('MouthWidth_R', 0.2), + ('MouthNarrow_L', 0), + ('MouthNarrow_R', 0), + ('LipsPart', 1.0), + ('UpLipsMidHeight', 0), + ('LoLipsMidHeight', 0.3), ('LoLipsIn', 0.6), - ('MouthOpen', 0), + ('MouthOpen', 0), ('TongueBackHeight', 0), ('TongueHeight', 0), - ], + ], 'S' : [ - ('MouthWidth_L', 0), - ('MouthWidth_R', 0), - ('MouthNarrow_L', 0), - ('MouthNarrow_R', 0), - ('LipsPart', 0), - ('UpLipsMidHeight', 0.5), - ('LoLipsMidHeight', -0.7), + ('MouthWidth_L', 0), + ('MouthWidth_R', 0), + ('MouthNarrow_L', 0), + ('MouthNarrow_R', 0), + ('LipsPart', 0), + ('UpLipsMidHeight', 0.5), + ('LoLipsMidHeight', -0.7), ('LoLipsIn', 0), - ('MouthOpen', 0), + ('MouthOpen', 0), ('TongueBackHeight', 0), ('TongueHeight', 0), - ], + ], 'SH' : [ - ('MouthWidth_L', 0.8), - ('MouthWidth_R', 0.8), - ('MouthNarrow_L', 0), - ('MouthNarrow_R', 0), - ('LipsPart', 0), - ('UpLipsMidHeight', 1.0), - ('LoLipsMidHeight', 0), + ('MouthWidth_L', 0.8), + ('MouthWidth_R', 0.8), + ('MouthNarrow_L', 0), + ('MouthNarrow_R', 0), + ('LipsPart', 0), + ('UpLipsMidHeight', 1.0), + ('LoLipsMidHeight', 0), ('LoLipsIn', 0), - ('MouthOpen', 0), + ('MouthOpen', 0), ('TongueBackHeight', 0), ('TongueHeight', 0), - ], + ], 'EE' : [ - ('MouthWidth_L', 0.2), - ('MouthWidth_R', 0.2), - ('MouthNarrow_L', 0), - ('MouthNarrow_R', 0), - ('LipsPart', 0), - ('UpLipsMidHeight', 0.6), - ('LoLipsMidHeight', -0.6), + ('MouthWidth_L', 0.2), + ('MouthWidth_R', 0.2), + ('MouthNarrow_L', 0), + ('MouthNarrow_R', 0), + ('LipsPart', 0), + ('UpLipsMidHeight', 0.6), + ('LoLipsMidHeight', -0.6), ('LoLipsIn', 0), - ('MouthOpen', 0.5), + ('MouthOpen', 0.5), ('TongueBackHeight', 0), ('TongueHeight', 0), - ], + ], 'AH' : [ - ('MouthWidth_L', 0), - ('MouthWidth_R', 0), - ('MouthNarrow_L', 0), - ('MouthNarrow_R', 0), - ('LipsPart', 0), - ('UpLipsMidHeight', 0.4), - ('LoLipsMidHeight', 0), + ('MouthWidth_L', 0), + ('MouthWidth_R', 0), + ('MouthNarrow_L', 0), + ('MouthNarrow_R', 0), + ('LipsPart', 0), + ('UpLipsMidHeight', 0.4), + ('LoLipsMidHeight', 0), ('LoLipsIn', 0), - ('MouthOpen', 0.7), + ('MouthOpen', 0.7), ('TongueBackHeight', 0), ('TongueHeight', 0), - ], + ], 'EH' : [ - ('MouthWidth_L', 0), - ('MouthWidth_R', 0), - ('MouthNarrow_L', 0), - ('MouthNarrow_R', 0), - ('LipsPart', 0), - ('UpLipsMidHeight', 0.5), - ('LoLipsMidHeight', -0.6), + ('MouthWidth_L', 0), + ('MouthWidth_R', 0), + ('MouthNarrow_L', 0), + ('MouthNarrow_R', 0), + ('LipsPart', 0), + ('UpLipsMidHeight', 0.5), + ('LoLipsMidHeight', -0.6), ('LoLipsIn', 0), - ('MouthOpen', 0.25), + ('MouthOpen', 0.25), ('TongueBackHeight', 0), ('TongueHeight', 0), - ], + ], 'TH' : [ - ('MouthWidth_L', 0), - ('MouthWidth_R', 0), - ('MouthNarrow_L', 0), - ('MouthNarrow_R', 0), - ('LipsPart', 0), - ('UpLipsMidHeight', 0), - ('LoLipsMidHeight', 0), + ('MouthWidth_L', 0), + ('MouthWidth_R', 0), + ('MouthNarrow_L', 0), + ('MouthNarrow_R', 0), + ('LipsPart', 0), + ('UpLipsMidHeight', 0), + ('LoLipsMidHeight', 0), ('LoLipsIn', 0), - ('MouthOpen', 0.2), + ('MouthOpen', 0.2), ('TongueBackHeight', 1.0), ('TongueHeight', 1.0) - ], + ], 'L' : [ - ('MouthWidth_L', 0), - ('MouthWidth_R', 0), - ('MouthNarrow_L', 0), - ('MouthNarrow_R', 0), - ('LipsPart', 0), - ('UpLipsMidHeight', 0.5), - ('LoLipsMidHeight', -0.5), + ('MouthWidth_L', 0), + ('MouthWidth_R', 0), + ('MouthNarrow_L', 0), + ('MouthNarrow_R', 0), + ('LipsPart', 0), + ('UpLipsMidHeight', 0.5), + ('LoLipsMidHeight', -0.5), ('LoLipsIn', 0), - ('MouthOpen', -0.2), + ('MouthOpen', -0.2), ('TongueBackHeight', 1.0), ('TongueHeight', 1.0), - ], + ], 'G' : [ - ('MouthWidth_L', 0), - ('MouthWidth_R', 0), - ('MouthNarrow_L', 0), - ('MouthNarrow_R', 0), - ('LipsPart', 0), - ('UpLipsMidHeight', 0.5), - ('LoLipsMidHeight', -0.5), + ('MouthWidth_L', 0), + ('MouthWidth_R', 0), + ('MouthNarrow_L', 0), + ('MouthNarrow_R', 0), + ('LipsPart', 0), + ('UpLipsMidHeight', 0.5), + ('LoLipsMidHeight', -0.5), ('LoLipsIn', 0), - ('MouthOpen', -0.2), + ('MouthOpen', -0.2), ('TongueBackHeight', 1.0), ('TongueHeight', 0), - ], + ], 'Blink' : [ - ('UpLidUp_L', 1), - ('UpLidUp_R', 1), + ('UpLidUp_L', 1), + ('UpLidUp_R', 1), ('LoLidDown_L', 1), ('LoLidDown_R', 1) - ], - + ], + 'Unblink' : [ - ('UpLidUp_L', 0), - ('UpLidUp_R', 0), + ('UpLidUp_L', 0), + ('UpLidUp_R', 0), ('LoLidDown_L', 0), ('LoLidDown_R', 0) - ], + ], }) VisemePanelBones = { @@ -3329,15 +3335,15 @@ VisemePanelBones = { 'MouthWidth_R' : ('PMouth_R', (-0.25,0)), 'MouthNarrow_L' : ('PMouth_L', (-0.25,0)), 'MouthNarrow_R' : ('PMouth_R', (0.25,0)), - 'LipsPart' : ('PMouthMid', (0, -0.25)), + 'LipsPart' : ('PMouthMid', (0, -0.25)), 'TongueBackHeight': ('PTongue', (-0.25, 0)), 'TongueHeight' : ('PTongue', (0, -0.25)), - + 'UpLidUp_L' : ('PUpLid_L', (0,1.0)), 'UpLidUp_R' : ('PUpLid_R', (0,1.0)), - 'LoLidDown_L' : ('PLoLid_L', (0,-1.0)), - 'LoLidDown_R' : ('PLoLid_R', (0,-1.0)), -} + 'LoLidDown_L' : ('PLoLid_L', (0,-1.0)), + 'LoLidDown_R' : ('PLoLid_R', (0,-1.0)), +} VisemeList = [ ('Rest', 'Etc', 'AH'), @@ -3364,13 +3370,13 @@ def makeVisemes(ob, scn): print("Visemes already created") return except: - pass + pass - verts = ob.data.vertices + verts = ob.data.vertices for (vis,shapes) in bodyLanguageVisemes.items(): if vis in ['Blink', 'Unblink']: continue - vkey = ob.shape_key_add(name="VIS_%s" % vis) + vkey = ob.shape_key_add(name="VIS_%s" % vis) print(vkey.name) for n,v in enumerate(verts): vkey.data[n].co = v.co @@ -3381,9 +3387,9 @@ def makeVisemes(ob, scn): factor = 0.75*value for n,v in enumerate(verts): vkey.data[n].co += factor*(skey.data[n].co - v.co) - print("Visemes made") + print("Visemes made") return - + class VIEW3D_OT_MhxMakeVisemesButton(bpy.types.Operator): bl_idname = "mhx.make_visemes" bl_label = "Generate viseme shapekeys" @@ -3391,36 +3397,36 @@ class VIEW3D_OT_MhxMakeVisemesButton(bpy.types.Operator): def execute(self, context): makeVisemes(context.object, context.scene) - return{'FINISHED'} -""" + return{'FINISHED'} +""" # # mohoVisemes # magpieVisemes # MohoVisemes = dict({ - 'rest' : 'Rest', - 'etc' : 'Etc', - 'AI' : 'AH', - 'O' : 'O', - 'U' : 'OO', - 'WQ' : 'AH', - 'L' : 'L', - 'E' : 'EH', - 'MBP' : 'MBP', - 'FV' : 'FV', + 'rest' : 'Rest', + 'etc' : 'Etc', + 'AI' : 'AH', + 'O' : 'O', + 'U' : 'OO', + 'WQ' : 'AH', + 'L' : 'L', + 'E' : 'EH', + 'MBP' : 'MBP', + 'FV' : 'FV', }) MagpieVisemes = dict({ - "CONS" : "Etc", - "AI" : 'AH', - "E" : "EH", - "O" : "O", - "UW" : "AH", - "MBP" : "MBP", - "L" : "L", - "FV" : "FV", - "Sh" : "SH", + "CONS" : "Etc", + "AI" : 'AH', + "E" : "EH", + "O" : "O", + "UW" : "AH", + "MBP" : "MBP", + "L" : "L", + "FV" : "FV", + "Sh" : "SH", }) # @@ -3460,7 +3466,7 @@ def setVisemeAlpha7(context, vis, visemes, setKey, frame): for (skey, value) in visemes[vis]: if isPanel: (b, (x,z)) = VisemePanelBones[skey] - loc = mathutils.Vector((float(x*value),0,float(z*value))) + loc = mathutils.Vector((float(x*value),0,float(z*value))) pb = rig.pose.bones[b] pb.location = loc*scale if setKey or context.tool_settings.use_keyframe_insert_auto: @@ -3474,14 +3480,14 @@ def setVisemeAlpha7(context, vis, visemes, setKey, frame): continue rig[skey] = value*scale if setKey or context.tool_settings.use_keyframe_insert_auto: - rig.keyframe_insert('["%s"]' % skey, frame=frame, group="Visemes") + rig.keyframe_insert('["%s"]' % skey, frame=frame, group="Visemes") elif shapekeys: try: shapekeys[skey].value = value*scale except: continue if setKey or context.tool_settings.use_keyframe_insert_auto: - shapekeys[skey].keyframe_insert("value", frame=frame) + shapekeys[skey].keyframe_insert("value", frame=frame) updatePose(context) return @@ -3514,12 +3520,12 @@ def readLipsync(context, filepath, offs, struct): auto = context.tool_settings.use_keyframe_insert_auto auto = True factor = rig.MhxStrength - shapekeys = getMhmShapekeys(rig, mesh) + shapekeys = getMhmShapekeys(rig, mesh) else: - visemes = getVisemeSet(context, rig) + visemes = getVisemeSet(context, rig) context.scene.objects.active = rig - bpy.ops.object.mode_set(mode='POSE') - + bpy.ops.object.mode_set(mode='POSE') + fp = open(filepath, "rU") for line in fp: words= line.split() @@ -3533,7 +3539,7 @@ def readLipsync(context, filepath, offs, struct): else: setVisemeAlpha7(context, vis, visemes, True, frame) fp.close() - + #setInterpolation(rig) updatePose(context) print("Lipsync file %s loaded" % filepath) @@ -3543,18 +3549,18 @@ class VIEW3D_OT_MhxMohoButton(bpy.types.Operator, ImportHelper): bl_idname = "mhx.pose_load_moho" bl_label = "Load Moho (.dat)" bl_options = {'UNDO'} - + filename_ext = ".dat" filter_glob = StringProperty(default="*.dat", options={'HIDDEN'}) - filepath = StringProperty(subtype='FILE_PATH') + filepath = StringProperty(subtype='FILE_PATH') - def execute(self, context): - readLipsync(context, self.properties.filepath, context.scene.frame_start - 1, MohoVisemes) - return{'FINISHED'} + def execute(self, context): + readLipsync(context, self.properties.filepath, context.scene.frame_start - 1, MohoVisemes) + return{'FINISHED'} def invoke(self, context, event): context.window_manager.fileselect_add(self) - return {'RUNNING_MODAL'} + return {'RUNNING_MODAL'} class MhxLipsyncPanel(bpy.types.Panel): @@ -3572,14 +3578,14 @@ class MhxLipsyncPanel(bpy.types.Panel): if not rig: layout.label("No MHX rig found") return - layout = self.layout - + layout = self.layout + if rig.MhAlpha8: visemes = getProps(rig, "Mhv") if not visemes: layout.label("No visemes found") return - + layout.operator("mhx.pose_reset_expressions", text="Reset visemes").prefix="Mhsmouth" layout.operator("mhx.pose_key_expressions", text="Key visemes").prefix="Mhsmouth" layout.prop(rig, "MhxStrength") @@ -3589,16 +3595,16 @@ class MhxLipsyncPanel(bpy.types.Panel): if n % 3 == 0: row = layout.row() n = 0 - row.operator("mhx.pose_mhm", text=prop[3:]).data="Mhsmouth;"+rig[prop] + row.operator("mhx.pose_mhm", text=prop[3:]).data="Mhsmouth;"+rig[prop] n += 1 while n % 3 != 0: row.label("") n += 1 layout.separator() row = layout.row() - row.operator("mhx.pose_mhm", text="Blink").data="Mhsmouth;eye_left_closure:1;eye_right_closure:1" - row.operator("mhx.pose_mhm", text="Unblink").data="Mhsmouth;eye_left_closure:0;eye_right_closure:0" - else: + row.operator("mhx.pose_mhm", text="Blink").data="Mhsmouth;eye_left_closure:1;eye_right_closure:1" + row.operator("mhx.pose_mhm", text="Unblink").data="Mhsmouth;eye_left_closure:0;eye_right_closure:0" + else: layout.label("Lipsync disabled for alpha7 mhx files") return for (vis1, vis2, vis3) in VisemeList: @@ -3612,7 +3618,7 @@ class MhxLipsyncPanel(bpy.types.Panel): row.operator("mhx.pose_viseme", text="Unblink").viseme = 'Unblink' layout.separator() layout.operator("mhx.make_visemes") - + layout.separator() row = layout.row() row.operator("mhx.pose_load_moho") @@ -3636,14 +3642,14 @@ class VIEW3D_OT_MhxUpdateButton(bpy.types.Operator): def execute(self, context): updatePose(context) - return{'FINISHED'} - + return{'FINISHED'} + -################################################################################### +################################################################################### # # Expression panels # -################################################################################### +################################################################################### class VIEW3D_OT_MhxResetExpressionsButton(bpy.types.Operator): bl_idname = "mhx.pose_reset_expressions" @@ -3656,7 +3662,7 @@ class VIEW3D_OT_MhxResetExpressionsButton(bpy.types.Operator): shapekeys = getMhmShapekeys(rig, mesh) clearMhmProps(rig, shapekeys, self.prefix, context.tool_settings.use_keyframe_insert_auto, context.scene.frame_current) updatePose(context) - return{'FINISHED'} + return{'FINISHED'} class VIEW3D_OT_MhxKeyExpressionsButton(bpy.types.Operator): @@ -3672,8 +3678,8 @@ class VIEW3D_OT_MhxKeyExpressionsButton(bpy.types.Operator): for prop in props: rig.keyframe_insert('["%s"]'%prop, frame=frame) updatePose(context) - return{'FINISHED'} - + return{'FINISHED'} + class VIEW3D_OT_MhxPinExpressionButton(bpy.types.Operator): bl_idname = "mhx.pose_pin_expression" @@ -3686,7 +3692,7 @@ class VIEW3D_OT_MhxPinExpressionButton(bpy.types.Operator): words = self.data.split(";") prefix = words[0] expression = words[1] - + props = getProps(rig, prefix) if context.tool_settings.use_keyframe_insert_auto: frame = context.scene.frame_current @@ -3698,14 +3704,14 @@ class VIEW3D_OT_MhxPinExpressionButton(bpy.types.Operator): rig[prop] = 0.0 if abs(rig[prop] - old) > 1e-3: rig.keyframe_insert('["%s"]'%prop, frame=frame) - else: + else: for prop in props: if prop == expression: rig[prop] = 1.0 else: rig[prop] = 0.0 updatePose(context) - return{'FINISHED'} + return{'FINISHED'} def getMhmShapekeys(rig, mesh): @@ -3713,7 +3719,7 @@ def getMhmShapekeys(rig, mesh): return None else: return mesh.data.shape_keys.key_blocks - + def setMhmProps(rig, shapekeys, prefix, units, factor, auto, frame): clearMhmProps(rig, shapekeys, prefix, auto, frame) @@ -3722,13 +3728,13 @@ def setMhmProps(rig, shapekeys, prefix, units, factor, auto, frame): skey = prop[3:].replace("_","-") shapekeys[skey].value = factor*value if auto: - shapekeys[skey].keyframe_insert("value", frame=frame) + shapekeys[skey].keyframe_insert("value", frame=frame) else: rig[prop] = factor*value if auto: - rig.keyframe_insert('["%s"]'%prop, frame=frame) - - + rig.keyframe_insert('["%s"]'%prop, frame=frame) + + def clearMhmProps(rig, shapekeys, prefix, auto, frame): props = getProps(rig, prefix) for prop in props: @@ -3736,26 +3742,26 @@ def clearMhmProps(rig, shapekeys, prefix, auto, frame): skey = prop[3:].replace("_","-") shapekeys[skey].value = 0.0 if auto: - shapekeys[skey].keyframe_insert("value", frame=frame) + shapekeys[skey].keyframe_insert("value", frame=frame) else: rig[prop] = 0.0 if auto: - rig.keyframe_insert('["%s"]'%prop, frame=frame) + rig.keyframe_insert('["%s"]'%prop, frame=frame) -def getUnitsFromString(string): +def getUnitsFromString(string): words = string.split(";") prefix = words[0] units = [] for word in words[1:]: if word == "": continue - unit = word.split(":") + unit = word.split(":") prop = "Mhs" + unit[0] value = float(unit[1]) units.append((prop, value)) - return prefix,units - + return prefix,units + class VIEW3D_OT_MhxMhmButton(bpy.types.Operator): bl_idname = "mhx.pose_mhm" @@ -3763,23 +3769,23 @@ class VIEW3D_OT_MhxMhmButton(bpy.types.Operator): bl_options = {'UNDO'} data = StringProperty() - def execute(self, context): + def execute(self, context): rig,mesh = getMhxRigMesh(context.object) auto = context.tool_settings.use_keyframe_insert_auto frame = context.scene.frame_current shapekeys = getMhmShapekeys(rig, mesh) - prefix,units = getUnitsFromString(self.data) + prefix,units = getUnitsFromString(self.data) setMhmProps(rig, shapekeys, prefix, units, rig.MhxStrength, auto, frame) updatePose(context) - return{'FINISHED'} - - + return{'FINISHED'} + + def getProps(rig, prefix): props = [] for prop in rig.keys(): if prop.startswith(prefix): props.append(prop) - props.sort() + props.sort() return props @@ -3788,7 +3794,7 @@ class MhxExpressionsPanel(bpy.types.Panel): bl_space_type = "VIEW_3D" bl_region_type = "UI" bl_options = {'DEFAULT_CLOSED'} - + @classmethod def poll(cls, context): return pollMhx(context.object) @@ -3803,7 +3809,7 @@ class MhxExpressionsPanel(bpy.types.Panel): if not exprs: layout.label("No expressions found") return - + layout.operator("mhx.pose_reset_expressions").prefix="Mhs" layout.operator("mhx.pose_key_expressions").prefix="Mhs" layout.prop(rig, "MhxStrength") @@ -3826,7 +3832,7 @@ def drawShapePanel(self, context, prefix, name): if not props: layout.label("No %ss found" % name) return - + layout.operator("mhx.pose_reset_expressions", text="Reset %ss" % name).prefix=prefix layout.operator("mhx.pose_key_expressions", text="Key %ss" % name).prefix=prefix #layout.operator("mhx.update") @@ -3844,7 +3850,7 @@ class MhxExpressionUnitsPanel(bpy.types.Panel): bl_space_type = "VIEW_3D" bl_region_type = "UI" bl_options = {'DEFAULT_CLOSED'} - + @classmethod def poll(cls, context): return pollMhx(context.object) @@ -3858,7 +3864,7 @@ class MhxCustomShapePanel(bpy.types.Panel): bl_space_type = "VIEW_3D" bl_region_type = "UI" bl_options = {'DEFAULT_CLOSED'} - + @classmethod def poll(cls, context): return pollMhx(context.object) @@ -3869,7 +3875,7 @@ class MhxCustomShapePanel(bpy.types.Panel): ######################################### # -# FK-IK snapping. +# FK-IK snapping. # ######################################### @@ -3882,7 +3888,7 @@ def getPoseMatrix(mat, pb): else: return restInv * mat - + def getGlobalMatrix(mat, pb): gmat = pb.bone.matrix_local * mat if pb.parent: @@ -3896,9 +3902,10 @@ def getGlobalMatrix(mat, pb): def matchPoseTranslation(pb, fkPb, auto): mat = getPoseMatrix(fkPb.matrix, pb) insertLocation(pb, mat, auto) - + print("TRANS %s => %s" % (fkPb, pb)) + -def insertLocation(pb, mat, auto): +def insertLocation(pb, mat, auto): pb.location = mat.to_translation() if auto: pb.keyframe_insert("location", group=pb.name) @@ -3909,9 +3916,10 @@ def insertLocation(pb, mat, auto): def matchPoseRotation(pb, fkPb, auto): mat = getPoseMatrix(fkPb.matrix, pb) insertRotation(pb, mat, auto) - + print("ROT %s => %s" % (fkPb, pb)) -def insertRotation(pb, mat, auto): + +def insertRotation(pb, mat, auto): q = mat.to_quaternion() if pb.rotation_mode == 'QUATERNION': pb.rotation_quaternion = q @@ -3929,15 +3937,15 @@ def matchPoseReverse(pb, fkPb, auto): bpy.ops.object.mode_set(mode='OBJECT') bpy.ops.object.mode_set(mode='POSE') gmat = fkPb.matrix * Matrix.Rotation(math.pi, 4, 'Z') - offs = pb.bone.length * fkPb.matrix.col[1] + offs = pb.bone.length * fkPb.matrix.col[1] gmat[0][3] += offs[0] gmat[1][3] += offs[1] - gmat[2][3] += offs[2] + gmat[2][3] += offs[2] mat = getPoseMatrix(gmat, pb) pb.matrix_basis = mat insertLocation(pb, mat, auto) insertRotation(pb, mat, auto) - + def matchPoseScale(pb, fkPb, auto): mat = getPoseMatrix(fkPb.matrix, pb) @@ -3952,21 +3960,25 @@ def fk2ikArm(context, suffix): rig = context.object auto = context.scene.tool_settings.use_keyframe_insert_auto print("Snap FK Arm%s" % suffix) - snapIk,cnsIk = getSnapBones(rig, "ArmIK", suffix) - (uparmIk, loarmIk, elbow, elbowPt, wrist) = snapIk + snap,_ = getSnapBones(rig, "Arm", suffix) + (uparm, loarm, hand) = snap snapFk,cnsFk = getSnapBones(rig, "ArmFK", suffix) (uparmFk, loarmFk, elbowPtFk, handFk) = snapFk muteConstraints(cnsFk, True) - matchPoseRotation(uparmFk, uparmFk, auto) - matchPoseScale(uparmFk, uparmFk, auto) + matchPoseRotation(uparmFk, uparm, auto) + matchPoseScale(uparmFk, uparm, auto) - matchPoseRotation(loarmFk, loarmFk, auto) - matchPoseScale(loarmFk, loarmFk, auto) + matchPoseRotation(loarmFk, loarm, auto) + matchPoseScale(loarmFk, loarm, auto) - if rig["MhaHandFollowsWrist" + suffix]: - matchPoseRotation(handFk, wrist, auto) - matchPoseScale(handFk, wrist, auto) + try: + matchHand = rig["MhaHandFollowsWrist" + suffix] + except KeyError: + matchHand = True + if matchHand: + matchPoseRotation(handFk, hand, auto) + matchPoseScale(handFk, hand, auto) muteConstraints(cnsFk, False) return @@ -3978,17 +3990,18 @@ def ik2fkArm(context, suffix): auto = scn.tool_settings.use_keyframe_insert_auto print("Snap IK Arm%s" % suffix) snapIk,cnsIk = getSnapBones(rig, "ArmIK", suffix) - (uparmIk, loarmIk, elbow, elbowPt, wrist) = snapIk + (uparmIk, loarmIk, elbow, elbowPt, handIk) = snapIk snapFk,cnsFk = getSnapBones(rig, "ArmFK", suffix) (uparmFk, loarmFk, elbowPtFk, handFk) = snapFk muteConstraints(cnsIk, True) #rig["MhaElbowFollowsShoulder" + suffix] = False #rig["MhaElbowFollowsWrist" + suffix] = False - - matchPoseTranslation(wrist, handFk, auto) - matchPoseRotation(wrist, handFk, auto) - matchPoseTranslation(elbow, elbowPtFk, auto) + + matchPoseTranslation(handIk, handFk, auto) + matchPoseRotation(handIk, handFk, auto) + if elbow is not None: + matchPoseTranslation(elbow, elbowPtFk, auto) matchPoseTranslation(elbowPt, elbowPtFk, auto) setInverse(rig, elbowPt) muteConstraints(cnsIk, False) @@ -3999,22 +4012,22 @@ def fk2ikLeg(context, suffix): rig = context.object auto = context.scene.tool_settings.use_keyframe_insert_auto print("Snap FK Leg%s" % suffix) - snapIk,cnsIk = getSnapBones(rig, "LegIK", suffix) - (uplegIk, lolegIk, kneePt, ankleIk, legIk, legFk, footIk, toeIk) = snapIk + snap,_ = getSnapBones(rig, "Leg", suffix) + (upleg, loleg, foot, toe) = snap snapFk,cnsFk = getSnapBones(rig, "LegFK", suffix) (uplegFk, lolegFk, kneePtFk, footFk, toeFk) = snapFk muteConstraints(cnsFk, True) - + + matchPoseRotation(uplegFk, upleg, auto) + matchPoseScale(uplegFk, upleg, auto) + + matchPoseRotation(lolegFk, loleg, auto) + matchPoseScale(lolegFk, loleg, auto) + if not rig["MhaLegIkToAnkle" + suffix]: - matchPoseRotation(footFk, footFk, auto) - matchPoseRotation(toeFk, toeFk, auto) - - matchPoseRotation(uplegFk, uplegFk, auto) - matchPoseScale(uplegFk, uplegFk, auto) - - matchPoseRotation(lolegFk, lolegFk, auto) - matchPoseScale(lolegFk, lolegFk, auto) - + matchPoseRotation(footFk, foot, auto) + matchPoseRotation(toeFk, toe, auto) + muteConstraints(cnsFk, False) return @@ -4032,12 +4045,12 @@ def ik2fkLeg(context, suffix): #rig["MhaKneeFollowsHip" + suffix] = False #rig["MhaKneeFollowsFoot" + suffix] = False - + legIkToAnkle = rig["MhaLegIkToAnkle" + suffix] if legIkToAnkle: matchPoseTranslation(ankleIk, footFk, auto) matchPoseTranslation(legIk, legFk, auto) - matchPoseRotation(legIk, legFk, auto) + matchPoseRotation(legIk, legFk, auto) matchPoseReverse(toeIk, toeFk, auto) matchPoseReverse(footIk, footFk, auto) setInverse(rig, ankleIk) @@ -4070,24 +4083,53 @@ def setInverse(rig, pb): # # -SnapBones = { +SnapBonesAlpha7 = { + "Arm" : ["UpArm", "LoArm", "Hand"], "ArmFK" : ["UpArm", "LoArm", "ElbowPTFK", "Hand"], "ArmIK" : ["UpArmIK", "LoArmIK", "Elbow", "ElbowPT", "Wrist"], + "Leg" : ["UpLeg", "LoLeg", "Foot", "Toe"], "LegFK" : ["UpLeg", "LoLeg", "KneePTFK", "Foot", "Toe"], "LegIK" : ["UpLegIK", "LoLegIK", "KneePT", "Ankle", "LegIK", "LegFK", "FootRev", "ToeRev"], } +SnapBonesAlpha8 = { + "Arm" : ["upper_arm", "forearm", "hand"], + "ArmFK" : ["upper_arm.fk", "forearm.fk", "elbow.pt.fk", "hand.fk"], + "ArmIK" : ["upper_arm.ik", "forearm.ik", None, "elbow.pt.ik", "hand.ik"], + "Leg" : ["thigh", "shin", "foot", "toe"], + "LegFK" : ["thigh.fk", "shin.fk", "knee.pt.fk", "foot.fk", "toe.fk"], + "LegIK" : ["thigh.ik", "shin.ik", "knee.pt.ik", "ankle.ik", "foot.ik", "foot_helper", "foot.rev", "toe.rev"], +} def getSnapBones(rig, key, suffix): - names = SnapBones[key] + try: + rig.pose.bones["UpLeg_L"] + names = SnapBonesAlpha7[key] + except KeyError: + names = None + + if not names: + try: + rig.pose.bones["thigh.L"] + names = SnapBonesAlpha8[key] + suffix = '.' + suffix[1:] + except KeyError: + names = None + + if not names: + raise NameError("Not an mhx armature") + print(key, names) pbones = [] constraints = [] for name in names: - pb = rig.pose.bones[name+suffix] - pbones.append(pb) - for cns in pb.constraints: - if cns.type == 'LIMIT_ROTATION' and not cns.mute: - constraints.append(cns) + if name: + pb = rig.pose.bones[name+suffix] + pbones.append(pb) + for cns in pb.constraints: + if cns.type == 'LIMIT_ROTATION' and not cns.mute: + constraints.append(cns) + else: + pbones.append(None) return tuple(pbones),constraints @@ -4100,7 +4142,7 @@ class VIEW3D_OT_MhxSnapFk2IkButton(bpy.types.Operator): bl_idname = "mhx.snap_fk_ik" bl_label = "Snap FK" bl_options = {'UNDO'} - data = StringProperty() + data = StringProperty() def execute(self, context): bpy.ops.object.mode_set(mode='POSE') @@ -4113,14 +4155,14 @@ class VIEW3D_OT_MhxSnapFk2IkButton(bpy.types.Operator): elif prop[:6] == "MhaLeg": fk2ikLeg(context, prop[-2:]) restoreSnapProp(rig, prop, old, context) - return{'FINISHED'} + return{'FINISHED'} class VIEW3D_OT_MhxSnapIk2FkButton(bpy.types.Operator): bl_idname = "mhx.snap_ik_fk" bl_label = "Snap IK" bl_options = {'UNDO'} - data = StringProperty() + data = StringProperty() def execute(self, context): bpy.ops.object.mode_set(mode='POSE') @@ -4133,7 +4175,7 @@ class VIEW3D_OT_MhxSnapIk2FkButton(bpy.types.Operator): elif prop[:6] == "MhaLeg": ik2fkLeg(context, prop[-2:]) restoreSnapProp(rig, prop, old, context) - return{'FINISHED'} + return{'FINISHED'} def setSnapProp(rig, data, value, context, isIk): @@ -4162,7 +4204,7 @@ def setSnapProp(rig, data, value, context, isIk): oldExtra = False return (prop, (oldValue, ik, fk, extra, oldIk, oldFk, oldExtra)) - + def restoreSnapProp(rig, prop, old, context): updatePose(context) (oldValue, ik, fk, extra, oldIk, oldFk, oldExtra) = old @@ -4177,13 +4219,13 @@ class VIEW3D_OT_MhxToggleFkIkButton(bpy.types.Operator): bl_idname = "mhx.toggle_fk_ik" bl_label = "FK - IK" bl_options = {'UNDO'} - toggle = StringProperty() + toggle = StringProperty() def execute(self, context): words = self.toggle.split() rig = context.object prop = words[0] - value = float(words[1]) + value = float(words[1]) onLayer = int(words[2]) offLayer = int(words[3]) rig.data.layers[onLayer] = True @@ -4191,9 +4233,9 @@ class VIEW3D_OT_MhxToggleFkIkButton(bpy.types.Operator): rig[prop] = value # Don't do autokey - confusing. #if context.tool_settings.use_keyframe_insert_auto: - # rig.keyframe_insert('["%s"]' % prop, frame=scn.frame_current) + # rig.keyframe_insert('["%s"]' % prop, frame=scn.frame_current) updatePose(context) - return{'FINISHED'} + return{'FINISHED'} # @@ -4205,14 +4247,14 @@ class MhxFKIKPanel(bpy.types.Panel): bl_space_type = "VIEW_3D" bl_region_type = "UI" #bl_options = {'DEFAULT_CLOSED'} - + @classmethod def poll(cls, context): return (context.object and context.object.MhxRig == 'MHX') def draw(self, context): rig = context.object - layout = self.layout + layout = self.layout row = layout.row() row.label("") @@ -4228,7 +4270,7 @@ class MhxFKIKPanel(bpy.types.Panel): row.label("Leg") self.toggleButton(row, rig, "MhaLegIk_L", " 5", " 4") self.toggleButton(row, rig, "MhaLegIk_R", " 21", " 20") - + layout.label("IK Influence") row = layout.row() row.label("Arm") @@ -4238,7 +4280,7 @@ class MhxFKIKPanel(bpy.types.Panel): row.label("Leg") row.prop(rig, '["MhaLegIk_L"]', text="") row.prop(rig, '["MhaLegIk_R"]', text="") - + try: ok = (rig["MhxVersion"] >= 12) except: @@ -4246,14 +4288,14 @@ class MhxFKIKPanel(bpy.types.Panel): if not ok: layout.label("Snapping only works with MHX version 1.12 and later.") return - + layout.separator() layout.label("Snapping") row = layout.row() row.label("Rotation Limits") row.prop(rig, '["MhaRotationLimits"]', text="") row.prop(rig, "MhxSnapExact", text="Exact Snapping") - + layout.label("Snap Arm bones") row = layout.row() row.label("FK Arm") @@ -4280,13 +4322,13 @@ class MhxFKIKPanel(bpy.types.Panel): row.operator("mhx.toggle_fk_ik", text="IK").toggle = prop + " 0" + fk + ik else: row.operator("mhx.toggle_fk_ik", text="FK").toggle = prop + " 1" + ik + fk - -################################################################################### + +################################################################################### # # Posing panel # -################################################################################### +################################################################################### # # class MhxDriversPanel(bpy.types.Panel): # @@ -4296,7 +4338,7 @@ class MhxDriversPanel(bpy.types.Panel): bl_space_type = "VIEW_3D" bl_region_type = "UI" bl_options = {'DEFAULT_CLOSED'} - + @classmethod def poll(cls, context): return (context.object and context.object.MhxRig) @@ -4319,7 +4361,7 @@ class MhxDriversPanel(bpy.types.Panel): lrFaceProps.append(prop[:-2]) elif prop[-2:] != '_R': faceProps.append(prop) - + ob = context.object layout = self.layout for prop in props: @@ -4348,14 +4390,14 @@ class MhxDriversPanel(bpy.types.Panel): row = layout.row() row.prop(ob, '["%s"]' % (prop+"_L"), text=prop[3:]) row.prop(ob, '["%s"]' % (prop+"_R"), text=prop[3:]) - + return -################################################################################### +################################################################################### # # Visibility panel # -################################################################################### +################################################################################### # # class MhxVisibilityPanel(bpy.types.Panel): # @@ -4365,7 +4407,7 @@ class MhxVisibilityPanel(bpy.types.Panel): bl_space_type = "VIEW_3D" bl_region_type = "UI" bl_options = {'DEFAULT_CLOSED'} - + @classmethod def poll(cls, context): return (context.object and context.object.MhxRig) @@ -4376,7 +4418,7 @@ class MhxVisibilityPanel(bpy.types.Panel): props = list(ob.keys()) props.sort() for prop in props: - if prop[0:3] == "Mhh": + if prop[0:3] == "Mhh": layout.prop(ob, '["%s"]' % prop, text="Hide %s" % prop[3:]) layout.separator() layout.operator("mhx.update_textures") @@ -4402,8 +4444,8 @@ class VIEW3D_OT_MhxUpdateTexturesButton(bpy.types.Operator): prop = mat.path_resolve(driver.data_path) value = driver.evaluate(scn.frame_current) prop[driver.array_index] = value - return{'FINISHED'} - + return{'FINISHED'} + class VIEW3D_OT_MhxAddHidersButton(bpy.types.Operator): bl_idname = "mhx.add_hiders" bl_label = "Add Hide Property" @@ -4413,13 +4455,13 @@ class VIEW3D_OT_MhxAddHidersButton(bpy.types.Operator): rig = context.object for ob in context.scene.objects: if ob.select and ob != rig: - prop = "Mhh%s" % ob.name + prop = "Mhh%s" % ob.name defNewProp(prop, "Bool", "default=False") - rig[prop] = False + rig[prop] = False addHider(ob, "hide", rig, prop) addHider(ob, "hide_render", rig, prop) - return{'FINISHED'} - + return{'FINISHED'} + def addHider(ob, attr, rig, prop): fcu = ob.driver_add(attr) drv = fcu.driver @@ -4445,13 +4487,13 @@ class VIEW3D_OT_MhxRemoveHidersButton(bpy.types.Operator): ob.driver_remove("hide") ob.driver_remove("hide_render") del rig["Mhh%s" % ob.name] - return{'FINISHED'} - -################################################################################### + return{'FINISHED'} + +################################################################################### # # Layers panel # -################################################################################### +################################################################################### MhxLayers = [ (( 0, 'Root', 'MhxRoot'), @@ -4490,7 +4532,7 @@ class MhxLayersPanel(bpy.types.Panel): bl_space_type = "VIEW_3D" bl_region_type = "UI" #bl_options = {'DEFAULT_CLOSED'} - + @classmethod def poll(cls, context): ob = context.object @@ -4524,7 +4566,7 @@ class VIEW3D_OT_MhxEnableAllLayersButton(bpy.types.Operator): if type(left) != str: for (n, name, prop) in [left,right]: rig.data.layers[n] = True - return{'FINISHED'} + return{'FINISHED'} class VIEW3D_OT_MhxDisableAllLayersButton(bpy.types.Operator): bl_idname = "mhx.pose_disable_all_layers" @@ -4544,18 +4586,18 @@ class VIEW3D_OT_MhxDisableAllLayersButton(bpy.types.Operator): layers[0] = True if rig: rig.data.layers = layers - return{'FINISHED'} - -################################################################################### + return{'FINISHED'} + +################################################################################### # # Common functions # -################################################################################### +################################################################################### # # getMhxRigMesh(ob): # -def pollMhx(ob): +def pollMhx(ob): if not ob: return False elif ob.type == 'ARMATURE': @@ -4571,7 +4613,7 @@ def getMhxRigMesh(ob): for mesh in ob.children: if mesh.MhxMesh and ob.MhxRig: return (ob, mesh) - return (ob, None) + return (ob, None) elif ob.type == 'MESH': par = ob.parent if (par and par.type == 'ARMATURE' and par.MhxRig): @@ -4582,8 +4624,8 @@ def getMhxRigMesh(ob): else: return (None, None) return (None, None) - - + + # # setInterpolation(rig): # @@ -4599,12 +4641,12 @@ def setInterpolation(rig): pt.interpolation = 'LINEAR' fcu.extrapolation = 'CONSTANT' return - -################################################################################### + +################################################################################### # # initialize and register # -################################################################################### +################################################################################### def menu_func(self, context): self.layout.operator(ImportMhx.bl_idname, text="MakeHuman (.mhx)...") -- cgit v1.2.3