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
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
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