OSDN Git Service

update bone group export.
[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
302 class material:
303     @staticmethod
304     def create(name):
305         return bpy.data.materials.new(name)
306
307     @staticmethod
308     def get(material_name):
309         return bpy.data.materials[material_name]
310
311     @staticmethod
312     def addTexture(material, texture, enable=True):
313         # search free slot
314         index=None
315         for i, slot in enumerate(material.texture_slots):
316             if not slot:
317                 index=i
318                 break
319         if index==None:
320             return
321
322         if enable:
323             material.add_texture(texture, "UV", "COLOR")
324             slot=material.texture_slots[index]
325             slot.blend_type='MULTIPLY'
326             slot.map_alpha=True
327         else:
328             material.add_texture(texture)
329             material.use_textures[index]=False
330         return index
331
332     @staticmethod
333     def getTexture(material, index):
334         return material.texture_slots[index].texture
335
336     @staticmethod
337     def hasTexture(material):
338         return material.texture_slots[0]
339
340     @staticmethod
341     def setUseTexture(material, index, enable):
342         material.use_textures[index]=enable
343
344     @staticmethod
345     def eachTexturePath(m):
346         for slot in m.texture_slots:
347             if slot and slot.texture:
348                 texture=slot.texture
349                 if  texture.type=="IMAGE":
350                     image=texture.image
351                     if not image:
352                         continue
353                     yield image.filename
354
355 class mesh:
356     @staticmethod
357     def create(name):
358         global SCENE
359         mesh=bpy.data.meshes.new("Mesh")
360         mesh_object= bpy.data.objects.new(name, mesh)
361         SCENE.objects.link(mesh_object)
362         return mesh, mesh_object
363
364     @staticmethod
365     def addGeometry(mesh, vertices, faces):
366         mesh.from_pydata(vertices, [], faces)
367         """
368         mesh.add_geometry(len(vertices), 0, len(faces))
369         # add vertex
370         unpackedVertices=[]
371         for v in vertices:
372             unpackedVertices.extend(v)
373         mesh.verts.foreach_set("co", unpackedVertices)
374         # add face
375         unpackedFaces = []
376         for face in faces:
377             if len(face) == 4:
378                 if face[3] == 0:
379                     # rotate indices if the 4th is 0
380                     face = [face[3], face[0], face[1], face[2]]
381             elif len(face) == 3:
382                 if face[2] == 0:
383                     # rotate indices if the 3rd is 0
384                     face = [face[2], face[0], face[1], 0]
385                 else:
386                     face.append(0)
387             unpackedFaces.extend(face)
388         mesh.faces.foreach_set("verts_raw", unpackedFaces)
389         """
390         assert(len(vertices)==len(mesh.verts))
391         assert(len(faces)==len(mesh.faces))
392
393     @staticmethod
394     def hasUV(mesh):
395         return mesh.active_uv_texture
396
397     @staticmethod
398     def useVertexUV(mesh):
399         pass
400
401     @staticmethod
402     def addUV(mesh):
403         mesh.add_uv_texture()
404
405     @staticmethod
406     def hasFaceUV(mesh, i, face):
407         return mesh.active_uv_texture and mesh.active_uv_texture.data[i]
408
409     @staticmethod
410     def getFaceUV(mesh, i, faces, count=3):
411         if mesh.active_uv_texture and mesh.active_uv_texture.data[i]:
412             uvFace=mesh.active_uv_texture.data[i]
413             if count==3:
414                 return (uvFace.uv1, uvFace.uv2, uvFace.uv3)
415             elif count==4:
416                 return (uvFace.uv1, uvFace.uv2, uvFace.uv3, uvFace.uv4)
417             else:
418                 print(count)
419                 assert(False)
420         else:
421             return ((0, 0), (0, 0), (0, 0), (0, 0))
422
423     @staticmethod
424     def setFaceUV(mesh, i, face, uv_array, image):
425         uv_face=mesh.uv_textures[0].data[i]
426         uv_face.uv=uv_array
427         if image:
428             uv_face.image=image
429             uv_face.tex=True
430
431     @staticmethod
432     def vertsDelete(mesh, remove_vertices):
433         enterEditMode()
434         bpy.ops.mesh.select_all(action='DESELECT')
435         enterObjectMode()
436
437         for i in remove_vertices:
438             mesh.verts[i].selected=True
439
440         enterEditMode()
441         bpy.ops.mesh.delete(type='VERT')
442         enterObjectMode()
443
444     @staticmethod
445     def setSmooth(mesh, smoothing):
446         mesh.autosmooth_angle=int(smoothing)
447         mesh.autosmooth=True
448
449     @staticmethod
450     def recalcNormals(mesh_object):
451         bpy.ops.object.select_all(action='DESELECT')
452         object.activate(mesh_object)
453         enterEditMode()
454         bpy.ops.mesh.normals_make_consistent()
455         enterObjectMode()
456
457     @staticmethod
458     def flipNormals(mesh):
459         mesh.flipNormals()
460
461     @staticmethod
462     def addMaterial(mesh, material):
463         mesh.add_material(material)
464
465
466 class vertex:
467     @staticmethod
468     def setNormal(mvert, normal):
469         mvert.normal=mathutils.Vector(normal)
470
471     @staticmethod
472     def setUv(mvert, uv):
473         pass
474
475
476 class face:
477     @staticmethod
478     def getVertexCount(face):
479         return len(face.verts)
480
481     @staticmethod
482     def getVertices(face):
483         return face.verts[:]
484
485     @staticmethod
486     def getIndices(face, count=3):
487         if count==3:
488             return [face.verts[0], face.verts[1], face.verts[2]]
489         elif count==4:
490             return [face.verts[0], face.verts[1], face.verts[2], face.verts[3]]
491         else:
492             assert(False)
493
494     @staticmethod
495     def setMaterial(face, material_index):
496         face.material_index=material_index
497
498     @staticmethod
499     def getMaterialIndex(face):
500         return face.material_index
501
502     @staticmethod
503     def setNormal(face, normal):
504         face.normal=normal
505
506     @staticmethod
507     def getNormal(face):
508         return face.normal
509
510     @staticmethod
511     def setSmooth(face, isSmooth):
512         face.smooth=True if isSmooth else False
513
514
515 class armature:
516     @staticmethod
517     def create():
518         global SCENE
519         armature = bpy.data.armatures.new('Armature')
520         armature_object=bpy.data.objects.new('Armature', armature)
521         SCENE.objects.link(armature_object)
522
523         armature_object.x_ray=True
524         armature.draw_names=True
525         #armature.drawtype='OCTAHEDRAL'
526         armature.drawtype='STICK'
527         armature.deform_envelope=False
528         armature.deform_vertexgroups=True
529         armature.x_axis_mirror=True
530
531         return armature, armature_object
532
533     @staticmethod
534     def makeEditable(armature_object):
535         global SCENE
536         # select only armature object and set edit mode
537         SCENE.objects.active=armature_object
538         bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
539         bpy.ops.object.mode_set(mode='EDIT', toggle=False)
540
541     @staticmethod
542     def createIkConstraint(armature_object, p_bone, effector_name, ik):
543         constraint = p_bone.constraints.new('IK')
544         constraint.chain_length=len(ik.children)
545         constraint.target=armature_object
546         constraint.subtarget=effector_name
547         constraint.use_tail=False
548         # not used. place folder when export.
549         constraint.weight=ik.weight
550         constraint.iterations=ik.iterations * 10
551         return constraint
552
553     @staticmethod
554     def createBone(armature, name):
555         return armature.edit_bones.new(name)
556
557     @staticmethod
558     def update(armature):
559         pass
560
561
562 class bone:
563     @staticmethod
564     def setConnected(bone):
565         bone.connected=True
566
567     @staticmethod
568     def isConnected(b):
569         return b.connected
570
571     @staticmethod
572     def setLayerMask(bone, layers):
573         layer=[]
574         for i in range(32):
575             try:
576                 layer.append(True if layers[i]!=0 else False)
577             except IndexError:
578                 layer.append(False)
579         bone.layer=layer
580
581     @staticmethod
582     def getHeadLocal(b):
583         return b.head_local[0:3]
584
585     @staticmethod
586     def getTailLocal(b):
587         return b.tail_local[0:3]
588
589
590 class constraint:
591     @staticmethod
592     def ikChainLen(c):
593         return c.chain_length
594
595     @staticmethod
596     def ikTarget(c):
597         return c.subtarget
598
599     @staticmethod
600     def ikItration(c):
601         return c.iterations
602
603     @staticmethod
604     def ikRotationWeight(c):
605         return c.weight
606
607     @staticmethod
608     def isIKSolver(c):
609         return c.type=='IK'
610
611