From 1c076eba729de8743d11c0ba13b5dca97b2c7f12 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 5 Jul 2024 22:29:32 +0200 Subject: [PATCH 01/13] Fix #17: Remove `HOUDINI_MENU_PATH` because `HOUDINI_PATH` is already set and contains our menus --- client/ayon_houdini/addon.py | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/client/ayon_houdini/addon.py b/client/ayon_houdini/addon.py index 4c23553008..d9b836c4c7 100644 --- a/client/ayon_houdini/addon.py +++ b/client/ayon_houdini/addon.py @@ -12,14 +12,11 @@ class HoudiniAddon(AYONAddon, IHostAddon): host_name = "houdini" def add_implementation_envs(self, env, _app): - # Add requirements to HOUDINI_PATH and HOUDINI_MENU_PATH + # Add requirements to HOUDINI_PATH startup_path = os.path.join(HOUDINI_HOST_DIR, "startup") new_houdini_path = [startup_path] - new_houdini_menu_path = [startup_path] old_houdini_path = env.get("HOUDINI_PATH") or "" - old_houdini_menu_path = env.get("HOUDINI_MENU_PATH") or "" - for path in old_houdini_path.split(os.pathsep): if not path: continue @@ -28,20 +25,9 @@ def add_implementation_envs(self, env, _app): if norm_path not in new_houdini_path: new_houdini_path.append(norm_path) - for path in old_houdini_menu_path.split(os.pathsep): - if not path: - continue - - norm_path = os.path.normpath(path) - if norm_path not in new_houdini_menu_path: - new_houdini_menu_path.append(norm_path) - - # Add ampersand for unknown reason (Maybe is needed in Houdini?) + # Add & (ampersand), it represents "the standard Houdini Path contents" new_houdini_path.append("&") - new_houdini_menu_path.append("&") - env["HOUDINI_PATH"] = os.pathsep.join(new_houdini_path) - env["HOUDINI_MENU_PATH"] = os.pathsep.join(new_houdini_menu_path) def get_launch_hook_paths(self, app): if app.host_name != self.host_name: From 481c928770136e6cc789ffa6dce2edc90d32a22a Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 5 Jul 2024 23:01:31 +0200 Subject: [PATCH 02/13] Load Asset LOP allow to pick product type, make sure filtered product names are sorted --- client/ayon_houdini/api/hda_utils.py | 7 +++++-- .../ayon_8_8Lop_1lop__import_8_81.0/DialogScript | 8 +++++++- .../ayon_8_8Lop_1lop__import_8_81.0/OnCreated | 1 - 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/client/ayon_houdini/api/hda_utils.py b/client/ayon_houdini/api/hda_utils.py index 412364bc04..2023825f39 100644 --- a/client/ayon_houdini/api/hda_utils.py +++ b/client/ayon_houdini/api/hda_utils.py @@ -569,13 +569,16 @@ def get_available_products(node): if not folder_entity: return [] + # Apply filter only if any value is set + product_types = [product_type] if product_type else None + products = ayon_api.get_products( project_name, folder_ids=[folder_entity["id"]], - product_types=[product_type] + product_types=product_types ) - return [product["name"] for product in products] + return list(sorted(product["name"] for product in products)) def set_to_latest_version(node): diff --git a/client/ayon_houdini/startup/otls/ayon_lop_import.hda/ayon_8_8Lop_1lop__import_8_81.0/DialogScript b/client/ayon_houdini/startup/otls/ayon_lop_import.hda/ayon_8_8Lop_1lop__import_8_81.0/DialogScript index 3c97d10f35..00875fb462 100644 --- a/client/ayon_houdini/startup/otls/ayon_lop_import.hda/ayon_8_8Lop_1lop__import_8_81.0/DialogScript +++ b/client/ayon_houdini/startup/otls/ayon_lop_import.hda/ayon_8_8Lop_1lop__import_8_81.0/DialogScript @@ -3,7 +3,7 @@ { name ayon::lop_import::1.0 script load_asset::1.0 - label "Load Asset" + label "AYON Load Asset" help { "" @@ -52,6 +52,12 @@ label "Product Type" type string default { "usd" } + menu { + "usd" "usd" + "pointcache" "pointcache" + "model" "model" + "" "*" + } } parm { name "product_name" diff --git a/client/ayon_houdini/startup/otls/ayon_lop_import.hda/ayon_8_8Lop_1lop__import_8_81.0/OnCreated b/client/ayon_houdini/startup/otls/ayon_lop_import.hda/ayon_8_8Lop_1lop__import_8_81.0/OnCreated index 06ccdaa653..bd09a7838b 100644 --- a/client/ayon_houdini/startup/otls/ayon_lop_import.hda/ayon_8_8Lop_1lop__import_8_81.0/OnCreated +++ b/client/ayon_houdini/startup/otls/ayon_lop_import.hda/ayon_8_8Lop_1lop__import_8_81.0/OnCreated @@ -2,5 +2,4 @@ node = kwargs["node"] hda_module = node.hdaModule() hda_module.setup_flag_changed_callback(node) -node.parm("product_type").lock(True) node.parm("file").lock(True) From b4b03c6232967f6d5c98b1ca4498700f554a3665 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 5 Jul 2024 23:14:08 +0200 Subject: [PATCH 03/13] Sort product types alphabetically, add camera product type --- .../ayon_8_8Lop_1lop__import_8_81.0/DialogScript | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/client/ayon_houdini/startup/otls/ayon_lop_import.hda/ayon_8_8Lop_1lop__import_8_81.0/DialogScript b/client/ayon_houdini/startup/otls/ayon_lop_import.hda/ayon_8_8Lop_1lop__import_8_81.0/DialogScript index 00875fb462..fa9e3b7099 100644 --- a/client/ayon_houdini/startup/otls/ayon_lop_import.hda/ayon_8_8Lop_1lop__import_8_81.0/DialogScript +++ b/client/ayon_houdini/startup/otls/ayon_lop_import.hda/ayon_8_8Lop_1lop__import_8_81.0/DialogScript @@ -53,10 +53,11 @@ type string default { "usd" } menu { - "usd" "usd" - "pointcache" "pointcache" - "model" "model" "" "*" + "camera" "camera" + "model" "model" + "pointcache" "pointcache" + "usd" "usd" } } parm { From ba5c8a77df6ab3b874b77688d62aeb57ab3d264c Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 5 Jul 2024 23:34:43 +0200 Subject: [PATCH 04/13] Update product type parm to the loaded product if it mismatches --- client/ayon_houdini/api/hda_utils.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/client/ayon_houdini/api/hda_utils.py b/client/ayon_houdini/api/hda_utils.py index 2023825f39..bb66f2242f 100644 --- a/client/ayon_houdini/api/hda_utils.py +++ b/client/ayon_houdini/api/hda_utils.py @@ -129,6 +129,14 @@ def update_info(node, context): if node.evalParm(key) != value} parms["load_message"] = "" # clear any warnings/errors + # Update the product type filter to match the type + current = node.evalParm("product_type") + product_type = context["product"]["productType"] + if current or current != product_type: + # If current is empty we consider no filtering applied and we allow + # that to be a state that needs no switching + parms["product_type"] = product_type + # Note that these never trigger any parm callbacks since we do not # trigger the `parm.pressButton` and programmatically setting values # in Houdini does not trigger callbacks automatically From bcfd46a14713b22dc9f79f9f3823dccae6c5debb Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 5 Jul 2024 23:35:43 +0200 Subject: [PATCH 05/13] Fix if statement --- client/ayon_houdini/api/hda_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_houdini/api/hda_utils.py b/client/ayon_houdini/api/hda_utils.py index bb66f2242f..8b8b0a323b 100644 --- a/client/ayon_houdini/api/hda_utils.py +++ b/client/ayon_houdini/api/hda_utils.py @@ -132,7 +132,7 @@ def update_info(node, context): # Update the product type filter to match the type current = node.evalParm("product_type") product_type = context["product"]["productType"] - if current or current != product_type: + if current and current != product_type: # If current is empty we consider no filtering applied and we allow # that to be a state that needs no switching parms["product_type"] = product_type From 2e32aafd2d240eb40cfa5e5fbfe4987a4c45ea33 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sat, 6 Jul 2024 00:57:49 +0200 Subject: [PATCH 06/13] Fix #14: Use task entity attributes instead fo folder attributes --- client/ayon_houdini/api/lib.py | 69 ++++++++++--------- client/ayon_houdini/api/shelves.py | 4 +- .../inventory/set_camera_resolution.py | 6 +- .../ayon_houdini/plugins/load/load_camera.py | 2 +- .../plugins/publish/collect_asset_handles.py | 14 ++-- .../plugins/publish/validate_frame_range.py | 19 +++-- 6 files changed, 59 insertions(+), 55 deletions(-) diff --git a/client/ayon_houdini/api/lib.py b/client/ayon_houdini/api/lib.py index eec3995821..4a74a51814 100644 --- a/client/ayon_houdini/api/lib.py +++ b/client/ayon_houdini/api/lib.py @@ -22,7 +22,7 @@ ) from ayon_core.pipeline.create import CreateContext from ayon_core.pipeline.template_data import get_template_data -from ayon_core.pipeline.context_tools import get_current_folder_entity +from ayon_core.pipeline.context_tools import get_current_task_entity from ayon_core.tools.utils import PopupUpdateKeys, SimplePopup from ayon_core.tools.utils.host_tools import get_tool_by_name @@ -35,12 +35,12 @@ JSON_PREFIX = "JSON:::" -def get_folder_fps(folder_entity=None): - """Return current folder fps.""" +def get_entity_fps(entity=None): + """Return current task fps or fps from an entity.""" - if folder_entity is None: - folder_entity = get_current_folder_entity(fields=["attrib.fps"]) - return folder_entity["attrib"]["fps"] + if entity is None: + entity = get_current_task_entity(fields=["attrib.fps"]) + return entity["attrib"]["fps"] def get_output_parameter(node): @@ -121,7 +121,7 @@ def validate_fps(): """ - fps = get_folder_fps() + fps = get_entity_fps() current_fps = hou.fps() # returns float if current_fps != fps: @@ -400,7 +400,7 @@ def reset_framerange(fps=True, frame_range=True): # Set FPS if fps: - fps = get_folder_fps(folder_entity) + fps = get_entity_fps(folder_entity) print("Setting scene FPS to {}".format(int(fps))) set_scene_fps(fps) @@ -646,43 +646,43 @@ def get_output_children(output_node, include_sops=True): return out_list -def get_resolution_from_folder(folder_entity): +def get_resolution_from_entity(entity): """Get resolution from the given folder entity. Args: - folder_entity (dict[str, Any]): Folder entity. + entity (dict[str, Any]): Project, Folder or Task entity. Returns: Union[Tuple[int, int], None]: Resolution width and height. """ - if not folder_entity or "attrib" not in folder_entity: + if not entity or "attrib" not in entity: print("Entered folder is not valid. \"{}\"".format( - str(folder_entity) + str(entity) )) return None - folder_attributes = folder_entity["attrib"] + folder_attributes = entity["attrib"] resolution_width = folder_attributes.get("resolutionWidth") resolution_height = folder_attributes.get("resolutionHeight") # Make sure both width and height are set if resolution_width is None or resolution_height is None: print("No resolution information found for '{}'".format( - folder_entity["path"] + entity["path"] )) return None return int(resolution_width), int(resolution_height) -def set_camera_resolution(camera, folder_entity=None): - """Apply resolution to camera from folder entity of the publish""" +def set_camera_resolution(camera, task_entity=None): + """Apply resolution to camera from task entity of the publish""" - if not folder_entity: - folder_entity = get_current_folder_entity() + if not task_entity: + task_entity = get_current_task_entity() - resolution = get_resolution_from_folder(folder_entity) + resolution = get_resolution_from_entity(task_entity) if resolution: print("Setting camera resolution: {} -> {}x{}".format( @@ -705,10 +705,13 @@ def get_camera_from_container(container): return cameras[0] -def get_current_context_template_data_with_folder_attrs(): - """ +def get_current_context_template_data_with_entity_attrs(): + """Return template data including current context folder and task attribs. - Output contains 'folderAttributes' key with folder attribute values. + Output contains: + - Regular template data from `get_template_data` + - 'folderAttributes' key with folder attribute values. + - 'taskAttributes' key with task attribute values. Returns: dict[str, Any]: Template data to fill templates. @@ -729,23 +732,25 @@ def get_current_context_template_data_with_folder_attrs(): # get context specific vars folder_attributes = folder_entity["attrib"] + task_attributes = task_entity["attrib"] # compute `frameStartHandle` and `frameEndHandle` - frame_start = folder_attributes.get("frameStart") - frame_end = folder_attributes.get("frameEnd") - handle_start = folder_attributes.get("handleStart") - handle_end = folder_attributes.get("handleEnd") - if frame_start is not None and handle_start is not None: - folder_attributes["frameStartHandle"] = frame_start - handle_start - - if frame_end is not None and handle_end is not None: - folder_attributes["frameEndHandle"] = frame_end + handle_end + for attributes in [folder_attributes, task_attributes]: + frame_start = attributes.get("frameStart") + frame_end = attributes.get("frameEnd") + handle_start = attributes.get("handleStart") + handle_end = attributes.get("handleEnd") + if frame_start is not None and handle_start is not None: + attributes["frameStartHandle"] = frame_start - handle_start + if frame_end is not None and handle_end is not None: + attributes["frameEndHandle"] = frame_end + handle_end template_data = get_template_data( project_entity, folder_entity, task_entity, host_name ) template_data["root"] = anatomy.roots template_data["folderAttributes"] = folder_attributes + template_data["taskAttributes"] = task_attributes return template_data @@ -806,7 +811,7 @@ def get_context_var_changes(): return houdini_vars_to_update # Get Template data - template_data = get_current_context_template_data_with_folder_attrs() + template_data = get_current_context_template_data_with_entity_attrs() # Set Houdini Vars for item in houdini_vars: diff --git a/client/ayon_houdini/api/shelves.py b/client/ayon_houdini/api/shelves.py index 2987568af1..9fadb30e88 100644 --- a/client/ayon_houdini/api/shelves.py +++ b/client/ayon_houdini/api/shelves.py @@ -10,7 +10,7 @@ import hou -from .lib import get_current_context_template_data_with_folder_attrs +from .lib import get_current_context_template_data_with_entity_attrs log = logging.getLogger("ayon_houdini.shelves") @@ -31,7 +31,7 @@ def generate_shelves(): return # Get Template data - template_data = get_current_context_template_data_with_folder_attrs() + template_data = get_current_context_template_data_with_entity_attrs() for config in shelves_configs: selected_option = config["options"] diff --git a/client/ayon_houdini/plugins/inventory/set_camera_resolution.py b/client/ayon_houdini/plugins/inventory/set_camera_resolution.py index e2f8fcfa9b..dc558ad2ef 100644 --- a/client/ayon_houdini/plugins/inventory/set_camera_resolution.py +++ b/client/ayon_houdini/plugins/inventory/set_camera_resolution.py @@ -3,7 +3,7 @@ get_camera_from_container, set_camera_resolution ) -from ayon_core.pipeline.context_tools import get_current_folder_entity +from ayon_core.pipeline.context_tools import get_current_task_entity class SetCameraResolution(InventoryAction): @@ -19,8 +19,8 @@ def is_compatible(container): ) def process(self, containers): - folder_entity = get_current_folder_entity() + task_entity = get_current_task_entity() for container in containers: node = container["node"] camera = get_camera_from_container(node) - set_camera_resolution(camera, folder_entity) + set_camera_resolution(camera, task_entity) diff --git a/client/ayon_houdini/plugins/load/load_camera.py b/client/ayon_houdini/plugins/load/load_camera.py index b597519813..3eb5be9da9 100644 --- a/client/ayon_houdini/plugins/load/load_camera.py +++ b/client/ayon_houdini/plugins/load/load_camera.py @@ -121,7 +121,7 @@ def load(self, context, name=None, namespace=None, data=None): camera = get_camera_from_container(node) self._match_maya_render_mask(camera) - set_camera_resolution(camera, folder_entity=context["folder"]) + set_camera_resolution(camera, task_entity=context["folder"]) self[:] = nodes return pipeline.containerise(node_name, diff --git a/client/ayon_houdini/plugins/publish/collect_asset_handles.py b/client/ayon_houdini/plugins/publish/collect_asset_handles.py index db9bde8595..d5c8576dbe 100644 --- a/client/ayon_houdini/plugins/publish/collect_asset_handles.py +++ b/client/ayon_houdini/plugins/publish/collect_asset_handles.py @@ -8,7 +8,7 @@ class CollectAssetHandles(plugin.HoudiniInstancePlugin, AYONPyblishPluginMixin): - """Apply folder handles. + """Apply instance's task entity handles. If instance does not have: - frameStart @@ -19,7 +19,7 @@ class CollectAssetHandles(plugin.HoudiniInstancePlugin, - frameStartHandle - frameEndHandle - Then we will retrieve the folder's handles to compute + Then we will retrieve the task's handles to compute the exclusive frame range and actual handle ranges. """ @@ -27,7 +27,7 @@ class CollectAssetHandles(plugin.HoudiniInstancePlugin, # this plugin runs after CollectAnatomyInstanceData order = pyblish.api.CollectorOrder + 0.499 - label = "Collect Folder Handles" + label = "Collect Task Handles" use_asset_handles = True def process(self, instance): @@ -50,9 +50,9 @@ def process(self, instance): attr_values = self.get_attr_values_from_data(instance.data) if attr_values.get("use_handles", self.use_asset_handles): - folder_attributes = instance.data["folderEntity"]["attrib"] - handle_start = folder_attributes.get("handleStart", 0) - handle_end = folder_attributes.get("handleEnd", 0) + task_attributes = instance.data["taskEntity"]["attrib"] + handle_start = task_attributes.get("handleStart", 0) + handle_end = task_attributes.get("handleEnd", 0) else: handle_start = 0 handle_end = 0 @@ -116,7 +116,7 @@ def get_attribute_defs(cls): BoolDef("use_handles", tooltip="Disable this if you want the publisher to" " ignore start and end handles specified in the" - " folder attributes for this publish instance", + " task attributes for this publish instance", default=cls.use_asset_handles, label="Use asset handles") ] diff --git a/client/ayon_houdini/plugins/publish/validate_frame_range.py b/client/ayon_houdini/plugins/publish/validate_frame_range.py index 9435fa033a..f977524865 100644 --- a/client/ayon_houdini/plugins/publish/validate_frame_range.py +++ b/client/ayon_houdini/plugins/publish/validate_frame_range.py @@ -9,9 +9,8 @@ from ayon_houdini.api import plugin - -class DisableUseFolderHandlesAction(RepairAction): - label = "Disable use folder handles" +class DisableUseTaskHandlesAction(RepairAction): + label = "Disable use task handles" icon = "mdi.toggle-switch-off" @@ -25,7 +24,7 @@ class ValidateFrameRange(plugin.HoudiniInstancePlugin): order = pyblish.api.ValidatorOrder - 0.1 label = "Validate Frame Range" - actions = [DisableUseFolderHandlesAction, SelectInvalidAction] + actions = [DisableUseTaskHandlesAction, SelectInvalidAction] def process(self, instance): @@ -43,11 +42,11 @@ def process(self, instance): "## Invalid Frame Range\n" "The frame range for the instance is invalid because " "the start frame is higher than the end frame.\n\nThis " - "is likely due to folder handles being applied to your " + "is likely due to task handles being applied to your " "instance or the ROP node's start frame " "is set higher than the end frame.\n\nIf your ROP frame " - "range is correct and you do not want to apply folder " - "handles make sure to disable Use folder handles on the " + "range is correct and you do not want to apply task " + "handles make sure to disable Use task handles on the " "publish instance." ) ) @@ -73,7 +72,7 @@ def get_invalid(cls, instance): cls.log.info( "The ROP node render range is set to " "{0[frameStartHandle]} - {0[frameEndHandle]} " - "The folder handles applied to the instance are start handle " + "The task handles applied to the instance are start handle " "{0[handleStart]} and end handle {0[handleEnd]}" .format(instance.data) ) @@ -86,7 +85,7 @@ def repair(cls, instance): # Already fixed return - # Disable use folder handles + # Disable use task handles context = instance.context create_context = context.data["create_context"] instance_id = instance.data.get("instance_id") @@ -104,5 +103,5 @@ def repair(cls, instance): created_instance.publish_attributes["CollectAssetHandles"]["use_handles"] = False # noqa create_context.save_changes() - cls.log.debug("use folder handles is turned off for '{}'" + cls.log.debug("use task handles is turned off for '{}'" .format(instance)) From 3c04e5c76a4e351f3ac9989ed194732c968371e6 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sat, 6 Jul 2024 01:11:12 +0200 Subject: [PATCH 07/13] Use more task entity attributes instead of folder attributes --- client/ayon_houdini/api/lib.py | 47 +++++++++++++++------------------- 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/client/ayon_houdini/api/lib.py b/client/ayon_houdini/api/lib.py index 4a74a51814..ffe311c297 100644 --- a/client/ayon_houdini/api/lib.py +++ b/client/ayon_houdini/api/lib.py @@ -14,7 +14,6 @@ from ayon_core.settings import get_current_project_settings from ayon_core.pipeline import ( Anatomy, - get_current_project_name, get_current_folder_path, registered_host, get_current_context, @@ -392,30 +391,29 @@ def parm_values(overrides): def reset_framerange(fps=True, frame_range=True): """Set frame range and FPS to current folder.""" - project_name = get_current_project_name() - folder_path = get_current_folder_path() - - folder_entity = ayon_api.get_folder_by_path(project_name, folder_path) - folder_attributes = folder_entity["attrib"] + task_entity = get_current_task_entity() # Set FPS if fps: - fps = get_entity_fps(folder_entity) + fps = get_entity_fps(task_entity) print("Setting scene FPS to {}".format(int(fps))) set_scene_fps(fps) if frame_range: # Set Start and End Frames - frame_start = folder_attributes.get("frameStart") - frame_end = folder_attributes.get("frameEnd") + frame_start = task_entity.get("frameStart") + frame_end = task_entity.get("frameEnd") if frame_start is None or frame_end is None: - log.warning("No edit information found for '%s'", folder_path) + folder_path = get_current_folder_path() + task_name = task_entity["name"] + log.warning("No edit information found for '%s' > '%s'", + folder_path, task_name) return - handle_start = folder_attributes.get("handleStart", 0) - handle_end = folder_attributes.get("handleEnd", 0) + handle_start = task_entity.get("handleStart", 0) + handle_end = task_entity.get("handleEnd", 0) frame_start -= int(handle_start) frame_end += int(handle_end) @@ -507,7 +505,7 @@ def get_frame_data(node, log=None): log.info( "Node '{}' has 'Render current frame' set.\n" - "Folder Handles are ignored.\n" + "Task handles are ignored.\n" "frameStart and frameEnd are set to the " "current frame.".format(node.path()) ) @@ -647,7 +645,7 @@ def get_output_children(output_node, include_sops=True): def get_resolution_from_entity(entity): - """Get resolution from the given folder entity. + """Get resolution from the given entity. Args: entity (dict[str, Any]): Project, Folder or Task entity. @@ -657,20 +655,15 @@ def get_resolution_from_entity(entity): """ if not entity or "attrib" not in entity: - print("Entered folder is not valid. \"{}\"".format( - str(entity) - )) - return None + raise ValueError(f"Entity is not valid: \"{entity}\"") - folder_attributes = entity["attrib"] - resolution_width = folder_attributes.get("resolutionWidth") - resolution_height = folder_attributes.get("resolutionHeight") + attributes = entity["attrib"] + resolution_width = attributes.get("resolutionWidth") + resolution_height = attributes.get("resolutionHeight") # Make sure both width and height are set if resolution_width is None or resolution_height is None: - print("No resolution information found for '{}'".format( - entity["path"] - )) + print(f"No resolution information found in entity: '{entity}'") return None return int(resolution_width), int(resolution_height) @@ -843,7 +836,7 @@ def get_context_var_changes(): def update_houdini_vars_context(): - """Update folder context variables""" + """Update task context variables""" for var, (_old, new, is_directory) in get_context_var_changes().items(): if is_directory: @@ -862,7 +855,7 @@ def update_houdini_vars_context(): def update_houdini_vars_context_dialog(): - """Show pop-up to update folder context variables""" + """Show pop-up to update task context variables""" update_vars = get_context_var_changes() if not update_vars: # Nothing to change @@ -878,7 +871,7 @@ def update_houdini_vars_context_dialog(): parent = hou.ui.mainQtWindow() dialog = SimplePopup(parent=parent) dialog.setModal(True) - dialog.setWindowTitle("Houdini scene has outdated folder variables") + dialog.setWindowTitle("Houdini scene has outdated task variables") dialog.set_message(message) dialog.set_button_text("Fix") From 6dc4ece3db6992b70cd52fa3da14b906ab2b84c5 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 11 Jul 2024 14:08:39 +0200 Subject: [PATCH 08/13] Update client/ayon_houdini/startup/otls/ayon_lop_import.hda/ayon_8_8Lop_1lop__import_8_81.0/DialogScript --- .../ayon_8_8Lop_1lop__import_8_81.0/DialogScript | 1 + 1 file changed, 1 insertion(+) diff --git a/client/ayon_houdini/startup/otls/ayon_lop_import.hda/ayon_8_8Lop_1lop__import_8_81.0/DialogScript b/client/ayon_houdini/startup/otls/ayon_lop_import.hda/ayon_8_8Lop_1lop__import_8_81.0/DialogScript index fa9e3b7099..dee8fa4c8f 100644 --- a/client/ayon_houdini/startup/otls/ayon_lop_import.hda/ayon_8_8Lop_1lop__import_8_81.0/DialogScript +++ b/client/ayon_houdini/startup/otls/ayon_lop_import.hda/ayon_8_8Lop_1lop__import_8_81.0/DialogScript @@ -54,6 +54,7 @@ default { "usd" } menu { "" "*" + "animation" "animation" "camera" "camera" "model" "model" "pointcache" "pointcache" From d503cab825f1c284a6b359fce6ffa7a1be710f5c Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 11 Jul 2024 22:46:32 +0200 Subject: [PATCH 09/13] Fall back to folder entity if task is not set --- .../ayon_houdini/plugins/publish/collect_asset_handles.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/client/ayon_houdini/plugins/publish/collect_asset_handles.py b/client/ayon_houdini/plugins/publish/collect_asset_handles.py index d5c8576dbe..ce24671263 100644 --- a/client/ayon_houdini/plugins/publish/collect_asset_handles.py +++ b/client/ayon_houdini/plugins/publish/collect_asset_handles.py @@ -50,9 +50,11 @@ def process(self, instance): attr_values = self.get_attr_values_from_data(instance.data) if attr_values.get("use_handles", self.use_asset_handles): - task_attributes = instance.data["taskEntity"]["attrib"] - handle_start = task_attributes.get("handleStart", 0) - handle_end = task_attributes.get("handleEnd", 0) + # Get from task (if task is set), otherwise from folder + entity = instance.data.get("taskEntity", + instance.data["folderEntity"]) + handle_start = entity["attrib"].get("handleStart", 0) + handle_end = entity["attrib"].get("handleEnd", 0) else: handle_start = 0 handle_end = 0 From e501dbdae83b2908e43f53b13fbf99de349f4b08 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 11 Jul 2024 22:48:48 +0200 Subject: [PATCH 10/13] Refactor argument and improve docstring --- client/ayon_houdini/api/lib.py | 16 +++++++++++----- client/ayon_houdini/plugins/load/load_camera.py | 2 +- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/client/ayon_houdini/api/lib.py b/client/ayon_houdini/api/lib.py index ffe311c297..d51c0ba1fe 100644 --- a/client/ayon_houdini/api/lib.py +++ b/client/ayon_houdini/api/lib.py @@ -669,13 +669,19 @@ def get_resolution_from_entity(entity): return int(resolution_width), int(resolution_height) -def set_camera_resolution(camera, task_entity=None): - """Apply resolution to camera from task entity of the publish""" +def set_camera_resolution(camera, entity=None): + """Apply resolution to camera from task or folder entity. - if not task_entity: - task_entity = get_current_task_entity() + Arguments: + camera (hou.OpNode): Camera node. + entity (Optional[Dict[str, Any]]): Folder or task entity. + If not provided falls back to current task entity. + """ + + if not entity: + entity = get_current_task_entity() - resolution = get_resolution_from_entity(task_entity) + resolution = get_resolution_from_entity(entity) if resolution: print("Setting camera resolution: {} -> {}x{}".format( diff --git a/client/ayon_houdini/plugins/load/load_camera.py b/client/ayon_houdini/plugins/load/load_camera.py index 3eb5be9da9..b0fa83310f 100644 --- a/client/ayon_houdini/plugins/load/load_camera.py +++ b/client/ayon_houdini/plugins/load/load_camera.py @@ -121,7 +121,7 @@ def load(self, context, name=None, namespace=None, data=None): camera = get_camera_from_container(node) self._match_maya_render_mask(camera) - set_camera_resolution(camera, task_entity=context["folder"]) + set_camera_resolution(camera, entity=context["folder"]) self[:] = nodes return pipeline.containerise(node_name, From ab335170e34bd21af516a9c951492e0ce2355ca0 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 12 Jul 2024 15:40:52 +0200 Subject: [PATCH 11/13] Fix task entity access to frame ranges --- client/ayon_houdini/api/lib.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/client/ayon_houdini/api/lib.py b/client/ayon_houdini/api/lib.py index d51c0ba1fe..76ab4393bb 100644 --- a/client/ayon_houdini/api/lib.py +++ b/client/ayon_houdini/api/lib.py @@ -402,18 +402,12 @@ def reset_framerange(fps=True, frame_range=True): if frame_range: # Set Start and End Frames - frame_start = task_entity.get("frameStart") - frame_end = task_entity.get("frameEnd") - - if frame_start is None or frame_end is None: - folder_path = get_current_folder_path() - task_name = task_entity["name"] - log.warning("No edit information found for '%s' > '%s'", - folder_path, task_name) - return - - handle_start = task_entity.get("handleStart", 0) - handle_end = task_entity.get("handleEnd", 0) + task_attrib = task_entity["attrib"] + frame_start = task_attrib.get("frameStart", 0) + frame_end = task_attrib.get("frameEnd", 0) + + handle_start = task_attrib.get("handleStart", 0) + handle_end = task_attrib.get("handleEnd", 0) frame_start -= int(handle_start) frame_end += int(handle_end) From e20fbe045ed1480d01e529ccac054ec8a6c344b7 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 12 Jul 2024 15:42:27 +0200 Subject: [PATCH 12/13] Request less data from database --- client/ayon_houdini/api/lib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_houdini/api/lib.py b/client/ayon_houdini/api/lib.py index 76ab4393bb..4f46ba2964 100644 --- a/client/ayon_houdini/api/lib.py +++ b/client/ayon_houdini/api/lib.py @@ -391,7 +391,7 @@ def parm_values(overrides): def reset_framerange(fps=True, frame_range=True): """Set frame range and FPS to current folder.""" - task_entity = get_current_task_entity() + task_entity = get_current_task_entity(fields={"attrib"}) # Set FPS if fps: From 56e679f8f0385371f6e04c0788d38db116d14add Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 12 Jul 2024 16:54:52 +0200 Subject: [PATCH 13/13] Update client/ayon_houdini/api/lib.py Co-authored-by: Mustafa Taher --- client/ayon_houdini/api/lib.py | 1 - 1 file changed, 1 deletion(-) diff --git a/client/ayon_houdini/api/lib.py b/client/ayon_houdini/api/lib.py index 4f46ba2964..3c2520250d 100644 --- a/client/ayon_houdini/api/lib.py +++ b/client/ayon_houdini/api/lib.py @@ -14,7 +14,6 @@ from ayon_core.settings import get_current_project_settings from ayon_core.pipeline import ( Anatomy, - get_current_folder_path, registered_host, get_current_context, get_current_host_name,