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)
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 __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)
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 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
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)
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
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)
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
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
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)
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
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])
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)
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)
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)
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)
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)
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
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)
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
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
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()