def monitor(): """ Launch Deadline Monitor. """ try: subprocess.Popen(os.environ['RQ_DEADLINEMONITOR'], shell=True) except: verbose.warning("Could not open Deadline Monitor.")
def calcDuration(self, rangeStart, rangeEnd): """ Calculate the duration. """ durationFrames = rangeEnd - rangeStart + 1 # fps = self.parent.prefs.get_attr('units', 'fps', type='float') fps = self.parent.prefs.get_attr('units', 'fps') if fps == None: if self.parent.inherit: # fps = self.parent.prefs_inherited.get_attr( # 'units', 'fps', type='float') fps = self.parent.prefs_inherited.get_attr('units', 'fps') if fps == None: verbose.warning("Undefined FPS.") return durationFrames, "" durationSecs = float(durationFrames) / float(fps) durationStr = "" if durationSecs < 60: durationStr = "%s seconds" % round(durationSecs, 6) elif durationSecs < 3600: mins = durationSecs / 60 secs = durationSecs % 60 durationStr = "%dm %ds" % (mins, secs) else: durationStr = time.strftime("%H:%M:%S", time.gmtime(durationSecs)) formattedStr = "%s @ %s fps" % (durationStr, round(fps, 3)) return durationFrames, formattedStr
def generate_job_info_file(**kwargs): """ Generate job submission info file. """ if kwargs['renderLayer']: job_info_file_suffix = "_%s_deadlineJobInfo.txt" % kwargs['renderLayer'] else: job_info_file_suffix = "_deadlineJobInfo.txt" job_info_file = temp_file(kwargs['scene'], suffix=job_info_file_suffix) with open(job_info_file, 'w') as fh: fh.write("Plugin=%s\n" % kwargs['plugin']) if kwargs['renderLayer']: fh.write("Name=%s - %s\n" % (kwargs['jobName'], kwargs['renderLayer'])) fh.write("BatchName=%s\n" % kwargs['jobName']) else: fh.write("Name=%s\n" % kwargs['jobName']) fh.write("Comment=%s\n" % kwargs['comment']) fh.write("Frames=%s\n" % kwargs['frames']) fh.write("ChunkSize=%s\n" % kwargs['taskSize']) fh.write("Pool=%s\n" % kwargs['pool']) fh.write("SecondaryPool=%s\n" % kwargs['secondaryPool']) fh.write("Group=%s\n" % kwargs['group']) fh.write("Priority=%s\n" % kwargs['priority']) fh.write("UserName=%s\n" % kwargs['username']) if kwargs['priority'] == 0: fh.write("InitialStatus=Suspended\n") try: if kwargs['renderLayer']: # Single layer output output_path = kwargs['output'][kwargs['renderLayer']] fh.write("OutputDirectory0=%s\n" % output_path[0]) fh.write("OutputFilename0=%s\n" % output_path[1]) else: # Multiple layer outputs for i, layer in enumerate(kwargs['output']): output_path = kwargs['output'][layer] fh.write("OutputDirectory%d=%s\n" % (i, output_path[0])) fh.write("OutputFilename%d=%s\n" % (i, output_path[1])) except: verbose.warning("Could not determine render output path(s).") for i, key in enumerate(kwargs['envVars']): try: fh.write("EnvironmentKeyValue%d=%s=%s\n" % (i, key, os.environ[key])) except KeyError: verbose.warning("Environment variable '%s' not set." % key) try: fh.write("ExtraInfo0=%s\n" % os.environ['RQ_JOB']) fh.write("ExtraInfo1=%s\n" % os.environ['RQ_SHOT']) except KeyError: pass fh.write("ExtraInfo2=%s\n" % kwargs['submitter']) return job_info_file
def updateShotsPreview(self): """ Update the preview field showing the shot directories to be created. """ multi_ui = [ 'shotCount_label', 'shotCount_spinBox', 'start_label', 'start_spinBox', 'increment_label', 'increment_spinBox' ] self.shots_to_create = [] seq_name = self.ui.seq_comboBox.currentText() if seq_name != "": seq_name += '/' shot_name = self.ui.prefix_comboBox.currentText() count = self.ui.shotCount_spinBox.value() index = self.ui.start_spinBox.value() step = self.ui.increment_spinBox.value() re_digits_pattern = re.compile(r'#+') match = re.findall(re_digits_pattern, shot_name) # Create multiple shots if match: hashes = str(match[0]) padding = len(hashes) for shot in range(count): self.shots_to_create.append( seq_name + shot_name.replace(hashes, str(index).zfill(padding))) index += step for widget in multi_ui: eval('self.ui.%s.setEnabled(True)' % widget) # Create single shot else: verbose.warning( "Cannot create multiple shots as there are no hashes (#) in shot name pattern." ) self.shots_to_create.append(seq_name + shot_name) for widget in multi_ui: eval('self.ui.%s.setEnabled(False)' % widget) # Update UI elements self.ui.shotPreview_listWidget.clear() self.ui.shotPreview_listWidget.addItems(self.shots_to_create) num_shots = len(self.shots_to_create) if num_shots and shot_name != "": self.ui.create_pushButton.setEnabled(True) self.ui.create_pushButton.setText( "Create %d %s" % (num_shots, verbose.pluralise('Shot', num_shots))) else: self.ui.create_pushButton.setEnabled(False) self.ui.create_pushButton.setText("Create")
def get_groups(): """ Get Deadline groups and return in a list. """ try: groups = os_wrapper.execute( [os.environ['RQ_DEADLINECOMMAND'], '-groups'])[1] return groups.splitlines() except: verbose.warning("Could not retrieve Deadline groups.") return None
def storeWindow(self): """ Store window geometry and state. (Save state may cause issues with PyQt5) """ if self.store_window_geometry: try: self.settings.setValue("geometry", self.saveGeometry()) verbose.print_("Storing window geometry for '%s'." % self.objectName()) except: verbose.warning("Could not store window geometry for '%s'." % self.objectName())
def createShots(self): """ Create the shot(s). """ success = 0 existing = 0 failure = 0 shots_created = "" shots_existing = "" shots_failed = "" dialog_msg = "" for shot in self.shots_to_create: shot_datafile = self.getShotDatafile(shot) os_wrapper.createDir(os.path.dirname(shot_datafile)) if self.shot_data.load(shot_datafile): existing += 1 shots_existing += shot + "\n" elif self.shot_data.save(): success += 1 shots_created += shot + "\n" else: failure += 1 shots_failed += shot + "\n" if success: message = "%d %s created successfully: " % ( success, verbose.pluralise('shot', success)) dialog_msg += "%s\n%s\n" % (message, shots_created) verbose.message(message + shots_created) if existing: message = "The following %d shot(s) were not created as they already exist: " % existing dialog_msg += "%s\n%s\n" % (message, shots_existing) verbose.warning(message + shots_existing) if failure: message = "The following %d shot(s) could not be created - please check write permissions and try again: " % failure dialog_msg += "%s\n%s\n" % (message, shots_failed) verbose.error(message + shots_failed) # Confirmation dialog dialog_title = "Shot Creator Results" dialog = prompt.dialog() dialog.display(dialog_msg, dialog_title, conf=True) self.populateShots()
def checkRootPaths(self): """ Check if root paths have been set, and if not prompt the user to set them up. """ self.j.getRootPaths() if (self.j.win_root is None) or (self.j.osx_root is None) or (self.j.linux_root is None): dialogMsg = "Paths to the root of the shared filesystem must be set for each OS to enable cross-platform portability. Please set the values in the next dialog." #verbose.print_(dialogMsg, 1) verbose.warning("Root filesystem path(s) not set.") # Confirmation dialog dialogTitle = "Root Paths Not Set" dialog = prompt.dialog() dialog.display(dialogMsg, dialogTitle, conf=True) self.editPaths()
def deploy(): mayaShelvesDir = os.path.join(mc.about(preferences=True), 'prefs', 'shelves') # mayaModulesDir = os.path.join(mc.about(preferences=True), 'modules') try: os_wrapper.copyDirContents( os.path.join(os.environ['IC_BASEDIR'], 'rsc', 'maya', 'shelves'), mayaShelvesDir) # os_wrapper.copyDirContents(os.path.join(os.environ['IC_BASEDIR'], 'rsc', 'maya', 'modules'), mayaModulesDir) # os_wrapper.copyDirContents(os.path.join(os.environ['IC_JOBPUBLISHDIR'], 'ma_shelves'), mayaShelvesDir) verbose.message("Successfully deployed %s tools." % os.environ['IC_VENDOR_INITIALS']) return True except: verbose.warning("Failed to deploy %s tools." % os.environ['IC_VENDOR_INITIALS']) return False
def hardLink(source, destination, umask='000', verify=True): """ Creates hard links. """ src = os.path.normpath(source) dst = os.path.normpath(destination) if os.environ['IC_RUNNING_OS'] == "Windows": # If destination is a folder, append the filename from the source if os.path.isdir(dst): filename = os.path.basename(src) dst = os.path.join(dst, filename) # Delete the destination file if it already exists - this is to mimic # the Unix behaviour and force creation of the hard link if os.path.isfile(dst): os.system('del "%s" /f /q' % dst) # Create the hardlink #cmdStr = 'mklink /H "%s" "%s"' %(dst, src) # This only works with local NTFS volumes cmdStr = 'fsutil hardlink create "%s" "%s" >nul' % ( dst, src ) # Works over SMB network shares; suppressing output to null else: #cmdStr = '%s; ln -f %s %s' %(setUmask(umask), src, dst) cmdStr = 'ln -f %s %s' % (src, dst) verbose.print_(cmdStr) os.system(cmdStr) # Make sure source and destination files match if verify: if verify_hardlink(src, dst): return dst else: verbose.warning( "Failed to create hardlink. Attempting to copy file instead.") copy(src, dst) else: return dst
def findCategory(self, widget): """ Recursively check the parents of the given widget until a custom property 'xmlCategory' is found. """ # print("widget: " + widget.objectName()) if widget.property('xmlCategory'): #verbose.print_("Category '%s' found for '%s'." %(widget.property('xmlCategory'), widget.objectName())) return widget.property('xmlCategory') else: # # Stop iterating if the widget's parent is the top window... # if isinstance(widget.parent(), QtWidgets.QMainWindow) \ # or isinstance(widget.parent(), QtWidgets.QDialog): # verbose.warning("No category could be found for '%s'. The widget's value cannot be stored." %self.base_widget) # return None # else: try: return self.findCategory(widget.parent()) except TypeError: verbose.warning( "No category could be found for '%s'. The widget's value cannot be stored." % self.base_widget) return "none"
def loadPanel(self, category): """ Load the panel UI (and helper module if required). The exec function is called here to avoid the error: 'unqualified exec is not allowed in function because it contains a nested function with free variables' with Python 2.x. """ ui_file = "settings_%s_ui.ui" % category helper_module = 'settings_%s' % category panel_ui_loaded = False helper_module_loaded = False # Create new frame to hold properties UI & load into frame self.ui.settings_frame.close() try: uifile = os.path.join(os.environ['IC_FORMSDIR'], ui_file) self.ui.settings_frame = QtCompat.loadUi(uifile) self.ui.settings_verticalLayout.addWidget(self.ui.settings_frame) panel_ui_loaded = True except FileNotFoundError: message = "Could not open '%s' properties panel UI. " % category verbose.error(message) # Load helper module try: exec_str = 'from . import %s as sh; helper = sh.helper(self, self.ui.settings_frame)' % helper_module # print(exec_str) exec(exec_str) helper_module_loaded = True except ImportError: message = "Could not import '%s' module. " % helper_module verbose.warning(message) if panel_ui_loaded: # and helper_module_loaded: return True else: return False
def setupUI(self, window_object, window_title="", ui_file="", stylesheet="", prefs_file=None, store_window_geometry=True): """ Setup the UI. """ verbose.debug("Window object: %s Parent: %s" % (self, self.parent)) # Instantiate preferences data class if prefs_file is None: self.prefs = None else: self.prefs = self.createPrefs(prefs_file) # Define some global variables self.currentAttrStr = "" # Load UI & stylesheet found_ui_file = self.checkFilePath(ui_file, searchpath=[ os.environ['IC_FORMSDIR'], ]) if os.path.isfile(found_ui_file): self.ui = QtCompat.loadUi(found_ui_file, self) else: verbose.error("UI file does not exist: %s" % found_ui_file) # Store some system UI colours & define colour palette self.col = {} self.col['text'] = QtGui.QColor(204, 204, 204) self.col['disabled'] = QtGui.QColor(102, 102, 102) self.col['highlighted-text'] = QtGui.QColor(255, 255, 255) tmpWidget = QtWidgets.QWidget() self.col['sys-window'] = tmpWidget.palette().color( QtGui.QPalette.Window) self.col['sys-highlight'] = tmpWidget.palette().color( QtGui.QPalette.Highlight) # self.col['window'] = self.col['sys-window'] self.col['highlight'] = self.col['sys-highlight'] self.col['window'] = QtGui.QColor('#444444') # self.col['highlight'] = QtGui.QColor('#78909c') self.computeUIPalette() # Load and set stylesheet self.stylesheet = self.checkFilePath(stylesheet, searchpath=[ os.environ['IC_FORMSDIR'], ]) self.loadStyleSheet() # Set window title self.setObjectName(window_object) if window_title: self.setWindowTitle(window_title) else: window_title = self.windowTitle() # Perform custom widget setup self.setupWidgets(self.ui) # Restore window geometry and state self.store_window_geometry = store_window_geometry if self.store_window_geometry: try: uiName = self.objectName() if os.environ['IC_ENV'] != 'STANDALONE': uiName += "_" + os.environ['IC_ENV'].lower() self.settings = QtCore.QSettings(os.environ['IC_VENDOR'], uiName) self.restoreGeometry(self.settings.value("geometry", "")) verbose.print_("Restoring window geometry for '%s'." % self.objectName()) except (KeyError, TypeError): verbose.warning("Could not restore window geometry for '%s'." % self.objectName()) # # Use QSettings to store window geometry and state. # # (Restore state may cause issues with PyQt5) # if os.environ['IC_ENV'] == 'STANDALONE': # verbose.print_("Restoring window geometry for '%s'." %self.objectName()) # try: # self.settings = QtCore.QSettings( # os.environ['IC_VENDOR'], window_title) # self.restoreGeometry(self.settings.value("geometry", "")) # # self.restoreState(self.settings.value("windowState", "")) # except: # pass # # Makes Maya perform magic which makes the window stay on top in # # OS X and Linux. As an added bonus, it'll make Maya remember the # # window position. # elif os.environ['IC_ENV'] == 'MAYA': # self.setProperty("saveWindowPref", True) # elif os.environ['IC_ENV'] == 'NUKE': # pass # else: # # Move to centre of active screen # desktop = QtWidgets.QApplication.desktop() # screen = desktop.screenNumber(desktop.cursor().pos()) # self.move(desktop.screenGeometry(screen).center() - self.frameGeometry().center()) # # Move to centre of parent window # self.move(self.parent.frameGeometry().center() - self.frameGeometry().center()) # Set up keyboard shortcuts self.shortcutUnloadStyleSheet = QtWidgets.QShortcut(self) self.shortcutUnloadStyleSheet.setKey('Ctrl+Shift+R') self.shortcutUnloadStyleSheet.activated.connect(self.unloadStyleSheet) self.shortcutReloadStyleSheet = QtWidgets.QShortcut(self) self.shortcutReloadStyleSheet.setKey('Ctrl+R') self.shortcutReloadStyleSheet.activated.connect(self.loadStyleSheet)
def setInfoMessage(self, message=""): """ Set the information message. """ if message: verbose.warning(message) self.frame.timeInfo_label.setText(message)