~ubuntu-branches/ubuntu/trusty/blender/trusty

« back to all changes in this revision

Viewing changes to release/scripts/addons/io_export_unreal_psk_psa.py

  • Committer: Package Import Robot
  • Author(s): Matteo F. Vescovi
  • Date: 2012-05-12 20:02:22 UTC
  • mfrom: (14.2.16 sid)
  • Revision ID: package-import@ubuntu.com-20120512200222-lznjs2cxzaq96wua
Tags: 2.63a-1
* New upstream bugfix release
  + debian/patches/: re-worked since source code changed

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 
19
19
bl_info = {
20
20
    "name": "Export Unreal Engine Format(.psk/.psa)",
21
 
    "author": "Darknet/Optimus_P-Fat/Active_Trash/Sinsoft/VendorX",
22
 
    "version": (2, 4),
23
 
    "blender": (2, 6, 2),
 
21
    "author": "Darknet/Optimus_P-Fat/Active_Trash/Sinsoft/VendorX/Spoof",
 
22
    "version": (2, 5),
 
23
    "blender": (2, 6, 3),
24
24
    "api": 36079,
25
25
    "location": "File > Export > Skeletal Mesh/Animation Data (.psk/.psa)",
26
26
    "description": "Export Skeleletal Mesh/Animation Data",
969
969
        bpy.context.scene.update()
970
970
        return me_ob
971
971
 
 
972
#copy mesh data and then merge them into one object
 
973
def meshmerge(selectedobjects):
 
974
    bpy.ops.object.mode_set(mode='OBJECT')
 
975
    cloneobjects = []
 
976
    if len(selectedobjects) > 1:
 
977
        print("selectedobjects:",len(selectedobjects))
 
978
        count = 0 #reset count
 
979
        for count in range(len( selectedobjects)):
 
980
            #print("Index:",count)
 
981
            if selectedobjects[count] != None:
 
982
                me_da = selectedobjects[count].data.copy() #copy data
 
983
                me_ob = selectedobjects[count].copy() #copy object
 
984
                #note two copy two types else it will use the current data or mesh
 
985
                me_ob.data = me_da
 
986
                bpy.context.scene.objects.link(me_ob)#link the object to the scene #current object location
 
987
                print("Index:",count,"clone object",me_ob.name)
 
988
                cloneobjects.append(me_ob)
 
989
        #bpy.ops.object.mode_set(mode='OBJECT')
 
990
        for i in bpy.data.objects: i.select = False #deselect all objects
 
991
        count = 0 #reset count
 
992
        #bpy.ops.object.mode_set(mode='OBJECT')
 
993
        for count in range(len( cloneobjects)):
 
994
            if count == 0:
 
995
                bpy.context.scene.objects.active = cloneobjects[count]
 
996
                print("Set Active Object:",cloneobjects[count].name)
 
997
            cloneobjects[count].select = True
 
998
        bpy.ops.object.join()
 
999
        if len(cloneobjects) > 1:
 
1000
            bpy.types.Scene.udk_copy_merge = True
 
1001
    return cloneobjects[0]
 
1002
        
 
1003
#sort the mesh center top list and not center at the last array. Base on order while select to merge mesh to make them center.
 
1004
def sortmesh(selectmesh):
 
1005
        print("MESH SORTING...")
 
1006
        centermesh = []
 
1007
        notcentermesh = []
 
1008
        for countm in range(len(selectmesh)):
 
1009
                if selectmesh[countm].location.x == 0 and selectmesh[countm].location.y == 0 and selectmesh[countm].location.z == 0:
 
1010
                        centermesh.append(selectmesh[countm])
 
1011
                else:
 
1012
                        notcentermesh.append(selectmesh[countm])
 
1013
        selectmesh = []
 
1014
        for countm in range(len(centermesh)):
 
1015
                selectmesh.append(centermesh[countm])
 
1016
        for countm in range(len(notcentermesh)):
 
1017
                selectmesh.append(notcentermesh[countm])
 
1018
        if len(selectmesh) == 1:
 
1019
                return selectmesh[0]
 
1020
        else:
 
1021
                return meshmerge(selectmesh)
972
1022
 
973
1023
#===========================================================================
974
1024
# parse_mesh
981
1031
        scene = bpy.context.scene
982
1032
        for i in scene.objects: i.select = False # deselect all objects
983
1033
        scene.objects.active    = mesh
 
1034
        setmesh = mesh
984
1035
        mesh = triangulate_mesh(mesh)
 
1036
        if bpy.types.Scene.udk_copy_merge == True:
 
1037
                bpy.context.scene.objects.unlink(setmesh)
985
1038
        #print("FACES----:",len(mesh.data.tessfaces))
986
1039
        verbose("Working mesh object: {}".format(mesh.name))
987
1040
        
1547
1600
        
1548
1601
        # TODO:
1549
1602
        # this could be more intuitive
1550
 
 
 
1603
        bpy.ops.object.mode_set(mode='OBJECT')
1551
1604
        # try the active object
1552
1605
        if active_object and active_object.type == 'ARMATURE':
1553
1606
                armature = active_object
1567
1620
        
1568
1621
        verbose("Found armature: {}".format(armature.name))
1569
1622
        
1570
 
        
 
1623
        meshselected = []
 
1624
        parented_meshes = [obj for obj in armature.children if obj.type == 'MESH']
 
1625
        for obj in armature.children:
 
1626
                #print(dir(obj))
 
1627
                if obj.type == 'MESH' and obj.select == True:
 
1628
                        meshselected.append(obj)
1571
1629
        # try the active object
1572
 
        if active_object and active_object.type == 'MESH':
1573
 
                
 
1630
        if active_object and active_object.type == 'MESH' and len(meshselected) == 0:
 
1631
        
1574
1632
                if active_object.parent == armature:
1575
1633
                        mesh = active_object
1576
1634
                
1579
1637
        
1580
1638
        # otherwise, expect a single mesh parented to the armature (other object types are ignored)
1581
1639
        else:
1582
 
                parented_meshes = [obj for obj in armature.children if obj.type == 'MESH']
1583
1640
                print("Number of meshes:",len(parented_meshes))
 
1641
                print("Number of meshes (selected):",len(meshselected))
1584
1642
                if len(parented_meshes) == 1:
1585
1643
                        mesh = parented_meshes[0]
1586
1644
                        
1587
1645
                elif len(parented_meshes) > 1:
1588
 
                        raise Error("More than one mesh parented to armature")
1589
 
                        
 
1646
                        if len(meshselected) >= 1:
 
1647
                                mesh = sortmesh(meshselected)
 
1648
                        else:
 
1649
                                raise Error("More than one mesh(s) parented to armature. Select object(s)!")
1590
1650
                else:
1591
1651
                        raise Error("No mesh parented to armature")
1592
1652
                
1613
1673
                verbose("  " + group.name)
1614
1674
        
1615
1675
        return groups
1616
 
 
1617
 
 
 
1676
                
1618
1677
#===========================================================================
1619
1678
# Main
1620
1679
#===========================================================================
1621
1680
def export(filepath):
1622
1681
        print(header("Export", 'RIGHT'))
1623
 
        
 
1682
        bpy.types.Scene.udk_copy_merge = False #in case fail to export set this to default
1624
1683
        t               = time.clock()
1625
1684
        context = bpy.context
1626
1685
        
1792
1851
                name            = "Clamp UV",
1793
1852
                description     = "Clamp UV co-ordinates to [0-1]",
1794
1853
                default         = False)
 
1854
                
 
1855
bpy.types.Scene.udk_copy_merge = BoolProperty(
 
1856
                name            = "merge mesh",
 
1857
                description     = "Deal with unlinking the mesh to be remove while exporting the object.",
 
1858
                default         = False)
1795
1859
 
1796
1860
bpy.types.Scene.udk_option_export = EnumProperty(
1797
1861
                name            = "Export",
1817
1881
                default         = False)
1818
1882
                
1819
1883
 
 
1884
import bmesh
1820
1885
#===========================================================================
1821
1886
# User interface
1822
1887
#===========================================================================
 
1888
class OBJECT_OT_UTSelectedFaceSmooth(bpy.types.Operator):
 
1889
    bl_idname = "object.utselectfacesmooth"  # XXX, name???
 
1890
    bl_label = "Select Smooth faces"
 
1891
    __doc__ = """It will only select smooth faces that is select mesh"""
 
1892
    
 
1893
    def invoke(self, context, event):
 
1894
        print("----------------------------------------")
 
1895
        print("Init Select Face(s):")
 
1896
        bselected = False
 
1897
        for obj in bpy.data.objects:
 
1898
            if obj.type == 'MESH' and obj.select == True:
 
1899
                smoothcount = 0
 
1900
                flatcount = 0
 
1901
                bpy.ops.object.mode_set(mode='OBJECT')#it need to go into object mode to able to select the faces
 
1902
                for i in bpy.context.scene.objects: i.select = False #deselect all objects
 
1903
                obj.select = True #set current object select
 
1904
                bpy.context.scene.objects.active = obj #set active object
 
1905
                mesh = bmesh.new();
 
1906
                mesh.from_mesh(obj.data)
 
1907
                for face in mesh.faces:
 
1908
                    face.select = False
 
1909
                for face in mesh.faces:
 
1910
                    if face.smooth == True:
 
1911
                        face.select = True
 
1912
                        smoothcount += 1
 
1913
                    else:
 
1914
                        flatcount += 1
 
1915
                        face.select = False
 
1916
                mesh.to_mesh(obj.data)
 
1917
                bpy.context.scene.update()
 
1918
                bpy.ops.object.mode_set(mode='EDIT')
 
1919
                print("Select Smooth Count(s):",smoothcount," Flat Count(s):",flatcount)
 
1920
                bselected = True
 
1921
                break
 
1922
        if bselected:
 
1923
            print("Selected Face(s) Exectue!")
 
1924
            self.report({'INFO'}, "Selected Face(s) Exectue!")
 
1925
        else:
 
1926
            print("Didn't select Mesh Object!")
 
1927
            self.report({'INFO'}, "Didn't Select Mesh Object!")
 
1928
        print("----------------------------------------")        
 
1929
        return{'FINISHED'}
 
1930
                
 
1931
class OBJECT_OT_MeshClearWeights(bpy.types.Operator):
 
1932
    bl_idname = "object.meshclearweights"  # XXX, name???
 
1933
    bl_label = "Remove Mesh vertex weights"
 
1934
    __doc__ = """Remove all mesh vertex groups weights for the bones."""
 
1935
    
 
1936
    def invoke(self, context, event):
 
1937
        for obj in bpy.data.objects:
 
1938
            if obj.type == 'MESH' and obj.select == True:
 
1939
                for vg in obj.vertex_groups:
 
1940
                    obj.vertex_groups.remove(vg)
 
1941
                self.report({'INFO'}, "Mesh Vertex Groups Remove!")
 
1942
                break                   
 
1943
        return{'FINISHED'}
 
1944
 
 
1945
def unpack_list(list_of_tuples):
 
1946
    l = []
 
1947
    for t in list_of_tuples:
 
1948
        l.extend(t)
 
1949
    return l
 
1950
        
 
1951
class OBJECT_OT_UTRebuildMesh(bpy.types.Operator):
 
1952
    bl_idname = "object.utrebuildmesh"  # XXX, name???
 
1953
    bl_label = "Rebuild Mesh"
 
1954
    __doc__ = """It rebuild the mesh from scrape from the selected mesh object. Note the scale will be 1:1 for object mode. To keep from deforming"""
 
1955
    
 
1956
    def invoke(self, context, event):
 
1957
        print("----------------------------------------")
 
1958
        print("Init Mesh Bebuild...")
 
1959
        bselected = False
 
1960
        for obj in bpy.data.objects:
 
1961
            if obj.type == 'MESH' and obj.select == True:
 
1962
                for i in bpy.context.scene.objects: i.select = False #deselect all objects
 
1963
                obj.select = True
 
1964
                bpy.context.scene.objects.active = obj
 
1965
                bpy.ops.object.mode_set(mode='OBJECT')
 
1966
                me_ob = bpy.data.meshes.new(("Re_"+obj.name))
 
1967
                mesh = obj.data
 
1968
                faces = []
 
1969
                verts = []
 
1970
                smoothings = []
 
1971
                uvfaces = []
 
1972
                print("creating array build mesh...")
 
1973
                mmesh = obj.to_mesh(bpy.context.scene,True,'PREVIEW')
 
1974
                uv_layer = mmesh.tessface_uv_textures.active
 
1975
                for face in mmesh.tessfaces:
 
1976
                    smoothings.append(face.use_smooth)#smooth or flat in boolean
 
1977
                    if uv_layer != None:#check if there texture data exist
 
1978
                        faceUV = uv_layer.data[face.index]
 
1979
                        uvs = []
 
1980
                        for uv in faceUV.uv:
 
1981
                            uvs.append((uv[0],uv[1]))
 
1982
                        uvfaces.append(uvs)
 
1983
                    print((face.vertices[:]))
 
1984
                    if len(face.vertices) == 3:
 
1985
                        faces.extend([(face.vertices[0],face.vertices[1],face.vertices[2],0)])
 
1986
                    else:
 
1987
                        faces.extend([(face.vertices[0],face.vertices[1],face.vertices[2],face.vertices[3])])
 
1988
                #vertex positions
 
1989
                for vertex in mesh.vertices:
 
1990
                    verts.append(vertex.co.to_tuple())                          
 
1991
                #vertices weight groups into array
 
1992
                vertGroups = {} #array in strings
 
1993
                for vgroup in obj.vertex_groups:
 
1994
                    vlist = []
 
1995
                    for v in mesh.vertices:
 
1996
                        for vg in v.groups:
 
1997
                            if vg.group == vgroup.index:
 
1998
                                vlist.append((v.index,vg.weight))
 
1999
                                #print((v.index,vg.weight))
 
2000
                    vertGroups[vgroup.name] = vlist
 
2001
                
 
2002
                print("creating mesh object...")
 
2003
                #me_ob.from_pydata(verts, [], faces)
 
2004
                me_ob.vertices.add(len(verts))
 
2005
                me_ob.tessfaces.add(len(faces))
 
2006
                me_ob.vertices.foreach_set("co", unpack_list(verts)) 
 
2007
                me_ob.tessfaces.foreach_set("vertices_raw",unpack_list( faces))
 
2008
                me_ob.tessfaces.foreach_set("use_smooth", smoothings)#smooth array from face
 
2009
                
 
2010
                #check if there is uv faces
 
2011
                if len(uvfaces) > 0:
 
2012
                    uvtex = me_ob.tessface_uv_textures.new(name="retex")
 
2013
                    for i, face in enumerate(me_ob.tessfaces):
 
2014
                        blender_tface = uvtex.data[i] #face
 
2015
                        mfaceuv = uvfaces[i]
 
2016
                        if len(mfaceuv) == 3:
 
2017
                            blender_tface.uv1 = mfaceuv[0];
 
2018
                            blender_tface.uv2 = mfaceuv[1];
 
2019
                            blender_tface.uv3 = mfaceuv[2];
 
2020
                        if len(mfaceuv) == 4:
 
2021
                            blender_tface.uv1 = mfaceuv[0];
 
2022
                            blender_tface.uv2 = mfaceuv[1];
 
2023
                            blender_tface.uv3 = mfaceuv[2];
 
2024
                            blender_tface.uv4 = mfaceuv[3];
 
2025
                
 
2026
                me_ob.update()#need to update the information to able to see into the secne
 
2027
                obmesh = bpy.data.objects.new(("Re_"+obj.name),me_ob)
 
2028
                bpy.context.scene.update()
 
2029
                #Build tmp materials
 
2030
                materialname = "ReMaterial"
 
2031
                for matcount in mesh.materials:
 
2032
                    matdata = bpy.data.materials.new(materialname)
 
2033
                    me_ob.materials.append(matdata)
 
2034
                #assign face to material id
 
2035
                for face in mesh.tessfaces:
 
2036
                    me_ob.faces[face.index].material_index = face.material_index
 
2037
                #vertices weight groups
 
2038
                for vgroup in vertGroups:
 
2039
                    group = obmesh.vertex_groups.new(vgroup)
 
2040
                    for v in vertGroups[vgroup]:
 
2041
                        group.add([v[0]], v[1], 'ADD')# group.add(array[vertex id],weight,add)
 
2042
                bpy.context.scene.objects.link(obmesh)
 
2043
                print("Mesh Material Count:",len(me_ob.materials))
 
2044
                matcount = 0
 
2045
                print("MATERIAL ID OREDER:")
 
2046
                for mat in me_ob.materials:
 
2047
                    print("-Material:",mat.name,"INDEX:",matcount)
 
2048
                    matcount += 1
 
2049
                print("Object Name:",obmesh.name)
 
2050
                bpy.context.scene.update()
 
2051
                bselected = True
 
2052
                break
 
2053
        if bselected:
 
2054
            self.report({'INFO'}, "Rebuild Mesh Finish!")
 
2055
            print("Finish Mesh Build...")
 
2056
        else:
 
2057
            self.report({'INFO'}, "Didn't Select Mesh Object!")
 
2058
            print("Didn't Select Mesh Object!")
 
2059
        print("----------------------------------------")
 
2060
        return{'FINISHED'}
 
2061
                
 
2062
class OBJECT_OT_UTRebuildArmature(bpy.types.Operator):
 
2063
    bl_idname = "object.utrebuildarmature"  # XXX, name???
 
2064
    bl_label = "Rebuild Armature"
 
2065
    __doc__ = """If mesh is deform when importing to unreal engine try this. It rebuild the bones one at the time by select one armature object scrape to raw setup build. Note the scale will be 1:1 for object mode. To keep from deforming"""
 
2066
    
 
2067
    def invoke(self, context, event):
 
2068
        print("----------------------------------------")
 
2069
        print("Init Rebuild Armature...")
 
2070
        bselected = False
 
2071
        for obj in bpy.data.objects:
 
2072
            if obj.type == 'ARMATURE' and obj.select == True:
 
2073
                currentbone = [] #select armature for roll copy
 
2074
                print("Armature Name:",obj.name)
 
2075
                objectname = "ArmatureDataPSK"
 
2076
                meshname ="ArmatureObjectPSK"
 
2077
                armdata = bpy.data.armatures.new(objectname)
 
2078
                ob_new = bpy.data.objects.new(meshname, armdata)
 
2079
                bpy.context.scene.objects.link(ob_new)
 
2080
                bpy.ops.object.mode_set(mode='OBJECT')
 
2081
                for i in bpy.context.scene.objects: i.select = False #deselect all objects
 
2082
                ob_new.select = True
 
2083
                bpy.context.scene.objects.active = obj
 
2084
                
 
2085
                bpy.ops.object.mode_set(mode='EDIT')
 
2086
                for bone in obj.data.edit_bones:
 
2087
                    if bone.parent != None:
 
2088
                        currentbone.append([bone.name,bone.roll])
 
2089
                    else:
 
2090
                        currentbone.append([bone.name,bone.roll])
 
2091
                bpy.ops.object.mode_set(mode='OBJECT')
 
2092
                for i in bpy.context.scene.objects: i.select = False #deselect all objects
 
2093
                bpy.context.scene.objects.active = ob_new
 
2094
                bpy.ops.object.mode_set(mode='EDIT')
 
2095
                
 
2096
                for bone in obj.data.bones:
 
2097
                    bpy.ops.object.mode_set(mode='EDIT')
 
2098
                    newbone = ob_new.data.edit_bones.new(bone.name)
 
2099
                    newbone.head = bone.head_local
 
2100
                    newbone.tail = bone.tail_local
 
2101
                    for bonelist in currentbone:
 
2102
                        if bone.name == bonelist[0]:
 
2103
                            newbone.roll = bonelist[1]
 
2104
                            break
 
2105
                    if bone.parent != None:
 
2106
                        parentbone = ob_new.data.edit_bones[bone.parent.name]
 
2107
                        newbone.parent = parentbone
 
2108
                print("Bone Count:",len(obj.data.bones))
 
2109
                print("Hold Bone Count",len(currentbone))
 
2110
                print("New Bone Count",len(ob_new.data.edit_bones))
 
2111
                print("Rebuild Armture Finish:",ob_new.name)
 
2112
                bpy.context.scene.update()
 
2113
                bselected = True
 
2114
                break
 
2115
        if bselected:
 
2116
            self.report({'INFO'}, "Rebuild Armature Finish!")
 
2117
        else:
 
2118
            self.report({'INFO'}, "Didn't Select Armature Object!")
 
2119
        print("End of Rebuild Armature.")
 
2120
        print("----------------------------------------")
 
2121
        return{'FINISHED'}
 
2122
 
 
2123
 
1823
2124
class Panel_UDKExport( bpy.types.Panel ):
1824
2125
 
1825
2126
        bl_label                = "UDK Export"
1856
2157
                row = layout.row()
1857
2158
                row.label(text="Active object: " + object_name)
1858
2159
 
1859
 
                layout.separator()
 
2160
                #layout.separator()
1860
2161
 
1861
2162
                layout.prop(context.scene, "udk_option_filename_src")
1862
2163
                row = layout.row()
1863
2164
                row.label(text=path)
1864
2165
 
1865
 
                layout.separator()
 
2166
                #layout.separator()
1866
2167
 
1867
2168
                layout.prop(context.scene, "udk_option_export")
1868
2169
                layout.operator("object.udk_export")
1869
2170
                
1870
 
                layout.separator()
 
2171
                #layout.separator()
1871
2172
                
1872
2173
                layout.operator("object.toggle_console")
 
2174
                layout.operator(OBJECT_OT_UTRebuildArmature.bl_idname)
 
2175
                layout.operator(OBJECT_OT_MeshClearWeights.bl_idname)
 
2176
                layout.operator(OBJECT_OT_UTSelectedFaceSmooth.bl_idname)
 
2177
                layout.operator(OBJECT_OT_UTRebuildMesh.bl_idname)
1873
2178
 
1874
 
                layout.separator()
 
2179
                #layout.separator()
1875
2180
 
1876
2181
class ExportUDKAnimData(bpy.types.Operator):
1877
2182
    
1931
2236
def menu_func(self, context):
1932
2237
    default_path = os.path.splitext(bpy.data.filepath)[0] + ".psk"
1933
2238
    self.layout.operator(ExportUDKAnimData.bl_idname, text="Skeleton Mesh / Animation Data (.psk/.psa)").filepath = default_path
 
2239
 
1934
2240
#===========================================================================
1935
2241
# Entry
1936
2242
#===========================================================================
1951
2257
        
1952
2258
#loader
1953
2259
#filename = "D:/Projects/BlenderScripts/io_export_udk_psa_psk_alpha.py"
1954
 
#exec(compile(open(filename).read(), filename, 'exec'))
 
 
b'\\ No newline at end of file'
 
2260
#exec(compile(open(filename).read(), filename, 'exec'))