示例#1
0
    def _callback__WorkSaveAs(self):

        _work_path = self.ui.WorkPath.text()
        _cur_work = tk2.cur_work()
        _next_work = tk2.obtain_work(_work_path).find_next()

        # Apply change task warning
        if _cur_work:

            _cur_task = _cur_work.get_work_area(), _cur_work.task
            _next_task = _next_work.get_work_area(), _next_work.task

            print 'CUR WORK ', _cur_work
            print 'NEXT WORK', _next_work

            if _cur_task != _next_task:
                _icon = hb_work.get_work_icon(_next_work)
                qt.ok_cancel(
                    'Are you sure you want to switch to a different task?'
                    '\n\nCurrent:\n{}\n\nNew:\n{}'.format(
                        _cur_work.path, _next_work.path),
                    title='Switch task', icon=_icon, parent=self)

        # Save
        self.ui.WorkSaveAs.setEnabled(False)
        _comment = qt.read_input(
            'Enter comment:', title='Save new version', parent=self)
        _next_work.save(comment=_comment)

        # Update ui
        self._callback__TaskRefresh()
        self._callback__WorkJumpTo()

        self.ui.WorkSaveAs.setEnabled(True)
示例#2
0
def _get_default_browser_dir(work=None, verbose=0):
    """Get default directory for file browser.

    Args:
        work (TTWork): override primary work
        verbose (int): print process data

    Returns:
        (str): browser dir
    """
    _works = [work] + [tk2.cur_work()] + hive_bro.get_recent_work()
    _shots = [_work.get_shot()
              for _work in _works if _work and _work.shot] + tk2.find_shots()
    _shots = [
        _shot for _idx, _shot in enumerate(_shots)
        if _shots.index(_shot) == _idx
    ]
    if verbose:
        pprint.pprint(_works)
        pprint.pprint(_shots)

    _dir = None
    for _shot in _shots:
        _dir = _shot.find_step_root('animation').map_to(
            hint='shot_output_type',
            class_=tk2.TTOutputType,
            output_type='animcache',
            Task='animation')
        if not _dir.exists():
            lprint(' - MISSING', _dir, verbose=verbose)
            continue
        lprint(' - MATCHED', _dir, verbose=verbose)
        return _dir.path

    return None
示例#3
0
def cache_work_file(work_file,
                    namespaces,
                    confirm=False,
                    new_scene=False,
                    farm=True,
                    parent=None):
    """Recache the given work file.

    The work file is opened, versioned up and the recached.


    Args:
        work_file (TTWorkFileBase): work file to recache
        namespaces (str list): list of assets to recache
        confirm (bool): confirm before execute
        new_scene (bool): new scene after recache
        farm (bool): submit recache to farm
        parent (QDialog): parent interface (for dialog positioning)
    """
    dprint('RECACHING', work_file.path)

    _engine = tank.platform.current_engine()
    _fileops = _engine.apps['psy-multi-fileops']

    # Load the scene
    work_file.load()
    maya.utils.processIdleEvents()
    _fileops.init_app()

    # Update assets
    _updated = []
    for _ns in qt.progress_bar(namespaces,
                               'Updating {:d} asset{}',
                               col='LightSteelBlue',
                               parent=parent):
        _ref = ref.find_ref(_ns, class_=m_pipe.OutputRef)
        if not _ref.is_loaded():
            _ref.load()
        if _ref.update_to_latest():
            _updated.append(_ref.namespace)

    # Version up
    _fileops.init_app()
    maya.utils.processIdleEvents()
    _engine = tank.platform.current_engine()
    _fileops = _engine.apps['psy-multi-fileops']
    _fileops.version_up_workfile()
    maya.utils.processIdleEvents()
    _cur_work = tk2.cur_work(class_=BCWork)
    _cur_work.set_comment('Versioned up by batch cache tool')
    _cur_work.read_dependencies(new_scene=False)

    _exec_cache(namespaces=namespaces,
                new_scene=new_scene,
                confirm=confirm,
                farm=farm)
    cmds.file(new=True, force=True)
示例#4
0
    def get_cache_xml(self):
        """Get cache xml file for the current workspace.

        Returns:
            (File): cache xml file
        """
        _work = tk2.cur_work()
        _cache_xml = File('{}/cache/nCache/{}/{}.xml'.format(
            _work.get_work_area().path, _work.basename, self))
        return _cache_xml
示例#5
0
def _get_default_browser_dir():
    """Get default directory for work file browser.

    Returns:
        (str): path to default browser dir
    """
    _cur_work = tk2.cur_work()
    if _cur_work:
        return _cur_work.dir

    return pipe.cur_project().path
示例#6
0
def _get_blast_seq():
    """Get blast image sequence for the current workspace.

    Returns:
        (Seq): blast/capture sequence
    """
    _cam = hom.get_active_cam()
    _work = tk2.cur_work()
    return _work.map_to(tk2.TTOutputFileSeq,
                        output_type='capture',
                        format='jpg',
                        extension='jpg',
                        output_name=str(_cam))
示例#7
0
def launch_cache_tools():
    """Launch yeti cache tools interface."""
    global DIALOG

    # Make sure we are in a shot
    _work = tk2.cur_work()
    if not _work:
        qt.notify_warning(
            'No current work file found.\n\nPlease save your scene.')
        return None

    # Launch interface
    from maya_psyhive.tools import yeti
    DIALOG = _YetiCacheToolsUi()
    yeti.DIALOG = DIALOG
    return yeti.DIALOG
示例#8
0
def yeti_to_output(yeti, work=None):
    """Get output for the given yeti node.

    Args:
        yeti (HFnDependencyNode): yeti node to export
        work (TTWork): work file

    Returns:
        (TTOutputFileSeq): export path
    """
    _work = work or tk2.cur_work()
    _out = _work.map_to(
        tk2.TTOutputFileSeq,
        output_name='{}Yeti_{}'.format(
            yeti.namespace, yeti.get_parent().clean_name),
        format='yeti', output_type='fxcache', extension='fur',
        Step=_work.step, Task=_work.task)
    return _out
示例#9
0
    def __init__(self):
        """Constructor."""
        self.work = tk2.cur_work()
        self._yeti_caches = []

        _ui_file = abs_path('{}/yeti_cache_tools.ui'.format(
            os.path.dirname(__file__)))
        super(_YetiCacheToolsUi, self).__init__(ui_file=_ui_file)
        self.set_icon(ICON)

        self._redraw__Step()

        self.ui.Step.currentTextChanged.connect(self._redraw__Name)
        self.ui.Name.currentTextChanged.connect(self._redraw__Version)
        self.ui.Version.currentIndexChanged.connect(
            self._redraw__CacheReadAsset)
        self.ui.Version.currentIndexChanged.connect(
            self._redraw__CacheReadRoot)
        self.ui.Version.currentIndexChanged.connect(self._redraw__VersionLabel)
示例#10
0
    def _callback__Work(self):
        """Update work elements."""

        _work = get_single(self.ui.Work.selected_data(), catch=True)
        _c_work = self.c_works.get(_work)
        _cur_scene = host.cur_scene()
        _cur_work = tk2.cur_work()

        if _work:
            _cur_work_selected = (_cur_work.ver_fmt == _work.ver_fmt
                                  if _cur_work else False)
            _work_orig = _work.map_to(version=1)

            self.ui.WorkPath.setText(_work.path)
            self.ui.VendorMa.setText(_work_orig.get_vendor_file())

            # Set label
            _rng = _work_orig.get_range()
            if _rng:
                _start, _end = [int(round(_val)) for _val in _rng]
                _label = 'Range: {:d} - {:d}'.format(_start, _end)
            else:
                _label = 'Cache missing'
            self.ui.WorkLabel.setText(_label)

            self.ui.Load.setEnabled(True)
            self.ui.VersionUp.setEnabled(_cur_work_selected)
            self.ui.ExportFbx.setEnabled(_cur_work_selected)
            self.ui.WorkBrowser.setEnabled(True)
            self.ui.PlaySeq.setEnabled(bool(_c_work.find_outputs()))

        else:
            self.ui.WorkPath.setText('')
            self.ui.VendorMa.setText('')

            self.ui.Load.setEnabled(False)
            self.ui.VersionUp.setEnabled(False)
            self.ui.ExportFbx.setEnabled(False)
            self.ui.WorkBrowser.setEnabled(False)
            self.ui.PlaySeq.setEnabled(False)
示例#11
0
    def _redraw__Name(self):

        _step = self.ui.Step.currentText()

        _names = sorted(
            set([
                tk2.TTOutputName(_ver.dir) for _ver in self._yeti_caches
                if _ver.step == _step
            ]))

        # Update widget
        _select = None
        self.ui.Name.clear()
        for _name in _names:
            self.ui.Name.add_item(_name.basename, data=_name)
            if not _select and _name.task == tk2.cur_work().task:
                _select = _name
        if _select:
            self.ui.Name.select_data(_select)
        if not _names:
            self.ui.Name.addItem('<None>')
        self.ui.Name.setEnabled(bool(_names))

        self._redraw__Version()
示例#12
0
def _do_create_cache(start,
                     end,
                     file_mode=_FileMode.ONE_FILE_PER_FRAME,
                     update_viewport=True,
                     cache_dir='',
                     cache_per_geo=False,
                     cache_name='',
                     cache_name_as_prefix=False,
                     action=_Action.ADD,
                     force_save=True,
                     sim_rate=1,
                     sample_mult=1,
                     inherit_settings=False,
                     use_float=True,
                     verbose=0):
    """Create an nCloth cache.

    Args:
        start (int): start frame
        end (int): end frame
        file_mode (FileMode): file mode
        update_viewport (bool): update viewport on cache
        cache_dir (str): force cache dir (empty to use default)
        cache_per_geo (bool): generate cache xml per geo
        cache_name (str): name of cache (normally nCloth shape name)
        cache_name_as_prefix (bool): use cache name as prefix
        action (Action): cache action
        force_save (bool): force save even if it overwrites existing files
        sim_rate (int): the rate at which the cloth simulation is
            forced to run
        sample_mult (int): the rate at which samples are written, as
            a multiple of simulation rate.
        inherit_settings (bool): whether modifications should be
            inherited from the cache about to be replaced
        use_float (bool): whether to store doubles as floats
        verbose (int): print process data
    """
    _source_custom_n_cache()

    _start = int(host.t_start())
    _end = int(host.t_end())
    _work = tk2.cur_work()

    _args = [None] * 16
    _args[0] = 0  # time_range_mode - use args 1/2
    _args[1] = start
    _args[2] = end
    _args[3] = file_mode
    _args[4] = int(update_viewport)
    _args[5] = cache_dir
    _args[6] = int(cache_per_geo)
    _args[7] = cache_name
    _args[8] = int(cache_name_as_prefix)
    _args[9] = action
    _args[10] = int(force_save)
    _args[11] = sim_rate
    _args[12] = sample_mult
    _args[13] = int(inherit_settings)
    _args[14] = int(use_float)
    _args[15] = "mcx"

    _cmd = 'PSY_doCreateNclothCache 5 {{ {} }};'.format(', '.join(
        ['"{}"'.format(_arg) for _arg in _args]))
    lprint(_cmd, verbose=verbose)
    mel.eval(_cmd)
示例#13
0
def build_scene(shot='log0320',
                step='previz',
                submitter='/out/submitter1',
                version_up=True,
                submit=True):
    """Build scene from template.

    This will:

     - update the timeline to the shotgun range
     - updates the camera rop to the latest camcache from this shot
     - remove any abcs in /obj and replace them with the latest version
       of each abc in this shot
     - press the submit button on the given qube subitter

    Args:
        shot (str): name of shot to update to
        step (str): step to search for abcs
        submitter (str): path to submitter rop
        version_up (bool): version up scene
        submit (bool): execute submission
    """
    print 'BUILD SCENE', shot
    _trg_shot = tk2.find_shot(shot)
    _step = _trg_shot.find_step_root(step)
    _src_work = tk2.cur_work()
    _root = hou.node('/obj')

    _submitter = hou.node(submitter)
    if not _submitter:
        raise RuntimeError('Missing submitter ' + submitter)
    _cam = _root.node('renderCam')
    if not _submitter:
        raise RuntimeError('Missing camera /obj/renderCam')

    # Update frame range
    _rng = _trg_shot.get_frame_range()
    host.set_range(*_rng)

    # Update cam
    _cam_abc = _step.find_output_file(output_type='camcache',
                                      extn='abc',
                                      verbose=1,
                                      version='latest')
    print 'CAM ABC', _cam_abc
    _cam.parm('fileName').set(_cam_abc.path)
    _cam.parm('buildHierarchy').pressButton()
    _cam_pos = _cam.position()

    # Flush abcs
    for _node in _root.children():
        if _node.type().name().startswith('psyhou.general::alembic_import'):
            _node.destroy()

    # Bring in abcs
    for _idx, _abc in enumerate(
            _step.find_output_files(output_type='animcache',
                                    extn='abc',
                                    version='latest')):
        print 'ABC', _abc

        if _root.node(_abc.basename):
            _root.node(_abc.basename).destroy()

        _node = _root.createNode(
            node_type_name='psyhou.general::alembic_import::0.1.0',
            node_name=_abc.basename)
        _node.setPosition(_cam_pos + hou.Vector2(0, -1 - 0.8 * _idx))
        _node.parm('fileName').set(_abc.path)
        _node.parm('shop_materialpath').set('/shop/set')
        _node.parm('loadmode').set(1)
        _node.setColor(hou.Color([0, 0.5, 0]))
        print 'NODE', _node
        print

    if version_up:
        _trg_work = _src_work.map_to(Shot=_trg_shot.name).find_next()
        print 'WORK', _trg_work
        _trg_work.save(comment='Generated by scene builder tool')

    if submit:
        _submitter.parm('submit_node').pressButton()
示例#14
0
def _cache_yetis(yetis, apply_on_complete=False, samples=3, verbose=0):
    """Cache a list of yeti nodes.

    Args:
        yetis (HFnDependencyNode list): nodes to cache
        apply_on_complete (bool): apply cache on completion
        samples (int): samples per frame
        verbose (int): print process data
    """
    from . import yeti_ui

    print 'CACHE YETIS', yetis
    _work = tk2.cur_work()
    _yetis, _outs, _namespaces = _prepare_yetis_and_outputs(
        yetis=yetis, work=_work)

    # Get cache path - if multiple namespace need to cache to tmp
    _tmp_fmt = abs_path('{}/yetiTmp/<NAME>.%04d.cache'.format(
        tempfile.gettempdir()))
    if len(_yetis) > 1:
        _cache_path = _tmp_fmt
        _tmp_dir = Dir(os.path.dirname(_tmp_fmt))
        _tmp_dir.delete(force=True)
        _tmp_dir.test_path()
    else:
        assert len(_outs) == 1
        _cache_path = _outs[0].path
    print "CACHE PATH", _cache_path

    # Generate caches
    dprint('GENERATING CACHES', _cache_path)
    print ' - SAMPLES', samples
    for _yeti in _yetis:
        _yeti.plug('cacheFileName').set_val('')
        _yeti.plug('fileMode').set_val(0)
        _yeti.plug('overrideCacheWithInputs').set_val(False)
    cmds.select(_yetis)
    cmds.pgYetiCommand(
        writeCache=_cache_path, range=host.t_range(), samples=samples)
    dprint('GENERATED CACHES', _cache_path)

    # Move tmp caches to outputs
    if len(_yetis) > 1:
        dprint('MOVING CACHES FROM TMP')
        for _yeti, _out in safe_zip(_yetis, _outs):
            print ' - MOVING', _out.path
            _name = str(_yeti).replace(":", "_")
            _tmp_seq = Seq(_tmp_fmt.replace('<NAME>', _name))
            for _frame, _tmp_path in safe_zip(
                    _tmp_seq.get_frames(), _tmp_seq.get_paths()):
                lprint('   -', _frame, _tmp_path, verbose=verbose)
                shutil.move(_tmp_path, _out[_frame])

    # Apply cache to yeti nodes
    if apply_on_complete:
        dprint('APPLYING CACHES TO YETIS')
        for _yeti, _cache in safe_zip(_yetis, _outs):
            apply_cache(cache=_cache, yeti=_yeti)

    qt.notify(
        'Cached {:d} yeti node{}.\n\nSee script editor for details.'.format(
            len(_yetis), get_plural(_yetis)),
        title='Cache complete', icon=yeti_ui.ICON, parent=yeti_ui.DIALOG)

    return _outs