OSDN Git Service

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