diff --git a/client/ayon_houdini/api/hda_utils.py b/client/ayon_houdini/api/hda_utils.py index 059d25b9d3..e1841343cd 100644 --- a/client/ayon_houdini/api/hda_utils.py +++ b/client/ayon_houdini/api/hda_utils.py @@ -1,6 +1,7 @@ """Heper functions for load HDA""" import os +import re import uuid from typing import List @@ -15,8 +16,11 @@ get_folder_by_path, get_product_by_name, get_version_by_name, - get_representation_by_name + get_representation_by_name, + get_representations ) +from ayon_core.pipeline import Anatomy +from ayon_core.lib import StringTemplate from ayon_core.pipeline.context_tools import ( get_current_project_name, get_current_folder_path @@ -145,7 +149,7 @@ def get_representation_path( if use_ayon_entity_uri: path = get_ayon_entity_uri_from_representation_context(context) else: - path = get_representation_path_from_context(context) + path = _get_filepath_from_context(context) # Load fails on UNC paths with backslashes and also # fails to resolve @sourcename var with backslashed # paths correctly. So we force forward slashes @@ -153,6 +157,55 @@ def get_representation_path( return path +def _remove_format_spec(template: str, key: str) -> str: + """Remove format specifier from a format token in formatting string. + For example, change `{frame:0>4d}` into `{frame}` + Examples: + >>> remove_format_spec("{frame:0>4d}", "frame") + '{frame}' + >>> remove_format_spec("{digit:04d}/{frame:0>4d}", "frame") + '{digit:04d}/{udim}_{frame}' + >>> remove_format_spec("{a: >4}/{aa: >4}", "a") + '{a}/{aa: >4}' + """ + # Find all {key:foobar} and remove the `:foobar` + # Pattern will be like `({key):[^}]+(})` where we use the captured groups + # to keep those parts in the resulting string + pattern = f"({{{key}):[^}}]+(}})" + return re.sub(pattern, r"\1\2", template) + + +def _get_filepath_from_context(context: dict): + """Format file path for sequence with $F or .""" + # The path is either a single file or sequence in a folder. + # Format frame as $F and udim as + representation = context["representation"] + frame = representation["context"].get("frame") + udim = representation["context"].get("udim") + if frame is not None or udim is not None: + template: str = representation["attrib"]["template"] + repre_context: dict = representation["context"] + if udim is not None: + repre_context["udim"] = "" + template = _remove_format_spec(template, "udim") + if frame is not None: + # Substitute frame number in sequence with $F with padding + repre_context["frame"] = "$F{}".format(len(frame)) # e.g. $F4 + template = _remove_format_spec(template, "frame") + + project_name: str = repre_context["project"]["name"] + anatomy = Anatomy(project_name, project_entity=context["project"]) + repre_context["root"] = anatomy.roots + path = StringTemplate(template).format(repre_context) + else: + path = get_representation_path_from_context(context) + + # Load fails on UNC paths with backslashes and also + # fails to resolve @sourcename var with backslashed + # paths correctly. So we force forward slashes + return os.path.normpath(path).replace("\\", "/") + + def _get_thumbnail(project_name: str, version_id: str, thumbnail_dir: str): folder = hou.text.expandString(thumbnail_dir) path = os.path.join(folder, "{}_thumbnail.jpg".format(version_id)) @@ -357,7 +410,10 @@ def on_flag_changed(node, **kwargs): if not images: return - brightness = 0.3 if node.isBypassed() else 1.0 + # This may trigger on a node that can't be bypassed, like `ObjNode` so + # consider those never bypassed + is_bypassed = hasattr(node, "isBypassed") and node.isBypassed() + brightness = 0.3 if is_bypassed else 1.0 has_changes = False node_path = node.path() for image in images: @@ -653,11 +709,64 @@ def select_product_name(node): product_parm.pressButton() # allow any callbacks to trigger +def get_available_representations(node): + """Return the representation list for node. + + Args: + node (hou.Node): Node to query selected version's representations for. + + Returns: + list[str]: representation names for the product version. + """ + + project_name = node.evalParm("project_name") or get_current_project_name() + folder_path = node.evalParm("folder_path") + product_name = node.evalParm("product_name") + version = node.evalParm("version") + + if not all([ + project_name, folder_path, product_name, version + ]): + return [] + + try: + version = int(version.strip()) + except ValueError: + load_message_parm = node.parm("load_message") + load_message_parm.set(f"Invalid version format: '{version}'\n" + "Make sure to set a valid version number.") + return + + folder_entity = get_folder_by_path( + project_name, + folder_path=folder_path, + fields={"id"} + ) + product_entity = get_product_by_name( + project_name, + product_name=product_name, + folder_id=folder_entity["id"], + fields={"id"}) + version_entity = get_version_by_name( + project_name, + version, + product_id=product_entity["id"], + fields={"id"}) + representations = get_representations( + project_name, + version_ids={version_entity["id"]}, + fields={"name"} + ) + representations_names = [n["name"] for n in representations] + return representations_names + + def set_to_latest_version(node): """Callback on product name change - Refresh version parameter value by setting its value to - the latest version of the selected product. + Refresh version and representation parameters value by setting + their value to the latest version and representation of + the selected product. Args: node (hou.OpNode): The HDA node. @@ -667,6 +776,10 @@ def set_to_latest_version(node): if versions: node.parm("version").set(str(versions[0])) + representations = get_available_representations(node) + if representations: + node.parm("representation_name").set(representations[0]) + # region Parm Expressions # Callbacks used for expression on HDAs (e.g. Load Asset or Load Shot LOP) diff --git a/client/ayon_houdini/api/lib.py b/client/ayon_houdini/api/lib.py index c938fd6481..26c1b78438 100644 --- a/client/ayon_houdini/api/lib.py +++ b/client/ayon_houdini/api/lib.py @@ -10,6 +10,8 @@ import six import ayon_api +import hou + from ayon_core.lib import StringTemplate from ayon_core.settings import get_current_project_settings from ayon_core.pipeline import ( @@ -27,8 +29,6 @@ from ayon_core.tools.utils import PopupUpdateKeys, SimplePopup from ayon_core.tools.utils.host_tools import get_tool_by_name -import hou - self = sys.modules[__name__] self._parent = None @@ -1400,7 +1400,7 @@ def find_active_network(category, default): Arguments: category (hou.NodeTypeCategory): The node network category type. default (str): The default path to fallback to if no active pane - is found with the given category. + is found with the given category, e.g. "/obj" Returns: hou.Node: The node network to return. @@ -1521,3 +1521,67 @@ def start_workfile_template_builder(): build_workfile_template(workfile_creation_enabled=True) except TemplateProfileNotFound: log.warning("Template profile not found. Skipping...") + + +def show_node_parmeditor(node): + """Show Parameter Editor for the Node. + + Args: + node (hou.Node): node instance + """ + + # Check if there's a floating parameter editor pane with its node set to the specified node. + for tab in hou.ui.paneTabs(): + if ( + tab.type() == hou.paneTabType.Parm + and tab.isFloating() + and tab.currentNode() == node + ): + tab.setIsCurrentTab() + return + + # We are using the hscript to create and set the network path of the pane + # because hscript can set the node path without selecting the node. + # Create a floating pane and set its name to the node path. + hou.hscript( + f"pane -F -m parmeditor -n {node.path()}" + ) + # Hide network controls, turn linking off and set operator node path. + hou.hscript( + f"pane -a 1 -l 0 -H {node.path()} {node.path()}" + ) + + +def connect_file_parm_to_loader(file_parm: hou.Parm): + """Connect the given file parm to a generic loader. + If the parm is already connected to a generic loader node, go to that node. + """ + + from .pipeline import get_or_create_avalon_container + + referenced_parm = file_parm.getReferencedParm() + + # If the parm has reference + if file_parm != referenced_parm: + referenced_node = referenced_parm.getReferencedParm().node() + if referenced_node.type().name() == "ayon::generic_loader::1.0": + show_node_parmeditor(referenced_node) + return + + # Create a generic loader node and reference its file parm + main_container = get_or_create_avalon_container() + + node_name = f"{file_parm.node().name()}_{file_parm.name()}_loader" + load_node = main_container.createNode("ayon::generic_loader", + node_name=node_name) + load_node.moveToGoodPosition() + + # Set relative reference via hscript. This avoids the issues of + # `setExpression` e.g. having a keyframe. + relative_path = file_parm.node().relativePathTo(load_node) + expression = rf'chs\(\"{relative_path}/file\"\)' # noqa + hou.hscript( + 'opparm -r' + f' {file_parm.node().path()} {file_parm.name()} \`{expression}\`' + ) + show_node_parmeditor(load_node) diff --git a/client/ayon_houdini/plugins/load/load_filepath.py b/client/ayon_houdini/plugins/load/load_filepath.py index dddc26e32a..ee1bf84dc5 100644 --- a/client/ayon_houdini/plugins/load/load_filepath.py +++ b/client/ayon_houdini/plugins/load/load_filepath.py @@ -1,34 +1,8 @@ -import os -import re -import hou - -from ayon_core.pipeline import Anatomy -from ayon_core.lib import StringTemplate from ayon_houdini.api import ( - pipeline, + hda_utils, plugin ) - - -def remove_format_spec(template: str, key: str) -> str: - """Remove format specifier from a format token in formatting string. - - For example, change `{frame:0>4d}` into `{frame}` - - Examples: - >>> remove_format_spec("{frame:0>4d}", "frame") - '{frame}' - >>> remove_format_spec("{digit:04d}/{frame:0>4d}", "frame") - '{digit:04d}/{udim}_{frame}' - >>> remove_format_spec("{a: >4}/{aa: >4}", "a") - '{a}/{aa: >4}' - - """ - # Find all {key:foobar} and remove the `:foobar` - # Pattern will be like `({key):[^}]+(})` where we use the captured groups - # to keep those parts in the resulting string - pattern = f"({{{key}):[^}}]+(}})" - return re.sub(pattern, r"\1\2", template) +from ayon_houdini.api.pipeline import get_or_create_avalon_container class FilePathLoader(plugin.HoudiniLoader): @@ -50,64 +24,42 @@ class FilePathLoader(plugin.HoudiniLoader): def load(self, context, name=None, namespace=None, data=None): - # Get the root node - obj = hou.node("/obj") - # Define node name namespace = namespace if namespace else context["folder"]["name"] node_name = "{}_{}".format(namespace, name) if namespace else name - # Create a null node - container = obj.createNode("null", node_name=node_name) - - # Destroy any children - for node in container.children(): - node.destroy() - - # Add filepath attribute, set value as default value - filepath = self.filepath_from_context(context) - parm_template_group = container.parmTemplateGroup() - attr_folder = hou.FolderParmTemplate("attributes_folder", "Attributes") - parm = hou.StringParmTemplate(name="filepath", - label="Filepath", - num_components=1, - default_value=(filepath,)) - attr_folder.addParmTemplate(parm) - parm_template_group.append(attr_folder) - - # Hide some default labels - for folder_label in ["Transform", "Render", "Misc", "Redshift OBJ"]: - folder = parm_template_group.findFolder(folder_label) - if not folder: - continue - parm_template_group.hideFolder(folder_label, True) - - container.setParmTemplateGroup(parm_template_group) - - container.setDisplayFlag(False) - container.setSelectableInViewport(False) - container.useXray(False) - - nodes = [container] - - self[:] = nodes - - return pipeline.containerise( - node_name, - namespace, - nodes, - context, - self.__class__.__name__, - suffix="", - ) + # Create node + parent_node = get_or_create_avalon_container() + node = parent_node.createNode("ayon::generic_loader", + node_name=node_name) + node.moveToGoodPosition() + + hda_utils.set_node_representation_from_context(node, context) def update(self, container, context): + # First we handle backwards compatibility where this loader still + # loaded using a `null` node instead of the `ayon::generic_loader` + node = container["node"] + if node.type().name() == "null": + # Update the legacy way + self.update_legacy(node, context) + return + + hda_utils.set_node_representation_from_context(node, context) + + def switch(self, container, context): + self.update(container, context) + + def remove(self, container): + node = container["node"] + node.destroy() + + def update_legacy(self, node, context): # Update the file path representation_entity = context["representation"] - filepath = self.filepath_from_context(context) + filepath = hda_utils.get_filepath_from_context(context) - node = container["node"] node.setParms({ "filepath": filepath, "representation": str(representation_entity["id"]) @@ -119,39 +71,4 @@ def update(self, container, context): parm.setDefaultValue((filepath,)) parm_template_group.replace(parm_template_group.find("filepath"), parm) - node.setParmTemplateGroup(parm_template_group) - - def switch(self, container, context): - self.update(container, context) - - def remove(self, container): - - node = container["node"] - node.destroy() - - def filepath_from_context(self, context: dict) -> str: - """Format file path for sequence with $F or .""" - # The path is either a single file or sequence in a folder. - # Format frame as $F and udim as - representation = context["representation"] - frame = representation["context"].get("frame") - udim = representation["context"].get("udim") - if frame is not None or udim is not None: - template: str = representation["attrib"]["template"] - repre_context: dict = representation["context"] - if udim is not None: - repre_context["udim"] = "" - template = remove_format_spec(template, "udim") - if frame is not None: - # Substitute frame number in sequence with $F with padding - repre_context["frame"] = "$F{}".format(len(frame)) # e.g. $F4 - template = remove_format_spec(template, "frame") - - project_name: str = repre_context["project"]["name"] - anatomy = Anatomy(project_name, project_entity=context["project"]) - repre_context["root"] = anatomy.roots - path = StringTemplate(template).format(repre_context) - else: - path = super().filepath_from_context(context) - - return os.path.normpath(path).replace("\\", "/") + node.setParmTemplateGroup(parm_template_group) \ No newline at end of file diff --git a/client/ayon_houdini/startup/PARMmenu.xml b/client/ayon_houdini/startup/PARMmenu.xml new file mode 100644 index 0000000000..6c26d984ab --- /dev/null +++ b/client/ayon_houdini/startup/PARMmenu.xml @@ -0,0 +1,18 @@ + + + + + + + + len(kwargs["parms"]) > 0 and kwargs["parms"][0].parmTemplate().type() == hou.parmTemplateType.String and kwargs["parms"][0].parmTemplate().stringType() == hou.stringParmType.FileReference and not isinstance(kwargs["parms"][0].node(), hou.RopNode) + + + + + \ No newline at end of file diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/INDEX__SECTION b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/INDEX__SECTION new file mode 100644 index 0000000000..8219191034 --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/INDEX__SECTION @@ -0,0 +1,28 @@ +Operator: ayon::generic_loader::1.0 +Label: AYON Generic Loader +Path: oplib:/ayon::Object/generic_loader::1.0?ayon::Object/generic_loader::1.0 +Icon: opdef:/ayon::Object/generic_loader::1.0?IconImage +Table: Object +License: +Extra: +User: +Inputs: 0 to 0 +Subnet: true +Python: false +Empty: false +Modified: Mon Oct 21 13:04:25 2024 + +Operator: ayon::generic_loader::1.0 +Label: AYON Generic Loader +Path: oplib:/ayon::Sop/generic_loader::1.0?ayon::Sop/generic_loader::1.0 +Icon: opdef:/ayon::Sop/generic_loader::1.0?IconImage +Table: Sop +License: +Extra: inputcolors='0 ' outputcolors='1 "RGB 0.700195 0.700195 0.700195" ' +User: +Inputs: 0 to 0 +Subnet: true +Python: false +Empty: false +Modified: Mon Oct 21 13:05:51 2024 + diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/Sections.list b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/Sections.list new file mode 100644 index 0000000000..377acba3cc --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/Sections.list @@ -0,0 +1,5 @@ +"" +INDEX__SECTION INDEX_SECTION +houdini.hdalibrary houdini.hdalibrary +ayon_8_8Object_1generic__loader_8_81.0 ayon::Object/generic_loader::1.0 +ayon_8_8Sop_1generic__loader_8_81.0 ayon::Sop/generic_loader::1.0 diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/Contents.dir/Contents.createtimes b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/Contents.dir/Contents.createtimes new file mode 100644 index 0000000000..0c72080052 --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/Contents.dir/Contents.createtimes @@ -0,0 +1,3 @@ +{ + "hdaroot.def":1729504993 +} diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/Contents.dir/Contents.mime b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/Contents.dir/Contents.mime new file mode 100644 index 0000000000..8fed4398a0 --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/Contents.dir/Contents.mime @@ -0,0 +1,69 @@ +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="HOUDINIMIMEBOUNDARY0xD3ADD339-0x00000F49-0x56B122C9-0x00000001HOUDINIMIMEBOUNDARY" + +--HOUDINIMIMEBOUNDARY0xD3ADD339-0x00000F49-0x56B122C9-0x00000001HOUDINIMIMEBOUNDARY +Content-Disposition: attachment; filename="node_type" +Content-Type: text/plain + +Object + +--HOUDINIMIMEBOUNDARY0xD3ADD339-0x00000F49-0x56B122C9-0x00000001HOUDINIMIMEBOUNDARY +Content-Disposition: attachment; filename="hdaroot.init" +Content-Type: text/plain + +type = ayon::generic_loader::1.0 +matchesdef = 0 + +--HOUDINIMIMEBOUNDARY0xD3ADD339-0x00000F49-0x56B122C9-0x00000001HOUDINIMIMEBOUNDARY +Content-Disposition: attachment; filename="hdaroot.def" +Content-Type: text/plain + +objflags objflags = origin off +pretransform UT_DMatrix4 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 +comment "" +position -7.16358 -1.02336 +connectornextid 0 +flags = lock off model off template off footprint off xray off bypass off display on render off highlight off unload off savedata off compress on colordefault on exposed on selectable on +outputsNamed3 +{ +} +inputsNamed3 +{ +} +inputs +{ +} +stat +{ + create -1 + modify -1 + author Mustafa_Taher@Major-Kalawy + access 0777 +} +color UT_Color RGB 0.8 0.8 0.8 +delscript "" +exprlanguage hscript +end + +--HOUDINIMIMEBOUNDARY0xD3ADD339-0x00000F49-0x56B122C9-0x00000001HOUDINIMIMEBOUNDARY +Content-Disposition: attachment; filename="hdaroot.userdata" +Content-Type: text/plain + +{ + "___Version___":{ + "type":"string", + "value":"" + }, + "nodeshape":{ + "type":"string", + "value":"null" + } +} + +--HOUDINIMIMEBOUNDARY0xD3ADD339-0x00000F49-0x56B122C9-0x00000001HOUDINIMIMEBOUNDARY +Content-Disposition: attachment; filename="hdaroot.net" +Content-Type: text/plain + +1 + +--HOUDINIMIMEBOUNDARY0xD3ADD339-0x00000F49-0x56B122C9-0x00000001HOUDINIMIMEBOUNDARY-- diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/Contents.dir/Contents.modtimes b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/Contents.dir/Contents.modtimes new file mode 100644 index 0000000000..838a24a814 --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/Contents.dir/Contents.modtimes @@ -0,0 +1,3 @@ +{ + "hdaroot.def":1729505078 +} diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/Contents.dir/Sections.list b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/Contents.dir/Sections.list new file mode 100644 index 0000000000..49f2c1522a --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/Contents.dir/Sections.list @@ -0,0 +1,2 @@ +"" +Contents.mime Contents.mime diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/CreateScript b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/CreateScript new file mode 100644 index 0000000000..3456d09ef3 --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/CreateScript @@ -0,0 +1,15 @@ +# Automatically generated script +\set noalias = 1 +# +# Creation script for ayon::generic_loader::1.0 operator +# + +if ( "$arg1" == "" ) then + echo This script is intended as a creation script + exit +endif + +# Node $arg1 (ayon::Object/generic_loader::1.0) +opexprlanguage -s hscript $arg1 +opuserdata -n '___Version___' -v '' $arg1 +opuserdata -n 'nodeshape' -v 'null' $arg1 diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/DialogScript b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/DialogScript new file mode 100644 index 0000000000..c3c6fc5cd3 --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/DialogScript @@ -0,0 +1,506 @@ +# Dialog script for ayon::generic_loader::1.0 automatically generated + +{ + name ayon::generic_loader::1.0 + script Ynput::ayon_generic_loader + label "AYON Generic Loader" + + help { + "" + } + + inputlabel 1 "Sub-Network Input #1" + inputlabel 2 "Sub-Network Input #2" + inputlabel 3 "Sub-Network Input #3" + inputlabel 4 "Sub-Network Input #4" + + groupsimple { + name "info2" + label "Info" + parmtag { "script_callback" "hou.phm().refresh_available_versions(kwargs['node'])" } + parmtag { "script_callback_language" "python" } + + parm { + name "assetinfo_labelparm" + label "Heading" + type label + default { "Choose Product" } + parmtag { "sidefx::look" "heading" } + } + parm { + name "project_name" + label "Project" + type string + default { "$AYON_PROJECT_NAME" } + parmtag { "script_action" "from ayon_houdini.api.hda_utils import select_folder_path;select_folder_path(kwargs['node'])" } + parmtag { "script_action_icon" "BUTTONS_reselect" } + } + parm { + name "folder_path" + label "Folder Path" + type string + default { "$AYON_FOLDER_PATH" } + parmtag { "script_action" "from ayon_houdini.api.hda_utils import select_folder_path;select_folder_path(kwargs['node'])" } + parmtag { "script_action_icon" "BUTTONS_reselect" } + } + parm { + name "folder_name" + label "Folder Name" + type label + default { "`strsplit(chs(\"folder_path\"), \"/\", -1)`" } + } + parm { + name "product_name" + label "Product" + type string + default { "" } + parmtag { "script_action" "from ayon_houdini.api.hda_utils import select_product_name;select_product_name(kwargs['node'])" } + parmtag { "script_action_icon" "BUTTONS_reselect" } + parmtag { "script_callback" "hou.phm().set_to_latest_version(kwargs['node'])" } + parmtag { "script_callback_language" "python" } + } + parm { + name "version" + label "Version" + type string + default { "" } + disablewhen "{ representation_old == \"\" }" + menureplace { + [ "versions = hou.phm().get_available_versions(kwargs['node'])" ] + [ "" ] + [ "result = []" ] + [ "for version in versions:" ] + [ " result.append(str(version))" ] + [ " result.append(f\"v{version:03d}\")" ] + [ " " ] + [ "return result" ] + language python + } + parmtag { "script_callback_language" "python" } + } + parm { + name "representation_name" + label "Representation" + type string + default { "" } + menureplace { + [ "representations_names = hou.phm().get_available_representations(kwargs['node'])" ] + [ "" ] + [ "result = []" ] + [ "for name in representations_names:" ] + [ " result.append(name)" ] + [ " result.append(name)" ] + [ " " ] + [ "return result" ] + language python + } + parmtag { "script_callback_language" "python" } + } + parm { + name "clear_cache" + label "Clear Cache" + type button + default { "0" } + help "The load logic uses expressions that cache into the current session to avoid continuously requeryin the database. This clear that cache to enforce a full refresh of the expressions." + parmtag { "script_callback" "hou.phm().expression_clear_cache()" } + parmtag { "script_callback_language" "python" } + } + parm { + name "sepparm" + label "Separator" + type separator + default { "" } + } + parm { + name "file" + label "File" + type string + default { [ "from ayon_houdini.api import hda_utils\nreturn hda_utils.expression_get_representation_path()" python ] } + parmtag { "script_callback_language" "python" } + } + parm { + name "use_ayon_entity_uri" + label "Use AYON Entity URI" + type toggle + default { "0" } + help "When enabled, loads the filepath using the AYON Entity URI instead of the resolved filepath." + } + } + + groupcollapsible { + name "info_display2" + label "Info Display" + + parm { + name "show_thumbnail" + label "Show Entity Thumbnail" + type toggle + joinnext + default { "0" } + parmtag { "script_callback" "hou.phm().on_thumbnail_show_changed(kwargs['node'])" } + parmtag { "script_callback_language" "python" } + } + parm { + name "thumbnail_size" + label "Size" + type float + joinnext + default { "2" } + hidewhen "{ show_thumbnail == 0 }" + range { 0 10 } + parmtag { "script_callback" "hou.phm().on_thumbnail_size_changed(kwargs['node'])" } + parmtag { "script_callback_language" "python" } + } + parm { + name "thumbnail_cache_dir" + label "Thumbnail Cache Dir" + type directory + invisible + default { "$JOB/.houdini_loader_thumbnails" } + parmtag { "script_callback_language" "python" } + } + parm { + name "thumbnail_padding" + label "Padding" + type float + invisible + default { "1" } + range { 0 10 } + parmtag { "script_callback_language" "python" } + } + parm { + name "thumbnail_offset" + label "Offset" + type vector2 + size 2 + default { "0" "0.35" } + hidewhen "{ show_thumbnail == 0 }" + range { -1 1 } + parmtag { "script_callback" "hou.phm().on_thumbnail_size_changed(kwargs['node'])" } + parmtag { "script_callback_language" "python" } + } + parm { + name "update_thumbnail" + label "Update Thumbnail" + type button + default { "0" } + hidewhen "{ show_thumbnail == 0 }" + parmtag { "script_callback" "hou.phm().update_thumbnail(kwargs['node'])" } + parmtag { "script_callback_language" "python" } + } + parm { + name "show_pipeline_parms" + label "Show Pipeline Parms" + type toggle + default { "0" } + } + } + + group { + name "ayon_folder0" + label "Ayon" + hidewhen "{ show_pipeline_parms == 0 }" + + parm { + name "name" + label "Name" + type label + default { "$OS" } + } + parm { + name "namespace" + label "Namespace" + type label + default { "`opfullpath(\".\")`" } + } + parm { + name "loader" + label "Loader" + type label + default { "FilePathLoader" } + } + parm { + name "id" + label "ID" + type label + default { "pyblish.avalon.container" } + } + parm { + name "representation" + label "Representation ID" + type string + default { [ "from ayon_houdini.api import hda_utils\nreturn hda_utils.expression_get_representation_id()" python ] } + } + parm { + name "version_name" + label "Current Version Label" + type label + invisible + default { "" } + } + parm { + name "subset_name" + label "Subset (backwards compatibility)" + type label + invisible + default { "`chs(\"product_name\")`" } + } + } + + group { + name "ayon_folder0_1" + label "Transform" + invisibletab + + parm { + name "xOrd" + baseparm + label "Transform Order" + joinnext + export none + } + parm { + name "rOrd" + baseparm + label "Rotate Order" + nolabel + export none + } + parm { + name "t" + baseparm + label "Translate" + export none + } + parm { + name "r" + baseparm + label "Rotate" + export none + } + parm { + name "s" + baseparm + label "Scale" + export none + } + parm { + name "p" + baseparm + label "Pivot Translate" + export none + } + parm { + name "pr" + baseparm + label "Pivot Rotate" + export none + } + parm { + name "scale" + baseparm + label "Uniform Scale" + export none + } + parm { + name "pre_xform" + baseparm + label "Modify Pre-Transform" + export none + } + parm { + name "keeppos" + baseparm + label "Keep Position When Parenting" + export none + } + parm { + name "childcomp" + baseparm + label "Child Compensation" + export none + } + parm { + name "constraints_on" + baseparm + label "Enable Constraints" + export none + } + parm { + name "constraints_path" + baseparm + label "Constraints" + export none + } + parm { + name "lookatpath" + baseparm + label "Look At" + invisible + export none + } + parm { + name "lookupobjpath" + baseparm + label "Look Up Object" + invisible + export none + } + parm { + name "lookup" + baseparm + label "Look At Up Vector" + invisible + export none + } + parm { + name "pathobjpath" + baseparm + label "Path Object" + invisible + export none + } + parm { + name "roll" + baseparm + label "Roll" + invisible + export none + } + parm { + name "pos" + baseparm + label "Position" + invisible + export none + } + parm { + name "uparmtype" + baseparm + label "Parameterization" + invisible + export none + } + parm { + name "pathorient" + baseparm + label "Orient Along Path" + invisible + export none + } + parm { + name "up" + baseparm + label "Orient Up Vector" + invisible + export none + } + parm { + name "bank" + baseparm + label "Auto-Bank factor" + invisible + export none + } + } + + group { + name "ayon_folder0_2" + label "Subnet" + invisibletab + + parm { + name "label1" + baseparm + label "Input #1 Label" + invisible + export dialog + } + parm { + name "label2" + baseparm + label "Input #2 Label" + invisible + export dialog + } + parm { + name "label3" + baseparm + label "Input #3 Label" + invisible + export dialog + } + parm { + name "label4" + baseparm + label "Input #4 Label" + invisible + export dialog + } + parm { + name "tdisplay" + baseparm + label "Display" + joinnext + export all + } + parm { + name "display" + baseparm + label "Display" + export all + } + parm { + name "outputobj" + baseparm + label "Output Transform" + export all + } + parm { + name "visibleobjects" + baseparm + label "Visible Children" + export none + } + parm { + name "picking" + baseparm + label "Viewport Selecting Enabled" + export none + } + parm { + name "pickscript" + baseparm + label "Select Script" + export none + } + parm { + name "caching" + baseparm + label "Cache Object Transform" + export none + } + parm { + name "use_dcolor" + baseparm + label "Set Wireframe Color" + invisible + export none + } + parm { + name "dcolor" + baseparm + label "Wireframe Color" + invisible + export none + } + } + + parm { + name "newparameter" + label "Nodes referencing file" + type oplist + default { [ "\" \".join(parm.node().path() for parm in hou.parm('./file').parmsReferencingThis())" python ] } + parmtag { "script_callback_language" "python" } + } +} diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/ExtraFileOptions b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/ExtraFileOptions new file mode 100644 index 0000000000..2a040f7f77 --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/ExtraFileOptions @@ -0,0 +1,102 @@ +{ + "OnCreated/Cursor":{ + "type":"intarray", + "value":[14,1] + }, + "OnCreated/IsExpr":{ + "type":"bool", + "value":false + }, + "OnCreated/IsPython":{ + "type":"bool", + "value":true + }, + "OnCreated/IsScript":{ + "type":"bool", + "value":true + }, + "OnCreated/Source":{ + "type":"string", + "value":"" + }, + "OnDeleted/Cursor":{ + "type":"intarray", + "value":[2,1] + }, + "OnDeleted/IsExpr":{ + "type":"bool", + "value":false + }, + "OnDeleted/IsPython":{ + "type":"bool", + "value":true + }, + "OnDeleted/IsScript":{ + "type":"bool", + "value":true + }, + "OnDeleted/Source":{ + "type":"string", + "value":"" + }, + "OnLoaded/Cursor":{ + "type":"intarray", + "value":[11,1] + }, + "OnLoaded/IsExpr":{ + "type":"bool", + "value":false + }, + "OnLoaded/IsPython":{ + "type":"bool", + "value":true + }, + "OnLoaded/IsScript":{ + "type":"bool", + "value":true + }, + "OnLoaded/Source":{ + "type":"string", + "value":"" + }, + "OnNameChanged/Cursor":{ + "type":"intarray", + "value":[9,1] + }, + "OnNameChanged/IsExpr":{ + "type":"bool", + "value":false + }, + "OnNameChanged/IsPython":{ + "type":"bool", + "value":true + }, + "OnNameChanged/IsScript":{ + "type":"bool", + "value":true + }, + "OnNameChanged/Source":{ + "type":"string", + "value":"" + }, + "PythonModule/Cursor":{ + "type":"intarray", + "value":[10,1] + }, + "PythonModule/IsExpr":{ + "type":"bool", + "value":false + }, + "PythonModule/IsPython":{ + "type":"bool", + "value":true + }, + "PythonModule/IsScript":{ + "type":"bool", + "value":true + }, + "PythonModule/Source":{ + "type":"string", + "value":"" + } +} diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/Help b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/Help new file mode 100644 index 0000000000..e69de29bb2 diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/IconImage b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/IconImage new file mode 100644 index 0000000000..3186837283 Binary files /dev/null and b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/IconImage differ diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/InternalFileOptions b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/InternalFileOptions new file mode 100644 index 0000000000..222988aa02 --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/InternalFileOptions @@ -0,0 +1,10 @@ +{ + "nodeconntype":{ + "type":"bool", + "value":false + }, + "nodeparmtype":{ + "type":"bool", + "value":false + } +} diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/OnCreated b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/OnCreated new file mode 100644 index 0000000000..63537e4e5b --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/OnCreated @@ -0,0 +1,13 @@ +node = kwargs["node"] +hda_module = node.hdaModule() +hda_module.setup_flag_changed_callback(node) + +node.parm("file").lock(True) + +# Get attribute defaults from settings +# TODO: Clean this up and re-use more from HDA utils lib +from ayon_core.settings import get_current_project_settings +settings = get_current_project_settings() +load_settings = settings["houdini"].get("load", {}).get("GenericLoader", {}) +use_ayon_entity_uri = load_settings.get("use_ayon_entity_uri", False) +node.parm("use_ayon_entity_uri").set(use_ayon_entity_uri) diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/OnDeleted b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/OnDeleted new file mode 100644 index 0000000000..42e4ef2401 --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/OnDeleted @@ -0,0 +1,6 @@ +from ayon_houdini.api.lib import remove_all_thumbnails + + +# Clear thumbnails +node = kwargs["node"] +remove_all_thumbnails(node) diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/OnLoaded b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/OnLoaded new file mode 100644 index 0000000000..9d5dfd7749 --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/OnLoaded @@ -0,0 +1,14 @@ +node = kwargs["node"] +hda_module = node.hdaModule() +hda_module.setup_flag_changed_callback(node) + + +# Duplicate callback +def on_duplicate(): + """Duplicate thumbnail on node duplicate""" + if node.evalParm("show_thumbnail") and node.evalParm("representation"): + hda_module.update_thumbnail(node) + + +if not hou.hipFile.isLoadingHipFile(): + on_duplicate() diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/OnNameChanged b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/OnNameChanged new file mode 100644 index 0000000000..2076f5ad9d --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/OnNameChanged @@ -0,0 +1,8 @@ +from ayon_houdini.api.hda_utils import ( + keep_background_images_linked +) + + +node = kwargs["node"] +old_name = kwargs["old_name"] +keep_background_images_linked(node, old_name) diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/PythonModule b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/PythonModule new file mode 100644 index 0000000000..f1f9592243 --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/PythonModule @@ -0,0 +1,11 @@ +from ayon_houdini.api.hda_utils import ( + on_thumbnail_show_changed, + on_thumbnail_size_changed, + update_thumbnail, + setup_flag_changed_callback, + get_available_versions, + get_available_representations, + select_product_name, + set_to_latest_version, + expression_clear_cache +) diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/Sections.list b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/Sections.list new file mode 100644 index 0000000000..c6d20f84f3 --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/Sections.list @@ -0,0 +1,15 @@ +"" +DialogScript DialogScript +CreateScript CreateScript +InternalFileOptions InternalFileOptions +Contents.gz Contents.gz +TypePropertiesOptions TypePropertiesOptions +Tools.shelf Tools.shelf +Help Help +IconImage IconImage +PythonModule PythonModule +OnCreated OnCreated +OnLoaded OnLoaded +OnDeleted OnDeleted +OnNameChanged OnNameChanged +ExtraFileOptions ExtraFileOptions diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/Tools.shelf b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/Tools.shelf new file mode 100644 index 0000000000..b9843737a8 --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/Tools.shelf @@ -0,0 +1,17 @@ + + + + + + + $HDA_TABLE_AND_NAME + OBJ + + AYON + + + diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/TypePropertiesOptions b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/TypePropertiesOptions new file mode 100644 index 0000000000..a6d52acf2a --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Object_1generic__loader_8_81.0/TypePropertiesOptions @@ -0,0 +1,14 @@ +CheckExternal := 1; +ContentsCompressionType := 1; +ForbidOutsideParms := 1; +GzipContents := 1; +LockContents := 1; +MakeDefault := 1; +ParmsFromVfl := 0; +PrefixDroppedParmLabel := 0; +PrefixDroppedParmName := 0; +SaveCachedCode := 0; +SaveIcon := 1; +SaveSpareParms := 0; +UnlockOnCreate := 0; +UseDSParms := 1; diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/Contents.dir/Contents.createtimes b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/Contents.dir/Contents.createtimes new file mode 100644 index 0000000000..f4ea60f05a --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/Contents.dir/Contents.createtimes @@ -0,0 +1,4 @@ +{ + "hdaroot/output0.def":1728474331, + "hdaroot.def":1729505122 +} diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/Contents.dir/Contents.houdini_versions b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/Contents.dir/Contents.houdini_versions new file mode 100644 index 0000000000..89a9d39a89 --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/Contents.dir/Contents.houdini_versions @@ -0,0 +1,7 @@ +{ + "values":["19.5.805" + ], + "indexes":{ + "hdaroot/output0.userdata":0 + } +} diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/Contents.dir/Contents.mime b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/Contents.dir/Contents.mime new file mode 100644 index 0000000000..5ffd527bee --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/Contents.dir/Contents.mime @@ -0,0 +1,125 @@ +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="HOUDINIMIMEBOUNDARY0xD3ADD339-0x00000F49-0x56B122C9-0x00000001HOUDINIMIMEBOUNDARY" + +--HOUDINIMIMEBOUNDARY0xD3ADD339-0x00000F49-0x56B122C9-0x00000001HOUDINIMIMEBOUNDARY +Content-Disposition: attachment; filename="node_type" +Content-Type: text/plain + +Sop + +--HOUDINIMIMEBOUNDARY0xD3ADD339-0x00000F49-0x56B122C9-0x00000001HOUDINIMIMEBOUNDARY +Content-Disposition: attachment; filename="hdaroot.init" +Content-Type: text/plain + +type = ayon::generic_loader::1.0 +matchesdef = 0 + +--HOUDINIMIMEBOUNDARY0xD3ADD339-0x00000F49-0x56B122C9-0x00000001HOUDINIMIMEBOUNDARY +Content-Disposition: attachment; filename="hdaroot.def" +Content-Type: text/plain + +sopflags sopflags = +comment "" +position 1.1895 -18.6548 +connectornextid 0 +flags = lock off model off template off footprint off xray off bypass off display off render off highlight off unload off savedata off compress on colordefault on exposed on +outputsNamed3 +{ +} +inputsNamed3 +{ +} +inputs +{ +} +stat +{ + create -1 + modify -1 + author Mustafa_Taher@Major-Kalawy + access 0777 +} +color UT_Color RGB 0.8 0.8 0.8 +delscript "" +exprlanguage hscript +end + +--HOUDINIMIMEBOUNDARY0xD3ADD339-0x00000F49-0x56B122C9-0x00000001HOUDINIMIMEBOUNDARY +Content-Disposition: attachment; filename="hdaroot.userdata" +Content-Type: text/plain + +{ + "___Version___":{ + "type":"string", + "value":"" + }, + "nodeshape":{ + "type":"string", + "value":"null" + } +} + +--HOUDINIMIMEBOUNDARY0xD3ADD339-0x00000F49-0x56B122C9-0x00000001HOUDINIMIMEBOUNDARY +Content-Disposition: attachment; filename="hdaroot/output0.init" +Content-Type: text/plain + +type = output +matchesdef = 1 + +--HOUDINIMIMEBOUNDARY0xD3ADD339-0x00000F49-0x56B122C9-0x00000001HOUDINIMIMEBOUNDARY +Content-Disposition: attachment; filename="hdaroot/output0.def" +Content-Type: text/plain + +sopflags sopflags = +comment "" +position 0 3.9 +connectornextid 0 +flags = lock off model off template off footprint off xray off bypass off display on render on highlight off unload off savedata off compress on colordefault on exposed on +outputsNamed3 +{ +} +inputsNamed3 +{ +} +inputs +{ +} +stat +{ + create -1 + modify -1 + author Mustafa_Taher@Major-Kalawy + access 0777 +} +color UT_Color RGB 0.8 0.8 0.8 +delscript "" +exprlanguage hscript +end + +--HOUDINIMIMEBOUNDARY0xD3ADD339-0x00000F49-0x56B122C9-0x00000001HOUDINIMIMEBOUNDARY +Content-Disposition: attachment; filename="hdaroot/output0.parm" +Content-Type: text/plain + +{ +version 0.8 +outputidx [ 0 locks=0 ] ( 0 ) +} + +--HOUDINIMIMEBOUNDARY0xD3ADD339-0x00000F49-0x56B122C9-0x00000001HOUDINIMIMEBOUNDARY +Content-Disposition: attachment; filename="hdaroot/output0.userdata" +Content-Type: text/plain + +{ + "___Version___":{ + "type":"string", + "value":"___EXTERNAL___" + } +} + +--HOUDINIMIMEBOUNDARY0xD3ADD339-0x00000F49-0x56B122C9-0x00000001HOUDINIMIMEBOUNDARY +Content-Disposition: attachment; filename="hdaroot.net" +Content-Type: text/plain + +1 + +--HOUDINIMIMEBOUNDARY0xD3ADD339-0x00000F49-0x56B122C9-0x00000001HOUDINIMIMEBOUNDARY-- diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/Contents.dir/Contents.modtimes b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/Contents.dir/Contents.modtimes new file mode 100644 index 0000000000..9b975b55b2 --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/Contents.dir/Contents.modtimes @@ -0,0 +1,4 @@ +{ + "hdaroot/output0.def":1728474347, + "hdaroot.def":1729505164 +} diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/Contents.dir/Sections.list b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/Contents.dir/Sections.list new file mode 100644 index 0000000000..49f2c1522a --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/Contents.dir/Sections.list @@ -0,0 +1,2 @@ +"" +Contents.mime Contents.mime diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/CreateScript b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/CreateScript new file mode 100644 index 0000000000..6813ae16ab --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/CreateScript @@ -0,0 +1,15 @@ +# Automatically generated script +\set noalias = 1 +# +# Creation script for ayon::generic_loader::1.0 operator +# + +if ( "$arg1" == "" ) then + echo This script is intended as a creation script + exit +endif + +# Node $arg1 (ayon::Sop/generic_loader::1.0) +opexprlanguage -s hscript $arg1 +opuserdata -n '___Version___' -v '' $arg1 +opuserdata -n 'nodeshape' -v 'null' $arg1 diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/DialogScript b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/DialogScript new file mode 100644 index 0000000000..75b945dc52 --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/DialogScript @@ -0,0 +1,258 @@ +# Dialog script for ayon::generic_loader::1.0 automatically generated + +{ + name ayon::generic_loader::1.0 + script ayon::generic_loader::1.0 + label "AYON Generic Loader" + + help { + "" + } + + inputlabel 1 "Sub-Network Input #1" + inputlabel 2 "Sub-Network Input #2" + inputlabel 3 "Sub-Network Input #3" + inputlabel 4 "Sub-Network Input #4" + + groupsimple { + name "info2" + label "Info" + parmtag { "script_callback" "hou.phm().refresh_available_versions(kwargs['node'])" } + parmtag { "script_callback_language" "python" } + + parm { + name "assetinfo_labelparm" + label "Heading" + type label + default { "Choose Product" } + parmtag { "sidefx::look" "heading" } + } + parm { + name "project_name" + label "Project" + type string + default { "$AYON_PROJECT_NAME" } + parmtag { "script_action" "from ayon_houdini.api.hda_utils import select_folder_path;select_folder_path(kwargs['node'])" } + parmtag { "script_action_icon" "BUTTONS_reselect" } + } + parm { + name "folder_path" + label "Folder Path" + type string + default { "$AYON_FOLDER_PATH" } + parmtag { "script_action" "from ayon_houdini.api.hda_utils import select_folder_path;select_folder_path(kwargs['node'])" } + parmtag { "script_action_icon" "BUTTONS_reselect" } + } + parm { + name "folder_name" + label "Folder Name" + type label + default { "`strsplit(chs(\"folder_path\"), \"/\", -1)`" } + } + parm { + name "product_name" + label "Product" + type string + default { "" } + parmtag { "script_action" "from ayon_houdini.api.hda_utils import select_product_name;select_product_name(kwargs['node'])" } + parmtag { "script_action_icon" "BUTTONS_reselect" } + parmtag { "script_callback" "hou.phm().set_to_latest_version(kwargs['node'])" } + parmtag { "script_callback_language" "python" } + } + parm { + name "version" + label "Version" + type string + default { "" } + disablewhen "{ representation_old == \"\" }" + menureplace { + [ "versions = hou.phm().get_available_versions(kwargs['node'])" ] + [ "" ] + [ "result = []" ] + [ "for version in versions:" ] + [ " result.append(str(version))" ] + [ " result.append(f\"v{version:03d}\")" ] + [ " " ] + [ "return result" ] + language python + } + parmtag { "script_callback_language" "python" } + } + parm { + name "representation_name" + label "Representation" + type string + default { "" } + menureplace { + [ "representations_names = hou.phm().get_available_representations(kwargs['node'])" ] + [ "" ] + [ "result = []" ] + [ "for name in representations_names:" ] + [ " result.append(name)" ] + [ " result.append(name)" ] + [ " " ] + [ "return result" ] + language python + } + parmtag { "script_callback_language" "python" } + } + parm { + name "clear_cache" + label "Clear Cache" + type button + default { "0" } + help "The load logic uses expressions that cache into the current session to avoid continuously requeryin the database. This clear that cache to enforce a full refresh of the expressions." + parmtag { "script_callback" "hou.phm().expression_clear_cache()" } + parmtag { "script_callback_language" "python" } + } + parm { + name "sepparm" + label "Separator" + type separator + default { "" } + } + parm { + name "file" + label "File" + type string + default { [ "from ayon_houdini.api import hda_utils\nreturn hda_utils.expression_get_representation_path()" python ] } + parmtag { "script_callback_language" "python" } + } + parm { + name "use_ayon_entity_uri" + label "Use AYON Entity URI" + type toggle + default { "0" } + help "When enabled, loads the filepath using the AYON Entity URI instead of the resolved filepath." + } + } + + groupcollapsible { + name "info_display2" + label "Info Display" + + parm { + name "show_thumbnail" + label "Show Entity Thumbnail" + type toggle + joinnext + default { "0" } + parmtag { "script_callback" "hou.phm().on_thumbnail_show_changed(kwargs['node'])" } + parmtag { "script_callback_language" "python" } + } + parm { + name "thumbnail_size" + label "Size" + type float + joinnext + default { "2" } + hidewhen "{ show_thumbnail == 0 }" + range { 0 10 } + parmtag { "script_callback" "hou.phm().on_thumbnail_size_changed(kwargs['node'])" } + parmtag { "script_callback_language" "python" } + } + parm { + name "thumbnail_cache_dir" + label "Thumbnail Cache Dir" + type directory + invisible + default { "$JOB/.houdini_loader_thumbnails" } + parmtag { "script_callback_language" "python" } + } + parm { + name "thumbnail_padding" + label "Padding" + type float + invisible + default { "1" } + range { 0 10 } + parmtag { "script_callback_language" "python" } + } + parm { + name "thumbnail_offset" + label "Offset" + type vector2 + size 2 + default { "0" "0.35" } + hidewhen "{ show_thumbnail == 0 }" + range { -1 1 } + parmtag { "script_callback" "hou.phm().on_thumbnail_size_changed(kwargs['node'])" } + parmtag { "script_callback_language" "python" } + } + parm { + name "update_thumbnail" + label "Update Thumbnail" + type button + default { "0" } + hidewhen "{ show_thumbnail == 0 }" + parmtag { "script_callback" "hou.phm().update_thumbnail(kwargs['node'])" } + parmtag { "script_callback_language" "python" } + } + parm { + name "show_pipeline_parms" + label "Show Pipeline Parms" + type toggle + default { "0" } + } + } + + group { + name "ayon_folder0" + label "Ayon" + hidewhen "{ show_pipeline_parms == 0 }" + + parm { + name "name" + label "Name" + type label + default { "$OS" } + } + parm { + name "namespace" + label "Namespace" + type label + default { "`opfullpath(\".\")`" } + } + parm { + name "loader" + label "Loader" + type label + default { "FilePathLoader" } + } + parm { + name "id" + label "ID" + type label + default { "pyblish.avalon.container" } + } + parm { + name "representation" + label "Representation ID" + type string + default { [ "from ayon_houdini.api import hda_utils\nreturn hda_utils.expression_get_representation_id()" python ] } + } + parm { + name "version_name" + label "Current Version Label" + type label + invisible + default { "" } + } + parm { + name "subset_name" + label "Subset (backwards compatibility)" + type label + invisible + default { "`chs(\"product_name\")`" } + } + } + + parm { + name "newparameter" + label "Nodes referencing file" + type oplist + default { [ "\" \".join(parm.node().path() for parm in hou.parm('./file').parmsReferencingThis())" python ] } + parmtag { "oprelative" "/" } + parmtag { "script_callback_language" "python" } + } +} diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/ExtraFileOptions b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/ExtraFileOptions new file mode 100644 index 0000000000..3f31fdb65e --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/ExtraFileOptions @@ -0,0 +1,102 @@ +{ + "OnCreated/Cursor":{ + "type":"intarray", + "value":[11,71] + }, + "OnCreated/IsExpr":{ + "type":"bool", + "value":false + }, + "OnCreated/IsPython":{ + "type":"bool", + "value":true + }, + "OnCreated/IsScript":{ + "type":"bool", + "value":true + }, + "OnCreated/Source":{ + "type":"string", + "value":"" + }, + "OnDeleted/Cursor":{ + "type":"intarray", + "value":[7,1] + }, + "OnDeleted/IsExpr":{ + "type":"bool", + "value":false + }, + "OnDeleted/IsPython":{ + "type":"bool", + "value":true + }, + "OnDeleted/IsScript":{ + "type":"bool", + "value":true + }, + "OnDeleted/Source":{ + "type":"string", + "value":"" + }, + "OnLoaded/Cursor":{ + "type":"intarray", + "value":[15,1] + }, + "OnLoaded/IsExpr":{ + "type":"bool", + "value":false + }, + "OnLoaded/IsPython":{ + "type":"bool", + "value":true + }, + "OnLoaded/IsScript":{ + "type":"bool", + "value":true + }, + "OnLoaded/Source":{ + "type":"string", + "value":"" + }, + "OnNameChanged/Cursor":{ + "type":"intarray", + "value":[9,1] + }, + "OnNameChanged/IsExpr":{ + "type":"bool", + "value":false + }, + "OnNameChanged/IsPython":{ + "type":"bool", + "value":true + }, + "OnNameChanged/IsScript":{ + "type":"bool", + "value":true + }, + "OnNameChanged/Source":{ + "type":"string", + "value":"" + }, + "PythonModule/Cursor":{ + "type":"intarray", + "value":[11,1] + }, + "PythonModule/IsExpr":{ + "type":"bool", + "value":false + }, + "PythonModule/IsPython":{ + "type":"bool", + "value":true + }, + "PythonModule/IsScript":{ + "type":"bool", + "value":true + }, + "PythonModule/Source":{ + "type":"string", + "value":"" + } +} diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/Help b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/Help new file mode 100644 index 0000000000..e69de29bb2 diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/IconImage b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/IconImage new file mode 100644 index 0000000000..cd1f2fde76 Binary files /dev/null and b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/IconImage differ diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/InternalFileOptions b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/InternalFileOptions new file mode 100644 index 0000000000..222988aa02 --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/InternalFileOptions @@ -0,0 +1,10 @@ +{ + "nodeconntype":{ + "type":"bool", + "value":false + }, + "nodeparmtype":{ + "type":"bool", + "value":false + } +} diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/OnCreated b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/OnCreated new file mode 100644 index 0000000000..63537e4e5b --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/OnCreated @@ -0,0 +1,13 @@ +node = kwargs["node"] +hda_module = node.hdaModule() +hda_module.setup_flag_changed_callback(node) + +node.parm("file").lock(True) + +# Get attribute defaults from settings +# TODO: Clean this up and re-use more from HDA utils lib +from ayon_core.settings import get_current_project_settings +settings = get_current_project_settings() +load_settings = settings["houdini"].get("load", {}).get("GenericLoader", {}) +use_ayon_entity_uri = load_settings.get("use_ayon_entity_uri", False) +node.parm("use_ayon_entity_uri").set(use_ayon_entity_uri) diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/OnDeleted b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/OnDeleted new file mode 100644 index 0000000000..42e4ef2401 --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/OnDeleted @@ -0,0 +1,6 @@ +from ayon_houdini.api.lib import remove_all_thumbnails + + +# Clear thumbnails +node = kwargs["node"] +remove_all_thumbnails(node) diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/OnLoaded b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/OnLoaded new file mode 100644 index 0000000000..9d5dfd7749 --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/OnLoaded @@ -0,0 +1,14 @@ +node = kwargs["node"] +hda_module = node.hdaModule() +hda_module.setup_flag_changed_callback(node) + + +# Duplicate callback +def on_duplicate(): + """Duplicate thumbnail on node duplicate""" + if node.evalParm("show_thumbnail") and node.evalParm("representation"): + hda_module.update_thumbnail(node) + + +if not hou.hipFile.isLoadingHipFile(): + on_duplicate() diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/OnNameChanged b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/OnNameChanged new file mode 100644 index 0000000000..2076f5ad9d --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/OnNameChanged @@ -0,0 +1,8 @@ +from ayon_houdini.api.hda_utils import ( + keep_background_images_linked +) + + +node = kwargs["node"] +old_name = kwargs["old_name"] +keep_background_images_linked(node, old_name) diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/PythonModule b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/PythonModule new file mode 100644 index 0000000000..f1f9592243 --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/PythonModule @@ -0,0 +1,11 @@ +from ayon_houdini.api.hda_utils import ( + on_thumbnail_show_changed, + on_thumbnail_size_changed, + update_thumbnail, + setup_flag_changed_callback, + get_available_versions, + get_available_representations, + select_product_name, + set_to_latest_version, + expression_clear_cache +) diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/Sections.list b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/Sections.list new file mode 100644 index 0000000000..c6d20f84f3 --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/Sections.list @@ -0,0 +1,15 @@ +"" +DialogScript DialogScript +CreateScript CreateScript +InternalFileOptions InternalFileOptions +Contents.gz Contents.gz +TypePropertiesOptions TypePropertiesOptions +Tools.shelf Tools.shelf +Help Help +IconImage IconImage +PythonModule PythonModule +OnCreated OnCreated +OnLoaded OnLoaded +OnDeleted OnDeleted +OnNameChanged OnNameChanged +ExtraFileOptions ExtraFileOptions diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/Tools.shelf b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/Tools.shelf new file mode 100644 index 0000000000..67ffa05787 --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/Tools.shelf @@ -0,0 +1,19 @@ + + + + + + SOP + + + $HDA_TABLE_AND_NAME + + AYON + + + + \ No newline at end of file diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/TypePropertiesOptions b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/TypePropertiesOptions new file mode 100644 index 0000000000..a6d52acf2a --- /dev/null +++ b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/ayon_8_8Sop_1generic__loader_8_81.0/TypePropertiesOptions @@ -0,0 +1,14 @@ +CheckExternal := 1; +ContentsCompressionType := 1; +ForbidOutsideParms := 1; +GzipContents := 1; +LockContents := 1; +MakeDefault := 1; +ParmsFromVfl := 0; +PrefixDroppedParmLabel := 0; +PrefixDroppedParmName := 0; +SaveCachedCode := 0; +SaveIcon := 1; +SaveSpareParms := 0; +UnlockOnCreate := 0; +UseDSParms := 1; diff --git a/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/houdini.hdalibrary b/client/ayon_houdini/startup/otls/ayon.generic_loader.hda/houdini.hdalibrary new file mode 100644 index 0000000000..e69de29bb2