def process(self, context): """Entry point to collector.""" render_instance = None for instance in context: if "rendering" in instance.data["families"]: render_instance = instance render_instance.data["remove"] = True # make sure workfile instance publishing is enabled if "workfile" in instance.data["families"]: instance.data["publish"] = True if not render_instance: self.log.info( "No render instance found, skipping render " "layer collection." ) return render_globals = render_instance collected_render_layers = render_instance.data["setMembers"] filepath = context.data["currentFile"].replace("\\", "/") asset = api.Session["AVALON_ASSET"] workspace = context.data["workspaceDir"] self._rs = renderSetup.instance() current_layer = self._rs.getVisibleRenderLayer() maya_render_layers = { layer.name(): layer for layer in self._rs.getRenderLayers() } self.maya_layers = maya_render_layers for layer in collected_render_layers: # every layer in set should start with `LAYER_` prefix try: expected_layer_name = re.search(r"^LAYER_(.*)", layer).group(1) except IndexError: msg = "Invalid layer name in set [ {} ]".format(layer) self.log.warnig(msg) continue self.log.info("processing %s" % layer) # check if layer is part of renderSetup if expected_layer_name not in maya_render_layers: msg = "Render layer [ {} ] is not in " "Render Setup".format( expected_layer_name ) self.log.warning(msg) continue # check if layer is renderable if not maya_render_layers[expected_layer_name].isRenderable(): msg = "Render layer [ {} ] is not " "renderable".format( expected_layer_name ) self.log.warning(msg) continue # test if there are sets (subsets) to attach render to sets = cmds.sets(layer, query=True) or [] attach_to = [] if sets: for s in sets: if "family" not in cmds.listAttr(s): continue attach_to.append( { "version": None, # we need integrator for that "subset": s, "family": cmds.getAttr("{}.family".format(s)), } ) self.log.info(" -> attach render to: {}".format(s)) layer_name = "rs_{}".format(expected_layer_name) # collect all frames we are expecting to be rendered renderer = cmds.getAttr( "defaultRenderGlobals.currentRenderer" ).lower() # handle various renderman names if renderer.startswith("renderman"): renderer = "renderman" # return all expected files for all cameras and aovs in given # frame range ef = ExpectedFiles() exp_files = ef.get(renderer, layer_name) self.log.info("multipart: {}".format(ef.multipart)) assert exp_files, "no file names were generated, this is bug" # if we want to attach render to subset, check if we have AOV's # in expectedFiles. If so, raise error as we cannot attach AOV # (considered to be subset on its own) to another subset if attach_to: assert isinstance(exp_files, list), ( "attaching multiple AOVs or renderable cameras to " "subset is not supported" ) # append full path full_exp_files = [] aov_dict = {} # we either get AOVs or just list of files. List of files can # mean two things - there are no AOVs enabled or multipass EXR # is produced. In either case we treat those as `beauty`. if isinstance(exp_files[0], dict): for aov, files in exp_files[0].items(): full_paths = [] for e in files: full_path = os.path.join(workspace, "renders", e) full_path = full_path.replace("\\", "/") full_paths.append(full_path) aov_dict[aov] = full_paths else: full_paths = [] for e in exp_files: full_path = os.path.join(workspace, "renders", e) full_path = full_path.replace("\\", "/") full_paths.append(full_path) aov_dict["beauty"] = full_paths frame_start_render = int(self.get_render_attribute( "startFrame", layer=layer_name)) frame_end_render = int(self.get_render_attribute( "endFrame", layer=layer_name)) if (int(context.data['frameStartHandle']) == frame_start_render and int(context.data['frameEndHandle']) == frame_end_render): # noqa: W503, E501 handle_start = context.data['handleStart'] handle_end = context.data['handleEnd'] frame_start = context.data['frameStart'] frame_end = context.data['frameEnd'] frame_start_handle = context.data['frameStartHandle'] frame_end_handle = context.data['frameEndHandle'] else: handle_start = 0 handle_end = 0 frame_start = frame_start_render frame_end = frame_end_render frame_start_handle = frame_start_render frame_end_handle = frame_end_render full_exp_files.append(aov_dict) self.log.info(full_exp_files) self.log.info("collecting layer: {}".format(layer_name)) # Get layer specific settings, might be overrides data = { "subset": expected_layer_name, "attachTo": attach_to, "setMembers": layer_name, "multipartExr": ef.multipart, "review": render_instance.data.get("review") or False, "publish": True, "handleStart": handle_start, "handleEnd": handle_end, "frameStart": frame_start, "frameEnd": frame_end, "frameStartHandle": frame_start_handle, "frameEndHandle": frame_end_handle, "byFrameStep": int( self.get_render_attribute("byFrameStep", layer=layer_name)), "renderer": self.get_render_attribute("currentRenderer", layer=layer_name), # instance subset "family": "renderlayer", "families": ["renderlayer"], "asset": asset, "time": api.time(), "author": context.data["user"], # Add source to allow tracing back to the scene from # which was submitted originally "source": filepath, "expectedFiles": full_exp_files, "resolutionWidth": cmds.getAttr("defaultResolution.width"), "resolutionHeight": cmds.getAttr("defaultResolution.height"), "pixelAspect": cmds.getAttr("defaultResolution.pixelAspect"), "tileRendering": render_instance.data.get("tileRendering") or False, # noqa: E501 "tilesX": render_instance.data.get("tilesX") or 2, "tilesY": render_instance.data.get("tilesY") or 2, "priority": render_instance.data.get("priority") } # Apply each user defined attribute as data for attr in cmds.listAttr(layer, userDefined=True) or list(): try: value = cmds.getAttr("{}.{}".format(layer, attr)) except Exception: # Some attributes cannot be read directly, # such as mesh and color attributes. These # are considered non-essential to this # particular publishing pipeline. value = None data[attr] = value # handle standalone renderers if render_instance.data.get("vrayScene") is True: data["families"].append("vrayscene") if render_instance.data.get("assScene") is True: data["families"].append("assscene") # Include (optional) global settings # Get global overrides and translate to Deadline values overrides = self.parse_options(str(render_globals)) data.update(**overrides) # Define nice label label = "{0} ({1})".format(expected_layer_name, data["asset"]) label += " [{0}-{1}]".format( int(data["frameStartHandle"]), int(data["frameEndHandle"]) ) instance = context.create_instance(expected_layer_name) instance.data["label"] = label instance.data.update(data) self.log.debug("data: {}".format(json.dumps(data, indent=4))) # Restore current layer. self.log.info("Restoring to {}".format(current_layer.name())) self._rs.switchToLayer(current_layer)
def process(self, instance): """Collector entry point.""" collected_render_layers = instance.data["setMembers"] instance.data["remove"] = True context = instance.context _rs = renderSetup.instance() # current_layer = _rs.getVisibleRenderLayer() # collect all frames we are expecting to be rendered renderer = cmds.getAttr("defaultRenderGlobals.currentRenderer").lower() if renderer != "vray": raise AssertionError("Vray is not enabled.") maya_render_layers = { layer.name(): layer for layer in _rs.getRenderLayers() } layer_list = [] for layer in collected_render_layers: # every layer in set should start with `LAYER_` prefix try: expected_layer_name = re.search(r"^.+:(.*)", layer).group(1) except IndexError: msg = "Invalid layer name in set [ {} ]".format(layer) self.log.warnig(msg) continue self.log.info("processing %s" % layer) # check if layer is part of renderSetup if expected_layer_name not in maya_render_layers: msg = "Render layer [ {} ] is not in " "Render Setup".format( expected_layer_name) self.log.warning(msg) continue # check if layer is renderable if not maya_render_layers[expected_layer_name].isRenderable(): msg = "Render layer [ {} ] is not " "renderable".format( expected_layer_name) self.log.warning(msg) continue layer_name = "rs_{}".format(expected_layer_name) self.log.debug(expected_layer_name) layer_list.append(expected_layer_name) frame_start_render = int( self.get_render_attribute("startFrame", layer=layer_name)) frame_end_render = int( self.get_render_attribute("endFrame", layer=layer_name)) if (int(context.data['frameStartHandle']) == frame_start_render and int(context.data['frameEndHandle']) == frame_end_render): # noqa: W503, E501 handle_start = context.data['handleStart'] handle_end = context.data['handleEnd'] frame_start = context.data['frameStart'] frame_end = context.data['frameEnd'] frame_start_handle = context.data['frameStartHandle'] frame_end_handle = context.data['frameEndHandle'] else: handle_start = 0 handle_end = 0 frame_start = frame_start_render frame_end = frame_end_render frame_start_handle = frame_start_render frame_end_handle = frame_end_render # Get layer specific settings, might be overrides data = { "subset": expected_layer_name, "layer": layer_name, "setMembers": cmds.sets(layer, q=True) or ["*"], "review": False, "publish": True, "handleStart": handle_start, "handleEnd": handle_end, "frameStart": frame_start, "frameEnd": frame_end, "frameStartHandle": frame_start_handle, "frameEndHandle": frame_end_handle, "byFrameStep": int(self.get_render_attribute("byFrameStep", layer=layer_name)), "renderer": self.get_render_attribute("currentRenderer", layer=layer_name), # instance subset "family": "vrayscene_layer", "families": ["vrayscene_layer"], "asset": api.Session["AVALON_ASSET"], "time": api.time(), "author": context.data["user"], # Add source to allow tracing back to the scene from # which was submitted originally "source": context.data["currentFile"].replace("\\", "/"), "resolutionWidth": cmds.getAttr("defaultResolution.width"), "resolutionHeight": cmds.getAttr("defaultResolution.height"), "pixelAspect": cmds.getAttr("defaultResolution.pixelAspect"), "priority": instance.data.get("priority"), "useMultipleSceneFiles": instance.data.get("vraySceneMultipleFiles") } # Define nice label label = "{0} ({1})".format(expected_layer_name, data["asset"]) label += " [{0}-{1}]".format(int(data["frameStartHandle"]), int(data["frameEndHandle"])) instance = context.create_instance(expected_layer_name) instance.data["label"] = label instance.data.update(data)
def process(self, context): # Sort by displayOrder def sort_by_display_order(layer): return cmds.getAttr("%s.displayOrder" % layer) host = api.registered_host() asset = api.Session["AVALON_ASSET"] work_dir = context.data["workspaceDir"] # Get VRay Scene instance vray_scenes = host.lsattr("family", "vrayscene") if not vray_scenes: self.log.info("Skipping vrayScene collection, no " "vrayscene instance found..") return assert len(vray_scenes) == 1, "Multiple vrayscene instances found!" vray_scene = vray_scenes[0] vrscene_data = host.read(vray_scene) assert cmds.ls("vraySettings", type="VRaySettingsNode"), ( "VRay Settings node does not exists. " "Please ensure V-Ray is the current renderer.") # Output data start_frame = int(cmds.getAttr("defaultRenderGlobals.startFrame")) end_frame = int(cmds.getAttr("defaultRenderGlobals.endFrame")) # Create output file path with template file_name = context.data["currentFile"].replace("\\", "/") vrscene = ("vrayscene", "<Scene>", "<Scene>_<Layer>", "<Layer>") vrscene_output = os.path.join(work_dir, *vrscene) # Check and create render output template for render job # outputDir is required for submit_publish_job if not vrscene_data.get("suspendRenderJob", False): renders = ("renders", "<Scene>", "<Scene>_<Layer>", "<Layer>") output_renderpath = os.path.join(work_dir, *renders) vrscene_data["outputDir"] = output_renderpath # Get resolution resolution = (cmds.getAttr("defaultResolution.width"), cmds.getAttr("defaultResolution.height")) # Get format extension extension = cmds.getAttr("vraySettings.imageFormatStr") # Get render layers render_layers = [ i for i in cmds.ls(type="renderLayer") if cmds.getAttr("{}.renderable".format(i)) and not cmds.referenceQuery(i, isNodeReferenced=True) ] render_layers = sorted(render_layers, key=sort_by_display_order) for layer in render_layers: subset = layer if subset == "defaultRenderLayer": subset = "masterLayer" data = { "subset": subset, "setMembers": layer, "startFrame": start_frame, "endFrame": end_frame, "renderer": "vray", "resolution": resolution, "ext": ".{}".format(extension), # instance subset "family": "VRay Scene", "families": ["vrayscene"], "asset": asset, "time": api.time(), "author": context.data["user"], # Add source to allow tracing back to the scene from # which was submitted originally "source": file_name, # Store VRay Scene additional data "vrsceneOutput": vrscene_output } data.update(vrscene_data) instance = context.create_instance(subset) self.log.info("Created: %s" % instance.name) instance.data.update(data)
def process(self, context): asset = api.Session["AVALON_ASSET"] filepath = context.data["currentFile"].replace("\\", "/") # Get render globals node try: render_globals = cmds.ls("renderglobalsMain")[0] for instance in context: self.log.debug(instance.name) if instance.data['family'] == 'workfile': instance.data['publish'] = True except IndexError: self.log.info("Skipping renderlayer collection, no " "renderGlobalsDefault found..") return # Get all valid renderlayers # This is how Maya populates the renderlayer display rlm_attribute = "renderLayerManager.renderLayerId" connected_layers = cmds.listConnections(rlm_attribute) or [] valid_layers = set(connected_layers) # Get all renderlayers and check their state renderlayers = [ i for i in cmds.ls(type="renderLayer") if cmds.getAttr("{}.renderable".format(i)) and not cmds.referenceQuery(i, isNodeReferenced=True) ] # Sort by displayOrder def sort_by_display_order(layer): return cmds.getAttr("%s.displayOrder" % layer) renderlayers = sorted(renderlayers, key=sort_by_display_order) for layer in renderlayers: # Check if layer is in valid (linked) layers if layer not in valid_layers: self.log.warning("%s is invalid, skipping" % layer) continue if layer.endswith("defaultRenderLayer"): continue else: # Remove Maya render setup prefix `rs_` layername = layer.split("rs_", 1)[-1] # Get layer specific settings, might be overrides data = { "subset": layername, "setMembers": layer, "publish": True, "frameStart": self.get_render_attribute("startFrame", layer=layer), "frameEnd": self.get_render_attribute("endFrame", layer=layer), "byFrameStep": self.get_render_attribute("byFrameStep", layer=layer), "renderer": self.get_render_attribute("currentRenderer", layer=layer), # instance subset "family": "Render Layers", "families": ["renderlayer"], "asset": asset, "time": api.time(), "author": context.data["user"], # Add source to allow tracing back to the scene from # which was submitted originally "source": filepath } # Apply each user defined attribute as data for attr in cmds.listAttr(layer, userDefined=True) or list(): try: value = cmds.getAttr("{}.{}".format(layer, attr)) except Exception: # Some attributes cannot be read directly, # such as mesh and color attributes. These # are considered non-essential to this # particular publishing pipeline. value = None data[attr] = value # Include (optional) global settings # TODO(marcus): Take into account layer overrides # Get global overrides and translate to Deadline values overrides = self.parse_options(render_globals) data.update(**overrides) # Define nice label label = "{0} ({1})".format(layername, data["asset"]) label += " [{0}-{1}]".format(int(data["frameStart"]), int(data["frameEnd"])) instance = context.create_instance(layername) instance.data["label"] = label instance.data.update(data)
def process(self, context): context.data["time"] = api.time()
def process(self, context): asset = api.Session["AVALON_ASSET"] filepath = context.data["currentFile"].replace("\\", "/") # Get render globals node try: render_globals = cmds.ls("renderglobalsDefault")[0] except IndexError: self.log.error("Cannot collect renderlayers without " "renderGlobals node") return # Get start and end frame start_frame = self.get_render_attribute("startFrame") end_frame = self.get_render_attribute("endFrame") context.data["startFrame"] = start_frame context.data["endFrame"] = end_frame # Get render layers renderlayers = [i for i in cmds.ls(type="renderLayer") if cmds.getAttr("{}.renderable".format(i)) and not cmds.referenceQuery(i, isNodeReferenced=True)] # Include/exclude default render layer default_layer = "{}.includeDefaultRenderLayer".format(render_globals) use_defaultlayer = cmds.getAttr(default_layer) if not use_defaultlayer: renderlayers = [i for i in renderlayers if not i.endswith("defaultRenderLayer")] # Sort by displayOrder def sort_by_display_order(layer): return cmds.getAttr("%s.displayOrder" % layer) renderlayers = sorted(renderlayers, key=sort_by_display_order) for layer in renderlayers: if layer.endswith("defaultRenderLayer"): layername = "masterLayer" else: layername = layer.split("rs_", 1)[-1] # Get layer specific settings, might be overrides with lib.renderlayer(layer): data = { "subset": layername, "setMembers": layer, "publish": True, "startFrame": self.get_render_attribute("startFrame"), "endFrame": self.get_render_attribute("endFrame"), "byFrameStep": self.get_render_attribute("byFrameStep"), "renderer": self.get_render_attribute("currentRenderer"), # instance subset "family": "Render Layers", "families": ["colorbleed.renderlayer"], "asset": asset, "time": api.time(), "author": context.data["user"], # Add source to allow tracing back to the scene from # which was submitted originally "source": filepath } # Apply each user defined attribute as data for attr in cmds.listAttr(layer, userDefined=True) or list(): try: value = cmds.getAttr("{}.{}".format(layer, attr)) except Exception: # Some attributes cannot be read directly, # such as mesh and color attributes. These # are considered non-essential to this # particular publishing pipeline. value = None data[attr] = value # Include (optional) global settings # TODO(marcus): Take into account layer overrides # Get global overrides and translate to Deadline values overrides = self.parse_options(render_globals) data.update(**overrides) instance = context.create_instance(layername) instance.data.update(data)
def process(self, context): from mindbender import api context.data["time"] = api.time()
def process(self, context): from avalon import api context.data["time"] = api.time()