マンガじゃない Houdini チュートリアル ーーPySideーーーHoudini検証 インスタンス&コピー 

November 12, 2016

マンガじゃない Houdini チュートリアル ーーParmTemplateーーー

前回はPySideを使ってパラメータを挿入するスクリプトを作りましたが、それを事を踏まえて指定のパラメータをレイアウトの中で上下させるスクリプトを作ってみました。

今回はPySideと言うよりはPythonによるパラメータのレイアウト書式であるparmTemplateについて説明してみたいと思います。少しだけね。

parmUpDown
 

先ず始めにこんなパラメータが在ったとします。
parmUpDown1
この全体のレイアウトに関しては、ノードから.parmTemplateGroup()から取り出せます。

node = hou.node('/obj/geo1/null')
nodeTemp = node.parmTemplateGroup()

それぞれのパラメータのテンプレートは.parmTemplateGroup()のparmTemplates()階層下にリストで入っています。

例えばAのテンプレートを取り出したい場合、Aは3番目のパラメータでリストは0からなので
parmA = nodeTemp.parmTemplates()[2]
という事になります。

別にテンプレートグループからたどらなくても直接これでもいけます。
parmA =  hou.parm('/obj/geo1/nullA/a').parmTemplate()

もしくはテンプレートグループからfindで名前検索も出来ます。これも同じです。
parmA =  nodeTemp.find("a")

そして前回のようにこのAの下にパラメータを作りたい場合。

newParm = hou.FloatParmTemplate("newParm", "NewParm", 1)
こんな感じで新しいパラメータテンプレートを作り。

nodeTemp.insertAfter(parmA,newParm)
でAの下に挿入します。これでnodeTempは更新されましたが、parmTemplateGroupはノードとレイアウトをコピーしただけであってノードのほうとの直接の互換性はないので、これを.setParmTemplateGroup()によってノードに当てはめやらないければパラメータは更新されません。

node.setParmTemplateGroup(nodeTemp)
なのでこれを走らせることで始めてノードのパラメータレイアウトが更新されます。
parmUpDown2


今回の場合をひとつ上に上げたり下に下げたりする必要があるので自分のパラメータの番号を知る必要があります。それによって指定番号のパラメータにinsertBefore()もしくはinsertAfter()を使い挿入しなおします。

自分の番号自体はfindIndices()によって探せます。
myIndex = nodeTemp.findIndices(parmA)
もしくは
myIndex = nodeTemp.findIndices(”a”)
これによって
(2,)
と返ってきます。 リストで帰ってくるのはフォルダ構造がある場合の為でこれがちょっとめんどくさいのでここでは省略。

とりあえず今回はこうしておきましょう。
myIndex = nodeTemp.findIndices(parmA)[0]

これによってひとつ下のパラメータがこのように探せます。
parmNext = nodeTemp.parmTemplates()[myIndex - 1]

なので自分自身を.remove()で一旦消して
nodeTemp.remove(parmA)
それからafter結合&更新すればひとつ下に
nodeTemp.insertAfter(parmNext,parmA)
node.setParmTemplateGroup(nodeTemp)

大まかにはこんな感じなのですがめんどくさいのはフォルダー階層。
例えばこんなパラメータがあるとして 
parmUpDown3
これのDのインデックス
(4, 2, 0)
これはtemplateGroupのナンバー4のフォルダ内のナンバー2のフォルダないのナンバー0がパラメータDと言う事を意味します。

フォルダもparmTmplate()として取り出せるのですがフォルダの場合更にそこからparmTmplates()によって下の階層のパラメータ取り出す事が出来ます。
なのでさっきのインデックスからパラメータDを取り出すとすると
nodeTemp.parmTemplates()[4].parmTemplates()[2].parmTemplates()[0]
となりますが、
これじゃああんまりなので僕の場合は階層フォルダのリストを取り出すことにしました。
curFolder = nodeTemp
folders = [curFolder]
for i in indexcis:
        curItem = curFolder.parmTemplates()[i]
        if curItem.type().name() == "Folder":
            curFolder = curItem
            folders.append(curItem)

と言う感じで階層をループしてfoldersというリストが出来ます。最後の自身のパラメータをは含まないようにしています。indexcisは.findIndices()によって取り出した(4, 2, 0)の事です。
これによって
folders[-1].parmTemplates()[indecis[-1]]で自分自身の居場所が分かります。
ひとつ上の場合は
folders[-1].parmTemplates()[indecis[-1]-1]
ただ現パラメータの位置がフォルダのトップの場合はフォルダを飛び越えてそのフォルダ自身の上に生きた印尾でその場合単純に
folders[-1]
となるifによる分岐が必要です。

そうして出来たのがこれです。

from PySide import QtCore
from PySide import QtGui

parm = kwargs["parms"][0]
parmTmp = parm.parmTemplate()
node = parm.node()
parmGroup = node.parmTemplateGroup()

class Example(QtGui.QWidget):
    def __init__(self):
        super(Example, self).__init__()
        self.initUI()
    
    def initUI(self):
        Lbox = QtGui.QVBoxLayout()
        
        mpos = QtGui.QCursor().pos()
        self.setGeometry(mpos.x() - 100 ,mpos.y() - 200 ,250,120)
        self.setWindowTitle('Parm Up & Down')
        
        self.checkBox = QtGui.QCheckBox('Keep in Current Folder', self)
        Lbox.addWidget(self.checkBox)    
        
        upButton = QtGui.QPushButton('Up', self)
        Lbox.addWidget(upButton)
        upButton.clicked.connect( self.upButtonPress )
        
        downButton = QtGui.QPushButton('Down', self)
        Lbox.addWidget(downButton)
        downButton.clicked.connect( self.downButtonPress )
        
        self.setLayout(Lbox)
        
    def HierarchyIndexies(self):
        return parmGroup.findIndices(parmTmp)
        
    def HierarchyFolders(self):
        curFolder = parmGroup
        parmHierarchy = [curFolder]
        for i in self.HierarchyIndexies():
            curItem = curFolder.parmTemplates()[i]
            if curItem.type().name() == "Folder":
                curFolder = curItem
                parmHierarchy.append(curItem)
        return parmHierarchy
        
    def upButtonPress(self):
        index = self.HierarchyIndexies()[-1]
        folder = self.HierarchyFolders()[-1]
        if index == 0:
            parmNext = folder
        else:
            parmNext = folder.parmTemplates()[index-1]
        
        if not (index == 0 and self.checkBox.isChecked()):
            parmGroup.remove(parmTmp)
            parmRef = parmGroup.find(parmNext.name())
            if index != 0 and parmRef.type().name() == "Folder" and not self.checkBox.isChecked():
                parmGroup.appendToFolder(parmRef,parmTmp)
            else:
                parmGroup.insertBefore(parmRef,parmTmp)
            node.setParmTemplateGroup(parmGroup)
    
    def downButtonPress(self):
        index = self.HierarchyIndexies()[-1]
        folder = self.HierarchyFolders()[-1]
        folNum = len(folder.parmTemplates())-1
        if index == folNum:
            parmNext = folder
        else:
            parmNext = folder.parmTemplates()[index+1]
        
        if not (index == folNum and self.checkBox.isChecked()):
            parmGroup.remove(parmTmp)
            parmRef = parmGroup.find(parmNext.name())
            if index != folNum and parmRef.type().name() == "Folder" and not self.checkBox.isChecked():
                if len(parmRef.parmTemplates()) != 0:
                    parmGroup.insertBefore(parmRef.parmTemplates()[0],parmTmp)
                else:
                    parmGroup.appendToFolder(parmRef,parmTmp)
            else:
                parmGroup.insertAfter(parmRef,parmTmp)
            node.setParmTemplateGroup(parmGroup)

dialog = Example()
dialog.show()

parmPic

と言う感じになります。
ここまでやっておいてなんですがこれが出来たからといってCGが上手くなったりとかは全くありません。
普通にEdit Parameter Interfaceを開けば良いだけの話です。

ただ仕事でアセットを提供するような立場になってくるとただのHDAだけ使うよりもスクリプトも交えて提供するほうが使用する側にフレンドリーな場合もあったりなかったりするので手数は多いに越した事はないかと。ガチガチなHDAだとかだと更新に対して軟弱だったりとか。
その辺はそれぞれのアーティストの哲学とかもあったりでいろいろ一筋縄ではいかない部分ですけど。。。


fujitarium at 15:38│Comments(0)TrackBack(0)│ │CG | Houdiniチュートリアル

トラックバックURL

コメントする

名前
 
  絵文字
 
 
マンガじゃない Houdini チュートリアル ーーPySideーーーHoudini検証 インスタンス&コピー 

ライブドアブログでは広告のパーソナライズや効果測定のためクッキー(cookie)を使用しています。
このバナーを閉じるか閲覧を継続することでクッキーの使用を承認いただいたものとさせていただきます。
また、お客様は当社パートナー企業における所定の手続きにより、クッキーの使用を管理することもできます。
詳細はライブドア利用規約をご確認ください。