Beispiel #1
0
    def execute(self, shotCutList, selection, additionalData=None):
        self.shotList = flix.core2.shotCutList.ShotCutList.fromFile(
            shotCutList.defaultPath())
        self.mode = self.shotList.mode

        shotNumber = int(self.mode.get(kMarkerNameIncrement))
        data = []
        data.append('<Recipies>')
        for shot in self.shotList:
            if shot.isMarker():
                recipe = shot.recipe
                properties = recipe.getProperties()
                newName = self.mode.get(kMarkerNameRegex) % shotNumber
                poses = recipe.getPoses()
                poseXML = poses[0]['poseXML']
                poseXML.attrib['dialogue'] = newName
                recipe.saveRecipeFiles()
                data.append(
                    '<Setup show="%(show)s" sequence="%(sequence)s" beat="%(beat)s" setup="%(setup)s" version="%(version)s">'
                    % recipe.getProperties())
                data.append(
                    ET.tostring(recipe.getMultiTrackXML()) + "</Setup>")
                shotNumber += int(self.mode.get(kMarkerNameIncrement))
        data.append("</Recipies>")
        dataString = "".join(data)
        log("DATASTRING: %s" % dataString)
        self.serverFlixFunctions.addFeedback('reloadSetupsMultiTracks',
                                             dataString)
Beispiel #2
0
    def emailResult(self):

    # email publish summary
        try:
            publishTemplateName = self.shotCutList.mode[fromFCP.kParamImportTemplate]
            publishSummary      = flix.utilities.template.render(publishTemplateName, **{
                'cutlist'          : self.shotCutList,
                'comment'          : self.comment,
                })
            show = self.shotCutList.show
            sequence = self.shotCutList.sequence

            # grab tracking code for sequence
            trackingCode = flix.core.sequence.Sequence(show, sequence).getTrackingIndex()
            mode = self.shotCutList.mode
            kargs = {}
            # compile subject
            kargs['[trackingCode]']        = (" %s" % trackingCode).rstrip()
            kargs['[sequenceInfo]']        = "[show]/[sequence][trackingCode]"
            kargs['[emailSubjectMessage]'] = "From Nuke Studio [sequenceInfo]"
            kargs['[emailSubjectComment]'] = self.comment

            # email summary
            log("Nuke Studio: Emailing Publish Summary: %s" % kargs)
            with mode.using(kargs):
                flix.utilities.email.sendHtmlEmail(
                    '[FLIX_USER]@[domain]', '[emailFromEditorial]',
                    '[emailFullSubject]', publishSummary, mode)

        # email error to support
        except Exception, e:
            log('Publish email summary failed.%s' % e, trace=True, isError=True)
Beispiel #3
0
 def __init__(self):
     """Initialize the plugins that will show up in Flix gui"""
     super(LocalPluginConfig, self).__init__()
     try:
         # Edit plugins
         PhotoshopEachFile().default()
         # Maya plugins
         PictureInPicture()
         # PDF plugins
         ToPDFSelection()
         ToPDFShots()
         # Export plugins
         ToMovDialogue()
         ToMovPerShot()
         ToShotgunGEAH()
         RenameMarkers()
         LogShotMarkers()
         LogMultipleShotEdits()
         NukeTestEA()
         # Import plugins
         ImportDialogue()
         ShotsToCSV()
         ToAvidCopy()
     except Exception, e:
         log("Failed to initialize a custom plugin: %s" % e, isError=True)
Beispiel #4
0
    def breakdownMovie(self):
        """Export out the frames and audio from the movie"""

        frameRanges = []
        for c in self.mergedClips:
            recipe = c.recipe
            if isinstance(recipe, dict):
                frameRanges.append([recipe['refStart'], recipe['refEnd']])

        log('FrameRanges %s' % frameRanges, isInfo=True)

        self.sound = ''
        self.refMovie = ''

        if self.movie != '' and self.movie is not None:
            movFolder = self.mode.get('[editorialMOVFolder]')
            if not self.fileService.exists(os.path.dirname(movFolder)):
                self.fileService.createFolders(os.path.dirname(movFolder))
            tempMov = "%s/%s"%(movFolder, os.path.basename(self.movie))
            self.fileService.copy(self.movie, tempMov)
            self.fromMov = self.remoteExecute(1000, "FromMovNuke.convert", self.show, self.sequence, self.editVersion, tempMov, frameRanges, self.lookupFile)
            if isinstance(self.fromMov, remoting.ErrorFault):
                self.fromMov.raiseException()
            self.verifyRefImages(frameRanges)
            self.sound = self.fromMov['mp3']
            self.refMovie = self.fromMov['mov']
Beispiel #5
0
 def getPanelDialogueLines(self, panels, dialogueFileContent):
     """ Returns a dictionary listing the first and last dialogue lines for each panel
     """
     panelDialogueLines = {}
     previousPanel = None
     for panel in panels:
         # Panels with no dialogue get set to -1
         panelDialogueLines[panel] = [-1]
         # Ignore Markers
         if "marker" in panel:
             continue
         panelName = "%s:\n" % panel
         # If this panel has dialogue associated to it in the text file
         if panelName in dialogueFileContent:
             # Record the first line of dialogue for this panel
             panelDialogueLines[panel] = [
                 dialogueFileContent.index(panelName) + 1
             ]
             if previousPanel is not None:
                 # Record the last line of dialogue for the previous panel
                 panelDialogueLines[previousPanel].append(
                     dialogueFileContent.index(panelName) - 2)
             if panel == panels[-1]:
                 panelDialogueLines[panel].append(
                     len(dialogueFileContent) - 1)
             else:
                 previousPanel = panel
     log("PANELDIALOGUELINES: %s" % panelDialogueLines)
     return panelDialogueLines
Beispiel #6
0
    def _validateVersion(self, shotList):
        versionArgs = copy.copy(self.kargs)
        versionArgs['version'] = "%03d" % versionArgs['version']
        if getattr(shotList, 'isMarker'):
            versionArgs['shot'] = shotList.isMarker
        else:
            versionArgs['shot'] = versionArgs.get('sequence')

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

        filters = [['entity', 'is', self.sgSeq]]
        if self.sgShot:
            filters = [['entity', 'is', self.sgShot]]

        vFilters = [['code', 'is', versionName], {
            'filter_operator': 'any',
            'filters': filters
        }]

        self.sgVersion = self.sg.find_one('Version', vFilters)
        log(versionName, isInfo=True)
        log(self.sgVersion, isInfo=True)
        if self.sgVersion:
            raise ShotgunExceptions(
                msg="A SG version already exists for your current edit.",
                error={
                    'moviePath': versionName,
                    'SGversion': self.sgVersion
                })
    def breakdownMovie(self):
        """Export out the frames and audio from the movie"""

        frameRanges = []
        for c in self.mergedClips:
            recipe = c.recipe
            if isinstance(recipe, dict):
                frameRanges.append([recipe['refStart'], recipe['refEnd']])

        log('FrameRanges %s' % frameRanges, isInfo=True)

        self.sound = ''
        self.refMovie = ''

        if self.movie != '' and self.movie is not None:
            movFolder = self.mode.get('[editorialMOVFolder]')
            if not self.fileService.exists(os.path.dirname(movFolder)):
                self.fileService.createFolders(os.path.dirname(movFolder))
            tempMov = "%s/%s" % (movFolder, os.path.basename(self.movie))
            self.fileService.copy(self.movie, tempMov)
            self.fromMov = self.remoteExecute(1000, "FromMovNuke.convert",
                                              self.show, self.sequence,
                                              self.editVersion, tempMov,
                                              frameRanges, self.lookupFile)
            if isinstance(self.fromMov, remoting.ErrorFault):
                self.fromMov.raiseException()
            self.verifyRefImages(frameRanges)
            self.sound = self.fromMov['mp3']
            self.refMovie = self.fromMov['mov']
 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)
Beispiel #9
0
    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
Beispiel #10
0
 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)
Beispiel #11
0
 def _validateShow(self, show):
     showField = self.mode[KparamSGshowField]
     log("showField: %s" % showField)
     pFilters = [[showField, 'is', show]]
     pFields = ['id', 'name']
     sgShow = self.sg.find_one('Project', pFilters, pFields)
     if sgShow:
         return sgShow
     else:
         raise ShotgunExceptions(msg="Could not find '%s' Project in SG" %
                                 show)
 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))
    def getRecipePropertiesFromClip(self, clip, name=None):

        if name:
            parts = name.split("_")
        else:
            if clip.name.startswith('_uuid_'):
                return None
            parts = clip.name.split(" ")[0]
            parts = parts.split("-")
        properties = {}

        # todo verify the sequence exists
        log("*** fromNukeStudio: getRecipePropertiesFromClip - clip: %s, name %s, parts: %s"
            % (str(clip), str(name), str(parts)),
            isInfo=True)

        if len(parts) == 3:
            # parse the name if the version is missing
            properties["show"] = self.show
            properties["sequence"] = parts[0]
            properties["beat"] = parts[1]
            properties["setup"] = parts[2]
            properties["version"] = "1"
            return properties
        elif len(parts) > 3:
            properties["show"] = self.show
            properties["sequence"] = ''.join(parts[0:-3])
            properties["beat"] = parts[-3]
            properties["setup"] = parts[-2]
            properties["version"] = "1"
            if parts[-1].isdigit():
                properties["version"] = parts[-1]
            return properties

        # Nuke Studio Clip names use underscores for clipitem names
        elif len(parts) == 1:
            clipNameParts = parts[0].split(
                '_')  # parts e.g: ['hum', 'p', '1033', 'v2.hd']

            # We need four parts of the Clip name... if not it's ref
            if len(clipNameParts) != 4:
                return None

            properties["show"] = self.show
            properties["sequence"] = clipNameParts[0]
            properties["beat"] = clipNameParts[1]
            properties["setup"] = clipNameParts[2]
            properties["version"] = clipNameParts[3].replace('v', '').replace(
                '.hd', '')
            if not properties["version"].isdigit():
                properties["version"] = "1"
            return properties

        return None
Beispiel #14
0
    def getRecipePropertiesFromClip(self, clip, name=None):

        if name:
            parts = name.split("_")
        else:
            if clip.name.startswith('_uuid_'):
                return None
            parts = clip.name.split(" ")[0]
            parts = parts.split("-")
        properties = {}

        # todo verify the sequence exists
        log("*** fromNukeStudio: getRecipePropertiesFromClip - clip: %s, name %s, parts: %s" % (str(clip), str(name), str(parts)), isInfo=True)

        if len(parts) == 3:
            # parse the name if the version is missing
            properties["show"] = self.show
            properties["sequence"] = parts[0]
            properties["beat"] = parts[1]
            properties["setup"] = parts[2]
            properties["version"] = "1"
            return properties
        elif len(parts) > 3:
            properties["show"] = self.show
            properties["sequence"] = ''.join(parts[0:-3])
            properties["beat"] = parts[-3]
            properties["setup"] = parts[-2]
            properties["version"] = "1"
            if parts[-1].isdigit():
                properties["version"] = parts[-1]
            return properties

        # Nuke Studio Clip names use underscores for clipitem names
        elif len(parts) == 1:
            clipNameParts = parts[0].split('_') # parts e.g: ['hum', 'p', '1033', 'v2.hd']
            
            # We need four parts of the Clip name... if not it's ref
            if len(clipNameParts) != 4:
                return None

            properties["show"] = self.show
            properties["sequence"] = clipNameParts[0]
            properties["beat"] = clipNameParts[1]
            properties["setup"] = clipNameParts[2]
            properties["version"] = clipNameParts[3].replace('v','').replace('.hd','')
            if not properties["version"].isdigit():
                properties["version"] = "1"
            return properties

        return None
Beispiel #15
0
    def emailSummary(self):
        # publish the cutlist
        publishSummary = self.getSummary()

        # # save publish summary
        publishPath = AvidWorkflow().getPublishPath(self.__shotCutList)
        publishDirectory = os.path.dirname(publishPath)
        if not self.fileServiceLocal.exists(publishDirectory):
            self.fileService.createFolders(publishDirectory)
        self.fileService.saveUtfTextFile(
            publishPath,
            urllib.unquote_plus(str(publishSummary)).decode('utf8'))
        # email publish summary
        try:

            show = self.__shotCutList.show
            sequence = self.__shotCutList.sequence

            # grab tracking code for sequence
            trackingCode = Sequence(show, sequence).getTrackingIndex()
            mode = self.__shotCutList.mode
            kargs = {}
            # compile subject
            kargs['[trackingCode]'] = (" %s" % trackingCode).rstrip()
            kargs['[sequenceInfo]'] = "[show]/[sequence][trackingCode]"
            kargs['[result]'] = '' if len(
                self.__errors) == 0 else 'INCOMPLETE '
            kargs['[emailSubjectMessage]'] = "[result]To Avid [sequenceInfo]"
            kargs['[emailSubjectComment]'] = self.__comment

            # email summary
            log("Avid: Emailing Publish Summary: %s" % kargs)
            with mode.using(kargs):
                flix.utilities.email.sendHtmlEmail('[defaultEmailSender]',
                                                   '[emailToEditorial]',
                                                   '[emailFullSubject]',
                                                   publishSummary, mode)

        # email error to support
        except Exception, e:
            log('Publish email summary failed.%s' % e,
                trace=True,
                isError=True)
            subject = "Avid '%s'" % self.__shotCutList.mode[
                kParamShotCutListFile]
            flix.utilities.email.sendSupportErrorEmail(subject, e)
Beispiel #16
0
    def toMov(self, source):
        """
        Create a standard movie for playback from a fle xml file
        """
        mode = flix.core2.mode.Mode()
        # localize file paths
        compPath   = self.repath.localize(source['compPath'])
        destination = self.validateUnicodeChars(source['destination'])
        scriptName = self.validateUnicodeChars(self.repath.localize(source['scriptName']))

        # set vars for script resolution and frame rate
        xResolution  = source['xResolution']
        yResolution  = source['yResolution']
        frameRate    = source['frameRate']

        # create nukeComp format
        compFormat   = "%d %d %s" % (xResolution, yResolution, "_flix_1_format")
        flixFormat   = nuke.addFormat(compFormat)

        # create read & write node. Define codec and file type
        readNodes     = source['readNodes']
        writeNodeName = self.validateUnicodeChars(source['writeNode'])

        # setup enumeration keys
        kInput1    = 0
        kInputNum  = 0
        kFilePath  = 0
        kReadNode  = 0
        kDuration  = 1
        kDialogue  = 2

        animationKey   = 0
        animationValue = 0
        lastFrame      = 0
        firstFrame     = 1

        # create list for read node objects
        readNodeList = []

        try:
            dialogueHeight = int(mode.get(kDialogueHeight))
        except ValueError, e:
            log("Could not get value for dialogue area height parameter (toMovDialogueHeight), defaulting to 100.", isWarning=True)
            dialogueHeight = 100
Beispiel #17
0
    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])
Beispiel #18
0
    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])
    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 emailResult(self):

        # email publish summary
        try:
            publishTemplateName = self.shotCutList.mode[
                fromFCP.kParamImportTemplate]
            publishSummary = flix.utilities.template.render(
                publishTemplateName, **{
                    'cutlist': self.shotCutList,
                    'comment': self.comment,
                })
            show = self.shotCutList.show
            sequence = self.shotCutList.sequence

            # grab tracking code for sequence
            trackingCode = flix.core.sequence.Sequence(
                show, sequence).getTrackingIndex()
            mode = self.shotCutList.mode
            kargs = {}
            # compile subject
            kargs['[trackingCode]'] = (" %s" % trackingCode).rstrip()
            kargs['[sequenceInfo]'] = "[show]/[sequence][trackingCode]"
            kargs['[emailSubjectMessage]'] = "From Nuke Studio [sequenceInfo]"
            kargs['[emailSubjectComment]'] = self.comment

            # email summary
            log("Nuke Studio: Emailing Publish Summary: %s" % kargs)
            with mode.using(kargs):
                flix.utilities.email.sendHtmlEmail('[FLIX_USER]@[domain]',
                                                   '[emailFromEditorial]',
                                                   '[emailFullSubject]',
                                                   publishSummary, mode)

        # email error to support
        except Exception, e:
            log('Publish email summary failed.%s' % e,
                trace=True,
                isError=True)
 def execute(self, shotCutList, selection, additionalData=None):
     self.shotList = flix.core2.shotCutList.ShotCutList.fromFile(
         shotCutList.defaultPath())
     newDialogue = "whatever"
     data = []
     data.append('<Recipies>')
     for panel in self.shotList:
         recipe = panel.recipe
         if not panel.isMarker():
             poses = recipe.getPoses()
             poseXML = poses[0]['poseXML']
             poseXML.attrib['dialogue'] = newDialogue
             recipe.saveRecipeFiles()
             data.append(
                 '<Setup show="%(show)s" sequence="%(sequence)s" beat="%(beat)s" setup="%(setup)s" version="%(version)s">'
                 % recipe.getProperties())
             data.append(
                 ET.tostring(recipe.getMultiTrackXML()) + "</Setup>")
     data.append("</Recipies>")
     dataString = "".join(data)
     log("DATASTRING: %s" % dataString)
     self.serverFlixFunctions.addFeedback('reloadSetupsMultiTracks',
                                          dataString)
Beispiel #22
0
    def execute(self, shotCutList, selection, additionalData=None, output=False):
        """ Copy panels into user defined directory
        """
        self.shotCutList  = shotCutList.loadAll()

        if not self.shotCutList:
            raise flix.exceptions.FlixException("CSV can not be created for empty sequence",
                                                error=ValueError("No values in ShotCutList"),
                                                notify=True)

        self.selection = selection
        self._dialogueErrors = []

        self.setKargs()
        # collect panel and shot infomation.
        self.getSequenceInfo()
        self.shots = ShotInfo(self.shotCutList).getShotsInfo()

        if not output:
            output = OSUtils.runFileBrowser(kBrowseTypeFolderUsingSaveFile, 'Choose a folder', '/', 'toCSV')
            # escape output path
            output = escape(output.decode('utf-8'))
            if not output or not os.path.isdir(output):
                raise flix.exceptions.FlixException(error="Directory error", msg='No Valid directory selected.')

        fileName = '{Sequence Folder}_v{Version}.csv'.format(**self.kargs)
        fileOut  = '/'.join([output, fileName])

        # tell the user what sequence and sequence version is exporting and where.
        log('Exporting out sequence csv: %s into: %s' % (fileName, output), isInfo=True)
        # # if outputPath exists and all panels exist export the sequence.
        if os.path.exists(output):
            self.saveCSV(fileOut)
            OSUtils().revealFiles([fileOut])
        if self._dialogueErrors:
            failedDialogues = ", ".join([shot.recipe.getLabelName() for shot in self._dialogueErrors])
            self._execMessage = "Executed %s Plugin Successfully\n\nFailed to parse dialogue for the following clips:\n%s"%(self.label, failedDialogues)
Beispiel #23
0
 def execute(self, shotCutList, selection, additionalData=None):
     dialogueFile = self.loadFileBrowser()
     if not dialogueFile or not os.path.exists(
             dialogueFile) or not dialogueFile[-4:] == ".txt":
         raise flix.exceptions.FlixException("No valid text file selected.")
     self.shotList = flix.core2.shotCutList.ShotCutList.fromFile(
         shotCutList.defaultPath())
     panels = self.getPanelSetupList()
     with open(dialogueFile) as f:
         dialogueFileContent = f.readlines()
     panelDialogueLines = self.getPanelDialogueLines(
         panels, dialogueFileContent)
     data = []
     data.append('<Recipies>')
     for panel in self.shotList:
         recipe = panel.recipe
         if not panel.isMarker():
             dialogueLines = panelDialogueLines[recipe.getShortLabelName()]
             if not dialogueLines == [-1]:
                 newDialogue = u""
                 for line in range(dialogueLines[0], dialogueLines[1] + 1):
                     newDialogue += dialogueFileContent[line].strip("\t")
                 poses = recipe.getPoses()
                 poseXML = poses[0]['poseXML']
                 poseXML.attrib['dialogue'] = newDialogue
                 recipe.saveRecipeFiles()
                 data.append(
                     '<Setup show="%(show)s" sequence="%(sequence)s" beat="%(beat)s" setup="%(setup)s" version="%(version)s">'
                     % recipe.getProperties())
                 data.append(
                     ET.tostring(recipe.getMultiTrackXML()) + "</Setup>")
     data.append("</Recipies>")
     dataString = "".join(data)
     log("DATASTRING: %s" % dataString)
     self.serverFlixFunctions.addFeedback('reloadSetupsMultiTracks',
                                          dataString)
Beispiel #24
0
            dissolveNode.setInput(kInputNum, readNode[kReadNode])
            dissolveNode['which'].setValueAt(animationValue, animationKey)
            kInputNum      += 1
            animationValue += 1
            # skip the mask input
            if kInputNum == 2:
                kInputNum = 3

        # set dissolveNode animation curve to constant (step)
        dissolveNode.knobs()['which'].animations()[0].changeInterpolation(
            dissolveNode.knobs()['which'].animations()[0].keys(),
            nuke.CONSTANT)

        # create writeNode and set input to dissolve Node
        self.fileService.createFolders(os.path.dirname(destination))
        log("destination path is %s"%destination, isInfo=True)
        writeJpgNode = nuke.createNode('Write')
        writeJpgNode['name'].setValue('saveJPG')
        writeJpgNode["file"].fromUserText(self.repath.localize(destination))
        writeJpgNode.setInput(kInput1, dissolveNode)

        # setup root preferences
        nuke.root().knob("first_frame").setValue(1)
        nuke.root().knob("last_frame").setValue(lastFrame)
        nuke.root().knob("fps").setValue(frameRate)
        nuke.root().knob("format").setValue(flixFormat)

        # render then save the script
        nuke.scriptSave(scriptName)
        nuke.render(writeJpgNode, 1, int(lastFrame))
        log('Render Complete. %s' % self.repath.localize(source['scriptName']), isInfo=True)        
Beispiel #25
0
    def execute(self, shotCutList, selection, additionalData=None):
        self.shotList = flix.core2.shotCutList.ShotCutList.fromFile(shotCutList.defaultPath())
        log("shotList: %s" % self.shotList)
        self.kargs = {'show'    :self.shotList.show,
                 'sequence':self.shotList.sequence,
                 'branch'  :self.shotList.branch,
                 'version' :self.shotList.version}
        self.mode = self.shotList.mode

        markerList = MarkerList.fromShotCutList(self.shotList)
        log("markerList: %s" % markerList)
        for marker in markerList:
            log("marker: %s" % marker)
        markerShotLists = MarkerList.markerShotCutList(self.shotList, markerList)
        log("markerShotLists 1: %s" % markerShotLists)
        if not markerShotLists:
            markerShotLists.append(self.shotList)
            log("markerShotLists was False, new one: %s" % markerShotLists)

        for markerShot in markerShotLists:
            log("markerShot: %s" % markerShot)
            if markerShot.isMarker:
                for shot in markerShot:
                    log("shot: %s" % shot)
Beispiel #26
0
    from flixConfig.plugins.toPDFSelection import ToPDFSelection
    from flixConfig.plugins.toPDFShots import ToPDFShots
    from flixConfig.plugins.toMovDialogue import ToMovDialogue
    from flixConfig.plugins.toMovPerShot import ToMovPerShot
    from flixConfig.plugins.photoshopEachFile import PhotoshopEachFile
    from flixConfig.plugins.pictureInPicture import PictureInPicture
    from flixConfig.plugins.toShotgunGEAH import ToShotgunGEAH
    from flixConfig.plugins.renameMarkers import RenameMarkers
    from flixConfig.plugins.logShotMarkers import LogShotMarkers
    from flixConfig.plugins.logMultipleShotEdits import LogMultipleShotEdits
    from flixConfig.plugins.nukeTestEA import NukeTestEA
    from flixConfig.plugins.importDialogue import ImportDialogue
    from flixConfig.plugins.shotsToCSV import ShotsToCSV
    from flixConfig.plugins.toAvidCopy import ToAvidCopy
except Exception, e:
    log("Failed to import a custom plugin: %s" % e, isError=True)


class LocalPluginConfig(PluginConfig):
    def __init__(self):
        """Initialize the plugins that will show up in Flix gui"""
        super(LocalPluginConfig, self).__init__()
        try:
            # Edit plugins
            PhotoshopEachFile().default()
            # Maya plugins
            PictureInPicture()
            # PDF plugins
            ToPDFSelection()
            ToPDFShots()
            # Export plugins
Beispiel #27
0
    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)
Beispiel #28
0
    def execute(self, shotCutList, selection, additionalData=None):
        if not additionalData is None:
            referenceCutList = additionalData.get('reference', None)
            comment = additionalData.get('comment', "")

        show = shotCutList.show
        sequence = shotCutList.sequence
        version = shotCutList.version
        branch = shotCutList.branch
        mode = Mode(show, sequence)

        log("To Avid: Publishing: %s %s %s %s Comment: %s" %
            (show, sequence, branch, version, comment),
            isInfo=True)

        # get path to cutlist to publish
        shotCutListPath = flix.core2.shotCutList.ShotCutList.getDefaultPath( \
            mode, version, branch)

        # check if reference cutlist is required
        referenceCutListPath = None
        referenceVersion = -2
        if referenceCutList is not None:
            referenceVersion = referenceCutList.version
        if referenceVersion == -2:
            referenceCutListPath = self.getMostRecentPublishedEdit( \
                show, sequence, version, branch)
        elif referenceVersion > 0:
            referenceCutList.load()
            referenceCutListPath = flix.core2.shotCutList.ShotCutList.getDefaultPath( \
                mode, referenceVersion, branch)

        # publish the cutlist
        avidWorkflow = AvidWorkflow()
        result = avidWorkflow.publish(shotCutListPath, referenceCutListPath,
                                      comment)

        if referenceCutList is None:
            referenceCutList = shotCutList

        self.__shotCutList = shotCutList
        self.__shotCutList.load()
        self.__referenceCutList = referenceCutList
        self.__newShots = avidWorkflow.newShots
        self.__errors = avidWorkflow.errors
        self.__encodingTime = avidWorkflow.encodingTime
        self.__comment = comment
        self._dialogueErrors = avidWorkflow.dialogueErrors

        self.saveAle(shotCutList)

        # email publish summary
        self.emailSummary()
        self.flixCore = FlixCore()
        importMedia = self.flixCore.examineFLEForNewAAFs(
            show, sequence, version, branch)
        log("importMedia: %s" % importMedia)
        destinationFolder = shotCutList.mode.get('[AAFDestinationFolder]')
        log("destinationFolder: %s" % destinationFolder)
        if self.fileService.exists(destinationFolder):
            self.flixCore.importAAFs(show, sequence, version, branch,
                                     destinationFolder)
        else:
            # self.editorialLog("AAF copy directory does not\nexist. Set a valid directory and try again.")
            # self.execMessage("\nExecuted Avid Plugin Successfully\nRefer to e-mail for more info.\nCould not find AAF destination folder, please import AAFs manually.")
            self._execMessage += "\nCould not find AAF destination folder, please import AAFs manually."
            log("Could not find AAF destination folder: %s" %
                destinationFolder)

        # Automatically create a PDF file during publish
        if shotCutList.mode.get('[avidAutoGeneratePDF]') == '1':
            # convert new shots into indices
            newPanelIndices = []
            index = 0
            panelIndex = 0
            for newShot in avidWorkflow.newShots:
                while index < len(shotCutList):
                    shot = shotCutList[index]
                    if shot.isMarker():
                        index += 1
                        continue
                    if shot.label == newShot.label:
                        newPanelIndices.append(panelIndex)
                        break
                    index += 1
                    panelIndex += 1

            toPDF = flix.plugins.toPDF.ToPDF9()
            toPDF.execute(shotCutList, [], {'newShots': newPanelIndices})

        log("To Avid:: Publish Complete with status: %s" % result)

        return "%s" % result
Beispiel #29
0
    def buildCanvas(self):
        """
        Builds a canvas object with current settings
        :return: canvas object
        """
        # get output
        if self.getOutput():
            return

        self.marginSize = 65

        # get page width and height
        self.pageWidth, self.pageHeight = self.getPageSize()

        # create an empty canvas
        self.canvas = reportlab.pdfgen.canvas.Canvas(self.repath.localize(self.output), pagesize=self.pageSize)

        rowCounter = 0
        colCounter = 0
        pageNumber = 1
        self.panelVertShift = 0
        self.textGap    = 120
        self.header = self.marginSize*1.5
        # self.header = 100
        log("self.header: %s" % self.header)

        # set the font type from parameters
        self.loadFontType()

        # set the canvas settings
        self.setCanvasSettings(pageNumber)

        # loop through imageDataList and create the pages of PDF with all content based on row and column count provided
        for index, imageData in enumerate(self.imageDataList):

            image = imageData['path']
            self.fileService.copyToLocal(image)
            if not self.fileServiceLocal.exists(image):
                image = self.mode.get('[FLIX_FOLDER]')+'/assets/errorImageInverted.jpg'
            panel = ImageReader(image)

            # figure out the image sizes based on the number of row's and column's
            panelWidth, panelHeight = self.getPanelSize(panel)

            # get each panels XY position on the pdf page
            panelX, panelY = self.getPanelPosition(panelWidth, panelHeight, rowCounter, colCounter)

            imageData.update({"panelX":panelX,
                              "panelY":panelY,
                              "panelW":panelWidth,
                              "panelH":panelHeight})

            # insert the image and stroke
            self.canvas.drawImage(panel, panelX, panelY, width=panelWidth, height=panelHeight)
            self.canvas.rect(panelX, panelY, width=panelWidth, height=panelHeight)

            # insert panel label and dialogue
            self.setPanelDialogueData(imageData)

            # set index number of each panel
            indexY = panelY - 10
            indexX = panelX + panelWidth
            self.canvas.setFillColor(self.fontColor)
            self.canvas.drawRightString(indexX, indexY, str(index+1))

            # check if shot status exists and set icon
            self.setPanelShotStatus(imageData)

            # check if the current panel is new and set new icon
            self.setPanelNewIcon(imageData)

            # set the shot label
            self.setPanelShotLabel(imageData)

            # check the row's and column's counter to set the next image in the correct place
            colCounter += 1
            if colCounter == self.column:
                colCounter = 0
                rowCounter += 1

            # if imageData != self.imageDataList[-1]:
            #     if imageData['shotLabel'] != self.imageDataList[index+1]['shotLabel']:
            #         shotChanged = True
            #     else:
            #         shotChanged = False

            if (rowCounter == self.row and not index == (len(self.imageDataList)-1)):
                self.setWatermark()
                self.canvas.showPage()
                pageNumber += 1
                self.setCanvasSettings(pageNumber)
                rowCounter = 0
                colCounter = 0
            elif index == (len(self.imageDataList)-1):
                self.setWatermark()
            self.serverSession.processingRemove(1)

        # save the pdf
        self.canvas.save()
        self.serverSession.processingRemove(1)
        return self.canvas
Beispiel #30
0
    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()