module y4d_draw.surfaceloader;

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

private import yamalib.log.log;

///	Surface の cacheメカニズムを実現する。
/**
	Sound に対する SoundLoader と同じく、
	Surface に対するキャッシュメカニズムを実現します。<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 SurfaceLoader : CacheLoader {

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

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

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

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

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

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

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

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

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

protected:

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

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

		return result;
	}

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

}
