ViewerStateでDrag&Drop
ViewerState を使用すると、Houdini の Viewport への Drag&Drop で指定した処理を実行できるようになります。
ので、今回はこの機能の使い方を試してみます。
追加する
まず、新しい State を作成します。
まず、ViewerStateBrowser を開きます。
追加したい Context を選び(今回は Lop)、File から NewState... を選びます。
Samples を Drag&Drop で、初期テンプレを作成しておくと楽です。
実行してみる
作成すると、ViewerStateBrowser に追加した State(Label 名で表示)が表示されるので、右クリック> Enter を実行します。
サンプルは、テキストファイルを Drag&Drop するようなコードになっているので
テスト用のテキストファイルを作り、Viewport に Drag&Drop してみます。
すると、このようなコンテキストメニューが表示され、Open を選ぶと、
ファイルを開くことができました。
onDragTest/onDropGetOptions/onDropAccept
おおむね動作が確認できたので、テストコードをみつつ実装方法を確認していきます。
Drag&Drop では、 onDragTest onDropGetOptions onDropAccept の 3 つの関数を実装します。
onDragTest
onDragTest は、ファイルの Drop を許可するかを判定するための関数で、
True を返すと許可され、False にすると onDropAccept が実行されなくなります。
if hou.ui.hasDragSourceData("text/plain"):
return True
シンプルな例だと、上記のようにすると「テキストファイルが Drop された」場合に
Drop 処理を許可する...という意味になります。
onDropGetOptions
onDropGetOptions は、 onDragTest が True だった場合に
マウスを話したタイミングで表示するコンテキストメニューを指定します。
def onDropGetOptions( self, kwargs ):
""" Build drag drop option list """
source = hou.ui.getDragSourceData("text/plain")
basename = os.path.basename( source )
kwargs["drop_options"]["ids"] = ("open", "info")
kwargs["drop_options"]["labels"] = ("Open: %s" % basename, "Info")
指定方法は、 kwargs["drop_options"] に対して、ID と Label を指定します。
ここで指定した値は onDropAccept で使用することができます。
def onDropAccept( self, kwargs ):
""" Process the event with the selected option """
selected = kwargs["drop_selection"]
print(selected)
filepath = hou.ui.getDragSourceData("text/plain")
print(filepath)
return True
onDropAccept をこのようにすると、Drop したときのコンテキストメニューの結果と
Drag したデータを、そのファイルの種別に応じて取得することができます。
応用編
デフォルトで追加される Sample はテキストファイルを Drag&Drop するサンプルでしたが、
当然テキストファイル以外の Drag&Drop も実装することができます。
https://www.sidefx.com/ja/docs/houdini/hom/hou/qt/mimeType.html
対応しているイベントタイプは、公式 Docs 内の上記のページまとめられています。
なので、ここに書かれている情報であれば
Drag&Drop で取得できるということになります。
実験で、今回は LOP の AssetBrowser の情報を取得してみます。
LOP には LayoutAssetGallery というパネルがデフォルトで用意されています。
このブラウザでは、USD のアセットのデータベースを作成することができて、
Layout ノードでアセットを配置するときの配置アセットの選択パレットとして使用できます。
デフォルトだと、このアイコンを選んで Drag&Drop すると Reference ノードが作成されますが
この処理を ViewerState を使用してのっとってみようと思います。
def onDragTest( self, kwargs ):
""" Accept text files only """
if hou.ui.hasDragSourceData(hou.qt.mimeType.asset):
return True
return False
onDragTest では、 mimeType.asset を使用して Drag を許可します。
def onDropGetOptions( self, kwargs ):
"""3つの項目でドロップオプションリストを収集します。"""
kwargs['drop_options']['ids'] = ('ok','ng')
kwargs['drop_options']['labels'] = ('はい','いいえ')
return True
マウスを話したときに表示されるコンテキストメニューは、 drop_options の要素として ids labels を
入れます。
このメニューには、最低2つ以上選択肢をれる必要があり、この関数とメニューが実装されていないと
Accept が呼ばれないので要注意です。
def onDropAccept( self, kwargs ):
""" Process the event with the selected option """
select = kwargs['drop_selection']
if select == "ok":
import json
data = json.loads(hou.ui.getDragSourceData(hou.qt.mimeType.asset))
print(data['filepaths'])
print(data['labels'])
return True
最後に Drop した時の動作を作ります。
Drag してきたデータは getDragSourceData に mimeType を指定することで
取得することができます。
取得できるデータは str で、ものによってことなりますが
今回のアセットの場合は json が Dump された str になっています。
構造はこのようになっているので、
これを json.loads で読み込めば
AssetBrowser のアセットのファイルパスを取得できます。
他にも Drag&Drop 可能な要素はたくさんあるので
うまく利用すればいい感じにカスタマイズできそうです。