OSDN Git Service

fix bone group name.
[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
276 class modifier:
277     @staticmethod
278     def addMirror(mesh_object):
279         return mesh_object.modifiers.append(Blender.Modifier.Types.MIRROR)
280
281     @staticmethod
282     def addArmature(mesh_object, armature_object):
283         mod=mesh_object.modifiers.append(Blender.Modifier.Types.ARMATURE)
284         mod[Blender.Modifier.Settings.OBJECT] = armature_object
285         mod[Blender.Modifier.Settings.ENVELOPES] = False
286
287     @staticmethod
288     def hasType(mesh_object, type_name):
289         for mod in mesh_object.modifiers:
290                 if mod.name.upper()==type_name.upper():
291                     return True
292
293     @staticmethod
294     def isType(m, type_name):
295         return m.name.upper()==type_name.upper()
296
297     @staticmethod
298     def getArmatureObject(m):
299         return m[Blender.Modifier.Settings.OBJECT]
300
301
302 class shapekey:
303     @staticmethod
304     def assign(b, index, pos):
305         b.data[index]=pos
306
307     @staticmethod
308     def getByIndex(b, index):
309         return b.data[index]
310
311     @staticmethod
312     def get(b):
313         return b.data
314
315
316 class texture:
317     @staticmethod
318     @to_internal_encoding
319     def create(path):
320         try:
321             image = Blender.Image.Load(path)
322         except IOError:
323             image = None
324         texture = Blender.Texture.New(path)
325         texture.type = Blender.Texture.Types.IMAGE
326         texture.image = image
327         texture.imageFlags|=Blender.Texture.ImageFlags.USEALPHA
328         return texture, image
329
330
331 class material:
332     @staticmethod
333     @to_internal_encoding
334     def create(name):
335         m = Blender.Material.New(name)
336         return m
337
338     @staticmethod
339     def get(material_name):
340         return Blender.Material.Get(material_name)
341
342     @staticmethod
343     def addTexture(m, texture, enable=True):
344         for i in xrange(10):
345             if m.textures[i]:
346                 continue
347             if enable:
348                 m.mode = m.mode | Blender.Material.Modes.TEXFACE
349                 m.setTexture(i, texture, Blender.Texture.TexCo.UV)
350             else:
351                 m.setTexture(i, texture)
352                 material.setUseTexture(m, i, False)
353             return i
354
355     @staticmethod
356     def getTexture(m, index):
357         return m.textures[index]
358
359     @staticmethod
360     def hasTexture(m):
361         return len(m.getTextures())>0
362
363     @staticmethod
364     def setUseTexture(m, index, enable):
365         enable_textures=set(m.enabledTextures)
366         if enable:
367             enabledTextures.add(index)
368         else;
369             enabledTextures.remove(index)
370         m.enabledTextures=list(enabledTextures)
371
372     @staticmethod
373     def eachTexturePath(m, dirname):
374         for texture in m.getTextures():
375             if texture and texture.tex and texture.tex.getImage():
376                 image=texture.tex.getImage()
377                 if not image:
378                     continue
379                 yield image.getFilename()
380
381
382 class mesh:
383     @staticmethod
384     @to_internal_encoding
385     def create(name):
386         global SCENE
387         m=Blender.Mesh.New()
388         o=SCENE.objects.new(m, name)
389         return m, o
390
391     @staticmethod
392     def addGeometry(m, vertices, faces):
393         m.verts.extend(vertices)
394         new_faces=m.faces.extend(faces,
395                 #ignoreDups=True, 
396                 indexList=True)
397         m.update()
398
399     @staticmethod
400     def hasUV(m):
401         return m.faceUV
402
403     @staticmethod
404     def useVertexUV(m):
405         m.vertexUV = 1
406
407     @staticmethod
408     def addUV(m):
409         m.addUVLayer('NewUV')
410
411     @staticmethod
412     def hasFaceUV(m, i, face):
413         return len(face.uv)>0
414
415     @staticmethod
416     def getFaceUV(m, i, face, count=3):
417         return face.uv
418
419     @staticmethod
420     def setFaceUV(m, i, face, uv_array, image):
421         face.uv=[Mathutils.Vector(uv[0], uv[1]) for uv in  uv_array]
422         if image:
423             face.image=image
424
425     @staticmethod
426     def vertsDelete(m, remove_vertices):
427         m.verts.delete(remove_vertices)
428
429     @staticmethod
430     def setSmooth(m, smoothing):
431         m.mode |= Blender.Mesh.Modes.AUTOSMOOTH
432         m.degr=int(smoothing)
433         #m.smooth()
434
435     @staticmethod
436     def recalcNormals(mesh_object):
437         m=mesh_object.getData(mesh=True)
438         m.calcNormals() 
439
440     @staticmethod
441     def flipNormals(m):
442         m.flipNormals()
443
444     @staticmethod
445     def addMaterial(m, material):
446         m.materials+=[material]
447
448
449 class vertex:
450     @staticmethod
451     def setNormal(mvert, normal):
452         mvert.no=Mathutils.Vector(*normal)
453
454     @staticmethod
455     def setUv(mvert, uv):
456         mvert.uvco=uv
457
458
459 class face:
460     @staticmethod
461     def getVertexCount(face):
462         return len(face.v)
463
464     @staticmethod
465     def getVertices(face):
466         return [v.index for v in face.v]
467
468     @staticmethod
469     def getIndices(face):
470         return [face.verts[0].index, face.verts[1].index, face.verts[2].index]
471
472     @staticmethod
473     def setMaterial(face, material_index):
474         face.mat=material_index
475
476     @staticmethod
477     def getMaterialIndex(face):
478         return face.mat
479
480     @staticmethod
481     def setNormal(face, normal):
482         face.no=normal
483
484     @staticmethod
485     def getNormal(face):
486         return face.no
487
488     @staticmethod
489     def setSmooth(face, isSmooth):
490         face.smooth=1 if isSmooth else 0
491      
492
493 class armature:
494     @staticmethod
495     def create():
496         global SCENE
497         armature = Blender.Armature.New()
498         armature_object = SCENE.objects.new(armature)
499
500         # set XRAY
501         armature_object.drawMode = (
502                 armature_object.drawMode | Blender.Object.DrawModes.XRAY)
503         # armature settings
504         armature.drawType = Blender.Armature.OCTAHEDRON
505         armature.drawNames=True
506         armature.envelopes = False
507         armature.vertexGroups = True
508         armature.mirrorEdit = True
509
510         return armature, armature_object
511
512     @staticmethod
513     def makeEditable(armature_object):
514         # create armature
515         armature_object.getData().makeEditable()
516
517     @staticmethod
518     def createIkConstraint(armature_object, p_bone, effector_name, ik):
519         cSetting = Blender.Constraint.Settings
520         # IK solver
521         constraint = p_bone.constraints.append(Blender.Constraint.Type.IKSOLVER)
522         constraint[cSetting.CHAINLEN]=len(ik.children)
523         constraint[cSetting.TARGET]=armature_object
524         constraint[cSetting.USETIP]=False
525         constraint[cSetting.BONE]=effector_name
526         # not used. place folder when export.
527         constraint[cSetting.ROTWEIGHT]=ik.weight
528         constraint[cSetting.ITERATIONS]=ik.iterations * 10
529         return constraint
530
531     @staticmethod
532     @to_internal_encoding
533     def createBone(armature_object, name):
534         bone=Blender.Armature.Editbone()
535         bone.name=name
536         armature_object.bones[name]=bone
537         return bone
538
539     @staticmethod
540     def update(armature):
541         armature.update()
542
543
544 class bone:
545     @staticmethod
546     def setConnected(bone):
547         bone.options+=[Blender.Armature.CONNECTED]
548
549     @staticmethod
550     def isConnected(b):
551         return Blender.Armature.CONNECTED in b.options
552
553     @staticmethod
554     def setLayerMask(bone, layers):
555         mask=0
556         for i, enable in enumerate(layers):
557             if enable!=0:
558                 mask+=(1<<i)
559         bone.layerMask=mask
560
561     @staticmethod
562     def getHeadLocal(b):
563         return b.head['ARMATURESPACE'][0:3]
564
565     @staticmethod
566     def getTailLocal(b):
567         return b.tail['ARMATURESPACE'][0:3]
568
569
570 class constraint:
571     @staticmethod
572     def ikChainLen(c):
573         return c[Blender.Constraint.Settings.CHAINLEN]
574
575     @staticmethod
576     def ikTarget(c):
577         return c[Blender.Constraint.Settings.BONE]
578
579     @staticmethod
580     def ikItration(c):
581         return c[Blender.Constraint.Settings.ITERATIONS]
582
583     @staticmethod
584     def ikRotationWeight(c):
585         return c[Blender.Constraint.Settings.ROTWEIGHT]
586
587     @staticmethod
588     def isIKSolver(c):
589         return c.type==Blender.Constraint.Type.IKSOLVER
590
591