Fix for bl_info blender versions, many addons used (2, 6, x) instead of (2, 6x, x...
[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, 64, 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
19 class OscEPc2ExporterPanel(bpy.types.Panel):
20     """Creates a Panel in the Object properties window"""
21     bl_label = "Mesh Cache Tools"
22     bl_idname = "Mesh Cache Tools"
23     bl_space_type = 'VIEW_3D'
24     bl_region_type = 'TOOLS'
25
26     def draw(self, context):
27         layout = self.layout
28
29         obj = context.object
30         row = layout.column(align=1)
31         row.prop(bpy.context.scene, "muu_pc2_folder", text="Folder")
32         row.operator("import_shape.pc2_copy", icon='FILESEL', text="Set Filepath")
33         row.prop(bpy.context.scene, "muu_pc2_relative_path", text="Relative Path (Optional):")
34         row = layout.box().column(align=1)
35         row.label("EXPORTER:")
36         row.operator("group.linked_group_to_local", text="Linked To Local", icon="LINKED")
37         row.operator("object.remove_subsurf_modifier", text="Remove Gen Modifiers", icon="MOD_SUBSURF")
38         row.operator("export_shape.pc2_selection", text="Export!", icon="POSE_DATA")
39         row.prop(bpy.context.scene, "muu_pc2_world_space", text="World Space")
40         row = layout.column(align=1)
41         row.prop(bpy.context.scene, "muu_pc2_start", text="Frame Start")
42         row.prop(bpy.context.scene, "muu_pc2_end", text="Frame End")
43         row.prop_search(bpy.context.scene, "muu_pc2_group", bpy.data, "groups", text="")
44         row = layout.box().column(align=1)
45         row.label("IMPORTER:")
46         row.operator("import_shape.pc2_selection", text="Import", icon="POSE_DATA")
47         row.operator("object.modifier_mesh_cache_up", text="MC Top", icon="TRIA_UP")
48
49 def OscFuncExportPc2(self):
50     start = bpy.context.scene.muu_pc2_start
51     end = bpy.context.scene.muu_pc2_end
52     folderpath = bpy.context.scene.muu_pc2_folder
53
54     for ob in bpy.data.groups[bpy.context.scene.muu_pc2_group].objects[:]:
55         pc2list = []
56         bpy.context.window_manager.progress_begin(0, 100) #progressbar
57         if ob.type == "MESH":
58             with open("%s/%s.pc2" % (os.path.normpath(folderpath), ob.name), mode="wb") as file:
59                 #encabezado
60                 headerFormat = '<12siiffi'
61                 headerStr = struct.pack(headerFormat,
62                          b'POINTCACHE2\0', 1, len(ob.data.vertices[:]), 0, 1.0, (end + 1) - start)
63                 file.write(headerStr)
64                 #bakeado
65                 obmat = ob.matrix_world
66                 for frame in range((end + 1) - start):
67                     print("Percentage of %s bake: %s " % (ob.name, frame / end * 100))
68                     bpy.context.window_manager.progress_update(frame / end * 100) #progressbarUpdate
69                     bpy.context.scene.frame_set(frame)
70                     me = bpy.data.meshes.new_from_object(
71                         scene=bpy.context.scene,
72                         object=ob,
73                         apply_modifiers=True,
74                         settings="RENDER",
75                         calc_tessface=True,
76                         calc_undeformed=False)
77                     #rotate
78                     if bpy.context.scene.muu_pc2_world_space:
79                         me.transform(obmat)
80                         me.calc_normals()
81                     #creo archivo
82                     for vert in me.vertices[:]:
83                         pc2list.append((
84                             float(vert.co[0]),
85                             float(vert.co[1]),
86                             float(vert.co[2])
87                             ))
88
89                     #dreno mesh
90                     bpy.data.meshes.remove(me)
91
92                 print("%s Bake finished! \nAwaiting Compile file..." % (ob.name))
93
94                 # write file
95                 for i, frame in enumerate(pc2list):
96                     file.write(struct.pack("<3f", *frame))
97                 print("%s File Compiled Write finished!" % (ob.name))
98                 del(pc2list)
99         bpy.context.window_manager.progress_end()#progressBarClose
100     print("Bake Finished!")
101
102 class OscPc2ExporterBatch(bpy.types.Operator):
103     bl_idname = "export_shape.pc2_selection"
104     bl_label = "Export pc2 for selected Objects"
105     bl_description = "Export pc2 for selected Objects"
106     bl_options = {'REGISTER', 'UNDO'}
107
108     @classmethod
109     def poll(cls, context):
110         return(bpy.context.scene.muu_pc2_group != "" and bpy.context.scene.muu_pc2_folder != 'Set me Please!')
111
112     def execute(self, context):
113         OscFuncExportPc2(self)
114         return {'FINISHED'}
115
116 class OscRemoveSubsurf(bpy.types.Operator):
117     bl_idname = "object.remove_subsurf_modifier"
118     bl_label = "Remove SubSurf Modifier"
119     bl_description = "Remove SubSurf Modifier"
120     bl_options = {'REGISTER', 'UNDO'}
121
122     @classmethod
123     def poll(cls, context):
124         return(bpy.context.scene.muu_pc2_group != "")
125
126     def execute(self, context):
127         GENERATE = ['MULTIRES', 'ARRAY', 'BEVEL', 'BOOLEAN', 'BUILD', 'DECIMATE', 'MASK', 'MIRROR', 'REMESH', 'SCREW', 'SKIN', 'SOLIDIFY', 'SUBSURF', 'TRIANGULATE']
128         for OBJ in bpy.data.groups[bpy.context.scene.muu_pc2_group].objects[:]:
129             for MOD in OBJ.modifiers[:]:
130                 if MOD.type in GENERATE:
131                     OBJ.modifiers.remove(MOD)
132         return {'FINISHED'}
133
134
135 class OscPc2iMporterBatch(bpy.types.Operator):
136     bl_idname = "import_shape.pc2_selection"
137     bl_label = "Import pc2 for selected Objects"
138     bl_description = "Import pc2 for selected Objects"
139     bl_options = {'REGISTER', 'UNDO'}
140
141     @classmethod
142     def poll(cls, context):
143         return(bpy.context.scene.muu_pc2_folder != 'Set me Please!')
144
145     def execute(self, context):
146         for OBJ in bpy.context.selected_objects[:]:
147             MOD = OBJ.modifiers.new("MeshCache", 'MESH_CACHE')
148             MOD.filepath = "%s%s%s.pc2" % (bpy.context.scene.muu_pc2_folder, os.sep, OBJ.name)
149             MOD.cache_format = "PC2"
150             MOD.forward_axis = "POS_Y"
151             MOD.up_axis = "POS_Z"
152             MOD.flip_axis = set(())
153
154         return {'FINISHED'}
155
156 class OscPc2iMporterCopy(bpy.types.Operator):
157     bl_idname = "import_shape.pc2_copy"
158     bl_label = "Copy Filepath"
159     bl_description = "Copy Filepath"
160     bl_options = {'REGISTER', 'UNDO'}
161
162     def execute(self, context):
163         filefolder = os.path.dirname(bpy.data.filepath)
164         os.chdir(filefolder)
165         if bpy.context.scene.muu_pc2_relative_path != "":
166             if os.path.exists("%s" % (os.path.join(filefolder,bpy.context.scene.muu_pc2_relative_path))):
167                 print("Folder Already Exists.")
168             else:
169                 os.mkdir("%s" % (os.path.join(filefolder,bpy.context.scene.muu_pc2_relative_path)))
170             bpy.context.scene.muu_pc2_folder = "%s" % (os.path.join(filefolder,bpy.context.scene.muu_pc2_relative_path))
171         else:
172             bpy.context.scene.muu_pc2_folder = "%s" % (filefolder)
173
174         return {'FINISHED'}
175
176 def OscLinkedGroupToLocal():
177     ACTOBJ = bpy.context.active_object
178     GROBJS = [ob for ob in ACTOBJ.id_data.dupli_group.objects[:] if ob.type == "MESH"]
179
180     for ob in ACTOBJ.id_data.dupli_group.objects[:]:
181         bpy.context.scene.objects.link(ob)
182     NEWGROUP = bpy.data.groups.new("%s_CLEAN" % (ACTOBJ.name))
183     bpy.context.scene.objects.unlink(ACTOBJ)
184     NEWOBJ = []
185     for ob in GROBJS:
186         NEWGROUP.objects.link(ob)
187         NEWOBJ.append(ob)
188     for ob in NEWOBJ:
189         if ob.type == "MESH":
190             if len(ob.modifiers):
191                 for MODIFIER in ob.modifiers[:]:
192                     if MODIFIER.type == "SUBSURF" or MODIFIER.type == "MASK":
193                         ob.modifiers.remove(MODIFIER)
194
195 class OscGroupLinkedToLocal(bpy.types.Operator):
196     bl_idname = "group.linked_group_to_local"
197     bl_label = "Group Linked To Local"
198     bl_description = "Group Linked To Local"
199     bl_options = {'REGISTER', 'UNDO'}
200
201     @classmethod
202     def poll(cls, context):
203         return(bpy.context.scene.muu_pc2_group != "")
204
205     def execute(self, context):
206         OscLinkedGroupToLocal()
207         return {'FINISHED'}
208
209 class OscMeshCacheUp(bpy.types.Operator):
210     bl_idname = "object.modifier_mesh_cache_up"
211     bl_label = "Mesh Cache To Top"
212     bl_description = "Send Mesh Cache Modifiers top"
213     bl_options = {'REGISTER', 'UNDO'}
214
215     @classmethod
216     def poll(cls, context):
217         return(bpy.context.object.type == "MESH")
218
219     def execute(self, context):
220
221         actob = bpy.context.scene.objects.active
222
223         for ob in bpy.context.selected_objects[:]:
224             bpy.context.scene.objects.active = ob
225             for mod in ob.modifiers[:]:
226                 if mod.type == "MESH_CACHE":
227                     for up in range(ob.modifiers.keys().index(mod.name)):
228                         bpy.ops.object.modifier_move_up(modifier=mod.name)
229
230         bpy.context.scene.objects.active = actob
231
232         return {'FINISHED'}
233
234
235 def register():
236     from bpy.types import Scene
237     from bpy.props import (BoolProperty,
238                            IntProperty,
239                            StringProperty,
240                            )
241
242     Scene.muu_pc2_rotx = BoolProperty(default=True, name="Rotx = 90")
243     Scene.muu_pc2_world_space = BoolProperty(default=True, name="World Space")
244     Scene.muu_pc2_modifiers = BoolProperty(default=True, name="Apply Modifiers")
245     Scene.muu_pc2_subsurf = BoolProperty(default=True, name="Turn Off SubSurf")
246     Scene.muu_pc2_start = IntProperty(default=0, name="Frame Start")
247     Scene.muu_pc2_end = IntProperty(default=100, name="Frame End")
248     Scene.muu_pc2_group = StringProperty()
249     Scene.muu_pc2_folder = StringProperty(default="Set me Please!")
250     Scene.muu_pc2_relative_path = StringProperty(default="")
251
252     bpy.utils.register_module(__name__)
253
254
255 def unregister():
256     from bpy.types import Scene
257
258     del Scene.muu_pc2_rotx
259     del Scene.muu_pc2_world_space
260     del Scene.muu_pc2_modifiers
261     del Scene.muu_pc2_subsurf
262     del Scene.muu_pc2_start
263     del Scene.muu_pc2_end
264     del Scene.muu_pc2_group
265     del Scene.muu_pc2_folder
266     del Scene.muu_pc2_relative_path
267
268     bpy.utils.unregister_module(__name__)
269
270 if __name__ == "__main__":
271     register()