この記事は Maya Advent Calendar 2024 シリーズ1 の14日目の記事です。
前日は @9boz さんの「Mayaで反対側のfaceを取得したい1」、
翌日は @9boz さんの「UVchoserのはなし」です。
今回は OpenMaya API 2.0 の maya.api.OpenMayaAnim のネームスペースにある MAnimMessage クラスのコールバックのタイミングについてまとめていこうと思います。
この記事は Maya 2023.3 で検証したものです。
最初に書いておきますが、色々試した結果 1つだけまだ使い所が分かっていない「flushAnimKeyframeEditedCallbacks」というコールバックがあります。
分かり次第追記しますが、もし使い方をご存知の方がいらっしゃれば教えて下さい。
ちなみに過去にコールバック系で
「【Maya/Python】OpenMaya API2.0 の MSceneMessage クラス内のコールバックタイミング解説」
「【Maya/Python】OpenMaya API2.0 の Message 系クラス内のコールバックタイミング解説 1」
という記事も書いておりますのでご興味あればご覧下さい。
OpenMayaAnim.MAnimMessage
OpenMayaAnim.MAnimMessage.addAnimCurveEditedCallback()
import maya.api.OpenMayaAnim as oma2
def addAnimCurveEditedCallbackMethod(*args):
print(args[0]) # 変更のあったアニメーションカーブ (MFnAnimCurve) が MObjectArray で渡されます
oma2.MAnimMessage.addAnimCurveEditedCallback(addAnimCurveEditedCallbackMethod)
OpenMayaAnim.MAnimMessage.addAnimKeyframeEditCheckCallback()
import maya.api.OpenMayaAnim as oma2
def addAnimKeyframeEditCheckCallbackMethod(*args):
print(args[0]) # 変更のあった MPlug (例: pSphere1.translateX) が渡される
return True
oma2.MAnimMessage.addAnimKeyframeEditCheckCallback(addAnimKeyframeEditCheckCallbackMethod)
OpenMayaAnim.MAnimMessage.addAnimKeyframeEditedCallback()
シーン内でキーを打ったりアニメーションの値を変更してアニメーションカーブに変更があった場合に呼ばれます。
MObjectArray が渡ってきて、それを for で回して MObject の apiTypeStr を見てみると
・キーを追加したり削除したとき kKeyframeDeltaAddRemove
・キーの時間や値を変更したとき kKeyframeDeltaMove
・Tangent が変わったとき kKeyframeDeltaTangent
・Tangent のウェイト付き/非ウェイト付きを切り替えたとき kKeyframeDeltaWeighted
などの情報が分かります。
しかし!!!!
なんと、Maya 2023 時点では API 2.0 には MFnKeyframeDelta 系クラスが移植されていないので、この渡された MObjectArray をおそらく何にもできません(方法があれば教えて下さい)
ちなみに API 1.0 の方には MFnKeyframeDelta 系クラスがあり、試してみたところ
例えばキーの追加や削除したときは MFnKeyframeDeltaAddRemove でそのキーの値や時間やインデックスを取得したり、キーの値や時間を変更したときは MFnKeyframeDeltaMove で変更前と変更後の値や時間を取得したりできます。
import maya.api.OpenMayaAnim as oma2
def addAnimKeyframeEditedCallbackMethod(*args):
print(args[0]) # 変更のあったキーの MFnKeyframeDelta 系が MObjectArray で渡される
oma2.MAnimMessage.addAnimKeyframeEditedCallback(addAnimKeyframeEditedCallbackMethod)
OpenMayaAnim.MAnimMessage.addDisableImplicitControlCallback()
ベイク時に disableImplicitControl(ベイク後にIKハンドルによるIKの制御などを無効にするかどうか)というオプションが有効になっていた場合に、「シミュレーションのベイク処理」を実行し終わったあとに呼ばれます。
渡ってきた MDGModifier は ベイク処理を Undo/Redo するためのものだそうです。
import maya.api.OpenMaya as om2
def addDisableImplicitControlCallbackMethod(*args):
print(args[0]) # ベイクされたキーたちが MPlugArray で渡される
print(args[1]) # MDGModifier が渡される
oma2.MAnimMessage.addDisableImplicitControlCallback(addDisableImplicitControlCallbackMethod)
OpenMayaAnim.MAnimMessage.addNodeAnimKeyframeEditedCallback()
addAnimKeyframeEditedCallback と同じようにキーを打ったりアニメーションの値を変更した場合に呼ばれますが、異なる点は監視したいノードをセットする部分です。
特定のノードだけチェックしたい場合に使えます。
ただこちらも addAnimKeyframeEditedCallback と同様に第二引数に渡される MObjectArrayは MFnKeyframeDelta 系のデータとなっております。
import maya.api.OpenMaya as om2
import maya.api.OpenMayaAnim as oma2
def addNodeAnimKeyframeEditedCallbackMethod(*args):
print(args[0]) # 変更のあったアニメーションカーブ (MFnAnimCurve) が渡される
print(args[1]) # 変更のあったキーの MFnKeyframeDelta 系が MObjectArray で渡される
def getAnimNodes(transNode):
animNodeList = []
connectionPlugs = transNode.getConnections()
for cPlug in connectionPlugs:
if cPlug.isKeyable == False: # キーが設定できないプラグはパス
continue
srcConnect = cPlug.source()
if srcConnect.node().hasFn(om2.MFn.kAnimCurve):
animCurve = oma2.MFnAnimCurve(srcConnect.node())
animNodeList.append(animCurve)
return animNodeList
selList = om2.MGlobal.getActiveSelectionList()
mDagPath = selList.getDagPath(0)
transNode = om2.MFnTransform(mDagPath)
animNodeList = getAnimNodes(transNode)
oma2.MAnimMessage.addNodeAnimKeyframeEditedCallback(animNodeList[0].object(), addNodeAnimKeyframeEditedCallbackMethod) # とりあえず animNodeList の1つ目だけ渡す例
OpenMayaAnim.MAnimMessage.addPostBakeResultsCallback()
「シミュレーションのベイク処理」を実行し終わったあとに呼ばれます。
import maya.api.OpenMayaAnim as oma2
def addPostBakeResultsCallbackMethod(*args):
print(args[0]) # ベイクされたキーたちが MPlugArray で渡される
print(args[1]) # MDGModifier が渡される
oma2.MAnimMessage.addPostBakeResultsCallback(addPostBakeResultsCallbackMethod)
OpenMayaAnim.MAnimMessage.addPreBakeResultsCallback()
「シミュレーションのベイク処理」の実行直前に呼ばれます。
import maya.api.OpenMayaAnim as oma2
def addPostBakeResultsCallbackMethod(*args):
print(args[0]) # ベイクされたキーたちが MPlugArray で渡される
print(args[1]) # MDGModifier が渡される
oma2.MAnimMessage.addPostBakeResultsCallback(addPostBakeResultsCallbackMethod)
OpenMayaAnim.MAnimMessage.flushAnimKeyframeEditedCallbacks()
冒頭でも書きましたが、まだこのコールバックの使い所が分かっていません…
この関数の説明の Google 翻訳版を載せておきます。
「アニメーション キーフレーム編集コールバックは、アイドル イベントでのみ発行されるようにキューに入れられます。
特定の時間にコールバックを発行することが必要な場合があります。
このメソッドはこの機能を提供します。
すべてのアニメーション キーフレーム編集コールバックをフラッシュし、その中に含まれるデータを使用してコールバックを発行するように強制します。」
import maya.api.OpenMayaAnim as oma2
oma2.MAnimMessage.flushAnimKeyframeEditedCallbacks()
コメントをお書きください