4 * License : The MIT License
5 * Copyright(c) 2010 MikuToga Partners
8 package jp.sfjp.mikutoga.pmd.xml101009;
10 import java.awt.Color;
11 import java.io.IOException;
12 import java.io.OutputStream;
13 import java.util.List;
15 import jp.sourceforge.mikutoga.corelib.I18nText;
16 import jp.sourceforge.mikutoga.math.MkPos2D;
17 import jp.sourceforge.mikutoga.math.MkPos3D;
18 import jp.sourceforge.mikutoga.math.MkVec3D;
19 import jp.sourceforge.mikutoga.pmd.BoneType;
20 import jp.sourceforge.mikutoga.pmd.Deg3d;
21 import jp.sourceforge.mikutoga.pmd.MorphType;
22 import jp.sourceforge.mikutoga.pmd.Rad3d;
23 import jp.sourceforge.mikutoga.pmd.RigidShapeType;
24 import jp.sourceforge.mikutoga.pmd.TripletRange;
25 import jp.sourceforge.mikutoga.pmd.model.BoneGroup;
26 import jp.sourceforge.mikutoga.pmd.model.BoneInfo;
27 import jp.sourceforge.mikutoga.pmd.model.DynamicsInfo;
28 import jp.sourceforge.mikutoga.pmd.model.IKChain;
29 import jp.sourceforge.mikutoga.pmd.model.JointInfo;
30 import jp.sourceforge.mikutoga.pmd.model.Material;
31 import jp.sourceforge.mikutoga.pmd.model.MorphPart;
32 import jp.sourceforge.mikutoga.pmd.model.MorphVertex;
33 import jp.sourceforge.mikutoga.pmd.model.PmdModel;
34 import jp.sourceforge.mikutoga.pmd.model.RigidGroup;
35 import jp.sourceforge.mikutoga.pmd.model.RigidInfo;
36 import jp.sourceforge.mikutoga.pmd.model.RigidShape;
37 import jp.sourceforge.mikutoga.pmd.model.SerialNumbered;
38 import jp.sourceforge.mikutoga.pmd.model.ShadeInfo;
39 import jp.sourceforge.mikutoga.pmd.model.Surface;
40 import jp.sourceforge.mikutoga.pmd.model.ToonMap;
41 import jp.sourceforge.mikutoga.pmd.model.Vertex;
42 import jp.sourceforge.mikutoga.xml.BasicXmlExporter;
43 import jp.sourceforge.mikutoga.xml.XmlResourceResolver;
46 * 101009形式XMLでPMDモデルデータを出力する。
48 public class Xml101009Exporter extends BasicXmlExporter{
50 private static final String TOP_COMMENT =
52 + " model-data(*.pmd) on XML";
55 private static final String CR = "\r"; // 0x0d
57 private static final String LF = "\n"; // 0x0a
59 private static final String CRLF = CR + LF; // 0x0d, 0x0a
61 private static final String PFX_SURFACEGROUP = "sg";
62 private static final String PFX_TOONFILE = "tf";
63 private static final String PFX_VERTEX = "vtx";
64 private static final String PFX_BONE = "bn";
65 private static final String PFX_RIGID = "rd";
66 private static final String PFX_RIGIDGROUP = "rg";
68 private static final String BONETYPE_COMMENT =
70 + "[0 : ROTATE : Rotate : 回転 :]\n"
71 + "[1 : ROTMOV : Rotate/Move : 回転/移動 :]\n"
72 + "[2 : IK : IK : IK :]\n"
73 + "[3 : UNKNOWN : Unknown : 不明 :]\n"
74 + "[4 : UNDERIK : Under IK : IK影響下(回転) :]\n"
75 + "[5 : UNDERROT : Under rotate : 回転影響下 :]\n"
76 + "[6 : IKCONNECTED : IK connected : IK接続先 :]\n"
77 + "[7 : HIDDEN : Hidden : 非表示 :]\n"
78 + "[8 : TWIST : Twist : 捩り :]\n"
79 + "[9 : LINKEDROT : Linked Rotate: 回転連動 :]\n";
81 private static final String MORPHTYPE_COMMENT =
83 + "[1 : EYEBROW : まゆ ]\n"
85 + "[3 : LIP : リップ ]\n"
86 + "[4 : EXTRA : その他 ]\n";
88 private static final String RIGIDBEHAVIOR_COMMENT =
89 "Rigid behavior types:\n"
90 + "[0 : FOLLOWBONE : ボーン追従 ]\n"
91 + "[1 : ONLYDYNAMICS : 物理演算 ]\n"
92 + "[2 : BONEDDYNAMICS : ボーン位置合わせ ]\n";
94 private String generator = null;
98 * 文字エンコーディングはUTF-8が用いられる。
99 * @param stream 出力ストリーム
101 public Xml101009Exporter(OutputStream stream){
107 * Generatorメタ情報を設定する。
108 * @param generatorArg Generatorメタ情報。表示したくないときはnull
110 public void setGenerator(String generatorArg){
111 this.generator = generatorArg;
116 * 任意の文字列がBasicLatin文字のみから構成されるか判定する。
118 * @return null、長さ0もしくはBasicLatin文字のみから構成されるならtrue
120 public static boolean hasOnlyBasicLatin(CharSequence seq){
121 if(seq == null) return true;
122 int length = seq.length();
123 for(int pos = 0; pos < length; pos++){
124 char ch = seq.charAt(pos);
125 if(ch > 0x007f) return false;
132 * @return {@inheritDoc}
133 * @throws IOException {@inheritDoc}
136 public Xml101009Exporter ind() throws IOException{
142 * 文字参照によるエスケープを補佐するためのコメントを出力する。
145 * @throws IOException 出力エラー
147 protected Xml101009Exporter putUnescapedComment(CharSequence seq)
149 if( ! isBasicLatinOnlyOut() ) return this;
150 if(hasOnlyBasicLatin(seq)) return this;
151 sp().putLineComment(seq);
160 * @throws IOException 出力エラー
162 protected Xml101009Exporter putI18nName(I18nText text) throws IOException{
163 for(String lang639 : text.lang639CodeList()){
164 if(lang639.equals(I18nText.CODE639_PRIMARY)) continue;
165 String name = text.getI18nText(lang639);
166 ind().putRawText("<i18nName ");
167 putAttr("lang", lang639).sp();
168 putAttr("name", name);
170 putUnescapedComment(name);
177 * 番号付けされたID(IDREF)属性を出力する。
178 * @param attrName 属性名
179 * @param prefix IDプレフィクス
182 * @throws IOException 出力エラー
184 protected Xml101009Exporter putNumberedIdAttr(CharSequence attrName,
188 putRawText(attrName).putRawText("=\"");
189 putRawText(prefix).putXsdInt(num);
195 * 番号付けされたID(IDREF)属性を出力する。
196 * @param attrName 属性名
197 * @param prefix IDプレフィクス
198 * @param numbered 番号付けされたオブジェクト
200 * @throws IOException 出力エラー
202 protected Xml101009Exporter putNumberedIdAttr(CharSequence attrName,
204 SerialNumbered numbered )
206 putNumberedIdAttr(attrName, prefix, numbered.getSerialNumber());
212 * @param position 位置情報
214 * @throws IOException 出力エラー
216 protected Xml101009Exporter putPosition(MkPos3D position)
218 putRawText("<position ");
219 putFloatAttr("x", (float) position.getXpos()).sp();
220 putFloatAttr("y", (float) position.getYpos()).sp();
221 putFloatAttr("z", (float) position.getZpos()).sp();
228 * @param rotation 姿勢情報
230 * @throws IOException 出力エラー
232 protected Xml101009Exporter putRadRotation(Rad3d rotation)
234 putRawText("<radRotation ");
235 putFloatAttr("xRad", rotation.getXRad()).sp();
236 putFloatAttr("yRad", rotation.getYRad()).sp();
237 putFloatAttr("zRad", rotation.getZRad()).sp();
243 * 多言語識別名属性のローカルな名前をコメント出力する。
246 * @throws IOException 出力エラー
248 protected Xml101009Exporter putLocalNameComment(I18nText name)
250 String localName = name.getText();
251 if(localName.isEmpty()){
252 localName = "[NAMELESS]";
254 ind().putLineComment(localName);
259 * 多言語識別名属性のプライマリな名前を出力する。
260 * @param attrName 属性名
263 * @throws IOException 出力エラー
265 protected Xml101009Exporter putPrimaryNameAttr(CharSequence attrName,
268 String primaryName = name.getPrimaryText();
269 putAttr(attrName, primaryName);
274 * PMDモデルデータをXML形式で出力する。
275 * @param model PMDモデルデータ
276 * @throws IOException 出力エラー
278 public void putPmdModel(PmdModel model) throws IOException{
279 ind().putRawText("<?xml")
280 .sp().putAttr("version","1.0")
281 .sp().putAttr("encoding","UTF-8")
282 .sp().putRawText("?>").ln(2);
284 ind().putBlockComment(TOP_COMMENT).ln(2);
286 I18nText modelName = model.getModelName();
287 ind().putLocalNameComment(modelName).ln();
288 ind().putRawText("<pmdModel").ln();
291 ind().putAttr("xmlns", Xml101009Resources.NS_PMDXML).ln();
292 ind().putAttr("xmlns:xsi", XmlResourceResolver.NS_XSD).ln();
294 ind().putRawText("xsi:schemaLocation").putRawText("=\"");
295 putRawText(Xml101009Resources.NS_PMDXML).ln();
297 ind().putRawText(Xml101009Resources.SCHEMA_PMDXML).putRawCh('"').ln();
300 ind().putAttr("schemaVersion", Xml101009Resources.VER_PMDXML).ln(2);
301 ind().putPrimaryNameAttr("name", modelName).ln();
304 putRawText(">").ln(2);
306 putModelInfo(model).flush();
307 putMetaInfo(model).flush();
308 putMaterialList(model).flush();
309 putToonMap(model).flush();
310 putBoneList(model).flush();
311 putBoneGroupList(model).flush();
312 putIKChainList(model).flush();
313 putMorphList(model).flush();
314 putRigidList(model).flush();
315 putRigidGroupList(model).flush();
316 putJointList(model).flush();
317 putSurfaceGroupList(model).flush();
318 putVertexList(model).flush();
320 ind().putRawText("</pmdModel>").ln(2);
321 ind().putRawText("<!-- EOF -->").ln();
330 * @throws IOException 出力エラー
332 private Xml101009Exporter putModelInfo(PmdModel model)
334 I18nText modelName = model.getModelName();
335 putI18nName(modelName);
338 I18nText description = model.getDescription();
339 for(String lang639 : description.lang639CodeList()){
340 String descText = description.getI18nText(lang639);
341 putDescription(lang639, descText);
350 * @param lang639 言語コード
351 * @param content 詳細内容
353 * @throws IOException 出力エラー
355 private Xml101009Exporter putDescription(CharSequence lang639,
356 CharSequence content)
358 String text = content.toString();
359 text = text.replace(CRLF, LF);
360 text = text.replace(CR, LF);
362 ind().putRawText("<description");
363 if( ! I18nText.CODE639_PRIMARY.equals(lang639) ){
364 sp().putAttr("lang", lang639).sp();
366 putRawText(">").ln();
368 putBRedContent(text);
370 ind().putRawText("</description>").ln();
372 if( ! hasOnlyBasicLatin(text) && isBasicLatinOnlyOut() ){
373 putBlockComment(text);
380 * break要素を含む要素内容を出力する。
381 * 必要に応じてXML定義済み実体文字が割り振られた文字、
382 * コントロールコード、および非BasicLatin文字がエスケープされる。
386 * @throws IOException 出力エラー
388 protected BasicXmlExporter putBRedContent(CharSequence content)
390 int length = content.length();
394 for(int idx = 0; idx < length; idx++){
395 char ch = content.charAt(idx);
397 CharSequence seq = content.subSequence(startPos, idx);
398 putContent(seq).putRawText("<br/>").ln();
403 if(startPos < length){
404 CharSequence seq = content.subSequence(startPos, length);
405 putContent(seq).ln();
413 * @param model モデルデータ
415 * @throws IOException 出力エラー
417 private Xml101009Exporter putMetaInfo(PmdModel model) throws IOException{
418 ind().putRawText("<license>").ln();
419 ind().putRawText("</license>").ln(2);
421 ind().putRawText("<credits>").ln();
422 ind().putRawText("</credits>").ln(2);
424 if(this.generator != null){
425 ind().putRawText("<meta ");
426 putAttr("name", "generator").sp()
427 .putAttr("content", this.generator);
428 putRawText(" />").ln();
431 ind().putRawText("<meta ");
432 putAttr("name", "siteURL").sp().putAttr("content", "");
433 putRawText(" />").ln();
434 ind().putRawText("<meta ");
435 putAttr("name", "imageURL").sp().putAttr("content", "");
436 putRawText(" />").ln(2);
443 * @param model モデルデータ
445 * @throws IOException 出力エラー
447 private Xml101009Exporter putMaterialList(PmdModel model)
449 ind().putRawText("<materialList>").ln();
453 boolean dumped = false;
454 List<Material> materialList = model.getMaterialList();
455 for(Material material : materialList){
457 putMaterial(material, ct++);
462 ind().putRawText("</materialList>").ln(2);
469 * @param material マテリアル素材
470 * @param no マテリアル通し番号
472 * @throws IOException 出力エラー
474 private Xml101009Exporter putMaterial(Material material, int no)
477 if(material.getEdgeAppearance()) bool = "true";
479 I18nText name = material.getMaterialName();
480 String primary = name.getPrimaryText();
481 String local = name.getText();
483 if(local != null && local.length() > 0){
484 ind().putLineComment(local).ln();
486 ind().putRawText("<material ");
487 if(primary != null && primary.length() > 0){
488 putAttr("name", primary).sp();
491 putAttr("showEdge", bool);
493 putNumberedIdAttr("surfaceGroupIdRef", PFX_SURFACEGROUP, no);
494 sp().putRawCh('>').ln();
499 float[] rgba = new float[4];
501 Color diffuse = material.getDiffuseColor();
502 diffuse.getRGBComponents(rgba);
503 ind().putRawText("<diffuse ");
504 putFloatAttr("r", rgba[0]).sp();
505 putFloatAttr("g", rgba[1]).sp();
506 putFloatAttr("b", rgba[2]).sp();
507 putFloatAttr("alpha", rgba[3]).sp();
508 putRawText("/>").ln();
510 Color specular = material.getSpecularColor();
511 specular.getRGBComponents(rgba);
512 float shininess = material.getShininess();
513 ind().putRawText("<specular ");
514 putFloatAttr("r", rgba[0]).sp();
515 putFloatAttr("g", rgba[1]).sp();
516 putFloatAttr("b", rgba[2]).sp();
517 putFloatAttr("shininess", shininess).sp();
518 putRawText("/>").ln();
520 Color ambient = material.getAmbientColor();
521 ambient.getRGBComponents(rgba);
522 ind().putRawText("<ambient ");
523 putFloatAttr("r", rgba[0]).sp();
524 putFloatAttr("g", rgba[1]).sp();
525 putFloatAttr("b", rgba[2]).sp();
526 putRawText("/>").ln();
528 ShadeInfo shade = material.getShadeInfo();
529 String textureFileName = shade.getTextureFileName();
530 String spheremapFileName = shade.getSpheremapFileName();
532 if(shade.isValidToonIndex()){
533 ind().putRawText("<toon ");
534 int toonIdx = shade.getToonIndex();
535 putNumberedIdAttr("toonFileIdRef", PFX_TOONFILE, toonIdx);
537 String toonFileName = shade.getToonFileName();
538 if(toonFileName != null && toonFileName.length() > 0){
539 sp().putLineComment(toonFileName);
544 if(textureFileName != null && textureFileName.length() > 0){
545 ind().putRawText("<textureFile ");
546 putAttr("winFileName", textureFileName);
547 putRawText(" />").ln();
550 if(spheremapFileName != null && spheremapFileName.length() > 0){
551 ind().putRawText("<spheremapFile ");
552 putAttr("winFileName", spheremapFileName);
553 putRawText(" />").ln();
557 ind().putRawText("</material>").ln(2);
563 * トゥーンファイルマッピング情報を出力する。
564 * @param model モデルデータ
566 * @throws IOException 出力エラー
568 private Xml101009Exporter putToonMap(PmdModel model)
570 ind().putRawText("<toonMap>").ln();
573 ToonMap map = model.getToonMap();
574 for(int index = 0; index <= 9; index++){
575 ind().putToon(map, index).ln();
579 ind().putRawText("</toonMap>").ln(2);
584 * 個別のトゥーンファイル情報を出力する。
586 * @param index インデックス値
588 * @throws IOException 出力エラー
590 private Xml101009Exporter putToon(ToonMap map, int index)
592 putRawText("<toonDef ");
593 putNumberedIdAttr("toonFileId", PFX_TOONFILE, index).sp();
594 putIntAttr("index", index).sp();
595 String toonFile = map.getIndexedToon(index);
596 putAttr("winFileName", toonFile);
598 putUnescapedComment(toonFile);
603 * サーフェイスグループリストを出力する。
604 * @param model モデルデータ
606 * @throws IOException 出力エラー
608 private Xml101009Exporter putSurfaceGroupList(PmdModel model)
610 ind().putRawText("<surfaceGroupList>").ln();
614 boolean dumped = false;
615 List<Material> materialList = model.getMaterialList();
616 for(Material material : materialList){
617 List<Surface> surfaceList = material.getSurfaceList();
619 putSurfaceList(surfaceList, ct++);
624 ind().putRawText("</surfaceGroupList>").ln(2);
630 * 個別のサーフェイスグループを出力する。
631 * @param surfaceList サーフェイスのリスト
632 * @param index グループインデックス
634 * @throws IOException 出力エラー
636 private Xml101009Exporter putSurfaceList(List<Surface> surfaceList,
639 ind().putRawText("<surfaceGroup ");
640 putNumberedIdAttr("surfaceGroupId", PFX_SURFACEGROUP, index);
641 sp().putRawText(">").ln();
644 for(Surface surface : surfaceList){
649 ind().putRawText("</surfaceGroup>").ln(2);
656 * @param surface サーフェイス
658 * @throws IOException 出力エラー
660 private Xml101009Exporter putSurface(Surface surface)
662 ind().putRawText("<surface ");
664 Vertex vertex1 = surface.getVertex1();
665 Vertex vertex2 = surface.getVertex2();
666 Vertex vertex3 = surface.getVertex3();
668 putNumberedIdAttr("vtxIdRef1", PFX_VERTEX, vertex1).sp();
669 putNumberedIdAttr("vtxIdRef2", PFX_VERTEX, vertex2).sp();
670 putNumberedIdAttr("vtxIdRef3", PFX_VERTEX, vertex3).sp();
672 putRawText("/>").ln();
678 * @param model モデルデータ
680 * @throws IOException 出力エラー
682 private Xml101009Exporter putVertexList(PmdModel model)
684 ind().putRawText("<vertexList>").ln();
687 boolean dumped = false;
688 List<Vertex> vertexList = model.getVertexList();
689 for(Vertex vertex : vertexList){
696 ind().putRawText("</vertexList>").ln(2);
705 * @throws IOException 出力エラー
707 private Xml101009Exporter putVertex(Vertex vertex)
710 if(vertex.getEdgeAppearance()) bool = "true";
713 ind().putRawText("<vertex ");
714 putNumberedIdAttr("vtxId", PFX_VERTEX, vertex).sp();
715 putAttr("showEdge", bool);
716 sp().putRawText(">").ln();
719 MkPos3D position = vertex.getPosition();
720 ind().putPosition(position).ln();
722 MkVec3D normal = vertex.getNormal();
723 ind().putRawText("<normal ");
724 putFloatAttr("x", (float) normal.getXVal()).sp();
725 putFloatAttr("y", (float) normal.getYVal()).sp();
726 putFloatAttr("z", (float) normal.getZVal()).sp();
727 putRawText("/>").ln();
729 MkPos2D uvPos = vertex.getUVPosition();
730 ind().putRawText("<uvMap ");
731 putFloatAttr("u", (float) uvPos.getXpos()).sp();
732 putFloatAttr("v", (float) uvPos.getYpos()).sp();
733 putRawText("/>").ln();
735 BoneInfo boneA = vertex.getBoneA();
736 BoneInfo boneB = vertex.getBoneB();
737 int weight = vertex.getWeightA();
738 ind().putRawText("<skinning ");
739 putNumberedIdAttr("boneIdRef1", PFX_BONE, boneA).sp();
740 putNumberedIdAttr("boneIdRef2", PFX_BONE, boneB).sp();
741 putIntAttr("weightBalance", weight).sp();
742 putRawText("/>").ln();
745 ind().putRawText("</vertex>").ln(2);
752 * @param model モデルデータ
754 * @throws IOException 出力エラー
756 private Xml101009Exporter putBoneList(PmdModel model)
758 ind().putRawText("<boneList>").ln();
761 boolean dumped = false;
762 for(BoneInfo bone : model.getBoneList()){
764 ln().putBlockComment(BONETYPE_COMMENT).ln();
771 ind().putRawText("</boneList>").ln(2);
780 * @throws IOException 出力エラー
782 private Xml101009Exporter putBone(BoneInfo bone)
784 I18nText i18nName = bone.getBoneName();
785 BoneType type = bone.getBoneType();
787 StringBuilder boneComment = new StringBuilder();
788 String boneName = i18nName.getText();
789 if(boneName.isEmpty()){
790 boneName = "[NAMELESS]";
792 boneComment.append(boneName);
793 String typeName = type.getGuiName();
794 boneComment.append(" [").append(typeName).append(']');
795 ind().putLineComment(boneComment.toString()).ln();
797 ind().putRawText("<bone ");
798 putPrimaryNameAttr("name", i18nName).sp();
799 putNumberedIdAttr("boneId", PFX_BONE, bone).sp();
800 putAttr("type", type.name());
801 sp().putRawText(">").ln();
804 putI18nName(i18nName);
806 MkPos3D position = bone.getPosition();
807 ind().putPosition(position).ln();
809 BoneInfo ikBone = bone.getIKBone();
810 if(bone.getBoneType() == BoneType.LINKEDROT){
811 ind().putRawText("<rotationRatio ");
812 putIntAttr("ratio", bone.getRotationRatio());
813 putRawText(" />").ln();
814 }else if(ikBone != null){
815 ind().putRawText("<ikBone ");
816 putNumberedIdAttr("boneIdRef", PFX_BONE, ikBone);
818 String ikBoneName = "Ref:" + ikBone.getBoneName().getText();
819 putLineComment(ikBoneName);
823 BoneInfo prev = bone.getPrevBone();
824 BoneInfo next = bone.getNextBone();
826 StringBuilder chainComment = new StringBuilder();
828 chainComment.append('[')
829 .append(prev.getBoneName().getPrimaryText())
834 if(chainComment.length() <= 0) chainComment.append("#");
835 chainComment.append(">> ")
837 .append(next.getBoneName().getPrimaryText())
840 if(chainComment.length() > 0){
842 ind().putLineComment(chainComment).ln();
845 ind().putRawText("<boneChain");
848 putNumberedIdAttr("prevBoneIdRef", PFX_BONE, prev);
852 putNumberedIdAttr("nextBoneIdRef", PFX_BONE, next);
854 putRawText(" />").ln();
857 ind().putRawText("</bone>").ln(2);
864 * @param model モデルデータ
866 * @throws IOException 出力エラー
868 private Xml101009Exporter putBoneGroupList(PmdModel model)
870 ind().putRawText("<boneGroupList>").ln();
873 boolean dumped = false;
874 List<BoneGroup> groupList = model.getBoneGroupList();
875 for(BoneGroup group : groupList){
876 if(group.isDefaultBoneGroup()) continue;
883 ind().putRawText("</boneGroupList>").ln(2);
890 * @param group ボーングループ情報
892 * @throws IOException 出力エラー
894 private Xml101009Exporter putBoneGroup(BoneGroup group)
896 I18nText i18nName = group.getGroupName();
898 putLocalNameComment(i18nName).ln();
899 ind().putRawText("<boneGroup ");
900 putPrimaryNameAttr("name", i18nName);
901 sp().putRawText(">").ln();
904 putI18nName(i18nName);
906 for(BoneInfo bone : group){
907 ind().putRawText("<boneGroupMember ");
908 putNumberedIdAttr("boneIdRef", PFX_BONE, bone);
910 String boneName = "Ref:" + bone.getBoneName().getText();
911 putLineComment(boneName).ln();
915 ind().putRawText("</boneGroup>").ln(2);
922 * @param model モデルデータ
924 * @throws IOException 出力エラー
926 private Xml101009Exporter putIKChainList(PmdModel model)
928 ind().putRawText("<ikChainList>").ln();
931 boolean dumped = false;
932 List<IKChain> chainList = model.getIKChainList();
933 for(IKChain chain : chainList){
940 ind().putRawText("</ikChainList>").ln(2);
947 * @param chain チェーン情報
949 * @throws IOException 出力エラー
951 private Xml101009Exporter putIKChain(IKChain chain)
953 int depth = chain.getIKDepth();
954 float weight = chain.getIKWeight();
955 BoneInfo ikBone = chain.getIkBone();
957 ind().putLineComment("Ref:" + ikBone.getBoneName().getText()).ln();
958 ind().putRawText("<ikChain ");
959 putNumberedIdAttr("ikBoneIdRef", PFX_BONE, ikBone).sp();
960 putIntAttr("recursiveDepth", depth).sp();
961 putFloatAttr("weight", weight);
962 sp().putRawText(">").ln();
965 for(BoneInfo bone : chain){
966 ind().putRawText("<chainOrder ");
967 putNumberedIdAttr("boneIdRef", PFX_BONE, bone);
969 putLineComment("Ref:" + bone.getBoneName().getText());
974 ind().putRawText("</ikChain>").ln(2);
981 * @param model モデルデータ
983 * @throws IOException 出力エラー
985 private Xml101009Exporter putMorphList(PmdModel model)
987 ind().putRawText("<morphList>").ln();
990 boolean dumped = false;
991 Map<MorphType, List<MorphPart>> morphMap = model.getMorphMap();
992 for(MorphType type : MorphType.values()){
993 if(type == MorphType.BASE) continue;
994 List<MorphPart> partList = morphMap.get(type);
995 if(partList == null) continue;
996 for(MorphPart part : partList){
998 ln().putBlockComment(MORPHTYPE_COMMENT).ln();
1006 ind().putRawText("</morphList>").ln(2);
1015 * @throws IOException 出力エラー
1017 private Xml101009Exporter putMorphPart(MorphPart part)
1019 I18nText i18nName = part.getMorphName();
1020 String primary = i18nName.getPrimaryText();
1022 putLocalNameComment(i18nName).ln();
1023 ind().putRawText("<morph ");
1024 putAttr("name", primary).sp();
1025 putAttr("type", part.getMorphType().name());
1026 sp().putRawText(">");
1030 putI18nName(i18nName);
1032 for(MorphVertex mvertex : part){
1033 MkPos3D offset = mvertex.getOffset();
1034 Vertex base = mvertex.getBaseVertex();
1036 ind().putRawText("<morphVertex ");
1037 putNumberedIdAttr("vtxIdRef", PFX_VERTEX, base).sp();
1038 putFloatAttr("xOff", (float) offset.getXpos()).sp();
1039 putFloatAttr("yOff", (float) offset.getYpos()).sp();
1040 putFloatAttr("zOff", (float) offset.getZpos()).sp();
1046 ind().putRawText("</morph>").ln(2);
1053 * @param model モデルデータ
1055 * @throws IOException 出力エラー
1057 private Xml101009Exporter putRigidList(PmdModel model)
1059 ind().putRawText("<rigidList>").ln();
1062 boolean dumped = false;
1063 for(RigidInfo rigid : model.getRigidList()){
1065 ln().putBlockComment(RIGIDBEHAVIOR_COMMENT).ln();
1072 ind().putRawText("</rigidList>").ln(2);
1081 * @throws IOException 出力エラー
1083 private Xml101009Exporter putRigid(RigidInfo rigid)
1085 BoneInfo linkedBone = rigid.getLinkedBone();
1086 I18nText i18nName = rigid.getRigidName();
1087 String primary = i18nName.getPrimaryText();
1089 putLocalNameComment(i18nName).ln();
1090 ind().putRawText("<rigid ");
1091 putAttr("name", primary).sp();
1092 putNumberedIdAttr("rigidId", PFX_RIGID, rigid).sp();
1093 putAttr("behavior", rigid.getBehaviorType().name());
1094 sp().putRawText(">").ln();
1097 putI18nName(i18nName);
1099 if(linkedBone != null){
1100 ind().putRawText("<linkedBone ");
1101 putNumberedIdAttr("boneIdRef", PFX_BONE, linkedBone);
1103 putLineComment("Ref:" + linkedBone.getBoneName().getText());
1107 RigidShape shape = rigid.getRigidShape();
1108 putRigidShape(shape);
1110 MkPos3D position = rigid.getPosition();
1111 ind().putPosition(position).ln();
1113 Rad3d rotation = rigid.getRotation();
1114 ind().putRadRotation(rotation).ln();
1116 DynamicsInfo dynamics = rigid.getDynamicsInfo();
1117 putDynamics(dynamics).ln();
1119 for(RigidGroup group : rigid.getThroughGroupColl()){
1120 ind().putRawText("<throughRigidGroup ");
1121 putNumberedIdAttr("rigidGroupIdRef",
1123 group.getSerialNumber() + 1).sp();
1124 putRawText(" />").ln();
1128 ind().putRawText("</rigid>").ln(2);
1137 * @throws IOException 出力エラー
1139 private Xml101009Exporter putRigidShape(RigidShape shape)
1141 RigidShapeType type = shape.getShapeType();
1145 ind().putRawText("<rigidShapeBox ");
1146 putFloatAttr("width", shape.getWidth()).sp();
1147 putFloatAttr("height", shape.getHeight()).sp();
1148 putFloatAttr("depth", shape.getDepth()).sp();
1151 ind().putRawText("<rigidShapeSphere ");
1152 putFloatAttr("radius", shape.getRadius()).sp();
1155 ind().putRawText("<rigidShapeCapsule ");
1156 putFloatAttr("height", shape.getHeight()).sp();
1157 putFloatAttr("radius", shape.getRadius()).sp();
1161 throw new AssertionError();
1164 putRawText("/>").ln();
1171 * @param dynamics 力学設定
1173 * @throws IOException 出力エラー
1175 private Xml101009Exporter putDynamics(DynamicsInfo dynamics)
1177 ind().putRawText("<dynamics").ln();
1179 ind().putFloatAttr("mass", dynamics.getMass()).ln();
1180 ind().putFloatAttr("dampingPosition",
1181 dynamics.getDampingPosition()).ln();
1182 ind().putFloatAttr("dampingRotation",
1183 dynamics.getDampingRotation()).ln();
1184 ind().putFloatAttr("restitution", dynamics.getRestitution()).ln();
1185 ind().putFloatAttr("friction", dynamics.getFriction()).ln();
1187 ind().putRawText("/>").ln();
1194 * @param model モデルデータ
1196 * @throws IOException 出力エラー
1198 private Xml101009Exporter putRigidGroupList(PmdModel model)
1200 ind().putRawText("<rigidGroupList>").ln(2);
1203 boolean singleLast = false;
1204 for(RigidGroup group : model.getRigidGroupList()){
1205 List<RigidInfo> rigidList = group.getRigidList();
1206 if(singleLast && ! rigidList.isEmpty()){
1209 ind().putRawText("<rigidGroup ");
1210 putNumberedIdAttr("rigidGroupId",
1212 group.getSerialNumber() + 1);
1213 if(rigidList.isEmpty()){
1214 putRawText(" />").ln();
1218 putRawText(" >").ln();
1221 for(RigidInfo rigid : rigidList){
1222 ind().putRawText("<rigidGroupMember ");
1223 putNumberedIdAttr("rigidIdRef", PFX_RIGID, rigid).sp();
1226 putLineComment("Ref:" + rigid.getRigidName().getText());
1231 ind().putRawText("</rigidGroup>").ln(2);
1240 ind().putRawText("</rigidGroupList>").ln(2);
1247 * @param model モデルデータ
1249 * @throws IOException 出力エラー
1251 private Xml101009Exporter putJointList(PmdModel model)
1253 ind().putRawText("<jointList>").ln();
1256 boolean dumped = false;
1257 List<JointInfo> jointList = model.getJointList();
1258 for(JointInfo joint : jointList){
1259 if( ! dumped ) ln();
1265 ind().putRawText("</jointList>").ln(2);
1272 * @param joint ジョイント情報
1274 * @throws IOException 出力エラー
1276 private Xml101009Exporter putJoint(JointInfo joint)
1278 I18nText i18nName = joint.getJointName();
1280 putLocalNameComment(i18nName).ln();
1281 ind().putRawText("<joint ");
1282 putPrimaryNameAttr("name", i18nName);
1283 sp().putRawText(">").ln();
1286 putI18nName(i18nName);
1288 RigidInfo rigidA = joint.getRigidA();
1289 RigidInfo rigidB = joint.getRigidB();
1292 putLineComment("[" + rigidA.getRigidName().getText() + "]"
1293 + " <=> [" + rigidB.getRigidName().getText() + "]");
1296 ind().putRawText("<jointedRigidPair ");
1297 putNumberedIdAttr("rigidIdRef1", PFX_RIGID, rigidA).sp();
1298 putNumberedIdAttr("rigidIdRef2", PFX_RIGID, rigidB).sp();
1299 putRawText("/>").ln(2);
1301 MkPos3D position = joint.getPosition();
1302 ind().putPosition(position).ln();
1304 TripletRange posRange = joint.getPositionRange();
1305 ind().putRawText("<limitPosition").ln();
1308 putFloatAttr("xFrom", posRange.getXFrom()).sp();
1309 putFloatAttr("xTo", posRange.getXTo()).ln();
1311 putFloatAttr("yFrom", posRange.getYFrom()).sp();
1312 putFloatAttr("yTo", posRange.getYTo()).ln();
1314 putFloatAttr("zFrom", posRange.getZFrom()).sp();
1315 putFloatAttr("zTo", posRange.getZTo()).ln();
1317 ind().putRawText("/>").ln(2);
1319 Rad3d rotation = joint.getRotation();
1320 ind().putRadRotation(rotation).ln();
1321 TripletRange rotRange = joint.getRotationRange();
1322 ind().putRawText("<limitRotation").ln();
1325 putFloatAttr("xFrom", rotRange.getXFrom()).sp();
1326 putFloatAttr("xTo", rotRange.getXTo()).ln();
1328 putFloatAttr("yFrom", rotRange.getYFrom()).sp();
1329 putFloatAttr("yTo", rotRange.getYTo()).ln();
1331 putFloatAttr("zFrom", rotRange.getZFrom()).sp();
1332 putFloatAttr("zTo", rotRange.getZTo()).ln();
1334 ind().putRawText("/>").ln(2);
1336 MkPos3D elaPosition = joint.getElasticPosition();
1337 ind().putRawText("<elasticPosition ");
1338 putFloatAttr("x", (float) elaPosition.getXpos()).sp();
1339 putFloatAttr("y", (float) elaPosition.getYpos()).sp();
1340 putFloatAttr("z", (float) elaPosition.getZpos()).sp();
1341 putRawText("/>").ln();
1343 Deg3d elaRotation = joint.getElasticRotation();
1344 ind().putRawText("<elasticRotation ");
1345 putFloatAttr("xDeg", elaRotation.getXDeg()).sp();
1346 putFloatAttr("yDeg", elaRotation.getYDeg()).sp();
1347 putFloatAttr("zDeg", elaRotation.getZDeg()).sp();
1348 putRawText("/>").ln(2);
1351 ind().putRawText("</joint>").ln(2);