def setResolution(self, resolution): if self.isReferenced(): # handles qstrings resolution = unicode(resolution) # If I dont re-initialize a model object it does not return me the right resolutions. resolutions = self._scene.findObject(self.name()).resolutions() for res in resolutions: # Handles cases sensitivity (crappy, but needed because resolution # names often come from filenames). if res.lower() != resolution.lower(): continue # Storing the user props that might be compromised when switching the reference model. userProps = self.userProps() oldUserProps = userProps.lookupProps() # Setting the resolution. xsi.SetValue("%s.Delta.persist_mixer_modifications"%self._nativePointer.FullName, 13, "") xsi.SetResolutionOfRefModels(self._nativePointer, resolutions.index(res)) xsi.SetValue("%s.Delta.persist_mixer_modifications"%self._nativePointer.FullName, 15, "") # Making sure all the keys that where on the old resolution are re-assigned to the new one. for key in oldUserProps: if oldUserProps.get(key) and not userProps.get(key): userProps[key] = oldUserProps[key] # If the resolution did change. if self.resolution() == res: return True else: self.userProps()['resolution'] = resolution return False
def setSilentMode(self, switch): """ \remarks implements AbstractScene.setSilentMode method to make the application silent during intense calls. \param switch <bool> \return <bool> success """ if switch: if not self._buffer.get('silentMode', None): self._buffer['silentMode'] = {} self._buffer['silentMode']['cmdlog'] = xsi.GetValue( "preferences.scripting.cmdlog") self._buffer['silentMode']['msglogverbose'] = xsi.GetValue( "preferences.scripting.msglogverbose") self._buffer['silentMode']['msglogrealtime'] = xsi.GetValue( "preferences.scripting.msglogrealtime") self._buffer['silentMode']['autoinspect'] = xsi.GetValue( "preferences.Interaction.autoinspect") xsi.SetValue("preferences.scripting.cmdlog", False, "") xsi.SetValue("preferences.scripting.msglogverbose", False, "") xsi.SetValue("preferences.scripting.msglogrealtime", False, "") xsi.SetValue("preferences.Interaction.autoinspect", False, "") else: if self._buffer.get('silentMode', None): xsi.SetValue("preferences.scripting.cmdlog", self._buffer['silentMode']['cmdlog'], "") xsi.SetValue("preferences.scripting.msglogverbose", self._buffer['silentMode']['msglogverbose'], "") xsi.SetValue("preferences.scripting.msglogrealtime", self._buffer['silentMode']['msglogrealtime'], "") xsi.SetValue("preferences.Interaction.autoinspect", self._buffer['silentMode']['autoinspect'], "") del self._buffer['silentMode'] return True
def setPlatePath(self, path): """ TODO: This is currently only handling FileSequence paths defined by the cross3d.FileSequence class. It does not support static images or movies. """ fs = FileSequence(path) start = fs.start() end = fs.end() # Example: S:\\Deadpool\\Footage\\Sc000\\S0000.00\\Plates\\Sc000_S0000.00.[100..190;4].jpg fileName = '%s%s[%i..%i;%i].%s' % (fs.baseName(), fs.separator(), start, end, fs.padding(), fs.extension()) path = os.path.join(fs.basePath(), fileName) clip = xsi.Dictionary.GetObject('Clips.%s_Plate' % self.name(), False) if not clip: clip = xsi.SICreateImageClip2(path, '%s_Plate' % self.name())(0) else: clip.Source.FileName.Value = path # TODO: Do not get why this does not work! # clip.TimeControl.clipin = start # clip.TimeControl.clipout= end # clip.TimeControl.startoffset = start xsi.setValue('%s.timectrl.clipin' % clip.FullName, start) xsi.setValue('%s.timectrl.clipout' % clip.FullName, end) xsi.setValue('%s.timectrl.startoffset' % clip.FullName, start) xsi.SetValue("%s.rotoscope.imagename" % self.name(), clip.FullName, "") return False
def setSlateText(self, text=''): import cross3d application = cross3d.application version = application.version() if version > 9: camera = self._nativeCamera() xsi.SetValue(camera.FullName + '.camvis.camerainfotext', text) return True
def setSlateIsActive(self, state): import cross3d application = cross3d.application version = application.version() if version > 9: camera = self._nativeCamera() xsi.SetValue(camera.FullName + '.camvis.camerainfo', state) return True
def setResolutionPath(self, path, resolution=''): if self.isReferenced(): if not resolution: resolution = self.resolution() resolutions = self.resolutions() if resolution in resolutions: xsi.SetValue("%s.resolutions.res%i.file" % (self.name(), resolutions.index(resolution)), path) return True return False
def setRenderSize(self, size): """ \remarks set the render output size for the scene \param size <QSize> \return <bool> success """ from PyQt4.QtCore import QSize if isinstance(size, QSize): width = size.width() height = size.height() elif isinstance(size, list): if len(size) < 2: raise TypeError( 'You must provide a width and a height when setting the render size using a list' ) width = size[0] height = size[1] xsi.SetValue("Passes.RenderOptions.ImageWidth", width) xsi.SetValue("Passes.RenderOptions.ImageHeight", height) return True
def _setNativeProperty(self, key, nativeValue): """ \remarks implements the AbstractSceneWrapper._setNativeProperty method to set the value of the property defined by the inputed key \sa hasProperty, property, setProperty, AbstractScene._toNativeValue \param key <str> \param value <variant> (pre-converted to the application's native value) \retrun <bool> success """ xsi.SetValue('%s.%s' % (self._nativePointer.fullname, key), nativeValue) return True
def setViewOptions(self, viewOptions): for prop in viewOptions: if prop in [ 'Camera Visibility', 'Camera Display' ]: for param in viewOptions[prop]: if not param in ['hidlincol', 'wrfrmdpthcuecol']: try: self._nativePointer.Properties(prop).Parameters(param).Value = viewOptions[prop][param] except: print 'TRACEBACK: skipping param: {} {}...'.format(prop, param) print traceback.format_exc() xsi.SetValue('preferences.ViewCube.show', viewOptions.get('viewcubeshow'), xsi.GetValue('preferences.ViewCube.show')) return True
def setHeadLightIsActive(self, switch): xsi.SetValue(self.name() + '.camdisp.headlight', switch) return True
def __exit__(self, exc_type, exc_value, traceback): xsi.SetValue("preferences.General.undo", self._undo, "")
def setShowsFrame(self, switch): xsi.SetValue(self.name() + '.camvis.currenttime', switch) return True
def setShowsCustomParameters(self, switch): xsi.SetValue(self.name() + '.camvis.custominfo', switch) 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
def createFrustrumPlane(self, name='', imagePath='', offset=0.0, speed=1.0, distance=1.0, parent=None): """ Will create a 3D plane attached to the camera and matching the camera view frustum. Parent can be used when the plane should not be directly parented under the camera and constrained instead. """ from win32com.client import Dispatch xsiMath = Dispatch("XSI.Math") # Initializing things. fs = None # Figuring out if we have an image or a file fs. if FileSequence.isValidSequencePath(imagePath): fs = FileSequence(imagePath) name = name or fs.baseName() else: name = name or os.path.splitext(os.path.basename(imagePath))[0] # Conforming the name. Non supported Softimage character will become underscores. name = application.conformObjectName(name) anchor = xsi.ActiveSceneRoot.AddNull(name) if parent or self.isReferenced() else self._nativePointer # Creating the Plane. plane = xsi.CreatePrim("Grid", "MeshSurface", '{}_Plane'.format(name) if parent or self.isReferenced() else name, "") plane.Properties("Visibility").Parameters("selectability").Value = False # Parenting the plane to the anchor. anchor.AddChild(plane) # If parent is defined. if parent: parent.nativePointer().addChild(anchor) # If the anchor is not the camera we need to constrain the anchor to the camera. # This is mosty useful for cameras inside a reference model. if not anchor.isEqualTo(self._nativePointer): anchor.Kinematics.AddConstraint('Pose', self._nativePointer) # Setting dipslay options. display = plane.AddProperty("Display Property") parameters = ['staticsel', 'intsel', 'playbacksel', 'staticunselnear', 'intunselnear', 'staticunselfar', 'intunselfar', 'playbackunselfar'] for parameter in parameters: display.Parameters(parameter).Value = 9 # Setting the plane transform. transform = xsiMath.CreateTransform() transform.SetTranslation(xsiMath.CreateVector3(0, 0, -distance)) transform.SetRotationFromXYZAngles(xsiMath.CreateVector3(math.pi * 0.5, 0, math.pi)) plane.Kinematics.Local.Transform = transform # Setting the plane subdivs and size. for parameter in ['subdivu', 'subdivv', 'ulength', 'vlength']: plane.Parameters(parameter).Value = 1 # Creating UVs xsi.CreateProjection(plane, "siTxtPlanarXZ", "siTxtDefaultPlanarXZ", "", "imagePath_Projection") xsi.FreezeObj(plane) # Setting the scale expressions. expression = 'tan(%s.camera.fov * 0.5) * %s.kine.local.posz * 2' % (self.name(), plane.FullName) plane.sclx.AddExpression(expression) expression = '%s / %s.camera.aspect' % (expression, self.name()) plane.sclz.AddExpression(expression) # Locking transforms. for parameter in ['posx', 'posy', 'rotx', 'roty', 'rotz', 'sclx', 'scly', 'sclz']: parameter = plane.Parameters(parameter) parameter.Keyable = False parameter.ReadOnly = True # If a imagePath is provided we create a material. if not imagePath: return True # Getting or creating the clip. clip = self.setFrustrumPlaneImagePath(name, imagePath, offset, speed) # Getting or creating the material. header = 'Sources.Materials.DefaultLib' material = xsi.Dictionary.GetObject('%s.%s' % (header, name), False) if not material: preset = '$XSI_DSPRESETS\\Shaders\\Material\\Constant.Preset' material = xsi.Dictionary.GetObject(header).CreateMaterial(preset, 'Constant') material.Name = name xsi.SIApplyShaderToCnxPoint("Image", "%s.Constant.color" % material.FullName) xsi.SIConnectShaderToCnxPoint(clip.FullName, "%s.Image.tex" % material.FullName) # TODO: Ideally I would detect if the image has alpha. if os.path.splitext(imagePath)[1] in ['.png', '.tga', '.exr', '.tif', '.tiff']: xsi.SIConnectShaderToCnxPoint("%s.Image.out" % material.FullName, "%s.Constant.transparency" % material.FullName, False) xsi.SetValue("%s.Constant.usealphatrans" % material.FullName, True) xsi.SetValue("%s.Constant.inverttrans" % material.FullName, True) if material: xsi.AssignMaterial(','.join([material.FullName, plane.FullName])) # Returning. return True
def headlightIsActive(self, state): camera = self._nativeCamera() xsi.SetValue(camera.FullName + '.camdisp.headlight', state) return True
def importFBX(self, path, **kwargs): args = { "animation": True, "cameras": True, "lights": True, "envelopes": True, "forceNormEnvelope": False, "keepXSIEffectors": True, "skeletonsAsNulls": True, "frameRate": True, "scaleFactor": 1.0, "fillTimeline": True, 'convertUnit': None } units = { "mm": "Millimeters", "cm": "Centimeters", "dm": "Decimeters", "m": "Meters", "km": "Kilometers", "in": "Inches", "ft": "Feet", "yd": "Yards", "mi": "Miles" } args.update(kwargs) if args["convertUnit"] is not None and args[ "convertUnit"] not in units.keys(): raise ValueError("FBX invalid unit '%s'. Must be %s" % (args["convertUnit"], units.keys())) xsi.FBXImportAnimation(args["animation"]) xsi.FBXImportCameras(args["cameras"]) xsi.FBXImportLights(args["lights"]) xsi.FBXImportSetEnvelopes(args["envelopes"]) xsi.FBXImportForceNormEnvelope(args["forceNormEnvelope"]) xsi.FBXImportKeepXSIEffectors(args["keepXSIEffectors"]) xsi.FBXImportSkeletonsAsNulls(args["skeletonsAsNulls"]) xsi.FBXImportAutomaticUnit(args["convertUnit"] is None) if args["convertUnit"] is not None: xsi.FBXImportUnit(units[args["convertUnit"]]) xsi.FBXImport("options") xsi.SetValue("ImportFBXOptions.ImportFrameRate", args["frameRate"]) xsi.SetValue("ImportFBXOptions.ImportFillTimeline", args["fillTimeline"]) models = [ model.FullName for model in xsi.ActiveSceneRoot.FindChildren2( "*", xsiConstants.siModelType) ] xsi.FBXImport(path) for model in xsi.ActiveSceneRoot.FindChildren2( "*", xsiConstants.siModelType): if model.FullName not in models: from cross3d import SceneModel return SceneModel(self, model) return False
def __enter__(self): self._undo = xsi.GetValue("preferences.General.undo") xsi.SetValue("preferences.General.undo", 0, "")