/*
* pmd-xml exporter
*
* License : The MIT License
* Copyright(c) 2010 MikuToga Partners
*/
package jp.sfjp.mikutoga.pmd.xml;
import java.awt.Color;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import jp.sfjp.mikutoga.corelib.I18nText;
import jp.sfjp.mikutoga.math.MkPos2D;
import jp.sfjp.mikutoga.math.MkPos3D;
import jp.sfjp.mikutoga.math.MkVec3D;
import jp.sfjp.mikutoga.pmd.BoneType;
import jp.sfjp.mikutoga.pmd.Deg3d;
import jp.sfjp.mikutoga.pmd.MorphType;
import jp.sfjp.mikutoga.pmd.Rad3d;
import jp.sfjp.mikutoga.pmd.RigidShapeType;
import jp.sfjp.mikutoga.pmd.TripletRange;
import jp.sfjp.mikutoga.pmd.model.BoneGroup;
import jp.sfjp.mikutoga.pmd.model.BoneInfo;
import jp.sfjp.mikutoga.pmd.model.DynamicsInfo;
import jp.sfjp.mikutoga.pmd.model.IKChain;
import jp.sfjp.mikutoga.pmd.model.JointInfo;
import jp.sfjp.mikutoga.pmd.model.Material;
import jp.sfjp.mikutoga.pmd.model.MorphPart;
import jp.sfjp.mikutoga.pmd.model.MorphVertex;
import jp.sfjp.mikutoga.pmd.model.PmdModel;
import jp.sfjp.mikutoga.pmd.model.RigidGroup;
import jp.sfjp.mikutoga.pmd.model.RigidInfo;
import jp.sfjp.mikutoga.pmd.model.RigidShape;
import jp.sfjp.mikutoga.pmd.model.SerialNumbered;
import jp.sfjp.mikutoga.pmd.model.ShadeInfo;
import jp.sfjp.mikutoga.pmd.model.Surface;
import jp.sfjp.mikutoga.pmd.model.ToonMap;
import jp.sfjp.mikutoga.pmd.model.Vertex;
import jp.sourceforge.mikutoga.xml.BasicXmlExporter;
import jp.sourceforge.mikutoga.xml.XmlResourceResolver;
/**
* 101009形式XMLでPMDモデルデータを出力する。
*/
public class PmdXmlExporter extends BasicXmlExporter{
private static final String TOP_COMMENT =
" MikuMikuDance\n"
+ " model-data(*.pmd) on XML";
/** 改行文字列 CR。 */
private static final String CR = "\r"; // 0x0d
/** 改行文字列 LF。 */
private static final String LF = "\n"; // 0x0a
/** 改行文字列 CRLF。 */
private static final String CRLF = CR + LF; // 0x0d, 0x0a
private static final String PFX_SURFACEGROUP = "sg";
private static final String PFX_TOONFILE = "tf";
private static final String PFX_VERTEX = "vtx";
private static final String PFX_BONE = "bn";
private static final String PFX_RIGID = "rd";
private static final String PFX_RIGIDGROUP = "rg";
private static final String BONETYPE_COMMENT =
"Bone types:\n"
+ "[0 : ROTATE : Rotate : 回転 :]\n"
+ "[1 : ROTMOV : Rotate/Move : 回転/移動 :]\n"
+ "[2 : IK : IK : IK :]\n"
+ "[3 : UNKNOWN : Unknown : 不明 :]\n"
+ "[4 : UNDERIK : Under IK : IK影響下(回転) :]\n"
+ "[5 : UNDERROT : Under rotate : 回転影響下 :]\n"
+ "[6 : IKCONNECTED : IK connected : IK接続先 :]\n"
+ "[7 : HIDDEN : Hidden : 非表示 :]\n"
+ "[8 : TWIST : Twist : 捩り :]\n"
+ "[9 : LINKEDROT : Linked Rotate: 回転連動 :]\n";
private static final String MORPHTYPE_COMMENT =
"Morph types:\n"
+ "[1 : EYEBROW : まゆ ]\n"
+ "[2 : EYE : 目 ]\n"
+ "[3 : LIP : リップ ]\n"
+ "[4 : EXTRA : その他 ]\n";
private static final String RIGIDBEHAVIOR_COMMENT =
"Rigid behavior types:\n"
+ "[0 : FOLLOWBONE : ボーン追従 ]\n"
+ "[1 : ONLYDYNAMICS : 物理演算 ]\n"
+ "[2 : BONEDDYNAMICS : ボーン位置合わせ ]\n";
private static final Locale DEF_LOCALE = Locale.JAPANESE;
private String generator = null;
private XmlModelFileType xmlType = XmlModelFileType.XML_101009;
/**
* コンストラクタ。
*/
public PmdXmlExporter(){
super();
return;
}
/**
* 出力XMLファイル種別を返す。
* @return ファイル種別
*/
public XmlModelFileType getXmlFileType(){
return this.xmlType;
}
/**
* 出力XMLファイル種別を設定する。
* @param type ファイル種別
*/
public void setXmlFileType(XmlModelFileType type){
switch(type){
case XML_101009:
case XML_130128:
this.xmlType = type;
break;
case XML_AUTO:
this.xmlType = XmlModelFileType.XML_130128;
break;
default:
throw new IllegalArgumentException();
}
assert this.xmlType == XmlModelFileType.XML_101009
|| this.xmlType == XmlModelFileType.XML_130128;
return;
}
/**
* Generatorメタ情報を設定する。
* @param generatorArg Generatorメタ情報。表示したくないときはnull
*/
public void setGenerator(String generatorArg){
this.generator = generatorArg;
return;
}
/**
* 任意の文字列がBasicLatin文字のみから構成されるか判定する。
* @param seq 文字列
* @return null、長さ0もしくはBasicLatin文字のみから構成されるならtrue
*/
public static boolean hasOnlyBasicLatin(CharSequence seq){
if(seq == null) return true;
int length = seq.length();
for(int pos = 0; pos < length; pos++){
char ch = seq.charAt(pos);
if(ch > 0x007f) return false;
}
return true;
}
/**
* {@inheritDoc}
* @return {@inheritDoc}
* @throws IOException {@inheritDoc}
*/
@Override
public PmdXmlExporter ind() throws IOException{
super.ind();
return this;
}
/**
* 文字参照によるエスケープを補佐するためのコメントを出力する。
* @param seq 文字列
* @return this本体
* @throws IOException 出力エラー
*/
protected PmdXmlExporter putUnescapedComment(CharSequence seq)
throws IOException{
if( ! isBasicLatinOnlyOut() ) return this;
if(hasOnlyBasicLatin(seq)) return this;
sp().putLineComment(seq);
return this;
}
/**
* 多言語化された各種識別名を出力する。
* プライマリ名は出力対象外。
* @param text 多言語文字列
* @return this本体
* @throws IOException 出力エラー
*/
protected PmdXmlExporter putI18nName(I18nText text) throws IOException{
for(String lang639 : text.lang639CodeList()){
if(lang639.equals(I18nText.CODE639_PRIMARY)) continue;
String name = text.getI18nText(lang639);
ind().putRawText("");
putUnescapedComment(name);
ln();
}
return this;
}
/**
* 番号付けされたID(IDREF)属性を出力する。
* @param attrName 属性名
* @param prefix IDプレフィクス
* @param num 番号
* @return this本体
* @throws IOException 出力エラー
*/
protected PmdXmlExporter putNumberedIdAttr(CharSequence attrName,
CharSequence prefix,
int num )
throws IOException{
putRawText(attrName).putRawText("=\"");
putRawText(prefix).putXsdInt(num);
putRawCh('"');
return this;
}
/**
* 番号付けされたID(IDREF)属性を出力する。
* @param attrName 属性名
* @param prefix IDプレフィクス
* @param numbered 番号付けされたオブジェクト
* @return this本体
* @throws IOException 出力エラー
*/
protected PmdXmlExporter putNumberedIdAttr(CharSequence attrName,
CharSequence prefix,
SerialNumbered numbered )
throws IOException{
putNumberedIdAttr(attrName, prefix, numbered.getSerialNumber());
return this;
}
/**
* 位置情報を出力する。
* @param position 位置情報
* @return this本体
* @throws IOException 出力エラー
*/
protected PmdXmlExporter putPosition(MkPos3D position)
throws IOException{
putRawText("");
return this;
}
/**
* 姿勢情報(ラジアン)を出力する。
* @param rotation 姿勢情報
* @return this本体
* @throws IOException 出力エラー
*/
protected PmdXmlExporter putRadRotation(Rad3d rotation)
throws IOException{
putRawText("");
return this;
}
/**
* 多言語識別名属性のローカルな名前をコメント出力する。
* @param name 多言語識別名
* @return this本体
* @throws IOException 出力エラー
*/
protected PmdXmlExporter putLocalNameComment(I18nText name)
throws IOException{
String localName = name.getText();
if(localName.isEmpty()){
localName = "[NAMELESS]";
}
ind().putLineComment(localName);
return this;
}
/**
* 多言語識別名属性のプライマリな名前を出力する。
* @param attrName 属性名
* @param name 多言語識別名
* @return this本体
* @throws IOException 出力エラー
*/
protected PmdXmlExporter putPrimaryNameAttr(CharSequence attrName,
I18nText name)
throws IOException{
String primaryName = name.getPrimaryText();
putAttr(attrName, primaryName);
return this;
}
/**
* PMDモデルデータをXML形式で出力する。
* @param model PMDモデルデータ
* @param xmlOut XML出力先
* @throws IOException 出力エラー
*/
public void putPmdModel(PmdModel model, Appendable xmlOut)
throws IOException{
setAppendable(xmlOut);
ind().putRawText("").ln(2);
ind().putBlockComment(TOP_COMMENT).ln(2);
I18nText modelName = model.getModelName();
ind().putLocalNameComment(modelName).ln();
ind().putRawText("").ln(2);
putModelInfo(model).flush();
putMetaInfo(model).flush();
putMaterialList(model).flush();
putToonMap(model).flush();
putBoneList(model).flush();
putBoneGroupList(model).flush();
putIKChainList(model).flush();
putMorphList(model).flush();
putRigidList(model).flush();
putRigidGroupList(model).flush();
putJointList(model).flush();
putSurfaceGroupList(model).flush();
putVertexList(model).flush();
ind().putRawText("").ln(2);
ind().putRawText("").ln();
return;
}
/**
* モデル基本情報を出力する。
* @param model モデル情報
* @return this本体
* @throws IOException 出力エラー
*/
private PmdXmlExporter putModelInfo(PmdModel model)
throws IOException{
I18nText modelName = model.getModelName();
putI18nName(modelName);
ln();
I18nText description = model.getDescription();
for(String lang639 : description.lang639CodeList()){
String descText = description.getI18nText(lang639);
putDescription(lang639, descText);
ln();
}
return this;
}
/**
* モデル詳細テキストを出力する。
* @param lang639 言語コード
* @param content 詳細内容
* @return this本体
* @throws IOException 出力エラー
*/
private PmdXmlExporter putDescription(CharSequence lang639,
CharSequence content)
throws IOException{
String text = content.toString();
text = text.replace(CRLF, LF);
text = text.replace(CR, LF);
ind().putRawText("").ln();
putBRedContent(text);
ind().putRawText("").ln();
if( ! hasOnlyBasicLatin(text) && isBasicLatinOnlyOut() ){
putBlockComment(text);
}
return this;
}
/**
* break要素を含む要素内容を出力する。
* 必要に応じてXML定義済み実体文字が割り振られた文字、
* コントロールコード、および非BasicLatin文字がエスケープされる。
* \nはbrタグに変換される。
* @param content 内容
* @return this本体
* @throws IOException 出力エラー
*/
protected BasicXmlExporter putBRedContent(CharSequence content)
throws IOException{
int length = content.length();
int startPos = 0;
for(int idx = 0; idx < length; idx++){
char ch = content.charAt(idx);
if(ch == '\n'){
CharSequence seq = content.subSequence(startPos, idx);
putContent(seq).putRawText("
").ln();
startPos = idx + 1;
}
}
if(startPos < length){
CharSequence seq = content.subSequence(startPos, length);
putContent(seq).ln();
}
return this;
}
/**
* 各種メタ情報を出力する。
* @param model モデルデータ
* @return this本体
* @throws IOException 出力エラー
*/
private PmdXmlExporter putMetaInfo(PmdModel model) throws IOException{
ind().putRawText("").ln();
ind().putRawText("").ln(2);
ind().putRawText("").ln();
ind().putRawText("").ln(2);
if(this.generator != null){
ind().putRawText("").ln();
}
ind().putRawText("").ln();
ind().putRawText("").ln(2);
return this;
}
/**
* マテリアル素材一覧を出力する。
* @param model モデルデータ
* @return this本体
* @throws IOException 出力エラー
*/
private PmdXmlExporter putMaterialList(PmdModel model)
throws IOException{
ind().putRawText("").ln();
pushNest();
int ct = 0;
boolean dumped = false;
List materialList = model.getMaterialList();
for(Material material : materialList){
if( ! dumped ) ln();
putMaterial(material, ct++);
dumped = true;
}
popNest();
ind().putRawText("").ln(2);
return this;
}
/**
* マテリアル素材情報を出力する。
* @param material マテリアル素材
* @param no マテリアル通し番号
* @return this本体
* @throws IOException 出力エラー
*/
private PmdXmlExporter putMaterial(Material material, int no)
throws IOException{
String bool;
if(material.getEdgeAppearance()) bool = "true";
else bool = "false";
I18nText name = material.getMaterialName();
String primary = name.getPrimaryText();
String local = name.getText();
if(local != null && local.length() > 0){
ind().putLineComment(local).ln();
}
ind().putRawText(" 0){
putAttr("name", primary).sp();
}
putAttr("showEdge", bool);
sp();
putNumberedIdAttr("surfaceGroupIdRef", PFX_SURFACEGROUP, no);
sp().putRawCh('>').ln();
pushNest();
putI18nName(name);
float[] rgba = new float[4];
Color diffuse = material.getDiffuseColor();
diffuse.getRGBComponents(rgba);
ind().putRawText("").ln();
Color specular = material.getSpecularColor();
specular.getRGBComponents(rgba);
float shininess = material.getShininess();
ind().putRawText("").ln();
Color ambient = material.getAmbientColor();
ambient.getRGBComponents(rgba);
ind().putRawText("").ln();
ShadeInfo shade = material.getShadeInfo();
String textureFileName = shade.getTextureFileName();
String spheremapFileName = shade.getSpheremapFileName();
if(shade.isValidToonIndex()){
ind().putRawText("");
String toonFileName = shade.getToonFileName();
if(toonFileName != null && toonFileName.length() > 0){
sp().putLineComment(toonFileName);
}
ln();
}
if(textureFileName != null && textureFileName.length() > 0){
ind().putRawText("").ln();
}
if(spheremapFileName != null && spheremapFileName.length() > 0){
ind().putRawText("").ln();
}
popNest();
ind().putRawText("").ln(2);
return this;
}
/**
* トゥーンファイルマッピング情報を出力する。
* @param model モデルデータ
* @return this本体
* @throws IOException 出力エラー
*/
private PmdXmlExporter putToonMap(PmdModel model)
throws IOException{
ind().putRawText("").ln();
pushNest();
ToonMap map = model.getToonMap();
for(int index = 0; index <= 9; index++){
ind().putToon(map, index).ln();
}
popNest();
ind().putRawText("").ln(2);
return this;
}
/**
* 個別のトゥーンファイル情報を出力する。
* @param map トゥーンマップ
* @param index インデックス値
* @return this本体
* @throws IOException 出力エラー
*/
private PmdXmlExporter putToon(ToonMap map, int index)
throws IOException{
putRawText("");
putUnescapedComment(toonFile);
return this;
}
/**
* サーフェイスグループリストを出力する。
* @param model モデルデータ
* @return this本体
* @throws IOException 出力エラー
*/
private PmdXmlExporter putSurfaceGroupList(PmdModel model)
throws IOException{
ind().putRawText("").ln();
pushNest();
int ct = 0;
boolean dumped = false;
List materialList = model.getMaterialList();
for(Material material : materialList){
List surfaceList = material.getSurfaceList();
if( ! dumped ) ln();
putSurfaceList(surfaceList, ct++);
dumped = true;
}
popNest();
ind().putRawText("").ln(2);
return this;
}
/**
* 個別のサーフェイスグループを出力する。
* @param surfaceList サーフェイスのリスト
* @param index グループインデックス
* @return this本体
* @throws IOException 出力エラー
*/
private PmdXmlExporter putSurfaceList(List surfaceList,
int index)
throws IOException{
ind().putRawText("").ln();
pushNest();
for(Surface surface : surfaceList){
putSurface(surface);
}
popNest();
ind().putRawText("").ln(2);
return this;
}
/**
* 個別のサーフェイスを出力する。
* @param surface サーフェイス
* @return this本体
* @throws IOException 出力エラー
*/
private PmdXmlExporter putSurface(Surface surface)
throws IOException{
ind().putRawText("").ln();
return this;
}
/**
* 頂点リストを出力する。
* @param model モデルデータ
* @return this本体
* @throws IOException 出力エラー
*/
private PmdXmlExporter putVertexList(PmdModel model)
throws IOException{
ind().putRawText("").ln();
pushNest();
boolean dumped = false;
List vertexList = model.getVertexList();
for(Vertex vertex : vertexList){
if( ! dumped ) ln();
putVertex(vertex);
dumped = true;
}
popNest();
ind().putRawText("").ln(2);
return this;
}
/**
* 個別の頂点情報を出力する。
* @param vertex 頂点
* @return this本体
* @throws IOException 出力エラー
*/
private PmdXmlExporter putVertex(Vertex vertex)
throws IOException{
String bool;
if(vertex.getEdgeAppearance()) bool = "true";
else bool = "false";
ind().putRawText("").ln();
pushNest();
MkPos3D position = vertex.getPosition();
ind().putPosition(position).ln();
MkVec3D normal = vertex.getNormal();
ind().putRawText("").ln();
MkPos2D uvPos = vertex.getUVPosition();
ind().putRawText("").ln();
BoneInfo boneA = vertex.getBoneA();
BoneInfo boneB = vertex.getBoneB();
int weight = vertex.getWeightA();
ind().putRawText("").ln();
popNest();
ind().putRawText("").ln(2);
return this;
}
/**
* ボーンリストを出力する。
* @param model モデルデータ
* @return this本体
* @throws IOException 出力エラー
*/
private PmdXmlExporter putBoneList(PmdModel model)
throws IOException{
ind().putRawText("").ln();
pushNest();
boolean dumped = false;
for(BoneInfo bone : model.getBoneList()){
if( ! dumped ){
ln().putBlockComment(BONETYPE_COMMENT).ln();
}
putBone(bone);
dumped = true;
}
popNest();
ind().putRawText("").ln(2);
return this;
}
/**
* 個別のボーン情報を出力する。
* @param bone ボーン情報
* @return this本体
* @throws IOException 出力エラー
*/
private PmdXmlExporter putBone(BoneInfo bone)
throws IOException{
I18nText i18nName = bone.getBoneName();
BoneType type = bone.getBoneType();
StringBuilder boneComment = new StringBuilder();
String boneName = i18nName.getText();
if(boneName.isEmpty()){
boneName = "[NAMELESS]";
}
boneComment.append(boneName);
String typeName = type.getGuiName(DEF_LOCALE);
boneComment.append(" [").append(typeName).append(']');
ind().putLineComment(boneComment.toString()).ln();
ind().putRawText("").ln();
pushNest();
putI18nName(i18nName);
MkPos3D position = bone.getPosition();
ind().putPosition(position).ln();
BoneInfo srcBone = bone.getSrcBone();
if(bone.getBoneType() == BoneType.LINKEDROT){
ind().putRawText("").ln();
}else if(srcBone != null){
String iktag;
switch(getXmlFileType()){
case XML_101009:
iktag = " ");
String ikBoneName = "Ref:" + srcBone.getBoneName().getText();
putLineComment(ikBoneName);
ln();
}
BoneInfo prev = bone.getPrevBone();
BoneInfo next = bone.getNextBone();
StringBuilder chainComment = new StringBuilder();
if(prev != null){
chainComment.append('[')
.append(prev.getBoneName().getPrimaryText())
.append(']')
.append(" >>#");
}
if(next != null){
if(chainComment.length() <= 0) chainComment.append("#");
chainComment.append(">> ")
.append('[')
.append(next.getBoneName().getPrimaryText())
.append(']');
}
if(chainComment.length() > 0){
ln();
ind().putLineComment(chainComment).ln();
}
ind().putRawText("").ln();
popNest();
ind().putRawText("").ln(2);
return this;
}
/**
* ボーングループリストを出力する。
* @param model モデルデータ
* @return this本体
* @throws IOException 出力エラー
*/
private PmdXmlExporter putBoneGroupList(PmdModel model)
throws IOException{
ind().putRawText("").ln();
pushNest();
boolean dumped = false;
List groupList = model.getBoneGroupList();
for(BoneGroup group : groupList){
if(group.isDefaultBoneGroup()) continue;
if( ! dumped ) ln();
putBoneGroup(group);
dumped = true;
}
popNest();
ind().putRawText("").ln(2);
return this;
}
/**
* 個別のボーングループ情報を出力する。
* @param group ボーングループ情報
* @return this本体
* @throws IOException 出力エラー
*/
private PmdXmlExporter putBoneGroup(BoneGroup group)
throws IOException{
I18nText i18nName = group.getGroupName();
putLocalNameComment(i18nName).ln();
ind().putRawText("").ln();
pushNest();
putI18nName(i18nName);
for(BoneInfo bone : group){
ind().putRawText(" ");
String boneName = "Ref:" + bone.getBoneName().getText();
putLineComment(boneName).ln();
}
popNest();
ind().putRawText("").ln(2);
return this;
}
/**
* IKチェーンリストを出力する。
* @param model モデルデータ
* @return this本体
* @throws IOException 出力エラー
*/
private PmdXmlExporter putIKChainList(PmdModel model)
throws IOException{
ind().putRawText("").ln();
pushNest();
boolean dumped = false;
List chainList = model.getIKChainList();
for(IKChain chain : chainList){
if( ! dumped ) ln();
putIKChain(chain);
dumped = true;
}
popNest();
ind().putRawText("").ln(2);
return this;
}
/**
* 個別のIKチェーン情報を出力する。
* @param chain チェーン情報
* @return this本体
* @throws IOException 出力エラー
*/
private PmdXmlExporter putIKChain(IKChain chain)
throws IOException{
int depth = chain.getIKDepth();
float weight = chain.getIKWeight();
BoneInfo ikBone = chain.getIkBone();
ind().putLineComment("Ref:" + ikBone.getBoneName().getText()).ln();
ind().putRawText("").ln();
pushNest();
for(BoneInfo bone : chain){
ind().putRawText(" ");
putLineComment("Ref:" + bone.getBoneName().getText());
ln();
}
popNest();
ind().putRawText("").ln(2);
return this;
}
/**
* モーフリストを出力する。
* @param model モデルデータ
* @return this本体
* @throws IOException 出力エラー
*/
private PmdXmlExporter putMorphList(PmdModel model)
throws IOException{
ind().putRawText("").ln();
pushNest();
boolean dumped = false;
Map> morphMap = model.getMorphMap();
for(MorphType type : MorphType.values()){
if(type == MorphType.BASE) continue;
List partList = morphMap.get(type);
if(partList == null) continue;
for(MorphPart part : partList){
if( ! dumped ){
ln().putBlockComment(MORPHTYPE_COMMENT).ln();
}
putMorphPart(part);
dumped = true;
}
}
popNest();
ind().putRawText("").ln(2);
return this;
}
/**
* 個別のモーフ情報を出力する。
* @param part モーフ情報
* @return this本体
* @throws IOException 出力エラー
*/
private PmdXmlExporter putMorphPart(MorphPart part)
throws IOException{
I18nText i18nName = part.getMorphName();
String primary = i18nName.getPrimaryText();
putLocalNameComment(i18nName).ln();
ind().putRawText("");
ln();
pushNest();
putI18nName(i18nName);
for(MorphVertex mvertex : part){
MkPos3D offset = mvertex.getOffset();
Vertex base = mvertex.getBaseVertex();
ind().putRawText("");
ln();
}
popNest();
ind().putRawText("").ln(2);
return this;
}
/**
* 剛体リストを出力する。
* @param model モデルデータ
* @return this本体
* @throws IOException 出力エラー
*/
private PmdXmlExporter putRigidList(PmdModel model)
throws IOException{
ind().putRawText("").ln();
pushNest();
boolean dumped = false;
for(RigidInfo rigid : model.getRigidList()){
if( ! dumped ){
ln().putBlockComment(RIGIDBEHAVIOR_COMMENT).ln();
}
putRigid(rigid);
dumped = true;
}
popNest();
ind().putRawText("").ln(2);
return this;
}
/**
* 個別の剛体情報を出力する。
* @param rigid 剛体情報
* @return this本体
* @throws IOException 出力エラー
*/
private PmdXmlExporter putRigid(RigidInfo rigid)
throws IOException{
BoneInfo linkedBone = rigid.getLinkedBone();
I18nText i18nName = rigid.getRigidName();
String primary = i18nName.getPrimaryText();
putLocalNameComment(i18nName).ln();
ind().putRawText("").ln();
pushNest();
putI18nName(i18nName);
if(linkedBone != null){
ind().putRawText(" ");
putLineComment("Ref:" + linkedBone.getBoneName().getText());
ln(2);
}
RigidShape shape = rigid.getRigidShape();
putRigidShape(shape);
MkPos3D position = rigid.getPosition();
ind().putPosition(position).ln();
Rad3d rotation = rigid.getRotation();
ind().putRadRotation(rotation).ln();
DynamicsInfo dynamics = rigid.getDynamicsInfo();
putDynamics(dynamics).ln();
for(RigidGroup group : rigid.getThroughGroupColl()){
ind().putRawText("").ln();
}
popNest();
ind().putRawText("").ln(2);
return this;
}
/**
* 剛体形状を出力する。
* @param shape 剛体形状
* @return this本体
* @throws IOException 出力エラー
*/
private PmdXmlExporter putRigidShape(RigidShape shape)
throws IOException{
RigidShapeType type = shape.getShapeType();
switch(type){
case BOX:
ind().putRawText("").ln();
return this;
}
/**
* 力学設定を出力する。
* @param dynamics 力学設定
* @return this本体
* @throws IOException 出力エラー
*/
private PmdXmlExporter putDynamics(DynamicsInfo dynamics)
throws IOException{
ind().putRawText("").ln();
return this;
}
/**
* 剛体グループリストを出力する。
* @param model モデルデータ
* @return this本体
* @throws IOException 出力エラー
*/
private PmdXmlExporter putRigidGroupList(PmdModel model)
throws IOException{
ind().putRawText("").ln(2);
pushNest();
boolean singleLast = false;
for(RigidGroup group : model.getRigidGroupList()){
List rigidList = group.getRigidList();
if(singleLast && ! rigidList.isEmpty()){
ln();
}
ind().putRawText("").ln();
singleLast = true;
continue;
}
putRawText(" >").ln();
pushNest();
for(RigidInfo rigid : rigidList){
ind().putRawText("");
sp();
putLineComment("Ref:" + rigid.getRigidName().getText());
ln();
}
popNest();
ind().putRawText("").ln(2);
singleLast = false;
}
if(singleLast){
ln();
}
popNest();
ind().putRawText("").ln(2);
return this;
}
/**
* ジョイントリストを出力する。
* @param model モデルデータ
* @return this本体
* @throws IOException 出力エラー
*/
private PmdXmlExporter putJointList(PmdModel model)
throws IOException{
ind().putRawText("").ln();
pushNest();
boolean dumped = false;
List jointList = model.getJointList();
for(JointInfo joint : jointList){
if( ! dumped ) ln();
putJoint(joint);
dumped = true;
}
popNest();
ind().putRawText("").ln(2);
return this;
}
/**
* 個別のジョイント情報を出力する。
* @param joint ジョイント情報
* @return this本体
* @throws IOException 出力エラー
*/
private PmdXmlExporter putJoint(JointInfo joint)
throws IOException{
I18nText i18nName = joint.getJointName();
putLocalNameComment(i18nName).ln();
ind().putRawText("").ln();
pushNest();
putI18nName(i18nName);
RigidInfo rigidA = joint.getRigidA();
RigidInfo rigidB = joint.getRigidB();
ind();
putLineComment("[" + rigidA.getRigidName().getText() + "]"
+ " <=> [" + rigidB.getRigidName().getText() + "]");
ln();
ind().putRawText("").ln(2);
MkPos3D position = joint.getPosition();
ind().putPosition(position).ln();
TripletRange posRange = joint.getPositionRange();
ind().putRawText("").ln(2);
Rad3d rotation = joint.getRotation();
ind().putRadRotation(rotation).ln();
TripletRange rotRange = joint.getRotationRange();
ind().putRawText("").ln(2);
MkPos3D elaPosition = joint.getElasticPosition();
ind().putRawText("").ln();
Deg3d elaRotation = joint.getElasticRotation();
ind().putRawText("").ln(2);
popNest();
ind().putRawText("").ln(2);
return this;
}
}