def yetigraph_attribute_values(assumed_destination, resources): """Get values from Yeti attributes in graph.""" try: for resource in resources: if "graphnode" not in resource: continue fname = os.path.basename(resource["source"]) new_fpath = os.path.join(assumed_destination, fname) new_fpath = new_fpath.replace("\\", "/") try: cmds.pgYetiGraph(resource["node"], node=resource["graphnode"], param=resource["param"], setParamValueString=new_fpath) except Exception as exc: print(">>> Exception:", exc) yield finally: for resource in resources: if "graphnode" not in resources: continue try: cmds.pgYetiGraph(resource["node"], node=resource["graphnode"], param=resource["param"], setParamValue=resource["source"]) except RuntimeError: pass
def _get_yeti_attr(nodeType, attrName, ignoreReference=True): pg_dict = {} _pgyetinodes = cmds.ls(type="pgYetiMaya") if _pgyetinodes: for _i in _pgyetinodes: if ignoreReference and cmds.referenceQuery(_i, inr=1): continue selnodes = cmds.pgYetiGraph(_i, listNodes=1, type=nodeType) for selnode in selnodes: attr_v = cmds.pgYetiGraph(_i, node=selnode, param=attrName, getParamValue=1) # 查询param命令lsp = 1 pg_dict["%s/%s" % (_i, selnode)] = attr_v return pg_dict
def tex_files(): import zfused_maya.node.core.texture as texture _texlist = list() _pgnodes = cmds.ls(type="pgYetiMaya") for _pgnode in _pgnodes: _tex_nodes = cmds.pgYetiGraph(_pgnode, listNodes=1, type="texture") if not _tex_nodes: continue for _j in _tex_nodes: _v = cmds.pgYetiGraph(_pgnode, node=_j, param="file_name", getParamValue=1) if not _v: continue _filepaths = texture.get_udim_texfile(_v, False) for _filepath in _filepaths: if not os.path.exists(_filepath): continue _texlist.append(_filepath) return _texlist
def change_node_path(ori_dict, src, dst): """ change file nodes path """ for _k, _v in ori_dict.items(): _v = _v.replace("\\", "/") # _extend_file = _v.split(src)[-1] _extend_file = os.path.basename(_v) while _extend_file.startswith("/"): _extend_file = _extend_file[1:] _new_file_text_path = "{}/{}".format(dst, _extend_file) # print(_v,_extend_file,_new_file_text_path) _node, _tex_node = _k.split("/") while True: cmds.pgYetiGraph(_node, node=_tex_node, param="file_name", setParamValueString=_new_file_text_path) if cmds.pgYetiGraph(_node, node=_tex_node, param="file_name", getParamValue=1) == _new_file_text_path: break
def k_checkYeticache(self): #缓存匹配公式 self.kexpo3 = r'(.*?)([\.]?)([%][0-9]*d)(\.fur)$' #贴图匹配公式 self.kexpo4 = r'(.*?)([\.]?)([%][0-9]*d)(\.png|\.tif|\.exr)$' self.kexpu4 = r'(.*)(\.png|\.tif|\.exr)$' #节点返回的路径存放地 为了不重复检查 if cc.pluginInfo("pgYetiMaya",q=1,l=1): yetis=cc.ls(type='pgYetiMaya') version = cc.pluginInfo("pgYetiMaya",q=1,v=1) self.mayaplugin_version.update({'Yeti':version}) for yeti in yetis: yeticache=cc.getAttr(yeti+'.cacheFileName') #判断是否绝对路径 if yeticache and not os.path.isabs(yeticache): yeticache=self.projectDir+yeticache if yeticache: ##########设置节点内容 及 加入到节点数据############# ktemp={'path':yeticache,'port':'.cacheFileName'} if self.kNodedate.has_key('kYeticache'): self.kNodedate['kYeticache'].update({yeti:[ktemp]}) else:self.kNodedate['kYeticache']={yeti:[ktemp]} #################################################### #获取 缓存名 与 路径 yeticache_name=os.path.basename(yeticache) yeticache_dir =os.path.dirname (yeticache) pattern = re.search(self.kexpo3,yeticache) if pattern: try: #返回路径下的所谓文件 yeticachefiles=os.listdir(yeticache_dir) for yeticachefile in yeticachefiles: #print yeticachefile #匹配 kexpc = r'%s%s([0-9]*)(\.fur)$' %(pattern.group(1),pattern.group(2)) #判断是否在盘的根目录 防止出现E://xxxxx 这种情况 if yeticache_dir[-2:]==':/': yeticachefilef=yeticache_dir+yeticachefile else:yeticachefilef=yeticache_dir+'/'+yeticachefile pattern2 = re.search(kexpc,yeticachefilef) if pattern2 and not yeticachefilef in self.kYeticache: self.kYeticache.append(yeticachefilef) #print yeticachefilef except: #print e.message pass else: #非序列的文件 if os.path.exists(yeticache) and not yeticache in self.kYeticache: self.kYeticache.append(yeticache) #print yeticache #pgYetiGraph为 yeti提供的mel try: yetiTexs=cc.pgYetiGraph(yeti,listNodes=True,type='texture') if yetiTexs: for yetiTex in yetiTexs: #获取yeti Graph里面的节点 及 参数 yetiTexfile=cc.pgYetiGraph(yeti,node=yetiTex,param='file_name',getParamValue=True) if yetiTexfile and not os.path.isabs(yetiTexfile): yetiTexfile=self.projectDir+yetiTexfile yetiTexfile=yetiTexfile.replace('\\','/') if yetiTexfile: ##########设置节点内容 及 加入到节点数据############# ktemp={'path':yetiTexfile,'texNode':yetiTex} if self.kNodedate.has_key('kYetitex'): #一个maya节点内 如果有多个 Yeti贴图节点 用数组添加法 if self.kNodedate['kYetitex'].has_key(yeti): self.kNodedate['kYetitex'][yeti].append(ktemp) else: self.kNodedate['kYetitex'].update({yeti:[ktemp]}) else:self.kNodedate['kYetitex']={yeti:[ktemp]} #################################################### yetiTex_name=os.path.basename(yetiTexfile) yetiTex_dir =os.path.dirname (yetiTexfile) patternt = re.search(self.kexpo4,yetiTexfile) #匹配是否为序列格式 if patternt: try: YetiTexfiles=os.listdir(yetiTex_dir) for YetiTexfile in YetiTexfiles: #print yeticachefile kexpt = r'%s%s([0-9]*)(\.png|\.tif|\.exr)$' %(patternt.group(1),patternt.group(2)) #判断是否在盘的根目录 防止出现E://xxxxx 这种情况 if yetiTex_dir[-2:]==':/': YetiTexfilef=yetiTex_dir+YetiTexfile else:YetiTexfilef=yetiTex_dir+'/'+YetiTexfile #匹配完整路径格式 pattern = re.search(kexpt,YetiTexfilef) if pattern and not YetiTexfilef in self.kYetitex: self.kYetitex.append(YetiTexfilef) print YetiTexfilef except: #print e.message pass else: if os.path.exists(yetiTexfile) and not yetiTexfile in self.kYeticache: #匹配yeti支持的图片格式 patternt = re.search(self.kexpu4,yetiTexfile) if patternt and not yetiTexfile in self.kYetitex: self.kYetitex.append(yetiTexfile) print yetiTexfile except: pass self.kYeti=list(set(self.kYeticache+self.kYetitex))
def get_texture_nodes(yeti_node): texture_nodes = mc.pgYetiGraph(yeti_node, listNodes=True, type='texture') return texture_nodes
def set_texture_path(yeti_node, texture_node, new_texture_path): mc.pgYetiGraph(yeti_node, node=texture_node, param="file_name", setParamValueString=new_texture_path)
def get_texture_path(yeti_node, texture_node): return mc.pgYetiGraph(yeti_node, node=texture_node, param="file_name", getParamValue=True)
def get_yeti_resources(self, node): """Get all resource file paths If a texture is a sequence it gathers all sibling files to ensure the texture sequence is complete. References can be used in the Yeti graph, this means that it is possible to load previously caches files. The information will need to be stored and, if the file not publish, copied to the resource folder. Args: node (str): node name of the pgYetiMaya node Returns: list """ resources = [] image_search_paths = cmds.getAttr("{}.imageSearchPath".format(node)) texture_filenames = [] if image_search_paths: # TODO: Somehow this uses OS environment path separator, `:` vs `;` # Later on check whether this is pipeline OS cross-compatible. image_search_paths = [ p for p in image_search_paths.split(os.path.pathsep) if p ] # find all ${TOKEN} tokens and replace them with $TOKEN env. variable image_search_paths = self._replace_tokens(image_search_paths) # List all related textures texture_filenames = cmds.pgYetiCommand(node, listTextures=True) self.log.info("Found %i texture(s)" % len(texture_filenames)) # Get all reference nodes reference_nodes = cmds.pgYetiGraph(node, listNodes=True, type="reference") self.log.info("Found %i reference node(s)" % len(reference_nodes)) if texture_filenames and not image_search_paths: raise ValueError("pgYetiMaya node '%s' is missing the path to the " "files in the 'imageSearchPath " "atttribute'" % node) # Collect all texture files # find all ${TOKEN} tokens and replace them with $TOKEN env. variable texture_filenames = self._replace_tokens(texture_filenames) for texture in texture_filenames: files = [] if os.path.isabs(texture): self.log.debug("Texture is absolute path, ignoring " "image search paths for: %s" % texture) files = self.search_textures(texture) else: for root in image_search_paths: filepath = os.path.join(root, texture) files = self.search_textures(filepath) if files: # Break out on first match in search paths.. break if not files: self.log.warning("No texture found for: %s " "(searched: %s)" % (texture, image_search_paths)) item = {"files": files, "source": texture, "node": node} resources.append(item) # For now validate that every texture has at least a single file # resolved. Since a 'resource' does not have the requirement of having # a `files` explicitly mapped it's not explicitly validated. # TODO: Validate this as a validator invalid_resources = [] for resource in resources: if not resource['files']: invalid_resources.append(resource) if invalid_resources: raise RuntimeError("Invalid resources") # Collect all referenced files for reference_node in reference_nodes: ref_file = cmds.pgYetiGraph(node, node=reference_node, param="reference_file", getParamValue=True) # Create resource dict item = { "source": ref_file, "node": node, "graphnode": reference_node, "param": "reference_file", "files": [] } ref_file_name = os.path.basename(ref_file) if "%04d" in ref_file_name: item["files"] = self.get_sequence(ref_file) else: if os.path.exists(ref_file) and os.path.isfile(ref_file): item["files"] = [ref_file] if not item["files"]: self.log.warning("Reference node '%s' has no valid file " "path set: %s" % (reference_node, ref_file)) # TODO: This should allow to pass and fail in Validator instead raise RuntimeError("Reference node must be a full file path!") resources.append(item) return resources
def k_checkYeticache(self): #缓存匹配公式 self.kexpo3 = r'(.*?)([\.]?)([%][0-9]*d)(\.fur)$' #贴图匹配公式 self.kexpo4 = r'(.*?)([\.]?)([%][0-9]*d)(\.png|\.tif|\.exr)$' self.kexpu4 = r'(.*)(\.png|\.tif|\.exr)$' #节点返回的路径存放地 为了不重复检查 pgYeti = [] if cc.pluginInfo("pgYetiMaya", q=1, l=1): yetis = cc.ls(type='pgYetiMaya') version = cc.pluginInfo("pgYetiMaya", q=1, v=1) self.mayaplugin_version.update({'Yeti': version}) for yeti in yetis: yeticache = cc.getAttr(yeti + '.cacheFileName') #判断是否绝对路径 if yeticache and not os.path.isabs(yeticache): yeticache = self.projectDir + yeticache #判断有无重复检查 if yeticache and not yeticache in pgYeti: pgYeti.append(yeticache) #获取 缓存名 与 路径 yeticache_name = os.path.basename(yeticache) yeticache_dir = os.path.dirname(yeticache) pattern = re.search(self.kexpo3, yeticache) if pattern: try: #返回路径下的所谓文件 yeticachefiles = os.listdir(yeticache_dir) for yeticachefile in yeticachefiles: #print yeticachefile #匹配 kexpc = r'%s%s([0-9]*)(\.fur)$' % ( pattern.group(1), pattern.group(2)) #判断是否在盘的根目录 防止出现E://xxxxx 这种情况 if yeticache_dir[-2:] == ':/': yeticachefilef = yeticache_dir + yeticachefile else: yeticachefilef = yeticache_dir + '/' + yeticachefile pattern2 = re.search(kexpc, yeticachefilef) if pattern2 and not yeticachefilef in self.kYeticache: self.kYeticache.append(yeticachefilef) print yeticachefilef except WindowsError: #print e.message pass else: if os.path.exists( yeticache ) and not yeticache in self.kYeticache: self.kYeticache.append(yeticache) print yeticache yetiTexs = cc.pgYetiGraph(yeti, listNodes=True, type='texture') if yetiTexs: for yetiTex in yetiTexs: yetiTexfile = cc.pgYetiGraph(yeti, node=yetiTex, param='file_name', getParamValue=True) if yetiTexfile and not os.path.isabs(yetiTexfile): yetiTexfile = self.projectDir + yetiTexfile yetiTexfile = yetiTexfile.replace('\\', '/') if yetiTexfile: yetiTex_name = os.path.basename(yetiTexfile) yetiTex_dir = os.path.dirname(yetiTexfile) patternt = re.search(self.kexpo4, yetiTexfile) if patternt: try: YetiTexfiles = os.listdir(yetiTex_dir) for YetiTexfile in YetiTexfiles: #print yeticachefile kexpt = r'%s%s([0-9]*)(\.png|\.tif|\.exr)$' % ( patternt.group(1), patternt.group(2)) #判断是否在盘的根目录 防止出现E://xxxxx 这种情况 if yetiTex_dir[-2:] == ':/': YetiTexfilef = yetiTex_dir + YetiTexfile else: YetiTexfilef = yetiTex_dir + '/' + YetiTexfile pattern = re.search( kexpt, YetiTexfilef) if pattern and not YetiTexfilef in self.kYetitex: self.kYetitex.append(YetiTexfilef) print YetiTexfilef except WindowsError: #print e.message pass else: if os.path.exists( yetiTexfile ) and not yetiTexfile in self.kYeticache: patternt = re.search( self.kexpu4, yetiTexfile) if patternt: self.kYeticache.append(yetiTexfile) print yetiTexfile
def k_eMayaPath(k_id): #k_python_sp = '//ftdyproject/digital/film_project/hq_tool/programs/python_site-packages' #if not k_python_sp in sys.path: #sys.path.append(k_python_sp) #import datetime #from bson.objectid import ObjectId #import pymongo client = pymongo.MongoClient('10.99.40.10', 27017) db = client['hqft_film'] kpost = db['check'] #文件路径 p = kpost.find({"_id": ObjectId(k_id)}, {'mayaPath': 1}) for p in p: p = p['mayaPath'] #工程路径 j = kpost.find({"_id": ObjectId(k_id)}, {'mayaProject': 1}) for j in j: j = j['mayaProject'] #目标路径 o = kpost.find({"_id": ObjectId(k_id)}, {'Opath': 1}) for o in o: o = o['Opath'] #目标特殊文件夹路径 op = o + '/ftbox_otherfile' #数据内容 data = kpost.find({"_id": ObjectId(k_id)}, {'Nodedate': 1}) for data in data: data = data['Nodedate'] #创建临时文件夹路径 p_dir = os.path.dirname(p) p_basename = os.path.basename(p) p_savedir = p_dir + '/temp' kexp = r'(^O:/|^o:/)(.*)' kexpb = r'(^%s)(.*)' % (j) #k_eNodedate2=['kYeticache','kabcmeshfiles','kassfiles','kaiTex','kassfiles','kcacheFiles','kmayaTex_default','kmrcacheFiles','kshave_cache',] k_except2 = ['kmayaTex_userTex', 'kYetitex'] for plug in data: if plug == 'kYetitex' and data['kYetitex']: for nodes in data['kYetitex']: for node in data['kYetitex'][nodes]: path = node['path'] port = node['port'] fileMode = node['fileMode'] if not fileMode and not re.search(kexp, path): if re.search(kexpb, path): opath = path.replace(j, o) cc.pgYetiGraph(nodes, node=port, param='file_name', setParamValueString=opath) else: cc.pgYetiGraph(nodes, node=port, param='file_name', setParamValueString=op) elif plug == 'kmayaTex_userTex' and data['kmayaTex_userTex']: for nodes in data['kmayaTex_userTex']: for node in data['kmayaTex_userTex'][nodes]: path = node['path'] port = node['port'] if not re.search(kexp, path): if re.search(kexpb, path): opath = path.replace(j, o) cc.setAttr(nodes + port, opath, type='string') else: cc.setAttr(nodes + port, op, type='string') elif plug == 'kcacheFiles': pass else: if data[plug]: print plug for node in data[plug]: path = data[plug][node][0]['path'] port = data[plug][node][0]['port'] if not re.search(kexp, path): if re.search(kexpb, path): #print path opath = path.replace(j, o) cc.setAttr(node + port, opath, type='string') print node + port, opath else: cc.setAttr(node + port, op, type='string') print 'out' print 'ok' #创建临时文件夹 if not os.path.exists(p_savedir): os.makedirs(p_savedir) tempfile = p_savedir + '/' + p_basename #修改文件名 并 保存 cc.file(rename=tempfile) cc.file(f=1, op="v=0;", typ="mayaBinary", save=True) ksocket.send('saved')
def k_checkYeticache(self): self.kexpo3 = r'(.*?)([\.]?)([%][0-9]*d)(\.fur)$' self.kexpo4 = r'(.*?)([\.]?)([%][0-9]*d)(\.png|\.tif|\.exr)$' self.kexpu4 = r'(.*)(\.png|\.tif|\.exr)$' if cc.pluginInfo("pgYetiMaya", q=1, l=1): yetis = cc.ls(type='pgYetiMaya') version = cc.pluginInfo("pgYetiMaya", q=1, v=1) self.mayaplugin_version.update({'Yeti': version}) for yeti in yetis: yeticache = cc.getAttr(yeti + '.cacheFileName') if yeticache and not os.path.isabs(yeticache): yeticache = self.projectDir + yeticache if yeticache: self.k_Nodedate('kYeticache', yeti, '.cacheFileName', yeticache) yeticache_name = os.path.basename(yeticache) yeticache_dir = os.path.dirname(yeticache) pattern = re.search(self.kexpo3, yeticache) if pattern: try: yeticachefiles = os.listdir(yeticache_dir) for yeticachefile in yeticachefiles: kexpc = r'%s%s([0-9]*)(\.fur)$' % ( pattern.group(1), pattern.group(2)) if yeticache_dir[-2:] == ':/': yeticachefilef = yeticache_dir + yeticachefile else: yeticachefilef = yeticache_dir + '/' + yeticachefile pattern2 = re.search(kexpc, yeticachefilef) if pattern2 and not yeticachefilef in self.kYeticache: self.kYeticache.append(yeticachefilef) except: pass else: if os.path.exists( yeticache ) and not yeticache in self.kYeticache: self.kYeticache.append(yeticache) try: yetiTexs = cc.pgYetiGraph(yeti, listNodes=True, type='texture') enablecache = cc.getAttr(yeti + '.fileMode') if yetiTexs: for yetiTex in yetiTexs: yetiTexfile = cc.pgYetiGraph(yeti, node=yetiTex, param='file_name', getParamValue=True) if yetiTexfile and not os.path.isabs(yetiTexfile): yetiTexfile = self.projectDir + yetiTexfile yetiTexfile = yetiTexfile.replace('\\', '/') if yetiTexfile: self.k_Nodedate2('kYetitex', yeti, yetiTex, yetiTexfile, fileMode=enablecache) yetiTex_name = os.path.basename(yetiTexfile) yetiTex_dir = os.path.dirname(yetiTexfile) patternt = re.search(self.kexpo4, yetiTexfile) if patternt: try: YetiTexfiles = os.listdir(yetiTex_dir) for YetiTexfile in YetiTexfiles: kexpt = r'%s%s([0-9]*)(\.png|\.tif|\.exr)$' % ( patternt.group(1), patternt.group(2)) if yetiTex_dir[-2:] == ':/': YetiTexfilef = yetiTex_dir + YetiTexfile else: YetiTexfilef = yetiTex_dir + '/' + YetiTexfile pattern = re.search( kexpt, YetiTexfilef) if pattern and not YetiTexfilef in self.kYetitex: self.kYetitex.append( YetiTexfilef) except: pass else: if os.path.exists( yetiTexfile ) and not yetiTexfile in self.kYeticache: patternt = re.search( self.kexpu4, yetiTexfile) if patternt and not yetiTexfile in self.kYetitex: self.kYetitex.append(yetiTexfile) except: pass self.kYeti = list(set(self.kYeticache + self.kYetitex))
def k_eMayaPath(k_id): checkIP = ('127.0.0.1', 998) ksocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ksocket.connect(checkIP) client = pymongo.MongoClient('10.99.40.240', 27017) db = client['hqft_film'] kpost = db['check'] p = kpost.find({"_id": ObjectId(k_id)}, {'mayaPath': 1}) for p in p: p = p['mayaPath'] j = kpost.find({"_id": ObjectId(k_id)}, {'mayaProject': 1}) for j in j: j = j['mayaProject'] o = kpost.find({"_id": ObjectId(k_id)}, {'Opath': 1}) for o in o: o = o['Opath'] k_customname = kpost.find({"_id": ObjectId(k_id)}, {'customname': 1}) for k_customname in k_customname: k_customname = k_customname['customname'] op = o + 'ftbox_otherfile/' + k_customname oimage = o + 'sourceimages/' + k_customname data = kpost.find({"_id": ObjectId(k_id)}, {'Nodedate': 1}) for data in data: data = data['Nodedate'] p_dir = os.path.dirname(p) p_basename = os.path.basename(p) p_savedir = p_dir + '/ftp_updata' kexp = r'(^O:/|^o:/)(.*)' kexpb = r'(^%s)(.*)' % (j) for plug in data: if plug == 'kYetitex' and data['kYetitex']: for nodes in data['kYetitex']: for node in data['kYetitex'][nodes]: path = node['path'] port = node['port'] fileMode = node['fileMode'] if not fileMode and not re.search(kexp, path): if re.search(kexpb, path): opath = path.replace(j, o) cc.pgYetiGraph(nodes, node=port, param='file_name', setParamValueString=opath) else: path_name = os.path.basename(path) oppath = oimage + '/' + path_name cc.pgYetiGraph(nodes, node=port, param='file_name', setParamValueString=oppath) elif plug == 'kmayaTex_userTex' and data['kmayaTex_userTex']: for nodes in data['kmayaTex_userTex']: for node in data['kmayaTex_userTex'][nodes]: path = node['path'] port = node['port'] if not re.search(kexp, path): if re.search(kexpb, path): opath = path.replace(j, o) cc.setAttr(nodes + port, opath, type='string') else: path_name = os.path.basename(path) oppath = oimage + '/' + path_name cc.setAttr(nodes + port, oppath, type='string') elif plug == 'kaiTex' or plug == 'kmayaTex_default': for node in data[plug]: path = data[plug][node][0]['path'] port = data[plug][node][0]['port'] if not re.search(kexp, path): if re.search(kexpb, path): opath = path.replace(j, o) cc.setAttr(node + port, opath, type='string') else: path_name = os.path.basename(path) oppath = oimage + '/' + path_name cc.setAttr(node + port, oppath, type='string') else: if data[plug]: for node in data[plug]: path = data[plug][node][0]['path'] port = data[plug][node][0]['port'] if not re.search(kexp, path): if re.search(kexpb, path): opath = path.replace(j, o) cc.setAttr(node + port, opath, type='string') else: path_name = os.path.basename(path) oppath = op + '/' + path_name cc.setAttr(node + port, oppath, type='string') if not os.path.exists(p_savedir): os.makedirs(p_savedir) tempfile = p_savedir + '/' + p_basename cc.file(rename=tempfile) cc.file(f=1, op="v=0;", typ="mayaBinary", save=True) cc.file(f=1, new=1) ksocket.send('saved')
def scrape_yeti_graph(yeti_node): ''' For the given pgYetiMaya node, scrape all of it's external file dependencies. Note that this node not only contains typical string attributes which may contain filepaths, but it also is a "gateway" into yeti's own internal dependency node system.... which must be queried for file dependencies as well. To further complicate things, these nodes allow paths to be defined relative/global (rather than absolute), so we'll need to resolve them by reading the imageSearchPath attribute on the yeti node, as well as searching any search paths defined in PG_IMAGE_PATH environment variable. ''' # If the node is reading from a cache file/directory, then ensure that it # exists on disk before attempting to read/traverse it's data if cmds.getAttr('%s.fileMode' % yeti_node): path = cmds.getAttr("%s.cacheFileName" % yeti_node) # if no path is specified, or the path doesn't resolves to any files, raise an exception if not path or not file_utils.process_upload_filepath(path): raise Exception( "Cannot scrape yeti dependencies! Cache path does not exist: %s" % path) filepaths = [] yeti_input_nodes = ["texture", "reference"] attr_name = "file_name" # Query the the yeti search paths from imageSearchPath attr. This attr # will be a single string value that may contain multiple paths (just # like a typical environment variable might). node_search_paths = [ p.strip() for p in (cmds.getAttr("%s.imageSearchPath" % yeti_node) or "").split(os.pathsep) ] logger.debug("%s image search paths: %s", yeti_node, node_search_paths) # Get any search paths defined by the PG_IMAGE_PATH env variable pg_image_search_paths = [ p.strip() for p in os.environ.get("PG_IMAGE_PATH", "").split(os.pathsep) ] logger.debug("PG_IMAGE_PATH search paths: %s", pg_image_search_paths) search_paths = node_search_paths + pg_image_search_paths logger.debug("combined image search paths: %s", search_paths) for node_type in yeti_input_nodes: logger.debug("Traversing yeti %s nodes", node_type) for node in cmds.pgYetiGraph(yeti_node, listNodes=True, type=node_type) or []: filepath = cmds.pgYetiGraph(yeti_node, node=node, getParamValue=True, param=attr_name) logger.debug("Yeti graph node: %s.%s: %s", node, attr_name, filepath) if filepath: # Yeti nodes may store the filepath in either forward slash or backslash format (ugh). # This is problematic if the content is initially created on one platform (like Windows) # but is now currently opened on a different platform (like linux), which doesn't acknowledge # backslashes as path separators (since a backslash is a valid character in unix path). # So we must choose between two evils and simply assume that all backslashes are intended # to be directory separators, and so we convert them to forward slashes (which Windows # will handle just fine as well). filepath = os.path.normpath(filepath).replace('\\', "/") logger.debug("Conformed path: %s", filepath) # if the filepath is absolute, then great; record it. if os.path.isabs(filepath): filepaths.append(filepath) continue # If the path is relative then we must construct a potential path # from each of our search paths, and check whether the path existst. logger.debug("Resolving relative path: %s", filepath) for search_path in search_paths: full_path = os.path.join(search_path, filepath) logger.debug("Checking for potential filepath: %s", full_path) # We must account for cases where the path could actually # be an expression (e.g. <udim>, etc), so we can't just check # for the path's literal existence. Instead, we check whether # the expression resolves in at least one path. If it does # then great; we've resolved our relative path. resolved_filepaths = file_utils.process_upload_filepath( full_path, strict=False) if resolved_filepaths: logger.debug("Resolved filepaths: %s", resolved_filepaths) filepaths.extend(resolved_filepaths) break else: raise Exception("Couldn't resolve relative path: %s" % filepath) return filepaths
def scrape_yeti_graph(yeti_node): ''' For the given pgYetiMaya node, scrape all of it's external file dependencies. Note that this node not only contains typical string attributes which may contain filepaths, but it also is a "gateway" into yeti's own internal dependency node system.... which must be queried for file dependencies as well. To further complicate things, these nodes allow paths to be defined relatively (rather than absolute), so we'll need to resolve them by reading the imageSearchPath attribute on the yeti node. TODO(lws): we may need to also include the PG_IMAGE_PATH environment variable as another search location. ''' # If the node is reading from a cache file/directory, then ensure that it # exists on disk before attempting to read/traverse it's data if cmds.getAttr('%s.fileMode' % yeti_node): path = cmds.getAttr("%s.cacheFileName" % yeti_node) # if no path is specified, or the path doesn't resolves to any files, raise an exception if not path or not file_utils.process_upload_filepath(path): raise Exception("Cannot scrape yeti dependencies! Cache path does not exist: %s" % path) filepaths = [] yeti_input_nodes = ["texture", "reference"] attr_name = "file_name" # Query the the yeti search paths from imageSearchPath attr. This attr # will be a single string value that may contain multiple paths (just # like a typical environment variable might). search_paths = [p.strip() for p in (cmds.getAttr("%s.imageSearchPath" % yeti_node) or "").split(os.pathsep)] logger.debug("Yeti image search paths: %s", search_paths) for node_type in yeti_input_nodes: logger.debug("Traversing yeti %s nodes", node_type) for node in cmds.pgYetiGraph(yeti_node, listNodes=True, type=node_type) or []: filepath = cmds.pgYetiGraph(yeti_node, node=node, getParamValue=True, param=attr_name) logger.debug("Yeti graph node: %s.%s: %s", node, attr_name, filepath) if filepath: # if the filepath is absolute, then great; record it. if os.path.isabs(filepath): filepaths.append(filepath) continue # If the path is relative then we must construct a potential path # from each of our search paths, and check whether the path existst. logging.debug("Resolving relative path: %s", filepath) for search_path in search_paths: full_path = os.path.join(search_path, filepath) logging.debug("Checking for potential filepath: %s", full_path) # We must account for cases where the path could actually # be an expression (e.g. <udim>, etc), so we can't just check # for the path's literal existence. Instead, we check whether # the expression resolves in at least one path. If it does # then great; we've resolved our relative path. if file_utils.process_upload_filepath(full_path, strict=False): logging.debug("Resolved filepath: %s", full_path) filepaths.append(full_path) break else: raise Exception("Couldn't resolve relative path: %s" % filepath) return filepaths