/*
	Ninja Library
	
	COPYRIGHT ( C ) SEGA ENTERPRISES, LTD.
*/

#include "NuMotionMake.h"



/*	シェープ情報構造体（スロット）		*/
NUS_CUR_SHAPE_INFO		_nu_shape_info_[NUD_SHAPE_INFO_MAX];

/*	現在処理中のシェープ情報		*/
NUS_CUR_SHAPE_INFO		*_nu_shpinfo_ptr_;

NUS_SHAPE_GROUP_COEFF	*_nu_shape_buf_;
NUS_CSHAPELIST *_nu_shape_list_;

/*
	func:	NUS_MDATA(n) 配列への参照ポインタが一つ進められる。
			オブジェクトモーションにおいて、次のノードに進むために使用する。
	
	note:	_nuSetShapeMDataCnt( MDataCnt );		を呼び出しておくこと。
*/
void nuSetNextShapeNodeEx( void )
{
	_nu_shpinfo_ptr_->mdata		+= 1;
	_nu_shpinfo_ptr_->cnt		= _nu_shpinfo_ptr_->mdata->nb[0];
	_nu_shpinfo_ptr_->group		= _nu_shpinfo_ptr_->mdata->p[0];
}


/*
	func:	現在のシェープパラメータを設定する。
			NUS_MDATA(n) 配列への参照ポインタが、その先頭にセットされる。
			
	in:		_nu_shpinfo_ptr_	= シェープ情報構造体へのポインタ（内容はどうでもよい）
			
			shape		= シェープ
			frame		= フレーム番号
	
	out:	_nu_shpinfo_ptr_	= シェープ情報
	
	注意:	この関数は、_nu_shpinfo_ptr_ に対して出力を行う。
			nuSetCurShapeInfoSlot() などを用いて必ず初期化すること。
*/
void nuStartShapeEx( const NUS_MOTION *shape, Float frame )
{
	_nu_shpinfo_ptr_->mdata		= shape->mdata;
	_nu_shpinfo_ptr_->nbframes	= shape->nbFrame;
	_nu_shpinfo_ptr_->frame		= frame;
	_nu_shpinfo_ptr_->checkID	++;

	_nu_shpinfo_ptr_->cnt		= _nu_shpinfo_ptr_->mdata->nb[0];
	_nu_shpinfo_ptr_->group		= _nu_shpinfo_ptr_->mdata->p[0];
}

/*
	func:	モーション関数群が読み書きするモーション情報構造体を指定する。
	
	expl.:	この指定は、次にこの関数や、nuSetCurShapeInfoSlot() が呼び出されるまで
			有効である。
*/
void nuSetCurShapeInfoPtr( const NUS_CUR_SHAPE_INFO *shape_info_ptr )
{
	_nu_shpinfo_ptr_	= shape_info_ptr;
}

/*
	func:	モーション関数群が読み書きするモーション情報構造体のスロット番号を指定する。
	
	in:		Slot	= モーション構造体のスロット番号
					  0 〜 NUD_SHAPE_INFO_MAX - 1
	
	expl.:	この指定は、次にこの関数や、nuSetCurShapeInfoPtr() が呼び出されるまで
			有効である。
*/
void nuSetCurShapeInfoSlot( int Slot )
{
	_nu_shpinfo_ptr_	= &_nu_shape_info_[Slot];
}

/*
	この関数は、シェープグループIDの補間係数を格納するバッファを確保する
*/
void nuInitShape( void *buf, Sint32 size )
{
	Sint32	i;
	NUS_SHAPE_GROUP_COEFF *p;
	
	_nu_shape_buf_ = buf;

	p = buf;
	size  = size / ( sizeof(NUS_SHAPE_GROUP_COEFF) );
	
	for( i=0; i<size; i++ ) {
		p->checkID = 0;
	}
}

/*
	シェープリスト設定
*/
void nuSetShapeList( const NUS_CSHAPELIST *shape_list )
{
	_nu_shape_list_ = shape_list;
}

/*
	モデルのVlistにシェープデータを計算して埋め込みます
*/
void nuCalcShapeVlist( const NJS_CNK_MODEL *cnkmodel )
{
	Sint32	i;
	Uint16	*vlist;
	Uint32	vtype,size;
	

	vlist = (Uint16*)cnkmodel->vlist;

	//１ノードで複数チャンクに分かれます
	for( i=0; i<_nu_shpinfo_ptr_->cnt; i++ ) {
		nuGetShapeGroupID();

		vtype = *vlist++ & 0x00ff;
		size = *vlist++;		/* size */
		vlist++;				/* offset */
		vlist++;				/* vertex num */

		//オリジナルのVlistとシェープデータポインタでデータを埋め込みます
		nuSetShapeVlist( (Uint32*)vlist, vtype );
		
		//次のシェープデータ
		_nu_shpinfo_ptr_->group += 1;
		//次のチャンク
		vlist += size * 2 - 2;
	}
}

/*
	カレントのキーグループIDをチェックし、
	補間係数をセットする
*/
void nuGetShapeGroupID( void )
{
	Uint32	id,group;
	NUS_MKEY_SHAPEID	*key1,*key2;
	Float	Rate;
	
	id = _nu_shpinfo_ptr_->group->keys->shapeId;
	
	group = _nu_shape_list_->shapes[id].groupId;
	_nu_shpinfo_ptr_->KeyGroupID = group;
	
	//補間係数をすでに計算しているか
	if( _nu_shape_buf_[group].checkID != _nu_shpinfo_ptr_->checkID ) {
		
		_nuGetMotionLinearKeys( _nu_shpinfo_ptr_->group->keys, sizeof( NUS_MKEY_SHAPEID ), _nu_shpinfo_ptr_->group->nbKey,
								_nu_shpinfo_ptr_->frame, (void**)&key1, (void**)&key2, &Rate );
		
		_nu_shape_buf_[group].checkID  = _nu_shpinfo_ptr_->checkID;
		_nu_shape_buf_[group].ShapeID1 = key1->shapeId;
		_nu_shape_buf_[group].ShapeID2 = key2->shapeId;
		_nu_shape_buf_[group].rate     = Rate;
	}
}
