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")
python类addAttr()的实例源码
def softWave(sftmod, arrow, ctrl, *args):
# add values to positions in graph
positions = [0.0, 0.3, 0.6, 0.9, 0.95]
values = [1.0, -0.3, 0.1, -0.05, 0.01]
for i in range(len(positions)):
cmds.setAttr("{0}.falloffCurve[{1}].falloffCurve_Position".format(sftmod, i), positions[i])
cmds.setAttr("{0}.falloffCurve[{1}].falloffCurve_FloatValue".format(sftmod, i), values[i])
cmds.setAttr("{0}.falloffCurve[{1}].falloffCurve_Interp".format(sftmod, i), 2)
cmds.addAttr(arrow, ln="WaveAttrs", at="enum", k=True)
cmds.setAttr("{0}.WaveAttrs".format(arrow), l=True)
# expose these on the control
for j in range(5):
cmds.addAttr(arrow, ln="position{0}".format(j), at="float", min=0.0, max=1.0, dv=positions[j], k=True)
cmds.connectAttr("{0}.position{1}".format(arrow, j),
"{0}.falloffCurve[{1}].falloffCurve_Position".format(sftmod, j))
for j in range(5):
cmds.addAttr(arrow, ln="value{0}".format(j), at="float", min=-1.0, max=1.0, dv=values[j], k=True)
cmds.connectAttr("{0}.value{1}".format(arrow, j),
"{0}.falloffCurve[{1}].falloffCurve_FloatValue".format(sftmod, j))
cmds.setAttr("{0}.position{1}".format(arrow, j), l=True)
cmds.setAttr("{0}.value{1}".format(arrow, j), l=True)
def locked_attr(*args):
"""
creates a locked attr (I use as a separator). Uses the long name as the nice name (literal name in channel box)
"""
attrName = cmds.textFieldButtonGrp(widgets["lockAttrTFBG"], q=True, tx=True)
if attrName:
sel = cmds.ls(sl=True)
if sel:
for obj in sel:
try:
cmds.addAttr(obj, ln=attrName, nn=attrName, at="enum", en="-----", k=True)
cmds.setAttr("%s.%s" % (obj, attrName), l=True)
except:
cmds.warning("Failed to add %s to %s, skipping!" % (attrName, obj))
else:
cmds.warning("Please select some objects to add attr to!")
else:
cmds.warning("Please enter a name for the attr!")
def add_zero_one_attribute(attrType, *args):
"""
adds an attribute with range of 0 to 1 to each selected obj
:param attrType: either "short" or "float"
:param args:
:return:
"""
sel = cmds.ls(sl=True)
if not sel:
cmds.warning("You need to select an object add attrs to!")
return()
attrName = cmds.textFieldGrp(widgets["newAttrTFG"], q=True, tx=True)
if not attrName:
cmds.warning("Please enter a name for the attribute in the field!")
return()
for obj in sel:
try:
cmds.addAttr(obj, ln=attrName, at=attrType, min=0, max=1, dv=0, k=True)
except:
cmds.warning("Couldn't add attr: {0} to object: {1}. Skipping.".format(attrName, obj))
def lock():
"""Lock scene
Add an invisible node to your Maya scene with the name of the
current file, indicating that this file is "locked" and cannot
be modified any further.
"""
if not cmds.objExists("lock"):
with lib.maintained_selection():
cmds.createNode("objectSet", name="lock")
cmds.addAttr("lock", ln="basename", dataType="string")
# Permanently hide from outliner
cmds.setAttr("lock.verticesOnlySet", True)
fname = cmds.file(query=True, sceneName=True)
basename = os.path.basename(fname)
cmds.setAttr("lock.basename", basename, type="string")
def set_info_to_scene(search_key, context):
# add info about particular scene
skey_link = 'skey://{0}&context={1}'.format(search_key, context)
if not cmds.attributeQuery('tacticHandler_skey', node='defaultObjectSet', exists=True):
cmds.addAttr('defaultObjectSet', longName='tacticHandler_skey', dataType='string')
cmds.setAttr('defaultObjectSet.tacticHandler_skey', skey_link, type='string')
def _set_uuid(node):
"""Add mbID to `node`
Unless one already exists.
"""
attr = "{0}.mbID".format(node)
if not cmds.objExists(attr):
cmds.addAttr(node, longName="mbID", dataType="string")
_, uid = str(uuid.uuid4()).rsplit("-", 1)
cmds.setAttr(attr, uid, type="string")
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_transform_stack(node, count=2):
"""Creates a transform stack above the given node.
Any previous transform stack will be deleted.
:param node: Node to parent into a transform stack.
:param count: Number of transforms to add in the stack.
:return: A list of the transform nodes created starting from top to bottom.
"""
previous_parent = cmds.listRelatives(node, parent=True, path=True)
if previous_parent:
previous_parent = previous_parent[0]
while previous_parent and STACK_ATTRIBUTE in (cmds.listAttr(previous_parent, ud=True) or []):
parent = cmds.listRelatives(previous_parent, parent=True, path=True)
if parent:
cmds.parent(node, parent)
parent = parent[0]
else:
cmds.parent(node, world=True)
cmds.delete(previous_parent)
previous_parent = parent
nulls = []
for i in reversed(range(count)):
name = '_'.join(node.split('_')[:-1])
name = '{0}_{1}nul'.format(name, i+1)
null = cmds.createNode('transform', name=name)
nulls.append(null)
cmds.addAttr(null, ln=STACK_ATTRIBUTE, at='message')
cmds.connectAttr('{0}.message'.format(node), '{0}.{1}'.format(null, STACK_ATTRIBUTE))
cmds.delete(cmds.parentConstraint(node, null))
if previous_parent:
cmds.parent(null, previous_parent)
previous_parent = null
cmds.parent(node, previous_parent)
return nulls
def BT_Setup(set = None):
if not set:
return False
transforms = cmds.listConnections(set +'.dagSetMembers')
if not transforms:
return False
if not cmds.attributeQuery('Blend_Node', n = set, ex = True):
cmds.addAttr(set, ln = 'Blend_Node', k = False, h = True, dt = 'string')
else:
return False
btNode = cmds.createNode("BlendTransforms")
cmds.setAttr(set +'.Blend_Node', btNode, type = "string")
for i in range(0, len(transforms)):
baseMatrix = cmds.xform(transforms[i], q = True, m = True)
baseScale = cmds.getAttr(transforms[i] +'.scale')[0]
baseRotOffset = [0.0, 0.0, 0.0]
if cmds.objectType(transforms[i], isType = 'joint'):
baseRotOffset = cmds.getAttr(transforms[i] +'.jointOrient')[0]
btAttr = 'transforms[' +str(i) +'].baseMatrix'
btScaleAttr = 'transforms[' +str(i) +'].baseScale'
btRotOffsetAttr = 'transforms[' +str(i) +'].baseRotOffset'
BT_MatrixValuesToNode(values = baseMatrix, node = btNode, attr = btAttr)
BT_Double3ValuesToNode(values = baseScale, node = btNode, attr = btScaleAttr)
BT_Double3ValuesToNode(values = baseRotOffset, node = btNode, attr = btRotOffsetAttr)
BT_ConnectOutputs(index = i, node = btNode, transform = transforms[i])
return True
def BT_Setup(set = None):
if not set:
return False
transforms = cmds.listConnections(set +'.dagSetMembers')
if not transforms:
return False
if not cmds.attributeQuery('Blend_Node', n = set, ex = True):
cmds.addAttr(set, ln = 'Blend_Node', k = False, h = True, dt = 'string')
else:
return False
btNode = cmds.createNode("BlendTransforms")
cmds.setAttr(set +'.Blend_Node', btNode, type = "string")
for i in range(0, len(transforms)):
baseMatrix = cmds.xform(transforms[i], q = True, m = True)
baseScale = cmds.getAttr(transforms[i] +'.scale')[0]
baseRotOffset = [0.0, 0.0, 0.0]
if cmds.objectType(transforms[i], isType = 'joint'):
baseRotOffset = cmds.getAttr(transforms[i] +'.jointOrient')[0]
btAttr = 'transforms[' +str(i) +'].baseMatrix'
btScaleAttr = 'transforms[' +str(i) +'].baseScale'
btRotOffsetAttr = 'transforms[' +str(i) +'].baseRotOffset'
BT_MatrixValuesToNode(values = baseMatrix, node = btNode, attr = btAttr)
BT_Double3ValuesToNode(values = baseScale, node = btNode, attr = btScaleAttr)
BT_Double3ValuesToNode(values = baseRotOffset, node = btNode, attr = btRotOffsetAttr)
BT_ConnectOutputs(index = i, node = btNode, transform = transforms[i])
return True
def BT_Setup(set = None):
if not set:
return False
transforms = cmds.listConnections(set +'.dagSetMembers')
if not transforms:
return False
if not cmds.attributeQuery('Blend_Node', n = set, ex = True):
cmds.addAttr(set, ln = 'Blend_Node', k = False, h = True, dt = 'string')
else:
return False
btNode = cmds.createNode("BlendTransforms")
cmds.setAttr(set +'.Blend_Node', btNode, type = "string")
for i in range(0, len(transforms)):
baseMatrix = cmds.xform(transforms[i], q = True, m = True)
baseScale = cmds.getAttr(transforms[i] +'.scale')[0]
baseRotOffset = [0.0, 0.0, 0.0]
if cmds.objectType(transforms[i], isType = 'joint'):
baseRotOffset = cmds.getAttr(transforms[i] +'.jointOrient')[0]
btAttr = 'transforms[' +str(i) +'].baseMatrix'
btScaleAttr = 'transforms[' +str(i) +'].baseScale'
btRotOffsetAttr = 'transforms[' +str(i) +'].baseRotOffset'
BT_MatrixValuesToNode(values = baseMatrix, node = btNode, attr = btAttr)
BT_Double3ValuesToNode(values = baseScale, node = btNode, attr = btScaleAttr)
BT_Double3ValuesToNode(values = baseRotOffset, node = btNode, attr = btRotOffsetAttr)
BT_ConnectOutputs(index = i, node = btNode, transform = transforms[i])
return True
def BT_Setup(set = None):
if not set:
return False
transforms = cmds.listConnections(set +'.dagSetMembers')
if not transforms:
return False
if not cmds.attributeQuery('Blend_Node', n = set, ex = True):
cmds.addAttr(set, ln = 'Blend_Node', k = False, h = True, dt = 'string')
else:
return False
btNode = cmds.createNode("BlendTransforms")
cmds.setAttr(set +'.Blend_Node', btNode, type = "string")
for i in range(0, len(transforms)):
baseMatrix = cmds.xform(transforms[i], q = True, m = True)
baseScale = cmds.getAttr(transforms[i] +'.scale')[0]
baseRotOffset = [0.0, 0.0, 0.0]
if cmds.objectType(transforms[i], isType = 'joint'):
baseRotOffset = cmds.getAttr(transforms[i] +'.jointOrient')[0]
btAttr = 'transforms[' +str(i) +'].baseMatrix'
btScaleAttr = 'transforms[' +str(i) +'].baseScale'
btRotOffsetAttr = 'transforms[' +str(i) +'].baseRotOffset'
BT_MatrixValuesToNode(values = baseMatrix, node = btNode, attr = btAttr)
BT_Double3ValuesToNode(values = baseScale, node = btNode, attr = btScaleAttr)
BT_Double3ValuesToNode(values = baseRotOffset, node = btNode, attr = btRotOffsetAttr)
BT_ConnectOutputs(index = i, node = btNode, transform = transforms[i])
return True
def DagPathFromJoint(name, needsRest=True):
# Check for it
if not cmds.objExists(name):
# Not found in scene
return False
# Check to add
if needsRest:
# Check for the attr (to set rest pos)
if not cmds.objExists(name + ".seanimUndoT"):
# We need to setup the undo data
ResetTranslation = cmds.getAttr(name + ".t")[0]
ResetScale = cmds.getAttr(name + ".scale")[0]
ResetRotation = cmds.getAttr(name + ".jo")[0]
# Make the attributes
cmds.addAttr(name, longName="seanimUndoT", dataType="double3", storable=True)
cmds.addAttr(name, longName="seanimUndoS", dataType="double3", storable=True)
cmds.addAttr(name, longName="seanimUndoR", dataType="double3", storable=True)
# Set them
cmds.setAttr(name + ".seanimUndoT", ResetTranslation[0], ResetTranslation[1], ResetTranslation[2], type="double3")
cmds.setAttr(name + ".seanimUndoS", ResetScale[0], ResetScale[1], ResetScale[2], type="double3")
cmds.setAttr(name + ".seanimUndoR", ResetRotation[0], ResetRotation[1], ResetRotation[2], type="double3")
# Make selector
sList = OpenMaya.MSelectionList()
# Add it
sList.add(name)
# New Path
dResult = OpenMaya.MDagPath()
# Set it
sList.getDagPath(0, dResult)
# Return
return dResult
# Disconnects a MDagPath from it's input keyframes
def toggle_burnin(value):
'''Toggle default viewport burnin'''
viewport_burnin = get_viewport_burnin()
if viewport_burnin:
cmds.setAttr(viewport_burnin + '.v', value)
return
if not value:
return
if not cmds.pluginInfo(burnin.type_name, q=True, loaded=True):
cmds.loadPlugin(burnin.type_name)
viewport_burnin = cmds.createNode('burnin')
cmds.addAttr(viewport_burnin, ln='viewport_burnin', at='bool', dv=True)
cmds.setAttr(viewport_burnin + '.fontSize', 16)
cmds.setAttr(viewport_burnin + '.fontWeight', 75)
cmds.setAttr(viewport_burnin + '.fontAlpha', 0.75)
t0 = viewport_burnin + '.textArray[0]'
cmds.setAttr(t0 + '.textString', '{frame:0>3d}\n{camera}', type='string')
cmds.setAttr(t0 + '.textColor', 1, 1, 1)
cmds.setAttr(t0 + '.textAlign', 7)
t1 = viewport_burnin + '.textArray[1]'
cmds.setAttr(t1 + '.textString', '{user}\n{scene}', type='string')
cmds.setAttr(t1 + '.textColor', 1, 1, 1)
cmds.setAttr(t1 + '.textAlign', 6)
def containerise(name, nodes, version):
"""Bundle `nodes` into an assembly and imprint it with metadata
Containerisation enables a tracking of version, author and origin
for loaded assets.
Arguments:
name (str): Name of resulting assembly
nodes (list): Long names of nodes to containerise
version (pyblish-starter:version-1.0): Current version
"""
assemblies = cmds.ls(nodes, assemblies=True)
container = cmds.group(assemblies, name=name)
data = [
("id", "pyblish.starter.container"),
("author", version["author"]),
("loader", self.__name__),
("time", version["time"]),
("version", version["version"]),
("source", version["source"]),
("comment", version.get("comment", ""))
]
for key, value in data:
if not value:
continue
cmds.addAttr(container, longName=key, dataType="string")
cmds.setAttr(container + "." + key, value, type="string")
return container
def imprint(node, data):
"""Write `data` to `node` as userDefined attributes
Arguments:
node (str): Long name of node
data (dict): Dictionary of key/value pairs
"""
for key, value in data.items():
if isinstance(value, bool):
add_type = {"attributeType": "bool"}
set_type = {"keyable": False, "channelBox": True}
elif isinstance(value, basestring):
add_type = {"dataType": "string"}
set_type = {"type": "string"}
elif isinstance(value, int):
add_type = {"attributeType": "long"}
set_type = {"keyable": False, "channelBox": True}
elif isinstance(value, float):
add_type = {"attributeType": "double"}
set_type = {"keyable": False, "channelBox": True}
else:
raise TypeError("Unsupported type: %r" % type(value))
cmds.addAttr(node, longName=key, **add_type)
cmds.setAttr(node + "." + key, value, **set_type)
def createMessage(host="none", attr="none", target="none", *args):
"""creates a message attr on object with target as value. Args are: 'host'-some object to hold the message attr, 'attr'-the name of the message attribute to create, and 'target'-the host to be the value of the message attr"""
cmds.addAttr(host, at='message', ln=attr)
cmds.connectAttr("%s.message"%target, "%s.%s"%(host, attr))
return("%s.%s"%(host, attr))
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 transfer_attrs(*args):
"""
transfers attrs and connections from second obj to first object selected
"""
tgt, src = get_source_and_targets()
if not tgt or len(src) > 1:
cmds.warning("Select only one target then one source obj to transfer the attributes and connections!")
return ()
attrs = cmds.channelBox('mainChannelBox', q=True, selectedMainAttributes=True)
if not attrs:
cmds.warning("You have to select at least one attr on last object selected to transfer!")
return ()
for attr in attrs:
attrType, hasMin, attrMin, hasMax, attrMax, value, inConnection, outConnection, locked = get_channel_attributes(
src[0], attr)
if not attrType == "enum":
# create attribute
if not cmds.attributeQuery(attr, node=tgt, exists=True):
if hasMin and not hasMax:
cmds.addAttr(tgt, ln=attr, at=attrType, min=attrMin[0], dv=value, k=True)
elif hasMax and not hasMin:
cmds.addAttr(tgt, ln=attr, at=attrType, max=attrMax[0], dv=value, k=True)
elif hasMin and hasMax:
cmds.addAttr(tgt, ln=attr, at=attrType, min=attrMin[0], max=attrMax[0], dv=value, k=True)
else:
cmds.addAttr(tgt, ln=attr, at=attrType, dv=value, k=True)
else:
cmds.warning("The attribute: {0} already exists. Skipping creation!".format(attr))
# lock
if locked:
cmds.setAttr("{0}.{1}".format(tgt, attr), l=True)
else:
cmds.warning("I don't do enums at the moment!")
# connect tgt attr to connection, forced
if inConnection:
cmds.connectAttr(inConnection[0], "{0}.{1}".format(tgt, attr))
if outConnection:
for conn in outConnection:
cmds.connectAttr("{0}.{1}".format(tgt, attr), conn, force=True)
def load(file_path, obj_name, parent_name):
"""Import a file exported from ZBrush.
This is the command sent over the Maya command port from ZBrush.
Parameters
----------
file_path : str
Path to the file that we are importing
obj_name : str
Name of the object being imported
parent_name : str
Name of the parent for the object being imported
"""
file_name = utils.split_file_name(file_path)
_cleanup(file_name)
cmds.file(file_path, i=True,
usingNamespaces=False,
removeDuplicateNetworks=True)
# Set smoothing options if necessary
if cmds.optionVar(ex='gozbruh_smooth') and not cmds.optionVar(q='gozbruh_smooth'):
cmds.displaySmoothness(obj_name, du=0, dv=0, pw=4, ps=1, po=1)
if not cmds.attributeQuery("gozbruhParent", n=obj_name, ex=True):
cmds.addAttr(obj_name, longName='gozbruhParent', dataType='string')
cmds.setAttr(obj_name + '.gozbruhParent', parent_name, type='string')
def editPivotHandle(self):
qt_maya_window.installEventFilter(self.keypressFilter)
#create transform
self.pivotHandle = mc.group(em=True, name='Adjust_Pivot')
mc.setAttr(self.pivotHandle+'.rotate', lock=True)
mc.setAttr(self.pivotHandle+'.rx', keyable=False)
mc.setAttr(self.pivotHandle+'.ry', keyable=False)
mc.setAttr(self.pivotHandle+'.rz', keyable=False)
mc.setAttr(self.pivotHandle+'.scale', lock=True)
mc.setAttr(self.pivotHandle+'.sx', keyable=False)
mc.setAttr(self.pivotHandle+'.sy', keyable=False)
mc.setAttr(self.pivotHandle+'.sz', keyable=False)
mc.setAttr(self.pivotHandle+'.visibility', lock=True, keyable=False)
mc.setAttr(self.pivotHandle+'.displayHandle', True)
self.pivotHandle = mc.parent(self.pivotHandle, self.node)[0]
mc.addAttr(self.pivotHandle, ln='ml_pivot_handle', at='bool', keyable=False)
#set initial position
mc.setAttr(self.pivotHandle+'.translate', *mc.getAttr(self.node+'.rotatePivot')[0])
#lock it so you don't delete it or something.
mc.lockNode(self.pivotHandle, lock=True)
self.scriptJob = mc.scriptJob(event=['SelectionChanged', self.cleanup], runOnce=True)
mc.setToolTo('Move')
mc.inViewMessage( amg='After moving the pivot, press <hl>Return</hl> to bake or <hl>Esc</hl> to cancel.', pos='midCenterTop', fade=True, fadeStayTime=4000, dragKill=True)
def BT_AddPose(set = None, poseName = '', index = None):
prefixedPoseName = 'BT_' +poseName
if not set:
return False
if not cmds.attributeQuery('Blend_Node', ex = True, n = set):
return False
if BT_IsSetupConnected(set = set):
cmds.warning('Disconnect setup first!')
return False
blendNode = cmds.getAttr(set +'.Blend_Node')
if not cmds.objExists(blendNode) or not cmds.objExists(set):
return False
if cmds.attributeQuery(prefixedPoseName, ex = True, n = set):
return False
transforms = cmds.listConnections(set +'.dagSetMembers')
numTransforms = len(transforms)
poseIndex = cmds.getAttr(blendNode +'.transforms[0].poses', size = True)
if index is not None:
poseIndex = index
if index is None:
cmds.addAttr(set, ln = prefixedPoseName, nn = poseName, k = True, min = 0, max = 1.0, at = 'double')
# print ('Num poses = ' +str(numPoses))
for i in range(0, numTransforms):
#get the base matrix
baseScale = cmds.getAttr(blendNode +'.transforms[' +str(i) +'].baseScale')[0]
baseMatrix = cmds.getAttr(blendNode +'.transforms[' +str(i) +'].baseMatrix')
#store the scale and set it
transformScale = cmds.getAttr(transforms[i] +'.scale')[0]
#set the scale back to 1.0
cmds.setAttr(transforms[i] +'.scale', 1.0, 1.0, 1.0, type = 'double3')
transformMatrix = cmds.xform(transforms[i], q = True, m = True)
poseMatrix = [x-y for x, y in zip(transformMatrix, baseMatrix)]
poseScale = [x-y for x, y in zip(transformScale, baseScale)]
#set the scale back to what the user had it at
cmds.setAttr(transforms[i] +'.scale', transformScale[0], transformScale[1], transformScale[2], type = 'double3')
cmds.setAttr(blendNode +'.transforms[' +str(i) +'].poses[' +str(poseIndex) +'].matrix', poseMatrix, type = 'matrix')
BT_Double3ValuesToNode(values = poseScale, node = blendNode, attr = 'transforms[' +str(i) +'].poses[' +str(poseIndex) +'].scale' )
if index is None:
cmds.connectAttr(set +'.' +prefixedPoseName, blendNode +'.transforms[' +str(i) +'].poses[' +str(poseIndex) +'].weight')
return True
def BT_AddPose(set = None, poseName = '', index = None):
prefixedPoseName = 'BT_' +poseName
if not set:
return False
if not cmds.attributeQuery('Blend_Node', ex = True, n = set):
return False
if BT_IsSetupConnected(set = set):
cmds.warning('Disconnect setup first!')
return False
blendNode = cmds.getAttr(set +'.Blend_Node')
if not cmds.objExists(blendNode) or not cmds.objExists(set):
return False
if cmds.attributeQuery(prefixedPoseName, ex = True, n = set):
return False
transforms = cmds.listConnections(set +'.dagSetMembers')
numTransforms = len(transforms)
poseIndex = cmds.getAttr(blendNode +'.transforms[0].poses', size = True)
if index is not None:
poseIndex = index
if index is None:
cmds.addAttr(set, ln = prefixedPoseName, nn = poseName, k = True, min = 0, max = 1.0, at = 'double')
# print ('Num poses = ' +str(numPoses))
for i in range(0, numTransforms):
#get the base matrix
baseScale = cmds.getAttr(blendNode +'.transforms[' +str(i) +'].baseScale')[0]
baseMatrix = cmds.getAttr(blendNode +'.transforms[' +str(i) +'].baseMatrix')
#store the scale and set it
transformScale = cmds.getAttr(transforms[i] +'.scale')[0]
#set the scale back to 1.0
cmds.setAttr(transforms[i] +'.scale', 1.0, 1.0, 1.0, type = 'double3')
transformMatrix = cmds.xform(transforms[i], q = True, m = True)
poseMatrix = [x-y for x, y in zip(transformMatrix, baseMatrix)]
poseScale = [x-y for x, y in zip(transformScale, baseScale)]
#set the scale back to what the user had it at
cmds.setAttr(transforms[i] +'.scale', transformScale[0], transformScale[1], transformScale[2], type = 'double3')
cmds.setAttr(blendNode +'.transforms[' +str(i) +'].poses[' +str(poseIndex) +'].matrix', poseMatrix, type = 'matrix')
BT_Double3ValuesToNode(values = poseScale, node = blendNode, attr = 'transforms[' +str(i) +'].poses[' +str(poseIndex) +'].scale' )
if index is None:
cmds.connectAttr(set +'.' +prefixedPoseName, blendNode +'.transforms[' +str(i) +'].poses[' +str(poseIndex) +'].weight')
return True
def BT_AddPose(set = None, poseName = '', index = None):
prefixedPoseName = 'BT_' +poseName
if not set:
return False
if not cmds.attributeQuery('Blend_Node', ex = True, n = set):
return False
if BT_IsSetupConnected(set = set):
cmds.warning('Disconnect setup first!')
return False
blendNode = cmds.getAttr(set +'.Blend_Node')
if not cmds.objExists(blendNode) or not cmds.objExists(set):
return False
if cmds.attributeQuery(prefixedPoseName, ex = True, n = set):
return False
transforms = cmds.listConnections(set +'.dagSetMembers')
numTransforms = len(transforms)
poseIndex = cmds.getAttr(blendNode +'.transforms[0].poses', size = True)
if index is not None:
poseIndex = index
if index is None:
cmds.addAttr(set, ln = prefixedPoseName, nn = poseName, k = True, min = 0, max = 1.0, at = 'double')
# print ('Num poses = ' +str(numPoses))
for i in range(0, numTransforms):
#get the base matrix
baseScale = cmds.getAttr(blendNode +'.transforms[' +str(i) +'].baseScale')[0]
baseMatrix = cmds.getAttr(blendNode +'.transforms[' +str(i) +'].baseMatrix')
#store the scale and set it
transformScale = cmds.getAttr(transforms[i] +'.scale')[0]
#set the scale back to 1.0
cmds.setAttr(transforms[i] +'.scale', 1.0, 1.0, 1.0, type = 'double3')
transformMatrix = cmds.xform(transforms[i], q = True, m = True)
poseMatrix = [x-y for x, y in zip(transformMatrix, baseMatrix)]
poseScale = [x-y for x, y in zip(transformScale, baseScale)]
#set the scale back to what the user had it at
cmds.setAttr(transforms[i] +'.scale', transformScale[0], transformScale[1], transformScale[2], type = 'double3')
cmds.setAttr(blendNode +'.transforms[' +str(i) +'].poses[' +str(poseIndex) +'].matrix', poseMatrix, type = 'matrix')
BT_Double3ValuesToNode(values = poseScale, node = blendNode, attr = 'transforms[' +str(i) +'].poses[' +str(poseIndex) +'].scale' )
if index is None:
cmds.connectAttr(set +'.' +prefixedPoseName, blendNode +'.transforms[' +str(i) +'].poses[' +str(poseIndex) +'].weight')
return True
def smartClose(*args):
name = cmds.textFieldGrp(widgets["nameTFG"], q=True, tx=True)
upSuf = cmds.textFieldGrp(widgets["upNameTFG"], q=True, tx=True)
dwnSuf = cmds.textFieldGrp(widgets["downNameTFG"], q=True, tx=True)
topMidCtrl = ctrlsUp[len(ctrlsUp)/2]
downMidCtrl = ctrlsUp[len(ctrlsDown)/2]
if len(lowResCurves)==2 and len(highResCurves)==2:
tmpCloseLow = cmds.duplicate(lowResCurves[0], n="{0}_closeLowTmpCrv".format(name))[0]
cmds.parent(tmpCloseLow, w=True)
tmpLowBS = cmds.blendShape(lowResCurves[0], lowResCurves[1], tmpCloseLow)[0]
tmpLowUpAttr = "{0}.{1}".format(tmpLowBS, lowResCurves[0])
tmpLowDwnAttr = "{0}.{1}".format(tmpLowBS, lowResCurves[1])
cmds.setAttr(tmpLowUpAttr, 0.5)
cmds.setAttr(tmpLowDwnAttr, 0.5)
closeLow = cmds.duplicate(tmpCloseLow, n="{0}_CLOSE_LOW_CRV".format(name))[0]
cmds.delete([tmpCloseLow, tmpLowBS])
lowBS = cmds.blendShape(lowResCurves[0], lowResCurves[1], closeLow)[0]
lowUpAttr = "{0}.{1}".format(lowBS, lowResCurves[0])
lowDwnAttr = "{0}.{1}".format(lowBS, lowResCurves[1])
#---------------- connect up down into reverse setup that drives lowclosecrv to go up/down
cmds.addAttr(topMidCtrl, ln="__xtraAttrs__", )
cmds.setAttr(lowUpAttr, 1)
cmds.setAttr(lowDwnAttr, 0)
closeUpHigh = cmds.duplicate(highResCurves[0], n="{0}_HI_{1}_CLOSE_CRV".format(name, upSuf.upper() ))[0]
cmds.parent(closeUpHigh, w=True)
upHighWire = cmds.wire(closeUpHigh, en=1, gw=True, ce=0, li=0, w=closeLow, name = "{0}_CLS_UP_WIRE".format(name))[0]
wireUpBaseCrv = "{0}BaseWire".format(closeLow)
cmds.setAttr("{0}.scale[0]".format(upHighWire), 0)
#---------------- set up blend shape on high res curve (drive high res with wire driven curve)
#---------------- set up the center ctrl to drive this BS
cmds.setAttr(lowUpAttr, 0)
cmds.setAttr(lowDwnAttr, 1)
closeDwnHigh = cmds.duplicate(highResCurves[1], n="{0}_HI_{1}_CLOSE_CRV".format(name, dwnSuf.upper() ))[0]
cmds.parent(closeDwnHigh, w=True)
dwnHighWire = cmds.wire(closeDwnHigh, en=1, gw=True, ce=0, li=0, w=closeLow, name = "{0}_CLS_DWN_WIRE".format(name))[0]
wireDwnBase = "{0}BaseWire".format(closeLow)
cmds.setAttr("{0}.scale[0]".format(dwnHighWire), 0)
#---------------- set up blend shape on high res curve (drive high res with wire driven curve)
#---------------- set up the center ctrl to drive this BS
def curve_CV_controls_execute(crv, *args):
"""
takes given curve and makes a ctrl for each cv. Then connects the matrix of the control directly to the point
position of the cv. Basically hijacking the shape node, more or less. If there's a parent to the curve,
will put whole rig under that and turn off inherit transforms for the crv itself.
puts an attr called 'controlScale' on the group controls are under to scale size of controls
Args:
crv: string - name of given curve
*args:
Returns:
Void
"""
par = cmds.listRelatives(crv, p=True)
ctrlGrps = []
cvs = cmds.ls("{0}.cv[*]".format(crv), fl=True)
xformGrp = cmds.group(empty=True, name="{0}_ctrl_GRP".format(crv))
cmds.addAttr(xformGrp, ln="controlScale", at="float", min=0.01, max=100, dv=1.0, k=True)
for x in range(0, len(cvs)):
pos = cmds.pointPosition(cvs[x])
shp = cmds.listRelatives(crv, s=True)[0]
ctrl = rig.createControl(type="sphere", name="{0}_{1}_CTRL".format(crv, x), color="red")
grp = rig.groupFreeze(ctrl)
cmds.connectAttr("{0}.controlScale".format(xformGrp), "{0}.sx".format(ctrl))
cmds.connectAttr("{0}.controlScale".format(xformGrp), "{0}.sy".format(ctrl))
cmds.connectAttr("{0}.controlScale".format(xformGrp), "{0}.sz".format(ctrl))
cmds.setAttr("{0}.scale".format(ctrl), l=True, k=False)
cmds.xform(grp, ws=True, t=pos)
dm = cmds.shadingNode("decomposeMatrix", asUtility=True,name="{0}_{1}_DM".format(crv, x))
cmds.connectAttr("{0}.worldMatrix[0]".format(ctrl), "{0}.inputMatrix".format(dm))
cmds.connectAttr("{0}.outputTranslate".format(dm), "{0}.controlPoints[{1}]".format(shp, x))
ctrlGrps.append(grp)
cmds.xform(xformGrp, ws=True, t=(cmds.xform(crv, ws=True, q=True, rp=True)))
cmds.xform(xformGrp, ws=True, ro=(cmds.xform(crv, ws=True, q=True, ro=True)))
cmds.xform(xformGrp, s=(cmds.xform(crv, q=True, r=True, s=True)))
if par:
inhGrp = cmds.group(empty=True, name="noInherit_{0}_GRP".format(crv))
cmds.parent(xformGrp, par[0])
cmds.parent(inhGrp, par[0])
cmds.parent(crv, inhGrp)
cmds.setAttr("{0}.inheritsTransform".format(inhGrp), 0)
cmds.parent(ctrlGrps, xformGrp)
cmds.xform(crv, ws=True, t=(0,0,0))
cmds.xform(crv, ws=True, ro=(0,0,0))
cmds.xform(crv, a=True, s=(1,1,1))
def zbw_mmConnectM(*args):
"""
uses the items from the textFields to create message attrs in the base obj, and connects to those the objs from the rightmost fields of the UI
"""
#check there's a base obj
if (cmds.textFieldButtonGrp("zbw_tfbg_baseObj", q=True, tx=True)):
#check there are any fields created
if (cmds.rowColumnLayout("mmRCLayout", q=True, ca=True)):
children = cmds.rowColumnLayout("mmRCLayout", q=True, ca=True)
numObj = (len(children)/2)
if numObj:
for num in range(1, numObj+1):
attrTFG = "attr" + str(num)
objTFBG = "obj" + str(num)
baseObj = cmds.textFieldButtonGrp("zbw_tfbg_baseObj", q=True, tx=True)
targetObj = cmds.textFieldButtonGrp(objTFBG, q=True, tx=True)
baseAttr = cmds.textFieldGrp(attrTFG, q=True, tx=True)
baseMAttr = baseObj + "." + baseAttr
objMAttr = targetObj + ".message"
#check to make sure there's something in each field, otherwise skip
if baseAttr and targetObj:
#check that attr doesnt' already exist with connection
if (cmds.attributeQuery(baseAttr, n=baseObj, ex=True)):
#delete the attr that exists, print note about it
cmds.deleteAttr(baseMAttr)
cmds.warning(baseMAttr + " already exists! Deleting for overwrite and reconnection")
cmds.addAttr(baseObj, at="message", ln=baseAttr)
cmds.connectAttr(objMAttr, baseMAttr, f=True)
#print confirmation of connection
print("Connected: "+ objMAttr +"--->"+ baseMAttr)
else:
cmds.warning("Line # " + str(num) + " was empty! Skipped that attr")
#leave a text field saying that it's done
zbw_mmDeleteConfirm()
cmds.separator("mmConfirmSep", h=20, st="single", p="mmAddNewConnections")
cmds.text("mmTextConfirm", l="MESSAGES MAPPED!", p="mmAddNewConnections")
else:
cmds.warning("Please create some attrs and objs to connect to base obj!")
else:
cmds.warning("Please choose a base object to add attrs to!")
def containerise(name,
namespace,
nodes,
context,
loader=None,
suffix="CON"):
"""Bundle `nodes` into an assembly and imprint it with metadata
Containerisation enables a tracking of version, author and origin
for loaded assets.
Arguments:
name (str): Name of resulting assembly
namespace (str): Namespace under which to host container
nodes (list): Long names of nodes to containerise
context (dict): Asset information
loader (str, optional): Name of loader used to produce this container.
suffix (str, optional): Suffix of container, defaults to `_CON`.
Returns:
container (str): Name of container assembly
"""
container = cmds.sets(nodes, name="%s_%s_%s" % (namespace, name, suffix))
data = [
("schema", "avalon-core:container-2.0"),
("id", "pyblish.avalon.container"),
("name", name),
("namespace", namespace),
("loader", str(loader)),
("representation", context["representation"]["_id"]),
]
for key, value in data:
if not value:
continue
if isinstance(value, (int, float)):
cmds.addAttr(container, longName=key, attributeType="short")
cmds.setAttr(container + "." + key, value)
else:
cmds.addAttr(container, longName=key, dataType="string")
cmds.setAttr(container + "." + key, value, type="string")
main_container = cmds.ls(AVALON_CONTAINERS, type="objectSet")
if not main_container:
main_container = cmds.sets(empty=True, name=AVALON_CONTAINERS)
else:
main_container = main_container[0]
cmds.sets(container, addElement=main_container)
return container
def imprint(node, data):
"""Write `data` to `node` as userDefined attributes
Arguments:
node (str): Long name of node
data (dict): Dictionary of key/value pairs
Example:
>>> from maya import cmds
>>> def compute():
... return 6
...
>>> cube, generator = cmds.polyCube()
>>> imprint(cube, {
... "regularString": "myFamily",
... "computedValue": lambda: compute()
... })
...
>>> cmds.getAttr(cube + ".computedValue")
6
"""
for key, value in data.items():
if callable(value):
# Support values evaluated at imprint
value = value()
if isinstance(value, bool):
add_type = {"attributeType": "bool"}
set_type = {"keyable": False, "channelBox": True}
elif isinstance(value, basestring):
add_type = {"dataType": "string"}
set_type = {"type": "string"}
elif isinstance(value, int):
add_type = {"attributeType": "long"}
set_type = {"keyable": False, "channelBox": True}
elif isinstance(value, float):
add_type = {"attributeType": "double"}
set_type = {"keyable": False, "channelBox": True}
else:
raise TypeError("Unsupported type: %r" % type(value))
cmds.addAttr(node, longName=key, **add_type)
cmds.setAttr(node + "." + key, value, **set_type)