From c1a4204fb96d33fede2341096247a23dbce3cecd Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sun, 20 Feb 2022 22:56:07 +0100 Subject: [PATCH 1/5] Implement Reset Frame Range for Houdini --- openpype/hosts/houdini/api/lib.py | 34 +++++++++++++++++++ .../hosts/houdini/startup/MainMenuCommon.xml | 8 +++++ 2 files changed, 42 insertions(+) diff --git a/openpype/hosts/houdini/api/lib.py b/openpype/hosts/houdini/api/lib.py index 72f1c8e71f..5a087ea276 100644 --- a/openpype/hosts/houdini/api/lib.py +++ b/openpype/hosts/houdini/api/lib.py @@ -542,3 +542,37 @@ def maintained_selection(): if previous_selection: for node in previous_selection: node.setSelected(on=True) + + +def reset_framerange(): + """Set frame range to current asset""" + + asset_name = api.Session["AVALON_ASSET"] + asset = io.find_one({"name": asset_name, "type": "asset"}) + + frame_start = asset["data"].get("frameStart") + frame_end = asset["data"].get("frameEnd") + # Backwards compatibility + if frame_start is None or frame_end is None: + frame_start = asset["data"].get("edit_in") + frame_end = asset["data"].get("edit_out") + + if frame_start is None or frame_end is None: + log.warning("No edit information found for %s" % asset_name) + return + + handles = asset["data"].get("handles") or 0 + handle_start = asset["data"].get("handleStart") + if handle_start is None: + handle_start = handles + + handle_end = asset["data"].get("handleEnd") + if handle_end is None: + handle_end = handles + + frame_start -= int(handle_start) + frame_end += int(handle_end) + + hou.playbar.setFrameRange(frame_start, frame_end) + hou.playbar.setPlaybackRange(frame_start, frame_end) + hou.setFrame(frame_start) diff --git a/openpype/hosts/houdini/startup/MainMenuCommon.xml b/openpype/hosts/houdini/startup/MainMenuCommon.xml index b8c7f93d76..abfa3f136e 100644 --- a/openpype/hosts/houdini/startup/MainMenuCommon.xml +++ b/openpype/hosts/houdini/startup/MainMenuCommon.xml @@ -66,6 +66,14 @@ host_tools.show_workfiles(parent) ]]> + + + + + From e945775161cd86934464c62dd734ea876ea2448a Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sun, 20 Feb 2022 23:05:10 +0100 Subject: [PATCH 2/5] Set asset frame range on Houdini launch and for each new scene --- openpype/hosts/houdini/api/pipeline.py | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/houdini/api/pipeline.py b/openpype/hosts/houdini/api/pipeline.py index c3dbdc5ef5..69fb236432 100644 --- a/openpype/hosts/houdini/api/pipeline.py +++ b/openpype/hosts/houdini/api/pipeline.py @@ -66,9 +66,9 @@ def install(): sys.path.append(hou_pythonpath) - # Set asset FPS for the empty scene directly after launch of Houdini - # so it initializes into the correct scene FPS - _set_asset_fps() + # Set asset settings for the empty scene directly after launch of Houdini + # so it initializes into the correct scene FPS, Frame Range, etc. + _set_context_settings() def uninstall(): @@ -280,17 +280,31 @@ def on_open(*args): def on_new(_): """Set project resolution and fps when create a new file""" log.info("Running callback on new..") - _set_asset_fps() + _set_context_settings() -def _set_asset_fps(): - """Set Houdini scene FPS to the default required for current asset""" +def _set_context_settings(): + """Apply the project settings from the project definition + + Settings can be overwritten by an asset if the asset.data contains + any information regarding those settings. + + Examples of settings: + fps + resolution + renderer + + Returns: + None + """ # Set new scene fps fps = get_asset_fps() print("Setting scene FPS to %i" % fps) lib.set_scene_fps(fps) + lib.reset_framerange() + def on_pyblish_instance_toggled(instance, new_value, old_value): """Toggle saver tool passthrough states on instance toggles.""" From 46d3ee4ba4fa392c4ea90f0f9db2ba238b6e9312 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Sun, 20 Feb 2022 23:41:18 +0100 Subject: [PATCH 3/5] Add todo --- openpype/hosts/houdini/api/pipeline.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/hosts/houdini/api/pipeline.py b/openpype/hosts/houdini/api/pipeline.py index 69fb236432..5280a6b60a 100644 --- a/openpype/hosts/houdini/api/pipeline.py +++ b/openpype/hosts/houdini/api/pipeline.py @@ -68,6 +68,7 @@ def install(): # Set asset settings for the empty scene directly after launch of Houdini # so it initializes into the correct scene FPS, Frame Range, etc. + # todo: make sure this doesn't trigger when opening with last workfile _set_context_settings() From 88a6aaee70c21f1941704d4280dddc18a663410c Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 21 Feb 2022 16:15:10 +0100 Subject: [PATCH 4/5] Fix current frame not set correctly on new scene --- openpype/hosts/houdini/api/pipeline.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/openpype/hosts/houdini/api/pipeline.py b/openpype/hosts/houdini/api/pipeline.py index 5280a6b60a..4c55de7246 100644 --- a/openpype/hosts/houdini/api/pipeline.py +++ b/openpype/hosts/houdini/api/pipeline.py @@ -4,6 +4,7 @@ import logging import contextlib import hou +import hdefereval import pyblish.api import avalon.api @@ -283,6 +284,15 @@ def on_new(_): log.info("Running callback on new..") _set_context_settings() + # It seems that the current frame always gets reset to frame 1 on + # new scene. So we enforce current frame to be at the start of the playbar + # with execute deferred + def _enforce_start_frame(): + start = hou.playbar.playbackRange()[0] + hou.setFrame(start) + + hdefereval.executeDeferred(_enforce_start_frame) + def _set_context_settings(): """Apply the project settings from the project definition From 823164e6c49732fa96d6960f886b66d2e1d688fb Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 21 Feb 2022 16:29:57 +0100 Subject: [PATCH 5/5] Avoid on_new callback when opening a Houdini file --- openpype/hosts/houdini/api/pipeline.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/openpype/hosts/houdini/api/pipeline.py b/openpype/hosts/houdini/api/pipeline.py index 4c55de7246..1c08e72d65 100644 --- a/openpype/hosts/houdini/api/pipeline.py +++ b/openpype/hosts/houdini/api/pipeline.py @@ -281,6 +281,14 @@ def on_open(*args): def on_new(_): """Set project resolution and fps when create a new file""" + + if hou.hipFile.isLoadingHipFile(): + # This event also triggers when Houdini opens a file due to the + # new event being registered to 'afterClear'. As such we can skip + # 'new' logic if the user is opening a file anyway + log.debug("Skipping on new callback due to scene being opened.") + return + log.info("Running callback on new..") _set_context_settings()