Beispiel #1
0
    def process(self, instance):
        from reveries.houdini import lib

        ropnode = instance[0]

        files = list()

        if "frameOutputs" in instance.data:
            output = instance.data["frameOutputs"][0]

            for path in instance.data["frameOutputs"]:
                files.append(os.path.basename(path))

        else:
            output_parm = lib.get_output_parameter(ropnode)
            output = output_parm.eval()

        staging_dir, filename = os.path.split(output)
        repr_root = instance.data["reprRoot"]

        instance.data["repr.VDB._stage"] = staging_dir
        instance.data["repr.VDB._hardlinks"] = files or [filename]
        instance.data["repr.VDB.entryFileName"] = filename
        instance.data["repr.VDB.reprRoot"] = repr_root

        instance.data["repr.VDB._delayRun"] = {
            "func": self.render,
            "args": [ropnode],
        }
Beispiel #2
0
    def process(self, instance):
        import hou
        from reveries.houdini import lib

        start_frame = instance.data.get("startFrame", None)
        end_frame = instance.data.get("endFrame", None)
        step = instance.data.get("step", None)

        if start_frame is None:
            self.log.info("No frame range data, skipping.")
            return

        self.log.info("Collecting range: [{s} - {e} @ {p}]"
                      "".format(s=start_frame, e=end_frame, p=step))

        ropnode = instance[0]

        output_parm = lib.get_output_parameter(ropnode)
        raw_output = output_parm.rawValue()

        frames = set()
        for frame in range(start_frame, end_frame + 1, step):
            output = hou.expandStringAtFrame(raw_output, frame)
            frames.add(output)

        instance.data.update({"frameOutputs": sorted(frames)})
    def process(self, instance):
        import hou
        from reveries.houdini import lib

        collected_frames = instance.data.get("frameOutputs", [])

        start_frame = instance.data.get("startFrame", None)
        end_frame = instance.data.get("endFrame", None)
        step = instance.data.get("step", None)

        if start_frame is None:
            if collected_frames:
                raise Exception("Frame range collected but not in validation"
                                ", please restart.")

            self.log.info("No frame range data, skipping.")
            return

        ropnode = instance[0]
        output_parm = lib.get_output_parameter(ropnode)
        raw_output = output_parm.rawValue()

        frames = set()
        for frame in range(start_frame, end_frame + 1, step):
            output = hou.expandStringAtFrame(raw_output, frame)
            frames.add(output)

        for count, output in enumerate(sorted(frames)):
            if collected_frames[count] != output:
                raise Exception("Output file name not matched with collected "
                                "data, please restart.")

        count += 1
        if count != len(collected_frames):
            raise Exception("Output range changed, please restart.")
    def get_invalid(cls, instance):

        node = instance[0]

        # Check trange parm, 0 means Render Current Frame
        frame_range = node.evalParm("trange")
        if frame_range == 0:
            return []

        output_parm = lib.get_output_parameter(node)
        unexpanded_str = output_parm.unexpandedString()

        if "$F" not in unexpanded_str:
            cls.log.error("No frame token found in '%s'" % node.path())
            return [instance]
Beispiel #5
0
    def process(self, instance):
        from reveries.houdini import lib

        cache_root = instance.data["reprRoot"]
        assert cache_root is not None, ("Cache root not collected, "
                                        "this is a bug.")

        ropnode = instance[0]
        output = lib.get_output_parameter(ropnode).eval()

        try:
            os.path.relpath(output, cache_root)
        except ValueError as e:
            self.log.error(e)
            raise Exception("Please write output under %s, "
                            "or use '$JOB' over '$HIP'." % cache_root)
    def get_invalid(cls, instance):
        # Get ROP node from instance
        node = instance[0]

        # Create lookup for current family in instance
        families = instance.data.get("families", list())
        family = instance.data.get("family", None)
        if family:
            families.append(family)
        families = set(families)

        # Perform extension check
        output = lib.get_output_parameter(node).eval()
        _, output_extension = os.path.splitext(output)

        for family in families:
            extension = cls.family_extensions.get(family, None)
            if extension is None:
                raise RuntimeError("Unsupported family: %s" % family)

            if output_extension != extension:
                return [node.path()]
    def process(self, instance):
        from reveries.houdini import lib

        context = instance.context

        if not all(result["success"] for result in context.data["results"]):
            self.log.warning("Atomicity not held, aborting.")
            return

        # Context data

        username = context.data["user"]
        comment = context.data.get("comment", "")
        project = context.data["projectDoc"]
        asset = instance.data["assetDoc"]["name"]

        fpath = context.data["currentMaking"]
        houdini_version = context.data["houdiniVersion"]

        project_id = str(project["_id"])[-4:].upper()
        project_code = project["data"].get("codename") or project_id
        fname = os.path.basename(fpath)

        batch_name = "({projcode}): [{asset}] {filename}".format(
            projcode=project_code, asset=asset, filename=fname)

        # Instance data

        subset = instance.data["subset"]
        version = instance.data["versionNext"]

        deadline_pool = instance.data["deadlinePool"]
        deadline_prio = instance.data["deadlinePriority"]
        deadline_group = instance.data.get("deadlineGroup")

        frame_per_task = instance.data.get("deadlineFramesPerTask", 1)

        try:
            frame_start = int(instance.data["startFrame"])
            frame_end = int(instance.data["endFrame"])
            frame_step = int(instance.data["step"])

        except KeyError:
            frames = None
        else:
            frames = "{start}-{end}x{step}".format(
                start=frame_start,
                end=frame_end,
                step=frame_step,
            )
            if instance.data["singleOutput"]:
                frame_per_task = len(range(frame_start, frame_end + 1))

        job_name = "{subset} v{version:0>3}".format(
            subset=subset,
            version=version,
        )

        if instance.data.get("deadlineSuspendJob", False):
            init_state = "Suspended"
        else:
            init_state = "Active"

        ropnode = instance[0]

        # Override output to use original $HIP
        output = lib.get_output_parameter(ropnode).rawValue()
        on_HIP = output.startswith("$HIP")
        origin_HIP = os.path.dirname(context.data["originMaking"])
        output = output.replace("$HIP", origin_HIP, 1) if on_HIP else None
        # (NOTE) ^^^ For a fixed staging dir
        #   We need this because the scene file we submit to Deadline is a
        #   backup under `$HIP/_published` dir which copied via extractor
        #   plugin `AvalonSaveScene`.
        #
        #   Note that the Deadline (10.0.27.2) Houdini plugin does not support
        #   output filename override if the ROP node type is `alembic`. So to
        #   make this work, I have modified the Deadline Houdini plugin script
        #   `{DeadlineRepo}/plugins/Houdini/hrender_dl.py` at line 375:
        #   ```diff
        #   - elif ropType == "rop_alembic":
        #   + elif ropType in ("rop_alembic", "alembic"):
        #   ```

        # Assemble payload

        payload = {
            "JobInfo": {
                "Plugin": "Houdini",
                "BatchName": batch_name,  # Top-level group name
                "Name": job_name,
                "UserName": username,
                "MachineName": platform.node(),
                "Comment": comment,
                "Pool": deadline_pool,
                "Priority": deadline_prio,
                "Group": deadline_group,
                "Frames": frames,
                "ChunkSize": frame_per_task,
                "InitialStatus": init_state,
                "ExtraInfo0": project["name"],
            },
            "PluginInfo": {
                "SceneFile": fpath,
                "Build": "64bit",
                "Version": houdini_version,

                # Renderer Node
                "OutputDriver": ropnode.path(),
                # Output Filename
                "Output": output,
                "IgnoreInputs": False,
                "GPUsPerTask": 0,
                "SelectGPUDevices": "",
            },
            # Mandatory for Deadline, may be empty
            "AuxFiles": [],
            "IdOnly": True
        }

        # Environment

        environment = self.assemble_environment(instance)

        parsed_environment = {
            "EnvironmentKeyValue%d" % index:
            u"{key}={value}".format(key=key, value=environment[key])
            for index, key in enumerate(environment)
        }
        payload["JobInfo"].update(parsed_environment)

        self.log.info("Submitting.. %s" % instance)
        self.log.info(json.dumps(payload, indent=4, sort_keys=True))

        # Submit

        submitter = context.data["deadlineSubmitter"]
        submitter.add_job(payload)
    def get_staging_dir(cls, ropnode):
        from reveries.houdini import lib
        output_parm = lib.get_output_parameter(ropnode)
        output = output_parm.eval()

        return os.path.dirname(output)