def applyLocalOverrides(objnode): """ Promote all material parameters from the Material SHOP to the node. """ # Get the path to the material. material_path = objnode.evalParm("shop_materialpath") # Try to find the node. material_node = objnode.node(material_path) # The node type for the SHOP material node. material_type = hou.nodeType(hou.shopNodeTypeCategory(), "vopmaterial") # If the material node doesn't exist we need to throw an error. if not material_node: msg = "{0} is not a valid node.".format(material_path) raise hou.OperationFailed(msg) # If the material node is not actually a material we need to throw # an error. if material_node.type() != material_type: msg = "{0} is not a material.".format(material_path) raise hou.OperationFailed(msg) # Grab the parm template groups for the material and object. material_template_group = material_node.parmTemplateGroup() template_group = objnode.parmTemplateGroup() # We need to loop over every entry in the material group and apply the # 'material_spare' tag with a value of '1'. for template in material_template_group.entriesWithoutFolders(): # Grab any existing tags. tags = template.tags() # Apply the tag to signify it is a material spare property. tags["material_spare"] = "1" # Set the tags back to the template. template.setTags(tags) # Replace the original template with the modified one. material_template_group.replace(template.name(), template) # Find the folder to place the parameters into. # DOESN'T WORK with appendToFolder for some reason #material_folder = template_group.findFolder("Material") # For each entry in the template group, append it to the material # folder. for template in material_template_group.entries(): template_group.appendToFolder(template_group.findFolder("Material"), template) # Set the parm template group with the new parms to the object. objnode.setParmTemplateGroup(template_group)
def displayError(msg, exception=None): """Pop up a message dialog to display the given error message. If the ui is unavailable, then it writes the message to the console. """ if hou.isUIAvailable(): details = (str(exception) if exception is not None else None) hou.ui.displayMessage(msg, severity=hou.severityType.Error, details=details) else: if exception is not None: msg += "\n" + str(exception) raise hou.OperationFailed(msg)
def buildViewPath(viewer_or_scriptargs): """ Get a string representing the current viewport. """ if isinstance(viewer_or_scriptargs, dict): activepane = toolutils.activePane(viewer_or_scriptargs) elif isinstance(viewer_or_scriptargs, hou.SceneViewer): activepane = viewer_or_scriptargs desktop_name = hou.ui.curDesktop().name() if not isinstance(activepane, hou.SceneViewer): raise hou.OperationFailed("Pane is not a Scene Viewer.") # Get the name of the current viewer. pane_name = activepane.name() # Get the name of the current viewer's viewport. viewport_name = activepane.curViewport().name() return "%s.%s.world.%s" % (desktop_name, pane_name, viewport_name)
def __copy_inputs_to_node(self, node, target, ignore_missing=False): """ Copy all the input connections from this node to the target node. ignore_missing: If the target node does not have enough inputs then skip this connection. """ input_connections = node.inputConnections() num_target_inputs = len(target.inputConnectors()) if num_target_inputs is 0: raise hou.OperationFailed("Target node has no inputs.") for connection in input_connections: index = connection.inputIndex() if index > (num_target_inputs - 1): if ignore_missing: continue else: raise hou.InvalidInput("Target node has too few inputs.") target.setInput(index, connection.inputNode())
def computeWedge(ropnode, roptype): # check if this is a wedge rendering and compute the number of wedges numWedgeJobs = None if roptype == "wedge": if ropnode.parm("wedgemethod").eval() == 0: if ropnode.parm("random").eval() == 1: numWedgeJobs = ropnode.parm("numrandom").eval() else: numWedgeJobs = 1 for parm in ropnode.parm("wedgeparams").multiParmInstances(): if parm.name().startswith("steps"): if parm.eval() != 0: numWedgeJobs *= parm.eval() else: parent = ropnode.parm("roottake").eval() parentTakes = hou.hscript("takels -iqp %s" % parent)[0].split("\n") takes = [takename for takename in parentTakes if takename] numWedgeJobs = len(takes) if not numWedgeJobs: raise hou.OperationFailed("The specified wedge node does not compute anyting.") return numWedgeJobs
def _get_manager_generator_style(self, node_type): """Look for a style match based on the node type being a manager or generator type. :param node_type: A manager/generator node type :type node_type: hou.NodeType :return: An applicable styling object. :rtype: StyleConstant or StyleRule """ categories = (node_type.category().name(), constants.ALL_CATEGORY_KEY) for category_name in categories: # Check if the category has any rules. if category_name in self.node_type_rules: category_rules = self.node_type_rules[category_name] # The node type is a manager. if node_type.isManager(): # Check for a manager rule under the category. if constants.MANAGER_TYPE_KEY in category_rules: return self._resolve_rule( category_rules[constants.MANAGER_TYPE_KEY]) # The node type is a generator. elif node_type.isGenerator(): # Check for a generator rule under the category. if constants.GENERATOR_TYPE_KEY in category_rules: return self._resolve_rule( category_rules[constants.GENERATOR_TYPE_KEY]) else: raise hou.OperationFailed( "{} is not a manager or a generator type".format( node_type.nameWithCategory())) return None
def promote_parameter_to_node(scriptargs): # pylint: disable=too-many-locals """Promote a parameter to a target node. :param scriptargs: kwargs dict from PARMmenu entry. :type scriptargs: dict :return: """ # Get the parms to act on. parms = scriptargs["parms"] # The start node for the node chooser prompt start_node = None parm_tuple = None parm_tuple_map = {} parm_tuple_nodes = [] # Process all the selected parms, partitioning by parm tuple. for parm in parms: parm_tuple = parm.tuple() # Get or create a list of parms for this tuple. parms_for_tuple = parm_tuple_map.setdefault(parm_tuple, []) parms_for_tuple.append(parm) node = parm_tuple.node() parm_tuple_nodes.append(node) # Update the start node to be the parent of this tuple's node. start_node = node.parent() # The number of parms in the tuple. num_components = len(parm_tuple) # Determine how many components of the tuple we will set. num_components_to_set = max([len(value) for value in parm_tuple_map.values()]) # Prompt for a target node. Start at the parent (the most logical choice?) result = hou.ui.selectNode(initial_node=start_node) # Try to find ths selected node. target_node = hou.node(result) if target_node is not None: # Can't promote to a selected node. if target_node in parm_tuple_nodes: raise hou.OperationFailed("Cannot promote to a source node.") # Should the target parm will be set to the source value? set_value = True # The target node already has a parm tuple with the desired name so we # should prompt to use it. if target_node.parmTuple(parm_tuple.name()) is not None: choice = hou.ui.displayMessage( "Parameter already exists on {}. Link to existing parameter?".format(target_node.path()), buttons=("Yes and keep current value", "Yes and update value", "Cancel"), severity=hou.severityType.ImportantMessage, ) # Use parm but keep value, so don't set. if choice == 0: set_value = False # Use parm and update value. elif choice == 1: set_value = True # Bail out since we're cancelling. else: return # No existing parameter so we'll have to create one. else: # Get the target node's parm interface. target_ptg = target_node.parmTemplateGroup() # The parameter definition for the parm we are trying to link. parm_template = parm_tuple.parmTemplate() # If we are trying to link a single parm inside a tuple then modify # the parm definition to represent that single parm. if num_components_to_set != num_components: parm_template.setNumComponents(1) # Since we're just setting a single component the parms should all # have the same name so just grab the first. parm_template.setName(parms[0].name()) # Add the parameter definition to the parm list. target_ptg.addParmTemplate(parm_template) # Update the interface with the new definition. target_node.setParmTemplateGroup(target_ptg) # Process each parm to set. for parm in parms: # Get the target parm. target_parm = target_node.parm(parm.name()) # Set the target parm to the current value if required. if set_value: target_parm.set(parm.eval()) # Create the channel reference. parm.set(target_parm)
def raise_error(*args, **kwargs): raise hou.OperationFailed()
def buildAttribMenu( kwargs, # regular hou kwargs attribClass, # string or tuple inputGeo=None, # either a hou.Geometry or None means function will try its best filter=None, # filter function, taking a hou.Attrib object showClass=None, # None, True or False, to override default decision # if attribute class should be shown ): """Build an attribute popup menu based on various criteria. """ assert type(kwargs) is dict, "expected a valid kwargs dict" assert type(attribClass) in ( str, tuple, list, ), "invalid attribClass argument" # auto-detect geometry input if necessary # if not inputGeo and kwargs and kwargs.has_key("node"): i = kwargs["node"].inputs() if len(i): inputGeo = i[0].geometry() # process attribClass input # if type(attribClass) is str: # support plain strings like "point primitive" attribClass = tuple(attribClass.split()) if "all" in attribClass: attribClass = ( "point", "primitive", "vertex", "detail", ) if "comp" in attribClass or "component" in attribClass: attribClass = ( "point", "primitive", "vertex", ) if type(attribClass) is not tuple: # this is intended for lists attribClass = tuple(attribClass) attribClass = tuple(sorted(attribClass)) # got inputGeo and attribClass (hopefully) if not inputGeo: raise hou.OperationFailed("Couldn't determine input geometry") # collect attributes, filter and sort them # get_funcs = { "point": "pointAttribs", "primitive": "primAttribs", "prim": "primAttribs", "vertex": "vertexAttribs", "detail": "globalAttribs", "global": "globalAttribs" } show_class = len(attribClass) > 1 if showClass: show_class = showClass R = [] add_sep = False for c in attribClass: # get them attributes attribs = () if c in get_funcs: attribs = inputGeo.__getattribute__(get_funcs[c])() # filter them if required if filter: attribs = [a for a in attribs if filter(a)] # sort 'em alphabetically attribs = sorted(attribs, key=lambda a: a.name().lower()) # add menu separator between classes if add_sep and len(attribs) > 0: R.append("_separator_") R.append("") for a in attribs: R.append(a.name()) R.append(buildAttribLabel(a, showClass=show_class)) add_sep = True return R