Source code for bgdev.tools.renamer.core

"""Renamer tool for maya.

:created: 06/04/2016
:author: Benoit GIELLY <benoit.gielly@gmail.com>
"""
import logging

from maya import cmds

from .ui import RenamerUi
from .utils import UNDO

LOG = logging.getLogger(__name__)


[docs]def show(parent=None): """Show widget.""" cls = Renamer(parent) cls.show() return cls
class Renamer(RenamerUi): """Core renamer class.""" def __init__(self, parent=None): super(Renamer, self).__init__(parent=parent) self.conflict_detected = False self.setFocus() @staticmethod def get_uuid(node): """Get the given node's uuid.""" return str(cmds.ls(node, uuid=True)[0]) @staticmethod def get_node(uuid): """Get the node name from given uuid.""" return cmds.ls(uuid)[0] def get_selection(self, as_name=False): """Get selection.""" selection = cmds.ls(selection=True) if not selection: raise RuntimeError("Please, select something!") uuids = [self.get_uuid(x) for x in selection] return selection if as_name else uuids def check_conflict(self, name): """Check name conflicts.""" if cmds.ls(name): if not self.conflict_detected: LOG.warning("Careful, name conflict detected: %s", name) self.conflict_detected = True @UNDO def hash_rename(self, text=None, start=None, letters=None): # pylint: disable=too-many-locals """Rename given text by replacing ###. Args: text (str): Text to rename. Must contains at least one "#". start (int): Value to start when replacing "#" with numbers letters (bool): Using letter instead of numbers when True. """ # gather informations from UI (or from kwargs) text = text or self.hash_text.text() start = start or self.hash_spinbox.value() letters = letters or self.hash_letters_radio.isChecked() pad = text.count("#") # get selection and size uuids = self.get_selection() size = len(uuids) # set conflict var and cleanup script edit self.conflict_detected = False # return if not text or selection if not text: LOG.warning("Please, type something in textField") return elif not pad: LOG.warning("Couldn't find any '#'...") return # cleanup new name if " " in text: text = text.replace(" ", "_") # check the padding selection_pad = len(str(size + start - 1)) padding = pad if selection_pad > pad: padding = selection_pad # replace hashes and format name if letters: alpha = start / 27 new_name = text.replace("#" * pad, "{0}") else: new_name = text.replace("#" * pad, "{0:0%dd}" % padding) # temp rename to avoid bad names orig_name_dict = {} for i, uuid in enumerate(uuids): node = self.get_node(uuid) orig_name_dict[i] = node cmds.rename(node, "HASH_rename_%02d_TMP" % i) # rename each elements for i, uuid in enumerate(uuids): name = i + start if letters: # check padding if size + start > 27: letter_a = [chr(65 + j) for j in range(26)][alpha] letter_b = [chr(65 + j) for j in range(26)][name % 26 - 1] if name % 26 == 0 and i > 0: alpha += 1 nice_name = new_name.format(letter_a + letter_b) else: nice_name = new_name.format(chr(64 + name)) else: nice_name = new_name.format(name) # rename command self.check_conflict(nice_name) cmds.rename(self.get_node(uuid), nice_name) @UNDO def search_replace(self, search=None, replace=None, hierarchy=None): """Replace the 'search' text with the 'replace' text. Args: search (str): String to search within text. replace (str): String used to replaced if match is found. hierarchy (bool): Rename every nodes below if True. """ search = search or self.search_text.text() replace = replace or self.replace_text.text() hierarchy = hierarchy or self.hierarchy_radio.isChecked() # get selection and size uuids = self.get_selection() # check hierarchy if hierarchy: nodes = [self.get_node(x) for x in uuids] nodes = cmds.ls(nodes, dagObjects=True) uuids = [self.get_uuid(x) for x in nodes] # set conflict var self.conflict_detected = False # return if not text or selection if not search: LOG.warning("Please, type something in the 'Search' field") return # rename each elements for uuid in uuids: node = self.get_node(uuid) base_name = node.rsplit("|")[-1] new_name = base_name.replace(search, replace) if new_name != base_name: self.check_conflict(new_name) cmds.rename(node, new_name) @UNDO def prefix_suffix(self, prefix=None, suffix=None, mode=None): """Add, remove, or replace prefixes and/or suffixes. Args: prefix (bool): True if you want to update the prefix. suffix (bool): True if you want to update the suffix. mode (str): The mode to use. Must be "add", "replace", or "remove" """ _prefix = None if prefix is True and mode in ["add", "replace"]: _prefix = self.prefix_text.text() elif prefix is not None: _prefix = prefix _suffix = None if suffix is True and mode in ["add", "replace"]: _suffix = self.suffix_text.text() elif suffix is not None: _suffix = suffix # get selection and size uuids = self.get_selection() # set conflict var self.conflict_detected = False # rename each elements for uuid in uuids: node = self.get_node(uuid) base_name = node.rsplit("|")[-1] split_name = base_name.rsplit("_") if _prefix: if mode == "add": new_name = _prefix + "_" + base_name elif mode == "remove": split_name.pop(0) new_name = "_".join(split_name) elif mode == "replace": split_name.pop(0) new_name = "_".join([_prefix] + split_name) elif _suffix: if mode == "add": new_name = base_name + "_" + _suffix elif mode == "remove": split_name.pop(-1) new_name = "_".join(split_name) elif mode == "replace": split_name.pop(-1) new_name = "_".join(split_name + [_suffix]) else: if _prefix is None: LOG.warning("Please, type something in the 'Suffix' field") elif _suffix is None: LOG.warning("Please, type something in the 'Prefix' field") LOG.warning( "Please, type something in the 'Prefix' or 'Suffix' field" ) return cmds.rename(node, new_name) return