OSDN Git Service

0f845ef0667d7ff21bf02579b8429268c8e2c733
[meshio/pymeshio.git] / blender25-meshio / import_pmd.py
1 #!BPY
2 # coding:utf-8
3 """
4  Name: 'MikuMikuDance model (.pmd)...'
5  Blender: 248
6  Group: 'Import'
7  Tooltip: 'Import PMD file for MikuMikuDance.'
8 """
9 __author__= ["ousttrue"]
10 __version__= "2.5"
11 __url__=()
12 __bpydoc__="""
13 pmd Importer
14
15 This script imports a pmd into Blender for editing.
16
17 0.1 20091126: first implement.
18 0.2 20091209: implement IK.
19 0.3 20091210: implement morph target.
20 0.4 20100305: use english name.
21 0.5 20100408: cleanup not used vertices.
22 0.6 20100416: fix fornt face. texture load fail safe. add progress.
23 0.7 20100506: C extension.
24 0.8 20100521: add shape_key group.
25 1.0 20100530: add invisilbe bone tail(armature layer 2).
26 1.1 20100608: integrate 2.4 and 2.5.
27 1.2 20100616: implement rigid body.
28 1.3 20100619: fix for various models.
29 1.4 20100623: fix constraint name.
30 1.5 20100626: refactoring.
31 1.6 20100629: sphere map.
32 1.7 20100703: implement bone group.
33 1.8 20100710: implement toon texture.
34 1.9 20100718: keep model name, comment.
35 2.0 20100724: update for Blender2.53.
36 2.1 20100731: add full python module.
37 2.2 20101005: update for Blender2.54.
38 2.3 20101228: update for Blender2.55.
39 2.4 20110429: update for Blender2.57b.
40 2.5 20110522: implement RigidBody and Constraint.
41 2.6 20110918: update for Blender2.59.
42 """
43 bl_addon_info = {
44         'category': 'Import/Export',
45         'name': 'Import: MikuMikuDance Model Format (.pmd)',
46         'author': 'ousttrue',
47         'version': (2, 2),
48         'blender': (2, 5, 3),
49         'location': 'File > Import',
50         'description': 'Import from the MikuMikuDance Model Format (.pmd)',
51         'warning': '', # used for warning icon and text in addons panel
52         'wiki_url': 'http://sourceforge.jp/projects/meshio/wiki/FrontPage',
53         'tracker_url': 'http://sourceforge.jp/ticket/newticket.php?group_id=5081',
54         }
55
56
57 ###############################################################################
58 # import
59 ###############################################################################
60 import os
61 import sys
62 import math
63
64 try:
65     # C extension
66     from .meshio import pmd, englishmap
67     print('use meshio C module')
68 except ImportError:
69     # full python
70     from .pymeshio import englishmap
71     #from .pymeshio import mmd as pmd
72     #pmd.IO=pmd.PMDLoader
73     from .pymeshio import pmd
74
75 # for 2.5
76 import bpy
77 import mathutils
78
79 # wrapper
80 from . import bl25 as bl
81
82 xrange=range
83
84 def createPmdMaterial(m, index):
85     material = bpy.data.materials.new("Material")
86     # diffuse
87     material.diffuse_shader='FRESNEL'
88     material.diffuse_color=([m.diffuse.r, m.diffuse.g, m.diffuse.b])
89     material.alpha=m.diffuse.a
90     # specular
91     material.specular_shader='TOON'
92     material.specular_color=([m.specular.r, m.specular.g, m.specular.b])
93     material.specular_toon_size=int(m.shinness)
94     # ambient
95     material.mirror_color=([m.ambient.r, m.ambient.g, m.ambient.b])
96     # flag
97     material.subsurface_scattering.use=True if m.flag==1 else False
98     # other
99     material.name="m_%02d" % index
100     material.preview_render_type='FLAT'
101     material.use_transparency=True
102     return material
103
104 def poseBoneLimit(n, b):
105     if n.endswith("_t"):
106         return
107     if n.startswith("knee_"):
108         b.lock_ik_y=True
109         b.lock_ik_z=True
110         b.lock_ik_x=False
111         # IK limit
112         b.use_ik_limit_x=True
113         b.ik_min_x=0
114         b.ik_max_x=180
115     elif n.startswith("ankle_"):
116         #b.ik_dof_y=False
117         pass
118
119 def setSphereMap(material, index, blend_type='MULTIPLY'):
120     slot=material.texture_slots[index]
121     slot.texture_coords='NORMAL'
122     slot.mapping='SPHERE'
123     slot.blend_type=blend_type
124
125
126 ###############################################################################
127 def VtoV(v):
128     return bl.createVector(v.x, v.y, v.z)
129
130
131 def convert_coord(pos):
132     """
133     Left handed y-up to Right handed z-up
134     """
135     return (pos.x, pos.z, pos.y)
136
137
138 def to_radian(degree):
139     return math.pi * degree / 180
140
141
142 def get_bone_name(l, index):
143     if index==0xFFFF:
144         return l.bones[0]._name
145
146     if index < len(l.bones):
147         name=englishmap.getEnglishBoneName(l.bones[index]._name)
148         if name:
149             return name
150         return l.bones[index]._name
151     print('invalid bone index', index)
152     return l.bones[0]._name
153
154
155 def get_group_name(g):
156     group_name=englishmap.getEnglishBoneGroupName(g._name.strip())
157     if not group_name:
158         group_name=g._name.strip()
159     return group_name
160
161
162 def __importToonTextures(io, tex_dir):
163     mesh, meshObject=bl.mesh.create(bl.TOON_TEXTURE_OBJECT)
164     material=bl.material.create(bl.TOON_TEXTURE_OBJECT)
165     bl.mesh.addMaterial(mesh, material)
166     for toon in (io.toon_textures._toon_textures[i] for i in range(10)):
167         path=os.path.join(tex_dir, toon)
168         texture, image=bl.texture.create(path)
169         bl.material.addTexture(material, texture, False)
170     return meshObject, material
171
172
173 def __importShape(obj, l, vertex_map):
174     if len(l.morph_list)==0:
175         return
176
177     # set shape_key pin
178     bl.object.pinShape(obj, True)
179
180     # find base
181     base=None
182     for s in l.morph_list:
183         if s.type==0:
184             base=s
185
186             # create vertex group
187             bl.object.addVertexGroup(obj, bl.MMD_SHAPE_GROUP_NAME)
188             hasShape=False
189             for i in s.indices:
190                 if i in vertex_map:
191                     hasShape=True
192                     bl.object.assignVertexGroup(
193                             obj, bl.MMD_SHAPE_GROUP_NAME, vertex_map[i], 0)
194             if not hasShape:
195                 return
196     assert(base)
197
198     # create base key
199     baseShapeBlock=bl.object.addShapeKey(obj, bl.BASE_SHAPE_NAME)
200     # mesh
201     mesh=bl.object.getData(obj)
202     mesh.update()
203
204     # each skin
205     for s in l.morph_list:
206         if s.type==0:
207             continue
208
209         # name
210         name=englishmap.getEnglishSkinName(s._name)
211         if not name:
212             name=s._name
213
214         # 25
215         new_shape_key=bl.object.addShapeKey(obj, name)
216
217         for index, offset in zip(s.indices, s.pos_list):
218             try:
219                 base_index=base.indices[index]
220             except IndexError as msg:
221                 print(name)
222                 print(msg)
223                 print("invalid index %d/%d" % (index, len(base.indices)))
224                 continue
225             vertex_index=vertex_map[base_index]
226             bl.shapekey.assign(new_shape_key, vertex_index,
227                     mesh.vertices[vertex_index].co+
228                     bl.createVector(*convert_coord(offset)))
229
230     # select base shape
231     bl.object.setActivateShapeKey(obj, 0)
232
233
234 def __build(armature, b, p, parent):
235     name=englishmap.getEnglishBoneName(b._name)
236     if not name:
237         name=b._name
238
239     bone=bl.armature.createBone(armature, name)
240
241     if parent and (b.tail_index==0 or b.type==6 or b.type==7 or b.type==9):
242         # 先端ボーン
243         bone.head = bl.createVector(*convert_coord(b.pos))
244         bone.tail=bone.head+bl.createVector(0, 1, 0)
245         bone.parent=parent
246         if bone.name=="center_t":
247             # センターボーンは(0, 1, 0)の方向を向いていないと具合が悪い
248             parent.tail=parent.head+bl.createVector(0, 1, 0)
249             bone.head=parent.tail
250             bone.tail=bone.head+bl.createVector(0, 1, 0)
251         else:
252             if parent.tail==bone.head:
253                 pass
254             else:
255                 print('diffurence with parent.tail and head', name)
256
257         if b.type!=9:
258             bl.bone.setConnected(bone)
259         # armature layer 2
260         bl.bone.setLayerMask(bone, [0, 1])
261     else:
262         # 通常ボーン
263         bone.head = bl.createVector(*convert_coord(b.pos))
264         bone.tail = bl.createVector(*convert_coord(b.tail))
265         if parent:
266             bone.parent=parent
267             if parent.tail==bone.head:
268                 bl.bone.setConnected(bone)
269
270     if bone.head==bone.tail:
271         bone.tail=bone.head+bl.createVector(0, 1, 0)
272
273     for c in b.children:
274         __build(armature, c, b, bone)
275
276
277 def __importArmature(l):
278     armature, armature_object=bl.armature.create()
279
280     # build bone
281     bl.armature.makeEditable(armature_object)
282     for b in l.bones:
283         if not b.parent:
284             __build(armature, b, None, None)
285     bl.armature.update(armature)
286     bl.enterObjectMode()
287
288     # IK constraint
289     pose = bl.object.getPose(armature_object)
290     for ik in l.ik_list:
291         target=l.bones[ik.target]
292         name = englishmap.getEnglishBoneName(target._name)
293         if not name:
294             name=target._name
295         p_bone = pose.bones[name]
296         if not p_bone:
297             print('not found', name)
298             continue
299         if len(ik.children) >= 16:
300             print('over MAX_CHAINLEN', ik, len(ik.children))
301             continue
302         effector_name=englishmap.getEnglishBoneName(
303                 l.bones[ik.index]._name)
304         if not effector_name:
305             effector_name=l.bones[ik.index]._name
306
307         constraint=bl.armature.createIkConstraint(armature_object,
308                 p_bone, effector_name, ik)
309
310     bl.armature.makeEditable(armature_object)
311     bl.armature.update(armature)
312     bl.enterObjectMode()
313
314     # create bone group
315     for i, g in enumerate(l.bone_group_list):
316         name=get_group_name(g)
317         bl.object.createBoneGroup(armature_object, name, "THEME%02d" % (i+1))
318
319     # assign bone to group
320     for b_index, g_index in l.bone_display_list:
321         # bone
322         b=l.bones[b_index]
323         bone_name=englishmap.getEnglishBoneName(b._name)
324         if not bone_name:
325             bone_name=b._name
326         # group
327         g=l.bone_group_list[g_index-1]
328         group_name=get_group_name(g)
329
330         # assign
331         pose.bones[bone_name].bone_group=pose.bone_groups[group_name]
332
333     bl.enterObjectMode()
334
335     return armature_object
336
337
338 def __import16MaerialAndMesh(meshObject, l,
339         material_order, face_map, tex_dir, toon_material):
340
341     mesh=bl.object.getData(meshObject)
342     ############################################################
343     # material
344     ############################################################
345     bl.progress_print('create materials')
346     mesh_material_map={}
347     textureMap={}
348     imageMap={}
349     index=0
350
351     for material_index in material_order:
352         try:
353             m=l.materials[material_index]
354             mesh_material_map[material_index]=index
355         except KeyError:
356             break
357
358         material=createPmdMaterial(m, material_index)
359
360         # main texture
361         texture_name=m._texture
362         if texture_name!='':
363             for i, t in enumerate(texture_name.split('*')):
364                 if t in textureMap:
365                     texture=textureMap[t]
366                 else:
367                     path=os.path.join(tex_dir, t)
368                     texture, image=bl.texture.create(path)
369                     textureMap[texture_name]=texture
370                     imageMap[material_index]=image
371                 texture_index=bl.material.addTexture(material, texture)
372                 if t.endswith('sph'):
373                     # sphere map
374                     setSphereMap(material, texture_index)
375                 elif t.endswith('spa'):
376                     # sphere map
377                     setSphereMap(material, texture_index, 'ADD')
378
379         # toon texture
380         toon_index=bl.material.addTexture(
381                 material,
382                 bl.material.getTexture(
383                     toon_material,
384                     0 if m.toon_index==0xFF else m.toon_index
385                     ),
386                 False)
387
388         bl.mesh.addMaterial(mesh, material)
389
390         index+=1
391
392     ############################################################
393     # vertex
394     ############################################################
395     bl.progress_print('create vertices')
396     # create vertices
397     vertices=[]
398     for v in l.each_vertex():
399         vertices.append(convert_coord(v.pos))
400
401     ############################################################
402     # face
403     ############################################################
404     bl.progress_print('create faces')
405     # create faces
406     mesh_face_indices=[]
407     mesh_face_materials=[]
408     used_vertices=set()
409
410     for material_index in material_order:
411         face_offset=face_map[material_index]
412         m=l.materials[material_index]
413         material_faces=l.indices[face_offset:face_offset+m.vertex_count]
414
415         def degenerate(i0, i1, i2):
416             """
417             縮退しているか?
418             """
419             return i0==i1 or i1==i2 or i2==i0
420
421         for j in xrange(0, len(material_faces), 3):
422             i0=material_faces[j]
423             i1=material_faces[j+1]
424             i2=material_faces[j+2]
425             # flip
426             triangle=[i2, i1, i0]
427             if degenerate(*triangle):
428                 continue
429             mesh_face_indices.append(triangle[0:3])
430             mesh_face_materials.append(material_index)
431             used_vertices.add(i0)
432             used_vertices.add(i1)
433             used_vertices.add(i2)
434
435     ############################################################
436     # create vertices & faces
437     ############################################################
438     bl.mesh.addGeometry(mesh, vertices, mesh_face_indices)
439
440     ############################################################
441     # vertex bone weight
442     ############################################################
443     # create vertex group
444     vertex_groups={}
445     for v in l.each_vertex():
446         vertex_groups[v.bone0]=True
447         vertex_groups[v.bone1]=True
448     for i in vertex_groups.keys():
449         bl.object.addVertexGroup(meshObject, get_bone_name(l, i))
450
451     # vertex params
452     bl.mesh.useVertexUV(mesh)
453     for i, v, mvert in zip(xrange(len(l.vertices)),
454         l.each_vertex(), mesh.vertices):
455         # normal, uv
456         bl.vertex.setNormal(mvert, convert_coord(v.normal))
457         # bone weight
458         w1=float(v.weight0)/100.0
459         w2=1.0-w1
460         bl.object.assignVertexGroup(meshObject, get_bone_name(l, v.bone0),
461             i,  w1)
462         bl.object.assignVertexGroup(meshObject, get_bone_name(l, v.bone1),
463             i,  w2)
464
465     ############################################################
466     # face params
467     ############################################################
468     used_map={}
469     bl.mesh.addUV(mesh)
470     for i, (face, material_index) in enumerate(
471             zip(mesh.faces, mesh_face_materials)):
472         try:
473             index=mesh_material_map[material_index]
474         except KeyError as message:
475             print(message, mesh_material_map, m)
476             assert(False)
477         bl.face.setMaterial(face, index)
478         material=mesh.materials[index]
479         used_map[index]=True
480         if bl.material.hasTexture(material):
481             uv_array=[l.getUV(i) for i in bl.face.getIndices(face)]
482             bl.mesh.setFaceUV(mesh, i, face,
483                     # fix uv
484                     [(uv.x, 1.0-uv.y) for uv in uv_array],
485                     imageMap.get(index, None))
486
487         # set smooth
488         bl.face.setSmooth(face, True)
489
490     mesh.update()
491
492     ############################################################
493     # clean up not used vertices
494     ############################################################
495     bl.progress_print('clean up vertices not used')
496     remove_vertices=[]
497     vertex_map={}
498     for i, v in enumerate(l.each_vertex()):
499         if i in used_vertices:
500             vertex_map[i]=len(vertex_map)
501         else:
502             remove_vertices.append(i)
503
504     bl.mesh.vertsDelete(mesh, remove_vertices)
505
506     bl.progress_print('%s created' % mesh.name)
507     return vertex_map
508
509
510 def __importMaterialAndMesh(io, tex_dir, toon_material):
511     """
512     @param l[in] mmd.PMDLoader
513     @param filename[in]
514     """
515     ############################################################
516     # shpaeキーで使われるマテリアル優先的に前に並べる
517     ############################################################
518     # shapeキーで使われる頂点インデックスを集める
519     shape_key_used_vertices=set()
520     if len(io.morph_list)>0:
521         # base
522         base=None
523         for s in io.morph_list:
524             if s.type!=0:
525                 continue
526             base=s
527             break
528         assert(base)
529
530         for index in base.indices:
531             shape_key_used_vertices.add(index)
532
533     # マテリアルに含まれる頂点がshape_keyに含まれるか否か?
534     def isMaterialUsedInShape(offset, m):
535         for i in xrange(offset, offset+m.vertex_count):
536             if io.indices[i] in shape_key_used_vertices:
537                 return True
538
539     material_with_shape=set()
540
541     # 各マテリアルの開始頂点インデックスを記録する
542     face_map={}
543     face_count=0
544     for i, m in enumerate(io.materials):
545         face_map[i]=face_count
546         if isMaterialUsedInShape(face_count, m):
547             material_with_shape.add(i)
548         face_count+=m.vertex_count
549
550     # shapeキーで使われる頂点のあるマテリアル
551     material_with_shape=list(material_with_shape)
552     material_with_shape.sort()
553
554     # shapeキーに使われていないマテリアル
555     material_without_shape=[]
556     for i in range(len(io.materials)):
557         if not i in material_with_shape:
558             material_without_shape.append(i)
559
560     # メッシュの生成
561     def __splitList(l, length):
562         for i in range(0, len(l), length):
563             yield l[i:i+length]
564
565     def __importMeshAndShape(material16, name):
566         mesh, meshObject=bl.mesh.create(name)
567
568         # activate object
569         bl.object.deselectAll()
570         bl.object.activate(meshObject)
571
572         # shapeキーで使われる順に並べなおしたマテリアル16個分の
573         # メッシュを作成する
574         vertex_map=__import16MaerialAndMesh(
575                 meshObject, io, material16, face_map, tex_dir, toon_material)
576
577         # crete shape key
578         __importShape(meshObject, io, vertex_map)
579
580         mesh.update()
581         return meshObject
582
583     mesh_objects=[__importMeshAndShape(material16, 'with_shape')
584         for material16 in __splitList(material_with_shape, 16)]
585
586     mesh_objects+=[__importMeshAndShape(material16, 'mesh')
587         for material16 in __splitList(material_without_shape, 16)]
588
589     return mesh_objects
590
591
592 def __importConstraints(io):
593     print("create constraint")
594     container=bl.object.createEmpty('Constraints')
595     layers=[
596         True, False, False, False, False, False, False, False, False, False,
597         False, False, False, False, False, False, False, False, False, False,
598             ]
599     material=bl.material.create('constraint')
600     material.diffuse_color=(1, 0, 0)
601     constraintMeshes=[]
602     for i, c in enumerate(io.constraints):
603         bpy.ops.mesh.primitive_uv_sphere_add(
604                 segments=8,
605                 ring_count=4,
606                 size=0.1,
607                 location=(c.pos.x, c.pos.z, c.pos.y),
608                 layers=layers
609                 )
610         meshObject=bl.object.getActive()
611         constraintMeshes.append(meshObject)
612         mesh=bl.object.getData(meshObject)
613         bl.mesh.addMaterial(mesh, material)
614         meshObject.name='c_%03d' % i
615         #meshObject.draw_transparent=True
616         #meshObject.draw_wire=True
617         meshObject.draw_type='SOLID'
618         rot=c.rot
619         meshObject.rotation_euler=(-rot.x, -rot.z, -rot.y)
620
621         meshObject[bl.CONSTRAINT_NAME]=c._name
622         meshObject[bl.CONSTRAINT_A]=io.rigidbodies[c.rigidA]._name
623         meshObject[bl.CONSTRAINT_B]=io.rigidbodies[c.rigidB]._name
624         meshObject[bl.CONSTRAINT_POS_MIN]=VtoV(c.constraintPosMin)
625         meshObject[bl.CONSTRAINT_POS_MAX]=VtoV(c.constraintPosMax)
626         meshObject[bl.CONSTRAINT_ROT_MIN]=VtoV(c.constraintRotMin)
627         meshObject[bl.CONSTRAINT_ROT_MAX]=VtoV(c.constraintRotMax)
628         meshObject[bl.CONSTRAINT_SPRING_POS]=VtoV(c.springPos)
629         meshObject[bl.CONSTRAINT_SPRING_ROT]=VtoV(c.springRot)
630
631     for meshObject in reversed(constraintMeshes):
632         bl.object.makeParent(container, meshObject)
633
634     return container
635
636
637 def __importRigidBodies(io):
638     print("create rigid bodies")
639
640     container=bl.object.createEmpty('RigidBodies')
641     layers=[
642         True, False, False, False, False, False, False, False, False, False,
643         False, False, False, False, False, False, False, False, False, False,
644             ]
645     material=bl.material.create('rigidBody')
646     rigidMeshes=[]
647     for i, rigid in enumerate(io.rigidbodies):
648         if rigid.boneIndex==0xFFFF:
649             # no reference bone
650             bone=io.bones[0]
651         else:
652             bone=io.bones[rigid.boneIndex]
653         pos=bone.pos+rigid.position
654
655         if rigid.shapeType==pmd.SHAPE_SPHERE:
656             bpy.ops.mesh.primitive_ico_sphere_add(
657                     location=(pos.x, pos.z, pos.y),
658                     layers=layers
659                     )
660             bpy.ops.transform.resize(
661                     value=(rigid.w, rigid.w, rigid.w))
662         elif rigid.shapeType==pmd.SHAPE_BOX:
663             bpy.ops.mesh.primitive_cube_add(
664                     location=(pos.x, pos.z, pos.y),
665                     layers=layers
666                     )
667             bpy.ops.transform.resize(
668                     value=(rigid.w, rigid.d, rigid.h))
669         elif rigid.shapeType==pmd.SHAPE_CAPSULE:
670             bpy.ops.mesh.primitive_cylinder_add(
671                     location=(pos.x, pos.z, pos.y),
672                     layers=layers
673                     )
674             bpy.ops.transform.resize(
675                     value=(rigid.w, rigid.w, rigid.h))
676         else:
677             assert(False)
678
679         meshObject=bl.object.getActive()
680         mesh=bl.object.getData(meshObject)
681         rigidMeshes.append(meshObject)
682         bl.mesh.addMaterial(mesh, material)
683         meshObject.name='r_%03d' % i
684         meshObject[bl.RIGID_NAME]=rigid._name
685         #meshObject.draw_transparent=True
686         #meshObject.draw_wire=True
687         meshObject.draw_type='WIRE'
688         rot=rigid.rotation
689         meshObject.rotation_euler=(-rot.x, -rot.z, -rot.y)
690
691         # custom properties
692         meshObject[bl.RIGID_SHAPE_TYPE]=rigid.shapeType
693         meshObject[bl.RIGID_PROCESS_TYPE]=rigid.processType
694
695         bone_name = englishmap.getEnglishBoneName(bone._name)
696         if not bone_name:
697             bone_name=bone._name
698         meshObject[bl.RIGID_BONE_NAME]=bone_name
699
700         meshObject[bl.RIGID_GROUP]=rigid.group
701         meshObject[bl.RIGID_INTERSECTION_GROUP]=rigid.target
702         meshObject[bl.RIGID_WEIGHT]=rigid.weight
703         meshObject[bl.RIGID_LINEAR_DAMPING]=rigid.linearDamping
704         meshObject[bl.RIGID_ANGULAR_DAMPING]=rigid.angularDamping
705         meshObject[bl.RIGID_RESTITUTION]=rigid.restitution
706         meshObject[bl.RIGID_FRICTION]=rigid.friction
707
708     for meshObject in reversed(rigidMeshes):
709         bl.object.makeParent(container, meshObject)
710
711     return container
712
713
714 def _execute(filepath=""):
715     """
716     load pmd file to context.
717     """
718
719     # load pmd
720     bl.progress_set('load %s' % filepath, 0.0)
721
722     io=pmd.IO()
723     if not io.read(filepath):
724         bl.message("fail to load %s" % filepath)
725         return
726     bl.progress_set('loaded', 0.1)
727
728     # create root object
729     model_name=io._english_name
730     if len(model_name)==0:
731         model_name=io._name
732     root=bl.object.createEmpty(model_name)
733     root[bl.MMD_MB_NAME]=io._name
734     root[bl.MMD_MB_COMMENT]=io._comment
735     root[bl.MMD_COMMENT]=io._english_comment
736
737     # toon textures
738     tex_dir=os.path.dirname(filepath)
739     toonTextures, toonMaterial=__importToonTextures(io, tex_dir)
740     bl.object.makeParent(root, toonTextures)
741
742     # import mesh
743     mesh_objects=__importMaterialAndMesh(io, tex_dir, toonMaterial)
744     for o in mesh_objects:
745         bl.object.makeParent(root, o)
746
747     # import armature
748     armature_object=__importArmature(io)
749     if armature_object:
750         bl.object.makeParent(root, armature_object)
751         armature = bl.object.getData(armature_object)
752
753         # add armature modifier
754         for o in mesh_objects:
755             bl.modifier.addArmature(o, armature_object)
756
757         # Limitation
758         for n, b in bl.object.getPose(armature_object).bones.items():
759             poseBoneLimit(n, b)
760
761     # import rigid bodies
762     rigidBodies=__importRigidBodies(io)
763     if rigidBodies:
764         bl.object.makeParent(root, rigidBodies)
765
766     # import constraints
767     constraints=__importConstraints(io)
768     if constraints:
769         bl.object.makeParent(root, constraints)
770
771     bl.object.activate(root)
772