def showNodeUserData(node=None, cached=False, **kwargs): if node is None: nodes = hou.selectedNodes() if not nodes: raise hou.Error('No node selected') elif len(nodes) > 1: raise hou.Error('Too much nodes selected') node = nodes[0] window = UserDataWindow(node, hou.qt.mainWindow()) window.user_data_model.updateDataFromNode(node, cached) window.show()
def updateHda(): import hou node = hou.selectedNodes()[0] if node is None: return None nodetyp=node.type().definition() if nodetyp is None: return None file_path =nodetyp.libraryFilePath() if file_path == "Embedded" : return None namespace0,namespace1,name,version = node.type().nameComponents() major = float(version)+1.0 minor = float(version)+0.1 major_ver = "update to {}".format(major) minor_ver = "update to {}".format(minor) if version != "": if not node.matchesCurrentDefinition(): selected_Item=hou.ui.displayMessage("please select version to update",buttons=(major_ver,minor_ver,"cancel")) if selected_Item == 0 : nodetyp.setVersion(str(major)) new_name = "{}::{}::{}".format(namespace1,name,major) nodetyp.copyToHDAFile(file_path,new_name=new_name) node.changeNodeType(new_name, keep_name=True, keep_parms=True, keep_network_contents = True, ) if selected_Item == 1: nodetyp.setVersion(str(minor)) new_name = "{}::{}::{}".format(namespace1,name,minor) nodetyp.copyToHDAFile(file_path,new_name=new_name) node.changeNodeType(new_name, keep_name=True, keep_parms=True, keep_network_contents=True, ) if selected_Item == 2: return None else: raise(hou.Error("please unlock the asset")) else: raise(hou.Error("hda namespace is wrong"))
def groupSelectedById(): """ Promote all material parameters from the Material SHOP to the node. """ sel = hou.selectedNodes() for n in range(0, len(sel)): current = sel[n] # Obtain a geometry selection geo_types = (hou.geometryType.Points, ) selection = scene_viewer.selectGeometry( "Select the points to group by 'id' and press Enter to complete", geometry_types=geo_types, allow_obj_sel=True) # The following will raise an exception if nothing was selected. if len(selection.nodes()) == 0: raise hou.Error("Nothing was selected.") # Create a new SOP container with the merged geometry container = soptoolutils.createSopNodeContainer(scene_viewer, "extract_object1") merge_sop = selection.mergedNode(container, nodetypename, True, True) # Turn back on the display flag for merged nodes for sop in selection.nodes(): sop.parent().setDisplayFlag(True) # Change our viewer to the new object scene_viewer.setPwd(merge_sop.parent()) merge_sop.setDisplayFlag(True) merge_sop.setRenderFlag(True) merge_sop.setHighlightFlag(True) merge_sop.setCurrent(True, True) merge_sop.moveToGoodPosition() toolutils.homeToSelectionNetworkEditorsFor(merge_sop) scene_viewer.enterCurrentNodeState()
def execute(node): data = eval_node_parms(node) filepath = hou.hipFile.path() filename = hou.hipFile.basename() dir_path = os.path.splitext(data["cachedir"])[0].rsplit("/", 1)[0] if os.path.exists(hou.expandString(data["path"])) is False: os.makedirs(hou.expandString(data["path"])) dirs = os.listdir(hou.expandString(data["path"])) node.parm("description").set(data["description"]) node.setUserData(data["fullpath"], data["description"]) if dir_path not in data["tempdir"]: if len(dirs) != 0: hou.ui.displayMessage( "Detected the existence of files, replace them ?", buttons=("yes", "no"), severity=hou.severityType.Message) hou.hipFile.saveAsBackup() node.node("rop_geometry1").parm("execute").pressButton() else: hou.hipFile.saveAsBackup() node.node("rop_geometry1").parm("execute").pressButton() else: raise (hou.Error("This is tempfile, please set correct path"))
def run(self): import toolutils import soptoolutils activepane = toolutils.activePane(kwargs) if activepane.type() == hou.paneTabType.SceneViewer: # Get the current context. sceneviewer = toolutils.sceneViewer() # Create a SOP container. container = soptoolutils.createSopNodeContainer( sceneviewer, "curve_object1") # Create the curve. newnode = soptoolutils.createSopNodeGenerator( container, "curve", None) # Turn on the highlight flag so we see the SOPs selected output. newnode.setHighlightFlag(True) if sceneviewer.isCreateInContext(): newnode.setCurrent(True, True) sceneviewer.enterCurrentNodeState() toolutils.homeToSelectionNetworkEditorsFor(newnode) else: container.setCurrent(True, True) toolutils.homeToSelectionNetworkEditorsFor(container) activepane.setPwd(container.parent()) activepane.setCurrentState("objcurve") elif activepane.type() == hou.paneTabType.NetworkEditor: soptoolutils.genericTool(kwargs, "curve") else: raise hou.Error("Can't run the tool in the selected pane.")
def takeScreenshot(): '''Take a screenshot and save it in the temp folder''' import tempfile res = [1024, 768] filename = "%s.jpg" % (os.path.join(tempfile.gettempdir(), str(uuid.uuid4()))) desktop = hou.ui.curDesktop() scene_view = toolutils.sceneViewer() if scene_view is None or (scene_view.type() != hou.paneTabType.SceneViewer): raise hou.Error("No scene view available to flipbook") viewport = scene_view.curViewport() if viewport.camera() is not None: res = [ viewport.camera().parm('resx').eval(), viewport.camera().parm('resy').eval() ] view = '%s.%s.world.%s' % (desktop.name(), scene_view.name(), viewport.name()) executeCommand = "viewwrite -c -f 0 1 -r %s %s %s %s" % ( res[0], res[1], view, filename) hou.hscript(executeCommand) return filename
def ik_to_fk(self): if self.length > 2: raise hou.Error("Only two-bone chains are currently supported for IK->FK matching") self.solver.parm("blend").set(0) self.set_end_pos() self.set_twist_pos()
def openFile(node): parms_path = node.parm("sopoutput").eval() path = os.path.split(parms_path)[0] if os.path.exists(hou.expandString(path)) is True: os.startfile(hou.expandString(path)) else: raise (hou.Error("can't find file path"))
def loadFromFile(self, filename): file = open(filename, "rb") with open(filename, "rb") as file: magic = file.readline() if magic != "pcache\n": raise hou.Error("Invalid file header: expected pcache magic number : {}".format(magic)) self.clear() done = False while not done: with hou.InterruptableOperation("Loading PCACHE Header", open_interrupt_dialog=False) as operation: line = file.readline().replace("\n","") words = line.split(" ") kw = words[0] if kw == "end_header": done = True elif kw == "format": if words[1] == "ascii": self.fileType = 'a' elif words[1] == "binary": self.fileType = 'b' else: raise hou.Error("Invalid format: {}".format(words[1])) elif kw == "elements": count = int(words[1]) self.itemcount = count elif kw == "property": if len(words) != 3: raise hou.Error("Invalid property description: {}".format(words)) if words[1] == "float": self.propertyTypes.append("float") self.propertyNames.append(words[2]) self.itemstride += 4 elif words[1] == "int": self.propertyTypes.append("int") self.propertyNames.append(words[2]) self.itemstride += 4 elif kw == "comment": print ' '.join(words).replace("comment ", "") self.propertyData = bytearray(file.read()) print "Item Stride is {} bytes".format(self.itemstride) length = len(self.propertyData) self.itemcount = length/self.itemstride print "Found {} bytes of data, corresponding to {} items".format(length, self.itemcount)
def main(): import hou node = hou.node(".") path = node.parm("path").eval() if not path: raise hou.Error("Please supply a path") export_data(node, path)
def dialog(tp): nodes = hou.selectedNodes() found_node = None for nd in nodes: if nd.type().name() == tp: found_node = nd if not found_node: raise hou.Error("Node type {} wasn't selected".format(tp)) return found_node
def generateCode(**kwargs): nodes = hou.selectedNodes() if not nodes: raise hou.Error('No node selected') code = '' for node in nodes: code += node.asCode() if code: hou.ui.copyTextToClipboard(code) hou.ui.setStatusMessage('Code was generated and copied', hou.severityType.ImportantMessage)
def slerpParmTuple(tup, t1, t2, bias): if not isCompleteRotate(tup): raise hou.Error(str(tup) + " is not a value set of euler rotates") r1 = tup.evalAtFrame(t1) r2 = tup.evalAtFrame(t2) q1 = hou.Quaternion(hou.hmath.buildRotate(r1)) q2 = hou.Quaternion(hou.hmath.buildRotate(r2)) outq = q1.slerp(q2, bias) return tuple(outq.extractEulerRotates())
def removeFolder(foldername, node, apply_to_definition=False): if apply_to_definition: if not node.isEditable(): raise hou.Error("Cannot apply to definition, node is not editable") target = node.type().definition() else: target = node ptg = target.parmTemplateGroup() ptg.remove(ptg.findFolder(foldername)) target.setParmTemplateGroup(ptg)
def _set_to_input(node, rop): """Give all channels an expression to link the input node. If rop doesn't actually have f1, f2, f3 then we cant link, so throw an error. """ if not rop: return rop_path = rop.path() if not rop.parmTuple("f"): raise hou.Error("""The selected ROP %s has no frame range parameter. Please select or create an output Rop with start, end, and step""" % rop_path) for channel in ['1', '2', '3']: _replace_with_input_expression( node.parm('fs%s' % channel), '%s/f%s' % (rop_path, channel))
def addResetButton(node, folder, apply_to_definition=False, move_to_top=False): """add a reset button to a given folder within the target node""" if apply_to_definition: if not node.isEditable(): raise hou.Error("Cannot apply to definition, node is not editable") target = node.type().definition() else: target = node ptg = target.parmTemplateGroup() if isinstance(folder, str): split_path = folder.split("/") if len(split_path) == 1: f_path = findFolder(ptg, folder) elif len(split_path) > 1: f_path = tuple(split_path) elif isinstance(folder, tuple): f_path = folder print(f_path) f = ptg.findFolder(f_path) script = """for p in kwargs['node'].parmsInFolder({0}): p.revertToDefaults()""".format(f_path) button_name = "reset_" + "_".join(f.lower().replace(" ", "_") for f in f_path) button = hou.ButtonParmTemplate(button_name, "Reset " + f.label()) button.setScriptCallback(script) button.setScriptCallbackLanguage(hou.scriptLanguage.Python) f.addParmTemplate(button) ptg.replace(ptg.findFolder(f_path), f) target.setParmTemplateGroup(ptg) if move_to_top: moveToTop(node.parm(button_name), apply_to_definition=apply_to_definition) return node.parm(button_name)
def set(): hipPath = os.path.dirname(hou.hipFile.name()) pathParts = getfolders(hipPath) #hipName = os.path.splitext(os.path.basename(hou.hipFile.name())[0] if pathParts[-1] != 'hip': raise hou.Error( "hip file does not reside in a directory called 'hip', can't get job name" ) jobPath = os.path.join(os.path.split(hipPath)[0]) hou.hscript("setenv JOB=%s" % jobPath) jobName = pathParts[-2] hou.hscript('setenv JOBCACHE=E:/Projects/%s' % jobName)
def run(): sel = hou.selectedNodes() if len(sel) == 0: raise hou.Error("Nothing was selected") for n in sel: display = n.displayNode() if display: geo = display.geometry() pivot = geo.boundingBox().center() sop = n.createNode('xform', 'move_to_pivot1') sop.setInput(0, display) sop.moveToGoodPosition() sop.setDisplayFlag(True) if display.isRenderFlagSet(): sop.setRenderFlag(True) sop.parmTuple("t").set(-pivot) sop.parmTuple("p").set(pivot) n.parmTuple("t").set(pivot)
def run(): sel = hou.selectedNodes() if len(sel) == 0: raise hou.Error("Nothing was selected") for n in sel: display = n.displayNode() if display: geo = display.geometry() pivot = n.parmTuple("p").eval() sop = n.createNode('xform', 'move_to_pivot') sop.setInput(0, display) sop.moveToGoodPosition() sop.setDisplayFlag(True) if display.isRenderFlagSet(): sop.setRenderFlag(True) sop.parmTuple("p").set(pivot) sop.parm("tx").set(pivot[0] * -1) sop.parm("ty").set(pivot[1] * -1) sop.parm("tz").set(pivot[2] * -1) n.parmTuple("t").set(pivot)
def removeParms(parms, node=None, apply_to_definition=False): if not node: node = parms[0].node() if apply_to_definition: if not node.isEditable(): raise hou.Error("Cannot apply to definition, node is not editable") target = node.type().definition() else: target = node ptg = target.parmTemplateGroup() for p in parms: if not ptg.find(p.parmTemplate().name()): continue ptg.remove(p.parmTemplate().name()) for rp in p.parmsReferencingThis(): rp.deleteAllKeyframes() target.setParmTemplateGroup(ptg)
def tweenParmTuple(tup, valuebias=0.5, timingbias=0.5, ref_frame=None, keyatref=True): print(tup) if not ref_frame: ref_frame = hou.frame() with hou.undos.group("Tween ParmTuple"): prevframes = () nextframes = () for p in tup: if p.keyframesBefore(ref_frame): prevframes += (p.keyframesBefore(ref_frame)[-1], ) if p.keyframesAfter(ref_frame): nextframes += (p.keyframesAfter(ref_frame)[0], ) if not prevframes or not nextframes: raise hou.Error("no surrounding keys") k1 = max(prevframes) k2 = min(nextframes) if isCompleteRotate(tup): out_v = slerpParmTuple(tup, k1.frame(), k2.frame(), valuebias) else: out_v = lerpParmTuple(tup, k1.frame(), k2.frame(), valuebias) if keyatref: out_f = ref_frame else: out_f = k1.frame() + ((k2.frame() - k1.frame()) * timingbias) return keyParmTuple(tup, int(out_f), out_v, onlykeyed=True)
def moveToTop(parm, apply_to_definition=False): """move the given parm to the top of it's containing folder""" node = parm.node() if apply_to_definition: if not node.isEditable(): raise hou.Error("Cannot apply to definition, node is not editable") target = node.type().definition() else: target = node ptg = target.parmTemplateGroup() pt = parm.parmTemplate() ptg.remove(pt.name()) f = ptg.findFolder(parm.containingFolders()) templates = f.parmTemplates() templates = (pt, ) + templates f.setParmTemplates(templates) ptg.replace(ptg.findFolder(parm.containingFolders()), f) target.setParmTemplateGroup(ptg)
def writeGeo(geo, outpath, attribs=None, version=2): with open(outpath,'wb') as f: points = geo.points() prims = geo.prims() if version == 1: uvAttrib = geo.findPointAttrib('uv') f.write(struct.pack('>ii', len(points), len(prims))) for p in points: pos = p.position() f.write(struct.pack('>fff',pos[0],pos[1],pos[2])) for p in points: uv = p.attribValue(uvAttrib) f.write(struct.pack('>ff',uv[0],1-uv[1])) for p in prims: verts = p.vertices() if len(verts) != 3: raise hou.Error('Non-Triangle primitive found') f.write(struct.pack('>HHH', verts[0].point().number(), verts[1].point().number(), verts[2].point().number())) if version == 2: checkGeo(geo) excludeAttribs = ('Pw',) writeAttribs = [attrib for attrib in geo.pointAttribs() if (attribs == None or attrib.name() in attribs) and attrib.name() not in excludeAttribs] f.write(struct.pack('>iii', len(points), len(prims), len(writeAttribs))) for attrib in writeAttribs: attribName = attrib.name() nameLen = len(attribName) attribSize = attrib.size() if nameLen > MAX_ATTRIBNAME_LEN: raise hou.Error('Attrib name too long at %d chars. Max: %d' % (nameLen, MAX_ATTRIBNAME_LEN)) f.write(struct.pack('>%ds' % MAX_ATTRIBNAME_LEN, attribName)) f.write(struct.pack('>i', attribSize)) for p in prims: verts = p.vertices() if len(verts) != 3: raise hou.Error('Non-Triangle primitive found') f.write(struct.pack('>HHH', verts[0].point().number(), verts[1].point().number(), verts[2].point().number())) for attrib in writeAttribs: for p in points: value = p.attribValue(attrib) if isinstance(value, tuple): f.write(struct.pack('>%df' % len(value), *value)) else: f.write(struct.pack('>f', value))
def checkGeo(geo): prims = geo.prims() for p in prims: verts = p.vertices() if len(verts) != 3: raise hou.Error('Non-Triangle primitive found')
def createGeo(self, geo, useRecommendedNames=True): # sets data into geometry if not isinstance(geo, hou.Geometry): raise hou.Error("Input is not not a valid Houdini Geometry") geo.clear() # deduce attributes to create from properties attribs_to_create = {} attribs_types_to_create = {} attribs_property = {} for i in xrange(len(self.propertyNames)): name = self.propertyNames[i] type = self.propertyTypes[i] comp = self.__getNameWithoutComponent(name) if useRecommendedNames: attrib_name = self.__reverseBinding(comp) if attrib_name is not None: attribs_property[attrib_name] = comp comp = attrib_name else: attribs_property[comp] = comp complen = self.__getComponentCountFromName(name) attribs_types_to_create[comp] = type; if comp in attribs_to_create: attribs_to_create[comp] = max(attribs_to_create[comp], complen) else: attribs_to_create[comp] = complen # Attrib Creation, item structure for comp in attribs_to_create: if geo.findPointAttrib(comp) is None: print "{} point attribute not found: creating...".format(comp) if attribs_types_to_create[comp] == "float": default_val = 0.0 elif attribs_types_to_create[comp] == "int": default_val = 0 else: default_val = None if attribs_to_create[comp] == 1: geo.addAttrib(hou.attribType.Point, comp, default_val) else: default_vec = list() for i in xrange(attribs_to_create[comp]): default_vec.append(default_val) geo.addAttrib(hou.attribType.Point, comp, default_vec) # Data Storage for i in xrange(self.itemcount): pt = geo.createPoint() # get bytes item_data = self.propertyData[i * self.itemstride: (i * self.itemstride) + self.itemstride] attrib_data = {} # fill in data index = 0 for j in xrange(len(self.propertyNames)): # get actual value if self.propertyTypes[j] == "float": val = struct.unpack("f", item_data[index:index+4]) index += 4 # print "Unpack Float ({}) : {}".format(self.propertyNames[j], val[0]) elif self.propertyTypes[j] == "int": val = struct.unpack("i", item_data[index:index+4]) index += 4 # print "Unpack Integer ({}) : {}".format(self.propertyNames[j], val[0]) else: val = None if self.__isVectorComponent(self.propertyNames[j]): # for vector stuff key = self.__reverseBinding(self.__getNameWithoutComponent(self.propertyNames[j])) idx = self.__componentIndexOf(self.propertyNames[j]) if key not in attrib_data: attrib_data[key] = [0.0, 0.0, 0.0] attrib_data[key][idx] = val[0] else: # 1-component data key = self.__reverseBinding(self.__getNameWithoutComponent(self.propertyNames[j])) attrib_data[key] = val[0] # print attrib_data for attrib in attrib_data: pt.setAttribValue(attrib, attrib_data[attrib])
def setDataFromGeometry(self, geo, export_attribs, property_names=None): # sets data into geometry if not isinstance(geo, hou.Geometry): raise hou.Error("Input is not not a valid Houdini Geometry") self.clear() bindings = {} attribs = export_attribs.split(' ') if property_names is None: # use default corresponding table bindings = self.defaultBindings else: propnames = property_names.split(' ') for i in xrange(len(attribs)): bindings[attribs[i]] = propnames[i] retained_attribs = [] for attrib in attribs: geo_attr = geo.findPointAttrib(attrib) if geo_attr is not None: data_type = geo_attr.dataType() if data_type == hou.attribData.Int: str_type = 'int' elif data_type == hou.attribData.Float: str_type = 'float' components = geo_attr.size() retained_attribs.append(geo_attr) if components == 1: # float self.propertyNames.append(bindings[attrib]) self.propertyTypes.append(str_type) self.itemstride += 4 elif components <= 4: # vector for i in xrange(components): self.propertyNames.append(bindings[attrib] + ".{}".format(self.components[i])) self.propertyTypes.append(str_type) self.itemstride += 4 else: raise hou.NodeWarning("Point attribute not found : {}".format(attrib)) print("------- {} PROPERTIES --------".format(len(self.propertyNames))) for i in xrange(len(self.propertyNames)): print("Property : {} ({})".format(self.propertyNames[i], self.propertyTypes[i])) points = geo.points() numpt = len(points) self.itemcount = numpt for point in points: for i in xrange(len(retained_attribs)): attr = retained_attribs[i] val = point.attribValue(attr) if self.propertyTypes[i] == "float": t = 'f' elif self.propertyTypes[i] == "int": t = 'i' if attr.size() > 1: for comp in val: pack = struct.pack(t, comp) for byte in pack: self.propertyData.append(byte) else: pack = struct.pack(t, val) for byte in pack: self.propertyData.append(byte)
def resizeFluidSops(kwargs): """ Select fluid and set it up to be resizeable. """ sceneviewer = toolutils.activePane(kwargs) if not isinstance(sceneviewer, hou.SceneViewer): raise hou.Error("Invalid pane type for this operation.") # Select the target fluid box. fluidobjects = sceneviewer.selectDynamics( prompt="Select fluid box to resize. Press Enter to complete.", allow_multisel=False) if len(fluidobjects) < 1: raise hou.Error( "No fluid container selected to set initial conditions.") fluidobject = fluidobjects[0] fluidnode = doptoolutils.getDopObjectCreator(fluidobject) if fluidnode is None: raise hou.Error("No fluid object node found.") """ Create and configure the reference container for resizing. """ dopnet = doptoolutils.getCurrentDopNetwork() refobject = fluidnode.parent().parent().createNode( "geo", "fluid_resize_container", run_init_scripts=False) fluidfields = refobject.createNode("dopio", "fluidfields") fluidfields.parm("doppath").set(dopnet.path()) fluidfields.setParmExpressions( {"defobj": "chs(\"" + fluidnode.path() + "/object_name\")"}) fluidfields.parm("fields").set(2) fluidfields.parm("fieldname1").set("density") fluidfields.parm("fieldname2").set("vel") parms = refobject.parmTemplateGroup() parms.hideFolder("Transform", True) parms.hideFolder("Material", True) parms.hideFolder("Render", True) parms.hideFolder("Misc", True) ref_folder = hou.FolderParmTemplate("ref_folder", "Resize Container") ref_folder.addParmTemplate( hou.IntParmTemplate( "nptsperarea", "Scatter per Area", 1, default_value=([5000]), min=1000, max=20000, help="Scatter points on simulated density to calculate bounds")) ref_folder.addParmTemplate( hou.FloatParmTemplate( "treshold", "Density Treshold", 1, default_value=([0]), min=0, max=1, help="Delete density below this value prior to scattering points")) ref_folder.addParmTemplate(hou.SeparatorParmTemplate("sep1")) ref_folder.addParmTemplate( hou.LabelParmTemplate("merge_source", "Merge Sources")) ref_folder.addParmTemplate( hou.ButtonParmTemplate( "update", "Update sources", help="Push this to update ObjectMerge node inside", tags={ "script_callback": "import adddoputils; adddoputils.updateSourcesButton()", "script_callback_language": "python" })) ref_folder.addParmTemplate( hou.IntParmTemplate( "source_activation", "All Sources Activation", 1, default_value=([1]), min=0, max=1, min_is_strict=True, max_is_strict=True, help= "Activation of merging all of the listed sources and additional objects" )) ref_folder.addParmTemplate( hou.MenuParmTemplate( "xformtype", "Transform", "012", ("None", "Into This Object", "Into Specified Object"), 1)) ref_folder.addParmTemplate( hou.StringParmTemplate("xformpath", "Transform object", 1, "", hou.parmNamingScheme.Base1, hou.stringParmType.NodeReference, disable_when=("{ xformtype != 2 }"))) sources_folder = hou.FolderParmTemplate( "source_folder", "Sources to Merge", folder_type=hou.folderType.MultiparmBlock) sources_folder.addParmTemplate( hou.ToggleParmTemplate("source_activation#", "Source # Activation", default_value=True)) sources_folder.addParmTemplate( hou.StringParmTemplate("objpath#", "Object #", 1, "", hou.parmNamingScheme.Base1, hou.stringParmType.NodeReference)) sources_folder.addParmTemplate( hou.StringParmTemplate("group#", "Group #", 1, "", hou.parmNamingScheme.Base1, hou.stringParmType.Regular)) ref_folder.addParmTemplate(sources_folder) parms.append(ref_folder) refobject.setParmTemplateGroup(parms) keep_density = refobject.createNode("blast", "keep_density") keep_density.setFirstInput(fluidfields) keep_density.parm("group").set("@name==vel*") keep_vel = refobject.createNode("blast", "keep_vel") keep_vel.setFirstInput(fluidfields) keep_vel.parm("group").set("@name==density") # VOLUME VOP clamping density field below given treshold density_treshold = keep_density.createOutputNode("volumevop", "density_treshold") vopglobals = density_treshold.node("volumevopglobal1") treshold = density_treshold.createNode("parameter", "treshold") treshold.parm("parmname").set("treshold") treshold.parm("parmlabel").set("Treshold") compare_density = density_treshold.createNode("compare", "compare_density") compare_density.parm("cmp").set("gte") compare_density.setInput(0, vopglobals, 1) compare_density.setInput(1, treshold, 0) twoway = compare_density.createOutputNode("twoway", "switch_density") twoway.setInput(1, vopglobals, 1) vop_output = density_treshold.node("volumevopoutput1") vop_output.setFirstInput(twoway, 0) density_treshold.setParmExpressions({"treshold": "ch(\"../treshold\")"}) # End of VOLUME VOP scatter = refobject.createNode("scatter", "scatter") scatter.setFirstInput(density_treshold) scatter.parm("ptsperarea").set(1) scatter.setParmExpressions({"nptsperarea": "ch(\"../nptsperarea\")"}) add_particles = scatter.createOutputNode("add", "add_particles") add_particles.parm("addparticlesystem").set(1) # VOP SOP adding velocity field to density-based pointcloud add_vel = refobject.createNode("vopsop", "add_vel") add_vel.parm("vex_numthreads").set(1) add_vel.setFirstInput(add_particles) add_vel.setInput(1, keep_vel, 0) globals = add_vel.node("global1") volumesamplex = add_vel.createNode("volumesample", "volumesample_x") volumesamplex.setInput(2, globals, 0) volumesamplex.parm("input_index").set(1) volumesamplex.parm("primnum").set(0) volumesampley = add_vel.createNode("volumesample", "volumesample_y") volumesampley.setInput(2, globals, 0) volumesampley.parm("input_index").set(1) volumesampley.parm("primnum").set(1) volumesamplez = add_vel.createNode("volumesample", "volumesample_z") volumesamplez.setInput(2, globals, 0) volumesamplez.parm("input_index").set(1) volumesamplez.parm("primnum").set(2) vel = volumesamplex.createOutputNode("floattovec", "vel") vel.setInput(1, volumesampley, 0) vel.setInput(2, volumesamplez, 0) vel_by_fps = vel.createOutputNode("divconst", "vel_by_fps") vel_by_fps.setParmExpressions({"divconst": "$FPS"}) add_vector = globals.createOutputNode("add", "add_vector") add_vector.setNextInput(vel_by_fps, 0) vex_output = add_vel.node("output1") vex_output.setFirstInput(add_vector, 0) # End of VOP SOP merge1 = refobject.createNode("merge", "merge1") merge1.setFirstInput(add_particles) merge1.setInput(1, add_vel, 0) bound = merge1.createOutputNode("bound", "bound") # Box to switch from after first simulation frame initial_box = refobject.createNode("box", "initial_box") initial_box.setParmExpressions({ "sizex": "ch(\"" + initial_box.relativePathTo(fluidnode) + "/sizex\")", "sizey": "ch(\"" + initial_box.relativePathTo(fluidnode) + "/sizey\")", "sizez": "ch(\"" + initial_box.relativePathTo(fluidnode) + "/sizez\")" }) initial_box.setParmExpressions({ "tx": "ch(\"" + initial_box.relativePathTo(fluidnode) + "/tx\")", "ty": "ch(\"" + initial_box.relativePathTo(fluidnode) + "/ty\")", "tz": "ch(\"" + initial_box.relativePathTo(fluidnode) + "/tz\")" }) initial_switch = initial_box.createOutputNode("switch", "initial_switch") initial_switch.setParmExpressions({ "input": "$F>ch(\"" + initial_switch.relativePathTo(fluidnode) + "/createframe\")", }) initial_switch.setInput(1, bound, 0) # Null to switch to if merging of simulation sources is disabled no_active_source = refobject.createNode("null", "no_active_source") merge_source = refobject.createNode("object_merge", "merge_source") merge_source.setParmExpressions({ "numobj": "ch(\"../source_folder\")", "xformtype": "ch(\"../xformtype\")" }) merge_source.parm("xformpath").set("`chsop(\"../xformpath\")`") numobj = merge_source.parm("numobj").eval() source_switch = no_active_source.createOutputNode("switch", "source_switch") source_switch.setParmExpressions({"input": "ch(\"../source_activation\")"}) source_switch.setInput(1, merge_source, 0) merge2 = initial_switch.createOutputNode("merge", "merge2") merge2.setInput(1, source_switch, 0) bound = merge2.createOutputNode("bound", "bound") unroll_edges = bound.createOutputNode("ends", "unroll_edges") unroll_edges.parm("closeu").set(4) out = unroll_edges.createOutputNode("null", "OUT") density_treshold.layoutChildren() add_vel.layoutChildren() refobject.layoutChildren() out.setDisplayFlag(True) out.setRenderFlag(True) resize = resizeFluidToMatchSops(fluidnode, refobject) resize.setCurrent(True, True) sceneviewer.enterCurrentNodeState()
def current(self): if self.count() < 1: raise hou.Error( "No measurements available!" ) #this check is for debugging. we should never be in this place if things work correctly. return self.measurements[-1]