#はじめに
選択した階層以下のノード名を取得したいとします。
まず最初に思いつくのが、listRelativesコマンドだと思います。
listRelativesコマンドを使えば、子階層が取得できます。
cmds.listRelatives( ad=True, c=True, typ="transform" )
ただこの方法で取得すると、リスト内の順番が階層順でないため使いにくいです。
# 結果: [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より、高速に処理を行うことができますので、活用してみてください。