4 * License : The MIT License
5 * Copyright(c) 2010 MikuToga Partners
8 package jp.sfjp.mikutoga.pmd.model.xml;
10 import java.io.IOException;
11 import jp.sfjp.mikutoga.corelib.I18nText;
12 import jp.sfjp.mikutoga.pmd.model.PmdModel;
13 import jp.sfjp.mikutoga.xml.BasicXmlExporter;
14 import jp.sfjp.mikutoga.xml.SchemaUtil;
17 * PMDモーションデータをXMLへエクスポートする。
19 public class PmdXmlExporter extends BasicXmlExporter{
21 private static final String XML_VER = "1.0";
22 private static final String XML_ENC = "UTF-8";
23 private static final String XML_DECL =
24 "<?xml version=\"" + XML_VER
25 + "\" encoding=\"" + XML_ENC
28 private static final String XSINS = "xsi";
30 private static final String TOP_COMMENT =
31 "\u0020\u0020" + "MikuMikuDance\n"
32 + "\u0020\u0020\u0020\u0020" + "model-data(*.pmd) on XML";
35 private static final String CR = "\r"; // 0x0d
37 private static final String LF = "\n"; // 0x0a
39 private static final String CRLF = CR + LF; // 0x0d, 0x0a
42 private XmlModelFileType xmlType = XmlModelFileType.XML_130128;
44 private String generator = null;
46 private final ExporterMaterial materialExporter;
47 private final ExporterBone boneExporter;
48 private final ExporterMorph morphExporter;
49 private final ExporterDynamics dynamicsExporter;
50 private final ExporterShape shapeExporter;
52 private final ExtraExporter exp;
58 public PmdXmlExporter(){
61 this.materialExporter = new ExporterMaterial(this);
62 this.boneExporter = new ExporterBone(this);
63 this.morphExporter = new ExporterMorph(this);
64 this.dynamicsExporter = new ExporterDynamics(this);
65 this.shapeExporter = new ExporterShape(this);
67 this.exp = new ExtraExporter(this);
69 this.boneExporter.setXmlFileType(this.xmlType);
79 public XmlModelFileType getXmlFileType(){
87 public void setXmlFileType(XmlModelFileType type){
94 this.xmlType = XmlModelFileType.XML_130128;
97 throw new IllegalArgumentException();
100 assert this.xmlType == XmlModelFileType.XML_101009
101 || this.xmlType == XmlModelFileType.XML_130128;
103 this.boneExporter.setXmlFileType(this.xmlType);
109 * Generatorメタ情報を設定する。
110 * @param generatorArg Generatorメタ情報。表示したくないときはnull
112 public void setGenerator(String generatorArg){
113 this.generator = generatorArg;
119 * @return Generatorメタ情報。表示したくないときはnull
121 public String getGenerator(){
122 return this.generator;
126 * PMDモデルデータをXML形式で出力する。
127 * @param model PMDモデルデータ
128 * @param xmlOut XML出力先
129 * @throws IOException 出力エラー
131 public void putPmdXml(PmdModel model, Appendable xmlOut)
133 setAppendable(xmlOut);
136 putPmdXmlImpl(model);
145 * PMDモデルデータをXML形式で出力する。
146 * @param model PMDモデルデータ
147 * @throws IOException 出力エラー
149 private void putPmdXmlImpl(PmdModel model) throws IOException{
150 putPmdRootOpen(model);
155 this.materialExporter.putMaterialList(model);
156 this.materialExporter.putToonMap(model);
158 this.boneExporter.putBoneList(model);
159 this.boneExporter.putBoneGroupList(model);
160 this.boneExporter.putIKChainList(model);
162 this.morphExporter.putMorphList(model);
164 this.dynamicsExporter.putRigidList(model);
165 this.dynamicsExporter.putRigidGroupList(model);
166 this.dynamicsExporter.putJointList(model);
168 this.shapeExporter.putSurfaceGroupList(model);
169 this.shapeExporter.putVertexList(model);
171 ind().putETag(PmdTag.PMD_MODEL.tag()).ln(2);
172 ind().putLineComment("EOF").ln();
180 * @throws IOException 出力エラー
182 private void putPmdRootOpen(PmdModel model)
184 ind().putRawText(XML_DECL).ln(2);
185 ind().putBlockComment(TOP_COMMENT).ln(2);
187 I18nText modelName = model.getModelName();
189 this.exp.putLocalNameComment(modelName);
192 ind().putOpenSTag(PmdTag.PMD_MODEL.tag()).ln();
195 putPmdRootAttr(model);
198 putCloseSTag().ln(2);
206 * @throws IOException 出力エラー
208 private void putPmdRootAttr(PmdModel model)
214 if(this.xmlType == XmlModelFileType.XML_101009){
215 namespace = Schema101009.NS_PMDXML;
216 schemaUrl = Schema101009.SCHEMA_PMDXML;
217 schemaVer = Schema101009.VER_PMDXML;
218 }else if(this.xmlType == XmlModelFileType.XML_130128){
219 namespace = Schema130128.NS_PMDXML;
220 schemaUrl = Schema130128.SCHEMA_PMDXML;
221 schemaVer = Schema130128.VER_PMDXML;
224 throw new AssertionError();
227 ind().putAttr("xmlns", namespace).ln();
228 ind().putAttr("xmlns:" + XSINS, SchemaUtil.NS_XSD).ln();
230 ind().putRawText(XSINS).putRawText(":schemaLocation=")
232 putRawText(namespace).ln();
233 ind().sp(2).putRawText(schemaUrl)
236 ind().putAttr(PmdAttr.SCHEMA_VERSION.attr(), schemaVer);
239 I18nText modelName = model.getModelName();
241 this.exp.putPrimaryNameAttr(PmdAttr.NAME, modelName);
251 * @throws IOException 出力エラー
253 private PmdXmlExporter putModelInfo(PmdModel model)
255 I18nText modelName = model.getModelName();
256 this.exp.putI18nName(modelName);
259 I18nText description = model.getDescription();
260 for(String lang639 : description.lang639CodeList()){
261 String descText = description.getI18nText(lang639);
262 putDescription(lang639, descText);
271 * @param lang639 言語コード
272 * @param content 詳細内容
274 * @throws IOException 出力エラー
276 private PmdXmlExporter putDescription(CharSequence lang639,
277 CharSequence content)
279 String text = content.toString();
280 text = text.replace(CRLF, LF);
281 text = text.replace(CR, LF);
283 ind().putOpenSTag(PmdTag.DESCRIPTION.tag());
284 if( ! I18nText.CODE639_PRIMARY.equals(lang639) ){
285 sp().putAttr(PmdAttr.LANG.attr(), lang639).sp();
289 putBRedContent(text);
291 ind().putETag(PmdTag.DESCRIPTION.tag()).ln();
293 if( ! ExtraExporter.hasOnlyBasicLatin(text)
294 && isBasicLatinOnlyOut() ){
295 putBlockComment(text);
302 * break要素を含む要素内容を出力する。
303 * 必要に応じてXML定義済み実体文字が割り振られた文字、
304 * コントロールコード、および非BasicLatin文字がエスケープされる。
308 * @throws IOException 出力エラー
310 private PmdXmlExporter putBRedContent(CharSequence content)
312 int length = content.length();
316 for(int idx = 0; idx < length; idx++){
317 char ch = content.charAt(idx);
319 CharSequence seq = content.subSequence(startPos, idx);
320 putContent(seq).putRawText("<br/>").ln();
325 if(startPos < length){
326 CharSequence seq = content.subSequence(startPos, length);
327 putContent(seq).ln();
336 * @throws IOException 出力エラー
338 private PmdXmlExporter putMetaInfo() throws IOException{
339 ind().putSimpleSTag(PmdTag.LICENSE.tag()).ln();
340 ind().putETag(PmdTag.LICENSE.tag()).ln(2);
342 ind().putSimpleSTag(PmdTag.CREDITS.tag()).ln();
343 ind().putETag(PmdTag.CREDITS.tag()).ln(2);
345 String genName = getGenerator();
347 ind().putOpenSTag(PmdTag.META.tag()).sp();
348 putAttr(PmdAttr.NAME.attr(), "generator").sp();
349 putAttr(PmdAttr.CONTENT.attr(), genName).sp();
350 putCloseEmpty().ln();
353 ind().putOpenSTag(PmdTag.META.tag()).sp();
354 putAttr(PmdAttr.NAME.attr(), "siteURL").sp();
355 putAttr(PmdAttr.CONTENT.attr(), "").sp();
356 putCloseEmpty().ln();
358 ind().putOpenSTag(PmdTag.META.tag()).sp();
359 putAttr(PmdAttr.NAME.attr(), "imageURL").sp();
360 putAttr(PmdAttr.CONTENT.attr(), "").sp();
361 putCloseEmpty().ln(2);