search
LoginSignup
3

More than 1 year has passed since last update.

posted at

updated at

OpenMaya.MEventMessageとScriptJobの実行タイミングは違う

この記事はTakumi Akashiro ひとり Advent Calendar 2020の22日目の記事です。

始めに

MEventMessage、ScriptJobどちらもEventが発火したら登録したコールバック関数を実行させる仕組みですが、
実はMEventMessageとScriptJobの実行タイミングは違います。

コマンドリファレンスをしっかりと読んだことがある方は、何故かそうなる理解できると思います。

まずはどちらも試してみる

今回は分かりやすいSelectionChanged Eventにフックさせていきます

sample_scriptJob.py
#! python2
# encoding: utf-8
from maya import cmds


def print_func(text):
    print(text)


if __name__ == '__main__':
    if 'scriptjob_id' in globals() and cmds.scriptJob(ex=scriptjob_id):
        cmds.scriptJob(kill=scriptjob_id)
    scriptjob_id = cmds.scriptJob(event=["SelectionChanged", "print_func('SelectionChanged: ScriptJob')"])

22_01.gif

sample_m_event_message.py
#! python2
# encoding: utf-8
from maya.api import OpenMaya


def print_func(text):
    print(text)


if __name__ == '__main__':

    if 'm_event_message_cbk_id' in globals():  # コールバックIDが生きてるか確認する手段が思いつかなったのでtry-exceptで誤魔化す。
        try:
            OpenMaya.MEventMessage.removeCallback(m_event_message_cbk_id)
        except RuntimeError, UnicodeDecodeError:  # UnicodeDecodeErrorは日本語環境用
            pass
    m_event_message_cbk_id = OpenMaya.MEventMessage.addEventCallback("SelectionChanged", print_func, 'SelectionChanged: MEventMessage')

22_02.gif

ScriptJobもMEventMessageも同じく動いている'ように'見えますね!

MEventMessageとScriptJob、その違い

ではScriptEditorで以下を実行してみます。

#! python2
# encoding: utf-8
from maya import cmds

for x in range(3):
    cmds.select(cmds.ls(sl=True))

ScriptJob
image.png

OpenMaya.MEventMessage
image.png

なんということでしょう!
ScriptJobの方は1回しか実行されてないですが、MEventMessageは3回とも実行されててますね。

どうしてそうなるのか

これにはScriptjobの実行タイミングに秘密があります。
公式リファレンスを読んでみましょう。

スクリプト ジョブは、インタラクティブなアプリケーションでイベント ループに結び付けられています。
このジョブはアイドル イベント中に実行されます。
このことは、スクリプト ジョブがバッチ アプリケーションに存在しないことを意味しています。scriptJob コマンドは、バッチ モードでは何も行いません。
Command Reference: scriptJob - Maya ヘルプ より抜粋

というわけでScriptJobは処理がいったん終わって、アイドル状態にならないと動かないのです。

なのでScriptJobとMEventMessageを併用した状態で、さっきのスクリプトにprint文を足して動かすと……

#! python2
# encoding: utf-8
from maya import cmds

print('-'*10 + '\nStart')

for x in range(3):
    print('Selection_before: %s' % x)
    cmds.select(cmds.ls(sl=True))
    print('Selection_after: %s' % x)
    if x != 2:
        print('-'*10)

print('-'*10 + '\nEnd')

image.png

処理直後にMEventMessageが走り、処理が完全に終わったあと、
Mayaがアイドルになった段階でScriptJobがやっと実行されるわけです。

締め

違いが分かると、処理回数をできる限り減らすためにScriptJobを使ったり、
厳密に監視するためにMEventMessageを使うなど、使い方が分けられると思います。

Eventにフックさせる系は便利ですが、引き換えに操作レスポンスを悪くする可能性があるので、
ここらへんは意識できるといいですね!

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
3