On this page |
Overview ¶
You can use the hou.ViewerStateMenu object to build a custom context menu that appears when the user presses while your state is active.
Optionally, you can manage the UI states of the custom context menu with the onMenuPreOpen
handler.
Building and binding the menu ¶
Responding to menu actions ¶
Reading menu settings ¶
Whenever you include checkbox menu items (using hou.ViewerStateMenu.addToggleItem) or radio button items (using hou.ViewerStateMenu.addRadioStrip) in the context menu, Houdini passes the current state of those items in every kwargs
dictionary passed to every event handler method.
This makes it easy to check a menu setting to change how you handle a certain event. In the following example, the onMouseEvent
code checks menu settings to change how it interprets mouse clicks.
from __future__ import print_function # Class implementing the state behavior 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(): # Check if the "Bend" checkbox item in the menu is on if kwargs["bend"]: option = kwargs["bend_parm_option"] # ... else: # ... # Function to generate the state's context menu 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 # Function to generate the state template, which describes the state and any # menus, handles, selectors, etc. bound to it def createViewerStateTemplate(): # Create the template object template = hou.ViewerStateTemplate( "mystate", "My State", hou.sopNodeTypeCategory() ) # Bind the implementation class template.bindFactory(MyState) # Bind handles, selectors, menus... template.bindMenu(create_menu()) return template
Menu hotkeys ¶
Note
The hotkey system in Houdini is in transition and may be replaced in a future version.
-
Houdini uses symbols (such as
h.pane.gview.world.selectall
) to represent hotkey-able actions instead of the key itself (such asshift+p
) so users can edit them using the hotkey editor.When you build the state menu, you can create your own custom hotkey symbol, and assign it to menu items in the state context menu. This will allow users to assign a hotkey to the menu item.
-
The hou.ViewerStateMenu.addActionItem, hou.ViewerStateMenu.addToggleItem, and hou.ViewerStateMenu.addRadioStripItem methods accept Houdini hotkey symbol strings as an optional argument.
-
Hotkey symbols have a dotted prefix that specifies in what context the hotkey is usable (this allows the user to assign to same hotkey to different actions in different contexts).
For a SOP viewer state, the prefix for your hotkeys will be:
h.pane.gview.state.sop.‹state_name›.
where ‹state_name› is the internal name for the state you specify when you create the state template.
-
You will add a name for the specific action to the end of the context to make a hotkey symbol. So, for example, if you want to specify a Delete hotkey, you could use the symbol:
h.pane.gview.state.sop.‹state_name›.delete
import hou # Create hotkey symbols # Need to create the hotkey context first with addContext key_context = "h.pane.gview.state.sop.mystate" hou.hotkeys.addContext( key_context, "mystate Operation", "These keys apply to the mystate operation." ) # Call addCommand with the symbol, a name, and a description 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") # Build the menu menu = hou.ViewerStateMenu('bend_menu', 'Bend') # Call add*Item methods with the hotkey symbol as an extra argument menu.addActionItem("delete", "Delete", del_key) menu.addActionItem("dup", "Duplicate", dup_key) menu.addActionItem("done", "Finish", end_key)