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

ViewerStateでDrag&Drop

ViewerState を使用すると、Houdini の Viewport への Drag&Drop で指定した処理を実行できるようになります。
ので、今回はこの機能の使い方を試してみます。

追加する

まず、新しい State を作成します。

Image from Gyazo

まず、ViewerStateBrowser を開きます。

Image from Gyazo

追加したい Context を選び(今回は Lop)、File から NewState... を選びます。

Image from Gyazo

Samples を Drag&Drop で、初期テンプレを作成しておくと楽です。

実行してみる

Image from Gyazo

作成すると、ViewerStateBrowser に追加した State(Label 名で表示)が表示されるので、右クリック> Enter を実行します。

サンプルは、テキストファイルを Drag&Drop するようなコードになっているので
テスト用のテキストファイルを作り、Viewport に Drag&Drop してみます。

Image from Gyazo

すると、このようなコンテキストメニューが表示され、Open を選ぶと、

Image from Gyazo

ファイルを開くことができました。

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

Image from Gyazo

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 の情報を取得してみます。

Image from Gyazo

LOP には LayoutAssetGallery というパネルがデフォルトで用意されています。

Image from Gyazo

このブラウザでは、USD のアセットのデータベースを作成することができて、
Layout ノードでアセットを配置するときの配置アセットの選択パレットとして使用できます。

Image from Gyazo

デフォルトだと、このアイコンを選んで 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 になっています。

Image from Gyazo

構造はこのようになっているので、
これを json.loads で読み込めば
AssetBrowser のアセットのファイルパスを取得できます。

他にも Drag&Drop 可能な要素はたくさんあるので
うまく利用すればいい感じにカスタマイズできそうです。