IO Groups rewritten!
[blender-addons-contrib.git] / oscurart_tools / oscurart_meshes.py
1 import bpy
2 import math
3 import sys
4 import os
5 import stat
6 import bmesh
7 import time
8 import random
9
10 C = bpy.context
11 D = bpy.data
12
13 ##-----------------------------RECONST---------------------------
14 def defReconst(self, OFFSET):
15     bpy.ops.object.mode_set(mode='EDIT', toggle=False)
16     bpy.context.tool_settings.mesh_select_mode = (True, False, False)
17     OBJETO = bpy.context.active_object
18     OBDATA = bmesh.from_edit_mesh(OBJETO.data)
19     OBDATA.select_flush(False)
20     for vertice in OBDATA.verts[:]:
21         if abs(vertice.co[0]) < OFFSET:
22             vertice.co[0] = 0
23     bpy.ops.mesh.select_all(action="DESELECT")
24     for vertices in OBDATA.verts[:]:
25       if vertices.co[0] < 0:
26         vertices.select = 1
27     bpy.ops.mesh.delete()
28     bpy.ops.object.modifier_add(type='MIRROR')
29     bpy.ops.mesh.select_all(action="SELECT")
30     bpy.ops.mesh.uv_texture_add()
31     LENUVLISTSIM = len(bpy.data.objects[OBJETO.name].data.uv_textures)
32     LENUVLISTSIM = LENUVLISTSIM - 1
33     OBJETO.data.uv_textures[LENUVLISTSIM:][0].name = "SYMMETRICAL"
34     bpy.ops.uv.unwrap(method='ANGLE_BASED', fill_holes=True, correct_aspect=False, use_subsurf_data=0)
35     bpy.ops.object.mode_set(mode="OBJECT", toggle= False)
36     bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Mirror")
37     bpy.ops.object.mode_set(mode="EDIT", toggle= False)
38     OBDATA = bmesh.from_edit_mesh(OBJETO.data)
39     OBDATA.select_flush(0)
40     bpy.ops.mesh.uv_texture_add()
41     LENUVLISTASIM = len(OBJETO.data.uv_textures)
42     LENUVLISTASIM = LENUVLISTASIM  - 1
43     OBJETO.data.uv_textures[LENUVLISTASIM:][0].name = "ASYMMETRICAL"
44     OBJETO.data.uv_textures.active = OBJETO.data.uv_textures["ASYMMETRICAL"]
45     bpy.ops.uv.unwrap(method='ANGLE_BASED', fill_holes=True, correct_aspect=False, use_subsurf_data=0)
46
47 class reConst (bpy.types.Operator):
48     bl_idname = "mesh.reconst_osc"
49     bl_label = "ReConst Mesh"
50     bl_options = {"REGISTER", "UNDO"}
51     OFFSET=bpy.props.FloatProperty(name="Offset", default=0.001, min=-0, max=0.1)
52
53     def execute(self,context):
54         defReconst(self, self.OFFSET)
55         return {'FINISHED'}
56
57 ## -----------------------------------SELECT LEFT---------------------
58 def side (self, nombre, offset):
59
60     bpy.ops.object.mode_set(mode="EDIT", toggle=0)
61     OBJECT = bpy.context.active_object
62     ODATA = bmesh.from_edit_mesh(OBJECT.data)
63     MODE = bpy.context.mode
64     bpy.context.tool_settings.mesh_select_mode = (True, False, False)
65     for VERTICE in ODATA.verts[:]:
66         VERTICE.select = False
67     if nombre == False:
68         for VERTICES in ODATA.verts[:]:
69             if VERTICES.co[0] < (offset):
70                 VERTICES.select = 1
71     else:
72         for VERTICES in ODATA.verts[:]:
73             if VERTICES.co[0] > (offset):
74                 VERTICES.select = 1
75     ODATA.select_flush(False)
76     bpy.ops.object.mode_set(mode="EDIT", toggle=0)
77
78 class SelectMenor (bpy.types.Operator):
79     bl_idname = "mesh.select_side_osc"
80     bl_label = "Select Side"
81     bl_options = {"REGISTER", "UNDO"}
82
83     side = bpy.props.BoolProperty(name="Greater than zero", default=False)
84     offset = bpy.props.FloatProperty(name="Offset", default=0)
85     def execute(self,context):
86
87         side(self, self.side, self.offset)
88
89         return {'FINISHED'}
90
91
92 ##-------------------------RESYM VG----------------------------------
93
94
95
96 class resymVertexGroups (bpy.types.Operator):
97     bl_idname = "mesh.resym_vertex_weights_osc"
98     bl_label = "Resym Vertex Weights"
99     bl_options = {"REGISTER", "UNDO"}
100     def execute(self,context):
101
102         OBACTIVO = bpy.context.active_object
103         VGACTIVO = OBACTIVO.vertex_groups.active.index
104         
105         bpy.ops.object.mode_set(mode='EDIT')
106         BM = bmesh.from_edit_mesh(bpy.context.object.data)  
107         bpy.ops.mesh.select_all(action='DESELECT')
108         bpy.ops.object.vertex_group_select()
109         SELVER=[VERT.index for VERT in BM.verts[:] if VERT.select]   
110         
111         SYSBAR = os.sep     
112          
113         FILEPATH=bpy.data.filepath
114         ACTIVEFOLDER=FILEPATH.rpartition(SYSBAR)[0]
115         ENTFILEPATH= "%s%s%s_%s_SYM_TEMPLATE.xml" %  (ACTIVEFOLDER, SYSBAR, bpy.context.scene.name, bpy.context.object.name)
116         XML=open(ENTFILEPATH ,mode="r")        
117         SYMAP = eval(XML.readlines()[0])      
118         INL = [VERT for VERT in SYMAP if SYMAP[VERT] in SELVER if VERT!= SYMAP[VERT]] 
119         bpy.ops.mesh.select_all(action='DESELECT')
120         for VERT in INL:
121             BM.verts[VERT].select = True
122         bpy.ops.object.vertex_group_assign(new=False)    
123         bpy.ops.object.mode_set(mode='WEIGHT_PAINT')        
124         for VERT in INL:
125             for i, GRA in enumerate(OBACTIVO.data.vertices[SYMAP[VERT]].groups[:]):
126                 if GRA.group == VGACTIVO:
127                     print (i)
128                     EM = i                    
129
130             for a, GRA in enumerate(OBACTIVO.data.vertices[VERT].groups[:]):     
131                 if GRA.group == VGACTIVO:
132                     print (a)
133                     REC = a
134
135                     
136             OBACTIVO.data.vertices[VERT].groups[REC].weight = OBACTIVO.data.vertices[SYMAP[VERT]].groups[EM].weight  
137         XML.close()
138         SYMAP.clear()  
139       
140
141         print("===============(JOB DONE)=============")
142         return {'FINISHED'}
143
144
145 ###------------------------IMPORT EXPORT GROUPS--------------------
146
147 class OscExportVG (bpy.types.Operator):
148     bl_idname = "file.export_groups_osc"
149     bl_label = "Export Groups"
150     bl_options = {"REGISTER", "UNDO"}
151     def execute(self,context):
152         
153         with open(os.path.join(os.path.split(bpy.data.filepath)[0],"%s_vg" % (bpy.context.object.name)), "w") as FILE:
154             WEIGHTLIST = [[group.group, vert.index, group.weight] for vert in bpy.context.object.data.vertices[:] for group in vert.groups[:]]
155             WEIGHTLIST.append([group.name for group in bpy.context.object.vertex_groups])
156             FILE.write(str(WEIGHTLIST))
157
158         return {'FINISHED'}
159
160 class OscImportVG (bpy.types.Operator):
161     bl_idname = "file.import_groups_osc"
162     bl_label = "Import Groups"
163     bl_options = {"REGISTER", "UNDO"}
164     def execute(self,context):
165         
166         with open(os.path.join(os.path.split(bpy.data.filepath)[0],"%s_vg" % (bpy.context.object.name)), "r") as FILE:
167             WEIGHTLIST = eval(FILE.read())
168             for group in WEIGHTLIST[-1]:
169                 bpy.context.object.vertex_groups.new(name=group)
170             for ind ,(gr, index, weight) in enumerate(WEIGHTLIST[:-1]):
171                 print(ind, gr, index, weight)
172                 bpy.context.object.vertex_groups[gr].add(index=(index,index),weight=weight, type="REPLACE")
173         
174         return {'FINISHED'}
175
176
177
178 ## ------------------------------------ RESYM MESH--------------------------------------
179
180
181 def reSymSave (self):
182     
183     bpy.ops.object.mode_set(mode='EDIT')
184     
185     BM = bmesh.from_edit_mesh(bpy.context.object.data)   
186      
187     L = {VERT.index : [VERT.co[0],VERT.co[1],VERT.co[2]] for VERT in BM.verts[:] if VERT.co[0] < 0.0001}
188     R = {VERT.index : [-VERT.co[0],VERT.co[1],VERT.co[2]]  for VERT in BM.verts[:] if VERT.co[0] > -0.0001}
189     
190     SYMAP = {VERTL : VERTR for VERTR in R for VERTL in L if R[VERTR] == L[VERTL] }            
191         
192     FILEPATH=bpy.data.filepath
193     ACTIVEFOLDER = os.path.split(FILEPATH)[0]
194     ENTFILEPATH= "%s_%s_SYM_TEMPLATE.xml" %  (os.path.join(ACTIVEFOLDER, bpy.context.scene.name), bpy.context.object.name)
195     with open(ENTFILEPATH ,mode="w") as file:   
196         file.writelines(str(SYMAP))
197         SYMAP.clear()
198
199 def reSymMesh (self, SELECTED, SIDE):    
200     bpy.ops.object.mode_set(mode='EDIT')    
201     BM = bmesh.from_edit_mesh(bpy.context.object.data)    
202     FILEPATH=bpy.data.filepath
203     ACTIVEFOLDER = os.path.split(FILEPATH)[0]
204     ENTFILEPATH= "%s_%s_SYM_TEMPLATE.xml" %  (os.path.join(ACTIVEFOLDER,bpy.context.scene.name), bpy.context.object.name)
205     with open(ENTFILEPATH ,mode="r") as file: 
206         SYMAP = eval(file.readlines()[0])    
207         if SIDE == "+-":
208             if SELECTED:
209                 for VERT in SYMAP:
210                     if BM.verts[SYMAP[VERT]].select:
211                         if VERT == SYMAP[VERT]:
212                             BM.verts[VERT].co[0] = 0
213                             BM.verts[VERT].co[1] = BM.verts[SYMAP[VERT]].co[1]
214                             BM.verts[VERT].co[2] = BM.verts[SYMAP[VERT]].co[2]            
215                         else:    
216                             BM.verts[VERT].co[0] = -BM.verts[SYMAP[VERT]].co[0]
217                             BM.verts[VERT].co[1] = BM.verts[SYMAP[VERT]].co[1]
218                             BM.verts[VERT].co[2] = BM.verts[SYMAP[VERT]].co[2]        
219             else:    
220                 for VERT in SYMAP:
221                     if VERT == SYMAP[VERT]:
222                         BM.verts[VERT].co[0] = 0
223                         BM.verts[VERT].co[1] = BM.verts[SYMAP[VERT]].co[1]
224                         BM.verts[VERT].co[2] = BM.verts[SYMAP[VERT]].co[2]            
225                     else:    
226                         BM.verts[VERT].co[0] = -BM.verts[SYMAP[VERT]].co[0]
227                         BM.verts[VERT].co[1] = BM.verts[SYMAP[VERT]].co[1]
228                         BM.verts[VERT].co[2] = BM.verts[SYMAP[VERT]].co[2]
229         else:
230             if SELECTED:
231                 for VERT in SYMAP:
232                     if BM.verts[VERT].select:
233                         if VERT == SYMAP[VERT]:
234                             BM.verts[SYMAP[VERT]].co[0] = 0
235                             BM.verts[SYMAP[VERT]].co[1] = BM.verts[VERT].co[1]
236                             BM.verts[SYMAP[VERT]].co[2] = BM.verts[VERT].co[2]            
237                         else:    
238                             BM.verts[SYMAP[VERT]].co[0] = -BM.verts[VERT].co[0]
239                             BM.verts[SYMAP[VERT]].co[1] = BM.verts[VERT].co[1]
240                             BM.verts[SYMAP[VERT]].co[2] = BM.verts[VERT].co[2]        
241             else:    
242                 for VERT in SYMAP:
243                     if VERT == SYMAP[VERT]:
244                         BM.verts[SYMAP[VERT]].co[0] = 0
245                         BM.verts[SYMAP[VERT]].co[1] = BM.verts[VERT].co[1]
246                         BM.verts[SYMAP[VERT]].co[2] = BM.verts[VERT].co[2]            
247                     else:    
248                         BM.verts[SYMAP[VERT]].co[0] = -BM.verts[VERT].co[0]
249                         BM.verts[SYMAP[VERT]].co[1] = BM.verts[VERT].co[1]
250                         BM.verts[SYMAP[VERT]].co[2] = BM.verts[VERT].co[2]                    
251         
252         bpy.ops.object.mode_set(mode='OBJECT')
253         bpy.ops.object.mode_set(mode='EDIT')
254         SYMAP.clear()
255         
256 class OscResymSave (bpy.types.Operator):
257     bl_idname = "mesh.resym_save_map"
258     bl_label = "Resym save XML Map"
259     bl_options = {"REGISTER", "UNDO"}
260
261     def execute (self, context):
262         reSymSave(self)
263         return {'FINISHED'}
264
265 class OscResymMesh (bpy.types.Operator):
266     bl_idname = "mesh.resym_mesh"
267     bl_label = "Resym save Apply XML"
268     bl_options = {"REGISTER", "UNDO"}
269
270     selected=bpy.props.BoolProperty(default=False, name="Only Selected")
271     
272     side = bpy.props.EnumProperty(
273             name="Side:",
274             description="Select Side.",
275             items=(('+-', "+X to -X", "+X to -X"),
276                    ('-+', "-X to +X", "-X to +X")),
277             default='+-',
278             )    
279     
280     def execute (self, context):
281         reSymMesh(self, self.selected,self.side)
282         return {'FINISHED'}
283     
284
285
286 ## -------------------------- OBJECT TO MESH --------------------------------------
287
288 def DefOscObjectToMesh():
289     ACTOBJ = bpy.context.object
290     MESH = ACTOBJ.to_mesh(scene=bpy.context.scene, apply_modifiers=True, settings="RENDER", calc_tessface=True)
291     OBJECT = bpy.data.objects.new(("%s_Freeze") % (ACTOBJ.name), MESH)
292     bpy.context.scene.objects.link(OBJECT)
293
294 class OscObjectToMesh(bpy.types.Operator):
295     bl_idname = "mesh.object_to_mesh_osc"
296     bl_label = "Object To Mesh"
297
298     @classmethod
299     def poll(cls, context):
300         return True if context.active_object is not None and context.object.type == "MESH" else False
301
302     def execute(self, context):
303         DefOscObjectToMesh()
304         return {'FINISHED'}
305
306
307 ## ----------------------------- OVERLAP UV --------------------------------------------
308
309
310 def DefOscOverlapUv():
311     rd = 4
312     ACTOBJ = bpy.context.object
313     inicio= time.time()
314     bpy.ops.mesh.faces_mirror_uv(direction='POSITIVE')
315     bpy.ops.object.mode_set(mode='OBJECT')
316     SELUVVERT = [ver for ver in ACTOBJ.data.uv_layers[ACTOBJ.data.uv_textures.active.name].data[:] if ver.select]
317     MAY = [ver for ver in SELUVVERT if ver.uv[0] > .5]
318     
319     for vl in MAY:
320         vl.uv = (1-vl.uv[0],vl.uv[1])   
321                    
322     bpy.ops.object.mode_set(mode='EDIT')
323     print("Time elapsed: %4s seconds" % (time.time()-inicio))
324
325 class OscOverlapUv(bpy.types.Operator):
326     bl_idname = "mesh.overlap_uv_faces"
327     bl_label = "Overlap Uvs"
328
329
330     def execute(self, context):
331         DefOscOverlapUv()
332         return {'FINISHED'}