Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Houdini: Extract active view as thumbnail when no thumbnail set #31

Merged
merged 20 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
361d21e
📸 allow taking snapshoots from houdini
MustafaJafar Dec 31, 2023
5658b10
🐾 Resolve Hound
MustafaJafar Dec 31, 2023
ab61e75
📝 Kuba's and Big Roy's comments
MustafaJafar Jan 3, 2024
9f1412f
Merge branch 'develop' into feature/houdini_allow_taking_snapshoots
MustafaJafar Jan 3, 2024
a27c7bf
✏️ fix typo
MustafaJafar Jan 3, 2024
b6a432d
🖼️ Extract active view as thumbnail
MustafaJafar Jan 3, 2024
08ccdfc
🦴 Resolve Hound
MustafaJafar Jan 3, 2024
0e7efc5
Kuba's comments - Better Code
MustafaJafar Jan 4, 2024
435cd9c
➖ Remove unnecessary comment
MustafaJafar Jan 5, 2024
3ffb6db
📝 Stick to Google doc string style
MustafaJafar Jan 9, 2024
3224f92
Merge branch 'develop' into feature/houdini_allow_taking_snapshoots
MustafaJafar Jan 16, 2024
5d60fb3
Merge branch 'develop' into feature/houdini_allow_taking_snapshoots
MustafaJafar Mar 4, 2024
62020ca
update 'sceneview_snapshot' docstring
MustafaJafar Mar 4, 2024
ab6d89c
wrap lib.sceneview_snapshot() into tempfile.NamedTemporaryFile
MustafaJafar Mar 4, 2024
8320ab7
Houdini: add a warning if no sceneview was found
MustafaJafar Mar 4, 2024
57af216
Merge branch 'develop' into feature/houdini_allow_taking_snapshoots |…
MustafaJafar Apr 2, 2024
71bb555
BigRoy's comments - Better doc strings
MustafaJafar Apr 2, 2024
f543e56
BigRoy's comment - Better logic
MustafaJafar Apr 2, 2024
634d0a8
Merge branch 'develop' into feature/houdini_allow_taking_snapshoots
antirotor Apr 9, 2024
ee5cd1b
Merge branch 'develop' into feature/houdini_allow_taking_snapshoots
antirotor Apr 10, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 73 additions & 2 deletions client/ayon_core/hosts/houdini/api/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -948,7 +948,7 @@ def self_publish():

Firstly, it gets the node and its dependencies.
Then, it deactivates all other ROPs
And finaly, it triggers the publishing action.
And finally, it triggers the publishing action.
"""

result, comment = hou.ui.readInput(
Expand Down Expand Up @@ -998,6 +998,77 @@ def add_self_publish_button(node):
node.setParmTemplateGroup(template)


def get_scene_viewer():
"""
Return an instance of a visible viewport.

There may be many, some could be closed, any visible are current
MustafaJafar marked this conversation as resolved.
Show resolved Hide resolved
"""
panes = hou.ui.paneTabs()
panes = [x for x in panes if x.type() == hou.paneTabType.SceneViewer]
panes = sorted(panes, key=lambda x: x.isCurrentTab())
if panes:
return panes[-1]

return None


def sceneview_snapshot(
sceneview,
filepath="$HIP/thumbnails/$HIPNAME.$F4.jpg",
frame_start=None,
frame_end=None):
"""Take a snapshot of your scene view.

It takes snapshot of your scene view for the given frame range.
So, it's capable of generating snapshots image sequence.
It works in different Houdini context e.g. Objects, Solaris

Example:
This is how the function can be used::

from ayon_core.hosts.houdini.api import lib
sceneview = hou.ui.paneTabOfType(hou.paneTabType.SceneViewer)
lib.sceneview_snapshot(sceneview)

Notes:
.png output will render poorly, so use .jpg.

How it works:
Get the current sceneviewer (may be more than one or hidden)
and screengrab the perspective viewport to a file in the
publish location to be picked up with the publish.

Credits:
https://www.sidefx.com/forum/topic/42808/?page=1#post-354796

Args:
sceneview (hou.SceneViewer): The scene view pane from which you want
to take a snapshot.
filepath (str): thumbnail filepath.
MustafaJafar marked this conversation as resolved.
Show resolved Hide resolved
frame_start (int): the frame at which snapshot starts
frame_end (int): the frame at which snapshot ends
"""

if frame_start is None:
frame_start = hou.frame()
if frame_end is None:
frame_end = frame_start

if not isinstance(sceneview, hou.SceneViewer):
log.debug("Wrong Input. {} is not of type hou.SceneViewer."
.format(sceneview))
return
viewport = sceneview.curViewport()

flip_settings = sceneview.flipbookSettings().stash()
flip_settings.frameRange((frame_start, frame_end))
flip_settings.output(filepath)
flip_settings.outputToMPlay(False)
sceneview.flipbook(viewport, flip_settings)
log.debug("A snapshot of sceneview has been saved to: {}".format(filepath))


def update_content_on_context_change():
"""Update all Creator instances to current asset"""
host = registered_host()
Expand Down Expand Up @@ -1076,4 +1147,4 @@ def prompt_reset_context():
if options["instances"]:
update_content_on_context_change()

dialog.deleteLater()
dialog.deleteLater()
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import pyblish.api
import tempfile
from ayon_core.pipeline import publish
from ayon_core.hosts.houdini.api import lib
from ayon_core.hosts.houdini.api.pipeline import IS_HEADLESS


class ExtractActiveViewThumbnail(publish.Extractor):
"""Set instance thumbnail to a screengrab of current active viewport.

This makes it so that if an instance does not have a thumbnail set yet that
it will get a thumbnail of the currently active view at the time of
publishing as a fallback.

"""
order = pyblish.api.ExtractorOrder + 0.49
label = "Extract Active View Thumbnail"
families = ["workfile"]
hosts = ["houdini"]

def process(self, instance):
if IS_HEADLESS:
self.log.debug(
"Skip extraction of active view thumbnail, due to being in"
"headless mode."
)
return

thumbnail = instance.data.get("thumbnailPath")
if not thumbnail:
view_thumbnail = self.get_view_thumbnail(instance)
if not view_thumbnail:
return

self.log.debug("Setting instance thumbnail path to: {}".format(
view_thumbnail
))
instance.data["thumbnailPath"] = view_thumbnail
MustafaJafar marked this conversation as resolved.
Show resolved Hide resolved

def get_view_thumbnail(self, instance):

sceneview = lib.get_scene_viewer()
MustafaJafar marked this conversation as resolved.
Show resolved Hide resolved
if sceneview is None:
self.log.warning("Skipping Extract Active View Thumbnail"
" because no scene view was detected.")
MustafaJafar marked this conversation as resolved.
Show resolved Hide resolved
return

with tempfile.NamedTemporaryFile("w", suffix=".jpg", delete=False) as tmp:
lib.sceneview_snapshot(sceneview, tmp.name)
thumbnail_path = tmp.name

instance.context.data["cleanupFullPaths"].append(thumbnail_path)
return thumbnail_path
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ line-ending = "auto"

[tool.codespell]
# Ignore words that are not in the dictionary.
ignore-words-list = "ayon,ynput"
ignore-words-list = "ayon,ynput,parms,parm,hda"
skip = "./.*,./package/*,*/vendor/*,*/unreal/integration/*,*/aftereffects/api/extension/js/libs/*"
count = true
quiet-level = 3
Expand Down
Loading