-
Notifications
You must be signed in to change notification settings - Fork 128
Bugfix: houdini switching context doesnt update variables #5651
Bugfix: houdini switching context doesnt update variables #5651
Conversation
openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_general.json
Outdated
Show resolved
Hide resolved
654c9fa
to
32a88fd
Compare
0ba8f02
to
a349733
Compare
Should we add admin docs for this feature? |
Yes, we should. At least let the user know $JOB would be not showed or errored out if they enabled the toggled button with the non-existent path. |
Can you share a screenshot of the current dialog you get when context changes? |
Hey yeah I'm sorry I've been hammered in my studio firefighting production needs and haven't had time to do what I said I would. Let me share here the quick and dirty implementation I did of this: I added this on the def on_open():
if not hou.isUIAvailable():
log.debug("Batch mode detected, ignoring `on_open` callbacks..")
return
log.info("Running callback on open..")
outdated_asset_variables = lib.get_outdated_asset_variables()
if outdated_asset_variables:
parent = lib.get_main_window()
if parent is None:
# When opening Houdini with last workfile on launch the UI hasn't
# initialized yet completely when the `on_open` callback triggers.
# We defer the dialog popup to wait for the UI to become available.
# We assume it will open because `hou.isUIAvailable()` returns True
import hdefereval
hdefereval.executeDeferred(
lib.show_outdated_asset_variables_popup,
outdated_asset_variables
)
else:
lib.show_outdated_asset_variables_popup(outdated_asset_variables)
log.warning("Scene has outdated context variables.") And these are the functions that Ia dded on the def set_scene_resolution(width, height, pix_aspect):
if width:
hou.hscript(f"set -g RESX={width}")
hou.hscript("varchange -V RESX")
if height:
hou.hscript(f"set -g RESY={height}")
hou.hscript("varchange -V RESY")
if pix_aspect:
hou.hscript(f"set -g PIX_AR={pix_aspect}")
hou.hscript("varchange -V PIX_AR")
def get_outdated_asset_variables():
outdated_variables = {}
asset_doc = get_current_project_asset()
# Validate FPS
fps = get_asset_fps()
current_fps = hou.fps() # returns float
if current_fps != fps:
outdated_variables["FPS"] = (current_fps, fps)
# Validate resolution
width, height, pix_aspect = get_resolution_from_doc(asset_doc)
cur_width = hou.getenv("RESX")
cur_height = hou.getenv("RESY")
cur_pix_aspect = hou.getenv("PIX_AR")
if width != cur_width:
outdated_variables["RESX"] = (cur_width, width)
if height != cur_height:
outdated_variables["RESY"] = (cur_height, height)
if pix_aspect != cur_pix_aspect:
outdated_variables["PIX_AR"] = (cur_pix_aspect, pix_aspect)
return outdated_variables
def show_outdated_asset_variables_popup(outdated_variables):
# Get main window
parent = get_main_window()
if parent is None:
log.info("Skipping outdated content pop-up "
"because Houdini window can't be found.")
else:
from openpype.widgets import popup
dialog = popup.PopupUpdateKeys(parent=parent)
dialog.setModal(True)
dialog.setWindowTitle("Houdini scene has outdated asset variables")
outaded_vars_list = []
for variable_name, outdated_value in outdated_variables.items():
cur_value, new_value = outdated_value
outaded_vars_list.append(
f"${variable_name}: {cur_value} -> {new_value}"
)
dialog.setMessage("\n".join(outaded_vars_list))
dialog.setButtonText("Fix")
new_width = None
outdated_width = outdated_variables.get("RESX")
if outdated_width:
new_width = outdated_width[1]
new_height = None
outdated_height = outdated_variables.get("RESY")
if outdated_height:
new_height = outdated_height[1]
new_pix_aspect = None
outdated_pix_aspect = outdated_variables.get("PIX_AR")
if outdated_pix_aspect:
new_pix_aspect = outdated_pix_aspect[1]
new_fps = None
outdated_fps = outdated_variables.get("FPS")
if outdated_fps:
new_fps = outdated_fps[1]
# on_show is the Fix button clicked callback
dialog.on_clicked_state.connect(
lambda: (
set_scene_resolution(new_width, new_height, new_pix_aspect),
set_scene_fps(new_fps)
)
)
dialog.show() Notice that I changed the existing def get_resolution_from_doc(doc):
"""Get resolution from the given asset document. """
if not doc or "data" not in doc:
print("Entered document is not valid. \"{}\"".format(str(doc)))
return None
resolution_width = doc["data"].get("resolutionWidth")
resolution_height = doc["data"].get("resolutionHeight")
pixel_aspect = doc["data"].get("pixelAspect")
# Make sure both width and height are set
if resolution_width is None or resolution_height is None \
or pixel_aspect is None:
print("No resolution information found for \"{}\"".format(doc["name"]))
return None
return int(resolution_width), int(resolution_height), float(pixel_aspect) This is very dirty and we should make a proper Qt dialog that's more user friendly and ideally something we can reuse in all other OP DCCs for startup dialog |
This startup dialog should show up automatically every time an artist opens (not saves) a scene and has outdated variables. Doing it as an on-demand button it's helpful for the cases you want to validate or trigger an update because you know some have been updated but the most common case should be when an artist starts to work on a scene, they want to know if there's been an update on any of those and choose if he wants to pull them or not |
@fabiaserra Never mind man!
I made a quick test with this PR |
Nice! that's looking good. Could we spend some cycles on this PR to make a better Qt dialog for this use case? We should be able to update each of the variables independently (although resolution I would probably expect to be a single entry) |
It's a great idea, however I prefer to add it as a |
Can you create a Github issue to track it once this PR is merged? The UX on path changes (since they are long) felt way off in this screenshot. |
@fabiaserra there there is popup dialog which can be imported by using |
That's the one currently being used, also see this comment. |
Yes I noticed that just now too :). So ignore my previous comment. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code looks good for a first prototype. Solid work.
Yeah that's the same one I used for my dirty implementation of this... but it's just so Windows 98 haha I wish I could show you a screenshot of the startup dialog we had in my prior company, it was so pretty and clear for the artists. I think a simple vertical layout with horizontal layouts of three QLabels (variable, current and new value) and an "Update" button next to it, inheriting the stylesheet of the OP widgets with a title of "Outdated scene variables" and the OP logo would have already gone a long way and shouldn't take more than an hour to write |
Changelog Description
Allows admins to have a list of vars (e.g. JOB) with (dynamic) values that will be updated on context changes, e.g. when switching to another asset or task.
Using template keys is supported but formatting keys capitalization variants is not, e.g. {Asset} and {ASSET} won't work
Note
If is Dir Path toggle is activated, Openpype will consider the given value as a path to a folder.
If the folder does not exist on the context change it will be created by this feature so that the path will always try to point to an existing folder.
Disabling Update Houdini vars on context change feature will leave all Houdini vars unmanaged and thus no context update changes will occur.
Also, this PR adds a new button in menu to update vars on demand.
Testing notes: