On this page |
Overview
The standard way to allow the user to interactively edit parameters by working in a node’s viewer state is by binding handles to node parameters.
Even though it’s possible to interpret lower-level input device events, handles are likely still the main way you will set up user interaction in your state. Handles can be very powerful on their own, letting you specify a ready-made user interface for a wide variety of parameter setups. You can choose from a large library of different handles.
You bind handles to your state when the state template is created. Currently, you cannot dynamically create or destroy handles – you must specify ahead of time all the handles your state will need. However you can dynamically manipulate handles with hou.Handle.
Static handles
A static handle binding supports a simple 1:1 mapping of handle parameters to node parameters. This is often all you need, since handle parameters such as translate, rotation, scale, length, and so on, often correspond exactly to parameters you have on your node.
For each static handle you want to add to your state, call hou.ViewerStateTemplate.bindHandleStatic() with the name of the handle type, an internal name for the handle (each handle’s name must be unique amongst other handles in the tool), and a list of ("node_parm_name", "handle_parm_name")
tuples mapping node parameters to handle parameters.
You can run the example below in the Python Source Editor for a quick test:
import hou class PythonMeasureState(): def __init__(self, state_name, scene_viewer): self.state_name = state_name self.scene_viewer = scene_viewer template = hou.ViewerStateTemplate( "pythonmeasure", "Python Measure", hou.sopNodeTypeCategory() ) template.bindFactory(PythonMeasureState) # Assume the asset this state is for has two translate # parameters, "start" and "end" template.bindHandleStatic( "xform", "start_handle", [("startx", "tx"), ("starty", "ty"), ("startz", "tz")] ) template.bindHandleStatic( "xform", "end_handle", [("endx", "tx"), ("endy", "ty"), ("endz", "tz")] ) hou.ui.registerViewerState(template)
Dynamic handles
Dynamic handle bindings let you decide in a callback function how changes to a handle affect parameters on the node, or how changes to parameters on the node affect handle parameters.
For each dynamic handle you want to add to your state, call hou.ViewerStateTemplate.bindHandle() with the name of the handle type, and an internal name for the handle (each handle’s name must be unique amongst other handles in the tool).
Note
hou.ViewerStateTemplate.bindHandle() takes a cache_previous_parms
boolean argument.
If you pass cache_previous_parms=True
, Houdini keeps track of the handle values and in the handle callback gives you both the previous and the new handle values. This can be useful if you want to track deltas, for example to see how fast the user is moving the handle.
If you pass False
(the default), Houdini does not pass the previous values to the handle callback.
You can run the example below in the Python Source Editor for a quick test:
from __future__ import print_function import hou class PythonTwistState(): def __init__(self, state_name, scene_viewer): self.state_name = state_name self.scene_viewer = scene_viewer def onHandleToState(self, kwargs): # Called when the user manipulates a handle handle_name = kwargs["handle"] parms = kwargs["parms"] prev_parms = kwargs["prev_parms"] print("User edited handle:", handle_name) for parm_name in kwargs["mod_parms"]: old_value = prev_parms[parm_name] new_value = parms[parm_name] print("%s was: %s now: %s" % (parm_name, old_value, new_value)) def onStateToHandle(self, kwargs): # Called when the user changes parameter(s), so you can update # dynamic handles if necessary parms = kwargs["parms"] print("Parameters are now:", parms) for p in parms: print(p) template = hou.ViewerStateTemplate( "pythontwist", "Python Twist", hou.sopNodeTypeCategory() ) template.bindFactory(PythonTwistState) template.bindHandle("xform", "twist_handle", cache_previous_parms=True) hou.ui.registerViewerState(template)
The dictionary passed to the dynamic handle event methods contains the following standard items:
node
Contains a hou.Node instance representing the node being operated on by the current state.
Menu items
The dictionary also contains the current values associated with menu items, using the menu item name as the key.
state_parms
Contains the names representing the state parameters bound to the current state. This dictionary is used for modifying the parameter states. See the details here.
state_flags
A dictionary containing various flags associated to the state. State flags can be set by all state handlers via their kwargs
argument.
Flag |
Notes |
---|---|
|
Controls whether a mouse drag event (with the When If mouse drag events are not required by your state, consider setting class MyState(object): def __init__(self, state_name, scene_viewer): self.state_name = state_name self.scene_viewer = scene_viewer onEnter( self, kwargs): kwargs['state_flags']['mouse_drag'] = False ... |
|
The flag triggers a redraw of the viewport on a mouse move or mouse wheel event when it’s set to By default the viewport always redraw. To reduce performance issues with large scenes, class MyState(object): def __init__(self, state_name, scene_viewer): self.state_name = state_name self.scene_viewer = scene_viewer onMouseEvent( self, kwargs): kwargs['state_flags']['redraw'] = False if __some_redraw_test__: kwargs['state_flags']['redraw'] = True ... |
interrupt_state
The name of the state that is interrupting the python state when a volatile state is activated, or an empty string.
onHandleToState
This lets you update node parameters (and/or the state/display) when a handle changes.
The dictionary passed to this method contains the following extra items:
handle
The string ID of the handle.
parms
A dictionary containing the new handle parameter values.
mod_parms
A list of of the names of parameters that changed.
prev_parms
This key is only present if you passed cache_previous_parms=True
to the hou.ViewerStateTemplate.bindHandle() method.
This is a dictionary containing the previous handle parameter values. This can be useful for computing deltas.
ui_event
A hou.UIEvent object to access the handle status. For instance, you can use the hou.uiEventReason value returned by hou.UIEvent.reason() to know if the user has started or finished dragging the handle.
These hou.uiEventReason values have different meanings for onHandleToState
:
-
uiEventReason.Active
: User is dragging the handle. -
uiEventReason.Changed
: User has finished dragging the handle.prev_parms
should contain the most recent handle values at this point. -
uiEventReason.Start
: User has started dragging the handle. -
uiEventReason.Picked
: Handle menu action, hotkey or mouse click. For instance, a Picked value is generated when clicking on aHUD
slider.
onStateToHandle
This method is called separately for each dynamic handle bound to your state whenever a parameter on the node changes. It lets you update handle parameters to match changed node parameters.
The dictionary passed to this method contains the following extra items:
handle
The name of the handle.
parms
A dictionary mapping the handle’s parameter names to values. You can change the values in this dictionary to edit the handle parameters.
In this method you would read parameters from the node’s parameters, and do whatever dynamic updates of the handle’s parameters in kwargs["parms"]
you want:
def onStateToHandle(self, kwargs): node = kwargs["node"] handle_parms = kwargs["parms"] if kwargs["handle"] == "my_angle": node_tx = node.parm("tx").evalAsFloat() handle_parms["tx"] = node_tx * 2
Extra notifications
Houdini provides special callbacks to notify the state when the user has started or ended the manipulation of dynamic handles.
onBeginHandleToState
is called right
before the onHandleToState
callback. onBeginHandleToState
could be used, for example, to
open an undo block and perform undoable operations while the
user manipulate the handle.
onEndHandleToState
is called after onHandleToState
has been called. The callback can then be used to close the undo block
that may have been opened in onBeginHandleToState
.
Handle types
Name |
Description |
Parameters |
---|---|---|
|
A position and rotation handle. |
|
|
Bounding Box Vector |
|
|
Bounding Box |
|
|
Bounding Rectangle |
|
|
Bounder Bounding Box |
|
|
Circle Transform |
|
|
Clay Translate |
|
|
Curve Point Options |
|
|
Distance |
|
|
Domain |
|
|
Edit |
|
|
Extrude |
|
|
Extrude v2 |
|
|
Vector with Fallback |
|
|
HUD Int Slider |
|
|
HUD Slider |
|
|
Isoparm Segment |
|
|
Isoparm Segment |
|
|
Mouse Wheel Bump |
|
|
Mouse Wheel Radius |
|
|
Paste Range |
|
|
Peak |
|
|
Pill |
|
|
Pivot |
|
|
Project |
|
|
Soft Transformer |
|
|
Sphere Transformer |
|
|
Translate |
|
|
Torus Transformer |
|
|
Tube Transformer |
|
|
U Isoparm |
|
|
UV Edit Manipulator |
|
|
Texture Transformer |
|
|
UV Point |
|
|
UV Project Manipulator |
|
|
UV Range Manipulator |
|
|
UV Transform Manipulator |
|
|
UV Unwrap Manipulator |
|
|
Vector |
|
|
V Isoparm |
|
|
Transformer |
|
Handle settings
Settings are attributes for changing the handle behavior.
See also:
HUD integer slider settings
hudharbourname('name')
Assigns the slider to a group. Sliders in the same group will dock together.
hudharbourx(int)
Slider group X position.
hudharboury(int)
Slider group Y position.
hudnameside(int)
Label position: top(1), left(2), right(3), bottom(4)
hudrangehigh(int)
Slider range high value.
hudrangelow(int)
Slider range low value.
hudlockhigh(int)
High value limits.
hudlocklow(int)
Low value limits.
hudvalueside(int)
Value position: top(1), left(2), right(3), bottom(4)
hudx(int)
X position in the viewer pane.
hudy(int)
Y position in the viewer pane.
hudw(int)
Width
hudh(int)
Height
HUD slider settings
hudharbourname('name')
Assigns the slider to a group. Sliders in the same group will dock together.
hudharbourx(int)
Slider group X position.
hudharboury(int)
Slider group Y position.
hudnameside(int)
Label position: top(1), left(2), right(3), bottom(4)
hudrangehigh(float)
Slider range high value.
hudrangelow(float)
Slider range low value.
hudlockhigh(float)
High value limits.
hudlocklow(float)
Low value limits.
hudvalueside(int)
Value position: top(1), left(2), right(3), bottom(4)
hudx(int)
X position in the viewer pane.
hudy(int)
Y position in the viewer pane.
hudw(int)
Width
hudh(int)
Height
xform settings
translate(int)
Enable (1) or disable (0) the xform
translate mode.
scale(int)
Enable (1) or disable (0) the xform
scale mode.
rotate(int)
Enable (1) or disable (0) the xform
rotate mode.
boundingbox settings
translate(int)
Enable (1) or disable (0) the boundingbox
translate mode.
rotate(int)
Enable (1) or disable (0) the boundingbox
rotate mode.