Exemple #1
0
    def __init__(self, shotCutList=''):
        self.fileService = flix.fileServices.FileService()
        self.fileServiceLocal = flix.fileServices.fileLocal.FileLocal()
        self.rePath = RepathDefault()
        # self.shotList    = shotCutList
        if shotCutList != '':
            self.shotList = flix.core2.shotCutList.ShotCutList.fromFile(
                shotCutList.defaultPath())
            self.kargs = {
                'show': self.shotList.show,
                'sequence': self.shotList.sequence,
                'branch': self.shotList.branch,
                'version': self.shotList.version
            }
            self.mode = self.shotList.mode
            self.movDir = self.mode.get("[editorialMOVFolder]")

        # load the icon
        iconPath = flix.core2.mode.Mode().get(
            '[FLIX_FOLDER]') + '/assets/20px-quicktime.png'
        icon = self.fileService.loadByteArray(iconPath)

        self.init(label='QuickTime per Shot',
                  icon=icon,
                  tooltip='QuickTime per Shot',
                  group='Export',
                  pluginPath='flixConfig.plugins.toMovPerShot.ToMovPerShot')
    def __init__(self):
        self.fileService = fileService
        self.rePath = RepathDefault()

        self.shotList = ''

        # load the icon
        iconPath = Mode().get('[FLIX_FOLDER]') + '/assets/custom_icon.png'
        icon = self.fileService.loadByteArray(iconPath)

        self.init(label='BurnIn per Shot',
                  icon=icon,
                  tooltip='BurnIn per Shot',
                  group='Export',
                  pluginPath='flixConfig.plugins.burnInPerShot.BurnInPerShot')
    def __init__(self):
        self.fileService = fileService
        self.rePath      = RepathDefault()

        self.shotList             = ''

        # load the icon
        iconPath = Mode().get('[FLIX_CONFIG_FOLDER]')+'/plugins/icons/custom_icon.png'
        icon = self.fileService.loadByteArray(iconPath)

        self.init(label     ='Log Multiple Shot Edits',
                  icon      =icon,
                  tooltip   ='Logs latest shotedit from every sequence',
                  group     ='Export',
                  pluginPath='flixConfig.plugins.logMultipleShotEdits.LogMultipleShotEdits')
    def __init__(self):
        self.fileService = flix.fileServices.FileService()
        self.fileServiceLocal = flix.fileServices.fileLocal.FileLocal()
        self.rePath = RepathDefault()

        self.shotList = ''

        # load the icon
        iconPath = flix.core2.mode.Mode().get(
            '[FLIX_FOLDER]') + '/assets/20px-quicktime.png'
        icon = self.fileService.loadByteArray(iconPath)

        self.init(label='QuickTime per Shot',
                  icon=icon,
                  tooltip='QuickTime per Shot',
                  group='Export',
                  pluginPath='flixConfig.plugins.toMovPerShot.ToMovPerShot')
class LogMultipleShotEdits(PluginDecorator):

    #--------------------------------------------------------------------------
    # object
    #--------------------------------------------------------------------------

    def __init__(self):
        self.fileService = fileService
        self.rePath      = RepathDefault()

        self.shotList             = ''

        # load the icon
        iconPath = Mode().get('[FLIX_CONFIG_FOLDER]')+'/plugins/icons/custom_icon.png'
        icon = self.fileService.loadByteArray(iconPath)

        self.init(label     ='Log Multiple Shot Edits',
                  icon      =icon,
                  tooltip   ='Logs latest shotedit from every sequence',
                  group     ='Export',
                  pluginPath='flixConfig.plugins.logMultipleShotEdits.LogMultipleShotEdits')

    #--------------------------------------------------------------------------
    # executions
    #--------------------------------------------------------------------------

    def execute(self, shotCutList, selection, additionalData=None):
        self.shotList = flix.core2.shotCutList.ShotCutList.fromFile(shotCutList.defaultPath())
        self.show = self.shotList.show
        sequences = flix.core.sequence.Sequence.sequencesToXMLList(flix.core.sequence.Sequence.getSequences(self.show))
        for seq in sequences:
            seqName = seq.attrib["name"]
            latestShotEdit = self.getLatestShotCutList(seqName)
            log("latestShotEdit: %s" % latestShotEdit)

    def getLatestSequenceVersion(self, sequence, branch="main"):
        maxEditVersions = flix.versioning.flixVersioning.FlixVersioning().getCurrentFlixEditVersion(self.show, sequence, branch)
        i = 0

        sequenceObj = flix.core.sequence.Sequence(self.show, sequence)
        for i in range(maxEditVersions, -1, -1):
            editVersion = str(i)
            editorialPath = sequenceObj.getShotEditPath(branch, editVersion)

            if self.fileService.exists(editorialPath):
                break
        return i

    def getLatestShotCutList(self, sequence, branch="main"):
        editVersion = self.getLatestSequenceVersion(sequence)
        sequenceObj = flix.core.sequence.Sequence(self.show, sequence)
        editorialPath = sequenceObj.getShotEditPath(branch, editVersion)

        if not fileService.exists(editorialPath):
            flix.logger.log('Could not get the latest shotcutlist %s' % self.rePath.localize(editorialPath), isError=True)
            return None

        return flix.core2.shotCutList.ShotCutList.fromFile(editorialPath)
Exemple #6
0
    def __init__(self):
        self.fileService = fileService
        self.rePath = RepathDefault()
        self.fileServiceLocal = flix.fileServices.fileLocal.FileLocal()
        self.serverFlixFunctions = ServerFlixFunctions()

        self.shotList = ''

        # load the icon
        iconPath = Mode().get(
            '[FLIX_CONFIG_FOLDER]') + '/plugins/icons/custom_icon.png'
        icon = self.fileService.loadByteArray(iconPath)

        self.init(
            label='Picture In Picture',
            icon=icon,
            tooltip='Picture In Picture',
            group='Maya',
            pluginPath='flixConfig.plugins.pictureInPicture.PictureInPicture')
    def __init__(self):
        self.fileService = fileService
        self.rePath = RepathDefault()

        self.shotList = ''
        self.sg = None
        self.sgShow = ''
        self.sgSeq = ''
        self.sgShot = ''
        self.sgTask = ''

        # load the icon
        iconPath = Mode().get('[FLIX_FOLDER]') + '/assets/20px-shotgun.png'
        icon = self.fileService.loadByteArray(iconPath)

        self.init(label='Shotgun GEAH',
                  icon=icon,
                  tooltip='Shotgun GEAH',
                  group='Editorial',
                  pluginPath='flixConfig.plugins.toShotgunGEAH.ToShotgunGEAH')
    def __init__(self):
        self.fileService = fileService
        self.rePath      = RepathDefault()

        self.shotList             = ''

        # load the icon
        iconPath = Mode().get('[FLIX_CONFIG_FOLDER]')+'/plugins/icons/custom_icon.png'
        icon = self.fileService.loadByteArray(iconPath)

        self.init(label     ='Log Shot Markers',
                  icon      =icon,
                  tooltip   ='Logs what shots, markers and markerlists are',
                  group     ='Export',
                  pluginPath='flixConfig.plugins.logShotMarkers.LogShotMarkers')
    def __init__(self):
        self.fileService = fileService
        self.rePath      = RepathDefault()
        self.flixNuke = FlixNuke()

        self.shotList             = ''

        # load the icon
        iconPath = Mode().get('[FLIX_FOLDER]')+'/assets/custom_icon.png'
        icon = self.fileService.loadByteArray(iconPath)

        self.init(label     ='Quick Nuke Render',
                  icon      =icon,
                  tooltip   ='Quick Nuke Render',
                  group     ='Export',
                  pluginPath='flixConfig.plugins.quickNukeRender.QuickNukeRender')
    def __init__(self):
        self.fileService = fileService
        self.rePath = RepathDefault()

        self.shotList = ''
        self.serverFlixFunctions = ServerFlixFunctions()

        # load the icon
        iconPath = Mode().get(
            '[FLIX_CONFIG_FOLDER]') + '/plugins/icons/custom_icon.png'
        icon = self.fileService.loadByteArray(iconPath)

        self.init(
            label='Import Dialogue',
            icon=icon,
            tooltip='Import dialogue to current edit',
            group='Export',
            pluginPath='flixConfig.plugins.importDialogue.ImportDialogue')
Exemple #11
0
class BurnInPerShot(PluginDecorator):

    #--------------------------------------------------------------------------
    # object
    #--------------------------------------------------------------------------

    def __init__(self):
        self.fileService = fileService
        self.rePath = RepathDefault()

        self.shotList = ''

        # load the icon
        iconPath = Mode().get('[FLIX_FOLDER]') + '/assets/custom_icon.png'
        icon = self.fileService.loadByteArray(iconPath)

        self.init(label='BurnIn per Shot',
                  icon=icon,
                  tooltip='BurnIn per Shot',
                  group='Export',
                  pluginPath='flixConfig.plugins.burnInPerShot.BurnInPerShot')

    #--------------------------------------------------------------------------
    # executions
    #--------------------------------------------------------------------------

    def execute(self, shotCutList, selection, additionalData=None):
        self.shotList = flix.core2.shotCutList.ShotCutList.fromFile(
            shotCutList.defaultPath())
        self.kargs = {
            'show': self.shotList.show,
            'sequence': self.shotList.sequence,
            'branch': self.shotList.branch,
            'version': self.shotList.version
        }
        self.mode = self.shotList.mode
        self.movDir = self.mode.get("[editorialMOVFolder]")
        movieFile = self.rePath.localize(self.__getMovFilePath())
        if movieFile is None:
            raise flix.exceptions.FlixException(
                msg="Current version does not have an editorial movie.",
                notify=True)
        else:
            log("Movie File: %s" % movieFile)

        self.addProgress(5)
        output = OSUtils.runFileBrowser(kBrowseTypeFolderUsingSaveFile,
                                        'Choose a folder', '/',
                                        'burnInPerShot')
        self.removeProgress(5)
        # escape output path
        output = escape(output.decode('utf-8'))
        if not output or not os.path.isdir(output):
            raise flix.exceptions.FlixException(
                error=output, msg='No Valid directory selected.', notify=False)

        # markerShotLists = self.getMarkerList(self.shotList)

        markerList = MarkerList.fromShotCutList(self.shotList)
        self.addProgress(len(markerList))
        shotLabels = []
        for marker in markerList:
            shotLabels.append(marker.name)
        markerShotLists = MarkerList.markerShotCutList(self.shotList,
                                                       markerList)
        if not markerShotLists:
            markerShotLists.append(self.shotList)

        self.markIn = 1
        self.markOut = 0
        markerTuples = []
        for markerShot in markerShotLists:
            if markerShot.isMarker:
                for shot in markerShot:
                    self.markOut += int(round(shot.duration))
                markerTuples.append((self.markIn, self.markOut))
                self.markIn = self.markOut + 1

        self.breakDownMov(movieFile, markerTuples, shotLabels, self.movDir)

        for shot in shotLabels:
            toReplace = str(shotLabels.index(shot)).zfill(3) + ".tmp"
            oldName = self.movDir + "/" + toReplace + ".mov"
            newName = oldName.replace(toReplace,
                                      shot + "_v" + str(self.shotList.version))
            try:
                # self.fileService.rename(oldName, newName)
                self.addBurnIns(oldName, newName)
                self.fileService.copy(newName, output)
                self.fileService.removeFile(oldName)
                self.fileService.removeFile(newName)
            except Exception, e:
                log("Failed to rename, copy or remove the temp mov: %s" % e,
                    isError=True)
            self.removeProgress(1)

        # self.removeProgress()
        OSUtils().revealFiles([output])
Exemple #12
0
class ToShotgunGEAH(ToShotgun):

    #--------------------------------------------------------------------------
    # object
    #--------------------------------------------------------------------------

    def __init__(self):
        self.fileService = fileService
        self.rePath = RepathDefault()

        self.shotList = ''
        self.sg = None
        self.sgShow = ''
        self.sgSeq = ''
        self.sgShot = ''
        self.sgTask = ''

        # load the icon
        iconPath = Mode().get('[FLIX_FOLDER]') + '/assets/20px-shotgun.png'
        icon = self.fileService.loadByteArray(iconPath)

        self.init(label='Shotgun GEAH',
                  icon=icon,
                  tooltip='Shotgun GEAH',
                  group='Editorial',
                  pluginPath='flixConfig.plugins.toShotgunGEAH.ToShotgunGEAH')

    #--------------------------------------------------------------------------
    # executions
    #--------------------------------------------------------------------------

    def execute(self, shotCutList, selection, additionalData=None):
        if not additionalData is None:
            referenceCutList = additionalData.get('reference', None)
            comment = additionalData.get('comment', "")
        else:
            comment = ''

        comment = unicode(urllib.unquote_plus(comment))
        self.shotList = flix.core2.shotCutList.ShotCutList.fromFile(
            shotCutList.defaultPath())
        self.kargs = {
            'show': self.shotList.show,
            'sequence': self.shotList.sequence,
            'branch': self.shotList.branch,
            'version': self.shotList.version
        }
        self.mode = self.shotList.mode
        self.markerShotLists = self.getMarkerList(self.shotList)
        # Get the editorial movie path
        self.addProgress(4)
        self.movDir = self.mode.get("[editorialMOVFolder]")

        movieFileName = self.shotList.refVideoFilename
        if movieFileName is None:
            raise flix.exceptions.FlixException(
                msg="Current version does not have an editorial movie.",
                notify=True)
        else:
            movieFile = "%s/%s" % (self.movDir, movieFileName)
            log("Movie File: %s" % movieFile)
        shotInfoObject = ShotInfo(self.shotList)
        shotsInfo = shotInfoObject.getShotsInfo()
        toMovPerShotObject = ToMovPerShot(self.shotList)
        self.addProgress(len(shotsInfo))
        shotMovies = toMovPerShotObject.toMovPerShot(shotsInfo, movieFile)

        self.removeProgress()
        self.sg = self._connectToSG(self.mode)
        self.removeProgress()

        self.seqUrl = self.getSequenceUrl()

        # validate that all information for Flix has an equivalent in shotgun
        self.sgShow = self._validateShow(self.shotList.show)
        if int(Mode(self.shotList.show).get('[isEpisodic]')):
            episodeName = self.shotList.sequence.split("_")[0]
            self.sgEp = self._validateEp(episodeName)
            sequenceName = "_".join(self.shotList.sequence.split("_")[1:])
            self.sgSeq = self._validateSeqs(sequenceName)
        else:
            self.sgEp = None
            self.sgSeq = self._validateSeqs(self.shotList.sequence)

        self.removeProgress()

        # check for shots to create movies and upload to shotgun as version
        # if shots don't exists yet create a movie of the entire sequence and upload to shotgun as version

        if not self.markerShotLists:
            self.markerShotLists.append(self.shotList)

        self.addProgress(len(self.markerShotLists))
        for markerShot in self.markerShotLists:
            index = self.markerShotLists.index(markerShot)
            if markerShot.isMarker:
                self.sgShot = self._validateShot(markerShot)
                self._validateVersion(markerShot)
                # dialogue = shotsInfo[index][5]
                movie = shotMovies[index]
                mp3 = movie.replace(".mov", ".mp3")
                AudioUtils().localConvertAudio(movie, mp3)
                if not self.sgShot:
                    # self.sgShot = self.createSgShot(markerShot)
                    self.sgShot = self.createSgShot(markerShot,
                                                    shotsInfo[index])
                sgVersion = self.uploadSeqVersion(self.rePath.localize(movie),
                                                  self.rePath.localize(mp3),
                                                  self.sgShot,
                                                  comment=comment)
            else:
                self._validateVersion(markerShot)
                self.sgTask = self._validateTask()
                movie = self.createMov(markerShot)
                mp3 = movie.replace(".mov", ".mp3")
                AudioUtils().localConvertAudio(movie, mp3)
                sgVersion = self.uploadSeqVersion(self.rePath.localize(movie),
                                                  self.rePath.localize(mp3),
                                                  self.sgSeq,
                                                  self.sgTask,
                                                  comment=comment)

            # Validate that a FLIX playlist exists or else create one
            self.playlist = self._validatePlaylist()

            # update the FLIX playlist to add the new sgVersion
            self.updatePlaylist(self.playlist, sgVersion)
            self.removeProgress()

        ToShotgunGEAH.toFile(self, **self.kargs)

        autoMarkOmittedShots = self.mode['[sgAutoMarkOmittedShots]'] == "1"

        if autoMarkOmittedShots:
            self.autoMarkOmittedShots()

        self.removeProgress()

    #--------------------------------------------------------------------------
    # Shotgun Methods
    #--------------------------------------------------------------------------
    def _validateEp(self, episode):
        epField = 'sg_flixepname'
        pFilters = [['project', 'is', self.sgShow], [epField, 'is', episode]]
        pFields = ['id', 'code', 'sg_flixepname']
        sgEp = self.sg.find_one(kParamSgEpisodeEntity, pFilters, pFields)
        if sgEp:
            return sgEp
        else:
            raise ShotgunExceptions(msg="Could not find '%s' Episode in SG" %
                                    episode)

    #--------------------------------------------------------------------------

    def _validateSeqs(self, sequence):
        if self.sgEp is None:
            sequenceField = self.mode[KparamSGsequenceField]
            sFilters = [['project', 'is', self.sgShow],
                        [sequenceField, 'is', sequence]]
        else:
            sequenceField = 'sg_flixseqname'
            sFilters = [['project', 'is', self.sgShow],
                        ['sg_episode', 'is', self.sgEp],
                        [sequenceField, 'is', sequence]]
        sFields = ['id', 'code', 'content', sequenceField, 'sg_status_list']
        sgSeq = self.sg.find_one('Sequence', sFilters, sFields)
        if sgSeq:
            return sgSeq
        else:
            raise ShotgunExceptions(msg="Could not find '%s' Sequence in SG" %
                                    sequence)

    #--------------------------------------------------------------------------

    def _validateShotTaskTemplate(self):
        """ Gets the Task Template entity that each shot should be assigned (e.g. "Basic shot template")
        """
        tFilters = [['id', 'is', kParamSgShotTaskTemplateId]]
        tFields = ['id']
        sgShotTaskTemplate = self.sg.find_one('TaskTemplate', tFilters,
                                              tFields)
        return sgShotTaskTemplate

    #--------------------------------------------------------------------------

    def createSgShot(self, shotList, shotInfo):
        """create a new shotgun shot based on marker name
        """
        shotArgs = copy.copy(self.kargs)
        shotArgs['shot'] = shotList.isMarker
        shotName = self.mode.get(KparamSGshotName, shotArgs)
        taskTemplate = self._validateShotTaskTemplate()
        data = {
            'project': self.sgShow,
            'sg_sequence': self.sgSeq,
            'code': shotName,
            'sg_cut_duration': shotInfo['cut duration'],
            kParamSgDissolveInField: shotInfo['dissolve in'],
            kParamSgDissolveOutField: shotInfo['dissolve out'],
            kParamSgDialogueField: shotInfo['dialogue'],
            'sg_working_duration': shotInfo['working duration'],
            'task_template': taskTemplate
        }
        return self.sg.create('Shot', data, ['id', 'code'])

    #--------------------------------------------------------------------------

    def _validateVersionTask(self):
        """ Gets the Task entity that each version should be assigned (e.g. "Final Animatic")
        """
        tFilters = [['id', 'is', kParamSgVersionTaskId]]
        tFields = ['id']
        sgVersionTask = self.sg.find_one('Task', tFilters, tFields)
        return sgVersionTask

    #--------------------------------------------------------------------------

    def uploadSeqVersion(self,
                         movPath,
                         mp3Path,
                         entity,
                         sgTask='',
                         comment=u''):
        """Uploads the given movie path to the specific entity in shotgun
            adds a link back to FLIX as the comment
        """
        versionArgs = copy.copy(self.kargs)
        versionArgs['version'] = "%03d" % versionArgs['version']
        versionArgs['shot'] = entity.get('code', '')

        versionName = self.mode.get(
            "%s_%s_%s" %
            (self.sgEp["code"], self.sgSeq["code"], versionArgs["shot"]),
            versionArgs)

        description = "%s,\n%s %s %s" % (comment, self.sgEp["code"],
                                         self.sgSeq["code"],
                                         versionArgs["version"])

        data = {
            'project': self.sgShow,
            'code': versionName,
            'description': description,
            'sg_path_to_movie': movPath,
            'entity': entity,
            'sg_task': self._validateVersionTask()
        }
        if sgTask:
            data['sg_task'] = sgTask

        if not self.sgVersion:
            self.sgVersion = self.sg.create('Version', data, ['id'])
        else:
            self.sg.update('Version', self.sgVersion['id'], data)
        successUpload = False
        tryIter = 1
        while not successUpload:
            try:
                self.fileService.refreshCache(movPath)
                self.sg.upload('Version', self.sgVersion['id'], movPath,
                               'sg_uploaded_movie')
                self.sg.upload('Version', self.sgVersion['id'], mp3Path,
                               'sg_uploaded_audio')
                successUpload = True
                return self.sgVersion
            except urllib2.URLError, err:
                if tryIter < 3:
                    tryIter += 1
                    log('Failed to connect\nAttempt %01d of 3 to connect to SG'
                        % int(tryIter),
                        isWarning=True)
                    continue
                raise err
Exemple #13
0
class PictureInPicture(PluginDecorator):

    #--------------------------------------------------------------------------
    # object
    #--------------------------------------------------------------------------

    def __init__(self):
        self.fileService = fileService
        self.rePath = RepathDefault()
        self.fileServiceLocal = flix.fileServices.fileLocal.FileLocal()
        self.serverFlixFunctions = ServerFlixFunctions()

        self.shotList = ''

        # load the icon
        iconPath = Mode().get(
            '[FLIX_CONFIG_FOLDER]') + '/plugins/icons/custom_icon.png'
        icon = self.fileService.loadByteArray(iconPath)

        self.init(
            label='Picture In Picture',
            icon=icon,
            tooltip='Picture In Picture',
            group='Maya',
            pluginPath='flixConfig.plugins.pictureInPicture.PictureInPicture')

    #--------------------------------------------------------------------------
    # executions
    #--------------------------------------------------------------------------

    def execute(self, shotCutList, selection, additionalData=None):
        setattr(self, 'selection', selection)

        self.shotList = flix.core2.shotCutList.ShotCutList.fromFile(
            shotCutList.defaultPath())
        self.mode = self.shotList.mode

        # For each selected panel
        for p in self.selection:
            shot = self.shotList[p]
            if shot.isMarker():
                continue
            # Get the path to the layout panel's jpeg (thumbnail)
            layoutPanelJpegPath = self._getPanelFilePath(shot)
            # Find which version is the latest board (i.e. not from Maya)
            latestBoard = self._getLatestStoryVersion(shot)
            if latestBoard is None:
                log("%s has no non-Maya version." % shot)
                continue
            log("latestBoard: %s" % latestBoard)
            # Get the path to the story panel's jpeg (thumbnail)
            latestBoardJpegPath = self._getPanelFilePath(latestBoard)
            # Create nk script using the paths to both jpeg files
            self.renderPip(layoutPanelJpegPath, latestBoardJpegPath,
                           int(self.mode.get('[yResolution]')),
                           int(self.mode.get('[xResolution]')))
            # Refresh the cache and thumbnail in Flix
            self.fileServiceLocal.refreshCache(layoutPanelJpegPath)
            log('__renderCallback:: Reloading image %s' %
                self.rePath.localize(layoutPanelJpegPath))
            self.serverFlixFunctions.addFeedback("reloadImages",
                                                 [layoutPanelJpegPath])

    #--------------------------------------------------------------------------
    # methods
    #--------------------------------------------------------------------------
    def _getPanelFilePath(self, shot):
        """ Get the path to the shot's thumbnail jpeg
        """
        kargs = {
            'beat': shot.beat,
            'setup': shot.setup,
            'version': shot.version,
            'frame': "%04d" % shot.markInFrame
        }
        return self.shotList.mode.get('[recipeCompedFile]', kargs)

    def _getLatestStoryVersion(self, shot):
        """ Get the latest story version of a panel (i.e. not coming from Maya)
        """
        for v in self._getRelatedVersions(shot):
            if v["version"] == shot.version:
                continue
            s = flix.core2.shot.Shot(shot.show, shot.sequence, v["beat"],
                                     v["setup"], v["version"])
            # Right now we assume if the panel's got a thirdPartyMetaData.json file, it comes from Maya and if not, it comes from story
            if not self.fileServiceLocal.exists(
                    s.recipe.getThirdPartyMetaDataPath()):
                return s
        return None

    def _getRelatedVersions(self, shot):
        """ Get all the related versions for the given panel
        """
        versions = FlixCore().getRelatedVersion(shot)
        versions.reverse()
        return versions

    @flix.remote.autoRemote(flix.remote.kProcGroupNuke)
    def renderPip(self, read1, read2, yRes, xRes):
        """ Create the Nuke script and execute it to render the new thumbnail
        """
        # Clear the nk script
        FlixNuke().clearScript()
        # Tweak this parameter for the pic in pic to be smaller(down to 0) or bigger (up to 1)
        scale = 0.25
        # Create the read nodes for both the layout and board panels
        readNode1 = nuke.createNode("Read",
                                    "file {%s}" % self.rePath.localize(read1))
        readNode2 = nuke.createNode("Read",
                                    "file {%s}" % self.rePath.localize(read2))
        # Create the transform node to resize and move the board to the bottom right hand corner
        transformNode = nuke.createNode("Transform")
        transformNode.setInput(0, readNode2)
        transformNode["scale"].setValue(scale)
        ytranslate = yRes * (scale - 1) / 2
        xtranslate = xRes * (1 - scale) / 2
        transformNode["translate"].setValue([xtranslate, ytranslate])
        # Create the merge node that puts the board over the layout panel
        mergeNode = nuke.createNode("Merge2")
        mergeNode.setInput(1, transformNode)
        mergeNode.setInput(0, readNode1)
        # Create the Write node to render the thumbnail
        writeNode = nuke.createNode("Write")
        writeNode["file"].setValue(self.rePath.localize(read1))
        # Execute the script to render the thumbnail
        nuke.execute(writeNode["name"].getValue(), 1, 1, 1)
        # Comment out to actually save the nk script to troubleshoot or modify
        # nuke.scriptSave(self.rePath.localize(read1.replace(".jpg", ".nk")))
        # Clear the nk script
        FlixNuke().clearScript()
Exemple #14
0
class ToMovPerShot(PluginDecorator):

    #--------------------------------------------------------------------------
    # object
    #--------------------------------------------------------------------------

    def __init__(self, shotCutList=''):
        self.fileService = flix.fileServices.FileService()
        self.fileServiceLocal = flix.fileServices.fileLocal.FileLocal()
        self.rePath = RepathDefault()
        # self.shotList    = shotCutList
        if shotCutList != '':
            self.shotList = flix.core2.shotCutList.ShotCutList.fromFile(
                shotCutList.defaultPath())
            self.kargs = {
                'show': self.shotList.show,
                'sequence': self.shotList.sequence,
                'branch': self.shotList.branch,
                'version': self.shotList.version
            }
            self.mode = self.shotList.mode
            self.movDir = self.mode.get("[editorialMOVFolder]")

        # load the icon
        iconPath = flix.core2.mode.Mode().get(
            '[FLIX_FOLDER]') + '/assets/20px-quicktime.png'
        icon = self.fileService.loadByteArray(iconPath)

        self.init(label='QuickTime per Shot',
                  icon=icon,
                  tooltip='QuickTime per Shot',
                  group='Export',
                  pluginPath='flixConfig.plugins.toMovPerShot.ToMovPerShot')

    #--------------------------------------------------------------------------
    # executions
    #--------------------------------------------------------------------------

    def execute(self, shotCutList, selection, additionalData=None):
        self.shotList = flix.core2.shotCutList.ShotCutList.fromFile(
            shotCutList.defaultPath())
        self.kargs = {
            'show': self.shotList.show,
            'sequence': self.shotList.sequence,
            'branch': self.shotList.branch,
            'version': self.shotList.version
        }
        self.mode = self.shotList.mode
        self.movDir = self.mode.get("[editorialMOVFolder]")
        movieFileName = self.shotList.refVideoFilename
        if movieFileName is None:
            raise flix.exceptions.FlixException(
                msg="Current version does not have an editorial movie.",
                notify=True)
        else:
            movieFile = "%s/%s" % (self.movDir, movieFileName)
            log("Movie File: %s" % movieFile)

        self.addProgress(5)
        output = OSUtils.runFileBrowser(kBrowseTypeFolderUsingSaveFile,
                                        'Choose a folder', '/', 'toMovPerShot')
        self.removeProgress(5)
        # escape output path
        output = escape(output.decode('utf-8'))
        if not output or not os.path.isdir(output):
            raise flix.exceptions.FlixException(
                error=output, msg='No Valid directory selected.', notify=False)

        shotInfoObject = ShotInfo(self.shotList)
        shots = shotInfoObject.getShotsInfo()
        self.addProgress(len(shots))

        shotMovies = self.toMovPerShot(shots, movieFile)
        for shotMovie in shotMovies:
            self.fileService.copy(shotMovie, output)

        OSUtils().revealFiles([output])

    #--------------------------------------------------------------------------
    # methods
    #--------------------------------------------------------------------------
    def toMovPerShot(self, shots, movieFile):
        shotMovies = []

        seqName = "%s_v%s_" % (self.shotList.sequence, self.shotList.version)
        for shot in shots:
            # If it's a middle shot, cut the movie in 3 and take the middle part
            segments = str(shot['first frame'] - 1) + "," + str(
                shot['last frame'])
            segment = 1
            if shot is shots[0]:
                # If it's the first shot, cut the movie in 2 and take the 1st part
                segments = str(shot['last frame'])
                segment = 0
            # Get the MOV proc to cut the movie
            self.breakDownMov(movieFile, segments)
            # Rename the randomly named shots with the proper shotlabels and copy them to their respective directories
            toReplace = str(segment).zfill(3) + ".tmp"
            oldName = self.movDir + "/" + toReplace + ".mov"
            shotDir = "%s/%s" % (self.movDir, shot['shot label'])
            self.fileService.createFolders(shotDir)
            newName = oldName.replace(
                toReplace,
                "%s/%s%s" % (shot['shot label'], seqName, shot['shot label']))
            self.fileService.rename(oldName, newName)
            shotMovies.append(newName)
            self.removeProgress(1)
        # Delete unused cut segments
        toDelete = [self.movDir + "/000.tmp.mov", self.movDir + "/002.tmp.mov"]
        for f in toDelete:
            self.fileService.removeFile(f)
        return shotMovies

    @flix.remote.autoRemote(flix.remote.kProcGroupMov, firstProcOnly=True)
    def breakDownMov(self, movieFile, segments):
        ffmpeg = os.environ.get("FLIX_FFMPEG")
        source = self.rePath.localize(movieFile)
        movDir = os.path.abspath(os.path.join(source, os.pardir))
        destination = movDir + "/%03d.tmp.mov"
        # ToMov().setLibraryPaths()
        self.setLibraryPaths()
        cmd = "%(ffmpeg)s -i %(source)s -f segment -segment_frames %(segments)s -c copy -map 0 -reset_timestamps 1 \"%(destination)s\"" % locals(
        )
        log("ffmpeg cmd: %s" % cmd)
        flix.utilities.osUtils.OSUtils.quickCall(cmd,
                                                 cwd=os.path.dirname(ffmpeg))

    def setLibraryPaths(self):
        ffmpegFolder = os.path.dirname(os.environ.get('FLIX_FFMPEG'))
        ffmpegLibs = "/".join([ffmpegFolder, "lib"])
        lameLibs = flix.thirdParty.getLameLibPath()
        if ffmpegLibs not in os.environ.get('LD_LIBRARY_PATH'):
            os.environ["LD_LIBRARY_PATH"] = ":".join(
                [ffmpegLibs, os.environ.get('LD_LIBRARY_PATH')])
        if lameLibs not in os.environ.get('LD_LIBRARY_PATH'):
            os.environ["LD_LIBRARY_PATH"] = ":".join(
                [lameLibs, os.environ.get('LD_LIBRARY_PATH')])
Exemple #15
0
class ToShotgunCustom(PluginDecorator):

    #--------------------------------------------------------------------------
    # Static
    #--------------------------------------------------------------------------
    @staticmethod
    def toFile(obj, **kwargs):
        ''' write out the shotgun publish
        '''
        sgPubPath = obj.shotList.mode.get('[sgPublishFolder]', kwargs)
        if fileService.exists(sgPubPath):
            fileService.copyToLocal(sgPubPath)
            return
        if not fileService.exists(os.path.dirname(sgPubPath)):
            fileService.createFolders(os.path.dirname(sgPubPath))
        log(sgPubPath, isInfo=True)
        fileService.saveJsonFile(sgPubPath, kwargs)

    #--------------------------------------------------------------------------
    # object
    #--------------------------------------------------------------------------

    def __init__(self):
        self.fileService = fileService
        self.rePath = RepathDefault()

        self.shotList = ''
        self.sg = None
        self.sgShow = ''
        self.sgSeq = ''
        self.sgShot = ''
        self.sgTask = ''

        # load the icon
        iconPath = Mode().get('[FLIX_FOLDER]') + '/assets/20px-shotgun.png'
        icon = self.fileService.loadByteArray(iconPath)

        self.init(
            label='Shotgun Publish Custom',
            icon=icon,
            tooltip='Shotgun Publish Custom',
            group='Editorial',
            pluginPath='flixConfig.plugins.toShotgunCustom.ToShotgunCustom')

    #--------------------------------------------------------------------------
    # executions
    #--------------------------------------------------------------------------

    def shotgunPublish(self, source, output):
        setattr(self, 'shotList', ShotCutList.fromFile(source))
        self.execute(self.shotList, [], output)

    #--------------------------------------------------------------------------

    def execute(self, shotCutList, selection, additionalData=None):
        if not additionalData is None:
            referenceCutList = additionalData.get('reference', None)
            comment = additionalData.get('comment', "")
        else:
            comment = ''

        comment = unicode(urllib.unquote_plus(comment))
        self.shotList = flix.core2.shotCutList.ShotCutList.fromFile(
            shotCutList.defaultPath())
        self.kargs = {
            'show': self.shotList.show,
            'sequence': self.shotList.sequence,
            'branch': self.shotList.branch,
            'version': self.shotList.version
        }
        self.mode = self.shotList.mode

        self.addProgress(4)

        markerShotLists = self.getMarkerList(self.shotList)

        self.removeProgress()
        self.sg = self._connectToSG(self.mode)
        self.removeProgress()

        self.seqUrl = self.getSequenceUrl()

        # validate that all information for Flix has an equivalent in shotgun
        self.sgShow = self._validateShow(self.shotList.show)
        if int(Mode(self.shotList.show).get('[isEpisodic]')):
            episodeName = self.shotList.sequence.split("_")[0]
            self.sgEp = self._validateEp(episodeName)
            sequenceName = self.shotList.sequence.split("_")[1]
            self.sgSeq = self._validateSeqs(sequenceName)
        else:
            self.sgEp = None
            self.sgSeq = self._validateSeqs(self.shotList.sequence)

        self.removeProgress()

        # check for shots to create movies and upload to shotgun as version
        # if shots don't exists yet create a movie of the entire sequence and upload to shotgun as version

        if not markerShotLists:
            markerShotLists.append(self.shotList)

        self.addProgress(len(markerShotLists))
        self.markIn = 1
        self.markOut = 0
        for markerShot in markerShotLists:
            if markerShot.isMarker:
                for shot in markerShot:
                    self.markOut += int(round(shot.duration))
                self.sgShot = self._validateShot(markerShot)
                self._validateVersion(markerShot)
                tupleMarker = (markerShot, self.getShotsIndex(markerShot))
                movie = self.createMov(tupleMarker)
                self.markIn += self.markOut
                if not self.sgShot:
                    self.sgShot = self.createSgShot(markerShot)
                sgVersion = self.uploadSeqVersion(movie,
                                                  self.sgShot,
                                                  comment=comment)
            else:
                self._validateVersion(markerShot)
                self.sgTask = self._validateTask()
                movie = self.createMov(markerShot)
                sgVersion = self.uploadSeqVersion(movie,
                                                  self.sgSeq,
                                                  self.sgTask,
                                                  comment=comment)

            # Validate that a FLIX playlist exists or else create one
            self.playlist = self._validatePlaylist()

            # update the FLIX playlist to add the new sgVersion
            self.updatePlaylist(self.playlist, sgVersion)
            self.removeProgress()

        ToShotgunCustom.toFile(self, **self.kargs)

        autoMarkOmittedShots = self.mode['[sgAutoMarkOmittedShots]'] == "1"

        if autoMarkOmittedShots:
            self.autoMarkOmittedShots()

        self.removeProgress()

    #--------------------------------------------------------------------------
    # methods
    #--------------------------------------------------------------------------

    @flix.remote.autoRemote(flix.remote.kProcGroupFile, lockProc=False)
    def getPublishedVersions(self, show, sequence, branch):
        """Return an array of the versions that were published to editorial
        """
        matches = Mode(show, sequence).getMatches('[sgPublishFolder]',
                                                  {'version': '*'})
        versions = []
        for m in matches:
            try:
                versions.append(int(m['version']))
            except ValueError:
                pass
        return versions

    #--------------------------------------------------------------------------
    @flix.remote.autoRemote(flix.remote.kProcGroupFile, lockProc=False)
    def getPublishedSetups(self, show, sequence):
        """Return an array of the versions that were published to editorial
        """
        pass

    #--------------------------------------------------------------------------

    def createMov(self, shotList):
        """creates a movie of the given shotcutlist
        """
        toMov = ToMov()
        toMov.compBuild(shotList)
        return self.rePath.localize(toMov.movieName)

    #--------------------------------------------------------------------------

    def uploadSeqVersion(self, movPath, entity, sgTask='', comment=u''):
        """Uploads the given movie path to the specific entity in shotgun
            adds a link back to FLIX as the comment
        """
        versionArgs = copy.copy(self.kargs)
        versionArgs['version'] = "%03d" % versionArgs['version']
        versionArgs['shot'] = entity.get('code', '')

        versionName = self.mode.get(KparamSGversionName, versionArgs)

        comment += "\n%s" % self.seqUrl

        data = {
            'project': self.sgShow,
            'code': versionName,
            'description': comment,
            'sg_path_to_movie': movPath,
            'entity': entity
        }
        if sgTask:
            data['sg_task'] = sgTask

        if not self.sgVersion:
            self.sgVersion = self.sg.create('Version', data, ['id'])
        else:
            self.sg.update('Version', self.sgVersion['id'], data)
        successUpload = False
        tryIter = 1
        while not successUpload:
            try:
                self.fileService.refreshCache(movPath)
                self.sg.upload('Version', self.sgVersion['id'], movPath,
                               'sg_uploaded_movie')
                successUpload = True
                return self.sgVersion
            except urllib2.URLError, err:
                if tryIter < 3:
                    tryIter += 1
                    log('Failed to connect\nAttempt %01d of 3 to connect to SG'
                        % int(tryIter),
                        isWarning=True)
                    continue
                raise err
class ToMovPerShot(PluginDecorator):

    #--------------------------------------------------------------------------
    # object
    #--------------------------------------------------------------------------

    def __init__(self):
        self.fileService = flix.fileServices.FileService()
        self.fileServiceLocal = flix.fileServices.fileLocal.FileLocal()
        self.rePath = RepathDefault()

        self.shotList = ''

        # load the icon
        iconPath = flix.core2.mode.Mode().get(
            '[FLIX_FOLDER]') + '/assets/20px-quicktime.png'
        icon = self.fileService.loadByteArray(iconPath)

        self.init(label='QuickTime per Shot',
                  icon=icon,
                  tooltip='QuickTime per Shot',
                  group='Export',
                  pluginPath='flixConfig.plugins.toMovPerShot.ToMovPerShot')

    #--------------------------------------------------------------------------
    # executions
    #--------------------------------------------------------------------------

    def execute(self, shotCutList, selection, additionalData=None):
        self.shotList = flix.core2.shotCutList.ShotCutList.fromFile(
            shotCutList.defaultPath())
        self.kargs = {
            'show': self.shotList.show,
            'sequence': self.shotList.sequence,
            'branch': self.shotList.branch,
            'version': self.shotList.version
        }
        self.mode = self.shotList.mode
        self.movDir = self.mode.get("[editorialMOVFolder]")
        movieFile = self.getMovFilePath()
        if movieFile is None:
            raise flix.exceptions.FlixException(
                msg="Current version does not have an editorial movie.",
                notify=True)
        else:
            log("Movie File: %s" % movieFile)

        self.addProgress(5)
        output = OSUtils.runFileBrowser(kBrowseTypeFolderUsingSaveFile,
                                        'Choose a folder', '/', 'toMovPerShot')
        self.removeProgress(5)
        # escape output path
        output = escape(output.decode('utf-8'))
        if not output or not os.path.isdir(output):
            raise flix.exceptions.FlixException(
                error=output, msg='No Valid directory selected.', notify=False)

        shotsInfo = self.getShotsInfo()

        shotMovies = self.toMovPerShot(shotsInfo, movieFile)
        for shotMovie in shotMovies:
            self.fileService.copy(shotMovie, output)

        OSUtils().revealFiles([output])

    #--------------------------------------------------------------------------
    # methods
    #--------------------------------------------------------------------------
    def getMovFilePath(self):
        movieFileName = self.shotList.refVideoFilename
        if movieFileName is not None:
            return "%s/%s" % (self.movDir, movieFileName)

    def getShotsInfo(self):
        markerList = MarkerList.fromShotCutList(self.shotList)
        self.addProgress(len(markerList))
        shotLabels = []
        for marker in markerList:
            shotLabels.append(marker.name)
        markerShotLists = MarkerList.markerShotCutList(self.shotList,
                                                       markerList)
        if not markerShotLists:
            markerShotLists.append(self.shotList)

        # List of shot info of the form [[shotLabel, firstFrame, lastFrame, dissolveIn, dissolveOut]]
        newShots = []
        firstFrame = 0
        lastFrame = 0
        dialogue = ""
        sequencePanelIndex = 0
        for markerShot in markerShotLists:
            if markerShot.isMarker:
                shotLabel = shotLabels[markerShotLists.index(markerShot)]
                for shot in markerShot:
                    sequencePanelIndex += 1
                    duration = self.shotList[sequencePanelIndex].duration
                    lastFrame += int(round(duration))
                    if shot is markerShot[-1]:
                        dissolveOut = int(round(shot.dissolveOut))
                    if shot is markerShot[0]:
                        dissolveIn = int(round(shot.dissolveIn))
                    newDialogue = str(shot.recipe.getPoses()[0]['dialogue'])
                    if newDialogue != "":
                        dialogue = "\n".join([dialogue, newDialogue])
                newShots.append([
                    shotLabel, firstFrame, lastFrame - 1 + dissolveOut,
                    dissolveIn, dissolveOut, dialogue
                ])
                firstFrame = lastFrame - dissolveOut
                sequencePanelIndex += 1
        log("newShots: %s" % newShots)
        return newShots

    def toMovPerShot(self, shots, movieFile):
        shotMovies = []

        seqName = "%s_v%s_" % (self.shotList.sequence, self.shotList.version)
        for shot in shots:
            # If it's a middle shot, cut the movie in 3 and take the middle part
            segments = str(shot[1] - 1) + "," + str(shot[2])
            segment = 1
            if shot is shots[0]:
                # If it's the first shot, cut the movie in 2 and take the 1st part
                segments = str(shot[2] + 1)
                segment = 0
            elif shot is shots[-1]:
                # If it's the last shot, cut the movie in 2 and take the 2nd part
                segments = str(shot[1])
            # Get the MOV proc to cut the movie
            self.breakDownMov(movieFile, segments)
            # Rename the randomly named shots with the proper shotlabels and copy them to their respective directories
            toReplace = str(segment).zfill(3) + ".tmp"
            oldName = self.movDir + "/" + toReplace + ".mov"
            shotDir = "%s/%s" % (self.movDir, shot[0])
            self.fileService.createFolders(shotDir)
            newName = oldName.replace(toReplace,
                                      "%s/%s%s" % (shot[0], seqName, shot[0]))
            self.fileService.rename(oldName, newName)
            shotMovies.append(newName)
            self.removeProgress(1)
        # Delete unused cut segments
        toDelete = [self.movDir + "/000.tmp.mov", self.movDir + "/002.tmp.mov"]
        for f in toDelete:
            self.fileService.removeFile(f)
        return shotMovies

    @flix.remote.autoRemote(flix.remote.kProcGroupMov, firstProcOnly=True)
    def breakDownMov(self, movieFile, segments):
        ffmpeg = os.environ.get("FLIX_FFMPEG")
        source = self.rePath.localize(movieFile)
        movDir = os.path.abspath(os.path.join(source, os.pardir))
        destination = movDir + "/%03d.tmp.mov"
        ToMov().setLibraryPaths()
        cmd = "%(ffmpeg)s -i %(source)s -f segment -segment_frames %(segments)s -c copy -map 0 -reset_timestamps 1 \"%(destination)s\"" % locals(
        )
        log("ffmpeg cmd: %s" % cmd)
        flix.utilities.osUtils.OSUtils.quickCall(cmd,
                                                 cwd=os.path.dirname(ffmpeg))