Copy parameter from one node to another using Python

   637   4   2
User Avatar
Member
12 posts
Joined: 1月 2019
Offline
Hello forum,

I am trying to copy parameter from one node to another using Python.

If you do it manually, you would have to go to:
edit parameter interface > create parameter > from node > then drag and drop the parm.



For some parm I can manually create the parm then connect it to the original parm.
But I would lost the functionality of some parm like the ability to select group like this:



If anyone can share how they would approach this, point me to resource or pages on help I would be very appreciated.

Thank you!

Attachments:
screenshot.png (329.8 KB)
functionality.png (18.0 KB)

User Avatar
Member
222 posts
Joined: 5月 2017
Offline
Hi there are a many topics on this, search for parmTemplateGroup/parmTemplate.

Here brief overview:

Each hda can holds multiple parmTemplateGroups [www.sidefx.com], but a single one can be represented as an actual parameter interface. A template group can contain different types of parmTemplates [www.sidefx.com], such as floatParmTemplate [www.sidefx.com], int, string and so on. They all have their own unique methods, but also sharing common methods like name, label, type. A FolderParmTemplate [www.sidefx.com] acts similar to a parmTemplateGroup, which again can contain a variety of parm templates. So it is a tree structure like it is represented in the type properties parameter interface - a nested tuple in python.

To operate on this you need a reference of a parmTemplateGroup, for example:
node = hou.node('/obj/geo1/my_hda')
ptg  = node.type().definition().parmTemplateGroup()
type().definition() refers to the node type parmTemplateGroup. You can also use,
ptg_spare = node.parmTemplateGroup()
to get a reference of the spare parmTemplateGroup. Which has a session/hip file life time as an instance of a node type, they are not stored in the hda/otl it self. So when ever you like to operate on the hda you have to refer to the type definition of the hda.

Here an example to change the label of an existing parameter:
# get a reference to parmTemplate
new_pt = ptg.find('my_parm_name')
# set label
new_pt.setLabel('new_label')
# update the parm group by replacing the new parm template with the existing
ptg.replace('my_parm_name', new_pt)
# apply and store changes to the parm group
node.type().definition().setParmTemplateGroup(ptg)
Also note that each parmTemplate must have a unique name. If you try to store a template with the same name houdini will act by adding indices or even avoid the operation.

For handle you task you need two node/parm group references, the source and target:
node_source = hou.node('/obj/geo1/source_hda')
node_target = hou.node('/obj/geo1/target_hda')

ptg_source = node_source.type().definition().parmTemplateGroup()
ptg_target =  node_target.type().definition().parmTemplateGroup()

# get parm template reference from source
pt = ptg_source.find('my_parm')

# append to target ptg
ptg_target.apped(pt)
# apply and store changes to the target parm group
node_target.type().definition().setParmTemplateGroup(ptg_target)

There are variety of methods for example to add a template before or after to a parm template.

I would also recommend working with dummies for the time being, as this can lead to irreversible results.
Edited by viklc - 2024年11月14日 07:08:40
User Avatar
Member
12 posts
Joined: 1月 2019
Offline
Hello viklc,

Thank you for your detailed reply!
I could be wrong, but your answer don't really solve my problem.
I am not working with HDA in this case, but from my understanding the methods are interchangable.

I can get a copy of a parm using ParmTemplate, but many of it's settings are different from the original parm.
Directly plugging it into the new parmTemplateGroup result in a parm that behaves slightly differently from the original.

What I ended up doing for now is to do the copy the parm manually (like in the pic I attached earlier), get the copied parm as parmTuple, get the settings through the templateAsData() command, save the setting somewhere and delete said parm.

Now I can somewhat proceed to recreate the parm that behaves like the original.

I can get a copy of the parm using parmTemplate(), from then I set the parmTemplate with the setting I saved earlier, e.g.:
setTags, setScriptCallbackLanguage, setMenuType, setItemGeneratorScript, setItemGeneratorScriptLanguage etc.

Now, when I plug the parmTemplate into a new parmTemplateGroup, the parm behaves like the original.

It works, but it feels like a very roundabout way of approaching this.
User Avatar
Member
222 posts
Joined: 5月 2017
Offline
Simply making a copy of the wrangles group/grouptype parms won't work, the functionality lies internally. Some hscript you can take from, but then there is channel link which refer to a vop and then you get nothing out of using python. You can copy the group parameters from the attribnoise sop, but there is no additional menu to select the group type. So, you example above works because you copy the parm template and creating a reference to the wrangle, this trigger the intern function.

You can use this to reproduce it python:


node = hou.node('node_path')
# ref to wrangle inside you hda
wrangle = node.node('attribwrangle1/')
wrangle_ptg = wrangle.parmTemplateGroup()
# parm templates
group = wrangle_ptg.find('group')
grouptype = wrangle_ptg.find('grouptype')
# append to parent hda
ptg = node.type().definition().parmTemplateGroup()
ptg.append(group)
ptg.append(grouptype)
node.type().definition().setParmTemplateGroup(ptg)
# set ref to wrangle
wrangle.parm('group').setExpression('chs("../group")')
wrangle.parm('grouptype').setExpression('ch("../grouptype")')
Edited by viklc - 2024年11月15日 09:28:46
User Avatar
Member
222 posts
Joined: 5月 2017
Offline
My script above doesn't work messed up something.

If you set a reference to the group parm template of the wrangle with python then two tags are missing (import_token, import_source) which seems to be important to set the menu hscript properly so if it is done manually then the opmenu command refer to the wrangle and the group parm, doing it with python then a reference to the attribtvop bindgroup appears - basically just a copy from the wrangle.

I tried to set the missing tags, but they are gone by updating the parm group.

But you can fix the menu script by using setItemGeneratorScript:
node = kwargs['node']
node_def = node.type().definition()
wrangle_name = 'attribwrangle1'
wrangle = node.node(wrangle_name + '/')
wrangle_pt = wrangle.parm('group').parmTemplate()
wrangle_pt.setItemGeneratorScript('opmenu -l -a ' +  wrangle_name + ' group' )

ptg = node_def.parmTemplateGroup()
ptg.append(wrangle_pt)
node_def.setParmTemplateGroup(ptg)

wrangle.parm('group').setExpression('chs("../group")'))
Should work without using templateAsData().
Edited by viklc - 2024年11月15日 09:28:38
  • Quick Links