<< TOP

Maya; Python で Clip 保存ツール を作ろう!!

Maya; Let's Make a SaveClip Tool with Python
(Used Maya 2014, 2015)
    プロローグ; Prologue
 Maya の標準機能でClipを保存するツールは ブラウザが表示 されるものです。
TraxEditorで ファイル>アニメーションクリップの書き出し です。
また、バイザーでは、右マウスクリック>書き出し もあります。

そこで思うのです。
TraxEditor 上に配置された Clip を直接保存するツールをスクリプトで作れないかなー
って、いざ挑戦してみると・・・意外に・・・ハマります!!
(Mayaの書き込みフォーラムでも沢山の人がハマってます~)

 今回は、MELの解き方と合わせて、
上記機能を実現するスクリプトを Pythonで組んでみたい と思います。

さ~、どんな困難に直面しするのか、皆さんも謎解きに御参加してください。

あ、ツールだけ使いたい、でもOKなんですがね。

 なお、このサイトで掲載している事例の決まり事ですが、
使用に関しては自己責任でよろしくお願い申し上げます。
(Maya2014、2015で動作確認しています)

Please use it as your own risk.

Windows7 Professional 64Bit、Intel Core i7-3930K (3.20GHz,6コア/12スレッド)
メモリ16GB、NVIDIA GeForce GTX560 Ti 2GB (メモリ2GB)








 標準機能
     まずは、Mayaの標準機能で TraxEditor 上の Clip を保存して、そのログを見てみましょう。
    Clip だけを選択状態にし、ファイル>アニメーションクリップの書き出し を実行します。

    すると doExportClipArgList 1 {"clipEditorPanel2ClipEditor"}; という Melコマンド を発見できます。

     では、もう1つの方法はどうでしょうか。
    バイザーでは、右マウスクリック>書き出し を実行します。



    すると doExportClipArgList 2 { "", "joint_1anmSource"}; という Melコマンド を発見できます。

    なんだ、同じコマンドじゃん、となります。

    doExportClipArgList の後の数字は、だいたいMelの場合 バージョン番号で 、
    の時はClipが選択されている状態で実行する
    の時は 出力するClipの名前 で実行する
    ・・のではないかと 推測できます。

    では、Melの探検準備OK、覗いてみることにしましょう。


 doExportClipArgList って?
     さて、doExportClipArgList がどこにあるかのは いつもの呪文 whatIs を使います。
    スクリプトエディタのMELタブにて whatIs doExportClipArgList を実行します。



    すると、C:/Program Files/Autodesk/Maya2015/scripts/others/doExportClipArgList.mel だって分ります。

    では、doExportClipArgList.mel を手持ちのWindows用スクリプトエディタ開いてみます。
    だいたい、先頭部分にフラグの説明が書いてあります。思っていた感じの番号の説明が書いてありますね。



    そこまで分ったので、doExportClipArgList にクリップ名を渡している部分を探してみましょう。 
    doExportClipArgList を実行している部分です。



     バージョン番号 文字列 を doExportClipArgList に渡しています。
    そして、ブラウサー fileBrowser を立ち上げて clipEditorExportClip を実行している部分があります。

    次はこの clipEditorExportClip が何をしているかが分れば良いことになります。


    すると、出力するファイルの種類はClipの場合、Asciiの ma って分っていて、
    file コマンド と フラグ が書いてあるので、おお、しめしめ これで求めるスクリプトを想像してみることが出来ます。

    file -f -type "mayaAscii" -exportSelected -channels true -constructionHistory true "F:/user_maya/Maya2015/clips/joint_1anm2.ma";

    Python 的に書き直すと、

    cmds.file('F:/user_maya/Maya2015/clips/joint_1anm2.ma',type='mayaAscii',force=True,exportSelected=True,channels=True, constructionHistory=True)

    でしょうか。

    いざ実行! 結果、エラーも無く、あっと言う間に終わるので、OKか?? って思うじゃん。

    出力されたファイルの大きさを、Mayaの標準機能で出力した ma ファイルと比べると、少ない事に気が付きます。
    そして、実際に TraxEditor に今スクリプトで保存したClipを読み込もうとすると・・・失敗します!! 

      Why? なぜでしょう・・・



 clipLibrary
     出力される Clipのデータは ASCIIファイル なので、テキストエディターで開いて違う部分を見てみることにしましょう。


     すると、12行目ではやくも違いを見つけることが出来ます。

    Mayaの標準ツールで保存した .ma には、clipLibrary の項目があり、その中に 各ノードのデータ が記述されています。
    この部分がごっそり無いのに気が付きます。これじゃ動かないわけです。

     では、改めて doExportClipArgList.mel の clipEditorExportClip 部分、先に発見した file コマンドの少し上あたりに注目します。
    すると Clip に関する記述が 2つあるのが解ります。


     下のは sourceClip と書いてあるので、ソースのClipも追加選択した状態で出力するのか とわかります。
    もう1つ、clip に isolate フラグを立てた値を渡しています。 ここで ピン と来た方は Clip のコマンド表を見た事のある人ですね。見てみましょう。


      isolate(i) 
        このフラグは name フラグと一緒に使用し、1 つまたは複数のクリップを新規のクリップ ライブラリにコピーするように指定します。
        このフラグの最も一般的な用途は、キャラクタのすべてのクリップではなく、特定のクリップのみの書き出しです。

    これです。!!
    つまり、クリップのライブラリーを取得して、Clipのソースと共に選択した状態で file コマンドで出力する ようなんです。

    Melをもっと簡単に書くと、

    string $clipName = "joint_1anm";
    string $sourceClipName = `clip -q -scn $clipName`;
    string $result[] = `clip -isolate -name $sourceClipName`;
    select -clear;
    select $result[0];
    select -add $sourceClipName;
    file -f -type "mayaAscii" -exportSelected -channels true -constructionHistory true "F:/user_maya/Maya2015/clips/joint_1anm2.ma";

    です。
    Python に書き直し、Clipのみを選択した状態で、実行します。

    selected_clip = cmds.ls( sl=True )[0]
    selected_clip_source = cmds.clip(selected_clip,query=True,sourceClipName=True,allAbsolute=True)
    selected_clip_library = cmds.clip(isolate=True,name=selected_clip_source,allAbsolute=True)
    print selected_clip_library
    cmds.select(clear=True)
    cmds.select(selected_clip_library[0],replace=True)
    cmds.select(selected_clip_source,add=True)
    cmds.file('F:/user_maya/Maya2015/clips/joint_1anm2.ma',type='mayaAscii',force=True,exportSelected=True, channels=True, constructionHistory=True)
    
    結果
    [u'clipLibrary1', u'joint_1anmSource']


     これで書き出された .ma ファイルは見事に動きます。大成功です。

     途中に print 文を挟んでいます。
    すると 2つの文字がリストで出力されるのを認識して欲しかったからと、もう1つの理由は後で説明します。

    1つ目は、その2つ下の行で わざわざ selected_clip_library[0] と書いているのは 
    この2つのデータの内、最初の クリップ ライブラリ を設定したかったからだ と気が付きます。

    2つ目の理由は・・・・
    同じClipを選択した状態から何度か上のスクリプトを実行してみてください。

    結果
    [u'clipLibrary4', u'clipLibrary5', u'clipLibrary6', u'clipLibrary7', u'joint_1anmSource']


    ん?どんどん増えるぞ、やばくね?



 後処理
     またまた、 doExportClipArgList.mel の clipEditorExportClip 部分、先に発見した file コマンドの下あたりに注目します。
    すると clipLibraryに関する記述が続いているのがわかります。


    ファイルを出力した後、クリップライブラリーを消しているのです。
    そこで、記述も真似て、もし1つ以上あったらその分だけ全部消す というスクリプトを追加します。

    lib = cmds.ls(selected_clip_library,type='clipLibrary')
    if len(lib) != 0:
        for i in range(len(lib)):
            cmds.delete(lib[i])

    これで完成か!? と思い、先に出力したClipをTraxEditorに乗せてみます。
    そこで気が付くのは、1つ目の元のClipと同じっぽいけど違う動きの結果になったりしています。

      Why? なぜでしょう・・・



 絶対値の処理
     Clipを配置し、そのアトリビュートの チャンネルオフセット 項目を見ます。



     すると、全ての値が 相対値 になっています。
    追加される動きの時には相対値は便利ですが、通常のアニメーション編集の時は 絶対値 でないと理解できなくなります。
    元のClipを見ると絶対値になっているので、これは保存の仕方や前処理があるに違いない と考えます。

    またまた、 doExportClipArgList.mel の clipEditorExportClip 部分もっと最初の部分に注目します。
    Clip と ソースClip に何やら前処理をしている部分があることに気が付きます。


     この copyAbsoluteChannelsClipData も別Melファイルのコマンドです。(C:/Program Files/Autodesk/Maya2014/scripts/others/copyAbsoluteChannelsClipData.mel)
    今回はこのまま利用してしまいます。

    if selected_clip_source != selected_clip:
        mel.eval('copyAbsoluteChannelsClipData("%s","%s")' % (selected_clip_source,selected_clip))

     これを通して作成したClipをTraxEditor に配置してみると 絶対値 になっていて、元のClipを同じ動きをするようになりました。



    めでたしめでたし。

    以上です。



 save_clip.py
     という訳で  Clipを直接TraxEditorから保存するツール save_clip.py を公開します。 
    あくまでも自己責任でお使いください。 use as your own risk.


    Clipを直接TraxEditorから保存するツール
    (Maya2014,2015)

    save_clip.zip  1.15 KB 2015/03/19 現在





     
    という訳で、次回 は ... What's Next ...

      乞う、ご期待!! Stay tuned ..