On this page |
Overview
Houdini lets you customize several menus, including the main menus, using XML configuration files.
-
Houdini loads the default menu files from the Houdini installation (
$HFS/houdini
), then any files with the same names from$HOUDINI_MENU_PATH
. (The default path is$HOME/houdiniX.x/
and the current working directory.) This allows per-user menu customization. -
By default
$HOUDINI_MENU_PATH
is the same as$HOUDINI_PATH
. -
Each definition file can add, rearrange, and remove menu items from files loaded earlier in the path.
-
Menus and menu items are identified by their
id
attribute. It is not an error to create a menu or item without anid
attribute, but for various reasons every menu/item should have one. -
For action and toggle menu items in the main menu files, the
id
value is also a hotkey symbol, allowing you to assign a hotkey to the item in the hotkey editor.Hotkey symbols must start with
h.
, so if an item’sid
doesn’t start withh.
already, Houdini creates its hotkey symbol by prefixing theid
withh.
. -
Most of the menu items in the default files shipped with Houdini trigger built-in functionality based on the hotkey. However, action items can also trigger Python scripts. Additionally, you can create alias menu items. See the
<scriptItem>
and<actionId>
tags below. -
You can customize the context menu for nodes in the network editor using an
$HOUDINI_MENU_PATH/OPmenu.xml
.
Configuration files
The configuration files are in an XML format, using a schema defined in $HFS/houdini/menu.xsd
.
Main menu files
Context menu files
VOP FX menu file
Menu items
Reorganizing menus
Toggle and radio items
The <scriptToggleItem>
, <scriptMenuStripRadio>
, and <scriptRadioItem>
tags let you create custom checkmark and radio menu items. The "states" of the items are stored in Houdini global variables.
Note
As of this writing, there is no way to get and set Houdini global variables in the optional scripts, so you will have to use hou.hscript()
to access the HScript echo and set commands.
# Set the value of a global hou.hscript("set -g MYGLOBAL = 0") # Get the value of a global value, err = hou.hscript("echo $MYGLOBAL")
Checkbox (toggle) items
You can create an item that is on or off using <scriptToggleItems>
. The <variableName>
sub-element specifies the name of the global variable controlled by this menu item. By default, choosing this menu item will change the value of the global variable between "0"
and "1"
.
<scriptToggleItem id="myitem"> <label>The text that appears in the menu</label> <variableName>MY_GLOBAL_VARIABLE</variableName> </scriptToggleItem>
You can optionally specify a Python script inside the <scriptCode>
sub-element or using a <scriptPath>
reference. The script runs when the user chooses the item or the value of the global variable changes.
<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>
Radio (mutually exclusive) items
The code should set the variable, but it does not have to. The radio items that don’t specify explicit script are equivalent to the following Python script:
The code, however, can do whatever it wants. Still, it is a good idea to at least call hou.hscript('varchange VAR') to restore the radio item index, otherwise the menu may get out of sync, if the variable is not set to the value corresponding to the clicked item.
You can use <scriptMenuStripRadio>
in place of a regular menu item, to create a list of mutually exclusive items. The <variableName>
sub-element specifies the name of the global variable controlled by this menu item. The <scriptMenuStripRadio>
element should contain one or more <scriptRadioItem>
elements which represent the items in the list. By default, choosing one of the menu item in the list will change the value of the global variable to the value inside the menu item’s <variableValue>
sub-element.
<scriptMenuStripRadio> <variableName>MY_GLOBAL_VARIABLE</variableName> <scriptRadioItem id="my_item_1"> <label>First item</label> <variableValue>value1</variableValue> </scriptRadioItem> ... </scriptMenuStripRadio>
You can optionally specify a Python script inside the <scriptCode>
sub-element or using a <scriptPath>
reference. The script runs when the user chooses the item or the value of the global variable changes to the value in that item’s <variableValue>
sub-element.
The default action is equivalent to the script:
hou.hscript('set -g VAR = val') hou.hscript('varchange VAR')`
Technically, the script can do anything and is not required to use these commands, but to conform to user expectations about how radio menus work it should at some point set the global variable and then call varchange to update the menu 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: # call varchange anyway to restore the radio strip UI to old radio index hou.hscript("varchange MYVAR_RADIO")]]> </scriptCode> </scriptRadioItem> </scriptMenuStripRadio> </subMenu> </subMenu>
Deferring execution of <scriptCode>
There are times when it is best to defer the execution of the <scriptCode>
script
instead of immediately running the script when the menu item is clicked.
For example, consider when the script contains code that pops up a message dialog or prompts for a selection from a choice dialog. In either case the script indefinitely runs until the dialog is closed. Immediately running such a script is undesirable as the menu does not fully close until the script completes. This can sometimes cause the menu to be visible and frozen while the dialog is open. It can also cause a crash in Houdini since opening a dialog can internally change the order of processed UI events.
To defer execution of the <scriptCode>
script so that it runs after the menu
has fully closed use the hdefereval
module.
For example, suppose you had this script:
<scriptCode><![CDATA[ hou.ui.displayMessage("Hello World") ]]> </scriptCode>
Then to defer execution change the script to this:
<scriptCode><![CDATA[ def runLater(): hou.ui.displayMessage("Hello World") import hdefereval hdefereval.executeDeferred(runLater) ]]> </scriptCode>