OSDN Git Service

export toon textures.
[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     @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
392 class mesh:
393     @staticmethod
394     @to_internal_encoding
395     def create(name):
396         global SCENE
397         m=Blender.Mesh.New()
398         o=SCENE.objects.new(m, name)
399         return m, o
400
401     @staticmethod
402     def addGeometry(m, vertices, faces):
403         m.verts.extend(vertices)
404         new_faces=m.faces.extend(faces,
405                 #ignoreDups=True, 
406                 indexList=True)
407         m.update()
408
409     @staticmethod
410     def hasUV(m):
411         return m.faceUV
412
413     @staticmethod
414     def useVertexUV(m):
415         m.vertexUV = 1
416
417     @staticmethod
418     def addUV(m):
419         m.addUVLayer('NewUV')
420
421     @staticmethod
422     def hasFaceUV(m, i, face):
423         return len(face.uv)>0
424
425     @staticmethod
426     def getFaceUV(m, i, face, count=3):
427         return face.uv
428
429     @staticmethod
430     def setFaceUV(m, i, face, uv_array, image):
431         face.uv=[Mathutils.Vector(uv[0], uv[1]) for uv in  uv_array]
432         if image:
433             face.image=image
434
435     @staticmethod
436     def vertsDelete(m, remove_vertices):
437         m.verts.delete(remove_vertices)
438
439     @staticmethod
440     def setSmooth(m, smoothing):
441         m.mode |= Blender.Mesh.Modes.AUTOSMOOTH
442         m.degr=int(smoothing)
443         #m.smooth()
444
445     @staticmethod
446     def recalcNormals(mesh_object):
447         m=mesh_object.getData(mesh=True)
448         m.calcNormals() 
449
450     @staticmethod
451     def flipNormals(m):
452         m.flipNormals()
453
454     @staticmethod
455     def addMaterial(m, material):
456         m.materials+=[material]
457
458     @staticmethod
459     def getMaterial(m, index):
460         return m.materials[index]
461
462
463 class vertex:
464     @staticmethod
465     def setNormal(mvert, normal):
466         mvert.no=Mathutils.Vector(*normal)
467
468     @staticmethod
469     def setUv(mvert, uv):
470         mvert.uvco=uv
471
472
473 class face:
474     @staticmethod
475     def getVertexCount(face):
476         return len(face.v)
477
478     @staticmethod
479     def getVertices(face):
480         return [v.index for v in face.v]
481
482     @staticmethod
483     def getIndices(face):
484         return [face.verts[0].index, face.verts[1].index, face.verts[2].index]
485
486     @staticmethod
487     def setMaterial(face, material_index):
488         face.mat=material_index
489
490     @staticmethod
491     def getMaterialIndex(face):
492         return face.mat
493
494     @staticmethod
495     def setNormal(face, normal):
496         face.no=normal
497
498     @staticmethod
499     def getNormal(face):
500         return face.no
501
502     @staticmethod
503     def setSmooth(face, isSmooth):
504         face.smooth=1 if isSmooth else 0
505      
506
507 class armature:
508     @staticmethod
509     def create():
510         global SCENE
511         armature = Blender.Armature.New()
512         armature_object = SCENE.objects.new(armature)
513
514         # set XRAY
515         armature_object.drawMode = (
516                 armature_object.drawMode | Blender.Object.DrawModes.XRAY)
517         # armature settings
518         armature.drawType = Blender.Armature.OCTAHEDRON
519         armature.drawNames=True
520         armature.envelopes = False
521         armature.vertexGroups = True
522         armature.mirrorEdit = True
523
524         return armature, armature_object
525
526     @staticmethod
527     def makeEditable(armature_object):
528         # create armature
529         armature_object.getData().makeEditable()
530
531     @staticmethod
532     def createIkConstraint(armature_object, p_bone, effector_name, ik):
533         cSetting = Blender.Constraint.Settings
534         # IK solver
535         constraint = p_bone.constraints.append(Blender.Constraint.Type.IKSOLVER)
536         constraint[cSetting.CHAINLEN]=len(ik.children)
537         constraint[cSetting.TARGET]=armature_object
538         constraint[cSetting.USETIP]=False
539         constraint[cSetting.BONE]=effector_name
540         # not used. place folder when export.
541         constraint[cSetting.ROTWEIGHT]=ik.weight
542         constraint[cSetting.ITERATIONS]=ik.iterations * 10
543         return constraint
544
545     @staticmethod
546     @to_internal_encoding
547     def createBone(armature_object, name):
548         bone=Blender.Armature.Editbone()
549         bone.name=name
550         armature_object.bones[name]=bone
551         return bone
552
553     @staticmethod
554     def update(armature):
555         armature.update()
556
557
558 class bone:
559     @staticmethod
560     def setConnected(bone):
561         bone.options+=[Blender.Armature.CONNECTED]
562
563     @staticmethod
564     def isConnected(b):
565         return Blender.Armature.CONNECTED in b.options
566
567     @staticmethod
568     def setLayerMask(bone, layers):
569         mask=0
570         for i, enable in enumerate(layers):
571             if enable!=0:
572                 mask+=(1<<i)
573         bone.layerMask=mask
574
575     @staticmethod
576     def getHeadLocal(b):
577         return b.head['ARMATURESPACE'][0:3]
578
579     @staticmethod
580     def getTailLocal(b):
581         return b.tail['ARMATURESPACE'][0:3]
582
583
584 class constraint:
585     @staticmethod
586     def ikChainLen(c):
587         return c[Blender.Constraint.Settings.CHAINLEN]
588
589     @staticmethod
590     def ikTarget(c):
591         return c[Blender.Constraint.Settings.BONE]
592
593     @staticmethod
594     def ikItration(c):
595         return c[Blender.Constraint.Settings.ITERATIONS]
596
597     @staticmethod
598     def ikRotationWeight(c):
599         return c[Blender.Constraint.Settings.ROTWEIGHT]
600
601     @staticmethod
602     def isIKSolver(c):
603         return c.type==Blender.Constraint.Type.IKSOLVER
604
605