On this page |
|
一般的なtips ¶
-
コードが実行されたかどうかをチェックする必要がある場合、一番簡単な方法は、hou.ui.displayMessageをコールすることです:
import hou hou.ui.displayMessage("I ran! I ran so far away!")
これを使用することで、変数の値も表示することができます。例えば、イベントハンドラーで
kwargs
グローバル変数の内容を調べるには:import hou hou.ui.displayMessage(repr(kwargs))
-
ディスク上のモジュールにコードを置いて、それをハンドラースクリプトからコールすることで、そのコードをハンドラー間で共有することができます。例えば、ハンドラースクリプトは共通の関数に
kwargs
を渡すことができます:import companyutils companyutils.on_created(kwargs)
-
Houdiniには、非常に膨大で強力(なのに冗長な)APIセットが用意されています。APIリファレンスで利用可能なAPIをブラウズすることで、何がスクリプトで可能なのか調べることができます。
-
一般的には 、Houdiniは、
HOUDINIPATH/scripts/
下でディスク上の“スクリプト”(通常はコールバックスクリプト)を探すのに対し、インポートされるモジュールはHOUDINIPATH/python2.7libs/
に置きます。残念なことに、これでは整合性が取れてないので、例えばHoudiniはpython2.7libs
ではpythonrc.py
初期化スクリプトを探します。
スクリプト内で他のロケーションにあるコードを参照する方法 ¶
ディスク上のPythonファイルの場合
ディスク上のモジュールをインポートする方法を参照してください。
現行.hip
ファイルのセッションモジュールの場合
現行ファイルのセッションモジュールを参照するには、hou.session
を使用します。
現行ノードのPythonモジュールの場合
カスタムノードタイプでは、そのノードタイプに関係するコードを格納するためのデフォルトのPythonモジュールを作成することができます。 そして他の場所でhou.Node.hdaModule(またはhou.NodeType.hdaModule)を使用することで、そのノードタイプのPythonモジュールを参照することができます。
ボタンパラメータのコールバックスクリプトまたはアセットイベントスクリプトの例:
# コールバックスクリプトでは、現行ノードの参照は、kwargs["node"]に含まれています。 nodeutils = kwargs["node"].hdaModule() nodeutils.my_function()
スタートアップスクリプト ¶
Houdiniは、$HOUDINI_PATH
で指定されたディレクトリで以下のディレクトリ/ファイルを探します。
|
Houdiniは、Houdiniのパスで、このパターンに一致するファイルを探し、起動時に実行します。 例えば、 |
|
Houdiniは、シーン( これは、Pythonの Note Houdini FXのみが |
|
Houdiniは、(Houdiniがシーンファイルで起動する場合など)シーンファイルがロードされる時には常にこのスクリプトを実行します。 これは、Pythonの |
|
以下のノードイベントスクリプトを参照してください。 |
Note
新しいスクリプトを認識させるには、Houdiniを再起動する必要があります。 とはいえ、Houdiniを再起動することなく既存のスクリプトを変更することができます。
シーンファイル(.hip)を保存する前と後でスクリプトを実行します ¶
Houdiniは、保存の前と後でスクリプトを実行することができます。 これは、保存の度にアセット管理とソースコントロールのツールを更新するのに役立ちます。
-
HOUDINIPATH/scripts/beforescenesave.py
が存在すれば、Houdiniはシーンファイルを保存する前にそれを実行します。 -
HOUDINIPATH/scripts/afterscenesave.py
が存在すれば、Houdiniはシーンを保存した後にそれを実行します。
Tip
これらのスクリプトは、自動的にグローバル(どのシーンファイルでも動作する)で、セットアップしやすいので便利です。 その一方で、プログラム的にセットアップするのが難しく、保存関係にしか使えません。
シーンファイルイベントに反応させるもっと一般的で細かい調整が効く方法は、シーンファイルイベントハンドラーをセットアップすることです。
これらのスクリプトは、kwargs
グローバル辞書に含まれているコンテキストで実行されます。この辞書には以下の項目が含まれています:
file
(str
)
保存先となる 予定の シーンファイルのパス(beforescenesave.py
では、既にファイルがそこに存在していてもしていなくても構いません)。
autosave
(bool
)
自動保存タイマーによって保存が発動された時には、ここにTrue
が格納されます。ユーザによる“通常の”保存では、ここにFalse
が格納されます。
success
(bool
)
(afterscenesave.py
のみ)Houdiniがファイルに保存可能だった時には、ここにTrue
が格納されます。
Note
指定したパスにHoudiniがファイルを実際に保存できるとは限りません(例えば、ユーザに適切な権限がなかった場合)。
そのため、afterscenesave.py
が実行された時でもそのファイルが存在しなかったり、更新されたデータが含まれていないことがあります。
保存されたデータがファイルに含まれていることを前提としているのであれば、そのスクリプトのkwargs["success"]
をチェックするべきです。
以下のコードは、ファイルを保存した時にgit
にコミットされるようにそのファイルを自動的に“ステージ”します:
# afterscenesave.py import subprocess # 保存に成功していて、それが自動保存でなかった場合にのみコマンドを実行します。 if kwargs["success"] and not kwargs["autosave"]: # gitコマンドにシーンファイルのパスを渡します。 subprocess.call("git", "add", kwargs["file"])
シーンファイルのイベントコールバック ¶
シーンファイルが変更された時にHoudiniがコールするコールバック関数を登録することができます。 Houdiniは、この関数を1個の引数を使ってコールします。この引数は、発生したイベントのタイプを表現したhou.hipFileEventTypeオブジェクトです。
このスクリプトは、特定のイベントに限定されているわけでなく、どのイベントからでもコールされ、そのイベントがあなたの興味のあるイベントなのかどうかを確認するには、そのイベントタイプをチェックする必要があります。 いくつかのイベントに反応するコードを共有させたいことが多いので、これは通常ではシーンイベントで非常に役立ちます。
このスクリプトにhou.hipFileモジュール内の関数を使用することで、現在のシーンファイルに関する情報を取得することができます。 各ファイル操作(New file, Open file, Import file, Save)には、それに相当する“Before”と“After”のイベントタイプがあるので、その操作の変更前と変更後でのシーンファイルの値を読み込むことができます。
例えば、新しいシーンファイルが読み込まれる度に何かのコードを実行するには:
def scene_was_loaded(event_type): if event_type == hou.hipFileEventType.AfterLoad: print("The user loaded", hou.hipFile.path())
パラメータのエクスプレッション ¶
セッションモジュール ¶
Houdiniは、シーンファイルに関連するPythonモジュールを保持します。 これは、 Window ▸ Python Source Editor を使って編集することができます。 これにより、シーンファイルに固有の関数, クラス, オブジェクトを保存するのに便利な場所が与えられ、自動的にそれらが保存されて、シーンファイルと一緒にロードされます。
シーンファイルがロードされた場合(または、ソースコードを編集する場合)、モジュールのソースコードが評価され、他のPythonコードで、モジュールをhou.session
として使用できるようになります。
例えば、Python Source Editor内にlog_deletion()
関数を記述しておけば、以下のようにアセット削除コールバックからその関数をコールすることができます:
hou.session.log_deletion()
hou.appendSessionModuleSource()関数を使用して、プログラムでhou.session
ソースコードを修正することができます。
ソースコードは、シーンファイルに保存されます。
Note
モジュールオブジェクトが一度メモリに読み込まれた後にそのモジュールオブジェクトに加えられた動的な変更内容(例えば、hou.session.x = "foo"
)は、シーンファイルに保存 されません 。
そのモジュールのソースコードのみがシーンファイルに保存されます。
アセットモジュール ¶
各デジタルアセットタイプには、シーンファイルのhou.session
モジュールに似たPythonモジュールがあります。
このモジュールを使用して、アセットタイプに固有の関数, クラス, オブジェクトを保存することができます。
モジュールのソースコードは、(Type Propertiesウィンドウの Extra Files タブにある)PythonModule
という名前のアセットのセクションに保存されます。
このセクションは手動で作成することができます。または、 Scripts タブで“Python Module”イベントハンドラーを作成すると、Houdiniは、このセクションを自動的に作成します。
HDAモジュールのコードでは、以下のコードを使用することで、HDAのノードタイプの参照を取得することができます:
nodetype = kwargs["type"]
(NodeType
オブジェクトがある場合は)hou.NodeType.hdaModuleメソッドにより、または(Node
オブジェクトがある場合は)hou.Node.hdaModuleメソッドにより、モジュールにアクセスすることができます。
例えば、myasset
オブジェクトタイプで、myfunc
関数をコールするには:
hou.nodeType(hou.objNodeTypeCategory(), "myasset").hdaModule().my_function()
アセットの定義内にあるノードのPythonエクスプレッションは、相対参照によりPythonModule
にアクセスすることができます。
例えば、アセットの定義のサブネットワークにあるノードのPythonパラメータエクスプレッションは、hou.node("..").hdaModule().foo()
を使用することができます。
アセット内に多くのPythonコードがあり、複数のモジュール内へ整理したい場合、他のHDAセクションを作成して、これらのモジュールを保存することができます。
例えば、Pythonコードを含むFooModule
セクションを作成することができます。
次に、メインのPythonModule
セクションで、以下のコードを使用して、FooModule
のコンテンツをfoo
としてインポートします:
import toolutils foo = toolutils.createModuleFromSection('bar', kwargs['type'], 'FooModule')
Note
Houdini18.0から、createModuleFromSection
関数は、HDAセクション内にPython3スタイルのprintステートメントが必要になりました。
一般的には、これはHDAセクション内のprintステートメントが丸括弧で引数を閉じなければならないことを意味しています。
例
print("Hello world!")
旧
print "Hello world!"
ディスク上のモジュール ¶
Houdiniは、Pythonのパスに$HOUDINI_PATH/pythonX.Xlibs
ディレクトリを自動的に追加します。
これは、これらのディレクトリ内にあるパッケージやモジュールをPythonコードにインポートすることができるという意味です。
他の場所のパッケージやモジュールをpythonで使用できるようにするには、$PYTHONPATH
環境変数を使用するか、Pythonでsys.path
リストを修正します。
例えば、$HOUDINI_USER_PREF_DIR/python2.7libs/mystuff.py
のモジュールは、以下のコードを使用してインポートします:
import mystuff mystuff.my_function()
スクリプトを1行に維持したいのであれば(例えば、パラメータエクスプレッションやコールバック)、Pythonの__import__
ビルトイン関数を使用することで、そのモジュールを取得して即座にそのアトリビュートにアクセスすることができます:
__import__("mystuff").my_function()
デジタルアセットイベントハンドラー ¶
Pythonで、デジタルアセットイベントハンドラーを書き込むことができます。 Type Properties Windowの Scripts ページでイベントハンドラー(例えば、“On Created”)を作成後、必ず Edit as を“Python”に設定してください。
イベントスクリプトは、kwargs
というグローバル辞書変数のイベントパラメータにアクセスすることができます。
例えば、hou.Nodeオブジェクトをイベントに関与させるには、kwargs["node"]
を使用します。
Houdiniがファイル名を必要とする場所に埋め込まれたスクリプトを参照する方法に関しては、埋め込みファイルを参照する方法を参照してください。
Tip
これらのハンドラーは、 特定のノードタイプ でイベントが発生した時に実行するスクリプトをセットアップすることができます。 どの アセットでもアセットライブラリでもロードまたはアンロードされた時に実行する全般的なアセットイベントハンドラーをセットアップすることもできます。
Note
The default language when creating a handler in the type properties interface is now Python, however, if you create a handler section through scripting, its default language will still be HScript.
To set the default language of an asset section to Python through script, use the HDADefinition.setExtraFileOption method to set the option EventName/IsPython
to True
:
on_created_body = """ from my_studio import register_stats register_stats.createdSpecialNode() """ # Get a reference to the asset definition hdadef = hou.nodeType("mystudio::Sop/flamingo::2.0").definition() # Create the event handler section on the asset hdadef.addSection('OnCreated', on_created_body) # Set the "IsPython" option on the section hdadef.setExtraFileOption("OnCreated/IsPython", True)
イベントタイプ ¶
以下のイベントは、スクリプトをトリガー(発動)することができます。
Before First Create ( |
シーン内に 初めてのノードタイプのインスタンス が作成された時に実行されます。 これには、Houdiniがディスクからシーンファイルをロードした時にノードを作成する時も含みます 。 例えば、シーンにジオメトリオブジェクトがない環境でジオメトリオブジェクトを追加すると、これは、そのジオメトリオブジェクトタイプに対して これは、アセットのインスタンスを1つ以上動作させるのに必要な環境をセットアップするのに役立ちます。 例えば、テクスチャマップを必要な場所にコピーしたり、環境変数を設定します。
|
On Created ( |
ユーザが新しいノードタイプのインスタンスを作成した後に実行されます(これは、シーンファイルをロードした時 ではありません 。下記の これを使用することで、例えば、ノードに変更(Spareパラメータを追加するなど)を加えた時にHoudiniに自動的に保存させるようにすることができます。 |
On Loaded ( |
Houdiniがディスクからシーンファイルをロードした時にノードタイプのインスタンスが作成された後に実行されます(これは、ユーザがネットワークエディタ内にノードを作成した時 ではありません 。上記の 他のアセットの内容の一部 としてノードをロードした時には実行 されません 。アセット内のノードをロードした時に何かの処理をさせたいのであれば、そのアセットのロードハンドラー内にそのコードを記述してください。 これは、すべてのノードがロードされた 後で 各ノードに対して実行されるので、このスクリプトは、シーン全体を見ることになります。 |
On Updated ( |
共有の定義が変更されたためにアセットを更新する時には、そのアセットの各インスタンスに対して実行されます。 |
On Deleted ( |
ノードタイプのインスタンスが削除される前に実行されます(その時点では、まだそのノードは存在します)。ユーザは新しいファイルを開始したり、ファイルを開いたり、終了したりするので、 これは、Houdiniがそのノードを“アンロード”する時を含みます 。
|
After Last Delete ( |
ノードタイプの 最後のインスタンス がシーン内で削除された後に実行されます。 ユーザは新しいファイルを開始したり、ファイルを開いたり、終了したりするので、 これは、Houdiniがそのノードを“アンロード”する時を含みます 。 これは、
|
On Input Changed ( |
このタイプのノードの入力が接続された時、接続解除された時、切り替えられた時に実行されます。
スクリプトに |
On Name Changed ( |
ユーザがこのタイプのノードの名前を変更した後に実行されます。スクリプトに これは、例えば、名前や外部ストレージのパスによってノードに何かのインデックスを付けて、外部インデックスを最新に維持する時に役立ちます。 |
On Install ( |
このノードタイプをセッションにインストールした時に実行されます。 Note HDAノードタイプに変更を保存すると、まず最初に古いHDAノードタイプがアンインストールされてから、最新の変更が反映された新しいHDAノードタイプがインストールされるので、On UninstallとOn Installのスクリプトが発動されます。 |
On Uninstall ( |
このノードタイプをセッションからアンインストールした時に実行されます。 Note HDAノードタイプに変更を保存すると、まず最初に古いHDAノードタイプがアンインストールされてから、最新の変更が反映された新しいHDAノードタイプがインストールされるので、On UninstallとOn Installのスクリプトが発動されます。 |
Sync Node Version ( |
これは、古いバージョン管理システムの一部で、古いバージョンのノードを自動的に最新バージョンに変換できる“アップグレード”ハンドラーを記述することができます。 このシステムは、新しいパラメータの追加などの小さな規模で上位互換のある変更に対して役立ちます。 詳細は、2つのタイプのアセットバージョン管理を参照してください。 これは、シーンファイルを保存して以来、アセットインスタンスをロードして、そのアセットの Version フィールドに変更があった時に実行されます。
これは、ノードのパラメータがロードされて解決された後で、且つ、 スクリプトに このハンドラーは、( (hou.Node.syncNodeVersionIfNeededを使用することで、手動でノードのアップグレードスクリプトをトリガーすることができます。) |
スクリプト変数 ¶
ハンドラースクリプトは、グローバルのkwargs
辞書を使った環境で実行されます。以下のテーブルには、色々なイベントタイプに対して利用可能な辞書のアイテムを載せています:
キー |
値 |
イベント |
---|---|---|
|
ノードインスタンスのhou.Node参照。 |
|
|
ノードタイプのhou.NodeType参照。 |
|
|
HDAインスタンスの古い名前を含む文字列。 |
|
|
接続/切断された入力のインデックス。 |
|
|
現行のHDAバージョンの文字列。 |
|
|
ノードが最後に保存されたHDAバージョンの文字列。 |
|
ノードのイベントハンドラーファイル ¶
イベントハンドラースクリプトは、アセット内への埋め込みだけでなく、Houdiniパスにもファイルとして格納することができます。 デジタルアセットのイベントに反応させるために、おそらくType Propertiesウィンドウのビルトインのイベントハンドラーサポートを使用したいことでしょう。 しかし、スクリプトファイルを使用すると、以下のメリットがあります:
-
これらのディスク上のイベントスクリプトは、アセットとビルトインノードタイプの どちらでも 動作します。
-
どの ノードタイプに対しても実行できる“グローバル”なイベントハンドラーファイルをインストールすることができます。
Houdiniは、以下のパターンに合致したファイルを探します:
-
HOUDINIPATH/scripts/category/nodename_event.py
(例えば、$HOUDINI_USER_PREF_DIR/scripts/obj/geo_OnCreated.py
)のパターンに合致したファイルは、指定したイベントタイプが指定したタイプのノードで発生した時に実行されます。ネームスペース/バージョンを含んだ複雑なノードタイプ名に関しては、その名前の
::
セパレータを 1個のハイフン に置換してください。例えば、ノードタイプ名が
edu.toronto3d::foo::2.0
なら、edu.toronto3d-foo-2.0_OnCreate.py
のようなファイル名を使用します。 -
HOUDINIPATH/scripts/event.py
のパターンに合致したファイルは、指定したイベントタイプが どの ノードにも発生した時に実行されます。
Note
このスクリプトのパスは、“テーブル形式”ではなくノードカテゴリの“ディレクトリ”形式を使用します。
例えば、Object
ではなくobj
、Sop
ではなくsop
、Rop
ではなくout
です。
Houdiniでこれらの形式が異なっている不整合性は、歴史的に残念でなりません。
イベントスクリプトファイルは、ビルトインのkwargs
グローバル辞書変数を使った環境で実行します。
スクリプト内で新しく作成されたノードのhou.Nodeオブジェクトを取得するには、kwargs["node"]
を使用します。
この辞書で利用可能なアイテムに関する情報は、上記のスクリプト変数を参照してください。
Note
Houdiniは、HOUDINIPATH/scripts/category/nodename.py
(イベント接尾辞なし。例えば、$HOUDINI_USER_PREF_DIR/scripts/obj/geo.py
)に合致したファイルも検索します。
これは、ファクトリーノードの“Creationスクリプト”で、(紛らわしいですが)ノードのOnCreated
ハンドラーと同じではありません。
古いドキュメントやチュートリアルでは、ノードが作成される時にコードを実行する方法として、このタイプのファイルのことを説明しています。 しかし、これはデジタルアセットでは動作しません。 今では、代わりにOnCreatedイベントスクリプトを使用します 。 “Creationスクリプト”の内部的な実装の詳細は、何の予告もなく変更されることがあるので注意してください。
個々のノードのイベントハンドラー ¶
個々のノードインスタンス に対してイベントハンドラーをセットアップすることができます。 アセットのどのインスタンス に対してもイベントが発生した時にトリガーされるアセットイベントとは異なり、 これらのハンドラーは、それらをセットアップした 特定のノード に対してイベントが発生した時にのみ実行されます。
ノードに対してイベントハンドラーをセットアップする方法は、hou.Node.addEventCallbackを参照してください。 反応させることができるイベントのタイプは、hou.nodeEventTypeを参照してください。
全般的なアセットイベントハンドラー ¶
アセットライブラリ を変更するハンドラーをセットアップすることができます。例えば、アセットの作成や削除、または、アセットライブラリのインストールやアンインストールの時です。
アセットライブラリのイベントハンドラーをセットアップする方法は、hou.hda.addEventCallbackを参照してください。 反応させることができるイベントのタイプは、hou.hdaEventTypeを参照してください。
シェルフツールスクリプト ¶
ユーザがシェルフツールをクリックした時に実行するスクリプトをPythonで記述します。詳細は、ツールスクリプトを記述する方法を参照してください。
パラメータコールバックスクリプト ¶
ノード上のパラメータ値が変更された時にコールされるPythonスクリプトを記述することができます。
デフォルトのコールバック言語が HScriptであれば、それを
Pythonに変更することを忘れないでください 。
イベントスクリプトは、kwargs
というグローバル辞書変数のイベントパラメータにアクセスすることができます。
例えば、パラメータを含むhou.Nodeオブジェクトを取得するには、kwargs["node"]
を使用し、パラメータのhou.Parmオブジェクトを取得するには、kwargs["parm"]
を使用します。
Tip
コールバックスクリプトを実装する最も便利な方法は、アセットのPythonモジュール内の“実際の”コールバック関数をコールする1行のPythonコードを記述して、そのコードにkwargs
辞書を渡すことです。
例えば、アセットのPythonモジュール内で、オプションの辞書と現行ノードインスタンスを表現したhou.Node
オブジェクトを受け取るmy_callback
関数を作成します。
次に、パラメータのPython Callback の行で、以下のコードを使って、そのモジュールからその関数をコールするように設定します:
hou.pwd().hm().my_callback(kwargs, hou.pwd())
(hou.pwd()は、現在クックされているノードを返します。hou.Node.hmは、アセットのPythonモジュールを返します。)
以下の表は、パラメータコールバックに対するkwargs
辞書のコンテンツを一覧にしたものです。
|
コールバックスクリプトが呼び出されたhou.Parmオブジェクト。 |
|
パラメータを含むhou.Nodeオブジェクト。 |
|
hou.Parmの名前。この値は、 |
|
パラメータを含むhou.ParmTupleの名前。これは、 |
|
パラメータの値です。このエントリは、 |
|
パラメータタプルの値です。これらのエントリは、 |
|
パラメータがmultiparmインスタンスの場合のmultiparmの番号(それ以外は |
|
このパラメータがmultiparmインスタンスでない場合、この値は |
|
これらの値は、 |
パラメータメニュースクリプト ¶
ボタンストリップ/アイコンストリップのパラメータのスクリプト化 ¶
key-valueパラメータボタンスクリプト ¶
バックグラウンド処理 ¶
ユーザが作業している最中に“バックグラウンドで”実行されるPythonコードをセットアップすることができます。
-
hou.ui.addEventLoopCallbackを使用することで、そのUIがビジーでない時にHoudiniがコールする関数をセットアップすることができます。
このコールバック関数は、 高い頻度 (1秒あたり20回程度)でコールされます。この関数は、UIを遅くさせないように実行速度を非常に速くしてください。
-
Qt
QTimer
オブジェクトを使用することで、今後実行されるコードをスケジューリングすることができます。特定の間隔であるコードを実行させたいのであれば、そのコード自体に他のQTimer
をセットアップすることができます。
Tips ¶
-
hou.findFile()を使用して、Houdiniのパスでファイル名を検索することができます。
-
アセット内に埋め込まれたファイルから内容を読み込むには、hou.HDADefinition.sectionsを使って
HDASection
オブジェクトのセクション名の辞書を取得してから、hou.HDASection.contentsを使ってそのセクションの内容を取得します。my_asset
オブジェクトに埋め込まれたexample
ファイルの内容を読み込む例:objects = hou.nodeTypeCategories()["Object"] my_asset = objects.nodeTypes()["my_asset"] my_asset_def = my_asset.definition() section = my_asset_def.sections()["example"] contents = section.contents()
ショートカットとして
opdef:
パスを使用することで、アセットセクションがまるでファイルであるかのようにそれらのセクションを読み込むことができます:content = hou.readFile("opdef:Object/my_asset?example")
-
hou.session
からグローバルスコープのPython変数にアクセスするには、__main__
をインポートします。例えば、x
がグローバルスコープの変数であれば、その変数に__main__.x
としてアクセスすることができます。この方法を使用して、パラメータエクスプレッション, HDA Pythonモジュール, Pythonボタンコールバック, シェルフスクリプトなどからPythonのグローバル変数にアクセスすることができます。
See also |