-
Thomas Dinges authoredThomas Dinges authored
import_scene_mhx.py 51.95 KiB
"""
**Project Name:** MakeHuman
**Product Home Page:** http://www.makehuman.org/
**Code Home Page:** http://code.google.com/p/makehuman/
**Authors:** Thomas Larsson
**Copyright(c):** MakeHuman Team 2001-2010
**Licensing:** GPL3 (see also http://sites.google.com/site/makehumandocs/licensing)
**Coding Standards:** See http://sites.google.com/site/makehumandocs/developers-guide
Abstract
MHX (MakeHuman eXchange format) importer for Blender 2.5x.
Version 0.9
"""
bl_addon_info = {
'name': 'Import MakeHuman (.mhx)',
'author': 'Thomas Larsson',
'version': '0.9, Make Human Alpha 5',
'blender': (2, 5, 3),
'location': 'File > Import',
'description': 'Import files in the MakeHuman eXchange format (.mhx)',
'wiki_url': 'http://wiki.blender.org/index.php/Extensions:2.5/Py/' \
'Scripts/File_I-O/Make_Human',
'category': 'Import/Export'}
"""
Place this file in the .blender/scripts/addons dir
You have to activated the script in the "Add-Ons" tab (user preferences).
Access from the File > Import menu.
"""
#
#
#
import bpy
import os
import time
import mathutils
from mathutils import *
import geometry
import string
MAJOR_VERSION = 0
MINOR_VERSION = 9
MHX249 = False
Blender24 = False
Blender25 = True
TexDir = "~/makehuman/exports"
#
#
#
theScale = 1.0
useMesh = 1
doSmash = 1
verbosity = 2
warnedTextureDir = False
warnedVersion = False
true = True
false = False
Epsilon = 1e-6
nErrors = 0
theTempDatum = None
todo = []
#
# toggle flags
#
T_ArmIK = 0x01
T_LegIK = 0x02
T_Replace = 0x20
T_Face = 0x40
T_Shape = 0x80
T_Mesh = 0x100
T_Armature = 0x200
T_Proxy = 0x400
T_Panel = 0x800
T_Rigify = 0x1000
T_Preset = 0x2000
T_Symm = 0x4000
T_MHX = 0x8000
toggle = T_Replace + T_ArmIK + T_LegIK + T_Mesh + T_Armature + T_Face
#
# setFlagsAndFloats(rigFlags):
#
# Global floats
fLegIK = 0.0
fArmIK = 0.0
fFingerPanel = 0.0
fFingerIK = 0.0
fFingerCurl = 0.0
# rigLeg and rigArm flags
T_Toes = 0x0001
T_GoboFoot = 0x0002
T_InvFoot = 0x0004
T_FingerPanel = 0x100
T_FingerCurl = 0x0200
T_FingerIK = 0x0400
T_LocalFKIK = 0x8000
rigLeg = 0
rigArm = 0
def setFlagsAndFloats(rigFlags):
global toggle, rigLeg, rigArm
(footRig, fingerRig) = rigFlags
rigLeg = 0
rigArm = 0
if footRig == 'Reverse foot': rigLeg |= T_InvFoot
elif footRig == 'Gobo': rigLeg |= T_GoboFoot
if fingerRig == 'Panel': rigArm |= T_FingerPanel
elif fingerRig == 'IK': rigArm |= T_FingerIK
elif fingerRig == 'Curl': rigArm |= T_FingerCurl
toggle |= T_Panel
# Global floats, used as influences
global fFingerCurl, fLegIK, fArmIK, fFingerIK
fFingerCurl = 1.0 if rigArm&T_FingerCurl else 0.0
fLegIK = 1.0 if toggle&T_LegIK else 0.0
fArmIK = 1.0 if toggle&T_ArmIK else 0.0
fFingerIK = 1.0 if rigArm&T_FingerIK else 0.0
return
#
# Dictionaries
#
loadedData = {
'NONE' : {},
'Object' : {},
'Mesh' : {},
'Armature' : {},
'Lamp' : {},
'Camera' : {},
'Lattice' : {},
'Curve' : {},
'Material' : {},
'Image' : {},
'MaterialTextureSlot' : {},
'Texture' : {},
'Bone' : {},
'BoneGroup' : {},
'Rigify' : {},
'Action' : {},
'Group' : {},
'MeshTextureFaceLayer' : {},
'MeshColorLayer' : {},
'VertexGroup' : {},
'ShapeKey' : {},
'ParticleSystem' : {},
'ObjectConstraints' : {},
'ObjectModifiers' : {},
'MaterialSlot' : {},
}
Plural = {
'Object' : 'objects',
'Mesh' : 'meshes',
'Lattice' : 'lattices',
'Curve' : 'curves',
'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',
}
#
# Creators
#
def uvtexCreator(me, name):
print("uvtexCreator", me, name)
me.add_uv_texture()
uvtex = me.uv_textures[-1]
uvtex.name = name
return uvtex
def vertcolCreator(me, name):
print("vertcolCreator", me, name)
me.add_vertex_color()
vcol = me.vertex_colors[-1]
vcol.name = name
return vcol
#
# loadMhx(filePath, context, flags):
#
def loadMhx(filePath, context, flags):
global toggle
toggle = flags
readMhxFile(filePath)
return
#
# readMhxFile(filePath, rigFlags):
#
def readMhxFile(filePath, rigFlags):
global todo, nErrors
fileName = os.path.expanduser(filePath)
(shortName, ext) = os.path.splitext(fileName)
if ext != ".mhx":
print("Error: Not a mhx file: " + fileName)
return
print( "Opening MHX file "+ fileName )
time1 = time.clock()
ignore = False
stack = []
tokens = []
key = "toplevel"
level = 0
nErrors = 0
setFlagsAndFloats(rigFlags)
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] == '#':
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" % lineNo )
print( line )
dummy = 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:
raise NameError("Tokenizer out of kilter %d" % level)
clearScene()
print( "Parsing" )
parse(tokens)
for (expr, glbals, lcals) in todo:
try:
# print("Doing %s" % expr)
exec(expr, glbals, lcals)
except:
msg = "Failed: "+expr
print( msg )
nErrors += 1
#raise NameError(msg)
print("Postprocess")
postProcess()
print("HideLayers")
hideLayers()
time2 = time.clock()
print("toggle = %x" % toggle)
msg = "File %s loaded in %g s" % (fileName, time2-time1)
if nErrors:
msg += " but there where %d errors. " % (nErrors)
print(msg)
return # loadMhx
#
# getObject(name, var, glbals, lcals):
#
def getObject(name, var, glbals, lcals):
try:
ob = loadedData['Object'][name]
except:
if name != "None":
expr = "%s = loadedData['Object'][name]" % var
print("Todo ", expr)
todo.append((expr, glbals, lcals))
ob = None
return ob
#
# parse(tokens):
#
ifResult = False
def parse(tokens):
global warnedVersion, MHX249, ifResult
for (key, val, sub) in tokens:
# print("Parse %s" % key)
data = None
if key == 'MHX':
if int(val[0]) != MAJOR_VERSION and int(val[1]) != MINOR_VERSION and not warnedVersion:
print("Warning: \nThis file was created with another version of MHX\n")
warnedVersion = True
elif key == 'MHX249':
MHX249 = eval(val[0])
print("Blender 2.49 compatibility mode is %s\n" % MHX249)
elif key == 'if':
try:
ifResult = eval(val[0])
except:
ifResult = False
if ifResult:
parse(sub)
elif key == 'elif':
if not ifResult:
try:
ifResult = eval(val[0])
except:
ifResult = False
if ifResult:
parse(sub)
elif key == 'else':
if not ifResult:
parse(sub)
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)
raise NameError(msg)
elif key == "Object":
parseObject(val, sub)
elif key == "Mesh":
data = parseMesh(val, sub)
elif key == "Curve":
data = parseCurve(val, sub)
elif key == "Lattice":
data = parseLattice(val, sub)
elif key == "Group":
data = parseGroup(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 == "Process":
parseProcess(val, sub)
elif key == 'AnimationData':
try:
ob = loadedData['Object'][val[0]]
except:
ob = None
if ob:
bpy.context.scene.objects.active = ob
parseAnimationData(ob, sub)
elif key == 'ShapeKeys':
try:
ob = loadedData['Object'][val[0]]
except:
ob = None
if ob:
bpy.context.scene.objects.active = ob
parseShapeKeys(ob, ob.data, val, sub)
else:
data = parseDefaultType(key, val, sub)
if data and key != 'Mesh':
print( data )
return
#
# parseDefaultType(typ, args, tokens):
#
def parseDefaultType(typ, args, tokens):
global todo
name = args[0]
data = None
expr = "bpy.data.%s.new('%s')" % (Plural[typ], name)
print(expr)
data = eval(expr)
print(" ok", data)
bpyType = typ.capitalize()
print(bpyType, name, data)
loadedData[bpyType][name] = data
if data == None:
return None
for (key, val, sub) in tokens:
#print("%s %s" % (key, val))
defaultKey(key, val, sub, 'data', [], globals(), locals())
print("Done ", 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 == 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', [], globals(), locals())
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 = eval(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]
# print(expr, channel, index)
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)
#raise NameError("kp", fcu, n, len(fcu.keyframe_points), val)
else:
defaultKey(key, val, sub, 'fcu', [], globals(), locals())
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, tokens):
# parseDriver(drv, args, tokens):
# parseDriverVariable(var, args, tokens):
#
def parseAnimationData(rna, tokens):
if 0 and toggle & T_MHX:
return
if rna.animation_data == 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', [], globals(), locals())
return adata
def parseAnimDataFCurve(adata, rna, args, tokens):
if invalid(args[2]):
return
dataPath = args[0]
index = int(args[1])
# print("parseAnimDataFCurve", adata, dataPath, index)
for (key, val, sub) in tokens:
if key == 'Driver':
fcu = parseDriver(adata, dataPath, index, rna, val, sub)
elif key == 'FModifier':
parseFModifier(fcu, val, sub)
else:
defaultKey(key, val, sub, 'fcu', [], globals(), locals())
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]
# print("prop", expr, prop)
bone = eval(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
# print("expr", rna, expr)
fcu = eval(expr)
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', [], globals(), locals())
return fcu
def parseDriverVariable(drv, rna, args, tokens):
var = drv.variables.new()
var.name = args[0]
var.type = args[1]
nTarget = 0
# print("var", var, var.name, var.type)
for (key, val, sub) in tokens:
if key == 'Target':
parseDriverTarget(var, nTarget, rna, val, sub)
nTarget += 1
else:
defaultKey(key, val, sub, 'var', [], globals(), locals())
return var
def parseFModifier(fcu, args, tokens):
#fmod = fcu.modifiers.new()
fmod = fcu.modifiers[0]
#fmod.type = args[0]
#print("fmod", fmod, fmod.type)
for (key, val, sub) in tokens:
defaultKey(key, val, sub, 'fmod', [], globals(), locals())
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]
# targ.rna_path = args[0]
# targ.id_type = args[1]
targ.id = loadedData['Object'][args[0]]
for (key, val, sub) in tokens:
defaultKey(key, val, sub, 'targ', [], globals(), locals())
#print("Targ", targ, targ.id, targ.data_path, targ.id_type, targ.bone_target, targ.use_local_space_transforms)
return targ
#
# parseMaterial(args, ext, tokens):
# parseMTex(mat, args, tokens):
# parseTexture(args, tokens):
#
def parseMaterial(args, tokens):
global todo
name = args[0]
#print("Parse material "+name)
mat = bpy.data.materials.new(name)
if mat == None:
return None
loadedData['Material'][name] = mat
#print("Material %s %s %s" % (mat, name, loadedData['Material'][name]))
for (key, val, sub) in tokens:
if key == 'MTex':
parseMTex(mat, val, sub)
elif key == 'Ramp':
parseRamp(mat, val, sub)
elif key == 'SSS':
parseSSS(mat, val, sub)
elif key == 'Strand':
parseStrand(mat, val, sub)
else:
exclude = ['specular_intensity', 'tangent_shading']
defaultKey(key, val, sub, 'mat', [], globals(), locals())
#print("Done ", mat)
return mat
def parseMTex(mat, args, tokens):
global todo
index = int(args[0])
texname = args[1]
texco = args[2]
mapto = args[3]
mat.add_texture(texture = loadedData['Texture'][texname], texture_coordinates = texco, map_to = mapto)
mtex = mat.texture_slots[index]
#mat.use_textures[index] = Bool(use)
for (key, val, sub) in tokens:
defaultKey(key, val, sub, "mtex", [], globals(), locals())
return mtex
def parseTexture(args, tokens):
global todo
if verbosity > 2:
print( "Parsing texture %s" % args )
name = args[0]
tex = bpy.data.textures.new(name)
typ = args[1]
tex.type = typ
tex = tex.recast_type()
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)
else:
defaultKey(key, val, sub, "tex", ['use_nodes', 'use_textures', 'contrast'], globals(), locals())
return tex
def parseRamp(data, args, tokens):
nvar = "data.%s" % args[0]
use = "data.use_%s = True" % args[0]
exec(use)
ramp = eval(nvar)
elts = ramp.elements
n = 0
for (key, val, sub) in tokens:
# print("Ramp", key, val)
if key == 'Element':
elts[n].color = eval(val[0])
elts[n].position = eval(val[1])
n += 1
else:
defaultKey(key, val, sub, "tex", ['use_nodes', 'use_textures', 'contrast'], globals(), locals())
def parseSSS(mat, args, tokens):
sss = mat.subsurface_scattering
for (key, val, sub) in tokens:
defaultKey(key, val, sub, "sss", [], globals(), locals())
def parseStrand(mat, args, tokens):
strand = mat.strand
for (key, val, sub) in tokens:
defaultKey(key, val, sub, "strand", [], globals(), locals())
#
# doLoadImage(filepath):
# loadImage(filepath):
# parseImage(args, tokens):
#
def doLoadImage(filepath):
path1 = os.path.expanduser(filepath)
file1 = os.path.realpath(path1)
if os.path.isfile(file1):
print( "Found file "+file1 )
try:
img = bpy.data.images.load(file1)
return img
except:
print( "Cannot read image" )
return None
else:
print( "No file "+file1 )
return None
def loadImage(filepath):
global TexDir, warnedTextureDir, loadedData
texDir = os.path.expanduser(TexDir)
path1 = os.path.expanduser(filepath)
file1 = os.path.realpath(path1)
(path, filename) = os.path.split(file1)
(name, ext) = os.path.splitext(filename)
print( "Loading ", filepath, " = ", filename )
# img = doLoadImage(texDir+"/"+name+".png")
# if img:
# return img
img = doLoadImage(texDir+"/"+filename)
if img:
return img
# img = doLoadImage(path+"/"+name+".png")
# if img:
# return img
img = doLoadImage(path+"/"+filename)
if img:
return img
if warnedTextureDir:
return None
warnedTextureDir = True
return None
TexDir = Draw.PupStrInput("TexDir? ", path, 100)
texDir = os.path.expanduser(TexDir)
img = doLoadImage(texDir+"/"+name+".png")
if img:
return img
img = doLoadImage(TexDir+"/"+filename)
return img
def parseImage(args, tokens):
global todo
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 == None:
return None
img.name = imgName
else:
defaultKey(key, val, sub, "img", ['depth', 'dirty', 'has_data', 'size', 'type'], globals(), locals())
print ("Image %s" % img )
loadedData['Image'][imgName] = img
return img
#
# parseObject(args, tokens):
# createObject(type, name, data, datName):
# createObjectAndData(args, typ):
#
def parseObject(args, tokens):
if verbosity > 2:
print( "Parsing object %s" % args )
name = args[0]
typ = args[1]
datName = args[2]
try:
data = loadedData[typ.capitalize()][datName]
except:
data = None
if data == None and typ != 'EMPTY':
print("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")
except:
ob = createObject(typ, name, data, datName)
if bpy.context.object != ob:
print("Context", ob, bpy.context.object, bpy.context.scene.objects.active)
# ob = foo
for (key, val, sub) in tokens:
if key == 'Modifier':
parseModifier(ob, val, sub)
elif key == 'Constraint':
parseConstraint(ob.constraints, val, sub)
elif key == 'AnimationData':
if eval(val[0]):
parseAnimationData(ob, sub)
elif key == 'ParticleSystem':
parseParticleSystem(ob, val, sub)
else:
defaultKey(key, val, sub, "ob", ['type', 'data'], globals(), locals())
# Needed for updating layers
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.object.mode_set(mode='OBJECT')
return
def createObject(typ, name, data, datName):
#print( "Creating object %s %s %s" % (typ, name, data) )
ob = bpy.data.objects.new(name, data)
loadedData[typ][datName] = data
loadedData['Object'][name] = ob
return ob
def linkObject(ob, data):
#print("Data", data, ob.data)
if data and ob.data == 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 createObjectAndData(args, typ):
datName = args[0]
obName = args[1]
bpy.ops.object.add(type=typ.upper())
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:
defaultKey(key, val, sub, 'mod', [], globals(), locals())
return mod
#
# 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', [], globals(), locals())
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', [], globals(), locals())
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 = eval(val[0])
h.time = int(val[1])
h.weight = float(val[2])
n += 1
elif key == 'location':
par.location = eval(val[0])
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 todo
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:
#x = me.from_pydata(verts, [], faces)
me.add_geometry(len(verts), 0, len(faces))
me.verts.foreach_set("co", unpackList(verts))
me.faces.foreach_set("verts_raw", unpackList(faces))
else:
#x = me.from_pydata(verts, edges, [])
me.add_geometry(len(verts), len(edges), 0)
me.verts.foreach_set("co", unpackList(verts))
me.edges.foreach_set("verts", unpackList(edges))
#print(x)
me.update()
#print(me)
linkObject(ob, me)
mats = []
for (key, val, sub) in tokens:
if key == 'Verts' or \
key == 'Edges':
pass
elif key == 'Faces':
parseFaces2(sub, me)
elif key == 'MeshTextureFaceLayer':
parseUvTexture(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:
me.add_material(loadedData['Material'][val[0]])
except:
print("Could not add material", val[0])
else:
defaultKey(key, val, sub, "me", [], globals(), locals())
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( (float(val[0]), float(val[1]), 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]), 0]
elif len(val) == 4:
face = [int(val[0]), int(val[1]), int(val[2]), int(val[3])]
faces.append(face)
return faces
def parseFaces2(tokens, me):
n = 0
for (key, val, sub) in tokens:
if key == 'ft':
f = me.faces[n]
f.material_index = int(val[0])
f.smooth = int(val[1])
n += 1
elif key == 'ftall':
mat = int(val[0])
smooth = int(val[1])
for f in me.faces:
f.material_index = mat
f.smooth = smooth
return
#
# parseUvTexture(args, tokens, me):
# parseUvTexData(args, tokens, uvdata):
#
def parseUvTexture(args, tokens, me):
me.add_uv_texture()
uvtex = me.uv_textures[-1]
name = args[0]
uvtex.name = name
loadedData['MeshTextureFaceLayer'][name] = uvtex
for (key, val, sub) in tokens:
if key == 'Data':
parseUvTexData(val, sub, uvtex.data)
else:
defaultKey(key, val, sub, "uvtex", [], globals(), locals())
return
def parseUvTexData(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
else:
pass
#for i in range(n):
# defaultKey(key, val, sub, "data[i]", [], globals(), locals())
return
#
# parseVertColorLayer(args, tokens, me):
# parseVertColorData(args, tokens, data):
#
def parseVertColorLayer(args, tokens, me):
name = args[0]
print("VertColorLayer", name)
me.add_vertex_color()
vcol = me.vertex_colors[-1]
vcol.name = 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", [], globals(), locals())
return
def parseVertColorData(args, tokens, data):
n = 0
for (key, val, sub) in tokens:
if key == 'cv':
data[n].color1 = eval(val[0])
data[n].color2 = eval(val[1])
data[n].color3 = eval(val[2])
data[n].color4 = eval(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 = eval(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']):
group = ob.add_vertex_group(grpName)
group.name = grpName
loadedData['VertexGroup'][grpName] = group
for (key, val, sub) in tokens:
if key == 'wv':
ob.add_vertex_to_group( int(val[0]), group, 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_Shape+T_Face) and (name == 'Basis'):
return True
else:
return (toggle & T_Face)
def parseShapeKeys(ob, me, args, tokens):
if bpy.context.object == None:
return
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, sub)
return
def parseShapeKey(ob, me, args, tokens):
if verbosity > 0:
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:
raise NameError("ShapeKey L/R %s" % lr)
return
def addShapeKey(ob, name, vgroup, tokens):
bpy.ops.object.shape_key_add(False)
skey = ob.active_shape_key
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] += float(val[1])
pt[1] += float(val[2])
pt[2] += float(val[3])
else:
defaultKey(key, val, sub, "skey", [], globals(), locals())
return
#
# parseArmature (obName, args, tokens)
#
def parseArmature (args, tokens):
global toggle, theScale
if verbosity > 2:
print( "Parsing armature %s" % args )
amtname = args[0]
obname = args[1]
mode = args[2]
if mode == 'Rigify':
toggle |= T_Rigify
theScale = 0.1
return parseRigify(amtname, obname, tokens)
toggle &= ~T_Rigify
theScale = 1.0
amt = bpy.data.armatures.new(amtname)
ob = createObject('Armature', obname, amt, amtname)
linkObject(ob, amt)
print("Linked")
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.edit_bones, sub, heads, tails)
loadedData['Bone'][bname] = bone
else:
defaultKey(key, val, sub, "amt", ['MetaRig'], globals(), locals())
bpy.ops.object.mode_set(mode='OBJECT')
return amt
#
# parseRigify(amtname, obname, tokens):
#
def parseRigify(amtname, obname, tokens):
(key,val,sub) = tokens[0]
if key != 'MetaRig':
raise NameError("Expected MetaRig")
typ = val[0]
if typ == "human":
bpy.ops.object.armature_human_advanced_add()
else:
bpy.ops.pose.metarig_sample_add(type = typ)
ob = bpy.context.scene.objects.active
amt = ob.data
loadedData['Rigify'][obname] = ob
loadedData['Armature'][amtname] = amt
loadedData['Object'][obname] = ob
print("Rigify object", ob, amt)
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.mode_set(mode='EDIT')
heads = {}
tails = {}
for (bname, bone) in amt.edit_bones.items():
heads[bname] = 10*theScale*bone.head
tails[bname] = 10*theScale*bone.tail
for (key, val, sub) in tokens:
if key == 'Bone':
bname = val[0]
print("Bone", bname)
try:
bone = amt.edit_bones[bname]
except:
print("Did not find bone %s" % bname)
bone = None
print(" -> ", bone)
if bone:
parseBone(bone, amt.edit_bones, sub, heads, tails)
else:
defaultKey(key, val, sub, "amt", ['MetaRig'], globals(), locals())
bpy.ops.object.mode_set(mode='OBJECT')
return amt
#
# parseBone(bone, bones, tokens, heads, tails):
#
def parseBone(bone, bones, tokens, heads, tails):
global todo
for (key, val, sub) in tokens:
if key == "head":
bone.head = (float(val[0]), float(val[1]), float(val[2]))
elif key == "tail":
bone.tail = (float(val[0]), float(val[1]), float(val[2]))
elif key == "head-as":
target = val[0]
if val[1] == 'head':
bone.head = heads[bone.name] + bones[target].head - heads[target]
elif val[1] == 'tail':
bone.head = heads[bone.name] + bones[target].tail - tails[target]
else:
raise NameError("head-as %s" % val)
elif key == "tail-as":
target = val[0]
if val[1] == 'head':
bone.tail = tails[bone.name] + bones[target].head - heads[target]
elif val[1] == 'tail':
bone.tail = tails[bone.name] + bones[target].tail - tails[target]
else:
raise NameError("tail-as %s" % val)
elif key == 'restrict_select':
pass
else:
defaultKey(key, val, sub, "bone", [], globals(), locals())
return bone
#
# parsePose (args, tokens):
#
def parsePose (args, tokens):
global todo
if toggle & T_Rigify:
return
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 = eval(val[2])
pb = pbones[bone]
print("Setting", pb, prop, val)
pb[prop] = value
print("Prop set", pb[prop])
else:
defaultKey(key, val, sub, "ob.pose", [], globals(), locals())
bpy.ops.object.mode_set(mode='OBJECT')
return ob
#
# parsePoseBone(pbones, args, tokens):
# parseArray(data, exts, args):
#
def parseBoneGroup(pose, nGrps, args, tokens):
global todo
return
print( "Parsing bonegroup %s" % args )
name = args[0]
print(dir(pose.bone_groups))
bg = pose.bone_groups.add()
print("Created", bg)
loadedData['BoneGroup'][name] = bg
for (key, val, sub) in tokens:
defaultKey(key, val, sub, "bg", [], globals(), locals())
return
def parsePoseBone(pbones, ob, args, tokens):
global todo
#print( "Parsing posebone %s" % args )
if invalid(args[1]):
return
name = args[0]
pb = pbones[name]
# Make posebone active - don't know how to do this in pose mode
bpy.ops.object.mode_set(mode='OBJECT')
ob.data.bones.active = pb.bone
bpy.ops.object.mode_set(mode='POSE')
for (key, val, sub) in tokens:
if key == 'Constraint':
cns = parseConstraint(pb.constraints, val, sub)
elif key == 'bpyops':
expr = "bpy.ops.%s" % val[0]
print(expr)
print("ob", bpy.context.active_object)
print("b", bpy.context.active_bone)
print("pb", bpy.context.active_pose_bone)
print("md", bpy.context.mode)
exec(expr)
print("alive")
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)
else:
defaultKey(key, val, sub, "pb", [], globals(), locals())
#print("pb %s done" % name)
return
def parseArray(data, exts, args):
n = 1
for ext in exts:
expr = "data.%s = %s" % (ext, args[n])
# print(expr)
exec(expr)
n += 1
return
#
# parseConstraint(constraints, args, tokens)
#
def parseConstraint(constraints, args, tokens):
if invalid(args[2]):
return None
cns = constraints.new(args[1])
#bpy.ops.pose.constraint_add(type=args[1])
#cns = pb.constraints[-1]
cns.name = args[0]
#print("cns", cns.name)
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, ["pos_lock_x", "pos_lock_y", "pos_lock_z"], val)
elif key == 'rot_lock':
parseArray(cns, ["rot_lock_x", "rot_lock_y", "rot_lock_z"], val)
else:
defaultKey(key, val, sub, "cns", [], globals(), locals())
#print("cns %s done" % cns.name)
return cns
def insertInfluenceIpo(cns, bone):
global todo
if bone != 'PArmIK_L' and bone != 'PArmIK_R' and bone != 'PLegIK_L' and bone != 'PLegIK_R':
return False
if (toggle & T_FKIK):
fcurve = cns.driver_add("influence", 0)
fcurve.driver.type = 'AVERAGE'
var = fcurve.driver.variables.new()
var.name = bone
var.targets[0].id_type = 'OBJECT'
var.targets[0].id = getObject('HumanRig', 'var.targets[0].id', globals(), locals())
var.targets[0].bone_target = bone
var.targets[0].transform_type = 'LOC_X'
# controller_path = fk_chain.arm_p.path_to_id()
#var.targets[0].data_path = controller_path + '["hinge"]'
mod = fcurve.modifiers[0]
mod.poly_order = 2
mod.coefficients[0] = 0.0
mod.coefficients[1] = 1.0
elif bone == 'PArmIK_L' or bone == 'PArmIK_R':
if toggle & T_ArmIK:
cns.influence = 1.0
else:
cns.influence = 0.0
elif bone == 'PLegIK_L' or bone == 'PLegIK_R':
if toggle & T_LegIK:
cns.influence = 1.0
else:
cns.influence = 0.0
return True
#
# parseCurve (args, tokens):
# parseNurb(cu, nNurbs, args, tokens):
# parseBezier(nurb, n, args, tokens):
#
def parseCurve (args, tokens):
global todo
if verbosity > 2:
print( "Parsing curve %s" % args )
cu = createObjectAndData(args, 'Curve')
nNurbs = 0
for (key, val, sub) in tokens:
if key == 'Nurb':
parseNurb(cu, nNurbs, val, sub)
nNurbs += 1
else:
defaultKey(key, val, sub, "cu", [], globals(), locals())
return
def parseNurb(cu, nNurbs, args, tokens):
if nNurbs > 0:
bpy.ops.object.curve_add(type='BEZIER_CURVE')
print(cu.splines, list(cu.splines), nNurbs)
nurb = cu.splines[nNurbs]
nPoints = int(args[0])
print(nurb, nPoints)
for n in range(2, nPoints):
bpy.ops.curve.extrude(mode=1)
n = 0
for (key, val, sub) in tokens:
if key == 'bz':
parseBezier(nurb, n, val, sub)
n += 1
elif key == 'pt':
parsePoint(nurb, n, val, sub)
n += 1
else:
defaultKey(key, val, sub, "nurb", [], globals(), locals())
return
def parseBezier(nurb, n, args, tokens):
bez = nurb[n]
bez.co = eval(args[0])
bez.handle1 = eval(args[1])
bez.handle1_type = args[2]
bez.handle2 = eval(args[3])
bez.handle2_type = args[4]
return
def parsePoint(nurb, n, args, tokens):
pt = nurb[n]
pt.co = eval(args[0])
return
#
# parseLattice (args, tokens):
#
def parseLattice (args, tokens):
global todo
if verbosity > 2:
print( "Parsing lattice %s" % args )
lat = createObjectAndData(args, 'Lattice')
for (key, val, sub) in tokens:
if key == 'Points':
parseLatticePoints(val, sub, lat.points)
else:
defaultKey(key, val, sub, "lat", [], globals(), locals())
return
def parseLatticePoints(args, tokens, points):
global todo
n = 0
for (key, val, sub) in tokens:
if key == 'pt':
v = points[n].co
(x,y,z) = eval(val[0])
v.x = x
v.y = y
v.z = z
v = points[n].deformed_co
(x,y,z) = eval(val[1])
v.x = x
v.y = y
v.z = z
n += 1
return
#
# parseGroup (args, tokens):
#
def parseGroup (args, tokens):
global todo
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", [], globals(), locals())
return
def parseGroupObjects(args, tokens, grp):
global todo
for (key, val, sub) in tokens:
if key == 'ob':
try:
ob = loadedData['Object'][val[0]]
grp.objects.link(ob)
except:
pass
return
#
# postProcess()
# setInfluence(bones, cnsName, w):
#
def postProcess():
if not toggle & T_MHX:
return
if toggle & T_Rigify:
return
for rig in loadedData['Rigify'].values():
bpy.context.scene.objects.active = rig
print("Rigify", rig)
bpy.ops.pose.metarig_generate()
print("Metarig generated")
#bpy.context.scene.objects.unlink(rig)
rig = bpy.context.scene.objects.active
print("Rigged", rig, bpy.context.object)
ob = loadedData['Object']['Human']
mod = ob.modifiers[0]
print(ob, mod, mod.object)
mod.object = rig
print("Rig changed", mod.object)
return
#
# parseProcess(args, tokens):
#
def parseProcess(args, tokens):
return
rig = loadedData['Object'][args[0]]
parents = {}
objects = []
for (key, val, sub) in tokens:
if key == 'Reparent':
bname = val[0]
try:
eb = ebones[bname]
parents[bname] = eb.parent.name
eb.parent = ebones[val[1]]
except:
pass
elif key == 'Bend':
print(val)
axis = val[1]
angle = float(val[2])
mat = mathutils.RotationMatrix(angle, 4, axis)
try:
pb = pbones[val[0]]
prod = pb.matrix_local * mat
for i in range(4):
for j in range(4):
pb.matrix_local[i][j] = prod[i][j]
print("Done", pb.matrix_local)
except:
pass
elif key == 'Pose':
bpy.context.scene.objects.active = rig
bpy.ops.object.mode_set(mode='POSE')
pbones = rig.pose.bones
elif key == 'Edit':
bpy.context.scene.objects.active = rig
bpy.ops.object.mode_set(mode='EDIT')
ebones = rig.data.edit_bones
elif key == 'Object':
bpy.ops.object.mode_set(mode='OBJECT')
try:
ob = loadedData['Object'][val[0]]
objects.append((ob,sub))
except:
ob = None
if ob:
bpy.context.scene.objects.active = ob
mod = ob.modifiers[0]
ob.modifiers.remove(mod)
for (key1, val1, sub1) in sub:
if key1 == 'Modifier':
parseModifier(ob, val1, sub1)
for (ob,tokens) in objects:
bpy.context.scene.objects.active = ob
bpy.ops.object.visual_transform_apply()
#print("vis", list(ob.modifiers))
bpy.ops.object.modifier_apply(apply_as='DATA', modifier='Armature')
#print("app", list(ob.modifiers))
bpy.context.scene.objects.active = rig
bpy.ops.object.mode_set(mode='POSE')
bpy.ops.pose.armature_apply()
bpy.ops.object.mode_set(mode='EDIT')
ebones = rig.data.edit_bones
for (bname, pname) in parents.items():
eb = ebones[bname]
par = ebones[pname]
if eb.connected:
par.tail = eb.head
eb.parent = par
bpy.ops.object.mode_set(mode='OBJECT')
for (ob,tokens) in objects:
bpy.context.scene.objects.active = ob
for (key, val, sub) in tokens:
if key == 'Modifier':
parseModifier(ob, val, sub)
return
#
# defaultKey(ext, args, tokens, var, exclude, glbals, lcals):
#
def defaultKey(ext, args, tokens, var, exclude, glbals, lcals):
global todo
if ext == 'Property':
expr = "%s['%s'] = %s" % (var, args[0], args[1])
print("Property", expr)
exec(expr, glbals, lcals)
#print("execd")
return
nvar = "%s.%s" % (var, ext)
# print(ext)
if ext in exclude:
return
#print("D", nvar)
if len(args) == 0:
raise NameError("Key length 0: %s" % ext)
rnaType = args[0]
if rnaType == 'Add':
print("*** Cannot Add yet ***")
return
elif rnaType == 'Refer':
typ = args[1]
name = args[2]
data = "loadedData['%s']['%s']" % (typ, name)
elif rnaType == 'Struct' or rnaType == 'Define':
typ = args[1]
name = args[2]
try:
data = eval(nvar, glbals, lcals)
except:
data = None
# print("Old structrna", nvar, data)
if data == None:
try:
creator = args[3]
except:
creator = None
# print("Creator", creator, eval(var,glbals,lcals))
try:
rna = eval(var,glbals,lcals)
data = eval(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", [], globals(), locals())
print("Struct done", nvar)
return
elif rnaType == 'PropertyRNA':
raise NameError("PropertyRNA!")
#print("PropertyRNA ", ext, var)
for (key, val, sub) in tokens:
defaultKey(ext, val, sub, nvar, [], glbals, lcals)
return
elif rnaType == 'Array':
for n in range(1, len(args)):
expr = "%s[%d] = %s" % (nvar, n-1, args[n])
exec(expr, glbals, lcals)
if len(args) > 0:
expr = "%s[0] = %s" % (nvar, args[1])
exec(expr, glbals, lcals)
return
elif rnaType == 'List':
data = []
for (key, val, sub) in tokens:
elt = eval(val[1], glbals, lcals)
data.append(elt)
elif rnaType == 'Matrix':
return
i = 0
n = len(tokens)
for (key, val, sub) in tokens:
if key == 'row':
for j in range(n):
expr = "%s[%d][%d] = %g" % (nvar, i, j, float(val[j]))
exec(expr, glbals, lcals)
i += 1
return
else:
try:
data = loadedData[rnaType][args[1]]
#print("From loaded", rnaType, args[1], data)
return data
except:
data = rnaType
#print(var, ext, data)
expr = "%s = %s" % (nvar, data)
try:
exec(expr, glbals, lcals)
except:
#print("Failed ",expr)
todo.append((expr, glbals, lcals))
return
#
# 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 = Matrix( [1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1] )
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, exclude):
#
def parseDefault(data, tokens):
for (key, val, sub) in tokens:
defaultKey(key, val, sub, "data", exclude, globals(), locals())
#
# 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:
raise NameError("Bool %s?" % string)
#
# invalid(condition):
#
def invalid(condition):
global rigLeg, rigArm, toggle
res = eval(condition, globals())
try:
res = eval(condition, globals())
#print("%s = %s" % (condition, res))
return not res
except:
#print("%s invalid!" % condition)
return True
#
# clearScene(context):
# hideLayers():
#
def clearScene():
global toggle
scn = bpy.context.scene
for n in range(len(scn.layers)):
scn.layers[n] = True
print("clearScene %s %s" % (toggle & T_Replace, scn))
if not toggle & T_Replace:
return scn
for ob in scn.objects:
if ob.type == "MESH" or ob.type == "ARMATURE":
scn.objects.active = ob
bpy.ops.object.mode_set(mode='OBJECT')
scn.objects.unlink(ob)
del ob
#print(scn.objects)
return scn
def hideLayers():
scn = bpy.context.scene
for n in range(len(scn.layers)):
if n < 3:
scn.layers[n] = True
else:
scn.layers[n] = False
return
#
# User interface
#
DEBUG= False
from bpy.props import *
class IMPORT_OT_makehuman_mhx(bpy.types.Operator):
'''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"
path = StringProperty(name="File Path", description="File path used for importing the MHX file", maxlen= 1024, default= "")
#preset = BoolProperty(name="Use rig preset", description="Use rig preset (Classic/Gobo)?", default=True)
#presetRig = EnumProperty(name="Rig", description="Choose preset rig",
# items = [('Classic','Classic','Classic'), ('Gobo','Gobo','Gobo')], default = '1')
footRig = EnumProperty(name="Foot rig", description="Foot rig",
items = [('Reverse foot','Reverse foot','Reverse foot'), ('Gobo','Gobo','Gobo')], default = '1')
fingerRig = EnumProperty(name="Finger rig", description="Finger rig",
items = [('Panel','Panel','Panel'), ('Curl','Curl','Curl'), ('IK','IK','IK')], default = '1')
mesh = BoolProperty(name="Mesh", description="Use main mesh", default=toggle&T_Mesh)
armature = BoolProperty(name="Armature", description="Use armature", default=toggle&T_Armature)
proxy = BoolProperty(name="Proxy", description="Use proxy object", default=toggle&T_Proxy)
replace = BoolProperty(name="Replace scene", description="Replace scene", default=toggle&T_Replace)
face = BoolProperty(name="Face shapes", description="Include facial shapekeys", default=toggle&T_Face)
shape = BoolProperty(name="Body shapes", description="Include body shapekeys", default=toggle&T_Shape)
symm = BoolProperty(name="Symmetric shapes", description="Keep shapekeys symmetric", default=toggle&T_Symm)
def execute(self, context):
global toggle
O_Mesh = T_Mesh if self.properties.mesh else 0
O_Armature = T_Armature if self.properties.armature else 0
O_Proxy = T_Proxy if self.properties.proxy else 0
O_Replace = T_Replace if self.properties.replace else 0
O_Face = T_Face if self.properties.face else 0
O_Shape = T_Shape if self.properties.shape else 0
O_Symm = T_Symm if self.properties.symm else 0
#O_Preset = T_Preset if self.properties.preset else 0
toggle = O_Mesh | O_Armature | O_Proxy | T_ArmIK | T_LegIK | O_Replace | O_Face | O_Shape | O_Symm | T_MHX
readMhxFile(self.properties.path,
(self.properties.footRig,
self.properties.fingerRig))
return {'FINISHED'}
def invoke(self, context, event):
wm = context.manager
wm.add_fileselect(self)
return {'RUNNING_MODAL'}
'''
class MakeHumanFKIKPanel(bpy.types.Panel):
bl_label = "MakeHuman FK/IK"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
def draw(self, context):
layout = self.layout
ob = bpy.context.active_object
if ob.type == 'ARMATURE':
layout.row().prop(ob, "PArmIK_L")
layout.row().prop(ob, "PArmIK_R")
layout.row().prop(ob, "PLegIK_L")
layout.row().prop(ob, "PLegIK_R")
layout.row().prop(ob, "PHandLocal_L")
layout.row().prop(ob, "PHandLocal_R")
layout.row().prop(ob, "PFootLocal_L")
layout.row().prop(ob, "PFootLocal_R")
return
class MakeHumanFingerPanel(bpy.types.Panel):
bl_label = "MakeHuman Fingers"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
def draw(self, context):
layout = self.layout
pb = bpy.context.active_pose_bone
layout.row().prop(pb, "MHRelax")
layout.row().prop(pb, "MHCurl")
layout.row().prop(pb, "MHCone")
layout.row().prop(pb, "MHSpread")
layout.row().prop(pb, "MHScrunch")
layout.row().prop(pb, "MHLean")
return
def registerPanels():
bpy.types.Object.FloatProperty(attr="PArmIK_L", name="L arm - IK", default = 0, min = 0.0, max = 1.0)
bpy.types.Object.FloatProperty(attr="PArmIK_R", name="R arm - IK", default = 0, min = 0.0, max = 1.0)
bpy.types.Object.FloatProperty(attr="PLegIK_L", name="L leg - IK", default = 0, min = 0.0, max = 1.0)
bpy.types.Object.FloatProperty(attr="PLegIK_R", name="R leg - IK", default = 0, min = 0.0, max = 1.0)
bpy.types.Object.FloatProperty(attr="PHandLocal_L", name="L hand - Loc", default = 0, min = 0.0, max = 1.0)
bpy.types.Object.FloatProperty(attr="PHandLocal_R", name="R hand - Loc", default = 0, min = 0.0, max = 1.0)
bpy.types.Object.FloatProperty(attr="PFootLocal_L", name="L foot - Loc", default = 0, min = 0.0, max = 1.0)
bpy.types.Object.FloatProperty(attr="PFootLocal_R", name="R foot - Loc", default = 0, min = 0.0, max = 1.0)
bpy.types.PoseBone.FloatProperty(attr="MHCone", name="Cone", default = 0, min = -0.5, max = 1.0)
bpy.types.PoseBone.FloatProperty(attr="MHRelax", name="Relax", default = 0, min = -0.5, max = 1.0)
bpy.types.PoseBone.FloatProperty(attr="MHCurl", name="Curl", default = 0, min = -0.5, max = 1.0)
bpy.types.PoseBone.FloatProperty(attr="MHLean", name="Lean", default = 0, min = -1.0, max = 1.0)
bpy.types.PoseBone.FloatProperty(attr="MHScrunch", name="Scrunch", default = 0, min = -0.5, max = 1.0)
bpy.types.PoseBone.FloatProperty(attr="MHSpread", name="Spread", default = 0, min = -0.5, max = 1.0)
bpy.types.register(MakeHumanFKIKPanel)
bpy.types.register(MakeHumanFingerPanel)
def unregisterPanels():
bpy.types.unregister(MakeHumanFKIKPanel)
bpy.types.unregister(MakeHumanFingerPanel)
'''
def register():
# registerPanels()
bpy.types.register(IMPORT_OT_makehuman_mhx)
menu_func = lambda self, context: self.layout.operator(IMPORT_OT_makehuman_mhx.bl_idname, text="MakeHuman (.mhx)...")
bpy.types.INFO_MT_file_import.append(menu_func)
return
def unregister():
# unregisterPanels()
bpy.types.unregister(IMPORT_OT_makehuman_mhx)
menu_func = lambda self, context: self.layout.operator(IMPORT_OT_makehuman_mhx.bl_idname, text="MakeHuman (.mhx)...")
bpy.types.INFO_MT_file_import.remove(menu_func)
if __name__ == "__main__":
register()
#
# Testing
#
"""
theScale = 1.0
toggle = T_Replace + T_Mesh + T_Armature + T_MHX + T_ArmIK + T_LegIK
#rigLeg = T_Toes + T_GoboFoot
#rigArm = T_ElbowPT + T_FingerCurl
#readMhxFile("/home/thomas/makehuman/exports/foo-25.mhx")
#toggle = T_Replace + T_Armature
#readMhxFile("/home/thomas/makehuman/exports/foo-sintel-25.mhx")
readMhxFile("C:/Documents and Settings/xxxxxxxxxxxxxxxxxxxx/Mina dokument/makehuman/exports/foo-25.mhx", 'Classic')
#readMhxFile("/home/thomas/mhx5/test1.mhx")
#readMhxFile("/home/thomas/myblends/gobo/gobo.mhx")
#readMhxFile("/home/thomas/myblends/sintel/simple.mhx")
"""