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:
authormeta-androcto <meta.androcto1@gmail.com>2016-08-05 13:17:48 +0300
committermeta-androcto <meta.androcto1@gmail.com>2016-08-05 13:17:48 +0300
commite2ebaa80b48550cdbb0e47f29e39e59ab57085b1 (patch)
treef21d1a648fe21547274402128d72164c497779e5 /io_import_scene_mhx.py
parent9178b6b22389333d19c12bd4d8b253fa9e3aa661 (diff)
remove .mhx i/o re: T49021
Diffstat (limited to 'io_import_scene_mhx.py')
-rw-r--r--io_import_scene_mhx.py4861
1 files changed, 0 insertions, 4861 deletions
diff --git a/io_import_scene_mhx.py b/io_import_scene_mhx.py
deleted file mode 100644
index 764c3633..00000000
--- a/io_import_scene_mhx.py
+++ /dev/null
@@ -1,4861 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-# You should have received a copy of the GNU General Public License
-#
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-# Project Name: MakeHuman
-# Product Home Page: http://www.makehuman.org/
-# Code Home Page: http://code.google.com/p/makehuman/
-# Authors: Thomas Larsson
-# Script copyright (C) MakeHuman Team 2001-2013
-# Coding Standards: See http://www.makehuman.org/node/165
-
-"""
-Abstract
-MHX (MakeHuman eXchange format) importer for Blender 2.6x.
-
-This script should be distributed with Blender.
-If not, place it in the .blender/scripts/addons dir
-Activate the script in the "Addons" tab (user preferences).
-Access from the File > Import menu.
-
-Alternatively, run the script in the script editor (Alt-P), and access from the File > Import menu
-"""
-
-bl_info = {
- "name": "Import: MakeHuman (.mhx)",
- "author": "Thomas Larsson",
- "version": "1.16.12",
- "blender": (2, 68, 0),
- "location": "File > Import > MakeHuman (.mhx)",
- "description": "Import files in the MakeHuman eXchange format (.mhx)",
- "warning": "",
- "wiki_url": "http://www.makehuman.org/documentation",
- "category": "Import-Export",
-}
-
-MAJOR_VERSION = 1
-MINOR_VERSION = 16
-FROM_VERSION = 13
-SUB_VERSION = 12
-
-majorVersion = MAJOR_VERSION
-minorVersion = MINOR_VERSION
-
-#
-#
-#
-
-import bpy
-import os
-import time
-import math
-import mathutils
-from mathutils import Vector, Matrix, Quaternion
-from bpy.props import *
-
-MHX249 = False
-Blender24 = False
-Blender25 = True
-theDir = "~/makehuman/exports"
-
-#
-#
-#
-
-theScale = 1.0
-One = 1.0/theScale
-useMesh = 1
-verbosity = 2
-warnedTextureDir = False
-warnedVersion = False
-
-true = True
-false = False
-Epsilon = 1e-6
-nErrors = 0
-theTempDatum = None
-theMessage = ""
-theMhxFile = ""
-
-#
-# toggle flags
-#
-
-T_EnforceVersion = 0x01
-T_Clothes = 0x02
-T_HardParents = 0x0
-T_CrashSafe = 0x0
-
-T_Diamond = 0x10
-T_Replace = 0x20
-T_Shapekeys = 0x40
-T_ShapeDrivers = 0x80
-
-T_Face = T_Shapekeys
-T_Shape = T_Shapekeys
-
-T_Mesh = 0x100
-T_Armature = 0x200
-T_Proxy = 0x400
-T_Cage = 0x800
-
-T_Rigify = 0x1000
-T_Opcns = 0x2000
-T_Symm = 0x4000
-
-DefaultToggle = ( T_EnforceVersion + T_Mesh + T_Armature +
- T_Shapekeys + T_ShapeDrivers + T_Proxy + T_Clothes + T_Rigify )
-
-toggle = DefaultToggle
-toggleSettings = toggle
-loadedData = None
-
-#
-# mhxEval(expr) - an attempt at a reasonably safe eval.
-# Note that expr never contains any whitespace due to the behavior
-# of the mhx tokenizer.
-#
-
-def mhxEval(expr, locls={}):
- globls = {
- '__builtins__' : {},
- 'toggle' : toggle,
- 'theScale' : theScale,
- 'One' : One,
- 'T_EnforceVersion' : T_EnforceVersion,
- 'T_Clothes' : T_Clothes,
- 'T_HardParents' : T_HardParents,
- 'T_CrashSafe' : T_CrashSafe,
- 'T_Diamond' : T_Diamond,
- 'T_Replace' : T_Replace,
- 'T_Shapekeys' : T_Shapekeys,
- 'T_ShapeDrivers' : T_ShapeDrivers,
- 'T_Face' : T_Face,
- 'T_Shape' : T_Shape,
- 'T_Mesh' : T_Mesh,
- 'T_Armature' : T_Armature,
- 'T_Proxy' : T_Proxy,
- 'T_Cage' : T_Cage,
- 'T_Rigify' : T_Rigify,
- 'T_Opcns' : T_Opcns,
- 'T_Symm' : T_Symm,
- }
- return eval(expr, globls, locls)
-
-#
-# Dictionaries
-#
-
-def initLoadedData():
- global loadedData
-
- loadedData = {
- 'NONE' : {},
-
- 'Object' : {},
- 'Mesh' : {},
- 'Armature' : {},
- 'Lamp' : {},
- 'Camera' : {},
- 'Lattice' : {},
- 'Curve' : {},
- 'Text' : {},
-
- 'Material' : {},
- 'Image' : {},
- 'MaterialTextureSlot' : {},
- 'Texture' : {},
-
- 'Bone' : {},
- 'BoneGroup' : {},
- 'Rigify' : {},
-
- 'Action' : {},
- 'Group' : {},
-
- 'MeshTextureFaceLayer' : {},
- 'MeshColorLayer' : {},
- 'VertexGroup' : {},
- 'ShapeKey' : {},
- 'ParticleSystem' : {},
-
- 'ObjectConstraints' : {},
- 'ObjectModifiers' : {},
- 'MaterialSlot' : {},
- }
- return
-
-def reinitGlobalData():
- global loadedData
- for key in [
- 'MeshTextureFaceLayer', 'MeshColorLayer', 'VertexGroup', 'ShapeKey',
- 'ParticleSystem', 'ObjectConstraints', 'ObjectModifiers', 'MaterialSlot']:
- loadedData[key] = {}
- return
-
-Plural = {
- 'Object' : 'objects',
- 'Mesh' : 'meshes',
- 'Lattice' : 'lattices',
- 'Curve' : 'curves',
- 'Text' : 'texts',
- 'Group' : 'groups',
- 'Empty' : 'empties',
- 'Armature' : 'armatures',
- 'Bone' : 'bones',
- 'BoneGroup' : 'bone_groups',
- 'Pose' : 'poses',
- 'PoseBone' : 'pose_bones',
- 'Material' : 'materials',
- 'Texture' : 'textures',
- 'Image' : 'images',
- 'Camera' : 'cameras',
- 'Lamp' : 'lamps',
- 'World' : 'worlds',
-}
-
-#
-# readMhxFile(filePath):
-#
-
-def readMhxFile(filePath):
- global nErrors, theScale, theArmature, defaultScale, One
- global toggle, warnedVersion, theMessage, alpha7, theDir
-
- defaultScale = theScale
- One = 1.0/theScale
- theArmature = None
- alpha7 = False
- warnedVersion = False
- initLoadedData()
- theMessage = ""
-
- theDir = os.path.dirname(filePath)
- fileName = os.path.expanduser(filePath)
- _,ext = os.path.splitext(fileName)
- if ext.lower() != ".mhx":
- print("Error: Not a mhx file: %s" % fileName.encode('utf-8', 'strict'))
- return
- print( "Opening MHX file %s " % fileName.encode('utf-8', 'strict') )
- print("Toggle %x" % toggle)
- time1 = time.clock()
-
- # ignore = False # UNUSED
- stack = []
- tokens = []
- key = "toplevel"
- level = 0
- nErrors = 0
- comment = 0
- nesting = 0
-
- file= open(fileName, "rU")
- print( "Tokenizing" )
- lineNo = 0
- for line in file:
- # print(line)
- lineSplit= line.split()
- lineNo += 1
- if len(lineSplit) == 0:
- pass
- elif lineSplit[0][0] == '#':
- if lineSplit[0] == '#if':
- if comment == nesting:
- try:
- res = mhxEval(lineSplit[1])
- except:
- res = False
- if res:
- comment += 1
- nesting += 1
- elif lineSplit[0] == '#else':
- if comment == nesting-1:
- comment += 1
- elif comment == nesting:
- comment -= 1
- elif lineSplit[0] == '#endif':
- if comment == nesting:
- comment -= 1
- nesting -= 1
- elif comment < nesting:
- pass
- elif lineSplit[0] == 'end':
- try:
- sub = tokens
- tokens = stack.pop()
- if tokens:
- tokens[-1][2] = sub
- level -= 1
- except:
- print( "Tokenizer error at or before line %d.\nThe mhx file has been corrupted.\nTry to export it again from MakeHuman." % lineNo )
- print( line )
- stack.pop()
- elif lineSplit[-1] == ';':
- if lineSplit[0] == '\\':
- key = lineSplit[1]
- tokens.append([key,lineSplit[2:-1],[]])
- else:
- key = lineSplit[0]
- tokens.append([key,lineSplit[1:-1],[]])
- else:
- key = lineSplit[0]
- tokens.append([key,lineSplit[1:],[]])
- stack.append(tokens)
- level += 1
- tokens = []
- file.close()
-
- if level != 0:
- MyError("Tokenizer error (%d).\nThe mhx file has been corrupted.\nTry to export it again from MakeHuman." % level)
- scn = clearScene()
- print( "Parsing" )
- parse(tokens)
-
- scn.objects.active = theArmature
- bpy.ops.object.mode_set(mode='OBJECT')
- bpy.ops.object.select_all(action='DESELECT')
- theArmature.select = True
- bpy.ops.object.mode_set(mode='POSE')
- 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:
- msg += " but there where %d errors. " % (nErrors)
- print(msg)
- return
-
-#
-# getObject(name, var):
-#
-
-def getObject(name, var):
- try:
- return loadedData['Object'][name]
- except:
- raise MhxError("Bug: object %s not found" % ob)
-
-#
-# checkMhxVersion(major, minor):
-#
-
-def checkMhxVersion(major, minor):
- global warnedVersion
- print("MHX", (major,minor), (MAJOR_VERSION, MINOR_VERSION), warnedVersion)
- if major != MAJOR_VERSION or minor < FROM_VERSION:
- if warnedVersion:
- return
- else:
- msg = (
-"Wrong MHX version\n" +
-"Expected MHX %d.%02d but the loaded file " % (MAJOR_VERSION, MINOR_VERSION) +
-"has version MHX %d.%02d\n" % (major, minor))
- if minor < FROM_VERSION:
- msg += (
-"You can disable this error message by deselecting the \n" +
-"Enforce version option when importing. Better:\n" +
-"Export the MHX file again with an updated version of MakeHuman.\n" +
-"The most up-to-date version of MakeHuman is the nightly build.\n")
- else:
- msg += (
-"Download the most recent Blender build from www.graphicall.org. \n" +
-"The most up-to-date version of the import script is distributed\n" +
-"with Blender. It can also be downloaded from MakeHuman. \n" +
-"It is located in the importers/mhx/blender25x \n" +
-"folder and is called import_scene_mhx.py. \n")
- if (toggle & T_EnforceVersion or minor > MINOR_VERSION):
- MyError(msg)
- else:
- print(msg)
- warnedVersion = True
- return
-
-#
-# parse(tokens):
-#
-
-ifResult = False
-
-def printMHXVersionInfo(versionStr, performVersionCheck = False):
- versionInfo = dict()
- val = versionStr.split()
-
- majorVersion = int(val[0])
- minorVersion = int(val[1])
-
- for debugVal in val[2:]:
- debugVal = debugVal.replace("_"," ")
- dKey, dVal = debugVal.split(':')
- versionInfo[ dKey.strip() ] = dVal.strip()
-
- if 'MHXImporter' in versionInfo:
- print("MHX importer version: ", versionInfo["MHXImporter"])
- if performVersionCheck:
- checkMhxVersion(majorVersion, minorVersion)
- else:
- print("MHX: %s.%s" % (majorVersion, minorVersion))
-
- for (key, value) in versionInfo.items():
- if key == "MHXImporter":
- continue
- print("%s: %s" % (key, value))
-
-def parse(tokens):
- global MHX249, ifResult, theScale, defaultScale, One
- global majorVersion, minorVersion
- versionInfoStr = ""
-
- for (key, val, sub) in tokens:
- data = None
- if key == 'MHX':
- importerVerStr = "MHXImporter:_%s" % (bl_info["version"])
- versionInfoStr = " ".join(val + [importerVerStr])
-
- printMHXVersionInfo(versionInfoStr, performVersionCheck = True)
- elif key == 'MHX249':
- MHX249 = mhxEval(val[0])
- print("Blender 2.49 compatibility mode is %s\n" % MHX249)
- elif MHX249:
- pass
- elif key == 'print':
- msg = concatList(val)
- print(msg)
- elif key == 'warn':
- msg = concatList(val)
- print(msg)
- elif key == 'error':
- msg = concatList(val)
- MyError(msg)
- elif key == 'NoScale':
- if mhxEval(val[0]):
- theScale = 1.0
- else:
- theScale = defaultScale
- One = 1.0/theScale
- elif key == "Object":
- parseObject(val, sub, versionInfoStr)
- elif key == "Mesh":
- reinitGlobalData()
- data = parseMesh(val, sub)
- elif key == "Armature":
- data = parseArmature(val, sub)
- elif key == "Pose":
- data = parsePose(val, sub)
- elif key == "Action":
- data = parseAction(val, sub)
- elif key == "Material":
- data = parseMaterial(val, sub)
- elif key == "Texture":
- data = parseTexture(val, sub)
- elif key == "Image":
- data = parseImage(val, sub)
- elif key == "Curve":
- data = parseCurve(val, sub)
- elif key == "TextCurve":
- data = parseTextCurve(val, sub)
- elif key == "Lattice":
- data = parseLattice(val, sub)
- elif key == "Group":
- data = parseGroup(val, sub)
- elif key == "Lamp":
- data = parseLamp(val, sub)
- elif key == "World":
- data = parseWorld(val, sub)
- elif key == "Scene":
- data = parseScene(val, sub)
- elif key == "DefineProperty":
- parseDefineProperty(val, sub)
- elif key == "Process":
- parseProcess(val, sub)
- elif key == "PostProcess":
- postProcess(val)
- hideLayers(val)
- elif key == "CorrectRig":
- correctRig(val)
- elif key == "Rigify":
- if toggle & T_Rigify:
- rigifyMhx(bpy.context)
- elif key == 'AnimationData':
- try:
- ob = loadedData['Object'][val[0]]
- except:
- ob = None
- if ob:
- bpy.context.scene.objects.active = ob
- parseAnimationData(ob, val, sub)
- elif key == 'MaterialAnimationData':
- try:
- ob = loadedData['Object'][val[0]]
- except:
- ob = None
- if ob:
- bpy.context.scene.objects.active = ob
- mat = ob.data.materials[int(val[2])]
- parseAnimationData(mat, val, sub)
- elif key == 'ShapeKeys':
- try:
- ob = loadedData['Object'][val[0]]
- except:
- MyError("ShapeKeys object %s does not exist" % val[0])
- if ob:
- bpy.context.scene.objects.active = ob
- parseShapeKeys(ob, ob.data, val, sub)
- else:
- data = parseDefaultType(key, val, sub)
-
-
-#
-# parseDefaultType(typ, args, tokens):
-#
-
-def parseDefaultType(typ, args, tokens):
- name = args[0]
- data = None
- expr = "bpy.data.%s.new('%s')" % (Plural[typ], name)
- data = mhxEval(expr)
-
- bpyType = typ.capitalize()
- loadedData[bpyType][name] = data
- if data is None:
- return None
-
- for (key, val, sub) in tokens:
- defaultKey(key, val, sub, data)
- return data
-
-#
-# concatList(elts)
-#
-
-def concatList(elts):
- string = ""
- for elt in elts:
- string += " %s" % elt
- return string
-
-#
-# parseAction(args, tokens):
-# parseFCurve(fcu, args, tokens):
-# parseKeyFramePoint(pt, args, tokens):
-#
-
-def parseAction(args, tokens):
- name = args[0]
- if invalid(args[1]):
- return
-
- ob = bpy.context.object
- bpy.ops.object.mode_set(mode='POSE')
- if ob.animation_data:
- ob.animation_data.action = None
- created = {}
- 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:
- print("Ignoring action %s" % name)
- 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)
- else:
- defaultKey(key, val, sub, act)
- ob.animation_data.action = None
- bpy.ops.object.mode_set(mode='OBJECT')
- return act
-
-def prepareActionFCurve(ob, created, args, tokens):
- dataPath = args[0]
- index = args[1]
- (expr, channel) = channelFromDataPath(dataPath, index)
- try:
- if channel in created[expr]:
- return
- else:
- created[expr].append(channel)
- except:
- created[expr] = [channel]
-
- times = []
- for (key, val, sub) in tokens:
- if key == 'kp':
- times.append(int(val[0]))
-
- try:
- data = mhxEval(expr)
- except:
- print("Ignoring illegal expression: %s" % expr)
- return
-
- n = 0
- for t in times:
- #bpy.context.scene.current_frame = t
- bpy.ops.anim.change_frame(frame = t)
- try:
- data.keyframe_insert(channel)
- n += 1
- except:
- pass
- #print("failed", data, expr, channel)
- if n != len(times):
- print("Mismatch", n, len(times), expr, channel)
- return
-
-def channelFromDataPath(dataPath, index):
- words = dataPath.split(']')
- if len(words) == 1:
- # location
- expr = "ob"
- channel = dataPath
- elif len(words) == 2:
- # pose.bones["tongue"].location
- expr = "ob.%s]" % (words[0])
- cwords = words[1].split('.')
- channel = cwords[1]
- elif len(words) == 3:
- # pose.bones["brow.R"]["mad"]
- expr = "ob.%s]" % (words[0])
- cwords = words[1].split('"')
- channel = cwords[1]
- return (expr, channel)
-
-def parseActionFCurve(act, ob, args, tokens):
- dataPath = args[0]
- index = args[1]
- (expr, channel) = channelFromDataPath(dataPath, index)
- index = int(args[1])
-
- success = False
- for fcu in act.fcurves:
- (expr1, channel1) = channelFromDataPath(fcu.data_path, fcu.array_index)
- if expr1 == expr and channel1 == channel and fcu.array_index == index:
- success = True
- break
- if not success:
- return None
-
- n = 0
- for (key, val, sub) in tokens:
- if key == 'kp':
- try:
- pt = fcu.keyframe_points[n]
- pt.interpolation = 'LINEAR'
- pt = parseKeyFramePoint(pt, val, sub)
- n += 1
- except:
- pass
- #print(tokens)
- #MyError("kp", fcu, n, len(fcu.keyframe_points), val)
- else:
- defaultKey(key, val, sub, fcu)
- return fcu
-
-def parseKeyFramePoint(pt, args, tokens):
- pt.co = (float(args[0]), float(args[1]))
- if len(args) > 2:
- pt.handle1 = (float(args[2]), float(args[3]))
- pt.handle2 = (float(args[3]), float(args[5]))
- return pt
-
-#
-# parseAnimationData(rna, args, tokens):
-# parseDriver(drv, args, tokens):
-# parseDriverVariable(var, args, tokens):
-#
-
-def parseAnimationData(rna, args, tokens):
- if not mhxEval(args[1]):
- return
- 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)
- else:
- defaultKey(key, val, sub, adata)
- return adata
-
-def parseAnimDataFCurve(adata, rna, args, tokens):
- if invalid(args[2]):
- return
- dataPath = args[0]
- index = int(args[1])
- n = 1
- for (key, val, sub) in tokens:
- if key == 'Driver':
- fcu = parseDriver(adata, dataPath, index, rna, val, sub)
- fmod = fcu.modifiers[0]
- fcu.modifiers.remove(fmod)
- elif key == 'FModifier':
- parseFModifier(fcu, val, sub)
- elif key == 'kp':
- pt = fcu.keyframe_points.insert(n, 0)
- pt.interpolation = 'LINEAR'
- pt = parseKeyFramePoint(pt, val, sub)
- n += 1
- else:
- defaultKey(key, val, sub, fcu)
- return fcu
-
-"""
- fcurve = con.driver_add("influence", 0)
- driver = fcurve.driver
- driver.type = 'AVERAGE'
-"""
-def parseDriver(adata, dataPath, index, rna, args, tokens):
- if dataPath[-1] == ']':
- words = dataPath.split(']')
- expr = "rna." + words[0] + ']'
- pwords = words[1].split('"')
- prop = pwords[1]
- bone = mhxEval(expr)
- return None
- else:
- words = dataPath.split('.')
- channel = words[-1]
- expr = "rna"
- for n in range(len(words)-1):
- expr += "." + words[n]
- expr += ".driver_add('%s', index)" % channel
-
- fcu = mhxEval(expr, locals())
- drv = fcu.driver
- drv.type = args[0]
- for (key, val, sub) in tokens:
- if key == 'DriverVariable':
- var = parseDriverVariable(drv, rna, val, sub)
- else:
- defaultKey(key, val, sub, drv)
- return fcu
-
-def parseDriverVariable(drv, rna, args, tokens):
- var = drv.variables.new()
- var.name = args[0]
- var.type = args[1]
- nTarget = 0
- for (key, val, sub) in tokens:
- if key == 'Target':
- parseDriverTarget(var, nTarget, rna, val, sub)
- nTarget += 1
- else:
- defaultKey(key, val, sub, var)
- return var
-
-def parseFModifier(fcu, args, tokens):
- fmod = fcu.modifiers.new(args[0])
- #fmod = fcu.modifiers[0]
- for (key, val, sub) in tokens:
- defaultKey(key, val, sub, fmod)
- return fmod
-
-"""
- var = driver.variables.new()
- var.name = target_bone
- var.targets[0].id_type = 'OBJECT'
- var.targets[0].id = obj
- var.targets[0].rna_path = driver_path
-"""
-def parseDriverTarget(var, nTarget, rna, args, tokens):
- targ = var.targets[nTarget]
- name = args[0]
- #targ.id_type = args[1]
- dtype = args[1].capitalize()
- dtype = 'Object'
- targ.id = loadedData[dtype][name]
- for (key, val, sub) in tokens:
- if key == 'data_path':
- words = val[0].split('"')
- if len(words) > 1:
- targ.data_path = propNames(words[1])[1]
- else:
- targ.data_path = propNames(val)[1]
- else:
- defaultKey(key, val, sub, targ)
- return targ
-
-
-#
-# parseMaterial(args, ext, tokens):
-# parseMTex(mat, args, tokens):
-# parseTexture(args, tokens):
-#
-
-def parseMaterial(args, tokens):
- name = args[0]
- mat = bpy.data.materials.new(name)
- if mat is None:
- return None
- loadedData['Material'][name] = mat
- for (key, val, sub) in tokens:
- if key == 'MTex':
- parseMTex(mat, val, sub)
- elif key == 'Ramp':
- parseRamp(mat, val, sub)
- elif key == 'RaytraceTransparency':
- parseDefault(mat.raytrace_transparency, sub, {}, [])
- elif key == 'Halo':
- parseDefault(mat.halo, sub, {}, [])
- elif key == 'SSS':
- parseDefault(mat.subsurface_scattering, sub, {}, [])
- elif key == 'Strand':
- parseDefault(mat.strand, sub, {}, [])
- elif key == 'NodeTree':
- mat.use_nodes = True
- parseNodeTree(mat.node_tree, val, sub)
- elif key == 'AnimationData':
- parseAnimationData(mat, val, sub)
- else:
- exclude = ['specular_intensity', 'tangent_shading']
- defaultKey(key, val, sub, mat)
-
- return mat
-
-def parseMTex(mat, args, tokens):
- index = int(args[0])
- texname = args[1]
- texco = args[2]
- mapto = args[3]
- tex = loadedData['Texture'][texname]
- mtex = mat.texture_slots.add()
- mtex.texture_coords = texco
- mtex.texture = tex
-
- for (key, val, sub) in tokens:
- defaultKey(key, val, sub, mtex)
-
- return mtex
-
-def parseTexture(args, tokens):
- if verbosity > 2:
- print( "Parsing texture %s" % args )
- 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:
- imgName = val[0]
- img = loadedData['Image'][imgName]
- tex.image = img
- except:
- msg = "Unable to load image '%s'" % val[0]
- elif key == 'Ramp':
- parseRamp(tex, val, sub)
- elif key == 'NodeTree':
- tex.use_nodes = True
- parseNodeTree(tex.node_tree, val, sub)
- else:
- defaultKey(key, val, sub, tex, ['use_nodes', 'use_textures', 'contrast', 'use_alpha'])
-
- return tex
-
-def parseRamp(data, args, tokens):
- setattr(data, "use_%s" % args[0], True)
- ramp = getattr(data, args[0])
- elts = ramp.elements
- n = 0
- for (key, val, sub) in tokens:
- if key == 'Element':
- elts[n].color = mhxEval(val[0], locals())
- elts[n].position = mhxEval(val[1], locals())
- n += 1
- else:
- defaultKey(key, val, sub, tex, ['use_nodes', 'use_textures', 'contrast'])
-
-def parseSSS(mat, args, tokens):
- sss = mat.subsurface_scattering
- for (key, val, sub) in tokens:
- defaultKey(key, val, sub, sss)
-
-def parseStrand(mat, args, tokens):
- strand = mat.strand
- for (key, val, sub) in tokens:
- defaultKey(key, val, sub, strand)
-
-#
-# parseNodeTree(tree, args, tokens):
-# parseNode(node, args, tokens):
-# parseSocket(socket, args, tokens):
-#
-
-def parseNodeTree(tree, args, tokens):
- return
- print("Tree", tree, args)
- print(list(tree.nodes))
- tree.name = args[0]
- for (key, val, sub) in tokens:
- if key == 'Node':
- parseNodes(tree.nodes, val, sub)
- else:
- defaultKey(key, val, sub, tree)
-
-def parseNodes(nodes, args, tokens):
- print("Nodes", nodes, args)
- print(list(nodes))
- node.name = args[0]
- for (key, val, sub) in tokens:
- if key == 'Inputs':
- parseSocket(node.inputs, val, sub)
- elif key == 'Outputs':
- parseSocket(node.outputs, val, sub)
- else:
- defaultKey(key, val, sub, node)
-
-def parseNode(node, args, tokens):
- print("Node", node, args)
- print(list(node.inputs), list(node.outputs))
- node.name = args[0]
- for (key, val, sub) in tokens:
- if key == 'Inputs':
- parseSocket(node.inputs, val, sub)
- elif key == 'Outputs':
- parseSocket(node.outputs, val, sub)
- else:
- defaultKey(key, val, sub, node)
-
-def parseSocket(socket, args, tokens):
- print("Socket", socket, args)
- socket.name = args[0]
- for (key, val, sub) in tokens:
- if key == 'Node':
- parseNode(tree.nodes, val, sub)
- else:
- defaultKey(key, val, sub, tree)
-
-
-
-#
-# loadImage(filepath):
-# parseImage(args, tokens):
-#
-
-def loadImage(relFilepath):
- filepath = os.path.normpath(os.path.join(theDir, relFilepath))
- print( "Loading %s" % filepath.encode('utf-8','strict'))
- if os.path.isfile(filepath):
- #print( "Found file %s." % filepath.encode('utf-8','strict') )
- try:
- img = bpy.data.images.load(filepath)
- return img
- except:
- print( "Cannot read image" )
- return None
- else:
- print( "No such file: %s" % filepath.encode('utf-8','strict') )
- return None
-
-
-def parseImage(args, tokens):
- imgName = args[0]
- img = None
- for (key, val, sub) in tokens:
- if key == 'Filename':
- filename = val[0]
- for n in range(1,len(val)):
- filename += " " + val[n]
- img = loadImage(filename)
- if img is None:
- return None
- img.name = imgName
- else:
- defaultKey(key, val, sub, img, ['depth', 'dirty', 'has_data', 'size', 'type', 'use_premultiply'])
- print ("Image %s" % img )
- loadedData['Image'][imgName] = img
- return img
-
-#
-# parseObject(args, tokens):
-# createObject(type, name, data, datName):
-# setObjectAndData(args, typ):
-#
-
-def parseObject(args, tokens, versionInfoStr=""):
- if verbosity > 2:
- print( "Parsing object %s" % args )
- name = args[0]
- typ = args[1]
- datName = args[2]
-
- if typ == 'EMPTY':
- ob = bpy.data.objects.new(name, None)
- loadedData['Object'][name] = ob
- linkObject(ob, None)
- else:
- try:
- data = loadedData[typ.capitalize()][datName]
- except:
- MyError("Failed to find data: %s %s %s" % (name, typ, datName))
- return
-
- try:
- ob = loadedData['Object'][name]
- bpy.context.scene.objects.active = ob
- #print("Found data", ob)
- except:
- ob = None
-
- if ob is None:
- ob = createObject(typ, name, data, datName)
- linkObject(ob, data)
-
- for (key, val, sub) in tokens:
- if key == 'Modifier':
- parseModifier(ob, val, sub)
- elif key == 'Constraint':
- parseConstraint(ob.constraints, None, val, sub)
- elif key == 'AnimationData':
- parseAnimationData(ob, val, sub)
- elif key == 'ParticleSystem':
- parseParticleSystem(ob, val, sub)
- elif key == 'FieldSettings':
- parseDefault(ob.field, sub, {}, [])
- else:
- defaultKey(key, val, sub, ob, ['type', 'data'])
-
- if versionInfoStr:
- print('============= updating version string %s' % versionInfoStr)
- ob.MhxVersionStr = versionInfoStr
- else:
- print('============= not updating version str')
-
- if bpy.context.object == ob:
- if ob.type == 'MESH':
- bpy.ops.object.shade_smooth()
- else:
- print("Context", ob, bpy.context.object, bpy.context.scene.objects.active)
- return
-
-def createObject(typ, name, data, datName):
- # 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:
- ob.data = data
- scn = bpy.context.scene
- scn.objects.link(ob)
- scn.objects.active = ob
- #print("Linked object", ob)
- #print("Scene", scn)
- #print("Active", scn.objects.active)
- #print("Context", bpy.context.object)
- return ob
-
-def setObjectAndData(args, typ):
- datName = args[0]
- obName = args[1]
- #bpy.ops.object.add(type=typ)
- ob = bpy.context.object
- ob.name = obName
- ob.data.name = datName
- loadedData[typ][datName] = ob.data
- loadedData['Object'][obName] = ob
- return ob.data
-
-
-#
-# parseModifier(ob, args, tokens):
-#
-
-
-def parseModifier(ob, args, tokens):
- name = args[0]
- typ = args[1]
- if typ == 'PARTICLE_SYSTEM':
- return None
- mod = ob.modifiers.new(name, typ)
- for (key, val, sub) in tokens:
- if key == 'HookAssignNth':
- if val[0] == 'CURVE':
- hookAssignNth(mod, int(val[1]), True, ob.data.splines[0].points)
- elif val[0] == 'LATTICE':
- hookAssignNth(mod, int(val[1]), False, ob.data.points)
- elif val[0] == 'MESH':
- hookAssignNth(mod, int(val[1]), True, ob.data.vertices)
- else:
- MyError("Unknown hook %s" % val)
- else:
- defaultKey(key, val, sub, mod)
- return mod
-
-def hookAssignNth(mod, n, select, points):
- if select:
- for pt in points:
- pt.select = False
- points[n].select = True
- sel = []
- for pt in points:
- sel.append(pt.select)
- #print(mod, sel, n, points)
-
- bpy.ops.object.mode_set(mode='EDIT')
- bpy.ops.object.hook_reset(modifier=mod.name)
- bpy.ops.object.hook_select(modifier=mod.name)
- bpy.ops.object.hook_assign(modifier=mod.name)
- bpy.ops.object.mode_set(mode='OBJECT')
- return
-
-#
-# parseParticleSystem(ob, args, tokens):
-# parseParticles(particles, args, tokens):
-# parseParticle(par, args, tokens):
-#
-
-def parseParticleSystem(ob, args, tokens):
- print(ob, bpy.context.object)
- pss = ob.particle_systems
- print(pss, pss.values())
- name = args[0]
- typ = args[1]
- #psys = pss.new(name, typ)
- bpy.ops.object.particle_system_add()
- print(pss, pss.values())
- psys = pss[-1]
- psys.name = name
- psys.settings.type = typ
- loadedData['ParticleSystem'][name] = psys
- print("Psys", psys)
-
- for (key, val, sub) in tokens:
- if key == 'Particles':
- parseParticles(psys, val, sub)
- else:
- defaultKey(key, val, sub, psys)
- return psys
-
-def parseParticles(psys, args, tokens):
- particles = psys.particles
- bpy.ops.particle.particle_edit_toggle()
- n = 0
- for (key, val, sub) in tokens:
- if key == 'Particle':
- parseParticle(particles[n], val, sub)
- n += 1
- else:
- for par in particles:
- defaultKey(key, val, sub, par)
- bpy.ops.particle.particle_edit_toggle()
- return particles
-
-def parseParticle(par, args, tokens):
- n = 0
- for (key, val, sub) in tokens:
- if key == 'h':
- h = par.hair[n]
- h.location = mhxEval(val[0], locals())
- h.time = int(val[1])
- h.weight = float(val[2])
- n += 1
- elif key == 'location':
- par.location = mhxEval(val[0], locals())
- return
-
-#
-# unpackList(list_of_tuples):
-#
-
-def unpackList(list_of_tuples):
- l = []
- for t in list_of_tuples:
- l.extend(t)
- return l
-
-
-#
-
-# parseMesh (args, tokens):
-#
-
-def parseMesh (args, tokens):
- global BMeshAware
- if verbosity > 2:
- print( "Parsing mesh %s" % args )
-
- mename = args[0]
- obname = args[1]
- me = bpy.data.meshes.new(mename)
- ob = createObject('MESH', obname, me, mename)
-
- verts = []
- edges = []
- faces = []
- vertsTex = []
- texFaces = []
-
- for (key, val, sub) in tokens:
- if key == 'Verts':
- verts = parseVerts(sub)
- elif key == 'Edges':
- edges = parseEdges(sub)
- elif key == 'Faces':
- faces = parseFaces(sub)
-
- if faces:
- me.from_pydata(verts, [], faces)
- else:
- 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:
- if key == 'Verts' or key == 'Edges' or key == 'Faces':
- pass
- elif key == 'MeshTextureFaceLayer':
- if BMeshAware:
- parseUvTextureBMesh(val, sub, me)
- else:
- parseUvTextureNoBMesh(val, sub, me)
- 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:
- mat = loadedData['Material'][val[0]]
- except:
- mat = None
- if mat:
- me.materials.append(mat)
- else:
- defaultKey(key, val, sub, me)
-
- for (key, val, sub) in tokens:
- if key == 'Faces':
- if BMeshAware:
- parseFaces2BMesh(sub, me)
- else:
- parseFaces2NoBMesh(sub, me)
- return me
-
-#
-# parseVerts(tokens):
-# parseEdges(tokens):
-# parseFaces(tokens):
-# parseFaces2(tokens, me):
-#
-
-def parseVerts(tokens):
- verts = []
- for (key, val, sub) in tokens:
- if key == 'v':
- verts.append( (theScale*float(val[0]), theScale*float(val[1]), theScale*float(val[2])) )
- return verts
-
-def parseEdges(tokens):
- edges = []
- for (key, val, sub) in tokens:
- if key == 'e':
- edges.append((int(val[0]), int(val[1])))
- return edges
-
-def parseFaces(tokens):
- faces = []
- for (key, val, sub) in tokens:
- if key == 'f':
- if len(val) == 3:
- face = [int(val[0]), int(val[1]), int(val[2])]
- elif len(val) == 4:
- face = [int(val[0]), int(val[1]), int(val[2]), int(val[3])]
- faces.append(face)
- return faces
-
-def parseFaces2BMesh(tokens, me):
- n = 0
- for (key, val, sub) in tokens:
- if key == 'ft':
- f = me.polygons[n]
- f.material_index = int(val[0])
- f.use_smooth = int(val[1])
- n += 1
- elif key == 'ftn':
- mn = int(val[1])
- us = int(val[2])
- npts = int(val[0])
- for i in range(npts):
- f = me.polygons[n]
- f.material_index = mn
- f.use_smooth = us
- n += 1
- elif key == 'mn':
- fn = int(val[0])
- mn = int(val[1])
- f = me.polygons[fn]
- f.material_index = mn
- elif key == 'ftall':
- mat = int(val[0])
- smooth = int(val[1])
- for f in me.polygons:
- f.material_index = mat
- f.use_smooth = smooth
- return
-
-def parseFaces2NoBMesh(tokens, me):
- n = 0
- for (key, val, sub) in tokens:
- if key == 'ft':
- f = me.faces[n]
- f.material_index = int(val[0])
- f.use_smooth = int(val[1])
- n += 1
- elif key == 'ftn':
- mn = int(val[1])
- us = int(val[2])
- npts = int(val[0])
- for i in range(npts):
- f = me.faces[n]
- f.material_index = mn
- f.use_smooth = us
- n += 1
- elif key == 'mn':
- fn = int(val[0])
- mn = int(val[1])
- f = me.faces[fn]
- f.material_index = mn
- elif key == 'ftall':
- mat = int(val[0])
- smooth = int(val[1])
- for f in me.faces:
- f.material_index = mat
- f.use_smooth = smooth
- return
-
-
-#
-# parseUvTexture(args, tokens, me,):
-# parseUvTexData(args, tokens, uvdata):
-#
-
-def parseUvTextureBMesh(args, tokens, me):
- name = args[0]
- bpy.ops.mesh.uv_texture_add()
- uvtex = me.uv_textures[-1]
- uvtex.name = name
- uvloop = me.uv_layers[-1]
- loadedData['MeshTextureFaceLayer'][name] = uvloop
- for (key, val, sub) in tokens:
- if key == 'Data':
- parseUvTexDataBMesh(val, sub, uvloop.data)
- else:
- defaultKey(key, val, sub, uvtex)
- return
-
-def parseUvTexDataBMesh(args, tokens, data):
- n = 0
- for (key, val, sub) in tokens:
- if key == 'vt':
- data[n].uv = (float(val[0]), float(val[1]))
- n += 1
- data[n].uv = (float(val[2]), float(val[3]))
- n += 1
- data[n].uv = (float(val[4]), float(val[5]))
- n += 1
- if len(val) > 6:
- data[n].uv = (float(val[6]), float(val[7]))
- n += 1
- return
-
-def parseUvTextureNoBMesh(args, tokens, me):
- name = args[0]
- uvtex = me.uv_textures.new(name = name)
- loadedData['MeshTextureFaceLayer'][name] = uvtex
- for (key, val, sub) in tokens:
- if key == 'Data':
- parseUvTexDataNoBMesh(val, sub, uvtex.data)
- else:
- defaultKey(key, val, sub, uvtex)
- return
-
-def parseUvTexDataNoBMesh(args, tokens, data):
- n = 0
- for (key, val, sub) in tokens:
- if key == 'vt':
- data[n].uv1 = (float(val[0]), float(val[1]))
- data[n].uv2 = (float(val[2]), float(val[3]))
- data[n].uv3 = (float(val[4]), float(val[5]))
- if len(val) > 6:
- data[n].uv4 = (float(val[6]), float(val[7]))
- n += 1
- return
-
-#
-# parseVertColorLayer(args, tokens, me):
-# parseVertColorData(args, tokens, data):
-#
-
-def parseVertColorLayer(args, tokens, me):
- name = args[0]
- print("VertColorLayer", name)
- vcol = me.vertex_colors.new(name)
- loadedData['MeshColorLayer'][name] = vcol
- for (key, val, sub) in tokens:
- if key == 'Data':
- parseVertColorData(val, sub, vcol.data)
- else:
- defaultKey(key, val, sub, vcol)
- return
-
-def parseVertColorData(args, tokens, data):
- n = 0
- for (key, val, sub) in tokens:
- if key == 'cv':
- data[n].color1 = mhxEval(val[0])
- data[n].color2 = mhxEval(val[1])
- data[n].color3 = mhxEval(val[2])
- data[n].color4 = mhxEval(val[3])
- n += 1
- return
-
-
-#
-# parseVertexGroup(ob, me, args, tokens):
-#
-
-def parseVertexGroup(ob, me, args, tokens):
- global toggle
- if verbosity > 2:
- print( "Parsing vertgroup %s" % args )
- grpName = args[0]
- try:
- res = mhxEval(args[1])
- except:
- res = True
- if not res:
- return
-
- if (toggle & T_Armature) or (grpName in ['Eye_L', 'Eye_R', 'Gums', 'Head', 'Jaw', 'Left', 'Middle', 'Right', 'Scalp']):
- try:
- group = loadedData['VertexGroup'][grpName]
- except KeyError:
- group = ob.vertex_groups.new(grpName)
- loadedData['VertexGroup'][grpName] = group
- for (key, val, sub) in tokens:
- if key == 'wv':
- group.add( [int(val[0])], float(val[1]), 'REPLACE' )
- return
-
-
-#
-# parseShapeKeys(ob, me, args, tokens):
-# parseShapeKey(ob, me, args, tokens):
-# addShapeKey(ob, name, vgroup, tokens):
-# doShape(name):
-#
-
-def doShape(name):
- if (toggle & T_Shapekeys) and (name == 'Basis'):
- return True
- else:
- return (toggle & T_Face)
-
-
-def parseShapeKeys(ob, me, args, tokens):
- for (key, val, sub) in tokens:
- if key == 'ShapeKey':
- parseShapeKey(ob, me, val, sub)
- elif key == 'AnimationData':
- if me.shape_keys:
- parseAnimationData(me.shape_keys, val, sub)
- elif key == 'Expression':
- prop = "Mhe" + val[0].capitalize()
- parseUnits(prop, ob, sub)
- elif key == 'Viseme':
- name = val[0].upper()
- if name in ["REST", "ETC"]:
- name = name.capitalize()
- prop = "Mhv" + name
- parseUnits(prop, ob, sub)
- ob.active_shape_key_index = 0
-
-
-def parseUnits(prop, ob, sub):
- string = ""
- for words in sub:
- unit = words[0].replace("-","_")
- value = words[1][0]
- string += "%s:%s;" % (unit, value)
- rig = ob.parent
- rig[prop] = string
-
-
-def parseShapeKey(ob, me, args, tokens):
- if verbosity > 2:
- print( "Parsing ob %s shape %s" % (bpy.context.object, args[0] ))
- name = args[0]
- lr = args[1]
- if invalid(args[2]):
- return
-
- if lr == 'Sym': # or toggle & T_Symm:
- addShapeKey(ob, name, None, tokens)
- elif lr == 'LR':
- addShapeKey(ob, name+'_L', 'Left', tokens)
- addShapeKey(ob, name+'_R', 'Right', tokens)
- else:
- MyError("ShapeKey L/R %s" % lr)
- return
-
-
-def addShapeKey(ob, name, vgroup, tokens):
- skey = ob.shape_key_add(name=name, from_mix=False)
- if name != 'Basis':
- skey.relative_key = loadedData['ShapeKey']['Basis']
- skey.name = name
- if vgroup:
- skey.vertex_group = vgroup
- loadedData['ShapeKey'][name] = skey
-
- for (key, val, sub) in tokens:
- if key == 'sv':
- index = int(val[0])
- pt = skey.data[index].co
- pt[0] += theScale*float(val[1])
- pt[1] += theScale*float(val[2])
- pt[2] += theScale*float(val[3])
- else:
- defaultKey(key, val, sub, skey)
-
- return
-
-
-#
-# parseArmature (obName, args, tokens)
-#
-
-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)
- theArmature = ob
-
- bpy.ops.object.mode_set(mode='OBJECT')
- bpy.ops.object.mode_set(mode='EDIT')
-
- heads = {}
- tails = {}
- for (key, val, sub) in tokens:
- if key == 'Bone':
- bname = val[0]
- if not invalid(val[1]):
- bone = amt.edit_bones.new(bname)
- parseBone(bone, amt, sub, heads, tails)
- loadedData['Bone'][bname] = bone
- elif key == 'RecalcRoll':
- rolls = {}
- for bone in amt.edit_bones:
- bone.select = False
- blist = mhxEval(val[0])
- for name in blist:
- bone = amt.edit_bones[name]
- bone.select = True
- bpy.ops.armature.calculate_roll(type='Z')
- for bone in amt.edit_bones:
- rolls[bone.name] = bone.roll
- bpy.ops.object.mode_set(mode='OBJECT')
- for bone in amt.bones:
- bone['Roll'] = rolls[bone.name]
- bpy.ops.object.mode_set(mode='EDIT')
- else:
- defaultKey(key, val, sub, amt, ['MetaRig'])
- bpy.ops.object.mode_set(mode='OBJECT')
-
- return amt
-
-#
-# parseBone(bone, amt, tokens, heads, tails):
-#
-
-def parseBone(bone, amt, tokens, heads, tails):
- for (key, val, sub) in tokens:
- if key == "head":
- bone.head = (theScale*float(val[0]), theScale*float(val[1]), theScale*float(val[2]))
- elif key == "tail":
- bone.tail = (theScale*float(val[0]), theScale*float(val[1]), theScale*float(val[2]))
- #elif key == 'restrict_select':
- # pass
- elif key == 'hide' and val[0] == 'True':
- name = bone.name
- else:
- defaultKey(key, val, sub, bone)
- return bone
-
-#
-# parsePose (args, tokens):
-#
-
-def parsePose (args, tokens):
- name = args[0]
- ob = loadedData['Object'][name]
- bpy.context.scene.objects.active = ob
- bpy.ops.object.mode_set(mode='POSE')
- pbones = ob.pose.bones
- nGrps = 0
- for (key, val, sub) in tokens:
- if key == 'Posebone':
- parsePoseBone(pbones, ob, val, sub)
- elif key == 'BoneGroup':
- parseBoneGroup(ob.pose, nGrps, val, sub)
- nGrps += 1
- elif key == 'SetProp':
- bone = val[0]
- prop = val[1]
- value = mhxEval(val[2])
- pb = pbones[bone]
- pb[prop] = value
- else:
- defaultKey(key, val, sub, ob.pose)
- bpy.ops.object.mode_set(mode='OBJECT')
- return ob
-
-
-#
-# parsePoseBone(pbones, args, tokens):
-# parseArray(data, exts, args):
-#
-
-def parseBoneGroup(pose, nGrps, args, tokens):
- if verbosity > 2:
- print( "Parsing bonegroup %s" % args )
- name = args[0]
- bpy.ops.pose.group_add()
- bg = pose.bone_groups.active
- loadedData['BoneGroup'][name] = bg
- for (key, val, sub) in tokens:
- defaultKey(key, val, sub, bg)
- return
-
-def parsePoseBone(pbones, ob, args, tokens):
- if invalid(args[1]):
- return
- name = args[0]
- pb = pbones[name]
- amt = ob.data
- amt.bones.active = pb.bone
-
- for (key, val, sub) in tokens:
- if key == 'Constraint':
- amt.bones.active = pb.bone
- cns = parseConstraint(pb.constraints, pb, val, sub)
- elif key == 'bpyops':
- amt.bones.active = pb.bone
- expr = "bpy.ops.%s" % val[0]
- raise MhxError("MHX bug: Must not exec %s" % expr)
- elif key == 'ik_dof':
- parseArray(pb, ["ik_dof_x", "ik_dof_y", "ik_dof_z"], val)
- elif key == 'ik_limit':
- parseArray(pb, ["ik_limit_x", "ik_limit_y", "ik_limit_z"], val)
- elif key == 'ik_max':
- parseArray(pb, ["ik_max_x", "ik_max_y", "ik_max_z"], val)
- elif key == 'ik_min':
- parseArray(pb, ["ik_min_x", "ik_min_y", "ik_min_z"], val)
- elif key == 'ik_stiffness':
- parseArray(pb, ["ik_stiffness_x", "ik_stiffness_y", "ik_stiffness_z"], val)
- elif key == 'hide':
- #bpy.ops.object.mode_set(mode='OBJECT')
- amt.bones[name].hide = mhxEval(val[0])
- #bpy.ops.object.mode_set(mode='POSE')
-
- else:
- defaultKey(key, val, sub, pb)
- return
-
-def parseArray(data, exts, args):
- n = 1
- for ext in exts:
- setattr(data, ext, mhxEval(args[n]))
- n += 1
- return
-
-#
-# parseConstraint(constraints, pb, args, tokens)
-#
-
-def parseConstraint(constraints, pb, args, tokens):
- if invalid(args[2]):
- return None
- if (toggle&T_Opcns and pb):
- print("Active")
- aob = bpy.context.object
- print("ob", aob)
- aamt = aob.data
- print("amt", aamt)
- apose = aob.pose
- print("pose", apose)
- abone = aamt.bones.active
- print("bone", abone)
- print('Num cns before', len(list(constraints)))
- bpy.ops.pose.constraint_add(type=args[1])
- cns = constraints.active
- print('and after', pb, cns, len(list(constraints)))
- else:
- cns = constraints.new(args[1])
-
- cns.name = args[0]
- for (key,val,sub) in tokens:
- if key == 'invert':
- parseArray(cns, ["invert_x", "invert_y", "invert_z"], val)
- elif key == 'use':
- parseArray(cns, ["use_x", "use_y", "use_z"], val)
- elif key == 'pos_lock':
- parseArray(cns, ["lock_location_x", "lock_location_y", "lock_location_z"], val)
- elif key == 'rot_lock':
- parseArray(cns, ["lock_rotation_x", "lock_rotation_y", "lock_rotation_z"], val)
- else:
- defaultKey(key, val, sub, cns, ["use_target"])
-
-
- #print("cns %s done" % cns.name)
- return cns
-
-#
-
-
-# parseCurve (args, tokens):
-# parseSpline(cu, args, tokens):
-# parseBezier(spline, n, args, tokens):
-#
-
-def parseCurve (args, tokens):
- if verbosity > 2:
- print( "Parsing curve %s" % args )
- bpy.ops.object.add(type='CURVE')
- cu = setObjectAndData(args, 'Curve')
-
- for (key, val, sub) in tokens:
- if key == 'Spline':
- parseSpline(cu, val, sub)
- else:
- defaultKey(key, val, sub, cu)
- return
-
-def parseTextCurve (args, tokens):
- if verbosity > 2:
- print( "Parsing text curve %s" % args )
- bpy.ops.object.text_add()
- txt = setObjectAndData(args, 'Text')
-
- for (key, val, sub) in tokens:
- if key == 'Spline':
- parseSpline(txt, val, sub)
- elif key == 'BodyFormat':
- parseCollection(txt.body_format, sub, [])
- elif key == 'EditFormat':
- parseDefault(txt.edit_format, sub, {}, [])
- elif key == 'Font':
- parseDefault(txt.font, sub, {}, [])
- elif key == 'TextBox':
- parseCollection(txt.body_format, sub, [])
- else:
- defaultKey(key, val, sub, txt)
- return
-
-
-def parseSpline(cu, args, tokens):
- typ = args[0]
- spline = cu.splines.new(typ)
- nPointsU = int(args[1])
- nPointsV = int(args[2])
- #spline.point_count_u = nPointsU
- #spline.point_count_v = nPointsV
- if typ == 'BEZIER' or typ == 'BSPLINE':
- spline.bezier_points.add(nPointsU)
- else:
- spline.points.add(nPointsU)
-
- n = 0
- for (key, val, sub) in tokens:
- if key == 'bz':
- parseBezier(spline.bezier_points[n], val, sub)
- n += 1
- elif key == 'pt':
- parsePoint(spline.points[n], val, sub)
- n += 1
- else:
- defaultKey(key, val, sub, spline)
- return
-
-def parseBezier(bez, args, tokens):
- bez.co = mhxEval(args[0])
- bez.co = theScale*bez.co
- bez.handle1 = mhxEval(args[1])
- bez.handle1_type = args[2]
- bez.handle2 = mhxEval(args[3])
- bez.handle2_type = args[4]
- return
-
-def parsePoint(pt, args, tokens):
- pt.co = mhxEval(args[0])
- pt.co = theScale*pt.co
- print(" pt", pt.co)
- return
-
-#
-# parseLattice (args, tokens):
-#
-
-def parseLattice (args, tokens):
- if verbosity > 2:
- print( "Parsing lattice %s" % args )
- bpy.ops.object.add(type='LATTICE')
- lat = setObjectAndData(args, 'Lattice')
- for (key, val, sub) in tokens:
- if key == 'Points':
- parseLatticePoints(val, sub, lat.points)
- else:
- defaultKey(key, val, sub, lat)
- return
-
-def parseLatticePoints(args, tokens, points):
- n = 0
- for (key, val, sub) in tokens:
- if key == 'pt':
- v = points[n].co_deform
- v.x = theScale*float(val[0])
- v.y = theScale*float(val[1])
- v.z = theScale*float(val[2])
- n += 1
- return
-
-#
-# parseLamp (args, tokens):
-# parseFalloffCurve(focu, args, tokens):
-#
-
-def parseLamp (args, tokens):
- if verbosity > 2:
- print( "Parsing lamp %s" % args )
- bpy.ops.object.add(type='LAMP')
- lamp = setObjectAndData(args, 'Lamp')
- for (key, val, sub) in tokens:
- if key == 'FalloffCurve':
- parseFalloffCurve(lamp.falloff_curve, val, sub)
- else:
- defaultKey(key, val, sub, lamp)
- return
-
-def parseFalloffCurve(focu, args, tokens):
- return
-
-#
-# parseGroup (args, tokens):
-# parseGroupObjects(args, tokens, grp):
-#
-
-def parseGroup (args, tokens):
- if verbosity > 2:
- print( "Parsing group %s" % args )
-
- grpName = args[0]
- grp = bpy.data.groups.new(grpName)
- loadedData['Group'][grpName] = grp
- for (key, val, sub) in tokens:
- if key == 'Objects':
- parseGroupObjects(val, sub, grp)
- else:
- defaultKey(key, val, sub, grp)
- return
-
-def parseGroupObjects(args, tokens, grp):
- rig = None
- for (key, val, sub) in tokens:
- if key == 'ob':
- try:
- ob = loadedData['Object'][val[0]]
- grp.objects.link(ob)
- except:
- ob = None
- if ob:
- print(ob, ob.type, rig, ob.parent)
- if ob.type == 'ARMATURE':
- rig = ob
- elif ob.type == 'EMPTY' and rig and not ob.parent:
- ob.parent = rig
- print("SSS")
- return
-
-#
-# parseWorld (args, tokens):
-#
-
-def parseWorld (args, tokens):
- if verbosity > 2:
- print( "Parsing world %s" % args )
- world = bpy.context.scene.world
- for (key, val, sub) in tokens:
- if key == 'Lighting':
- parseDefault(world.lighting, sub, {}, [])
- elif key == 'Mist':
- parseDefault(world.mist, sub, {}, [])
- elif key == 'Stars':
- parseDefault(world.stars, sub, {}, [])
- else:
- defaultKey(key, val, sub, world)
- return
-
-#
-# parseScene (args, tokens):
-# parseRenderSettings(render, args, tokens):
-# parseToolSettings(tool, args, tokens):
-#
-
-def parseScene (args, tokens):
- if verbosity > 2:
- print( "Parsing scene %s" % args )
- scn = bpy.context.scene
- for (key, val, sub) in tokens:
- if key == 'NodeTree':
- scn.use_nodes = True
- parseNodeTree(scn, val, sub)
- elif key == 'GameData':
- parseDefault(scn.game_data, sub, {}, [])
- elif key == 'KeyingSet':
- pass
- #parseDefault(scn.keying_sets, sub, {}, [])
- elif key == 'ObjectBase':
- pass
- #parseDefault(scn.bases, sub, {}, [])
- elif key == 'RenderSettings':
- parseRenderSettings(scn.render, sub, [])
- elif key == 'ToolSettings':
- subkeys = {'ImagePaint' : "image_paint",
- 'Sculpt' : "sculpt",
- 'VertexPaint' : "vertex_paint",
- 'WeightPaint' : "weight_paint" }
- parseDefault(scn.tool_settings, sub, subkeys, [])
- elif key == 'UnitSettings':
- parseDefault(scn.unit_settings, sub, {}, [])
- else:
- defaultKey(key, val, sub, scn)
- return
-
-def parseRenderSettings(render, args, tokens):
- if verbosity > 2:
- print( "Parsing RenderSettings %s" % args )
- for (key, val, sub) in tokens:
- if key == 'Layer':
- pass
- #parseDefault(scn.layers, sub, [])
- else:
- defaultKey(key, val, sub, render)
- return
-
-#
-# parseDefineProperty(args, tokens):
-#
-
-def parseDefineProperty(args, tokens):
- prop = "%sProperty" % (args[1])
- c = '('
- for option in args[2:]:
- prop += "%s %s" % (c, option)
- c = ','
- prop += ')'
- setattr(bpy.types.Object, args[0], prop)
- return
-
-#
-# correctRig(args):
-#
-
-def correctRig(args):
- human = args[0]
- print("CorrectRig %s" % human)
- try:
- ob = loadedData['Object'][human]
- except:
- return
- ob.MhxShapekeyDrivers = (toggle&T_Shapekeys != 0 and toggle&T_ShapeDrivers != 0)
- bpy.context.scene.objects.active = ob
- bpy.ops.object.mode_set(mode='POSE')
- amt = ob.data
- cnslist = []
- for pb in ob.pose.bones:
- pb.bone.select = False
- for cns in pb.constraints:
- if cns.type == 'CHILD_OF':
- cnslist.append((pb, cns, cns.influence))
- cns.influence = 0
-
- for (pb, cns, inf) in cnslist:
- amt.bones.active = pb.bone
- cns.influence = 1
- #print("Childof %s %s %s %.2f" % (amt.name, pb.name, cns.name, inf))
- bpy.ops.constraint.childof_clear_inverse(constraint=cns.name, owner='BONE')
- bpy.ops.constraint.childof_set_inverse(constraint=cns.name, owner='BONE')
- cns.influence = 0
-
- for (pb, cns, inf) in cnslist:
- cns.influence = inf
- return
-
-
-#
-# postProcess(args)
-#
-
-def postProcess(args):
- human = args[0]
- print("Postprocess %s" % human)
- try:
- ob = loadedData['Object'][human]
- except:
- ob = None
- if toggle & T_Diamond == 0 and ob:
- deleteDiamonds(ob)
- return
-
-#
-# deleteDiamonds(ob)
-# Delete joint diamonds in main mesh
-# Invisio = material # 1
-#
-
-def deleteDiamonds(ob):
- bpy.context.scene.objects.active = ob
- if not bpy.context.object:
- return
- print("Delete helper geometry in %s" % bpy.context.object)
- bpy.ops.object.mode_set(mode='EDIT')
- bpy.ops.mesh.select_all(action='DESELECT')
- bpy.ops.object.mode_set(mode='OBJECT')
- me = ob.data
- invisioNum = -1
- for mn,mat in enumerate(me.materials):
- if "Invis" in mat.name:
- invisioNum = mn
- break
- if invisioNum < 0:
- print("WARNING: Nu Invisio material found. Cannot delete helper geometry")
- 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:
- if f.material_index >= invisioNum:
- for vn in f.vertices:
- me.vertices[vn].select = True
- 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:
- bpy.ops.object.mode_set(mode='EDIT')
- print("Do delete")
- bpy.ops.mesh.delete(type='VERT')
- print("Verts deleted")
- bpy.ops.object.mode_set(mode='OBJECT')
- print("Back to object mode")
- return
-
-#
-# defaultKey(ext, args, tokens, data, exclude):
-#
-
-theProperty = None
-
-def propNames(string):
- global alpha7
- #string = string.encode('utf-8', 'strict')
-
- # Alpha 7 compatibility
- if string[0:2] == "&_":
- string = "Mhf"+string[2:]
- alpha7 = True
- elif string[0] == "&":
- string = "Mha"+string[1:]
- alpha7 = True
- elif string[0] == "*":
- string = "Mhs"+string[1:]
- alpha7 = True
- 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
- string[0:3] in ["Mha", "Mhf", "Mhs", "Mhh", "Mhv", "Mhc"]):
- name = string.replace("-","_")
- return name, '["%s"]' % name
- else:
- return string, '["%s"]' % string
-
-
-def defProp(args, var):
- proptype = args[0]
- name = propNames(args[1])[0]
- value = args[2]
- rest = 'description="%s"' % args[3].replace("_", " ")
- if len(args) > 4:
- rest += ", " + args[4]
-
- if name:
- var[name] = value
-
-
-def defNewProp(name, proptype, rest):
- prop = "%sProperty(%s)" % (proptype, rest)
- setattr(bpy.types.Object, name, eval(prop)) # safe: only called from this file
-
-
-def setProperty(args, var):
- global theProperty
- tip = ""
- name = propNames(args[0])[0]
- value = mhxEval(args[1])
- if name:
- var[name] = value
- if len(args) > 2:
- tip = 'description="%s"' % args[2].replace("_", " ")
- theProperty = (name, tip, value)
-
-
-def setPropKeys(args):
- global theProperty
- if theProperty is None:
- return
- (name, tip, value) = theProperty
- if len(args) >= 2 and not isinstance(value, bool):
- if "BOOLEAN" in args[1]:
- value = bool(value)
- else:
- tip = tip + "," + args[1].replace(":", "=").replace('"', " ")
- #expr = "bpy.types.Object.%s = %sProperty(%s)" % (name, proptype, tip)
- if isinstance(value, bool):
- prop = BoolProperty(tip)
- elif isinstance(value, int):
- prop = IntProperty(tip)
- elif isinstance(value, float):
- prop = FloatProperty(tip)
- elif isinstance(value, string):
- prop = StringProperty(tip)
- setattr(bpy.types.Object, name, prop)
- theProperty = None
-
-
-def defaultKey(ext, args, tokens, var, exclude=[]):
- if ext == 'Property':
- return setProperty(args, var)
- elif ext == 'PropKeys':
- return setPropKeys(args)
- elif ext == 'DefProp':
- return defProp(args, var)
-
- if ext == 'bpyops':
- expr = "bpy.ops.%s" % args[0]
- print(expr)
- raise MhxError("MHX bug: calling %s" % expr)
-
- if ext in exclude:
- return
- nvar = getattr(var, ext)
-
- if len(args) == 0:
- MyError("Key length 0: %s" % ext)
-
- rnaType = args[0]
- if rnaType == 'Refer':
- typ = args[1]
- name = args[2]
- setattr(var, ext, loadedData[typ][name])
- return
-
- elif rnaType == 'Struct' or rnaType == 'Define':
- raise MhxError("Struct/Define!")
- typ = args[1]
- name = args[2]
- try:
- data = getattr(var, ext)
- except:
- data = None
- # print("Old structrna", nvar, data)
-
- if data is None:
- try:
- creator = args[3]
- except:
- creator = None
-
- try:
- rna = mhxEval(var, locals())
- data = mhxEval(creator)
- except:
- data = None
- # print("New struct", nvar, typ, data)
-
- if rnaType == 'Define':
- loadedData[typ][name] = data
-
- if data:
- for (key, val, sub) in tokens:
- defaultKey(key, val, sub, data)
- return
-
- elif rnaType == 'PropertyRNA':
- raise MhxError("PropertyRNA!")
- #print("PropertyRNA ", ext, var)
- for (key, val, sub) in tokens:
- defaultKey(ext, val, sub, nvar, [])
- return
-
- elif rnaType == 'Array':
- for n in range(1, len(args)):
- nvar[n-1] = mhxEval(args[n], locals())
- if len(args) > 0:
- nvar[0] = mhxEval(args[1], locals())
- return
-
- elif rnaType == 'List':
- raise MhxError("List!")
- data = []
- for (key, val, sub) in tokens:
- elt = mhxEval(val[1], locals())
- data.append(elt)
- setattr(var, ext, data)
- return
-
- elif rnaType == 'Matrix':
- raise MhxError("Matrix!")
- i = 0
- n = len(tokens)
- for (key, val, sub) in tokens:
- if key == 'row':
- for j in range(n):
- nvar[i][j] = float(val[j])
- i += 1
- return
-
- else:
- try:
- data = loadedData[rnaType][args[1]]
- raise MhxError("From loaded %s %s!" % (rnaType, args[1]))
- except KeyError:
- pass
- data = mhxEval(rnaType, locals())
- setattr(var, ext, data)
-
-
-#
-#
-#
-
-def pushOnTodoList(var, expr):
- print("Unrecognized expression", expr)
- return
- print(dir(mhxEval(var)))
- MyError(
- "Unrecognized expression %s.\n" % expr +
- "This can mean that Blender's python API has changed\n" +
- "since the MHX file was exported. Try to export again\n" +
- "from an up-to-date MakeHuman nightly build.\n" +
- "Alternatively, your Blender version may be obsolete.\n" +
- "Download an up-to-date version from www.graphicall.org")
-
-
-#
-# parseBoolArray(mask):
-#
-
-def parseBoolArray(mask):
- list = []
- for c in mask:
- if c == '0':
- list.append(False)
- else:
- list.append(True)
- return list
-
-# parseMatrix(args, tokens)
-#
-
-def parseMatrix(args, tokens):
- matrix = mathutils.Matrix()
- i = 0
- for (key, val, sub) in tokens:
- if key == 'row':
- matrix[i][0] = float(val[0])
- matrix[i][1] = float(val[1])
- matrix[i][2] = float(val[2])
- matrix[i][3] = float(val[3])
- i += 1
- return matrix
-
-#
-# parseDefault(data, tokens, subkeys, exclude):
-#
-
-def parseDefault(data, tokens, subkeys, exclude):
- for (key, val, sub) in tokens:
- if key in subkeys.keys():
- for (key2, val2, sub2) in sub:
- ndata = getattr(data, subkeys[key])
- defaultKey(key2, val2, sub2, ndata)
- else:
- defaultKey(key, val, sub, data, exclude)
-
-def parseCollection(data, tokens, exclude):
- return
-
-
-#
-# Utilities
-#
-
-#
-# extractBpyType(data):
-#
-"""
-def extractBpyType(data):
- typeSplit = str(type(data)).split("'")
- if typeSplit[0] != '<class ':
- return None
- classSplit = typeSplit[1].split(".")
- if classSplit[0] == 'bpy' and classSplit[1] == 'types':
- return classSplit[2]
- elif classSplit[0] == 'bpy_types':
- return classSplit[1]
- else:
- return None
-
-#
-# Bool(string):
-#
-
-def Bool(string):
- if string == 'True':
- return True
- elif string == 'False':
- return False
- else:
- MyError("Bool %s?" % string)
-"""
-#
-# invalid(condition):
-#
-
-def invalid(condition):
- global rigLeg, rigArm, toggle
- try:
- res = mhxEval(condition)
- #print("%s = %s" % (condition, res))
- return not res
- except:
- #print("%s invalid!" % condition)
- return True
-
-
-
-#
-# clearScene(context):
-#
-
-def clearScene():
- global toggle
- scn = bpy.context.scene
- for n in range(len(scn.layers)):
- scn.layers[n] = True
- return scn
- print("clearScene %s %s" % (toggle & T_Replace, scn))
- if not toggle & T_Replace:
- return scn
-
- for ob in scn.objects:
- if ob.type in ['MESH', 'ARMATURE', 'EMPTY', 'CURVE', 'LATTICE']:
- scn.objects.active = ob
- ob.name = "#" + ob.name
- try:
- bpy.ops.object.mode_set(mode='OBJECT')
- except:
- pass
- scn.objects.unlink(ob)
- del ob
-
- for grp in bpy.data.groups:
- grp.name = "#" + grp.name
- #print(scn.objects)
- return scn
-
-#
-# hideLayers(args):
-# args = sceneLayers sceneHideLayers boneLayers boneHideLayers or nothing
-#
-
-def hideLayers(args):
- if len(args) > 1:
- sceneLayers = int(args[2], 16)
- sceneHideLayers = int(args[3], 16)
- boneLayers = int(args[4], 16)
- # boneHideLayers = int(args[5], 16)
- boneHideLayers = 0
- else:
- sceneLayers = 0x00ff
- sceneHideLayers = 0
- boneLayers = 0
- boneHideLayers = 0
-
- scn = bpy.context.scene
- mask = 1
- hidelayers = []
- for n in range(20):
- scn.layers[n] = True if sceneLayers & mask else False
- if sceneHideLayers & mask:
- hidelayers.append(n)
- mask = mask << 1
-
- for ob in scn.objects:
- for n in hidelayers:
- if ob.layers[n]:
- ob.hide = True
- ob.hide_render = True
-
- if boneLayers:
- human = args[1]
- try:
- ob = loadedData['Object'][human]
- except:
- return
-
- mask = 1
- hidelayers = []
- for n in range(32):
- ob.data.layers[n] = True if boneLayers & mask else False
- if boneHideLayers & mask:
- hidelayers.append(n)
- mask = mask << 1
-
- for b in ob.data.bones:
- for n in hidelayers:
- if b.layers[n]:
- b.hide = True
-
- return
-
-
-#
-# readDefaults():
-# writeDefaults():
-#
-
-ConfigFile = '~/mhx_import.cfg'
-
-
-def readDefaults():
- global toggle, toggleSettings, theScale
- path = os.path.realpath(os.path.expanduser(ConfigFile))
- try:
- fp = open(path, 'rU')
- print('Storing defaults')
- except:
- print('Cannot open "%s" for reading' % path)
- return
- bver = ''
- 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)
- fp.close()
- toggleSettings = toggle
- return
-
-def writeDefaults():
- global toggleSettings, theScale
- path = os.path.realpath(os.path.expanduser(ConfigFile))
- try:
- fp = open(path, 'w')
- print('Storing defaults')
- except:
- print('Cannot open "%s" for writing' % path)
- return
- fp.write("%x %f Graphicall" % (toggleSettings, theScale))
- fp.close()
- return
-
-###################################################################################
-#
-# Postprocessing of rigify rig
-#
-# rigifyMhx(context):
-#
-###################################################################################
-
-class RigifyBone:
- def __init__(self, eb):
- self.name = eb.name
- self.realname = None
- self.realname1 = None
- self.realname2 = None
- self.fkname = None
- self.ikname = None
-
- self.head = eb.head.copy()
- self.tail = eb.tail.copy()
- self.roll = eb.roll
- self.deform = eb.use_deform
- self.parent = None
- self.child = None
- self.connect = False
- self.original = False
- self.extra = (eb.name in ["spine-1"])
-
- def __repr__(self):
- return ("<RigifyBone %s %s %s>" % (self.name, self.realname, self.realname1))
-
-
-def rigifyMhx(context):
- global theArmature
- from collections import OrderedDict
-
- print("Modifying MHX rig to Rigify")
- scn = context.scene
- ob = context.object
- if ob.type == 'ARMATURE':
- rig = ob
- elif ob.type == 'MESH':
- rig = ob.parent
- else:
- rig = None
- if not(rig and rig.type == 'ARMATURE'):
- 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
- 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:
- bone.parent = eb.parent.name
- bones[bone.parent].child = eb.name
- bpy.ops.object.mode_set(mode='OBJECT')
-
- # Create metarig
- try:
- bpy.ops.object.armature_human_metarig_add()
- except AttributeError:
- raise MyError("The Rigify add-on is not enabled. It is found under rigging.")
- bpy.ops.object.location_clear()
- bpy.ops.object.rotation_clear()
- 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
- meta = context.object
- bpy.ops.object.mode_set(mode='EDIT')
- extra = []
- for bone in bones.values():
- try:
- eb = meta.data.edit_bones[bone.name]
- except KeyError:
- eb = None
- if eb:
- eb.head = bone.head
- eb.tail = bone.tail
- eb.roll = bone.roll
- bone.original = True
- elif bone.extra:
- extra.append(bone.name)
- bone.original = True
- eb = meta.data.edit_bones.new(bone.name)
- eb.use_connect = False
- eb.head = bones[bone.parent].tail
- eb.tail = bones[bone.child].head
- eb.roll = bone.roll
- parent = meta.data.edit_bones[bone.parent]
- child = meta.data.edit_bones[bone.child]
- child.parent = eb
- child.head = bones[bone.child].head
- 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
- 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
- bpy.ops.object.mode_set(mode='EDIT')
- layers = 32*[False]
- layers[1] = True
- for bone in bones.values():
- if not bone.original:
- if bone.deform:
- bone.realname = "DEF-" + bone.name
- else:
- bone.realname = "MCH-" + bone.name
- eb = gen.data.edit_bones.new(bone.realname)
- eb.head = bone.head
- eb.tail = bone.tail
- eb.roll = bone.roll
- eb.use_deform = bone.deform
- if bone.parent:
- parent = bones[bone.parent]
- if parent.realname:
- eb.parent = gen.data.edit_bones[parent.realname]
- elif parent.realname1:
- eb.parent = gen.data.edit_bones[parent.realname1]
- else:
- print(bone)
- eb.use_connect = (eb.parent != None and eb.parent.tail == eb.head)
- eb.layers = layers
-
- bpy.ops.object.mode_set(mode='OBJECT')
- for bone in bones.values():
- if not bone.original:
- pb = gen.pose.bones[bone.realname]
- db = rig.pose.bones[bone.name]
- 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
- for key in rig.keys():
- gen[key] = rig[key]
-
- # Copy MHX bone drivers
- if rig.animation_data:
- for fcu1 in rig.animation_data.drivers:
- rna,channel = fcu1.data_path.rsplit(".", 1)
- pb = mhxEval("gen.%s" % rna)
- fcu2 = pb.driver_add(channel, fcu1.array_index)
- 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)
-
- 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)
-
- for mod in ob.modifiers:
- if mod.type == 'ARMATURE' and mod.object == rig:
- mod.object = gen
-
- if group:
- group.objects.link(gen)
-
- # Parent widgets under empty
- empty = bpy.data.objects.new("Widgets", None)
- scn.objects.link(empty)
- empty.layers = 20*[False]
- empty.layers[19] = True
- empty.parent = gen
- for ob in scn.objects:
- if ob.type == 'MESH' and ob.name[0:4] == "WGT-" and not ob.parent:
- ob.parent = empty
- grp.objects.link(ob)
-
- #Clean up
- gen.show_x_ray = True
- gen.data.draw_type = 'STICK'
- gen.MhxRigify = False
- name = rig.name
- scn.objects.unlink(rig)
- del rig
- gen.name = name
- bpy.ops.object.mode_set(mode='POSE')
- theArmature = gen
- print("MHX rig %s successfully rigified" % name)
-
-
-
-def setBoneName(bone, gen):
- fkname = bone.name.replace(".", ".fk.")
- try:
- gen.data.bones[fkname]
- bone.fkname = fkname
- bone.ikname = fkname.replace(".fk.", ".ik")
- except KeyError:
- pass
-
- defname = "DEF-" + bone.name
- try:
- gen.data.bones[defname]
- bone.realname = defname
- return
- except KeyError:
- pass
-
- defname1 = "DEF-" + bone.name + ".01"
- try:
- gen.data.bones[defname1]
- bone.realname1 = defname1
- bone.realname2 = defname1.replace(".01.", ".02.")
- return
- except KeyError:
- pass
-
- defname1 = "DEF-" + bone.name.replace(".", ".01.")
- try:
- gen.data.bones[defname1]
- bone.realname1 = defname1
- bone.realname2 = defname1.replace(".01.", ".02")
- return
- except KeyError:
- pass
-
- try:
- gen.data.edit_bones[bone.name]
- bone.realname = bone.name
- except KeyError:
- pass
-
-
-def fixConstraint(cns1, cns2, gen, bones):
- for key in dir(cns1):
- if ((key[0] != "_") and
- (key not in ["bl_rna", "type", "rna_type", "is_valid", "error_location", "error_rotation"])):
- expr = ("cns2.%s = cns1.%s" % (key, key))
- setattr(cns2, key, getattr(cns1, key))
-
- cns2.target = gen
-
- if cns1.type == 'STRETCH_TO':
- bone = bones[cns1.subtarget]
- if bone.realname:
- cns2.subtarget = bone.realname
- cns2.head_tail = cns1.head_tail
- elif not bone.realname1:
- print(bone)
- halt
- elif cns1.head_tail < 0.5:
- cns2.subtarget = bone.realname1
- cns2.head_tail = 2*cns1.head_tail
- else:
- cns2.subtarget = bone.realname2
- cns2.head_tail = 2*cns1.head_tail-1
-
- elif cns1.type == 'TRANSFORM':
- bone = bones[cns1.subtarget]
- if bone.fkname:
- cns2.subtarget = bone.fkname
- elif bone.ikname:
- cns2.subtarget = bone.ikname
- else:
- cns2.subtarget = bone.realname
-
-
-def copyDriver(fcu1, fcu2, id):
- drv1 = fcu1.driver
- drv2 = fcu2.driver
-
- for var1 in drv1.variables:
- var2 = drv2.variables.new()
- var2.name = var1.name
- var2.type = var1.type
- targ1 = var1.targets[0]
- 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
-
-
-def changeDriverTarget(fcu, id):
- for var in fcu.driver.variables:
- targ = var.targets[0]
- targ.id = id
-
-
-#
-# class OBJECT_OT_RigifyMhxButton(bpy.types.Operator):
-#
-
-class OBJECT_OT_RigifyMhxButton(bpy.types.Operator):
- bl_idname = "mhxrig.rigify_mhx"
- bl_label = "Rigify MHX rig"
- bl_options = {'UNDO'}
-
- def execute(self, context):
- rigifyMhx(context)
- 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):
- return (context.object and context.object.MhxRigify)
-
- def draw(self, context):
- self.layout.operator("mhxrig.rigify_mhx")
- return
-
-###################################################################################
-#
-# Error popup
-#
-###################################################################################
-
-DEBUG = False
-from bpy.props import StringProperty, FloatProperty, EnumProperty, BoolProperty
-
-class ErrorOperator(bpy.types.Operator):
- bl_idname = "mhx.error"
- bl_label = "Error when loading MHX file"
-
- def execute(self, context):
- return {'RUNNING_MODAL'}
-
- def invoke(self, context, event):
- global theErrorLines
- maxlen = 0
- for line in theErrorLines:
- if len(line) > maxlen:
- maxlen = len(line)
- width = 20+5*maxlen
- height = 20+5*len(theErrorLines)
- #self.report({'INFO'}, theMessage)
- wm = context.window_manager
- return wm.invoke_props_dialog(self, width=width, height=height)
-
- def draw(self, context):
- global theErrorLines
- for line in theErrorLines:
- self.layout.label(line)
-
-def MyError(message):
- global theMessage, theErrorLines, theErrorStatus
- theMessage = message
- theErrorLines = message.split('\n')
- theErrorStatus = True
- bpy.ops.mhx.error('INVOKE_DEFAULT')
- raise MhxError(theMessage)
-
-class MhxError(Exception):
- def __init__(self, value):
- self.value = value
- def __str__(self):
- return repr(self.value)
-
-class SuccessOperator(bpy.types.Operator):
- bl_idname = "mhx.success"
- bl_label = "MHX file successfully loaded:"
- message = StringProperty()
-
- def execute(self, context):
- return {'RUNNING_MODAL'}
-
- def invoke(self, context, event):
- wm = context.window_manager
- return wm.invoke_props_dialog(self)
-
- def draw(self, context):
- self.layout.label(self.message + theMessage)
-
-###################################################################################
-#
-# User interface
-#
-###################################################################################
-
-from bpy_extras.io_utils import ImportHelper, ExportHelper
-
-MhxBoolProps = [
- ("enforce", "Enforce version", "Only accept MHX files of correct version", T_EnforceVersion),
- #("crash_safe", "Crash-safe", "Disable features that have caused Blender crashes", T_CrashSafe),
- ("mesh", "Mesh", "Use main mesh", T_Mesh),
- ("proxy", "Proxies", "Use proxies", T_Proxy),
- #("armature", "Armature", "Use armature", T_Armature),
- #("replace", "Replace scene", "Replace scene", T_Replace),
- ("cage", "Cage", "Load mesh deform cage", T_Cage),
- ("clothes", "Clothes", "Include clothes", T_Clothes),
- ("shapekeys", "Shapekeys", "Include shapekeys", T_Shapekeys),
- ("shapedrivers", "Shapekey drivers", "Include shapekey drivers", T_ShapeDrivers),
- #("symm", "Symmetric shapes", "Keep shapekeys symmetric", T_Symm),
- ("diamond", "Helper geometry", "Keep helper geometry", T_Diamond),
- ("rigify", "Rigify", "Create rigify control rig", T_Rigify),
-]
-
-class ImportMhx(bpy.types.Operator, ImportHelper):
- """Import from MHX file format (.mhx)"""
- bl_idname = "import_scene.makehuman_mhx"
- bl_description = 'Import from MHX file format (.mhx)'
- bl_label = "Import MHX"
- bl_space_type = "PROPERTIES"
- bl_region_type = "WINDOW"
- bl_options = {'UNDO'}
-
- 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) # Trusted source: this file.
-
-
- def draw(self, context):
- layout = self.layout
- layout.prop(self, "scale")
- layout.prop(self, "advanced")
- if self.advanced:
- for (prop, name, desc, flag) in MhxBoolProps:
- layout.prop(self, prop)
-
-
- def execute(self, context):
- global toggle, toggleSettings, theScale, MhxBoolProps
- if not self.advanced:
- toggle = DefaultToggle
- else:
- toggle = T_Armature
- for (prop, name, desc, flag) in MhxBoolProps:
- expr = '(%s if self.%s else 0)' % (flag, prop)
- toggle |= eval(expr) # trusted source: this file
- toggleSettings = toggle
- print("execute flags %x" % toggle)
- theScale = self.scale
-
- #filepathname = self.filepath.encode('utf-8', 'strict')
- try:
- if not context.user_preferences.system.use_scripts_auto_execute:
- MyError("Auto Run Python Scripts must be turned on.\nIt is found under\n File > User Preferences > File")
- readMhxFile(self.filepath)
- #bpy.ops.mhx.success('INVOKE_DEFAULT', message = self.filepath)
- except MhxError:
- print("Error when loading MHX file %s:\n" % self.filepath + theMessage)
-
- if self.advanced:
- writeDefaults()
- self.advanced = False
- return {'FINISHED'}
-
-
- def invoke(self, context, event):
- global toggle, theScale, MhxBoolProps
- readDefaults()
- self.scale = theScale
- for (prop, name, desc, flag) in MhxBoolProps:
- setattr(self, prop, mhxEval('(toggle&%s != 0)' % flag))
- context.window_manager.fileselect_add(self)
- return {'RUNNING_MODAL'}
-
-
-###################################################################################
-#
-# Main panel
-#
-###################################################################################
-
-MhxLayers = [
- (( 0, 'Root', 'MhxRoot'),
- ( 1, 'Spine', 'MhxFKSpine')),
- ((10, 'Head', 'MhxHead'),
- ( 8, 'Face', 'MhxFace')),
- (( 9, 'Tweak', 'MhxTweak'),
- (16, 'Clothes', 'MhxClothes')),
- #((17, 'IK Spine', 'MhxIKSpine'),
- #((13, 'Inv FK Spine', 'MhxInvFKSpine')),
- ('Left', 'Right'),
- (( 2, 'IK Arm', 'MhxIKArm'),
- (18, 'IK Arm', 'MhxIKArm')),
- (( 3, 'FK Arm', 'MhxFKArm'),
- (19, 'FK Arm', 'MhxFKArm')),
- (( 4, 'IK Leg', 'MhxIKLeg'),
- (20, 'IK Leg', 'MhxIKLeg')),
- (( 5, 'FK Leg', 'MhxFKLeg'),
- (21, 'FK Leg', 'MhxFKLeg')),
- ((12, 'Extra', 'MhxExtra'),
- (28, 'Extra', 'MhxExtra')),
- (( 6, 'Fingers', 'MhxFingers'),
- (22, 'Fingers', 'MhxFingers')),
- (( 7, 'Links', 'MhxLinks'),
- (23, 'Links', 'MhxLinks')),
- ((11, 'Palm', 'MhxPalm'),
- (27, 'Palm', 'MhxPalm')),
-]
-
-OtherLayers = [
- (( 1, 'Spine', 'MhxFKSpine'),
- ( 10, 'Head', 'MhxHead')),
- (( 9, 'Tweak', 'MhxTweak'),
- ( 8, 'Face', 'MhxFace')),
- ('Left', 'Right'),
- (( 3, 'Arm', 'MhxFKArm'),
- (19, 'Arm', 'MhxFKArm')),
- (( 5, 'Leg', 'MhxFKLeg'),
- (21, 'Leg', 'MhxFKLeg')),
- (( 7, 'Fingers', 'MhxLinks'),
- (23, 'Fingers', 'MhxLinks')),
- ((11, 'Palm', 'MhxPalm'),
- (27, 'Palm', 'MhxPalm')),
-]
-
-
-#
-# class MhxMainPanel(bpy.types.Panel):
-#
-
-class MhxMainPanel(bpy.types.Panel):
- bl_label = "MHX Main v %s" % bl_info["version"]
- 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)
-
- def draw(self, context):
- layout = self.layout
- layout.label("Layers")
- layout.operator("mhx.pose_enable_all_layers")
- layout.operator("mhx.pose_disable_all_layers")
-
- rig = context.object
- if rig.MhxRig == 'MHX':
- layers = MhxLayers
- else:
- layers = OtherLayers
-
- for (left,right) in layers:
- row = layout.row()
- if type(left) == str:
- row.label(left)
- row.label(right)
- else:
- for (n, name, prop) in [left,right]:
- row.prop(rig.data, "layers", index=n, toggle=True, text=name)
-
- layout.separator()
- layout.label("Export/Import MHP")
- layout.operator("mhx.saveas_mhp")
- layout.operator("mhx.load_mhp")
-
-
-class VIEW3D_OT_MhxEnableAllLayersButton(bpy.types.Operator):
- bl_idname = "mhx.pose_enable_all_layers"
- bl_label = "Enable all layers"
- bl_options = {'UNDO'}
-
- def execute(self, context):
- rig,mesh = getMhxRigMesh(context.object)
- for (left,right) in MhxLayers:
- if type(left) != str:
- for (n, name, prop) in [left,right]:
- rig.data.layers[n] = True
- return{'FINISHED'}
-
-
-class VIEW3D_OT_MhxDisableAllLayersButton(bpy.types.Operator):
- bl_idname = "mhx.pose_disable_all_layers"
- bl_label = "Disable all layers"
- bl_options = {'UNDO'}
-
- def execute(self, context):
- rig,mesh = getMhxRigMesh(context.object)
- layers = 32*[False]
- pb = context.active_pose_bone
- if pb:
- for n in range(32):
- if pb.bone.layers[n]:
- layers[n] = True
- break
- else:
- layers[0] = True
- if rig:
- rig.data.layers = layers
- return{'FINISHED'}
-
-
-
-def saveMhpFile(rig, scn, filepath):
- roots = []
- for pb in rig.pose.bones:
- if pb.parent is None:
- roots.append(pb)
-
- (pname, ext) = os.path.splitext(filepath)
- mhppath = pname + ".mhp"
-
- fp = open(mhppath, "w", encoding="utf-8", newline="\n")
- for root in roots:
- writeMhpBones(fp, root, None)
- fp.close()
- print("Mhp file %s saved" % mhppath)
-
-
-def writeMhpBones(fp, pb, log):
- if not isMuscleBone(pb):
- b = pb.bone
- if pb.parent:
- mat = b.matrix_local.inverted() * b.parent.matrix_local * pb.parent.matrix.inverted() * pb.matrix
- else:
- mat = pb.matrix.copy()
- maty = mat[1].copy()
- matz = mat[2].copy()
- mat[1] = matz
- mat[2] = -maty
-
- diff = mat - Matrix()
- nonzero = False
- for i in range(4):
- if abs(diff[i].length) > 5e-3:
- nonzero = True
- break
-
- if nonzero:
- fp.write("%s\tmatrix" % pb.name)
- for i in range(4):
- row = mat[i]
- fp.write("\t%.4f\t%.4f\t%.4f\t%.4f" % (row[0], row[1], row[2], row[3]))
- fp.write("\n")
-
- for child in pb.children:
- writeMhpBones(fp, child, log)
-
-
-def isMuscleBone(pb):
- layers = pb.bone.layers
- if (layers[14] or layers[15] or layers[30] or layers[31]):
- return True
- for cns in pb.constraints:
- if (cns.type == 'STRETCH_TO' or
- cns.type == 'TRANSFORM' or
- cns.type == 'TRACK_TO' or
- cns.type == 'IK' or
- cns.type[0:5] == 'COPY_'):
- return True
- return False
-
-
-def loadMhpFile(rig, scn, filepath):
- unit = Matrix()
- for pb in rig.pose.bones:
- pb.matrix_basis = unit
-
- (pname, ext) = os.path.splitext(filepath)
- mhppath = pname + ".mhp"
-
- fp = open(mhppath, "rU")
- for line in fp:
- words = line.split()
- if len(words) < 4:
- continue
-
- try:
- pb = rig.pose.bones[words[0]]
- except KeyError:
- print("Warning: Did not find bone %s" % words[0])
- continue
-
- if isMuscleBone(pb):
- pass
- elif words[1] == "quat":
- q = Quaternion((float(words[2]), float(words[3]), float(words[4]), float(words[5])))
- mat = q.to_matrix().to_4x4()
- pb.matrix_basis = mat
- elif words[1] == "gquat":
- q = Quaternion((float(words[2]), float(words[3]), float(words[4]), float(words[5])))
- mat = q.to_matrix().to_4x4()
- maty = mat[1].copy()
- matz = mat[2].copy()
- mat[1] = -matz
- mat[2] = maty
- pb.matrix_basis = pb.bone.matrix_local.inverted() * mat
- elif words[1] == "matrix":
- rows = []
- n = 2
- for i in range(4):
- rows.append((float(words[n]), float(words[n+1]), float(words[n+2]), float(words[n+3])))
- n += 4
- mat = Matrix(rows)
- if pb.parent:
- pb.matrix_basis = mat
- else:
- maty = mat[1].copy()
- matz = mat[2].copy()
- mat[1] = -matz
- mat[2] = maty
- pb.matrix_basis = pb.bone.matrix_local.inverted() * mat
- elif words[1] == "scale":
- pass
- else:
- print("WARNING: Unknown line in mcp file:\n%s" % line)
- fp.close()
- print("Mhp file %s loaded" % mhppath)
-
-
-class VIEW3D_OT_LoadMhpButton(bpy.types.Operator):
- bl_idname = "mhx.load_mhp"
- bl_label = "Load MHP File"
- bl_description = "Load a pose in MHP format"
- bl_options = {'UNDO'}
-
- filename_ext = ".mhp"
- filter_glob = StringProperty(default="*.mhp", options={'HIDDEN'})
- filepath = bpy.props.StringProperty(
- name="File Path",
- description="File path used for mhp file",
- maxlen= 1024, default= "")
-
- def execute(self, context):
- loadMhpFile(context.object, context.scene, self.properties.filepath)
- return {'FINISHED'}
-
- def invoke(self, context, event):
- context.window_manager.fileselect_add(self)
- return {'RUNNING_MODAL'}
-
-
-class VIEW3D_OT_SaveasMhpFileButton(bpy.types.Operator, ExportHelper):
- bl_idname = "mhx.saveas_mhp"
- bl_label = "Save MHP File"
- bl_description = "Save current pose in MHP format"
- bl_options = {'UNDO'}
-
- filename_ext = ".mhp"
- filter_glob = StringProperty(default="*.mhp", options={'HIDDEN'})
- filepath = bpy.props.StringProperty(
- name="File Path",
- description="File path used for mhp file",
- maxlen= 1024, default= "")
-
- def execute(self, context):
- saveMhpFile(context.object, context.scene, self.properties.filepath)
- return {'FINISHED'}
-
- def invoke(self, context, event):
- context.window_manager.fileselect_add(self)
- return {'RUNNING_MODAL'}
-
-###################################################################################
-#
-# Lipsync panel
-#
-###################################################################################
-
-#
-# visemes
-#
-
-bodyLanguageVisemes = ({
- 'Rest' : [
- ('MouthWidth_L', 0),
- ('MouthWidth_R', 0),
- ('MouthNarrow_L', 0),
- ('MouthNarrow_R', 0),
- ('LipsPart', 0.6),
- ('UpLipsMidHeight', 0),
- ('LoLipsMidHeight', 0),
- ('LoLipsIn', 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),
- ('LoLipsIn', 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),
- ('LoLipsIn', 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),
- ('LoLipsIn', 0),
- ('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),
- ('LoLipsIn', 0),
- ('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),
- ('LoLipsIn', 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),
- ('LoLipsIn', 0.6),
- ('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),
- ('LoLipsIn', 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),
- ('LoLipsIn', 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),
- ('LoLipsIn', 0),
- ('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),
- ('LoLipsIn', 0),
- ('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),
- ('LoLipsIn', 0),
- ('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),
- ('LoLipsIn', 0),
- ('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),
- ('LoLipsIn', 0),
- ('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),
- ('LoLipsIn', 0),
- ('MouthOpen', -0.2),
- ('TongueBackHeight', 1.0),
- ('TongueHeight', 0),
- ],
-
- 'Blink' : [
- ('UpLidUp_L', 1),
- ('UpLidUp_R', 1),
- ('LoLidDown_L', 1),
- ('LoLidDown_R', 1)
- ],
-
- 'Unblink' : [
- ('UpLidUp_L', 0),
- ('UpLidUp_R', 0),
- ('LoLidDown_L', 0),
- ('LoLidDown_R', 0)
- ],
-})
-
-VisemePanelBones = {
- 'MouthOpen' : ('PJaw', (0,0.25)),
- 'UpLipsMidHeight' : ('PUpLipMid', (0,-0.25)),
- 'LoLipsMidHeight' : ('PLoLipMid', (0,-0.25)),
- 'LoLipsIn': ('PLoLipMid', (-0.25,0)),
- 'MouthWidth_L' : ('PMouth_L', (0.25,0)),
- '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)),
- '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)),
-}
-
-VisemeList = [
- ('Rest', 'Etc', 'AH'),
- ('MBP', 'OO', 'O'),
- ('R', 'FV', 'S'),
- ('SH', 'EE', 'EH'),
- ('TH', 'L', 'G')
-]
-
-#
-# makeVisemes(ob, scn):
-# class VIEW3D_OT_MhxMakeVisemesButton(bpy.types.Operator):
-#
-
-def makeVisemes(ob, scn):
- rig = ob.parent
- if ob.type != 'MESH':
- print("Active object %s is not a mesh" % ob)
- return
- if not ob.data.shape_keys:
- print("%s has no shapekeys" % ob)
- return
- try:
- ob.data.shape_keys.key_blocks["VIS_Rest"]
- print("Visemes already created")
- return
- except KeyError:
- pass
- try:
- ob.data.shape_keys.key_blocks["MouthOpen"]
- except KeyError:
- print("Mesh does not have face shapes")
- return
-
- 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)
- print(vkey.name)
- for n,v in enumerate(verts):
- vkey.data[n].co = v.co
- for (name,value) in shapes:
- if name[-2:] == "_R":
- continue
- skey = ob.data.shape_keys.key_blocks[name]
- factor = 0.75*value
- for n,v in enumerate(verts):
- vkey.data[n].co += factor*(skey.data[n].co - v.co)
- print("Visemes made")
- return
-
-class VIEW3D_OT_MhxMakeVisemesButton(bpy.types.Operator):
- bl_idname = "mhx.make_visemes"
- bl_label = "Generate viseme shapekeys"
- bl_options = {'UNDO'}
-
- def execute(self, context):
- makeVisemes(context.object, context.scene)
- 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",
-})
-
-MagpieVisemes = dict({
- "CONS" : "Etc",
- "AI" : "AH",
- "E" : "EH",
- "O" : "O",
- "UW" : "AH",
- "MBP" : "MBP",
- "L" : "L",
- "FV" : "FV",
- "Sh" : "SH",
-})
-
-#
-# setViseme(context, vis, setKey, frame):
-# setBoneLocation(context, pbone, loc, mirror, setKey, frame):
-# class VIEW3D_OT_MhxVisemeButton(bpy.types.Operator):
-#
-
-def getVisemeSet(context, rig):
- if rig.MhxVisemeSet == "StopStaring":
- return stopStaringVisemes
- elif rig.MhxVisemeSet == "BodyLanguage":
- return bodyLanguageVisemes
- else:
- raise MhxError("Unknown viseme set %s" % visset)
-
-
-def setVisemeAlpha7(context, vis, visemes, setKey, frame):
- (rig, mesh) = getMhxRigMesh(context.object)
- isPanel = False
- isProp = False
- shapekeys = None
- scale = 0.75
- if rig.MhxShapekeyDrivers:
- try:
- scale *= rig.pose.bones['PFace'].bone.length
- isPanel = True
- except:
- isProp = True
- elif mesh:
- shapekeys = mesh.data.shape_keys.key_blocks
-
- for (skey, value) in visemes[vis]:
- if isPanel:
- (b, (x,z)) = VisemePanelBones[skey]
- 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:
- for n in range(3):
- pb.keyframe_insert('location', index=n, frame=frame, group=pb.name)
- elif isProp:
- skey = 'Mhf' + skey
- try:
- prop = rig[skey]
- except:
- continue
- rig[skey] = value*scale
- if setKey or context.tool_settings.use_keyframe_insert_auto:
- 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)
- updatePose(context)
- return
-
-
-class VIEW3D_OT_MhxVisemeButton(bpy.types.Operator):
- bl_idname = 'mhx.pose_viseme'
- bl_label = 'Viseme'
- bl_options = {'UNDO'}
- viseme = StringProperty()
-
- def invoke(self, context, event):
- (rig, mesh) = getMhxRigMesh(context.object)
- visemes = getVisemeSet(context, rig)
- setVisemeAlpha7(context, self.viseme, visemes, False, context.scene.frame_current)
- return{'FINISHED'}
-
-
-def readLipsync(context, filepath, offs, struct):
- (rig, mesh) = getMhxRigMesh(context.object)
- if rig.MhxVisemeSet:
- visemes = getVisemeSet(context, rig)
- else:
- props = getProps(rig, "Mhv")
- visemes = {}
- oldKeys = []
- for prop in props:
- dummy,units = getUnitsFromString("x;"+rig[prop])
- visemes[prop] = units
- props = getProps(rig, "Mhsmouth")
- auto = context.tool_settings.use_keyframe_insert_auto
- auto = True
- factor = rig.MhxStrength
- shapekeys = getMhmShapekeys(rig, mesh)
- context.scene.objects.active = rig
- bpy.ops.object.mode_set(mode='POSE')
-
- fp = open(filepath, "rU")
- for line in fp:
- words= line.split()
- if len(words) < 2:
- continue
- else:
- vis = struct[words[1]]
- frame = int(words[0])+offs
- if rig.MhxVisemeSet:
- setVisemeAlpha7(context, vis, visemes, True, frame)
- else:
- setMhmProps(rig, shapekeys, "Mhsmouth", visemes["Mhv"+vis], factor, auto, frame)
- fp.close()
-
- #setInterpolation(rig)
- updatePose(context)
- print("Lipsync file %s loaded" % filepath)
-
-
-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')
-
- 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'}
-
-
-class MhxLipsyncPanel(bpy.types.Panel):
- bl_label = "MHX Lipsync"
- bl_space_type = "VIEW_3D"
- bl_region_type = "UI"
- bl_options = {'DEFAULT_CLOSED'}
-
- @classmethod
- def poll(cls, context):
- return hasProps(context.object, "Mhv")
-
- def draw(self, context):
- rig,mesh = getMhxRigMesh(context.object)
- if not rig:
- layout.label("No MHX rig found")
- return
- layout = self.layout
-
- if not rig.MhxVisemeSet:
- 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")
- layout.separator()
- n = 0
- for prop in visemes:
- if n % 3 == 0:
- row = layout.row()
- n = 0
- 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:
- for (vis1, vis2, vis3) in VisemeList:
- row = layout.row()
- row.operator("mhx.pose_viseme", text=vis1).viseme = vis1
- row.operator("mhx.pose_viseme", text=vis2).viseme = vis2
- row.operator("mhx.pose_viseme", text=vis3).viseme = vis3
- layout.separator()
- row = layout.row()
- row.operator("mhx.pose_viseme", text="Blink").viseme = 'Blink'
- 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")
- #layout.operator("mhx.update")
-
-#
-# updatePose(context):
-# class VIEW3D_OT_MhxUpdateButton(bpy.types.Operator):
-#
-
-def updatePose(context):
- scn = context.scene
- scn.frame_current = scn.frame_current
- bpy.ops.object.posemode_toggle()
- bpy.ops.object.posemode_toggle()
- return
-
-class VIEW3D_OT_MhxUpdateButton(bpy.types.Operator):
- bl_idname = "mhx.update"
- bl_label = "Update"
-
- def execute(self, context):
- updatePose(context)
- return{'FINISHED'}
-
-
-###################################################################################
-#
-# Expression panels
-#
-###################################################################################
-
-class VIEW3D_OT_MhxResetExpressionsButton(bpy.types.Operator):
- bl_idname = "mhx.pose_reset_expressions"
- bl_label = "Reset expressions"
- bl_options = {'UNDO'}
- prefix = StringProperty()
-
- def execute(self, context):
- rig,mesh = getMhxRigMesh(context.object)
- shapekeys = getMhmShapekeys(rig, mesh)
- clearMhmProps(rig, shapekeys, self.prefix, context.tool_settings.use_keyframe_insert_auto, context.scene.frame_current)
- updatePose(context)
- return{'FINISHED'}
-
-
-class VIEW3D_OT_MhxKeyExpressionsButton(bpy.types.Operator):
- bl_idname = "mhx.pose_key_expressions"
- bl_label = "Key expressions"
- bl_options = {'UNDO'}
- prefix = StringProperty()
-
- def execute(self, context):
- rig,mesh = getMhxRigMesh(context.object)
- props = getProps(rig, self.prefix)
- frame = context.scene.frame_current
- for prop in props:
- rig.keyframe_insert('["%s"]'%prop, frame=frame)
- updatePose(context)
- return{'FINISHED'}
-
-
-class VIEW3D_OT_MhxPinExpressionButton(bpy.types.Operator):
- bl_idname = "mhx.pose_pin_expression"
- bl_label = "Pin"
- bl_options = {'UNDO'}
- data = StringProperty()
-
- def execute(self, context):
- rig,mesh = getMhxRigMesh(context.object)
- 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
- for prop in props:
- old = rig[prop]
- if prop == expression:
- rig[prop] = 1.0
- else:
- rig[prop] = 0.0
- if abs(rig[prop] - old) > 1e-3:
- rig.keyframe_insert('["%s"]'%prop, frame=frame)
- else:
- for prop in props:
- if prop == expression:
- rig[prop] = 1.0
- else:
- rig[prop] = 0.0
- updatePose(context)
- return{'FINISHED'}
-
-
-def getMhmShapekeys(rig, mesh):
- if rig.MhxShapekeyDrivers:
- 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)
- for (prop, value) in units:
- if shapekeys:
- skey = prop[3:].replace("_","-")
- shapekeys[skey].value = factor*value
- if auto:
- shapekeys[skey].keyframe_insert("value", frame=frame)
- else:
- rig[prop] = factor*value
- if auto:
- rig.keyframe_insert('["%s"]'%prop, frame=frame)
-
-
-def clearMhmProps(rig, shapekeys, prefix, auto, frame):
- props = getProps(rig, prefix)
- for prop in props:
- if shapekeys:
- skey = prop[3:].replace("_","-")
- shapekeys[skey].value = 0.0
- if auto:
- shapekeys[skey].keyframe_insert("value", frame=frame)
- else:
- rig[prop] = 0.0
- if auto:
- rig.keyframe_insert('["%s"]'%prop, frame=frame)
-
-
-def getUnitsFromString(string):
- words = string.split(";")
- prefix = words[0]
- units = []
- for word in words[1:]:
- if word == "":
- continue
- unit = word.split(":")
- prop = "Mhs" + unit[0]
- value = float(unit[1])
- units.append((prop, value))
- return prefix,units
-
-
-class VIEW3D_OT_MhxMhmButton(bpy.types.Operator):
- bl_idname = "mhx.pose_mhm"
- bl_label = "Mhm"
- bl_options = {'UNDO'}
- data = StringProperty()
-
- 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)
- setMhmProps(rig, shapekeys, prefix, units, rig.MhxStrength, auto, frame)
- updatePose(context)
- return{'FINISHED'}
-
-
-def getProps(rig, prefix):
- props = []
- for prop in rig.keys():
- if prop.startswith(prefix):
- props.append(prop)
- props.sort()
- return props
-
-
-def hasProps(ob, prefix):
- if ob is None:
- return False
- if ob.type == 'MESH' and ob.parent:
- rig = ob.parent
- elif ob.type == 'ARMATURE':
- rig = ob
- else:
- return False
- for prop in rig.keys():
- if prop.startswith(prefix):
- return True
- return False
-
-
-class MhxExpressionsPanel(bpy.types.Panel):
- bl_label = "MHX Expressions"
- bl_space_type = "VIEW_3D"
- bl_region_type = "UI"
- bl_options = {'DEFAULT_CLOSED'}
-
- @classmethod
- def poll(cls, context):
- return hasProps(context.object, "Mhe")
-
- def draw(self, context):
- layout = self.layout
- rig,mesh = getMhxRigMesh(context.object)
- if not rig:
- layout.label("No MHX rig found")
- return
- exprs = getProps(rig, "Mhe")
- 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")
- layout.separator()
- for prop in exprs:
- layout.operator("mhx.pose_mhm", text=prop[3:]).data="Mhs;"+rig[prop]
-
-
-def drawShapePanel(self, context, prefix, name):
- layout = self.layout
- rig,mesh = getMhxRigMesh(context.object)
- if not rig:
- print("No MHX rig found")
- return
- if not rig.MhxShapekeyDrivers:
- layout.label("No shapekey drivers.")
- layout.label("Set %s values in mesh context instead" % name)
- return
- props = getProps(rig, prefix)
- 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")
-
- layout.separator()
- for prop in props:
- row = layout.split(0.85)
- row.prop(rig, '["%s"]' % prop, text=prop[3:])
- row.operator("mhx.pose_pin_expression", text="", icon='UNPINNED').data = (prefix + ";" + prop)
- return
-
-
-class MhxExpressionUnitsPanel(bpy.types.Panel):
- bl_label = "MHX Expression Tuning"
- bl_space_type = "VIEW_3D"
- bl_region_type = "UI"
- bl_options = {'DEFAULT_CLOSED'}
-
- @classmethod
- def poll(cls, context):
- return hasProps(context.object, "Mhs")
-
- def draw(self, context):
- drawShapePanel(self, context, "Mhs", "expression")
-
-
-class MhxCustomShapePanel(bpy.types.Panel):
- bl_label = "MHX Custom Shapes"
- bl_space_type = "VIEW_3D"
- bl_region_type = "UI"
- bl_options = {'DEFAULT_CLOSED'}
-
- @classmethod
- def poll(cls, context):
- return hasProps(context.object, "Mhc")
-
- def draw(self, context):
- drawShapePanel(self, context, "Mhc", "custom shape")
-
-
-#########################################
-#
-# FK-IK snapping.
-#
-#########################################
-
-def getPoseMatrix(gmat, pb):
- restInv = pb.bone.matrix_local.inverted()
- if pb.parent:
- parInv = pb.parent.matrix.inverted()
- parRest = pb.parent.bone.matrix_local
- return restInv * (parRest * (parInv * gmat))
- else:
- return restInv * gmat
-
-
-def getGlobalMatrix(mat, pb):
- gmat = pb.bone.matrix_local * mat
- if pb.parent:
- parMat = pb.parent.matrix
- parRest = pb.parent.bone.matrix_local
- return parMat * (parRest.inverted() * gmat)
- else:
- return gmat
-
-
-def matchPoseTranslation(pb, src, auto):
- pmat = getPoseMatrix(src.matrix, pb)
- insertLocation(pb, pmat, auto)
-
-
-def insertLocation(pb, mat, auto):
- pb.location = mat.to_translation()
- if auto:
- pb.keyframe_insert("location", group=pb.name)
- bpy.ops.object.mode_set(mode='OBJECT')
- bpy.ops.object.mode_set(mode='POSE')
-
-
-def matchPoseRotation(pb, src, auto):
- pmat = getPoseMatrix(src.matrix, pb)
- insertRotation(pb, pmat, auto)
-
-
-def printMatrix(string,mat):
- print(string)
- for i in range(4):
- print(" %.4g %.4g %.4g %.4g" % tuple(mat[i]))
-
-
-def insertRotation(pb, mat, auto):
- q = mat.to_quaternion()
- if pb.rotation_mode == 'QUATERNION':
- pb.rotation_quaternion = q
- if auto:
- pb.keyframe_insert("rotation_quaternion", group=pb.name)
- else:
- pb.rotation_euler = q.to_euler(pb.rotation_mode)
- if auto:
- pb.keyframe_insert("rotation_euler", group=pb.name)
- bpy.ops.object.mode_set(mode='OBJECT')
- bpy.ops.object.mode_set(mode='POSE')
-
-
-def matchIkLeg(legIk, toeFk, mBall, mToe, mHeel, auto):
- rmat = toeFk.matrix.to_3x3()
- tHead = Vector(toeFk.matrix.col[3][:3])
- ty = rmat.col[1]
- tail = tHead + ty * toeFk.bone.length
-
- try:
- zBall = mBall.matrix.col[3][2]
- except AttributeError:
- return
- zToe = mToe.matrix.col[3][2]
- zHeel = mHeel.matrix.col[3][2]
-
- x = Vector(rmat.col[0])
- y = Vector(rmat.col[1])
- z = Vector(rmat.col[2])
-
- if zHeel > zBall and zHeel > zToe:
- # 1. foot.ik is flat
- if abs(y[2]) > abs(z[2]):
- y = -z
- y[2] = 0
- else:
- # 2. foot.ik starts at heel
- hHead = Vector(mHeel.matrix.col[3][:3])
- y = tail - hHead
-
- y.normalize()
- x -= x.dot(y)*y
- x.normalize()
- z = x.cross(y)
- head = tail - y * legIk.bone.length
-
- # Create matrix
- gmat = Matrix()
- gmat.col[0][:3] = x
- gmat.col[1][:3] = y
- gmat.col[2][:3] = z
- gmat.col[3][:3] = head
- pmat = getPoseMatrix(gmat, legIk)
-
- insertLocation(legIk, pmat, auto)
- insertRotation(legIk, pmat, auto)
-
-
-def matchPoleTarget(pb, above, below, auto):
- x = Vector(above.matrix.col[1][:3])
- y = Vector(below.matrix.col[1][:3])
- p0 = Vector(below.matrix.col[3][:3])
- n = x.cross(y)
- if abs(n.length) > 1e-4:
- z = x - y
- n = n/n.length
- z -= z.dot(n)*n
- p = p0 + z/z.length*3.0
- else:
- p = p0
- gmat = Matrix.Translation(p)
- pmat = getPoseMatrix(gmat, pb)
- insertLocation(pb, pmat, auto)
-
-
-def matchPoseReverse(pb, src, auto):
- gmat = src.matrix
- tail = gmat.col[3] + src.length * gmat.col[1]
- rmat = Matrix((gmat.col[0], -gmat.col[1], -gmat.col[2], tail))
- rmat.transpose()
- pmat = getPoseMatrix(rmat, pb)
- pb.matrix_basis = pmat
- insertRotation(pb, pmat, auto)
-
-
-def matchPoseScale(pb, src, auto):
- pmat = getPoseMatrix(src.matrix, pb)
- pb.scale = pmat.to_scale()
- if auto:
- pb.keyframe_insert("scale", group=pb.name)
- bpy.ops.object.mode_set(mode='OBJECT')
- bpy.ops.object.mode_set(mode='POSE')
-
-
-def snapFkArm(context, data):
- rig = context.object
- prop,old,suffix = setSnapProp(rig, data, 1.0, context, False)
- auto = context.scene.tool_settings.use_keyframe_insert_auto
-
- print("Snap FK Arm%s" % suffix)
- snapFk,cnsFk = getSnapBones(rig, "ArmFK", suffix)
- (uparmFk, loarmFk, handFk) = snapFk
- muteConstraints(cnsFk, True)
- snapIk,cnsIk = getSnapBones(rig, "ArmIK", suffix)
- (uparmIk, loarmIk, elbow, elbowPt, handIk) = snapIk
-
- matchPoseRotation(uparmFk, uparmIk, auto)
- matchPoseScale(uparmFk, uparmIk, auto)
-
- matchPoseRotation(loarmFk, loarmIk, auto)
- matchPoseScale(loarmFk, loarmIk, auto)
-
- restoreSnapProp(rig, prop, old, context)
-
- try:
- matchHand = rig["MhaHandFollowsWrist" + suffix]
- except KeyError:
- matchHand = True
- if matchHand:
- matchPoseRotation(handFk, handIk, auto)
- matchPoseScale(handFk, handIk, auto)
-
- #muteConstraints(cnsFk, False)
- return
-
-
-def snapIkArm(context, data):
- rig = context.object
- prop,old,suffix = setSnapProp(rig, data, 0.0, context, True)
- auto = context.scene.tool_settings.use_keyframe_insert_auto
-
- print("Snap IK Arm%s" % suffix)
- snapIk,cnsIk = getSnapBones(rig, "ArmIK", suffix)
- (uparmIk, loarmIk, elbow, elbowPt, handIk) = snapIk
- snapFk,cnsFk = getSnapBones(rig, "ArmFK", suffix)
- (uparmFk, loarmFk, handFk) = snapFk
- muteConstraints(cnsIk, True)
-
- matchPoseTranslation(handIk, handFk, auto)
- matchPoseRotation(handIk, handFk, auto)
-
- matchPoleTarget(elbowPt, uparmFk, loarmFk, auto)
-
- #matchPoseRotation(uparmIk, uparmFk, auto)
- #matchPoseRotation(loarmIk, loarmFk, auto)
-
- restoreSnapProp(rig, prop, old, context)
- #muteConstraints(cnsIk, False)
- return
-
-
-def snapFkLeg(context, data):
- rig = context.object
- prop,old,suffix = setSnapProp(rig, data, 1.0, context, False)
- auto = context.scene.tool_settings.use_keyframe_insert_auto
-
- print("Snap FK Leg%s" % suffix)
- snap,_ = getSnapBones(rig, "Leg", suffix)
- (upleg, loleg, foot, toe) = snap
- snapIk,cnsIk = getSnapBones(rig, "LegIK", suffix)
- (uplegIk, lolegIk, kneePt, ankleIk, legIk, footRev, toeRev, mBall, mToe, mHeel) = snapIk
- snapFk,cnsFk = getSnapBones(rig, "LegFK", suffix)
- (uplegFk, lolegFk, footFk, toeFk) = snapFk
- muteConstraints(cnsFk, True)
-
- matchPoseRotation(uplegFk, uplegIk, auto)
- matchPoseScale(uplegFk, uplegIk, auto)
-
- matchPoseRotation(lolegFk, lolegIk, auto)
- matchPoseScale(lolegFk, lolegIk, auto)
-
- restoreSnapProp(rig, prop, old, context)
-
- if not rig["MhaLegIkToAnkle" + suffix]:
- matchPoseReverse(footFk, footRev, auto)
- matchPoseReverse(toeFk, toeRev, auto)
-
- #muteConstraints(cnsFk, False)
- return
-
-
-def snapIkLeg(context, data):
- rig = context.object
- scn = context.scene
- prop,old,suffix = setSnapProp(rig, data, 0.0, context, True)
- auto = scn.tool_settings.use_keyframe_insert_auto
-
- print("Snap IK Leg%s" % suffix)
- snapIk,cnsIk = getSnapBones(rig, "LegIK", suffix)
- (uplegIk, lolegIk, kneePt, ankleIk, legIk, footRev, toeRev, mBall, mToe, mHeel) = snapIk
- snapFk,cnsFk = getSnapBones(rig, "LegFK", suffix)
- (uplegFk, lolegFk, footFk, toeFk) = snapFk
- muteConstraints(cnsIk, True)
-
- legIkToAnkle = rig["MhaLegIkToAnkle" + suffix]
- if legIkToAnkle:
- matchPoseTranslation(ankleIk, footFk, auto)
-
- #matchPoseTranslation(legIk, legFk, auto)
- #matchPoseRotation(legIk, legFk, auto)
- matchIkLeg(legIk, toeFk, mBall, mToe, mHeel, auto)
-
- matchPoseReverse(toeRev, toeFk, auto)
- matchPoseReverse(footRev, footFk, auto)
-
- matchPoleTarget(kneePt, uplegFk, lolegFk, auto)
-
- #matchPoseRotation(uplegIk, uplegFk, auto)
- #matchPoseRotation(lolegIk, lolegFk, auto)
-
- if not legIkToAnkle:
- matchPoseTranslation(ankleIk, footFk, auto)
-
- restoreSnapProp(rig, prop, old, context)
- #muteConstraints(cnsIk, False)
- return
-
-
-SnapBonesAlpha8 = {
- "Arm" : ["upper_arm", "forearm", "hand"],
- "ArmFK" : ["upper_arm.fk", "forearm.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", "foot.fk", "toe.fk"],
- "LegIK" : ["thigh.ik", "shin.ik", "knee.pt.ik", "ankle.ik", "foot.ik", "foot.rev", "toe.rev", "ball.marker", "toe.marker", "heel.marker"],
-}
-
-
-def getSnapBones(rig, key, suffix):
- try:
- pb = rig.pose.bones["UpLeg_L"]
- except KeyError:
- pb = None
-
- if pb is not None:
- raise NameError("MakeHuman alpha 7 not supported after Blender 2.68")
-
- try:
- rig.pose.bones["thigh.fk.L"]
- names = SnapBonesAlpha8[key]
- suffix = '.' + suffix[1:]
- except KeyError:
- names = None
-
- if not names:
- raise NameError("Not an mhx armature")
-
- pbones = []
- constraints = []
- for name in names:
- if name:
- try:
- pb = rig.pose.bones[name+suffix]
- except KeyError:
- pb = None
- pbones.append(pb)
- if pb is not None:
- 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
-
-
-def muteConstraints(constraints, value):
- for cns in constraints:
- cns.mute = value
-
-
-class VIEW3D_OT_MhxSnapFk2IkButton(bpy.types.Operator):
- bl_idname = "mhx.snap_fk_ik"
- bl_label = "Snap FK"
- bl_options = {'UNDO'}
- data = StringProperty()
-
- def execute(self, context):
- bpy.ops.object.mode_set(mode='POSE')
- rig = context.object
- if rig.MhxSnapExact:
- rig["MhaRotationLimits"] = 0.0
- if self.data[:6] == "MhaArm":
- snapFkArm(context, self.data)
- elif self.data[:6] == "MhaLeg":
- snapFkLeg(context, self.data)
- return{'FINISHED'}
-
-
-class VIEW3D_OT_MhxSnapIk2FkButton(bpy.types.Operator):
- bl_idname = "mhx.snap_ik_fk"
- bl_label = "Snap IK"
- bl_options = {'UNDO'}
- data = StringProperty()
-
- def execute(self, context):
- bpy.ops.object.mode_set(mode='POSE')
- rig = context.object
- if rig.MhxSnapExact:
- rig["MhaRotationLimits"] = 0.0
- if self.data[:6] == "MhaArm":
- snapIkArm(context, self.data)
- elif self.data[:6] == "MhaLeg":
- snapIkLeg(context, self.data)
- return{'FINISHED'}
-
-
-def setSnapProp(rig, data, value, context, isIk):
- words = data.split()
- prop = words[0]
- oldValue = rig[prop]
- rig[prop] = value
- ik = int(words[1])
- fk = int(words[2])
- extra = int(words[3])
- oldIk = rig.data.layers[ik]
- oldFk = rig.data.layers[fk]
- oldExtra = rig.data.layers[extra]
- rig.data.layers[ik] = True
- rig.data.layers[fk] = True
- rig.data.layers[extra] = True
- updatePose(context)
- if isIk:
- oldValue = 1.0
- oldIk = True
- oldFk = False
- else:
- oldValue = 0.0
- oldIk = False
- oldFk = True
- oldExtra = False
- return (prop, (oldValue, ik, fk, extra, oldIk, oldFk, oldExtra), prop[-2:])
-
-
-def restoreSnapProp(rig, prop, old, context):
- updatePose(context)
- (oldValue, ik, fk, extra, oldIk, oldFk, oldExtra) = old
- rig[prop] = oldValue
- rig.data.layers[ik] = oldIk
- rig.data.layers[fk] = oldFk
- rig.data.layers[extra] = oldExtra
- updatePose(context)
- return
-
-
-class VIEW3D_OT_MhxToggleFkIkButton(bpy.types.Operator):
- bl_idname = "mhx.toggle_fk_ik"
- bl_label = "FK - IK"
- bl_options = {'UNDO'}
- toggle = StringProperty()
-
- def execute(self, context):
- words = self.toggle.split()
- rig = context.object
- prop = words[0]
- value = float(words[1])
- onLayer = int(words[2])
- offLayer = int(words[3])
- rig.data.layers[onLayer] = True
- rig.data.layers[offLayer] = False
- 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)
- updatePose(context)
- return{'FINISHED'}
-
-#
-# MHX FK/IK Switch panel
-#
-
-class MhxFKIKPanel(bpy.types.Panel):
- bl_label = "MHX FK/IK Switch"
- 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
-
- row = layout.row()
- row.label("")
- row.label("Left")
- row.label("Right")
-
- layout.label("FK/IK switch")
- row = layout.row()
- row.label("Arm")
- self.toggleButton(row, rig, "MhaArmIk_L", " 3", " 2")
- self.toggleButton(row, rig, "MhaArmIk_R", " 19", " 18")
- row = layout.row()
- 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")
- row.prop(rig, '["MhaArmIk_L"]', text="")
- row.prop(rig, '["MhaArmIk_R"]', text="")
- row = layout.row()
- row.label("Leg")
- row.prop(rig, '["MhaLegIk_L"]', text="")
- row.prop(rig, '["MhaLegIk_R"]', text="")
-
- try:
- ok = (rig["MhxVersion"] >= 12)
- except:
- ok = False
- 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")
- row.operator("mhx.snap_fk_ik", text="Snap L FK Arm").data = "MhaArmIk_L 2 3 12"
- row.operator("mhx.snap_fk_ik", text="Snap R FK Arm").data = "MhaArmIk_R 18 19 28"
- row = layout.row()
- row.label("IK Arm")
- row.operator("mhx.snap_ik_fk", text="Snap L IK Arm").data = "MhaArmIk_L 2 3 12"
- row.operator("mhx.snap_ik_fk", text="Snap R IK Arm").data = "MhaArmIk_R 18 19 28"
-
- layout.label("Snap Leg bones")
- row = layout.row()
- row.label("FK Leg")
- row.operator("mhx.snap_fk_ik", text="Snap L FK Leg").data = "MhaLegIk_L 4 5 12"
- row.operator("mhx.snap_fk_ik", text="Snap R FK Leg").data = "MhaLegIk_R 20 21 28"
- row = layout.row()
- row.label("IK Leg")
- row.operator("mhx.snap_ik_fk", text="Snap L IK Leg").data = "MhaLegIk_L 4 5 12"
- row.operator("mhx.snap_ik_fk", text="Snap R IK Leg").data = "MhaLegIk_R 20 21 28"
-
-
- def toggleButton(self, row, rig, prop, fk, ik):
- if rig[prop] > 0.5:
- 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):
-#
-
-class MhxDriversPanel(bpy.types.Panel):
- bl_label = "MHX Drivers"
- 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):
- lrProps = []
- props = []
- lrFaceProps = []
- faceProps = []
- plist = list(context.object.keys())
- plist.sort()
- for prop in plist:
- if prop[0:3] == 'Mha':
- if prop[-2:] == '_L':
- lrProps.append(prop[:-2])
- elif prop[-2:] != '_R':
- props.append(prop)
- elif prop[0:3] == 'Mhf':
- if prop[-2:] == '_L':
- lrFaceProps.append(prop[:-2])
- elif prop[-2:] != '_R':
- faceProps.append(prop)
-
- ob = context.object
- layout = self.layout
- for prop in props:
- layout.prop(ob, '["%s"]' % prop, text=prop[3:])
-
- layout.separator()
- row = layout.row()
- row.label("Left")
- row.label("Right")
- for prop in lrProps:
- row = layout.row()
- row.prop(ob, '["%s"]' % (prop+"_L"), text=prop[3:])
- row.prop(ob, '["%s"]' % (prop+"_R"), text=prop[3:])
-
- if faceProps:
- layout.separator()
- layout.label("Face shapes")
- for prop in faceProps:
- layout.prop(ob, '["%s"]' % prop, text=prop[3:])
-
- layout.separator()
- row = layout.row()
- row.label("Left")
- row.label("Right")
- for prop in lrFaceProps:
- 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):
-#
-
-class MhxVisibilityPanel(bpy.types.Panel):
- bl_label = "MHX Visibility"
- 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)
-
- def draw(self, context):
- ob = context.object
- layout = self.layout
- props = list(ob.keys())
- props.sort()
- for prop in props:
- if prop[0:3] == "Mhh":
- layout.prop(ob, '["%s"]' % prop, text="Hide %s" % prop[3:])
- layout.separator()
- layout.operator("mhx.update_textures")
- layout.separator()
- layout.operator("mhx.add_hiders")
- layout.operator("mhx.remove_hiders")
- return
-
-class VIEW3D_OT_MhxUpdateTexturesButton(bpy.types.Operator):
- bl_idname = "mhx.update_textures"
- bl_label = "Update"
- bl_options = {'UNDO'}
-
- def execute(self, context):
- scn = context.scene
- for mat in bpy.data.materials:
- if mat.animation_data:
- try:
- mat["MhxDriven"]
- except:
- continue
- for driver in mat.animation_data.drivers:
- prop = mat.path_resolve(driver.data_path)
- value = driver.evaluate(scn.frame_current)
- prop[driver.array_index] = value
- return{'FINISHED'}
-
-class VIEW3D_OT_MhxAddHidersButton(bpy.types.Operator):
- bl_idname = "mhx.add_hiders"
- bl_label = "Add Hide Property"
- bl_options = {'UNDO'}
-
- def execute(self, context):
- rig = context.object
- for ob in context.scene.objects:
- if ob.select and ob != rig:
- prop = "Mhh%s" % ob.name
- defNewProp(prop, "Bool", "default=False")
- rig[prop] = False
- addHider(ob, "hide", rig, prop)
- addHider(ob, "hide_render", rig, prop)
- return{'FINISHED'}
-
-def addHider(ob, attr, rig, prop):
- fcu = ob.driver_add(attr)
- drv = fcu.driver
- drv.type = 'SCRIPTED'
- drv.expression = "x"
- drv.show_debug_info = True
- var = drv.variables.new()
- var.name = "x"
- targ = var.targets[0]
- targ.id = rig
- targ.data_path = '["%s"]' % prop
- return
-
-class VIEW3D_OT_MhxRemoveHidersButton(bpy.types.Operator):
- bl_idname = "mhx.remove_hiders"
- bl_label = "Remove Hide Property"
- bl_options = {'UNDO'}
-
- def execute(self, context):
- rig = context.object
- for ob in context.scene.objects:
- if ob.select and ob != rig:
- ob.driver_remove("hide")
- ob.driver_remove("hide_render")
- del rig["Mhh%s" % ob.name]
- return{'FINISHED'}
-
-###################################################################################
-#
-# Common functions
-#
-###################################################################################
-#
-# getMhxRigMesh(ob):
-#
-
-def pollMhx(ob):
- if not ob:
- return False
- elif ob.type == 'ARMATURE':
- return ob.MhxRig
- elif ob.type == 'MESH':
- par = ob.parent
- return (par and (par.type == 'ARMATURE') and par.MhxRig)
- else:
- return False
-
-def getMhxRigMesh(ob):
- if ob.type == 'ARMATURE':
- for mesh in ob.children:
- if mesh.MhxMesh and ob.MhxRig:
- return (ob, mesh)
- return (ob, None)
- elif ob.type == 'MESH':
- par = ob.parent
- if (par and par.type == 'ARMATURE' and par.MhxRig):
- if ob.MhxMesh:
- return (par, ob)
- else:
- return (par, None)
- else:
- return (None, None)
- return (None, None)
-
-
-#
-# setInterpolation(rig):
-#
-
-def setInterpolation(rig):
- if not rig.animation_data:
- return
- act = rig.animation_data.action
- if not act:
- return
- for fcu in act.fcurves:
- for pt in fcu.keyframe_points:
- pt.interpolation = 'LINEAR'
- fcu.extrapolation = 'CONSTANT'
- return
-
-###################################################################################
-#
-# initialize and register
-#
-###################################################################################
-
-def menu_func(self, context):
- self.layout.operator(ImportMhx.bl_idname, text="MakeHuman (.mhx)...")
-
-def register():
- bpy.types.Object.MhxVersionStr = StringProperty(name="Version", default="", maxlen=128)
- bpy.types.Object.MhAlpha8 = BoolProperty(default=True)
- bpy.types.Object.MhxMesh = BoolProperty(default=False)
- bpy.types.Object.MhxRig = StringProperty(default="")
- bpy.types.Object.MhxVisemeSet = StringProperty(default="")
- bpy.types.Object.MhxRigify = BoolProperty(default=False)
- bpy.types.Object.MhxSnapExact = BoolProperty(default=False)
- bpy.types.Object.MhxShapekeyDrivers = BoolProperty(default=True)
- bpy.types.Object.MhxStrength = FloatProperty(
- name = "Expression strength",
- description = "Multiply expression with this factor",
- default=1.0, min=-1.0, max=2.0
- )
- bpy.utils.register_module(__name__)
- bpy.types.INFO_MT_file_import.append(menu_func)
-
-def unregister():
- try:
- bpy.utils.unregister_module(__name__)
- except:
- pass
- try:
- bpy.types.INFO_MT_file_import.remove(menu_func)
- except:
- pass
-
-if __name__ == "__main__":
- unregister()
- register()
-
-
-
-
-