OSDN Git Service

implement pmx.writer
[meshio/pymeshio.git] / pymeshio / pmx / __init__.py
1 #!/usr/bin/env python\r
2 # coding: utf-8\r
3 """\r
4 pmx file io library.\r
5 \r
6 pmx file format:\r
7     PMDEditor's Lib/PMX仕様/PMX仕様.txt\r
8 """\r
9 __author__="ousttrue"\r
10 __license__="zlib"\r
11 __versioon__="1.0.0"\r
12 \r
13 \r
14 import io\r
15 import os\r
16 import struct\r
17 from pymeshio import common\r
18 \r
19 \r
20 \r
21 class Ik(object):\r
22     """ik info\r
23     """\r
24     __slots__=[\r
25             'target_index',\r
26             'loop',\r
27             'limit_radian',\r
28             'link',\r
29             ]\r
30     def __init__(self, target_index, loop, limit_radian):\r
31         self.target_index=target_index\r
32         self.loop=loop\r
33         self.limit_radian=limit_radian\r
34         self.link=[]\r
35 \r
36 \r
37 class IkLink(object):\r
38     """ik link info\r
39     """\r
40     __slots__=[\r
41             'bone_index',\r
42             'limit_angle',\r
43             'limit_min',\r
44             'limit_max',\r
45             ]\r
46     def __init__(self, bone_index, limit_angle):\r
47         self.bone_index=bone_index\r
48         self.limit_angle=limit_angle\r
49         self.limit_min=None\r
50         self.limit_max=None\r
51 \r
52 \r
53 class Bone(object):\r
54     """material\r
55 \r
56     Bone: see __init__\r
57     """\r
58     __slots__=[\r
59             'name',\r
60             'english_name',\r
61             'position',\r
62             'parent_index',\r
63             'layer',\r
64             'flag',\r
65 \r
66             'tail_positoin',\r
67             'tail_index',\r
68             'effect_index',\r
69             'effect_factor',\r
70             'fixed_axis',\r
71             'local_x_vector',\r
72             'local_z_vector',\r
73             'external_key',\r
74             'ik',\r
75             ]\r
76     def __init__(self,\r
77             name,\r
78             english_name,\r
79             position,\r
80             parent_index,\r
81             layer,\r
82             flag\r
83             ):\r
84         self.name=name\r
85         self.english_name=english_name\r
86         self.position=position\r
87         self.parent_index=parent_index\r
88         self.layer=layer\r
89         self.flag=flag\r
90 \r
91     def __eq__(self, rhs):\r
92         return (\r
93                 self.name==rhs.name\r
94                 and self.english_name==rhs.english_name\r
95                 and self.position==rhs.position\r
96                 and self.parent_index==rhs.parent_index\r
97                 and self.layer==rhs.layer\r
98                 and self.flag==rhs.flag\r
99                 )\r
100 \r
101     def getConnectionFlag(self):\r
102         return self.flag & 0x0001\r
103 \r
104     def getIkFlag(self):\r
105         return (self.flag & 0x0020) >> 5\r
106 \r
107     def getRotationFlag(self):\r
108         return (self.flag & 0x0100) >> 8\r
109 \r
110     def getTranslationFlag(self):\r
111         return (self.flag & 0x0200) >> 9\r
112 \r
113     def getFixedAxisFlag(self):\r
114         return (self.flag & 0x0400) >> 10\r
115 \r
116     def getLocalCoordinateFlag(self):\r
117         return (self.flag &  0x0800) >> 11\r
118     \r
119     def getExternalParentDeformFlag(self):\r
120         return (self.flag &  0x2000) >> 13\r
121 \r
122  \r
123 class Material(object):\r
124     """material\r
125 \r
126     Attributes: see __init__\r
127     """\r
128     __slots__=[\r
129             'name',\r
130             'english_name',\r
131             'diffuse_color',\r
132             'alpha',\r
133             'specular_color',\r
134             'specular_factor',\r
135             'ambient_color',\r
136             'flag',\r
137             'edge_color',\r
138             'edge_size',\r
139             'texture_index',\r
140             'sphere_texture_index',\r
141             'sphere_mode',\r
142             'toon_sharing_flag',\r
143             'toon_texture_index',\r
144             'comment',\r
145             'vertex_count',\r
146             ]\r
147     def __init__(self,\r
148             name,\r
149             english_name,\r
150             diffuse_color,\r
151             alpha,\r
152             specular_color,\r
153             specular_factor,\r
154             ambient_color,\r
155             flag,\r
156             edge_color,\r
157             edge_size,\r
158             texture_index,\r
159             sphere_texture_index,\r
160             sphere_mode,\r
161             toon_sharing_flag\r
162             ):\r
163         self.name=name\r
164         self.english_name=english_name\r
165         self.diffuse_color=diffuse_color\r
166         self.alpha=alpha\r
167         self.specular_color=specular_color\r
168         self.specular_factor=specular_factor\r
169         self.ambient_color=ambient_color\r
170         self.flag=flag\r
171         self.edge_color=edge_color\r
172         self.edge_size=edge_size\r
173         self.texture_index=texture_index\r
174         self.sphere_texture_index=sphere_texture_index\r
175         self.sphere_mode=sphere_mode\r
176         self.toon_sharing_flag=toon_sharing_flag\r
177         #\r
178         self.toon_texture_index=None\r
179         self.comment=name.__class__() # unicode\r
180         self.vertex_count=0\r
181 \r
182     def __eq__(self, rhs):\r
183         return (\r
184                 self.name==rhs.name\r
185                 and self.english_name==rhs.english_name\r
186                 and self.diffuse_color==rhs.diffuse_color\r
187                 and self.alpha==rhs.alpha\r
188                 and self.specular_color==rhs.specular_color\r
189                 and self.specular_factor==rhs.specular_factor\r
190                 and self.ambient_color==rhs.ambient_color\r
191                 and self.flag==rhs.flag\r
192                 and self.edge_color==rhs.edge_color\r
193                 and self.edge_size==rhs.edge_size\r
194                 and self.texture_index==rhs.texture_index\r
195                 and self.sphere_texture_index==rhs.sphere_texture_index\r
196                 and self.sphere_mode==rhs.sphere_mode\r
197                 and self.toon_sharing_flag==rhs.toon_sharing_flag\r
198                 and self.toon_texture_index==rhs.toon_texture_index\r
199                 and self.comment==rhs.comment\r
200                 and self.vertex_count==rhs.vertex_count\r
201                 )\r
202 \r
203     def __str__(self):\r
204         return ("<pmx.Material {name}>".format(\r
205             name=self.english_name\r
206             ))\r
207 \r
208 \r
209 class Deform(object):\r
210     pass\r
211 \r
212 \r
213 class Bdef1(object):\r
214     """bone deform. use a weight\r
215 \r
216     Attributes: see __init__\r
217     """\r
218     __slots__=[ 'index0']\r
219     def __init__(self, index0):\r
220         self.index0=index0\r
221 \r
222     def __eq__(self, rhs):\r
223         return self.index0==rhs.index0\r
224 \r
225 \r
226 class Bdef2(object):\r
227     """bone deform. use two weights\r
228 \r
229     Attributes: see __init__\r
230     """\r
231     __slots__=[ 'index0', 'index1', 'weight0']\r
232     def __init__(self, \r
233             index0,\r
234             index1,\r
235             weight0):\r
236         self.index0=index0\r
237         self.index1=index1\r
238         self.weight0=weight0\r
239 \r
240     def __eq__(self, rhs):\r
241         return (\r
242                 self.index0==rhs.index0\r
243                 and self.index1==rhs.index1\r
244                 and self.weight0==rhs.weight0\r
245                 )\r
246 \r
247 \r
248 class Vertex(object):\r
249     """pmx vertex\r
250 \r
251     Attributes: see __init__\r
252     """\r
253     __slots__=[ 'position', 'normal', 'uv', 'deform', 'edge_factor' ]\r
254     def __init__(self, \r
255             position, \r
256             normal, \r
257             uv, \r
258             deform, \r
259             edge_factor):\r
260         self.position=position \r
261         self.normal=normal\r
262         self.uv=uv\r
263         self.deform=deform\r
264         self.edge_factor=edge_factor\r
265 \r
266     def __eq__(self, rhs):\r
267         return (\r
268                 self.position==rhs.position\r
269                 and self.normal==rhs.normal\r
270                 and self.uv==rhs.uv\r
271                 and self.deform==rhs.deform\r
272                 and self.edge_factor==rhs.edge_factor\r
273                 )\r
274 \r
275 \r
276 class Morph(object):\r
277     """pmx morph\r
278 \r
279     Attributes:\r
280         name: \r
281         english_name: \r
282         panel:\r
283         morph_type:\r
284         offsets:\r
285     """\r
286     __slots__=[\r
287             'name',\r
288             'english_name',\r
289             'panel',\r
290             'morph_type',\r
291             'offsets',\r
292             ]\r
293     def __init__(self, name, english_name, panel, morph_type):\r
294         self.name=name\r
295         self.english_name=english_name\r
296         self.panel=panel\r
297         self.morph_type=morph_type\r
298         self.offsets=[]\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.panel==rhs.panel\r
305                 and self.morph_type==rhs.morph_type\r
306                 and self.offsets==rhs.offsets\r
307                 )\r
308 \r
309 \r
310 class VerexMorphOffset(object):\r
311     """pmx vertex morph offset\r
312 \r
313     Attributes:\r
314         vertex_index:\r
315         position_offset: Vector3\r
316     """\r
317     __slots__=[\r
318             'vertex_index',\r
319             'position_offset',\r
320             ]\r
321     def __init__(self, vertex_index, position_offset):\r
322         self.vertex_index=vertex_index\r
323         self.position_offset=position_offset\r
324 \r
325     def __eq__(self, rhs):\r
326         return (\r
327                 self.vertex_index==rhs.vertex_index \r
328                 and self.position_offset==rhs.position_offset\r
329                 )\r
330 \r
331 \r
332 class DisplaySlot(object):\r
333     """pmx display slot\r
334 \r
335     Attributes:\r
336         name: \r
337         english_name: \r
338         special_flag:\r
339         refrences: list of (ref_type, ref_index)\r
340     """\r
341     __slots__=[\r
342             'name',\r
343             'english_name',\r
344             'special_flag',\r
345             'refrences',\r
346             ]\r
347     def __init__(self, name, english_name, special_flag):\r
348         self.name=name\r
349         self.english_name=english_name\r
350         self.special_flag=special_flag\r
351         self.refrences=[]\r
352 \r
353     def __eq__(self, rhs):\r
354         return (\r
355                 self.name==rhs.name\r
356                 and self.english_name==rhs.english_name\r
357                 and self.special_flag==rhs.special_flag\r
358                 and self.refrences==rhs.refrences\r
359                 )\r
360 \r
361 \r
362 class RigidBodyParam(object):\r
363     """pmx rigidbody param(for bullet)\r
364 \r
365     Attributes:\r
366         mass:\r
367         linear_damping:\r
368         angular_damping:\r
369         restitution:\r
370         friction:\r
371     """\r
372     __slots__=[\r
373             'mass',\r
374             'linear_damping',\r
375             'angular_damping',\r
376             'restitution',\r
377             'friction',\r
378             ]\r
379     def __init__(self, mass, \r
380             linear_damping, angular_damping, restitution, friction):\r
381         self.mass=mass\r
382         self.linear_damping=linear_damping\r
383         self.angular_damping=angular_damping\r
384         self.restitution=restitution\r
385         self.friction=friction\r
386 \r
387     def __eq__(self, rhs):\r
388         return (\r
389                 self.mass==rhs.mass\r
390                 and self.linear_damping==rhs.linear_damping\r
391                 and self.angular_damping==rhs.angular_damping\r
392                 and self.restitution==rhs.restitution\r
393                 and self.friction==rhs.friction\r
394                 )\r
395 \r
396 \r
397 class RigidBody(object):\r
398     """pmx rigidbody\r
399 \r
400     Attributes:\r
401         name: \r
402         english_name: \r
403         bone_index:\r
404         collision_group:\r
405         no_collision_group:\r
406         shape:\r
407         param:\r
408         mode:\r
409     """\r
410     __slots__=[\r
411             'name',\r
412             'english_name',\r
413             'bone_index',\r
414             'collision_group',\r
415             'no_collision_group',\r
416             'shape_type',\r
417             'shape_size',\r
418             'shape_position',\r
419             'shape_rotation',\r
420             'param',\r
421             'mode',\r
422             ]\r
423     def __init__(self,\r
424             name,\r
425             english_name,\r
426             bone_index,\r
427             collision_group,\r
428             no_collision_group,\r
429             shape_type,\r
430             shape_size,\r
431             shape_position,\r
432             shape_rotation,\r
433             mass,\r
434             linear_damping,\r
435             angular_damping,\r
436             restitution,\r
437             friction,\r
438             mode\r
439             ):\r
440         self.name=name\r
441         self.english_name=english_name\r
442         self.bone_index=bone_index\r
443         self.collision_group=collision_group\r
444         self.no_collision_group=no_collision_group\r
445         self.shape_type=shape_type\r
446         self.shape_size=shape_size\r
447         self.shape_position=shape_position\r
448         self.shape_rotation=shape_rotation\r
449         self.param=RigidBodyParam(mass,\r
450                 linear_damping, angular_damping,\r
451                 restitution, friction)\r
452         self.mode=mode\r
453 \r
454     def __eq__(self, rhs):\r
455         return (\r
456                 self.name==rhs.name\r
457                 and self.english_name==rhs.english_name\r
458                 and self.bone_index==rhs.bone_index\r
459                 and self.collision_group==rhs.collision_group\r
460                 and self.no_collision_group==rhs.no_collision_group\r
461                 and self.shape_type==rhs.shape_type\r
462                 and self.shape_size==rhs.shape_size\r
463                 and self.param==rhs.param\r
464                 and self.mode==rhs.mode\r
465                 )\r
466 \r
467 \r
468 class Joint(object):\r
469     """pmx joint\r
470 \r
471     Attributes:\r
472         name: \r
473         english_name: \r
474         joint_type:\r
475         rigidbody_index_a:\r
476         rigidbody_index_b:\r
477         position: Vector3\r
478         rotation: Vector3\r
479         translation_limit_min: Vector3\r
480         translation_limit_max: Vector3\r
481         rotation_limit_min: Vector3\r
482         rotation_limit_max: Vector3\r
483         spring_constant_translation: Vector3\r
484         spring_constant_rotation: Vector3\r
485     """\r
486     __slots__=[\r
487             'name',\r
488             'english_name',\r
489             'joint_type',\r
490             'rigidbody_index_a',\r
491             'rigidbody_index_b',\r
492             'position',\r
493             'rotation',\r
494             'translation_limit_min',\r
495             'translation_limit_max',\r
496             'rotation_limit_min',\r
497             'rotation_limit_max',\r
498             'spring_constant_translation',\r
499             'spring_constant_rotation',\r
500             ]\r
501     def __init__(self, name, english_name,\r
502             joint_type,\r
503             rigidbody_index_a,\r
504             rigidbody_index_b,\r
505             position,\r
506             rotation,\r
507             translation_limit_min,\r
508             translation_limit_max,\r
509             rotation_limit_min,\r
510             rotation_limit_max,\r
511             spring_constant_translation,\r
512             spring_constant_rotation\r
513             ):\r
514         self.name=name\r
515         self.english_name=english_name\r
516         self.joint_type=joint_type\r
517         self.rigidbody_index_a=rigidbody_index_a\r
518         self.rigidbody_index_b=rigidbody_index_b\r
519         self.position=position\r
520         self.rotation=rotation\r
521         self.translation_limit_min=translation_limit_min\r
522         self.translation_limit_max=translation_limit_max\r
523         self.rotation_limit_min=rotation_limit_min\r
524         self.rotation_limit_max=rotation_limit_max\r
525         self.spring_constant_translation=spring_constant_translation\r
526         self.spring_constant_rotation=spring_constant_rotation\r
527 \r
528     def __eq__(self, rhs):\r
529         return (\r
530                 self.name==rhs.name\r
531                 and self.english_name==rhs.english_name\r
532                 and self.joint_type==rhs.joint_type\r
533                 and self.rigidbody_index_a==rhs.rigidbody_index_a\r
534                 and self.rigidbody_index_b==rhs.rigidbody_index_b\r
535                 and self.position==rhs.position\r
536                 and self.rotation==rhs.rotation\r
537                 and self.translation_limit_min==rhs.translation_limit_min\r
538                 and self.translation_limit_max==rhs.translation_limit_max\r
539                 and self.rotation_limit_min==rhs.rotation_limit_min\r
540                 and self.rotation_limit_max==rhs.rotation_limit_max\r
541                 and self.spring_constant_translation==rhs.spring_constant_translation\r
542                 and self.spring_constant_rotation==rhs.spring_constant_rotation\r
543                 )\r
544 \r
545 \r
546 class Model(object):\r
547     """pmx data representation\r
548 \r
549     Attributes:\r
550         version: pmx version(expected 2.0)\r
551         name: \r
552         english_name: \r
553         comment: \r
554         english_comment: \r
555         vertices:\r
556         textures:\r
557         materials:\r
558         bones:\r
559         morph:\r
560         display_slots:\r
561         rigidbodies:\r
562         joints:\r
563     """\r
564     __slots__=[\r
565             'version', # pmx version\r
566             'name', # model name\r
567             'english_name', # model name in english\r
568             'comment', # model comment\r
569             'english_comment', # model comment in english\r
570             'vertices',\r
571             'indices',\r
572             'textures',\r
573             'materials',\r
574             'bones',\r
575             'morphs',\r
576             'display_slots',\r
577             'rigidbodies',\r
578             'joints',\r
579             ]\r
580     def __init__(self, version):\r
581         self.version=version\r
582         self.name=''\r
583         self.english_name=''\r
584         self.comment=''\r
585         self.english_comment=''\r
586         self.vertices=[]\r
587         self.indices=[]\r
588         self.textures=[]\r
589         self.materials=[]\r
590         self.bones=[]\r
591         self.morphs=[]\r
592         self.display_slots=[]\r
593         self.rigidbodies=[]\r
594         self.joints=[]\r
595 \r
596     def __str__(self):\r
597         return ('<pmx-{version} "{name}" {vertices}vertices>'.format(\r
598             version=self.version,\r
599             name=self.english_name,\r
600             vertices=len(self.vertices)\r
601             ))\r
602 \r
603     def __eq__(self, rhs):\r
604         return (\r
605                 self.version==rhs.version\r
606                 and self.name==rhs.name\r
607                 and self.english_name==rhs.english_name\r
608                 and self.comment==rhs.comment\r
609                 and self.english_comment==rhs.english_comment\r
610                 and self.vertices==rhs.vertices\r
611                 and self.indices==rhs.indices\r
612                 and self.textures==rhs.textures\r
613                 and self.materials==rhs.materials\r
614                 and self.bones==rhs.bones\r
615                 and self.morphs==rhs.morphs\r
616                 and self.display_slots==rhs.display_slots\r
617                 and self.rigidbodies==rhs.rigidbodies\r
618                 and self.joints==rhs.joints\r
619                 )\r
620 \r