But with some buttons to invoke my custom scripts. Is it possible to do so without directly changing the python code shipped with Houdini?
Is APEX animate state extensible?
413 4 2-
- raincole
- Member
- 714 posts
- Joined: Aug. 2019
- Offline
-
- jonathangardner
- Staff
- 47 posts
- Joined: March 2020
- Offline
Hey! More support will come in the future but you can extend those parameter windows through the use of shelf tools.
Here's an example script that will add a new tab and a button.
Here's an example script that will add a new tab and a button.
import hou import apex from apex.ui.animationhudwidgets import TAB_WIDGET sv = hou.ui.paneTabOfType(hou.paneTabType.SceneViewer) # Send a state command to retrieve the viewer state object kwargs = {} sv.runStateCommand('getState', kwargs) state = kwargs["state"] # Get the Parms window hud_window = state.hud_channel_panel.hud_window # Add the tab TAB_NAME = "scripts" hud_window.addTab(TAB_WIDGET, TAB_NAME, "Scripts") # Create the callback function def helloWorld(): print("Hello World!") # The hud window's class is defined in `$HFS/houdini/python3.13libs/statehud/window.py`. # All the functions that bind parameters to the window start with `bind`. hud_window.bindButton( name = "hello_world", label = "Hello World", callback = helloWorld, tab_widget_name = TAB_WIDGET, tab_name = TAB_NAME, label_width = 70 )
Edited by jonathangardner - March 23, 2026 12:58:35
-
- raincole
- Member
- 714 posts
- Joined: Aug. 2019
- Offline
-
- jonathangardner
- Staff
- 47 posts
- Joined: March 2020
- Offline
The etc.. bit scares me because that is a much bigger question that will need a lot more documentation than we have ready.
There will be a proper guide for extending the state in the future but I can give you a couple of sample functions for the specific examples you gave.
Setting a control's parameters
Updating the channel primitives for a rig
Please note that neither of these examples set add undo blocks. Those need to be custom made.
A few other things you may find useful:
There will be a proper guide for extending the state in the future but I can give you a couple of sample functions for the specific examples you gave.
Setting a control's parameters
import apex from apex.control_2 import getParmsForControls, controlRigPath def setControlTranslation(state, ctrl_path, frame, value=hou.Vector3(0,0,0)): # Get the animation scene from the state scene = state.scene # Get the rig path from the control path then grab the rig's control manager from the scene data # The control path is f"{rig_path}/{control_name}" rig_path = controlRigPath(ctrl_path) rig_control_manager = scene.getData(f"{rig_path}/control_manager") # Get the control mapping ctrl_mapping = rig_control_manager.getControlMapping(ctrl_path) # If the control's 't' parameter is not set, return early. # The control mapping also contains entries for r, s, x, and y if ctrl_mapping.t == "": return False # Get the rig from the scene's data rig = scene.getData(rig_path) if rig is None: return False # Set the new value for the t parameter into the rig's parameter dictionary rig.graph_parms[ctrl_mapping.t] = value # Grab the animation binding for the rig and set a key for the parameter binding = scene.getData(f"{rig_path}/animbinding") binding.setKeysFromDict(scene, frame, pattern=ctrl_mapping.t, force_key=True) # Run the scene callbacks on the viewer state to update the geometries state.runSceneCallbacks() return True
Updating the channel primitives for a rig
import apex from apex.control_2 import getParmsForControls, controlRigPath def updateRigChannelPrims(state, rig_path): # Get the animation scene from the state scene = state.scene # Grab the animation binding for the rig binding = scene.getData(f"{rig_path}/animbinding") # Grab the path in the scene data for the geometry containing the given rigs channels on the current animation layer channels_path = binding.activeLayerGeoPath() # Grab a copy of the channel primitives from the scene channels_geo = scene.getData(channels_path).freeze() # # Make your alterations to the geometry here. # Each primitive on this geometry is a channel primitive matching the parameter names from the rig. # Vector parameters on rig have 3 associated channel primitives, one for each component. # # Set the new channel primitives back into the scene scene.getData(channels_path, channels_geo) # Run the scene callbacks on the viewer state to update the geometries state.runSceneCallbacks() return True
Please note that neither of these examples set add undo blocks. Those need to be custom made.
A few other things you may find useful:
# The path for the latest selected control in the viewer state (the one that shows up in the channels widget). state.primary_control # All of the currently selected controls state.control_paths # Sets the list of selected controls with a pick modifier. state._selectControls(...) # Set keys or pending values for each of the currently selected controls. state.setKeysOrPending(...)
-
- raincole
- Member
- 714 posts
- Joined: Aug. 2019
- Offline
Thank you very much for the answer again! I'll try it out.
Just one more clarifying question: you said
It means that I have to write an undo class that can be passed into
Just one more clarifying question: you said
Please note that neither of these examples set add undo blocks. Those need to be custom made.
It means that I have to write an undo class that can be passed into
hou.undos.add(), right.
Edited by raincole - March 23, 2026 23:08:47
-
- Quick Links

