diff --git a/client/ayon_core/hosts/nuke/api/lib.py b/client/ayon_core/hosts/nuke/api/lib.py index a2ec8fdb98..c11a9d9be0 100644 --- a/client/ayon_core/hosts/nuke/api/lib.py +++ b/client/ayon_core/hosts/nuke/api/lib.py @@ -720,17 +720,17 @@ def get_created_node_imageio_setting_legacy(nodeclass, creator, subset): "`{}`: Missing mandatory kwargs `host`, `cls`".format(__file__)) imageio_nodes = get_nuke_imageio_settings()["nodes"] - required_nodes = imageio_nodes["requiredNodes"] + required_nodes = imageio_nodes["required_nodes"] # HACK: for backward compatibility this needs to be optional - override_nodes = imageio_nodes.get("overrideNodes", []) + override_nodes = imageio_nodes.get("override_nodes", []) imageio_node = None for node in required_nodes: log.info(node) if ( - nodeclass in node["nukeNodeClass"] - and creator in node["plugins"] + nodeclass in node["nuke_node_class"] + and creator in node["plugins"] ): imageio_node = node break @@ -741,10 +741,10 @@ def get_created_node_imageio_setting_legacy(nodeclass, creator, subset): override_imageio_node = None for onode in override_nodes: log.info(onode) - if nodeclass not in node["nukeNodeClass"]: + if nodeclass not in onode["nuke_node_class"]: continue - if creator not in node["plugins"]: + if creator not in onode["plugins"]: continue if ( @@ -766,26 +766,33 @@ def get_created_node_imageio_setting_legacy(nodeclass, creator, subset): knob_names = [k["name"] for k in imageio_node["knobs"]] for oknob in override_imageio_node["knobs"]: + oknob_name = oknob["name"] + oknob_type = oknob["type"] + oknob_value = oknob[oknob_type] 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"] - + knob_name = knob["name"] # add missing knobs into imageio_node - if oknob["name"] not in knob_names: + if oknob_name not in knob_names: log.debug( "_ adding knob: `{}`".format(oknob)) imageio_node["knobs"].append(oknob) - knob_names.append(oknob["name"]) + knob_names.append(oknob_name) + continue + + # override matching knob name + if oknob_name != knob_name: + continue + + knob_type = knob["type"] + 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[knob_type] = oknob_value log.info("ImageIO node: {}".format(imageio_node)) return imageio_node @@ -795,14 +802,14 @@ def get_imageio_node_setting(node_class, plugin_name, subset): ''' Get preset data for dataflow (fileType, compression, bitDepth) ''' imageio_nodes = get_nuke_imageio_settings()["nodes"] - required_nodes = imageio_nodes["requiredNodes"] + required_nodes = imageio_nodes["required_nodes"] imageio_node = None for node in required_nodes: log.info(node) if ( - node_class in node["nukeNodeClass"] - and plugin_name in node["plugins"] + node_class in node["nuke_node_class"] + and plugin_name in node["plugins"] ): imageio_node = node break @@ -830,14 +837,14 @@ def get_imageio_node_override_setting( ''' Get imageio node overrides from settings ''' imageio_nodes = get_nuke_imageio_settings()["nodes"] - override_nodes = imageio_nodes["overrideNodes"] + override_nodes = imageio_nodes["override_nodes"] # find matching override node override_imageio_node = None for onode in override_nodes: log.debug("__ onode: {}".format(onode)) log.debug("__ subset: {}".format(subset)) - if node_class not in onode["nukeNodeClass"]: + if node_class not in onode["nuke_node_class"]: continue if plugin_name not in onode["plugins"]: @@ -862,26 +869,31 @@ def get_imageio_node_override_setting( knob_names = [k["name"] for k in knobs_settings] for oknob in override_imageio_node["knobs"]: + oknob_name = oknob["name"] + oknob_type = oknob["type"] + oknob_value = oknob[oknob_type] for knob in knobs_settings: - # 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 - knobs_settings.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)) + if oknob_name not in knob_names: + log.debug("_ adding knob: `{}`".format(oknob)) knobs_settings.append(oknob) - knob_names.append(oknob["name"]) + knob_names.append(oknob_name) + continue + + if oknob_name != knob["name"]: + continue + + knob_type = knob["type"] + # override matching knob name + log.debug( + "_ overriding knob: `{}` > `{}`".format(knob, oknob) + ) + if not oknob_value: + # remove original knob if no value found in oknob + knobs_settings.remove(knob) + else: + # override knob value with oknob's + knob[knob_type] = oknob_value return knobs_settings @@ -890,7 +902,7 @@ def get_imageio_input_colorspace(filename): ''' Get input file colorspace based on regex in settings. ''' imageio_regex_inputs = ( - get_nuke_imageio_settings()["regexInputs"]["inputs"]) + get_nuke_imageio_settings()["regex_inputs"]["inputs"]) preset_clrsp = None for regexInput in imageio_regex_inputs: @@ -1177,8 +1189,9 @@ def create_prenodes( ): last_node = None for_dependency = {} - for name, node in nodes_setting.items(): + for node in nodes_setting: # get attributes + name = node["name"] nodeclass = node["nodeclass"] knobs = node["knobs"] @@ -1240,8 +1253,8 @@ def create_write_node( name (str): name of node data (dict): creator write instance data input (node)[optional]: selected node to connect to - prenodes (dict)[optional]: - nodes to be created before write with dependency + prenodes (Optional[list[dict]]): nodes to be created before write + with dependency review (bool)[optional]: adding review knob farm (bool)[optional]: rendering workflow target kwargs (dict)[optional]: additional key arguments for formatting @@ -1270,7 +1283,7 @@ def create_write_node( Return: node (obj): group node with avalon data as Knobs ''' - prenodes = prenodes or {} + prenodes = prenodes or [] # filtering variables plugin_name = data["creator"] @@ -1285,7 +1298,8 @@ def create_write_node( for knob in imageio_writes["knobs"]: if knob["name"] == "file_type": - ext = knob["value"] + knot_type = knob["type"] + ext = knob[knot_type] data.update({ "imageio_writes": imageio_writes, @@ -1400,12 +1414,17 @@ def create_write_node( # set tile color tile_color = next( iter( - k["value"] for k in imageio_writes["knobs"] + k[k["type"]] for k in imageio_writes["knobs"] if "tile_color" in k["name"] ), [255, 0, 0, 255] ) + new_tile_color = [] + for c in tile_color: + if isinstance(c, float): + c = int(c * 255) + new_tile_color.append(c) GN["tile_color"].setValue( - color_gui_to_int(tile_color)) + color_gui_to_int(new_tile_color)) return GN @@ -1701,42 +1720,32 @@ def set_node_knobs_from_settings(node, knob_settings, **kwargs): """ for knob in knob_settings: log.debug("__ knob: {}".format(pformat(knob))) - knob_type = knob["type"] knob_name = knob["name"] - if knob_name not in node.knobs(): continue + knob_type = knob["type"] + knob_value = knob[knob_type] if knob_type == "expression": - knob_expression = knob["expression"] - node[knob_name].setExpression( - knob_expression - ) + node[knob_name].setExpression(knob_value) continue # first deal with formattable knob settings if knob_type == "formatable": - template = knob["template"] - to_type = knob["to_type"] + template = knob_value["template"] + to_type = knob_value["to_type"] try: - _knob_value = template.format( - **kwargs - ) + knob_value = template.format(**kwargs) except KeyError as msg: raise KeyError( "Not able to format expression: {}".format(msg)) # convert value to correct type if to_type == "2d_vector": - knob_value = _knob_value.split(";").split(",") - else: - knob_value = _knob_value + knob_value = knob_value.split(";").split(",") knob_type = to_type - else: - knob_value = knob["value"] - if not knob_value: continue @@ -1747,29 +1756,46 @@ def set_node_knobs_from_settings(node, knob_settings, **kwargs): def convert_knob_value_to_correct_type(knob_type, knob_value): - # first convert string types to string - # just to ditch unicode - if isinstance(knob_value, six.text_type): - knob_value = str(knob_value) + # Convert 'text' to string to avoid unicode + if knob_type == "text": + return str(knob_value) - # set correctly knob types - if knob_type == "bool": - knob_value = bool(knob_value) - elif knob_type == "decimal_number": - knob_value = float(knob_value) - elif knob_type == "number": - knob_value = int(knob_value) - elif knob_type == "text": - knob_value = knob_value - elif knob_type == "color_gui": - knob_value = color_gui_to_int(knob_value) - elif knob_type in ["2d_vector", "3d_vector", "color", "box"]: - knob_value = [float(val_) for val_ in knob_value] + if knob_type == "boolean": + return bool(knob_value) + + if knob_type == "decimal_number": + return float(knob_value) + + if knob_type == "number": + return int(knob_value) + + if knob_type == "color_gui": + new_color = [] + for value in knob_value: + if isinstance(value, float): + value = int(value * 255) + new_color.append(value) + return color_gui_to_int(new_color) + + if knob_type == "box": + return [ + knob_value["x"], knob_value["y"], + knob_value["r"], knob_value["t"] + ] + + if knob_type == "vector_2d": + return [knob_value["x"], knob_value["y"]] + + if knob_type == "vector_3d": + return [knob_value["x"], knob_value["y"], knob_value["z"]] return knob_value def color_gui_to_int(color_gui): + # Append alpha channel if not present + if len(color_gui) == 3: + color_gui = list(color_gui) + [255] hex_value = ( "0x{0:0>2x}{1:0>2x}{2:0>2x}{3:0>2x}").format(*color_gui) return int(hex_value, 16) @@ -2016,41 +2042,21 @@ class WorkfileSettings(object): host_name="nuke" ) - workfile_settings = imageio_host["workfile"] viewer_process_settings = imageio_host["viewer"]["viewerProcess"] + workfile_settings = imageio_host["workfile"] + color_management = workfile_settings["color_management"] + native_ocio_config = workfile_settings["native_ocio_config"] if not config_data: - # TODO: backward compatibility for old projects - remove later - # perhaps old project overrides is having it set to older version - # with use of `customOCIOConfigPath` - resolved_path = None - if workfile_settings.get("customOCIOConfigPath"): - unresolved_path = workfile_settings["customOCIOConfigPath"] - ocio_paths = unresolved_path[platform.system().lower()] + # no ocio config found and no custom path used + if self._root_node["colorManagement"].value() \ + not in color_management: + self._root_node["colorManagement"].setValue(color_management) - for ocio_p in ocio_paths: - resolved_path = str(ocio_p).format(**os.environ) - if not os.path.exists(resolved_path): - continue - - if resolved_path: - # set values to root - self._root_node["colorManagement"].setValue("OCIO") - self._root_node["OCIO_config"].setValue("custom") - self._root_node["customOCIOConfigPath"].setValue( - resolved_path) - else: - # no ocio config found and no custom path used - if self._root_node["colorManagement"].value() \ - not in str(workfile_settings["colorManagement"]): - self._root_node["colorManagement"].setValue( - str(workfile_settings["colorManagement"])) - - # second set ocio version - if self._root_node["OCIO_config"].value() \ - not in str(workfile_settings["OCIO_config"]): - self._root_node["OCIO_config"].setValue( - str(workfile_settings["OCIO_config"])) + # second set ocio version + if self._root_node["OCIO_config"].value() \ + not in native_ocio_config: + self._root_node["OCIO_config"].setValue(native_ocio_config) else: # OCIO config path is defined from prelaunch hook @@ -2063,22 +2069,17 @@ class WorkfileSettings(object): residual_path )) - # we dont need the key anymore - workfile_settings.pop("customOCIOConfigPath", None) - workfile_settings.pop("colorManagement", None) - workfile_settings.pop("OCIO_config", None) - # get monitor lut from settings respecting Nuke version differences - monitor_lut = workfile_settings.pop("monitorLut", None) + monitor_lut = workfile_settings["thumbnail_space"] monitor_lut_data = self._get_monitor_settings( - viewer_process_settings, monitor_lut) - - # set monitor related knobs luts (MonitorOut, Thumbnails) - for knob, value_ in monitor_lut_data.items(): - workfile_settings[knob] = value_ + viewer_process_settings, monitor_lut + ) + monitor_lut_data["workingSpaceLUT"] = ( + workfile_settings["working_space"] + ) # then set the rest - for knob, value_ in workfile_settings.items(): + for knob, value_ in monitor_lut_data.items(): # skip unfilled ocio config path # it will be dict in value if isinstance(value_, dict): @@ -2360,25 +2361,8 @@ Reopening Nuke should synchronize these paths and resolve any discrepancies. if not write_node: return - try: - # write all knobs to node - for knob in nuke_imageio_writes["knobs"]: - value = knob["value"] - if isinstance(value, six.text_type): - value = str(value) - if str(value).startswith("0x"): - value = int(value, 16) - - log.debug("knob: {}| value: {}".format( - knob["name"], value - )) - write_node[knob["name"]].setValue(value) - except TypeError: - log.warning( - "Legacy workflow didn't work, switching to current") - - set_node_knobs_from_settings( - write_node, nuke_imageio_writes["knobs"]) + set_node_knobs_from_settings( + write_node, nuke_imageio_writes["knobs"]) def set_reads_colorspace(self, read_clrs_inputs): """ Setting colorspace to Read nodes @@ -2456,7 +2440,7 @@ Reopening Nuke should synchronize these paths and resolve any discrepancies. log.error(_error) log.info("Setting colorspace to read nodes...") - read_clrs_inputs = nuke_colorspace["regexInputs"].get("inputs", []) + read_clrs_inputs = nuke_colorspace["regex_inputs"].get("inputs", []) if read_clrs_inputs: self.set_reads_colorspace(read_clrs_inputs) diff --git a/client/ayon_core/hosts/nuke/api/plugin.py b/client/ayon_core/hosts/nuke/api/plugin.py index 59042acee1..bf338a3010 100644 --- a/client/ayon_core/hosts/nuke/api/plugin.py +++ b/client/ayon_core/hosts/nuke/api/plugin.py @@ -396,17 +396,25 @@ class NukeWriteCreator(NukeCreator): # plugin settings plugin_settings = self.get_creator_settings(project_settings) - + temp_rendering_path_template = ( + plugin_settings.get("temp_rendering_path_template") + or self.temp_rendering_path_template + ) + # TODO remove template key replacements + temp_rendering_path_template = ( + temp_rendering_path_template + .replace("{product[name]}", "{subset}") + .replace("{product[type]}", "{family}") + .replace("{task[name]}", "{task}") + .replace("{folder[name]}", "{asset}") + ) # individual attributes self.instance_attributes = plugin_settings.get( "instance_attributes") or self.instance_attributes self.prenodes = plugin_settings["prenodes"] self.default_variants = plugin_settings.get( "default_variants") or self.default_variants - self.temp_rendering_path_template = ( - plugin_settings.get("temp_rendering_path_template") - or self.temp_rendering_path_template - ) + self.temp_rendering_path_template = temp_rendering_path_template class OpenPypeCreator(LegacyCreator): @@ -1061,7 +1069,7 @@ class AbstractWriteRender(OpenPypeCreator): icon = "sign-out" defaults = ["Main", "Mask"] knobs = [] - prenodes = {} + prenodes = [] def __init__(self, *args, **kwargs): super(AbstractWriteRender, self).__init__(*args, **kwargs) @@ -1167,7 +1175,7 @@ class AbstractWriteRender(OpenPypeCreator): bool: True if legacy """ imageio_nodes = get_nuke_imageio_settings()["nodes"] - node = imageio_nodes["requiredNodes"][0] + node = imageio_nodes["required_nodes"][0] if "type" not in node["knobs"][0]: # if type is not yet in project anatomy return True diff --git a/client/ayon_core/hosts/nuke/plugins/load/load_clip.py b/client/ayon_core/hosts/nuke/plugins/load/load_clip.py index 8bce2eac6e..31b523fbc8 100644 --- a/client/ayon_core/hosts/nuke/plugins/load/load_clip.py +++ b/client/ayon_core/hosts/nuke/plugins/load/load_clip.py @@ -53,7 +53,7 @@ class LoadClip(plugin.NukeLoader): color = "white" # Loaded from settings - _representations = [] + representations_include = [] script_start = int(nuke.root()["first_frame"].value()) @@ -82,7 +82,7 @@ class LoadClip(plugin.NukeLoader): @classmethod def get_representations(cls): - return cls._representations or cls.representations + return cls.representations_include or cls.representations def load(self, context, name, namespace, options): """Load asset via database @@ -457,7 +457,7 @@ class LoadClip(plugin.NukeLoader): colorspace = repre_data.get("colorspace") colorspace = colorspace or version_data.get("colorspace") - # colorspace from `project_settings/nuke/imageio/regexInputs` + # colorspace from `project_settings/nuke/imageio/regex_inputs` iio_colorspace = get_imageio_input_colorspace(path) # Set colorspace defined in version data diff --git a/client/ayon_core/hosts/nuke/plugins/load/load_image.py b/client/ayon_core/hosts/nuke/plugins/load/load_image.py index b9f47bddc9..e9435ec10a 100644 --- a/client/ayon_core/hosts/nuke/plugins/load/load_image.py +++ b/client/ayon_core/hosts/nuke/plugins/load/load_image.py @@ -47,7 +47,7 @@ class LoadImage(load.LoaderPlugin): color = "white" # Loaded from settings - _representations = [] + representations_include = [] node_name_template = "{class_name}_{ext}" @@ -64,7 +64,7 @@ class LoadImage(load.LoaderPlugin): @classmethod def get_representations(cls): - return cls._representations or cls.representations + return cls.representations_include or cls.representations def load(self, context, name, namespace, options): self.log.info("__ options: `{}`".format(options)) diff --git a/client/ayon_core/hosts/nuke/plugins/publish/collect_nuke_instance_data.py b/client/ayon_core/hosts/nuke/plugins/publish/collect_nuke_instance_data.py index 449a1cc935..75380bf409 100644 --- a/client/ayon_core/hosts/nuke/plugins/publish/collect_nuke_instance_data.py +++ b/client/ayon_core/hosts/nuke/plugins/publish/collect_nuke_instance_data.py @@ -12,7 +12,7 @@ class CollectInstanceData(pyblish.api.InstancePlugin): hosts = ["nuke", "nukeassist"] # presets - sync_workfile_version_on_families = [] + sync_workfile_version_on_product_types = [] def process(self, instance): family = instance.data["family"] @@ -25,7 +25,7 @@ class CollectInstanceData(pyblish.api.InstancePlugin): pixel_aspect = format_.pixelAspect() # sync workfile version - if family in self.sync_workfile_version_on_families: + if family in self.sync_workfile_version_on_product_types: self.log.debug( "Syncing version with workfile for '{}'".format( family diff --git a/client/ayon_core/hosts/nuke/plugins/publish/extract_review_intermediates.py b/client/ayon_core/hosts/nuke/plugins/publish/extract_review_intermediates.py index a00c1c593f..1f4410d347 100644 --- a/client/ayon_core/hosts/nuke/plugins/publish/extract_review_intermediates.py +++ b/client/ayon_core/hosts/nuke/plugins/publish/extract_review_intermediates.py @@ -50,6 +50,7 @@ class ExtractReviewIntermediates(publish.Extractor): cls.outputs = current_setting["outputs"] def process(self, instance): + # TODO 'families' should not be included for filtering of outputs families = set(instance.data["families"]) # add main family to make sure all families are compared @@ -75,29 +76,33 @@ class ExtractReviewIntermediates(publish.Extractor): # generate data with maintained_selection(): generated_repres = [] - for o_name, o_data in self.outputs.items(): + for o_data in self.outputs: + o_name = o_data["name"] self.log.debug( "o_name: {}, o_data: {}".format(o_name, pformat(o_data))) - f_families = o_data["filter"]["families"] + f_product_types = o_data["filter"]["product_types"] f_task_types = o_data["filter"]["task_types"] - f_subsets = o_data["filter"]["subsets"] + product_names = o_data["filter"]["product_names"] self.log.debug( - "f_families `{}` > families: {}".format( - f_families, families)) + "f_product_types `{}` > families: {}".format( + f_product_types, families)) self.log.debug( "f_task_types `{}` > task_type: {}".format( f_task_types, task_type)) self.log.debug( - "f_subsets `{}` > subset: {}".format( - f_subsets, subset)) + "product_names `{}` > subset: {}".format( + product_names, subset)) # test if family found in context # using intersection to make sure all defined # families are present in combination - if f_families and not families.intersection(f_families): + if ( + f_product_types + and not families.intersection(f_product_types) + ): continue # test task types from filter @@ -105,8 +110,9 @@ class ExtractReviewIntermediates(publish.Extractor): continue # test subsets from filter - if f_subsets and not any( - re.search(s, subset) for s in f_subsets): + if product_names and not any( + re.search(p, subset) for p in product_names + ): continue self.log.debug( @@ -117,7 +123,7 @@ class ExtractReviewIntermediates(publish.Extractor): # check if settings have more then one preset # so we dont need to add outputName to representation # in case there is only one preset - multiple_presets = len(self.outputs.keys()) > 1 + multiple_presets = len(self.outputs) > 1 # adding bake presets to instance data for other plugins if not instance.data.get("bakePresets"): diff --git a/client/ayon_core/hosts/nuke/plugins/publish/extract_slate_frame.py b/client/ayon_core/hosts/nuke/plugins/publish/extract_slate_frame.py index 0c4823b1aa..6918e4f50f 100644 --- a/client/ayon_core/hosts/nuke/plugins/publish/extract_slate_frame.py +++ b/client/ayon_core/hosts/nuke/plugins/publish/extract_slate_frame.py @@ -29,9 +29,15 @@ class ExtractSlateFrame(publish.Extractor): # Settings values key_value_mapping = { - "f_submission_note": [True, "{comment}"], - "f_submitting_for": [True, "{intent[value]}"], - "f_vfx_scope_of_work": [False, ""] + "f_submission_note": { + "enabled": True, "template": "{comment}" + }, + "f_submitting_for": { + "enabled": True, "template": "{intent[value]}" + }, + "f_vfx_scope_of_work": { + "enabled": False, "template": "" + } } def process(self, instance): @@ -316,11 +322,11 @@ class ExtractSlateFrame(publish.Extractor): }) for key, _values in self.key_value_mapping.items(): - enabled, template = _values - if not enabled: + if not _values["enabled"]: self.log.debug("Key \"{}\" is disabled".format(key)) continue + template = _values["template"] try: value = template.format(**fill_data) diff --git a/client/ayon_core/hosts/nuke/plugins/publish/help/validate_write_nodes.xml b/client/ayon_core/hosts/nuke/plugins/publish/help/validate_write_nodes.xml index 1717622a45..96aa6e4494 100644 --- a/client/ayon_core/hosts/nuke/plugins/publish/help/validate_write_nodes.xml +++ b/client/ayon_core/hosts/nuke/plugins/publish/help/validate_write_nodes.xml @@ -25,7 +25,7 @@ ### How to repair? Contact your supervisor or fix it in project settings at - 'project_settings/nuke/imageio/nodes/requiredNodes' at knobs. + 'project_settings/nuke/imageio/nodes/required_nodes' at knobs. Each '__legacy__' type has to be defined accordingly to its type. diff --git a/client/ayon_core/hosts/nuke/plugins/publish/validate_knobs.py b/client/ayon_core/hosts/nuke/plugins/publish/validate_knobs.py index 84efebab53..bede67dabe 100644 --- a/client/ayon_core/hosts/nuke/plugins/publish/validate_knobs.py +++ b/client/ayon_core/hosts/nuke/plugins/publish/validate_knobs.py @@ -30,6 +30,8 @@ class ValidateKnobs(pyblish.api.ContextPlugin): actions = [RepairContextAction] optional = True + knobs = "{}" + def process(self, context): invalid = self.get_invalid(context, compute=True) if invalid: @@ -61,6 +63,8 @@ class ValidateKnobs(pyblish.api.ContextPlugin): invalid_knobs = [] for instance in context: + # Load fresh knobs data for each instance + settings_knobs = json.loads(cls.knobs) # Filter families. families = [instance.data["family"]] @@ -74,12 +78,12 @@ class ValidateKnobs(pyblish.api.ContextPlugin): family = family.split(".")[0] # avoid families not in settings - if family not in cls.knobs: + if family not in settings_knobs: continue # get presets of knobs - for preset in cls.knobs[family]: - knobs[preset] = cls.knobs[family][preset] + for preset in settings_knobs[family]: + knobs[preset] = settings_knobs[family][preset] # Get invalid knobs. nodes = [] diff --git a/client/ayon_core/hosts/nuke/plugins/publish/validate_write_nodes.py b/client/ayon_core/hosts/nuke/plugins/publish/validate_write_nodes.py index 7679022487..0244c1d504 100644 --- a/client/ayon_core/hosts/nuke/plugins/publish/validate_write_nodes.py +++ b/client/ayon_core/hosts/nuke/plugins/publish/validate_write_nodes.py @@ -86,7 +86,10 @@ class ValidateNukeWriteNode( # Collect key values of same type in a list. values_by_name = defaultdict(list) for knob_data in correct_data["knobs"]: - values_by_name[knob_data["name"]].append(knob_data["value"]) + knob_type = knob_data["type"] + knob_value = knob_data[knob_type] + + values_by_name[knob_data["name"]].append(knob_value) for knob_data in correct_data["knobs"]: knob_type = knob_data["type"] @@ -97,7 +100,7 @@ class ValidateNukeWriteNode( raise PublishXmlValidationError( self, ( "Please update data in settings 'project_settings" - "/nuke/imageio/nodes/requiredNodes'" + "/nuke/imageio/nodes/required_nodes'" ), key="legacy" ) diff --git a/client/ayon_core/hosts/nuke/startup/custom_write_node.py b/client/ayon_core/hosts/nuke/startup/custom_write_node.py index 89dfde297c..5eb58a3679 100644 --- a/client/ayon_core/hosts/nuke/startup/custom_write_node.py +++ b/client/ayon_core/hosts/nuke/startup/custom_write_node.py @@ -127,8 +127,8 @@ class WriteNodeKnobSettingPanel(nukescripts.PythonPanel): knobs_nodes = [] settings = [ node_settings for node_settings - in get_nuke_imageio_settings()["nodes"]["overrideNodes"] - if node_settings["nukeNodeClass"] == "Write" + in get_nuke_imageio_settings()["nodes"]["override_nodes"] + if node_settings["nuke_node_class"] == "Write" and node_settings["subsets"] ] if not settings: diff --git a/client/ayon_core/settings/ayon_settings.py b/client/ayon_core/settings/ayon_settings.py index 775351eb38..e444a4dc10 100644 --- a/client/ayon_core/settings/ayon_settings.py +++ b/client/ayon_core/settings/ayon_settings.py @@ -133,192 +133,6 @@ def convert_system_settings(ayon_settings, default_settings, addon_versions): # --------- Project settings --------- -def _convert_nuke_knobs(knobs): - new_knobs = [] - for knob in knobs: - knob_type = knob["type"] - - if knob_type == "boolean": - knob_type = "bool" - - if knob_type != "bool": - value = knob[knob_type] - elif knob_type in knob: - value = knob[knob_type] - else: - value = knob["boolean"] - - new_knob = { - "type": knob_type, - "name": knob["name"], - } - new_knobs.append(new_knob) - - if knob_type == "formatable": - new_knob["template"] = value["template"] - new_knob["to_type"] = value["to_type"] - continue - - value_key = "value" - if knob_type == "expression": - value_key = "expression" - - elif knob_type == "color_gui": - value = _convert_color(value) - - elif knob_type == "vector_2d": - value = [value["x"], value["y"]] - - elif knob_type == "vector_3d": - value = [value["x"], value["y"], value["z"]] - - elif knob_type == "box": - value = [value["x"], value["y"], value["r"], value["t"]] - - new_knob[value_key] = value - return new_knobs - - -def _convert_nuke_project_settings(ayon_settings, output): - if "nuke" not in ayon_settings: - return - - ayon_nuke = ayon_settings["nuke"] - - # --- Load --- - ayon_load = ayon_nuke["load"] - ayon_load["LoadClip"]["_representations"] = ( - ayon_load["LoadClip"].pop("representations_include") - ) - ayon_load["LoadImage"]["_representations"] = ( - ayon_load["LoadImage"].pop("representations_include") - ) - - # --- Create --- - ayon_create = ayon_nuke["create"] - for creator_name in ( - "CreateWritePrerender", - "CreateWriteImage", - "CreateWriteRender", - ): - create_plugin_settings = ayon_create[creator_name] - create_plugin_settings["temp_rendering_path_template"] = ( - create_plugin_settings["temp_rendering_path_template"] - .replace("{product[name]}", "{subset}") - .replace("{product[type]}", "{family}") - .replace("{task[name]}", "{task}") - .replace("{folder[name]}", "{asset}") - ) - new_prenodes = {} - for prenode in create_plugin_settings["prenodes"]: - name = prenode.pop("name") - prenode["knobs"] = _convert_nuke_knobs(prenode["knobs"]) - new_prenodes[name] = prenode - - create_plugin_settings["prenodes"] = new_prenodes - - # --- Publish --- - ayon_publish = ayon_nuke["publish"] - slate_mapping = ayon_publish["ExtractSlateFrame"]["key_value_mapping"] - for key in tuple(slate_mapping.keys()): - value = slate_mapping[key] - slate_mapping[key] = [value["enabled"], value["template"]] - - ayon_publish["ValidateKnobs"]["knobs"] = json.loads( - ayon_publish["ValidateKnobs"]["knobs"] - ) - - new_review_data_outputs = {} - outputs_settings = [] - # Check deprecated ExtractReviewDataMov - # settings for backwards compatibility - deprecrated_review_settings = ayon_publish["ExtractReviewDataMov"] - current_review_settings = ( - ayon_publish.get("ExtractReviewIntermediates") - ) - if deprecrated_review_settings["enabled"]: - outputs_settings = deprecrated_review_settings["outputs"] - elif current_review_settings is None: - pass - elif current_review_settings["enabled"]: - outputs_settings = current_review_settings["outputs"] - - for item in outputs_settings: - item_filter = item["filter"] - if "product_names" in item_filter: - item_filter["subsets"] = item_filter.pop("product_names") - item_filter["families"] = item_filter.pop("product_types") - - reformat_nodes_config = item.get("reformat_nodes_config") or {} - reposition_nodes = reformat_nodes_config.get( - "reposition_nodes") or [] - - for reposition_node in reposition_nodes: - if "knobs" not in reposition_node: - continue - reposition_node["knobs"] = _convert_nuke_knobs( - reposition_node["knobs"] - ) - - name = item.pop("name") - new_review_data_outputs[name] = item - - if deprecrated_review_settings["enabled"]: - deprecrated_review_settings["outputs"] = new_review_data_outputs - elif current_review_settings["enabled"]: - current_review_settings["outputs"] = new_review_data_outputs - - collect_instance_data = ayon_publish["CollectInstanceData"] - if "sync_workfile_version_on_product_types" in collect_instance_data: - collect_instance_data["sync_workfile_version_on_families"] = ( - collect_instance_data.pop( - "sync_workfile_version_on_product_types")) - - # --- ImageIO --- - # NOTE 'monitorOutLut' is maybe not yet in v3 (ut should be) - ayon_imageio = ayon_nuke["imageio"] - - # workfile - imageio_workfile = ayon_imageio["workfile"] - workfile_keys_mapping = ( - ("color_management", "colorManagement"), - ("native_ocio_config", "OCIO_config"), - ("working_space", "workingSpaceLUT"), - ("thumbnail_space", "monitorLut"), - ) - for src, dst in workfile_keys_mapping: - if ( - src in imageio_workfile - and dst not in imageio_workfile - ): - imageio_workfile[dst] = imageio_workfile.pop(src) - - # regex inputs - if "regex_inputs" in ayon_imageio: - ayon_imageio["regexInputs"] = ayon_imageio.pop("regex_inputs") - - # nodes - ayon_imageio_nodes = ayon_imageio["nodes"] - if "required_nodes" in ayon_imageio_nodes: - ayon_imageio_nodes["requiredNodes"] = ( - ayon_imageio_nodes.pop("required_nodes")) - if "override_nodes" in ayon_imageio_nodes: - ayon_imageio_nodes["overrideNodes"] = ( - ayon_imageio_nodes.pop("override_nodes")) - - for item in ayon_imageio_nodes["requiredNodes"]: - if "nuke_node_class" in item: - item["nukeNodeClass"] = item.pop("nuke_node_class") - item["knobs"] = _convert_nuke_knobs(item["knobs"]) - - for item in ayon_imageio_nodes["overrideNodes"]: - if "nuke_node_class" in item: - item["nukeNodeClass"] = item.pop("nuke_node_class") - item["knobs"] = _convert_nuke_knobs(item["knobs"]) - - output["nuke"] = ayon_nuke - - def _convert_royalrender_project_settings(ayon_settings, output): if "royalrender" not in ayon_settings: return @@ -335,8 +149,6 @@ def convert_project_settings(ayon_settings, default_settings): default_settings = copy.deepcopy(default_settings) output = {} - _convert_nuke_project_settings(ayon_settings, output) - _convert_royalrender_project_settings(ayon_settings, output) for key, value in ayon_settings.items():