OSDN Git Service

update for blender2.59
[meshio/pymeshio.git] / blender25-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 get():
117         global SCENE
118         return SCENE
119
120     def update(scene):
121         scene.update()
122
123
124 class object:
125     @staticmethod
126     def createEmpty(name):
127         global SCENE
128         empty=bpy.data.objects.new(name, None)
129         SCENE.objects.link(empty)
130         return empty
131
132     @staticmethod
133     def each():
134         for o in SCENE.objects:
135             yield o
136
137     @staticmethod
138     def makeParent(parent, child):
139         child.parent=parent
140
141     @staticmethod
142     def duplicate(o):
143         global SCENE
144         bpy.ops.object.select_all(action='DESELECT')
145         o.select=True
146         SCENE.objects.active=o
147         bpy.ops.object.duplicate()
148         dumy=SCENE.objects.active
149         #bpy.ops.object.rotation_apply()
150         #bpy.ops.object.scale_apply()
151         #bpy.ops.object.location_apply()
152         return dumy.data, dumy
153
154     @staticmethod
155     def delete(o):
156         global SCENE
157         SCENE.objects.unlink(o)
158
159     @staticmethod
160     def getData(o):
161         return o.data
162
163     @staticmethod
164     def select(o):
165         o.select=True
166
167     @staticmethod
168     def activate(o):
169         global SCENE
170         o.select=True 
171         SCENE.objects.active=o
172
173     @staticmethod
174     def getActive():
175         global SCENE 
176         return SCENE.objects.active
177
178     @staticmethod
179     def deselectAll():
180         bpy.ops.object.select_all(action='DESELECT')
181
182     @staticmethod
183     def setLayerMask(object, layers):
184         layer=[]
185         for i in range(20):
186             try:
187                 layer.append(True if layers[i]!=0 else False)
188             except IndexError:
189                 layer.append(False)
190         object.layers=layer
191
192     @staticmethod
193     def isVisible(o):
194         return False if o.hide else True
195
196     @staticmethod
197     def getShapeKeys(o):
198         return o.data.shape_keys.key_blocks
199
200     @staticmethod
201     def addShapeKey(o, name):
202         try:
203             return o.shape_key_add(name)
204         except:
205             return o.add_shape_key(name)
206
207     @staticmethod
208     def hasShapeKey(o):
209         return o.data.shape_keys
210
211     @staticmethod
212     def pinShape(o, enable):
213         o.show_only_shape_key=enable
214
215     @staticmethod
216     def setActivateShapeKey(o, index):
217         o.active_shape_key_index=index
218
219     @staticmethod
220     def getPose(o):
221         return o.pose
222
223     @staticmethod
224     def getVertexGroup(o, name):
225         indices=[]
226         for i, v in enumerate(o.data.vertices):
227             for g in v.groups:
228                 if o.vertex_groups[g.group].name==name:
229                     indices.append(i)
230         return indices
231
232     @staticmethod
233     def getVertexGroupNames(o):
234         for g in o.vertex_groups:
235             yield g.name
236
237     @staticmethod
238     def addVertexGroup(o, name):
239         o.vertex_groups.new(name)
240
241     @staticmethod
242     def assignVertexGroup(o, name, index, weight):
243         o.vertex_groups[name].add([index], weight, 'ADD')
244
245     @staticmethod
246     def createBoneGroup(o, name, color_set='DEFAULT'):
247         # create group
248         object.activate(o)
249         enterPoseMode()
250         bpy.ops.pose.group_add()
251         # set name
252         pose=object.getPose(o)
253         g=pose.bone_groups.active
254         g.name=name
255         g.color_set=color_set
256
257     @staticmethod
258     def boneGroups(o):
259         return object.getPose(o).bone_groups
260
261
262 class modifier:
263     @staticmethod
264     def addMirror(mesh_object):
265         return mesh_object.modifiers.new("Modifier", "MIRROR")
266
267     @staticmethod
268     def addArmature(mesh_object, armature_object):
269         mod=mesh_object.modifiers.new("Modifier", "ARMATURE")
270         mod.object = armature_object
271         mod.use_bone_envelopes=False
272
273     @staticmethod
274     def hasType(mesh_object, type_name):
275         for mod in mesh_object.modifiers:
276                 if mod.type==type_name.upper():
277                     return True
278
279     @staticmethod
280     def isType(m, type_name):
281         return m.type==type_name.upper()
282
283     @staticmethod
284     def getArmatureObject(m):
285         return m.object
286
287
288 class shapekey:
289     @staticmethod
290     def assign(shapeKey, index, pos):
291         shapeKey.data[index].co=pos
292
293     @staticmethod
294     def getByIndex(b, index):
295         return b.data[index].co
296
297     @staticmethod
298     def get(b):
299         for k in b.data:
300             yield k.co
301
302
303 class texture:
304     @staticmethod
305     def create(path):
306         texture=bpy.data.textures.new(os.path.basename(path), 'IMAGE')
307         texture.use_mipmap=True
308         texture.use_interpolation=True
309         texture.use_alpha=True
310         try:
311             image=bpy.data.images.load(path)
312         except RuntimeError:
313             image=bpy.data.images.new('Image', width=16, height=16)
314         texture.image=image
315         return texture, image
316
317     @staticmethod
318     def getPath(t):
319         if  t.type=="IMAGE":
320             image=t.image
321             if image:
322                 return image.filepath
323
324
325 class material:
326     @staticmethod
327     def create(name):
328         return bpy.data.materials.new(name)
329
330     @staticmethod
331     def get(material_name):
332         return bpy.data.materials[material_name]
333
334     @staticmethod
335     def addTexture(material, texture, enable=True):
336         # search free slot
337         index=None
338         for i, slot in enumerate(material.texture_slots):
339             if not slot:
340                 index=i
341                 break
342         if index==None:
343             return
344         #
345         #material.add_texture(texture, "UV", "COLOR")
346         #slot=material.texture_slots.add()
347         slot=material.texture_slots.create(index)
348         slot.texture=texture
349         slot.texture_coords='UV'
350         slot.blend_type='MULTIPLY'
351         slot.use_map_alpha=True
352         slot.use=enable
353         return index
354
355     @staticmethod
356     def getTexture(m, index):
357         return m.texture_slots[index].texture
358
359     @staticmethod
360     def hasTexture(m):
361         return m.texture_slots[0]
362
363     @staticmethod
364     def setUseTexture(m, index, enable):
365         m.use_textures[index]=enable
366
367     @staticmethod
368     def eachTexturePath(m):
369         for slot in m.texture_slots:
370             if slot and slot.texture:
371                 texture=slot.texture
372                 if  texture.type=="IMAGE":
373                     image=texture.image
374                     if not image:
375                         continue
376                     yield image.filepath
377
378     @staticmethod
379     def eachEnalbeTexturePath(m):
380         for i, slot in enumerate(m.texture_slots):
381             if m.use_textures[i] and slot and slot.texture:
382                 texture=slot.texture
383                 if  texture.type=="IMAGE":
384                     image=texture.image
385                     if not image:
386                         continue
387                     yield image.filepath
388
389
390 class mesh:
391     @staticmethod
392     def create(name):
393         global SCENE
394         mesh=bpy.data.meshes.new("Mesh")
395         mesh_object= bpy.data.objects.new(name, mesh)
396         SCENE.objects.link(mesh_object)
397         return mesh, mesh_object
398
399     @staticmethod
400     def addGeometry(mesh, vertices, faces):
401         mesh.from_pydata(vertices, [], faces)
402         """
403         mesh.add_geometry(len(vertices), 0, len(faces))
404         # add vertex
405         unpackedVertices=[]
406         for v in vertices:
407             unpackedVertices.extend(v)
408         mesh.vertices.foreach_set("co", unpackedVertices)
409         # add face
410         unpackedFaces = []
411         for face in faces:
412             if len(face) == 4:
413                 if face[3] == 0:
414                     # rotate indices if the 4th is 0
415                     face = [face[3], face[0], face[1], face[2]]
416             elif len(face) == 3:
417                 if face[2] == 0:
418                     # rotate indices if the 3rd is 0
419                     face = [face[2], face[0], face[1], 0]
420                 else:
421                     face.append(0)
422             unpackedFaces.extend(face)
423         mesh.faces.foreach_set("verts_raw", unpackedFaces)
424         """
425         assert(len(vertices)==len(mesh.vertices))
426         assert(len(faces)==len(mesh.faces))
427
428     @staticmethod
429     def hasUV(mesh):
430         return len(mesh.uv_textures)>0
431
432     @staticmethod
433     def useVertexUV(mesh):
434         pass
435
436     @staticmethod
437     def addUV(mesh):
438         mesh.uv_textures.new()
439
440     @staticmethod
441     def hasFaceUV(mesh, i, face):
442         active_uv_texture=None
443         for t in mesh.uv_textures:
444             if t.active:
445                 active_uv_texture=t
446                 break
447         return active_uv_texture and active_uv_texture.data[i]
448
449     @staticmethod
450     def getFaceUV(mesh, i, faces, count=3):
451         active_uv_texture=None
452         for t in mesh.uv_textures:
453             if t.active:
454                 active_uv_texture=t
455                 break
456         if active_uv_texture and active_uv_texture.data[i]:
457             uvFace=active_uv_texture.data[i]
458             if count==3:
459                 return (uvFace.uv1, uvFace.uv2, uvFace.uv3)
460             elif count==4:
461                 return (uvFace.uv1, uvFace.uv2, uvFace.uv3, uvFace.uv4)
462             else:
463                 print(count)
464                 assert(False)
465         else:
466             return ((0, 0), (0, 0), (0, 0), (0, 0))
467
468     @staticmethod
469     def setFaceUV(m, i, face, uv_array, image):
470         uv_face=m.uv_textures[0].data[i]
471         uv_face.uv=uv_array
472         if image:
473             uv_face.image=image
474             uv_face.use_image=True
475
476     @staticmethod
477     def vertsDelete(m, remove_vertices):
478         enterEditMode()
479         bpy.ops.mesh.select_all(action='DESELECT')
480         enterObjectMode()
481
482         for i in remove_vertices:
483             m.vertices[i].select=True
484
485         enterEditMode()
486         bpy.ops.mesh.delete(type='VERT')
487         enterObjectMode()
488
489     @staticmethod
490     def setSmooth(m, smoothing):
491         m.auto_smooth_angle=int(smoothing)
492         m.use_auto_smooth=True
493
494     @staticmethod
495     def recalcNormals(mesh_object):
496         bpy.ops.object.select_all(action='DESELECT')
497         object.activate(mesh_object)
498         enterEditMode()
499         bpy.ops.mesh.normals_make_consistent()
500         enterObjectMode()
501
502     @staticmethod
503     def flipNormals(m):
504         m.flipNormals()
505
506     @staticmethod
507     def addMaterial(m, material):
508         m.materials.append(material)
509
510     @staticmethod
511     def getMaterial(m, index):
512         return m.materials[index]
513
514
515 class vertex:
516     @staticmethod
517     def setNormal(v, normal):
518         v.normal=mathutils.Vector(normal)
519
520     @staticmethod
521     def getNormal(v):
522         return v.normal
523
524     @staticmethod
525     def setUv(v, uv):
526         # sticky ?
527         pass
528
529
530 class face:
531     @staticmethod
532     def getVertexCount(face):
533         return len(face.vertices)
534
535     @staticmethod
536     def getVertices(face):
537         return face.vertices[:]
538
539     @staticmethod
540     def getIndices(face, count=3):
541         if count==3:
542             return [face.vertices[0], face.vertices[1], face.vertices[2]]
543         elif count==4:
544             return [face.vertices[0], face.vertices[1], face.vertices[2], face.vertices[3]]
545         else:
546             assert(False)
547
548     @staticmethod
549     def setMaterial(face, material_index):
550         face.material_index=material_index
551
552     @staticmethod
553     def getMaterialIndex(face):
554         return face.material_index
555
556     @staticmethod
557     def setNormal(face, normal):
558         face.normal=normal
559
560     @staticmethod
561     def getNormal(face):
562         return face.normal
563
564     @staticmethod
565     def setSmooth(face, isSmooth):
566         face.use_smooth=True if isSmooth else False
567
568
569 class armature:
570     @staticmethod
571     def create():
572         global SCENE
573         armature = bpy.data.armatures.new('Armature')
574         armature_object=bpy.data.objects.new('Armature', armature)
575         SCENE.objects.link(armature_object)
576
577         armature_object.show_x_ray=True
578         armature.show_names=True
579         #armature.draw_type='OCTAHEDRAL'
580         armature.draw_type='STICK'
581         armature.use_deform_envelopes=False
582         armature.use_deform_vertex_groups=True
583         armature.use_mirror_x=True
584
585         return armature, armature_object
586
587     @staticmethod
588     def makeEditable(armature_object):
589         global SCENE
590         # select only armature object and set edit mode
591         SCENE.objects.active=armature_object
592         bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
593         bpy.ops.object.mode_set(mode='EDIT', toggle=False)
594
595     @staticmethod
596     def createIkConstraint(armature_object, p_bone, effector_name, ik):
597         constraint = p_bone.constraints.new('IK')
598         constraint.chain_count=len(ik.children)
599         constraint.target=armature_object
600         constraint.subtarget=effector_name
601         constraint.use_tail=False
602         # not used. place folder when export.
603         constraint.weight=ik.weight
604         constraint.iterations=ik.iterations * 10
605         return constraint
606
607     @staticmethod
608     def createBone(armature, name):
609         return armature.edit_bones.new(name)
610
611     @staticmethod
612     def update(armature):
613         pass
614
615
616 class bone:
617     @staticmethod
618     def setConnected(bone):
619         bone.use_connect=True
620
621     @staticmethod
622     def isConnected(bone):
623         return bone.use_connect
624
625     @staticmethod
626     def setLayerMask(bone, layers):
627         layer=[]
628         for i in range(32):
629             try:
630                 layer.append(True if layers[i]!=0 else False)
631             except IndexError:
632                 layer.append(False)
633         bone.layers=layer
634
635     @staticmethod
636     def getHeadLocal(b):
637         return b.head_local[0:3]
638
639     @staticmethod
640     def getTailLocal(b):
641         return b.tail_local[0:3]
642
643
644 class constraint:
645     @staticmethod
646     def ikChainLen(c):
647         return c.chain_count
648
649     @staticmethod
650     def ikTarget(c):
651         return c.subtarget
652
653     @staticmethod
654     def ikItration(c):
655         return c.iterations
656
657     @staticmethod
658     def ikRotationWeight(c):
659         return c.weight
660
661     @staticmethod
662     def isIKSolver(c):
663         return c.type=='IK'
664
665 MMD_SHAPE_GROUP_NAME='_MMD_SHAPE'
666 MMD_MB_NAME='mb_name'
667 MMD_MB_COMMENT='mb_comment'
668 MMD_COMMENT='comment'
669 BASE_SHAPE_NAME='Basis'
670 RIGID_NAME='rigid_name'
671 RIGID_SHAPE_TYPE='rigid_shape_type'
672 RIGID_PROCESS_TYPE='rigid_process_type'
673 RIGID_BONE_NAME='rigid_bone_name'
674 RIGID_GROUP='ribid_group'
675 RIGID_INTERSECTION_GROUP='rigid_intersection_group'
676 RIGID_WEIGHT='rigid_weight'
677 RIGID_LINEAR_DAMPING='rigid_linear_damping'
678 RIGID_ANGULAR_DAMPING='rigid_angular_damping'
679 RIGID_RESTITUTION='rigid_restitution'
680 RIGID_FRICTION='rigid_friction'
681 CONSTRAINT_NAME='const_name'
682 CONSTRAINT_A='const_a'
683 CONSTRAINT_B='const_b'
684 CONSTRAINT_POS_MIN='const_pos_min'
685 CONSTRAINT_POS_MAX='const_pos_max'
686 CONSTRAINT_ROT_MIN='const_rot_min'
687 CONSTRAINT_ROT_MAX='const_rot_max'
688 CONSTRAINT_SPRING_POS='const_spring_pos'
689 CONSTRAINT_SPRING_ROT='const_spring_rot'
690 TOON_TEXTURE_OBJECT='ToonTextures'
691