def get_def_icon(name, set_): """Pick random icon for the given def name. Args: name (str): def name to use as seed set_ (Collection): icon set to use """ if not set_: return None _rand = str_to_seed(name) return _rand.choice(set_.get_paths())
def __init__(self, path, title=None, all_defs=False, base_col=None, mod=None, verbose=0): """Constructor. Args: path (str): path to build interface from title (str): override gui title all_defs (bool): force all defs into interface (by default only defs decorated with the py_gui.install decorator are added) base_col (QColor|str): override base colour for this interface mod (module): py file module (to avoid reimport/calculate) verbose (int): print process data """ # Store kwargs for rebuild self._kwargs = copy.copy(locals()) self._kwargs.pop('self') self.py_file = PyFile(path) self.label_width = 70 self._height = 400 self.all_defs = all_defs self.section = None _mod = mod or self.py_file.get_module() self.mod_name = _mod.__name__ self.title = title or getattr(_mod, 'PYGUI_TITLE', self.mod_name) self.ui_name = self.mod_name.replace(".", "_") + "_ui" self.settings_file = abs_path('{}/Psyop/settings/py_gui/{}.yml'.format( os.environ.get('HOME') or os.environ.get('HOMEDRIVE'), self.mod_name.replace('.', '_'))) # Read attrs from module self.icon_set = getattr(_mod, 'PYGUI_ICON_SET', icons.FRUIT) self._width = getattr(_mod, 'PYGUI_WIDTH', 300) self.base_col = base_col or getattr( _mod, 'PYGUI_COL', str_to_seed(self.mod_name).choice(NICE_COLS)) self.section_col = qt.HColor(self.base_col).blacken(0.5) if self.icon_set: assert isinstance(self.icon_set, Collection) # Build defs into ui self.read_settings_fns = copy.deepcopy(_EMPTY_SETTINGS) self.set_settings_fns = copy.deepcopy(_EMPTY_SETTINGS) _defs_data = self._get_defs_data() self.init_ui() lprint('FOUND {:d} DEFS TO ADD'.format(len(_defs_data)), verbose=verbose) for _last, (_fn, _opts) in last(_defs_data): _def = self.py_file.find_def(_fn.__name__, catch=True) lprint(" - TESTING DEF", _fn, _opts, _def, verbose=verbose) if _def: lprint(" - ADDING DEF", _def, _opts, verbose=verbose) self.add_def(_def, opts=_opts, last_=_last) self.finalise_ui() if os.path.exists(self.settings_file): self.load_settings()
def _add_psyhive_btn(label, icon, cmd, tooltip, add_dots=True, verbose=0): """Add styled button to PsyHive shelf. Args: label (str): button label icon (str): button icon name cmd (fn): button command tooltip (str): button tooltip add_dots (bool): add speckled dots to button background verbose (int): print process data Returns: (str): button element """ global _BUTTON_IDX # Set name/tmp_file lprint('ADDING', label, verbose=verbose) _name = 'PsyHive_' + label for _find, _replace in [('/', ''), (' ', ''), ('\n', '')]: _name = _name.replace(_find, _replace) _tmp_file = '{}/pixmaps/{}.png'.format(tempfile.gettempdir(), _name) _rand = str_to_seed(_name) lprint(' - NAME', _name, verbose=verbose) # Get colour _cols = ['RoyalBlue', 'CornflowerBlue', 'DodgerBlue'] _col_name = _rand.choice(_cols) _col = qt.get_col(_col_name) lprint(' - COL NAME', _col_name, verbose=verbose) # Draw base _pix = qt.HPixmap(32, 32) _pix.fill('Transparent') _col = _col.whiten(0.3) _pix.add_rounded_rect(pos=(0, 0), size=(32, 32), col=_col, outline=None, bevel=4) _col = _col.whiten(0.3) _pix.add_rounded_rect(pos=(2, 2), size=(28, 28), col=_col, outline=None) if add_dots: for _ in range(8): if _rand.random() > 0.3: _pos = qt.get_p([int(33 * _rand.random()) for _ in range(2)]) _rad = ValueRange('2-6').rand(random_=_rand) _alpha = ValueRange('80-100').rand(random_=_rand) _col = QtGui.QColor(255, 255, 255, _alpha) _pix.add_dot(pos=_pos, radius=_rad, col=_col) # Add icon if icon: _pix.add_overlay(icon, pos=qt.get_p(15, 2), resize=12, anchor='T') # Add text _lines = label.split('\n') for _jdx, _line in enumerate(_lines): _r_jdx = len(_lines) - _jdx - 1 _pix.add_text(_line, pos=qt.get_p(16, 31 - _r_jdx * 7), font=_get_btn_font(), anchor='B') _pix.save_as(_tmp_file, force=True) lprint(' - TMP FILE', _tmp_file, verbose=verbose) _btn = ui.add_shelf_button(_name, image=_tmp_file, command=cmd, parent='PsyHive', annotation=tooltip) lprint(verbose=verbose) _BUTTON_IDX += 1 return _btn
def _ph_add_show_toolkits(parent, verbose=0): """Add show toolkits options. Args: parent (str): parent menu verbose (int): print process data """ _shows = cmds.menuItem(label='Shows', parent=parent, subMenu=True, image=icons.EMOJI.find('Top Hat', catch=True)) _shows_dir = File(shows.__file__).parent() # Get list of toolkits _toolkits = [] for _py in _shows_dir.find(extn='py', depth=1, type_='f'): _file = PyFile(_py) if _file.basename.startswith('_'): continue try: _mod = _file.get_module(catch=True) except ImportError: continue if not _mod: continue _toolkits.append((_file, _file.basename)) for _dir in _shows_dir.find(depth=1, type_='d'): _toolkit = PyFile('{}/toolkit.py'.format(_dir)) if Dir(_dir).filename.startswith('_'): continue lprint(' - ADDING DIR', _dir, verbose=verbose) try: _mod = _toolkit.get_module(catch=True) except ImportError: continue if not _mod: continue _name = _toolkit.parent().filename _toolkits.append((_toolkit, _name)) _toolkits.sort(key=operator.itemgetter(1)) lprint('FOUND TOOLKITS', verbose=verbose) # Build show toolkit buttons for _toolkit, _name in _toolkits: lprint(' - ADDING TOOLKIT', _name, verbose=verbose) _mod = _toolkit.get_module() _rand = str_to_seed(_name) _icon = getattr(_mod, 'ICON', _rand.choice(icons.ANIMALS)) _label = getattr(_mod, 'LABEL', to_nice(_name)) _title = '{} tools'.format(_label) _cmd = '\n'.join([ 'import {py_gui} as py_gui', '_path = "{file}"', '_title = "{title}"', 'py_gui.MayaPyGui(_path, title=_title, all_defs=True)', ]).format(py_gui=py_gui.__name__, file=_toolkit.path, title=_title) cmds.menuItem(command=_cmd, image=_icon, label=_label, parent=_shows) _btn_label = getattr(_mod, 'BUTTON_LABEL', _label) _btn = _add_psyhive_btn(label=_btn_label, cmd=None, icon=_icon, tooltip=_title) py_gui.MayaPyShelfButton(mod=_mod, parent='PsyHive', image=_icon, label=_label, button=_btn)
def __init__(self, items, title='Processing {:d} item{}', col=None, show=True, pos=None, parent=None, stack_key='progress', plural=None): """Constructor. Args: items (list): list of items to iterate title (str): title for interface col (str): progress bar colour show (bool): show the dialog pos (QPoint): override progress bar position (applied to centre) parent (QDialog): parent dialog stack_key (str): override identifier for this dialog - if an existing progress bar has the same stack key then this will replace it plural (str): override plural str (eg. 'es' for 'passes') """ global _PROGRESS_BARS from psyhive import host, qt # Avoid batch mode seg fault if host.batch_mode(): raise RuntimeError("Cannot create progress bar in batch mode") _items = items if isinstance(_items, (enumerate, collections.Iterable)): _items = list(_items) self.stack_key = stack_key self.items = _items self.counter = 0 self.last_update = time.time() self.durs = [] self.info = '' _parent = parent or host.get_main_window_ptr() _args = [_parent] if _parent else [] super(ProgressBar, self).__init__(*_args) _title = title.format(len(self.items), get_plural(self.items, plural=plural)) self.setWindowTitle(_title) self.resize(408, 54) if pos: _pos = pos - get_p(self.size()) / 2 else: _pos = _get_next_pos(stack_key=stack_key) if _pos: self.move(_pos) _col = col if not _col: _random = str_to_seed(title) _col = _random.choice(qt.NICE_COLS) # Build ui self.grid_lyt = QtWidgets.QGridLayout(self) self.progress_bar = HProgressBar(self) _size_policy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) _size_policy.setHorizontalStretch(0) _size_policy.setVerticalStretch(0) _size_policy.setHeightForWidth( self.progress_bar.sizePolicy().hasHeightForWidth()) self.progress_bar.setSizePolicy(_size_policy) self.progress_bar.setProperty("value", 0) self.grid_lyt.addWidget(self.progress_bar, 0, 0, 1, 1) self.progress_bar.set_col(_col) self._hidden = not show if show: self.show() _PROGRESS_BARS.append(self)
def get_work_icon(work, mode='full', size=50, overlay_size=25, force=False, verbose=0): """Get icon for the given work file. Args: work (CTTWork): work file mode (str): type of icon to build (full/basic) size (int): icon size overlay_size (int): overlay size force (bool): force redraw icon verbose (int): print process data Returns: (str|QPixmap): work file icon """ # Get base icon _uid = work.task lprint('UID', _uid, verbose=verbose) if _uid == 'test': _icon = icons.EMOJI.find('Alembic') else: _random = str_to_seed(_uid) _icon = _random.choice(icons.FRUIT.get_paths()) lprint('ICON', _icon, verbose=verbose) if mode == 'basic': return _icon _random = str_to_seed(work.path) _rotate = _random.random() * 360 _pix = qt.HPixmap(size, size) _pix.fill(qt.HColor(0, 0, 0, 0)) # Add rotated icon as overlay _size_fr = 1 / (2**0.5) _size = _pix.size() * _size_fr _over = qt.HPixmap(_icon).resize(_size) _tfm = QtGui.QTransform() _tfm.rotate(_rotate) _over = _over.transformed(_tfm) _offs = (_pix.size() - _over.size()) / 2 _pix.add_overlay(_over, _offs) # Add overlays _overlays = [] if work.find_seqs(): _over = qt.HPixmap( icons.EMOJI.find('Play button')).resize(overlay_size) _overlays.append(_over) if work.find_publishes(): _over = qt.HPixmap( icons.EMOJI.find('Funeral Urn')).resize(overlay_size) _overlays.append(_over) if work.find_caches(): _over = qt.HPixmap(icons.EMOJI.find('Money bag')).resize(overlay_size) _overlays.append(_over) for _idx, _over in enumerate(_overlays): _offs = (13 * _idx, _pix.height() - 0 * _idx) lprint(' - ADD OVERLAY', _idx, _offs, verbose=verbose) _pix.add_overlay(_over, _offs, anchor='BL') return _pix