Пример #1
0
    def update_sequences_categories(self):
        """
        Updates current sequences categories
        """

        from artellapipe.widgets import sequence as sequence_widgets

        for btn in self._sequences_btn_grp.buttons():
            self._sequences_btn_grp.removeButton(btn)

        qtutils.clear_layout(self._sequences_menu_layout)

        all_sequences_categories = ['All']
        all_sequences = artellapipe.SequencesMgr().find_all_sequences()
        if all_sequences:
            sequence_names = [
                sequence.get_name() for sequence in all_sequences
            ]
            all_sequences_categories.extend(sequence_names)

        for sequence_name in all_sequences_categories:
            sequence = artellapipe.SequencesMgr().find_sequence(sequence_name)
            new_btn = sequence_widgets.SequenceCategoryButton(
                sequence_name, sequence)
            new_btn.setMinimumWidth(
                QFontMetrics(new_btn.font()).width(sequence_name) + 10)
            new_btn.setCheckable(True)
            self._sequences_menu_layout.addWidget(new_btn)
            self._sequences_btn_grp.addButton(new_btn)
            if sequence_name == 'All':
                new_btn.setIcon(tpDcc.ResourcesMgr().icon('home'))
                new_btn.setChecked(True)
            new_btn.toggled.connect(
                partial(self._on_change_sequence, sequence_name))
Пример #2
0
    def get_path(self):
        """
        Implements abstract get_path function
        Returns the path of the sequence
        :return: str
        """

        path_template_name = artellapipe.SequencesMgr().config.get('data', 'path_template_name')
        template = artellapipe.FilesMgr().get_template(path_template_name)
        if not template:
            LOGGER.warning(
                'Impossible to retrieve sequence path because template "{}" is not in configuration file'.format(
                    path_template_name))
            return None

        template_dict = {
            'project_id': self._project.id,
            'project_id_number': self._project.id_number,
            'sequence_name': self.get_name()
        }
        sequence_path = template.format(template_dict)

        if not sequence_path:
            LOGGER.warning(
                'Impossible to retrieve sequence path from template: "{} | {} | {}"'.format(
                    template.name, template.pattern, template_dict))
            return None

        sequence_path = artellapipe.FilesMgr().prefix_path_with_project_path(sequence_path)

        return sequence_path
Пример #3
0
    def change_sequence(self, sequence_name=None):
        """
        Changes the sequence of the shots that are being showed by the viewer
        :param sequence_name: str
        """

        if not sequence_name:
            sequence_name = 'All'

        all_sequences_names = artellapipe.SequencesMgr().get_sequence_names()
        if sequence_name != 'All' and sequence_name not in all_sequences_names:
            LOGGER.warning(
                'Sequence {} not found for current project {}'.format(
                    sequence_name, self._project.name.title()))
            sequence_name = 'All'

        self.clear()

        new_shots = list()
        for new_shot in reversed(self._shots):
            if sequence_name == 'All':
                new_shot.setVisible(True)
                new_shots.insert(0, new_shot)
            else:
                if new_shot.shot.get_sequence() == sequence_name:
                    new_shot.setVisible(True)
                    new_shots.insert(0, new_shot)
                else:
                    new_shot.setVisible(False)
                    new_shots.append(new_shot)

        for new_shot in new_shots:
            self._add_widget(new_shot)
Пример #4
0
    def __init__(self, sequence, text=None, parent=None):
        self._sequence = sequence
        self._text = text or artellapipe.SequencesMgr(
        ).get_default_sequence_name()

        super(ArtellaSequenceWidget, self).__init__(parent=parent)

        self._init()
Пример #5
0
    def get_latest_published_versions(self):
        """
        Implements base ArtellaFile get_path function
        Returns latest published version of file
        :return: str
        """

        file_path = self.get_path()
        return artellapipe.SequencesMgr().get_latest_published_versions(
            file_path, file_type=self.FILE_TYPE)
Пример #6
0
    def update_cache(self, force=False):
        """
        Updates internal cache with the current sequences located in Artella server
        """

        if self._cache and not force:
            return self._cache

        python.clear_list(self._sequences)
        return artellapipe.SequencesMgr().find_all_sequences(
            force_update=force)
Пример #7
0
    def get_thumbnail_path(self):
        """
        Implements abstract get_path function
        Returns the path where sequence thumbnail is located
        :return: str
        """

        thumb_attr = artellapipe.SequencesMgr().config.get('data', 'thumb_attribute')
        thumb_path = self._sequence_data.get(thumb_attr, None)

        return thumb_path
Пример #8
0
    def get_name(self):
        """
        Implements abstract get_name function
        Returns the name of the sequence
        :return: str
        """

        name_attr = artellapipe.SequencesMgr().config.get('data', 'name_attribute')
        sequence_name = self._sequence_data.get(name_attr, None)
        if not sequence_name:
            LOGGER.warning(
                'Impossible to retrieve sequence name because sequence data does not contains "{}" attribute.'
                '\nSequence Data: {}'.format(name_attr, self._sequence_data))
            return None

        return sequence_name.rstrip()
    def _on_sequence_clicked(self, sequence_widget):
        if not sequence_widget:
            return
        sequence = sequence_widget.sequence
        if not sequence:
            return

        sequence_name = sequence.get_name()
        sequence = artellapipe.SequencesMgr().find_sequence(sequence_name)
        if not sequence:
            LOGGER.warning('No Sequence found with name "{}" in current project'.format(sequence_name))
            return
        valid_open = sequence.open_master_layout()
        if not valid_open:
            return

        self._stack.slide_in_index(1)
Пример #10
0
    def get_file_type(self, file_type, extension=None):
        """
        Returns sequence file object of the current sequence and given file type
        :param file_type: str
        :param extension: str
        :return: ArtellaAssetType
        """

        if file_type not in self.FILES:
            return None

        sequence_file_class = artellapipe.SequencesMgr().get_sequence_file(file_type=file_type, extension=extension)
        if not sequence_file_class:
            LOGGER.warning(
                'File Type: {} | {} not registered in current project!'.format(file_type, extension))
            return

        return sequence_file_class(sequence=self)
Пример #11
0
    def process(self, instance):

        if not instance.data.get('publish', False):
            return False

        project = instance.data.get('project', None)
        assert project, 'No valid project defined in current instance: {}'.format(
            instance)

        shots_config = tp.ConfigsMgr().get_config(
            config_name='artellapipe-shots')

        assert shots_config, 'No valid shots configuration file found in current instance: {}'.format(
            instance)

        shot_node = instance.data.get('shot', None)
        assert shot_node, 'No valid shot node found in current instance: {}'.format(
            instance)

        # Retrieve master layout file path
        sequence_name = shot_node.get_sequence()
        assert sequence_name, 'No valid sequence name found linked to current instance: {}'.format(
            instance)
        sequence = artellapipe.SequencesMgr().find_sequence(sequence_name)
        assert sequence, 'No valid sequence found linked to current instance: {}'.format(
            instance)
        sequence_file_type = sequence.get_file_type('master')
        assert sequence, 'File type "master" not found in current project'
        sequence_file_type.open_file()

        shot_name = shot_node.get_name()
        assert tp.Dcc.object_exists(
            shot_name), 'No valid shot found in current instance: {}'.format(
                instance)

        all_shots = artellapipe.ShotsMgr().find_all_shots()
        assert all_shots, 'No shots defined in current project!'

        start_frame = shots_config.get('start_frame', default=101)

        found = False
        for shot in all_shots:
            if shot.get_name() == shot_name:
                found = True
                break
        assert found, 'Shot with name: "{}" not found in current sequence!'.format(
            shot_name)

        new_version = bool(
            util.strtobool(
                os.environ.get(
                    '{}_SEQUENCES_PUBLISHER_NEW_VERSION'.format(
                        project.get_clean_name().upper()), 'False')))
        base_comment = '{} | {} | Sequences Publisher > Shot "{}" Export'.format(
            timedate.get_current_time(), osplatform.get_user(True), shot_name)
        comment = instance.data.get('comment', None)
        if comment:
            base_comment = '{} | {}'.format(base_comment, comment)

        valid_export = artellapipe.ShotsMgr().export_shot(
            shot_name,
            start_frame=start_frame,
            new_version=new_version,
            comment=base_comment)
        assert valid_export, 'Shot with name "{}" was not exported successfully!'.format(
            shot_name)

        return True
Пример #12
0
    def _export_file(self, file_path, *args, **kwargs):

        # Retrieve master layout file path
        sequence_name = self._shot.get_sequence()
        if not sequence_name:
            LOGGER.warning(
                'Impossible to export shot file "{}" because is not linked to any sequence!'
                .format(self._shot.get_name()))
            return None
        sequence = artellapipe.SequencesMgr().find_sequence(sequence_name)
        if not sequence:
            LOGGER.warning(
                'Impossible to export shot file "{}" because sequence "{}" was not found in current project'
                .format(self._shot.get_name(), sequence_name))
            return None
        sequence_file_type = sequence.get_file_type('master')
        if not sequence_file_type:
            LOGGER.warning(
                'Impossible to export shot file "{}" because sequence file type "master" is not defined '
                'in current project'.format(self._shot.get_name()))
            return None

        master_file_path = sequence_file_type.get_file()
        if not master_file_path or not os.path.exists(master_file_path):
            LOGGER.warning(
                'Impossible to export shot file "{}" because master layout file "{}" does not exists!'
                .format(self._shot.get_name(), master_file_path))
            return None

        sequence_file_type.open_file()

        master_locked = False
        if os.path.isfile(master_file_path):
            valid_lock = artellapipe.FilesMgr().lock_file(master_file_path)
            master_locked = True
            if not valid_lock:
                LOGGER.warning('Was not possible to lock file: {}'.format(
                    master_file_path))
                return False

        sequence_file_type.open_file()

        file_path_name = os.path.basename(file_path)
        file_path_dir = os.path.dirname(file_path)
        if not os.path.isdir(file_path_dir):
            LOGGER.info('Creating export file path directory: {}'.format(
                file_path_dir))
            try:
                os.makedirs(file_path_dir)
            except Exception as exc:
                LOGGER.error(
                    'Error while creating export path directory: "{}" | {} | {}'
                    .format(file_path_dir, exc, traceback.format_exc()))
                return None

        try:
            if os.path.isfile(file_path):
                fileio.delete_file(file_path_name, file_path_dir)
            fileio.copy_file(master_file_path, file_path)
            LOGGER.info('Created new Shot File: {}'.format(file_path))
        except Exception as exc:
            LOGGER.error(
                'Error while copying shot file "{}" from master layout file "{}" | {} | {}'
                .format(file_path, master_file_path, exc,
                        traceback.format_exc()))
            return None

        if os.path.isfile(file_path):
            valid_lock = artellapipe.FilesMgr().lock_file(file_path)
            if not valid_lock:
                LOGGER.warning(
                    'Was not possible to lock file: {}'.format(file_path))

        tp.Dcc.open_file(file_path)

        shot_anim_file_type = self._shot.get_file_type('shot_layout_anim')
        if not shot_anim_file_type:
            LOGGER.warning(
                'Impossible to export shot "{}" because shot file type "shot_layout_anim" is not defined '
                'in current project'.format(self._shot.get_name()))
            return None

        start_frame = kwargs.get('start_frame', 101)
        valid_anim_export = shot_anim_file_type.export_file(
            start_frame=start_frame)
        if not valid_anim_export:
            LOGGER.warning('Layout Animation Export was not exported in file!')
            return None

        if master_locked:
            artellapipe.FilesMgr().unlock_file(master_file_path,
                                               warn_user=False)

        try:
            shot_anim_file_path = shot_anim_file_type.get_file()
            shot_anim_file_path_name = os.path.basename(shot_anim_file_path)
            shot_anim_file_path_directory = os.path.dirname(
                shot_anim_file_path)
            fileio.delete_file(shot_anim_file_path_name,
                               shot_anim_file_path_directory)
        except Exception as exc:
            LOGGER.warning(
                'Was not possible to remove Shot Layout Animation File: "{}" | {} | {}. Remove it manually'
                .format(shot_anim_file_path, exc, traceback.format_exc()))

        try:
            tp.Dcc.convert_fraction_keys_to_whole_keys(
                consider_selected_range=False)
        except Exception as exc:
            LOGGER.warning(
                'Could not resolve any keyframes on fractions of a frame: {} | {}'
                .format(exc, traceback.format_exc()))

        # Clean shot nodes that are not valid anymore
        all_shots = tp.Dcc.all_scene_shots()
        shots_to_delete = [
            shot for shot in all_shots if shot != self.get_name()
        ]
        tp.Dcc.delete_object(shots_to_delete)

        # Update timeline
        start_offset = self._shot.get_start_frame() - start_frame
        start_frame = self._shot.get_start_frame() - start_offset
        end_frame = self._shot.get_end_frame() - start_offset
        tp.Dcc.set_active_frame_range(start_frame, end_frame)

        # Update shot attributes
        self._shot.set_start_frame(start_frame)
        self._shot.set_end_frame(end_frame)

        # Remove cameras that does not belong to the shot
        camera_name = self._shot.get_camera()
        root_node = None
        all_cameras = tp.Dcc.get_all_cameras(full_path=True) or list()
        for camera in all_cameras:
            if not camera:
                continue
            base_name = tp.Dcc.node_short_name(camera)
            if base_name == camera_name:
                root_node = camera.split('|')[1]
                break
        if root_node:
            for camera in all_cameras:
                if not camera or not tp.Dcc.object_exists(camera):
                    continue
                base_name = tp.Dcc.node_short_name(camera)
                if base_name == camera_name:
                    continue
                reps = 0
                node_to_delete = camera
                camera_parent = tp.Dcc.node_parent(camera)
                while camera_parent != '|{}'.format(root_node) and reps < 10:
                    node_to_delete = camera_parent
                    camera_parent = tp.Dcc.node_parent(node_to_delete)
                    reps += 1
                tp.Dcc.delete_object(node_to_delete)
        else:
            for camera in all_cameras:
                if not camera:
                    continue
                base_name = tp.Dcc.node_short_name(camera)
                if base_name == camera_name:
                    continue
                tp.Dcc.delete_object(camera)

        # Force look through to shot camera
        tp.Dcc.look_through_camera(camera_name)

        # Save scene
        tp.Dcc.save_current_scene(force=True)
        if tp.is_maya():
            from tpDcc.dccs.maya.core import helpers
            helpers.clean_student_line()

        return True