/*
 *	clipact.h
 *
 *	アクターオブジェクト
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2017 Naoyuki Sawa
 *
 *	* Sun Feb 07 21:14:38 JST 2016 Naoyuki Sawa
 *	- 1st リリース。
 *	- 有限状態機械とプロパティヘッダとアプリケーション定義のデータをまとめたものを、アクターオブジェクトと呼ぶ事にしました。
 *        当モジュールは、アクターオブジェクトを、ツリー構造で管理する機能を提供します。
 *	- 2016/02/07現在の所、最低限の機能だけを実装しました。
 *	  今後、アクターオブジェクトを検索する機能を追加したり、座標プロパティや当たり判定プロパティを標準化したりする予定です。
 *	* Fri Feb 26 21:51:12 JST 2016 Naoyuki Sawa
 *	- ActObj_ApplyTrans_l(),ActObj_ApplyTrans_a(),ActObj_ApplyTrans_v()を追加しました。
 *	  ActObj_ApplyTransToChildren_l(),ActObj_ApplyTransToChildren_a(),ActObj_ApplyTransToChildren_v()を追加しました。
 *	  ActObj_ApplyTransToTree_l(),ActObj_ApplyTransToTree_a(),ActObj_ApplyTransToTree_v()を追加しました。
 *	  詳細は、clipfsm.h の同日のコメントを参照して下さい。
 *	* Sat Feb 27 21:21:24 JST 2016 Naoyuki Sawa
 *	- FsmObj_Init()の引数で有権状態機械の初期状態を明示しなくなった事に伴い、ActObj_New()からも初期状態を指定する引数を削除しました。
 *	  詳細は、clipfsm.h の同日のコメントを参照して下さい。
 *	- ActObj_GetParent()を追加しました。
 *	  この関数を追加した理由は、clipact.c の実装個所のコメントを参照して下さい。
 *	* Sat Apr 02 23:34:06 JST 2016 Naoyuki Sawa
 *	- ARRAY_SIZE()マクロの変更に伴い、VC++6.0でintとunsignedの比較に対する警告が厳密に出るようになったので、警告が出ないように明示的なキャストを追加しました。
 *	  動作自体はこれまでと変わりません。
 *	  詳細はclipmisc.hの同日のコメントを参照して下さい。
 *	* Fri Jul 08 21:19:03 JST 2016 Naoyuki Sawa
 *	- clipfsm.cモジュールの、FsmObj_ApplyTrans_l(),FsmObj_ApplyTrans_a(),FsmObj_ApplyTrans_v()に対して行ったのと同じ変更を、
 *	  ActObj_ApplyTrans_l(),ActObj_ApplyTrans_a(),ActObj_ApplyTrans_v()、及び、
 *	  ActObj_ApplyTransToChildren_l(),ActObj_ApplyTransToChildren_a(),ActObj_ApplyTransToChildren_v()、及び、
 *	  ActObj_ApplyTransToTree_l(),ActObj_ApplyTransToTree_a(),ActObj_ApplyTransToTree_v()にも適用しました。
 *	  詳細は、clipfsm.cモジュールの、同日のコメントを参照して下さい。
 *	- 余談ですが、これまで、上記の関数のアセンブラ版の実装は、スタック操作のバグが有った事に気付きました。
 *	  今回の変更に合わせて、スタック操作のバグも修正しました。
 *	* Sat Aug 27 12:10:07 JST 2016 Naoyuki Sawa
 *	- gnode.hにG_PRE_ORDER内でnode自身を削除出来るようにするための独自拡張を追加した事に伴い、ActObj_ApplyTransToTree()がG_POST_ORDERでなくG_PRE_ORDERを使用するように変更しました。
 *	  gnode.hの、同日のコメントも参照して下さい。
 *	- gnode.hの「G_PRE_ORDER内でnode自身を削除出来るようにするための独自拡張」で行ったのと同じ検証を、当モジュール経由でも検証しました。
 *	  今回の変更が、正しく反映されている事を確認しました。
 *	  ------------------------------------------------------------------------------
 *	  ■テストプログラム
 *	  (app.c)
 *	  │void test() {
 *	  │  ST_ActObj *root, *node1, *node2, *node11, *node12, *node21, *node22;
 *	  │  root = ActObj_New(NULL, pFsmKey, FsmMap_Test, NULL, 0, sizeof(const char*));
 *	  │  *(const char**)ActObj_GetData(root) = "root";
 *	  │    node1 = ActObj_New(root, pFsmKey, FsmMap_Test, NULL, 0, sizeof(const char*));
 *	  │    *(const char**)ActObj_GetData(node1) = "node1";
 *	  │      node11 = ActObj_New(node1, pFsmKey, FsmMap_Test, NULL, 0, sizeof(const char*));
 *	  │      *(const char**)ActObj_GetData(node11) = "node11";
 *	  │      node12 = ActObj_New(node1, pFsmKey, FsmMap_Test, NULL, 0, sizeof(const char*));
 *	  │      *(const char**)ActObj_GetData(node12) = "node12";
 *	  │    node2 = ActObj_New(root, pFsmKey, FsmMap_Test, NULL, 0, sizeof(const char*));
 *	  │    *(const char**)ActObj_GetData(node2) = "node2";
 *	  │      node21 = ActObj_New(node2, pFsmKey, FsmMap_Test, NULL, 0, sizeof(const char*));
 *	  │      *(const char**)ActObj_GetData(node21) = "node21";
 *	  │      node22 = ActObj_New(node2, pFsmKey, FsmMap_Test, NULL, 0, sizeof(const char*));
 *	  │      *(const char**)ActObj_GetData(node22) = "node22";
 *	  │  ActObj_ApplyTransToTree_l(root, FsmTrans_Exec, 1, 0);
 *	  │  ActObj_Free(root);
 *	  │}
 *	  (FsmMap.txt)
 *	  │Test Run
 *	  │     Run
 *	  │         Exec {`
 *	  │                ST_ActObj* pActObj = ActObj_FromFsmObj(pFsmObj);
 *	  │                const char* name = *(const char**)ActObj_GetData(pActObj);
 *	  │                ST_FsmArg* pFsmArg = pParam;
 *	  │                int nest = (int)pFsmArg->argv[0];
 *	  │                printf("%*s%s\n", nest, "", name);
 *	  │                if(!strcmp(name, "node1")) {
 *	  │                  if(nest <= 1) {
 *	  │                    ActObj_ApplyTransToTree_l(ActObj_GetParent(pActObj), FsmTrans_Exec, 1, nest + 1);
 *	  │                    if(nest == 1) {
 *	  │                      ActObj_Free(pActObj);
 *	  │                      printf("%*s%s自身を削除しました。\n", nest, "", name);
 *	  │                    }
 *	  │                  }
 *	  │                }
 *	  │              `}
 *	  │     end
 *	  │end
 *	  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 *	  □結果
 *	  │root			←G_PRE_ORDERの順序で、親が先にトラバースされている事を確認しました。
 *	  │node1
 *	  │ root
 *	  │ node1
 *	  │  root
 *	  │  node1
 *	  │  node11
 *	  │  node12
 *	  │  node2
 *	  │  node21
 *	  │  node22
 *	  │ node1自身を削除しました。
 *	  │ node2			←期待通り、ここでnode11とnode12のトラバースが行われていないので、正しく動作している事が確認出来ました。
 *	  │ node21
 *	  │ node22
 *	  │node2			←期待通り、ここでnode11とnode12のトラバースが行われていないので、正しく動作している事が確認出来ました。
 *	  │node21
 *	  │node22
 *	  ------------------------------------------------------------------------------
 *	* Sun Sep 11 21:23:51 JST 2016 Naoyuki Sawa
 *	- アクターオブジェクトに、演出シーケンサを含めました。
 *	  演出シーケンサを使用するアクターオブジェクトは、ActObj_New()の引数fnAct,nDirSeqChに0以外の値を指定して作成して下さい。
 *	  その後、各アクターオブジェクトの演出シーケンサを、ActObj_GetDirSeq()で取得して使用して下さい。
 *	  fnActからアクターオブジェクトを逆引きするには、ActObj_FromDirSeq()を使用して下さい。
 *	- ユーティリティマクロACTOBJ_FSMFUNC_PROLOGUE_BASE,ACTOBJ_FSMFUNC_EPILOGUE_BASEを追加しました。
 *	  ユーティリティマクロACTOBJ_DIRFUNC_PROLOGUE_BASE,ACTOBJ_DIRFUNC_EPILOGUE_BASEを追加しました。
 *	* Fri Nov 25 22:46:52 JST 2016 Naoyuki Sawa
 *	- ActObj_InitAttr_l(),ActObj_InitAttr_a(),ActObj_InitAttr_v()を追加しました。
 *	  ActObj_InitAttrToChildren_l(),ActObj_InitAttrToChildren_a(),ActObj_InitAttrToChildren_v()を追加しました。
 *	  ActObj_InitAttrToTree_l(),ActObj_InitAttrToTree_a()ActObj_InitAttrToTree_v()を追加しました。
 *	  これらの関数を追加した目的は、以下の通りです。
 *	- アクターオブジェクトのプロパティヘッダは、アクターオブジェクトごとに個別のツリーなので、PrpHdr_init_l()等を使ってまとめて再初期化する事が出来ません。
 *	  これまでは、アプリケーションが明示的にアクターオブジェクトのツリーを辿って、個々のアクターオブジェクトのプロパティヘッダに対して、個別にPrpHdr_init_l()等を呼び出す必要が有りました。
 *	  動作上はそれでも構わないのですが、アクターオブジェクトのツリー(あるいはツリーの特定のノード以下全体)の、全てのアクターオブジェクトのプロパティヘッダを、まとめて再初期化出来るとより便利だと思いました。
 *	  そこで、上記の関数を追加する事にしました。
 *	- 今回追加した関数は、属性を限定して初期化を行う、PrpHdr_init_l(),PrpHdr_init_a(),PrpHdr_init_v()に相当するものです。
 *	  属性を限定せずに初期化を行う、PrpHdr_init()に相当する関数は、追加しませんでした。
 *	  属性を限定せずに、アクターオブジェクトのツリー全体のプロパティヘッダを再初期化するようなケースは、まず無いと思ったからです。
 *	  しかし、もし必要な場合は、ActObj_InitAttr_l(),ActObj_InitAttrToChildren_l(),ActObj_InitAttrToTree_l()に、属性を指定せずに呼び出せは、(効率は悪いですが)それに相当する処理も行えます。
 *	* Sat Dec 10 21:29:37 JST 2016 Naoyuki Sawa
 *	- アクターオブジェクトに、コルーチンを含めました。
 *	* Sun Dec 11 13:55:50 JST 2016 Naoyuki Sawa
 *	- コルーチンの関数内で、自分自身のアクターオブジェクトを削除出来るようにしました。
 *	  □サンプル
 *	  │typedef struct _MyData {
 *	  │  void* mem;
 *	  │} MyData;
 *	  │static void coFree(void* data) {
 *	  │  ST_ActObj* pActObj = data;
 *	  │  MyData* pMyData = ActObj_GetData(pActObj);//クリーンアップ関数が呼び出された時点でpActObjはまだ生きているのでデータにアクセス出来る。当サンプルでは行っていないが有限状態機械や演出シーケンサやプロパティテーブルにもアクセス出来る。
 *	  │  free(pMyData->mem);
 *	  │  pMyData->mem = NULL;
 *	  │}
 *	  │static void coFunc(ST_ActObj* pActObj, void* coData) {
 *	  │  MyData* pMyData = ActObj_GetData(pActObj);
 *	  │  pMyData->mem = malloc(1);
 *	  │  co_cleanup_push_np(coFree,pActObj);
 *	  │  co_resume();//1回目のActObj_CallCoroutineToTree(aoRoot)はここまで実行される。
 *	  │  co_cleanup_pop_np(1);
 *	  │  pMyData->mem = malloc(1);
 *	  │  co_cleanup_push_np(coFree,pActObj);
 *	  │  ActObj_Free(pActObj);//コルーチンの関数内で、自分自身のアクターオブジェクトを削除するには、ActObj_Free()を呼び出す。
 *	  │  co_resume();//2回目のActObj_CallCoroutineToTree(aoRoot)はここまで実行されるが、実際には上の行で終了するのでここへは到達しない。
 *	  │  co_cleanup_pop_np(1);
 *	  │}
 *	  │int app_main(int argc, char* argv[]) {
 *	  │  //以下の処理を繰り返して、メモリリークが発生しない事を確認する。
 *	  │  int i;
 *	  │  for(i = 0; i < 1000; i++) {
 *	  │    ST_ActObj* aoRoot = ActObj_New(NULL);
 *	  │    ST_ActObj_New_Param param = {aoRoot,coFunc,NULL,NULL,0,NULL,0,NULL,0,sizeof(MyData)};
 *	  │    ST_ActObj* aoTest = ActObj_New(&param);
 *	  │    ActObj_CallCoroutineToTree(aoRoot);//1回目
 *	  │    printf("1回目:g_node_n_children(aoRoot->node)=%d\n",g_node_n_children(aoRoot->node));//⇒1
 *	  │    ActObj_CallCoroutineToTree(aoRoot);//2回目
 *	  │    printf("2回目:g_node_n_children(aoRoot->node)=%d\n",g_node_n_children(aoRoot->node));//⇒0
 *	  │    ActObj_Free(aoRoot);
 *	  │  }
 *	  │  if(GC_dont_gc) { DIE(); }
 *	  │  CHECK_LEAKS();
 *	  │  return 0;
 *	  │}
 *	- コルーチンの関数が終了しても、アクターオブジェクトは削除されない事に注意して下さい。
 *	  ActObj_CallCoroutine()に対して何も実行されなくなるだけで、アクターオブジェクトとしては有効であり続けます。
 *	  コルーチンの関数内で自分自身を削除する方法は、co_exit()ではなく、上記のサンプルのようにActObj_Free()を呼び出して下さい。
 *	* Sun Dec 11 16:17:58 JST 2016 Naoyuki Sawa
 *	- ActObj_New()の引数を、構造体で指定するように変更しました。
 *	  変更した理由は、以下の通りです。
 *	- これまでは、親オブジェクト,コルーチン,有限状態機械,プロパティテーブル,演出シーケンサ,アプリケーション定義のデータを、全て個別の引数で指定していました。
 *	  動作上は問題無いのですが、引数が多過ぎて呼び出し処理を間違う危険性が高い事や、もし今後変更する時にその都度アプリケーションを書き換える必要が生じます。
 *	  そこで、個別の引数ではなく、構造体で指定するように変更する事にしました。
 *	  今回はActObj_New()を使用している既存のアプリケーションの修正が必要ですが、今後は構造体のフィールドが増えてもアプリケーションの変更は少なくて済みます。
 *	* Wed Dec 14 21:49:23 JST 2016 Naoyuki Sawa
 *	- ActObj_New()の引数の、ST_ActObj_New_Param構造体に、coStackSizeフィールドを追加しました。
 *	  コルーチンを作成する場合(coFuncにNULL以外の値を指定する場合)、coStackSizeに0以外の値を設定すれば、確保されるコルーチンのスタックサイズを指定出来ます。
 *	  coStackSizeに0を設定すれば、これまで通り、pcl.cモジュールによる既定のスタックサイズが確保されます。
 *	* Fri Jan 06 23:24:43 JST 2017 Naoyuki Sawa
 *	- clipfsm.cにて状態マップに初期化Act関数を定義出来るようにした事に伴い、ActObj_New()関数,及び,ST_ActObj_New_Param構造体も変更しました。
 *	* Sun Jan 08 21:43:34 JST 2017 Naoyuki Sawa
 *	- clipfsm.cにてFsm_Initの値を0x8000⇒0xFFFFに変更した事に伴い、ActObj_New()関数を変更しました。
 */
#ifndef __CLIP_ACT_H__
#define __CLIP_ACT_H__
#ifdef  __cplusplus
extern "C" {
#endif//__cplusplus
/****************************************************************************
 *	
 ****************************************************************************/
//{{2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
//typedef struct _ST_ActObj {
//	GNode*		node;
//	ST_FsmObj	stFsmObj;
//	ST_PrpHdr	stPrpHdr;
//    //	int		aPrpTbl[nPrpTblWords];
//    //	int		aData[nDataWords];
//} ST_ActObj;
//↓2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
typedef struct _ST_ActObj {
	GNode*		node;				//+0┐
	coroutine_t	co;				//+0┘										//{{2016/12/10追加:アクターオブジェクトに、コルーチンを含めました。}}
    //	ST_FsmObj	stFsmObj;			//+sizeof(ST_ActObj)
    //	ST_DirSeq	stDirSeq;			//+sizeof(ST_ActObj)+sizeof(ST_FsmObj)
    //	ST_DirSeqCh	_TBL_DirSeqCh[nDirSeqCh];	//+sizeof(ST_ActObj)+sizeof(ST_FsmObj)+sizeof(ST_DirSeq)
    //	ST_PrpHdr	stPrpHdr;			//+sizeof(ST_ActObj)+sizeof(ST_FsmObj)+sizeof(ST_DirSeq)+(sizeof(ST_DirSeqCh)*nDirSeqCh)
    //	int		_aPrpTbl[nPrpTblWords];		//+sizeof(ST_ActObj)+sizeof(ST_FsmObj)+sizeof(ST_DirSeq)+(sizeof(ST_DirSeqCh)*nDirSeqCh)+sizeof(ST_PrpHdr)
    //	int		_aData[nDataWords];		//+sizeof(ST_ActObj)+sizeof(ST_FsmObj)+sizeof(ST_DirSeq)+(sizeof(ST_DirSeqCh)*nDirSeqCh)+sizeof(ST_PrpHdr)+(sizeof(int)*nPrpTblWords)
} ST_ActObj;						//=sizeof(ST_ActObj)+sizeof(ST_FsmObj)+sizeof(ST_DirSeq)+(sizeof(ST_DirSeqCh)*nDirSeqCh)+sizeof(ST_PrpHdr)+(sizeof(int)*nPrpTblWords)+(sizeof(int)*nDataWords)
//}}2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
/*--------------------------------------------------------------------------*/
typedef struct _ST_ActObj_Iter {
	ST_ActObj*	pNext;
} ST_ActObj_Iter;
/****************************************************************************
 *	基本的な関数
 ****************************************************************************/
//{{2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
//ST_ActObj* ActObj_New(ST_ActObj* pParent/*NULL可*/, const void* pFsmKey/*NULL可*/, int iFsmMap, const void* pPrpKey/*NULL可*/, int iPrpTbl, int nDataBytes);
//↓2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
//ST_ActObj* ActObj_New(ST_ActObj* pParent/*NULL可*/,
//  void (*coFunc/*NULL可*/)(ST_ActObj* pActObj, void* coData), void* coData/*(coFunc=NULL)ならば参照しない*/,				//{{2016/12/10追加:アクターオブジェクトに、コルーチンを含めました。}}
//  const void* pFsmKey/*NULL可*/, int iFsmMap/*(pFsmKey=NULL)ならば参照しない*/,
//  const void* pPrpKey/*NULL可*/, int iPrpTbl/*(pPrpKey=NULL)ならば参照しない*/,								//┐この引数順序がST_ActObj構造体内での並びとは逆なのですが、この引数順序の方が直観的に判り易いのでこうする事にしました。
//  void (*fnAct/*(nDirSeqCh=0)ならば参照しない*/)(struct _ST_DirSeq* pDirSeq, int iCh, int ActNo, int bOverFlow), int nDirSeqCh/*0可*/,	//┘ST_ActObj構造体内での並びがstDirSeq,stPrpHdrの順である理由は、アドレス計算処理の都合だけでやむを得ずそうしただけです。
//  int nDataBytes/*0可*/);
//↓2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
typedef struct _ST_ActObj_New_Param {
	//親オブジェクト
	ST_ActObj*	pParent;									//NULL可
	//コルーチン
	void		(*coFunc)(ST_ActObj* pActObj, void* coData);					//NULL可
	void*		coData;										//(coFunc=NULL)ならば参照しない。
	int		coStackSize;									//(coFunc=NULL)ならば参照しない。	//{{2016/12/14追加:ActObj_New()の引数の、ST_ActObj_New_Param構造体に、coStackSizeフィールドを追加しました。}}
	//有限状態機械
	const void*	pFsmKey;									//NULL可
	int		iFsmMap;									//(pFsmKey=NULL)ならば参照しない。
	void*		pFsmInitParam;									//(pFsmKey=NULL)ならば参照しない。	//{{2017/01/06追加:clipfsm.cにて状態マップに初期化Act関数を定義出来るようにした事に伴い、ActObj_New()関数,及び,ST_ActObj_New_Param構造体も変更しました。}}
	//プロパティテーブル
	const void*	pPrpKey;									//NULL可
	int		iPrpTbl;									//(pPrpKey=NULL)ならば参照しない。
	//演出シーケンサ
	void		(*fnAct)(struct _ST_DirSeq* pDirSeq, int iCh, int ActNo, int bOverFlow);	//(nDirSeqCh=0)ならば参照しない。
	int		nDirSeqCh;									//0可
	//アプリケーション定義のデータ
	int		nDataBytes;									//0可
} ST_ActObj_New_Param;
ST_ActObj* ActObj_New(const ST_ActObj_New_Param* pParam/*NULL可*/);
//}}2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
void ActObj_Free(ST_ActObj* pActObj);
void ActObj_FreeChildren(ST_ActObj* pActObj);
ST_ActObj* ActObj_GetParent(ST_ActObj* pActObj);
ST_ActObj* ActObj_FirstChild(ST_ActObj* pActObj, ST_ActObj_Iter* pIter);
ST_ActObj* ActObj_NextSibling(ST_ActObj_Iter* pIter);
/*--------------------------------------------------------------------------*/
//{{2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
//void* ActObj_GetData(ST_ActObj* pActObj);
//ST_ActObj* ActObj_FromFsmObj(ST_FsmObj* pFsmObj);
//↓2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
ST_FsmObj* ActObj_GetFsmObj(ST_ActObj* pActObj);	//┐ST_ActObjの先頭アドレスから、stFsmObjフィールドのアドレスを取得する。
ST_ActObj* ActObj_FromFsmObj(ST_FsmObj* pFsmObj);	//┘stFsmObjフィールドのアドレスから、ST_ActObjの先頭アドレスを取得する。
ST_DirSeq* ActObj_GetDirSeq(ST_ActObj* pActObj);	//┐ST_ActObjの先頭アドレスから、stDirSeqフィールドのアドレスを取得する。
ST_ActObj* ActObj_FromDirSeq(ST_DirSeq* pDirSeq);	//┘stDirSeqフィールドのアドレスから、ST_ActObjの先頭アドレスを取得する。
ST_PrpHdr* ActObj_GetPrpHdr(ST_ActObj* pActObj);	//┐ST_ActObjの先頭アドレスから、stPrpHdrフィールドのアドレスを取得する。
//ST_ActObj* ActObj_FromPrpHdr(ST_PrpHdr* pPrpHdr);	//┘stPrpHdrフィールドのアドレスから、ST_ActObjの先頭アドレスを取得する。		×この操作は提供出来ません。stPrpHdrフィールド以降の情報だけでは、stPrpHdrフィールド以前のサイズを計算出来ないからです。
void* ActObj_GetData(ST_ActObj* pActObj);		//┐ST_ActObjの先頭アドレスから、アプリケーション定義のデータのアドレスを取得する。
//ST_ActObj* ActObj_FromData(void* pData);		//┘アプリケーション定義のデータのアドレスから、ST_ActObjの先頭アドレスを取得する。	×この操作は提供出来ません。stPrpHdrフィールド以降の情報だけでは、stPrpHdrフィールド以前のサイズを計算出来ないからです。
//}}2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
/*--------------------------------------------------------------------------*/
//{{2016/12/10追加:アクターオブジェクトに、コルーチンを含めました。
void ActObj_CallCoroutine(ST_ActObj* pActObj);
void ActObj_CallCoroutineToChildren(ST_ActObj* pActObj);
void ActObj_CallCoroutineToTree(ST_ActObj* pActObj);
//}}2016/12/10追加:アクターオブジェクトに、コルーチンを含めました。
/*--------------------------------------------------------------------------*/
void ActObj_ApplyTrans(ST_ActObj* pActObj, int iFsmTrans, void* pParam);				//┐
void ActObj_ApplyTransToChildren(ST_ActObj* pActObj, int iFsmTrans, void* pParam);			//├pParamがそのまま、Act関数へのpParam引数となります。
void ActObj_ApplyTransToTree(ST_ActObj* pActObj, int iFsmTrans, void* pParam);				//┘
/*--------------------------------------------------------------------------*/
//{{2016/09/11追加:アクターオブジェクトに、演出シーケンサを含めました。
void ActObj_ExecDirSeq(ST_ActObj* pActObj);		//┐
void ActObj_ExecDirSeqToChildren(ST_ActObj* pActObj);	//├アプリケーションを簡潔に書けるようツリーに対するDirSeq_Exec()操作のみ実装しました。ツリーに対するそれ以外の操作(DirSeqCh_SetTbl(),DirSeqCh_SendTrig()等)が必要ならばアプリケーションが個別に実装して下さい。
void ActObj_ExecDirSeqToTree(ST_ActObj* pActObj);	//┘
//}}2016/09/11追加:アクターオブジェクトに、演出シーケンサを含めました。
/****************************************************************************
 *	ユーティリティ関数(有限状態機械)
 ****************************************************************************/
void ActObj_ApplyTrans_l(ST_ActObj* pActObj, int iFsmTrans, int argc, ...);				//┐
void ActObj_ApplyTrans_a(ST_ActObj* pActObj, int iFsmTrans, int argc, va_list ap);			//├可変引数の情報をST_FsmArg型の構造体に格納して、Act関数へのpParam引数となります。
void ActObj_ApplyTrans_v(ST_ActObj* pActObj, int iFsmTrans, int argc, void* argv[/*argc*/]);		//┘
/*--------------------------------------------------------------------------*/
void ActObj_ApplyTransToChildren_l(ST_ActObj* pActObj, int iFsmTrans, int argc, ...);			//┐
void ActObj_ApplyTransToChildren_a(ST_ActObj* pActObj, int iFsmTrans, int argc, va_list ap);		//├可変引数の情報をST_FsmArg型の構造体に格納して、Act関数へのpParam引数となります。
void ActObj_ApplyTransToChildren_v(ST_ActObj* pActObj, int iFsmTrans, int argc, void* argv[/*argc*/]);	//┘
/*--------------------------------------------------------------------------*/
void ActObj_ApplyTransToTree_l(ST_ActObj* pActObj, int iFsmTrans, int argc, ...);			//┐
void ActObj_ApplyTransToTree_a(ST_ActObj* pActObj, int iFsmTrans, int argc, va_list ap);		//├可変引数の情報をST_FsmArg型の構造体に格納して、Act関数へのpParam引数となります。
void ActObj_ApplyTransToTree_v(ST_ActObj* pActObj, int iFsmTrans, int argc, void* argv[/*argc*/]);	//┘
/****************************************************************************
 *	ユーティリティ関数(プロパティテーブル)
 ****************************************************************************/
void ActObj_InitAttr_l(ST_ActObj* pActObj, ...);
void ActObj_InitAttr_a(ST_ActObj* pActObj, va_list ap);
void ActObj_InitAttr_v(ST_ActObj* pActObj, const int* aAttr/*[inclAttr,...,]-1,[exclAttr,...,]-1*/);
/*--------------------------------------------------------------------------*/
void ActObj_InitAttrToChildren_l(ST_ActObj* pActObj, ...);
void ActObj_InitAttrToChildren_a(ST_ActObj* pActObj, va_list ap);
void ActObj_InitAttrToChildren_v(ST_ActObj* pActObj, const int* aAttr/*[inclAttr,...,]-1,[exclAttr,...,]-1*/);
/*--------------------------------------------------------------------------*/
void ActObj_InitAttrToTree_l(ST_ActObj* pActObj, ...);
void ActObj_InitAttrToTree_a(ST_ActObj* pActObj, va_list ap);
void ActObj_InitAttrToTree_v(ST_ActObj* pActObj, const int* aAttr/*[inclAttr,...,]-1,[exclAttr,...,]-1*/);
/****************************************************************************
 *	ユーティリティマクロ
 ****************************************************************************/
//ST_ActObj内のST_FsmObjから呼び出される関数(FsmFunc_〜)の実装を容易にするためのユーティリティマクロです。
//関数の最初に行う処理と関数の最後で行う処理の、一般的な処理の共通部分をマクロ定義しました。
//必要に応じて、アプリケーション定義のマクロにマージして、使用して下さい。
//・現在の所、関数の最後で行う共通部分は無いので、下記の定義では空のマクロとしてあります。
//・「ST_FsmArg* const pFsmArg = (ST_FsmArg*)pParam;」も含めるか検討しましたが、含めない事にしました。
//  含めなかった理由の一つ目は、pParam引数が有るのはAct関数だけであり、その他のEntry関数等には無いからです。
//  含めなかった理由の二つ目は、pParamが(ST_FsmArg*)型だとは限らず、遷移の種類毎に判断すべきだからです。
#define ACTOBJ_FSMFUNC_PROLOGUE_BASE				\
	int        const iState  = FsmObj_GetState(  pFsmObj);	\
	ST_ActObj* const pActObj = ActObj_FromFsmObj(pFsmObj);	\
	ST_DirSeq* const pDirSeq = ActObj_GetDirSeq( pActObj);	\
	ST_PrpHdr* const pPrpHdr = ActObj_GetPrpHdr( pActObj);	\
	void*      const pData   = ActObj_GetData(   pActObj);	\
	/* PrpHdr_load( pPrpHdr, 変数名); */			\
	/* PrpHdr_fload(pPrpHdr, 変数名); */
#define ACTOBJ_FSMFUNC_EPILOGUE_BASE				\
	/* PrpHdr_save( pPrpHdr, 変数名); */			\
	/* PrpHdr_fsave(pPrpHdr, 変数名); */
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//ST_ActObj内のST_DirSeqから呼び出される演出実行関数(fnAct)の実装を容易にするためのユーティリティマクロです。
//関数の最初に行う処理と関数の最後で行う処理の、一般的な処理の共通部分をマクロ定義しました。
//必要に応じて、アプリケーション定義のマクロにマージして、使用して下さい。
//・現在の所、関数の最後で行う共通部分は無いので、下記の定義では空のマクロとしてあります。
#define ACTOBJ_DIRFUNC_PROLOGUE_BASE				\
	ST_ActObj* const pActObj = ActObj_FromDirSeq(pDirSeq);	\
	ST_FsmObj* const pFsmObj = ActObj_GetFsmObj( pActObj);	\
	int        const iState  = FsmObj_GetState(  pFsmObj);	\
	ST_PrpHdr* const pPrpHdr = ActObj_GetPrpHdr( pActObj);	\
	void*      const pData   = ActObj_GetData(   pActObj);	\
	/* PrpHdr_load( pPrpHdr, 変数名); */			\
	/* PrpHdr_fload(pPrpHdr, 変数名); */
#define ACTOBJ_DIRFUNC_EPILOGUE_BASE				\
	/* PrpHdr_save( pPrpHdr, 変数名); */			\
	/* PrpHdr_fsave(pPrpHdr, 変数名); */
#ifdef  __cplusplus
}//extern "C"
#endif//__cplusplus
#endif//__CLIP_ACT_H__
