OSDN Git Service

c8b556022bba3bfb6874faffd794dfe8c15191e7
[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)
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         bone.head = bl.createVector(*convert_coord(b.pos))
231         bone.tail = bl.createVector(*convert_coord(b.tail))
232         if parent:
233             bone.parent=parent
234             if parent.tail==bone.head:
235                 bl.boneSetConnected(bone)
236
237     if bone.head==bone.tail:
238         bone.tail=bone.head+bl.createVector(0, 1, 0)
239
240     for c in b.children:
241         __build(armature, c, b, bone)
242
243
244 def __importArmature(scene, l):
245     # build bone
246     armature, armature_object=bl.createArmature(scene)
247     bl.armatureMakeEditable(scene, armature_object)
248     for b in l.bones:
249         if not b.parent:
250             __build(armature, b, None, None)
251     bl.armatureUpdate(armature)
252     bl.exitEditMode()
253
254     # IK constraint
255     pose = bl.objectGetPose(armature_object)
256     for ik in l.ik_list:
257         target=l.bones[ik.target]
258         name = englishmap.getEnglishBoneName(target.getName())
259         if not name:
260             name=target.getName()
261         p_bone = pose.bones[name]
262         if not p_bone:
263             print('not found', name)
264             continue
265         if len(ik.children) >= 16:
266             print('over MAX_CHAINLEN', ik, len(ik.children))
267             continue
268         effector_name=englishmap.getEnglishBoneName(
269                 l.bones[ik.index].getName())
270         if not effector_name:
271             effector_name=l.bones[ik.index].getName()
272
273         constraint=bl.createIkConstraint(armature_object, 
274                 p_bone, effector_name, ik)
275
276     bl.armatureMakeEditable(scene, armature_object)
277     bl.armatureUpdate(armature)
278     bl.exitEditMode()
279
280     return armature_object
281         
282
283 def __import16MaerialAndMesh(meshObject, l, 
284         material_order, face_map, tex_dir):
285
286     mesh=bl.objectGetData(meshObject)
287     ############################################################
288     # material
289     ############################################################
290     bl.progress_print('create materials')
291     mesh_material_map={}
292     textureMap={}
293     imageMap={}
294     index=0
295
296     for material_index in material_order:
297         try:
298             m=l.materials[material_index]
299             mesh_material_map[material_index]=index
300         except KeyError:
301             break
302
303         material=bl.createPmdMaterial(m)
304
305         texture_name=m.getTexture()
306         if texture_name!='':
307             if texture_name in textureMap:
308                 texture=textureMap[texture_name]
309             else:
310                 try:
311                     texture, image=bl.createTexture(
312                             os.path.join(tex_dir, texture_name))
313                     textureMap[texture_name]=texture
314                     imageMap[material_index]=image
315                 except:
316                     continue
317             bl.materialAddTexture(material, texture)
318         bl.meshAddMaterial(mesh, material)
319         index+=1
320
321     ############################################################
322     # vertex
323     ############################################################
324     bl.progress_print('create vertices')
325     # create vertices
326     vertices=[]
327     if isBlender24():
328         for v in l.each_vertex():
329             vertices.append(convert_coord(v.pos))
330     else:
331         for v in l.each_vertex():
332             vertices.extend(convert_coord(v.pos))
333
334     ############################################################
335     # face
336     ############################################################
337     bl.progress_print('create faces')
338     # create faces
339     mesh_face_indices=[]
340     mesh_face_materials=[]
341     used_vertices=set()
342
343     for material_index in material_order:
344         face_offset=face_map[material_index]
345         m=l.materials[material_index]
346         material_faces=l.indices[face_offset:face_offset+m.vertex_count]
347
348         def degenerate(i0, i1, i2):
349             """
350             縮退しているか?
351             """
352             return i0==i1 or i1==i2 or i2==i0
353
354         for j in xrange(0, len(material_faces), 3):
355             i0=material_faces[j]
356             i1=material_faces[j+1]
357             i2=material_faces[j+2]
358             if i2==0:
359                 triangle=[i2, i0, i1]
360             else:
361                 triangle=[i0, i1, i2]
362             if degenerate(*triangle):
363                 continue
364             if isBlender24():
365                 mesh_face_indices.append(triangle[0:3])
366             else:
367                 mesh_face_indices.extend(
368                         [triangle[0], triangle[1], triangle[2], 0])
369             mesh_face_materials.append(material_index)
370             used_vertices.add(i0)
371             used_vertices.add(i1)
372             used_vertices.add(i2)
373
374     ############################################################
375     # create vertices & faces
376     ############################################################
377     bl.meshCreateVerteicesAndFaces(mesh, vertices, mesh_face_indices)
378
379     ############################################################
380     # vertex bone weight
381     ############################################################
382     # create vertex group
383     vertex_groups={}
384     for v in l.each_vertex():
385         vertex_groups[v.bone0]=True
386         vertex_groups[v.bone1]=True
387     for i in vertex_groups.keys():
388         bl.meshAddVertexGroup(meshObject, get_bone_name(l, i))
389
390     # vertex params
391     bl.meshUseVertexUv(mesh)
392     for i, v, mvert in zip(xrange(len(l.vertices)), 
393         l.each_vertex(), mesh.verts):
394         # normal, uv
395         bl.vertexSetNormal(mvert, convert_coord(v.normal))
396         bl.vertexSetUv(mvert, convert_uv(v.uv))
397         # bone weight
398         w1=float(v.weight0)/100.0
399         w2=1.0-w1
400         bl.meshAssignVertexGroup(meshObject, get_bone_name(l, v.bone0),
401             i,  w1)
402         bl.meshAssignVertexGroup(meshObject, get_bone_name(l, v.bone1),
403             i,  w2)
404
405     ############################################################
406     # face params
407     ############################################################
408     used_map={}
409     bl.meshAddUV(mesh)
410
411     if isBlender24():
412         for face, material_index in zip(mesh.faces, mesh_face_materials):
413             try:
414                 index=mesh_material_map[material_index]
415             except KeyError as message:
416                 print(message, mesh_material_map, m)
417                 assert(False)
418             face.mat=index
419             material=mesh.materials[index]
420             texture=material.getTextures()[0]
421             used_map[index]=True
422             if texture:
423                 face.image=texture.tex.image
424                 texture.tex.imageFlags|=Blender.Texture.ImageFlags.USEALPHA
425                 face.uv=[
426                     face.verts[0].uvco, face.verts[1].uvco, face.verts[2].uvco]
427             # set smooth
428             face.smooth = 1
429         # flip
430         mesh.flipNormals()
431     else:
432         for face, uv_face, material_index in zip(mesh.faces, 
433                 mesh.uv_textures[0].data,
434                 mesh_face_materials,
435                 ):
436             try:
437                 index=mesh_material_map[material_index]
438             except KeyError as message:
439                 print(message, mesh_material_map, m)
440                 assert(False)
441             face.material_index=index
442             material=mesh.materials[index]
443             used_map[index]=True
444             if material.texture_slots[0]:
445                 uv=l.getUV(face.verts[0])
446                 uv_face.uv1=[uv.x, 1.0-uv.y]
447
448                 uv=l.getUV(face.verts[1])
449                 uv_face.uv2=[uv.x, 1.0-uv.y]
450
451                 uv=l.getUV(face.verts[2])
452                 uv_face.uv3=[uv.x, 1.0-uv.y]
453             if face.material_index in imageMap:
454                 uv_face.image=imageMap[face.material_index]
455                 uv_face.tex=True
456
457             # set smooth
458             face.smooth = 1
459     mesh.update()
460
461     ############################################################
462     # clean up not used vertices
463     ############################################################
464     bl.progress_print('clean up vertices not used')
465     remove_vertices=[]
466     vertex_map={}
467     for i, v in enumerate(l.each_vertex()):
468         if i in used_vertices:
469             vertex_map[i]=len(vertex_map)
470         else:
471             remove_vertices.append(i)
472
473     bl.meshVertsDelete(mesh, remove_vertices)
474
475     bl.progress_print('%s created' % mesh.name)
476     return vertex_map
477
478
479 def __importMesh(scene, io, tex_dir):
480     """
481     @param l[in] mmd.PMDLoader
482     @param filename[in]
483     """
484     ############################################################
485     # shpaeキーで使われるマテリアル優先的に前に並べる
486     ############################################################
487     # shapeキーで使われる頂点インデックスを集める
488     shape_key_used_vertices=set()
489     if len(io.morph_list)>0:
490         # base 
491         base=None
492         for s in io.morph_list:
493             if s.type!=0:
494                 continue
495             base=s
496             break
497         assert(base)
498
499         for index in base.indices:
500             shape_key_used_vertices.add(index)
501
502     # マテリアルに含まれる頂点がshape_keyに含まれるか否か?
503     def isMaterialUsedInShape(offset, m):
504         for i in xrange(offset, offset+m.vertex_count): 
505             if io.indices[i] in shape_key_used_vertices:
506                 return True
507
508     # shapeキーで使われるマテリアルを記録する
509     shape_key_materials=set()
510     # 各マテリアルの開始頂点インデックスを記録する
511     face_map={}
512     face_count=0
513     for i, m in enumerate(io.materials):
514         face_map[i]=face_count
515         if isMaterialUsedInShape(face_count, m):
516             shape_key_materials.add(i)
517         face_count+=m.vertex_count
518
519     # list化
520     material_order=list(shape_key_materials)
521
522     # shapeキーに使われていないマテリアルを後ろに追加
523     for i in range(len(io.materials)):
524         if not i in material_order:
525             material_order.append(i)
526
527     # マテリアル16個ごとに分割したメッシュを作成する
528     material_offset=0
529     mesh_objects=[]
530     while material_offset<len(io.materials):
531         mesh, meshObject=bl.createMesh(scene, 'mesh')
532         # create object
533         #meshObject.layers = [1]
534         mesh_objects.append(meshObject)
535
536         # activate object
537         bl.objectDeselectAll()
538         bl.objectActivate(scene, meshObject)
539
540         # shapeキーで使われる順に並べなおしたマテリアル16個分の
541         # メッシュを作成する
542         vertex_map=__import16MaerialAndMesh(
543                 meshObject, io, 
544                 material_order[material_offset:material_offset+16], 
545                 face_map, tex_dir)
546
547         # enter Edit Mode
548         #bl.enterEditMode()
549
550         # crete shape key
551         __importShape(meshObject, io, vertex_map)
552
553         # exit Edit Mode
554         #bl.exitEditMode()
555
556         mesh.update()
557         material_offset+=16
558
559     return mesh_objects
560
561
562 def __importConstraints(scene, io):
563     if isBlender24():
564         return
565     print("create constrains")
566     container=bl.createEmptyObject(scene, 'Constraints')
567     layer=[
568             True, False, False, False, False, False, False, False,
569             False, 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             ]
573     material=bl.createMaterial('constraint')
574     material.diffuse_color=(1, 0, 0)
575     constraintMeshes=[]
576     for c in io.constraints:
577         bpy.ops.mesh.primitive_uv_sphere_add(
578                 segments=8,
579                 rings=4,
580                 size=0.1,
581                 location=(c.pos.x, c.pos.z, c.pos.y),
582                 layer=layer
583                 )
584         meshObject=scene.objects.active
585         constraintMeshes.append(meshObject)
586         mesh=bl.objectGetData(meshObject)
587         bl.meshAddMaterial(mesh, material)
588         meshObject.name='c'+c.getName()
589         #meshObject.draw_transparent=True
590         #meshObject.draw_wire=True
591         meshObject.max_draw_type='SOLID'
592         rot=c.rot
593         meshObject.rotation_euler=(-rot.x, -rot.z, -rot.y)
594
595         meshObject[CONSTRAINT_A]=io.rigidbodies[c.rigidA].getName()
596         meshObject[CONSTRAINT_B]=io.rigidbodies[c.rigidB].getName()
597         meshObject[CONSTRAINT_POS_MIN]=bl.VtoV(c.constraintPosMin)
598         meshObject[CONSTRAINT_POS_MAX]=bl.VtoV(c.constraintPosMax)
599         meshObject[CONSTRAINT_ROT_MIN]=bl.VtoV(c.constraintRotMin)
600         meshObject[CONSTRAINT_ROT_MAX]=bl.VtoV(c.constraintRotMax)
601         meshObject[CONSTRAINT_SPRING_POS]=bl.VtoV(c.springPos)
602         meshObject[CONSTRAINT_SPRING_ROT]=bl.VtoV(c.springRot)
603
604     for meshObject in reversed(constraintMeshes):
605         bl.objectMakeParent(container, meshObject)
606
607     return container
608
609
610 def __importRigidBodies(scene, io):
611     if isBlender24():
612         return
613     print("create rigid bodies")
614
615     container=bl.createEmptyObject(scene, 'RigidBodies')
616     layer=[
617             True, False, False, False, False, False, False, False,
618             False, 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             ]
622     material=bl.createMaterial('rigidBody')
623     rigidMeshes=[]
624     for rigid in io.rigidbodies:
625         if rigid.boneIndex==0xFFFF:
626             # no reference bone
627             bone=io.bones[0]
628         else:
629             bone=io.bones[rigid.boneIndex]
630         pos=bone.pos+rigid.position
631
632         if rigid.shapeType==pmd.SHAPE_SPHERE:
633             bpy.ops.mesh.primitive_ico_sphere_add(
634                     location=(pos.x, pos.z, pos.y),
635                     layer=layer
636                     )
637             bpy.ops.transform.resize(
638                     value=(rigid.w, rigid.w, rigid.w))
639         elif rigid.shapeType==pmd.SHAPE_BOX:
640             bpy.ops.mesh.primitive_cube_add(
641                     location=(pos.x, pos.z, pos.y),
642                     layer=layer
643                     )
644             bpy.ops.transform.resize(
645                     value=(rigid.w, rigid.d, rigid.h))
646         elif rigid.shapeType==pmd.SHAPE_CAPSULE:
647             bpy.ops.mesh.primitive_tube_add(
648                     location=(pos.x, pos.z, pos.y),
649                     layer=layer
650                     )
651             bpy.ops.transform.resize(
652                     value=(rigid.w, rigid.w, rigid.h))
653         else:
654             assert(False)
655
656         meshObject=scene.objects.active
657         mesh=bl.objectGetData(meshObject)
658         rigidMeshes.append(meshObject)
659         bl.meshAddMaterial(mesh, material)
660         meshObject.name=rigid.getName()
661         #meshObject.draw_transparent=True
662         #meshObject.draw_wire=True
663         meshObject.max_draw_type='WIRE'
664         rot=rigid.rotation
665         meshObject.rotation_euler=(-rot.x, -rot.z, -rot.y)
666
667         # custom properties
668         meshObject[RIGID_SHAPE_TYPE]=rigid.shapeType
669         meshObject[RIGID_PROCESS_TYPE]=rigid.processType
670
671         bone_name = englishmap.getEnglishBoneName(bone.getName())
672         if not bone_name:
673             bone_name=bone.getName()
674         meshObject[RIGID_BONE_NAME]=bone_name
675
676         #meshObject[RIGID_LOCATION]=bl.VtoV(rigid.location)
677         meshObject[RIGID_GROUP]=rigid.group
678         meshObject[RIGID_INTERSECTION_GROUP]=rigid.target
679         meshObject[RIGID_WEIGHT]=rigid.weight
680         meshObject[RIGID_LINEAR_DAMPING]=rigid.linearDamping
681         meshObject[RIGID_ANGULAR_DAMPING]=rigid.angularDamping
682         meshObject[RIGID_RESTITUTION]=rigid.restitution
683         meshObject[RIGID_FRICTION]=rigid.friction
684
685     for meshObject in reversed(rigidMeshes):
686         bl.objectMakeParent(container, meshObject)
687
688     return container
689
690
691 def __execute(filename, scene):
692     """
693     load pmd file to context.
694     """
695     bl.progress_start('pmd_import')
696
697     # load pmd
698     bl.progress_set('load %s' % filename, 0.0)
699
700     io=pmd.IO()
701     if not io.read(filename):
702         print("fail to load %s" % filename)
703         return
704     bl.progress_set('loaded %s' % filename, 0.1)
705
706     # create root object
707     model_name=io.getEnglishName()
708     if len(model_name)==0:
709         model_name=io.getName()
710     root=bl.createEmptyObject(scene, model_name)
711
712     # import mesh
713     mesh_objects=__importMesh(scene, io, os.path.dirname(filename))
714     for o in mesh_objects:
715         bl.objectMakeParent(root, o)
716
717     # import armature
718     armature_object=__importArmature(scene, io)
719     if armature_object:
720         bl.objectMakeParent(root, armature_object)
721         armature = bl.objectGetData(armature_object) 
722
723         # add armature modifier
724         for o in mesh_objects:
725             bl.objectAddArmatureModifier(o, armature_object)
726
727         # Limitation
728         for n, b in bl.objectGetPose(armature_object).bones.items():
729             bl.poseBoneLimit(n, b)
730
731     # import rigid bodies
732     rigidBodies=__importRigidBodies(scene, io)
733     if rigidBodies:
734         bl.objectMakeParent(root, rigidBodies)
735
736     # import constraints
737     constraints=__importConstraints(scene, io)
738     if constraints:
739         bl.objectMakeParent(root, constraints)
740
741     bl.objectActivate(scene, root)
742     bl.progress_finish()
743
744 if isBlender24():
745     # for 2.4
746     def execute_24(filename):
747         """
748         @param filename
749         """
750         filename=filename.decode(bl.INTERNAL_ENCODING)
751         print(bl.INTERNAL_ENCODING, bl.FS_ENCODING)
752
753         # set object mode
754         mode_edit = Blender.Window.EditMode() 
755         if mode_edit: 
756             Blender.Window.EditMode(0)
757             
758         scene = bpy.data.scenes.active
759         __execute(filename, scene)
760         scene.update(0)
761
762         # restore edit mode
763         if mode_edit: 
764             Blender.Window.EditMode(1)
765         Blender.Window.RedrawAll()
766
767     Blender.Window.FileSelector(
768             execute_24, 
769             'Import PMD file', 
770             Blender.sys.makename(ext='.pmd'))
771
772 else:
773     # for 2.5
774     def execute_25(*args):
775         __execute(*args)
776
777     # import operator
778     class IMPORT_OT_pmd(bpy.types.Operator):
779         bl_idname = "import_scene.pmd"
780         bl_label = 'Import PMD'
781
782         # List of operator properties, the attributes will be assigned
783         # to the class instance from the operator settings before calling.
784
785         path = StringProperty(
786                 name="File Path", 
787                 description="File path used for importing the PMD file", 
788                 maxlen= 1024, default= "")
789         filename = StringProperty(
790                 name="File Name", 
791                 description="Name of the file.")
792         directory = StringProperty(
793                 name="Directory", 
794                 description="Directory of the file.")
795
796         def execute(self, context):
797             execute_25(self.properties.path, context.scene)
798             return 'FINISHED'
799
800         def invoke(self, context, event):
801             wm = context.manager
802             wm.add_fileselect(self)
803             return 'RUNNING_MODAL'
804
805     # register menu
806     def menu_func(self, context): 
807         self.layout.operator(IMPORT_OT_pmd.bl_idname, 
808                 text="MikuMikuDance model (.pmd)")
809
810     def register():
811         bpy.types.register(IMPORT_OT_pmd)
812         bpy.types.INFO_MT_file_import.append(menu_func)
813
814     def unregister():
815         bpy.types.unregister(IMPORT_OT_pmd)
816         bpy.types.INFO_MT_file_import.remove(menu_func)
817
818     if __name__=="__main__":
819         register()
820