def test_shade_geo_from_rig(self): _path = (_DEV_PROJ.path + '/assets/3D/character/archer/' 'rig/output/rig/rig_main/v016/maya/archer_rig_main_v016.mb') _ref = ref.obtain_ref(file_=_path, namespace='archer_test') _ref.get_node('placer_Ctrl', class_=hom.HFnTransform).tz.set_val(10) _bbox = _ref.get_node('hairStrand_04_Geo', class_=hom.HFnMesh).bbox() _cache_set = nt.ObjectSet(_ref.get_node('bakeSet')) _n_refs = len(ref.find_refs()) del_namespace(':tmp_archer_test') tank_support.drive_shade_geo_from_rig(_cache_set, verbose=1) assert len(ref.find_refs()) == _n_refs _geo = hom.HFnMesh('tmp_archer_test:hairStrand_04_Geo') assert _geo.bbox().min == _bbox.min assert _geo.bbox().max == _bbox.max
def _update_assets(verbose=0): """Update scene assets to latest version. Args: verbose (int): print process data """ dprint('UPDATING ASSETS') for _ref in qt.progress_bar(ref.find_refs(), 'Updating {:d} asset{}'): # Find asset _asset = tk2.TTOutputFile(_ref.path) if not _asset: continue # Make sure asset is latest if not _asset.is_latest(): lprint(' - CURRENT FILE: {}'.format(_asset.path), verbose=verbose) _latest = _asset.find_latest() lprint(' - UPDATING TO LATEST: {}'.format(_latest.path), verbose=verbose) _ref.swap_to(_latest.path) _status = 'updated' else: _status = 'no update needed' print ' - {:25} {:20} {}'.format(_ref.namespace, _status, _ref.path) print
def fix_groups(): """Fix groups to follow psyop scene organisation.""" _to_fix = [] for _ref in ref.find_refs(unloaded=False): _top_node = _ref.find_top_node(catch=True) if not _top_node: continue _parent = _top_node.get_parent() if _parent in _GROUPS: continue if '/layout/' in _ref.path: _grp = 'JUNK' elif '/camera/' in _ref.path: _grp = 'CAMERA' elif '/prop/' in _ref.path: _grp = 'PROPS' elif '/character/' in _ref.path: _grp = 'CHAR' else: print 'FAILED', _ref.path continue print _ref, _parent, _grp _to_fix.append((_top_node, _grp)) if not _to_fix: print 'NOTHING TO FIX' return qt.ok_cancel('Group {:d} ref{}?'.format(len(_to_fix), get_plural(_to_fix))) for _top_node, _grp in qt.progress_bar(_to_fix): _top_node.add_to_grp(_grp)
def fix_namespaces(): """Fix namespaces to follow psyop naming.""" _used = [] _to_rename = [] for _ref in ref.find_refs(unloaded=False): if not _find_ref_namespace_issues(_ref): continue _base = _ref.namespace.split('_')[0] _name = _base _idx = 1 while True: check_heart() if not cmds.namespace(exists=_name) and _name not in _used: break _name = '{}_{:d}'.format(_base, _idx) _idx += 1 print _ref, _name _used.append(_name) _to_rename.append((_ref, _name)) if not _to_rename: print 'NOTHING TO FIX' return qt.ok_cancel('Rename {:d} ref{}?'.format(len(_to_rename), get_plural(_to_rename))) for _ref, _name in qt.progress_bar(_to_rename): _ref.rename(_name)
def _ingest_check_work(self, comment, force=False): """Check this file has a corresponding psyop work file. Args: comment (str): save comment force (bool): lose unsaved changes without confirmation """ _work = self.to_psy_work() _src = _work.cache_read('vendor_source_file') if _work.exists() and _src: print 'THIS', self.path print 'SRC', _src if _src != self: raise RuntimeError('Source does not match') return print ' - INGEST WORK', _work.path print ' - COMMENT', comment if not force: qt.ok_cancel('Copy {} to pipeline?\n\n{}\n\n{}'.format( _work.step, self.path, _work.path)) host.open_scene(self, force=force, lazy=True) # Update refs for _ref in qt.progress_bar( ref.find_refs(), 'Updating {:d} ref{}', stack_key='UpdateRefs'): self._ingest_check_ref(_ref) # Save to disk print ' - SAVING WORK', _work.path _work.save(comment=comment, safe=False, force=force) _work.cache_write(tag='vendor_source_file', data=self.path)
def read_dependencies(self, force=False, confirm=True, new_scene=True, verbose=0): """Read dependencies of this workfile. Args: force (bool): force reread confirm (bool): confirm before replace current scene new_scene (bool): new scene after read verbose (int): print process data Returns: (dict): namespace/path dependencies dict """ # Make sure scene is loaded _replaced_scene = False if not cmds.file(query=True, location=True) == self.path: if confirm: qt.ok_cancel('Open scene to read contents?\n\n{}\n\n' 'Current scene will be lost.'.format(self.path), title='Replace current scene') cmds.file(self.path, open=True, prompt=False, force=True, loadReferenceDepth='none') _replaced_scene = True _deps = {'refs': {}, 'abcs': {}} # Read refs for _ref in ref.find_refs(): if not _ref.path: continue _deps['refs'][_ref.namespace] = _ref.path # Read abcs for _abc in cmds.ls(type='ExocortexAlembicFile'): if ':' not in _abc: continue _ns = str(_abc.split(':')[0]) _path = str(cmds.getAttr(_abc + '.fileName', asString=True)) _deps['abcs'][_ns] = _path if verbose: pprint.pprint(_deps) if new_scene: cmds.file(new=True, force=True) return _deps, _replaced_scene
def scene_get_refs(self, force=False): """Find reference paths in this scene. Args: force (bool): lose unsaved changes without confirmation Returns: (dict): dict of reference namespaces/paths """ host.open_scene(self.path, lazy=True, force=True) _refs = {} for _ref in ref.find_refs(): _refs[_ref.namespace] = _ref.path return _refs
def blast_with_frustrum_check(kwargs, sample_freq=5): """Blast and check rigs in frustrum. Args: kwargs (dict): playblast kwargs sample_freq (int): frame gap between frustrum tests - ie. a value of 5 means the frustrum is sampled every 5 frames """ cycle_check() _cam = hom.get_active_cam() _rigs = ref.find_refs(class_=_Rig) _off_cam_rigs = _blast_and_find_rigs_outside_frustrum( _cam, _rigs, kwargs, sample_freq=sample_freq) print '{}/{} RIGS ARE OFF CAMERA {}'.format(len(_off_cam_rigs), len(_rigs), _cam) # Remove off cam rigs if _off_cam_rigs: remove_rigs.launch(_off_cam_rigs)
def _update_outputs_to_latest(refs=None): """Update outputs referenced in this file to latest versions. Args: refs (FileRef list): override list of file refs """ for _ref in refs or ref.find_refs(): # Find asset try: _asset = tk2.TTOutputFile(_ref.path) except ValueError: continue print 'CHECKING ASSET', _ref # Make sure asset is latest if not _asset.is_latest(): _latest = _asset.find_latest() print ' - UPDATING TO LATEST: {}'.format(_latest.path) _ref.swap_to(_latest.path) # Check if cache needs updating _exo = get_single([ _node for _node in hom.CMDS.referenceQuery( _ref.ref_node, nodes=True, dagPath=True) if cmds.objectType(_node) == 'ExocortexAlembicFile' ], catch=True) if _exo: print ' - EXO', _exo _abc = _exo.plug('fileName').get_val() print ' - CURRENT ABC', _abc _latest = _get_latest_abc(_abc) if _latest and _abc == _latest: _exo.plug('fileName').set_val(_latest) else: print ' - IS LATEST'
def scene_get_cam(self): """Get render cam from this scene. Returns: (str): camera name """ print 'READING CAM', self.path host.open_scene(self.path, lazy=True, force=True) _cam_rig = None for _ref in ref.find_refs(): if 'cam' not in _ref.path.lower(): continue if _ref.is_loaded(): _cam_rig = _ref continue print ' - REF', _ref.path _psy_file = ingest.map_file_to_psy_asset(_ref.path) print ' - PSY FILE', _psy_file if _psy_file: _ref.swap_to(_psy_file) assert not _cam_rig _cam_rig = _ref _cams = [ _cam for _cam in hom.find_nodes(class_=hom.HFnCamera) if _cam not in DEFAULT_NODES] print ' - CAMS', _cams print ' - CAM RIG', _cam_rig if not len(_cams) == 1 and _cam_rig: _cam_rig_cam = _cam_rig.get_tfm('animCam') return str(_cam_rig_cam) _cam = get_single(_cams) return str(_cam)
def _ingest_check_cache(self, force=False, farm=True): """Check this file has been cached, executing cache if necessary. Args: force (bool): lose unsaved changes without confirmation farm (bool): cache on farm """ if self.has_cache(): return _work = self.to_psy_work() print 'CACHING', _work.path print ' - CACHE FMT', _work.cache_fmt if _work.cache_read(_WAITING_ON_FARM_CACHE_TOKEN): print ' - CACHE ALREADY SUBMITTED' return _work.load(lazy=True, force=force) assert not ref.find_refs(extn='abc') tk2.cache_scene(force=True, farm=farm) if farm: _work.cache_write(_WAITING_ON_FARM_CACHE_TOKEN, True)
def check_current_scene(show_dialog=True, verbose=1): """Check current scene for ingestion issues. Args: show_dialog (bool): show status dialog on completion verbose (int): print process data Returns: (str list): list of issues with current file """ _file = File(host.cur_scene()) _issues = [] lprint('FILE', _file, verbose=verbose) lprint(' - BASENAME', _file.basename, verbose=verbose) # Check current scene filename _issues += _find_scene_name_issues(_file) # Check maya version _ver = int(cmds.about(version=True)) if _ver != 2018: _issues.append('Bad maya version {:d}'.format(_ver)) # Check for unwanted node types for _type in ['displayLayer', 'renderLayer']: _lyrs = [ _lyr for _lyr in cmds.ls(type=_type) if _lyr not in DEFAULT_NODES if not cmds.referenceQuery(_lyr, isNodeReferenced=True) ] if _lyrs: _issues.append('Scene has {} layers: {}'.format( _type.replace("Layer", ""), ', '.join(_lyrs))) for _type in ['unknown']: _nodes = [ _node for _node in cmds.ls(type=_type) if _node not in DEFAULT_NODES if not cmds.referenceQuery(_node, isNodeReferenced=True) ] if _nodes: _issues.append('Scene has {} nodes: {}'.format( _type, ', '.join(_nodes))) # Check references _refs = ref.find_refs(unloaded=False) lprint('CHECKING {:d} REFS'.format(len(_refs)), verbose=verbose) for _ref in _refs: lprint(' - CHECKING', _ref, verbose=verbose) _issues += _find_ref_issues(_ref) # Print summary if verbose: print '\nSUMMARY: FOUND {:d} ISSUE{}'.format( len(_issues), get_plural(_issues).upper()) for _idx, _issue in enumerate(_issues): print ' {:5} {}'.format('[{:d}]'.format(_idx + 1), _issue) print if not show_dialog: pass elif not _issues: qt.notify('No issues found.\n\nFile is read to send to psyop.', verbose=0) else: qt.notify_warning( 'This file has {:d} issue{}.\n\nCheck the script editor for ' 'details.'.format(len(_issues), get_plural(_issues)), verbose=0) return _issues