Move 'render auto tile size' addon to main repo.
[blender-addons-contrib.git] / oscurart_mesh_cache_tools.py
1 bl_info = {
2     "name": "Mesh Cache Tools",
3     "author": "Oscurart",
4     "version": (1, 0),
5     "blender": (2, 70, 0),
6     "location": "Tools > Mesh Cache Tools",
7     "description": "Tools for Management Mesh Cache Process",
8     "warning": "",
9     "wiki_url": "",
10     "tracker_url": "",
11     "category": "Import-Export"}
12
13
14 import bpy
15 import sys
16 import os
17 import struct
18 from bpy.types import Operator
19 from bpy_extras.io_utils import ImportHelper
20 from bpy.props import StringProperty, BoolProperty, EnumProperty
21
22
23 class ModifiersSettings(bpy.types.PropertyGroup):
24     array = bpy.props.BoolProperty(default=True)
25     bevel = bpy.props.BoolProperty(default=True)
26     boolean = bpy.props.BoolProperty(default=True)
27     build = bpy.props.BoolProperty(default=True)
28     decimate = bpy.props.BoolProperty(default=True)
29     edge_split = bpy.props.BoolProperty(default=True)
30     mask = bpy.props.BoolProperty(default=True)
31     mirror = bpy.props.BoolProperty(default=True)
32     multires = bpy.props.BoolProperty(default=True)
33     remesh = bpy.props.BoolProperty(default=True)
34     screw = bpy.props.BoolProperty(default=True)
35     skin = bpy.props.BoolProperty(default=True)
36     solidify = bpy.props.BoolProperty(default=True)
37     subsurf = bpy.props.BoolProperty(default=True)
38     triangulate = bpy.props.BoolProperty(default=True)
39     wireframe = bpy.props.BoolProperty(default=True)
40     cloth = bpy.props.BoolProperty(default=True)
41     
42
43 bpy.utils.register_class(ModifiersSettings) #registro PropertyGroup
44
45 bpy.types.Scene.mesh_cache_tools_settings = bpy.props.PointerProperty(type=ModifiersSettings)
46
47
48 class View3DMCPanel():
49     bl_space_type = 'VIEW_3D'
50     bl_region_type = 'TOOLS'   
51   
52
53 class OscEPc2ExporterPanel(View3DMCPanel, bpy.types.Panel):    
54     """
55     bl_label = "Mesh Cache Tools"
56     bl_idname = "Mesh Cache Tools"
57     bl_space_type = 'VIEW_3D'
58     bl_region_type = 'TOOLS'
59     """
60     bl_category = "Mesh Cache Tools"
61     bl_label = "Mesh Cache Tools"
62
63     def draw(self, context):
64         layout = self.layout
65
66         obj = context.object
67         row = layout.column(align=1)
68         row.prop(bpy.context.scene, "muu_pc2_folder", text="Folder")
69         row.operator("buttons.set_meshcache_folder", icon='FILESEL', text="Select Folder Path")
70         row = layout.box().column(align=1)
71         row.label("EXPORTER:")
72         row.operator("group.linked_group_to_local", text="Linked To Local", icon="LINKED")
73         row.operator("object.remove_subsurf_modifier", text="Remove Gen Modifiers", icon="MOD_SUBSURF")
74         row.prop(bpy.context.scene.mesh_cache_tools_settings, "array", text="Array")
75         row.prop(bpy.context.scene.mesh_cache_tools_settings, "bevel", text="Bevel")
76         row.prop(bpy.context.scene.mesh_cache_tools_settings, "boolean", text="Boolean")
77         row.prop(bpy.context.scene.mesh_cache_tools_settings, "build", text="Build")     
78         row.prop(bpy.context.scene.mesh_cache_tools_settings, "decimate", text="Decimate")
79         row.prop(bpy.context.scene.mesh_cache_tools_settings, "edge_split", text="Edge Split") 
80         row.prop(bpy.context.scene.mesh_cache_tools_settings, "mask", text="Mask")
81         row.prop(bpy.context.scene.mesh_cache_tools_settings, "mirror", text="Mirror")
82         row.prop(bpy.context.scene.mesh_cache_tools_settings, "multires", text="Multires")
83         row.prop(bpy.context.scene.mesh_cache_tools_settings, "remesh", text="Remesh")     
84         row.prop(bpy.context.scene.mesh_cache_tools_settings, "screw", text="Screw")
85         row.prop(bpy.context.scene.mesh_cache_tools_settings, "skin", text="Skin")
86         row.prop(bpy.context.scene.mesh_cache_tools_settings, "solidify", text="Solidify")
87         row.prop(bpy.context.scene.mesh_cache_tools_settings, "subsurf", text="Subsurf")
88         row.prop(bpy.context.scene.mesh_cache_tools_settings, "triangulate", text="Triangulate")
89         row.prop(bpy.context.scene.mesh_cache_tools_settings, "wireframe", text="Wireframe")           
90         #row = layout.column(align=1)
91         row.prop(bpy.context.scene, "muu_pc2_start", text="Frame Start")
92         row.prop(bpy.context.scene, "muu_pc2_end", text="Frame End")
93         row.prop_search(bpy.context.scene, "muu_pc2_group", bpy.data, "groups", text="")
94         row.operator("export_shape.pc2_selection", text="Export!", icon="POSE_DATA")
95         row.prop(bpy.context.scene, "muu_pc2_world_space", text="World Space")
96         row = layout.box().column(align=1)
97         row.label("IMPORTER:")
98         row.operator("import_shape.pc2_selection", text="Import", icon="POSE_DATA")
99         row.operator("object.modifier_mesh_cache_up", text="MC Top", icon="TRIA_UP")
100
101 def OscSetFolder(context, filepath):
102     fp =  filepath if os.path.isdir(filepath) else  os.path.dirname(filepath)
103     for sc in bpy.data.scenes:
104         sc.muu_pc2_folder = fp
105     return {'FINISHED'}
106
107
108 class OscMeshCacheButtonSet(Operator, ImportHelper):
109     bl_idname = "buttons.set_meshcache_folder"  
110     bl_label = "Set Mesh Cache Folder"
111     filename_ext = ".txt"
112
113
114     def execute(self, context):
115         return OscSetFolder(context, self.filepath)
116
117
118 def OscFuncExportPc2(self):
119     start = bpy.context.scene.muu_pc2_start
120     end = bpy.context.scene.muu_pc2_end
121     folderpath = bpy.context.scene.muu_pc2_folder
122     framerange = end-start
123
124     for ob in bpy.data.groups[bpy.context.scene.muu_pc2_group].objects[:]:
125         bpy.context.window_manager.progress_begin(0, 100) #progressbar
126         if ob.type == "MESH":
127             with open("%s/%s.pc2" % (os.path.normpath(folderpath), ob.name), mode="wb") as file:
128                 #encabezado
129                 headerFormat = '<12siiffi'
130                 headerStr = struct.pack(headerFormat,
131                          b'POINTCACHE2\0', 1, len(ob.data.vertices[:]), 0, 1.0, (end + 1) - start)
132                 file.write(headerStr)
133                 #bakeado
134                 obmat = ob.matrix_world
135                 for i,frame in enumerate(range(start,end+1)):
136                     print("Percentage of %s bake: %s " % (ob.name, i * 100 / framerange))
137                     bpy.context.window_manager.progress_update(i * 100 / framerange) #progressbarUpdate
138                     bpy.context.scene.frame_set(frame)
139                     me = bpy.data.meshes.new_from_object(
140                         scene=bpy.context.scene,
141                         object=ob,
142                         apply_modifiers=True,
143                         settings="RENDER",
144                         calc_tessface=True,
145                         calc_undeformed=False)
146                     #rotate
147                     if bpy.context.scene.muu_pc2_world_space:
148                         me.transform(obmat)
149                         me.calc_normals()
150                     #creo archivo
151                     for vert in me.vertices[:]:
152                         file.write(struct.pack("<3f", *vert.co)) 
153                     #dreno mesh
154                     bpy.data.meshes.remove(me)
155
156
157                 print("%s Bake finished!" % (ob.name))
158                 
159         bpy.context.window_manager.progress_end()#progressBarClose
160     print("Bake Totally Finished!")
161
162 class OscPc2ExporterBatch(bpy.types.Operator):
163     bl_idname = "export_shape.pc2_selection"
164     bl_label = "Export pc2 for selected Objects"
165     bl_description = "Export pc2 for selected Objects"
166     bl_options = {'REGISTER', 'UNDO'}
167
168     @classmethod
169     def poll(cls, context):
170         return(bpy.context.scene.muu_pc2_group != "" and bpy.context.scene.muu_pc2_folder != 'Set me Please!')
171
172     def execute(self, context):
173         OscFuncExportPc2(self)
174         return {'FINISHED'}
175
176 class OscRemoveSubsurf(bpy.types.Operator):
177     bl_idname = "object.remove_subsurf_modifier"
178     bl_label = "Remove SubSurf Modifier"
179     bl_description = "Remove SubSurf Modifier"
180     bl_options = {'REGISTER', 'UNDO'}
181
182     @classmethod
183     def poll(cls, context):
184         return(bpy.context.scene.muu_pc2_group != "")
185
186     def execute(self, context):
187         GENERATE = ['MULTIRES', 'ARRAY', 'BEVEL', 'BOOLEAN', 'BUILD', 'DECIMATE', 'MASK', 'MIRROR', 'REMESH', 'SCREW', 'SKIN', 'SOLIDIFY', 'SUBSURF', 'TRIANGULATE']
188         for OBJ in bpy.data.groups[bpy.context.scene.muu_pc2_group].objects[:]:
189             for MOD in OBJ.modifiers[:]:
190                 if MOD.type in GENERATE:
191                     if eval("bpy.context.scene.mesh_cache_tools_settings.%s" % (MOD.type.lower())):
192                         OBJ.modifiers.remove(MOD)
193   
194         return {'FINISHED'}
195
196
197 class OscPc2iMporterBatch(bpy.types.Operator):
198     bl_idname = "import_shape.pc2_selection"
199     bl_label = "Import pc2 for selected Objects"
200     bl_description = "Import pc2 for selected Objects"
201     bl_options = {'REGISTER', 'UNDO'}
202
203     @classmethod
204     def poll(cls, context):
205         return(bpy.context.scene.muu_pc2_folder != 'Set me Please!')
206
207     def execute(self, context):
208         for OBJ in bpy.context.selected_objects[:]:
209             MOD = OBJ.modifiers.new("MeshCache", 'MESH_CACHE')
210             MOD.filepath = "%s%s%s.pc2" % (bpy.context.scene.muu_pc2_folder, os.sep, OBJ.name)
211             MOD.cache_format = "PC2"
212             MOD.forward_axis = "POS_Y"
213             MOD.up_axis = "POS_Z"
214             MOD.flip_axis = set(())
215             MOD.frame_start = bpy.context.scene.muu_pc2_start
216
217         return {'FINISHED'}
218
219 def OscLinkedGroupToLocal():
220     ACTOBJ = bpy.context.active_object
221     GROBJS = [ob for ob in ACTOBJ.id_data.dupli_group.objects[:] if ob.type == "MESH"]
222
223     for ob in ACTOBJ.id_data.dupli_group.objects[:]:
224         bpy.context.scene.objects.link(ob)
225     NEWGROUP = bpy.data.groups.new("%s_CLEAN" % (ACTOBJ.name))
226     bpy.context.scene.objects.unlink(ACTOBJ)
227     NEWOBJ = []
228     for ob in GROBJS:
229         NEWGROUP.objects.link(ob)
230         NEWOBJ.append(ob)
231     """    
232     for ob in NEWOBJ:
233         if ob.type == "MESH":
234             if len(ob.modifiers):
235                 for MODIFIER in ob.modifiers[:]:
236                     if MODIFIER.type == "SUBSURF" or MODIFIER.type == "MASK":
237                         ob.modifiers.remove(MODIFIER)
238     """                    
239
240 class OscGroupLinkedToLocal(bpy.types.Operator):
241     bl_idname = "group.linked_group_to_local"
242     bl_label = "Group Linked To Local"
243     bl_description = "Group Linked To Local"
244     bl_options = {'REGISTER', 'UNDO'}
245
246     @classmethod
247     def poll(cls, context):
248         return(bpy.context.scene.muu_pc2_group != "")
249
250     def execute(self, context):
251         OscLinkedGroupToLocal()
252         return {'FINISHED'}
253
254 class OscMeshCacheUp(bpy.types.Operator):
255     bl_idname = "object.modifier_mesh_cache_up"
256     bl_label = "Mesh Cache To Top"
257     bl_description = "Send Mesh Cache Modifiers top"
258     bl_options = {'REGISTER', 'UNDO'}
259
260     @classmethod
261     def poll(cls, context):
262         obj = context.object
263         return (obj and obj.type == "MESH")
264
265     def execute(self, context):
266
267         actob = bpy.context.scene.objects.active
268
269         for ob in bpy.context.selected_objects[:]:
270             bpy.context.scene.objects.active = ob
271             for mod in ob.modifiers[:]:
272                 if mod.type == "MESH_CACHE":
273                     for up in range(ob.modifiers.keys().index(mod.name)):
274                         bpy.ops.object.modifier_move_up(modifier=mod.name)
275
276         bpy.context.scene.objects.active = actob
277
278         return {'FINISHED'}
279
280
281 def register():
282     from bpy.types import Scene
283     from bpy.props import (BoolProperty,
284                            IntProperty,
285                            StringProperty,
286                            )
287
288     Scene.muu_pc2_rotx = BoolProperty(default=True, name="Rotx = 90")
289     Scene.muu_pc2_world_space = BoolProperty(default=True, name="World Space")
290     Scene.muu_pc2_modifiers = BoolProperty(default=True, name="Apply Modifiers")
291     Scene.muu_pc2_subsurf = BoolProperty(default=True, name="Turn Off SubSurf")
292     Scene.muu_pc2_start = IntProperty(default=0, name="Frame Start")
293     Scene.muu_pc2_end = IntProperty(default=100, name="Frame End")
294     Scene.muu_pc2_group = StringProperty()
295     Scene.muu_pc2_folder = StringProperty(default="Set me Please!")
296
297     bpy.utils.register_module(__name__)
298
299
300 def unregister():
301     from bpy.types import Scene
302
303     del Scene.muu_pc2_rotx
304     del Scene.muu_pc2_world_space
305     del Scene.muu_pc2_modifiers
306     del Scene.muu_pc2_subsurf
307     del Scene.muu_pc2_start
308     del Scene.muu_pc2_end
309     del Scene.muu_pc2_group
310     del Scene.muu_pc2_folder
311
312     bpy.utils.unregister_module(__name__)
313
314 if __name__ == "__main__":
315     register()