Add new item to Ordered Menu via Python

   1451   3   1
User Avatar
Member
21 posts
Joined: 1月 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!
Edited by Alexander_Nguyen - 2024年2月17日 09:11:52

Attachments:
Screenshot 2024-02-17 204108.png (70.7 KB)
adas.png (71.7 KB)

User Avatar
Member
218 posts
Joined: 5月 2017
Offline
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")



For spare parameters, you can use node.setParmTemplateGroup(ptg) instead of node.type().definition().setParmTemplateGroup(ptg).
Edited by viklc - 2024年2月17日 14:20:39

Attachments:
hindie_Qn8sE6VCrj.gif (50.0 KB)

User Avatar
Member
21 posts
Joined: 1月 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!

Attachments:
adas.png (55.5 KB)

User Avatar
Member
6 posts
Joined: 9月 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:
hou.phm().readItems(kwargs)
And in your Scripts>Python Module, add something like this:
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))
Then in your parameter interface just get a button and 2 string parms like Viklc has.
Add this callback script to the button:
hou.phm().writeItem(kwargs,kwargs['node'].parm('itemString').evalAsString(),kwargs['node'].parm('labelString').evalAsString())
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:
kwargs['node'].parm('menu').set(kwargs['node'].parm('menu').eval())
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!
  • Quick Links