OSDN Git Service

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