def _isLightCamera(nodeObj): fn = OpenMaya.MFnDagNode(nodeObj) if fn.object().hasFn( OpenMaya.MFn.kCamera) and fn.parentCount() == 1: # Check if the parent transform has another child that is a light source fn = OpenMaya.MFnDagNode(fn.parent(0)) if fn.object().hasFn( OpenMaya.MFn.kTransform) and fn.childCount() == 2: fnChild0 = OpenMaya.MFnDependencyNode(fn.child(0)) fnChild1 = OpenMaya.MFnDependencyNode(fn.child(1)) return cmds.getClassification(fnChild0.typeName, satisfies='light') or \ cmds.getClassification(fnChild1.typeName, satisfies='light') return False
def utilityCreateMaterial(name, type, slots={}, path=""): switcher = { None: "lambert", "lambert": "lambert", "phong": "phong", "pbr": "StingrayPBS" } loader = { "lambert": utilityAssignGenericSlots, "phong": utilityAssignGenericSlots, "StingrayPBS": utilityAssignStingrayPBSSlots } if not type in switcher: type = None mayaShaderType = switcher[type] if cmds.getClassification(mayaShaderType) == [u'']: mayaShaderType = switcher[None] materialInstance = cmds.shadingNode(mayaShaderType, asShader=True, name=name) loader[mayaShaderType](materialInstance, slots, path) return (materialInstance)
def nameChangedCB(self, node, prevName, client): ''' Callback when a node is renamed ''' if prevName == "" or not prevName or prevName.startswith("_"): return handle = MObjectHandle( node ) if not handle.isValid(): return mobject = handle.object() nodeFn = MFnDependencyNode ( mobject ) if nodeFn.hasUniqueName(): nodeName = nodeFn.name() if cmds.getClassification(cmds.nodeType(nodeName), satisfies="shader"): if cmds.nodeType(nodeName) == "displacementShader": items = self.displacementList.findItems(prevName, QtCore.Qt.MatchExactly) for item in items: item.setText(nodeName) # renaming shaders in caches for cache in self.ABCViewerNode.values(): cache.renameDisplacement(prevName, nodeName) self.checkShaders() else: items = self.shadersList.findItems(prevName, QtCore.Qt.MatchExactly) for item in items: item.setText(nodeName) if cmds.nodeType(nodeName) == "shadingEngine": # renaming shaders in caches for cache in self.ABCViewerNode.values(): cache.renameShader(prevName, nodeName) self.checkShaders()
def fileComboChanged(self, index): """The combo box has been changed""" if self.fileNodesCombo.currentText() == 'RGB': # restore the color button and the suspended_color self.colorBtn.setEnabled(True) if self.suspended_color: self.colorBtn.setPalette(self.suspended_color) else: # reset the color button self.updatePalette(self.default_color) self.colorBtn.setEnabled(False) self.controller.mainEditor.propertyChanged( dict(propname=self.paramName, default=False, value=self.fileNodesCombo.currentText())) fileNode = cmds.ls("%s" % self.fileNodesCombo.currentText(), textures=True)[0] for k in self.controller.mainEditor.ABCViewerNode.keys(): ports_in_use = 0 for c in cmds.listConnections("%s" % k): if cmds.getClassification( cmds.nodeType(c), satisfies="shader") or cmds.nodeType(c) == 'file': ports_in_use += 1 found = False for each in range(0, ports_in_use): if cmds.isConnected("%s.message" % fileNode, "%s.shaders[%i]" % (k, each)): found = True if not found: cmds.connectAttr("%s.message" % fileNode, "%s.shaders[%i]" % (k, ports_in_use + 1))
def _findCustomCreateCommand(nodeType): """ Locate a custom command to create this nodeType, based on registered custom classification categories. Return None if no match. """ use2012 = not hasattr(cmds, 'callbacks') if use2012: # use the pre-2013 method of finding custom node create scripts return _findCustomCreateCommand2012(nodeType) # get the list of classifications which have custom handlers customClassifications = cmds.callbacks(hook='renderNodeClassification', executeCallbacks=True) if not customClassifications: return None for topclassif in customClassifications: if cmds.getClassification(nodeType, sat=topclassif): # this is a type with a custom handler postCmd = '' customCallbacks = cmds.callbacks(postCmd, nodeType, hook='createRenderNodeCommand', executeCallbacks=True) if customCallbacks and len(customCallbacks): # there should be only one callback, which must be a MEL fragment return customCallbacks[0]
def execute(self, command): from maya import cmds parts = command.split() if len(parts) > 2: raise Exception( 'Input must be a node type and optional name:\n\n' ' multiplyDivide\n' ' multiplyDivide myMultiplyDivide\n' ) node_type = parts[0] node = None name = None if len(parts) == 2: name = parts[1] # Handle dg nodes shading_classifications = ( 'Utility', 'Shader', 'Texture', 'Rendering', 'PostProcess', 'Light' ) for cls in shading_classifications: if cmds.getClassification(node_type, satisfies=cls.lower()): node = cmds.shadingNode(node_type, **{'as' + cls: True}) # Handle dag nodes if not node: node = cmds.createNode(node_type) if name: cmds.rename(node, name)
def execute(self, command): from maya import cmds parts = command.split() if len(parts) > 2: raise Exception('Input must be a node type and optional name:\n\n' ' multiplyDivide\n' ' multiplyDivide myMultiplyDivide\n') node_type = parts[0] node = None name = None if len(parts) == 2: name = parts[1] # Handle dg nodes shading_classifications = ('Utility', 'Shader', 'Texture', 'Rendering', 'PostProcess', 'Light') for cls in shading_classifications: if cmds.getClassification(node_type, satisfies=cls.lower()): node = cmds.shadingNode(node_type, **{'as' + cls: True}) # Handle dag nodes if not node: node = cmds.createNode(node_type) if name: cmds.rename(node, name)
def _setup_data(self): """Check node classification, filter, save config file and return.""" classlist = ['utility', 'shader', 'transform', 'drawdb', 'general'] ignore = ['nexManip', 'xgmPatch'] nodes = [n for n in pm.allNodeTypes() for c in classlist if cmds.getClassification(n, satisfies=c) and cmds.getClassification(n) if not n in ignore] nodes = list(set(nodes + [n for n in pm.allNodeTypes() if (n.startswith('n_') or n == 'pointOnCurveInfo' or n == 'pointOnSurfaceInfo' or n == 'pointMatrixMult')])) data = dict() self._get_data(nodes, data) self._abbs = self._add_abbreviation(data) self._save_config_file(data) return data
def _findStandardCreateCommand(nodeType): """ Locate a standard create command based on classification cateogries """ for name, classif, asFlag, catFlag in mayaNodeCategories(): if cmds.getClassification(nodeType, sat=classif): # this type matches the current category, create as a standard maya render node return 'createRenderNodeCB %s "%s" "%s" ""' % (asFlag, catFlag, nodeType)
def getSGs(self, src): SGs = [] for s in src: connectedSGs = m.listConnections(s, d=True, s=False, type='shadingEngine', exactType=True) if connectedSGs: SGs.extend(connectedSGs) nextLevel = [] for c in m.listConnections(s, d=True, s=False): if (m.getClassification(m.nodeType(c), satisfies='shader') or m.getClassification(m.nodeType(c), satisfies='texture') or m.getClassification(m.nodeType(c), satisfies='utility')): nextLevel.append(c) for nl in nextLevel: SGs.extend(self.getSGs([nl])) return SGs
def checkIfCurrentSelectedIsATexture(selection): if (mc.getClassification(mc.objectType(selection), satisfies="texture") ) is True or len(selection) != 1: mc.confirmDialog( message= 'What you select is not a texture or you have selected multiple texture' ) else: return selection
def _get_connections(self, item): """Return connections from given pynode object""" connections = list() for c in item.listConnections(c=True, s=False, scn=True, plugs=True): if cmds.getClassification(cmds.nodeType(c[-1].name()))[0]: connections.append(list(c)) # end if get valid nodes # end for iterate connections return connections
def mrCreateNodeCB(postCmd, nodeType): """ If the given node is Mentalray, return a MEL command which will create an instance of the supplied node type. Return None if the given node is not handled by Mayatomr. \param[in] postCmd - MEL code to be executed after creation \param[in] nodeType - The type of the node to be created \return MEL command which creates the given node, or None """ if cmds.pluginInfo('Mayatomr', q=True, loaded=True) and\ cmds.getClassification(nodeType, sat='rendernode/mentalray'): for title, uibasename, staticclassif, runtimeclassif in mrNodeCategories(): if cmds.getClassification(nodeType, sat=staticclassif): # this type matches the current category return 'mrCreateCustomNode "%s" "%s" "%s"' % (runtimeclassif, postCmd, nodeType)
def getShader(category): ''' Use this method to get selected shader from cg app After get the current shader, fill shaderData dict with necessary information and returns it. Args: category (string): category of this shader Returns: shaderData (dic): info from shader or False msg (string): error message ''' ignoreDefaults = [ 'lambert1', 'particleCloud1', 'shaderGlow1', 'defaultColorMgtGlobals' ] app = 'maya' shaderData = { 'name': 'default', 'maps': [], 'app': app, 'node': 'defaultNode', 'shaderType': 'N/A' } selection = cmds.ls(sl=True) if len(selection) == 0: return False, 'Nothing Selected!' elif len(selection) > 1: return False, 'Multiple objects selected!' selType = cmds.nodeType(selection[0]) if selType == 'transform': shape = cmds.ls(dag=1, o=1, s=1, sl=1) sg = cmds.listConnections(shape, type='shadingEngine') shaders = cmds.ls(cmds.listConnections(sg), materials=1) if len(shaders) == 0: return False, 'No shader found on selected object' else: isShader = cmds.getClassification(selType, satisfies="shader") shaders = [selection[0]] if not isShader: return False, 'No shader found for type ({})'.format(selType) if shaders[0] in ignoreDefaults: msg = 'Shader found is maya default ({})'.format(shaders[0]) return False, msg shaderData['name'] = shaders[0] shaderData['node'] = shaders[0] shaderData['maps'] = ['maps1', 'maps2'] shaderData['shaderType'] = cmds.nodeType(shaders[0]) shaderData['sourceFile'] = cmds.file(query=True, sceneName=True, shortName=True) shaderData['category'] = category.name return shaderData, 1
def getAllRegisteredSurfaceShader(): registeredSurfaceShaders = [] registeredNodeTypes = cmds.ls(nodeTypes = 1) for registeredNodeType in registeredNodeTypes: classifications = cmds.getClassification(registeredNodeType) for classification in classifications: if 'shader/surface' in classification: registeredSurfaceShaders.append(registeredNodeType) registeredSurfaceShaders = tuple(registeredSurfaceShaders) return registeredSurfaceShaders
def _setup_data(self): """Check node classification, filter, save config file and return""" classlist = ['utility', 'shader', 'transform', 'drawdb', 'general'] nodes = [n for n in pm.allNodeTypes() for c in classlist if cmds.getClassification(n, satisfies=c) if n != 'nexManip'] data = dict() self._get_data(nodes, data) self._add_abbreviation(data) self._save_config_file(data) return data
def createRenderNodeCallback(postCommand, nodeType): #logger.debug("createRenderNodeCallback called!") for c in mc.getClassification(nodeType): if 'rendernode/appleseed' in c.lower(): buildNodeCmd = ( "import appleseedMaya.hypershadeCallbacks;" "appleseedMaya.hypershadeCallbacks.createAsRenderNode" "(nodeType=\\\"{0}\\\", postCommand='{1}')").format(nodeType, postCommand) return "string $cmd = \"{0}\"; python($cmd);".format(buildNodeCmd)
def filterListByType(self, nodeType): if len(self.itemList) > 0: for item in self.itemList: classification = [] classification.append(item.nodeType) classification.extend(cmds.getClassification(item.nodeType)) clsStr = '|'.join(classification) if nodeType in clsStr: cmds.layout(item.listItemLayoutId, edit = 1, manage = 1) else: cmds.layout(item.listItemLayoutId, edit = 1, manage = 0)
def _setup_data(self): """Check node classification, filter, save config file and return""" classlist = ['utility', 'shader', 'transform', 'drawdb', 'general'] nodes = [ n for n in pm.allNodeTypes() for c in classlist if cmds.getClassification(n, satisfies=c) if n != 'nexManip' ] data = dict() self._get_data(nodes, data) self._add_abbreviation(data) self._save_config_file(data) return data
def classification_SG(self, sgNode): shaders = mc.listConnections(sgNode, d = False, s = True) if shaders == None: return for oneShader in shaders: typeNode = mc.nodeType(oneShader) if mc.getClassification(typeNode, satisfies = 'shader/surface'): if typeNode in self.sameSGTypeDict: self.sameSGTypeDict[typeNode].append(sgNode) else: self.sameSGTypeDict[typeNode] = [sgNode]
def getNodeClassType(nodeType): #get type of node #nodeType = cmds.nodeType(node) nodeClass = '' #list of shading nodes nodeClasses = ['utility', 'shader', 'texture'] #find type of class for c in nodeClasses: if cmds.getClassification(nodeType, satisfies=c): nodeClass = c return nodeClass
def createSurfaceNodeCommand (type): classification = mc.getClassification (type) for c in classification: mat = mc.shadingNode (type, asShader = True) shadingGroup = mc.sets (renderable = True, noSurfaceShader = True, empty = True, name = mat + "SG") mc.connectAttr (mat + ".outColor", shadingGroup + ".surfaceShader") return ""
def compositeTexture(node=None, **kwargs): if not node: return None nodeT = cmds.nodeType(node) if cmds.getClassification(nodeT, satisfies='utility') or cmds.getClassification( nodeT, satisfies='texture'): if len(cmds.listConnections(node, s=False, d=True)) < 2: return None else: xRes = kwargs.get('xRes', 1024) yRes = kwargs.get('yRes', 1024) imageName = kwargs.get('imageName', node.replace(':', '-')) imageFormat = 'tga' filePath = kwargs.get('filePath', 'images') startFrame = kwargs.get('startFrame', int(cmds.currentTime(q=True))) endFrame = kwargs.get('endFrame', startFrame) by = kwargs.get('by', 1) padding = kwargs.get('padding', 4) loadInImageViewer = 1 filePath = 'images' if os.path.isabs(filePath) else filePath fullPath = os.path.join(cmds.workspace(q=True, rootDirectory=True), filePath) if not os.path.exists(fullPath): os.makedirs(fullPath) #composite 512 512 "aaa" "tga" "images/compositedTexture" 1.000000 1.000000 1 4 1 oriSel = cmds.ls(sl=True) cmds.select(node, r=True) mel.eval('composite %d %d "%s" "%s" "%s" %d %f %d %d %d' % (xRes, yRes, imageName, imageFormat, filePath, startFrame, endFrame, by, padding, loadInImageViewer)) fullImagePath = (os.path.join( fullPath, imageName) + '.' + str(startFrame).zfill(padding) + '.' + imageFormat)\ .replace('\\', '/') if oriSel: cmds.select(oriSel, r=True) return fullImagePath
def _isLightNode(nodeObj): fn = OpenMaya.MFnDagNode(nodeObj) if fn.object().hasFn(OpenMaya.MFn.kTransform): childCount = fn.childCount() for i in range(childCount): if not _isLightNode(fn.child(i)): # At least one child is not a light shape return False # If we got here then all children were light shapes return childCount > 0 else: return cmds.getClassification(fn.typeName, satisfies='light')
def breakConnections(self): """ Break shader connections to the alembicHolder node """ for connections in pm.listConnections(self.data['shapeNode'], plugs=True, connections=True): # if connections[-1].nodeType() in ['shadingEngine', 'displacementShader']: if cmds.getClassification(connections[-1].nodeType(), satisfies="shader"): pm.disconnectAttr(str(connections[-1]), str(connections[0])) self.logger.info("Break Connection : %s > %s" % (str(connections[-1]), str(connections[0])))
def newNodeCB(self, newNode, data): """Callback when creating a new node""" mobject = MObjectHandle(newNode).object() nodeFn = MFnDependencyNode(mobject) if nodeFn.hasUniqueName(): nodeName = nodeFn.name() if cmds.getClassification(cmds.nodeType(nodeName), satisfies="shader"): # add shader to scroller self.shaderEditor.addShader(nodeName) elif nodeFn.typeName() == 'renderLayer': self.renderLayer.addItems([nodeName])
def createRenderNodeCommandCallback (postCommand, type): if mc.getClassification (type, satisfies = 'rendernode/niepce/surface'): # Type of current node is registered in surface classification # # Return a command as mel command string # - Creating shading group node # - Connect shading node's outColor to shading group's surfaceShader python_cmd_str = ("import hypershade_callbacks;" "hypershade_callbacks.createSurfaceNodeCommand (\\\"{0}\\\")").format (type) return "string $cmd = \"{0}\"; python ($cmd);".format (python_cmd_str) else: # om.MGlobal.displayError ("Faild to create render node.") return ""
def collectNodes(): global data nodes = cmds.ls(nodeTypes=True) classifications = [] for n in nodes: for cl in cmds.getClassification(n)[0].split(':'): for s in shaders.keys(): if cl.startswith(s): data[n] = cl if cl not in classifications: classifications.append(cl) for cl in classifications: #print( cl ) pass
def _findCustomCreateCommand2012(nodeType): """ Implementation of _findCustomCreateCommand for 2012 """ for i, classifCB in enumerate(pluginNodeClassificationCallbacks): topclassif = classifCB() if cmds.getClassification(nodeType, sat=topclassif): # this is a type with a custom handler, call the corresponding callback # to get the MEL script which will actually create the node createCB = pluginNodeCreationCallbacks[i] postCmd = '' customCallback = createCB(postCmd, nodeType) # the result must be a MEL fragment return customCallback
def aiSwatchLabel(nodeName) : type = cmds.nodeType(nodeName) classificationsList = cmds.getClassification(type) for classification in classificationsList : allClassList = classification.split(':') for allClass in allClassList : classList = allClass.split('/') if 'swatch' == classList[0] : continue else : if classList : if 'shader' != classList[-1] : classList = filter(lambda x:x!='shader', classList) return "\n".join(map(lambda x:x.capitalize(), classList)) else : return "Sample"
def aiSwatchLabel(nodeName): type = cmds.nodeType(nodeName) classificationsList = cmds.getClassification(type) for classification in classificationsList: allClassList = classification.split(':') for allClass in allClassList: classList = allClass.split('/') if 'swatch' == classList[0]: continue else: if classList: if 'shader' != classList[-1]: classList = filter(lambda x: x != 'shader', classList) return "\n".join(map(lambda x: x.capitalize(), classList)) else: return "Sample"
def setDisplayFlag(cls, show): nodes = cmds.allNodeTypes() types = [] for n in nodes: c = cmds.getClassification(n)[0] do = True for cl in cls: if cl not in c: do = False break if do: types.append(n) for t in types: print(t) tag = cmds.objectType(tagFromType=t) cmds.setNodeTypeFlag(tag, display=show)
def createAsRenderNode(nodeType=None, postCommand=None): classification = mc.getClassification(nodeType) logger.debug( "CreateAsRenderNode called: nodeType = {0}, class = {1}, pcmd = {2}".format( nodeType, classification, postCommand ) ) for cl in classification: if "rendernode/appleseed/surface" in cl.lower(): mat = mc.shadingNode(nodeType, asShader=True) shadingGroup = mc.sets( renderable=True, noSurfaceShader=True, empty=True, name=mat + "SG" ) mc.connectAttr(mat + ".outColor", shadingGroup + ".surfaceShader") if nodeType == 'asGlass': mc.setAttr(shadingGroup + ".asDoubleSided", 1) logger.debug("Created shading node {0} asShader".format(mat)) elif "rendernode/appleseed/texture/2d" in cl.lower(): mat = mc.shadingNode(nodeType, asTexture=True) placeTex = mc.shadingNode("place2dTexture", asUtility=True) mc.connectAttr(placeTex + ".outUV", mat + ".uv") mc.connectAttr(placeTex + ".outUvFilterSize", mat + ".uvFilterSize") logger.debug("Created shading node {0} asTexture2D".format(mat)) elif "rendernode/appleseed/texture/3d" in cl.lower(): mat = mc.shadingNode(nodeType, asTexture=True) placeTex = mc.shadingNode("place3dTexture", asUtility=True) mc.connectAttr(placeTex + ".wim[0]", mat + ".placementMatrix") logger.debug("Created shading node {0} asTexture3D".format(mat)) else: mat = mc.shadingNode(nodeType, asUtility=True) logger.debug("Created shading node {0} asUtility".format(mat)) if postCommand is not None: postCommand = postCommand.replace("%node", mat) postCommand = postCommand.replace("%type", '\"\"') mel.eval(postCommand) return ""
def getConnectedShaders(self): """ Get the shaders / displacements connected the alembicHolder node Returns: list: The shaders and displacements connected to the alembicHolder node """ self.logger.debug("Connected Shaders") connected = [] for connections in pm.listConnections(self.data['shapeNode'], plugs=True, connections=True): if cmds.getClassification(connections[-1].nodeType(), satisfies="shader"): self.logger.debug("Connected shader : %s" % connections[-1].node()) connected.append(connections[-1].node()) return connected
def newNodeCB(self, newNode, data ): ''' Callback when creating a new node ''' mobject = MObjectHandle( newNode ).object() nodeFn = MFnDependencyNode ( mobject ) if nodeFn.hasUniqueName(): nodeName = nodeFn.name() if cmds.getClassification(cmds.nodeType(nodeName), satisfies="shader"): if cmds.nodeType(nodeName) == "displacementShader": icon = QtGui.QIcon() icon.addFile(os.path.join(d, "../../icons/sg.xpm"), QtCore.QSize(25,25)) item = QtGui.QListWidgetItem(nodeName) item.setIcon(icon) self.displacementList.addItem(item) else: icon = QtGui.QIcon() icon.addFile(os.path.join(d, "../../icons/sg.xpm"), QtCore.QSize(25,25)) item = QtGui.QListWidgetItem(nodeName) item.setIcon(icon) self.shadersList.addItem(item)
def get_node_classification(node_type): """ Return the classification string associated with a registered node in maya. >>> get_node_classification('transform') u'drawdb/geometry/transform' :param str node_type: The type of the node to inspect. :return: The node classification string :rtype: str """ classifications = cmds.getClassification(node_type) # Get the node identification tags if len(classifications) != 1: # This should not happen, we don't know why getClassification return a list. raise Exception("Unexpected classification return value for %r" % node_type) classification = classifications[0] return classification
def get_unused_shading_engines(): u"""未使用のShadingEngineのリストを返す :return: 未使用のShadingEngineのリスト :rtype: list of unicode """ shading_engines = cmds.ls(type="shadingEngine") unused_shading_engines = [] for s in shading_engines: if s in _DEFAULT_SHADING_ENGINES: continue unused = True for c in cmds.listConnections(s): node_type = cmds.nodeType(c) if "shader" in cmds.getClassification(node_type)[0]: unused = False break if unused: unused_shading_engines.append(s) return unused_shading_engines
def create_node(type_, name=None, **attributes): kwargs = {} if name: kwargs['name'] = name node_name = None for shading_class, shading_kwargs in SHADING_CLASSIFICATIONS.iteritems(): if cmds.getClassification(type_, satisfies=shading_class): node_name = cmds.shadingNode(type_, **shading_kwargs) if name: node_name = cmds.rename(node_name, name) if cmds.objectType(node_name, isType='transform'): node_name = cmds.listRelatives(node_name, shapes=True)[0] node_name = cmds.rename(node_name, name + 'Shape') if not node_name: node_name = cmds.createNode(type_, **kwargs) node = pmc.PyNode(node_name) set_attributes(node, **attributes) return node
def node_handler(self, input_str): input_buffer = input_str.split() if len(input_buffer) > 1: node_type, node_name = input_buffer if "#" in node_name: raise NameError( "# symbol found in node name. " "This will completely f**k your maya scene. \n" "Try again without the #.") else: node_type = input_buffer[0] node_name = None #Wrap node creation and naming in a single chunk prev_chunk = cmds.undoInfo(q=True, chunkName=True) cmds.undoInfo(openChunk=True) try: if cmds.getClassification(node_type, satisfies="utility"): node = cmds.shadingNode(node_type, asUtility=True) elif cmds.getClassification(node_type, satisfies="shader"): node = cmds.shadingNode(node_type, asShader=True) elif cmds.getClassification(node_type, satisfies="texture"): node = cmds.shadingNode(node_type, asTexture=True) elif cmds.getClassification(node_type, satisfies="rendering"): node = cmds.shadingNode(node_type, asRendering=True) elif cmds.getClassification(node_type, satisfies="postprocess"): node = cmds.shadingNode(node_type, asPostProcess=True) elif cmds.getClassification(node_type, satisfies="light"): node = cmds.shadingNode(node_type, asLight=True) else: node = cmds.createNode(node_type) if node_name: cmds.rename(node, node_name.replace('\"', '')) cmds.undoInfo(closeChunk=True) except: cmds.undoInfo(closeChunk=True) if not cmds.undoInfo(q=True, chunkName=True) == prev_chunk: cmds.undo() raise
def __init__(self,name): self.name=name self.type= cmds.nodeType(name) self.classification = cmds.getClassification(self.type) self.attributes=dict() self.connections=dict()