def _get_curve_type(self, curve): curve_type_value = None if dcc.attribute_exists(curve, 'curveType'): curve_type_value = dcc.get_attribute_value(curve, 'curveType') elif dcc.attribute_exists(curve, 'type'): curve_type_value = dcc.get_attribute_value(curve, 'type') return curve_type_value
def _update_curve_data(self, transform, curve_data): if dcc.attribute_exists(transform, 'curveType') or dcc.attribute_exists( transform, 'type'): value = dcc.get_attribute_value(transform, 'curveType') if value: curve_data['type'] = value if dcc.attribute_exists(transform, 'type'): value = dcc.get_attribute_value(transform, 'type') if value: curve_data['type'] = value
def exists(self): """ Returns whether or not node with attribute exists in current scene :return: bool """ return dcc.attribute_exists(self.name, self.attr)
def set_curve_type(self, type_name=None, keep_color=True, **kwargs): """ Updates the curves of the control with the given control type :param type_name: str :param keep_color: bool """ if not type_name: if dcc.attribute_exists(self.get(), 'curveType'): type_name = dcc.get_attribute_value(self.get(), 'curveType') shapes = shape_utils.get_shapes(self.get()) color = kwargs.pop('color', None) kwargs['color'] = color or (node_utils.get_rgb_color(shapes[0]) if shapes else 0) super(MayaRigControl, self).set_curve_type(type_name=type_name, keep_color=keep_color, **kwargs) self.update_shapes() string_attr = attr_utils.StringAttribute('curveType') string_attr.create(self._name) string_attr.set_value(type_name) return True
def set_skeleton_generator_attrs(skeleton_generator_node, attrs_dict): for attr_name, attr_value in attrs_dict.items(): if not dcc.attribute_exists(skeleton_generator_node, attr_name): logger.warning( 'Impossible to set {} because that attribute was not found in ' 'HIK Skeleton generator node "{}"'.format(attr_name, skeleton_generator_node)) continue dcc.set_attribute_value(skeleton_generator_node, attr_name, attr_value)
def has_attribute(self, attribute_name): """ Returns whether or not wrapped native DCC object has an attribute with the given name :param attribute_name: str, name of the attribute we are looking for :return: bool, True if the attribute exists in the wrapped native DCC object; False otherwise. """ node_name = node_utils.get_name(self._dcc_native_object, fullname=True) return dcc.attribute_exists(node_name, attribute_name)
def set_local_rotation_axis(data, reply): state = data.get('state', False) sel = dcc.selected_nodes() for obj in sel: if dcc.attribute_exists(obj, 'displayLocalAxis'): dcc.set_attribute_value(obj, 'displayLocalAxis', state) reply['success'] = True
def set_skeleton_generator_defaults(skeleton_generator_node): """ Sets given Skeleton Generator node to its defaults values :param skeleton_generator_node: str """ for attr_name, default_value in HIK_SKELETON_GENERATOR_DEFAULTS.items(): if not dcc.attribute_exists(skeleton_generator_node, attr_name): logger.warning( 'Impossible to reset {} because that attribute was not found in ' 'HIK Skeleton generator node: "{}"'.format(attr_name, skeleton_generator_node)) continue dcc.set_attribute_value(skeleton_generator_node, attr_name, default_value)
def get_render_globals_attribute(attribute_name, default_value=None): """ Internal function that returns value of the given attribute of the render global Maya node :param attribute_name: str, name of the attribute to get :param default_value: object, value that is returned if the attribute does not exists :return: object """ render_globals_node = get_render_globals_node_name() if not dcc.attribute_exists(render_globals_node, attribute_name): LOGGER.warning( 'Attribute "{}" does not exists in RenderGlobals node "{}"!'. format(attribute_name, render_globals_node)) return default_value return dcc.get_attribute_value(render_globals_node, attribute_name)
def get_default_resolution_attribute(attribute_name, default_value=None): """ Internal function that returns value of the given attribute of the default resolution Maya node :param attribute_name: str, name of the attribute to get :param default_value: object, value that is returned if the attribute does not exists :return: object """ default_resolution_node = get_default_resolution_node_name() if not dcc.attribute_exists(default_resolution_node, attribute_name): LOGGER.warning( 'Attribute "{}" does not exists in DefaultResolution node "{}"!'. format(attribute_name, default_resolution_node)) return default_value return dcc.get_attribute_value(default_resolution_node, attribute_name)
def add_control_tracker_attributes( control_name, control_type='circle', translate=(0.0, 0.0, 0.0), rotate=(0.0, 0.0, 0.0), scale=(1.0, 1.0, 1.0), color=None, ): """ Add control tracker attributes :param control_name: str, name of the control lwe want to track :param control_type: str, control type of the control :param translate: tuple(float, float, float), initial translation value :param rotate: tuple(float, float, float), initial rotation value :param scale: tuple(float, float, float), initial scale value :param color: list(float), initial color as linear color """ xform_utils.add_transform_tracker_attributes(control_name, translate=translate, rotate=rotate, scale=scale) if not color: shapes = dcc.list_shapes_of_type(control_name, shape_type='nurbsCurve') if shapes: color = node_utils.get_rgb_color(shapes[0], linear=True) if not color: color = (0.0, 0.0, 0.0) color_utils.add_color_tracker_attributes(control_name, color) for i, attr_name in enumerate( consts.ALL_CONTROL_TYPE_TRACKER_ATTRIBUTE_NAMES): if not dcc.attribute_exists(control_name, attr_name): dcc.add_string_attribute(control_name, attr_name) dcc.set_attribute_value(control_name, consts.TRACKER_CONTROL_TYPE_ATTR_NAME, control_type) dcc.set_attribute_value(control_name, consts.TRACKER_CONTROL_TYPE_DEFAULT_ATTR_NAME, control_type)
def set_render_globals_attribute(attribute_name, attribute_value): """ Internal function that returns value of the given attribute of the render global Maya node :param attribute_name: str, name of the attribute to get :param attribute_value: object, value used to set attribute to :return: object """ render_globals_node = get_render_globals_node_name() if not dcc.attribute_exists(render_globals_node, attribute_name): LOGGER.warning( 'Attribute "{}" does not exists in RenderGlobasls node "{}"!'. format(attribute_name, render_globals_node)) return False try: return dcc.set_attribute_value(render_globals_node, attribute_name, attribute_value) except Exception as exc: LOGGER.error( 'Was impossible to set attribute "{}" in RenderGlobals node "{}" with value "{}" | "{}"' .format(attribute_name, render_globals_node, attribute_value, exc)) return False
def _import_skin_weights(self, data_path, mesh): if not dcc.node_exists(mesh) or not os.path.isdir(data_path): return False try: if not dcc.is_plugin_loaded('ngSkinTools2'): dcc.load_plugin('ngSkinTools2') import ngSkinTools2 from ngSkinTools2 import api as ngst_api except ImportError: logger.warning( 'NgSkinTools 2.0 is not installed. Impossible to import ngSkin data' ) return False ng_skin_data_path = path_utils.join_path(data_path, 'ngdata.json') if not path_utils.is_file(ng_skin_data_path): logger.warning( 'No Ng Skin Data file found: "{}", aborting import skin weights operation ...' .format(ng_skin_data_path)) return False is_valid_mesh = False shape_types = ['mesh', 'nurbsSurface', 'nurbsCurve', 'lattice'] for shape_type in shape_types: if shape_utils.has_shape_of_type(mesh, shape_type): is_valid_mesh = True break if not is_valid_mesh: logger.warning( 'Node "{}" is not a valid mesh node! Currently supported nodes include: {}' .format(mesh, shape_types)) return False logger.info('Importing skin clusters {} --> "{}"'.format( mesh, data_path)) influence_dict = self._get_influences(data_path) if not influence_dict: logger.warning('No influences data found for: {}'.format(mesh)) return False influences = influence_dict.keys() if not influences: logger.warning('No influences found for: "{}"'.format(mesh)) return False influences.sort() logger.debug('Influences found for {}: {}'.format(mesh, influences)) short_name = dcc.node_short_name(mesh) transfer_mesh = None if shape_utils.has_shape_of_type(mesh, 'mesh'): orig_mesh = self._import_mesh_obj(data_path) if orig_mesh: mesh_match = geo_utils.is_mesh_compatible(orig_mesh, mesh) if not mesh_match: transfer_mesh = mesh mesh = orig_mesh else: dcc.delete_node(orig_mesh) # Check if there are duplicated influences and also for the creation of influences that does not currently # in the scene add_joints = list() remove_entries = list() for influence in influences: joints = dcc.list_nodes(influence, full_path=True) if type(joints) == list and len(joints) > 1: add_joints.append(joints[0]) conflicting_count = len(joints) logger.warning( 'Found {} joints with name {}. Using only the first one: {}' .format(conflicting_count, influence, joints[0])) remove_entries.append(influence) influence = joints[0] if not dcc.node_exists(influence): dcc.clear_selection() dcc.create_joint( name=influence, position=influence_dict[influence]['position']) for entry in remove_entries: influences.remove(entry) influences += add_joints settings_data = dict() settings_path = path_utils.join_path(data_path, 'settings.info') if path_utils.is_file(settings_path): lines = fileio.get_file_lines(settings_path) for line in lines: test_line = line.strip() if not test_line: continue line_list = eval(line) attr_name = line_list[0] value = line_list[1] settings_data[attr_name] = value # Create skin cluster and removes if it already exists skin_cluster = deform_utils.find_deformer_by_type(mesh, 'skinCluster') if skin_cluster: dcc.delete_node(skin_cluster) skin_node_name = settings_data.pop('skinNodeName', 'skin_{}'.format(short_name)) skin_cluster = maya.cmds.skinCluster( influences, mesh, tsb=True, n=dcc.find_unique_name(skin_node_name))[0] dcc.set_attribute_value(skin_cluster, 'normalizeWeights', 0) skin_utils.set_skin_weights_to_zero(skin_cluster) # TODO: This Influence mapping configuration should be generated during export and imported here as JSON file # Import ng skin data config = ngst_api.InfluenceMappingConfig() config.use_distance_matching = True config.use_label_matching = True config.use_name_matching = True ngst_api.import_json(mesh, file=ng_skin_data_path, influences_mapping_config=config) maya.cmds.skinCluster(skin_cluster, edit=True, normalizeWeights=1) maya.cmds.skinCluster(skin_cluster, edit=True, forceNormalizeWeights=True) for attr_name, value in settings_data.items(): if attr_name == 'blendWeights': skin_utils.set_skin_blend_weights(skin_cluster, value) else: if dcc.attribute_exists(skin_cluster, attr_name): dcc.set_attribute_value(skin_cluster, attr_name, value) if transfer_mesh: logger.info( 'Import sking weights: mesh topology does not match. Trying to transfer topology ...' ) skin_utils.skin_mesh_from_mesh(mesh, transfer_mesh) dcc.delete_node(mesh) logger.info('Import skinCluster weights: {} from {}'.format( short_name, data_path)) return True
def save(self, *args, **kwargs): """ Saves NG Skin weights file """ dependencies = dict() filepath = self.format_identifier() if not filepath: logger.warning( 'Impossible to save NGSkin Cluster Weights 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( 'Nothing selected to export skin weights of. Please, select a mesh,' ' curve, NURBS surface or lattice with skin weights to export') return False logger.debug('Saving {} | {}'.format(filepath, kwargs)) try: if not dcc.is_plugin_loaded('ngSkinTools2'): dcc.load_plugin('ngSkinTools2') import ngSkinTools2 from ngSkinTools2 import api as ngst_api except ImportError: logger.warning( 'NgSkinTools 2.0 is not installed. Impossible to export ngSkin data' ) return False valid_nodes = list() # Check that all objects that we are going to export have at least one skin cluster node associated # Make sure also that all objects skin output folder have been created obj_dirs = OrderedDict() skin_nodes = OrderedDict() geo_paths = OrderedDict() skin_weights = OrderedDict() for obj in objects: if dcc.client().node_is_a_shape(obj): obj = dcc.client().node_parent(obj, full_path=True) obj_filename = obj if obj.find('|') > -1: obj_filename = obj_filename.replace('|', '.') if obj_filename.startswith('.'): obj_filename = obj_filename[1:] if obj_filename.find(':') > -1: obj_filename = obj_filename.replace(':', '-') skin = dcc.client().find_deformer_by_type(obj, 'skinCluster') if not skin: logger.warning( 'Skip skin weights export for object because no skinCluster found!' .format(obj)) continue valid_nodes.append((obj, obj_filename, skin)) if not valid_nodes: logger.warning( 'Skin exported failed! No objects found with skinClusters applied!' ) return False # Create skin folder only is valid nodes are available file_name = '.{}'.format(os.path.basename(filepath)) file_folder = path_utils.join_path(os.path.dirname(filepath), file_name) if not os.path.isdir(file_folder): skin_folder = folder.create_folder(file_folder, make_unique=True) dependencies[skin_folder] = 'skin_folder' for node_data in valid_nodes: obj, obj_filename, skin = node_data geo_path = path_utils.join_path(file_folder, obj_filename) if path_utils.is_dir(geo_path): folder.delete_folder(obj_filename, file_folder) geo_path = folder.create_folder(obj_filename, file_folder) if not geo_path: logger.error( 'Unable to create skin weights directory: "{}" in "{}"'. format(obj_filename, file_folder)) return False dependencies[geo_path] = 'geo_path' weights = dcc.client().get_skin_weights(skin) obj_dirs[obj] = obj_filename skin_nodes[obj] = skin geo_paths[obj] = geo_path skin_weights[obj] = weights for (obj, skin_node), (_, geo_path), (_, skin_weights) in zip( skin_nodes.items(), geo_paths.items(), skin_weights.items()): logger.info('Exporting weights: {} > {} --> "{}"'.format( obj, skin_node, geo_path)) info_lines = list() info_file = fileio.create_file('influence.info', geo_path) for influence in skin_weights: if influence is None or influence == 'None': continue weight_list = skin_weights[influence] if not weight_list: continue influence_name = skin_utils.get_skin_influence_at_index( influence, skin_node) if not influence_name or not dcc.node_exists(influence_name): continue influence_position = dcc.node_world_space_translation( influence_name) influence_line = "{'%s' : {'position' : %s}}" % ( influence_name, str(influence_position)) info_lines.append(influence_line) writer = fileio.FileWriter(info_file) writer.write(info_lines) settings_file = fileio.create_file('settings.info', geo_path) setting_lines = list() if shape_utils.has_shape_of_type(obj, 'mesh'): self._export_mesh_obj(obj, geo_path) setting_lines.append("['skinNodeName', '{}']".format( dcc.node_short_name(skin_node))) if dcc.attribute_exists(skin_node, 'blendWeights'): blend_weights = skin_utils.get_skin_blend_weights(skin_node) setting_lines.append( "['blendWeights', {}]".format(blend_weights)) if dcc.attribute_exists(skin_node, 'skinningMethod'): skin_method = dcc.get_attribute_value(skin_node, 'skinningMethod') setting_lines.append( "['skinningMethod', {}]".format(skin_method)) write_settings = fileio.FileWriter(settings_file) write_settings.write(setting_lines) ng_skin_file_name = os.path.join(geo_path, 'ngdata.json') ngst_api.export_json(obj, file=ng_skin_file_name) logger.info( 'Skin weights exported successfully: {} > {} --> "{}"'.format( obj, skin_node, geo_path)) data_to_save = OrderedDict() for obj, obj_filename in obj_dirs.items(): data_to_save[obj] = {'enabled': True, 'folder': obj_filename} with open(filepath, 'w') as fh: json.dump(data_to_save, fh) logger.info('Skin weights export operation completed successfully!') return True
def is_control(transform_node, only_tagged=False, **kwargs): """ Returns whether or not given transform is a rig control :param transform_node: str :param only_tagged: bool :return: bool """ maybe_control = False names_to_skip = python.force_list(kwargs.get('names_to_skip', list())) prefixes_to_check = python.force_list( kwargs.get('prefixes_to_check', list())) prefixes_to_skip = python.force_list(kwargs.get('prefixes_to_skip', list())) suffixes_to_check = python.force_list( kwargs.get('suffixes_to_check', list())) suffixes_to_skip = python.force_list(kwargs.get('suffixes_to_skip', list())) attributes_to_check = python.force_list( kwargs.get('attributes_to_check', list())) attributes_to_skip = python.force_list( kwargs.get('attributes_to_skip', list())) names_to_skip.extend(consts.CONTROLS_NAMES_TO_SKIP) prefixes_to_check.extend(consts.CONTROLS_PREFIXES) prefixes_to_skip.extend(consts.CONTROLS_PREFIXES_TO_SKIP) suffixes_to_check.extend(consts.CONTROLS_SUFFIXES) suffixes_to_skip.extend(consts.CONTROLS_SUFFIXES_TO_SKIP) attributes_to_check.extend(consts.CONTROLS_ATTRIBUTES) attributes_to_skip.extend(consts.CONTROLS_ATTRIBUTES_TO_SKIP) names_to_skip = tuple(set(names_to_skip)) prefixes_to_check = tuple(set(prefixes_to_check)) prefixes_to_skip = tuple(set(prefixes_to_skip)) suffixes_to_check = tuple(set(suffixes_to_check)) suffixes_to_skip = tuple(set(suffixes_to_skip)) attributes_to_check = tuple(set(attributes_to_check)) attributes_to_skip = tuple(set(attributes_to_skip)) # TODO: We could use nomenclature to check control validity transform = name_utils.remove_namespace_from_string(transform_node) if only_tagged: if dcc.attribute_exists(transform, 'tag'): value = dcc.get_attribute_value(transform, 'tag') if value: return True return False else: # Check names if transform in names_to_skip: return False # Check prefix and suffix if transform.startswith(prefixes_to_skip) or transform.endswith( suffixes_to_skip): return False if transform.startswith(prefixes_to_check) or transform.endswith( suffixes_to_check): maybe_control = True # Check attributes for attr_to_skip in attributes_to_skip: if dcc.attribute_exists(transform, attr_to_skip): return False for attr_to_check in attributes_to_check: if dcc.attribute_exists(transform, attr_to_check): return True if dcc.attribute_exists(transform, 'tag'): value = dcc.get_attribute_value(transform, 'tag') if value: maybe_control = True if dcc.attribute_exists(transform, 'curveType') or dcc.attribute_exists( transform, 'type'): value = dcc.get_attribute_value(transform, 'curveType') if value: maybe_control = True if dcc.attribute_exists(transform, 'type'): value = dcc.get_attribute_value(transform, 'type') if value: maybe_control = True if maybe_control: if dcc.node_has_shape_of_type( transform, 'nurbsCurve') or dcc.node_has_shape_of_type( transform, 'nurbsSurface'): return True return False