def build(self, create_grp_anm=True, create_grp_rig=True, connect_global_scale=True, segmentScaleCompensate=None, parent=True): """ Build the module following the provided rig rules. :param create_grp_anm: If True, a group for all the animation controller will be created. :param create_grp_rig: If True, a group for all the rig data will be created/ :param segmentScaleCompensate: If provided, the segmentScaleCompensation attribute of all the inputs will be modified. :param parent: If True, the parent_to method will be automatically called. :return: """ self.info("Building") # Disable segment scale compensate by default. # Otherwise we might have scale issues since the rig won't propagate uniform scale change. if segmentScaleCompensate is not None: for inn in self.input: if inn.hasAttr('segmentScaleCompensate'): inn.segmentScaleCompensate.set(segmentScaleCompensate) if create_grp_anm: grp_anm_name = self.get_nomenclature_anm_grp().resolve() self.grp_anm = pymel.createNode('transform', name=grp_anm_name) if create_grp_rig: grp_rig_name = self.get_nomenclature_rig_grp().resolve() self.grp_rig = pymel.createNode('transform', name=grp_rig_name) libAttr.lock_hide_trs(self.grp_rig) if connect_global_scale: # todo: keep it here? pymel.addAttr(self.grp_rig, longName='globalScale', defaultValue=1.0) self.globalScale = self.grp_rig.globalScale if parent and self.parent: parent_obj = self.get_parent_obj() if parent_obj: self.parent_to(parent_obj)
def build( self, create_grp_anm=True, create_grp_rig=True, connect_global_scale=True, segmentScaleCompensate=None, parent=True, ): """ Build the module following the provided rig rules. :param create_grp_anm: If True, a group for all the animation controller will be created. :param create_grp_rig: If True, a group for all the rig data will be created/ :param segmentScaleCompensate: If provided, the segmentScaleCompensation attribute of all the inputs will be modified. :param parent: If True, the parent_to method will be automatically called. :return: """ self.info("Building") # Disable segment scale compensate by default. # Otherwise we might have scale issues since the rig won't propagate uniform scale change. if segmentScaleCompensate is not None: for inn in self.input: if inn.hasAttr("segmentScaleCompensate"): inn.segmentScaleCompensate.set(segmentScaleCompensate) if create_grp_anm: grp_anm_name = self.get_nomenclature_anm_grp().resolve() self.grp_anm = pymel.createNode("transform", name=grp_anm_name) if create_grp_rig: grp_rig_name = self.get_nomenclature_rig_grp().resolve() self.grp_rig = pymel.createNode("transform", name=grp_rig_name) libAttr.lock_hide_trs(self.grp_rig) if connect_global_scale: # todo: keep it here? pymel.addAttr(self.grp_rig, longName="globalScale", defaultValue=1.0) self.globalScale = self.grp_rig.globalScale if parent and self.parent: parent_obj = self.get_parent_obj() if parent_obj: self.parent_to(parent_obj)
def pre_build(self, create_grp_anm=True, create_display_layers=True, **kwargs): super(RigSqueeze, self).pre_build(create_grp_anm=create_grp_anm, create_master_grp=False, create_display_layers=create_display_layers, **kwargs) if create_grp_anm: grp_anim_size = CtrlMaster._get_recommended_radius(self) self.grp_anm_master = self.build_grp( CtrlMaster, self.grp_anm_master, self.nomenclature.root_anm_master_name, size=grp_anim_size ) if create_display_layers: pymel.editDisplayLayerMembers(self.layer_anm, self.grp_anm_master, noRecurse=True) # # Create specific group related to squeeze rig convention # all_geos = libPymel.ls_root_geos() # Build All_Grp self.grp_master = self.build_grp(classRig.RigGrp, self.grp_master, self.nomenclature.root_all_name) self.grp_model = self.build_grp(classRig.RigGrp, self.grp_model, self.nomenclature.root_model_name) self.grp_proxy = self.build_grp(classRig.RigGrp, self.grp_proxy, self.nomenclature.root_proxy_name) self.grp_fx = self.build_grp(classRig.RigGrp, self.grp_fx, self.nomenclature.root_fx_name) # Parent all groups in the main grp_master pymel.parent(self.grp_anm_master, self.grp_master) pymel.parent(self.grp_anm, self.grp_anm_master) # grp_anm is not a Node, but a Ctrl self.grp_rig.setParent(self.grp_master) self.grp_fx.setParent(self.grp_master) self.grp_model.setParent(self.grp_master) self.grp_proxy.setParent(self.grp_master) self.grp_geo.setParent(self.grp_master) ''' if self.grp_jnt.getParent() is None: self.grp_jnt.setParent(self.grp_master) ''' # Lock and hide all attributes we don't want the animator to play with libAttr.lock_hide_trs(self.grp_master) libAttr.lock_hide_trs(self.grp_rig) libAttr.lock_hide_trs(self.grp_fx) libAttr.lock_hide_trs(self.grp_model) libAttr.lock_hide_trs(self.grp_proxy) libAttr.lock_hide_trs(self.grp_geo) libAttr.hide_scale(self.grp_anm) # Hide some group # self.grp_jnt.visibility.set(False) self.grp_rig.visibility.set(False) self.grp_fx.visibility.set(False) self.grp_model.visibility.set(False) # # Add root ctrl attributes specific to squeeze while preserving existing connections. # if not self.grp_anm.hasAttr(self.GROUP_NAME_DISPLAY, checkShape=False): libAttr.addAttr_separator(self.grp_anm, self.GROUP_NAME_DISPLAY) attr_display_mesh_output_attrs = {self.grp_geo.visibility} attr_display_proxy_output_attrs = {self.grp_proxy.visibility} # attr_display_ctrl_output_attrs = set( # [children.visibility for children in self.grp_anm.getChildren(type='transform')] # ) # In the past, the displayMesh attribute was a boolean and the displayProxy was also a boolean. # Now we use an enum. This mean that we need to remap. if self.grp_anm.hasAttr(self.ATTR_NAME_DISPLAY_MESH): attr_display_mesh = self.grp_anm.attr(self.ATTR_NAME_DISPLAY_MESH) if attr_display_mesh.type() == 'short': for attr_dst in attr_display_mesh.outputs(plugs=True): attr_display_mesh_output_attrs.add(attr_dst) pymel.disconnectAttr(attr_display_mesh, attr_dst) if self.grp_anm.hasAttr(self.ATTR_NAME_DISPLAY_PROXY): attr_display_proxy = self.grp_anm.attr(self.ATTR_NAME_DISPLAY_PROXY) for attr_dst in attr_display_proxy.outputs(plugs=True): attr_display_proxy_output_attrs.add(attr_dst) pymel.disconnectAttr(attr_display_proxy, attr_dst) attr_display_proxy.delete() # Create DisplayMesh attribute attr_display_mesh = self._init_attr_display_mesh() # Create DisplayCtrl attribute attr_display_ctrl = self._init_attr_display_ctrl() # Connect DisplayMesh attribute for attr_dst in attr_display_mesh_output_attrs: if not libAttr.is_connected_to(attr_display_mesh, attr_dst, max_depth=3): self.debug("Connecting {} to {}".format(attr_display_mesh, attr_dst)) attr_proxy_display_inn = libRigging.create_utility_node( 'condition', firstTerm=attr_display_mesh, secondTerm=0, colorIfTrueR=True, colorIfFalseR=False ).outColorR pymel.connectAttr(attr_proxy_display_inn, attr_dst, force=True) for attr_dst in attr_display_proxy_output_attrs: if not libAttr.is_connected_to(attr_display_mesh, attr_dst, max_depth=3): self.debug("Connecting {} to {}".format(attr_display_mesh, attr_dst)) # attr_proxy_display_inn = libRigging.create_utility_node( # 'condition', # firstTerm=attr_display_mesh, # secondTerm=0, # colorIfTrueR=True, # colorIfFalseR=False # ).outColorR pymel.connectAttr(attr_display_mesh, attr_dst, force=True)
def pre_build(self): super(RigSqueeze, self).pre_build(create_master_grp=False) # # Create specific group related to squeeze rig convention # all_geos = libPymel.ls_root_geos() # Build All_Grp self.grp_master = self.build_grp(classRig.RigGrp, self.grp_master, self.nomenclature.root_all_name) self.grp_model = self.build_grp(classRig.RigGrp, self.grp_model, self.nomenclature.root_model_name) self.grp_proxy = self.build_grp(classRig.RigGrp, self.grp_proxy, self.nomenclature.root_proxy_name) self.grp_fx = self.build_grp(classRig.RigGrp, self.grp_fx, self.nomenclature.root_fx_name) # Parent all groups in the main grp_master pymel.parent(self.grp_anm, self.grp_master) # grp_anm is not a Node, but a Ctrl self.grp_rig.setParent(self.grp_master) self.grp_fx.setParent(self.grp_master) self.grp_model.setParent(self.grp_master) self.grp_proxy.setParent(self.grp_master) self.grp_geo.setParent(self.grp_master) ''' if self.grp_jnt.getParent() is None: self.grp_jnt.setParent(self.grp_master) ''' # Lock and hide all attributes we don't want the animator to play with libAttr.lock_hide_trs(self.grp_master) libAttr.lock_hide_trs(self.grp_rig) libAttr.lock_hide_trs(self.grp_fx) libAttr.lock_hide_trs(self.grp_model) libAttr.lock_hide_trs(self.grp_proxy) libAttr.lock_hide_trs(self.grp_geo) libAttr.hide_scale(self.grp_anm) # Hide some group # self.grp_jnt.visibility.set(False) self.grp_rig.visibility.set(False) self.grp_fx.visibility.set(False) self.grp_model.visibility.set(False) # # Add root ctrl attributes specific to squeeze # if not self.grp_anm.hasAttr(self.GROUP_NAME_DISPLAY, checkShape=False): libAttr.addAttr_separator(self.grp_anm, self.GROUP_NAME_DISPLAY) # Display Mesh if not self.grp_anm.hasAttr(self.ATTR_NAME_DISPLAY_MESH, checkShape=False): attr_displayMesh = libAttr.addAttr(self.grp_anm, longName=self.ATTR_NAME_DISPLAY_MESH, at='short', k=True, hasMinValue=True, hasMaxValue=True, minValue=0, maxValue=1, defaultValue=1) else: attr_displayMesh = self.grp_anm.attr(self.ATTR_NAME_DISPLAY_MESH) # Display Ctrl if not self.grp_anm.hasAttr(self.ATTR_NAME_DISPLAY_CTRL, checkShape=False): attr_displayCtrl = libAttr.addAttr(self.grp_anm, longName=self.ATTR_NAME_DISPLAY_CTRL, at='short', k=True, hasMinValue=True, hasMaxValue=True, minValue=0, maxValue=1, defaultValue=1) else: attr_displayCtrl = self.grp_anm.attr(self.ATTR_NAME_DISPLAY_CTRL) # Display Proxy if not self.grp_anm.hasAttr(self.ATTR_NAME_DISPLAY_PROXY, checkShape=False): attr_displayProxy = libAttr.addAttr(self.grp_anm, longName=self.ATTR_NAME_DISPLAY_PROXY, at='short', k=True, hasMinValue=True, hasMaxValue=True, minValue=0, maxValue=1, defaultValue=0) else: attr_displayProxy = self.grp_anm.attr(self.ATTR_NAME_DISPLAY_PROXY) pymel.connectAttr(attr_displayMesh, self.grp_geo.visibility, force=True) pymel.connectAttr(attr_displayProxy, self.grp_proxy.visibility, force=True) for child in self.grp_anm.getChildren(): pymel.connectAttr(attr_displayCtrl, child.visibility, force=True)
def build(self, *args, **kwargs): super(AdditiveFK, self).build(*args, **kwargs) nomenclature_anm = self.get_nomenclature_anm() nomenclature_rig = self.get_nomenclature_rig() # Ensure to create the finger ctrl in the good orientation if nomenclature_anm.side == self.rig.nomenclature.SIDE_L: normal_data = {constants.Axis.x: (1, 0, 0), constants.Axis.y: (0, 1, 0), constants.Axis.z: (0, 0, 1)} else: normal_data = {constants.Axis.x: (-1, 0, 0), constants.Axis.y: (0, -1, 0), constants.Axis.z: (0, 0, -1)} self.additive_ctrls = filter(None, self.additive_ctrls) if not self.additive_ctrls: ctrl_add = CtrlFkAdd() self.additive_ctrls.append(ctrl_add) # HACK - Temp since we don't support multiple ctrl for the moment ctrl_add = self.additive_ctrls[0] for i, ctrl in enumerate(self.additive_ctrls): # Resolve ctrl name nomenclature = nomenclature_anm + self.rig.nomenclature(self.jnt.stripNamespace().nodeName()) if not self._FORCE_INPUT_NAME: if len(self.additive_ctrls) == 1 and len(self.chains) == 1: ctrl_name = nomenclature_anm.resolve("addFk") elif len(self.chains) == 1 or self._NAME_CTRL_ENUMERATE: ctrl_name = nomenclature_anm.resolve("addFk", "{0:02d}".format(i)) else: ctrl_name = nomenclature.resolve("addFk") else: ctrl_name = nomenclature.resolve("addFk") ctrl.build(name=ctrl_name, refs=self.chain.start, normal=normal_data[self.rig.DEFAULT_UPP_AXIS]) ctrl.offset.setMatrix(self.chain.start.getMatrix(worldSpace=True)) ctrl.setParent(self.grp_anm) # In case we don't want to see addFk ctrl, like in a hand. # TODO - In this case, maybe the hand would be best to switch it's finger to fk if not self.enable_addfk_ctrl: ctrl.visibility.set(False) libAttr.lock_hide_trs(ctrl) for i, ctrl in enumerate(self.ctrls): # HACK Add a new layer if this is the first ctrl to prevent Gimbal lock problems if i == 0: ctrl.offset = ctrl.append_layer("gimbal") attr_rotate_x = libRigging.create_utility_node('addDoubleLinear', input1=ctrl.offset.rotateX.get(), input2=ctrl_add.rotateX ).output attr_rotate_y = libRigging.create_utility_node('addDoubleLinear', input1=ctrl.offset.rotateY.get(), input2=ctrl_add.rotateY ).output attr_rotate_z = libRigging.create_utility_node('addDoubleLinear', input1=ctrl.offset.rotateZ.get(), input2=ctrl_add.rotateZ ).output pymel.connectAttr(attr_rotate_x, ctrl.offset.rotateX) pymel.connectAttr(attr_rotate_y, ctrl.offset.rotateY) pymel.connectAttr(attr_rotate_z, ctrl.offset.rotateZ) # Constraint the fk ctrls in position to the additive fk ctrls pymel.pointConstraint(ctrl_add, self.ctrls[0].offset)