<< TOP

Maya; Python で Rig用 ICON を作ろう!!

Maya; Let's Make a Rig ICON with Python
(Used Maya 2012, 2014, 2015)
    プロローグ; Prologue
 キャラクターアニメーション用の制御Rigの作成において、
見易い、理解しやすい、便利だ、とアニメーターに思わせるような工夫を施す事も
キャラクターセットアップの重要な作業です。
 (実はセットアップしている側としては、間違った事をされないように・・と考えていたりしますが・・・)

そこで、てっとりばやく、良い表示物が欲しい・・となった場合、
Softimageでは良くNullの表示形状を変更させて使っていました。
Mayaでは、色々なシーンを見ていくと、なんとなく似たような形の表示物を
多く使っていることに気が付くことでしょう。
これらはカーブなのですが、その複数のShapeノードを1つに結合して使用したり、
Shapeノードを他のものに移し変えて使う、ということも可能なのです。

 今回は、良く使えそうなカーブ形状を見真似して作成し、
便利なツールと合わせてまとめたものを Python で構築した例、
として紹介します。

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

Please use it as your own risk.

 PS
  一部カカーブの形状やスクリプトは既に公開されている
 ユーザーさんの記述を参考にさせて頂いた部分も含まれています。
 ありがたく使わせて頂きました、よろしくお願いします。

 Some custom shapes and scripts are refer to what was shown
formaly by users . Great thanks .
Windows7 Professional 64Bit、Intel Core i7-3930K (3.20GHz,6コア/12スレッド)
メモリ16GB、NVIDIA GeForce GTX560 Ti 2GB (メモリ2GB)






 カーブについて ;結合
     まずは カーブ について。
    作成>CVカーブツールオプション を開くと、カーブの設定画面が表示されます。
    カーブの次数 の設定では、当然 ○ 1 一次 が直線になり、○ 3 三次 が 曲線になります。

     この curve Pythonコマンド の説明で見ると、次数とは degree(d) のことであり、デフォルトが 3 だとわかります。

    ついでに、スクリプトでカーブを描くには以下のデータが必要だとも気が付きます。

        degree(d) カーブの次数。既定は 3 です。 (だいたい 1 か 3 です。)
          目に見えるカーブ スパンを作成するには、次数に 1 を足した数のカーブ ポイントが必要です。
          たとえば、3 次カーブには、4 個のポイントを配置する必要があります。
        point(p) ポイントの x、y、z の位置
        knot(k) ノットベクトルにあるノットの値。ノット値ごとに 1 フラグ。

     また、アトリビュートエディタでカーブ情報を見ると、
    形式次数コンポーネントの表示 項目に □ CVの表示 等があり、全てにチェックを入れると下図のような表示になります。


     と、ここで最も重要な点にも気が付いたと思いますが、カーブの形状データは Shapeデータである という点です。



    アウトライナーで ディスプレイ> [レ] シェイプ にチェックを入れてシェープノードを表示させると
    curveShape は Transformノードの子 という階層構造になっています。
    シェープだけ削除すると表示するものが無くなってしまいます。
     また気が付くのは、シェープ情報の親を変えることによってカーブを1つの表示物として扱えるようになる、という点です。
    なので、カーブの結合 とは parent コマンド で行うことになります。

    Locator に 正方形のシェープをくっ付けるには、以下の手順で行います。



     正方形のカーブを用意し、トランスフォームのフリーズヒストリの削除 (編集>種類ごとに削除>ヒストリ) をしておきます。
    正方形のシェープを選択、続いて Ctrl + で Locatorのグループノード を選択します。

    import maya.cmds as cmds
    
    cmds.parent(relative=True, shape=True)

    を実行します。すると、正方形の形がついたLocator になります。

    この方法は Joint にも有効で、下図のような 選択用のカーブシェープが付いた Joint を作ることも出来ます。
    回転方向にロックを付けておくと ICON表示 と 操作 が関連して見えて、アニメーションを付ける時に理解しやすいJointになります。
     (Jointの方向と くっ付けた CurveShapeの方向は、くっ付けた後にカーブシェイプの頂点を回転させて見た目に合わせています。)




    ★追加情報; カーブの長さ
     カーブの長さが分る簡単なコマンドをご紹介しておきます。

    最初、カーブを選択するとその名前が確認できます。その名前を arclen というコマンドに渡してみると 長さ が分ります。


    import maya.cmds as cmds
    
    print cmds.arclen( 'curve1' )
    
    3.56455588253



 ICONの作成 ;カーブのモデリング
     あまり Maya のモデリング については記述して来てませんが、
    カーブの作成で面白い方法がありましたのでちょっと紹介します。

    ポリゴンの球を作成し、分割数を30ぐらいにしておき、X軸に90度回転させておきます。
    この球を選択した状態で、上のメニューアイコンから 磁石の絵 [ライブサーフェイスなし] ってなっているボタンをクリックします。
    すると [ pSphere はライブです。]  という表示が出て、球面がカーブを描く際の下敷きになります。



      後は、カーブのシェルフで左から3番目の EPカーブツール でカーブを球面上に描いていきます。



      左右対称の円形矢印に仕上げます。


    回転や移動など編集をした後は、
    移動/回転/スケールのフリーズ (修正>トランスフォームのフリーズ) 履歴の削除 (編集>種類ごとに削除>ヒストリ) をしておきます。
    必ずこの2つをやってからデータ化をします。

     では次は、出来たカーブ矢印をデータ化してみましょう。



 カーブのデータ化 ;値の取得
     今度は、作成したカーブから必要なデータを取得して、最初に紹介した curve コマンド を使って カーブを再生成をしてみます。
    必要なデータとは、degree(d)=次数 、point(p)=ポイントの x、y、z の位置 、knot(k)=ノットベクトルにあるノットの値 です。

    カーブをデータから生成する時のコマンドの書き方は、

      cmds.curve(name='作成されるカーブの名前',d=次数,p=ポイントの x、y、z の位置, k=ノットベクトルにあるノットの値)

    です。
    では、先程作成した円形矢印カーブを使って、各データを取得してみましょう。

    1.  degree(d) 値の取得 ; 一旦、カーブを選択してみると、このカーブの名前が curve1 だと分ります。
       矢印カーブ curve1 を選択した状態で以下を実行します。

      cmds.getAttr( 'curve1.degree' )
      
      # 結果: 3 # 

    2.  point(p) 値の取得 ; いっぺんに取得出来る書き方があります。結構いっぱい出ます。

      cmds.getAttr( 'curve1.cv[*]' )
      
      # 結果: [
      (-1.1112534999848538, 2.4959175586702926, 0.14370895922185412), 
      (-0.9331233132338141, 2.563328364756063, 0.14413296666402145), 
      (-0.5768629397317305, 2.698149976927584, 0.1449809815483553), 
      ・・・ 
      (-1.111253499984741, 2.4959175586700435, 0.14370895922183932)] # 

    3.  knot(k) 値の取得 ; これはエラーが表示されることもあります。既に同名の Node がある場合など。
       その場合でも最後の行を、もう一回実行すると表示したりします。それでもダメな場合は、新しいシーンで試すなどします。

      cmds.createNode( 'curveInfo' )
      cmds.connectAttr( 'curveShape1.worldSpace', 'curveInfo1.inputCurve' )  
      cmds.getAttr( 'curveInfo1.knots[*]' )
      
      # 警告: 'curveShape1.worldSpace[0]' はすでに 'curveInfo1.inputCurve' に接続されています。 # 
      # エラー: line 1: RuntimeError: file <maya console> line 2: Maya コマンド エラー # 
      
      cmds.getAttr( 'curveInfo1.knots[*]' )
      
      # 結果: 
      [0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 
      17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 26.0, 26.0] # 


    以上で必要なデータはそろいました。
    これを curve コマンド に組み込めば カーブが再生されるはずです。

    cmds.curve(name='curve1',d=3,
        p=[(-1.1112534999848538, 2.4959175586702926, 0.14370895922185412),
            (-0.9331233132338141, 2.563328364756063, 0.14413296666402145),
            (-0.5768629397317305, 2.698149976927584, 0.1449809815483553),
            (0.010468042431126258, 2.74599266393373, 0.13862096096210494),
            (0.534990774046297, 2.7106081667485182, 0.16278902069019613),
            (1.2578118068473458, 2.4460833696756445, 0.07247680151801067),
            (1.1012887244926626, 2.4805608419678893, 0.4095576178332147),
            (0.9317770264436573, 2.443702620948175, 0.8666246868009936),
            (1.621582714787527, 2.231512788715753, 0.388169951654192),
            (2.11211977631732, 1.7474728230878585, 0.15802746641556129),
            (2.112113816590134, 1.7474710878882356, -0.15802606206936842),
            (1.6215977326470483, 2.2315179949867296, -0.3881769734764182),
            (0.9317229139545076, 2.4436835328118143, -0.8665980042262186),
            (1.1014901552208554, 2.4806305603810714, -0.4096566117686963),
            (1.257060193799814, 2.445825017900337, -0.07210768771421013),
            (0.5377957915342638, 2.7115718590149593, -0.16416648211247603),
            (-4.190341508384234e-07, 2.7423962511790343, -0.13348022857389805),
            (-0.5377941153976628, 2.7115719418108557, -0.16416635892297352),
            (-1.2570603382320027, 2.445824686716671, -0.07210818047221686),
            (-1.101485531234036, 2.4806318015364774, -0.40965467456429844),
            (-0.931736256758382, 2.4436788944682974, -0.8666050817499987),
            (-1.6215425469082625, 2.2315367306180405, -0.3881506009657419),
            (-2.112315494940899, 1.7474022077243718, -0.15812447493121792),
            (-2.1113625278628154, 1.747729603006845, 0.15839465566800492),
            (-1.6244014485670313, 2.230554546101922, 0.3867996966988733),
            (-0.9212536182159592, 2.447280240913892, 0.8717386960102025),
            (-1.1405579010411544, 2.4672086056127878, 0.3904711209107791),
            (-1.1210216336702121, 2.4863479076509583, 0.22596301311815253),
            (-1.111253499984741, 2.4959175586700435, 0.14370895922183932)],
        k=[0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 
            14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 26.0, 26.0])

    実行すると、おお、再生されました!!



     でも、うまくいかない時もあります。それは円みたいに閉じたカーブだったり します(この時は次数が1)
    その時は、なんと、円のカーブを生成する Mel コマンドを実行しているのです。

    mel.eval('CreateNURBSCircle')
    mel.eval('DeleteHistory')
    o_selected = cmds.ls(sl=True)[0]
    o_size = cmds.intSliderGrp('set_size', q=True, value=True)
    cmds.xform(o_selected, scale=(o_size, o_size, o_size) )
    cmds.makeIdentity( apply=True )




 Size設定項目を共通化するGUI ;Python
     さて、今回は カーブだけが作られるツールを省みて、それに改善点を入れて Python で作り込む、をしています。
    必要になるであろう機能としては、サイズの数値を最初に設定してその大きさで生成させたい、色設定バーをきちんと対応させたい、
    カーブの種類は後でも簡単に増やせるような単純なボタンにしたい (その方が起動も速い)、
    ある程度のカーブの種類は分類するタブを設けたい、回転やミラーが出来るツールを用意したい・・ などがありました。

     苦労して作っている色設定バーの構築ウラバナについては、

     今回用意した GUI は少し凝っていて面白い作りになっています。
    気が付いた方も居るかと思いますが、タブが並んでいる上にもボタン等を設定している、というところです。
    この設定のおかげで、各タブ共通のツールを用意することが出来ました。

     tabLayout コマンドの Python ドキュメントの 例を見てみます。


    import maya.cmds as cmds
    
    cmds.window( widthHeight=(200, 150) )
    form = cmds.formLayout()
    tabs = cmds.tabLayout(innerMarginWidth=5, innerMarginHeight=5)
    cmds.formLayout( form, edit=True, attachForm=((tabs, 'top', 0), (tabs, 'left', 0), (tabs, 'bottom', 0), (tabs, 'right', 0)) )
    
    child1 = cmds.rowColumnLayout(numberOfColumns=2)
    cmds.button()
    cmds.button()
    cmds.button()
    cmds.setParent( '..' )
    
    child2 = cmds.rowColumnLayout(numberOfColumns=2)
    cmds.button()
    cmds.button()
    cmds.button()
    cmds.setParent( '..' )
    
    cmds.tabLayout( tabs, edit=True, tabLabel=((child1, 'One'), (child2, 'Two')) )
    
    cmds.showWindow()

     formLayout の中に tabLayout である tabs を 位置を決めて配置していて、
    後から(下から2行目) tabLabel として タブ表示部分の 
    child1、child2 である rowColumnLayout を設定しています。
    記述が前後している上に入り組んでいて、簡単な編集で思い通りになりにくいです。

    また、formLayout を使うと ボタン等を細かく位置指定することができるのですが、逆に自由度を奪います。   

    そこで、formLayout を使わないで、もっと簡単にタブの配置設定が出来る方法を模索してみます。

    import maya.cmds as cmds
    
    window = cmds.window(title='ri Rig ICONs',sizeable=True, topLeftCorner=[200, 200], widthHeight=(420,300))
    tabs = cmds.tabLayout(innerMarginWidth=5,innerMarginHeight=5)
    
    tab_cl1 = cmds.columnLayout('  One  ',width=420,height=150,adjustableColumn=True)
    
    cmds.text(label='One',width=400,bgc=[0.2,0.2,0.2],align='center' )
    cmds.scrollLayout(childResizable = 1)
    cmds.rowColumnLayout(numberOfColumns=4)
    
    cmds.button(label='Triangle',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
    cmds.button(label='Triangle',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
    cmds.button(label='Triangle',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
    cmds.button(label='Triangle',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
    
    cmds.setParent('..')
    cmds.setParent('..')
    cmds.setParent('..')
    tab_cl2 = cmds.columnLayout('  Two  ',width=420,height=150,adjustableColumn=True)
    
    cmds.text(label='Two',width=400,bgc=[0.2,0.2,0.2],align='center' )
    cmds.rowColumnLayout(numberOfColumns=4)
    cmds.button(label='Triangle',width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
    cmds.button(label='Triangle',width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
    cmds.button(label='Triangle',width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
    cmds.button(label='Triangle',width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
    
    
    cmds.columnLayout('  Three  ',width=420,height=150,adjustableColumn=True)
    cmds.text(label='Tools For ICONs',width=400,bgc=[0.2,0.2,0.2],align='center' )
    cmds.rowColumnLayout(numberOfColumns=4)
    cmds.button(label='Shikaku',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
    cmds.button(label='Shikaku',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
    cmds.button(label='Shikaku',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
    
    cmds.setParent(tabs)
    
    cmds.showWindow()

     今度はどうでしょうか?

    スクリプトの見た目も簡単そうなのに、かなり面白いGUIが作成出来ます。
    setParent を多用しているところがポイントで、これを減らしたり増やしたりすると    
    見た目の変わったGUIを色々と作り出すことが出来ます。


    最後から2行目に、cmds.setParent(tabs) という記述があることに注目してください。
    このカッコ内の設定で tabs が親だって指定しているので、ここを タブじゃないもの に設定すれば、それが一番上に来ます。
    そこでボタンの配列を設定した columnLayout を一番上に配置してみます。

    window = cmds.window(title='ri Rig ICONs',sizeable=True, topLeftCorner=[200, 200], widthHeight=(420,300))
    
    top_w = cmds.columnLayout('  set size  ',width=400,height=50,adjustableColumn=False)
    cmds.rowColumnLayout(numberOfColumns=4)
    cmds.button(label='Shikaku',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
    cmds.button(label='Shikaku',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
    cmds.button(label='Shikaku',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
    cmds.button(label='Shikaku',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
    cmds.setParent('..')
    
    tabs = cmds.tabLayout(innerMarginWidth=5,innerMarginHeight=5)
    
    tab_cl1 = cmds.columnLayout('  One  ',width=420,height=150,adjustableColumn=True)
    
    cmds.text(label='One',width=400,bgc=[0.2,0.2,0.2],align='center' )
    cmds.scrollLayout(childResizable = 1)
    cmds.rowColumnLayout(numberOfColumns=4)
    
    cmds.button(label='Triangle',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
    cmds.button(label='Triangle',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
    cmds.button(label='Triangle',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
    cmds.button(label='Triangle',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
    
    cmds.setParent('..')
    cmds.setParent('..')
    cmds.setParent('..')
    tab_cl2 = cmds.columnLayout('  Two  ',width=420,height=150,adjustableColumn=True)
    
    cmds.text(label='Two',width=400,bgc=[0.2,0.2,0.2],align='center' )
    cmds.rowColumnLayout(numberOfColumns=4)
    cmds.button(label='Triangle',width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
    cmds.button(label='Triangle',width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
    cmds.button(label='Triangle',width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
    cmds.button(label='Triangle',width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
    
    cmds.setParent('..')
    cmds.setParent('..')
    cmds.columnLayout('  Three  ',width=420,height=150,adjustableColumn=True)
    cmds.text(label='Tools For ICONs',width=400,bgc=[0.2,0.2,0.2],align='center' )
    cmds.rowColumnLayout(numberOfColumns=4)
    cmds.button(label='Shikaku',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
    cmds.button(label='Shikaku',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
    cmds.button(label='Shikaku',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
    
    cmds.setParent(top_w)
    
    cmds.showWindow()

    最後から2行目を cmds.setParent(top_w) と変えて、
    最初から2行目に top_w の 内容である4つのボタンが入った columnLayout を指定しています。   
    すると、タブ列よりも上に4つのボタンが配置することが出来ました。

    今回のGUIではこのような方法で 各タブでボタン表示部分を変えても
    共通で使用する サイズ変更機能 が用意できるレイアウトを作成してみました。




 ツール解説
     ツールの説明を記述しておきます。

      Size は右のスライダーを動かしても、直接記入しても設定出来
      ボタンを押してカーブが作成される時に そのサイズ で作成されます。

      Immediate [] はデフォルトでオフになっています。
      これをオンにすると、選択されたカーブがスライダーでサイズ変更できます。
      選択したものはスライダーでサイズ変更するので、
      通常はオフの方が安全でしょう。

      [Freeze SRT] は選択状態のカーブを 移動/回転/縮尺フリーズします。

      2D / 3D / Arrows / Others タブ には
      それぞれに分類されたカーブ生成ボタンが並びます。

      Tools タブ 内には以下のツールがあります。

      [Merge Curves] は複数のカーブを1つにまとめます。
      次数が異なるもの、階層構造になっているものはマージできません。

      [Center Pivot] はピボットの位置を修正します。

      Mirror は 各軸を中心にミラーします。
      Rotate は 各軸に90度ずつ回転します。

      Select Color は選択しているものの色をスライダーで変更します。
      [SelColorToSelected] は選択しているものをスライダーの色に変更します。
      これは便利で、階層構造選択しているものを一発で色変更出来たりします。




 ri_rig_icons.py
     という訳で  Rig用ICON作成ツール ri_rig_icons.py を公開します。 
    あくまでも自己責任でお使いください。 use as your own risk.


    Rig用ICON作成ツール
    (Maya2012,2014,2015)

    ri_rig_icons.zip 15.1 KB  2015/02/08 現在





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

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