Skip to content
Snippets Groups Projects
io_export_directx_x.py 61.2 KiB
Newer Older
            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
        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__":