//! @cond
// == LICENSE INFORMATION ==
/*
 * First author tiritomato 2013.
 * This program is distributed under the GNU General Public License(GPL).
 * support blog (Japanese only) http://d.hatena.ne.jp/tiri_tomato/
 */
// == LICENSE INFORMATION ==
//! @endcond

/*! @mainpage メインページ

- @ref UVTexIntegraについて
- @ref ライセンス
- @ref OpenTKライセンス
- @ref 入手先
	- @ref DeveloperDownload
- @ref サポート・問い合わせ先
- @ref UVTexIntegra名前空間 "開発者向けリファレンス(UVTexIntegra名前空間)"
- @ref ScriptReference
.
<hr/>

@par UVTexIntegraについて
@anchor UVTexIntegraについて
次のようなプラグインを開発するプロジェクトです。
1. UV座標の再レイアウト情報をエディットして、UV値を縮小並行移動／マテリアル統合したクローンオブジェクトを生成する
2. 同様にレイアウト情報を反映しつつ、頂点色の焼き込み機能を持つ。
3. 焼込機能でスクリプトまたはDLL（拡張プログラム）を投入し、UV情報と頂点色の計算を多少カスタマイズできる。
.

@par ライセンス
@anchor ライセンス
UVTexIntegraは、現在のところGPLライセンスVer3で配布されています。

@par OpenTKライセンス
@anchor OpenTKライセンス
UVTexIntegraではOpenGLのコントロールに<a href="http://www.opentk.com/"><b>OpenTK</b></a>を利用しています。
OpenTKはいわゆるMITタイプのライセンスで配布されます。詳しくは同梱の OpenTK.License.txt を参照してください。

@par 入手先
@anchor 入手先
- <a href="http://sourceforge.jp/users/tiritomato/pf/DotNetEx"><b>DotNetEx</b> (SourceForge)</a><br/>
<a href="http://sourceforge.jp/users/tiritomato/pf/DotNetEx/files/">ダウンロード（ファイルツリー）</a>またはgitリポジトリから入手できます。
<table>
<tr><th colspan=2><small>動作環境</small></th></tr>
<tr><td>.Net framework 4.0</td><td>必須 <small>(※) 作者のPCが4.5に対応してないので、4.5で動くかどうかは不明</small></td></tr>
<tr><td>OpenGL1.5以上のグラフィック環境</td><td><small>(※) 焼き込み処理をする場合は必要</small></td></tr>
<tr><td>Visual Studio C# 2010 (Express可)</td><td><small>(※) 焼込をカスタマイズする時にあると便利</small></td></tr>
</table>
\>\> @ref DeveloperDownload

@par サポート・問い合わせ先
@anchor サポート・問い合わせ先
公式サイトなどはありませんので、お手数ですが
1. ツイッターアカウント(<a href="http://twitter.com/#!/tiri_tomato">tiri_tomato</a>)
2. SourceForgeメールアドレス: tiritomato@users.sourceforge.jp \n（お手数ですが表題に \"[UVTexIntegra問い合わせ]\" と記入していただけると幸いです）
3. <a href="http://d.hatena.ne.jp/tiri_tomato/">ブログ(チリペヂィア)</a>に適当にコメント
.
いずれかまでご連絡ください。

@page DeveloperDownload 開発者向けダウンロード情報
@details
- @ref 開発環境 "必要な開発環境"
- <b>ビルドの準備</b>
	- @ref プロジェクトファイルの取得
		1. @ref リリースされたソースコードアーカイブを取得する場合
		2. @ref リポジトリからソースコード複製する場合
	- @ref mqsdkのコピー
@details
<hr/>

@paragraph 開発環境
<a name="開発環境"><b>開発環境</b></a>
- 必須開発環境
	- Visual Studio C++ 2010 (Express可)
	- Visual Studio C# 2010 (Express可)
	- Microsoft Windows SDK 7.1 <small>(SDK7.1はなくてもコンパイル可能と思いますが、SDKなしでコンパイルする時はVCプロジェクト設定の「プラットフォームツールセット」を「v100」に設定して下さい)</small>
- 開発ツール <small>(※) 必要に応じて。</small>
	- Doxygen (ver1.8.4)
	- NUnit (ver2.6.2)
	.
.

@par プロジェクトファイルの取得
@anchor プロジェクトファイルの取得

@par リリースされたソースコードアーカイブを取得する場合
@anchor リリースされたソースコードアーカイブを取得する場合
バイナリパッケージ同様に、ダウンロードして解凍します。

@par リポジトリからソースコード複製する場合
@anchor リポジトリからソースコード複製する場合
UVTexIntegraのプロジェクトは、３つのリポジトリから構成されていて、これらをひとつひとつ正しい位置関係で複製しなければなりません。
<table>
<tr><td>UVTexIntegra</td><td>主なリポジトリ。他の二つを内側に複製しないとビルドできない。</td></tr>
<tr><td>mqsdx</td><td>mqsdkのCLIラッパー</td></tr>
<tr><td>DotNetEx</td><td>C\#の拡張ライブラリ</td></tr>
</table>
（mqsdx,DotNetExは本来サブモジュール扱いにするところですが、
submoduleコマンドの使い勝手が悪いのでUVTexIntegraのリポジトリには含めていません。手動で追加する必要があります。）
@par
1. UVTexIntegraのリポジトリをローカルに複製する。<br/>（以後、ローカルの\"C:\\UVTexa\"にダウンロードしてきたとします。）
2. mqsdxプロジェクトをローカルに複製してmqsdkを配置する。
	1. mqsdxフォルダを作成します。<br/>場所：\"C:\\UVTexa\\mqsdx\"
	2. ローカルのmqsdxフォルダに、サーバー上のmqsdxリポジトリから複製します。
3. DotNetExプロジェクトをローカルに複製する。
	1. DotNetExフォルダを作成します。<br/>場所：\"C:\\UVTexa\\DotNetEx\"
	2. ローカルのDotNetExフォルダに、サーバー上のDotNetExリポジトリから複製します。
.
<table>
<tr><th colspan=3><small>\"C:\\UVTexa\"に複製するとして、それぞれのルートとファイルの位置</small></th><th><small>リリースブランチ</small></th><th><small>ナイトリーブランチ</small></th></tr>
<tr><td>UVTexIntegra</td><td>C:\\UVTexa</td><td>C:\\UVTexa\\UVTexIntegra.sln など</td><td>master</td><td>develop</td></tr>
<tr><td>mqsdx</td><td>C:\\UVTexa\\mqsdx</td><td>C:\\UVTexa\\mqsdx\\document, C:\\UVTexa\\mqsdx\\mqsdk, C:\\UVTexa\\mqsdx\\mqsdx など</td><td>master</td><td>develop_uvtexa</td></tr>
<tr><td>DotNetEx</td><td>C:\\UVTexa\\DotNetEx</td><td>C:\\UVTexa\\DotNetEx\\DotNetE.sln など</td><td>master</td><td>develop_uvtexa</td></tr>
</table>
ここまで良く分からなければ、リリース済みのソースコードアーカイブもダウンロードしてきて、フォルダ構成が一致するか確認してください。

@par mqsdkのコピー
@anchor mqsdkのコピー
プロジェクトファイルを正しく取得できたら、メタセコイアの公式ダウンロードからmqsdkをダウンロードしてきて、
以下のファイルを\"mqsdx\\mqsdk\"（上の例では\"C:\\UVTexa\\mqsdx\\mqsdk\"）の直下にコピーしてください。
	- MQ3DLib.h
	- MQ3DLib.cpp
	- MQBasePlugin.cpp
	- MQBasePlugin.h
	- MQPlugin.cpp
	- MQPlugin.h
	- MQSetting.cpp
	- MQSetting.h
	- MQInit.cpp
.

@details 以上でビルドの準備は完了です。

@page ScriptReference カスタムベイク・スクリプトリファレンス
カスタムベイクは、頂点色の焼き込みをカスタマイズする機能です。
- @subpage scr1MakeScript
- @subpage scr2Rename
- @subpage scr3PublishProp
- @subpage scr4SaveProp
- @subpage scr5UVOp
- @subpage scrX1Sample1
- <b>リファレンス</b>
	- @ref UVTexIntegra.Scripting.ScriptMain "ScriptMain"
	- @ref UVTexIntegra.Scripting.ScriptMain.Face "ScriptMain.Face"
	- @ref UVTexIntegra.Scripting.ScriptMain.Face.Point "ScriptMain.Face.Point"
	.
.
UVTexIntegraのパッケージには、サンプルのカスタムベイクスクリプトとして、鋭角ベイクプロジェクト（EdgeBake.sln）と、EdgeBake.dllが付属しています。これらも参考にしてみてください。

@page scr1MakeScript スクリプトプロジェクトの作成

ここではC\#でのカスタムベイクDLLプロジェクトをビルドする手順を最初から紹介します。

VC\#2010を起動して、新しい空のプロジェクトを作成します。
1. 種類はクラスライブラリ
2. 要らないのでClass1.csを削除
3. 参照設定に以下のDLLを加えてください。UVTexIntegra/libフォルダにあります。
	- OpenTK.dll
	- UVTexIntegra.Scripting.dll
	.
	(これらをビルド時のビルドフォルダにコピーさせる必要はありません)
.
プロジェクト作成は以上で完了です。

作成したプロジェクトに、次のようなTestScript.csファイルを追加してください。
このTestというのは、とくになにもしないクラスですが、ビルドすればスクリプトは完成です。

@code
public class Test : UVTexIntegra.Scripting.ScriptMain
{
}
@endcode

ビルドしたDLL(プロジェクトの bin\\Release フォルダに出来ています)を、メタセコイアの Plugins\\Command\\UVTexIntegra フォルダにコピーします。

メタセコイアを起動して、UVTexIntegraのカスタムベイクダイアログを表示します。
カスタムベイクダイアログが表示されたら、ファイル>新規スクリプトのロードを選択して、先ほどコピーしたDLLを選択します。

これで、自分の作ったDLLをUVTexIntegraにロードする事が出来ました。

@note <b>参照設定で、独自のDLLをさらに追加したい時はlibフォルダに</b><br/>
システムにインストールされているDLLなら参照設定に加えるだけで問題ありませんが、そうでない場合は
参照設定にそのDLLを加えた後、Plugins\\Command\\UVTexIntegra\\libフォルダにそのDLLをコピーしてください。
@note <b>スクリプト？</b><br/>「スクリプトなのにビルドとは如何に？」とはもっともな話です…
スクリプトを謳っているのは、実際に開発環境を使わなくてもプラグイン実行時にソースコードからビルド＆ロードできるからです。
しかし作ってみると、ちょっとスクリプトの行数が増えるとバグ発見に手間取ったり、コンパイル設定ミスによるリンクエラーの例外はどうしてもキャッチできないのと、
VisualStudioの入力補完が優秀なのとで、最初ちょっと面倒ですがDLLプロジェクトを作ってしまった方が、結局のところ総じて手間がないようです。

@page scr2Rename 名前を変更する

@ref UVTexIntegra.Scripting.ScriptMain.Name "Name"プロパティをオーバーライドして、スクリプトの名前を設定できます。

@code
public class Test : UVTexIntegra.Scripting.ScriptMain
{
	public override string Name
	{
		get
		{
			return "テストスクリプト";
		}
	}
}
@endcode

スクリプトを選択するプルダウンに名前が表示されるようになります。

@page scr3PublishProp パラメーターを実行時に設定できるようにする

Publicプロパティを定義してください（フィールドは不可。プロパティのみ）。

@code
public class Test : UVTexIntegra.Scripting.ScriptMain
{
	public int MyValue { get; set; }
}
@endcode
実行時にプロパティグリッドから値を設定できるようになります。

また、プロパティグリッドに設定を反映できる属性もあります。
@code
public class Test : UVTexIntegra.Scripting.ScriptMain
{
	[System.ComponentModel.DefaultValue(0)] // DefaultValueと違う値に設定されると、プロパティグリッドでは太字の表示になります。
	[System.ComponentModel.Description("Descriptionに書いたテキストが、プロパティグリッドで選択した時に表示されます")]
	public int MyValue { get; set; }
}
@endcode

より詳しくは、C\#のプロパティグリッドコントロールについて調べてください。

@page scr4SaveProp パラメーターを実行時に保存できるようにする

スクリプトクラスは以下のシリアライズ条件を満たせば、プロパティに入力した値を保存できます。

1. Serializable属性
2. デシリアライズ用コンストラクタ／(SerializationInfo info, StreamingContext stream)を引数としたパブリックコンストラクタを公開
3. ISerializableを実装して、GetObjectData()メソッドを提供
4. UVTexIntegra.Scripting.SerializeSaveAttribute属性をtrueに設定
.

@code
[Serializable]
[UVTexIntegra.Scripting.SerializeSave(true)]
public class Test :
	UVTexIntegra.Scripting.ScriptMain,
	System.Runtime.Serialization.ISerializable
{
	public Test()
	{
		MyValue = 0;
	}
	
	// デシリアライズ
	public Test(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext stream)
		: this()
	{
		try
		{
			MyValue = info.GetInt32("MyValue"); // 型に応じたGet〜()メソッドで値を取得。
		}
		catch (System.Exception)
		{
		}
	}
	
	public int MyValue { get; set; }
	
	// シリアライズ
	public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext stream)
	{
		info.AddValue("MyValue", MyValue); // 型に応じたAddValue()メソッドで値を設定。
	}
}
@endcode

@page scr5UVOp 実際のUV処理をカスタマイズする

いよいよ @ref UVTexIntegra.Scripting.ScriptMain.OnUVOperation() "OnUVOperation()" メソッドをオーバーライドします。

プレビューや保存処理の前に @ref UVTexIntegra.Scripting.ScriptMain.OnUVOperation() "OnUVOperation()" メソッドが呼び出されるので、
パラメータに渡された @ref UVTexIntegra.Scripting.ScriptMain.Face "ScriptMain.Face[]" を参照し、
@ref UVTexIntegra.Scripting.ScriptMain.Face.Normal "Face.Normal" などの面情報をもとに
@ref UVTexIntegra.Scripting.ScriptMain.Face.Point.Coordinate "Face.Points[].Coordinate"
または @ref UVTexIntegra.Scripting.ScriptMain.Face.Point.Color "Face.Points[].Color" を書き換えていきます。

@code
// 頂点を全て白にするサンプル
public class Test : UVTexIntegra.Scripting.ScriptMain
{
	// 〜 <略> 〜 //

	public override void OnUVOperation(ScriptMain.Face[] faces)
	{
		// すべての面を総当り
		foreach (ScriptMain.Face face in faces)
		{
			foreach (ScriptMain.Face.Point point in face.Points)
			{
				// 真っ白に
				point.Color = System.Drawing.Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF);
			}
		}
	}

	// 〜 <略> 〜 //
}
@endcode

<br/>もし、面ごとの処理だけでなく、頂点ごとの処理を行うには OnUVOperation() の処理中に独自に解析バッファを作るか
@ref UVTexIntegra.Scripting.ScriptMain.Face.ShareRelation.GetRelationsSnap() "ScriptMain.Face.ShareRelation.GetRelationsSnap()" メソッドを使います。
このメソッドは現在UV座標がどのように複数の面に共有されているかリストにします。

@code
// 同じUVを共有する頂点同士で頂点色を平均化するサンプル
public override void OnUVOperation(ScriptMain.Face[] faces)
{
	// ScriptMain.Face.ShareRelation.GetRelationsSnap()メソッドを使うと、
	// その時点で、ほとんど同じ座標（座標の差がきわめて小さい）のUV頂点を並べたデータを返します。
	// (*1) ここでは同じ座標とみなす許容誤差にfloat.Epsilon * 4.0fをとりあえず設定しています。とくに論拠はありません。
	// (*2) UV頂点はひとつのShareRelationにしか属さないので、重複登録されたりはしません。
	System.Collections.ObjectModel.ReadOnlyCollection<ScriptMain.Face.ShareRelation> shareSnap =
		ScriptMain.Face.ShareRelation.GetRelationsSnap(faces, float.Epsilon * 4.0f);

	// まとめられたUV情報(ScriptMain.Face.ShareRelation)を総当り
	foreach (ScriptMain.Face.ShareRelation rel in shareSnap)
	{
		if (1 < rel.Owners.Count)
		{
			int[] sum = new int[4] { 0, 0, 0, 0 };
			// このShareRelationでUVを共有する全てのオーナーの色を合計
			foreach (Face.ShareRelation.IReference reference in rel.Owners)
			{
				sum[0] += reference.Point.Color.A;
				sum[1] += reference.Point.Color.R;
				sum[2] += reference.Point.Color.G;
				sum[3] += reference.Point.Color.B;
			}
			// 要素数で割って平均値。一応オーバーフローしないようにしてるけどいらないかも
			sum[0] = System.Math.Min(sum[0] / rel.Owners.Count, 0xFF);
			sum[1] = System.Math.Min(sum[1] / rel.Owners.Count, 0xFF);
			sum[2] = System.Math.Min(sum[2] / rel.Owners.Count, 0xFF);
			sum[3] = System.Math.Min(sum[3] / rel.Owners.Count, 0xFF);
			// このShareRelationでUVを共有する全てのオーナーのカラーを平均値で更新
			System.Drawing.Color color = System.Drawing.Color.FromArgb(sum[0], sum[1], sum[2], sum[3]);
			foreach (Face.ShareRelation.IReference reference in rel.Owners) reference.Point.Color = color;
		}
	}
}
@endcode

@note GetRelationsSnap() はその瞬間のUV座標で静的な共有リストを作ります。 GetRelationsSnap()
で共有リストを作ったあと、UV座標の位置を書き換えると、共有リストは正しい共有関係を維持しなくなるので注意してください。

@page scrX1Sample1 実装例（EdgeBake.cs）

@details これまでのトピックを踏まえて、「頂点法線と面法線の角度差が大きいほど黒ずむ」鋭角ベイクのサンプルコードを示します。
@include EdgeBake.cs

EdgeBake.cs は、EdgeBakeフォルダにあるEdgeBake.slnに含まれています。
*/

/*!
@defgroup UVTexIntegra名前空間
UVTexIntegraのルートになる名前空間です。
@{
	@defgroup UVTexIntegra-MQCLIEX名前空間
	UVTexIntegra-MQCLIEX名前空間 は、MQCLIライブラリを拡張します。「汎用（MQCLI）」と「UVTexIntegra固有」の中間ライブラリ層です。
	@{
	@}
	@defgroup UVTexIntegra-Scripting名前空間
	UVTexIntegra-Scripting名前空間 は、主に外部DLLやスクリプトコンパイルなどに関する処理を定義します。
	またプロパティグリッドに情報を公開するための属性や型情報などを動的に操作する処理も含みます。
	@{
	@}
	@defgroup UVTexIntegra-CustomControls名前空間
	UVTexIntegra-CustomControls名前空間 は、UVTexIntegra用のカスタムコントロールを定義します。
	@{
	@}
@}
*/
