If an attribute in maya is being overridden by a render setup layer, is there a way to get the base, non-overridden value of that attribute without switching to the default render layer? So, for example, if the start frame in the render globals is set to 0, but my current render setup layer is applying an absolute override setting it to 100, is there a way to access the original value without changing the current layer in maya?
Ultimately I want to be able to query the value of an attribute in a layer that is not the current layer (for the purposes of sending tasks to a render farm). I don't want to change the active layer in maya as that can be slow with a lot of layers, and I want to avoid making changes to the scene if possible. I've been using the render setup python api to query overrides, but I've not yet found a way to find the original value if the currently active layer is overriding the value I'm trying to query in a different layer.
This is the code I'm using to get the value currently:
def getAttrForSetupLayer(node, attr, setupLayer):
import maya.app.renderSetup.model.renderSetup as renderSetup
import maya.cmds as cmds
renderSetupHandler = renderSetup.instance()
# get the current value of the attribute
result = cmds.getAttr("{0}.{1}".format(node, attr)) # apply overrides if cmds.objExists(setupLayer) and cmds.nodeType(setupLayer) == "renderSetupLayer": try: currentLayerObject = renderSetupHandler.getRenderLayer(setupLayer) except Exception as err: log.error("could not get current layer object for {0}: {1}".format(setupLayer, err)) currentLayerObject = None if currentLayerObject is not None: layerCollections = currentLayerObject.getCollections() for coll in layerCollections: collectionOverrides = coll.getOverrides() for override in collectionOverrides: # not all override types have targetNodeName, so catch exceptions try: targetNode = override.targetNodeName() targetAttr = override.attributeName() except: continue if targetNode == node and targetAttr == attr: if override.typeName() == "relUniqueOverride": mult = override.getMultiply() offset = override.getOffset() result = result*mult+offset else: try: result = override.getAttrValue() except Exception as err: log.error("could not get override for {0}.{1} on layer {2}: {3}".format(node, attr, setupLayer, err))
However, this only works if there is no override on the attribute in the current layer. If the override in the current layer is a relative attribute, I can work back and get the original value, but if it's absolute I can't find a way to do it, and having to 'work back' doesn't seem like an ideal solution anyway.
I'm still learning the ropes of the render setup api - I hope someone can point me in the right direction!
Thanks!
Solved! Go to Solution.
If an attribute in maya is being overridden by a render setup layer, is there a way to get the base, non-overridden value of that attribute without switching to the default render layer? So, for example, if the start frame in the render globals is set to 0, but my current render setup layer is applying an absolute override setting it to 100, is there a way to access the original value without changing the current layer in maya?
Ultimately I want to be able to query the value of an attribute in a layer that is not the current layer (for the purposes of sending tasks to a render farm). I don't want to change the active layer in maya as that can be slow with a lot of layers, and I want to avoid making changes to the scene if possible. I've been using the render setup python api to query overrides, but I've not yet found a way to find the original value if the currently active layer is overriding the value I'm trying to query in a different layer.
This is the code I'm using to get the value currently:
def getAttrForSetupLayer(node, attr, setupLayer):
import maya.app.renderSetup.model.renderSetup as renderSetup
import maya.cmds as cmds
renderSetupHandler = renderSetup.instance()
# get the current value of the attribute
result = cmds.getAttr("{0}.{1}".format(node, attr)) # apply overrides if cmds.objExists(setupLayer) and cmds.nodeType(setupLayer) == "renderSetupLayer": try: currentLayerObject = renderSetupHandler.getRenderLayer(setupLayer) except Exception as err: log.error("could not get current layer object for {0}: {1}".format(setupLayer, err)) currentLayerObject = None if currentLayerObject is not None: layerCollections = currentLayerObject.getCollections() for coll in layerCollections: collectionOverrides = coll.getOverrides() for override in collectionOverrides: # not all override types have targetNodeName, so catch exceptions try: targetNode = override.targetNodeName() targetAttr = override.attributeName() except: continue if targetNode == node and targetAttr == attr: if override.typeName() == "relUniqueOverride": mult = override.getMultiply() offset = override.getOffset() result = result*mult+offset else: try: result = override.getAttrValue() except Exception as err: log.error("could not get override for {0}.{1} on layer {2}: {3}".format(node, attr, setupLayer, err))
However, this only works if there is no override on the attribute in the current layer. If the override in the current layer is a relative attribute, I can work back and get the original value, but if it's absolute I can't find a way to do it, and having to 'work back' doesn't seem like an ideal solution anyway.
I'm still learning the ropes of the render setup api - I hope someone can point me in the right direction!
Thanks!
Solved! Go to Solution.
Solved by cheng_xi_li. Go to Solution.
Hi,
You could find the node connected to the attrValue of the override node.
There is an original attribute stores original value in that node.
e.g.
import maya.app.renderSetup.model.collection as collection import maya.app.renderSetup.model.renderLayer as renderLayer import maya.app.renderSetup.model.renderSetup as renderSetup import maya.cmds as cmds import maya.api.OpenMaya as om rs = renderSetup.instance() layers = rs.getRenderLayers() for layer in layers: collections = layer.getCollections() for collection in collections: name = collection.name() overrides = collection.getOverrides() for override in overrides: obj = override.thisMObject() fn = om.MFnDependencyNode(obj) plug = fn.findPlug('attrValue', True) overridden = override.getOverridden() mobj = overridden[0][0] pname = overridden[0][1] mfn = om.MFnDependencyNode(mobj) connectedToPlugs = plug.connectedTo(False,True) for c in connectedToPlugs: node = c.node() fnAttr = om.MFnDependencyNode(node) originalPlug = fnAttr.findPlug('original', True) valuePlug = fnAttr.findPlug('value', True) print mfn.name()+"."+pname,'original',originalPlug.asDouble(),'new',valuePlug.asDouble()
Result
pSphere1.translateX original 1.0 new 3.0
Hope it helps.
Yours,
Li
Hi,
You could find the node connected to the attrValue of the override node.
There is an original attribute stores original value in that node.
e.g.
import maya.app.renderSetup.model.collection as collection import maya.app.renderSetup.model.renderLayer as renderLayer import maya.app.renderSetup.model.renderSetup as renderSetup import maya.cmds as cmds import maya.api.OpenMaya as om rs = renderSetup.instance() layers = rs.getRenderLayers() for layer in layers: collections = layer.getCollections() for collection in collections: name = collection.name() overrides = collection.getOverrides() for override in overrides: obj = override.thisMObject() fn = om.MFnDependencyNode(obj) plug = fn.findPlug('attrValue', True) overridden = override.getOverridden() mobj = overridden[0][0] pname = overridden[0][1] mfn = om.MFnDependencyNode(mobj) connectedToPlugs = plug.connectedTo(False,True) for c in connectedToPlugs: node = c.node() fnAttr = om.MFnDependencyNode(node) originalPlug = fnAttr.findPlug('original', True) valuePlug = fnAttr.findPlug('value', True) print mfn.name()+"."+pname,'original',originalPlug.asDouble(),'new',valuePlug.asDouble()
Result
pSphere1.translateX original 1.0 new 3.0
Hope it helps.
Yours,
Li
That works great for absolute overrides, thanks! It doesn't work for relative overrides though (fails finding the attrValue plug) - what plug would I need to query in this case?
That works great for absolute overrides, thanks! It doesn't work for relative overrides though (fails finding the attrValue plug) - what plug would I need to query in this case?
There also seem to be other situations where this doesn't work, for instance with an absolute override on defaultRenderGlobals.endFrame it fails on this line: originalPlug = fnAttr.findPlug('original', True)
There also seem to be other situations where this doesn't work, for instance with an absolute override on defaultRenderGlobals.endFrame it fails on this line: originalPlug = fnAttr.findPlug('original', True)
Hi,
Relative override nodes and apply nodes are having different attributes, you'll need to use them instead.
There is a unitConversion node between endFrame override node and apply override node. So, we'll need to use MItDependencyGraph to get the apply override node here. I did some hack here by checking apiType. Because renderSetup is a plugin, so it should have kPluginDependNode apiType. Once we find it, we could get values from it.
import maya.app.renderSetup.model.collection as collection import maya.app.renderSetup.model.renderLayer as renderLayer import maya.app.renderSetup.model.renderSetup as renderSetup import maya.cmds as cmds import maya.api.OpenMaya as om rs = renderSetup.instance() layers = rs.getRenderLayers() def getOriginalValue(typeName, overridden, connectedToPlugs, isRel): mobj = overridden[0][0] pname = overridden[0][1] mfn = om.MFnDependencyNode(mobj) for c in connectedToPlugs: node = c.node() #There is a time conversion between overridden node and apply override node. We'll use MItDependencyGraph to find it. I assume there are only no custom plugins between them. if node.apiTypeStr != 'kPluginDependNode': dgIt = om.MItDependencyGraph(mobj, om.MFn.kPluginDependNode, om.MItDependencyGraph.kUpstream, om.MItDependencyGraph.kBreadthFirst, om.MItDependencyGraph.kNodeLevel) node = dgIt.currentNode() fnAttr = om.MFnDependencyNode(node) originalPlug = fnAttr.findPlug('original', True) originalValue = originalPlug.asDouble() newValue = 0.0 if not isRel: valuePlug = fnAttr.findPlug('value', True) newValue = valuePlug.asDouble() else: multiplyPlug = fnAttr.findPlug('multiply', True) offsetPlug = fnAttr.findPlug('offset', True) newValue = originalValue * multiplyPlug.asDouble() + offsetPlug.asDouble() print typeName,mfn.name()+"."+pname,'original',originalValue,'new',newValue for layer in layers: collections = layer.getCollections() for collection in collections: name = collection.name() overrides = collection.getOverrides() for override in overrides: obj = override.thisMObject() fn = om.MFnDependencyNode(obj) typeName = fn.typeName overridden = override.getOverridden() targetPlug = 'attrValue' isRel = False if typeName[0:3] == 'rel': targetPlug = 'offset' isRel = True plug = fn.findPlug(targetPlug, True) connectedToPlugs = plug.connectedTo(False,True) getOriginalValue(typeName, overridden, connectedToPlugs, isRel)
Result:
absUniqueOverride defaultRenderGlobals.endFrame original 100.0 new 200.0 relOverride pSphere1.translateX original 4.0 new 6.0
Hope it helps.
Yours,
Li
Hi,
Relative override nodes and apply nodes are having different attributes, you'll need to use them instead.
There is a unitConversion node between endFrame override node and apply override node. So, we'll need to use MItDependencyGraph to get the apply override node here. I did some hack here by checking apiType. Because renderSetup is a plugin, so it should have kPluginDependNode apiType. Once we find it, we could get values from it.
import maya.app.renderSetup.model.collection as collection import maya.app.renderSetup.model.renderLayer as renderLayer import maya.app.renderSetup.model.renderSetup as renderSetup import maya.cmds as cmds import maya.api.OpenMaya as om rs = renderSetup.instance() layers = rs.getRenderLayers() def getOriginalValue(typeName, overridden, connectedToPlugs, isRel): mobj = overridden[0][0] pname = overridden[0][1] mfn = om.MFnDependencyNode(mobj) for c in connectedToPlugs: node = c.node() #There is a time conversion between overridden node and apply override node. We'll use MItDependencyGraph to find it. I assume there are only no custom plugins between them. if node.apiTypeStr != 'kPluginDependNode': dgIt = om.MItDependencyGraph(mobj, om.MFn.kPluginDependNode, om.MItDependencyGraph.kUpstream, om.MItDependencyGraph.kBreadthFirst, om.MItDependencyGraph.kNodeLevel) node = dgIt.currentNode() fnAttr = om.MFnDependencyNode(node) originalPlug = fnAttr.findPlug('original', True) originalValue = originalPlug.asDouble() newValue = 0.0 if not isRel: valuePlug = fnAttr.findPlug('value', True) newValue = valuePlug.asDouble() else: multiplyPlug = fnAttr.findPlug('multiply', True) offsetPlug = fnAttr.findPlug('offset', True) newValue = originalValue * multiplyPlug.asDouble() + offsetPlug.asDouble() print typeName,mfn.name()+"."+pname,'original',originalValue,'new',newValue for layer in layers: collections = layer.getCollections() for collection in collections: name = collection.name() overrides = collection.getOverrides() for override in overrides: obj = override.thisMObject() fn = om.MFnDependencyNode(obj) typeName = fn.typeName overridden = override.getOverridden() targetPlug = 'attrValue' isRel = False if typeName[0:3] == 'rel': targetPlug = 'offset' isRel = True plug = fn.findPlug(targetPlug, True) connectedToPlugs = plug.connectedTo(False,True) getOriginalValue(typeName, overridden, connectedToPlugs, isRel)
Result:
absUniqueOverride defaultRenderGlobals.endFrame original 100.0 new 200.0 relOverride pSphere1.translateX original 4.0 new 6.0
Hope it helps.
Yours,
Li
Thanks very much! I just had one issue that I managed to resolve: if there is an override on both the start and frames, the dg iterator will fail to find the correct node (it returns the same plug for both attributes), so I changed it to:
dgIt = om.MItDependencyGraph(mfn.findPlug(pname, True), om.MFn.kPluginDependNode, om.MItDependencyGraph.kUpstream, om.MItDependencyGraph.kBreadthFirst, om.MItDependencyGraph.kNodeLevel)
With this change I'm able to extract the values I need. Thanks!
Thanks very much! I just had one issue that I managed to resolve: if there is an override on both the start and frames, the dg iterator will fail to find the correct node (it returns the same plug for both attributes), so I changed it to:
dgIt = om.MItDependencyGraph(mfn.findPlug(pname, True), om.MFn.kPluginDependNode, om.MItDependencyGraph.kUpstream, om.MItDependencyGraph.kBreadthFirst, om.MItDependencyGraph.kNodeLevel)
With this change I'm able to extract the values I need. Thanks!
Can't find what you're looking for? Ask the community or share your knowledge.