Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
graphic:python:houdini [2023/01/26 08:24] – [HDA Operation (Houdini Digital Asset)] ying | graphic:python:houdini [2024/03/22 06:37] (current) – [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:// | ||
* VHDA = versioned houdini digital asset | * VHDA = versioned houdini digital asset | ||
* ref: create your own videos https:// | * ref: create your own videos https:// | ||
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 | ||
</ | </ | ||
+ | * node > definition > all info related | ||
+ | ===== Simple hda operation ===== | ||
+ | |||
+ | * lock hda node <code python> | ||
+ | * unlock hda node (same like allow edit of content)< | ||
+ | if result_node.isLockedHDA(): | ||
+ | result_node.allowEditingOfContents() | ||
+ | </ | ||
+ | * open type property dialog of a hda node <code python> | ||
+ | |||
+ | ===== Complex hda operation ===== | ||
+ | |||
+ | |||
+ | * 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() ) | ||
+ | </ | ||
+ | * 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: | ||
+ | print(str(node) + " comment: " + hda_def.comment()) | ||
+ | # definition operation | ||
+ | cur_def.isInstalled() | ||
+ | cur_def.save(tmp_filepath, | ||
+ | </ | ||
+ | * 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(' | ||
+ | |||
+ | # hda file load/unload | ||
+ | hou.hda.installFile(hda_file_path) | ||
+ | hou.hda.uninstallFile(hda_file_path) | ||
+ | # hda file reload | ||
+ | hou.hda.reloadAllFiles(True) | ||
+ | </ | ||
* check and remove HDA <code python> | * check and remove HDA <code python> | ||
Line 129: | Line 185: | ||
# remove action | # remove action | ||
# os.remove(cur_path) | # os.remove(cur_path) | ||
+ | </ | ||
+ | |||
+ | How create new ... HDA works? | ||
+ | |||
+ | - menu calls <code python> | ||
+ | import hou | ||
+ | import assettools | ||
+ | |||
+ | node = kwargs[" | ||
+ | assettools.createNewVHDAFromSubnet(node) | ||
+ | </ | ||
+ | - assettools.py has function createNewVHDAFromSubnet(), | ||
+ | - dialog VHDASaveAsDialog() class show up, the Create button do the node publish | ||
+ | - setMembersFromUI | ||
+ | - namespace_author, | ||
+ | - library_file = self.getCorrectLibraryFile() | ||
+ | - tablabel = constructVHDALabel(self.tablabel, | ||
+ | - library_file_path = os.path.join(hou.text.expandString(self.library_dir), | ||
+ | - vhda_typename = constructVHDATypeName(namespace_author, | ||
+ | - continue: alert deals with lib path file contains multi- definition | ||
+ | - new asset <code python> | ||
+ | createVHDA(node, | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | - version up case (a versioned copy of an existing): <code python> | ||
+ | copyToVHDAFile(node, | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | - details of VHDA function (from assettolls.py) <code python> | ||
+ | def createVHDA(node, | ||
+ | hda_name | ||
+ | hda_label = label | ||
+ | hda_filename = savefile if savefile else constructVHDAFileName(namespace_author, | ||
+ | hda_savedir = savedir | ||
+ | hda_filepath = os.path.join(hda_savedir, | ||
+ | |||
+ | 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, | ||
+ | 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 == " | ||
+ | ignore_external_references=True, | ||
+ | ) | ||
+ | |||
+ | vhda_node.setName(name, | ||
+ | vhda_def = vhda_node.type().definition() | ||
+ | |||
+ | # Update and save new HDA | ||
+ | vhda_options = vhda_def.options() | ||
+ | vhda_options.setSaveInitialParmsAndContents(True) | ||
+ | # | ||
+ | |||
+ | vhda_def.setOptions(vhda_options) | ||
+ | ''' | ||
+ | setVHDASection(vhda_def, | ||
+ | False if namespace_branch == "" | ||
+ | ''' | ||
+ | setToolSubmenu(vhda_def, | ||
+ | |||
+ | vhda_def.save(hda_filepath, | ||
+ | hou.hda.installFile(hda_filepath) | ||
+ | hou.hda.reloadAllFiles(True) | ||
+ | | ||
+ | </ | ||
+ | - copyToVHDAFile <code python> | ||
+ | def copyToVHDAFile(node, | ||
+ | hda_name | ||
+ | hda_label = label | ||
+ | hda_filename = savefile if savefile else constructVHDAFileName(namespace_author, | ||
+ | hda_savedir = savedir | ||
+ | hda_filepath = os.path.join(hda_savedir, | ||
+ | tmp_filepath = os.path.join(hou.text.expandString(" | ||
+ | |||
+ | # 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, | ||
+ | |||
+ | created_definition = hou.hda.definitionsInFile(tmp_filepath)[0] | ||
+ | # Sets the tabmenu location only if it differs from the original | ||
+ | if tabmenu: | ||
+ | setToolSubmenu(created_definition, | ||
+ | |||
+ | created_definition.copyToHDAFile(hda_filepath, | ||
+ | |||
+ | os.remove(tmp_filepath) | ||
+ | hou.hda.installFile(hda_filepath) | ||
+ | hou.hda.reloadAllFiles(True) | ||
+ | node.changeNodeType(hda_name) | ||
</ | </ | ||
====== Tutorial ====== | ====== Tutorial ====== |