Hi all,
I am trying to run a python function on a spare button parameter, but in troubleshooting why it wouldn't work, it seems the function is running twice. Is this expected? If so, how can I work around it? Is there a way to distinguish between button press and button release?
Here is what I've done:
- create spare button parameter
- set a key on the button
- right click > Expression > Change Language to Python
- right click > Expression > Edit Expression
- make the expression: print ‘hello’
- click the button
And I get the following in the Python Shell from a single button press:
Thanks for the help,
Python Expression on Button Running Twice
9622 14 3- seando
- Member
- 6 posts
- Joined: July 2015
- Offline
- Enivob
- Member
- 2537 posts
- Joined: June 2008
- Offline
- seando
- Member
- 6 posts
- Joined: July 2015
- Offline
Enivob
Instead of using the expression try using the callback script instead. Remove the Key and then under the Edit parameter interface put your code in the Callback Script field.
If my final code was a one-liner like this, I would totally do that. But I have a 60 line function with loops. I know that semicolons work as line breaks in the Callback script field, but I couldn't get them to work with my loops. I also have considered doing an HDA and shoving the function in the Script tab, but I am trying to keep this as a light preset that is easier to share out.
So my preference is to keep this a Python Expression if possible.
- Enivob
- Member
- 2537 posts
- Joined: June 2008
- Offline
I think there is a way to use the callback to point to a python def which can have as many lines as you want.
Check out this thread on odforum.
http://forums.odforce.net/topic/21441-run-python-when-button-is-clicked-callback-script/#entry128367 [forums.odforce.net]
Check out this thread on odforum.
http://forums.odforce.net/topic/21441-run-python-when-button-is-clicked-callback-script/#entry128367 [forums.odforce.net]
Using Houdini Indie 20.0
Windows 11 64GB Ryzen 16 core.
nVidia 3050RTX 8BG RAM.
Windows 11 64GB Ryzen 16 core.
nVidia 3050RTX 8BG RAM.
- seando
- Member
- 6 posts
- Joined: July 2015
- Offline
Thanks for the tip.
While I certainly could make a function in my scene's Python Source Editor and call from the button's callback via something like:
hou.session.foo()
That would require additional setup for every shot. This is for something I use on all my jobs so I'd really like this to be a preset that can just be selected from the gear menu. And I don't want to depend on requiring my code to be in every scene I or anyone else opens for the preset to be usable.
Is this simply a bug where a Python expression on a button runs twice? Or am I building my Python expression incorrectly?
I'm using 14.0.361 if that matters.
While I certainly could make a function in my scene's Python Source Editor and call from the button's callback via something like:
hou.session.foo()
That would require additional setup for every shot. This is for something I use on all my jobs so I'd really like this to be a preset that can just be selected from the gear menu. And I don't want to depend on requiring my code to be in every scene I or anyone else opens for the preset to be usable.
Is this simply a bug where a Python expression on a button runs twice? Or am I building my Python expression incorrectly?
I'm using 14.0.361 if that matters.
- Enivob
- Member
- 2537 posts
- Joined: June 2008
- Offline
I am thinking it might be because you have a keyframe on the button, right? So you click the button and it runs then the scene has to update and the key framed button fires off another run. Have you tried not keying the button?
Using Houdini Indie 20.0
Windows 11 64GB Ryzen 16 core.
nVidia 3050RTX 8BG RAM.
Windows 11 64GB Ryzen 16 core.
nVidia 3050RTX 8BG RAM.
- seando
- Member
- 6 posts
- Joined: July 2015
- Offline
Thank you for the idea. I just gave it a try. Unfortunately, the keyframe is what makes the expression work.
To test, I:
- made a brand new button
- right click > Expression > Edit Expression
- add my stupid print test statement
- right click > Expression > Change Language to Python
- click the button
It still prints twice. Not only that, I noticed while I was testing that by doing (right click > Expression > Edit Expression) it adds a keyframe. I can confirm by checking (right click > Channels and Keyframes) and looking at whether Set Keyframe is grayed out or not. Before I created the expression, Set Keyframe is an enabled option while Remove Keyframe is disabled. After I added the expression and change the language, the reverse is true.
If I am remembering correctly, expressions (hscript and python) are run by keyframes and the keyframe is what tells Houdini to evaluate something other than the default value of the parameter. In this case, it's what tells the button to perform some action.
To test, I:
- made a brand new button
- right click > Expression > Edit Expression
- add my stupid print test statement
- right click > Expression > Change Language to Python
- click the button
It still prints twice. Not only that, I noticed while I was testing that by doing (right click > Expression > Edit Expression) it adds a keyframe. I can confirm by checking (right click > Channels and Keyframes) and looking at whether Set Keyframe is grayed out or not. Before I created the expression, Set Keyframe is an enabled option while Remove Keyframe is disabled. After I added the expression and change the language, the reverse is true.
If I am remembering correctly, expressions (hscript and python) are run by keyframes and the keyframe is what tells Houdini to evaluate something other than the default value of the parameter. In this case, it's what tells the button to perform some action.
- Anonymous
- Member
- 678 posts
- Joined: July 2005
- Offline
Maybe store script in node userData
http://www.sidefx.com/docs/houdini14.0/hom/nodeuserdata [sidefx.com]
as string and then extract it in callback and exec().
This way you could write whole multiline function with loops.
http://www.sidefx.com/docs/houdini14.0/hom/nodeuserdata [sidefx.com]
as string and then extract it in callback and exec().
This way you could write whole multiline function with loops.
- seando
- Member
- 6 posts
- Joined: July 2015
- Offline
Before I spend the time trying to get the multiline function into what looks like a single string to attach via setUserData, it doesn't seem like the userData is able to be saved in a preset, being node specific data.
To test, I have my null, created a simple userData test, saved it as a preset, then made a new null, applied the new preset and here is what I got:
>>> hou.node('/obj/break_geo/null3').setUserData(“foo”, “print ‘user data test’”)
>>> hou.node('/obj/break_geo/null3').userDataDict()
{'___Version___': ‘14.0.361’, ‘foo’: “print ‘user data test’”}
>>> hou.node('/obj/break_geo/null4').userDataDict()
{}
To test, I have my null, created a simple userData test, saved it as a preset, then made a new null, applied the new preset and here is what I got:
>>> hou.node('/obj/break_geo/null3').setUserData(“foo”, “print ‘user data test’”)
>>> hou.node('/obj/break_geo/null3').userDataDict()
{'___Version___': ‘14.0.361’, ‘foo’: “print ‘user data test’”}
>>> hou.node('/obj/break_geo/null4').userDataDict()
{}
- tamte
- Member
- 8554 posts
- Joined: July 2007
- Online
just create multiline string parm (e.g. ‘code’), (you can even set lanuage to Python for highlighting)
then do callback script for your button:
exec(hou.pwd().evalParm(“code”))
you can make the code parm invisible and locked if you don't want users to see it
then do callback script for your button:
exec(hou.pwd().evalParm(“code”))
you can make the code parm invisible and locked if you don't want users to see it
Tomas Slancik
FX Supervisor
Method Studios, NY
FX Supervisor
Method Studios, NY
- seando
- Member
- 6 posts
- Joined: July 2015
- Offline
- tamte
- Member
- 8554 posts
- Joined: July 2007
- Online
seando
Thank you sir, that works beautifully! It does exactly what I want and it is saved in my preset.
It's a bit of a workaround to the expression running twice on the button. I'll look into sending a bug report about it since it doesn't seem intentional.
I don't think that expression on button was ever meant to be used as a callback, so I would not expect it to be working that way
expression on button is expected to drive the button, not the button to necessarily drive the expression
you should really use callbacks for want you want
Tomas Slancik
FX Supervisor
Method Studios, NY
FX Supervisor
Method Studios, NY
- Dean_19
- Member
- 319 posts
- Joined:
- Offline
- Anonymous
- Member
- 678 posts
- Joined: July 2005
- Offline
- Dean_19
- Member
- 319 posts
- Joined:
- Offline
I'm not sure if this is obvious to other people or not, but I used this trick today and found out that the code you execute automatically inherits/has access to the kwargs dictionary.
So in your multiline string parm with code you can also access the node, parameter its being called from and its value!
useful!
So in your multiline string parm with code you can also access the node, parameter its being called from and its value!
useful!
-
- Quick Links