//------------------------------------------------------------------------------
// Lamp : Open source game middleware
// Copyright (C) 2004  Junpei Ohtani ( Email : junpee@users.sourceforge.jp )
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//------------------------------------------------------------------------------

/** @file
 * テキストアニメーションセーバ実装
 * @author Junpee
 */

#include "LampBasic.h"
#include "Animation/InputOutput/TextAnimationSaver.h"
#include "Core/InputOutput/TextFileWriter.h"

#include "Animation/VectorInterpolator/VectorConstantInterpolator.h"
#include "Animation/VectorInterpolator/VectorArrayInterpolator.h"
#include "Animation/VectorInterpolator/VectorLinearInterpolator.h"
#include "Animation/RotationInterpolator/RotationConstantInterpolator.h"
#include "Animation/RotationInterpolator/EulerArrayInterpolator.h"
#include "Animation/RotationInterpolator/QuaternionArrayInterpolator.h"
#include "Animation/RotationInterpolator/QuaternionLinearInterpolator.h"

#include "Animation/System/AnimationManager.h"
#include "Animation/System/AnimationSet.h"
#include "Animation/Camera/CameraAnimation.h"
#include "Animation/SceneNode/SceneNodeAnimation.h"
#include "Animation/Model/CharacterModelAnimation.h"

namespace Lamp{

//------------------------------------------------------------------------------
// コンストラクタ
TextAnimationSaver::TextAnimationSaver(){
}
//------------------------------------------------------------------------------
// デストラクタ
TextAnimationSaver::~TextAnimationSaver(){
}
//------------------------------------------------------------------------------
// セーブ
void TextAnimationSaver::save(
	const String& filePath, AnimationManager* manager){
	TextFileWriter* textFileWriter = new TextFileWriter(filePath);
	save(textFileWriter, manager);
	delete textFileWriter;
}
//------------------------------------------------------------------------------
// セーブ
void TextAnimationSaver::save(
	TextWriter* textWriter, AnimationManager* manager){
	writer_ = textWriter;
	manager_ = manager;
	// ヘッダの書き出し
	writeHeader();
	// オブジェクトのカウント
	if(countObjects() == 0){ return; }
	// アニメーションリストの書き出し
	writeAnimationList();
	// リンクの書き出し
	writeLink();
	writeLineComment();
}
//------------------------------------------------------------------------------
// ヘッダの書き出し
void TextAnimationSaver::writeHeader(){
	writeBlockComment("Header");
	writer_->writeText("Header {\n");
	writer_->writeText("\ttype LampTextAnimationFormat\n");
	writer_->writeText("\tversion 0_9_0\n");
	writer_->writeText("}\n\n");
}
//------------------------------------------------------------------------------
// オブジェクトのカウント
int TextAnimationSaver::countObjects(){
	// アニメーションカウントクリア
	animationCount_ = manager_->getCount();
	animationSetCount_ = 0;
	cameraCount_ = 0;
	sceneNodeCount_ = 0;
	characterModelCount_ = 0;
	// 各アニメーションのカウント
	for(int i = 0; i < animationCount_; i++){
		Animation* animation = manager_->get(i);
		if(animation->isAnimationSet()){
			animationSetCount_++;
		}else if(animation->isCameraAnimation()){
			cameraCount_++;
		}else if(animation->isSceneNodeAnimation()){
			sceneNodeCount_++;
		}else if(animation->isCharacterModelAnimation()){
			characterModelCount_++;
		}else{
			ErrorOut("TextAnimationSaver::countObjects() "
				"Unsupported animation type");
		}
	}
	// アニメーションデータカウントクリア
	animationDataCount_ = manager_->getDataCount();
	cameraDataCount_ = 0;
	sceneNodeDataCount_ = 0;
	characterModelDataCount_ = 0;
	// 各アニメーションデータのカウント
	for(int i = 0; i < animationDataCount_; i++){
		AnimationData* data = manager_->getData(i);
		if(data->isCameraAnimationData()){
			cameraDataCount_++;
		}else if(data->isSceneNodeAnimationData()){
			sceneNodeDataCount_++;
		}else if(data->isCharacterModelAnimationData()){
			characterModelDataCount_++;
		}else{
			ErrorOut("TextAnimationSaver::countObjects() "
				"Unsupported animation data type");
		}
	}
	return (animationCount_ + animationDataCount_);
}
//------------------------------------------------------------------------------
// アニメーションリストの書き出し
void TextAnimationSaver::writeAnimationList(){
	// アニメーションセットの書き出し
	if(animationSetCount_ != 0){
		writeBlockComment("AnimationSet");
		writer_->writeText("AnimationSet {\n");
		for(int i = 0; i < animationCount_; i++){
			Animation* animation = manager_->get(i);
			if(animation->isAnimationSet()){
				writeAnimationSet(animation->castAnimationSet());
			}
		}
		writer_->writeText("}\n\n");
	}
	// カメラアニメーションの書き出し
	if(cameraCount_ != 0){
		writeBlockComment("CameraAnimation");
		writer_->writeText("CameraAnimation {\n");
		for(int i = 0; i < animationCount_; i++){
			Animation* animation = manager_->get(i);
			if(animation->isCameraAnimation()){
				writeCameraAnimation(animation->castCameraAnimation());
			}
		}
		writer_->writeText("}\n\n");
	}
	// カメラアニメーションデータの書き出し
	if(cameraDataCount_ != 0){
		writeBlockComment("CameraAnimationData");
		writer_->writeText("CameraAnimationData {\n");
		for(int i = 0; i < animationDataCount_; i++){
			AnimationData* data = manager_->getData(i);
			if(data->isCameraAnimationData()){
				writeCameraAnimationData(
					data->castCameraAnimationData());
			}
		}
		writer_->writeText("}\n\n");
	}
	// シーンノードアニメーションの書き出し
	if(sceneNodeCount_ != 0){
		writeBlockComment("SceneNodeAnimation");
		writer_->writeText("SceneNodeAnimation {\n");
		for(int i = 0; i < animationCount_; i++){
			Animation* animation = manager_->get(i);
			if(animation->isSceneNodeAnimation()){
				writeSceneNodeAnimation(animation->castSceneNodeAnimation());
			}
		}
		writer_->writeText("}\n\n");
	}
	// シーンノードアニメーションデータの書き出し
	if(sceneNodeDataCount_ != 0){
		writeBlockComment("SceneNodeAnimationData");
		writer_->writeText("SceneNodeAnimationData {\n");
		for(int i = 0; i < animationDataCount_; i++){
			AnimationData* data = manager_->getData(i);
			if(data->isSceneNodeAnimationData()){
				writeSceneNodeAnimationData(
					data->castSceneNodeAnimationData());
			}
		}
		writer_->writeText("}\n\n");
	}
	// キャラクタモデルアニメーションの書き出し
	if(characterModelCount_ != 0){
		writeBlockComment("CharacterModelAnimation");
		writer_->writeText("CharacterModelAnimation {\n");
		for(int i = 0; i < animationCount_; i++){
			Animation* animation = manager_->get(i);
			if(animation->isCharacterModelAnimation()){
				writeCharacterModelAnimation(
					animation->castCharacterModelAnimation());
			}
		}
		writer_->writeText("}\n\n");
	}
	// キャラクタモデルアニメーションデータの書き出し
	if(characterModelDataCount_ != 0){
		writeBlockComment("CharacterModelAnimationData");
		writer_->writeText("CharacterModelAnimationData {\n");
		for(int i = 0; i < animationDataCount_; i++){
			AnimationData* data = manager_->getData(i);
			if(data->isCharacterModelAnimationData()){
				writeCharacterModelAnimationData(
					data->castCharacterModelAnimationData());
			}
		}
		writer_->writeText("}\n\n");
	}
}
//------------------------------------------------------------------------------
// リンクの書き出し
void TextAnimationSaver::writeLink(){
	writeBlockComment("Link");
	// アニメーションセットリンク
	if(animationSetCount_ != 0){
		writer_->writeText("AnimationSetLink {\n");
		for(int i = 0; i < animationCount_; i++){
			Animation* animation = manager_->get(i);
			if(animation->isAnimationSet()){
				writeAnimationSetLink(animation->castAnimationSet());
			}
		}
		writer_->writeText("}\n\n");
	}
	// カメラリンク
	if(cameraCount_ != 0){
		writer_->writeText("CameraLink {\n");
		for(int i = 0; i < animationCount_; i++){
			Animation* animation = manager_->get(i);
			if(animation->isCameraAnimation()){
				writeCameraAnimationLink(
					animation->castCameraAnimation());
			}
		}
		writer_->writeText("}\n\n");
	}
	// シーンノードリンク
	if(sceneNodeCount_ != 0){
		writer_->writeText("SceneNodeLink {\n");
		for(int i = 0; i < animationCount_; i++){
			Animation* animation = manager_->get(i);
			if(animation->isSceneNodeAnimation()){
				writeSceneNodeAnimationLink(
					animation->castSceneNodeAnimation());
			}
		}
		writer_->writeText("}\n\n");
	}
	// キャラクタモデルリンク
	if(characterModelCount_ != 0){
		writer_->writeText("CharacterModelLink {\n");
		for(int i = 0; i < animationCount_; i++){
			Animation* animation = manager_->get(i);
			if(animation->isCharacterModelAnimation()){
				writeCharacterModelAnimationLink(
					animation->castCharacterModelAnimation());
			}
		}
		writer_->writeText("}\n\n");
	}
}
//------------------------------------------------------------------------------
// アニメーションセット
//------------------------------------------------------------------------------
// アニメーションセットの書き出し
void TextAnimationSaver::writeAnimationSet(AnimationSet* animation){
	writer_->writeText("\t");
	writer_->writeText(animation->getName());
	writer_->writeText(" {\n");
	// 有効、無効
	writer_->writeText("\t\tenabled ");
	writeBool(animation->isEnabled());
	writer_->writeText("\n");
	writer_->writeText("\t}\n\n");
}
//------------------------------------------------------------------------------
// カメラ
//------------------------------------------------------------------------------
// カメラアニメーションの書き出し
void TextAnimationSaver::writeCameraAnimation(CameraAnimation* animation){
	writer_->writeText("\t");
	writer_->writeText(animation->getName());
	writer_->writeText(" {\n");
	// ターゲット名
	writer_->writeText("\t\ttargetName ");
	writer_->writeText(animation->getTargetName());
	writer_->writeText("\n");
	// 有効、無効
	writer_->writeText("\t\tenabled ");
	writeBool(animation->isEnabled());
	writer_->writeText("\n");
	writer_->writeText("\t}\n\n");
}
//------------------------------------------------------------------------------
// カメラアニメーションデータの書き出し
void TextAnimationSaver::writeCameraAnimationData(
	CameraAnimationData* data){
	writer_->writeText("\t");
	writer_->writeText(data->getName());
	writer_->writeText(" {\n");
	// シーケンス数
	int sequenceCount = data->getSequenceCount();
	writer_->writeFormat("\t\tsequenceCount %d\n", sequenceCount);
	// アニメーションデータの書き出し
	String tabDepth = "\t\t\t";
	for(int i = 0; i < sequenceCount; i++){
		writer_->writeFormat("\t\tsequence %d {\n", i);
		// 回転
		writeRotationInterpolator(
			data->getRotation(i), "rotation", tabDepth);
		// 移動
		writeVectorInterpolator(
			data->getTranslation(i), "translation", tabDepth);
		// ループフラグ
		writer_->writeText("\t\t\tlooped ");
		writeBool(data->isLooped(i));
		writer_->writeText("\n\t\t}\n");
	}
	writer_->writeText("\t}\n\n");
}
//------------------------------------------------------------------------------
// シーンノード
//------------------------------------------------------------------------------
// シーンノードアニメーションの書き出し
void TextAnimationSaver::writeSceneNodeAnimation(SceneNodeAnimation* animation){
	writer_->writeText("\t");
	writer_->writeText(animation->getName());
	writer_->writeText(" {\n");
	// ターゲット名
	writer_->writeText("\t\ttargetName ");
	writer_->writeText(animation->getTargetName());
	writer_->writeText("\n");
	// 有効、無効
	writer_->writeText("\t\tenabled ");
	writeBool(animation->isEnabled());
	writer_->writeText("\n");
	writer_->writeText("\t}\n\n");
}
//------------------------------------------------------------------------------
// シーンノードアニメーションデータの書き出し
void TextAnimationSaver::writeSceneNodeAnimationData(
	SceneNodeAnimationData* data){
	writer_->writeText("\t");
	writer_->writeText(data->getName());
	writer_->writeText(" {\n");
	// シーケンス数
	int sequenceCount = data->getSequenceCount();
	writer_->writeFormat("\t\tsequenceCount %d\n", sequenceCount);
	// アニメーションデータの書き出し
	String tabDepth = "\t\t\t";
	for(int i = 0; i < sequenceCount; i++){
		writer_->writeFormat("\t\tsequence %d {\n", i);
		// スケール
		writeVectorInterpolator(
			data->getScale(i), "scale", tabDepth);
		// 回転
		writeRotationInterpolator(
			data->getRotation(i), "rotation", tabDepth);
		// 移動
		writeVectorInterpolator(
			data->getTranslation(i), "translation", tabDepth);
		// ループフラグ
		writer_->writeText("\t\t\tlooped ");
		writeBool(data->isLooped(i));
		writer_->writeText("\n\t\t}\n");
	}
	writer_->writeText("\t}\n\n");
}
//------------------------------------------------------------------------------
// モデル
//------------------------------------------------------------------------------
// キャラクタモデルアニメーションの書き出し
void TextAnimationSaver::writeCharacterModelAnimation(
	CharacterModelAnimation* animation){
	writer_->writeText("\t");
	writer_->writeText(animation->getName());
	writer_->writeText(" {\n");
	// ターゲット名
	writer_->writeText("\t\ttargetName ");
	writer_->writeText(animation->getTargetName());
	writer_->writeText("\n");
	// ボーン数
	int boneCount = animation->getBoneCount();
	writer_->writeFormat("\t\tboneCount %d {\n", boneCount);
	for(int i = 0; i < boneCount; i++){
		writer_->writeText("\t\t\t");
		writer_->writeText(animation->getBoneName(i));
		writer_->writeText("\n");
	}
	writer_->writeText("\t\t}\n");
	// 有効、無効
	writer_->writeText("\t\tenabled ");
	writeBool(animation->isEnabled());
	writer_->writeText("\n");
	writer_->writeText("\t}\n\n");
}
//------------------------------------------------------------------------------
// キャラクタモデルアニメーションデータの書き出し
void TextAnimationSaver::writeCharacterModelAnimationData(
	CharacterModelAnimationData* data){
	writer_->writeText("\t");
	writer_->writeText(data->getName());
	writer_->writeText(" {\n");
	// ボーン数
	int boneCount = data->getBoneCount();
	writer_->writeFormat("\t\tboneCount %d\n", boneCount);
	// シーケンス数
	int sequenceCount = data->getSequenceCount();
	writer_->writeFormat("\t\tsequenceCount %d\n", sequenceCount);
	// アニメーションデータの書き出し
	String tabDepth = "\t\t\t\t";
	for(int i = 0; i < sequenceCount; i++){
		writer_->writeFormat("\t\tsequence %d {\n", i);
		for(int j = 0; j < boneCount; j++){
			writer_->writeFormat("\t\t\tbone %d {\n", j);
			// スケール
			writeVectorInterpolator(
				data->getScale(i, j), "scale", tabDepth);
			// 回転
			writeRotationInterpolator(
				data->getRotation(i, j), "rotation", tabDepth);
			// 移動
			writeVectorInterpolator(
				data->getTranslation(i, j), "translation", tabDepth);
			writer_->writeText("\t\t\t}\n");
		}
		// ループフラグ
		writer_->writeText("\t\t\tlooped ");
		writeBool(data->isLooped(i));
		writer_->writeText("\n\t\t}\n");
	}
	writer_->writeText("\t}\n\n");
}
//------------------------------------------------------------------------------
// リンク
//------------------------------------------------------------------------------
// アニメーションセットリンクの書き出し
void TextAnimationSaver::writeAnimationSetLink(AnimationSet* animation){
	int childCount = animation->getAnimationCount();
	if(childCount == 0){ return; }
	writer_->writeText("\t");
	writer_->writeText(animation->getName());
	writer_->writeText(" {\n");
	for(int i = 0; i < childCount; i++){
		Animation* child = animation->getAnimation(i);
		writer_->writeText("\t\t");
		writer_->writeText(child->getName());
		writer_->writeText("\n");
	}
	writer_->writeText("\t}\n\n");
}
//------------------------------------------------------------------------------
// カメラアニメーションリンクの書き出し
void TextAnimationSaver::writeCameraAnimationLink(
	CameraAnimation* animation){
	writer_->writeText("\t");
	writer_->writeText(animation->getName());
	writer_->writeText(" ");
	writer_->writeText(animation->getAnimationData()->getName());
	writer_->writeText("\n");
}
//------------------------------------------------------------------------------
// シーンノードアニメーションリンクの書き出し
void TextAnimationSaver::writeSceneNodeAnimationLink(
	SceneNodeAnimation* animation){
	writer_->writeText("\t");
	writer_->writeText(animation->getName());
	writer_->writeText(" ");
	writer_->writeText(animation->getAnimationData()->getName());
	writer_->writeText("\n");
}
//------------------------------------------------------------------------------
// キャラクタモデルアニメーションリンクの書き出し
void TextAnimationSaver::writeCharacterModelAnimationLink(
	CharacterModelAnimation* animation){
	writer_->writeText("\t");
	writer_->writeText(animation->getName());
	writer_->writeText(" ");
	writer_->writeText(animation->getAnimationData()->getName());
	writer_->writeText("\n");
}
//------------------------------------------------------------------------------
// ベクトル補間
//------------------------------------------------------------------------------
// ベクトル補間の書き出し
void TextAnimationSaver::writeVectorInterpolator(
	VectorInterpolator* interpolator,
	const String& name, const String& tabDepth){
	// NULL対応
	if(interpolator == NULL){
		writer_->writeText(tabDepth);
		writer_->writeText(name);
		writer_->writeText(" NULL\n");
		return;
	}
	// 各補間の書き出し
	if(interpolator->isVectorConstantInterpolator()){
		writeVectorConstantInterpolator(
			interpolator->castVectorConstantInterpolator(), name, tabDepth);
	}else if(interpolator->isVectorArrayInterpolator()){
		writeVectorArrayInterpolator(
			interpolator->castVectorArrayInterpolator(), name, tabDepth);
	}else if(interpolator->isVectorLinearInterpolator()){
		writeVectorLinearInterpolator(
			interpolator->castVectorLinearInterpolator(), name, tabDepth);
	}else{
		ErrorOut("TextAnimationSaver::writeVectorInterpolator() "
			"Unsupported interpolater");
	}
}
//------------------------------------------------------------------------------
// ベクトル定数補間の書き出し
void TextAnimationSaver::writeVectorConstantInterpolator(
	VectorConstantInterpolator* interpolator,
	const String& name, const String& tabDepth){
	// 名前
	writer_->writeText(tabDepth);
	writer_->writeText(name);
	writer_->writeText(" {\n");
	// タイプ
	writer_->writeText(tabDepth);
	writer_->writeText("\ttype Constant\n");
	// 長さ
	writer_->writeText(tabDepth);
	writer_->writeFormat("\tlength %.8f\n", interpolator->getLength());
	// 値
	writer_->writeText(tabDepth);
	Vector3 value = interpolator->getValue();
	writer_->writeFormat("\tvalue { %.8f %.8f %.8f }\n",
		value.x, value.y, value.z);
	writer_->writeText(tabDepth);
	writer_->writeText("}\n");
}
//------------------------------------------------------------------------------
// ベクトル配列補間の書き出し
void TextAnimationSaver::writeVectorArrayInterpolator(
	VectorArrayInterpolator* interpolator,
	const String& name, const String& tabDepth){
	// 名前
	writer_->writeText(tabDepth);
	writer_->writeText(name);
	writer_->writeText(" {\n");
	// タイプ
	writer_->writeText(tabDepth);
	writer_->writeText("\ttype Array\n");
	// 値
	writer_->writeText(tabDepth);
	int size = interpolator->getSize();
	writer_->writeFormat("\tvalue %d {\n", size);
	String valueTab = tabDepth + "\t\t";
	for(int i = 0; i < size; i++){
		writer_->writeText(valueTab);
		const Vector3& value = interpolator->getValue(i);
		writer_->writeFormat("{ %.8f %.8f %.8f }\n",
			value.x, value.y, value.z);
	}
	writer_->writeText(tabDepth);
	writer_->writeText("\t}\n");
	writer_->writeText(tabDepth);
	writer_->writeText("}\n");
}
//------------------------------------------------------------------------------
// ベクトル線形補間の書き出し
void TextAnimationSaver::writeVectorLinearInterpolator(
	VectorLinearInterpolator* interpolator,
	const String& name, const String& tabDepth){
	// 名前
	writer_->writeText(tabDepth);
	writer_->writeText(name);
	writer_->writeText(" {\n");
	// タイプ
	writer_->writeText(tabDepth);
	writer_->writeText("\ttype Linear\n");
	// 値
	writer_->writeText(tabDepth);
	int keyCount = interpolator->getKeyCount();
	writer_->writeFormat("\tvalue %d {\n", keyCount);
	String valueTab = tabDepth + "\t\t";
	for(int i = 0; i < keyCount; i++){
		writer_->writeText(valueTab);
		float time = interpolator->getTime(i);
		const Vector3& value = interpolator->getValue(i);
		writer_->writeFormat("%.8f { %.8f %.8f %.8f }\n",
			time, value.x, value.y, value.z);
	}
	writer_->writeText(tabDepth);
	writer_->writeText("\t}\n");
	writer_->writeText(tabDepth);
	writer_->writeText("}\n");
}
//------------------------------------------------------------------------------
// 回転補間
//------------------------------------------------------------------------------
// 回転補間の書き出し
void TextAnimationSaver::writeRotationInterpolator(
	RotationInterpolator* interpolator,
	const String& name, const String& tabDepth){
	// NULL対応
	if(interpolator == NULL){
		writer_->writeText(tabDepth);
		writer_->writeText(name);
		writer_->writeText(" NULL\n");
		return;
	}
	// 各補間の書き出し
	if(interpolator->isRotationConstantInterpolator()){
		writeRotationConstantInterpolator(
			interpolator->castRotationConstantInterpolator(), name, tabDepth);
	}else if(interpolator->isEulerArrayInterpolator()){
		writeEulerArrayInterpolator(
			interpolator->castEulerArrayInterpolator(), name, tabDepth);
	}else if(interpolator->isQuaternionArrayInterpolator()){
		writeQuaternionArrayInterpolator(
			interpolator->castQuaternionArrayInterpolator(), name, tabDepth);
	}else if(interpolator->isQuaternionLinearInterpolator()){
		writeQuaternionLinearInterpolator(
			interpolator->castQuaternionLinearInterpolator(), name, tabDepth);
	}else{
		ErrorOut("TextAnimationSaver::writeRotationInterpolator() "
			"Unsupported interpolater");
	}
}
//------------------------------------------------------------------------------
// 回転定数補間の書き出し
void TextAnimationSaver::writeRotationConstantInterpolator(
	RotationConstantInterpolator* interpolator,
	const String& name, const String& tabDepth){
	// 名前
	writer_->writeText(tabDepth);
	writer_->writeText(name);
	writer_->writeText(" {\n");
	// タイプ
	writer_->writeText(tabDepth);
	writer_->writeText("\ttype Constant\n");
	// 長さ
	writer_->writeText(tabDepth);
	writer_->writeFormat("\tlength %.8f\n", interpolator->getLength());
	// 値
	writer_->writeText(tabDepth);
	Quaternion value = interpolator->getQuaternion();
	writer_->writeFormat("\tquaternionValue { %.8f %.8f %.8f %.8f }\n",
		value.x, value.y, value.z, value.w);
	writer_->writeText(tabDepth);
	writer_->writeText("}\n");
}
//------------------------------------------------------------------------------
// オイラー回転配列補間の書き出し
void TextAnimationSaver::writeEulerArrayInterpolator(
	EulerArrayInterpolator* interpolator,
	const String& name, const String& tabDepth){
	// 名前
	writer_->writeText(tabDepth);
	writer_->writeText(name);
	writer_->writeText(" {\n");
	// タイプ
	writer_->writeText(tabDepth);
	writer_->writeText("\ttype EulerArray\n");
	// 値
	writer_->writeText(tabDepth);
	int size = interpolator->getSize();
	writer_->writeFormat("\tvalue %d {\n", size);
	String valueTab = tabDepth + "\t\t";
	for(int i = 0; i < size; i++){
		writer_->writeText(valueTab);
		const Vector3& value = interpolator->getValue(i);
		writer_->writeFormat("{ %.8f %.8f %.8f }\n",
			value.x, value.y, value.z);
	}
	writer_->writeText(tabDepth);
	writer_->writeText("\t}\n");
	writer_->writeText(tabDepth);
	writer_->writeText("}\n");
}
//------------------------------------------------------------------------------
// 四元数回転配列補間の書き出し
void TextAnimationSaver::writeQuaternionArrayInterpolator(
	QuaternionArrayInterpolator* interpolator,
	const String& name, const String& tabDepth){
	// 名前
	writer_->writeText(tabDepth);
	writer_->writeText(name);
	writer_->writeText(" {\n");
	// タイプ
	writer_->writeText(tabDepth);
	writer_->writeText("\ttype QuaternionArray\n");
	// 値
	writer_->writeText(tabDepth);
	int size = interpolator->getSize();
	writer_->writeFormat("\tvalue %d {\n", size);
	String valueTab = tabDepth + "\t\t";
	for(int i = 0; i < size; i++){
		writer_->writeText(valueTab);
		const Quaternion& value = interpolator->getValue(i);
		writer_->writeFormat("{ %.8f %.8f %.8f %.8f }\n",
			value.x, value.y, value.z, value.w);
	}
	writer_->writeText(tabDepth);
	writer_->writeText("\t}\n");
	writer_->writeText(tabDepth);
	writer_->writeText("}\n");
}
//------------------------------------------------------------------------------
// 四元数回転線形補間の書き出し
void TextAnimationSaver::writeQuaternionLinearInterpolator(
	QuaternionLinearInterpolator* interpolator,
	const String& name, const String& tabDepth){
	// 名前
	writer_->writeText(tabDepth);
	writer_->writeText(name);
	writer_->writeText(" {\n");
	// タイプ
	writer_->writeText(tabDepth);
	writer_->writeText("\ttype QuaternionLinear\n");
	// 値
	writer_->writeText(tabDepth);
	int keyCount = interpolator->getKeyCount();
	writer_->writeFormat("\tvalue %d {\n", keyCount);
	String valueTab = tabDepth + "\t\t";
	for(int i = 0; i < keyCount; i++){
		writer_->writeText(valueTab);
		float time = interpolator->getTime(i);
		const Quaternion& value = interpolator->getValue(i);
		writer_->writeFormat("%.8f { %.8f %.8f %.8f %.8f }\n",
			time, value.x, value.y, value.z, value.w);
	}
	writer_->writeText(tabDepth);
	writer_->writeText("\t}\n");
	writer_->writeText(tabDepth);
	writer_->writeText("}\n");
}
//------------------------------------------------------------------------------
// ユーティリティ
//------------------------------------------------------------------------------
// boolの書き出し
void TextAnimationSaver::writeBool(bool flag){
	if(flag){
		writer_->writeText("true");
	}else{
		writer_->writeText("false");
	}
}
//------------------------------------------------------------------------------
// 線コメントの書き出し
void TextAnimationSaver::writeLineComment(){
	writer_->writeText("//----------------------------"
		"--------------------------------------------------\n");
}
//------------------------------------------------------------------------------
// ブロックコメントの書き出し
void TextAnimationSaver::writeBlockComment(const String& blockName){
	writeLineComment();
	writer_->writeText("// ");
	writer_->writeText(blockName);
	writer_->writeText(" Block\n");
	writeLineComment();
}
//------------------------------------------------------------------------------
} // End of namespace Lamp
//------------------------------------------------------------------------------
