my funeral week

少しでも日々の生活に変化を。

MayaScriptMemo_ScriptJobについて

f:id:garysfirearms108:20200328135743j:plain:w256

こんにちは。
今日はPymelに関する備忘録です。

ScriptJob

「選択中のノードを変更する」「タイムラインをスクラブする」「ディスプレイレイヤーを選択する」等々・・・ユーザーのMayaの操作を検知して、何かしらのアクションを実行したい。実現する最も簡単な方法は、恐らく「ScriptJob( )」を利用することだと思います。

スクリプトジョブとはMayaがIdle状態の時に検知されたイベントに任意のスクリプトをアタッチすることができるコマンドです。

起動中のMayaにスクリプトジョブが登録され、指定したイベントや条件に応じて実行されます。一度登録されると任意にスクリプトジョブをKillするか、Mayaを終了させるまで残ります。

ただし、アニメーションの再生中は実行されないみたいです。

色々と使用用途はあるでしょうが、私がよく利用する方法を備忘録的に記載します。


特定の操作に反応

import pymel.core as pm

def somethingAction ():
    print "action called"

mayaEvent = "SelectionChanged" # 既定のMayaイベント名
action = somethingAction # 任意のアクション

scriptJobNumber = pm.scriptJob(e = [mayaEvent, action]) # スクリプトジョブを登録

上記のコードでは、選択物の変更があった場合に「somethingAction()」が実行されるようにスクリプトジョブを登録しています。
登録したスクリプトジョブを後から削除する為 に、変数「scriptJobNumber」には登録番号が返り値として渡されます。

「pm.scriptJob()」の引数「e」は「event」の略称で、Mayaで定義されている 既定のイベントの文字列 が必要です。

  • よく使うイベント名
    • SelectionChanged
      • 選択している内容が変更されたか
    • timeChanged
      • 現在のフレームが変更されたか(頭が小文字なのに注意)

すべての既定のイベント名のリストは、下記のように「listEvents」フラグにて取得できます。

eventList = pm.scriptJob(listEvents = True)
for eventName in eventList:
    print eventName


登録したスクリプトジョブを削除

pm.script(kill = scriptJobNumber)

削除するには、引数「kill」に登録されている任意の スクリプトジョブ番号 を渡す必要があります。
先ほどのコード例のように予め登録時に番号を取得しておくか、引数「listJobs」を利用して、現在登録されているジョブのリストから該当の番号を取得することができます。

jobList = pm.scriptJob(listJobs = True)
for jobInfo in jobList:
    print jobInfo

ちなみに変数「jobInfo」の中身は下記のようなジョブ番号を含む、ジョブ内容のテキストになっています。

108: e=('SelectionChanged', )


UIとスクリプトジョブを結びつける

任意のUI(ウィンドウ等)とスクリプトジョブを結びつけることもできます。


UI要素の削除に合わせてスクリプトジョブを実行

def uiDeletedAction ():
    print "UI element deleted"

# 適当なウィンドウを作成
with pm.window("TestWindow"):
    with pm.columnLayout(adj = True):
        pm.text(l = "TextLabel")
        pm.button(l = "Button")

deletedAction = ["TestWindow", uiDeletedAction] 
jobNumber = pm.scriptJob(uid = deletedAction) # スクリプトジョブ登録

引数「uid」は「uiDeleted」の略称で、任意のUI要素の名前と実行して欲しいメソッドを渡すと、該当のUIが削除された際にスクリプトジョブが実行 され、その後にMayaがIdle状態になり次第、自動的にそのジョブはシーンからも削除されます。
上記のコード例ではウィンドウ名を渡しているので、ウィンドウが閉じられた時に実行されます。


UI要素にスクリプトジョブをアタッチ

def somethingAction ():
    print "action called"

# 適当なウィンドウを作成
with pm.window("TestWindow"):
    with pm.columnLayout(adj = True):
        pm.text(l = "TextLabel")
        pm.button(l = "Button")

attachedAction = ["timeChanged", somethingAction]
pm.scriptJob(e = attachedAction, p = "TestWindow") # スクリプトジョブ登録

引数「p」は「parent」の略で、任意のUI要素名を渡すことで、その UIにスクリプトジョブをアタッチし、UI要素の削除と共にスクリプトジョブも自動で削除されるようになります。注意点として、スクリプトジョブが実行されるタイミングの指定は別途行う必要 があります。
上記のコード例では、UI「TestWindow」が表示されている間、「タイムスライダのスクラブ」を行う度に、「somethingAction()」が実行されます。




今回はこんな感じです。

ScriptJobには他にもノードやアトリビュートにアタッチできたり、任意の条件に応じて実行させたり等、色々と便利ですが、使い方を間違えると高負荷やMaya自体のクラッシュにも繋がるので、使いどころはよく考えて利用しましょう・・・。

それでは、また。