OSDN Git Service

3f36686862f1c2d4f0d42b67a04d6a57aee0e8ec
[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 .. 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(ra):\r
50             raise DifferenceException("%s diffrence %d with %d" % (key, len(la), len(ra)))\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=None):\r
78         self.target_index=target_index\r
79         self.loop=loop\r
80         self.limit_radian=limit_radian\r
81         self.link=link or []\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)!=0\r
219 \r
220     def getVisibleFlag(self):\r
221         return (self.flag & 0x0008)!=0\r
222 \r
223     def getIkFlag(self):\r
224         return (self.flag & 0x0020)!=0\r
225 \r
226     def getRotationFlag(self):\r
227         return (self.flag & 0x0100)!=0\r
228 \r
229     def getTranslationFlag(self):\r
230         return (self.flag & 0x0200)!=0\r
231 \r
232     def getFixedAxisFlag(self):\r
233         return (self.flag & 0x0400)!=0\r
234 \r
235     def getLocalCoordinateFlag(self):\r
236         return (self.flag &  0x0800)!=0\r
237     \r
238     def getExternalParentDeformFlag(self):\r
239         return (self.flag &  0x2000)!=0\r
240 \r
241  \r
242 class Material(Diff):\r
243     """material\r
244 \r
245     Attributes: see __init__\r
246     """\r
247     __slots__=[\r
248             'name',\r
249             'english_name',\r
250             'diffuse_color',\r
251             'alpha',\r
252             'specular_color',\r
253             'specular_factor',\r
254             'ambient_color',\r
255             'flag',\r
256             'edge_color',\r
257             'edge_size',\r
258             'texture_index',\r
259             'sphere_texture_index',\r
260             'sphere_mode',\r
261             'toon_sharing_flag',\r
262             'toon_texture_index',\r
263             'comment',\r
264             'vertex_count',\r
265             ]\r
266     def __init__(self,\r
267             name,\r
268             english_name,\r
269             diffuse_color,\r
270             alpha,\r
271             specular_factor,\r
272             specular_color,\r
273             ambient_color,\r
274             flag,\r
275             edge_color,\r
276             edge_size,\r
277             texture_index,\r
278             sphere_texture_index,\r
279             sphere_mode,\r
280             toon_sharing_flag,\r
281             toon_texture_index=0,\r
282             comment=common.unicode(""),\r
283             vertex_count=0,\r
284             ):\r
285         self.name=name\r
286         self.english_name=english_name\r
287         self.diffuse_color=diffuse_color\r
288         self.alpha=alpha\r
289         self.specular_color=specular_color\r
290         self.specular_factor=specular_factor\r
291         self.ambient_color=ambient_color\r
292         self.flag=flag\r
293         self.edge_color=edge_color\r
294         self.edge_size=edge_size\r
295         self.texture_index=texture_index\r
296         self.sphere_texture_index=sphere_texture_index\r
297         self.sphere_mode=sphere_mode\r
298         self.toon_sharing_flag=toon_sharing_flag\r
299         self.toon_texture_index=toon_texture_index\r
300         self.comment=comment\r
301         self.vertex_count=vertex_count\r
302 \r
303     def __eq__(self, rhs):\r
304         return (\r
305                 self.name==rhs.name\r
306                 and self.english_name==rhs.english_name\r
307                 and self.diffuse_color==rhs.diffuse_color\r
308                 and self.alpha==rhs.alpha\r
309                 and self.specular_color==rhs.specular_color\r
310                 and self.specular_factor==rhs.specular_factor\r
311                 and self.ambient_color==rhs.ambient_color\r
312                 and self.flag==rhs.flag\r
313                 and self.edge_color==rhs.edge_color\r
314                 and self.edge_size==rhs.edge_size\r
315                 and self.texture_index==rhs.texture_index\r
316                 and self.sphere_texture_index==rhs.sphere_texture_index\r
317                 and self.sphere_mode==rhs.sphere_mode\r
318                 and self.toon_sharing_flag==rhs.toon_sharing_flag\r
319                 and self.toon_texture_index==rhs.toon_texture_index\r
320                 and self.comment==rhs.comment\r
321                 and self.vertex_count==rhs.vertex_count\r
322                 )\r
323 \r
324     def diff(self, rhs):\r
325         #self._diff(rhs, "name")\r
326         self._diff(rhs, "english_name")\r
327         self._diff(rhs, "diffuse_color")\r
328         self._diff(rhs, "alpha")\r
329         self._diff(rhs, "specular_color")\r
330         self._diff(rhs, "specular_factor")\r
331         self._diff(rhs, "ambient_color")\r
332         self._diff(rhs, "flag")\r
333         self._diff(rhs, "edge_color")\r
334         self._diff(rhs, "edge_size")\r
335         self._diff(rhs, "texture_index")\r
336         self._diff(rhs, "sphere_texture_index")\r
337         self._diff(rhs, "sphere_mode")\r
338         self._diff(rhs, "toon_sharing_flag")\r
339         self._diff(rhs, "toon_texture_index")\r
340         self._diff(rhs, "comment")\r
341         self._diff(rhs, "vertex_count")\r
342 \r
343     def __ne__(self, rhs):\r
344         return not self.__eq__(rhs)\r
345 \r
346     def __str__(self):\r
347         return ("<pmx.Material {name}>".format(\r
348             name=self.english_name\r
349             ))\r
350 \r
351 \r
352 class Bdef1(Diff):\r
353     """bone deform. use a weight\r
354 \r
355     Attributes: see __init__\r
356     """\r
357     __slots__=[ 'index0']\r
358     def __init__(self, index0):\r
359         self.index0=index0\r
360 \r
361     def __str__(self):\r
362         return "<Bdef1 {0}>".format(self.index0)\r
363 \r
364     def __eq__(self, rhs):\r
365         return self.index0==rhs.index0\r
366 \r
367     def __ne__(self, rhs):\r
368         return not self.__eq__(rhs)\r
369 \r
370 \r
371 class Bdef2(Diff):\r
372     """bone deform. use two weights\r
373 \r
374     Attributes: see __init__\r
375     """\r
376     __slots__=[ 'index0', 'index1', 'weight0']\r
377     def __init__(self, \r
378             index0,\r
379             index1,\r
380             weight0):\r
381         self.index0=index0\r
382         self.index1=index1\r
383         self.weight0=weight0\r
384 \r
385     def __str__(self):\r
386         return "<Bdef2 {0}, {1}, {2}>".format(self.index0, self.index1, self.weight0)\r
387 \r
388     def __eq__(self, rhs):\r
389         return (\r
390                 self.index0==rhs.index0\r
391                 and self.index1==rhs.index1\r
392                 #and self.weight0==rhs.weight0\r
393                 and abs(self.weight0-rhs.weight0)<1e-5\r
394                 )\r
395 \r
396     def __ne__(self, rhs):\r
397         return not self.__eq__(rhs)\r
398 \r
399 \r
400 class Vertex(Diff):\r
401     """\r
402     ==========\r
403     pmx vertex\r
404     ==========\r
405 \r
406     :IVariables:\r
407         position\r
408             Vector3\r
409         normal \r
410             Vector3\r
411         uv \r
412             Vector2\r
413         deform\r
414             Bdef1, Bdef2 or Bdef4\r
415         edge_factor\r
416             float\r
417     """\r
418     __slots__=[ 'position', 'normal', 'uv', 'deform', 'edge_factor' ]\r
419     def __init__(self, \r
420             position, \r
421             normal, \r
422             uv, \r
423             deform, \r
424             edge_factor):\r
425         self.position=position \r
426         self.normal=normal\r
427         self.uv=uv\r
428         self.deform=deform\r
429         self.edge_factor=edge_factor\r
430 \r
431     def __str__(self):\r
432         return "<Vertex position:{0}, normal:{1}, uv:{2}, deform:{3}, edge:{4}".format(\r
433                 self.position, self.normal, self.uv, self.deform, self.edge_factor\r
434                 )\r
435 \r
436     def __eq__(self, rhs):\r
437         return (\r
438                 self.position==rhs.position\r
439                 and self.normal==rhs.normal\r
440                 and self.uv==rhs.uv\r
441                 and self.deform==rhs.deform\r
442                 and self.edge_factor==rhs.edge_factor\r
443                 )\r
444 \r
445     def __ne__(self, rhs):\r
446         return not self.__eq__(rhs)\r
447 \r
448     def diff(self, rhs):\r
449         self._diff(rhs, "position")\r
450         self._diff(rhs, "normal")\r
451         self._diff(rhs, "uv")\r
452         self._diff(rhs, "deform")\r
453         self._diff(rhs, "edge_factor")\r
454 \r
455 \r
456 class Morph(Diff):\r
457     """pmx morph\r
458 \r
459     Attributes:\r
460         name: \r
461         english_name: \r
462         panel:\r
463         morph_type:\r
464         offsets:\r
465     """\r
466     __slots__=[\r
467             'name',\r
468             'english_name',\r
469             'panel',\r
470             'morph_type',\r
471             'offsets',\r
472             ]\r
473     def __init__(self, name, english_name, panel, morph_type, offsets=None):\r
474         self.name=name\r
475         self.english_name=english_name\r
476         self.panel=panel\r
477         self.morph_type=morph_type\r
478         self.offsets=offsets or []\r
479 \r
480     def __eq__(self, rhs):\r
481         return (\r
482                 self.name==rhs.name\r
483                 and self.english_name==rhs.english_name\r
484                 and self.panel==rhs.panel\r
485                 and self.morph_type==rhs.morph_type\r
486                 and self.offsets==rhs.offsets\r
487                 )\r
488 \r
489     def __ne__(self, rhs):\r
490         return not self.__eq__(rhs)\r
491 \r
492     def diff(self, rhs):\r
493         self._diff(rhs, 'name')\r
494         self._diff(rhs, 'english_name')\r
495         #self._diff(rhs, 'panel')\r
496         self._diff(rhs, 'morph_type')\r
497         self._diff_array(rhs, 'offsets')\r
498 \r
499 \r
500 class VerexMorphOffset(Diff):\r
501     """pmx vertex morph offset\r
502 \r
503     Attributes:\r
504         vertex_index:\r
505         position_offset: Vector3\r
506     """\r
507     __slots__=[\r
508             'vertex_index',\r
509             'position_offset',\r
510             ]\r
511     def __init__(self, vertex_index, position_offset):\r
512         self.vertex_index=vertex_index\r
513         self.position_offset=position_offset\r
514 \r
515     def __eq__(self, rhs):\r
516         return (\r
517                 self.vertex_index==rhs.vertex_index \r
518                 and self.position_offset==rhs.position_offset\r
519                 )\r
520 \r
521     def __ne__(self, rhs):\r
522         return not self.__eq__(rhs)\r
523 \r
524     def diff(self, rhs):\r
525         self._diff(rhs, 'vertex_index')\r
526         self._diff(rhs, 'position_offset')\r
527 \r
528 \r
529 class DisplaySlot(Diff):\r
530     """pmx display slot\r
531 \r
532     Attributes:\r
533         name: \r
534         english_name: \r
535         special_flag:\r
536         references: list of (ref_type, ref_index)\r
537     """\r
538     __slots__=[\r
539             'name',\r
540             'english_name',\r
541             'special_flag',\r
542             'references',\r
543             ]\r
544     def __init__(self, name, english_name, special_flag, references=None):\r
545         self.name=name\r
546         self.english_name=english_name\r
547         self.special_flag=special_flag\r
548         self.references=references or []\r
549 \r
550     def __str__(self):\r
551         return "<DisplaySlots %s(%d)>" % (self.name, len(self.references))\r
552 \r
553     def __eq__(self, rhs):\r
554         return (\r
555                 self.name==rhs.name\r
556                 and self.english_name==rhs.english_name\r
557                 and self.special_flag==rhs.special_flag\r
558                 and self.references==rhs.references\r
559                 )\r
560 \r
561     def __ne__(self, rhs):\r
562         return not self.__eq__(rhs)\r
563 \r
564     def diff(self, rhs):\r
565         self._diff(rhs, 'name')\r
566         self._diff(rhs, 'english_name')\r
567         self._diff(rhs, 'special_flag')\r
568         #self._diff_array(rhs, 'references')\r
569 \r
570 \r
571 class RigidBodyParam(Diff):\r
572     """pmx rigidbody param(for bullet)\r
573 \r
574     Attributes:\r
575         mass:\r
576         linear_damping:\r
577         angular_damping:\r
578         restitution:\r
579         friction:\r
580     """\r
581     __slots__=[\r
582             'mass',\r
583             'linear_damping',\r
584             'angular_damping',\r
585             'restitution',\r
586             'friction',\r
587             ]\r
588     def __init__(self, mass, \r
589             linear_damping, angular_damping, restitution, friction):\r
590         self.mass=mass\r
591         self.linear_damping=linear_damping\r
592         self.angular_damping=angular_damping\r
593         self.restitution=restitution\r
594         self.friction=friction\r
595 \r
596     def __eq__(self, rhs):\r
597         return (\r
598                 self.mass==rhs.mass\r
599                 and self.linear_damping==rhs.linear_damping\r
600                 and self.angular_damping==rhs.angular_damping\r
601                 and self.restitution==rhs.restitution\r
602                 and self.friction==rhs.friction\r
603                 )\r
604 \r
605     def __ne__(self, rhs):\r
606         return not self.__eq__(rhs)\r
607 \r
608     def diff(self, rhs):\r
609         self._diff(rhs, 'mass')\r
610         self._diff(rhs, 'linear_damping')\r
611         self._diff(rhs, 'angular_damping')\r
612         self._diff_array(rhs, 'restitution')\r
613         self._diff_array(rhs, 'friction')\r
614 \r
615 \r
616 class RigidBody(Diff):\r
617     """pmx rigidbody\r
618 \r
619     Attributes:\r
620         name: \r
621         english_name: \r
622         bone_index:\r
623         collision_group:\r
624         no_collision_group:\r
625         shape:\r
626         param:\r
627         mode:\r
628     """\r
629     __slots__=[\r
630             'name',\r
631             'english_name',\r
632             'bone_index',\r
633             'collision_group',\r
634             'no_collision_group',\r
635             'shape_type',\r
636             'shape_size',\r
637             'shape_position',\r
638             'shape_rotation',\r
639             'param',\r
640             'mode',\r
641             ]\r
642     def __init__(self,\r
643             name,\r
644             english_name,\r
645             bone_index,\r
646             collision_group,\r
647             no_collision_group,\r
648             shape_type,\r
649             shape_size,\r
650             shape_position,\r
651             shape_rotation,\r
652             mass,\r
653             linear_damping,\r
654             angular_damping,\r
655             restitution,\r
656             friction,\r
657             mode\r
658             ):\r
659         self.name=name\r
660         self.english_name=english_name\r
661         self.bone_index=bone_index\r
662         self.collision_group=collision_group\r
663         self.no_collision_group=no_collision_group\r
664         self.shape_type=shape_type\r
665         self.shape_size=shape_size\r
666         self.shape_position=shape_position\r
667         self.shape_rotation=shape_rotation\r
668         self.param=RigidBodyParam(mass,\r
669                 linear_damping, angular_damping,\r
670                 restitution, friction)\r
671         self.mode=mode\r
672 \r
673     def __eq__(self, rhs):\r
674         return (\r
675                 self.name==rhs.name\r
676                 and self.english_name==rhs.english_name\r
677                 and self.bone_index==rhs.bone_index\r
678                 and self.collision_group==rhs.collision_group\r
679                 and self.no_collision_group==rhs.no_collision_group\r
680                 and self.shape_type==rhs.shape_type\r
681                 and self.shape_size==rhs.shape_size\r
682                 and self.param==rhs.param\r
683                 and self.mode==rhs.mode\r
684                 )\r
685 \r
686     def __ne__(self, rhs):\r
687         return not self.__eq__(rhs)\r
688 \r
689     def diff(self, rhs):\r
690         self._diff(rhs, 'name')\r
691         self._diff(rhs, 'english_name')\r
692         self._diff(rhs, 'bone_index')\r
693         self._diff(rhs, 'collision_group')\r
694         self._diff(rhs, 'no_collision_group')\r
695         self._diff(rhs, 'shape_type')\r
696         self._diff(rhs, 'shape_size')\r
697         #self._diff(rhs, 'shape_position')\r
698         self._diff(rhs, 'shape_rotation')\r
699         self._diff(rhs, 'param')\r
700         self._diff(rhs, 'mode')\r
701 \r
702 \r
703 class Joint(Diff):\r
704     """pmx joint\r
705 \r
706     Attributes:\r
707         name: \r
708         english_name: \r
709         joint_type:\r
710         rigidbody_index_a:\r
711         rigidbody_index_b:\r
712         position: Vector3\r
713         rotation: Vector3\r
714         translation_limit_min: Vector3\r
715         translation_limit_max: Vector3\r
716         rotation_limit_min: Vector3\r
717         rotation_limit_max: Vector3\r
718         spring_constant_translation: Vector3\r
719         spring_constant_rotation: Vector3\r
720     """\r
721     __slots__=[\r
722             'name',\r
723             'english_name',\r
724             'joint_type',\r
725             'rigidbody_index_a',\r
726             'rigidbody_index_b',\r
727             'position',\r
728             'rotation',\r
729             'translation_limit_min',\r
730             'translation_limit_max',\r
731             'rotation_limit_min',\r
732             'rotation_limit_max',\r
733             'spring_constant_translation',\r
734             'spring_constant_rotation',\r
735             ]\r
736     def __init__(self, name, english_name,\r
737             joint_type,\r
738             rigidbody_index_a,\r
739             rigidbody_index_b,\r
740             position,\r
741             rotation,\r
742             translation_limit_min,\r
743             translation_limit_max,\r
744             rotation_limit_min,\r
745             rotation_limit_max,\r
746             spring_constant_translation,\r
747             spring_constant_rotation\r
748             ):\r
749         self.name=name\r
750         self.english_name=english_name\r
751         self.joint_type=joint_type\r
752         self.rigidbody_index_a=rigidbody_index_a\r
753         self.rigidbody_index_b=rigidbody_index_b\r
754         self.position=position\r
755         self.rotation=rotation\r
756         self.translation_limit_min=translation_limit_min\r
757         self.translation_limit_max=translation_limit_max\r
758         self.rotation_limit_min=rotation_limit_min\r
759         self.rotation_limit_max=rotation_limit_max\r
760         self.spring_constant_translation=spring_constant_translation\r
761         self.spring_constant_rotation=spring_constant_rotation\r
762 \r
763     def __eq__(self, rhs):\r
764         return (\r
765                 self.name==rhs.name\r
766                 and self.english_name==rhs.english_name\r
767                 and self.joint_type==rhs.joint_type\r
768                 and self.rigidbody_index_a==rhs.rigidbody_index_a\r
769                 and self.rigidbody_index_b==rhs.rigidbody_index_b\r
770                 and self.position==rhs.position\r
771                 and self.rotation==rhs.rotation\r
772                 and self.translation_limit_min==rhs.translation_limit_min\r
773                 and self.translation_limit_max==rhs.translation_limit_max\r
774                 and self.rotation_limit_min==rhs.rotation_limit_min\r
775                 and self.rotation_limit_max==rhs.rotation_limit_max\r
776                 and self.spring_constant_translation==rhs.spring_constant_translation\r
777                 and self.spring_constant_rotation==rhs.spring_constant_rotation\r
778                 )\r
779 \r
780     def __ne__(self, rhs):\r
781         return not self.__eq__(rhs)\r
782 \r
783     def diff(self, rhs):\r
784         self._diff(rhs, 'name')\r
785         self._diff(rhs, 'joint_type')\r
786         self._diff(rhs, 'rigidbody_index_a')\r
787         self._diff(rhs, 'rigidbody_index_b')\r
788         self._diff(rhs, 'position')\r
789         self._diff(rhs, 'rotation')\r
790         self._diff(rhs, 'translation_limit_min')\r
791         self._diff(rhs, 'translation_limit_max')\r
792         self._diff(rhs, 'rotation_limit_min')\r
793         self._diff(rhs, 'rotation_limit_max')\r
794         self._diff(rhs, 'spring_constant_translation')\r
795         self._diff(rhs, 'spring_constant_rotation')\r
796 \r
797 \r
798 class Model(Diff):\r
799     """\r
800     ==========\r
801     pmx model\r
802     ==========\r
803 \r
804     :IVariables:\r
805         version\r
806             pmx version(expected 2.0)\r
807         name \r
808             model name\r
809         english_name \r
810             model name\r
811         comment \r
812             comment\r
813         english_comment \r
814             comment\r
815         vertices\r
816             vertex list\r
817         textures\r
818             texture list\r
819         materials\r
820             material list\r
821         bones\r
822             bone list\r
823         morph\r
824             morph list\r
825         display_slots\r
826             display list for bone/morph grouping\r
827         rigidbodies\r
828             bullet physics rigidbody list\r
829         joints\r
830             bullet physics joint list\r
831     """\r
832     __slots__=[\r
833             'path',\r
834             'version',\r
835             'name',\r
836             'english_name',\r
837             'comment',\r
838             'english_comment',\r
839             'vertices',\r
840             'indices',\r
841             'textures',\r
842             'materials',\r
843             'bones',\r
844             'morphs',\r
845             'display_slots',\r
846             'rigidbodies',\r
847             'joints',\r
848             ]\r
849     def __init__(self, version=2.0):\r
850         self.path=''\r
851         self.version=version\r
852         self.name=''\r
853         self.english_name=''\r
854         self.comment=''\r
855         self.english_comment=''\r
856         self.vertices=[]\r
857         self.indices=[]\r
858         self.textures=[]\r
859         self.materials=[]\r
860         self.bones=[]\r
861         self.morphs=[]\r
862         self.display_slots=[]\r
863         self.rigidbodies=[]\r
864         self.joints=[]\r
865 \r
866     def __str__(self):\r
867         return ('<pmx-{version} "{name}" {vertices}vertices>'.format(\r
868             version=self.version,\r
869             name=self.english_name,\r
870             vertices=len(self.vertices)\r
871             ))\r
872 \r
873     def __eq__(self, rhs):\r
874         return (\r
875                 self.version==rhs.version\r
876                 and self.name==rhs.name\r
877                 and self.english_name==rhs.english_name\r
878                 and self.comment==rhs.comment\r
879                 and self.english_comment==rhs.english_comment\r
880                 and self.vertices==rhs.vertices\r
881                 and self.indices==rhs.indices\r
882                 and self.textures==rhs.textures\r
883                 and self.materials==rhs.materials\r
884                 and self.bones==rhs.bones\r
885                 and self.morphs==rhs.morphs\r
886                 and self.display_slots==rhs.display_slots\r
887                 and self.rigidbodies==rhs.rigidbodies\r
888                 and self.joints==rhs.joints\r
889                 )\r
890 \r
891     def __ne__(self, rhs):\r
892         return not self.__eq__(rhs)\r
893 \r
894     def diff(self, rhs):\r
895         self._diff(rhs, "version")\r
896         self._diff(rhs, "name")\r
897         self._diff(rhs, "english_name")\r
898         self._diff(rhs, "comment")\r
899         self._diff(rhs, "english_comment")\r
900         self._diff_array(rhs, "vertices")\r
901         self._diff_array(rhs, "indices")\r
902         self._diff_array(rhs, "textures")\r
903         self._diff_array(rhs, "materials")\r
904         self._diff_array(rhs, "bones")\r
905         self._diff_array(rhs, "morphs")\r
906         self._diff_array(rhs, "display_slots")\r
907         self._diff_array(rhs, "rigidbodies")\r
908         self._diff_array(rhs, "joints")\r
909 \r