ynput / ayon-houdini

Houdini addon for AYON
Apache License 2.0
11 stars 9 forks source link

Houdini: Allow more ROP node types to detect their output filepaths #5

Open BigRoy opened 5 months ago

BigRoy commented 5 months ago

Is there an existing issue for this?

Please describe the feature you have in mind and explain what the current shortcomings are?

The Houdini integration uses the get_output_parameter we implemented in ayon_houdini.api.lib which has a hardcoded mapping of node type to the parm name that defines the output files. This is nice, because it's explicit. But time has also shown that it has a huge limitation - and that is that it can't detect anything not listed there.

I checked in with SideFX to see how they are doing it with their PDG/TOPs graphs to detect what the output files will be for any ROP node. They stated:

PDG does this by looking at parameters from a known list of output parm names -- there isn't a mechanism built into ROPs that it's using. It checks for the following list of parameters on the target ROP node, and if it finds one on the node it evaluates it for each frame and adds it as an expected output to the corresponding work item:

"vm_picture", "sopoutput", "dopoutput", "lopoutput", "picture", "copoutput", "filename", 
"usdfile", "file", "output", "outputfilepath", "outputimage", "outfile"

The node itself also makes it possible to specify a custom output parm name that overrides the list. This is also why the ROP Fetch TOP can't add expect outputs that aren't defined by a parameter, e.g. in LOPs the output paths might be defined in the USD data instead for example.

The actual implementation is specific to the ROP Fetch TOP and written in C++. It'd be fairly easy to do the same thing from Python though, but iterating over the hou.Node.parms() for a ROP node and checking them against the list of parm names.

How would you imagine the implementation of the feature?

Which made me think: should we follow suit and do something similar? Eg. we could apply this fallback logic for whenever the "explicit" mapping fails.

So basically:

# explicit mapping first
if node_type == "x":
    return node.parm("x")
elif node == "y":
    return node.parm("y")
else:
    # fallback
    names = ["vm_picture", "sopoutput", "dopoutput", "lopoutput", "picture", "copoutput", "filename", "usdfile", "file", "output", "outputfilepath", "outputimage", "outfile"]
    for name in names:
        parm = node.parm(name)
        if parm:
            return parm

Are there any labels you wish to add?

Describe alternatives you've considered:

We could expose to settings an additional mapping from node type to parm name so that any studio could configure it for any custom nodes they might be using in their studio. This is likely more explicit then the "fallback" method explained above - but it could also be combined:

# psuedocode
def get_output_parameter(node):
    # The hardcoded list for builtins we know to be true
    explicit = get_explicit_output_parameter(node)
    if explicit:
        return explicit

    # From settings
    user_defined = get_output_parameter_from_settings(node)
    if user_defined:
        return user_defined

    # The SideFX list of ROP filepath parm names
    fallback = get_fallback_output_parameter(node):
    if fallback:
        return fallback

Additional context:

Deadline also has their own (hardcoded?) list of expected output parameters for node types. I believe @fabiaserra may have matched those in the codebase here.

In Deadline, see DeadlineRepository\submission\Houdini\Main\SubmitHoudiniToDeadlineFunctions.py the GetOutputPath function. It also has GetExportPath which is also mimicked in Fabia's codebase.