Skip to content

Introduce Houdini to core#343

Merged
aardschok merged 39 commits into
getavalon:masterfrom
aardschok:PLN-171
Oct 3, 2018
Merged

Introduce Houdini to core#343
aardschok merged 39 commits into
getavalon:masterfrom
aardschok:PLN-171

Conversation

@aardschok
Copy link
Copy Markdown
Collaborator

This PR will add Houdini to the list of available hosts of Avalon.

Important nodes:

  • The 123.py is crucial to the implementation of Houdini into the pipeline. It is used to ensure that Avalon and the configuration are installed.
    From the documents
Houdini runs this script when it is started without a scene (.hip) file. 
Houdini will only run the first 123.py script it finds in the path
  • It is not possible to dynamically create a menu as Houdini needs to have xml files when it launches to create the menus. Houdini checks HOUDINI_PATH and HOUDINI_MENU_PATH for any xml files which match a certain name, for more information look here

Instances

Creating instances is a bit more complex in Houdini than it is in Maya. To keep everything as close to the application as possible I chose make the Creator class more dependent on the plugins. Example code:

class MyPlugin(houdini.Creator):
    """Some awesome plugin"""

    name = "pointcache"
    label = "Point Cache"
    family = "colorbleed.pointcache"
    icon = "gears"

    def __init__(self, *args, **kwargs):
        super(CreatePointCache, self).__init__(*args, **kwargs)

        # Remove the active, we are checking the bypass flag of the nodes
        self.data.pop("active", None)

        self.data.update({"node_type": "alembic"})

    def process(self):
        instance = super(CreatePointCache, self).process()

        parms = {"use_sop_path": True,       # Export single node from SOP Path
                        "build_from_path": True,  # Direct path of primitive in output
                        "path_attrib": "path",        # Pass path attribute for output
                        "format": 2,                       # Set format to Ogawa
                         "filename": "$HIP/pyblish/%s.abc" % self.name}

        if self.nodes:
            node = self.nodes[0]
            parms.update({"sop_path": "%s/OUT" % node.path()})

        instance.setParms(parms)

Depending on the output you want you to pass on the desired ROP node type in order to create it. Houdini uses the Out Network in which all render nodes reside.
In process can pass on any attribute adjustments or connections after the super.

The active is controlled by the isBypassed flag of the ROP node.

Containers
I tried to keep everything as close as possible to the approaches used in Maya, for example: AVALON_CONTAINERS to maintain some overview. In order to achieve that I have create a hierarchy which looks like this:

/obj/AVALON_CONTAINERS/ROOT

  • /obj is the object level in which the user 90% of the time works
  • AVALON_CONTAINERS is a geo node, this is required in order to create a secondary object network
  • ROOT is a objnet or object network, this is similar to /obj, in which content can be loaded

There is a drawback on the AVALON_CONTAINER setup I have created here. If Houdini is used for compositing for example, it might need its own AVALON_CONTAINER setup. When this is the case we will need to review the ls function for Houdini as it is currently focused on geometry.

Publishing
Because the instances are each their own type, the logic for extracting instances differs but is also more streamlines. There are a few similarities which help a whole lot, each ROP node has the same logic for frames. The basic parameters are the same for each of them and the main output method is the same, which is ropnode.render(). Their might be some alternative methods of rendering files, for example: executebackground() on geometry nodes (used for VDB)

Side note
This was a pretty cool DCC to develop a pipeline for as it has many things which help us developers.

aardschok added 30 commits July 17, 2018 09:49
Install config when launching standalone tool
Introduce Houdini to Avalon core
Improvement on Houdini pipeline + small bugfix
"avalon.tools",
"avalon.houdini"):
module = importlib.import_module(module)
reload(module)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

undefined name 'reload'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's upset because it thinks it's Python 3. This function is destined for refactoring anyway, happy to leave it as-is for now.

@@ -0,0 +1,38 @@
from .pipeline import (
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'.pipeline.Creator' imported but unused
'.pipeline.maintained_selection' imported but unused

Comment thread avalon/houdini/__init__.py Outdated
__all__ = [
"install",
"uninstall",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blank line contains whitespace

maintained_selection
)

from .lib import (
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'.lib.lsattr' imported but unused

Bah, editing on GitHub is hard. :)
@mottosso
Copy link
Copy Markdown
Contributor

mottosso commented Oct 3, 2018

Happy to see this merged once you're happy @aardschok, great job!

@aardschok
Copy link
Copy Markdown
Collaborator Author

We discovered a flaw in the design. A secondary object network will not display any items created in that network in the parent object network. To visualize the issue:

Image from Gyazo

We will switch to a subnetwork node as its contents are displayable when going a level up.

@aardschok aardschok merged commit 79ea85a into getavalon:master Oct 3, 2018


def _on_scene_open(*args):
api.emit("open", *[])
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if you wanted this: *[]. It would always unpack to nothing - should this be args like how the emit calls are done in the Maya pipeline in core. Or is there a reason to do *[] in Python?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have tested the args and *args but both will prompt the following error, I opened a file to test it.

WARNING:avalon.pipeline:Traceback (most recent call last):
  File "C:\Users\Guest4\Development\colorbleed\core\avalon\pipeline.py", line 532, in emit
    callback(*args)
TypeError: on_open() argument after * must be a sequence, not EnumValue

Passing a simple list, [] will suffice, I will setup a fix for it

tokejepsen pushed a commit to tokejepsen/core that referenced this pull request Jul 30, 2021
…ignore_project_change_on_refresh

Library loader refresh fix
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants