예제 #1
0
    def setIcon(self, column, icon, color=None):
        """
        Overrides base QTreeWidgetItem setIcon function
        :param column: int or str
        :param icon: QIcon
        :param color: QColor or None
        """

        is_app_running = bool(QApplication.instance())
        if not is_app_running:
            return

        if python.is_string(icon):
            if not os.path.exists(icon):
                color = color or QColor(255, 255, 255, 20)
                icon = resources.icon('image', color=color)
            else:
                icon = QIcon(icon)
        if python.is_string(column):
            self._icon[column] = icon
        else:
            self._pixmap[column] = None
            super(ItemView, self).setIcon(column, icon)

        self.update_icon()
예제 #2
0
    def _format_option_value(self, value):
        """
        Internal function used to format object option value
        :param value: variant
        :return: variant
        """

        new_value = value
        option_type = None
        if type(value) == list:
            try:
                option_type = value[1]
            except Exception:
                pass
            value = value[0]
            if option_type == 'dictionary':
                new_value = value[0]
                dict_order = value[1]
                if type(new_value) == list:
                    new_value = new_value[0]
                new_value = python.order_dict_by_list_of_keys(
                    new_value, dict_order)
                return new_value
            elif option_type == 'list' or option_type == 'file' or option_type == 'vector3f':
                return value
            elif option_type == 'combo':
                try:
                    return value[1]
                except Exception:
                    return [-1, '']
            else:
                new_value = self._format_custom_option_value(
                    option_type, value)

        if not option_type == 'script':
            if python.is_string(value):
                eval_value = None
                try:
                    if value:
                        eval_value = eval(value)
                except Exception:
                    pass
                if eval_value:
                    if type(eval_value) in [list, tuple, dict]:
                        new_value = eval_value
                        value = eval_value
            if python.is_string(value):
                if value.find(',') > -1:
                    new_value = value.split(',')

        LOGGER.debug('Formatted value: {}'.format(new_value))

        return new_value
예제 #3
0
def confirm_dialog(title, message, button=None, cancel_button=None, default_button=None, dismiss_string=None):
    """
    Shows DCC confirm dialog
    :param title:
    :param message:
    :param button:
    :param cancel_button:
    :param default_button:
    :param dismiss_string:
    :return:
    """

    from tpDcc.libs.qt.widgets import messagebox
    from Qt.QtWidgets import QDialogButtonBox

    new_buttons = None
    if button:
        if python.is_string(button):
            if button == 'Yes':
                new_buttons = QDialogButtonBox.Yes
            elif button == 'No':
                new_buttons = QDialogButtonBox.No
        elif isinstance(button, (tuple, list)):
            for i, btn in enumerate(button):
                if i == 0:
                    if btn == 'Yes':
                        new_buttons = QDialogButtonBox.Yes
                    elif btn == 'No':
                        new_buttons = QDialogButtonBox.No
                else:
                    if btn == 'Yes':
                        new_buttons = new_buttons | QDialogButtonBox.Yes
                    elif btn == 'No':
                        new_buttons = new_buttons | QDialogButtonBox.No
    if new_buttons:
        buttons = new_buttons
    else:
        buttons = button or QDialogButtonBox.Yes | QDialogButtonBox.No

    if cancel_button:
        if python.is_string(cancel_button):
            if cancel_button == 'No':
                buttons = buttons | QDialogButtonBox.No
            elif cancel_button == 'Cancel':
                buttons = buttons | QDialogButtonBox.Cancel
        else:
            buttons = buttons | QDialogButtonBox.Cancel

    return messagebox.MessageBox.question(None, title=title, text=message, buttons=buttons)
예제 #4
0
def get_skin_cluster(dag_path=None):
    """
    Loops through the DAG hierarchy of the given DAG path finding a skin cluster
    :param dag_path: OpenMaya.MDagPath
    :return: (OpenMayaAnim.MFnSkinCluster, str), Skin cluster object and skin cluster node name
    """

    if not dag_path:
        return None, None

    if not python.is_string(dag_path):
        dag_path = dag_path.fullPathName()

    skin_cluster = maya.cmds.ls(maya.cmds.listHistory(dag_path),
                                type='skinCluster')
    if not skin_cluster:
        return None, None

    skin_name = skin_cluster[0]
    selection_list = api.SelectionList()
    selection_list.create_by_name(skin_name)

    skin_node = selection_list.get_depend_node(0)
    skin_node = maya.api.OpenMayaAnim.MFnSkinCluster(skin_node)

    return skin_node, skin_name
예제 #5
0
def convert_2_hex(color):
    """
    Converts given color to hexadecimal value
    :param color:
    :return: str
    """

    if python.is_string(color):
        if string_is_hex(color):
            return color
        else:
            if color.startswith('rgba'):
                color = [int(value.strip()) for value in color.split('rgba(')[-1].split(')')[0].split(',')]
            elif color.startswith('rgb'):
                color = [int(value.strip()) for value in color.split('rgb(')[-1].split(')')[0].split(',')]

    hex = '#'
    for var in color:
        var = format(var, 'x')
        if len(var) == 1:
            hex += '0' + str(var)
        else:
            hex += str(var)

    if len(hex) == 9:
        hex = '#{}{}'.format(hex[-2:], hex[1:-2])

    return hex
예제 #6
0
    def set_icon(self, icon=None, highlight=False):
        """
        Sets the icon of the window dragger
        :param icon: QIcon
        :param highlight: bool
        """

        icon = icon or self._window.windowIcon()
        if icon and python.is_string(icon):
            icon = resources.icon(icon)
        if not icon or icon.isNull():
            icon = resources.icon('tpDcc')

        size = self.DEFAULT_LOGO_ICON_SIZE

        if highlight:
            self._logo_button.set_icon(
                [icon],
                colors=[None],
                tint_composition=QPainter.CompositionMode_Plus,
                size=size,
                icon_scaling=[1],
                color_offset=0,
                grayscale=True)
        else:
            self._logo_button.set_icon([icon],
                                       colors=None,
                                       size=size,
                                       icon_scaling=[1],
                                       color_offset=0)

        self._logo_button.set_icon_idle(icon)
예제 #7
0
    def get(self, setting_name, default_value=None, setting_group=None, begin_group=None):
        """
        Returns the setting stored with the given name
        :param setting_name: str
        :param default_value: variant
        :param default_value: variant
        :param setting_group: str
        :return:
        """

        if setting_group:
            setting_name = '{}/{}'.format(setting_group, setting_name)

        if begin_group:
            self.beginGroup(begin_group)

        val = self.value(setting_name)
        if not val:
            if begin_group:
                self.endGroup()
            return default_value

        if python.is_string(val) and val.lower() in ['true', 'false']:
            if begin_group:
                self.endGroup()
            return strings.to_boolean(val)

        if begin_group:
            self.endGroup()

        return val
예제 #8
0
def set_slot_model(character_node, slot, model):
    """
    Adds a model to a slot in the characterization map
    :param character_node: FBCharacter
    :param slot: str, full name of character slot
    :param model: str or FBModel, model to add to the slot (can be name or model object)
    :return:
    """

    if python.is_string(model):
        obj = node.get_model_node_by_name(model)
        if not obj:
            logger.warning(
                'Object "{}" does not exist. Unable to add it to the character map "{}" under slot "{}"'
                .format(model, character_node.Name, slot))
            return False
    else:
        obj = model

    character_slot = property.list_properties(pattern=slot)
    if not character_slot:
        logger.warning('Invalid character slot "{}"'.format(slot))
        return False

    # remove all current models from the slot
    character_slot[0].removeAll()

    if obj:
        character_slot[0].append(obj)

    return True
예제 #9
0
def get_mobject(node_name):
    """
    Returns an MObject for the input scene object
    :param node_name: str, Name of the Maya node to get MObject for
    :return:
    """

    check_node(node_name)

    if python.is_string(node_name):
        selection_list = maya.api.OpenMaya.MSelectionList()
        selection_list.add(node_name)
        try:
            mobj = selection_list.getDependNode(0)
        except Exception as exc:
            maya.cmds.warning(
                'Impossible to get MObject from name {} : {}'.format(
                    node_name, exc))
            return

        return mobj

    else:
        try:
            if node_name.__module__.startswith('pymel'):
                return node_name.__apimfn__().object()
        except AttributeError:
            if node_name.__class__.__module__.startswith('pymel'):
                return node_name.__apimfn__().object()

    return node_name
예제 #10
0
    def find_side(cls, objects, regex_sides):
        """
        Returns the naming convention for the given object names
        :param objects: list(str)
        :param regex_sides: str or list(str)
        :return: str
        """

        if python.is_string(regex_sides):
            regex_sides = regex_sides.split('|')

        regex_sides = python.force_list(regex_sides)
        regex_sides = [re.compile(side) for side in regex_sides]

        for obj in objects:
            obj = obj.split('|')[-1].split(':')[-1]
            for regex_side in regex_sides:
                match = regex_side.search(obj)
                if match:
                    side = match.group()
                    if obj.startswith(side):
                        side += '*'
                    if obj.endswith(side):
                        side = '*' + side
                    return side

        return ''
예제 #11
0
    def _import_submodules(pkg):

        found_modules = list()

        if python.is_string(pkg):
            pkg = import_module(pkg)
        if not pkg:
            return found_modules

        pkg_paths = tuple([os.path.normpath(pkg_path) for pkg_path in pkg.__path__ if pkg is not None])
        for pkg_path in list(pkg_paths):
            for loader, name, is_pkg in pkgutil.walk_packages(pkg_paths):
                loader_path = os.path.normpath(loader.path)
                full_name = pkg.__name__ + '.' + name
                if not loader_path.startswith(pkg_path):
                    # print('Trying to import non valid module: {} | {}'.format(full_name, loader_path))
                    continue
                if full_name in skip_modules or full_name.startswith(extra_skip):
                    # print('Skipping .... {}'.format(full_name))
                    continue
                found_modules.append(full_name)
                if recursive and is_pkg:
                    found_modules.extend(_import_submodules(full_name))

        return found_modules
예제 #12
0
def get_skin_weights(skin_cluster, mesh_shape_name):
    """
    Returns the skin weights of the given skin cluster in the given mesh
    :param skin_cluster:
    :param mesh_shape_name:
    :return:
    """

    if python.is_string(skin_cluster):
        skin_cluster, _ = get_skin_cluster(skin_cluster)
    if not skin_cluster:
        return None

    mesh_path, mesh_components = mesh.get_mesh_path_and_components(
        mesh_shape_name)
    if not mesh_path or not mesh_components:
        return None

    influences_array = maya.api.OpenMaya.MIntArray()
    path_array = skin_cluster.influenceObjects()
    influences_count = len(path_array)
    for i in range(influences_count):
        influences_array.append(
            skin_cluster.indexForInfluenceObject(path_array[i]))

    weights = skin_cluster.getWeights(mesh_path, mesh_components,
                                      influences_array)

    return weights
예제 #13
0
def set_skin_weights(skin_cluster, mesh_shape_name, skin_data):
    if python.is_string(skin_cluster):
        skin_cluster, _ = get_skin_cluster(skin_cluster)
    if not skin_cluster:
        return None

    skin_data = str(list(skin_data))

    mesh_path, mesh_components = mesh.get_mesh_path_and_components(
        mesh_shape_name)
    if not mesh_path or not mesh_components:
        return None

    influences_array = maya.api.OpenMaya.MIntArray()
    path_array = skin_cluster.influenceObjects()
    influences_count = len(path_array)
    for i in range(influences_count):
        influences_array.append(
            skin_cluster.indexForInfluenceObject(path_array[i]))

    weights_array = maya.api.OpenMaya.MDoubleArray()
    for i in skin_data[1:-1].split(','):
        weights_array.append(float(i))

    runner = command.CommandRunner()

    runner.run('tpDcc-dccs-maya-commands-setSkinWeights',
               skin_cluster=skin_cluster,
               mesh_path=mesh_path,
               mesh_components=mesh_components,
               influences_array=influences_array,
               weights_array=weights_array)
예제 #14
0
    def _dcc_objects(self,
                     from_selection=False,
                     wildcard='',
                     object_type=None):
        """
        Returns DCC objects from current scene
        :param from_selection: bool, Whether to return only selected DCC objects or all objects in the scene
        :param wildcard: str, filter objects by its name
        :param object_type: int
        :return: list(variant)
        """

        expression_regex = name_utils.wildcard_to_regex(wildcard)

        if from_selection:
            objects = helpers.get_selection_iterator()
        else:
            if python.is_string(object_type):
                objects = maya.cmds.ls(type=object_type, long=True)
            else:
                maya_type = dcc.node_types().get(
                    object_type, (maya.api.OpenMaya.MFn.kDagNode,
                                  maya.api.OpenMaya.MFn.kCharacter))
                objects = list(
                    helpers.get_objects_of_mtype_iterator(maya_type))

        if (object_type is not None and object_type != 0) or wildcard:
            objects_list = list()
            for obj in objects:
                if python.is_string(object_type):
                    type_check = True if not object_type else dcc.node_tpdcc_type(
                        obj, as_string=True) == object_type
                else:
                    type_check = True if not object_type else dcc.node_tpdcc_type(
                        obj) == object_type
                if wildcard:
                    obj_name = node_utils.get_name(mobj=obj, fullname=False)
                    wildcard_check = expression_regex.match(obj_name)
                else:
                    wildcard_check = False
                if type_check and wildcard_check:
                    if python.is_string(obj):
                        obj = node_utils.get_mobject(obj)
                    objects_list.append(obj)
            objects = objects_list

        return objects
예제 #15
0
def generate_color(primary_color, index):
    """
    Generates a new color from the given one and with given index (between 1 and 10)
    https://github.com/phenom-films/dayu_widgets/blob/master/dayu_widgets/utils.py
    :param primary_color: base color (RRGGBB)
    :param index: color step from 1 (light) to 10 (dark)
    :return: out color Color
    """

    hue_step = 2
    saturation_step = 16
    saturation_step2 = 5
    brightness_step1 = 5
    brightness_step2 = 15
    light_color_count = 5
    dark_color_count = 4

    def _get_hue(color, i, is_light):
        h_comp = color.hue()
        if 60 <= h_comp <= 240:
            hue = h_comp - hue_step * i if is_light else h_comp + hue_step * i
        else:
            hue = h_comp + hue_step * i if is_light else h_comp - hue_step * i
        if hue < 0:
            hue += 359
        elif hue >= 359:
            hue -= 359
        return hue / 359.0

    def _get_saturation(color, i, is_light):
        s_comp = color.saturationF() * 100
        if is_light:
            saturation = s_comp - saturation_step * i
        elif i == dark_color_count:
            saturation = s_comp + saturation_step
        else:
            saturation = s_comp + saturation_step2 * i
        saturation = min(100.0, saturation)
        if is_light and i == light_color_count and saturation > 10:
            saturation = 10
        saturation = max(6.0, saturation)
        return round(saturation * 10) / 1000.0

    def _get_value(color, i, is_light):
        v_comp = color.valueF()
        if is_light:
            return min((v_comp * 100 + brightness_step1 * i) / 100, 1.0)
        return max((v_comp * 100 - brightness_step2 * i) / 100, 0.0)

    light = index <= 6
    hsv_color = Color(primary_color) if python.is_string(primary_color) else primary_color
    index = light_color_count + 1 - index if light else index - light_color_count - 1

    return Color.fromHsvF(
        _get_hue(hsv_color, index, light),
        _get_saturation(hsv_color, index, light),
        _get_value(hsv_color, index, light)
    ).name()
예제 #16
0
    def insertSeparator(self, before):
        """
        Extends insertSeparator QMenu function
        :param before: str or QAction
        :return: QAction
        """

        if python.is_string(before):
            before = self.find_action(before)

        return super(Menu, self).insertSeparator(before)
예제 #17
0
def show_message_box(parent,
                     title,
                     text,
                     width=None,
                     height=None,
                     buttons=None,
                     header_pixmap=None,
                     header_color=None,
                     enable_dont_show_checkbox=False,
                     force=False,
                     theme_to_apply=None):
    """
    Opens a question message box with the given options
    :param parent: QWidget
    :param title: str
    :param text: str
    :param width: int
    :param height: int
    :param buttons: list(QMessageBox.StandardButton)
    :param header_pixmap: QPixmap
    :param header_color: str
    :param enable_dont_show_checkbox: bool
    :param force: bool
    :param theme_to_apply: Theme
    :return: MessageBox
    """

    if python.is_string(enable_dont_show_checkbox):
        enable_dont_show_checkbox = enable_dont_show_checkbox == 'true'

    clicked_btn = None

    if qtutils.is_control_modifier() or qtutils.is_alt_modifier():
        force = True

    if force or not enable_dont_show_checkbox or not enable_dont_show_checkbox:
        mb = create_message_box(
            parent=parent,
            title=title,
            text=text,
            width=width,
            height=height,
            buttons=buttons,
            header_pixmap=header_pixmap,
            header_color=header_color,
            enable_dont_show_checkbox=enable_dont_show_checkbox,
            theme_to_apply=theme_to_apply)
        mb.exec_()
        mb.close()

        clicked_btn = mb.clicked_standard_button()
        dont_show_again = mb.is_dont_show_checkbox_checked()

    return clicked_btn
예제 #18
0
def check_node(node_name):
    """
    Returns whether the given node has valid type to work with MaxPlus. If not, raises an Exception
    :param node_name: variant, str || MaxPlus.INode, node we want to check
    """

    if not python.is_string(node_name) and type(
            node_name) is not MaxPlus.INode:
        raise Exception(
            'Given node "{}" has not a valid type: "{}" (str or MaxPlus.INode instead)!'
            .format(node_name, type(node_name)))
예제 #19
0
def set_default_prim(stage, prim):
    """
    Sets given prim as the default prim in the given stage
    :param stage: Usd.Stage
    :param prim: Usd.Prim
    """

    if python.is_string(prim):
        prim = get_prim_at_path(stage, prim)

    return stage.SetDefaultPrim(prim)
예제 #20
0
def get_node_color_data(node):
    """
    Returns the color data in the given Maya node
    :param node: str or OpenMaya.MObject
    :return: dict
    """

    if python.is_string(node):
        node = get_mobject(node)

    return api_node.get_node_color_data(node)
예제 #21
0
def get_pymxs_node(node_name):
    """
    Returns 3ds Max pymxs return based on its name or handle
    :return:
    """

    if python.is_string(node_name):
        return get_node_by_name(node_name)
    elif isinstance(node_name, int):
        return get_node_by_handle(node_name)

    return node_name
예제 #22
0
def set_index_color_as_rgb(node, index, linear=True):
    """
    Sets the override RGB color by the given Maya color index
    :param node: str or list(str)
    :param index: int or str, Maya index color or Maya nice name color
    :param linear: bool, Whether or not the RGB should be set in linear space (matches viewport color)
    """

    if python.is_string(index):
        index = maya_color.convert_maya_color_string_to_index(index)
    rgb_list = maya_color.convert_maya_color_index_to_rgb(index, linear=linear)
    set_rgb_color(node, rgb_list=rgb_list)
예제 #23
0
    def insertMenu(self, before, menu):
        """
        Extends insertMenu QMenu function
        Add supports for finding the before action by the given string
        :param before: str or QAction
        :param menu: QMenu
        :return: QAction
        """

        if python.is_string(before):
            before = self.find_action(before)

        return super(Menu, self).insertMenu(before, menu)
예제 #24
0
    def __getattr__(self, item):
        options = self.options(skip_instance_attrs=True)
        if not options or item not in options:
            return super(Theme, self).__getattribute__(item)

        option_value = options[item]
        if python.is_string(option_value):
            if option_value.startswith('^'):
                return utils.dpi_scale(int(option_value[1:]))
            if color.string_is_hex(option_value):
                return color.hex_to_rgb(option_value)
        else:
            return option_value
예제 #25
0
    def is_iterator(name):
        """
        Returns true if the passed name is an iterator or False otherwise
        :param name: str, name to check
        :return: bool
        """

        if not python.is_string(name):
            return False

        if '#' in name or '@' in name:
            return True
        return False
예제 #26
0
    def set_icon_hover(self, icon=None):
        """
        Sets the icon hover of the window dragger
        :param icon: QIcon
        """

        icon = icon or self._window.windowIcon()
        if icon and python.is_string(icon):
            icon = resources.icon(icon)
        if not icon or icon.isNull():
            icon = resources.icon('tpDcc')

        self._logo_button.set_icon_hover(icon)
예제 #27
0
def get_shape(node, intermediate=False):
    """
     Get the shape node of a transform
     This is useful if you don't want to have to check if a node is a shape node or transform.
     You can pass in a shape node or transform and the function will return the shape node
     If no shape exists, the original name or MObject is returned
     @param node: str | MObject, Name of the node or MObject
     @param intermediate: bool, True to get the intermediate shape
     @return: The name of the shape node
    """

    if type(node) in [list, tuple]:
        node = node[0]

    check_node(node)

    if python.is_string(node):
        if maya.cmds.nodeType(node) == 'transform':
            shapes = maya.cmds.listRelatives(node, shapes=True, path=True)
            if not shapes:
                shapes = []
            for shape in shapes:
                is_intermediate = maya.cmds.getAttr('%s.intermediateObject' %
                                                    shape)
                if intermediate and is_intermediate and maya.cmds.listConnections(
                        shape, source=False):
                    return shape
                elif not intermediate and not is_intermediate:
                    return shape
            if shapes:
                return shapes[0]
        elif maya.cmds.nodeType(node) in [
                'mesh', 'nurbsCurve', 'nurbsSurface'
        ]:
            is_intermediate = maya.cmds.getAttr('%s.intermediateObject' % node)
            if is_intermediate and not intermediate:
                node = maya.cmds.listRelatives(node, parent=True, path=True)[0]
                return get_shape(node)
            else:
                return node
    elif isinstance(node, maya.api.OpenMaya.MObject):
        if not node.apiType() == maya.api.OpenMaya.MFn.kTransform:
            return node

        path = maya.api.OpenMaya.MDagPath.getAPathTo(node)
        num_shapes = path.numberOfShapesDirectlyBelow()
        if num_shapes:
            path.extendToShape(0)
            return path.node()

    return node
예제 #28
0
    def setTextColor(self, text_color):
        """
        Sets the foreground color to the given color
        :param text_color: variant, QColor or str
        """

        if isinstance(text_color, QColor):
            text_color = color.Color.from_color(text_color)
        elif python.is_string(text_color):
            text_color = color.Color.from_string(text_color)
        self._settings['textColor'] = text_color.to_string()
        brush = QBrush()
        brush.setColor(text_color)
        self.setForeground(0, brush)
예제 #29
0
def get_curve_data(curve_shape, space=None):
    """
    Returns curve dat from the given shape node
    :param curve_shape: str, node that represents nurbs curve shape
    :param space:
    :return: dict
    """

    space = space or maya.api.OpenMaya.MSpace.kObject

    if python.is_string(curve_shape):
        curve_shape = node_utils.get_mobject(curve_shape)

    return api_curves.get_curve_data(curve_shape, space)
예제 #30
0
def check_node(node):
    """
    Checks if a node is a valid node and raise and exception if the node is not valid
    :param node: str | MObject, name of the node to be checked or MObject to be checked
     :return: bool, True if the given node is valid
    """

    if python.is_string(node):
        if not maya.cmds.objExists(node):
            return False
    elif isinstance(node, maya.api.OpenMaya.MObject):
        return not node.isNull()

    return True