//===================================================================
//
// ExportXS.h
// ExportXS.cpp
//
// 外部プラグインからのデータアクセスサンプル
//
//===================================================================

■概要
　外部エクスポートプラグインなどからKeynoteのデータに
　アクセスをするサンプルです。
　色々と仕様には悩みましたが、プラグイン内部で一度
　テンポラリクラスを作成し、そのクラス経由でデータを取得する形に
　しています。
　　
　独自のアニメーションフォーマットを作成したい場合、
　高価な3Dソフトに頼らざるを得ません。
　また、独自のエクスポートプラグインを書く際には
　SDK読解にそれなりの時間がかかります。
　KeynoteではMetasequoiaのプラグイン作成が出来る方であれば
　比較的容易にデータ作成が出来る事を目的としています。
　基本的なデータ型や関数はMetasequoiaと近いものにしていますので
　短時間での習得が可能です。

■注意点
　全てpublic扱いにしていますが、
　データへのアクセスは関数経由での取得のみの利用にして下さい。
　将来的には内部→外部だけでなく内部⇔外部の双方向のデータアクセスを
　可能にするかも知れませんが、現状未定です。
　※Keynote 0.0.3.2にてモーションデータに関しては外部プラグインから
　　データ送信出来るようにしました。サンプルも更新しています。
　
　Metasequoiaでは面ごとにUV情報を保持していますが、
　頂点ごとにUVを持たせる為に、Keynote内部で頂点を分離しています。
　オリジナルのMQOと頂点数が異なる場合がありますが、正常な動作です。
　分割前の情報を取得したい場合には描画用のMQObjectから頂点数、
　面構成を取得し、位置情報はXSMeshから取得して下さい。
　Keynoteでは線ポリゴンを全て破棄する為、オリジナルMQObjectと
　作成されたMQObjectでは頂点のindex配列が異なる場合があります。

■サンプルの解説
int ExportXS::CheckVersion(MQDocument doc)

　対応していないバージョンの場合には負の整数が
　戻ります。対応可能の場合にはKeynote側が
　保持しているフォーマットのバージョンが返ります。
　
CXSDocument* ExportXS::CreateXSDocument(MQDocument doc)

　XSDocument(=CXSDocument*)を取得。
　基本的に全てのデータはここからアクセスします。
　
BOOL ExportXS::DeleteXSDocument(MQDocument doc)

　内部のテンポラリクラスを削除します。
　削除はKeynote側で行いますので、外部から
　実体を削除してはいけません。
　
int ExportXS::FrameMove(MQDocument doc, int framenum)

　カレントフレームを移動します。
　返り値は現在のフレームです。
　framenumにマイナスの値を指定することで
　カレントフレームを移動させずにカレントフレームの取得が出来ます。
　
int ExportXS::SetAnimationSet(MQDocument doc, int index)

　Keynoteではフレームが0のAnimationSetを出力しません。
　indexにはXSAnimationSet::GetIndexで取得のindexを
　指定して下さい。

BOOL ExportXS::IsActive(MQDocument doc)
　Keynoteのウィンドウのアクティブ状態をチェックします。
　内部データの状況に関わらず、ウィンドウの表示非表示状態のみをチェックします。

BOOL ExportXS::SendXSAnimation(MQDocument doc, const char* data)
　外部プラグインからKeynoteにモーションデータを転送します。
　転送するデータフォーマットはKeynoteのクリップボードと同じ形式です。
　動作としてもKeynote上でペーストをした際と同様になります。
　つまりカレントフレームにデータ転送されますので、必要に応じて
　フレーム移動後に実施して下さい。
　存在しないボーン名、メッシュ名はスキップされますがCreateXSDocumentで
　Keynote内部データをチェック後に実施するのが確実です。
　※後述「クリップボードのフォーマット」参照
　
float ExportXS::GetFPS(void)
　Keynoteが保持しているFPSを取得します。Keynoteからは1000をかけたint型で
　値が戻る事に注意して下さい。
　
■構造体

typedef struct XSVertex
　ヘッダ参照
　
typedef struct XSFace
　ヘッダ参照
　
typedef struct XSWeight
　
　indexとnumはKeynote内部で使用しています。
　外部からは使いません。
　XSMeshクラスの中のウェイト情報は頂点情報と対になっています。
　（つまり頂点数とウェイト数は常に同一です）
　以下に頂点のウェイトと関連ボーンの取得のコードを記します。
　
　int vert_index;	//頂点のインデックス
　XSMesh xsm;
　
　XSWeight wgt = xsm->GetWeight(vert_index);
　XSBone bone0,bone1;
　float w0,w1;
　
　//refはその頂点に影響を与えるボーンの数
　switch(wgt.ref) 
　{
　case 0; //スキニングなし
　	break;
　case 1; //100%のスキニング
　	bone0 = xs->GetBone(wgt.refbone[0]);
　	w0 = wgt.weight[0]; //ここでは1ボーンの影響なのでw0は1.0になる
　	break;
　case 2; //ブレンド
　	bone0 = xs->GetBone(wgt.refbone[0]);
　	bone1 = xs->GetBone(wgt.refbone[1]);
　	w0 = wgt.weight[0]; //ウェイト取得
　	w1 = wgt.weight[1]; //ウェイト取得
　	break;
　}
typedef struct XSVectorKey
　numはフレームのインデックス
　ヘッダ参照
　
typedef struct XSQuaternionKey
　ヘッダ参照
　
typedef struct XSMeshState
　visibleはアニメーション内のXSMeshの可視状態です。
　他は将来の予約。
　
typedef struct XSSceneAttribute
　Sceneモードで書き込んだ文字列を保持します。
　
typedef struct XSPluginMsg
　Keynoteから外部プラグインにアクセスする際に
　使用している構造体です、通常使用しません。

■クラス

class CXSDocument
　データアクセスの親。
　
class CXSMesh
　メッシュクラス。
　m_MQObjはKeynoteが使用している描画用オブジェクトです。
　Metasequoiaの画面上で反映されているボーン変形の結果は
　ここから取得が可能です。
　
class CXSBone
　ボーンクラス。
　m_attrにはマテリアルのバンプファイル名が入ります。
　Metasequoiaでバンプを使用する事はまず無いと思いますので
　ボーンに独自データを持たせたい場合にはバンプに文字列を記載し、
　ここから取得してください。
　m_pivot[3]にはボーンの元になった三角ポリゴンの頂点位置が入っています。
　※m_pivot[0]=始点、m_pivot[1]=終点、m_pivot[2]、残りの頂点。
　m_matrixにはボーンの初期回転情報が入っています。
　m_typeにはボーンの属性が入っています。
　現在は浮動ボーンの際に1が入ります。
　pParentにはボーンの親へのポインタが入ります。
　m_cur_matrixには現在のボーンの姿勢が入ります。
　これは回転情報と移動情報を含んだMatrixです。
　現在の姿勢を更新するにはSetAnimationSet、FrameMoveで
　Keynote側の姿勢を更新する必要があります。
　
class CXSMaterial
　Metasequoiaとほぼ同一です。
　ただし、ボーン作成用のマテリアルは名前等、
　オリジナルとデータが異なる場合があります。
　※[]LR自動指定などの為
　
class CXSAnimationSet
　アニメーションにアクセスする基本クラスです。
　m_nInterpolateには補間タイプが入ります。
　
class CXSAnimationKey
　KeynoteはMatrixではなく、VectorとQuaternionで
　アニメーションを制御しています。
　そのキー情報が入ります。
　キーの数はボーンの数と同一です。
　
class CXSAnimationState
　メッシュの情報変更に対するパラメータが入ります。
　現状有効なのはXSMeshStateのvisibleのみです。
　XSMeshStateの数はメッシュの数と同一です。
　
■クリップボードのフォーマット

テキスト形式の単純なフォーマットです。
特に説明は不要かも知れませんが、以下の様に定義しています。

注意点
・データ構造毎に改行が必要です
・大文字、小文字は区別します
・空行は無視されます

・ヘッダ
　"xsc 0002"
　必須です。現在のバージョンは0002です。これ以外は破棄されます。

・ボーン名
　"bn %s"
　%sにボーン名を指定します。「bn」はボーンの略です。

・ボーンの移動
　"v %f %f %f"
　「bn」で検索されたボーンに対して動作します。
　成分はx,y,zの順で、成分の省略は出来ません。
　移動可能であるボーンは、ルートボーンもしくは浮動ボーンのみです。
　
・ボーンの回転
　"q %f %f %f %f"
　「bn」で検索されたボーンに対して動作します。
　成分はx,y,z,wの順で、成分の省略は出来ません。
　回転成分はボーンの初期姿勢に依存しません。
　
・メッシュ名
　"ms %s"
　%sにメッシュ名を指定します。「ms」はメッシュの略です。

・メッシュの表示
　"sh %d"
　「ms」で検索されたメッシュに対して動作します。
　%dに表示状態を指定します。0で非表示、1で表示です。
　
・メッシュのFloat値
　"f %f"
　「ms」で検索されたメッシュに対して動作します。
　Keynoteではエレメントオブジェクトに対して動作します。
　内部で-1.0f〜1.0fの値にクランプされます。
　
・ボーン回転基準
　"noiv %d"
　通常は0です。Keynoteではモーションが初期姿勢に
　依存しないようにボーンの回転は親ボーンの差分を記録しています。
　ボーンのローカル回転を記録したソフトからのデータ以降時
　この値に1を指定すると親の姿勢を考慮しません。


他、不明点があればお問い合わせ下さい。
