OSDN Git Service

implement pmd_import bone group.
[meshio/meshio.git] / swig / blender / bl25.py
1 # coding: utf-8
2 import os
3 import sys
4 import time
5 import functools
6
7 try:
8     import bpy
9     import mathutils
10 except:
11     pass
12
13\e$B%U%!%$%k%7%9%F%`$NJ8;z%3!<%I\e(B
14\e$B2~B$HG$H$N6&MQ$N$?$a\e(B
15 FS_ENCODING=sys.getfilesystemencoding()
16 if os.path.exists(os.path.dirname(sys.argv[0])+"/utf8"):
17     INTERNAL_ENCODING='utf-8'
18 else:
19     INTERNAL_ENCODING=FS_ENCODING
20
21 SCENE=None
22 def initialize(name, scene):
23     global SCENE
24     SCENE=scene
25     progress_start(name)
26
27 def finalize():
28     scene.update(SCENE)
29     progress_finish()
30
31 def message(msg):
32     pass
33
34 def enterEditMode():
35     bpy.ops.object.mode_set(mode='EDIT', toggle=False)
36
37 def enterObjectMode():
38     bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
39
40 def enterPoseMode():
41     bpy.ops.object.mode_set(mode='POSE', toggle=False)
42
43 def createVector(x, y, z):
44     return mathutils.Vector([x, y, z])
45
46
47 class Writer(object):
48     '''
49     io wrapper
50     '''
51     def __init__(self, path, encoding):
52         self.io=open(path, "wb")
53         self.encoding=encoding
54
55     def write(self, s):
56         self.io.write(s.encode(self.encoding))
57
58     def flush(self):
59         self.io.flush()
60
61     def close(self):
62         self.io.close()
63
64
65 class ProgressBar(object):
66     '''
67     progress bar wrapper
68     '''
69     def __init__(self, base):
70         print("#### %s ####" % base)
71         self.base=base
72         self.start=time.time() 
73         self.set('<start>', 0)
74
75     def advance(self, message, progress):
76         self.progress+=float(progress)
77         self._print(message)
78
79     def set(self, message, progress):
80         self.progress=float(progress)
81         self._print(message)
82
83     def _print(self, message):
84         print(message)
85         message="%s: %s" % (self.base, message)
86         #Blender.Window.DrawProgressBar(self.progress, message)
87
88     def finish(self):
89         self.progress=1.0
90         message='finished in %.2f sec' % (time.time()-self.start)
91         self.set(message, 1.0)
92
93 def progress_start(base):
94     global progressBar
95     progressBar=ProgressBar(base)
96
97 def progress_finish():
98     global progressBar
99     progressBar.finish()
100
101 def progress_print(message, progress=0.05):
102     global progressBar
103     progressBar.advance(message, progress)
104
105 def progress_set(message, progress):
106     global progressBar
107     progressBar.set(message, progress)
108
109
110 class scene:
111     @staticmethod
112     def update(scene):
113         scene.update()
114
115
116 class object:
117     @staticmethod
118     def createEmpty(name):
119         global SCENE
120         empty=bpy.data.objects.new(name, None)
121         SCENE.objects.link(empty)
122         return empty
123
124     @staticmethod
125     def makeParent(parent, child):
126         child.parent=parent
127
128     @staticmethod
129     def duplicate(o):
130         global SCENE
131         bpy.ops.object.select_all(action='DESELECT')
132         o.selected=True
133         SCENE.objects.active=o
134         bpy.ops.object.duplicate()
135         dumy=SCENE.objects.active
136         #bpy.ops.object.rotation_apply()
137         #bpy.ops.object.scale_apply()
138         #bpy.ops.object.location_apply()
139         return dumy.data, dumy
140
141     @staticmethod
142     def delete(o):
143         global SCENE
144         SCENE.objects.unlink(o)
145
146     @staticmethod
147     def getData(o):
148         return o.data
149
150     @staticmethod
151     def select(o):
152         o.selected=True
153
154     @staticmethod
155     def activate(o):
156         global SCENE
157         o.selected=True 
158         SCENE.objects.active=o
159
160     @staticmethod
161     def getActive():
162         global SCENE 
163         return SCENE.objects.active
164
165     @staticmethod
166     def deselectAll():
167         bpy.ops.object.select_all(action='DESELECT')
168
169     @staticmethod
170     def setLayerMask(object, layers):
171         layer=[]
172         for i in range(20):
173             try:
174                 layer.append(True if layers[i]!=0 else False)
175             except IndexError:
176                 layer.append(False)
177         object.layers=layer
178
179     @staticmethod
180     def isVisible(o):
181         return o.restrict_view
182
183     @staticmethod
184     def getShapeKeys(o):
185         return o.data.shape_keys.keys
186
187     @staticmethod
188     def addShapeKey(o, name):
189         return o.add_shape_key(name)
190
191     @staticmethod
192     def hasShapeKey(o):
193         return o.data.shape_keys
194
195     @staticmethod
196     def pinShape(o, enable):
197         o.shape_key_lock=enable
198
199     @staticmethod
200     def setActivateShapeKey(o, index):
201         o.active_shape_key_index=index
202
203     @staticmethod
204     def getPose(o):
205         return o.pose
206
207     @staticmethod
208     def getVertexGroup(o, name):
209         indices=[]
210         for i, v in enumerate(o.data.verts):
211             for g in v.groups:
212                 if o.vertex_groups[g.group].name==name:
213                     indices.append(i)
214         return indices
215
216     @staticmethod
217     def getVertexGroupNames(o):
218         for g in o.vertex_groups:
219             yield g.name
220
221     @staticmethod
222     def addVertexGroup(o, name):
223         o.add_vertex_group(name)
224
225     @staticmethod
226     def assignVertexGroup(o, name, index, weight):
227         o.add_vertex_to_group(index, 
228                     o.vertex_groups[name], weight, 'ADD')
229
230     @staticmethod
231     def createBoneGroup(o, name, color_set='DEFAULT'):
232         # create group
233         object.activate(o)
234         enterPoseMode()
235         bpy.ops.pose.group_add()
236         # set name
237         pose=object.getPose(o)
238         g=pose.active_bone_group
239         g.name=name
240         g.color_set=color_set
241
242
243 class modifier:
244     @staticmethod
245     def addMirror(mesh_object):
246         return mesh_object.modifiers.new("Modifier", "MIRROR")
247
248     @staticmethod
249     def addArmature(mesh_object, armature_object):
250         mod=mesh_object.modifiers.new("Modifier", "ARMATURE")
251         mod.object = armature_object
252         mod.use_bone_envelopes=False
253
254     @staticmethod
255     def hasType(mesh_object, type_name):
256         for mod in mesh_object.modifiers:
257                 if mod.type==type_name.upper():
258                     return True
259
260     @staticmethod
261     def isType(m, type_name):
262         return m.type==type_name.upper()
263
264     @staticmethod
265     def getArmatureObject(m):
266         return m.object
267
268
269 class shapekey:
270     @staticmethod
271     def assign(shapeKey, index, pos):
272         shapeKey.data[index].co=pos
273
274     @staticmethod
275     def getByIndex(b, index):
276         return b.data[index].co
277
278     @staticmethod
279     def get(b):
280         for k in b.data:
281             yield k.co
282
283
284 class texture:
285     @staticmethod
286     def create(path):
287         texture=bpy.data.textures.new(os.path.basename(path))
288         texture.type='IMAGE'
289         texture=texture.recast_type()
290         image=bpy.data.images.load(path)
291         texture.image=image
292         texture.mipmap=True
293         texture.interpolation=True
294         texture.use_alpha=True
295         return texture, image
296
297
298 class material:
299     @staticmethod
300     def create(name):
301         return bpy.data.materials.new(name)
302
303     @staticmethod
304     def get(material_name):
305         return bpy.data.materials[material_name]
306
307     @staticmethod
308     def addTexture(material, texture):
309         material.add_texture(texture, "UV", "COLOR")
310         slot=material.texture_slots[material.active_texture_index]
311         slot.blend_type='MULTIPLY'
312         slot.map_alpha=True
313
314     @staticmethod
315     def hasTexture(material):
316         return material.texture_slots[0]
317
318     @staticmethod
319     def eachTexturePath(m):
320         for slot in m.texture_slots:
321             if slot and slot.texture:
322                 texture=slot.texture
323                 if  texture.type=="IMAGE":
324                     image=texture.image
325                     if not image:
326                         continue
327                     yield image.filename
328
329 class mesh:
330     @staticmethod
331     def create(name):
332         global SCENE
333         mesh=bpy.data.meshes.new("Mesh")
334         mesh_object= bpy.data.objects.new(name, mesh)
335         SCENE.objects.link(mesh_object)
336         return mesh, mesh_object
337
338     @staticmethod
339     def addGeometry(mesh, vertices, faces):
340         mesh.from_pydata(vertices, [], faces)
341         """
342         mesh.add_geometry(len(vertices), 0, len(faces))
343         # add vertex
344         unpackedVertices=[]
345         for v in vertices:
346             unpackedVertices.extend(v)
347         mesh.verts.foreach_set("co", unpackedVertices)
348         # add face
349         unpackedFaces = []
350         for face in faces:
351             if len(face) == 4:
352                 if face[3] == 0:
353                     # rotate indices if the 4th is 0
354                     face = [face[3], face[0], face[1], face[2]]
355             elif len(face) == 3:
356                 if face[2] == 0:
357                     # rotate indices if the 3rd is 0
358                     face = [face[2], face[0], face[1], 0]
359                 else:
360                     face.append(0)
361             unpackedFaces.extend(face)
362         mesh.faces.foreach_set("verts_raw", unpackedFaces)
363         """
364         assert(len(vertices)==len(mesh.verts))
365         assert(len(faces)==len(mesh.faces))
366
367     @staticmethod
368     def hasUV(mesh):
369         return mesh.active_uv_texture
370
371     @staticmethod
372     def useVertexUV(mesh):
373         pass
374
375     @staticmethod
376     def addUV(mesh):
377         mesh.add_uv_texture()
378
379     @staticmethod
380     def hasFaceUV(mesh, i, face):
381         return mesh.active_uv_texture.data[i]
382
383     @staticmethod
384     def getFaceUV(mesh, i, faces, count=3):
385         uvFace=mesh.active_uv_texture.data[i]
386         if count==3:
387             return (uvFace.uv1, uvFace.uv2, uvFace.uv3)
388         elif count==4:
389             return (uvFace.uv1, uvFace.uv2, uvFace.uv3, uvFace.uv4)
390         else:
391             print(count)
392             assert(False)
393
394     @staticmethod
395     def setFaceUV(mesh, i, face, uv_array, image):
396         uv_face=mesh.uv_textures[0].data[i]
397         uv_face.uv=uv_array
398         if image:
399             uv_face.image=image
400             uv_face.tex=True
401
402     @staticmethod
403     def vertsDelete(mesh, remove_vertices):
404         enterEditMode()
405         bpy.ops.mesh.select_all(action='DESELECT')
406         enterObjectMode()
407
408         for i in remove_vertices:
409             mesh.verts[i].selected=True
410
411         enterEditMode()
412         bpy.ops.mesh.delete(type='VERT')
413         enterObjectMode()
414
415     @staticmethod
416     def setSmooth(mesh, smoothing):
417         mesh.autosmooth_angle=int(smoothing)
418         mesh.autosmooth=True
419
420     @staticmethod
421     def recalcNormals(mesh_object):
422         bpy.ops.object.select_all(action='DESELECT')
423         object.activate(mesh_object)
424         enterEditMode()
425         bpy.ops.mesh.normals_make_consistent()
426         enterObjectMode()
427
428     @staticmethod
429     def flipNormals(mesh):
430         mesh.flipNormals()
431
432     @staticmethod
433     def addMaterial(mesh, material):
434         mesh.add_material(material)
435
436
437 class vertex:
438     @staticmethod
439     def setNormal(mvert, normal):
440         mvert.normal=mathutils.Vector(normal)
441
442     @staticmethod
443     def setUv(mvert, uv):
444         pass
445
446
447 class face:
448     @staticmethod
449     def getVertexCount(face):
450         return len(face.verts)
451
452     @staticmethod
453     def getVertices(face):
454         return face.verts[:]
455
456     @staticmethod
457     def getIndices(face, count=3):
458         if count==3:
459             return [face.verts[0], face.verts[1], face.verts[2]]
460         elif count==4:
461             return [face.verts[0], face.verts[1], face.verts[2], face.verts[3]]
462         else:
463             assert(False)
464
465     @staticmethod
466     def setMaterial(face, material_index):
467         face.material_index=material_index
468
469     @staticmethod
470     def getMaterialIndex(face):
471         return face.material_index
472
473     @staticmethod
474     def setNormal(face, normal):
475         face.normal=normal
476
477     @staticmethod
478     def getNormal(face):
479         return face.normal
480
481     @staticmethod
482     def setSmooth(face, isSmooth):
483         face.smooth=True if isSmooth else False
484
485
486 class armature:
487     @staticmethod
488     def create():
489         global SCENE
490         armature = bpy.data.armatures.new('Armature')
491         armature_object=bpy.data.objects.new('Armature', armature)
492         SCENE.objects.link(armature_object)
493
494         armature_object.x_ray=True
495         armature.draw_names=True
496         #armature.drawtype='OCTAHEDRAL'
497         armature.drawtype='STICK'
498         armature.deform_envelope=False
499         armature.deform_vertexgroups=True
500         armature.x_axis_mirror=True
501
502         return armature, armature_object
503
504     @staticmethod
505     def makeEditable(armature_object):
506         global SCENE
507         # select only armature object and set edit mode
508         SCENE.objects.active=armature_object
509         bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
510         bpy.ops.object.mode_set(mode='EDIT', toggle=False)
511
512     @staticmethod
513     def createIkConstraint(armature_object, p_bone, effector_name, ik):
514         constraint = p_bone.constraints.new('IK')
515         constraint.chain_length=len(ik.children)
516         constraint.target=armature_object
517         constraint.subtarget=effector_name
518         constraint.use_tail=False
519         # not used. place folder when export.
520         constraint.weight=ik.weight
521         constraint.iterations=ik.iterations * 10
522         return constraint
523
524     @staticmethod
525     def createBone(armature, name):
526         return armature.edit_bones.new(name)
527
528     @staticmethod
529     def update(armature):
530         pass
531
532
533 class bone:
534     @staticmethod
535     def setConnected(bone):
536         bone.connected=True
537
538     @staticmethod
539     def isConnected(b):
540         return b.connected
541
542     @staticmethod
543     def setLayerMask(bone, layers):
544         layer=[]
545         for i in range(32):
546             try:
547                 layer.append(True if layers[i]!=0 else False)
548             except IndexError:
549                 layer.append(False)
550         bone.layer=layer
551
552     @staticmethod
553     def getHeadLocal(b):
554         return b.head_local[0:3]
555
556     @staticmethod
557     def getTailLocal(b):
558         return b.tail_local[0:3]
559
560
561 class constraint:
562     @staticmethod
563     def ikChainLen(c):
564         return c.chain_length
565
566     @staticmethod
567     def ikTarget(c):
568         return c.subtarget
569
570     @staticmethod
571     def ikItration(c):
572         return c.iterations
573
574     @staticmethod
575     def ikRotationWeight(c):
576         return c.weight
577
578     @staticmethod
579     def isIKSolver(c):
580         return c.type=='IK'
581
582