From d6159a0d0b46cb62c8358c6a6cb4af33208684d7 Mon Sep 17 00:00:00 2001 From: jrsndlr Date: Thu, 5 Sep 2024 16:27:51 +0200 Subject: [PATCH 1/8] enhancement/AY-6116-blender_allow_handles_frame_range --- client/ayon_blender/api/ops.py | 10 ++--- client/ayon_blender/api/pipeline.py | 67 ++++++++++++++++++----------- server/settings/include_handles.py | 30 +++++++++++++ server/settings/main.py | 7 ++- 4 files changed, 82 insertions(+), 32 deletions(-) create mode 100644 server/settings/include_handles.py diff --git a/client/ayon_blender/api/ops.py b/client/ayon_blender/api/ops.py index 7d15601..1abe95f 100644 --- a/client/ayon_blender/api/ops.py +++ b/client/ayon_blender/api/ops.py @@ -369,8 +369,8 @@ class SetFrameRange(bpy.types.Operator): bl_label = "Set Frame Range" def execute(self, context): - data = get_current_task_entity() - pipeline.set_frame_range(data) + task_entity = get_current_task_entity() + pipeline.set_frame_range(task_entity) return {"FINISHED"} @@ -379,8 +379,8 @@ class SetResolution(bpy.types.Operator): bl_label = "Set Resolution" def execute(self, context): - data = get_current_task_entity() - pipeline.set_resolution(data) + task_entity = get_current_task_entity() + pipeline.set_resolution(task_entity) return {"FINISHED"} @@ -482,4 +482,4 @@ def unregister(): bpy.utils.previews.remove(pcoll) bpy.types.TOPBAR_MT_editor_menus.remove(draw_avalon_menu) for cls in reversed(classes): - bpy.utils.unregister_class(cls) + bpy.utils.unregister_class(cls) \ No newline at end of file diff --git a/client/ayon_blender/api/pipeline.py b/client/ayon_blender/api/pipeline.py index 750b373..e5b9a24 100644 --- a/client/ayon_blender/api/pipeline.py +++ b/client/ayon_blender/api/pipeline.py @@ -254,44 +254,59 @@ def get_frame_range(task_entity=None) -> Union[Dict[str, int], None]: } -def set_frame_range(data): +def set_frame_range(entity: dict): scene = bpy.context.scene # Default scene settings - frameStart = scene.frame_start - frameEnd = scene.frame_end + frame_start = scene.frame_start + frame_end = scene.frame_end fps = scene.render.fps / scene.render.fps_base - if not data: + if not entity: return - if data.get("frameStart"): - frameStart = data.get("frameStart") - if data.get("frameEnd"): - frameEnd = data.get("frameEnd") - if data.get("fps"): - fps = data.get("fps") - - scene.frame_start = frameStart - scene.frame_end = frameEnd + attrib = entity["attrib"] + if attrib.get("frameStart"): + frame_start = attrib.get("frameStart") + if attrib.get("frameEnd"): + frame_end = attrib.get("frameEnd") + if attrib.get("fps"): + fps = attrib.get("fps") + + # Should handles be included? + settings = get_project_settings(get_current_project_name()) + task_type = attrib.get("taskType") + include_handles_settings = settings["blender"]["include_handles"] + include_handles = include_handles_settings["include_handles_default"] + for item in include_handles_settings["per_task_type"]: + if task_type in item["task_type"]: + include_handles = item["include_handles"] + break + if include_handles: + frame_start -= int(attrib.get("handleStart", 0)) + frame_end += int(attrib.get("handleEnd", 0)) + + scene.frame_start = frame_start + scene.frame_end = frame_end scene.render.fps = round(fps) scene.render.fps_base = round(fps) / fps -def set_resolution(data): +def set_resolution(entity: dict): scene = bpy.context.scene # Default scene settings resolution_x = scene.render.resolution_x resolution_y = scene.render.resolution_y - if not data: + if not entity: return - if data.get("resolutionWidth"): - resolution_x = data.get("resolutionWidth") - if data.get("resolutionHeight"): - resolution_y = data.get("resolutionHeight") + attrib = entity["attrib"] + if attrib.get("resolutionWidth"): + resolution_x = attrib.get("resolutionWidth") + if attrib.get("resolutionHeight"): + resolution_y = attrib.get("resolutionHeight") scene.render.resolution_x = resolution_x scene.render.resolution_y = resolution_y @@ -313,12 +328,12 @@ def on_new(): set_resolution_startup = settings.get("set_resolution_startup") set_frames_startup = settings.get("set_frames_startup") - data = get_current_task_entity() + task_entity = get_current_task_entity() if set_resolution_startup: - set_resolution(data) + set_resolution(task_entity) if set_frames_startup: - set_frame_range(data) + set_frame_range(task_entity) unit_scale_settings = settings.get("unit_scale_settings") set_unit_scale_from_settings(unit_scale_settings=unit_scale_settings) @@ -331,12 +346,12 @@ def on_open(): set_resolution_startup = settings.get("set_resolution_startup") set_frames_startup = settings.get("set_frames_startup") - data = get_current_task_entity() + task_entity = get_current_task_entity() if set_resolution_startup: - set_resolution(data) + set_resolution(task_entity) if set_frames_startup: - set_frame_range(data) + set_frame_range(task_entity) unit_scale_settings = settings.get("unit_scale_settings") unit_scale_enabled = unit_scale_settings.get("enabled") @@ -603,4 +618,4 @@ def ls() -> Iterator: def publish(): """Shorthand to publish from within host.""" - return pyblish.util.publish() + return pyblish.util.publish() \ No newline at end of file diff --git a/server/settings/include_handles.py b/server/settings/include_handles.py new file mode 100644 index 0000000..cd2e193 --- /dev/null +++ b/server/settings/include_handles.py @@ -0,0 +1,30 @@ +from ayon_server.settings import ( + BaseSettingsModel, + SettingsField, + task_types_enum, +) + + +class IncludeByTaskTypeModel(BaseSettingsModel): + task_type: list[str] = SettingsField( + default_factory=list, + title="Task types", + enum_resolver=task_types_enum + ) + include_handles: bool = SettingsField(True, title="Include handles") + + +class IncludeHandlesModel(BaseSettingsModel): + include_handles_default: bool = SettingsField( + True, title="Include handles by default" + ) + per_task_type: list[IncludeByTaskTypeModel] = SettingsField( + default_factory=list, + title="Include/exclude handles by task type" + ) + + +DEFAULT_INCLUDE_HANDLES = { + "include_handles_default": False, + "per_task_type": [] +} \ No newline at end of file diff --git a/server/settings/main.py b/server/settings/main.py index 3cca22a..58fc737 100644 --- a/server/settings/main.py +++ b/server/settings/main.py @@ -3,7 +3,7 @@ SettingsField, TemplateWorkfileBaseOptions, ) - +from .include_handles import IncludeHandlesModel, DEFAULT_INCLUDE_HANDLES from .imageio import BlenderImageIOModel from .publish_plugins import ( PublishPluginsModel, @@ -37,6 +37,10 @@ class BlenderSettings(BaseSettingsModel): True, title="Set Start/End Frames and FPS on Startup" ) + include_handles: IncludeHandlesModel = SettingsField( + default_factory=IncludeHandlesModel, + title="Include/Exclude Handles in default playback & render range" + ) imageio: BlenderImageIOModel = SettingsField( default_factory=BlenderImageIOModel, title="Color Management (ImageIO)" @@ -61,6 +65,7 @@ class BlenderSettings(BaseSettingsModel): }, "set_frames_startup": True, "set_resolution_startup": True, + "include_handles": DEFAULT_INCLUDE_HANDLES, "RenderSettings": DEFAULT_RENDER_SETTINGS, "publish": DEFAULT_BLENDER_PUBLISH_SETTINGS, "workfile_builder": { From fe15e4484936cfd27159b626f0311fb54eadf38b Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 5 Sep 2024 17:29:31 +0200 Subject: [PATCH 2/8] Cosmetics --- client/ayon_blender/api/ops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_blender/api/ops.py b/client/ayon_blender/api/ops.py index 1abe95f..f19d9e6 100644 --- a/client/ayon_blender/api/ops.py +++ b/client/ayon_blender/api/ops.py @@ -482,4 +482,4 @@ def unregister(): bpy.utils.previews.remove(pcoll) bpy.types.TOPBAR_MT_editor_menus.remove(draw_avalon_menu) for cls in reversed(classes): - bpy.utils.unregister_class(cls) \ No newline at end of file + bpy.utils.unregister_class(cls) From a65196bda64830cbe1bb47c96ebedd561f23e68b Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 5 Sep 2024 17:30:05 +0200 Subject: [PATCH 3/8] Cosmetics --- server/settings/include_handles.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/settings/include_handles.py b/server/settings/include_handles.py index cd2e193..96b914a 100644 --- a/server/settings/include_handles.py +++ b/server/settings/include_handles.py @@ -27,4 +27,4 @@ class IncludeHandlesModel(BaseSettingsModel): DEFAULT_INCLUDE_HANDLES = { "include_handles_default": False, "per_task_type": [] -} \ No newline at end of file +} From 0d7d2e5190721aa46912e9e1e24fe0864850f0ca Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 6 Sep 2024 10:49:33 +0200 Subject: [PATCH 4/8] Update client/ayon_blender/api/pipeline.py --- client/ayon_blender/api/pipeline.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_blender/api/pipeline.py b/client/ayon_blender/api/pipeline.py index 032e46a..9e99470 100644 --- a/client/ayon_blender/api/pipeline.py +++ b/client/ayon_blender/api/pipeline.py @@ -275,7 +275,7 @@ def set_frame_range(entity: dict): # Should handles be included, defined by settings settings = get_project_settings(get_current_project_name()) - task_type = attrib.get("taskType") + task_type = entity.get("taskType") include_handles_settings = settings["blender"]["include_handles"] include_handles = include_handles_settings["include_handles_default"] for item in include_handles_settings["per_task_type"]: From ac363b24d48ff39c73c9fb0e7b51d0c95dff6d26 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 6 Sep 2024 12:09:08 +0200 Subject: [PATCH 5/8] Apply suggestions from code review Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- server/settings/include_handles.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/settings/include_handles.py b/server/settings/include_handles.py index 96b914a..ffe09cb 100644 --- a/server/settings/include_handles.py +++ b/server/settings/include_handles.py @@ -16,7 +16,7 @@ class IncludeByTaskTypeModel(BaseSettingsModel): class IncludeHandlesModel(BaseSettingsModel): include_handles_default: bool = SettingsField( - True, title="Include handles by default" + False, title="Include handles by default" ) per_task_type: list[IncludeByTaskTypeModel] = SettingsField( default_factory=list, From 33162dbeb724f2f067aa37d5755944fa0801ffb6 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 6 Sep 2024 12:21:45 +0200 Subject: [PATCH 6/8] Move include handles settings to `main` --- server/settings/include_handles.py | 30 ------------------------------ server/settings/main.py | 26 ++++++++++++++++++++++++-- 2 files changed, 24 insertions(+), 32 deletions(-) delete mode 100644 server/settings/include_handles.py diff --git a/server/settings/include_handles.py b/server/settings/include_handles.py deleted file mode 100644 index ffe09cb..0000000 --- a/server/settings/include_handles.py +++ /dev/null @@ -1,30 +0,0 @@ -from ayon_server.settings import ( - BaseSettingsModel, - SettingsField, - task_types_enum, -) - - -class IncludeByTaskTypeModel(BaseSettingsModel): - task_type: list[str] = SettingsField( - default_factory=list, - title="Task types", - enum_resolver=task_types_enum - ) - include_handles: bool = SettingsField(True, title="Include handles") - - -class IncludeHandlesModel(BaseSettingsModel): - include_handles_default: bool = SettingsField( - False, title="Include handles by default" - ) - per_task_type: list[IncludeByTaskTypeModel] = SettingsField( - default_factory=list, - title="Include/exclude handles by task type" - ) - - -DEFAULT_INCLUDE_HANDLES = { - "include_handles_default": False, - "per_task_type": [] -} diff --git a/server/settings/main.py b/server/settings/main.py index 58fc737..405aca0 100644 --- a/server/settings/main.py +++ b/server/settings/main.py @@ -2,8 +2,8 @@ BaseSettingsModel, SettingsField, TemplateWorkfileBaseOptions, + task_types_enum, ) -from .include_handles import IncludeHandlesModel, DEFAULT_INCLUDE_HANDLES from .imageio import BlenderImageIOModel from .publish_plugins import ( PublishPluginsModel, @@ -24,6 +24,25 @@ class UnitScaleSettingsModel(BaseSettingsModel): ) +class IncludeByTaskTypeModel(BaseSettingsModel): + task_type: list[str] = SettingsField( + default_factory=list, + title="Task types", + enum_resolver=task_types_enum + ) + include_handles: bool = SettingsField(True, title="Include handles") + + +class IncludeHandlesModel(BaseSettingsModel): + include_handles_default: bool = SettingsField( + False, title="Include handles by default" + ) + per_task_type: list[IncludeByTaskTypeModel] = SettingsField( + default_factory=list, + title="Include/exclude handles by task type" + ) + + class BlenderSettings(BaseSettingsModel): unit_scale_settings: UnitScaleSettingsModel = SettingsField( default_factory=UnitScaleSettingsModel, @@ -65,7 +84,10 @@ class BlenderSettings(BaseSettingsModel): }, "set_frames_startup": True, "set_resolution_startup": True, - "include_handles": DEFAULT_INCLUDE_HANDLES, + "include_handles": { + "include_handles_default": False, + "per_task_type": [] + }, "RenderSettings": DEFAULT_RENDER_SETTINGS, "publish": DEFAULT_BLENDER_PUBLISH_SETTINGS, "workfile_builder": { From d58ba536e5e3995afca7552d52aae0866cf3f4f6 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 6 Sep 2024 12:22:54 +0200 Subject: [PATCH 7/8] `task_type` -> `task_types` --- client/ayon_blender/api/pipeline.py | 2 +- server/settings/main.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/ayon_blender/api/pipeline.py b/client/ayon_blender/api/pipeline.py index 9e99470..e08876f 100644 --- a/client/ayon_blender/api/pipeline.py +++ b/client/ayon_blender/api/pipeline.py @@ -279,7 +279,7 @@ def set_frame_range(entity: dict): include_handles_settings = settings["blender"]["include_handles"] include_handles = include_handles_settings["include_handles_default"] for item in include_handles_settings["per_task_type"]: - if task_type in item["task_type"]: + if task_type in item["task_types"]: include_handles = item["include_handles"] break if include_handles: diff --git a/server/settings/main.py b/server/settings/main.py index 405aca0..724f0a3 100644 --- a/server/settings/main.py +++ b/server/settings/main.py @@ -25,7 +25,7 @@ class UnitScaleSettingsModel(BaseSettingsModel): class IncludeByTaskTypeModel(BaseSettingsModel): - task_type: list[str] = SettingsField( + task_types: list[str] = SettingsField( default_factory=list, title="Task types", enum_resolver=task_types_enum From 6534f1c5f390359f36ec3ed1bb8e0b0560ce4855 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 6 Sep 2024 14:22:44 +0200 Subject: [PATCH 8/8] Use profiles instead --- client/ayon_blender/api/pipeline.py | 16 +++++++++++----- server/settings/main.py | 18 ++++++++++++------ 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/client/ayon_blender/api/pipeline.py b/client/ayon_blender/api/pipeline.py index e08876f..5f81ec4 100644 --- a/client/ayon_blender/api/pipeline.py +++ b/client/ayon_blender/api/pipeline.py @@ -30,7 +30,8 @@ from ayon_core.lib import ( Logger, register_event_callback, - emit_event + emit_event, + filter_profiles ) from ayon_core.settings import get_project_settings from ayon_blender import BLENDER_ADDON_ROOT @@ -278,10 +279,15 @@ def set_frame_range(entity: dict): task_type = entity.get("taskType") include_handles_settings = settings["blender"]["include_handles"] include_handles = include_handles_settings["include_handles_default"] - for item in include_handles_settings["per_task_type"]: - if task_type in item["task_types"]: - include_handles = item["include_handles"] - break + profile = filter_profiles( + include_handles_settings["profiles"], + key_values={ + "task_types": task_type, + "task_names": entity["name"] + } + ) + if profile: + include_handles = profile["include_handles"] if include_handles: frame_start -= int(attrib.get("handleStart", 0)) frame_end += int(attrib.get("handleEnd", 0)) diff --git a/server/settings/main.py b/server/settings/main.py index 724f0a3..02b9a2a 100644 --- a/server/settings/main.py +++ b/server/settings/main.py @@ -24,11 +24,17 @@ class UnitScaleSettingsModel(BaseSettingsModel): ) -class IncludeByTaskTypeModel(BaseSettingsModel): +class IncludeHandlesProfilesModel(BaseSettingsModel): task_types: list[str] = SettingsField( default_factory=list, - title="Task types", - enum_resolver=task_types_enum + title="Task Types", + description="Filter by task types", + enum_resolver=task_types_enum, + ) + task_names: list[str] = SettingsField( + default_factory=list, + title="Task Names", + description="Filter by task names.", ) include_handles: bool = SettingsField(True, title="Include handles") @@ -37,9 +43,9 @@ class IncludeHandlesModel(BaseSettingsModel): include_handles_default: bool = SettingsField( False, title="Include handles by default" ) - per_task_type: list[IncludeByTaskTypeModel] = SettingsField( + profiles: list[IncludeHandlesProfilesModel] = SettingsField( default_factory=list, - title="Include/exclude handles by task type" + title="Include/exclude handles by profiles" ) @@ -86,7 +92,7 @@ class BlenderSettings(BaseSettingsModel): "set_resolution_startup": True, "include_handles": { "include_handles_default": False, - "per_task_type": [] + "profiles": [] }, "RenderSettings": DEFAULT_RENDER_SETTINGS, "publish": DEFAULT_BLENDER_PUBLISH_SETTINGS,