この記事は Maya Advent Calendar 2025 シリーズ2 の25日目の記事です。
自分の中での毎年のルーティンになりつつある、API2.0 の Message 系クラスの解説がなんとか間に合いました。
今回は OpenMaya API 2.0 の maya.api.OpenMaya.MCommandMessage あるコールバックのタイミングについてまとめていこうと思います。
この記事は Maya 2024.2.4 で検証したものです。
ちなみに過去にコールバック系で
「【Maya/Python】OpenMaya API2.0 の MAnimMessage のコールバックタイミング解説」
「【Maya/Python】OpenMaya API2.0 の MSceneMessage クラス内のコールバックタイミング解説」
「【Maya/Python】OpenMaya API2.0 の Message 系クラス内のコールバックタイミング解説 1」
という記事も書いておりますのでご興味あればご覧下さい。
OpenMaya.MCommandMessage
OpenMaya.MCommandMessage.addCommandCallback()
import maya.api.OpenMaya as om2
def addCommandCallbackMethod(*args):
print(args[0]) # 実行された MEL コマンドが文字列で渡されます
om2.MCommandMessage.addCommandCallback(addCommandCallbackMethod)
OpenMaya.MCommandMessage.addCommandOutputCallback()
上の addCommandCallback と少し似てはいますが、こちらはスクリプトエディタに文字が出力されるたびに呼ばれます。
なので、Python 側で print 文を実行しても呼ばれるので、どういう情報が取れるのかテストしようと print したら、無限ループになってしまったので、サンプルコードではテキストファイルに内容を出力するようにしています。
コールバックの args[0] にスクリプトエディタに出力されているメッセージ、args[1] にメッセージのタイプ ( int ) が渡されます。
メッセージタイプの番号が何かといいますと、公式ヘルプに載っていますがこんな感じになっています。
int kDisplay = 1
int kError = 4
int kHistory = 0
int kInfo = 2
int kResult = 5
int kStackTrace = 6
int kWarning = 3
このコールバックがどんなときに使えるかといいますと、なるほど!と思った例がこちらの BigRoy さんのノードのサイクルチェックツールで、17 行目でメッセージタイプが kWarning かどうかをチェック、21 行目でメッセージが "Cycle on" という文字列で始まっているかどうかをチェックして処理を実行されています。
このように何か特定のエラーや警告が出たタイミングをキャッチして任意の処理を走らせたいときに使えます。
import maya.api.OpenMayaAnim as oma2
from datetime import datetime
def addCommandOutputCallbackMethod(*args):
log_file_path = "D:/Maya_addCommandOutputCallbackMethod_Log.txt"
dt = datetime.now()
dataStr = dt.strftime("%Y-%m-%d_%H%M%S")
try:
with open(log_file_path, mode = "a") as f:
f.write(f"addCommandOutputCallbackMethod {dataStr} ====================================================\n")
print(f" message = {args[0]}")
print(f" messageType(int) = {args[1]}")
except:
pass
om2.MCommandMessage.addCommandOutputCallback(addCommandOutputCallbackMethod)
OpenMaya.MCommandMessage.addCommandOutputFilterCallback()
上の addCommandOutputCallback と基本は同じなのですが、こちらは関数名に Filter とついているように、出力されるログをスクリプトエディタに出力するかどうかをフィルタリングしたいときに使用します。
必ず bool 値を返す必要があり、True を返すと出力されなくなり、False を返すと通常通り出力されます。
例えば、
if args[0].startswith("poly"):
return True
みたいに書いておくと、ポリゴンのプリミティブを生成したときの「polySphere -r 1 -sx 20 -sy 20 -ax 0 1 0 -cuv 2 -ch 1;」のようなログがスクリプトエディタには出力されなくなります。
import maya.api.OpenMayaAnim as oma2
from datetime import datetime
def addCommandOutputFilterCallbackMethod(*args):
log_file_path = "D:/Maya_addCommandOutputFilterCallbackMethod_Log.txt"
dt = datetime.now()
dataStr = dt.strftime("%Y-%m-%d_%H%M%S")
try:
with open(log_file_path, mode = "a") as f:
f.write(f"addCommandOutputFilterCallbackMethod {dataStr} ====================================================\n")
for arg in args:
f.write(f" arg = {arg}, type = {type(arg)}\n")
except:
pass
return False
om2.MCommandMessage.addCommandOutputFilterCallback(addCommandOutputFilterCallbackMethod)
OpenMaya.MCommandMessage.addProcCallback()
こちらは1つ目の addCommandCallback と似ていて、MEL プロシージャが実行されるたびに呼ばれます。
例えば、下のような MEL とそれを呼び出す Python があったとして、その MEL の呼び出し前に addProcCallback を設定しておき、MEL を実行後にすぐにそのコールバックを削除してみると、どうなるか。
# Sample Code (MEL) ====================================
proc LocalProcTest1()
{
print("< Local Proc Test 1 >");
}
proc LocalProcTest2()
{
print("< Local Proc Test 2 >");
}
global proc GlobalProcTest()
{
print("< Global Proc Test Start >");
LocalProcTest1();
LocalProcTest2();
print("< Global Proc Test End >");
}
import maya.api.OpenMaya as om2
import maya.mel as mel
def addProcCallbackMethod(*args):
print("\n" + "addProcCallbackMethod ====================================================")
print(args[0]) # プロシージャ名
print(args[1]) # プロシージャの呼び出しの ID
print(args[2]) # 実行したプロシージャの呼び出し直前は True, 呼び出し後は False
print(args[3]) # MEL プロシージャなら 0, MEL コマンドなら 1
addProcCallbackID = om2.MCommandMessage.addProcCallback(addProcCallbackMethod)
mel.eval("GlobalProcTest;")
om2.MEventMessage.removeCallback(addProcCallbackID)
# ===============================================
これを実行したあとにスクリプトエディタに出力されるのはこんな感じです。
addProcCallbackMethod ====================================================
GlobalProcTest
0
True
0
< Global Proc Test Start >
addProcCallbackMethod ====================================================
LocalProcTest1
1
True
0
< Local Proc Test 1 >
addProcCallbackMethod ====================================================
LocalProcTest1
1
False
0
addProcCallbackMethod ====================================================
LocalProcTest2
2
True
0
< Local Proc Test 2 >
addProcCallbackMethod ====================================================
LocalProcTest2
2
False
0
< Global Proc Test End >
addProcCallbackMethod ====================================================
GlobalProcTest
0
False
0
こちらも1つ目同様、公式ヘルプに書かれているようにコールバックを設定したままにしておくと、Maya 操作時の MEL 実行によって大量に呼び出されて Maya のパフォーマンスが落ちるので、必要な場面以外ではなるべく早くコールバックの設定解除した方が良いようです。
ただ、呼び出す MEL の前後のタイミングをキャッチして、任意の処理を挟むことができるので、処理のチェックなどに使えるかもしれませんね。

コメントをお書きください