From d1364d2c15de6b66dcd985f5f514c669352c2179 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 13 Mar 2024 20:31:14 +0800 Subject: [PATCH 01/10] bug fix on getting aov expected files when global aov mode disabled --- .../hosts/maya/api/lib_renderproducts.py | 124 +++++++++--------- 1 file changed, 64 insertions(+), 60 deletions(-) diff --git a/client/ayon_core/hosts/maya/api/lib_renderproducts.py b/client/ayon_core/hosts/maya/api/lib_renderproducts.py index 7f26145e1d..63071c0053 100644 --- a/client/ayon_core/hosts/maya/api/lib_renderproducts.py +++ b/client/ayon_core/hosts/maya/api/lib_renderproducts.py @@ -1136,68 +1136,72 @@ def get_render_products(self): light_groups_enabled = False has_beauty_aov = False colorspace = lib.get_color_management_output_transform() - for aov in aovs: - enabled = self._get_attr(aov, "enabled") - if not enabled: - continue - - aov_type = self._get_attr(aov, "aovType") - if self.multipart and aov_type not in self.unmerged_aovs: - continue - - # Any AOVs that still get processed, like Cryptomatte - # by themselves are not multipart files. - - # Redshift skips rendering of masterlayer without AOV suffix - # when a Beauty AOV is rendered. It overrides the main layer. - if aov_type == "Beauty": - has_beauty_aov = True - - aov_name = self._get_attr(aov, "name") - - # Support light Groups - light_groups = [] - if self._get_attr(aov, "supportsLightGroups"): - all_light_groups = self._get_attr(aov, "allLightGroups") - if all_light_groups: - # All light groups is enabled - light_groups = self._get_redshift_light_groups() - else: - value = self._get_attr(aov, "lightGroupList") - # note: string value can return None when never set - if value: - selected_light_groups = value.strip().split() - light_groups = selected_light_groups - - for light_group in light_groups: - aov_light_group_name = "{}_{}".format(aov_name, - light_group) - for camera in cameras: - product = RenderProduct( - productName=aov_light_group_name, - aov=aov_name, - ext=ext, - multipart=False, - camera=camera, - driver=aov, - colorspace=colorspace) - products.append(product) + global_aov_enabled = bool( + self._get_attr("redshiftOptions.aovGlobalEnableMode") + ) + if global_aov_enabled: + for aov in aovs: + enabled = self._get_attr(aov, "enabled") + if not enabled: + continue - if light_groups: - light_groups_enabled = True + aov_type = self._get_attr(aov, "aovType") + if self.multipart and aov_type not in self.unmerged_aovs: + continue - # Redshift AOV Light Select always renders the global AOV - # even when light groups are present so we don't need to - # exclude it when light groups are active - for camera in cameras: - product = RenderProduct(productName=aov_name, - aov=aov_name, - ext=ext, - multipart=False, - camera=camera, - driver=aov, - colorspace=colorspace) - products.append(product) + # Any AOVs that still get processed, like Cryptomatte + # by themselves are not multipart files. + + # Redshift skips rendering of masterlayer without AOV suffix + # when a Beauty AOV is rendered. It overrides the main layer. + if aov_type == "Beauty": + has_beauty_aov = True + + aov_name = self._get_attr(aov, "name") + + # Support light Groups + light_groups = [] + if self._get_attr(aov, "supportsLightGroups"): + all_light_groups = self._get_attr(aov, "allLightGroups") + if all_light_groups: + # All light groups is enabled + light_groups = self._get_redshift_light_groups() + else: + value = self._get_attr(aov, "lightGroupList") + # note: string value can return None when never set + if value: + selected_light_groups = value.strip().split() + light_groups = selected_light_groups + + for light_group in light_groups: + aov_light_group_name = "{}_{}".format(aov_name, + light_group) + for camera in cameras: + product = RenderProduct( + productName=aov_light_group_name, + aov=aov_name, + ext=ext, + multipart=False, + camera=camera, + driver=aov, + colorspace=colorspace) + products.append(product) + + if light_groups: + light_groups_enabled = True + + # Redshift AOV Light Select always renders the global AOV + # even when light groups are present so we don't need to + # exclude it when light groups are active + for camera in cameras: + product = RenderProduct(productName=aov_name, + aov=aov_name, + ext=ext, + multipart=False, + camera=camera, + driver=aov, + colorspace=colorspace) + products.append(product) # When a Beauty AOV is added manually, it will be rendered as # 'Beauty_other' in file name and "standard" beauty will have From 024f6f5163a72722f7bed1d2062c45cf02332d80 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 13 Mar 2024 21:22:23 +0800 Subject: [PATCH 02/10] return products instead if global aov mode is disabled --- .../hosts/maya/api/lib_renderproducts.py | 124 +++++++++--------- 1 file changed, 63 insertions(+), 61 deletions(-) diff --git a/client/ayon_core/hosts/maya/api/lib_renderproducts.py b/client/ayon_core/hosts/maya/api/lib_renderproducts.py index 63071c0053..28981e1187 100644 --- a/client/ayon_core/hosts/maya/api/lib_renderproducts.py +++ b/client/ayon_core/hosts/maya/api/lib_renderproducts.py @@ -1139,69 +1139,71 @@ def get_render_products(self): global_aov_enabled = bool( self._get_attr("redshiftOptions.aovGlobalEnableMode") ) - if global_aov_enabled: - for aov in aovs: - enabled = self._get_attr(aov, "enabled") - if not enabled: - continue + if not global_aov_enabled: + return products - aov_type = self._get_attr(aov, "aovType") - if self.multipart and aov_type not in self.unmerged_aovs: - continue + for aov in aovs: + enabled = self._get_attr(aov, "enabled") + if not enabled: + continue - # Any AOVs that still get processed, like Cryptomatte - # by themselves are not multipart files. - - # Redshift skips rendering of masterlayer without AOV suffix - # when a Beauty AOV is rendered. It overrides the main layer. - if aov_type == "Beauty": - has_beauty_aov = True - - aov_name = self._get_attr(aov, "name") - - # Support light Groups - light_groups = [] - if self._get_attr(aov, "supportsLightGroups"): - all_light_groups = self._get_attr(aov, "allLightGroups") - if all_light_groups: - # All light groups is enabled - light_groups = self._get_redshift_light_groups() - else: - value = self._get_attr(aov, "lightGroupList") - # note: string value can return None when never set - if value: - selected_light_groups = value.strip().split() - light_groups = selected_light_groups - - for light_group in light_groups: - aov_light_group_name = "{}_{}".format(aov_name, - light_group) - for camera in cameras: - product = RenderProduct( - productName=aov_light_group_name, - aov=aov_name, - ext=ext, - multipart=False, - camera=camera, - driver=aov, - colorspace=colorspace) - products.append(product) - - if light_groups: - light_groups_enabled = True - - # Redshift AOV Light Select always renders the global AOV - # even when light groups are present so we don't need to - # exclude it when light groups are active - for camera in cameras: - product = RenderProduct(productName=aov_name, - aov=aov_name, - ext=ext, - multipart=False, - camera=camera, - driver=aov, - colorspace=colorspace) - products.append(product) + aov_type = self._get_attr(aov, "aovType") + if self.multipart and aov_type not in self.unmerged_aovs: + continue + + # Any AOVs that still get processed, like Cryptomatte + # by themselves are not multipart files. + + # Redshift skips rendering of masterlayer without AOV suffix + # when a Beauty AOV is rendered. It overrides the main layer. + if aov_type == "Beauty": + has_beauty_aov = True + + aov_name = self._get_attr(aov, "name") + + # Support light Groups + light_groups = [] + if self._get_attr(aov, "supportsLightGroups"): + all_light_groups = self._get_attr(aov, "allLightGroups") + if all_light_groups: + # All light groups is enabled + light_groups = self._get_redshift_light_groups() + else: + value = self._get_attr(aov, "lightGroupList") + # note: string value can return None when never set + if value: + selected_light_groups = value.strip().split() + light_groups = selected_light_groups + + for light_group in light_groups: + aov_light_group_name = "{}_{}".format(aov_name, + light_group) + for camera in cameras: + product = RenderProduct( + productName=aov_light_group_name, + aov=aov_name, + ext=ext, + multipart=False, + camera=camera, + driver=aov, + colorspace=colorspace) + products.append(product) + + if light_groups: + light_groups_enabled = True + + # Redshift AOV Light Select always renders the global AOV + # even when light groups are present so we don't need to + # exclude it when light groups are active + for camera in cameras: + product = RenderProduct(productName=aov_name, + aov=aov_name, + ext=ext, + multipart=False, + camera=camera, + driver=aov, + colorspace=colorspace) + products.append(product) # When a Beauty AOV is added manually, it will be rendered as # 'Beauty_other' in file name and "standard" beauty will have From b729bf4f30432a5a86ab7670e73b3e2b4514cc87 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 13 Mar 2024 23:56:31 +0800 Subject: [PATCH 03/10] make sure beauty still being added as render product --- client/ayon_core/hosts/maya/api/lib_renderproducts.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/client/ayon_core/hosts/maya/api/lib_renderproducts.py b/client/ayon_core/hosts/maya/api/lib_renderproducts.py index 28981e1187..3bba25ee12 100644 --- a/client/ayon_core/hosts/maya/api/lib_renderproducts.py +++ b/client/ayon_core/hosts/maya/api/lib_renderproducts.py @@ -1140,6 +1140,15 @@ def get_render_products(self): self._get_attr("redshiftOptions.aovGlobalEnableMode") ) if not global_aov_enabled: + beauty_name = "BeautyAux" if has_beauty_aov else "" + for camera in cameras: + products.insert(0, + RenderProduct(productName=beauty_name, + ext=ext, + multipart=self.multipart, + camera=camera, + colorspace=colorspace)) + return products for aov in aovs: From ffa395af64b066808cdffce100ad8593bf36fbd1 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 14 Mar 2024 15:10:03 +0800 Subject: [PATCH 04/10] add only beauty output when global aov disabled --- .../hosts/maya/api/lib_renderproducts.py | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/client/ayon_core/hosts/maya/api/lib_renderproducts.py b/client/ayon_core/hosts/maya/api/lib_renderproducts.py index 3bba25ee12..5f3917f642 100644 --- a/client/ayon_core/hosts/maya/api/lib_renderproducts.py +++ b/client/ayon_core/hosts/maya/api/lib_renderproducts.py @@ -1133,24 +1133,24 @@ def get_render_products(self): aovs = list(set(aovs) - set(ref_aovs)) products = [] - light_groups_enabled = False - has_beauty_aov = False - colorspace = lib.get_color_management_output_transform() global_aov_enabled = bool( self._get_attr("redshiftOptions.aovGlobalEnableMode") ) + colorspace = lib.get_color_management_output_transform() if not global_aov_enabled: - beauty_name = "BeautyAux" if has_beauty_aov else "" + # only beauty output for camera in cameras: products.insert(0, - RenderProduct(productName=beauty_name, - ext=ext, - multipart=self.multipart, - camera=camera, - colorspace=colorspace)) - + RenderProduct(productName="", + ext=ext, + multipart=self.multipart, + camera=camera, + colorspace=colorspace)) return products + light_groups_enabled = False + has_beauty_aov = False + for aov in aovs: enabled = self._get_attr(aov, "enabled") if not enabled: From 368444a7f25c2d9a6d044f605a860677f268d2d8 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 4 Apr 2024 22:21:11 +0800 Subject: [PATCH 05/10] use cmds.setattr instead of self._get_attr() --- client/ayon_core/hosts/maya/api/lib_renderproducts.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/hosts/maya/api/lib_renderproducts.py b/client/ayon_core/hosts/maya/api/lib_renderproducts.py index 5f3917f642..6b73639040 100644 --- a/client/ayon_core/hosts/maya/api/lib_renderproducts.py +++ b/client/ayon_core/hosts/maya/api/lib_renderproducts.py @@ -1133,9 +1133,11 @@ def get_render_products(self): aovs = list(set(aovs) - set(ref_aovs)) products = [] + # global_aov_enabled = bool( + # self._get_attr("redshiftOptions.aovGlobalEnableMode") + # ) global_aov_enabled = bool( - self._get_attr("redshiftOptions.aovGlobalEnableMode") - ) + cmds.getAttr("redshiftOptions.aovGlobalEnableMode")) colorspace = lib.get_color_management_output_transform() if not global_aov_enabled: # only beauty output From 4a04bd1397a9a5e564c6b5d7e7f7262b53588ccc Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 4 Apr 2024 16:35:49 +0200 Subject: [PATCH 06/10] fix update of context change --- client/ayon_core/tools/workfiles/control.py | 38 ++++++++++----------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/client/ayon_core/tools/workfiles/control.py b/client/ayon_core/tools/workfiles/control.py index 7fa7af1662..2cdcd37d53 100644 --- a/client/ayon_core/tools/workfiles/control.py +++ b/client/ayon_core/tools/workfiles/control.py @@ -659,16 +659,7 @@ def _open_workfile(self, folder_id, task_id, filepath): folder_id != self.get_current_folder_id() or task_name != self.get_current_task_name() ): - folder_entity = ayon_api.get_folder_by_id( - event_data["project_name"], - event_data["folder_id"], - ) - task_entity = ayon_api.get_task_by_name( - event_data["project_name"], - event_data["folder_id"], - event_data["task_name"] - ) - change_current_context(folder_entity, task_entity) + self._change_current_context(project_name, folder_id, task_id) self._host_open_workfile(filepath) @@ -710,16 +701,8 @@ def _save_as_workfile( folder_id != self.get_current_folder_id() or task_name != self.get_current_task_name() ): - folder_entity = ayon_api.get_folder_by_id( - project_name, folder["id"] - ) - task_entity = ayon_api.get_task_by_name( - project_name, folder["id"], task_name - ) - change_current_context( - folder_entity, - task_entity, - template_key=template_key + self._change_current_context( + project_name, folder_id, task_id, template_key ) # Save workfile @@ -745,3 +728,18 @@ def _save_as_workfile( # Trigger after save events emit_event("workfile.save.after", event_data, source="workfiles.tool") self.reset() + + def _change_current_context( + self, project_name, folder_id, task_id, template_key=None + ): + # Change current context + folder_entity = self.get_folder_entity(project_name, folder_id) + task_entity = self.get_task_entity(project_name, task_id) + change_current_context( + folder_entity, + task_entity, + template_key=template_key + ) + self._current_folder_id = folder_entity["id"] + self._current_folder_path = folder_entity["path"] + self._current_task_name = task_entity["name"] From 2701d4bf8aeddb4da0841b49d7d06451ee5f06d8 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 4 Apr 2024 16:46:15 +0200 Subject: [PATCH 07/10] removed unnecessary `reset` call --- client/ayon_core/tools/workfiles/control.py | 1 - 1 file changed, 1 deletion(-) diff --git a/client/ayon_core/tools/workfiles/control.py b/client/ayon_core/tools/workfiles/control.py index 2cdcd37d53..3048e6be94 100644 --- a/client/ayon_core/tools/workfiles/control.py +++ b/client/ayon_core/tools/workfiles/control.py @@ -727,7 +727,6 @@ def _save_as_workfile( # Trigger after save events emit_event("workfile.save.after", event_data, source="workfiles.tool") - self.reset() def _change_current_context( self, project_name, folder_id, task_id, template_key=None From dc21231c291ebffb532151806e2e696ac3510fdc Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 4 Apr 2024 23:16:12 +0800 Subject: [PATCH 08/10] exposes asString as arguments for getting attributes for renderlayer & renderlayersetup --- client/ayon_core/hosts/maya/api/lib.py | 9 +++++---- client/ayon_core/hosts/maya/api/lib_renderproducts.py | 10 ++++------ client/ayon_core/hosts/maya/api/lib_rendersetup.py | 6 +++--- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/client/ayon_core/hosts/maya/api/lib.py b/client/ayon_core/hosts/maya/api/lib.py index 060c16056c..89582bac8b 100644 --- a/client/ayon_core/hosts/maya/api/lib.py +++ b/client/ayon_core/hosts/maya/api/lib.py @@ -3129,7 +3129,7 @@ def load_capture_preset(data): return options -def get_attr_in_layer(attr, layer): +def get_attr_in_layer(attr, layer, as_string=True): """Return attribute value in specified renderlayer. Same as cmds.getAttr but this gets the attribute's value in a @@ -3156,7 +3156,8 @@ def get_attr_in_layer(attr, layer): try: if cmds.mayaHasRenderSetup(): from . import lib_rendersetup - return lib_rendersetup.get_attr_in_layer(attr, layer) + return lib_rendersetup.get_attr_in_layer( + attr, layer, as_string=as_string) except AttributeError: pass @@ -3173,7 +3174,7 @@ def get_attr_in_layer(attr, layer): type="renderLayer") or [] connections = filter(lambda x: x.endswith(".plug"), connections) if not connections: - return cmds.getAttr(attr) + return cmds.getAttr(attr, asString=as_string) # Some value types perform a conversion when assigning # TODO: See if there's a maya method to allow this conversion @@ -3215,7 +3216,7 @@ def get_attr_in_layer(attr, layer): value *= conversion return value - return cmds.getAttr(attr) + return cmds.getAttr(attr, asString=as_string) def fix_incompatible_containers(): diff --git a/client/ayon_core/hosts/maya/api/lib_renderproducts.py b/client/ayon_core/hosts/maya/api/lib_renderproducts.py index 6b73639040..832d1c21c2 100644 --- a/client/ayon_core/hosts/maya/api/lib_renderproducts.py +++ b/client/ayon_core/hosts/maya/api/lib_renderproducts.py @@ -297,7 +297,7 @@ def get_render_attribute(self, attribute): """ return self._get_attr("defaultRenderGlobals", attribute) - def _get_attr(self, node_attr, attribute=None): + def _get_attr(self, node_attr, attribute=None, as_string=True): """Return the value of the attribute in the renderlayer For readability this allows passing in the attribute in two ways. @@ -317,7 +317,7 @@ def _get_attr(self, node_attr, attribute=None): else: plug = "{}.{}".format(node_attr, attribute) - return lib.get_attr_in_layer(plug, layer=self.layer) + return lib.get_attr_in_layer(plug, layer=self.layer, as_string=as_string) @staticmethod def extract_separator(file_prefix): @@ -1133,11 +1133,9 @@ def get_render_products(self): aovs = list(set(aovs) - set(ref_aovs)) products = [] - # global_aov_enabled = bool( - # self._get_attr("redshiftOptions.aovGlobalEnableMode") - # ) global_aov_enabled = bool( - cmds.getAttr("redshiftOptions.aovGlobalEnableMode")) + self._get_attr("redshiftOptions.aovGlobalEnableMode", as_string=False) + ) colorspace = lib.get_color_management_output_transform() if not global_aov_enabled: # only beauty output diff --git a/client/ayon_core/hosts/maya/api/lib_rendersetup.py b/client/ayon_core/hosts/maya/api/lib_rendersetup.py index c2b5ec843c..6dca8eb6dd 100644 --- a/client/ayon_core/hosts/maya/api/lib_rendersetup.py +++ b/client/ayon_core/hosts/maya/api/lib_rendersetup.py @@ -77,7 +77,7 @@ def get_rendersetup_layer(layer): if conn.endswith(".legacyRenderLayer")), None) -def get_attr_in_layer(node_attr, layer): +def get_attr_in_layer(node_attr, layer, as_string=True): """Return attribute value in Render Setup layer. This will only work for attributes which can be @@ -124,7 +124,7 @@ def get_default_layer_value(node_attr_): node = history_overrides[-1] if history_overrides else override node_attr_ = node + ".original" - return get_attribute(node_attr_, asString=True) + return get_attribute(node_attr_, asString=as_string) layer = get_rendersetup_layer(layer) rs = renderSetup.instance() @@ -144,7 +144,7 @@ def get_default_layer_value(node_attr_): # we will let it error out. rs.switchToLayer(current_layer) - return get_attribute(node_attr, asString=True) + return get_attribute(node_attr, asString=as_string) overrides = get_attr_overrides(node_attr, layer) default_layer_value = get_default_layer_value(node_attr) From 8573a0f6cf63103284466d84c1c48ea6067e9fb0 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 4 Apr 2024 17:51:00 +0200 Subject: [PATCH 09/10] Improve Creator error for new users --- .../hosts/maya/plugins/create/create_render.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/hosts/maya/plugins/create/create_render.py b/client/ayon_core/hosts/maya/plugins/create/create_render.py index 213d5b543e..e5a8d4dbd8 100644 --- a/client/ayon_core/hosts/maya/plugins/create/create_render.py +++ b/client/ayon_core/hosts/maya/plugins/create/create_render.py @@ -40,8 +40,15 @@ def apply_settings(cls, project_settings): def create(self, product_name, instance_data, pre_create_data): # Only allow a single render instance to exist if self._get_singleton_node(): - raise CreatorError("A Render instance already exists - only " - "one can be configured.") + raise CreatorError( + "A Render instance already exists - only one can be " + "configured.\n\n" + "To render multiple render layers, create extra Render Setup " + "Layers via Maya's Render Setup UI.\n" + "Then refresh the publisher to detect the new layers for " + "rendering.\n\n" + "With a render instance present all Render Setup layers in " + "your workfile are renderable instances.") # Apply default project render settings on create if self.render_settings.get("apply_render_settings"): From 26b7a53656062625fed2c62f1573ad0166a6dbc3 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Fri, 5 Apr 2024 15:10:36 +0800 Subject: [PATCH 10/10] add docstring and make sure the backward compatible is converting to string value as before --- client/ayon_core/hosts/maya/api/lib.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/hosts/maya/api/lib.py b/client/ayon_core/hosts/maya/api/lib.py index 89582bac8b..91f60824b6 100644 --- a/client/ayon_core/hosts/maya/api/lib.py +++ b/client/ayon_core/hosts/maya/api/lib.py @@ -3147,6 +3147,7 @@ def get_attr_in_layer(attr, layer, as_string=True): Args: attr (str): attribute name, ex. "node.attribute" layer (str): layer name + as_string (bool): whether attribute should convert to a string value Returns: The return value from `maya.cmds.getAttr` @@ -3165,7 +3166,7 @@ def get_attr_in_layer(attr, layer, as_string=True): current_layer = cmds.editRenderLayerGlobals(query=True, currentRenderLayer=True) if layer == current_layer: - return cmds.getAttr(attr) + return cmds.getAttr(attr, asString=as_string) connections = cmds.listConnections(attr, plugs=True, @@ -3174,7 +3175,7 @@ def get_attr_in_layer(attr, layer, as_string=True): type="renderLayer") or [] connections = filter(lambda x: x.endswith(".plug"), connections) if not connections: - return cmds.getAttr(attr, asString=as_string) + return cmds.getAttr(attr) # Some value types perform a conversion when assigning # TODO: See if there's a maya method to allow this conversion