On this page |
概要 ¶
hou.ViewerStateMenuオブジェクトを使用することで、ステートがアクティブ中にユーザがクリックした時に表示される独自のコンテキストメニューを構築することができます。
任意でonMenuPreOpen
ハンドラーを使って、カスタムコンテキストメニューのUIステートを管理することができます。
メニューを構築してバインドする方法 ¶
ステートテンプレートを生成するコードの部分で、hou.ViewerStateMenuオブジェクトを使ってコンテキストメニューを作成してから、 hou.ViewerStateTemplate.bindMenuを使って、そのメニューをステートテンプレートにバインドさせます。
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 onMenuAction(self, kwargs): print("You chose:", kwargs["menu_item"]) # ステートテンプレートを生成する関数。このステートテンプレートは、コンテキストメニューにバインドさせるステート、メニュー、ハンドル、セレクターなどを表現します。 def createViewerStateTemplate(): # テンプレートオブジェクトを作成します。 template = hou.ViewerStateTemplate( "mystate", "My State", hou.sopNodeTypeCategory() ) # 実装したクラスをバインドします。 template.bindFactory(MyState) # コンテキストメニューを作成して、バインドします。 menu = hou.ViewerStateMenu('bend_menu', 'Bend') menu.addActionItem("first", "Action One") menu.addActionItem("second", "Action Two") menu.addActionItem("third", "Action Three") template.bindMenu(menu) return template
メニューを構築する方法は、hou.ViewerStateMenuオブジェクトを参照してください。
メニューのアクションに反応させる方法 ¶
ユーザがメニューを開いてアイテムを選択した時、Houdiniは、あなたのステートのonMenuAction
メソッドをコールします。
このメソッドに渡される辞書には、選択したメニューアイテムのIDを含んだmenu_item
キーが含まれています。
Tip
これは、アクションメニューアイテムが選択されたタイミングのみを追跡し、ユーザの“設定”変更(チェックボックスのオン/オフ、ラジオ選択の変更)は無視します。 他のハンドラーメソッドでその設定項目の現行値を読み込んで、その設定を使用することで、そのステートの挙動に影響を与えることができます。
-
アクションメニューアイテムとトグルアイテムに関しては、その辞書の
menu_item
がアイテムに設定したIDと同じであれば、そのアイテムが選択されています。# メニューを作成する時 menu = hou.ViewerStateMenu('bend_menu', 'Bend') menu.addActionItem("delete", "Delete Current") # ... # メニューハンドラーメソッド内 def onMenuAction(self, kwargs): if kwargs["menu_item"] == "delete": # "delete"アクションを実装したコード # ...
-
以下のようにメニュー内のすべてのアクションに対して面倒な
if
/else
ツリーをコーディングするよりは:def onMenuAction(self, kwargs): menu_item = kwargs["menu_item"] # 以下のコードだと、メニューアイテムがたくさんあると読み書きが面倒です。 if menu_item == "delete": # ... elif menu_item == "dup": # ... elif menu_item == "done": # ...
何かしらのPythonテクニックを使うことで、メニューアイテムIDに基づいてアクションハンドルをメソッドに分けることができます:
# メニューを作成する時。 menu = hou.ViewerStateMenu('bend_menu', 'Bend') menu.addActionItem("delete", "Delete") menu.addActionItem("dup", "Duplicate") menu.addActionItem("done", "Finish") # ... # ステートクラス内 class MyState(object): def __init__(self, state_name, scene_viewer): self.state_name = state_name self.scene_viewer = scene_viewer def onMenuAction(self, kwargs): # 選択したIDと同じ名前のメソッドをコールします # (ただし、メソッド名の頭にはアンダースコアを付けてください) menu_item = kwargs["menu_item"] method = getattr(self, "_" + menu_item) return method(kwargs) def _delete(self, kwargs): # ... def _dup(self, kwargs): # ... def _done(self, kwargs): # ...
-
トグルアイテムに関しては、メニューアイテムのIDをキーとして使用した辞書からトグルの新しいオン/オフの状態を取得することができます。
# メニューを作成する時。 menu = hou.ViewerStateMenu('bend_menu', 'Bend') menu.addToggleItem("showpoints", "Show Points") # ... # メニューハンドラーメソッド内 def onMenuAction(self, kwargs): if kwargs["menu_item"] == "showpoints": # チェックボックスの現在の状態を読み込みます。 showpoints = kwargs["showpoints"]
-
ラジオストリップアイテムに関しては、辞書内の
menu_item
が ラジオストリップ (個々のラジオアイテムではなく)に設定したIDと同じであれば、そのラジオストリップのアイテムが選択されています。ラジオストリップIDをキーとして使用した辞書から新しい現行アイテムインデックスを取得することができます。
# メニューを作成する時。 menu = hou.ViewerStateMenu('bend_menu', 'Bend') menu.addRadioStrip("deform_type", "Deformation Type", "bend") menu.addRadioStripItem("deform_type", "bend", "Bend") menu.addRadioStripItem("deform_type", "squash", "Squash") # ... # メニューハンドラーメソッド内 def onMenuAction(self, kwargs): if kwargs["menu_item"] == "deform_type": # 現在選択されているアイテムのインデックスを取得します。 current = kwargs["deform_type"]
メニュー設定を読み込む方法 ¶
コンテキストメニューにチェックボックスのメニューアイテムを追加(hou.ViewerStateMenu.addToggleItemを使用)またはラジオボタンアイテムを追加(hou.ViewerStateMenu.addRadioStripを使用)すると、
Houdiniは、渡されたすべてのkwargs
辞書内のそれらのアイテムの現在の状態をすべてのイベントハンドラーメソッドに渡します。
これによって、メニュー設定をチェックしてから特定のイベントの挙動を変更するのが簡単になります。
以下のサンプルのonMouseEvent
コードは、メニュー設定をチェックしてから、マウスクリックの挙動を変更しています。
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): ui_event = kwargs["ui_event"] if ui_event.device().isLeftButton(): # メニュー内の"Bend"チェックボックスアイテムが有効になっているかどうかチェックします。 if kwargs["bend"]: option = kwargs["bend_parm_option"] # ... else: # ... # ステートのコンテキストメニューを生成する関数。 def create_menu(): menu = hou.ViewerStateMenu('bend_menu', 'Bend') menu.addToggleItem( 'bend', 'Bend', True ) menu.addSeparator() select_parm_menu = hou.ViewerStateMenu( 'select_parm_menu', 'Select Parm...' ) select_parm_menu.addRadioStrip( 'bend_parm_option', 'Bend Parm', 0 ) select_parm_menu.addRadioStripItem( 'bend_parm_option', 'bend', 'Bend' ) select_parm_menu.addRadioStripItem( 'bend_parm_option', 'twist', 'Twist' ) select_parm_menu.addRadioStripItem( 'bend_parm_option', 'lengthscale', 'Length Scale' ) select_parm_menu.addRadioStripItem( 'bend_parm_option', 'taper', 'Taper' ) select_parm_menu.addRadioStripItem( 'bend_parm_option', 'squish', 'Squish' ) menu.addMenu(select_parm_menu) return menu # ステートテンプレートを生成する関数。このステートテンプレートは、コンテキストメニューにバインドさせるステート、メニュー、ハンドル、セレクターなどを表現します。 def createViewerStateTemplate(): # テンプレートオブジェクトを作成します。 template = hou.ViewerStateTemplate( "mystate", "My State", hou.sopNodeTypeCategory() ) # 実装したクラスをバインドします。 template.bindFactory(MyState) # ハンドル、セレクター、メニューなどをバインドします。 template.bindMenu(create_menu()) return template
メニューホットキー ¶
Note
Houdiniのホットキーシステムは、新しいシステムに移行中なので、将来のバージョンで置換される可能性があります。
-
Houdiniは、キー自体(例えば、
shift+p
)の代わりに記号(例えば、h.pane.gview.world.selectall
)を使用してホットキー可能なアクションを表現していて、ユーザはホットキーエディタを使ってそれらのアクションを編集することができます。ステートメニューを構築する時は、独自のホットキー記号を作成し、それをステートコンテキストメニューのメニューアイテムに割り当てることができます。 これによって、ユーザがホットキーをメニューアイテムに割り当てることができます。
-
hou.ViewerStateMenu.addActionItem, hou.ViewerStateMenu.addToggleItem, hou.ViewerStateMenu.addRadioStripItemのメソッドは、オプションの引数としてHoudiniの ホットキー記号 文字列を受け取ることができます。
-
ホットキー記号は、ドットの接頭辞を付けることで、そのホットキーが利用可能な コンテキスト を指定します(これによって、ユーザは同じホットキーにコンテキストの異なる別のアクションを割り当てることができます)。
SOP Viewer Stateに関しては、そのホットキーの接頭辞は以下のようになります:
h.pane.gview.state.sop.state_name.
state_nameは、ステートテンプレートを作成する時に指定するステートの内部名です。
-
ホットキー記号を作成するには、コンテキストの最後に特定のアクションの名前を追加します。例えば、Deleteホットキーを指定したいのであれば、以下の記号を使用することができます:
h.pane.gview.state.sop.state_name.delete
import hou # ホットキーシンボルを作成します。 # まず最初にaddContextを使ってホットキーコンテキストを作成する必要があります。 key_context = "h.pane.gview.state.sop.mystate" hou.hotkeys.addContext( key_context, "mystate Operation", "These keys apply to the mystate operation." ) # その記号、名前、説明を使ってaddCommandをコールします。 del_key = key_context + ".delete" hou.hotkeys.addCommand(del_key, "Delete", "Delete the current change") dup_key = key_context + ".duplicate" hou.hotkeys.addCommand( dup_key, "Duplicate", "Copies the current change into a new change" ) end_key = key_context + ".finish" hou.hotkeys.addCommand(end_key, "Finish", "Saves the current change") # メニューを構築します。 menu = hou.ViewerStateMenu('bend_menu', 'Bend') # 追加引数としてホットキー記号を使って、addなんちゃらItemメソッドをコールします。 menu.addActionItem("delete", "Delete", del_key) menu.addActionItem("dup", "Duplicate", dup_key) menu.addActionItem("done", "Finish", end_key)