OSDN Git Service

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