From 5bffaa730efce006283b66462d52a543713fcce0 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 11 Jun 2024 17:27:25 +0800 Subject: [PATCH 01/11] 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/11] 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/11] 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/11] 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/11] 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/11] 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/11] 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/11] 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/11] 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/11] 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 edd19c313585b48b975435b67e54e6d939359b62 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 13 Jun 2024 14:25:57 +0800 Subject: [PATCH 11/11] 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 = {