タスク使い方FAQ

タスクの使い方に関するFAQページです。


表現逆引き編


ドラムピッカーを作りたい

以下のように UI_List を起動/設定することで、ドラムピッカー的な動作をさせることができます。

  • verticalモードを指定(起動引数)
  • クリッピング領域サイズをアイテム一つ分と同じ面積で指定(起動引数)
  • ループモードを指定(sysCommand: UI_LIST_SET_LOOPMODE)
  • スクロールマネージャとして "page" を指定し、ページサイズをアイテム一つと同じにする(sysCommand: UI_LIST_SELECT_SCRMGR)
  • デフォルトスクロールを有効にする(property: .default_scroll)
   local itemSize = {
      width = 100,
      height = 32
   }
   pDrumPick = UI_List( ... ) -- 起動引数でサイズと動作モードを適切に指定
   sysCommand(pDrumPick, UI_LIST_SET_LOOPMODE, true)
   sysCommand(pDrumPick, UI_LIST_SELECT_SCRMGR, "page", itemSize.height)
   prop = TASK_getProperty(pDrumPick)
   prop.default_scroll = true
   TASK_setProperty(pDrumPick, prop)

UI_TouchPad/UI_Control編


UI_TouchPadのコールバックの引数として与えられるtblはどんなもの?

「直前のフレーム内に検出されたタッチパネルイベントの一覧を、時系列順にindexを与え格納した配列(Luaテーブル)」です。 index順に処理する限り、時系列順にイベントを取り出すことができます。

引数となるテーブルの各要素はさらにテーブルになっていて、以下のキーで値を取り出すことができます。

  • type : 操作のタイプ(PAD_ITEM_TAP / PAD_ITEM_DRAG / PAD_ITEM_RELEASE)
  • id : 操作ポイントID
  • x : X座標
  • y : Y座標

UI_TouchPadで取得したイベントの "id" って何?

マルチタッチの操作ポイントを区別するためのIDです。同時に複数の指が触れている場合、それぞれの指に異なるIDが割り当てられ、ある指に関する操作は、その指で触れて(TAP)から離す(RELEASE)までの間(DRAG)、すべて同じIDで通知されます。

UI_TouchPadを使用してタッチパネルイベントを取得する場合は、必ずIDを見てそれぞれの指を区別するように実装してください。 特に Win32 環境ではマウスポインタ以外によるポインティングが成されず id が常に 0 となるため、異なるidのイベントを混同することによる問題に気づきにくいので注意が必要です。


UI_SWFPlayer編


再生しているmovie名を取得するには?

プロパティの .mvname メンバを参照することで、起動時に指定された再生movie名を取得できます。

   pSWF = UI_SWFPlayer(...)
   prop = TASK_getProperty(pSWF)

   -- movie名を取得
   local movie_name = prop.mvname

UI_VirtualDoc編


BAD command table format.というassertで落ちた。何が原因?

sysCommandのUI_VDOC_DRAWに与える描画コマンドテーブルのフォーマットが誤っています。 必ず「テーブルのテーブル」でなければならない点に注意してください。発行するコマンドが一つしかなくても同じです。


UI_Form/UI_List共通編


FORM_UIE_SET_ASSETでNodeの画像が変更できない

FORM_UIE_* というコマンドは CKLBUIElement クラス以上に対するコマンドです。 通常のノードはもっとも基本的な CKLBNode クラスとして作られているため、FORM_UIE_SET_ASSET サブコマンドを適用することはできません。

CKLBUIElementクラスを使用するもっとも基本的なComposite中のアイテムはボタンです。対象のNodeをボタンとして生成することで FORM_UI_SET_ASSET サブコマンドを使用することができます。


元々Compositeで指定されているのと同じAssetをFORM_UIE_SET_ASSETで指定できない

本来、CompositeはAssetの差し替えを想定していない実装になっていますが、 現時点においては数多くの需要からAdHookな実装としてFORM_UIE_SET_ASSETが実現されています。

このため、おおもとのCompositeに設定されているものと同じAssetを指定した際、 正しくAssetが設定されないという副作用が確認されています。 FORM_UIE_SET_ASSETによる変更を必要とするNodeについては、変更後に使われる可能性のあるAssetをComposite中では指定しないことで問題を回避してください。


複数のUI_FormやUI_List間で、特定のボタンが操作されている間他のボタンがマルチタッチで操作されるのを防ぎたい

同時に操作されては困る複数の UI_Form や UI_List は「グループ化」することで、同一のグループに所属するものとの間で排他制御されるようになります。

UI_FORM_SET_GROUP(UI_LIST_SET_GROUP)で、フォームやリストを所属させるグループの名称を指定してください。

   pForm = UI_Form(...)
   pList = UI_List(...)

   sysCommand(pForm, UI_FORM_SET_GROUP, "exclusiveGroup")
   sysCommand(pList, UI_LIST_SET_GROUP, "exclusiveGroup")

上記の例では、フォームとリストを一つずつ生成し、それぞれを同じ "exclusiveGroup" という名称のグループに所属させています。 pFormが操作中はpListの操作が禁止され、pListの操作中はpFormの操作が禁止されます。


UI_Formの特定のノードに対してUI_GENERIC_NODE_RECONNECTを使いUIタスクを繋ぎなおしたが、繋いだはずのノードからUI_FORM_UPDATE_NODEのFORM_NODE_TASKでタスクポインタが取得できない。なぜ?

それは、UI_GENERIC_NODE_RECONNECTは指定されたノードの下にUIタスクのRootノードを繋ぐコマンドであり、 FORM_NODE_TASKは指定された名前のノードが持つタスクのポインタを返すコマンドだからです。 「指定した名前のノードにタスクのポインタを与えるコマンド」ではありません

たとえば、"connection_point"という名前のノードの下に、UIタスクを繋ぎたいと思って、下記のような処理を行ったとします。

   pForm = UI_Form( ... )
   pTask = UI_* (pForm, ... )
   sysCommand(pTask, UI_GENERIC_NODE_RECONNECT, "connection_point")

   pUI = sysCommand(pForm, UI_FORM_UPDATE_NODE, "connection_point", FORM_NODE_TASK)

このとき、pUIの値はnilにしかなりません。 UI_GENERIC_NODE_RECONNECTによる接続後、 "connection_point" 以下のSceneGraphはこうなっています。

   "connection_point" (タスクポインタ == NULL)
       |
       +- pTaskのRootノード (タスクポインタ == pTask)

このため、UI_FORM_UPDATE_NODE::FORM_NODE_TASK のターゲットとして "connection_point" を指定しても、そのノードが持っているタスクポインタはNULLなので、nilしか返されません。

取得ターゲットとしては、その下にぶら下がっている「pTaskのRootノード」を与える必要がありますが、このノードは名前を持っていないため、このままではUI_FORM_UPDATE_NODEのターゲットとして指定できません。

しかし、下記のようにすることで目的を果たすことができます。

   pForm = UI_Form( ... )
   pTask = UI_* (pForm, ... )
   sysCommand(pTask, UI_GENERIC_SET_NAME, "task_search_name")        -- 追加
   sysCommand(pTask, UI_GENERIC_NODE_RECONNECT, "connection_point")

   pUI = sysCommand(pForm, UI_FORM_UPDATE_NODE, "task_search_name", FORM_NODE_TASK) -- 変更

UI_GENERIC_SET_NAME は、UIタスクの持つRootノードに検索で使える名前を与えるためのコマンドです。 これにより名前のなかった「pTaskのRootノード」に名前を与えることができ、UI_GENERIC_NODE_RECONNECTにより pFormの持つSceneGraph以下にもつながるため、pFormのUI_FORM_UPDATE_NODEのターゲットとしてその名前を使用できるようになります。


UI_List編


"Overlapping clipping range"というassertで落ちた。何が原因?

UI_Listの起動時に指定した <base priority> から <max order> の範囲が、他の UI_List で指定されている範囲と重なっているのが原因です。 同時に起動している他のUI_Listで指定されているプライオリティ範囲と重複する値を指定することはできません。たとえば以下のような場合です。

   pList1 = UI_List(nil, 100, 200, ...)
   pList2 = UI_List(nil, 180, 300, ...)

上記の例ではpList1に指定された範囲とpList2に指定された範囲が、180~200の範囲で重なっています。 描画系のクリッピングシステムは描画プライオリティの範囲に対しクリッピングをかけるため、 異なるクリッピング領域の有効プライオリティ範囲が重なる指定はできません。


"Wrong clipping order (start >= end)"というassertで落ちた。何が原因?

UI_Listの起動時に指定した <base priority> より <max order> の値が小さいです。 <max order>は必ず<base priority>より大きな値でなければなりません。


アイテムとしてUI_List起動を伴うCompositeを登録したが、assertionが出て動いてくれない。

描画系の仕様上、UI_Listのアイテムとして、UI_Listの起動を伴うCompositeの登録はできません

これは、UI_Listが利用している描画系のクリッピング機能に下記の制約があるためです。

  • クリッピング領域をクリッピングすることはできない
  • 対象プライオリティ範囲が重複するクリッピング範囲を作ることはできない

リストアイテムのCompositeはUI_Listの指定したクリッピングの対象となるのが前提であり、 アイテムにUI_Listを含めるということは、アイテムのUI_Listのクリッピング範囲を 親となるUI_Listのクリッピング範囲でクリッピングするということですが、描画系の制約上これはできません。

また、同時に表示されるUI_Listはそれぞれクリッピング対象となるプライオリティ範囲が重複してはいけませんが、 親となる UI_List とアイテムの UI_Listだけでなく、アイテムのUI_List同士でも重複してはいけません。

この場合唯一の方法は「デザインの側を変更してもらう」ことです。


リスト上ドラッグのためのコールバックを書くのがめんどくさい

UI_List起動時のコールバック名<drag callback>として nil 値を指定した上で、プロパティ .default_scroll を true にしてください。 デフォルトのドラッグスクロール機能が有効になります。

   pList = UI_List(nil,
                   3000,     -- base priority
                   3200,     -- max priority
                   100, 100, -- position
                   300, 400, -- size
                   90,       -- default step
                   true,     -- vertical flag
                   nil       -- drag callback   ←これを nil に
                   )
    prop = TASK_getProperty(pList)
    prop.default_scroll = true     ← これをtrueに
    TASK_setProperty(pList, prop)

UI_Listにスクロールバーをつけたい

UI_LIST_USE_SCROLLBARに必要なパラメータを設定することで、UI_Listの組み込みスクロールバーが使用できます。


"Image source for Scroll bar does not have attributes for scroll bar design"というassertで落ちた。何が原因?

UI_LIST_USE_SCROLLBARでスクロールバーの設定を行っていますね?

スクロールバーのスライダに使用するassetの画像をToboggan上で開き、Editable propertyのImageTypeが"ScrollBar"になっていることを 確認してください。なっていない場合、そのままではその画像をスライダ用assetとして指定することはできません。設定を変更した上でテクスチャを再生成してください。


起動パラメータのLIST_FLAG_BOTTOMは何が変わるの?

通常UI_Listにアイテムを追加すると、追加されたCompositeの原点はすべて一本の直線の上に乗るよう配置されます。この直線を「原点ライン」と呼びます。

デフォルトでは、縦方向リストならばクリッピング領域の左側、横方向リストならば上側の辺の延長線が原点ラインとなりますが、 LIST_FLAG_BOTTOMを指定すると、原点ラインが「反対側の辺」の延長線になります。縦方向リストならば右側、横方向リストならば下側の辺です。

これは、「右の辺から生えているリスト」「アイテムが下の辺に乗っているリスト」のような表示を可能にするためのモードです。 原点ラインが移動するので、アイテムとして登録するCompositeの作り方にも注意が必要となります。


LIST_FLAG_BOTTOMを指定したらアイテムが表示されなくなった。なぜ?

LIST_FLAG_BOTTOMを指定しない状態でアイテムが表示されるのであれば、アイテムとして追加しているCompositeの作り方が間違っています。

たとえば縦方向リストの場合、原点の右側に表示オブジェクトを配置しているCompositeをLIST_FLAG_BOTTOM指定のUI_Listに追加すると、 表示物がクリッピング領域外に出てしまうため描画されません。

LIST_FLAG_BOTTOM指定のUI_Listにアイテムとして追加するCompositeは、縦方向リストであれば原点の左側、横方向リストならば原点の上側に 表示オブジェクトが配置されていなければなりません。


UI_List で特定のアイテムが中央にくるようにスクロールさせたい

UI_LIST_SET_ITEM_POSを、<position mode> = LIST_VIEW_CENTER で使用してください。

同じように、クリッピング領域の上/左に移動させたいなら LIST_VIEW_TOP,クリッピング領域の下/右ならばLIST_VIEW_BOTTOMです。


リスト中にあるアイテムの占有幅を個別に変更したい

UI_LIST_CHANGE_STEPを使用することで変更できます。


リストの端でスクロールが止まってしまうが、止めずにスクロールさせたい

UI_LIST_SET_LIMITCLIPで<limit clip enable>をfalseにすることで、両端を超えてスクロールできるようになります。


リストの両端でスクロールは止めたいが、両端に余白がほしい

UI_LIST_SET_MARGINで<margin-top>と<margin-bottom>を指定できます。

   pList = UI_List(...)
   sysCommand(pList, UI_LIST_SET_MARGIN, 50, 70)

また、プロパティ.margin_top と .margin_bottom で個別に指定できます。

   pList = UI_List(...)
   prop = TASK_getProperty(pList)
   prop.margin_top = 50    -- 先頭マージン
   prop.margin_bottom = 70 -- 末尾マージン
   TASK_setProperty(pList, prop)


リスト末尾にスクロールさせたいが、どこまでスクロールさせればよいか取得できるか?

UI_LIST_GET_LIMITで返ってくる値を使用してください。


現在のスクロール位置が知りたい

UI_LIST_GET_POSITION で返ってくる値を使用してください。


スクロール位置の値はどのような単位で扱われている?

スクロールアイテム群の先頭からのピクセル数です。


スクロールバーのコールバックに返される位置情報の単位は?

スクロール位置と同様にアイテム群先頭からのピクセル数です。 そのまま計算してUI_LIST_SET_POSITIONに与えることができます。


スクロール時にデフォルトのヌメっとした動きではなくきびきび動作させたい

UI_LIST_SELECT_SCRMGR で "solid" でも指定すると良いでしょう。 あるいは "default" の <delay> を小さくしても良いです。


スクロールマネージャ "default" に指定できる値<delay>の意味が知りたい

スクロールマネージャ "default" は、1フレームあたりに現在の位置とスクロール目標位置の間の 1/n だけ距離を詰めます。 距離が近づくにつれ 1/n の値も小さくなるのでだんだんとゆっくりになり、整数値に丸めた値が等しくなった時点で停止します。 つまり n に 1 を指定すると 1/n = 1/1 = 1 となり、見かけ上 "solid" と同じ動作になります。

<delay> はこの分母 n を指定する値で、整数値のみが指定できます。デフォルトの値は10です。


スクロールの停止位置を一定ピクセルおきにして「ページ単位スクロール」がしたい

UI_LIST_SELECT_SCRMGR で "page" を指定し、ページの「長さ」を指定してください。


現在のスクロール位置指標としてスクロールバーは表示させたいが、スクロールバーを操作させたくはない。どうすればいい?

UI_LIST_USE_SCROLLBAR のパラメータ <active> を false にしてください。 スクロールバーが指定のAssetで表示され、現在位置を反映しますが、スクロールバーそのものを操作することはできなくなります。


汎用タスク編


一定時間後にタスクを殺したい

LIFECtrlタスクを使用してください。


ゲームアプリが端末によってForeground/Background化されたときにスクリプト処理をさせたい

PAUSECtrl タスクを使用し、Background化された際の処理を <pause-callback> 、Foreground化の処理を <resume-callback> で指定した関数に記述してください。