Houdini 18.0 基本

メニューのカスタマイズ

On this page

概要

Houdiniでは、XML構成ファイルを使ってメインメニューを含むいくつかのメニュー をカスタマイズすることができます。

  • HoudiniはHoudiniインストール場所($HFS/houdini)からデフォルトのメニューファイルを読み込み、そして、$HOUDINI_MENU_PATH(デフォルトのパスは、$HOME/houdiniX.x/と現行作業ディレクトリです)からそれと同じ名前のファイルを読み込みます。 これは、ユーザ毎にメニューをカスタマイズすることができます。

  • デフォルトでは、$HOUDINI_MENU_PATH$HOUDINI_PATHと同じです。

  • 各定義ファイルは、そのパスで初めに読み込んだファイルに対してメニューを追加、再配置、削除することができます。

  • メニューとメニューアイテムはidアトリビュートで識別されます。idアトリビュートを使わないでメニューやアイテムを作成してもエラーにはなりませんが、様々な理由により、すべてのメニューとアイテムにはidアトリビュートを使うべきです。

  • メインメニューファイルのアクションとトグルメニューアイテムに関しては、idの値は、ホットキーのシンボルにもなり、ホットキーをHotkey Managerのアイテムに割り当てることができます。

    ホットキーのシンボルは、h.で始まらなければなりません。つまり、アイテムのidがまだh.で始まっていなければ、Houdiniは、そのホットキーのシンボルをidの前にh.を付けて作成します。

  • Houdini出荷時のデフォルトファイル内のほとんどのメニューアイテムは、ホットキーに基づいて組み込み機能をトリガーします。しかし、アクションアイテムもPythonスクリプトをトリガーすることができます。さらに、エイリアスメニューアイテムを作成することができます。以下の<scriptItem><actionId>のタグを参照してください。

  • $HOUDINI_MENU_PATH/OPmenu.xmlを使ってネットワークエディタ内のノードのコンテキストメニューをカスタマイズすることができます。

構成ファイル

構成ファイルはXMLフォーマットで、$HFS/houdini/menu.xsdで定義されたスキーマを使用します。

メインメニューファイル

メインメニューは$HFS/houdini内の以下のファイルで定義されています。

ファイル

使用方法

MainMenuCommon.xml

Houdini FXとHoudiniに共通のメニューを定義します。

MainMenuMaster.xml

Houdini FXメニューアイテムを共通メニューに追加するオーバーレイ。これはHoudini FXライセンスを開始すると適用されます。

MainMenuEscape.xml

Houdiniメニューアイテムを共通メニューに追加するオーバーレイ。これはHoudiniライセンスを開始すると適用されます。

MainMenuMPlay.xml

Mplay用のメニュー。

Houdiniは、逆順で$HOUDINI_MENU_PATHを検索し、まず最初にMainMenuCommon.xmlを探してから、MainMenuMaster.xmlファイルを探します。 メニュー項目に干渉している定義または編集があれば、後に読み込まれたファイルの優先度が高くなります。 "$HOUDINI_USER_PREF_DIR:$HH"がデフォルトの$HOUDINI_MENU_PATHを例にすると、Houdiniは、まず最初に"$HH/MainMenuCommon.xml"を探してから、次に"$HOUDINI_USER_PREF_DIR/MainMenuCommon.xml"を探し、"$HH/MainMenuMaster.xml"を探し、 最終的に"$HOUDINI_USER_PREF_DIR/MainMenuMaster.xml"を探します。

メニュー構成ファイル用のドキュメントエレメントは常に<mainMenu>です。メニューの定義と操作のエレメントは、<mainMenu>の中に記述します。

<?xml version="1.0" encoding="UTF-8"?>
<mainMenu>
...
</mainMenu>

mainMenuの中には、menuBaraddScriptItemmodifyItemremoveItemの4つのタグが許可されています。

<menuBar>エレメントにはメニューの構成を定義します。Houdini出荷時のMainMenuCommon.xmlファイルには、メインメニューを定義するmenuBarエレメントを含んでいます。最新のファイルで基本的な構成をカスタマイズするには、add、modify、removeのタグを使います。

このタグを使って、前のファイルで定義したメニューに構成を追加することもできます。

この例では、ユーザが選択するとスクリプトが走る3つのアイテムを含んだ"My Scripts"と呼ぶ上位レベルのメニューが新しく追加されます。

<?xml version="1.0" encoding="UTF-8"?>
<mainMenu>
  <menuBar>
    <subMenu id="my_submenu">
      <label>My Scripts</label>

      <scriptItem>
        <label>My First Item</label>
        <scriptPath>$HOME/scripts/first_script.py</scriptPath>
      </scriptItem>

      <titleItem>
        <label>My Title</label>
      </titleItem>

      <scriptItem id="h.second_item">
        <label>My Second Item</label>
        <scriptPath>$HOME/scripts/generic_script.py</scriptPath>
        <scriptArgs>-q -n camera</scriptArgs>
      </scriptItem>

      <separatorItem/>

      <scriptItem id="h.third_item">
        <label>My Third Item</label>
        <scriptPath>$HOME/scripts/generic_script.py</scriptPath>
        <scriptArgs>-q -n light</scriptArgs>
      </scriptItem>
    </subMenu>
  </menuBar>
</mainMenu>

コンテキストメニューファイル

いくつかのコンテキスト(右クリックボタン)メニューは、メインメニューファイルと同様のファイルを使って構成することができます。

ファイル

メニュー

id接頭辞

CHGmenu.xml

チャンネルグループコンテキストメニュー

h.pane.group.

ChannelListMenu.xml

プレイバーのチャンネルリストコンテキストメニュー

h.

KeyframesMenu.xml

プレイバーのキーフレームコンテキストメニュー

h.

OPmenu.xml

ノード編集メニュー(つまり、ネットワークエディタ内でノードを右クリック)

h.pane.wsheet.

PaneTabTypeMenu.xml

ペインタブタイプメニュー(つまり、ペインタブストリップ上の'+'ボタンをクリックしてNew Pane Tab Typeサブメニューを開く、または、ペインタブをRMBクリックして表示されるラジオボタン版のメニューを選択)

h.pane.

PARMmenu.xml

パラメータコンテキストメニュー(パラメータエディタで)

h.pane.parms.

ParmGearMenuenu.xml

パラメータエディタ内のギアアイコンメニューボタンに取り付けられているメニュー。

h.pane.parms.

PlaybarMenu.xml

プレイバーコンテキストメニュー

h.

ShelfToolMenu.xml

シェルフのツールボタンのコンテキストメニュー

h.shelf.menu.

ShelfMenu.xml

シェルフとシェルフタブのコンテキストメニュー

h.shelf.menu.

ShelfSetMenu.xmlShelfSetPlusMenu.xml

シェルフセットのメニュー(それぞれシェルフの右上コーナーにあるドロップダウン矢印ボタン、タブの隣のプラスボタン)

h.shelf.menu.

VOPFXmenu.xml

VOPノードのパラメータの右のMotion FXメニュー

h.pane.parms.

コンテキストメニューファイルの構造はメインメニューファイルと同様ですが、上位レベルのエレメントは<menuDocument>で、メニューアイテムは<menu>エレメントで囲みます。

組み込み関数のメニューアイテムのラベルは動的に生成されます。Houdiniは<actionItem>内の<label><labelExpression>のエレメントを無視します。

<?xml version="1.0" encoding="UTF-8"?>
<menuDocument>
  <menu>
    <scriptItem id="create_myramp">
      <label>My First Item</label>
      <scriptPath>$HOME/scripts/first_script.py</scriptPath>
    </scriptItem>
  </menu>
</menuDocument>

idは、ある固定接頭辞(構成するコンテキストメニューに依存)を持つホットキーに対応します。例えば、id=create_rampのアイテムは、Hotkey Managerでは、h.pane.parms.vopeffects.create_rampアクションを参照します。

ポップアップメニューは<scriptItem>(と他の)メニューアイテムエレメント内に<context> XMLエレメントもサポートしています。<context>エレメントでは、メニューアイテムをメニュー内に含めるために必須となる条件を指定します。<context>エレメントには以下のエレメントを追加することができます:

<ownerMask>

グロッビング(ワイルドカード)を使って、指定した文字列に対して所有者の名前と一致するものを見つけます。 ownerはメニューをポップアップ表示するエンティティ(例えば、パラメータやシェルフツール)。

<scriptItem id="box_tool_item">
  <label>Box Tool Menu Item</label>
  <context>
    <ownerMask>*box*</ownerMask>
  </context>
</scriptItem>

<expression>

これは、Pythonエクスプレッションがtrue(ゼロ以外)を評価されるとメニューアイテムがメニューに追加され、そうでない場合はメニューから排除されます。

<expression>kwargs.get('name','') == 'sop_box'</expression>
<expression>hou.applicationVersion()[0] >= 12</expression>

Note

複数行のエクスプレッションを使用することができます。そのエクスプレッションは必ずTrueまたはFalseをreturnしなければなりません。

例えば、このエクスプレッションは、kwargsにhou.Nodeオブジェクトが存在し、それがObjectノードの場合にTrueを返します:

<expression>
node = kwargs.get("node", None)
if node is None:
    return False

return node.type().category().name() == "Object"
</expression>

<parentNetworkType>

アイテムを表示させるネットワークタイプのリストを指定します。このエンティティはVOP FXメニューにだけ有効です。

<parentNetworkType>vopsurface,vopmaterial</parentNetworkType>

VOP FXメニューファイル

これは、VOPノードのパラメータエディタの入力パラメータの隣にあるエクスポートメニューボタンをクリックしたときに表示されるメニューです。このメニューはVOPノードの"boilerplate"セットをパラメータの入力に接続して様々なエフェクトをセットアップするのに使います。メニューはVOPFXmenu.xmlファイルを使ってカスタマイズすることができます。

VOPFXmenu.xmlの構造はコンテキストメニューファイルと同様ですが、<scriptItem>または<separatorItem>エレメント内の<context>エレメントを使ってメニューアイテムが利用できるネットワークタイプを指定することができます。<context>エレメント内には、<parentNetworkType>エレメントを追加します。エレメントのテキストはネットワークタイプ名(またはカンマ区切りの名前のリスト)です。

<menuDocument>
  <menu>
    <actionItem id="create_parm"/>
        <scriptItem id="create_texture">
          <label>Texture Map</label>
      <context>
        <parentNetworkType>
        vopsurface,vopmaterial,rsl_vopmaterial
        </parentNetworkType>
      </context>
      <scriptCode><![CDATA[
        import voptoolutils

        effect = voptoolutils.parmVopEffect(kwargs, 'texture')
      ]]></scriptCode>
    </scriptItem>
    ...

コンテキストタイプトークンは、ノードが存在する 親のネットワークノードタイプ です。例えば、VOPサーフェスシェーダに関しては、トークンはvopsurfaceです。VOP SOPノードに関しては、vopsopです。

<context>を指定しない場合、アイテムはVOPコンテキストすべてに表示されます。

idは、h.pane.parms.接頭辞を持つホットキーに対応します。例えば、id=create_rampのアイテムは、Hotkey Managerでは、h.pane.parms.vopeffects.create_rampアクションを参照します。

メニューアイテム

<menu>

トップレベルのメニュー。このエレメントには以下のアトリビュートを持つことができます:

allowRedundantSeparators

TrueまたはFalseに設定します。 Trueに設定すると、余分なセパレータ(つまり、セパレータの後のセパレータやメニューの最初と最後のセパレータ)をメニューに表示させることができます。 Falseに設定すると、Houdiniは自動的に、その余分なセパレータを削除して整理します。 デフォルトはFalseです。

<scriptItem>

<subMenu>内で、ユーザが選択するとPythonスクリプトをトリガーするメニューアイテムを追加します。

コンテキストメニューアイテムでは、指定したスクリプトがkwargs変数を含むPythonスコープ内で走ります。これはユーザがメニューを呼び出したアイテムに関して役立つ情報を含む辞書です。別のコンテキストメニューには、別のキーが用意されています。詳細は、$HFS/houdiniの中のファイルを参照してください。

<scriptItem>エレメントには以下のサブエレメントがあります。

<label>

メニューアイテムのラベル。<label>または<labelExpression>のうち1つしか<scriptItem>エレメント内に存在できません。

<labelExpression>

メニューアイテムのラベルを生成するPythonスクリプトを格納します。<label>または<labelExpression>のうち1つしか<scriptItem>エレメント内に存在できません。

Note

複数行のエクスプレッションを使用することができます。そのエクスプレッションは必ず文字列をreturnしなければなりません。

kwargsグローバル辞書変数はPythonスクリプトで利用可能です。 その辞書は、メニューの現行コンテキストに関連した情報を格納しています。

ユーザがこのメニューアイテムを選択した時に実行するスクリプトのパスを含みます。

<scriptCode>

ユーザがこのメニューアイテムを選択したときに実行するPythonスクリプトを含みます。

このスクリプトは、メニューアイテムが選択されると即座に実行されます。スクリプトの実行をメニューが閉じた後まで遅延させるには、<scriptCode>の実行を遅延させる方法を参照してください。

<scriptArgs>

(任意)スクリプトをコールした時のスクリプトに渡す引数文字列。スクリプトでは、sys.argvリストを使って、これらの引数を取得することができます。

これは複数のメニューアイテム用に1個のスクリプトを使って、パラメータに基づいて動作を変化させることができます。

<scriptItem id="h.my_item">
    <label>Geometry...</label>
        <scriptCode><![CDATA[
        import soptoolutils

    soptoolutils.chooseAndOpenGeoFile({}, False)
    ]]></scriptCode>
</scriptItem>
<scriptItem id="my_action">
    <label>My Action</label>
    <scriptCode><![CDATA[
        arguments = '\n  '.join(['%s = %s' % (k,w) for (k,w) in kwargs.items()])
        hou.ui.displayMessage('My Action with kwargs:\n  ' + arguments)
        ]]>
    </scriptCode>
</scriptItem>

<subMenu>

(メインメニューファイル内の)<menuBar>内では、これはトップレベルメニューに取り付けられます。(コンテキストメニューファイル内の)<menu>または他の<subMenu>内では、これはサブメニューを作成します。

<subMenu>エレメントの1番目の子を、メニューのラベルテキストを含んだ<label>エレメントにしてください。

<subMenu id="animation_menu">
    <label>Channels</label>

    <actionItem id="scope_append_channels" />
    <actionItem id="scope_channels"/>
        <separatorItem/>
        <actionItem id="set_keyframe"/>
        ...
    </subMenu>

<subMenu>エレメントは以下のアトリビュートを持つことができます:

allowRedundantSeparators

TrueまたはFalseに設定します。 Trueに設定すると、余分なセパレータ(つまり、セパレータの後のセパレータやメニューの最初と最後のセパレータ)をメニューに表示させることができます。 Falseに設定すると、Houdiniは自動的に、その余分なセパレータを削除して整理します。 デフォルトはFalseです。

<separatorItem>

<menu>または<subMenu>エレメント内に、分割線を作成します。

<titleItem>

メニューでアイテムを分類するのに役に立つ読み取り専用タイトルを作成します。

<actionItem>

idアトリビュート内のホットキーシンボルに基づいて、組み込みHoudiniコマンドを呼び出すメニューアイテムを作成します。

メインメニューファイル内で:

  • <actionItem>エレメントのidアトリビュートは、メニューアイテムで呼び出される内部のHoudiniコマンド(ホットキーシンボル)を識別します。

  • <actionItem>エレメントには、メニューアイテムのラベルのテキストを含む子の<label>エレメントを持ちます。

<actionItem id="h.startuphelp">
    <label>Start Here</label>
</actionItem>

コンテキストメニュー内で:

  • idアトリビュートはメニュー内のすべてのアイテムに対して共通コマンドに追加する 接尾辞 を指定します。

    例えば、PARMmenu.xml(パラメータコンテキストメニュー)構成ファイルでは、すべてのidアトリビュートがh.pane.parms接頭辞を持つホットキーに対応します。つまり、id="revert_to_prev_val"を持つアイテムは、h.pane.parms.revert_to_prev_valホットキーアクションを参照します。

  • 組み込み関数用のメニューアイテムが動的に生成されます。 Houdiniは<actionItem>内の<label>エレメントを無視します。

<actionItem id="set_keyframe"/>

<actionId>タグを使用することで、他のアイテムのメニューアイテムエイリアスを作成することができます。これによって、新しいラベルを持った新しいアイテムをどの場所にも配置することができ、それが他のメニューアイテムのアクションを実行します。

<actionItem id="set_keyframe_alias">
    <actionId>set_keyframe</actionId>
</actionItem>

<scriptMenuStripDynamic>

Pythonスクリプトで定義された動的生成メニューアイテムのスクリプトを作成します。 <menu><subMenu>のエレメント内にストリップを格納しなければなりません。 <scriptMenuStripDynamic>エレメント上のidアトリビュートは、そのストリップ内のメニューアイテムから呼び出される内部のHoudiniコマンド(ホットキーシンボル)を識別して登録します。

<scriptMenuStripDynamic>エレメントは、以下のサブエレメントを持つことができます。

  • <contentsScriptCode>:

    ストリップのメニューアイテムを文字列のシーケンスとして返すPythonスクリプトを格納します。 そのシーケンスは、メニューアイテムの内部トークン名とラベルを格納します。 例えば、['one', 'Apples', 'two', 'Cream Pie']は、内部トークン名の"one"と"two"、それらのラベルの"Apples"と"Cream Pie"を持つ2つのメニューエントリーに相当します。

    Pythonスクリプトが1行しかない場合、HoudiniはそれをPythonエクスプレッションとして評価します。 複数行が含まれている場合は、Houdiniはそれを関数ボディとして評価し、最後の行で文字列シーケンスをreturnする必要があります。

    kwargsグローバル辞書変数はPythonスクリプトで利用可能です。 その辞書は、メニューの現行コンテキストに関連した情報を格納しています。 例えば、パラメータRMB-menuには、現在メニューが適用しているノードパラメータのリストを持つkwargs内にparmsエントリーが格納されます。 kwargs内のエントリーを使用することで、ストリップで表示させるメニューアイテムを状況に応じて選択することができます。

    Note

    コンテンツストリップ内のkwargsエントリーにアクセスした時、まず最初にそれらのエントリーが存在するかチェックして、スプリクトが例外を起こさないようにしてください。 これは、メニューが開かれてもまだそのメニューストリップが開かれていない時にkwargs辞書が完全に初期化された状態でコンテンツストリップが実行されるかもしれないので必要です。

    例えば、get(...)メソッドを使用してkwargsエントリーにアクセスします:

    node = kwargs.get("node", None)
    if node:
        # ノードプロパティにアクセス...
        ...
    
  • <scriptCode>:

    ユーザがこのストリップからメニューアイテムを選択した時に実行されるPythonスクリプトを格納します。

    kwargsグローバル辞書変数はPythonスクリプトで利用可能です。 その辞書は、メニューの現在のコンテキストに関連した情報を格納しています。 また、選択したメニューアイテムの内部トークン名とラベルをそれぞれ記録したselectedtokenselectedlabelも格納しています。

    このスクリプトは、メニューアイテムが選択されると即座に実行されます。スクリプトの実行をメニューが閉じた後まで遅延させるには、<scriptCode>の実行を遅延させる方法を参照してください。

以下は、動的なメニューストリップをスクリプト化したサンプルです:

<subMenu id="mySubMenuId">
    <label>Colors</label>
    <scriptMenuStripDynamic id="myUniqueDynamicStripId">
        <contentsScriptCode><![CDATA[
        menu_items = ["red", "The Color Red", "green", "The Color Green", "blue", "The Color Blue"]
        return menu_items
        ]]></contentsScriptCode>
        <scriptCode><![CDATA[
        import hou

        selected_token = kwargs["selectedtoken"]
        selected_label = kwargs["selectedlabel"]

        hou.ui.displayMessage("You have selected %s (%s)." % (selected_label, selected_token))
        ]]></scriptCode>
    </scriptMenuStripDynamic>
</subMenu>

Note

スクリプト化したチェックボックスとラジオスタイルのメニューアイテムの作成、動的にユーザ定義メニュー/アイテムの無効・有効化、動的内容のサブメニューは現在はサポートされていません。

デフォルトメニューは上記で定義していない特別なタグを使用します。これらのタグはHoudiniの内部実装に密接に関連付けられていて、現在ではユーザがカスタマイズすることができません。

メニューの再構成

新しいアイテムやサブメニューを既存メニューに追加するには、既存の親の構造を複製して、そこに新しいアイテムを記述します。Houdiniは複製した構造と定義した構造を組み合わせます。

例えば、デフォルトの Edit ▸ Preferences のサブメニューは次のように定義されています:

<?xml version="1.0" encoding="UTF-8"?>
<mainMenu>
    <menuBar>
        ...
        <subMenu id="edit_menu">
            <label>Edit</label>
            ...
            <subMenu id="preferences_submenu">
                <label>Preferences</label>
                ...
            </subMenu>
            ...
        </subMenu>
        ...
    </menuBar>
</mainMenu>

新しいアイテムをPreferencesのサブメニューに上書きで追加するには、次のようにします:

<?xml version="1.0" encoding="UTF-8"?>
<mainMenu>
    <menuBar>
        <subMenu id="edit_menu">
            <subMenu id="preferences_submenu">
                <scriptItem id="h.mypref">
                    <label>My Preference</label>
                    <scriptPath>$HOME/scripts/generic_script.py</scriptPath>
                </scriptItem>
            </subMenu>
        </subMenu>
    </menuBar>
</mainMenu>

(構造を複製しないで1個のアイテムを追加する方法は、以下のaddScriptItemタグも参照してください。)

メニュー内の新規スクリプトアイテムの位置を細かく調整するには、<scriptItem>または<actionItem>内の次のサブタグを使うことができます:

<insertBefore />

既存アイテムの前、メニューの初めに、このアイテムを挿入します。

<insertBefore>id</insertBefore>

id="id"を持つアイテムの前に、このアイテムを挿入します。

<insertAfter />

既存メニューの後、メニューの終わりに、このアイテムを挿入します。

<insertAfter>id</insertAfter>

id="id"を持つアイテムの後に、このアイテムを挿入します。

<insertAtIndex>num</insertAtIndex>

メニューでn番目の位置に、このアイテムを挿入します。

つまり、Preferencesサブメニューの 3D Viewports エントリーの前に新しいメニューアイテムを挿入するには、以下のようにします:

<?xml version="1.0" encoding="UTF-8"?>
<mainMenu>
    <menuBar>
        <subMenu id="edit_menu">
            <subMenu id="preferences_submenu">
                <scriptItem id="h.mypref">
                    <label>My Preference</label>
                    <insertBefore>h.prefs_viewports</insertBefore>

                    <scriptPath>$HOME/scripts/generic_script.py</scriptPath>
                </scriptItem>
            </subMenu>
        </subMenu>
    </menuBar>
</mainMenu>

<addScriptItem>

<mainMenu>内のこのタグでは、上記の示すようなメニュー構造を複製しないで、既存の親のメニューに1個のスクリプトを追加することができます。

<mainMenu>
    <addScriptItem id="h.mypref">
        <label>My Preference</label>
        <parent>preferences_submenu</parent>
        <insertBefore>h.prefs_viewports</insertBefore>

        <scriptPath>$HOME/scripts/generic_script.py</scriptPath>
    </addScriptItem>
</mainMenu>

<parent>id</parent>

このアイテムを追加するメニューのid

<modifyItem>

<mainMenu>内のこのタグでは、既存アイテムの再ラベル、再配置、再親子化することができます。

<modifyItem>エレメントには、<label><parent><insertAfter><insertBefore><insertAtIndex>エレメントを含むことができます。

例えば、以下のXMLコードは、 Render ▸ Create Render Node ▸ Other Output Nodes ▸ Dynamics アイテムを1つ上のレベルに移動します:

<mainMenu>
    <modifyItem id="h.create_dynamics">
        <label>Moved Dynamics</label>
        <parent>render_create_submenu</parent>
        <insertBefore>render_create_subsubmenu</insertBefore>
    </modifyItem>
</mainMenu>

<menuBar>定義ストラクチャー内の<modifyItem>タグを使って以前定義したアイテムを調整することもできます。

<removeItem>

<mainMenu>内のこのタグは既存アイテムを削除することができます。

例えば、以下のXMLコードは、デスクトップサブメニューを上位レベルに移動し、不要な分割線を削除します。

<mainMenu>
  <menuBar>
    <subMenu id="desktop_submenu">
      <insertBefore>help_menu</insertBefore>
    </subMenu>
  </menuBar>

  <removeItem id="windows_menu_sep_0"/>
</mainMenu>

トグルとラジオのアイテム

<scriptToggleItem><scriptMenuStripRadio><scriptRadioItem>のタグは、独自チェックマークとラジオのメニューアイテムを作成します。アイテムの"状態"はHoudiniのグローバル変数に保存されます。

Note

このページを記述している時点では、オプションのスクリプトではHoudiniのグローバル変数を取得・設定する方法はありません。つまり、hou.hscript()を使って、HScriptのechosetのコマンドにアクセスする必要があります。

# グローバルの値を設定します。
hou.hscript("set -g MYGLOBAL = 0")

# グローバルの値を取得します。
value, err = hou.hscript("echo $MYGLOBAL")

チェックボックス(トグル)アイテム

<scriptToggleItems>を使ってオン・オフするアイテムを作成することができます。<variableName>サブエレメントは、このメニューアイテムで制御されるグローバル変数の名前を指定します。デフォルトでは、このメニューアイテムを閉じると、グローバル変数の値は"0""1"に切り替わります。

<scriptToggleItem id="myitem">
    <label>メニューに表示させるテキスト</label>
    <variableName>MY_GLOBAL_VARIABLE</variableName>
</scriptToggleItem>

任意で<scriptCode>サブエレメント内にPythonスクリプトを記述したり、<scriptPath>参照を使ってPythonスクリプトを指定することができます。 スクリプトは、ユーザがアイテムを選択した時やグローバル変数の値が変わったときに実行されます。

<subMenu id="edit_menu">
    <scriptToggleItem id="myvar_toggle_script">
        <label>MYVAR_TOGGLE Status With Script</label>
        <insertBefore>objects_submenu</insertBefore>
        <variableName>MYVAR_TOGGLE</variableName>
        <scriptCode><![CDATA[
        hou.hscript("""
if( $MYVAR_TOGGLE ) then
set -g MYVAR_TOGGLE = 0;
else
set -g MYVAR_TOGGLE = 1;
endif
        """)
        hou.hscript('varchange MYVAR_TOGGLE')
        (out, err) = hou.hscript('echo $MYVAR_TOGGLE')
        if( int(out) ):
            status = "on"
        else:
            status = "off"
        hou.ui.displayMessage( "MYVAR_TOGGLE has been turned " + status )
    ]]></scriptCode>
    </scriptToggleItem>
</subMenu>

ラジオ(お互いに排他的)アイテム

コードは変数を設定するべきですが、これは特に必要ありません。明示的なスクリプトを指定しないラジオアイテムは以下のPythonスクリプトと同等です:

コードでは何でも実行できます。さらに、最低でもhou.hscript('varchange VAR')をコールしてラジオアイテムのインデックスを返すのは良い考えです。そうしないと、変数がクリックしたアイテムに相当する値に設定していなければ、メニューは同期化しない場合があります。

標準のメニューアイテムの代わりに<scriptMenuStripRadio>を使って、お互いに排他的なアイテムのリストを作成することができます。<variableName>サブエレメントは、このメニューアイテムで制御されるグローバル変数の名前を指定します。<scriptMenuStripRadio>エレメントには、リストのアイテムを表現する<scriptRadioItem>エレメントを1つ以上含めるべきです。デフォルトでは、リストのメニューアイテムの1つを選択すると、グローバル変数の値をメニューアイテムの<variableValue>サブエレメント内の値に変更します。

<scriptMenuStripRadio>
    <variableName>MY_GLOBAL_VARIABLE</variableName>

    <scriptRadioItem id="my_item_1">
        <label>First item</label>
        <variableValue>value1</variableValue>
    </scriptRadioItem>
    ...
</scriptMenuStripRadio>

任意で<scriptCode>サブエレメント内にPythonスクリプトを記述したり、<scriptPath>参照を使ってPythonスクリプトを指定することができます。スクリプトは、ユーザがアイテムを選択したり、グローバル変数の値がそのアイテムの<variableValue>サブエレメント内の値に変わる時に実行されます。

デフォルトのアクションは次のスクリプトと同等です:

hou.hscript('set -g VAR = val')
hou.hscript('varchange VAR')`

技術的に、スクリプトは何でも実行でき、これらのコマンドを使う必要がありませんが、ラジオメニューの動作に関してはユーザの期待に応える必要があります。それにはグローバル変数をある場所に設定したり、varchangeをコールしてメニューのUIを更新するべきです。

<subMenu id="edit_menu">
    <subMenu id="myvar_variable">
        <label>Set MYVAR_RADIO</label>
        <insertBefore>objects_submenu</insertBefore>

        <scriptMenuStripRadio>
            <variableName>MYVAR_RADIO</variableName>
            <scriptRadioItem id="h.myvar_one">
                 <label>One</label>
                 <variableValue>value_of_one</variableValue>
            </scriptRadioItem>
            <scriptRadioItem id="h.myvar_two">
                 <label>Two</label>
                 <variableValue>two</variableValue>
            </scriptRadioItem>
            <scriptRadioItem id="h.myvar_three">
                 <label>Three</label>
                 <variableValue>3</variableValue>
            </scriptRadioItem>
            <scriptRadioItem id="h.myvar_four">
                 <label>Four</label>
                 <variableValue>fourth_value</variableValue>
                 <scriptCode><![CDATA[
                    message = 'Do you want to change the global variable MYVAR_RADIO?'
                    response = hou.ui.displayMessage( message, ('Yes', 'No'))
                    if response == 0:
                    hou.hscript("set -g MYVAR_RADIO = 'fourth_value'")
                    hou.hscript("varchange MYVAR_RADIO")
                    else:
                    # ラジオストリップUIを古いラジオインデックスに保存するような箇所でvarchangeをコールします。
                    hou.hscript("varchange MYVAR_RADIO")]]>
                </scriptCode>
            </scriptRadioItem>
        </scriptMenuStripRadio>

    </subMenu>
</subMenu>

<scriptCode>の実行を遅延させる方法

<scriptCode>スクリプトは、メニューアイテムがクリックされた時に即座に実行させるよりも、その実行を遅延させたい場合があります。

例えば、メッセージダイアログを出したり、選択ダイアログから選択を促すようなコードをスクリプトに記述したとします。 どちらの場合でも、ダイアログを閉じない限りスクリプトがずっと実行されたままになってしまいます。 メニューを完全に閉じないとスクリプトが完了しないようなスクリプトは、即座に実行させたくありません。 これだと、場合によってはダイアログが開かれている間はメニューが表示されたままフリーズしてしまいます。 さらに、ダイアログを開けば処理されるUIイベントの順番が内部的に変更される可能性があるのでHoudiniでクラッシュが起こり得ます。

メニューが完全に閉じた後に<scriptCode>スクリプトが実行されるように遅延させるには、hdeferevalモジュールを使用します。

例えば、以下のスクリプトを記述したとします:

<scriptCode><![CDATA[
hou.ui.displayMessage("Hello World")
]]>
</scriptCode>

このスクリプトの実行を遅延させるには、以下のように変更します:

<scriptCode><![CDATA[
def runLater():
    hou.ui.displayMessage("Hello World")

import hdefereval
hdefereval.executeDeferred(runLater)
]]>
</scriptCode>

基本

はじめよう

次のステップ

カスタマイズ

導師レベル