예제 #1
0
    def set_section(self, section, verbose=0):
        """Set current section (implemented in subclass).

        Args:
            section (_Section): section to apply
            verbose (int): print process data
        """
        _section = _SectionHeader(
            section.label, col=self.section_col, collapse=section.collapse)
        _section.setMinimumSize(100, 22)
        _policy = _section.sizePolicy()
        _policy.setHorizontalPolicy(_policy.Expanding)
        _policy.setHorizontalStretch(100)
        _section.setSizePolicy(_policy)
        self.main_layout.addWidget(_section)

        self.read_settings_fns['section'][section.label] = {}
        self.read_settings_fns['section'][section.label]['collapse'] = wrap_fn(
            getattr, _section, 'collapse')

        self.set_settings_fns['section'][section.label] = {}
        self.set_settings_fns['section'][section.label]['collapse'] = wrap_fn(
            _section.set_collapse)

        self.section = _section
예제 #2
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'))
예제 #3
0
 def _context__submit(self, menu):
     menu.add_action("Print renders + work files", chain_fns(
         wrap_fn(pprint.pprint, self._renders),
         wrap_fn(pprint.pprint, self._work_files.keys()),
         wrap_fn(pprint.pprint, self._passes)))
     menu.add_action("Print frame ranges", wrap_fn(
         self._read_frame_ranges, sorted(self._work_files), verbose=1))
예제 #4
0
 def delete(self):
     """Delete this interface."""
     for _mthd in (wrap_fn(self.closeEvent, None), self.deleteLater):
         try:
             _mthd()
         except RuntimeError:
             pass
예제 #5
0
def get_work_ctx_opts(work, menu, redraw_work, parent):
    """Add context options for the given work file.

    Args:
        work (TTWork): work file
        menu (QMenu): menu to add options too
        redraw_work (fn): function for redrawing work items
        parent (QDialog): parent dialog
    """
    _add_path_menu_items(menu=menu, obj=work)
    menu.addSeparator()

    _set_comment_fn = chain_fns(
        wrap_fn(_set_work_comment, work, parent=parent), redraw_work)
    menu.add_action('Set comment', _set_comment_fn, icon=icons.EDIT)

    # Add output options
    _add_work_ctx_output_files(work=work, menu=menu)

    # Add increments
    _incs = work.find_increments()
    menu.addSeparator()
    if _incs:
        _menu = menu.add_menu('Increments')
        _icon = get_work_icon(work)
        for _inc in _incs:
            _inc_menu = _menu.add_menu(_inc.basename, icon=_icon)
            _add_path_menu_items(menu=_inc_menu, obj=_inc)
    else:
        menu.add_label('No increments found')
예제 #6
0
    def connect_widgets(self,
                        catch_error_=False,
                        track_usage_=True,
                        disable_btns_on_exec=True,
                        verbose=0):
        """Connect widgets with redraw/callback methods.

        Only widgets with override types are linked.

        Args:
            catch_error_ (bool): apply catch error decorator to callbacks
            track_usage_ (bool): apply track usage decorator to callbacks
            disable_btns_on_exec (bool): disable push buttons while
                they are being executed - can interfere with
                enabling/disabling buttons on the fly
            verbose (int): print process data
        """
        for _widget in self.widgets:

            _name = _widget.objectName()
            lprint('CHECKING', _name, verbose=verbose > 1)

            # Connect callback
            _callback = getattr(self, '_callback__' + _name, None)
            if _callback:
                if isinstance(_widget, QtWidgets.QPushButton):
                    if track_usage_:
                        from psyhive.tools import track_usage
                        _callback = track_usage(_callback)
                    if catch_error_:
                        from psyhive.tools import get_error_catcher
                        _catcher = get_error_catcher(exit_on_error=False)
                        _callback = _catcher(_callback)
                    if disable_btns_on_exec:
                        _callback = _disable_while_executing(func=_callback,
                                                             btn=_widget)
                _callback = wrap_fn(_callback)  # To lose args from hook
                lprint(' - CONNECTING', _widget, verbose=verbose)
                for _hook_name in [
                        'clicked',
                        'currentTextChanged',
                        'textChanged',
                ]:
                    _hook = getattr(_widget, _hook_name, None)
                    if _hook:
                        _hook.connect(_callback)

            # Connect context
            _context = getattr(self, '_context__' + _name, None)
            if _context:
                _widget.customContextMenuRequested.connect(
                    _build_context_fn(_context, widget=_widget))
                _widget.setContextMenuPolicy(Qt.CustomContextMenu)

            # Connect redraw callback
            _redraw = getattr(self, '_redraw__' + _name, None)
            if _redraw:
                lprint(' - CONNECTING REDRAW', _widget, verbose=verbose)
                _mthd = _build_redraw_method(_redraw)
                _widget.redraw = types.MethodType(_mthd, _widget)
예제 #7
0
    def init_ui(self, rebuild_fn=None, verbose=1):
        """Initiate ui.

        Args:
            rebuild_fn (func): override rebuild function
            verbose (int): print process data
        """
        dprint('Building ui {} ({})'.format(self.ui_name, self.base_col),
               verbose=verbose)

        # Add menu bar
        _interface = self.add_menu('Interface')
        self.add_menu_item(_interface,
                           label='Collapse all',
                           image=icons.EMOJI.find('Sponge', catch=True),
                           command=self.collapse_all)
        self.add_menu_item(_interface,
                           label='Rebuild',
                           image=icons.EMOJI.find('Hammer', catch=True),
                           command=rebuild_fn or self.rebuild)

        _settings = self.add_menu('Settings')
        self.add_menu_item(_settings,
                           label='Save',
                           image=icons.EMOJI.find('Floppy disk', catch=True),
                           command=self.save_settings)
        self.add_menu_item(_settings,
                           label='Reset',
                           image=icons.EMOJI.find('Shower', catch=True),
                           command=wrap_fn(
                               self.reset_settings))  # Wrap to discard args
        self._save_on_close = self.add_menu_item(_settings,
                                                 label='Save on close',
                                                 checkbox=False)
예제 #8
0
def build_aistandin_from_shade(archive,
                               shade=None,
                               animated=True,
                               name=None,
                               deferred=True,
                               verbose=0):
    """Create aiStandIn from selected shade asset.

    The shader is read from all mesh nodes in the shade asset, and then this
    is used to create an aiSetParameter node on the standin for each shader.
    If all the meshes using the shader has matching values for ai attrs,
    these values are applied as overrides on the aiSetParameter node.

    Args:
        archive (str): path to archive to apply to standin
        shade (FileRef): shade asset to build overrides from
        animated (bool): whether this archive is animated
        name (str): base name for nodes (normally shade namespace)
        deferred (bool): apply deferrred changes - this allows the
            standin to be generated with no error message as maya
            makes deferred callbacks on aiStandIn create; however
            this cannot be used if running code as part of a publish
        verbose (int): print process data

    Returns:
        (HFnTransform) standin transform
    """
    _name = name or shade.namespace

    # Create standin
    _standin = hom.CMDS.createNode('aiStandIn')
    _standin.plug('dso').set_val(archive)
    _standin.plug('useFrameExtension').set_val(animated)

    _merge = hom.CMDS.createNode('aiMerge',
                                 name='{}_mergeOperators'.format(_name))
    _merge.plug('out').connect(_standin.plug('operators[0]'))

    _build_col_switches_aip(shade=shade, merge=_merge, name=_name)
    _build_shader_overrides(shade=shade, merge=_merge, verbose=verbose)

    # Init updates to happen after abc load
    _standin.select()
    _rng = _get_abc_range_from_sg(archive) if animated else None
    _ais_name = get_unique(name or '{}_AIS'.format(shade.namespace))
    _finalise_fn = wrap_fn(_finalise_standin,
                           node=_standin,
                           range_=_rng,
                           name=_ais_name)
    if deferred:
        cmds.evalDeferred(_finalise_fn, lowestPriority=True)
        _parent = None
    else:
        _parent = _finalise_fn()
        print 'NOT DEFERRED', _parent

    print 'CREATED', _standin, _parent

    return _parent
예제 #9
0
    def setup_ctrls(self):
        """Set up system controls."""

        _bones = {
            Limb.ARM: ('Shoulder', 'Elbow', 'Wrist'),
            Limb.LEG: ('Hip', 'Knee', 'Ankle')
        }
        _names = {
            'side': {
                Side.LEFT: 'L',
                Side.RIGHT: 'R'
            }[self.side],
            'limb': {
                Limb.ARM: 'Arm',
                Limb.LEG: 'Leg'
            }[self.limb],
            'gimbal': {
                Limb.ARM: 'wrist',
                Limb.LEG: 'ankle'
            }[self.limb],
            'offset': {
                Limb.ARM: 'Elbow',
                Limb.LEG: 'Knee'
            }[self.limb]
        }

        self.fk_ctrls = [
            self.rig.get_node('FK{bone}_{side}'.format(bone=_bone, **_names),
                              class_=hom.HFnTransform)
            for _bone in _bones[self.limb]
        ]

        self.ik_jnts = [
            self.rig.get_node('IKX{bone}_{side}'.format(bone=_bone, **_names))
            for _bone in _bones[self.limb]
        ]
        self.ik_ = self.rig.get_node('IK{limb}_{side}'.format(**_names),
                                     class_=hom.HFnTransform)
        self.ik_pole = self.rig.get_node('Pole{limb}_{side}'.format(**_names))
        self.ik_pole_rp = self.ik_pole.plug('rotatePivot')
        self.ik_offs = []

        self.gimbal = self.rig.get_node('FKIK{limb}_{side}'.format(**_names))
        self.ik_fk_attr = self.gimbal.plug('FKIKBlend')
        self.set_to_ik = wrap_fn(self.ik_fk_attr.set_val, 10)
        self.set_to_fk = wrap_fn(self.ik_fk_attr.set_val, 0)
예제 #10
0
 def _context__Keyframe(self, menu):
     menu.setStyleSheet('background-color:DimGrey; color:white')
     try:
         _system = system.get_selected_system(class_=self.system)
     except ValueError as _exc:
         menu.add_label(_exc.message)
     else:
         _nodes = _system.get_ctrls()
         menu.add_action('Select nodes', wrap_fn(cmds.select, _nodes))
예제 #11
0
    def setup_ctrls(self):
        """Set up system controls."""

        _names = {
            'side': {Side.LEFT: 'Lf', Side.RIGHT: 'Rt'}[self.side],
            'limb': {Limb.ARM: 'arm', Limb.LEG: 'leg'}[self.limb],
            'gimbal': {Limb.ARM: 'wrist', Limb.LEG: 'ankle'}[self.limb],
            'offset': {Limb.ARM: 'Elbow', Limb.LEG: 'Knee'}[self.limb]}
        self.fk_ctrls = [
            self.rig.get_node('{side}_{limb}Fk_{idx}_Ctrl'.format(
                idx=_idx, **_names))
            for _idx in range(1, 4)]
        self.fk_jnts = [
            self.rig.get_node('{side}_{limb}Fk_{idx}_Jnt'.format(
                idx=_idx, **_names))
            for _idx in range(1, 4)]
        self.ik_jnts = [
            self.rig.get_node('{side}_{limb}Ik_{idx}_Jnt'.format(
                idx=_idx, **_names))
            for _idx in range(1, 4)]

        self.ik_ = self.rig.get_node(
            '{side}_{limb}Ik_Ctrl'.format(**_names))
        self.ik_pole = self.rig.get_node(
            '{side}_{limb}Pole_Ctrl'.format(**_names))
        self.ik_pole_rp = self.ik_pole.plug('rotatePivot')

        self.ik_offs = ['{}.{offset}_Offset'.format(self.ik_, **_names)]
        if self.limb == 'leg':
            self.ik_offs += [
                "{}.Heel_Roll".format(self.ik_),
                "{}.Heel_Pivot".format(self.ik_),
                "{}.Toe_Rotate".format(self.ik_),
                "{}.Foot_Rock".format(self.ik_),
            ]

        self.gimbal = self.rig.get_node(
            '{side}_{gimbal}Gimbal_Ctrl'.format(**_names))
        self.ik_fk_attr = self.gimbal.plug('FK_IK')
        self.set_to_ik = wrap_fn(self.ik_fk_attr.set_val, 1)
        self.set_to_fk = wrap_fn(self.ik_fk_attr.set_val, 0)
예제 #12
0
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)
예제 #13
0
    def test_wrap_fn(self):

        def _test(a=1, b=2, c=3):
            return a, b, c
        assert wrap_fn(_test, b=3)() == (1, 3, 3)
        assert wrap_fn(_test, arg_to_kwarg='c')(4) == (1, 2, 4)

        # Test pass_data
        def _test(*args, **kwargs):
            return args, kwargs
        assert _test() == ((), {})
        assert _test(a=1) == ((), {'a': 1})
        assert wrap_fn(_test)() == ((), {})
        assert wrap_fn(_test, a=1)() == ((), {'a': 1})
        assert wrap_fn(_test)(a=1) == ((), {})
        assert wrap_fn(_test, arg_to_kwarg='test')(1) == ((), {'test': 1})
        assert wrap_fn(_test, pass_data=True)(a=1) == ((), {'a': 1})
예제 #14
0
def open_scene(file_, func=None, force=False, lazy=False):
    """Open the given scene file.

    A warning is raised if the current scene has been modified.

    Args:
        file_ (str): file to open
        func (fn): override save function
        force (bool): lose current scene with no warning
        lazy (bool): abandon open scene if file is already open
    """
    _file = get_path(file_)
    if lazy and cur_scene() == _file:
        print 'SCENE ALREADY OPEN', _file
        return
    if not force and _scene_modified():
        handle_unsaved_changes()
    _func = func or wrap_fn(_force_open_scene, _file)
    _func()
예제 #15
0
def user_setup(verbose=0):
    """User setup.

    Args:
        verbose (int): print process data
    """
    dprint('Executing PsyHive user setup')

    if cmds.about(batch=True):
        return

    _install_psyhive_elements(verbose=verbose)

    # Fix logging level (pymel sets to debug)
    _fix_fn = wrap_fn(logging.getLogger().setLevel, logging.WARNING)
    cmds.evalDeferred(_fix_fn, lowestPriority=True)

    # Add elements to psyop menu (deferred to make sure exists)
    cmds.evalDeferred(_add_elements_to_psyop_menu, lowestPriority=True)

    # Add script editor save to project
    cmds.evalDeferred(script_editor_add_project_opts)
예제 #16
0
 def _context__MakeTicket(self, menu):
     _url = _make_ticket(
         summary='[PSYHIVE] Error: {}'.format(self.message),
         description=self.summary, open_=False)
     _fn = wrap_fn(copy_text, _url)
     menu.add_action('Copy ticket url', icon=icons.COPY, func=_fn)
예제 #17
0

def refresh():
    """Refresh current dcc interface."""


try:
    from maya import cmds
except ImportError:
    pass
else:
    from maya_psyhive import ref, ui
    from maya_psyhive.utils import (get_fps, save_as, save_scene, open_scene as
                                    open_scene_, set_start, set_end)
    NAME = 'maya'
    batch_mode = wrap_fn(cmds.about, batch=True)
    _get_cur_scene = wrap_fn(cmds.file, query=True, location=True)
    _force_open_scene = lambda file_: open_scene_(file_, force=True)
    _force_new_scene = wrap_fn(cmds.file, new=True, force=True)
    refresh = cmds.refresh
    reference_scene = ref.create_ref
    _scene_modified = wrap_fn(cmds.file, query=True, modified=True)
    t_start = wrap_fn(cmds.playbackOptions, query=True, minTime=True)
    t_end = wrap_fn(cmds.playbackOptions, query=True, maxTime=True)
    save = wrap_fn(cmds.file, save=True)
    get_main_window_ptr = ui.get_main_window_ptr

if not NAME:
    try:
        import hou
    except ImportError:
예제 #18
0
 def _context__Step(self, menu):
     _step = get_single(self.ui.Step.selected_data(), catch=True)
     if _step:
         menu.add_action(
             'Copy path', wrap_fn(copy_text, _step.path), icon=icons.COPY)
예제 #19
0
    def _connect_widget(self,
                        widget,
                        track_usage_=True,
                        catch_error_=True,
                        disable_btns_on_exec=True,
                        verbose=0):
        """Connect a widget to callbacks on the parent object.

        Args:
            widget (QWidget): widget to connect
            track_usage_ (bool): apply track usage decorator
            catch_error_ (bool): apply error catcher decorator
            disable_btns_on_exec (bool): disable push buttons while
                executing (this can interfere with custom on the
                fly enabling/disabling)
            verbose (int): print process data
        """
        _name = widget.objectName()

        # See if this element needs connecting
        if not _name:
            return
        _callback = getattr(self, '_callback__' + _name, None)
        _context = getattr(self, '_context__' + _name, None)
        _redraw = getattr(self, '_redraw__' + _name, None)
        if not (_callback or _context or _redraw):
            return

        lprint('CONNECTING', _name, verbose=verbose)

        # Connect callback
        if _callback:

            # Wrap callback
            if isinstance(widget, QtWidgets.QPushButton):
                if track_usage_:
                    from psyhive.tools import track_usage
                    _callback = track_usage(_callback)
                if catch_error_:
                    from psyhive.tools import get_error_catcher
                    _catcher = get_error_catcher(exit_on_error=False)
                    _callback = _catcher(_callback)
                if disable_btns_on_exec:
                    _callback = _disable_while_executing(func=_callback,
                                                         btn=widget)

            _callback = wrap_fn(_callback)  # To lose args from hook
            lprint(' - CONNECTING', widget, verbose=verbose)

            # Find signals to connect to
            for _hook_name in [
                    'clicked',
                    'currentTextChanged',
                    'textChanged',
            ]:
                _hook = getattr(widget, _hook_name, None)
                if _hook:
                    _hook.connect(_callback)

        # Connect context
        if _context:
            widget.customContextMenuRequested.connect(
                _build_context_fn(_context, widget=widget))
            widget.setContextMenuPolicy(Qt.CustomContextMenu)

        # Connect redraw callback
        if _redraw:
            lprint(' - CONNECTING REDRAW', widget, verbose=verbose)
            _mthd = _build_redraw_method(_redraw)
            widget.redraw = types.MethodType(_mthd, widget)
예제 #20
0
 def _context__SendEmail(self, menu):
     _fn = wrap_fn(copy_text, self.summary)
     menu.add_action('Copy email text', icon=icons.COPY, func=_fn)