示例#1
0
def _visible(node, cache):
    visible = _node_is_visible(node, cache)
    cache[node] = visible
    if visible is False:
        return False
    # Note: We assume the node paths from 'get_node_parents' will
    # always be full paths.
    parents = node_utils.get_node_parents(node)
    for parent in parents:
        visible = _node_is_visible(parent, cache)
        cache[parent] = visible
        if visible is False:
            return False
    return True
示例#2
0
def remove_controller(controller_node, frame_start, frame_end, attrs=None):
    """
    Bake the affects of the controller node, and delete the controller.

    :param controller_node: The controller node.
    :type controller_node: str

    :param frame_start: First frame to bake.
    :type frame_start: int

    :param frame_end: Last frame to bake.
    :type frame_end: int

    :param attrs: List of attributes to bake. If None, all transform,
        rotate and scale attributes are baked.
    :type attrs: [str, ..] or None

    :returns: The list of transform nodes that were controlled by the
        given controller.
    :rtype: [str, ..]
    """
    assert isinstance(controller_node, pycompat.TEXT_TYPE)
    assert cmds.objExists(controller_node)
    assert isinstance(frame_start, int)
    assert isinstance(frame_end, int)
    if attrs is None:
        attrs = TRANSFORM_ATTRS
    assert isinstance(attrs, list)
    if len(attrs) == 0:
        attrs = TRANSFORM_ATTRS

    # Find controller nodes.
    controller_nodes = []
    is_controller_rig = _is_rig_node(controller_node)
    if is_controller_rig is False:
        controller_nodes = [controller_node]
    else:
        children = cmds.ls(
            controller_node, dag=True, long=True, type='transform') or []
        controller_nodes = [n for n in children if _is_rig_node(n)]

        # Sort nodes by depth, deeper nodes first, so we do do not
        # remove parents before children.
        controller_nodes = node_utils.sort_nodes_by_depth(controller_nodes,
                                                          reverse=True)

    # Find constraints.
    constraints = []
    for node in controller_nodes:
        constraints += _find_constraints_from_node(node)
    if len(constraints) == 0:
        LOG.warn('Selected controller is not driving any object(s).')
        return []

    # Get Driven nodes.
    driven_nodes = []
    for constraint in constraints:
        attr = constraint + '.constraintParentInverseMatrix'
        driven_nodes += cmds.listConnections(
            attr, destination=False, source=True) or []
    if len(driven_nodes) == 0:
        LOG.warn('Selected controller is not driving any object(s).')
        return []

    # Find nodes to be deleted.
    nodes_to_delete = []
    for node in controller_nodes:
        controller_id = _get_rig_node_identifier(node)
        parent_nodes = node_utils.get_node_parents(node)
        parent_node_ids = [_get_rig_node_identifier(n) for n in parent_nodes]
        nodes_to_delete += [
            n for n, id_ in zip(parent_nodes, parent_node_ids)
            if id_ == controller_id
        ]
    has_extra_parents = len(nodes_to_delete) == 0

    # Bake driven attributes.
    if is_controller_rig is True and has_extra_parents is False:
        for driven_node in driven_nodes:
            # If the original top-level controller node was "smart
            # baked", then set keys on all the same frames, therefore
            # re-creating the original keyframe times.
            _set_keyframes_at_source_node_key_times(controller_node,
                                                    driven_node, frame_start,
                                                    frame_end)
    else:
        fastbake_lib.bake_attributes(driven_nodes,
                                     attrs,
                                     frame_start,
                                     frame_end,
                                     smart_bake=True)

    # Delete nodes and clean up.
    if len(constraints) > 0:
        cmds.delete(constraints)
    _remove_constraint_blend_attr_from_nodes(driven_nodes)
    nodes_to_delete = [n for n in nodes_to_delete if cmds.objExists(n)]
    if len(nodes_to_delete) > 0:
        cmds.delete(nodes_to_delete)

    return driven_nodes
示例#3
0
def reparent(children, parent, sparse=True, delete_static_anim_curves=False):
    """
    Reparent the children under the given parent.

    :param children: List of child nodes to be modified.
    :type children: [TransformNode, ..]

    :param parent: The new parent node for children, or None means
                   un-parent.
    :type parent: TransformNode or None

    :param sparse: Keyframe animation on the children each frame
                   (dense) or sparse (only at keyframes).
    :type sparse: bool

    :param delete_static_anim_curves: Delete any animCurves that all
                                      have the same values.
    :type delete_static_anim_curves: bool

    :returns: List of 'children' TransformNodes modified, will not
              contain child nodes if the child is already parented under
              'parent'.
    :rtype: [TransformNode, ..]
    """
    assert len(children) > 0
    assert isinstance(children[0], tfm_utils.TransformNode)
    assert parent is None or isinstance(parent, tfm_utils.TransformNode)
    assert isinstance(sparse, bool)
    assert isinstance(delete_static_anim_curves, bool)
    children_nodes = [tn.get_node() for tn in children]

    parent_parent_nodes = []
    if parent is not None:
        parent_node = parent.get_node()
        parent_parent_nodes = [parent_node]
        parent_parent_nodes += node_utils.get_node_parents(parent_node) or []

    # Query keyframe times on each node attribute
    start_frame, end_frame = time_utils.get_maya_timeline_range_outer()
    keytime_obj = keytime_utils.KeyframeTimes()
    for child_node in children_nodes:
        child_parent_nodes = list(parent_parent_nodes)
        child_parent_nodes += node_utils.get_node_parents(child_node) or []
        keytime_obj.add_node_attrs(child_node,
                                   TFM_ATTRS,
                                   start_frame,
                                   end_frame,
                                   parents=child_parent_nodes)
    fallback_frame_range = keytime_obj.sum_frame_range_for_nodes(
        children_nodes)
    fallback_times = list(
        range(fallback_frame_range[0], fallback_frame_range[1] + 1))

    # Query current transforms
    tfm_cache = tfm_utils.TransformMatrixCache()
    for tfm_node, node in zip(children, children_nodes):
        times = keytime_obj.get_times(node, sparse) or fallback_times
        tfm_cache.add_node_attr(tfm_node, 'worldMatrix[0]', times)
    tfm_cache.process()

    # Apply parenting logic for the children nodes.
    changed_list = [False] * len(children)
    if parent is not None:
        parent_node = parent.get_node()
        assert maya.cmds.objExists(parent_node)
        for i, tfm_node in enumerate(children):
            node = tfm_node.get_node()
            current_parent = tfm_node.get_parent()
            if current_parent == parent:
                continue
            maya.cmds.parent(node, parent_node, absolute=True)
            changed_list[i] = True
    else:
        for i, (tfm_node, node) in enumerate(zip(children, children_nodes)):
            current_parent = tfm_node.get_parent()
            if current_parent is None:
                continue
            maya.cmds.parent(node, world=True, absolute=True)
            changed_list[i] = True
    assert len(changed_list) == len(children)

    # Set transforms again.
    changed_tfm_nodes = [
        tn for tn, c in zip(children, changed_list) if c is True
    ]
    for tfm_node in changed_tfm_nodes:
        node = tfm_node.get_node()
        times = keytime_obj.get_times(node, sparse) or []
        if len(times) > 0:
            tfm_utils.set_transform_values(
                tfm_cache,
                times,
                tfm_node,
                tfm_node,
                delete_static_anim_curves=delete_static_anim_curves,
            )
    return changed_tfm_nodes