haki Posted April 9, 2020 Share Posted April 9, 2020 (edited) A python newbie here... I'm working on a small script to make a certain workflow of swapping operator paths for filters a bit less clunky in the context of rendering (with Renderman in this case). The idea: 1. Click a button (New Filter) to create a new filter node in the shop context - I got this working. 2. That will add a multiparm toggle+operator path. Set the operator path to the newly created filter. - Also done and working. 3. Use toggles to set (and swap) Display Filter operator path parm on the ROP node (ris1) - Far from working I suspect this will have to do with ParmTupleChanged events? and here things become very fuzzy... how do I match the toggle to the operator path to evaluate the correct parm (Filter 1/2/3...)? From a tupple? I guess I need to def a function for that. But how do I prevent more tan 1 toggle be on at a time... I'm totally stuck. I hope that makes sence and if anyone could point me in the right direction, that'd be awesome! Edited April 21, 2020 by haki Quote Link to comment Share on other sites More sharing options...
Stalkerx777 Posted April 9, 2020 Share Posted April 9, 2020 Instead of having a checkbox for each filter, you could have a menu like parameter, with a script that lists your multiparm value, thus you will avoid messing around with checkboxes and which of them wins. As to the rest of your question, there are 2 common models of scripting in Houdini. I call them pull and push models. In a push model, you hook a callback on a parameter and that callback is pushing values to other Houdini nodes. The main shortcoming of this model is not being able to set parameter values in locked assets. It also makes it hard to debug complex setups(especially not yours) when you have no idea where a parameter value came from. In the pull model, you hook an expression on the parameter and it does the job. No problems in locked assets and no need to guess the origin of the value in it. The downside is that users won't be able to edit these parameters obviously. In your case, if the relationship between your CONTROLS and ris1 nodes is deterministic(e.g they know about each other) choose either to push to ris1 from a callback on a menu parameter on the CONTROLS or pull the value from an expression on ris1. Whatever fits better. Good luck. Quote Link to comment Share on other sites More sharing options...
haki Posted April 11, 2020 Author Share Posted April 11, 2020 (edited) Ok, I think the push and pull terms are starting to make me see the bigger pucture. Thanks!! I'd say the node ralationship is non deterministic as the ris1 has no clue about my CONTROLS at all. And it never will as its HDA is not to be messed with. (Btw I've no intention to package this little null (CONTROLS) into an HDA and I've just realized the Null ROP is in fact an HDA itself.) As for the menu like parm, i hope i'm not getting this totally wrong: 1. Click a button to create a node 2. Set above node's op path in the multiparm string field (at this point i'm starting to think I may even get away without multiparm if I list the children of shop/risnet and get the filters directly into the menu parm (3)) 3. Populate menu parameter with new path (or rather, all paths) from multiparm and push selected to ris1 (4.) Alright. Scripting time. Edited April 21, 2020 by haki Quote Link to comment Share on other sites More sharing options...
haki Posted April 12, 2020 Author Share Posted April 12, 2020 (edited) Ok, getting there: (A) and (B), still making my mind between the two. Lists of strings: (A) node = kwargs["node"] multi_parm = node.parm("filters") instances = multi_parm.multiParmInstances() menu = [] for p in range(len(instances)): token = str(p); value = "Filter {}".format(p+1) menu.append(token) menu.append(value) return menu returns: ['0', 'Filter 1', '1', 'Filter 2', '2', 'Filter 3', '3', 'Filter 4', '4', 'Filter 5'] There's something a bit confusing here: What would I be calling for to get the multiparm instance corresponding to the currently selected token? Or is that just my flawed logic: Current token -> Corresponding multiparm instance - > Push string to other node (B) menu = [] token = -1 for filter in instances: token += 1 value = filter.eval() menu.append(str(token)) menu.append(value) return menu returns: ['0', '/shop/risnet1/pxrgradedisplayfilter27', '1', '/shop/risnet1/pxrgradedisplayfilter28', '2', '/shop/risnet1/pxrgradedisplayfilter29', '3', '/shop/risnet1/pxrgradedisplayfilter30', '4', '/shop/risnet1/pxrgradedisplayfilter31'] This one seems a bit less confusing. After all the string value I need to push to the other node is right there...i can see it. And then the documentation: def get_selected_token(parm): # Read which item is currently selected selected = parm.eval() # Get the list of menu tokens from the parameter template tokens = parm.parmTemplate().menuItems() # Return the token corresponding to the selected item return tokens[selected] Which gets me: 'tuple index out of range' for the dropdown menu parm. (selected = parm.eval() returns the correct token, indeed) Perplexing... [Edit] I think I got it: evaluate the button strip/dropdown menu and use the token as the index for .multiParmInstances() evaluated as a string. If there were say, not 1 but 2 "Add Filter" buttons, is there a way, inside the Script New Filter, to know which button was clicked? Pushin on. It seems there may be some benefits of turning this into a digital asset and using a python module... I might be tottally ignorant here, but it seems to me functions from a python module make more sense.. Edited April 12, 2020 by haki 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.