Add CollectAssetHandles and modify associated files

This commit is contained in:
MustafaJafar 2023-11-03 11:18:09 +02:00
parent dca872e1fc
commit 8fb7266ff8
13 changed files with 151 additions and 103 deletions

View file

@ -569,9 +569,9 @@ def get_template_from_value(key, value):
return parm return parm
def get_frame_data(node, handle_start=0, handle_end=0, log=None): def get_frame_data(node, log=None):
"""Get the frame data: start frame, end frame, steps, """Get the frame data: `frameStartHandle`, `frameEndHandle`
start frame with start handle and end frame with end handle. and `byFrameStep`.
This function uses Houdini node's `trange`, `t1, `t2` and `t3` This function uses Houdini node's `trange`, `t1, `t2` and `t3`
parameters as the source of truth for the full inclusive frame parameters as the source of truth for the full inclusive frame
@ -579,20 +579,17 @@ def get_frame_data(node, handle_start=0, handle_end=0, log=None):
range including the handles. range including the handles.
The non-inclusive frame start and frame end without handles The non-inclusive frame start and frame end without handles
are computed by subtracting the handles from the inclusive can be computed by subtracting the handles from the inclusive
frame range. frame range.
Args: Args:
node (hou.Node): ROP node to retrieve frame range from, node (hou.Node): ROP node to retrieve frame range from,
the frame range is assumed to be the frame range the frame range is assumed to be the frame range
*including* the start and end handles. *including* the start and end handles.
handle_start (int): Start handles.
handle_end (int): End handles.
log (logging.Logger): Logger to log to.
Returns: Returns:
dict: frame data for start, end, steps, dict: frame data for `frameStartHandle`, `frameEndHandle`
start with handle and end with handle and `byFrameStep`.
""" """
@ -623,11 +620,6 @@ def get_frame_data(node, handle_start=0, handle_end=0, log=None):
data["frameEndHandle"] = int(node.evalParm("f2")) data["frameEndHandle"] = int(node.evalParm("f2"))
data["byFrameStep"] = node.evalParm("f3") data["byFrameStep"] = node.evalParm("f3")
data["handleStart"] = handle_start
data["handleEnd"] = handle_end
data["frameStart"] = data["frameStartHandle"] + data["handleStart"]
data["frameEnd"] = data["frameEndHandle"] - data["handleEnd"]
return data return data

View file

@ -22,7 +22,7 @@ class CollectArnoldROPRenderProducts(pyblish.api.InstancePlugin):
label = "Arnold ROP Render Products" label = "Arnold ROP Render Products"
# This specific order value is used so that # This specific order value is used so that
# this plugin runs after CollectFrames # this plugin runs after CollectFrames
order = pyblish.api.CollectorOrder + 0.49999 order = pyblish.api.CollectorOrder + 0.11
hosts = ["houdini"] hosts = ["houdini"]
families = ["arnold_rop"] families = ["arnold_rop"]

View file

@ -0,0 +1,125 @@
# -*- coding: utf-8 -*-
"""Collector plugin for frames data on ROP instances."""
import hou # noqa
import pyblish.api
from openpype.lib import BoolDef
from openpype.pipeline import OpenPypePyblishPluginMixin
class CollectAssetHandles(pyblish.api.InstancePlugin,
OpenPypePyblishPluginMixin):
"""Apply asset handles.
If instance does not have:
- frameStart
- frameEnd
- handleStart
- handleEnd
But it does have:
- frameStartHandle
- frameEndHandle
Then we will retrieve the asset's handles to compute
the exclusive frame range and actual handle ranges.
"""
hosts = ["houdini"]
# This specific order value is used so that
# this plugin runs after CollectAnatomyInstanceData
order = pyblish.api.CollectorOrder + 0.499
label = "Collect Asset Handles"
use_asset_handles = True
def process(self, instance):
# Only process instances without already existing handles data
# but that do have frameStartHandle and frameEndHandle defined
# like the data collected from CollectRopFrameRange
if "frameStartHandle" not in instance.data:
return
if "frameEndHandle" not in instance.data:
return
has_existing_data = {
"handleStart",
"handleEnd",
"frameStart",
"frameEnd"
}.issubset(instance.data)
if has_existing_data:
return
attr_values = self.get_attr_values_from_data(instance.data)
if attr_values.get("use_handles", self.use_asset_handles):
asset_data = instance.data["assetEntity"]["data"]
handle_start = asset_data.get("handleStart", 0)
handle_end = asset_data.get("handleEnd", 0)
else:
handle_start = 0
handle_end = 0
frame_start = instance.data["frameStartHandle"] + handle_start
frame_end = instance.data["frameEndHandle"] - handle_end
instance.data.update({
"handleStart": handle_start,
"handleEnd": handle_end,
"frameStart": frame_start,
"frameEnd": frame_end
})
# Log debug message about the collected frame range
if attr_values.get("use_handles", self.use_asset_handles):
self.log.debug(
"Full Frame range with Handles "
"[{frame_start_handle} - {frame_end_handle}]"
.format(
frame_start_handle=instance.data["frameStartHandle"],
frame_end_handle=instance.data["frameEndHandle"]
)
)
else:
self.log.debug(
"Use handles is deactivated for this instance, "
"start and end handles are set to 0."
)
# Log collected frame range to the user
message = "Frame range [{frame_start} - {frame_end}]".format(
frame_start=frame_start,
frame_end=frame_end
)
if handle_start or handle_end:
message += " with handles [{handle_start}]-[{handle_end}]".format(
handle_start=handle_start,
handle_end=handle_end
)
self.log.info(message)
if instance.data.get("byFrameStep", 1.0) != 1.0:
self.log.info(
"Frame steps {}".format(instance.data["byFrameStep"]))
# Add frame range to label if the instance has a frame range.
label = instance.data.get("label", instance.data["name"])
instance.data["label"] = (
"{label} [{frame_start} - {frame_end}]"
.format(
label=label,
frame_start=frame_start,
frame_end=frame_end
)
)
@classmethod
def get_attribute_defs(cls):
return [
BoolDef("use_handles",
tooltip="Disable this if you want the publisher to"
" ignore start and end handles specified in the"
" asset data for this publish instance",
default=cls.use_asset_handles,
label="Use asset handles")
]

View file

@ -13,7 +13,7 @@ class CollectFrames(pyblish.api.InstancePlugin):
# This specific order value is used so that # This specific order value is used so that
# this plugin runs after CollectRopFrameRange # this plugin runs after CollectRopFrameRange
order = pyblish.api.CollectorOrder + 0.4999 order = pyblish.api.CollectorOrder + 0.1
label = "Collect Frames" label = "Collect Frames"
families = ["vdbcache", "imagesequence", "ass", families = ["vdbcache", "imagesequence", "ass",
"redshiftproxy", "review", "bgeo"] "redshiftproxy", "review", "bgeo"]
@ -22,8 +22,8 @@ class CollectFrames(pyblish.api.InstancePlugin):
ropnode = hou.node(instance.data["instance_node"]) ropnode = hou.node(instance.data["instance_node"])
start_frame = instance.data.get("frameStart", None) start_frame = instance.data.get("frameStartHandle", None)
end_frame = instance.data.get("frameEnd", None) end_frame = instance.data.get("frameEndHandle", None)
output_parm = lib.get_output_parameter(ropnode) output_parm = lib.get_output_parameter(ropnode)
if start_frame is not None: if start_frame is not None:
@ -53,7 +53,7 @@ class CollectFrames(pyblish.api.InstancePlugin):
# Check if frames are bigger than 1 (file collection) # Check if frames are bigger than 1 (file collection)
# override the result # override the result
if end_frame - start_frame > 0: if end_frame - start_frame > 0:
result = self.create_file_list( result = self.create_file_list(self,
match, int(start_frame), int(end_frame) match, int(start_frame), int(end_frame)
) )
@ -62,7 +62,7 @@ class CollectFrames(pyblish.api.InstancePlugin):
instance.data.update({"frames": result}) instance.data.update({"frames": result})
@staticmethod @staticmethod
def create_file_list(match, start_frame, end_frame): def create_file_list(self,match, start_frame, end_frame):
"""Collect files based on frame range and `regex.match` """Collect files based on frame range and `regex.match`
Args: Args:

View file

@ -26,7 +26,7 @@ class CollectKarmaROPRenderProducts(pyblish.api.InstancePlugin):
label = "Karma ROP Render Products" label = "Karma ROP Render Products"
# This specific order value is used so that # This specific order value is used so that
# this plugin runs after CollectFrames # this plugin runs after CollectFrames
order = pyblish.api.CollectorOrder + 0.49999 order = pyblish.api.CollectorOrder + 0.11
hosts = ["houdini"] hosts = ["houdini"]
families = ["karma_rop"] families = ["karma_rop"]

View file

@ -26,7 +26,7 @@ class CollectMantraROPRenderProducts(pyblish.api.InstancePlugin):
label = "Mantra ROP Render Products" label = "Mantra ROP Render Products"
# This specific order value is used so that # This specific order value is used so that
# this plugin runs after CollectFrames # this plugin runs after CollectFrames
order = pyblish.api.CollectorOrder + 0.49999 order = pyblish.api.CollectorOrder + 0.11
hosts = ["houdini"] hosts = ["houdini"]
families = ["mantra_rop"] families = ["mantra_rop"]

View file

@ -26,7 +26,7 @@ class CollectRedshiftROPRenderProducts(pyblish.api.InstancePlugin):
label = "Redshift ROP Render Products" label = "Redshift ROP Render Products"
# This specific order value is used so that # This specific order value is used so that
# this plugin runs after CollectFrames # this plugin runs after CollectFrames
order = pyblish.api.CollectorOrder + 0.49999 order = pyblish.api.CollectorOrder + 0.11
hosts = ["houdini"] hosts = ["houdini"]
families = ["redshift_rop"] families = ["redshift_rop"]

View file

@ -2,22 +2,15 @@
"""Collector plugin for frames data on ROP instances.""" """Collector plugin for frames data on ROP instances."""
import hou # noqa import hou # noqa
import pyblish.api import pyblish.api
from openpype.lib import BoolDef
from openpype.hosts.houdini.api import lib from openpype.hosts.houdini.api import lib
from openpype.pipeline import OpenPypePyblishPluginMixin
class CollectRopFrameRange(pyblish.api.InstancePlugin, class CollectRopFrameRange(pyblish.api.InstancePlugin):
OpenPypePyblishPluginMixin):
"""Collect all frames which would be saved from the ROP nodes""" """Collect all frames which would be saved from the ROP nodes"""
hosts = ["houdini"] hosts = ["houdini"]
# This specific order value is used so that order = pyblish.api.CollectorOrder
# this plugin runs after CollectAnatomyInstanceData
order = pyblish.api.CollectorOrder + 0.499
label = "Collect RopNode Frame Range" label = "Collect RopNode Frame Range"
use_asset_handles = True
def process(self, instance): def process(self, instance):
@ -30,78 +23,16 @@ class CollectRopFrameRange(pyblish.api.InstancePlugin,
return return
ropnode = hou.node(node_path) ropnode = hou.node(node_path)
attr_values = self.get_attr_values_from_data(instance.data)
if attr_values.get("use_handles", self.use_asset_handles):
asset_data = instance.data["assetEntity"]["data"]
handle_start = asset_data.get("handleStart", 0)
handle_end = asset_data.get("handleEnd", 0)
else:
handle_start = 0
handle_end = 0
frame_data = lib.get_frame_data( frame_data = lib.get_frame_data(
ropnode, handle_start, handle_end, self.log ropnode, self.log
) )
if not frame_data: if not frame_data:
return return
# Log debug message about the collected frame range # Log debug message about the collected frame range
frame_start = frame_data["frameStart"] self.log.debug(
frame_end = frame_data["frameEnd"] "Collected frame_data: {}".format(frame_data)
if attr_values.get("use_handles", self.use_asset_handles):
self.log.debug(
"Full Frame range with Handles "
"[{frame_start_handle} - {frame_end_handle}]"
.format(
frame_start_handle=frame_data["frameStartHandle"],
frame_end_handle=frame_data["frameEndHandle"]
)
)
else:
self.log.debug(
"Use handles is deactivated for this instance, "
"start and end handles are set to 0."
)
# Log collected frame range to the user
message = "Frame range [{frame_start} - {frame_end}]".format(
frame_start=frame_start,
frame_end=frame_end
) )
if handle_start or handle_end:
message += " with handles [{handle_start}]-[{handle_end}]".format(
handle_start=handle_start,
handle_end=handle_end
)
self.log.info(message)
if frame_data.get("byFrameStep", 1.0) != 1.0:
self.log.info("Frame steps {}".format(frame_data["byFrameStep"]))
instance.data.update(frame_data) instance.data.update(frame_data)
# Add frame range to label if the instance has a frame range.
label = instance.data.get("label", instance.data["name"])
instance.data["label"] = (
"{label} [{frame_start} - {frame_end}]"
.format(
label=label,
frame_start=frame_start,
frame_end=frame_end
)
)
@classmethod
def get_attribute_defs(cls):
return [
BoolDef("use_handles",
tooltip="Disable this if you want the publisher to"
" ignore start and end handles specified in the"
" asset data for this publish instance",
default=cls.use_asset_handles,
label="Use asset handles")
]

View file

@ -26,7 +26,7 @@ class CollectVrayROPRenderProducts(pyblish.api.InstancePlugin):
label = "VRay ROP Render Products" label = "VRay ROP Render Products"
# This specific order value is used so that # This specific order value is used so that
# this plugin runs after CollectFrames # this plugin runs after CollectFrames
order = pyblish.api.CollectorOrder + 0.49999 order = pyblish.api.CollectorOrder + 0.11
hosts = ["houdini"] hosts = ["houdini"]
families = ["vray_rop"] families = ["vray_rop"]

View file

@ -89,7 +89,7 @@ class ValidateFrameRange(pyblish.api.InstancePlugin):
.format(instance)) .format(instance))
return return
created_instance.publish_attributes["CollectRopFrameRange"]["use_handles"] = False # noqa created_instance.publish_attributes["CollectAssetHandles"]["use_handles"] = False # noqa
create_context.save_changes() create_context.save_changes()
cls.log.debug("use asset handles is turned off for '{}'" cls.log.debug("use asset handles is turned off for '{}'"

View file

@ -137,7 +137,7 @@
} }
}, },
"publish": { "publish": {
"CollectRopFrameRange": { "CollectAssetHandles": {
"use_asset_handles": true "use_asset_handles": true
}, },
"ValidateContainers": { "ValidateContainers": {

View file

@ -11,8 +11,8 @@
{ {
"type": "dict", "type": "dict",
"collapsible": true, "collapsible": true,
"key": "CollectRopFrameRange", "key": "CollectAssetHandles",
"label": "Collect Rop Frame Range", "label": "Collect Asset Handles",
"children": [ "children": [
{ {
"type": "label", "type": "label",

View file

@ -3,7 +3,7 @@ from ayon_server.settings import BaseSettingsModel
# Publish Plugins # Publish Plugins
class CollectRopFrameRangeModel(BaseSettingsModel): class CollectAssetHandlesModel(BaseSettingsModel):
"""Collect Frame Range """Collect Frame Range
Disable this if you want the publisher to Disable this if you want the publisher to
ignore start and end handles specified in the ignore start and end handles specified in the