mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-25 05:14:40 +01:00
Merge pull request #3117 from pypeclub/feature/OP-2998_Nuke-render-instance-with-subset-name-filtered-overrides
Nuke: render instance with subset name filtered overrides
This commit is contained in:
commit
b8649c5661
8 changed files with 184 additions and 108 deletions
|
|
@ -400,7 +400,7 @@ def add_write_node(name, **kwarg):
|
|||
return w
|
||||
|
||||
|
||||
def read(node):
|
||||
def read_avalon_data(node):
|
||||
"""Return user-defined knobs from given `node`
|
||||
|
||||
Args:
|
||||
|
|
@ -415,8 +415,6 @@ def read(node):
|
|||
return knob_name[len("avalon:"):]
|
||||
elif knob_name.startswith("ak:"):
|
||||
return knob_name[len("ak:"):]
|
||||
else:
|
||||
return knob_name
|
||||
|
||||
data = dict()
|
||||
|
||||
|
|
@ -445,7 +443,8 @@ def read(node):
|
|||
(knob_type == 26 and value)
|
||||
):
|
||||
key = compat_prefixed(knob_name)
|
||||
data[key] = value
|
||||
if key is not None:
|
||||
data[key] = value
|
||||
|
||||
if knob_name == first_user_knob:
|
||||
break
|
||||
|
|
@ -507,20 +506,74 @@ def get_created_node_imageio_setting(**kwarg):
|
|||
log.debug(kwarg)
|
||||
nodeclass = kwarg.get("nodeclass", None)
|
||||
creator = kwarg.get("creator", None)
|
||||
subset = kwarg.get("subset", None)
|
||||
|
||||
assert any([creator, nodeclass]), nuke.message(
|
||||
"`{}`: Missing mandatory kwargs `host`, `cls`".format(__file__))
|
||||
|
||||
imageio_nodes = get_nuke_imageio_settings()["nodes"]["requiredNodes"]
|
||||
imageio_nodes = get_nuke_imageio_settings()["nodes"]
|
||||
required_nodes = imageio_nodes["requiredNodes"]
|
||||
override_nodes = imageio_nodes["overrideNodes"]
|
||||
|
||||
imageio_node = None
|
||||
for node in imageio_nodes:
|
||||
for node in required_nodes:
|
||||
log.info(node)
|
||||
if (nodeclass in node["nukeNodeClass"]) and (
|
||||
creator in node["plugins"]):
|
||||
if (
|
||||
nodeclass in node["nukeNodeClass"]
|
||||
and creator in node["plugins"]
|
||||
):
|
||||
imageio_node = node
|
||||
break
|
||||
|
||||
log.debug("__ imageio_node: {}".format(imageio_node))
|
||||
|
||||
# find matching override node
|
||||
override_imageio_node = None
|
||||
for onode in override_nodes:
|
||||
log.info(onode)
|
||||
if nodeclass not in node["nukeNodeClass"]:
|
||||
continue
|
||||
|
||||
if creator not in node["plugins"]:
|
||||
continue
|
||||
|
||||
if (
|
||||
onode["subsets"]
|
||||
and not any(re.search(s, subset) for s in onode["subsets"])
|
||||
):
|
||||
continue
|
||||
|
||||
override_imageio_node = onode
|
||||
break
|
||||
|
||||
log.debug("__ override_imageio_node: {}".format(override_imageio_node))
|
||||
# add overrides to imageio_node
|
||||
if override_imageio_node:
|
||||
# get all knob names in imageio_node
|
||||
knob_names = [k["name"] for k in imageio_node["knobs"]]
|
||||
|
||||
for oknob in override_imageio_node["knobs"]:
|
||||
for knob in imageio_node["knobs"]:
|
||||
# override matching knob name
|
||||
if oknob["name"] == knob["name"]:
|
||||
log.debug(
|
||||
"_ overriding knob: `{}` > `{}`".format(
|
||||
knob, oknob
|
||||
))
|
||||
if not oknob["value"]:
|
||||
# remove original knob if no value found in oknob
|
||||
imageio_node["knobs"].remove(knob)
|
||||
else:
|
||||
# override knob value with oknob's
|
||||
knob["value"] = oknob["value"]
|
||||
|
||||
# add missing knobs into imageio_node
|
||||
if oknob["name"] not in knob_names:
|
||||
log.debug(
|
||||
"_ adding knob: `{}`".format(oknob))
|
||||
imageio_node["knobs"].append(oknob)
|
||||
knob_names.append(oknob["name"])
|
||||
|
||||
log.info("ImageIO node: {}".format(imageio_node))
|
||||
return imageio_node
|
||||
|
||||
|
|
@ -542,7 +595,7 @@ def get_imageio_input_colorspace(filename):
|
|||
def on_script_load():
|
||||
''' Callback for ffmpeg support
|
||||
'''
|
||||
if nuke.env['LINUX']:
|
||||
if nuke.env["LINUX"]:
|
||||
nuke.tcl('load ffmpegReader')
|
||||
nuke.tcl('load ffmpegWriter')
|
||||
else:
|
||||
|
|
@ -567,7 +620,7 @@ def check_inventory_versions():
|
|||
|
||||
if container:
|
||||
node = nuke.toNode(container["objectName"])
|
||||
avalon_knob_data = read(node)
|
||||
avalon_knob_data = read_avalon_data(node)
|
||||
|
||||
# get representation from io
|
||||
representation = legacy_io.find_one({
|
||||
|
|
@ -593,7 +646,7 @@ def check_inventory_versions():
|
|||
versions = legacy_io.find({
|
||||
"type": "version",
|
||||
"parent": version["parent"]
|
||||
}).distinct('name')
|
||||
}).distinct("name")
|
||||
|
||||
max_version = max(versions)
|
||||
|
||||
|
|
@ -623,20 +676,20 @@ def writes_version_sync():
|
|||
if _NODE_TAB_NAME not in each.knobs():
|
||||
continue
|
||||
|
||||
avalon_knob_data = read(each)
|
||||
avalon_knob_data = read_avalon_data(each)
|
||||
|
||||
try:
|
||||
if avalon_knob_data['families'] not in ["render"]:
|
||||
log.debug(avalon_knob_data['families'])
|
||||
if avalon_knob_data["families"] not in ["render"]:
|
||||
log.debug(avalon_knob_data["families"])
|
||||
continue
|
||||
|
||||
node_file = each['file'].value()
|
||||
node_file = each["file"].value()
|
||||
|
||||
node_version = "v" + get_version_from_path(node_file)
|
||||
log.debug("node_version: {}".format(node_version))
|
||||
|
||||
node_new_file = node_file.replace(node_version, new_version)
|
||||
each['file'].setValue(node_new_file)
|
||||
each["file"].setValue(node_new_file)
|
||||
if not os.path.isdir(os.path.dirname(node_new_file)):
|
||||
log.warning("Path does not exist! I am creating it.")
|
||||
os.makedirs(os.path.dirname(node_new_file))
|
||||
|
|
@ -665,18 +718,19 @@ def check_subsetname_exists(nodes, subset_name):
|
|||
bool: True of False
|
||||
"""
|
||||
return next((True for n in nodes
|
||||
if subset_name in read(n).get("subset", "")),
|
||||
if subset_name in read_avalon_data(n).get("subset", "")),
|
||||
False)
|
||||
|
||||
|
||||
def get_render_path(node):
|
||||
''' Generate Render path from presets regarding avalon knob data
|
||||
'''
|
||||
data = {'avalon': read(node)}
|
||||
data = {'avalon': read_avalon_data(node)}
|
||||
data_preset = {
|
||||
"nodeclass": data['avalon']['family'],
|
||||
"families": [data['avalon']['families']],
|
||||
"creator": data['avalon']['creator']
|
||||
"nodeclass": data["avalon"]["family"],
|
||||
"families": [data["avalon"]["families"]],
|
||||
"creator": data["avalon"]["creator"],
|
||||
"subset": data["avalon"]["subset"]
|
||||
}
|
||||
|
||||
nuke_imageio_writes = get_created_node_imageio_setting(**data_preset)
|
||||
|
|
@ -749,7 +803,7 @@ def format_anatomy(data):
|
|||
def script_name():
|
||||
''' Returns nuke script path
|
||||
'''
|
||||
return nuke.root().knob('name').value()
|
||||
return nuke.root().knob("name").value()
|
||||
|
||||
|
||||
def add_button_write_to_read(node):
|
||||
|
|
@ -844,7 +898,7 @@ def create_write_node(name, data, input=None, prenodes=None,
|
|||
# adding dataflow template
|
||||
log.debug("imageio_writes: `{}`".format(imageio_writes))
|
||||
for knob in imageio_writes["knobs"]:
|
||||
_data.update({knob["name"]: knob["value"]})
|
||||
_data[knob["name"]] = knob["value"]
|
||||
|
||||
_data = fix_data_for_node_create(_data)
|
||||
|
||||
|
|
@ -1193,15 +1247,19 @@ class WorkfileSettings(object):
|
|||
|
||||
erased_viewers = []
|
||||
for v in nuke.allNodes(filter="Viewer"):
|
||||
v['viewerProcess'].setValue(str(viewer_dict["viewerProcess"]))
|
||||
# set viewProcess to preset from settings
|
||||
v["viewerProcess"].setValue(
|
||||
str(viewer_dict["viewerProcess"])
|
||||
)
|
||||
|
||||
if str(viewer_dict["viewerProcess"]) \
|
||||
not in v['viewerProcess'].value():
|
||||
not in v["viewerProcess"].value():
|
||||
copy_inputs = v.dependencies()
|
||||
copy_knobs = {k: v[k].value() for k in v.knobs()
|
||||
if k not in filter_knobs}
|
||||
|
||||
# delete viewer with wrong settings
|
||||
erased_viewers.append(v['name'].value())
|
||||
erased_viewers.append(v["name"].value())
|
||||
nuke.delete(v)
|
||||
|
||||
# create new viewer
|
||||
|
|
@ -1217,7 +1275,7 @@ class WorkfileSettings(object):
|
|||
nv[k].setValue(v)
|
||||
|
||||
# set viewerProcess
|
||||
nv['viewerProcess'].setValue(str(viewer_dict["viewerProcess"]))
|
||||
nv["viewerProcess"].setValue(str(viewer_dict["viewerProcess"]))
|
||||
|
||||
if erased_viewers:
|
||||
log.warning(
|
||||
|
|
@ -1293,12 +1351,12 @@ class WorkfileSettings(object):
|
|||
for node in nuke.allNodes(filter="Group"):
|
||||
|
||||
# get data from avalon knob
|
||||
avalon_knob_data = read(node)
|
||||
avalon_knob_data = read_avalon_data(node)
|
||||
|
||||
if not avalon_knob_data:
|
||||
if avalon_knob_data.get("id") != "pyblish.avalon.instance":
|
||||
continue
|
||||
|
||||
if avalon_knob_data["id"] != "pyblish.avalon.instance":
|
||||
if "creator" not in avalon_knob_data:
|
||||
continue
|
||||
|
||||
# establish families
|
||||
|
|
@ -1309,7 +1367,8 @@ class WorkfileSettings(object):
|
|||
data_preset = {
|
||||
"nodeclass": avalon_knob_data["family"],
|
||||
"families": families,
|
||||
"creator": avalon_knob_data['creator']
|
||||
"creator": avalon_knob_data["creator"],
|
||||
"subset": avalon_knob_data["subset"]
|
||||
}
|
||||
|
||||
nuke_imageio_writes = get_created_node_imageio_setting(
|
||||
|
|
@ -1342,7 +1401,6 @@ class WorkfileSettings(object):
|
|||
|
||||
write_node[knob["name"]].setValue(value)
|
||||
|
||||
|
||||
def set_reads_colorspace(self, read_clrs_inputs):
|
||||
""" Setting colorspace to Read nodes
|
||||
|
||||
|
|
@ -1368,17 +1426,16 @@ class WorkfileSettings(object):
|
|||
current = n["colorspace"].value()
|
||||
future = str(preset_clrsp)
|
||||
if current != future:
|
||||
changes.update({
|
||||
n.name(): {
|
||||
"from": current,
|
||||
"to": future
|
||||
}
|
||||
})
|
||||
changes[n.name()] = {
|
||||
"from": current,
|
||||
"to": future
|
||||
}
|
||||
|
||||
log.debug(changes)
|
||||
if changes:
|
||||
msg = "Read nodes are not set to correct colospace:\n\n"
|
||||
for nname, knobs in changes.items():
|
||||
msg += str(
|
||||
msg += (
|
||||
" - node: '{0}' is now '{1}' but should be '{2}'\n"
|
||||
).format(nname, knobs["from"], knobs["to"])
|
||||
|
||||
|
|
@ -1610,17 +1667,17 @@ def get_hierarchical_attr(entity, attr, default=None):
|
|||
if not value:
|
||||
break
|
||||
|
||||
if value or entity['type'].lower() == 'project':
|
||||
if value or entity["type"].lower() == "project":
|
||||
return value
|
||||
|
||||
parent_id = entity['parent']
|
||||
parent_id = entity["parent"]
|
||||
if (
|
||||
entity['type'].lower() == 'asset'
|
||||
and entity.get('data', {}).get('visualParent')
|
||||
entity["type"].lower() == "asset"
|
||||
and entity.get("data", {}).get("visualParent")
|
||||
):
|
||||
parent_id = entity['data']['visualParent']
|
||||
parent_id = entity["data"]["visualParent"]
|
||||
|
||||
parent = legacy_io.find_one({'_id': parent_id})
|
||||
parent = legacy_io.find_one({"_id": parent_id})
|
||||
|
||||
return get_hierarchical_attr(parent, attr)
|
||||
|
||||
|
|
@ -1630,12 +1687,13 @@ def get_write_node_template_attr(node):
|
|||
|
||||
'''
|
||||
# get avalon data from node
|
||||
data = dict()
|
||||
data['avalon'] = read(node)
|
||||
data = {"avalon": read_avalon_data(node)}
|
||||
|
||||
data_preset = {
|
||||
"nodeclass": data['avalon']['family'],
|
||||
"families": [data['avalon']['families']],
|
||||
"creator": data['avalon']['creator']
|
||||
"nodeclass": data["avalon"]["family"],
|
||||
"families": [data["avalon"]["families"]],
|
||||
"creator": data["avalon"]["creator"],
|
||||
"subset": data["avalon"]["subset"]
|
||||
}
|
||||
|
||||
# get template data
|
||||
|
|
@ -1646,10 +1704,11 @@ def get_write_node_template_attr(node):
|
|||
"file": get_render_path(node)
|
||||
})
|
||||
|
||||
# adding imageio template
|
||||
{correct_data.update({k: v})
|
||||
for k, v in nuke_imageio_writes.items()
|
||||
if k not in ["_id", "_previous"]}
|
||||
# adding imageio knob presets
|
||||
for k, v in nuke_imageio_writes.items():
|
||||
if k in ["_id", "_previous"]:
|
||||
continue
|
||||
correct_data[k] = v
|
||||
|
||||
# fix badly encoded data
|
||||
return fix_data_for_node_create(correct_data)
|
||||
|
|
@ -1765,8 +1824,8 @@ def maintained_selection():
|
|||
|
||||
Example:
|
||||
>>> with maintained_selection():
|
||||
... node['selected'].setValue(True)
|
||||
>>> print(node['selected'].value())
|
||||
... node["selected"].setValue(True)
|
||||
>>> print(node["selected"].value())
|
||||
False
|
||||
"""
|
||||
previous_selection = nuke.selectedNodes()
|
||||
|
|
@ -1774,11 +1833,11 @@ def maintained_selection():
|
|||
yield
|
||||
finally:
|
||||
# unselect all selection in case there is some
|
||||
current_seletion = nuke.selectedNodes()
|
||||
[n['selected'].setValue(False) for n in current_seletion]
|
||||
reset_selection()
|
||||
|
||||
# and select all previously selected nodes
|
||||
if previous_selection:
|
||||
[n['selected'].setValue(True) for n in previous_selection]
|
||||
select_nodes(previous_selection)
|
||||
|
||||
|
||||
def reset_selection():
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ from .lib import (
|
|||
launch_workfiles_app,
|
||||
check_inventory_versions,
|
||||
set_avalon_knob_data,
|
||||
read,
|
||||
read_avalon_data,
|
||||
Context
|
||||
)
|
||||
|
||||
|
|
@ -359,7 +359,7 @@ def parse_container(node):
|
|||
dict: The container schema data for this container node.
|
||||
|
||||
"""
|
||||
data = read(node)
|
||||
data = read_avalon_data(node)
|
||||
|
||||
# (TODO) Remove key validation when `ls` has re-implemented.
|
||||
#
|
||||
|
|
|
|||
|
|
@ -260,8 +260,6 @@ class ExporterReview(object):
|
|||
return nuke_imageio["viewer"]["viewerProcess"]
|
||||
|
||||
|
||||
|
||||
|
||||
class ExporterReviewLut(ExporterReview):
|
||||
"""
|
||||
Generator object for review lut from Nuke
|
||||
|
|
@ -673,7 +671,8 @@ class AbstractWriteRender(OpenPypeCreator):
|
|||
write_data = {
|
||||
"nodeclass": self.n_class,
|
||||
"families": [self.family],
|
||||
"avalon": self.data
|
||||
"avalon": self.data,
|
||||
"subset": self.data["subset"]
|
||||
}
|
||||
|
||||
# add creator data
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ class ExtractReviewDataMov(openpype.api.Extractor):
|
|||
for o_name, o_data in self.outputs.items():
|
||||
f_families = o_data["filter"]["families"]
|
||||
f_task_types = o_data["filter"]["task_types"]
|
||||
f_subsets = o_data["filter"]["sebsets"]
|
||||
f_subsets = o_data["filter"]["subsets"]
|
||||
|
||||
self.log.debug(
|
||||
"f_families `{}` > families: {}".format(
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@
|
|||
]
|
||||
}
|
||||
],
|
||||
"customNodes": []
|
||||
"overrideNodes": []
|
||||
},
|
||||
"regexInputs": {
|
||||
"inputs": [
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@
|
|||
"filter": {
|
||||
"task_types": [],
|
||||
"families": [],
|
||||
"sebsets": []
|
||||
"subsets": []
|
||||
},
|
||||
"read_raw": false,
|
||||
"viewer_process_override": "",
|
||||
|
|
|
|||
|
|
@ -253,7 +253,7 @@
|
|||
{
|
||||
"key": "requiredNodes",
|
||||
"type": "list",
|
||||
"label": "Required Nodes",
|
||||
"label": "Plugin required",
|
||||
"object_type": {
|
||||
"type": "dict",
|
||||
"children": [
|
||||
|
|
@ -272,35 +272,43 @@
|
|||
"label": "Nuke Node Class"
|
||||
},
|
||||
{
|
||||
"type": "splitter"
|
||||
},
|
||||
{
|
||||
"key": "knobs",
|
||||
"type": "collapsible-wrap",
|
||||
"label": "Knobs",
|
||||
"type": "list",
|
||||
"object_type": {
|
||||
"type": "dict",
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"key": "name",
|
||||
"label": "Name"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "value",
|
||||
"label": "Value"
|
||||
"collapsible": true,
|
||||
"collapsed": true,
|
||||
"children": [
|
||||
{
|
||||
"key": "knobs",
|
||||
"type": "list",
|
||||
"object_type": {
|
||||
"type": "dict",
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"key": "name",
|
||||
"label": "Name"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "value",
|
||||
"label": "Value"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "splitter"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"key": "customNodes",
|
||||
"label": "Custom Nodes",
|
||||
"key": "overrideNodes",
|
||||
"label": "Plugin's node overrides",
|
||||
"object_type": {
|
||||
"type": "dict",
|
||||
"children": [
|
||||
|
|
@ -319,27 +327,37 @@
|
|||
"label": "Nuke Node Class"
|
||||
},
|
||||
{
|
||||
"type": "splitter"
|
||||
"key": "subsets",
|
||||
"label": "Subsets",
|
||||
"type": "list",
|
||||
"object_type": "text"
|
||||
},
|
||||
{
|
||||
"key": "knobs",
|
||||
"label": "Knobs",
|
||||
"type": "list",
|
||||
"object_type": {
|
||||
"type": "dict",
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"key": "name",
|
||||
"label": "Name"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "value",
|
||||
"label": "Value"
|
||||
"type": "collapsible-wrap",
|
||||
"label": "Knobs overrides",
|
||||
"collapsible": true,
|
||||
"collapsed": true,
|
||||
"children": [
|
||||
{
|
||||
"key": "knobs",
|
||||
"type": "list",
|
||||
"object_type": {
|
||||
"type": "dict",
|
||||
"children": [
|
||||
{
|
||||
"type": "text",
|
||||
"key": "name",
|
||||
"label": "Name"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "value",
|
||||
"label": "Value"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@
|
|||
"object_type": "text"
|
||||
},
|
||||
{
|
||||
"key": "sebsets",
|
||||
"key": "subsets",
|
||||
"label": "Subsets",
|
||||
"type": "list",
|
||||
"object_type": "text"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue