Add new item to Ordered Menu via Python
1564 3 1- Alexander_Nguyen
- Member
- 21 posts
- Joined: Jan. 2018
- Offline
Hello everyone,
I am looking for a solution to add an item (or in a list of item / an array) to a menu using Python in PythonModule. Although I know this can be done in the menu script, I have personal reasons for needing to do it in PythonModule. Could someone please share a solution for this?
Thank you all in advance!
I am looking for a solution to add an item (or in a list of item / an array) to a menu using Python in PythonModule. Although I know this can be done in the menu script, I have personal reasons for needing to do it in PythonModule. Could someone please share a solution for this?
Thank you all in advance!
Edited by Alexander_Nguyen - Feb. 17, 2024 09:11:52
- viklc
- Member
- 222 posts
- Joined: May 2017
- Offline
Hi,
you can use parmtemplategroup [www.sidefx.com] to update parameter templates.
For spare parameters, you can use node.setParmTemplateGroup(ptg) instead of node.type().definition().setParmTemplateGroup(ptg).
you can use parmtemplategroup [www.sidefx.com] to update parameter templates.
def add_item(**kwargs): node = kwargs["node"] item = node.parm("item") label = node.parm("label") if item.eval() != "" and label.eval() != "": ptg = node.type().definition().parmTemplateGroup() my_menu = ptg.find("my_menu") items = list(my_menu.menuItems()) labels = list(my_menu.menuLabels()) items.append(item.eval()) labels.append(label.eval()) my_menu.setMenuItems(items) my_menu.setMenuLabels(labels) ptg.replace("my_menu", my_menu) node.type().definition().setParmTemplateGroup(ptg) else: print("set item and label")
For spare parameters, you can use node.setParmTemplateGroup(ptg) instead of node.type().definition().setParmTemplateGroup(ptg).
Edited by viklc - Feb. 17, 2024 14:20:39
- Alexander_Nguyen
- Member
- 21 posts
- Joined: Jan. 2018
- Offline
viklc
Hi,
you can use parmtemplategroup [www.sidefx.com] to update parameter templates.def add_item(**kwargs): node = kwargs["node"] item = node.parm("item") label = node.parm("label") if item.eval() != "" and label.eval() != "": ptg = node.type().definition().parmTemplateGroup() my_menu = ptg.find("my_menu") items = list(my_menu.menuItems()) labels = list(my_menu.menuLabels()) items.append(item.eval()) labels.append(label.eval()) my_menu.setMenuItems(items) my_menu.setMenuLabels(labels) ptg.replace("my_menu", my_menu) node.type().definition().setParmTemplateGroup(ptg) else: print("set item and label")Image Not Found
For spare parameters, you can use node.setParmTemplateGroup(ptg) instead of node.type().definition().setParmTemplateGroup(ptg).
Thank you very much, Viklc. That's exactly what I need. It works perfectly!
- FortifiedOatMilk
- Member
- 7 posts
- Joined: Sept. 2016
- Offline
A word to the wise here, using node.type().definition().setParmTemplateGroup(ptg) will update that menu item for each instance of that hda so they will all receive this menu change as it is updating the definition's menu parm template. If that's what you want, then cool and perfect.
If you want it differing per instance of your hda, you can definitely add it as spare parms, but I don't like them living separately from the hda's parameter interface as you would have to manually add them after the node is created or add them to your node with your "OnCreated" script callback. Both leave them open to being tweaked or deleted or forgotten about.
I think a better way of doing all of this while keeping the updates unique to each individual instance of the node would be to use the node's User Data [www.sidefx.com]. For example, use this as your menu script:
And in your Scripts>Python Module, add something like this:
Then in your parameter interface just get a button and 2 string parms like Viklc has.
Add this callback script to the button:
And when you pres your button it should add into that menu. I didn't use this exact code, adapting it from something else I have written so I havent tested this example, but you get the gist.
I did run into the issue when writing an item the menu doesn't automatically update, you kinda have to poke it to make it refresh. I would put a little callback whenever the menu should update where I would go:
Just to force it to set itself to its current value. This solved my issues. A little annoying to have to spread this code into multiple locations, but it's possible and works pretty well, so Im happy.
Hope this helps!
If you want it differing per instance of your hda, you can definitely add it as spare parms, but I don't like them living separately from the hda's parameter interface as you would have to manually add them after the node is created or add them to your node with your "OnCreated" script callback. Both leave them open to being tweaked or deleted or forgotten about.
I think a better way of doing all of this while keeping the updates unique to each individual instance of the node would be to use the node's User Data [www.sidefx.com]. For example, use this as your menu script:
hou.phm().readItems(kwargs)
import json def readItems(kwargs): node = kwargs['node'] info = json.loads(kwargs['node'].userData('Menu1Data')) menu = [] for i in range(len(info['labels'])): menu.append(info['items'][i]) menu.append(info['labels'][i]) return menu def writeItem(kwargs,item,label): info = json.loads(kwargs['node'].userData('Menu1Data')) if info == '': info == {'labels':[],'items':[]} info['labels'].append(str(label)) info['items'].append(str(item)) kwargs['node'].setUserData('Menu1Data',json.dumps(info))
Add this callback script to the button:
hou.phm().writeItem(kwargs,kwargs['node'].parm('itemString').evalAsString(),kwargs['node'].parm('labelString').evalAsString())
I did run into the issue when writing an item the menu doesn't automatically update, you kinda have to poke it to make it refresh. I would put a little callback whenever the menu should update where I would go:
kwargs['node'].parm('menu').set(kwargs['node'].parm('menu').eval())
Hope this helps!
-
- Quick Links