def build_fk_chain(self, chain_start=None, chain_end=None, shape=None, duplicate=True, parent=None, name_tokens=None, meta_data=None, **kwargs): """ :param parent: list or object: list of up to length 2, [fk chain parent, control chain parent] :return: (NonLinearHierarchyNodeSet(Control), LinearHierarchyNodeSet(Joint)) """ parent = to_size_list(parent, 2) name_tokens = MetaData(self.name_tokens, name_tokens) if hasattr(self, cfg.NAME_TOKENS) else name_tokens meta_data = MetaData(self.meta_data, meta_data) if hasattr(self, cfg.META_DATA) else meta_data kwargs['skip_register'] = True kwargs['skip_report'] = True fk_chain = nt.LinearHierarchyNodeSet(chain_start, chain_end, duplicate=duplicate, parent=parent.pop()) fk_controls = nt.NonLinearHierarchyNodeSet() control_parent = parent.pop() for node, shape in zip(fk_chain, to_size_list(shape or self.DEFAULT_FK_SHAPE, len(fk_chain))): control = self.build_node(nt.Control, reference_object=node, shape=shape, parent=control_parent, name_tokens=name_tokens, meta_data=meta_data, **kwargs) control.parent(control_parent) control_parent = control.node.connection_group rt.dcc.connections.parent(control_parent, node, maintainOffset=True) fk_controls.append(control) return fk_chain, fk_controls
def build_ik_chain(self, layout_joints, ik_end_index=-1, solver=cfg.IK_RP_SOLVER, parent=None, duplicate=True, **kwargs): """ :param parent: list or object: list of up to length 4: [ik chain parent, handle parent, pv control parent, [3 pole vector control parents]] :return: (NonLinearHierarchyNodeSet(Control), LinearHierarchyNodeSet(Joint)) """ parent = list(reversed(to_size_list(parent, 3))) kwargs[cfg.SKIP_REGISTER] = True kwargs[cfg.SKIP_REPORT] = True ik_chain = nt.LinearHierarchyNodeSet(layout_joints, duplicate=duplicate, parent=parent.pop(), **kwargs) handle, effector = self.build_ik(ik_chain, chain_end=ik_chain[ik_end_index], parent=parent.pop(), name_tokens=MetaData( {cfg.NAME: cfg.IK}, kwargs.pop(cfg.NAME_TOKENS, {})), **kwargs) controls = nt.NonLinearHierarchyNodeSet() # build ik control controls.append( nt.Control.build(**MetaData( kwargs, { cfg.PARENT: parent.pop(), cfg.REFERENCE_OBJECT: ik_chain[-1], cfg.SHAPE: cfg.DEFAULT_IK_SHAPE, cfg.NAME_TOKENS: { cfg.PURPOSE: cfg.IK } }).to_dict())) # build pole vector control if using RP solver. if solver == cfg.IK_RP_SOLVER: pv_control = self.build_pole_vector_control( ik_chain, handle, **MetaData( kwargs, { cfg.SHAPE: cfg.DEFAULT_PV_SHAPE, cfg.NAME_TOKENS: { cfg.PURPOSE: cfg.POLE_VECTOR } })) controls.append(pv_control) rt.dcc.connections.translate(controls[0].connection_group, handle) return ik_chain, controls, handle, effector
def build_fk_chain(self, chain_start=None, chain_end=None, shape=None, duplicate=True, parent=None, name_tokens=None, meta_data=None, **kwargs): """ :param parent: list or object: list of up to length 2, [fk chain parent, control chain parent] :return: (NonLinearHierarchyNodeSet(Control), LinearHierarchyNodeSet(Joint)) """ parent = to_size_list(parent, 2) name_tokens = MetaData(self.name_tokens, name_tokens) if hasattr( self, cfg.NAME_TOKENS) else name_tokens meta_data = MetaData(self.meta_data, meta_data) if hasattr( self, cfg.META_DATA) else meta_data kwargs['skip_register'] = True kwargs['skip_report'] = True fk_chain = nt.LinearHierarchyNodeSet(chain_start, chain_end, duplicate=duplicate, parent=parent.pop()) fk_controls = nt.NonLinearHierarchyNodeSet() control_parent = parent.pop() for node, shape in zip( fk_chain, to_size_list(shape or self.DEFAULT_FK_SHAPE, len(fk_chain))): control = self.build_node(nt.Control, reference_object=node, shape=shape, parent=control_parent, name_tokens=name_tokens, meta_data=meta_data, **kwargs) control.parent(control_parent) control_parent = control.node.connection_group rt.dcc.connections.parent(control_parent, node, maintainOffset=True) fk_controls.append(control) return fk_chain, fk_controls
def build_pole_vector_control(self, joints, ik_handle, parent=None, up_vector=None, aim_vector=None, up_object=None, move_by=None, meta_data=None, name_tokens=None, **kwargs): """ Builds a pole vector control based on positions of joints and existing ik handle. Runs as follows: - Point constraint to the two base positions, aim constrain to the other objects - Delete constraints then move the control outside of the reference transforms in the aim direction. :param parent: list or object: list of up to length 3, [control parent, clusters parent, pv line parent] :param joints: LinearHierarchyNodeSet(Joint), linear hierarchy set of joints. :param ik_handle: DagNode, ik handle node :param kwargs: dict, build kwargs for the control build call :return: (Control, DagNode, NonLinearHierarchyNodeSet(DagNode)) """ parent = list(reversed(to_size_list(parent, 3))) name_tokens = MetaData(self.name_tokens, name_tokens) if hasattr( self, cfg.NAME_TOKENS) else name_tokens meta_data = MetaData(self.meta_data, meta_data) if hasattr( self, cfg.META_DATA) else meta_data kwargs.update({ cfg.NAME_TOKENS: name_tokens, cfg.META_DATA: meta_data, 'move_by': move_by, 'parent': parent.pop(), 'up_vector': up_vector, 'aim_vector': aim_vector, 'up_object': up_object }) control = nt.Control.build_pole_vector(joints, ik_handle, **kwargs) pv_line, clusters = nt.Curve.build_line_indicator( joints[len(joints) // 2], control.controller, **kwargs) cluster_parent = parent.pop() for cluster in clusters: cluster.visibility.set(False) cluster.parent(cluster_parent) pv_line.parent(parent.pop()) return control, pv_line, nt.NonLinearHierarchyNodeSet(clusters)
def wrapper(abstract_grouping, *args, **kwargs): """ Creates a dictionary of created nodes that will be digested later by the node registration function. :param args: object, node to sort into the hierarchy, SHOULD be an Anvil node. :param kwargs: dict, use kwargs if you want to override the types. By default accepts any key from abstract_grouping.BUILD_REPORT_KEYS :return: A build report looks like this: {'control': {'default': [anvil_controls_or_set_of_controls, ...]}, 'node': {'default': [anvil_nodes_or_set_of_nodes, ...], 'user custom hierarchy id': node}}, 'set': {'default': None}, 'joint': {'default': None}, A top level key will not be present if the result nodes from the wrapped function are not of that type. The top level key possibilities are: ['control', 'joint', 'node', 'set'] """ skip_report = kwargs.pop('skip_report', False) custom_hierarchy_ids = kwargs.pop(cfg.ID_TYPE, None) nodes_built = f(abstract_grouping, *args, **kwargs) if skip_report: return nodes_built result = {} nodes_built = to_list(nodes_built) for node, hierarchy_id in zip(nodes_built, to_size_list(custom_hierarchy_ids, len(nodes_built))): tag = getattr(node, cfg.ANVIL_TYPE, cfg.NODE_TYPE) if hierarchy_id: # We are assuming the extra tag is unique and we can just do a plain update instead of checking. result.update({tag: {hierarchy_id: node}}) else: result[tag] = result.get(tag, {cfg.DEFAULT: []}) result[tag][cfg.DEFAULT].append(node) return result
def build_ik_chain(self, layout_joints, ik_end_index=-1, solver=cfg.IK_RP_SOLVER, parent=None, duplicate=True, **kwargs): """ :param parent: list or object: list of up to length 4: [ik chain parent, handle parent, pv control parent, [3 pole vector control parents]] :return: (NonLinearHierarchyNodeSet(Control), LinearHierarchyNodeSet(Joint)) """ parent = list(reversed(to_size_list(parent, 3))) kwargs[cfg.SKIP_REGISTER] = True kwargs[cfg.SKIP_REPORT] = True ik_chain = nt.LinearHierarchyNodeSet(layout_joints, duplicate=duplicate, parent=parent.pop(), **kwargs) handle, effector = self.build_ik(ik_chain, chain_end=ik_chain[ik_end_index], parent=parent.pop(), name_tokens=MetaData({cfg.NAME: cfg.IK}, kwargs.pop(cfg.NAME_TOKENS, {})), **kwargs) controls = nt.NonLinearHierarchyNodeSet() # build ik control controls.append(nt.Control.build(**MetaData(kwargs, {cfg.PARENT: parent.pop(), cfg.REFERENCE_OBJECT: ik_chain[-1], cfg.SHAPE: cfg.DEFAULT_IK_SHAPE, cfg.NAME_TOKENS: {cfg.PURPOSE: cfg.IK}}).to_dict())) # build pole vector control if using RP solver. if solver == cfg.IK_RP_SOLVER: pv_control = self.build_pole_vector_control(ik_chain, handle, **MetaData(kwargs, {cfg.SHAPE: cfg.DEFAULT_PV_SHAPE, cfg.NAME_TOKENS: { cfg.PURPOSE: cfg.POLE_VECTOR}})) controls.append(pv_control) rt.dcc.connections.translate(controls[0].connection_group, handle) return ik_chain, controls, handle, effector
def build_pole_vector_control(self, joints, ik_handle, parent=None, up_vector=None, aim_vector=None, up_object=None, move_by=None, meta_data=None, name_tokens=None, **kwargs): """ Builds a pole vector control based on positions of joints and existing ik handle. Runs as follows: - Point constraint to the two base positions, aim constrain to the other objects - Delete constraints then move the control outside of the reference transforms in the aim direction. :param parent: list or object: list of up to length 3, [control parent, clusters parent, pv line parent] :param joints: LinearHierarchyNodeSet(Joint), linear hierarchy set of joints. :param ik_handle: DagNode, ik handle node :param kwargs: dict, build kwargs for the control build call :return: (Control, DagNode, NonLinearHierarchyNodeSet(DagNode)) """ parent = list(reversed(to_size_list(parent, 3))) name_tokens = MetaData(self.name_tokens, name_tokens) if hasattr(self, cfg.NAME_TOKENS) else name_tokens meta_data = MetaData(self.meta_data, meta_data) if hasattr(self, cfg.META_DATA) else meta_data kwargs.update({cfg.NAME_TOKENS: name_tokens, cfg.META_DATA: meta_data, 'move_by': move_by, 'parent': parent.pop(), 'up_vector': up_vector, 'aim_vector': aim_vector, 'up_object': up_object}) control = nt.Control.build_pole_vector(joints, ik_handle, **kwargs) pv_line, clusters = nt.Curve.build_line_indicator(joints[len(joints) // 2], control.controller, **kwargs) cluster_parent = parent.pop() for cluster in clusters: cluster.visibility.set(False) cluster.parent(cluster_parent) pv_line.parent(parent.pop()) return control, pv_line, nt.NonLinearHierarchyNodeSet(clusters)
def __init__(self, heel=None, outsole=None, insole=None, *args, **kwargs): super(BipedFoot, self).__init__(*args, **kwargs) self.ankle, self.ball, self.toe = to_size_list(self.layout_joints, 3) self.heel = heel self.outsole = outsole self.insole = insole
def test_kwarg_shape_input(self): self.assertEqual(generic.to_size_list('pyramid', 6), ['pyramid'] * 6)
def test_over_length_shape_list(self): input = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] self.assertEqual(generic.to_size_list(input, 5), input[:5])
def test_short_shape_list_by_one(self): input = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] self.assertEqual(generic.to_size_list(input, 9), ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'h'])
def test_short_shape_list(self): input = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] self.assertEqual(generic.to_size_list(input, 14), ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] + ['h'] * 6)
def test_input_shape_list(self): input = ['f', 'g', 'h', 'i'] self.assertEqual(generic.to_size_list(input, 4), input)