Ejemplo n.º 1
0
def set_attribute_state(attr, state):
    node = attr.get_node()
    plug_name = attr.get_name()
    if node is None or plug_name is None:
        LOG.warn("Attribute is invalid: %r", attr)
        return
    if state == mmapi.ATTR_STATE_LOCKED:
        if not node_utils.node_is_referenced(node):
            maya.cmds.setAttr(plug_name, lock=True)

    elif state == mmapi.ATTR_STATE_STATIC:
        if not node_utils.node_is_referenced(node):
            maya.cmds.setAttr(plug_name, lock=False)
        # Break the connection going in to the attribute.
        src = maya.cmds.connectionInfo(plug_name,
                                       sourceFromDestination=True) or None
        if src is None:
            return
        dst = plug_name
        connected = maya.cmds.isConnected(src, dst)
        if connected:
            maya.cmds.disconnectAttr(src, dst)

    elif state == mmapi.ATTR_STATE_ANIMATED:
        if not node_utils.node_is_referenced(node):
            maya.cmds.setAttr(plug_name, lock=False)
        locked = maya.cmds.getAttr(plug_name, lock=True)
        if locked is False:
            maya.cmds.setKeyframe(plug_name)

    else:
        LOG.warn("Cannot set invalid attribute state: %r", attr)
    return
Ejemplo n.º 2
0
def _get_plug_names_as_set(attr_list):
    plug_names = set()
    for attr_obj in attr_list:
        node_path = attr_obj.get_node(full_path=True)
        if node_utils.node_is_referenced(node_path):
            continue
        plug_name = attr_obj.get_name(full_path=True)
        plug_names.add(plug_name)
    return plug_names
Ejemplo n.º 3
0
def _find_constraints_from_node(node):
    constraints = cmds.listConnections(node + ".parentMatrix[0]",
                                       destination=True,
                                       source=False,
                                       type="constraint") or []
    constraints = [
        n for n in constraints if node_utils.node_is_referenced(n) is False
    ]
    constraints = list(set(constraints))
    return constraints
Ejemplo n.º 4
0
def _get_constraints_from_ctrls(input_node):
    """
    Get Constraints 'input_node' is connected to.
    """
    constraints = maya.cmds.listConnections(
        input_node, type='constraint', source=False, destination=True) or []
    constraints = [
        n for n in constraints if node_utils.node_is_referenced(n) is False
    ]
    constraints = set(constraints)
    if len(constraints) == 0:
        LOG.warn('node is not controlling anything: %r', input_node)
        return set()
    return constraints
Ejemplo n.º 5
0
def remove(nodes, current_frame=None, eval_mode=None):
    """
    Remove a controller and push the animation back to the controlled
    object.

    Order the nodes to remove by hierarchy depth. This means that
    children will be removed first, then parents, this ensures we
    don't delete a controller accidentally when a parent controller is
    deleted first.

    :param nodes: The nodes to delete.
    :type nodes: [str, ..]

    :param current_frame: What frame number is considered to be
                          'current' when evaluating transforms without
                          any keyframes.
    :type current_frame: float or int

    :param eval_mode: What type of transform evaluation method to use?
    :type eval_mode: mmSolver.utils.constant.EVAL_MODE_*

    :returns: List of once controlled transform nodes, that are no
              longer controlled.
    :rtype: [str, ..]
    """
    if current_frame is None:
        current_frame = maya.cmds.currentTime(query=True)
    assert current_frame is not None
    sparse = False

    nodes = _sort_by_hierarchy(nodes, children_first=True)
    tfm_nodes = [tfm_utils.TransformNode(node=n) for n in nodes]

    # Find controlled nodes from controller nodes
    ctrl_to_ctrlled_map = {}
    for tfm_node in tfm_nodes:
        node = tfm_node.get_node()
        constraints = _get_constraints_from_ctrls(node)
        dests = _get_destination_nodes_from_ctrls(constraints)
        if len(dests) == 0:
            continue
        dests = _sort_by_hierarchy(dests, children_first=True)
        ctrl_to_ctrlled_map[node] = (constraints, dests)

    # Query keyframe times on controller nodes.
    start_frame, end_frame = time_utils.get_maya_timeline_range_outer()
    keytime_obj = keytime_utils.KeyframeTimes()
    for node in nodes:
        keytime_obj.add_node_attrs(node, const.TFM_ATTRS, start_frame,
                                   end_frame)
    fallback_frame_range = keytime_obj.sum_frame_range_for_nodes(nodes)
    fallback_times = list(
        range(fallback_frame_range[0], fallback_frame_range[1] + 1))

    # Query keyframe times on each node attribute
    key_times_map = time_utils.get_keyframe_times_for_node_attrs(
        nodes, const.TFM_ATTRS)

    # Query transform matrix on controlled nodes.
    cache = tfm_utils.TransformMatrixCache()
    for src_node, (constraints, dst_nodes) in ctrl_to_ctrlled_map.items():
        times = key_times_map.get(src_node, [current_frame])
        assert len(times) > 0
        ctrl = tfm_utils.TransformNode(node=src_node)
        cache.add_node(ctrl, times)
        for dst_node in dst_nodes:
            dst = tfm_utils.TransformNode(node=dst_node)
            cache.add_node(dst, times)
    cache.process(eval_mode=eval_mode)

    # Get Controlled nodes
    ctrlled_nodes = set()
    for src_node, (_, dst_nodes) in ctrl_to_ctrlled_map.items():
        for dst_node in dst_nodes:
            ctrlled_nodes.add(dst_node)

    # Delete constraints on controlled nodes.
    const_nodes = set()
    for src_node, (constraints, _) in ctrl_to_ctrlled_map.items():
        assert src_node not in constraints
        const_nodes |= constraints
    if len(const_nodes) > 0:
        maya.cmds.delete(list(const_nodes))

    # Set keyframes (per-frame) on controlled nodes
    for ctrl_node, (_, ctrlled_nodes) in ctrl_to_ctrlled_map.items():
        times = key_times_map.get(ctrl_node, [current_frame])
        ctrl = tfm_utils.TransformNode(node=ctrl_node)
        for ctrlled_node in ctrlled_nodes:
            ctrlled = tfm_utils.TransformNode(node=ctrlled_node)
            tfm_utils.set_transform_values(cache,
                                           times,
                                           ctrl,
                                           ctrlled,
                                           delete_static_anim_curves=False)

    parent_nodes = []
    anim_curves = []
    for src_node, (_, dst_nodes) in ctrl_to_ctrlled_map.items():
        src_times = key_times_map.get(src_node, [current_frame])
        assert len(src_times) > 0
        ctrl = tfm_utils.TransformNode(node=src_node)
        for dst_node in dst_nodes:
            dst = tfm_utils.TransformNode(node=dst_node)
            tfm_utils.set_transform_values(cache,
                                           src_times,
                                           ctrl,
                                           dst,
                                           delete_static_anim_curves=False)

            # Re-parent controller child nodes under controlled node.
            ctrl_children = maya.cmds.listRelatives(
                src_node,
                children=True,
                shapes=False,
                fullPath=True,
                type='transform',
            ) or []
            for child_node in ctrl_children:
                if child_node in nodes:
                    continue
                child = tfm_utils.TransformNode(node=child_node)
                parent_nodes.append((child, dst))

            src_had_keys = key_times_map.get(src_node) is not None
            if src_had_keys is True:
                continue
            # Maintain that destination node will not have keyframes now, the
            # same as the source node.
            dst_node = dst.get_node()
            keyable_attrs = _get_keyable_attrs(dst_node, const.TFM_ATTRS)
            anim_curves += anim_utils.get_anim_curves_from_nodes(
                list(keyable_attrs), )

    # Reparent children back to under the controlled.
    for src, dst in parent_nodes:
        src_node = src.get_node()
        dst_node = dst.get_node()
        maya.cmds.parent(src_node, dst_node, absolute=True)

    # Remove animation curves.
    anim_curves = [
        n for n in anim_curves if node_utils.node_is_referenced(n) is False
    ]
    if len(anim_curves) > 0:
        maya.cmds.delete(anim_curves)

    # Delete controller nodes
    ctrl_nodes = [n.get_node() for n in tfm_nodes]
    if len(ctrl_nodes) > 0:
        maya.cmds.delete(ctrl_nodes)
    return list(ctrlled_nodes)
Ejemplo n.º 6
0
def create(nodes, current_frame=None, eval_mode=None):
    """
    Create a Controller for the given nodes.

    :param nodes: The nodes to create Controller for.
    :type nodes: [str, ..]

    :param current_frame: What frame number is considered to be
                          'current' when evaluating transforms without
                          any keyframes.
    :type current_frame: float or int

    :param eval_mode: What type of transform evaluation method to use?
    :type eval_mode: mmSolver.utils.constant.EVAL_MODE_*

    :returns: List of controller transform nodes.
    :rtype: [str, ..]
    """
    if current_frame is None:
        current_frame = maya.cmds.currentTime(query=True)
    assert current_frame is not None
    sparse = False

    tfm_nodes = [tfm_utils.TransformNode(node=n) for n in nodes]

    # Force into long-names.
    nodes = [n.get_node() for n in tfm_nodes]

    # Ensure node attributes are editable.
    keyable_attrs = set()
    for node in nodes:
        keyable_attrs |= _get_keyable_attrs(node, const.TFM_ATTRS)

    # Query keyframe times on each node attribute
    start_frame, end_frame = time_utils.get_maya_timeline_range_outer()
    keytime_obj = keytime_utils.KeyframeTimes()
    for node in nodes:
        keytime_obj.add_node_attrs(node, const.TFM_ATTRS, start_frame,
                                   end_frame)
    fallback_frame_range = keytime_obj.sum_frame_range_for_nodes(nodes)
    fallback_times = list(
        range(fallback_frame_range[0], fallback_frame_range[1] + 1))
    key_times_map = time_utils.get_keyframe_times_for_node_attrs(
        nodes, const.TFM_ATTRS)

    # Query the transform matrix for the nodes
    cache = tfm_utils.TransformMatrixCache()
    for tfm_node in tfm_nodes:
        node = tfm_node.get_node()
        times = key_times_map.get(node, [current_frame])
        cache.add_node(tfm_node, times)
    cache.process(eval_mode=eval_mode)

    depth_to_tfm_node_map = _sort_hierarchy_depth_to_tfm_nodes(tfm_nodes)
    nodes_parent = _get_node_parent_map(nodes)

    # Create new (locator) node for each input node
    ctrl_list = []
    node_to_ctrl_map = {}
    node_to_ctrl_tfm_map = {}
    depths = sorted(depth_to_tfm_node_map.keys())
    for depth in depths:
        depth_tfm_nodes = depth_to_tfm_node_map.get(depth)
        assert depth_tfm_nodes is not None
        sorted_tfm_nodes = sorted(depth_tfm_nodes, key=lambda x: x.get_node())
        for tfm_node in sorted_tfm_nodes:
            node = tfm_node.get_node()
            node_parent = nodes_parent.get(node)
            if node_parent is not None:
                node_parent = node_to_ctrl_map.get(node_parent)
            name = node.rpartition('|')[-1]
            assert '|' not in name
            name = name.replace(':', '_')
            name = name + '_CTRL'
            name = mmapi.find_valid_maya_node_name(name)
            tfm = maya.cmds.createNode('transform',
                                       name=name,
                                       parent=node_parent)
            tfm = node_utils.get_long_name(tfm)
            shape_name = name + 'Shape'
            maya.cmds.createNode('locator', name=shape_name, parent=tfm)
            rot_order = maya.cmds.xform(node, query=True, rotateOrder=True)
            maya.cmds.xform(tfm, rotateOrder=rot_order, preserve=True)
            ctrl_tfm = tfm_utils.TransformNode(node=tfm)
            ctrl_list.append(tfm)
            node_to_ctrl_map[node] = tfm
            node_to_ctrl_tfm_map[node] = ctrl_tfm

    # Set transform matrix on new node
    anim_curves = []
    for src in tfm_nodes:
        src_node = src.get_node()
        src_times = key_times_map.get(src_node, [current_frame])
        dst = node_to_ctrl_tfm_map.get(src_node)
        assert len(src_times) > 0
        tfm_utils.set_transform_values(cache,
                                       src_times,
                                       src,
                                       dst,
                                       delete_static_anim_curves=False,
                                       eval_mode=eval_mode)
        src_had_keys = key_times_map.get(src_node) is not None
        if src_had_keys is True:
            continue
        # Maintain that destination node will not have keyframes now, the
        # same as the source node.
        dst_node = dst.get_node()
        keyable_attrs = _get_keyable_attrs(dst_node, const.TFM_ATTRS)
        anim_curves += anim_utils.get_anim_curves_from_nodes(
            list(keyable_attrs), )
    anim_curves = [
        n for n in anim_curves if node_utils.node_is_referenced(n) is False
    ]
    if len(anim_curves) > 0:
        maya.cmds.delete(anim_curves)

    # Delete all keyframes on controlled nodes
    keyable_attrs = set()
    for tfm_node in tfm_nodes:
        node = tfm_node.get_node()
        keyable_attrs |= _get_keyable_attrs(node, const.TFM_ATTRS)
    anim_curves = anim_utils.get_anim_curves_from_nodes(list(keyable_attrs), )
    anim_curves = [
        n for n in anim_curves if node_utils.node_is_referenced(n) is False
    ]
    if len(anim_curves) > 0:
        maya.cmds.delete(anim_curves)

    # Create constraint(s) to previous nodes.
    for tfm_node in tfm_nodes:
        src_node = tfm_node.get_node()
        ctrl = node_to_ctrl_tfm_map.get(src_node)
        dst_node = ctrl.get_node()
        _create_constraint(src_node, dst_node)
    return ctrl_list
Ejemplo n.º 7
0
def create(nodes, sparse=True):
    tfm_nodes = [tfm_utils.TransformNode(node=n) for n in nodes]

    # Force into long-names.
    nodes = [n.get_node() for n in tfm_nodes]

    # Ensure node attributes are editable.
    keyable_attrs = set()
    for node in nodes:
        keyable_attrs |= _get_keyable_attrs(node, const.TFM_ATTRS)

    # Query keyframe times on each node attribute
    start_frame, end_frame = time_utils.get_maya_timeline_range_outer()
    keytime_obj = keytime_utils.KeyframeTimes()
    for node in nodes:
        keytime_obj.add_node_attrs(node, const.TFM_ATTRS, start_frame, end_frame)
    fallback_frame_range = keytime_obj.sum_frame_range_for_nodes(nodes)
    fallback_times = list(range(fallback_frame_range[0],
                                fallback_frame_range[1]+1))

    # Query the transform matrix for the nodes
    cache = tfm_utils.TransformMatrixCache()
    for tfm_node in tfm_nodes:
        node = tfm_node.get_node()
        times = keytime_obj.get_times(node, sparse) or fallback_times
        cache.add_node(tfm_node, times)
    cache.process()

    # Create new (locator) node for each input node
    ctrl_list = []
    for tfm_node in tfm_nodes:
        node = tfm_node.get_node()
        name = node.rpartition('|')[-1]
        assert '|' not in name
        name = name.replace(':', '_')
        name = name + '_CTRL'
        name = mmapi.find_valid_maya_node_name(name)
        # TODO: Allow maintaining relative hierarchy of nodes.
        tfm = maya.cmds.createNode('transform', name=name)
        maya.cmds.createNode('locator', parent=tfm)
        rot_order = maya.cmds.xform(node, query=True, rotateOrder=True)
        maya.cmds.xform(tfm, rotateOrder=rot_order, preserve=True)
        ctrl_list.append(tfm)
    ctrl_tfm_nodes = [tfm_utils.TransformNode(node=tfm)
                      for tfm in ctrl_list]

    # Set transform matrix on new node
    for src, dst in zip(tfm_nodes, ctrl_tfm_nodes):
        src_node = src.get_node()
        times = keytime_obj.get_times(src_node, sparse) or fallback_times
        tfm_utils.set_transform_values(
            cache, times, src, dst,
            delete_static_anim_curves=False
        )
        if sparse is True:
            # Remove keyframes
            src_times = keytime_obj.get_times(src_node, sparse) or []
            dst_node = dst.get_node()
            if len(src_times) == 0:
                time_range = keytime_obj.get_frame_range_for_node(src_node)
                assert time_range[0] is not None
                assert time_range[1] is not None
                maya.cmds.cutKey(
                    dst_node,
                    attribute=const.TFM_ATTRS,
                    time=time_range,
                    clear=True
                )

    # Delete all keyframes on controlled nodes
    anim_curves = anim_utils.get_anim_curves_from_nodes(
        list(keyable_attrs),
    )
    anim_curves = [n for n in anim_curves
                   if node_utils.node_is_referenced(n) is False]
    if len(anim_curves) > 0:
        maya.cmds.delete(anim_curves)

    # Create constraint(s) to previous nodes.
    for tfm_node, ctrl in zip(tfm_nodes, ctrl_tfm_nodes):
        src_node = tfm_node.get_node()
        dst_node = ctrl.get_node()
        _create_constraint(src_node, dst_node)
    return ctrl_list