OSDN Git Service

fix bone connection.
[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(material, texture):
344         material.mode = material.mode | Blender.Material.Modes.TEXFACE
345         material.setTexture(0, texture, Blender.Texture.TexCo.UV)
346
347     @staticmethod
348     def hasTexture(material):
349         return len(material.getTextures())>0
350
351     @staticmethod
352     def eachTexturePath(m, dirname):
353         for texture in m.getTextures():
354             if texture and texture.tex and texture.tex.getImage():
355                 image=texture.tex.getImage()
356                 if not image:
357                     continue
358                 yield image.getFilename()
359
360
361 class mesh:
362     @staticmethod
363     @to_internal_encoding
364     def create(name):
365         global SCENE
366         m=Blender.Mesh.New()
367         o=SCENE.objects.new(m, name)
368         return m, o
369
370     @staticmethod
371     def addGeometry(m, vertices, faces):
372         m.verts.extend(vertices)
373         new_faces=m.faces.extend(faces,
374                 #ignoreDups=True, 
375                 indexList=True)
376         m.update()
377
378     @staticmethod
379     def hasUV(m):
380         return m.faceUV
381
382     @staticmethod
383     def useVertexUV(m):
384         m.vertexUV = 1
385
386     @staticmethod
387     def addUV(m):
388         m.addUVLayer('NewUV')
389
390     @staticmethod
391     def hasFaceUV(m, i, face):
392         return len(face.uv)>0
393
394     @staticmethod
395     def getFaceUV(m, i, face, count=3):
396         return face.uv
397
398     @staticmethod
399     def setFaceUV(m, i, face, uv_array, image):
400         face.uv=[Mathutils.Vector(uv[0], uv[1]) for uv in  uv_array]
401         if image:
402             face.image=image
403
404     @staticmethod
405     def vertsDelete(m, remove_vertices):
406         m.verts.delete(remove_vertices)
407
408     @staticmethod
409     def setSmooth(m, smoothing):
410         m.mode |= Blender.Mesh.Modes.AUTOSMOOTH
411         m.degr=int(smoothing)
412         #m.smooth()
413
414     @staticmethod
415     def recalcNormals(mesh_object):
416         m=mesh_object.getData(mesh=True)
417         m.calcNormals() 
418
419     @staticmethod
420     def flipNormals(m):
421         m.flipNormals()
422
423     @staticmethod
424     def addMaterial(m, material):
425         m.materials+=[material]
426
427
428 class vertex:
429     @staticmethod
430     def setNormal(mvert, normal):
431         mvert.no=Mathutils.Vector(*normal)
432
433     @staticmethod
434     def setUv(mvert, uv):
435         mvert.uvco=uv
436
437
438 class face:
439     @staticmethod
440     def getVertexCount(face):
441         return len(face.v)
442
443     @staticmethod
444     def getVertices(face):
445         return [v.index for v in face.v]
446
447     @staticmethod
448     def getIndices(face):
449         return [face.verts[0].index, face.verts[1].index, face.verts[2].index]
450
451     @staticmethod
452     def setMaterial(face, material_index):
453         face.mat=material_index
454
455     @staticmethod
456     def getMaterialIndex(face):
457         return face.mat
458
459     @staticmethod
460     def setNormal(face, normal):
461         face.no=normal
462
463     @staticmethod
464     def getNormal(face):
465         return face.no
466
467     @staticmethod
468     def setSmooth(face, isSmooth):
469         face.smooth=1 if isSmooth else 0
470      
471
472 class armature:
473     @staticmethod
474     def create():
475         global SCENE
476         armature = Blender.Armature.New()
477         armature_object = SCENE.objects.new(armature)
478
479         # set XRAY
480         armature_object.drawMode = (
481                 armature_object.drawMode | Blender.Object.DrawModes.XRAY)
482         # armature settings
483         armature.drawType = Blender.Armature.OCTAHEDRON
484         armature.drawNames=True
485         armature.envelopes = False
486         armature.vertexGroups = True
487         armature.mirrorEdit = True
488
489         return armature, armature_object
490
491     @staticmethod
492     def makeEditable(armature_object):
493         # create armature
494         armature_object.getData().makeEditable()
495
496     @staticmethod
497     def createIkConstraint(armature_object, p_bone, effector_name, ik):
498         cSetting = Blender.Constraint.Settings
499         # IK solver
500         constraint = p_bone.constraints.append(Blender.Constraint.Type.IKSOLVER)
501         constraint[cSetting.CHAINLEN]=len(ik.children)
502         constraint[cSetting.TARGET]=armature_object
503         constraint[cSetting.USETIP]=False
504         constraint[cSetting.BONE]=effector_name
505         # not used. place folder when export.
506         constraint[cSetting.ROTWEIGHT]=ik.weight
507         constraint[cSetting.ITERATIONS]=ik.iterations * 10
508         return constraint
509
510     @staticmethod
511     @to_internal_encoding
512     def createBone(armature_object, name):
513         bone=Blender.Armature.Editbone()
514         bone.name=name
515         armature_object.bones[name]=bone
516         return bone
517
518     @staticmethod
519     def update(armature):
520         armature.update()
521
522
523 class bone:
524     @staticmethod
525     def setConnected(bone):
526         bone.options+=[Blender.Armature.CONNECTED]
527
528     @staticmethod
529     def isConnected(b):
530         return Blender.Armature.CONNECTED in b.options
531
532     @staticmethod
533     def setLayerMask(bone, layers):
534         mask=0
535         for i, enable in enumerate(layers):
536             if enable!=0:
537                 mask+=(1<<i)
538         bone.layerMask=mask
539
540     @staticmethod
541     def getHeadLocal(b):
542         return b.head['ARMATURESPACE'][0:3]
543
544     @staticmethod
545     def getTailLocal(b):
546         return b.tail['ARMATURESPACE'][0:3]
547
548
549 class constraint:
550     @staticmethod
551     def ikChainLen(c):
552         return c[Blender.Constraint.Settings.CHAINLEN]
553
554     @staticmethod
555     def ikTarget(c):
556         return c[Blender.Constraint.Settings.BONE]
557
558     @staticmethod
559     def ikItration(c):
560         return c[Blender.Constraint.Settings.ITERATIONS]
561
562     @staticmethod
563     def ikRotationWeight(c):
564         return c[Blender.Constraint.Settings.ROTWEIGHT]
565
566     @staticmethod
567     def isIKSolver(c):
568         return c.type==Blender.Constraint.Type.IKSOLVER
569
570