__license__="zlib"\r
__versioon__="0.0.1"\r
\r
+\r
+import io\r
+import os\r
+import struct\r
+\r
+\r
+class Model(object):\r
+ """pmx data holder\r
+\r
+ version: pmx version\r
+ """\r
+ __slots__=[\r
+ 'version', # pmx version\r
+ 'name', # model name\r
+ 'english_name', # model name in english\r
+ 'comment', # model comment\r
+ 'english_comment', # model comment in english\r
+ ]\r
+ def __init__(self):\r
+ self.version=0.0\r
+\r
+\r
+class IO(object):\r
+ """pmx loader\r
+\r
+ Attributes:\r
+ name: model name\r
+ """\r
+ def __init__(self):\r
+ self.__io=None\r
+ self.__pos=-1\r
+ self.__end=-1\r
+ self.__model=Model()\r
+\r
+ def read(self, path: 'filepath') -> Model:\r
+ size=os.path.getsize(path)\r
+ with open(path, "rb") as f:\r
+ if self.load(path, f, size):\r
+ return self.__model\r
+\r
+ def load(self, path: 'filepath', io: io.IOBase, size: int) -> bool: \r
+ self.__io=io\r
+ self.__end=size\r
+ self.__check_position()\r
+\r
+ if not self.__loadHeader():\r
+ return False\r
+ self.__check_position()\r
+ # model info\r
+ self.__model.name = self.__read_text()\r
+ self.__model.english_name = self.__read_text()\r
+ self.__model.comment = self.__read_text()\r
+ self.__model.english_comment = self.__read_text()\r
+ return True\r
+\r
+ def __str__(self) -> str:\r
+ return '<PmxIO>'\r
+\r
+ def __check_position(self):\r
+ self.__pos=self.__io.tell()\r
+\r
+ def __unpack(self, fmt: str, size: int) -> "read value as format":\r
+ return struct.unpack(fmt, self.__io.read(size))[0]\r
+\r
+ def __loadHeader(self) -> bool:\r
+ signature=self.__unpack("4s", 4)\r
+ if signature!=b"PMX ":\r
+ print("invalid signature", signature)\r
+ return False\r
+ version=self.__unpack("f", 4)\r
+ if version!=2.0:\r
+ print("unknown version", version)\r
+ self.__model.version=version\r
+ # flags\r
+ flag_bytes=self.__unpack("B", 1)\r
+ if flag_bytes!=8:\r
+ print("invalid flag length", flag_bytes)\r
+ return False\r
+ # text encoding\r
+ text_encoding=self.__unpack("B", 1)\r
+ if text_encoding==0:\r
+ def read_text():\r
+ size=self.__unpack("I", 4)\r
+ return self.__unpack("{0}s".format(size), size).decode("UTF16")\r
+ elif text_encoding==1:\r
+ def read_text():\r
+ size=self.__unpack("I", 4)\r
+ return self.__unpack("{0}s".format(size), size).decode("UTF8")\r
+ else:\r
+ print("unknown text encoding", text_encoding)\r
+ return False\r
+ self.__read_text=read_text\r
+ self.__unpack("B", 1)\r
+ self.__unpack("B", 1)\r
+ self.__unpack("B", 1)\r
+ self.__unpack("B", 1)\r
+ self.__unpack("B", 1)\r
+ self.__unpack("B", 1)\r
+ self.__unpack("B", 1)\r
+ return True\r
+\r
--- /dev/null
+# coding: utf-8\r
+import pymeshio.pmx\r
+\r
+\r
+PMX_MODEL='resources/初音ミクVer2.pmx'\r
+\r
+def test_load():\r
+ io=pymeshio.pmx.IO()\r
+ model=io.read(PMX_MODEL)\r
+ assert model.__class__==pymeshio.pmx.Model\r
+ assert model.name=='初音ミク'\r
+ assert model.english_name=='Miku Hatsune'\r
+ assert model.comment==(\r
+ "PolyMo用モデルデータ:初音ミク ver.2.3\r\n"+\r
+ "(物理演算対応モデル)\r\n"+\r
+ "\r\n"+\r
+ "モデリング :あにまさ氏\r\n"+\r
+ "データ変換 :あにまさ氏\r\n"+\r
+ "Copyright :CRYPTON FUTURE MEDIA, INC"\r
+ )\r
+ assert model.english_comment==(\r
+ "MMD Model: Miku Hatsune ver.2.3\r\n"+\r
+ "(Physical Model)\r\n"+\r
+ "\r\n"+\r
+ "Modeling by Animasa\r\n"+\r
+ "Converted by Animasa\r\n"+\r
+ "Copyright CRYPTON FUTURE MEDIA, INC"\r
+ )\r
+\r