OSDN Git Service

separate vertex with uv or normal.
[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     @staticmethod
243     def boneGroups(o):
244         return object.getPose(o).bone_groups
245
246
247 class modifier:
248     @staticmethod
249     def addMirror(mesh_object):
250         return mesh_object.modifiers.new("Modifier", "MIRROR")
251
252     @staticmethod
253     def addArmature(mesh_object, armature_object):
254         mod=mesh_object.modifiers.new("Modifier", "ARMATURE")
255         mod.object = armature_object
256         mod.use_bone_envelopes=False
257
258     @staticmethod
259     def hasType(mesh_object, type_name):
260         for mod in mesh_object.modifiers:
261                 if mod.type==type_name.upper():
262                     return True
263
264     @staticmethod
265     def isType(m, type_name):
266         return m.type==type_name.upper()
267
268     @staticmethod
269     def getArmatureObject(m):
270         return m.object
271
272
273 class shapekey:
274     @staticmethod
275     def assign(shapeKey, index, pos):
276         shapeKey.data[index].co=pos
277
278     @staticmethod
279     def getByIndex(b, index):
280         return b.data[index].co
281
282     @staticmethod
283     def get(b):
284         for k in b.data:
285             yield k.co
286
287
288 class texture:
289     @staticmethod
290     def create(path):
291         texture=bpy.data.textures.new(os.path.basename(path))
292         texture.type='IMAGE'
293         texture=texture.recast_type()
294         image=bpy.data.images.load(path)
295         texture.image=image
296         texture.mipmap=True
297         texture.interpolation=True
298         texture.use_alpha=True
299         return texture, image
300
301     @staticmethod
302     def getPath(t):
303         if  t.type=="IMAGE":
304             image=t.image
305             if image:
306                 return image.filename
307
308
309 class material:
310     @staticmethod
311     def create(name):
312         return bpy.data.materials.new(name)
313
314     @staticmethod
315     def get(material_name):
316         return bpy.data.materials[material_name]
317
318     @staticmethod
319     def addTexture(material, texture, enable=True):
320         # search free slot
321         index=None
322         for i, slot in enumerate(material.texture_slots):
323             if not slot:
324                 index=i
325                 break
326         if index==None:
327             return
328
329         if enable:
330             material.add_texture(texture, "UV", "COLOR")
331             slot=material.texture_slots[index]
332             slot.blend_type='MULTIPLY'
333             slot.map_alpha=True
334         else:
335             material.add_texture(texture)
336             material.use_textures[index]=False
337         return index
338
339     @staticmethod
340     def getTexture(m, index):
341         return m.texture_slots[index].texture
342
343     @staticmethod
344     def hasTexture(m):
345         return m.texture_slots[0]
346
347     @staticmethod
348     def setUseTexture(m, index, enable):
349         m.use_textures[index]=enable
350
351     @staticmethod
352     def eachTexturePath(m):
353         for slot in m.texture_slots:
354             if slot and slot.texture:
355                 texture=slot.texture
356                 if  texture.type=="IMAGE":
357                     image=texture.image
358                     if not image:
359                         continue
360                     yield image.filename
361
362     @staticmethod
363     def eachEnalbeTexturePath(m):
364         for i, slot in enumerate(m.texture_slots):
365             if m.use_textures[i] and slot and slot.texture:
366                 texture=slot.texture
367                 if  texture.type=="IMAGE":
368                     image=texture.image
369                     if not image:
370                         continue
371                     yield image.filename
372
373
374 class mesh:
375     @staticmethod
376     def create(name):
377         global SCENE
378         mesh=bpy.data.meshes.new("Mesh")
379         mesh_object= bpy.data.objects.new(name, mesh)
380         SCENE.objects.link(mesh_object)
381         return mesh, mesh_object
382
383     @staticmethod
384     def addGeometry(mesh, vertices, faces):
385         mesh.from_pydata(vertices, [], faces)
386         """
387         mesh.add_geometry(len(vertices), 0, len(faces))
388         # add vertex
389         unpackedVertices=[]
390         for v in vertices:
391             unpackedVertices.extend(v)
392         mesh.verts.foreach_set("co", unpackedVertices)
393         # add face
394         unpackedFaces = []
395         for face in faces:
396             if len(face) == 4:
397                 if face[3] == 0:
398                     # rotate indices if the 4th is 0
399                     face = [face[3], face[0], face[1], face[2]]
400             elif len(face) == 3:
401                 if face[2] == 0:
402                     # rotate indices if the 3rd is 0
403                     face = [face[2], face[0], face[1], 0]
404                 else:
405                     face.append(0)
406             unpackedFaces.extend(face)
407         mesh.faces.foreach_set("verts_raw", unpackedFaces)
408         """
409         assert(len(vertices)==len(mesh.verts))
410         assert(len(faces)==len(mesh.faces))
411
412     @staticmethod
413     def hasUV(mesh):
414         return mesh.active_uv_texture
415
416     @staticmethod
417     def useVertexUV(mesh):
418         pass
419
420     @staticmethod
421     def addUV(mesh):
422         mesh.add_uv_texture()
423
424     @staticmethod
425     def hasFaceUV(mesh, i, face):
426         return mesh.active_uv_texture and mesh.active_uv_texture.data[i]
427
428     @staticmethod
429     def getFaceUV(mesh, i, faces, count=3):
430         if mesh.active_uv_texture and mesh.active_uv_texture.data[i]:
431             uvFace=mesh.active_uv_texture.data[i]
432             if count==3:
433                 return (uvFace.uv1, uvFace.uv2, uvFace.uv3)
434             elif count==4:
435                 return (uvFace.uv1, uvFace.uv2, uvFace.uv3, uvFace.uv4)
436             else:
437                 print(count)
438                 assert(False)
439         else:
440             return ((0, 0), (0, 0), (0, 0), (0, 0))
441
442     @staticmethod
443     def setFaceUV(m, i, face, uv_array, image):
444         uv_face=m.uv_textures[0].data[i]
445         uv_face.uv=uv_array
446         if image:
447             uv_face.image=image
448             uv_face.tex=True
449
450     @staticmethod
451     def vertsDelete(m, remove_vertices):
452         enterEditMode()
453         bpy.ops.mesh.select_all(action='DESELECT')
454         enterObjectMode()
455
456         for i in remove_vertices:
457             m.verts[i].selected=True
458
459         enterEditMode()
460         bpy.ops.mesh.delete(type='VERT')
461         enterObjectMode()
462
463     @staticmethod
464     def setSmooth(m, smoothing):
465         m.autosmooth_angle=int(smoothing)
466         m.autosmooth=True
467
468     @staticmethod
469     def recalcNormals(mesh_object):
470         bpy.ops.object.select_all(action='DESELECT')
471         object.activate(mesh_object)
472         enterEditMode()
473         bpy.ops.mesh.normals_make_consistent()
474         enterObjectMode()
475
476     @staticmethod
477     def flipNormals(m):
478         m.flipNormals()
479
480     @staticmethod
481     def addMaterial(m, material):
482         m.add_material(material)
483
484     @staticmethod
485     def getMaterial(m, index):
486         return m.materials[index]
487
488
489 class vertex:
490     @staticmethod
491     def setNormal(v, normal):
492         v.normal=mathutils.Vector(normal)
493
494     @staticmethod
495     def getNormal(v):
496         return v.normal
497
498     @staticmethod
499     def setUv(v, uv):
500         # sticky ?
501         pass
502
503
504 class face:
505     @staticmethod
506     def getVertexCount(face):
507         return len(face.verts)
508
509     @staticmethod
510     def getVertices(face):
511         return face.verts[:]
512
513     @staticmethod
514     def getIndices(face, count=3):
515         if count==3:
516             return [face.verts[0], face.verts[1], face.verts[2]]
517         elif count==4:
518             return [face.verts[0], face.verts[1], face.verts[2], face.verts[3]]
519         else:
520             assert(False)
521
522     @staticmethod
523     def setMaterial(face, material_index):
524         face.material_index=material_index
525
526     @staticmethod
527     def getMaterialIndex(face):
528         return face.material_index
529
530     @staticmethod
531     def setNormal(face, normal):
532         face.normal=normal
533
534     @staticmethod
535     def getNormal(face):
536         return face.normal
537
538     @staticmethod
539     def setSmooth(face, isSmooth):
540         face.smooth=True if isSmooth else False
541
542
543 class armature:
544     @staticmethod
545     def create():
546         global SCENE
547         armature = bpy.data.armatures.new('Armature')
548         armature_object=bpy.data.objects.new('Armature', armature)
549         SCENE.objects.link(armature_object)
550
551         armature_object.x_ray=True
552         armature.draw_names=True
553         #armature.drawtype='OCTAHEDRAL'
554         armature.drawtype='STICK'
555         armature.deform_envelope=False
556         armature.deform_vertexgroups=True
557         armature.x_axis_mirror=True
558
559         return armature, armature_object
560
561     @staticmethod
562     def makeEditable(armature_object):
563         global SCENE
564         # select only armature object and set edit mode
565         SCENE.objects.active=armature_object
566         bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
567         bpy.ops.object.mode_set(mode='EDIT', toggle=False)
568
569     @staticmethod
570     def createIkConstraint(armature_object, p_bone, effector_name, ik):
571         constraint = p_bone.constraints.new('IK')
572         constraint.chain_length=len(ik.children)
573         constraint.target=armature_object
574         constraint.subtarget=effector_name
575         constraint.use_tail=False
576         # not used. place folder when export.
577         constraint.weight=ik.weight
578         constraint.iterations=ik.iterations * 10
579         return constraint
580
581     @staticmethod
582     def createBone(armature, name):
583         return armature.edit_bones.new(name)
584
585     @staticmethod
586     def update(armature):
587         pass
588
589
590 class bone:
591     @staticmethod
592     def setConnected(bone):
593         bone.connected=True
594
595     @staticmethod
596     def isConnected(b):
597         return b.connected
598
599     @staticmethod
600     def setLayerMask(bone, layers):
601         layer=[]
602         for i in range(32):
603             try:
604                 layer.append(True if layers[i]!=0 else False)
605             except IndexError:
606                 layer.append(False)
607         bone.layer=layer
608
609     @staticmethod
610     def getHeadLocal(b):
611         return b.head_local[0:3]
612
613     @staticmethod
614     def getTailLocal(b):
615         return b.tail_local[0:3]
616
617
618 class constraint:
619     @staticmethod
620     def ikChainLen(c):
621         return c.chain_length
622
623     @staticmethod
624     def ikTarget(c):
625         return c.subtarget
626
627     @staticmethod
628     def ikItration(c):
629         return c.iterations
630
631     @staticmethod
632     def ikRotationWeight(c):
633         return c.weight
634
635     @staticmethod
636     def isIKSolver(c):
637         return c.type=='IK'
638
639