Skip to content

collect_slapcomps

CollectSlapComps

Bases: HoudiniInstancePlugin

Collect Slap Comps.

It collects Slap Comps from the USD render rop node and save them as a list in slapComp key in instance.data.

It also generates a .bgeo file if the slap comp is using a COP Node. This is a workaround as it's not possible to predict the generated filename from the USD ROP, as discussed in https://www.sidefx.com/forum/topic/101973/

Each item in the list follows

slap_comp_path?option=value&option2=value2

Source code in client/ayon_houdini/plugins/publish/collect_slapcomps.py
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
class CollectSlapComps(plugin.HoudiniInstancePlugin):
    """Collect Slap Comps.

    It collects Slap Comps from the USD render rop node and
    save them as a list in `slapComp` key in `instance.data`.

    It also generates a `.bgeo` file if the slap comp is using
    a COP Node. This is a workaround as it's not possible to
    predict the generated filename from the USD ROP,
    as discussed in https://www.sidefx.com/forum/topic/101973/

    Each item in the list follows:
        slap_comp_path?option=value&option2=value2

    """

    # This specific order value is used so that
    # this plugin runs after CollectRenderProducts
    order = pyblish.api.CollectorOrder + 0.1
    label = "Collect Slap Comps"
    families = ["usdrender"]

    # Copernicus was introduced in Houdini 20.5 so we only enable this
    # Collect Slap Comps if the Houdini version is 20.5 or higher.
    enabled = hou.applicationVersion() >= (20, 5, 0)

    def process(self, instance):
        if not instance.data["splitRender"]:
            # This collector plugin is only needed when using the
            # `Farm Rendering - Split export & render jobs` render
            # target, as it uses a separate DL plugin from the
            # default Houdini DL plugin.
            # For other render targets, such as **farm rendering** and
            # **local machine rendering**, this plugin is not necessary
            # because Houdini handles the slap comp process by default.
            return

        node_path = instance.data.get("instance_node")
        if node_path is None:
            # Instance without instance node like a workfile instance
            self.log.debug(
                "No instance node found for instance: {}".format(instance)
            )
            return

        ropnode = hou.node(node_path)

        slapcomp_sources =  []

        comp_numbers = ropnode.evalParm("husk_slapcomp")
        for i in range(1, comp_numbers+1):

            if not ropnode.evalParm(f'husk_sc_enable{i}'):
                continue

            # slap comp cli expects a path to apex node.
            slapcomp_src = ""

            if ropnode.evalParm(f'husk_sc_source{i}') != "file":
                slapcomp_out = ropnode.parm(f'husk_sc_cop{i}').evalAsNode()

                slapcomp_dir = os.path.dirname(instance.data["ifdFile"])
                slapcomp_src = f"{slapcomp_dir}/{slapcomp_out.name()}.bgeo"

                lib.save_slapcomp_to_file(
                    slapcomp_out,
                    slapcomp_src
                )
                self.log.debug(
                    f"USD Render ROP '{node_path}' has Slap Comp {i}"
                    " enabled using a COP node. A Slap Comp file"
                    " been exported for farm rendering."
                )
            else:
                slapcomp_src = ropnode.evalParm(f'husk_sc_file{i}')

            name = ropnode.evalParm(f'husk_sc_label{i}')

            map_inputs: list[str] = []
            for j in range(1, ropnode.evalParm(f'husk_sc_mapinput{i}')+1):
                src_aov = ropnode.evalParm(f'husk_sc_in{i}_aov{j}')
                dst_cop = ropnode.evalParm(f'husk_sc_in{i}_cop{j}')
                if src_aov or dst_cop:
                    map_inputs.append(f"{src_aov}:{dst_cop}")

            map_outputs: list[str] = []
            for j in range(1, ropnode.evalParm(f'husk_sc_mapoutput{i}')+1):
                src_cop = ropnode.evalParm(f'husk_sc_out{i}_cop{j}')
                dst_aov = ropnode.evalParm(f'husk_sc_out{i}_aov{j}')
                if src_cop or dst_aov:
                    map_outputs.append(f"{src_cop}:{dst_aov}")

            options = {
                "name": name,
                "mapinput": ",".join(map_inputs),
                "mapoutput": ",".join(map_outputs),
            }

            options = "&".join(
                f"{option}={value}"
                for option, value in options.items() if value
            )

            if options:
                slapcomp_src += f"?{options}"

            self.log.debug(
                f"Found Slap Comp: {slapcomp_src}"
            )

            slapcomp_sources.append(slapcomp_src)

        instance.data["slapComp"] = slapcomp_sources