Exemple #1
0
def version_updater(logging_level=logging.WARNING):
    """helper function for version_updater UI for Maya
    """
    # connect to db
    do_db_setup()

    # use PySide for Maya 2014
    import pymel
    try:
        if pymel.versions.current() >= pymel.versions.v2014:
            from anima import ui
            ui.SET_PYSIDE()
    except AttributeError:
        pass

    from anima.ui import version_updater, models
    from anima.env import mayaEnv
    reload(mayaEnv)
    reload(version_updater)
    reload(models)
    m = Maya()
    m.name = "Maya" + str(pymel.versions.current())[0:4]

    logger.setLevel(logging_level)

    # generate a reference_resolution
    version_updater.UI(environment=m)
Exemple #2
0
    def from_edl(self, path):
        """Parses EDL file and returns a Sequence instance which reflects the
        whole time line hierarchy.

        :param path: The path of the XML file
        :return: :class:`.Sequence`
        """
        if not isinstance(path, str):
            raise TypeError(
                'path argument in %s.from_edl should be a string, not %s' %
                (self.__class__.__name__, path.__class__.__name__)
            )

        from anima.env.mayaEnv import Maya
        m = Maya()
        fps = m.get_fps()

        import edl
        p = edl.Parser(str(fps))
        with open(path) as f:
            l = p.parse(f)

        seq = Sequence()
        seq.from_edl(l)

        self.from_seq(seq)
Exemple #3
0
def check_if_previous_version_references():
    """check if a previous version of the same task is referenced to the scene
    """
    from anima.env.mayaEnv import Maya
    m = Maya()
    ver = m.get_current_version()

    if ver is None:
        return

    same_version_references = []
    for ref in pm.listReferences():  # check only 1st level references
        ref_version = m.get_version_from_full_path(ref.path)
        if ref_version:
            if ref_version.task == ver.task \
               and ref_version.take_name == ver.take_name:
                same_version_references.append(ref)

    if len(same_version_references):
        print('The following nodes are references to an older version of this '
              'scene')
        print('\n'.join(
            map(lambda x: x.refNode.name(), same_version_references)))
        raise PublishError(
            'The current scene contains a <b>reference</b> to a<br>'
            '<b>previous version</b> of itself.<br><br>'
            'Please remove it!!!')
Exemple #4
0
def check_if_previous_version_references():
    """check if a previous version of the same task is referenced to the scene
    """
    from anima.env.mayaEnv import Maya
    m = Maya()
    ver = m.get_current_version()

    if ver is None:
        return

    same_version_references = []
    for ref in pm.listReferences():  # check only 1st level references
        ref_version = m.get_version_from_full_path(ref.path)
        if ref_version:
            if ref_version.task == ver.task \
               and ref_version.take_name == ver.take_name:
                same_version_references.append(ref)

    if len(same_version_references):
        print('The following nodes are references to an older version of this '
              'scene')
        print(
            '\n'.join(map(lambda x: x.refNode.name(), same_version_references))
        )
        raise PublishError(
            'The current scene contains a <b>reference</b> to a<br>'
            '<b>previous version</b> of itself.<br><br>'
            'Please remove it!!!'
        )
Exemple #5
0
    def archive_current_scene(cls):
        """archives the current scene
        """
        # before doing anything ask it
        response = pm.confirmDialog(
            title='Do Archive?',
            message='This will create a ZIP file containing\n'
            'the current scene and all its references\n'
            '\n'
            'Is that OK?',
            button=['Yes', 'No'],
            defaultButton='No',
            cancelButton='No',
            dismissString='No')
        if response == 'No':
            return

        import os
        import shutil
        import anima
        from anima.env.mayaEnv import Maya
        from anima.env.mayaEnv.archive import Archiver
        m_env = Maya()
        version = m_env.get_current_version()
        if version:
            path = version.absolute_full_path
            arch = Archiver()
            task = version.task
            if False:
                from stalker import Version, Task
                assert (isinstance(version, Version))
                assert (isinstance(task, Task))
            # project_name = version.nice_name
            project_name = os.path.splitext(
                os.path.basename(version.absolute_full_path))[0]
            project_path = arch.flatten(path, project_name=project_name)

            # append link file
            stalker_link_file_path = \
                os.path.join(project_path, 'scenes/stalker_links.txt')
            version_upload_link = '%s/tasks/%s/versions/list' % (
                anima.defaults.stalker_server_external_address, task.id)
            request_review_link = '%s/tasks/%s/view' % (
                anima.defaults.stalker_server_external_address, task.id)
            with open(stalker_link_file_path, 'w+') as f:
                f.write("Version Upload Link: %s\n"
                        "Request Review Link: %s\n" %
                        (version_upload_link, request_review_link))
            zip_path = arch.archive(project_path)
            new_zip_path = os.path.join(version.absolute_path,
                                        os.path.basename(zip_path))

            # move the zip right beside the original version file
            shutil.move(zip_path, new_zip_path)

            # open the zip file in browser
            from anima.utils import open_browser_in_location
            open_browser_in_location(new_zip_path)
Exemple #6
0
 def archive_current_scene(cls):
     """archives the current scene
     """
     from anima.env.mayaEnv import Maya
     from anima.env.mayaEnv.archive import Archiver
     from anima.utils.archive import archive_current_scene
     m_env = Maya()
     version = m_env.get_current_version()
     archiver = Archiver()
     archive_current_scene(version, archiver)
Exemple #7
0
 def playblast_on_farm(cls):
     """Submits playblast creation jobs to Afanasy
     """
     from anima.env.mayaEnv import Maya, afanasy_publisher
     m = Maya()
     v = m.get_current_version()
     if v:
         afanasy_publisher.submit_playblast_job(
             v.absolute_full_path, project_code=v.task.project.code)
     else:
         raise RuntimeError("This scene is not a Stalker version!")
Exemple #8
0
    def repr(self):
        """the representation name of the related version
        """
        from anima.env.mayaEnv import Maya
        m = Maya()
        v = m.get_version_from_full_path(self.path)

        if v is None:
            return None

        rep = Representation(version=v)
        return rep.repr
Exemple #9
0
    def __init__(self):
        self.mEnv = Maya()

        self.width = 265
        self.height = 300
        self.row_spacing = 3
        self.window = None
        self.window_name = 'Previz_Window'
        self.window_title = "Previz Tools v%s" % anima.__version__

        self.edl_checkBox = None
        self.mxf_checkBox = None
Exemple #10
0
    def __init__(self, version=None):
        local_session = LocalSession()
        self.logged_in_user = local_session.logged_in_user

        if not self.logged_in_user:
            raise RuntimeError('Please login first!')

        from anima.env.mayaEnv import Maya
        self.maya_env = Maya()

        self.base_take_name = None
        self.version = version
Exemple #11
0
    def get_base(self):
        """returns the base version instance
        """
        from anima.env.mayaEnv import Maya
        m = Maya()
        v = m.get_version_from_full_path(self.path)

        if v is None:
            return True

        rep = Representation(version=v)
        return rep.find(rep.base_repr_name)
Exemple #12
0
    def is_base(self):
        """returns True or False depending to if this is the base
        representation for this reference
        """
        from anima.env.mayaEnv import Maya
        m = Maya()
        v = m.get_version_from_full_path(self.path)

        if v is None:
            return True

        rep = Representation(version=v)
        return rep.is_base()
Exemple #13
0
    def has_repr(self, repr_name):
        """checks if the reference has the given representation

        :param str repr_name: The name of the desired representation
        :return:
        """
        from anima.env.mayaEnv import Maya
        m = Maya()
        v = m.get_version_from_full_path(self.path)

        if v is None:
            return False

        rep = Representation(version=v)
        return rep.has_repr(repr_name)
Exemple #14
0
    def is_repr(self, repr_name):
        """returns True or False depending to if this is the requested repr

        :param str repr_name: The representation name
        :return:
        """
        from anima.env.mayaEnv import Maya
        m = Maya()
        v = m.get_version_from_full_path(self.path)

        if v is None:
            return False

        rep = Representation(version=v)
        return rep.is_repr(repr_name=repr_name)
Exemple #15
0
    def list_all_repr(self):
        """Returns a list of strings representing all the representation names
        of this FileReference

        :return: list of str
        """
        from anima.env.mayaEnv import Maya
        m = Maya()
        v = m.get_version_from_full_path(self.path)

        if v is None:
            return []

        rep = Representation(version=v)
        return rep.list_all()
Exemple #16
0
    def find_repr(self, repr_name):
        """Finds the representation with the given repr_name.

        :param str repr_name: The desired repr name
        :return: :class:`.Version`
        """
        from anima.env.mayaEnv import Maya
        m = Maya()
        v = m.get_version_from_full_path(self.path)

        if v is None:
            return

        rep = Representation(version=v)
        rep_v = rep.find(repr_name)

        return rep_v
Exemple #17
0
    def __init__(self):
        self.mEnv = Maya()

        self.width = 265
        self.height = 300
        self.row_spacing = 3
        self.window = None
        self.window_name = 'Previz_Window'
        self.window_title = "Previz Tools v%s" % anima.__version__

        self.edl_checkBox = None
        self.mxf_checkBox = None
Exemple #18
0
def version_creator(logging_level=logging.WARNING):
    """Helper function for version_creator UI for Maya
    """
    # connect to db
    do_db_setup()

    # use PySide for Maya 2014
    set_qt_lib()

    from anima.ui import version_creator, models
    from anima.env import mayaEnv
    reload(version_creator)
    reload(models)
    reload(mayaEnv)
    m = Maya()

    import pymel
    m.name = "Maya%s" % str(pymel.versions.current())[0:4]

    logger.setLevel(logging_level)

    version_creator.UI(environment=m)
Exemple #19
0
def version_updater(logging_level=logging.WARNING):
    """helper function for version_updater UI for Maya
    """
    # connect to db
    do_db_setup()

    # set Qt lib
    set_qt_lib()

    from anima.ui import version_updater, models
    from anima.env import mayaEnv
    reload(mayaEnv)
    reload(version_updater)
    reload(models)
    m = Maya()
    import pymel
    m.name = "Maya" + str(pymel.versions.current())[0:4]

    logger.setLevel(logging_level)

    # generate a reference_resolution
    version_updater.UI(environment=m)
Exemple #20
0
def version_updater(logging_level=logging.WARNING):
    """helper function for version_updater UI for Maya
    """
    # connect to db
    do_db_setup()

    # set Qt lib
    set_qt_lib()

    from anima.ui import version_updater, models
    from anima.env import mayaEnv
    reload(mayaEnv)
    reload(version_updater)
    reload(models)
    m = Maya()
    import pymel
    m.name = "Maya" + str(pymel.versions.current())[0:4]

    logger.setLevel(logging_level)

    # generate a reference_resolution
    version_updater.UI(environment=m)
Exemple #21
0
def version_creator(logging_level=logging.WARNING):
    """Helper function for version_creator UI for Maya
    """
    # connect to db
    do_db_setup()

    # use PySide for Maya 2014
    set_qt_lib()

    from anima.ui import version_creator, models
    from anima.env import mayaEnv
    reload(version_creator)
    reload(models)
    reload(mayaEnv)
    m = Maya()

    import pymel
    m.name = "Maya%s" % str(pymel.versions.current())[0:4]

    logger.setLevel(logging_level)

    version_creator.UI(environment=m)
Exemple #22
0
    def generate_repr_of_all_references(cls,
                                        generate_gpu=True,
                                        generate_ass=True,
                                        generate_rs=True,
                                        skip_existing=False):
        """generates all representations of all references of this scene
        """
        from anima.ui.progress_dialog import ProgressDialogManager
        from anima.env.mayaEnv import Maya, repr_tools, auxiliary
        reload(auxiliary)
        reload(repr_tools)

        paths_visited = []
        versions_to_visit = []
        versions_cannot_be_published = []

        # generate a sorted version list
        # and visit each reference only once
        from anima.env.mayaEnv import MayaMainProgressBarWrapper
        wrp = MayaMainProgressBarWrapper()
        pdm = ProgressDialogManager(dialog=wrp)

        use_progress_window = False
        if not pm.general.about(batch=1):
            use_progress_window = True

        all_refs = pm.listReferences(recursive=True)

        pdm.use_ui = use_progress_window
        caller = pdm.register(len(all_refs), 'List References')

        for ref in reversed(all_refs):
            ref_path = str(ref.path)
            caller.step(message=ref_path)
            if ref_path not in paths_visited:
                v = ref.version
                if v is not None:
                    paths_visited.append(ref_path)
                    versions_to_visit.append(v)

        response = pm.confirmDialog(
            title='Do Create Representations?',
            message='Create all Repr. for all %s FileReferences?'
                    % len(versions_to_visit),
            button=['Yes', 'No'],
            defaultButton='No',
            cancelButton='No',
            dismissString='No'
        )
        if response == 'No':
            return

        # register a new caller
        caller = pdm.register(max_iteration=len(versions_to_visit),
                              title='Generate Reprs')

        m_env = Maya()
        source_version = m_env.get_current_version()
        gen = repr_tools.RepresentationGenerator()

        # open each version
        from stalker import Version
        for v in versions_to_visit:
            local_generate_gpu = generate_gpu
            local_generate_ass = generate_ass
            local_generate_rs = generate_rs

            # check if this is a repr
            if '@' in v.take_name:
                # use the parent
                v = v.parent
                if not v:
                    continue

            if skip_existing:
                # check if there is a GPU or ASS repr
                # generated from this version
                child_versions = Version.query.filter(Version.parent == v).all()
                for cv in child_versions:
                    if local_generate_gpu is True and '@GPU' in cv.take_name:
                        local_generate_gpu = False

                    if local_generate_ass is True and '@ASS' in cv.take_name:
                        local_generate_ass = False

                    if local_generate_rs is True and '@RS' in cv.take_name:
                        local_generate_rs = False

            gen.version = v
            # generate representations
            if local_generate_gpu:
                try:
                    gen.generate_gpu()
                except RuntimeError:
                    if v not in versions_cannot_be_published:
                        versions_cannot_be_published.append(v)

            if local_generate_ass:
                try:
                    gen.generate_ass()
                except RuntimeError:
                    if v not in versions_cannot_be_published:
                        versions_cannot_be_published.append(v)

            if local_generate_rs:
                try:
                    gen.generate_rs()
                except RuntimeError:
                    if v not in versions_cannot_be_published:
                        versions_cannot_be_published.append(v)

            caller.step()

        # now open the source version again
        m_env.open(source_version, force=True, skip_update_check=True)

        # and generate representation for the source
        gen.version = source_version

        # generate representations
        if not versions_cannot_be_published:
            if generate_gpu:
                gen.generate_gpu()
            if generate_ass:
                gen.generate_ass()
            if generate_rs:
                gen.generate_rs()
        else:
            pm.confirmDialog(
                title='Error',
                message='The following versions can not be published '
                        '(check script editor):\n\n%s' % (
                            '\n'.join(
                                map(lambda x: x.nice_name,
                                    versions_cannot_be_published)
                            )
                        ),
                button=['OK'],
                defaultButton='OK',
                cancelButton='OK',
                dismissString='OK'
            )

            pm.error(
                '\n'.join(
                    map(lambda x: x.absolute_full_path,
                        versions_cannot_be_published)
                )
            )
Exemple #23
0
    def generate_repr_of_scene(cls,
                               generate_gpu=True,
                               generate_ass=True,
                               generate_rs=True,
                               skip_existing=False):
        """generates desired representations of this scene
        """
        from anima.ui.progress_dialog import ProgressDialogManager
        from anima.env.mayaEnv import Maya, repr_tools, auxiliary
        reload(auxiliary)
        reload(repr_tools)

        response = pm.confirmDialog(
            title='Do Create Representations?',
            message='Create all Repr. for this scene?',
            button=['Yes', 'No'],
            defaultButton='No',
            cancelButton='No',
            dismissString='No'
        )
        if response == 'No':
            return

        # register a new caller
        from anima.env.mayaEnv import MayaMainProgressBarWrapper
        wrp = MayaMainProgressBarWrapper()
        pdm = ProgressDialogManager(dialog=wrp)

        m_env = Maya()
        source_version = m_env.get_current_version()
        gen = repr_tools.RepresentationGenerator()

        # open each version
        from stalker import Version
        if skip_existing:
            # check if there is a GPU or ASS repr
            # generated from this version
            child_versions = \
                Version.query.filter(Version.parent == source_version).all()
            for cv in child_versions:
                if generate_gpu is True and '@GPU' in cv.take_name:
                    generate_gpu = False

                if generate_ass is True and '@ASS' in cv.take_name:
                    generate_ass = False

                if generate_rs is True and '@RS' in cv.take_name:
                    generate_rs = False

        total_number_of_reprs = generate_gpu + generate_ass + generate_rs
        caller = pdm.register(total_number_of_reprs, title='Generate Reprs')

        gen.version = source_version
        # generate representations
        if generate_gpu:
            gen.generate_gpu()
            caller.step()

        if generate_ass:
            gen.generate_ass()
            caller.step()

        if generate_rs:
            gen.generate_rs()
            caller.step()

        # now open the source version again
        m_env.open(source_version, force=True, skip_update_check=True)
Exemple #24
0
class RepresentationGenerator(object):
    """Generates different representations of the current scene
    """

    def __init__(self, version=None):
        local_session = LocalSession()
        self.logged_in_user = local_session.logged_in_user

        if not self.logged_in_user:
            raise RuntimeError('Please login first!')

        from anima.env.mayaEnv import Maya
        self.maya_env = Maya()

        self.base_take_name = None
        self.version = version

    @classmethod
    def get_local_root_nodes(cls):
        """returns the root nodes that are not referenced
        """
        return [node for node in auxiliary.get_root_nodes()
                if node.referenceFile() is None]

    def get_latest_repr_version(self, take_name):
        """returns the latest published version or creates a new version

        :param str take_name: The take_name
        :return:
        """
        from stalker import Version

        # filter to get the latest published version
        v = Version.query\
            .filter(Version.task == self.version.task)\
            .filter(Version.take_name == take_name)\
            .filter(Version.is_published == True)\
            .order_by(Version.version_number.desc())\
            .first()

        if v is None:
            # create a new version
            v = Version(
                created_by=self.logged_in_user,
                task=self.version.task,
                take_name=take_name
            )
            v.is_published = True
        else:
            # change updated by
            v.updated_by = self.logged_in_user

        return v

    @classmethod
    def is_model_task(cls, task):
        """checks if the given task is a model task

        :param task: A Stalker Task instance
        """
        task_type = task.type
        if task_type:
            # check the task type name
            if task_type.name.lower() in ['model']:
                return True
        else:
            # check the task name
            if task.name.lower() in ['model']:
                return True

        # if we came here it must not be a model task
        return False

    @classmethod
    def is_look_dev_task(cls, task):
        """checks if the given task is a look development task

        :param task: A Stalker Task instance
        """
        task_type = task.type
        if task_type:
            # check the task type name
            if task_type.name.lower() in ['look development']:
                return True
        else:
            # check the task name
            if task.name.lower() in ['look_dev', 'lookdev', 'look dev']:
                return True

        # if we came here it must not be a look dev task task
        return False

    @classmethod
    def is_scene_assembly_task(cls, task):
        """checks if the given task is a scene assembly task

        :param task: A Stalker Task instance
        """
        task_type = task.type
        if task_type:
            # check the task type name
            if task_type.name.lower() in ['scene assembly']:
                return True
        else:
            # check the task name
            if task.name.lower() in ['scene assembly']:
                return True

        # if we came here it must not be a scene assembly task task
        return False

    @classmethod
    def is_vegetation_task(cls, task):
        """checks if the given task is a vegetation task

        :param task: A Stalker Task instance
        """
        task_type = task.type
        if task_type:
            # check the task type name
            if task_type.name.lower() in ['vegetation']:
                return True
        else:
            # check the task name
            if task.name.lower() in ['vegetation']:
                return True

        # if we came here it must not be a vegetation task task
        return False

    @classmethod
    def is_exterior_or_interior_task(cls, task):
        """checks if the given task is the first Layout task of an
        Exterior or Interior task.

        :param task: a stalker.task
        :return:
        """

        if task.type and task.type.name.lower() == 'layout':
            parent = task.parent
            if task.name.lower() == 'hires':
                if parent and parent.parent and parent.parent.type \
                   and parent.parent.type.name.lower() in ['exterior', 'interior']:
                    return True
            elif task.name.lower() == 'layout':
                if parent and parent.type \
                   and parent.type.name.lower() in ['exterior', 'interior']:
                    return True

        return False

    def _validate_version(self, version):
        """validates the given version value

        :param version: A stalker.model.version.Version instance
        :return:
        """
        if not version:
            raise RuntimeError(
                'Please supply a valid Stalker Version object!'
            )

        from stalker import Version
        if not isinstance(version, Version):
            raise TypeError(
                'version should be a stalker.models.version.Version instance'
            )

        r = Representation(version=version)

        self.base_take_name = r.get_base_take_name(version)
        if not r.is_base():
            raise RuntimeError(
                'This is not a Base take for this representation series, '
                'please open the base (%s) take!!!' % self.base_take_name
            )

        return version

    def open_version(self, version=None):
        """Opens the given version

        :param version: A stalker.models.version.Version instance
        :return:
        """
        current_v = self.maya_env.get_current_version()
        if current_v is not version:
            self.maya_env.open(version, force=True,
                               skip_update_check=True,
                               reference_depth=3)

    @classmethod
    def make_unique(cls, filename, force=True):
        """Generates a unique filename if the file already exists

        :param filename:
        :return:
        """
        import uuid

        def generate_filename():
            random_part = uuid.uuid4().hex[-4:]
            data = os.path.splitext(filename)
            return '%s_%s%s' % (data[0], random_part, data[1])

        if not force:
            if os.path.exists(filename):
                new_filename = generate_filename()
                while os.path.exists(new_filename):
                    new_filename = generate_filename()
                return new_filename
            else:
                return filename
        else:
            return generate_filename()

    def generate_all(self):
        """generates all representations at once
        """
        self.generate_gpu()
        self.generate_ass()

    def generate_bbox(self):
        """generates the BBox representation of the current scene
        """
        # validate the version first
        self.version = self._validate_version(self.version)

        self.open_version(self.version)

        task = self.version.task

        # check if all references have an BBOX repr first
        refs_with_no_bbox_repr = []
        for ref in pm.listReferences():
            if ref.version and not ref.has_repr('BBOX'):
                refs_with_no_bbox_repr.append(ref)

        if len(refs_with_no_bbox_repr):
            raise RuntimeError(
                'Please generate the BBOX Representation of the references '
                'first!!!\n%s' %
                '\n'.join(map(lambda x: str(x.path), refs_with_no_bbox_repr))
            )

        # do different things for Vegetation tasks
        if self.is_vegetation_task(task):
            # load all references back
            for ref in pm.listReferences():
                ref.load()

            # find the _pfxPolygons node
            pfx_polygons_node = pm.PyNode('kks___vegetation_pfxPolygons')

            all_children = []
            for node in pfx_polygons_node.getChildren():
                for child_node in node.getChildren():
                    all_children.append(child_node)

            auxiliary.replace_with_bbox(all_children)

            # clean up other nodes
            pm.delete('kks___vegetation_pfxStrokes')
            pm.delete('kks___vegetation_paintableGeos')
        elif self.is_scene_assembly_task(task):
            # reload all references
            # replace all root references with their BBOX representation
            for ref in pm.listReferences():
                ref.to_repr('BBOX')
        else:
            # find all non referenced root nodes
            root_nodes = self.get_local_root_nodes()

            if len(root_nodes):
                all_children = []
                for root_node in root_nodes:
                    for child in root_node.getChildren():
                        all_children.append(child)

                auxiliary.replace_with_bbox(all_children)

            # reload all references
            # replace all root references with their BBOX representation
            for ref in pm.listReferences():
                ref.to_repr('BBOX')

        # if this is an Exterior/Interior -> Layout -> Hires task flatten it
        if self.is_exterior_or_interior_task(task):
            # and import all of the references
            all_refs = pm.listReferences()
            while len(all_refs) != 0:
                for ref in all_refs:
                    if not ref.isLoaded():
                        ref.load()
                    ref.importContents()
                all_refs = pm.listReferences()

        # save the scene as {{original_take}}___BBOX
        # use maya
        take_name = '%s%s%s' % (
            self.base_take_name, Representation.repr_separator, 'BBOX'
        )
        v = self.get_latest_repr_version(take_name)

        self.maya_env.save_as(v)

        # reopen the original version
        pm.newFile(force=True)

    def generate_proxy(self):
        """generates the Proxy representation of the current scene
        """
        pass

    def generate_gpu(self):
        """generates the GPU representation of the current scene
        """
        # validate the version first
        self.version = self._validate_version(self.version)

        self.open_version(self.version)

        # load necessary plugins
        pm.loadPlugin('gpuCache')
        pm.loadPlugin('AbcExport')
        pm.loadPlugin('AbcImport')

        # check if all references have an GPU repr first
        refs_with_no_gpu_repr = []
        for ref in pm.listReferences():
            if ref.version and not ref.has_repr('GPU'):
                refs_with_no_gpu_repr.append(ref)

        if len(refs_with_no_gpu_repr):
            raise RuntimeError(
                'Please generate the GPU Representation of the references '
                'first!!!\n%s' %
                '\n'.join(map(lambda x: str(x.path), refs_with_no_gpu_repr))
            )

        # unload all references
        for ref in pm.listReferences():
            ref.unload()

        # for local models generate an ABC file
        output_path = os.path.join(
            self.version.absolute_path,
            'Outputs/alembic/'
        ).replace('\\', '/')

        abc_command = \
            'AbcExport -j "-frameRange %(start_frame)s ' \
            '%(end_frame)s ' \
            '-ro -stripNamespaces ' \
            '-uvWrite ' \
            '-wholeFrameGeo ' \
            '-worldSpace ' \
            '-root |%(node)s -file %(file_path)s";'

        gpu_command = \
            'gpuCache -startTime %(start_frame)s ' \
            '-endTime %(end_frame)s ' \
            '-optimize -optimizationThreshold 40000 ' \
            '-writeMaterials ' \
            '-directory "%(path)s" ' \
            '-fileName "%(filename)s" ' \
            '%(node)s;'

        start_frame = end_frame = int(pm.currentTime(q=1))

        if not self.is_scene_assembly_task(self.version.task):

            if self.is_vegetation_task(self.version.task):
                # in vegetation files, we export the GPU files directly from
                # the Base version, also we use the geometry under
                # "pfxPolygons" and parent the resulting Stand-In nodes to the
                # pfxPolygons
                # load all references
                for ref in pm.listReferences():
                    ref.load()

                # find the _pfxPolygons node
                pfx_polygons_node = pm.PyNode('kks___vegetation_pfxPolygons')

                for node in pfx_polygons_node.getChildren():
                    for child_node in node.getChildren():
                        child_node_name = child_node.name().split('___')[-1]
                        child_node_shape = child_node.getShape()
                        child_node_shape_name = None

                        if child_node_shape:
                            child_node_shape_name = child_node_shape.name()

                        pm.select(child_node)
                        temp_output_fullpath = \
                            tempfile.mktemp().replace('\\', '/')
                        temp_output_path, temp_output_filename = \
                            os.path.split(temp_output_fullpath)

                        output_filename = '%s_%s' % (
                            self.version.nice_name,
                            child_node_name.split(':')[-1]
                            .replace(':', '_')
                            .replace('|', '_')
                        )

                        # run the mel command
                        # check if file exists
                        pm.mel.eval(
                            gpu_command % {
                                'start_frame': start_frame,
                                'end_frame': end_frame,
                                'node': child_node.fullPath(),
                                'path': temp_output_path,
                                'filename': temp_output_filename
                            }
                        )

                        cache_file_full_path = \
                            os.path\
                            .join(output_path, output_filename + '.abc')\
                            .replace('\\', '/')

                        # create the intermediate directories
                        try:
                            os.makedirs(
                                os.path.dirname(cache_file_full_path)
                            )
                        except OSError:
                            # directory exists
                            pass

                        # now move in to its place
                        shutil.move(
                            temp_output_fullpath + '.abc',
                            cache_file_full_path
                        )

                        # set rotate and scale pivots
                        rp = pm.xform(child_node, q=1, ws=1, rp=1)
                        sp = pm.xform(child_node, q=1, ws=1, sp=1)
                        #child_node.setRotatePivotTranslation([0, 0, 0])

                        # delete the child and add a GPU node instead
                        pm.delete(child_node)

                        # check if file exists and create nodes
                        if os.path.exists(cache_file_full_path):
                            gpu_node = pm.createNode('gpuCache')
                            gpu_node_tra = gpu_node.getParent()

                            pm.parent(gpu_node_tra, node)
                            gpu_node_tra.rename(child_node_name)

                            if child_node_shape_name is not None:
                                gpu_node.rename(child_node_shape_name)

                            pm.xform(gpu_node_tra, ws=1, rp=rp)
                            pm.xform(gpu_node_tra, ws=1, sp=sp)

                            gpu_node.setAttr(
                                'cacheFileName',
                                cache_file_full_path,
                                type="string"
                            )
                        else:
                            print('File not found!: %s' % cache_file_full_path)

                # clean up other nodes
                pm.delete('kks___vegetation_pfxStrokes')
                pm.delete('kks___vegetation_paintableGeos')

            else:
                root_nodes = self.get_local_root_nodes()
                if len(root_nodes):
                    for root_node in root_nodes:
                        # export each child of each root as separate nodes
                        for child_node in root_node.getChildren():

                            # check if it is a transform node
                            if not isinstance(child_node, pm.nt.Transform):
                                continue

                            if not auxiliary.has_shape(child_node):
                                continue

                            child_name = child_node.name()
                            child_shape = child_node.getShape()
                            child_shape_name = None
                            if child_shape:
                                child_shape_name = child_shape.name()

                            child_full_path = \
                                child_node.fullPath()[1:].replace('|', '_')

                            temp_output_fullpath = \
                                tempfile.mktemp().replace('\\', '/')
                            temp_output_path, temp_output_filename = \
                                os.path.split(temp_output_fullpath)

                            output_filename =\
                                '%s_%s' % (
                                    self.version.nice_name,
                                    child_full_path
                                )

                            # run the mel command
                            # check if file exists
                            pm.mel.eval(
                                gpu_command % {
                                    'start_frame': start_frame,
                                    'end_frame': end_frame,
                                    'node': child_node.fullPath(),
                                    'path': temp_output_path,
                                    'filename': temp_output_filename
                                }
                            )

                            cache_file_full_path = \
                                os.path\
                                .join(
                                    output_path,
                                    '%s.abc' % (
                                        output_filename
                                    )
                                )\
                                .replace('\\', '/')

                            # create the intermediate directories
                            try:
                                os.makedirs(
                                    os.path.dirname(cache_file_full_path)
                                )
                            except OSError:
                                # directory exists
                                pass

                            # now move in to its place
                            shutil.move(
                                temp_output_fullpath + '.abc',
                                cache_file_full_path
                            )

                            # set rotate and scale pivots
                            rp = pm.xform(child_node, q=1, ws=1, rp=1)
                            sp = pm.xform(child_node, q=1, ws=1, sp=1)
                            # rpt = child_node.getRotatePivotTranslation()

                            # delete the child and add a GPU node instead
                            pm.delete(child_node)

                            # check if file exists
                            if os.path.exists(cache_file_full_path):
                                gpu_node = pm.createNode('gpuCache')
                                gpu_node_tra = gpu_node.getParent()

                                pm.parent(gpu_node_tra, root_node)
                                gpu_node_tra.rename(child_name)

                                if child_shape_name is not None:
                                    gpu_node.rename(child_shape_name)

                                pm.xform(gpu_node_tra, ws=1, rp=rp)
                                pm.xform(gpu_node_tra, ws=1, sp=sp)
                                # child_node.setRotatePivotTranslation(rpt)

                                gpu_node.setAttr(
                                    'cacheFileName',
                                    cache_file_full_path,
                                    type="string"
                                )

        # load all references again
        # convert all references to GPU
        logger.debug('converting all references to GPU')
        for ref in pm.listReferences():
            # check if this is a Model reference
            ref.to_repr('GPU')
            ref.load()

        # if this is an Exterior/Interior -> Layout -> Hires task flatten it
        task = self.version.task

        is_exterior_or_interior_task = self.is_exterior_or_interior_task(task)
        if is_exterior_or_interior_task:
            logger.debug('importing all references')
            # and import all of the references
            all_refs = pm.listReferences()
            while len(all_refs) != 0:
                for ref in all_refs:
                    if not ref.isLoaded():
                        ref.load()
                    ref.importContents()
                all_refs = pm.listReferences()

            # assign lambert1 to all GPU nodes
            pm.sets('initialShadingGroup', e=1, fe=auxiliary.get_root_nodes())

            # clean up
            self.clean_up()

        # 6. save the scene as {{original_take}}___GPU
        # use maya
        take_name = '%s%s%s' % (
            self.base_take_name, Representation.repr_separator, 'GPU'
        )
        v = self.get_latest_repr_version(take_name)
        self.maya_env.save_as(v)

        # export the root nodes under the same file
        if is_exterior_or_interior_task:
            logger.debug('exporting root nodes')
            pm.select(auxiliary.get_root_nodes())
            pm.exportSelected(
                v.absolute_full_path,
                type='mayaAscii',
                force=True
            )

        logger.debug('renewing scene')
        # clear scene
        pm.newFile(force=True)

    def make_tx(self, texture_path):
        """converts the given texture to TX
        """
        tx_path = ''.join([os.path.splitext(texture_path)[0], '.tx'])

        # generate if not exists
        if not os.path.exists(tx_path):
            cmd = 'maketx -o "%s" -u --oiio %s' % (tx_path, texture_path)

            if os.name == 'nt':
                proc = subprocess.Popen(
                    cmd,
                    creationflags=subprocess.SW_HIDE,
                    shell=True
                )
            else:
                proc = subprocess.Popen(
                    cmd,
                    shell=True
                )

            proc.wait()
        return tx_path

    @classmethod
    def clean_up(self):
        """cleans up the scene
        """
        num_of_items_deleted = pm.mel.eval('MLdeleteUnused')

        logger.debug('deleting unknown references')
        delete_nodes_types = ['reference', 'unknown']
        for node in pm.ls(type=delete_nodes_types):
            node.unlock()

        logger.debug('deleting "delete_nodes_types"')
        try:
            pm.delete(pm.ls(type=delete_nodes_types))
        except RuntimeError:
            pass

    def generate_ass(self):
        """generates the ASS representation of the current scene

        For Model Tasks the ASS is generated over the LookDev Task because it
        is not possible to assign a material to an object inside an ASS file.
        """
        # before doing anything, check if this is a look dev task
        # and export the objects from the referenced files with their current
        # shadings, then replace all of the references to ASS repr and than
        # add Stand-in nodes and parent them under the referenced models

        # load necessary plugins
        pm.loadPlugin('mtoa')

        # disable "show plugin shapes"
        active_panel = auxiliary.Playblaster.get_active_panel()
        show_plugin_shapes = pm.modelEditor(active_panel, q=1, pluginShapes=1)
        pm.modelEditor(active_panel, e=1, pluginShapes=False)

        # validate the version first
        self.version = self._validate_version(self.version)

        self.open_version(self.version)

        task = self.version.task

        # export_command = 'arnoldExportAss -f "%(path)s" -s -mask 24 ' \
        #                  '-lightLinks 0 -compressed -boundingBox ' \
        #                  '-shadowLinks 0 -cam perspShape;'

        export_command = 'arnoldExportAss -f "%(path)s" -s -mask 60' \
                         '-lightLinks 1 -compressed -boundingBox ' \
                         '-shadowLinks 1 -cam perspShape;'

        # calculate output path
        output_path = \
            os.path.join(self.version.absolute_path, 'Outputs/ass/')\
            .replace('\\', '/')

        # check if all references have an ASS repr first
        refs_with_no_ass_repr = []
        for ref in pm.listReferences():
            if ref.version and not ref.has_repr('ASS'):
                refs_with_no_ass_repr.append(ref)

        if len(refs_with_no_ass_repr):
            raise RuntimeError(
                'Please generate the ASS Representation of the references '
                'first!!!\n%s' %
                '\n'.join(map(lambda x: str(x.path), refs_with_no_ass_repr))
            )

        if self.is_look_dev_task(task):
            # in look dev files, we export the ASS files directly from the Base
            # version and parent the resulting Stand-In node to the parent of
            # the child node

            # load only Model references
            for ref in pm.listReferences():
                v = ref.version
                load_ref = False
                if v:
                    ref_task = v.task
                    if self.is_model_task(ref_task):
                        load_ref = True

                if load_ref:
                    ref.load()
                    ref.importContents()

            # Make all texture paths relative
            # replace all "$REPO#" from all texture paths first
            #
            # This is needed to properly render textures with any OS
            types_and_attrs = {
                'aiImage': 'filename',
                'file': 'fileTextureName',
                'imagePlane': 'imageName'
            }

            for node_type in types_and_attrs.keys():
                attr_name = types_and_attrs[node_type]
                for node in pm.ls(type=node_type):
                    orig_path = node.getAttr(attr_name).replace("\\", "/")
                    path = re.sub(
                        r'(\$REPO[0-9/]+)',
                        '',
                        orig_path
                    )
                    tx_path = self.make_tx(path)
                    inputs = node.attr(attr_name).inputs(p=1)
                    if len(inputs):
                        # set the input attribute
                        for input_node_attr in inputs:
                            input_node_attr.set(tx_path)
                    else:
                        node.setAttr(attr_name, tx_path)

            # randomize all render node names
            # This is needed to prevent clashing of materials in a bigger scene
            for node in pm.ls(type=RENDER_RELATED_NODE_TYPES):
                if node.referenceFile() is None and \
                   node.name() not in READ_ONLY_NODE_NAMES:
                    node.rename('%s_%s' % (node.name(), uuid.uuid4().hex))

            nodes_to_ass_files = {}

            # export all root ass files as they are
            for root_node in auxiliary.get_root_nodes():
                for child_node in root_node.getChildren():
                    # check if it is a transform node
                    if not isinstance(child_node, pm.nt.Transform):
                        continue

                    if not auxiliary.has_shape(child_node):
                        continue

                    # randomize child node name
                    # TODO: This is not working as intended, node names are like |NS:node1|NS:node2
                    #       resulting a child_node_name as "node2"
                    child_node_name = child_node\
                        .fullPath()\
                        .replace('|', '_')\
                        .split(':')[-1]

                    child_node_full_path = child_node.fullPath()

                    pm.select(child_node)
                    child_node.rename('%s_%s' % (child_node.name(), uuid.uuid4().hex))

                    output_filename =\
                        '%s_%s.ass' % (
                            self.version.nice_name,
                            child_node_name
                        )

                    output_full_path = \
                        os.path.join(output_path, output_filename)

                    # run the mel command
                    pm.mel.eval(
                        export_command % {
                            'path': output_full_path.replace('\\', '/')
                        }
                    )
                    nodes_to_ass_files[child_node_full_path] = \
                        '%s.gz' % output_full_path
                    # print('%s -> %s' % (
                    #     child_node_full_path,
                    #     output_full_path)
                    # )

            # reload the scene
            pm.newFile(force=True)
            self.open_version(self.version)

            # convert all references to ASS
            # we are doing it a little bit early here, but we need to
            for ref in pm.listReferences():
                ref.to_repr('ASS')

            all_stand_ins = pm.ls(type='aiStandIn')
            for ass_node in all_stand_ins:
                ass_tra = ass_node.getParent()
                full_path = ass_tra.fullPath()
                if full_path in nodes_to_ass_files:
                    ass_file_path = \
                        Repository.to_os_independent_path(
                            nodes_to_ass_files[full_path]
                        )
                    ass_node.setAttr('dso', ass_file_path)

        elif self.is_vegetation_task(task):
            # in vegetation files, we export the ASS files directly from the
            # Base version, also we use the geometry under "pfxPolygons"
            # and parent the resulting Stand-In nodes to the
            # pfxPolygons
            # load all references
            for ref in pm.listReferences():
                ref.load()

            # Make all texture paths relative
            # replace all "$REPO#" from all texture paths first
            #
            # This is needed to properly render textures with any OS
            types_and_attrs = {
                'aiImage': 'filename',
                'file': 'fileTextureName',
                'imagePlane': 'imageName'
            }

            for node_type in types_and_attrs.keys():
                attr_name = types_and_attrs[node_type]
                for node in pm.ls(type=node_type):
                    orig_path = node.getAttr(attr_name).replace("\\", "/")
                    path = re.sub(
                        r'(\$REPO[0-9/]+)',
                        '',
                        orig_path
                    )
                    tx_path = self.make_tx(path)
                    inputs = node.attr(attr_name).inputs(p=1)
                    if len(inputs):
                        # set the input attribute
                        for input_node_attr in inputs:
                            input_node_attr.set(tx_path)
                    else:
                        node.setAttr(attr_name, tx_path)

            # randomize all render node names
            # This is needed to prevent clashing of materials in a bigger scene
            for node in pm.ls(type=RENDER_RELATED_NODE_TYPES):
                if node.referenceFile() is None and \
                   node.name() not in READ_ONLY_NODE_NAMES:
                    node.rename('%s_%s' % (node.name(), uuid.uuid4().hex))

            # find the _pfxPolygons node
            pfx_polygons_node = pm.PyNode('kks___vegetation_pfxPolygons')

            for node in pfx_polygons_node.getChildren():
                for child_node in node.getChildren():
                    #print('processing %s' % child_node.name())
                    child_node_name = child_node.name().split('___')[-1]

                    pm.select(child_node)
                    output_filename =\
                        '%s_%s.ass' % (
                            self.version.nice_name,
                            child_node_name.replace(':', '_').replace('|', '_')
                        )

                    output_full_path = \
                        os.path.join(output_path, output_filename)

                    # run the mel command
                    pm.mel.eval(
                        export_command % {
                            'path': output_full_path.replace('\\', '/')
                        }
                    )

                    # generate an aiStandIn node and set the path
                    ass_node = auxiliary.create_arnold_stand_in(
                        path='%s.gz' % output_full_path
                    )
                    ass_tra = ass_node.getParent()

                    # parent the ass node under the current node
                    # under pfx_polygons_node
                    pm.parent(ass_tra, node)

                    # set pivots
                    rp = pm.xform(child_node, q=1, ws=1, rp=1)
                    sp = pm.xform(child_node, q=1, ws=1, sp=1)
                    # rpt = child_node.getRotatePivotTranslation()

                    pm.xform(ass_node, ws=1, rp=rp)
                    pm.xform(ass_node, ws=1, sp=sp)
                    # ass_node.setRotatePivotTranslation(rpt)

                    # delete the child_node
                    pm.delete(child_node)

                    # give it the same name with the original
                    ass_tra.rename('%s' % child_node_name)

            # clean up other nodes
            pm.delete('kks___vegetation_pfxStrokes')
            pm.delete('kks___vegetation_paintableGeos')

        elif self.is_model_task(task):
            # convert all children of the root node
            # to an empty aiStandIn node
            # and save it as it is
            root_nodes = self.get_local_root_nodes()

            for root_node in root_nodes:
                for child_node in root_node.getChildren():
                    child_node_name = child_node.name()

                    rp = pm.xform(child_node, q=1, ws=1, rp=1)
                    sp = pm.xform(child_node, q=1, ws=1, sp=1)

                    pm.delete(child_node)

                    ass_node = auxiliary.create_arnold_stand_in(path='')
                    ass_tra = ass_node.getParent()
                    pm.parent(ass_tra, root_node)
                    ass_tra.rename(child_node_name)

                    # set pivots
                    pm.xform(ass_tra, ws=1, rp=rp)
                    pm.xform(ass_tra, ws=1, sp=sp)

                    # because there will be possible material assignments
                    # in look dev disable overrideShaders
                    ass_node.setAttr('overrideShaders', False)

                    # we definitely do not use light linking in our studio,
                    # which seems to create more problems then it solves.
                    ass_node.setAttr('overrideLightLinking', False)

        # convert all references to ASS
        for ref in pm.listReferences():
            ref.to_repr('ASS')
            ref.load()

        # fix an arnold bug
        for node_name in ['initialShadingGroup', 'initialParticleSE']:
            node = pm.PyNode(node_name)
            node.setAttr("ai_surface_shader", (0, 0, 0), type="float3")
            node.setAttr("ai_volume_shader", (0, 0, 0), type="float3")

        # if this is an Exterior/Interior -> Layout -> Hires task flatten it
        is_exterior_or_interior_task = self.is_exterior_or_interior_task(task)
        if is_exterior_or_interior_task:
            # and import all of the references
            all_refs = pm.listReferences()
            while len(all_refs) != 0:
                for ref in all_refs:
                    if not ref.isLoaded():
                        ref.load()
                    ref.importContents()
                all_refs = pm.listReferences()

            # assign lambert1 to all GPU nodes
            pm.sets('initialShadingGroup', e=1, fe=auxiliary.get_root_nodes())

            # now remove them from the group
            pm.sets('initialShadingGroup', e=1, rm=pm.ls())

            # and to make sure that no override is enabled
            [node.setAttr('overrideLightLinking', False)
             for node in pm.ls(type='aiStandIn')]

            # clean up
            self.clean_up()

        # check if all aiStandIn nodes are included in
        # ArnoldStandInDefaultLightSet set
        try:
            arnold_stand_in_default_light_set = \
                pm.PyNode('ArnoldStandInDefaultLightSet')
        except pm.MayaNodeError:
            # just create it
            arnold_stand_in_default_light_set = \
                pm.createNode(
                    'objectSet',
                    name='ArnoldStandInDefaultLightSet'
                )

        pm.select(None)
        pm.sets(
            arnold_stand_in_default_light_set,
            fe=pm.ls(type='aiStandIn')
        )

        # save the scene as {{original_take}}___ASS
        # use maya
        take_name = '%s%s%s' % (
            self.base_take_name, Representation.repr_separator, 'ASS'
        )
        v = self.get_latest_repr_version(take_name)
        self.maya_env.save_as(v)

        # export the root nodes under the same file
        if is_exterior_or_interior_task:
            pm.select(auxiliary.get_root_nodes())
            pm.exportSelected(
                v.absolute_full_path,
                type='mayaAscii',
                force=True
            )

        # new scene
        pm.newFile(force=True)

        # reset show plugin shapes option
        active_panel = auxiliary.Playblaster.get_active_panel()
        pm.modelEditor(active_panel, e=1, pluginShapes=show_plugin_shapes)
Exemple #25
0
class PrevisUI(object):
    """Main class for managing the previs UI
    """

    def __init__(self):
        self.mEnv = Maya()

        self.width = 265
        self.height = 300
        self.row_spacing = 3
        self.window = None
        self.window_name = 'Previz_Window'
        self.window_title = "Previz Tools v%s" % anima.__version__

        self.edl_checkBox = None
        self.mxf_checkBox = None

    def init_ui(self):
        if core.window(self.window_name, q=True, ex=True):
            core.deleteUI(self.window_name, wnd=True)

        self.window = core.window(
            self.window_name,
            wh=(self.width, self.height),
            mnb = False,
            mxb=False,
            sizeable=False,
            title=self.window_title
        )

        #the layout
        main_formLayout = core.formLayout(
            'main_formLayout',
            nd=100,
            parent=self.window
        )

        prog_columnLayout = core.columnLayout(
            'prog_columnLayout',
            columnAttach=('both', 3),
            rowSpacing=10,
            columnWidth=265,
            parent=main_formLayout
        )

        top_rowLayout = core.rowLayout(
            'top_rowLayout',
            numberOfColumns=2,
            columnWidth2=(85, 180),
            adjustableColumn=2,
            columnAlign=(1, 'right'),
            columnAttach=[(1, 'both', 0), (2, 'both', 0)],
            parent= prog_columnLayout
        )

        topleft_columnLayout = core.columnLayout(
            'topleft_columnLayout',
             w=85,
             columnAttach=('left' , 5),
             cal='left',
             rowSpacing=17,
             columnWidth=85,
             parent=top_rowLayout
        )

        core.text(label='Scene Code', parent=topleft_columnLayout)
        core.text(label='File Version', parent=topleft_columnLayout)
        core.text(label='Handle Lenght', parent=topleft_columnLayout)
        core.text(label='Export', parent=topleft_columnLayout)
        core.text(label='Convert MOVs', parent=topleft_columnLayout)

        right_columnLayout = core.columnLayout(
            'right_columnLayout',
            columnAttach=('left' , 5),
            cal='left',
            rowSpacing=10,
            columnWidth=85,
            parent=top_rowLayout
        )

        Seqname_rowLayout = core.rowLayout(
            'seqNameRow',
            numberOfColumns=3,
            columnWidth3=(40,60,55),
            columnAttach=[(1, 'both', 5), (2, 'both', 10), (3, 'both', 5)],
            parent=right_columnLayout
        )

        seq = core.textField(pht="SEQ" , parent=Seqname_rowLayout)
        loc = core.textField(pht="LOC" , parent=Seqname_rowLayout)
        script = core.textField(pht= "Script", parent=Seqname_rowLayout)

        topRight_columnLayout = core.columnLayout(
            'topRight_columnLayout',
            w=170,
            columnAttach=('both', 5),
            rowSpacing=10,
            columnWidth=160,
            parent=right_columnLayout
        )

        current_version = self.mEnv.get_current_version()
        if current_version:
            version_number = current_version.version_number
        else:
            version_number = 1
        version_string = 'v%03d' % version_number

        version = core.textField(text=version_string)
        lenght_slider_grp = core.intSliderGrp(field= True, cw2= (30,70), cc=self.set_handle, min=0, v=15, max=50 )
        self.edl_checkBox = core.checkBox('EDL', value=True)
        self.mxf_checkBox = core.checkBox('to MXF', value=True)

        core.separator (h=20, parent= prog_columnLayout)

        bottom_columnLayout = core.columnLayout(
            'bottom_rowLayout',
            w = 260,
            columnAttach=('both', 5),
            rowSpacing=10,
            columnWidth=260,
            parent= prog_columnLayout
        )

        core.button(label='Export' , bgc=(0.1, 0.4, 0.1), w=250, parent=bottom_columnLayout, c=self.export)
        core.button(
            label='Close Window',
            command=self.close,
            bgc= (0.3, 0.1, 0.1), w=250,
            parent= bottom_columnLayout
        )

    def show(self):
        if not self.window:
            self.init_ui()

        try:
            core.showWindow(self.window)
        except RuntimeError:
            self.init_ui
            core.showWindow(self.window)

        core.window(self.window, edit=True, w=self.width, h=self.height)

    def close(self, value):
        """closes the UI
        """
        core.deleteUI(self.window_name, window=True)

    ### learning Scene Version
    def set_ver(self):
        scVer = 'v001'
        sm.set_version(scVer)

    def set_handle(self, value):
        """sets handles from UI
        """
        sm = core.ls('sequenceManager1')[0]
        seq1 = sm.sequences.get()[0]
        seq1.set_shot_handles(value)

    def set_seq_name(name):
        """sets sequence name
        """
        sm.get_shot_name_template()  # sets the default shot name template
        seq1.set_sequence_name('SEQ001_TNGI_Scr_010')

    def export(self, button_value):
        """
        """
        ### get sequenceManager1
        sm = pymel.core.PyNode('sequenceManager1')

        ### get sequencer
        seq1 = sm.sequences.get()[0]
        # set path values
        current_workspace_path = pymel.core.workspace.path
        playblast_output_path = os.path.normpath(
            os.path.join(current_workspace_path, 'Outputs', 'All_Shots')
        )

        edl_path = os.path.normpath(
            os.path.join(
                playblast_output_path,
                '%s_%s.%s' % (seq1.get_sequence_name(), sm.get_version(), 'edl')
            )
        )

        # create shot playblast
        seq1.create_shot_playblasts(playblast_output_path)

        # convert to MXF
        if self.mxf_checkBox.value():
            shot_count = len(seq1.shots.get())
            step = int(100.0/shot_count)
            import time
            core.progressWindow(
                title='Converting To MXFs',
                progress=0,
                status='',
                isInterruptable=True
            )
            for i in seq1.metafuze():
                core.progressWindow(e=1, step=step)
            core.progressWindow(endProgress=1)

        if self.edl_checkBox.value():
            # create EDL file
            l = sm.to_edl()
            with open(edl_path, 'w') as f:
                f.write(l.to_string())
Exemple #26
0
class PrevisUI(object):
    """Main class for managing the previs UI
    """
    def __init__(self):
        self.mEnv = Maya()

        self.width = 265
        self.height = 300
        self.row_spacing = 3
        self.window = None
        self.window_name = 'Previz_Window'
        self.window_title = "Previz Tools v%s" % anima.__version__

        self.edl_checkBox = None
        self.mxf_checkBox = None

    def init_ui(self):
        if core.window(self.window_name, q=True, ex=True):
            core.deleteUI(self.window_name, wnd=True)

        self.window = core.window(self.window_name,
                                  wh=(self.width, self.height),
                                  mnb=False,
                                  mxb=False,
                                  sizeable=False,
                                  title=self.window_title)

        #the layout
        main_formLayout = core.formLayout('main_formLayout',
                                          nd=100,
                                          parent=self.window)

        prog_columnLayout = core.columnLayout('prog_columnLayout',
                                              columnAttach=('both', 3),
                                              rowSpacing=10,
                                              columnWidth=265,
                                              parent=main_formLayout)

        top_rowLayout = core.rowLayout('top_rowLayout',
                                       numberOfColumns=2,
                                       columnWidth2=(85, 180),
                                       adjustableColumn=2,
                                       columnAlign=(1, 'right'),
                                       columnAttach=[(1, 'both', 0),
                                                     (2, 'both', 0)],
                                       parent=prog_columnLayout)

        topleft_columnLayout = core.columnLayout('topleft_columnLayout',
                                                 w=85,
                                                 columnAttach=('left', 5),
                                                 cal='left',
                                                 rowSpacing=17,
                                                 columnWidth=85,
                                                 parent=top_rowLayout)

        core.text(label='Scene Code', parent=topleft_columnLayout)
        core.text(label='File Version', parent=topleft_columnLayout)
        core.text(label='Handle Lenght', parent=topleft_columnLayout)
        core.text(label='Export', parent=topleft_columnLayout)
        core.text(label='Convert MOVs', parent=topleft_columnLayout)

        right_columnLayout = core.columnLayout('right_columnLayout',
                                               columnAttach=('left', 5),
                                               cal='left',
                                               rowSpacing=10,
                                               columnWidth=85,
                                               parent=top_rowLayout)

        Seqname_rowLayout = core.rowLayout('seqNameRow',
                                           numberOfColumns=3,
                                           columnWidth3=(40, 60, 55),
                                           columnAttach=[(1, 'both', 5),
                                                         (2, 'both', 10),
                                                         (3, 'both', 5)],
                                           parent=right_columnLayout)

        seq = core.textField(pht="SEQ", parent=Seqname_rowLayout)
        loc = core.textField(pht="LOC", parent=Seqname_rowLayout)
        script = core.textField(pht="Script", parent=Seqname_rowLayout)

        topRight_columnLayout = core.columnLayout('topRight_columnLayout',
                                                  w=170,
                                                  columnAttach=('both', 5),
                                                  rowSpacing=10,
                                                  columnWidth=160,
                                                  parent=right_columnLayout)

        current_version = self.mEnv.get_current_version()
        if current_version:
            version_number = current_version.version_number
        else:
            version_number = 1
        version_string = 'v%03d' % version_number

        version = core.textField(text=version_string)
        lenght_slider_grp = core.intSliderGrp(field=True,
                                              cw2=(30, 70),
                                              cc=self.set_handle,
                                              min=0,
                                              v=15,
                                              max=50)
        self.edl_checkBox = core.checkBox('EDL', value=True)
        self.mxf_checkBox = core.checkBox('to MXF', value=True)

        core.separator(h=20, parent=prog_columnLayout)

        bottom_columnLayout = core.columnLayout('bottom_rowLayout',
                                                w=260,
                                                columnAttach=('both', 5),
                                                rowSpacing=10,
                                                columnWidth=260,
                                                parent=prog_columnLayout)

        core.button(label='Export',
                    bgc=(0.1, 0.4, 0.1),
                    w=250,
                    parent=bottom_columnLayout,
                    c=self.export)
        core.button(label='Close Window',
                    command=self.close,
                    bgc=(0.3, 0.1, 0.1),
                    w=250,
                    parent=bottom_columnLayout)

    def show(self):
        if not self.window:
            self.init_ui()

        try:
            core.showWindow(self.window)
        except RuntimeError:
            self.init_ui
            core.showWindow(self.window)

        core.window(self.window, edit=True, w=self.width, h=self.height)

    def close(self, value):
        """closes the UI
        """
        core.deleteUI(self.window_name, window=True)

    ### learning Scene Version
    def set_ver(self):
        scVer = 'v001'
        sm.set_version(scVer)

    def set_handle(self, value):
        """sets handles from UI
        """
        sm = core.ls('sequenceManager1')[0]
        seq1 = sm.sequences.get()[0]
        seq1.set_shot_handles(value)

    def set_seq_name(name):
        """sets sequence name
        """
        sm.get_shot_name_template()  # sets the default shot name template
        seq1.set_sequence_name('SEQ001_TNGI_Scr_010')

    def export(self, button_value):
        """
        """
        ### get sequenceManager1
        sm = pymel.core.PyNode('sequenceManager1')

        ### get sequencer
        seq1 = sm.sequences.get()[0]
        # set path values
        current_workspace_path = pymel.core.workspace.path
        playblast_output_path = os.path.normpath(
            os.path.join(current_workspace_path, 'Outputs', 'All_Shots'))

        edl_path = os.path.normpath(
            os.path.join(
                playblast_output_path, '%s_%s.%s' %
                (seq1.get_sequence_name(), sm.get_version(), 'edl')))

        # create shot playblast
        seq1.create_shot_playblasts(playblast_output_path)

        # convert to MXF
        if self.mxf_checkBox.value():
            shot_count = len(seq1.shots.get())
            step = int(100.0 / shot_count)
            import time
            core.progressWindow(title='Converting To MXFs',
                                progress=0,
                                status='',
                                isInterruptable=True)
            for i in seq1.metafuze():
                core.progressWindow(e=1, step=step)
            core.progressWindow(endProgress=1)

        if self.edl_checkBox.value():
            # create EDL file
            l = sm.to_edl()
            with open(edl_path, 'w') as f:
                f.write(l.to_string())
Exemple #27
0
def export_edl():
    """exports edl of animation scenes
    """
    from anima.env.mayaEnv import Maya
    m = Maya()
    current_version = m.get_current_version()

    if not current_version:
        return

    # get sequenceManager1
    sm = pm.PyNode('sequenceManager1')
    seqs = sm.sequences.get()
    if not len(seqs):
        return

    seq1 = seqs[0]

    edl_path = tempfile.gettempdir()
    edl_file_name = '%s_v%03i.edl' % (
        current_version.nice_name,
        current_version.version_number
    )

    edl_file_full_path = os.path.join(edl_path, edl_file_name)

    # convert to MXF
    from anima.ui.progress_dialog import ProgressDialogManager
    pdm = ProgressDialogManager()

    #shots = seq1.shots.get()
    shots = pm.ls(type='shot')
    shot_count = len(shots)

    # before doing a playblast set all shot handles to 48
    for shot in pm.ls(type='shot'):
        if shot.hasAttr('handle'):
            shot.handle.set(48)

    caller = pdm.register(shot_count, title='Converting To MXF')

    # update shot outputs to the correct place first
    # there should be only one shot in the current animation scene
    # if there is more than one shot, the other publisher will already warn the
    # user so the code path will not reach to this point

    # we also should already have a video output created by another publisher
    playblast_file = None
    for output in current_version.outputs:
        extension = os.path.splitext(output.full_path)[-1]
        if extension in ['.mov', '.avi', '.mp4']:
            playblast_file = output
            break

    if not playblast_file:
        return
    shot = shots[0]
    shot.output.set(playblast_file.full_path)

    for i in seq1.metafuze():
        caller.step()

    # create EDL file
    from anima import utils
    mm = utils.MediaManager()
    l = sm.to_edl()
    with open(edl_file_full_path, 'w') as f:
        f.write(l.to_string())

    with open(edl_file_full_path, 'r') as f:
        link = mm.upload_version_output(current_version, f, edl_file_name)

    # add the link to database
    from stalker import db
    db.DBSession.commit()

    # revert the handles to 0
    for shot in pm.ls(type='shot'):
        if shot.hasAttr('handle'):
            shot.handle.set(0)
Exemple #28
0
 def version(self):
     """returns the Stalker Version instance related to this reference
     """
     from anima.env.mayaEnv import Maya
     m = Maya()
     return m.get_version_from_full_path(self.path)
Exemple #29
0
    def setUp(self):
        """create test data
        """
        database_url = 'sqlite:///:memory:'
        db.setup({'sqlalchemy.url': database_url})
        db.init()

        self.temp_repo_path = tempfile.mkdtemp()

        self.user1 = User(name='User 1',
                          login='******',
                          email='*****@*****.**',
                          password='******')

        self.repo1 = Repository(name='Test Project Repository',
                                linux_path=self.temp_repo_path,
                                windows_path=self.temp_repo_path,
                                osx_path=self.temp_repo_path)

        self.status_new = Status.query.filter_by(code='NEW').first()
        self.status_wip = Status.query.filter_by(code='WIP').first()
        self.status_comp = Status.query.filter_by(code='CMPL').first()

        self.task_template = FilenameTemplate(
            name='Task Template',
            target_entity_type='Task',
            path='{{project.code}}/'
            '{%- for parent_task in parent_tasks -%}'
            '{{parent_task.nice_name}}/'
            '{%- endfor -%}',
            filename='{{version.nice_name}}'
            '_v{{"%03d"|format(version.version_number)}}',
        )

        self.asset_template = FilenameTemplate(
            name='Asset Template',
            target_entity_type='Asset',
            path='{{project.code}}/'
            '{%- for parent_task in parent_tasks -%}'
            '{{parent_task.nice_name}}/'
            '{%- endfor -%}',
            filename='{{version.nice_name}}'
            '_v{{"%03d"|format(version.version_number)}}',
        )

        self.shot_template = FilenameTemplate(
            name='Shot Template',
            target_entity_type='Shot',
            path='{{project.code}}/'
            '{%- for parent_task in parent_tasks -%}'
            '{{parent_task.nice_name}}/'
            '{%- endfor -%}',
            filename='{{version.nice_name}}'
            '_v{{"%03d"|format(version.version_number)}}',
        )

        self.sequence_template = FilenameTemplate(
            name='Sequence Template',
            target_entity_type='Sequence',
            path='{{project.code}}/'
            '{%- for parent_task in parent_tasks -%}'
            '{{parent_task.nice_name}}/'
            '{%- endfor -%}',
            filename='{{version.nice_name}}'
            '_v{{"%03d"|format(version.version_number)}}',
        )

        self.structure = Structure(name='Project Struture',
                                   templates=[
                                       self.task_template, self.asset_template,
                                       self.shot_template,
                                       self.sequence_template
                                   ])

        self.project_status_list = \
            StatusList.query.filter_by(target_entity_type='Project').first()

        self.image_format = ImageFormat(name='HD 1080',
                                        width=1920,
                                        height=1080,
                                        pixel_aspect=1.0)

        # create a test project
        self.project = Project(name='Test Project',
                               code='TP',
                               repository=self.repo1,
                               status_list=self.project_status_list,
                               structure=self.structure,
                               image_format=self.image_format)

        # create task hierarchy
        #
        # ASSETS
        #
        self.assets = Task(name='Assets',
                           project=self.project,
                           responsible=[self.user1])

        #
        # SEQUENCES
        #
        self.sequences = Task(name='Sequences',
                              project=self.project,
                              responsible=[self.user1])

        self.seq001 = Sequence(name='Seq001',
                               code='Seq001',
                               parent=self.sequences)

        self.scene_task = Task(name='001_IST', parent=self.seq001)

        self.scene_previs_type = Type(name='Scene Previs',
                                      code='Scene Previs',
                                      target_entity_type='Task')

        self.scene_previs = Task(name='Scene Previs',
                                 parent=self.scene_task,
                                 type=self.scene_previs_type)

        self.shots = Task(name='Shots', parent=self.scene_task)

        self.shot1 = Shot(name='Seq001_001_IST_0010',
                          code='Seq001_001_IST_0010',
                          parent=self.shots)

        # create shot tasks
        self.previs = Task(name='Previs', parent=self.shot1)

        self.camera = Task(name='Camera', parent=self.shot1)

        self.animation = Task(name='Animation', parent=self.shot1)

        self.scene_assembly = Task(name='SceneAssembly', parent=self.shot1)

        self.lighting = Task(name='Lighting', parent=self.shot1)

        self.comp = Task(name='Comp', parent=self.shot1)

        # create maya files
        self.maya_env = Maya()
        pm.newFile(force=True)

        sm = pm.PyNode('sequenceManager1')

        seq1 = sm.create_sequence('001_IST')

        # create 3 shots
        shot1 = seq1.create_shot('shot1')
        shot2 = seq1.create_shot('shot2')
        shot3 = seq1.create_shot('shot3')

        # set shot ranges
        shot1.startFrame.set(1)
        shot1.endFrame.set(100)

        shot2.startFrame.set(101)
        shot2.endFrame.set(200)
        shot2.sequenceStartFrame.set(101)

        shot3.startFrame.set(201)
        shot3.endFrame.set(300)
        shot3.sequenceStartFrame.set(201)

        # save the file under scene previs
        v = Version(task=self.scene_previs)

        self.maya_env.save_as(v)
        pm.newFile(force=1)
        print(v.absolute_full_path)
Exemple #30
0
    def setUp(self):
        """create test data
        """
        database_url = 'sqlite:///:memory:'
        db.setup({'sqlalchemy.url': database_url})
        db.init()

        self.temp_repo_path = tempfile.mkdtemp()

        self.user1 = User(
            name='User 1',
            login='******',
            email='*****@*****.**',
            password='******'
        )

        self.repo1 = Repository(
            name='Test Project Repository',
            linux_path=self.temp_repo_path,
            windows_path=self.temp_repo_path,
            osx_path=self.temp_repo_path
        )

        self.status_new = Status.query.filter_by(code='NEW').first()
        self.status_wip = Status.query.filter_by(code='WIP').first()
        self.status_comp = Status.query.filter_by(code='CMPL').first()

        self.task_template = FilenameTemplate(
            name='Task Template',
            target_entity_type='Task',
            path='{{project.code}}/'
                 '{%- for parent_task in parent_tasks -%}'
                 '{{parent_task.nice_name}}/'
                 '{%- endfor -%}',
            filename='{{version.nice_name}}'
                     '_v{{"%03d"|format(version.version_number)}}',
        )

        self.asset_template = FilenameTemplate(
            name='Asset Template',
            target_entity_type='Asset',
            path='{{project.code}}/'
                 '{%- for parent_task in parent_tasks -%}'
                 '{{parent_task.nice_name}}/'
                 '{%- endfor -%}',
            filename='{{version.nice_name}}'
                     '_v{{"%03d"|format(version.version_number)}}',
        )

        self.shot_template = FilenameTemplate(
            name='Shot Template',
            target_entity_type='Shot',
            path='{{project.code}}/'
                 '{%- for parent_task in parent_tasks -%}'
                 '{{parent_task.nice_name}}/'
                 '{%- endfor -%}',
            filename='{{version.nice_name}}'
                     '_v{{"%03d"|format(version.version_number)}}',
        )

        self.sequence_template = FilenameTemplate(
            name='Sequence Template',
            target_entity_type='Sequence',
            path='{{project.code}}/'
                 '{%- for parent_task in parent_tasks -%}'
                 '{{parent_task.nice_name}}/'
                 '{%- endfor -%}',
            filename='{{version.nice_name}}'
                     '_v{{"%03d"|format(version.version_number)}}',
        )

        self.structure = Structure(
            name='Project Struture',
            templates=[self.task_template, self.asset_template,
                       self.shot_template, self.sequence_template]
        )

        self.project_status_list = StatusList(
            name='Project Statuses',
            target_entity_type='Project',
            statuses=[self.status_new, self.status_wip, self.status_comp]
        )

        self.image_format = ImageFormat(
            name='HD 1080',
            width=1920,
            height=1080,
            pixel_aspect=1.0
        )

        # create a test project
        self.project = Project(
            name='Test Project',
            code='TP',
            repository=self.repo1,
            status_list=self.project_status_list,
            structure=self.structure,
            image_format=self.image_format
        )

        # create task hierarchy
        #
        # ASSETS
        #
        self.assets = Task(
            name='Assets',
            project=self.project,
            responsible=[self.user1]
        )

        #
        # SEQUENCES
        #
        self.sequences = Task(
            name='Sequences',
            project=self.project,
            responsible=[self.user1]
        )

        self.seq001 = Sequence(
            name='Seq001',
            code='Seq001',
            parent=self.sequences
        )

        self.scene_task = Task(
            name='001_IST',
            parent=self.seq001
        )

        self.scene_previs_type = Type(
            name='Scene Previs',
            code='Scene Previs',
            target_entity_type='Task'
        )

        self.scene_previs = Task(
            name='Scene Previs',
            parent=self.scene_task,
            type=self.scene_previs_type
        )

        self.shots = Task(
            name='Shots',
            parent=self.scene_task
        )

        self.shot1 = Shot(
            name='Seq001_001_IST_0010',
            code='Seq001_001_IST_0010',
            parent=self.shots
        )

        # create shot tasks
        self.previs = Task(
            name='Previs',
            parent=self.shot1
        )

        self.camera = Task(
            name='Camera',
            parent=self.shot1
        )

        self.animation = Task(
            name='Animation',
            parent=self.shot1
        )

        self.scene_assembly = Task(
            name='SceneAssembly',
            parent=self.shot1
        )

        self.lighting = Task(
            name='Lighting',
            parent=self.shot1
        )

        self.comp = Task(
            name='Comp',
            parent=self.shot1
        )

        # create maya files
        self.maya_env = Maya()
        pm.newFile(force=True)

        sm = pm.PyNode('sequenceManager1')

        seq1 = sm.create_sequence('001_IST')

        # create 3 shots
        shot1 = seq1.create_shot('shot1')
        shot2 = seq1.create_shot('shot2')
        shot3 = seq1.create_shot('shot3')

        # set shot ranges
        shot1.startFrame.set(1)
        shot1.endFrame.set(100)

        shot2.startFrame.set(101)
        shot2.endFrame.set(200)
        shot2.sequenceStartFrame.set(101)

        shot3.startFrame.set(201)
        shot3.endFrame.set(300)
        shot3.sequenceStartFrame.set(201)

        # save the file under scene previs
        v = Version(task=self.scene_previs)

        self.maya_env.save_as(v)
        pm.newFile(force=1)
        print(v.absolute_full_path)
Exemple #31
0
def export_edl():
    """exports edl of animation scenes
    """
    from anima.env.mayaEnv import Maya
    m = Maya()
    current_version = m.get_current_version()

    if not current_version:
        return

    # get sequenceManager1
    sm = pm.PyNode('sequenceManager1')
    seqs = sm.sequences.get()
    if not len(seqs):
        return

    seq1 = seqs[0]

    edl_path = tempfile.gettempdir()
    edl_file_name = '%s_v%03i.edl' % (current_version.nice_name,
                                      current_version.version_number)

    edl_file_full_path = os.path.join(edl_path, edl_file_name)

    # convert to MXF
    from anima.ui.progress_dialog import ProgressDialogManager
    pdm = ProgressDialogManager()

    #shots = seq1.shots.get()
    shots = pm.ls(type='shot')
    shot_count = len(shots)

    # before doing a playblast set all shot handles to 48
    for shot in pm.ls(type='shot'):
        if shot.hasAttr('handle'):
            shot.handle.set(48)

    caller = pdm.register(shot_count, title='Converting To MXF')

    # update shot outputs to the correct place first
    # there should be only one shot in the current animation scene
    # if there is more than one shot, the other publisher will already warn the
    # user so the code path will not reach to this point

    # we also should already have a video output created by another publisher
    playblast_file = None
    for output in current_version.outputs:
        extension = os.path.splitext(output.full_path)[-1]
        if extension in ['.mov', '.avi', '.mp4']:
            playblast_file = output
            break

    if not playblast_file:
        return
    shot = shots[0]
    shot.output.set(playblast_file.full_path)

    for i in seq1.metafuze():
        caller.step()

    # create EDL file
    from anima import utils
    mm = utils.MediaManager()
    l = sm.to_edl()
    with open(edl_file_full_path, 'w') as f:
        f.write(l.to_string())

    with open(edl_file_full_path, 'r') as f:
        link = mm.upload_version_output(current_version, f, edl_file_name)

    # add the link to database
    from stalker import db
    db.DBSession.commit()

    # revert the handles to 0
    for shot in pm.ls(type='shot'):
        if shot.hasAttr('handle'):
            shot.handle.set(0)
Exemple #32
0
    def generate_sequence_structure(self):
        """Generates a Sequence structure suitable for XML<->EDL conversion

        :return: Sequence
        """
        import timecode
        from anima.env.mayaEnv import Maya

        m = Maya()
        fps = m.get_fps()

        # export only the first sequence, ignore others
        sequencers = self.sequences.get()
        if len(sequencers) == 0:
            return None

        sequencer = sequencers[0]
        time = pm.PyNode('time1')

        seq = Sequence()
        seq.name = str(sequencer.get_sequence_name())

        seq.rate = Rate(timebase=str(fps), ntsc=False)
        seq.timecode = str(timecode.Timecode(
            framerate=seq.rate.timebase,
            frames=time.timecodeProductionStart.get() + 1
        ))
        seq.duration = sequencer.duration

        media = Media()
        video = Video()
        media.video = video

        for shot in sequencer.shots.get():
            clip = Clip()
            clip.id = str(shot.full_shot_name)
            clip.name = str(shot.full_shot_name)
            clip.duration = shot.duration + 2 * shot.handle.get()
            clip.enabled = True
            clip.start = shot.sequenceStartFrame.get()
            clip.end = shot.sequenceEndFrame.get() + 1
            # clips always start from 0 and includes the shot handle
            clip.in_ = shot.handle.get()  # handle at start
            clip.out = shot.handle.get() + shot.duration  # handle at end
            clip.type = 'Video'  # always video for now

            f = File()
            f.name = os.path.splitext(
                os.path.basename(str(shot.output.get()))
            )[0]

            f.duration = shot.duration + 2 * shot.handle.get()

            f.pathurl = str('file://localhost/%s' % shot.output.get())

            clip.file = f

            track_number = shot.track.get() - 1  # tracks should start from 0
            try:
                track = video.tracks[track_number]
            except IndexError:
                track = Track()
                video.tracks.append(track)

            track.clips.append(clip)
            # set video resolution
            video.width = shot.wResolution.get()
            video.height = shot.hResolution.get()

        seq.media = media
        return seq