From 51957dd3aec5d09c83ffca921966229d4a382b3f Mon Sep 17 00:00:00 2001 From: Derek Severin Date: Wed, 2 Mar 2022 15:37:53 +0700 Subject: [PATCH 01/27] Deformer node ids validation plugin for Maya --- .../validate_node_ids_deformer_transfer.py | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 openpype/hosts/maya/plugins/publish/validate_node_ids_deformer_transfer.py diff --git a/openpype/hosts/maya/plugins/publish/validate_node_ids_deformer_transfer.py b/openpype/hosts/maya/plugins/publish/validate_node_ids_deformer_transfer.py new file mode 100644 index 0000000000..67b4aff136 --- /dev/null +++ b/openpype/hosts/maya/plugins/publish/validate_node_ids_deformer_transfer.py @@ -0,0 +1,105 @@ +from maya import cmds + +import pyblish.api +import openpype.api +import openpype.hosts.maya.api.action +from openpype.hosts.maya.api import lib + + +class ValidateNodeIdsDeformerTransfer(pyblish.api.InstancePlugin): + """Validate if deformed shapes have related IDs to the original + shapes. + + When a deformer is applied in the scene on a mesh, + Maya creates a new "deformer" shape node for the mesh. + This new node does not get the original ID and later references + to the original node ID don't match. + + This validator checks whether the IDs are valid on all the shape + nodes in the instance. + """ + + order = openpype.api.ValidateContentsOrder + families = ['rig'] + hosts = ['maya'] + label = 'Deformed shape ids transferred' + actions = [ + openpype.hosts.maya.api.action.SelectInvalidAction, + openpype.api.RepairAction + ] + + def process(self, instance): + """Process all the nodes in the instance""" + + # Ensure nodes with sibling share the same ID + invalid = self.get_invalid(instance) + if invalid: + raise RuntimeError( + "Shapes found that are considered 'Deformed'" + " with invalid object ids: {0}".format(invalid) + ) + + @classmethod + def get_invalid(cls, instance): + """Get all nodes which do not match the criteria""" + + shapes = cmds.ls(instance[:], + dag=True, + leaf=True, + shapes=True, + long=True, + noIntermediate=True) + + invalid = [] + for shape in shapes: + sibling_id = cls._get_id_from_sibling(shape) + if not sibling_id: + continue + + current_id = lib.get_id(shape) + if current_id != sibling_id: + invalid.append(shape) + + return invalid + + @classmethod + def _get_id_from_sibling(cls, node): + """In some cases, the history of the deformed shapes cannot be used + to get the original shape, as the relation with the orignal shape + has been lost. + The original shape can be found as a sibling of the deformed shape + (sharing same transform parent), which has the "intermediate object" + attribute set. + The ID of that shape node can then be transferred to the deformed + shape node. + """ + + # Get long name + node = cmds.ls(node, long=True)[0] + + parent = cmds.listRelatives(node, parent=True, fullPath=True) + + # Get siblings of same type + node_type = cmds.nodeType(node) + similar_nodes = cmds.listRelatives(parent, type=node_type, fullPath=1) + # Exclude itself + similar_nodes = [x for x in similar_nodes if x != node] + + for similar_node in similar_nodes: + # Make sure it is an "intermediate object" + if cmds.getAttr(similar_node + ".io"): + _id = lib.get_id(similar_node) + if _id: + return _id + + @classmethod + def repair(cls, instance): + + for node in cls.get_invalid(instance): + # Get the original id from sibling + sibling_id = cls._get_id_from_sibling(node) + if not sibling_id: + cls.log.error("Could not find ID from sibling for '%s'", node) + continue + + lib.set_id(node, sibling_id, overwrite=True) From d714e52921ca6a36d2568e1a9e98fc7da8085662 Mon Sep 17 00:00:00 2001 From: Derek Severin Date: Wed, 2 Mar 2022 18:47:07 +0700 Subject: [PATCH 02/27] Refactor to existing lib function + plugin --- openpype/hosts/maya/api/lib.py | 30 ++++- ...date_animation_out_set_related_node_ids.py | 4 +- .../validate_node_ids_deformed_shapes.py | 4 +- .../validate_node_ids_deformer_transfer.py | 105 ------------------ .../publish/validate_rig_out_set_node_ids.py | 16 +-- 5 files changed, 38 insertions(+), 121 deletions(-) delete mode 100644 openpype/hosts/maya/plugins/publish/validate_node_ids_deformer_transfer.py diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index 41528f20ba..2f7a09d4c4 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -1751,18 +1751,24 @@ def remove_other_uv_sets(mesh): cmds.removeMultiInstance(attr, b=True) -def get_id_from_history(node): +def get_id_from_sibling(node, history_only=True): """Return first node id in the history chain that matches this node. The nodes in history must be of the exact same node type and must be parented under the same parent. + If no matching node is found in history, the siblings of the node + are checked. Additionally to having the same parent, the sibling must + be marked as 'intermediate object'. + Args: - node (str): node to retrieve the + node (str): node to retrieve the history from + history_only (bool): also looks in node's siblings if True + and if nothing found in history Returns: - str or None: The id from the node in history or None when no id found - on any valid nodes in the history. + str or None: The id from the sibling node or None when no id found + on any valid nodes in the history or siblings. """ @@ -1791,6 +1797,22 @@ def get_id_from_history(node): if _id: return _id + if not history_only: + # Get siblings of same type + similar_nodes = cmds.listRelatives(parent, + type=node_type, + fullPath=True) + # Exclude itself + similar_nodes = [x for x in similar_nodes if x != node] + + for similar_node in similar_nodes: + # Check if "intermediate object" + if cmds.getAttr(similar_node + ".io"): + _id = get_id(similar_node) + if _id: + return _id + + # Project settings def set_scene_fps(fps, update=True): diff --git a/openpype/hosts/maya/plugins/publish/validate_animation_out_set_related_node_ids.py b/openpype/hosts/maya/plugins/publish/validate_animation_out_set_related_node_ids.py index 00f0d38775..7c1c695237 100644 --- a/openpype/hosts/maya/plugins/publish/validate_animation_out_set_related_node_ids.py +++ b/openpype/hosts/maya/plugins/publish/validate_animation_out_set_related_node_ids.py @@ -65,7 +65,7 @@ class ValidateOutRelatedNodeIds(pyblish.api.InstancePlugin): invalid.append(node) continue - history_id = lib.get_id_from_history(node) + history_id = lib.get_id_from_sibling(node) if history_id is not None and node_id != history_id: invalid.append(node) @@ -76,7 +76,7 @@ class ValidateOutRelatedNodeIds(pyblish.api.InstancePlugin): for node in cls.get_invalid(instance): # Get the original id from history - history_id = lib.get_id_from_history(node) + history_id = lib.get_id_from_sibling(node) if not history_id: cls.log.error("Could not find ID in history for '%s'", node) continue diff --git a/openpype/hosts/maya/plugins/publish/validate_node_ids_deformed_shapes.py b/openpype/hosts/maya/plugins/publish/validate_node_ids_deformed_shapes.py index a4d4d2bcc2..0324be9fc9 100644 --- a/openpype/hosts/maya/plugins/publish/validate_node_ids_deformed_shapes.py +++ b/openpype/hosts/maya/plugins/publish/validate_node_ids_deformed_shapes.py @@ -48,7 +48,7 @@ class ValidateNodeIdsDeformedShape(pyblish.api.InstancePlugin): invalid = [] for shape in shapes: - history_id = lib.get_id_from_history(shape) + history_id = lib.get_id_from_sibling(shape) if history_id: current_id = lib.get_id(shape) if current_id != history_id: @@ -61,7 +61,7 @@ class ValidateNodeIdsDeformedShape(pyblish.api.InstancePlugin): for node in cls.get_invalid(instance): # Get the original id from history - history_id = lib.get_id_from_history(node) + history_id = lib.get_id_from_sibling(node) if not history_id: cls.log.error("Could not find ID in history for '%s'", node) continue diff --git a/openpype/hosts/maya/plugins/publish/validate_node_ids_deformer_transfer.py b/openpype/hosts/maya/plugins/publish/validate_node_ids_deformer_transfer.py deleted file mode 100644 index 67b4aff136..0000000000 --- a/openpype/hosts/maya/plugins/publish/validate_node_ids_deformer_transfer.py +++ /dev/null @@ -1,105 +0,0 @@ -from maya import cmds - -import pyblish.api -import openpype.api -import openpype.hosts.maya.api.action -from openpype.hosts.maya.api import lib - - -class ValidateNodeIdsDeformerTransfer(pyblish.api.InstancePlugin): - """Validate if deformed shapes have related IDs to the original - shapes. - - When a deformer is applied in the scene on a mesh, - Maya creates a new "deformer" shape node for the mesh. - This new node does not get the original ID and later references - to the original node ID don't match. - - This validator checks whether the IDs are valid on all the shape - nodes in the instance. - """ - - order = openpype.api.ValidateContentsOrder - families = ['rig'] - hosts = ['maya'] - label = 'Deformed shape ids transferred' - actions = [ - openpype.hosts.maya.api.action.SelectInvalidAction, - openpype.api.RepairAction - ] - - def process(self, instance): - """Process all the nodes in the instance""" - - # Ensure nodes with sibling share the same ID - invalid = self.get_invalid(instance) - if invalid: - raise RuntimeError( - "Shapes found that are considered 'Deformed'" - " with invalid object ids: {0}".format(invalid) - ) - - @classmethod - def get_invalid(cls, instance): - """Get all nodes which do not match the criteria""" - - shapes = cmds.ls(instance[:], - dag=True, - leaf=True, - shapes=True, - long=True, - noIntermediate=True) - - invalid = [] - for shape in shapes: - sibling_id = cls._get_id_from_sibling(shape) - if not sibling_id: - continue - - current_id = lib.get_id(shape) - if current_id != sibling_id: - invalid.append(shape) - - return invalid - - @classmethod - def _get_id_from_sibling(cls, node): - """In some cases, the history of the deformed shapes cannot be used - to get the original shape, as the relation with the orignal shape - has been lost. - The original shape can be found as a sibling of the deformed shape - (sharing same transform parent), which has the "intermediate object" - attribute set. - The ID of that shape node can then be transferred to the deformed - shape node. - """ - - # Get long name - node = cmds.ls(node, long=True)[0] - - parent = cmds.listRelatives(node, parent=True, fullPath=True) - - # Get siblings of same type - node_type = cmds.nodeType(node) - similar_nodes = cmds.listRelatives(parent, type=node_type, fullPath=1) - # Exclude itself - similar_nodes = [x for x in similar_nodes if x != node] - - for similar_node in similar_nodes: - # Make sure it is an "intermediate object" - if cmds.getAttr(similar_node + ".io"): - _id = lib.get_id(similar_node) - if _id: - return _id - - @classmethod - def repair(cls, instance): - - for node in cls.get_invalid(instance): - # Get the original id from sibling - sibling_id = cls._get_id_from_sibling(node) - if not sibling_id: - cls.log.error("Could not find ID from sibling for '%s'", node) - continue - - lib.set_id(node, sibling_id, overwrite=True) diff --git a/openpype/hosts/maya/plugins/publish/validate_rig_out_set_node_ids.py b/openpype/hosts/maya/plugins/publish/validate_rig_out_set_node_ids.py index e2090080f6..c1029366e8 100644 --- a/openpype/hosts/maya/plugins/publish/validate_rig_out_set_node_ids.py +++ b/openpype/hosts/maya/plugins/publish/validate_rig_out_set_node_ids.py @@ -51,10 +51,10 @@ class ValidateRigOutSetNodeIds(pyblish.api.InstancePlugin): noIntermediate=True) for shape in shapes: - history_id = lib.get_id_from_history(shape) - if history_id: + sibling_id = lib.get_id_from_sibling(shape, history_only=False) + if sibling_id: current_id = lib.get_id(shape) - if current_id != history_id: + if current_id != sibling_id: invalid.append(shape) return invalid @@ -63,10 +63,10 @@ class ValidateRigOutSetNodeIds(pyblish.api.InstancePlugin): def repair(cls, instance): for node in cls.get_invalid(instance): - # Get the original id from history - history_id = lib.get_id_from_history(node) - if not history_id: - cls.log.error("Could not find ID in history for '%s'", node) + # Get the original id from sibling + sibling_id = lib.get_id_from_sibling(node, history_only=False) + if not sibling_id: + cls.log.error("Could not find ID in siblings for '%s'", node) continue - lib.set_id(node, history_id, overwrite=True) + lib.set_id(node, sibling_id, overwrite=True) From c95752be966e5f99f0ac25490a035a47c1264f1a Mon Sep 17 00:00:00 2001 From: Derek Severin Date: Thu, 3 Mar 2022 14:57:35 +0700 Subject: [PATCH 03/27] 'history only' as plugin setting --- .../publish/validate_rig_out_set_node_ids.py | 9 +++++++-- .../schemas/schema_maya_publish.json | 20 +++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_rig_out_set_node_ids.py b/openpype/hosts/maya/plugins/publish/validate_rig_out_set_node_ids.py index c1029366e8..c272c5c485 100644 --- a/openpype/hosts/maya/plugins/publish/validate_rig_out_set_node_ids.py +++ b/openpype/hosts/maya/plugins/publish/validate_rig_out_set_node_ids.py @@ -24,6 +24,7 @@ class ValidateRigOutSetNodeIds(pyblish.api.InstancePlugin): openpype.hosts.maya.api.action.SelectInvalidAction, openpype.api.RepairAction ] + allow_history_only = False def process(self, instance): """Process all meshes""" @@ -51,7 +52,9 @@ class ValidateRigOutSetNodeIds(pyblish.api.InstancePlugin): noIntermediate=True) for shape in shapes: - sibling_id = lib.get_id_from_sibling(shape, history_only=False) + sibling_id = \ + lib.get_id_from_sibling(shape, + history_only=cls.allow_history_only) if sibling_id: current_id = lib.get_id(shape) if current_id != sibling_id: @@ -64,7 +67,9 @@ class ValidateRigOutSetNodeIds(pyblish.api.InstancePlugin): for node in cls.get_invalid(instance): # Get the original id from sibling - sibling_id = lib.get_id_from_sibling(node, history_only=False) + sibling_id = \ + lib.get_id_from_sibling(node, + history_only=cls.allow_history_only) if not sibling_id: cls.log.error("Could not find ID in siblings for '%s'", node) continue diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json index 7c9a5a6b46..0c82997cce 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json @@ -396,6 +396,26 @@ "label": "Validate Rig Controllers" } ] + }, + { + "type": "dict", + "collapsible": true, + "checkbox_key": "enabled", + "key": "ValidateRigOutSetNodeIds", + "label": "Validate Rig Out Set Node Ids", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "allow_history_only", + "label": "Allow history only" + } + ] } ] }, From acd86c30914f1a2e52dcd3e2f3c9a63d9b3be7d7 Mon Sep 17 00:00:00 2001 From: Derek Severin Date: Thu, 3 Mar 2022 16:25:38 +0700 Subject: [PATCH 04/27] Full attribute name for readability --- openpype/hosts/maya/api/lib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index 2f7a09d4c4..c9e10c7041 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -1807,7 +1807,7 @@ def get_id_from_sibling(node, history_only=True): for similar_node in similar_nodes: # Check if "intermediate object" - if cmds.getAttr(similar_node + ".io"): + if cmds.getAttr(similar_node + ".intermediateObject"): _id = get_id(similar_node) if _id: return _id From cd498441a6aa86d02cc2deb8be6c33102797e1ff Mon Sep 17 00:00:00 2001 From: Derek Severin Date: Thu, 3 Mar 2022 16:55:40 +0700 Subject: [PATCH 05/27] Code style fix --- .../publish/validate_rig_out_set_node_ids.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_rig_out_set_node_ids.py b/openpype/hosts/maya/plugins/publish/validate_rig_out_set_node_ids.py index c272c5c485..ed1d36261a 100644 --- a/openpype/hosts/maya/plugins/publish/validate_rig_out_set_node_ids.py +++ b/openpype/hosts/maya/plugins/publish/validate_rig_out_set_node_ids.py @@ -52,9 +52,10 @@ class ValidateRigOutSetNodeIds(pyblish.api.InstancePlugin): noIntermediate=True) for shape in shapes: - sibling_id = \ - lib.get_id_from_sibling(shape, - history_only=cls.allow_history_only) + sibling_id = lib.get_id_from_sibling( + shape, + history_only=cls.allow_history_only + ) if sibling_id: current_id = lib.get_id(shape) if current_id != sibling_id: @@ -67,9 +68,10 @@ class ValidateRigOutSetNodeIds(pyblish.api.InstancePlugin): for node in cls.get_invalid(instance): # Get the original id from sibling - sibling_id = \ - lib.get_id_from_sibling(node, - history_only=cls.allow_history_only) + sibling_id = lib.get_id_from_sibling( + node, + history_only=cls.allow_history_only + ) if not sibling_id: cls.log.error("Could not find ID in siblings for '%s'", node) continue From 4ba40f2a175ec78ac8371dbf62ea2a3eeb61998b Mon Sep 17 00:00:00 2001 From: Derek Severin Date: Thu, 3 Mar 2022 17:48:40 +0700 Subject: [PATCH 06/27] Exact type for siblings --- openpype/hosts/maya/api/lib.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index c9e10c7041..bbd7786b36 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -1802,6 +1802,8 @@ def get_id_from_sibling(node, history_only=True): similar_nodes = cmds.listRelatives(parent, type=node_type, fullPath=True) + similar_nodes = cmds.ls(similar_nodes, exactType=node_type, long=True) + # Exclude itself similar_nodes = [x for x in similar_nodes if x != node] From 024a7220fe36f8a3df60347df10873aa01a1cd6b Mon Sep 17 00:00:00 2001 From: Derek Severin Date: Thu, 3 Mar 2022 17:52:18 +0700 Subject: [PATCH 07/27] Plugin setting default value --- openpype/settings/defaults/project_settings/maya.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json index a756071106..b6fa3719ef 100644 --- a/openpype/settings/defaults/project_settings/maya.json +++ b/openpype/settings/defaults/project_settings/maya.json @@ -351,6 +351,10 @@ "optional": true, "active": true }, + "ValidateRigOutSetNodeIds": { + "enabled": true, + "allow_history_only": false + }, "ValidateCameraAttributes": { "enabled": false, "optional": true, From 3b0cee19ba2b3f9351e87c49f690950d86587b90 Mon Sep 17 00:00:00 2001 From: Derek Severin Date: Thu, 3 Mar 2022 19:20:52 +0700 Subject: [PATCH 08/27] Adapted/corrected comment --- openpype/hosts/maya/api/lib.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index bbd7786b36..62de5a96eb 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -1757,14 +1757,16 @@ def get_id_from_sibling(node, history_only=True): The nodes in history must be of the exact same node type and must be parented under the same parent. - If no matching node is found in history, the siblings of the node - are checked. Additionally to having the same parent, the sibling must - be marked as 'intermediate object'. + Optionally, if no matching node is found from the history, all the + siblings of the node that are of the same type are checked. + Additionally to having the same parent, the sibling must be marked as + 'intermediate object'. Args: node (str): node to retrieve the history from - history_only (bool): also looks in node's siblings if True - and if nothing found in history + history_only (bool): if True and if nothing found in history, + look for an 'intermediate object' in all the node's siblings + of same type Returns: str or None: The id from the sibling node or None when no id found From a864b80862d91ace2d46e23aa1fbb10b8a6a7481 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Mon, 14 Mar 2022 15:53:41 +0100 Subject: [PATCH 09/27] flame: convert segment comment to attributes wip --- .../hosts/flame/plugins/publish/collect_timeline_instances.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py b/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py index 6424bce3bc..54ff543f21 100644 --- a/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py +++ b/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py @@ -16,6 +16,9 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin): audio_track_items = [] + def _get_comment_attributes(self, segment): + comment = segment.comment.get_value() + def process(self, context): project = context.data["flameProject"] sequence = context.data["flameSequence"] @@ -26,6 +29,7 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin): # process all sellected with opfapi.maintained_segment_selection(sequence) as segments: for segment in segments: + comment_attributes = self._get_comment_attributes(segment) clip_data = opfapi.get_segment_attributes(segment) clip_name = clip_data["segment_name"] self.log.debug("clip_name: {}".format(clip_name)) From 34b44bec6306c807c3c652872d5b53b8838b0e11 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Mon, 14 Mar 2022 19:36:25 +0100 Subject: [PATCH 10/27] flame: resolving attributes from segment comments --- .../publish/collect_timeline_instances.py | 45 +++++++++++++++++-- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py b/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py index 54ff543f21..9e6c7210fb 100644 --- a/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py +++ b/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py @@ -1,3 +1,4 @@ +import re import pyblish import openpype import openpype.hosts.flame.api as opfapi @@ -16,9 +17,6 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin): audio_track_items = [] - def _get_comment_attributes(self, segment): - comment = segment.comment.get_value() - def process(self, context): project = context.data["flameProject"] sequence = context.data["flameSequence"] @@ -30,6 +28,9 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin): with opfapi.maintained_segment_selection(sequence) as segments: for segment in segments: comment_attributes = self._get_comment_attributes(segment) + self.log.debug("_ comment_attributes: {}".format( + pformat(comment_attributes))) + clip_data = opfapi.get_segment_attributes(segment) clip_name = clip_data["segment_name"] self.log.debug("clip_name: {}".format(clip_name)) @@ -130,6 +131,44 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin): if marker_data.get("reviewTrack") is not None: instance.data["reviewAudio"] = True + def _get_comment_attributes(self, segment): + comment = segment.comment.get_value() + + # first split comment by comma + split_comments = [] + if "," in comment: + split_comments.extend(iter(comment.split(","))) + elif ";" in comment: + split_comments.extend(iter(comment.split(";"))) + else: + split_comments.append(comment) + + # try to find attributes + attributes = {} + # search for `:` + for split in split_comments: + # make sure we ignore if not `:` in key + if ":" not in split: + continue + + # split to key and value + key, value = split.split(":") + + # condition for resolution in key + if "resolution" in key.lower(): + patern = re.compile(r"([0-9]+)") + res_goup = patern.findall(value) + + # check if axpect was also defined + # 1920x1080x1.5 + aspect = res_goup[2] if len(res_goup) > 2 else 1 + + attributes["resolution"] = { + "width": int(res_goup[0]), + "height": int(res_goup[1]), + "pixelAspect": float(aspect) + } + def _get_head_tail(self, clip_data, first_frame): # calculate head and tail with forward compatibility head = clip_data.get("segment_head") From bd57a0fd56f76c71328020eeaa29aec294ea7efb Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Mon, 14 Mar 2022 19:49:15 +0100 Subject: [PATCH 11/27] flame: add comment attributes to instance data --- .../plugins/publish/collect_timeline_instances.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py b/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py index 9e6c7210fb..dd44627021 100644 --- a/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py +++ b/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py @@ -106,6 +106,9 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin): # add resolution self._get_resolution_to_data(inst_data, context) + # add comment attributes if any + inst_data.update(comment_attributes) + # create instance instance = context.create_instance(**inst_data) @@ -163,11 +166,13 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin): # 1920x1080x1.5 aspect = res_goup[2] if len(res_goup) > 2 else 1 - attributes["resolution"] = { - "width": int(res_goup[0]), - "height": int(res_goup[1]), + attributes.update({ + "resolutionWidth": int(res_goup[0]), + "resolutionHeight": int(res_goup[1]), "pixelAspect": float(aspect) - } + }) + + return attributes def _get_head_tail(self, clip_data, first_frame): # calculate head and tail with forward compatibility From 420122b8c9ec5e3eeefe7f89e8627c06a30f6eed Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Mon, 14 Mar 2022 19:57:35 +0100 Subject: [PATCH 12/27] flame: fix regex to get float number too --- .../hosts/flame/plugins/publish/collect_timeline_instances.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py b/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py index dd44627021..f41f773802 100644 --- a/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py +++ b/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py @@ -159,7 +159,7 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin): # condition for resolution in key if "resolution" in key.lower(): - patern = re.compile(r"([0-9]+)") + patern = re.compile(r"([0-9\.]+)") res_goup = patern.findall(value) # check if axpect was also defined From 0a7cbeef6df772531270755c93120dcb4fa20fad Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 15 Mar 2022 14:17:24 +0100 Subject: [PATCH 13/27] flame: refactor to settings configurability --- .../publish/collect_timeline_instances.py | 103 +++++++++++++----- 1 file changed, 76 insertions(+), 27 deletions(-) diff --git a/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py b/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py index f41f773802..e54ff9a167 100644 --- a/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py +++ b/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py @@ -7,6 +7,10 @@ from openpype.hosts.flame.otio import flame_export # # developer reload modules from pprint import pformat +# constatns +NUM_PATERN = re.compile(r"([0-9\.]+)") +TXT_PATERN = re.compile(r"([a-zA-Z]+)") + class CollectTimelineInstances(pyblish.api.ContextPlugin): """Collect all Timeline segment selection.""" @@ -17,6 +21,16 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin): audio_track_items = [] + # TODO: add to settings + # settings + xml_preset_attrs_from_comments = { + "width": "number", + "height": "number", + "pixelRatio": "number", + "resizeType": "string", + "resizeFilter": "string" + } + def process(self, context): project = context.data["flameProject"] sequence = context.data["flameSequence"] @@ -137,43 +151,78 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin): def _get_comment_attributes(self, segment): comment = segment.comment.get_value() - # first split comment by comma - split_comments = [] - if "," in comment: - split_comments.extend(iter(comment.split(","))) - elif ";" in comment: - split_comments.extend(iter(comment.split(";"))) - else: - split_comments.append(comment) - # try to find attributes - attributes = {} + attributes = { + "pixelRatio": 1.00 + } # search for `:` - for split in split_comments: + for split in self._split_comments(comment): # make sure we ignore if not `:` in key if ":" not in split: continue - # split to key and value - key, value = split.split(":") + self._get_xml_preset_attrs( + attributes, split) - # condition for resolution in key - if "resolution" in key.lower(): - patern = re.compile(r"([0-9\.]+)") - res_goup = patern.findall(value) - - # check if axpect was also defined - # 1920x1080x1.5 - aspect = res_goup[2] if len(res_goup) > 2 else 1 - - attributes.update({ - "resolutionWidth": int(res_goup[0]), - "resolutionHeight": int(res_goup[1]), - "pixelAspect": float(aspect) - }) + if attributes.get("width"): + attributes["resolution"] = { + "resolutionWidth": attributes["width"], + "resolutionHeight": attributes["height"], + "pixelAspect": attributes["pixelRatio"] + } return attributes + def _get_xml_preset_attrs(self, attributes, split): + + # split to key and value + key, value = split.split(":") + + for a_name, a_type in self.xml_preset_attrs_from_comments.items(): + # exclude all not related attributes + if a_name.lower() not in key: + continue + + # get pattern defined by type + pattern = TXT_PATERN if "string" in a_type else NUM_PATERN + res_goup = pattern.findall(value) + + # raise if nothing is found as it is not correctly defined + if not res_goup: + raise ValueError(( + "Value for `{}` attribute is not " + "set correctly: `{}`").format(a_name, split)) + + attributes[a_name] = res_goup[0] + + # condition for resolution in key + if "resolution" in key.lower(): + res_goup = NUM_PATERN.findall(value) + # check if axpect was also defined + # 1920x1080x1.5 + aspect = res_goup[2] if len(res_goup) > 2 else 1 + + width = int(res_goup[0]) + height = int(res_goup[1]) + pixel_ratio = float(aspect) + attributes.update({ + "width": width, + "height": height, + "pixelRatio": pixel_ratio + }) + + def _split_comments(self, comment_string): + # first split comment by comma + split_comments = [] + if "," in comment_string: + split_comments.extend(iter(comment_string.split(","))) + elif ";" in comment_string: + split_comments.extend(iter(comment_string.split(";"))) + else: + split_comments.append(comment_string) + + return split_comments + def _get_head_tail(self, clip_data, first_frame): # calculate head and tail with forward compatibility head = clip_data.get("segment_head") From d408139bb7a9753e0892d648819af4db6093e9e9 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 15 Mar 2022 14:26:08 +0100 Subject: [PATCH 14/27] flame: restructure data nesting for better absorption to instance data --- .../publish/collect_timeline_instances.py | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py b/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py index e54ff9a167..72ad2cd1c3 100644 --- a/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py +++ b/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py @@ -153,7 +153,8 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin): # try to find attributes attributes = { - "pixelRatio": 1.00 + "xml_overrides": { + "pixelRatio": 1.00} } # search for `:` for split in self._split_comments(comment): @@ -164,12 +165,14 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin): self._get_xml_preset_attrs( attributes, split) - if attributes.get("width"): - attributes["resolution"] = { - "resolutionWidth": attributes["width"], - "resolutionHeight": attributes["height"], - "pixelAspect": attributes["pixelRatio"] - } + # add xml overides resolution to instance data + xml_overrides = attributes["xml_overrides"] + if xml_overrides.get("width"): + attributes.update({ + "resolutionWidth": xml_overrides["width"], + "resolutionHeight": xml_overrides["height"], + "pixelAspect": xml_overrides["pixelRatio"] + }) return attributes @@ -193,7 +196,7 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin): "Value for `{}` attribute is not " "set correctly: `{}`").format(a_name, split)) - attributes[a_name] = res_goup[0] + attributes["xml_overrides"][a_name] = res_goup[0] # condition for resolution in key if "resolution" in key.lower(): @@ -205,7 +208,7 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin): width = int(res_goup[0]) height = int(res_goup[1]) pixel_ratio = float(aspect) - attributes.update({ + attributes["xml_overrides"].update({ "width": width, "height": height, "pixelRatio": pixel_ratio From 48ce34c58e960e458676bf215b21fb5416ad960d Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 15 Mar 2022 14:26:47 +0100 Subject: [PATCH 15/27] flame: add xml_overrides to extracting profiles --- .../flame/plugins/publish/extract_subset_resources.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/openpype/hosts/flame/plugins/publish/extract_subset_resources.py b/openpype/hosts/flame/plugins/publish/extract_subset_resources.py index 5c3aed9672..194557e37a 100644 --- a/openpype/hosts/flame/plugins/publish/extract_subset_resources.py +++ b/openpype/hosts/flame/plugins/publish/extract_subset_resources.py @@ -1,9 +1,11 @@ import os from pprint import pformat from copy import deepcopy + import pyblish.api import openpype.api from openpype.hosts.flame import api as opfapi +from pprint import pformat class ExtractSubsetResources(openpype.api.Extractor): @@ -131,6 +133,12 @@ class ExtractSubsetResources(openpype.api.Extractor): "startFrame": frame_start }) + # add any xml overrides collected form segment.comment + modify_xml_data.update(instance.data["xml_overrides"]) + self.log.debug("__ modify_xml_data: {}".format(pformat( + modify_xml_data + ))) + # with maintained duplication loop all presets with opfapi.maintained_object_duplication( exporting_clip) as duplclip: From db7e9cc4aa6b4fd09496139d2fff878e3606312f Mon Sep 17 00:00:00 2001 From: 2-REC Date: Wed, 16 Mar 2022 12:13:47 +0700 Subject: [PATCH 16/27] Warning log if more than 1 shape id --- openpype/hosts/maya/api/lib.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index 62de5a96eb..f49c0f689e 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -1809,12 +1809,22 @@ def get_id_from_sibling(node, history_only=True): # Exclude itself similar_nodes = [x for x in similar_nodes if x != node] + first_id = None for similar_node in similar_nodes: # Check if "intermediate object" if cmds.getAttr(similar_node + ".intermediateObject"): _id = get_id(similar_node) if _id: - return _id + # Check if already found an id + if first_id: + log.warning(("Found more than 1 matching intermediate" + " shape for '{}'. Using id of first" + " found: '{}'".format(node, found_node))) + break + first_id = _id + found_node = similar_node + + return first_id From 802f8a482d6278f2184b0f38ad52fc56efb737cb Mon Sep 17 00:00:00 2001 From: 2-REC Date: Wed, 16 Mar 2022 12:16:33 +0700 Subject: [PATCH 17/27] Variable declaration --- openpype/hosts/maya/api/lib.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index f49c0f689e..e2c07624e6 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -1810,6 +1810,7 @@ def get_id_from_sibling(node, history_only=True): similar_nodes = [x for x in similar_nodes if x != node] first_id = None + found_node = None for similar_node in similar_nodes: # Check if "intermediate object" if cmds.getAttr(similar_node + ".intermediateObject"): From a11fe7a5503c993b53c72c16eb306d3447ead29a Mon Sep 17 00:00:00 2001 From: 2-REC Date: Wed, 16 Mar 2022 16:38:17 +0700 Subject: [PATCH 18/27] Fix to allow more than 1 shape with same ids --- openpype/hosts/maya/api/lib.py | 40 ++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index b46eff5a4b..f0f6bb706f 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -1989,23 +1989,35 @@ def get_id_from_sibling(node, history_only=True): # Exclude itself similar_nodes = [x for x in similar_nodes if x != node] - first_id = None - found_node = None + + # Get all unique ids from siblings in order since + # we consistently take the first one found + sibling_ids = OrderedDict() for similar_node in similar_nodes: # Check if "intermediate object" - if cmds.getAttr(similar_node + ".intermediateObject"): - _id = get_id(similar_node) - if _id: - # Check if already found an id - if first_id: - log.warning(("Found more than 1 matching intermediate" - " shape for '{}'. Using id of first" - " found: '{}'".format(node, found_node))) - break - first_id = _id - found_node = similar_node + if not cmds.getAttr(similar_node + ".intermediateObject"): + continue - return first_id + _id = get_id(similar_node) + if not _id: + continue + + if _id in sibling_ids: + sibling_ids[_id].append(similar_node) + else: + sibling_ids[_id] = [similar_node] + + if sibling_ids: + first_id, found_nodes = next(iter(sibling_ids.items())) + + # Log a warning if we've found multiple unique ids + if len(sibling_ids) > 1: + log.warning(("Found more than 1 intermediate shape with" + " unique id for '{}'. Using id of first" + " found: '{}'".format(node, found_nodes[0]))) + break + + return first_id From 9e4a3cf9504ebbb09c30d3c1d2bcd772eed1cf4d Mon Sep 17 00:00:00 2001 From: 2-REC Date: Wed, 16 Mar 2022 16:41:27 +0700 Subject: [PATCH 19/27] Distraction fix... --- openpype/hosts/maya/api/lib.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index f0f6bb706f..f7507d87c5 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -1989,7 +1989,6 @@ def get_id_from_sibling(node, history_only=True): # Exclude itself similar_nodes = [x for x in similar_nodes if x != node] - # Get all unique ids from siblings in order since # we consistently take the first one found sibling_ids = OrderedDict() @@ -2015,7 +2014,6 @@ def get_id_from_sibling(node, history_only=True): log.warning(("Found more than 1 intermediate shape with" " unique id for '{}'. Using id of first" " found: '{}'".format(node, found_nodes[0]))) - break return first_id From 8af535adba3303ae759638f9933cb68ec46517bb Mon Sep 17 00:00:00 2001 From: 2-REC Date: Wed, 16 Mar 2022 18:09:50 +0700 Subject: [PATCH 20/27] More adapted error message --- .../publish/validate_animation_out_set_related_node_ids.py | 4 ++-- .../maya/plugins/publish/validate_rig_out_set_node_ids.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_animation_out_set_related_node_ids.py b/openpype/hosts/maya/plugins/publish/validate_animation_out_set_related_node_ids.py index 7c1c695237..05d63f1d56 100644 --- a/openpype/hosts/maya/plugins/publish/validate_animation_out_set_related_node_ids.py +++ b/openpype/hosts/maya/plugins/publish/validate_animation_out_set_related_node_ids.py @@ -32,8 +32,8 @@ class ValidateOutRelatedNodeIds(pyblish.api.InstancePlugin): # if a deformer has been created on the shape invalid = self.get_invalid(instance) if invalid: - raise RuntimeError("Nodes found with non-related " - "asset IDs: {0}".format(invalid)) + raise RuntimeError("Nodes found with mismatching " + "IDs: {0}".format(invalid)) @classmethod def get_invalid(cls, instance): diff --git a/openpype/hosts/maya/plugins/publish/validate_rig_out_set_node_ids.py b/openpype/hosts/maya/plugins/publish/validate_rig_out_set_node_ids.py index ed1d36261a..cc3723a6e1 100644 --- a/openpype/hosts/maya/plugins/publish/validate_rig_out_set_node_ids.py +++ b/openpype/hosts/maya/plugins/publish/validate_rig_out_set_node_ids.py @@ -33,8 +33,8 @@ class ValidateRigOutSetNodeIds(pyblish.api.InstancePlugin): # if a deformer has been created on the shape invalid = self.get_invalid(instance) if invalid: - raise RuntimeError("Nodes found with non-related " - "asset IDs: {0}".format(invalid)) + raise RuntimeError("Nodes found with mismatching " + "IDs: {0}".format(invalid)) @classmethod def get_invalid(cls, instance): From d867b872a894986579709718e2894596ed9e527a Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 16 Mar 2022 16:55:51 +0100 Subject: [PATCH 21/27] flame: distribute better value types --- .../publish/collect_timeline_instances.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py b/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py index 72ad2cd1c3..44c25f04a2 100644 --- a/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py +++ b/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py @@ -26,7 +26,7 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin): xml_preset_attrs_from_comments = { "width": "number", "height": "number", - "pixelRatio": "number", + "pixelRatio": "float", "resizeType": "string", "resizeFilter": "string" } @@ -183,11 +183,14 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin): for a_name, a_type in self.xml_preset_attrs_from_comments.items(): # exclude all not related attributes - if a_name.lower() not in key: + if a_name.lower() not in key.lower(): continue # get pattern defined by type - pattern = TXT_PATERN if "string" in a_type else NUM_PATERN + pattern = TXT_PATERN + if "number" in a_type or "float" in a_type: + pattern = NUM_PATERN + res_goup = pattern.findall(value) # raise if nothing is found as it is not correctly defined @@ -196,7 +199,14 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin): "Value for `{}` attribute is not " "set correctly: `{}`").format(a_name, split)) - attributes["xml_overrides"][a_name] = res_goup[0] + if "string" in a_type: + _value = res_goup[0] + if "float" in a_type: + _value = float(res_goup[0]) + if "number" in a_type: + _value = int(res_goup[0]) + + attributes["xml_overrides"][a_name] = _value # condition for resolution in key if "resolution" in key.lower(): From d98d8905afb1ae3a28af03904adc6b4e57114fff Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 16 Mar 2022 17:10:56 +0100 Subject: [PATCH 22/27] Flame: add ignoring toggle to settings parsed attributes from comments can be ignored now --- .../plugins/publish/extract_subset_resources.py | 14 +++++++++----- .../settings/defaults/project_settings/flame.json | 1 + .../projects_schema/schema_project_flame.json | 11 +++++++++++ 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/flame/plugins/publish/extract_subset_resources.py b/openpype/hosts/flame/plugins/publish/extract_subset_resources.py index 2e3b84def8..ac50c7c980 100644 --- a/openpype/hosts/flame/plugins/publish/extract_subset_resources.py +++ b/openpype/hosts/flame/plugins/publish/extract_subset_resources.py @@ -25,6 +25,7 @@ class ExtractSubsetResources(openpype.api.Extractor): "xml_preset_file": "Jpeg (8-bit).xml", "xml_preset_dir": "", "export_type": "File Sequence", + "ignore_comment_attrs": True, "colorspace_out": "Output - sRGB", "representation_add_range": False, "representation_tags": ["thumbnail"] @@ -34,6 +35,7 @@ class ExtractSubsetResources(openpype.api.Extractor): "xml_preset_file": "Apple iPad (1920x1080).xml", "xml_preset_dir": "", "export_type": "Movie", + "ignore_comment_attrs": True, "colorspace_out": "Output - Rec.709", "representation_add_range": True, "representation_tags": [ @@ -104,6 +106,7 @@ class ExtractSubsetResources(openpype.api.Extractor): preset_dir = preset_config["xml_preset_dir"] export_type = preset_config["export_type"] repre_tags = preset_config["representation_tags"] + ignore_comment_attrs = preset_config["ignore_comment_attrs"] color_out = preset_config["colorspace_out"] # get frame range with handles for representation range @@ -133,11 +136,12 @@ class ExtractSubsetResources(openpype.api.Extractor): "startFrame": frame_start }) - # add any xml overrides collected form segment.comment - modify_xml_data.update(instance.data["xml_overrides"]) - self.log.debug("__ modify_xml_data: {}".format(pformat( - modify_xml_data - ))) + if not ignore_comment_attrs: + # add any xml overrides collected form segment.comment + modify_xml_data.update(instance.data["xml_overrides"]) + self.log.debug("__ modify_xml_data: {}".format(pformat( + modify_xml_data + ))) # with maintained duplication loop all presets with opfapi.maintained_object_duplication( diff --git a/openpype/settings/defaults/project_settings/flame.json b/openpype/settings/defaults/project_settings/flame.json index ef9c2b1041..c7188b10b5 100644 --- a/openpype/settings/defaults/project_settings/flame.json +++ b/openpype/settings/defaults/project_settings/flame.json @@ -28,6 +28,7 @@ "xml_preset_file": "OpenEXR (16-bit fp DWAA).xml", "xml_preset_dir": "", "export_type": "File Sequence", + "ignore_comment_attrs": false, "colorspace_out": "ACES - ACEScg", "representation_add_range": true, "representation_tags": [] diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_flame.json b/openpype/settings/entities/schemas/projects_schema/schema_project_flame.json index 1f30b45981..e352f8b132 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_flame.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_flame.json @@ -189,6 +189,17 @@ ] }, + { + "type": "separator" + }, + { + "type": "boolean", + "key": "ignore_comment_attrs", + "label": "Ignore attributes parsed from a segment comments" + }, + { + "type": "separator" + }, { "key": "colorspace_out", "label": "Output color (imageio)", From 4b83446230d54a804fd2a509a709abab463c44cc Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 16 Mar 2022 17:42:27 +0100 Subject: [PATCH 23/27] flame: moving logging outside of condition --- .../flame/plugins/publish/extract_subset_resources.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/flame/plugins/publish/extract_subset_resources.py b/openpype/hosts/flame/plugins/publish/extract_subset_resources.py index ac50c7c980..d52669d955 100644 --- a/openpype/hosts/flame/plugins/publish/extract_subset_resources.py +++ b/openpype/hosts/flame/plugins/publish/extract_subset_resources.py @@ -139,9 +139,10 @@ class ExtractSubsetResources(openpype.api.Extractor): if not ignore_comment_attrs: # add any xml overrides collected form segment.comment modify_xml_data.update(instance.data["xml_overrides"]) - self.log.debug("__ modify_xml_data: {}".format(pformat( - modify_xml_data - ))) + + self.log.debug("__ modify_xml_data: {}".format(pformat( + modify_xml_data + ))) # with maintained duplication loop all presets with opfapi.maintained_object_duplication( From d0a79e31f5afb8dcdd5bbcf7d376b89c98d29456 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 16 Mar 2022 17:44:01 +0100 Subject: [PATCH 24/27] hound and suggested changes --- .../hosts/flame/plugins/publish/collect_timeline_instances.py | 4 ++-- .../hosts/flame/plugins/publish/extract_subset_resources.py | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py b/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py index 44c25f04a2..c6793874c0 100644 --- a/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py +++ b/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py @@ -228,9 +228,9 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin): # first split comment by comma split_comments = [] if "," in comment_string: - split_comments.extend(iter(comment_string.split(","))) + split_comments.extend(comment_string.split(",")) elif ";" in comment_string: - split_comments.extend(iter(comment_string.split(";"))) + split_comments.extend(comment_string.split(";")) else: split_comments.append(comment_string) diff --git a/openpype/hosts/flame/plugins/publish/extract_subset_resources.py b/openpype/hosts/flame/plugins/publish/extract_subset_resources.py index d52669d955..32f6b9508f 100644 --- a/openpype/hosts/flame/plugins/publish/extract_subset_resources.py +++ b/openpype/hosts/flame/plugins/publish/extract_subset_resources.py @@ -5,7 +5,6 @@ from copy import deepcopy import pyblish.api import openpype.api from openpype.hosts.flame import api as opfapi -from pprint import pformat class ExtractSubsetResources(openpype.api.Extractor): From fdb880c5440568e1f5f1a8fdc539ae7ddcad15f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Je=C5=BEek?= Date: Thu, 17 Mar 2022 12:57:34 +0100 Subject: [PATCH 25/27] Update openpype/hosts/flame/plugins/publish/collect_timeline_instances.py Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- .../hosts/flame/plugins/publish/collect_timeline_instances.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py b/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py index c6793874c0..70340ad7a2 100644 --- a/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py +++ b/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py @@ -188,7 +188,7 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin): # get pattern defined by type pattern = TXT_PATERN - if "number" in a_type or "float" in a_type: + if a_type in ("number" , "float"): pattern = NUM_PATERN res_goup = pattern.findall(value) From 0ea4e0acd4f78899df9e2ba6932a11beb88283dc Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 17 Mar 2022 12:59:30 +0100 Subject: [PATCH 26/27] improving gap detection in extract review --- openpype/plugins/publish/extract_review.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/openpype/plugins/publish/extract_review.py b/openpype/plugins/publish/extract_review.py index cbe1924408..3ecea1f8bd 100644 --- a/openpype/plugins/publish/extract_review.py +++ b/openpype/plugins/publish/extract_review.py @@ -747,10 +747,14 @@ class ExtractReview(pyblish.api.InstancePlugin): collections = clique.assemble(files)[0] assert len(collections) == 1, "Multiple collections found." col = collections[0] - # do nothing if sequence is complete - if list(col.indexes)[0] == start_frame and \ - list(col.indexes)[-1] == end_frame and \ - col.is_contiguous(): + + # do nothing if no gap is found in input range + not_gap = True + for fr in range(start_frame, end_frame + 1): + if fr not in col.indexes: + not_gap = False + + if not_gap: return [] holes = col.holes() From eaae7f4828ba68b1e4b11f688357a9bd13c46ec1 Mon Sep 17 00:00:00 2001 From: OpenPype Date: Thu, 17 Mar 2022 13:33:11 +0000 Subject: [PATCH 27/27] [Automated] Bump version --- CHANGELOG.md | 11 ++++++++++- openpype/version.py | 2 +- pyproject.toml | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7790894b7f..6a1da69f13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,19 +1,28 @@ # Changelog -## [3.9.1-nightly.1](https://github.com/pypeclub/OpenPype/tree/HEAD) +## [3.9.1-nightly.2](https://github.com/pypeclub/OpenPype/tree/HEAD) [Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.9.0...HEAD) +**🚀 Enhancements** + +- Nuke: ExtractReviewSlate can handle more codes and profiles [\#2879](https://github.com/pypeclub/OpenPype/pull/2879) +- Flame: sequence used for reference video [\#2869](https://github.com/pypeclub/OpenPype/pull/2869) + **🐛 Bug fixes** +- Pyblish Pype - ensure current state is correct when entering new group order [\#2899](https://github.com/pypeclub/OpenPype/pull/2899) +- SceneInventory: Fix import of load function [\#2894](https://github.com/pypeclub/OpenPype/pull/2894) - Harmony - fixed creator issue [\#2891](https://github.com/pypeclub/OpenPype/pull/2891) - General: Remove forgotten use of avalon Creator [\#2885](https://github.com/pypeclub/OpenPype/pull/2885) - General: Avoid circular import [\#2884](https://github.com/pypeclub/OpenPype/pull/2884) - Fixes for attaching loaded containers \(\#2837\) [\#2874](https://github.com/pypeclub/OpenPype/pull/2874) +- Maya: Deformer node ids validation plugin [\#2826](https://github.com/pypeclub/OpenPype/pull/2826) **🔀 Refactored code** - General: Reduce style usage to OpenPype repository [\#2889](https://github.com/pypeclub/OpenPype/pull/2889) +- General: Move loader logic from avalon to openpype [\#2886](https://github.com/pypeclub/OpenPype/pull/2886) ## [3.9.0](https://github.com/pypeclub/OpenPype/tree/3.9.0) (2022-03-14) diff --git a/openpype/version.py b/openpype/version.py index 17e514642d..5eca7c1d90 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.9.1-nightly.1" +__version__ = "3.9.1-nightly.2" diff --git a/pyproject.toml b/pyproject.toml index 128d1cd615..af448ed24c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "OpenPype" -version = "3.9.1-nightly.1" # OpenPype +version = "3.9.1-nightly.2" # OpenPype description = "Open VFX and Animation pipeline with support." authors = ["OpenPype Team "] license = "MIT License"