def add_curve_to_system(curve_shape, hair_system=None):
if hair_system is None:
selection = cmds.ls(sl=True, dag=True, leaf=True, type='hairSystem')
if selection:
hair_system = selection[0]
else:
hair_system = create_hair_system()
follicle_nodes, out_curve_nodes = curve_to_hair(curve_shape, hair_system)
follicles_grp = hair_system + 'Follicles'
if not cmds.objExists(follicles_grp):
cmds.group(empty=True, name=follicles_grp)
cmds.parent(follicle_nodes[0], follicles_grp)
outcurves_grp = hair_system + 'OutputCurves'
if not cmds.objExists(outcurves_grp):
cmds.group(empty=True, name=outcurves_grp)
cmds.parent(out_curve_nodes[0], outcurves_grp)
return follicle_nodes
python类group()的实例源码
def insertGroupAbove(*args):
sel = cmds.ls(sl=True)
for obj in sel:
par = cmds.listRelatives(obj, p=True)
grp = cmds.group(em=True, n="{}_Grp".format(obj))
# grp = nameCheck(grp)
pos = cmds.xform(obj, q=True, ws=True, rp=True)
rot = cmds.xform(obj, q=True, ws=True, ro=True)
cmds.xform(grp, ws=True, t=pos)
cmds.xform(grp, ws=True, ro=rot)
cmds.parent(obj, grp)
if par:
cmds.parent(grp, par[0])
def groupOrient(target='none',orig='none', group="GRP"):
"""
groups the second object and snaps the group to the second (point and orient). The group arg is to name the suffix you want the group to have (default is '_GRP')
Arguments: target (to be constrained to), orig (obj to move), group (suffix for group)
"""
if (target == "none"):
sel = getTwoSelection()
target = sel[0]
orig = sel[1]
cmds.select(orig)
grpName = "%s_%s"%(orig,group)
cmds.group(name=grpName)
pc = cmds.pointConstraint(target, grpName)
oc = cmds.orientConstraint(target, grpName)
cmds.delete(pc)
cmds.delete(oc)
cmds.select(clear=True)
return(grpName)
def addGroupAbove(obj="none", suff="none", *args):
"""name of existing obj, new group suffix. New group will be oriented to the object BELOW it"""
#FIX THE OBJ, SUFIX TO BE EITHER SELECTED OR ENTERED
sel = cmds.ls(sl=True, type = "transform")
for obj in sel:
suff = "_new"
name = obj + suff + "_GRP"
#get worldspace location of existing obj
loc = cmds.xform(obj, q=True, ws=True, rp=True)
#create new group, name it, move it to new postion in ws and Orient it
grp = cmds.group(empty=True, name=name)
cmds.move(loc[0], loc[1], loc[2], grp, ws=True)
oc = cmds.orientConstraint(obj, grp)
cmds.delete(oc)
#check if there's a parent to the old group
par = cmds.listRelatives(obj, p=True)
print(par)
if par:
cmds.parent(grp, par)
cmds.parent(obj, grp)
def addGroupBelow(*args):
############----------fix lots of stuff here, but basic idea works
sel = cmds.ls(sl=True)
for obj in sel:
pos = cmds.xform(obj, ws=True, q=True, rp=True)
rot = cmds.xform(obj, ws=True, q=True, ro=True)
children = cmds.listRelatives(obj, children=True)
grp = cmds.group(em=True, name=obj.replace("Auto", "Manual"))
cmds.xform(grp, ws=True, t=pos)
cmds.xform(grp, ws=True, ro=rot)
cmds.parent(grp, obj)
for child in children:
cmds.parent(child, grp)
def insertGroupAbove(obj, *args):
par = cmds.listRelatives(obj, p=True)
grp = cmds.group(em=True, n="{}_Grp".format(obj))
# grp = nameCheck(grp)
pos = cmds.xform(obj, q=True, ws=True, rp=True)
rot = cmds.xform(obj, q=True, ws=True, ro=True)
cmds.xform(grp, ws=True, t=pos)
cmds.xform(grp, ws=True, ro=rot)
cmds.parent(obj, grp)
if par:
cmds.parent(grp, par[0])
return(grp)
def modelSequenceUI(*args):
if (cmds.window("modSeq", exists=True)):
cmds.deleteUI("modSeq")
widgets["win"] = cmds.window("modSeq", w = 300, h = 220, t = "zbw_modelSequence")
widgets["mainCLO"] = cmds.columnLayout(w = 300,h = 220)
cmds.separator(h=10)
cmds.text("Select ONE object to be duplicated \nThis will duplicate it for frames selected and group", al="left")
cmds.separator(h=20)
#textFieldGRP - name of objs
widgets["sufTFG"] = cmds.textFieldGrp(l="Sequence Suffix:", cw = [(1, 100), (2,200)], cal = [(1, "left"),(2, "right")])
#radioButtonGrp - timeslider or frame range
widgets["frmRBG"] = cmds.radioButtonGrp(l="Get Frames From:", nrb=2, sl=2, l1="Time Slider", l2="Frame Range", cw = [(1, 120), (2,80), (3,80)], cal = [(1, "left"),(2, "left")], cc=enableFR)
#textFieldGrp - framerange (enable)
widgets["frmRngIFG"] = cmds.intFieldGrp(l="Range:", nf=2, en=True, v1=0, v2 = 9, cw = [(1, 120), (2,80), (3,80)], cal = [(1, "left"),(2, "left")])
#int = by frame step
widgets["stepIFG"] = cmds.intFieldGrp(l="Step By (frames):", v1 = 1, cw = [(1, 120), (2,80)], cal = [(1, "left"),(2, "right")])
cmds.separator(h=30)
widgets["doBut"] = cmds.button(l="Create duplicates of objects!", w= 300, h=40, bgc = (0,.8, 0), c=getValues)
cmds.showWindow(widgets["win"])
def makeSequence(obj = "", name = "", frameStart = 0, frameEnd = 1, step = 1):
"""duplicate selected geo based on settings from UI"""
dupes = []
numCopies = (frameEnd-frameStart)/step
#check here if we want to create more than 25 duplicates?
confirm = cmds.confirmDialog(t="Confirm", m= "This will create %d copies of %s. \nFrames: %d to %d\nFor dense meshes, this could get heavy\nAre you sure you want to do this?"%(numCopies, obj, frameStart, frameEnd), button = ["Yes", "No"], cancelButton = "No")
if confirm == "Yes":
for frame in range(frameStart, frameEnd + 1, step):
cmds.currentTime(frame, edit=True)
dupe = cmds.duplicate(obj, n="%s_%d"%(name, frame), ic = False, un = False)
dupes.append(dupe)
if dupes:
grp = cmds.group(em = True, n = "%s_GRP"%name)
for dupe in dupes:
cmds.parent(dupe, grp)
#cmds.currentTime(currentFrame, e=True)
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 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)
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_arrow(jointName):
curve = cmds.curve(name='%s_ForwardDirection' % jointName, degree=1, point=[(-1, 0, 0), (-1, 2, 0), (-2, 2, 0), (0, 4, 0), (2, 2, 0), (1, 2, 0), (1, 0, 0), (-1, 0, 0)])
group = cmds.group()
cmds.xform(objectSpace=True, pivots=(0, 0, 0))
jointScale = cmds.jointDisplayScale(query=True)
jointRadius = cmds.getAttr('%s.radius' % jointName)
jointScale *= jointRadius
cmds.xform(scale=(jointScale, jointScale, jointScale))
return group
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 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 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 control(type="none", *args):
"""gets teh name from the button pushed and the axis from the radio button group"""
axisRaw = cmds.radioButtonGrp(widgets["ctrlAxisRBG"], q=True, sl=True)
if axisRaw == 1:
axis = "x"
if axisRaw == 2:
axis = "y"
if axisRaw == 3:
axis = "z"
rig.createControl(name = "Ctrl", type = type, axis = axis, color = "yellow")
def groupFreeze(*args):
"""group freeze an obj"""
sel = cmds.ls(sl=True, type="transform")
for obj in sel:
rig.groupFreeze(obj)
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 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 clearArcs(*args):
'''
Simply deletes the arc group by name.
'''
try:
mc.delete('ml_arcGroup')
except StandardError:
pass
def bakeCenterOfMass(*args):
'''
Bake root animation to center of mass.
'''
sel = mc.ls(sl=True)
if not len(sel) == 1:
raise RuntimeError('Please select the root control of your puppet.')
root, com = getRootAndCOM(sel[0])
if not root:
root = sel[0]
if not com:
com = createCenterOfMass()
start, end = utl.frameRange()
with utl.IsolateViews():
mc.bakeResults(com, time=(start,end), sampleBy=1, attribute=['tx','ty','tz'], simulation=True)
rootOffset = mc.group(em=True, name='rootOffset')
rootOffset = mc.parent(rootOffset, com)[0]
#bake
utl.matchBake(source=[root],
destination=[rootOffset],
bakeOnOnes=True,
maintainOffset=False,
preserveTangentWeight=False,
translate=True,
rotate=True)
mc.cutKey(root, attribute=['tx','ty','tz','rx','ry','rz'])
mc.parentConstraint(rootOffset, root)
mc.select(com)
def doEditPivotDriver(self, *args):
newValue = mc.floatSliderButtonGrp(self.floatSlider, query=True, value=True)
try:
mc.deleteUI(self.pivotDriverWindow)
except:
pass
currentValue = mc.getAttr(self.pivotDriver)
if newValue == currentValue:
return
oldRP = mc.getAttr(self.node+'.rotatePivot')[0]
mc.setAttr(self.pivotDriver, newValue)
newRP = mc.getAttr(self.node+'.rotatePivot')[0]
mc.setAttr(self.pivotDriver, currentValue)
parentPosition = mc.group(em=True)
offsetPosition = mc.group(em=True)
offsetPosition = mc.parent(offsetPosition, parentPosition)[0]
mc.setAttr(offsetPosition+'.translate', newRP[0]-oldRP[0], newRP[1]-oldRP[1], newRP[2]-oldRP[2])
mc.delete(mc.parentConstraint(self.node, parentPosition))
utl.matchBake(source=[self.node], destination=[parentPosition], bakeOnOnes=True, maintainOffset=False, preserveTangentWeight=False)
mc.cutKey(self.pivotDriver)
mc.setAttr(self.pivotDriver, newValue)
mc.refresh()
utl.matchBake(source=[offsetPosition], destination=[self.node], bakeOnOnes=True, maintainOffset=False, preserveTangentWeight=False, rotate=False)
mc.delete(parentPosition)
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 __init__(self, curve_sel, vertex_list, chain_geo):
self.curve_sel = curve_sel
self.verts = vertex_list
self.chain_geo = chain_geo
self.find_length = Find_Out()
self.link_length = self.find_length.edge_length(self.verts)
self.chain_length = self.find_length.curve_length(self.curve_sel)
self.link_total = int(self.chain_length/self.link_length)
self.motion_path_name = str(self.chain_geo) + '_Path'
cmds.pathAnimation(self.chain_geo, name = self.motion_path_name, fractionMode = True, follow= True, followAxis = 'x',
upAxis = 'y', worldUpType = 'object', startTimeU = 1, endTimeU = self.link_total, c = self.curve_sel)
cmds.setKeyframe(self.motion_path_name + '.frontTwist', v = 0.0, t = 1 )
cmds.setKeyframe(self.motion_path_name + '.frontTwist', v = 60.0*self.link_total, t = self.link_total )
cmds.keyTangent(self.motion_path_name + '.uValue', itt = 'linear', ott = 'linear' )
cmds.keyTangent(self.motion_path_name + '.frontTwist', itt = 'linear', ott = 'linear')
cmds.snapshot( self.chain_geo, constructionHistory=True, startTime=1, endTime = self.link_total, increment=1, update = 'animCurve',
name = str(self.chain_geo) + '_snapShot' )
self.chain_group = cmds.group( em=True, name=str(self.chain_geo) + '_geo_grp' )
self.chain_list = cmds.listRelatives(str(self.chain_geo + '_snapShotGroup'))
for dummy_geo in self.chain_list:
cmds.delete(icn = True, ch = True)
cmds.parent(dummy_geo, self.chain_group)
def test_modeling():
"""Modeling workflow is functional"""
transform, generator = cmds.polyCube(name="body_PLY")
group = cmds.group(transform, name="ROOT")
cmds.select(group, replace=True)
maya.create(
name="modelDefault",
asset=ASSET_NAME,
family="mindbender.model",
options={"useSelection": True}
)
# Comply with save validator
cmds.file(save=True)
publish()
asset = io.find_one({
"type": "asset",
"name": ASSET_NAME
})
assert asset
subset = io.find_one({
"parent": asset["_id"],
"type": "subset",
"name": "modelDefault"
})
assert subset
version = io.find_one({
"parent": subset["_id"],
"type": "version",
})
assert version
assert io.find_one({
"parent": version["_id"],
"type": "representation",
"name": "ma"
}) is not None
def test_update():
"""Updating works"""
transform, generator = cmds.polyCube(name="body_PLY")
group = cmds.group(transform, name="ROOT")
cmds.select(group, replace=True)
maya.create(
name="modelDefault",
asset=ASSET_NAME,
family="mindbender.model",
options={"useSelection": True}
)
# Comply with save validator
cmds.file(save=True)
publish()
publish()
publish() # Version 3
cmds.file(new=True, force=True)
asset = io.find_one({
"type": "asset",
"name": ASSET_NAME
})
subset = io.find_one({
"parent": asset["_id"],
"type": "subset",
"name": "modelDefault"
})
version = io.find_one({
"parent": subset["_id"],
"type": "version",
"name": 2
})
assert version
representation = io.find_one({
"parent": version["_id"],
"type": "representation",
"name": "ma"
})
maya.load(representation["_id"])
container = next(maya.ls())
maya.update(container, 3)
def rebuild_joints(*args):
if not cmds.objExists(ORIENT_GROUP):
return
nodes = cmds.listRelatives(ORIENT_GROUP, ad=True, path=True) or []
joints = []
for node in nodes:
attrs = cmds.listAttr(node, ud=True) or []
if MESSAGE_ATTRIBUTE not in attrs:
continue
joint = cmds.listConnections('{0}.{1}'.format(node, MESSAGE_ATTRIBUTE), d=False)[0]
joints.append(joint)
rotation = cmds.getAttr('{0}.rx'.format(node))
children = cmds.listRelatives(joint, children=True, shapes=False, path=True)
if children:
# First unparent children so change in joint orient does not affect children
children = [cmds.parent(child, world=True)[0] for child in children]
# Add rotation offset to joint orient
orient_x = cmds.getAttr('{0}.jointOrientX'.format(joint))
orient_x += rotation
while orient_x > 180.0:
orient_x -= 360.0
while orient_x < -180.0:
orient_x += 360.0
cmds.setAttr('{0}.jointOrientX'.format(joint), orient_x)
# Reparent child
for child in children:
cmds.parent(child, joint)
else:
# tip joint, just zero out joint orient
cmds.setAttr('%s.jointOrientX' % joint, 0)
cmds.setAttr('%s.jointOrientY' % joint, 0)
cmds.setAttr('%s.jointOrientZ' % joint, 0)
# Untemplate
cmds.setAttr('{0}.template'.format(joint), 0)
# Delete arrow group
cmds.delete(ORIENT_GROUP)
cmds.select(joints)
def create_joint(cvs, wts):
tform = cvs[0].partition(".")[0]
curve = cmds.listRelatives(tform, f=True, s=True)[0]
ps = []
center = []
for cv in cvs:
ps.append(cmds.pointPosition(cv))
center = [sum(y)/len(y) for y in zip(*ps)]
#create joint at location
# ----------- should get closest point on surface
cmds.select(cl=True)
jnt = cmds.joint()
cmds.xform(jnt, ws=True, t=center)
#---------------- orient the joint along the curve?
#---------------- here create the ctrl set up for the joint
ctrl = rig.createControl(name="{0}Ctrl".format(jnt), type="sphere", color="red")
grp = cmds.group(name="{0}Grp".format(ctrl), em=True)
cmds.parent(ctrl, grp)
cmds.xform(grp, ws=True, t=center)
cmds.parent(jnt, ctrl)
# scale the control
comps = cmds.ls("{0}.cv[*]".format(ctrl))
cmds.select(comps, r=True)
cmds.scale(.2,.2,.2)
#add influence to skin Cluster
cmds.select(tform, r=True)
cmds.skinCluster(e=True, ai=jnt, wt=0)
cmds.setAttr("{0}.v".format(jnt), 0)
#apply weights to that joint
cls = mel.eval("findRelatedSkinCluster " + tform)
for v in range(len(cvs)):
cmds.skinPercent(cls, cvs[v], transformValue=[jnt, wts[v]])
return(jnt, ctrl, grp)
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))