| 
									
										
										
										
											2009-11-01 15:21:20 +00:00
										 |  |  | # ##### BEGIN 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 2 | 
					
						
							|  |  |  | #  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, write to the Free Software Foundation, | 
					
						
							|  |  |  | #  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # ##### END GPL LICENSE BLOCK ##### | 
					
						
							| 
									
										
										
										
											2009-10-08 17:32:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | __author__ = "Bill L.Nieuwendorp" | 
					
						
							|  |  |  | __bpydoc__ = """\
 | 
					
						
							|  |  |  | This script Exports Lightwaves MotionDesigner format. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The .mdd format has become quite a popular Pipeline format<br> | 
					
						
							|  |  |  | for moving animations from package to package. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Be sure not to use modifiers that change the number or order of verts in the mesh | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | #Please send any fixes,updates,bugs to Slow67_at_Gmail.com or cbarton_at_metavr.com | 
					
						
							|  |  |  | #Bill Niewuendorp | 
					
						
							|  |  |  | # ***** BEGIN 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 2 | 
					
						
							|  |  |  | # 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, write to the Free Software Foundation, | 
					
						
							|  |  |  | # Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # ***** END GPL LICENCE BLOCK ***** | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import bpy | 
					
						
							|  |  |  | import Mathutils | 
					
						
							|  |  |  | import math | 
					
						
							|  |  |  | import os | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #import Blender | 
					
						
							|  |  |  | #from Blender import * | 
					
						
							|  |  |  | #import BPyMessages | 
					
						
							|  |  |  | try: | 
					
						
							| 
									
										
										
										
											2009-11-04 18:35:32 +00:00
										 |  |  |     from struct import pack | 
					
						
							| 
									
										
										
										
											2009-10-08 17:32:51 +00:00
										 |  |  | except: | 
					
						
							| 
									
										
										
										
											2009-11-04 18:35:32 +00:00
										 |  |  |     pack = None | 
					
						
							| 
									
										
										
										
											2009-10-08 17:32:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def zero_file(filepath): | 
					
						
							| 
									
										
										
										
											2009-11-04 18:35:32 +00:00
										 |  |  |     '''
 | 
					
						
							|  |  |  |     If a file fails, this replaces it with 1 char, better not remove it? | 
					
						
							|  |  |  |     '''
 | 
					
						
							|  |  |  |     file = open(filepath, 'w') | 
					
						
							|  |  |  |     file.write('\n') # apparently macosx needs some data in a blank file? | 
					
						
							|  |  |  |     file.close() | 
					
						
							| 
									
										
										
										
											2009-10-08 17:32:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def check_vertcount(mesh,vertcount): | 
					
						
							| 
									
										
										
										
											2009-11-04 18:35:32 +00:00
										 |  |  |     '''
 | 
					
						
							|  |  |  |     check and make sure the vertcount is consistent throughout the frame range | 
					
						
							|  |  |  |     '''
 | 
					
						
							|  |  |  |     if len(mesh.verts) != vertcount: | 
					
						
							|  |  |  |         raise Exception('Error, number of verts has changed during animation, cannot export') | 
					
						
							|  |  |  |         f.close() | 
					
						
							|  |  |  |         zero_file(filepath) | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2009-10-08 17:32:51 +00:00
										 |  |  | def write(filename, sce, ob, PREF_STARTFRAME, PREF_ENDFRAME, PREF_FPS): | 
					
						
							| 
									
										
										
										
											2009-11-04 18:35:32 +00:00
										 |  |  |     """
 | 
					
						
							|  |  |  |     Blender.Window.WaitCursor(1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     mesh_orig = Mesh.New() | 
					
						
							|  |  |  |     mesh_orig.getFromObject(ob.name) | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bpy.ops.object.mode_set(mode='OBJECT') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     orig_frame = sce.current_frame | 
					
						
							|  |  |  |     sce.set_frame(PREF_STARTFRAME) | 
					
						
							|  |  |  |     me = ob.create_mesh(True, 'PREVIEW') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     #Flip y and z | 
					
						
							|  |  |  |     mat_flip= Mathutils.Matrix(\ | 
					
						
							|  |  |  |     [1.0, 0.0, 0.0, 0.0],\ | 
					
						
							|  |  |  |     [0.0, 0.0, 1.0, 0.0],\ | 
					
						
							|  |  |  |     [0.0, 1.0, 0.0, 0.0],\ | 
					
						
							|  |  |  |     [0.0, 0.0, 0.0, 1.0],\ | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     numverts = len(me.verts) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     numframes = PREF_ENDFRAME-PREF_STARTFRAME+1 | 
					
						
							|  |  |  |     PREF_FPS= float(PREF_FPS) | 
					
						
							|  |  |  |     f = open(filename, 'wb') #no Errors yet:Safe to create file | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     # Write the header | 
					
						
							|  |  |  |     f.write(pack(">2i", numframes, numverts)) | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     # Write the frame times (should we use the time IPO??) | 
					
						
							|  |  |  |     f.write( pack(">%df" % (numframes), *[frame/PREF_FPS for frame in range(numframes)]) ) # seconds | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     #rest frame needed to keep frames in sync | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     Blender.Set('curframe', PREF_STARTFRAME) | 
					
						
							|  |  |  |     me_tmp.getFromObject(ob.name) | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     check_vertcount(me,numverts) | 
					
						
							|  |  |  |     me.transform(mat_flip * ob.matrix) | 
					
						
							|  |  |  |     f.write(pack(">%df" % (numverts*3), *[axis for v in me.verts for axis in v.co])) | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |     for frame in range(PREF_STARTFRAME,PREF_ENDFRAME+1):#in order to start at desired frame | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Blender.Set('curframe', frame) | 
					
						
							|  |  |  |         me_tmp.getFromObject(ob.name) | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         sce.set_frame(frame) | 
					
						
							|  |  |  |         me = ob.create_mesh(True, 'PREVIEW') | 
					
						
							|  |  |  |         check_vertcount(me,numverts) | 
					
						
							|  |  |  |         me.transform(mat_flip * ob.matrix) | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         # Write the vertex data | 
					
						
							|  |  |  |         f.write(pack(">%df" % (numverts*3), *[axis for v in me.verts for axis in v.co])) | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     me_tmp.verts= None | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     f.close() | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     print ('MDD Exported: %s frames:%d\n'% (filename, numframes-1)) | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     Blender.Window.WaitCursor(0) | 
					
						
							|  |  |  |     Blender.Set('curframe', orig_frame) | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     sce.set_frame(orig_frame) | 
					
						
							| 
									
										
										
										
											2009-10-08 17:32:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
											  
											
												define operator properties in the class, similar to django fields
# Before
[
	bpy.props.StringProperty(attr="path", name="File Path", description="File path used for exporting the PLY file", maxlen= 1024, default= ""),
	bpy.props.BoolProperty(attr="use_modifiers", name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default= True),
	bpy.props.BoolProperty(attr="use_normals", name="Export Normals", description="Export Normals for smooth and hard shaded faces", default= True),
	bpy.props.BoolProperty(attr="use_uvs", name="Export UVs", description="Exort the active UV layer", default= True),
	bpy.props.BoolProperty(attr="use_colors", name="Export Vertex Colors", description="Exort the active vertex color layer", default= True)
]
# After
path = StringProperty(attr="", name="File Path", description="File path used for exporting the PLY file", maxlen= 1024, default= "")
use_modifiers = BoolProperty(attr="", name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default= True)
use_normals = BoolProperty(attr="", name="Export Normals", description="Export Normals for smooth and hard shaded faces", default= True)
use_uvs = BoolProperty(attr="", name="Export UVs", description="Exort the active UV layer", default= True)
use_colors = BoolProperty(attr="", name="Export Vertex Colors", description="Exort the active vertex color layer", default= True)
											
										 
											2009-10-31 16:40:14 +00:00
										 |  |  | from bpy.props import * | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-04 18:35:32 +00:00
										 |  |  | class ExportMDD(bpy.types.Operator): | 
					
						
							|  |  |  |     '''Animated mesh to MDD vertex keyframe file.''' | 
					
						
							|  |  |  |     bl_idname = "export.mdd" | 
					
						
							|  |  |  |     bl_label = "Export MDD" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # get first scene to get min and max properties for frames, fps | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-13 08:44:57 +00:00
										 |  |  |     minframe = 1 | 
					
						
							|  |  |  |     maxframe = 300000 | 
					
						
							|  |  |  |     minfps = 1 | 
					
						
							|  |  |  |     maxfps = 120 | 
					
						
							| 
									
										
										
										
											2009-11-04 18:35:32 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # List of operator properties, the attributes will be assigned | 
					
						
							|  |  |  |     # to the class instance from the operator settings before calling. | 
					
						
							|  |  |  |     path = StringProperty(name="File Path", description="File path used for exporting the MDD file", maxlen= 1024, default= "tmp.mdd") | 
					
						
							|  |  |  |     fps = IntProperty(name="Frames Per Second", description="Number of frames/second", min=minfps, max=maxfps, default= 25) | 
					
						
							|  |  |  |     start_frame = IntProperty(name="Start Frame", description="Start frame for baking", min=minframe,max=maxframe,default=1) | 
					
						
							|  |  |  |     end_frame = IntProperty(name="End Frame", description="End frame for baking", min=minframe, max=maxframe, default= 250) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def poll(self, context): | 
					
						
							|  |  |  |         ob = context.active_object | 
					
						
							|  |  |  |         return (ob and ob.type=='MESH') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def execute(self, context): | 
					
						
							|  |  |  |         if not self.path: | 
					
						
							|  |  |  |             raise Exception("filename not set") | 
					
						
							|  |  |  |         write(self.path, context.scene, context.active_object, | 
					
						
							|  |  |  |             self.start_frame, self.end_frame, self.fps ) | 
					
						
							|  |  |  |         return ('FINISHED',) | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     def invoke(self, context, event): | 
					
						
							|  |  |  |         wm = context.manager | 
					
						
							|  |  |  |         wm.add_fileselect(self) | 
					
						
							|  |  |  |         return ('RUNNING_MODAL',) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bpy.ops.add(ExportMDD) | 
					
						
							| 
									
										
										
										
											2009-10-08 17:32:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
											
												- add torus back from 2.4x as an operator
  bpy.ops.mesh.primitive_torus_add(major_radius=1, minor_radius=0.25, major_segments=48, minor_segments=16)
- experemental dynamic menus, used for INFO_MT_file, INFO_MT_file_import, INFO_MT_file_export and INFO_MT_mesh_add. these can have items added from python.
eg.
- removed OBJECT_OT_mesh_add, use the python add menu instead.
- made mesh primitive ops -  MESH_OT_primitive_plane_add, ...cube_add, etc. work in object mode.
- RNA scene.active_object wrapped
- bugfix [#19466] 2.5: Tweak menu only available for mesh objects added within Edit Mode
  ED_object_exit_editmode was always doing an undo push, made this optional using the existing flag - EM_DO_UNDO, called everywhere except when adding primitives.
											
										 
											2009-10-10 21:23:20 +00:00
										 |  |  | # Add to a menu | 
					
						
							|  |  |  | import dynamic_menu | 
					
						
							| 
									
										
										
										
											2009-11-04 18:35:32 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def menu_func(self, context): | 
					
						
							|  |  |  |     default_path = bpy.data.filename.replace(".blend", ".mdd") | 
					
						
							|  |  |  |     self.layout.item_stringO(ExportMDD.bl_idname, "path", default_path, text="Vertex Keyframe Animation (.mdd)...") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												- add torus back from 2.4x as an operator
  bpy.ops.mesh.primitive_torus_add(major_radius=1, minor_radius=0.25, major_segments=48, minor_segments=16)
- experemental dynamic menus, used for INFO_MT_file, INFO_MT_file_import, INFO_MT_file_export and INFO_MT_mesh_add. these can have items added from python.
eg.
- removed OBJECT_OT_mesh_add, use the python add menu instead.
- made mesh primitive ops -  MESH_OT_primitive_plane_add, ...cube_add, etc. work in object mode.
- RNA scene.active_object wrapped
- bugfix [#19466] 2.5: Tweak menu only available for mesh objects added within Edit Mode
  ED_object_exit_editmode was always doing an undo push, made this optional using the existing flag - EM_DO_UNDO, called everywhere except when adding primitives.
											
										 
											2009-10-10 21:23:20 +00:00
										 |  |  | menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-08 17:32:51 +00:00
										 |  |  | if __name__=='__main__': | 
					
						
							| 
									
										
										
										
											2009-11-13 08:44:57 +00:00
										 |  |  |     bpy.ops.export.mdd(path="/tmp/test.mdd") |