OSDN Git Service

fix bone structure.
[meshio/meshio.git] / swig / blender / pmd_import.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__= "1.2"
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 """
29
30 MMD_SHAPE_GROUP_NAME='_MMD_SHAPE'
31 BASE_SHAPE_NAME='Basis'
32 RIGID_SHAPE_TYPE='rigid_shape_type'
33 RIGID_PROCESS_TYPE='rigid_process_type'
34 RIGID_BONE_NAME='rigid_bone_name'
35 #RIGID_LOCATION='rigid_loation'
36 RIGID_GROUP='ribid_group'
37 RIGID_INTERSECTION_GROUP='rigid_intersection_group'
38 RIGID_WEIGHT='rigid_weight'
39 RIGID_LINEAR_DAMPING='rigid_linear_damping'
40 RIGID_ANGULAR_DAMPING='rigid_angular_damping'
41 RIGID_RESTITUTION='rigid_restitution'
42 RIGID_FRICTION='rigid_friction'
43 CONSTRAINT_A='const_a'
44 CONSTRAINT_B='const_b'
45 CONSTRAINT_POS_MIN='const_pos_min'
46 CONSTRAINT_POS_MAX='const_pos_max'
47 CONSTRAINT_ROT_MIN='const_rot_min'
48 CONSTRAINT_ROT_MAX='const_rot_max'
49 CONSTRAINT_SPRING_POS='const_spring_pos'
50 CONSTRAINT_SPRING_ROT='const_spring_rot'
51
52
53 ###############################################################################
54 # import
55 ###############################################################################
56 import os
57 import sys
58 import math
59
60 # C extension
61 from meshio import pmd, englishmap
62
63 def isBlender24():
64     return sys.version_info[0]<3
65
66 if isBlender24():
67     # for 2.4
68     import Blender
69     from Blender import Mathutils
70     import bpy
71
72     # wrapper
73     import bl24 as bl
74 else:
75     # for 2.5
76     import bpy
77     from bpy.props import *
78     import mathutils
79
80     # wrapper
81     import bl25 as bl
82
83     xrange=range
84
85 ###############################################################################
86 def convert_coord(pos):
87     """
88     Left handed y-up to Right handed z-up
89     """
90     return (pos.x, pos.z, pos.y)
91
92
93 def convert_uv(uv):
94     return (uv.x, 1.0 - uv.y)
95
96
97 def to_radian(degree):
98     return math.pi * degree / 180
99
100
101 def get_bone_name(l, index):
102     name=englishmap.getEnglishBoneName(l.bones[index].getName())
103     return name if name else l.bones[index].getName()
104
105 def __importShape(obj, l, vertex_map):
106     if len(l.morph_list)==0:
107         return
108
109     # set shape_key pin
110     bl.objectPinShape(obj)
111
112     # find base 
113     base=None
114     for s in l.morph_list:
115         if s.type==0:
116             base=s
117
118             # create vertex group
119             bl.meshAddVertexGroup(obj, MMD_SHAPE_GROUP_NAME)
120             hasShape=False
121             for i in s.indices:
122                 if i in vertex_map:
123                     hasShape=True
124                     bl.meshAssignVertexGroup(
125                             obj, MMD_SHAPE_GROUP_NAME, vertex_map[i], 0)
126             if not hasShape:
127                 return
128     assert(base)
129
130     # create base key
131     baseShapeBlock=bl.objectAddShapeKey(obj, BASE_SHAPE_NAME)
132     # mesh
133     mesh=bl.objectGetData(obj)
134     mesh.update()
135
136     # each skin
137     for s in l.morph_list:
138         if s.type==0:
139             continue
140
141         # name
142         name=englishmap.getEnglishSkinName(s.getName())
143         if not name:
144             name=s.getName()
145
146         if isBlender24():
147             # 24
148             for index, offset in zip(s.indices, s.pos_list):
149                 try:
150                     vertex_index=vertex_map[base.indices[index]]
151                     v=mesh.verts[vertex_index].co
152                     offset=convert_coord(offset)
153                     v[0]+=offset[0]
154                     v[1]+=offset[1]
155                     v[2]+=offset[2]
156                 except IndexError as msg:
157                     print(msg)
158                     print(index, len(base.indices), len(vertex_map))
159                     print(len(mesh.verts))
160                     print(base.indices[index])
161                     print(vertex_index)
162                     break
163                 except KeyError:
164                     #print 'this mesh not has shape vertices'
165                     break
166
167             # create shapekey block
168             new_shape_key=bl.objectAddShapeKey(obj, name)
169
170             # copy vertex to shape key
171             mesh.update()
172             
173             # restore
174             for mv, v in zip(mesh.verts, baseShapeBlock.getData()):
175                 mv.co[0] = v[0]
176                 mv.co[1] = v[1]
177                 mv.co[2] = v[2]
178             mesh.update()
179
180         else:
181             # 25
182             new_shape_key=bl.objectAddShapeKey(obj, name)
183
184             for index, offset in zip(s.indices, s.pos_list):
185                 try:
186                     vertex_index=vertex_map[base.indices[index]]
187                     bl.shapeKeyAssign(new_shape_key, vertex_index,
188                             mesh.verts[vertex_index].co+
189                             bl.createVector(*convert_coord(offset)))
190                 except IndexError as msg:
191                     print(msg)
192                     print(index, len(base.indices), len(vertex_map))
193                     print(len(mesh.verts))
194                     print(base.indices[index])
195                     print(vertex_index)
196                     break
197                 except KeyError:
198                     #print 'this mesh not has shape vertices'
199                     break
200
201     # select base shape
202     bl.objectActivateShapeKey(obj, 0)
203
204
205 def __build(armature, b, p, parent):
206     name=englishmap.getEnglishBoneName(b.getName())
207     if not name:
208         name=b.getName()
209
210     bone=bl.createArmatureBone(armature, name)
211
212     if b.tail_index==0:
213         # 先端ボーン
214         assert(b.type==6 or b.type==7 or b.type==9)
215         bone.head = bl.createVector(*convert_coord(b.pos))
216         bone.tail=bone.head+bl.createVector(0, 1, 0)
217         assert(parent)
218         bone.parent=parent
219         if bone.name=="center_t":
220             # センターボーンは(0, 1, 0)の方向を向いていないと具合が悪い
221             parent.tail=parent.head+bl.createVector(0, 1, 0)
222             bone.head=parent.tail
223             bone.tail=bone.head+bl.createVector(0, 1, 0)
224         else:
225             assert(parent.tail==bone.head)
226         bl.boneSetConnected(bone)
227         # armature layer 2
228         bl.boneLayerMask(bone, [0, 1])
229     else:
230         # 通常ボーン
231         bone.head = bl.createVector(*convert_coord(b.pos))
232         bone.tail = bl.createVector(*convert_coord(b.tail))
233         if parent:
234             bone.parent=parent
235             if parent.tail==bone.head:
236                 bl.boneSetConnected(bone)
237
238     if bone.head==bone.tail:
239         bone.tail=bone.head+bl.createVector(0, 1, 0)
240
241     for c in b.children:
242         __build(armature, c, b, bone)
243
244
245 def __importArmature(scene, l):
246     # build bone
247     armature, armature_object=bl.createArmature(scene)
248     bl.armatureMakeEditable(scene, armature_object)
249     for b in l.bones:
250         if not b.parent:
251             __build(armature, b, None, None)
252     bl.armatureUpdate(armature)
253     bl.exitEditMode()
254
255     # IK constraint
256     pose = bl.objectGetPose(armature_object)
257     for ik in l.ik_list:
258         target=l.bones[ik.target]
259         name = englishmap.getEnglishBoneName(target.getName())
260         if not name:
261             name=target.getName()
262         p_bone = pose.bones[name]
263         if not p_bone:
264             print('not found', name)
265             continue
266         if len(ik.children) >= 16:
267             print('over MAX_CHAINLEN', ik, len(ik.children))
268             continue
269         effector_name=englishmap.getEnglishBoneName(
270                 l.bones[ik.index].getName())
271         if not effector_name:
272             effector_name=l.bones[ik.index].getName()
273
274         constraint=bl.createIkConstraint(armature_object, 
275                 p_bone, effector_name, ik)
276
277     bl.armatureMakeEditable(scene, armature_object)
278     bl.armatureUpdate(armature)
279     bl.exitEditMode()
280
281     return armature_object
282         
283
284 def __import16MaerialAndMesh(meshObject, l, 
285         material_order, face_map, tex_dir):
286
287     mesh=bl.objectGetData(meshObject)
288     ############################################################
289     # material
290     ############################################################
291     bl.progress_print('create materials')
292     mesh_material_map={}
293     textureMap={}
294     imageMap={}
295     index=0
296
297     for material_index in material_order:
298         try:
299             m=l.materials[material_index]
300             mesh_material_map[material_index]=index
301         except KeyError:
302             break
303
304         material=bl.createPmdMaterial(m)
305
306         texture_name=m.getTexture()
307         if texture_name!='':
308             if texture_name in textureMap:
309                 texture=textureMap[texture_name]
310             else:
311                 try:
312                     texture, image=bl.createTexture(
313                             os.path.join(tex_dir, texture_name))
314                     textureMap[texture_name]=texture
315                     imageMap[material_index]=image
316                 except:
317                     continue
318             bl.materialAddTexture(material, texture)
319         bl.meshAddMaterial(mesh, material)
320         index+=1
321
322     ############################################################
323     # vertex
324     ############################################################
325     bl.progress_print('create vertices')
326     # create vertices
327     vertices=[]
328     if isBlender24():
329         for v in l.each_vertex():
330             vertices.append(convert_coord(v.pos))
331     else:
332         for v in l.each_vertex():
333             vertices.extend(convert_coord(v.pos))
334
335     ############################################################
336     # face
337     ############################################################
338     bl.progress_print('create faces')
339     # create faces
340     mesh_face_indices=[]
341     mesh_face_materials=[]
342     used_vertices=set()
343
344     for material_index in material_order:
345         face_offset=face_map[material_index]
346         m=l.materials[material_index]
347         material_faces=l.indices[face_offset:face_offset+m.vertex_count]
348
349         def degenerate(i0, i1, i2):
350             """
351             縮退しているか?
352             """
353             return i0==i1 or i1==i2 or i2==i0
354
355         for j in xrange(0, len(material_faces), 3):
356             i0=material_faces[j]
357             i1=material_faces[j+1]
358             i2=material_faces[j+2]
359             if i2==0:
360                 triangle=[i2, i0, i1]
361             else:
362                 triangle=[i0, i1, i2]
363             if degenerate(*triangle):
364                 continue
365             if isBlender24():
366                 mesh_face_indices.append(triangle[0:3])
367             else:
368                 mesh_face_indices.extend(
369                         [triangle[0], triangle[1], triangle[2], 0])
370             mesh_face_materials.append(material_index)
371             used_vertices.add(i0)
372             used_vertices.add(i1)
373             used_vertices.add(i2)
374
375     ############################################################
376     # create vertices & faces
377     ############################################################
378     bl.meshCreateVerteicesAndFaces(mesh, vertices, mesh_face_indices)
379
380     ############################################################
381     # vertex bone weight
382     ############################################################
383     # create vertex group
384     vertex_groups={}
385     for v in l.each_vertex():
386         vertex_groups[v.bone0]=True
387         vertex_groups[v.bone1]=True
388     for i in vertex_groups.keys():
389         bl.meshAddVertexGroup(meshObject, get_bone_name(l, i))
390
391     # vertex params
392     bl.meshUseVertexUv(mesh)
393     for i, v, mvert in zip(xrange(len(l.vertices)), 
394         l.each_vertex(), mesh.verts):
395         # normal, uv
396         bl.vertexSetNormal(mvert, convert_coord(v.normal))
397         bl.vertexSetUv(mvert, convert_uv(v.uv))
398         # bone weight
399         w1=float(v.weight0)/100.0
400         w2=1.0-w1
401         bl.meshAssignVertexGroup(meshObject, get_bone_name(l, v.bone0),
402             i,  w1)
403         bl.meshAssignVertexGroup(meshObject, get_bone_name(l, v.bone1),
404             i,  w2)
405
406     ############################################################
407     # face params
408     ############################################################
409     used_map={}
410     bl.meshAddUV(mesh)
411
412     if isBlender24():
413         for face, material_index in zip(mesh.faces, mesh_face_materials):
414             try:
415                 index=mesh_material_map[material_index]
416             except KeyError as message:
417                 print(message, mesh_material_map, m)
418                 assert(False)
419             face.mat=index
420             material=mesh.materials[index]
421             texture=material.getTextures()[0]
422             used_map[index]=True
423             if texture:
424                 face.image=texture.tex.image
425                 texture.tex.imageFlags|=Blender.Texture.ImageFlags.USEALPHA
426                 face.uv=[
427                     face.verts[0].uvco, face.verts[1].uvco, face.verts[2].uvco]
428             # set smooth
429             face.smooth = 1
430         # flip
431         mesh.flipNormals()
432     else:
433         for face, uv_face, material_index in zip(mesh.faces, 
434                 mesh.uv_textures[0].data,
435                 mesh_face_materials,
436                 ):
437             try:
438                 index=mesh_material_map[material_index]
439             except KeyError as message:
440                 print(message, mesh_material_map, m)
441                 assert(False)
442             face.material_index=index
443             material=mesh.materials[index]
444             used_map[index]=True
445             if material.texture_slots[0]:
446                 uv=l.getUV(face.verts[0])
447                 uv_face.uv1=[uv.x, 1.0-uv.y]
448
449                 uv=l.getUV(face.verts[1])
450                 uv_face.uv2=[uv.x, 1.0-uv.y]
451
452                 uv=l.getUV(face.verts[2])
453                 uv_face.uv3=[uv.x, 1.0-uv.y]
454             if face.material_index in imageMap:
455                 uv_face.image=imageMap[face.material_index]
456                 uv_face.tex=True
457
458             # set smooth
459             face.smooth = 1
460     mesh.update()
461
462     ############################################################
463     # clean up not used vertices
464     ############################################################
465     bl.progress_print('clean up vertices not used')
466     remove_vertices=[]
467     vertex_map={}
468     for i, v in enumerate(l.each_vertex()):
469         if i in used_vertices:
470             vertex_map[i]=len(vertex_map)
471         else:
472             remove_vertices.append(i)
473
474     bl.meshVertsDelete(mesh, remove_vertices)
475
476     bl.progress_print('%s created' % mesh.name)
477     return vertex_map
478
479
480 def __importMesh(scene, io, tex_dir):
481     """
482     @param l[in] mmd.PMDLoader
483     @param filename[in]
484     """
485     ############################################################
486     # shpaeキーで使われるマテリアル優先的に前に並べる
487     ############################################################
488     # shapeキーで使われる頂点インデックスを集める
489     shape_key_used_vertices=set()
490     if len(io.morph_list)>0:
491         # base 
492         base=None
493         for s in io.morph_list:
494             if s.type!=0:
495                 continue
496             base=s
497             break
498         assert(base)
499
500         for index in base.indices:
501             shape_key_used_vertices.add(index)
502
503     # マテリアルに含まれる頂点がshape_keyに含まれるか否か?
504     def isMaterialUsedInShape(offset, m):
505         for i in xrange(offset, offset+m.vertex_count): 
506             if io.indices[i] in shape_key_used_vertices:
507                 return True
508
509     # shapeキーで使われるマテリアルを記録する
510     shape_key_materials=set()
511     # 各マテリアルの開始頂点インデックスを記録する
512     face_map={}
513     face_count=0
514     for i, m in enumerate(io.materials):
515         face_map[i]=face_count
516         if isMaterialUsedInShape(face_count, m):
517             shape_key_materials.add(i)
518         face_count+=m.vertex_count
519
520     # list化
521     material_order=list(shape_key_materials)
522
523     # shapeキーに使われていないマテリアルを後ろに追加
524     for i in range(len(io.materials)):
525         if not i in material_order:
526             material_order.append(i)
527
528     # マテリアル16個ごとに分割したメッシュを作成する
529     material_offset=0
530     mesh_objects=[]
531     while material_offset<len(io.materials):
532         mesh, meshObject=bl.createMesh(scene, 'mesh')
533         # create object
534         #meshObject.layers = [1]
535         mesh_objects.append(meshObject)
536
537         # activate object
538         bl.objectDeselectAll()
539         bl.objectActivate(scene, meshObject)
540
541         # shapeキーで使われる順に並べなおしたマテリアル16個分の
542         # メッシュを作成する
543         vertex_map=__import16MaerialAndMesh(
544                 meshObject, io, 
545                 material_order[material_offset:material_offset+16], 
546                 face_map, tex_dir)
547
548         # enter Edit Mode
549         #bl.enterEditMode()
550
551         # crete shape key
552         __importShape(meshObject, io, vertex_map)
553
554         # exit Edit Mode
555         #bl.exitEditMode()
556
557         mesh.update()
558         material_offset+=16
559
560     return mesh_objects
561
562
563 def __importConstraints(scene, io):
564     if isBlender24():
565         return
566     print("create constrains")
567     container=bl.createEmptyObject(scene, 'Constraints')
568     layer=[
569             True, False, False, False, False, False, False, False,
570             False, False, False, False, False, False, False, False,
571             False, False, False, False, False, False, False, False,
572             False, False, False, False, False, False, False, False,
573             ]
574     material=bl.createMaterial('constraint')
575     material.diffuse_color=(1, 0, 0)
576     constraintMeshes=[]
577     for c in io.constraints:
578         bpy.ops.mesh.primitive_uv_sphere_add(
579                 segments=8,
580                 rings=4,
581                 size=0.1,
582                 location=(c.pos.x, c.pos.z, c.pos.y),
583                 layer=layer
584                 )
585         meshObject=scene.objects.active
586         constraintMeshes.append(meshObject)
587         mesh=bl.objectGetData(meshObject)
588         bl.meshAddMaterial(mesh, material)
589         meshObject.name='c'+c.getName()
590         #meshObject.draw_transparent=True
591         #meshObject.draw_wire=True
592         meshObject.max_draw_type='SOLID'
593         rot=c.rot
594         meshObject.rotation_euler=(-rot.x, -rot.z, -rot.y)
595
596         meshObject[CONSTRAINT_A]=io.rigidbodies[c.rigidA].getName()
597         meshObject[CONSTRAINT_B]=io.rigidbodies[c.rigidB].getName()
598         meshObject[CONSTRAINT_POS_MIN]=bl.VtoV(c.constraintPosMin)
599         meshObject[CONSTRAINT_POS_MAX]=bl.VtoV(c.constraintPosMax)
600         meshObject[CONSTRAINT_ROT_MIN]=bl.VtoV(c.constraintRotMin)
601         meshObject[CONSTRAINT_ROT_MAX]=bl.VtoV(c.constraintRotMax)
602         meshObject[CONSTRAINT_SPRING_POS]=bl.VtoV(c.springPos)
603         meshObject[CONSTRAINT_SPRING_ROT]=bl.VtoV(c.springRot)
604
605     for meshObject in reversed(constraintMeshes):
606         bl.objectMakeParent(container, meshObject)
607
608     return container
609
610
611 def __importRigidBodies(scene, io):
612     if isBlender24():
613         return
614     print("create rigid bodies")
615
616     container=bl.createEmptyObject(scene, 'RigidBodies')
617     layer=[
618             True, False, False, False, False, False, False, False,
619             False, False, False, False, False, False, False, False,
620             False, False, False, False, False, False, False, False,
621             False, False, False, False, False, False, False, False,
622             ]
623     material=bl.createMaterial('rigidBody')
624     rigidMeshes=[]
625     for rigid in io.rigidbodies:
626         if rigid.boneIndex==0xFFFF:
627             # no reference bone
628             bone=io.bones[0]
629         else:
630             bone=io.bones[rigid.boneIndex]
631         pos=bone.pos+rigid.position
632
633         if rigid.shapeType==pmd.SHAPE_SPHERE:
634             bpy.ops.mesh.primitive_ico_sphere_add(
635                     location=(pos.x, pos.z, pos.y),
636                     layer=layer
637                     )
638             bpy.ops.transform.resize(
639                     value=(rigid.w, rigid.w, rigid.w))
640         elif rigid.shapeType==pmd.SHAPE_BOX:
641             bpy.ops.mesh.primitive_cube_add(
642                     location=(pos.x, pos.z, pos.y),
643                     layer=layer
644                     )
645             bpy.ops.transform.resize(
646                     value=(rigid.w, rigid.d, rigid.h))
647         elif rigid.shapeType==pmd.SHAPE_CAPSULE:
648             bpy.ops.mesh.primitive_tube_add(
649                     location=(pos.x, pos.z, pos.y),
650                     layer=layer
651                     )
652             bpy.ops.transform.resize(
653                     value=(rigid.w, rigid.w, rigid.h))
654         else:
655             assert(False)
656
657         meshObject=scene.objects.active
658         mesh=bl.objectGetData(meshObject)
659         rigidMeshes.append(meshObject)
660         bl.meshAddMaterial(mesh, material)
661         meshObject.name=rigid.getName()
662         #meshObject.draw_transparent=True
663         #meshObject.draw_wire=True
664         meshObject.max_draw_type='WIRE'
665         rot=rigid.rotation
666         meshObject.rotation_euler=(-rot.x, -rot.z, -rot.y)
667
668         # custom properties
669         meshObject[RIGID_SHAPE_TYPE]=rigid.shapeType
670         meshObject[RIGID_PROCESS_TYPE]=rigid.processType
671
672         bone_name = englishmap.getEnglishBoneName(bone.getName())
673         if not bone_name:
674             bone_name=bone.getName()
675         meshObject[RIGID_BONE_NAME]=bone_name
676
677         #meshObject[RIGID_LOCATION]=bl.VtoV(rigid.location)
678         meshObject[RIGID_GROUP]=rigid.group
679         meshObject[RIGID_INTERSECTION_GROUP]=rigid.target
680         meshObject[RIGID_WEIGHT]=rigid.weight
681         meshObject[RIGID_LINEAR_DAMPING]=rigid.linearDamping
682         meshObject[RIGID_ANGULAR_DAMPING]=rigid.angularDamping
683         meshObject[RIGID_RESTITUTION]=rigid.restitution
684         meshObject[RIGID_FRICTION]=rigid.friction
685
686     for meshObject in reversed(rigidMeshes):
687         bl.objectMakeParent(container, meshObject)
688
689     return container
690
691
692 def __execute(filename, scene):
693     """
694     load pmd file to context.
695     """
696     bl.progress_start('pmd_import')
697
698     # load pmd
699     bl.progress_set('load %s' % filename, 0.0)
700
701     io=pmd.IO()
702     if not io.read(filename):
703         print("fail to load %s" % filename)
704         return
705     bl.progress_set('loaded %s' % filename, 0.1)
706
707     # create root object
708     model_name=io.getEnglishName()
709     if len(model_name)==0:
710         model_name=io.getName()
711     root=bl.createEmptyObject(scene, model_name)
712
713     # import mesh
714     mesh_objects=__importMesh(scene, io, os.path.dirname(filename))
715     for o in mesh_objects:
716         bl.objectMakeParent(root, o)
717
718     # import armature
719     armature_object=__importArmature(scene, io)
720     if armature_object:
721         bl.objectMakeParent(root, armature_object)
722         armature = bl.objectGetData(armature_object) 
723
724         # add armature modifier
725         for o in mesh_objects:
726             bl.objectAddArmatureModifier(o, armature_object)
727
728         # Limitation
729         for n, b in bl.objectGetPose(armature_object).bones.items():
730             bl.poseBoneLimit(n, b)
731
732     # import rigid bodies
733     rigidBodies=__importRigidBodies(scene, io)
734     if rigidBodies:
735         bl.objectMakeParent(root, rigidBodies)
736
737     # import constraints
738     constraints=__importConstraints(scene, io)
739     if constraints:
740         bl.objectMakeParent(root, constraints)
741
742     bl.objectActivate(scene, root)
743     bl.progress_finish()
744
745 if isBlender24():
746     # for 2.4
747     def execute_24(filename):
748         """
749         @param filename
750         """
751         filename=filename.decode(bl.INTERNAL_ENCODING)
752         print(bl.INTERNAL_ENCODING, bl.FS_ENCODING)
753
754         # set object mode
755         mode_edit = Blender.Window.EditMode() 
756         if mode_edit: 
757             Blender.Window.EditMode(0)
758             
759         scene = bpy.data.scenes.active
760         __execute(filename, scene)
761         scene.update(0)
762
763         # restore edit mode
764         if mode_edit: 
765             Blender.Window.EditMode(1)
766         Blender.Window.RedrawAll()
767
768     Blender.Window.FileSelector(
769             execute_24, 
770             'Import PMD file', 
771             Blender.sys.makename(ext='.pmd'))
772
773 else:
774     # for 2.5
775     def execute_25(*args):
776         __execute(*args)
777
778     # import operator
779     class IMPORT_OT_pmd(bpy.types.Operator):
780         bl_idname = "import_scene.pmd"
781         bl_label = 'Import PMD'
782
783         # List of operator properties, the attributes will be assigned
784         # to the class instance from the operator settings before calling.
785
786         path = StringProperty(
787                 name="File Path", 
788                 description="File path used for importing the PMD file", 
789                 maxlen= 1024, default= "")
790         filename = StringProperty(
791                 name="File Name", 
792                 description="Name of the file.")
793         directory = StringProperty(
794                 name="Directory", 
795                 description="Directory of the file.")
796
797         def execute(self, context):
798             execute_25(self.properties.path, context.scene)
799             return 'FINISHED'
800
801         def invoke(self, context, event):
802             wm = context.manager
803             wm.add_fileselect(self)
804             return 'RUNNING_MODAL'
805
806     # register menu
807     def menu_func(self, context): 
808         self.layout.operator(IMPORT_OT_pmd.bl_idname, 
809                 text="MikuMikuDance model (.pmd)")
810
811     def register():
812         bpy.types.register(IMPORT_OT_pmd)
813         bpy.types.INFO_MT_file_import.append(menu_func)
814
815     def unregister():
816         bpy.types.unregister(IMPORT_OT_pmd)
817         bpy.types.INFO_MT_file_import.remove(menu_func)
818
819     if __name__=="__main__":
820         register()
821