<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://berniebernie.fr/mediawiki-1.37.1/index.php?action=history&amp;feed=atom&amp;title=Maya_Python</id>
	<title>Maya Python - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://berniebernie.fr/mediawiki-1.37.1/index.php?action=history&amp;feed=atom&amp;title=Maya_Python"/>
	<link rel="alternate" type="text/html" href="https://berniebernie.fr/mediawiki-1.37.1/index.php?title=Maya_Python&amp;action=history"/>
	<updated>2026-05-22T19:40:31Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.37.1</generator>
	<entry>
		<id>https://berniebernie.fr/mediawiki-1.37.1/index.php?title=Maya_Python&amp;diff=633&amp;oldid=prev</id>
		<title>Bernie: /* Convert Curve Vertices to Joints */</title>
		<link rel="alternate" type="text/html" href="https://berniebernie.fr/mediawiki-1.37.1/index.php?title=Maya_Python&amp;diff=633&amp;oldid=prev"/>
		<updated>2022-11-29T11:45:25Z</updated>

		<summary type="html">&lt;p&gt;&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;Convert Curve Vertices to Joints&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;== Select Constraint Parents from Constrained Object ==&lt;br /&gt;
Should work on any constraint type, not tested extensively&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import maya.cmds as mc&lt;br /&gt;
parents = []&lt;br /&gt;
constraints = mc.listConnections(mc.ls(sl=1),s=1,type=&amp;quot;constraint&amp;quot;)&lt;br /&gt;
constraints = list(set(constraints ))&lt;br /&gt;
for constraint in constraints:&lt;br /&gt;
    cmd = &amp;quot;mc.&amp;quot;+mc.nodeType(constraint) + &amp;quot;(&amp;#039;&amp;quot; + constraint + &amp;quot;&amp;#039;,q=1,tl=1)&amp;quot;&lt;br /&gt;
    for target in eval(cmd):&lt;br /&gt;
        parents.append(target)&lt;br /&gt;
mc.select(parents,r=1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Convert Curve Vertices to Joints == &lt;br /&gt;
1 CV = 1 joint, works with objects that have multiple shapes, parents resulting joints (for an IKspline), orients along X.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#joint chain from curve(s) cvs, orient X up&lt;br /&gt;
import maya.cmds as cmds&lt;br /&gt;
&lt;br /&gt;
myCurve = cmds.ls(selection=True)&lt;br /&gt;
for item in myCurve:&lt;br /&gt;
    shapes = cmds.listRelatives(item,s=1,f=1)&lt;br /&gt;
    for shape in shapes:&lt;br /&gt;
        cmds.select(cl=True)&lt;br /&gt;
        jointN = 0&lt;br /&gt;
        jointChain = []&lt;br /&gt;
        cvs = cmds.ls(&amp;#039;%s.cv[:]&amp;#039;%shape, fl=True)&lt;br /&gt;
       &lt;br /&gt;
        for cv in cvs:&lt;br /&gt;
            jointN = jointN + 1&lt;br /&gt;
            [x,y,z] = cmds.xform(cv,t=1,q=1,ws=1)&lt;br /&gt;
            j = cmds.joint(n=&amp;#039;%s_jnt%s&amp;#039;%(shape,jointN),p=(x,y,z))&lt;br /&gt;
            jointChain.append(j)&lt;br /&gt;
        for j in jointChain[:-1]:&lt;br /&gt;
            cmds.joint(j,e=1,oj=&amp;#039;xyz&amp;#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ikSpline&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import maya.cmds as cmds&lt;br /&gt;
&lt;br /&gt;
curveAndJnt = cmds.ls(sl=1)&lt;br /&gt;
&lt;br /&gt;
curvOb = curveAndJnt[0]&lt;br /&gt;
first = curveAndJnt[1]&lt;br /&gt;
last = cmds.listRelatives(first,ad=1)[0]&lt;br /&gt;
&lt;br /&gt;
cmds.select([first,last,curvOb],r=1)&lt;br /&gt;
&lt;br /&gt;
handle = cmds.ikHandle(sol=&amp;#039;ikSplineSolver&amp;#039;,ccv=False,roc=False,pcv=False)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Export Camera to World ==&lt;br /&gt;
copies selected cameras to world with parent constraints so you can bake them with alembic&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import maya.cmds as mc&lt;br /&gt;
&lt;br /&gt;
for cameras in mc.ls(sl=1):&lt;br /&gt;
&lt;br /&gt;
    selection = cameras&lt;br /&gt;
    cam = mc.duplicate(selection)[0]&lt;br /&gt;
    #unlock transforms&lt;br /&gt;
    for item in [&amp;#039;tx&amp;#039;,&amp;#039;ty&amp;#039;,&amp;#039;tz&amp;#039;,&amp;#039;rx&amp;#039;,&amp;#039;ry&amp;#039;,&amp;#039;rz&amp;#039;,&amp;#039;sx&amp;#039;,&amp;#039;sy&amp;#039;,&amp;#039;sz&amp;#039;]:&lt;br /&gt;
        mc.setAttr(cam+&amp;#039;.&amp;#039;+item,lock=0)   &lt;br /&gt;
    #delete children if any&lt;br /&gt;
    children = mc.listRelatives(cam,typ=&amp;quot;transform&amp;quot;,f=1)&lt;br /&gt;
    if children:&lt;br /&gt;
        mc.delete(children)&lt;br /&gt;
&lt;br /&gt;
    if mc.listRelatives(cam,parent=1):&lt;br /&gt;
        cam = mc.parent(cam,world=1)        &lt;br /&gt;
    mc.parentConstraint(selection,cam)&lt;br /&gt;
    &lt;br /&gt;
    camShape=mc.listRelatives(cam)[0]&lt;br /&gt;
    selectionShape=mc.listRelatives(selection)[0]&lt;br /&gt;
    for at in [&amp;#039;focalLength&amp;#039;,&amp;#039;focusDistance&amp;#039;,&amp;#039;centerOfInterest&amp;#039;,&amp;#039;shutterAngle&amp;#039;]:&lt;br /&gt;
        mc.connectAttr(selectionShape+&amp;#039;.&amp;#039;+at,camShape+&amp;#039;.&amp;#039;+at)&lt;br /&gt;
    cam = mc.rename(cam,selection)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Copy object and spread it along a path ==&lt;br /&gt;
&lt;br /&gt;
https://i.imgur.com/Ox8Ck6N.gif&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import maya.cmds as mc&lt;br /&gt;
&lt;br /&gt;
result = mc.promptDialog(&lt;br /&gt;
        title=&amp;#039;Copy along curve&amp;#039;,&lt;br /&gt;
        message=&amp;#039;Uses motionPath to spread copies of your first object on the second object selected (a path)\nThis means you can animate the curve. Check uVal attr on objects to displace along curve\n\nNumber of copies spread on curve:&amp;#039;,&lt;br /&gt;
        button=[&amp;#039;OK&amp;#039;, &amp;#039;Cancel&amp;#039;],&lt;br /&gt;
        defaultButton=&amp;#039;OK&amp;#039;,&lt;br /&gt;
        cancelButton=&amp;#039;Cancel&amp;#039;,&lt;br /&gt;
        tx=10,&lt;br /&gt;
        dismissString=&amp;#039;Cancel&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
if result == &amp;#039;OK&amp;#039;:&lt;br /&gt;
    count = int(mc.promptDialog(query=True, text=True))&lt;br /&gt;
    path = mc.ls(sl=1)[1]&lt;br /&gt;
    pathShp = mc.listRelatives(path,s=1)[0]&lt;br /&gt;
    profile = mc.ls(sl=1)[0]&lt;br /&gt;
    emGroup = mc.group(n=&amp;#039;copies&amp;#039;,em=1)&lt;br /&gt;
    &lt;br /&gt;
    for i in range(count):&lt;br /&gt;
        obj = mc.duplicate(profile,n=profile+&amp;#039;_copy&amp;#039;)[0]&lt;br /&gt;
        mc.addAttr(obj,ln=&amp;quot;uVal&amp;quot;)&lt;br /&gt;
        mc.setAttr(obj+&amp;#039;.uVal&amp;#039;,1.0*i/(count-1),e=1,k=1)&lt;br /&gt;
        mc.parent(obj,emGroup)&lt;br /&gt;
        pathA = mc.pathAnimation(obj,follow=True,fm=1,c=pathShp)&lt;br /&gt;
        mc.connectAttr(obj+&amp;#039;.uVal&amp;#039;,pathA+&amp;#039;.uValue&amp;#039;,f=1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Pop-up (HUD) slider to change channel box attribute speed ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import maya.cmds as mc&lt;br /&gt;
from math import pow&lt;br /&gt;
&lt;br /&gt;
def chboxspeed( HUD, *args ):&lt;br /&gt;
    v = mc.hudSliderButton( HUD, query=True, v=True )&lt;br /&gt;
    nv = pow(10,v)   &lt;br /&gt;
    mc.channelBox(&amp;quot;mainChannelBox&amp;quot;, edit=True, spd=nv)&lt;br /&gt;
    if nv &amp;lt; 1.0:&lt;br /&gt;
        nv =  &amp;quot;%.6f&amp;quot; % nv&lt;br /&gt;
    else:&lt;br /&gt;
        nv = int(nv)&lt;br /&gt;
    mc.hudSliderButton( HUD, e=True, sl=nv )&lt;br /&gt;
    if len(args)&amp;gt;0:&lt;br /&gt;
        mc.channelBox(&amp;quot;mainChannelBox&amp;quot;, edit=True, spd=chboxspeedvalue)&lt;br /&gt;
        mc.headsUpDisplay(&amp;#039;HUDchboxspeed&amp;#039;,rem=1)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
chboxspeedvalue = mc.channelBox(&amp;quot;mainChannelBox&amp;quot;, query=True, spd=1)&lt;br /&gt;
hud = mc.hudSliderButton( &amp;#039;HUDchboxspeed&amp;#039;, s=2, b=5, vis=True, sl=&amp;#039;speed&amp;#039;, value=0, type=&amp;#039;int&amp;#039;, min=-6, max=6, slw=50, vw=50, sln=100, si=1, bl=&amp;#039;reset&amp;amp;delete&amp;#039;, bw=80, bsh=&amp;#039;rectangle&amp;#039;,brc=lambda : chboxspeed( &amp;#039;HUDchboxspeed&amp;#039;,&amp;#039;delete&amp;#039; ), sdc=lambda : chboxspeed( &amp;#039;HUDchboxspeed&amp;#039; ))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reconnect motion paths ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039; reconnects selected objects with motion paths to a a given curve&lt;br /&gt;
select objects driven by motion path and path last &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
import maya.cmds as mc&lt;br /&gt;
&lt;br /&gt;
objs = mc.ls(sl=1,l=1)&lt;br /&gt;
curveShp = mc.listRelatives(objs[-1])[0]&lt;br /&gt;
&lt;br /&gt;
for o in objs[:-1]:&lt;br /&gt;
    mp = mc.listConnections(o+&amp;#039;.specifiedManipLocation&amp;#039;)[0]&lt;br /&gt;
    if mc.nodeType(o) == &amp;#039;motionPath&amp;#039;:&lt;br /&gt;
        mp = o&lt;br /&gt;
    if mc.nodeType(mp) == &amp;#039;motionPath&amp;#039;:&lt;br /&gt;
        mc.connectAttr(curveShp+&amp;#039;.worldSpace[0]&amp;#039;,mp+&amp;#039;.geometryPath&amp;#039;,f=1)&lt;br /&gt;
    else:&lt;br /&gt;
        warning(&amp;#039;\nNo motion path found on &amp;#039;+o)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Match translates and pivots ==&lt;br /&gt;
&lt;br /&gt;
Sets translates/rotates/scales and pivots of selected objects to the last selected object&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# sets the pivots and transforms of objects to last object of selection, using parents and freeze transforms&lt;br /&gt;
# remember to delete history&lt;br /&gt;
&lt;br /&gt;
import maya.cmds as mc&lt;br /&gt;
&lt;br /&gt;
objs = mc.ls(sl=1)&lt;br /&gt;
target = objs[-1]&lt;br /&gt;
&lt;br /&gt;
targetPivot = mc.xform(target,q=1,ws=1,rp=1)&lt;br /&gt;
&lt;br /&gt;
for o in objs[:-1]:&lt;br /&gt;
    parentObj = mc.listRelatives(o,parent=1)&lt;br /&gt;
    mc.parent(o,target)    &lt;br /&gt;
    mc.makeIdentity(o,a=1,)&lt;br /&gt;
    &lt;br /&gt;
    mc.xform(o,ws=1,rp=[targetPivot[0],targetPivot[1],targetPivot[2]])&lt;br /&gt;
    mc.xform(o,ws=1,sp=[targetPivot[0],targetPivot[1],targetPivot[2]])&lt;br /&gt;
    &lt;br /&gt;
    if parentObj:&lt;br /&gt;
        mc.parent(o,parentObj)&lt;br /&gt;
    else:&lt;br /&gt;
        mc.parent(o,w=1)&lt;br /&gt;
        &lt;br /&gt;
print(&amp;#039;You might need to delete histories&amp;#039;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== No-flip flow motion path object using curve normals ==&lt;br /&gt;
&lt;br /&gt;
Well, not really no-flip, but you can easily modify the motion path loft&lt;br /&gt;
&lt;br /&gt;
http://i.imgur.com/PX7bF1R.png&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#select object and curve and run code&lt;br /&gt;
&lt;br /&gt;
import maya.cmds as mc&lt;br /&gt;
&lt;br /&gt;
def curveOnSurfaceFromCurve(curveObj,offsetDistance=.5):&lt;br /&gt;
    offset1 = mc.offsetCurve(curveObj,ugn=0,d=offsetDistance)&lt;br /&gt;
    offset2 = mc.offsetCurve(curveObj,ugn=0,d=-offsetDistance)&lt;br /&gt;
    loftObj = mc.loft(offset1,offset2,u=1,ch=1)[0]&lt;br /&gt;
    loftShp = mc.listRelatives(loftObj,s=1)[0]&lt;br /&gt;
    v = mc.getAttr(loftShp+&amp;#039;.minMaxRangeV.maxValueV&amp;#039;)&lt;br /&gt;
    cOs = mc.curveOnSurface(loftObj,d=3,uv=((.5, 0),(0.5, 1*v/3), (0.5, 2*v/3), (0.5, v)))&lt;br /&gt;
    return cOs&lt;br /&gt;
&lt;br /&gt;
def motionPathWithNormalsAndFlow(object,motionPathCurve,useTimeline=True,flowSpans=10):&lt;br /&gt;
    mc.xform(object,a=True, ro=(0, 0, 0) )&lt;br /&gt;
    bbox = mc.xform(object,q=1,os=1,bb=1)&lt;br /&gt;
    axes = sorted([(bbox[3]-bbox[0],&amp;#039;x&amp;#039;,0),(bbox[4]-bbox[1],&amp;#039;y&amp;#039;,1),(bbox[5]-bbox[2],&amp;#039;z&amp;#039;,2)])&lt;br /&gt;
    if useTimeline:&lt;br /&gt;
        mc.pathAnimation(object,c=motionPathCurve,wut=&amp;quot;normal&amp;quot;,f=1,ua=axes[0][1],fa=axes[-1][1],fm=1,stu=mc.playbackOptions(q=1,minTime=1),etu=mc.playbackOptions(q=1,maxTime=1))&lt;br /&gt;
    else:   &lt;br /&gt;
        mc.pathAnimation(object,c=motionPathCurve,wut=&amp;quot;normal&amp;quot;,f=1,ua=axes[0][1],fa=axes[-1][1])&lt;br /&gt;
&lt;br /&gt;
    flowLatticeSides = [3,3,3]&lt;br /&gt;
    flowLatticeSides[axes[-1][2]] = flowSpans&lt;br /&gt;
    mc.flow(object,dv=flowLatticeSides)&lt;br /&gt;
&lt;br /&gt;
selectedCurve = mc.ls(sl=1,tl=1)&lt;br /&gt;
object = mc.ls(sl=1,hd=1)     &lt;br /&gt;
motionPathCurveOnSurface = curveOnSurfaceFromCurve(selectedCurve)&lt;br /&gt;
motionPathWithNormalsAndFlow(object,motionPathCurveOnSurface)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== zDepth control tool ==&lt;br /&gt;
http://i.imgur.com/4Jod4XJ.png&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import maya.cmds as mc&lt;br /&gt;
&lt;br /&gt;
def oneCurveGrid(rezx=10,rezy=10,scalex=1,scaley=1):&lt;br /&gt;
    &lt;br /&gt;
    points = []&lt;br /&gt;
&lt;br /&gt;
    sx = 1.0/(rezx-1)&lt;br /&gt;
    sy = 1.0/(rezy-1)&lt;br /&gt;
&lt;br /&gt;
    &lt;br /&gt;
    for i in range(rezx/2):&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
        for j in range(rezy):&lt;br /&gt;
            points.append( [ ( 2.0 * i * sx -.5 ) * scalex , ( j * sy -.5 ) * scaley ,0] )&lt;br /&gt;
        for j in reversed(range(rezy)):&lt;br /&gt;
            points.append( [ ( ( 2.0* i + 1) * sx -.5 ) * scalex ,( j * sy -.5 ) * scaley ,0])&lt;br /&gt;
            &lt;br /&gt;
    for i in range(rezy/2):  &lt;br /&gt;
        for j in reversed(range(rezx)):&lt;br /&gt;
            points.append( [ ( j * sx -.5 ) * scalex , ( i*2.0 * sy -.5 ) * scaley ,0])&lt;br /&gt;
        for j in range(rezx):&lt;br /&gt;
            points.append( [ ( j * sx -.5 ) * scalex , ( ( i*2.0+1) * sy -.5 ) * scaley ,0])&lt;br /&gt;
    &lt;br /&gt;
    for i in reversed(range(rezx)):&lt;br /&gt;
        points.append( [((i * sx -.5)*scalex) ,((i * sx -.5)*scaley), 0])&lt;br /&gt;
&lt;br /&gt;
    return points&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
def createZDistanceTool():&lt;br /&gt;
    &amp;#039;&amp;#039;&amp;#039;creates controllers to help with the focus distance. Plugs into &amp;#039;focusDistance&amp;#039; of camera shape&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    # choose cam &lt;br /&gt;
    &lt;br /&gt;
    selection = mc.ls(sl=True)&lt;br /&gt;
    &lt;br /&gt;
    chosenCamera = False&lt;br /&gt;
    &lt;br /&gt;
    if len(selection) &amp;gt; 0:&lt;br /&gt;
        selShp = (selection[0],mc.listRelatives(selection[0],s=True))[mc.nodeType(selection[0])==&amp;#039;transform&amp;#039;] #gives us the shape&lt;br /&gt;
        if mc.nodeType(selShp) == &amp;#039;camera&amp;#039;:&lt;br /&gt;
            chosenCamera = selShp&lt;br /&gt;
    else:&lt;br /&gt;
        currentPanel = mc.getPanel(withFocus=True)&lt;br /&gt;
        if mc.getPanel(typeOf=currentPanel) == &amp;#039;modelPanel&amp;#039;:&lt;br /&gt;
            chosenCamera = mc.modelPanel(currentPanel,q=True,cam=True)&lt;br /&gt;
            chosenCamera = mc.listRelatives(chosenCamera,s=True)&lt;br /&gt;
            &lt;br /&gt;
    if not chosenCamera:&lt;br /&gt;
        mc.warning(&amp;#039;Select camera or run in a perspective viewport&amp;#039;)    &lt;br /&gt;
    else:&lt;br /&gt;
        camObj = mc.listRelatives(chosenCamera,p=1)[0]&lt;br /&gt;
        camShape = chosenCamera[0]&lt;br /&gt;
        confirm  = mc.confirmDialog( title=&amp;#039;Confirm&amp;#039;, message=&amp;#039;Create z-depth controller for &amp;quot;&amp;#039;+camObj+&amp;#039;&amp;quot; ?&amp;#039;, button=[&amp;#039;Yes&amp;#039;,&amp;#039;No&amp;#039;], defaultButton=&amp;#039;Yes&amp;#039;, cancelButton=&amp;#039;No&amp;#039;, dismissString=&amp;#039;No&amp;#039; )&lt;br /&gt;
        if confirm == &amp;#039;Yes&amp;#039;:&lt;br /&gt;
    &lt;br /&gt;
            #spaghetti code below&lt;br /&gt;
            &lt;br /&gt;
            #floating locator system&lt;br /&gt;
            &lt;br /&gt;
            floatingZLoc = mc.curve(p=[[-0.319, -0.001, 0.0], [0.621, 0.94, 0.0], [-1.0, 0.94, 0.0], [-1.0, 1.06, 0.0], [1.392, 1.06, 0.0], [-0.608, -0.94, 0.0], [1.0, -0.94, 0.0], [1.0, -1.06, 0.0], [-1.379, -1.06, 0.0], [-0.319, -0.001, 0.0], [0.0, 0.0, 0.0], [-0.233, -0.233, -0.233], [0.233, 0.233, 0.233], [0.0, 0.0, 0.0], [-0.233, -0.233, 0.233], [0.233, 0.233, -0.233], [0.0, 0.0, 0.0], [-0.233, 0.233, -0.233], [0.233, -0.233, 0.233], [0.0, 0.0, 0.0], [0.233, -0.233, -0.233], [-0.233, 0.233, 0.233]],d=1,n=camObj+&amp;#039;_zDepth_FloatCtrl&amp;#039;)&lt;br /&gt;
            projCurve = mc.curve(p=[[0,0,0],[0,0,1000]],d=1,n=camObj+&amp;#039;_longCurve&amp;#039;)                    #create a curve to project our locator on&lt;br /&gt;
            pc = mc.parentConstraint(camObj,projCurve,mo=False)[0]                                    #curve follows camera&lt;br /&gt;
            mc.setAttr(pc+&amp;#039;.target[0].targetOffsetRotateY&amp;#039;,180)&lt;br /&gt;
            cameraLocator = mc.spaceLocator(n=camObj+&amp;#039;_camLocator&amp;#039;)[0]                                #locator on camera to get world position later&lt;br /&gt;
            mc.pointConstraint(camObj,cameraLocator,mo=False)&lt;br /&gt;
            floatingLocator = mc.spaceLocator(n=camObj+&amp;#039;_floatLocator&amp;#039;)[0]                            #locator to get floating controller world pos&lt;br /&gt;
            mc.parent(floatingLocator,floatingZLoc)&lt;br /&gt;
            projectionLocator = mc.spaceLocator(n=camObj+&amp;#039;_projLocator&amp;#039;)[0]                           #locator to project on curve&lt;br /&gt;
            &lt;br /&gt;
            nPoc = mc.createNode(&amp;#039;nearestPointOnCurve&amp;#039;)&lt;br /&gt;
            mc.connectAttr(mc.listRelatives(floatingLocator,s=True)[0]+&amp;#039;.worldPosition&amp;#039;,nPoc+&amp;#039;.inPosition&amp;#039;,f=True)&lt;br /&gt;
            mc.connectAttr(mc.listRelatives(projCurve,s=True)[0]+&amp;#039;.worldSpace&amp;#039;,nPoc+&amp;#039;.inputCurve&amp;#039;,f=True)&lt;br /&gt;
            mc.connectAttr(nPoc+&amp;#039;.position&amp;#039;,projectionLocator+&amp;#039;.translate&amp;#039;,f=True)&lt;br /&gt;
            &lt;br /&gt;
            db = mc.createNode(&amp;#039;distanceBetween&amp;#039;)&lt;br /&gt;
            mc.connectAttr(mc.listRelatives(projectionLocator,s=True)[0]+&amp;#039;.worldPosition&amp;#039;,db+&amp;#039;.point1&amp;#039;)&lt;br /&gt;
            mc.connectAttr(mc.listRelatives(cameraLocator,s=True)[0]+&amp;#039;.worldPosition&amp;#039;,db+&amp;#039;.point2&amp;#039;)&lt;br /&gt;
            &lt;br /&gt;
            #end result locator and grid&lt;br /&gt;
            &lt;br /&gt;
            resultLocator = mc.spaceLocator(n=camObj+&amp;#039;resultLocator&amp;#039;)[0]&lt;br /&gt;
            resultGrid = mc.curve(p=oneCurveGrid(14,8,3.84,2.16),d=1,n=camObj+&amp;#039;_resultGrid&amp;#039;)&lt;br /&gt;
            mc.setAttr(resultGrid+&amp;#039;.tz&amp;#039;,keyable=False,channelBox=False )&lt;br /&gt;
            mc.setAttr(resultGrid+&amp;#039;.visibility&amp;#039;,keyable=False,channelBox=False )&lt;br /&gt;
                  &lt;br /&gt;
            #camera based system&lt;br /&gt;
            &lt;br /&gt;
            cameraGrid = mc.curve(p=oneCurveGrid(28,16,8,4.5),d=1,n=camObj+&amp;#039;_zDepth_Ctrl&amp;#039;)           #create a grid to visualize standard focus distance z&lt;br /&gt;
            cameraGridNull = mc.group(em=True,n=camObj+&amp;#039;_zDepth_Ctrl_ZERO&amp;#039;)&lt;br /&gt;
            mc.parent(cameraGrid,cameraGridNull)&lt;br /&gt;
            mc.parent(resultLocator,cameraGridNull)&lt;br /&gt;
            mc.parent(resultGrid,cameraGridNull)&lt;br /&gt;
            pc2 = mc.parentConstraint(projCurve,cameraGridNull,mo=False)[0]&lt;br /&gt;
            &lt;br /&gt;
            &lt;br /&gt;
            #grab existing zdepth focus distance, with renderer specific options (maxwell for now)&lt;br /&gt;
            &lt;br /&gt;
            currentDistance = 5.0&lt;br /&gt;
            if mc.getAttr(&amp;quot;defaultRenderGlobals.currentRenderer&amp;quot;) == &amp;quot;maxwell&amp;quot;:&lt;br /&gt;
                currentDistance= mc.getAttr(camShape+&amp;quot;.mxFocusDistance&amp;quot;)&lt;br /&gt;
            else:&lt;br /&gt;
                currentDistance = mc.getAttr(camShape+&amp;#039;.focusDistance&amp;#039;)&lt;br /&gt;
            &lt;br /&gt;
            mc.setAttr(cameraGrid+&amp;#039;.tz&amp;#039;,currentDistance)&lt;br /&gt;
    &lt;br /&gt;
            #choice system&lt;br /&gt;
            &lt;br /&gt;
            sr = mc.createNode(&amp;#039;setRange&amp;#039;)&lt;br /&gt;
            sr2 = mc.createNode(&amp;#039;setRange&amp;#039;)&lt;br /&gt;
            &lt;br /&gt;
            mc.setAttr(sr+&amp;#039;.oldMaxX&amp;#039;,1)&lt;br /&gt;
            mc.setAttr(sr+&amp;#039;.oldMaxY&amp;#039;,1)&lt;br /&gt;
            mc.setAttr(sr+&amp;#039;.maxY&amp;#039;,0)&lt;br /&gt;
            mc.setAttr(sr+&amp;#039;.minY&amp;#039;,1)&lt;br /&gt;
            &lt;br /&gt;
            mc.setAttr(sr2+&amp;#039;.maxX&amp;#039;,1)&lt;br /&gt;
            mc.setAttr(sr2+&amp;#039;.maxY&amp;#039;,0)&lt;br /&gt;
            mc.setAttr(sr2+&amp;#039;.minY&amp;#039;,1)&lt;br /&gt;
            mc.setAttr(sr2+&amp;#039;.oldMaxX&amp;#039;,.001)&lt;br /&gt;
            mc.setAttr(sr2+&amp;#039;.oldMinY&amp;#039;,.999)&lt;br /&gt;
            mc.setAttr(sr2+&amp;#039;.oldMaxY&amp;#039;,1)&lt;br /&gt;
            &lt;br /&gt;
            mc.connectAttr(db+&amp;#039;.distance&amp;#039;,sr+&amp;#039;.maxX&amp;#039;,f=1)&lt;br /&gt;
            mc.connectAttr(cameraGrid+&amp;#039;.tz&amp;#039;,sr+&amp;#039;.minX&amp;#039;,f=1)           &lt;br /&gt;
            mc.connectAttr(sr+&amp;#039;.outValue.outValueX&amp;#039;,resultLocator+&amp;#039;.tz&amp;#039;,f=True)&lt;br /&gt;
            &lt;br /&gt;
                   &lt;br /&gt;
            arrow = mc.annotate(resultLocator,p=(0, 0, 0))&lt;br /&gt;
            arrowObj = mc.listRelatives(arrow,p=1)[0]&lt;br /&gt;
            arrowObj = mc.rename(arrowObj,camObj+&amp;#039;_zDistance&amp;#039;)&lt;br /&gt;
            arrow = mc.listRelatives(arrowObj,s=1)[0]&lt;br /&gt;
            mc.parent(arrowObj,cameraGridNull,r=True)&lt;br /&gt;
            &lt;br /&gt;
            md = mc.createNode(&amp;#039;multiplyDivide&amp;#039;)                                                      #ridiculous hack to force annoation update&lt;br /&gt;
            mc.connectAttr(camObj+&amp;#039;.tx&amp;#039;,md+&amp;#039;.input2.input2X&amp;#039;)&lt;br /&gt;
            mc.connectAttr(sr+&amp;#039;.outValue.outValueX&amp;#039;,md+&amp;#039;.input2.input2Y&amp;#039;)&lt;br /&gt;
            mc.connectAttr(floatingZLoc+&amp;#039;.tx&amp;#039;,md+&amp;#039;.input2.input2Z&amp;#039;)&lt;br /&gt;
            mc.connectAttr(md+&amp;#039;.output&amp;#039;,mc.listRelatives(arrow,p=1)[0]+&amp;#039;.translate&amp;#039;)&lt;br /&gt;
            &lt;br /&gt;
&lt;br /&gt;
            &lt;br /&gt;
            #mostly controls and cosmetic stuff&lt;br /&gt;
            &lt;br /&gt;
            for o in (projCurve,resultLocator,floatingLocator,projectionLocator,cameraLocator,pc2):&lt;br /&gt;
                mc.setAttr(o+&amp;#039;.visibility&amp;#039;,False)&lt;br /&gt;
    &lt;br /&gt;
            for o in (cameraGrid,arrowObj):&lt;br /&gt;
                for p in (&amp;#039;tx&amp;#039;,&amp;#039;ty&amp;#039;,&amp;#039;tz&amp;#039;,&amp;#039;sx&amp;#039;,&amp;#039;sy&amp;#039;,&amp;#039;sz&amp;#039;,&amp;#039;rx&amp;#039;,&amp;#039;ry&amp;#039;,&amp;#039;rz&amp;#039;):&lt;br /&gt;
                    mc.setAttr(o+&amp;#039;.&amp;#039;+p,keyable=False,channelBox=False )&lt;br /&gt;
                    &lt;br /&gt;
            mc.setAttr(cameraGrid+&amp;#039;.tz&amp;#039;,keyable=True,channelBox=False )&lt;br /&gt;
            mc.setAttr(cameraGrid+&amp;#039;.tx&amp;#039;,lock=True)&lt;br /&gt;
            mc.setAttr(cameraGrid+&amp;#039;.ty&amp;#039;,lock=True)&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
            mc.addAttr(arrowObj,ln=&amp;#039;focusDistance&amp;#039;)&lt;br /&gt;
            mc.setAttr(arrowObj+&amp;#039;.focusDistance&amp;#039;,e=0,keyable=False,channelBox=True)&lt;br /&gt;
            mc.connectAttr(sr+&amp;#039;.outValue.outValueX&amp;#039;,arrowObj+&amp;#039;.focusDistance&amp;#039;,f=True)&lt;br /&gt;
            mc.connectAttr(sr+&amp;#039;.outValue.outValueX&amp;#039;,resultGrid+&amp;#039;.tz&amp;#039;,f=True) #&lt;br /&gt;
            mc.connectAttr(sr2+&amp;#039;.outValue.outValueX&amp;#039;,resultGrid+&amp;#039;.visibility&amp;#039;,f=True) &lt;br /&gt;
            mc.connectAttr(sr2+&amp;#039;.outValue.outValueY&amp;#039;,cameraGrid+&amp;#039;.visibility&amp;#039;,f=True) &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
            mc.setAttr(resultGrid+&amp;#039;.overrideEnabled&amp;#039;,1)&lt;br /&gt;
            mc.setAttr(resultGrid+&amp;#039;.overrideColor&amp;#039;,1)&lt;br /&gt;
            &lt;br /&gt;
            &lt;br /&gt;
            mc.addAttr(arrowObj,ln=&amp;#039;useFloatingLocator&amp;#039;,dv=0.0,min=0.0,max=1.0)&lt;br /&gt;
            mc.setAttr(arrowObj+&amp;#039;.useFloatingLocator&amp;#039;,e=1,keyable=True,channelBox=False)&lt;br /&gt;
            mc.connectAttr(arrowObj+&amp;#039;.useFloatingLocator&amp;#039;,sr+&amp;#039;.valueX&amp;#039;,f=True)        &lt;br /&gt;
            mc.connectAttr(arrowObj+&amp;#039;.useFloatingLocator&amp;#039;,sr+&amp;#039;.valueY&amp;#039;,f=True)&lt;br /&gt;
            mc.connectAttr(arrowObj+&amp;#039;.useFloatingLocator&amp;#039;,sr+&amp;#039;.valueZ&amp;#039;,f=True)&lt;br /&gt;
            mc.connectAttr(arrowObj+&amp;#039;.useFloatingLocator&amp;#039;,sr2+&amp;#039;.valueX&amp;#039;,f=True)&lt;br /&gt;
            mc.connectAttr(arrowObj+&amp;#039;.useFloatingLocator&amp;#039;,sr2+&amp;#039;.valueY&amp;#039;,f=True)&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
            mc.setAttr(arrow+&amp;#039;.overrideEnabled&amp;#039;,1)&lt;br /&gt;
            mc.setAttr(arrow+&amp;#039;.overrideColor&amp;#039;,17)&lt;br /&gt;
            &lt;br /&gt;
            mc.setAttr(cameraGrid+&amp;#039;.overrideEnabled&amp;#039;,1)&lt;br /&gt;
            mc.setAttr(cameraGrid+&amp;#039;.overrideColor&amp;#039;,12)&lt;br /&gt;
            mc.setAttr(floatingZLoc+&amp;#039;.overrideEnabled&amp;#039;,1)&lt;br /&gt;
            mc.setAttr(floatingZLoc+&amp;#039;.overrideColor&amp;#039;,12)&lt;br /&gt;
            &lt;br /&gt;
    &lt;br /&gt;
            zFocusGroup = mc.group(em=True,n=camObj+&amp;#039;_zFocusGroup&amp;#039;)&lt;br /&gt;
            mc.parent(cameraGridNull,floatingZLoc,projCurve,projectionLocator,cameraLocator,zFocusGroup)&lt;br /&gt;
            &lt;br /&gt;
            if mc.getAttr(&amp;quot;defaultRenderGlobals.currentRenderer&amp;quot;) == &amp;quot;maxwell&amp;quot;:&lt;br /&gt;
                mc.connectAttr(resultLocator+&amp;#039;.tz&amp;#039;,camShape+&amp;#039;.mxFocusDistance&amp;#039;,f=1)                &lt;br /&gt;
            mc.connectAttr(resultLocator+&amp;#039;.tz&amp;#039;,camShape+&amp;#039;.focusDistance&amp;#039;,f=1)&lt;br /&gt;
            &lt;br /&gt;
            mc.select(arrowObj)&lt;br /&gt;
            &lt;br /&gt;
            &lt;br /&gt;
            &lt;br /&gt;
createZDistanceTool()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create python generating code for given curve ==&lt;br /&gt;
http://i.imgur.com/AEmB4nR.png&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import maya.cmds as mc&lt;br /&gt;
from decimal import *&lt;br /&gt;
&lt;br /&gt;
getcontext().prec = 5&lt;br /&gt;
&lt;br /&gt;
shp = mc.listRelatives(mc.ls(sl=1)[0],s=1)[0]&lt;br /&gt;
cvs = mc.getAttr(shp+&amp;#039;.cv[*]&amp;#039;)&lt;br /&gt;
cvsSimple = []&lt;br /&gt;
for c in cvs:&lt;br /&gt;
    cvsSimple.append([float(Decimal(&amp;quot;%.3f&amp;quot; % c[0])),float(Decimal(&amp;quot;%.3f&amp;quot; % c[1])),float(Decimal(&amp;quot;%.3f&amp;quot; % c[2]))])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
out = &amp;#039;\n\n### run python: #################\n\nimport maya.cmds as mc\nmc.curve(p=&amp;#039;  &lt;br /&gt;
out += &amp;#039;[%s]&amp;#039; % &amp;#039;, &amp;#039;.join(map(str, cvsSimple))&lt;br /&gt;
out += &amp;#039;,d=&amp;#039;+str(mc.getAttr(shp+&amp;#039;.degree&amp;#039;))+&amp;#039;)\n\n#################################&amp;#039;&lt;br /&gt;
&lt;br /&gt;
print out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Result:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
### run python: #################&lt;br /&gt;
&lt;br /&gt;
import maya.cmds as mc&lt;br /&gt;
mc.curve(p=[[0.445, 0.49, 0.0], [0.317, 0.49, 0.0], [0.189, 0.49, 0.0], [0.061, 0.49, 0.0], [0.061, 0.441, 0.0], [0.061, 0.391, 0.0], [0.061, 0.342, 0.0], ...etc ,d=3)&lt;br /&gt;
&lt;br /&gt;
#################################&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Attach Geos to closest Geo with follicles ==&lt;br /&gt;
&lt;br /&gt;
Uses pivot point as attach point&lt;br /&gt;
&lt;br /&gt;
https://i.imgur.com/5KQ8Tiv.mp4 (howto)&lt;br /&gt;
&lt;br /&gt;
http://i.imgur.com/LclDANC.jpg https://i.imgur.com/mudCz4x.gif&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import maya.cmds as mc&lt;br /&gt;
from math import sqrt, fabs&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
def attachThingsToThingsUI(*kwargs):&lt;br /&gt;
    &amp;#039;&amp;#039;&amp;#039;simple ui wrapper for &amp;quot;attachThingsToThings&amp;quot; function. No error checking or fancy stuff&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
    &lt;br /&gt;
    if len(kwargs) == 0:&lt;br /&gt;
        #ui&lt;br /&gt;
        if mc.windowPref(&amp;#039;AttachStuffWindow&amp;#039;,ex=1):&lt;br /&gt;
            mc.windowPref(&amp;#039;AttachStuffWindow&amp;#039;,remove=1)&lt;br /&gt;
        if cmds.window(&amp;#039;AttachStuffWindow&amp;#039;, exists=True):&lt;br /&gt;
            cmds.deleteUI(&amp;#039;AttachStuffWindow&amp;#039;, window=True)&lt;br /&gt;
        window = mc.window(&amp;#039;AttachStuffWindow&amp;#039;,title=&amp;#039;Attach stuff to stuff&amp;#039;, iconName=&amp;#039;Short Name&amp;#039;, widthHeight=(80, 55),rtf=1 )&lt;br /&gt;
        mc.frameLayout(mh=10,mw=10,bv=0,l=&amp;quot;&amp;quot;)&lt;br /&gt;
        mc.columnLayout(adjustableColumn=True )&lt;br /&gt;
        textInfo1 = &amp;#039;This script attaches objects to other objects using follicles. Parent objects require non-overlapping UVs.&amp;#039;&lt;br /&gt;
        textInfo2 = &amp;#039;Objects will be attached from their pivot to the closest point on parent mesh. In case of multiple parents, the script will try to figure out which is the closest&amp;#039;&lt;br /&gt;
        textInfo3 = &amp;#039;Tips: if attached objects \&amp;#039;jump\&amp;#039; when on animated objects, or are not stuck precisely, you need more polygons on your parent object(s)&amp;#039;&lt;br /&gt;
        mc.text(ww=1, label=textInfo1 )&lt;br /&gt;
        mc.separator(st=&amp;quot;none&amp;quot;,h=4)&lt;br /&gt;
        mc.text(ww=1, label=textInfo2 )&lt;br /&gt;
        mc.separator(st=&amp;quot;none&amp;quot;,h=8)&lt;br /&gt;
        mc.separator(st=&amp;quot;in&amp;quot;,h=4)&lt;br /&gt;
        mc.separator(st=&amp;quot;none&amp;quot;,h=8)&lt;br /&gt;
        mc.text(ww=1, label=textInfo3 )&lt;br /&gt;
        mc.separator(st=&amp;quot;none&amp;quot;,h=8)&lt;br /&gt;
        mc.separator(st=&amp;quot;in&amp;quot;,h=4)&lt;br /&gt;
        mc.separator(st=&amp;quot;none&amp;quot;,h=8)&lt;br /&gt;
        cb1 = mc.checkBox(&amp;#039;cboxZero&amp;#039;, label=&amp;quot;Add \&amp;#039;zero out\&amp;#039; parents to all objects&amp;quot;,v=1,rs=1,annotation=&amp;quot;creates a group above each object that takes the constrains, so that your object is still free to move - won&amp;#039;t work with references&amp;quot; )&lt;br /&gt;
        mc.checkBox(&amp;#039;cboxCtrl&amp;#039;, label=&amp;quot;Add controllers to all objects&amp;quot;,v=0,rs=1,annotation=&amp;#039;creates \&amp;#039;zero-out\&amp;#039; controls that constrain your objects. Use if you have references and want to animate&amp;#039;,onc=(&amp;#039;mc.checkBox(&amp;quot;cboxZero&amp;quot;,e=1,ed=0)&amp;#039;),ofc=(&amp;#039;mc.checkBox(&amp;quot;cboxZero&amp;quot;,e=1,ed=1)&amp;#039;) )&lt;br /&gt;
        mc.separator(st=&amp;quot;none&amp;quot;,h=8)&lt;br /&gt;
        mc.button( label=&amp;#039;Set object(s) to attach&amp;#039;,command=(&amp;#039;mc.sets(n=\&amp;#039;tmp_childrenObjects_set\&amp;#039;)&amp;#039;) )&lt;br /&gt;
        mc.separator(st=&amp;quot;none&amp;quot;,h=2)&lt;br /&gt;
        mc.button( label=&amp;#039;Set parent object(s)&amp;#039;, command=(&amp;#039;mc.sets(n=\&amp;#039;tmp_parentObjects_set\&amp;#039;)&amp;#039;) )&lt;br /&gt;
        mc.separator(st=&amp;quot;none&amp;quot;,h=10)&lt;br /&gt;
        mc.button( label=&amp;#039;Apply&amp;#039;, command=(&amp;#039;attachThingsToThingsUI(1)&amp;#039;) )&lt;br /&gt;
        mc.showWindow( window )&lt;br /&gt;
    else:&lt;br /&gt;
        children = mc.listConnections(&amp;quot;tmp_childrenObjects_set&amp;quot;,s=1,d=0,p=0,c=0)&lt;br /&gt;
        parents = mc.listConnections(&amp;quot;tmp_parentObjects_set&amp;quot;,s=1,d=0,p=0,c=0)&lt;br /&gt;
        useZeroOut = mc.checkBox(&amp;quot;cboxZero&amp;quot;,q=1,v=1)&lt;br /&gt;
        useCtrl = mc.checkBox(&amp;quot;cboxCtrl&amp;quot;,q=1,v=1)&lt;br /&gt;
        attachThingsToThings(children,parents,1,useZeroOut,useCtrl)&lt;br /&gt;
        mc.delete(&amp;quot;tmp_childrenObjects_set&amp;quot;,&amp;quot;tmp_parentObjects_set&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
def attachThingsToThings(objects,targets,keepHierachy=True,useZeroOut=True,useCtrl=False):&lt;br /&gt;
    &amp;#039;&amp;#039;&amp;#039;requires closestUV() closestDistanceToMesh() mag() python math -- and non overlapping UVs &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
    selectedObjects = []&lt;br /&gt;
    for o in objects:&lt;br /&gt;
        parents = mc.listRelatives(o,p=1,f=1)&lt;br /&gt;
        smallest = 99999.9&lt;br /&gt;
        closest = u&amp;#039;&amp;#039;&lt;br /&gt;
        outPos = []&lt;br /&gt;
        p = mc.xform(o,ws=1,q=1,rotatePivot=True)&lt;br /&gt;
        ro = mc.xform(o,ws=1,q=1,ro=True)&lt;br /&gt;
        bbox = mc.xform(o,ws=1,q=1,bb=True)&lt;br /&gt;
        ctrlscale = ((bbox[3]-bbox[0])+(bbox[4]-bbox[1])+(bbox[5]-bbox[2]))/3.0&lt;br /&gt;
        for r in targets:&lt;br /&gt;
            dist = closestDistanceToMesh(p,r)&lt;br /&gt;
            if dist &amp;lt; smallest:&lt;br /&gt;
                smallest = dist&lt;br /&gt;
                closest = r&lt;br /&gt;
                outPos = p&lt;br /&gt;
        follicle = closestUV(outPos,closest,attachFollicle=1)&lt;br /&gt;
        eg = &amp;#039;&amp;#039;&lt;br /&gt;
        if useZeroOut and not useCtrl:&lt;br /&gt;
            eg = mc.group(em=1,n=o+&amp;#039;zero&amp;#039;)&lt;br /&gt;
            mc.parent(eg,o)&lt;br /&gt;
            mc.makeIdentity(eg)&lt;br /&gt;
            mc.parent(eg,w=1)&lt;br /&gt;
            mc.parent(o,eg)&lt;br /&gt;
        elif useCtrl:&lt;br /&gt;
            eg = mc.group(em=1,n=o+&amp;#039;zero&amp;#039;)&lt;br /&gt;
            s = .33*ctrlscale/2.0&lt;br /&gt;
            ctrlr = mc.curve(n=o+&amp;#039;ctrl&amp;#039;,p=[[0.0, s*3, 0.0], [0.0, s*2, -s*2], [0.0, 0.0, -s*3], [0.0, -s*2, -s*2], [0.0, -s*3, 0.0], [0.0, -s*2, s*2], [0.0, 0.0, s*3], [0.0, s*2, s*2], [0.0, s*3, 0.0], [s*2, s*2, 0.0], [s*3, 0.0, 0.0], [s*2, -s*2, 0.0], [0.0, -s*3, 0.0], [-s*2, -s*2, 0.0], [-s*3, 0.0, 0.0], [-s*2, s*2, 0.0], [0.0, s*3, 0.0]],d=1)&lt;br /&gt;
            ctrlrShp = mc.listRelatives(ctrlr,s=1)[0]&lt;br /&gt;
            mc.setAttr(ctrlrShp+&amp;#039;.overrideEnabled&amp;#039;,1)&lt;br /&gt;
            mc.setAttr(ctrlrShp+&amp;#039;.overrideColor&amp;#039;,12)&lt;br /&gt;
            mc.parent(ctrlr,eg)&lt;br /&gt;
            &lt;br /&gt;
            mc.setAttr(eg+&amp;#039;.tx&amp;#039;,p[0])&lt;br /&gt;
            mc.setAttr(eg+&amp;#039;.ty&amp;#039;,p[1])&lt;br /&gt;
            mc.setAttr(eg+&amp;#039;.tz&amp;#039;,p[2])&lt;br /&gt;
            mc.setAttr(eg+&amp;#039;.rx&amp;#039;,ro[0])&lt;br /&gt;
            mc.setAttr(eg+&amp;#039;.ry&amp;#039;,ro[1])&lt;br /&gt;
            mc.setAttr(eg+&amp;#039;.rz&amp;#039;,ro[2])&lt;br /&gt;
            #mc.setAttr(&amp;#039;%s.t&amp;#039; % eg,p[0],p[1],p[2])&lt;br /&gt;
            #mc.setAttr(&amp;#039;%s.r&amp;#039; % eg,ro[0],ro[1],ro[2])&lt;br /&gt;
            &lt;br /&gt;
            mc.parentConstraint(ctrlr,o,mo=1)&lt;br /&gt;
            mc.scaleConstraint(ctrlr,o,mo=1)&lt;br /&gt;
            selectedObjects.append(ctrlr)&lt;br /&gt;
        else:&lt;br /&gt;
            eg = o&lt;br /&gt;
            selectedObjects.append(o)&lt;br /&gt;
        mc.parentConstraint(follicle,eg,mo=1)&lt;br /&gt;
 &lt;br /&gt;
        if keepHierachy is True and parents is not False and useZeroOut is True and useCtrl is False:&lt;br /&gt;
            mc.parent(eg,parents[0])&lt;br /&gt;
 &lt;br /&gt;
        #add follicles to a group, hide it&lt;br /&gt;
        fGroup = &amp;#039;FolliclesGroup&amp;#039;&lt;br /&gt;
        if not mc.objExists(fGroup):&lt;br /&gt;
            fGroup = mc.group(follicle,n=fGroup)&lt;br /&gt;
            mc.setAttr(fGroup+&amp;#039;.visibility&amp;#039;,0)&lt;br /&gt;
        else:&lt;br /&gt;
            fGroup = mc.ls(fGroup)[-1]&lt;br /&gt;
            mc.parent(follicle,fGroup)&lt;br /&gt;
        mc.select(selectedObjects)&lt;br /&gt;
        &lt;br /&gt;
def closestUV(position,target,attachFollicle=0):&lt;br /&gt;
    &amp;#039;&amp;#039;&amp;#039;target geo MUST have its transforms frozen&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
    cpom = mc.createNode( &amp;#039;closestPointOnMesh&amp;#039;)&lt;br /&gt;
    targetMeshes = mc.listRelatives(target,s=1,ni=1,f=1)&lt;br /&gt;
    #if len(targetMeshes):      &lt;br /&gt;
    #    mc.warning(&amp;#039;Multiple shapes found on \&amp;#039;&amp;#039;+target+&amp;#039;\&amp;#039; follicles might not be connected properly&amp;#039;)&lt;br /&gt;
    targetMesh = targetMeshes[0]&lt;br /&gt;
 &lt;br /&gt;
    mc.connectAttr(targetMesh+&amp;quot;.worldMesh[0]&amp;quot;,cpom+&amp;quot;.inMesh&amp;quot;)&lt;br /&gt;
    mc.connectAttr(targetMesh+&amp;quot;.worldMatrix[0]&amp;quot;,cpom+&amp;quot;.inputMatrix&amp;quot;)&lt;br /&gt;
    mc.setAttr(cpom+&amp;quot;.inPosition&amp;quot;, position[0], position[1], position[2], type=&amp;quot;double3&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    getU = mc.getAttr(cpom+&amp;quot;.result.parameterU&amp;quot;)&lt;br /&gt;
    getV = mc.getAttr(cpom+&amp;quot;.result.parameterV&amp;quot;)&lt;br /&gt;
    mc.delete(cpom)&lt;br /&gt;
    if attachFollicle:&lt;br /&gt;
        follicle = mc.createNode(&amp;#039;follicle&amp;#039;)&lt;br /&gt;
        follicleObj = mc.listRelatives(follicle,p=1,f=1)[0]&lt;br /&gt;
        mc.connectAttr(targetMesh+&amp;quot;.outMesh&amp;quot;,follicle+&amp;quot;.inputMesh&amp;quot;)&lt;br /&gt;
        mc.connectAttr(targetMesh+&amp;quot;.worldMatrix[0]&amp;quot;,follicle+&amp;quot;.inputWorldMatrix&amp;quot;)&lt;br /&gt;
        mc.connectAttr(follicle+&amp;quot;.outTranslate&amp;quot;,follicleObj+&amp;quot;.translate&amp;quot;)&lt;br /&gt;
        mc.connectAttr(follicle+&amp;quot;.outRotate&amp;quot;,follicleObj+&amp;quot;.rotate&amp;quot;)&lt;br /&gt;
        mc.setAttr(follicle+&amp;quot;.parameterU&amp;quot;, getU)&lt;br /&gt;
        mc.setAttr(follicle+&amp;quot;.parameterV&amp;quot;, getV)&lt;br /&gt;
        return follicleObj&lt;br /&gt;
    else:&lt;br /&gt;
        return [getU,getV]&lt;br /&gt;
 &lt;br /&gt;
def closestDistanceToMesh(position,target):&lt;br /&gt;
    cpom = mc.createNode( &amp;#039;closestPointOnMesh&amp;#039;)&lt;br /&gt;
    targetMesh = mc.listRelatives(target,ni=1,s=1)[0]&lt;br /&gt;
 &lt;br /&gt;
    mc.connectAttr(targetMesh+&amp;quot;.worldMesh[0]&amp;quot;,cpom+&amp;quot;.inMesh&amp;quot;)&lt;br /&gt;
    mc.connectAttr(targetMesh+&amp;quot;.worldMatrix[0]&amp;quot;,cpom+&amp;quot;.inputMatrix&amp;quot;)&lt;br /&gt;
    mc.setAttr(cpom+&amp;quot;.inPosition&amp;quot;, position[0], position[1], position[2], type=&amp;quot;double3&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    x = mc.getAttr(cpom+&amp;quot;.result.position.positionX&amp;quot;)&lt;br /&gt;
    y = mc.getAttr(cpom+&amp;quot;.result.position.positionY&amp;quot;)&lt;br /&gt;
    z = mc.getAttr(cpom+&amp;quot;.result.position.positionZ&amp;quot;)&lt;br /&gt;
    p2 = [x,y,z]&lt;br /&gt;
    mc.delete(cpom)&lt;br /&gt;
    return mag(position,p2)&lt;br /&gt;
 &lt;br /&gt;
def mag(v1,v2):&lt;br /&gt;
    return sqrt(pow(v2[0]-v1[0],2) + pow(v2[1]-v1[1],2) + pow(v2[2]-v1[2],2))&lt;br /&gt;
 &lt;br /&gt;
attachThingsToThingsUI()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Attach to Closest Point On Curve ==&lt;br /&gt;
http://i.imgur.com/0kk59Ni.jpg&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import maya.cmds as mc&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def attachToClosestPointOnCurve():&lt;br /&gt;
    #last element should be curve , no error checking - snaps to cloest point on mesh using motionPath&lt;br /&gt;
    &lt;br /&gt;
    sel = mc.ls(sl=1)&lt;br /&gt;
    curveObj = sel[len(sel)-1]&lt;br /&gt;
    sel.pop()&lt;br /&gt;
    npc = mc.createNode( &amp;#039;nearestPointOnCurve&amp;#039;)&lt;br /&gt;
    mc.connectAttr(mc.listRelatives(curveObj,s=1)[0]+&amp;quot;.worldSpace[0]&amp;quot;, npc+&amp;quot;.inputCurve&amp;quot;, f=1)&lt;br /&gt;
    for ob in sel:&lt;br /&gt;
        #parm = jc_closestPointOnCurve(mc.xform(ob, q=1, ws=1, t=1), curveObj)&lt;br /&gt;
        pos = mc.xform(ob, q=1, ws=1, t=1)&lt;br /&gt;
        mc.setAttr(npc+&amp;quot;.inPosition&amp;quot;, pos[0], pos[1], pos[2], type=&amp;quot;double3&amp;quot;)&lt;br /&gt;
        parm = mc.getAttr(npc+&amp;quot;.parameter&amp;quot;)&lt;br /&gt;
        #loc = mc.spaceLocator(n=ob+&amp;quot;_pointOnCurve&amp;quot;)&lt;br /&gt;
        pathAnim = mc.pathAnimation( ob, c=curveObj )&lt;br /&gt;
        inputs = mc.listConnections(pathAnim+&amp;quot;.uValue&amp;quot;, s=1)&lt;br /&gt;
        mc.disconnectAttr(inputs[0]+&amp;quot;.output&amp;quot;,pathAnim+&amp;quot;.uValue&amp;quot;)&lt;br /&gt;
        mc.setAttr(pathAnim+&amp;quot;.uValue&amp;quot;,parm)&lt;br /&gt;
        &lt;br /&gt;
    mc.delete(npc)&lt;br /&gt;
    &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Make UV Check lambert ==&lt;br /&gt;
http://i.imgur.com/iajDjqc.jpg&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import urllib2&lt;br /&gt;
import os&lt;br /&gt;
import maya.cmds as cmds&lt;br /&gt;
&lt;br /&gt;
tempDir = cmds.internalVar(userTmpDir=True)&lt;br /&gt;
uvFile = tempDir+&amp;#039;uv1024bis.jpg&amp;#039;;&lt;br /&gt;
f = open(uvFile,&amp;#039;wb&amp;#039;)&lt;br /&gt;
err = f.write(urllib2.urlopen(&amp;#039;http://berniebernie.fr/dump/uv1024.jpg&amp;#039;).read())&lt;br /&gt;
f.close()&lt;br /&gt;
shader=cmds.shadingNode(&amp;quot;lambert&amp;quot;,asShader=True,name=&amp;quot;UVlambert&amp;quot;)&lt;br /&gt;
file_node=cmds.shadingNode(&amp;quot;file&amp;quot;,asTexture=True)&lt;br /&gt;
file_text=cmds.shadingNode(&amp;quot;place2dTexture&amp;quot;,asUtility=True)&lt;br /&gt;
shading_group= cmds.sets(renderable=True,noSurfaceShader=True,empty=True)&lt;br /&gt;
cmds.connectAttr(&amp;#039;%s.outColor&amp;#039; %shader ,&amp;#039;%s.surfaceShader&amp;#039; %shading_group)&lt;br /&gt;
cmds.connectAttr(&amp;#039;%s.outColor&amp;#039; %file_node, &amp;#039;%s.color&amp;#039; %shader)&lt;br /&gt;
cmds.connectAttr(&amp;#039;%s.coverage&amp;#039; %file_text ,&amp;#039;%s.coverage&amp;#039; %file_node)&lt;br /&gt;
cmds.connectAttr(&amp;#039;%s.translateFrame&amp;#039; %file_text ,&amp;#039;%s.translateFrame&amp;#039; %file_node)&lt;br /&gt;
cmds.connectAttr(&amp;#039;%s.rotateFrame&amp;#039; %file_text ,&amp;#039;%s.rotateFrame&amp;#039; %file_node)&lt;br /&gt;
cmds.connectAttr(&amp;#039;%s.mirrorU&amp;#039; %file_text ,&amp;#039;%s.mirrorU&amp;#039; %file_node)&lt;br /&gt;
cmds.connectAttr(&amp;#039;%s.mirrorV&amp;#039; %file_text ,&amp;#039;%s.mirrorV&amp;#039; %file_node)&lt;br /&gt;
cmds.connectAttr(&amp;#039;%s.stagger&amp;#039; %file_text ,&amp;#039;%s.stagger&amp;#039; %file_node)&lt;br /&gt;
cmds.connectAttr(&amp;#039;%s.wrapU&amp;#039; %file_text ,&amp;#039;%s.wrapU&amp;#039; %file_node)&lt;br /&gt;
cmds.connectAttr(&amp;#039;%s.wrapV&amp;#039; %file_text ,&amp;#039;%s.wrapV&amp;#039; %file_node)&lt;br /&gt;
cmds.connectAttr(&amp;#039;%s.repeatUV&amp;#039; %file_text ,&amp;#039;%s.repeatUV&amp;#039; %file_node)&lt;br /&gt;
cmds.connectAttr(&amp;#039;%s.offset&amp;#039; %file_text ,&amp;#039;%s.offset&amp;#039; %file_node)&lt;br /&gt;
cmds.connectAttr(&amp;#039;%s.rotateUV&amp;#039; %file_text ,&amp;#039;%s.rotateUV&amp;#039; %file_node)&lt;br /&gt;
cmds.connectAttr(&amp;#039;%s.noiseUV&amp;#039; %file_text ,&amp;#039;%s.noiseUV&amp;#039; %file_node)&lt;br /&gt;
cmds.connectAttr(&amp;#039;%s.vertexUvOne&amp;#039; %file_text ,&amp;#039;%s.vertexUvOne&amp;#039; %file_node)&lt;br /&gt;
cmds.connectAttr(&amp;#039;%s.vertexUvTwo&amp;#039; %file_text ,&amp;#039;%s.vertexUvTwo&amp;#039; %file_node)&lt;br /&gt;
cmds.connectAttr(&amp;#039;%s.vertexUvThree&amp;#039; %file_text ,&amp;#039;%s.vertexUvThree&amp;#039; %file_node)&lt;br /&gt;
cmds.connectAttr(&amp;#039;%s.vertexCameraOne&amp;#039; %file_text ,&amp;#039;%s.vertexCameraOne&amp;#039; %file_node)&lt;br /&gt;
cmds.connectAttr(&amp;#039;%s.outUV&amp;#039; %file_text ,&amp;#039;%s.uv&amp;#039; %file_node)&lt;br /&gt;
cmds.connectAttr(&amp;#039;%s.outUvFilterSize&amp;#039; %file_text ,&amp;#039;%s.uvFilterSize&amp;#039; %file_node)&lt;br /&gt;
cmds.setAttr( &amp;#039;%s.fileTextureName&amp;#039; %file_node,uvFile,type=&amp;quot;string&amp;quot; )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
==Check if latest ref==&lt;br /&gt;
http://i.imgur.com/w3yYdLL.jpg&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import maya.cmds as mc&lt;br /&gt;
import maya.mel as mel&lt;br /&gt;
from functools import partial&lt;br /&gt;
from os import listdir&lt;br /&gt;
from os.path import split, isfile, join, dirname&lt;br /&gt;
import subprocess&lt;br /&gt;
&lt;br /&gt;
class refCheckWindow(object):&lt;br /&gt;
    &lt;br /&gt;
    onlyMissing = True&lt;br /&gt;
    &lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        print &amp;quot;\nProcessing! Be patient =)&amp;quot;&lt;br /&gt;
        self.buildWin()&lt;br /&gt;
    def reinitWin(*args):&lt;br /&gt;
        w = refCheckWindow()     &lt;br /&gt;
    def buttonPush(*args):&lt;br /&gt;
        refPath = dirname(args[1])&lt;br /&gt;
        refPath = refPath.replace(&amp;#039;/&amp;#039;, &amp;#039;\\&amp;#039;)&lt;br /&gt;
        subprocess.Popen(&amp;#039;explorer &amp;quot;%s&amp;quot;&amp;#039; % refPath)&lt;br /&gt;
    def buildWin(self):&lt;br /&gt;
        &lt;br /&gt;
        scene = mc.file(query=True,sn=True)&lt;br /&gt;
        allrefs = mc.file(query=True, list=True, withoutCopyNumber=True)&lt;br /&gt;
        fileRefs = sorted(list(set([item for item in allrefs if item.endswith(&amp;#039;.ma&amp;#039;) or item.endswith(&amp;#039;.mb&amp;#039;)])))&lt;br /&gt;
        if mc.window(&amp;quot;checkRefs&amp;quot;,ex=1):&lt;br /&gt;
            mc.deleteUI(&amp;quot;checkRefs&amp;quot;,window=1)&lt;br /&gt;
        mc.window(&amp;quot;checkRefs&amp;quot;,title=&amp;#039;Check latest Refs&amp;#039;,resizeToFitChildren=1,w=600)&lt;br /&gt;
        scrollLayout = cmds.scrollLayout(horizontalScrollBarThickness=16,verticalScrollBarThickness=16)&lt;br /&gt;
        mc.columnLayout(adjustableColumn=True, columnAlign=&amp;#039;center&amp;#039;,rowSpacing=10)&lt;br /&gt;
        &lt;br /&gt;
        mc.rowLayout(numberOfColumns=3)&lt;br /&gt;
&lt;br /&gt;
        mc.text( label=&amp;#039;     Checking if you have latest refs :     &amp;#039;, align=&amp;#039;left&amp;#039; )&lt;br /&gt;
        mc.checkBox(&amp;quot;cbox&amp;quot;, label=&amp;#039;Only show missing refs    &amp;#039;, v=1 )&lt;br /&gt;
        mc.button(w=55,l=&amp;quot;Refresh&amp;quot;,c=self.reinitWin)&lt;br /&gt;
        &lt;br /&gt;
        mc.setParent(upLevel=True)&lt;br /&gt;
        mc.separator()&lt;br /&gt;
        for ref in fileRefs:&lt;br /&gt;
            if ref != scene:&lt;br /&gt;
                curRefNamespace = mc.referenceQuery(ref,rfn=1)&lt;br /&gt;
                curRefParent = mc.referenceQuery(curRefNamespace,rfn=1,p=1)&lt;br /&gt;
&lt;br /&gt;
                onlyfiles = [ f for f in listdir(split(ref)[0]) if isfile(join(split(ref)[0],f)) and f.endswith((&amp;#039;.mb&amp;#039;,&amp;#039;.ma&amp;#039;)) ]&lt;br /&gt;
                #beautiful code below&lt;br /&gt;
                refFileName = ref.rpartition(&amp;#039;/&amp;#039;)[2]&lt;br /&gt;
                refStepName = ref.rpartition(&amp;#039;/&amp;#039;)[0].rpartition(&amp;#039;/&amp;#039;)[2];&lt;br /&gt;
                refChar = ref.rpartition(&amp;#039;/&amp;#039;)[0].rpartition(&amp;#039;/&amp;#039;)[0].rpartition(&amp;#039;/&amp;#039;)[0];&lt;br /&gt;
                refCharName = refChar.rpartition(&amp;#039;/&amp;#039;)[0].rpartition(&amp;#039;/&amp;#039;)[2]+&amp;quot; / &amp;quot;+refChar.rpartition(&amp;#039;/&amp;#039;)[2];&lt;br /&gt;
                refCharName = refCharName.lower();&lt;br /&gt;
                latestRef = sorted(onlyfiles)[-1];&lt;br /&gt;
                col = [.3,.8,.3];&lt;br /&gt;
                if(refFileName!=latestRef):&lt;br /&gt;
                    col = [.9,.1,.1];&lt;br /&gt;
                print &amp;quot;.&amp;quot;,&lt;br /&gt;
                &lt;br /&gt;
                if( mc.checkBox(&amp;quot;cbox&amp;quot;,q=1,v=1) and refFileName!=latestRef):&lt;br /&gt;
                &lt;br /&gt;
                    mc.rowLayout(numberOfColumns=6,ann=curRefParent)&lt;br /&gt;
    &lt;br /&gt;
                    mc.separator()&lt;br /&gt;
                    mc.button(w=50,l=refStepName,en=0)&lt;br /&gt;
                    if curRefParent:&lt;br /&gt;
                        col = [(col[0]+.6)/2,(col[1]+.6)/2,(col[2]+.6)/2]&lt;br /&gt;
                    mc.button(w=150,l=refCharName,bgc=col)&lt;br /&gt;
                    mc.text(w=370,l=&amp;quot;  &amp;quot;+refFileName+&amp;quot; -&amp;gt; &amp;quot;+latestRef+&amp;quot; &amp;quot;)&lt;br /&gt;
        &lt;br /&gt;
                    mc.button(w=55,l=&amp;quot;browse&amp;quot;,c=partial(self.buttonPush, ref))&lt;br /&gt;
                    mc.separator()&lt;br /&gt;
                    mc.setParent(upLevel=True)&lt;br /&gt;
                    mc.separator()&lt;br /&gt;
       &lt;br /&gt;
        &lt;br /&gt;
        mc.showWindow()&lt;br /&gt;
w = refCheckWindow()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Category:Maya]]&lt;/div&gt;</summary>
		<author><name>Bernie</name></author>
	</entry>
</feed>