LoginSignup
6
3

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-12-22

この記事は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にフックさせる系は便利ですが、引き換えに操作レスポンスを悪くする可能性があるので、
ここらへんは意識できるといいですね!

6
3
0

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
  3. You can use dark theme
What you can do with signing up
6
3