Chain Creator

Download chainCreator.py

python, pyfuncs, maya

I made this script when I had to modellize an old prison scene, with a lot of chains :)

 ⚭ Chain creation example

Here is an example using the function :

1
create_chain(crv=cmds.ls(sl=True)[0], radius=1)

Full code here ;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
def create_chain_ring(radius=1.0):
    """
    Create a chain ring from a Torus stretched
    :param radius: then radius of the ring
    :return      : the name of the new ring part
    """
    part = cmds.polyTorus(r=radius, sr=radius/3.0, tw=0, sx=8, sy=6,
                          ax=(1, 0, 0), ch=0)[0]
    cmds.rotate(22.5, 0, 0, part, os=True)
    # vertice sequence we need to translate
    vseq = [0, 1, 2, 7, 8, 9, 10, 15, 16, 17, 18, 23, 24, 25, 26, 31,
            32, 33, 34, 39, 40, 41, 42, 47]
    vsel = ['%s.vtx[%d]' % (part, v) for v in vseq]
    cmds.move(0, 0, -radius, vsel, ws=True, r=True)
    # edge sequence we need to connect
    eseq = [2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46]
    esel = ['%s.e[%d]' % (part, v) for v in eseq]
    cmds.polyConnectComponents(esel, insertWithEdgeFlow=0, ch=0,
                               adjustEdgeFlow=1)
    cmds.select(part)
    # clear history
    cmds.makeIdentity(apply=True, t=0, r=1, s=1, n=0, pn=1)
    return part


def create_chain(crv, radius=1.0):
    """
    Create a simple chain, number of parts depends on the radius
    :param    crv: the selected curve
    :param radius: radius of the chain's parts
    """
    part_size = radius * 2
    # we rebuild the curve with a lot a points
    crv = cmds.rebuildCurve(crv, ch=0, rpo=1, rt=0, end=1, kr=0, kcp=0,
                            kep=1, kt=0, s=36, d=2, tol=0.01)
    shape = cmds.listRelatives(crv, c=True, s=True, ni=True)[0]
    # we create a curveInfo to get the length
    ci = cmds.shadingNode('curveInfo', au=True)
    cmds.connectAttr('%s.worldSpace[0]' % shape, '%s.inputCurve' % ci)
    c_length = cmds.getAttr('%s.arcLength' % ci)
    cmds.delete(ci)
    # we determine how many rings we can insert in this length
    parts_range = int(c_length / part_size)
    perc_delta = 1.0 / parts_range
    # create a node we'll use to get the correct position on the curve and
    # to orient our rings
    getter = cmds.shadingNode('pointOnCurveInfo', au=True)
    cmds.connectAttr('%s.worldSpace[0]' % shape, '%s.inputCurve' % getter)
    # turn on Percentage on our pointOnCurveInfo
    cmds.setAttr('%s.top' % getter, 1)
    for i in range(parts_range):
        cmds.setAttr('%s.parameter' % getter, perc_delta * i)
        current = cmds.getAttr('%s.p' % getter)[0]
        # get curve center attribute for the aim up
        center = cmds.getAttr('%s.cc' % getter)[0]
        g = cmds.group(n='up_%d' % i, em=True)
        cmds.setAttr('%s.t' % g, *center, type='double3')
        cmds.setAttr('%s.parameter' % getter, perc_delta * (i + 1))
        next = cmds.getAttr('%s.p' % getter)[0]
        cmds.select(cl=1)
        j = cmds.joint(p=current)
        cmds.select(cl=1)
        n = cmds.joint(p=next)
        # we switch our up object if i%2
        up = [0, 1, 0] if i % 2 == 0 else [1, 0, 0]
        cmds.aimConstraint(n, j, w=1.0, mo=False, aim=[0, 0, -1],
                           u=up, wu=[1, 0, 0], wut='object', wuo=g)
        part = create_chain_ring(radius=radius)
        pc = cmds.parentConstraint(j, part, mo=False, w=1.0)[0]
        cmds.setAttr('%s.interpType' % pc, 2)
        # cleaning
        cmds.delete([pc, n, j, g])
    cmds.delete([crv, getter])

If you have any questions... =)