From 5bffaa730efce006283b66462d52a543713fcce0 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 11 Jun 2024 17:27:25 +0800 Subject: [PATCH 01/15] fix the incorrect fps value when loading point cache --- server_addon/max/client/ayon_max/api/lib.py | 17 ++++++++++++----- .../ayon_max/plugins/load/load_pointcache.py | 4 +++- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/server_addon/max/client/ayon_max/api/lib.py b/server_addon/max/client/ayon_max/api/lib.py index eb22dbafd2..8fce21311a 100644 --- a/server_addon/max/client/ayon_max/api/lib.py +++ b/server_addon/max/client/ayon_max/api/lib.py @@ -272,10 +272,8 @@ def reset_frame_range(fps: bool = True): scene frame rate in frames-per-second. """ if fps: - task_entity = get_current_task_entity() - task_attributes = task_entity["attrib"] - fps_number = float(task_attributes["fps"]) - rt.frameRate = fps_number + set_fps() + frame_range = get_frame_range() set_timeline( @@ -284,6 +282,15 @@ def reset_frame_range(fps: bool = True): frame_range["frameStartHandle"], frame_range["frameEndHandle"]) +def set_fps(): + """Set fps to current folder + """ + task_entity = get_current_task_entity() + task_attributes = task_entity["attrib"] + fps_number = float(task_attributes["fps"]) + rt.frameRate = fps_number + + def reset_unit_scale(): """Apply the unit scale setting to 3dsMax """ @@ -358,7 +365,7 @@ def is_headless(): def set_timeline(frameStart, frameEnd): """Set frame range for timeline editor in Max """ - rt.animationRange = rt.interval(frameStart, frameEnd) + rt.animationRange = rt.interval(int(frameStart), int(frameEnd)) return rt.animationRange diff --git a/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py b/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py index d7def3d0ba..7f2d4c05f8 100644 --- a/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py +++ b/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py @@ -7,7 +7,7 @@ Because of limited api, alembics can be only loaded, but not easily updated. import os from ayon_core.pipeline import load, get_representation_path from ayon_max.api import lib, maintained_selection -from ayon_max.api.lib import unique_namespace +from ayon_max.api.lib import unique_namespace, set_fps from ayon_max.api.pipeline import ( containerise, get_previous_loaded_object, @@ -31,6 +31,8 @@ class AbcLoader(load.LoaderPlugin): file_path = self.filepath_from_context(context) file_path = os.path.normpath(file_path) + set_fps() + abc_before = { c for c in rt.rootNode.Children From e3f8ff9de35ad5ec37b6981c2f7fd3710acd6356 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 11 Jun 2024 19:58:08 +0800 Subject: [PATCH 02/15] set scene fps during loading point cache context --- server_addon/max/client/ayon_max/api/lib.py | 55 ++++++++++-- .../ayon_max/plugins/load/load_pointcache.py | 85 ++++++++++--------- 2 files changed, 92 insertions(+), 48 deletions(-) diff --git a/server_addon/max/client/ayon_max/api/lib.py b/server_addon/max/client/ayon_max/api/lib.py index 8fce21311a..eb29af5ec5 100644 --- a/server_addon/max/client/ayon_max/api/lib.py +++ b/server_addon/max/client/ayon_max/api/lib.py @@ -7,8 +7,11 @@ from typing import Any, Dict, Union import six +import ayon_api + from ayon_core.pipeline import ( get_current_project_name, + get_current_folder_path, colorspace ) from ayon_core.settings import get_project_settings @@ -272,7 +275,7 @@ def reset_frame_range(fps: bool = True): scene frame rate in frames-per-second. """ if fps: - set_fps() + rt.frameRate = float(get_fps_for_current_context()) frame_range = get_frame_range() @@ -282,13 +285,37 @@ def reset_frame_range(fps: bool = True): frame_range["frameStartHandle"], frame_range["frameEndHandle"]) -def set_fps(): - """Set fps to current folder +def get_fps_for_current_context(): + """Get fps that should be set for current context. + + Todos: + - Skip project value. + - Merge logic with 'get_frame_range' and 'reset_scene_resolution' -> + all the values in the functions can be collected at one place as + they have same requirements. + + Returns: + Union[int, float]: FPS value. """ - task_entity = get_current_task_entity() - task_attributes = task_entity["attrib"] - fps_number = float(task_attributes["fps"]) - rt.frameRate = fps_number + task_entity = get_current_task_entity(fields={"attrib"}) + fps = task_entity.get("attrib", {}).get("fps") + if not fps: + project_name = get_current_project_name() + folder_path = get_current_folder_path() + folder_entity = ayon_api.get_folder_by_path( + project_name, folder_path, fields={"attrib.fps"} + ) or {} + + fps = folder_entity.get("attrib", {}).get("fps") + if not fps: + project_entity = ayon_api.get_project( + project_name, fields=["attrib.fps"] + ) or {} + fps = project_entity.get("attrib", {}).get("fps") + + if not fps: + fps = 25 + return fps def reset_unit_scale(): @@ -580,3 +607,17 @@ def suspended_refresh(): finally: rt.enableSceneRedraw() rt.resumeEditing() + + +@contextlib.contextmanager +def scene_fps(fps): + """Set scene fps during context + + Args: + fps (float): fps value + """ + try: + rt.frameRate = float(get_fps_for_current_context()) + yield + finally: + rt.frameRate = fps diff --git a/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py b/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py index 7f2d4c05f8..f862f2ed67 100644 --- a/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py +++ b/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py @@ -7,7 +7,7 @@ Because of limited api, alembics can be only loaded, but not easily updated. import os from ayon_core.pipeline import load, get_representation_path from ayon_max.api import lib, maintained_selection -from ayon_max.api.lib import unique_namespace, set_fps +from ayon_max.api.lib import unique_namespace, scene_fps from ayon_max.api.pipeline import ( containerise, get_previous_loaded_object, @@ -31,47 +31,50 @@ class AbcLoader(load.LoaderPlugin): file_path = self.filepath_from_context(context) file_path = os.path.normpath(file_path) - set_fps() - - abc_before = { - c - for c in rt.rootNode.Children - if rt.classOf(c) == rt.AlembicContainer - } - - rt.AlembicImport.ImportToRoot = False - rt.importFile(file_path, rt.name("noPrompt"), using=rt.AlembicImport) - - abc_after = { - c - for c in rt.rootNode.Children - if rt.classOf(c) == rt.AlembicContainer - } - - # This should yield new AlembicContainer node - abc_containers = abc_after.difference(abc_before) - - if len(abc_containers) != 1: - self.log.error("Something failed when loading.") - - abc_container = abc_containers.pop() - selections = rt.GetCurrentSelection() - for abc in selections: - for cam_shape in abc.Children: - cam_shape.playbackType = 0 - - namespace = unique_namespace( - name + "_", - suffix="_", - ) abc_objects = [] - for abc_object in abc_container.Children: - abc_object.name = f"{namespace}:{abc_object.name}" - abc_objects.append(abc_object) - # rename the abc container with namespace - abc_container_name = f"{namespace}:{name}" - abc_container.name = abc_container_name - abc_objects.append(abc_container) + product_fps = float(context["version"]["attrib"].get("fps")) + if product_fps is None: + # Just stick to current scene FPS + product_fps = float(rt.frameRate) + with scene_fps(product_fps): + abc_before = { + c + for c in rt.rootNode.Children + if rt.classOf(c) == rt.AlembicContainer + } + + rt.AlembicImport.ImportToRoot = False + rt.importFile(file_path, rt.name("noPrompt"), using=rt.AlembicImport) + + abc_after = { + c + for c in rt.rootNode.Children + if rt.classOf(c) == rt.AlembicContainer + } + + # This should yield new AlembicContainer node + abc_containers = abc_after.difference(abc_before) + + if len(abc_containers) != 1: + self.log.error("Something failed when loading.") + + abc_container = abc_containers.pop() + selections = rt.GetCurrentSelection() + for abc in selections: + for cam_shape in abc.Children: + cam_shape.playbackType = 0 + + namespace = unique_namespace( + name + "_", + suffix="_", + ) + for abc_object in abc_container.Children: + abc_object.name = f"{namespace}:{abc_object.name}" + abc_objects.append(abc_object) + # rename the abc container with namespace + abc_container_name = f"{namespace}:{name}" + abc_container.name = abc_container_name + abc_objects.append(abc_container) return containerise( name, abc_objects, context, From d7aa02c3e681474d16a1f245a0116c7a83706042 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 11 Jun 2024 20:11:06 +0800 Subject: [PATCH 03/15] code tweaks - big roy's comment --- .../ayon_max/plugins/load/load_pointcache.py | 70 ++++++++++--------- 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py b/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py index f862f2ed67..498c5c6ce7 100644 --- a/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py +++ b/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py @@ -31,50 +31,52 @@ class AbcLoader(load.LoaderPlugin): file_path = self.filepath_from_context(context) file_path = os.path.normpath(file_path) - abc_objects = [] + abc_before = { + c + for c in rt.rootNode.Children + if rt.classOf(c) == rt.AlembicContainer + } + + rt.AlembicImport.ImportToRoot = False product_fps = float(context["version"]["attrib"].get("fps")) if product_fps is None: # Just stick to current scene FPS product_fps = float(rt.frameRate) with scene_fps(product_fps): - abc_before = { - c - for c in rt.rootNode.Children - if rt.classOf(c) == rt.AlembicContainer - } + rt.importFile(file_path, + rt.name("noPrompt"), + using=rt.AlembicImport) - rt.AlembicImport.ImportToRoot = False - rt.importFile(file_path, rt.name("noPrompt"), using=rt.AlembicImport) + abc_after = { + c + for c in rt.rootNode.Children + if rt.classOf(c) == rt.AlembicContainer + } - abc_after = { - c - for c in rt.rootNode.Children - if rt.classOf(c) == rt.AlembicContainer - } + # This should yield new AlembicContainer node + abc_containers = abc_after.difference(abc_before) - # This should yield new AlembicContainer node - abc_containers = abc_after.difference(abc_before) + if len(abc_containers) != 1: + self.log.error("Something failed when loading.") - if len(abc_containers) != 1: - self.log.error("Something failed when loading.") + abc_container = abc_containers.pop() + selections = rt.GetCurrentSelection() + for abc in selections: + for cam_shape in abc.Children: + cam_shape.playbackType = 0 - abc_container = abc_containers.pop() - selections = rt.GetCurrentSelection() - for abc in selections: - for cam_shape in abc.Children: - cam_shape.playbackType = 0 - - namespace = unique_namespace( - name + "_", - suffix="_", - ) - for abc_object in abc_container.Children: - abc_object.name = f"{namespace}:{abc_object.name}" - abc_objects.append(abc_object) - # rename the abc container with namespace - abc_container_name = f"{namespace}:{name}" - abc_container.name = abc_container_name - abc_objects.append(abc_container) + namespace = unique_namespace( + name + "_", + suffix="_", + ) + abc_objects = [] + for abc_object in abc_container.Children: + abc_object.name = f"{namespace}:{abc_object.name}" + abc_objects.append(abc_object) + # rename the abc container with namespace + abc_container_name = f"{namespace}:{name}" + abc_container.name = abc_container_name + abc_objects.append(abc_container) return containerise( name, abc_objects, context, From 253ae11736fe75d5ae4ccb01a86605a35db2cea7 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 11 Jun 2024 20:31:44 +0800 Subject: [PATCH 04/15] code tweaks - big roy's comment --- server_addon/max/client/ayon_max/api/lib.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/server_addon/max/client/ayon_max/api/lib.py b/server_addon/max/client/ayon_max/api/lib.py index eb29af5ec5..03310ff16f 100644 --- a/server_addon/max/client/ayon_max/api/lib.py +++ b/server_addon/max/client/ayon_max/api/lib.py @@ -616,8 +616,9 @@ def scene_fps(fps): Args: fps (float): fps value """ + fps_before = rt.frameRate try: - rt.frameRate = float(get_fps_for_current_context()) + rt.frameRate = float(fps) yield finally: - rt.frameRate = fps + rt.frameRate = fps_before From 92d49139a5c565ffa1f17314ff13ab0e5fbf7405 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 11 Jun 2024 20:51:13 +0800 Subject: [PATCH 05/15] make sure the timeline and custom frame range matched to the export --- server_addon/max/client/ayon_max/api/lib.py | 15 --------------- .../ayon_max/plugins/load/load_pointcache.py | 9 ++++----- 2 files changed, 4 insertions(+), 20 deletions(-) diff --git a/server_addon/max/client/ayon_max/api/lib.py b/server_addon/max/client/ayon_max/api/lib.py index 03310ff16f..7c140be72e 100644 --- a/server_addon/max/client/ayon_max/api/lib.py +++ b/server_addon/max/client/ayon_max/api/lib.py @@ -607,18 +607,3 @@ def suspended_refresh(): finally: rt.enableSceneRedraw() rt.resumeEditing() - - -@contextlib.contextmanager -def scene_fps(fps): - """Set scene fps during context - - Args: - fps (float): fps value - """ - fps_before = rt.frameRate - try: - rt.frameRate = float(fps) - yield - finally: - rt.frameRate = fps_before diff --git a/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py b/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py index 498c5c6ce7..3eb4ba3323 100644 --- a/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py +++ b/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py @@ -7,7 +7,7 @@ Because of limited api, alembics can be only loaded, but not easily updated. import os from ayon_core.pipeline import load, get_representation_path from ayon_max.api import lib, maintained_selection -from ayon_max.api.lib import unique_namespace, scene_fps +from ayon_max.api.lib import unique_namespace from ayon_max.api.pipeline import ( containerise, get_previous_loaded_object, @@ -42,10 +42,9 @@ class AbcLoader(load.LoaderPlugin): if product_fps is None: # Just stick to current scene FPS product_fps = float(rt.frameRate) - with scene_fps(product_fps): - rt.importFile(file_path, - rt.name("noPrompt"), - using=rt.AlembicImport) + # TODO: remove after the post-system fps setup + rt.frameRange = product_fps + rt.importFile(file_path, rt.name("noPrompt"), using=rt.AlembicImport) abc_after = { c From 728e3d6a7301b046a9e105b18f3f9496c46dad92 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 12 Jun 2024 18:50:20 +0800 Subject: [PATCH 06/15] update get_fps_for_current_context() function --- server_addon/max/client/ayon_max/api/lib.py | 19 +------------------ .../ayon_max/plugins/load/load_pointcache.py | 4 +++- 2 files changed, 4 insertions(+), 19 deletions(-) diff --git a/server_addon/max/client/ayon_max/api/lib.py b/server_addon/max/client/ayon_max/api/lib.py index 7c140be72e..4b5b07880b 100644 --- a/server_addon/max/client/ayon_max/api/lib.py +++ b/server_addon/max/client/ayon_max/api/lib.py @@ -298,24 +298,7 @@ def get_fps_for_current_context(): Union[int, float]: FPS value. """ task_entity = get_current_task_entity(fields={"attrib"}) - fps = task_entity.get("attrib", {}).get("fps") - if not fps: - project_name = get_current_project_name() - folder_path = get_current_folder_path() - folder_entity = ayon_api.get_folder_by_path( - project_name, folder_path, fields={"attrib.fps"} - ) or {} - - fps = folder_entity.get("attrib", {}).get("fps") - if not fps: - project_entity = ayon_api.get_project( - project_name, fields=["attrib.fps"] - ) or {} - fps = project_entity.get("attrib", {}).get("fps") - - if not fps: - fps = 25 - return fps + return task_entity["attrib"]["fps"] def reset_unit_scale(): diff --git a/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py b/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py index 3eb4ba3323..8ab25f2eeb 100644 --- a/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py +++ b/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py @@ -7,7 +7,7 @@ Because of limited api, alembics can be only loaded, but not easily updated. import os from ayon_core.pipeline import load, get_representation_path from ayon_max.api import lib, maintained_selection -from ayon_max.api.lib import unique_namespace +from ayon_max.api.lib import unique_namespace, get_fps_for_current_context from ayon_max.api.pipeline import ( containerise, get_previous_loaded_object, @@ -31,6 +31,8 @@ class AbcLoader(load.LoaderPlugin): file_path = self.filepath_from_context(context) file_path = os.path.normpath(file_path) + rt.frameRate = get_fps_for_current_context() + abc_before = { c for c in rt.rootNode.Children From 80293ae26442a84692ed6f48b62f530dbbc7cc43 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 12 Jun 2024 18:55:08 +0800 Subject: [PATCH 07/15] ruff cosmetic fix --- server_addon/max/client/ayon_max/api/lib.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/server_addon/max/client/ayon_max/api/lib.py b/server_addon/max/client/ayon_max/api/lib.py index 4b5b07880b..7acc18196f 100644 --- a/server_addon/max/client/ayon_max/api/lib.py +++ b/server_addon/max/client/ayon_max/api/lib.py @@ -7,11 +7,8 @@ from typing import Any, Dict, Union import six -import ayon_api - from ayon_core.pipeline import ( get_current_project_name, - get_current_folder_path, colorspace ) from ayon_core.settings import get_project_settings From 8bff418a0937979c20442cb57ee5fa3f82a2c822 Mon Sep 17 00:00:00 2001 From: Kayla Man <64118225+moonyuet@users.noreply.github.com> Date: Wed, 12 Jun 2024 19:21:39 +0800 Subject: [PATCH 08/15] Update server_addon/max/client/ayon_max/plugins/load/load_pointcache.py Co-authored-by: Roy Nieterau --- server_addon/max/client/ayon_max/plugins/load/load_pointcache.py | 1 - 1 file changed, 1 deletion(-) diff --git a/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py b/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py index 8ab25f2eeb..cb5aaca2fd 100644 --- a/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py +++ b/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py @@ -31,7 +31,6 @@ class AbcLoader(load.LoaderPlugin): file_path = self.filepath_from_context(context) file_path = os.path.normpath(file_path) - rt.frameRate = get_fps_for_current_context() abc_before = { c From 6e6d3c02f603331560586430b4b180e3bb46b8f3 Mon Sep 17 00:00:00 2001 From: Kayla Man <64118225+moonyuet@users.noreply.github.com> Date: Wed, 12 Jun 2024 19:22:54 +0800 Subject: [PATCH 09/15] Update server_addon/max/client/ayon_max/plugins/load/load_pointcache.py Co-authored-by: Roy Nieterau --- server_addon/max/client/ayon_max/plugins/load/load_pointcache.py | 1 - 1 file changed, 1 deletion(-) diff --git a/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py b/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py index cb5aaca2fd..cb1ffaa430 100644 --- a/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py +++ b/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py @@ -31,7 +31,6 @@ class AbcLoader(load.LoaderPlugin): file_path = self.filepath_from_context(context) file_path = os.path.normpath(file_path) - abc_before = { c for c in rt.rootNode.Children From e8107e2b971142626ebaf3ddc047a7f67db0094a Mon Sep 17 00:00:00 2001 From: Kayla Man <64118225+moonyuet@users.noreply.github.com> Date: Wed, 12 Jun 2024 19:23:01 +0800 Subject: [PATCH 10/15] Update server_addon/max/client/ayon_max/plugins/load/load_pointcache.py Co-authored-by: Roy Nieterau --- .../max/client/ayon_max/plugins/load/load_pointcache.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py b/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py index cb1ffaa430..3eb4ba3323 100644 --- a/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py +++ b/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py @@ -7,7 +7,7 @@ Because of limited api, alembics can be only loaded, but not easily updated. import os from ayon_core.pipeline import load, get_representation_path from ayon_max.api import lib, maintained_selection -from ayon_max.api.lib import unique_namespace, get_fps_for_current_context +from ayon_max.api.lib import unique_namespace from ayon_max.api.pipeline import ( containerise, get_previous_loaded_object, From 0f350d3704f2aa830186445bcff5531d471d7aab Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Wed, 12 Jun 2024 19:01:23 +0200 Subject: [PATCH 11/15] try to auto-fix shell true --- client/ayon_core/scripts/otio_burnin.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/scripts/otio_burnin.py b/client/ayon_core/scripts/otio_burnin.py index f12d298ac6..6b132b9a6a 100644 --- a/client/ayon_core/scripts/otio_burnin.py +++ b/client/ayon_core/scripts/otio_burnin.py @@ -14,9 +14,10 @@ from ayon_core.lib import ( convert_ffprobe_fps_value, ) +FFMPEG_EXE_COMMAND = subprocess.list2cmdline(get_ffmpeg_tool_args("ffmpeg")) FFMPEG = ( '{}%(input_args)s -i "%(input)s" %(filters)s %(args)s%(output)s' -).format(subprocess.list2cmdline(get_ffmpeg_tool_args("ffmpeg"))) +).format(FFMPEG_EXE_COMMAND) DRAWTEXT = ( "drawtext@'%(label)s'=fontfile='%(font)s':text=\\'%(text)s\\':" @@ -482,10 +483,19 @@ class ModifiedBurnins(ffmpeg_burnins.Burnins): ) print("Launching command: {}".format(command)) + use_shell = True + try: + test_proc = subprocess.Popen( + f"{FFMPEG_EXE_COMMAND} --help", shell=True + ) + test_proc.wait() + except BaseException: + use_shell = False + kwargs = { "stdout": subprocess.PIPE, "stderr": subprocess.PIPE, - "shell": True, + "shell": use_shell, } proc = subprocess.Popen(command, **kwargs) From edd19c313585b48b975435b67e54e6d939359b62 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 13 Jun 2024 14:25:57 +0800 Subject: [PATCH 12/15] reset frame range & frame rate for the correct frame range & fps value --- .../client/ayon_max/plugins/load/load_pointcache.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py b/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py index 3eb4ba3323..87ea5c75bc 100644 --- a/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py +++ b/server_addon/max/client/ayon_max/plugins/load/load_pointcache.py @@ -7,7 +7,7 @@ Because of limited api, alembics can be only loaded, but not easily updated. import os from ayon_core.pipeline import load, get_representation_path from ayon_max.api import lib, maintained_selection -from ayon_max.api.lib import unique_namespace +from ayon_max.api.lib import unique_namespace, reset_frame_range from ayon_max.api.pipeline import ( containerise, get_previous_loaded_object, @@ -38,12 +38,9 @@ class AbcLoader(load.LoaderPlugin): } rt.AlembicImport.ImportToRoot = False - product_fps = float(context["version"]["attrib"].get("fps")) - if product_fps is None: - # Just stick to current scene FPS - product_fps = float(rt.frameRate) - # TODO: remove after the post-system fps setup - rt.frameRange = product_fps + # TODO: it will be removed after the improvement + # on the post-system setup + reset_frame_range() rt.importFile(file_path, rt.name("noPrompt"), using=rt.AlembicImport) abc_after = { From eb124b54ad3781b79f507ef270fc86f2737d9128 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 13 Jun 2024 17:01:46 +0200 Subject: [PATCH 13/15] use task name as source of truth from ui --- client/ayon_core/tools/workfiles/abstract.py | 13 ++++++----- client/ayon_core/tools/workfiles/control.py | 23 +++++++++++++++---- .../tools/workfiles/models/workfiles.py | 12 ++++++---- .../widgets/files_widget_workarea.py | 10 ++++---- .../tools/workfiles/widgets/side_panel.py | 16 ++++++------- 5 files changed, 46 insertions(+), 28 deletions(-) diff --git a/client/ayon_core/tools/workfiles/abstract.py b/client/ayon_core/tools/workfiles/abstract.py index f345e20dca..330b413300 100644 --- a/client/ayon_core/tools/workfiles/abstract.py +++ b/client/ayon_core/tools/workfiles/abstract.py @@ -834,12 +834,13 @@ class AbstractWorkfilesFrontend(AbstractWorkfilesCommon): pass @abstractmethod - def get_workarea_file_items(self, folder_id, task_id): + def get_workarea_file_items(self, folder_id, task_name, sender=None): """Get workarea file items. Args: folder_id (str): Folder id. - task_id (str): Task id. + task_name (str): Task name. + sender (Optional[str]): Who requested workarea file items. Returns: list[FileItem]: List of workarea file items. @@ -905,12 +906,12 @@ class AbstractWorkfilesFrontend(AbstractWorkfilesCommon): pass @abstractmethod - def get_workfile_info(self, folder_id, task_id, filepath): + def get_workfile_info(self, folder_id, task_name, filepath): """Workfile info from database. Args: folder_id (str): Folder id. - task_id (str): Task id. + task_name (str): Task id. filepath (str): Workfile path. Returns: @@ -921,7 +922,7 @@ class AbstractWorkfilesFrontend(AbstractWorkfilesCommon): pass @abstractmethod - def save_workfile_info(self, folder_id, task_id, filepath, note): + def save_workfile_info(self, folder_id, task_name, filepath, note): """Save workfile info to database. At this moment the only information which can be saved about @@ -932,7 +933,7 @@ class AbstractWorkfilesFrontend(AbstractWorkfilesCommon): Args: folder_id (str): Folder id. - task_id (str): Task id. + task_name (str): Task id. filepath (str): Workfile path. note (Union[str, None]): Note. """ diff --git a/client/ayon_core/tools/workfiles/control.py b/client/ayon_core/tools/workfiles/control.py index 8fa9135bc0..1f66b363e1 100644 --- a/client/ayon_core/tools/workfiles/control.py +++ b/client/ayon_core/tools/workfiles/control.py @@ -410,9 +410,11 @@ class BaseWorkfileController( return self._workfiles_model.get_workarea_dir_by_context( folder_id, task_id) - def get_workarea_file_items(self, folder_id, task_id): + def get_workarea_file_items(self, folder_id, task_name, sender=None): + task_id = self._get_task_id(folder_id, task_name) return self._workfiles_model.get_workarea_file_items( - folder_id, task_id) + folder_id, task_id, task_name + ) def get_workarea_save_as_data(self, folder_id, task_id): return self._workfiles_model.get_workarea_save_as_data( @@ -447,12 +449,14 @@ class BaseWorkfileController( return self._workfiles_model.get_published_file_items( folder_id, task_name) - def get_workfile_info(self, folder_id, task_id, filepath): + def get_workfile_info(self, folder_id, task_name, filepath): + task_id = self._get_task_id(folder_id, task_name) return self._workfiles_model.get_workfile_info( folder_id, task_id, filepath ) - def save_workfile_info(self, folder_id, task_id, filepath, note): + def save_workfile_info(self, folder_id, task_name, filepath, note): + task_id = self._get_task_id(folder_id, task_name) self._workfiles_model.save_workfile_info( folder_id, task_id, filepath, note ) @@ -627,6 +631,17 @@ class BaseWorkfileController( def _emit_event(self, topic, data=None): self.emit_event(topic, data, "controller") + def _get_task_id(self, folder_id, task_name, sender=None): + task_item = self._hierarchy_model.get_task_item_by_name( + self.get_current_project_name(), + folder_id, + task_name, + sender + ) + if not task_item: + return None + return task_item.id + # Expected selection # - expected selection is used to restore selection after refresh # or when current context should be used diff --git a/client/ayon_core/tools/workfiles/models/workfiles.py b/client/ayon_core/tools/workfiles/models/workfiles.py index c93bbb6637..a47e459a6e 100644 --- a/client/ayon_core/tools/workfiles/models/workfiles.py +++ b/client/ayon_core/tools/workfiles/models/workfiles.py @@ -173,7 +173,7 @@ class WorkareaModel: folder_mapping[task_id] = workdir return workdir - def get_file_items(self, folder_id, task_id): + def get_file_items(self, folder_id, task_id, task_name): items = [] if not folder_id or not task_id: return items @@ -192,7 +192,7 @@ class WorkareaModel: continue workfile_info = self._controller.get_workfile_info( - folder_id, task_id, filepath + folder_id, task_name, filepath ) modified = os.path.getmtime(filepath) items.append(FileItem( @@ -770,19 +770,21 @@ class WorkfilesModel: return self._workarea_model.get_workarea_dir_by_context( folder_id, task_id) - def get_workarea_file_items(self, folder_id, task_id): + def get_workarea_file_items(self, folder_id, task_id, task_name): """Workfile items for passed context from workarea. Args: folder_id (Union[str, None]): Folder id. task_id (Union[str, None]): Task id. + task_name (Union[str, None]): Task name. Returns: list[FileItem]: List of file items matching workarea of passed context. """ - - return self._workarea_model.get_file_items(folder_id, task_id) + return self._workarea_model.get_file_items( + folder_id, task_id, task_name + ) def get_workarea_save_as_data(self, folder_id, task_id): return self._workarea_model.get_workarea_save_as_data( diff --git a/client/ayon_core/tools/workfiles/widgets/files_widget_workarea.py b/client/ayon_core/tools/workfiles/widgets/files_widget_workarea.py index 5c102dcdd4..7f76b6a8ab 100644 --- a/client/ayon_core/tools/workfiles/widgets/files_widget_workarea.py +++ b/client/ayon_core/tools/workfiles/widgets/files_widget_workarea.py @@ -66,7 +66,7 @@ class WorkAreaFilesModel(QtGui.QStandardItemModel): self._empty_item_used = False self._published_mode = False self._selected_folder_id = None - self._selected_task_id = None + self._selected_task_name = None self._add_missing_context_item() @@ -153,7 +153,7 @@ class WorkAreaFilesModel(QtGui.QStandardItemModel): def _on_task_changed(self, event): self._selected_folder_id = event["folder_id"] - self._selected_task_id = event["task_id"] + self._selected_task_name = event["task_name"] if not self._published_mode: self._fill_items() @@ -179,13 +179,13 @@ class WorkAreaFilesModel(QtGui.QStandardItemModel): def _fill_items_impl(self): folder_id = self._selected_folder_id - task_id = self._selected_task_id - if not folder_id or not task_id: + task_name = self._selected_task_name + if not folder_id or not task_name: self._add_missing_context_item() return file_items = self._controller.get_workarea_file_items( - folder_id, task_id + folder_id, task_name ) root_item = self.invisibleRootItem() if not file_items: diff --git a/client/ayon_core/tools/workfiles/widgets/side_panel.py b/client/ayon_core/tools/workfiles/widgets/side_panel.py index 53fdf0e0ac..7ba60b5544 100644 --- a/client/ayon_core/tools/workfiles/widgets/side_panel.py +++ b/client/ayon_core/tools/workfiles/widgets/side_panel.py @@ -75,7 +75,7 @@ class SidePanelWidget(QtWidgets.QWidget): self._btn_note_save = btn_note_save self._folder_id = None - self._task_id = None + self._task_name = None self._filepath = None self._orig_note = "" self._controller = controller @@ -93,10 +93,10 @@ class SidePanelWidget(QtWidgets.QWidget): def _on_selection_change(self, event): folder_id = event["folder_id"] - task_id = event["task_id"] + task_name = event["task_name"] filepath = event["path"] - self._set_context(folder_id, task_id, filepath) + self._set_context(folder_id, task_name, filepath) def _on_note_change(self): text = self._note_input.toPlainText() @@ -106,19 +106,19 @@ class SidePanelWidget(QtWidgets.QWidget): note = self._note_input.toPlainText() self._controller.save_workfile_info( self._folder_id, - self._task_id, + self._task_name, self._filepath, note ) self._orig_note = note self._btn_note_save.setEnabled(False) - def _set_context(self, folder_id, task_id, filepath): + def _set_context(self, folder_id, task_name, filepath): workfile_info = None # Check if folder, task and file are selected - if bool(folder_id) and bool(task_id) and bool(filepath): + if bool(folder_id) and bool(task_name) and bool(filepath): workfile_info = self._controller.get_workfile_info( - folder_id, task_id, filepath + folder_id, task_name, filepath ) enabled = workfile_info is not None @@ -127,7 +127,7 @@ class SidePanelWidget(QtWidgets.QWidget): self._btn_note_save.setEnabled(enabled) self._folder_id = folder_id - self._task_id = task_id + self._task_name = task_name self._filepath = filepath # Disable inputs and remove texts if any required arguments are From 43713d7ac01f021ff8a81a59e87c7acc5142037c Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 13 Jun 2024 17:16:08 +0200 Subject: [PATCH 14/15] define id of workfile entity for updates --- client/ayon_core/tools/workfiles/models/workfiles.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/ayon_core/tools/workfiles/models/workfiles.py b/client/ayon_core/tools/workfiles/models/workfiles.py index a47e459a6e..a268a9bd0e 100644 --- a/client/ayon_core/tools/workfiles/models/workfiles.py +++ b/client/ayon_core/tools/workfiles/models/workfiles.py @@ -1,6 +1,7 @@ import os import re import copy +import uuid import arrow import ayon_api @@ -587,6 +588,7 @@ class WorkfileEntitiesModel: username = self._get_current_username() workfile_info = { + "id": uuid.uuid4().hex, "path": rootless_path, "taskId": task_id, "attrib": { From ad23386d189453b1acaa1d8c86681d8a9185dfcd Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 13 Jun 2024 17:16:15 +0200 Subject: [PATCH 15/15] fix create new workfile --- client/ayon_core/tools/workfiles/control.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/tools/workfiles/control.py b/client/ayon_core/tools/workfiles/control.py index 1f66b363e1..fbd0bd3ac8 100644 --- a/client/ayon_core/tools/workfiles/control.py +++ b/client/ayon_core/tools/workfiles/control.py @@ -737,7 +737,7 @@ class BaseWorkfileController( self._host_save_workfile(dst_filepath) # Make sure workfile info exists - self.save_workfile_info(folder_id, task_id, dst_filepath, None) + self.save_workfile_info(folder_id, task_name, dst_filepath, None) # Create extra folders create_workdir_extra_folders(