//
//	clipgrp_uni.cs
//
//	アプリケーションのグラフィック関数
//
//	CLiP - Common Library for P/ECE
//	Copyright (C) 2017 Naoyuki Sawa
//
//	* Mon Mar 27 22:39:32 JST 2017 Naoyuki Sawa
//	- 1st リリース。
//	  まだアプリケーションとライブラリの分離が不完全で、当モジュール内にアプリケーション依存の定数やグローバル変数への参照が残っています。
//	  そのため、現在はまだ、当モジュールを直接アプリケーションに含めて、ビルドしています。
//	  引き続き、アプリケーションとライブラリの分離を行って行きます。(※TODO:)
//	* Wed Mar 29 16:08:13 JST 2017 Naoyuki Sawa
//	- draw_spr()において、UnityのSpriteのPivotを相殺する処理が、縦軸に関して間違っていたのを修正しました。
//	* Thu Mar 30 22:26:51 JST 2017 Naoyuki Sawa
//	- 一旦、当モジュールはライブラリから除外しました。
//	  あまりにもアプリケーション依存の部分が多過ぎて、ライブラリに含めたままでは変更が行い辛い問題が生じたからです。
//	  当面は、当モジュールはアプリケーションに含めて変更を進め、いずれ、アプリケーション依存部分と非依存部分の切り分けが出来たら、あらためて非依存部分だけをライブラリに取り込もうと思います。
//	* Thu Mar 30 23:36:41 JST 2017 Naoyuki Sawa
//	- CbkQue_prep_spr()を廃止し、prep_spr()を直接呼び出せるようにしました。
//	  これまで、prep_spr()の内部で使用している処理の中に、サブスレッドからは呼び出せないUnityの処理が含まれていると思って、アプリケーションからはCbkQue_prep_spr()を経由しないとprep_spr()を呼び出せないようにしていました。
//	  しかし、実験してみた所、prep_spr()の内部で使用している処理は、全てSofdecの処理だけでUnityの処理は呼び出していなかったようで、サブスレッドからprep_spr()を呼び出しても問題無く動作しました。
//	  アプリケーションの観点からも、prep_spr()を直接呼び出せる方が都合が良いので、CbkQue_prep_spr()を廃止し、prep_spr()を直接呼び出せるようにしました。
//	  変更前は、prep_spr()は戻り値が無かった(CbkQue_prep_spr()経由では戻り値が返せないから)のですが、変更後は戻り値が返せるようになったので、C言語版と同様に、準備完了かどうかを戻り値で返すようにしました。
//	* Fri Mar 31 21:21:33 JST 2017 Naoyuki Sawa
//	- テクスチャの自動スケーリングを追加しました。
//	  おおよそ、/clip/DxlibHelper.cppの自動スケーリングの機能と同じです。
//	  ただし、/clip/DxlibHelper.cppの自動スケーリングの機能は、テクスチャファイル名から判断していましたが、当モジュールでは、レジストリから自動スケーリングの拡大率を取得するようにしました。
//	  2017/03/26に、/clip/tool/dTexDefC/に、テクスチャに汎用の属性リストを追加した事によって、任意の情報がテクスチャ定義に追加出来るようになったからです。
//	  テクスチャファイル名から判断するよりも自然だし、効率も良いと思います。
//	  いずれ、/clip/DxlibHelper.cppも、当モジュールと同様に、レジストリから自動スケーリングの拡大率を取得するように変更する予定です。	⇒{{2017/04/01コメント追記:/clip/DxlibHelper.cppに、左記の変更を適用しました。}}
//	* Tue Apr 04 23:33:32 JST 2017 Naoyuki Sawa
//	- スプライトフォント描画に回転機能を追加しました。
//	* Sun Apr 09 22:05:18 JST 2017 Naoyuki Sawa
//	- Unity 5.6.0ではLineRenderer.numPositionsがobsoleteになり、positionCountに変わった事に対応しました。
//	  numPositionsのままでもビルドは出来ますが、以下のような警告が出ます。
//	  ＞warning CS0618: `UnityEngine.LineRenderer.numPositions' is obsolete: `Use positionCount property (UnityUpgradable) -> positionCount'
//	* Mon Apr 10 21:37:40 JST 2017 Naoyuki Sawa
//	- 「スプライト描画(フォールバック有り)」を削除し、既存の「スプライト描画(フォールバック無し)」を単純に「スプライト描画」としました。
//	  「スプライト描画(フォールバック有り)」を作成した頃は、まだprep_spr()に戻り値が無かったので、アプリケーションが準備完了かどうかを知らなくても処理出来るように「スプライト描画(フォールバック有り)」を用意したのですが、
//	  もうprep_spr()に戻り値を返すようになったので、アプリケーションが明示的に準備完了かどうかを判定して描画方法を変えられるようになったので、「スプライト描画(フォールバック有り)」が無くても大丈夫になったからです。
//	  「スプライト描画(フォールバック有り)」を残しておいても構わなかったのですが、実際に少しアプリケーションから使ってみた所、かなり使い辛かったので、判り易さのために削除する方が良いと思い、削除しました。
//	* Tue Apr 11 21:34:28 JST 2017 Naoyuki Sawa
//	- 各描画関数のalpha引数を、rgba引数に変更しました。
//	  元々/clip/DxlibHelper.cppの描画関数はrgba引数だったのですが、当モジュールへ(アレンジしながら)移植する際に、簡単のためにalpha引数に変更していました。
//	  やっぱり/clip/DxlibHelper.cppの描画関数と同様に、rgba引数にする事にしました。
//	* Wed Apr 12 22:29:29 JST 2017 Naoyuki Sawa
//	- CbkQue_draw_box()を追加しました。
//	  C言語版のCbkQue_draw_box()ではなく、CbkQue_draw_box_fill()に相当します。
//	  Unityでゲームを作る時に矩形の枠だけを描画する事は無さそうなので、C言語版のCbkQue_draw_box()に相当する関数は作成せず、塗り潰す関数の名前を単純化してCbkQue_draw_box()としました。
//	- draw_spr()にて、ムービーのカラーブレンディングも対応しました。
//	  この機能を使うためには、シェーダの変更も必要です。
//	  具体的には、/clip/libclip.net/keep/Program/README.TXTの、同日のコメントを参照して下さい。
//	* Fri Apr 21 21:38:57 JST 2017 Naoyuki Sawa
//	- CbkQue_draw_polygon()を追加しました。
//	  C言語版のCbkQue_draw_polygon()ではなく、CbkQue_draw_polygon_fill()に相当します。
//	  Unityでゲームを作る時に多角形の枠だけを描画する事は無さそうなので、C言語版のCbkQue_draw_polygon()に相当する関数は作成せず、塗り潰す関数の名前を単純化してCbkQue_draw_polygon()としました。
//	- C言語版のCbkQue_draw_polygon_fill()は凹多角形も描画出来ますが、Unity版のCbkQue_draw_polygon()は凸多角形しか描画出来ません。
//	  Unityでゲームを作る時に、動的に凹多角形を描く事はまず無いと思うからです。
//	  元々、C言語版のCbkQue_draw_polygon_fill()で凹多角形に対応していた理由は、凹多角形の分割処理(vec2i_split_polygon_into_triangles())の検証のためだけで、実際にゲームで使う事はほとんど有りませんでした。
//	* Fri Apr 21 22:01:07 JST 2017 Naoyuki Sawa
//	- StableAspect()を追加しました。
//
#if     UNITY_5_3_OR_NEWER
using System;
using System.IO;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using UnityEngine.SceneManagement;
using static org.piece_me.libclip;
using static Const;
public static partial class Program {
	//*****************************************************************************
	//	ローカル変数
	//*****************************************************************************
	private static class Graph {
		public static GameObject			goRoot;			//表示オブジェクトのルートGameObject
		public static int				layer;			//オブジェクトプールから次に取得するオブジェクトに設定するレイヤー	Reset()で戻す。CbkQue_SetLayer()で設定する。
		public static int				sortingOrder;		//オブジェクトプールから次に取得するオブジェクトに設定するオーダー順	Reset()で戻す。CbkQue_SetSortingOrder()で明示的に設定する。ObjectPool<T>.GetObject()で自動的に進む。
		//-----------------------------------------------------------------------------
		public static ObjectPool<MovieObject>		movieObjectPool		= new ObjectPool<MovieObject>();	//Movieオブジェクトプール
		public static ObjectPool<SpriteObject>		spriteObjectPool	= new ObjectPool<SpriteObject>();	//Spriteオブジェクトプール
		public static ObjectPool<LineObject>		lineObjectPool		= new ObjectPool<LineObject>();		//Lineオブジェクトプール
		public static ObjectPool<BoxObject>		boxObjectPool		= new ObjectPool<BoxObject>();		//Boxオブジェクトプール
		public static ObjectPool<PolygonObject>		polygonObjectPool	= new ObjectPool<PolygonObject>();	//Polygonオブジェクトプール
		//-----------------------------------------------------------------------------
		public static Dictionary<int,ST_TexDef>		texDefCache		= new Dictionary<int,ST_TexDef>();	//取得済みのテクスチャ定義キャッシュ
		public static Dictionary<int,ST_SprDef>		sprDefCache		= new Dictionary<int,ST_SprDef>();	//取得済みのスプライト定義キャッシュ
		public static Dictionary<int,Sprite>		spriteCache		= new Dictionary<int,Sprite>();		//ロード済みのスプライトキャッシュ
		//-----------------------------------------------------------------------------
		public static ST_MovieHelper			pMovieHelper;
	}
	//*****************************************************************************
	//	オブジェクトプール
	//*****************************************************************************
	private class ObjectPool<T> where T : PoolObject, new() {
		public List<T>		TBL_PoolObject	= new List<T>();	//作成した全てのオブジェクト
		public int		Count;					//オブジェクトを取り出した数
		//-----------------------------------------------------------------------------
		//オブジェクトを取得する。
		public T GetObject() {
			//プールが空ならば…
			if(Count == TBL_PoolObject.Count) {
				//オブジェクトを作成して、プールに追加する。
				TBL_PoolObject.Add(new T());
			}
			//プールから、オブジェクトを取得する。
			T po = TBL_PoolObject[Count++];
			//オブジェクトを有効にする。
			po.SetActive(true);
			//オブジェクトのレイヤを設定する。
			po.SetLayer(Graph.layer);
			//レンダラーのオーダー順を設定する。
			po.SetSortingOrder(Graph.sortingOrder++);
			//オブジェクトを返す。
			return po;
		}
		//-----------------------------------------------------------------------------
		//プールをリセットする。
		public void Reset() {
			//取り出された各オブジェクトについて…
			while(Count != 0) {
				//オブジェクトを無効に戻す。
				T po = TBL_PoolObject[--Count];
				po.SetActive(false);
			}
		}
	}
	//*****************************************************************************
	//	プールオブジェクトの基底クラス
	//*****************************************************************************
	private abstract class PoolObject {
		public GameObject		goOuter;		//外側のオブジェクト
		public GameObject		goInner;		//内側のオブジェクト
		public abstract Renderer	renderer { get; }	//内側のオブジェクトのレンダラー
		//-----------------------------------------------------------------------------
		protected PoolObject() {
			//外側のGameObjectを作成する。
			goOuter = new GameObject();
			goOuter.transform.SetParent(Graph.goRoot.transform, false);
		}
		//-----------------------------------------------------------------------------
		public void SetActive(bool value) {
			//外側のオブジェクトを有効,又は,無効にする。
			goOuter.SetActive(value);
		}
		//-----------------------------------------------------------------------------
		public void SetLayer(int layer) {
			//内側のオブジェクトのレイヤを設定する。
			goInner.layer = layer;
		}
		//-----------------------------------------------------------------------------
		public void SetSortingOrder(int sortingOrder) {
			//レンダラーのオーダー順を設定する。
			renderer.sortingOrder = sortingOrder;
		}
	}
	//*****************************************************************************
	//	Movieオブジェクト
	//*****************************************************************************
	private class MovieObject : PoolObject {
		public MeshRenderer	meshRenderer;		//内側のオブジェクトのMeshRenderer
//{{2017/04/12追加:draw_spr()にて、ムービーのカラーブレンディングも対応しました。
		public MeshFilter	meshFilter;		//内側のオブジェクトのMeshFilter
//}}2017/04/12追加:draw_spr()にて、ムービーのカラーブレンディングも対応しました。
		//-----------------------------------------------------------------------------
		public MovieObject() {
			//内側のGameObjectを作成する。
			goInner = GameObject.CreatePrimitive(PrimitiveType.Quad);
			goInner.transform.SetParent(goOuter.transform, false);
			//MeshRendererを取得しておく。
			meshRenderer = goInner.GetComponent<MeshRenderer>();
			if(meshRenderer == null) { throw new ApplicationException(); }
//{{2017/04/12追加:draw_spr()にて、ムービーのカラーブレンディングも対応しました。
			//MeshFilterを取得しておく。
			meshFilter = goInner.GetComponent<MeshFilter>();
			if(meshFilter == null) { throw new ApplicationException(); }
//}}2017/04/12追加:draw_spr()にて、ムービーのカラーブレンディングも対応しました。
		}
		//-----------------------------------------------------------------------------
		//PoolObject
		public override Renderer renderer {
			get {
				//内側のオブジェクトのレンダラーを返す。
				return meshRenderer;
			}
		}
	}
	//*****************************************************************************
	//	Spriteオブジェクト
	//*****************************************************************************
	private class SpriteObject : PoolObject {
		public SpriteRenderer	spriteRenderer;		//内側のオブジェクトのSpriteRenderer
		//-----------------------------------------------------------------------------
		public SpriteObject() {
			//内側のGameObjectを作成する。
			goInner = new GameObject(null, typeof(SpriteRenderer));
			goInner.transform.SetParent(goOuter.transform, false);
			//SpriteRendererを取得しておく。
			spriteRenderer = goInner.GetComponent<SpriteRenderer>();
			if(spriteRenderer == null) { throw new ApplicationException(); }
		}
		//-----------------------------------------------------------------------------
		//PoolObject
		public override Renderer renderer {
			get {
				//内側のオブジェクトのレンダラーを返す。
				return spriteRenderer;
			}
		}
	}
	//*****************************************************************************
	//	Lineオブジェクト
	//*****************************************************************************
	private class LineObject : PoolObject {
		public LineRenderer	lineRenderer;		//内側のオブジェクトのLineRenderer
		public Material		material;		//内側のオブジェクトのLineRendererのMaterial
		//-----------------------------------------------------------------------------
		public LineObject() {
			//内側のGameObjectを作成する。
			goInner = new GameObject();
			goInner.transform.SetParent(goOuter.transform, false);
			goInner.transform.localPosition = new Vector2(	//位置は固定。
				(float)(-(DISP_X / 2) / PPU),
				(float)( (DISP_Y / 2) / PPU));
			goInner.transform.localScale = new Vector2(	//スケールも固定。ただし、goInner.transform.localScaleはlineRenderer.startWidth,endWidthには影響しないようなので、lineRenderer.startWidth,endWidthにもスケールを掛ける必要が有ります。
				(float)( 1.0 / PPU),
				(float)(-1.0 / PPU));
			//LineRendererを作成する。
			lineRenderer = goInner.AddComponent<LineRenderer>();
			lineRenderer.useWorldSpace = false;	//必要です!!
			//Materialを作成する。
			material = new Material(Shader.Find("Sprites/Default"));	//※要検討。深度バッファを無視して背面消去もしないシェーダなら何でも良い。	【注意】シーンでこのシェーダが参照されない場合は、ProjectSettings/Graphicsで"Always Included Shaders"リストに含めておく必要が有ります。現在の所、シーンでこのシェーダが参照しているので、左記の設定は必要有りません。
			if(material == null) { throw new ApplicationException(); }
			lineRenderer.material = material;
		}
		//-----------------------------------------------------------------------------
		//PoolObject
		public override Renderer renderer {
			get {
				//内側のオブジェクトのレンダラーを返す。
				return lineRenderer;
			}
		}
	}
	//*****************************************************************************
	//	Boxオブジェクト
	//*****************************************************************************
	private class BoxObject : PoolObject {
		public MeshRenderer	meshRenderer;		//内側のオブジェクトのMeshRenderer
		public Material		material;		//内側のオブジェクトのMeshRendererのMaterial
		//-----------------------------------------------------------------------------
		public BoxObject() {
			//内側のGameObjectを作成する。
			goInner = GameObject.CreatePrimitive(PrimitiveType.Quad);
			goInner.transform.SetParent(goOuter.transform, false);
			//内側のGameObjectのQuadが(0,0)-(1,1)になるようにしておく。
			goInner.transform.localPosition = new Vector2(
				(float)( 0.5 / PPU),
				(float)(-0.5 / PPU));
			goInner.transform.localScale = new Vector2(
				(float)( 1.0 / PPU),
				(float)( 1.0 / PPU));
			//MeshRendererを取得しておく。
			meshRenderer = goInner.GetComponent<MeshRenderer>();
			if(meshRenderer == null) { throw new ApplicationException(); }
			//Materialを作成する。
			material = new Material(Shader.Find("Sprites/Default"));
			if(material == null) { throw new ApplicationException(); }
			meshRenderer.material = material;
		}
		//-----------------------------------------------------------------------------
		//PoolObject
		public override Renderer renderer {
			get {
				//内側のオブジェクトのレンダラーを返す。
				return meshRenderer;
			}
		}
	}
	//*****************************************************************************
	//	Polygonオブジェクト
	//*****************************************************************************
	private class PolygonObject : PoolObject {
		public MeshRenderer	meshRenderer;		//内側のオブジェクトのMeshRenderer
		public Material		material;		//内側のオブジェクトのMeshRendererのMaterial
		public MeshFilter	meshFilter;		//内側のオブジェクトのMeshFilter
		public Mesh		mesh;			//内側のオブジェクトのMeshFilterのMesh
		//-----------------------------------------------------------------------------
		public PolygonObject() {
			//内側のGameObjectを作成する。
			goInner = new GameObject();
			goInner.transform.SetParent(goOuter.transform, false);
			goInner.transform.localPosition = new Vector2(	//位置は固定。
				(float)(-(DISP_X / 2) / PPU),
				(float)( (DISP_Y / 2) / PPU));
			goInner.transform.localScale = new Vector2(	//スケールも固定。
				(float)( 1.0 / PPU),
				(float)(-1.0 / PPU));
			//MeshRendererを作成する。
			meshRenderer = goInner.AddComponent<MeshRenderer>();
			//Materialを作成する。
			material = new Material(Shader.Find("Sprites/Default"));	//※要検討。深度バッファを無視して背面消去もしないシェーダなら何でも良い。	【注意】シーンでこのシェーダが参照されない場合は、ProjectSettings/Graphicsで"Always Included Shaders"リストに含めておく必要が有ります。現在の所、シーンでこのシェーダが参照しているので、左記の設定は必要有りません。
			if(material == null) { throw new ApplicationException(); }
			meshRenderer.material = material;
			//MeshFilterを作成する。
			meshFilter = goInner.AddComponent<MeshFilter>();
			//Meshを作成する。
			mesh = new Mesh();
			meshFilter.mesh = mesh;
		}
		//-----------------------------------------------------------------------------
		//PoolObject
		public override Renderer renderer {
			get {
				//内側のオブジェクトのレンダラーを返す。
				return meshRenderer;
			}
		}
	}
	//*****************************************************************************
	//	テクスチャ定義
	//*****************************************************************************
	public class ST_TexDef {
		public string		sPath;			//パス			スプライトの場合はリソースパス、ムービーの場合はファイルパス
		public bool		bLoop;			//ループフラグ		ムービーの場合のみ
		public bool		bAdditive;		//加算モード
//{{2017/03/31追加:テクスチャの自動スケーリングを追加しました。
		public int		nScale;			//拡大率
//}}2017/03/31追加:テクスチャの自動スケーリングを追加しました。
		//-----------------------------------------------------------------------------
		public bool	isSprite{
			get {
				return string.IsNullOrEmpty(Path.GetExtension(sPath));	//※仮:パスに拡張子が無ければ、リソースパスであると判断して、スプライトと見なす事にした。
			}
		}
		//-----------------------------------------------------------------------------
		public bool	isMovie {
			get {
				return !isSprite;					//※仮:スプライトでなければ、ムービーと見なす事にした。
			}
		}
	}
	//*****************************************************************************
	//	スプライト定義
	//*****************************************************************************
	public class ST_SprDef {
		public int		iTexNo;			//テクスチャ番号
		public int		x, y;			//左上座標
		public int		w, h;			//幅、高さ
		public int		cx, cy;			//原点オフセット
		//-----------------------------------------------------------------------------
		public bool	isSprite{
			get {
				return GetTexDef(iTexNo).isSprite;
			}
		}
		//-----------------------------------------------------------------------------
		public bool	isMovie {
			get {
				return GetTexDef(iTexNo).isMovie;
			}
		}
	}
	//*****************************************************************************
	//	Movieプレイヤーの実装
	//*****************************************************************************
	public class MoviePlayer : IMoviePlayer {
		public CriManaMovieMaterial	criManaMovieMaterial;	//ムービーマテリアル
		//-----------------------------------------------------------------------------
		public MoviePlayer() {
			//ムービーマテリアルを作成する。
			criManaMovieMaterial = Graph.goRoot.AddComponent<CriManaMovieMaterial>();
		}
		//-----------------------------------------------------------------------------
		void IDisposable.Dispose() {
			//ムービーマテリアルを削除する。
			UnityEngine.Object.Destroy(criManaMovieMaterial);
		}
		//-----------------------------------------------------------------------------
		MoviePlayerStatus IMoviePlayer.GetStatus() {
			//プレイヤーの状態を取得する。
			return (MoviePlayerStatus)criManaMovieMaterial.player.status;
		}
		//-----------------------------------------------------------------------------
		void IMoviePlayer.Prepare(int iTexNo) {
			//テクスチャ番号を検査する。
			if((iTexNo < 1) || (iTexNo > TexNo_Max)) { throw new ApplicationException(); }
			//テクスチャ定義を取得する。
			ST_TexDef stTexDef = GetTexDef(iTexNo);
			//テクスチャのファイルパス,ループ設定,加算合成モード設定を設定する。
			if(!criManaMovieMaterial.player.SetFile(binder, stTexDef.sPath)) { throw new ApplicationException(); }
			criManaMovieMaterial.player.Loop(stTexDef.bLoop);
			criManaMovieMaterial.player.additiveMode = stTexDef.bAdditive;
			//再生準備を開始する。
			criManaMovieMaterial.player.Prepare();
		}
		//-----------------------------------------------------------------------------
		void IMoviePlayer.Start() {
			//再生を開始する。
			criManaMovieMaterial.player.Start();
			//マテリアルが有効になるまで待つ。
			for(;;) {
				if(criManaMovieMaterial.player.status == CriMana.Player.Status.Error) { throw new ApplicationException(); }
				if(criManaMovieMaterial.isMaterialAvailable) { break; }
				typeof(CriManaMovieMaterial).InvokeMember("Update", BindingFlags.InvokeMethod|BindingFlags.NonPublic, null, criManaMovieMaterial, null);	//CriManaMovieMaterial.Update()を呼び出すために左記の処理が必要です。criManaMovieMaterial.player.Update()ではマテリアルが更新されないのでダメです(Unityが落ちたりします)。
			}
		}
		//-----------------------------------------------------------------------------
		void IMoviePlayer.Stop() {
			//再生,又は,再生準備を停止する。
			criManaMovieMaterial.Stop();
			//プレイヤーの状態が停止中になるまで待つ。
			for(;;) {
				CriMana.Player.Status status = criManaMovieMaterial.player.status;
				if(status == CriMana.Player.Status.Error) { throw new ApplicationException(); }
				if(status == CriMana.Player.Status.Stop) { break; }
				typeof(CriManaMovieMaterial).InvokeMember("Update", BindingFlags.InvokeMethod|BindingFlags.NonPublic, null, criManaMovieMaterial, null);	//CriManaMovieMaterial.Update()を呼び出すために左記の処理が必要です。criManaMovieMaterial.player.Update()ではマテリアルが更新されないのでダメです(Unityが落ちたりします)。
			}
		}
	}
	//*****************************************************************************
	//	グローバル関数
	//*****************************************************************************
	//グラフィックの初期化処理
	public static void Graph_Init() {
		//ルートGameObjectを作成する。
		Graph.goRoot = new GameObject();
	//{{任意:普段はUnityエディタ上で確認する必要が無いと思うので非表示にしておく事にした。Unityエディタ上で確認する場合はこの範囲をコメントアウトして下さい。
		Graph.goRoot.hideFlags = HideFlags.HideInHierarchy;
	//}}任意:普段はUnityエディタ上で確認する必要が無いと思うので非表示にしておく事にした。Unityエディタ上で確認する場合はこの範囲をコメントアウトして下さい。
		//新しいシーンを読み込んでもこのオブジェクトが自動で破壊されないように設定する。
		// - LoadScene()の後にそのフレーム内でGameObjectを作成した場合、DontDestroyOnLoad()を呼んでいなければそのGameObjectも削除されるようだ。
		//   LoadScene()関数の中でシーンが移行するのでなく、そのフレームの最後にシーンが移行しているのかも知れない。(※未検証)
		//   安全のためには、LoadScene()を行ったフレームでは、他の処理は何も行わない方が良さそうだ。
		//   ここでDontDestroyOnLoad()を呼び出す目的は、上記の問題を回避するためではないのだが、結果的に問題を回避出来ている。
		// - ルートGameObjectに対してDontDestroyOnLoad()を呼び出しておけば、その全トランスフォーム階層も破壊されない。
		//   従って、この後で作成してルートGameObjectの子にする個々のGameObjectに対しては、DontDestroyOnLoad()を呼び出す必要は無い。
		UnityEngine.Object.DontDestroyOnLoad(Graph.goRoot);
		//ムービー管理の初期化を実行する。
		int nCh = criWareInitializer.manaConfig.numberOfDecoders / 2;	//全てのムービーマテリアルでアルファムービーを再生してもデコーダが足りるように、デコーダの半分の数とする事にした。
		Graph.pMovieHelper = MovieHelper_New(nCh, delegate(object arg) { return new MoviePlayer(); }, null);
	}
	//-----------------------------------------------------------------------------
	//グラフィックの周期処理
	public static void Graph_Exec() {
		//オブジェクトプールをリセットする。
		Graph.layer = 0/*Default*/;		//オブジェクトプールから次に取得するオブジェクトに設定するレイヤーをDefaultに戻す。
		Graph.sortingOrder = short.MinValue;	//オブジェクトプールから次に取得するオブジェクトに設定するオーダー順を最小値に戻す。
		Graph.movieObjectPool.Reset();		//Movieオブジェクトプールから取り出したオブジェクトを無効にしてプールに返す。
		Graph.spriteObjectPool.Reset();		//Spriteオブジェクトプールから取り出したオブジェクトを無効にしてプールに返す。
		Graph.lineObjectPool.Reset();		//Lineオブジェクトプールから取り出したオブジェクトを無効にしてプールに返す。
		Graph.boxObjectPool.Reset();		//Boxオブジェクトプールから取り出したオブジェクトを無効にしてプールに返す。
		Graph.polygonObjectPool.Reset();	//Polygonオブジェクトプールから取り出したオブジェクトを無効にしてプールに返す。
		//ムービー管理の周期処理を実行する。
		MovieHelper_Exec(Graph.pMovieHelper);
	}
	//-----------------------------------------------------------------------------
	//グラフィックの終了処理
	public static void Graph_Exit() {
		//ムービー管理の終了処理を実行する。
		MovieHelper_Exit(Graph.pMovieHelper);
		//ルートGameObjectを削除する。
		UnityEngine.Object.Destroy(Graph.goRoot);
	}
	//-----------------------------------------------------------------------------
	//画面のアスペクト比を固定にする。
	// - GameControllerオブジェクトのUpdate()の先頭で呼び出して下さい。
	//   □参考資料:「Unity2Dで画面のアスペクト比を固定にしたい【Unity】」(http://qiita.com/kwst/items/371542a6d3892b577b41)
	public static void StableAspect() {
		//メインカメラが無ければ何もしない。
		Camera camera = Camera.main;
		if(camera == null) { return; }	//ここまで。
		//カメラの垂直サイズの視野量の半分を設定する。
		camera.orthographicSize = (float)((DISP_Y / PPU) / 2.0);
		//画面のアスペクト比を求める。
		double scrAspect = (double)Screen.height / (double)Screen.width;
		//背景のアスペクト比を求める。
		double bgAspect = (double)DISP_Y / (double)DISP_X;
		//背景のアスペクト比が画面のアスペクト比以上ならば、背景を画面の縦幅いっぱいに表示して左右に隙間を作る。
		if(bgAspect >= scrAspect) {
			double camWidth = scrAspect / bgAspect;
			camera.rect = new Rect((float)((1.0 - camWidth) / 2.0), 0, (float)camWidth, 1);
		//背景のアスペクト比が画面のアスペクト比未満ならば、背景を画面の横幅いっぱいに表示して上下に隙間を作る。
		} else {
			double camHeight = bgAspect / scrAspect;
			camera.rect = new Rect(0, (float)((1.0 - camHeight) / 2.0), 1, (float)camHeight);
		}
	}
	//*****************************************************************************
	//	ローカル関数
	//*****************************************************************************
	//ムービーマテリアルを取得する。
	private static CriManaMovieMaterial GetMovieMaterial(int iTexNo) {
		MoviePlayer moviePlayer = (MoviePlayer)MovieHelper_Draw(Graph.pMovieHelper, iTexNo);
		return moviePlayer.criManaMovieMaterial;
	}
	//-----------------------------------------------------------------------------
	//スプライトを取得する。
	private static Sprite GetSprite(int iSprNo) {
		Sprite sprite;
		//スプライト番号を検査する。
		if((iSprNo < 1) || (iSprNo > SprNo_Max)) { throw new ApplicationException(); }
		//指定された番号のスプライトが、まだロードされていなければ…
		if(!Graph.spriteCache.TryGetValue(iSprNo, out sprite)) {
			//スプライト定義を取得する。
			ST_SprDef stSprDef = GetSprDef(iSprNo);
			//テクスチャ定義を取得する。
			ST_TexDef stTexDef = GetTexDef(stSprDef.iTexNo);
			//スプライトをロードする。
			sprite = Resources.Load<Sprite>(stTexDef.sPath);
			if(sprite == null) { throw new ApplicationException(); }
			//スプライトをキャッシュに登録する。
			Graph.spriteCache.Add(iSprNo, sprite);
		}
		//スプライトを返す。
		return sprite;
	}
	//-----------------------------------------------------------------------------
	//スプライト定義を取得する。
	public static ST_SprDef GetSprDef(int iSprNo) {
		ST_SprDef stSprDef;
		//スプライト番号を検査する。
		if((iSprNo < 1) || (iSprNo > SprNo_Max)) { throw new ApplicationException(); }
		//指定された番号のスプライト定義が、まだ取得されていなければ…
		if(!Graph.sprDefCache.TryGetValue(iSprNo, out stSprDef)) {
			//スプライト定義を取得する。
			VoidPtr pSprDef = REG_open_key_l(TBL_RegTbl, RegKey_SprDef, iSprNo);
			if(!pSprDef) { throw new ApplicationException(); }
			stSprDef = new ST_SprDef() {
				iTexNo = REG_get_value(pSprDef, RegKey_TexNo),
				x      = REG_get_value(pSprDef, RegKey_x),
				y      = REG_get_value(pSprDef, RegKey_y),
				w      = REG_get_value(pSprDef, RegKey_w),
				h      = REG_get_value(pSprDef, RegKey_h),
				cx     = REG_get_value(pSprDef, RegKey_cx),
				cy     = REG_get_value(pSprDef, RegKey_cy),
			};
			if((stSprDef.iTexNo == -1) ||
			   (stSprDef.x      == -1) ||
			   (stSprDef.y      == -1) ||
			   (stSprDef.w      == -1) ||
			   (stSprDef.h      == -1) ||
			   (stSprDef.cx     == -1) ||
			   (stSprDef.cy     == -1)) { throw new ApplicationException(); }
			//スプライト定義をキャッシュに登録する。
			Graph.sprDefCache.Add(iSprNo, stSprDef);
		}
		//スプライト定義を返す。
		return stSprDef;
	}
	//-----------------------------------------------------------------------------
	//テクスチャ定義を取得する。
	private static ST_TexDef GetTexDef(int iTexNo) {
		ST_TexDef stTexDef;
		//テクスチャ番号を検査する。
		if((iTexNo < 1) || (iTexNo > TexNo_Max)) { throw new ApplicationException(); }
		//指定された番号のテクスチャ定義が、まだ取得されていなければ…
		if(!Graph.texDefCache.TryGetValue(iTexNo, out stTexDef)) {
			//テクスチャ定義を取得する。
			VoidPtr pTexDef = REG_open_key_l(TBL_RegTbl, RegKey_TexDef, iTexNo);
			if(!pTexDef) { throw new ApplicationException(); }
			string sPath = REG_get_string(pTexDef, RegKey_Path);
			if(sPath == null) { throw new ApplicationException(); }
			bool bLoop = (REG_get_value(pTexDef, RegKey_loop) == 1);		//ループ無しならばレジストリにループフラグは格納されておらず、REG_get_value()の戻り値は(-1)である。ループ有りならばレジストリに'loop=1'が格納されている。従って、REG_get_value()の戻り値が1である場合のみbLoopを1とすれば良い。
			bool bAdditive = (REG_get_value(pTexDef, RegKey_additive) == 1);	//通常モードならばレジストリにモードフラグは格納されておらず、REG_get_value()の戻り値は(-1)である。加算モードならばレジストリに'additive=1'が格納されている。従って、REG_get_value()の戻り値が1である場合のみbAdditiveを1とすれば良い。
//{{2017/03/31追加:テクスチャの自動スケーリングを追加しました。
			int nScale = Math.Abs(REG_get_value(pTexDef, RegKey_scale));		//自動スケーリング無しならばレジストリに拡大率は格納されておらず、REG_get_value()の戻り値は(-1)である。自動スケーリング有りならばレジストリに'scale=0～'が格納されている。従って、REG_get_value()の戻り値が-1ならば1に変換し、0～ならばそのまま拡大率と見なせば良い。明示的に-1か0～かを判断しなくても、常に絶対値を取れば左記の結果が得られる。
//}}2017/03/31追加:テクスチャの自動スケーリングを追加しました。
			stTexDef = new ST_TexDef() {
				sPath = sPath,
				bLoop = bLoop,
				bAdditive = bAdditive,
//{{2017/03/31追加:テクスチャの自動スケーリングを追加しました。
				nScale = nScale,
//}}2017/03/31追加:テクスチャの自動スケーリングを追加しました。
			};
			//テクスチャ定義をキャッシュに登録する。
			Graph.texDefCache.Add(iTexNo, stTexDef);
		}
		//テクスチャ定義を返す。
		return stTexDef;
	}
	//*****************************************************************************
	//	グローバル関数
	//*****************************************************************************
//{{2017/03/30追加:CbkQue_prep_spr()を廃止し、prep_spr()を直接呼び出せるようにしました。
	//スプライト準備
	public static bool prep_spr(int iSprNo) {
		//スプライト定義を取得する。
		ST_SprDef stSprDef = GetSprDef(iSprNo);
		//ムービーならば…
		if(stSprDef.isMovie) {
			//ムービーマテリアルを準備する。準備完了ならばtrue,未完了ならばfalseを返す。
			return MovieHelper_Prepare(Graph.pMovieHelper, stSprDef.iTexNo);
		//スプライトならば…
		} else {
			//スプライトは裏読み未対応なので、常に準備が出来ていると見なしてtrueを返す。
			return true;
		}
	}
//}}2017/03/30追加:CbkQue_prep_spr()を廃止し、prep_spr()を直接呼び出せるようにしました。
	//*****************************************************************************
	//	優先度付き描画
	//*****************************************************************************
	//シーンを切り替える。
	private static void LoadScene(string sceneName) {
		SceneManager.LoadScene(sceneName);
	}
	//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	public static void CbkQue_LoadScene(ST_CbkQue pCbkQue, int pri, string sceneName) {
		CbkQue_Add(pCbkQue, pri, delegate(ST_CbkQue _pCbkQue, int _pri, object param) {
				LoadScene(sceneName);
			}, null);
	}
	//-----------------------------------------------------------------------------
	//オブジェクトプールから次に取得するオブジェクトに設定するレイヤーを設定する。
	private static void SetLayer(int layer) {
		Graph.layer = layer;
	}
	//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	public static void CbkQue_SetLayer(ST_CbkQue pCbkQue, int pri, int layer) {
		CbkQue_Add(pCbkQue, pri, delegate(ST_CbkQue _pCbkQue, int _pri, object param) {
				SetLayer(layer);
			}, null);
	}
	//-----------------------------------------------------------------------------
	//オブジェクトプールから次に取得するオブジェクトに設定するオーダー順を設定する。
	private static void SetSortingOrder(int sortingOrder) {
		Graph.sortingOrder = sortingOrder;
	}
	//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	public static void CbkQue_SetSortingOrder(ST_CbkQue pCbkQue, int pri, int sortingOrder) {
		CbkQue_Add(pCbkQue, pri, delegate(ST_CbkQue _pCbkQue, int _pri, object param) {
				SetSortingOrder(sortingOrder);
			}, null);
	}
	//-----------------------------------------------------------------------------
//{{2017/03/30削除:CbkQue_prep_spr()を廃止し、prep_spr()を直接呼び出せるようにしました。
//	//スプライト準備
//	private static void prep_spr(int iSprNo) {
//		//スプライト定義を取得する。
//		ST_SprDef stSprDef = GetSprDef(iSprNo);
//		//ムービーならば…
//		if(stSprDef.isMovie) {
//			//ムービーマテリアルを準備する。
//			MovieHelper_Prepare(Graph.pMovieHelper, stSprDef.iTexNo);
//		//スプライトならば…
//		} else {
//			//スプライトは裏読み未対応です。
//			/** no job **/
//		}
//	}
//	//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//	public static void CbkQue_prep_spr(ST_CbkQue pCbkQue, int pri, int iSprNo) {
//		CbkQue_Add(pCbkQue, pri, delegate(ST_CbkQue _pCbkQue, int _pri, object param) {
//				prep_spr(iSprNo);
//			}, null);
//	}
//}}2017/03/30削除:CbkQue_prep_spr()を廃止し、prep_spr()を直接呼び出せるようにしました。
	//-----------------------------------------------------------------------------
//{{2017/04/10削除:「スプライト描画(フォールバック有り)」を削除し、既存の「スプライト描画(フォールバック無し)」を単純に「スプライト描画」としました。
//	//スプライト描画(フォールバック有り)
//	private static void draw_spr(double x, double y, int[] aSprNo, double scale_x, double scale_y, double rot, double alpha) {
//		//各候補について…
//		for(int i = 0; i < aSprNo.Length; i++) {	//┬この下の処理で、最終候補かを判定する必要が有るので、foreachではなくforを使ってループする。
//			int iSprNo = aSprNo[i];			//┘
//			//スプライト定義を取得する。
//			ST_SprDef stSprDef = GetSprDef(iSprNo);
//			PoolObject po;
//			//ムービーならば…
//			if(stSprDef.isMovie) {
//				//最終候補でなければ…
//				if(i < (aSprNo.Length - 1)) {
//					//ムービーマテリアルを準備する。
//					if(!MovieHelper_Prepare(Graph.pMovieHelper, stSprDef.iTexNo)) { continue; }	//まだ準備が完了していなければ、次の候補へ進む。
//				}
//				//ムービーマテリアルを取得する。
//				CriManaMovieMaterial movieMaterial = ((MoviePlayer)MovieHelper_Draw(Graph.pMovieHelper, stSprDef.iTexNo)).criManaMovieMaterial;
//				if(movieMaterial == null) { throw new ApplicationException(); }	//バグ
//				//Movieオブジェクトを取得する。
//				MovieObject mo = Graph.movieObjectPool.GetObject();
//				//Movieオブジェクトを設定する。
//				mo.meshRenderer.material = movieMaterial.material;
//				//※TODO:alpha未対応
//				mo.goInner.transform.localPosition = new Vector2(
//					(float)(((stSprDef.w / 2) - (stSprDef.cx)) / PPU),
//					(float)(((stSprDef.cy) - (stSprDef.h / 2)) / PPU));
//				mo.goInner.transform.localScale = new Vector2(
//					(float)(stSprDef.w / PPU),
//					(float)(stSprDef.h / PPU));
//				//Poolオブジェクトの共通処理へ進む。
//				po = mo;
//			//スプライトならば…
//			} else {
//				//スプライトを取得する。
//				Sprite sprite = GetSprite(iSprNo);
//				//Spriteオブジェクトを取得する。
//				SpriteObject so = Graph.spriteObjectPool.GetObject();
//				//Spriteオブジェクトを設定する。
//				so.spriteRenderer.sprite = sprite;
//				so.spriteRenderer.color = new Color(1, 1, 1, (float)alpha);
//				so.goInner.transform.localPosition = new Vector2(
//					(sprite.pivot.x - stSprDef.cx) / sprite.pixelsPerUnit,
////{{2017/03/29変更:draw_spr()において、UnityのSpriteのPivotを相殺する処理が、縦軸に関して間違っていたのを修正しました。
////					(stSprDef.cy - sprite.pivot.y) / sprite.pixelsPerUnit);
////↓2017/03/29変更:draw_spr()において、UnityのSpriteのPivotを相殺する処理が、縦軸に関して間違っていたのを修正しました。
//					(stSprDef.cy - (sprite.rect.height - sprite.pivot.y)) / sprite.pixelsPerUnit);
////{{2017/03/29変更:draw_spr()において、UnityのSpriteのPivotを相殺する処理が、縦軸に関して間違っていたのを修正しました。
//				//Poolオブジェクトの共通処理へ進む。
//				po = so;
//			}
////{{2017/03/31追加:テクスチャの自動スケーリングを追加しました。
//			//テクスチャ定義を取得する。
//			// - この処理を、このforループの先頭で行わないように注意して下さい。
//			//   ムービーだった場合、ムービーマテリアルの準備が完了していなければ、そのテクスチャを描画しない可能性が有るからです。
//			//   もし、この処理をこのforループの先頭で行ってしまうと、最終候補ではないムービーでcontinueで次のループへ進んだ場合に、自動スケーリングが設定されていないスプライトに適用してしまうバグが生じる可能性が有ります。
//			//   そうならないよう、自動スケーリングを適用する処理は、描画するテクスチャが決定した後、この場所で行う必要が有ります。
//			ST_TexDef stTexDef = GetTexDef(stSprDef.iTexNo);
//			if(stTexDef.nScale != 1) {	//この判断を行わずに無条件に乗算を行っても同じ結果ではあるが、ほとんどの場合は(stTexDef.nScale==1)だと思うので、この判断を行う方が乗算二回分のコストよりも僅かに効率が良いだろう。
//				scale_x *= stTexDef.nScale;
//				scale_y *= stTexDef.nScale;
//			}
////}}2017/03/31追加:テクスチャの自動スケーリングを追加しました。
//			//Poolオブジェクトを設定する。
//			po.goOuter.transform.localPosition = new Vector2(
//				(float)((x - (DISP_X / 2)) / PPU),
//				(float)(((DISP_Y / 2) - y) / PPU));
//			po.goOuter.transform.localScale = new Vector2(
//				(float)scale_x,
//				(float)scale_y);
//			po.goOuter.transform.localEulerAngles = new Vector3(
//				0,
//				0,
//				(float)rot * -Mathf.Rad2Deg);
//			return;	//ここまで。	忘れないで!!これを忘れると無条件に全ての候補を表示してしまうバグになる。
//		}
//	}
//	//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//	public static void CbkQue_draw_spr(ST_CbkQue pCbkQue, int pri, double x, double y, int[] aSprNo, double scale_x = 1, double scale_y = 1, double rot = 0, double alpha = 1) {
//		CbkQue_Add(pCbkQue, pri, delegate(ST_CbkQue _pCbkQue, int _pri, object param) {
//				draw_spr(x, y, aSprNo, scale_x, scale_y, rot, alpha);
//			}, null);
//	}
//}}2017/04/10削除:「スプライト描画(フォールバック有り)」を削除し、既存の「スプライト描画(フォールバック無し)」を単純に「スプライト描画」としました。
	//-----------------------------------------------------------------------------
//{{2017/04/10変更:「スプライト描画(フォールバック有り)」を削除し、既存の「スプライト描画(フォールバック無し)」を単純に「スプライト描画」としました。
//	//スプライト描画(フォールバック無し)
//	private static void draw_spr(double x, double y, int iSprNo, double scale_x, double scale_y, double rot, double alpha) {
//		draw_spr(x, y, new int[] { iSprNo }, scale_x, scale_y, rot, alpha);
//	}
//	//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//	public static void CbkQue_draw_spr(ST_CbkQue pCbkQue, int pri, double x, double y, int iSprNo, double scale_x = 1, double scale_y = 1, double rot = 0, double alpha = 1) {
//		CbkQue_Add(pCbkQue, pri, delegate(ST_CbkQue _pCbkQue, int _pri, object param) {
//				draw_spr(x, y, iSprNo, scale_x, scale_y, rot, alpha);
//			}, null);
//	}
//↓2017/04/10変更:「スプライト描画(フォールバック有り)」を削除し、既存の「スプライト描画(フォールバック無し)」を単純に「スプライト描画」としました。
	//スプライト描画
//{{2017/04/11変更:各描画関数のalpha引数を、rgba引数に変更しました。
//	private static void draw_spr(double x, double y, int iSprNo, double scale_x, double scale_y, double rot, double alpha) {
//↓2017/04/11変更:各描画関数のalpha引数を、rgba引数に変更しました。
	private static void draw_spr(double x, double y, int iSprNo, double scale_x, double scale_y, double rot, int rgba) {
//}}2017/04/11変更:各描画関数のalpha引数を、rgba引数に変更しました。
		//スプライト定義を取得する。
		ST_SprDef stSprDef = GetSprDef(iSprNo);
		PoolObject po;
		//ムービーならば…
		if(stSprDef.isMovie) {
			//ムービーマテリアルを取得する。
			CriManaMovieMaterial movieMaterial = ((MoviePlayer)MovieHelper_Draw(Graph.pMovieHelper, stSprDef.iTexNo)).criManaMovieMaterial;
			if(movieMaterial == null) { throw new ApplicationException(); }	//バグ
			//Movieオブジェクトを取得する。
			MovieObject mo = Graph.movieObjectPool.GetObject();
			//Movieオブジェクトを設定する。
			mo.meshRenderer.material = movieMaterial.material;
//{{2017/04/11変更:各描画関数のalpha引数を、rgba引数に変更しました。
//			//※TODO:alpha未対応
//↓2017/04/11変更:各描画関数のalpha引数を、rgba引数に変更しました。
//			//※TODO:rgba未対応
//↓2017/04/12変更:draw_spr()にて、ムービーのカラーブレンディングも対応しました。
			Mesh mesh = mo.meshFilter.mesh;	//sharedMeshとの使い分けがいまいち良く判らない…この下でmesh.colors32を変更しているが、どの時点からsharedMeshへの変更ではなく複製への変更と見なされるのだろうか?(※要確認)
			Color32 c = RGBA_TOCOLOR(rgba);
			mesh.colors32 = new Color32[] { c,c,c,c };
			mo.meshFilter.mesh = mesh;	//sharedMeshとの使い分けがいまいち良く判らない…この上でmesh.colors32を変更しているが、どの時点からsharedMeshへの変更ではなく複製への変更と見なされるのだろうか?(※要確認)
//}}2017/04/12変更:draw_spr()にて、ムービーのカラーブレンディングも対応しました。
			mo.goInner.transform.localPosition = new Vector2(
				(float)(((stSprDef.w / 2) - (stSprDef.cx)) / PPU),
				(float)(((stSprDef.cy) - (stSprDef.h / 2)) / PPU));
			mo.goInner.transform.localScale = new Vector2(
				(float)(stSprDef.w / PPU),
				(float)(stSprDef.h / PPU));
			//Poolオブジェクトの共通処理へ進む。
			po = mo;
		//スプライトならば…
		} else {
			//スプライトを取得する。
			Sprite sprite = GetSprite(iSprNo);
			//Spriteオブジェクトを取得する。
			SpriteObject so = Graph.spriteObjectPool.GetObject();
			//Spriteオブジェクトを設定する。
			so.spriteRenderer.sprite = sprite;
//{{2017/04/11変更:各描画関数のalpha引数を、rgba引数に変更しました。
//			so.spriteRenderer.color = new Color(1, 1, 1, (float)alpha);
//↓2017/04/11変更:各描画関数のalpha引数を、rgba引数に変更しました。
			so.spriteRenderer.color = RGBA_TOCOLOR(rgba);
//}}2017/04/11変更:各描画関数のalpha引数を、rgba引数に変更しました。
			so.goInner.transform.localPosition = new Vector2(
				(sprite.pivot.x - stSprDef.cx) / sprite.pixelsPerUnit,
				(stSprDef.cy - (sprite.rect.height - sprite.pivot.y)) / sprite.pixelsPerUnit);
			//Poolオブジェクトの共通処理へ進む。
			po = so;
		}
		//テクスチャ定義を取得する。
		// - この処理を、このforループの先頭で行わないように注意して下さい。
		//   ムービーだった場合、ムービーマテリアルの準備が完了していなければ、そのテクスチャを描画しない可能性が有るからです。
		//   もし、この処理をこのforループの先頭で行ってしまうと、最終候補ではないムービーでcontinueで次のループへ進んだ場合に、自動スケーリングが設定されていないスプライトに適用してしまうバグが生じる可能性が有ります。
		//   そうならないよう、自動スケーリングを適用する処理は、描画するテクスチャが決定した後、この場所で行う必要が有ります。
		ST_TexDef stTexDef = GetTexDef(stSprDef.iTexNo);
		if(stTexDef.nScale != 1) {	//この判断を行わずに無条件に乗算を行っても同じ結果ではあるが、ほとんどの場合は(stTexDef.nScale==1)だと思うので、この判断を行う方が乗算二回分のコストよりも僅かに効率が良いだろう。
			scale_x *= stTexDef.nScale;
			scale_y *= stTexDef.nScale;
		}
		//Poolオブジェクトを設定する。
		po.goOuter.transform.localPosition = new Vector2(
			(float)((x - (DISP_X / 2)) / PPU),
			(float)(((DISP_Y / 2) - y) / PPU));
		po.goOuter.transform.localScale = new Vector2(
			(float)scale_x,
			(float)scale_y);
		po.goOuter.transform.localEulerAngles = new Vector3(
			0,
			0,
			(float)rot * -Mathf.Rad2Deg);
	}
	//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//{{2017/04/11変更:各描画関数のalpha引数を、rgba引数に変更しました。
//	public static void CbkQue_draw_spr(ST_CbkQue pCbkQue, int pri, double x, double y, int iSprNo, double scale_x = 1, double scale_y = 1, double rot = 0, double alpha = 1) {
//		CbkQue_Add(pCbkQue, pri, delegate(ST_CbkQue _pCbkQue, int _pri, object param) {
//				draw_spr(x, y, iSprNo, scale_x, scale_y, rot, alpha);
//			}, null);
//	}
//↓2017/04/11変更:各描画関数のalpha引数を、rgba引数に変更しました。
	public static void CbkQue_draw_spr(ST_CbkQue pCbkQue, int pri, double x, double y, int iSprNo, double scale_x = 1, double scale_y = 1, double rot = 0, int rgba = -1) {
		CbkQue_Add(pCbkQue, pri, delegate(ST_CbkQue _pCbkQue, int _pri, object param) {
				draw_spr(x, y, iSprNo, scale_x, scale_y, rot, rgba);
			}, null);
	}
//}}2017/04/11変更:各描画関数のalpha引数を、rgba引数に変更しました。
//{{2017/04/10変更:「スプライト描画(フォールバック有り)」を削除し、既存の「スプライト描画(フォールバック無し)」を単純に「スプライト描画」としました。
	//-----------------------------------------------------------------------------
	//スプライトフォント描画
//{{2017/04/04変更:スプライトフォント描画に回転機能を追加しました。
//	private static void draw_sprf_fn(object user_data, int x, int y, double scale_x, double scale_y, int rgba, int iSprNo) {
//		double alpha = (double)RGBA_GETALPHA(rgba) / (double)byte.MaxValue;
//		draw_spr(x, y, iSprNo, scale_x, scale_y, 0, alpha);
//	}
//	//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//	private static void draw_sprf(VoidPtr pSprFnt, double x, double y, double scale_x, double scale_y, double ax, double ay, double alpha, string s) {
//		SprFnt_Print(pSprFnt, draw_sprf_fn, null, (int)x, (int)y, scale_x, scale_y, ax, ay, D3DRGBA(1,1,1,alpha), s);
//	}
//	//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//	public static void CbkQue_draw_sprf(ST_CbkQue pCbkQue, int pri, VoidPtr pSprFnt, double x, double y, double scale_x, double scale_y, double ax, double ay, double alpha, string s) {
//		CbkQue_Add(pCbkQue, pri, delegate(ST_CbkQue _pCbkQue, int _pri, object param) {
//				draw_sprf(pSprFnt, x, y, scale_x, scale_y, ax, ay, alpha, s);
//			}, null);
//	}
//↓2017/04/04変更:スプライトフォント描画に回転機能を追加しました。
//	private static void draw_sprf_fn(object user_data, int x, int y, double scale_x, double scale_y, double rot, int rgba, int iSprNo) {
//		double alpha = (double)RGBA_GETALPHA(rgba) / (double)byte.MaxValue;
//		draw_spr(x, y, iSprNo, scale_x, scale_y, rot, alpha);
//	}
//	//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//	private static void draw_sprf(VoidPtr pSprFnt, double x, double y, double scale_x, double scale_y, double rot, double ax, double ay, double alpha, string s) {
//		SprFnt_Print(pSprFnt, draw_sprf_fn, null, (int)x, (int)y, scale_x, scale_y, rot, ax, ay, D3DRGBA(1,1,1,alpha), s);
//	}
//	//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//	public static void CbkQue_draw_sprf(ST_CbkQue pCbkQue, int pri, VoidPtr pSprFnt, double x, double y, double scale_x, double scale_y, double rot, double ax, double ay, double alpha, string s) {
//		CbkQue_Add(pCbkQue, pri, delegate(ST_CbkQue _pCbkQue, int _pri, object param) {
//				draw_sprf(pSprFnt, x, y, scale_x, scale_y, rot, ax, ay, alpha, s);
//			}, null);
//	}
//↓2017/04/11変更:各描画関数のalpha引数を、rgba引数に変更しました。
	private static void draw_sprf_fn(object user_data, int x, int y, double scale_x, double scale_y, double rot, int rgba, int iSprNo) {
		draw_spr(x, y, iSprNo, scale_x, scale_y, rot, rgba);
	}
	//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	private static void draw_sprf(VoidPtr pSprFnt, double x, double y, double scale_x, double scale_y, double rot, double ax, double ay, int rgba, string s) {
		SprFnt_Print(pSprFnt, draw_sprf_fn, null, (int)x, (int)y, scale_x, scale_y, rot, ax, ay, rgba, s);
	}
	//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	public static void CbkQue_draw_sprf(ST_CbkQue pCbkQue, int pri, VoidPtr pSprFnt, double x, double y, double scale_x, double scale_y, double rot, double ax, double ay, int rgba, string s) {
		CbkQue_Add(pCbkQue, pri, delegate(ST_CbkQue _pCbkQue, int _pri, object param) {
				draw_sprf(pSprFnt, x, y, scale_x, scale_y, rot, ax, ay, rgba, s);
			}, null);
	}
//}}2017/04/11変更:各描画関数のalpha引数を、rgba引数に変更しました。
	//-----------------------------------------------------------------------------
	//スプライトフォント描画(書式付き)
//{{2017/04/04変更:スプライトフォント描画に回転機能を追加しました。
//	private static void draw_sprf(VoidPtr pSprFnt, double x, double y, double scale_x, double scale_y, double ax, double ay, double alpha, string fmt, params object[] ap) {
//		SprFnt_PrintF(pSprFnt, draw_sprf_fn, null, (int)x, (int)y, scale_x, scale_y, ax, ay, D3DRGBA(1,1,1,alpha), fmt, ap);
//	}
//	//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//	public static void CbkQue_draw_sprf(ST_CbkQue pCbkQue, int pri, VoidPtr pSprFnt, double x, double y, double scale_x, double scale_y, double ax, double ay, double alpha, string fmt, params object[] ap) {
//		CbkQue_Add(pCbkQue, pri, delegate(ST_CbkQue _pCbkQue, int _pri, object param) {
//				draw_sprf(pSprFnt, x, y, scale_x, scale_y, ax, ay, alpha, fmt, ap);
//			}, null);
//	}
//↓2017/04/04変更:スプライトフォント描画に回転機能を追加しました。
//	private static void draw_sprf(VoidPtr pSprFnt, double x, double y, double scale_x, double scale_y, double rot, double ax, double ay, double alpha, string fmt, params object[] ap) {
//		SprFnt_PrintF(pSprFnt, draw_sprf_fn, null, (int)x, (int)y, scale_x, scale_y, rot, ax, ay, D3DRGBA(1,1,1,alpha), fmt, ap);
//	}
//	//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//	public static void CbkQue_draw_sprf(ST_CbkQue pCbkQue, int pri, VoidPtr pSprFnt, double x, double y, double scale_x, double scale_y, double rot, double ax, double ay, double alpha, string fmt, params object[] ap) {
//		CbkQue_Add(pCbkQue, pri, delegate(ST_CbkQue _pCbkQue, int _pri, object param) {
//				draw_sprf(pSprFnt, x, y, scale_x, scale_y, rot, ax, ay, alpha, fmt, ap);
//			}, null);
//	}
//↓2017/04/11変更:各描画関数のalpha引数を、rgba引数に変更しました。
	private static void draw_sprf(VoidPtr pSprFnt, double x, double y, double scale_x, double scale_y, double rot, double ax, double ay, int rgba, string fmt, params object[] ap) {
		SprFnt_PrintF(pSprFnt, draw_sprf_fn, null, (int)x, (int)y, scale_x, scale_y, rot, ax, ay, rgba, fmt, ap);
	}
	//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	public static void CbkQue_draw_sprf(ST_CbkQue pCbkQue, int pri, VoidPtr pSprFnt, double x, double y, double scale_x, double scale_y, double rot, double ax, double ay, int rgba, string fmt, params object[] ap) {
		CbkQue_Add(pCbkQue, pri, delegate(ST_CbkQue _pCbkQue, int _pri, object param) {
				draw_sprf(pSprFnt, x, y, scale_x, scale_y, rot, ax, ay, rgba, fmt, ap);
			}, null);
	}
//}}2017/04/11変更:各描画関数のalpha引数を、rgba引数に変更しました。
	//-----------------------------------------------------------------------------
	//スプライトフォント描画(クロスフェード)
//{{2017/04/04変更:スプライトフォント描画に回転機能を追加しました。
//	private static void draw_sprf_xf(VoidPtr pSprFnt, double x, double y, double scale_x, double scale_y, double ax, double ay, double alpha, string s1, string s2, double transition/*0.0～1.0*/) {
//		SprFnt_PrintXF(pSprFnt, draw_sprf_fn, null, (int)x, (int)y, scale_x, scale_y, ax, ay, D3DRGBA(1,1,1,alpha), s1, s2, transition);
//	}
//	//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//	public static void CbkQue_draw_sprf_xf(ST_CbkQue pCbkQue, int pri, VoidPtr pSprFnt, double x, double y, double scale_x, double scale_y, double ax, double ay, double alpha, string s1, string s2, double transition/*0.0～1.0*/) {
//		CbkQue_Add(pCbkQue, pri, delegate(ST_CbkQue _pCbkQue, int _pri, object param) {
//				draw_sprf_xf(pSprFnt, x, y, scale_x, scale_y, ax, ay, alpha, s1, s2, transition);
//			}, null);
//	}
//↓2017/04/04変更:スプライトフォント描画に回転機能を追加しました。
//	private static void draw_sprf_xf(VoidPtr pSprFnt, double x, double y, double scale_x, double scale_y, double rot, double ax, double ay, double alpha, string s1, string s2, double transition/*0.0～1.0*/) {
//		SprFnt_PrintXF(pSprFnt, draw_sprf_fn, null, (int)x, (int)y, scale_x, scale_y, rot, ax, ay, D3DRGBA(1,1,1,alpha), s1, s2, transition);
//	}
//	//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//	public static void CbkQue_draw_sprf_xf(ST_CbkQue pCbkQue, int pri, VoidPtr pSprFnt, double x, double y, double scale_x, double scale_y, double rot, double ax, double ay, double alpha, string s1, string s2, double transition/*0.0～1.0*/) {
//		CbkQue_Add(pCbkQue, pri, delegate(ST_CbkQue _pCbkQue, int _pri, object param) {
//				draw_sprf_xf(pSprFnt, x, y, scale_x, scale_y, rot, ax, ay, alpha, s1, s2, transition);
//			}, null);
//	}
//↓2017/04/11変更:各描画関数のalpha引数を、rgba引数に変更しました。
	private static void draw_sprf_xf(VoidPtr pSprFnt, double x, double y, double scale_x, double scale_y, double rot, double ax, double ay, int rgba, string s1, string s2, double transition/*0.0～1.0*/) {
		SprFnt_PrintXF(pSprFnt, draw_sprf_fn, null, (int)x, (int)y, scale_x, scale_y, rot, ax, ay, rgba, s1, s2, transition);
	}
	//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	public static void CbkQue_draw_sprf_xf(ST_CbkQue pCbkQue, int pri, VoidPtr pSprFnt, double x, double y, double scale_x, double scale_y, double rot, double ax, double ay, int rgba, string s1, string s2, double transition/*0.0～1.0*/) {
		CbkQue_Add(pCbkQue, pri, delegate(ST_CbkQue _pCbkQue, int _pri, object param) {
				draw_sprf_xf(pSprFnt, x, y, scale_x, scale_y, rot, ax, ay, rgba, s1, s2, transition);
			}, null);
	}
//}}2017/04/11変更:各描画関数のalpha引数を、rgba引数に変更しました。
	//-----------------------------------------------------------------------------
	private static void draw_line(double[,] xy, double w, int iSprNo, int rgba) {
		//Lineオブジェクトを取得する。
		LineObject lo = Graph.lineObjectPool.GetObject();
		//Lineオブジェクトを設定する。
		int n = xy.GetLength(0);
//{{2017/04/09変更:Unity 5.6.0ではLineRenderer.numPositionsがobsoleteになり、positionCountに変わった事に対応しました。
//		lo.lineRenderer.numPositions = n;
//↓2017/04/09変更:Unity 5.6.0ではLineRenderer.numPositionsがobsoleteになり、positionCountに変わった事に対応しました。
		lo.lineRenderer.positionCount = n;
//}}2017/04/09変更:Unity 5.6.0ではLineRenderer.numPositionsがobsoleteになり、positionCountに変わった事に対応しました。
		lo.lineRenderer.startWidth = lo.lineRenderer.endWidth = (float)(w / PPU);	//goInner.transform.localScaleはlineRenderer.startWidth,endWidthには影響しないようなので、lineRenderer.startWidth,endWidthにもスケールを掛ける必要が有ります。
		lo.lineRenderer.startColor = lo.lineRenderer.endColor = RGBA_TOCOLOR(rgba);
		Vector3[] positions = new Vector3[n];
		for(int i = 0; i < n; i++) {
			positions[i] = new Vector2(
				(float)xy[i,0/*x*/],
				(float)xy[i,1/*y*/]);
		}
		lo.lineRenderer.SetPositions(positions);
		//スプライト番号が指定されていたら…
		if(iSprNo != -1) {
			//スプライト定義を取得する。
			ST_SprDef stSprDef = GetSprDef(iSprNo);
			//ムービーならば…
			if(stSprDef.isMovie) {
				throw new ApplicationException();	//※未対応。多分、対応するのはそんなに難しくないと思う。CRIが返したマテリアルをlo.material.mainTextureに格納すれば良いだけなはずなので。
			//スプライトならば…
			} else {
				//スプライトを取得する。
				Sprite sprite = GetSprite(iSprNo);
				//Materialを設定する。
				lo.material.mainTexture = sprite.texture;
			}
		//スプライト番号が指定されていなければ…
		} else {
			//Materialを設定する。
			lo.material.mainTexture = null;
		}
	}
	//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	public static void CbkQue_draw_line(ST_CbkQue pCbkQue, int pri, double[,] xy, double w, int iSprNo, int rgba = -1) {
		CbkQue_Add(pCbkQue, pri, delegate(ST_CbkQue _pCbkQue, int _pri, object param) {
				draw_line(xy, w, iSprNo, rgba);
			}, null);
	}
	//-----------------------------------------------------------------------------
	private static void draw_box(double x, double y, double w, double h, int rgba) {
		//Boxオブジェクトを取得する。
		BoxObject bo = Graph.boxObjectPool.GetObject();
		//Boxオブジェクトを設定する。
		bo.goOuter.transform.localPosition = new Vector2(
			(float)((x - (DISP_X / 2)) / PPU),
			(float)(((DISP_Y / 2) - y) / PPU));
		bo.goOuter.transform.localScale = new Vector2(
			(float)w,
			(float)h);
		bo.material.color = RGBA_TOCOLOR(rgba);
	}
	//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	public static void CbkQue_draw_box(ST_CbkQue pCbkQue, int pri, double x, double y, double w, double h, int rgba = -1) {
		CbkQue_Add(pCbkQue, pri, delegate(ST_CbkQue _pCbkQue, int _pri, object param) {
				draw_box(x, y, w, h, rgba);
			}, null);
	}
	//-----------------------------------------------------------------------------
	private static void draw_polygon(double[,] xy, int rgba = -1) {
		//Polygonオブジェクトを取得する。
		PolygonObject po = Graph.polygonObjectPool.GetObject();
		//Polygonオブジェクトを設定する。
		{
			int n = xy.GetLength(0);
			if(n < 3) { throw new ApplicationException(); }	//少なくとも三角形以上でなくてはなりません。
			{
				Vector3[] vertices = new Vector3[n];
				for(int i = 0; i < n; i++) { vertices[i] = new Vector2((float)xy[i,0/*x*/], (float)xy[i,1/*y*/]); }
				po.mesh.vertices = vertices;
			}
			{
				int[] triangles = new int[(n - 2) * 3];
				for(int i = 0; i < n - 2; i++) {	//┐
					triangles[(i * 3) + 0] = 0;	//│
					triangles[(i * 3) + 1] = i + 1;	//├実装を簡単にするためにトライアングルファンの形に分割する事にしました。本当はトライアングルストリップの形に分割する方が良いとは思うのですが、実際の所当関数で描画するのはせいぜい3～4角形程度だと思うのでどちらでもさほど違いは無いと思います。
					triangles[(i * 3) + 2] = i + 2;	//│
				}					//┘
				po.mesh.triangles = triangles;
			}
		}
		po.material.color = RGBA_TOCOLOR(rgba);	//Mesh.colors32はnullのままでマテリアルで色を設定する方が簡単です。(MovieObjectの場合は複数のオブジェクトでマテリアルを共有しているのでMesh.colors32を使わざるを得ませんが…)
	}
	//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	public static void CbkQue_draw_polygon(ST_CbkQue pCbkQue, int pri, double[,] xy, int rgba = -1) {
		CbkQue_Add(pCbkQue, pri, delegate(ST_CbkQue _pCbkQue, int _pri, object param) {
				draw_polygon(xy, rgba);
			}, null);
	}
	//-----------------------------------------------------------------------------
	//※TODO:ここに追加して下さい。
}
#endif//UNITY_5_3_OR_NEWER
