diff --git a/client/ayon_core/hosts/fusion/plugins/create/create_saver.py b/client/ayon_core/hosts/fusion/plugins/create/create_saver.py
index b6cda1f302..20c7b99851 100644
--- a/client/ayon_core/hosts/fusion/plugins/create/create_saver.py
+++ b/client/ayon_core/hosts/fusion/plugins/create/create_saver.py
@@ -1,6 +1,11 @@
-from ayon_core.lib import EnumDef
+from ayon_core.lib import (
+ UILabelDef,
+ NumberDef,
+ EnumDef
+)
from ayon_core.hosts.fusion.api.plugin import GenericCreateSaver
+from ayon_core.hosts.fusion.api.lib import get_current_comp
class CreateSaver(GenericCreateSaver):
@@ -45,6 +50,7 @@ class CreateSaver(GenericCreateSaver):
self._get_reviewable_bool(),
self._get_frame_range_enum(),
self._get_image_format_enum(),
+ *self._get_custom_frame_range_attribute_defs()
]
return attr_defs
@@ -53,6 +59,7 @@ class CreateSaver(GenericCreateSaver):
"current_folder": "Current Folder context",
"render_range": "From render in/out",
"comp_range": "From composition timeline",
+ "custom_range": "Custom frame range",
}
return EnumDef(
@@ -61,3 +68,82 @@ class CreateSaver(GenericCreateSaver):
label="Frame range source",
default=self.default_frame_range_option
)
+
+ @staticmethod
+ def _get_custom_frame_range_attribute_defs() -> list:
+
+ # Define custom frame range defaults based on current comp
+ # timeline settings (if a comp is currently open)
+ comp = get_current_comp()
+ if comp is not None:
+ attrs = comp.GetAttrs()
+ frame_defaults = {
+ "frameStart": int(attrs["COMPN_GlobalStart"]),
+ "frameEnd": int(attrs["COMPN_GlobalEnd"]),
+ "handleStart": int(
+ attrs["COMPN_RenderStart"] - attrs["COMPN_GlobalStart"]
+ ),
+ "handleEnd": int(
+ attrs["COMPN_GlobalEnd"] - attrs["COMPN_RenderEnd"]
+ ),
+ }
+ else:
+ frame_defaults = {
+ "frameStart": 1001,
+ "frameEnd": 1100,
+ "handleStart": 0,
+ "handleEnd": 0
+ }
+
+ return [
+ UILabelDef(
+ label="
Custom Frame Range
"
+ "only used with 'Custom frame range' source"
+ ),
+ NumberDef(
+ "custom_frameStart",
+ label="Frame Start",
+ default=frame_defaults["frameStart"],
+ minimum=0,
+ decimals=0,
+ tooltip=(
+ "Set the start frame for the export.\n"
+ "Only used if frame range source is 'Custom frame range'."
+ )
+ ),
+ NumberDef(
+ "custom_frameEnd",
+ label="Frame End",
+ default=frame_defaults["frameEnd"],
+ minimum=0,
+ decimals=0,
+ tooltip=(
+ "Set the end frame for the export.\n"
+ "Only used if frame range source is 'Custom frame range'."
+ )
+ ),
+ NumberDef(
+ "custom_handleStart",
+ label="Handle Start",
+ default=frame_defaults["handleStart"],
+ minimum=0,
+ decimals=0,
+ tooltip=(
+ "Set the start handles for the export, this will be "
+ "added before the start frame.\n"
+ "Only used if frame range source is 'Custom frame range'."
+ )
+ ),
+ NumberDef(
+ "custom_handleEnd",
+ label="Handle End",
+ default=frame_defaults["handleEnd"],
+ minimum=0,
+ decimals=0,
+ tooltip=(
+ "Set the end handles for the export, this will be added "
+ "after the end frame.\n"
+ "Only used if frame range source is 'Custom frame range'."
+ )
+ )
+ ]
diff --git a/client/ayon_core/hosts/fusion/plugins/publish/collect_instances.py b/client/ayon_core/hosts/fusion/plugins/publish/collect_instances.py
index 51d7e68fb6..921c282877 100644
--- a/client/ayon_core/hosts/fusion/plugins/publish/collect_instances.py
+++ b/client/ayon_core/hosts/fusion/plugins/publish/collect_instances.py
@@ -57,6 +57,14 @@ class CollectInstanceData(pyblish.api.InstancePlugin):
start_with_handle = comp_start
end_with_handle = comp_end
+ if frame_range_source == "custom_range":
+ start = int(instance.data["custom_frameStart"])
+ end = int(instance.data["custom_frameEnd"])
+ handle_start = int(instance.data["custom_handleStart"])
+ handle_end = int(instance.data["custom_handleEnd"])
+ start_with_handle = start - handle_start
+ end_with_handle = end + handle_end
+
frame = instance.data["creator_attributes"].get("frame")
# explicitly publishing only single frame
if frame is not None: