rewrite import_shots and cleanup
This commit is contained in:
+197
-27
@@ -1,4 +1,5 @@
|
||||
from os.path import expandvars
|
||||
from os.path import expandvars, abspath
|
||||
from pathlib import Path
|
||||
import bpy
|
||||
from bpy.types import Operator
|
||||
from bpy.props import (BoolProperty, StringProperty)
|
||||
@@ -7,6 +8,8 @@ from vse_toolbox.sequencer_utils import (get_strips, rename_strips, set_channels
|
||||
get_channel_index, new_text_strip, get_strip_at, get_channel_name)
|
||||
|
||||
from vse_toolbox.bl_utils import get_scene_settings, get_strip_settings
|
||||
from vse_toolbox.constants import REVIEW_TEMPLATE_BLEND
|
||||
from shutil import copy2
|
||||
|
||||
|
||||
class VSETB_OT_rename(Operator):
|
||||
@@ -17,8 +20,7 @@ class VSETB_OT_rename(Operator):
|
||||
|
||||
#template : StringProperty(name="Strip Name", default="")
|
||||
#increment : IntProperty(name="Increment", default=0)
|
||||
channel_name : StringProperty(name="Channel Name", default="")
|
||||
selected_only : BoolProperty(name="Selected Only", default=False)
|
||||
selected_only : BoolProperty(name="Selected Only", default=True)
|
||||
#start_number : IntProperty(name="Start Number", default=0, min=0)
|
||||
#by_sequence : BoolProperty(
|
||||
# name="Reset By Sequence",
|
||||
@@ -29,7 +31,8 @@ class VSETB_OT_rename(Operator):
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
settings = get_scene_settings()
|
||||
return settings.active_project
|
||||
strip = context.active_sequence_strip
|
||||
return settings.active_project and get_channel_name(strip) in ('Shots', 'Sequences')
|
||||
|
||||
def invoke(self, context, event):
|
||||
scn = context.scene
|
||||
@@ -43,39 +46,62 @@ class VSETB_OT_rename(Operator):
|
||||
settings = get_scene_settings()
|
||||
project = settings.active_project
|
||||
|
||||
episode = project.episode_name
|
||||
sequence = str(project.sequence_start_number).zfill(project.sequence_padding)
|
||||
shot = str(project.shot_start_number).zfill(project.shot_padding)
|
||||
|
||||
strip = context.active_sequence_strip
|
||||
channel_name = get_channel_name(strip)
|
||||
|
||||
col = layout.column()
|
||||
col.use_property_split = True
|
||||
col.use_property_decorate = False
|
||||
|
||||
if self.channel_name == 'Shots':
|
||||
if channel_name == 'Shots':
|
||||
col.prop(project, 'shot_template', text='Shot Name')
|
||||
col.prop(project, 'shot_start_number', text='Start Number')
|
||||
col.prop(project, 'shot_increment', text='Increment')
|
||||
col.prop(project, 'shot_padding', text='Padding')
|
||||
col.prop(project, 'reset_by_sequence')
|
||||
elif self.channel_name == 'Sequences':
|
||||
|
||||
|
||||
elif channel_name == 'Sequences':
|
||||
col.prop(project, 'sequence_template' ,text='Sequence Name')
|
||||
col.prop(project, 'sequence_start_number', text='Start Number')
|
||||
col.prop(project, 'sequence_increment', text='Increment')
|
||||
col.prop(project, 'sequence_padding', text='Padding')
|
||||
|
||||
col.prop(self, 'selected_only')
|
||||
|
||||
if channel_name == 'Shots':
|
||||
label = project.shot_template.format(episode=episode, sequence=sequence, shot=shot)
|
||||
elif channel_name == 'Sequences':
|
||||
label = project.sequence_template.format(episode=episode, sequence=sequence)
|
||||
|
||||
col.label(text=f'Renaming {label}')
|
||||
|
||||
def execute(self, context):
|
||||
scn = context.scene
|
||||
settings = get_scene_settings()
|
||||
project = settings.active_project
|
||||
|
||||
strips = get_strips(channel=self.channel_name, selected_only=self.selected_only)
|
||||
if self.channel_name == 'Shots':
|
||||
strip = context.active_sequence_strip
|
||||
channel_name = get_channel_name(strip)
|
||||
|
||||
strips = get_strips(channel=channel_name, selected_only=self.selected_only)
|
||||
if channel_name == 'Shots':
|
||||
rename_strips(strips,
|
||||
template=project.shot_template,
|
||||
increment=project.shot_increment, start_number=project.shot_start_number,
|
||||
by_sequence=project.reset_by_sequence
|
||||
by_sequence=project.reset_by_sequence,
|
||||
padding=project.shot_padding
|
||||
)
|
||||
|
||||
if self.channel_name == 'Sequences':
|
||||
if channel_name == 'Sequences':
|
||||
rename_strips(strips,
|
||||
template=project.sequence_template,
|
||||
increment=project.sequence_increment, start_number=project.sequence_start_number
|
||||
increment=project.sequence_increment, start_number=project.sequence_start_number,
|
||||
padding=project.sequence_padding
|
||||
)
|
||||
|
||||
return {"FINISHED"}
|
||||
@@ -180,10 +206,10 @@ class VSETB_OT_set_stamps(Operator):
|
||||
font_size=font_size, y=margin, box_margin=box_margin, select=True, box_color=(0, 0, 0, 0.5))
|
||||
|
||||
# Project Name
|
||||
project_text = '{project_name}'
|
||||
project_text = '{project}'
|
||||
if project.type == 'TVSHOW':
|
||||
project_text = '{project_name} / {episode_name}'
|
||||
project_strip_stamp = new_text_strip('project_name_stamp', channel=1, **stamp_params,
|
||||
project_text = '{project} / ep{episode}'
|
||||
project_strip_stamp = new_text_strip('project_stamp', channel=1, **stamp_params,
|
||||
text=project_text, x=0.01, align_x='LEFT', align_y='BOTTOM')
|
||||
|
||||
project_strip_stamp.crop.max_x = crop_x * 2
|
||||
@@ -191,16 +217,16 @@ class VSETB_OT_set_stamps(Operator):
|
||||
|
||||
# Shot Name
|
||||
|
||||
shot_strip_stamp = new_text_strip('shot_name_stamp', channel=2, **stamp_params,
|
||||
text='{sequence_name} / {shot_name}', align_y='BOTTOM')
|
||||
shot_strip_stamp = new_text_strip('shot_stamp', channel=2, **stamp_params,
|
||||
text='sq{sequence} / sh{shot}', align_y='BOTTOM')
|
||||
|
||||
shot_strip_stamp.crop.min_x = crop_x
|
||||
shot_strip_stamp.crop.max_x = crop_x
|
||||
shot_strip_stamp.crop.max_y = crop_max_y
|
||||
|
||||
# Frame Range
|
||||
frame_strip_stamp = new_text_strip('frame_range_stamp', channel=3, **stamp_params,
|
||||
text='{shot_frame} / {shot_duration}', x=0.99, align_x='RIGHT', align_y='BOTTOM')
|
||||
# Frame
|
||||
frame_strip_stamp = new_text_strip('frame_stamp', channel=3, **stamp_params,
|
||||
text='{shot_frame} / {shot_duration} {timecode}', x=0.99, align_x='RIGHT', align_y='BOTTOM')
|
||||
|
||||
frame_strip_stamp.crop.min_x = crop_x *2
|
||||
frame_strip_stamp.crop.max_y = crop_max_y
|
||||
@@ -269,10 +295,11 @@ class VSETB_OT_next_shot(Operator):
|
||||
|
||||
return {"FINISHED"}
|
||||
|
||||
class VSETB_OT_open_shot_dir(Operator):
|
||||
bl_idname = "vse_toolbox.open_shot_dir"
|
||||
bl_label = "Open Shot Dir"
|
||||
bl_description = "Open Shot Dir"
|
||||
|
||||
class VSETB_OT_open_shot_folder(Operator):
|
||||
bl_idname = "vse_toolbox.open_shot_folder"
|
||||
bl_label = "Open Shot Folder"
|
||||
bl_description = "Open Shot Folder"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
@classmethod
|
||||
@@ -289,13 +316,154 @@ class VSETB_OT_open_shot_dir(Operator):
|
||||
|
||||
format_data = {**settings.format_data, **project.format_data, **strip_settings.format_data}
|
||||
|
||||
shot_dir_template = expandvars(project.shot_dir_template)
|
||||
shot_dir_path = shot_dir_template.format(**format_data)
|
||||
bpy.ops.wm.path_open(filepath=shot_dir_path)
|
||||
shot_folder_template = expandvars(project.import_shots.shot_folder_template)
|
||||
shot_folder_path = shot_folder_template.format(**format_data)
|
||||
bpy.ops.wm.path_open(filepath=shot_folder_path)
|
||||
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class VSETB_OT_collect_files(Operator):
|
||||
bl_idname = "vse_toolbox.collect_files"
|
||||
bl_label = "Collect Files"
|
||||
bl_description = "Collect Files"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
collect_folder: StringProperty(
|
||||
name="Collect Folder", default="//sources", subtype='DIR_PATH')
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if bpy.data.is_saved:
|
||||
return True
|
||||
|
||||
cls.poll_message_set('Save the blend to collect files')
|
||||
|
||||
def execute(self, context):
|
||||
strip = context.active_sequence_strip
|
||||
settings = get_scene_settings()
|
||||
project = settings.active_project
|
||||
|
||||
|
||||
strips = [s for s in context.scene.sequence_editor.sequences_all if s.type in ('MOVIE', 'SOUND')]
|
||||
context.window_manager.progress_begin(0, len(strips))
|
||||
|
||||
for i, strip in enumerate(strips):
|
||||
context.window_manager.progress_update(i)
|
||||
|
||||
if strip.type == 'MOVIE':
|
||||
src_path = strip.filepath
|
||||
elif strip.type == 'SOUND':
|
||||
src_path = strip.sound.filepath
|
||||
|
||||
src_path = Path(abspath(bpy.path.abspath(src_path)))
|
||||
dst_path = Path(bpy.path.abspath(self.collect_folder), src_path.name)
|
||||
|
||||
if src_path == dst_path:
|
||||
continue
|
||||
|
||||
dst_path.parent.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
print(f'Copy file from {src_path} to {dst_path}')
|
||||
copy2(str(src_path), str(dst_path))
|
||||
|
||||
rel_path = bpy.path.relpath(str(dst_path))
|
||||
if len(Path(rel_path).as_posix()) < len(dst_path.as_posix()):
|
||||
dst_path = rel_path
|
||||
|
||||
if strip.type == 'MOVIE':
|
||||
strip.filepath = str(dst_path)
|
||||
elif strip.type == 'SOUND':
|
||||
strip.sound.filepath = str(dst_path)
|
||||
|
||||
context.window_manager.progress_end()
|
||||
|
||||
return {"FINISHED"}
|
||||
|
||||
def invoke(self, context, event):
|
||||
scn = context.scene
|
||||
settings = get_scene_settings()
|
||||
|
||||
return context.window_manager.invoke_props_dialog(self)
|
||||
|
||||
|
||||
class WM_OT_split_view(Operator):
|
||||
"""Toggle Split sequencer view"""
|
||||
|
||||
bl_idname = "wm.split_view"
|
||||
bl_label = "Split View"
|
||||
|
||||
def get_preview_areas(self, context):
|
||||
return [
|
||||
x for x in context.screen.areas
|
||||
if x.type == "SEQUENCE_EDITOR" and x.spaces[0].view_type == "PREVIEW"
|
||||
]
|
||||
|
||||
def invoke(self, context, event):
|
||||
preview_areas = self.get_preview_areas(context)
|
||||
|
||||
if not preview_areas:
|
||||
return {"CANCELLED"}
|
||||
|
||||
scn = context.scene
|
||||
video_channels = [i for i, c in enumerate(scn.sequence_editor.channels) if 'Video' in c.name]
|
||||
|
||||
if len(video_channels) == 2 and len(preview_areas) == 1:
|
||||
# Split area
|
||||
with bpy.context.temp_override(area=preview_areas[0]):
|
||||
bpy.ops.screen.area_split(direction="VERTICAL")
|
||||
|
||||
# Disable toolbar on right panel
|
||||
# Update areas
|
||||
preview_areas = self.get_preview_areas(context)
|
||||
|
||||
preview_areas[-1].spaces[0].display_channel = video_channels[-1]
|
||||
preview_areas[0].spaces[0].display_channel = video_channels[-2]
|
||||
|
||||
preview_areas[0].spaces[0].show_gizmo_navigate = False
|
||||
preview_areas[-1].spaces[0].show_gizmo_navigate = False
|
||||
# Hide toolbar
|
||||
#preview_areas[0].spaces[0].show_region_toolbar = False
|
||||
|
||||
else:
|
||||
# Give the remaining area to have the left area's channel displayed
|
||||
|
||||
# Show toolbar of remaning area
|
||||
#preview_areas[0].spaces[0].show_region_toolbar = True
|
||||
|
||||
# Join areas
|
||||
# Simulates the mouse position as being between the two areas horizontally
|
||||
# and a bit above the bottom corner vertically
|
||||
cursor_x = int(preview_areas[0].x - (preview_areas[0].x - preview_areas[1].width) / 2)
|
||||
cursor_y = preview_areas[0].y + 10
|
||||
|
||||
bpy.ops.screen.area_join(cursor=(cursor_x, cursor_y))
|
||||
|
||||
preview_areas = self.get_preview_areas(context)
|
||||
|
||||
preview_areas[0].spaces[0].display_channel = 0
|
||||
|
||||
# Force UI update, due to Blender bug, delete when fixed -> https://developer.blender.org/T65529
|
||||
bpy.ops.screen.area_swap(cursor=(preview_areas[0].x, preview_areas[0].y))
|
||||
bpy.ops.screen.area_swap(cursor=(preview_areas[0].x, preview_areas[0].y))
|
||||
|
||||
return {"FINISHED"}
|
||||
|
||||
'''
|
||||
class VSETB_OT_set_review_workspace(Operator):
|
||||
"""Set Review Workspace"""
|
||||
|
||||
bl_idname = "vse_toolbox.set_workspace"
|
||||
bl_label = "Set Review Workspace"
|
||||
|
||||
|
||||
def execute(self, context):
|
||||
bpy.ops.workspace.append_activate(idname='Review', filepath=str(REVIEW_TEMPLATE_BLEND))
|
||||
|
||||
return {"FINISHED"}
|
||||
'''
|
||||
|
||||
|
||||
addon_keymaps = []
|
||||
def register_keymaps():
|
||||
addon = bpy.context.window_manager.keyconfigs.addon
|
||||
@@ -331,7 +499,9 @@ classes = (
|
||||
VSETB_OT_show_waveform,
|
||||
VSETB_OT_previous_shot,
|
||||
VSETB_OT_next_shot,
|
||||
VSETB_OT_open_shot_dir
|
||||
VSETB_OT_open_shot_folder,
|
||||
VSETB_OT_collect_files,
|
||||
WM_OT_split_view
|
||||
)
|
||||
|
||||
def register():
|
||||
|
||||
Reference in New Issue
Block a user