def check(): """Makes sure everything is running right""" print("SYSTEM CHECK FOR {0}".format(mnpr_info.prototype)) # check viewport viewport = lib.getActiveModelPanel() cmds.modelEditor(viewport, dtx=True, e=True) # display textures # plugin needs to be loaded mnpr_info.loadRenderer() # 3rd party plugins must be loaded cmds.loadPlugin('shaderFXPlugin', quiet=True) if cmds.about(nt=True, q=True): cmds.loadPlugin( 'dx11Shader', quiet=True) # deprecated (only shadeFXPlugin in the future) cmds.loadPlugin( 'glslShader', quiet=True) # deprecated (only shaderFXPlugin in the future) # viewport renderer must be set mel.eval("setRendererAndOverrideInModelPanel vp2Renderer {0} {1};".format( mnpr_info.prototype, viewport)) # modify color of heads up display cmds.displayColor("headsUpDisplayLabels", 2, dormant=True) cmds.displayColor("headsUpDisplayValues", 2, dormant=True) # make sure a config node exists if not cmds.objExists(mnpr_info.configNode): selected = cmds.ls(sl=True, l=True) selectConfig() cmds.select(selected, r=True) lib.printInfo("-> SYSTEM CHECK SUCCESSFUL")
def charcoalContrast(): """ Modifies ShaderFX materials to generate contrast from lightness """ materials = cmds.ls(type="ShaderfxShader") for mat in materials: lib.setAttr(mat, "Shade_Override", 0) lib.setAttr(mat, "Diffuse_Factor", 0.8) lib.printInfo("ShaderFX materials changed for charcoal stylization")
def createVersion(directory): """ Creates a new MNPR version with all the latest updates Args: directory (str): Directory where files are made available for download """ mnpr = dict() # get current version path = os.path.join(directory, "version.json") with open(path, 'r') as f: oldMNPR = json.load(f) mnpr["version"] = oldMNPR["version"] + 0.01 # crawl files in download directory to create new version for root, dirs, files in os.walk(directory): relDir = root.replace(directory, '') relDir = relDir.replace('\\', '/') if files: mnpr[relDir] = dict() for f in files: mnpr[relDir][f] = os.path.getmtime(os.path.join(root, f)) pprint.pprint(mnpr) # write and save json info with open(path, 'w') as f: json.dump(mnpr, f, indent=4) lib.printInfo("MNPR version created successfully")
def loadStyle(self, attrs): if cmds.objExists(mnpr_info.configNode): # set attributes for attr in attrs: splitter = attr.split('.') lib.setAttr(splitter[0], splitter[1], attrs[attr], True) lib.printInfo("Style changed and attributes set successfully")
def noiseReset(fx): """ Turn off and reset noise parameters to their defaults Args: fx (MNPR_FX): MNPR_FX object coming from the caller """ # get node names of operation sfxNodes = getNodeNames(fx, 0) lib.printInfo("Recompiling material") # reset each material materials = getMaterials() for mat in materials: # turn off procedural noise stateId = getId(mat, sfxNodes.stateNodeName) cmds.shaderfx(sfxnode=mat, edit_bool=(stateId, "value", False)) sfxNodes.refreshIds(mat) # reset attributes cmds.shaderfx(sfxnode=mat, edit_float=(sfxNodes.scale, "value", 1.0)) cmds.shaderfx(sfxnode=mat, edit_float=(sfxNodes.intensity, "value", 10.0)) cmds.shaderfx(sfxnode=mat, edit_float=(sfxNodes.shift, "value", 0.0)) cmds.shaderfx(sfxnode=mat, edit_bool=(sfxNodes.scale, "value", True)) lib.printInfo("{0} procedural control has been reset".format( fx.description))
def changeStyle(): """Resets MNPR to load a new style""" # reset stylization cmds.mnpr(resetStylization=True) # delete old config node if cmds.objExists(mnpr_info.configNode): cmds.delete(mnpr_info.configNode) # flush undo cmds.flushUndo() print("style deleted") # deregister node cmds.mnpr(rn=False) # register node cmds.mnpr(rn=True) # create new config node selectConfig() # refresh AETemplate mnpr_runner.reloadConfig() # set new media type mnpr_info.media = cmds.mnpr(style=True, q=True) # rebuild opened UI's import mnpr_UIs if cmds.window(mnpr_UIs.BreakdownUI.windowTitle, exists=True): mnpr_runner.openOverrideSettings(rebuild=True) import mnpr_FX if cmds.window(mnpr_FX.MNPR_FX_UI.windowTitle, exists=True): mnpr_runner.openPaintFX(rebuild=True) lib.printInfo("Style changed")
def run(root): """ Insert system paths in the Maya.env Args: root: root directory of MNPR """ print("-> Installing MNPR") variables = { 'MNPR_PATH': [os.path.abspath(root)], 'MAYA_MODULE_PATH': [os.path.abspath(root)], 'MAYA_VP2_USE_GPU_MAX_TARGET_SIZE': [1] } # get Maya.env file mayaEnvFilePath = cmds.about(env=True, q=True) # check if Maya env exists (some users have reported that the Maya.env file did not exist in their environment dir) if not os.path.isfile(mayaEnvFilePath): tempFileDir = os.path.join(os.path.dirname(mayaEnvFilePath), "Maya.env") with open(tempFileDir, 'ab') as tmp: tmp.write("") # get Maya environment variables envVariables, envVariablesOrder = getEnvironmentVariables(mayaEnvFilePath) print("ENVIRONMENT VARIABLES:") pprint.pprint(envVariables) # check if MNPR is already installed if installationCheck(variables, envVariables): return # merge mnpr variables envVariables = mergeVariables(variables, envVariables) print("MODIFIED VARIABLES:") pprint.pprint(envVariables) # write environment variables tempFilePath = os.path.join(os.path.dirname(mayaEnvFilePath), "maya.tmp") writeVariables(tempFilePath, envVariables, envVariablesOrder) # replace environment file shutil.move(tempFilePath, mayaEnvFilePath) # change renderer to support hardware shaders if cmds.about(win=True): mel.eval('setRenderingEngineInModelPanel "DirectX11"') else: mel.eval('setRenderingEngineInModelPanel "OpenGLCoreProfileCompat"') lib.printInfo("-> Installation complete") # restart maya cmds.confirmDialog( title='Restart Maya', message='\nAll changes will be shown upon restarting Maya', icn='warning', button='OK', ma='center')
def testScene(prototype="shaderFX"): """ Creates a boring default scene with a sphere Args: prototype (str): either with "shaderFX" or "prototypeC" """ mnpr_system.check() # create and place test sphere cmds.polySphere() testSphere = cmds.ls(sl=True) mnpr_matPresets.createMaterial(testSphere, prototype=prototype) mnpr_matPresets.defaultLighting() lib.printInfo("Default scene created")
def installationCheck(variables, envVariables): """ Checks for previous installations and handles each case Args: variables (dict): variables to add during installation envVariables (dict): existing environment variables Returns: Bool: False -> proceed with installation, True -> do not install """ # check for installation mnprVariable = 'MNPR_PATH' if mnprVariable in envVariables: # previous installation exists MNPRPath = "{0}".format( envVariables[mnprVariable][0]) # previous MNPR path iCheck = True # integrity check starts True newMNPRPath = variables[mnprVariable][0] # new MNPR path # if installing from the existing MNPR path if MNPRPath == newMNPRPath: # integrity check iCheck = integrityCheck(variables, envVariables) # if integrity check passed, MNPR if iCheck: message = 'MNPR has already been installed from here:\n "{0}"\n\nPlease restart Maya to show any performed changes.'.format( newMNPRPath) cmds.confirmDialog(m=message, title="MNPR already installed", b="Sure thing!", icn="information") return True # MNPR has been previously installed, what now? mString = "MNPR has been previously installed at:\n {0}\n\nDo you wish to override the existing installation (files won't be deleted).".format( envVariables[mnprVariable][0]) if not iCheck: mString = "MNPR has been previously installed but needs to update for it to work\n\nDo you wish to update the existing installation (files won't be deleted)." reply = cmds.confirmDialog(title='Overriding existing installation', message=mString, button=['Yes', 'No'], defaultButton='Yes', cancelButton='No', dismissString='No', icn="warning") # don't do anything if reply == "No": lib.printInfo("-> Nothing was done to your current installation") return True # delete MNPR paths from environment variables deleteMNPRVariables(envVariables, MNPRPath) return False
def unloadPlugin(plugin): """ Unloads plugin and cleans scene from plugin traces Args: plugin (str): name of plugin to be unloaded """ # check which prototype is active if cmds.pluginInfo(plugin, loaded=True, q=True): # remove traces and unload if cmds.objExists(mnpr_info.configNode): cmds.delete(mnpr_info.configNode) # delete config node cmds.flushUndo() # clear undo queue cmds.unloadPlugin(plugin) # unload plugin lib.printInfo("->PLUGIN SUCCESSFULLY UNLOADED")
def load(self, name): """ Loads the specified attribute set Args: name (str): Name of the attribute set to import """ attrs = self[name]['attributes'] # check if substrate is available substrateAttr = "{0}.substrateTexture".format(mnpr_info.configNode) p = lib.Path(lib.getLibDir()).parent().child("textures") textures = os.listdir(p.path) if attrs[substrateAttr] not in textures: # check if substrates have been installed if len(textures) <= 2: result = cmds.confirmDialog(t="Substrates (papers/canvas) not found", m="The required substrate is not available.\nWould you like to download the MNPR substrates?", b=['Yes', 'Load anyway', 'Close'], icn="warning") if result == "Close": return elif result == "Yes": mnpr_runner.downloadSubstrates() return else: cmds.warning("Substrate texture not found, reverting to default substrate (style might not display correctly)") attrs[substrateAttr] = "rough_default_2k.jpg" else: cmds.warning("Substrate texture not found, reverting to default substrate (style might not display correctly)") attrs[substrateAttr] = "rough_default_2k.jpg" # check change of style first styleAttr = "{0}.style".format(mnpr_info.configNode) if styleAttr in attrs: style = attrs[styleAttr] if style != cmds.mnpr(style=True): lib.setAttr(mnpr_info.configNode, "style", style) func = functools.partial(self.loadStyle, attrs) return cmds.scriptJob(runOnce=True, event=["SelectionChanged", func]) else: # set attributes for attr in attrs: splitter = attr.split('.') lib.setAttr(splitter[0], splitter[1], attrs[attr]) else: # for legacy presets (we do not worry about styles here) for attr in attrs: splitter = attr.split('.') if "NPRConfig" in splitter[0]: splitter[0] = "mnprConfig" lib.setAttr(splitter[0], splitter[1], attrs[attr]) lib.printInfo("Attributes set successfully")
def updateMNPR(directory, files2Update, files2Delete): """ Updates MNPR at directory Args: directory (str): Directory where MNPR is installed files2Update (list): files that need to be updated files2Delete (list): files that need to be deleted Returns: True if update successful """ print("\nUpdating files at {0}".format(directory)) print("Files to update: {0}".format(files2Update)) print("Files to delete: {0}".format(files2Delete)) # unload MNPR mnpr_system.unloadPlugin(mnpr_info.prototype) # update files downloader = urllib.URLopener() for f in files2Update: onlineURL = "{0}{1}".format(distURL, f) print("Downloading {0}".format(onlineURL)) filePath = os.path.abspath(os.path.join(directory, f.lstrip('/'))) try: downloader.retrieve(onlineURL, filePath) except IOError: print("Error: Couldn't download {0} into {1}".format(onlineURL, filePath)) continue # after download, reload modules try: module = f.split("/")[-1].split(".")[0] exec("reload({0})".format(module)) except NameError: pass print("Download successful") # delete deprecated files for f in files2Delete: filePath = os.path.abspath(os.path.join(directory, f.lstrip('/'))) print("Deleting {0}".format(filePath)) try: os.remove(filePath) except: print("Couldn't remove {0}".format(filePath)) lib.printInfo("Update completed.") return True
def refreshShaders(): """ Refreshes object-space plugin shaders """ shaderDir = systemDir("shaders") if os.name == 'nt' and mnpr_info.backend == 'dx11': shaderFile = os.path.join(shaderDir, "PrototypeC.fx") if not os.path.isfile(shaderFile): shaderFile = os.path.join(shaderDir, "prototypeC.fxo") shaders = cmds.ls(type="dx11Shader") else: shaderFile = os.path.join(shaderDir, "PrototypeC.ogsfx") shaders = cmds.ls(type="GLSLShader") for shader in shaders: cmds.setAttr("{0}.shader".format(shader), shaderFile, type="string") lib.printInfo('Shaders refreshed') return True
def run(root): """ Insert system paths in the Maya.env Args: root: root directory of the plugin hierarchy """ print("-> Installing plugin") variables = {'MAYA_MODULE_PATH': [os.path.abspath(root)]} # get Maya.env file mayaEnvFilePath = cmds.about(env=True, q=True) # check if Maya env exists (some users have reported that the Maya.env file did not exist in their environment dir) if not os.path.isfile(mayaEnvFilePath): tempFileDir = os.path.join(os.path.dirname(mayaEnvFilePath), "Maya.env") with open(tempFileDir, 'ab') as tmp: tmp.write("") # get Maya environment variables envVariables, envVariablesOrder, envCleanup = getEnvironmentVariables( mayaEnvFilePath) print("ENVIRONMENT VARIABLES:") pprint.pprint(envVariables) # merge environment variables envVariables = mergeVariables(variables, envVariables) print("MODIFIED VARIABLES:") pprint.pprint(envVariables) # write environment variables tempFilePath = os.path.join(os.path.dirname(mayaEnvFilePath), "maya.tmp") writeVariables(tempFilePath, envVariables, envVariablesOrder) # replace environment file shutil.move(tempFilePath, mayaEnvFilePath) lib.printInfo("-> Installation complete") # restart maya (we make sure everything will load correctly once maya is restarted) cmds.confirmDialog( title='Restart Maya', message= 'Installation successful!\nPlease restart Maya to make sure everything loads correctly', icn='information', button='OK', ma='center')
def installationCheck(variables, envVariables): """ Checks for previous installations and handles each case Args: variables (dict): variables to add during installation envVariables (dict): existing environment variables Returns: Bool: True -> proceed with installation, False -> do not install """ mnprVariable = 'MNPR_PATH' if mnprVariable in envVariables: mnprPath = variables[mnprVariable][0] # if installing from the existing MNPR path if envVariables[mnprVariable][0] == mnprPath: message = 'MNPR has already been installed from here:\n "{0}"\n\nPlease restart Maya to show any performed changes.'.format( mnprPath) cmds.confirmDialog(m=message, title="MNPR already installed", b="Sure thing!", icn="information") return False # MNPR has been previously installed, what now? mString = "MNPR has been previously installed at:\n {0}\n\nDo you wish to override the existing installation (files won't be deleted).".format( envVariables[mnprVariable][0]) reply = cmds.confirmDialog(title='Overriding existing installation', message=mString, button=['Yes', 'No'], defaultButton='Yes', cancelButton='No', dismissString='No', icn="warning") # don't do anything if reply == "No": lib.printInfo("-> Nothing was done to your current installation") return False # delete mnpr paths previousPath = "{0}".format(envVariables[mnprVariable][0]) print("Deleting previous MNPR installation at : {0}".format( previousPath)) for key in envVariables: for value in envVariables[key]: if previousPath in str(value): envVariables[key].remove(value) return True
def noiseSlide(fx, widget): """ Noise slide, will modify the procedural noise of an effect Args: fx (MNPR_FX): MNPR_FX object coming from the caller widget (LabeledSlider): LabeledSlider object that is calling this function """ # get index of sliding operation idx = 0 # default scale index if widget.label != "scale": idx = fx.procOptions.index(widget.label) # get node names of operation sfxNodes = getNodeNames(fx, idx) # get value to enter valueDiff = widget.slider.relValue() if widget.label == "scale": valueDiff /= 100.0 else: valueDiff /= 5.0 materials = getMaterials() for mat in materials: # turn on procedural noise if turned off stateId = getId(mat, sfxNodes.stateNodeName) if not cmds.shaderfx(sfxnode=mat, getPropertyValue=(stateId, "value")): lib.printInfo("Recompiling material") cmds.shaderfx(sfxnode=mat, edit_bool=(stateId, "value", True)) # get attribute name attr = "" if widget.label != "scale": attr = sfxNodes.intensityNodeName else: attr = sfxNodes.scaleNodeName # set attribute attribute = "{0}.{1}".format(mat, attr) prevValue = cmds.getAttr(attribute) newValue = prevValue + valueDiff lib.setAttr(mat, attr, newValue)
def selectConfig(): """Select configuration node and re-check connections""" # delete old configuration nodes if cmds.objExists("NPRConfig"): cmds.delete("NPRConfig") if not cmds.objExists(mnpr_info.configNode): print(mnpr_info.configNode) cmds.createNode("mnprConfig", n=mnpr_info.configNode) cmds.connectAttr("{0}.evaluate".format(mnpr_info.configNode), "persp.visibility", f=True) mel.eval("AttributeEditor") lib.printInfo("-> CONFIG NODE CREATED AND CONNECTED") else: cmds.select(mnpr_info.configNode) mel.eval("AttributeEditor") lib.printInfo("Selected {0} configuration node".format( mnpr_info.prototype))
def updateShaderFX(): """ Updates shaderFX shaders""" shaderDir = systemDir("shaders") materials = cmds.ls(type="ShaderfxShader") counter = 0 for mat in materials: counter += 1 # get materials attributes matAttrs = {} mnpr_matPresets.getMaterialAttrs(mat, matAttrs) # load new graph shaderFile = os.path.join(shaderDir, "{0}.sfx".format(matAttrs["graph"])) cmds.shaderfx(sfxnode=mat, loadGraph=shaderFile) # set attributes mnpr_matPresets.setMaterialAttrs(mat, matAttrs) print("{0} has been updated to the latest version".format(mat)) print("{0}/{1} materials updated".format(counter, len(materials))) lib.printInfo('Shaders updated')
def getPlugin(variables): """ Gets the plugin locally or online Args: variables (dict): environment variables """ pluginName = "MNPR{0}".format(ext) # check if plugin is available, otherwise, download pluginDir = variables["MAYA_PLUG_IN_PATH"][0] lib.createDirectory(pluginDir) filesInDir = os.listdir(pluginDir) if not filesInDir: # download the right plugin for the OS and Maya version pluginURL = "{0}/plugins".format(distURL) pluginURL += "/{0}".format(mayaV) # add Maya version pluginURL += "/{0}".format(lib.localOS()) # add OS pluginURL += "/{0}".format(pluginName) # add plugin name # get plugin file online print("Getting plugin from: {0}".format(pluginURL)) lib.printInfo("Downloading plugin...") downloader = urllib.URLopener() downloader.retrieve(pluginURL, os.path.join(pluginDir, pluginName))
def noiseTypeClicked(fx): """ Toggle between noise types (3D or 2D) Args: fx (MNPR_FX): MnprFx object coming from the caller """ materials = getMaterials() # get node names of operation sfxNodes = getNodeNames(fx, 0) lib.printInfo("Recompiling material") typeId = getId( materials[0], sfxNodes.typeNodeName) # base toggle on first material state state = cmds.shaderfx(sfxnode=materials[0], getPropertyValue=(typeId, "value")) for mat in materials: cmds.shaderfx(sfxnode=mat, edit_bool=(typeId, "value", not state)) if state: lib.printInfo("NoiseFX for {0} is now in 2D".format(fx.description)) else: lib.printInfo("NoiseFX for {0} is now in 3D".format(fx.description))
def noiseToggleClicked(fx): """ Toggle procedural effect (On or Off) Args: fx (MNPR_FX): MnprFx object coming from the caller """ materials = getMaterials() # get node names of operation sfxNodes = getNodeNames(fx, 0) lib.printInfo("Recompiling material") stateId = getId( materials[0], sfxNodes.stateNodeName) # base toggle on first material state state = cmds.shaderfx(sfxnode=materials[0], getPropertyValue=(stateId, "value")) for mat in materials: stateId = getId(mat, sfxNodes.stateNodeName) cmds.shaderfx(sfxnode=mat, edit_bool=(stateId, "value", not state)) if state: lib.printInfo("NoiseFX for {0} is off".format(fx.description)) else: lib.printInfo("NoiseFX for {0} is on".format(fx.description))
def getSubstrates(): """ Downloads and extracts the substrate textures """ url = "https://researchdata.ntu.edu.sg/api/access/datafile/2793?gbrecs=true" if lib.localOS() == "mac": result = cmds.confirmDialog( t="Download substrates", m= "Please download the substrates and extract them into the textures folder of MNPR.", b="Download", icn="information") if result == "Download": lib.openUrl("https://doi.org/10.21979/N9/HI7GT7") lib.openUrl(url) return else: lib.printInfo("No substrates will be downloaded.") return # windows and linux import zipfile result = cmds.confirmDialog( t="Downloading substrates", m= "Do you wish to download the substrates \nautomatically in the background?", b=['Yes', 'Manual download', 'Close'], icn="question") if result == "Manual download": lib.openUrl("https://doi.org/10.21979/N9/HI7GT7") lib.openUrl(url) return elif result == "Close": lib.printInfo("No substrates will be downloaded.") return else: p = lib.Path(lib.getLibDir()) p.parent().child("textures") dest = os.path.join(p.path, "seamless_textures_light.zip") if lib.downloader(url, dest): print("Substrates downloaded, extracting...") zip = zipfile.ZipFile(dest, 'r') zip.extractall(p.path) zip.close() os.remove(dest) lib.printInfo("MNPR substrates installed successfully") cmds.confirmDialog(t="Download successful", m="The substrates downloaded successfully", b="Yay!", icn="information") else: cmds.warning( "Problem downloading substrates, please download and install manually" ) result = cmds.confirmDialog( t="Download substrates", m= "Please download the substrates and extract them into the textures folder of MNPR.", b="Download", icn="information") if result == "Download": lib.openUrl("https://doi.org/10.21979/N9/HI7GT7") lib.openUrl(url)
def playblast(saveDir, width, height, renderCamera, modelPanel, renderSize=1): """ Playblasts the timeslider Args: saveDir (str): save directory with *.mov extension width (int): width in pixels height: height in pixels renderCamera: camera to playblast from modelPanel: modelPanel to playblast from renderSize: render size (factor) """ check() # check that everything is in order renderSize = resolutionCheck( width, height, renderSize) # make sure resolution is reasonable aPlayBackSliderPython = mel.eval('$tmpVar=$gPlayBackSlider') audioNode = cmds.timeControl(aPlayBackSliderPython, q=True, s=True) # get audio node # get working values to be changed workingRenderSize = cmds.getAttr("{0}.renderScale".format( mnpr_info.configNode)) workingColorDepth = cmds.getAttr("{0}.colorDepth".format( mnpr_info.configNode)) workingCamera = cmds.modelEditor(modelPanel, cam=True, q=True) workingCameraShape = cmds.listRelatives(workingCamera, s=True) if workingCameraShape: workingCameraShape = workingCameraShape[0] else: # we already have the shape workingCameraShape = workingCamera # set desired attributes cmds.mnpr(g=True) mnprOperations = len(cmds.mnpr(lsO=True)) cmds.mnpr(renderOperation=mnprOperations - 1, s=0) # HUD cmds.mnpr(renderOperation=mnprOperations - 2, s=0) # UI cmds.modelEditor(modelPanel, cam=renderCamera, e=True) # change modelPanel lib.setAttr(mnpr_info.configNode, "renderScale", renderSize) lib.setAttr(mnpr_info.configNode, "colorDepth", 2) # needs to be 32bit to avoid artefacts cmds.refresh() # try playblasting try: cmds.playblast(f=saveDir, format="qt", w=width, h=height, percent=100, qlt=100, v=True, fo=True, os=True, s=audioNode, compression="PNG") except RuntimeError: try: cmds.playblast(f=saveDir, format="avi", w=width, h=height, percent=100, qlt=100, v=True, fo=True, os=True, s=audioNode) except RuntimeError: cmds.error( "Video cannot be playblasted as qt or avi, please check the installed codecs." ) # bring everything back to normal cmds.mnpr(renderOperation=mnprOperations - 1, s=1) # HUD cmds.mnpr(renderOperation=mnprOperations - 2, s=1) # UI cmds.modelEditor(modelPanel, cam=workingCameraShape, e=True) lib.setAttr(mnpr_info.configNode, "renderScale", workingRenderSize) lib.setAttr(mnpr_info.configNode, "colorDepth", workingColorDepth) cmds.mnpr(g=False) cmds.refresh() lib.printInfo( "Video has been successfully playblasted to: {0}".format(saveDir))
def checkUpdates(directory): """ Checks for MNPR updates online and lets the user decide what to do Args: directory (str): Directory of installed MNPR """ print("Checking for updates...") # get local mnpr version localPath = os.path.join(directory, "version.json") with open(localPath, 'r') as f: localMNPR = json.load(f) # get online mnpr version onlinePath = distURL + "/version.json" tempPath = os.path.join(directory, "onlineVersion.json") downloader = urllib.URLopener() try: downloader.retrieve(onlinePath, tempPath) except IOError: lib.printInfo("Maya can't connect to the internet.") return with open(tempPath, 'r') as f: onlineMNPR = json.load(f) os.remove(tempPath) # check versions localVer = localMNPR.pop("version") onlineVer = onlineMNPR.pop("version") if onlineVer <= localVer: return "Nothing to update" # delete unnecessary plugin entries depending on OS mayaV = int(lib.mayaVersion()) localOS = "win" if cmds.about(mac=True): localOS = "mac" elif cmds.about(linux=True): localOS = "linux" # search in local version keys2Delete = [] for key in localMNPR: if "/plugins/" in key: if "/{0}/{1}".format(mayaV, localOS) not in key: keys2Delete.append(key) continue # delete unnecessary local keys for key in keys2Delete: localMNPR.pop(key) # search in online version keys2Delete = [] for key in onlineMNPR: if "/plugins/" in key: if "/{0}/{1}".format(mayaV, localOS) not in key: keys2Delete.append(key) continue # delete unnecessary online keys for key in keys2Delete: onlineMNPR.pop(key) print("LOCAL") pprint.pprint(localMNPR) print("\nONLINE") pprint.pprint(onlineMNPR) # compare the two versions files2Update = [] for key in onlineMNPR: if key in localMNPR: for file in onlineMNPR[key]: if file in localMNPR[key]: if onlineMNPR[key][file]>localMNPR[key][file]: # online file is newer than local file, download files2Update.append("{0}/{1}".format(key, file)) else: # file doesn't exist locally, download files2Update.append("{0}/{1}".format(key, file)) else: for file in onlineMNPR[key]: files2Update.append("{0}/{1}".format(key, file)) files2Delete = [] for key in localMNPR: if key in onlineMNPR: for file in localMNPR[key]: if file not in onlineMNPR[key]: files2Delete.append("{0}/{1}".format(key, file)) else: for file in localMNPR[key]: files2Delete.append("{0}/{1}".format(key, file)) # check if a shelf needs to update, as Maya would then require a restart restartMaya = False for f2u in files2Update: if "/shelves/" in f2u: restartMaya = True for f2d in files2Delete: if "/shelves/" in f2d: restartMaya = True # update prompt mString = "An update for MNPR is available, do you wish to download and install this update?\n\n" mString += "Files to be updated:\n" if files2Update: for fUpdate in files2Update: mString += "-. {0}\n".format(fUpdate) else: mString += "- None -\n" mString += "\nFiles to be deleted:\n" if files2Delete: for fDelete in files2Delete: mString += "-. {0}\n".format(fDelete) else: mString += "- None -\n" reply = cmds.confirmDialog(title='Update is available', message=mString, button=['Yes', 'No'], defaultButton='Yes', cancelButton='No', dismissString='No', icn="information") # don't do anything if reply == "No": lib.printInfo("Nothing has been updated") return if restartMaya: mString = "The shelf will be updated, so Maya will close automatically after the update has concluded\n\n" mString += "No scenes/preferences will be saved upon closure, do you still wish to proceed?" reply = cmds.confirmDialog(title='Shelf update', message=mString, button=['Yes', 'No'], defaultButton='Yes', cancelButton='No', dismissString='No', icn="warning") if reply == "No": lib.printInfo("Nothing has been updated") return if updateMNPR(directory, files2Update, files2Delete): if restartMaya: cmds.quit(abort=True)