Blender Kitsu: Add Operator to Push Frame Start #98
@ -161,7 +161,7 @@ In the `Push` panel you will find all the operators that push data to Kitsu. <br
|
||||
|
||||
>**Metadata**: Pushes metadata of shot: sequence, shot name, frame range, sequence_color
|
||||
>>**Note**: Global edit frame range will be saved in `"frame_in"` `"frame_out"` kitsu shot attribute <br/>
|
||||
The actual shot frame range (starting at 101) will be saved in `["data"]["3d_in"] and `["data"]["3d_out"] kitsu shot attribute <br/>
|
||||
The actual shot frame range (starting at 101) will be saved in `["data"]["3d_start"]` kitsu shot attribute <br/>
|
||||
|
||||
>**Thumbnails**: Renders a thumbnail of the selected shots (will be saved to the `Thumbnail Directory` -> see addon preferences) and uploads it to Kitsu. Thumbnails are linked to a task in Kitsu. So you can select the Task Type for which you want to upload the thumbnail with the `Set Thumbnail Task Type` operator. <br/>
|
||||
If you select multiple metastrips it will always use the middle frame to create the thumbnail. If you have only one selected it will use the frame which is under the cursor (it curser is inside shot range). <br/>
|
||||
@ -243,7 +243,7 @@ The animation tools will show up when you selected a `Task Type` with the name `
|
||||
![image info](/media/addons/blender_kitsu/context_animation_tools.jpg)
|
||||
|
||||
>**Create Playblast**: Will create a openGL viewport render of the viewport from which the operator was executed and uploads it to Kitsu. The `+` button increments the version of the playblast. If you would override an older version you will see a warning before the filepath. The `directory` button will open a file browser in the playblast directory. The playblast will be uploaded to the `Animation` Task Type of the active shot that was set in the `Context Browser`. The web browser will be opened after the playblast and should point to the respective shot on Kitsu. <br/>
|
||||
**Update Frame Range**: Will pull the frame range of the active shot from Kitsu and apply it to the scene. It will use the `['data']['3d_in']` and `['data']['3d_out']` attribute of the Kitsu shot. <br/>
|
||||
**Update Frame Range**: Will pull the frame range of the active shot from Kitsu and apply it to the scene. It will use the `['data']['3d_start]` attribute of the Kitsu shot. <br/>
|
||||
**Update Output Collection**: Blender Studio Pipeline specific operator. <br/>
|
||||
**Duplicate Collection**: Blender Studio Pipeline specific operator. <br/>
|
||||
**Check Action Names**: Blender Studio Pipeline specific operator. <br/>
|
||||
|
@ -345,32 +345,24 @@ class KITSU_OT_playblast_set_version(bpy.types.Operator):
|
||||
|
||||
class KITSU_OT_push_frame_range(bpy.types.Operator):
|
||||
bl_idname = "kitsu.push_frame_range"
|
||||
bl_label = "Push Frame Range Offset"
|
||||
bl_label = "Push Frame Start"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
bl_description = "Adjusts the start frame to set it outside of the global value set for productionPush metadata via 3d_offset."
|
||||
|
||||
_shot = None
|
||||
kitsu_offset: bpy.props.IntProperty(name="Frame Range Offset", default=0)
|
||||
bl_description = "Adjusts the start frame of animation file."
|
||||
|
||||
def draw(self, context: bpy.types.Context) -> None:
|
||||
layout = self.layout
|
||||
col = layout.column(align=True)
|
||||
col.label(text="Choose an offset value for this animation file's frame range.")
|
||||
col.label(
|
||||
text="This will affect the results of 'Update Frame Range'", icon="ERROR"
|
||||
)
|
||||
col.prop(self, "kitsu_offset")
|
||||
col.label(text=f"New Frame Start: {context.scene.frame_start}", icon="ERROR")
|
||||
|
||||
def execute(self, context: bpy.types.Context) -> Set[str]:
|
||||
shot = cache.shot_active_pull_update()
|
||||
shot.data["3d_offset"] = self.kitsu_offset
|
||||
shot.data["3d_start"] = context.scene.frame_start
|
||||
shot.update()
|
||||
|
||||
self.report({"INFO"}, f"Updated frame range offset {shot.data['3d_offset']}")
|
||||
self.report({"INFO"}, f"Updated frame range offset {context.scene.frame_start}")
|
||||
return {"FINISHED"}
|
||||
|
||||
def invoke(self, context: bpy.types.Context, event: bpy.types.Event) -> Set[str]:
|
||||
self.kitsu_offset = context.scene.frame_start - bkglobals.FRAME_START
|
||||
return context.window_manager.invoke_props_dialog(self, width=500)
|
||||
|
||||
|
||||
@ -390,15 +382,15 @@ class KITSU_OT_pull_frame_range(bpy.types.Operator):
|
||||
def execute(self, context: bpy.types.Context) -> Set[str]:
|
||||
active_shot = cache.shot_active_pull_update()
|
||||
|
||||
if "3d_in" not in active_shot.data or "3d_out" not in active_shot.data:
|
||||
if "3d_start" not in active_shot.data:
|
||||
self.report(
|
||||
{"ERROR"},
|
||||
f"Failed to pull frame range. Shot {active_shot.name} missing '3d_in', '3d_out' attribute on server",
|
||||
f"Failed to pull frame range. Shot {active_shot.name} missing '3d_start'",
|
||||
)
|
||||
return {"CANCELLED"}
|
||||
|
||||
frame_in = int(active_shot.data["3d_in"]) + int(active_shot.data["3d_offset"])
|
||||
frame_out = int(active_shot.data["3d_out"]) + int(active_shot.data["3d_offset"])
|
||||
frame_in = int(active_shot.data["3d_start"])
|
||||
frame_out = int(active_shot.data["3d_start"]) + int(active_shot.nb_frames) - 1
|
||||
|
||||
# Check if current frame range matches the one for active shot.
|
||||
if (
|
||||
@ -462,14 +454,14 @@ def load_post_handler_check_frame_range(dummy: Any) -> None:
|
||||
# Pull update for shot.
|
||||
cache.shot_active_pull_update()
|
||||
|
||||
if "3d_in" not in active_shot.data or "3d_out" not in active_shot.data:
|
||||
if "3d_start" not in active_shot.data:
|
||||
logger.warning(
|
||||
"Failed to check frame range. Shot %s missing '3d_in', '3d_out' attribute on server",
|
||||
"Failed to check frame range. Shot %s missing '3d_start' attribute on server",
|
||||
active_shot.name,
|
||||
)
|
||||
return
|
||||
frame_in = int(active_shot.data["3d_in"]) + int(active_shot.data["3d_offset"])
|
||||
frame_out = int(active_shot.data["3d_out"]) + int(active_shot.data["3d_offset"])
|
||||
frame_in = int(active_shot.data["3d_start"])
|
||||
frame_out = int(active_shot.data["3d_start"]) + int(active_shot.nb_frames) - 1
|
||||
if (
|
||||
frame_in == bpy.context.scene.frame_start
|
||||
and frame_out == bpy.context.scene.frame_end
|
||||
|
@ -25,8 +25,8 @@ from blender_kitsu.shot_builder.task_type import TaskType
|
||||
from blender_kitsu.shot_builder.render_settings import RenderSettings
|
||||
from blender_kitsu.shot_builder.connectors.connector import Connector
|
||||
import requests
|
||||
from blender_kitsu import cache
|
||||
from blender_kitsu.gazu.asset import all_assets_for_shot
|
||||
from blender_kitsu import cache
|
||||
from blender_kitsu.gazu.asset import all_assets_for_shot
|
||||
from blender_kitsu.gazu.shot import all_shots_for_project, all_sequences_for_project
|
||||
|
||||
import typing
|
||||
@ -43,16 +43,19 @@ class KitsuPreferences(bpy.types.PropertyGroup):
|
||||
backend: bpy.props.StringProperty( # type: ignore
|
||||
name="Server URL",
|
||||
description="Kitsu server address",
|
||||
default="https://kitsu.blender.cloud/api")
|
||||
default="https://kitsu.blender.cloud/api",
|
||||
)
|
||||
|
||||
username: bpy.props.StringProperty( # type: ignore
|
||||
name="Username",
|
||||
description="Username to connect to Kitsu",)
|
||||
description="Username to connect to Kitsu",
|
||||
)
|
||||
|
||||
password: bpy.props.StringProperty( # type: ignore
|
||||
name="Password",
|
||||
description="Password to connect to Kitsu",
|
||||
subtype='PASSWORD',)
|
||||
subtype='PASSWORD',
|
||||
)
|
||||
|
||||
def draw(self, layout: bpy.types.UILayout, context: bpy.types.Context) -> None:
|
||||
layout.label(text="Kitsu")
|
||||
@ -63,10 +66,11 @@ class KitsuPreferences(bpy.types.PropertyGroup):
|
||||
def _validate(self):
|
||||
if not (self.backend and self.username and self.password):
|
||||
raise KitsuException(
|
||||
"Kitsu connector has not been configured in the add-on preferences")
|
||||
"Kitsu connector has not been configured in the add-on preferences"
|
||||
)
|
||||
|
||||
|
||||
class KitsuDataContainer():
|
||||
class KitsuDataContainer:
|
||||
def __init__(self, data: typing.Dict[str, typing.Optional[str]]):
|
||||
self._data = data
|
||||
|
||||
@ -109,7 +113,17 @@ class KitsuSequenceRef(ShotRef):
|
||||
|
||||
|
||||
class KitsuShotRef(ShotRef):
|
||||
def __init__(self, kitsu_id: str, name: str, code: str, frame_start: int, frames: int, frame_end: int, frames_per_second: float, sequence: KitsuSequenceRef):
|
||||
def __init__(
|
||||
self,
|
||||
kitsu_id: str,
|
||||
name: str,
|
||||
code: str,
|
||||
frame_start: int,
|
||||
frames: int,
|
||||
frame_end: int,
|
||||
frames_per_second: float,
|
||||
sequence: KitsuSequenceRef,
|
||||
):
|
||||
super().__init__(name=name, code=code)
|
||||
self.kitsu_id = kitsu_id
|
||||
self.frame_start = frame_start
|
||||
@ -137,8 +151,7 @@ class KitsuConnector(Connector):
|
||||
|
||||
def __get_production_data(self) -> KitsuProject:
|
||||
production = cache.project_active_get()
|
||||
project = KitsuProject(typing.cast(
|
||||
typing.Dict[str, typing.Any], production))
|
||||
project = KitsuProject(typing.cast(typing.Dict[str, typing.Any], production))
|
||||
return project
|
||||
|
||||
def get_name(self) -> str:
|
||||
@ -149,6 +162,7 @@ class KitsuConnector(Connector):
|
||||
project = cache.project_active_get()
|
||||
task_types = project.task_types
|
||||
import pprint
|
||||
|
||||
pprint.pprint(task_types)
|
||||
return []
|
||||
|
||||
@ -156,56 +170,80 @@ class KitsuConnector(Connector):
|
||||
project = cache.project_active_get()
|
||||
kitsu_sequences = all_sequences_for_project(project.id)
|
||||
|
||||
sequence_lookup = {sequence_data['id']: KitsuSequenceRef(
|
||||
kitsu_id=sequence_data['id'],
|
||||
name=sequence_data['name'],
|
||||
code=sequence_data['code'],
|
||||
) for sequence_data in kitsu_sequences}
|
||||
sequence_lookup = {
|
||||
sequence_data['id']: KitsuSequenceRef(
|
||||
kitsu_id=sequence_data['id'],
|
||||
name=sequence_data['name'],
|
||||
code=sequence_data['code'],
|
||||
)
|
||||
for sequence_data in kitsu_sequences
|
||||
}
|
||||
|
||||
kitsu_shots = all_shots_for_project(project.id)
|
||||
shots: typing.List[ShotRef] = []
|
||||
|
||||
for shot_data in kitsu_shots:
|
||||
|
||||
#Initialize default values
|
||||
# Initialize default values
|
||||
frame_start = vars.DEFAULT_FRAME_START
|
||||
frame_end = 0
|
||||
|
||||
# shot_data['data'] can be None
|
||||
if shot_data['data']:
|
||||
# If 3d_in key not found use default start frame.
|
||||
frame_start = int(shot_data['data'].get('3d_in', vars.DEFAULT_FRAME_START))
|
||||
frame_end = int(shot_data['data'].get('3d_out', 0))
|
||||
# If 3d_start key not found use default start frame.
|
||||
frame_start = int(
|
||||
shot_data['data'].get('3d_start', vars.DEFAULT_FRAME_START)
|
||||
)
|
||||
frame_end = (
|
||||
int(shot_data['data'].get('3d_start', vars.DEFAULT_FRAME_START))
|
||||
+ shot_data['nb_frames']
|
||||
- 1
|
||||
)
|
||||
|
||||
# If 3d_in and 3d_out available use that to calculate frames.
|
||||
# If 3d_start and 3d_out available use that to calculate frames.
|
||||
# If not try shot_data['nb_frames'] or 0 -> invalid.
|
||||
frames = int((frame_end - frame_start + 1) if frame_end else shot_data['nb_frames'] or 0)
|
||||
frames = int(
|
||||
(frame_end - frame_start + 1)
|
||||
if frame_end
|
||||
else shot_data['nb_frames'] or 0
|
||||
)
|
||||
if frames < 0:
|
||||
logger.error("%s duration is negative: %i. Check frame range information on Kitsu", shot_data['name'], frames)
|
||||
logger.error(
|
||||
"%s duration is negative: %i. Check frame range information on Kitsu",
|
||||
shot_data['name'],
|
||||
frames,
|
||||
)
|
||||
frames = 0
|
||||
|
||||
shots.append(KitsuShotRef(
|
||||
kitsu_id=shot_data['id'],
|
||||
name=shot_data['name'],
|
||||
code=shot_data['code'],
|
||||
frame_start=frame_start,
|
||||
frames=frames,
|
||||
frame_end = frame_end,
|
||||
frames_per_second=24.0,
|
||||
sequence=sequence_lookup[shot_data['parent_id']],
|
||||
))
|
||||
shots.append(
|
||||
KitsuShotRef(
|
||||
kitsu_id=shot_data['id'],
|
||||
name=shot_data['name'],
|
||||
code=shot_data['code'],
|
||||
frame_start=frame_start,
|
||||
frames=frames,
|
||||
frame_end=frame_end,
|
||||
frames_per_second=24.0,
|
||||
sequence=sequence_lookup[shot_data['parent_id']],
|
||||
)
|
||||
)
|
||||
|
||||
return shots
|
||||
|
||||
def get_assets_for_shot(self, shot: Shot) -> typing.List[AssetRef]:
|
||||
kitsu_assets = all_assets_for_shot(shot.kitsu_id)
|
||||
|
||||
return [AssetRef(name=asset_data['name'], code=asset_data['code'])
|
||||
for asset_data in kitsu_assets]
|
||||
return [
|
||||
AssetRef(name=asset_data['name'], code=asset_data['code'])
|
||||
for asset_data in kitsu_assets
|
||||
]
|
||||
|
||||
def get_render_settings(self, shot: Shot) -> RenderSettings:
|
||||
"""
|
||||
Retrieve the render settings for the given shot.
|
||||
"""
|
||||
project = cache.project_active_get()
|
||||
return RenderSettings(width=int(project.resolution.split('x')[0]), height=int(project.resolution.split('x')[1]), frames_per_second=project.fps)
|
||||
return RenderSettings(
|
||||
width=int(project.resolution.split('x')[0]),
|
||||
height=int(project.resolution.split('x')[1]),
|
||||
frames_per_second=project.fps,
|
||||
)
|
||||
|
@ -5,49 +5,53 @@ from typing import Set
|
||||
from blender_kitsu import prefs
|
||||
from blender_kitsu import cache
|
||||
|
||||
def editorial_export_get_latest(context:bpy.types.Context, shot) -> list[bpy.types.Sequence]: #TODO add info to shot
|
||||
"""Loads latest export from editorial department"""
|
||||
addon_prefs = prefs.addon_prefs_get(context)
|
||||
strip_channel = 1
|
||||
latest_file = editorial_export_check_latest(context)
|
||||
if not latest_file:
|
||||
return None
|
||||
# Check if Kitsu server returned empty shot
|
||||
if shot.get("id") == '':
|
||||
return None
|
||||
strip_filepath = latest_file.as_posix()
|
||||
strip_frame_start = addon_prefs.shot_builder_frame_offset
|
||||
|
||||
scene = context.scene
|
||||
if not scene.sequence_editor:
|
||||
scene.sequence_editor_create()
|
||||
seq_editor = scene.sequence_editor
|
||||
movie_strip = seq_editor.sequences.new_movie(
|
||||
latest_file.name,
|
||||
strip_filepath,
|
||||
strip_channel + 1,
|
||||
strip_frame_start,
|
||||
fit_method="FIT",
|
||||
def editorial_export_get_latest(
|
||||
context: bpy.types.Context, shot
|
||||
) -> list[bpy.types.Sequence]: # TODO add info to shot
|
||||
"""Loads latest export from editorial department"""
|
||||
addon_prefs = prefs.addon_prefs_get(context)
|
||||
strip_channel = 1
|
||||
latest_file = editorial_export_check_latest(context)
|
||||
if not latest_file:
|
||||
return None
|
||||
# Check if Kitsu server returned empty shot
|
||||
if shot.get("id") == '':
|
||||
return None
|
||||
strip_filepath = latest_file.as_posix()
|
||||
strip_frame_start = addon_prefs.shot_builder_frame_offset
|
||||
|
||||
scene = context.scene
|
||||
if not scene.sequence_editor:
|
||||
scene.sequence_editor_create()
|
||||
seq_editor = scene.sequence_editor
|
||||
movie_strip = seq_editor.sequences.new_movie(
|
||||
latest_file.name,
|
||||
strip_filepath,
|
||||
strip_channel + 1,
|
||||
strip_frame_start,
|
||||
fit_method="FIT",
|
||||
)
|
||||
sound_strip = seq_editor.sequences.new_sound(
|
||||
latest_file.name,
|
||||
strip_filepath,
|
||||
strip_channel,
|
||||
strip_frame_start,
|
||||
)
|
||||
new_strips = [movie_strip, sound_strip]
|
||||
|
||||
# Update shift frame range prop.
|
||||
frame_in = shot["data"].get("frame_in")
|
||||
frame_3d_start = shot["data"].get("3d_start")
|
||||
frame_3d_offset = frame_3d_start - addon_prefs.shot_builder_frame_offset
|
||||
edit_export_offset = addon_prefs.edit_export_frame_offset
|
||||
|
||||
# Set sequence strip start kitsu data.
|
||||
for strip in new_strips:
|
||||
strip.frame_start = (
|
||||
-frame_in + (strip_frame_start * 2) + frame_3d_offset + edit_export_offset
|
||||
)
|
||||
sound_strip = seq_editor.sequences.new_sound(
|
||||
latest_file.name,
|
||||
strip_filepath,
|
||||
strip_channel,
|
||||
strip_frame_start,
|
||||
)
|
||||
new_strips = [movie_strip, sound_strip]
|
||||
|
||||
# Update shift frame range prop.
|
||||
frame_in = shot["data"].get("frame_in")
|
||||
frame_3d_in = shot["data"].get("3d_in")
|
||||
frame_3d_offset = frame_3d_in - addon_prefs.shot_builder_frame_offset
|
||||
edit_export_offset = addon_prefs.edit_export_frame_offset
|
||||
|
||||
# Set sequence strip start kitsu data.
|
||||
for strip in new_strips:
|
||||
strip.frame_start = -frame_in + (strip_frame_start * 2) + frame_3d_offset + edit_export_offset
|
||||
return new_strips
|
||||
|
||||
return new_strips
|
||||
|
||||
|
||||
def editorial_export_check_latest(context: bpy.types.Context):
|
||||
@ -59,7 +63,10 @@ def editorial_export_check_latest(context: bpy.types.Context):
|
||||
files_list = [
|
||||
f
|
||||
for f in edit_export_path.iterdir()
|
||||
if f.is_file() and editorial_export_is_valid_edit_name(addon_prefs.edit_export_file_pattern, f.name)
|
||||
if f.is_file()
|
||||
and editorial_export_is_valid_edit_name(
|
||||
addon_prefs.edit_export_file_pattern, f.name
|
||||
)
|
||||
]
|
||||
if len(files_list) >= 1:
|
||||
files_list = sorted(files_list, reverse=True)
|
||||
@ -67,7 +74,7 @@ def editorial_export_check_latest(context: bpy.types.Context):
|
||||
return None
|
||||
|
||||
|
||||
def editorial_export_is_valid_edit_name(file_pattern:str, filename: str) -> bool:
|
||||
def editorial_export_is_valid_edit_name(file_pattern: str, filename: str) -> bool:
|
||||
"""Verify file name matches file pattern set in preferences"""
|
||||
match = re.search(file_pattern, filename)
|
||||
if match:
|
||||
|
@ -3,17 +3,18 @@ from typing import Set
|
||||
from blender_kitsu.shot_builder.editorial.core import editorial_export_get_latest
|
||||
from blender_kitsu import cache, gazu
|
||||
|
||||
|
||||
class ANIM_SETUP_OT_load_latest_editorial(bpy.types.Operator):
|
||||
bl_idname = "asset_setup.load_latest_editorial"
|
||||
bl_label = "Load Editorial Export"
|
||||
bl_description = (
|
||||
"Loads latest edit from shot_preview_folder "
|
||||
"Shifts edit so current shot starts at 3d_in metadata shot key from Kitsu"
|
||||
"Shifts edit so current shot starts at 3d_start metadata shot key from Kitsu"
|
||||
)
|
||||
|
||||
def execute(self, context: bpy.types.Context) -> Set[str]:
|
||||
cache_shot = cache.shot_active_get()
|
||||
shot = gazu.shot.get_shot(cache_shot.id) #TODO INEFFICENT TO LOAD SHOT TWICE
|
||||
shot = gazu.shot.get_shot(cache_shot.id) # TODO INEFFICENT TO LOAD SHOT TWICE
|
||||
strips = editorial_export_get_latest(context, shot)
|
||||
if strips is None:
|
||||
self.report(
|
||||
@ -24,6 +25,7 @@ class ANIM_SETUP_OT_load_latest_editorial(bpy.types.Operator):
|
||||
self.report({"INFO"}, f"Loaded latest edit: {strips[0].name}")
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
classes = [
|
||||
ANIM_SETUP_OT_load_latest_editorial,
|
||||
]
|
||||
@ -33,6 +35,7 @@ def register():
|
||||
for cls in classes:
|
||||
bpy.utils.register_class(cls)
|
||||
|
||||
|
||||
def unregister():
|
||||
for cls in classes:
|
||||
bpy.utils.unregister_class(cls)
|
@ -1866,22 +1866,22 @@ class KITSU_OT_sqe_pull_edit(bpy.types.Operator):
|
||||
def _apply_strip_slip_from_shot(
|
||||
self, context: bpy.types.Context, strip: bpy.types.Sequence, shot: Shot
|
||||
) -> None:
|
||||
if "3d_in" not in shot.data:
|
||||
if "3d_start" not in shot.data:
|
||||
logger.warning(
|
||||
"%s no update to frame_start_offset. '3d_in' key not in shot.data",
|
||||
"%s no update to frame_start_offset. '3d_start' key not in shot.data",
|
||||
shot.name,
|
||||
)
|
||||
return
|
||||
|
||||
if not shot.data["3d_in"]:
|
||||
if not shot.data["3d_start"]:
|
||||
logger.warning(
|
||||
"%s no update to frame_start_offset. '3d_in' key invalid value: %i",
|
||||
"%s no update to frame_start_offset. '3d_start' key invalid value: %i",
|
||||
shot.name,
|
||||
shot.data["3d_in"],
|
||||
shot.data["3d_start"],
|
||||
)
|
||||
return
|
||||
# get offset
|
||||
offset = strip.kitsu_frame_start - int(shot.data["3d_in"])
|
||||
offset = strip.kitsu_frame_start - int(shot.data["3d_start"])
|
||||
|
||||
# Deselect everything.
|
||||
if context.selected_sequences:
|
||||
|
@ -30,14 +30,11 @@ logger = LoggerFactory.getLogger()
|
||||
|
||||
|
||||
def shot_meta(strip: bpy.types.Sequence, shot: Shot) -> None:
|
||||
|
||||
# Update shot info.
|
||||
shot.name = strip.kitsu.shot_name
|
||||
shot.description = strip.kitsu.shot_description
|
||||
shot.data["frame_in"] = strip.frame_final_start
|
||||
shot.data["frame_out"] = strip.frame_final_end
|
||||
shot.data["3d_in"] = strip.kitsu_frame_start
|
||||
shot.data["3d_out"] = strip.kitsu_frame_end
|
||||
shot.nb_frames = strip.frame_final_duration
|
||||
shot.data["fps"] = bkglobals.FPS
|
||||
|
||||
@ -59,7 +56,6 @@ def new_shot(
|
||||
sequence: Sequence,
|
||||
project: Project,
|
||||
) -> Shot:
|
||||
|
||||
frame_range = (strip.frame_final_start, strip.frame_final_end)
|
||||
shot = project.create_shot(
|
||||
sequence,
|
||||
@ -69,8 +65,6 @@ def new_shot(
|
||||
frame_out=frame_range[1],
|
||||
data={
|
||||
"fps": bkglobals.FPS,
|
||||
"3d_in": strip.kitsu_frame_start,
|
||||
"3d_out": strip.kitsu_frame_end,
|
||||
},
|
||||
)
|
||||
# Update description, no option to pass that on create.
|
||||
|
Loading…
Reference in New Issue
Block a user