diff --git a/openpype/hosts/nuke/api/plugin.py b/openpype/hosts/nuke/api/plugin.py index fd754203d4..3e61caedf9 100644 --- a/openpype/hosts/nuke/api/plugin.py +++ b/openpype/hosts/nuke/api/plugin.py @@ -446,6 +446,8 @@ class ExporterReviewMov(ExporterReview): return path def generate_mov(self, farm=False, **kwargs): + reformat_node_add = kwargs["reformat_node_add"] + reformat_node_config = kwargs["reformat_node_config"] bake_viewer_process = kwargs["bake_viewer_process"] bake_viewer_input_process_node = kwargs[ "bake_viewer_input_process"] @@ -483,6 +485,30 @@ class ExporterReviewMov(ExporterReview): self.previous_node = r_node self.log.debug("Read... `{}`".format(self._temp_nodes[subset])) + # add reformat node + if reformat_node_add: + # append reformated tag + add_tags.append("reformated") + + rf_node = nuke.createNode("Reformat") + for kn_conf in reformat_node_config: + _type = kn_conf["type"] + k_name = str(kn_conf["name"]) + k_value = kn_conf["value"] + + # to remove unicode as nuke doesn't like it + if _type == "string": + k_value = str(kn_conf["value"]) + + rf_node[k_name].setValue(k_value) + + # connect + rf_node.setInput(0, self.previous_node) + self._temp_nodes[subset].append(rf_node) + self.previous_node = rf_node + self.log.debug( + "Reformat... `{}`".format(self._temp_nodes[subset])) + # only create colorspace baking if toggled on if bake_viewer_process: if bake_viewer_input_process_node: diff --git a/openpype/hosts/nuke/plugins/publish/extract_review_data_mov.py b/openpype/hosts/nuke/plugins/publish/extract_review_data_mov.py index 5bbc88266a..1071834497 100644 --- a/openpype/hosts/nuke/plugins/publish/extract_review_data_mov.py +++ b/openpype/hosts/nuke/plugins/publish/extract_review_data_mov.py @@ -1,4 +1,5 @@ import os +import re import pyblish.api import openpype from openpype.hosts.nuke.api import plugin @@ -25,6 +26,7 @@ class ExtractReviewDataMov(openpype.api.Extractor): def process(self, instance): families = instance.data["families"] task_type = instance.context.data["taskType"] + subset = instance.data["subset"] self.log.info("Creating staging dir...") if "representations" not in instance.data: @@ -46,6 +48,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"] # test if family found in context test_families = any([ @@ -69,11 +72,25 @@ class ExtractReviewDataMov(openpype.api.Extractor): bool(not f_task_types) ]) + # test subsets from filter + test_subsets = any([ + # check if any of subset filter inputs + # converted to regex patern is not found in subset + # we keep strict case sensitivity + bool(next(( + s for s in f_subsets + if re.search(re.compile(s), subset) + ), None)), + # but if no subsets were set then make this acuntable too + bool(not f_subsets) + ]) + # we need all filters to be positive for this # preset to be activated test_all = all([ test_families, - test_task_types + test_task_types, + test_subsets ]) # if it is not positive then skip this preset @@ -120,6 +137,13 @@ class ExtractReviewDataMov(openpype.api.Extractor): if generated_repres: # assign to representations instance.data["representations"] += generated_repres + else: + instance.data["families"].remove("review") + self.log.info(( + "Removing `review` from families. " + "Not available baking profile." + )) + self.log.debug(instance.data["families"]) self.log.debug( "_ representations: {}".format( diff --git a/openpype/plugins/publish/extract_review.py b/openpype/plugins/publish/extract_review.py index 5f286a53e6..b4a5117959 100644 --- a/openpype/plugins/publish/extract_review.py +++ b/openpype/plugins/publish/extract_review.py @@ -1171,6 +1171,9 @@ class ExtractReview(pyblish.api.InstancePlugin): self.log.debug("input_width: `{}`".format(input_width)) self.log.debug("input_height: `{}`".format(input_height)) + reformat_in_baking = bool("reformated" in new_repre["tags"]) + self.log.debug("reformat_in_baking: `{}`".format(reformat_in_baking)) + # Use instance resolution if output definition has not set it. if output_width is None or output_height is None: output_width = temp_data["resolution_width"] @@ -1182,6 +1185,17 @@ class ExtractReview(pyblish.api.InstancePlugin): output_width = input_width output_height = input_height + if reformat_in_baking: + self.log.debug(( + "Using resolution from input. It is already " + "reformated from baking process" + )) + output_width = input_width + output_height = input_height + pixel_aspect = 1 + new_repre["resolutionWidth"] = input_width + new_repre["resolutionHeight"] = input_height + output_width = int(output_width) output_height = int(output_height) diff --git a/openpype/settings/defaults/project_settings/nuke.json b/openpype/settings/defaults/project_settings/nuke.json index 5a819e6904..6992fb6e3e 100644 --- a/openpype/settings/defaults/project_settings/nuke.json +++ b/openpype/settings/defaults/project_settings/nuke.json @@ -116,13 +116,42 @@ "baking": { "filter": { "task_types": [], - "families": [] + "families": [], + "sebsets": [] }, "extension": "mov", "viewer_process_override": "", "bake_viewer_process": true, "bake_viewer_input_process": true, - "add_tags": [] + "add_tags": [], + "reformat_node_add": false, + "reformat_node_config": [ + { + "type": "string", + "name": "type", + "value": "to format" + }, + { + "type": "string", + "name": "format", + "value": "HD_1080" + }, + { + "type": "string", + "name": "filter", + "value": "Lanczos6" + }, + { + "type": "bool", + "name": "black_outside", + "value": true + }, + { + "type": "bool", + "name": "pbb", + "value": false + } + ] } } }, diff --git a/openpype/settings/entities/dict_conditional.py b/openpype/settings/entities/dict_conditional.py index 963fd406ed..19f326aea7 100644 --- a/openpype/settings/entities/dict_conditional.py +++ b/openpype/settings/entities/dict_conditional.py @@ -584,8 +584,9 @@ class DictConditionalEntity(ItemEntity): self.enum_entity.update_default_value(enum_value) for children_by_key in self.non_gui_children.values(): + value_copy = copy.deepcopy(value) for key, child_obj in children_by_key.items(): - child_value = value.get(key, NOT_SET) + child_value = value_copy.get(key, NOT_SET) child_obj.update_default_value(child_value) def update_studio_value(self, value): @@ -620,8 +621,9 @@ class DictConditionalEntity(ItemEntity): self.enum_entity.update_studio_value(enum_value) for children_by_key in self.non_gui_children.values(): + value_copy = copy.deepcopy(value) for key, child_obj in children_by_key.items(): - child_value = value.get(key, NOT_SET) + child_value = value_copy.get(key, NOT_SET) child_obj.update_studio_value(child_value) def update_project_value(self, value): @@ -656,8 +658,9 @@ class DictConditionalEntity(ItemEntity): self.enum_entity.update_project_value(enum_value) for children_by_key in self.non_gui_children.values(): + value_copy = copy.deepcopy(value) for key, child_obj in children_by_key.items(): - child_value = value.get(key, NOT_SET) + child_value = value_copy.get(key, NOT_SET) child_obj.update_project_value(child_value) def _discard_changes(self, on_change_trigger): diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_publish.json index 39390f355a..1636a8d700 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_publish.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_publish.json @@ -195,6 +195,12 @@ "label": "Families", "type": "list", "object_type": "text" + }, + { + "key": "sebsets", + "label": "Subsets", + "type": "list", + "object_type": "text" } ] }, @@ -226,6 +232,121 @@ "label": "Add additional tags to representations", "type": "list", "object_type": "text" + }, + { + "type": "separator" + }, + { + "type": "boolean", + "key": "reformat_node_add", + "label": "Add Reformat Node", + "default": false + }, + { + "type": "collapsible-wrap", + "label": "Reformat Node Knobs", + "collapsible": true, + "collapsed": false, + "children": [ + { + "type": "list", + "key": "reformat_node_config", + "object_type": { + "type": "dict-conditional", + "enum_key": "type", + "enum_label": "Type", + "enum_children": [ + { + "key": "string", + "label": "String", + "children": [ + { + "type": "text", + "key": "name", + "label": "Name" + }, + { + "type": "text", + "key": "value", + "label": "Value" + } + ] + }, + { + "key": "bool", + "label": "Boolean", + "children": [ + { + "type": "text", + "key": "name", + "label": "Name" + }, + { + "type": "boolean", + "key": "value", + "label": "Value" + } + ] + }, + { + "key": "number", + "label": "Number", + "children": [ + { + "type": "text", + "key": "name", + "label": "Name" + }, + { + "type": "list-strict", + "key": "value", + "label": "Value", + "object_types": [ + { + "type": "number", + "key": "number", + "default": 1, + "decimal": 4 + } + ] + } + + ] + }, + { + "key": "list_numbers", + "label": "2 Numbers", + "children": [ + { + "type": "text", + "key": "name", + "label": "Name" + }, + { + "type": "list-strict", + "key": "value", + "label": "Value", + "object_types": [ + { + "type": "number", + "key": "x", + "default": 1, + "decimal": 4 + }, + { + "type": "number", + "key": "y", + "default": 1, + "decimal": 4 + } + ] + } + ] + } + ] + } + } + ] } ] }