def _reference_alembic(self, alembic_file, namespace, parent):
        """
        Internal function that references given alembic file
        :param alembic_file: str
        :param namespace: str
        :return:
        """

        all_nodes = alembic.reference_alembic(project=self._project,
                                              alembic_file=alembic_file,
                                              namespace=namespace)
        if not all_nodes:
            logger.warning(
                'Error while reference Alembic file: {}'.format(alembic_file))
            return
        for obj in all_nodes:
            if not dcc.node_exists(obj):
                continue
            if not dcc.client().node_type(obj) == 'transform':
                continue
            obj_parent = dcc.client().node_parent(obj)
            if obj_parent:
                continue
            dcc.client().set_parent(node=obj, parent=parent)

        return all_nodes
    def _import_mesh_obj(self, data_path):
        """
        Internal function that imports mesh object stored in given path
        :param data_path: str, path that contains already exported mesh object
        :return: str, name of the imported mesh
        """

        dependencies = self.get_dependencies(data_path)
        mesh_path = dependencies.get('geo_file', None)
        if not mesh_path or not os.path.isfile(mesh_path):
            mesh_path = path_utils.join_path(data_path, 'mesh.obj')
        if not path_utils.is_file(mesh_path):
            return None

        nodes = dcc.client().list_nodes(node_type='mesh', full_path=False)
        dcc.client().import_file(mesh_path,
                                 import_type='OBJ',
                                 ignore_version=True,
                                 options='mo=1')
        current_nodes = dcc.client().list_nodes(node_type='mesh',
                                                full_path=False)
        delta = list(set(current_nodes).difference(nodes))
        if delta:
            delta = dcc.client().node_parent(delta, full_path=True)

        return delta
Beispiel #3
0
    def parse_object(self, name):
        """
        Returns the object data for the given object name
        :param name: str
        :return: dict
        """

        attrs = list(
            set(dcc.client().list_attributes(name, unlocked=True, keyable=True)
                or list()))
        attrs = [utils.Attribute(name, attr) for attr in attrs]

        data_dict = {
            'attrs': self.attrs(name),
            'uuid': dcc.client().node_handle(name)
        }

        for attr in attrs:
            if not attr.is_valid():
                continue
            if attr.value is None:
                logger.warning(
                    'Cannot save the attribute {} with value None'.format(
                        attr.fullname))
            else:
                data_dict['attrs'][attr.attr] = {
                    'type': attr.type,
                    'value': attr.value
                }

        return data_dict
    def _on_import_alembic(self, as_reference=False):
        """
        Internal callback function that is called when Import/Reference Alembic button is clicked
        :param as_reference: bool
        """

        abc_file = self._alembic_path_line.text()
        if not abc_file or not os.path.isfile(abc_file):
            dcc.client().confirm_dialog(
                title='Error',
                message=
                'No Alembic File is selected or file is not currently available in disk'
            )
            return None

        abc_name = os.path.basename(abc_file).split('.')[0]
        tag_json_file = os.path.join(
            os.path.dirname(abc_file),
            os.path.basename(abc_file).replace('.abc', '_abc.info'))
        valid_tag_info = True
        if os.path.isfile(tag_json_file):
            with open(tag_json_file, 'r') as f:
                tag_info = json.loads(f.read())
            if not tag_info:
                logger.warning('No Alembic Info loaded!')
                valid_tag_info = False
        else:
            logger.warning('No Alembic Info file found!')
            valid_tag_info = False

        if as_reference:
            reference_nodes = self._reference_alembic(alembic_file=abc_file,
                                                      namespace=abc_name)
        else:
            reference_nodes = self._import_alembic(
                alembic_file=abc_file, valid_tag_info=valid_tag_info)
        reference_nodes = python.force_list(reference_nodes)

        added_tag = False
        for key in tag_info.keys():
            if reference_nodes:
                for obj in reference_nodes:
                    short_obj = dcc.client().node_short_name(obj)
                    if key == short_obj:
                        self._add_tag_info_data(self._project, tag_info[key],
                                                obj)
                        added_tag = True

        if not added_tag:
            self._add_tag_info_data(self._project, tag_info,
                                    reference_nodes[0])

        if reference_nodes:
            if as_reference:
                self.showOk.emit('Alembic file referenced successfully!')
            else:
                self.showOk.emit('Alembic file imported successfully!')

        return reference_nodes
Beispiel #5
0
    def ls(cls, objects=None, selection=False):
        if objects is None and not selection:
            objects = dcc.client().all_scene_nodes(full_path=False)
        else:
            objects = objects or list()
            if selection:
                objects.extend(dcc.client().selected_nodes(full_path=False)
                               or [])

        return [cls(name) for name in objects]
 def __call__(self, *args, **kwargs):
     if dcc.client().is_maya():
         from artellapipe.tools.alembicmanager.dccs.maya import importer
         return type.__call__(importer.MayaAlembicImporter, *args, **kwargs)
     elif dcc.client().is_houdini():
         from artellapipe.tools.alembicmanager.dccs.houdini import importer
         return type.__call__(importer.HoudiniAlembicImporter, *args,
                              **kwargs)
     else:
         return type.__call__(BaseAlembicImporter, *args, **kwargs)
Beispiel #7
0
    def load(self):
        """
        Opens OS explorer where data is located
        """

        filepath = self.format_identifier()
        if not filepath.endswith(MayaBinaryData.EXTENSION):
            filepath = '{}{}'.format(filepath, MayaBinaryData.EXTENSION)

        if not filepath or not os.path.isfile(filepath):
            return

        dcc.client().open_file(filepath)
Beispiel #8
0
 def _recursive_hierarchy(transform):
     child_nodes = list()
     if not transform:
         return child_nodes
     transforms = dcc.client().list_relatives(node=transform,
                                              full_path=True)
     if not transforms:
         return child_nodes
     for eachTransform in transforms:
         if dcc.client().node_type(eachTransform) == 'transform':
             child_nodes.append(eachTransform)
             child_nodes.extend(_recursive_hierarchy(eachTransform))
     return child_nodes
Beispiel #9
0
    def save(self, *args, **kwargs):

        filepath = self.format_identifier()
        if not filepath.endswith(ControlCVsData.EXTENSION):
            filepath = '{}{}'.format(filepath, ControlCVsData.EXTENSION)

        if not filepath:
            logger.warning(
                'Impossible to save Control CVs file because save file path not defined!'
            )
            return

        logger.debug('Saving {} | {}'.format(filepath, kwargs))

        objects = kwargs.get('objects', None)
        if not objects:
            objects = dcc.client().selected_nodes(full_path=True)
        if not objects:
            logger.warning(
                'Nothing selected to export Control CVs of. Please, select a curve to export'
            )
            return False

        # We make sure that we store the short name of the controls
        objects = [dcc.client().node_short_name(obj) for obj in objects]

        controls = objects or controllib.get_controls()
        valid_controls = list()
        for control in controls:
            if not controllib.is_control(control):
                continue
            valid_controls.append(control)
        if not valid_controls:
            logger.warning('No valid controls found to export.')
            return False

        library = self._initialize_library(filepath)
        if not controls:
            logger.warning('No controls found to export.')
            return False

        for control in controls:
            library.add_curve(control)

        library.write_data_to_file()

        logger.info('Saved {} data'.format(self.name()))

        return True
Beispiel #10
0
def get_reference_paths(objects, without_copy_number=False):
    """
    Returns the reference paths for the given objects
    :param objects: list(str)
    :param without_copy_number: bool
    :return: list(str)
    """

    paths = list()
    for obj in objects:
        if dcc.client().node_is_referenced(obj):
            paths.append(dcc.client().node_reference_path(
                obj, without_copy_number=without_copy_number))

    return list(set(paths))
    def export_data(self, *args, **kwargs):

        filepath = self.format_identifier()
        if not filepath.endswith(TransformsData.EXTENSION):
            filepath = '{}{}'.format(filepath, TransformsData.EXTENSION)

        if not filepath or not os.path.isfile(filepath):
            LOGGER.warning(
                'Impossible to export transforms data to: "{}"'.format(
                    filepath))
            return

        LOGGER.debug('Exporting: {} | {}'.format(filepath, kwargs))

        with open(filepath, 'r') as fh:
            transforms_data = json.load(fh)
        if not transforms_data:
            LOGGER.warning(
                'No transforms data found in file: "{}"'.format(filepath))
            return False

        selected_nodes = dcc.client().selected_nodes(full_path=False)

        saved_nodes = list()
        if not selected_nodes:
            for node_data in transforms_data:
                node_name = node_data.get('name')
                if not node_name:
                    continue
                saved_nodes.append(node_name)
        else:
            for selected_node in selected_nodes:
                if selected_node not in saved_nodes:
                    saved_nodes.append(selected_node)

        valid_nodes = list()
        for selected_node in saved_nodes:
            if not dcc.client().node_exists(selected_node) or not dcc.client(
            ).node_is_transform(selected_node):
                continue
            valid_nodes.append(selected_node)

        if not valid_nodes:
            LOGGER.warning(
                'No transforms to export to file found: "{}"'.format(filepath))
            return False

        return self.save(objects=valid_nodes)
Beispiel #12
0
    def save(self, *args, **kwargs):
        from tpDcc.libs.datalibrary.dccs.maya.core import pose

        filepath = self.format_identifier()
        if not filepath.endswith(PoseData.EXTENSION):
            filepath = '{}{}'.format(filepath, PoseData.EXTENSION)

        if not filepath:
            logger.warning('Impossible to save pose file because save file path not defined!')
            return

        objects = kwargs.get('objects', None)
        if not objects:
            objects = dcc.client().selected_nodes(full_path=True)
        if not objects:
            logger.warning('Select objects to export pose from')
            return False

        logger.debug('Saving {} | {}'.format(filepath, kwargs))

        new_pose = pose.Pose.from_objects(objects=objects)
        try:
            new_pose.save(filepath)
        except IOError:
            logger.error('Pose data not saved to file {}'.format(filepath))
            return False

        logger.debug('Saved {} successfully!'.format(filepath))

        return True
Beispiel #13
0
    def is_locked(self):
        """
        Returns True if the attribute is locked; False otherwise.
        :return: bool
        """

        return dcc.client().is_attribute_locked(self.name, self.attr)
    def load_validator(self, **options):
        namespaces = options.get('namespaces')
        namespace_option = options.get('namespaceOption')

        if namespace_option == 'From file':
            namespaces = list()
            # namespaces = self.metadata().get('namespaces', list())
        elif namespace_option == 'From selection':
            namespaces = dcc.client().list_namespaces_from_selection() or ['']

        field_changed = options.get('fieldChanged')
        if field_changed == 'namespaces':
            options['namespaceOption'] = 'Use custom'
        else:
            options['namespaceOption'] = namespaces

        self._current_load_values = options

        return [{
            "name": "namespaces",
            "value": options.get("namespaces")
        }, {
            "name": "namespaceOption",
            "value": options.get("namespaceOption")
        }]
Beispiel #15
0
    def is_valid(self):
        """
        Returns True if the attribute type is valid; False otherwise.
        :return: bool
        """

        return self.type in dcc.client().get_valid_attribute_types()
    def _add_tag_info_data(project, tag_info, attr_node):
        """
        Internal function that updates the tag info of the Alembic node
        :param project: ArtellaProject
        :param tag_info: dict
        :param attr_node: str
        """

        if not dcc.client().attribute_exists(node=attr_node,
                                             attribute_name='tag_info'):
            dcc.client().add_string_attribute(node=attr_node,
                                              attribute_name='tag_info',
                                              keyable=True)
        dcc.client().set_string_attribute_value(node=attr_node,
                                                attribute_name='tag_info',
                                                attribute_value=str(tag_info))
Beispiel #17
0
    def import_data(self, *args, **kwargs):
        filepath = self.format_identifier()
        if not filepath.endswith(MayaCurveData.EXTENSION):
            filepath = '{}{}'.format(filepath, MayaCurveData.EXTENSION)

        if not filepath:
            LOGGER.warning(
                'Impossible to load Maya Curves from file: "{}"!'.format(
                    filepath))
            return False

        with open(filepath, 'r') as fh:
            curves_data = json.load(fh)
        if not curves_data:
            LOGGER.warning(
                'No curves data found in file: "{}"'.format(filepath))
            return False

        created_curves = list()

        for curve_name, curve_data in curves_data.items():
            new_curve = dcc.client().create_curve(curve_name, **curve_data)
            created_curves.append(new_curve)

        return created_curves
    def load_schema(self):

        return [{
            'name': 'namespaceGroup',
            'title': 'Namespace',
            'type': 'group',
            'order': 10,
        }, {
            'name': 'namespaceOption',
            'title': '',
            'type': 'radio',
            'value': 'From file',
            'items': ['From file', 'From selection', 'Use custom'],
            'persistent': True,
            'persistentKey': 'MayaAsciiData',
        }, {
            'name': 'namespaces',
            'title': '',
            'type': 'tags',
            'value': [],
            'items': dcc.client().list_namespaces(),
            'persistent': True,
            'label': {
                'visible': False
            },
            'persistentKey': 'MayaAsciiData'
        }]
Beispiel #19
0
    def _refresh_frame_ranges(self):
        """
        Internal function that updates the frame ranges values
        """

        frame_range = dcc.client().get_time_slider_range()
        self._start.setValue(int(frame_range[0]))
        self._end.setValue(int(frame_range[1]))
    def _create_alembic_group(cls, group_name):
        """
        Internal function that creates root gruop for Alembic Node
        :return: str
        """

        root = dcc.client().create_empty_group(name=group_name)

        return root
Beispiel #21
0
    def type(self):
        """
        Returns the type of data currently in the attribute
        :return: str
        """

        if self._type is None:
            try:
                if dcc.client().attribute_exists(self.name, self.attr):
                    self._type = dcc.client().get_attribute_type(
                        self.name, self.attr)
                    if self._type:
                        self._type = self._type.encode('ascii')
            except Exception:
                logger.exception('Cannot get attribute type for "{}'.format(
                    self.fullname))

        return self._type
Beispiel #22
0
    def _get_tag_atributes_dict(self, tag_node):
        # We add attributes to the first node in the list
        tag_info = dict()
        if not tag_node:
            return tag_info

        attrs = dcc.client().list_user_attributes(tag_node)
        for attr in attrs:
            try:
                tag_info[attr] = dcc.client().get_attribute_value(
                    node=tag_node, attribute_name=attr)
            except Exception:
                pass
        if not tag_info:
            logger.warning('Node has not valid tag data: {}'.format(tag_node))
            return

        return tag_info
Beispiel #23
0
    def create(cls, tool_id, *args, **kwargs):

        # If a client with given ID is already registered, we return it
        client = dcc.client(tool_id, only_clients=True)
        if client:
            return client

        client = cls(tool_id=tool_id)

        return client
    def _on_browse_alembic(self):
        """
        Internal callback function that is called when Browse Alembic File button is clicked
        """

        shot_name = self._shot_line.text()
        abc_folder = os.path.normpath(
            os.path.join(self._project.get_path(), shot_name)
        ) if shot_name != 'unresolved' else self._project.get_path()

        pattern = 'Alembic Files (*.abc)'
        if dcc.client().is_houdini():
            pattern = '*.abc'
        abc_file = dcc.client().select_file_dialog(
            title='Select Alembic to Import',
            start_directory=abc_folder,
            pattern=pattern)
        if abc_file:
            self._alembic_path_line.setText(abc_file)
Beispiel #25
0
    def value(self):
        if self._value is None or not self._cache:
            try:
                self._value = dcc.client().get_attribute_value(
                    self.name, self.attr)
            except Exception:
                logger.exception('Cannot get attribute value for "{}'.format(
                    self.fullname))

        return self._value
Beispiel #26
0
 def to_short_name(self):
     names = dcc.client().list_nodes(node_name=self.short_name(),
                                     full_path=False) or list()
     if len(names) == 1:
         return Node(names[0])
     elif len(names) > 1:
         raise exceptions.MoreThanOneObjectFoundError(
             'More than one object found {}'.format(str(names)))
     else:
         raise exceptions.NoObjectFoundError('No object found {}'.format(
             self.short_name()))
Beispiel #27
0
 def load(cls):
     # Initialize environment variable that contains paths were curves libs command are located
     # This environment variable is used by the command runner
     dcc_name = dcc.client().get_name()
     commands_path = path_utils.clean_path(
         os.path.join(
             os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
             'dccs', dcc_name, 'commands'))
     if os.path.isdir(commands_path):
         command.CommandRunner().manager().register_path(
             commands_path, 'tpDcc')
Beispiel #28
0
    def import_data(self, **kwargs):

        filepath = self.format_identifier()
        if not filepath.endswith(ControlCVsData.EXTENSION):
            filepath = '{}{}'.format(filepath, ControlCVsData.EXTENSION)

        if not filepath:
            logger.warning(
                'Impossible to load Control CVs from file: "{}"!'.format(
                    filepath))
            return False

        library = self._initialize_library(filepath)

        objects = kwargs.get('objects', None)
        if not objects:
            objects = dcc.client().selected_nodes(full_path=True) or list()

        # We make sure that we store the short name of the controls
        objects = [dcc.node_short_name(obj) for obj in objects]

        updated_controls = list()
        controls = objects or controllib.get_controls()
        for control in controls:
            shapes = dcc.client().get_curve_shapes(control)
            if not shapes:
                continue
            library.set_curve(control, check_curve=True)
            updated_controls.append(control)

        # We force the update of all the curves that are stored in the library and are in the scene
        for curve_data in list(library._library_curves.values()):
            for curve_name in list(curve_data.keys()):
                if curve_name and dcc.node_exists(
                        curve_name) and curve_name not in updated_controls:
                    library.set_curve(curve_name, check_curve=True)
                    updated_controls.append(curve_name)

        logger.info('Imported {} data'.format(self.name()))

        return True
Beispiel #29
0
    def _refresh_alembic_name(self):
        """
        Internal function that updates Alembic name
        """

        if self._name_line.text() != '':
            return

        sel = dcc.client().selected_nodes()
        if sel:
            sel = sel[0]
            is_referenced = dcc.client().node_is_referenced(sel)
            if is_referenced:
                sel_namespace = dcc.client().node_namespace(sel)
                if not sel_namespace or not sel_namespace.startswith(':'):
                    pass
                else:
                    sel_namespace = sel_namespace[1:] + ':'
                    sel = sel.replace(sel_namespace, '')

            self._name_line.setText(dcc.client().node_short_name(sel))
    def run(self, influence_index, skin, weights, file_path):
        influence_name = dcc.client().get_skin_influence_at_index(
            influence_index, skin)
        if not influence_name or not dcc.client().node_exists(influence_name):
            return None, None
        weight_path = fileio.create_file('{}.weights'.format(influence_name),
                                         file_path)
        if not path_utils.is_file(weight_path):
            logger.warning(
                '"{}" is not a valid path to save skin weights into!'.format(
                    file_path))
            return None, None

        writer = fileio.FileWriter(weight_path)
        writer.write_line(weights)

        influence_position = dcc.client().node_world_space_translation(
            influence_name)

        return "{'%s' : {'position' : %s}}" % (
            influence_name, str(influence_position)), weight_path