OSDN Git Service

implement converter
[meshio/pymeshio.git] / pymeshio / pmx / __init__.py
1 #!/usr/bin/env python\r
2 # coding: utf-8\r
3 """\r
4 ========================\r
5 MikuMikuDance PMX format\r
6 ========================\r
7 \r
8 file format\r
9 ~~~~~~~~~~~\r
10 * PMDEditor's Lib/PMX仕様/PMX仕様.txt\r
11 \r
12 specs\r
13 ~~~~~\r
14 * textencoding: unicode\r
15 * coordinate: left handed y-up(DirectX)\r
16 * uv origin: \r
17 * face: only triangle\r
18 * backculling: \r
19 \r
20 """\r
21 __author__="ousttrue"\r
22 __license__="zlib"\r
23 __versioon__="1.0.0"\r
24 \r
25 \r
26 import io\r
27 import os\r
28 import struct\r
29 from pymeshio import common\r
30 \r
31 \r
32 \r
33 class DifferenceException(Exception):\r
34     pass\r
35 \r
36 \r
37 class Diff(object):\r
38     def _diff(self, rhs, key):\r
39         l=getattr(self, key)\r
40         r=getattr(rhs, key)\r
41         if l!=r:\r
42             print(l)\r
43             print(r)\r
44             raise DifferenceException(key)\r
45 \r
46     def _diff_array(self, rhs, key):\r
47         la=getattr(self, key)\r
48         ra=getattr(rhs, key)\r
49         if len(la)!=len(la):\r
50             raise DifferenceException(key)\r
51         for i, (l, r) in enumerate(zip(la, ra)):\r
52             if isinstance(l, Diff):\r
53                 try:\r
54                     l.diff(r)\r
55                 except DifferenceException as e:\r
56                     print(i)\r
57                     print(l)\r
58                     print(r)\r
59                     raise DifferenceException("{0}: {1}".format(key, e.message))\r
60             else:\r
61                 if l!=r:\r
62                     print(i)\r
63                     print(l)\r
64                     print(r)\r
65                     raise DifferenceException("{0}".format(key))\r
66 \r
67 \r
68 class Ik(Diff):\r
69     """ik info\r
70     """\r
71     __slots__=[\r
72             'target_index',\r
73             'loop',\r
74             'limit_radian',\r
75             'link',\r
76             ]\r
77     def __init__(self, target_index, loop, limit_radian, link=[]):\r
78         self.target_index=target_index\r
79         self.loop=loop\r
80         self.limit_radian=limit_radian\r
81         self.link=link\r
82 \r
83     def __eq__(self, rhs):\r
84         return (\r
85                 self.target_index==rhs.target_index\r
86                 and self.loop==rhs.loop\r
87                 and self.limit_radian==rhs.limit_radian\r
88                 and self.link==rhs.link\r
89                 )\r
90 \r
91     def diff(self, rhs):\r
92         self._diff(rhs, 'target_index')\r
93         self._diff(rhs, 'loop')\r
94         self._diff(rhs, 'limit_radian')\r
95         self._diff_array(rhs, 'link')\r
96 \r
97 \r
98 class IkLink(Diff):\r
99     """ik link info\r
100     """\r
101     __slots__=[\r
102             'bone_index',\r
103             'limit_angle',\r
104             'limit_min',\r
105             'limit_max',\r
106             ]\r
107     def __init__(self, bone_index, limit_angle, limit_min=common.Vector3(), limit_max=common.Vector3()):\r
108         self.bone_index=bone_index\r
109         self.limit_angle=limit_angle\r
110         self.limit_min=limit_min\r
111         self.limit_max=limit_max\r
112 \r
113     def __eq__(self, rhs):\r
114         return (\r
115                 self.bone_index==rhs.bone_index\r
116                 and self.limit_angle==rhs.limit_angle\r
117                 and self.limit_min==rhs.limit_min\r
118                 and self.limit_max==rhs.limit_max\r
119                 )\r
120 \r
121     def diff(self, rhs):\r
122         self._diff(rhs, 'bone_index')\r
123         self._diff(rhs, 'limit_angle')\r
124         self._diff(rhs, 'limit_min')\r
125         self._diff(rhs, 'limit_max')\r
126 \r
127 \r
128 class Bone(Diff):\r
129     """material\r
130 \r
131     Bone: see __init__\r
132     """\r
133     __slots__=[\r
134             'name',\r
135             'english_name',\r
136             'position',\r
137             'parent_index',\r
138             'layer',\r
139             'flag',\r
140 \r
141             'tail_position',\r
142             'tail_index',\r
143             'effect_index',\r
144             'effect_factor',\r
145             'fixed_axis',\r
146             'local_x_vector',\r
147             'local_z_vector',\r
148             'external_key',\r
149             'ik',\r
150             ]\r
151     def __init__(self,\r
152             name,\r
153             english_name,\r
154             position,\r
155             parent_index,\r
156             layer,\r
157             flag,\r
158             tail_position=common.Vector3(),\r
159             tail_index=-1,\r
160             effect_index=-1,\r
161             effect_factor=0.0,\r
162             fixed_axis=common.Vector3(),\r
163             local_x_vector=common.Vector3(),\r
164             local_z_vector=common.Vector3(),\r
165             external_key=-1,\r
166             ik=None\r
167             ):\r
168         self.name=name\r
169         self.english_name=english_name\r
170         self.position=position\r
171         self.parent_index=parent_index\r
172         self.layer=layer\r
173         self.flag=flag\r
174         self.tail_position=tail_position\r
175         self.tail_index=tail_index\r
176         self.effect_index=effect_index\r
177         self.effect_factor=effect_factor\r
178         self.fixed_axis=fixed_axis\r
179         self.local_x_vector=local_x_vector\r
180         self.local_z_vector=local_z_vector\r
181         self.external_key=external_key\r
182         self.ik=ik\r
183 \r
184     def __eq__(self, rhs):\r
185         return (\r
186                 self.name==rhs.name\r
187                 and self.english_name==rhs.english_name\r
188                 and self.position==rhs.position\r
189                 and self.parent_index==rhs.parent_index\r
190                 and self.layer==rhs.layer\r
191                 and self.flag==rhs.flag\r
192                 )\r
193 \r
194     def __ne__(self, rhs):\r
195         return not self.__eq__(rhs)\r
196 \r
197     def diff(self, rhs):\r
198         self._diff(rhs, 'name')\r
199         self._diff(rhs, 'english_name')\r
200         self._diff(rhs, 'position')\r
201         self._diff(rhs, 'parent_index')\r
202         #self._diff(rhs, 'layer')\r
203         self._diff(rhs, 'flag')\r
204         self._diff(rhs, 'tail_position')\r
205         self._diff(rhs, 'tail_index')\r
206         #self._diff(rhs, 'effect_index')\r
207         #self._diff(rhs, 'effect_factor')\r
208         #self._diff(rhs, 'fixed_axis')\r
209         self._diff(rhs, 'local_x_vector')\r
210         self._diff(rhs, 'local_z_vector')\r
211         self._diff(rhs, 'external_key')\r
212         if self.ik and rhs.ik:\r
213             self.ik.diff(rhs.ik)\r
214         else:\r
215             self._diff(rhs, 'ik')\r
216 \r
217     def getConnectionFlag(self):\r
218         return self.flag & 0x0001\r
219 \r
220     def getIkFlag(self):\r
221         return (self.flag & 0x0020) >> 5\r
222 \r
223     def getRotationFlag(self):\r
224         return (self.flag & 0x0100) >> 8\r
225 \r
226     def getTranslationFlag(self):\r
227         return (self.flag & 0x0200) >> 9\r
228 \r
229     def getFixedAxisFlag(self):\r
230         return (self.flag & 0x0400) >> 10\r
231 \r
232     def getLocalCoordinateFlag(self):\r
233         return (self.flag &  0x0800) >> 11\r
234     \r
235     def getExternalParentDeformFlag(self):\r
236         return (self.flag &  0x2000) >> 13\r
237 \r
238  \r
239 class Material(Diff):\r
240     """material\r
241 \r
242     Attributes: see __init__\r
243     """\r
244     __slots__=[\r
245             'name',\r
246             'english_name',\r
247             'diffuse_color',\r
248             'alpha',\r
249             'specular_color',\r
250             'specular_factor',\r
251             'ambient_color',\r
252             'flag',\r
253             'edge_color',\r
254             'edge_size',\r
255             'texture_index',\r
256             'sphere_texture_index',\r
257             'sphere_mode',\r
258             'toon_sharing_flag',\r
259             'toon_texture_index',\r
260             'comment',\r
261             'vertex_count',\r
262             ]\r
263     def __init__(self,\r
264             name,\r
265             english_name,\r
266             diffuse_color,\r
267             alpha,\r
268             specular_factor,\r
269             specular_color,\r
270             ambient_color,\r
271             flag,\r
272             edge_color,\r
273             edge_size,\r
274             texture_index,\r
275             sphere_texture_index,\r
276             sphere_mode,\r
277             toon_sharing_flag,\r
278             toon_texture_index=0,\r
279             comment=common.unicode(""),\r
280             vertex_count=0,\r
281             ):\r
282         self.name=name\r
283         self.english_name=english_name\r
284         self.diffuse_color=diffuse_color\r
285         self.alpha=alpha\r
286         self.specular_color=specular_color\r
287         self.specular_factor=specular_factor\r
288         self.ambient_color=ambient_color\r
289         self.flag=flag\r
290         self.edge_color=edge_color\r
291         self.edge_size=edge_size\r
292         self.texture_index=texture_index\r
293         self.sphere_texture_index=sphere_texture_index\r
294         self.sphere_mode=sphere_mode\r
295         self.toon_sharing_flag=toon_sharing_flag\r
296         self.toon_texture_index=toon_texture_index\r
297         self.comment=comment\r
298         self.vertex_count=vertex_count\r
299 \r
300     def __eq__(self, rhs):\r
301         return (\r
302                 self.name==rhs.name\r
303                 and self.english_name==rhs.english_name\r
304                 and self.diffuse_color==rhs.diffuse_color\r
305                 and self.alpha==rhs.alpha\r
306                 and self.specular_color==rhs.specular_color\r
307                 and self.specular_factor==rhs.specular_factor\r
308                 and self.ambient_color==rhs.ambient_color\r
309                 and self.flag==rhs.flag\r
310                 and self.edge_color==rhs.edge_color\r
311                 and self.edge_size==rhs.edge_size\r
312                 and self.texture_index==rhs.texture_index\r
313                 and self.sphere_texture_index==rhs.sphere_texture_index\r
314                 and self.sphere_mode==rhs.sphere_mode\r
315                 and self.toon_sharing_flag==rhs.toon_sharing_flag\r
316                 and self.toon_texture_index==rhs.toon_texture_index\r
317                 and self.comment==rhs.comment\r
318                 and self.vertex_count==rhs.vertex_count\r
319                 )\r
320 \r
321     def diff(self, rhs):\r
322         #self._diff(rhs, "name")\r
323         self._diff(rhs, "english_name")\r
324         self._diff(rhs, "diffuse_color")\r
325         self._diff(rhs, "alpha")\r
326         self._diff(rhs, "specular_color")\r
327         self._diff(rhs, "specular_factor")\r
328         self._diff(rhs, "ambient_color")\r
329         self._diff(rhs, "flag")\r
330         self._diff(rhs, "edge_color")\r
331         self._diff(rhs, "edge_size")\r
332         self._diff(rhs, "texture_index")\r
333         self._diff(rhs, "sphere_texture_index")\r
334         self._diff(rhs, "sphere_mode")\r
335         self._diff(rhs, "toon_sharing_flag")\r
336         self._diff(rhs, "toon_texture_index")\r
337         self._diff(rhs, "comment")\r
338         self._diff(rhs, "vertex_count")\r
339 \r
340     def __ne__(self, rhs):\r
341         return not self.__eq__(rhs)\r
342 \r
343     def __str__(self):\r
344         return ("<pmx.Material {name}>".format(\r
345             name=self.english_name\r
346             ))\r
347 \r
348 \r
349 class Bdef1(Diff):\r
350     """bone deform. use a weight\r
351 \r
352     Attributes: see __init__\r
353     """\r
354     __slots__=[ 'index0']\r
355     def __init__(self, index0):\r
356         self.index0=index0\r
357 \r
358     def __str__(self):\r
359         return "<Bdef1 {0}>".format(self.index0)\r
360 \r
361     def __eq__(self, rhs):\r
362         return self.index0==rhs.index0\r
363 \r
364     def __ne__(self, rhs):\r
365         return not self.__eq__(rhs)\r
366 \r
367 \r
368 class Bdef2(Diff):\r
369     """bone deform. use two weights\r
370 \r
371     Attributes: see __init__\r
372     """\r
373     __slots__=[ 'index0', 'index1', 'weight0']\r
374     def __init__(self, \r
375             index0,\r
376             index1,\r
377             weight0):\r
378         self.index0=index0\r
379         self.index1=index1\r
380         self.weight0=weight0\r
381 \r
382     def __str__(self):\r
383         return "<Bdef2 {0}, {1}, {2}>".format(self.index0, self.index1, self.weight0)\r
384 \r
385     def __eq__(self, rhs):\r
386         return (\r
387                 self.index0==rhs.index0\r
388                 and self.index1==rhs.index1\r
389                 #and self.weight0==rhs.weight0\r
390                 and abs(self.weight0-rhs.weight0)<1e-5\r
391                 )\r
392 \r
393     def __ne__(self, rhs):\r
394         return not self.__eq__(rhs)\r
395 \r
396 \r
397 class Vertex(Diff):\r
398     """\r
399     ==========\r
400     pmx vertex\r
401     ==========\r
402 \r
403     :IVariables:\r
404         position\r
405             Vector3\r
406         normal \r
407             Vector3\r
408         uv \r
409             Vector2\r
410         deform\r
411             Bdef1, Bdef2 or Bdef4\r
412         edge_factor\r
413             float\r
414     """\r
415     __slots__=[ 'position', 'normal', 'uv', 'deform', 'edge_factor' ]\r
416     def __init__(self, \r
417             position, \r
418             normal, \r
419             uv, \r
420             deform, \r
421             edge_factor):\r
422         self.position=position \r
423         self.normal=normal\r
424         self.uv=uv\r
425         self.deform=deform\r
426         self.edge_factor=edge_factor\r
427 \r
428     def __str__(self):\r
429         return "<Vertex position:{0}, normal:{1}, uv:{2}, deform:{3}, edge:{4}".format(\r
430                 self.position, self.normal, self.uv, self.deform, self.edge_factor\r
431                 )\r
432 \r
433     def __eq__(self, rhs):\r
434         return (\r
435                 self.position==rhs.position\r
436                 and self.normal==rhs.normal\r
437                 and self.uv==rhs.uv\r
438                 and self.deform==rhs.deform\r
439                 and self.edge_factor==rhs.edge_factor\r
440                 )\r
441 \r
442     def __ne__(self, rhs):\r
443         return not self.__eq__(rhs)\r
444 \r
445     def diff(self, rhs):\r
446         self._diff(rhs, "position")\r
447         self._diff(rhs, "normal")\r
448         self._diff(rhs, "uv")\r
449         self._diff(rhs, "deform")\r
450         self._diff(rhs, "edge_factor")\r
451 \r
452 \r
453 class Morph(Diff):\r
454     """pmx morph\r
455 \r
456     Attributes:\r
457         name: \r
458         english_name: \r
459         panel:\r
460         morph_type:\r
461         offsets:\r
462     """\r
463     __slots__=[\r
464             'name',\r
465             'english_name',\r
466             'panel',\r
467             'morph_type',\r
468             'offsets',\r
469             ]\r
470     def __init__(self, name, english_name, panel, morph_type):\r
471         self.name=name\r
472         self.english_name=english_name\r
473         self.panel=panel\r
474         self.morph_type=morph_type\r
475         self.offsets=[]\r
476 \r
477     def __eq__(self, rhs):\r
478         return (\r
479                 self.name==rhs.name\r
480                 and self.english_name==rhs.english_name\r
481                 and self.panel==rhs.panel\r
482                 and self.morph_type==rhs.morph_type\r
483                 and self.offsets==rhs.offsets\r
484                 )\r
485 \r
486     def __ne__(self, rhs):\r
487         return not self.__eq__(rhs)\r
488 \r
489     def diff(self, rhs):\r
490         self._diff(rhs, 'name')\r
491         self._diff(rhs, 'english_name')\r
492         self._diff(rhs, 'panel')\r
493         self._diff(rhs, 'morph_type')\r
494         self._diff_array(rhs, 'offsets')\r
495 \r
496 \r
497 class VerexMorphOffset(Diff):\r
498     """pmx vertex morph offset\r
499 \r
500     Attributes:\r
501         vertex_index:\r
502         position_offset: Vector3\r
503     """\r
504     __slots__=[\r
505             'vertex_index',\r
506             'position_offset',\r
507             ]\r
508     def __init__(self, vertex_index, position_offset):\r
509         self.vertex_index=vertex_index\r
510         self.position_offset=position_offset\r
511 \r
512     def __eq__(self, rhs):\r
513         return (\r
514                 self.vertex_index==rhs.vertex_index \r
515                 and self.position_offset==rhs.position_offset\r
516                 )\r
517 \r
518     def __ne__(self, rhs):\r
519         return not self.__eq__(rhs)\r
520 \r
521     def diff(self, rhs):\r
522         self._diff(rhs, 'name')\r
523         self._diff(rhs, 'english_name')\r
524 \r
525 \r
526 class DisplaySlot(Diff):\r
527     """pmx display slot\r
528 \r
529     Attributes:\r
530         name: \r
531         english_name: \r
532         special_flag:\r
533         refrences: list of (ref_type, ref_index)\r
534     """\r
535     __slots__=[\r
536             'name',\r
537             'english_name',\r
538             'special_flag',\r
539             'refrences',\r
540             ]\r
541     def __init__(self, name, english_name, special_flag):\r
542         self.name=name\r
543         self.english_name=english_name\r
544         self.special_flag=special_flag\r
545         self.refrences=[]\r
546 \r
547     def __eq__(self, rhs):\r
548         return (\r
549                 self.name==rhs.name\r
550                 and self.english_name==rhs.english_name\r
551                 and self.special_flag==rhs.special_flag\r
552                 and self.refrences==rhs.refrences\r
553                 )\r
554 \r
555     def __ne__(self, rhs):\r
556         return not self.__eq__(rhs)\r
557 \r
558     def diff(self, rhs):\r
559         self._diff(rhs, 'name')\r
560         self._diff(rhs, 'english_name')\r
561         self._diff(rhs, 'special_flag')\r
562         self._diff_array(rhs, 'refrences')\r
563 \r
564 \r
565 class RigidBodyParam(Diff):\r
566     """pmx rigidbody param(for bullet)\r
567 \r
568     Attributes:\r
569         mass:\r
570         linear_damping:\r
571         angular_damping:\r
572         restitution:\r
573         friction:\r
574     """\r
575     __slots__=[\r
576             'mass',\r
577             'linear_damping',\r
578             'angular_damping',\r
579             'restitution',\r
580             'friction',\r
581             ]\r
582     def __init__(self, mass, \r
583             linear_damping, angular_damping, restitution, friction):\r
584         self.mass=mass\r
585         self.linear_damping=linear_damping\r
586         self.angular_damping=angular_damping\r
587         self.restitution=restitution\r
588         self.friction=friction\r
589 \r
590     def __eq__(self, rhs):\r
591         return (\r
592                 self.mass==rhs.mass\r
593                 and self.linear_damping==rhs.linear_damping\r
594                 and self.angular_damping==rhs.angular_damping\r
595                 and self.restitution==rhs.restitution\r
596                 and self.friction==rhs.friction\r
597                 )\r
598 \r
599     def __ne__(self, rhs):\r
600         return not self.__eq__(rhs)\r
601 \r
602     def diff(self, rhs):\r
603         self._diff(rhs, 'mass')\r
604         self._diff(rhs, 'linear_damping')\r
605         self._diff(rhs, 'angular_damping')\r
606         self._diff_array(rhs, 'restitution')\r
607         self._diff_array(rhs, 'friction')\r
608 \r
609 \r
610 class RigidBody(Diff):\r
611     """pmx rigidbody\r
612 \r
613     Attributes:\r
614         name: \r
615         english_name: \r
616         bone_index:\r
617         collision_group:\r
618         no_collision_group:\r
619         shape:\r
620         param:\r
621         mode:\r
622     """\r
623     __slots__=[\r
624             'name',\r
625             'english_name',\r
626             'bone_index',\r
627             'collision_group',\r
628             'no_collision_group',\r
629             'shape_type',\r
630             'shape_size',\r
631             'shape_position',\r
632             'shape_rotation',\r
633             'param',\r
634             'mode',\r
635             ]\r
636     def __init__(self,\r
637             name,\r
638             english_name,\r
639             bone_index,\r
640             collision_group,\r
641             no_collision_group,\r
642             shape_type,\r
643             shape_size,\r
644             shape_position,\r
645             shape_rotation,\r
646             mass,\r
647             linear_damping,\r
648             angular_damping,\r
649             restitution,\r
650             friction,\r
651             mode\r
652             ):\r
653         self.name=name\r
654         self.english_name=english_name\r
655         self.bone_index=bone_index\r
656         self.collision_group=collision_group\r
657         self.no_collision_group=no_collision_group\r
658         self.shape_type=shape_type\r
659         self.shape_size=shape_size\r
660         self.shape_position=shape_position\r
661         self.shape_rotation=shape_rotation\r
662         self.param=RigidBodyParam(mass,\r
663                 linear_damping, angular_damping,\r
664                 restitution, friction)\r
665         self.mode=mode\r
666 \r
667     def __eq__(self, rhs):\r
668         return (\r
669                 self.name==rhs.name\r
670                 and self.english_name==rhs.english_name\r
671                 and self.bone_index==rhs.bone_index\r
672                 and self.collision_group==rhs.collision_group\r
673                 and self.no_collision_group==rhs.no_collision_group\r
674                 and self.shape_type==rhs.shape_type\r
675                 and self.shape_size==rhs.shape_size\r
676                 and self.param==rhs.param\r
677                 and self.mode==rhs.mode\r
678                 )\r
679 \r
680     def __ne__(self, rhs):\r
681         return not self.__eq__(rhs)\r
682 \r
683     def diff(self, rhs):\r
684         self._diff(rhs, 'name')\r
685         self._diff(rhs, 'english_name')\r
686         self._diff(rhs, 'bone_index')\r
687         self._diff(rhs, 'collision_group')\r
688         self._diff(rhs, 'no_collision_group')\r
689         self._diff(rhs, 'shape_type')\r
690         self._diff(rhs, 'shape_size')\r
691         self._diff(rhs, 'shape_position')\r
692         self._diff(rhs, 'shape_rotation')\r
693         self._diff(rhs, 'param')\r
694         self._diff(rhs, 'mode')\r
695 \r
696 \r
697 class Joint(Diff):\r
698     """pmx joint\r
699 \r
700     Attributes:\r
701         name: \r
702         english_name: \r
703         joint_type:\r
704         rigidbody_index_a:\r
705         rigidbody_index_b:\r
706         position: Vector3\r
707         rotation: Vector3\r
708         translation_limit_min: Vector3\r
709         translation_limit_max: Vector3\r
710         rotation_limit_min: Vector3\r
711         rotation_limit_max: Vector3\r
712         spring_constant_translation: Vector3\r
713         spring_constant_rotation: Vector3\r
714     """\r
715     __slots__=[\r
716             'name',\r
717             'english_name',\r
718             'joint_type',\r
719             'rigidbody_index_a',\r
720             'rigidbody_index_b',\r
721             'position',\r
722             'rotation',\r
723             'translation_limit_min',\r
724             'translation_limit_max',\r
725             'rotation_limit_min',\r
726             'rotation_limit_max',\r
727             'spring_constant_translation',\r
728             'spring_constant_rotation',\r
729             ]\r
730     def __init__(self, name, english_name,\r
731             joint_type,\r
732             rigidbody_index_a,\r
733             rigidbody_index_b,\r
734             position,\r
735             rotation,\r
736             translation_limit_min,\r
737             translation_limit_max,\r
738             rotation_limit_min,\r
739             rotation_limit_max,\r
740             spring_constant_translation,\r
741             spring_constant_rotation\r
742             ):\r
743         self.name=name\r
744         self.english_name=english_name\r
745         self.joint_type=joint_type\r
746         self.rigidbody_index_a=rigidbody_index_a\r
747         self.rigidbody_index_b=rigidbody_index_b\r
748         self.position=position\r
749         self.rotation=rotation\r
750         self.translation_limit_min=translation_limit_min\r
751         self.translation_limit_max=translation_limit_max\r
752         self.rotation_limit_min=rotation_limit_min\r
753         self.rotation_limit_max=rotation_limit_max\r
754         self.spring_constant_translation=spring_constant_translation\r
755         self.spring_constant_rotation=spring_constant_rotation\r
756 \r
757     def __eq__(self, rhs):\r
758         return (\r
759                 self.name==rhs.name\r
760                 and self.english_name==rhs.english_name\r
761                 and self.joint_type==rhs.joint_type\r
762                 and self.rigidbody_index_a==rhs.rigidbody_index_a\r
763                 and self.rigidbody_index_b==rhs.rigidbody_index_b\r
764                 and self.position==rhs.position\r
765                 and self.rotation==rhs.rotation\r
766                 and self.translation_limit_min==rhs.translation_limit_min\r
767                 and self.translation_limit_max==rhs.translation_limit_max\r
768                 and self.rotation_limit_min==rhs.rotation_limit_min\r
769                 and self.rotation_limit_max==rhs.rotation_limit_max\r
770                 and self.spring_constant_translation==rhs.spring_constant_translation\r
771                 and self.spring_constant_rotation==rhs.spring_constant_rotation\r
772                 )\r
773 \r
774     def __ne__(self, rhs):\r
775         return not self.__eq__(rhs)\r
776 \r
777     def diff(self, rhs):\r
778         self._diff(rhs, 'name')\r
779         self._diff(rhs, 'joint_type')\r
780         self._diff(rhs, 'rigidbody_index_a')\r
781         self._diff(rhs, 'rigidbody_index_b')\r
782         self._diff(rhs, 'position')\r
783         self._diff(rhs, 'rotation')\r
784         self._diff(rhs, 'translation_limit_min')\r
785         self._diff(rhs, 'translation_limit_max')\r
786         self._diff(rhs, 'rotation_limit_min')\r
787         self._diff(rhs, 'rotation_limit_max')\r
788         self._diff(rhs, 'spring_constant_translation')\r
789         self._diff(rhs, 'spring_constant_rotation')\r
790 \r
791 \r
792 class Model(Diff):\r
793     """\r
794     ==========\r
795     pmx model\r
796     ==========\r
797 \r
798     :IVariables:\r
799         version\r
800             pmx version(expected 2.0)\r
801         name \r
802             model name\r
803         english_name \r
804             model name\r
805         comment \r
806             comment\r
807         english_comment \r
808             comment\r
809         vertices\r
810             vertex list\r
811         textures\r
812             texture list\r
813         materials\r
814             material list\r
815         bones\r
816             bone list\r
817         morph\r
818             morph list\r
819         display_slots\r
820             display list for bone/morph grouping\r
821         rigidbodies\r
822             bullet physics rigidbody list\r
823         joints\r
824             bullet physics joint list\r
825     """\r
826     __slots__=[\r
827             'version',\r
828             'name',\r
829             'english_name',\r
830             'comment',\r
831             'english_comment',\r
832             'vertices',\r
833             'indices',\r
834             'textures',\r
835             'materials',\r
836             'bones',\r
837             'morphs',\r
838             'display_slots',\r
839             'rigidbodies',\r
840             'joints',\r
841             ]\r
842     def __init__(self, version=2.0):\r
843         self.version=version\r
844         self.name=''\r
845         self.english_name=''\r
846         self.comment=''\r
847         self.english_comment=''\r
848         self.vertices=[]\r
849         self.indices=[]\r
850         self.textures=[]\r
851         self.materials=[]\r
852         self.bones=[]\r
853         self.morphs=[]\r
854         self.display_slots=[]\r
855         self.rigidbodies=[]\r
856         self.joints=[]\r
857 \r
858     def __str__(self):\r
859         return ('<pmx-{version} "{name}" {vertices}vertices>'.format(\r
860             version=self.version,\r
861             name=self.english_name,\r
862             vertices=len(self.vertices)\r
863             ))\r
864 \r
865     def __eq__(self, rhs):\r
866         return (\r
867                 self.version==rhs.version\r
868                 and self.name==rhs.name\r
869                 and self.english_name==rhs.english_name\r
870                 and self.comment==rhs.comment\r
871                 and self.english_comment==rhs.english_comment\r
872                 and self.vertices==rhs.vertices\r
873                 and self.indices==rhs.indices\r
874                 and self.textures==rhs.textures\r
875                 and self.materials==rhs.materials\r
876                 and self.bones==rhs.bones\r
877                 and self.morphs==rhs.morphs\r
878                 and self.display_slots==rhs.display_slots\r
879                 and self.rigidbodies==rhs.rigidbodies\r
880                 and self.joints==rhs.joints\r
881                 )\r
882 \r
883     def __ne__(self, rhs):\r
884         return not self.__eq__(rhs)\r
885 \r
886     def diff(self, rhs):\r
887         self._diff(rhs, "version")\r
888         self._diff(rhs, "name")\r
889         self._diff(rhs, "english_name")\r
890         self._diff(rhs, "comment")\r
891         self._diff(rhs, "english_comment")\r
892         self._diff_array(rhs, "vertices")\r
893         self._diff_array(rhs, "indices")\r
894         self._diff_array(rhs, "textures")\r
895         self._diff_array(rhs, "materials")\r
896         self._diff_array(rhs, "bones")\r
897         self._diff_array(rhs, "morphs")\r
898         self._diff_array(rhs, "display_slots")\r
899         self._diff_array(rhs, "rigidbodies")\r
900         self._diff_array(rhs, "joints")\r
901 \r