io_mesh_uv_layout: count no longer a keyword only arg
[blender-addons.git] / io_export_pc2.py
blob86a1b3c10d9e98d75bd56a698155b3f07f47d6f9
1 # ##### BEGIN GPL LICENSE BLOCK #####
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # ##### END GPL LICENSE BLOCK #####
19 bl_info = {
20 "name": "Export Pointcache Format(.pc2)",
21 "author": "Florian Meyer (tstscr)",
22 "version": (1, 1, 1),
23 "blender": (2, 71, 0),
24 "location": "File > Export > Pointcache (.pc2)",
25 "description": "Export mesh Pointcache data (.pc2)",
26 "warning": "",
27 "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/"
28 "Scripts/Import-Export/PC2_Pointcache_export",
29 "category": "Import-Export"}
31 """
32 Related links:
33 https://developer.blender.org/T34456
34 https://developer.blender.org/T25408
36 Usage Notes:
38 in Maya Mel:
39 cacheFile -pc2 1 -pcf "<insert filepath of source>" -f "<insert target filename w/o extension>" -dir "<insert directory path for target>" -format "OneFile";
41 """
43 import bpy
44 from bpy.props import BoolProperty, IntProperty, EnumProperty
45 import mathutils
46 from bpy_extras.io_utils import ExportHelper
48 from os import remove
49 import time
50 import math
51 import struct
53 def get_sampled_frames(start, end, sampling):
54 return [math.modf(start + x * sampling) for x in range(int((end - start) / sampling) + 1)]
56 def do_export(context, props, filepath):
57 mat_x90 = mathutils.Matrix.Rotation(-math.pi/2, 4, 'X')
58 ob = context.active_object
59 sc = context.scene
60 start = props.range_start
61 end = props.range_end
62 sampling = float(props.sampling)
63 apply_modifiers = props.apply_modifiers
64 me = ob.to_mesh(sc, apply_modifiers, 'PREVIEW')
65 vertCount = len(me.vertices)
66 sampletimes = get_sampled_frames(start, end, sampling)
67 sampleCount = len(sampletimes)
69 # Create the header
70 headerFormat='<12siiffi'
71 headerStr = struct.pack(headerFormat, b'POINTCACHE2\0',
72 1, vertCount, start, sampling, sampleCount)
74 file = open(filepath, "wb")
75 file.write(headerStr)
77 for frame in sampletimes:
78 sc.frame_set(int(frame[1]), frame[0]) # stupid modf() gives decimal part first!
79 me = ob.to_mesh(sc, apply_modifiers, 'PREVIEW')
81 if len(me.vertices) != vertCount:
82 bpy.data.meshes.remove(me, do_unlink=True)
83 file.close()
84 try:
85 remove(filepath)
86 except:
87 empty = open(filepath, 'w')
88 empty.write('DUMMIFILE - export failed\n')
89 empty.close()
90 print('Export failed. Vertexcount of Object is not constant')
91 return False
93 if props.world_space:
94 me.transform(ob.matrix_world)
95 if props.rot_x90:
96 me.transform(mat_x90)
98 for v in me.vertices:
99 thisVertex = struct.pack('<fff', float(v.co[0]),
100 float(v.co[1]),
101 float(v.co[2]))
102 file.write(thisVertex)
104 bpy.data.meshes.remove(me, do_unlink=True)
107 file.flush()
108 file.close()
109 return True
112 ###### EXPORT OPERATOR #######
113 class Export_pc2(bpy.types.Operator, ExportHelper):
114 """Export the active Object as a .pc2 Pointcache file"""
115 bl_idname = "export_shape.pc2"
116 bl_label = "Export Pointcache (.pc2)"
118 filename_ext = ".pc2"
120 rot_x90 = BoolProperty(name="Convert to Y-up",
121 description="Rotate 90 degrees around X to convert to y-up",
122 default=True,
124 world_space = BoolProperty(name="Export into Worldspace",
125 description="Transform the Vertexcoordinates into Worldspace",
126 default=False,
128 apply_modifiers = BoolProperty(name="Apply Modifiers",
129 description="Applies the Modifiers",
130 default=True,
132 range_start = IntProperty(name='Start Frame',
133 description='First frame to use for Export',
134 default=1,
136 range_end = IntProperty(name='End Frame',
137 description='Last frame to use for Export',
138 default=250,
140 sampling = EnumProperty(name='Sampling',
141 description='Sampling --> frames per sample (0.1 yields 10 samples per frame)',
142 items=(('0.01', '0.01', ''),
143 ('0.05', '0.05', ''),
144 ('0.1', '0.1', ''),
145 ('0.2', '0.2', ''),
146 ('0.25', '0.25', ''),
147 ('0.5', '0.5', ''),
148 ('1', '1', ''),
149 ('2', '2', ''),
150 ('3', '3', ''),
151 ('4', '4', ''),
152 ('5', '5', ''),
153 ('10', '10', ''),
155 default='1',
158 @classmethod
159 def poll(cls, context):
160 obj = context.active_object
161 return (
162 obj is not None and
163 obj.type in {'MESH', 'CURVE', 'SURFACE', 'FONT'}
166 def execute(self, context):
167 start_time = time.time()
168 print('\n_____START_____')
169 props = self.properties
170 filepath = self.filepath
171 filepath = bpy.path.ensure_ext(filepath, self.filename_ext)
173 exported = do_export(context, props, filepath)
175 if exported:
176 print('finished export in %s seconds' %((time.time() - start_time)))
177 print(filepath)
179 return {'FINISHED'}
181 def invoke(self, context, event):
182 wm = context.window_manager
184 if True:
185 # File selector
186 wm.fileselect_add(self) # will run self.execute()
187 return {'RUNNING_MODAL'}
188 elif True:
189 # search the enum
190 wm.invoke_search_popup(self)
191 return {'RUNNING_MODAL'}
192 elif False:
193 # Redo popup
194 return wm.invoke_props_popup(self, event)
195 elif False:
196 return self.execute(context)
199 ### REGISTER ###
201 def menu_func(self, context):
202 self.layout.operator(Export_pc2.bl_idname, text="Pointcache (.pc2)")
205 def register():
206 bpy.utils.register_module(__name__)
208 bpy.types.TOPBAR_MT_file_export.append(menu_func)
209 #bpy.types.VIEW3D_PT_tools_objectmode.prepend(menu_func)
211 def unregister():
212 bpy.utils.unregister_module(__name__)
214 bpy.types.TOPBAR_MT_file_export.remove(menu_func)
215 #bpy.types.VIEW3D_PT_tools_objectmode.remove(menu_func)
217 if __name__ == "__main__":
218 register()