Ejemplo n.º 1
0
    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
Ejemplo n.º 2
0
    def build_sub_rig(self, sub_rig_key, sub_rig_candidate=SubRig, **kwargs):
        """ Initializes the given sub rig candidate class with kwargs and stores it in property sub_rigs under the key.

        :param sub_rig_key: str, key to store the sub rig under on the rig.
        :param sub_rig_candidate: anvil.sub_rig, a class that inherits from anvil.sub_rig.
        """
        kwargs[cfg.NAME_TOKENS] = MetaData(self.name_tokens,
                                           kwargs.get(cfg.NAME_TOKENS, {}))
        kwargs[cfg.META_DATA] = MetaData(self.meta_data,
                                         kwargs.get(cfg.META_DATA, {}))
        if inspect.isclass(sub_rig_candidate) and issubclass(
                sub_rig_candidate, SubRig):
            self.sub_rigs[sub_rig_key] = sub_rig_candidate(**kwargs)
            return self.sub_rigs[sub_rig_key]
Ejemplo n.º 3
0
    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)
Ejemplo n.º 4
0
    def build_ik(self,
                 linear_hierarchy_set,
                 solver=cfg.IK_RP_SOLVER,
                 parent=None,
                 name_tokens=None,
                 **kwargs):
        """

        :param parent: list or object: list of up to length 1, [handle parent]
        :return: (NonLinearHierarchyNodeSet(Control), LinearHierarchyNodeSet(Joint))
        """
        name_tokens = MetaData({cfg.TYPE: cfg.IK_HANDLE}, name_tokens or {})
        kwargs.update({
            'endEffector': str(linear_hierarchy_set.tail),
            'solver': solver
        })

        handle, effector = anvil.factory_list(
            rt.dcc.rigging.ik_handle(str(linear_hierarchy_set.head), **kwargs))
        if parent:
            rt.dcc.scene.parent(handle, parent)

        handle.name_tokens.update(name_tokens)
        effector.name_tokens.update({cfg.TYPE: cfg.IK_EFFECTOR})

        return handle, effector
Ejemplo n.º 5
0
class SubRig(base.AbstractGrouping):
    BUILT_IN_NAME_TOKENS = MetaData(base.AbstractGrouping.BUILT_IN_NAME_TOKENS)
    ROOT_NAME_TOKENS = {cfg.RIG_TYPE: cfg.SUB_RIG_TOKEN, cfg.TYPE: cfg.GROUP_TYPE}
    LOG = lg.obtain_logger(__name__)
    SUB_GROUPS = ['surfaces', 'joints', 'controls', 'nodes', 'world']

    def build(self, parent=None, **kwargs):
        super(SubRig, self).build(**kwargs)
        if self.root is None:
            self.build_node(Transform, meta_data=self.meta_data,
                            name_tokens=self.name_tokens + {cfg.RIG_TYPE: cfg.SUB_RIG_TYPE, cfg.TYPE: cfg.GROUP_TYPE},
                            **self.build_kwargs)
            self.root = self.group_top = self.hierarchy[cfg.NODE_TYPE][cfg.DEFAULT][-1]

        for main_group_type in self.SUB_GROUPS:
            hierarchy_id = '%s_%s' % (cfg.GROUP_TYPE, main_group_type)
            self.build_node(Transform,
                            hierarchy_id=hierarchy_id,
                            parent=self.root,
                            meta_data=self.meta_data,
                            name_tokens=self.name_tokens + {cfg.CHILD_TYPE: main_group_type, cfg.TYPE: cfg.GROUP_TYPE},
                            **self.build_kwargs)
            setattr(self, hierarchy_id, self.hierarchy[cfg.NODE_TYPE][hierarchy_id])
        self.group_world.inheritsTransform.set(False)

        self.parent(parent)
        self.initialize_sub_rig_attributes()
        self.connect_rendering_delegate()

        self.info('Built %s: %s', self.__class__.__name__, self)
Ejemplo n.º 6
0
    def __init__(self,
                 node_pointer,
                 meta_data=None,
                 name_tokens=None,
                 **kwargs):
        """ All nodes must be initialized with a string representation that the encompassing platform
            uses as DAG path representation for the object.

        :param node_pointer: str, DAG path to the object we want to encapsulate
        :param kwargs: dict, creation flags specific for the platform environment node creation function
        :param meta_data: dict, any object specific meta data we want to record
        """
        self._dcc_id = rt.dcc.scene.get_persistent_id(str(node_pointer))

        self.meta_data = self.BUILT_IN_METADATA.merge(meta_data, new=True)
        self.meta_data.set_protected(self.BUILT_IN_METADATA)

        self.name_tokens = self.BUILT_IN_NAME_TOKENS.merge(name_tokens,
                                                           new=True)
        self.name_tokens.set_protected(self.BUILT_IN_NAME_TOKENS.protected)

        self.build_kwargs = MetaData(kwargs)

        try:
            self._api_class_instance = rt.dcc.scene.APIWrapper(
                str(node_pointer))
        except AttributeError:
            self._api_class_instance = object()
Ejemplo n.º 7
0
 def rename(self, *input_dicts, **kwargs):
     new_tokens = MetaData(*input_dicts, **kwargs)
     self.name_tokens.merge(new_tokens)
     self._nomenclate.merge_dict(**self.name_tokens.data)
     self._cascade_across_hierarchy(
         lambda n: n.rename(
             self._nomenclate.get(**n.name_tokens.update(new_tokens))),
         lambda n: n.rename(self.name_tokens, n.name_tokens))
Ejemplo n.º 8
0
    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
Ejemplo n.º 9
0
    def __init__(self,
                 layout_joints=None,
                 parent=None,
                 top_node=None,
                 name_tokens=None,
                 meta_data=None,
                 **kwargs):
        self.hierarchy = Map()
        self.root = top_node
        self.layout_joints = layout_joints
        self.build_joints = None
        self.build_kwargs = MetaData(kwargs)
        self.name_tokens = self.BUILT_IN_NAME_TOKENS.merge(name_tokens,
                                                           new=True)
        self.meta_data = self.BUILT_IN_META_DATA.merge(meta_data, new=True)

        self._nomenclate = nomenclate.Nom(self.name_tokens.data)
        self.chain_nomenclate = nomenclate.Nom()

        for namer in [self._nomenclate, self.chain_nomenclate]:
            namer.format = cfg.RIG_FORMAT
            namer.var.case = cfg.UPPER

        self.parent(parent)
Ejemplo n.º 10
0
 def build_line_indicator(cls, object1, object2, **kwargs):
     kwargs[cfg.DEGREE] = 1
     kwargs[cfg.NAME_TOKENS] = MetaData(kwargs.get(cfg.NAME_TOKENS, {}))
     kwargs[cfg.NAME_TOKENS].update({
         cfg.NAME:
         '%s_to_%s' % (object1, object2),
         cfg.TYPE:
         cfg.CURVE_TYPE
     })
     curve = cls.build_from_nodes([object1, object2], **kwargs)
     object1_cluster, object2_cluster = curve.generate_clusters()
     object1_cluster.parent(object1)
     object2_cluster.parent(object2)
     curve.overrideEnabled.set(1)
     curve.overrideDisplayType.set(1)
     return (curve, [object1_cluster, object1_cluster])
Ejemplo n.º 11
0
    def __init__(self, layout_joints=None, parent=None, top_node=None, name_tokens=None, meta_data=None, **kwargs):
        self.hierarchy = Map()
        self.root = top_node
        self.layout_joints = layout_joints
        self.build_joints = None
        self.build_kwargs = MetaData(kwargs)
        self.name_tokens = self.BUILT_IN_NAME_TOKENS.merge(name_tokens, new=True)
        self.meta_data = self.BUILT_IN_META_DATA.merge(meta_data, new=True)

        self._nomenclate = nomenclate.Nom(self.name_tokens.data)
        self.chain_nomenclate = nomenclate.Nom()

        for namer in [self._nomenclate, self.chain_nomenclate]:
            namer.format = cfg.RIG_FORMAT
            namer.var.case = cfg.UPPER

        self.parent(parent)
Ejemplo n.º 12
0
class Rig(base.AbstractGrouping):
    """ A fully functional and self-contained rig with all requirements implemented that
        require it to give a performance.  A collection of SubRig(s)
    """
    LOG = anvil.log.obtain_logger(__name__)
    BUILT_IN_NAME_TOKENS = MetaData(base.AbstractGrouping.BUILT_IN_NAME_TOKENS)
    SUB_RIG_BUILD_ORDER = []
    SUB_RIG_BUILD_TABLE = OrderedDict()
    ORDERED_SUB_RIG_KEYS = []
    SUB_GROUPINGS = ['extras', 'model', 'sub_rigs']

    ROOT_NAME_TOKENS = {cfg.RIG_TYPE: cfg.RIG_TYPE, cfg.TYPE: cfg.GROUP_TYPE}
    UNIV_NAME_TOKENS = {cfg.CHILD_TYPE: cfg.UNIVERSAL}

    def __init__(self, character=None, sub_rig_dict=None, *args, **kwargs):
        self.sub_rigs = OrderedDict.fromkeys(self.ORDERED_SUB_RIG_KEYS)
        super(Rig, self).__init__(*args, **kwargs)
        self.name_tokens[cfg.CHARACTER] = character or self.name_tokens.get(
            cfg.CHARACTER, '')
        self.register_sub_rigs_from_dict(sub_rig_dict)

    def rename(self, *input_dicts, **name_tokens):
        super(Rig, self).rename(*input_dicts, **name_tokens)
        for sub_rig_instance in itervalues(self.sub_rigs):
            sub_rig_instance.rename()  # *input_dicts, **name_tokens)

    def register_sub_rigs_from_dict(self, sub_rig_dict):
        """ Only accepts dictionary with keys that match the built in SUB_RIG_BUILD_TABLE for the given Rig.
            Rig will initialize sub-rigs from the key, value and look up the proper sub-rig class from the build table.
            This is meant to rebuild a rig from a deserialized rig.

        :param sub_rig_dict: dict, key must be in SUB_RIG_BUILD_TABLE and value must be dict or list of joints.
        """
        if sub_rig_dict is None or not isinstance(sub_rig_dict, dict):
            return

        for sub_rig_name, sub_rig_data in iteritems(sub_rig_dict):
            try:
                sub_rig_construction_data = self.SUB_RIG_BUILD_TABLE.get(
                    sub_rig_name)
                sub_rig_class, default_name_tokens = sub_rig_construction_data
                sub_rig_kwargs = sub_rig_data if isinstance(
                    sub_rig_data, dict) else {
                        cfg.LAYOUT: sub_rig_data
                    }
                self.build_sub_rig(sub_rig_name,
                                   sub_rig_class,
                                   name_tokens=default_name_tokens,
                                   **sub_rig_kwargs)
            except TypeError:
                self.warning(
                    'Sub rig table entry %r not found in input dict %s',
                    sub_rig_name, sub_rig_dict)

    def build_sub_rig(self, sub_rig_key, sub_rig_candidate=SubRig, **kwargs):
        """ Initializes the given sub rig candidate class with kwargs and stores it in property sub_rigs under the key.

        :param sub_rig_key: str, key to store the sub rig under on the rig.
        :param sub_rig_candidate: anvil.sub_rig, a class that inherits from anvil.sub_rig.
        """
        kwargs[cfg.NAME_TOKENS] = MetaData(self.name_tokens,
                                           kwargs.get(cfg.NAME_TOKENS, {}))
        kwargs[cfg.META_DATA] = MetaData(self.meta_data,
                                         kwargs.get(cfg.META_DATA, {}))
        if inspect.isclass(sub_rig_candidate) and issubclass(
                sub_rig_candidate, SubRig):
            self.sub_rigs[sub_rig_key] = sub_rig_candidate(**kwargs)
            return self.sub_rigs[sub_rig_key]

    def build_sub_rigs(self):
        for sub_rig_member in itervalues(self.sub_rigs):
            if not sub_rig_member.is_built:
                self.info('Building sub-rig %s on rig %s', sub_rig_member,
                          self)
                sub_rig_member.build()
            anvil.runtime.dcc.scene.parent(sub_rig_member.root,
                                           self.node.group_sub_rigs)

    def auto_color(self):
        super(Rig, self).auto_color()
        for sub_rig_instance in itervalues(self.sub_rigs):
            sub_rig_instance.auto_color()

    def build(self, parent=None, name_tokens=None, **kwargs):
        self.info(
            'Building %s(%r) with parent: %s, name_tokens: %s, and kwargs: %s',
            self.__class__.__name__, self, parent, name_tokens, kwargs)
        self.name_tokens.update(name_tokens)

        self.build_node(ot.Transform,
                        hierarchy_id='top',
                        name_tokens=self.ROOT_NAME_TOKENS,
                        **kwargs)
        self.root = self.node.top

        self.build_node(ct.Control,
                        hierarchy_id='universal',
                        parent=self.node.top,
                        shape=cfg.DEFAULT_UNIVERSAL_SHAPE,
                        scale=5,
                        name_tokens=self.UNIV_NAME_TOKENS,
                        **kwargs)

        for main_group_type in self.SUB_GROUPINGS:
            self.build_node(
                ot.Transform,
                hierarchy_id='%s_%s' % (cfg.GROUP_TYPE, main_group_type),
                parent=self.control.universal.node.connection_group,
                name_tokens={
                    cfg.CHILD_TYPE: main_group_type,
                    cfg.TYPE: cfg.GROUP_TYPE
                })

        self.build_sub_rigs()
        self.initialize_sub_rig_attributes(self.control.universal.node.control)
        self.connect_rendering_delegate(self.control.universal.node.control)
        self.parent(parent)
        self.rename()
        self.auto_color()

    def __getattr__(self, item):
        try:
            return super(Rig, self).__getattribute__('sub_rigs')[item]
        except KeyError:
            return super(Rig, self).__getattr__(item)
Ejemplo n.º 13
0
 def __init__(self, nodes=None, name_tokens=None, **kwargs):
     self.name_tokens = MetaData(name_tokens or {}, **kwargs)
     self.nodes = nodes or []
Ejemplo n.º 14
0
class AbstractGrouping(log.LogMixin):
    """ A fully functional and self-contained rig with all requirements implemented that
        are required to give a performance.

    """
    LOG = log.obtain_logger(__name__)
    ANVIL_TYPE = cfg.RIG_TYPE
    BUILT_IN_NAME_TOKENS = MetaData({cfg.TYPE: cfg.GROUP_TYPE, cfg.NAME: 'untitled'}, protected=cfg.TYPE)
    BUILT_IN_META_DATA = MetaData()
    BUILT_IN_ATTRIBUTES = MetaData({})
    RENDERING_ATTRIBUTES = MetaData({
        '%ss' % cfg.SURFACE_TYPE: at.DISPLAY_KWARGS,
        '%ss' % cfg.JOINT_TYPE: merge_dicts(at.DISPLAY_KWARGS, {cfg.DEFAULT_VALUE: 2}),
        '%ss' % cfg.NODE_TYPE: at.DISPLAY_KWARGS,
        '%ss' % cfg.CONTROL_TYPE: merge_dicts(at.DISPLAY_KWARGS, {cfg.DEFAULT_VALUE: 1}),
        '%s' % cfg.LOD: merge_dicts(at.DISPLAY_KWARGS, {cfg.ENUM_NAME: 'Hero:Proxy'})
    })
    BUILD_REPORT_KEYS = [cfg.CONTROL_TYPE, cfg.JOINT_TYPE, cfg.NODE_TYPE]

    def __init__(self, layout_joints=None, parent=None, top_node=None, name_tokens=None, meta_data=None, **kwargs):
        self.hierarchy = Map()
        self.root = top_node
        self.layout_joints = layout_joints
        self.build_joints = None
        self.build_kwargs = MetaData(kwargs)
        self.name_tokens = self.BUILT_IN_NAME_TOKENS.merge(name_tokens, new=True)
        self.meta_data = self.BUILT_IN_META_DATA.merge(meta_data, new=True)

        self._nomenclate = nomenclate.Nom(self.name_tokens.data)
        self.chain_nomenclate = nomenclate.Nom()

        for namer in [self._nomenclate, self.chain_nomenclate]:
            namer.format = cfg.RIG_FORMAT
            namer.var.case = cfg.UPPER

        self.parent(parent)

    @property
    def is_built(self):
        return all([self.root])

    def build(self, joints=None, meta_data=None, name_tokens=None, **kwargs):
        self.build_kwargs.merge(kwargs)
        self.meta_data.merge(meta_data)
        self.name_tokens.merge(name_tokens)
        self.build_joints = joints or self.layout_joints

    def build_layout(self):
        raise NotImplementedError

    @register_built_nodes
    @generate_build_report
    def register_node(self, node, **kwargs):
        return node

    def connect_rendering_delegate(self, assignee=None):
        # TODO: API Attribute dependent...dangerous.
        assignee = anvil.factory(assignee) if assignee is not None else self.root

        for attr, attr_kwargs in iteritems(self.RENDERING_ATTRIBUTES):
            attr_name = '%s_rendering' % attr
            group_name = 'group_%s' % attr

            rendering_attribute = assignee.add_attr(attr_name, **attr_kwargs)

            if hasattr(self, group_name):
                target_group = getattr(self, group_name)
                target_group.overrideEnabled.set(1)
                rendering_attribute.connect(target_group.visibility, force=True)
                assignee.buffer_connect(attr_name, target_group.overrideDisplayType, -1, force=True)

    def initialize_sub_rig_attributes(self, controller=None, attr_dict=None):
        attr_dict = self.BUILT_IN_ATTRIBUTES if attr_dict is None else attr_dict
        if attr_dict:
            controller = self.root if controller is None else anvil.factory(controller)
            for attr, attr_kwargs in iteritems(attr_dict):
                controller.add_attr(attr, **attr_kwargs)

    def parent(self, new_parent, override_root=None):
        nodes_exist = [rt.dcc.scene.exists(node) if node is not None else False for node in
                       [override_root or self.root, new_parent]]
        if all(nodes_exist or [False]):
            (override_root or self.root).parent(new_parent)
            return True
        else:
            self.warning('Parent(%s) -> %r does not exist.', new_parent, override_root or self.root)
            return False

    def rename_chain(self, nodes, use_end_naming=False, **name_tokens):
        self.chain_nomenclate.merge_dict(self.name_tokens.merge(name_tokens))

        for index, object in enumerate(nodes):
            variation_kwargs = {'var': index}
            if use_end_naming and index == len(nodes) - 1:
                variation_kwargs = {'decorator': 'End'}
            rt.dcc.scene.rename(object, self.chain_nomenclate.get(**variation_kwargs))

    def rename(self, *input_dicts, **kwargs):
        new_tokens = MetaData(*input_dicts, **kwargs)
        self.name_tokens.merge(new_tokens)
        self._nomenclate.merge_dict(**self.name_tokens.data)
        self._cascade_across_hierarchy(lambda n: n.rename(self._nomenclate.get(**n.name_tokens.update(new_tokens))),
                                       lambda n: n.rename(self.name_tokens, n.name_tokens))

    @register_built_nodes
    @generate_build_report
    def build_node(self, node_class, *args, **kwargs):
        try:
            build_function = kwargs.pop('build_fn')
        except KeyError:
            build_function = 'build'
        kwargs[cfg.NAME_TOKENS] = self.name_tokens.merge(kwargs.get(cfg.NAME_TOKENS, {}), new=True)
        kwargs[cfg.META_DATA] = self.meta_data.merge(kwargs.get(cfg.META_DATA, {}), new=True)
        return getattr(node_class, build_function)(*args, **kwargs)

    def auto_color(self):
        self._cascade_across_hierarchy(lambda n: n.auto_color() if hasattr(n, 'auto_color') else None,
                                       lambda n: n.auto_color() if hasattr(n, 'auto_color') else None)

    def find_node(self, node_key, category_override=None):
        """ This will only work with user specified hierarchy IDs.
            Otherwise it will not detect the node key from the default node list.

        :param node_key: str, node key we are looking for within the hierarchy initial sets
        :param category_override: str, if there are double keys we can add granularity and specify the initial key.
        """
        try:
            if category_override:
                return self.hierarchy[category_override][node_key]
            for sub_hierarchy in itervalues(self.hierarchy):
                candidate = sub_hierarchy.get(node_key)
                if candidate:
                    return candidate
        except:
            raise KeyError('Node from key %s not found in hierarchy' % (
                '.'.join([category_override, node_key]) if category_override else node_key))

    def _flat_hierarchy(self):
        return gen_flatten_dict_depth_two(self.hierarchy)

    def _cascade_across_hierarchy(self, object_function, grouping_function):
        for sub_node in itervalues(self.hierarchy):
            for anvil_node in itervalues(sub_node):
                for node in anvil_node if anvil.is_aset(anvil_node) else [anvil_node]:
                    if anvil.is_agrouping(node):
                        grouping_function(node)
                    elif anvil.is_aobject(node):
                        object_function(node)

    def __getattr__(self, item):
        try:
            return super(AbstractGrouping, self).__getattribute__('hierarchy')[item]
        except KeyError:
            return super(AbstractGrouping, self).__getattribute__(item)

    def __str__(self):
        try:
            if self.root is None:
                raise KeyError
            return str(self.root)
        except (KeyError, AttributeError):
            return super(AbstractGrouping, self).__str__()

    def __repr__(self):
        formatted_properties = ' root=%s children=%d>' % (self.root, len(list(self.hierarchy)))
        return super(AbstractGrouping, self).__repr__().replace('>', formatted_properties)

    def __dir__(self):
        return dir(super(AbstractGrouping, self)) + list(self.hierarchy)
Ejemplo n.º 15
0
class AbstractGrouping(log.LogMixin):
    """ A fully functional and self-contained rig with all requirements implemented that
        are required to give a performance.

    """
    LOG = log.obtain_logger(__name__)
    ANVIL_TYPE = cfg.RIG_TYPE
    BUILT_IN_NAME_TOKENS = MetaData(
        {
            cfg.TYPE: cfg.GROUP_TYPE,
            cfg.NAME: 'untitled'
        }, protected=cfg.TYPE)
    BUILT_IN_META_DATA = MetaData()
    BUILT_IN_ATTRIBUTES = MetaData({})
    RENDERING_ATTRIBUTES = MetaData({
        '%ss' % cfg.SURFACE_TYPE:
        at.DISPLAY_KWARGS,
        '%ss' % cfg.JOINT_TYPE:
        merge_dicts(at.DISPLAY_KWARGS, {cfg.DEFAULT_VALUE: 2}),
        '%ss' % cfg.NODE_TYPE:
        at.DISPLAY_KWARGS,
        '%ss' % cfg.CONTROL_TYPE:
        merge_dicts(at.DISPLAY_KWARGS, {cfg.DEFAULT_VALUE: 1}),
        '%s' % cfg.LOD:
        merge_dicts(at.DISPLAY_KWARGS, {cfg.ENUM_NAME: 'Hero:Proxy'})
    })
    BUILD_REPORT_KEYS = [cfg.CONTROL_TYPE, cfg.JOINT_TYPE, cfg.NODE_TYPE]

    def __init__(self,
                 layout_joints=None,
                 parent=None,
                 top_node=None,
                 name_tokens=None,
                 meta_data=None,
                 **kwargs):
        self.hierarchy = Map()
        self.root = top_node
        self.layout_joints = layout_joints
        self.build_joints = None
        self.build_kwargs = MetaData(kwargs)
        self.name_tokens = self.BUILT_IN_NAME_TOKENS.merge(name_tokens,
                                                           new=True)
        self.meta_data = self.BUILT_IN_META_DATA.merge(meta_data, new=True)

        self._nomenclate = nomenclate.Nom(self.name_tokens.data)
        self.chain_nomenclate = nomenclate.Nom()

        for namer in [self._nomenclate, self.chain_nomenclate]:
            namer.format = cfg.RIG_FORMAT
            namer.var.case = cfg.UPPER

        self.parent(parent)

    @property
    def is_built(self):
        return all([self.root])

    def build(self, joints=None, meta_data=None, name_tokens=None, **kwargs):
        self.build_kwargs.merge(kwargs)
        self.meta_data.merge(meta_data)
        self.name_tokens.merge(name_tokens)
        self.build_joints = joints or self.layout_joints

    def build_layout(self):
        raise NotImplementedError

    @register_built_nodes
    @generate_build_report
    def register_node(self, node, **kwargs):
        return node

    def connect_rendering_delegate(self, assignee=None):
        # TODO: API Attribute dependent...dangerous.
        assignee = anvil.factory(
            assignee) if assignee is not None else self.root

        for attr, attr_kwargs in iteritems(self.RENDERING_ATTRIBUTES):
            attr_name = '%s_rendering' % attr
            group_name = 'group_%s' % attr

            rendering_attribute = assignee.add_attr(attr_name, **attr_kwargs)

            if hasattr(self, group_name):
                target_group = getattr(self, group_name)
                target_group.overrideEnabled.set(1)
                rendering_attribute.connect(target_group.visibility,
                                            force=True)
                assignee.buffer_connect(attr_name,
                                        target_group.overrideDisplayType,
                                        -1,
                                        force=True)

    def initialize_sub_rig_attributes(self, controller=None, attr_dict=None):
        attr_dict = self.BUILT_IN_ATTRIBUTES if attr_dict is None else attr_dict
        if attr_dict:
            controller = self.root if controller is None else anvil.factory(
                controller)
            for attr, attr_kwargs in iteritems(attr_dict):
                controller.add_attr(attr, **attr_kwargs)

    def parent(self, new_parent, override_root=None):
        nodes_exist = [
            rt.dcc.scene.exists(node) if node is not None else False
            for node in [override_root or self.root, new_parent]
        ]
        if all(nodes_exist or [False]):
            (override_root or self.root).parent(new_parent)
            return True
        else:
            self.warning('Parent(%s) -> %r does not exist.', new_parent,
                         override_root or self.root)
            return False

    def rename_chain(self, nodes, use_end_naming=False, **name_tokens):
        self.chain_nomenclate.merge_dict(self.name_tokens.merge(name_tokens))

        for index, object in enumerate(nodes):
            variation_kwargs = {'var': index}
            if use_end_naming and index == len(nodes) - 1:
                variation_kwargs = {'decorator': 'End'}
            rt.dcc.scene.rename(object,
                                self.chain_nomenclate.get(**variation_kwargs))

    def rename(self, *input_dicts, **kwargs):
        new_tokens = MetaData(*input_dicts, **kwargs)
        self.name_tokens.merge(new_tokens)
        self._nomenclate.merge_dict(**self.name_tokens.data)
        self._cascade_across_hierarchy(
            lambda n: n.rename(
                self._nomenclate.get(**n.name_tokens.update(new_tokens))),
            lambda n: n.rename(self.name_tokens, n.name_tokens))

    @register_built_nodes
    @generate_build_report
    def build_node(self, node_class, *args, **kwargs):
        try:
            build_function = kwargs.pop('build_fn')
        except KeyError:
            build_function = 'build'
        kwargs[cfg.NAME_TOKENS] = self.name_tokens.merge(kwargs.get(
            cfg.NAME_TOKENS, {}),
                                                         new=True)
        kwargs[cfg.META_DATA] = self.meta_data.merge(kwargs.get(
            cfg.META_DATA, {}),
                                                     new=True)
        return getattr(node_class, build_function)(*args, **kwargs)

    def auto_color(self):
        self._cascade_across_hierarchy(
            lambda n: n.auto_color()
            if hasattr(n, 'auto_color') else None, lambda n: n.auto_color()
            if hasattr(n, 'auto_color') else None)

    def find_node(self, node_key, category_override=None):
        """ This will only work with user specified hierarchy IDs.
            Otherwise it will not detect the node key from the default node list.

        :param node_key: str, node key we are looking for within the hierarchy initial sets
        :param category_override: str, if there are double keys we can add granularity and specify the initial key.
        """
        try:
            if category_override:
                return self.hierarchy[category_override][node_key]
            for sub_hierarchy in itervalues(self.hierarchy):
                candidate = sub_hierarchy.get(node_key)
                if candidate:
                    return candidate
        except:
            raise KeyError('Node from key %s not found in hierarchy' %
                           ('.'.join([category_override, node_key])
                            if category_override else node_key))

    def _flat_hierarchy(self):
        return gen_flatten_dict_depth_two(self.hierarchy)

    def _cascade_across_hierarchy(self, object_function, grouping_function):
        for sub_node in itervalues(self.hierarchy):
            for anvil_node in itervalues(sub_node):
                for node in anvil_node if anvil.is_aset(anvil_node) else [
                        anvil_node
                ]:
                    if anvil.is_agrouping(node):
                        grouping_function(node)
                    elif anvil.is_aobject(node):
                        object_function(node)

    def __getattr__(self, item):
        try:
            return super(AbstractGrouping,
                         self).__getattribute__('hierarchy')[item]
        except KeyError:
            return super(AbstractGrouping, self).__getattribute__(item)

    def __str__(self):
        try:
            if self.root is None:
                raise KeyError
            return str(self.root)
        except (KeyError, AttributeError):
            return super(AbstractGrouping, self).__str__()

    def __repr__(self):
        formatted_properties = ' root=%s children=%d>' % (
            self.root, len(list(self.hierarchy)))
        return super(AbstractGrouping,
                     self).__repr__().replace('>', formatted_properties)

    def __dir__(self):
        return dir(super(AbstractGrouping, self)) + list(self.hierarchy)
Ejemplo n.º 16
0
class UnicodeDelegate(log.LogMixin):
    LOG = log.obtain_logger(__name__)
    DCC_TYPE = None
    ANVIL_TYPE = cfg.NODE_TYPE
    BUILT_IN_METADATA = MetaData({})
    BUILT_IN_NAME_TOKENS = MetaData(
        {
            cfg.TYPE: cfg.NODE_TYPE,
            cfg.NAME: 'untitled'
        }, protected=cfg.TYPE)

    def __init__(self,
                 node_pointer,
                 meta_data=None,
                 name_tokens=None,
                 **kwargs):
        """ All nodes must be initialized with a string representation that the encompassing platform
            uses as DAG path representation for the object.

        :param node_pointer: str, DAG path to the object we want to encapsulate
        :param kwargs: dict, creation flags specific for the platform environment node creation function
        :param meta_data: dict, any object specific meta data we want to record
        """
        self._dcc_id = rt.dcc.scene.get_persistent_id(str(node_pointer))

        self.meta_data = self.BUILT_IN_METADATA.merge(meta_data, new=True)
        self.meta_data.set_protected(self.BUILT_IN_METADATA)

        self.name_tokens = self.BUILT_IN_NAME_TOKENS.merge(name_tokens,
                                                           new=True)
        self.name_tokens.set_protected(self.BUILT_IN_NAME_TOKENS.protected)

        self.build_kwargs = MetaData(kwargs)

        try:
            self._api_class_instance = rt.dcc.scene.APIWrapper(
                str(node_pointer))
        except AttributeError:
            self._api_class_instance = object()

    def name(self):
        return self._dcc_id.partialPathName()

    def exists(self):
        return rt.dcc.scene.exists(self)

    def rename(self, new_name):
        return rt.dcc.scene.rename(self.name(), new_name)

    def type(self):
        return rt.dcc.scene.get_type(self)

    @staticmethod
    def create_engine_instance(**flags):
        raise NotImplementedError('Cannot instantiate nodes from this class')

    @classmethod
    def build(cls, **kwargs):
        cls.info('Building node %s: %s(%s)', cls.__name__, cls.DCC_TYPE,
                 kwargs)
        dcc_instance = cls.create_engine_instance(**kwargs)
        instance = cls(dcc_instance, **kwargs)

        # If the instance isn't a string we can assume it's some API class instance we can use later.
        if not isinstance(dcc_instance, str):
            instance._api_class_instance = dcc_instance
        anvil.register_encapsulation(instance)
        return instance

    def get_history(self, **kwargs):
        return rt.dcc.connections.list_history(self, **kwargs)

    def get_future(self, **kwargs):
        kwargs['future'] = True
        return rt.dcc.connections.list_history(self, **kwargs)

    def __getattr__(self, item):
        try:
            return super(UnicodeDelegate, self).__getattribute__(item)
        except AttributeError:
            _api_class_instance = super(
                UnicodeDelegate, self).__getattribute__('_api_class_instance')
            try:
                return getattr(_api_class_instance, item)
            except AttributeError:
                return getattr(_api_class_instance, gc.to_camel_case(item))

    def __eq__(self, other):
        return str(self) == str(other)

    def __repr__(self):
        return '<%s.%s @ 0x%x (%s)>' % (self.__class__.__module__,
                                        self.__class__.__name__, id(self),
                                        str(self))

    def __str__(self):
        return str(self.name())