def add_controller_tag(ctl, tagParent=None): """Add a controller tag Args: ctl (dagNode): Controller to add the tar tagParent (dagNode): tag parent for the connection """ if versions.current() >= 201650: pm.controller(ctl) ctt = pm.PyNode(pm.controller(ctl, q=True)[0]) if tagParent: controller_tag_connect(ctt, tagParent) return ctt
def addCtl(self, parent, name, m, color, iconShape, **kwargs): """Create the control and apply the shape, if this is alrealdy stored in the guide controllers grp. Args: parent (dagNode): The control parent name (str): The control name. m (matrix): The transfromation matrix for the control. color (int or list of float): The color for the control in index or RGB. iconShape (str): The controls default shape. kwargs (variant): Other arguments for the iconShape type variations Returns: dagNode: The Control. """ if "degree" not in kwargs.keys(): kwargs["degree"] = 1 bufferName = name + "_controlBuffer" if bufferName in self.guide.controllers.keys(): ctl_ref = self.guide.controllers[bufferName] ctl = primitive.addTransform(parent, name, m) for shape in ctl_ref.getShapes(): ctl.addChild(shape, shape=True, add=True) pm.rename(shape, name + "Shape") else: ctl = icon.create(parent, name, m, color, iconShape, **kwargs) self.addToGroup(ctl, "controllers") # Set the control shapes isHistoricallyInteresting for oShape in ctl.getShapes(): oShape.isHistoricallyInteresting.set(False) # connecting the always draw shapes on top to global attribute if versions.current() >= 20220000: pm.connectAttr( self.ctlXRay_att, oShape.attr("alwaysDrawOnTop") ) # set controller tag if versions.current() >= 201650: pm.controller(ctl) self.add_controller_tag(ctl, None) attribute.addAttribute(ctl, "isCtl", "bool", keyable=False) return ctl
def controller_tag_connect(ctt, tagParent): """Summary Args: ctt (TYPE): Teh control tag tagParent (TYPE): The object with the parent control tag """ if pm.controller(tagParent, q=True): tpTagNode = pm.PyNode(pm.controller(tagParent, q=True)[0]) tpTagNode.cycleWalkSibling.set(True) pm.connectAttr(tpTagNode.prepopulate, ctt.prepopulate, f=True) ni = attribute.get_next_available_index(tpTagNode.children) pm.disconnectAttr(ctt.parent) pm.connectAttr(ctt.parent, tpTagNode.attr("children[%s]" % str(ni)))
def isController(obj): """ Checks if given object is a controller (has a controller tag node attached). :param obj: object to check :type obj: str or PyNode :return: True if object is controller, False if not. :rtype: bool """ return pm.controller(obj, q=1, ic=1)
def getTag(node): """ Gets the tag associated with the given node, if none given a tag is created. Args: node (pm.nodetypes.DependNode): node to find tag of. Returns: (pm.nodetypes.Controller): Tag associated with given nodes. """ tag = node.message.connections(scn=False, d=True, type='controller') if not tag: pm.controller(node) # make controller tag if none found return getTag( node ) # pm.controller does not return anything, so use getTag to get the node return tag[0]
def add_controller_tag(ctl, tagParent=None): """Add a controller tag Args: ctl (dagNode): Controller to add the tar tagParent (dagNode): tag parent for the connection """ pm.controller(ctl) ctt = pm.PyNode(pm.controller(ctl, q=True)[0]) if tagParent: tpTagNode = pm.PyNode(pm.controller(tagParent, q=True)[0]) tpTagNode.cycleWalkSibling.set(True) pm.connectAttr(tpTagNode.prepopulate, ctt.prepopulate, f=True) # The connectAttr to the children attribute is giving error # i.e: pm.connectAttr(ctt.attr("parent"), # tpTagNode.attr("children"), na=True) # if using the next available option tag # I was expecting to use ctt.setParent(tagParent) but doest't work as # expected. # After reading the documentation this method looks prety # useless. # Looks like is boolean and works based on selection :( # this is a dirty loop workaround. Naaah! i = 0 while True: try: pm.connectAttr(ctt.parent, tpTagNode.attr("children[%s]" % str(i))) break except RuntimeError: i += 1 if i > 100: pm.displayWarning( "The controller tag for %s has reached the " "limit index of 100 children" % ctl.name()) break return ctt
def addCtl(self, parent, name, m, color, iconShape, **kwargs): """Create the control and apply the shape, if this is alrealdy stored in the guide controllers grp. Args: parent (dagNode): The control parent name (str): The control name. m (matrix): The transfromation matrix for the control. color (int or list of float): The color for the control in index or RGB. iconShape (str): The controls default shape. kwargs (variant): Other arguments for the iconShape type variations Returns: dagNode: The Control. """ bufferName = name + "_controlBuffer" if bufferName in self.guide.controllers.keys(): ctl_ref = self.guide.controllers[bufferName] ctl = primitive.addTransform(parent, name, m) for shape in ctl_ref.getShapes(): ctl.addChild(shape, shape=True, add=True) else: ctl = icon.create(parent, name, m, color, iconShape, **kwargs) self.addToGroup(ctl, "controllers") # Set the control shapes isHistoricallyInteresting for oShape in ctl.getShapes(): oShape.isHistoricallyInteresting.set(False) # set controller tag if versions.current() >= 201650: pm.controller(ctl) return ctl
def rig(self, skeleton_dict, side, region, world_space=False, control_holder_list=None, use_global_queue=False, additive=False, reverse=False, **kwargs): if not self.valid_check(skeleton_dict, side, region): return False autokey_state = pm.autoKeyframe(q=True, state=True) pm.autoKeyframe(state=False) # Start Component Creation super(IK, self).rig(skeleton_dict, side, region, world_space, not use_global_queue, **kwargs) character_category = v1_core.global_settings.GlobalSettings( ).get_category(v1_core.global_settings.CharacterSettings) control_grp = self.create_control_grp(side, region) maya_utils.node_utils.force_align(self.skel_root, control_grp) world_group = self.create_world_grp(side, region) rigging_chain = self.network['rigging'].get_connections() rigging_chain = rigging.skeleton.sort_chain_by_hierarchy(rigging_chain) ik_solved_chain = rigging.skeleton.duplicate_chain( rigging_chain, self.namespace, 'ik_solved', self.prefix) ik_solved_chain_root = rigging.skeleton.get_chain_root(ik_solved_chain) ik_solved_chain_root.setParent(self.network['component'].group) ik_solver = 'ikRPsolver' if len(rigging_chain) > 2 else 'ikSCsolver' ik_handle, end_effector = pm.ikHandle( sj=ik_solved_chain[-1], ee=get_first_or_default(ik_solved_chain), sol=ik_solver, name="{0}{1}_{2}_ikHandle".format(self.namespace, side, region)) ik_handle.setParent(world_group) rigging.skeleton.force_set_attr(ik_handle.visibility, False) control_chain = rigging.skeleton.duplicate_chain( [get_first_or_default(rigging_chain)], self.namespace, 'control', self.prefix) control_root = rigging.skeleton.get_chain_root(control_chain) check_world_orient_ik = kwargs.get('world_orient_ik') if kwargs.get( 'world_orient_ik') != None else character_category.world_orient_ik if check_world_orient_ik: control_root.setParent(None) control_root.jointOrient.set([0, 0, 0]) control_root.rotate.set([0, 0, 0]) self.network['component'].set('ik_local_orient', not check_world_orient_ik, 'bool') control_root.setParent(world_group) self.network['controls'].connect_nodes(control_chain) self.create_controls(control_chain, side, region, 'ik_handle', control_holder_list) for control in control_chain: control_property = metadata.meta_properties.get_property( control, metadata.meta_properties.ControlProperty) control_property.set('world_space', True, 'bool') skel_root = skeleton_dict[side][region]['root'] skel_end = skeleton_dict[side][region]['end'] skeleton_chain = rigging.skeleton.get_joint_chain(skel_root, skel_end) if len(rigging_chain) > 2: pv_position = rigging.skeleton.calculate_pole_vector_position( rigging_chain, pm.currentTime()) pm.select( None ) # select None to make sure joint doesn't parent to anything pv_control = pm.joint(name="{0}control_{1}_{2}_ik_pv".format( self.namespace, side, region), position=pv_position) pv_control.setParent(world_group) pm.poleVectorConstraint(pv_control, ik_handle) self.network['controls'].connect_node(pv_control) self.create_controls([pv_control], side, region, 'pv', control_holder_list) pm.controller( [pv_control, get_first_or_default(control_chain)], p=True) pv_control_property = metadata.meta_properties.get_property( pv_control, metadata.meta_properties.ControlProperty) pv_control_property.set('world_space', True, 'bool') pm.parentConstraint(self.character_root, world_group, mo=True) pm.pointConstraint(get_first_or_default(control_chain), ik_handle, mo=False) self.attach_component(True) if rigging.skeleton.is_animated(skeleton_chain): self.attach_and_bake(self.skeleton_dict, use_global_queue) if use_global_queue: if not additive: maya_utils.baking.Global_Bake_Queue().add_post_process( self.save_animation, {}) maya_utils.baking.Global_Bake_Queue().add_post_process( self.bind_chain_process, { 'rigging_chain': rigging_chain, 'ik_solved_chain': ik_solved_chain, 'skeleton_chain': skeleton_chain, 'control_chain': control_chain, 'additive': additive }) else: if not additive: self.save_animation() self.bind_chain_process(rigging_chain, ik_solved_chain, skeleton_chain, control_chain, additive) pm.autoKeyframe(state=autokey_state) return True
def addCtl(self, parent, name, m, color, icon, tp=None, **kwargs): """ Create the control and apply the shape, if this is alrealdy stored in the guide controllers grp. Args: parent (dagNode): The control parent name (str): The control name. m (matrix): The transfromation matrix for the control. color (int or list of float): The color for the control in idex or RGB. icon (str): The controls default shape. tp (dagNode): Tag Parent Control object to connect as a parent controller kwargs (variant): Other arguments for the icon type variations. Returns: dagNode: The Control. """ fullName = self.getName(name) bufferName = fullName + "_controlBuffer" if bufferName in self.rig.guide.controllers.keys(): ctl_ref = self.rig.guide.controllers[bufferName] ctl = pri.addTransform(parent, fullName, m) for shape in ctl_ref.getShapes(): ctl.addChild(shape, shape=True, add=True) pm.rename(shape, fullName + "Shape") ico.setcolor(ctl, color) else: ctl = ico.create(parent, fullName, m, color, icon, **kwargs) # create the attributes to handlde mirror and symetrical pose att.addAttribute(ctl, "invTx", "bool", 0, keyable=False, niceName="Invert Mirror TX") att.addAttribute(ctl, "invTy", "bool", 0, keyable=False, niceName="Invert Mirror TY") att.addAttribute(ctl, "invTz", "bool", 0, keyable=False, niceName="Invert Mirror TZ") att.addAttribute(ctl, "invRx", "bool", 0, keyable=False, niceName="Invert Mirror RX") att.addAttribute(ctl, "invRy", "bool", 0, keyable=False, niceName="Invert Mirror RY") att.addAttribute(ctl, "invRz", "bool", 0, keyable=False, niceName="Invert Mirror RZ") att.addAttribute(ctl, "invSx", "bool", 0, keyable=False, niceName="Invert Mirror SX") att.addAttribute(ctl, "invSy", "bool", 0, keyable=False, niceName="Invert Mirror SY") att.addAttribute(ctl, "invSz", "bool", 0, keyable=False, niceName="Invert Mirror SZ") if self.settings["ctlGrp"]: ctlGrp = self.settings["ctlGrp"] self.addToGroup(ctl, ctlGrp, "controllers") else: ctlGrp = "controllers" self.addToGroup(ctl, ctlGrp) #lock the control parent attributes if is not a control if parent not in self.groups[ctlGrp]: self.transform2Lock.append(parent) # Set the control shapes isHistoricallyInteresting for oShape in ctl.getShapes(): oShape.isHistoricallyInteresting.set(False) #set controller tag if versions.current() >= 201650: try: oldTag = pm.PyNode(ctl.name() + "_tag") if not oldTag.controllerObject.connections(): # NOTE: The next line is comment out. Because this will happend alot since maya does't clean # controller tags after deleting the control Object of the tag. This have been log to Autodesk. # If orphane tags are found, it will be clean in silence. # pm.displayWarning("Orphane Tag: %s will be delete and created new for: %s"%(oldTag.name(), ctl.name())) pm.delete(oldTag) except: pass pm.controller(ctl) if tp: ctt = pm.PyNode(pm.controller(ctl, q=True)[0]) tpTagNode = pm.PyNode(pm.controller(tp, q=True)[0]) tpTagNode.cycleWalkSibling.set(True) pm.connectAttr(tpTagNode.prepopulate, ctt.prepopulate, f=True) # The connectAttr to the children attribute is giving error # i.e: pm.connectAttr(ctt.attr("parent"), tpTagNode.attr("children"), na=True) # if using the next available option tag # I was expecting to use ctt.setParent(tp) but doest't work as expected. # After reading the documentation this method looks prety useless. # Looks like is boolean and works based on selection :( # this is a dirty loop workaround. Naaah! i = 0 while True: try: pm.connectAttr(ctt.parent, tpTagNode.attr("children[%s]" % str(i))) break except: i += 1 if i > 100: pm.displayWarning( "The controller tag for %s has reached the limit index of 100 children" % ctl.name()) break return ctl
def create(transform, shape=curve.circle, name='control', axis='y', color='pink', scale=1.0, matrix_offset=True, parent=None, size=None, *args, **kwargs): """ Creates a control with the given shape, color, orientation, offset, and parent. Args: transform (pm.nodetypes.Transform): Transform to match control onto. shape (method): Creates control curve. name (string): Name of control. axis (string): Orientation for control. color (string): Color of curve. scale (float): Scale to multiply by joint radius. matrix_offset (boolean): If True, will zero out transform and place it in parent Offset Matrix attribute. parent (pm.nodetypes.Transform or None): If given, will parent control or group under given parent. size (list): If given, will use this as the size to set the scale of the control *args (Any): Used in shape method. **kwargs (Any): Used in shape method. Returns: (pm.nodetypes.Transform): Control made. """ control = shape(name=name + pcfg.control_suffix, *args, **kwargs) curve.color(control, color) pm.controller(control) if not size: size = calculateSize(transform) size = [xyz * scale for xyz in size] control.s.set(size) if axis == 'x': control.rz.set(control.rz.get() + 90) if axis == 'nx': control.rz.set(control.rz.get() - 90) elif axis == 'z': control.rx.set(control.rx.get() + 90) elif axis == 'nz': control.rx.set(control.rx.get() - 90) myu.freezeTransformations(control) if parent: if matrix_offset: pm.matchTransform(control, transform) pm.parent(control, parent) xform.toOffsetMatrix(control) else: pm.matchTransform(control, transform) pm.parent(control, parent) tagAsControllerParent(control, parent) else: if matrix_offset: control.offsetParentMatrix.set(transform.worldMatrix.get()) else: pm.matchTransform(control, transform) attribute.nonKeyable(control.visibility) return control
def rig(self, skeleton_dict, side, region, world_space=True, control_holder_list=None, use_global_queue=False, additive=False, reverse=False, **kwargs): if not self.valid_check(skeleton_dict, side, region): return False autokey_state = pm.autoKeyframe(q=True, state=True) pm.autoKeyframe(state=False) super(ReverseFoot, self).rig(skeleton_dict, side, region, world_space, not use_global_queue, **kwargs) character_category = v1_core.global_settings.GlobalSettings( ).get_category(v1_core.global_settings.CharacterSettings) control_grp = self.create_control_grp(side, region) maya_utils.node_utils.force_align(self.skel_root, control_grp) skeleton_chain = self.network['skeleton'].get_connections() skeleton_chain = rigging.skeleton.sort_chain_by_hierarchy( skeleton_chain) rigging_chain = self.network['rigging'].get_connections() control_chain = rigging.skeleton.duplicate_chain( rigging_chain, self.namespace, 'control', self.prefix) rigging.skeleton.reverse_joint_chain(control_chain) self.network['controls'].connect_nodes(control_chain) control_root = rigging.skeleton.get_chain_root(control_chain) control_root.setParent(control_grp) rigging_chain = rigging.skeleton.sort_chain_by_hierarchy(rigging_chain) control_chain = rigging.skeleton.sort_chain_by_hierarchy(control_chain) control_chain.reverse() toe_joint = skeleton_chain[-3] toe_children = toe_joint.getChildren(type='joint') toe_ik_joint = get_first_or_default( [x for x in toe_children if x not in skeleton_chain]) toe_ik_control = None if toe_ik_joint: toe_ik_control = get_first_or_default(pm.duplicate(toe_ik_joint)) toe_ik_control.rename(self.namespace + 'control_' + toe_ik_joint.name()) toe_ik_control.setParent(get_index_or_default(control_chain, -3)) self.network['controls'].connect_node(toe_ik_control) control_chain_start = get_first_or_default(control_chain) control_chain_end = get_last_or_default(control_chain) # Orient heel joint to world space if character_category.world_orient_ik: control_chain[1].setParent(None) control_chain_start.setParent(None) control_chain_start.jointOrient.set([0, 0, 0]) control_chain_start.rotate.set([0, 0, 0]) pm.delete( pm.aimConstraint(toe_joint, control_chain_start, aim=[0, -1, 0], upVector=[0, 0, 1], wut="scene", mo=False)) control_chain_start.setParent(control_grp) control_chain[1].setParent(control_chain_start) delete_chain = rigging_chain[:-3] rigging_chain = rigging_chain[-3:] pm.delete(delete_chain) # toe_ik will be inserted as index 0 (in place of the attach jonit) if it exists, if it doesn't we want to # move all control indicies up 1 since we don't allow control of the attach joint index_offset = -1 if toe_ik_joint: index_offset = 0 rigging.skeleton.force_set_attr(toe_ik_joint.visibility, False) rigging.skeleton.force_set_attr(toe_ik_control.visibility, True) self.create_controls([toe_ik_control], side, region, 'toe_ik', control_holder_list) self.create_controls(control_chain, side, region, 'reverse_fk', control_holder_list, index_offset) control_property = metadata.meta_properties.get_property( control_chain_start, metadata.meta_properties.ControlProperty) control_property.set('world_space', True, 'bool') for i, child_control in enumerate(control_chain[:-1]): pm.controller([control_chain[i + 1], child_control], p=True) ball_ik_handle, end_effector = pm.ikHandle( sj=rigging_chain[2], ee=rigging_chain[1], sol='ikSCsolver', name="{0}{1}_{2}_rv_ball_ikHandle".format(self.namespace, side, region)) ball_ik_handle.setParent(control_chain[-2]) rigging.skeleton.force_set_attr(ball_ik_handle.visibility, False) toe_ik_handle, end_effector = pm.ikHandle( sj=rigging_chain[1], ee=rigging_chain[0], sol='ikSCsolver', name="{0}{1}_{2}_rv_toe_ikHandle".format(self.namespace, side, region)) ik_parent = toe_ik_control if toe_ik_joint else control_chain[-3] toe_ik_handle.setParent(ik_parent) rigging.skeleton.force_set_attr(toe_ik_handle.visibility, False) control_chain_end.rename(control_chain_end + "_attach") self.network['attachment'].connect_node(skeleton_chain[-1]) for control in control_chain[:-1]: rigging.skeleton.force_set_attr(control.visibility, True) rigging.skeleton.force_set_attr(control_chain_end.visibility, False) rigging.skeleton.force_set_attr(skeleton_chain[-3].visibility, False) rigging.skeleton.force_set_attr(rigging_chain[-1].visibility, False) rigging.constraints.bind_chains([control_chain_end], [rigging_chain[2]], self.exclude) self.attach_component(True) if rigging.skeleton.is_animated(skeleton_chain): self.attach_and_bake(self.skeleton_dict, use_global_queue) if not use_global_queue: rigging.skeleton.remove_animation(skeleton_chain) if use_global_queue: if not additive: maya_utils.baking.Global_Bake_Queue().add_post_process( self.save_animation, {}) maya_utils.baking.Global_Bake_Queue().add_post_process( self.bind_chain_process, { 'skeleton_chain': skeleton_chain, 'rigging_chain': rigging_chain }) else: if not additive: self.save_animation() self.bind_chain_process(skeleton_chain, rigging_chain) pm.autoKeyframe(state=autokey_state) return True