def _get_flex_icon(arrow, arrow_size=80, bicep_size=110, verbose=0): """Build flex icon using the given arrow. Args: arrow (str): name of arrow emoji arrow_size (int): size of arrow icon bicep_size (int): size of bicep icon verbose (int): print process data """ _path = '{}/psyhive/icons/ik_fk_{}.png'.format(pipe.TMP, arrow) _bicep = icons.EMOJI.find('Flexed Biceps: Light Skin Tone') _arrow = icons.EMOJI.find(arrow) _px = qt.HPixmap(144, 144) _px.fill(qt.HColor(0, 0, 0, 0)) _bicep_px = qt.HPixmap(_bicep).resize(bicep_size, bicep_size) _px.add_overlay(_bicep_px, (0, 0)) _arrow_px = qt.HPixmap(_arrow).resize(arrow_size, arrow_size) _px.add_overlay(_arrow_px, (_px.width(), _px.height()), anchor='BR') _px.save_as(_path, verbose=verbose, force=True) return _path
def add_execute(self, def_, exec_fn, code_fn, help_fn, depth=35, icon=None, label=None, col=None): """Add execute button for the given def. Args: def_ (PyDef): def being added exec_fn (fn): function to call on execute code_fn (fn): function to call on jump to code help_fn (fn): function to call on launch help depth (int): size in pixels of def icon (str): path to icon to display label (str): override label from exec button col (str): colour for button """ # Layout _h_layout = QtWidgets.QHBoxLayout() _h_layout.addStretch(1) _h_layout.setSpacing(3) self.main_layout.addLayout(_h_layout) # Code button _code = qt.HLabel() _code.mousePressEvent = code_fn _code.resize(depth, depth) _code.move(3, 23) _pix = qt.HPixmap(icon) _code.set_pixmap(_pix.resize(depth)) _h_layout.addWidget(_code) # Button _btn = QtWidgets.QPushButton(label) _btn.mousePressEvent = exec_fn _policy = _btn.sizePolicy() _policy.setHorizontalPolicy(QtWidgets.QSizePolicy.Expanding) _policy.setVerticalPolicy(QtWidgets.QSizePolicy.Expanding) _policy.setHorizontalStretch(100) _pal = _btn.palette() _col = QtGui.QColor(col) _pal.setColor(_pal.Button, _col) _text_col = QtGui.QColor('black' if _col.valueF() > 0.55 else 'white') _pal.setColor(_pal.ButtonText, _text_col) _btn.setAutoFillBackground(True) _btn.setPalette(_pal) _btn.setSizePolicy(_policy) _h_layout.addWidget(_btn) # Info button _info = qt.HLabel() _info.resize(depth, depth) _info.move(0, 20) _pix = qt.HPixmap(icons.EMOJI.find('Info')) _info.set_pixmap(_pix.resize(depth)) _h_layout.addWidget(_info) _widgets = [_code, _btn, _info] if self.section: self._apply_section(*_widgets)
def _add_path_menu_items(menu, obj): """Add menu items for the given path object. Args: menu (QMenu): menu to add items to obj (Path): path object """ # Add label if isinstance(obj, Seq): _start, _end = obj.find_range() _join = '...' if obj.has_missing_frames() else '-' _label = 'Seq {:d}{}{:d}'.format(_start, _join, _end) else: _label = 'File' menu.add_label(_label) menu.add_action('Copy path', wrap_fn(copy_text, obj.path), icon=icons.COPY) _browser = wrap_fn(launch_browser, obj.dir) menu.add_action('Show in explorer', _browser, icon=icons.BROWSER) if obj.extn in ['mb', 'ma', 'abc']: # Open scene _open = wrap_fn(host.open_scene, obj.path) menu.add_action('Open scene', _open, icon=icons.OPEN) # Reference scene _namespace = obj.basename if isinstance(obj, tk2.TTWork): _namespace = obj.task elif isinstance(obj, tk2.TTOutputFile): _namespace = obj.output_name _ref = wrap_fn(host.reference_scene, obj.path, namespace=_namespace) _pix = qt.HPixmap(icons.OPEN) _pix.add_overlay(icons.EMOJI.find('Diamond With a Dot'), pos=_pix.size(), resize=80, anchor='BR') menu.add_action('Reference scene', _ref, icon=_pix) # Reference asset if isinstance(obj, tk2.TTOutputFile): _fn = wrap_fn(tk2.reference_publish, obj.path) menu.add_action('Reference publish', _fn, icon=_pix) if isinstance(obj, Seq): _icon = icons.EMOJI.find('Play button') menu.add_action('View images', obj.view, icon=_icon) elif obj.extn == 'mov': _icon = icons.EMOJI.find('Play button') _view = wrap_fn(system, 'djv_view ' + obj.path) menu.add_action('View images', _view, icon=_icon)
def get_pixmap(pix): """Get pixmap from the given data. Args: pix (QPixmap|str): pixmap data or path to pixmap Returns: (HPixmap): pixmap object """ from psyhive import qt, icons if isinstance(pix, qt.HPixmap): return pix elif isinstance(pix, QtGui.QPixmap): return qt.HPixmap(pix) elif isinstance(pix, six.string_types): if os.path.exists(pix): return qt.HPixmap(pix) return qt.HPixmap(icons.EMOJI.find(pix)) elif isinstance(pix, File): return qt.HPixmap(pix.path) raise ValueError(pix)
def update_pixmap(self): """Update pixmap.""" _pix = qt.HPixmap(self.size()) _pix.fill(self.col) _text_col = 'Silver' _pix.add_text( self.text, pos=(30, self.height()/2), anchor='L', col=_text_col, font=self.font) _grid = self.height()/3 if self.collapse: _pts = [(_grid*1.5, _grid*0.5), (_grid*2.5, _grid*1.5), (_grid*1.5, _grid*2.5)] else: _pts = [(_grid, _grid), (_grid*3, _grid), (_grid*2, _grid*2)] _pix.add_polygon(_pts, col=_text_col, outline=None) self.set_pixmap(_pix)
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 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
def _generate_blast_comp_mov(work, ref_imgs=True, comp_imgs=True, margin=20, thumb_aspect=0.75): """Generate blast comp mov file for the given work. Args: work (FrasierWork): work file to comp images for ref_imgs (bool): generate ref jpgs (disable for debugging) comp_imgs (bool): generate comp jpgs (disable for debugging) margin (int): face ref/blast overlay margin in pixels thumb_aspect (float): aspect ration of face ref/blast overlay """ print 'WORK', work.path assert work.blast.exists() assert work.face_blast.exists() assert not work.blast_comp.exists() _start, _end = work.blast.find_range() _dur_secs = 1.0 * (_end - _start + 1) / 30 print ' - BLAST COMP', work.blast_comp.path print ' - RANGE {:d}-{:d} ({:.02f}s)'.format(_start, _end, _dur_secs) # Generate tmp ref jpgs if ref_imgs and work.get_ref_mov(): _mov, _start = work.get_ref_data() _ref_tmp_jpgs = _get_ref_jpgs(mov=_mov, start=_start, secs=_dur_secs) else: _ref_tmp_jpgs = Seq( abs_path('{}/ref_tmp/images.%04d.jpg'.format( tempfile.gettempdir()))) _ref_tmp_jpgs.delete(force=True) print ' - REF JPG', _ref_tmp_jpgs # Build comp jpgs _comp_tmp_jpgs = Seq( abs_path('{}/comp_tmp/images.%04d.jpg'.format(tempfile.gettempdir()))) if comp_imgs: _comp_tmp_jpgs.test_dir() _comp_tmp_jpgs.delete(force=True) for _idx, _src_frame in qt.progress_bar(enumerate( work.blast.get_frames()), 'Comping {:d} images', stack_key='FrasierBlastComp', col='GreenYellow'): _out = qt.HPixmap(work.blast[_src_frame]) _face = qt.HPixmap(work.face_blast[_src_frame]) _thumb_w = (1.0 * _out.width() / 3 - margin * 3) / 2 _thumb_size = qt.get_size(_thumb_w, _thumb_w / thumb_aspect) # Add ref overlay if _ref_tmp_jpgs: _ref = qt.HPixmap(_ref_tmp_jpgs[_idx + 1]) _ref = _ref.resize(_thumb_size) _out.add_overlay(_ref, pos=(_out.width() * 2 / 3 + margin, margin)) # Add face blast overlay _face_size = qt.get_size(_face.height() * thumb_aspect, _face.height()) _face = _face.copy(_face.width() / 2 - _face_size.width() / 2, 0, _face_size.width(), _face_size.height()) _face = _face.resize(_thumb_size) _out.add_overlay(_face, pos=(_out.width() - margin, margin), anchor="TR") _out.save(_comp_tmp_jpgs[_idx + 1]) print ' - WROTE TMP IMAGES', _comp_tmp_jpgs.path print ' - COMP IMAGES {} {}'.format(_comp_tmp_jpgs.find_range(force=True), _comp_tmp_jpgs.path) # Compile out mov work.blast_comp.test_dir() _args = [ '-r', '30', '-f', 'image2', '-i', _comp_tmp_jpgs.path, '-vcodec', 'libx264', '-crf', '25', '-pix_fmt', 'yuv420p', work.blast_comp.path ] print 'launch ffmpeg --', ' '.join(_args) psylaunch.launch_app('ffmpeg', args=_args, wait=True) assert work.blast_comp.exists() print ' - WROTE MOV', work.blast_comp.path