OSDN Git Service

fix for 2.57b
[meshio/pymeshio.git] / blender25-meshio / pymeshio / pmd.py
index 2c5f072..076fc11 100644 (file)
@@ -1,7 +1,8 @@
 # coding: utf-8
 import os
+import sys
 import struct
-from mmd import *
+from .mmd import *
 
 ###############################################################################
 # PMD
@@ -35,8 +36,11 @@ class Vertex(object):
 class Material(object):
     __slots__=[
             'diffuse', 'shinness', 'specular',
-            'ambient', 'vertex_count', 'texture', 'toon_index', 'flag',
+            'ambient', 'vertex_count', '_texture', 'toon_index', 'flag',
             ]
+    def getTexture(self): return from_str(self._texture)
+    def setTexture(self, texture): self._texture=to_str(texture)
+    texture=property(getTexture, setTexture)
 
     def __init__(self, dr=0, dg=0, db=0, alpha=1, 
             specular=0, sr=0, sg=0, sb=0, ar=0, ag=0, ab=0):
@@ -55,15 +59,12 @@ class Material(object):
                 self.diffuse[2], self.diffuse[3],
                 )
 
-    def getTexture(self): return self.texture.decode('cp932')
-    def setTexture(self, u): self.texture=u
-
 
 # @return 各マテリアルについて、そのマテリアルが保持する面の回数だけ
 # マテリアル自身を返す
 def material_per_face(materials):
     for m in materials:
-        for x in xrange(int(m.vertex_count/3)):
+        for x in range(int(m.vertex_count/3)):
             yield m
 
 
@@ -79,10 +80,17 @@ class Bone(object):
     # since v4.0
     ROLLING=8 # ?
     TWEAK=9
-    __slots__=['name', 'index', 'type', 'parent', 'ik', 'pos',
-            'children', 'english_name', 'ik_index',
+    __slots__=['_name', 'index', 'type', 'parent', 'ik', 'pos',
+            'children', '_english_name', 'ik_index',
             'parent_index', 'tail_index', 'tail',
             ]
+    def getName(self): return from_str(self._name)
+    def setName(self, name): self._name=to_str(name)
+    name=property(getName, setName)
+    def getEnglishName(self): return from_str(self._english_name)
+    def setEnglishName(self, english_name): self._english_name=to_str(english_name)
+    english_name=property(getEnglishName, setEnglishName)
+
     def __init__(self, name='bone', type=0):
         self.name=name
         self.index=0
@@ -96,10 +104,6 @@ class Bone(object):
         self.children=[]
         self.english_name=''
 
-    def getName(self): return self.name.decode('cp932')
-    def setName(self, u): self.name=u
-    def setEnglishName(self, u): self.english_name=u
-
     def hasParent(self):
         return self.parent_index!=0xFFFF
 
@@ -121,7 +125,7 @@ class Bone(object):
             print(uni.encode(ENCODING))
 
         child_count=len(self.children)
-        for i in xrange(child_count):
+        for i in range(child_count):
             child=self.children[i]
             if i<child_count-1:
                 child.display(indent+[False])
@@ -231,9 +235,17 @@ class IK(object):
     def __str__(self):
         return "<IK index: %d, target: %d, iterations: %d, weight: %f, children: %s(%d)>" %(self.index, self.target, self.iterations, self.weight, '-'.join([str(i) for i in self.children]), len(self.children))
 
+
 class Skin(object):
-    __slots__=['name', 'type', 'indices', 'pos_list', 'english_name',
+    __slots__=['_name', 'type', 'indices', 'pos_list', '_english_name',
             'vertex_count']
+    def getName(self): return from_str(self._name)
+    def setName(self, name): self._name=to_str(name)
+    name=property(getName, setName)
+    def getEnglishName(self): return from_str(self._english_name)
+    def setEnglishName(self, english_name): self._english_name=to_str(english_name)
+    english_name=property(getEnglishName, setEnglishName)
+
     def __init__(self, name='skin'):
         self.name=name
         self.type=None
@@ -242,10 +254,6 @@ class Skin(object):
         self.english_name=''
         self.vertex_count=0
 
-    def getName(self): return self.name.decode('cp932')
-    def setName(self, u): self.name=u
-    def setEnglishName(self, u): self.english_name=u
-
     def append(self, index, x, y, z):
         self.indices.append(index)
         self.pos_list.append(Vector3(x, y, z))
@@ -255,40 +263,86 @@ class Skin(object):
             self.name, self.type, len(self.indices))
 
 
-class ToonTexture(object):
-    __slots__=['name']
-    def __init__(self, name): self.name=name
-    def getName(self): return self.name.decode('cp932')
-    def setName(self, u): self.name=u
+class BoneGroup(object):
+    __slots__=['_name', '_english_name']
+    def getName(self): return from_str(self._name)
+    def setName(self, name): self._name=to_str(name)
+    name=property(getName, setName)
+    def getEnglishName(self): return from_str(self._english_name)
+    def setEnglishName(self, english_name): self._english_name=to_str(english_name)
+    english_name=property(getEnglishName, setEnglishName)
 
+    def __init__(self, name='group'): self._name=name; self._english_name='center'
 
-class BoneGroup(object):
-    __slots__=['name', 'english_name']
-    def __init__(self, name='group'): self.name=name; self.english_name='center'
-    def getName(self): return self.name.decode('cp932')
-    def setName(self, u): self.name=u
-    def getEnglishName(self): return self.english_name.decode('cp932')
-    def setEnglishName(self, u): self.english_name=u
+
+SHAPE_SPHERE=0
+SHAPE_BOX=1
+SHAPE_CAPSULE=2
+
+RIGIDBODY_KINEMATICS=0
+RIGIDBODY_PHYSICS=1
+RIGIDBODY_PHYSICS_WITH_BONE=2
 
 
 class RigidBody(object):
-    __slots__=['name', 'boneIndex', 'group', 'target', 'shapeType',
+    __slots__=['_name', 'boneIndex', 'group', 'target', 'shapeType',
             'w', 'h', 'd', 'position', 'rotation', 'weight',
             'linearDamping', 'angularDamping', 'restitution', 'friction', 'processType'
             ]
+    def getName(self): return from_str(self._name)
+    def setName(self, name): self._name=to_str(name)
+    name=property(getName, setName)
+
     def __init__(self, name):
         self.name=name
+        self.position=Vector3()
+        self.rotation=Vector3()
 
 
 class Constraint(object):
+    __slots__=[ '_name', 'rigidA', 'rigidB', 'pos', 'rot',
+            'constraintPosMin', 'constraintPosMax',
+            'constraintRotMin', 'constraintRotMax',
+            'springPos', 'springRot',
+            ]
+    def getName(self): return from_str(self._name)
+    def setName(self, name): self._name=to_str(name)
+    name=property(getName, setName)
+
+    def __init__(self, name):
+        self.name=name
+        self.pos=Vector3()
+        self.rot=Vector3()
+        self.constraintPosMin=Vector3()
+        self.constraintPosMax=Vector3()
+        self.constraintRotMin=Vector3()
+        self.constraintRotMax=Vector3()
+        self.springPos=Vector3()
+        self.springRot=Vector3()
+
+
+class ToonTextures(object):
+    __slots__=['_toon_textures']
     def __init__(self):
-        pass
+        self._toon_textures=[]
+        for i in range(10):
+            self._toon_textures.append('toon%02d.bmp' % (i+1))
+
+    def __getitem__(self, key):
+        return from_str(self._toon_textures[key])
+
+    def __setitem__(self, key, value):
+        self._toon_textures[key]=to_str(value)
+
+    def __iter__(self):
+        for toon_texture in self._toon_textures:
+            yield from_str(toon_texture)
 
 
 class IO(object):
     __slots__=['io', 'end', 'pos',
-            'version', 'name', 'comment',
-            'english_name', 'english_comment',
+            'version', '_name', '_comment',
+            '_english_name', '_english_comment',
             'vertices', 'indices', 'materials', 'bones', 
             'ik_list', 'morph_list',
             'face_list', 'bone_group_list', 'bone_display_list',
@@ -296,46 +350,41 @@ class IO(object):
             'no_parent_bones',
             'rigidbodies', 'constraints',
             ]
+    def getName(self): return from_str(self._name)
+    def setName(self, name): self._name=to_str(name)
+    name=property(getName, setName)
+    def getEnglishName(self): return from_str(self._english_name)
+    def setEnglishName(self, english_name): self._english_name=to_str(english_name)
+    english_name=property(getEnglishName, setEnglishName)
+    def getComment(self): return from_str(self._comment)
+    def setComment(self, comment): self._comment=to_str(comment)
+    comment=property(getComment, setComment)
+    def getEnglishComment(self): return from_str(self._english_comment)
+    def setEnglishComment(self, english_comment): self._english_comment=to_str(english_comment)
+    english_comment=property(getEnglishComment, setEnglishComment)
+
     def __init__(self):
         self.version=1.0
-        self.name=b"default"
-        self.comment=b"default"
-        self.english_name=b'default'
-        self.english_comment=b'default'
+        self.name='default'
+        self.comment='default'
+        self.english_name='default'
+        self.english_comment='default'
         self.vertices=[]
         self.indices=[]
         self.materials=[]
         self.bones=[]
         self.ik_list=[]
         self.morph_list=[]
-
         self.face_list=[]
         self.bone_group_list=[]
         self.bone_display_list=[]
-
-        self.toon_textures=[
-                ToonTexture(b'toon'), ToonTexture(b'toon'),
-                ToonTexture(b'toon'), ToonTexture(b'toon'),
-                ToonTexture(b'toon'), ToonTexture(b'toon'),
-                ToonTexture(b'toon'), ToonTexture(b'toon'),
-                ToonTexture(b'toon'), ToonTexture(b'toon'),
-                ]
-
-        self.no_parent_bones=[]
-
+        # extend
+        self.toon_textures=ToonTextures()
         self.rigidbodies=[]
         self.constraints=[]
+        # innner use
+        self.no_parent_bones=[]
 
-    def getName(self): return self.name.decode('cp932')
-    def setName(self, u): self.name=u
-    def getComment(self): return self.comment.decode('cp932')
-    def setComment(self, u): self.comment=u
-    def getEnglishName(self): return self.english_name.decode('cp932')
-    def setEnglishName(self, u): self.english_name=u
-    def getEnglishComment(self): return self.english_comment.decode('cp932')
-    def setEnglishComment(self, u): self.english_comment=u
-
-    def getToonTexture(self, i): return self.toon_textures[i]
     def each_vertex(self): return self.vertices
     def getUV(self, i): return self.vertices[i].uv
     def addVertex(self): 
@@ -371,17 +420,12 @@ class IO(object):
             len(self.materials), len(self.bones), len(self.ik_list), len(self.morph_list))
 
     def _check_position(self):
-        """
-        if self.pos:
-            print(self.pos, self.io.tell()-self.pos)
-        """
         self.pos=self.io.tell()
-        pass
 
     def read(self, path):
         size=os.path.getsize(path)
-        f=open(path, "rb")
-        return self.load(path, f, size)
+        with open(path, "rb") as f:
+            return self.load(path, f, size)
 
     def load(self, path, io, end):
         self.io=io
@@ -461,7 +505,7 @@ class IO(object):
         if not io:
             return False
         # Header
-        io.write(b"Pmd")        
+        io.write(b"Pmd")
         io.write(struct.pack("f", self.version))
         io.write(struct.pack("20s", self.name))
         io.write(struct.pack("256s", self.comment))
@@ -524,23 +568,68 @@ class IO(object):
             for i, v in zip(s.indices, s.pos_list):
                 io.write(struct.pack("I3f", i, v[0], v[1], v[2]))
 
-        # skin list
+        # skin disp list
         io.write(struct.pack("B", len(self.face_list)))
         for i in self.face_list:
             io.write(struct.pack("H", i))
 
-        # bone name
+        # bone disp list
         io.write(struct.pack("B", len(self.bone_group_list)))
         for g in self.bone_group_list:
             io.write(struct.pack("50s", g.name))
 
-        # bone list
         io.write(struct.pack("I", len(self.bone_display_list)))
         for l in self.bone_display_list:
             io.write(struct.pack("=HB", *l))
 
-        # ToDo
-        # Extend Data
+        ############################################################
+        # extend data
+        ############################################################
+        io.write(struct.pack("B", 1))
+        # english name
+        io.write(struct.pack("=20s", self.english_name))
+        io.write(struct.pack("=256s", self.english_comment))
+        # english bone name
+        for bone in self.bones:
+            io.write(struct.pack("=20s", bone.english_name))
+        # english skin list
+        for skin in self.morph_list:
+            #print(skin.name)
+            if skin.name==b'base':
+                continue
+            io.write(struct.pack("=20s", skin.english_name))
+        # english bone list
+        for bone_group in self.bone_group_list:
+            io.write(struct.pack("50s", bone_group.english_name))
+        # toon texture
+        for toon_texture in self.toon_textures:
+            io.write(struct.pack("=100s", toon_texture))
+        # rigid
+        io.write(struct.pack("I", len(self.rigidbodies)))
+        for r in self.rigidbodies:
+            io.write(struct.pack("=20sHBHB14fB",
+                r.name, r.boneIndex, r.group, r.target, r.shapeType,
+                r.w, r.h, r.d, 
+                r.position.x, r.position.y, r.position.z, 
+                r.rotation.x, r.rotation.y, r.rotation.z, 
+                r.weight,
+                r.linearDamping, r.angularDamping, r.restitution,
+                r.friction, r.processType))
+
+        # constraint
+        io.write(struct.pack("I", len(self.constraints)))
+        for c in self.constraints:
+            io.write(struct.pack("=20sII24f",
+                c.name, c.rigidA, c.rigidB,
+                c.pos.x, c.pos.y, c.pos.z,
+                c.rot.x, c.rot.y, c.rot.z,
+                c.constraintPosMin.x, c.constraintPosMin.y, c.constraintPosMin.z,
+                c.constraintPosMax.x, c.constraintPosMax.y, c.constraintPosMax.z,
+                c.constraintRotMin.x, c.constraintRotMin.y, c.constraintRotMin.z,
+                c.constraintRotMax.x, c.constraintRotMax.y, c.constraintRotMax.z,
+                c.springPos.x, c.springPos.y, c.springPos.z,
+                c.springRot.x, c.springRot.y, c.springRot.z
+                ))
 
         return True
 
@@ -578,7 +667,6 @@ class IO(object):
 
     def _loadHeader(self):
         signature=struct.unpack("3s", self.io.read(3))[0]
-        #print(signature)
         if signature!=b"Pmd":
             print("invalid signature", signature)
             return False
@@ -590,19 +678,19 @@ class IO(object):
 
     def _loadVertex(self):
         count = struct.unpack("I", self.io.read(4))[0]
-        for i in xrange(count):
+        for i in range(count):
             self.vertices.append(Vertex(*struct.unpack("8f2H2B", self.io.read(38))))
         return True
 
     def _loadFace(self):
         count = struct.unpack("I", self.io.read(4))[0]
-        for i in xrange(0, count, 3):
+        for i in range(0, count, 3):
             self.indices+=struct.unpack("HHH", self.io.read(6))
         return True
 
     def _loadMaterial(self):
         count = struct.unpack("I", self.io.read(4))[0]
-        for i in xrange(count):
+        for i in range(count):
             material=Material(*struct.unpack("4ff3f3f", self.io.read(44)))
             material.toon_index=struct.unpack("B", self.io.read(1))[0]
             material.flag=struct.unpack("B", self.io.read(1))[0]
@@ -616,7 +704,7 @@ class IO(object):
 
     def _loadBone(self):
         size = struct.unpack("H", self.io.read(2))[0]
-        for i in xrange(size):
+        for i in range(size):
             name=truncate_zero(struct.unpack("20s", self.io.read(20))[0])
             parent_index, tail_index = struct.unpack("HH", self.io.read(4))
             type = struct.unpack("B", self.io.read(1))[0]
@@ -631,23 +719,23 @@ class IO(object):
 
     def _loadIK(self):
         size = struct.unpack("H", self.io.read(2))[0]
-        for i in xrange(size):
+        for i in range(size):
             ik=IK(*struct.unpack("2H", self.io.read(4)))
             ik.length = struct.unpack("B", self.io.read(1))[0]
             ik.iterations = struct.unpack("H", self.io.read(2))[0]
             ik.weight = struct.unpack("f", self.io.read(4))[0]
-            for j in xrange(ik.length):
+            for j in range(ik.length):
                 ik.children.append(struct.unpack("H", self.io.read(2))[0])
             self.ik_list.append(ik)
         return True
 
     def _loadSkin(self):
         size = struct.unpack("H", self.io.read(2))[0]
-        for i in xrange(size):
+        for i in range(size):
             skin=Skin(truncate_zero(struct.unpack("20s", self.io.read(20))[0]))
             skin_size = struct.unpack("I", self.io.read(4))[0]
             skin.type = struct.unpack("B", self.io.read(1))[0]
-            for j in xrange(skin_size):
+            for j in range(skin_size):
                 skin.indices.append(struct.unpack("I", self.io.read(4))[0])
                 skin.pos_list.append(
                         Vector3(*struct.unpack("3f", self.io.read(12))))
@@ -657,30 +745,31 @@ class IO(object):
 
     def _loadSkinIndex(self):
         size = struct.unpack("B", self.io.read(1))[0]
-        for i in xrange(size):
+        for i in range(size):
             self.face_list.append(struct.unpack("H", self.io.read(2))[0])
         return True
 
     def _loadBoneName(self):
         size = struct.unpack("B", self.io.read(1))[0]
-        for i in xrange(size):
+        for i in range(size):
             self.bone_group_list.append(BoneGroup(
                 truncate_zero(struct.unpack("50s", self.io.read(50))[0])))
         return True
 
     def _loadBoneIndex(self):
         size = struct.unpack("I", self.io.read(4))[0]
-        for i in xrange(size):
-            self.bone_display_list.append(struct.unpack("HB", self.io.read(3)))
+        for i in range(size):
+            first=struct.unpack("H", self.io.read(2))[0]
+            second=struct.unpack("B", self.io.read(1))[0]
+            self.bone_display_list.append((first, second))
         return True
 
     def loadToonTexture(self):
         """
         100bytex10
         """
-        for i in xrange(10):
-            self.toon_textures.append(ToonTexture(
-                    truncate_zero(struct.unpack("100s", self.io.read(100))[0])))
+        for i in range(10):
+            self.toon_textures[i]=truncate_zero(struct.unpack("100s", self.io.read(100))[0])
         return True
 
     def loadEnglishName(self):
@@ -689,42 +778,91 @@ class IO(object):
                 struct.unpack("20s", self.io.read(20))[0])
         self.english_comment=truncate_zero(
                 struct.unpack("256s", self.io.read(256))[0])
-        # english bone list
+        self._check_position()
+        # english bone name
         for bone in self.bones:
             english_name=truncate_zero(
                     struct.unpack("20s", self.io.read(20))[0])
-            if english_name!=bone.name:
-                bone.english_name=english_name
+            bone.english_name=english_name
+        self._check_position()
         # english skin list
-        #for index in self.face_list:
         for skin in self.morph_list:
-            if skin.name=='base':
+            if skin.name==b'base':
                 continue
             english_name=truncate_zero(
                     struct.unpack("20s", self.io.read(20))[0])
             #skin=self.morph_list[index]
             if english_name!=skin.name:
                 skin.english_name=english_name
+        self._check_position()
         # english bone list
-        for i in xrange(0, len(self.bone_group_list)):
+        for i in range(0, len(self.bone_group_list)):
             self.bone_group_list[i].english_name=truncate_zero(
                     struct.unpack("50s", self.io.read(50))[0])
+        self._check_position()
         return True
 
     def loadPhysics(self):
         # 剛体リスト
         count = struct.unpack("I", self.io.read(4))[0]
-        for i in xrange(count):
+        for i in range(count):
             name=truncate_zero(struct.unpack("20s", self.io.read(20))[0])
             rigidbody=RigidBody(name)
-            struct.unpack("63s", self.io.read(63))[0]
+            rigidbody.boneIndex=struct.unpack("H", self.io.read(2))[0]
+            rigidbody.group=struct.unpack("B", self.io.read(1))[0]
+            rigidbody.target=struct.unpack("H", self.io.read(2))[0]
+            rigidbody.shapeType=struct.unpack("B", self.io.read(1))[0]
+            rigidbody.w=struct.unpack("f", self.io.read(4))[0]
+            rigidbody.h=struct.unpack("f", self.io.read(4))[0]
+            rigidbody.d=struct.unpack("f", self.io.read(4))[0]
+            rigidbody.position.x=struct.unpack("f", self.io.read(4))[0]
+            rigidbody.position.y=struct.unpack("f", self.io.read(4))[0]
+            rigidbody.position.z=struct.unpack("f", self.io.read(4))[0]
+            rigidbody.rotation.x=struct.unpack("f", self.io.read(4))[0]
+            rigidbody.rotation.y=struct.unpack("f", self.io.read(4))[0]
+            rigidbody.rotation.z=struct.unpack("f", self.io.read(4))[0]
+            rigidbody.weight=struct.unpack("f", self.io.read(4))[0]
+            rigidbody.linearDamping=struct.unpack("f", self.io.read(4))[0]
+            rigidbody.angularDamping=struct.unpack("f", self.io.read(4))[0]
+            rigidbody.restitution=struct.unpack("f", self.io.read(4))[0]
+            rigidbody.friction=struct.unpack("f", self.io.read(4))[0]
+            rigidbody.processType=struct.unpack("B", self.io.read(1))[0]
             self.rigidbodies.append(rigidbody)
+        self._check_position()
 
         # ジョイントリスト
         count = struct.unpack("I", self.io.read(4))[0]
-        for i in xrange(count):
-            struct.unpack("124s", self.io.read(124))[0]
-            constraint=Constraint()
-            self.constraints.append(Constraint)
+        for i in range(count):
+            name=truncate_zero(struct.unpack("20s", self.io.read(20))[0])
+            constraint=Constraint(name)
+            constraint.rigidA=struct.unpack("I", self.io.read(4))[0]
+            constraint.rigidB=struct.unpack("I", self.io.read(4))[0]
+            constraint.pos.x=struct.unpack("f", self.io.read(4))[0]
+            constraint.pos.y=struct.unpack("f", self.io.read(4))[0]
+            constraint.pos.z=struct.unpack("f", self.io.read(4))[0]
+            constraint.rot.x=struct.unpack("f", self.io.read(4))[0]
+            constraint.rot.y=struct.unpack("f", self.io.read(4))[0]
+            constraint.rot.z=struct.unpack("f", self.io.read(4))[0]
+            constraint.constraintPosMin.x=struct.unpack("f", self.io.read(4))[0]
+            constraint.constraintPosMin.y=struct.unpack("f", self.io.read(4))[0]
+            constraint.constraintPosMin.z=struct.unpack("f", self.io.read(4))[0]
+            constraint.constraintPosMax.x=struct.unpack("f", self.io.read(4))[0]
+            constraint.constraintPosMax.y=struct.unpack("f", self.io.read(4))[0]
+            constraint.constraintPosMax.z=struct.unpack("f", self.io.read(4))[0]
+            constraint.constraintRotMin.x=struct.unpack("f", self.io.read(4))[0]
+            constraint.constraintRotMin.y=struct.unpack("f", self.io.read(4))[0]
+            constraint.constraintRotMin.z=struct.unpack("f", self.io.read(4))[0]
+            constraint.constraintRotMax.x=struct.unpack("f", self.io.read(4))[0]
+            constraint.constraintRotMax.y=struct.unpack("f", self.io.read(4))[0]
+            constraint.constraintRotMax.z=struct.unpack("f", self.io.read(4))[0]
+            constraint.springPos.x=struct.unpack("f", self.io.read(4))[0]
+            constraint.springPos.y=struct.unpack("f", self.io.read(4))[0]
+            constraint.springPos.z=struct.unpack("f", self.io.read(4))[0]
+            constraint.springRot.x=struct.unpack("f", self.io.read(4))[0]
+            constraint.springRot.y=struct.unpack("f", self.io.read(4))[0]
+            constraint.springRot.z=struct.unpack("f", self.io.read(4))[0]
+            self.constraints.append(constraint)
+        self._check_position()
+
         return True