【Maya/Python】OpenMaya API2.0 の Message 系クラス内のコールバックタイミング解説 1

この記事は Maya Advent Calendar 2023 シリーズ2 の14日目の記事です。(書いたのは 12/24 ですが)

 

シリーズ1の前日は @9boz さんの「mayaのプレイブラストをffmpegでmp4にしてみる2」、

当日は @cr_coyote さんの「スクリプトでAnimCurveをフィルタリング!」、

翌日は @9boz さんの「Mayaで ファイルを開かずにreferenceしてるファイルを知りたい」です。

シリーズ2の翌日は @9boz さんの「mayaでボクセルっぽいものを生成」です。

 

今回は OpenMaya API 2.0 の Message 系クラスにある様々なコールバックのタイミングについてまとめていこうと思います。

※ Message 系のコールバック = maya.cmds にある scriptJob と似たようなもの

この記事で紹介している Message は

・MCameraMessage

・MObjectSetMessage

・MDGMessage

・MModelMessage

で、Maya 2022.5 で検証したものです。

 

Message 系クラスは他にもたくさんあるので、徐々に紹介できたらいいなと思い、

記事のタイトルの末尾に 1 とつけています。

近いうちに、とは思いつつ来年の Advent Calendar で書いている未来が見えますが…

 

ちなみに2020年に「【Maya/Python】OpenMaya API2.0 の MSceneMessage クラス内のコールバックタイミング解説」という記事も書いておりますのでご興味あればご覧下さい。

※この中で MSceneMessage の addCheck~ 系が API2.0 だとエラーになると書いていましたが、登録する関数側の書き方の問題( return True/False を書いてなかったのがエラーの原因 )だという事に少し前に気付いたので追記しています。


OpenMaya.MCameraMessage

OpenMaya.MCameraMessage.addBeginManipulationCallback()

第一引数に CameraShape の MObject を渡す必要あります。 渡したカメラがビューポートに設定されている場合に移動回転(ビューポートをまわしたり)され始めたときに呼ばれます。
# Sample Code ===================================

import maya.api.OpenMaya as om2

 

def addBeginManipulationCallbackMethod(*args):

    print(args[0]) # 対象ノードの MObject

 

selList = om2.MGlobal.getActiveSelectionList() # CameraShape を選択した状態
mObject = selList.getDependNode(0)

om2.MCameraMessage.addBeginManipulationCallback(mObject, addBeginManipulationCallbackMethod)

 

OpenMaya.MCameraMessage.addEndManipulationCallback()

第一引数に CameraShape の MObject を渡す必要あります。 渡したカメラがビューポートに設定されている場合に移動回転(ビューポートをまわしたり)し終わったときに呼ばれます。
# Sample Code ===================================

import maya.api.OpenMaya as om2

 

def addEndManipulationCallbackMethod(*args):

    print(args[0]) # 対象ノードの MObject

 

selList = om2.MGlobal.getActiveSelectionList() # CameraShape を選択した状態
mObject = selList.getDependNode(0)

om2.MCameraMessage.addEndManipulationCallback(mObject, addEndManipulationCallbackMethod)

 


OpenMaya.MObjectSetMessage

OpenMaya.MObjectSetMessage.addSetMembersModifiedCallback()

第一引数に Set ノード の MObject を渡すことで, そのセットに何かが追加されたときに呼ばれます。
# Sample Code ===================================

import maya.api.OpenMaya as om2

 

def addSetMembersModifiedCallbackMethod(*args):

    print(args[0]) # 対象ノードの MObject

 

selList = om2.MGlobal.getActiveSelectionList() # Set を選択した状態
mObject = selList.getDependNode(0)

om2.MObjectSetMessage.addSetMembersModifiedCallback(mObject, addSetMembersModifiedCallbackMethod)

 


OpenMaya.MDGMessage

OpenMaya.MDGMessage.addPreConnectionCallback()

なにかのノードの 接続 or 切断 があったときに呼ばれる( addConnectionCallbackMethod の前)
# Sample Code ===================================

import maya.api.OpenMaya as om2

 

def addConnectionCallbackMethod(*args):

    print(args[0]) # src MPlug

    print(args[1]) # dst MPlug

    print(args[2]) # 接続されたときは True, 切断されたときは False

 

om2.MDGMessage.addPreConnectionCallback(addPreConnectionCallbackMethod)

 

OpenMaya.MDGMessage.addConnectionCallback()

なにかのノードの 接続 or 切断 があったときに呼ばれる( addPreConnectionCallbackMethod の後)
# Sample Code ===================================

import maya.api.OpenMaya as om2

 

def addConnectionCallbackMethod(*args):

    print(args[0]) # src MPlug

    print(args[1]) # dst MPlug

    print(args[2]) # 接続されたときは True, 切断されたときは False

 

om2.MDGMessage.addConnectionCallback(addConnectionCallbackMethod)

 

OpenMaya.MDGMessage.addDelayedTimeChangeCallback()

時間が変更されたときに呼ばれる
# Sample Code ===================================

import maya.api.OpenMaya as om2

 

def addDelayedTimeChangeCallbackMethod(*args):

    print(args[0]) # 変更後の MTime

 

om2.MDGMessage.addDelayedTimeChangeCallback(addDelayedTimeChangeCallbackMethod)

 

OpenMaya.MDGMessage.addDelayedTimeChangeRunupCallback()

時間が変更されたときに呼ばれる
(※説明を読むとダイナミクス関連のようですが、addDelayedTimeChangeCallbackMethod との違いはわからず…)
# Sample Code ===================================

import maya.api.OpenMaya as om2

 

def addDelayedTimeChangeRunupCallbackMethod(*args):

    print(args[0]) # 変更後の MTime

 

om2.MDGMessage.addDelayedTimeChangeRunupCallback(addDelayedTimeChangeRunupCallbackMethod)

 

OpenMaya.MDGMessage.addForceUpdateCallback()

時間が変更され、Dependency Graph がすべて評価されたあとに呼ばれる

 

# Sample Code ===================================

import maya.api.OpenMaya as om2

 

def addForceUpdateCallbackMethod(*args):

    print(args[0]) # 変更後の MTime

 

om2.MDGMessage.addForceUpdateCallback(addForceUpdateCallbackMethod)

 

OpenMaya.MDGMessage.addNodeAddedCallback()

設定時に指定した nodeType のノードがシーンに追加されるたびに呼ばれます。
指定する nodeType は apiType ではなく, nodeType コマンドそのままでも取得できるノードタイプを文字列で指定します。
 (今回の例の場合は mesh を指定しているので mesh ノードが追加されるたび)

 

# Sample Code ===================================

import maya.api.OpenMaya as om2

 

def addNodeAddedCallbackMethod(*args):

    print(args[0]) # 対象ノードの MObject

 

om2.MDGMessage.addNodeAddedCallback(addNodeAddedCallbackMethod, "mesh")

 

OpenMaya.MDGMessage.addNodeChangeUuidCheckCallback()

rename コマンドの uuid フラグを使って, uuid を変更したときなどに呼ばれる

 

# Sample Code ===================================

import maya.api.OpenMaya as om2

 

def addNodeChangeUuidCheckCallbackMethod(*args):

    print(args[0]) # 適用されるかどうかの bool

    print(args[1]) # 対象ノードの MObject

    print(args[2]) # 変更後の UUID

 

om2.MDGMessage.addNodeChangeUuidCheckCallback(addNodeChangeUuidCheckCallbackMethod)

 

OpenMaya.MDGMessage.addNodeRemovedCallback()

設定時に指定した nodeType のノードがシーンに削除されるたびに呼ばれます。
指定する nodeType は apiType ではなく, nodeType コマンドそのままでも取得できるノードタイプを文字列で指定します。
(今回の例の場合は mesh を指定しているので mesh が削除されるたび)

 

# Sample Code ===================================

import maya.api.OpenMaya as om2

 

def addNodeRemovedCallbackMethod(*args):

    print(args[0]) # 対象ノードの MObject

 

om2.MDGMessage.addNodeRemovedCallback(addNodeRemovedCallbackMethod, "mesh")

 

OpenMaya.MDGMessage.addTimeChangeCallback()

時間が変更されたときに呼ばれる

 

# Sample Code ===================================

import maya.api.OpenMaya as om2

 

def addTimeChangeCallbackMethod(*args):

    print(args[0]) # 変更後の MTime

 

om2.MDGMessage.addTimeChangeCallback(addTimeChangeCallbackMethod)

 


OpenMaya.MModelMessage

OpenMaya.MModelMessage.addAfterDuplicateCallback()

複製コマンドが呼ばれた後に呼ばれる( addBeforeDuplicateCallbackMethod の後)

 

# Sample Code ===================================

import maya.api.OpenMaya as om2

 

def addAfterDuplicateCallbackMethod(*args):

    pass

 

om2.MModelMessage.addAfterDuplicateCallback(addAfterDuplicateCallbackMethod)

 

OpenMaya.MModelMessage.addBeforeDuplicateCallback()

複製コマンドが呼ばれる前に呼ばれる( addAfterDuplicateCallbackMethod の前)

 

# Sample Code ===================================

import maya.api.OpenMaya as om2

 

def addBeforeDuplicateCallbackMethod(*args):

    pass

 

om2.MModelMessage.addBeforeDuplicateCallback(addBeforeDuplicateCallbackMethod)

 

OpenMaya.MModelMessage.addCallback()

選択を変更したときに呼ばれる(scriptJob の SelectionChanged と同じ)

addBeforeDuplicateCallback と addAfterDuplicateCallback と一緒に実行した場合、

 ①addBeforeDuplicateCallbackMethod

 ②ddCallbackMethod

 ③addAfterDuplicateCallbackMethod

の順に実行されます。

 

# Sample Code ===================================

import maya.api.OpenMaya as om2

 

def addCallbackMethod(*args):

    pass

 

om2.MModelMessage.addCallback(om2.MModelMessage.kActiveListModified, addCallbackMethod)

 

OpenMaya.MModelMessage.addNodeAddedToModelCallback()

第一引数で指定した dag node の MObject が Maya モデルに追加されようとするときに呼ばれる、らしいのですが、色々試しても処理の実行条件が未だにわからず…

(ご存知の方がいらっしゃったら教えて下さい)

 

# Sample Code ===================================

import maya.api.OpenMaya as om2

 

def addNodeAddedToModelCallbackMethod(*args):

    print(args[0]) # 対象ノードの MObject

 

selList = om2.MGlobal.getActiveSelectionList() # 対象ノードを選択した状態
mObject = selList.getDependNode(0)

om2.MModelMessage.addNodeAddedToModelCallback(mObject, addNodeAddedToModelCallbackMethod)

 

OpenMaya.MModelMessage.addNodeRemovedFromModelCallback()

第一引数で指定した dag node の MObject が Maya モデルから削除されるときに呼ばれる。

 

# Sample Code ===================================

import maya.api.OpenMaya as om2

 

def addNodeRemovedFromModelCallbackMethod(*args):

    print(args[0]) # 対象ノードの MObject

 

selList = om2.MGlobal.getActiveSelectionList() # 対象ノードを選択した状態
mObject = selList.getDependNode(0)

om2.MModelMessage.addNodeRemovedFromModelCallback(mObject, addNodeRemovedFromModelCallbackMethod)