def attach_closest_point_node(driver_name, mesh_name, follicle_name): """ attaches the closest point node. :param driver_name: <str> the driving object. :param mesh_name: <str> the mesh object. :param follicle_name: <str> the follicle transform object. :return: <str> closestPoint nodes. """ shape_m_obj_array = object_utils.get_shape_obj(mesh_name) shape_name_array = object_utils.get_shape_name(mesh_name) nodes = () for shape_m_obj, shape_name in zip(shape_m_obj_array, shape_name_array): foll_shape_name = object_utils.get_shape_name(follicle_name) if object_utils.check_shape_type_name(shape_m_obj, 'nurbsSurface'): node_name = closest_point_surface_node_name(driver_name) nodes += cmds.createNode('closestPointOnSurface', name=node_name), attr_connect(attr_name(shape_name, 'worldSpace[0]'), attr_name(node_name, 'inputSurface')) elif object_utils.check_shape_type_name(shape_m_obj, 'mesh'): node_name = closest_point_mesh_node_name(driver_name) nodes += cmds.createNode('closestPointOnMesh', name=follicle_name(driver_name)), attr_connect(attr_name(shape_name, 'worldMesh[0]'), attr_name(node_name, 'inMesh')) elif object_utils.check_shape_type_name(shape_m_obj, 'nurbsCurve'): node_name = closest_point_curve_node_name(driver_name) nodes += cmds.createNode('closestPointOnCurve', name=follicle_name(driver_name)), attr_connect(attr_name(shape_name, 'worldSpace[0]'), attr_name(node_name, 'inCurve')) attr_connect(attr_name(driver_name, 'translate'), attr_name(node_name, 'inPosition')) attr_connect(attr_name(node_name, 'parameterU'), attr_name(foll_shape_name, 'parameterU')) attr_connect(attr_name(node_name, 'parameterV'), attr_name(foll_shape_name, 'parameterV')) return nodes
def attach_follicle(mesh_name, follicle_object="", follicle_name=""): """ attaches a follicle to the specified mesh object. :param follicle_object: <str> the follicle object to use. :param follicle_name: <str> the follicle name to use when creating new follicle nodes. :param mesh_name: <str> the shape object name. Could be a nurbsSurface to a mesh object. :return: <bool> True for success. <bool> False for failure. """ # get the first mesh shape, we don't want a Shape Orig shape_m_obj_array = object_utils.get_shape_obj(mesh_name)[0], shape_name_array = object_utils.get_shape_name(mesh_name)[0], follicles = () for shape_m_obj, shape_name in zip(shape_m_obj_array, shape_name_array): if follicle_name: follicle_shape_name = create_follicle_node(name=follicle_name) follicle_name = object_utils.get_parent_name(follicle_shape_name)[0] elif not follicle_name and follicle_object: if object_utils.has_fn(follicle_object, 'transform'): follicle_shape_name = object_utils.get_shape_name(follicle_object)[0] follicle_name = follicle_object elif object_utils.has_fn(follicle_object, 'follicle'): follicle_name = object_utils.get_parent_name(follicle_object)[0] follicle_shape_name = follicle_object elif object_utils.has_fn(follicle_object, 'component'): follicle_shape_name = object_utils.get_shape_name(follicle_object)[0] follicle_name = object_utils.get_parent_name(follicle_object)[0] else: m_obj = object_utils.get_m_obj(follicle_object) print(m_obj.apiTypeStr()) raise NotImplementedError("[AttachFollicle] :: Could not get follicle node name.") follicles += follicle_name, if object_utils.check_shape_type_name(shape_m_obj, 'nurbsSurface'): attr_connect(attr_name(shape_name, 'matrix'), attr_name(follicle_shape_name, 'inputWorldMatrix')) attr_connect(attr_name(shape_name, 'worldSpace[0]'), attr_name(follicle_shape_name, 'inputSurface')) elif object_utils.check_shape_type_name(shape_m_obj, 'mesh'): attr_connect(attr_name(shape_name, 'worldMatrix[0]'), attr_name(follicle_shape_name, 'inputWorldMatrix')) attr_connect(attr_name(shape_name, 'outMesh'), attr_name(follicle_shape_name, 'inputMesh')) elif object_utils.check_shape_type_name(shape_m_obj, 'nurbsCurve'): attr_connect(attr_name(shape_name, 'worldMatrix[0]'), attr_name(follicle_shape_name, 'inputWorldMatrix')) attr_connect(attr_name(shape_name, 'worldSpace[0]'), attr_name(follicle_shape_name, 'inputCurve')) attr_connect(attr_name(follicle_shape_name, 'outRotate'), attr_name(follicle_name, 'rotate')) attr_connect(attr_name(follicle_shape_name, 'outTranslate'), attr_name(follicle_name, 'translate')) return follicles
def get_nurb_shapes(curve_name=""): """ get the nurbsCurve shape from name. :param curve_name: <str> the transform node of the nurbsCurve. :return: <tuple> nurbsCurve shape names. """ return object_utils.get_shape_name(curve_name, shape_type=__shape_name__)
def create_follicles_from_objects(driver_objects_array=(), mesh_name="", attach_offsets=True): """ creates the follicle objects from specified objects. :param driver_objects_array: <tuple>, <list> array of objects to get closest point from. :param mesh_name: <str> the mesh name to connect the follicle nodes to. :param attach_offsets: <bool> if set to true, attaches the offset attributes to the follicle nodes. :return: <tuple> created follicles. """ follicles_array = () for obj_name in driver_objects_array: # create a follicle using the object name follicles = attach_follicle(mesh_name, follicle_name=obj_name) for foll_name in follicles: # there is only ever one follicle shape object. follicle_shape_name = object_utils.get_shape_name(foll_name)[0] u, v = get_closest_uv(obj_name, mesh_name) cmds.setAttr(attr_name(follicle_shape_name, 'parameterU'), u) cmds.setAttr(attr_name(follicle_shape_name, 'parameterV'), v) # print(mesh_name, u, v) follicles_array += foll_name, if attach_offsets: attach_offset_nodes_to_follicles(follicles_array, create_container=False) return follicles_array
def attach_transform_to_curve(object_name="", curve_name=""): """ attach a transform object to the curve object. :return: """ poc_node_name = "{}_poc".format(object_name) cross_vector_name = "{}_cross".format(object_name) cross_vector_name2 = "{}_cross2".format(object_name) four_by_four_name = "{}_4by4".format(object_name) decompose_name = "{}_decomp".format(object_name) poc_node = create_node('pointOnCurveInfo', node_name=poc_node_name) cross_vector_node = create_node('vectorProduct', node_name=cross_vector_name) cross_vector_node2 = create_node('vectorProduct', node_name=cross_vector_name2) four_by_four_node = create_node('fourByFourMatrix', node_name=four_by_four_name) decompose_node = create_node('decomposeMatrix', node_name=decompose_name) # set the vector product into cross product operation attr_set(attr_name(cross_vector_name, 'operation'), 2) # connect the curve shape into the point on curve node connect_attr( object_utils.get_shape_name(curve_name)[0], attr_name(poc_node, 'inputCurve')) # connect the position vector to the four by four matrix node for out_attr, in_attr in zip(('positionX', 'positionY', 'positionZ'), ('in30', 'in31', 'in32')): connect_attr(attr_name(poc_node, out_attr), attr_name(four_by_four_node, in_attr)) # connect the normalized tangent vector to the cross product2 node for out_attr, in_attr in zip( ('normalizedTangentX', 'normalizedTangentY', 'normalizedTangentZ'), ('input2X', 'input2Y', 'input2Z')): connect_attr(attr_name(poc_node, out_attr), attr_name(cross_vector_node2, in_attr)) # connect the output # connect the normalized tangent vector to the four by four matrix node for out_attr, in_attr in zip( ('normalizedTangentX', 'normalizedTangentY', 'normalizedTangentZ'), ('in00', 'in01', 'in02')): connect_attr(attr_name(poc_node, out_attr), attr_name(four_by_four_node, in_attr)) # connect the normalized normal and the normalized tangent into the vector product (crossProduct) for out_attr, in_attr in zip( ('normalizedNormalX', 'normalizedNormalY', 'normalizedNormalZ'), ('input1X', 'input1Y', 'input1Z')): connect_attr(attr_name(poc_node, out_attr), attr_name(cross_vector_node, in_attr)) for out_attr, in_attr in zip( ('normalizedTangentX', 'normalizedTangentY', 'normalizedTangentZ'), ('input2X', 'input2Y', 'input2Z')): connect_attr(attr_name(poc_node, out_attr), attr_name(cross_vector_node, in_attr)) # connect the cross product output into the four by four matrix node for out_attr, in_attr in zip(('outputX', 'outputY', 'outputZ'), ('in20', 'in21', 'in22')): connect_attr(attr_name(cross_vector_name, out_attr), attr_name(four_by_four_node, in_attr)) # connect the four by four node into the decompose matrix node. connect_attr(attr_name(four_by_four_node, 'output'), attr_name(decompose_node, 'inputMatrix')) # connect the decompose matrix into the transform node. connect_attr(attr_name(decompose_node, 'outputRotate'), attr_name(object_name, 'rotate')) connect_attr(attr_name(decompose_node, 'outputTranslate'), attr_name(object_name, 'translate')) return True
def attach_offset_nodes_to_follicles(follicles_array=(), add_limit_attrs=False, create_container=False): """ attaching the plusMinusAverage offset nodes to follicle nodes. :param follicles_array: <tuple> array of follicle nodes. :param add_limit_attrs: <bool> if set to True, creates limit nodes. :param create_container: <bool> if True, creates containers on the created nodes. :return: <tuple> array of plusMinusAverage nodes. """ nodes_array = () for idx, follicle_node in enumerate(follicles_array): if object_utils.has_fn(follicle_node, 'transform'): follicle_shape_name = object_utils.get_shape_name(follicle_node)[0] else: follicle_shape_name = follicle_node follicle_node = object_utils.get_parent_name(follicle_node)[0] add_node_name_u = '{}_U_{}_add'.format(follicle_node, idx) add_node_u = create_node('addDoubleLinear', add_node_name_u) add_input_1_u = attr_name(add_node_u, 'input1') add_input_2_u = attr_name(add_node_u, 'input2') add_node_name_v = '{}_V_{}_add'.format(follicle_node, idx) add_node_v = create_node('addDoubleLinear', add_node_name_v) add_input_1_v = attr_name(add_node_v, 'input1') add_input_2_v = attr_name(add_node_v, 'input2') # offset node output attributes add_output_u = attr_name(add_node_u, 'output') add_output_v = attr_name(add_node_v, 'output') # add attributes to the follicle node offset_u_attr = attr_add_float(follicle_node, 'offset_u') offset_v_attr = attr_add_float(follicle_node, 'offset_v') offset_default_u_attr = attr_add_float(follicle_node, 'default_u') offset_default_v_attr = attr_add_float(follicle_node, 'default_v') # get default values value_u = attr_get_value(follicle_shape_name, 'parameterU') value_v = attr_get_value(follicle_shape_name, 'parameterV') attr_set(offset_default_u_attr, value_u) attr_set(offset_default_v_attr, value_v) # now connect the attributes attr_connect(offset_default_u_attr, add_input_1_u) attr_connect(offset_default_v_attr, add_input_1_v) # connect the attributes param_u_attr = attr_name(follicle_shape_name, 'parameterU') param_v_attr = attr_name(follicle_shape_name, 'parameterV') attr_connect(offset_u_attr, add_input_2_u) attr_connect(offset_v_attr, add_input_2_v) # finally connect the output of the add nodes to the follicle shape node if add_limit_attrs: nodes_array += attach_limit_attrs( add_output_u, param_u_attr, value_u, add_attrs_on_obj=attr_name(follicle_node, 'parameterU')) nodes_array += attach_limit_attrs( add_output_v, param_v_attr, value_v, add_attrs_on_obj=attr_name(follicle_node, 'parameterV')) else: attr_connect(add_output_u, param_u_attr) attr_connect(add_output_v, param_v_attr) nodes_array += follicle_node, add_node_u, add_node_v, if create_container: object_utils.create_container(follicle_node + '_container', nodes_array) return nodes_array