Skip to content
Snippets Groups Projects
io_export_directx_x.py 56.7 KiB
Newer Older
                    PoseMatrix = Config.SystemMatrix * PoseMatrix * Config.InverseSystemMatrix
                    
                    Position = PoseMatrix.translation_part()
                    Config.File.write("{}{}{:9f},{:9f},{:9f};;\n".format("  " * Config.Whitespace, (str(Frame) + ";3;").ljust(8), Position[0], Position[1], Position[2]))
                Config.Whitespace -= 1
                Config.File.write("{}}}\n".format("  " * Config.Whitespace))
                if Config.Verbose:
                    print("Done")
                
                #Rotation
                if Config.Verbose:
                    print("        Writing Rotation...", end=" ")
                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)
                    #Whew! I'm sure this could be simplified.
                    Rotation = Config.SystemQuaternion.cross(Matrix.Rotation(radians(90), 4, "X").to_quat().cross(Bone.rotation_quaternion.cross(Matrix.Rotation(radians(-90), 4, "X").to_quat().cross(Config.InverseSystemQuaternion))))
                    Config.File.write("{}{}{:9f},{:9f},{:9f},{:9f};;\n".format("  " * Config.Whitespace, (str(Frame) + ";4;").ljust(8), Rotation[0], Rotation[1], Rotation[2], Config.FlipZ * Rotation[3]))
                Config.Whitespace -= 1
                Config.File.write("{}}}\n".format("  " * Config.Whitespace))
                if Config.Verbose:
                    print("Done")
                
                #Scale
                if Config.Verbose:
                    print("        Writing Scale...", end=" ")
                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 * Matrix.Rotation(radians(-90), 4, "X")).invert()
                    else:
                        PoseMatrix = Matrix()
                    PoseMatrix *= Bone.matrix * Matrix.Rotation(radians(-90), 4, "X")
                    
                    PoseMatrix = Config.SystemMatrix * PoseMatrix * Config.InverseSystemMatrix
                    
                    Scale = PoseMatrix.scale_part()
                    Config.File.write("{}{}{:9f},{:9f},{:9f};;\n".format("  " * Config.Whitespace, (str(Frame) + ";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("      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))

def CloseFile(Config):
    if Config.Verbose:
        print("Closing File...", end=" ")
    Config.File.close()
    if Config.Verbose:
        print("Done")
CoordinateSystems = []
CoordinateSystems.append(("1", "Left-Handed", ""))
CoordinateSystems.append(("2", "Right-Handed", ""))
AnimationModes = []
AnimationModes.append(("0", "None", ""))
AnimationModes.append(("1", "Keyframes Only", ""))
AnimationModes.append(("2", "Full Animation", ""))
ExportModes = []
ExportModes.append(("1", "All Objects", ""))
ExportModes.append(("2", "Selected Objects", ""))
class DirectXExporter(bpy.types.Operator):
    """Export to the DirectX model format (.x)"""

    bl_idname = "export.directx"
    bl_label = "Export DirectX"

    filepath = StringProperty()
    filename = StringProperty()
    directory = StringProperty()

    #Coordinate System
    CoordinateSystem = EnumProperty(name="System", description="Select a coordinate system to export to", items=CoordinateSystems, default="1")

    #General Options
    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):
        #Append .x if needed
        if not FilePath.lower().endswith(".x"):
            FilePath += ".x"

        Config = DirectXExporterSettings(context,
                                         FilePath,
                                         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)
        ExportDirectX(Config)
        return {"FINISHED"}

    def invoke(self, context, event):
Campbell Barton's avatar
Campbell Barton committed
        WindowManager = context.window_manager
        WindowManager.add_fileselect(self)
        return {"RUNNING_MODAL"}


def menu_func(self, context):
    default_path = os.path.splitext(bpy.data.filepath)[0] + ".x"
    self.layout.operator(DirectXExporter.bl_idname, text="DirectX (.x)").filepath = default_path

def register():
    bpy.types.INFO_MT_file_export.append(menu_func)

def unregister():
    bpy.types.INFO_MT_file_export.remove(menu_func)


if __name__ == "__main__":
Luca Bonavita's avatar
Luca Bonavita committed
    register()