def build(name=None, crv=None, loc=None, num_jnts=None, num_cnts=None, order=None, reg_node=None, log=False): '''Create advnced IK spine rig Attributes: name -- Prefix name used for the rig. Str crv -- Nurbs curve used as guide. nt.Transform loc -- SpaceLocator used to determine "up" vector. Str num_jnts -- Number of spine joints. Int num_cnts -- Number of controls to make. Int order -- Joint order. Str reg_node -- Registration node. nt.Transform log -- Output log messages. Bool ''' general.check_type(name, 'name', [str]) general.check_type(crv, 'crv', [pm.nt.Transform]) general.check_type(loc, 'loc', [pm.nt.Transform]) general.check_type(num_jnts, 'num_jnts', [int]) general.check_type(num_cnts, 'num_cnts', [int]) general.check_type(order, 'order', [str]) if reg_node: general.check_type(reg_node, 'reg_node', [pm.nt.Transform]) general.check_type(log, 'log', [bool]) if num_jnts < 5 or num_jnts > 50: raise errors.InputError('num_jnts', num_jnts, 'Value Range: 5 - 50') if num_cnts < 2 or num_jnts > 20: raise errors.InputError('num_cnts', num_cnts, 'Value Range: 2 - 20') if order not in ['xyz', 'xzy', 'yxz', 'yzx', 'zxy', 'zyx']: raise errors.InputError('order', order, 'String: xyz, ...') if not reg_node: reg_node = control.create_register_node(name) # -Make joint chain # -- Duplicate loc and call build script dup_loc = loc.duplicate()[0] reg_node, chain = utils.build_joint_chain(name, crv, order, num_jnts, dup_loc, reg_node) pm.delete(dup_loc) # -Make curve (duplicate / rebuild) ik_crv = crv.duplicate(name='%s_ik_curve' % name)[0] pm.rebuildCurve(ik_crv, s=20) # -Make spline IK handle = pm.ikHandle(name='%s_ikHandle' % name, sj=chain[0], ee=chain[-1], c=ik_crv, ccv=False, rtm=False, sol='ikSplineSolver')[0] # -Ik curve jnts dup_loc = loc.duplicate()[0] temp, ikCrvJnts = utils.build_joint_chain('%s_ikCrv' % name, crv, order, num_cnts, dup_loc) pm.delete(dup_loc) pm.delete(temp) for j in ikCrvJnts: try: pm.parent(j, w=1) except: pass # -Make controls count = 1 cnts = [] for j in ikCrvJnts: # Create curve reg_node, cnt_crv = control.\ create_curve(name='%s%s_ik_cnt' % (name, count), typ='circle', scale=1.0, color='yellow', reg_node=reg_node) # Match curve to object control.match_object(cnt_crv, j) # Setup heirarchy pm.parent(j, cnt_crv) # Create heirarchy control.create_heirarchy(name='%s_%s' % (name, count), obj=cnt_crv, num=3) cnts.append(cnt_crv) count += 1 # Build plane for follicles, for controls plane = utils.build_plane('%s_ik_' % name, crv, 20, 'v', 'x', 0.5) # Create follicles follicles = [] incr = 1 / float(num_cnts) param = incr for c in cnts[1:-1]: fol = pm.createNode('transform', n='%s_fol' % c.name(), ss=True) folShape = pm.createNode('follicle', n=fol.name() + 'Shape', p=fol, ss=True) plane.local >> folShape.inputSurface plane.worldMatrix[0] >> folShape.inputWorldMatrix folShape.outRotate >> fol.rotate folShape.outTranslate >> fol.translate fol.inheritsTransform.set(False) folShape.parameterU.set(0.5) folShape.parameterV.set(param) param += incr follicles.append(fol) # -Setup controls cnts_grp = pm.group(name='%s_cnts_grp' % name, em=1) count = 0 for cnt in cnts[1:-1]: prnt = cnt.getParent() mid = prnt.getParent() top = mid.getParent() # --Grouping pm.parent(top, follicles[count]) count += 1 count = 0 for cnt in [cnts[0], cnts[-1]]: prnt = cnt.getParent() mid = prnt.getParent() top = mid.getParent() # --Grouping pm.parent(top, cnts_grp) count += 1 # Skin ik curve to control joints pm.skinCluster(ikCrvJnts, ik_crv, tsb=True, name='%s_ikCrv_sc' % name) # Skin plane curve to top/btm control joints pm.skinCluster(ikCrvJnts[0], ikCrvJnts[-1], plane, tsb=True, name='%s_ikPlane_sc' % name) # -Make Advance Spline ik_crv.inheritsTransform.set(0) # Enable Adv Ik / Set: Up Object (start/end) handle.dTwistControlEnable.set(1) handle.dWorldUpType.set(2) up_loc1 = pm.spaceLocator(name='%s_AdvIkUpObj1_loc' % name) up_loc2 = pm.spaceLocator(name='%s_AdvIkUpObj2_loc' % name) pm.parent(up_loc1, cnts[0]) pm.parent(up_loc2, cnts[-1]) for loc in [up_loc1, up_loc2]: loc.setTranslation(0) loc.setRotation([0, 0, 0]) attr = getattr(loc, 't%s' % order[1].lower()) attr.set(5) loc.visibility.set(0) up_loc1.worldMatrix >> handle.dWorldUpMatrix up_loc2.worldMatrix >> handle.dWorldUpMatrixEnd # Create poly planes to aid in skinning nurbs plane and curve polyPlane = pm.nurbsToPoly(plane, mnd=1, ch=0, f=0, pt=1, pc=20, chr=0.9, ft=0.01, mel=0.001, d=0.1, ut=1, un=3, vt=1, vn=3, uch=0, ucr=0, cht=0.2, es=0, ntr=0, mrt=0, uss=1)[0] polyCrvPlane = pm.nurbsToPoly(plane, mnd=1, ch=0, f=0, pt=1, pc=20, chr=0.9, ft=0.01, mel=0.001, d=0.1, ut=1, un=3, vt=1, vn=3, uch=0, ucr=0, cht=0.2, es=0, ntr=0, mrt=0, uss=1)[0] p1 = pm.PyNode(polyPlane) p1.rename('%s_nurbsPlaneAide' % name) p2 = pm.PyNode(polyCrvPlane) p2.rename('%s_ikCrvAide' % name) pm.skinCluster(ikCrvJnts, p2, tsb=1, name='%s_ikCrvAide_sc' % name) pm.skinCluster(ikCrvJnts[0], ikCrvJnts[-1], p1, tsb=1, name='%s_nurbsPlaneAide_sc' % name) # Clean up for j in ikCrvJnts: j.hide() fol_grp = pm.group(n='%s_follicle_grp' % name, em=1) dont_mov_grp = pm.group(n='%s_dont_move_grp' % name, em=1) skin_jnts_grp = pm.group(n='%s_ik_skin_jnts_grp' % name, em=1) dont_mov_grp.translate.lock() dont_mov_grp.rotate.lock() dont_mov_grp.hide() pm.parent(follicles, fol_grp) pm.parent(chain[0], skin_jnts_grp) pm.parent(handle, plane, ik_crv, p1, p2, dont_mov_grp) main_grp = pm.group(n='%s_ik_rig_grp' % name, em=1) pm.parent(fol_grp, dont_mov_grp, skin_jnts_grp, cnts_grp, main_grp) # Register joint chain and ik_crv control.register_object(reg_node, 'ik_top_node', main_grp) control.register_object(reg_node, 'ik_crv', ik_crv) return reg_node
def build(name=None, crv=None, loc=None, ik_jnts=None, ik_cnts=None, ik_order='xyz', fk_order='xyz', fk_num=None, fk_buffers=None, fk_color=None, fk_scale=None, fk_typ=None, log=False): ''' Create fk/ik/sine rig along provided curve Attributes: crv -- Curve to build rig along. nt.Transform loc -- Locator used to get up vector. nt.Transform ik_jnts -- Number of ik joints. Int ik_cnts -- Number of ik controls. Int ik_order -- IK joint order. Str. Default: 'xyz' fk_order -- FK joint order. Str. Default: 'xyz' fk_num -- Number of FK joints/Controls. Int fk_buffers -- Number of groups above controls. Int fk_color -- FK control color. Str fk_scale -- FK control scale. Float fk_typ -- FK control type. Str log -- Output logging messages. Bool ''' general.check_type(name, 'name', [str]) general.check_type(crv, 'crv', [pm.nt.Transform]) general.check_type(loc, 'loc', [pm.nt.Transform]) general.check_type(ik_jnts, 'ik_jnts', [int]) general.check_type(ik_cnts, 'ik_cnts', [int]) general.check_type(ik_order, 'ik_order', [str]) general.check_type(fk_order, 'fk_order', [str]) general.check_type(fk_num, 'fk_num', [int]) general.check_type(fk_buffers, 'fk_buffers', [int]) general.check_type(fk_color, 'fk_color', [str]) general.check_type(fk_scale, 'fk_scale', [float]) general.check_type(fk_typ, 'fk_typ', [str]) general.check_type(log, 'log', [bool]) reg_node = control.create_register_node(name=name) fk_rig.build(name=name+'FK', crv=crv, loc=loc, order=fk_order, num=fk_num, buffers=fk_buffers, color=fk_color, scale=fk_scale, typ=fk_typ, reg_node=reg_node) ik_rig.build(name+'IK', crv=crv, loc=loc, num_jnts=ik_jnts, num_cnts=ik_cnts, order=ik_order, reg_node=reg_node) crv = reg_node.ik_crv.listConnections()[0] sine_rig.build(name=name+'IK', crv=crv, reg_node=reg_node) sine = reg_node.sine_handle.listConnections()[0] ik_top = reg_node.ik_top_node.listConnections()[0] fk_top = reg_node.fk_top_node.listConnections()[0] rig_top = pm.group(name='%s_rig_top' % name, empty=1) pm.parent(sine.getParent(), rig_top) pm.parent(ik_top, rig_top) pm.parent(fk_top, rig_top) # Parent IK controls to fk fk_btm = pm.PyNode('%sFK_1' % name) fk_top = pm.PyNode('%sFK_%s' % (name, ik_cnts)) ik_btm = pm.PyNode('%sIK_1_top_node' % name) ik_top = pm.PyNode('%sIK_%s_top_node' % (name, ik_cnts)) pm.parent(ik_btm, fk_btm) pm.parent(ik_top, fk_top) control.register_object(reg_node, 'rig_top_node', rig_top) return reg_node
def build(name=None, crv=None, loc=None, ik_jnts=None, ik_cnts=None, ik_order='xyz', fk_order='xyz', fk_num=None, fk_buffers=None, fk_color=None, fk_scale=None, fk_typ=None, log=False): ''' Create fk/ik/sine rig along provided curve Attributes: crv -- Curve to build rig along. nt.Transform loc -- Locator used to get up vector. nt.Transform ik_jnts -- Number of ik joints. Int ik_cnts -- Number of ik controls. Int ik_order -- IK joint order. Str. Default: 'xyz' fk_order -- FK joint order. Str. Default: 'xyz' fk_num -- Number of FK joints/Controls. Int fk_buffers -- Number of groups above controls. Int fk_color -- FK control color. Str fk_scale -- FK control scale. Float fk_typ -- FK control type. Str log -- Output logging messages. Bool ''' general.check_type(name, 'name', [str]) general.check_type(crv, 'crv', [pm.nt.Transform]) general.check_type(loc, 'loc', [pm.nt.Transform]) general.check_type(ik_jnts, 'ik_jnts', [int]) general.check_type(ik_cnts, 'ik_cnts', [int]) general.check_type(ik_order, 'ik_order', [str]) general.check_type(fk_order, 'fk_order', [str]) general.check_type(fk_num, 'fk_num', [int]) general.check_type(fk_buffers, 'fk_buffers', [int]) general.check_type(fk_color, 'fk_color', [str]) general.check_type(fk_scale, 'fk_scale', [float]) general.check_type(fk_typ, 'fk_typ', [str]) general.check_type(log, 'log', [bool]) reg_node = control.create_register_node(name=name) fk_rig.build(name=name + 'FK', crv=crv, loc=loc, order=fk_order, num=fk_num, buffers=fk_buffers, color=fk_color, scale=fk_scale, typ=fk_typ, reg_node=reg_node) ik_rig.build(name + 'IK', crv=crv, loc=loc, num_jnts=ik_jnts, num_cnts=ik_cnts, order=ik_order, reg_node=reg_node) crv = reg_node.ik_crv.listConnections()[0] sine_rig.build(name=name + 'IK', crv=crv, reg_node=reg_node) sine = reg_node.sine_handle.listConnections()[0] ik_top = reg_node.ik_top_node.listConnections()[0] fk_top = reg_node.fk_top_node.listConnections()[0] rig_top = pm.group(name='%s_rig_top' % name, empty=1) pm.parent(sine.getParent(), rig_top) pm.parent(ik_top, rig_top) pm.parent(fk_top, rig_top) # Parent IK controls to fk fk_btm = pm.PyNode('%sFK_1' % name) fk_top = pm.PyNode('%sFK_%s' % (name, ik_cnts)) ik_btm = pm.PyNode('%sIK_1_top_node' % name) ik_top = pm.PyNode('%sIK_%s_top_node' % (name, ik_cnts)) pm.parent(ik_btm, fk_btm) pm.parent(ik_top, fk_top) control.register_object(reg_node, 'rig_top_node', rig_top) return reg_node
def build(name=None, crv=None, loc=None, num_jnts=None, num_cnts=None, order=None, reg_node=None, log=False): '''Create advnced IK spine rig Attributes: name -- Prefix name used for the rig. Str crv -- Nurbs curve used as guide. nt.Transform loc -- SpaceLocator used to determine "up" vector. Str num_jnts -- Number of spine joints. Int num_cnts -- Number of controls to make. Int order -- Joint order. Str reg_node -- Registration node. nt.Transform log -- Output log messages. Bool ''' general.check_type(name, 'name', [str]) general.check_type(crv, 'crv', [pm.nt.Transform]) general.check_type(loc, 'loc', [pm.nt.Transform]) general.check_type(num_jnts, 'num_jnts', [int]) general.check_type(num_cnts, 'num_cnts', [int]) general.check_type(order, 'order', [str]) if reg_node: general.check_type(reg_node, 'reg_node', [pm.nt.Transform]) general.check_type(log, 'log', [bool]) if num_jnts < 5 or num_jnts > 50: raise errors.InputError('num_jnts', num_jnts, 'Value Range: 5 - 50') if num_cnts < 2 or num_jnts > 20: raise errors.InputError('num_cnts', num_cnts, 'Value Range: 2 - 20') if order not in ['xyz', 'xzy', 'yxz', 'yzx', 'zxy', 'zyx']: raise errors.InputError('order', order, 'String: xyz, ...') if not reg_node: reg_node = control.create_register_node(name) # -Make joint chain # -- Duplicate loc and call build script dup_loc = loc.duplicate()[0] reg_node, chain = utils.build_joint_chain(name, crv, order, num_jnts, dup_loc, reg_node) pm.delete(dup_loc) # -Make curve (duplicate / rebuild) ik_crv = crv.duplicate(name='%s_ik_curve' % name)[0] pm.rebuildCurve(ik_crv, s=20) # -Make spline IK handle = pm.ikHandle(name='%s_ikHandle' % name, sj=chain[0], ee=chain[-1], c=ik_crv, ccv=False, rtm=False, sol='ikSplineSolver')[0] # -Ik curve jnts dup_loc = loc.duplicate()[0] temp, ikCrvJnts = utils.build_joint_chain('%s_ikCrv' % name, crv, order, num_cnts, dup_loc) pm.delete(dup_loc) pm.delete(temp) for j in ikCrvJnts: try: pm.parent(j, w=1) except: pass # -Make controls count = 1 cnts = [] for j in ikCrvJnts: # Create curve reg_node, cnt_crv = control.\ create_curve(name='%s%s_ik_cnt' % (name, count), typ='circle', scale=1.0, color='yellow', reg_node=reg_node) # Match curve to object control.match_object(cnt_crv, j) # Setup heirarchy pm.parent(j, cnt_crv) # Create heirarchy control.create_heirarchy(name='%s_%s' % (name, count), obj=cnt_crv, num=3) cnts.append(cnt_crv) count += 1 # Build plane for follicles, for controls plane = utils.build_plane('%s_ik_' % name, crv, 20, 'v', 'x', 0.5) # Create follicles follicles = [] incr = 1/float(num_cnts) param = incr for c in cnts[1:-1]: fol = pm.createNode('transform', n='%s_fol' % c.name(), ss=True) folShape = pm.createNode('follicle', n=fol.name()+'Shape', p=fol, ss=True) plane.local >> folShape.inputSurface plane.worldMatrix[0] >> folShape.inputWorldMatrix folShape.outRotate >> fol.rotate folShape.outTranslate >> fol.translate fol.inheritsTransform.set(False) folShape.parameterU.set(0.5) folShape.parameterV.set(param) param += incr follicles.append(fol) # -Setup controls cnts_grp = pm.group(name='%s_cnts_grp' % name, em=1) count = 0 for cnt in cnts[1:-1]: prnt = cnt.getParent() mid = prnt.getParent() top = mid.getParent() # --Grouping pm.parent(top, follicles[count]) count += 1 count = 0 for cnt in [cnts[0], cnts[-1]]: prnt = cnt.getParent() mid = prnt.getParent() top = mid.getParent() # --Grouping pm.parent(top, cnts_grp) count += 1 # Skin ik curve to control joints pm.skinCluster(ikCrvJnts, ik_crv, tsb=True, name='%s_ikCrv_sc' % name) # Skin plane curve to top/btm control joints pm.skinCluster(ikCrvJnts[0], ikCrvJnts[-1], plane, tsb=True, name='%s_ikPlane_sc' % name) # -Make Advance Spline ik_crv.inheritsTransform.set(0) # Enable Adv Ik / Set: Up Object (start/end) handle.dTwistControlEnable.set(1) handle.dWorldUpType.set(2) up_loc1 = pm.spaceLocator(name='%s_AdvIkUpObj1_loc' % name) up_loc2 = pm.spaceLocator(name='%s_AdvIkUpObj2_loc' % name) pm.parent(up_loc1, cnts[0]) pm.parent(up_loc2, cnts[-1]) for loc in [up_loc1, up_loc2]: loc.setTranslation(0) loc.setRotation([0, 0, 0]) attr = getattr(loc, 't%s' % order[1].lower()) attr.set(5) loc.visibility.set(0) up_loc1.worldMatrix >> handle.dWorldUpMatrix up_loc2.worldMatrix >> handle.dWorldUpMatrixEnd # Create poly planes to aid in skinning nurbs plane and curve polyPlane = pm.nurbsToPoly(plane, mnd=1, ch=0, f=0, pt=1, pc=20, chr=0.9, ft=0.01, mel=0.001, d=0.1, ut=1, un=3, vt=1, vn=3, uch=0, ucr=0, cht=0.2, es=0, ntr=0, mrt=0, uss=1)[0] polyCrvPlane = pm.nurbsToPoly(plane, mnd=1, ch=0, f=0, pt=1, pc=20, chr=0.9, ft=0.01, mel=0.001, d=0.1, ut=1, un=3, vt=1, vn=3, uch=0, ucr=0, cht=0.2, es=0, ntr=0, mrt=0, uss=1)[0] p1 = pm.PyNode(polyPlane) p1.rename('%s_nurbsPlaneAide' % name) p2 = pm.PyNode(polyCrvPlane) p2.rename('%s_ikCrvAide' % name) pm.skinCluster(ikCrvJnts, p2, tsb=1, name='%s_ikCrvAide_sc' % name) pm.skinCluster(ikCrvJnts[0], ikCrvJnts[-1], p1, tsb=1, name='%s_nurbsPlaneAide_sc' % name) # Clean up for j in ikCrvJnts: j.hide() fol_grp = pm.group(n='%s_follicle_grp' % name, em=1) dont_mov_grp = pm.group(n='%s_dont_move_grp' % name, em=1) skin_jnts_grp = pm.group(n='%s_ik_skin_jnts_grp' % name, em=1) dont_mov_grp.translate.lock() dont_mov_grp.rotate.lock() dont_mov_grp.hide() pm.parent(follicles, fol_grp) pm.parent(chain[0], skin_jnts_grp) pm.parent(handle, plane, ik_crv, p1, p2, dont_mov_grp) main_grp = pm.group(n='%s_ik_rig_grp' % name, em=1) pm.parent(fol_grp, dont_mov_grp, skin_jnts_grp, cnts_grp, main_grp) # Register joint chain and ik_crv control.register_object(reg_node, 'ik_top_node', main_grp) control.register_object(reg_node, 'ik_crv', ik_crv) return reg_node
def build_joint_chain(name=None, crv=None, order=None, num=None, loc=None, reg_node=None, log=False): '''Given a valid curve, build joint chain along curve, num joints long Attributes: name -- Prefix name for plane. Str crv -- Curve to use as build guide. pm.nt.Transform order -- ['xyz','xzy','yxz','yzx','zxy','zyx'] num -- Number of joints. 3 - 50, Int loc -- Used to set aim of secondary axis nt.Transform reg_node -- Registratioin node. nt.Transform log -- Output logging messages. Bool ''' general.check_type(name, 'name', [str]) general.check_type(crv, 'crv', [pm.nt.Transform]) general.check_type(order, 'order', [str]) general.check_type(num, 'num', [int]) general.check_type(loc, 'loc', [pm.nt.Transform]) orders = ['xyz', 'xzy', 'yxz', 'yzx', 'zxy', 'zyx'] if order not in orders: raise errors.InputError('order', order, orders) if num < 3 or num > 50: raise errors.InputError('num', num, 'Range: 3 - 50') loc = loc.duplicate()[0] chain = [] loc_v = None incr = float(1.0/num) if log: str_1 = 'Curve Length: ', pm.arclen(crv) str_2 = 'Increment: ', incr general.logging.debug(str_1) general.logging.debug(str_2) param = 0 pm.select(clear=1) for i in range(num): pos = pm.pointOnCurve(crv, pr=param, p=True, top=True) if i == 0: # Get vector to locator pos_v = pm.dt.Vector(pos) loc_pos = pm.dt.Vector(pm.xform(loc, q=1, ws=1, rp=1)) loc_v = loc_pos - pos_v if log: str_1 = 'Jnt Pos: ', pos_v str_2 = 'Loc Pos: ', loc_pos str_3 = 'Loc Vec: ', loc_v general.logging.debug(str_1) general.logging.debug(str_2) general.logging.debug(str_3) j = pm.joint(p=pos, name='%s_Jnt_%s' % (name, (i+1))) chain.append(j) if log: str_1 = 'Created Joint: ', j str_2 = 'Parameter: ', param str_3 = 'Pos: ', pos str_4 = 'Curve: ', crv general.logging.debug(str_1) general.logging.debug(str_2) general.logging.debug(str_3) general.logging.debug(str_4) param += incr if log: str_1 = 'Chain: ', str(chain) general.logging.debug(str_1) # aim vector aim_v = [] if order[0].lower() == 'x': aim_v = [1, 0, 0] if order[0].lower() == 'y': aim_v = [0, 1, 0] if order[0].lower() == 'z': aim_v = [0, 0, 1] # up vector up_v = [] if order[1].lower() == 'x': up_v = [1, 0, 0] if order[1].lower() == 'y': up_v = [0, 1, 0] if order[1].lower() == 'z': up_v = [0, 0, 1] for jnt in chain[:-1]: # Snap/parent locator to jnt pm.parent(loc, jnt) loc.setTranslation(0) loc.setRotation([0, 0, 0]) # move by loc_v pm.move(loc_v[0], loc_v[1], loc_v[2], loc, r=1) pm.parent(loc, w=1) # Remove joint from hierarchy p = jnt.getParent() c = jnt.getChildren() try: pm.parent(jnt, w=1) except: pass pm.parent(c, w=1) # Aim to child pm.delete(pm.aimConstraint(c, jnt, aim=aim_v, wu=up_v, wut='object', wuo=loc, mo=0)) # Reinsert to heirarchy if c: pm.parent(c, jnt) if p: pm.parent(jnt, p) # Oreint last joint to none pm.joint(chain[-1], e=1, oj='none', zso=True) if not reg_node: reg_node = control.create_register_node(name) control.register_object(reg_node, '%s_chain_root' % name, chain[0]) pm.select(clear=1) pm.delete(loc) return reg_node, chain
def build_joint_chain(name=None, crv=None, order=None, num=None, loc=None, reg_node=None, log=False): '''Given a valid curve, build joint chain along curve, num joints long Attributes: name -- Prefix name for plane. Str crv -- Curve to use as build guide. pm.nt.Transform order -- ['xyz','xzy','yxz','yzx','zxy','zyx'] num -- Number of joints. 3 - 50, Int loc -- Used to set aim of secondary axis nt.Transform reg_node -- Registratioin node. nt.Transform log -- Output logging messages. Bool ''' general.check_type(name, 'name', [str]) general.check_type(crv, 'crv', [pm.nt.Transform]) general.check_type(order, 'order', [str]) general.check_type(num, 'num', [int]) general.check_type(loc, 'loc', [pm.nt.Transform]) orders = ['xyz', 'xzy', 'yxz', 'yzx', 'zxy', 'zyx'] if order not in orders: raise errors.InputError('order', order, orders) if num < 3 or num > 50: raise errors.InputError('num', num, 'Range: 3 - 50') loc = loc.duplicate()[0] chain = [] loc_v = None incr = float(1.0 / num) if log: str_1 = 'Curve Length: ', pm.arclen(crv) str_2 = 'Increment: ', incr general.logging.debug(str_1) general.logging.debug(str_2) param = 0 pm.select(clear=1) for i in range(num): pos = pm.pointOnCurve(crv, pr=param, p=True, top=True) if i == 0: # Get vector to locator pos_v = pm.dt.Vector(pos) loc_pos = pm.dt.Vector(pm.xform(loc, q=1, ws=1, rp=1)) loc_v = loc_pos - pos_v if log: str_1 = 'Jnt Pos: ', pos_v str_2 = 'Loc Pos: ', loc_pos str_3 = 'Loc Vec: ', loc_v general.logging.debug(str_1) general.logging.debug(str_2) general.logging.debug(str_3) j = pm.joint(p=pos, name='%s_Jnt_%s' % (name, (i + 1))) chain.append(j) if log: str_1 = 'Created Joint: ', j str_2 = 'Parameter: ', param str_3 = 'Pos: ', pos str_4 = 'Curve: ', crv general.logging.debug(str_1) general.logging.debug(str_2) general.logging.debug(str_3) general.logging.debug(str_4) param += incr if log: str_1 = 'Chain: ', str(chain) general.logging.debug(str_1) # aim vector aim_v = [] if order[0].lower() == 'x': aim_v = [1, 0, 0] if order[0].lower() == 'y': aim_v = [0, 1, 0] if order[0].lower() == 'z': aim_v = [0, 0, 1] # up vector up_v = [] if order[1].lower() == 'x': up_v = [1, 0, 0] if order[1].lower() == 'y': up_v = [0, 1, 0] if order[1].lower() == 'z': up_v = [0, 0, 1] for jnt in chain[:-1]: # Snap/parent locator to jnt pm.parent(loc, jnt) loc.setTranslation(0) loc.setRotation([0, 0, 0]) # move by loc_v pm.move(loc_v[0], loc_v[1], loc_v[2], loc, r=1) pm.parent(loc, w=1) # Remove joint from hierarchy p = jnt.getParent() c = jnt.getChildren() try: pm.parent(jnt, w=1) except: pass pm.parent(c, w=1) # Aim to child pm.delete( pm.aimConstraint(c, jnt, aim=aim_v, wu=up_v, wut='object', wuo=loc, mo=0)) # Reinsert to heirarchy if c: pm.parent(c, jnt) if p: pm.parent(jnt, p) # Oreint last joint to none pm.joint(chain[-1], e=1, oj='none', zso=True) if not reg_node: reg_node = control.create_register_node(name) control.register_object(reg_node, '%s_chain_root' % name, chain[0]) pm.select(clear=1) pm.delete(loc) return reg_node, chain