def hookOnCurve(mode=1, tangent=False): sel = pm.ls(sl=True) crv = sel[-1] sampleNPoC = pm.createNode('nearestPointOnCurve') sampleGrpA = pm.group(empty=True) crv.worldSpace[0] >> sampleNPoC.inputCurve sampleGrpA.translate >> sampleNPoC.inPosition for obj in sel[:-1]: wp = pm.xform(obj, t=True, ws=True, q=True) pm.xform(sampleGrpA, t=wp, ws=True) hookPar = sampleNPoC.parameter.get() if mode == 1: hookPoci = pm.createNode('pointOnCurveInfo') crv.worldSpace[0] >> hookPoci.inputCurve hookPoci.position >> obj.translate hookPoci.parameter.set(hookPar) if tangent: pm.tangentConstraint(crv, obj, aimVector=(-1, 0, 0), upVector=(0, 1, 0), worldUpType="vector", worldUpVector=(0, 1, 0)) elif mode == 2: mpathName = pm.pathAnimation(obj, c=crv) mpath = pm.PyNode(mpathName) deleteConnection(mpath.uValue) mpath.uValue.set(hookPar) pm.delete(sampleNPoC, sampleGrpA)
def rig_attachToCurve(obj, crv, createGroup=True, constrainParent=False): ''' attaches an object to a curve Args: obj (pm.PyNode): Object to constrain to crv (pm.nt.NurbsCurve): Curve to get info from constrainParent (bool): if we constrain to the object's parent instead of the object Returns (pm.shadingNode.pointOnCurveInfo): pointOnCurveInfo node that results Usage: rig_attachToCurve(pm.ls(sl=True), pm.PyNode('curve1'), createGroup=False, constrainParent=False) for obj in pm.ls(sl=True): rig_attachToCurve(obj, pm.PyNode('curve1'), createGroup=False, constrainParent=False) ''' passArgs=[None,None] if constrainParent and obj.getParent(): passArgs = [obj.getParent(),obj.getParent()] elif not obj.getParent() and constrainParent: pm.error('Could not find a parent for object %s'%obj) return None elif createGroup: grp=pm.group(em=True, n='_'.join([obj.name(),crv.name(),'Offset_GRP'])) grp.inheritsTransform.set(0) grp.t.set(obj.getRotatePivot(space='world')) grp.r.set(pm.xform(obj, q=True, ro=True, a=True, ws=True)) pm.addAttr(grp, ln='connectPCObj', dt='string', k=True) passArgs=[obj,grp] else: passArgs=[obj, obj] poci = rig_getClosestPointNode(passArgs[0], crv, cpoc=True) mdpma = rig_connectPociWithOffset(poci, passArgs[1]) pm.tangentConstraint(crv, passArgs[1]) return [passArgs[1], poci] + mdpma
def hookJntsOnCurve(self, jntList, upList, jntCrv, upCrv): jntNPoC = pm.createNode('nearestPointOnCurve', n=self.name+'NPCjnt') jntGrpA = pm.group(empty=True, n=self.name + 'jntGrp') jntCrv.worldSpace[0] >> jntNPoC.inputCurve jntGrpA.translate >> jntNPoC.inPosition upNPoC = pm.createNode('nearestPointOnCurve', n=self.name+'NPCup') upGrpA = pm.group(empty=True, n=self.name + 'upGrpA') upCrv.worldSpace[0] >> upNPoC.inputCurve upGrpA.translate >> upNPoC.inPosition for jnt, up in zip(jntList, upList): wp = pm.xform(jnt, t=True, ws=True, q=True) pm.xform(jntGrpA, t=wp, ws=True) hookPoci = pm.createNode('pointOnCurveInfo', n=self.name+'CurveInfoA') jntCrv.worldSpace[0] >> hookPoci.inputCurve hookPoci.position >> jnt.translate hookPar = jntNPoC.parameter.get() hookPoci.parameter.set(hookPar) pm.tangentConstraint(jntCrv, jnt, aimVector=(-1, 0, 0), upVector=(0, 1, 0), worldUpType="object", worldUpObject=up) wp = pm.xform(up, t=True, ws=True, q=True) pm.xform(upGrpA, t=wp, ws=True) hookPoci = pm.createNode('pointOnCurveInfo', n=self.name+'CurveInfoB') upCrv.worldSpace[0] >> hookPoci.inputCurve hookPoci.position >> up.translate hookPar = upNPoC.parameter.get() hookPoci.parameter.set(hookPar) pm.delete(upNPoC, upGrpA, jntNPoC, jntGrpA)
def orientCtrlGrp(self, grp, percent): """Given grp along self.curve at given param, ensure the grp is oriented right: with the rig's primary axis along the curve's tangent""" param = percent * self.curve.getKnotDomain()[1] pos = self.curve.getPointAtParam(param) grp.translate.set(pos) if percent == 0.0: # just make it the same as the root joint #grp.setMatrix(self.jnts[0].matrix.get()) pmc.delete(pmc.orientConstraint(self.jnts[0], grp, mo=False)) return elif percent == 1.0: # similarly, set matrix to end joint #grp.setMatrix(self.jnts[-1].matrix.get()) pmc.delete(pmc.orientConstraint(self.jnts[-1], grp, mo=False)) return axis = self.jnts[1].translate.get().normal() arc = self.jnts[1].jointOrient.get().normal() pmc.delete( pmc.tangentConstraint(self.curve, grp, aimVector=axis, upVector=arc, worldUpVector=arc, worldUpObject=self.jnts[1])) """
def curve_point(input_curve, ctrl_attr): """ Takes a curve and an attribute and drives a locator on the curve based on the attribute (0-1) Args: input_curve (pm.nt.Transform): input curve's transform ctrl_attr (pm.nt.Attribute): attribute Returns: (pm.nt.pointOnCurveInfo): point on curve info node to use if you want Usage: curve_point(pm.ls(sl=True)[0], pm.ls(sl=True)[0].translateX) """ loc = pm.spaceLocator() poci = pm.createNode('pointOnCurveInfo') poci.turnOnPercentage.set(1) input_curve.getShape().worldSpace[0].connect( poci.inputCurve ) ctrl_attr.connect( poci.parameter ) poci.position.connect( loc.translate ) pm.tangentConstraint( input_curve, loc ) return poci
def duplicate_along_curve(obj, curve, step, align=True, aimVector=(0,0,1), upVector=(0,1,0)): """ Args: obj (pm.nt.Transform): transform to duplicate across curve (pm.nt.Transform): transform with curve shape step (int): number of CVs to skip over while duplicating align (bool): align the mesh with the curve aimVector (tuple): aim vector... upVector (tuple): up vector... Returns [pm.nt.Transform]: list of generated transforms Usage: duplicate_along_curve(pm.ls(sl=True)[0], pm.ls(sl=True)[1], 2)g """ dups = [] for cv in curve.getShape().cv[::step]: dup = pm.duplicate(obj)[0] pm.xform(dup, t=cv.getPosition(space='world'), a=True) if align: pm.delete(pm.tangentConstraint(curve, dup, aimVector=aimVector, upVector=upVector, worldUpType='scene', w=1)) dups.append(dup) return dups
def orientCtrlGrp(self, grp, percent): """Given grp along self.curve at given param, ensure the grp is oriented right: with the rig's primary axis along the curve's tangent""" param = percent * self.curve.getKnotDomain()[1] pos = self.curve.getPointAtParam(param) grp.translate.set(pos) if percent == 0.0: # just make it the same as the root joint #grp.setMatrix(self.jnts[0].matrix.get()) pmc.delete(pmc.orientConstraint(self.jnts[0], grp, mo=False)) return elif percent == 1.0: # similarly, set matrix to end joint #grp.setMatrix(self.jnts[-1].matrix.get()) pmc.delete(pmc.orientConstraint(self.jnts[-1], grp, mo=False)) return axis = self.jnts[1].translate.get().normal() arc = self.jnts[1].jointOrient.get().normal() pmc.delete(pmc.tangentConstraint(self.curve, grp, aimVector=axis, upVector=arc, worldUpVector=arc, worldUpObject=self.jnts[1])) """
def setup_extrudes(curve_transforms, **kwargs): """ Sets up all attributes to control objects given curve transforms and a control Args: control (pm.nt.Transform): transform to control objects curve_transforms [pm.nt.Transform]: list of transforms with nurbsCurve shapes Returns {type:pm.nt.Transform}: a dictionary of types of objects that were created """ prefix = kwargs.get('prefix',"") control = kwargs.get('control') radius = kwargs.get('%sradius'%prefix, 1) sensitive = kwargs.get('sensitive', True) robust = kwargs.get('robust', True) nodes = {} # Create all attributes and control attrs for crv_xform in curve_transforms: # Check for pre-existing attr entry, otherwise it's been done already if not pm.objExists('%s%s.%s'%(prefix, control.name(), crv_xform.name())): # Create the circle and align it to curve with a tangent constraint circle = pm.circle() cv0_pos = crv_xform.getShape().cv[0].getPosition(space='world') pm.xform(circle, a=True, t=cv0_pos, ws=True) tc = pm.tangentConstraint(crv_xform,circle) tc.aimVectorX.set(0) # Create the extrude extrude = pm.extrude(circle[0], crv_xform, ch=True, rn=True, po=1, et=2, ucp=1, fpt=1, upn=1, rotation=0, scale=1, rsp=1) if kwargs.get('quaded'): try: tessellate = extrude[1].listConnections(type='nurbsTessellate')[0] tessellate.polygonType.set(1) tessellate.attr('format').set(3) except ValueError: print 'Couldn\'t set the tessellate, sorry!' # Now we can store the sub curve profile options path_subCurve = extrude[1].path.listConnections()[0] profile_subCurve = extrude[1].profile.listConnections()[0] # Setup the main control with some default attributes # Set up a display attr if robust if robust: control.addAttr('%s%s' % (prefix, crv_xform.name()), at='enum', k=True) control.attr('%s%s' % (prefix, crv_xform.name())).lock() # Otherwise we want only radius to display attrs = [['%s%s_radius', circle[1].radius, 1], ['%s%s_profile_min', profile_subCurve.min, 0], ['%s%s_profile_max', profile_subCurve.max, 1], ['%s%s_path_min', path_subCurve.min, 0], ['%s%s_path_max', path_subCurve.max, 1], ['%s%s_flip_normals', tc.aimVectorZ, kwargs.get('flipped')-1]] for attr, destination, val in attrs: attr = attr % (prefix, crv_xform.name()) control.addAttr(attr, at='double', dv=val, k=True) control.attr(attr).connect(destination) if 'radius' not in attr and not robust: control.attr(attr).setKeyable(0) # initialize the radius with the value from kwargs if 'radius' in attr: control.attr(attr).set(radius) # Insert multiplier to global radius attr insert_modifier(control.global_radius, circle[1].radius, type='addDoubleLinear') result = [path_subCurve, profile_subCurve, extrude[0], extrude[1], circle[0]] for node in result: try: nodetype = pm.objectType(node.getShape()) except: nodetype = pm.objectType(node) nodes.setdefault(nodetype, []) nodes[nodetype].append(node) else: print 'object %s is already connected numbnuts'%(crv_xform.name()) return nodes
def setup_extrudes(control, curve_transforms): """ Sets up all attributes to control objects given curve transforms and a control Args: control (pm.nt.Transform): transform to control objects curve_transforms [pm.nt.Transform]: list of transforms with nurbsCurve shapes Returns {type:pm.nt.Transform}: a dictionary of types of objects that were created """ nodes = {} # Create all attributes and control attrs for crv_xform in curve_transforms: # Check for pre-existing attr entry, otherwise it's been done already if not pm.objExists('%s.%s'%(control.name(), crv_xform.name())): print crv_xform # Create the circle and align it to curve with a tangent constraint circle = pm.circle() cv0_pos = crv_xform.getShape().cv[0].getPosition(space='world') pm.xform(circle, a=True, t=cv0_pos, ws=True) tc = pm.tangentConstraint(crv_xform,circle) tc.aimVectorX.set(0) # Create the extrude extrude = pm.extrude(circle[0], crv_xform, ch=True, rn=True, po=1, et=2, ucp=1, fpt=1, upn=1, rotation=0, scale=1, rsp=1) # Now we can store the sub curve profile options path_subCurve = extrude[1].path.listConnections()[0] profile_subCurve = extrude[1].profile.listConnections()[0] # Setup the main control with some default attributes control.addAttr(crv_xform.name(), at='enum', k=True) control.attr(crv_xform.name()).lock() attrs = [['%s_radius', circle[1].radius, 1], ['%s_profile_min', profile_subCurve.min, 0], ['%s_profile_max', profile_subCurve.max, 1], ['%s_path_min', path_subCurve.min, 0], ['%s_path_max', path_subCurve.max, 1], ['%s_flip_normals', tc.aimVectorZ, -1]] for attr, destination, val in attrs: attr = attr%crv_xform.name() control.addAttr(attr, at='double', dv=val, k=True) control.attr(attr).connect(destination) # Insert multiplier to global radius attr insert_modifier(control.global_radius, circle[1].radius, type='addDoubleLinear') result = [path_subCurve, profile_subCurve, extrude[0], extrude[1], circle[0]] for node in result: try: nodetype = pm.objectType(node.getShape()) except: nodetype = pm.objectType(node) nodes.setdefault(nodetype, []) nodes[nodetype].append(node) else: print 'object %s is already connected numbnuts'%(crv_xform.name()) return nodes