/*
 *	ExportPieceClip.cpp
 *
 *	P/ECE CLiP Library 3D Object Exporter
 *	Copyright (C) 2006 Naoyuki Sawa
 *
 *	* Tue Jun 27 07:27:03 JST 2006 Naoyuki Sawa
 *	- 作成開始。
 *	  実行環境: Metasequoia Ver2.3.4
 *	  作成環境: Metasequoia Plug-in SDK Rev2.31 (2004/02/28)
 *	* Tue Jun 27 23:45:49 JST 2006 Naoyuki Sawa
 *	- 1st リリース。
 *	  現時点で、テクスチャ座標出力が未実装です。
 *	* Wed Jun 28 04:23:49 JST 2006 Naoyuki Sawa
 *	- RGB→モノクロ変換の明暗が逆だったのを修正しました。
 *	* Wed Jun 28 14:55:11 JST 2006 Naoyuki Sawa
 *	- MQ_ExportAxis()の座標軸変換は仕様がよくわからないので、自前で処理することにしました。
 *	  MQ_ExportAxis()は、Z軸反転を指示すると、勝手にX軸まで反転してしまうみたいです。
 *	  仕様がよくわからないので、自前で座標軸変換を行い、Z軸反転だけ行うことにします。
 *	- Metasequoiaの標準的なスケールは大きすぎるので、100分の1で出力することにします。
 *	  この変換処理は、MQFileDialogInfo.scaleの設定に相当します。
 *	  ダイアログで変更することができなくなってしまいましたが、とりあえず固定とします。
 *	  いずれ、カスタムダイアログを作って、変更できるようにしようと思います。(※TODO:)
 *	* Thu Jun 29 01:25:58 JST 2006 Naoyuki Sawa
 *	- テクスチャ座標出力を追加しました。
 *	- P/ECE CLiP Libraryのrender_mesh()は、メッシュ単位で一つのテクスチャを適用(または無し)するので、
 *	  実際には、複数のテクスチャを使用したオブジェクトを表示することはできません。
 *	  しかし、本ツールの出力ファイルには、テクスチャとの関連付けは含まれず、単にテクスチャ座標配列を
 *	  出力するのみなので、エラーとせずにそのまま出力することにしました。利用者側で注意してください。
 *	- P/ECE CLiP Libraryのテクスチャ座標は、ピクセル座標系で、0〜255の値を取ります。
 *	  テクスチャサイズが255未満の場合は、それよりも大きい値(0〜255)を指定することで、ループが可能です。
 *	  Metasequoiaのテクスチャ座標は、テクスチャサイズを0.0〜1.0とするグリッド座標系です。
 *	  ピクセル座標系に変換した結果、0〜255の範囲を超えた場合は、P/ECE上では正しいテクスチャ座標となりません。
 *	  今回の実装では、エラーとせずに単に0〜255にマスクして出力することにしました。利用者側で注意してください。
 *	* Thu Jun 29 04:15:33 JST 2006 Naoyuki Sawa
 *	- 失敗時のエラーメッセージボックスを追加しました。
 *	* Thu Jun 29 11:55:47 JST 2006 Naoyuki Sawa
 *	- アプリケーション全体の定義をapp.hに、メッシュエクスポート機能をExportMesh.cppに分離しました。
 *	- ワイヤフレームエクスポート機能を作成開始。(ExportWire.cpp)
 *	* Wed Jul 26 06:27:42 JST 2006 Naoyuki Sawa
 *	- オプションダイアログにて、拡大率と反転軸を指定できるよう、変更しました。
 *	* Wed Sep 27 03:54:09 JST 2006 Naoyuki Sawa
 *	- メッシュファイルの拡張子を、xml→pmxに変更しました。
 *	- ワイヤーフレームファイルの拡張子を、xml→pwxに変更しました。
 *	* Sun Aug 10 21:42:25 JST 2008 Naoyuki Sawa
 *	- <vector>要素を固定小数点でなく浮動小数点で出力するよう変更しました。
 *	  浮動小数点MESHとして使用する場合は、浮動小数点のまま読み込んでください。
 *	  固定小数点MESHとして使用する場合は、読み込み時に固定小数点に変換してください。
 */
#include "app.h"

/*****************************************************************************
 *	ローカル変数
 *****************************************************************************/

static HMODULE hModule;		/* DLLモジュールハンドル */

static OPTION option = {	/* オプションダイアログの設定内容 */
	1.0,	/* scale */
	-2,	/* exp */
	2,	/* axis */
};

/*****************************************************************************
 *	ライブラリ関数
 *****************************************************************************/

/* DLLが、プロセスやスレッドにアタッチ、または、デタッチされたときに、Windowsシステムから呼び出されます。
 * 厳密には、初回のプロセスアタッチ時のみ処理すれば充分ですが、hinstDLLはいつも同じなので、区別しないことにします。
 * - ダイアログリソースをロードするために、DLLモジュールハンドルを記憶しておきます。
 *   DoOptionDialog()で必要となるために、DllMain()の定義を追加しました。(2006/07/26)
 *   DLLモジュールハンドルを記憶しておくことが不要ならば、DllMain()を定義する必要はありません。
 */
BOOL WINAPI
DllMain(HINSTANCE hinstDLL,	/* handle to DLL module */
	DWORD fdwReason,	/* reason for calling function */
	LPVOID lpvReserved)	/* reserved */
{
	hModule = hinstDLL;
	return TRUE;
}

/* プロダクト名(制作者名)とIDを、全部で64bitの値として返します。
 * ProductおよびIDの値は他と重複しないような適当にランダムなもので構いません。
 * この関数は起動時に呼び出されます。
 * [in]
 *	Product		プロダクト名(制作者名)をセットすべきポインタ。
 *	ID		プロダクトIDをセットすべきポインタ。
 */
MQPLUGIN_EXPORT void
MQGetPlugInID(DWORD* Product, DWORD* ID)
{
	*Product = APP_PRODUCT;
	*ID      = APP_ID;
}

/* [プラグインについて]ダイアログ上で表示するプラグイン名を返します。
 * この関数はダイアログ表示時に呼び出されます。
 * [out]
 *	戻り値		プラグイン名。
 */
MQPLUGIN_EXPORT const char*
MQGetPlugInName()
{
	return "P/ECE CLiP Library 3D Object Exporter, Copyright (C) 2006-2008 Naoyuki Sawa";
}

/* プラグインのタイプを返します。
 * この関数は起動時に呼び出されます。
 * [out]
 *	戻り値		プラグインタイプ。
 *			[MQPLUGIN_TYPE_IMPORT] ファイル入力用
 *			[MQPLUGIN_TYPE_EXPORT] ファイル出力用
 *			[MQPLUGIN_TYPE_CREATE] オブジェクト作成用
 *			[MQPLUGIN_TYPE_OBJECT] オブジェクト変形用
 *			[MQPLUGIN_TYPE_SELECT] 選択部変形用
 */
MQPLUGIN_EXPORT int
MQGetPlugInType()
{
	return MQPLUGIN_TYPE_EXPORT;
}

/* ファイルの形式名を返します。
 * 返した形式名はファイルダイアログ上のコンボボックスに表示されます。
 * この関数は起動時に呼び出されます。
 * indexは0から順に呼び出されるごとに増えていき、戻り値としてNULLを返したときに呼び出しが終了します。
 * [in]
 *	index		ファイルの種類のインデクス。
 * [out]
 *	戻り値		プラグイン名。
 */
MQPLUGIN_EXPORT const char*
MQEnumFileType(int index)
{
	switch(index){
	case 0:	/* メッシュ */
	//	return "P/ECE CLiP Library Mesh (*.xml)";
	//↓* Wed Sep 27 03:54:09 JST 2006 Naoyuki Sawa
	//↓- メッシュファイルの拡張子を、xml→pmxに変更しました。
		return "P/ECE CLiP Library Mesh (*.pmx)";
	case 1:	/* ワイヤフレーム */
	//	return "P/ECE CLiP Library Wire (*.xml)";
	//↓* Wed Sep 27 03:54:09 JST 2006 Naoyuki Sawa
	//↓- ワイヤーフレームファイルの拡張子を、xml→pwxに変更しました。
		return "P/ECE CLiP Library Wire (*.pwx)";
	}
	return NULL;
}

/* ファイルの拡張子を返します。
 * 返した拡張子はファイルダイアログ上で扱われます。
 * この関数は起動時に呼び出されます。
 * indexは0から順に呼び出されるごとに増えていき、戻り値としてNULLを返したときに呼び出しが終了します。
 * [in]
 *	index		ファイルの種類のインデクス。
 * [out]
 *	戻り値		拡張子。
 */
MQPLUGIN_EXPORT const char*
MQEnumFileExt(int index)
{
	switch(index){
	//case 0:	/* メッシュ */
	//case 1:	/* ワイヤフレーム */
	//	return "xml"; /* 拡張子は共通です */
	//↓* Wed Sep 27 03:54:09 JST 2006 Naoyuki Sawa
	//↓- メッシュファイルの拡張子を、xml→pmxに変更しました。
	//↓- ワイヤーフレームファイルの拡張子を、xml→pwxに変更しました。
	case 0:	/* メッシュ */
		return "pmx";
	case 1:	/* ワイヤフレーム */
		return "pwx";
	}
	return NULL;
}

/* ドキュメントに登録されているオブジェクトをファイルへ書き込みます。
 * 何らかの理由で書き込みに失敗した場合はFALSEを返すようにしてください。
 * [in]
 *	index		ファイルの種類のインデクス。
 *	filename	ファイル名(フルパス)。
 *	doc		ドキュメントクラス。
 * [out]
 *	戻り値		ファイル出力の成功の可否。
 *			[TRUE] 出力に成功
 *			[FALSE] 出力に失敗
 */
MQPLUGIN_EXPORT BOOL
MQExportFile(int index, const char* filename, MQDocument doc)
{
	BOOL result = FALSE;
	//
	FILE* fp;
	MQObject obj;

	switch(index){
	case 0:	/* メッシュ */
	case 1:	/* ワイヤフレーム */
		/* オプションダイアログを表示します。 */
		if(DoOptionDialog(hModule, MQ_GetWindowHandle(), &option)) {
			/* ファイルを作成します。 */
			fp = fopen(filename, "wt");
			if(fp) {
				/* すべてのオブジェクトを一つに合成するために、作業用オブジェクトを作成します。 */
				obj = MQ_CreateObject();
				if(obj) {
					/* エクスポートを実行します。 */
					switch(index){
					case 0:	/* メッシュ */
						result = DoExportMesh(fp, doc, obj, &option);
						break;
					case 1:	/* ワイヤフレーム */
						result = DoExportWire(fp, doc, obj, &option);
						break;
					default:
						/* 有り得ない */
						break;
					}

					/* 作業用オブジェクトはもう不要なので、削除します。 */
					obj->DeleteThis();
				} else {
					MessageBox(MQ_GetWindowHandle(),
						"作業用オブジェクトの作成に失敗しました。",
						APP_TITLE, MB_ICONEXCLAMATION | MB_OK);
				}

				/* ファイルを閉じます。 */
				fclose(fp);

				/* ファイル作成に成功、かつ、エクスポートに失敗した場合、ファイルを削除します。 */
				if(!result) {
					remove(filename);
				}
			} else {
				MessageBox(MQ_GetWindowHandle(),
					"ファイルの作成に失敗しました。",
					APP_TITLE, MB_ICONEXCLAMATION | MB_OK);
			}
		}
		break;
	}

	return result;
}

