1 #!/usr/bin/env python
\r
4 ========================
\r
5 MikuMikuDance PMX format
\r
6 ========================
\r
10 * PMDEditor's Lib/PMX仕様/PMX仕様.txt
\r
14 * textencoding: unicode
\r
15 * coordinate: left handed y-up(DirectX)
\r
17 * face: only triangle
\r
21 __author__="ousttrue"
\r
23 __versioon__="1.0.0"
\r
29 from .. import common
\r
33 class DifferenceException(Exception):
\r
38 def _diff(self, rhs, key):
\r
39 l=getattr(self, key)
\r
44 raise DifferenceException(key)
\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
55 except DifferenceException as e:
\r
59 raise DifferenceException("{0}: {1}".format(key, e.message))
\r
65 raise DifferenceException("{0}".format(key))
\r
77 def __init__(self, target_index, loop, limit_radian, link=None):
\r
78 self.target_index=target_index
\r
80 self.limit_radian=limit_radian
\r
81 self.link=link or []
\r
83 def __eq__(self, rhs):
\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
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
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
113 def __eq__(self, rhs):
\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
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
158 tail_position=common.Vector3(),
\r
162 fixed_axis=common.Vector3(),
\r
163 local_x_vector=common.Vector3(),
\r
164 local_z_vector=common.Vector3(),
\r
169 self.english_name=english_name
\r
170 self.position=position
\r
171 self.parent_index=parent_index
\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
184 def __eq__(self, rhs):
\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
194 def __ne__(self, rhs):
\r
195 return not self.__eq__(rhs)
\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
215 self._diff(rhs, 'ik')
\r
217 def getConnectionFlag(self):
\r
218 return (self.flag & 0x0001)!=0
\r
220 def getVisibleFlag(self):
\r
221 return (self.flag & 0x0008)!=0
\r
223 def getIkFlag(self):
\r
224 return (self.flag & 0x0020)!=0
\r
226 def getRotationFlag(self):
\r
227 return (self.flag & 0x0100)!=0
\r
229 def getTranslationFlag(self):
\r
230 return (self.flag & 0x0200)!=0
\r
232 def getFixedAxisFlag(self):
\r
233 return (self.flag & 0x0400)!=0
\r
235 def getLocalCoordinateFlag(self):
\r
236 return (self.flag & 0x0800)!=0
\r
238 def getExternalParentDeformFlag(self):
\r
239 return (self.flag & 0x2000)!=0
\r
242 class Material(Diff):
\r
245 Attributes: see __init__
\r
259 'sphere_texture_index',
\r
261 'toon_sharing_flag',
\r
262 'toon_texture_index',
\r
278 sphere_texture_index,
\r
281 toon_texture_index=0,
\r
282 comment=common.unicode(""),
\r
286 self.english_name=english_name
\r
287 self.diffuse_color=diffuse_color
\r
289 self.specular_color=specular_color
\r
290 self.specular_factor=specular_factor
\r
291 self.ambient_color=ambient_color
\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
303 def __eq__(self, rhs):
\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
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
343 def __ne__(self, rhs):
\r
344 return not self.__eq__(rhs)
\r
347 return ("<pmx.Material {name}>".format(
\r
348 name=self.english_name
\r
353 """bone deform. use a weight
\r
355 Attributes: see __init__
\r
357 __slots__=[ 'index0']
\r
358 def __init__(self, index0):
\r
362 return "<Bdef1 {0}>".format(self.index0)
\r
364 def __eq__(self, rhs):
\r
365 return self.index0==rhs.index0
\r
367 def __ne__(self, rhs):
\r
368 return not self.__eq__(rhs)
\r
372 """bone deform. use two weights
\r
374 Attributes: see __init__
\r
376 __slots__=[ 'index0', 'index1', 'weight0']
\r
377 def __init__(self,
\r
383 self.weight0=weight0
\r
386 return "<Bdef2 {0}, {1}, {2}>".format(self.index0, self.index1, self.weight0)
\r
388 def __eq__(self, rhs):
\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
396 def __ne__(self, rhs):
\r
397 return not self.__eq__(rhs)
\r
400 class Vertex(Diff):
\r
414 Bdef1, Bdef2 or Bdef4
\r
418 __slots__=[ 'position', 'normal', 'uv', 'deform', 'edge_factor' ]
\r
419 def __init__(self,
\r
425 self.position=position
\r
429 self.edge_factor=edge_factor
\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
436 def __eq__(self, rhs):
\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
445 def __ne__(self, rhs):
\r
446 return not self.__eq__(rhs)
\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
473 def __init__(self, name, english_name, panel, morph_type, offsets=None):
\r
475 self.english_name=english_name
\r
477 self.morph_type=morph_type
\r
478 self.offsets=offsets or []
\r
480 def __eq__(self, rhs):
\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
489 def __ne__(self, rhs):
\r
490 return not self.__eq__(rhs)
\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
500 class VerexMorphOffset(Diff):
\r
501 """pmx vertex morph offset
\r
505 position_offset: Vector3
\r
511 def __init__(self, vertex_index, position_offset):
\r
512 self.vertex_index=vertex_index
\r
513 self.position_offset=position_offset
\r
515 def __eq__(self, rhs):
\r
517 self.vertex_index==rhs.vertex_index
\r
518 and self.position_offset==rhs.position_offset
\r
521 def __ne__(self, rhs):
\r
522 return not self.__eq__(rhs)
\r
524 def diff(self, rhs):
\r
525 self._diff(rhs, 'vertex_index')
\r
526 self._diff(rhs, 'position_offset')
\r
529 class DisplaySlot(Diff):
\r
530 """pmx display slot
\r
536 references: list of (ref_type, ref_index)
\r
544 def __init__(self, name, english_name, special_flag, references=None):
\r
546 self.english_name=english_name
\r
547 self.special_flag=special_flag
\r
548 self.references=references or []
\r
551 return "<DisplaySlots %s(%d)>" % (self.name, len(self.references))
\r
553 def __eq__(self, rhs):
\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
561 def __ne__(self, rhs):
\r
562 return not self.__eq__(rhs)
\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
571 class RigidBodyParam(Diff):
\r
572 """pmx rigidbody param(for bullet)
\r
588 def __init__(self, mass,
\r
589 linear_damping, angular_damping, restitution, friction):
\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
596 def __eq__(self, rhs):
\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
605 def __ne__(self, rhs):
\r
606 return not self.__eq__(rhs)
\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
616 class RigidBody(Diff):
\r
624 no_collision_group:
\r
634 'no_collision_group',
\r
647 no_collision_group,
\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
673 def __eq__(self, rhs):
\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
686 def __ne__(self, rhs):
\r
687 return not self.__eq__(rhs)
\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
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
725 'rigidbody_index_a',
\r
726 'rigidbody_index_b',
\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
736 def __init__(self, name, english_name,
\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
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
763 def __eq__(self, rhs):
\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
780 def __ne__(self, rhs):
\r
781 return not self.__eq__(rhs)
\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
806 pmx version(expected 2.0)
\r
826 display list for bone/morph grouping
\r
828 bullet physics rigidbody list
\r
830 bullet physics joint list
\r
849 def __init__(self, version=2.0):
\r
851 self.version=version
\r
853 self.english_name=''
\r
855 self.english_comment=''
\r
862 self.display_slots=[]
\r
863 self.rigidbodies=[]
\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
873 def __eq__(self, rhs):
\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
891 def __ne__(self, rhs):
\r
892 return not self.__eq__(rhs)
\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