Skip to content
Snippets Groups Projects
io_export_directx_x.py 61.2 KiB
Newer Older
  • Learn to ignore specific revisions
  •         Config.File.write("{}Animation {{\n".format("  " * Config.Whitespace))
            Config.Whitespace += 1
            Config.File.write("{}{{{}}}\n".format("  " * Config.Whitespace, LegalName(Object.name)))
            
            #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))
    
            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))
    
            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))
    
            
            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
    
                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:
    
                    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)
    
                            PoseMatrix = Bone.parent.matrix.inverted()
    
                        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:
    
                    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:
    
                    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)
    
                            PoseMatrix = Bone.parent.matrix.inverted()
    
                        Scale = PoseMatrix.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:
    
                    
                    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:
    
        Config.File.close()
    
        if Config.Verbose:
            print("Done")
    
    CoordinateSystems = (
        ("1", "Left-Handed", ""),
        ("2", "Right-Handed", ""),
        )
    
    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')
    
        #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):
    
            FilePath = bpy.path.ensure_ext(self.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):
    
            if not self.filepath:
                self.filepath = bpy.path.ensure_ext(bpy.data.filepath, ".x")
    
    Campbell Barton's avatar
    Campbell Barton committed
            WindowManager = context.window_manager
    
            WindowManager.fileselect_add(self)
    
            return {"RUNNING_MODAL"}
    
    
    
    def menu_func(self, context):
    
        self.layout.operator(DirectXExporter.bl_idname, text="DirectX (.x)")
    
        bpy.utils.register_module(__name__)
    
    
        bpy.types.INFO_MT_file_export.append(menu_func)
    
    
    def unregister():
    
        bpy.utils.unregister_module(__name__)
    
    
        bpy.types.INFO_MT_file_export.remove(menu_func)
    
    
    
    if __name__ == "__main__":