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], }
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]
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)