Skip to content
Snippets Groups Projects
io_import_scene_mhx.py 134 KiB
Newer Older
        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]
Luca Bonavita's avatar
Luca Bonavita committed
    try:
        ob = loadedData['Object'][human]
Luca Bonavita's avatar
Luca Bonavita committed
    except:
        ob = None
    if toggle & T_Diamond == 0 and ob:
Luca Bonavita's avatar
Luca Bonavita committed

#
#    deleteDiamonds(ob)
#    Delete joint diamonds in main mesh
Luca Bonavita's avatar
Luca Bonavita committed
    bpy.context.scene.objects.active = ob
    if not bpy.context.object:
        return
    print("Delete helper geometry in %s" % bpy.context.object)
Luca Bonavita's avatar
Luca Bonavita committed
    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")
            if f.material_index >= invisioNum:
                for vn in f.vertices:
                    me.vertices[vn].select = True
            if f.material_index >= invisioNum:
                for vn in f.vertices:
                    me.vertices[vn].select = True
        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")
Luca Bonavita's avatar
Luca Bonavita committed
    return
#    defaultKey(ext, args, tokens, data, exclude):
    #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":
    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 string, '["%s"]' % string
def defProp(args, var):
    proptype = args[0]
    name = propNames(args[1])[0]
    rest = 'description="%s"' % args[3].replace("_", " ")
    if len(args) > 4:
        rest += ", " + args[4]
    if name:
        var[name] = value
    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]
        var[name] = value
        if len(args) > 2:
            tip = 'description="%s"' % args[2].replace("_", " ")
        theProperty = (name, tip, value)
def setPropKeys(args):
    (name, tip, value) = theProperty
    if len(args) >= 2 and not isinstance(value, bool):
            value = bool(value)
            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)
def defaultKey(ext, args, tokens, var, exclude=[]):
Luca Bonavita's avatar
Luca Bonavita committed
    if ext == 'Property':
        return setProperty(args, var)
        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)
Luca Bonavita's avatar
Luca Bonavita committed
    if ext in exclude:
        return
    nvar = getattr(var, ext)
Luca Bonavita's avatar
Luca Bonavita committed

    if len(args) == 0:
        MyError("Key length 0: %s" % ext)
Luca Bonavita's avatar
Luca Bonavita committed
    rnaType = args[0]
Luca Bonavita's avatar
Luca Bonavita committed
        typ = args[1]
        name = args[2]
        setattr(var, ext, loadedData[typ][name])
        return
Luca Bonavita's avatar
Luca Bonavita committed

    elif rnaType == 'Struct' or rnaType == 'Define':
        raise MhxError("Struct/Define!")
Luca Bonavita's avatar
Luca Bonavita committed
        typ = args[1]
        name = args[2]
        try:
            data = getattr(var, ext)
Luca Bonavita's avatar
Luca Bonavita committed
        except:
Luca Bonavita's avatar
Luca Bonavita committed
        # print("Old structrna", nvar, data)

Luca Bonavita's avatar
Luca Bonavita committed
            try:
                creator = args[3]
            except:
                creator = None

            try:
                rna = mhxEval(var, locals())
                data = mhxEval(creator)
Luca Bonavita's avatar
Luca Bonavita committed
            except:
Luca Bonavita's avatar
Luca Bonavita committed
            # 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)
Luca Bonavita's avatar
Luca Bonavita committed
        return

    elif rnaType == 'PropertyRNA':
        raise MhxError("PropertyRNA!")
Luca Bonavita's avatar
Luca Bonavita committed
        #print("PropertyRNA ", ext, var)
        for (key, val, sub) in tokens:
            defaultKey(ext, val, sub, nvar, [])
Luca Bonavita's avatar
Luca Bonavita committed
        return

    elif rnaType == 'Array':
        for n in range(1, len(args)):
            nvar[n-1] = mhxEval(args[n], locals())
Luca Bonavita's avatar
Luca Bonavita committed
        if len(args) > 0:
            nvar[0] = mhxEval(args[1], locals())
Luca Bonavita's avatar
Luca Bonavita committed
        return
Luca Bonavita's avatar
Luca Bonavita committed
    elif rnaType == 'List':
Luca Bonavita's avatar
Luca Bonavita committed
        data = []
        for (key, val, sub) in tokens:
            elt = mhxEval(val[1], locals())
Luca Bonavita's avatar
Luca Bonavita committed
            data.append(elt)
        setattr(var, ext, data)
        return
Luca Bonavita's avatar
Luca Bonavita committed

    elif rnaType == 'Matrix':
        raise MhxError("Matrix!")
Luca Bonavita's avatar
Luca Bonavita committed
        i = 0
        n = len(tokens)
        for (key, val, sub) in tokens:
Luca Bonavita's avatar
Luca Bonavita committed
                for j in range(n):
                    nvar[i][j] = float(val[j])
Luca Bonavita's avatar
Luca Bonavita committed
                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)
Luca Bonavita's avatar
Luca Bonavita committed

def pushOnTodoList(var, expr):
    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")
Luca Bonavita's avatar
Luca Bonavita committed
#    parseBoolArray(mask):
Brendon Murphy's avatar
Brendon Murphy committed
#

def parseBoolArray(mask):
Luca Bonavita's avatar
Luca Bonavita committed
    list = []
    for c in mask:
Luca Bonavita's avatar
Luca Bonavita committed
            list.append(False)
        else:
            list.append(True)
    return list
Luca Bonavita's avatar
Luca Bonavita committed
#    parseMatrix(args, tokens)
Brendon Murphy's avatar
Brendon Murphy committed
#

def parseMatrix(args, tokens):
    matrix = mathutils.Matrix()
Luca Bonavita's avatar
Luca Bonavita committed
    i = 0
    for (key, val, sub) in tokens:
Luca Bonavita's avatar
Luca Bonavita committed
            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
Luca Bonavita's avatar
Luca Bonavita committed
#    parseDefault(data, tokens, subkeys, exclude):
def parseDefault(data, tokens, subkeys, exclude):
Luca Bonavita's avatar
Luca Bonavita committed
        if key in subkeys.keys():
            for (key2, val2, sub2) in sub:
                ndata = getattr(data, subkeys[key])
                defaultKey(key2, val2, sub2, ndata)
Luca Bonavita's avatar
Luca Bonavita committed
        else:
            defaultKey(key, val, sub, data, exclude)

def parseCollection(data, tokens, exclude):
Luca Bonavita's avatar
Luca Bonavita committed
    return
Luca Bonavita's avatar
Luca Bonavita committed
#    extractBpyType(data):
Brendon Murphy's avatar
Brendon Murphy committed
#
Brendon Murphy's avatar
Brendon Murphy committed
def extractBpyType(data):
Luca Bonavita's avatar
Luca Bonavita committed
    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
Luca Bonavita's avatar
Luca Bonavita committed
#    Bool(string):
Brendon Murphy's avatar
Brendon Murphy committed
#

def Bool(string):
Luca Bonavita's avatar
Luca Bonavita committed
    if string == 'True':
        return True
    elif string == 'False':
        return False
    else:
        MyError("Bool %s?" % string)
Brendon Murphy's avatar
Brendon Murphy committed
#
Luca Bonavita's avatar
Luca Bonavita committed
#    invalid(condition):
Brendon Murphy's avatar
Brendon Murphy committed
#

def invalid(condition):
Luca Bonavita's avatar
Luca Bonavita committed
    global rigLeg, rigArm, toggle
    try:
Luca Bonavita's avatar
Luca Bonavita committed
        #print("%s = %s" % (condition, res))
        return not res
    except:
        #print("%s invalid!" % condition)
        return True
Luca Bonavita's avatar
Luca Bonavita committed
#    clearScene(context):
Brendon Murphy's avatar
Brendon Murphy committed
def clearScene():
Luca Bonavita's avatar
Luca Bonavita committed
    global toggle
    scn = bpy.context.scene
    for n in range(len(scn.layers)):
        scn.layers[n] = True
    return scn
Luca Bonavita's avatar
Luca Bonavita committed
    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']:
Luca Bonavita's avatar
Luca Bonavita committed
            scn.objects.active = ob
            try:
                bpy.ops.object.mode_set(mode='OBJECT')
            except:
                pass
Luca Bonavita's avatar
Luca Bonavita committed
            scn.objects.unlink(ob)
            del ob

    for grp in bpy.data.groups:
        grp.name = "#" + grp.name
Luca Bonavita's avatar
Luca Bonavita committed
    #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

Luca Bonavita's avatar
Luca Bonavita committed
    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
        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 = ''
        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)
    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))
Luca Bonavita's avatar
Luca Bonavita committed
    return
###################################################################################
#
#   Postprocessing of rigify rig
#
#
###################################################################################

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
    def __repr__(self):
        return ("<RigifyBone %s %s %s>" % (self.name, self.realname, self.realname1))
    print("Modifying MHX rig to Rigify")
    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)
            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)
    bpy.ops.object.mode_set(mode='EDIT')
        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]
    bpy.ops.pose.rigify_generate()
    gen = context.object
    print("Generated", gen)
    for bone in bones.values():
        if bone.original:
            setBoneName(bone, gen)
    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
    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)

    # 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)
            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)
            for mod in ob.modifiers:
                if mod.type == 'ARMATURE' and mod.object == rig:

    # Parent widgets under empty
    empty = bpy.data.objects.new("Widgets", None)
    scn.objects.link(empty)
    empty.layers = 20*[False]
    empty.layers[19] = True
    for ob in scn.objects:
        if ob.type == 'MESH' and ob.name[0:4] == "WGT-" and not ob.parent:
            ob.parent = empty
    gen.show_x_ray = True
    gen.data.draw_type = 'STICK'
    name = rig.name
    scn.objects.unlink(rig)
    del rig
    gen.name = name
    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")
    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))
    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]

#
#   class OBJECT_OT_RigifyMhxButton(bpy.types.Operator):
#

class OBJECT_OT_RigifyMhxButton(bpy.types.Operator):
    bl_idname = "mhxrig.rigify_mhx"
    bl_label = "Rigify MHX rig"

    def execute(self, context):
#
#   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):
Thomas Dinges's avatar
Thomas Dinges committed
        self.layout.operator("mhxrig.rigify_mhx")
        return

###################################################################################
Brendon Murphy's avatar
Brendon Murphy committed
#
#    Error popup
Brendon Murphy's avatar
Brendon Murphy committed
#
###################################################################################
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
            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)"""
Luca Bonavita's avatar
Luca Bonavita committed
    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'}
Luca Bonavita's avatar
Luca Bonavita committed

    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)

Luca Bonavita's avatar
Luca Bonavita committed
    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
        print("execute flags %x" % toggle)
        theScale = self.scale
        #filepathname = self.filepath.encode('utf-8', 'strict')
            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)
            print("Error when loading MHX file %s:\n" % self.filepath + theMessage)
        if self.advanced:
            writeDefaults()
            self.advanced = False
Luca Bonavita's avatar
Luca Bonavita committed
        return {'FINISHED'}

Luca Bonavita's avatar
Luca Bonavita committed
    def invoke(self, context, event):
        global toggle, theScale, MhxBoolProps
        self.scale = theScale
        for (prop, name, desc, flag) in MhxBoolProps:
            setattr(self, prop, mhxEval('(toggle&%s != 0)' % flag))
Luca Bonavita's avatar
Luca Bonavita committed
        context.window_manager.fileselect_add(self)
        return {'RUNNING_MODAL'}
###################################################################################
#
#    Main panel
#