2016年05月24日

3ds Max 2016の新機能を調べてみた その93 3dsmax 2016

引き続き「Maxクリエーショングラフ」の「MCG_lookAt」コントローラのパラメータロールアウトについて調べてみたい。

前回は単純なサンプルをもとに「Remove Selected」ボタンの動作を調べてみた。今回は「MCG_lookAt」コントローラの方の「Remove Selected」ボタンを調べてみたい。

fig03

「Remove Target」ボタンが押された時に呼び出されるハンドラは以下の通り。

on removeFromList_Targets_UI pressed do with undo label:"Remove Targets" on (
 local indicies = mcgAPOps.GetSelectionIndices Combined_UI
 mcgAPOps.INodeA_RemoveFromList Combined_UI Targets_Tab
 for index in indicies do
 (
  if index < Weights_Tab.Count do deleteItem Weights_Tab (index+1)
 )
)

太字の部分はデフォルト状態の前回のものと同様のコードになっていて、「Combined_UI」の「ListView」コントロールのリストで選択されたアイテムの番号を調べて対応する「Targets_Tab」の要素を削除するようになっている。

「Targets_Tab」が変更されたら自動的に「on Targets_Tab tabChanged」ハンドラが呼び出されて「Combined_UI」の方に「Targets_Tab」の変更を反映しようとする事になる。

on Targets_Tab tabChanged action index count do
(
 Targets_List.clear()
 if (paramsOpen) do (
  this.params.FilltargetsListView()
  if (action == #insert) then (
   local sel = #()
   append sel (index - 1)
   this.params.SelectListviewTargets sel
  )
  else if (action == #append) then (
   local sel = #()
   append sel (Targets_Tab.Count - 1)
   this.params.SelectListviewTargets sel
  )
 )
)

でも「Combined_UI」は「Weights」欄もあって、これに対応する「Weights_Tab」の方も「Combined_UI」で選択されているアイテムに対応して削除する必要がある。そこで「Targets_Tab」の処理を始める前に

local indicies = mcgAPOps.GetSelectionIndices Combined_UI

を実行して「indicies」に「Combined_UI」で選択されているアイテムの番号の配列を取得して、

for index in indicies do
(
 if index < Weights_Tab.Count do deleteItem Weights_Tab (index+1)
)

の部分で一気に「Weights_Tab」の対応する要素を削除している。当然こっちの変化に対しても「on Weights_Tab tabChanged」ハンドラが呼び出されて「Combined_UI」の方に「Weights_Tab」の変更を反映しようとする。

on Weights_Tab tabChanged action index count do
(
 Weights_List.clear()
 if (paramsOpen) do
  this.params.FilltargetsListView()
)

以上を見て行くと、だったら「mcgAPOps.INodeA_RemoveFromList 」なんか呼び出さないで上の「for」文の中で一緒に「Targets_Tab」も削除しちゃえばいいじゃないと思うところだ。実際「mcgAPOps.INodeA_RemoveFromList 」の中でさらに「mcgAPOps.GetSelectionIndices Combined_UI」が呼び出されていたりして処理がダブったりしている。

ただコードをよく眺めてみると、「Tab」の変更ハンドラの中から呼び出されて「ListView」を更新する「FillTargetsListView」ファンクションの中では、現在の「Targets_Tab」と「Weights_Tab」の要素数が等しいかどうかをチェックしていて、2つが等しい時しか「ListView」の更新が行われないようになっている。

fn FillTargetsListView = (
 global theListView = Combined_UI
 local theRange = #()
 local lineNumber = 1
 if (Combined_UI != undefined) do (   Combined_UI.Items.Clear()
  if (this.Targets_Tab.Count == this.Weights_Tab.Count) do
  (
   for o in this.Targets_Tab do
   (
    local li = dotNetObject "System.Windows.Forms.ListViewItem" (mcgAPOps.INodeToStringFunc o)
    li.ToolTipText = (mcgAPOps.INodeToStringFunc o)
    local subli = li.SubItems.add (this.Weights_Tab[lineNumber] as string)
    append theRange li
    lineNumber = lineNumber+1
   )
   Combined_UI.Items.AddRange theRange
  )
 )
)

「on removeFromList_Targets_UI」内の処理で「Targets_Tab」と「Weights_Tab」の要素数が同じになるのは「Targets_Tab」も「Weights_Tab」も「ListView」で選択されている要素が全て削除された時だけになるので、「FillTargetsListView」は「Targets_Tab」や「Weights_Tab」が1つ変更されるたびに呼び出されるけど、実際に「ListView」を更新するのは2つの「Tab」の不要な要素の削除が全て終わった時だけってことになる。もしfor文のループ内で2つの「Tab」の要素を1つずつ削除していくループにしたら2つの要素数はループ1回ごとに等しくなり、「ListView」の更新が頻繁に起きることになる。もちろんもう少し効率のいいコードには出来ると思うけどね。

続きはまた次回。

maxまとめページ



take_z_ultima at 11:30│Comments(0)TrackBack(0)3ds Max | CG

トラックバックURL

この記事にコメントする

名前:
URL:
  情報を記憶: 評価: 顔   
 
 
 

Archives