Newer
Older
# ***** GPL LICENSE BLOCK *****
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# All rights reserved.
# ***** GPL LICENSE BLOCK *****
"name": "DirectX Model Format (.x)",
"version": (2, 1, 2),
"blender": (2, 5, 8),
"api": 37702,
"location": "File > Export > DirectX (.x)",
"description": "Export DirectX Model Format (.x)",
"wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
"tracker_url": "https://projects.blender.org/tracker/index.php?"\
from math import radians
import bpy
from mathutils import *
#Container for the exporter settings
class DirectXExporterSettings:
def __init__(self,
context,
FilePath,
CoordinateSystem=1,
RotateX=True,
FlipNormals=False,
ApplyModifiers=False,
IncludeFrameRate=False,
ExportTextures=True,
ExportArmatures=False,
ExportAnimation=0,
ExportMode=1,
Verbose=False):
self.context = context
self.FilePath = FilePath
self.CoordinateSystem = int(CoordinateSystem)
self.RotateX = RotateX
self.FlipNormals = FlipNormals
self.ApplyModifiers = ApplyModifiers
self.IncludeFrameRate = IncludeFrameRate
self.ExportTextures = ExportTextures
self.ExportArmatures = ExportArmatures
self.ExportAnimation = int(ExportAnimation)
self.ExportMode = int(ExportMode)
self.Verbose = Verbose
def ReplaceSet(String, OldSet, NewChar):
for OldChar in OldSet:
String = String.replace(OldChar, NewChar)
return String
import string
NewName = ReplaceSet(Name, string.punctuation + " ", "_")
if NewName[0].isdigit() or NewName in ["ARRAY",
"DWORD",
"UCHAR",
"BINARY",
"FLOAT",
"ULONGLONG",
"BINARY_RESOURCE",
"SDWORD",
"UNICODE",
"CHAR",
"STRING",
"WORD",
"CSTRING",
"SWORD",
"DOUBLE",
"TEMPLATE"]:
NewName = "_" + NewName
def ExportDirectX(Config):
print("----------\nExporting to {}".format(Config.FilePath))
print("Opening File...")
Config.File = open(Config.FilePath, "w")
if Config.Verbose:
print("Done")
if Config.Verbose:
print("Generating Object list for export... (Root parents only)")
if Config.ExportMode == 1:
Config.ExportList = [Object for Object in Config.context.scene.objects
if Object.type in {'ARMATURE', 'EMPTY', 'MESH'}
ExportList = [Object for Object in Config.context.selected_objects
if Object.type in {'ARMATURE', 'EMPTY', 'MESH'}]
Config.ExportList = [Object for Object in ExportList
if Object.parent not in ExportList]
if Config.Verbose:
print(" List: {}\nDone".format(Config.ExportList))
print("Setting up...")
Config.SystemMatrix = Matrix()
Config.SystemMatrix *= Matrix.Rotation(radians(-90), 4, "X")
if Config.CoordinateSystem == 1:
Config.SystemMatrix *= Matrix.Scale(-1, 4, Vector((0, 1, 0)))
CurrentFrame = bpy.context.scene.frame_current
bpy.context.scene.frame_current = bpy.context.scene.frame_current
if Config.Verbose:
print("Done")
if Config.Verbose:
print("Writing Header...")
if Config.Verbose:
print("Done")
Config.Whitespace = 0
if Config.Verbose:
print("Writing Root Frame...")
WriteRootFrame(Config)
if Config.Verbose:
print("Done")
Config.ObjectList = []
if Config.Verbose:
print("Writing Objects...")
WriteObjects(Config, Config.ExportList)
if Config.Verbose:
print("Done")
Config.Whitespace -= 1
Config.File.write("{}}} //End of Root Frame\n".format(" " * Config.Whitespace))
if Config.Verbose:
print("Objects Exported: {}".format(Config.ExportList))
if Config.ExportAnimation:
if Config.IncludeFrameRate:
print("Writing Frame Rate...")
Config.File.write("{}AnimTicksPerSecond {{\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
Config.File.write("{}{};\n".format(" " * Config.Whitespace, int(bpy.context.scene.render.fps / bpy.context.scene.render.fps_base)))
Config.Whitespace -= 1
Config.File.write("{}}}\n".format(" " * Config.Whitespace))
if Config.Verbose:
print("Done")
if Config.Verbose:
print("Writing Animation...")
if Config.ExportAnimation==1:
WriteKeyedAnimationSet(Config)
else:
WriteFullAnimationSet(Config)
bpy.context.scene.frame_current = CurrentFrame
if Config.Verbose:
print("Done")
CloseFile(Config)
print("Finished")
def GetObjectChildren(Parent):
return [Object for Object in Parent.children
if Object.type in {'ARMATURE', 'EMPTY', 'MESH'}]
#Returns the vertex count of Mesh, counting each vertex for every face.
def GetMeshVertexCount(Mesh):
#Returns the file path of first image texture from Material.
def GetMaterialTexture(Material):
if Material:
#Create a list of Textures that have type "IMAGE"
ImageTextures = [Material.texture_slots[TextureSlot].texture for TextureSlot in Material.texture_slots.keys() if Material.texture_slots[TextureSlot].texture.type == "IMAGE"]
#Refine a new list with only image textures that have a file source
ImageFiles = [bpy.path.basename(Texture.image.filepath) for Texture in ImageTextures if getattr(Texture.image, "source", "") == "FILE"]
if ImageFiles:
return ImageFiles[0]
return None
def WriteHeader(Config):
Config.File.write("xof 0303txt 0032\n\n")
Chris Foster
committed
if Config.IncludeFrameRate:
Config.File.write("template AnimTicksPerSecond {\n\
<9E415A43-7BA6-4a73-8743-B73D47E88476>\n\
DWORD AnimTicksPerSecond;\n\
}\n\n")
if Config.ExportArmatures:
Config.File.write("template XSkinMeshHeader {\n\
<3cf169ce-ff7c-44ab-93c0-f78f62d172e2>\n\
WORD nMaxSkinWeightsPerVertex;\n\
WORD nMaxSkinWeightsPerFace;\n\
WORD nBones;\n\
}\n\n\
template SkinWeights {\n\
<6f0d123b-bad2-4167-a0d0-80224f25fabb>\n\
STRING transformNodeName;\n\
DWORD nWeights;\n\
array DWORD vertexIndices[nWeights];\n\
array float weights[nWeights];\n\
Matrix4x4 matrixOffset;\n\
}\n\n")
def WriteRootFrame(Config):
Config.File.write("{}Frame Root {{\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
Config.File.write("{}FrameTransformMatrix {{\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
Config.File.write("{}{:9f},{:9f},{:9f},{:9f},\n".format(" " * Config.Whitespace, Config.SystemMatrix[0][0], Config.SystemMatrix[0][1], Config.SystemMatrix[0][2], Config.SystemMatrix[0][3]))
Config.File.write("{}{:9f},{:9f},{:9f},{:9f},\n".format(" " * Config.Whitespace, Config.SystemMatrix[1][0], Config.SystemMatrix[1][1], Config.SystemMatrix[1][2], Config.SystemMatrix[1][3]))
Config.File.write("{}{:9f},{:9f},{:9f},{:9f},\n".format(" " * Config.Whitespace, Config.SystemMatrix[2][0], Config.SystemMatrix[2][1], Config.SystemMatrix[2][2], Config.SystemMatrix[2][3]))
Config.File.write("{}{:9f},{:9f},{:9f},{:9f};;\n".format(" " * Config.Whitespace, Config.SystemMatrix[3][0], Config.SystemMatrix[3][1], Config.SystemMatrix[3][2], Config.SystemMatrix[3][3]))
Config.Whitespace -= 1
Config.File.write("{}}}\n".format(" " * Config.Whitespace))
def WriteObjects(Config, ObjectList):
Config.ObjectList += ObjectList
if Config.Verbose:
print(" Writing Object: {}...".format(Object.name))
Config.File.write("{}Frame {} {{\n".format(" " * Config.Whitespace, LegalName(Object.name)))
Config.Whitespace += 1
if Config.Verbose:
print(" Writing Local Matrix...")
WriteLocalMatrix(Config, Object)
if Config.Verbose:
print(" Done")
if Config.ExportArmatures and Object.type == "ARMATURE":
Armature = Object.data
ParentList = [Bone for Bone in Armature.bones if Bone.parent is None]
if Config.Verbose:
print(" Writing Armature Bones...")
WriteArmatureBones(Config, Object, ParentList)
if Config.Verbose:
print(" Done")
ChildList = GetObjectChildren(Object)
if Config.ExportMode == 2: #Selected Objects Only
ChildList = [Child for Child in ChildList
if Child in Config.context.selected_objects]
if Config.Verbose:
print(" Writing Children...")
WriteObjects(Config, ChildList)
if Config.Verbose:
print(" Done Writing Children")
if Object.type == "MESH":
if Config.Verbose:
print(" Generating Mesh...")
Chris Foster
committed
if Config.ApplyModifiers:
if Config.ExportArmatures:
#Create a copy of the object and remove all armature modifiers so an unshaped
#mesh can be created from it.
Object2 = Object.copy()
for Modifier in [Modifier for Modifier in Object2.modifiers if Modifier.type == "ARMATURE"]:
Object2.modifiers.remove(Modifier)
Mesh = Object2.to_mesh(bpy.context.scene, True, "PREVIEW")
Chris Foster
committed
else:
Mesh = Object.to_mesh(bpy.context.scene, True, "PREVIEW")
Chris Foster
committed
else:
Mesh = Object.to_mesh(bpy.context.scene, False, "PREVIEW")
print(" Done")
print(" Writing Mesh...")
WriteMesh(Config, Object, Mesh)
if Config.Verbose:
print(" Done")
Chris Foster
committed
if Config.ApplyModifiers and Config.ExportArmatures:
bpy.data.objects.remove(Object2)
bpy.data.meshes.remove(Mesh)
Config.Whitespace -= 1
Config.File.write("{}}} //End of {}\n".format(" " * Config.Whitespace, LegalName(Object.name)))
if Config.Verbose:
print(" Done Writing Object: {}".format(Object.name))
def WriteLocalMatrix(Config, Object):
LocalMatrix = Object.matrix_local
Config.File.write("{}FrameTransformMatrix {{\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
Config.File.write("{}{:9f},{:9f},{:9f},{:9f},\n".format(" " * Config.Whitespace, LocalMatrix[0][0], LocalMatrix[0][1], LocalMatrix[0][2], LocalMatrix[0][3]))
Config.File.write("{}{:9f},{:9f},{:9f},{:9f},\n".format(" " * Config.Whitespace, LocalMatrix[1][0], LocalMatrix[1][1], LocalMatrix[1][2], LocalMatrix[1][3]))
Config.File.write("{}{:9f},{:9f},{:9f},{:9f},\n".format(" " * Config.Whitespace, LocalMatrix[2][0], LocalMatrix[2][1], LocalMatrix[2][2], LocalMatrix[2][3]))
Config.File.write("{}{:9f},{:9f},{:9f},{:9f};;\n".format(" " * Config.Whitespace, LocalMatrix[3][0], LocalMatrix[3][1], LocalMatrix[3][2], LocalMatrix[3][3]))
Config.Whitespace -= 1
Config.File.write("{}}}\n".format(" " * Config.Whitespace))
def WriteArmatureBones(Config, Object, ChildList):
PoseBones = Object.pose.bones
print(" Writing Bone: {}...".format(Bone.name))
Config.File.write("{}Frame {} {{\n".format(" " * Config.Whitespace, LegalName(Object.name) + "_" + LegalName(Bone.name)))
Config.Whitespace += 1
PoseBone = PoseBones[Bone.name]
BoneMatrix = PoseBone.parent.matrix.inverted()
BoneMatrix *= PoseBone.matrix
Config.File.write("{}FrameTransformMatrix {{\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
Config.File.write("{}{:9f},{:9f},{:9f},{:9f},\n".format(" " * Config.Whitespace, BoneMatrix[0][0], BoneMatrix[0][1], BoneMatrix[0][2], BoneMatrix[0][3]))
Config.File.write("{}{:9f},{:9f},{:9f},{:9f},\n".format(" " * Config.Whitespace, BoneMatrix[1][0], BoneMatrix[1][1], BoneMatrix[1][2], BoneMatrix[1][3]))
Config.File.write("{}{:9f},{:9f},{:9f},{:9f},\n".format(" " * Config.Whitespace, BoneMatrix[2][0], BoneMatrix[2][1], BoneMatrix[2][2], BoneMatrix[2][3]))
Config.File.write("{}{:9f},{:9f},{:9f},{:9f};;\n".format(" " * Config.Whitespace, BoneMatrix[3][0], BoneMatrix[3][1], BoneMatrix[3][2], BoneMatrix[3][3]))
Config.Whitespace -= 1
Config.File.write("{}}}\n".format(" " * Config.Whitespace))
if Config.Verbose:
print(" Done")
WriteArmatureBones(Config, Object, Bone.children)
Config.Whitespace -= 1
Config.File.write("{}}} //End of {}\n".format(" " * Config.Whitespace, LegalName(Object.name) + "_" + LegalName(Bone.name)))
def WriteMesh(Config, Object, Mesh):
Config.File.write("{}Mesh {{ //{} Mesh\n".format(" " * Config.Whitespace, LegalName(Mesh.name)))
Config.Whitespace += 1
if Config.Verbose:
print(" Writing Mesh Vertices...")
WriteMeshVertices(Config, Mesh)
if Config.Verbose:
print(" Done\n Writing Mesh Normals...")
WriteMeshNormals(Config, Mesh)
if Config.Verbose:
print(" Done\n Writing Mesh Materials...")
WriteMeshMaterials(Config, Mesh)
if Config.Verbose:
print(" Done")
print(" Writing Mesh UV Coordinates...")
WriteMeshUVCoordinates(Config, Mesh)
if Config.Verbose:
print(" Done")
print(" Writing Mesh Skin Weights...")
WriteMeshSkinWeights(Config, Object, Mesh)
if Config.Verbose:
print(" Done")
Config.Whitespace -= 1
Config.File.write("{}}} //End of {} Mesh\n".format(" " * Config.Whitespace, LegalName(Mesh.name)))
def WriteMeshVertices(Config, Mesh):
Index = 0
VertexCount = GetMeshVertexCount(Mesh)
Config.File.write("{}{};\n".format(" " * Config.Whitespace, VertexCount))
if Config.CoordinateSystem == 1:
Vertices = Vertices[::-1]
for Vertex in [Mesh.vertices[Vertex] for Vertex in Vertices]:
Position = Vertex.co
Config.File.write("{}{:9f};{:9f};{:9f};".format(" " * Config.Whitespace, Position[0], Position[1], Position[2]))
Index += 1
if Index == VertexCount:
Config.File.write(";\n")
else:
Config.File.write(",\n")
Index = 0
Config.File.write("{}{};\n".format(" " * Config.Whitespace, len(Mesh.faces)))
Config.File.write("{}{};".format(" " * Config.Whitespace, len(Face.vertices)))
for Vertex in Face.vertices:
Config.File.write("{};".format(Index))
Index += 1
if Index == VertexCount:
Config.File.write(";\n")
else:
Config.File.write(",\n")
def WriteMeshNormals(Config, Mesh):
Config.File.write("{}MeshNormals {{ //{} Normals\n".format(" " * Config.Whitespace, LegalName(Mesh.name)))
Config.Whitespace += 1
Index = 0
VertexCount = GetMeshVertexCount(Mesh)
Config.File.write("{}{};\n".format(" " * Config.Whitespace, VertexCount))
if Config.CoordinateSystem == 1:
Vertices = Vertices[::-1]
for Vertex in [Mesh.vertices[Vertex] for Vertex in Vertices]:
Normal = Vertex.normal
Normal = Face.normal
if Config.FlipNormals:
Normal = -Normal
Config.File.write("{}{:9f};{:9f};{:9f};".format(" " * Config.Whitespace, Normal[0], Normal[1], Normal[2]))
Index += 1
if Index == VertexCount:
Config.File.write(";\n")
else:
Config.File.write(",\n")
Index = 0
Config.File.write("{}{};\n".format(" " * Config.Whitespace, len(Mesh.faces)))
Config.File.write("{}{};".format(" " * Config.Whitespace, len(Face.vertices)))
for Vertex in Face.vertices:
Config.File.write("{};".format(Index))
Index += 1
if Index == VertexCount:
Config.File.write(";\n")
else:
Config.File.write(",\n")
Config.Whitespace -= 1
Config.File.write("{}}} //End of {} Normals\n".format(" " * Config.Whitespace, LegalName(Mesh.name)))
def WriteMeshMaterials(Config, Mesh):
Config.File.write("{}MeshMaterialList {{ //{} Material List\n".format(" " * Config.Whitespace, LegalName(Mesh.name)))
Config.Whitespace += 1
Materials = Mesh.materials
for Face in Mesh.faces:
if Materials[Face.material_index] not in MaterialIndexes:
MaterialIndexes[Materials[Face.material_index]] = len(MaterialIndexes)
FaceCount = len(Mesh.faces)
Index = 0
Config.File.write("{}{};\n{}{};\n".format(" " * Config.Whitespace, len(MaterialIndexes), " " * Config.Whitespace, FaceCount))
Config.File.write("{}{}".format(" " * Config.Whitespace, MaterialIndexes[Materials[Face.material_index]]))
Index += 1
if Index == FaceCount:
Config.File.write(";;\n")
else:
Config.File.write(",\n")
Materials = [Item[::-1] for Item in MaterialIndexes.items()]
Materials.sort()
for Material in Materials:
WriteMaterial(Config, Material[1])
Config.File.write("{}1;\n{}1;\n{}0;;\n".format(" " * Config.Whitespace, " " * Config.Whitespace, " " * Config.Whitespace))
Config.Whitespace -= 1
Config.File.write("{}}} //End of {} Material List\n".format(" " * Config.Whitespace, LegalName(Mesh.name)))
def WriteMaterial(Config, Material=None):
Config.File.write("{}Material {} {{\n".format(" " * Config.Whitespace, LegalName(Material.name)))
Config.Whitespace += 1
Diffuse = list(Vector(Material.diffuse_color) * Material.diffuse_intensity)
Diffuse.append(Material.alpha)
Specularity = 1000 * (Material.specular_hardness - 1.0) / (511.0 - 1.0) # Map Blender's range of 1 - 511 to 0 - 1000
Specular = list(Vector(Material.specular_color) * Material.specular_intensity)
Config.File.write("{}{:9f};{:9f};{:9f};{:9f};;\n".format(" " * Config.Whitespace, Diffuse[0], Diffuse[1], Diffuse[2], Diffuse[3]))
Config.File.write("{} {:9f};\n".format(" " * Config.Whitespace, Specularity))
Config.File.write("{}{:9f};{:9f};{:9f};;\n".format(" " * Config.Whitespace, Specular[0], Specular[1], Specular[2]))
Config.File.write("{}Material Default_Material {{\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
Config.File.write("{} 0.800000; 0.800000; 0.800000; 0.800000;;\n".format(" " * Config.Whitespace))
Config.File.write("{} 96.078431;\n".format(" " * Config.Whitespace)) # 1000 * (50 - 1) / (511 - 1)
Config.File.write("{} 0.500000; 0.500000; 0.500000;;\n".format(" " * Config.Whitespace))
Config.File.write("{} 0.000000; 0.000000; 0.000000;;\n".format(" " * Config.Whitespace))
Texture = GetMaterialTexture(Material)
if Texture:
Config.File.write("{}TextureFilename {{\"{}\";}}\n".format(" " * Config.Whitespace, Texture))
Config.Whitespace -= 1
Config.File.write("{}}}\n".format(" " * Config.Whitespace))
def WriteMeshUVCoordinates(Config, Mesh):
Config.File.write("{}MeshTextureCoords {{ //{} UV Coordinates\n".format(" " * Config.Whitespace, LegalName(Mesh.name)))
Config.Whitespace += 1
UVCoordinates = None
for UV in Mesh.uv_textures:
if UV.active_render:
Index = 0
VertexCount = GetMeshVertexCount(Mesh)
Config.File.write("{}{};\n".format(" " * Config.Whitespace, VertexCount))
for Vertex in Face.uv:
Vertices.append(tuple(Vertex))
if Config.CoordinateSystem == 1:
Vertices = Vertices[::-1]
Config.File.write("{}{:9f};{:9f};".format(" " * Config.Whitespace, Vertex[0], 1 - Vertex[1]))
Index += 1
if Index == VertexCount:
Config.File.write(";\n")
else:
Config.File.write(",\n")
Config.Whitespace -= 1
Config.File.write("{}}} //End of {} UV Coordinates\n".format(" " * Config.Whitespace, LegalName(Mesh.name)))
def WriteMeshSkinWeights(Config, Object, Mesh):
ArmatureList = [Modifier for Modifier in Object.modifiers if Modifier.type == "ARMATURE"]
ArmatureObject = ArmatureList[0].object
Chris Foster
committed
ArmatureBones = ArmatureObject.data.bones
PoseBones = ArmatureObject.pose.bones
MaxInfluences = 0
UsedBones = set()
#Maps bones to a list of vertices they affect
Campbell Barton
committed
ObjectVertexGroups = {i: Group.name for (i, Group) in enumerate(Object.vertex_groups)}
#BoneInfluences contains the bones of the armature that affect the current vertex
Campbell Barton
committed
BoneInfluences = [PoseBone for Group in Vertex.groups
for PoseBone in (PoseBones.get(ObjectVertexGroups.get(Group.group, "")), )
if PoseBone is not None
]
if len(BoneInfluences) > MaxInfluences:
MaxInfluences = len(BoneInfluences)
for Bone in BoneInfluences:
UsedBones.add(Bone)
if Bone not in VertexGroups:
VertexGroups[Bone] = [Vertex]
else:
VertexGroups[Bone].append(Vertex)
BoneCount = len(UsedBones)
Config.File.write("{}XSkinMeshHeader {{\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
Config.File.write("{}{};\n{}{};\n{}{};\n".format(" " * Config.Whitespace, MaxInfluences, " " * Config.Whitespace, MaxInfluences * 3, " " * Config.Whitespace, BoneCount))
Config.Whitespace -= 1
Config.File.write("{}}}\n".format(" " * Config.Whitespace))
VertexCount = 0
VertexIndexes = [Vertex.index for Vertex in VertexGroups[Bone]]
if Vertex in VertexIndexes:
VertexCount += 1
Config.File.write("{}SkinWeights {{\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
Config.File.write("{}\"{}\";\n{}{};\n".format(" " * Config.Whitespace, LegalName(ArmatureObject.name) + "_" + LegalName(Bone.name), " " * Config.Whitespace, VertexCount))
VertexWeights = []
Index = 0
WrittenIndexes = 0
FaceVertices = list(Face.vertices)
if Config.CoordinateSystem == 1:
FaceVertices = FaceVertices[::-1]
for Vertex in FaceVertices:
if Vertex in VertexIndexes:
Config.File.write("{}{}".format(" " * Config.Whitespace, Index))
Campbell Barton
committed
GroupIndexes = {ObjectVertexGroups.get(Group.group): Index
for Index, Group in enumerate(Mesh.vertices[Vertex].groups)
if ObjectVertexGroups.get(Group.group, "") in PoseBones}
Campbell Barton
committed
for Weight in (Group.weight for Group in Mesh.vertices[Vertex].groups if ObjectVertexGroups.get(Group.group, "") in PoseBones):
VertexWeights.append(Mesh.vertices[Vertex].groups[GroupIndexes[Bone.name]].weight / WeightTotal)
else:
VertexWeights.append(0.0)
WrittenIndexes += 1
if WrittenIndexes == VertexCount:
Config.File.write(";\n")
else:
Config.File.write(",\n")
Index += 1
for Index, Weight in enumerate(VertexWeights):
Config.File.write("{}{:8f}".format(" " * Config.Whitespace, Weight))
if Index == (VertexCount - 1):
Config.File.write(";\n")
else:
Config.File.write(",\n")
Chris Foster
committed
RestBone = ArmatureBones[Bone.name]
#BoneMatrix transforms mesh vertices into the space of the bone.
#Here are the final transformations in order:
# - Object Space to World Space
# - World Space to Armature Space
# - Armature Space to Bone Space (The bone matrix needs to be rotated 90 degrees to align with Blender's world axes)
#This way, when BoneMatrix is transformed by the bone's Frame matrix, the vertices will be in their final world position.
BoneMatrix = RestBone.matrix_local.inverted()
BoneMatrix *= ArmatureObject.matrix_world.inverted()
BoneMatrix *= Object.matrix_world
Config.File.write("{}{:9f},{:9f},{:9f},{:9f},\n".format(" " * Config.Whitespace, BoneMatrix[0][0], BoneMatrix[0][1], BoneMatrix[0][2], BoneMatrix[0][3]))
Config.File.write("{}{:9f},{:9f},{:9f},{:9f},\n".format(" " * Config.Whitespace, BoneMatrix[1][0], BoneMatrix[1][1], BoneMatrix[1][2], BoneMatrix[1][3]))
Config.File.write("{}{:9f},{:9f},{:9f},{:9f},\n".format(" " * Config.Whitespace, BoneMatrix[2][0], BoneMatrix[2][1], BoneMatrix[2][2], BoneMatrix[2][3]))
Config.File.write("{}{:9f},{:9f},{:9f},{:9f};;\n".format(" " * Config.Whitespace, BoneMatrix[3][0], BoneMatrix[3][1], BoneMatrix[3][2], BoneMatrix[3][3]))
Config.Whitespace -= 1
Config.File.write("{}}} //End of {} Skin Weights\n".format(" " * Config.Whitespace, LegalName(ArmatureObject.name) + "_" + LegalName(Bone.name)))
def WriteKeyedAnimationSet(Config):
Config.File.write("{}AnimationSet {{\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
for Object in [Object for Object in Config.ObjectList if Object.animation_data]:
if Config.Verbose:
print(" Writing Animation Data for Object: {}".format(Object.name))
Action = Object.animation_data.action
PositionFCurves = [None, None, None]
RotationFCurves = [None, None, None]
ScaleFCurves = [None, None, None]
for FCurve in Action.fcurves:
if FCurve.data_path == "location":
PositionFCurves[FCurve.array_index] = FCurve
elif FCurve.data_path == "rotation_euler":
RotationFCurves[FCurve.array_index] = FCurve
elif FCurve.data_path == "scale":
ScaleFCurves[FCurve.array_index] = FCurve
if [FCurve for FCurve in PositionFCurves + RotationFCurves + ScaleFCurves if FCurve]:
Config.File.write("{}Animation {{\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
Config.File.write("{}{{{}}}\n".format(" " * Config.Whitespace, LegalName(Object.name)))
print(" Writing Position...")
AllKeyframes = set()
for Index, FCurve in enumerate(PositionFCurves):
for Keyframe in FCurve.keyframe_points:
if Keyframe.co[0] < bpy.context.scene.frame_start:
AllKeyframes.add(bpy.context.scene.frame_start)
elif Keyframe.co[0] > bpy.context.scene.frame_end:
AllKeyframes.add(bpy.context.scene.frame_end)
else:
Keyframes.append(Keyframe.co)
AllKeyframes.add(int(Keyframe.co[0]))
PositionFCurves[Index] = {int(Keyframe): Value for Keyframe, Value in Keyframes}
Config.File.write("{}AnimationKey {{ //Position\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
AllKeyframes = list(AllKeyframes)
AllKeyframes.sort()
if len(AllKeyframes):
Config.File.write("{}2;\n{}{};\n".format(" " * Config.Whitespace, " " * Config.Whitespace, len(AllKeyframes)))
for Keyframe in AllKeyframes:
Position = Vector()
Position[0] = ((PositionFCurves[0][Keyframe] if Keyframe in PositionFCurves[0] else Object.location[0]) if PositionFCurves[0] else Object.location[0])
Position[1] = ((PositionFCurves[1][Keyframe] if Keyframe in PositionFCurves[1] else Object.location[1]) if PositionFCurves[1] else Object.location[1])
Position[2] = ((PositionFCurves[2][Keyframe] if Keyframe in PositionFCurves[2] else Object.location[2]) if PositionFCurves[2] else Object.location[2])
Config.File.write("{}{}{:9f},{:9f},{:9f};;".format(" " * Config.Whitespace, (str(Keyframe - bpy.context.scene.frame_start) + ";3;").ljust(8), Position[0], Position[1], Position[2]))
if Keyframe == AllKeyframes[-1]:
Config.File.write(";\n")
else:
Config.File.write(",\n")
Config.File.write("{}2;\n{}1;\n".format(" " * Config.Whitespace, " " * Config.Whitespace))
bpy.context.scene.frame_set(bpy.context.scene.frame_start)
Position = Object.matrix_local.to_translation()
Config.File.write("{}{}{:9f},{:9f},{:9f};;;\n".format(" " * Config.Whitespace, ("0;3;").ljust(8), Position[0], Position[1], Position[2]))
Config.Whitespace -= 1
Config.File.write("{}}}\n".format(" " * Config.Whitespace))
if Config.Verbose:
print(" Done")
print(" Writing Rotation...")
AllKeyframes = set()
for Index, FCurve in enumerate(RotationFCurves):
for Keyframe in FCurve.keyframe_points:
if Keyframe.co[0] < bpy.context.scene.frame_start:
AllKeyframes.add(bpy.context.scene.frame_start)
elif Keyframe.co[0] > bpy.context.scene.frame_end:
AllKeyframes.add(bpy.context.scene.frame_end)
else:
Keyframes.append(Keyframe.co)
AllKeyframes.add(int(Keyframe.co[0]))
RotationFCurves[Index] = {int(Keyframe): Value for Keyframe, Value in Keyframes}
Config.File.write("{}AnimationKey {{ //Rotation\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
AllKeyframes = list(AllKeyframes)
AllKeyframes.sort()
if len(AllKeyframes):
Config.File.write("{}0;\n{}{};\n".format(" " * Config.Whitespace, " " * Config.Whitespace, len(AllKeyframes)))
for Keyframe in AllKeyframes:
Rotation = Euler()
Rotation[0] = ((RotationFCurves[0][Keyframe] if Keyframe in RotationFCurves[0] else Object.rotation_euler[0]) if RotationFCurves[0] else Object.rotation_euler[0])
Rotation[1] = ((RotationFCurves[1][Keyframe] if Keyframe in RotationFCurves[1] else Object.rotation_euler[1]) if RotationFCurves[1] else Object.rotation_euler[1])
Rotation[2] = ((RotationFCurves[2][Keyframe] if Keyframe in RotationFCurves[2] else Object.rotation_euler[2]) if RotationFCurves[2] else Object.rotation_euler[2])
Chris Foster
committed
Config.File.write("{}{}{:9f},{:9f},{:9f},{:9f};;".format(" " * Config.Whitespace, (str(Keyframe - bpy.context.scene.frame_start) + ";4;").ljust(8), -Rotation[0], Rotation[1], Rotation[2], Rotation[3]))
if Keyframe == AllKeyframes[-1]:
Config.File.write(";\n")
else:
Config.File.write(",\n")
Config.File.write("{}0;\n{}1;\n".format(" " * Config.Whitespace, " " * Config.Whitespace))
bpy.context.scene.frame_set(bpy.context.scene.frame_start)
Rotation = Object.rotation_euler.to_quaternion()
Config.File.write("{}{}{:9f},{:9f},{:9f},{:9f};;;\n".format(" " * Config.Whitespace, ("0;4;").ljust(8), -Rotation[0], Rotation[1], Rotation[2], Rotation[3]))
Config.Whitespace -= 1
Config.File.write("{}}}\n".format(" " * Config.Whitespace))
if Config.Verbose:
print(" Done")
print(" Writing Scale...")
AllKeyframes = set()
for Index, FCurve in enumerate(ScaleFCurves):
for Keyframe in FCurve.keyframe_points:
if Keyframe.co[0] < bpy.context.scene.frame_start:
AllKeyframes.add(bpy.context.scene.frame_start)
elif Keyframe.co[0] > bpy.context.scene.frame_end:
AllKeyframes.add(bpy.context.scene.frame_end)
else:
Keyframes.append(Keyframe.co)
AllKeyframes.add(int(Keyframe.co[0]))
ScaleFCurves[Index] = {int(Keyframe): Value for Keyframe, Value in Keyframes}
Config.File.write("{}AnimationKey {{ //Scale\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
AllKeyframes = list(AllKeyframes)
AllKeyframes.sort()
if len(AllKeyframes):
Config.File.write("{}1;\n{}{};\n".format(" " * Config.Whitespace, " " * Config.Whitespace, len(AllKeyframes)))
for Keyframe in AllKeyframes:
Scale = Vector()
Scale[0] = ((ScaleFCurves[0][Keyframe] if Keyframe in ScaleFCurves[0] else Object.scale[0]) if ScaleFCurves[0] else Object.scale[0])
Scale[1] = ((ScaleFCurves[1][Keyframe] if Keyframe in ScaleFCurves[1] else Object.scale[1]) if ScaleFCurves[1] else Object.scale[1])
Scale[2] = ((ScaleFCurves[2][Keyframe] if Keyframe in ScaleFCurves[2] else Object.scale[2]) if ScaleFCurves[2] else Object.scale[2])
Config.File.write("{}{}{:9f},{:9f},{:9f};;".format(" " * Config.Whitespace, (str(Keyframe - bpy.context.scene.frame_start) + ";3;").ljust(8), Scale[0], Scale[1], Scale[2]))
if Keyframe == AllKeyframes[-1]:
Config.File.write(";\n")
else:
Config.File.write(",\n")
Config.File.write("{}1;\n{}1;\n".format(" " * Config.Whitespace, " " * Config.Whitespace))
bpy.context.scene.frame_set(bpy.context.scene.frame_start)
Scale = Object.matrix_local.to_scale()
Config.File.write("{}{}{:9f},{:9f},{:9f};;;\n".format(" " * Config.Whitespace, ("0;3;").ljust(8), Scale[0], Scale[1], Scale[2]))
Config.Whitespace -= 1
Config.File.write("{}}}\n".format(" " * Config.Whitespace))
if Config.Verbose:
print(" Done")
Config.Whitespace -= 1
Config.File.write("{}}}\n".format(" " * Config.Whitespace))
if Config.Verbose:
print(" Object has no useable animation data.")
if Config.ExportArmatures and Object.type == "ARMATURE":
if Config.Verbose:
print(" Writing Armature Bone Animation Data...")
PoseBones = Object.pose.bones
if Config.Verbose:
print(" Writing Bone: {}...".format(Bone.name))
PositionFCurves = [None, None, None]
RotationFCurves = [None, None, None, None]
ScaleFCurves = [None, None, None]
for FCurve in Action.fcurves:
if FCurve.data_path == "pose.bones[\"{}\"].location".format(Bone.name):
PositionFCurves[FCurve.array_index] = FCurve
elif FCurve.data_path == "pose.bones[\"{}\"].rotation_quaternion".format(Bone.name):
RotationFCurves[FCurve.array_index] = FCurve
elif FCurve.data_path == "pose.bones[\"{}\"].scale".format(Bone.name):
ScaleFCurves[FCurve.array_index] = FCurve
if not [FCurve for FCurve in PositionFCurves + RotationFCurves + ScaleFCurves if FCurve]:
if Config.Verbose:
print(" Bone has no useable animation data.\n Done")
Config.File.write("{}Animation {{\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
Config.File.write("{}{{{}}}\n".format(" " * Config.Whitespace, LegalName(Object.name) + "_" + LegalName(Bone.name)))
print(" Writing Position...")
AllKeyframes = set()
for Index, FCurve in enumerate(PositionFCurves):
for Keyframe in FCurve.keyframe_points:
if Keyframe.co[0] < bpy.context.scene.frame_start:
AllKeyframes.add(bpy.context.scene.frame_start)
elif Keyframe.co[0] > bpy.context.scene.frame_end:
AllKeyframes.add(bpy.context.scene.frame_end)
else:
Keyframes.append(Keyframe.co)
AllKeyframes.add(int(Keyframe.co[0]))
PositionFCurves[Index] = {int(Keyframe): Value for Keyframe, Value in Keyframes}
Config.File.write("{}AnimationKey {{ //Position\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
AllKeyframes = list(AllKeyframes)
AllKeyframes.sort()
if not len(AllKeyframes):
AllKeyframes = [bpy.context.scene.frame_start]
Config.File.write("{}2;\n{}{};\n".format(" " * Config.Whitespace, " " * Config.Whitespace, len(AllKeyframes)))
for Keyframe in AllKeyframes:
PoseMatrix = Bone.parent.matrix.inverted()
PoseMatrix *= Bone.matrix
Position = PoseMatrix.to_translation()
Config.File.write("{}{}{:9f},{:9f},{:9f};;".format(" " * Config.Whitespace, (str(Keyframe - bpy.context.scene.frame_start) + ";3;").ljust(8), Position[0], Position[1], Position[2]))
if Keyframe == AllKeyframes[-1]:
Config.File.write(";\n")
else:
Config.File.write(",\n")
Config.Whitespace -= 1
Config.File.write("{}}}\n".format(" " * Config.Whitespace))
if Config.Verbose:
print(" Done")
print(" Writing Rotation...")
AllKeyframes = set()
for Index, FCurve in enumerate(RotationFCurves):
for Keyframe in FCurve.keyframe_points:
if Keyframe.co[0] < bpy.context.scene.frame_start:
AllKeyframes.add(bpy.context.scene.frame_start)
elif Keyframe.co[0] > bpy.context.scene.frame_end:
AllKeyframes.add(bpy.context.scene.frame_end)
else:
Keyframes.append(Keyframe.co)
AllKeyframes.add(int(Keyframe.co[0]))
RotationFCurves[Index] = {int(Keyframe): Value for Keyframe, Value in Keyframes}
Config.File.write("{}AnimationKey {{ //Rotation\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
AllKeyframes = list(AllKeyframes)
AllKeyframes.sort()
if not len(AllKeyframes):
AllKeyframes = [bpy.context.scene.frame_start]
Config.File.write("{}0;\n{}{};\n".format(" " * Config.Whitespace, " " * Config.Whitespace, len(AllKeyframes)))
for Keyframe in AllKeyframes:
PoseMatrix = Bone.parent.matrix.inverted()
PoseMatrix *= Bone.matrix
Rotation = PoseMatrix.to_3x3().to_quaternion()
Config.File.write("{}{}{:9f},{:9f},{:9f},{:9f};;".format(" " * Config.Whitespace, (str(Keyframe - bpy.context.scene.frame_start) + ";4;").ljust(8), -Rotation[0], Rotation[1], Rotation[2], Rotation[3]))
if Keyframe == AllKeyframes[-1]:
Config.File.write(";\n")
else:
Config.File.write(",\n")
Config.Whitespace -= 1
Config.File.write("{}}}\n".format(" " * Config.Whitespace))
if Config.Verbose:
print(" Done")
print(" Writing Scale...")
AllKeyframes = set()
for Index, FCurve in enumerate(ScaleFCurves):
for Keyframe in FCurve.keyframe_points:
if Keyframe.co[0] < bpy.context.scene.frame_start:
AllKeyframes.add(bpy.context.scene.frame_start)
elif Keyframe.co[0] > bpy.context.scene.frame_end:
AllKeyframes.add(bpy.context.scene.frame_end)
else:
Keyframes.append(Keyframe.co)
AllKeyframes.add(int(Keyframe.co[0]))
ScaleFCurves[Index] = {int(Keyframe): Value for Keyframe, Value in Keyframes}
Config.File.write("{}AnimationKey {{ //Scale\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
AllKeyframes = list(AllKeyframes)
AllKeyframes.sort()
if not len(AllKeyframes):
AllKeyframes = [bpy.context.scene.frame_start]
Config.File.write("{}1;\n{}{};\n".format(" " * Config.Whitespace, " " * Config.Whitespace, len(AllKeyframes)))
for Keyframe in AllKeyframes:
PoseMatrix = Bone.parent.matrix.inverted()
PoseMatrix *= Bone.matrix
Config.File.write("{}{}{:9f},{:9f},{:9f};;".format(" " * Config.Whitespace, (str(Keyframe - bpy.context.scene.frame_start) + ";3;").ljust(8), Scale[0], Scale[1], Scale[2]))
if Keyframe == AllKeyframes[-1]:
Config.File.write(";\n")
else:
Config.File.write(",\n")
Config.Whitespace -= 1
Config.File.write("{}}}\n".format(" " * Config.Whitespace))
if Config.Verbose:
print(" Done")
Config.Whitespace -= 1
Config.File.write("{}}}\n".format(" " * Config.Whitespace))
if Config.Verbose:
print(" Done") #Done with Armature Bone
print(" Done") #Done with Armature Bone data
print(" Done") #Done with Object
Config.Whitespace -= 1
Config.File.write("{}}} //End of AnimationSet\n".format(" " * Config.Whitespace))
def WriteFullAnimationSet(Config):
Config.File.write("{}AnimationSet {{\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
KeyframeCount = bpy.context.scene.frame_end - bpy.context.scene.frame_start + 1
for Object in Config.ObjectList:
if Config.Verbose:
print(" Writing Animation Data for Object: {}".format(Object.name))
Config.File.write("{}Animation {{\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
Config.File.write("{}{{{}}}\n".format(" " * Config.Whitespace, LegalName(Object.name)))
#Position
if Config.Verbose:
print(" Writing Position...")
Config.File.write("{}AnimationKey {{ //Position\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
Config.File.write("{}2;\n{}{};\n".format(" " * Config.Whitespace, " " * Config.Whitespace, KeyframeCount))
for Frame in range(0, KeyframeCount):
bpy.context.scene.frame_set(Frame + bpy.context.scene.frame_start)
Position = Object.matrix_local.to_translation()
Config.File.write("{}{}{:9f},{:9f},{:9f};;".format(" " * Config.Whitespace, (str(Frame) + ";3;").ljust(8), Position[0], Position[1], Position[2]))
if Frame == KeyframeCount-1:
Config.File.write(";\n")
else:
Config.File.write(",\n")
Config.Whitespace -= 1
Config.File.write("{}}}\n".format(" " * Config.Whitespace))
if Config.Verbose:
print(" Done")
#Rotation
if Config.Verbose:
print(" Writing Rotation...")
Config.File.write("{}AnimationKey {{ //Rotation\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
Config.File.write("{}0;\n{}{};\n".format(" " * Config.Whitespace, " " * Config.Whitespace, KeyframeCount))
for Frame in range(0, KeyframeCount):
bpy.context.scene.frame_set(Frame + bpy.context.scene.frame_start)
Rotation = Object.rotation_euler.to_quaternion()
Config.File.write("{}{}{:9f},{:9f},{:9f},{:9f};;".format(" " * Config.Whitespace, (str(Frame) + ";4;").ljust(8), -Rotation[0], Rotation[1], Rotation[2], Rotation[3]))
if Frame == KeyframeCount-1:
Config.File.write(";\n")
else:
Config.File.write(",\n")
Config.Whitespace -= 1
Config.File.write("{}}}\n".format(" " * Config.Whitespace))
if Config.Verbose:
print(" Done")
#Scale
if Config.Verbose:
print(" Writing Scale...")
Config.File.write("{}AnimationKey {{ //Scale\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
Config.File.write("{}1;\n{}{};\n".format(" " * Config.Whitespace, " " * Config.Whitespace, KeyframeCount))
for Frame in range(0, KeyframeCount):
bpy.context.scene.frame_set(Frame + bpy.context.scene.frame_start)
Scale = Object.matrix_local.to_scale()
Config.File.write("{}{}{:9f},{:9f},{:9f};;".format(" " * Config.Whitespace, (str(Frame) + ";3;").ljust(8), Scale[0], Scale[1], Scale[2]))
if Frame == KeyframeCount-1:
Config.File.write(";\n")
else:
Config.File.write(",\n")
Config.Whitespace -= 1
Config.File.write("{}}}\n".format(" " * Config.Whitespace))
if Config.Verbose:
print(" Done")
Config.Whitespace -= 1
Config.File.write("{}}}\n".format(" " * Config.Whitespace))
if Config.ExportArmatures and Object.type == "ARMATURE":
if Config.Verbose:
print(" Writing Armature Bone Animation Data...")
PoseBones = Object.pose.bones
Bones = Object.data.bones
for Bone in PoseBones:
if Config.Verbose:
print(" Writing Bone: {}...".format(Bone.name))
Config.File.write("{}Animation {{\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
Config.File.write("{}{{{}}}\n".format(" " * Config.Whitespace, LegalName(Object.name) + "_" + LegalName(Bone.name)))
#Position
if Config.Verbose:
print(" Writing Position...")
Config.File.write("{}AnimationKey {{ //Position\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
Config.File.write("{}2;\n{}{};\n".format(" " * Config.Whitespace, " " * Config.Whitespace, KeyframeCount))
for Frame in range(0, KeyframeCount):
bpy.context.scene.frame_set(Frame + bpy.context.scene.frame_start)
if Bone.parent:
PoseMatrix = Bone.parent.matrix.inverted()
else:
PoseMatrix = Matrix()
PoseMatrix *= Bone.matrix
Position = PoseMatrix.to_translation()
Config.File.write("{}{}{:9f},{:9f},{:9f};;".format(" " * Config.Whitespace, (str(Frame) + ";3;").ljust(8), Position[0], Position[1], Position[2]))
if Frame == KeyframeCount-1:
Config.File.write(";\n")
else:
Config.File.write(",\n")
Config.Whitespace -= 1
Config.File.write("{}}}\n".format(" " * Config.Whitespace))
if Config.Verbose:
print(" Done")
#Rotation
if Config.Verbose:
print(" Writing Rotation...")
Config.File.write("{}AnimationKey {{ //Rotation\n".format(" " * Config.Whitespace))
Config.Whitespace += 1
Config.File.write("{}0;\n{}{};\n".format(" " * Config.Whitespace, " " * Config.Whitespace, KeyframeCount))
for Frame in range(0, KeyframeCount):
bpy.context.scene.frame_set(Frame + bpy.context.scene.frame_start)
Rotation = Bones[Bone.name].matrix.to_quaternion() * Bone.rotation_quaternion
Config.File.write("{}{}{:9f},{:9f},{:9f},{:9f};;".format(" " * Config.Whitespace, (str(Frame) + ";4;").ljust(8), -Rotation[0], Rotation[1], Rotation[2], Rotation[3]))
if Frame == KeyframeCount-1:
Config.File.write(";\n")
else:
Config.File.write(",\n")
Config.Whitespace -= 1
Config.File.write("{}}}\n".format(" " * Config.Whitespace))
if Config.Verbose:
print(" Done")
#Scale
if Config.Verbose:
print(" Writing Scale...")
Config.File.write("{}AnimationKey {{ //Scale\n".format(" " * Config.Whitespace, KeyframeCount))
Config.Whitespace += 1
Config.File.write("{}1;\n{}{};\n".format(" " * Config.Whitespace, " " * Config.Whitespace, KeyframeCount))
for Frame in range(0, KeyframeCount):
bpy.context.scene.frame_set(Frame + bpy.context.scene.frame_start)
if Bone.parent:
PoseMatrix = Bone.parent.matrix.inverted()
else:
PoseMatrix = Matrix()
PoseMatrix *= Bone.matrix
Config.File.write("{}{}{:9f},{:9f},{:9f};;".format(" " * Config.Whitespace, (str(Frame) + ";3;").ljust(8), Scale[0], Scale[1], Scale[2]))
if Frame == KeyframeCount-1:
Config.File.write(";\n")
else:
Config.File.write(",\n")
Config.Whitespace -= 1
Config.File.write("{}}}\n".format(" " * Config.Whitespace))
if Config.Verbose:
print(" Done")
Config.Whitespace -= 1
Config.File.write("{}}}\n".format(" " * Config.Whitespace))
if Config.Verbose:
print(" Done") #Done with Armature Bone
if Config.Verbose:
print(" Done") #Done with Armature Bone data
if Config.Verbose:
print(" Done") #Done with Object
Config.Whitespace -= 1
Config.File.write("{}}} //End of AnimationSet\n".format(" " * Config.Whitespace))
print("Closing File...")
if Config.Verbose:
print("Done")
Campbell Barton
committed
CoordinateSystems = (
("1", "Left-Handed", ""),
("2", "Right-Handed", ""),
)
Campbell Barton
committed
AnimationModes = (
("0", "None", ""),
("1", "Keyframes Only", ""),
("2", "Full Animation", ""),
)
ExportModes = (
("1", "All Objects", ""),
("2", "Selected Objects", ""),
)
from bpy.props import StringProperty, EnumProperty, BoolProperty
class DirectXExporter(bpy.types.Operator):
"""Export to the DirectX model format (.x)"""
bl_idname = "export.directx"
bl_label = "Export DirectX"
filepath = StringProperty(subtype='FILE_PATH')
CoordinateSystem = EnumProperty(
name="System",
description="Select a coordinate system to export to",
items=CoordinateSystems,
default="1")
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
RotateX = BoolProperty(
name="Rotate X 90 Degrees",
description="Rotate the entire scene 90 degrees around the X axis so Y is up",
default=True)
FlipNormals = BoolProperty(
name="Flip Normals",
description="",
default=False)
ApplyModifiers = BoolProperty(
name="Apply Modifiers",
description="Apply object modifiers before export",
default=False)
IncludeFrameRate = BoolProperty(
name="Include Frame Rate",
description="Include the AnimTicksPerSecond template which is used by " \
"some engines to control animation speed",
default=False)
ExportTextures = BoolProperty(
name="Export Textures",
description="Reference external image files to be used by the model",
default=True)
ExportArmatures = BoolProperty(
name="Export Armatures",
description="Export the bones of any armatures to deform meshes",
default=False)
ExportAnimation = EnumProperty(
name="Animations",
description="Select the type of animations to export. Only object " \
"and armature bone animations can be exported. Full " \
"Animation exports every frame",
items=AnimationModes,
default="0")
ExportMode = EnumProperty(
name="Export",
description="Select which objects to export. Only Mesh, Empty, " \
"and Armature objects will be exported",
items=ExportModes,
default="1")
Verbose = BoolProperty(
name="Verbose",
description="Run the exporter in debug mode. Check the console for output",
default=False)
def execute(self, context):
Campbell Barton
committed
FilePath = bpy.path.ensure_ext(self.filepath, ".x")
Config = DirectXExporterSettings(context,
FilePath,
Thomas Dinges
committed
CoordinateSystem=self.CoordinateSystem,
RotateX=self.RotateX,
FlipNormals=self.FlipNormals,
ApplyModifiers=self.ApplyModifiers,
IncludeFrameRate=self.IncludeFrameRate,
ExportTextures=self.ExportTextures,
ExportArmatures=self.ExportArmatures,
ExportAnimation=self.ExportAnimation,
ExportMode=self.ExportMode,
Verbose=self.Verbose)
Campbell Barton
committed
ExportDirectX(Config)
return {"FINISHED"}
def invoke(self, context, event):
Campbell Barton
committed
if not self.filepath:
self.filepath = bpy.path.ensure_ext(bpy.data.filepath, ".x")
WindowManager.fileselect_add(self)
return {"RUNNING_MODAL"}
def menu_func(self, context):
Campbell Barton
committed
self.layout.operator(DirectXExporter.bl_idname, text="DirectX (.x)")
bpy.utils.register_module(__name__)
bpy.types.INFO_MT_file_export.append(menu_func)
bpy.utils.unregister_module(__name__)
bpy.types.INFO_MT_file_export.remove(menu_func)
if __name__ == "__main__":