HDAのUIにPySideを使用する

# 概要

Houdini18.0からHDAのUIにPySideを使えるようになりました。
例えばこういったリストビューを使ったマテリアルを一覧し、アサインするツールを作ったりする事が可能です。
![MatBrowser.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332597/48e13c24-9519-f0dd-c33c-07524b0dc2f0.gif)

# 方法

HDAのUIをPySideにするにはPython Panel Editorを使います。
Python Panel Editorについては下記ページが参考になると思います。

- [Houdini Python PanelでカスタムUIを作る](https://qiita.com/towazumi/items/cb7e5ae0fa609d4294c2)
- [Python Panel Editor(公式)](https://www.sidefx.com/ja/docs/houdini/ref/windows/pythonpaneleditor.html)
- [Pythonパネルのサンプル(公式)](https://www.sidefx.com/ja/docs/houdini/examples/python_panels/index.html)

上記に書かれてるのはPySideのUIをHoudiniのパネルに組み込む物ですが、HDAに適用するには**Show in Parameters Pane**にチェックを入れ、**For Operators**の欄にオペレータ名を指定します。
![](https://paper-attachments.dropbox.com/s_6BA232741FE99423F2EB8292E91D307B04583A5EFE7DE85E376DEF924A8E44C9_1586421992393_PythonPanel.png)


オペレータ名は**<ネットワークタイプ名>/<オペレータ名>**もしくは画像のようにHDAにプレフィックスを付けてる場合は**<プレフィックス>::<ネットワークタイプ名>/<オペレータ名>**にします。

あとはタブメニューからノードを作成するとPySideのUIが適用された状態で表示されます。
![](https://paper-attachments.dropbox.com/s_6BA232741FE99423F2EB8292E91D307B04583A5EFE7DE85E376DEF924A8E44C9_1586423588446_MatBrowserTabMenu.gif)

## 注意点

注意点としてはこのPython Panelファイル自体も読み込める場所に配置されてる必要があります。
基本的には下記どちらかに入れ、HDAは親階層の**otls**フォルダに入れると自動で読み込まれます。

- **$HOUDINI_PATH/python_panels**
- **$HOUDINI_USER_PREF_DIR/python_panels**

ちなみにPython Panel Editorに使用してるコードはMayaなどのPySideが対応してるツールでも使う事が出来ます。
このツールの場合はマテリアルを適用する箇所は書き換える必要がありますが、それ以外の箇所は共通で使える為、使い回すことが出来ます。
![](https://paper-attachments.dropbox.com/s_6BA232741FE99423F2EB8292E91D307B04583A5EFE7DE85E376DEF924A8E44C9_1586422745523_MatBrowserMaya.gif)

# 通常のUIと切り替え

UIの表示をPySideにするか通常の物にするかは図のボタンを押すことで切り替えることが出来ます。
![](https://paper-attachments.dropbox.com/s_6BA232741FE99423F2EB8292E91D307B04583A5EFE7DE85E376DEF924A8E44C9_1586424220316_MatBrowserUI01.png)


ちなみにMaterial Browserの通常UIはこのようになっています。
![](https://paper-attachments.dropbox.com/s_6BA232741FE99423F2EB8292E91D307B04583A5EFE7DE85E376DEF924A8E44C9_1586424214743_MatBrowserUI02.png)
グループとマテリアルまでのパスが書かれただけのシンプルな物です。
HDAではUIをPySideにしても、パラメータの情報は通常UIからしか取得する事が出来ないので、PySideから実行するコマンドではHDA内にマテリアルを作り、選択してた面とマテリアルのパスをパラメータに設定するという処理を行っています。

# 問題点

本来HDAノード自体をPythonで取得しようと思うと**`hou.pwd()`**や**`kwargs['node']`**を使いますが、PySide側では取得する事が出来ません。
これが出来ないとマテリアルを適用する時にどのノードを対象にするか指定する事が出来ないのです。

この問題に対して調べても解決策が出なかったので、これはあくまで私が考えた方法ですが、HDAの**OnCreated**と**OnLoaded**に下記スクリプトを登録しています。
![](https://paper-attachments.dropbox.com/s_6BA232741FE99423F2EB8292E91D307B04583A5EFE7DE85E376DEF924A8E44C9_1586425268299_HDAScripts.png)

```Python
def set_current_node(node, event_type, **kwargs):
    hou.setPwd(node)
node = kwargs['node']
node.addEventCallback((hou.nodeEventType.AppearanceChanged, ), set_current_node)
```


**OnCreated**はHDA作成時、**OnLoaded**はシーンファイルを開いた時に実行されるスクリプトです。

- https://www.sidefx.com/ja/docs/houdini/hom/locations.html#%E3%82%A4%E3%83%98-%E3%83%B3%E3%83%88%E3%82%BF%E3%82%A4%E3%83%95

ここに**addEventCallback**でノードの状態(選択やフラグなど)が変わった時にこのHDAを現行ノードに設定するというものです。
かなり強引ですが、こうする事でPySideから**hou.pwd()**でHDAノードを取得する事が出来ます。

もっと良い方法をご存じの方は教えていただけると助かります…

# まとめ

以上HDAのUIにPySideを使用する方法でした。

まだ対応して間もないので、情報や実装例がほとんどありませんが、HDAで出来ることの幅が増えるので、是非チャレンジしてみて下さい。

ちなみに私は今後、Houdiniからゲーム用にモデルをパブリッシュするHDAのUIをPySideに変更しようと思っています。