def shape_from_element(element):
"""Return shape of given 'element'
Supports components, meshes, and surfaces
"""
try:
# Get either shape or transform, based on element-type
node = cmds.ls(element, objectsOnly=True)[0]
except Exception:
cmds.warning("Could not find node in %s" % element)
return None
if cmds.nodeType(node) == 'transform':
try:
return cmds.listRelatives(node, shapes=True)[0]
except Exception:
cmds.warning("Could not find shape in %s" % element)
return None
else:
return node
python类nodeType()的实例源码
def follicle(shape, u=0, v=0, name=""):
"""Attach follicle to "shape" at specified "u" and "v" values"""
type = cmds.nodeType(shape)
assert type in ("mesh", "nurbsSurface"), (
"follicle() works on polygonal meshes and nurbs")
src, dst = {
"mesh": (".outMesh", ".inputMesh"),
"nurbsSurface": (".local", ".inputSurface")
}[type]
follicle = cmds.createNode("follicle", name=name + "Shape")
transform = cmds.listRelatives(follicle, parent=True)[0]
cmds.setAttr(follicle + ".parameterU", u)
cmds.setAttr(follicle + ".parameterV", v)
cmds.connectAttr(follicle + ".outTranslate", transform + ".translate")
cmds.connectAttr(follicle + ".outRotate", transform + ".rotate")
cmds.connectAttr(shape + ".worldMatrix[0]", follicle + ".inputWorldMatrix")
cmds.connectAttr(shape + src, follicle + dst, force=True)
return transform
def clone_special(*args):
"""Clone in localspace, and preserve user-defined attributes"""
for transform in cmds.ls(selection=True, long=True):
if cmds.nodeType(transform) != "transform":
cmds.warning("Skipping '%s', not a `transform`" % transform)
continue
shape = _find_shape(transform)
type = cmds.nodeType(shape)
if type not in ("mesh", "nurbsSurface", "nurbsCurve"):
cmds.warning("Skipping '{transform}': cannot clone nodes "
"of type '{type}'".format(**locals()))
continue
cloned = commands.clone(shape, worldspace=False)
new_transform = cmds.listRelatives(cloned,
parent=True,
fullPath=True)[0]
new_transform = cmds.rename(new_transform,
new_transform.rsplit(":", 1)[-1])
for attr in cmds.listAttr(transform,
userDefined=True) or list():
try:
cmds.addAttr(new_transform, longName=attr, dataType="string")
except Exception:
continue
value = cmds.getAttr(transform + "." + attr)
cmds.setAttr(new_transform + "." + attr, value, type="string")
# Connect visibility
cmds.connectAttr(transform + ".visibility",
new_transform + ".visibility")
def _clone(worldspace=False):
"""Clone selected objects in viewport
Arguments:
worldspace (bool): Whether or not to append a transformGeometry to
resulting clone.
"""
clones = list()
for node in cmds.ls(selection=True, long=True):
shape = _find_shape(node)
type = cmds.nodeType(shape)
if type not in ("mesh", "nurbsSurface", "nurbsCurve"):
cmds.warning("Skipping '{node}': cannot clone nodes "
"of type '{type}'".format(**locals()))
continue
cloned = commands.clone(shape, worldspace=worldspace)
clones.append(cloned)
if not clones:
return
# Select newly created transform nodes in the viewport
transforms = list()
for clone in clones:
transform = cmds.listRelatives(clone, parent=True, fullPath=True)[0]
transforms.append(transform)
cmds.select(transforms, replace=True)
def _find_shape(element):
"""Return shape of given 'element'
Supports components, meshes, and surfaces
Arguments:
element (str): Path to component, mesh or surface
Returns:
str of path if found, None otherwise
"""
# Get either shape or transform, based on element-type
node = cmds.ls(element, objectsOnly=True, long=True)[0]
if cmds.nodeType(node) == "transform":
try:
return cmds.listRelatives(node, shapes=True, fullPath=True)[0]
except IndexError:
return cmds.warning("Could not find shape in %s" % element)
else:
return node
def create_node(node_dictionary, parent=None):
"""Create the Maya node described by the given data dictionary.
:param node_dictionary: The data dictionary generated by one of the load/get functions.
:param parent: The node to parent the created node to.
"""
node = cmds.createNode(node_dictionary['nodeType'], name=node_dictionary['name'])
if parent:
cmds.parent(node, parent)
cmds.setAttr('{0}.t'.format(node), *node_dictionary['translate'])
cmds.setAttr('{0}.r'.format(node), *node_dictionary['rotate'])
cmds.setAttr('{0}.s'.format(node), *node_dictionary['scale'])
cmds.setAttr('{0}.rotateOrder'.format(node), node_dictionary['rotateOrder'])
cmds.setAttr('{0}.rotateAxis'.format(node), *node_dictionary['rotateAxis'])
if node_dictionary['nodeType'] == 'joint':
cmds.setAttr('{0}.jointOrient'.format(node), *node_dictionary['jointOrient'])
cmds.setAttr('{0}.radius'.format(node), node_dictionary['radius'])
cmds.setAttr('{0}.side'.format(node), node_dictionary['side'])
cmds.setAttr('{0}.type'.format(node), node_dictionary['type'])
cmds.setAttr('{0}.otherType'.format(node), node_dictionary['otherType'], type='string')
cmds.setAttr('{0}.jointTypeX'.format(node), node_dictionary['jointTypeX'])
cmds.setAttr('{0}.jointTypeY'.format(node), node_dictionary['jointTypeY'])
cmds.setAttr('{0}.jointTypeZ'.format(node), node_dictionary['jointTypeZ'])
for child in node_dictionary.get('children', []):
create_node(child, node)
def get_skin_clusters(nodes):
"""Get the skinClusters attached to the specified node and all nodes in descendents.
:param nodes: List of dag nodes.
@return A list of the skinClusters in the hierarchy of the specified root node.
"""
if isinstance(nodes, basestring):
nodes = [nodes, ]
all_skins = []
for node in nodes:
relatives = cmds.listRelatives(node, ad=True, path=True) or []
relatives.insert(0, node)
relatives = [shortcuts.get_shape(node) for node in relatives]
for relative in relatives:
history = cmds.listHistory(relative, pruneDagObjects=True, il=2) or []
skins = [x for x in history if cmds.nodeType(x) == 'skinCluster']
if skins:
all_skins.append(skins[0])
return list(set(all_skins))
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 to_curve_fn(curve):
shape = None
if cmds.nodeType(curve, 'nurbsCurve'):
shape = curve
else:
child = cmds.listRelatives(curve, shapes=True, noIntermediate=True)
if child:
shape = child[0]
else:
cmds.warning('Not a proper nurbsCurve: {}'.format(curve))
raise Exception('Not a proper nurbsCurve: {}'.format(curve))
sel = om.MSelectionList()
sel.add(shape)
dep = sel.getDagPath(0)
fn = om.MFnNurbsCurve(dep)
return fn
def getShape(self, node):
"""
Gets the shape node from the input node.
:param node (str): string name of input node
Raises:
`RuntimeError` if no shape node.
Returns:
(str) shape node name
"""
if cmds.nodeType(node) == 'transform':
shapes = cmds.listRelatives(node, shapes=True)
if not shapes:
raise RuntimeError('%s has no shape' % node)
return shapes[0]
elif cmds.nodeType(node) == "mesh":
return node
def get_deformers(obj, *args):
"""
gets a list of deformers on the passed obj
:param obj: string - the transform to get deformers on
:param args:
:return:
"""
history = cmds.listHistory(obj)
deformerList = []
if history:
for node in history:
types = cmds.nodeType(node, inherited=True)
if "geometryFilter" in types:
deformerList.append(types[1])
return(deformerList)
def shape_from_element(element):
"""Return shape of given 'element'
Supports components, meshes, and surfaces
"""
try:
# Get either shape or transform, based on element-type
node = cmds.ls(element, objectsOnly=True)[0]
except:
cmds.warning("Could not find node in %s" % element)
return None
if cmds.nodeType(node) == 'transform':
try:
return cmds.listRelatives(node, shapes=True)[0]
except:
cmds.warning("Could not find shape in %s" % element)
return None
else:
return node
def getNodeAttributes(node):
'''
Get Maya node attributes
'''
attributes = cmds.listAttr(node)
attr = {}
attr['nodeName'] = node
attr['nodeType'] = cmds.nodeType(node)
for attribute in attributes:
if '.' in attribute:
continue
try:
val = cmds.getAttr(node + '.' + attribute)
except RuntimeError:
continue
attr[attribute] = val
return attr
def processNode(node):
'''
Start individual node processing
'''
if 'name' not in node:
return None
nodeName = node['name']
nodeType = node['type']
if nodeType not in mappings:
return None
xmlPath = os.path.join(basedir, 'nodes', nodeType + '.xml')
if not os.path.isfile(xmlPath) or mappings.get(nodeType) is None:
return None
tree = ET.parse(xmlPath)
root = tree.getroot()
root.attrib['name'] = nodeName
xmlNode = root.find("./group_parameter/string_parameter[@name='name']")
if xmlNode is not None:
xmlNode.attrib['value'] = nodeName
iterateMappingRecursive(mappings[nodeType], root, node)
return root
def getParent(self,name, filter=None):
if cmds.objExists(name):
if cmds.nodeType(name) == 'mesh':
name = cmds.listRelatives(name, p=True, f=True)
par = cmds.listRelatives(name, p=True, f=True)
if par:
parent = par[0].split('|')[-1]
if filter:
tok = self.tokenPrefix(filter)
for t in tok:
if t in parent:
return parent
return self.getParent(par[0], filter)
else:
return parent
else:
return 'NoParent'
def getSkinCluster(mesh):
'''
Return the first skinCluster affecting this mesh.
'''
if mc.nodeType(mesh) in ('mesh','nurbsSurface','nurbsCurve'):
shapes = [mesh]
else:
shapes = mc.listRelatives(mesh, shapes=True, path=True)
for shape in shapes:
history = mc.listHistory(shape, groupLevels=True, pruneDagObjects=True)
if not history:
continue
skins = mc.ls(history, type='skinCluster')
if skins:
return skins[0]
return None
def pivot_driver_attr(node):
'''
Start with supporting pivots driven by remap value nodes, more support in the future as requested.
'''
#rpSrc = mc.listConnections(node+'.rotatePivot', source=True, destination=False, plugs=True)
#if rpSrc and rpSrc[0].endswith('.translate') and mc.getAttr(rpSrc[0], keyable=True):
#return rpSrc[0]
for each in ('rotatePivotX', 'rotatePivotY', 'rotatePivotZ'):
src = mc.listConnections(node+'.'+each, source=True, destination=False)
if not src:
continue
srcType = mc.nodeType(src[0])
if srcType == 'remapValue':
src = mc.listConnections(src[0]+'.inputValue', source=True, destination=False, plugs=True)
if src and mc.getAttr(src[0], keyable=True) and not mc.getAttr(src[0], lock=True):
return src[0]
return None
def parent_group(source, transferTransform=True):
"""Create and transfer transforms to parent group"""
assert cmds.objExists(source), "%s does not exist" % source
assert cmds.nodeType(source) == "transform", (
"%s must be transform" % source)
parent = cmds.listRelatives(source, parent=True)
if transferTransform:
group = cmds.createNode("transform", n="%s_parent" % source)
match_transform(group, source)
try:
cmds.parent(source, group)
except Exception:
cmds.warning("Failed to parent child under new parent")
cmds.delete(group)
if parent:
cmds.parent(group, parent[0])
else:
cmds.select(source)
group = cmds.group(n="%s_parent" % source)
return group
def create_ncloth(input_mesh):
"""Replace Create nCloth menu item
This performs the identical option of nCloth -> Create nCloth
with the following changes.
1. Input mesh not made intermediate
2. Current mesh and shape named "currentMesh"
Arguments:
input_mesh (str): Path to shape
"""
assert cmds.nodeType(input_mesh) == "mesh", (
"%s was not of type mesh" % input_mesh)
nucleus = cmds.createNode("nucleus", name="nucleus1")
ncloth = cmds.createNode("nCloth", name="nClothShape1")
current_mesh = cmds.createNode("mesh", name="currentMesh")
cmds.connectAttr(input_mesh + ".worldMesh[0]", ncloth + ".inputMesh")
cmds.connectAttr(ncloth + ".outputMesh", current_mesh + ".inMesh")
cmds.connectAttr("time1.outTime", nucleus + ".currentTime")
cmds.connectAttr("time1.outTime", ncloth + ".currentTime")
cmds.connectAttr(ncloth + ".currentState", nucleus + ".inputActive[0]")
cmds.connectAttr(ncloth + ".startState", nucleus + ".inputActiveStart[0]")
cmds.connectAttr(nucleus + ".outputObjects[0]", ncloth + ".nextState")
cmds.connectAttr(nucleus + ".startFrame", ncloth + ".startFrame")
# Assign default shader
cmds.sets(current_mesh, addElement="initialShadingGroup")
return current_mesh
def process(self, instance):
from maya import cmds
has_multiple_shapes = list()
# Consider entire hierarchy of nodes included in an Instance
hierarchy = cmds.listRelatives(instance, allDescendents=True)
# Consider only nodes of type="mesh"
meshes = cmds.ls(hierarchy, type="mesh", long=True)
transforms = cmds.listRelatives(meshes, parent=True)
for transform in set(transforms):
shapes = cmds.listRelatives(transform, shapes=True) or list()
# Ensure the one child is a shape
has_single_shape = len(shapes) == 1
self.log.info("has single shape: %s" % has_single_shape)
# Ensure the one shape is of type "mesh"
has_single_mesh = (
has_single_shape and
cmds.nodeType(shapes[0]) == "mesh"
)
self.log.info("has single mesh: %s" % has_single_mesh)
if not all([has_single_shape, has_single_mesh]):
has_multiple_shapes.append(transform)
assert not has_multiple_shapes, (
"\"%s\" has transforms with multiple shapes: %s" % (
instance, ", ".join(
"\"" + member + "\"" for member in has_multiple_shapes))
)
def process(self, instance):
import os
from maya import cmds
# Resources are optional
if "resources_SEL" not in instance:
return
resources = dict()
for resource in cmds.sets("resources_SEL", query=True):
if cmds.nodeType(resource) == "reference":
path = cmds.referenceQuery(resource,
filename=True,
unresolvedName=True)
elif cmds.nodeType(resource) == "AlembicNode":
path = cmds.getAttr(resource + ".abc_File")
else:
# Unsupported
path = None
resources[resource] = path
# All resources were resolved
assert all(resources.values()), (
"Unsupported resource(s): " +
", ".join("'%s': '%s'" % (resource, path)
for resource, path in resources.items()
if path is not None)
)
# No resource contains an absolute path
assert not any(os.path.isabs(fname) for fname in resources), (
"Some resources are absolute: " +
", ".join(resources)
)
def get_shape(node, intermediate=False):
"""Get the shape node of a tranform
This is useful if you don't want to have to check if a node is a shape node
or transform. You can pass in a shape node or transform and the function
will return the shape node.
:param node: node The name of the node.
:param intermediate: intermediate True to get the intermediate shape
:return: The name of the shape node.
"""
if cmds.nodeType(node) == 'transform':
shapes = cmds.listRelatives(node, shapes=True, path=True)
if not shapes:
shapes = []
for shape in shapes:
is_intermediate = cmds.getAttr('%s.intermediateObject' % shape)
if intermediate and is_intermediate and cmds.listConnections(shape, source=False):
return shape
elif not intermediate and not is_intermediate:
return shape
if shapes:
return shapes[0]
elif cmds.nodeType(node) in ['mesh', 'nurbsCurve', 'nurbsSurface']:
is_intermediate = cmds.getAttr('%s.intermediateObject' % node)
if is_intermediate and not intermediate:
node = cmds.listRelatives(node, parent=True, path=True)[0]
return get_shape(node)
else:
return node
return None
def get_data(root):
"""Get the data dictionary that makes up a joint/transform hierarchy. Non-transform
branches will be skipped.
:param root: The root node of the hierarchy to export.
:return: A dictionary containing all data required to rebuild the hierarchy in Maya.
"""
node_type = cmds.nodeType(root)
shapes = cmds.listRelatives(root, children=True, shapes=True)
if node_type not in ['joint', 'transform'] or (shapes and node_type == 'transform'):
# Skip nodes that are not joints or transforms or if there are shapes below.
return None
# Store everything we need to recreate the node
data = {
'nodeType': node_type,
'name': root,
'translate': [truncate(x) for x in cmds.getAttr('{0}.t'.format(root))[0]],
'rotate': [truncate(x) for x in cmds.getAttr('{0}.r'.format(root))[0]],
'scale': [truncate(x) for x in cmds.getAttr('{0}.s'.format(root))[0]],
'rotateOrder': cmds.getAttr('{0}.rotateOrder'.format(root)),
'rotateAxis': [truncate(x) for x in cmds.getAttr('{0}.ra'.format(root))[0]],
'children': [],
}
if node_type == 'joint':
data['jointOrient'] = [truncate(x) for x in cmds.getAttr('{0}.jo'.format(root))[0]]
data['radius'] = cmds.getAttr('{0}.radius'.format(root))
data['side'] = cmds.getAttr('{0}.side'.format(root))
data['type'] = cmds.getAttr('{0}.type'.format(root))
data['otherType'] = cmds.getAttr('{0}.otherType'.format(root))
data['jointTypeX'] = cmds.getAttr('{0}.jointTypeX'.format(root))
data['jointTypeY'] = cmds.getAttr('{0}.jointTypeX'.format(root))
data['jointTypeZ'] = cmds.getAttr('{0}.jointTypeX'.format(root))
# Recurse down to all the children
children = cmds.listRelatives(root, children=True, path=True) or []
for child in children:
child_data = get_data(child)
if child_data:
data['children'].append(child_data)
return data
def dump(curves=None, stack=False):
"""Get a data dictionary representing all the given curves.
:param curves: Optional list of curves.
:return: A json serializable list of dictionaries containing the data required to recreate the curves.
"""
if curves is None:
curves = cmds.ls(sl=True) or []
data = []
for node in curves:
shape = shortcuts.get_shape(node)
if cmds.nodeType(shape) == 'nurbsCurve':
control = {
'name': node,
'cvs': cmds.getAttr('{0}.cv[*]'.format(node)),
'degree': cmds.getAttr('{0}.degree'.format(node)),
'form': cmds.getAttr('{0}.form'.format(node)),
'xform': cmds.xform(node, q=True, ws=True, matrix=True),
'knots': get_knots(node),
'pivot': cmds.xform(node, q=True, rp=True),
'overrideEnabled': cmds.getAttr('{0}.overrideEnabled'.format(node)),
'overrideRGBColors': cmds.getAttr('{0}.overrideRGBColors'.format(node)),
'overrideColorRGB': cmds.getAttr('{0}.overrideColorRGB'.format(node))[0],
'overrideColor': cmds.getAttr('{0}.overrideColor'.format(node)),
}
if stack:
control['stack'] = get_stack_count(node)
control['parent'] = get_stack_parent(node)
data.append(control)
if curves:
cmds.select(curves)
return data
def list_referenced_files():
results = []
links = cmds.filePathEditor(query=True, listDirectories="")
for link in links:
pairs = cmds.filePathEditor(query=True, listFiles=link, withAttribute=True, status=True)
'''
paris: list of strings ["file_name node status ...", "file_name node status ...",...]
we need to make this large list of ugly strings (good inforamtion seperated by white space) into a dictionry we can use
'''
l = len(pairs)
items = l/3
order = {}
index = 0
'''
order: dict of {node: [file_name, status],...}
'''
for i in range(0,items):
order[pairs[index+1]] = [os.path.join(link,pairs[index]),pairs[index+1],pairs[index+2]]
index = index + 3
for key in order:
# for each item in the dict, if the status is 0, repath it
if order[key][2] == "1":
results.append([order[key][0],cmds.nodeType(order[key][1])])
return results
def test_sfx_create(self):
new_network = SFXNetwork.create('example')
assert cmds.ls('example') == ['example']
assert cmds.nodeType('example') == 'ShaderfxShader'
assert new_network.shader == 'example'
def get_history(node, node_type=None):
history = cmds.listHistory(node)
if not node_type:
return history
return [n for n in history if cmds.nodeType(n) == node_type]
def add_curves_to_hair_system():
sel = cmds.ls(sl=True, dag=True, leaf=True, long=True)
if len(sel) < 2:
cmds.warning('Select a bunch of curves and a hairSystem node.')
return
curves = sel[:-1]
hair_system = sel[-1].split('|')[-1]
if cmds.nodeType(hair_system) != 'hairSystem':
cmds.warning(hair_system + ' is not a hairSystem.')
return
for curve in curves:
add_curve_to_system(curve, hair_system)
def process(self, instance):
import os
from maya import cmds
# Resources are optional
if "resources_SEL" not in instance:
return
resources = dict()
for resource in cmds.sets("resources_SEL", query=True):
if cmds.nodeType(resource) == "reference":
path = cmds.referenceQuery(resource,
filename=True,
unresolvedName=True)
elif cmds.nodeType(resource) == "AlembicNode":
path = cmds.getAttr(resource + ".abc_File")
else:
# Unsupported
path = None
resources[resource] = path
# All resources were resolved
assert all(resources.values()), (
"Unsupported resource(s): " +
", ".join("'%s': '%s'" % (resource, path)
for resource, path in resources.items()
if path is not None)
)
# No resource contains an absolute path
assert not any(os.path.isabs(fname) for fname in resources), (
"Some resources are absolute: " +
", ".join(resources)
)
def remove(container):
"""Remove an existing `container` from Maya scene
Deprecated; this functionality is replaced by `api.remove()`
Arguments:
container (avalon-core:container-1.0): Which container
to remove from scene.
"""
node = container["objectName"]
# Assume asset has been referenced
reference_node = next((node for node in cmds.sets(node, query=True)
if cmds.nodeType(node) == "reference"), None)
assert reference_node, ("Imported container not supported; "
"container must be referenced.")
log.info("Removing '%s' from Maya.." % container["name"])
namespace = cmds.referenceQuery(reference_node, namespace=True)
fname = cmds.referenceQuery(reference_node, filename=True)
cmds.file(fname, removeReference=True)
try:
cmds.delete(node)
except ValueError:
# Already implicitly deleted by Maya upon removing reference
pass
try:
# If container is not automatically cleaned up by May (issue #118)
cmds.namespace(removeNamespace=namespace, deleteNamespaceContent=True)
except RuntimeError:
pass