MayaのDuplicateとHideを(個人的に)便利にしてみた※2016/02/06修正

※2016/02/06にスクリプトの修正 となんとなくkDuplicteのPythonバージョンも追記

 

====================================================

1ヶ月くらい前からMayaを仕事で触り始めまして~

まぁ~~~~噂には聞いてはいましたけど、ホンマにいちいち操作が一手間多い子ですね・・・

一応これで御三家(いやもうSIさんはあれですが)は触りましたが、Mayaさんはその中でもとっつきにくいですね~

 

仕事で他の人に教えづらくなるのでショートカットなどは大きく変更しないようにしていますが

それでも個人的にやりづらいのが操作の箇所がいくつかありました。

 

今回はまずDuplicate(複製)とHideのトグル(表示非表示)の操作を自分的にやりやすくするスクリプトをMELの練習も兼ねて書きました。

 

下記にもスクリプトを載せていますのでコピペするか、こちらからDLして下さい。( DuplicateのMEL : HideのMEL  )

 あとはscriptsフォルダに入れて、ホットキーに source "スクリプトファイル名"; と書くだけです。

※これらを使用して起きたトラブルや損害等の責任は負いません。

 またMaya2014の日本語版の環境でしか動作確認はしていません。


Duplicateの方はmyaraさんの下記のページを参考にさせて頂きました。


myara CG blog Maya | shift+D, ctrl+D ala XSI
http://myara.blog.fc2.com/blog-entry-191.html


最初はmyaraさんが書かれてxsiDuplicate.melを使わせて頂いていたのですが、

自分が試した感じではおそらくメッシュオブジェクト以外を複製できないようだったので

そこの条件分岐部分を変更したものになります。

また、挙動は以下のようになっています。(myaraさんのページから引用)


ポイント選択: 頂点の面取り (Chamfer Vertex)
エッジ選択: ベベル (Bevel)
ポリゴン選択: 押し出し (Extrude)
オブジェクト選択: Mayaのデフォルトの複製 (Duplicate)

 

global proc kDuplicate(){
    string $sel[] = `ls -sl`;

    int $objMode = `selectMode -q -object`;
    int $vertexMode = `selectType -q -pv`;
    int $edgeMode = `selectType -q -pe`;
    int $faceMode = `selectType -q -pf`;

    if($objMode){
        Duplicate;
    }else{
        if($vertexMode){
            ChamferVertex;
        }else if($edgeMode){
            polyBevel -offset 0.1 -offsetAsFraction 1 -autoFit 1 -segments 2 -worldSpace 0 -uvAssignment 0 -fillNgons 1 -mergeVertices 1 -mergeVertexTolerance 0.0001 -smoothingAngle 30 -miteringAngle 180 -angleTolerance 180 -ch 1 $sel;
        }else if($faceMode){
            PolyExtrude;
        }else{
            Duplicate;
        }
}
kDuplicate;

 

===============================================

※2016/02/06 修正バージョン 以前は選択モードで判別していましたがマーキングメニューからの切り替えとF8~F11などのショートカットからの切り替えなどで取得できる選択モードの状態が違ってうまく機能してくれない時があったのでfilterExpand -selectionMaskで頂点・エッジ・フェースの選択されている数から状況を判断して処理を変えるようにしました。

===============================================


global proc kDuplicate(){
    string $sel[] = `ls -sl`;

    if(size($sel) == 0){
            print("何にも選択されていません"+ "\n");
    }else{
        int $currentMode = 0;

        //polyEvaluateだとオブジェクトのときにエラーでるのでfilterExpandで調べる
        string $vt[] = `filterExpand -selectionMask 31 $sel`;
        string $ed[] = `filterExpand -selectionMask 32 $sel`;
        string $fc[] = `filterExpand -selectionMask 34 $sel`;
       
        int $vtNum = size($vt);
        int $edNum = size($ed);
        int $fcNum = size($fc);
       
        //マルチ選択のことを考慮してパターンを分ける
        if( $vtNum > 0 && $edNum > 0 && $fcNum > 0){
            if( $vtNum > $edNum && $vtNum > $fcNum ){
                $currentMode = 1;
            }else if( $edNum > $vtNum && $edNum > $fcNum){
                $currentMode = 2;
            }else if( $fcNum > $vtNum && $fcNum > $edNum){
                $currentMode = 3;
            }
        }else if( $vtNum > 0 && $edNum > 0){
            if( $vtNum > $edNum ){
                $currentMode = 1;
            }else if( $edNum  > $vtNum){
                $currentMode = 2;
            }
        }else if( $edNum > 0 && $fcNum > 0){
            if( $edNum > $fcNum){
                $currentMode = 2;
            }else if( $fcNum > $edNum){
                $currentMode = 3;
            }
        }else if( $vtNum > 0 && $fcNum > 0){
            if( $vtNum > $fcNum){
                $currentMode = 1;
            }else if($vtNum > $fcNum){
                $currentMode = 3;
            }
        }else if( $vtNum > 0){
            $currentMode = 1;
        }else if( $edNum > 0){
            $currentMode = 2;
        }else if( $fcNum > 0){
            $currentMode = 3;
        }else{
            $currentMode = 0;
        }
       
        //print("カレントモード" + $currentMode + "\n");

        //現在のモードから複製するコマンドを判別する
        if ($currentMode == 1){
            ChamferVertex;

        }else if ($currentMode == 2){
            //選択しているエッジが境界エッジ(ハードエッジ)のみの場合は押し出し、それ以外はベベル
            string $selMask[] = `filterExpand -selectionMask 32 $sel`;
            string $polyInfos[] = `polyInfo -edgeToVertex $selMask`;
            string $hardEdge[];
            for($x = 0; $x < size($polyInfos); $x++ ){

                if( ` match "Hard" $polyInfos[$x]` == "Hard"){
                    $hardEdge[$x] =  $polyInfos[$x];
                }
            }

            if(size($selMask) == size($hardEdge)){
                PolyExtrudeEdges -constructionHistory 1 -keepFacesTogether 1 -divisions 1 -twist 0 -taper 1 -offset 0 -thickness 0 -smoothingAngle 30 $sel;
            }else{
                polyBevel -offset 0.1 -offsetAsFraction 1 -autoFit 1 -segments 2 -worldSpace 0 -uvAssignment 0 -fillNgons 1 -mergeVertices 1 -mergeVertexTolerance 0.0001 -smoothingAngle 30 -miteringAngle 180 -angleTolerance 180 -ch 1 $sel;
               
            }
        }else if ($currentMode == 3){
            PolyExtrudeFaces;

        }else{
            Duplicate;
        }
    }
}
kDuplicate();


2016/02/06に追記

 

↑のkDuplicateのPythonバージョン。やっぱりPythonの方が書きやすいですね!w

===============================================

# -*- coding: utf-8 -*-

import maya.cmds as mc

def kDuplicate():
    sel = mc.ls(sl=True)

    if not sel:
            print 'Nothing is selected'
    else:   
       
        vtNum = mc.polyEvaluate(vertexComponent=True)
        edNum = mc.polyEvaluate(edgeComponent=True)
        fcNum = mc.polyEvaluate(faceComponent=True)

        currentMode = 0

        #vtNumの型を調べてintだったらメッシュなので判別開始
        if isinstance(vtNum , int):
            #マルチ選択のことを考慮してパターンを分ける
            if vtNum > 0 and edNum > 0 and fcNum > 0:
                if max(vtNum , edNum , fcNum) == vtNum:
                    print ("VERTEX")
                    currentMode = 1
                elif max(vtNum , edNum , fcNum) == edNum:
                    print ("EDGE")
                    currentMode = 2
                elif max(vtNum , edNum , fcNum) == fcNum:
                    print ("FACE")
                    currentMode = 3

            elif vtNum > 0 and edNum > 0:
                if vtNum > edNum:
                    print ("VERTEX")
                    currentMode = 1
                elif vtNum < edNum :
                    print ("EDGE")
                    currentMode = 2

            elif edNum > 0 and fcNum > 0:
                if edNum > fcNum:
                    print ("EDGE")
                    currentMode = 2
                elif edNum < fcNum:
                    print ("FACE")
                    currentMode = 3

            elif vtNum > 0 and fcNum > 0:
                if vtNum > fcNum:
                    print ("VERTEX")
                    currentMode = 1
                elif vtNum < fcNum:
                    print ("FACE")
                    currentMode = 3

            elif vtNum > 0:
                currentMode = 1
            elif edNum > 0:
                currentMode = 2
            elif fcNum > 0:
                currentMode = 3
            else:
                currentMode = 0

        #現在のモードから複製するコマンドを判別する
        if (currentMode == 0):
            mc.Duplicate()

        elif (currentMode == 1):
            mc.ChamferVertex()

        elif (currentMode == 2):
            #選択しているエッジが境界エッジ(ハードエッジ)のみの場合は押し出し、それ以外はベベル
            selMask = mc.filterExpand(sel , selectionMask=32)
            polyInfos = mc.polyInfo(selMask, edgeToVertex=True)
            hardEdge = []
            for info in polyInfos:
                if info.find("Hard") != -1:
                        hardEdge.append(info.find("Hard"))
            #print (str(len(selMask)) + "and" +  str(len(hardEdge)))
           
            if len(selMask) == len(hardEdge):
                mc.PolyExtrudeEdges(sel , constructionHistory=1 ,keepFacesTogether=1 ,divisions=1 ,twist=0 ,taper=1 ,offset=0 ,thickness=0 ,smoothingAngle=30 )
            else:
                mc.polyBevel(sel , offset=0.1 , offsetAsFraction=1 , autoFit=1 , segments=2 , worldSpace=0 , uvAssignment=0 , fillNgons=1 , mergeVertices=1 , mergeVertexTolerance=0.0001 , smoothingAngle=30 , miteringAngle=180 , angleTolerance=180 , ch=1 )

        elif (currentMode == 3):
            mc.PolyExtrudeFaces()

        else:
            mc.Duplicate()

kDuplicate()


続きまして、Hideのトグルの方です。

というか、MayaのHide変わっていませんか?!

なんで「選択したポリゴン(フェース)を非表示」ということをストレートにやらせてくれないんだ!

一回ポリゴン選択して反転してそれから選択項目の分離表示(isolateSelect)をやらないといけないって・・・

あぁ~~SIが恋しい

 

長くMayaをお使いの方はもしかして他に方法ご存知だったりするんですかね?(・・;)

 

SIと同じような挙動は今の自分にはまだ再現できないですが、

とりあえず選択モードがオブジェクトならそれらの表示・非表示のトグル、
フェースモードなら選択しているフェースを全モデルパネルから非表示(再度実行すると表示)にする、というような挙動です。

自分はホットキーエディタでHキーに割り当てています。

 

※2016/02/06 に修正 今まではフェース選択モードとオブジェクト選択モードだけで判別していましたが、コンポーネントモードかどうかも調べるようにしました。

ちなみにF8キーやマーキングメニューからオブジェクトにすると faceMode==1 : objMode==1 : compMode==0 となり、
F11でフェースモードにすると faceMode==1 : objMode==0 : compMode==0で
マーキングメニューからフェースモードにすると faceMode==1 : objMode==1 : compMode==1 となる

proc objHide(string $selObjects[]){
         for($obj in $selObjects){
              if(`attributeExists "visibility" $obj`){
                       int $vis=(getAttr ($obj+".visibility")) ? 0 : 1;
                       setAttr ($obj+".visibility") $vis;
              }
    }
}
global proc kToggleHide(){
    
    string $selectObj[] = `ls -sl`;

    int $faceMode = `selectType -q -polymeshFace`;
    int $objMode = `selectMode -q -object`;
    int $compMode = `selectType -q -objectComponent -allComponents`;

    if($faceMode == 1 && $objMode == 1 && $compMode == 0 ){
        objHide($selectObj);
       
    }else if($faceMode == 0 && $objMode == 1 && $compMode == 0 ){
        objHide($selectObj);
       
    }else{
        string $allPanels[] = `getPanel -typ modelPanel`;
        if( size($selectObj) > 0){
            string $selPolyCount[] = `filterExpand -selectionMask 34 $selectObj`;
            int $state = `isolateSelect -q -state $allPanels[0]`;
            if($state == 0 && size($selPolyCount) > 0){
                print ("stateが0 で selPolyCount[0]も0以上");
                invertSelection;
                for($panelName in $allPanels){
                    isolateSelect -state 1 $panelName;
                    isolateSelect -as $panelName;
                }
                select -cl;
            }else{
                print ("その他");
                invertSelection;
                for($panelName in $allPanels){
                    isolateSelect -state 0 $panelName;
                    //-rs(removeSelected)がしないと前の情報が残る
                    isolateSelect -rs $panelName;
                }
            }
        }else{
            print "何も選択されていません \n";
            for($panelName in $allPanels){
                isolateSelect -state 0 $panelName;
                isolateSelect -rs $panelName;
            }
        }
    }
}
kToggleHide();


コメントをお書きください

コメント: 2
  • #1

    Tom (金曜日, 05 2月 2016 14:24)

    選択ポリゴンだけ非表示するのは、
    非表示フェースの割り当て(Edit Mesh > Assign Invisible Faces)
    がSIのそれに近いかと思います。

    http://download.autodesk.com/global/docs/maya2012/ja_jp/index.html?url=files/Edit_Mesh__Assign_Invisible_Faces.htm,topicNumber=d28e150627

    ただし本当にフェースを非表示するだけで、エッジ・頂点は表示されてしまいますが。
    MayaにもSI方式のHide機能欲しいですね。

  • #2

    赤メガネ (日曜日, 07 2月 2016 04:25)

    >Tomさん
    訪問&コメントありがとうございます!
    「非表示フェースの割り当て」は使ったことなかったです!
    試してみましたが、仰られている通りエッジや頂点はそのまま残ってしまうというのが厄介ですね(^_^;)

    この記事で書いてるやり方も無理矢理「選択項目の分離」でやっているので
    他のオブジェクトも非表示になってしまうのが欠点です・・・orz

    非表示フェースの割り当てにオプションでもつけて、エッジ・頂点も非表示にできるようにしてほしいですね~