nuke: [wip] validate script attributes

This commit is contained in:
Jakub Jezek 2022-07-25 16:49:11 +02:00
parent c5258fb295
commit d3e982ebcf
No known key found for this signature in database
GPG key ID: 730D7C02726179A7
4 changed files with 147 additions and 158 deletions

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<root>
<error id="main">
<title>Script attributes</title>
<description>
## Invalid Script attributes
Following script root attributes need to be fixed:
{missing_attributes}
### How to repair?
1. Either use Repair or Select button.
2. If you chose Select then rename asset knob to correct name.
3. Hit Reload button on the publisher.
</description>
</error>
</root>

View file

@ -1,156 +0,0 @@
import pyblish.api
from openpype.client import get_project, get_asset_by_id, get_asset_by_name
from openpype.pipeline import legacy_io
@pyblish.api.log
class ValidateScript(pyblish.api.InstancePlugin):
""" Validates file output. """
order = pyblish.api.ValidatorOrder + 0.1
families = ["workfile"]
label = "Check script settings"
hosts = ["nuke"]
optional = True
def process(self, instance):
ctx_data = instance.context.data
project_name = legacy_io.active_project()
asset_name = ctx_data["asset"]
# TODO repace query with using 'instance.data["assetEntity"]'
asset = get_asset_by_name(project_name, asset_name)
asset_data = asset["data"]
# These attributes will be checked
attributes = [
"fps",
"frameStart",
"frameEnd",
"resolutionWidth",
"resolutionHeight",
"handleStart",
"handleEnd"
]
# Value of these attributes can be found on parents
hierarchical_attributes = [
"fps",
"resolutionWidth",
"resolutionHeight",
"pixelAspect",
"handleStart",
"handleEnd"
]
missing_attributes = []
asset_attributes = {}
for attr in attributes:
if attr in asset_data:
asset_attributes[attr] = asset_data[attr]
elif attr in hierarchical_attributes:
# TODO this should be probably removed
# Hierarchical attributes is not a thing since Pype 2?
# Try to find attribute on parent
parent_id = asset['parent']
parent_type = "project"
if asset_data['visualParent'] is not None:
parent_type = "asset"
parent_id = asset_data['visualParent']
value = self.check_parent_hierarchical(
project_name, parent_type, parent_id, attr
)
if value is None:
missing_attributes.append(attr)
else:
asset_attributes[attr] = value
else:
missing_attributes.append(attr)
# Raise error if attributes weren't found on asset in database
if len(missing_attributes) > 0:
atr = ", ".join(missing_attributes)
msg = 'Missing attributes "{}" in asset "{}"'
message = msg.format(atr, asset_name)
raise ValueError(message)
# Get handles from database, Default is 0 (if not found)
handle_start = 0
handle_end = 0
if "handleStart" in asset_attributes:
handle_start = asset_attributes["handleStart"]
if "handleEnd" in asset_attributes:
handle_end = asset_attributes["handleEnd"]
asset_attributes["fps"] = float("{0:.4f}".format(
asset_attributes["fps"]))
# Get values from nukescript
script_attributes = {
"handleStart": ctx_data["handleStart"],
"handleEnd": ctx_data["handleEnd"],
"fps": float("{0:.4f}".format(ctx_data["fps"])),
"frameStart": ctx_data["frameStart"],
"frameEnd": ctx_data["frameEnd"],
"resolutionWidth": ctx_data["resolutionWidth"],
"resolutionHeight": ctx_data["resolutionHeight"],
"pixelAspect": ctx_data["pixelAspect"]
}
# Compare asset's values Nukescript X Database
not_matching = []
for attr in attributes:
self.log.debug("asset vs script attribute \"{}\": {}, {}".format(
attr, asset_attributes[attr], script_attributes[attr])
)
if asset_attributes[attr] != script_attributes[attr]:
not_matching.append(attr)
# Raise error if not matching
if len(not_matching) > 0:
msg = "Attributes '{}' are not set correctly"
# Alert user that handles are set if Frame start/end not match
if (
(("frameStart" in not_matching) or ("frameEnd" in not_matching)) and
((handle_start > 0) or (handle_end > 0))
):
msg += " (`handle_start` are set to {})".format(handle_start)
msg += " (`handle_end` are set to {})".format(handle_end)
message = msg.format(", ".join(not_matching))
raise ValueError(message)
def check_parent_hierarchical(
self, project_name, parent_type, parent_id, attr
):
if parent_id is None:
return None
doc = None
if parent_type == "project":
doc = get_project(project_name)
elif parent_type == "asset":
doc = get_asset_by_id(project_name, parent_id)
if not doc:
return None
doc_data = doc["data"]
if attr in doc_data:
self.log.info(attr)
return doc_data[attr]
if parent_type == "project":
return None
parent_id = doc_data.get("visualParent")
new_parent_type = "asset"
if parent_id is None:
parent_id = doc["parent"]
new_parent_type = "project"
return self.check_parent_hierarchical(
project_name, new_parent_type, parent_id, attr
)

View file

@ -0,0 +1,129 @@
from pprint import pformat
import pyblish.api
from openpype.client import get_project, get_asset_by_id, get_asset_by_name
from openpype.pipeline import legacy_io
from openpype.pipeline import PublishXmlValidationError
import nuke
@pyblish.api.log
class ValidateScriptAttributes(pyblish.api.InstancePlugin):
""" Validates file output. """
order = pyblish.api.ValidatorOrder + 0.1
families = ["workfile"]
label = "Validatte script attributes"
hosts = ["nuke"]
optional = True
def process(self, instance):
ctx_data = instance.context.data
project_name = legacy_io.active_project()
asset_name = ctx_data["asset"]
asset = get_asset_by_name(project_name, asset_name)
asset_data = asset["data"]
# These attributes will be checked
attributes = [
"fps",
"frameStart",
"frameEnd",
"resolutionWidth",
"resolutionHeight",
"handleStart",
"handleEnd"
]
asset_attributes = {
attr: asset_data[attr]
for attr in attributes
if attr in asset_data
}
self.log.debug(pformat(
asset_attributes
))
handle_start = asset_attributes["handleStart"]
handle_end = asset_attributes["handleEnd"]
asset_attributes["fps"] = float("{0:.4f}".format(
asset_attributes["fps"]))
root = nuke.root()
# Get values from nukescript
script_attributes = {
"handleStart": ctx_data["handleStart"],
"handleEnd": ctx_data["handleEnd"],
"fps": float("{0:.4f}".format(ctx_data["fps"])),
"frameStart": int(root["first_frame"].getValue()),
"frameEnd": int(root["last_frame"].getValue()),
"resolutionWidth": ctx_data["resolutionWidth"],
"resolutionHeight": ctx_data["resolutionHeight"],
"pixelAspect": ctx_data["pixelAspect"]
}
self.log.debug(pformat(
script_attributes
))
# Compare asset's values Nukescript X Database
not_matching = []
for attr in attributes:
self.log.debug(
"Asset vs Script attribute \"{}\": {}, {}".format(
attr,
asset_attributes[attr],
script_attributes[attr]
)
)
if asset_attributes[attr] != script_attributes[attr]:
not_matching.append({
"name": attr,
"expected": asset_attributes[attr],
"actual": script_attributes[attr]
})
# Raise error if not matching
if not_matching:
msg = "Attributes '{}' are not set correctly"
# Alert user that handles are set if Frame start/end not match
message = msg.format(", ".join(
[at["name"] for at in not_matching]))
raise PublishXmlValidationError(
self, message,
formatting_data={
"missing_attributes": not_matching
}
)
def check_parent_hierarchical(
self, project_name, parent_type, parent_id, attr
):
if parent_id is None:
return None
doc = None
if parent_type == "project":
doc = get_project(project_name)
elif parent_type == "asset":
doc = get_asset_by_id(project_name, parent_id)
if not doc:
return None
doc_data = doc["data"]
if attr in doc_data:
self.log.info(attr)
return doc_data[attr]
if parent_type == "project":
return None
parent_id = doc_data.get("visualParent")
new_parent_type = "asset"
if parent_id is None:
parent_id = doc["parent"]
new_parent_type = "project"
return self.check_parent_hierarchical(
project_name, new_parent_type, parent_id, attr
)

View file

@ -1,10 +1,8 @@
import pyblish.api
from openpype.api import get_errored_instances_from_context
import openpype.hosts.nuke.api.lib as nlib
from openpype.hosts.nuke.api.lib import (
get_write_node_template_attr,
set_node_knobs_from_settings
)
from openpype.pipeline import PublishXmlValidationError