<< TOP

カスタム オブジェクト ビューア for Maya
Custom ObjectViewer for Maya
プロローグ; Prologue  


 MayaPython の試作段階で、昔、Softimage XSI に有った Object View という
指定したオブジェクトをずっと表示してくれる画面があり、
それのMaya版を作ってみたら、興味あるかな・・・? と問うたところ......!?
  予想に反して大きな反響がありました!!! <応援ありがとうございます>

そこで カスタム オブジェクト ビューア としてここに記事にして公開することにしました。

もちろん、Pythonの機能紹介を基本としたページですが、ツールだけをダウンロードして利用することも可能です。

 また、前回からツール自体を GitHub にて スクリプトを公開し、より皆さんに良いものが出来上がったら良いな~、という思いで試みていますが、今回も。 GitHub を利用したいと思います。

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

 Please use this information as your own risk.
Windows7 Professional 64Bit、Intel Core i7-3930K (3.20GHz,6コア/12スレッド)
メモリ16GB、NVIDIA GeForce GTX970 4GB


 Softimage XSI の Object View ってなんだっけ?

  すっかり操作を忘れてしまった感のある SoftimageXSI の画面とその機能ですが、
 Object View は、指定したオブジェクト (例えばキャラ全体や 頭・手 と言った特定の一部分 )を
 ずっと表示してくれる画面で、そのオブジェクトがどんなに動いても常に中央に表示し続けてくれるウィンドウでした。
 その部分の動きの確認やアニメーションを付ける際に非常に便利な画面でした。

     
 
    ■ドキュメント Basics(基本) > ビューイングとナビゲーション > Object View



 どんな使い方の時便利?

  すぐに思い付く Object View の使い方としては、
 アクションやダンスモーション中の手のアニメーションやフェイシャルアニメーションの
 検証用または設定用の表示画面として使えそう、と思い浮かべるかと思うのですが、
 実はある条件での作業でその機能がとても役立つことを知りました。

 それは、こんな場合です。
 キャラクターのアニメーションが原点で動いているのではなく、どんどんと原点から遠ざかって行ったり、
 原点の場所を全く無視したアクションを作っていたりする場合です。
 そして、それはどんな時に起こるか、といえば・・・・
 UnityUE4を利用した リアルタイムのシーケンスとして実機映像やムービーを作成している場合 などです。
 各キャラクターのモーションはオフセット値を使った配置型にするのではなく、
 その場の演技モーションとして作成して登録した方が作業的にも都合が良く、
 また、キャラクターのアニメーションも各カットシーン用に作成するものなので、
 使い回しを気にするデータではありません。
 
 そんな、途方も無く原点から遠い場所でアニメーションを作成している場合、
 どこに居ようがオブジェクトに追従して指定した部分をずっと表示してくれる画面である
 Object View は凄く重宝するウィンドウになることが予想されます。




 Viewウィンドウの用意 何のパネル?

 いつものごとく、カメラを選択出来るウィンドウは Mayaだと 何のパネル を使っているかを調べるところから始めます。
 いつも何気なく使っているMayaの画面で、カメラがあるウィンドウと言えば、
 そう、前面ビュー や 側面ビュー のウィンドウです。ここから紐解けそうです。

 今回の調べ方も、ちょっと違う方法から見てみましょう。
 Mayaにはパネルエディタ というウィンドウがあります。
 日本語UIにしていると日本語の表記の一覧になっています。

  

 Mayaのデフォルトの状態でもたくさんのパネルが用意されていることがわかります。
 Pythonを使ってデータをこの順番で表示するには 以下の方法で出来たりします。 
  
 
all_panels = cmds.getPanel(allPanels=True)
for o_panel in all_panels:
    o_type = cmds.getPanel(typeOf=o_panel)
    if o_type != 'emptyPanel':
        o_label = cmds.panel(o_panel, q=True, label=True )
        print o_label
#結果
上面ビュー
側面ビュー
前面ビュー
パース ビュー
ToggledOutliner
アウトライナ
グラフ エディタ
ドープシート
タイム エディタ
Trax エディタ
カメラ シーケンサ
ハイパーグラフ階層
ハイパーシェード
バイザー
ノード エディタ
ノードの作成
UV エディタ
レンダー ビュー
シェイプ エディタ
ポーズ エディタ
ダイナミック リレーションシップ エディタ
リレーションシップ エディタ
リファレンス エディタ
コンポーネント エディタ
ペイント エフェクト
スクリプト エディタ
プロファイラ
コンテンツ ブラウザ

 ここで注目するところは、全ての空でないパネルから 
 実は パネルのラベル を表示すると パネルエディタの表示と同じになる、ってところです。
 しかも日本語で返って来ます。
 で、その時の各パネルのタイプは、上記スクリプトでもう取得しているので、それを表示してみると。

 
all_panels = cmds.getPanel(allPanels=True)
for o_panel in all_panels:
    o_type = cmds.getPanel(typeOf=o_panel)
    if o_type != 'emptyPanel':
        print o_type
#結果
modelPanel
modelPanel
modelPanel
modelPanel
outlinerPanel
outlinerPanel
scriptedPanel
scriptedPanel
scriptedPanel
scriptedPanel
scriptedPanel
scriptedPanel
scriptedPanel
scriptedPanel
scriptedPanel
scriptedPanel
scriptedPanel
scriptedPanel
shapePanel
posePanel
scriptedPanel
scriptedPanel
scriptedPanel
scriptedPanel
scriptedPanel
scriptedPanel
scriptedPanel
scriptedPanel

 という結果を表示していることから、前面ビュー などは modelPanel であり、
 デフォルトの状態で既に4枚あることが理解出来ます。

 と、ここまで来れば、modelPanel を作れば良いので、このコマンドも modelPanel です。

 modelPanel
   http://help.autodesk.com/cloudhelp/2018/JPN/Maya-Tech-Docs/CommandsPython/modelPanel.html

 modelPanel を作成する時、上記のように ラベルに名前を付けると パネル名になり、
 表示に使うカメラも同時に設定することができます。
 パネルは formLayout を使ってUI的に表示制御しますので、今はこんな感じで書くと 想定して次に行きましょう。

 
c_model= cmds.modelPanel(label='ObjectView_ModelPanel', camera=o_cam)




  追加するカメラ どんなカメラ?

  さて、カメラの設定のあるパネルは用意出来たところで、今度はそのカメラについてです。
 通常、Mayaのカメラは、注目点の設定の無いカメラ単体のカメラですが、
 ここでは制御がしやすい カメラ、エイム、アップ を使いたいと思います。
 メニューから作成すると、グループノードの下にカメラと _aim、_up の制御が付いたカメラが作成されます。

  

 camera
   http://help.autodesk.com/cloudhelp/2018/JPN/Maya-Tech-Docs/CommandsPython/camera.html

 このカメラが作成される時の ログを [レ]すべてのコマンドのエコーを有効 にして、スクリプトエディタを見てみると、

   

 camera から始まるログ行を Python化 出来そう
 ・・・・なのですが、意外にもスクリプト化が面倒なのです。(特に cameraMakeNode のあたりなど・・・・)
 そこで、今回は最初の Melコマンド 行をそのまま使うことにしたいと思います。

 
mel.eval('CreateCameraAimUp;')

 この Melコマンド 'CreateCameraAimUp;' を実行後は、カメラgroup以下の3つのノードが選択状態になっていることから、
 続いて 選択 ls コマンドを使って、各要素の設定するようにしてみます。

 カメラ自身は、ニアクリップ10ファークリップ 30 とし、
 _aim の注目点の位置を 0,0,0 に設定します。

 
mel.eval('CreateCameraAimUp;')
aimup_list = cmds.ls( sl=True )
cmds.select(clear=True)

for n_camdata in aimup_list:
    cmds.select(n_camdata,r=True)
    n_dataShape = cmds.listRelatives(n_camdata, children=True)[0]
    n_cam_type = cmds.objectType(n_dataShape)
    if n_cam_type == 'camera':
        n_number = n_camdata[len('camera'):]
        cmds.setAttr( n_dataShape + '.nearClipPlane', 10 )
        cmds.setAttr( n_camdata + '.translateZ', 30)
        o_cam = n_camdata
    if '_aim' in n_camdata:
        cmds.setAttr( n_camdata + '.translateX', 0)
        cmds.setAttr( n_camdata + '.translateY', 0)                
        cmds.setAttr( n_camdata + '.translateZ', 0)
    cmds.select(clear=True)



 カメラのコンストレイント設定

  このスクリプトの実行条件として、"選択したものを注目する画面" にしたいので、
 選択したものを親とした _aim と _up の付いたカメラを作成した後、
 Mayaのシーンのトップに 作成されたカメラグループを移動させて、
 元あった親との Parentコンストレイント を設定します。
 こうすることで、最初に選択したものの階層構造内に作ったカメラが介在しないようにしておきます。

 上のスクリプトで、
 作成したカメラを特定していて ( o_cam ) 、そのカメラについている番号 (n_number 例;1,2,3) を利用します。

 上のスクリプトの続きで、
 カメラの親である カメラの groupノード を特定して、その名前を変更しておきます。(例;"ObjectViewCamera_group1")
 それを Mayaのシーンルートに移動したいのですが、
 これは parent コマンドで 、world=True とすると簡単に設定出来るところが面白いところです。
 後は、元の親とMayaのシーンルートに移したGroupノード間に parentConstraint を設定します。

 
o_pregrp = cmds.listRelatives(o_cam,parent=True )[0]
cmds.select(o_pregrp,r=True)
o_grp = cmds.rename('ObjectViewCamera_group' + n_number )
cmds.parent(o_grp, first_selected_node, relative=True )

cmds.select(clear=True)
cmds.select(o_grp,r=True)
pre_parent = cmds.listRelatives(o_grp,parent=True )[0]
cmds.parent(o_grp,world=True)
const_node = cmds.parentConstraint(pre_parent,o_grp,maintainOffset=True)[0]
cmds.select(clear=True)





 UIの用意 formLayoutの設定

  カメラの設定が出来る model パネル と、
 通常良く使う columnLayout を 一緒に1つの window に表示させるには formLayout を利用します。

 formLayout
   http://help.autodesk.com/cloudhelp/2018/JPN/Maya-Tech-Docs/CommandsPython/formLayout.html


 また、model パネル の表示設定は、modelEditor というコマンドから行います。

 modelEditor
   http://help.autodesk.com/cloudhelp/2018/JPN/Maya-Tech-Docs/CommandsPython/modelEditor.html

 modelEditor のオプション displayAppearance で 外観を設定し (例; 'smoothShaded' )、
 グリッド表示やテキスチャー表示の有無も設定出来ます。
 この部分だけを完成したスクリプトから抜粋すると、以下のようになっています。

 
try:
    cmds.window()
    window = cmds.window('CustomObjectViewer' + n_number, 
        title='Custom ObjectViewer' + n_number, sizeable=True, 
        topLeftCorner=[200, 200], widthHeight=(400,470))
    form = cmds.formLayout()
    c_model= cmds.modelPanel(label='CustomObjectViewer_Panel' + n_number, camera=o_cam)

except:
    print 'Check Panel Editor & CleanUp Unused Panels !!'

cmds.setParent('..')

column = cmds.columnLayout()

.....<中略> 

cmds.setParent('..')

cmds.formLayout(form,edit=True,
    attachForm=[
        (c_model,'left',5),(c_model,'top',0),(c_model,'right',5),(c_model,'bottom',80),
        (column,'left',5),(column,'top',400),(column,'right',0),(column,'bottom',0)
        ],
    attachPosition=[(column,'right',0,100)],
    attachNone=[(column,'top')]
    )
cmds.modelEditor(c_model,edit=True,grid=False,
    displayAppearance='smoothShaded',activeOnly=False, displayTextures=True )

cmds.showWindow( window )


 さて、完成しているUIの方を見ると、

 

 幾つかのスライダーで カメラの ニア/ファークリップや位置/回転値のオフセット値が変更出来るようにしています。
 このスライダーを動かすと値が瞬時に反映するようにするには
 floatSliderGrpコマンド のオプションで dragCommand changeCommand の設定を利用するのですが、
 ここでも面白い python らしい設定を仕込みます。
 以前に紹介している Python ツールにも登場しているのですが、無名関数 lambda を使います。とても便利です!!

  無名関数: ラムダ式
   https://docs.pyq.jp/python/library/lambda.html

 仕組みとしては、スライダーを動かして得た値 (つまり dragCommand か changeCommand が発生した時の値)を、
 別の式にその値をそのまま送って結果を反映するようにしたい訳です。
 以下完成スクリプトからの抜粋では、カメラの FarClipPlane のスライダーを動かしたら
 即座にカメラの FarClipPlane の値が変更がされる、というスクリプト部分になります。

 
def cam_far_slider(value,n_cam):
    n_cameraShape = cmds.listRelatives(n_cam, children=True)[0]
    cmds.setAttr( n_cameraShape + '.farClipPlane', value )

.....<中略> 

def object_view_menu(*args):
    if not cmds.ls( sl=True ):
        print 'Nothing is selected'
    else:
        first_selected_node = cmds.ls(sl=True)[0]

        cmds.select(clear=True)

.....<中略> 

        cmds.floatSliderGrp(label=' Far ClipPlane ',field=True,columnWidth3=[85,40,70],
            adjustableColumn=3, minValue=0.1, maxValue=100,fieldMinValue=0.1,
            fieldMaxValue=100, value=70,
            dragCommand=lambda x:cam_far_slider(x,o_cam),
            changeCommand=lambda x:cam_far_slider(x,o_cam))


 このような設定をスライダーがある分、行っているだけです。




 増殖し続けるパネル対応  未使用パネルの削除

  以前にも紹介しているカスタムのツールと同じ対応が必要です。
 それは、Mayaのパネルはシーンにどんどんと溜まっていってしまうので、
 閉じてしまったパネルの数に気が付かないままSaveして使い続けてしまえる
 ことへの対処が必要です。
 そこで、新たなパネルを作成する時、以前に作ったパネルを検索し、
 それが非表示パネルであれば消す、という仕組みを入れておきます。

 今回作っているパネルの種類は "modelPanel" と解っているので、その種類のパネルを全部取得し、
 その中から、今回パネル名、つまりラベルとして "CustomObjectViewer" って付いているパネルで、
 尚且つそれが 表示していないパネルであるなら そのパネルを削除する、っていう動作をスクリプト化します。

 getPanel コマンドを使えば、パネルの種類や非表示のパネルか、が取得でき、
 パネルの削除は deleteUI コマンドを使って行えます。

 
all_model_panels = cmds.getPanel(type='modelPanel')
m_panel_list =[]
for o_panel in all_model_panels:
    o_label = cmds.panel(o_panel, q=True, label=True)
    if "CustomObjectViewer" in o_label:
        m_panel_list.append(o_panel) 

invis_panel_list = cmds.getPanel(invisiblePanels=True)

for d_panel in m_panel_list:
    if d_panel in invis_panel_list:
        cmds.deleteUI(d_panel,panel=True)


 




 使い方

  基本的には、すっと見ていたいノードを選択状態にして、スクリプトを実行します。
 すると、自動的にその選択したものをずっと追うカメラが設定してあるウィンドウが立ち上がります。
 以下の図は、Character1_Head というエンドJointを選択してスクリプトを実行した例になります。

 

 選択したノードが必ずしも正面に対して プラスのZ方向とは限らず(例;手など)
 また、中央に表示したいものだけを表示して見やすくする為に
 Near/Farクリップ を設定すると良い感じに活用できます。

 

 キャラクター自身のJointの方向に合わせて、移動/回転値のオフセットを入れることで
 ウィンドウに合わせた方向に設定出来るはずです。
 カスタムグラフエディタのカレントフレームを左右に動かすことで、
 Mayaシーン と カスタムのウィンドウ のアニメーションが同時に動く様子が見れます。

 Near/Farクリップを設定することで、カメラから見て邪魔な前後の表示をカットすることが出来ます。

 例えば、Farクリップを設定して、
 自分の体で見えにくくなってしまう手だけを表示したい場合に有効です。

 

 また、Nearクリップを設定することで、腕で隠れてしまった顔だけを表示することが可能です。

 
 
 非表示にしたパネルはを必ず削除を実行していますが、
 新規作成したカメラのGroupノード以下はMayaのシーンに残っているので任意に削除が必要です。





 GitHubを使った公開
 という訳で、ツールは GitHub を使って公開しています。

 ツールの設定
 Pyファイルは シェルフにボタン登録する か、プルダウンメニューに登録 して実行します。

 既知の制限・注釈
     起動コマンドは 以下の通りです。
    object_view_menu()


 GitHubからの取得
 Pyファイルは GitHub に公開しています。
 GitHub にアカウント登録していなくても ダウンロードは出来ます。
  下記リンクページで、右上 [ Clone or downlaod ] という緑色のボタンからダウンロードを行います。
 ボタンを押すと表示される [ Download ZIP ] という右側のボタンから Zipファイル を取得します。

 ツィッターウェア (twitter ware)  @SI_UsersNotes
あくまでも自己責任でお使いください。 Use as your own risk.

https://github.com/O-Ritaro/Maya_CustomObjectViewer





 次回も Mayaかも?・・・
  乞う、ご期待!! Stay tuned ..