class MatUpdater: def __init__(self): self.project = Project() def updateAll(self): obj = hou.node("/obj") mat = hou.node("/mat") for node in obj.allSubChildren(): if node.isMaterialManager(): for material in node.children(): self.updateOne(material) for node in mat.children(): self.updateOne(node) qd.message("Updated all materials") def updateOne(self, mat): assetList = self.project.list_assets() for asset in assetList: asset = re.sub(r'\W+', '', asset) typeName = mat.type().name() if typeName not in assetList: return #not a material from the pipe, move on if mat.isLockedHDA(): mat.allowEditingOfContents() mat.matchCurrentDefinition() mat.allowEditingOfContents() print(mat.name())
def go(self): project = Project() asset_list = project.list_assets() self.item_gui = sfl.SelectFromList(l=asset_list, parent=maya_main_window(), title="Select an asset to clone") self.item_gui.submitted.connect(self.results)
def export(self): project = Project() asset_list = project.list_assets() self.item_gui = sfl.SelectFromList( l=asset_list, parent=maya_main_window(), title="Select an asset to export to") self.item_gui.submitted.connect(passAlong)
class AssetPublisher: def __init__(self): self.project = Project() def publish(self): asset_list = self.project.list_assets() self.item_gui = sfl.SelectFromList( l=asset_list, parent=hou.ui.mainQtWindow(), title="Select an asset to publish") self.item_gui.submitted.connect(self.results) def results(self, value): self.asset_name = value[0] body = Project().get_asset(self.asset_name) if not body: body = self.project.create_asset(self.asset_name) if not body: qd.error("Something broke :'(") return self.element = body.get_element(Asset.USD) self.path = os.path.join(self.element._filepath, "temp.usda") selection = hou.selectedNodes() if len(selection) != 1: qd.error("Please select the last node in the network and try again.") return out = selection[0] rop = hou.node("/stage").createNode("usd_rop") rop.setInput(0, out) rop.parm("lopoutput").set(self.path) rop.parm("enableoutputprocessor_simplerelativepaths").set(0) rop.parm("execute").pressButton() rop.destroy() publishes = self.element.list_publishes() publishes_string_list = "" for publish in publishes: label = publish[0] + " " + publish[1] + " " + publish[2] + "\n" publishes_string_list += label self.input = qd.HoudiniInput(parent=hou.qt.mainWindow(), title="Comment ", info=publishes_string_list) self.input.submitted.connect(self.comment_results) def comment_results(self, value): comment = str(value) username = Environment().get_user().get_username() name = self.asset_name self.element.update_app_ext(".usda") self.element.publish(username, self.path, comment, name)
def publish_asset(self, solaris): ''' this is what's called when the button is pushed. ''' project = Project() asset_list = project.list_assets() self.item_gui = sfl.SelectFromList(l=asset_list, parent=hou.ui.mainQtWindow(), title="Select an asset to publish") # call asset results function here to be used once selected if solaris: self.item_gui.submitted.connect(self.solaris_asset_results) else: self.item_gui.submitted.connect(self.asset_results)
''' 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 MaterialPublisher: def __init__(self): self.project = Project() def publish(self): asset_list = self.project.list_assets() self.item_gui = sfl.SelectFromList(l=asset_list, parent=hou.ui.mainQtWindow(), title="Select an asset to publish") self.item_gui.submitted.connect(self.results) def results(self, value): self.asset_name = value[0] body = Project().get_asset(self.asset_name) if not body: body = self.project.create_asset(self.asset_name) if not body: qd.error("Something broke :'(") return self.element = body.get_element(Asset.MATERIALS) self.path = os.path.join(self.element._filepath, "temp.usda") selection = hou.selectedNodes() if len(selection) != 1: qd.error("Please select only the material node and try again.") return shader = selection[0] if shader.type().name == "materiallibrary": qd.error( "Changes have been made to this publishing tool. Now you must select the material node itself, NOT the material library, to publish it. Please try again." ) return #check where we are and move shader node accordingly deleteLib = False path = shader.path() first = path.split("/")[1] if first != "stage": lib = hou.node("/stage").createNode("materiallibrary") deleteLib = True shader = hou.copyNodesTo([shader], lib)[0] else: lib = shader.parent() lib.setInput(0, None) lib.parm("matpath1").set(value[0]) #create and save material hda if shader.canCreateDigitalAsset(): hdaPath = os.path.join(self.element._filepath, self.asset_name + "_main.hda") shader = shader.createDigitalAsset(name=re.sub( r'\W+', '', self.asset_name), description=self.asset_name, hda_file_name=hdaPath, min_num_inputs=0, max_num_inputs=0) shaderDef = shader.type().definition() shaderOptions = shaderDef.options() shaderOptions.setUnlockNewInstances(True) shaderOptions.setSaveInitialParmsAndContents(True) shaderDef.setOptions(shaderOptions) shaderDef.save(hdaPath, shader, shaderOptions) elif shader.type().name() == re.sub(r'\W+', '', self.asset_name): shader.type().definition().updateFromNode(shader) shader.type().definition().save( shader.type().definition().libraryFilePath()) else: qd.error("Error creating/saving hda. Continuing to save USDA...") shader.setName(value[0]) rop = hou.node("/stage").createNode("usd_rop") rop.setInput(0, lib) rop.parm("lopoutput").set(self.path) rop.parm("enableoutputprocessor_simplerelativepaths").set(0) rop.parm("execute").pressButton() rop.destroy() if deleteLib: lib.destroy() publishes = self.element.list_publishes() publishes_string_list = "" for publish in publishes: label = publish[0] + " " + publish[1] + " " + publish[2] + "\n" publishes_string_list += label self.input = qd.HoudiniInput(parent=hou.qt.mainWindow(), title="Comment ", info=publishes_string_list) self.input.submitted.connect(self.comment_results) def comment_results(self, value): comment = str(value) username = Environment().get_user().get_username() name = self.asset_name self.element.update_app_ext(".usda") self.element.publish(username, self.path, comment, name)
class ObjPublisher: def __init__(self): self.project = Project() def publish(self): asset_list = self.project.list_assets() self.item_gui = sfl.SelectFromList(l=asset_list, parent=hou.ui.mainQtWindow(), title="Select an asset to publish") self.item_gui.submitted.connect(self.results) def results(self, value): self.asset_name = value[0] body = Project().get_asset(self.asset_name) if not body: body = self.project.create_asset(self.asset_name) if not body: qd.error("Something broke :'(") return self.element = body.get_element(Asset.GEO) self.usdElem = body.get_element(Asset.GEO) path = self.element._filepath selectedNodes = hou.selectedNodes() if len(selectedNodes) != 1: qd.error("Select one node to publish its geometry") return geo = selectedNodes[0] if geo.type().name() != "geo": qd.error("You can only publish from geo nodes") return for child in geo.children(): if child.isDisplayFlagSet(): #print("hello there from " + child.name()) cache = geo.createNode("filecache") cache.setInput(0, child) usd = geo.createNode("usdexport") usd.setInput(0, child) cache.parm("filemode").set(2) cache.parm("file").set(os.path.join(path, "temp.obj")) cache.parm("trange").set(0) cache.parm("execute").pressButton() usd.parm("authortimesamples").set("Never") usd.parm("lopoutput").set(os.path.join(path, "temp.usda")) usd.parm("execute").pressButton() usd.destroy() cache.destroy() publishes = self.element.list_publishes() publishes_string_list = "" for publish in publishes: label = publish[0] + " " + publish[1] + " " + publish[ 2] + "\n" publishes_string_list += label self.input = qd.HoudiniInput(parent=hou.qt.mainWindow(), title="Comment ", info=publishes_string_list) self.input.submitted.connect(self.comment_results) def comment_results(self, value): comment = str(value) username = Environment().get_user().get_username() name = self.asset_name basePath = self.element._filepath #usdElem = self.element.deepcopy() path = os.path.join(basePath, "temp.obj") self.element.update_app_ext(".obj") self.element.publish(username, path, comment, name) path = os.path.join(basePath, "temp.usda") self.usdElem.update_app_ext(".usda") self.usdElem.publish(username, path, comment, name)
class Exporter: def __init__(self): pass def go(self, alembic=False, usd=False, obj=False, mb=False, camera=False): self.alembic = alembic self.usd = usd self.obj = obj self.mb = mb self.camera = camera self.project = Project() self.chosen_asset = None if self.camera and self.alembic: #previs publish case shot_list = self.project.list_shots() self.item_gui = sfl.SelectFromList( l=shot_list, parent=maya_main_window(), title="What shot is this camera in?") self.item_gui.submitted.connect(self.shot_results) else: asset_list = self.project.list_assets() self.item_gui = sfl.SelectFromList( l=asset_list, parent=maya_main_window(), title="Select an asset to export to") self.item_gui.submitted.connect(self.asset_results) def export(self): publish_info = [] if self.obj: #modeling publish case publish_info.append(ObjExporter().exportSelected( self.chosen_asset)) #self.publish(publish_info) if self.usd: #modeling publish case publish_info.append(USDExporter().exportSelected( self.chosen_asset)) self.publish(publish_info) if self.alembic: #animation publish case shot_list = self.project.list_shots() self.item_gui = sfl.SelectFromList( l=shot_list, parent=maya_main_window(), title="What shot is this animation in?") self.item_gui.submitted.connect(self.shot_results) if self.mb: #rigging publish case publish_info.append(MbExporter().export(self.chosen_asset)) self.publish(publish_info) def asset_results(self, value): self.chosen_asset = value[0] #check if asset already exists #if not, create it self.project.create_asset(name=self.chosen_asset) self.export() def shot_results(self, value): self.chosen_shot = value[0] print(self.chosen_shot) shot = self.project.create_shot(self.chosen_shot) #if the shot didn't exist already, set the frame range if shot is not None: pass else: print("we're here") shot = self.project.get_shot(self.chosen_shot) if shot is None: print("uh oh stinky") return #pre-vis publish publish_info = [] if self.camera: camera_num = int(shot.get_camera_number()) if camera_num == 1: #only one camera in the shot self.chosen_asset = "camera1" publish_info.append(AlembicExporter().exportSelected( asset_name=self.chosen_asset, shot_name=self.chosen_shot, camera=self.camera)) self.publish(publish_info) else: #pick which camera to publish cam_list = [] for number in range(1, camera_num + 1): camera_name = "camera" + str(number) cam_list.append(camera_name) self.item_gui = sfl.SelectFromList( l=cam_list, parent=maya_main_window(), title="Which camera are you publishing?") self.item_gui.submitted.connect(self.camera_results) #animation publish else: publish_info.append(AlembicExporter().exportSelected( asset_name=self.chosen_asset, shot_name=self.chosen_shot, camera=self.camera)) self.publish(publish_info) def camera_results(self, value): publish_info = [] self.chosen_asset = value[0] publish_info.append(AlembicExporter().exportSelected( asset_name=self.chosen_asset, shot_name=self.chosen_shot, camera=self.camera)) self.publish(publish_info) def publish(self, publishes): publish_info = publishes[0] element = publish_info[0] path = publish_info[1] self.publishes = element.list_publishes() publishes_string_list = "" for publish in self.publishes: label = publish[0] + " " + publish[1] + " " + publish[2] + "\n" publishes_string_list += label # get comment and update element file with publish info comment = qd.input(title="Comment for publish", label=publishes_string_list) if comment is None or comment == "": comment = "No comment." username = Environment().get_user().get_username() for pub_info in publishes: element = pub_info[0] path = pub_info[1] element.publish(username, path, comment, self.chosen_asset)
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