''' quick utility function to check which assets have published materials ''' import os from pipe.pipeHandlers.project import Project from pipe.pipeHandlers.body import Body from pipe.pipeHandlers.body import Asset from pipe.pipeHandlers.body import AssetType from pipe.pipeHandlers.element import Element from pipe.pipeHandlers.environment import Environment from pipe.pipeHandlers import pipeline_io project = Project() assets = project.list_assets() output = "\n\n" for name in assets: asset = project.get_asset(name) element = asset.get_element(Asset.MATERIALS) if element and element.get_last_version() >= 0: path = element.get_last_publish()[3] out = name + "\n"#+ " material at " + path + "\n" output += out print(output)
class LayoutUpdater: def __init__(self): self.project = Project() self.assetList = self.project.list_assets() for asset in self.assetList: asset = re.sub(r'\W+', '', asset) def updateAll(self): obj = hou.node("/obj") for node in obj.children(): if node.type().name() == "cenoteLayoutNet": self.updateLayout(node) def updateLayout(self, layout): print("updating " + layout.name()) #reload its usd reference node self.reloadUsd(layout) #update all materials in the layout's library lib = None for node in layout.children(): if node.type().name() == "matnet": lib = node matList = [] for mat in lib.children(): self.reloadMaterial(mat) matList.append(mat.name()) #undo all material assignments (set to 0) layout.parm("num_materials").set(0) #parse through the material bindings again matDict = self.getMatDict(layout) self.assignMats(layout, matDict, matList, lib) qd.message("Successfully updated " + layout.name()) def reloadUsd(self, layout): refNodePath = layout.parm("loppath").eval() refNode = hou.node(refNodePath) refNode.parm("reload").pressButton() def reloadMaterial(self, matNode): typeName = matNode.type().name() if typeName not in self.assetList: return #not a material from the pipe, move on if matNode.isLockedHDA(): matNode.allowEditingOfContents() matNode.matchCurrentDefinition() matNode.allowEditingOfContents() def getMatDict(self, layout): refNodePath = layout.parm("loppath").eval() refNode = hou.node(refNodePath) stage = refNode.stage() matDict = {} for prim in stage.Traverse(): #print(prim.GetName() + " " + prim.GetTypeName()) mat_path = prim.GetRelationship("material:binding") #we decide what to copy into it's own geometry node by what has its own material if mat_path: #print(prim.GetName() + " has a material at path " + str(mat_path.GetForwardedTargets()[0])) primPaths = "" if prim.GetTypeName() == "Mesh": primPaths = primPaths + "@path=" + str( prim.GetPath()) + " " else: children = self.getDescendants(prim) for child in children: if child.GetTypeName() == "Mesh": primPaths = primPaths + "@path=" + str( child.GetPath()) + " " mat_path = mat_path.GetForwardedTargets() if mat_path[0].IsPrimPath(): #print(mat_path[0]) mat_name = os.path.basename(str(mat_path[0])) #print("\t" + mat_name) if mat_name in matDict.keys(): matDict[mat_name] += primPaths else: matDict[mat_name] = primPaths return matDict def assignMats(self, layout, matDict, matList, library): layout.parm("num_materials").set(len(matDict.keys())) index = 1 for mat in matDict.keys(): if re.sub(r'\W+', '', mat) in matList: #this material is already up to date matNode = hou.node(library.path() + "/" + mat) else: #clone in that material's hda to the network asset = self.project.get_asset(mat) if not asset: print("Well there's your problem :/") continue element = asset.get_element(Asset.MATERIALS) matNode = None if element.get_last_version() >= 0: path = element.get_last_publish()[3] hdaPath = path.split(".")[0] + ".hda" try: hou.hda.installFile(hdaPath) matNode = library.createNode(re.sub(r'\W+', '', mat)) matNode.setName(mat, 1) matNode.setMaterialFlag(True) except Exception as e: qd.error( "The material for " + mat + " needs to be republished. Sorry for the inconvenience." ) #print(e) #assign the material to all the paths layout.parm("group" + str(index)).set(matDict[mat]) if matNode: layout.parm("shop_materialpath" + str(index)).set( matNode.path()) index += 1 def getDescendants(self, prim): all = [] children = prim.GetChildren() all.extend(children) for child in children: all.extend(self.getDescendants(child)) return all #the only part that should need to be redone is the material stuff #so first, make sure to reload the usda file #from there, the lop import should be fine, so don't mess with that #parse through the usda to get the material assignments #and apply the materials like before #updating the materials might also be a problem, they won't update automatically but #there might be a way to force it to update from the hda file, which should take #care of it. #for each material node #check if it's an hda #check if it's unlocked, if not then unlock it #call hou.Node.matchCurrentDefinition() #unlock it again
class UpdateAssets: def __init__(self): self.project = Project() def update_assets(self): lists = ShotgunReader().getAssetLists() asset_list = lists[0] assets = lists[1] #update .asset_list list_file = open( os.path.join(self.project.get_assets_dir(), ".asset_list.txt"), "w") list_file.truncate(0) for name in asset_list: list_file.write(name + "\n") list_file.close() #update .short_asset_list list_file = open( os.path.join(self.project.get_assets_dir(), ".short_asset_list"), "w") list_file.truncate(0) for asset in assets: name = asset["name"] variants = asset["children"][:] print("name: " + name) print("variants: ", variants) self.build_asset(name, variants) list_file.write(name + "\n") list_file.close() qd.message("Assets updated successfully.") def build_asset(self, main_name, variants): stage = hou.node("/stage") self.primpath = "/" + main_name prim = stage.createNode("primitive") prim.setName("base_prim", 1) prim.parm("primpath").set(self.primpath) config = stage.createNode("configurelayer") config.setName("set_default_prim", 1) config.setInput(0, prim) config.parm("defaultprim").set(self.primpath) config.parm("setdefaultprim").set(1) add_var = stage.createNode("addvariant") add_var.parm("primpath").set(self.primpath) in_count = 1 for var in variants: self.add_variant(var, config, add_var, in_count) in_count += 1 out_label = stage.createNode("null") out_label.setName(main_name + "_OUT", 1) out_label.setInput(0, add_var) #our asset is now assembled, and just needs to be published body = self.project.get_asset(main_name) if not body: qd.error("Error publishing asset " + main_name + ". Continuing to next asset.") return element = body.get_element(Asset.USD) element.update_app_ext(".usda") path = os.path.join(element._filepath, "temp.usda") rop = hou.node("/stage").createNode("usd_rop") rop.setInput(0, out_label) rop.parm("lopoutput").set(path) rop.parm("enableoutputprocessor_simplerelativepaths").set(0) rop.parm("execute").pressButton() stage.layoutChildren() comment = "Automatic publish" username = "******" name = main_name element.publish(username, path, comment, name) for child in stage.children(): child.destroy() def add_variant(self, var, config, add_var, in_count): stage = hou.node("/stage") ref1 = stage.createNode("reference") ref1.setName(var + "_geo", 1) ref1.parm("primpath").set(self.primpath) geo_path = self.getGeoPath(var) ref1.parm("filepath1").set(geo_path) disp = stage.createNode("rendergeometrysettings") disp.parm("xn__primvarsdisplacementboundsphere_control_n4br").set( "set") disp.parm("xn__primvarsdisplacementboundsphere_mrbr").set(1) disp.setInput(0, ref1) lib1 = stage.createNode("reference") lib1.setInput(0, disp) lib1.parm("primpath").set("/materials/") mat_path = self.getMatPath(var) lib1.parm("filepath1").set(mat_path) mat_asgn = stage.createNode("assignmaterial") mat_asgn.setInput(0, lib1) mat_asgn.parm("primpattern1").set(self.primpath) usd_stage = mat_asgn.stage() mat_prim = usd_stage.GetPrimAtPath("/materials") shader_path = mat_prim.GetChildren()[0].GetPath() #print("SHADER PATH: " + str(shader_path)) mat_asgn.parm("matspecpath1").set(str(shader_path)) label = stage.createNode("null") label.setName(var + "_OUT", 1) label.setInput(0, mat_asgn) graft = stage.createNode("graftstages") graft.setName(var, 1) graft.parm("primpath").set(self.primpath) graft.parm("destpath").set("/") graft.setInput(0, config) graft.setInput(1, label) add_var.setInput(in_count, graft) def getGeoPath(self, var): body = self.project.get_asset(var) if not body: body = self.project.create_asset(var) element = body.get_element(Asset.GEO) if element.get_last_version() >= 0: return element.get_last_publish()[3] else: #copy over the blank usda file src = self.project.get_project_dir() src = os.path.join(src, "blank.usda") dst = os.path.join(element._filepath, var + "_main.usda") shutil.copyfile(src, dst) pio.set_permissions(dst) return dst def getMatPath(self, var): body = self.project.get_asset(var) if not body: body = self.project.create_asset(var) element = body.get_element(Asset.MATERIALS) myPath = os.path.join(element._filepath, var + "_main.usda") if os.path.exists(myPath): return myPath else: #create and publish a basic material, return the path dst = os.path.join(element._filepath, var + "_main.usda") mat_lib = hou.node("/stage").createNode("materiallibrary") pink = mat_lib.createNode("usdpreviewsurface") pink.setName(var) pink.parm("diffuseColorr").set(.6) pink.parm("diffuseColorg").set(.6) pink.parm("diffuseColorb").set(.6) rop = hou.node("/stage").createNode("usd_rop") rop.setInput(0, mat_lib) rop.parm("lopoutput").set(dst) rop.parm("enableoutputprocessor_simplerelativepaths").set(0) rop.parm("execute").pressButton() mat_lib.destroy() rop.destroy() pio.set_permissions(dst) return dst
class AnimCloner: def __init__(self): self.project = Project() def clone(self): shot_list = self.project.list_existing_shots() self.item_gui = sfl.SelectFromList(l=shot_list, parent=hou.ui.mainQtWindow(), title="Select a shot to clone from") self.item_gui.submitted.connect(self.shot_results) def shot_results(self, value): self.shot_name = value[0] self.shot = self.project.get_shot(self.shot_name) element = self.shot.get_element(Asset.ANIMATION) asset_list = next(os.walk(element._filepath))[1] for name in asset_list: if name == "cache": asset_list.remove(name) asset_list.sort(key=unicode.lower) self.item_gui = sfl.SelectFromList(l=asset_list, parent=hou.ui.mainQtWindow(), title="Select an asset to clone") self.item_gui.submitted.connect(self.asset_results) def asset_results(self, value): self.asset_name = value[0] element = self.shot.get_element( os.path.join(Asset.ANIMATION, self.asset_name)) if element.get_last_version < 0: qd.error("There are no publishes for this asset in this shot.") return path = element.get_last_publish()[3] self.build_network(path) def build_network(self, path): animNode = hou.node("/obj").createNode("cenoteAnimation") animNode.setName(self.asset_name + "_anim", 1) animNode.parm("fileName").set(path) animNode.parm("scale").set(0.01) animNode.parm("buildHierarchy").pressButton() #animNode.parm("rendersubd").set(True) matPath = self.getMatPath() hdaPath = matPath.split(".")[0] + ".hda" if os.path.exists(hdaPath): hou.hda.installFile(hdaPath) for child in hou.node("/mat").children(): if child.type().name() == re.sub(r'\W+', '', self.asset_name): child.destroy() newMat = hou.node("/mat").createNode( re.sub(r'\W+', '', self.asset_name)) newMat.setName(self.asset_name, 1) newMat.setMaterialFlag(True) animNode.parm("materialPath").set("/mat/" + newMat.name()) else: qd.error( "The material for " + self.asset_name + " needs to be republished before it can be cloned in. Republish the material and try again." ) def getMatPath(self): asset = self.project.get_asset(self.asset_name) element = asset.get_element(Asset.MATERIALS) if element.get_last_version() < 0: return os.path.join(element._filepath, self.asset_name + "_main.usda") path = element.get_last_publish()[3] return path