Python States: Guide geometry not updating on change

   2847   7   2
User Avatar
Member
8 posts
Joined: Feb. 2009
Offline
I'm working with a custom python state in H17. I've setup guide geometry in the HDA and reference it in the onEnter method as the docs suggest:

def onEnter(self, kwargs):
        node = kwargs["node"]
        inputs = node.inputs()
        
        #setup guide
        geo = node.node("Guide").geometry()
        #geo = node.node("Guide")
        self._guide = hou.Drawable(
            self.scene_viewer, geo,
            self.state_name + "_guide"
        ) 
        
        self._guide.enable(True)
        self._guide.show(True)

It's practically verbatim from the help: http://www.sidefx.com/docs/houdini/hom/state_guides.html#generating-guide-geometry [www.sidefx.com]

The guide geo does in fact display when I enter the tool. I does not update, however, when the guide geometry changes even though:
"If you get the geometry from a SOP node using SopNode.geometry, the resulting Geometry object is a live, read-only reference to the node’s output. If the node’s output changes (for example, because it is driven by parameters on your asset), the contents of the Geometry object automatically update.

I'm not seeing this behavior and was wondering if I was doing something incorrect. My geometry is static and does not update unless I re-enter the tool (or force a re-cook in one of the other events).

I would like the guides to update as the guide geometry updates. Thanks,

-Bob
User Avatar
Staff
396 posts
Joined: Feb. 2018
Offline
rkopinsky
I'm working with a custom python state in H17. I've setup guide geometry in the HDA and reference it in the onEnter method as the docs suggest:

def onEnter(self, kwargs):
        node = kwargs["node"]
        inputs = node.inputs()
        
        #setup guide
        geo = node.node("Guide").geometry()
        #geo = node.node("Guide")
        self._guide = hou.Drawable(
            self.scene_viewer, geo,
            self.state_name + "_guide"
        ) 
        
        self._guide.enable(True)
        self._guide.show(True)

It's practically verbatim from the help: http://www.sidefx.com/docs/houdini/hom/state_guides.html#generating-guide-geometry [www.sidefx.com]

The guide geo does in fact display when I enter the tool. I does not update, however, when the guide geometry changes even though:
"If you get the geometry from a SOP node using SopNode.geometry, the resulting Geometry object is a live, read-only reference to the node’s output. If the node’s output changes (for example, because it is driven by parameters on your asset), the contents of the Geometry object automatically update.

I'm not seeing this behavior and was wondering if I was doing something incorrect. My geometry is static and does not update unless I re-enter the tool (or force a re-cook in one of the other events).

I would like the guides to update as the guide geometry updates. Thanks,

-Bob

Hi, can you post your HDA ? I'll have a look.

thanks
User Avatar
Member
8 posts
Joined: Feb. 2009
Offline
Here you go. It takes any curve as input (a line SOP with several points will work just fine). The UI should produce arrows at every point. Thanks for the assist.

Attachments:
Sop_orientAlongCurve.hda (21.6 KB)

User Avatar
Staff
396 posts
Joined: Feb. 2018
Offline
Ok I think I found the problem… The drawable is not a node in the scene but just an object referencing the geometry. So when the node's scale parm is modified, it doesn't get refreshed since nothing is pulling on it.

The workaround I found is to add a callback to the scale parm to cook the node:

kwargs["node"].node("Guide").cook()

-mab
Edited by mabelzile - Jan. 22, 2019 19:41:49
User Avatar
Member
8 posts
Joined: Feb. 2009
Offline
That you very much for looking into this.

I guess I'm confused then on how to make the guide geometry live, as per the help. For example if the input curve is animated and I scrub the timeline the arrows do not update appropriately. I don't know where I would call the cook() method to accomplish this.

Actually the code from the help throws an error when pointing to a node, specifically:


geo = node.node("guide_output")

self._guide = hou.Drawable(
            self.scene_viewer, geo,
            self.state_name + "_guide"
)

hou.Drawable().__init__() takes a hou.Geometry() as it's second input. node.node() returns a hou.Node() so if you follow the sample code it fails.

Is there a way to point the Drawable towards a node rather than a geometry so the guide works for an animated input?

Thank you,
-Bob
User Avatar
Staff
396 posts
Joined: Feb. 2018
Offline
The documentation sample seems wrong, `hou.Drawable` takes either an enum or a geometry, not a node.

Using a node callback to react to scale change is another way to recook but the callback is not called on parms driven with an animation or an expression. I also tried with a playbar callback but for some reason the node won't recook either…

Here's my test code:
class MyState(object):
    def __init__(self, state_name, scene_viewer):
        self.state_name = state_name
        self.scene_viewer = scene_viewer
        
        self._guide = None
        self._node = None
        hou.playbar.addEventCallback(self.onPlaybarEvent)
        
    # Handler methods go here
    
    def onPlaybarEvent(self, event_type, frame):
        print 'onPlaybarEvent ', event_type, frame
        #self._node.parm('scale').eval()
        #self._node.node('Guide').cook(force=True, frame_range=(frame,frame))
        self._node.node('Guide').cook(force=True)

    def onNodeEvent(self, event_type, **kwargs):
        if event_type != hou.nodeEventType.ParmTupleChanged:
            return
        
        try:            
            if kwargs['parm_tuple'][0].name() == 'scale':
                kwargs['node'].node('Guide').cook()
        except:
            print kwargs['parm_tuple']
                
    def onExit(self,kwargs):
        try:
            hou.playbar.removeEventCallback(self.onPlaybarEvent)
        except:
            pass
            
        kwargs["node"].removeEventCallback( [hou.nodeEventType.ParmTupleChanged], self.onNodeEvent )
        self._node = None
        
    def onEnter(self, kwargs):
        node = kwargs["node"]
        inputs = node.inputs()
        
        #setup guide
        geo = node.node("Guide").geometry()
        #geo = node.node("Guide")
        self._guide = hou.Drawable(
            self.scene_viewer, geo,
            self.state_name + "_guide"
        ) 
        
        self._guide.enable(True)
        self._guide.show(True)
        self._node = node
        node.addEventCallback( [hou.nodeEventType.ParmTupleChanged], self.onNodeEvent )
Edited by mabelzile - Jan. 25, 2019 11:02:28
User Avatar
Member
8 posts
Joined: Feb. 2009
Offline
Thanks for the sanity check, it's really appreciated. I'll look forward to the advertised functionality in a future version then

-Bob
User Avatar
Member
12 posts
Joined: May 2017
Offline
I've been working with the new python states recently and also found quite a few issues with the examples from the docs.
Easiest way I've found to get my guides live updating is to use a null with the copy geometry parameter toggled off then merge that in above your actual output node.

(Excuse my ASCII node graph)
HDA network    Guide geo
| |
| GUIDES_OUT (point your Drawable to the .geometry() from this node)
| |
| null (copy geometry off)
| /
| /
| /
merge
|
OUT

Wiring it up like this will cause the guide geo branch to cook when the hda gets evaluated so you don't have to manually force cook any nodes with callbacks.
Edited by Leaf - Feb. 20, 2019 19:17:21
  • Quick Links