MayaのGUIからPython実行した時のアンドゥ とろわ

     MayaのPythonでGUIを作るとき、ボクはよくクラスを使います。
     で、クラスの中に変数作って、GUIの名前をドンドンそこへつっこんで行きます。
     これなら全部クラスの中に情報が保持されているんで、名前管理とかが楽チンです(え、これって邪道?)

     ついでにボタンを押したときやUIのリフレッシュなどもメソッドととして登録してしまいます。

     さて問題なのが、上記方法で作ったGUIクラスで、ボタンを押したときなどにメソッドを呼び出したいんですが、Mayaと同じ感覚では上手くいかないですね・・・

    #実行しても出来たウィンドウのボタンを押してもエラーがでます。
    import maya.cmds as mc
    class GUI( object ):
        def __init__( self ):
            if mc.window( 'testWindow', ex=True ):
                mc.deleteUI( 'testWindow' )
            mc.window( 'testWindow' )
    
            mc.paneLayout()
            mc.button( l='Create Sphere', c='self.create' )
    
            mc.showWindow( 'testWindow' )
        def create( self, *tmp ):
            for i in range( 0, 10 ):
            mc.sphere()
    

    問題は下線部の部分。ボタンからコマンドを発行する場合、名前がグローバル空間じゃないとダメなんです。
    selfはGUIクラス内で自身を表すキーワードなんで、当然グローバル空間にはいませんorz

    で、コマンドを文字列として囲むから呼ぶときにグローバルで呼ばれてしまうんで、直接=でつないでしまい、インスタンスとして呼び出せばいいんでね?と思い、早速実行。下線部を以下に置き換えてみました。
    mc.button(  l='Create Sphere', c=self.create )
     ま、self.createにあるコーテーション(')をとっただけなんですが・・・

     今度は成功! と、ここまでは前置きです。問題はここから
    MayaのPythonでGUIから上記のようにコマンドにインスタンスとして呼び出した場合、アンドゥの挙動がおかしくなります・・・上記例の場合、createメソッドのルーチンは10回sphereを作ると言うものなんですが、アンドゥして元の状態に戻るためには10回アンドゥしないといけません。そう、スクリプト内でやったMayaのシーンに影響するコマンドすべてが履歴として残ります
     え、何そのmaxScript・・・

    解決方法 → コマンドを(ダブル)コーテーションでくくり、文字列として渡します。
     永久ループ・・・

     もうこうなってくるとPython内では解決出来なさそうなので、今回はMayaの機能を使って強引にやってみようと思います。
    ただしこの方法はMaya2009以降じゃないと使えないと言う問題があるのですが・・・
    MayaのコマンドにundoInfoと言うのがあるのですが、Maya2009からopenChunkcloseChunkと言うフラグが追加されました。
    openChunkを実行してからcloseChunkを実行するまでのMayaのオペレーションを一つのundoキューにまとめてくれると言う、個人的には待望の機能です!
     これを上記クラスのcreateメソッドで使用してやると、今回のアンドゥ問題をとりあえずは解決できそうです。
     ただ、これを普通にスクリプトの最初と最後に入れてやるだけではエラーが起こったときに怖いので、tryを使って安全性を高めてやります。
    上記を踏まえて最初のスクリプトの青字部分を下記のように変更します。
            mc.undoInfo( openChunk=True )
            try:
                for i in range( 0, 10 ):
                    mc.sphere()
            except Exception, inst:
                raise type(inst), inst
            finally:
                mc.undoInfo( closeChunk=True )
    

     これでアンドゥの挙動も問題なくなりました。
     また、エラーが起こった場合はfinallyでcloseChunkを実行してからraiseでエラーを吐いてくれるので、途中スクリプトが何らかの障害にあってつまずいても、問題ないはずです。
     Pythonはエラーが発生した時の挙動も柔軟に制御できるので、こういう場合に非常に助かりますね~。
    スポンサーサイト

    コメントの投稿

    非公開コメント

    undoInfo!!!!
    それは知らなかった!!!!

    なんというPython力。
    勉強になります。

    No title

     こんにちわ、コメントありがとうございます!

     undoInfoはContextやSliderのCCフラグなんかで使う時も威力を発揮する、個人的には一押しの機能だったんですが、まさかこんな所で役立つとは・・・って感じでした

     Pythonは奥が深すぎて、僕自身全然追いつけてないっすヨ~(汗
    でも発見が多くて面白いんでこれからも頑張ります!
    プロフィール

    Eske

    Author:Eske
    萌えイラストレーターを目指す3DCGイラストレーター。
    現在ポケモンカードゲーム、ガンダムトライエイジ、ガンダムコンクエスト、妖怪ウォッチとりつきカードゲームなどで3DCGを使用したイラストレーターとして参加中。

    主にここでは日々気づいたメモなんかを残してます。
    イラストのお仕事も受け付けております。ココのメールアドレスからご連絡できますので、お気軽にご相談下さい。

    最新記事
    最新コメント
    カテゴリ
    最新トラックバック
    月別アーカイブ
    検索フォーム
    リンク
    QRコード
    QR