def update_contents_geo(node, asset_name, excluded_departments=[], mode=UpdateModes.SMART): # Set up the body/elements and make sure it's a character. Just do some simple error checking. body = Project().get_body(asset_name) if body is None: error_message("Asset doesn't exist.") return None if not body.is_asset() or body.get_type() == AssetType.SET or "byu_geo" not in node.type().name(): error_message("Must be a prop or character.") return None # Get interior nodes importnode = node.node("import") inside = node.node("inside") # Set the asset_name and reload if node.parm("asset_name").evalAsString() != asset_name: node.parm("asset_name").set(asset_name) importnode.parm("reload").pressButton() # Tab in each content HDA based on department for department in this.byu_geo_departments: # If the department is not excluded, tab-in/update the content node like normal if department not in excluded_departments: update_content_node(node, inside, asset_name, department, mode, inherit_parameters = department == Department.MODIFY) # If the department is excluded, we should delete it. elif mode == UpdateModes.CLEAN: destroy_if_there(inside, department) inside.layoutChildren() return node
def byu_geo(parent, asset_name, already_tabbed_in_node=None, excluded_departments=[], character=False, mode=UpdateModes.CLEAN): # Set up the body/elements and check if it's an asset. body = Project().get_body(asset_name) if not body.is_asset(): error_message("Must be an asset.") return None # Set up the nodes, name geo node = already_tabbed_in_node if already_tabbed_in_node else parent.createNode("byu_geo") if character: node.setName("geo") else: try: node.setName(asset_name.title()) except: node.setName(asset_name.title() + "_1", unique_name=True) # Set the asset_name data tag data = node.parm("data").evalAsJSONMap() data["asset_name"] = asset_name node.parm("data").set(data) # Set the contents to the nodes that belong to the asset update_contents_geo(node, asset_name, excluded_departments, mode) return node
def update_contents_character(node, asset_name, excluded_departments=[], mode=UpdateModes.SMART, shot=None): ##super_print("{0}() line {1}:\n\tcharacter: {2}\n\tmode: {3}".format(method_name(), lineno(), asset_name, mode)) # Set up the body/elements and make sure it's a character. Just do some simple error checking. body = Project().get_body(asset_name) if not body.is_asset() or body.get_type() != AssetType.CHARACTER or "byu_character" not in node.type().name(): error_message("Must be a character.") return None # Reset the data parm data = node.parm("data").evalAsJSONMap() data["asset_name"] = asset_name node.parm("data").set(data) inside = node.node("inside") # Make sure the geo is set correctly geo = inside.node("geo") if geo is not None: if mode == UpdateModes.SMART: update_contents_geo(geo, asset_name, excluded_departments, mode) elif mode == UpdateModes.CLEAN: geo.destroy() geo = byu_geo(inside, asset_name, excluded_departments=excluded_departments, character=True) else: geo = byu_geo(inside, asset_name, excluded_departments=excluded_departments, character=True) # Tab in each content HDA based on department for department in this.byu_character_departments: # If the department is not excluded, tab-in/update the content node like normal if department not in excluded_departments: update_content_node(node, inside, asset_name, department, mode) # If the department is excluded, we should delete it. elif mode == UpdateModes.CLEAN: destroy_if_there(inside, department) inside.layoutChildren() geo.parm("version_number").setExpression("ch(\"../../version_number\")", language=hou.exprLanguage.Hscript) # If this character is being animated, set parms accordingly if shot is not None: geo.parm("space").set("anim") geo.parm("asset_department").set("rig") geo.parm("shot").set(shot) return node
def publish_submitted(value): body = Project().get_body(value) if body.is_asset(): if body.get_type() == AssetType.SET: confirmWriteSetReferences(body) elif body.get_type() == AssetType.PROP: confirmWritePropReference(body) else: print("No JSON exported because this is a character.") elif body.is_shot(): confirmWriteShotReferences(body) else: message_gui.error("Not a valid body.")
def subnet_type(asset_name): body = Project().get_body(asset_name) if body is None or not body.is_asset(): error_message("Pipeline error: This asset either doesn't exist or isn't an asset.") return if body.get_type() == AssetType.CHARACTER: return "byu_character" elif body.get_type() == AssetType.PROP: return "byu_geo" elif body.get_type() == AssetType.SET: return "byu_set" else: error_message("Pipeline error: this asset isn't a character, prop or set.") return
def byu_set(parent, set_name, already_tabbed_in_node=False, mode=UpdateModes.CLEAN): # Check if it's a set and that it exists body = Project().get_body(set_name) if not body.is_asset() or not body.get_type() == AssetType.SET: error_message("Must be a set.") node = already_tabbed_in_node if already_tabbed_in_node else parent.createNode("byu_set") try: node.setName(set_name) except: node.setName(set_name + "_1", unique_name=True) # Update contents in the set update_contents_set(node, set_name, mode) return node
def tab_in(parent, asset_name, already_tabbed_in_node=None, excluded_departments=[]): print "Creating node for {0}".format(asset_name) body = Project().get_body(asset_name) if body is None or not body.is_asset(): error_message("Pipeline error: This asset either doesn't exist or isn't an asset.") return if body.get_type() == AssetType.CHARACTER: return byu_character(parent, asset_name, already_tabbed_in_node, excluded_departments) elif body.get_type() == AssetType.PROP: return byu_geo(parent, asset_name, already_tabbed_in_node, excluded_departments) elif body.get_type() == AssetType.SET: return byu_set(parent, asset_name, already_tabbed_in_node) else: error_message("Pipeline error: this asset isn't a character, prop or set.") return
def publishElement(element, user, src, comment): dst = element.publish(user, src, comment) #Ensure file has correct permissions try: os.chmod(dst, 0660) except: pass #freeze transformations and clear history if maya_publish_dialog.clearHistoryCheckbox.isChecked(): clear_construction_history() try: freeze_transformations() except: freeze_error_msg = ("Failed to freeze transformations, probably because " "there are one or more keyframed values in your object. Remove all " "keyframed values and expressions from your object and try again.") cmds.confirmDialog(title="Freeze Transformations Error", message=freeze_error_msg) print(freeze_error_msg) #Export a playblast print 'TODO: export playblast' print element.get_name() #Export Alembics print 'Publish Complete. Begin Exporting Alembic, or JSON if set' body = Project().get_body(element.get_parent()) try: alembic_exporter.go(element=element) except: print("alembic export failed.") if body and body.is_asset(): json_exporter.go(body, body.get_type()) else: json_exporter.go(body, type="shot") noEducationalLicence()
def byu_character(parent, asset_name, already_tabbed_in_node=None, excluded_departments=[], mode=UpdateModes.CLEAN, shot=None): # Set up the body/elements and make sure it's a character body = Project().get_body(asset_name) if not body.is_asset() or not body.get_type() == AssetType.CHARACTER: error_message("Must be a character.") return None # If there's an already tabbed in node, set it to that node node = already_tabbed_in_node if already_tabbed_in_node else parent.createNode("byu_character") try: node.setName(asset_name.title()) except: node.setName(asset_name.title() + "_1", unique_name=True) node.parm("asset_name").set(asset_name) # Set the asset_name data tag data = node.parm("data").evalAsJSONMap() data["asset_name"] = asset_name node.parm("data").set(data) # Set the contents to the character's nodes update_contents_character(node, asset_name, excluded_departments, mode, shot) return node
def exportPropJSON(filePath, rootNode, isReference=True, name="", version_number=None): if isReference: name, version_number = getReferenceName(rootNode) body = Project().get_body(name) if not body or not body.is_asset() or body.get_type() != AssetType.PROP: print "The asset %s does not exist as a prop, skipping.".format(name) return None # Check if verNum is nothing - if so, we need to make it be an int 0 if not version_number: version_number = 0 def strip_reference(input): i = input.rfind(":") if i == -1: return input return input[i + 1:] firstMesh = None path = "" stack = [] stack.append(rootNode) while len(stack) > 0 and firstMesh is None: curr = stack.pop() path = path + "/" + strip_reference(curr.name()) for child in curr.getChildren(): if isinstance(child, pm.nodetypes.Shape): firstMesh = child path = path + "/" + strip_reference(child.name()) break elif not isinstance(child, pm.nodetypes.Transform): continue if child.getShape() is not None: firstMesh = child.getShape() path = path + "/" + strip_reference( child.name()) + "/" + strip_reference( child.getShape().name()) break for child in curr.getChildren(): stack.append(child) verts = firstMesh.vtx vertpos1 = verts[0].getPosition(space='world') vertpos2 = verts[1].getPosition(space='world') vertpos3 = verts[2].getPosition(space='world') # Put all relevant data into dictionary object json_data = { "asset_name": name, "version_number": version_number, "path": path, "a": [vertpos1.x, vertpos1.y, vertpos1.z], "b": [vertpos2.x, vertpos2.y, vertpos2.z], "c": [vertpos3.x, vertpos3.y, vertpos3.z] } # Write JSON to fill jsonRef = json.dumps(json_data) wholePath = os.path.join( filePath, os.path.join(filePath, name + "_" + str(version_number) + ".json")) outfile = open(wholePath, "w") # *** THIS IS THE NAME OF THE OUTPUT FILE *** outfile.write(jsonRef) outfile.close() if not isReference: showSuccessPopup() return { "asset_name": json_data["asset_name"], "version_number": json_data["version_number"] }
def export_shot(filePath): refsSelection = getLoadedReferences() props = [] characters = [] sets = [] for ref in refsSelection: refPath = pm.referenceQuery(unicode(ref), filename=True) refNodes = pm.referenceQuery(unicode(refPath), nodes=True) rootNode = pm.ls(refNodes[0])[0] currRefName, currRefVerNum = getReferenceName(rootNode) body = Project().get_body(currRefName) if not body or not body.is_asset(): print "Asset \"{0}\" does not exist.".format(currRefName) continue if body.get_type() == AssetType.PROP: props.append({ "asset_name": currRefName, "version_number": int(currRefVerNum if len(currRefVerNum) > 0 else 0) }) elif body.get_type() == AssetType.CHARACTER: characters.append({ "asset_name": currRefName, "version_number": int(currRefVerNum if len(currRefVerNum) > 0 else 0) }) else: parent_is_set = False parent_node = rootNode.getParent() while parent_node is not None: asset_name, _ = getReferenceName(parent_node) parent_body = Project().get_body(asset_name) if parent_body is not None and parent_body.is_asset( ) and parent_body.get_type() == AssetType.SET: parent_is_set = True break parent_node = parent_node.parent_node() if parent_is_set: continue sets.append({ "asset_name": currRefName, "version_number": int(currRefVerNum if len(currRefVerNum) > 0 else 0) }) print "props: {0}\ncharacters: {1}\nsets: {2}".format( props, characters, sets) jsonCharacters = json.dumps(characters) path = os.path.join(filePath, "characters.json") with open(path, "w") as f: f.write(jsonCharacters) f.close() jsonSets = json.dumps(sets) path = os.path.join(filePath, "sets.json") with open(path, "w") as f: f.write(jsonSets) f.close() response = showAnimatedPropPopup() if response == "No": showSuccessPopup() return global select_from_list_dialog def write_animated_props(): animated_props = select_from_list_dialog.animated_props print "writing animated props: {0}".format(animated_props) animated_prop_jsons = [] for animated_prop in animated_props: animated_prop_name = animated_prop.split(", version")[0] animated_prop_number = animated_prop.split(", version")[1] animated_prop_jsons.append({ "asset_name": animated_prop_name, "version_number": animated_prop_number, "animated": True }) if len(animated_prop_jsons) < 1: return jsonAnimatedProps = json.dumps(animated_prop_jsons) path = os.path.join(filePath, "animated_props.json") with open(path, "w") as f: f.write(jsonAnimatedProps) f.close() showSuccessPopup() select_from_list_dialog = SelectFromList(parent=maya_main_window(), multiple_selection=True) select_from_list_dialog.setWindowTitle("Select any animated props") props_and_nums = [ prop["asset_name"] + ", version: " + str(prop["version_number"]) for prop in props ] select_from_list_dialog.setList(props_and_nums) select_from_list_dialog.filePath = filePath select_from_list_dialog.selected_list.connect(write_animated_props) select_from_list_dialog.show()
def create_hda(asset_name, department, already_tabbed_in_node=None): # Check if this body is an asset. If not, return error. body = Project().get_body(asset_name) if not body.is_asset(): error_message("Must be an asset of type PROP or CHARACTER.") return None # Check if it is a set. if body.get_type() == AssetType.SET: error_message("Asset must be a PROP or CHARACTER.") return None # Check if the user is trying to create a Hair or Cloth asset for a Prop on accident. if body.get_type() == AssetType.PROP and (department == Department.HAIR or department == Department.CLOTH): error_message("Hair and cloth should only be made for characters.") return None # Create element if does not exist. element = body.get_element(department, name=Element.DEFAULT_NAME, force_create=True) # TODO: Get rid of this ugly hotfix # !!! HOTFIX !!! # Material was previously used as an AssetElement, but now is being treated like an HDAElement. # This will convert it's file extension to .hdanc. (Before, it's extension was ""). element._datadict[Element.APP_EXT] = element.create_new_dict(Element.DEFAULT_NAME, department, asset_name)[Element.APP_EXT] element._update_pipeline_file() # !!! END HOTFIX !!! # Check out the department. username = Project().get_current_username() checkout_file = element.checkout(username) # Tab in the parent asset that will hold this checked out HDA node = already_tabbed_in_node if already_tabbed_in_node else tab_in(hou.node("/obj"), asset_name, excluded_departments=[department]) # If it's a character and it's not a hair or cloth asset, we need to reach one level deeper. if body.get_type() == AssetType.CHARACTER and department not in this.byu_character_departments: inside = node.node("inside/geo/inside") else: inside = node.node("inside") # CREATE NEW HDA DEFINITION operator_name = element.get_parent() + "_" + element.get_department() operator_label = (asset_name.replace("_", " ") + " " + element.get_department()).title() this.hda_definitions[department].copyToHDAFile(checkout_file, operator_name, operator_label) hda_type = hou.objNodeTypeCategory() if department in this.byu_character_departments else hou.sopNodeTypeCategory() hou.hda.installFile(checkout_file) hda_definition = hou.hdaDefinition(hda_type, operator_name, checkout_file) hda_definition.setPreferred(True) # Tab an instance of this new HDA into the asset you are working on try: hda_instance = inside.createNode(asset_name + "_" + department) print('noce') except Exception as e: error_message("HDA Creation Error. " + asset_name + "_" + department + " must not exist.") hda_instance.setName(department) tab_into_correct_place(inside, hda_instance, department) hda_instance.allowEditingOfContents() hda_instance.setSelected(True, clear_all_selected=True) return hda_instance
def update_contents_set(node, set_name, mode=UpdateModes.SMART): # Check if reference file exists set_file = os.path.join(Project().get_assets_dir(), set_name, "model", "main", "cache", "whole_set.json") # Error checking try: with open(set_file) as f: set_data = json.load(f) except Exception as error: error_message("No valid JSON file for " + set_name) return node.parm("asset_name").set(set_name) data = node.parm("data").evalAsJSONMap() data["asset_name"] = set_name node.parm("data").set(data) inside = node.node("inside") # Utility function to find if a node's asset and version number match an entry in the set's JSON def matches_reference(child, reference): # Grab data off the node. This data is stored as a key-value map parameter data = child.parm("data").evalAsJSONMap() print "{0}:\n\t checked {1} against {2}".format(str(child), str(data), str(reference)) # If it matches both the asset_name and version_number, it's a valid entry in the list if data["asset_name"] == reference["asset_name"] and data["version_number"] == str(reference["version_number"]): print "\tand it matched" return True else: print "\tand it didn't match" return False # Grab current BYU Dynamic Content Subnets that have been tabbed in current_children = [child for child in inside.children() if child.type().name() in ["byu_set", "byu_character", "byu_geo"]] # Smart updating will only destroy assets that no longer exist in the Set's JSON list if mode == UpdateModes.SMART: non_matching = [child for child in current_children if len([reference for reference in set_data if matches_reference(child, reference)]) == 0] for non_match in non_matching: non_match.destroy() # Clean updating will destroy all children. elif mode == UpdateModes.CLEAN: # Clear all child nodes. inside.deleteItems(inside.children()) # Grab current children again current_children = [child for child in inside.children() if child.type().name() in ["byu_set", "byu_character", "byu_geo"]] # Tab-in/update all assets in list for reference in set_data: body = Project().get_body(reference["asset_name"]) if body is None: print 'Error on: ', reference["asset_name"] continue if not body.is_asset() or body.get_type() == AssetType.SET: continue # Tab the subnet in if it doesn't exist, otherwise update_contents subnet = next((child for child in current_children if matches_reference(child, reference)), None) if subnet is None: subnet = byu_geo(inside, reference["asset_name"]) else: update_contents(subnet, reference["asset_name"], mode) # Try to not override parameters in the set if mode == UpdateModes.SMART: for key in reference: # Pull parm from node parm = subnet.parm(key) # If a non-default value is there, it most likely came from a user. Don't overwrite it. if parm and parm.isAtDefault(): parm.set(reference[key]) # Override parameters in the set elif mode == UpdateModes.CLEAN: newparms = {"asset_name" : reference["asset_name"], "version_number" : reference["version_number"] } subnet.setParms(newparms) # Set the set accordingly subnet.parm("space").set("set") subnet.parm("set").set(set_name) #subnet.parm("update_mode").setExpression("ch(\"../../update_mode\")", language=hou.exprLanguage.Hscript) subnet.parm("update_mode").set(UpdateModes.list_modes().index(mode)) # Set the data subnet.parm("data").set({ "asset_name": str(reference["asset_name"]), "version_number" : str(reference["version_number"]) }) inside.layoutChildren()