Skip to content
This repository has been archived by the owner on Sep 20, 2024. It is now read-only.

Commit

Permalink
Merge pull request #4009 from pypeclub/feature/OP-4217_ProRes4444-ACE…
Browse files Browse the repository at this point in the history
…Scct-mov-profile

Nuke | Global: adding custom tags representation filtering
  • Loading branch information
jakubjezek001 authored Oct 24, 2022
2 parents 644f63e + 827ba77 commit 75c2122
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 35 deletions.
44 changes: 44 additions & 0 deletions openpype/hosts/nuke/api/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -2930,3 +2930,47 @@ def get_nodes_by_names(names):
nuke.toNode(name)
for name in names
]


def get_viewer_config_from_string(input_string):
"""Convert string to display and viewer string
Args:
input_string (str): string with viewer
Raises:
IndexError: if more then one slash in input string
IndexError: if missing closing bracket
Returns:
tuple[str]: display, viewer
"""
display = None
viewer = input_string
# check if () or / or \ in name
if "/" in viewer:
split = viewer.split("/")

# rise if more then one column
if len(split) > 2:
raise IndexError((
"Viewer Input string is not correct. "
"more then two `/` slashes! {}"
).format(input_string))

viewer = split[1]
display = split[0]
elif "(" in viewer:
pattern = r"([\w\d\s]+).*[(](.*)[)]"
result = re.findall(pattern, viewer)
try:
result = result.pop()
display = str(result[1]).rstrip()
viewer = str(result[0]).rstrip()
except IndexError:
raise IndexError((
"Viewer Input string is not correct. "
"Missing bracket! {}"
).format(input_string))

return (display, viewer)
40 changes: 34 additions & 6 deletions openpype/hosts/nuke/api/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
add_publish_knob,
get_nuke_imageio_settings,
set_node_knobs_from_settings,
get_view_process_node
get_view_process_node,
get_viewer_config_from_string
)


Expand Down Expand Up @@ -190,7 +191,20 @@ def get_file_info(self):
if "#" in self.fhead:
self.fhead = self.fhead.replace("#", "")[:-1]

def get_representation_data(self, tags=None, range=False):
def get_representation_data(
self, tags=None, range=False,
custom_tags=None
):
""" Add representation data to self.data
Args:
tags (list[str], optional): list of defined tags.
Defaults to None.
range (bool, optional): flag for adding ranges.
Defaults to False.
custom_tags (list[str], optional): user inputed custom tags.
Defaults to None.
"""
add_tags = tags or []
repre = {
"name": self.name,
Expand All @@ -200,6 +214,9 @@ def get_representation_data(self, tags=None, range=False):
"tags": [self.name.replace("_", "-")] + add_tags
}

if custom_tags:
repre["custom_tags"] = custom_tags

if range:
repre.update({
"frameStart": self.first_frame,
Expand Down Expand Up @@ -312,7 +329,8 @@ def generate_lut(self, **kwargs):
dag_node.setInput(0, self.previous_node)
self._temp_nodes.append(dag_node)
self.previous_node = dag_node
self.log.debug("OCIODisplay... `{}`".format(self._temp_nodes))
self.log.debug(
"OCIODisplay... `{}`".format(self._temp_nodes))

# GenerateLUT
gen_lut_node = nuke.createNode("GenerateLUT")
Expand Down Expand Up @@ -415,6 +433,7 @@ def save_file(self):
return path

def generate_mov(self, farm=False, **kwargs):
add_tags = []
self.publish_on_farm = farm
read_raw = kwargs["read_raw"]
reformat_node_add = kwargs["reformat_node_add"]
Expand All @@ -433,10 +452,10 @@ def generate_mov(self, farm=False, **kwargs):
self.log.debug(">> baking_view_profile `{}`".format(
baking_view_profile))

add_tags = kwargs.get("add_tags", [])
add_custom_tags = kwargs.get("add_custom_tags", [])

self.log.info(
"__ add_tags: `{0}`".format(add_tags))
"__ add_custom_tags: `{0}`".format(add_custom_tags))

subset = self.instance.data["subset"]
self._temp_nodes[subset] = []
Expand Down Expand Up @@ -491,7 +510,15 @@ def generate_mov(self, farm=False, **kwargs):
if not self.viewer_lut_raw:
# OCIODisplay
dag_node = nuke.createNode("OCIODisplay")
dag_node["view"].setValue(str(baking_view_profile))

display, viewer = get_viewer_config_from_string(
str(baking_view_profile)
)
if display:
dag_node["display"].setValue(display)

# assign viewer
dag_node["view"].setValue(viewer)

# connect
dag_node.setInput(0, self.previous_node)
Expand Down Expand Up @@ -542,6 +569,7 @@ def generate_mov(self, farm=False, **kwargs):
# ---------- generate representation data
self.get_representation_data(
tags=["review", "delete"] + add_tags,
custom_tags=add_custom_tags,
range=True
)

Expand Down
73 changes: 48 additions & 25 deletions openpype/plugins/publish/extract_review.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ def _get_outputs_per_representations(self, instance, profile_outputs):
for repre in instance.data["representations"]:
repre_name = str(repre.get("name"))
tags = repre.get("tags") or []
custom_tags = repre.get("custom_tags")
if "review" not in tags:
self.log.debug((
"Repre: {} - Didn't found \"review\" in tags. Skipping"
Expand Down Expand Up @@ -158,15 +159,18 @@ def _get_outputs_per_representations(self, instance, profile_outputs):
)
continue

# Filter output definition by representation tags (optional)
outputs = self.filter_outputs_by_tags(profile_outputs, tags)
# Filter output definition by representation's
# custom tags (optional)
outputs = self.filter_outputs_by_custom_tags(
profile_outputs, custom_tags)
if not outputs:
self.log.info((
"Skipped representation. All output definitions from"
" selected profile does not match to representation's"
" tags. \"{}\""
" custom tags. \"{}\""
).format(str(tags)))
continue

outputs_per_representations.append((repre, outputs))
return outputs_per_representations

Expand Down Expand Up @@ -1656,14 +1660,17 @@ def families_filter_validation(self, families, output_families_filter):
return True
return False

def filter_output_defs(self, profile, subset_name, families):
def filter_output_defs(
self, profile, subset_name, families
):
"""Return outputs matching input instance families.
Output definitions without families filter are marked as valid.
Args:
profile (dict): Profile from presets matching current context.
families (list): All families of current instance.
subset_name (str): name of subset
Returns:
list: Containg all output definitions matching entered families.
Expand Down Expand Up @@ -1711,39 +1718,55 @@ def filter_output_defs(self, profile, subset_name, families):

return filtered_outputs

def filter_outputs_by_tags(self, outputs, tags):
"""Filter output definitions by entered representation tags.
def filter_outputs_by_custom_tags(self, outputs, custom_tags):
"""Filter output definitions by entered representation custom_tags.
Output definitions without tags filter are marked as valid.
Output definitions without custom_tags filter are marked as invalid,
only in case representation is having any custom_tags defined.
Args:
outputs (list): Contain list of output definitions from presets.
tags (list): Tags of processed representation.
custom_tags (list): Custom Tags of processed representation.
Returns:
list: Containg all output definitions matching entered tags.
"""
filtered_outputs = []
repre_tags_low = [tag.lower() for tag in tags]
repre_c_tags_low = [tag.lower() for tag in (custom_tags or [])]
for output_def in outputs:
valid = True
output_filters = output_def.get("filter")
if output_filters:
# Check tag filters
tag_filters = output_filters.get("tags")
if tag_filters:
tag_filters_low = [tag.lower() for tag in tag_filters]
valid = False
for tag in repre_tags_low:
if tag in tag_filters_low:
valid = True
break
valid = False
tag_filters = output_def.get("filter", {}).get("custom_tags")

if not valid:
continue
if (
# if any of tag filter is empty, skip
custom_tags and not tag_filters
or not custom_tags and tag_filters
):
continue
elif not custom_tags and not tag_filters:
valid = True

if valid:
filtered_outputs.append(output_def)
# lower all filter tags
tag_filters_low = [tag.lower() for tag in tag_filters]

self.log.debug("__ tag_filters: {}".format(tag_filters))
self.log.debug("__ repre_c_tags_low: {}".format(
repre_c_tags_low))

# check if any repre tag is not in filter tags
for tag in repre_c_tags_low:
if tag in tag_filters_low:
valid = True
break

if not valid:
continue

filtered_outputs.append(output_def)

self.log.debug("__ filtered_outputs: {}".format(
[_o["filename_suffix"] for _o in filtered_outputs]
))

return filtered_outputs

Expand Down
3 changes: 2 additions & 1 deletion openpype/settings/defaults/project_settings/global.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@
"review",
"ftrack"
],
"subsets": []
"subsets": [],
"custom_tags": []
},
"overscan_crop": "",
"overscan_color": [
Expand Down
2 changes: 1 addition & 1 deletion openpype/settings/defaults/project_settings/nuke.json
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@
}
],
"extension": "mov",
"add_tags": []
"add_custom_tags": []
}
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,15 @@
"label": "Subsets",
"type": "list",
"object_type": "text"
},
{
"type": "separator"
},
{
"key": "custom_tags",
"label": "Custom Tags",
"type": "list",
"object_type": "text"
}
]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,8 +296,8 @@
"label": "Write node file type"
},
{
"key": "add_tags",
"label": "Add additional tags to representations",
"key": "add_custom_tags",
"label": "Add custom tags",
"type": "list",
"object_type": "text"
}
Expand Down

0 comments on commit 75c2122

Please sign in to comment.