From e3f8ff9de35ad5ec37b6981c2f7fd3710acd6356 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 11 Jun 2024 19:58:08 +0800 Subject: [PATCH] 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,