// == 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 ==

#pragma once

namespace MQCLIEX {

	//! @addtogroup UVTexIntegra-MQCLIEX名前空間
	//! @{

	//! @brief メタセコイアのDWORD頂点カラーをSystem::Drawing::Colorに変換します。
	inline System::Drawing::Color FromMQVertexColor( DWORD vc ) {
		return System::Drawing::Color::FromArgb( (vc & 0xFF000000)>>24, (vc & 0x000000FF), (vc & 0x0000FF00)>>8, (vc & 0x00FF0000)>>16 );
	}

	//! @brief R,G,B,AをメタセコイアのDWORD頂点カラーに変換します。
	inline DWORD ArgbToMQVertexColor( const int a, const int r, const int g, const int b )
	{
		return DWORD( unsigned int(r & 0xFF) | (unsigned int(g & 0xFF) << 8) | (unsigned int(b & 0xFF) << 16) | (unsigned int(a & 0xFF) << 24) );
	}

	//! @brief map_typeの指定するテクスチャのファイルパスを取得し、MQDocument::FindMappingFileで絶対パスに変換します。
	inline System::String^ GetMaterialTextureAbsName( const MQDocument doc, const MQMaterial mat, DWORD map_type ) {
		char buf[MAX_PATH];
		if ( (doc==NULL)||(mat==NULL) ) return System::String::Empty;
		std::string path = MQ0x::GetMaterialTextureName(mat, map_type);
		if ( doc->FindMappingFile(buf,path.c_str(),map_type)==FALSE ) return System::String::Empty;
		return gcnew System::String( buf );
	}

	//! @brief 選択中のオブジェクトIDリストを返します
	//! @param [in] isRecursiveRootOnly trueに設定すると、選択中の子オブジェクトが、親方向にたどっていずれかのオブジェクトが選択状態にある場合にリストアップされなくなります。
	inline System::Collections::Generic::List<UINT>^ GetSelectedObjectIDs( const MQDocument doc, bool isRecursiveRootOnly ) {
		System::Collections::Generic::List<UINT>^ selectedObjectIDs = gcnew System::Collections::Generic::List<UINT>();
		if ( doc != NULL ) {
			const int ctObj = doc->GetObjectCount();
			for ( int ct = 0; ct < ctObj; ct++ ) {
				const MQObject obj = doc->GetObject(ct);
				if ( (obj!=NULL) && (obj->GetSelected()==TRUE) ) {
					const UINT id = obj->GetUniqueID();
					if ( selectedObjectIDs->Contains(id) == false ) {
						bool isFind = false;
						if ( isRecursiveRootOnly ) for ( MQObject parent = doc->GetParentObject( obj ); parent != NULL; parent = doc->GetParentObject(parent) ) {
							if ( parent->GetSelected() == TRUE ) { isFind = true; break; }
						}
						if ( isFind == false ) selectedObjectIDs->Add(id);
					}
				}
			}
		}
		return selectedObjectIDs;
	}
	//! @brief 選択中のオブジェクトIDリストを返します。GetSelectedObjectIDs( doc, false ) に等しい実装です。
	inline System::Collections::Generic::List<UINT>^ GetSelectedObjectIDs( const MQDocument doc ) { return GetSelectedObjectIDs( doc, false ); }
	//! @brief 選択中のオブジェクトの名前をString[]にして返します。
	//! @param [in] isRecursiveRootOnly trueに設定すると、選択中の子オブジェクトが、親方向にたどっていずれかのオブジェクトが選択状態にある場合にリストアップされなくなります。
	inline System::Collections::Generic::List<System::String^>^ GetSelectedObjectNames( const MQDocument doc, bool isRecursiveRootOnly ) {
		System::Collections::Generic::List<UINT>^ IDs = GetSelectedObjectIDs( doc, isRecursiveRootOnly );
		System::Collections::Generic::List<System::String^>^ ret = gcnew System::Collections::Generic::List<System::String^>(IDs->Count);
		for each ( UINT id in IDs ) {
			System::String^ item = gcnew System::String(MQ0x::GetName(doc->GetObjectFromUniqueID(id)).c_str());
			if (System::String::IsNullOrEmpty(item)==false) ret->Add(item);
		}
		return ret;
	}
	//! @brief 選択中のオブジェクトの名前をString[]にして返します。 GetSelectedObjectNames(doc,false) に等しい実装です。
	inline System::Collections::Generic::List<System::String^>^ GetSelectedObjectNames( const MQDocument doc ) { return GetSelectedObjectNames(doc,false); }

	//! @brief n以上の最小の2のべき乗を返します。
	//! @return n以上の最小の2のべき乗。もしnより大きい2の階乗がTの型の最大値を超える場合は、nより小さいが、最も近い2のべき乗が返ります。
	template <class T> T TryExpLogCeil2( T n ) {
		T threshold = 1;
		for ( ; threshold < (threshold*2); threshold *= 2 ) if ( n <= threshold ) break;
		return threshold;
	}


	//! @}
}