Python Expression on Button Running Twice

   9622   14   3
User Avatar
Member
6 posts
Joined: July 2015
Offline
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,

Attachments:
hou_python_doublePrint.png (1.2 KB)
hou_python_doublePrintSetup.png (82.5 KB)

User Avatar
Member
2537 posts
Joined: June 2008
Offline
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.
Using Houdini Indie 20.0
Windows 11 64GB Ryzen 16 core.
nVidia 3050RTX 8BG RAM.
User Avatar
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.
User Avatar
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]
Using Houdini Indie 20.0
Windows 11 64GB Ryzen 16 core.
nVidia 3050RTX 8BG RAM.
User Avatar
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.
User Avatar
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.
User Avatar
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.
User Avatar
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.
User Avatar
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()
{}
User Avatar
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
Tomas Slancik
FX Supervisor
Method Studios, NY
User Avatar
Member
6 posts
Joined: July 2015
Offline
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.
User Avatar
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
User Avatar
Member
319 posts
Joined:
Offline
Hey Tomas,

When I tested this method, I noticed that the code still executes when the node cooks, as well as on the button press. Do you know if there is a way to stop the cook execute? Or am I implementing this wrong?

Thanks!
User Avatar
Member
678 posts
Joined: July 2005
Offline
Probably because you put keyframe on string field. You don't have to put it if you just want to store text there.
User Avatar
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!
  • Quick Links