From 36f1a1103ee6e148c0dd42aa66f81fff05b352cf Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 30 Mar 2023 00:23:43 +0200 Subject: [PATCH 1/8] Fix #4693: Add `displayGradient` key to allow disabling gradient background --- openpype/hosts/maya/api/lib.py | 4 ++-- openpype/settings/defaults/project_settings/maya.json | 3 ++- .../projects_schema/schemas/schema_maya_capture.json | 10 +++++++--- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index aa1e501578..1a62e7dbc3 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -2478,8 +2478,8 @@ def load_capture_preset(data=None): float(value[2]) / 255 ] disp_options[key] = value - else: - disp_options['displayGradient'] = True + elif key == "displayGradient": + disp_options[key] = value options['display_options'] = disp_options diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json index e914eb29f9..fda053e6e6 100644 --- a/openpype/settings/defaults/project_settings/maya.json +++ b/openpype/settings/defaults/project_settings/maya.json @@ -795,6 +795,7 @@ "quality": 95 }, "Display Options": { + "override_display": true, "background": [ 125, 125, @@ -813,7 +814,7 @@ 125, 255 ], - "override_display": true + "displayGradient": true }, "Generic": { "isolate_view": true, diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json index 416e530db2..a4a986bad8 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json @@ -48,7 +48,11 @@ "type": "label", "label": "Display Options" }, - + { + "type": "boolean", + "key": "override_display", + "label": "Override display options" + }, { "type": "color", "key": "background", @@ -66,8 +70,8 @@ }, { "type": "boolean", - "key": "override_display", - "label": "Override display options" + "key": "displayGradient", + "label": "Display background gradient" } ] }, From 18efd5276df132909d8eae592f09cd6d7b011cbb Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Thu, 30 Mar 2023 11:57:36 +0200 Subject: [PATCH 2/8] :art: add camera loader --- .../hosts/maya/plugins/load/load_camera.py | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 openpype/hosts/maya/plugins/load/load_camera.py diff --git a/openpype/hosts/maya/plugins/load/load_camera.py b/openpype/hosts/maya/plugins/load/load_camera.py new file mode 100644 index 0000000000..5e26e8c02f --- /dev/null +++ b/openpype/hosts/maya/plugins/load/load_camera.py @@ -0,0 +1,76 @@ +import openpype.hosts.maya.api.plugin +from openpype.hosts.maya.api.lib import get_container_members + + +class CameraLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): + """Reference Camera""" + + families = ["camera", "camerarig"] + label = "Reference camera" + representations = ["abc", "ma"] + order = -10 + icon = "code-fork" + color = "orange" + + def process_reference(self, context, name, namespace, data): + + import maya.cmds as cmds + # Get family type from the context + + cmds.loadPlugin("AbcImport.mll", quiet=True) + nodes = cmds.file(self.fname, + namespace=namespace, + sharedReferenceFile=False, + groupReference=True, + groupName="{}:{}".format(namespace, name), + reference=True, + returnNewNodes=True) + + cameras = cmds.ls(nodes, type="camera") + + # Check the Maya version, lockTransform has been introduced since + # Maya 2016.5 Ext 2 + version = int(cmds.about(version=True)) + if version >= 2016: + for camera in cameras: + cmds.camera(camera, edit=True, lockTransform=True) + else: + self.log.warning("This version of Maya does not support locking of" + " transforms of cameras.") + + self[:] = nodes + + return nodes + + def update(self, container, representation): + + from maya import cmds + + # Get the modelPanels that used the old camera + members = get_container_members(container) + old_cameras = cmds.ls(members, type="camera", long=True) + update_panels = [] + for panel in cmds.getPanel(type="modelPanel"): + cam = cmds.ls(cmds.modelPanel(panel, query=True, camera=True), + long=True) + + # Often but not always maya returns the transform from the + # modelPanel as opposed to the camera shape, so we convert it + # to explicitly be the camera shape + if cmds.nodeType(cam) != "camera": + cam = cmds.listRelatives(cam, + children=True, + fullPath=True, + type="camera")[0] + if cam in old_cameras: + update_panels.append(panel) + + # Perform regular reference update + super(CameraLoader, self).update(container, representation) + + # Update the modelPanels to contain the new camera + members = get_container_members(container) + new_cameras = cmds.ls(members, type="camera", long=True) + new_camera = new_cameras[0] + for panel in update_panels: + cmds.modelPanel(panel, edit=True, camera=new_camera) From 951f868cef89ad5c778511c4b7f3f95b7fc7ecb4 Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Thu, 30 Mar 2023 15:14:21 +0200 Subject: [PATCH 3/8] :recycle: move logic from camera loader to reference loader --- .../hosts/maya/plugins/load/load_camera.py | 76 ------------------- .../hosts/maya/plugins/load/load_reference.py | 57 +++++++++++++- 2 files changed, 56 insertions(+), 77 deletions(-) delete mode 100644 openpype/hosts/maya/plugins/load/load_camera.py diff --git a/openpype/hosts/maya/plugins/load/load_camera.py b/openpype/hosts/maya/plugins/load/load_camera.py deleted file mode 100644 index 5e26e8c02f..0000000000 --- a/openpype/hosts/maya/plugins/load/load_camera.py +++ /dev/null @@ -1,76 +0,0 @@ -import openpype.hosts.maya.api.plugin -from openpype.hosts.maya.api.lib import get_container_members - - -class CameraLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): - """Reference Camera""" - - families = ["camera", "camerarig"] - label = "Reference camera" - representations = ["abc", "ma"] - order = -10 - icon = "code-fork" - color = "orange" - - def process_reference(self, context, name, namespace, data): - - import maya.cmds as cmds - # Get family type from the context - - cmds.loadPlugin("AbcImport.mll", quiet=True) - nodes = cmds.file(self.fname, - namespace=namespace, - sharedReferenceFile=False, - groupReference=True, - groupName="{}:{}".format(namespace, name), - reference=True, - returnNewNodes=True) - - cameras = cmds.ls(nodes, type="camera") - - # Check the Maya version, lockTransform has been introduced since - # Maya 2016.5 Ext 2 - version = int(cmds.about(version=True)) - if version >= 2016: - for camera in cameras: - cmds.camera(camera, edit=True, lockTransform=True) - else: - self.log.warning("This version of Maya does not support locking of" - " transforms of cameras.") - - self[:] = nodes - - return nodes - - def update(self, container, representation): - - from maya import cmds - - # Get the modelPanels that used the old camera - members = get_container_members(container) - old_cameras = cmds.ls(members, type="camera", long=True) - update_panels = [] - for panel in cmds.getPanel(type="modelPanel"): - cam = cmds.ls(cmds.modelPanel(panel, query=True, camera=True), - long=True) - - # Often but not always maya returns the transform from the - # modelPanel as opposed to the camera shape, so we convert it - # to explicitly be the camera shape - if cmds.nodeType(cam) != "camera": - cam = cmds.listRelatives(cam, - children=True, - fullPath=True, - type="camera")[0] - if cam in old_cameras: - update_panels.append(panel) - - # Perform regular reference update - super(CameraLoader, self).update(container, representation) - - # Update the modelPanels to contain the new camera - members = get_container_members(container) - new_cameras = cmds.ls(members, type="camera", long=True) - new_camera = new_cameras[0] - for panel in update_panels: - cmds.modelPanel(panel, edit=True, camera=new_camera) diff --git a/openpype/hosts/maya/plugins/load/load_reference.py b/openpype/hosts/maya/plugins/load/load_reference.py index d93702a16d..a0345dceb0 100644 --- a/openpype/hosts/maya/plugins/load/load_reference.py +++ b/openpype/hosts/maya/plugins/load/load_reference.py @@ -8,7 +8,10 @@ from openpype.pipeline.create import ( get_legacy_creator_by_name, ) import openpype.hosts.maya.api.plugin -from openpype.hosts.maya.api.lib import maintained_selection +from openpype.hosts.maya.api.lib import ( + maintained_selection, + get_container_members +) class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): @@ -68,6 +71,9 @@ class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): new_nodes = (list(set(nodes) - set(shapes))) + # if there are cameras, try to lock their transforms + self._lock_camera_transforms(new_nodes) + current_namespace = pm.namespaceInfo(currentNamespace=True) if current_namespace != ":": @@ -136,6 +142,11 @@ class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): def switch(self, container, representation): self.update(container, representation) + def update(self, container, representation): + update_panels = self._update_cameras(container) + super(ReferenceLoader, self).update(container, representation) + self._update_model_panels(container, update_panels) + def _post_process_rig(self, name, namespace, context, options): output = next((node for node in self if @@ -168,3 +179,47 @@ class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): options={"useSelection": True}, data={"dependencies": dependency} ) + + def _lock_camera_transforms(self, nodes): + cameras = cmds.ls(nodes, type="camera") + + # Check the Maya version, lockTransform has been introduced since + # Maya 2016.5 Ext 2 + version = int(cmds.about(version=True)) + if version >= 2016: + for camera in cameras: + cmds.camera(camera, edit=True, lockTransform=True) + else: + self.log.warning("This version of Maya does not support locking of" + " transforms of cameras.") + + @staticmethod + def _update_cameras(container): + # Get the modelPanels that used the old camera + members = get_container_members(container) + old_cameras = cmds.ls(members, type="camera", long=True) + update_panels = [] + for panel in cmds.getPanel(type="modelPanel"): + cam = cmds.ls(cmds.modelPanel(panel, query=True, camera=True), + long=True) + + # Often but not always maya returns the transform from the + # modelPanel as opposed to the camera shape, so we convert it + # to explicitly be the camera shape + if cmds.nodeType(cam) != "camera": + cam = cmds.listRelatives(cam, + children=True, + fullPath=True, + type="camera")[0] + if cam in old_cameras: + update_panels.append(panel) + return update_panels + + @staticmethod + def _update_model_panels(container, update_panels): + # Update the modelPanels to contain the new camera + members = get_container_members(container) + new_cameras = cmds.ls(members, type="camera", long=True) + new_camera = new_cameras[0] + for panel in update_panels: + cmds.modelPanel(panel, edit=True, camera=new_camera) From e62b0e48cb5c984595b36f20fb577cc84d5e1998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= <33513211+antirotor@users.noreply.github.com> Date: Thu, 30 Mar 2023 15:50:12 +0200 Subject: [PATCH 4/8] Update openpype/hosts/maya/plugins/load/load_reference.py Co-authored-by: Roy Nieterau --- openpype/hosts/maya/plugins/load/load_reference.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openpype/hosts/maya/plugins/load/load_reference.py b/openpype/hosts/maya/plugins/load/load_reference.py index a0345dceb0..60cae131bc 100644 --- a/openpype/hosts/maya/plugins/load/load_reference.py +++ b/openpype/hosts/maya/plugins/load/load_reference.py @@ -218,6 +218,8 @@ class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): @staticmethod def _update_model_panels(container, update_panels): # Update the modelPanels to contain the new camera + if not update_panels: + return members = get_container_members(container) new_cameras = cmds.ls(members, type="camera", long=True) new_camera = new_cameras[0] From 52b45f0384ea06be303f6e9392101f41c1b470d3 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 30 Mar 2023 16:36:44 +0200 Subject: [PATCH 5/8] Correctly preserve cameras in modelPanels with multiple cameras in a mayaScene --- .../hosts/maya/plugins/load/load_reference.py | 114 ++++++++++++------ 1 file changed, 78 insertions(+), 36 deletions(-) diff --git a/openpype/hosts/maya/plugins/load/load_reference.py b/openpype/hosts/maya/plugins/load/load_reference.py index 60cae131bc..235bee8ae1 100644 --- a/openpype/hosts/maya/plugins/load/load_reference.py +++ b/openpype/hosts/maya/plugins/load/load_reference.py @@ -1,4 +1,6 @@ import os +import difflib +import contextlib from maya import cmds from openpype.settings import get_project_settings @@ -14,6 +16,78 @@ from openpype.hosts.maya.api.lib import ( ) +@contextlib.contextmanager +def preserve_modelpanel_cameras(container, log=None): + """Preserve camera members of container in the modelPanels. + + This is used to ensure a camera remains in the modelPanels after updating + to a new version. + + """ + + # Get the modelPanels that used the old camera + members = get_container_members(container) + old_cameras = set(cmds.ls(members, type="camera", long=True)) + if not old_cameras: + # No need to manage anything + yield + return + + panel_cameras = {} + for panel in cmds.getPanel(type="modelPanel"): + cam = cmds.ls(cmds.modelPanel(panel, query=True, camera=True), + long=True) + + # Often but not always maya returns the transform from the + # modelPanel as opposed to the camera shape, so we convert it + # to explicitly be the camera shape + if cmds.nodeType(cam) != "camera": + cam = cmds.listRelatives(cam, + children=True, + fullPath=True, + type="camera")[0] + if cam in old_cameras: + panel_cameras[panel] = cam + + if not panel_cameras: + # No need to manage anything + yield + return + + try: + yield + finally: + new_members = get_container_members(container) + new_cameras = set(cmds.ls(new_members, type="camera", long=True)) + if not new_cameras: + return + + for panel, cam_name in panel_cameras.items(): + new_camera = None + if cam_name in new_cameras: + new_camera = cam_name + elif len(new_cameras) == 1: + new_camera = next(iter(new_cameras)) + else: + # Multiple cameras in the updated container but not an exact + # match detected by name. Find the closest match + matches = difflib.get_close_matches(word=cam_name, + possibilities=new_cameras, + n=1) + if matches: + new_camera = matches[0] # best match + if log: + log.info("Camera in '{}' restored with " + "closest match camera: {} (before: {})" + .format(panel, new_camera, cam_name)) + + if not new_camera: + # Unable to find the camera to re-apply in the modelpanel + continue + + cmds.modelPanel(panel, edit=True, camera=new_camera) + + class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): """Reference file""" @@ -143,9 +217,8 @@ class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): self.update(container, representation) def update(self, container, representation): - update_panels = self._update_cameras(container) - super(ReferenceLoader, self).update(container, representation) - self._update_model_panels(container, update_panels) + with preserve_modelpanel_cameras(container, log=self.log): + super(ReferenceLoader, self).update(container, representation) def _post_process_rig(self, name, namespace, context, options): @@ -182,6 +255,8 @@ class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): def _lock_camera_transforms(self, nodes): cameras = cmds.ls(nodes, type="camera") + if not cameras: + return # Check the Maya version, lockTransform has been introduced since # Maya 2016.5 Ext 2 @@ -192,36 +267,3 @@ class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): else: self.log.warning("This version of Maya does not support locking of" " transforms of cameras.") - - @staticmethod - def _update_cameras(container): - # Get the modelPanels that used the old camera - members = get_container_members(container) - old_cameras = cmds.ls(members, type="camera", long=True) - update_panels = [] - for panel in cmds.getPanel(type="modelPanel"): - cam = cmds.ls(cmds.modelPanel(panel, query=True, camera=True), - long=True) - - # Often but not always maya returns the transform from the - # modelPanel as opposed to the camera shape, so we convert it - # to explicitly be the camera shape - if cmds.nodeType(cam) != "camera": - cam = cmds.listRelatives(cam, - children=True, - fullPath=True, - type="camera")[0] - if cam in old_cameras: - update_panels.append(panel) - return update_panels - - @staticmethod - def _update_model_panels(container, update_panels): - # Update the modelPanels to contain the new camera - if not update_panels: - return - members = get_container_members(container) - new_cameras = cmds.ls(members, type="camera", long=True) - new_camera = new_cameras[0] - for panel in update_panels: - cmds.modelPanel(panel, edit=True, camera=new_camera) From 945d31876685fbe1264732748e8f9fbeed8d8d29 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 30 Mar 2023 16:38:45 +0200 Subject: [PATCH 6/8] Also lock new cameras on update --- openpype/hosts/maya/plugins/load/load_reference.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openpype/hosts/maya/plugins/load/load_reference.py b/openpype/hosts/maya/plugins/load/load_reference.py index 235bee8ae1..82c15ab899 100644 --- a/openpype/hosts/maya/plugins/load/load_reference.py +++ b/openpype/hosts/maya/plugins/load/load_reference.py @@ -220,6 +220,11 @@ class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): with preserve_modelpanel_cameras(container, log=self.log): super(ReferenceLoader, self).update(container, representation) + # We also want to lock camera transforms on any new cameras in the + # reference or for a camera which might have changed names. + members = get_container_members(container) + self._lock_camera_transforms(members) + def _post_process_rig(self, name, namespace, context, options): output = next((node for node in self if From 91740ea3561ce4f240710ba0b0dea9e1d5666ee4 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 30 Mar 2023 17:50:09 +0200 Subject: [PATCH 7/8] Harmony: render what is in timeline in Harmony locally (#4741) * OP-5466 - render what is in timeline in Harmony locally * OP-5466 - validate according to scene start in timeline scene start is denoted by small black triangle in the left on the timeline * OP-5466 - do not force settings from DB Added separate menu item to set frames and resolution from DB to scene. * OP-5466 - added logging details to validator --- openpype/hosts/harmony/api/TB_sceneOpened.js | 19 ++++++++++++++ openpype/hosts/harmony/api/pipeline.py | 2 +- .../harmony/plugins/publish/extract_render.py | 13 +++++++--- .../publish/validate_scene_settings.py | 25 ++++++++++++++----- 4 files changed, 48 insertions(+), 11 deletions(-) diff --git a/openpype/hosts/harmony/api/TB_sceneOpened.js b/openpype/hosts/harmony/api/TB_sceneOpened.js index e7cd555332..fe5e6569a8 100644 --- a/openpype/hosts/harmony/api/TB_sceneOpened.js +++ b/openpype/hosts/harmony/api/TB_sceneOpened.js @@ -476,6 +476,25 @@ function start() { action.triggered.connect(self.onSubsetManage); } + /** + * Set scene settings from DB to the scene + */ + self.onSetSceneSettings = function() { + app.avalonClient.send( + { + "module": "openpype.hosts.harmony.api", + "method": "ensure_scene_settings", + "args": [] + }, + false + ); + }; + // add Set Scene Settings + if (app.avalonMenu == null) { + action = menu.addAction('Set Scene Settings...'); + action.triggered.connect(self.onSetSceneSettings); + } + /** * Show Experimental dialog */ diff --git a/openpype/hosts/harmony/api/pipeline.py b/openpype/hosts/harmony/api/pipeline.py index 686770b64e..285ee806a1 100644 --- a/openpype/hosts/harmony/api/pipeline.py +++ b/openpype/hosts/harmony/api/pipeline.py @@ -142,7 +142,7 @@ def application_launch(event): harmony.send({"script": script}) inject_avalon_js() - ensure_scene_settings() + # ensure_scene_settings() check_inventory() diff --git a/openpype/hosts/harmony/plugins/publish/extract_render.py b/openpype/hosts/harmony/plugins/publish/extract_render.py index c29864bb28..38b09902c1 100644 --- a/openpype/hosts/harmony/plugins/publish/extract_render.py +++ b/openpype/hosts/harmony/plugins/publish/extract_render.py @@ -25,8 +25,9 @@ class ExtractRender(pyblish.api.InstancePlugin): application_path = instance.context.data.get("applicationPath") scene_path = instance.context.data.get("scenePath") frame_rate = instance.context.data.get("frameRate") - frame_start = instance.context.data.get("frameStart") - frame_end = instance.context.data.get("frameEnd") + # real value from timeline + frame_start = instance.context.data.get("frameStartHandle") + frame_end = instance.context.data.get("frameEndHandle") audio_path = instance.context.data.get("audioPath") if audio_path and os.path.exists(audio_path): @@ -55,9 +56,13 @@ class ExtractRender(pyblish.api.InstancePlugin): # Execute rendering. Ignoring error cause Harmony returns error code # always. - self.log.info(f"running [ {application_path} -batch {scene_path}") + + args = [application_path, "-batch", + "-frames", str(frame_start), str(frame_end), + "-scene", scene_path] + self.log.info(f"running [ {application_path} {' '.join(args)}") proc = subprocess.Popen( - [application_path, "-batch", scene_path], + args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE diff --git a/openpype/hosts/harmony/plugins/publish/validate_scene_settings.py b/openpype/hosts/harmony/plugins/publish/validate_scene_settings.py index 936533abd6..6e4c6955e4 100644 --- a/openpype/hosts/harmony/plugins/publish/validate_scene_settings.py +++ b/openpype/hosts/harmony/plugins/publish/validate_scene_settings.py @@ -60,7 +60,8 @@ class ValidateSceneSettings(pyblish.api.InstancePlugin): # which is available on 'context.data["assetEntity"]' # - the same approach can be used in 'ValidateSceneSettingsRepair' expected_settings = harmony.get_asset_settings() - self.log.info("scene settings from DB:".format(expected_settings)) + self.log.info("scene settings from DB:{}".format(expected_settings)) + expected_settings.pop("entityType") # not useful for the validation expected_settings = _update_frames(dict.copy(expected_settings)) expected_settings["frameEndHandle"] = expected_settings["frameEnd"] +\ @@ -68,21 +69,32 @@ class ValidateSceneSettings(pyblish.api.InstancePlugin): if (any(re.search(pattern, os.getenv('AVALON_TASK')) for pattern in self.skip_resolution_check)): + self.log.info("Skipping resolution check because of " + "task name and pattern {}".format( + self.skip_resolution_check)) expected_settings.pop("resolutionWidth") expected_settings.pop("resolutionHeight") - entity_type = expected_settings.get("entityType") - if (any(re.search(pattern, entity_type) + if (any(re.search(pattern, os.getenv('AVALON_TASK')) for pattern in self.skip_timelines_check)): + self.log.info("Skipping frames check because of " + "task name and pattern {}".format( + self.skip_timelines_check)) expected_settings.pop('frameStart', None) expected_settings.pop('frameEnd', None) - - expected_settings.pop("entityType") # not useful after the check + expected_settings.pop('frameStartHandle', None) + expected_settings.pop('frameEndHandle', None) asset_name = instance.context.data['anatomyData']['asset'] if any(re.search(pattern, asset_name) for pattern in self.frame_check_filter): - expected_settings.pop("frameEnd") + self.log.info("Skipping frames check because of " + "task name and pattern {}".format( + self.frame_check_filter)) + expected_settings.pop('frameStart', None) + expected_settings.pop('frameEnd', None) + expected_settings.pop('frameStartHandle', None) + expected_settings.pop('frameEndHandle', None) # handle case where ftrack uses only two decimal places # 23.976023976023978 vs. 23.98 @@ -99,6 +111,7 @@ class ValidateSceneSettings(pyblish.api.InstancePlugin): "frameEnd": instance.context.data["frameEnd"], "handleStart": instance.context.data.get("handleStart"), "handleEnd": instance.context.data.get("handleEnd"), + "frameStartHandle": instance.context.data.get("frameStartHandle"), "frameEndHandle": instance.context.data.get("frameEndHandle"), "resolutionWidth": instance.context.data.get("resolutionWidth"), "resolutionHeight": instance.context.data.get("resolutionHeight"), From d2e48426a6ec43fcdf62a42e9ffa44f4e72e77c4 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 30 Mar 2023 19:04:44 +0200 Subject: [PATCH 8/8] add all sites of previous files to new files (#4737) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jakub Ježek --- .../plugins/publish/integrate_hero_version.py | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/openpype/plugins/publish/integrate_hero_version.py b/openpype/plugins/publish/integrate_hero_version.py index e796f7b376..80141e88fe 100644 --- a/openpype/plugins/publish/integrate_hero_version.py +++ b/openpype/plugins/publish/integrate_hero_version.py @@ -388,22 +388,27 @@ class IntegrateHeroVersion(pyblish.api.InstancePlugin): old_repre, repre) # Keep previously synchronized sites up-to-date - # by comparing old and new sites and adding old sites - # if missing in new ones - old_repre_files_sites = [ - f.get("sites", []) for f in old_repre.get("files", []) - ] - for i, file in enumerate(repre.get("files", [])): - repre_sites_names = { - s["name"] for s in file.get("sites", []) + # by comparing old and new sites and adding old sites + # if missing in new ones + # Prepare all sites from all files in old representation + old_site_names = set() + for file_info in old_repre.get("files", []): + old_site_names |= { + site["name"] + for site in file_info["sites"] } - for site in old_repre_files_sites[i]: - if site["name"] not in repre_sites_names: - # Pop the date to tag for sync - site.pop("created_dt", None) - file["sites"].append(site) - update_data["files"][i] = file + for file_info in update_data.get("files", []): + file_info.setdefault("sites", []) + file_info_site_names = { + site["name"] + for site in file_info["sites"] + } + for site_name in old_site_names: + if site_name not in file_info_site_names: + file_info["sites"].append({ + "name": site_name + }) op_session.update_entity( project_name,