変更ハンドラは、シーン内のオブジェクトで特定のユーザ イベントが実行されるとき、その検出に使われます。スクリプトで記述できるので、オブジェクトの移動、頂点の編集、オブジェクトの削除、名前の変更などのユーザ操作に応答するスクリプトを作成できます。変更ハンドラは、各 MAXWrapper オブジェクトに適用され、そのオブジェクトで監視するアトリビュートやそのアトリビュートが変更されたときに評価する式を指定します。監視できるアトリビュートには、ジオメトリ、名前、変換、パラメータなどがあります。このハンドラは、3ds Max シーンには保存されません。
ChangeHandler : Value クラスのインスタンスは、変更ハンドラのセットアップを表します。ChangeHandler 値は、 when 構文を使用することにより作成されます。 when 構文が実行されるたびに、新しい ChangeHandler インスタンスを作成して返します。この ChangeHandler を変数または配列に保存しておき、必要に応じてハンドラを解除できるようにしてください。
when 構文は、1 つ以上のオブジェクトで特定のイベントに対して変更ハンドラ関数を定義します。そのイベントが発生すると、システムは自動的にこの関数を呼び出します。
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> には、次のいずれかを使用できます。
これらは、変更を監視する必要があるオブジェクトのアトリビュートを指定します。詳細は以下を参照してください。
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> は、単一式でもブロック式でもかまいません。
メッシュ スムーズ、最適化、または頂点の削除などを通してオブジェクトのトポロジがモディファイヤ パネルで変更された場合に、このシグナルが発行されます。
頂点の移動、またはアニメートされたモディファイヤによってオブジェクトのジオメトリが変更された場合に、このシグナルが発行されます。
3ds Max コマンド パネルで、ユーザが名前を編集して、オブジェクトの名前が変更された場合に、このシグナルが発行されます。文字が変更されるたびにハンドラが繰り返し呼び出されます。
移動、回転、またはスケールによってオブジェクトの変換が変更された場合に、このシグナルが発行されます。
シーン ノードが現在の選択セット中に移動した場合か、セット外に移動した場合に、このシグナルが発行されます。新規の状態を決定するには <node>.isSelected プロパティを調べる必要があります。
オブジェクト内でパラメータが変更された場合に、このシグナルが発行されます。多くの場合、コアはこのイベントをシグナルとして発行するため、これは一括キャッチと似ています。
新しい頂点が編集可能メッシュ内でアニメート化されたり、新しいコントローラがリスト コントローラに追加された場合など、ダイナミック subAnim 構造が変更された場合に、このシグナルが発行されます。また、サブアニメート可能構造が再割り当てされた場合(たとえば、オブジェクト内でマテリアルが変更された場合)に呼び出されます。
新しいコントローラがオブジェクトのトラックの 1 つに割り当てられた場合に、このシグナルが発行されます。
オブジェクトが直接子を追加または削除した場合に、このシグナルが発行されます。
変更ハンドラを削除するには次の 2 つのメソッドを使用できます。
指定された変更ハンドラを削除します。 change_handler は、 when 構文で返される値です。
オプションの id: パラメータが指定されていない場合、すべての変更ハンドラを削除します。オプションの id: パラメータが指定されている場合、指定された ID を持つ変更ハンドラをすべて削除します。
効率を上げるために、関連性のない変更ハンドラをバックグラウンドで実行している必要はないため、不要になったものは削除することが大切です。
変更ハンドラの実行中にその本文にランタイム エラーが発生した場合は、エラー メッセージが表示され、そのハンドラは永久的に使用不可になります。
do <expr> 変更ハンドラ コードは、それを作成したコードのコンテキストではなく、特別のコンテキストで実行されます。つまり、 <expr> コードは when を囲む外側のコードのネスト内にあるローカル変数への参照を含めることはできません。これは、ローカル変数が when ハンドラを呼び出したときに存在していない実行スタック上にあるためです。コンパイラは外側のローカルへの不正な参照をすべて検出し、コンパイラ メッセージを生成します。これに関する重要な例外は、ユーティリティとロールアウトのパネル ローカル(ローカル関数、ロールアウト変数、ネストされたロールアウトなど)です。これらは直接ロールアウトやユーティリティ オブジェクトと関連付けられているため、ロールアウト コード内の変更ハンドラで参照できます。
変更ハンドラは、コントローラ値の変化による結果の変更ではなく、ユーザが始めたイベントに対してのみ呼び出されます。たとえば、ノードの変換アトリビュートの変更ハンドラは、ユーザがノードを移動するときに呼び出されます。ノードの位置がアニメート化されている場合、アニメーションを再生しても変換アトリビュートの変更ハンドラは呼び出されません。
1 つの変更ハンドラを複数のオブジェクトのアトリビュートに割り当てた場合、オブジェクトのアトリビュートが変更されると、変更ハンドラは各オブジェクトにつき 1 度だけしか呼び出されません。
変更ハンドラは、シーン内に既に存在するオブジェクトに対してのみ適用されます。変更ハンドラが、新規作成オブジェクトに自動的に適用されることはありません。
3ds Max 内部の通知シグナルの処理方法のため、select 変更ハンドラでの $ 形式による選択オブジェクトへのアクセスはお勧めしません。選択オブジェクトにアクセスするにはオブジェクト セットを使用してください。$ は選択処理中にまだ設定されていない情報に依存しますが、selection では選択へのアクセスに異なるメソッドを使用し、すでに設定済みの情報を使用します。