Bases: HoudiniInstancePlugin
, AYONPyblishPluginMixin
Apply instance's task entity handles.
If instance does not have
- frameStart
- frameEnd
- handleStart
- handleEnd
But it does have: - frameStartHandle - frameEndHandle
Then we will retrieve the task's handles to compute the exclusive frame range and actual handle ranges.
Source code in client/ayon_houdini/plugins/publish/collect_task_handles.py
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143 | class CollectAssetHandles(plugin.HoudiniInstancePlugin,
AYONPyblishPluginMixin):
"""Apply instance's task entity handles.
If instance does not have:
- frameStart
- frameEnd
- handleStart
- handleEnd
But it does have:
- frameStartHandle
- frameEndHandle
Then we will retrieve the task's handles to compute
the exclusive frame range and actual handle ranges.
"""
# TODO: This also validates against model products, even though those
# should export a single frame regardless so maybe it's redundantly
# validating?
# This specific order value is used so that
# this plugin runs after CollectAnatomyInstanceData
order = pyblish.api.CollectorOrder + 0.499
label = "Collect Task Handles"
use_asset_handles = True
ignore_product_types: set[str] = {"rig"}
def process(self, instance):
# Do no check asset handles for products that are essentially not
# intended to be time-based
if instance.data.get("productType") in self.ignore_product_types:
return
# 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):
# Get from task (if task is set), otherwise from folder
entity = instance.data.get("taskEntity",
instance.data["folderEntity"])
handle_start = entity["attrib"].get("handleStart", 0)
handle_end = entity["attrib"].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_handle} - {frame_end_handle}]"
.format(
label=label,
frame_start_handle=instance.data["frameStartHandle"],
frame_end_handle=instance.data["frameEndHandle"]
)
)
@classmethod
def get_attr_defs_for_instance(cls, create_context, instance):
if not cls.instance_matches_plugin_families(instance):
return []
if instance.data.get("productType") in cls.ignore_product_types:
return []
return [
BoolDef("use_handles",
tooltip="Disable this if you want the publisher to"
" ignore start and end handles specified in the"
" task attributes for this publish instance",
default=cls.use_asset_handles,
label="Use task handles")
]
|