def template_joints(joints=None, reorient_children=True, reset_orientation=True):
if joints is None:
joints = cmds.ls(sl=True, type='joint')
if not joints:
raise RuntimeError('No joint selected to orient.')
if reorient_children:
children = cmds.listRelatives(fullPath=True, allDescendents=True, type='joint')
joints.extend(children)
red, green, blue = create_shaders()
orient_group = cmds.createNode('transform', name=ORIENT_GROUP)
manips = []
for joint in joints:
if reset_orientation:
cmds.makeIdentity(joint, apply=True)
cmds.joint(joint, edit=True, orientJoint='xyz', secondaryAxisOrient='yup', children=False, zeroScaleOrient=True)
if not cmds.listRelatives(joint, children=True):
zero_orient([joint])
continue
group, manip = create_orient_manipulator(joint, blue)
manips.append(manip)
cmds.parent(group, orient_group)
cmds.parentConstraint(joint, group)
cmds.setAttr(joint + '.template', 1)
cmds.select(manips)
python类parent()的实例源码
def create_orient_manipulator(joint, material):
joint_scale = cmds.jointDisplayScale(query=True)
joint_radius = cmds.getAttr('{0}.radius'.format(joint))
radius = joint_scale * joint_radius
children = cmds.listRelatives(joint, children=True, path=True)
if children:
p1 = cmds.xform(joint, q=True, ws=True, t=True)
p1 = OpenMaya.MPoint(*p1)
p2 = cmds.xform(children[0], q=True, ws=True, t=True)
p2 = OpenMaya.MPoint(*p2)
radius = p1.distanceTo(p2)
arrow_cvs = [[-1, 0, 0], [-1, 2, 0], [-2, 2, 0], [0, 4, 0], [2, 2, 0], [1, 2, 0], [1, 0, 0], [-1, 0, 0]]
arrow_cvs = [[x[0]*radius, x[1]*radius, x[2]*radius] for x in arrow_cvs]
shape = cmds.curve(name='{0}_zForward'.format(joint), degree=1, point=arrow_cvs)
# shape = cmds.sphere(n='{0}_zForward'.format(joint), p=(0, 0, 0), ax=(0, 0, -1), ssw=0, esw=180, r=radius, d=3, ut=0, tol=0.01, s=8, nsp=4, ch=0)[0]
# cmds.setAttr('{0}.sz'.format(shape), 0)
# cmds.select(shape)
# cmds.hyperShade(assign=material)
group = cmds.createNode('transform', name='{0}_grp'.format(shape))
cmds.parent(shape, group)
cmds.makeIdentity(shape, apply=True)
cmds.addAttr(shape, longName=MESSAGE_ATTRIBUTE, attributeType='message')
cmds.connectAttr('{0}.message'.format(joint), '{0}.{1}'.format(shape, MESSAGE_ATTRIBUTE))
for attr in ['tx', 'ty', 'tz', 'ry', 'rz', 'v']:
cmds.setAttr('{0}.{1}'.format(shape, attr), lock=True, keyable=False)
return group, shape
def create_curves(curves):
for curve in curves:
create_curve(curve)
# Now parent the curves
for curve in curves:
if curve.get('parent'):
parent = curve['parent']
if cmds.objExists(parent):
cmds.parent(curve['name'], parent)
# Then create the stacks
for curve in curves:
if curve.get('stack'):
create_transform_stack(curve['name'], curve['stack'])
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 test_duplicate_chain(self):
for i in range(5):
cmds.joint(p=(0, i, 0))
cmds.select(cl=True)
for i in range(5):
cmds.joint(p=(i+1, 0, 0))
cmds.parent('joint6', 'joint2')
joints, original_joints = shortcuts.duplicate_chain('joint1', 'joint5',
search_for='joint', replace_with='dupejoint')
self.assertEqual(5, len(joints))
self.assertListEqual(['dupejoint{0}'.format(x) for x in range(1, 6)], joints)
self.assertListEqual(['joint{0}'.format(x) for x in range(1, 6)], original_joints)
def _createInsideSphere(name, radius, parent):
node = cmds.sphere(r=radius * .999)[0]
cmds.parent(node, parent)
cmds.rename(node, name)
return node
def _createCurve(name, angle, cvs, parent):
node = cmds.curve(d=1, p=cvs)
cmds.parent(node, parent)
name += '_n%03d' if angle < 0. else '_p%03d'
cmds.rename(node, name % abs(round(angle)))
return node
def create_joint_chain(positions, **kwargs):
'''Create a joint chain from a list of om.MVectors'''
aim_vects = [b - a for a, b in zip(positions, positions[1:])]
aim_vects.append(aim_vects[-1])
joints = [create_joint(pos, aim, **kwargs) for pos, aim, in zip(positions, aim_vects)]
for parent, child in zip(joints, joints[1:]):
cmds.parent(child, parent)
cmds.setAttr(joints[-1] + '.jointOrient', 0, 0, 0) # Zero out the last joint in the chain
return joints
def new_strand(hair_system=None):
if not hair_system:
selection = cmds.ls(sl=True, dag=True, leaf=True, type='hairSystem')
if selection:
hair_system = selection[0]
start = om.MVector(0, 0, 0)
end = om.MVector(0, 0, 24)
start_loc = cmds.spaceLocator(name='strand_start#')[0]
end_loc = cmds.spaceLocator(name='strand_end#')[0]
cmds.xform(end_loc, ws=True, translation=end)
tta = cmds.createNode('transformsToArrays')
cmds.connectAttr(start_loc + '.worldMatrix', tta + '.inTransforms[0].inMatrix')
cmds.connectAttr(end_loc + '.worldMatrix', tta + '.inTransforms[1].inMatrix')
pcc = cmds.createNode('pointCloudToCurve')
cmds.connectAttr(tta + '.outPositionPP', pcc + '.inArray')
expand_grp = cmds.group([start_loc, end_loc], name='strand_expand_grp#')
curve, curve_shape = curve_between(start, end, name='strand_curve#')
cmds.connectAttr(pcc + '.outCurve', curve_shape + '.create')
root_grp = cmds.group(empty=True, name='strand_grp#')
cmds.parent([expand_grp, curve], root_grp)
follicle_nodes, out_curve_nodes = add_curve_to_system(curve_shape, hair_system)
follicle_shape = follicle_nodes[1]
cmds.setAttr(follicle_shape + '.pointLock', 3)
cmds.setAttr(follicle_shape + '.sampleDensity', 24)
def createJointFromObj(objs = [], *args):
"""
creates a joint at obj location/orientation. Can be arg[list] or selection
:param objs: a list of objects to operate on
:param args:
:return:
"""
if not objs:
objs = cmds.ls(sl=True, type="transform")
if objs:
for obj in objs:
pos = cmds.xform(obj, q=True, ws=True, rp=True)
rot = cmds.xform(obj, q=True, ws=True, ro=True)
jnt = cmds.joint(name="{0}_JNT".format(obj))
grp = cmds.group(jnt, n="{0}_JNT_GRP".format(obj))
if cmds.listRelatives(grp, p=True):
cmds.parent(grp, w=True)
cmds.xform(grp, ws=True, t=pos)
cmds.xform(grp, ws=True, ro=rot)
else:
cmds.warning("You need to select object(s)")
def createSpaceBuffers(*args):
"""
selection 1,2 = source parent, source obj
selection 3 = target obj
create two groups parented - named after source p,o
snap them to source obj
parentConstrain pGrp to sourceparent, oGrp to sourceobj
connectAttrs of oGrp to target obj(make sure values are zeroed)
"""
sel = cmds.ls(sl=True)
src1 = sel[0] # parent of Ctrl (or thing you want to relate it to)
src2 = sel[1] # ctrl
tgt = sel[2] # joint (should be in a group)
tgtGrp = cmds.group(em=True, name="{0}_spaceBuffer".format(src2))
tgtParGrp = cmds.group(em=True, name="{0}_spaceBuffer".format(src1))
cmds.parent(tgtGrp, tgtParGrp)
src1PC = cmds.parentConstraint(src1, tgtParGrp)
src2PC = cmds.parentConstraint(src2, tgtGrp)
if cmds.getAttr("{0}.t".format(tgt))[0]==(0,0,0):
cmds.connectAttr("{0}.t".format(src2), "{0}.t".format(tgt))
else:
print "{0} had non-zero translate values! Skipping connection.".format(tgt)
if cmds.getAttr("{0}.r".format(tgt))[0]==(0,0,0):
cmds.connectAttr("{0}.r".format(src2), "{0}.r".format(tgt))
else:
print "{0} had non-zero rotate values! Skipping connection.".format(tgt)
def parentChain(*args):
#parent chain (select objs, child first. WIll parent in order selected)
sel = cmds.ls(sl=True)
sizeSel = len(sel)
for x in range(0, sizeSel-1):
cmds.parent(sel[x], sel[x+1])
def parentCheck(obj):
""" checks whether there's a parent and if so returns it (otherwise returns None)"""
if obj:
plist = cmds.listRelatives(obj, p=True)
if plist:
return(plist)[0]
return(None)
def swapDupe(obj, target, delete = True, name="", *args):
"""
replaces an target with a duplicate of the obj
select the object you want to duplicate, then the target(s), delete bool, name optional
[obj] is the object to duplicate
[target] is the target to match and delete(?)
[delete] is bool to tell whether to delete the target or not
[name] is string to rename to
"""
if not name:
name = obj
# get pos, rot, scale of target
pos = cmds.xform(target, q=True, ws=True, rp=True)
rot = cmds.xform(target, q=True, ws=True, ro=True)
scl = cmds.getAttr("{0}.scale".format(target))
# duplicate the object and rename to name, if no name just use unique names
dupe = cmds.duplicate(obj, name=name, returnRootsOnly=True, renameChildren=True)
cmds.xform(dupe, ws=True, t=pos)
cmds.xform(dupe, ws=True, ro=rot)
cmds.xform(dupe, ws=True, s=scl[0])
parent = cmds.listRelatives(target, parent=True)
if parent:
cmds.parent(dupe, parent[0])
if delete:
cmds.delete(target)
return(dupe[0])
def doubleProxyCtrlGrp(ctrl = "", *args):
"""
creates a pair of groups parent constrained to selected ctrl (and it's group).
Basically is proxy to switch spaces (from rig part space to world space) for direct connections.
ctrl should be located in place with a group above (group frozen)
Args:
ctrl (string): the name of the ctrl(transform) to create the proxy for. Assumes a group above (group freeze)
Returns:
string, string: returns the names of the created ctrl group and the created parent group
"""
# grab the ctrl (must have group above)?
ctrlParent = parentCheck(ctrl)
if not ctrlParent:
cmds.error("doubleProxyGrp: don't have a parent group on the ctrl!")
return
# create groups for the proxy
ctrlGrp = cmds.group(empty=True, n="{0}_proxyCtrl".format(ctrl))
parGrp = cmds.group(empty=True, n="{0}_proxyGrp".format(ctrlParent))
# snap groups to the parent and child
snapTo(ctrlParent, parGrp)
snapTo(ctrl, ctrlGrp)
cmds.parent(ctrlGrp, parGrp)
# constrain groups
cmds.parentConstraint(ctrlParent, parGrp, mo=True)
cmds.parentConstraint(ctrl, ctrlGrp, mo=True)
# return groups
return(ctrlGrp, parGrp)
def groupFreeze(obj="", suffix = "GRP", *arg):
"""
takes an object in worldspace and snaps a group to it, then parents obj to that group
i.e. zeros out the obj's translates and rotations
Args:
obj (string): the object to put under the group (to zero it's transforms)
Returns:
string: returns the new group
"""
grp = cmds.group(empty=True, name="{0}_{1}".format(obj, suffix))
snapTo(obj, grp)
cmds.parent(obj, grp)
return(grp)
def get_soft_selection():
"""
should be a softSelection already selected (components). This returns list of cmpts and list of weights
:return: list of components, and list of weights
"""
# Grab the soft selection
selection = om.MSelectionList()
softSelection = om.MRichSelection()
om.MGlobal.getRichSelection(softSelection)
softSelection.getSelection(selection)
dagPath = om.MDagPath()
component = om.MObject()
# Filter Defeats the purpose of the else statement
iter = om.MItSelectionList(selection, om.MFn.kMeshVertComponent)
elements, weights = [], []
while not iter.isDone():
iter.getDagPath(dagPath, component)
dagPath.pop() # Grab the parent of the shape node
node = dagPath.fullPathName()
fnComp = om.MFnSingleIndexedComponent(component)
getWeight = lambda i: fnComp.weight(i).influence() if fnComp.hasWeights() else 1.0
for i in range(fnComp.elementCount()):
elements.append('%s.vtx[%i]' % (node, fnComp.element(i)))
weights.append(getWeight(i))
iter.next()
return elements, weights
def createWireDef(*args):
#clusterList = []
#rebuiltCrv = ""
#get geo and curve
geo = cmds.ls(sl=True)[0]
crv = cmds.ls(sl=True)[1]
rebuiltCrv = rebuildCrv(crv)
name = cmds.textFieldGrp(widgets["nameTFG"],q=True, tx=True)
defName = "wire_"+ name
wireDef = cmds.wire(geo, w = rebuiltCrv, n= defName, gw=True)
wireGroup = wireDef[1] + "Group"
cmds.setAttr(wireGroup + ".v", 0)
clusterList = clstrOnCurve(rebuiltCrv)
#print clusterList
ctrlGrp = createControls(clusterList)
masterGrp = cmds.group(n=name+"_GRP", em=True)
cmds.parent(ctrlGrp, masterGrp)
cmds.parent(wireGroup, masterGrp)
cmds.addAttr(masterGrp, ln="xxWireDeformerCtrlsXX", at="bool", k=True)
cmds.setAttr(masterGrp + ".xxWireDeformerCtrlsXX", l=True)
cmds.addAttr(masterGrp, ln = 'envelope', at = "float", dv = 1, min=0, max=1, k=True)
cmds.addAttr(masterGrp, ln = 'DropoffDistance', at = 'float', dv = 1, min = 0, max = 15, k = True)
cmds.addAttr(masterGrp, ln = 'tension', at = 'float', dv = 1, min = -10, max = 10, k = True)
cmds.addAttr(masterGrp, ln = 'rot', at = 'float', min = 0, max = 1, k =True)
cmds.addAttr(masterGrp, ln = 'scl', at = 'float', dv = 1, min = 0, max = 3, k = True)
cmds.connectAttr(masterGrp + ".envelope", wireDef[0] + ".envelope")
cmds.connectAttr(masterGrp + ".DropoffDistance", wireDef[0] + ".dropoffDistance[0]")
cmds.connectAttr(masterGrp + ".tension", wireDef[0] + ".tension")
cmds.connectAttr(masterGrp + ".rot", wireDef[0] + ".rotation")
cmds.connectAttr(masterGrp + ".scl", wireDef[0] + ".scale[0]")
cmds.select(masterGrp, r = True)
incrementName()
def create_object(verts_pos, face_verts):
"""
Function creates an object with mesh given by vertice and face data.
:type face_verts: Python list
:type verts_pos: Python list
"""
shark_mesh = om.MObject()
points = om.MFloatPointArray() # An array that is storing positions od vertices. Do not include id of vertices
for vert in verts_pos: # add every point to Maya float points array
p = om.MFloatPoint(vert[0], vert[2], -vert[1])
points.append(p)
face_connects = om.MIntArray() # an array for vertice numbers per face.
face_counts = om.MIntArray() # an array for total number of vertices per face
for verts in face_verts:
# In Maya mesh is created on a base of two arrays: list of vertice numbers and list of numbers of vertices
# of faces. Vertice numbers from the first list are not grouped by faces, this is just a one dimmension array.
# Based on this list only it would be impossible to recreate mesh, becouse number of vertices in faces may vary
# (in this example every face have 3 vertices, but this is not obligatory).
# The second array stores the number of vertices of faces. From this list Mata gets a number of vertices of a
# face, let's call it N, then assigns next N vertices to this face. The process is repeated for every face.
face_connects.append(verts[0]) # Append vertices of face.
face_connects.append(verts[1])
face_connects.append(verts[2])
face_counts.append(len(verts)) # append the number of vertices for this face
mesh_fs = om.MFnMesh()
mesh_fs.create(points, face_counts, face_connects, parent=shark_mesh)
mesh_fs.updateSurface()
node_name = mesh_fs.name()
cmds.polySoftEdge(node_name, a=30, ch=1) # Automatically soften the edges of the mesh
# assign new mesh to default shading group
cmds.sets(node_name, e=True, fe='initialShadingGroup')
return cmds.listRelatives(node_name, fullPath=True, parent=True) # node name stores a name of Shape node.
# Most functions need a Transform node. Ths line returns it.
def create_and_animate_trees():
"""
Function uses the create_palm() support function to create and animate some palm trees.
It was created to show how to create basic geometry objects, use instances and use modificators.
"""
palm1 = create_palm(diameter=1.3, segs_num=20, leafs_num=9, bending=34, id_num=1, anim_start=11, anim_end=26)
palm2 = create_palm(diameter=1.6, segs_num=20, leafs_num=9, bending=34, id_num=2, anim_start=40, anim_end=45)
palm3 = create_palm(diameter=1.1, segs_num=18, leafs_num=9, bending=24, id_num=3, anim_start=20, anim_end=35)
palm4 = create_palm(diameter=1.1, segs_num=24, leafs_num=9, bending=24, id_num=4, anim_start=25, anim_end=40)
cmds.currentTime(55) # The removal of history had strange effect when it was applied before tree animation
# Next line is intended to avoid a bug. If the history has to be deleted with a cmds.delete function. If it
# would not be modified then the bend modifictor would have to be moved wit an object or it would affect an object
# in different ways then desired during a changes in its position. The problem is, that during that an evaluation
# of commands may take some time and the removing of history resulted in not deformed mesh or a partialy
# deformed mesh. This is why cmds.refresh() ommand was used.
cmds.refresh(f=True)
cmds.delete(palm1, ch=True)
cmds.rotate(0.197, 105, 0.558, palm1, absolute=True) # Rotate the palm
cmds.move(-8.5, -4.538, 18.1, palm1, absolute=True) # Position the palm
cmds.parent(palm1, 'land', relative=True) # Rename it
cmds.delete(palm2, ch=True)
cmds.rotate(-16.935, 74.246, -23.907, palm2)
cmds.move(29.393, -3.990, 4.526, palm2)
cmds.parent(palm2, 'land', relative=True)
cmds.delete(palm3, ch=True)
cmds.move(24.498, -3.322, 36.057, palm3)
cmds.rotate(0.023, 0.248, -1.950, palm3)
cmds.parent(palm3, 'land', relative=True)
cmds.delete(palm4, ch=True)
cmds.move(4.353, -1.083, 22.68, palm4)
cmds.rotate(-150, -102.569, 872.616, palm4)
cmds.parent(palm4, 'land', relative=True)