3ds Max 2009 以降で提供されているノード イベント システムを使用すると、ノード関連のさまざまなシーン イベントに応じてトリガされるスクリプト関数を定義することができます。シーン イベントは 3ds Max SDK の INodeEventCallback クラスのイベント メソッドに 1 対 1 でマッピングされます。それぞれのイベント メソッドに関する詳細は、maxsdk\¥include\¥ISceneEventManager.h の INodeEventCallback クラスに関するメソッドのコメントを参照してください。
ノード イベント システムは一般イベント コールバック機能によく似ています。ノード イベント システムは一般イベント コールバック機能の上のレイヤとして動作しますが、従来のシステムでは処理できなかったようなノード メッセージ(ジオメトリ、トポロジ、マッピングの変更など)を受信することができます。ノード イベント システムは、従来のシステムでは捕らえることができない場合もあった、「元に戻す」や「やり直し」などの結果として発生するイベントも捕らえることができます。
このように、ノードに関連するイベントやノードに対する変更を捕らえたい場合には、ノード イベント システムを使用する方法が最適です。
コンストラクタ:
<callbackItem>NodeEventCallback [mouseUp:<boolean>] [delay:<integer>] \
[enabled:<boolean>] [polling:<boolean>] \
[callbackBegin:<fn>] [all:<fn>] \
[added:<fn>] [deleted:<fn>] \
[linkChanged:<fn>] [layerChanged:<fn>]\
[groupChanged:<fn>] [hierarchyOtherEvent:<fn>] \
[modelStructured:<fn>] [geometryChanged:<fn>] \
[topologyChanged:<fn>] [mappingChanged:<fn>] \
[extentionChannelChanged:<fn>] [modelOtherEvent:<fn>] \
[materialStructured:<fn>] [materialOtherEvent:<fn>] \
[controllerStructured:<fn>] [controllerOtherEvent:<fn>] \
[nameChanged:<fn>] \
[wireColorChanged:<fn>] [renderPropertiesChanged:<fn>] \
[displayPropertiesChanged:<fn>] [userPropertiesChanged:<fn>] \
[propertiesOtherEvent:<fn>] \
[subobjectSelectionChanged:<fn>] [selectionChanged:<fn>] \
[hideChanged:<fn>] [freezeChanged:<fn>] \
[displayOtherEvent:<fn>] [callbackEnd:<fn>]
次のスクリプト例は、オプションのキーワード引数 all:
に関数を登録することによって何らかのメッセージを受信した場合に、MAXScript リスナーに対してメッセージを出力します。
このスクリプトは linkChanged:
イベントまたは layerChanged:
イベントが発生した場合(1 つのノードが別のノードにリンクされた場合、別のノードへのリンクを解除された場合、別のレイヤに移動された場合)にもメッセージ ボックスを表示します。
スクリプト例:
--Define a callback function to handle linking and layer changes: fn CallbackFn1 ev nd = ( messageBox ("Event Detected: Event "+(ev as string)+ \ ", Nodes " + (nd as string)) ) --Define a callback function to handle ALL messages: fn CallbackFn2 ev nd = ( format "Event Detected: Event%, Nodes %\n" ev nd ) --Register callbacks for link changes, layer changes using the --first function and for all changes using the second function. --Act only when mouse is up and there have been no other events --within one second (1000 milliseconds): callbackItem = NodeEventCallback mouseUp:true delay:1000 linkChanged:CallbackFn1 layerChanged:CallbackFn1 all:CallbackFn2
デストラクタ:
NodeEventCallback()
コンストラクタが呼び出されると、クラスのインスタンスが作成され、呼び出しの結果として返されます。
このインスタンスを開放して呼び出しを取り除くためには、インスタンスに対するハンドラを保持している変数の値を未定義に設定し、ガーベジ コレクタを呼び出してメモリをクリアして効率的に呼び出しを破棄します。
例:
--Continuing the previous example where the variable --callbackItem was used to store the callback instance, callbackItem = undefined gc light:true
mouseup:
オプションのキーワード引数である mouseUp:
が true
に設定されている場合は、コールバックはマウス ボタンが押されていない場合にのみトリガされます。
delay:
オプションのキーワード引数である delay:
が(ミリ秒単位の時間で)指定されている場合は、コールバックは指定された時間だけ一切のイベントが発生しなかった場合(指定された時間だけシステムがアイドル状態であった場合)にのみトリガされます。
polling:
オプションのキーワード引数 polling:
が true に設定されている場合は、triggerNodeEventCallback()
を使用して NodeEventCallbackValue
の保留中のイベントを起動することができます。3ds Max 2019.3 Update 以降で使用可能です。mouseUp または delay が指定されている場合は、polling 引数を使用できません。
ノード イベント システムによって受信されたメッセージ内に指定されたタイプのコールバックが含まれている場合に実行される定義済みの MAXScript 関数には、1 個または複数個のその他のオプションのキーワード引数を指定することができます。
コールバック関数は常に 2 つのパラメータを取ります。1 つ目は関数呼び出しをトリガしたイベント名、2 つ目はノードの AnimHandle のリストです。
ノード自体を取得するためには、GetAnimByHandle()
メソッドを使用する必要があります。
指定した関数が 2 つの引数を予期しないものである場合は、エラーが発生します。たとえば、関数 ObjFn が渡されて、引数が何も指定されない場合は、次のようなエラーになります。
>> MAXScript NodeEventCallback Exception: -- Argument count error: ObjFn wanted 0, got 2 <<
エラーの文章から、関数は正しくコールバックが誤っているものと誤解してしまう場合がありますが、そうとは限りません。
コールバックは常に 2 つの引数を渡しますが、関数が 2 つの引数を受け入れられない場合には、エラー メッセージは単に、関数が何によって呼び出されたのか、2 つのパラメータが渡されたのはなぜかを認識できないという事実を表しているにすぎません。
callbackBegin:
callbackEnd:
コールバックがトリガされると、キューイングされているすべてのイベントのメッセージが 1 つのバッチに送信されます。
callbackBegin:
メッセージはバッチの開始を示し、callbackEnd:
はバッチの終了を示します。
この 2 つのオプション キーワード引数を使用して関数を登録すると、単一のメッセージ バッチの開始と終了の通知を受けることができます。
all:
指定した関数は、次のリストに記載されているノードに関連するメッセージのいずれかが受信された場合に必ず呼び出されます。登録されているイベント固有の関数のほかに、この関数も呼び出されることに注意してください。最初に all
関数が呼び出されます。
added:
指定された関数は、シーンにノードが追加された場合に必ず呼び出されます。
deleted:
指定された関数は、シーンからノードが削除された場合に必ず呼び出されます。
linkChanged:
指定された関数は、ノードが別のノードにリンクされたり別のノードからリンク解除された場合に必ず呼び出されます。
layerChanged:
指定された関数は、ノードが別のレイヤに移動された場合に必ず呼び出されます。
groupChanged:
指定された関数は、ノードがグループに追加されたり、グループから削除された場合に必ず呼び出されます。
hierarchyOtherEvent:
指定された関数は、ノードの階層がその他の何らかの方法で変更された場合に必ず呼び出されます。
modelStructured:
指定された関数は、モデルの構造が変更された場合に必ず呼び出されます。
geometryChanged:
指定された関数は、ノードのジオメトリが変更された場合(頂点が移動された場合など)に必ず呼び出されます。
topologyChanged:
指定された関数は、ノードのジオメトリのトポロジが変更された場合(エッジが追加または削除された場合など)に必ず呼び出されます。
mappingChanged:
指定された関数は、ノードのジオメトリのマッピングが変更された場合(UV 座標が割り当てられた場合や修正された場合など)に必ず呼び出されます。
extentionChannelChanged:
指定された関数は、ノードの非マッピング チャネルが変更された場合(頂点アルファ、ソフト選択など)に必ず呼び出されます。
modelOtherEvent:
指定された関数は、ノードのモデルがその他の何らかの方法で変更された場合に必ず呼び出されます。
materialStructured:
指定された関数は、マテリアルがノードに追加されたり、ノードから削除されたりした場合に必ず呼び出されます。
materialOtherEvent:
指定された関数は、ノードのマテリアルが変更された場合に必ず呼び出されます。
controllerStructured:
指定された関数は、コントローラがノードの SubAnim トラックに割り当てられたり、SubAnim トラックから削除されたりした場合に必ず呼び出されます。
controllerOtherEvent:
指定された関数は、ノードのコントローラがその他の何らかの方法で変更された場合に必ず呼び出されます。
nameChanged:
指定された関数は、ノードの名前が変更された場合に必ず呼び出されます。
wireColorChanged:
指定された関数は、ノードのワイヤフレーム カラーが変更された場合に必ず呼び出されます。
renderPropertiesChanged:
指定された関数は、ノードのレンダリング制御プロパティ([レンダリング可能] (Renderable)、[カメラに対して可視](Visible to Camera)、[反射/屈折に対して可視](Visible to Reflection/Refraction)など)が変更された場合に必ず呼び出されます。
displayPropertiesChanged:
指定された関数は、ノードの表示プロパティ([ボックスで表示](Display as Box)、[頂点数](Vertex Ticks)、[背面非表示](Backface Culling)など)が変更された場合に必ず呼び出されます。
userPropertiesChanged:
指定された関数は、ノードのユーザ定義プロパティ バッファが変更された場合に必ず呼び出されます。
propertiesOtherEvent:
指定された関数は、ノードのその他のすべてのプロパティが変更された場合に呼び出されます。
subobjectSelectionChanged:
指定された関数は、ノードのサブオブジェクト選択が変更された場合に必ず呼び出されます。
selectionChanged:
指定された関数は、ノードの選択状態が変更された場合(ノードが選択され場合や選択解除された場合など)に必ず呼び出されます。
hideChanged:
指定された関数は、ノードの表示(Hidden)フラグが変更された場合に必ず呼び出されます。
freezeChanged:
指定された関数は、ノードのロック(Frozen)フラグが変更された場合に必ず呼び出されます。
displayOtherEvent:
指定された関数は、ノードのその他の表示フラグが変更された場合に必ず呼び出されます。
triggerNodeEventCallback <NodeEventCallbackValue>
指定した NodeEventCallbackValue の保留中のイベントをトリガします。3ds Max 2019.3 Update 以降で使用可能です。この関数は、polling
が true として指定されている NodeEventCallbackValues
で機能します。
<array> getNodeEventCallbacks
現在のシーンに登録されているすべての NodeEventCallback 値を取得します。3ds Max 2019.3 Update 以降で使用可能です。
showNodeEventCallbacks [asArray:<boolean>] [to:<stream>] [
現在のシーンに登録されているすべての NodeEventCallback 値に関する情報を返します。これらの情報は、enabled、polling、mouseUp、および delay の設定、登録されているイベント ID、これらのイベントに関連付けられている関数、およびNodeEventCallback を作成したスクリプト ファイル名などです。3ds Max 2019.3 Update 以降で使用可能です。
オプションの asArray キーワード パラメータが true として指定されている場合は、この情報が、NodeEventCallback ごとに文字列を 1 つずつ含む配列として返されます。それ以外の場合は、単一の文字列として返されます。
オプションの to キーワード パラメータが指定されている場合は、出力が指定されたストリームに書き込まれます。
poll_event_count = 0
fn runExample = (
-- reset the scene
resetMaxFile #noprompt --reset the scene
gc() -- run gc again to clean out previous runs
--Define a callback function to handle ALL messages:
fn MyCallback ev nd = (format "Event Detected: Event%, Nodes %\n" ev nd )
fn MyPollCallback ev nd = (
format "Event Detected: Event%, Nodes %\n" ev nd
poll_event_count += 1 )
-- Create callback item
callbackItem = NodeEventCallback added:MyCallback
pollCallBackItem = NodeEventCallback added:MyPollCallback
-- add something, which will trigger the first callback, but not the second:
t = teapot()
-- this will still be 0, because polling is on:
format "poll events: % \n" poll_event_count
-- trigger polling callback
triggerNodeEventCallback pollCallBackItem
-- node event system is timer based, and requires
-- message pump system. This will give the system
-- time to "catch up", since we do not have a UI
windows.processpostedmessages();sleep .1
windows.processpostedmessages()
-- did it trigger?
format "poll events: % \n" poll_event_count
showNodeEvents = showNodeEventCallbacks asArray:true
format "showNodeEventCallbacks : % \n" showNodeEvents
getNodeEvents = getNodeEventCallbacks()
format "Number of event callbacks: %\n" getNodeEvents.count
for i = 1 to getNodeEvents.count do format "Callback % : % \n" i getNodeEvents[i]
-- delete the callback items, and garbage collect:
callbackItem = pollCallbackItem = undefined
gc()
)
runExample()
--> Output:
runExample()
poll events: 0
Event Detected: Event#added, Nodes #(6772)
Event Detected: Event#added, Nodes #(6772)
poll events: 1
showNodeEventCallbacks : #(#(NodeEventCallback<0x000001A535A18210>, #added, "MyPollCallback", \
"D:\My Documents\3ds Max\scripts\NodeEventCallbacksEx.ms"), #(NodeEventCallback<0x000001A535A229F4>,\
#added, "MyCallback", "D:\My Documents\3ds Max\scripts\NodeEventCallbacksEx.ms"))
Number of event callbacks: 2
Callback 1 : NodeEventCallback<0x000001A535A18210>
Callback 2 : NodeEventCallback<0x000001A535A229F4>
482872L
OK