November 06, 2016
マンガじゃない Houdini チュートリアル ーーPySideーーー
やろうやろうと思ってちょっとやっては思ったことが出来なくて放置していたPySide。
重い腰をあげてようやく着手してみました。最近はその手のチュートリアルを書いてくれている方々も出てきて
ありがたいんですが、ちょっと皆さん不親切すぎやしませんかね。肝心な事が省かれてたり、パラメータを作れるのは良いが、肝心のそれをどう使えるようにするのかとか。前提とされるプログラミング能力が高すぎる。。。
って事を書くとお前が言うなとか言われそうですが。 。
今回僕は追加パラメータを右クリックメニューから追加できるスクリプトをつくりながら勉強してみたので、それの紹介です。 対象はプログラムは本格的にやったことは無いけど、たまに仕方なくPythonスクリプト書くよって感じの方向けです。

こんな感じで Edit Parameterを開かずに右クリで追加できます。
パラメータ名すでに存在するのと被ってたら赤くなります。
Labelはnameに追従し、最初の字だけ大文字化します。 Labelのみ変更すれば全然違うラベル名も入力可能。
Typeは使用頻度の高そうな最低限だけにしてます。
重い腰をあげてようやく着手してみました。最近はその手のチュートリアルを書いてくれている方々も出てきて
ありがたいんですが、ちょっと皆さん不親切すぎやしませんかね。肝心な事が省かれてたり、パラメータを作れるのは良いが、肝心のそれをどう使えるようにするのかとか。前提とされるプログラミング能力が高すぎる。。。
って事を書くとお前が言うなとか言われそうですが。 。
今回僕は追加パラメータを右クリックメニューから追加できるスクリプトをつくりながら勉強してみたので、それの紹介です。 対象はプログラムは本格的にやったことは無いけど、たまに仕方なくPythonスクリプト書くよって感じの方向けです。
こんな感じで Edit Parameterを開かずに右クリで追加できます。
パラメータ名すでに存在するのと被ってたら赤くなります。
Labelはnameに追従し、最初の字だけ大文字化します。 Labelのみ変更すれば全然違うラベル名も入力可能。
Typeは使用頻度の高そうな最低限だけにしてます。
parm Menuの作り方自体はこちらで紹介しています。
単にパラメータ追加するだけならこんな感じで可能です。
parmはparm.parmTemplate()の指定のパラメータのテンプレート取得
node.parmTemplateGroup()で ノードのパラメータz全体のテンプレート取得
hou.FloatParmTemplate("newParm", "NewParm", 1)で新しいパラメータ作り
parmGroup.insertAfter(parmTmp,newParm)で指定したパラメータの下にドッキング
そしてnode.setParmTemplateGroup(parmGroup)でノードのパラメータレイアウト更新です。
但しパラメータは同名のパラメータの存在は許可されてないので、すでに同名が存在するとエラーが出ますし。
ひとつのノードに対しては一度しか実行できません。
なのでその為に自分で名前を入力し、それをパラメータとして追加したいので、パネルの存在が必要となってきます。
先ずパネルを作る程度の練習過程ではShelf Toolで試すのが良いと思われる。
こんな感じのテンプレートになります。

ググりまくってたどり着いただけなので詳しい事は分かりませんが
def initUI(self):の中でレイアウトを作ってる感じですね。
Lbox = QtGui.QVBoxLayout()は縦に並べるレイアウト、Lbox.addWidget(text)で突っ込んだ順に並べてくれるので手っ取り早い。QtGui.QHBoxLayout()だと横に並べる。
text = QtGui.QLineEdit('text', self) テキストエディターを作る。
button = QtGui.QPushButton('button', self) ボタンを作る。
次にやりたいのがボタンを押すとtextの内容がプリントされるようにする事。
そしてググって見つけたのがこれ
button.clicked.connect()
()内にファンクションを突っ込むと実効してくれるらしい。
赤字更新箇所。こうするとボタンを押すとPython ShellにAAAAAが表示されます。
次に欲しいのがtext内容の取得これは普通にtext.text()で取得できるので
なんか知らないがlambda:と言うのを実効ファンクションの前に入れないと()が必要なファインションとかが使えないらしい。これのせいで数時間無駄に消費する。。。
とりあえず自分が必要だったのはここまでで、後は勉強がてら調べながら色々実装してみました。
そうして出来たのがこんな感じです。
その他の事についてざっくり説明するとこんな感じになります。

読んでくれてる人にとって肝心な所を飛ばしてる気がしなくも無いですがまあこんな感じです。
そういえばmaxscriptのパネルの作り方ってかなり楽だったよなあ。。。
単にパラメータ追加するだけならこんな感じで可能です。
parm = kwargs["parms"][0] parmTmp = parm.parmTemplate() node = parm.node() parmGroup = node.parmTemplateGroup() newParm = hou.FloatParmTemplate("newParm", "NewParm", 1) parmGroup.insertAfter(parmTmp,newParm) node.setParmTemplateGroup(parmGroup) |
parmはparm.parmTemplate()の指定のパラメータのテンプレート取得
node.parmTemplateGroup()で ノードのパラメータz全体のテンプレート取得
hou.FloatParmTemplate("newParm", "NewParm", 1)で新しいパラメータ作り
parmGroup.insertAfter(parmTmp,newParm)で指定したパラメータの下にドッキング
そしてnode.setParmTemplateGroup(parmGroup)でノードのパラメータレイアウト更新です。
但しパラメータは同名のパラメータの存在は許可されてないので、すでに同名が存在するとエラーが出ますし。
ひとつのノードに対しては一度しか実行できません。
なのでその為に自分で名前を入力し、それをパラメータとして追加したいので、パネルの存在が必要となってきます。
先ずパネルを作る程度の練習過程ではShelf Toolで試すのが良いと思われる。
from PySide import QtCore from PySide import QtGui class Example(QtGui.QWidget): def __init__(self): super(Example, self).__init__() self.initUI() def initUI(self): self.setGeometry(300, 300, 250, 150) self.setWindowTitle('Panel Title') Lbox = QtGui.QVBoxLayout() text = QtGui.QLineEdit('text', self) Lbox.addWidget(text) button = QtGui.QPushButton('button', self) Lbox.addWidget(button) self.setLayout(Lbox) dialog = Example() dialog.show() |
ググりまくってたどり着いただけなので詳しい事は分かりませんが
def initUI(self):の中でレイアウトを作ってる感じですね。
Lbox = QtGui.QVBoxLayout()は縦に並べるレイアウト、Lbox.addWidget(text)で突っ込んだ順に並べてくれるので手っ取り早い。QtGui.QHBoxLayout()だと横に並べる。
text = QtGui.QLineEdit('text', self) テキストエディターを作る。
button = QtGui.QPushButton('button', self) ボタンを作る。
次にやりたいのがボタンを押すとtextの内容がプリントされるようにする事。
そしてググって見つけたのがこれ
button.clicked.connect()
()内にファンクションを突っ込むと実効してくれるらしい。
from PySide import QtCore from PySide import QtGui class Example(QtGui.QWidget): def __init__(self): super(Example, self).__init__() self.initUI() def initUI(self): self.setGeometry(300, 300, 250, 150) self.setWindowTitle('Panel Title') Lbox = QtGui.QVBoxLayout() text = QtGui.QLineEdit('text', self) Lbox.addWidget(text,) button = QtGui.QPushButton('button', self) Lbox.addWidget(button) button.clicked.connect(self.buttonPush) self.setLayout(Lbox) def buttonPush(self): print "AAAAA" dialog = Example() dialog.show() |
次に欲しいのがtext内容の取得これは普通にtext.text()で取得できるので
from PySide import QtCore from PySide import QtGui class Example(QtGui.QWidget): def __init__(self): super(Example, self).__init__() self.initUI() def initUI(self): self.setGeometry(300, 300, 250, 150) self.setWindowTitle('Panel Title') Lbox = QtGui.QVBoxLayout() text = QtGui.QLineEdit('text', self) Lbox.addWidget(text,) button = QtGui.QPushButton('button', self) Lbox.addWidget(button) button.clicked.connect(lambda: self.buttonPush(text.text()) ) self.setLayout(Lbox) def buttonPush(self, showtext): print showtext dialog = Example() dialog.show() |
とりあえず自分が必要だったのはここまでで、後は勉強がてら調べながら色々実装してみました。
そうして出来たのがこんな感じです。
from PySide import QtCore from PySide import QtGui parm = kwargs["parms"][0] parmTmp = parm.parmTemplate() node = parm.node() parmGroup = node.parmTemplateGroup() class Panel(QtGui.QWidget): def __init__(self): super(Panel, self).__init__() self.initUI() def initUI(self): Lbox = QtGui.QGridLayout() mpos = QtGui.QCursor().pos() self.setGeometry(mpos.x() - 100 ,mpos.y() - 200 ,250,120) self.setWindowTitle('Parm Insert') label_Name = QtGui.QLabel('Name:') Lbox.addWidget(label_Name,0,0) label_Label = QtGui.QLabel('Label:') Lbox.addWidget(label_Label,1,0) Type_Label = QtGui.QLabel('Type:') Lbox.addWidget(Type_Label,2,0) text_Name = QtGui.QLineEdit("newParm",self) text_Name.textChanged.connect(lambda: self.onTextChanged( text_Name, text_Label ) ) Lbox.addWidget(text_Name,0,1) text_Label = QtGui.QLineEdit("newLabel",self) Lbox.addWidget(text_Label,1,1) parmType = QtGui.QComboBox(self) parmType.addItems(["Float","Vector","Int","String","Ramp_Float", "Ramp_Color"]) Lbox.addWidget(parmType,2,1) button = QtGui.QPushButton("Create Parm" , self) button.clicked.connect(lambda: self.pressButton( text_Name.text(),text_Label.text(), parmType.currentText() ) ) Lbox.addWidget(button,3,1) self.onTextChanged( text_Name, text_Label ) self.setLayout(Lbox) def pressButton(self, name, label, ptype): if not parmGroup.find(name): if ptype == "Float": newParm = hou.FloatParmTemplate(name, label, 1) elif ptype == "Vector": newParm = hou.FloatParmTemplate(name, label, 3) elif ptype == "Int": newParm = hou.IntParmTemplate(name, label, 1) elif ptype == "String": newParm = hou.StringParmTemplate(name, label, 1) elif ptype == "Ramp_Float": newParm = hou.RampParmTemplate(name, label, ramp_parm_type=hou.rampParmType.Float) elif ptype == "Ramp_Color": newParm = hou.RampParmTemplate(name, label, ramp_parm_type=hou.rampParmType.Color) parmGroup.insertAfter(parmTmp,newParm) node.setParmTemplateGroup(parmGroup) else: msgBox = QtGui.QMessageBox(self) msgBox.setText( 'F**k! "%s" is Already Exist' % name) msgBox.show(); self.close() def onTextChanged(self , name, label): if not parmGroup.find(name.text()): name.setStyleSheet("background-color: rgb(255, 255, 255);") else: name.setStyleSheet("background-color: rgb(255, 107, 107);") text = name.text() label.setText( text[0].upper() + text[1:] ) dialog = Panel() dialog.show() |
その他の事についてざっくり説明するとこんな感じになります。
読んでくれてる人にとって肝心な所を飛ばしてる気がしなくも無いですがまあこんな感じです。
そういえばmaxscriptのパネルの作り方ってかなり楽だったよなあ。。。