Merge pull request #262 from BigRoy/enhancement/houdini_prompt_save_task_change

Houdini: Prompt reset scene context on saving to another task
This commit is contained in:
Ondřej Samohel 2024-03-27 14:38:40 +01:00 committed by GitHub
commit 7d9ddb4dd7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 128 additions and 19 deletions

View file

@ -447,7 +447,7 @@ def maintained_selection():
node.setSelected(on=True)
def reset_framerange():
def reset_framerange(fps=True, frame_range=True):
"""Set frame range and FPS to current folder."""
project_name = get_current_project_name()
@ -456,29 +456,32 @@ def reset_framerange():
folder_entity = ayon_api.get_folder_by_path(project_name, folder_path)
folder_attributes = folder_entity["attrib"]
# Get FPS
fps = get_folder_fps(folder_entity)
# Set FPS
if fps:
fps = get_folder_fps(folder_entity)
print("Setting scene FPS to {}".format(int(fps)))
set_scene_fps(fps)
# Get Start and End Frames
frame_start = folder_attributes.get("frameStart")
frame_end = folder_attributes.get("frameEnd")
if frame_range:
if frame_start is None or frame_end is None:
log.warning("No edit information found for '{}'".format(folder_path))
return
# Set Start and End Frames
frame_start = folder_attributes.get("frameStart")
frame_end = folder_attributes.get("frameEnd")
handle_start = folder_attributes.get("handleStart", 0)
handle_end = folder_attributes.get("handleEnd", 0)
if frame_start is None or frame_end is None:
log.warning("No edit information found for '%s'", folder_path)
return
frame_start -= int(handle_start)
frame_end += int(handle_end)
handle_start = folder_attributes.get("handleStart", 0)
handle_end = folder_attributes.get("handleEnd", 0)
# Set frame range and FPS
print("Setting scene FPS to {}".format(int(fps)))
set_scene_fps(fps)
hou.playbar.setFrameRange(frame_start, frame_end)
hou.playbar.setPlaybackRange(frame_start, frame_end)
hou.setFrame(frame_start)
frame_start -= int(handle_start)
frame_end += int(handle_end)
# Set frame range and FPS
hou.playbar.setFrameRange(frame_start, frame_end)
hou.playbar.setPlaybackRange(frame_start, frame_end)
hou.setFrame(frame_start)
def get_main_window():
@ -993,3 +996,84 @@ def add_self_publish_button(node):
template = node.parmTemplateGroup()
template.insertBefore((0,), button_parm)
node.setParmTemplateGroup(template)
def update_content_on_context_change():
"""Update all Creator instances to current asset"""
host = registered_host()
context = host.get_current_context()
folder_path = context["folder_path"]
task = context["task_name"]
create_context = CreateContext(host, reset=True)
for instance in create_context.instances:
instance_folder_path = instance.get("folderPath")
if instance_folder_path and instance_folder_path != folder_path:
instance["folderPath"] = folder_path
instance_task = instance.get("task")
if instance_task and instance_task != task:
instance["task"] = task
create_context.save_changes()
def prompt_reset_context():
"""Prompt the user what context settings to reset.
This prompt is used on saving to a different task to allow the scene to
get matched to the new context.
"""
# TODO: Cleanup this prototyped mess of imports and odd dialog
from ayon_core.tools.attribute_defs.dialog import (
AttributeDefinitionsDialog
)
from ayon_core.style import load_stylesheet
from ayon_core.lib import BoolDef, UILabelDef
definitions = [
UILabelDef(
label=(
"You are saving your workfile into a different folder or task."
"\n\n"
"Would you like to update some settings to the new context?\n"
)
),
BoolDef(
"fps",
label="FPS",
tooltip="Reset workfile FPS",
default=True
),
BoolDef(
"frame_range",
label="Frame Range",
tooltip="Reset workfile start and end frame ranges",
default=True
),
BoolDef(
"instances",
label="Publish instances",
tooltip="Update all publish instance's folder and task to match "
"the new folder and task",
default=True
),
]
dialog = AttributeDefinitionsDialog(definitions)
dialog.setWindowTitle("Saving to different context.")
dialog.setStyleSheet(load_stylesheet())
if not dialog.exec_():
return None
options = dialog.get_values()
if options["fps"] or options["frame_range"]:
reset_framerange(
fps=options["fps"],
frame_range=options["frame_range"]
)
if options["instances"]:
update_content_on_context_change()
dialog.deleteLater()

View file

@ -39,6 +39,9 @@ LOAD_PATH = os.path.join(PLUGINS_DIR, "load")
CREATE_PATH = os.path.join(PLUGINS_DIR, "create")
INVENTORY_PATH = os.path.join(PLUGINS_DIR, "inventory")
# Track whether the workfile tool is about to save
ABOUT_TO_SAVE = False
class HoudiniHost(HostBase, IWorkfileHost, ILoadHost, IPublishHost):
name = "houdini"
@ -61,10 +64,12 @@ class HoudiniHost(HostBase, IWorkfileHost, ILoadHost, IPublishHost):
log.info("Installing callbacks ... ")
# register_event_callback("init", on_init)
self._register_callbacks()
register_event_callback("workfile.save.before", before_workfile_save)
register_event_callback("before.save", before_save)
register_event_callback("save", on_save)
register_event_callback("open", on_open)
register_event_callback("new", on_new)
register_event_callback("taskChanged", on_task_changed)
self._has_been_setup = True
@ -287,6 +292,11 @@ def ls():
yield parse_container(container)
def before_workfile_save(event):
global ABOUT_TO_SAVE
ABOUT_TO_SAVE = True
def before_save():
return lib.validate_fps()
@ -298,6 +308,21 @@ def on_save():
# update houdini vars
lib.update_houdini_vars_context_dialog()
nodes = lib.get_id_required_nodes()
for node, new_id in lib.generate_ids(nodes):
lib.set_id(node, new_id, overwrite=False)
# We are now starting the actual save directly
global ABOUT_TO_SAVE
ABOUT_TO_SAVE = False
def on_task_changed():
global ABOUT_TO_SAVE
if not IS_HEADLESS and ABOUT_TO_SAVE:
# Let's prompt the user to update the context settings or not
lib.prompt_reset_context()
def _show_outdated_content_popup():
# Get main window