//------------------------------------------------------------------------------
// 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 "System/stdafx.h"
#include "Translator/Animation/TranslationSequence.h"

namespace LampForMaya{

//------------------------------------------------------------------------------
// コンストラクタ
TranslationSequence::TranslationSequence() :
	hasSequence_(false), sequenceCount_(0),
	startTime_(NULL), endTime_(NULL), looped_(NULL){
}
//------------------------------------------------------------------------------
// デストラクタ
TranslationSequence::~TranslationSequence(){
	SafeArrayDelete(startTime_);
	SafeArrayDelete(endTime_);
	SafeArrayDelete(looped_);
}
//------------------------------------------------------------------------------
// 分析
bool TranslationSequence::analyze(const MObject& object){
	hasSequence_ = false;
	String errorString;
	MStatus result;
	MFnDependencyNode dependencyNode(object, &result);
	MayaStatusCheck(result);
	MString name = dependencyNode.name(&result);
	MayaStatusCheck(result);
	// シーケンスアトリビュートが存在するか
	MString sequenceName("LampSequence");
	MObject attribute = dependencyNode.attribute(sequenceName, &result);
	if(!result){ return hasSequence_; }
	// シーケンスアトリビュートがアニメーションしているか
	MPlug attributePlug = dependencyNode.findPlug(sequenceName, &result);
	MayaStatusCheck(result);
	if(!MAnimUtil::isAnimated(attributePlug)){
//		MayaErrorOut(MString("TranslationSequence::analyze() ") + sequenceName +
//			"アトリビュートが有りますが、アニメーションしていません " + name);
		return hasSequence_;
	}
	// アニメーションカーブの取得
	MPlugArray plugArray;
	if(!attributePlug.connectedTo(plugArray, true, false, &result)){
		MayaErrorOut(MString("TranslationSequence::analyze() ") + sequenceName +
			"アトリビュートが有りますが、アニメーションしていません " + name);
		return hasSequence_;
	}
	MayaStatusCheck(result);
	if(plugArray.length() != 1){
		MayaErrorOut(MString("TranslationSequence::analyze() ") + sequenceName +
			"アトリビュートが有りますが、複数のプラグが接続されています " + name);
		return hasSequence_;
	}
	MObject curveObject = plugArray[0].node(&result);
	MayaStatusCheck(result);
	MFnAnimCurve curve(curveObject, &result);
	MayaStatusCheck(result);
	// アニメーションキーが1つ以上あるか
	u_int keyCount = curve.numKeys(&result);
	MayaStatusCheck(result);
	if(keyCount == 0){
		MayaErrorOut(MString("TranslationSequence::analyze() ") + sequenceName +
			"アトリビュートが有りますが、キーがありません " + name);
		return hasSequence_;
	}
	// キーの間隔チェック
	double preTime = 0.f;
	for(u_int i = 0; i < keyCount; i++){
		double time = curve.time(i, &result).value();
		MayaStatusCheck(result);
		if(time - preTime < 2.0){
			MayaErrorOut(MString("TranslationSequence::analyze() "
				"シーケンスのアニメーションキーは時間の間隔が2以上必要です ") +
				name);
			return hasSequence_;
		}
		preTime = time;
	}
	// キーのエラーチェック
	for(u_int i = 0; i < keyCount; i++){
		// 時間が-のキーが無いかチェック
		double time = curve.time(i, &result).value();
		MayaStatusCheck(result);
		if(time < 0.0){
			MayaErrorOut(MString("TranslationSequence::analyze() "
				"シーケンスのアニメーションキーは+の時間を設定してください ") +
				name + " " + time);
			return hasSequence_;
		}
		// 端数が無いかチェック
//		double integer;
//		double fraction = ::modf(time, &integer);
//		if(fraction > (double)Math::epsilon){
//			MayaErrorOut(MString("TranslationSequence::analyze() "
//				"シーケンスのアニメーションキーは整数時間を設定してください ") +
//				name + " " + time);
//			return hasSequence_;
//		}
	}
	// シーケンスデータ作成
	sequenceCount_ = keyCount;
	SafeArrayDelete(startTime_);
	SafeArrayDelete(endTime_);
	SafeArrayDelete(looped_);
	startTime_ = new int[sequenceCount_];
	endTime_ = new int[sequenceCount_];
	looped_ = new bool[sequenceCount_];
	MTime time;
	double value;
	// 1番目シーケンス作成
	startTime_[0] = 0;
	time = curve.time(0, &result);
	MayaStatusCheck(result);
	endTime_[0] = (int)time.value();
	MayaStatusCheck(curve.evaluate(time, value));
	looped_[0] = (value > 0.5);
	// 2番目以降のシーケンス作成
	for(int i = 1; i < sequenceCount_; i++){
		startTime_[i] = (int)curve.time((i - 1), &result).value() + 1;
		MayaStatusCheck(result);
		time = curve.time(i, &result);
		MayaStatusCheck(result);
		endTime_[i] = ((int)time.value());
		MayaStatusCheck(curve.evaluate(time, value));
		looped_[i] = (value > 0.5);
	}
/*
	for(int i = 0; i < sequenceCount_; i++){
		MTime time = curve.time(i, &result);
		startTime_[i] = (int)time.value();
		MayaStatusCheck(result);
		endTime_[i] = ((int)curve.time(i + 1, &result).value()) - 1;
		MayaStatusCheck(result);
		double value;
		result = curve.evaluate(time, value);
		looped_[i] = (value > 0.5);
	}
*/
	hasSequence_ = true;
	return hasSequence_;
}
//------------------------------------------------------------------------------
} // End of namespace Lamp
//------------------------------------------------------------------------------
