示例#1
0
    def _redraw__Desc(self, verbose=0):

        dprint('REDRAW DESC', verbose=verbose)

        _type = get_single(self.ui.Type.selected_text(), catch=True)
        _char = get_single(self.ui.Character.selected_text(), catch=True)
        _name = get_single(self.ui.Name.selected_text(), catch=True)
        _descs = sorted(
            set([
                _work.desc for _work in self.o_works if _work.type_ == _type
                and _work.asset == _char and _work.name == _name
            ]))

        # Populate list
        self.ui.Desc.blockSignals(True)
        self.ui.Desc.clear()
        for _desc in _descs:
            self.ui.Desc.addItem(_desc)
        if _descs:
            self.ui.Desc.setCurrentRow(0)
        self.ui.Desc.blockSignals(False)

        self.ui.DescLabel.setText({'Name': 'Desc'}.get(_type, 'Desc'))

        self._redraw__Iteration()
示例#2
0
def read_shd(shp, allow_base=False, verbose=1):
    """Read shader from the given geo shape node.

    Args:
        shp (str): shape node to read
        allow_base (bool): return BaseShader objects for unhandled shaders
        verbose (int): print process data

    Returns:
        (_BaseShader): shader object
    """
    _shp = shp
    if cmds.objectType(_shp) == 'transform':
        _shp = get_shp(_shp)
    _se = get_single(cmds.listConnections(_shp,
                                          source=False,
                                          type='shadingEngine'),
                     catch=True)
    if not _se:
        lprint('No shading engine found:', _shp, verbose=verbose)
        return None
    lprint('Shading engine:', _se, verbose=verbose > 1)
    _shd = get_single(cmds.listConnections(_se + '.surfaceShader',
                                           destination=False),
                      catch=True)
    if not _shd:
        return None
    _shd = find_shd(_shd, allow_base=allow_base)
    _shd.set_se(hom.HFnDependencyNode(_se))
    return _shd
示例#3
0
    def _callback__PlaySeq(self):

        _work = get_single(self.ui.Work.selected_data(), catch=True)
        if not _work:
            return
        _c_work = self.c_works[_work]
        _viewables = [
            _out for _out in _c_work.find_outputs()
            if _out.format in ['mov', 'jpg']
        ]

        if len(_viewables) == 1:
            _viewable = get_single(_viewables)
            _seq = get_single(_viewable.find_files())
            _seq.view()
            return

        _menu = qt.HMenu(self.ui.PlaySeq)
        for _viewable in _viewables:
            _seq = get_single(_viewable.find_files())
            _menu.add_action('View ' + _viewable.output_type,
                             func=_seq.view,
                             icon=icons.EMOJI.find('Blue Circle'))
        _pos = qt.get_p(self.ui.PlaySeq.size() / 2)
        _menu.exec_(self.ui.PlaySeq.mapToGlobal(_pos))
示例#4
0
    def _redraw__Step(self):

        # Get step root
        _mode = self.ui.RootTabs.cur_text()
        if _mode == 'Assets':
            _root = get_single(self.ui.Asset.selected_data(), catch=True)
        elif _mode == 'Shots':
            _root = get_single(self.ui.Shot.selected_data(), catch=True)
        else:
            raise ValueError(_mode)
        _steps = _root.find_step_roots() if _root else []

        # Populate list
        _cur = self.ui.Step.selected_text(single=True)
        self.ui.Step.blockSignals(True)
        self.ui.Step.clear()
        _sel = _cur if _cur in _steps else None
        for _step in _steps:
            _work_area = _step.get_work_area(dcc=hb_utils.cur_dcc())
            _col = 'grey'
            if os.path.exists(_work_area.yaml):
                _col = 'white'
                _sel = _sel or _step
            _item = qt.HListWidgetItem(_step.step, data=_step)
            _item.set_col(_col)
            self.ui.Step.addItem(_item)
        if _sel:
            self.ui.Step.select_data([_sel])
        else:
            self.ui.Step.setCurrentRow(0)
        self.ui.Step.blockSignals(False)

        self._callback__Step()
示例#5
0
    def _redraw__Work(self, verbose=0):

        dprint('POPULATE WORK', verbose=verbose)

        _type = get_single(self.ui.Type.selected_text(), catch=True)
        _char = get_single(self.ui.Character.selected_data(), catch=True)
        _name = get_single(self.ui.Name.selected_text(), catch=True)
        _desc = get_single(self.ui.Desc.selected_text(), catch=True)
        _iter = get_single(self.ui.Iteration.selected_data(), catch=True)
        _works = [
            _work for _work in self.o_works
            if _work.type_ == _type and _work.get_root() == _char and
            _work.iter == _iter and _work.name == _name and _work.desc == _desc
        ]

        # Populate list
        self.ui.Work.setSpacing(2)
        self.ui.Work.blockSignals(True)
        self.ui.Work.clear()
        for _o_work in reversed(_works):
            _c_work = self.c_works[_o_work]
            _item = hive_bro.create_work_item(_c_work)
            _item.set_data(_o_work)
            self.ui.Work.addItem(_item)
        if _works:
            self.ui.Work.setCurrentRow(0)
        self.ui.Work.blockSignals(False)

        self._callback__Work()
示例#6
0
    def _redraw__Name(self, verbose=0):

        dprint('REDRAW NAME', verbose=verbose)

        # Get names
        _type = get_single(self.ui.Type.selected_text(), catch=True)
        _char = get_single(self.ui.Character.selected_data(), catch=True)
        _names = sorted(
            set([
                _work.name for _work in self.o_works
                if _work.type_ == _type and _work.get_root() == _char
            ]))

        # Populate list
        self.ui.Name.blockSignals(True)
        self.ui.Name.clear()
        for _item in _names:
            self.ui.Name.addItem(_item)
        if _names:
            self.ui.Name.select_text(_names[0])
        self.ui.Name.blockSignals(False)

        self.ui.NameLabel.setText(_type)

        self._redraw__Desc()
示例#7
0
    def _redraw__Iteration(self):

        # Get iterations
        _type = get_single(self.ui.Type.selected_text(), catch=True)
        _char = get_single(self.ui.Character.selected_data(), catch=True)
        _name = get_single(self.ui.Name.selected_text(), catch=True)
        _desc = get_single(self.ui.Desc.selected_text(), catch=True)
        _iters = sorted(
            set([
                _work.iter for _work in self.o_works
                if _work.type_ == _type and _work.get_root() == _char
                and _work.name == _name and _work.desc == _desc
            ]))

        # Populate list
        self.ui.Iteration.blockSignals(True)
        self.ui.Iteration.clear()
        for _iter in _iters:
            _item = qt.HListWidgetItem('{:02d}'.format(_iter), data=_iter)
            self.ui.Iteration.addItem(_item)
        if _iters:
            self.ui.Iteration.setCurrentRow(0)
        self.ui.Iteration.blockSignals(False)

        self._redraw__Work()
示例#8
0
    def test_find(self):

        _test_dir = '{}/psyhive/testing/blah'.format(tempfile.gettempdir())
        _test_file = abs_path('{}/test.txt'.format(_test_dir))
        if os.path.exists(_test_dir):
            shutil.rmtree(_test_dir)
        touch(_test_file)
        assert get_single(find(_test_dir)) == _test_file
        assert get_single(find(_test_dir, full_path=False)) == 'test.txt'
示例#9
0
    def get_metadata(self, data=None, catch=True, verbose=0):
        """Get metadata for this work file.

        This can be expensive - it should read at work area level and
        then passed using the data arg.

        Args:
            data (dict): override data dict rather than read from disk
            catch (bool): no error on work file missing from metadata
            verbose (int): print process data
        """
        dprint('Reading metadata', self.path, verbose=verbose)
        _work_area = self.get_work_area()
        if data:
            _data = data
        else:
            dprint('Reading work area metadata (slow)',
                   _work_area.path,
                   verbose=verbose)
            _data = _work_area.get_metadata()
        if not _data:
            return {}

        # Apply task filter
        _task_files = [
            _data for _data in _data['workfiles']
            if _data['name'] == self.task.lower()
        ]
        if not _task_files:
            if catch:
                return {}
            raise ValueError('Missing task {} from metadata {}'.format(
                self.task.lower(), self.path))
        _work_files = get_single(_task_files)
        lprint("MATCHED {:d} WORK FILES IN TASK {}".format(
            len(_work_files), self.task.lower()),
               verbose=verbose > 1)
        lprint(pprint.pformat(_work_files), verbose=verbose > 1)

        # Find this version
        if 'versions' not in _work_files:
            raise ValueError("Missing versions key in metadata " +
                             _work_area.path)
        _versions = [
            _data for _data in _work_files['versions']
            if _data['version'] == self.version
        ]
        if not _versions and catch:
            return {}
        _version = get_single(_versions,
                              fail_message='Missing version in metadata ' +
                              self.path)

        return _version
示例#10
0
    def get_sg_data(self, verbose=0):
        """Find shotgun data for this publish.

        Args:
            verbose (int): print process data

        Returns:
            (dict): shoutgun data
        """
        from psyhive import tk2
        _proj = tk2.get_project_sg_data(pipe.Project(self.path))
        _root = tk2.TTRoot(self.path)
        _task = tk2.get_sg_data(
            'Task', content=self.task, project=_proj,
            entity=_root.get_sg_data())
        _data = tk2.get_sg_data(
            'PublishedFile', version_number=self.ver_n, sg_format=self.extn,
            project=_proj, task=_task, limit=2,
            code=self.filename.replace('%04d', '####'),
            fields=['task', 'code', 'short_name'])
        if verbose:
            pprint.pprint(_data)
        if len(_data) > 1:
            raise RuntimeError(self.path)
        return get_single(_data, catch=True)
示例#11
0
def find_ref(namespace=None,
             filter_=None,
             catch=False,
             class_=None,
             prefix=None,
             extn=None,
             verbose=0):
    """Find reference with given namespace.

    Args:
        namespace (str): namespace to match
        filter_ (str): apply filter to names list
        catch (bool): no error on fail to find matching ref
        class_ (FileRef): override FileRef class
        prefix (str): match reference by prefix (prefix references don't
            use namespaces)
        extn (str): filter by extension
        verbose (int): print process data

    Returns:
        (FileRef): matching ref
    """
    _refs = find_refs(namespace=namespace,
                      filter_=filter_,
                      class_=class_,
                      prefix=prefix,
                      extn=extn)
    lprint('Found {:d} refs'.format(len(_refs)), _refs, verbose=verbose)
    return get_single(_refs, catch=catch, name='ref')
示例#12
0
def _add_work_ctx_output_files(work, menu):
    """Add work file output context options.

    Args:
        work (TTWork): work file
        menu (QMenu): menu to add to
    """
    _files = work.find_output_files()
    menu.addSeparator()

    # No outputs found
    if not _files:
        menu.add_label("No outputs found")
        return

    menu.add_label("Outputs")

    # Show individual files if small number
    if len(_files) < 10:
        for _file in _files:
            _add_work_ctx_output_file(menu=menu, file_=_file)
        return

    # Organise into names
    _names = sorted(set([_file.output_name for _file in _files]))
    for _name in _names:
        _name_files = [_file for _file in _files if _file.output_name == _name]
        if len(_name_files) == 1:
            _add_work_ctx_output_file(menu=menu, file_=get_single(_name_files))
        else:
            _add_work_ctx_output_name(menu=menu, name=_name, files=_name_files)
示例#13
0
    def get_default(self):
        """Get default value of this plug.

        Returns:
            (any): default value
        """
        return get_single(self.attribute_query(listDefault=True), catch=True)
示例#14
0
    def __init__(self, node, verbose=0):
        """Constructor.

        Args:
            node (str): tranform node name
            verbose (int): print process data
        """
        from maya_psyhive import open_maya as hom
        super(BaseTransform, self).__init__(node)

        # Get shape (if any)
        _shps = cmds.listRelatives(
            self.node, shapes=True, path=True, noIntermediate=True) or []
        _shp = get_single([str(_shp) for _shp in _shps], catch=True)
        self.shp = hom.HFnDependencyNode(_shp) if _shp else None
        lprint('SHAPE', self.shp, _shps, verbose=verbose)

        # Create plugs
        for _param in 'trs':
            for _axis in 'xyz':
                _attr = _param + _axis
                _plug = HPlug(self.node + '.' + _attr)
                setattr(self, _attr, _plug)
        self.translate = HPlug(self.node + '.translate')
        self.rotate = HPlug(self.node + '.rotate')
        self.scale = HPlug(self.node + '.scale')
        self.visibility = HPlug(self.node + '.visibility')
示例#15
0
def _script_editor_find_file_menu(verbose=0):
    """Find script editor file menu.

    Args:
        verbose (int): print process data

    Returns:
        (str): script editor file menu name
    """

    # Find script editor file menu
    _menus = []
    for _menu in cmds.lsUI(menus=True):
        if cmds.menu(_menu, query=True, label=True) != 'File':
            continue
        lprint('TESTING', _menu, verbose=verbose)
        _post_cmd = cmds.menu(_menu, query=True, postMenuCommand=True)
        lprint(' - POST CMD', _post_cmd, verbose=verbose)
        if not _post_cmd or 'ScriptEditor' not in _post_cmd:
            continue
        lprint(' - MATCHED', verbose=verbose)
        _menus.append(_menu)

    _menu = get_single(_menus, catch=True)
    if not _menu:
        print ' - PSYHIVE FAILED TO FIND SCRIPT EDITOR MENU'
        return None

    # Init menu if it has no children
    if not cmds.menu(_menu, query=True, itemArray=True):
        _init_cmd = cmds.menu(_menu, query=True, postMenuCommand=True)
        mel.eval(_init_cmd)
        assert cmds.menu(_menu, query=True, itemArray=True)

    return _menu
示例#16
0
def map_tag_to_shot(tag):
    """Map the given tag to a shot in the current project.

    Args:
        tag (str): tag to match

    Returns:
        (TTShot): shot root
    """

    # Try existing shot on disk
    _shot = tk2.find_shot(tag, catch=True, mode='sg')
    if _shot:
        return _shot

    # Try shot from sg
    _data = get_single(tk2.get_sg_data('Shot',
                                       code=tag,
                                       fields=['sg_sequence']),
                       catch=True)
    if _data:
        _path = '{}/sequences/{}/{}'.format(pipe.cur_project().path,
                                            _data['sg_sequence']['name'], tag)
        return tk2.TTShot(_path)

    return None
示例#17
0
def _script_editor_save_to_project(*xargs):
    """Execute save to project."""

    del xargs  # Maya callbacks require args

    # Get current editor
    _cur_editor = [
        _ui for _ui in cmds.lsUI(dumpWidgets=True, long=False)
        if cmds.cmdScrollFieldExecuter(_ui, query=True, exists=True)
        and not cmds.cmdScrollFieldExecuter(_ui, query=True, isObscured=True)
    ][0]

    # Get file path
    _src_type = cmds.cmdScrollFieldExecuter(_cur_editor,
                                            query=True,
                                            sourceType=True)
    _extn = {'mel': 'mel', 'python': 'py'}[_src_type]
    _text = cmds.cmdScrollFieldExecuter(_cur_editor, query=True, text=True)
    _file = get_single(
        cmds.fileDialog2(
            fileMode=0,  # Single file doesn't need to exist
            caption="Save Script",
            okCaption='Save',
            startingDirectory=pipe.cur_project().maya_scripts_path,
            fileFilter='{} Files (*.{})'.format(_extn.upper(), _extn)),
        catch=True)

    # Write file to disk
    if _file:
        write_file(file_=_file, text=_text)
示例#18
0
def _add_elements_to_psyop_menu(verbose=0):
    """Add elements to psyop menu.

    Args:
        verbose (int): print process data
    """
    dprint('ADDING {:d} TO PSYOP MENU'.format(len(_BUTTONS)), verbose=verbose)
    _menu = ui.obtain_menu('Psyop')

    _children = cmds.menu(_menu, query=True, itemArray=True) or []
    _anim = get_single([
        _child for _child in _children
        if cmds.menuItem(_child, query=True, label=True) == 'Animation'
    ],
                       catch=True)

    if _anim:
        for _name, _data in _BUTTONS.items():
            _mi_name = 'HIVE_' + _name
            if cmds.menuItem(_mi_name, query=True, exists=True):
                cmds.deleteUI(_mi_name)
            lprint(' - ADDING', _mi_name, verbose=verbose)
            cmds.menuItem(_mi_name,
                          parent=_anim,
                          command=_data['cmd'],
                          image=_data['image'],
                          label=_data['label'])
示例#19
0
def _clean_unused_uv_sets(mesh, verbose=0):
    """Clean unused uv sets from the given mesh.

    Args:
        mesh (HFnMesh): mesh to clean
        verbose (int): print process data
    """
    _all = cmds.polyUVSet(mesh, query=True, allUVSets=True) or []

    if len(_all) <= 1:
        lprint('NO UV CLEAN REQUIRED', verbose=verbose)
        return

    _cur = get_single(cmds.polyUVSet(mesh, query=True, currentUVSet=True))
    lprint('   - CLEANING UVS {} cur="{}" all={}'.format(mesh, _cur, _all),
           verbose=verbose)

    # Reorder if current is not default set (can't delete first set)
    if _all.index(_cur):
        lprint('     - SWITCHING SETS', _cur, _all[0], verbose=verbose)
        cmds.polyUVSet(mesh, reorder=True, uvSet=_cur, newUVSet=_all[0])

    for _idx, _set in enumerate(_all):
        if _set != _cur:
            lprint('     - DELETE SET', _idx, _set, verbose=verbose)
            cmds.polyUVSet(mesh, delete=True, uvSet=_set)
示例#20
0
def build_loc(name='locator', scale=None, col=None):
    """Build locator at this array's position.

    Args:
        name (str): name for locator
        scale (str): locator scale
        col (str): locator colour

    Returns:
        (str): locator name
    """
    from maya_psyhive import open_maya as hom
    from maya_psyhive.utils import set_col

    _loc = cmds.spaceLocator(name=get_unique(name))[0]

    # Apply scale
    _scale = scale or hom.LOC_SCALE
    if _scale != 1.0:
        _shp = get_single(cmds.listRelatives(_loc, shapes=True))
        cmds.setAttr(_shp + '.localScale', _scale, _scale, _scale)

    # Apply colour
    _col = col or hom.LOC_COL
    set_col(_loc, _col)

    return hom.HFnTransform(_loc)
示例#21
0
    def find_output_file(self,
                         format_=None,
                         extn=None,
                         version=None,
                         task=None,
                         output_type=None,
                         catch=False,
                         verbose=0):
        """Find a specific output file in this step root.

        Args:
            format_ (str): match format (eg. maya)
            extn (str): match extension (eg. mb)
            version (str): match version (eg. v003 or latest)
            task (str): match task
            output_type (str): match output type
            catch (bool): no error on fail
            verbose (int): print process data

        Returns:
            (TTOutputFileBase): matching output file
        """
        _files = self.find_output_files(format_=format_,
                                        extn=extn,
                                        version=version,
                                        task=task,
                                        output_type=output_type)
        return get_single(_files, catch=catch, verbose=verbose)
示例#22
0
def export_img_plane(camera, abc):
    """Export image plane preset data for the given camera/abc.

    Args:
        camera (str): camera shape node name
        abc (str): path to output abc
    """
    _cam = hom.HFnCamera(get_parent(str(camera)))
    lprint(' - CAM', _cam)

    # Read image plane
    _img_plane = get_single(_cam.shp.list_connections(type='imagePlane'),
                            catch=True)
    if not _img_plane:
        lprint(' - NO IMAGE PLANE FOUND')
        return
    _img_plane = hom.HFnTransform(_img_plane.split('->')[-1])

    # Export preset for each shape
    for _shp in [_cam.shp, _img_plane.shp]:
        _preset = '{}/{}.preset'.format(os.path.dirname(abc),
                                        _shp.object_type())
        lprint(' - SAVING', _preset)
        try:
            _shp.save_preset(_preset)
        except RuntimeError:
            lprint(' - FAILED TO SAVE')
示例#23
0
def _add_displacement_override(shd, aip, verbose=0):
    """Add displacement override if applicable.

    Args:
        shd (HFnDepedencyNode): shader node
        aip (HFnDepedencyNode): aiSetParameter node
        verbose (int): print process data
    """
    _shd = tex.find_shd(str(shd), catch=True)
    if not _shd:
        return
    lprint(' - SHD', _shd, verbose=verbose)
    if not _shd.get_se():
        return

    lprint(' - SE', _shd.get_se(), verbose=verbose)
    _displ = get_single(
        _shd.get_se().plug('displacementShader').list_connections(),
        catch=True)
    if not _displ:
        return

    lprint(' - DISPL', _displ, verbose=verbose)
    _val = "disp_map = '{}'".format(_displ)
    _get_next_idx(aip.plug('assignment')).set_val(_val)
示例#24
0
def _get_latest_abc(abc):
    """Get latest path for an abc.

    This is the latest version of any output file with a special case added
    to handle to off-pipeline rest cache abcs.

    Args:
        abc (str): path to abc

    Returns:
        (str): path to latest version
    """

    # Handle regular output file
    try:
        _out_file = tk2.TTOutputFile(abc)
    except ValueError:
        pass
    else:
        return _out_file.find_latest().path

    # Special handling for rest cache
    try:
        _output = tk2.TTOutput(abc)
    except ValueError:
        pass
    else:
        return get_single(_output.find_latest().find(extn=File(abc).extn))
示例#25
0
    def _context__WorkJumpTo(self, menu):

        _work = get_single(self.ui.Work.selected_data(), catch=True)

        # Add jump to recent options
        menu.add_label("Jump to")
        for _work in hb_work.get_recent_work():
            _work = _work.find_latest()
            if not _work:
                continue
            _label = hb_work.get_work_label(_work)
            _icon = hb_work.get_work_icon(_work, mode='basic')
            _fn = wrap_fn(self.jump_to, _work.path)
            menu.add_action(_label, _fn, icon=_icon)

        menu.addSeparator()

        # Jump to clipboard work
        _clip_work = tk2.get_work(qt.get_application().clipboard().text())
        if _clip_work:
            _label = hb_work.get_work_label(_clip_work)
            _fn = wrap_fn(self.jump_to, _clip_work.path)
            menu.add_action('Jump to '+_label, _fn, icon=icons.COPY)
        else:
            menu.add_label('No work in clipboard', icon=icons.COPY)

        # Add current work to recent
        if _work:
            menu.add_action(
                'Add selection to recent', _work.add_to_recent,
                icon=icons.EMOJI.find('Magnet'))
示例#26
0
    def _callback__WorkSave(self):

        self.ui.WorkSave.setEnabled(False)
        _work = get_single(self.ui.Work.selected_data())
        _comment = qt.read_input(
            'Enter comment:', title='Save new version', parent=self)
        _work.save_inc(comment=_comment)
        self.ui.WorkSave.setEnabled(True)
示例#27
0
    def _callback__WorkLoad(self):

        _ver = get_single(self.ui.Work.selected_data(), catch=True)
        self.ui.WorkLoad.setEnabled(False)
        host.refresh()
        _ver.load()
        self.ui.WorkLoad.setEnabled(True)
        self._callback__Work()
示例#28
0
    def _redraw__WorkPath(self):

        _work = get_single(self.ui.Work.selected_data(), catch=True)
        _task = self.ui.TaskEdit.text()
        _step = get_single(self.ui.Step.selected_data(), catch=True)

        if not _work and _task and _step:
            _dcc = hb_utils.cur_dcc()
            _hint = '{dcc}_{area}_work'.format(dcc=_dcc, area=_step.area)
            try:
                _work = _step.map_to(
                    hint=_hint, class_=tk2.TTWork, Task=_task,
                    extension=tk2.get_extn(_dcc), version=1)
            except ValueError:
                _work = None

        self.ui.WorkPath.setText(_work.path if _work else '')
示例#29
0
    def get_plugs(self):
        """Get name of plug which this curve is driving.

        Returns:
            (str): plug being driven
        """
        return get_single(
            self.output.list_connections(source=False, plugs=True))
示例#30
0
    def is_static(self):
        """Test whether this is a static anim.

        Returns:
            (bool): whether anim is static
        """
        _ktv = get_single(cmds.getAttr(self.plug('keyTimeValue')))
        return bool(_ktv)