OSDN Git Service

update bone group export.
[meshio/meshio.git] / swig / blender / bl24.py
1 # coding: utf-8
2 import sys
3 import os
4
5 try:
6     import Blender
7     from Blender import Mathutils
8     import bpy
9 except:
10     pass
11
12 # ファイルシステムの文字コード
13 # 改造版との共用のため
14 FS_ENCODING=sys.getfilesystemencoding()
15 if os.path.exists(os.path.dirname(sys.argv[0])+"/utf8"):
16     INTERNAL_ENCODING='utf-8'
17 else:
18     INTERNAL_ENCODING=FS_ENCODING
19
20 def to_internal_encoding(fn):
21     '''
22     decorator for fix string encoding
23     '''
24     def newfn(*args):
25         return fn(*[
26             v.encode(INTERNAL_ENCODING) if isinstance(v, unicode) else v 
27             for v in args])
28     return newfn
29
30
31 SCENE=None
32 def initialize(name, scene):
33     global SCENE
34     SCENE=scene
35     progress_start(name)
36     # set object mode
37     mode_edit = Blender.Window.EditMode() 
38     if mode_edit: 
39         Blender.Window.EditMode(0)
40
41 def finalize():
42     scene.update(SCENE)
43     progress_finish()
44     # restore edit mode
45     #if mode_edit: 
46     #    Blender.Window.EditMode(1)
47
48 @to_internal_encoding
49 def message(msg):
50     res=Blender.Draw.PupMenu(msg + "%t|OK")
51     print(res)
52
53 def enterEditMode():
54     Blender.Window.EditMode(1)
55
56 def enterObjectMode():
57     Blender.Window.EditMode(0)
58
59 def enterPoseMode():
60     Blender.Window.PoseMode(1)
61
62 def createVector(x, y, z):
63     return Mathutils.Vector(x, y, z)
64
65
66 class Writer(object):
67     '''
68     io wrapper
69     '''
70     __slots__=[
71             'io', 'encoding',
72             ]
73     def __init__(self, path, encoding):
74         '''
75         path: file path to open
76         encoding: text encoding to write
77
78         '''
79         self.io=open(path, "wb")
80         self.encoding=encoding
81
82     def write(self, s):
83         self.io.write(s)
84
85     def flush(self):
86         self.io.flush()
87
88     def close(self):
89         self.io.close()
90
91
92 class ProgressBar(object):
93     '''
94     progress bar wrapper
95     '''
96     __slots__=['base', 'start', 'progress',]
97     def __init__(self, base):
98         print("#### %s ####" % base)
99         self.base=base
100         self.start=Blender.sys.time() 
101         self.set('<start>', 0)
102         Blender.Window.WaitCursor(1) 
103
104     def advance(self, message, progress):
105         self.progress+=float(progress)
106         self._print(message)
107
108     def set(self, message, progress):
109         self.progress=float(progress)
110         self._print(message)
111
112     @to_internal_encoding
113     def _print(self, message):
114         print(message.decode(INTERNAL_ENCODING))
115         message="%s: %s" % (self.base, message)
116         Blender.Window.DrawProgressBar(self.progress, message)
117
118     def finish(self):
119         self.progress=1.0
120         message='finished in %.2f sec' % (Blender.sys.time()-self.start)
121         self.set(message, 1.0)
122         Blender.Window.WaitCursor(0) 
123         Blender.Redraw()
124
125 def progress_start(base):
126     global progressBar
127     progressBar=ProgressBar(base)
128
129 def progress_finish():
130     global progressBar
131     progressBar.finish()
132
133 def progress_print(message, progress=0.05):
134     global progressBar
135     progressBar.advance(message, progress)
136
137 def progress_set(message, progress):
138     global progressBar
139     progressBar.set(message, progress)
140
141
142 class scene:
143     @staticmethod
144     def update(scene):
145         scene.update(0)
146
147
148 class object:
149     @staticmethod
150     @to_internal_encoding
151     def createEmpty(name):
152         global SCENE
153         empty=SCENE.objects.new("Empty")
154         empty.setName(name)
155         return empty
156
157     @staticmethod
158     def makeParent(parent, child):
159         parent.makeParent([child])
160
161     @staticmethod
162     def duplicate(o):
163         new_mesh, new_object=mesh.create(o.name.decode(INTERNAL_ENCODING))
164         # not apply modifiers
165         new_mesh.getFromObject(o.name, 1)
166         # apply matrix
167         #o.setMatrix(o.matrixWorld)
168         return new_mesh, new_object
169
170     @staticmethod
171     def delete(o):
172         global SCENE
173         SCENE.objects.unlink(o)
174
175     @staticmethod
176     def getData(o):
177         return o.getData(mesh=True)
178
179     @staticmethod
180     def select(o):
181         o.select(True)
182
183     @staticmethod
184     def activate(o):
185         global SCENE
186         o.select(True )
187         SCENE.objects.active=o
188
189     @staticmethod
190     def getActive():
191         global SCENE
192         return SCENE.objects.active
193
194     @staticmethod
195     def deselectAll():
196         for o in bpy.data.scenes.active.objects:
197             o.select(False)
198
199     @staticmethod
200     def setLayerMask(o, layers):
201         mask=0
202         for i, enable in enumerate(layers):
203             if enable!=0:
204                 mask+=(1<<i)
205         o.Layers=mask
206
207     @staticmethod
208     def isVisible(o):
209         return o.restrictDisplay
210
211     @staticmethod
212     def getShapeKeys(o):
213         return o.getData(mesh=True).key.blocks
214
215     @staticmethod
216     @to_internal_encoding
217     def addShapeKey(o, name):
218         mesh=o.getData(mesh=True)
219         mesh.insertKey()
220         block=mesh.key.blocks[-1]
221         block.name=name
222         return block
223
224     @staticmethod
225     def hasShapeKey(o):
226         return o.getData(mesh=True).key
227
228     @staticmethod
229     def pinShape(o, enable):
230         o.pinShape=enable
231
232     @staticmethod
233     def setActivateShapeKey(o, index):
234         o.activeShape=index
235
236     @staticmethod
237     def getPose(o):
238         return o.getPose()
239
240     @staticmethod
241     @to_internal_encoding
242     def addVertexGroup(o, name):
243         o.getData(mesh=True).addVertGroup(name)
244
245     @staticmethod
246     @to_internal_encoding
247     def assignVertexGroup(o, name, index, weight):
248         o.getData(mesh=True).assignVertsToGroup(name, 
249                 [index], weight, Blender.Mesh.AssignModes.ADD)
250
251     @staticmethod
252     def getVertexGroupNames(o):
253         return o.getData(mesh=True).getVertGroupNames()
254
255     @staticmethod
256     @to_internal_encoding
257     def getVertexGroup(o, name):
258         indices=[]
259         for index in o.getData(mesh=True).getVertsFromGroup(name):
260             indices.append(index)
261         return indices
262
263     @staticmethod
264     def createBoneGroup(o, name, color_set='DEFAULT'):
265         # create group
266         object.activate(o)
267         enterPoseMode()
268         bpy.ops.pose.group_add()
269         # set name
270         pose=object.getPose(o)
271         g=pose.active_bone_group
272         g.name=name
273         g.color_set=color_set
274
275     @staticmethod
276     def boneGroups(o):
277         return object.getPose(o).bone_groups
278
279
280 class modifier:
281     @staticmethod
282     def addMirror(mesh_object):
283         return mesh_object.modifiers.append(Blender.Modifier.Types.MIRROR)
284
285     @staticmethod
286     def addArmature(mesh_object, armature_object):
287         mod=mesh_object.modifiers.append(Blender.Modifier.Types.ARMATURE)
288         mod[Blender.Modifier.Settings.OBJECT] = armature_object
289         mod[Blender.Modifier.Settings.ENVELOPES] = False
290
291     @staticmethod
292     def hasType(mesh_object, type_name):
293         for mod in mesh_object.modifiers:
294                 if mod.name.upper()==type_name.upper():
295                     return True
296
297     @staticmethod
298     def isType(m, type_name):
299         return m.name.upper()==type_name.upper()
300
301     @staticmethod
302     def getArmatureObject(m):
303         return m[Blender.Modifier.Settings.OBJECT]
304
305
306 class shapekey:
307     @staticmethod
308     def assign(b, index, pos):
309         b.data[index]=pos
310
311     @staticmethod
312     def getByIndex(b, index):
313         return b.data[index]
314
315     @staticmethod
316     def get(b):
317         return b.data
318
319
320 class texture:
321     @staticmethod
322     @to_internal_encoding
323     def create(path):
324         try:
325             image = Blender.Image.Load(path)
326         except IOError:
327             image = None
328         texture = Blender.Texture.New(path)
329         texture.type = Blender.Texture.Types.IMAGE
330         texture.image = image
331         texture.imageFlags|=Blender.Texture.ImageFlags.USEALPHA
332         return texture, image
333
334
335 class material:
336     @staticmethod
337     @to_internal_encoding
338     def create(name):
339         m = Blender.Material.New(name)
340         return m
341
342     @staticmethod
343     def get(material_name):
344         return Blender.Material.Get(material_name)
345
346     @staticmethod
347     def addTexture(m, texture, enable=True):
348         for i in xrange(10):
349             if m.textures[i]:
350                 continue
351             if enable:
352                 m.mode = m.mode | Blender.Material.Modes.TEXFACE
353                 m.setTexture(i, texture, Blender.Texture.TexCo.UV)
354             else:
355                 m.setTexture(i, texture)
356                 material.setUseTexture(m, i, False)
357             return i
358
359     @staticmethod
360     def getTexture(m, index):
361         return m.textures[index].tex
362
363     @staticmethod
364     def hasTexture(m):
365         return len(m.getTextures())>0
366
367     @staticmethod
368     def setUseTexture(m, index, enable):
369         enabledTextures=set(m.enabledTextures)
370         if enable:
371             enabledTextures.add(index)
372         else:
373             enabledTextures.remove(index)
374         m.enabledTextures=list(enabledTextures)
375
376     @staticmethod
377     def eachTexturePath(m, dirname):
378         for texture in m.getTextures():
379             if texture and texture.tex and texture.tex.getImage():
380                 image=texture.tex.getImage()
381                 if not image:
382                     continue
383                 yield image.getFilename()
384
385
386 class mesh:
387     @staticmethod
388     @to_internal_encoding
389     def create(name):
390         global SCENE
391         m=Blender.Mesh.New()
392         o=SCENE.objects.new(m, name)
393         return m, o
394
395     @staticmethod
396     def addGeometry(m, vertices, faces):
397         m.verts.extend(vertices)
398         new_faces=m.faces.extend(faces,
399                 #ignoreDups=True, 
400                 indexList=True)
401         m.update()
402
403     @staticmethod
404     def hasUV(m):
405         return m.faceUV
406
407     @staticmethod
408     def useVertexUV(m):
409         m.vertexUV = 1
410
411     @staticmethod
412     def addUV(m):
413         m.addUVLayer('NewUV')
414
415     @staticmethod
416     def hasFaceUV(m, i, face):
417         return len(face.uv)>0
418
419     @staticmethod
420     def getFaceUV(m, i, face, count=3):
421         return face.uv
422
423     @staticmethod
424     def setFaceUV(m, i, face, uv_array, image):
425         face.uv=[Mathutils.Vector(uv[0], uv[1]) for uv in  uv_array]
426         if image:
427             face.image=image
428
429     @staticmethod
430     def vertsDelete(m, remove_vertices):
431         m.verts.delete(remove_vertices)
432
433     @staticmethod
434     def setSmooth(m, smoothing):
435         m.mode |= Blender.Mesh.Modes.AUTOSMOOTH
436         m.degr=int(smoothing)
437         #m.smooth()
438
439     @staticmethod
440     def recalcNormals(mesh_object):
441         m=mesh_object.getData(mesh=True)
442         m.calcNormals() 
443
444     @staticmethod
445     def flipNormals(m):
446         m.flipNormals()
447
448     @staticmethod
449     def addMaterial(m, material):
450         m.materials+=[material]
451
452
453 class vertex:
454     @staticmethod
455     def setNormal(mvert, normal):
456         mvert.no=Mathutils.Vector(*normal)
457
458     @staticmethod
459     def setUv(mvert, uv):
460         mvert.uvco=uv
461
462
463 class face:
464     @staticmethod
465     def getVertexCount(face):
466         return len(face.v)
467
468     @staticmethod
469     def getVertices(face):
470         return [v.index for v in face.v]
471
472     @staticmethod
473     def getIndices(face):
474         return [face.verts[0].index, face.verts[1].index, face.verts[2].index]
475
476     @staticmethod
477     def setMaterial(face, material_index):
478         face.mat=material_index
479
480     @staticmethod
481     def getMaterialIndex(face):
482         return face.mat
483
484     @staticmethod
485     def setNormal(face, normal):
486         face.no=normal
487
488     @staticmethod
489     def getNormal(face):
490         return face.no
491
492     @staticmethod
493     def setSmooth(face, isSmooth):
494         face.smooth=1 if isSmooth else 0
495      
496
497 class armature:
498     @staticmethod
499     def create():
500         global SCENE
501         armature = Blender.Armature.New()
502         armature_object = SCENE.objects.new(armature)
503
504         # set XRAY
505         armature_object.drawMode = (
506                 armature_object.drawMode | Blender.Object.DrawModes.XRAY)
507         # armature settings
508         armature.drawType = Blender.Armature.OCTAHEDRON
509         armature.drawNames=True
510         armature.envelopes = False
511         armature.vertexGroups = True
512         armature.mirrorEdit = True
513
514         return armature, armature_object
515
516     @staticmethod
517     def makeEditable(armature_object):
518         # create armature
519         armature_object.getData().makeEditable()
520
521     @staticmethod
522     def createIkConstraint(armature_object, p_bone, effector_name, ik):
523         cSetting = Blender.Constraint.Settings
524         # IK solver
525         constraint = p_bone.constraints.append(Blender.Constraint.Type.IKSOLVER)
526         constraint[cSetting.CHAINLEN]=len(ik.children)
527         constraint[cSetting.TARGET]=armature_object
528         constraint[cSetting.USETIP]=False
529         constraint[cSetting.BONE]=effector_name
530         # not used. place folder when export.
531         constraint[cSetting.ROTWEIGHT]=ik.weight
532         constraint[cSetting.ITERATIONS]=ik.iterations * 10
533         return constraint
534
535     @staticmethod
536     @to_internal_encoding
537     def createBone(armature_object, name):
538         bone=Blender.Armature.Editbone()
539         bone.name=name
540         armature_object.bones[name]=bone
541         return bone
542
543     @staticmethod
544     def update(armature):
545         armature.update()
546
547
548 class bone:
549     @staticmethod
550     def setConnected(bone):
551         bone.options+=[Blender.Armature.CONNECTED]
552
553     @staticmethod
554     def isConnected(b):
555         return Blender.Armature.CONNECTED in b.options
556
557     @staticmethod
558     def setLayerMask(bone, layers):
559         mask=0
560         for i, enable in enumerate(layers):
561             if enable!=0:
562                 mask+=(1<<i)
563         bone.layerMask=mask
564
565     @staticmethod
566     def getHeadLocal(b):
567         return b.head['ARMATURESPACE'][0:3]
568
569     @staticmethod
570     def getTailLocal(b):
571         return b.tail['ARMATURESPACE'][0:3]
572
573
574 class constraint:
575     @staticmethod
576     def ikChainLen(c):
577         return c[Blender.Constraint.Settings.CHAINLEN]
578
579     @staticmethod
580     def ikTarget(c):
581         return c[Blender.Constraint.Settings.BONE]
582
583     @staticmethod
584     def ikItration(c):
585         return c[Blender.Constraint.Settings.ITERATIONS]
586
587     @staticmethod
588     def ikRotationWeight(c):
589         return c[Blender.Constraint.Settings.ROTWEIGHT]
590
591     @staticmethod
592     def isIKSolver(c):
593         return c.type==Blender.Constraint.Type.IKSOLVER
594
595