module kyojintati4d.tasktest;

debug {

// デバッグ専用クラス

private import SDL;
private import SDL_image;

private import std.string;
private import std.stdio;
private import std.regexp;
private import std.utf;
private import std.thread;

private import y4d;
private import y4d_draw.transbltter;
private import y4d_aux.filesys;
private import y4d_aux.direnumerator;

private import kyojintati4d.myapp;
private import kyojintati4d.gameinfo;

private import kyojintati4d.bookmark;
private import yamalib.auxil.appassist;
private import yamalib.auxil.fileex;
private import yamalib.draw.ripplingtexture;
private import yamalib.draw.effectsoft;
private import yamalib.counterfsp;
private import yamalib.log.log;
private import yamalib.log.performancelog;
private import yamalib.gui.guibutton;
private import yamalib.gui.dialog;


private import yamalib.draw.morph;
private import yamalib.draw.camerawork;
private import yamalib.draw.menu;
private import yamalib.draw.scenariodraw;
private import yamalib.draw.textdraw;;
private import yamalib.draw.spreadstring;

private import kyojintati4d.component.titledial;

private import yamablib.dict.dictcontroller;
private import yamalib.draw.rring;
private import yamalib.draw.sequencedraw;

private import yamalib.draw.spiralmove;
private import yamalib.draw.directivityobject;

private import yamalib.draw.drawassist;


// 通信
pragma(lib, "ws2_32.lib ");
private import std.socket;
private import yamalib.log.netreport;
private import yamalib.util.systeminfo;
//private import yamalib.network.networkconnectionsdlnet;
//private import yamalib.network.inetworkconnection;
//private import yamalib.network.networkmanagersdlnet;
//private import yamalib.network.inetworkmanager;
//private import yamalib.network.errorvalue;
//private import yamalib.network.httpresponse;

/+
/// キャラ入れ替えテスト
class TaskTest : GameTaskBase {
	

	/// 毎回呼び出す
	override int onMove(Object o) {
		info = cast(GameInfo) o;
		if (!init) {
			onInit();
			info.screen.blendSrcAlpha();
			info.screen.setClearColor(255,255,255);
			init = true;
		}
		
		m_phase.inc();
		m_phaseProto.inc();
		
		m_preAlpha.inc();
		m_nowAlpha.inc();
		
		if (m_preAlpha.isEnd()) {
			m_preAlpha.reset();
			m_nowAlpha.reset();
		}
		
		return 0;	
	}
	
	override int onDraw(Object o) {
		info = cast(GameInfo) o;
		
		info.screen.clear();
		info.screen.setColor(255,255,255,255);
		info.screen.blendSubColor();
		DrawAssist.blt(info.screen, m_imgBg, 0, 0,  m_dac);

		return 0;
	}
	
	override int task(Object o) {
		return 0;
	}
	
private:

	void onInit() {
		try {
			m_phase = new RootCounter();
			m_phase.set(0, 255, 4);
			m_phaseProto = new FreeLineCounter(new RootCounter());
			m_phaseProto.set(0,255,4);
			
			m_preAlpha = new RootCounterS();
			m_preAlpha.set(255,0,1);
			m_nowAlpha = new RootCounterS();
			m_nowAlpha.set(0,255,2);
			
			m_phase.setReverse(true);
			m_imgPre = new Texture();
			m_imgNow = new Texture();
			m_imgBg = new Texture();
			
			m_imgPre.load("img/sil/mido/midoriko101.0.png");
			m_imgNow.load("img/sil/mido/midoriko102.0.png");
			m_imgBg.load("TEST/place005.jpg");
			
			Rect* srcRect = new Rect();
			srcRect.setRect(320,0, 640, 240);
			Size* size = new Size();
			size.setSize(640u,480u);
			m_dac = new DrawAssist.Context(size);
			m_dac.setRad(10,0,0);
			m_dac.enableRad = true;

			m_dac.rate = 1.99f;
			m_dac.srcRect = srcRect;
			m_dac.enableRate = true;
			m_dac.enableSrcRect = true;
	

		} catch (Exception e) {
			Log.printFatal("[%s]", e.toString());
			throw e;
		}
	}
	
	GameInfo info;
	bool init;
	Texture m_imgBg;
	Texture m_imgPre;
	Texture m_imgNow;
	Texture m_imgBackup;
	
	DrawAssist.Context m_dac;
	
	RootCounterS m_preAlpha;
	RootCounterS m_nowAlpha;
	
	RootCounter m_phase;
	FreeLineCounter m_phaseProto;
	
	static class CharaAlphaCounter : FreeLineCounter {
	}

}
+/

/+

/**
	HTTP通信テスト
*/
class TaskTest : GameTaskBase {
	
	/// 毎回呼び出す
	override int onMove(Object o) {
		info = cast(GameInfo) o;

		if (!init) {
			onInit();
			init = true;
		}
		
		return 0;
		
	}
	
	override int onDraw(Object o) {
		info = cast(GameInfo) o;
		
		info.screen.clear();

		return 0;
	}
	
	override int task(Object o) {
		return 0;
	}
	
private:

	/// 初期化処理
	void onInit() {
	}

	static const char[] HTTP_REQ_TEMPLATE = "GET http://download.forest.impress.co.jp/pub/win/c/collage/Collage.zip HTTP/1.0\r\nAccept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*\r\nReferer: http://www.forest.impress.co.jp/lib/game/advrpg/adv/collage.html\r\nAccept-Language: ja\r\nProxy-Connection: Keep-Alive\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.1)\r\nHost: download.forest.impress.co.jp\r\nCookie: NGUserID2=ac140446-168-1150193797-1\r\n\r\n";
	GameInfo info;
	Socket m_sock;
	bool init;

}

+/

/+
/// ダイアログテスト
class TaskTest : GameTaskBase {
	
	/// 毎回呼び出す
	override int onMove(Object o) {
		info = cast(GameInfo) o;

		if (!init) {
			onInit();
			info.screen.blendSrcAlpha();
			info.screen.setClearColor(255,255,255);
			info.showDialog(0);
			init = true;
		}
		
		return 0;
		
	}
	
	override int onDraw(Object o) {
		info = cast(GameInfo) o;
		
		info.screen.clear();

//		m_dialog.onDraw(info.screen);

		return 0;
	}
	
	override int task(Object o) {
		return 0;
	}
	
private:

	void onInit() {
		m_dialog = new DialogBox();
		m_dialog.setDialogSize(280, 160);
		m_dialog.setXY(320, 240);
	}

	GameInfo info;
	DialogBox m_dialog;
	bool init;

}
+/

/+
/// ぼかしてすと
class TaskTest : GameTaskBase {
	

	/// 毎回呼び出す
	override int onMove(Object o) {
		info = cast(GameInfo) o;

		if (!init) {
			onInit();
			info.screen.blendSrcAlpha();
			init = true;
		}
		
		if ( currentidx > 0 ) {
			tex.subSurfaceFast(sufs[--currentidx]);
		}

		return 0;	
	}
	
	override int onDraw(Object o) {
		info = cast(GameInfo) o;
		info.screen.clear();
		
		info.screen.blt(tex,0,0);

		return 0;
	}
	
	override int task(Object o) {
		return 0;
	}
	
private:

	static Surface copySurface(Surface surface_) {
		int width = cast(int) surface_.getWidth();
		int height = cast(int) surface_.getHeight();
		bool alpha = (surface_.getSurface().format.BitsPerPixel==32);

		// createDIBして転送したほうがはやいんでないかな...
		Surface surface = new Surface();
		surface.createDIB( width, height, alpha );

		surface.blt( surface_, 0, 0 );
		return surface;
	}

	void onInit() {
		surface = new Surface();
		surface.load("soft_test.png");
		
		sufs ~= surface;
		
		for (int i = 0; i < 256; ++i) {
			sufs ~= EffectSoft.excecute( copySurface(sufs[length-1]), 2);
		}
		
		currentidx = sufs.length-1;
		
//		for (int i = 0; i < 5; ++i) 
//			EffectSoft.excecute(surface,4);
		
		Surface tmp = new Surface();
		tmp.load("soft_test.png");

		tex = new Texture();
		tex.setSurface(tmp);
		try {
			tex.subSurfaceFast(sufs[currentidx]);
		} catch (Exception e) {
			Log.printFatal("[%s]", e.toString());
		}
		
	}
	
	Surface[] sufs;
	int currentidx = 0;
	
	GameInfo info;
	bool init;
	Texture tex;
	Surface surface;

}
+/


/+
/// 螺旋球テスト
class TaskTest : GameTaskBase {
	

	/// 毎回呼び出す
	override int onMove(Object o) {
		info = cast(GameInfo) o;

		if (!init) {
			onInit();
			info.screen.blendSrcAlpha();
			init = true;
		}
		

		
		// 暗黙の型推定
		auto i = 5;
		auto s = "Hello";
		auto b = true;
		auto numbers = new int[] [ 1,2,3 ];
		auto v = new vector!(int);
//		auto i;// エラー！　型が特定できない。
//		auto y = [ 1,2,3 ];// エラー！　配列初期化子は許されていない。
		auto z = null;// void* 型
		auto fp = function int(int x, int y) { return x - y; };
		auto dg = delegate int(int x, int y) { return x - y; };
		
		sort( dg );
			
		
//		z.length;		
//		z = new C();
		
		
		
		return 0;	
	}
	
	void sort( int delegate(int,int) dg) { 
	
	}
	
	override int onDraw(Object o) {
		info = cast(GameInfo) o;
		
		info.screen.clear();

		return 0;
	}
	
	override int task(Object o) {
		return 0;
	}
	
private:

	void onInit() {
		rand = new Rand();
		rand.randomize();
		int delegate() a = &readA;
		int delegate() b = &readB;
		Thread ta = new Thread(a);
		Thread tb = new Thread(b);
		
		ta.start();
		tb.start();
	}
	
	int readA() {
		// アーカイブテスト
		FileInfoEx* lpFileInfo;
		int count = 0;
		char[] arcName = "img.dat";
		char[][] filenames;
		while ( !((lpFileInfo = FileEx.getInfo(arcName, count++)) is null) ) {
			if (count == 174) continue;
//			printf( "THREAD A -- no: %d, %*s", count, lpFileInfo.filename );
			filenames ~= "snd\\" ~ lpFileInfo.filename;
			printf("file:%*s", "snd\\" ~ lpFileInfo.filename);
			printf( "\n" );
		}
		printf( "enum file end\n" );
	
		void[] lpData;
		int readcount = 0;
		foreach (inout char[] filename; filenames) {
			lpData = FileEx.readStatic("img.dat", rand.get(filenames.length));
			printf("THREAD A -- no: %d, filename:%*s size:%d\n", readcount++, "-" ,lpData.length);
		}
		return 0;
	}
	
	int readB() {
		// アーカイブテスト
		FileInfoEx* lpFileInfo;
		int count = 0;
		char[] arcName = "img.dat";
		char[][] filenames;
		while ( !((lpFileInfo = FileEx.getInfo(arcName, count++)) is null) ) {
			if (count == 174) continue;
			printf( "THREAD B -- no: %d, %*s", count, lpFileInfo.filename );
			filenames ~= "img\\" ~ lpFileInfo.filename;
			printf( "\n" );
		}
		printf( "enum file end\n" );
	
		void[] lpData;
		int readcount = 0;
		foreach (inout char[] filename; filenames) {
//			lpData = FileSys.read("snd/bgm/01.ogg");
			lpData = FileEx.readStatic("img.dat", rand.get(filenames.length));
			printf("THREAD B -- no: %d, filename:%*s size:%d\n", readcount++, "-" ,lpData.length);
		}
		return 0;
	}
	static Rand rand;
	GameInfo info;
	SpiralObjectManager sm;
	DirectivityObjectManager dm;
	bool init;

}
+/

/+
/// 螺旋球テスト
class TaskTest : GameTaskBase {
	
	/// 毎回呼び出す
	override int onMove(Object o) {
		info = cast(GameInfo) o;

		if (!init) {
			onInit();
			info.screen.blendSrcAlpha();
			init = true;
		}
		
//		sm.onMove(info.screen);
		dm.onMove(info.screen);
		
		static uint cnt = 0;
		cnt++;
		
		if (cnt == 30*15) {
			Rect* rc = new Rect();
			rc.setRect(50, 80, 150, 170);
			dm.convergenceAll(100, 150, rc);
		}
				
		return 0;	}
	
	override int onDraw(Object o) {
		info = cast(GameInfo) o;
		
		info.screen.clear();

//		sm.onDraw(info.screen);
		dm.onDraw(info.screen);

		return 0;
	}
	
	override int task(Object o) {
		return 0;
	}
	
private:

	void onInit() {

		
	}

	GameInfo info;
	SpiralObjectManager sm;
	DirectivityObjectManager dm;
	bool init;

}
+/

/+
/// パフォーマンス計測テスト
class TaskTest : GameTaskBase {
	
	/// 毎回呼び出す
	override int onMove(Object o) {
		info = cast(GameInfo) o;

		if (!init) {
			onInit();
			init = true;
		}
		
		return 0;
	}
	
	override int onDraw(Object o) {
		info = cast(GameInfo) o;
		

		PerformanceLog.logRW("screen#clear");
		info.screen.clear();
		PerformanceLog.endLog();
		
		PerformanceLog.logRW("screen#blt");
		for (int i = 0; i < 10; ++i) {
			info.screen.blt(tex640100, 0, 0 );
		}
		PerformanceLog.endLog();
		
		return 0;
	}
	
	override int task(Object o) {
		return 0;
	}
	
private:

	void onInit() {
//		info.screen.blendSrcAlpha ();
		
		
		tex1024100 = new Texture();
		tex1024100.load("img/test/1024100.png");
		
		tex102450 = new Texture();
		tex512100 = new Texture();
		tex51250 = new Texture();
		
		tex640100 = new Texture();
		tex640100.load("img/test/64050.png");
		
	}


	GameInfo info;
	SequenceDraw seqDraw;
	bool init;
	
	
	
	Texture tex1024100;
	Texture tex102450;
	Texture tex512100;
	Texture tex51250;
	Texture tex640100;

}
+/

/+
/// KGAビューアテスト
class TaskTest : GameTaskBase {
	
	/// 毎回呼び出す
	override int onMove(Object o) {
		info = cast(GameInfo) o;

		if (!init) {
			info.getFpsTimer().setFps(2);
			onInit();
			init = true;
		}
		
		if ( index <= filenames.length-1 ) {
	//		tex.load( filenames[index] );
			index++;
		}
		
		return 0;
	}
	
	override int onDraw(Object o) {
		info = cast(GameInfo) o;

		info.screen.blendSrcAlpha ();
		info.screen.clear();
		
		info.screen.blt( tex2, 0, 0 );
		
		return 0;
	}
	
	override int task(Object o) {
		return 0;
	}
	
private:

	static const char[][] EXT_PIC = [
		"kga"
	];

	/// 画像リソースファイル列挙
	static char[][] getFileNames(char[] topDir) {
		DirEnumerator dir = new DirEnumerator();
		dir.setDir( topDir );
		
		char[][] ret;
				
		foreach ( char[] filename; dir ) {
			if ( isResouceFile( filename ) ) {
				ret ~= filename;
			}
		}
		
		return ret;
	}
	
	/// 対象拡張子がリソースファイルかどうか	
	static bool isResouceFile(char[] filename) {
		foreach ( char[] ext; EXT_PIC) {
			if (std.string.tolower(std.path.getExt(filename)) == ext) {
				return true;
			}
		}
		return false;
	}	

	/// 初期化処理
	void onInit() {
		filenames = getFileNames("img");
		
		tex = new Texture();
		tex2 = new Texture();
		SDL_Surface* surface;
		
		FileSys.RWops rw = FileSys.readRW("test/logo_2.bmp");
printf("RW OK\n");


		if(rw.rwops) {
			surface = IMG_Load_RW(rw.rwops,0);
				//	0 mean is will not automatically close/free the src

			if (surface) {
				SDL_RWclose(rw.rwops);
				tex2.setSurface( surface );
printf("LOAD OK\n");
			} else {
				printf("DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDME\n");
			}
			
			//	RWopsは生きているので他の読み込み方法をトライすべき..

//			SDL_RWclose(rw.rwops);
		} else {
		}
	}

	GameInfo info;
	bool init;
	char[][] filenames;
	Texture tex;
	Texture tex2;
	int index;

}
+/

/+
/// 文字描画動作テスト
class TaskTest : GameTaskBase {
	
	/// 毎回呼び出す
	override int onMove(Object o) {
		info = cast(GameInfo) o;

		if (!init) {
			onInit();
			init = true;
		}
		
		seqDraw.onMove(info.screen);
		
		return 0;
	}
	
	override int onDraw(Object o) {
		info = cast(GameInfo) o;

		info.screen.blendSrcAlpha ();
		info.screen.clear();
		
		seqDraw.onDraw(info.screen);
		
		
		return 0;
	}
	
	override int task(Object o) {
		return 0;
	}
	
private:

	void onInit() {
		seqDraw = new SequenceDraw();
		seqDraw.loadDefFile("img/eye/chi.lst");
	}


	GameInfo info;
	SequenceDraw seqDraw;
	bool init;

}
+/


/+
/// 多重リング動作テスト
class TaskTest : GameTaskBase {
	
	/// 毎回呼び出す
	override int onMove(Object o) {
		info = cast(GameInfo) o;

		if (!init) {
			onInit();
			init = true;
		}
		
		ring.onMove(info.screen);
		
		return 0;
	}
	
	override int onDraw(Object o) {
		info = cast(GameInfo) o;

		info.screen.blendSrcAlpha ();
		info.screen.setClearColor(128,128,128);
		info.screen.clear();
		
		
		ring.onDraw(info.screen);
		
		return 0;
	}
	
	override int task(Object o) {
		return 0;
	}
	
private:

	void onInit() {
		ring = new Rring();
		Texture t = new Texture();
		t.load("ring.png");
		ring.setTexture(t);
		ring.setPos(100,100);
		ring.setRingNum(4);
		ring.setSpeed(5);
	}


	GameInfo info;
	Rring ring;
	bool init;

}
+/

/+
/// モーフィングテスト
class TaskTest : GameTaskBase {
	
	/// 動作処理
	int onMove(Object o) {
		GameInfo info = cast(GameInfo) o;
		
		if (!init) {
			info.screen.blendSrcAlpha ();
			info.getFpsTimer().setFps(10);
			onInit(info);
			init = true;
		}
		
		m_mouse.update();
		
		if ( !bExec ) {
			// 座標セット生成フェーズ
			if ( m_mouse.isLButtonUp() ) {
				int mx,my;
				m_mouse.getPos(mx,my);
				PointInt pt;
				pt.x = mx;
				pt.y = my;
				
				if (  bSetSrc ) {
					m_srcPts ~= pt;
				} else {
					m_dstPts ~= pt;
				}
				// フェーズ入れ替え
				bSetSrc = !bSetSrc;
			} else if ( m_mouse.isRButtonUp() ) {

				// 設定座標書き出し
				fileOut();
				// 実行
				setMorpher();
				bExec = true;

			}
		} 
		
		return 0;
	}
	
	/// 描画処理
	int onDraw(Object o) {
		GameInfo info = cast(GameInfo) o;
		static int cnt = 0;
		static int add = 5;
		
		info.screen.clear();
		if ( bExec ) {
			
			// 動作テスト
			if (cnt > 255) {
				add = -1;
			} else if (cnt < 0) {
				add = 1;
			}
			cnt += add;
			
			morpher[0].OnDraw(info.screen, srcSurface, dstSurface, tmpSurface1,tmpSurface2, cnt);
		} else {
			// 座標セット生成
			
			Texture t1st;
			Texture t2nd;
			
			if (bSetSrc) {
				t1st = texSrc;
				t2nd = texDst;
			} else {
				t1st = texDst;
				t2nd = texSrc;
			}
			
			// 元画像描画
			info.screen.setColor(255,255,255,255);
			info.screen.blt(t1st, 0, 0);
			
			// 先画像透過描画
			info.screen.setColor(255,255,255,64);
			info.screen.blt(t2nd, 0, 0);

			info.screen.setColor(255,255,255,255);
		}
		
		return 0;
	}
	
	/// 今は昔
	int task(Object o) {
		return 0;
	}
	
	/// コンストラクタ
	this() {
		bSetSrc = true;
	}
		
	
private:

	/// 初期化処理
	void onInit(GameInfo info) {
		
		m_mouse = cast(MouseInput) info.mouse;
		
		// ここを変更
//		char[] strSrcFile = "TEST/morph/alice0101.0.png";
//		char[] strDstFile = "TEST/morph/tomie101.0.png";
		char[] strSrcFile = "TEST/morph/tomie01.png";
		char[] strDstFile = "TEST/morph/anzai01.png";
		
		tmpSurface1 = new Surface();
		tmpSurface1.createDIB(640, 480, true);
		tmpSurface2 = new Surface();
		tmpSurface2.createDIB(640, 480, true);
		
		srcSurface = new Surface();
		dstSurface = new Surface();
		
		srcSurface.load(strSrcFile);
		dstSurface.load(strDstFile);
		
		// 表示用画像の生成
		texSrc = new Texture();
		texDst = new Texture();
		texSrc.load( strSrcFile );
		texDst.load( strDstFile );
		
		srcSurface.setDIB32Compatible();
		dstSurface.setDIB32Compatible();
		tmpSurface1.setDIB32Compatible();
		tmpSurface2.setDIB32Compatible();

		// SubTextureを使うために、使用するサイズより大きなテクスチャを設定しておく
		Surface tmp = new Surface();
		tmp.createDIB(640,480,true);
		texTest = new Texture();
		texTest.setSurface(tmp);
		
	}
	
	/// 設定した座標を、モーファーに設定し、実行の準備を行う。
	void setMorpher() {
		morpher[0] = new SurfaceMorph();

		// あかんやん...
		if ( m_srcPts is null || m_dstPts is null ) return;
		
		for( int i = 0; i < m_srcPts.length; ++i) {
			if (i >= m_dstPts.length) break;
			morpher[0].Set(m_srcPts[i].x, m_srcPts[i].y,
							m_dstPts[i].x, m_dstPts[i].y);
		}

		morpher[0].SetDiv(220,386,10,10);//	分解能
		morpher[0].Calc();				//	計算しなちゃい＾＾
		
		// 不要消去
		m_srcPts = null;
		m_dstPts = null;
	}
	
	/// 設定した座標をファイルに書き出す
	void fileOut() {
		char[] buf;
		
		if ( m_srcPts is null || m_dstPts is null ) return;
		
		for( int i = 0; i < m_srcPts.length; ++i) {
			if (i >= m_dstPts.length) break;
			
			buf ~= std.string.toString(m_srcPts[i].x) ~ ",";
			buf ~= std.string.toString(m_srcPts[i].y) ~ ",";
			buf ~= std.string.toString(m_dstPts[i].x) ~ ",";
			buf ~= std.string.toString(m_dstPts[i].y) ~ "\r\n";
		}

		// 書き出し！		
		FileSys.write("TEST/morph/morph_conf.txt", buf);
	}
	
	bool bExec;			//!< 実行フラグ
	bool bSetSrc;		//!< 元画像の座標指定フェーズかどうか
	MouseInput m_mouse;
	
	PointInt[] m_srcPts;
	PointInt[] m_dstPts;
	
	Texture texTest;
	
	Texture texSrc;
	Texture texDst;

	SurfaceMorph morpher[2];
	bool init;
	Surface tmpSurface1;
	Surface tmpSurface2;
	Surface srcSurface;
	Surface dstSurface;
}
+/

/+
/// ScenarioDrawテスト
class TaskTest : GameTaskBase {
	
	/// 毎回呼び出す
	override int onMove(Object o) {
		GameInfo info = cast(GameInfo) o;
		
		if (!init) {
			onInit(info);
			init = true;
		}

		mouse.update();
		
		// しおり画面からもどってきた！
		if (jumpShiori) {
			
			CurrentInfo ci = Bookmark.getCurrentInfo();
			if ( !(ci is null) ) {
				// 選択されたしおりからScenarioDrawを再構築
				initSecectedInfo(ci);
			}
			
			jumpShiori = false;
		}
		
		int taskReq = sd.popTaskReq();
		if ( -1 != taskReq ) {
			if ( KyojinConst.Task.Task_Scenario == taskReq ) {
				sd.nextScenario( sd.getCurrentScenarioInfo().storyNo+1 );
			}
			printf("next scenario load\n");
		}
		
		// オプション画面からもどってきた！
		if (jumpOption) {
			sd.setOptionInf(info.optionInfo);
			jumpOption = false;
		}
		
		sd.onMove(info.screen);
		if ( mouse.isLButtonUp() && !m_menu.isInBar() ) {
			sd.setNext(true);
		}
		
		// 事典コントローラ
		m_dictCtl.onMove(info.screen);

		
		m_menu.onMove(info.screen);
		int bx,by;
		
		// メニューボタン判定
		foreach ( int i,MenuItem item; m_menu.getItems() ) {
			if ( item.getButton().isLClick() ) {

				// 遷移する前にオートセーブ
				doAutoSave();
				switch (i) {
				case 0:		// SAVE
					Bookmark.setTitle(false);
					foreach (inout Bookmark bm; info.bookmark) {
						bm.setReadOnly(false);
						bm.resetBtFlag();
						bm.onMove(info.screen);
					}
					
					CurrentInfo ci = new CurrentInfo();
					ci.si = sd.getCurrentScenarioInfo();
					ci.text = sd.getCurrentText();
					
					Bookmark.setCurrentInfo(ci);
					
					jumpShiori = true;
					
					info.gameSceneTransiter.callScene(KyojinConst.Task.Task_Bookmark);
					break;
					
				case 1:		// OPTION
					info.gameSceneTransiter.callScene(KyojinConst.Task.Task_Option);
					break;
					
				case 2:	// 事典
					break;
				
				default:
					break;				
				}
				break;
			}
		}
		

		return 0;
	}
	
	/// 毎回呼び出すなり
	override int onDraw(Object o) {
		GameInfo info = cast(GameInfo) o;
		
		info.screen.clear();
		info.screen.blendSrcAlpha();
		
		sd.onDraw(info.screen);
		
//		m_dictCtl.onDraw(info.screen);
		
		info.screen.disableBlend();
		m_menu.onDraw(info.screen);

		return 0;
	}
	
	/// レガシーなやつ
	override int task(Object o) {
		return 0;
	}
	
	/// デストラクタ
	~this() {
	}
	
private:

	/// 初期化処理
	void onInit(GameInfo info) {
		
		Log.print("TaskTest onInit start!");
		
		// マウス情報
		mouse = cast(MouseInput) info.mouse();

		// メニューバー生成
		initMenu();
		// 事典コントローラ
		initDict(info.fontloader);
		m_dictCtl.onMove(info.screen);
		
		sd = new ScenarioDrawEx();
		context = new TextDrawContext();
		si = new ScenarioInfo();
		
		// @TODO
		char[] strText = cast(char[])FileSys.read( KyojinConst.scenarioFileName[4] );
		context.setText( toWCS(strText) );

		sd.setOptionInf(info.optionInfo);
		sd.setScenarioInfo(si);
		sd.setTextDrawContext(context);
		sd.setBGLoader(info.tl_bg);
		sd.setSilhouetteLoader(info.tl_shil);
		sd.setBGMLoader(info.bgmloader);
		sd.setSELoader(info.seloader);
		sd.setVoiceLoader(info.voiceloader);
		sd.setFontLoader(info.fontloader);
		sd.setOffset(38,28);
		
		Texture t = new Texture();
		t.load( FileSys.makeFullName("img/scenario/carsor.png") );
		sd.setPromptCarsor(t);
		
		
		Log.print("ScenarioDrawEx setting ok\n");
	}
	
	/// メニューバーを生成する
	void initMenu() {
		// メニューバーテスト
		m_menu = new MenuBar(mouse);
		Texture tTmp = new Texture();
		tTmp.load("img/menu/nbar.bmp");
		m_menu.setBaseTexture( tTmp ); 
			
		// メニューボタンの生成
		TextureLoader tl = new TextureLoader();
		tl.loadDefRW( FileSys.read("img/menu/menu_bt.txt") );
		
		GUIButton btSaveLoad = new GUIButton();
		GUIButton btOp = new GUIButton();
		GUIButton btSd = new GUIButton();
		
		GUINormalButtonListener v  = new GUINormalButtonListener;
		v.setTextureLader(tl,0);
		v.setType(9);
		btSaveLoad.setMouse( cast(MouseInput) mouse);
		btSaveLoad.setEvent(v);
		btSaveLoad.setXY(4, 1);
		
		v  = new GUINormalButtonListener;
		v.setTextureLader(tl,3);
		v.setType(9);
		btOp.setMouse( cast(MouseInput)  mouse);
		btOp.setEvent(v);
		btOp.setXY(120, 1);

		// リスナ
		v  = new GUINormalButtonListener;
		// ボタンテクスチャの番号
		v.setTextureLader(tl,6);
		v.setType(9);
		btSd.setMouse( cast(MouseInput)  mouse);
		btSd.setEvent(v);
		// 描画位置
		btSd.setXY(200, 1);
		
		// コンテナにつめる
		MenuItem item = new MenuItem();
		item.setButton( btSaveLoad );
		m_menu.addItem( item );
		
		item = new MenuItem();
		item.setButton( btOp );
		
		m_menu.addItem( item );

		// 事典ボタン
		item = new MenuItem();
		item.setButton( btSd );
		
		m_menu.addItem( item );
		
	}
	
	/// 事典コンポーネント生成
	void initDict(FontLoader fl) {
		m_dictCtl = new DictController();
		m_dictCtl.setMouse( mouse );
		m_dictCtl.setFontLoader(fl); 
	}
	
	/// ブックマークで選択された情報からScenarioDrawを再構築します
	void initSecectedInfo(CurrentInfo ci) {
		int sNo = ci.si.storyNo;
		char[] strText = cast(char[])FileSys.read(KyojinConst.scenarioFileName[sNo]);
		context.setText( toWCS(strText) );
		
		sd.onLoad( ci.si, context, ci.start );
	}
	
	/// オートセーブを実行する
	void doAutoSave() {
		// オートセーブデータの更新
		GameInfo.bookmark[KyojinConst.BookmarkID.AUTO].setScenarioInfo(sd.getCurrentScenarioInfo());
		GameInfo.bookmark[KyojinConst.BookmarkID.AUTO].setText(sd.getCurrentText());
	}
	
	MenuBar m_menu;				//!< メニューコントローラ
	bool init;
	DictController m_dictCtl;	//!< 事典コントローラ
	
	bool jumpShiori;	//!< 遷移フラグ
	bool jumpOption;
	
	TextDrawContext context;	//!< 描画コンテキスト
	ScenarioInfo si;			//!< シナリオモデル
	
	ScenarioDrawEx sd;			//!< ScenarioDrawコンポーネント
	MouseInput mouse;			//!< マウスデバイス
	
	Texture texTest;
}

+/

/+
/// モーフィングテスト
class TaskTest : GameTaskBase {
	
	int onMove(Object o) {
		GameInfo info = cast(GameInfo) o;
		
		if (!init) {
			info.screen.blendSrcAlpha ();
			info.getFpsTimer().setFps(10);
			onInit();
			init = true;
		}
		
		
		return 0;
	}
	
	int onDraw(Object o) {
		GameInfo info = cast(GameInfo) o;
		
		info.screen.clear();
		
		
		static int cnt = 0;
		static int add = 5;

		if (cnt > 256) {
			add = -5;
		} else if (cnt < 0) {
			add = 5;
		}
		cnt += add;
		
		morpher[0].OnDraw(info.screen, srcSurface, dstSurface, tmpSurface1,tmpSurface2, cnt);
		
		return 0;
	}
	
	int task(Object o) {
		return 0;
	}
	
private:
	void onInit() {
		morpher[0] = new SurfaceMorph();
		morpher[1] = new SurfaceMorph();
		morpher[0].Set(0,0,0,0);		//	４隅
		morpher[0].Set(219,0,220,0);
		morpher[0].Set(0,375,0,386);
		morpher[0].Set(219,375,220,386);
		morpher[0].Set(36,47,108,3);	//	顔の輪郭６点	
		morpher[0].Set(106,106,106,107);
//		morpher[0].Set(57,106,66,66);
		morpher[0].Set(117,54,147,53);
		morpher[0].Set(72,102,90,68);
		morpher[0].Set(95,74,121,67);

		morpher[0].Set(126,372,118,385);
		morpher[0].Set(65,231,60,279);
		morpher[0].Set(162,253,160,280);
		morpher[0].Set(169,105,161,139);
		morpher[0].Set(85,120,58,135);

		morpher[0].SetDiv(220,386,10,10);//	分解能
		morpher[0].Calc();				//	計算しなちゃい＾＾
		//	以下同様
		morpher[1].Set(0,0,0,0);
		morpher[1].Set(542,0,306,0);
		morpher[1].Set(0,438,0,258);
		morpher[1].Set(542,438,306,258);
		morpher[1].Set(262,168,58,140);
		morpher[1].Set(312,386,60,188);
		morpher[1].Set(396,396,100,240);
		morpher[1].Set(472,374,180,236);
		morpher[1].Set(488,292,222,190);
		morpher[1].Set(476,218,76,60);
		morpher[1].SetDiv(542,438,10,10);
		morpher[1].Calc();
		
		tmpSurface1 = new Surface();
		tmpSurface1.createDIB(640, 480, true);
		tmpSurface2 = new Surface();
		tmpSurface2.createDIB(640, 480, true);
		
		srcSurface = new Surface();
		dstSurface = new Surface();
		
		srcSurface.load("alice0101.0.png");
		dstSurface.load("tomie101.0.png");
		
		srcSurface.setDIB32Compatible();
		dstSurface.setDIB32Compatible();
		tmpSurface1.setDIB32Compatible();
		tmpSurface2.setDIB32Compatible();
		

		// SubTextureを使うために、使用するサイズより大きなテクスチャを設定しておく
		Surface tmp = new Surface();
		tmp.createDIB(640,480,true);
		texTest = new Texture();
		texTest.setSurface(tmp);
		
	}
	
	Texture texTest;

	SurfaceMorph morpher[2];
	bool init;
	Surface tmpSurface1;
	Surface tmpSurface2;
	Surface srcSurface;
	Surface dstSurface;
	
}

+/

/+
/// カメラワーククリエイター
class TaskTest : GameTaskBase {

	/// タスク名を返却する
	/**
		このタスク名称を使って、コントローラ部でタスク判別を行う可能性があるので
		ユニークな名前で、実装しておくべきである
	*/	
	override char[] getTaskName() {
		return kyojintati4d.val.kyojinconst.KyojinConst.TASK_NAME[kyojintati4d.val.kyojinconst.KyojinConst.Task.Task_Test];
	}
	
	int onMove(Object o) {
		GameInfo info = cast(GameInfo) o;
		
		static uint time = 0;
		
		if (!init) {
			onInit(info);
			init = true;
		}
		
		if ( mouse.isRButtonUp() ) {
			wc.save( 640, 480 );
			Log.print("SAVED.");
		}
		
//		wc.onMove(info.screen);

		cw.onMove(info.screen);
		return 0;
	}
	
	int onDraw(Object o) {
		GameInfo info = cast(GameInfo) o;
//		info.screen.blendSrcAlpha ();
//		info.screen.setClearColor(128,128,128);
//		info.screen.clear();
		
		cw.onDraw(info.screen);
	
//		wc.onDraw(info.screen);	
		
		return 0;
	}
	
	int task(Object o) {
		return 0;
	}
	
private:

	void onInit(GameInfo info) {
		mouse = cast(MouseInput) info.mouse();
		
		Texture t = new Texture();
		t.load("img/main_ending/s11/cw/original_resize.jpg");
		wc = new WarkCreater(info.mouse, info.screen.getWidth(), info.screen.getHeight() );
		wc.setPicSize( 1024, 1024 );
		wc.setBaseTexture(t);
		
		t = new Texture();
		t.load("img/pin/pin01.png");
		cw = new CameraWork("img/main_ending/s11/cw/list.lst", 2, 2);
		cw.setBaseTexture(t);
//		cw.loadFlow("mouse.txt");
		cw.loadFlow("img/main_ending/s11/cw/mouse.txt");
//		m_cameraWork = new CameraWork("img/main_ending/s11/cw/list.lst", 2, 2);
//		m_cameraWork.loadFlow("img/main_ending/s11/cw/mouse.txt");
//		cw.addSubjectSimple(t,1500, 1400);
		
	}
	WarkCreater wc;
	CameraWork cw;
	
	MouseInput mouse;

	Texture tex;			//!< 表示テクスチャ
	bool init;
	Texture testTex;
}
+/



/+
/// フレームバッファコピーテスト
class TaskTest : GameTaskBase {
	
	int onMove(Object o) {
		GameInfo info = cast(GameInfo) o;
		
		static uint time = 0;
		
		if (!init) {
			onInit();
			init = true;
		}
		
		if ( time++ == 100 ) {
			printf("test!!");
			test = true;
			info.gameSceneTransiter.setTransitType(22,1);
			info.gameSceneTransiter.jumpScene(KyojinConst.Task.Task_Logo);
			return 1;
		}
		
		return 0;
	}
	
	int onDraw(Object o) {
		GameInfo info = cast(GameInfo) o;
		
		info.screen.clear();
		
		if (!test) {
			info.screen.blt( tex, 0, 0 );
		} else {
			Rect rc;
			rc.left = 0.0f;
			rc.right = testTex.getWidth();
			rc.bottom = 0.0f;
			rc.top = testTex.getHeight();
			info.screen.blt( testTex, 0, 0, &rc );
		}
		
		
		return 0;
	}
	
	int task(Object o) {
		return 0;
	}
	
private:
	void onInit() {
		tex = new Texture();
		tex.load("img/back/place058.jpg");
	}


	Texture tex;			//!< 表示テクスチャ
	bool init;
	Texture testTex;
	
	bool test;
}
+/




/// エフェクターテストタスク
class TaskTest : GameTaskBase {

	/// 毎回呼び出すなり
	override int onMove(Object o) {
		info = cast(GameInfo) o;

		if (wait) {
			
			wait++;
			if ( wait >= LC_WAIT ) {
				wait = 0;
				if ( bgEffect.get() == 255 ) {
					bgEffect.set(255, 0, effectSpeed);
				} else {
					bgEffect.set(0, 255, effectSpeed);
				}
			}	

		} else {
			
			bgEffect++;
			if ( bgEffect.isEnd() ) {
				wait = 1;
			}
			
				
		}

		info.key.update();
		
		if ( info.key.isPush(3) ) {

			if (!press) {
				bgEffectNo--;
	
				if (bgEffectNo < 0) {
					bgEffectNo = LC_EFFECT_MAX;
				}
				
				texNo.setSurface(
					info.fontloader.get(0).drawSolidUTF8( 
						"EFFECT NO:" ~ std.string.toString(bgEffectNo) ) );
				
				press = true;
			}

		} else if ( info.key.isPush(4) ) {
			if (!press) {
				bgEffectNo++;

				if (bgEffectNo > LC_EFFECT_MAX) {
					bgEffectNo = 0;
				}

				texNo.setSurface(
					info.fontloader.get(0).drawSolidUTF8( 
						"EFFECT NO:" ~ std.string.toString(bgEffectNo) ) );
	
				press = true;
			}
			
			
		} else if ( info.key.isPush(2) ) {
			// speed アップ
			effectSpeed--;
			
			if (effectSpeed == 0) {
				effectSpeed = -1;
			}

			texSpeed.setSurface(
				info.fontloader.get(0).drawSolidUTF8( 
					"EFFECT SPEED:" ~ std.string.toString(effectSpeed) ) );
			
			bgEffect.setStep( effectSpeed );

		} else if ( info.key.isPush(1) ) {
			// speed ダウン
			effectSpeed++;
			
			if (effectSpeed == 255) {
				effectSpeed = 255;
			}

			texSpeed.setSurface(
				info.fontloader.get(0).drawSolidUTF8( 
					"EFFECT SPEED:" ~ std.string.toString(effectSpeed) ) );

			bgEffect.setStep( effectSpeed );

		} else {
			press = false;
		}
		
		texPhase.setSurface(
			info.fontloader.get(0).drawSolidUTF8( 
					"phase:" ~ std.string.toString(bgEffect.get()) ) );
		
		return 0;
	}

	/// 毎回呼び出すなり
	override int onDraw(Object o) {
		info = cast(GameInfo) o;
		info.screen.clear();
		info.screen.blendSrcAlpha();
		info.screen.setColor(255, 255, 255, 255);
		
		if (bgEffect.get() != 0) {
			TransBltter.blt(
				bgEffectNo,
				info.screen,
				tex,
				0,0,
				bgEffect.get());
		}
		
		info.screen.setColor(255, 255, 255, 255);
			
		info.screen.blt( texNo, 0, 0 );
		info.screen.blt( texSpeed, 0, 24 );
		info.screen.blt( texPhase, 400, 0 );
			
		return 0;
	}

	/// 移動描画同時
	int task(Object o) {
		return 0;
	}
	
	/// コンストラクタ
	this() {
		effectSpeed = 1;
		bgEffect = new RootCounterS();
		bgEffect.set(0, 255, effectSpeed);
		tex = new Texture();
		tex.load(cast(char[]) "dev_tool/effector/bg.jpg");
		
		texNo = new Texture();
		texSpeed = new Texture();
		texPhase = new Texture();
	}
	

private:
	static const int LC_WAIT = 60;
	static const int LC_EFFECT_MAX = 23;

	GameInfo info;
	
	bool press;
	int wait;
	int waitCount;
	int bgEffectNo;			//!< エフェクト番号
	RootCounterS bgEffect;	//!< エフェクト位相
	int effectSpeed;
	
	Texture tex;			//!< 表示テクスチャ
	Texture texNo;
	Texture texSpeed;
	Texture texPhase;

}


/+
/// ぼかしてすと
class TaskTest : GameTaskBase {
	

	/// 毎回呼び出す
	override int onMove(Object o) {
		info = cast(GameInfo) o;

		if (!init) {
			onInit();
			info.screen.blendSrcAlpha();
			info.screen.setClearColor(255,255,255);
			init = true;
		}
		
		foreach(spreadStringBlur;spreadStringBlurs) {
			spreadStringBlur.onMove(info.screen);
			if (spreadStringBlur.isEndAlpha()) {
				if (rand is null) {
					rand = new Rand();
				}
				spreadStringBlur.reset();
				spreadStringBlur.setStringUnicode(messages[rand.get(messages.length)]);
			}
		}

		return 0;	
	}
	
	override int onDraw(Object o) {
		info = cast(GameInfo) o;
		info.screen.clear();

		info.screen.setColor(0,0,0);
		foreach(spreadStringBlur;spreadStringBlurs) {
			spreadStringBlur.onDraw(info.screen);
		}

		return 0;
	}
	
	override int task(Object o) {
		return 0;
	}
	
private:

	void onInit() {
		messages = loadMessage();

		FontRepository frontRep = createFontRepository("./fonts/FS-Mincho.ttf", 50, 0, 100);
		FontRepository backRep = createFontRepository("./fonts/FS-Mincho.ttf", 10, 0, 100);
		
		spreadStringBlurs ~= createSpread1(frontRep, backRep);
		spreadStringBlurs[0].setStringUnicode(messages[100]);
		spreadStringBlurs[0].setPosXY(320,240);
		
		auto obj = createSpread2(frontRep, backRep);
		for(int i = 0; i < 10; ++i) {
			obj.onMove(null);
		}
		obj.setStringUnicode(messages[100]);
		obj.setPosXY(320, 220);
		spreadStringBlurs ~= obj;
	}
	
	
	SpreadStringBlur createSpread1(FontRepository frontRep, FontRepository backRep) {
		int rad = 500; //480;
		int step = 256;
		int startWidth = -10;
		int endWidth = 30;

		// フォント作成

		// エッセンス生成
		auto essence = new SpreadStringBlur.EssencePram();
		essence.frontFont = frontRep;
		essence.backFont = backRep;
		essence.spreadStartWidth = startWidth;
		essence.spreadEndWidth = endWidth;
		essence.spreadSpeed = step;
		essence.rad = rad;
		essence.frontRate = 1.0f;
		essence.backRate = 5.0f;
		{
			auto alphaCounter = new RootCounterS();
			alphaCounter.set(200, 15, 30);
			essence.frontAlpha = alphaCounter;
		}
		{
			auto alphaCounter = new RootCounterS();
			alphaCounter.set(150, 15, 5);
			essence.backAlpha = alphaCounter;
		}
		
		return new SpreadStringBlur(essence);
	}

	SpreadStringBlur createSpread2(FontRepository frontRep, FontRepository backRep) {
		int rad = 500 - 256
		; //480;
		int step = 256;
		int startWidth = -10;
		int endWidth = 30;

		// エッセンス生成
		auto essence = new SpreadStringBlur.EssencePram();
		essence.frontFont = frontRep;
		essence.backFont = backRep;
		essence.spreadStartWidth = startWidth;
		essence.spreadEndWidth = endWidth;
		essence.spreadSpeed = step;
		essence.rad = rad;
		essence.frontRate = 1.0f;
		essence.backRate = 5.0f;
		{
			auto alphaCounter = new RootCounterS();
			alphaCounter.set(200, 15, 30);
			essence.frontAlpha = alphaCounter;
		}
		{
			auto alphaCounter = new RootCounterS();
			alphaCounter.set(150, 15, 5);
			essence.backAlpha = alphaCounter;
		}
		
		return new SpreadStringBlur(essence);
	}

	
	
	FontRepository createFontRepository(char[] fontFilename, int fontSize, int fontIndex, int max) {
		FontLoader fontLoader = SpreadString.createFontLoader(fontFilename, fontSize, fontIndex);
		fontLoaders ~= fontLoader;
		return SpreadString.setupFontRepository(fontLoader, 0, max);
	}

	wchar[][] loadMessage() {
		char[] strText = cast(char[]) FileSys.read("data/sKyojin1.html");
		char[] normalText = std.regexp.sub(strText, "s/<.*?>//g", "");
//printf("%*s", normalText);
		wchar[][] result;
		std.stream.MemoryStream m = new std.stream.MemoryStream(cast(ubyte[]) normalText);
		while (!m.eof) {
			wchar[] wc = .toWCS(m.readLine());
			if (wc is null) {
				continue;
			}
			if (wc.length > 20) {
				result ~= wc[0..20];
			} else {
				result ~= wc;
			}
		}
		return result;
	}
	
	GameInfo info = null;
	bool init = false;
	SpreadStringBlur[] spreadStringBlurs;
	static Rand rand;
	
	// 展開描画クラス
	FontLoader[] fontLoaders;
	wchar[][] messages;
}
+/

}
