メインコンテンツまでスキップ

PythonViewerStateの基本

Houdini の ViewerState とは「ビューポート内でのインタラクティブな操作を制御することができる」機能です。
例えば、ギズモを表示したりビューポート内でマウスをクリックしたり等
そういった操作もすべて ViewerState で行っています。

Houdini では、各ノード(HDA)ごとに、ノードに関係した ViewerState を呼び出しているのですが
この ViewerState は、Python を使用して書かれていて
色々とカスタムすることが可能です。

あまりやっている人も少なく、資料もあまりないので
0スタートで学習しつつ、作り方などをメモしていきたいと思います。

ViewerState

まず、現在存在している ViewerState を確認してみます。

New Pane Tab Type から Inspectors > Viewer State Browser を選びます。

表示すると、現在存在している ViewerState を一覧でみることができます。

たとえば、LOP の StageManager を見てみると、
このような ViewerState があります。

Source を右クリック> Edit すると、このように中のコードを確認することができます。

作成する

すでにあるものの見方はわかったので、早速新しく作成してみます。

ViewerState を作成する場合は、2 種類やり方が存在しています。
1つが HDA に埋め込む方法、もう1つが指定のディレクトリにファイルを配置する方法です。

HDA に埋め込む

まずは簡単な HDA に埋め込む方法からみていきます。

ViewerState を作成したい HDA を右クリックして、Type Properties を選びます。

Interactive タブ> State Script を選び、右下にある New ボタンを押します。

CodeGenerator を使うと、基本的なテンプレを作成してくれるので
ここで、Name (ユニークなもの) Label Description を入れて、
作成したいイベントハンドラーを作成します。

今回は、マウスをクリックしたときに何かを実行させるのをサンプルで作りたいので
onMouseEvent のチェックをいれておきます。

すると、State Script にテンプレートになるコードが追加されるので、
onMouseEvent 関数だけを、以下のように書き換えます。
それ以外の部分は消さずに残してください。

    def onMouseEvent(self, kwargs):
""" Process mouse and tablet events
"""
ui_event = kwargs["ui_event"]
reason = ui_event.reason()

if reason == hou.uiEventReason.Start:
print("Click!!")

# Must return True to consume the event
return False

書き換えができたら、保存して
Viewport 上で「Enter」を押します。

Enter を押すと、ViewPort の左上が、CodeGenerator で指定した Label になります。

Viewport 上でクリックすると、このように表示されます。
この状態から戻したい場合は Esc を押すことで、通常のモードに戻ることができます。

指定ディレクトリ以下に保存する

HDA に埋め込む方法は、HDA 固有の機能であればよいですが
それ以外に複数の HDA だったりもっと汎用的に使いたいような機能もあるはずです。
その場合は、指定ディレクトリ以下に Python ファイルを配置します。

この場合は、ドキュメント/houdini###/viewer_states フォルダを作り
その下に Python ファイルを配置します。

import hou

class State(object):
def __init__(self, state_name, scene_viewer):
self.state_name = state_name
self.scene_viewer = scene_viewer

def onMouseEvent(self, kwargs):
"""マウスイベントを処理します
"""
ui_event = kwargs["ui_event"]
dev = ui_event.device()
self.log("Mouse:", dev.mouseX(), dev.mouseY(), dev.isLeftButton())

# イベントを消費するにはTrueを返さなければなりません
return False


def createViewerStateTemplate():
"""登録するViewerステートテンプレートを作成して返すのに必須となるエントリーポイント"""

state_typename = "remi_statedemo"
state_label = "Statedemo"
state_cat = hou.sopNodeTypeCategory()


template = hou.ViewerStateTemplate(state_typename, state_label, state_cat)
template.bindFactory(State)
template.bindIcon("MISC_python")

return template

コードは、 Houdini 公式の ViewerState 解説ページにあったものを一部改変したものです。

この場合の注意点は、どのコンテキストで使うものかを指定する必要があることです。
サンプルのコードだと Obj になっていて SOP ではなかったので
hou.sopNodeTypeCategory() のように sop になるようにしています。

配置したら Houdini を再起動します。

Viewer State Browser を確認すると、viewer_states フォルダ下に配置したスクリプトが認識されているのがわかります。

このままだと使用できないので、この ViewerState を使えるようにするには
HDA 側に指定をします。

TypeProperties の Node の「DefaultState」に、作成した ViewerState の Name(Label ではない)を入れます。

入れたら、HDA に埋め込んだ時と同じように「Enter」を押すと、

ViewerState Browser のコンソールにログが表示されました。

まとめ

これで基本的な作成方法と実行方法がわかりましたので、
次から細かく実装方法を確認していきます。

参考