OSDN Git Service

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