Skip to content
Snippets Groups Projects
io_import_scene_mhx.py 67.5 KiB
Newer Older
  • Learn to ignore specific revisions
  • Luca Bonavita's avatar
    Luca Bonavita committed
    #
    #    parseProcess(args, tokens):
    #    applyTransform(objects, rig, parents):
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    #
    
    def parseProcess(args, tokens):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        if toggle & T_Bend == 0:
            return
        try:
            rig = loadedData['Object'][args[0]]
        except:
            rig = None
        if not rig:
            return
    
        parents = {}
        objects = []
    
        for (key, val, sub) in tokens:
            #print(key, val)
            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':
                axis = val[1]
                angle = float(val[2])
                mat = mathutils.Matrix.Rotation(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]
                except:
                    print("No bone "+val[0])
                    pass
            elif key == 'Snap':
                try:
                    eb = ebones[val[0]]
                except:
                    eb = None
                tb = ebones[val[1]]
                typ = val[2]
                if eb == None:
                    pass
                elif typ == 'Inv':
                    eb.head = tb.tail
                    eb.tail = tb.head
                elif typ == 'Head':
                    eb.head = tb.head
                elif typ == 'Tail':
                    eb.tail = tb.tail
                elif typ == 'Both':
                    eb.head = tb.head
                    eb.tail = tb.tail
                    eb.roll = tb.roll
                else:
                    raise NameError("Snap type %s" % typ)
            elif key == 'PoseMode':
                bpy.context.scene.objects.active = rig
                bpy.ops.object.mode_set(mode='POSE')
                pbones = rig.pose.bones    
            elif key == 'ObjectMode':
                bpy.context.scene.objects.active = rig
                bpy.ops.object.mode_set(mode='POSE')
                pbones = rig.pose.bones    
            elif key == 'EditMode':
                bpy.context.scene.objects.active = rig
                bpy.ops.object.mode_set(mode='EDIT')
                ebones = rig.data.edit_bones    
                bpy.ops.armature.select_all(action='DESELECT')
            elif key == 'Roll':
                try:
                    eb = ebones[val[0]]
                except:
                    eb = None
                if eb:
                    eb.roll = float(val[1])
            elif key == 'Select':
                pass
            elif key == 'RollUp':
                pass
            elif key == 'Apply':
                applyTransform(objects, rig, parents)
            elif key == 'ApplyArmature':
                try:
                    ob = loadedData['Object'][val[0]]
                    objects.append((ob,sub))
                except:
                    ob = None
            elif key == 'Object':
                try:
                    ob = loadedData['Object'][val[0]]
                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)
        return
    
    
    def applyTransform(objects, rig, parents):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        for (ob,tokens) in objects:
            print("Applying transform to %s" % ob)
            bpy.context.scene.objects.active = ob        
            bpy.ops.object.visual_transform_apply()
            bpy.ops.object.modifier_apply(apply_as='DATA', modifier='Armature')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        bpy.context.scene.objects.active = rig
        bpy.ops.object.mode_set(mode='POSE')
        bpy.ops.pose.armature_apply()
        bpy.ops.object.mode_set(mode='OBJECT')
        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.use_connect:
                par.tail = eb.head
            eb.parent = par
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        bpy.ops.object.mode_set(mode='OBJECT')
        return            
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    defaultKey(ext, args, tokens, var, exclude, glbals, lcals):
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    #
    
    def defaultKey(ext, args, tokens, var, exclude, glbals, lcals):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        global todo
    
        if ext == 'Property':
            try:
                expr = "%s['%s'] = %s" % (var, args[0], args[1])
            except:
                expr = None
            # print("Property", expr)
            if expr:
                exec(expr, glbals, lcals)
            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:
            pushOnTodoList(var, expr, glbals, lcals)
        return
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        global todo
        print("Tdo", var)
        print(dir(eval(var, glbals, lcals)))
        raise NameError("Todo", expr)
        todo.append((expr, glbals, lcals))
        return
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                
    
    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:
            if c == '0':            
                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 = Matrix()
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        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
    
    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
        for (key, val, sub) in tokens:    
            if key in subkeys.keys():
                for (key2, val2, sub2) in sub:
                    defaultKey(key2, val2, sub2, "data.%s" % subkeys[key], [], globals(), locals())
            else:
                defaultKey(key, val, sub, "data", exclude, globals(), locals())
    
    
    def parseCollection(data, tokens, exclude):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        return
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    Utilities    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    extractBpyType(data):
    
    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:
            raise NameError("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
        res = eval(condition, globals())
        try:
            res = eval(condition, globals())
            #print("%s = %s" % (condition, res))
            return not res
        except:
            #print("%s invalid!" % condition)
            return True
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    clearScene(context):
    #    hideLayers():
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        
    
    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
        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" or ob.type == 'EMPTY':
                scn.objects.active = ob
                bpy.ops.object.mode_set(mode='OBJECT')
                scn.objects.unlink(ob)
                del ob
        #print(scn.objects)
        return scn
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    def hideLayers():
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        scn = bpy.context.scene
        for n in range(len(scn.layers)):
            if n < 8:
                scn.layers[n] = True
            else:
                scn.layers[n] = False
        return
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    User interface
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    #
    
    DEBUG= False
    from bpy.props import *
    
    class IMPORT_OT_makehuman_mhx(bpy.types.Operator):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        '''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"
    
        filepath = StringProperty(name="File Path", description="File path used for importing the MHX file", maxlen= 1024, default= "")
    
        scale = FloatProperty(name="Scale", description="Default meter, decimeter = 1.0", default = theScale)
    
    
    
        enforce = BoolProperty(name="Enforce version", description="Only accept MHX files of correct version", default=toggle&T_EnforceVersion)
        mesh = BoolProperty(name="Mesh", description="Use main mesh", default=toggle&T_Mesh)
        proxy = BoolProperty(name="Proxies", description="Use proxies", default=toggle&T_Proxy)
        armature = BoolProperty(name="Armature", description="Use armature", default=toggle&T_Armature)
        replace = BoolProperty(name="Replace scene", description="Replace scene", default=toggle&T_Replace)
        cage = BoolProperty(name="Cage", description="Load mesh deform cage", default=toggle&T_Cage)
        clothes = BoolProperty(name="Clothes", description="Include clothes", default=toggle&T_Clothes)
        stretch = BoolProperty(name="Stretchy limbs", description="Stretchy limbs", default=toggle&T_Stretch)
        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)
        diamond = BoolProperty(name="Diamonds", description="Keep joint diamonds", default=toggle&T_Diamond)
        bend = BoolProperty(name="Bend joints", description="Bend joints for better IK", default=toggle&T_Bend)
            
        def execute(self, context):
            global toggle
            O_EnforceVersion = T_EnforceVersion if self.properties.enforce else 0
            O_Mesh = T_Mesh if self.properties.mesh else 0
            O_Proxy = T_Proxy if self.properties.proxy else 0
            O_Armature = T_Armature if self.properties.armature else 0
            O_Replace = T_Replace if self.properties.replace else 0
            O_Cage = T_Cage if self.properties.cage else 0
            O_Clothes = T_Clothes if self.properties.clothes else 0
            O_Stretch = T_Stretch if self.properties.stretch 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_Diamond = T_Diamond if self.properties.diamond else 0
            O_Bend = T_Bend if self.properties.bend else 0
            toggle = ( O_EnforceVersion | O_Mesh | O_Proxy | O_Armature | O_Replace | O_Stretch | O_Cage | 
                    O_Face | O_Shape | O_Symm | O_Diamond | O_Bend | O_Clothes | T_MHX )
    
            print("Load", self.properties.filepath)
            readMhxFile(self.properties.filepath, self.properties.scale)
            return {'FINISHED'}
    
        def invoke(self, context, event):
            context.window_manager.fileselect_add(self)
            return {'RUNNING_MODAL'}
    
    
    def menu_func(self, context):
        self.layout.operator(IMPORT_OT_makehuman_mhx.bl_idname, text="MakeHuman (.mhx)...")
    
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    def register():
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        bpy.types.INFO_MT_file_import.append(menu_func)
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    def unregister():
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        bpy.types.INFO_MT_file_import.remove(menu_func)
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    
    if __name__ == "__main__":
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        try:
            unregister()
        except:
            pass
        register()
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    #    Testing
    
    Brendon Murphy's avatar
    Brendon Murphy committed
    #
    """
    
    #readMhxFile("C:/Documents and Settings/xxxxxxxxxxxxxxxxxxxx/Mina dokument/makehuman/exports/foo-25.mhx", 'Classic')
    readMhxFile("/home/thomas/makehuman/exports/foo-25.mhx", 1.0)
    
    #toggle = T_Replace + T_Mesh + T_Armature + T_MHX
    #readMhxFile("/home/thomas/myblends/test.mhx", 1.0)
    """