graphic:python:houdini

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Last revisionBoth sides next revision
graphic:python:houdini [2023/01/26 08:24] – [HDA Operation (Houdini Digital Asset)] yinggraphic:python:houdini [2023/05/31 09:08] – [HDA Operation (Houdini Digital Asset)] ying
Line 85: Line 85:
     * you can save the changes back into hda files (**Save node type**), or just keep changes in the scene     * you can save the changes back into hda files (**Save node type**), or just keep changes in the scene
     * to revert back to original state, just select node, use (**Match current definition** cmd)     * to revert back to original state, just select node, use (**Match current definition** cmd)
 +    * hda file can contain many hda assets, but recommed one asset for one hda file
 +    * hda asset can be inside houdini scene file, as Embedded instead of on a path file
 +    * nested hda need to be manually updated inside
 +    * ref:
 +      * https://www.tokeru.com/cgwiki/index.php?title=HoudiniHDA
   * VHDA = versioned houdini digital asset   * VHDA = versioned houdini digital asset
     * ref: create your own videos https://vimeo.com/458751335     * ref: create your own videos https://vimeo.com/458751335
Line 111: Line 116:
 #hda related files #hda related files
 assettools.py assettools.py
 +C:\Program Files\Side Effects Software\Houdini X\houdini\python3.7libs\assettools.py
 </code> </code>
 +  * node > definition > all info related
 +  * node info <code python>
 +# node
 +if len(hou.selectedNodes()) == 1:
 +    node = hou.selectedNodes()[0]
 +# node info
 +print(str(node) + " name: " + node.type().name() )
 +print(str(node) + " locked: " + node.isLockedHDA() )
 +</code>
 +  * definition <code python>
 +# definition
 +if node.type().definition() is not None:
 +    hda_def = node.type().definition()
  
 +# definition info
 +print(str(node) + " path: " + hda_def.libraryFilePath() )
 +print(str(node) + " version: " + hda_def.version())
 +print(str(node) + " description: " + hda_def.description())
 +print(str(node) + " comment: " + hda_def.comment())
 +# definition operation
 +cur_def.isInstalled()
 +cur_def.save(tmp_filepath, template_node=node)
 +</code>
 +  * hda file <code python>
 +# hda file
 +hda_file_path = hda_def.libraryFilePath()
 +definition_list = hou.hda.definitionsInFile(hda_file_path)
 +
 +# check hda file list loaded in memory
 +loaded_hda_file_list= hou.hda.loadedFiles()
 +print('\n'.join(loaded_hda_file_list))
 +
 +# hda file load/unload
 +hou.hda.installFile(hda_file_path)
 +hou.hda.uninstallFile(hda_file_path)
 +# hda file reload
 +hou.hda.reloadAllFiles(True)
 +</code>
  
  * check and remove HDA <code python>  * check and remove HDA <code python>
Line 129: Line 172:
     # remove action     # remove action
     # os.remove(cur_path)     # os.remove(cur_path)
 +</code>
 +
 +How create new ... HDA works?
 +
 +  - menu calls <code python>
 +import hou
 +import assettools
 +
 +node = kwargs["node"] # it get node from menu click action
 +assettools.createNewVHDAFromSubnet(node)
 +</code>
 +  - assettools.py has function createNewVHDAFromSubnet(), it basically create the dialog
 +  - dialog VHDASaveAsDialog() class show up, the Create button do the node publish
 +    - setMembersFromUI
 +    - namespace_author, namespace_branch, major_version, minor_version = self.getCorrectNamespacesAndVersion()
 +    - library_file = self.getCorrectLibraryFile()
 +    - tablabel = constructVHDALabel(self.tablabel, self.namespace_branch if self.display_branch_in_label_enable else None)
 +    - library_file_path = os.path.join(hou.text.expandString(self.library_dir), library_file)
 +    - vhda_typename = constructVHDATypeName(namespace_author, namespace_branch, self.type_name, major_version, minor_version)
 +    - continue: alert deals with lib path file contains multi- definition
 +    - new asset <code python>
 +createVHDA(node,
 +   namespace_author,
 +   namespace_branch,
 +   self.type_name,
 +   major_version,
 +   minor_version,
 +   tablabel,
 +   self.tabmenu_entry,
 +   self.library_dir,
 +   library_file)
 +</code>
 +    - version up case (a versioned copy of an existing): <code python>
 +copyToVHDAFile(node,
 +   namespace_author,
 +   namespace_branch,
 +   self.type_name,
 +   major_version,
 +   minor_version,
 +   tablabel,
 +   self.tabmenu_entry,
 +   self.library_dir,
 +   library_file)
 +</code>
 +  - details of VHDA function (from assettolls.py) <code python>
 +  def createVHDA(node, namespace_author, namespace_branch, name, major, minor, label, tabmenu, savedir, savefile=None):
 +    hda_name  = constructVHDATypeName(namespace_author, namespace_branch,name,major,minor)
 +    hda_label = label
 +    hda_filename = savefile if savefile else constructVHDAFileName(namespace_author, namespace_branch,name,major,minor)
 +    hda_savedir = savedir
 +    hda_filepath = os.path.join(hda_savedir, hda_filename) if hda_savedir != "Embedded" else "Embedded"
 +
 +    max_num_inputs = 0
 +
 +    # If there are inputs to the node, find the largest index of the input connections and use it as the max_num_inputs
 +    # This will preserve the inputs at the right indexes
 +    if len(node.inputs()) > 0:
 +        for connection in node.inputConnections():
 +            max_num_inputs = max(max_num_inputs,connection.inputIndex())
 +        max_num_inputs = max_num_inputs + 1
 +
 +    vhda_node = node.createDigitalAsset(
 +        name = hda_name,
 +        hda_file_name = hda_filepath,
 +        description = hda_label,
 +        min_num_inputs = 0,
 +        max_num_inputs = max_num_inputs,
 +        save_as_embedded = hda_savedir == "Embedded",
 +        ignore_external_references=True,
 +    )
 +
 +    vhda_node.setName(name, unique_name=True)
 +    vhda_def = vhda_node.type().definition()
 +
 +    # Update and save new HDA
 +    vhda_options = vhda_def.options()
 +    vhda_options.setSaveInitialParmsAndContents(True)
 +    #vhda_options.setSaveSpareParms(True) ####### TO-DO
 +
 +    vhda_def.setOptions(vhda_options)
 +    '''
 +    setVHDASection(vhda_def, False if namespace_author == "" else True,
 +                             False if namespace_branch == "" else True)
 +    '''
 +    setToolSubmenu(vhda_def, tabmenu)
 +
 +    vhda_def.save(hda_filepath, vhda_node, vhda_options)
 +    hou.hda.installFile(hda_filepath)
 +    hou.hda.reloadAllFiles(True)
 +  
 +</code>
 +  - copyToVHDAFile <code python>
 +def copyToVHDAFile(node, namespace_author, namespace_branch, name, major, minor, label, tabmenu, savedir, savefile=None):
 +    hda_name  = constructVHDATypeName(namespace_author, namespace_branch,name,major,minor)
 +    hda_label = label
 +    hda_filename = savefile if savefile else constructVHDAFileName(namespace_author, namespace_branch,name,major,minor)
 +    hda_savedir = savedir
 +    hda_filepath = os.path.join(hda_savedir, hda_filename) if hda_savedir != "Embedded" else "Embedded"
 +    tmp_filepath = os.path.join(hou.text.expandString("$HOUDINI_TEMP_DIR"),"tmphda.hda")
 +
 +    # Update and save new HDA
 +    vhda_def = node.type().definition()
 +    # vhda_options = vhda_def.options()
 +    # vhda_options.setSaveInitialParmsAndContents(True)
 +    # vhda_options.setSaveSpareParms(True) ####### TO-DO
 +
 +    vhda_def.save(tmp_filepath, template_node=node)
 +
 +    created_definition = hou.hda.definitionsInFile(tmp_filepath)[0]
 +    # Sets the tabmenu location only if it differs from the original
 +    if tabmenu:
 +        setToolSubmenu(created_definition, tabmenu)
 +
 +    created_definition.copyToHDAFile(hda_filepath,hda_name,hda_label)
 +
 +    os.remove(tmp_filepath)
 +    hou.hda.installFile(hda_filepath)
 +    hou.hda.reloadAllFiles(True)
 +    node.changeNodeType(hda_name)  
 </code> </code>
 ====== Tutorial ====== ====== Tutorial ======
  • graphic/python/houdini.txt
  • Last modified: 2024/03/22 06:37
  • by ying