From f2259e5b8ba88f08265f8d74be0efc8f62d6dc93 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 8 Jun 2010 06:06:39 +0900 Subject: [PATCH] add integrate pmd_import. --- swig/blender/Makefile | 2 +- swig/blender/bl24.py | 292 +++++++----- swig/blender/bl25.py | 62 ++- swig/blender/cp.py | 3 +- swig/blender/pmd_import.py | 1127 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 1365 insertions(+), 121 deletions(-) create mode 100644 swig/blender/pmd_import.py diff --git a/swig/blender/Makefile b/swig/blender/Makefile index 1e2dfbb..2793516 100644 --- a/swig/blender/Makefile +++ b/swig/blender/Makefile @@ -1,5 +1,5 @@ all: copy -copy: bl24.py bl25.py mqo_import.py mqo_export.py +copy: bl24.py bl25.py mqo_import.py mqo_export.py pmd_import.py /cygdrive/C/Python26/python cp.py $^ diff --git a/swig/blender/bl24.py b/swig/blender/bl24.py index 0cce8a3..81220e6 100644 --- a/swig/blender/bl24.py +++ b/swig/blender/bl24.py @@ -5,8 +5,8 @@ import Blender from Blender import Mathutils -# $B%U%!%$%k%7%9%F%`$NJ8;z%3!<%I(B -# $B2~B$HG$H$N6&MQ$N$?$a(B +# ファイルシステムの文字コード +# 改造版との共用のため FS_ENCODING=sys.getfilesystemencoding() if os.path.exists(os.path.dirname(sys.argv[0])+"/utf8"): INTERNAL_ENCODING='utf-8' @@ -14,6 +14,9 @@ else: INTERNAL_ENCODING=FS_ENCODING +############################################################################### +# Writer +############################################################################### class Writer(object): def __init__(self, path, encoding): self.io=open(path, "wb") @@ -29,117 +32,36 @@ class Writer(object): self.io.close() -def createEmptyObject(scene, name): - empty=scene.objects.new("Empty") - empty.setName(name) - return empty - - -def createMqoMaterial(m): - material = Blender.Material.New(m.getName().encode(INTERNAL_ENCODING)) - material.mode |= Blender.Material.Modes.SHADELESS - material.rgbCol = [m.color.r, m.color.g, m.color.b] - material.alpha = m.color.a - material.amb = m.ambient - material.spec = m.specular - material.hard = int(255 * m.power) - return material - - -def createTexture(path): - image = Blender.Image.Load(path.encode(INTERNAL_ENCODING)) - texture = Blender.Texture.New(path.encode(INTERNAL_ENCODING)) - texture.type = Blender.Texture.Types.IMAGE - texture.image = image - return texture, image - - -def materialAddTexture(material, texture): - material.mode = material.mode | Blender.Material.Modes.TEXFACE - material.setTexture(0, texture, Blender.Texture.TexCo.UV) - - -def createMesh(scene, name): - mesh = Blender.Mesh.New() - mesh_object=scene.objects.new(mesh, name.encode(INTERNAL_ENCODING)) - return mesh, mesh_object - - -def objectMakeParent(parent, child): - parent.makeParent([child]) - - -def meshAddMqoGeometry(mesh, o, materials, imageMap, scale): - # add vertices - mesh.verts.extend(Mathutils.Vector(0, 0, 0)) # dummy - mesh.verts.extend([(v.x, -v.z, v.y) for v in o.vertices]) - # add faces - mesh_faces=[] - for face in o.faces: - face_indices=[] - for i in xrange(face.index_count): - face_indices.append(face.getIndex(i)+1) - mesh_faces.append(face_indices) - #new_faces=mesh.faces.extend([face.indices for face in o.faces], - new_faces=mesh.faces.extend(mesh_faces, - #ignoreDups=True, - indexList=True) - mesh.update() - - # gather used materials - materialMap = {} - if new_faces: - for i in new_faces: - if type(i) is int: - materialMap[o.faces[i].material_index]=True - - # blender limits 16 materials per mesh - # separate mesh ? - for i, material_index in enumerate(materialMap.keys()): - if i>=16: - print("over 16 materials!") - break - mesh.materials+=[materials[material_index]] - materialMap[material_index]=i - - # set face params - for i, f in enumerate(o.faces): - if not type(new_faces[i]) is int: - continue - - face=mesh.faces[new_faces[i]] - - uv_array=[] - for i in xrange(f.index_count): - uv_array.append(Blender.Mathutils.Vector( - f.getUV(i).x, - 1.0-f.getUV(i).y) - ) - try: - face.uv=uv_array - except Exception as msg: - #print msg - #print face.index, uv_array - pass - - if f.material_index in materialMap: - face.mat = materialMap[f.material_index] - - face.smooth = 1 - - # rmeove dummy 0 vertex - mesh.verts.delete(0) - - mesh.mode |= Blender.Mesh.Modes.AUTOSMOOTH - mesh.maxSmoothAngle = int(o.smoothing) - mesh.smooth() - mesh.calcNormals() - mesh.flipNormals() - mesh.update() +############################################################################### +# ProgressBar +############################################################################### +class ProgressBar(object): + def __init__(self, base): + print "#### %s ####" % base + self.base=base + self.start=Blender.sys.time() + self.set('', 0) + + def advance(self, message, progress): + self.progress+=float(progress) + self._print(message) + + def set(self, message, progress): + self.progress=float(progress) + self._print(message) + + def _print(self, message): + print message + message="%s: %s" % (self.base, message) + if message.__class__ is unicode: + message=message.encode(FS_ENCODING) + Blender.Window.DrawProgressBar(self.progress, message) + + def finish(self): + self.progress=1.0 + message='finished in %.2f sec' % (Blender.sys.time()-self.start) + self.set(message, 1.0) - # mirror modifier - if o.mirror: - mod=mesh_object.modifiers.append(Blender.Modifier.Types.MIRROR) ############################################################################### # for mqo mikoto bone. @@ -345,8 +267,8 @@ def create_armature(scene, mqo): class TrianglePlane(object): """ - mikoto$BJ}<0%\!<%s$N%"%s%+!<%&%'%$%H7W;;MQ!#(B - ($BIT40A4(B) + mikoto方式ボーンのアンカーウェイト計算用。 + (不完全) """ __slots__=['normal', 'v0', 'v1', 'v2', @@ -404,7 +326,7 @@ class TrianglePlane(object): class MikotoAnchor(object): """ - mikoto$BJ}<0%9%1%k%H%s$N%"%s%+!=16: + print("over 16 materials!") + break + mesh.materials+=[materials[material_index]] + materialMap[material_index]=i + + # set face params + for i, f in enumerate(o.faces): + if not type(new_faces[i]) is int: + continue + + face=mesh.faces[new_faces[i]] + + uv_array=[] + for i in xrange(f.index_count): + uv_array.append(Blender.Mathutils.Vector( + f.getUV(i).x, + 1.0-f.getUV(i).y) + ) + try: + face.uv=uv_array + except Exception as msg: + #print msg + #print face.index, uv_array + pass + + if f.material_index in materialMap: + face.mat = materialMap[f.material_index] + + face.smooth = 1 + + # rmeove dummy 0 vertex + mesh.verts.delete(0) + + mesh.mode |= Blender.Mesh.Modes.AUTOSMOOTH + mesh.maxSmoothAngle = int(o.smoothing) + mesh.smooth() + mesh.calcNormals() + mesh.flipNormals() + mesh.update() + + # mirror modifier + if o.mirror: + mod=mesh_object.modifiers.append(Blender.Modifier.Types.MIRROR) + def getTexture(m, dirname): tex="" aplane="" @@ -538,7 +572,7 @@ def getTexture(m, dirname): continue imagePath=Blender.sys.expandpath(image.getFilename()) if len(dirname)>0 and imagePath.startswith(dirname): - # $BAjBP%Q%9$KJQ49$9$k(B + # 相対パスに変換する imagePath=imagePath[len(dirname)+1:len(imagePath)] if texture.mtCol>0: tex=" tex(\"%s\")" % imagePath @@ -578,3 +612,29 @@ def materialToMqo(m): def faceMaterialIndex(face): return face.mat +def objectGetData(o): + return o.getData(mesh=True) + +def objectAddArmatureModifier(o, armature_object): + mod=o.modifiers.append(Blender.Modifier.Types.ARMATURE) + mod[Blender.Modifier.Settings.OBJECT] = armature_object + mod[Blender.Modifier.Settings.ENVELOPES] = False + +def objectSelect(o): + o.select(True) + +def objectGetPose(o): + return o.getPose() + +def poseBoneLimit(n, b): + if n.endswith("_t"): + return + if n.startswith("knee_"): + b.lockYRot=True + b.lockZRot=True + b.limitX=True + b.limitMin=[0, 0, 0] + b.limitMax=[180, 0, 0] + elif n.startswith("ankle_"): + b.lockYRot=True + diff --git a/swig/blender/bl25.py b/swig/blender/bl25.py index 27ff977..92144c0 100644 --- a/swig/blender/bl25.py +++ b/swig/blender/bl25.py @@ -1,7 +1,38 @@ +# coding: utf-8 import bpy import os - - +import time + +############################################################################### +# ProgressBar +############################################################################### +class ProgressBar(object): + def __init__(self, base): + print("#### %s ####" % base) + self.base=base + self.start=time.time() + self.set('', 0) + + def advance(self, message, progress): + self.progress+=float(progress) + self._print(message) + + def set(self, message, progress): + self.progress=float(progress) + self._print(message) + + def _print(self, message): + print(message) + message="%s: %s" % (self.base, message) + #Blender.Window.DrawProgressBar(self.progress, message) + + def finish(self): + self.progress=1.0 + message='finished in %.2f sec' % (time.time()-self.start) + self.set(message, 1.0) + + +############################################################################### class Writer(object): def __init__(self, path, encoding): self.io=open(path, "wb") @@ -16,7 +47,7 @@ class Writer(object): def close(self): self.io.close() - +############################################################################### def createEmptyObject(scene, name): empty=bpy.data.objects.new(name, None) scene.objects.link(empty) @@ -206,3 +237,28 @@ def materialToMqo(m): def faceMaterialIndex(face): return face.material_index +def objectGetData(o): + return o.data + +def objectAddArmatureModifier(o, armature_object): + mod=o.modifiers.new("Modifier", "ARMATURE") + mod.object = armature_object + mod.use_bone_envelopes=False + +def objectSelect(o): + o.selected=True + +def objectGetPose(o): + return o.pose + +def poseBoneLimit(n, b): + if n.endswith("_t"): + return + if n.startswith("knee_"): + b.lock_rotation[1]=True + b.lock_rotation[2]=True + b.ik_min_x=0 + b.ik_max_x=180 + elif n.startswith("ankle_"): + b.lock_rotation[1]=True + diff --git a/swig/blender/cp.py b/swig/blender/cp.py index 10fd049..2c49f92 100644 --- a/swig/blender/cp.py +++ b/swig/blender/cp.py @@ -7,9 +7,10 @@ DST_24=[ ] MAP_25={ + "bl25.py": "bl25.py", "mqo_import.py": "import_scene_mqo.py", "mqo_export.py": "export_scene_mqo.py", - "bl25.py": "bl25.py", + "pmd_import.py": "import_scene_pmd.py", } DST_25=[ diff --git a/swig/blender/pmd_import.py b/swig/blender/pmd_import.py new file mode 100644 index 0000000..3f7220a --- /dev/null +++ b/swig/blender/pmd_import.py @@ -0,0 +1,1127 @@ +#!BPY +# coding:utf-8 +""" + Name: 'MikuMikuDance model (.pmd)...' + Blender: 248 + Group: 'Import' + Tooltip: 'Import PMD file for MikuMikuDance.' +""" +__author__= ["ousttrue"] +__version__= "1.1" +__url__=() +__bpydoc__=""" +pmd Importer + +This script imports a pmd into Blender for editing. + +0.1: 20091126: first implement. +0.2: 20091209: implement IK. +0.3: 20091210: implement morph target. +0.4: 20100305: use english name. +0.5: 20100408: cleanup not used vertices. +0.6: 20100416: fix fornt face. texture load fail safe. add progress. +0.7: 20100506: C extension. +0.8: 20100521: add shape_key group. +1.0: 20100530: add invisilbe bone tail(armature layer 2). +1.1: 20100608: integrate 2.4 and 2.5. +""" + +MMD_SHAPE_GROUP_NAME='_MMD_SHAPE' + + +############################################################################### +# import +############################################################################### +import os +import sys +import re +import math + +# C extension +from meshio import pmd, englishmap + +def isBlender24(): + return sys.version_info[0]<3 + +if isBlender24(): + # for 2.4 + import Blender + from Blender import Mathutils + import bpy + + # wrapper + import bl24 as bl +else: + # for 2.5 + import bpy + from bpy.props import * + import mathutils + + # wrapper + import bl25 as bl + + +############################################################################### +# progress bar +############################################################################### +def progress_start(base): + global progressBar + progressBar=bl.ProgressBar(base) + +def progress_finish(): + global progressBar + progressBar.finish() + +def progress_print(message, progress=0.05): + global progressBar + progressBar.advance(message, progress) + +def progress_set(message, progress): + global progressBar + progressBar.set(message, progress) + + +if isBlender24(): + # functions + def convert_coord(pos): + """ + Left handed y-up to Right handed z-up + """ + return (pos.x, pos.z, pos.y) + + + def convert_uv(uv): + return (uv.x, 1.0 - uv.y) + + + def get_bone_name(l, index): + name=englishmap.getEnglishBoneName(l.bones[index].getName()) + return name if name else l.bones[index].getName().encode(bl.INTERNAL_ENCODING) + + + def createMaterial(): + """ + create default materil + """ + material=Blender.Material.New() + material.setDiffuseShader(Blender.Material.Shaders.DIFFUSE_TOON) + material.setRef(1) + material.diffuseSize = 3.14/2 + material.setDiffuseSmooth(0) + material.setSpecShader(Blender.Material.Shaders.SPEC_TOON) + material.setSpecSize(0) + material.setSpec(0) + return material + + + def importMesh(scene, l, tex_dir): + """ + @param l[in] mmd.PMDLoader + @param filename[in] + """ + + ############################################################ + # shpaeキーで使われるマテリアル優先的に前に並べる + ############################################################ + # shapeキーで使われる頂点インデックスを集める + shape_key_used_vertices=set() + if len(l.morph_list)>0: + # base + base=None + for s in l.morph_list: + if s.type!=0: + continue + base=s + break + assert(base) + + for index in base.indices: + shape_key_used_vertices.add(index) + + # マテリアルに含まれる頂点がshape_keyに含まれるか否か? + def isMaterialUsedInShape(offset, m): + for i in xrange(offset, offset+m.vertex_count): + if l.indices[i] in shape_key_used_vertices: + return True + + # shapeキーで使われるマテリアルを記録する + shape_key_materials=set() + # 各マテリアルの開始頂点インデックスを記録する + face_map={} + face_count=0 + for i, m in enumerate(l.materials): + face_map[i]=face_count + if isMaterialUsedInShape(face_count, m): + shape_key_materials.add(i) + face_count+=m.vertex_count + + # list化 + material_order=list(shape_key_materials) + + # shapeキーに使われていないマテリアルを後ろに追加 + for i in range(len(l.materials)): + if not i in material_order: + material_order.append(i) + + # マテリアル16個ごとに分割したメッシュを作成する + material_offset=0 + mesh_objects=[] + while material_offsetparent(=IK).name + target=l.bones[ik.target] + name = englishmap.getEnglishBoneName(target.getName()) + p_bone = pose.bones[name] + if not p_bone: + print('not found', name) + continue + if len(ik.children) >= 16: + print('over MAX_CHAINLEN', ik, len(ik.children)) + continue + # IK solver + ik_solver = p_bone.constraints.append(Blender.Constraint.Type.IKSOLVER) + ik_solver[cSetting.CHAINLEN]=len(ik.children) + ik_solver[cSetting.TARGET]=armature_object + ik_solver[cSetting.USETIP]=False + + effector_name=englishmap.getEnglishBoneName( + l.bones[ik.index].getName()) + if not effector_name: + effector_name=l.bones[ik.index].getName() + + ik_solver[cSetting.BONE]=effector_name + #ik_solver.influence=ik.weight + # not used. place folder when export. + ik_solver[cSetting.ROTWEIGHT]=ik.weight + ik_solver[cSetting.ITERATIONS]=ik.iterations * 10 + + armature.makeEditable() + armature.update() + + return armature_object + + + def importShape(obj, l, vertex_map): + if len(l.morph_list)==0: + return + obj.pinShape=True + mesh=obj.getData(mesh=True) + + # find base + base=None + for s in l.morph_list: + if s.type==0: + base=s + + # create vertex group + mesh.addVertGroup(MMD_SHAPE_GROUP_NAME) + indices=[] + hasShape=False + for i in s.indices: + if i in vertex_map: + hasShape=True + indices.append(vertex_map[i]) + mesh.assignVertsToGroup(MMD_SHAPE_GROUP_NAME, indices, 0, + Blender.Mesh.AssignModes.ADD) + if not hasShape: + return + + # create base key + mesh.insertKey() + assert(len(mesh.key.blocks)==1) + baseShapeIndex=0 + baseShapeBlock=mesh.key.blocks[baseShapeIndex] + baseShapeBlock.name='Basis' + obj.activeShape=baseShapeIndex + mesh.update() + break + + assert(base) + + # each skin + for s in l.morph_list: + if s.name==base.name: + continue + + for index, offset in zip(s.indices, s.pos_list): + try: + vertex_index=vertex_map[base.indices[index]] + v=mesh.verts[vertex_index].co + offset=convert_coord(offset) + v[0]+=offset[0] + v[1]+=offset[1] + v[2]+=offset[2] + except IndexErrora as msg: + print(msg) + print(index, len(base.indices), len(vertex_map)) + print(len(mesh.verts)) + print(base.indices[index]) + print(vertex_index) + break + except KeyError: + #print 'this mesh not has shape vertices' + break + + # get skin name + name=englishmap.getEnglishSkinName(s.getName()) + if not name: + name=s.getName().encode(bl.INTERNAL_ENCODING) + print(name) + + # create shapekey block + mesh.insertKey() + shapeIndex=len(mesh.key.blocks)-1 + keyBlock=mesh.key.blocks[shapeIndex] + keyBlock.name=name + + # copy vertex to shape key + mesh.update() + + # restore + for mv, v in zip(mesh.verts, baseShapeBlock.getData()): + mv.co[0] = v[0] + mv.co[1] = v[1] + mv.co[2] = v[2] + mesh.update() + + # select base shape + obj.activeShape=baseShapeIndex + +else: + # for 2.5 + def to_radian(degree): + return math.pi * degree / 180 + + + def convert_coord(pos): + """ + Left handed y-up to Right handed z-up + """ + return (pos.x, pos.z, pos.y) + + + def convert_uv(uv): + return (uv.x, 1.0 - uv.y) + + + def getBoneName(bone): + name = englishmap.getEnglishBoneName(bone.getName()) + return name if name else bone.getName() + + + def create_texture(directory, texture_name): + texture=bpy.data.textures.new(texture_name) + texture.type='IMAGE' + texture=texture.recast_type() + texturePath=os.path.join(directory, texture_name) + print('create_texture', texturePath) + image=bpy.data.images.load(texturePath) + texture.image=image + texture.mipmap = True + texture.interpolation = True + texture.use_alpha = True + return texture + + + def createMaterial(): + """ + create default materil + """ + material = bpy.data.materials.new("Material") + material.diffuse_shader='TOON' + material.specular_shader='TOON' + # temporary + material.emit=1.0 + return material + + + def importMesh(scene, l, tex_dir): + """ + @param l[in] mmd.PMDLoader + @param filename[in] + """ + + ############################################################ + # shpaeキーで使われるマテリアル優先的に前に並べる + ############################################################ + # shapeキーで使われる頂点インデックスを集める + shape_key_used_vertices=set() + if len(l.morph_list)>0: + # base + base=None + for s in l.morph_list: + if s.type!=0: + continue + base=s + break + assert(base) + + for index in base.indices: + shape_key_used_vertices.add(index) + + # マテリアルに含まれる頂点がshape_keyに含まれるか否か? + def isMaterialUsedInShape(offset, m): + for i in range(offset, offset+m.vertex_count): + if l.indices[i] in shape_key_used_vertices: + return True + + # shapeキーで使われるマテリアルを記録する + shape_key_materials=set() + # 各マテリアルの開始頂点インデックスを記録する + face_map={} + face_count=0 + for i, m in enumerate(l.materials): + face_map[i]=face_count + if isMaterialUsedInShape(face_count, m): + shape_key_materials.add(i) + face_count+=m.vertex_count + + # shapeキーで使われるマテリアルを前に並べるインデックスマップを作る + material_map={} + used_index=0 + not_used_index=len(shape_key_materials) + for i, m in enumerate(l.materials): + if i in shape_key_materials: + material_map[i]=used_index + used_index+=1 + else: + material_map[i]=not_used_index + not_used_index+=1 + + # マテリアル16個ごとに分割したメッシュを作成する + material_index=0 + mesh_objects=[] + while material_index= 16: + print('over MAX_CHAINLEN', ik, len(ik.children)) + continue + # IK + ik_const = p_bone.constraints.new('IK') + ik_const.chain_length=len(ik.children) + ik_const.target=armature_object + ik_const.subtarget=getBoneName(l.bones[ik.index]) + # ROT + rot_const = p_bone.constraints.new('LIMIT_ROTATION') + rot_const.influence = ik.weight + rot_const.owner_space = 'LOCAL' + rot_const.use_limit_x=True + rot_const.use_limit_z=True + rot_const.minimum_x=to_radian(ik.iterations) + rot_const.maximum_x=to_radian(180) + rot_const.minimum_z=to_radian(180 - ik.iterations) + rot_const.maximum_z=to_radian(0) + + return armature_object + + + def importShape(meshObject, l): + if len(l.morph_list)==0: + return + + # base + base=None + for s in l.morph_list: + if s.type!=0: + continue + base=s + break + assert(base) + + # create base key + baseblock=meshObject.add_shape_key("Basis") + + # mesh + mesh=meshObject.data + + # each skin + for s in l.morph_list: + if s.getName()==base.name: + # skip base + continue + + # restore + #for v, base_pos in zip(mesh.verts, baseblock.data): + # v.co=base_pos.co + #mesh.update() + + # name + name=englishmap.getEnglishSkinName(s.getName()) + if not name: + name=s.getName() + new_shape_key=meshObject.add_shape_key(name) + #new_shape_key.value=1.0 + + # morph + for i, offset in zip(s.indices, s.pos_list): + try: + vertex_index=base.indices[i] + new_shape_key.data[vertex_index].co=[p+o for p, o in zip( + mesh.verts[vertex_index].co, convert_coord(offset))] + except IndexError as msg: + print(IndexError, msg) + print(i, len(base.indices)) + print(vertex_index, len(mesh.verts)) + print(base.indices[i]) + break + except KeyError: + #print 'this mesh not has shape vertices' + break + + # set ipo curve + #icu=ipo.addCurve(name) + #icu.interpolation = Blender.IpoCurve.InterpTypes.LINEAR + #icu.append( (0.0, 0.0) ) + + +def __execute(filename, scene): + """ + load pmd file to context. + """ + # load pmd + progress_set('load %s' % filename, 0.0) + + io=pmd.IO() + if not io.read(filename): + print("fail to load %s" % filename) + return + progress_set('loaded %s' % filename, 0.1) + + # create root object + root=bl.createEmptyObject(scene, + io.english_name if len(io.english_name)>0 else io.getName().encode(bl.INTERNAL_ENCODING)) + + # import mesh + mesh_objects=importMesh(scene, io, os.path.dirname(filename)) + for o in mesh_objects: + bl.objectMakeParent(root, o) + + # import armature + armature_object=importArmature(scene, io) + if armature_object: + bl.objectMakeParent(root, armature_object) + armature = bl.objectGetData(armature_object) + + # add armature modifier + for o in mesh_objects: + bl.objectAddArmatureModifier(o, armature_object) + + # Limitation + for n, b in bl.objectGetPose(armature_object).bones.items(): + bl.poseBoneLimit(n, b) + + # select objects + bl.objectSelect(root) + for o in mesh_objects: + bl.objectSelect(o) + bl.objectSelect(armature_object) + + +if isBlender24(): + # for 2.4 + def execute_24(filename): + """ + @param filename + """ + filename=filename.decode(bl.INTERNAL_ENCODING) + print(bl.INTERNAL_ENCODING, bl.FS_ENCODING) + + # set object mode + mode_edit = Blender.Window.EditMode() + if mode_edit: + Blender.Window.EditMode(0) + + progress_start('pmd_import') + scene = bpy.data.scenes.active + __execute(filename, scene) + scene.update(0) + progress_finish() + + # restore edit mode + if mode_edit: + Blender.Window.EditMode(1) + Blender.Window.RedrawAll() + + Blender.Window.FileSelector( + execute_24, + 'Import PMD file', + Blender.sys.makename(ext='.pmd')) + +else: + # for 2.5 + def execute_25(*args): + progress_start('pmd_import') + __execute(*args) + progress_finish() + + # import operator + class IMPORT_OT_pmd(bpy.types.Operator): + bl_idname = "import_scene.pmd" + bl_label = 'Import PMD' + + # List of operator properties, the attributes will be assigned + # to the class instance from the operator settings before calling. + + path = StringProperty( + name="File Path", + description="File path used for importing the PMD file", + maxlen= 1024, default= "") + filename = StringProperty( + name="File Name", + description="Name of the file.") + directory = StringProperty( + name="Directory", + description="Directory of the file.") + + def execute(self, context): + execute_25(self.properties.path, context.scene) + return 'FINISHED' + + def invoke(self, context, event): + wm = context.manager + wm.add_fileselect(self) + return 'RUNNING_MODAL' + + # register menu + def menu_func(self, context): + self.layout.operator(IMPORT_OT_pmd.bl_idname, + text="MikuMikuDance model (.pmd)") + + def register(): + bpy.types.register(IMPORT_OT_pmd) + bpy.types.INFO_MT_file_import.append(menu_func) + + def unregister(): + bpy.types.unregister(IMPORT_OT_pmd) + bpy.types.INFO_MT_file_import.remove(menu_func) + + if __name__=="__main__": + register() + -- 2.11.0