more ui api changes.
[blender.git] / release / scripts / io / export_mdd.py
1 # ##### BEGIN GPL LICENSE BLOCK #####
2 #
3 #  This program is free software; you can redistribute it and/or
4 #  modify it under the terms of the GNU General Public License
5 #  as published by the Free Software Foundation; either version 2
6 #  of the License, or (at your option) any later version.
7
8 #  This program is distributed in the hope that it will be useful,
9 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 #  GNU General Public License for more details.
12
13 #  You should have received a copy of the GNU General Public License
14 #  along with this program; if not, write to the Free Software Foundation,
15 #  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
16 #
17 # ##### END GPL LICENSE BLOCK #####
18
19 __author__ = "Bill L.Nieuwendorp"
20 __bpydoc__ = """\
21 This script Exports Lightwaves MotionDesigner format.
22
23 The .mdd format has become quite a popular Pipeline format<br>
24 for moving animations from package to package.
25
26 Be sure not to use modifiers that change the number or order of verts in the mesh
27 """
28 #Please send any fixes,updates,bugs to Slow67_at_Gmail.com or cbarton_at_metavr.com
29 #Bill Niewuendorp
30 # ***** BEGIN GPL LICENSE BLOCK *****
31 #
32 # This program is free software; you can redistribute it and/or
33 # modify it under the terms of the GNU General Public License
34 # as published by the Free Software Foundation; either version 2
35 # of the License, or (at your option) any later version.
36 #
37 # This program is distributed in the hope that it will be useful,
38 # but WITHOUT ANY WARRANTY; without even the implied warranty of
39 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
40 # GNU General Public License for more details.
41 #
42 # You should have received a copy of the GNU General Public License
43 # along with this program; if not, write to the Free Software Foundation,
44 # Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
45 #
46 # ***** END GPL LICENCE BLOCK *****
47
48 import bpy
49 import Mathutils
50 import math
51 import os
52
53 #import Blender
54 #from Blender import *
55 #import BPyMessages
56 try:
57     from struct import pack
58 except:
59     pack = None
60
61 def zero_file(filepath):
62     '''
63     If a file fails, this replaces it with 1 char, better not remove it?
64     '''
65     file = open(filepath, 'w')
66     file.write('\n') # apparently macosx needs some data in a blank file?
67     file.close()
68
69 def check_vertcount(mesh,vertcount):
70     '''
71     check and make sure the vertcount is consistent throughout the frame range
72     '''
73     if len(mesh.verts) != vertcount:
74         raise Exception('Error, number of verts has changed during animation, cannot export')
75         f.close()
76         zero_file(filepath)
77         return
78     
79     
80 def write(filename, sce, ob, PREF_STARTFRAME, PREF_ENDFRAME, PREF_FPS):
81     """
82     Blender.Window.WaitCursor(1)
83
84     mesh_orig = Mesh.New()
85     mesh_orig.getFromObject(ob.name)
86     """
87
88     bpy.ops.object.mode_set(mode='OBJECT')
89
90     orig_frame = sce.current_frame
91     sce.set_frame(PREF_STARTFRAME)
92     me = ob.create_mesh(True, 'PREVIEW')
93
94     #Flip y and z
95     mat_flip= Mathutils.Matrix(\
96     [1.0, 0.0, 0.0, 0.0],\
97     [0.0, 0.0, 1.0, 0.0],\
98     [0.0, 1.0, 0.0, 0.0],\
99     [0.0, 0.0, 0.0, 1.0],\
100     )
101
102     numverts = len(me.verts)
103
104     numframes = PREF_ENDFRAME-PREF_STARTFRAME+1
105     PREF_FPS= float(PREF_FPS)
106     f = open(filename, 'wb') #no Errors yet:Safe to create file
107     
108     # Write the header
109     f.write(pack(">2i", numframes, numverts))
110     
111     # Write the frame times (should we use the time IPO??)
112     f.write( pack(">%df" % (numframes), *[frame/PREF_FPS for frame in range(numframes)]) ) # seconds
113     
114     #rest frame needed to keep frames in sync
115     """
116     Blender.Set('curframe', PREF_STARTFRAME)
117     me_tmp.getFromObject(ob.name)
118     """
119
120     check_vertcount(me,numverts)
121     me.transform(mat_flip * ob.matrix)
122     f.write(pack(">%df" % (numverts*3), *[axis for v in me.verts for axis in v.co]))
123         
124     for frame in range(PREF_STARTFRAME,PREF_ENDFRAME+1):#in order to start at desired frame
125         """
126         Blender.Set('curframe', frame)
127         me_tmp.getFromObject(ob.name)
128         """
129
130         sce.set_frame(frame)
131         me = ob.create_mesh(True, 'PREVIEW')
132         check_vertcount(me,numverts)
133         me.transform(mat_flip * ob.matrix)
134         
135         # Write the vertex data
136         f.write(pack(">%df" % (numverts*3), *[axis for v in me.verts for axis in v.co]))
137     
138     """
139     me_tmp.verts= None
140     """
141     f.close()
142     
143     print ('MDD Exported: %s frames:%d\n'% (filename, numframes-1))
144     """
145     Blender.Window.WaitCursor(0)
146     Blender.Set('curframe', orig_frame)
147     """
148     sce.set_frame(orig_frame)
149
150 from bpy.props import *
151
152 class ExportMDD(bpy.types.Operator):
153     '''Animated mesh to MDD vertex keyframe file.'''
154     bl_idname = "export.mdd"
155     bl_label = "Export MDD"
156
157     # get first scene to get min and max properties for frames, fps
158
159     minframe = 1
160     maxframe = 300000
161     minfps = 1
162     maxfps = 120
163
164     # List of operator properties, the attributes will be assigned
165     # to the class instance from the operator settings before calling.
166     path = StringProperty(name="File Path", description="File path used for exporting the MDD file", maxlen= 1024, default= "tmp.mdd")
167     fps = IntProperty(name="Frames Per Second", description="Number of frames/second", min=minfps, max=maxfps, default= 25)
168     start_frame = IntProperty(name="Start Frame", description="Start frame for baking", min=minframe,max=maxframe,default=1)
169     end_frame = IntProperty(name="End Frame", description="End frame for baking", min=minframe, max=maxframe, default= 250)
170
171     def poll(self, context):
172         ob = context.active_object
173         return (ob and ob.type=='MESH')
174
175     def execute(self, context):
176         if not self.properties.path:
177             raise Exception("filename not set")
178         write(self.properties.path, context.scene, context.active_object,
179             self.properties.start_frame, self.properties.end_frame, self.properties.fps )
180         return ('FINISHED',)
181     
182     def invoke(self, context, event):
183         wm = context.manager
184         wm.add_fileselect(self)
185         return ('RUNNING_MODAL',)
186
187 bpy.ops.add(ExportMDD)
188
189 # Add to a menu
190 import dynamic_menu
191
192 def menu_func(self, context):
193     default_path = bpy.data.filename.replace(".blend", ".mdd")
194     self.layout.operator(ExportMDD.bl_idname, text="Vertex Keyframe Animation (.mdd)...").path = default_path
195
196 menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func)
197
198 if __name__=='__main__':
199     bpy.ops.export.mdd(path="/tmp/test.mdd")