OSDN Git Service

add pymeshio.
[meshio/meshio.git] / swig / blender / pmd_import.py
index 51309d0..5ef212f 100755 (executable)
@@ -7,7 +7,7 @@
  Tooltip: 'Import PMD file for MikuMikuDance.'
 """
 __author__= ["ousttrue"]
-__version__= "1.8"
+__version__= "2.0"
 __url__=()
 __bpydoc__="""
 pmd Importer
@@ -31,10 +31,28 @@ This script imports a pmd into Blender for editing.
 1.6 20100629: sphere map.
 1.7 20100703: implement bone group.
 1.8 20100710: implement toon texture.
+1.9 20100718: keep model name, comment.
+2.0 20100724: update for Blender2.53.
+2.1 20100731: add full python module.
 """
+bl_addon_info = {
+        'category': 'Import/Export',
+        'name': 'Import: MikuMikuDance Model Format (.pmd)',
+        'author': 'ousttrue',
+        'version': '2.0',
+        'blender': (2, 5, 3),
+        'location': 'File > Import',
+        'description': 'Import from the MikuMikuDance Model Format (.pmd)',
+        'warning': '', # used for warning icon and text in addons panel
+        'wiki_url': 'http://sourceforge.jp/projects/meshio/wiki/FrontPage',
+        }
 
 MMD_SHAPE_GROUP_NAME='_MMD_SHAPE'
+MMD_MB_NAME='mb_name'
+MMD_MB_COMMENT='mb_comment'
+MMD_COMMENT='comment'
 BASE_SHAPE_NAME='Basis'
+RIGID_NAME='rigid_name'
 RIGID_SHAPE_TYPE='rigid_shape_type'
 RIGID_PROCESS_TYPE='rigid_process_type'
 RIGID_BONE_NAME='rigid_bone_name'
@@ -55,6 +73,7 @@ CONSTRAINT_ROT_MIN='const_rot_min'
 CONSTRAINT_ROT_MAX='const_rot_max'
 CONSTRAINT_SPRING_POS='const_spring_pos'
 CONSTRAINT_SPRING_ROT='const_spring_rot'
+TOON_TEXTURE_OBJECT='ToonTextures'
 
 
 ###############################################################################
@@ -64,8 +83,14 @@ import os
 import sys
 import math
 
-# C extension
-from meshio import pmd, englishmap
+try:
+    # C extension
+    from meshio import pmd, englishmap
+except ImportError:
+    # full python
+    from pymeshio import englishmap
+    from pymeshio import mmd as pmd
+    pmd.IO=pmd.PMDLoader
 
 def isBlender24():
     return sys.version_info[0]<3
@@ -81,13 +106,7 @@ if isBlender24():
 
     def createPmdMaterial(m, index):
         material=Blender.Material.New()
-        #material.setRef(1)
-        #material.diffuseSize = 3.14/2
-        #material.setDiffuseSmooth(0)
-        #material.setSpecSize(0)
-        #material.setSpec(0)
-        # shader
-        # diffuse
+        # fresnelが無いw
         material.setDiffuseShader(Blender.Material.Shaders.DIFFUSE_TOON)
         material.setRGBCol([m.diffuse.r, m.diffuse.g, m.diffuse.b])
         material.setAlpha(m.diffuse.a)
@@ -115,13 +134,18 @@ if isBlender24():
         elif n.startswith("ankle_"):
             b.lockYRot=True
 
-    def setSphereMap(material, index, blende_type=None):
-        pass
+    def setSphereMap(material, index, blend_type='MULTIPLY'):
+        slot=material.textures[index]
+        slot.mapto=Blender.Texture.MapTo.NOR
+        slot.mapping=Blender.Texture.Mappings.SPHERE
+        if blend_type=='MULTIPLY':
+            slot.blendmode=Blender.Texture.BlendModes.MULTIPLY
+        elif blend_type=='ADD':
+            slot.blendmode=Blender.Texture.BlendModes.ADD
 
 else:
     # for 2.5
     import bpy
-    from bpy.props import *
     import mathutils
 
     # wrapper
@@ -163,12 +187,11 @@ else:
             #b.ik_dof_y=False
             pass
 
-    def setSphereMap(material, index, blend_type=None):
+    def setSphereMap(material, index, blend_type='MULTIPLY'):
         slot=material.texture_slots[index]
-        slot.texture_coordinates='REFLECTION'
+        slot.texture_coordinates='NORMAL'
         slot.mapping='SPHERE'
-        if blend_type:
-            slot.blend_type=blend_type
+        slot.blend_type=blend_type
 
 
 ###############################################################################
@@ -200,9 +223,16 @@ def get_bone_name(l, index):
     return l.bones[0].getName()
 
 
+def get_group_name(g):
+    group_name=englishmap.getEnglishBoneGroupName(g.getName().strip())
+    if not group_name:
+        group_name=g.getName().strip()
+    return group_name
+
+
 def __importToonTextures(io, tex_dir):
-    mesh, meshObject=bl.mesh.create('ToonTextures')
-    material=bl.material.create('ToonTextures')
+    mesh, meshObject=bl.mesh.create(TOON_TEXTURE_OBJECT)
+    material=bl.material.create(TOON_TEXTURE_OBJECT)
     bl.mesh.addMaterial(mesh, material)
     for i in range(10):
         t=io.getToonTexture(i)
@@ -320,6 +350,7 @@ def __build(armature, b, p, parent):
     bone=bl.armature.createBone(armature, name)
 
     if parent and (b.tail_index==0 or b.type==6 or b.type==7 or b.type==9):
+        # 先端ボーン
         bone.head = bl.createVector(*convert_coord(b.pos))
         bone.tail=bone.head+bl.createVector(0, 1, 0)
         bone.parent=parent
@@ -396,9 +427,7 @@ def __importArmature(l):
     else:
         # create bone group
         for i, g in enumerate(l.bone_group_list):
-            name=englishmap.getEnglishBoneGroupName(g.getName().strip())
-            if not name:
-                name=g.getName()
+            name=get_group_name(g)
             bl.object.createBoneGroup(armature_object, name, "THEME%02d" % (i+1))
 
         # assign bone to group
@@ -410,9 +439,7 @@ def __importArmature(l):
                 bone_name=b.getName()
             # group
             g=l.bone_group_list[g_index-1]
-            group_name=englishmap.getEnglishBoneGroupName(g.getName().strip())
-            if not group_name:
-                group_name=g.getName()
+            group_name=get_group_name(g)
 
             # assign
             pose.bones[bone_name].bone_group=pose.bone_groups[group_name]
@@ -443,11 +470,8 @@ def __import16MaerialAndMesh(meshObject, l,
             break
 
         material=createPmdMaterial(m, material_index)
-        toon_index=bl.material.addTexture(
-                material, 
-                bl.material.getTexture(toon_material, m.toon_index).texture,
-                False)
 
+        # main texture
         texture_name=m.getTexture()
         if texture_name!='':
             for i, t in enumerate(texture_name.split('*')):
@@ -458,15 +482,25 @@ def __import16MaerialAndMesh(meshObject, l,
                     texture, image=bl.texture.create(path)
                     textureMap[texture_name]=texture
                     imageMap[material_index]=image
-                bl.material.addTexture(material, texture)
+                texture_index=bl.material.addTexture(material, texture)
                 if t.endswith('sph'):
                     # sphere map
-                    setSphereMap(material, i)
+                    setSphereMap(material, texture_index)
                 elif t.endswith('spa'):
                     # sphere map
-                    setSphereMap(material, i, 'ADD')
+                    setSphereMap(material, texture_index, 'ADD')
+
+        # toon texture
+        toon_index=bl.material.addTexture(
+                material, 
+                bl.material.getTexture(
+                    toon_material, 
+                    0 if m.toon_index==0xFF else m.toon_index
+                    ),
+                False)
 
         bl.mesh.addMaterial(mesh, material)
+
         index+=1
 
     ############################################################
@@ -675,10 +709,8 @@ def __importConstraints(io):
     print("create constraint")
     container=bl.object.createEmpty('Constraints')
     layer=[
-            True, False, False, False, False, False, False, False,
-            False, False, False, False, False, False, False, False,
-            False, False, False, False, False, False, False, False,
-            False, False, False, False, False, False, False, False,
+        True, False, False, False, False, False, False, False, False, False,
+        False, False, False, False, False, False, False, False, False, False,
             ]
     material=bl.material.create('constraint')
     material.diffuse_color=(1, 0, 0)
@@ -725,14 +757,12 @@ def __importRigidBodies(io):
 
     container=bl.object.createEmpty('RigidBodies')
     layer=[
-            True, False, False, False, False, False, False, False,
-            False, False, False, False, False, False, False, False,
-            False, False, False, False, False, False, False, False,
-            False, False, False, False, False, False, False, False,
+        True, False, False, False, False, False, False, False, False, False,
+        False, False, False, False, False, False, False, False, False, False,
             ]
     material=bl.material.create('rigidBody')
     rigidMeshes=[]
-    for rigid in io.rigidbodies:
+    for i, rigid in enumerate(io.rigidbodies):
         if rigid.boneIndex==0xFFFF:
             # no reference bone
             bone=io.bones[0]
@@ -768,7 +798,8 @@ def __importRigidBodies(io):
         mesh=bl.object.getData(meshObject)
         rigidMeshes.append(meshObject)
         bl.mesh.addMaterial(mesh, material)
-        meshObject.name=rigid.getName()
+        meshObject.name='r_%d' % i
+        meshObject[RIGID_NAME]=rigid.getName()
         #meshObject.draw_transparent=True
         #meshObject.draw_wire=True
         meshObject.max_draw_type='WIRE'
@@ -817,6 +848,9 @@ def _execute(filename):
     if len(model_name)==0:
         model_name=io.getName()
     root=bl.object.createEmpty(model_name)
+    root[MMD_MB_NAME]=io.getName()
+    root[MMD_MB_COMMENT]=io.getComment()
+    root[MMD_COMMENT]=io.getEnglishComment()
 
     # toon textures
     tex_dir=os.path.dirname(filename)
@@ -875,21 +909,13 @@ else:
 
         # 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.")
+        filepath = bpy.props.StringProperty()
+        filename = bpy.props.StringProperty()
+        directory = bpy.props.StringProperty()
 
         def execute(self, context):
             bl.initialize('pmd_import', context.scene)
-            _execute(self.properties.path)
+            _execute(self.properties.filepath)
             bl.finalize()
             return 'FINISHED'
 
@@ -901,7 +927,9 @@ else:
     # register menu
     def menu_func(self, context): 
         self.layout.operator(IMPORT_OT_pmd.bl_idname, 
-                text="MikuMikuDance model (.pmd)")
+                text="MikuMikuDance model (.pmd)",
+                icon='PLUGIN'
+                )
 
     def register():
         bpy.types.register(IMPORT_OT_pmd)