def binariesPath(cls, version=None, architecture=64, language='English'): """ Finds the install path for various software installations. :param version: The version of the software. Default is None :param architecture: The bit type to query the registry for(32, 64). Default is 64 :param language: Optional language that may be required for specific softwares. """ version = cls._yearForVersion.get(unicode(version), version) hive = 'HKEY_LOCAL_MACHINE' from cross3d.migrate import winregistry if version == None: # Get all of the installed versions so we can find the latest version. versions = winregistry.listRegKeys(hive, cls._hkeyBase, architecture=architecture) for v in sorted(versions, reverse=True): if v not in cls._ignoredVersions: version = v break hkey = r'{hkeyBase}\{version}'.format(hkeyBase=cls._hkeyBase, version=version) try: ret = winregistry.registryValue(hive, hkey, 'InstallPath', architecture)[0] except WindowsError: raise Exceptions.SoftwareNotInstalled('MotionBuilder', version=version, architecture=architecture, language=language) # If the version is not installed this will return '.', we want to return False. if ret: return os.path.normpath(ret) raise Exceptions.SoftwareNotInstalled('MotionBuilder', version=version, architecture=architecture, language=language)
def binariesPath(cls, version=None, architecture=64, language='English'): """ Finds the install path for various software installations. If version is None, the default it will return the latest installed version of the software. Raises cross3d.Exceptions.SoftwareNotInstalled if the software is not installed. :param version: The version of the software. Default is None :param architecture: The bit type to query the registry for(32, 64). Default is 64 :param language: Optional language that may be required for specific softwares. """ langId = cls._languageIDs.get(language, cls._languageIDs['English']) hive = 'HKEY_LOCAL_MACHINE' # Ensure we get a valid version number version = cls._versionForYear.get(unicode(version), version) from cross3d.migrate import winregistry if version == None: # Get all of the installed versions so we can find the latest version. versions = set( winregistry.listRegKeys(hive, cls._hkeyBase, architecture=architecture)) # Years to ignore isnt very useful, convert them to version numbers ('14.0'). # This allows the environment variable to remain the same for all of the software implemntations ignoredVersions = set([ '{}.0'.format(cls._versionForYear[year]) for year in cls._ignoredVersions if year in cls._versionForYear ]) for v in sorted(versions, reverse=True): if v in versions and v not in ignoredVersions: version = v.rsplit('.', 1)[0] try: float(version) except ValueError: # Not a valid version number. Most likely something like RegistryVersion19.0 continue # Ignore all keys that don't store Installdir info. hkey = cls._getHkey(version, langId) try: ret = winregistry.registryValue( hive, hkey, 'Installdir', architecture)[0] if not ret: continue except WindowsError: continue break dispVersion = cls._yearForVersion.get(unicode(version), version) hkey = cls._getHkey(version, langId) try: ret = winregistry.registryValue(hive, hkey, 'Installdir', architecture)[0] except WindowsError: raise Exceptions.SoftwareNotInstalled('Studiomax', version=dispVersion, architecture=architecture, language=language) # If the version is not installed this will return '.', we want to return False. if ret: return os.path.normpath(ret) raise Exceptions.SoftwareNotInstalled('Studiomax', version=dispVersion, architecture=architecture, language=language)
def __exit__(self, exec_type, exec_value, traceback): if hasattr(exec_value, 'message'): if exec_value.message in ( '(kInvalidParameter): Argument is a NULL pointer', '(kFailure): Object does not exist'): # This exception is raised when you try to access a MObject via MObjectHandle that # no longer exists in the scene. raise Exceptions.InvalidNativeObject( 'The Native Pointer is invalid') # re-raise the exception return False
def binariesPath(cls, version=None, architecture=64, language='English'): """ Finds the install path for various software installations. If version is None, the default it will return the latest installed version of the software. Raises cross3d.Exceptions.SoftwareNotInstalled if the software is not installed. :param version: The version of the software. Default is None :param architecture: The bit type to query the registry for(32, 64). Default is 64 :param language: Optional language that may be required for specific softwares. """ from cross3d.migrate import winregistry hive = 'HKEY_LOCAL_MACHINE' hkey = r'Software\Autodesk\Softimage\InstallPaths' ret = None if version == None: # Find the latest version versions = winregistry.listRegKeyValues(hive, hkey, architecture=architecture) for version in sorted(versions, key=lambda i: i[0], reverse=True): if version[0] not in cls._ignoredVersions: ret = version[1] break else: version = cls._yearForVersion.get(unicode(version), version) try: ret = winregistry.registryValue(hive, hkey, unicode(version), architecture)[0] except WindowsError: raise Exceptions.SoftwareNotInstalled( 'Softimage', version=version, architecture=architecture, language=language) # If the version is not installed this will return '.', we want to return False. if ret: return os.path.join(os.path.normpath(ret), 'Application', 'bin') raise Exceptions.SoftwareNotInstalled('Softimage', version=version, architecture=architecture, language=language)
def generatePlayblast( self, fileName, frameRange=None, resolution=None, slate=None, effects=True, geometryOnly=True, pathFormat=r'{basePath}\{fileName}.{frame}.{ext}'): fileName, ext = os.path.splitext(fileName) # Make sure a invalid file format was not requested if ext.replace('.', '').lower() not in self._validPlayblastFormats: raise Exceptions.FileFormatNotSupported('The file format {ext} is not supported by Maya'.format(ext=ext)) playblastFormat = 'image' compression = ext.replace('.', '') quality = 100 if ext.lower() == '.mov': playblastFormat = 'qt' elif ext.lower() == '.avi': playblastFormat = 'avi' compression = None if isinstance(frameRange, int): frameRange = FrameRange([frameRange, frameRange]) if not frameRange: frameRange = self._scene.animationRange() # TODO: Make generating movies not require setting frame padding to 1 padding = 1 if not resolution: resolution = self._scene.renderSize() # TODO: Add support for these arguments if slate != None: # Note: this is probably how we can handle slate #cmds.headsUpDisplay( 'blurBurnin', section=8, block=0, blockAlignment='right', dw=50, label='This is my burnin') cross3d.logger.debug('slate is not implemented in Maya') if pathFormat != r'{basePath}\{fileName}.{frame}.{ext}': cross3d.logger.debug('pathFormat is not implemented in Maya') # Prepare to detect if the playblast was canceled formatter = '{fileName}.{frame:0%i}{ext}' % padding lastFrameFileName = formatter.format(fileName=fileName, frame=frameRange[1], ext=ext) try: lastFrameStartTime = os.path.getmtime(lastFrameFileName) except os.error: lastFrameStartTime = 0 # to properly generate a playblast # pass the width/height to the playblast command # set the camera displayOptions # set overscan to 1.0 and lock it # uncheck all options # set camera\Film Back # Fit Resolution Gate to overscan # set proper film aspect ratio? # set the render resolution? # MCH 10/16/14 NOTE: Info on parsing playblast Display Menu if we decide to add support for that later #-------------------------------------------------------------------------------- #for i in cmds.optionVar(list=True): # if i.startswith('playblastShow'): # print cmds.optionVar(query=i), i # # Set the value # cmds.optionVar( intValue=(i, False) # # Update the playblast menus # maya.mel.eval('updatePlayblastPluginMenus()') #-------------------------------------------------------------------------------- cam = self.camera() name = cam.path() overscanLocked = cmds.getAttr("{name}.overscan".format(name=cam.path()), lock=True) if overscanLocked: # unlock overscan if it is locked cmds.setAttr("{name}.overscan".format(name=name), lock=False) # create a StateLocker object to backup the current values before setting them from blur3d.lib.statelockerlib import StateLocker with StateLocker() as stateLocker: # Currently the state locker isnt the most convienent to use def setPropertyLocker(obj, key, value): stateLocker.setMethodArgs(obj, obj.setProperty, partial(obj.property, key), key, value) # Set FilmBack.FitResolutionGate to Overscan setPropertyLocker(cam, 'filmFit', 3) # uncheck Display Film Gate setPropertyLocker(cam, 'displayFilmGate', 0) # uncheck Display Resolution setPropertyLocker(cam, 'displayResolution', 0) # Set overscan to 1.0 setPropertyLocker(cam, 'overscan', 1.0) # Store and restore these settings using modelEditor # The key is the property to query/edit, the value is the value used while playblasting modelEditorOverrides = {'sel':False} # Find the current viewport so we can apply the viewport settings panel = cmds.getPanel(withFocus=True) # Check for if non-viewport panel's are active if not panel in cmds.getPanel(type='modelPanel'): panel = 'modelPanel4' if geometryOnly: modelEditorOverrides['nurbsSurfaces'] = True modelEditorOverrides['polymeshes'] = True modelEditorOverrides['subdivSurfaces'] = True # HACK: This records the viewport show options, sets them to playblast options, then # restores them # TODO: Make this load the settings from the playblast overrides attrs = ['nurbsCurves', 'nurbsSurfaces', 'cv', 'hulls', 'polymeshes', 'subdivSurfaces', 'planes', 'lights', 'cameras', 'imagePlane', 'joints', 'ikHandles', 'dynamics', 'deformers', 'fluids', 'hairSystems', 'follicles', 'nCloths', 'nParticles', 'nRigids', 'dynamicConstraints', 'locators', 'dimensions', 'pivots', 'handles', 'textures', 'strokes', 'motionTrails', 'pluginShapes', 'clipGhosts', 'greasePencils', 'manipulators', 'grid', 'hud'] # Disable display of all of these options as long as modelEditorOverrides doesnt # already contain a setting key updateDict = dict([(attr, False) for attr in attrs if attr not in modelEditorOverrides]) modelEditorOverrides.update(updateDict) # New features in 2015 if cross3d.application.version() > 2014 and 'particleInstancers' not in modelEditorOverrides: modelEditorOverrides.update(particleInstancers=False) if effects == True: modelEditorOverrides.update(displayTextures=True, displayLights='all') setPropertyLocker(self._scene, 'hardwareRenderingGlobals.ssaoEnable', 1) setPropertyLocker(self._scene, 'hardwareRenderingGlobals.motionBlurEnable', 1) setPropertyLocker(self._scene, 'hardwareRenderingGlobals.multiSampleEnable', True) # TODO: Add Camera.setDeptOfField to cross3d ntp = cam._nativeTypePointer stateLocker.setMethod(ntp, ntp.setDepthOfField, ntp.isDepthOfField, True) if effects == False: modelEditorOverrides.update(displayTextures=False, displayLights='default') setPropertyLocker(self._scene, 'hardwareRenderingGlobals.ssaoEnable', 0) setPropertyLocker(self._scene, 'hardwareRenderingGlobals.motionBlurEnable', 0) setPropertyLocker(self._scene, 'hardwareRenderingGlobals.multiSampleEnable', False) # TODO: Add Camera.setDeptOfField to cross3d ntp = cam._nativeTypePointer stateLocker.setMethod(ntp, ntp.setDepthOfField, ntp.isDepthOfField, False) # Store the current values modelEditorStates = {} for option, value in modelEditorOverrides.iteritems(): # Store the current value modelEditorStates[option] = cmds.modelEditor(panel, query=True, **{option: True}) # Set the playblast value cmds.modelEditor(panel, edit=True, **{option: value}) # # Uncomment this code to update the ui so you can see what options get disabled in the toolbar # from PyQt4.QtGui import QApplication, QMessageBox # QApplication.processEvents() # QMessageBox.question(None, 'Temp', 'update') # generate playblast cmds.playblast( width=resolution.width(), height=resolution.height(), startTime=frameRange.start(), endTime=frameRange.end(), percent=100, filename=fileName, showOrnaments=False, format=playblastFormat, compression=compression, quality=quality, framePadding=padding, viewer=False) # Restore the modelEditor options to their previous value for option, value in modelEditorStates.iteritems(): cmds.modelEditor(panel, edit=True, **{option: value}) if overscanLocked: # relock overscan cmds.setAttr("{name}.overscan".format(name=name), lock=True) # No way to detect if a avi or quicktime was canceled if ext.lower() in ('.mov', '.avi'): return True # If the capture was not completed we just return False. try: lastFrameEndTime = os.path.getmtime(lastFrameFileName) if not lastFrameStartTime < lastFrameEndTime: return False except os.error: return False return True
def generatePlayblast(self, fileName, frameRange=None, resolution=None, slate=None, effects=True, geometryOnly=True, pathFormat=r'{basePath}\{fileName}.{frame}.{ext}'): """ Creates an unpadded JPG file sequence from the viewport for a given range. """ # Treating inputs. if isinstance(frameRange, int): frameRange = FrameRange([frameRange, frameRange]) # Checking frame range. initialFrameRange = self._scene.animationRange() if not frameRange: frameRange = initialFrameRange # Collecting data. nativeCamera = self._nativeCamera() def genImagePath(frame=None): basePath, fn = os.path.split(fileName) pf = pathFormat # Deal with xsi's special number padding format if frame == None: filen = '(fn)' ext = '(ext)' # Remove any number specific formatting so we can insert a simple # for each padding digit pf = re.sub(r'{frame:[^}]*', r'{frame', pf) padding = re.findall(r'{frame:(\d+)', pathFormat) if padding: frameNo = '#' * int(padding[0]) else: frameNo = '#' else: fileSplit = fn.split('.') filen = '.'.join(fileSplit[:-1]) ext = fileSplit[-1] frameNo = frame out = pf.format(basePath=basePath, fileName=filen, frame=frameNo, ext=ext) index = pathFormat.find('{ext}') if frame == None and index > 0 and pathFormat[index - 1] == '.': # strip out the file extension dot fileSplit = out.split('.') out = '.'.join(fileSplit[:-1]) + fileSplit[-1] return out firstFrameFileName = genImagePath(frameRange[0]) lastFrameFileName = genImagePath(frameRange[1]) try: firstFrameStartTime = os.path.getmtime(firstFrameFileName) lastFrameStartTime = os.path.getmtime(lastFrameFileName) except os.error: firstFrameStartTime = 0 lastFrameStartTime = 0 # Storing object states. self._scene.storeState() self.storeViewOptions() # Setting slate. if slate: self.setSlateText(slate) self.setSlateIsActive(True) xsi.SetValue(nativeCamera.FullName + '.camvis.currenttime', False) elif slate == None: xsi.SetValue(nativeCamera.FullName + '.camvis.currenttime', False) else: xsi.SetValue(nativeCamera.FullName + '.camvis.currenttime', True) # Setting regular visibility options. nativeCamera.Properties('Camera Visibility').Parameters( 'gridvis').Value = False nativeCamera.Properties('Camera Visibility').Parameters( 'gridaxisvis').Value = False nativeCamera.Properties('Camera Visibility').Parameters( 'constructionlevel').Value = False nativeCamera.Properties('Camera Visibility').Parameters( 'objannotationobjects').Value = False xsi.SetValue('preferences.ViewCube.show', False) if geometryOnly: # Setting geometry only visibility options. nativeCamera.Properties('Camera Visibility').Parameters( 'objpolymesh').Value = True nativeCamera.Properties('Camera Visibility').Parameters( 'objparticles').Value = True nativeCamera.Properties('Camera Visibility').Parameters( 'objinstances').Value = True nativeCamera.Properties('Camera Visibility').Parameters( 'objlights').Value = False nativeCamera.Properties('Camera Visibility').Parameters( 'objcameras').Value = False nativeCamera.Properties('Camera Visibility').Parameters( 'objimpgeometry').Value = False nativeCamera.Properties('Camera Visibility').Parameters( 'objcurves').Value = False nativeCamera.Properties('Camera Visibility').Parameters( 'objhair').Value = False nativeCamera.Properties('Camera Visibility').Parameters( 'objnulls').Value = False nativeCamera.Properties('Camera Visibility').Parameters( 'objctrltransfogroups').Value = False nativeCamera.Properties('Camera Visibility').Parameters( 'objctrlchnjnts').Value = False nativeCamera.Properties('Camera Visibility').Parameters( 'objctrlchnroots').Value = False nativeCamera.Properties('Camera Visibility').Parameters( 'objctrlchneff').Value = False nativeCamera.Properties('Camera Visibility').Parameters( 'objctrllattices').Value = False nativeCamera.Properties('Camera Visibility').Parameters( 'objctrltextsupp').Value = False nativeCamera.Properties('Camera Visibility').Parameters( 'objctrlchnjnts').Value = False nativeCamera.Properties('Camera Visibility').Parameters( 'objctrlwaves').Value = False nativeCamera.Properties('Camera Visibility').Parameters( 'objctrlother').Value = False nativeCamera.Properties('Camera Visibility').Parameters( 'objenvironment').Value = False nativeCamera.Properties('Camera Visibility').Parameters( 'custominfo').Value = False # Checking resolution. if not resolution: resolution = QSize( xsi.GetValue("Passes.RenderOptions.ImageWidth"), xsi.GetValue("Passes.RenderOptions.ImageHeight")) # Setting the scene range. Apparently if you don't it causes an animation layer issue. if not initialFrameRange.contains(frameRange): self._scene.setAnimationRange(frameRange) # Set camera's picture ratio. camera = self.camera() if camera: pictureRatio = camera.pictureRatio() camera.setPictureRatio( float(resolution.width()) / resolution.height()) fps = self._scene.animationFPS() viewportCapture = xsi.Dictionary.GetObject( 'ViewportCapture').NestedObjects viewportCapture('File Name').Value = fileName viewportCapture('Padding').Value = os.path.basename(genImagePath()) viewportCapture('Width').Value = resolution.width() viewportCapture('Height').Value = resolution.height() viewportCapture('Scale Factor').Value = 1 viewportCapture('User Pixel Ratio').Value = True viewportCapture('Pixel Ratio').Value = 1 viewportCapture('Frame Rate').Value = fps viewportCapture('Write Alpha').Value = False viewportCapture('Record Audio Track').Value = False viewportCapture('Start Frame').Value = frameRange[0] viewportCapture('End Frame').Value = frameRange[1] viewportCapture('Launch Flipbook').Value = False viewportCapture('Use Native Movie Player').Value = False viewportCapture('Movie').Value = False viewportCapture('OpenGL Anti-Aliasing').Value = 16 if effects else 1 viewportCapture('Remember Last Sequence').Value = False letterToNumber = {"A": 1, "B": 2, "C": 3, "D": 4} xsi.CaptureViewport(letterToNumber[self.name], False) # Restoring states. self._scene.restoreViewOptions() self.restoreViewOptions() if camera: camera.setPictureRatio(pictureRatio) # If the famous capture Softimage bug happened we raise a specific error. try: firstFrameEndTime = os.path.getmtime(firstFrameFileName) if not firstFrameStartTime < firstFrameEndTime: raise Exceptions.OutputFailed( 'The playblast failed due to a native Softimage bug. Do not panic, the fix is easy. Open the regular capture window, change the format to anything. Close the window and try again.' ) except os.error: raise Exceptions.OutputFailed( 'The playblast failed due to a native Softimage bug. Do not panic, the fix is easy. Open the regular capture window, change the format to anything. Close the window and try again.' ) # If the capture was not completed we just return False. try: lastFrameEndTime = os.path.getmtime(lastFrameFileName) if not lastFrameStartTime < lastFrameEndTime: return False except os.error: return False return True