/*
 *	clipact.c
 *
 *	アクターオブジェクト
 *
 *	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
 *	  ------------------------------------------------------------------------------
 *	* Mon Sep 05 21:24:05 JST 2016 Naoyuki Sawa
 *	- 64ビット対応のために、ActObj_ApplyTrans_func()へのパラメータを簡易的に(void*)[2]で渡すのをやめて、パラメータ用の構造体ST_ActObj_ApplyTrans_func_Paramを定義しました。
 *	  (void*)[2]で渡すと、64ビット版では(void*)⇔(int)を変換する箇所で、コンパイラの警告が出るからです。
 *	* 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()関数を変更しました。
 */
#include "clip.h"
/****************************************************************************
 *	基本的な関数
 ****************************************************************************/
static int GetPrpTblWords(const void* pPrpKey, int iPrpTbl) {
	//プロパティテープルの(ビット数-1)を取得する。
	int iBitLen = REG_get_value_l(pPrpKey, iPrpTbl, Prp_len, -1);
	if(iBitLen == -1) { DIE(); }
	//(ビット数-1)⇒(ビット数)に補正する。
	iBitLen++;
	//ビット数⇒ワード数に切り上げる。
	return (iBitLen + 31) >> 5;
}
/*--------------------------------------------------------------------------*/
//{{2016/12/10追加:アクターオブジェクトに、コルーチンを含めました。
static void ActObj_New_coFunc(void* data) {
	//ActObj_New()が終了してparam[3]がActObj_New()のスタックフレームから消える前に、当関数がparam[3]の値を取得しておく。
	void** param = data;
	void (*coFunc)(ST_ActObj* pActObj, void* coData) = param[0];
	ST_ActObj* pActObj                               = param[1];
	void* coData                                     = param[2];
	//ActObj_New()に処理を返す。
	co_resume();
	//コルーチンのデータとしてはparam[3]のアドレスが格納されているが、指定されたコルーチンの関数の観点からは無意味なので、指定されたデータに差し替えておく。
	co_set_data(co_current(), coData);
	//指定されたコルーチンの関数を呼び出す。
	(*coFunc)(pActObj, coData);
}
//}}2016/12/10追加:アクターオブジェクトに、コルーチンを含めました。
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//アクターオブジェクトを作成する。
//{{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()の引数を、構造体で指定するように変更しました。
ST_ActObj* ActObj_New(const ST_ActObj_New_Param* pParam/*NULL可*/) {
//}}2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
	int nPrpTblWords, nDataWords;
	ST_ActObj* pActObj;
//{{2016/12/11追加:ActObj_New()の引数を、構造体で指定するように変更しました。
	ST_ActObj_New_Param stParam;
	if(pParam) {
		memcpy(&stParam, pParam, sizeof stParam);	//pParam引数が指定されたら、ローカル構造体にコピーする。(この後の処理で書き換える場合があるため。)
	} else {
		memset(&stParam,      0, sizeof stParam);	//pParam引数が指定されなければ、全てのフィールドがクリアされた構造体が指定されたのと同じと見なす。
	}
//}}2016/12/11追加:ActObj_New()の引数を、構造体で指定するように変更しました。
	//アプリケーションがpFsmKeyを指定しなかった場合は、ダミーとして、何もしないステートを持つマップを使って初期化する事にしました。
//{{2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
//	if(!pFsmKey) {
//↓2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
	if(!stParam.pFsmKey) {
//}}2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
//{{2017/01/06変更:clipfsm.cにて状態マップに初期化Act関数を定義出来るようにした事に伴い、ActObj_New()関数,及び,ST_ActObj_New_Param構造体も変更しました。
//		//-------------------------------------
//		//□FsmMap.txt
//		//│Map0 State0
//		//│     State0
//		//│            default State0
//		//│     end
//		//│end
//		//- - - - - - - - - - - - - - - - - - -
//		//□RegFsmMap.txt
//		//│FsmMap
//		//│       Map0
//		//│            init = State0
//		//│            State0
//		//│                   default
//		//│                           Fsm_State(3N+2) = State0
//		//│                   end
//		//│            end
//		//│       end
//		//│FsmMap
//		//- - - - - - - - - - - - - - - - - - -
//		static const uint8_t TBL_FsmMap_dummy[]={
//		0x80,
//		0x00,0x00,
//		HIBYTE(           0x0000),LOBYTE(           0x0000), 0x00,0x00,0x00,	//Map0
//		0xC0,
//		0x00,0x00,
//		HIBYTE(           0x8000),LOBYTE(           0x8000), 0x00,0x00,0x07,	//State0
//		0x00,0x00,
//		HIBYTE(   Fsm_State_init),LOBYTE(   Fsm_State_init), 0x00,0x00,0x00,	//init = State0
//		0x80,
//		0x00,0x00,
//		HIBYTE(Fsm_Trans_default),LOBYTE(Fsm_Trans_default), 0x00,0x00,0x00,	//default
//		0x40,
//		0x00,0x00,
//		/*Fsm_State*/HIBYTE(0x02),/*Fsm_State*/LOBYTE(0x02), 0x00,0x00,0x00,	//Fsm_State(3N+2) = State0
//		};
//		//-------------------------------------
////{{2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
////		pFsmKey = TBL_FsmMap_dummy;
////		iFsmMap = 0;	//Map0
////↓2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
//		stParam.pFsmKey = TBL_FsmMap_dummy;
//		stParam.iFsmMap = 0;	//Map0
////}}2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
//↓2017/01/06変更:clipfsm.cにて状態マップに初期化Act関数を定義出来るようにした事に伴い、ActObj_New()関数,及び,ST_ActObj_New_Param構造体も変更しました。
//		//-------------------------------------
//		//□FsmMap.txt
//		//│Map0 State0
//		//│     State0
//		//│            default State0
//		//│     end
//		//│end
//		//- - - - - - - - - - - - - - - - - - -
//		//□RegFsmMap.txt
//		//│FsmMap
//		//│       Map0
//		//│            Fsm_Init
//		//│                   Fsm_InitState = State0
//		//│            end
//		//│            State0
//		//│                   default
//		//│                           Fsm_State(3N+2) = State0
//		//│                   end
//		//│            end
//		//│       end
//		//│FsmMap
//		//- - - - - - - - - - - - - - - - - - -
//		static const uint8_t TBL_FsmMap_dummy[]={
//		0x80,
//		0x00,0x00,
//		HIBYTE(           0x0001),LOBYTE(           0x0001),0x00,0x00,0x00,	//Map0
//		0x80,
//		0x00,0x01,
//		HIBYTE(         Fsm_Init),LOBYTE(         Fsm_Init),0x00,0x00,0x0D,	//Fsm_Init
//		HIBYTE(           0x8001),LOBYTE(           0x8001),0x00,0x00,0x00,	//State0
//		0x80,
//		0x00,0x00,
//		HIBYTE(Fsm_Trans_default),LOBYTE(Fsm_Trans_default),0x00,0x00,0x00,	//Fsm_Trans_default
//		0x40,
//		0x00,0x00,
//		HIBYTE(    Fsm_InitState),LOBYTE(    Fsm_InitState),0x00,0x00,0x01,	//Fsm_InitState = State0	Fsm_State(3N+2) = State0	バイナリ表現はどちらも'2 = 1'なので共通化出来る。
//		};
//		//-------------------------------------
//		stParam.pFsmKey = TBL_FsmMap_dummy;
//		stParam.iFsmMap = 1;	//Map0
//↓2017/01/08変更:clipfsm.cにてFsm_Initの値を0x8000⇒0xFFFFに変更した事に伴い、ActObj_New()関数を変更しました。
		//-------------------------------------
		//□FsmMap.txt
		//│Map0 State0
		//│     State0
		//│            default State0
		//│     end
		//│end
		//- - - - - - - - - - - - - - - - - - -
		//□RegFsmMap.txt
		//│FsmMap
		//│       Map0
		//│            State0
		//│                   default
		//│                           Fsm_State(3N+2) = State0
		//│                   end
		//│            end
		//│            Fsm_Init
		//│                   Fsm_InitState = State0
		//│            end
		//│       end
		//│FsmMap
		//- - - - - - - - - - - - - - - - - - -
		static const uint8_t TBL_FsmMap_dummy[]={
		0x80,
		0x00,0x00,
		HIBYTE(           0x0000),LOBYTE(           0x0000),0x00,0x00,0x00,	//Map0
		0x80,
		0x00,0x01,
		HIBYTE(           0x8000),LOBYTE(           0x8000),0x00,0x00,0x05,	//State0
		HIBYTE(         Fsm_Init),LOBYTE(         Fsm_Init),0x00,0x00,0x08,	//Fsm_Init
		0x80,
		0x00,0x00,
		HIBYTE(Fsm_Trans_default),LOBYTE(Fsm_Trans_default),0x00,0x00,0x00,	//Fsm_Trans_default
		0x40,
		0x00,0x00,
		HIBYTE(    Fsm_InitState),LOBYTE(    Fsm_InitState),0x00,0x00,0x00,	//Fsm_InitState = State0	Fsm_State(3N+2) = State0	バイナリ表現はどちらも'2 = 0'なので共通化出来る。
		};
		//-------------------------------------
		stParam.pFsmKey = TBL_FsmMap_dummy;
		stParam.iFsmMap = 0;	//Map0
//}}2017/01/08変更:clipfsm.cにてFsm_Initの値を0x8000⇒0xFFFFに変更した事に伴い、ActObj_New()関数を変更しました。
	}
	//アプリケーションがpPrpKeyを指定しなかった場合は、ダミーとして、空のテーブルを使って初期化する事にしました。
//{{2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
//	if(!pPrpKey) {
//↓2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
	if(!stParam.pPrpKey) {
//}}2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
		//dPrpTblC.exeを使ってプロパティテーブルスクリプトをコンパイルすると、空のテーブルは作成出来ないので、以下のデータは手で作成しました。
		//dPrpTblC.exeを使って作成する事は出来ないデータですが、プロパティテーブルのレジストリデータ構造としては有効です。
		//-------------------------------------
		//□PrpTbl.txt
		//│Table0
		//│    (empty)
		//│end
		//- - - - - - - - - - - - - - - - - - -
		//□RegPrpTbl.txt
		//│PrpTbl
		//│    Table0
		//│        len = 1-1	//本当は(len=0-1)としたいがレジストリ構造上出来ない。1bit(切り上げて1word)分無駄に確保してしまうが動作上は問題無い。
		//│    end
		//│end
		//- - - - - - - - - - - - - - - - - - -
		static const uint8_t TBL_PrpTbl_dummy[]={
		0x80,
		0x00,0x00,
		HIBYTE(           0x0000),LOBYTE(           0x0000), 0x00,0x00,0x00,	//Table0
		0x40,
		0x00,0x00,
		HIBYTE(          Prp_len),LOBYTE(          Prp_len), 0x00,0x00,0x00,	//len = 1-1
		};
		//-------------------------------------
//{{2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
//		pPrpKey = TBL_PrpTbl_dummy;
//		iPrpTbl = 0;	//Table0
//↓2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
		stParam.pPrpKey = TBL_PrpTbl_dummy;
		stParam.iPrpTbl = 0;	//Table0
//}}2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
	}
	//プロパティテープルのワード数を求める。
//{{2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
//	nPrpTblWords = GetPrpTblWords(pPrpKey, iPrpTbl);
//↓2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
	nPrpTblWords = GetPrpTblWords(stParam.pPrpKey, stParam.iPrpTbl);
//}}2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
	//データのワード数を求める。
//{{2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
//	nDataWords = (nDataBytes + 3) >> 2;
//↓2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
	nDataWords = (stParam.nDataBytes + 3) >> 2;
//}}2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
//{{2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
//	//アクターオブジェクトのメモリを確保する。
//	pActObj = calloc(sizeof(ST_ActObj) + sizeof(int) * (nPrpTblWords + nDataWords), 1);
//	if(!pActObj) { DIE(); }
//↓2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
//	//アクターオブジェクトのメモリを確保する。		//	typedef struct _ST_ActObj {
//	pActObj = calloc(sizeof(ST_ActObj) +			//		GNode*		node;				//+0┐
//								//		coroutine_t	co;				//+0┘	//{{2016/12/10追加:アクターオブジェクトに、コルーチンを含めました。}}
//	                 sizeof(ST_FsmObj) +			//	    //	ST_FsmObj	stFsmObj;			//+sizeof(ST_ActObj)
//	                 sizeof(ST_DirSeq) +			//	    //	ST_DirSeq	stDirSeq;			//+sizeof(ST_ActObj)+sizeof(ST_FsmObj)
//	                (sizeof(ST_DirSeqCh) * nDirSeqCh) +	//	    //	ST_DirSeqCh	_TBL_DirSeqCh[nDirSeqCh];	//+sizeof(ST_ActObj)+sizeof(ST_FsmObj)+sizeof(ST_DirSeq)
//	                 sizeof(ST_PrpHdr) +			//	    //	ST_PrpHdr	stPrpHdr;			//+sizeof(ST_ActObj)+sizeof(ST_FsmObj)+sizeof(ST_DirSeq)+(sizeof(ST_DirSeqCh)*nDirSeqCh)
//	                (sizeof(int) * nPrpTblWords) +		//	    //	int		_aPrpTbl[nPrpTblWords];		//+sizeof(ST_ActObj)+sizeof(ST_FsmObj)+sizeof(ST_DirSeq)+(sizeof(ST_DirSeqCh)*nDirSeqCh)+sizeof(ST_PrpHdr)
//	                (sizeof(int) * nDataWords), 1);		//	    //	int		_aData[nDataWords];		//+sizeof(ST_ActObj)+sizeof(ST_FsmObj)+sizeof(ST_DirSeq)+(sizeof(ST_DirSeqCh)*nDirSeqCh)+sizeof(ST_PrpHdr)+(sizeof(int)*nPrpTblWords)
//	if(!pActObj) { DIE(); }					//	} 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/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
	//アクターオブジェクトのメモリを確保する。			//	typedef struct _ST_ActObj {
	pActObj = calloc(sizeof(ST_ActObj) +				//		GNode*		node;				//+0┐
									//		coroutine_t	co;				//+0┘	//{{2016/12/10追加:アクターオブジェクトに、コルーチンを含めました。}}
	                 sizeof(ST_FsmObj) +				//	    //	ST_FsmObj	stFsmObj;			//+sizeof(ST_ActObj)
	                 sizeof(ST_DirSeq) +				//	    //	ST_DirSeq	stDirSeq;			//+sizeof(ST_ActObj)+sizeof(ST_FsmObj)
	                (sizeof(ST_DirSeqCh) * stParam.nDirSeqCh) +	//	    //	ST_DirSeqCh	_TBL_DirSeqCh[nDirSeqCh];	//+sizeof(ST_ActObj)+sizeof(ST_FsmObj)+sizeof(ST_DirSeq)
	                 sizeof(ST_PrpHdr) +				//	    //	ST_PrpHdr	stPrpHdr;			//+sizeof(ST_ActObj)+sizeof(ST_FsmObj)+sizeof(ST_DirSeq)+(sizeof(ST_DirSeqCh)*nDirSeqCh)
	                (sizeof(int) * nPrpTblWords) +			//	    //	int		_aPrpTbl[nPrpTblWords];		//+sizeof(ST_ActObj)+sizeof(ST_FsmObj)+sizeof(ST_DirSeq)+(sizeof(ST_DirSeqCh)*nDirSeqCh)+sizeof(ST_PrpHdr)
	                (sizeof(int) * nDataWords), 1);			//	    //	int		_aData[nDataWords];		//+sizeof(ST_ActObj)+sizeof(ST_FsmObj)+sizeof(ST_DirSeq)+(sizeof(ST_DirSeqCh)*nDirSeqCh)+sizeof(ST_PrpHdr)+(sizeof(int)*nPrpTblWords)
	if(!pActObj) { DIE(); }						//	} 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/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
	//親オブジェクトが指定されていたら…
//{{2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
//	if(pParent) {
//↓2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
	if(stParam.pParent) {
//}}2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
		//子ノードを作成する。
//{{2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
//		pActObj->node = g_node_append_data(pParent->node, pActObj);
//↓2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
		pActObj->node = g_node_append_data(stParam.pParent->node, pActObj);
//}}2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
	//親オブジェクトが指定されていなければ…
	} else {
		//ルートノードを作成する。
		pActObj->node = g_node_new(pActObj);
	}
//{{2016/12/10追加:アクターオブジェクトに、コルーチンを含めました。
	//コルーチンの関数が指定されていたら…
//{{2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
//	if(coFunc) {
//↓2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
	if(stParam.coFunc) {
//}}2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
		//合流可能なコルーチンを作成して、指定されたコルーチンの関数(coFunc)にpActObj引数,及び,coData引数を引き渡す、中継関数(ActObj_New_coFunc)を呼び出します。
//{{2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
//		void* param[3] = { coFunc, pActObj, coData };
//↓2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
		void* param[3] = { stParam.coFunc, pActObj, stParam.coData };
//}}2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
//{{2016/12/14変更:ActObj_New()の引数の、ST_ActObj_New_Param構造体に、coStackSizeフィールドを追加しました。
//		pActObj->co = co_create_joinable_np(ActObj_New_coFunc, param, NULL, 0);
//↓2016/12/14変更:ActObj_New()の引数の、ST_ActObj_New_Param構造体に、coStackSizeフィールドを追加しました。
		pActObj->co = co_create_joinable_np(ActObj_New_coFunc, param, NULL, stParam.coStackSize/*0可*/);
//}}2016/12/14変更:ActObj_New()の引数の、ST_ActObj_New_Param構造体に、coStackSizeフィールドを追加しました。
		co_call(pActObj->co);	//当関数が終了してparam[3]が当関数のスタックフレームから消える前に、ActObj_New_coFunc()にparam[3]の値を取得させます。ActObj_New_coFunc()の最初のco_resume()までの部分が実行されます。
	//コルーチンの関数が指定されていなければ…
	} else {
		//ダミーとして、合流可能,かつ,終了済みの、何もしないコルーチンを作成します。
		// - スタックメモリは確保されないので、無駄にメモリを消費し過ぎる心配は有りません。
		//   詳細は、pcl.c内のco_create_joinable_np()の実装部の、2016/12/10の変更内容を参照して下さい。
		pActObj->co = co_create_joinable_np(NULL, NULL, NULL, 0);
	}
//}}2016/12/10追加:アクターオブジェクトに、コルーチンを含めました。
//{{2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
//	//プロパティヘッダを初期化する。
//	PrpHdr_init(&pActObj->stPrpHdr, pPrpKey, iPrpTbl);
//	//有限状態機械を初期化する。
//	// - この処理を一番最後に行う必要が有る事に注意せよ。
//	//   有限状態機械のstart関数の中でアクターオブジェクトを操作する可能性が有るので、その前にアクターオブジェクトの初期化が完了していなければいけない。
//	FsmObj_Init(&pActObj->stFsmObj, pFsmKey, iFsmMap);
//↓2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
//	//演出シーケンサを初期化する。					//┐
//	DirSeq_Init(ActObj_GetDirSeq(pActObj), fnAct, nDirSeqCh);	//│この初期化順序は必須です。
//	//プロパティヘッダを初期化する。				//│ActObj_GetPrpHdr(pActObj)の処理が、stDirSeq.nChを参照しているからです。
//	PrpHdr_init(ActObj_GetPrpHdr(pActObj), pPrpKey, iPrpTbl);	//┘
//	//有限状態機械を初期化する。
//	// - この処理を一番最後に行う必要が有る事に注意せよ。
//	//   有限状態機械のstart関数の中でアクターオブジェクトを操作する可能性が有るので、その前にアクターオブジェクトの初期化が完了していなければいけない。
//	FsmObj_Init(ActObj_GetFsmObj(pActObj), pFsmKey, iFsmMap);
//↓2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
	//演出シーケンサを初期化する。							//┐
	DirSeq_Init(ActObj_GetDirSeq(pActObj), stParam.fnAct, stParam.nDirSeqCh);	//│この初期化順序は必須です。
	//プロパティヘッダを初期化する。						//│ActObj_GetPrpHdr(pActObj)の処理が、stDirSeq.nChを参照しているからです。
	PrpHdr_init(ActObj_GetPrpHdr(pActObj), stParam.pPrpKey, stParam.iPrpTbl);	//┘
	//有限状態機械を初期化する。
	// - この処理を一番最後に行う必要が有る事に注意せよ。
	//   有限状態機械のstart関数の中でアクターオブジェクトを操作する可能性が有るので、その前にアクターオブジェクトの初期化が完了していなければいけない。
//{{2017/01/06変更:clipfsm.cにて状態マップに初期化Act関数を定義出来るようにした事に伴い、ActObj_New()関数,及び,ST_ActObj_New_Param構造体も変更しました。
//	FsmObj_Init(ActObj_GetFsmObj(pActObj), stParam.pFsmKey, stParam.iFsmMap);
//↓2017/01/06変更:clipfsm.cにて状態マップに初期化Act関数を定義出来るようにした事に伴い、ActObj_New()関数,及び,ST_ActObj_New_Param構造体も変更しました。
	FsmObj_Init(ActObj_GetFsmObj(pActObj), stParam.pFsmKey, stParam.iFsmMap, stParam.pFsmInitParam);
//}}2017/01/06変更:clipfsm.cにて状態マップに初期化Act関数を定義出来るようにした事に伴い、ActObj_New()関数,及び,ST_ActObj_New_Param構造体も変更しました。
//}}2016/12/11変更:ActObj_New()の引数を、構造体で指定するように変更しました。
	//アクターオブジェクトを返す。
	return pActObj;
}
/*--------------------------------------------------------------------------*/
//このアクターオブジェクトと、子アクターオブジェクトを開放する。
void ActObj_Free(ST_ActObj* pActObj) {
//{{2016/12/11変更:コルーチンの関数内で、自分自身のアクターオブジェクトを削除出来るようにしました。
//	ActObj_FreeChildren(pActObj);
//	co_delete(pActObj->co);		//{{2016/12/10追加:アクターオブジェクトに、コルーチンを含めました。}}
//	g_node_destroy(pActObj->node);
//	free(pActObj);
//↓2016/12/11変更:コルーチンの関数内で、自分自身のアクターオブジェクトを削除出来るようにしました。
	coroutine_t co = pActObj->co;	//pActObjのメモリを解放する前に、pActObj->coを取り出しておく。
	co_cleanup_np(co);		//解放するアクターオブジェクトに変更を加える前に、コルーチンのクリーンアップハンドラを実行する。	C++のデストラクタと同様に、解放するアクターオブジェクトのクリーンアップハンドラを実行する時点では、解放するアクターオブジェクトはまだ変更されていないのが自然だと思うので、こういう処理順序にしました。
	ActObj_FreeChildren(pActObj);	//子アクターオブジェクトを解放する。
	g_node_destroy(pActObj->node);	//ノードを解放する。
	free(pActObj);			//pActObjのメモリを解放する。
	if(co != co_current()) {	//解放するアクターオブジェクトのコルーチンが、現在のコンテキストでなければ…
		co_delete(co);		//コルーチンを削除する。
	} else {			//解放するアクターオブジェクトのコルーチンが、現在のコンテキストならば…				アクターオブジェクトのコルーチンの関数内で、自分自身のアクターオブジェクトに対して「ActObj_Free(pActObj)」を実行した場合です。
		co_detach_np(co);	//コルーチンを合流不可能に変更する。									この下のco_exit()で、コルーチンが削除されるようにするためです。
		co_exit();		//コルーチンを終了する。										この処理を一番最後に行う事に注意して下さい。
	}
//}}2016/12/11変更:コルーチンの関数内で、自分自身のアクターオブジェクトを削除出来るようにしました。
}
/*--------------------------------------------------------------------------*/
static void ActObj_Free_func(GNode* node, void* data) {
	ST_ActObj* pActObj = node->data;
	ActObj_Free(pActObj);
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//子アクターオブジェクトを開放する。
//このアクターオブジェクトは開放しない。
void ActObj_FreeChildren(ST_ActObj* pActObj) {
	g_node_children_foreach(pActObj->node, G_TRAVERSE_ALL, ActObj_Free_func, NULL);
}
/*--------------------------------------------------------------------------*/
//親オブジェクトを取得する。
//親オブジェクトが無ければ(=pFsmObjがルートノードならば)NULLを返す。
// - N-ary Treesの仕様では、親ノードにアクセスするには node->parent を直接参照するだけで良いのですが、
//   ST_ActObjの場合 (pActObj->node->parent ? pActObj->node->parent->data : NULL) と長くなってしまい、
//   アプリケーションの中に何度も書くのは煩わしいので、関数として定義する事にしました。
// - N-ary Treesの機能を使って実現出来る事は、なるべく当モジュールの関数としては実装しない方針ですが、
//   上記の理由で、これは、当モジュールの関数として実装しておく方が良いと判断しました。
ST_ActObj* ActObj_GetParent(ST_ActObj* pActObj) {
	GNode* parent = pActObj->node->parent;
	return parent ? parent->data : NULL;
}
/*--------------------------------------------------------------------------*/
//最初の子アクターオブジェクトを取得する。
//<使用例>
//│ST_ActObj_Iter Iter;
//│ST_ActObj* pChild;
//│for(pChild=ActObj_FirstChild(pActObj,&Iter);
//│    pChild;
//│    pChild=ActObj_NextSibling(&Iter)){
//│      〜  //ここでActObj_Free(pChild)を実行しても安全です。
//│}
ST_ActObj* ActObj_FirstChild(ST_ActObj* pActObj, ST_ActObj_Iter* pIter) {
	GNode* node = g_node_first_child(pActObj->node);
	pIter->pNext = node ? node->data : NULL;
	return ActObj_NextSibling(pIter);
}
/*--------------------------------------------------------------------------*/
//次の子アクターオブジェクトを取得する。
ST_ActObj* ActObj_NextSibling(ST_ActObj_Iter* pIter) {
	ST_ActObj* pActObj = pIter->pNext;
	if(pActObj) {
		GNode* node = g_node_next_sibling(pActObj->node);
		pIter->pNext = node ? node->data : NULL;
	}
	return pActObj;
}
/*--------------------------------------------------------------------------*/
//{{2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
////ST_ActObj.stFsmObjへのポインタを、ST_ActObjへのポインタに変換する。
//ST_ActObj* ActObj_FromFsmObj(ST_FsmObj* pFsmObj) {
//	return CONTAINING_RECORD(pFsmObj, ST_ActObj, stFsmObj);
//}
///*--------------------------------------------------------------------------*/
////アプリケーション定義のデータへのポインタを取得する。
//void* ActObj_GetData(ST_ActObj* pActObj) {
//	//プロパティテープルのワード数を求める。
//	int nPrpTblWords = GetPrpTblWords(pActObj->stPrpHdr.pPrpKey, pActObj->stPrpHdr.iTbl);
//	//pActObj->stPrpHdrのプロパティテーブルの後にデータが有る。
//	return (int*)(&pActObj->stPrpHdr + 1) + nPrpTblWords;
//}
//↓2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
//ST_ActObjの先頭アドレスから、stFsmObjフィールドのアドレスを取得する。
ST_FsmObj* ActObj_GetFsmObj(ST_ActObj* pActObj) {
	return (ST_FsmObj*)((char*)pActObj + sizeof(ST_ActObj));		//		GNode*		node;				//+0
}
/*--------------------------------------------------------------------------*/
//stFsmObjフィールドのアドレスから、ST_ActObjの先頭アドレスを取得する。
ST_ActObj* ActObj_FromFsmObj(ST_FsmObj* pFsmObj) {
	return (ST_ActObj*)((char*)pFsmObj - sizeof(ST_ActObj));		//		GNode*		node;				//+0
}
/*--------------------------------------------------------------------------*/
//ST_ActObjの先頭アドレスから、stDirSeqフィールドのアドレスを取得する。
ST_DirSeq* ActObj_GetDirSeq(ST_ActObj* pActObj) {
	return (ST_DirSeq*)((char*)pActObj + sizeof(ST_ActObj)			//		GNode*		node;				//+0
	                                   + sizeof(ST_FsmObj));		//	    //	ST_FsmObj	stFsmObj;			//+sizeof(ST_ActObj)
}
/*--------------------------------------------------------------------------*/
//stDirSeqフィールドのアドレスから、ST_ActObjの先頭アドレスを取得する。
ST_ActObj* ActObj_FromDirSeq(ST_DirSeq* pDirSeq) {
	return (ST_ActObj*)((char*)pDirSeq - sizeof(ST_ActObj)			//		GNode*		node;				//+0
	                                   - sizeof(ST_FsmObj));		//	    //	ST_FsmObj	stFsmObj;			//+sizeof(ST_ActObj)
}
/*--------------------------------------------------------------------------*/
//ST_ActObjの先頭アドレスから、stPrpHdrフィールドのアドレスを取得する。
ST_PrpHdr* ActObj_GetPrpHdr(ST_ActObj* pActObj) {
	ST_DirSeq* pDirSeq = ActObj_GetDirSeq(pActObj);				//	    //	ST_DirSeq	stDirSeq;			//+sizeof(ST_ActObj)+sizeof(ST_FsmObj)
	return (ST_PrpHdr*)&pDirSeq->TBL_DirSeqCh[pDirSeq->nCh];		//	    //	ST_DirSeqCh	_TBL_DirSeqCh[nDirSeqCh];	//+sizeof(ST_ActObj)+sizeof(ST_FsmObj)+sizeof(ST_DirSeq)
}
/*--------------------------------------------------------------------------*/
//ST_ActObjの先頭アドレスから、アプリケーション定義のデータのアドレスを取得する。
void* ActObj_GetData(ST_ActObj* pActObj) {
	//プロパティヘッダのアドレスを取得する。
	ST_PrpHdr* pPrpHdr = ActObj_GetPrpHdr(pActObj);
	//プロパティテープルのワード数を求める。
	int nPrpTblWords = GetPrpTblWords(pPrpHdr->pPrpKey, pPrpHdr->iTbl);
	//pActObj->stPrpHdrのプロパティテーブルの後にデータが有る。
	return (int*)(pPrpHdr + 1) + nPrpTblWords;
}
//}}2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
/*--------------------------------------------------------------------------*/
//{{2016/12/10追加:アクターオブジェクトに、コルーチンを含めました。
static int ActObj_CallCoroutine_func(GNode* node, void* data) {
	ST_ActObj* pActObj = node->data;
	ActObj_CallCoroutine(pActObj);
	return 0;
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//このアクターオブジェクトのコルーチンを実行する。
void ActObj_CallCoroutine(ST_ActObj* pActObj) {
	co_call_joinable_np(pActObj->co);
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//子アクターオブジェクトのコルーチンを実行する。
//このアクターオブジェクト,及び,直接の子以外の子孫アクターオブジェクトのコルーチンは実行しない。
void ActObj_CallCoroutineToChildren(ST_ActObj* pActObj) {
	g_node_children_foreach(pActObj->node, G_TRAVERSE_ALL, (void(*)(GNode*,void*))ActObj_CallCoroutine_func, NULL);
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//このアクターオブジェクト,及び,子孫アクターオブジェクトのコルーチンを実行する。
void ActObj_CallCoroutineToTree(ST_ActObj* pActObj) {
    #ifndef GNODE_SAFE_SELF_DESTRUCTION_DURING_PRE_ORDER_TRAVERSING
	g_node_traverse(pActObj->node, G_POST_ORDER, G_TRAVERSE_ALL, -1/*depth*/, ActObj_CallCoroutine_func, NULL);
	//                             ~~~~~~~~~~~~コールバック関数が、コールバック関数に渡されたノードを削除する可能性が有るので、G_PRE_ORDERは不可です。詳細はg_node_traverse()のコメントを参照して下さい。
	//                                         G_POST_ORDER,又は,G_LEVEL_ORDERのどちらでも正常に動作しますが、G_LEVEL_ORDERよりもG_POST_ORDERの方が効率が良いので、G_POST_ORDERを使う事にしました。
    #else //GNODE_SAFE_SELF_DESTRUCTION_DURING_PRE_ORDER_TRAVERSING
	g_node_traverse(pActObj->node, G_PRE_ORDER, G_TRAVERSE_ALL, -1/*depth*/, ActObj_CallCoroutine_func, NULL);
	//                             ~~~~~~~~~~~G_PRE_ORDER内でnode自身を削除出来るようになったので、G_POST_ORDERやG_LEVEL_ORDERよりも自然である、G_PRE_ORDERを使用する事にしました。
	//                                        G_PRE_ORDER内でnode自身を削除出来るようになった経緯については、gnode.h内の'Sat Aug 27 21:24:43 JST 2016'のコメントを参照して下さい。
    #endif//GNODE_SAFE_SELF_DESTRUCTION_DURING_PRE_ORDER_TRAVERSING
}
//}}2016/12/10追加:アクターオブジェクトに、コルーチンを含めました。
/*--------------------------------------------------------------------------*/
//{{2016/09/05追加:64ビット対応のために、ActObj_ApplyTrans_func()へのパラメータを簡易的に(void*)[2]で渡すのをやめて、パラメータ用の構造体ST_ActObj_ApplyTrans_func_Paramを定義しました。
typedef struct _ST_ActObj_ApplyTrans_func_Param {
	int	iFsmTrans;
	void*	pParam;
} ST_ActObj_ApplyTrans_func_Param;
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//}}2016/09/05追加:64ビット対応のために、ActObj_ApplyTrans_func()へのパラメータを簡易的に(void*)[2]で渡すのをやめて、パラメータ用の構造体ST_ActObj_ApplyTrans_func_Paramを定義しました。
static int ActObj_ApplyTrans_func(GNode* node, void* data) {
	ST_ActObj* pActObj = node->data;
//{{2016/09/05追加:64ビット対応のために、ActObj_ApplyTrans_func()へのパラメータを簡易的に(void*)[2]で渡すのをやめて、パラメータ用の構造体ST_ActObj_ApplyTrans_func_Paramを定義しました。
//	void** d = data;		//┐
//	int iFsmTrans = (int)d[0];	//├←ActObj_ApplyTransToChildren(),ActObj_ApplyTransToTree()
//	void* pParam  =      d[1];	//┘
//	ActObj_ApplyTrans(pActObj, iFsmTrans, pParam);
//↓2016/09/05追加:64ビット対応のために、ActObj_ApplyTrans_func()へのパラメータを簡易的に(void*)[2]で渡すのをやめて、パラメータ用の構造体ST_ActObj_ApplyTrans_func_Paramを定義しました。
	ST_ActObj_ApplyTrans_func_Param* p = data;	//←ActObj_ApplyTransToChildren(),ActObj_ApplyTransToTree()
	ActObj_ApplyTrans(pActObj, p->iFsmTrans, p->pParam);
//}}2016/09/05追加:64ビット対応のために、ActObj_ApplyTrans_func()へのパラメータを簡易的に(void*)[2]で渡すのをやめて、パラメータ用の構造体ST_ActObj_ApplyTrans_func_Paramを定義しました。
	return 0;
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//このアクターオブジェクトの有限状態機械に、遷移を適用する。
void ActObj_ApplyTrans(ST_ActObj* pActObj, int iFsmTrans, void* pParam) {
//{{2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
//	FsmObj_ApplyTrans(&pActObj->stFsmObj, iFsmTrans, pParam);
//↓2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
	FsmObj_ApplyTrans(ActObj_GetFsmObj(pActObj), iFsmTrans, pParam);
//}}2016/09/11変更:アクターオブジェクトに、演出シーケンサを含めました。
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//子アクターオブジェクトの有限状態機械に、遷移を適用する。
//このアクターオブジェクト,及び,直接の子以外の子孫アクターオブジェクトの有限状態機械には、遷移を適用しない。
void ActObj_ApplyTransToChildren(ST_ActObj* pActObj, int iFsmTrans, void* pParam) {
//{{2016/09/05追加:64ビット対応のために、ActObj_ApplyTrans_func()へのパラメータを簡易的に(void*)[2]で渡すのをやめて、パラメータ用の構造体ST_ActObj_ApplyTrans_func_Paramを定義しました。
//	void* d[2];			//┐
//	d[0] = (void*)iFsmTrans;	//├→ActObj_ApplyTrans_func()
//	d[1] =        pParam;		//┘
//	g_node_children_foreach(pActObj->node, G_TRAVERSE_ALL, (void(*)(GNode*,void*))ActObj_ApplyTrans_func, d);
//↓2016/09/05追加:64ビット対応のために、ActObj_ApplyTrans_func()へのパラメータを簡易的に(void*)[2]で渡すのをやめて、パラメータ用の構造体ST_ActObj_ApplyTrans_func_Paramを定義しました。
	ST_ActObj_ApplyTrans_func_Param p;	//┐
	p.iFsmTrans = iFsmTrans;		//├→ActObj_ApplyTrans_func()
	p.pParam    = pParam;			//┘
	g_node_children_foreach(pActObj->node, G_TRAVERSE_ALL, (void(*)(GNode*,void*))ActObj_ApplyTrans_func, &p);
//}}2016/09/05追加:64ビット対応のために、ActObj_ApplyTrans_func()へのパラメータを簡易的に(void*)[2]で渡すのをやめて、パラメータ用の構造体ST_ActObj_ApplyTrans_func_Paramを定義しました。
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//このアクターオブジェクト,及び,子孫アクターオブジェクトの有限状態機械に、遷移を適用する。
void ActObj_ApplyTransToTree(ST_ActObj* pActObj, int iFsmTrans, void* pParam) {
//{{2016/09/05追加:64ビット対応のために、ActObj_ApplyTrans_func()へのパラメータを簡易的に(void*)[2]で渡すのをやめて、パラメータ用の構造体ST_ActObj_ApplyTrans_func_Paramを定義しました。
//	void* d[2];			//┐
//	d[0] = (void*)iFsmTrans;	//├→ActObj_ApplyTrans_func()
//	d[1] =        pParam;		//┘
//  //{{2016/08/27追加:gnode.hにG_PRE_ORDER内でnode自身を削除出来るようにするための独自拡張を追加した事に伴い、ActObj_ApplyTransToTree()がG_POST_ORDERでなくG_PRE_ORDERを使用するように変更しました。
//  #ifndef GNODE_SAFE_SELF_DESTRUCTION_DURING_PRE_ORDER_TRAVERSING
//  //}}2016/08/27追加:gnode.hにG_PRE_ORDER内でnode自身を削除出来るようにするための独自拡張を追加した事に伴い、ActObj_ApplyTransToTree()がG_POST_ORDERでなくG_PRE_ORDERを使用するように変更しました。
//	g_node_traverse(pActObj->node, G_POST_ORDER, G_TRAVERSE_ALL, -1/*depth*/, ActObj_ApplyTrans_func, d);
//	//                             ~~~~~~~~~~~~コールバック関数が、コールバック関数に渡されたノードを削除する可能性が有るので、G_PRE_ORDERは不可です。詳細はg_node_traverse()のコメントを参照して下さい。
//	//                                         G_POST_ORDER,又は,G_LEVEL_ORDERのどちらでも正常に動作しますが、G_LEVEL_ORDERよりもG_POST_ORDERの方が効率が良いので、G_POST_ORDERを使う事にしました。
//  //{{2016/08/27追加:gnode.hにG_PRE_ORDER内でnode自身を削除出来るようにするための独自拡張を追加した事に伴い、ActObj_ApplyTransToTree()がG_POST_ORDERでなくG_PRE_ORDERを使用するように変更しました。
//  #else //GNODE_SAFE_SELF_DESTRUCTION_DURING_PRE_ORDER_TRAVERSING
//	g_node_traverse(pActObj->node, G_PRE_ORDER, G_TRAVERSE_ALL, -1/*depth*/, ActObj_ApplyTrans_func, d);
//	//                             ~~~~~~~~~~~G_PRE_ORDER内でnode自身を削除出来るようになったので、G_POST_ORDERやG_LEVEL_ORDERよりも自然である、G_PRE_ORDERを使用する事にしました。
//	//                                        G_PRE_ORDER内でnode自身を削除出来るようになった経緯については、gnode.h内の'Sat Aug 27 21:24:43 JST 2016'のコメントを参照して下さい。
//  #endif//GNODE_SAFE_SELF_DESTRUCTION_DURING_PRE_ORDER_TRAVERSING
//  //}}2016/08/27追加:gnode.hにG_PRE_ORDER内でnode自身を削除出来るようにするための独自拡張を追加した事に伴い、ActObj_ApplyTransToTree()がG_POST_ORDERでなくG_PRE_ORDERを使用するように変更しました。
//↓2016/09/05追加:64ビット対応のために、ActObj_ApplyTrans_func()へのパラメータを簡易的に(void*)[2]で渡すのをやめて、パラメータ用の構造体ST_ActObj_ApplyTrans_func_Paramを定義しました。
	ST_ActObj_ApplyTrans_func_Param p;	//┐
	p.iFsmTrans = iFsmTrans;		//├→ActObj_ApplyTrans_func()
	p.pParam    = pParam;			//┘
    //{{2016/08/27追加:gnode.hにG_PRE_ORDER内でnode自身を削除出来るようにするための独自拡張を追加した事に伴い、ActObj_ApplyTransToTree()がG_POST_ORDERでなくG_PRE_ORDERを使用するように変更しました。
    #ifndef GNODE_SAFE_SELF_DESTRUCTION_DURING_PRE_ORDER_TRAVERSING
    //}}2016/08/27追加:gnode.hにG_PRE_ORDER内でnode自身を削除出来るようにするための独自拡張を追加した事に伴い、ActObj_ApplyTransToTree()がG_POST_ORDERでなくG_PRE_ORDERを使用するように変更しました。
	g_node_traverse(pActObj->node, G_POST_ORDER, G_TRAVERSE_ALL, -1/*depth*/, ActObj_ApplyTrans_func, &p);
	//                             ~~~~~~~~~~~~コールバック関数が、コールバック関数に渡されたノードを削除する可能性が有るので、G_PRE_ORDERは不可です。詳細はg_node_traverse()のコメントを参照して下さい。
	//                                         G_POST_ORDER,又は,G_LEVEL_ORDERのどちらでも正常に動作しますが、G_LEVEL_ORDERよりもG_POST_ORDERの方が効率が良いので、G_POST_ORDERを使う事にしました。
    //{{2016/08/27追加:gnode.hにG_PRE_ORDER内でnode自身を削除出来るようにするための独自拡張を追加した事に伴い、ActObj_ApplyTransToTree()がG_POST_ORDERでなくG_PRE_ORDERを使用するように変更しました。
    #else //GNODE_SAFE_SELF_DESTRUCTION_DURING_PRE_ORDER_TRAVERSING
	g_node_traverse(pActObj->node, G_PRE_ORDER, G_TRAVERSE_ALL, -1/*depth*/, ActObj_ApplyTrans_func, &p);
	//                             ~~~~~~~~~~~G_PRE_ORDER内でnode自身を削除出来るようになったので、G_POST_ORDERやG_LEVEL_ORDERよりも自然である、G_PRE_ORDERを使用する事にしました。
	//                                        G_PRE_ORDER内でnode自身を削除出来るようになった経緯については、gnode.h内の'Sat Aug 27 21:24:43 JST 2016'のコメントを参照して下さい。
    #endif//GNODE_SAFE_SELF_DESTRUCTION_DURING_PRE_ORDER_TRAVERSING
    //}}2016/08/27追加:gnode.hにG_PRE_ORDER内でnode自身を削除出来るようにするための独自拡張を追加した事に伴い、ActObj_ApplyTransToTree()がG_POST_ORDERでなくG_PRE_ORDERを使用するように変更しました。
//}}2016/09/05追加:64ビット対応のために、ActObj_ApplyTrans_func()へのパラメータを簡易的に(void*)[2]で渡すのをやめて、パラメータ用の構造体ST_ActObj_ApplyTrans_func_Paramを定義しました。
}
/*--------------------------------------------------------------------------*/
//{{2016/09/11追加:アクターオブジェクトに、演出シーケンサを含めました。
static int ActObj_ExecDirSeq_func(GNode* node, void* data) {
	ST_ActObj* pActObj = node->data;
	ActObj_ExecDirSeq(pActObj);
	return 0;
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//このアクターオブジェクトの演出シーケンサを実行する。
void ActObj_ExecDirSeq(ST_ActObj* pActObj) {
	DirSeq_Exec(ActObj_GetDirSeq(pActObj));
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//子アクターオブジェクトの演出シーケンサを実行する。
//このアクターオブジェクト,及び,直接の子以外の子孫アクターオブジェクトの演出シーケンサは実行しない。
void ActObj_ExecDirSeqToChildren(ST_ActObj* pActObj) {
	g_node_children_foreach(pActObj->node, G_TRAVERSE_ALL, (void(*)(GNode*,void*))ActObj_ExecDirSeq_func, NULL);
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//このアクターオブジェクト,及び,子孫アクターオブジェクトの演出シーケンサを実行する。
void ActObj_ExecDirSeqToTree(ST_ActObj* pActObj) {
    #ifndef GNODE_SAFE_SELF_DESTRUCTION_DURING_PRE_ORDER_TRAVERSING
	g_node_traverse(pActObj->node, G_POST_ORDER, G_TRAVERSE_ALL, -1/*depth*/, ActObj_ExecDirSeq_func, NULL);
	//                             ~~~~~~~~~~~~コールバック関数が、コールバック関数に渡されたノードを削除する可能性が有るので、G_PRE_ORDERは不可です。詳細はg_node_traverse()のコメントを参照して下さい。
	//                                         G_POST_ORDER,又は,G_LEVEL_ORDERのどちらでも正常に動作しますが、G_LEVEL_ORDERよりもG_POST_ORDERの方が効率が良いので、G_POST_ORDERを使う事にしました。
    #else //GNODE_SAFE_SELF_DESTRUCTION_DURING_PRE_ORDER_TRAVERSING
	g_node_traverse(pActObj->node, G_PRE_ORDER, G_TRAVERSE_ALL, -1/*depth*/, ActObj_ExecDirSeq_func, NULL);
	//                             ~~~~~~~~~~~G_PRE_ORDER内でnode自身を削除出来るようになったので、G_POST_ORDERやG_LEVEL_ORDERよりも自然である、G_PRE_ORDERを使用する事にしました。
	//                                        G_PRE_ORDER内でnode自身を削除出来るようになった経緯については、gnode.h内の'Sat Aug 27 21:24:43 JST 2016'のコメントを参照して下さい。
    #endif//GNODE_SAFE_SELF_DESTRUCTION_DURING_PRE_ORDER_TRAVERSING
}
//}}2016/09/11追加:アクターオブジェクトに、演出シーケンサを含めました。
/****************************************************************************
 *	ユーティリティ関数(有限状態機械)
 ****************************************************************************/
#ifndef PIECE
void ActObj_ApplyTrans_l(ST_ActObj* pActObj, int iFsmTrans, int argc, ...) {
	va_list ap;
	va_start(ap, argc);
	ActObj_ApplyTrans_a(pActObj, iFsmTrans, argc, ap);
	va_end(ap);
}
void ActObj_ApplyTrans_a(ST_ActObj* pActObj, int iFsmTrans, int argc, va_list ap) {
	void* argv[16/*調整可*/];	//実用上、パラメータ数が16以下と考えて充分だろう。不足した場合は増やせ。
	int i;
	if((unsigned)argc > (unsigned)ARRAY_SIZE(argv)) { DIE(); }	//ここで停止した場合は、argv[]の要素数を増やせ。
	for(i = 0; i < argc; i++) { argv[i] = va_arg(ap, void*); }
	ActObj_ApplyTrans_v(pActObj, iFsmTrans, argc, argv);
}
void ActObj_ApplyTrans_v(ST_ActObj* pActObj, int iFsmTrans, int argc, void* argv[/*argc*/]) {
	ST_FsmArg fsmArg = { argc, argv };
	ActObj_ApplyTrans(pActObj, iFsmTrans, &fsmArg);
}
#else //PIECE
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);
void ActObj_ApplyTrans_v(ST_ActObj* pActObj, int iFsmTrans, int argc, void* argv[/*argc*/]);
asm("
		.code
		.align		1
		.global		ActObj_ApplyTrans_l
		.global		ActObj_ApplyTrans_a
		.global		ActObj_ApplyTrans_v
ActObj_ApplyTrans_l:
		;//%r12    := pActObj
		;//%r13    := iFsmTrans
		;//[%sp+0] := retp
		;//[%sp+4] := argc
		;//[%sp+8] := ...
		xld.w		%r14, [%sp+4]			;//%r14 := argc
		xadd		%r15, %sp, 8			;//%r15 := ap = &...
ActObj_ApplyTrans_a:
		;//%r12    := pActObj
		;//%r13    := iFsmTrans
		;//%r14    := argc
		;//%r15    := ap
ActObj_ApplyTrans_v:
		xsub		%sp, %sp, 8
		;//%r12    := pActObj
		;//%r13    := iFsmTrans
		;//%r14    := argc
		;//%r15    := argv
		;//[%sp+0] := (fsmArg.argc)
		;//[%sp+4] := (fsmArg.argv)
		xld.w		[%sp+0], %r14			;//[%sp+0] := fsmArg.argc = argc
		xld.w		[%sp+4], %r15			;//[%sp+4] := fsmArg.argv = argv
		ld.w		%r14, %sp			;//%r14    := pParam = &fsmArg
		xcall		ActObj_ApplyTrans		;//ActObj_ApplyTrans(pActObj, iFsmTrans, pParam)
		xadd		%sp, %sp, 8
		ret
");
#endif//PIECE
/*--------------------------------------------------------------------------*/
#ifndef PIECE
void ActObj_ApplyTransToChildren_l(ST_ActObj* pActObj, int iFsmTrans, int argc, ...) {
	va_list ap;
	va_start(ap, argc);
	ActObj_ApplyTransToChildren_a(pActObj, iFsmTrans, argc, ap);
	va_end(ap);
}
void ActObj_ApplyTransToChildren_a(ST_ActObj* pActObj, int iFsmTrans, int argc, va_list ap) {
	void* argv[16/*調整可*/];	//実用上、パラメータ数が16以下と考えて充分だろう。不足した場合は増やせ。
	int i;
	if((unsigned)argc > (unsigned)ARRAY_SIZE(argv)) { DIE(); }	//ここで停止した場合は、argv[]の要素数を増やせ。
	for(i = 0; i < argc; i++) { argv[i] = va_arg(ap, void*); }
	ActObj_ApplyTransToChildren_v(pActObj, iFsmTrans, argc, argv);
}
void ActObj_ApplyTransToChildren_v(ST_ActObj* pActObj, int iFsmTrans, int argc, void* argv[/*argc*/]) {
	ST_FsmArg fsmArg = { argc, argv };
	ActObj_ApplyTransToChildren(pActObj, iFsmTrans, &fsmArg);
}
#else //PIECE
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);
void ActObj_ApplyTransToChildren_v(ST_ActObj* pActObj, int iFsmTrans, int argc, void* argv[/*argc*/]);
asm("
		.code
		.align		1
		.global		ActObj_ApplyTransToChildren_l
		.global		ActObj_ApplyTransToChildren_a
		.global		ActObj_ApplyTransToChildren_v
ActObj_ApplyTransToChildren_l:
		;//%r12    := pActObj
		;//%r13    := iFsmTrans
		;//[%sp+0] := retp
		;//[%sp+4] := argc
		;//[%sp+8] := ...
		xld.w		%r14, [%sp+4]			;//%r14 := argc
		xadd		%r15, %sp, 8			;//%r15 := ap = &...
ActObj_ApplyTransToChildren_a:
		;//%r12    := pActObj
		;//%r13    := iFsmTrans
		;//%r14    := argc
		;//%r15    := ap
ActObj_ApplyTransToChildren_v:
		xsub		%sp, %sp, 8
		;//%r12    := pActObj
		;//%r13    := iFsmTrans
		;//%r14    := argc
		;//%r15    := argv
		;//[%sp+0] := (fsmArg.argc)
		;//[%sp+4] := (fsmArg.argv)
		xld.w		[%sp+0], %r14			;//[%sp+0] := fsmArg.argc = argc
		xld.w		[%sp+4], %r15			;//[%sp+4] := fsmArg.argv = argv
		ld.w		%r14, %sp			;//%r14    := pParam = &fsmArg
		xcall		ActObj_ApplyTransToChildren	;//ActObj_ApplyTransToChildren(pActObj, iFsmTrans, pParam)
		xadd		%sp, %sp, 8
		ret
");
#endif//PIECE
/*--------------------------------------------------------------------------*/
#ifndef PIECE
void ActObj_ApplyTransToTree_l(ST_ActObj* pActObj, int iFsmTrans, int argc, ...) {
	va_list ap;
	va_start(ap, argc);
	ActObj_ApplyTransToTree_a(pActObj, iFsmTrans, argc, ap);
	va_end(ap);
}
void ActObj_ApplyTransToTree_a(ST_ActObj* pActObj, int iFsmTrans, int argc, va_list ap) {
	void* argv[16/*調整可*/];	//実用上、パラメータ数が16以下と考えて充分だろう。不足した場合は増やせ。
	int i;
	if((unsigned)argc > (unsigned)ARRAY_SIZE(argv)) { DIE(); }	//ここで停止した場合は、argv[]の要素数を増やせ。
	for(i = 0; i < argc; i++) { argv[i] = va_arg(ap, void*); }
	ActObj_ApplyTransToTree_v(pActObj, iFsmTrans, argc, argv);
}
void ActObj_ApplyTransToTree_v(ST_ActObj* pActObj, int iFsmTrans, int argc, void* argv[/*argc*/]) {
	ST_FsmArg fsmArg = { argc, argv };
	ActObj_ApplyTransToTree(pActObj, iFsmTrans, &fsmArg);
}
#else //PIECE
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);
void ActObj_ApplyTransToTree_v(ST_ActObj* pActObj, int iFsmTrans, int argc, void* argv[/*argc*/]);
asm("
		.code
		.align		1
		.global		ActObj_ApplyTransToTree_l
		.global		ActObj_ApplyTransToTree_a
		.global		ActObj_ApplyTransToTree_v
ActObj_ApplyTransToTree_l:
		;//%r12    := pActObj
		;//%r13    := iFsmTrans
		;//[%sp+0] := retp
		;//[%sp+4] := argc
		;//[%sp+8] := ...
		xld.w		%r14, [%sp+4]			;//%r14 := argc
		xadd		%r15, %sp, 8			;//%r15 := ap = &...
ActObj_ApplyTransToTree_a:
		;//%r12    := pActObj
		;//%r13    := iFsmTrans
		;//%r14    := argc
		;//%r15    := ap
ActObj_ApplyTransToTree_v:
		xsub		%sp, %sp, 8
		;//%r12    := pActObj
		;//%r13    := iFsmTrans
		;//%r14    := argc
		;//%r15    := argv
		;//[%sp+0] := (fsmArg.argc)
		;//[%sp+4] := (fsmArg.argv)
		xld.w		[%sp+0], %r14			;//[%sp+0] := fsmArg.argc = argc
		xld.w		[%sp+4], %r15			;//[%sp+4] := fsmArg.argv = argv
		ld.w		%r14, %sp			;//%r14    := pParam = &fsmArg
		xcall		ActObj_ApplyTransToTree		;//ActObj_ApplyTransToTree(pActObj, iFsmTrans, pParam)
		xadd		%sp, %sp, 8
		ret
");
#endif//PIECE
/****************************************************************************
 *	ユーティリティ関数(プロパティテーブル)
 ****************************************************************************/
static int ActObj_InitAttr_func(GNode* node, void* data) {
	ST_ActObj* pActObj = node->data;
	const int* aAttr/*[inclAttr,...,]-1,[exclAttr,...,]-1*/ = data;
	PrpHdr_init_attr_v(ActObj_GetPrpHdr(pActObj), aAttr);
	return 0;
}
/*--------------------------------------------------------------------------*/
#ifndef PIECE
void ActObj_InitAttr_l(ST_ActObj* pActObj, ...) {
	va_list ap;
	va_start(ap, pActObj);
	ActObj_InitAttr_a(pActObj, ap);
	va_end(ap);
}
void ActObj_InitAttr_a(ST_ActObj* pActObj, va_list ap) {
	int aAttr[(14+2)/*調整可*/], i = 0, j = 0;	//実用上、必須属性リストと拒否属性リストが14以下(終端(-1)を含めて16以下)と考えて充分だろう。不足した場合は増やせ。
	for(;;) {
		if((aAttr[i] = va_arg(ap, int)) == -1) { if(++j == 2/*必須属性リスト,拒否属性リスト*/) { break; } }
		if(++i >= ARRAY_SIZE(aAttr)) { DIE(); }	//ここで停止した場合は、aAttr[]不足か,又は,呼出し側が終端を忘れている。おそらく後者だろう。
	}
	ActObj_InitAttr_v(pActObj, aAttr);
}
#else //PIECE
void ActObj_InitAttr_l(ST_ActObj* pActObj, ...);
void ActObj_InitAttr_a(ST_ActObj* pActObj, va_list ap);
asm("
		.code
		.align		1
		.global		ActObj_InitAttr_l
		.global		ActObj_InitAttr_a
ActObj_InitAttr_l:
		;//[%sp+0] := retp
		;//[%sp+4] := pActObj
		;//[%sp+8] := ...
		xld.w		%r12, [%sp+4]			;//%r12 := pActObj
		xadd		%r13, %sp, 8			;//%r13 := ap = &...
ActObj_InitAttr_a:
		;//%r12    := pActObj
		;//%r13    := ap
		xjp		ActObj_InitAttr_v
");
#endif//PIECE
void ActObj_InitAttr_v(ST_ActObj* pActObj, const int* aAttr/*[inclAttr,...,]-1,[exclAttr,...,]-1*/) {
	ActObj_InitAttr_func(pActObj->node, /*const警告抑制*/(void*)aAttr);
}
/*--------------------------------------------------------------------------*/
#ifndef PIECE
void ActObj_InitAttrToChildren_l(ST_ActObj* pActObj, ...) {
	va_list ap;
	va_start(ap, pActObj);
	ActObj_InitAttrToChildren_a(pActObj, ap);
	va_end(ap);
}
void ActObj_InitAttrToChildren_a(ST_ActObj* pActObj, va_list ap) {
	int aAttr[(14+2)/*調整可*/], i = 0, j = 0;	//実用上、必須属性リストと拒否属性リストが14以下(終端(-1)を含めて16以下)と考えて充分だろう。不足した場合は増やせ。
	for(;;) {
		if((aAttr[i] = va_arg(ap, int)) == -1) { if(++j == 2/*必須属性リスト,拒否属性リスト*/) { break; } }
		if(++i >= ARRAY_SIZE(aAttr)) { DIE(); }	//ここで停止した場合は、aAttr[]不足か,又は,呼出し側が終端を忘れている。おそらく後者だろう。
	}
	ActObj_InitAttrToChildren_v(pActObj, aAttr);
}
#else //PIECE
void ActObj_InitAttrToChildren_l(ST_ActObj* pActObj, ...);
void ActObj_InitAttrToChildren_a(ST_ActObj* pActObj, va_list ap);
asm("
		.code
		.align		1
		.global		ActObj_InitAttrToChildren_l
		.global		ActObj_InitAttrToChildren_a
ActObj_InitAttrToChildren_l:
		;//[%sp+0] := retp
		;//[%sp+4] := pActObj
		;//[%sp+8] := ...
		xld.w		%r12, [%sp+4]			;//%r12 := pActObj
		xadd		%r13, %sp, 8			;//%r13 := ap = &...
ActObj_InitAttrToChildren_a:
		;//%r12    := pActObj
		;//%r13    := ap
		xjp		ActObj_InitAttrToChildren_v
");
#endif//PIECE
void ActObj_InitAttrToChildren_v(ST_ActObj* pActObj, const int* aAttr/*[inclAttr,...,]-1,[exclAttr,...,]-1*/) {
	g_node_children_foreach(pActObj->node, G_TRAVERSE_ALL, (void(*)(GNode*,void*))ActObj_InitAttr_func, /*const警告抑制*/(void*)aAttr);
}
/*--------------------------------------------------------------------------*/
#ifndef PIECE
void ActObj_InitAttrToTree_l(ST_ActObj* pActObj, ...) {
	va_list ap;
	va_start(ap, pActObj);
	ActObj_InitAttrToTree_a(pActObj, ap);
	va_end(ap);
}
void ActObj_InitAttrToTree_a(ST_ActObj* pActObj, va_list ap) {
	int aAttr[(14+2)/*調整可*/], i = 0, j = 0;	//実用上、必須属性リストと拒否属性リストが14以下(終端(-1)を含めて16以下)と考えて充分だろう。不足した場合は増やせ。
	for(;;) {
		if((aAttr[i] = va_arg(ap, int)) == -1) { if(++j == 2/*必須属性リスト,拒否属性リスト*/) { break; } }
		if(++i >= ARRAY_SIZE(aAttr)) { DIE(); }	//ここで停止した場合は、aAttr[]不足か,又は,呼出し側が終端を忘れている。おそらく後者だろう。
	}
	ActObj_InitAttrToTree_v(pActObj, aAttr);
}
#else //PIECE
void ActObj_InitAttrToTree_l(ST_ActObj* pActObj, ...);
void ActObj_InitAttrToTree_a(ST_ActObj* pActObj, va_list ap);
asm("
		.code
		.align		1
		.global		ActObj_InitAttrToTree_l
		.global		ActObj_InitAttrToTree_a
ActObj_InitAttrToTree_l:
		;//[%sp+0] := retp
		;//[%sp+4] := pActObj
		;//[%sp+8] := ...
		xld.w		%r12, [%sp+4]			;//%r12 := pActObj
		xadd		%r13, %sp, 8			;//%r13 := ap = &...
ActObj_InitAttrToTree_a:
		;//%r12    := pActObj
		;//%r13    := ap
		xjp		ActObj_InitAttrToTree_v
");
#endif//PIECE
void ActObj_InitAttrToTree_v(ST_ActObj* pActObj, const int* aAttr/*[inclAttr,...,]-1,[exclAttr,...,]-1*/) {
    #ifndef GNODE_SAFE_SELF_DESTRUCTION_DURING_PRE_ORDER_TRAVERSING
	g_node_traverse(pActObj->node, G_POST_ORDER, G_TRAVERSE_ALL, -1/*depth*/, ActObj_InitAttr_func, /*const警告抑制*/(void*)aAttr);
	//                             ~~~~~~~~~~~~コールバック関数が、コールバック関数に渡されたノードを削除する可能性が有るので、G_PRE_ORDERは不可です。詳細はg_node_traverse()のコメントを参照して下さい。
	//                                         G_POST_ORDER,又は,G_LEVEL_ORDERのどちらでも正常に動作しますが、G_LEVEL_ORDERよりもG_POST_ORDERの方が効率が良いので、G_POST_ORDERを使う事にしました。
    #else //GNODE_SAFE_SELF_DESTRUCTION_DURING_PRE_ORDER_TRAVERSING
	g_node_traverse(pActObj->node, G_PRE_ORDER, G_TRAVERSE_ALL, -1/*depth*/, ActObj_InitAttr_func, /*const警告抑制*/(void*)aAttr);
	//                             ~~~~~~~~~~~G_PRE_ORDER内でnode自身を削除出来るようになったので、G_POST_ORDERやG_LEVEL_ORDERよりも自然である、G_PRE_ORDERを使用する事にしました。
	//                                        G_PRE_ORDER内でnode自身を削除出来るようになった経緯については、gnode.h内の'Sat Aug 27 21:24:43 JST 2016'のコメントを参照して下さい。
    #endif//GNODE_SAFE_SELF_DESTRUCTION_DURING_PRE_ORDER_TRAVERSING
}
