class AssetCloner: def __init__(self): self.project = Project() def clone(self): asset_list = self.project.list_assets_short() self.item_gui = sfl.SelectFromList(l=asset_list, parent=hou.ui.mainQtWindow(), title="Select an asset to clone") self.item_gui.submitted.connect(self.results) def results(self, value): print("Selected asset: " + value[0]) filename = value[0] self.body = Project().get_body(filename) self.element = self.body.get_element(Asset.USD) if self.element: path = self.element.get_last_publish()[3] if path: ref = hou.node("/stage").createNode("reference") ref.setName(filename + "_ref", 1) ref.parm("filepath1").set(path) ref.parm("primpath").set("/layout/" + filename) else: qd.error("Nothing was cloned")
def solaris_asset_results(self, value): self.asset_name = value[0] body = Project().get_asset(self.asset_name) if not body: body = 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()
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 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 getFilePath(self, name): asset = Project().get_asset(name) path = asset.get_filepath() path = os.path.join(path, Asset.RIG) self.element = asset.get_element(Asset.RIG) path = os.path.join(path, name) last_version = self.element.get_last_version() current_version = last_version + 1 path = path + "_v" + str(current_version).zfill(3) + ".mb" print(path) return path
class GeoCloner: def __init__(self): self.project = Project() def clone(self): asset_list = self.project.list_existing_assets() self.item_gui = sfl.SelectFromList(l=asset_list, parent=hou.ui.mainQtWindow(), title="Select an asset to clone") self.item_gui.submitted.connect(self.results) def results(self, value): print("Selected asset: " + value[0]) filename = value[0] self.body = Project().get_body(filename) self.element = self.body.get_element(Asset.GEO) if self.element: #just reference in the asset, make sure we're referencing the usda geo path = self.element.get_last_publish()[3] parts = path.split(".") path = parts[0] + ".usda" ref = hou.node("/stage").createNode("reference") ref.setName(filename + "_geo", 1) ref.parm("filepath1").set(path) #also clone into the geo context from the obj file parts = path.split(".") path = parts[0] + ".obj" geo = hou.node("/obj").createNode("geo") geo.setName(filename + "_geoRef", 1) geo.parm("scale").set(0.01) fileNode = geo.createNode("file") fileNode.parm("file").set(path) else: qd.error("Nothing was cloned")
class ShotCloner: 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") self.item_gui.submitted.connect(self.results) def results(self, value): print("Selected shot: " + value[0]) shot_name = value[0] self.body = Project().get_body(shot_name) self.element = self.body.get_element(Asset.HIP) if self.element.get_last_version() >= 0: #check if checked out if self.element.is_assigned(): assigned_user = self.element.get_assigned_user() username = Environment().get_user().get_username() if not assigned_user == username: qd.error("This shot is currently checked out by " + assigned_user) return else: username = Environment().get_user().get_username() self.element.update_assigned_user(username) path = self.element.get_last_publish()[3] if path: hou.hipFile.load(path) else: qd.error("Nothing was cloned")
class Publisher: def __init__(self): print("starting publisher") self.body = None self.fileName = None self.element = None def export_usd_files(): # TODO: export usd from the whole asset node tree to the asset folder (same as .body) pass # command necessary for publish_asset dialog box to load correctly def set_new_version_button_command(self, node, version_window): """ :param node: hou.Node :param version_window: VersionWindow :return: None """ library_filepath = node.type().definition().libraryFilePath() name_base = '::'.join(node.type().name().split('::')[:-1]) new_version = '{major}.{minor}.{revision}'.format( major=version_window.major_version.value(), minor=version_window.minor_version.value(), revision=version_window.revision_version.textFromValue( version_window.revision_version.value())) new_name = '{name_base}::{new_version}'.format(name_base=name_base, new_version=new_version) # Here we can compare the current version to new version and detect if the new version is lower or equal if not StrictVersion(new_version) > StrictVersion( node.type().nameComponents()[-1]): hou.ui.displayMessage( 'The version number is the same as the current version - please increase number' ) return # Create a pop up to give the user a chance to confirm or cancel answer = hou.ui.displayMessage( 'Creating a new version for {node_name}\nNew Version - {new_version}' .format(node_name=node.type().name(), new_version=new_version), title='Setting New Version', buttons=['OK', 'Cancel']) # If answer 'OK', create new version and set to latest version if answer == 0: node.type().definition().copyToHDAFile(library_filepath, new_name) all_definitions = hou.hda.definitionsInFile(library_filepath) node.changeNodeType(all_definitions[-1].nodeTypeName()) # Close version window 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) def solaris_asset_results(self, value): self.asset_name = value[0] body = Project().get_asset(self.asset_name) if not body: body = 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() def asset_comment(self, value): comment = value[0] username = Environment().get_user().get_username() self.element.publish(username, self.path, comment, self.asset_name) def asset_results(self, value): self.fileName = value[0] selection = hou.selectedNodes() # If it is more than one or none, abort if len(selection) != 1: qd.error( 'Please select a single Houdini Digital Asset node to save and update version on.' ) return # If it is not a Houdini Digital Asset, abort if not selection[0].type().definition(): qd.error( 'Please select a single Houdini Digital Asset node to save and update version on.' ) return #add code to force node name/node type name hda_node = selection[0] definition = hda_node.type().definition() libraryFilePath = definition.libraryFilePath() self.filepath = libraryFilePath '''current_full_name = hda_node.type().name() # last index is current version current_version_string = hda_node.type().nameComponents()[-1] #current_major = current_version_string.split('.')[0] #print('major version is ' + current_major) #current_minor = current_version_string.split('.')[1] # Set the 3 digit revision number to 0 if the HDA is only using the single float versioning (1.0 and not 1.0.005) current_revision = 0 if len(current_version_string.split( '.')) < 3 else current_version_string.split('.')[2] all_definitions = hou.hda.definitionsInFile(libraryFilePath) # This sets the node to the latest version of those stored hda_node.changeNodeType(all_definitions[-1].nodeTypeName())''' definition.updateFromNode(hda_node) self.body = Project().create_asset(self.fileName) if self.body is None: self.body = Project().get_asset(self.fileName) if self.body is None: print("Stephanie did an oopsie whoopsie :'(") return self.input = qd.HoudiniInput(parent=hou.qt.mainWindow(), title="Comment ") self.input.submitted.connect(self.comment_results) def comment_results(self, value): comment = str(value) path = os.path.join(self.body.get_filepath(), Asset.HDA) self.element = Element(path) username = Environment().get_user().get_username() name = self.fileName self.element.update_app_ext(".hda") self.element.publish(username, self.filepath, comment, name) # this bit will display the version info. Probably unneeded, as we'll be using element stuff instead. #f = open('/users/animation/martinje/Desktop/info.txt', 'r') #file_contents = f.read() # print(file_contents) # f.close() # qd.info(file_contents) # Instantiate the VersionWindow class - at this point, I would jump over to that code - keep in mind, we will # return a window object and afterwards we will set its initial state, using everything we just learned about # this HDA. #version_window = qd.VersionWindow(hou.qt.mainWindow()) #version_window.setWindowTitle('Versioning for: {hda_name}'.format(hda_name=current_full_name)) # version_window.current_version_label.setText(current_version_string) # version_window.current_path_label.setText(libraryFilePath) # Set value of the integer editor and set the editor to not go down from there # version_window.major_version.setValue(int(current_major)) # version_window.major_version.setMinimum(int(current_major)) # Set value of the integer editor and set the editor to not go down from there # version_window.minor_version.setValue(int(current_minor)) # version_window.minor_version.setMinimum(int(current_minor)) # Set value of the integer editor and set the editor to not go down from there # version_window.revision_version.setValue(int(current_revision)) # version_window.revision_version.setMinimum(int(current_revision)) # Connect the button signal to the set new version command and pass the hda node and the version window as arguments #version_window.set_version.clicked.connect(partial(self.set_new_version_button_command, hda_node, version_window)) # Show the window # version_window.show() def publish_tool(self): pass def publish_shot(self): ''' publishes shot (entire .hip file). Nothing needs to be selected for this to work. ''' scene = hou.hipFile.name() print('file name is ' + scene) project = Project() # get project and its shots asset_list = project.list_shots() self.item_gui = sfl.SelectFromList( l=asset_list, parent=hou.qt.mainWindow(), title="Select a shot to publish to, my friend.") self.item_gui.submitted.connect(self.shot_results) def shot_results(self, value): # chosen shot is the only asset in the list self.chosen_shot = value[0] self.comment = qd.HoudiniInput(parent=hou.qt.mainWindow(), title="Comments?") self.comment.submitted.connect(self.shot_comment) def shot_comment(self, value): # hou.hipFile.setName('newName_v01') #this will change the name of the file: can be versioned. So that's nice. comment = value if comment is None: comment = "Publish by " + \ str(user.get_username()) + \ '. Ask them to leave a comment next time lol' # FIXME: make variable more specific to shot? chosen_shot = self.chosen_shot project = Project() print('Selected shot name: ' + chosen_shot) # print(project.get_body(chosen_shot)) shot_body = project.create_shot(chosen_shot) if shot_body is None: shot_body = project.get_shot(chosen_shot) if shot_body is None: print("Something is horribly wrong. Talk to Stephanie") return filepath = shot_body.get_filepath() shot_element = shot_body.get_element("hip") shot_element.update_app_ext(".hip") prev_vers = shot_element.get_last_version() # path = os.path.abspath(inspect.getfile(project.get_body(chosen_shot))) #trying to get path here. filepath = os.path.join(shot_element._filepath, chosen_shot + ".hip") # print('file path is ', filepath) hou.hipFile.setName(filepath) src = hou.hipFile.save() # # hou.hipFile.saveAndIncrementFileName() #this actually works! Dunno if I want to use it though. # # #Publish user = Environment().get_user() pipeline_io.set_permissions(src) # try that asset name is body name. dst = self.publish_element(shot_element, user, filepath, comment) #pipeline_io.set_permissions(dst) # # message = "Successfully published " + str(self.body.get_name()) + "!" # self.print_success_message(message) def publish_element(self, element, user, src, comment="None"): print('username is', user.get_username()) dst = element.publish(user.get_username(), src, comment, self.chosen_shot) # Ensure file has correct permissions # Permissions are actually taken care of as part of the element.publish() function, so this isn't necessary '''try: os.chmod(dst, 0660) except Exception as e: print("Error setting file permissions: " + str(e))''' return dst def publish_layout(self): if len(hou.selectedNodes()) != 1: qd.error("Select only the last node in the network") return layout_list = Project().list_layouts() self.item_gui = sfl.SelectFromList( l=layout_list, parent=hou.qt.mainWindow(), title="Which layout are you publishing?") self.item_gui.submitted.connect(self.layout_results) def layout_results(self, value): self.layout_name = value[0] self.layout = Project().get_layout(self.layout_name) if self.layout is None: self.layout = Project().create_layout(self.layout_name) if self.layout is None: qd.error("Stephanie done messed up") return self.element = self.layout.get_element(Asset.LAYOUT) # make a USD ROP node rop = hou.node("/stage").createNode("usd_rop") # connect the selected node to the ROP out = hou.selectedNodes()[0] rop.setInput(0, out) # set the necessary values in the ROP self.savePath = os.path.join(self.element._filepath, self.layout_name + ".usda") rop.parm("lopoutput").set(self.savePath) rop.parm("enableoutputprocessor_simplerelativepaths").set(0) # save to disk rop.parm("execute").pressButton() #add attributes to stage reqired for proper unpacking later self.create_attributes(out) # publish :) self.comment = qd.HoudiniInput(parent=hou.qt.mainWindow(), title="Comment for publish?") self.comment.submitted.connect(self.layout_comment) def create_attributes(self, node): stage = Usd.Stage.Open(self.savePath) node_list = [] node_list = self.listInputs(node, node_list) for n in node_list: #create a ref_path attribute for each reference in the stage '''if n.type().name() == "reference": prim = stage.GetPrimAtPath(n.parm("primpath").eval()) if prim.IsValid(): path = prim.CreateAttribute("ref_path", Sdf.ValueTypeNames.String) path.Set(n.parm("filepath1").eval()) else: print("uh oh")''' #create a hda_path attribute for each material in the stage if n.type().name() == "materiallibrary": mats = n.children() for mat in mats: if mat.type().definition(): print(mat.type().definition().libraryFilePath()) prim = stage.GetPrimAtPath( n.parm("matpathprefix").eval() + mat.name()) if prim.IsValid(): path = prim.CreateAttribute( "hda_path", Sdf.ValueTypeNames.String) path.Set(mat.type().definition().libraryFilePath()) else: print("hmmmmmmmqow;ugh") else: #send error message qd.error( "Material " + mat.name() + " is not an HDA and won't load properly in the scene." ) stage.Save() def listInputs(self, n, list): list.append(n) inputs = n.inputs() for input in inputs: if input is not None: blank = [] list.extend(self.listInputs(input, blank)) return list def layout_comment(self, value): comment = value[0] username = Environment().get_user().get_username() self.element.update_app_ext(".usda") self.element.publish(username, self.savePath, comment, self.layout_name) if self.element.get_last_version() == 0: # if it is the first publish, we have to make the referencing file as well # create a reference node ref = hou.node("/stage").createNode("reference") # set the values to reference the main publish file, etc. ref.parm("primpath").set("/layout") ref.parm("filepath1").set(self.element.get_last_publish()[3]) # create a USD ROP node and connect it to the ref node refrop = hou.node("/stage").createNode("usd_rop") refrop.setInput(0, ref) # set the values in the ROP and save to disk alongside the main publish refrop.parm("lopoutput").set( os.path.join(self.element._filepath, self.layout_name + "_ref.usda")) refrop.parm("enableoutputprocessor_simplerelativepaths").set(0) refrop.parm("execute").pressButton() # this only needs to be done once since with every new publish, the file being referenced gets updated ref.destroy() refrop.destroy()
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)
class LayoutPublisher: def __init__(self): self.project = Project() def publish(self): if len(hou.selectedNodes()) != 1: qd.error("Select only the last node in the network") return layout_list = Project().list_layouts() self.item_gui = sfl.SelectFromList(l=layout_list, parent=hou.qt.mainWindow(), title="Which layout are you publishing?") self.item_gui.submitted.connect(self.results) def results(self, value): self.layout_name = value[0] self.layout = self.project.get_layout(self.layout_name) if self.layout is None: self.layout = Project().create_layout(self.layout_name) if self.layout is None: qd.error("Stephanie done messed up") return self.element = self.layout.get_element(Asset.LAYOUT) rop = hou.node("/stage").createNode("usd_rop") out = hou.selectedNodes()[0] rop.setInput(0, out) self.savePath = os.path.join(self.element._filepath, self.layout_name + ".usda") rop.parm("lopoutput").set(self.savePath) 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.comment = qd.HoudiniInput( parent=hou.qt.mainWindow(), title="Comment for publish?", info=publishes_string_list) self.comment.submitted.connect(self.comment_results) def comment_results(self, value): comment = str(value) username = Environment().get_user().get_username() self.element.update_app_ext(".usda") self.element.publish(username, self.savePath, comment, self.layout_name) if self.element.get_last_version() == 0: # if it is the first publish, we have to make the referencing file as well # create a reference node ref = hou.node("/stage").createNode("reference") # set the values to reference the main publish file, etc. ref.parm("primpath").set("/layout") ref.parm("filepath1").set(self.element.get_last_publish()[3]) # create a USD ROP node and connect it to the ref node refrop = hou.node("/stage").createNode("usd_rop") refrop.setInput(0, ref) # set the values in the ROP and save to disk alongside the main publish refrop.parm("lopoutput").set(os.path.join(self.element._filepath, self.layout_name + "_ref.usda")) refrop.parm("enableoutputprocessor_simplerelativepaths").set(0) refrop.parm("execute").pressButton() pio.set_permissions(os.path.join(self.element._filepath, self.layout_name + "_ref.usda")) # this only needs to be done once since with every new publish, the file being referenced gets updated ref.destroy() refrop.destroy()
class BuildShot: def __init__(self): self.project = Project() def build(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") self.item_gui.submitted.connect(self.results) def results(self, value): self.shot_name = value[0] self.shotBody = Project().get_body(self.shot_name) camElement = self.shotBody.get_element(Asset.CAMERA) asset_list = next(os.walk(camElement._filepath))[1] for name in asset_list: if name == "cache": asset_list.remove(name) asset_list.sort(key=unicode.lower) if len(asset_list) < 1: qd.error( "There is no camera for this shot, so it cannot be built. Quitting build for shot " + self.shot_name + "...") elif len(asset_list) == 1: self.camResults(asset_list) else: self.item_gui = sfl.SelectFromList( l=asset_list, parent=hou.ui.mainQtWindow(), title="Select a camera to clone") self.item_gui.submitted.connect(self.camera_results) def camResults(self, value): camName = value[0] self.camElement = self.shotBody.get_element( os.path.join(Asset.CAMERA, camName)) options = ["Animation", "Layout", "Lights", "FX"] valueGui = qd.CheckboxSelect( text="Select what to import from this shot", options=options, parent=hou.ui.mainQtWindow(), title="Shot Build Settings") valueGui.submitted.connect(self.options_results) def options_results(self, options): '''for op in options: print(op)''' anim = options[0] layout = options[1] lights = options[2] fx = options[3] isCamera = self.get_camera() if not isCamera: return if anim: isAnim = self.get_all_anim() if not isAnim: qd.message( "There is no animation published for this shot. Continuing to build shot..." ) if layout: isLayout = self.get_layout() if not isLayout: qd.message( "Couldn't clone the layout for this shot. Continuing to build shot..." ) self.sequence_name = self.shot_name[:1] self.sequence = self.project.get_sequence(self.sequence_name) if lights: isLights = self.get_lights() if not isLights: qd.message( "Couldn't clone sequence lighting. Continuing to build shot..." ) if fx: self.get_fx() hou.node("/obj").layoutChildren() self.build_render() def get_camera(self): if self.camElement.get_last_version < 0: qd.error( "There is no camera for this shot, so it cannot be built. Quitting build for shot " + self.shot_name + "...") return False try: path = self.camElement.get_last_publish()[3] cameraNode = hou.node("/obj").createNode("cenoteCamera") cameraNode.setName(self.shot_name + "_camera", 1) cameraNode.parm("fileName").set(path) cameraNode.parm("scale").set(0.01) cameraNode.parm("buildHierarchy").pressButton() return True except Exception as e: print(e) return False def get_all_anim(self): animElement = self.shotBody.get_element(Asset.ANIMATION) asset_list = next(os.walk(animElement._filepath))[1] for name in asset_list: if name == "cache": asset_list.remove(name) asset_list.sort(key=unicode.lower) if len(asset_list) < 1: return False for asset in asset_list: self.get_anim(asset) return True def get_anim(self, asset): element = self.shotBody.get_element( os.path.join(Asset.ANIMATION, asset)) if element.get_last_version() < 0: return False try: path = element.get_last_publish()[3] anim_cloner = AnimCloner() anim_cloner.asset_name = asset anim_cloner.build_network(path) return True except Exception as e: print(e) return False def get_layout(self): layout_element = self.shotBody.get_element(Asset.LAYOUT) path = os.path.join(layout_element._filepath, self.shot_name + ".usda") if not os.path.exists(path): print("Layout path doesn't exist") return False try: layoutUnpacker = LayoutUnpacker() layoutUnpacker.shot_name = self.shot_name layoutUnpacker.unpack(path) return True except Exception as e: print(e) return False def get_lights(self): lightElement = self.sequence.get_element(Asset.LIGHTS) if lightElement.get_last_version() < 0: return False path = lightElement.get_last_publish()[3] hou.hda.installFile(path) try: hda = hou.node("/obj").createNode("sequence_" + self.sequence_name + "_lights") except Exception as e: #qd.error("Couldn't create node of type " + name + ". You should still be able to tab in the node manually.") print(e) return False try: hda.setName(self.sequence_name + "_sequence_lights", 1) except: pass try: hda.allowEditOfContents() except: pass return True def get_fx(self): fxElement = self.sequence.get_element(Asset.HDA) fx_list = next(os.walk(fxElement._filepath))[1] for name in fx_list: if name == "cache": fx_list.remove(name) fx_list.sort(key=unicode.lower) for fx in fx_list: self.get_one_fx(fx) def get_one_fx(self, fx): element = self.sequence.get_element(os.path.join(Asset.HDA, fx)) if element.get_last_version() < 0: return filepath = element.get_last_publish()[3] try: hou.hda.installFile(filepath) except Exception as e: print(e) return try: hda = hou.node("/obj").createNode(fx) except Exception as e: qd.error("Couldn't create node of type " + fx + ". You should still be able to tab in the node manually.") try: hda.setName(fx, 1) except: pass try: hda.allowEditOfContents() except: pass def build_render(self): ris = hou.node("/out").createNode("cenote_layered_render") ris.parm("frame1").set(1) ris.parm("frame2").set(self.shotBody.get_frame_range()) ris.parm("frame3").set(2) selected = None root = hou.node('/') camera_nodes = root.recursiveGlob('*', hou.nodeTypeFilter.ObjCamera) for cam in camera_nodes: if "shot" in cam.name(): selected = cam if not selected: qd.error( "Error selecting camera for render. Will need to be done manually." ) else: ris.parm("camera").set(selected.path()) layers = self.build_layer_string() print(layers) ris.parm("render_layers").set(layers) ris.parm("build_rops").pressButton() for node in ris.children(): if node.type().name() == "tractorsubmit_main": node.parm("job_title").set(self.shot_name + "_Test_Render") else: node.parm("override_camerares").set(True) old = node.parm("ri_display_0").unexpandedString() new = old.replace("render", "testRender") node.parm("ri_display_0").set(new) def build_layer_string(self): first = "" second = "" third = "" total = "" for node in hou.node("/obj").children(): if node.type().name() == "cenoteAnimation": first = first + "[ " + node.name() + " ] " elif node.type().name() == "cenoteLayoutNet": third = third + node.name() + " " elif node.type().name( ) != "cenoteCamera" and not "sequence_lights" in node.name(): second = second + node.name() + " " if len(first) > 0: total = total + first if len(second) > 0: total = total + "[ " + second + "] " if len(third) > 0: total = total + "[ " + third + "]" return total
class MaterialCloner: def __init__(self): self.project = Project() def clone(self): asset_list = self.project.list_existing_assets() self.item_gui = sfl.SelectFromList( l=asset_list, parent=hou.ui.mainQtWindow(), title="Select an asset's material to clone") self.item_gui.submitted.connect(self.results) def results(self, value): print("Selected asset: " + value[0]) filename = value[0] self.body = Project().get_body(filename) self.element = self.body.get_element(Asset.MATERIALS) if self.element.get_last_version() >= 0: path = self.element.get_last_publish()[3] if path: createNewRef = True for child in hou.node("/stage").children(): if child.name( ) == filename + "_material_ref" and child.parm( "filepath1").eval() == path: child.parm("reload").pressButton() createNewRef = False if createNewRef: ref = hou.node("/stage").createNode("reference") ref.setName(filename + "_material_ref", 1) ref.parm("filepath1").set(path) ref.parm("primpath").set("/materials/") panes = self.getCurrentNetworkEditorPane() paths = [] for pane in panes: paths.append(pane.pwd()) hdaPath = path.split(".")[0] + ".hda" hou.hda.installFile(hdaPath) success = False for p in paths: try: for child in p.children(): if child.type().name() == re.sub( r'\W+', '', filename): child.destroy() newMat = p.createNode(re.sub(r'\W+', '', filename)) newMat.setName(filename, 1) newMat.setMaterialFlag(True) success = True except: pass if not success: for child in hou.node("/mat").children(): if child.type().name() == re.sub(r'\W+', '', filename): child.destroy() newMat = hou.node("/mat").createNode( re.sub(r'\W+', '', filename)) newMat.setName(filename, 1) newMat.setMaterialFlag(True) qd.message( "Material successfully cloned into /mat context.") else: qd.error("Nothing was cloned") def getCurrentNetworkEditorPane(self): editors = [ pane for pane in hou.ui.paneTabs() if isinstance(pane, hou.NetworkEditor) and pane.isCurrentTab() ] return editors
class AlembicExporter: def __init__(self, frame_range=1): self.frame_range = frame_range pm.loadPlugin("AbcExport") def asset_results(self, value): chosen_asset = value[0] print(chosen_asset) def exportSelected(self, asset_name, shot_name, camera=False): self.shot_name = shot_name self.shot = Project().get_shot(shot_name) if self.shot is None: return None start_frame = 0 frame_range = str(self.shot.get_frame_range()) #This means there's been no cameras even published for this shot but they're trying to save an animation. shouldn't ever happen if int(frame_range) == 0 and not camera: qd.error("How are you publishing without a camera yet? Get that done, bestie.") return #if this is previs we need to know where to move the keyframes to if camera: #ask the artist what frame the shot starts at and make sure that's a valid input start_frame = qd.input("Enter the starting frame for this shot") if start_frame is None or start_frame == u'': qd.error("Invalid frame range. Try publishing again.") return start_frame = str(start_frame) if not start_frame.isdigit(): qd.error("Invalid frame range. Try publishing again.") return #ask the artist for the last frame and make sure that's valid input #we'll do this every time in case the length of the shot changes end_frame = qd.input("Enter the last frame for this shot") if end_frame is None or end_frame == u'': qd.error("Invalid frame range. Try publishing again.") return end_frame = str(end_frame) if not end_frame.isdigit(): qd.error("Invalid frame range. Try publishing again.") return #calculate the frame-range and save it to the shot's .body file frame_range = int(end_frame) - int(start_frame) + 1 self.shot.set_frame_range(frame_range) #now move the keyframes and build the command timeChange = int(start_frame) - 1 anim_curves = mc.ls(type=['animCurveTA', 'animCurveTL', 'animCurveTT', 'animCurveTU']) for each in anim_curves: mc.keyframe(each, edit=True, relative=True, timeChange=-timeChange) path = self.getCameraPath(asset_name) command = self.buildAlembicCommand(path, uv=False) else: path = self.getFilePath(asset_name) command = self.buildAlembicCommand(path) cont = qd.yes_or_no("This asset is about to be saved with " + str(frame_range) + " frames. Is that correct?") if not cont: qd.error("Nothing was published.") return pm.Mel.eval(command) #now move the keyframes back for previs if camera: timeChange = int(start_frame) - 1 anim_curves = mc.ls(type=['animCurveTA', 'animCurveTL', 'animCurveTT', 'animCurveTU']) for each in anim_curves: mc.keyframe(each, edit=True, relative=True, timeChange=timeChange) publish_info = [self.element, path] return publish_info def buildAlembicCommand(self, path, uv=True): #get selected nodes selected = mc.ls(sl=True,long=True) nodes = "" for node in selected: nodes += node nodes += " " frame_range = str(self.shot.get_frame_range()) options = "-frameRange -48 " + frame_range if uv: options += " -uvWrite -writeUVSets" options += " -worldSpace -dataFormat ogawa -root " + nodes + "-file " + path command = "AbcExport -verbose -j \"" + options +"\"" print(command) return command def getFilePath(self, asset_name): path = self.shot.get_filepath() dept = os.path.join(Asset.ANIMATION, asset_name) #this is to make it so we can keep track of the versions of animations for each asset path = os.path.join(path, dept) #try to create the element if it doesn't exist self.element = self.shot.create_element(dept, Element.DEFAULT_NAME) #retrieve it if it does already if self.element is None: self.element = self.shot.get_element(dept) self.element.update_app_ext(".abc") path = os.path.join(path, asset_name) last_version = self.element.get_last_version() current_version = last_version + 1 path = path + "_v" + str(current_version).zfill(3) + ".abc" print(path) return path def getCameraPath(self, camera_name): path = self.shot.get_filepath() dept = os.path.join(Asset.CAMERA, camera_name) #this is to make it so we can keep track of the versions of animations for each camera path = os.path.join(path, dept) #try to create the element if it doesn't exist self.element = self.shot.create_element(dept, Element.DEFAULT_NAME) #retrieve it if it does already if self.element is None: self.element = self.shot.get_element(dept) self.element.update_app_ext(".abc") path = os.path.join(path, camera_name) last_version = self.element.get_last_version() current_version = last_version + 1 path = path + "_v" + str(current_version).zfill(3) + ".abc" print(path) return path