On this page |
Pythonビューアステート
概要
Viewer Stateは、ビューポート内でのインタラクティブな操作を制御することができます。 例えば、 RotateツールはViewer Stateです。 Handlesツールは、現行ノードに関係したViewer Stateにアクセスすることができます。 Houdiniは、Pythonで独自のViewer Stateを作成して登録することができます。
独自のViewer Stateの例:
-
ディスプレイハンドルは、ユーザー側でハンドルを制御して、パラメータ/設定を変更することができます。
-
ジオメトリとの対話操作は、サーフェス上で描画したり、マウスカーソル下の情報を表示させることができます。
-
ガイド表示は、ジオメトリをガイドとして表示することができます。
-
ユーザーにジオメトリを選択させることができます。
-
独自の右クリックメニューを表示することができます。
-
ローレベルでマウス、キーボード、タブレットのイベントに反応させることができます。
-
Undoブロックで変更内容を制御することができます。
Houdiniデジタルアセットには、Viewer Stateを指定することができます(例えば、そのタイプのノードが現行になった時に Handlesツールを使用させることができます)。 結局のところ、(Inspectionツールのようにノードを作成しないツールの)シェルフツールスクリプトでは、hou.SceneViewer.setCurrentState()をコールすることで、プログラム的にステートを変更することができます。
コードを今すぐにでも試したいのであれば、以下のViewer Stateの実装方法を参照してください。そこでは、最低限のViewer Stateの実装、登録、実行の方法について説明しています。
制限事項
-
現在のところ、Pythonステートは、 SOP(ジオメトリ)レベルとOBJレベルでのみ利用可能です 。現在のところ、例えばダイナミクスネットワークやコンポジットネットワークなどの他のネットワークタイプで独自のViewer Stateを作成することはできません。
-
現在のところ、Viewer Stateにアイコンを指定する方法がありません。
ステート名
ステートは、 内部名 とUIで表示する人が解読可能な ラベル を持ちます。 新しく独自のステートを作成する場合、その内部名は固有でなければなりません。もし2人の作成者が同じステート名を使用してしまった場合、どちらかのステートは登録に失敗します。 あなたが作成したステートまたはアセットがいつの日か他のユーザー/スタジオで共有もしくは製品として販売することを考慮すれば、適切な固有名になるようにちゃんと時間をかけて決めてください。
Houdiniはアセット毎に自動的に汎用ステートを作成するということも相まって、既存のノードタイプの名前をステート名として使用することはできません。
-
ステートが特定のアセットで固有であれば、そのアセットの名前(ネームスペース付き)をステート名として使用し、最後に
.pystate
を付けてください。これによって、ステートとアセットの関係が明確になり、自動的に作成されるアセットの汎用ステートとの干渉を回避することができます例えば、
OnInstall
イベントスクリプトで自動的に以下のような名前を付けることができます:state_name = kwargs["type"].type().name() + ".pystate"
詳細は、以下の登録の方法を参照してください。
-
ステートを2つ以上のノード間で共有したい場合やノードに関連付けたくない場合、必ずどのアセットの汎用ステートとも干渉しないようなステート名を付けなければなりません。この一番良い方法は、アセットで使用しているのと同じネームスペースを組み込むことです。
例えば、あなたがExample.com映画スタジオで働いていて、アセットのネームスペースの接頭辞に
examplecom::
を使用していると仮定すると、"scrub"ステートを作成する時は、そのステート名をexamplecom::scrub
にしてください。 -
ステート名には、ノードタイプ名やノード名と同じ文字制限がありません。ステート名は多かれ少なかれ任意の文字列にすることができます。
-
ファイル/ディレクトリ名として名前を使用する必要が出てくる場合があります(例えば、コードをファイルに保存する場合)。
ツール + ステート vs. 自己完結型ステート
ほとんどじゃなくても多くの"ネイティブ"のHoudiniノードステートは自身の選択を制御することもノードを作成することもしません。 代わりに、それらのノードステートは、選択の促しとノード作成をシェルフツールに頼っています。 それらのノードステートは単にハンドルの表示を担っているだけです。
独自のPythonステートを使ってこのワークフローを使用することもできます。特に、そのステートがアセットに密接に関係している時です。 選択を促してノードを作成する(そして、その選択をノードの Group フィールドに設定する)シェルフツールスクリプトを書くことができます。
別の方法としては、ステートを自己完結型にすることができます。 つまり、ノードをビューアから呼び出した時にそのノードを作成して、そこに独自のセレクターを持たせることができます。
(ステートにノードが不要な場合(例えば、検査タイプのツール)、その詳細はノードを使用しないステートの書き方を参照してください)
-
2つ以上のタイプの選択を要求する必要がある場合(例えば、"いくつかカーブを選択"した後に"それらのカーブ上のいくつかのポイントを選択する"場合)、ツールスクリプトを使用してください。現在のところ、Pythonステートは、1個のタイプの選択のみ受け入れることができます。
-
コードがノードを作成 する前に 何が選択されているのかを知る必要がある場合、ツールスクリプトを使用してください。
ステートでノードインスタンスを制御する詳細は、ノードの扱い方を参照してください。
Houdiniにステートをインストールする方法
現在のところ、Houdiniで利用可能なカスタムステートを作成する方法が2通りあります: アセットにステートのコードを埋め込む方法とHoudiniパスの正しいディレクトリにそのコードを含んだPythonファイルを配置する方法です。
アセットにステートを埋め込む方法
以下の手順は、アセットを作成し、そこに最低限のステートを試せるようにコードを記述します。
Note
これらの手順は、SOPステートまたはOBJステートの作成にも使うことができます。
-
ステートを追加できるようにアセットの作成から始めます。
空っぽのアセットから始めたい場合は、に従うことでSOPアセットを、に従うことでOBJアセットを作成することができます。
実験できるように"空っぽ"のSOPアセットを手軽に作成するには:
-
オブジェクトレベルで、⇥ Tabメニューを使ってGeoオブジェクトを作成します。
-
geo1
ノードをダブルクリックして、ジオメトリネットワークの中に入ります。 -
⇥ Tabメニューを使ってSubnetworkノードを作成します。
-
subnet1
ノードを右クリックして、 Create Digital Asset を選択します。 -
Operator Name を
statedemo
、 Operator Label をState Demo
、 Save to Library をEmbedded
に設定します。ライブラリの場所を
Embedded
に設定することで、アセットライブラリではなく、現行シーンファイルにアセットが保存されます。
実験できるように"空っぽ"のOBJアセットを手軽に作成するには:
-
オブジェクトレベルで、⇥ Tabメニューを使ってSubnetworkノードを作成します。
-
subnet1
ノードを右クリックして、 Create Digital Asset を選択します。 -
Operator Name を
statedemo
、 Operator Label をState Demo
、 Save to Library をEmbedded
に設定します。ライブラリの場所を
Embedded
に設定することで、アセットライブラリではなく、現行シーンファイルにアセットが保存されます。
-
-
そのアセットのType Propertiesウィンドウを開きます(アセットタイプのインスタンスを右クリックして、 Type Properties を選択します)。
-
Scripts タブをクリックします。
-
左側のスクリプトのリスト下で、 Event Handler ポップアップメニューから"Python Module"を選択します。
左側でその
PythonModule
スクリプトを選択すると、右側のエディタでそのモジュールの内容を編集することができます。 -
以下の最低限のステートコードをエディタ内にペーストします。
from __future__ import print_function # 最低限のステートハンドラーの実装。 class MyState(object): def __init__(self, state_name, scene_viewer): self.state_name = state_name self.scene_viewer = scene_viewer # ハンドラーメソッドをここに記述します。 def onMouseEvent(self, kwargs): dev = kwargs["ui_event"].device() print("Mouse:", dev.mouseX(), dev.mouseY(), dev.isLeftButton()) # アセットのノードタイプの参照を取得します。 nodetype = kwargs['type'] # そのノードの名前とラベルをステートの名前とラベルとして使用します。 state_name = nodetype.name() + ".pystate" label = nodetype.description() category = nodetype.category() # そのステートの名前とラベルとノードタイプカテゴリでViewerStateTemplateをインスタンス化します。 template = hou.ViewerStateTemplate(state_name, label, category) # このバインドは必須です。 template.bindFactory(MyState) # 他の任意のバインドをここに記述します...
ステートクラスに機能を追加する方法の詳細は、以下のステートを実装する方法を参照してください。
Tip
(上記で示したように)モジュールレベルでテンプレートオブジェクトを構築し、
module.template
を使ってそれを参照することができます。 しかし、関数内でテンプレートオブジェクトの作成をラップしたいのであれば、一時変数名(例えば、上記のstate_name
とlabel
)がモジュールのネームスペースから漏れないようにしてください:# モジュールレベルでテンプレートを作成するのではなく、関数内にテンプレート作成コードをラップします。 def createViewerStateTemplate(): # ノードの名前とラベルをステートの名前とラベルとして使用します。 state_name = nodetype.name() + ".pystate" label = nodetype.description() category = nodetype.category() # そのステートの名前とラベルとノードタイプカテゴリでViewerStateTemplateをインスタンス化します。 template = hou.ViewerStateTemplate(state_name, label, category) # このバインドは必須です。 template.bindFactory(MyState) # 他の任意のバインドをここに記述します。 return template
次にモジュールの外で
module.createViewerStateTemplate()
を使えば、そのテンプレートを参照ではなく直接取得することができます。 -
左側のスクリプトのリスト下で、 Event Handler ポップアップメニューから"On Install"を選択します。
左側でその
OnInstall
スクリプトを選択すると、右側のエディタでそのモジュールの内容を編集することができます。ここでは、ステートを登録するために
OnInstall
スクリプト(ノードタイプがセッションにインストールされると実行されます)を使用しました。 -
以下のイベントスクリプトをエディタ内にペーストします:
module = kwargs['type'].hdaModule() hou.ui.registerViewerState(module.template)
これは、そのステートをHoudiniに登録します。
-
次に、このステートの登録を解除するために他のアセットイベントスクリプトも追加しようと思います。
左側のスクリプトのリスト下で、 Event Handler ポップアップメニューから"On Uninstall"を選択します。
左側でその
OnUninstall
スクリプトを選択すると、右側のエディタでそのモジュールの内容を編集することができます。以下のイベントスクリプトをエディタ内にペーストします:
state_name = kwargs['type'].name() + ".pystate" hou.ui.unregisterViewerState(state_name)
これは、そのノードタイプをセッションからアンインストールすると、Houdiniからそのステートの登録が解除されます。
OnInstall
とOnUninstall
のスクリプトを使用することで、 アセットを保存することでステートの違いをテスト できるようになります。これによって、ステートが再度登録させて、私達の変更を反映させます。 -
最後に、この新しいステートを使用するようにアセットを設定します。Type Propertiesウィンドウの Node タブをクリックします。
-
Default State フィールドにそのステート名(ウィンドウの上部に表示されている Operator Type: の隣のノードの内部名と
.pystate
接尾辞)を設定します。 -
Type Propertiesウィンドウの下部にある Accept をクリックします。
アセットがロックされていた場合、Houdiniは、あなたの変更を保存できるようにそのアセットのロックを解除するのか尋ねてきます。
-
このステートをテストするために、ネットワークエディタ内でそのアセットを選択します。マウスをシーンビューア内に移動させて、Enterを押します。
-
ビューアの上部にあるツールバーは、左側にこのステートのラベルを表示します。
-
Tip
上記の手順では、 アセットのノードタイプ の名前を ステート の名前として使用しました。 これは賢明で、ステートとアセットを関係づけるのが簡単になります。 しかし別の方法として、一部の人は、 まず最初 に__Node__ タブの Default State フィールドを入力すると、自動的に そのフィールドの名前がステート名として使用される という便利な方法を発見しました。 Default State フィールドの内容は、埋め込んだステート名と同期しなくなることはありませんが、その名前はノードから自動的に派生しません。
この方法でステートに名前を付けるには、まず最初に名前を付けたいステート名の Default State フィールドを入力します(これは、すべてのステートとインストールされたアセット名に被らないようにしなければなりません)。 次に、スクリプト内でノード名からステート名を計算する箇所で、以下のように名前を取得できるようにスクリプトを変更します:
state_name = node_type.definition().sections()['DefaultState'].contents()
( Default State フィールドの内容は、DefaultState
という名前で"Extra Files"に内部的に保存されるので、このメソッドを使えば、スクリプトでそれを読み込んだり変更することができます。)
Houdiniパスからステートを読み込む方法
以下の手順では、複数のアセット間で"共有"可能なViewer Stateを作成します。このタイプのステート(self-installed
ステートという名前にします)は、Houdiniを起動した時に登録されます。
-
$HOUDINI_USER_PREF_DIR
下にviewer_states
という新しいフォルダを作成します。そのフォルダの中にmystate.py
という新しいファイルを作成します。HOUDINIPATH / viewer_states / mystate.py
-
テキストエディタで
mystate.py
を開き、以下の最低限のステートの実装をペーストします。from __future__ import print_function import hou # 最低限のステートハンドラーの実装。 class MyState(object): def __init__(self, state_name, scene_viewer): self.state_name = state_name self.scene_viewer = scene_viewer # ハンドラーメソッドをここに記述します。 def onMouseEvent(self, kwargs): dev = kwargs["ui_event"].device() print("Mouse:", dev.mouseX(), dev.mouseY(), dev.isLeftButton()) # 登録エントリーポイント def createViewerStateTemplate(): # 名前とラベルを選択します。 state_name = "mystate" state_label = "My New State" category = hou.sopNodeTypeCategory() # テンプレートを作成します。 template = hou.ViewerStateTemplate(state_name, state_label, category) template.bindFactory(MyState) # 他の任意のバインドをここに記述します... # 'mystate'テンプレートを返します。 return template
-
ステートを追加したいアセットを探します。
空っぽのアセットから始めたい場合は、SOPアセットに関しては、OBJアセットに関してはに従ってください。
実験できるように"空っぽ"のSOPアセットを手軽に作成するには:
-
オブジェクトレベルで、⇥ Tabメニューを使ってGeoオブジェクトを作成します。
-
geo1
ノードをダブルクリックして、ジオメトリネットワークの中に入ります。 -
⇥ Tabメニューを使ってSubnetworkノードを作成します。
-
subnet1
ノードを右クリックして、 Create Digital Asset を選択します。 -
Operator Name を
statedemo
、 Operator Label をState Demo
、 Save to Library をEmbedded
に設定します。ライブラリの場所を
Embedded
に設定することで、アセットライブラリではなく、現行シーンファイルにアセットが保存されます。
実験できるように"空っぽ"のOBJアセットを手軽に作成するには:
-
オブジェクトレベルで、⇥ Tabメニューを使ってSubnetworkノードを作成します。
-
subnet1
ノードを右クリックして、 Create Digital Asset を選択します。 -
Operator Name を
statedemo
、 Operator Label をState Demo
、 Save to Library をEmbedded
に設定します。ライブラリの場所を
Embedded
に設定することで、アセットライブラリではなく、現行シーンファイルにアセットが保存されます。
-
-
アセットのType Propertiesウィンドウを開きます(アセットタイプのインスタンスを右クリックして、 Type Properties を開きます)。
-
Node タブをクリックします。
-
Default State フィールドにステート名を設定します(例えば上記のコードでは、これは
mystate
です)。 -
Type Propertiesウィンドウの下部にある Accept をクリックします。
アセットがロックされていた場合、Houdiniは、あなたの変更を保存できるようにそのアセットのロックを解除するのか尋ねてきます。
-
このステートをテストするために、ネットワークエディタ内でそのアセットを選択します。マウスをシーンビューア内に移動させて、Enterを押します。
-
ビューアの上部にあるツールバーは、左側にこのステートのラベルを表示します。
-
Houdiniは起動時にcreateViewerStateTemplate
をコールして、そのステートテンプレートにアクセスして、それを登録します。省略すると、Houdiniは単にそのステートの登録をスキップします。
ステートクラスに機能性を追加する方法の詳細は、以下のステートを実装する方法を参照してください。
Tip
どのファイルがどのステートを保持しているのか把握しやすくするためには、テンプレートをインスタンス化する時に使用するステート名(例えば、examplestudio::bend
)と同様にファイル名(例えば、examplestudio_bend.py
)を維持してください。
Tip
Houdiniセッション中にself-installed
ステートを再読込するには、そのステートの名前を使ってhou.ui.reloadViewerState()をコールしなければなりません。
これによって、Houdiniを再起動することなくステートに変更を加えてテストすることができます。
ステートを実装する方法
以下のセクションでは、ステートを実装するクラスに追加可能なハイレベルのメソッドの概要について載せています。
特定の機能の実装方法のガイドに関しては、以下のページを参照してください:
イニシャライザ(必須)
def __init__(self, state_name, scene_viewer):
state_name
このステートが登録されたステート名の文字列。
scene_viewer
ツールが作用しているシーンビューアを表現したhou.SceneViewerオブジェクト。 このオブジェクトには、ステートを実装する際に使用可能な便利なメソッドがたくさんあります。例えば、hou.SceneViewer.currentGeometrySelection()やhou.SceneViewer.setCurrentGeometrySelection()です。
一般的には、他のメソッドが引数を必要とする場合に、それらの引数をオブジェクトアトリビュートに格納したいことでしょう:
class MyState(object): def __init__(self, state_name, scene_viewer): self.state_name = state_name self.scene_viewer = scene_viewer # イベントハンドラー # ...
イベントハンドラー
ライフサイクルのイベントハンドラー
メソッド名 |
コールされるタイミング |
メモ |
---|---|---|
|
ネットワークからステートが実行された時 |
このメソッドは、ユーザーが新しいノードを作成、または、既存ノードを選択してビューポート内でEnterを押したことによってステートがアクティブになった時にコールされます。 |
|
既存ノードを使わずにステートが実行された時 |
このメソッドは、ユーザーが既存ノード 以外 からステートを実行した時、例えば、シェルフツールスクリプトからhou.SceneViewer.setCurrentState()をコールすることによってステートがアクティブになったときにコールされます。 ノードを使わないで動作するステートに関する情報は、ノードを使用しないステートを参照してください。 アセット関連のステートに関しては、理論的にはこのメソッドでノードを作成することができますが、代わりにツールスクリプトからノードを作成することを強く推奨します。 詳細は、Pythonステートでノードを扱う方法を参照してください。 このメソッドに渡される辞書には、 |
|
ステートが中断された時 |
このメソッドは以下の時にコールされます:
|
|
中断を終了した時 |
このメソッドは以下の時にコールされます:
|
|
ステートを終了させた時 |
このメソッドは以下の時にコールされます:
|
補足メモ:
-
Houdiniは、ツールがアクティブになった時に
onEnter
(ステートが既存ノードに対して動作する場合) またはonGenerate
(ステートが新しいノードを作成する場合)の どちらか をコールします。両方をコールすることはありません。onEnter
に渡される辞書にはnode
アイテムが含まれており、既存ノードをhou.Nodeオブジェクトとしてアクセスすることができます。詳細は、ノードの編集を参照してください。 -
Houdiniは、ステートを開始する時にマウスポインタがビューア上になくても
onEnter
/onGenerate
をコールします。マウスポインタ周辺に何かの視覚的な表示を行ないたいのであれば、それらを表示できるようにonMouseEvent
コールを待ってください。 -
ステートを"中断"している間は、UIイベントは受信されません。
-
onInterrupt
コールの後にそれに呼応するonResume
が必ず実行されるようにすることはできません。ステートを中断している間にユーザーがステートを終了すると、onResume
コールではなくonExit
が受信されます。 -
ユーザーがステートのコンテキストメニューを開いた場合、マウスポインタをそのメニュー上に動かすと
onInterrupt
が受信され、そのメニューから出るとonResume
コールが受信されます。 -
ステートが現行で中断された際にHoudiniがバックグラウンドにあれば、マウスポインタがビューア上にあったとしても、ユーザーから何かの入力(例えば、マウスの移動)がない限りは、ステートは
onResume
コールを受信しません。
UIのイベントハンドラー
詳細は、UIイベントの制御を参照してください。
これらのメソッドに渡される辞書には、以下の追加アイテムが含まれています:
ui_event
イベントに関する情報を持ったhou.ViewerEventインスタンスを含んでいます(例えば、マウスイベントに関しては、現行マウス座標、ボタンがクリックされたかどうか)。
メソッド名 |
コールされるタイミング |
メモ |
---|---|---|
|
マウスを移動/クリックした時 |
マウスの制御を参照してください。 |
|
マウスホイールをスクロールした時 |
hou.UIEventDevice.mouseWheel()は、スクロールの方向に応じて マウスホイールの制御を参照してください。 |
|
コンテキストメニューを選択した時 |
コンテキストメニューの制御を参照してください。 |
選択のイベントハンドラー
ステートにセレクターをバインドしていると、Houdiniは以下のメソッドをコールします。詳細は、選択の制御を参照してください。
メソッド名 |
コールされるタイミング |
メモ |
---|---|---|
|
ユーザーが選択を開始した時 |
なし |
|
ユーザーがジオメトリを選択した時 |
このハンドラーに渡される辞書には、以下の追加アイテムが含まれています:
完了した選択を表現したhou.GeometrySelectionオブジェクト。 現行選択を"受け入れて"セレクターを終了するようにステートに命令を送るには、 このメソッドからTrue を返さなければなりません。
このメソッドがそれ以外の値を返す場合(または、 |
|
ユーザーが選択を終了した時 |
|
ハンドルのイベントハンドラー
ステートにハンドルをバインドしていると、Houdiniは以下のメソッドをコールします。詳細は、Pythonステートハンドルを参照してください。
メソッド名 |
コールされるタイミング |
メモ |
---|---|---|
|
ユーザーがハンドルを使って操作した時 |
これは、ハンドルを動かしてノードパラメータ(またはステート/ディスプレイ)を更新することができます。 このハンドラーに渡される辞書には、以下の追加アイテムが含まれています:
ハンドルの文字列ID。
新しいハンドルパラメータ値を含んだ辞書。
変更されたパラメータ名のリスト。
以前のハンドルパラメータ値を含んだ辞書。 これは、差分を計算するのに役立ちます。 |
|
ノードパラメータが変更された時 |
これは、ノードパラメータを変更した際にハンドルパラメータを更新することができます。 このハンドラーに渡される辞書には、以下の追加アイテムが含まれています:
ハンドルの文字列ID。
新しいノードパラメータ値を含んだ辞書。 |
HOM API
デバッグに関するTips
ステートを再読込する方法
ディスク上に定義されたステートに関しては、そのディスク上のファイルを変更したら、hou.ui.reloadViewerState()を使うことで、Houdiniにそのステートを再読込するように伝えることができます。
デバッグ情報を表示する方法
最も基本的だけどデバッグで役立つのは、スクリプトを実行した時に変数の内容などの情報をプリントすることです。 Houdiniは、このタイプの情報を表示するのにいくつかの方法を用意しています。
-
スクリプト内でPythonの
print
関数を使用することで、情報をプリントすることができます。-
printを使用する主なメリットは、(現在のPythonコールスタックのような)複数行のテキストを含むたくさんの情報を出力することができ、それを後にスクロールして読むことができることです。
-
この出力は、Houdiniの起動方法やウィンドウの開き方に応じて、コンソールウィンドウ、HoudiniのPythonシェルウィンドウ、Houdiniを起動させた時のシェルに表示させることができます。
Tip
print
をステートメントではなく関数として使用することに慣れてしまっているのあれば、from __future__ import print
を使用すると良いでしょう。 この関数は、使いやすくて多機能です。from __future__ import print import traceback class MyState(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"] device = ui_event.device() print("Mouse position x=", device.mouseX(), "y=", device.mouseY()) # 現在のPythonコールスタックをプリントします。 traceback.print_stack()
-
-
hou.SceneViewer.setPromptMessage()とhou.SceneViewer.clearPromptMessage()の関数は、メインのHoudiniウィンドウの下部のスタータスラインにユーザー操作を促すことができます。これらの関数を"応用"することで、デバッグ情報を表示させることができます。
-
このメソッドのメリットは、Houdiniを操作する際にウィンドウの正面中心に情報を表示できることです。
-
このデメリットは、ステータスラインは一度に一行でしか情報を表示できないので、変更があると前のメッセージが消えてしまうことです。
class MyState(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"] device = ui_event.device() message = "Mouse x=%d y=%d" % (device.mouseX(), device.mouseY()) self.scene_viewer.setPromptMessage(message)
-
-
hou.ui.displayMessage()関数は、メッセージウィンドウをポップアップして、ユーザーがOKかCancelをクリックするのを待ちます。
-
これは、デバッグするのにいくつかメリットがあります。その1つは、待機中にスクリプトが一時停止されるので、非常に簡単に変更内容を調べることができます。また、クリックされたボタンに応じていくつかのフィードバックをスクリプトに渡すことができます。もう1つは、この関数はキーワード引数を持っているので、デフォルトで非表示になっている"詳細"ブロックを追加して展開することができます。これは、例えば現在のPythonコールスタックを表示するのに役立ちます。
-
おそらくループでこの関数を使用したくないことでしょう。というのも、複数のメッセージウィンドウを閉じるのに一々クリックしなければならないので面倒なことになります。
import traceback import hou class MyState(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"] device = ui_event.device() # クリックするとメッセージのみが表示されます。 if device.isLeftButton(): message = "Mouse x=%d y=%d" % (device.mouseX(), device.mouseY()) # スクリプト内のこの時点でのコールスタックを取得し、それをメッセージの"詳細"として追加できるように文字列の書式に変換します。 details = "".join(traceback.format_stack()) # メッセージを表示して、ユーザーがメッセージウィンドウのボタンをクリックするのを待ちます。 clicked = hou.ui.displayMessage( message, buttons=("OK", "Error"), details_label="Current call stack", details=details ) # ユーザーが"Error"ボタンをクリックすると、エラーを引き起こします。 if clicked == 1: raise Exception("Don't blame me!")
-
Pythonビューアステート