module y4d_draw.textureloader;

private import ytl.y4d_result;
private import y4d_aux.filesys;
private import y4d_aux.cacheloader;
private import y4d_draw.texture;

private import yamalib.log.log;

///	Texture の cacheメカニズムを実現する。
/**
	Sound に対する SoundLoader と同じく、
	Texture に対するキャッシュメカニズムを実現します。<BR>

	cacheの単位はbyte。ディフォルトでは32MB。<BR>

	640×480のテクスチャは、2^nに拡張されるので、
	1024×512×4(ARGB) = 2MB にもなる。<BR>

	CacheLoader の説明も読んでください。

<PRE>
	y4d_result	loadDefFile(char[] filename);
	で読み込む定義ファイルは、
			a.bmp , 2 , -1
			b.bmp ,,-1
	のように書き、ひとつ目は、ファイル名、二つ目は、読み込む番号、3つ目は
	optionである。optionは現在、未使用である。
</PRE>

	使用例)
<PRE>
int main(){
	Screen screen = new Screen;
	screen.setVideoMode(640,480,0);

	TextureLoader tl = new TextureLoader;
	tl.loadDefRW("title.png \n 4.png \n 3.png \n 4.bmp");

	//	事前に設定したいなら、ここで設定する
	tl.getObj(3).setColorKey(255,255,255);
	tl.getObj(3).disableAlpha();

	int x,y;
	while (!GameFrame.pollEvent()){
		//	1フレーム分の処理

		screen.resetColor();
		screen.clear();

		screen.blt(tl.get(0),0,0);

		//	これは半透明画像なので転送元αを有効にして転送
		screen.blendSrcAlpha();
		screen.blt(tl.get(1),70,70);

		//	(100,100,200)にfadeして描画
		screen.disableBlend();
		screen.setColor(100,100,200);
		screen.blt(tl.get(2),250,250);

		screen.update();
	}
	return 0;
</PRE>

	使用例その2
<PRE>
private import y4d;

void main() {
	Screen screen = new Screen;
	screen.setVideoMode(640,480,0);

	TextureLoader tl = new TextureLoader;
	tl.readLine("bg.jpg");
	tl.setColorKeyPos(0,0);
	//	getを行なうまでにカラーキーの設定を行なうべし

	while (!GameFrame.pollEvent()){
		screen.clear();
		screen.blendSrcAlpha();
		screen.blt(tl.get(0),0,0);
		screen.update();
	}
}
</PRE>

*/
class TextureLoader : CacheLoader {

	///	指定された番号のオブジェクトを構築して返す
	/**
		暗黙のうちにオブジェクトは構築され、loadされる。

		定義ファイル上に存在しない番号を指定した場合はnullが返る
		ファイルの読み込みに失敗した場合は、nullは返らない。
		定義ファイル上に存在しない番号のものを再生することは
		考慮しなくてもいいと思われる．．。
	*/
	Texture get(int no) {
		return cast(Texture)getHelpper(no);
	}

	///	指定された番号のオブジェクトを構築して返す
	/**
		暗黙のうちにオブジェクトは構築されるが、loadはされない。
		(この点、 get とは異なる)
	*/
	Texture getObj(int no) {
		return cast(Texture) getHelpperObj(no);
	}

	///	Textureのcloneメソッド。
	Texture createInstance() { return new Texture; }

	///	指定した番号のテクスチャーにbindする
	/**
		指定した番号のテクスチャーが存在しなければ非0。
	*/
	y4d_result		bind(int no){
		Texture t = get(no);
		if (t) {
			t.bind();
			return y4d_result.no_error;
		}
		return y4d_result.precondition_error; // 存在しない
	}

	///	foreachに対応させるためのもの
	/**
		事前にすべてのオブジェクトに対して
		setColorKeyのようなことをしたいならば、
		foreachがあったほうが便利である。<BR>

		getObjしたものを返すバージョン
	*/
	int opApply(int delegate(inout Texture) dg)
	{
		int result = 0;
		foreach(int key;filelist.getKeys())
		{
			Texture t = getObj(key);
			result = dg(t);
			if (result)	break;
		}
		return result;
	}

	///	foreachに対応させるためのもの
	/**
		事前にすべてのを読み込んでおきたいならば、
		foreachがあったほうが便利である。<BR>

		keyを返すバージョン。
	*/
	int opApply(int delegate(inout int) dg)
	{ return super.opApply(dg); }

	//	--- カラーキーの設定も出来るようにしといちゃう

	///	テクスチャーのある座標をカラーキーにする
	/**
		また、画像を読み込む(load)するより以前に、この関数を
		呼び出しておかなければならない。(loadするときに抜き色部分の
		α値を0に書き換えるので)<BR>

		その後の画像読み込み、解放によっては設定したカラーキーは
		無効にはならない。
	*/
	void	setColorKeyPos(int cx_,int cy_){
		bColorKey = false;
		bColorKeyPos = true;
		cx = cx_; cy = cy_;
	}

	///	カラーキーの取り消し
	/**
		setColorKey / setColorKeyPos で設定した情報を無効化します。
	*/
	void	resetColorKey(){
		bColorKey = false;
		bColorKeyPos = false;
	}

	this() {
		cacheSize = 32*1024*1024; // 32MBのtexture cache
	}

protected:

	///	テクスチャを読み込むための関数。LoadCacheからのオーバーロード
	y4d_result loadFile(char[] filename,inout Object obj,int option1,
		int option2) {

		void setColorKey(Texture s) {
			if (s) {
				if (bColorKey) s.setColorKey(r,g,b);
				else if (bColorKeyPos) s.setColorKeyPos(cx,cy);
			}
		}

		y4d_result result;
		if (obj) {
			Texture s = cast(Texture)obj;
			setColorKey(s);
			result = s.load( FileSys.makeFullName(filename) );
		} else {
			Texture s = new Texture;
			setColorKey(s);
			result = s.load( FileSys.makeFullName(filename) );
			obj = s;
		}
		
		debug {
			if ( result ) {
				Log.print( "TextureLoader#loadFile : Y4DRESULT %s\n",result );
			}
		}		

		return result;
	}

	///	サウンドを解放するための関数。LoadCacheからのオーバーロード
	y4d_result releaseFile(inout Object obj) {
		if (obj) {
			Texture s = cast(Texture)obj;
			s.release();
			//	Texture.releaseは失敗しないメソッドなのだ
		} else {
			//	読み込んでないから解放しないでいいんよね？
		}
		return y4d_result.no_error;
	}

private:
	bool	bColorKey;		//	カラーキーが設定されているか。
	uint	r,g,b;			//	カラーキー
	bool	bColorKeyPos;	//	位置指定のカラーキーが設定されているか。
	uint	cx,cy;			//	位置指定型カラーキーのcx,cy

}
