OSDN Git Service

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