1424 lines
47 KiB
Python
1424 lines
47 KiB
Python
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
import importlib
|
|
import json
|
|
import re
|
|
import time
|
|
from pprint import pprint
|
|
import csv
|
|
from datetime import datetime
|
|
import os
|
|
from pathlib import Path
|
|
|
|
import bpy
|
|
from bpy.types import (Operator, Menu)
|
|
from bpy_extras.io_utils import ImportHelper
|
|
from bpy.props import (CollectionProperty, BoolProperty, EnumProperty,
|
|
IntProperty, StringProperty)
|
|
from bpy.types import PropertyGroup
|
|
from bl_operators.presets import AddPresetBase
|
|
|
|
import vse_toolbox
|
|
|
|
from vse_toolbox.constants import (ASSET_PREVIEWS, CASTING_BUFFER, CONFIG_DIR,
|
|
EDITS, EDIT_SUFFIXES, MOVIES, MOVIE_SUFFIXES, PREVIEWS_DIR, SOUNDS,
|
|
SOUND_SUFFIXES, TASK_ITEMS)
|
|
|
|
from vse_toolbox.sequencer_utils import (clean_sequencer, get_strips, set_active_strip,
|
|
import_edit, import_movie, import_sound, rename_strips, render_strips, set_channels,
|
|
get_channel_index, new_text_strip, get_strip_render_path, get_strip_sequence_name)
|
|
|
|
from vse_toolbox.bl_utils import (get_addon_prefs, get_scene_settings, get_strip_settings)
|
|
from vse_toolbox.file_utils import (install_module, norm_name, norm_str, open_file, read_file)
|
|
|
|
|
|
class VSETB_OT_tracker_connect(Operator):
|
|
bl_idname = "vse_toolbox.tracker_connect"
|
|
bl_label = "Connect to Tracker"
|
|
bl_description = "Connect to Tracker"
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
prefs = get_addon_prefs()
|
|
if prefs.tracker:
|
|
|
|
return True
|
|
|
|
def execute(self, context):
|
|
prefs = get_addon_prefs()
|
|
settings = get_scene_settings()
|
|
try:
|
|
prefs.tracker.connect()
|
|
self.report({'INFO'}, f'Sucessfully login to {settings.tracker_name.title()}')
|
|
return {"FINISHED"}
|
|
except Exception as e:
|
|
print('e: ', e)
|
|
self.report({'ERROR'}, f'Cannot connect to tracker.')
|
|
return {"CANCELLED"}
|
|
|
|
|
|
class VSETB_OT_copy_metadata(Operator):
|
|
bl_idname = "vse_toolbox.copy_metadata"
|
|
bl_label = "Copy metadata to selected"
|
|
bl_description = "Copy Metadata to selected strips"
|
|
|
|
metadata : StringProperty()
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
return context.selected_sequences and context.active_sequence_strip
|
|
|
|
def execute(self, context):
|
|
prefs = get_addon_prefs()
|
|
settings = get_scene_settings()
|
|
project = settings.active_project
|
|
|
|
metadata = next((m.field_name for m in project.metadata_types if m.name == self.metadata), None)
|
|
|
|
if not metadata:
|
|
self.report({'ERROR'}, f'No Metadata named {self.metadata}')
|
|
|
|
active_strip = context.active_sequence_strip
|
|
metadata_value = getattr(active_strip.vsetb_strip_settings.metadata, metadata)
|
|
|
|
for strip in context.selected_sequences:
|
|
if strip == context.active_sequence_strip:
|
|
continue
|
|
|
|
setattr(strip.vsetb_strip_settings.metadata, metadata, metadata_value)
|
|
|
|
return {"FINISHED"}
|
|
|
|
|
|
class VSETB_OT_export_spreadsheet(Operator):
|
|
bl_idname = "vse_toolbox.export_spreadsheet"
|
|
bl_label = "Export Spreadsheet"
|
|
bl_description = "Export Shot data in a table as a csv or an xlsl"
|
|
bl_options = {"REGISTER", "UNDO"}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
settings = get_scene_settings()
|
|
return settings.active_project
|
|
|
|
def invoke(self, context, event):
|
|
settings = get_scene_settings()
|
|
project = settings.active_project
|
|
|
|
return context.window_manager.invoke_props_dialog(self)
|
|
|
|
def draw(self, context):
|
|
scn = context.scene
|
|
settings = get_scene_settings()
|
|
project = settings.active_project
|
|
options = project.spreadsheet_options
|
|
|
|
layout = self.layout
|
|
|
|
row = layout.row()
|
|
row.template_list("VSETB_UL_spreadsheet", "spreadsheet", project, "spreadsheet", project, "spreadsheet_index", rows=8)
|
|
|
|
col_tool = row.column(align=True)
|
|
|
|
#bpy.types.VSETB_PT_presets.draw_panel_header(col_tool)
|
|
#col_tool.operator('wm.call_menu', icon="PRESET").name = 'VSETB_MT_spreadsheet_presets'
|
|
#col_tool.operator('vse_toolbox.load_spreadsheet_preset', icon='PRESET', text="")
|
|
op = col_tool.operator('wm.call_panel', icon="PRESET", emboss=False, text='')
|
|
op.name = 'VSETB_PT_presets'
|
|
op.keep_open = False
|
|
|
|
col_tool.separator()
|
|
col_tool.operator('vse_toolbox.spreadsheet_move', icon='TRIA_UP', text="").direction = 'UP'
|
|
col_tool.operator('vse_toolbox.spreadsheet_move', icon='TRIA_DOWN', text="").direction = 'DOWN'
|
|
|
|
col = layout.column()
|
|
col.use_property_split = True
|
|
|
|
row = col.row(align=True, heading='Custom Name')
|
|
#row.use_property_split = True
|
|
row.prop(options, 'use_custom_name', text='')
|
|
sub = row.row(align=True)
|
|
sub.enabled = options.use_custom_name
|
|
sub.prop(options, 'custom_name', text='')
|
|
|
|
col.separator()
|
|
|
|
row = col.row(align=False)
|
|
row.prop(options, "format", expand=True, text='Format')
|
|
row.prop(options, 'show_settings', text='', icon='PREFERENCES')
|
|
if options.show_settings:
|
|
col.prop(options, "separator", expand=True, text='Separator')
|
|
if options.format == 'CSV':
|
|
col.prop(options, "delimiter", expand=True, text='Delimiter')
|
|
|
|
col.separator()
|
|
col.prop(options, 'open_folder', text='Open Folder')
|
|
col.prop(options, 'export_path', text='Export Path')
|
|
|
|
def execute(self, context):
|
|
#self.report({'ERROR'}, f'Export not implemented yet.')
|
|
prefs = get_addon_prefs()
|
|
settings = get_scene_settings()
|
|
project = settings.active_project
|
|
options = project.spreadsheet_options
|
|
episode = settings.active_episode
|
|
|
|
cells = [cell for cell in project.spreadsheet if cell.enabled]
|
|
rows = []
|
|
|
|
# Header
|
|
rows.append([cell.export_name for cell in cells])
|
|
|
|
separator = options.separator.replace('\\n', '\n').replace('\\t', '\t').replace('\\r', '\r')
|
|
delimiter = options.delimiter.replace('\\n', '\n').replace('\\t', '\t').replace('\\r', '\r')
|
|
|
|
for strip in get_strips('Shots'):
|
|
row = []
|
|
for cell in cells:
|
|
if cell.type == "METADATA":
|
|
row += [getattr(strip.vsetb_strip_settings.metadata, cell.field_name)]
|
|
elif cell.type == "ASSET_TYPE":
|
|
asset_castings = []
|
|
for asset_casting in strip.vsetb_strip_settings.casting:
|
|
asset = asset_casting.asset
|
|
if not asset.asset_type == cell.name:
|
|
continue
|
|
|
|
if options.use_custom_name:
|
|
if asset.get('metadata', {}).get(options.custom_name):
|
|
asset_castings.append(asset['metadata'][options.custom_name])
|
|
else:
|
|
self.report({'ERROR'}, f'The asset {asset.tracker_name} has no data {options.custom_name}')
|
|
else:
|
|
asset_castings.append(asset.tracker_name)
|
|
|
|
row += [separator.join(asset_castings)]
|
|
elif cell.field_name == 'EPISODE':
|
|
row += [settings.active_episode.name]
|
|
elif cell.field_name == 'SEQUENCE':
|
|
row += [get_strip_sequence_name(strip)]
|
|
elif cell.field_name == 'SHOT':
|
|
row += [strip.name]
|
|
elif cell.field_name == 'DESCRIPTION':
|
|
row += [strip.vsetb_strip_settings.description]
|
|
elif cell.field_name == 'FRAMES':
|
|
row += [strip.frame_final_duration]
|
|
|
|
rows.append(row)
|
|
|
|
#print(rows)
|
|
|
|
export_path = Path(os.path.abspath(bpy.path.abspath(options.export_path)))
|
|
export_name = export_path.name
|
|
|
|
if export_path.suffix or export_name.endswith('{ext}'):
|
|
export_path = export_path.parent
|
|
|
|
else: # It's a directory
|
|
if project.type == 'TVSHOW':
|
|
export_name = '{date}_{project}_{episode}_{tracker}_shots.{ext}'
|
|
else:
|
|
export_name = '{date}_{project}_{tracker}_shots.{ext}'
|
|
|
|
date = datetime.now().strftime('%Y_%m_%d')
|
|
project_name = project.name.replace(' ', '_').lower()
|
|
episode_name = episode.name.replace(' ', '_').lower() if episode else 'episode'
|
|
ext = options.format.lower()
|
|
|
|
export_name = export_name.format(date=date, project=project_name,
|
|
episode=episode_name, tracker=settings.tracker_name.lower(), ext=ext)
|
|
|
|
export_path = export_path / export_name
|
|
|
|
#2023_04_11_kitsu_boris_ep01_shots
|
|
export_path.parent.mkdir(parents=True, exist_ok=True)
|
|
|
|
if options.format == 'CSV':
|
|
print('Writing .csv file to', export_path)
|
|
with open(str(export_path), 'w', newline='\n', encoding='utf-8') as f:
|
|
writer = csv.writer(f, delimiter=options.delimiter)
|
|
for row in rows:
|
|
writer.writerow(row)
|
|
|
|
elif options.format == 'XLSX':
|
|
try:
|
|
import openpyxl
|
|
except ModuleNotFoundError:
|
|
self.report({'INFO'}, 'Installing openpyxl')
|
|
openpyxl = install_module('openpyxl')
|
|
|
|
from openpyxl import Workbook
|
|
|
|
workbook = Workbook()
|
|
worksheet = workbook.active
|
|
for row in rows:
|
|
worksheet.append(row)
|
|
|
|
for col in worksheet.columns:
|
|
letter = col[0].column_letter
|
|
worksheet.column_dimensions[letter].auto_size = True
|
|
|
|
# Save the file
|
|
workbook.save(str(export_path))
|
|
|
|
if options.open_folder:
|
|
open_file(export_path, select=True)
|
|
|
|
|
|
return {"FINISHED"}
|
|
|
|
|
|
def get_task_status_items(self, context):
|
|
settings = get_scene_settings()
|
|
project = settings.active_project
|
|
|
|
status_items = [('CURRENT', 'Current', '')]
|
|
|
|
if project:
|
|
status_items += [(t.name, t.name, '') for t in project.task_statuses]
|
|
return status_items
|
|
|
|
def get_task_type_items(self, context):
|
|
settings = get_scene_settings()
|
|
project = settings.active_project
|
|
|
|
if not project:
|
|
return [('NONE', 'None', '')]
|
|
|
|
return [(t.name, t.name, '') for t in project.task_types]
|
|
|
|
class VSETB_OT_upload_to_tracker(Operator):
|
|
bl_idname = "vse_toolbox.upload_to_tracker"
|
|
bl_label = "Upload to tracker"
|
|
bl_description = "Upload selected strip to tracker"
|
|
bl_options = {"REGISTER", "UNDO"}
|
|
|
|
task : EnumProperty(items=get_task_type_items)
|
|
status : EnumProperty(items=get_task_status_items)
|
|
comment : StringProperty()
|
|
add_preview : BoolProperty(default=True)
|
|
preview_mode : EnumProperty(items=[(m, m.title().replace('_', ' '), '')
|
|
for m in ('ONLY_NEW', 'REPLACE', 'ADD')])
|
|
set_main_preview : BoolProperty(default=True)
|
|
casting : BoolProperty(default=True)
|
|
custom_data : BoolProperty(default=True)
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
return True
|
|
|
|
def invoke(self, context, event):
|
|
prefs = get_addon_prefs()
|
|
settings = get_scene_settings()
|
|
project = settings.active_project
|
|
|
|
tracker = prefs.tracker
|
|
tracker.connect()
|
|
|
|
#self.bl_label = f"Upload to {settings.tracker_name.title()}"
|
|
|
|
return context.window_manager.invoke_props_dialog(self)
|
|
|
|
def draw(self, context):
|
|
scn = context.scene
|
|
settings = get_scene_settings()
|
|
|
|
layout = self.layout
|
|
col = layout.column()
|
|
col.use_property_split = True
|
|
col.prop(self, 'task', text='Task')
|
|
col.prop(self, 'status', text='Status')
|
|
col.prop(self, 'comment', text='Comment')
|
|
row = col.row(heading='Add Preview')
|
|
row.prop(self, 'add_preview', text='')
|
|
row.prop(self, 'preview_mode', text='')
|
|
col.separator()
|
|
col.prop(self, 'casting', text='Casting')
|
|
col.prop(self, 'custom_data', text='Custom Data')
|
|
|
|
def execute(self, context):
|
|
#self.report({'ERROR'}, f'Export not implemented yet.')
|
|
prefs = get_addon_prefs()
|
|
settings = get_scene_settings()
|
|
project = settings.active_project
|
|
episode = None
|
|
if settings.active_episode:
|
|
episode = settings.active_episode.id
|
|
|
|
|
|
tracker = prefs.tracker
|
|
|
|
status = self.status
|
|
if status == 'CURRENT':
|
|
status = None
|
|
|
|
for strip in get_strips(channel='Shots', selected_only=True):
|
|
sequence_name = get_strip_sequence_name(strip)
|
|
shot_name = strip.name
|
|
sequence = tracker.get_sequence(sequence_name, episode=episode)
|
|
metadata = strip.vsetb_strip_settings.metadata.to_dict()
|
|
#print(metadata)
|
|
|
|
if not sequence:
|
|
self.report({"INFO"}, f'Create sequence {sequence_name} in Kitsu')
|
|
sequence = tracker.new_sequence(sequence_name, episode=episode)
|
|
|
|
shot = tracker.get_shot(shot_name, sequence=sequence)
|
|
if not shot:
|
|
self.report({"INFO"}, f'Create shot {shot_name} in Kitsu')
|
|
shot = tracker.new_shot(shot_name, sequence=sequence)
|
|
|
|
task = tracker.get_task(self.task, entity=shot)
|
|
if not task:
|
|
task = tracker.new_task(shot, task_type=self.task)
|
|
|
|
# print('\n', 'task comment')
|
|
# print(task['last_comment'])
|
|
|
|
preview = None
|
|
if self.add_preview:
|
|
preview = Path(get_strip_render_path(strip, project.render_template))
|
|
#print(preview)
|
|
if not preview.exists():
|
|
print(f'The preview {preview} not exists')
|
|
preview = None
|
|
|
|
elif task.get('last_comment') and task['last_comment']['previews']:
|
|
if self.preview_mode == 'REPLACE':
|
|
tracker.remove_comment(task['last_comment'])
|
|
elif self.preview_mode == 'ONLY_NEW':
|
|
preview = None
|
|
|
|
#print(f'{preview=}')
|
|
#print(f'{status=}')
|
|
if status or preview:
|
|
tracker.new_comment(task, comment=self.comment, status=status, preview=preview, set_main_preview=self.set_main_preview)
|
|
|
|
if self.custom_data:
|
|
metadata = strip.vsetb_strip_settings.metadata.to_dict()
|
|
description = strip.vsetb_strip_settings.description
|
|
tracker.update_data(shot, metadata, frames=strip.frame_final_duration, description=description)
|
|
|
|
if self.casting:
|
|
casting = [{'asset_id': a.id, 'nb_occurences': a.instance} for a in strip.vsetb_strip_settings.casting]
|
|
tracker.update_casting(shot, casting)
|
|
|
|
|
|
return {"FINISHED"}
|
|
|
|
|
|
class VSETB_OT_auto_select_files(Operator):
|
|
bl_idname = "import.auto_select_files"
|
|
bl_label = "Auto Select"
|
|
bl_description = "Auto Select Files"
|
|
bl_options = {"REGISTER", "UNDO"}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
return True
|
|
|
|
def get_items(self, items=[]):
|
|
if not items:
|
|
return [('NONE', 'None', '', 0)]
|
|
return [(e, e, '', i) for i, e in enumerate(sorted(items))]
|
|
|
|
def execute(self, context):
|
|
params = context.space_data.params
|
|
directory = Path(params.directory.decode())
|
|
|
|
EDITS.clear()
|
|
MOVIES.clear()
|
|
SOUNDS.clear()
|
|
|
|
edits = []
|
|
movies = []
|
|
sounds = []
|
|
|
|
for file_entry in directory.glob('*'):
|
|
if file_entry.is_dir():
|
|
continue
|
|
|
|
if file_entry.suffix in EDIT_SUFFIXES:
|
|
edits.append(file_entry.name)
|
|
elif file_entry.suffix in MOVIE_SUFFIXES:
|
|
movies.append(file_entry.name)
|
|
elif file_entry.suffix in SOUND_SUFFIXES:
|
|
sounds.append(file_entry.name)
|
|
|
|
EDITS.extend(self.get_items(items=edits))
|
|
MOVIES.extend(self.get_items(items=movies))
|
|
SOUNDS.extend(self.get_items(items=sounds))
|
|
|
|
return {'FINISHED'}
|
|
|
|
|
|
class VSETB_OT_import_files(Operator):
|
|
bl_idname = "vse_toolbox.import_files"
|
|
bl_label = "Import"
|
|
bl_description = "Import Edit"
|
|
bl_options = {"REGISTER", "UNDO"}
|
|
|
|
directory : StringProperty(subtype='DIR_PATH')
|
|
filepath: StringProperty(
|
|
name="File Path",
|
|
description="Filepath used for importing the file",
|
|
maxlen=1024,
|
|
subtype='FILE_PATH',
|
|
)
|
|
files : CollectionProperty(type=bpy.types.OperatorFileListElement)
|
|
clean_sequencer : BoolProperty(
|
|
name="Clean Sequencer",
|
|
default=False,
|
|
description="Clean all existing strips in sequencer",
|
|
)
|
|
|
|
import_edit : BoolProperty(name='', default=True)
|
|
edit: EnumProperty(name='', items=lambda s, c: EDITS)
|
|
|
|
import_movie : BoolProperty(name='', default=False)
|
|
movie: EnumProperty(name='', items=lambda s, c: MOVIES)
|
|
|
|
import_sound : BoolProperty(name='', default=False)
|
|
sound: EnumProperty(name='', items=lambda s, c: SOUNDS)
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
return True
|
|
|
|
def draw(self, context):
|
|
scn = context.scene
|
|
settings = get_scene_settings()
|
|
|
|
layout = self.layout
|
|
layout.use_property_split = True
|
|
layout.use_property_decorate = False
|
|
|
|
col = layout.column(align=True)
|
|
col.operator('import.auto_select_files', text='Auto Select')
|
|
|
|
row = self.layout.row(heading="Import Edit", align=True)
|
|
row.prop(self, 'import_edit')
|
|
sub = row.row(align=True)
|
|
sub.active = self.import_edit
|
|
sub.prop(self, 'edit')
|
|
|
|
row = self.layout.row(heading="Import Movie", align=True)
|
|
row.prop(self, 'import_movie')
|
|
sub = row.row()
|
|
sub.active = self.import_movie
|
|
sub.prop(self, 'movie')
|
|
|
|
row = self.layout.row(heading="Import Sound", align=True)
|
|
row.prop(self, 'import_sound')
|
|
sub = row.row()
|
|
sub.active = self.import_sound
|
|
sub.prop(self, 'sound')
|
|
|
|
col = layout.column()
|
|
col.separator()
|
|
col.prop(self, 'clean_sequencer')
|
|
|
|
def invoke(self, context, event):
|
|
context.window_manager.fileselect_add(self)
|
|
return {'RUNNING_MODAL'}
|
|
|
|
def execute(self, context):
|
|
otio = install_module('opentimelineio')
|
|
|
|
edit_filepath = Path(self.directory, self.edit)
|
|
if not edit_filepath.exists():
|
|
self.import_edit = False
|
|
|
|
movie_filepath = Path(self.directory, self.movie)
|
|
if not movie_filepath.exists():
|
|
self.import_movie = False
|
|
|
|
sound_filepath = Path(self.directory, self.sound)
|
|
if not sound_filepath.exists():
|
|
self.import_sound = False
|
|
|
|
if self.clean_sequencer:
|
|
clean_sequencer(
|
|
edit=self.import_edit,
|
|
movie=self.import_movie,
|
|
sound=self.import_sound,
|
|
)
|
|
|
|
if self.import_edit:
|
|
print(f'[>.] Loading Edit from: {str(edit_filepath)}')
|
|
import_edit(edit_filepath, adapter="cmx_3600")
|
|
|
|
if self.import_movie:
|
|
print(f'[>.] Loading Movie from: {str(movie_filepath)}')
|
|
import_movie(movie_filepath)
|
|
|
|
if self.import_sound:
|
|
print(f'[>.] Loading Audio from: {str(sound_filepath)}')
|
|
import_sound(sound_filepath)
|
|
elif not self.import_sound and self.import_movie:
|
|
print(f'[>.] Loading Audio from Movie: {str(movie_filepath)}')
|
|
import_sound(movie_filepath)
|
|
|
|
context.scene.sequence_editor.sequences.update()
|
|
|
|
return {"FINISHED"}
|
|
|
|
|
|
class VSETB_OT_load_assets(Operator):
|
|
bl_idname = "vse_toolbox.load_assets"
|
|
bl_label = "Load Assets for current projects"
|
|
bl_description = "Load Assets"
|
|
bl_options = {"REGISTER", "UNDO"}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
settings = get_scene_settings()
|
|
if settings.active_project:
|
|
return True
|
|
|
|
def execute(self, context):
|
|
settings = get_scene_settings()
|
|
prefs = get_addon_prefs()
|
|
tracker = prefs.tracker
|
|
|
|
tracker.connect()
|
|
project = settings.active_project
|
|
project.assets.clear()
|
|
|
|
assets = tracker.get_assets(project['id'])
|
|
if not assets:
|
|
self.report({'ERROR'}, f'No Assets found for {project.name}.')
|
|
|
|
for asset_data in assets:
|
|
asset = project.assets.add()
|
|
|
|
asset.name = asset_data['id']
|
|
asset.norm_name = norm_name(asset_data['name'], separator=' ', format=str.lower)
|
|
|
|
asset.tracker_name = asset_data['name']
|
|
asset.id = asset_data['id']
|
|
asset.asset_type = asset_data['asset_type']
|
|
|
|
#for key, value in asset_data.get('data', {}).items():
|
|
asset['metadata'] = asset_data.get('data', {})
|
|
|
|
preview_id = asset_data.get('preview_file_id')
|
|
if preview_id:
|
|
asset.preview = preview_id
|
|
preview_path = Path(PREVIEWS_DIR / project.id / preview_id).with_suffix('.png')
|
|
tracker.download_preview(preview_id, preview_path)
|
|
|
|
if preview_id not in ASSET_PREVIEWS:
|
|
ASSET_PREVIEWS.load(preview_id, preview_path.as_posix(), 'IMAGE', True)
|
|
|
|
|
|
self.report({'INFO'}, f'Assets for {project.name} successfully loaded')
|
|
return {"FINISHED"}
|
|
|
|
|
|
class VSETB_OT_load_projects(Operator):
|
|
bl_idname = "vse_toolbox.load_projects"
|
|
bl_label = "Load Projects"
|
|
bl_description = "Load Projects"
|
|
bl_options = {"REGISTER", "UNDO"}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
return True
|
|
|
|
def execute(self, context):
|
|
settings = get_scene_settings()
|
|
prefs = get_addon_prefs()
|
|
tracker = prefs.tracker
|
|
|
|
old_project_name = settings.project_name.replace(' ', '_').upper()
|
|
|
|
settings.projects.clear()
|
|
tracker.connect()
|
|
|
|
for project_data in tracker.get_projects():
|
|
project = settings.projects.add()
|
|
project.type = project_data['production_type'].upper().replace(' ', '')
|
|
project.name = project_data['name']
|
|
project.id = project_data['id']
|
|
|
|
if project.type == 'TVSHOW':
|
|
for episode_data in tracker.get_episodes(project_data):
|
|
episode = project.episodes.add()
|
|
episode.name = episode_data['name']
|
|
episode.id = episode_data['id']
|
|
|
|
for metadata_data in tracker.get_metadata_types(project_data):
|
|
#pprint(metadata_data)
|
|
metadata_type = project.metadata_types.add()
|
|
metadata_type.name = metadata_data['name']
|
|
metadata_type.field_name = metadata_data['field_name']
|
|
#metadata_type['choices'] = metadata_data['choices']
|
|
|
|
if prefs.sort_metadata_items:
|
|
metadata_data['choices'].sort()
|
|
|
|
for choice in metadata_data['choices']:
|
|
choice_item = metadata_type.choices.add()
|
|
choice_item.name = choice
|
|
|
|
metadata_type['entity_type'] = metadata_data['entity_type'].upper()
|
|
|
|
for status_data in tracker.get_task_statuses(project_data):
|
|
#print(metadata_data)
|
|
task_status = project.task_statuses.add()
|
|
task_status.name = status_data['short_name'].upper()
|
|
|
|
for task_type_data in tracker.get_shot_task_types(project_data):
|
|
task_type = project.task_types.add()
|
|
task_type.name = task_type_data['name']
|
|
|
|
for asset_type_data in tracker.get_asset_types(project_data):
|
|
asset_type = project.asset_types.add()
|
|
asset_type.name = asset_type_data['name']
|
|
|
|
project.set_spreadsheet()
|
|
|
|
for project in settings.projects:
|
|
if project.name.replace(' ', '_').upper() == old_project_name:
|
|
settings.project_name = project.name
|
|
|
|
load_settings()
|
|
#else:
|
|
# print('Could Not restore Project Name')
|
|
|
|
#if settings.active_project:
|
|
# settings.active_project.set_strip_metadata()
|
|
|
|
#bpy.ops.vse_toolbox.load_assets()
|
|
|
|
self.report({"INFO"}, 'Successfully Load Tracker Projects')
|
|
|
|
return {'FINISHED'}
|
|
|
|
|
|
class VSETB_OT_new_episode(Operator):
|
|
bl_idname = "vse_toolbox.new_episode"
|
|
bl_label = "New Epispde"
|
|
bl_description = "Add new Episode to Project"
|
|
bl_options = {"REGISTER", "UNDO"}
|
|
|
|
episode_name : StringProperty(name="Episode Name", default="")
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
return True
|
|
|
|
def invoke(self, context, event):
|
|
scn = context.scene
|
|
settings = get_scene_settings()
|
|
|
|
return context.window_manager.invoke_props_dialog(self)
|
|
|
|
def execute(self, context):
|
|
settings = get_scene_settings()
|
|
prefs = get_addon_prefs()
|
|
tracker = prefs.tracker
|
|
|
|
episode_name = settings.episode_template.format(index=int(self.episode_name))
|
|
|
|
#print(self.episode_name)
|
|
#print('episode_name: ', episode_name)
|
|
|
|
episode = tracker.get_episode(episode_name)
|
|
if episode:
|
|
self.report({'ERROR'}, f'Episode {episode_name} already exists')
|
|
return {"CANCELLED"}
|
|
|
|
tracker.new_episode(episode_name)
|
|
# tracker.get_episodes
|
|
tracker.update_project()
|
|
self.report({'INFO'}, f'Episode {episode_name} successfully created')
|
|
return {'FINISHED'}
|
|
|
|
|
|
class VSETB_OT_reload_addon(Operator):
|
|
bl_idname = "vse_toolbox.reload_addon"
|
|
bl_options = {"UNDO"}
|
|
bl_label = 'Reload VSE ToolBox Addon'
|
|
bl_description = 'Reload The VSE ToolBox Addon'
|
|
|
|
def execute(self, context):
|
|
|
|
print('Execute reload')
|
|
|
|
vse_toolbox.unregister()
|
|
importlib.reload(vse_toolbox)
|
|
vse_toolbox.register()
|
|
|
|
return {'FINISHED'}
|
|
|
|
|
|
class VSETB_OT_rename(Operator):
|
|
bl_idname = "vse_toolbox.strips_rename"
|
|
bl_label = "Rename Strips"
|
|
bl_description = "Rename Strips"
|
|
bl_options = {"REGISTER", "UNDO"}
|
|
|
|
#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)
|
|
#start_number : IntProperty(name="Start Number", default=0, min=0)
|
|
#by_sequence : BoolProperty(
|
|
# name="Reset By Sequence",
|
|
# description="Reset Start Number for each sequence",
|
|
# default=False
|
|
#)
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
settings = get_scene_settings()
|
|
return settings.active_project
|
|
|
|
def invoke(self, context, event):
|
|
scn = context.scene
|
|
settings = get_scene_settings()
|
|
|
|
return context.window_manager.invoke_props_dialog(self)
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
scn = context.scene
|
|
settings = get_scene_settings()
|
|
project = settings.active_project
|
|
|
|
col = layout.column()
|
|
col.use_property_split = True
|
|
col.use_property_decorate = False
|
|
|
|
if self.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, 'reset_by_sequence')
|
|
elif self.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(self, 'selected_only')
|
|
|
|
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':
|
|
rename_strips(strips,
|
|
template=project.shot_template,
|
|
increment=project.shot_increment, start_number=project.shot_start_number,
|
|
by_sequence=project.reset_by_sequence
|
|
)
|
|
|
|
if self.channel_name == 'Sequences':
|
|
rename_strips(strips,
|
|
template=project.sequence_template,
|
|
increment=project.sequence_increment, start_number=project.sequence_start_number
|
|
)
|
|
|
|
return {"FINISHED"}
|
|
|
|
|
|
class VSETB_OT_render(Operator):
|
|
bl_idname = "vse_toolbox.strips_render"
|
|
bl_label = "Render Shots Strips"
|
|
bl_description = "Render Shots Strips"
|
|
bl_options = {"REGISTER", "UNDO"}
|
|
|
|
#selected_only : BoolProperty(name="Selected Only", default=False)
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
settings = get_scene_settings()
|
|
return settings.active_project
|
|
|
|
def invoke(self, context, event):
|
|
scn = context.scene
|
|
settings = get_scene_settings()
|
|
|
|
return context.window_manager.invoke_props_dialog(self)
|
|
|
|
def draw(self, context):
|
|
scn = context.scene
|
|
settings = get_scene_settings()
|
|
|
|
layout = self.layout
|
|
col = layout.column()
|
|
col.use_property_split = True
|
|
col.use_property_decorate = False
|
|
#col.prop(settings, 'channel', text='Channel')
|
|
#col.prop(self, 'selected_only')
|
|
|
|
col.prop(settings.active_project, "render_template")
|
|
|
|
def execute(self, context):
|
|
scn = context.scene
|
|
settings = get_scene_settings()
|
|
strips = get_strips(channel='Shots', selected_only=True)
|
|
|
|
start_time = time.perf_counter()
|
|
render_strips(strips, settings.active_project.render_template)
|
|
|
|
self.report({"INFO"}, f'Strips rendered in {time.perf_counter()-start_time} seconds')
|
|
|
|
return {"FINISHED"}
|
|
|
|
|
|
class VSETB_OT_show_waveform(Operator):
|
|
bl_idname = "vse_toolbox.show_waveform"
|
|
bl_label = "Show Waveform"
|
|
bl_description = "Show Waveform of all audio strips"
|
|
bl_options = {"REGISTER", "UNDO"}
|
|
|
|
enabled : BoolProperty(default=True)
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
return True
|
|
|
|
def execute(self, context):
|
|
scn = context.scene
|
|
|
|
for strip in get_strips(channel='Audio'):
|
|
strip.show_waveform = self.enabled
|
|
|
|
return {"FINISHED"}
|
|
|
|
|
|
class VSETB_OT_set_sequencer(Operator):
|
|
bl_idname = "vse_toolbox.set_sequencer"
|
|
bl_label = "Set Sequencer"
|
|
bl_description = "Set resolution, frame end and channel names"
|
|
bl_options = {"REGISTER", "UNDO"}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
return True
|
|
|
|
def execute(self, context):
|
|
scn = context.scene
|
|
|
|
set_channels()
|
|
movie = get_strips(channel='Movie')
|
|
if movie:
|
|
movie = movie[0]
|
|
movie.transform.scale_x = movie.transform.scale_y = 1
|
|
elem = movie.strip_elem_from_frame(scn.frame_current)
|
|
scn.render.resolution_x = elem.orig_width
|
|
scn.render.resolution_y = elem.orig_height
|
|
else:
|
|
self.report({'INFO'}, f'Cannot set Resolution. No Movie Found.')
|
|
|
|
scn.view_settings.view_transform = 'Standard'
|
|
scn.render.image_settings.file_format = 'FFMPEG'
|
|
scn.render.ffmpeg.gopsize = 5
|
|
scn.render.ffmpeg.constant_rate_factor = 'HIGH'
|
|
scn.render.ffmpeg.format = 'QUICKTIME'
|
|
scn.render.ffmpeg.audio_codec = 'AAC'
|
|
scn.render.ffmpeg.audio_codec = 'MP3'
|
|
scn.render.ffmpeg.audio_mixrate = 44100
|
|
scn.render.ffmpeg.audio_bitrate = 128
|
|
|
|
return {"FINISHED"}
|
|
|
|
|
|
class VSETB_OT_casting_replace(Operator):
|
|
bl_idname = "vse_toolbox.casting_replace"
|
|
bl_label = "Replace Asset"
|
|
bl_description = "Replace Asset of selected strips"
|
|
|
|
old_asset : StringProperty()
|
|
new_asset : StringProperty()
|
|
|
|
assets : CollectionProperty(type=PropertyGroup)
|
|
|
|
def execute(self, context):
|
|
prefs = get_addon_prefs()
|
|
settings = get_scene_settings()
|
|
|
|
new_asset = next(a for a in settings.active_project.assets if a.tracker_name == self.new_asset)
|
|
|
|
for strip in get_strips('Shots', selected_only=True):
|
|
strip_settings = strip.vsetb_strip_settings
|
|
for asset_casting in strip_settings.casting:
|
|
if asset_casting.asset.tracker_name == self.old_asset:
|
|
|
|
print(f'Replace casting on {strip.name}')
|
|
|
|
asset_casting.name = new_asset.name
|
|
asset_casting.id = new_asset.id
|
|
asset_casting['_name'] = new_asset.label
|
|
|
|
strip_settings.casting.update()
|
|
|
|
self.assets.clear()
|
|
|
|
return {'FINISHED'}
|
|
|
|
def invoke(self, context, event):
|
|
settings = get_scene_settings()
|
|
project = settings.active_project
|
|
|
|
self.assets.clear()
|
|
for asset in project.assets:
|
|
item = self.assets.add()
|
|
item.name = asset.tracker_name
|
|
|
|
strip = context.active_sequence_strip
|
|
asset_casting_index = strip.vsetb_strip_settings.casting_index
|
|
active_asset = strip.vsetb_strip_settings.casting[asset_casting_index].asset
|
|
|
|
self.old_asset = active_asset.tracker_name
|
|
self.new_asset = ''
|
|
|
|
return context.window_manager.invoke_props_dialog(self)
|
|
#
|
|
|
|
def draw(self, context):
|
|
scn = context.scene
|
|
settings = get_scene_settings()
|
|
|
|
project = settings.active_project
|
|
|
|
layout = self.layout
|
|
col = layout.column()
|
|
col.use_property_split = True
|
|
col.prop_search(self, 'old_asset', self, 'assets', text='Old Asset', icon='ASSET_MANAGER')
|
|
col.prop_search(self, 'new_asset', self, 'assets', text='New Asset', icon='ASSET_MANAGER')
|
|
|
|
|
|
def get_asset_items(self, context):
|
|
settings = get_scene_settings()
|
|
project = settings.active_project
|
|
|
|
return [(a.id, a.label, '', i) for i, a in enumerate(project.assets)]
|
|
|
|
class VSETB_OT_casting_add(Operator):
|
|
bl_idname = "vse_toolbox.casting_add"
|
|
bl_label = "Casting Add"
|
|
bl_description = "Add Asset to Castin"
|
|
bl_options = {"REGISTER", "UNDO"}
|
|
bl_property = "asset_name"
|
|
|
|
asset_name : EnumProperty(name='', items=get_asset_items)
|
|
@classmethod
|
|
def poll(cls, context):
|
|
active_strip = context.scene.sequence_editor.active_strip
|
|
if active_strip:
|
|
return True
|
|
|
|
def invoke(self, context, event):
|
|
context.window_manager.invoke_search_popup(self)
|
|
return {'FINISHED'}
|
|
|
|
def execute(self, context):
|
|
scn = context.scene
|
|
active_strip = scn.sequence_editor.active_strip
|
|
|
|
settings = get_scene_settings()
|
|
strip_settings = get_strip_settings()
|
|
|
|
project = settings.active_project
|
|
|
|
if strip_settings.casting.get(self.asset_name):
|
|
asset = project.assets[self.asset_name]
|
|
self.report({'WARNING'}, f"Asset {asset.label} already casted.")
|
|
return {"CANCELLED"}
|
|
|
|
item = strip_settings.casting.add()
|
|
asset = project.assets[self.asset_name]
|
|
|
|
item.name = asset.name
|
|
item.id = project.assets[self.asset_name].id
|
|
item['_name'] = asset.label
|
|
|
|
strip_settings.casting.update()
|
|
|
|
return {"FINISHED"}
|
|
|
|
|
|
class VSETB_OT_casting_remove(Operator):
|
|
bl_idname = "vse_toolbox.casting_remove"
|
|
bl_label = "Remove Item from Casting"
|
|
bl_description = "Remove Item from Casting"
|
|
bl_options = {"REGISTER", "UNDO"}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
active_strip = context.scene.sequence_editor.active_strip
|
|
if active_strip:
|
|
return True
|
|
|
|
def invoke(self, context, event):
|
|
scn = context.scene
|
|
|
|
strip_settings = get_strip_settings()
|
|
idx = strip_settings.casting_index
|
|
|
|
try:
|
|
item = strip_settings.casting[idx]
|
|
except IndexError:
|
|
pass
|
|
else:
|
|
item = strip_settings.casting[strip_settings.casting_index]
|
|
label = item.asset.label if item.asset.label else 'Empty'
|
|
info = f"Item {label} removed from casting"
|
|
strip_settings.casting.remove(idx)
|
|
|
|
if strip_settings.casting_index == 0:
|
|
strip_settings.casting_index = 0
|
|
else:
|
|
strip_settings.casting_index -= 1
|
|
|
|
self.report({'INFO'}, info)
|
|
|
|
return {"FINISHED"}
|
|
|
|
|
|
class VSETB_OT_casting_move(Operator):
|
|
bl_idname = "vse_toolbox.casting_move"
|
|
bl_label = "Move Casting items"
|
|
bl_description = "Move Casting items"
|
|
bl_options = {"REGISTER", "UNDO"}
|
|
|
|
direction: EnumProperty(
|
|
items=(
|
|
('UP', "Up", ""),
|
|
('DOWN', "Down", ""),
|
|
)
|
|
)
|
|
|
|
asset_name : StringProperty()
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
active_strip = context.scene.sequence_editor.active_strip
|
|
if active_strip:
|
|
return True
|
|
|
|
def execute(self, context):
|
|
scn = context.scene
|
|
|
|
strip_settings = get_strip_settings()
|
|
idx = strip_settings.casting_index
|
|
|
|
try:
|
|
item = strip_settings.casting[idx]
|
|
except IndexError:
|
|
pass
|
|
else:
|
|
if self.direction == 'DOWN' and idx < len(strip_settings.casting) - 1:
|
|
item_next = strip_settings.casting[idx+1].name
|
|
strip_settings.casting.move(idx, idx+1)
|
|
strip_settings.casting_index += 1
|
|
|
|
elif self.direction == 'UP' and idx >= 1:
|
|
item_prev = strip_settings.casting[idx-1].name
|
|
strip_settings.casting.move(idx, idx-1)
|
|
strip_settings.casting_index -= 1
|
|
|
|
info = f"Item {item.asset.label} moved to position {(item.asset.label, strip_settings.casting_index + 1)}"
|
|
self.report({'INFO'}, info)
|
|
|
|
return {"FINISHED"}
|
|
|
|
|
|
class VSETB_MT_spreadsheet_presets(Menu):
|
|
bl_label = 'Presets'
|
|
preset_subdir = 'vse_toolbox'
|
|
preset_operator = 'script.execute_preset'
|
|
draw = Menu.draw_preset
|
|
|
|
|
|
class VSETB_OT_add_spreadsheet_preset(AddPresetBase, Operator):
|
|
|
|
bl_idname = "vse_toolbox.add_spreadsheet_preset"
|
|
bl_label = "Add Spreadsheet Preset"
|
|
bl_description = "Add Spreadsheet Preset"
|
|
bl_options = {"REGISTER", "UNDO"}
|
|
|
|
preset_menu = 'VSETB_MT_spreadsheet_presets'
|
|
|
|
#preset_menu = 'VSETB_OT_MT_spreadsheet_presets'
|
|
|
|
# Common variable used for all preset values
|
|
#C.scene.vsetb_settings.active_project.spreadsheet_options
|
|
preset_defines = [
|
|
'scene = bpy.context.scene',
|
|
'settings = scene.vsetb_settings',
|
|
'project = settings.active_project'
|
|
]
|
|
|
|
# Properties to store in the preset
|
|
preset_values = [
|
|
'project.spreadsheet',
|
|
'project.spreadsheet_options'
|
|
]
|
|
|
|
# Directory to store the presets
|
|
preset_subdir = 'vse_toolbox'
|
|
|
|
|
|
|
|
class VSETB_OT_spreadsheet_move(Operator):
|
|
bl_idname = "vse_toolbox.spreadsheet_move"
|
|
bl_label = "Move Spreadsheet items"
|
|
bl_description = "Move Spreadsheet items"
|
|
bl_options = {"REGISTER", "UNDO"}
|
|
|
|
direction: EnumProperty(
|
|
items=(
|
|
('UP', "Up", ""),
|
|
('DOWN', "Down", ""),
|
|
)
|
|
)
|
|
|
|
def execute(self, context):
|
|
scn = context.scene
|
|
project = get_scene_settings().active_project
|
|
|
|
idx = project.spreadsheet_index
|
|
|
|
try:
|
|
item = project.spreadsheet[idx]
|
|
except IndexError:
|
|
pass
|
|
else:
|
|
if self.direction == 'DOWN' and idx < len(project.spreadsheet) - 1:
|
|
item_next = project.spreadsheet[idx+1].name
|
|
project.spreadsheet.move(idx, idx+1)
|
|
project.spreadsheet_index += 1
|
|
|
|
elif self.direction == 'UP' and idx >= 1:
|
|
item_prev = project.spreadsheet[idx-1].name
|
|
project.spreadsheet.move(idx, idx-1)
|
|
project.spreadsheet_index -= 1
|
|
|
|
return {"FINISHED"}
|
|
|
|
|
|
class VSETB_OT_copy_casting(Operator):
|
|
bl_idname = "vse_toolbox.copy_casting"
|
|
bl_label = "Copy Casting"
|
|
bl_description = "Copy Casting from active strip"
|
|
bl_options = {"REGISTER", "UNDO"}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
active_strip = context.scene.sequence_editor.active_strip
|
|
strip_settings = get_strip_settings()
|
|
|
|
if active_strip and strip_settings.casting:
|
|
return True
|
|
|
|
def execute(self, context):
|
|
scn = context.scene
|
|
|
|
active_strip = scn.sequence_editor.active_strip
|
|
strip_settings = get_strip_settings()
|
|
|
|
datas = [c.to_dict() for c in strip_settings.casting]
|
|
CASTING_BUFFER.write_text(json.dumps(datas), encoding='utf-8')
|
|
|
|
return {"FINISHED"}
|
|
|
|
|
|
class VSETB_OT_paste_casting(Operator):
|
|
bl_idname = "vse_toolbox.paste_casting"
|
|
bl_label = "Paste Casting"
|
|
bl_description = "Paste Casting to active strip"
|
|
bl_options = {"REGISTER", "UNDO"}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
active_strip = context.scene.sequence_editor.active_strip
|
|
if active_strip:
|
|
return True
|
|
|
|
def execute(self, context):
|
|
scn = context.scene
|
|
strip_settings = get_strip_settings()
|
|
|
|
if not CASTING_BUFFER.exists():
|
|
self.report({'ERROR'}, f'No Casting to copy.')
|
|
return {"CANCELLED"}
|
|
|
|
casting_datas = json.loads(CASTING_BUFFER.read_text())
|
|
|
|
|
|
|
|
for strip in context.selected_sequences:
|
|
strip_settings = strip.vsetb_strip_settings
|
|
for casting_data in casting_datas:
|
|
|
|
item = strip.vsetb_strip_settings.casting.add()
|
|
|
|
item.name = casting_data['name']
|
|
item.id = casting_data['id']
|
|
item['_name'] = casting_data['_name']
|
|
|
|
strip_settings.casting.update()
|
|
|
|
return {"FINISHED"}
|
|
|
|
|
|
class VSETB_OT_set_stamps(Operator):
|
|
bl_idname = "vse_toolbox.set_stamps"
|
|
bl_label = "Set Stamps"
|
|
bl_description = "Set Stamps on Video"
|
|
bl_options = {"REGISTER", "UNDO"}
|
|
|
|
def execute(self, context):
|
|
scn = context.scene
|
|
settings = get_scene_settings()
|
|
#strip_settings = get_strip_settings()
|
|
channel_index = get_channel_index('Stamps')
|
|
|
|
for strip in get_strips('Stamps'):
|
|
if strip.type == 'META':
|
|
scn.sequence_editor.sequences.remove(strip)
|
|
|
|
bpy.ops.sequencer.select_all(action='DESELECT')
|
|
|
|
crop_x = int(scn.render.resolution_x * 0.4)
|
|
crop_max_y = int(scn.render.resolution_y * 0.96)
|
|
crop_min_y = int(scn.render.resolution_y * 0.01)
|
|
|
|
stamp_params = dict(start=scn.frame_start, end=scn.frame_end,
|
|
font_size=22, y=0.015, box_margin=0.005, select=True, box_color=(0, 0, 0, 0.5))
|
|
|
|
# Project Name
|
|
project_strip_stamp = new_text_strip('project_name_stamp', channel=1, **stamp_params,
|
|
text=settings.active_project.name, x=0.01, align_x='LEFT', align_y='BOTTOM')
|
|
|
|
project_strip_stamp.crop.max_x = crop_x * 2
|
|
project_strip_stamp.crop.max_y = crop_max_y
|
|
project_strip_stamp.crop.min_y = crop_min_y
|
|
|
|
# Shot Name
|
|
shot_strip_stamp = new_text_strip('shot_name_stamp', channel=2, **stamp_params,
|
|
text='{active_shot_name}', 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
|
|
shot_strip_stamp.crop.min_y = crop_min_y
|
|
|
|
# Frame Range
|
|
frame_strip_stamp = new_text_strip('frame_range_stamp', channel=3, **stamp_params,
|
|
text='{active_shot_frame} / {active_shot_duration}', 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
|
|
frame_strip_stamp.crop.min_y = crop_min_y
|
|
|
|
bpy.ops.sequencer.meta_make()
|
|
stamps_strip = context.active_sequence_strip
|
|
stamps_strip.name = 'Stamps'
|
|
stamps_strip.channel = channel_index
|
|
|
|
#stamps_strip = scn.sequence_editor.sequences.new_meta('Stamps', scn.frame_start, scn.frame_end)
|
|
#stamps_strip.channel = get_channel_index('Stamps')
|
|
scn.frame_set(scn.frame_current) # For update stamps
|
|
|
|
return {"FINISHED"}
|
|
|
|
|
|
def load_settings():
|
|
prefs = get_addon_prefs()
|
|
settings = get_scene_settings()
|
|
project = settings.active_project
|
|
|
|
prefs_config_file = prefs.config_path
|
|
|
|
if not prefs_config_file:
|
|
return
|
|
|
|
prefs_datas = read_file(os.path.expandvars(prefs_config_file))
|
|
|
|
prefs_datas['trackers'] = prefs_datas.get('trackers')
|
|
prefs_datas['spreadsheet'] = prefs_datas.get('spreadsheet')
|
|
|
|
#print(prefs_datas)
|
|
trackers = prefs_datas.pop('trackers')
|
|
spreadsheet = prefs_datas.pop('spreadsheet')
|
|
|
|
project_name = prefs_datas.get('project_name')
|
|
if project_name:
|
|
settings.project_name = project_name
|
|
|
|
# Project Properties
|
|
for k, v in prefs_datas.items():
|
|
try:
|
|
setattr(project, k, v)
|
|
except Exception:
|
|
print(f'Could not set property {k} with value {v} to project {settings.project_name}')
|
|
|
|
if spreadsheet.get('cells'):
|
|
#project.spreadsheet.clear()
|
|
|
|
for i, cell_data in enumerate(spreadsheet['cells']):
|
|
if not 'name' in cell_data:
|
|
print(f'cell_data {cell_data} need to have a attribute name')
|
|
continue
|
|
|
|
cell = project.spreadsheet.get(cell_data['name'])
|
|
|
|
if not cell:
|
|
print(f"cell {cell_data['name']} not in spreadsheet")
|
|
continue
|
|
|
|
project.spreadsheet.move(list(project.spreadsheet).index(cell), i)
|
|
|
|
for prop_name in ('export_name', 'enabled'):
|
|
if prop_name in cell_data:
|
|
setattr(cell, prop_name, cell_data[prop_name])
|
|
|
|
if spreadsheet.get('options'):
|
|
for k, v in spreadsheet['options'].items():
|
|
try:
|
|
setattr(project.spreadsheet_options, k, v)
|
|
except Exception:
|
|
print(f'Could not set option {k} with value {v} to spreadsheet')
|
|
|
|
classes = (
|
|
VSETB_OT_auto_select_files,
|
|
VSETB_OT_casting_add,
|
|
VSETB_OT_casting_remove,
|
|
VSETB_OT_casting_move,
|
|
VSETB_OT_add_spreadsheet_preset,
|
|
VSETB_MT_spreadsheet_presets,
|
|
VSETB_OT_spreadsheet_move,
|
|
VSETB_OT_copy_casting,
|
|
VSETB_OT_paste_casting,
|
|
VSETB_OT_casting_replace,
|
|
VSETB_OT_export_spreadsheet,
|
|
VSETB_OT_import_files,
|
|
VSETB_OT_load_assets,
|
|
VSETB_OT_load_projects,
|
|
VSETB_OT_new_episode,
|
|
VSETB_OT_reload_addon,
|
|
VSETB_OT_rename,
|
|
VSETB_OT_render,
|
|
VSETB_OT_set_sequencer,
|
|
VSETB_OT_tracker_connect,
|
|
VSETB_OT_set_stamps,
|
|
VSETB_OT_upload_to_tracker,
|
|
VSETB_OT_show_waveform,
|
|
VSETB_OT_copy_metadata
|
|
)
|
|
|
|
def register():
|
|
for cls in classes:
|
|
bpy.utils.register_class(cls)
|
|
|
|
def unregister():
|
|
for cls in reversed(classes):
|
|
bpy.utils.unregister_class(cls) |