OSDN Git Service

fix export vertex map.
[meshio/meshio.git] / swig / blender / bl25.py
1 # coding: utf-8
2 import os
3 import sys
4 import time
5 import functools
6
7 try:
8     import bpy
9     import mathutils
10 except:
11     pass
12
13\e$B%U%!%$%k%7%9%F%`$NJ8;z%3!<%I\e(B
14\e$B2~B$HG$H$N6&MQ$N$?$a\e(B
15 FS_ENCODING=sys.getfilesystemencoding()
16 if os.path.exists(os.path.dirname(sys.argv[0])+"/utf8"):
17     INTERNAL_ENCODING='utf-8'
18 else:
19     INTERNAL_ENCODING=FS_ENCODING
20
21 SCENE=None
22 def initialize(name, scene):
23     global SCENE
24     SCENE=scene
25     progress_start(name)
26
27 def finalize():
28     scene.update(SCENE)
29     progress_finish()
30
31 def message(msg):
32     pass
33
34 def enterEditMode():
35     bpy.ops.object.mode_set(mode='EDIT', toggle=False)
36
37 def enterObjectMode():
38     bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
39
40 def enterPoseMode():
41     bpy.ops.object.mode_set(mode='POSE', toggle=False)
42
43 def createVector(x, y, z):
44     return mathutils.Vector([x, y, z])
45
46
47 class Writer(object):
48     '''
49     io wrapper
50     '''
51     def __init__(self, path, encoding):
52         self.io=open(path, "wb")
53         self.encoding=encoding
54
55     def write(self, s):
56         self.io.write(s.encode(self.encoding))
57
58     def flush(self):
59         self.io.flush()
60
61     def close(self):
62         self.io.close()
63
64
65 class ProgressBar(object):
66     '''
67     progress bar wrapper
68     '''
69     def __init__(self, base):
70         print("#### %s ####" % base)
71         self.base=base
72         self.start=time.time() 
73         self.set('<start>', 0)
74
75     def advance(self, message, progress):
76         self.progress+=float(progress)
77         self._print(message)
78
79     def set(self, message, progress):
80         self.progress=float(progress)
81         self._print(message)
82
83     def _print(self, message):
84         print(message)
85         message="%s: %s" % (self.base, message)
86         #Blender.Window.DrawProgressBar(self.progress, message)
87
88     def finish(self):
89         self.progress=1.0
90         message='finished in %.2f sec' % (time.time()-self.start)
91         self.set(message, 1.0)
92
93 def progress_start(base):
94     global progressBar
95     progressBar=ProgressBar(base)
96
97 def progress_finish():
98     global progressBar
99     progressBar.finish()
100
101 def progress_print(message, progress=0.05):
102     global progressBar
103     progressBar.advance(message, progress)
104
105 def progress_set(message, progress):
106     global progressBar
107     progressBar.set(message, progress)
108
109
110 class scene:
111     @staticmethod
112     def update(scene):
113         scene.update()
114
115
116 class object:
117     @staticmethod
118     def createEmpty(name):
119         global SCENE
120         empty=bpy.data.objects.new(name, None)
121         SCENE.objects.link(empty)
122         return empty
123
124     @staticmethod
125     def makeParent(parent, child):
126         child.parent=parent
127
128     @staticmethod
129     def duplicate(o):
130         global SCENE
131         bpy.ops.object.select_all(action='DESELECT')
132         o.selected=True
133         SCENE.objects.active=o
134         bpy.ops.object.duplicate()
135         dumy=SCENE.objects.active
136         #bpy.ops.object.rotation_apply()
137         #bpy.ops.object.scale_apply()
138         #bpy.ops.object.location_apply()
139         return dumy.data, dumy
140
141     @staticmethod
142     def delete(o):
143         global SCENE
144         SCENE.objects.unlink(o)
145
146     @staticmethod
147     def getData(o):
148         return o.data
149
150     @staticmethod
151     def select(o):
152         o.selected=True
153
154     @staticmethod
155     def activate(o):
156         global SCENE
157         o.selected=True 
158         SCENE.objects.active=o
159
160     @staticmethod
161     def getActive():
162         global SCENE 
163         return SCENE.objects.active
164
165     @staticmethod
166     def deselectAll():
167         bpy.ops.object.select_all(action='DESELECT')
168
169     @staticmethod
170     def setLayerMask(object, layers):
171         layer=[]
172         for i in range(20):
173             try:
174                 layer.append(True if layers[i]!=0 else False)
175             except IndexError:
176                 layer.append(False)
177         object.layers=layer
178
179     @staticmethod
180     def isVisible(o):
181         return o.restrict_view
182
183     @staticmethod
184     def getShapeKeys(o):
185         return o.data.shape_keys.keys
186
187     @staticmethod
188     def addShapeKey(o, name):
189         return o.add_shape_key(name)
190
191     @staticmethod
192     def hasShapeKey(o):
193         return o.data.shape_keys
194
195     @staticmethod
196     def pinShape(o, enable):
197         o.shape_key_lock=enable
198
199     @staticmethod
200     def setActivateShapeKey(o, index):
201         o.active_shape_key_index=index
202
203     @staticmethod
204     def getPose(o):
205         return o.pose
206
207     @staticmethod
208     def getVertexGroup(o, name):
209         indices=[]
210         for i, v in enumerate(o.data.verts):
211             for g in v.groups:
212                 if o.vertex_groups[g.group].name==name:
213                     indices.append(i)
214         return indices
215
216     @staticmethod
217     def getVertexGroupNames(o):
218         for g in o.vertex_groups:
219             yield g.name
220
221     @staticmethod
222     def addVertexGroup(o, name):
223         o.add_vertex_group(name)
224
225     @staticmethod
226     def assignVertexGroup(o, name, index, weight):
227         o.add_vertex_to_group(index, 
228                     o.vertex_groups[name], weight, 'ADD')
229
230     @staticmethod
231     def createBoneGroup(o, name, color_set='DEFAULT'):
232         # create group
233         object.activate(o)
234         enterPoseMode()
235         bpy.ops.pose.group_add()
236         # set name
237         pose=object.getPose(o)
238         g=pose.active_bone_group
239         g.name=name
240         g.color_set=color_set
241
242     @staticmethod
243     def boneGroups(o):
244         return object.getPose(o).bone_groups
245
246
247 class modifier:
248     @staticmethod
249     def addMirror(mesh_object):
250         return mesh_object.modifiers.new("Modifier", "MIRROR")
251
252     @staticmethod
253     def addArmature(mesh_object, armature_object):
254         mod=mesh_object.modifiers.new("Modifier", "ARMATURE")
255         mod.object = armature_object
256         mod.use_bone_envelopes=False
257
258     @staticmethod
259     def hasType(mesh_object, type_name):
260         for mod in mesh_object.modifiers:
261                 if mod.type==type_name.upper():
262                     return True
263
264     @staticmethod
265     def isType(m, type_name):
266         return m.type==type_name.upper()
267
268     @staticmethod
269     def getArmatureObject(m):
270         return m.object
271
272
273 class shapekey:
274     @staticmethod
275     def assign(shapeKey, index, pos):
276         shapeKey.data[index].co=pos
277
278     @staticmethod
279     def getByIndex(b, index):
280         return b.data[index].co
281
282     @staticmethod
283     def get(b):
284         for k in b.data:
285             yield k.co
286
287
288 class texture:
289     @staticmethod
290     def create(path):
291         texture=bpy.data.textures.new(os.path.basename(path))
292         texture.type='IMAGE'
293         texture=texture.recast_type()
294         image=bpy.data.images.load(path)
295         texture.image=image
296         texture.mipmap=True
297         texture.interpolation=True
298         texture.use_alpha=True
299         return texture, image
300
301     @staticmethod
302     def getPath(t):
303         if  t.type=="IMAGE":
304             image=t.image
305             if image:
306                 return image.filename
307
308
309 class material:
310     @staticmethod
311     def create(name):
312         return bpy.data.materials.new(name)
313
314     @staticmethod
315     def get(material_name):
316         return bpy.data.materials[material_name]
317
318     @staticmethod
319     def addTexture(material, texture, enable=True):
320         # search free slot
321         index=None
322         for i, slot in enumerate(material.texture_slots):
323             if not slot:
324                 index=i
325                 break
326         if index==None:
327             return
328
329         if enable:
330             material.add_texture(texture, "UV", "COLOR")
331             slot=material.texture_slots[index]
332             slot.blend_type='MULTIPLY'
333             slot.map_alpha=True
334         else:
335             material.add_texture(texture)
336             material.use_textures[index]=False
337         return index
338
339     @staticmethod
340     def getTexture(material, index):
341         return material.texture_slots[index].texture
342
343     @staticmethod
344     def hasTexture(material):
345         return material.texture_slots[0]
346
347     @staticmethod
348     def setUseTexture(material, index, enable):
349         material.use_textures[index]=enable
350
351     @staticmethod
352     def eachTexturePath(m):
353         for slot in m.texture_slots:
354             if slot and slot.texture:
355                 texture=slot.texture
356                 if  texture.type=="IMAGE":
357                     image=texture.image
358                     if not image:
359                         continue
360                     yield image.filename
361
362
363 class mesh:
364     @staticmethod
365     def create(name):
366         global SCENE
367         mesh=bpy.data.meshes.new("Mesh")
368         mesh_object= bpy.data.objects.new(name, mesh)
369         SCENE.objects.link(mesh_object)
370         return mesh, mesh_object
371
372     @staticmethod
373     def addGeometry(mesh, vertices, faces):
374         mesh.from_pydata(vertices, [], faces)
375         """
376         mesh.add_geometry(len(vertices), 0, len(faces))
377         # add vertex
378         unpackedVertices=[]
379         for v in vertices:
380             unpackedVertices.extend(v)
381         mesh.verts.foreach_set("co", unpackedVertices)
382         # add face
383         unpackedFaces = []
384         for face in faces:
385             if len(face) == 4:
386                 if face[3] == 0:
387                     # rotate indices if the 4th is 0
388                     face = [face[3], face[0], face[1], face[2]]
389             elif len(face) == 3:
390                 if face[2] == 0:
391                     # rotate indices if the 3rd is 0
392                     face = [face[2], face[0], face[1], 0]
393                 else:
394                     face.append(0)
395             unpackedFaces.extend(face)
396         mesh.faces.foreach_set("verts_raw", unpackedFaces)
397         """
398         assert(len(vertices)==len(mesh.verts))
399         assert(len(faces)==len(mesh.faces))
400
401     @staticmethod
402     def hasUV(mesh):
403         return mesh.active_uv_texture
404
405     @staticmethod
406     def useVertexUV(mesh):
407         pass
408
409     @staticmethod
410     def addUV(mesh):
411         mesh.add_uv_texture()
412
413     @staticmethod
414     def hasFaceUV(mesh, i, face):
415         return mesh.active_uv_texture and mesh.active_uv_texture.data[i]
416
417     @staticmethod
418     def getFaceUV(mesh, i, faces, count=3):
419         if mesh.active_uv_texture and mesh.active_uv_texture.data[i]:
420             uvFace=mesh.active_uv_texture.data[i]
421             if count==3:
422                 return (uvFace.uv1, uvFace.uv2, uvFace.uv3)
423             elif count==4:
424                 return (uvFace.uv1, uvFace.uv2, uvFace.uv3, uvFace.uv4)
425             else:
426                 print(count)
427                 assert(False)
428         else:
429             return ((0, 0), (0, 0), (0, 0), (0, 0))
430
431     @staticmethod
432     def setFaceUV(m, i, face, uv_array, image):
433         uv_face=m.uv_textures[0].data[i]
434         uv_face.uv=uv_array
435         if image:
436             uv_face.image=image
437             uv_face.tex=True
438
439     @staticmethod
440     def vertsDelete(m, remove_vertices):
441         enterEditMode()
442         bpy.ops.mesh.select_all(action='DESELECT')
443         enterObjectMode()
444
445         for i in remove_vertices:
446             m.verts[i].selected=True
447
448         enterEditMode()
449         bpy.ops.mesh.delete(type='VERT')
450         enterObjectMode()
451
452     @staticmethod
453     def setSmooth(m, smoothing):
454         m.autosmooth_angle=int(smoothing)
455         m.autosmooth=True
456
457     @staticmethod
458     def recalcNormals(mesh_object):
459         bpy.ops.object.select_all(action='DESELECT')
460         object.activate(mesh_object)
461         enterEditMode()
462         bpy.ops.mesh.normals_make_consistent()
463         enterObjectMode()
464
465     @staticmethod
466     def flipNormals(m):
467         m.flipNormals()
468
469     @staticmethod
470     def addMaterial(m, material):
471         m.add_material(material)
472
473     @staticmethod
474     def getMaterial(m, index):
475         return m.materials[index]
476
477
478 class vertex:
479     @staticmethod
480     def setNormal(mvert, normal):
481         mvert.normal=mathutils.Vector(normal)
482
483     @staticmethod
484     def setUv(mvert, uv):
485         pass
486
487
488 class face:
489     @staticmethod
490     def getVertexCount(face):
491         return len(face.verts)
492
493     @staticmethod
494     def getVertices(face):
495         return face.verts[:]
496
497     @staticmethod
498     def getIndices(face, count=3):
499         if count==3:
500             return [face.verts[0], face.verts[1], face.verts[2]]
501         elif count==4:
502             return [face.verts[0], face.verts[1], face.verts[2], face.verts[3]]
503         else:
504             assert(False)
505
506     @staticmethod
507     def setMaterial(face, material_index):
508         face.material_index=material_index
509
510     @staticmethod
511     def getMaterialIndex(face):
512         return face.material_index
513
514     @staticmethod
515     def setNormal(face, normal):
516         face.normal=normal
517
518     @staticmethod
519     def getNormal(face):
520         return face.normal
521
522     @staticmethod
523     def setSmooth(face, isSmooth):
524         face.smooth=True if isSmooth else False
525
526
527 class armature:
528     @staticmethod
529     def create():
530         global SCENE
531         armature = bpy.data.armatures.new('Armature')
532         armature_object=bpy.data.objects.new('Armature', armature)
533         SCENE.objects.link(armature_object)
534
535         armature_object.x_ray=True
536         armature.draw_names=True
537         #armature.drawtype='OCTAHEDRAL'
538         armature.drawtype='STICK'
539         armature.deform_envelope=False
540         armature.deform_vertexgroups=True
541         armature.x_axis_mirror=True
542
543         return armature, armature_object
544
545     @staticmethod
546     def makeEditable(armature_object):
547         global SCENE
548         # select only armature object and set edit mode
549         SCENE.objects.active=armature_object
550         bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
551         bpy.ops.object.mode_set(mode='EDIT', toggle=False)
552
553     @staticmethod
554     def createIkConstraint(armature_object, p_bone, effector_name, ik):
555         constraint = p_bone.constraints.new('IK')
556         constraint.chain_length=len(ik.children)
557         constraint.target=armature_object
558         constraint.subtarget=effector_name
559         constraint.use_tail=False
560         # not used. place folder when export.
561         constraint.weight=ik.weight
562         constraint.iterations=ik.iterations * 10
563         return constraint
564
565     @staticmethod
566     def createBone(armature, name):
567         return armature.edit_bones.new(name)
568
569     @staticmethod
570     def update(armature):
571         pass
572
573
574 class bone:
575     @staticmethod
576     def setConnected(bone):
577         bone.connected=True
578
579     @staticmethod
580     def isConnected(b):
581         return b.connected
582
583     @staticmethod
584     def setLayerMask(bone, layers):
585         layer=[]
586         for i in range(32):
587             try:
588                 layer.append(True if layers[i]!=0 else False)
589             except IndexError:
590                 layer.append(False)
591         bone.layer=layer
592
593     @staticmethod
594     def getHeadLocal(b):
595         return b.head_local[0:3]
596
597     @staticmethod
598     def getTailLocal(b):
599         return b.tail_local[0:3]
600
601
602 class constraint:
603     @staticmethod
604     def ikChainLen(c):
605         return c.chain_length
606
607     @staticmethod
608     def ikTarget(c):
609         return c.subtarget
610
611     @staticmethod
612     def ikItration(c):
613         return c.iterations
614
615     @staticmethod
616     def ikRotationWeight(c):
617         return c.weight
618
619     @staticmethod
620     def isIKSolver(c):
621         return c.type=='IK'
622
623