この記事はHoudini Advent Calender 2018の24日目の記事で
15日目の記事の続きになります。 https://qiita.com/yuya_torii/items/9ae1248380c47b79efa3
前回の記事で、次はレイアウトをPythonで保存して複数のHDAで使い回す方法 を紹介しますと予告していたのですが
21日目の@shun-tumnoriさんによるノード作成時に独自パラメターを追加する方法という記事で紹介されている
「asCodeで関数として書き出し、OnCreateイベントで読み込む」というのがまさしく自分が紹介したい方法でした!
自分もディスパッチャー用の拡張に使ったりしていますが
こんな感じで、数が多くて階層が複雑でも、ExpressionやHide When〜などのイベント含めて丸ごと書き出せるので便利です。
(手打ちで書いたことがある人は辛さがわかるハズ・・!)
というわけで、今回も引き続きParameterInterfaceで使えるPythonの話で
個人的によく使う組み合わせなどを紹介していこうと思います。
OrderdMenu + CallbackScript
各ParameterにCallbackScriptが仕込める事を前回紹介しましたが、
OrderdMenuでは Menuを変更する度にCallbackScriptが実行 されます。
この時kwargsのscript_valueというキーに、選択中のmenuのtokenが入ってますので
こんな感じに書いておくと、OrderdMenuの項目に応じた処理が書けたりします
これ、完全に普段PySideでUIを作ってる人向けの例えなんですが
QComboBox の currentIndexChanged() がHoudiniのCallbackScriptにあたり
**currentText()やcurrentItem()**の代わりに、kwargs["script_value"]を使う、という感じです
(HoudiniでHDA作りを頼まれたTD/TAさん、参考にして下さい!)
kwargsの中身については、前回もご紹介したこちらにかかれています
OrderdMenuを使ったHDA,処理の分岐に関しては、個人的にかなり使うネタなのですが
これだけではピンとこないと思うのでもう少しサンプルを紹介してみます
OrderdMenu + CallbackScript + Error SOP
「OrderdMenuで選択した環境変数が定義済みでなければエラーを返す」というのを作ってみます
まずは、こんな感じで任意の環境変数を選択できるOrderdMenuを作っておきます。
あとで書きますが、callbackには先程のようにkwargsが渡るようにしておきます。
エラーに関しては、error sopを使います
こんな感じで用意しましょう。
ちなみに、Report This Errorを、HDAにenv_errorというparameterを作ってそちらにリンクしてありますが
汎用性を高めるためにそうしてあるだけなので、必ず必要な処理では無いです。
OrderdMenuとError SOPが用意出来たら、PythonModuleに以下のような処理を書きます
def envCheck(kwargs):
node = kwargs["node"] # 自身のノードオブジェクトを取り出す
token = kwargs["script_value"] # Orderd MenuのTokenを取り出す
if hou.expandString(token): # tokenが存在する環境変数か判定
node.parm("env_error").set(0)
else:
node.parm("env_error").set(1)
これで、定義されていない環境変数が選択された場合、エラーが出るHDA、が作れました
この例で言えば、**キャッシュツールの書き出しに必要な環境が正しくセットされているか?**とか
処理を変えて、Inputされている内容と、選択しているMenuの組み合わせがあっているか? など
OrderdMenu + CallbackScript + Error Sop の組み合わせ、個人的によく使うので紹介しました。
+ - ボタン
次に、+-ボタンの作り方について紹介します
何それ? って感じだと思いますが・・・個人的にはこれはHoudini標準でついて欲しい!そんなParameterです
サクっと説明します
まず、IntergerやFloatのParameterを作った時、こんな感じで自動でFieldとSliderの組み合わせになりますが
コレ、Houdiniお馴染みのMMB+ドラッグで値が変えられるのは便利なんですが
ぴったり正確な値を入れるのが難しくないですか? 1動かしたいのに2〜3動いてしまったり・・・しませんか?
よく、Versionやtakeの入力にコレを使ってるHDAを見るのですが・・・自分は結局数字キーで直接入力してしまいます。
ではどうするのが望みかというと、こんな感じになって欲しいと思っています。
たぶん見た目通りでわかって頂けると思うのですが、ボタンをポチポチ押すと数字が1つずつ上下する。そんな仕組みです。
作り方を解説します(といっても、新しい知識は必要ありません)
まず、VersionやTakeなどのParameterはStringで用意します。
- -はButtonですが、CallbackSciprtに以下のように書いておきます。
def count(parm_name, num): # 変えたいParameterの名前とカウントしたい数(増やすなら1、減らすなら-1)を与える
parm = hou.pwd().parm(parm_name)
cur_value = parm.eval()
next_value = int(cur_value) + num
clamp_value = max(min(999, cur_value),1) # 最大999、最小1でClamp
parm.set(str(clamp_value).zfill(len(cur_value))) # 桁を揃える
最大値や桁数は任意に変更して下さい。
自分の場合は、Versionが上がったらTakeは初期化されるように
少し処理を加えたりしています
def count(parm_name, num, reset_parm_name=None):
parm = hou.pwd().parm(parm_name)
cur_value = parm.eval()
next_value = int(cur_value) + num
clamp_value = max(min(999, cur_value),1)
parm.set(str(clamp_value).zfill(len(cur_value)))
if reset_parm_name:
hou.pwd().parm(reset_parm_name).set("01")
+ーボタンに関しては以上です。
画像を見ていて気になった人も居ると思いますが、ボタンを並べるとあんまり見た目が綺麗に揃わないんですよね
ぜひ標準で+ーできるボタン、もしくはQtにあるこんなやつ、つけて欲しいです。SideFX様・・
Default Value
はい、正直あまりネタが浮かば無いので、ParameterのDefaultValueにHscriptやPython入れる時のことについて
少し解説しようかな、と思います。
default Valueに関しては、ParameterDescriptionのこちらにありますが
例えば、環境変数のHIPNAMEとUSERを繋いだ文字をデフォルトにしておきたい、とかいうケースがあったとして
こういう設定をしている人をたまに見かけます
これ、間違いでは無いのですが、ノードを作った時、こういう風に表示されます
普通、ParameterにExpression書くときはこうすると思うので、普通じゃん!と思うかもしれません が..!
これ、LabelのところをMMBクリックしないと結果が表示されませんよね。こんな風に
とても細かい事なんですが、これってアーティストにとって**使いづらい(見づらい)**と思いませんか?
実はこれ、既にあるParameterに対してExpressionを書くときは仕方ないと思いますが
Default Valueを設定する場合はこれを美しく回避する方法があるんです
それがコレです
電卓みたいなアイコンのところをクリックして、HScriptに変えるです
いや当たり前でしょ!っていう人が多いとは思いますが
HScriptに変えた場合、Expressionを`(シングルクォーテーション)で囲う必要が無くなります というか囲うとエラーになるので
この場合であれば $HIPNAME + "_" + $USER
と、囲わずに書くのが正しくなります。
これが間違えやすいのでは無いかと思っていて、たぶんエラーになるのでそのままにしてる人が居るのでは・・?と思っています
正しく設定すれば、ノード作成時に、MMBクリックしなくてもこのように表示されます
ハイライトされて、Expressionが入っていると明示された上で結果のみ表示されます
これはPythonでも同じで、Pythonを書く場合は先ほどの電卓マークをPythonのマークにするだけです
特に、長い文字列を生成するときはPythonのほうが便利なので、個人的にはPythonもよく使います。
ちなみに、これはCallBackScriptも一緒ですが、あらかじめ作っておいたModuleから関数を呼びたいときは
という感じで、__import__
を使えば動的にModuleを読んで関数を使ったりできます
以上
ちょっと地味な内容だったかもしれませんが、ParameterIntafaceで使えるPythonの話でした
ご質問、ご依頼などあればお気軽にどうぞ
toriivfx@gmail.com