Bases: OptionalPyblishPluginMixin, HoudiniInstancePlugin
Validate if the unexpanded string contains a frame token (e.g. '$F' or '@Frame').
This validator will only check the output parameter of the node if the "Use Custom Frames" attribute is set.
Rules
If "Use Custom Frames" attribute is set in publisher it is mandatory to have the frame token - '$F4' or similar - to ensure that each frame gets written. If this is not the case you may face black render as the output USD file may not cover the whole range.
Examples:
Good: 'render.$F4.usd' Bad: 'render.usd'
Source code in client/ayon_deadline/plugins/publish/houdini/validate_frame_token_usd_render.py
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 | class ValidateFrameTokenUSDRender(
OptionalPyblishPluginMixin,
plugin.HoudiniInstancePlugin
):
"""Validate if the unexpanded string contains a frame
token (e.g. '$F' or '@Frame').
This validator will *only* check the output parameter of the node if
the "Use Custom Frames" attribute is set.
Rules:
If "Use Custom Frames" attribute is set in publisher
it is mandatory to have the frame token - '$F4' or similar -
to ensure that each frame gets written.
If this is not the case you may face black render
as the output USD file may not cover the whole range.
Examples:
Good: '__render__.$F4.usd'
Bad: '__render__.usd'
"""
order = pyblish.api.ValidatorOrder
label = "Validate Frame Token (USD Render)"
families = ["usdrender"]
targets = ["local"]
hosts = ["houdini"]
optional = True
actions = [FixParameterAction, SelectInvalidAction]
settings_category = "deadline"
def process(self, instance):
if not self.is_active(instance.data):
return
if not instance.data.get("farm"):
self.log.debug("Not a farm instance, skipping.")
return
if "deadline.submit.publish.job" not in instance.data["families"]:
self.log.debug(
"Should only checked if submitting to deadline, skipping.")
return
job_info = instance.data["deadline"]["job_info"]
if job_info.Frames is None:
self.log.debug(
"Should only checked if deadline job has custom frames,"
" skipping."
)
return
invalid = self.get_invalid(instance)
if invalid:
raise PublishValidationError(
"No frame token found in the USD Export Output File parm in"
f" '{invalid[0].path()}'"
)
@classmethod
def get_invalid(cls, instance):
node = hou.node(instance.data["instance_node"])
output_parm = node.parm("lopoutput")
outparm_keyframs = output_parm.keyframes()
if outparm_keyframs:
cls.log.warning(
"Skipping validation: 'lopoutput' parm on "
f"{node.path()} is animated."
)
return
unexpanded_str = output_parm.unexpandedString()
if (
"$F" not in unexpanded_str
and
"@Frame" not in unexpanded_str
):
return [node]
@classmethod
def repair(cls, instance):
if not cls.get_invalid(instance):
# Already fixed
return
rop_node = hou.node(instance.data["instance_node"])
lopoutput = rop_node.parm("lopoutput").unexpandedString()
path, ext = os.path.splitext(lopoutput)
rop_node.parm("lopoutput").set(f"{path}.$F4{ext}")
|