Jump to content

Python Callback and Multiparm


Zhaie

Recommended Posts

Hi Houdini People !
 

i have a question :

I have a Multiparm who's updating number by Python Script (Basically : It get the input value of an attribute )

Once my Multiparm is set to the right number , i want to add some scipting on the hda. The problem is, if i update manually the number of multiparm instance, the callback is called ? But with my python script nothing happend.

Any idear ? 

to be clear in the step i used : 

  1.  Plug a node with an attribute in my HDA (  the node is a connectivity who give me attribute pieces "name" )
  2. On my HDA, the multiparm number is updated with python (it give me 3 different attribute pieces ( Pieces_0 , Pieces_1, Pieces_2)
  3. Now i call a function with callback on the multiparm to updates dymanically values

nothing happend

if  i create a new multiparm with no Python on the number of instances

  1. i plug a node
  2. i update the values to 3
  3. the callback is working fine

any idears ? 

  1. 20200407_Houdini_Multiparm_Bug.thumb.gif.2b428468a51127d1b0209f3e9b39d69a.gif
Link to comment
Share on other sites

Hey Zhaie ! Or bonjour, as you're in Montréal :)

So, I'm having a hard time understanding your intentions

First and foremost, you want to update a multiparm to be the same number as the number of pieces in your input geometry. Right ?
As I understand it, you got this part working.

And now, you want to fill the individual parameters inside of the multiparm ?
Like, naming the Piece Name automatically ?

I'm not sure about the two multiparms, one has a python script, the other doesn't
Do you want to update one of them, or both of them dynamically ?

 

What I would do is to have a wrangle in the node to gather the info you need in a clean fashion. So instead of passing on the input geo, I'd do something like get the uniquevals of the name attribute, and create a point for each of them with said name. So I'd have a resulting X amount of points, X being the number of unique names in the input.

Then, I'd place a Python node, with the first input in the main execution chain, and the second input from that wrangle. I do that instead of On Input Changed on the HDA itself, since that doesn't take into account when the input geometry changes.
I'd handle the UI updating stuff in there, gathering the number of points, setting the multiparameter to that, and then for each points, get the name attribute value, and set the individual parameter values.

Kinda like this :
updateUIFromInput.thumb.gif.38fe2911d76a90b956646336e60aa5dd.gif

I'm very not sure if that's what you need, but hopefully that helps !

In the first part, you can see that with the On Input Changed, it works when changing the input node, but when modifying an upstream node, it is not updated. That's the only reason I choose a python node inside the HDA to update the UI over using the On Input Changed.

And do keep in mind that if the user can change any of the parameter updated by the script, it'll get overwritten by the script. I see that you have disabled the parameters for the name, that's a good solution.
But again, if you have some non-script updating parm that the user needs to edit himself, and somehow the input ends up with 1 piece, then all of the custom-entered data will be wiped away.
You might want an "Update UI" button to workaround that, if that is a potential issue for you.

 

Here's the Wrangle script (plug geometry in the second input, and Run Over Detail)

string names[] = uniquevals(1, "point", "name");

for(int i=0; i<len(names); i++){
    int pt = addpoint(0, 0);
    setpointattrib(0, "name", pt, names[i]);
}

Here's the Python Script (plug wrangle in second input)

node = hou.pwd().parent()
geo = hou.pwd().inputs()[1].geometry()

# Set multiparameter number
count = len(geo.points())
node.parm("numberOfPieces").set(count)

# For each points, get the name, then set the pieceName parameter
for i, point in enumerate(geo.points()):
    name = point.attribValue("name")
    node.parm("pieceName" + str(i+1)).set(name)

image.png.53dc7de7233f74b2026988079d969c4f.png

Edited by Alain2131
Link to comment
Share on other sites

EDIT : I you're in QUEBEC ! Bonjour ! That's good to see other Houdini user in Quebec <3

Thanks a Lot Alain ! i realy appreciate that you take lot's of time to explain !

Ok sorry if it wasnt clear my goal is to create collisions for Unreal on pieces:
- Create a multiparm where X is the number of pieces.
- Let the user choose this type of collision ( Box / Sphere / Convex...)
--- for that when i generate the multiparm number i need to create a subnet with parameters / nodes / inside of it. Thes node gonna have parameter linked to the multiparm pieces.

-----> To create thes subnet/parm i need to generate them dynamically in my HDA Python. so i need the number to callback this script. ( that's not working :( )  

I was doing the same thing as you at the beginning (Creating a Python node inside the HDA and use nuniqueval to make a list + get hre number of pieces ) But a friend of mine told me that it's a bit dangerous to Set Ui once you're in the node, that it could create some kind of a loop.
That's why i'm trying to find the pieces number with a python script who's chek on the previous node :) 
 

the issue i got on my locgic was : if the number update in a parameter python script it dont callback the script on your HDA. But when you do it maanually it does ><
The second multiparm was just to test that :) 

I gues you're right i'm gonna need a refesh button. that's sad :( 

Also, you're right, if i update a node before, my pieces number isn't always updated...damn ><

 

Edited by Zhaie
Link to comment
Share on other sites

I do agree that a Python node isn't super ideal.
Another issue with this is that if you have an animation, it'll be executed at each frame, which you definitely don't want.

I think you'll have to have a button to kind of "stash" the input. This will make your life easier, and potentially the user's as well. (I think you should literally stash the input, this might save you some headache when referencing the input geometry inside of your subnet)
That way, you don't have to worry about having to automatically detect a change, and this gives the user more control.
I don't think that's sad, I think it's simply better that way. A few of SideFX's tools are made that way.
Look at the Attribute Paint node. If the input changes, the paint becomes all mangled, until the user manually presses on "Recache Strokes".

What I'd do is make a button that calls a script on the HDA (instead of a OnInputChanged it'd be a simple Python Script). That function would handle the creation of the UI stuff, as well as the creation of the subnets inside the HDA, and making sure that the UI stuff is referenced in the relevant places in the subnet.

So instead of trying to make the tool detect a change automatically, changing the UI, and then when the UI changes, trying to call another script to then create the subnet, which has scripts all over the place, all your scripts would be in one location.

I'm guessing that you want to do that dynamic callback to make it automatic if the user adds or removes items from the multiparameter list ?
My opinion is that the user shouldn't even be able to do that, since this should always be relative to the number of pieces. What if there are 10 pieces, the multiparameter has them all, but the user adds one ? The piece name can't be any of them, all the pieces are accounted for. And the user can't even change the piece name.
(I would even go as far as to not make it a multiparameter, and straight up automatically add spare parameters. And if the user doesn't want a piece, I'd add a tickbox with a name like "Ignore Piece")
Just my two cents.

I know I dodged the "trigger callback script when modifying multiparameter by script" question. I don't know about that, I just think you can go about without doing it.
Sorry I couldn't be of help for that (which was the question in and of itself).
If you still want to stick with the multiparameter and automatic creation along with callback, then yeah, a button to force the update should work.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...