LoginSignup
2
1

More than 1 year has passed since last update.

OpenMayaのイテレータを使って階層名を取得する

Last updated at Posted at 2021-01-19

はじめに

選択した階層以下のノード名を取得したいとします。
まず最初に思いつくのが、listRelativesコマンドだと思います。
listRelativesコマンドを使えば、子階層が取得できます。

cmds.listRelatives( ad=True, c=True, typ="transform" )

ただこの方法で取得すると、リスト内の順番が階層順でないため使いにくいです。
image.png

# 結果: [u'_03', u'_02', u'_01', u'_05', u'_07', u'_06', u'_04'] # 

上記は"_00"を選択して、コマンドを実行した結果です。
取得したリストを reverse() すれば階層順にはなりますが、スマートではないです。

そこで、OpenMayaを使って解決していきます。

コード

import maya.OpenMaya as om

def getHierarchicalNameList(): 
    list = [] 
    selList = om.MSelectionList() 
    om.MGlobal.getActiveSelectionList(selList)

    for i in range(selList.length()): 
        dag = om.MObject() 
        selList.getDependNode( i, dag ) 

        dagIterator = om.MItDag( om.MItDag.kBreadthFirst, om.MFn.kInvalid ) 
        dagIterator.reset( dag, om.MItDag.kBreadthFirst, om.MFn.kTransform )  

        fDn = om.MFnDagNode() 
        while ( not dagIterator.isDone()): 
            currentObj = dagIterator.currentItem() 
            fDn.setObject(currentObj) 
            fName = fDn.name() 
            list.append( fName ) 

            dagIterator.next() 

    return list 

解説

OpenMayaのイテレータを使っていきます。
イテレータとはデータ集合構造です。親子階層は、DAGの集合構造ですので、MItDagクラスを使用します。

        dagIterator = om.MItDag( om.MItDag.kDepthFirst, om.MFn.kInvalid ) 

イテレータを作成します。引数は【type】と【filter】です。
Typeは、捜索タイプを指定します。

  • kDepthFirst   : 子階層を捜索後、兄弟階層に移動します。
  • kBreadthFirst  : 兄弟階層を捜索後、子階層に移動します。

それぞれのTypeを実行すると下記のような違いがあります。


# kDepthFirst 
[u'_00', u'_01', u'_02', u'_03', u'_04', u'_05', u'_06', u'_07']

# kBreadthFirst 
[u'_00', u'_01', u'_04', u'_02', u'_05', u'_06', u'_03', u'_07']

filter で、フィルタを設定することができます。
kTransform はフィルタを無効にしています。
その他のフィルタはココを参照してください。

        dagIterator.reset( dag, om.MItDag.kBreadthFirst, om.MFn.kTransform ) 

イテレータをリセットしています。
ここで捜索したいDAGノードを指定しています。
Transform のみを取得したいので、MFn.kTransform でフィルタを設定しています。

        while ( not dagIterator.isDone()): 
            dagIterator.next() 

while でイテレータが終わるまでループさせます。
next() メソッドで、次のノードに移動します。next が無いと永久ループとなりますので気を付けてください。

まとめ

イテレータクラスは、MItDag 以外にも、ノードネットワーク(MItDependdenctGraph)や頂点(MItVertex)・ポリゴン(MItMeshPolygon)などがあります。
上記のポイントを押さえれば、どれも似たような感じで扱えます。
cmdsより、高速に処理を行うことができますので、活用してみてください。

2
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1