Search - User list
Full Version: TOP's hda's and presubmit scripts
Root » PDG/TOPs » TOP's hda's and presubmit scripts
Andrew Graham
Is there anyway to make an asset in tops?
I have some scripts that I'd like to be able to reproduce and put in version control but it doesn't seem like there is an hda of type TOP.


I'm also wondering if its possible to do a presubmission script in the current hip, prior to it being saved for submission- for example, If I execute a stream of nodes, I want all their versions to be set to the version of the current hip version, but it needs to occur within the current houdini session prior to saving of the hip. otherwise the version saved on disk post submission would be out of sync with the current state.

My current workaround is that I use a shelf tool / right click script to do all this and execute the submission, but I'd like to find a better way if you guys have any cool ideas.
kenxu
Hi Andrew,

So I can answer at least the first part of your question, which is more straightforward. Yes, we can create assets in TOPs. Select a few nodes, make a subnet, and go ahead and create digital asset - it is no different than any other process. When you insert such a an HDA in a TOP graph, it behaves like syntatic sugar - that is, the graph will evaluate as if the contents of the HDA is inlined into the graph. You can also create HDAs with a python processor, to better encapsulate and present the functionality of your custom processor. The difference between “save to digital asset” and “save to python script” is that one will be callable by “pure pdg” outside of TOPs (save to python script), and one will only be usable within TOPs (save to digital asset), but is friendlier to use.

The second part of your question is a bit trickier. There are no hooks within TOPs to allow some sort of script to be run just prior to file save, or prior to file submission. For a hook prior to file save, perhaps there is some mechanism in the standard hou python interface? We are thinking about some sort of pre-flight mechanism, so maybe there is some hook there we can expose…?
Cera
You can also make a subnet into an HDA in TOPs. That has been my current workflow. Albeit I would RFE an Script based HDA option from the File > New Asset Dialog. Then again that whole dialog needs to be converted into a PyQt menu and be fully scriptable, but that is a trip down the rabbit hole.
Andrew Graham
Yes that was what caught me, old habits. It would be good to see tops in the new digital asset options.

I'm currently working on a custom right click menu to execute the dirty and then cook operation on the selected node to run preflight scripts, but one issue I'm bumping into is you can't cook a brand new top node like this-

hou.node('/obj/geo1/topnet1/ropfetch2').getPDGNode().cook(True)
Traceback (most recent call last):
File “<console>”, line 1, in <module>
AttributeError: ‘NoneType’ object has no attribute ‘cook’


You have to initilise it first through the standard cook menu item. Is there a way around that?

The same problem happens for “dirty”
Cera
This has worked for me in the past, but it does it for the chain from the selected node, not just the selected node.
block = False
node.node("TOPs/OUT").dirtyAllTasks(True)
node.node("TOPs/OUT").executeGraph(False, block, False) 
Andrew Graham
Thankyou for sharing i will put it to use, but i think side fx need to give us more than this to execute in the standard fashion. I often don't want to cook the entire graph.

I see no reason why i can't cook something upon opening a hip file. That python function to cook should always be possible.

Without the ability, we can't hack a preflight script.
kenxu
This is another artifact from the fact that TOPs is just a wrapper for PDG. When you first open the file, the PDG network is not created yet. That's why that first call fails. If you run

executeGraph(filter_static, block, generate_only, tops_only)

on the TOP node with the “generate_only” flag, it will cause the PDG graph to be generated and thus the rest of the script to succeed.
Andrew Graham
Ok great I'll try that, thanks for your help Ken and Laidlaw. Something I've noticed in the past when doing generate is that I've seen workitems actually start processing, which might have had something to do with dynamic modes on them.
Andrew Graham
Actually i just observed static items stay cooking when i only selected generate through the right click menu just now.
Andrew Graham
I've had some success being able to execute a preflight top node via a right click menu.

I realised though that I needed to ensure the python script wouldn't continue to execute the primary top stream though until the preflight finished cooking.
the nasty way would be to use cook(True), but this isn't great because it locks up the ui which is no good.

What would the recommended / best way be to execute the next stage after preflight completed?

I thought it would be something like adding an event handler (is this a callback?). if thats the best way, I wasn't able to get it to work in this very simple example, which should print “done”, when the node (top preflight stream) finished cooking.

If that is the right way to do it, do you have any suggestions on how I would get it to work?

>>> def done(node):
...     print "done", node
... 
>>> pdg_node = hou.node('/obj/geo1/topnet1/genericgenerator6').getPDGNode()
>>> pdg_node.addEventHandler(done(pdg_node), filter=pdg.EventType.CookComplete)
done <_pdg.genericgenerator name='genericgenerator6'>
Traceback (most recent call last):
  File "<console>", line 1, in <module>
TypeError: addEventHandler(): incompatible function arguments. The following argument types are supported:
    1. (self: _pdg.Node, arg0: object) -> _pdg.EventHandler
    2. (self: _pdg.Node, arg0: object, arg1: _pdg.EventType) -> _pdg.EventHandler

Invoked with: <_pdg.genericgenerator name='genericgenerator6'>, None


I wanted to note though, I think mappers should be able to do this. the only reason why this is being built instead of using something like a mapper, is that mappers will always pass the dirty/parent changed state downstream, which in the case of a preflight run is bad, because preflight is almost always dirty, and it shouldn't regenerate items downstream if they are on disk.

it would be great if all mappers / the waitfor all node had a tick box to not dirty downstream items, this seems to be the kind of thing mappers should be able do by extension (define relationships between two parts of a graph where workitems aren't being passed through).

By the way, the spelling of eventType in this doc should be EventType
https://www.sidefx.com/docs/houdini/tops/pdg/eventType.html [www.sidefx.com]
…I was wondering why it initally was not an object from following the docs
Andrew Graham
Another way I thought I'd try is just having a wait for all at the end of the preflight tree, and using a python script node to execute. this command works fine in a python shell, but in a python script node it just hangs on an endless loop and I have to kill the houdini session.

import hou
import pdg

hou.node('/obj/geo1/topnet1/filecopy6').getPDGNode().cook(False)
Andrew Graham
actually scratch that idea. its not the right way, because I need to resave the hip file in the current session after all my preflight finishes (files are synchronised/pushed elsewhere and version parms updated), before the submission of the main job.

whatever I do, I have to essentialy run two cook operations in the current houdini session, without locking up the ui.

cook(False) wont do, because its asynchronous, and cook(True) wont do, because the first task will lock up the ui until it completes.
chrisgreb
Just to clarify - it sounds like you have two disjoint graphs that you want to cook one after the other, with no dependencies between them. So dirtying the first does not dirty the second. Is that right?
Andrew Graham
Yes that's right Chris.
Andrew Graham
support were able to show me the right way to use an event handler in this situation and it works upon some initial testing which is great!

          ### setup handler before executing preflight ###
          self.graph_context = self.preflight_node.getPDGGraphContext()
          self.handler = self.graph_context.addEventHandler(cook_done, pdg.EventType.CookComplete)
          ### cook preflight ###
          self.preflight_status='cooking'
          self.preflight_node.getPDGNode().cook(False)

where cook_done is something like:

def cook_done(event):
      print event
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB