変更ハンドラおよび When 構文

 

   

コールバック通知 - クイック ナビゲーション

変更ハンドラは、シーン内のオブジェクトで特定のユーザ イベントが実行されるとき、その検出に使われます。スクリプトで記述できるので、オブジェクトの移動、頂点の編集、オブジェクトの削除、名前の変更などのユーザ操作に応答するスクリプトを作成できます。変更ハンドラは、各 MAXWrapper オブジェクトに適用され、そのオブジェクトで監視するアトリビュートやそのアトリビュートが変更されたときに評価する式を指定します。監視できるアトリビュートには、ジオメトリ、名前、変換、パラメータなどがあります。このハンドラは、3ds Max シーンには保存されません。

ChangeHandler : Value クラスのインスタンスは、変更ハンドラのセットアップを表します。ChangeHandler 値は、 when 構文を使用することにより作成されます。 when 構文が実行されるたびに、新しい ChangeHandler インスタンスを作成して返します。この ChangeHandler を変数または配列に保存しておき、必要に応じてハンドラを解除できるようにしてください。

when 構文は、1 つ以上のオブジェクトで特定のイベントに対して変更ハンドラ関数を定義します。そのイベントが発生すると、システムは自動的にこの関数を呼び出します。

when 構文には、次の 2 つの形式があります。

when <attribute> <objects> change[s] [ id:<name> ] \ 
[handleAt: #redrawViews|#timeChange] \ 
[ <object_parameter> ] do <expr>
when <objects> deleted [ id:<name> ] \ 
[handleAt:#redrawViews|#timeChange] \
[ <object_parameter> ] do <expr> 

最初の形式では、 <attribute> には、次のいずれかを使用できます。

 topology geometry name[s] transform select parameters subAnimStructure controller children

これらは、変更を監視する必要があるオブジェクトのアトリビュートを指定します。詳細は以下を参照してください。

2 番目の形式は、ユーザまたは他のスクリプトによるオブジェクトの削除を監視します。通常、MAXScript オブジェクト値を含むテーブルや他の構造体を持ち、シーンの変更時に削除されたオブジェクトを破棄したい場合に使用します。

注:

#selectedNodesPreDelete 汎用コールバックは、ユーザによるノードの削除を補足するために使用される、さらに優れたメソッドです。このメソッドはノード上に操作が何も行われていない時点で呼び出され、あらゆるノードの削除を報告します。これに対し when 構文は、コールバックで明示的に登録されたノードに対してのみ動作します。

mypot1 = teapot() --create a teapot
fn whendeleted = --define a callback function
(
local deletedobjects = callbacks.notificationParam()
format "Callback: %\n" deletedobjects
-- This will printevery object that was deleted.
-- By this point, the object isstillattached to it's parents
-- and is still in groups etc...
-- Nothing has been done to the nodeyet.
)
when mypot1 deleted id:#foo obj do --define a when construct
(
format "When Construct:%\n" obj
)
--unregisterany preDeletecallbacks
callbacks.removeScripts #selectedNodesPreDelete
--register the function as general callback
callbacks.addscript #selectedNodesPreDelete "whendeleted()"

3ds Max 9 に戻ると、 when 構文の呼び出し方が変更されます。3ds Max 9 以前のリリースでは、 when 構文はオブジェクトを実際に削除する前に呼び出されていました。3ds Max 9で上記のコードを実行すると、when コールバックは「削除されたシーン ノード」を返します。

3ds Max 2008 ではこの動作が修正されました。

どちらの形式でも、引数 <objects> には次のいずれかを使用できます。

複数のオブジェクトが指定された場合、3ds Max コアによって任意のオブジェクトの特定のアトリビュートが変更され、シグナルが発行されるたびにハンドラが呼び出されます。

オプションの id: パラメータは、1 つまたは複数のハンドラの ID を名前リテラルとして指定します。ID 名は、後でハンドラを削除する場合に使用できます。同じ名前のハンドラが複数ある場合は、それらをグループとして削除できます。

オプションの handleAt: パラメータは、変更ハンドラの式が通知後すぐに実行されないようにシグナルを発行し、3ds Max ビューポートが再描画されるまで( #redrawViews )、または現在の 3ds Max アニメーション時間が変更されるまで( #timeChange )、実行を遅らせます。後述の「注意」で解説されているように、変更ハンドラの式の処理を遅らせることをお勧めします。 handleAt: パラメータの使用例は次のとおりです。when select $ changes id:#foo handleAt:#redrawViews do ...

オプションの <object_parameter> を使用すると、do <expr> 内でアクセスでき、変更された実際のオブジェクトを保持するパラメータ変数の名前を指定できます。ハンドラが多数のオブジェクトの変更に応答する場合は、どのオブジェクトが変更されたかを決定できるように、このパラメータ名を指定します。 <expr> は、単一式でもブロック式でもかまいません。

例:

b1 = box()
b2 = box()
b3 = box()
when transform $box001 changes do
$box002.pos = $box001.pos + delta
max select all
when names selection change obj do update_name_table obj
when #($box001, $box002, $box003) deleted obj do
(
messageBox "Warning!"
deleteItem obj_table (findItem obj_table obj)
)

変更アトリビュートは次のように解釈されます。

topology

メッシュ スムーズ、最適化、または頂点の削除などを通してオブジェクトのトポロジがモディファイヤ パネルで変更された場合に、このシグナルが発行されます。

geometry

頂点の移動、またはアニメートされたモディファイヤによってオブジェクトのジオメトリが変更された場合に、このシグナルが発行されます。

name or names

3ds Max コマンド パネルで、ユーザが名前を編集して、オブジェクトの名前が変更された場合に、このシグナルが発行されます。文字が変更されるたびにハンドラが繰り返し呼び出されます。

transform

移動、回転、またはスケールによってオブジェクトの変換が変更された場合に、このシグナルが発行されます。

select

シーン ノードが現在の選択セット中に移動した場合か、セット外に移動した場合に、このシグナルが発行されます。新規の状態を決定するには <node>.isSelected プロパティを調べる必要があります。

parameters

オブジェクト内でパラメータが変更された場合に、このシグナルが発行されます。多くの場合、コアはこのイベントをシグナルとして発行するため、これは一括キャッチと似ています。

subAnimStructure

新しい頂点が編集可能メッシュ内でアニメート化されたり、新しいコントローラがリスト コントローラに追加された場合など、ダイナミック subAnim 構造が変更された場合に、このシグナルが発行されます。また、サブアニメート可能構造が再割り当てされた場合(たとえば、オブジェクト内でマテリアルが変更された場合)に呼び出されます。

controller

新しいコントローラがオブジェクトのトラックの 1 つに割り当てられた場合に、このシグナルが発行されます。

children

オブジェクトが直接子を追加または削除した場合に、このシグナルが発行されます。

   

変更ハンドラの削除

変更ハンドラを削除するには次の 2 つのメソッドを使用できます。

deleteChangeHandler <change_handler>

指定された変更ハンドラを削除します。 change_handler は、 when 構文で返される値です。

   

deleteAllChangeHandlers [ id:<name> ]

オプションの id: パラメータが指定されていない場合、すべての変更ハンドラを削除します。オプションの id: パラメータが指定されている場合、指定された ID を持つ変更ハンドラをすべて削除します。

例:

deleteAllChangeHandlers id:#foo

効率を上げるために、関連性のない変更ハンドラをバックグラウンドで実行している必要はないため、不要になったものは削除することが大切です。

特に注意すべき点

例:

when select $ changes obj do update_modifier_list obj

オブジェクトが選択および選択解除されたとき、 update_modifier_list 関数が呼び出されます。これは、[編集](Edit) /[すべてを選択](Select All) を実行したときにもあてはまります。この場合、 update_modifier_list は、現在選択されている各オブジェクトに対して一度だけ呼び出され(オブジェクトの選択が解除されるとき)、続いて、シーン内のすべてのオブジェクトに対して一度だけ呼び出されます(オブジェクトが選択されるとき)。 update_modifier_list がプロセッサ集約処理を行う場合、システムの処理速度が著しく低下します。

警告 :

この変更ハンドラ システムは、3ds Max 内のすべてのアニメーションとインタラクティビティを実質的に駆動する 3ds Max の内部通知システムに基づいています。

コアが同じ変更に対して非常に多くのシグナルを送信する場合があり、大量の計算を行う多くのオブジェクトに変更ハンドラを設定すると、システムの処理速度が大幅に遅くなることがあります。

厳密には、変更ハンドラは、処理量が軽くて順序に依存しない「ダーティ フラグ」を設定し、再描画ビューや時間変更コールバックを使用して、実際にトリガされた処理の実行に使われます。

変更ハンドラは慎重に使用してください。スクリプト化コントローラを簡単に取得するなどのために使用することはお勧めしません。

使用したいセットアップが不要なシグナルであふれている場合は、 handleAt: を使って redrawViews や timeChange イベントが起こるまでイベント ハンドラ スクリプトの実際の処理を遅らせます。

 

   

コールバック通知 - クイック ナビゲーション

関連事項