diff --git a/openpype/hosts/hiero/api/startup/Python/Startup/version_everywhere.py b/openpype/hosts/hiero/api/startup/Python/Startup/version_everywhere.py deleted file mode 100644 index 3d60b213d5..0000000000 --- a/openpype/hosts/hiero/api/startup/Python/Startup/version_everywhere.py +++ /dev/null @@ -1,352 +0,0 @@ -# version_up_everywhere.py -# Adds action to enable a Clip/Shot to be Min/Max/Next/Prev versioned in all shots used in a Project. -# -# Usage: -# 1) Copy file to /Python/Startup -# 2) Right-click on Clip(s) or Bins containing Clips in in the Bin View, or on Shots in the Timeline/Spreadsheet -# 3) Set Version for all Shots > OPTION to update the version in all shots where the Clip is used in the Project. - -import hiero.core -try: - from PySide.QtGui import * - from PySide.QtCore import * -except: - from PySide2.QtGui import * - from PySide2.QtWidgets import * - from PySide2.QtCore import * - - -def whereAmI(self, searchType="TrackItem"): - """returns a list of TrackItem or Sequnece objects in the Project which contain this Clip. - By default this will return a list of TrackItems where the Clip is used in its project. - You can also return a list of Sequences by specifying the searchType to be "Sequence". - Should consider putting this into hiero.core.Clip by default? - - Example usage: - - shotsForClip = clip.whereAmI("TrackItem") - sequencesForClip = clip.whereAmI("Sequence") - """ - proj = self.project() - - if ("TrackItem" not in searchType) and ("Sequence" not in searchType): - print("searchType argument must be \"TrackItem\" or \"Sequence\"") - return None - - # If user specifies a TrackItem, then it will return - searches = hiero.core.findItemsInProject(proj, searchType) - - if len(searches) == 0: - print("Unable to find {} in any items of type: {}".format( - str(self), searchType)) - return None - - # Case 1: Looking for Shots (trackItems) - clipUsedIn = [] - if isinstance(searches[0], hiero.core.TrackItem): - for shot in searches: - # We have to wrap this in a try/except because it's possible through the Python API for a Shot to exist without a Clip in the Bin - try: - - # For versioning to work, we must look to the BinItem that a Clip is wrapped in. - if shot.source().binItem() == self.binItem(): - clipUsedIn.append(shot) - - # If we throw an exception here its because the Shot did not have a Source Clip in the Bin. - except RuntimeError: - hiero.core.log.info( - 'Unable to find Parent Clip BinItem for Shot: %s, Source:%s' - % (shot, shot.source())) - pass - - # Case 1: Looking for Shots (trackItems) - elif isinstance(searches[0], hiero.core.Sequence): - for seq in searches: - # Iterate tracks > shots... - tracks = seq.items() - for track in tracks: - shots = track.items() - for shot in shots: - if shot.source().binItem() == self.binItem(): - clipUsedIn.append(seq) - - return clipUsedIn - - -# Add whereAmI method to Clip object -hiero.core.Clip.whereAmI = whereAmI - - -#### MAIN VERSION EVERYWHERE GUBBINS ##### -class VersionAllMenu(object): - - # These are a set of action names we can use for operating on multiple Clip/TrackItems - eMaxVersion = "Max Version" - eMinVersion = "Min Version" - eNextVersion = "Next Version" - ePreviousVersion = "Previous Version" - - # This is the title used for the Version Menu title. It's long isn't it? - actionTitle = "Set Version for all Shots" - - def __init__(self): - self._versionEverywhereMenu = None - self._versionActions = [] - - hiero.core.events.registerInterest("kShowContextMenu/kBin", - self.binViewEventHandler) - hiero.core.events.registerInterest("kShowContextMenu/kTimeline", - self.binViewEventHandler) - hiero.core.events.registerInterest("kShowContextMenu/kSpreadsheet", - self.binViewEventHandler) - - def showVersionUpdateReportFromShotManifest(self, sequenceShotManifest): - """This just displays an info Message box, based on a Sequence[Shot] manifest dictionary""" - - # Now present an info dialog, explaining where shots were updated - updateReportString = "The following Versions were updated:\n" - for seq in sequenceShotManifest.keys(): - updateReportString += "%s:\n Shots:\n" % (seq.name()) - for shot in sequenceShotManifest[seq]: - updateReportString += ' %s\n (New Version: %s)\n' % ( - shot.name(), shot.currentVersion().name()) - updateReportString += "\n" - - infoBox = QMessageBox(hiero.ui.mainWindow()) - infoBox.setIcon(QMessageBox.Information) - - if len(sequenceShotManifest) <= 0: - infoBox.setText("No Shot Versions were updated") - infoBox.setInformativeText( - "Clip could not be found in any Shots in this Project") - else: - infoBox.setText( - "Versions were updated in %i Sequences of this Project." % - (len(sequenceShotManifest))) - infoBox.setInformativeText("Show Details for more info.") - infoBox.setDetailedText(updateReportString) - - infoBox.exec_() - - def makeVersionActionForSingleClip(self, version): - """This is used to populate the QAction list of Versions when a single Clip is selected in the BinView. - It also triggers the Version Update action based on the version passed to it. - (Not sure if this is good design practice, but it's compact!)""" - action = QAction(version.name(), None) - action.setData(lambda: version) - - def updateAllTrackItems(): - currentClip = version.item() - trackItems = currentClip.whereAmI() - if not trackItems: - return - - proj = currentClip.project() - - # A Sequence-Shot manifest dictionary - sequenceShotManifest = {} - - # Make this all undo-able in a single Group undo - with proj.beginUndo( - "Update All Versions for %s" % currentClip.name()): - for shot in trackItems: - seq = shot.parentSequence() - if seq not in sequenceShotManifest.keys(): - sequenceShotManifest[seq] = [shot] - else: - sequenceShotManifest[seq] += [shot] - shot.setCurrentVersion(version) - - # We also should update the current Version of the selected Clip for completeness... - currentClip.binItem().setActiveVersion(version) - - # Now disaplay a Dialog which informs the user of where and what was changed - self.showVersionUpdateReportFromShotManifest(sequenceShotManifest) - - action.triggered.connect(updateAllTrackItems) - return action - - # This is just a convenience method for returning QActions with a title, triggered method and icon. - def makeAction(self, title, method, icon=None): - action = QAction(title, None) - action.setIcon(QIcon(icon)) - - # We do this magic, so that the title string from the action is used to trigger the version change - def methodWrapper(): - method(title) - - action.triggered.connect(methodWrapper) - return action - - def clipSelectionFromView(self, view): - """Helper method to return a list of Clips in the Active View""" - selection = hiero.ui.activeView().selection() - - if len(selection) == 0: - return None - - if isinstance(view, hiero.ui.BinView): - # We could have a mixture of Bins and Clips selected, so sort of the Clips and Clips inside Bins - clipItems = [ - item.activeItem() for item in selection - if hasattr(item, "activeItem") - and isinstance(item.activeItem(), hiero.core.Clip) - ] - - # We'll also append Bins here, and see if can find Clips inside - bins = [ - item for item in selection if isinstance(item, hiero.core.Bin) - ] - - # We search inside of a Bin for a Clip which is not already in clipBinItems - if len(bins) > 0: - # Grab the Clips inside of a Bin and append them to a list - for bin in bins: - clips = hiero.core.findItemsInBin(bin, "Clip") - for clip in clips: - if clip not in clipItems: - clipItems.append(clip) - - elif isinstance(view, - (hiero.ui.TimelineEditor, hiero.ui.SpreadsheetView)): - # Here, we have shots. To get to the Clip froma TrackItem, just call source() - clipItems = [ - item.source() for item in selection if hasattr(item, "source") - and isinstance(item, hiero.core.TrackItem) - ] - - return clipItems - - # This generates the Version Up Everywhere menu - def createVersionEveryWhereMenuForView(self, view): - - versionEverywhereMenu = QMenu(self.actionTitle) - self._versionActions = [] - # We look to the activeView for a selection of Clips - clips = self.clipSelectionFromView(view) - - # And bail if nothing is found - if len(clips) == 0: - return versionEverywhereMenu - - # Now, if we have just one Clip selected, we'll form a special menu, which lists all versions - if len(clips) == 1: - - # Get a reversed list of Versions, so that bigger ones appear at top - versions = list(reversed(clips[0].binItem().items())) - for version in versions: - self._versionActions += [ - self.makeVersionActionForSingleClip(version) - ] - - elif len(clips) > 1: - # We will add Max/Min/Prev/Next options, which can be called on a TrackItem, without the need for a Version object - self._versionActions += [ - self.makeAction( - self.eMaxVersion, - self.setTrackItemVersionForClipSelection, - icon=None) - ] - self._versionActions += [ - self.makeAction( - self.eMinVersion, - self.setTrackItemVersionForClipSelection, - icon=None) - ] - self._versionActions += [ - self.makeAction( - self.eNextVersion, - self.setTrackItemVersionForClipSelection, - icon=None) - ] - self._versionActions += [ - self.makeAction( - self.ePreviousVersion, - self.setTrackItemVersionForClipSelection, - icon=None) - ] - - for act in self._versionActions: - versionEverywhereMenu.addAction(act) - - return versionEverywhereMenu - - def setTrackItemVersionForClipSelection(self, versionOption): - - view = hiero.ui.activeView() - if not view: - return - - clipSelection = self.clipSelectionFromView(view) - - if len(clipSelection) == 0: - return - - proj = clipSelection[0].project() - - # Create a Sequence-Shot Manifest, to report to users where a Shot was updated - sequenceShotManifest = {} - - with proj.beginUndo("Update multiple Versions"): - for clip in clipSelection: - - # Look to see if it exists in a TrackItem somewhere... - shotUsage = clip.whereAmI("TrackItem") - - # Next, depending on the versionOption, make the appropriate update - # There's probably a more neat/compact way of doing this... - for shot in shotUsage: - - # This step is done for reporting reasons - seq = shot.parentSequence() - if seq not in sequenceShotManifest.keys(): - sequenceShotManifest[seq] = [shot] - else: - sequenceShotManifest[seq] += [shot] - - if versionOption == self.eMaxVersion: - shot.maxVersion() - elif versionOption == self.eMinVersion: - shot.minVersion() - elif versionOption == self.eNextVersion: - shot.nextVersion() - elif versionOption == self.ePreviousVersion: - shot.prevVersion() - - # Finally, for completeness, set the Max/Min version of the Clip too (if chosen) - # Note: It doesn't make sense to do Next/Prev on a Clip here because next/prev means different things for different Shots - if versionOption == self.eMaxVersion: - clip.binItem().maxVersion() - elif versionOption == self.eMinVersion: - clip.binItem().minVersion() - - # Now disaplay a Dialog which informs the user of where and what was changed - self.showVersionUpdateReportFromShotManifest(sequenceShotManifest) - - # This handles events from the Project Bin View - def binViewEventHandler(self, event): - - if not hasattr(event.sender, "selection"): - # Something has gone wrong, we should only be here if raised - # by the Bin view which gives a selection. - return - selection = event.sender.selection() - - # Return if there's no Selection. We won't add the Localise Menu. - if selection == None: - return - - view = hiero.ui.activeView() - # Only add the Menu if Bins or Sequences are selected (this ensures menu isn't added in the Tags Pane) - if len(selection) > 0: - self._versionEverywhereMenu = self.createVersionEveryWhereMenuForView( - view) - hiero.ui.insertMenuAction( - self._versionEverywhereMenu.menuAction(), - event.menu, - after="foundry.menu.version") - return - - -# Instantiate the Menu to get it to register itself. -VersionAllMenu = VersionAllMenu()