Beispiel #1
0
    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)
Beispiel #2
0
    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)
Beispiel #3
0
    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)
Beispiel #4
0
    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)
Beispiel #7
0
 def process(self, context):
     from mindbender import api
     context.data["time"] = api.time()
Beispiel #8
0
 def process(self, context):
     from avalon import api
     context.data["time"] = api.time()