D日記

フルリモートで働くモーションアーティストの技術ブログだよ。日常も書くよ。

MENU

【MEL】ボックスコントローラーを作成し選択ノードに位置・回転を合わせる

f:id:ponta565:20190806113146p:plain

こんにちは、最近 ゴッド・オブ・ウォー をやりすぎて妻にキレられたですぽんたです(^_^)

今回は、リギング作業時にあると便利なスクリプトを作ってみますた!

目的

リグを手動で組む時に、選択した骨の位置にコントローラーを配置するという作業がわりとあったりします。

私の場合は、


1.コントローラー作成(NurbsCurve)
    ↓
2.2重グループ化*1
    ↓
3.骨の位置にスナップ(場合によっては回転合わせをする)
    ↓
4.親子階層整理


といった順序でリグの配置を行うことが多いです。


ただ、これを毎回やるのは面倒くさいですよね(笑)
この面倒くさい手順をボタン一発で解決するのがこのスクリプトです。



機能

・nurbsCurve のボックスコントローラーを作成。
f:id:ponta565:20180513191638p:plain
・コントローラー名は、「rig_」+「選択オブジェクト名」となります。
f:id:ponta565:20180513210058p:plain
・コントローラーは2重グループ化されます。
f:id:ponta565:20180513205930p:plain
・作成したコントローラーを指定した親にペアレント。
 → 指定しない場合は、ルートに作成。
・コントローラーのサイズを決められる。

スクリプト

下記スクリプトをMayaのコマンドパネルにコピペしてEnter(たぁぁぁん!)

/*
■ 機能
・ボックスリグを追加する。
・ボックスリグは2重構造になっており、制御するコントローラのトランスフォームは初期状態で移動回転Zeroとなる。
・ボックスリグの位置・回転は、選択しているオブジェクトに合わせる。
・複数選択で作成できる。
・Pivotがズレている場合の対応はしていません。
*/


proc Exec(){
    global string $parentObjs[];
    
    $s = `floatField -q -v "ff_size"`; // リグサイズ変数縮小
    
    string $selObj[] = `ls -sl -type "transform"`; // 選択ノード配列取得
    
    // 何も選択されていない場合は処理中止
    if( size($selObj)==0){
        confirmDialog -m "なにか選択してください。";
        return;
    }
    


    for ($sel in $selObj){
        // boxカーブ作成
        $crv = `curve -d 1 
        -p (0.5*$s) (0.5*$s) (0.5*$s) -p (0.5*$s) (0.5*$s) (-0.5*$s) -p (-0.5*$s) (0.5*$s) (-0.5*$s) 
        -p (-0.5*$s) (-0.5*$s) (-0.5*$s) -p (0.5*$s) (-0.5*$s) (-0.5*$s) -p (0.5*$s) (0.5*$s) (-0.5*$s) 
        -p (-0.5*$s) (0.5*$s) (-0.5*$s) -p (-0.5*$s) (0.5*$s) (0.5*$s) -p (0.5*$s) (0.5*$s) (0.5*$s) 
        -p (0.5*$s) (-0.5*$s) (0.5*$s) -p (0.5*$s) (-0.5*$s) (-0.5*$s) -p (-0.5*$s) (-0.5*$s) (-0.5*$s) 
        -p (-0.5*$s) (-0.5*$s) (0.5*$s) -p (0.5*$s) (-0.5*$s) (0.5*$s) -p (-0.5*$s) (-0.5*$s) (0.5*$s) 
        -p (-0.5*$s) (0.5*$s) (0.5*$s)
        -k 0 -k 1 -k 2 -k 3 -k 4 -k 5 -k 6 -k 7 -k 8 -k 9 -k 10 -k 11 -k 12 -k 13 -k 14 -k 15 
        -n ("rig_"+$sel)`;
        
        // リグ<オフセット<ベーストランス保持用の3重構造
        $base = `createNode "transform" -n ("rig_" + $sel + "_base")`;
        $offs = `createNode "transform" -n ("rig_" + $sel + "_offs") -p $base`;
        parent $crv $offs;
        
        // base を選択オブジェクトの位置・回転へ合わせる
        $t = `xform -q -ws -t $sel`;
        $r = `xform -q -ws -ro $sel`;
        xform -ws -t $t[0] $t[1] $t[2] $base;
        xform -ws -ro $r[0] $r[1] $r[2] $base;
        
        // 親ノードの指定があった場合は移動
        if( size($parentObjs) > 0 ){
            parent $base $parentObjs[0];
        }
    }
}


// 親ノードを指定
proc SetParentObj(){
    global string $parentObjs[];
    $parentObjs = `ls -sl -l -type "transform"`;
    
    // ボタンに選択オブジェクト名を反映
    $shortName = `ls $parentObjs[0]`;
    
    if(size($parentObjs) == 0){
        button -e -l "Pick" -ann "親ノードは選択されていません" "btn_pick" ;
    }else{
        button -e -l $shortName -ann ($parentObjs[0] + "  が親ノードとしてセットされています!") "btn_pick" ;
    }
    
}



proc AddController(){
    global string $parentObjs[]; // リグ作成後の親となるオブジェクトの絶対パス
    
    string $win = "win_addController";
    
    if(`window -exists $win`){deleteUI $win;}
    
    window -title "Add Controller" -toolbox true $win;
    
    columnLayout -adj true;
    
        rowLayout -nc 2 -ad2 1;
            columnLayout -adj true;
                text -l "親ノードを指定 → " -al "right" -h 30;
                text -l "コントローラーのサイズを指定 → " -al "right"  -h 30;
                setParent "..";
        
            columnLayout -adj true -w 100;
                button -l "Pick" -h 30 -c "SetParentObj()" -ann "親ノードは選択されていません" "btn_pick";
                floatField -min 0 -max 100 -v 10 -precision 1 -step .01  -h 30 "ff_size";
                setParent "..";
    
        setParent "..";
    

        button -l "コントローラーを作成し、選択ノードにスナップ!" -c "Exec()";
        
    showWindow $win;
}


AddController();


f:id:ponta565:20180513221014g:plain


おわり。

*1:2重グループ化をする理由は、コントローラーのトランスフォームを初期状態に保ちたいのと、オフセットノードを設けることで、リグのカスタマイズ性を上げる目的があります。例えばオフセットノードにノイズコントローラーを適用させたりとか。