//
//	cliplcds.cs
//
//	液晶シーケンサ
//
//	CLiP - Common Library for P/ECE
//	Copyright (C) 2017 Naoyuki Sawa
//
//	* Thu Mar 09 22:07:47 JST 2017 Naoyuki Sawa
//	- 1st リリース。
//	* Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
//	- Unityの場合の条件コンパイルをやめました。
//	  Unityのプログラムでも、ゲームの処理における座標はDxLibと同様にピクセル単位の整数で管理して、最後の最後に、描画関数の中でUnityの論理座標の実数に変換する事にしたからです。
//	  そうした理由は、もしゲームの処理における座標もUnityの論理座標で管理すると、既存のプログラムを流用する際に変更箇所が多くなり過ぎる問題が生じたからです。
//	  また、色についても、ゲームの処理における色はこれまで通りD3DCOLOR(=int)で管理して、最後の最後に、描画関数の中でUnityEngine.Colorに変換する事にしました。
//	  以上の理由により、当モジュールの、Unityの場合の条件コンパイルは不要になりました。
//
using System;
namespace org.piece_me {
	public static partial class libclip {
		//*****************************************************************************
		//	構造体
		//*****************************************************************************
		//液晶シーケンサチャネル
		public class ST_LcdSeqCh {
			public ushort			Cnt;		//描画回数		0～USHRT_MAX(飽和)
			public ushort			SprNo;		//スプライト番号	0(非表示),1～SprNo_Max
			public ushort			Mode;		//描画モード		DX_BLENDMODE_*		DxLibを使用しない場合はアプリケーション定義の任意の値です。
			public short			Pri;		//優先度		SHRT_MIN～SHRT_MAX
//{{2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
//#if     !UNITY_5_3_OR_NEWER
//}}2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
			public short			PosX;		//座標X			SHRT_MIN～SHRT_MAX
			public short			PosY;		//座標Y			SHRT_MIN～SHRT_MAX
			public int			Color;		//カラー		D3DRGBA(r,g,b,a)
//{{2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
//#else //!UNITY_5_3_OR_NEWER
//			public float			PosX;		//座標X			FLT_MIN～FLT_MAX
//			public float			PosY;		//座標Y			FLT_MIN～FLT_MAX
//			public UnityEngine.Color	Color;		//カラー		Color(r,g,b,a),又は,Color32(r,g,b,a)
//#endif//!UNITY_5_3_OR_NEWER
//}}2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
		}
		//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
		//液晶シーケンサ
		public class ST_LcdSeq {
			public ST_LcdSeqInfo			pLcdSeqInfo;		//初期化情報へのポインタ
			public ST_LcdSeqCh[/*nLcdSeqCh*/]	TBL_LcdSeqCh;		//液晶シーケンサチャネル
		}
		//-----------------------------------------------------------------------------
		//液晶シーケンサチャネル初期化情報
		public class ST_LcdSeqChInfo {
			public ushort			Mode;		//デフォルト描画モード	DX_BLENDMODE_*		DxLibを使用しない場合はアプリケーション定義の任意の値です。
			public short			Pri;		//デフォルト優先度	SHRT_MIN～SHRT_MAX
//{{2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
//#if     !UNITY_5_3_OR_NEWER
//}}2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
			public short			PosX;		//デフォルト座標X	SHRT_MIN～SHRT_MAX
			public short			PosY;		//デフォルト座標Y	SHRT_MIN～SHRT_MAX
			public int			Color;		//カラー		D3DRGBA(r,g,b,a)
//{{2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
//#else //!UNITY_5_3_OR_NEWER
//			public float			PosX;		//座標X			FLT_MIN～FLT_MAX
//			public float			PosY;		//座標Y			FLT_MIN～FLT_MAX
//			public UnityEngine.Color	Color;		//カラー		Color(r,g,b,a),又は,Color32(r,g,b,a)
//#endif//!UNITY_5_3_OR_NEWER
//}}2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
		}
		//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
		//液晶シーケンサ初期化情報
		public class ST_LcdSeqInfo {
			public Action<int/*iLcdSeqCh*/,ST_LcdSeqCh/*pLcdSeqCh*/>	fnDraw;		//アプリケーション定義の描画関数
			public ushort		_SprNo_Max;						//スプライト番号の最大値
			public int		nLcdSeqCh { get { return TBL_LcdSeqChInfo.Length; } }	//液晶シーケンサチャネル数
			public ST_LcdSeqChInfo[/*nLcdSeqCh*/]	TBL_LcdSeqChInfo;			//液晶シーケンサチャネル初期化情報
		}
		//*****************************************************************************
		//	ローカル関数
		//*****************************************************************************
		private static void LcdSeqCh_Draw(ST_LcdSeq pLcdSeq, int iLcdSeqCh) {
			//チャネルの構造体を取得する。
			ST_LcdSeqCh pLcdSeqCh = LcdSeq_GetLcdSeqCh(pLcdSeq, iLcdSeqCh);
			//停止中ならば何もしない。
			if(pLcdSeqCh.SprNo == 0) { return; }	//ここまで
			//描画関数を呼び出す。
			pLcdSeq.pLcdSeqInfo.fnDraw.Invoke(iLcdSeqCh, pLcdSeqCh);
			//描画回数を増やす。
			if(pLcdSeqCh.Cnt < ushort.MaxValue/*飽和*/) { pLcdSeqCh.Cnt++; }
		}
		//*****************************************************************************
		//	グローバル関数
		//*****************************************************************************
		public static ST_LcdSeq LcdSeq_New(ST_LcdSeqInfo pLcdSeqInfo) {
			ST_LcdSeq pLcdSeq;
			//構造体のメモリを確保する。
			pLcdSeq = new ST_LcdSeq();
			//構造体を初期化する。
			LcdSeq_Init(pLcdSeq, pLcdSeqInfo);
			return pLcdSeq;
		}
		//-----------------------------------------------------------------------------
		public static void LcdSeq_Init(ST_LcdSeq pLcdSeq, ST_LcdSeqInfo pLcdSeqInfo) {
			int iLcdSeqCh;
#if     __DXLIB
			//初期化情報を検査する。
			for(iLcdSeqCh = 0; iLcdSeqCh < pLcdSeq.pLcdSeqInfo.nLcdSeqCh; iLcdSeqCh++) {
				ST_LcdSeqChInfo pLcdSeqChInfo = LcdSeq_GetLcdSeqChInfo(pLcdSeq, iLcdSeqCh);
				if((uint)pLcdSeqChInfo.Mode >= (uint)DX_BLENDMODE_NUM) { throw new ApplicationException(); }
			}
#endif//__DXLIB
			//構造体をクリアする。
		//不要	pLcdSeq.pLcdSeqInfo  = null;
		//不要	pLcdSeq.TBL_LcdSeqCh = null;
			//初期化情報へのポインタを格納する。
			pLcdSeq.pLcdSeqInfo = pLcdSeqInfo;
			//液晶シーケンサチャネル配列を作成する。
			pLcdSeq.TBL_LcdSeqCh = new ST_LcdSeqCh[pLcdSeqInfo.nLcdSeqCh];
			for(iLcdSeqCh = 0; iLcdSeqCh < pLcdSeqInfo.nLcdSeqCh; iLcdSeqCh++) {
				pLcdSeq.TBL_LcdSeqCh[iLcdSeqCh] = new ST_LcdSeqCh();
			}
		}
		//-----------------------------------------------------------------------------
		public static void LcdSeq_Draw(ST_LcdSeq pLcdSeq) {
			int iLcdSeqCh;
			//各チャネルについて…
			for(iLcdSeqCh = 0; iLcdSeqCh < pLcdSeq.pLcdSeqInfo.nLcdSeqCh; iLcdSeqCh++) {
				//チャネルを描画する。
				LcdSeqCh_Draw(pLcdSeq, iLcdSeqCh);
			}
		}
		//-----------------------------------------------------------------------------
		public static void LcdSeqCh_Play(ST_LcdSeq pLcdSeq, int iLcdSeqCh, int SprNo/*0可*/) {
			//引数のスプライト番号が0以外ならば…
			if(SprNo != 0) {
				//チャネルの初期化情報を取得する。
				ST_LcdSeqChInfo pLcdSeqChInfo = LcdSeq_GetLcdSeqChInfo(pLcdSeq, iLcdSeqCh);
				//チャネルの構造体を取得する。
				ST_LcdSeqCh pLcdSeqCh = LcdSeq_GetLcdSeqCh(pLcdSeq, iLcdSeqCh);
				//チャネルの構造体をクリアする。
				pLcdSeqCh.Cnt		= 0;				//描画回数		0～USHRT_MAX(飽和)
			//不要	pLcdSeqCh.SprNo		= 0;				//スプライト番号	0(非表示),1～SprNo_Max
			//不要	pLcdSeqCh.Mode		= 0;				//描画モード		DX_BLENDMODE_*		DxLibを使用しない場合はアプリケーション定義の任意の値です。
			//不要	pLcdSeqCh.Pri		= 0;				//優先度		SHRT_MIN～SHRT_MAX
//{{2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
//#if     !UNITY_5_3_OR_NEWER
//}}2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
			//不要	pLcdSeqCh.PosX		= 0;				//座標X			SHRT_MIN～SHRT_MAX
			//不要	pLcdSeqCh.PosY		= 0;				//座標Y			SHRT_MIN～SHRT_MAX
			//不要	pLcdSeqCh.Color		= 0;				//カラー		D3DRGBA(r,g,b,a)
//{{2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
//#else //!UNITY_5_3_OR_NEWER
//			//不要	pLcdSeqCh.PosX		= 0;				//座標X			FLT_MIN～FLT_MAX
//			//不要	pLcdSeqCh.PosY		= 0;				//座標Y			FLT_MIN～FLT_MAX
//			//不要	pLcdSeqCh.Color		= default(UnityEngine.Color);	//カラー		Color(r,g,b,a),又は,Color32(r,g,b,a)
//#endif//!UNITY_5_3_OR_NEWER
//}}2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
				//引数のスプライト番号を検査する。
				if((SprNo < 1) || (SprNo > pLcdSeq.pLcdSeqInfo._SprNo_Max)) { throw new ApplicationException(); }	//スプライト番号が不正。おそらくアプリケーションのバグです。
				//スプライト番号を格納する。
				pLcdSeqCh.SprNo = (ushort)SprNo;
				//デフォルト値を格納する。
				pLcdSeqCh.Mode  = pLcdSeqChInfo.Mode;
				pLcdSeqCh.Pri   = pLcdSeqChInfo.Pri;
				pLcdSeqCh.PosX  = pLcdSeqChInfo.PosX;
				pLcdSeqCh.PosY  = pLcdSeqChInfo.PosY;
				pLcdSeqCh.Color = pLcdSeqChInfo.Color;
			//引数のスプライト番号が0ならば…
			} else {
				//LcdSeqCh_Stop()を呼び出すのと同じ意味となります。
				LcdSeqCh_Stop(pLcdSeq, iLcdSeqCh);
			}
		}
		//-----------------------------------------------------------------------------
		public static void LcdSeqCh_SetMode(ST_LcdSeq pLcdSeq, int iLcdSeqCh, int Mode) {
			//チャネルの構造体を取得する。
			ST_LcdSeqCh pLcdSeqCh = LcdSeq_GetLcdSeqCh(pLcdSeq, iLcdSeqCh);
			//引数の描画モードを検査する。
#if     __DXLIB
			if((uint)Mode >= (uint)DX_BLENDMODE_NUM) { throw new ApplicationException(); }	//描画モードが不正。おそらくアプリケーションのバグです。
#endif//__DXLIB
			//停止中ならば格納しない。
			if(pLcdSeqCh.SprNo == 0) { return; }	//ここまで
			//描画モードを格納する。
			pLcdSeqCh.Mode = (ushort)Mode;
		}
		//-----------------------------------------------------------------------------
		public static void LcdSeqCh_SetPri(ST_LcdSeq pLcdSeq, int iLcdSeqCh, int Pri) {
			//チャネルの構造体を取得する。
			ST_LcdSeqCh pLcdSeqCh = LcdSeq_GetLcdSeqCh(pLcdSeq, iLcdSeqCh);
			//引数の優先度を検査する。
			if((Pri < short.MinValue) || (Pri > short.MaxValue)) { throw new ApplicationException(); }	//優先度が不正。おそらくアプリケーションのバグです。
			//停止中ならば格納しない。
			if(pLcdSeqCh.SprNo == 0) { return; }	//ここまで
			//優先度を格納する。
			pLcdSeqCh.Pri = (short)Pri;
		}
		//-----------------------------------------------------------------------------
//{{2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
//#if     !UNITY_5_3_OR_NEWER
//}}2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
		public static void LcdSeqCh_SetPos(ST_LcdSeq pLcdSeq, int iLcdSeqCh, int PosX, int PosY) {
//{{2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
//#else //!UNITY_5_3_OR_NEWER
//		public static void LcdSeqCh_SetPos(ST_LcdSeq pLcdSeq, int iLcdSeqCh, float PosX, float PosY) {
//#endif//!UNITY_5_3_OR_NEWER
//}}2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
			//チャネルの構造体を取得する。
			ST_LcdSeqCh pLcdSeqCh = LcdSeq_GetLcdSeqCh(pLcdSeq, iLcdSeqCh);
//{{2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
//#if     !UNITY_5_3_OR_NEWER
//}}2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
			//引数の座標を検査する。
			if(((PosX < short.MinValue) || (PosX > short.MaxValue)) ||
			   ((PosY < short.MinValue) || (PosY > short.MaxValue))) { throw new ApplicationException(); }	//座標が不正。おそらくアプリケーションのバグです。
//{{2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
//#endif//!UNITY_5_3_OR_NEWER
//}}2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
			//停止中ならば格納しない。
			if(pLcdSeqCh.SprNo == 0) { return; }	//ここまで
			//座標を格納する。
//{{2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
//#if     !UNITY_5_3_OR_NEWER
//}}2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
			pLcdSeqCh.PosX = (short)PosX;
			pLcdSeqCh.PosY = (short)PosY;
//{{2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
//#else //!UNITY_5_3_OR_NEWER
//			pLcdSeqCh.PosX = PosX;
//			pLcdSeqCh.PosY = PosY;
//#endif//!UNITY_5_3_OR_NEWER
//}}2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
		}
		//-----------------------------------------------------------------------------
//{{2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
//#if     !UNITY_5_3_OR_NEWER
//}}2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
		public static void LcdSeqCh_SetColor(ST_LcdSeq pLcdSeq, int iLcdSeqCh, int Color) {
//{{2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
//#else //!UNITY_5_3_OR_NEWER
//		public static void LcdSeqCh_SetColor(ST_LcdSeq pLcdSeq, int iLcdSeqCh, UnityEngine.Color Color) {
//#endif//!UNITY_5_3_OR_NEWER
//}}2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
			//チャネルの構造体を取得する。
			ST_LcdSeqCh pLcdSeqCh = LcdSeq_GetLcdSeqCh(pLcdSeq, iLcdSeqCh);
			//停止中ならば格納しない。
			if(pLcdSeqCh.SprNo == 0) { return; }	//ここまで
			//カラーを格納する。
			pLcdSeqCh.Color = Color;
		}
		//-----------------------------------------------------------------------------
		public static void LcdSeqCh_SetSprNo(ST_LcdSeq pLcdSeq, int iLcdSeqCh, int SprNo/*0可*/) {
			//引数のスプライト番号が0以外ならば…
			if(SprNo != 0) {
				//チャネルの構造体を取得する。
				ST_LcdSeqCh pLcdSeqCh = LcdSeq_GetLcdSeqCh(pLcdSeq, iLcdSeqCh);
				//引数のスプライト番号を検査する。
				if((SprNo < 1) || (SprNo > pLcdSeq.pLcdSeqInfo._SprNo_Max)) { throw new ApplicationException(); }	//スプライト番号が不正。おそらくアプリケーションのバグです。
				//停止中ならば格納しない。
				if(pLcdSeqCh.SprNo == 0) { return; }	//ここまで
				//スプライト番号を格納する。
				pLcdSeqCh.SprNo = (ushort)SprNo;
			//引数のスプライト番号が0ならば…
			} else {
				//LcdSeqCh_Stop()を呼び出すのと同じ意味となります。
				LcdSeqCh_Stop(pLcdSeq, iLcdSeqCh);
			}
		}
		//-----------------------------------------------------------------------------
		public static int LcdSeqCh_GetCnt(ST_LcdSeq pLcdSeq, int iLcdSeqCh) {
			//チャネルの構造体を取得する。
			ST_LcdSeqCh pLcdSeqCh = LcdSeq_GetLcdSeqCh(pLcdSeq, iLcdSeqCh);
			//再生中ならば描画回数(0～)を返す。停止中ならば-1を返す。
			return (pLcdSeqCh.SprNo != 0) ? pLcdSeqCh.Cnt : -1;
		}
		//-----------------------------------------------------------------------------
		public static void LcdSeq_Stop(ST_LcdSeq pLcdSeq) {
			int iLcdSeqCh;
			//各チャネルについて…
			for(iLcdSeqCh = 0; iLcdSeqCh < pLcdSeq.pLcdSeqInfo.nLcdSeqCh; iLcdSeqCh++) {
				//チャネルを停止する。
				LcdSeqCh_Stop(pLcdSeq, iLcdSeqCh);
			}
		}
		//-----------------------------------------------------------------------------
		public static void LcdSeqCh_Stop(ST_LcdSeq pLcdSeq, int iLcdSeqCh) {
			//チャネルの構造体を取得する。
			ST_LcdSeqCh pLcdSeqCh = LcdSeq_GetLcdSeqCh(pLcdSeq, iLcdSeqCh);
			//チャネルの構造体をクリアする。
			pLcdSeqCh.Cnt		= 0;				//描画回数		0～USHRT_MAX(飽和)
			pLcdSeqCh.SprNo		= 0;				//スプライト番号	0(非表示),1～SprNo_Max
			pLcdSeqCh.Mode		= 0;				//描画モード		DX_BLENDMODE_*		DxLibを使用しない場合はアプリケーション定義の任意の値です。
			pLcdSeqCh.Pri		= 0;				//優先度		SHRT_MIN～SHRT_MAX
//{{2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
//#if     !UNITY_5_3_OR_NEWER
//}}2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
			pLcdSeqCh.PosX		= 0;				//座標X			SHRT_MIN～SHRT_MAX
			pLcdSeqCh.PosY		= 0;				//座標Y			SHRT_MIN～SHRT_MAX
			pLcdSeqCh.Color		= 0;				//カラー		D3DRGBA(r,g,b,a)
//{{2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
//#else //!UNITY_5_3_OR_NEWER
//			pLcdSeqCh.PosX		= 0;				//座標X			FLT_MIN～FLT_MAX
//			pLcdSeqCh.PosY		= 0;				//座標Y			FLT_MIN～FLT_MAX
//			pLcdSeqCh.Color		= default(UnityEngine.Color);	//カラー		Color(r,g,b,a),又は,Color32(r,g,b,a)
//#endif//!UNITY_5_3_OR_NEWER
//}}2017/03/21削除:Tue Mar 21 21:23:37 JST 2017 Naoyuki Sawa
		}
		//-----------------------------------------------------------------------------
		//指定されたチャネル番号の初期化情報へのポインタを取得する。
		public static ST_LcdSeqChInfo LcdSeq_GetLcdSeqChInfo(ST_LcdSeq pLcdSeq, int iLcdSeqCh) {
			//引数のチャネル番号を検査する。
			if((uint)iLcdSeqCh >= (uint)pLcdSeq.pLcdSeqInfo.nLcdSeqCh) { throw new ApplicationException(); }	//チャネル番号が不正。おそらくアプリケーションのバグです。
			//初期化情報へのポインタを返す。
			return pLcdSeq.pLcdSeqInfo.TBL_LcdSeqChInfo[iLcdSeqCh];
		}
		//-----------------------------------------------------------------------------
		//指定されたチャネル番号の構造体へのポインタを取得する。
		public static ST_LcdSeqCh LcdSeq_GetLcdSeqCh(ST_LcdSeq pLcdSeq, int iLcdSeqCh) {
			//引数のチャネル番号を検査する。
			if((uint)iLcdSeqCh >= (uint)pLcdSeq.pLcdSeqInfo.nLcdSeqCh) { throw new ApplicationException(); }	//チャネル番号が不正。おそらくアプリケーションのバグです。
			//チャネルの構造体へのポインタを返す。
			return pLcdSeq.TBL_LcdSeqCh[iLcdSeqCh];
		}
	}
}
