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)
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
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)
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
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
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))
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
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
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)
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)
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()
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)
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()
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