Exemplo n.º 1
0
    def _create_instances_for_aov(self, instance_data, exp_files):
        """Create instance for each AOV found.

        This will create new instance for every aov it can detect in expected
        files list.

        Arguments:
            instance_data (pyblish.plugin.Instance): skeleton data for instance
                (those needed) later by collector
            exp_files (list): list of expected files divided by aovs

        Returns:
            list of instances

        """
        task = os.environ["AVALON_TASK"]
        subset = instance_data["subset"]
        instances = []
        # go through aovs in expected files
        for aov, files in exp_files[0].items():
            cols, rem = clique.assemble(files)
            # we shouldn't have any reminders. And if we do, it should
            # be just one item for single frame renders.
            if not cols and rem:
                assert len(rem) == 1, ("Found multiple non related files "
                                       "to render, don't know what to do "
                                       "with them.")
                col = rem[0]
                ext = os.path.splitext(col)[1].lstrip(".")
            else:
                # but we really expect only one collection.
                # Nothing else make sense.
                assert len(
                    cols
                ) == 1, "only one image sequence type is expected"  # noqa: E501
                ext = cols[0].tail.lstrip(".")
                col = list(cols[0])

            self.log.debug(col)
            # create subset name `familyTaskSubset_AOV`
            group_name = 'render{}{}{}{}'.format(task[0].upper(), task[1:],
                                                 subset[0].upper(), subset[1:])

            subset_name = '{}_{}'.format(group_name, aov)

            if isinstance(col, (list, tuple)):
                staging = os.path.dirname(col[0])
            else:
                staging = os.path.dirname(col)

            success, rootless_staging_dir = (
                self.anatomy.find_root_template_from_path(staging))
            if success:
                staging = rootless_staging_dir
            else:
                self.log.warning(
                    ("Could not find root path for remapping \"{}\"."
                     " This may cause issues on farm.").format(staging))

            self.log.info("Creating data for: {}".format(subset_name))

            app = os.environ.get("AVALON_APP", "")

            preview = False
            if app in self.aov_filter.keys():
                for aov_pattern in self.aov_filter[app]:
                    if re.match(aov_pattern, aov):
                        preview = True
                        break

            new_instance = copy(instance_data)
            new_instance["subset"] = subset_name
            new_instance["subsetGroup"] = group_name

            # create represenation
            if isinstance(col, (list, tuple)):
                files = [os.path.basename(f) for f in col]
            else:
                files = os.path.basename(col)

            rep = {
                "name": ext,
                "ext": ext,
                "files": files,
                "frameStart": int(instance_data.get("frameStartHandle")),
                "frameEnd": int(instance_data.get("frameEndHandle")),
                # If expectedFile are absolute, we need only filenames
                "stagingDir": staging,
                "fps": new_instance.get("fps"),
                "tags": ["review"] if preview else []
            }

            # support conversion from tiled to scanline
            if instance_data.get("convertToScanline"):
                self.log.info("Adding scanline conversion.")
                rep["tags"].append("toScanline")

            # poor man exclusion
            if ext in self.skip_integration_repre_list:
                rep["tags"].append("delete")

            self._solve_families(new_instance, preview)

            new_instance["representations"] = [rep]

            # if extending frames from existing version, copy files from there
            # into our destination directory
            if new_instance.get("extendFrames", False):
                self._copy_extend_frames(new_instance, rep)
            instances.append(new_instance)

        return instances
Exemplo n.º 2
0
    def _copy_extend_frames(self, instance, representation):
        """Copy existing frames from latest version.

        This will copy all existing frames from subset's latest version back
        to render directory and rename them to what renderer is expecting.

        Arguments:
            instance (pyblish.plugin.Instance): instance to get required
                data from
            representation (dict): presentation to operate on

        """
        import speedcopy

        self.log.info("Preparing to copy ...")
        start = instance.data.get("startFrame")
        end = instance.data.get("endFrame")

        # get latest version of subset
        # this will stop if subset wasn't published yet
        version = pype.api.get_latest_version(instance.data.get("asset"),
                                              instance.data.get("subset"))
        # get its files based on extension
        subset_resources = get_resources(version, representation.get("ext"))
        r_col, _ = clique.assemble(subset_resources)

        # if override remove all frames we are expecting to be rendered
        # so we'll copy only those missing from current render
        if instance.data.get("overrideExistingFrame"):
            for frame in range(start, end + 1):
                if frame not in r_col.indexes:
                    continue
                r_col.indexes.remove(frame)

        # now we need to translate published names from represenation
        # back. This is tricky, right now we'll just use same naming
        # and only switch frame numbers
        resource_files = []
        r_filename = os.path.basename(
            representation.get("files")[0])  # first file
        op = re.search(self.R_FRAME_NUMBER, r_filename)
        pre = r_filename[:op.start("frame")]
        post = r_filename[op.end("frame"):]
        assert op is not None, "padding string wasn't found"
        for frame in list(r_col):
            fn = re.search(self.R_FRAME_NUMBER, frame)
            # silencing linter as we need to compare to True, not to
            # type
            assert fn is not None, "padding string wasn't found"
            # list of tuples (source, destination)
            staging = representation.get("stagingDir")
            staging = self.anatomy.fill_roots(staging)
            resource_files.append(
                (frame,
                 os.path.join(staging, "{}{}{}".format(pre, fn.group("frame"),
                                                       post))))

        # test if destination dir exists and create it if not
        output_dir = os.path.dirname(representation.get("files")[0])
        if not os.path.isdir(output_dir):
            os.makedirs(output_dir)

        # copy files
        for source in resource_files:
            speedcopy.copy(source[0], source[1])
            self.log.info("  > {}".format(source[1]))

        self.log.info("Finished copying %i files" % len(resource_files))
Exemplo n.º 3
0
    def add_sequence(self, packager, aov_path, aov_name, package_path):
        """
        """
        from maya import cmds

        seq_dir, pattern = os.path.split(aov_path)

        self.log.info("Collecting sequence from: %s" % seq_dir)
        assert os.path.isdir(seq_dir), "Sequence dir not exists."

        # (NOTE) Did not consider frame step (byFrame)
        start_frame = self.data["startFrame"]
        end_frame = self.data["endFrame"]

        patterns = [
            clique.PATTERNS["frames"],
            clique.DIGITS_PATTERN,
        ]
        minimum_items = 1 if start_frame == end_frame else 2
        collections, _ = clique.assemble(os.listdir(seq_dir),
                                         patterns=patterns,
                                         minimum_items=minimum_items)

        assert len(collections), "Extraction failed, no sequence found."

        for sequence in collections:
            if pattern == (sequence.head + "#" * sequence.padding +
                           sequence.tail):
                break
        else:
            raise Exception("No sequence match this pattern: %s" % pattern)

        entry_fname = (sequence.head + "%%0%dd" % sequence.padding +
                       sequence.tail)

        project = self.context.data["projectDoc"]
        e_in, e_out, handles, _ = reveries.utils.get_timeline_data(project)
        camera = self.data["camera"]

        packager.add_data({
            "sequence": {
                aov_name: {
                    "imageFormat": self.data["fileExt"],
                    "fname": entry_fname,
                    "seqSrcDir": seq_dir,
                    "seqStart": list(sequence.indexes)[0],
                    "seqEnd": list(sequence.indexes)[-1],
                    "startFrame": start_frame,
                    "endFrame": end_frame,
                    "byFrameStep": self.data["byFrameStep"],
                    "edit_in": e_in,
                    "edit_out": e_out,
                    "handles": handles,
                    "focalLength": cmds.getAttr(camera + ".focalLength"),
                    "resolution": self.data["resolution"],
                    "fps": self.context.data["fps"],
                    "cameraUUID": utils.get_id(camera),
                    "renderlayer": self.data["renderlayer"],
                }
            }
        })

        for file in [entry_fname % i for i in sequence.indexes]:
            src = seq_dir + "/" + file
            dst = os.path.join(package_path, aov_name, file)
            packager.add_hardlink(src, dst)
Exemplo n.º 4
0
    def _get_representations(self, instance, exp_files):
        """Create representations for file sequences.

        This will return representations of expected files if they are not
        in hierarchy of aovs. There should be only one sequence of files for
        most cases, but if not - we create representation from each of them.

        Arguments:
            instance (pyblish.plugin.Instance): instance for which we are
                                                setting representations
            exp_files (list): list of expected files

        Returns:
            list of representations

        """
        representations = []
        collections, remainders = clique.assemble(exp_files)
        bake_render_path = instance.get("bakeRenderPath", [])

        # create representation for every collected sequence
        for collection in collections:
            ext = collection.tail.lstrip(".")
            preview = False
            # if filtered aov name is found in filename, toggle it for
            # preview video rendering
            for app in self.aov_filter.keys():
                if os.environ.get("AVALON_APP", "") == app:
                    for aov in self.aov_filter[app]:
                        if re.match(aov, list(collection)[0]):
                            preview = True
                            break

            if bake_render_path:
                preview = False

            staging = os.path.dirname(list(collection)[0])
            success, rootless_staging_dir = (
                self.anatomy.find_root_template_from_path(staging))
            if success:
                staging = rootless_staging_dir
            else:
                self.log.warning(
                    ("Could not find root path for remapping \"{}\"."
                     " This may cause issues on farm.").format(staging))

            rep = {
                "name": ext,
                "ext": ext,
                "files": [os.path.basename(f) for f in list(collection)],
                "frameStart": int(instance.get("frameStartHandle")),
                "frameEnd": int(instance.get("frameEndHandle")),
                # If expectedFile are absolute, we need only filenames
                "stagingDir": staging,
                "fps": instance.get("fps"),
                "tags": ["review"] if preview else [],
            }

            # poor man exclusion
            if ext in self.skip_integration_repre_list:
                rep["tags"].append("delete")

            if instance.get("multipartExr", False):
                rep["tags"].append("multipartExr")

            # support conversion from tiled to scanline
            if instance.get("convertToScanline"):
                self.log.info("Adding scanline conversion.")
                rep["tags"].append("toScanline")

            representations.append(rep)

            self._solve_families(instance, preview)

        # add reminders as representations
        for remainder in remainders:
            ext = remainder.split(".")[-1]

            staging = os.path.dirname(remainder)
            success, rootless_staging_dir = (
                self.anatomy.find_root_template_from_path(staging))
            if success:
                staging = rootless_staging_dir
            else:
                self.log.warning(
                    ("Could not find root path for remapping \"{}\"."
                     " This may cause issues on farm.").format(staging))

            rep = {
                "name": ext,
                "ext": ext,
                "files": os.path.basename(remainder),
                "stagingDir": os.path.dirname(remainder),
            }
            if "render" in instance.get("families"):
                rep.update({"fps": instance.get("fps"), "tags": ["review"]})
                self._solve_families(instance, True)

            if remainder in bake_render_path:
                rep.update({
                    "fps": instance.get("fps"),
                    "tags": ["review", "delete"]
                })
                # solve families with `preview` attributes
                self._solve_families(instance, True)
            representations.append(rep)

        return representations
Exemplo n.º 5
0
    def load(self, context, name, namespace, data):
        directory = os.path.dirname(self.fname)
        from avalon.vendor import clique

        pattern = clique.PATTERNS["frames"]
        files = os.listdir(directory)
        collections, remainder = clique.assemble(files,
                                                 patterns=[pattern],
                                                 minimum_items=1)

        if not remainder:
            seqeunce = collections[0]
            first_image = list(seqeunce)[0]
            # start = min(collections)
            # end = max(collections)
            #
            # range = (padding % start) + '-' + (padding % end)
            # filename = re.sub('%[0-9]*d', range, filename)
        else:
            first_image = self.fname
        filepath = os.path.normpath(os.path.join(directory, first_image))

        self.log.info("Opening : {}".format(filepath))

        fps = context.get('project', {}).get('data', {}).get('fps', 24)

        cmd = []
        # DJV path
        cmd.append(os.path.normpath(self.djv_path))
        # DJV Options Start ##############################################
        '''layer name'''
        # cmd.append('-file_layer (value)')
        ''' Proxy scale: 1/2, 1/4, 1/8'''
        # cmd.append('-file_proxy 1/2')
        ''' Cache: True, False.'''
        cmd.append('-file_cache True')
        ''' Start in full screen '''
        # cmd.append('-window_fullscreen')
        ''' Toolbar controls: False, True.'''
        # cmd.append("-window_toolbar False")
        ''' Window controls: False, True.'''
        # cmd.append("-window_playbar False")
        ''' Grid overlay: None, 1x1, 10x10, 100x100.'''
        # cmd.append("-view_grid None")
        ''' Heads up display: True, False.'''
        # cmd.append("-view_hud True")
        ''' Playback: Stop, Forward, Reverse.'''
        cmd.append("-playback Forward")
        ''' Frame.'''
        # cmd.append("-playback_frame (value)")
        cmd.append("-playback_speed " + str(fps))
        ''' Timer: Sleep, Timeout. Value: Sleep.'''
        # cmd.append("-playback_timer (value)")
        ''' Timer resolution (seconds): 0.001.'''
        # cmd.append("-playback_timer_resolution (value)")
        ''' Time units: Timecode, Frames.'''
        cmd.append("-time_units Frames")
        # DJV Options End ################################################

        # PATH TO COMPONENT
        cmd.append(os.path.normpath(filepath))

        # Run DJV with these commands
        subprocess.Popen(' '.join(cmd))