my funeral week

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

Maya:AnimationをPymelで操作する。その壱。

この間の3連休は結局全部仕事でした。おまけにちょっと風邪気味で気分最悪な今日この頃・・・。

さて!!!!!

いっつもやろうとしたときには忘れているAnimation周りの操作についてのメモ。です。 あらかじめよく使うことはモジュール化しとけば良いんだろうけど、毎度毎度「そんな大したことはしてないのでいいか」と放置した結果・・・毎回改めてコード打っています・・・。

長くなりそうなので、今回はそんなAnimation周りのメモ第一弾!



選択ノード内のアニメーション取得

アニメーション取得っていっても、単純にAnimationCurveノードを取得するだけのことが多い。
その昔、HIK(ヒューマンIK)のアニメーションをAtomではなく、独自手法(キーフレーム情報をまとめてXmlに書き込む)で操作したときに使ったのは覚えている。

そもそもなにをもってアニメーションの取得完了とするかはスクリプトの内容次第ではあるんだけど・・・

例えば、 グラフエディタで選択中のキーフレームを取得したいとか、それとも選択中のノードが持つアトリビュートの中でアニメイトされているものから取得したいのか。とか。

いずれにしても 最終的にはアニメーションカーブノード名を取得 してしまうのが、その後の処理が楽なんじゃないかなと思います。

というのも、アニメーションカーブノードを各種コマンドにターゲットとして渡す方が、アトリビュート名指定よりも精度が高いと考えているからです。AnimCurveノードとして、Pymelの機能を利用することもできるし。

まぁ、私みたいなプログラム素人ではなく、普段からDCCツールをバリバリ作ってます!って人からすると、そもそもPymel自体が重くて嫌だなんて話も聞きますから、絶対的に正義!ということはないですけど。

なかなか、この辺りは本職の人にかなわないところです。はい・・・。また誰か教えてください!!


グラフエディタで選択中のキーフレームから取得

画像で言うとこんな状況。

f:id:garysfirearms108:20180919223826j:plain

この場合で言うと、chestというノードのrotateYとrotateZのキーフレームを選択しています。

なので、出力結果的に望むのはchest.rotateYとZに接続されたアニメーションカーブノードです。

import pymel.core as pm

def getAnimCurveFromGraph():
    
    selected = pm.keyframe(q = 1, sl = 1, n = 1)
    
    animCurves = list()
    
    if not selected:
        
        return animCurves
    
    for i in selected:
        
        animCurveNode = pm.nodetypes.AnimCurve(i)
        
        animCurves.append(animCurveNode)
        
        print animCurveNode, "\n\t", type(animCurveNode)
        
    return animCurves

なるべく細かく残して起きたいので、冗長気味なコードですが、こんな感じですかね・・・?

keyframeにて主な取得をしています。 以下にそのフラグのメモ。

  • n
    • name の略で、アニメーションカーブのリストを返します。
  • sl
    • selection の略。文字通り、選択されているキーフレームに作用します。

注意点としましては、ここでカーブ名を取得しているのですが、出力されるのはあくまで名前です。Unicodeなのです。

別にこれでも良いのですが、念のためカーブノードとして取得したいので、一旦これをnodetypes.AnimCurveとして再取得しています。

この辺りは、リスト内包表記なんかで

animCurves = [pm.nodetypes.AnimCurve(name) for name in pm.keyframe(q = 1, sl = 1, n = 1)]

短縮してもよいと思います。

で、さっきの画像の状況でコードを実行すると・・・

結果

Chara01_chest_rotateY   

    class 'pymel.core.nodetypes.AnimCurveTA'  

Chara01_chest_rotateZ   

    class 'pymel.core.nodetypes.AnimCurveTA'  

きちんとアニメーションカーブノードが出力されていました!

ちなみにfindKeyframeを利用してもほぼ同じような結果が得られます。

selected = pm.findKeyframe(an = "keys", c = 1) #c = curve : カーブノードの名前を返します。

どっちでもよいと思いますが、findKeyframeはそもそもキーフレームを探すコマンドではあると思うので、

コードの文脈的にどうなんだろう・・・と思います。


選択中のノードが持つアトリビュートから取得

今度はもっとざっくりと選択中のノードからアニメーションカーブを取得します。

めんどくなってきたので、さっそくコードです!!

def getAnimCurveFromNode():
    
    animations = dict() #最終的に出力するもの。ノードをキーに、カーブリストを値とします。
    
    for node in pm.selected(): #選択中のノードを取得。
        
        animations[node] = list()
        
        for attribute in node.listAnimatable(): #アニメーション可能なアトリビュートを取得。
            
            animCurve = attribute.connections(t = "animCurve") #アニメーションカーブを取得
            
            animations[node].extend(animCurve)
            
    for i in animations.keys(): #ここはただの確認。
        
        print i, "\n\t", animations[i]
            
    return animations

手順としては、選択中のノードを取得して、アニメイタブルなアトリビュートのコネクションからアニメーションカーブノードを取得するだけです。

正直、ここから、自分の作るツールの仕様に応じて、各所にエラー処理を挟んでいくことは必須かと思いますが、大まかなコードはこんな感じです。

これを先ほどのChestノードを選択した状態で実行すると・・・

結果

chest
[nt.AnimCurveTA(u'Chara01_chest_rotateX'), nt.AnimCurveTA(u'Chara01_chest_rotateY'), nt.AnimCurveTA(u'Chara01_chest_rotateZ')]

こんな感じです。ノードに付随するアニメーションカーブノードの配列を取得できました。


今回は以上!!

次回は、キーフレームの操作についてまとめようと思います。さいなら~。