add generic templates
parent
2960bab63d
commit
0055e0f39e
|
@ -164,19 +164,24 @@ def parse(template, string):
|
||||||
if result := re.match(reg, string):
|
if result := re.match(reg, string):
|
||||||
return result.groupdict()
|
return result.groupdict()
|
||||||
|
|
||||||
def find_last(template, **kargs):
|
def expand(template, **kargs):
|
||||||
#print(find_last, template, kargs)
|
template = Path(template).as_posix()
|
||||||
pattern = Path(template).as_posix()
|
template = expandvars(template)
|
||||||
pattern = expandvars(pattern)
|
|
||||||
|
|
||||||
for key, value in kargs.items():
|
for key, value in kargs.items():
|
||||||
pattern = re.sub(r'\{%s\}'%key, value, pattern)
|
template = re.sub(r'\{%s\}'%key, value, template)
|
||||||
|
|
||||||
|
return template
|
||||||
|
|
||||||
|
def find_last(template, **kargs):
|
||||||
|
|
||||||
|
pattern = expand(template, **kargs)
|
||||||
|
|
||||||
pattern = re.sub(r'{\w+:(\d{2})d}', lambda x : '?' * int(x.groups()[0]), pattern)
|
pattern = re.sub(r'{\w+:(\d{2})d}', lambda x : '?' * int(x.groups()[0]), pattern)
|
||||||
pattern = re.sub(r'{.*?}', '*', pattern)
|
pattern = re.sub(r'{.*?}', '*', pattern)
|
||||||
|
|
||||||
print(pattern)
|
|
||||||
|
|
||||||
filepaths = glob.glob(pattern)
|
filepaths = glob.glob(pattern)
|
||||||
if filepaths:
|
if filepaths:
|
||||||
return Path(max(filepaths))
|
return Path(max(filepaths))
|
||||||
|
else:
|
||||||
|
print(f'No preview found for template {pattern}')
|
|
@ -5,6 +5,7 @@ import os
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
from bpy.types import Operator
|
from bpy.types import Operator
|
||||||
|
from bpy.props import IntProperty
|
||||||
|
|
||||||
import vse_toolbox
|
import vse_toolbox
|
||||||
|
|
||||||
|
@ -37,6 +38,21 @@ class VSETB_OT_load_settings(Operator):
|
||||||
bl_label = 'Load Settings'
|
bl_label = 'Load Settings'
|
||||||
bl_description = 'Load VSE ToolBox settings from config file'
|
bl_description = 'Load VSE ToolBox settings from config file'
|
||||||
|
|
||||||
|
def set_config(self, data, values):
|
||||||
|
for k, v in values.items():
|
||||||
|
if not hasattr(data, k):
|
||||||
|
print(f'{repr(data)} has no attribute {k}')
|
||||||
|
continue
|
||||||
|
|
||||||
|
if isinstance(v, list):
|
||||||
|
data[k] = v
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
setattr(data, k, v)
|
||||||
|
except Exception:
|
||||||
|
print(f'Could not set property {k} with value {v} to {repr(data)}')
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
prefs = get_addon_prefs()
|
prefs = get_addon_prefs()
|
||||||
settings = get_scene_settings()
|
settings = get_scene_settings()
|
||||||
|
@ -49,6 +65,10 @@ class VSETB_OT_load_settings(Operator):
|
||||||
if not addon_config:
|
if not addon_config:
|
||||||
return {'CANCELLED'}
|
return {'CANCELLED'}
|
||||||
|
|
||||||
|
# Environ set
|
||||||
|
for k, v in addon_config.get('environ', {}).items():
|
||||||
|
os.environ[k] = str(v)
|
||||||
|
|
||||||
addon_config['trackers'] = addon_config.get('trackers')
|
addon_config['trackers'] = addon_config.get('trackers')
|
||||||
trackers_config = addon_config.pop('trackers')
|
trackers_config = addon_config.pop('trackers')
|
||||||
for tracker_config in trackers_config:
|
for tracker_config in trackers_config:
|
||||||
|
@ -61,11 +81,10 @@ class VSETB_OT_load_settings(Operator):
|
||||||
for k, v in tracker_config.items():
|
for k, v in tracker_config.items():
|
||||||
setattr(tracker, k, v)
|
setattr(tracker, k, v)
|
||||||
|
|
||||||
addon_config['spreadsheet_export'] = addon_config.get('spreadsheet_export', {})
|
spreadsheet_export_config = addon_config.pop('spreadsheet_export', {})
|
||||||
spreadsheet_export_config = addon_config.pop('spreadsheet_export')
|
spreadsheet_import_config = addon_config.pop('spreadsheet_import', {})
|
||||||
|
upload_to_tracker_config = addon_config.pop('upload_to_tracker', {})
|
||||||
addon_config['spreadsheet_import'] = addon_config.get('spreadsheet_import', {})
|
import_shots_config = addon_config.pop('import_shots', {})
|
||||||
spreadsheet_import_config = addon_config.pop('spreadsheet_import')
|
|
||||||
|
|
||||||
project_name = addon_config.get('project_name')
|
project_name = addon_config.get('project_name')
|
||||||
if project_name not in settings.projects:
|
if project_name not in settings.projects:
|
||||||
|
@ -77,12 +96,7 @@ class VSETB_OT_load_settings(Operator):
|
||||||
|
|
||||||
# Project Properties
|
# Project Properties
|
||||||
project = settings.active_project
|
project = settings.active_project
|
||||||
for k, v in addon_config.items():
|
self.set_config(project, addon_config)
|
||||||
try:
|
|
||||||
setattr(project, k, v)
|
|
||||||
except Exception:
|
|
||||||
print(f'Could not set property {k} with value {v} to project {settings.project_name}')
|
|
||||||
|
|
||||||
|
|
||||||
export_cells = project.spreadsheet_export.cells
|
export_cells = project.spreadsheet_export.cells
|
||||||
for k, v in spreadsheet_export_config.items():
|
for k, v in spreadsheet_export_config.items():
|
||||||
|
@ -148,13 +162,53 @@ class VSETB_OT_load_settings(Operator):
|
||||||
except Exception:
|
except Exception:
|
||||||
print(f'Could not set option {k} with value {v} to spreadsheet')
|
print(f'Could not set option {k} with value {v} to spreadsheet')
|
||||||
|
|
||||||
self.report({"INFO"}, 'Settings loaded with sucess')
|
# Upload to Tracker
|
||||||
|
self.set_config(project.upload_to_tracker, upload_to_tracker_config)
|
||||||
|
|
||||||
|
# Import Shots
|
||||||
|
self.set_config(project.import_shots, import_shots_config)
|
||||||
|
|
||||||
|
self.report({"INFO"}, 'Settings loaded with success')
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
|
class VSETB_OT_add_template(Operator):
|
||||||
|
bl_idname = "vse_toolbox.add_template"
|
||||||
|
bl_label = "Add Template"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
scn = context.scene
|
||||||
|
settings = get_scene_settings()
|
||||||
|
project = settings.active_project
|
||||||
|
|
||||||
|
project.templates.add()
|
||||||
|
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
|
class VSETB_OT_remove_template(Operator):
|
||||||
|
bl_idname = "vse_toolbox.remove_template"
|
||||||
|
bl_label = "Remove Template"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
|
index : IntProperty()
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
scn = context.scene
|
||||||
|
settings = get_scene_settings()
|
||||||
|
project = settings.active_project
|
||||||
|
|
||||||
|
project.templates.remove(self.index)
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
VSETB_OT_reload_addon,
|
VSETB_OT_reload_addon,
|
||||||
VSETB_OT_load_settings
|
VSETB_OT_load_settings,
|
||||||
|
VSETB_OT_add_template,
|
||||||
|
VSETB_OT_remove_template
|
||||||
)
|
)
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
|
|
|
@ -8,9 +8,10 @@ import bpy
|
||||||
from bpy.types import Operator
|
from bpy.types import Operator
|
||||||
from bpy.props import BoolProperty
|
from bpy.props import BoolProperty
|
||||||
|
|
||||||
from vse_toolbox.sequencer_utils import (get_strips, render_strip, render_sound, render_scene)
|
from vse_toolbox.sequencer_utils import (get_strips, render_strip, render_sound,
|
||||||
|
render_scene, get_render_attributes)
|
||||||
from vse_toolbox.bl_utils import (get_scene_settings, background_render)
|
from vse_toolbox.bl_utils import (get_scene_settings, background_render)
|
||||||
from vse_toolbox.file_utils import install_module
|
from vse_toolbox.file_utils import install_module, expand
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -116,53 +117,67 @@ class VSETB_OT_render(Operator):
|
||||||
settings = get_scene_settings()
|
settings = get_scene_settings()
|
||||||
project = settings.active_project
|
project = settings.active_project
|
||||||
|
|
||||||
|
project_templates = {t.name: t.value for t in project.templates}
|
||||||
format_data = {**settings.format_data, **project.format_data}
|
format_data = {**settings.format_data, **project.format_data}
|
||||||
|
|
||||||
|
single_file = False
|
||||||
|
sequence_strips = []
|
||||||
|
shot_strips = []
|
||||||
|
|
||||||
|
render_attrs = get_render_attributes()
|
||||||
|
|
||||||
start_time = time.perf_counter()
|
start_time = time.perf_counter()
|
||||||
if project.render_single_file:
|
if project.render_single_file:
|
||||||
|
single_file = True
|
||||||
if project.render_video:
|
if project.render_video:
|
||||||
video_template = os.path.expandvars(project.render_video_template)
|
video_template = expand(project.render_video_template, **project_templates)
|
||||||
video_path = video_template.format(**format_data)
|
video_path = video_template.format(**format_data)
|
||||||
render_scene(video_path)
|
render_scene(video_path, attributes=render_attrs)
|
||||||
#background_render(output=video_path)
|
#background_render(output=video_path)
|
||||||
|
|
||||||
if project.render_audio:
|
if project.render_audio:
|
||||||
audio_template = os.path.expandvars(project.render_audio_template)
|
audio_template = expand(project.render_audio_template, **project_templates)
|
||||||
audio_path = audio_template.format(**format_data)
|
audio_path = audio_template.format(**format_data)
|
||||||
bpy.ops.sound.mixdown(filepath=audio_path)
|
bpy.ops.sound.mixdown(filepath=audio_path)
|
||||||
|
|
||||||
if project.render_sequence:
|
if project.render_sequence:
|
||||||
print('Render Sequences...')
|
print('Render Sequences...')
|
||||||
for strip in get_strips(channel='Sequences', selected_only=project.render_selected_only):
|
sequence_strips = get_strips(channel='Sequences', selected_only=project.render_selected_only)
|
||||||
|
for strip in sequence_strips:
|
||||||
#print(strip.name)
|
#print(strip.name)
|
||||||
strip_settings = strip.vsetb_strip_settings
|
strip_settings = strip.vsetb_strip_settings
|
||||||
strip_data = {**format_data, **strip_settings.format_data}
|
strip_data = {**format_data, **strip_settings.format_data}
|
||||||
|
|
||||||
if project.render_sequence and project.render_video_per_sequence:
|
if project.render_sequence and project.render_video_per_sequence:
|
||||||
video_sequence_template = os.path.expandvars(project.render_video_sequence_template)
|
video_sequence_template = expand(project.render_video_sequence_template, **project_templates)
|
||||||
sequence_render_path = video_sequence_template.format(**strip_data)
|
sequence_render_path = video_sequence_template.format(**strip_data)
|
||||||
render_strip(strip, sequence_render_path)
|
render_strip(strip, sequence_render_path, attributes=render_attrs)
|
||||||
|
|
||||||
if project.render_shot and project.render_audio_per_sequence:
|
if project.render_shot and project.render_audio_per_sequence:
|
||||||
audio_sequence_template = os.path.expandvars(project.render_audio_sequence_template)
|
audio_sequence_template = expand(project.render_audio_sequence_template, **project_templates)
|
||||||
audio_render_path = audio_sequence_template.format(**strip_data)
|
audio_render_path = audio_sequence_template.format(**strip_data)
|
||||||
render_sound(strip, audio_render_path)
|
render_sound(strip, audio_render_path)
|
||||||
|
|
||||||
if project.render_shot:
|
if project.render_shot:
|
||||||
for strip in get_strips(channel='Shots', selected_only=project.render_selected_only):
|
shot_strips = get_strips(channel='Shots', selected_only=project.render_selected_only)
|
||||||
|
for strip in shot_strips:
|
||||||
strip_settings = strip.vsetb_strip_settings
|
strip_settings = strip.vsetb_strip_settings
|
||||||
strip_data = {**format_data, **strip_settings.format_data}
|
strip_data = {**format_data, **strip_settings.format_data}
|
||||||
|
|
||||||
if project.render_video_per_strip:
|
if project.render_video_per_strip:
|
||||||
video_strip_template = os.path.expandvars(project.render_video_strip_template)
|
video_strip_template = expand(project.render_video_strip_template, **project_templates)
|
||||||
strip_render_path = video_strip_template.format(**strip_data)
|
strip_render_path = video_strip_template.format(**strip_data)
|
||||||
render_strip(strip, strip_render_path)
|
render_strip(strip, strip_render_path, attributes=render_attrs)
|
||||||
|
|
||||||
if project.render_audio_per_strip:
|
if project.render_audio_per_strip:
|
||||||
audio_strip_template = os.path.expandvars(project.render_audio_strip_template)
|
audio_strip_template = expand(project.render_audio_strip_template, **project_templates)
|
||||||
audio_render_path = audio_strip_template.format(**strip_data)
|
audio_render_path = audio_strip_template.format(**strip_data)
|
||||||
render_sound(strip, audio_render_path)
|
render_sound(strip, audio_render_path)
|
||||||
|
|
||||||
|
if not single_file and not sequence_strips and not shot_strips:
|
||||||
|
self.report({"ERROR"}, f'No strips rendered, select sequence or shot strips')
|
||||||
|
return {"CANCELLED"}
|
||||||
|
|
||||||
self.report({"INFO"}, f'Strips rendered in {time.perf_counter()-start_time} seconds')
|
self.report({"INFO"}, f'Strips rendered in {time.perf_counter()-start_time} seconds')
|
||||||
|
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
|
@ -7,7 +7,7 @@ from tempfile import gettempdir
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
from bpy.types import Operator, UIList
|
from bpy.types import Operator, UIList
|
||||||
from bpy.props import (CollectionProperty, BoolProperty, EnumProperty, StringProperty)
|
from bpy.props import (CollectionProperty, BoolProperty, EnumProperty, StringProperty, IntProperty)
|
||||||
|
|
||||||
from vse_toolbox.constants import (EDITS, EDIT_SUFFIXES, MOVIES, MOVIE_SUFFIXES,
|
from vse_toolbox.constants import (EDITS, EDIT_SUFFIXES, MOVIES, MOVIE_SUFFIXES,
|
||||||
SOUNDS, SOUND_SUFFIXES)
|
SOUNDS, SOUND_SUFFIXES)
|
||||||
|
@ -16,8 +16,8 @@ from vse_toolbox.sequencer_utils import (clean_sequencer, import_edit, import_mo
|
||||||
import_sound, get_strips, get_channel_index, get_empty_channel, scale_clip_to_fit)
|
import_sound, get_strips, get_channel_index, get_empty_channel, scale_clip_to_fit)
|
||||||
|
|
||||||
from vse_toolbox.bl_utils import (get_scene_settings, get_addon_prefs, get_scene_settings)
|
from vse_toolbox.bl_utils import (get_scene_settings, get_addon_prefs, get_scene_settings)
|
||||||
from vse_toolbox.file_utils import install_module, parse, find_last
|
from vse_toolbox.file_utils import install_module, parse, find_last, expand
|
||||||
#from vse_toolbox.template import Template
|
|
||||||
|
|
||||||
class VSETB_OT_auto_select_files(Operator):
|
class VSETB_OT_auto_select_files(Operator):
|
||||||
bl_idname = "vse_toolbox.auto_select_files"
|
bl_idname = "vse_toolbox.auto_select_files"
|
||||||
|
@ -254,6 +254,38 @@ class VSETB_OT_unselect_task(Operator):
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
|
class VSETB_OT_add_import_template(Operator):
|
||||||
|
bl_idname = "vse_toolbox.add_import_template"
|
||||||
|
bl_label = "Add Template"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
scn = context.scene
|
||||||
|
settings = get_scene_settings()
|
||||||
|
project = settings.active_project
|
||||||
|
|
||||||
|
project.import_shots.video_templates.add()
|
||||||
|
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
|
class VSETB_OT_remove_import_template(Operator):
|
||||||
|
bl_idname = "vse_toolbox.remove_import_template"
|
||||||
|
bl_label = "Remove Template"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
|
index : IntProperty()
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
scn = context.scene
|
||||||
|
settings = get_scene_settings()
|
||||||
|
project = settings.active_project
|
||||||
|
|
||||||
|
project.import_shots.video_templates.remove(self.index)
|
||||||
|
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
def get_sequence_items(self, context):
|
def get_sequence_items(self, context):
|
||||||
settings = get_scene_settings()
|
settings = get_scene_settings()
|
||||||
project = settings.active_project
|
project = settings.active_project
|
||||||
|
@ -351,6 +383,9 @@ class VSETB_OT_import_shots(Operator):
|
||||||
if not last_comment:
|
if not last_comment:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
last_preview = last_comment['previews'][0]
|
||||||
|
|
||||||
|
ext = last_preview['extension']
|
||||||
shot_name = shot['name']
|
shot_name = shot['name']
|
||||||
sequence_name = f"{shot['sequence_name']}_"
|
sequence_name = f"{shot['sequence_name']}_"
|
||||||
if shot_name.startswith(sequence_name):
|
if shot_name.startswith(sequence_name):
|
||||||
|
@ -358,10 +393,9 @@ class VSETB_OT_import_shots(Operator):
|
||||||
|
|
||||||
preview_dir = self.get_preview_dir()
|
preview_dir = self.get_preview_dir()
|
||||||
|
|
||||||
filepath = Path(preview_dir, f'{sequence_name}{shot_name}_{task_type.name}')
|
filepath = Path(preview_dir, f'{sequence_name}{shot_name}_{task_type.name}.{ext}')
|
||||||
filepath.parent.mkdir(parents=True, exist_ok=True)
|
filepath.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
last_preview = last_comment['previews'][0]
|
|
||||||
tracker.download_preview_file(last_preview, str(filepath))
|
tracker.download_preview_file(last_preview, str(filepath))
|
||||||
|
|
||||||
return filepath
|
return filepath
|
||||||
|
@ -378,17 +412,20 @@ class VSETB_OT_import_shots(Operator):
|
||||||
settings = get_scene_settings()
|
settings = get_scene_settings()
|
||||||
project = settings.active_project
|
project = settings.active_project
|
||||||
import_shots = project.import_shots
|
import_shots = project.import_shots
|
||||||
|
project_templates = {t.name: t.value for t in project.templates}
|
||||||
|
|
||||||
pattern = Path(
|
for template in [import_shots.video_template] + list(import_shots.video_templates.keys()):
|
||||||
import_shots.shot_folder_template,
|
|
||||||
import_shots.import_video_template)
|
|
||||||
|
|
||||||
# Normalize name in snake_case for now
|
template = expand(template, **project_templates)
|
||||||
sequence = sequence.name.lower().replace(' ', '_')
|
|
||||||
shot = parse(project.shot_template, shot_name)['shot']
|
|
||||||
task = task_type.name.lower().replace(' ', '_')
|
|
||||||
|
|
||||||
return find_last(pattern, sequence=sequence, shot=shot, task=task)
|
format_data = project.format_data
|
||||||
|
format_data.update(parse(project.sequence_template, sequence.name))
|
||||||
|
format_data.update(parse(project.shot_template, shot_name))
|
||||||
|
# Normalize name in snake_case for now
|
||||||
|
format_data.update(task=task_type.name.lower().replace(' ', '_'))
|
||||||
|
|
||||||
|
if last_preview := find_last(template, **format_data):
|
||||||
|
return last_preview
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
scn = context.scene
|
scn = context.scene
|
||||||
|
@ -405,6 +442,9 @@ class VSETB_OT_import_shots(Operator):
|
||||||
|
|
||||||
conformed = False
|
conformed = False
|
||||||
|
|
||||||
|
scn.sequence_editor_clear()
|
||||||
|
scn.sequence_editor_create()
|
||||||
|
|
||||||
self.set_sequencer_channels([t.name for t in task_types])
|
self.set_sequencer_channels([t.name for t in task_types])
|
||||||
frame_index = 1
|
frame_index = 1
|
||||||
for sequence in sequences:
|
for sequence in sequences:
|
||||||
|
@ -412,6 +452,7 @@ class VSETB_OT_import_shots(Operator):
|
||||||
sequence_start = frame_index
|
sequence_start = frame_index
|
||||||
for shot_data in shots_data:
|
for shot_data in shots_data:
|
||||||
frames = int(shot_data['nb_frames'])
|
frames = int(shot_data['nb_frames'])
|
||||||
|
frame_end = frame_index + frames
|
||||||
|
|
||||||
strip = scn.sequence_editor.sequences.new_effect(
|
strip = scn.sequence_editor.sequences.new_effect(
|
||||||
name=shot_data['name'],
|
name=shot_data['name'],
|
||||||
|
@ -426,24 +467,22 @@ class VSETB_OT_import_shots(Operator):
|
||||||
for task_type in task_types:
|
for task_type in task_types:
|
||||||
if import_shots.import_source == 'DISK':
|
if import_shots.import_source == 'DISK':
|
||||||
preview = self.find_shot_preview(sequence, shot_data['name'], task_type)
|
preview = self.find_shot_preview(sequence, shot_data['name'], task_type)
|
||||||
#print(videos)
|
|
||||||
#return {"FINISHED"}
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
preview = self.download_preview(task_type, shot_data)
|
preview = self.download_preview(task_type, shot_data)
|
||||||
|
if not preview:
|
||||||
|
print(f'No preview found for shot {shot_data["name"]}')
|
||||||
|
|
||||||
if not preview:
|
if not preview:
|
||||||
print(f'No preview found for shot {shot_data["name"]}')
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
print(f'Loading Preview from {preview}')
|
print(f'Loading Preview from {preview}')
|
||||||
|
|
||||||
# Load Video
|
|
||||||
channel_index = get_channel_index(f'{task_type.name} Video')
|
channel_index = get_channel_index(f'{task_type.name} Video')
|
||||||
video_clip = import_movie(preview)
|
video_clip = import_movie(preview, frame_start=frame_index, frame_end=frame_end)
|
||||||
video_clip.frame_start = frame_index
|
|
||||||
video_clip.channel = channel_index
|
video_clip.channel = channel_index
|
||||||
|
|
||||||
|
if video_clip.frame_offset_end:
|
||||||
|
video_clip.color_tag = 'COLOR_01'
|
||||||
|
|
||||||
if not conformed:
|
if not conformed:
|
||||||
self.conform_render(video_clip)
|
self.conform_render(video_clip)
|
||||||
conformed = True
|
conformed = True
|
||||||
|
@ -453,8 +492,10 @@ class VSETB_OT_import_shots(Operator):
|
||||||
# Load Audio
|
# Load Audio
|
||||||
channel_index = get_channel_index(f'{task_type.name} Audio')
|
channel_index = get_channel_index(f'{task_type.name} Audio')
|
||||||
audio_clip = import_sound(preview, frame_start=frame_index,
|
audio_clip = import_sound(preview, frame_start=frame_index,
|
||||||
frame_end=video_clip.frame_final_end)
|
frame_end=frame_end)
|
||||||
audio_clip.channel = channel_index
|
audio_clip.channel = channel_index
|
||||||
|
if video_clip.frame_offset_end:
|
||||||
|
audio_clip.color_tag = 'COLOR_01'
|
||||||
|
|
||||||
frame_index += frames
|
frame_index += frames
|
||||||
|
|
||||||
|
@ -471,6 +512,8 @@ class VSETB_OT_import_shots(Operator):
|
||||||
scn.frame_start = 1
|
scn.frame_start = 1
|
||||||
scn.frame_end = frame_index -1
|
scn.frame_end = frame_index -1
|
||||||
|
|
||||||
|
#bpy.ops.vse_toolbox.set_stamps()
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
|
@ -489,8 +532,16 @@ class VSETB_OT_import_shots(Operator):
|
||||||
|
|
||||||
if import_shots.import_source == 'DISK':
|
if import_shots.import_source == 'DISK':
|
||||||
#col.prop(import_shots, "sequence_dir_template", text='Sequence Dir')
|
#col.prop(import_shots, "sequence_dir_template", text='Sequence Dir')
|
||||||
col.prop(import_shots, "shot_folder_template", text='Shot Folder')
|
#col.prop(import_shots, "shot_folder_template", text='Shot Folder')
|
||||||
col.prop(import_shots, "import_video_template", text='Video')
|
row = col.row(align=True)
|
||||||
|
row.prop(import_shots, "video_template", text='')
|
||||||
|
row.operator("vse_toolbox.add_import_template", text='', icon='ADD')
|
||||||
|
|
||||||
|
for i, template in enumerate(import_shots.video_templates):
|
||||||
|
row = col.row(align=True)
|
||||||
|
row.prop(template, "name", text='')
|
||||||
|
row.operator("vse_toolbox.remove_import_template", text='', icon='REMOVE').index=i
|
||||||
|
|
||||||
col.separator()
|
col.separator()
|
||||||
else:
|
else:
|
||||||
col.prop(import_shots, "previews_folder", text='Previews Folder')
|
col.prop(import_shots, "previews_folder", text='Previews Folder')
|
||||||
|
@ -579,7 +630,7 @@ class VSETB_OT_import_shots(Operator):
|
||||||
# self.report({"ERROR"}, "Save your Blender file first")
|
# self.report({"ERROR"}, "Save your Blender file first")
|
||||||
# return {"CANCELLED"}
|
# return {"CANCELLED"}
|
||||||
|
|
||||||
return context.window_manager.invoke_props_dialog(self, width=400)
|
return context.window_manager.invoke_props_dialog(self, width=350)
|
||||||
|
|
||||||
def check(self, context):
|
def check(self, context):
|
||||||
return True
|
return True
|
||||||
|
@ -590,6 +641,8 @@ classes = (
|
||||||
VSETB_OT_unselect_sequence,
|
VSETB_OT_unselect_sequence,
|
||||||
VSETB_OT_unselect_task,
|
VSETB_OT_unselect_task,
|
||||||
VSETB_OT_select_task,
|
VSETB_OT_select_task,
|
||||||
|
VSETB_OT_add_import_template,
|
||||||
|
VSETB_OT_remove_import_template,
|
||||||
VSETB_UL_import_task,
|
VSETB_UL_import_task,
|
||||||
VSETB_OT_auto_select_files,
|
VSETB_OT_auto_select_files,
|
||||||
VSETB_OT_import_files,
|
VSETB_OT_import_files,
|
||||||
|
|
|
@ -155,7 +155,7 @@ class VSETB_OT_set_sequencer(Operator):
|
||||||
|
|
||||||
scn.view_settings.view_transform = 'Standard'
|
scn.view_settings.view_transform = 'Standard'
|
||||||
scn.render.image_settings.file_format = 'FFMPEG'
|
scn.render.image_settings.file_format = 'FFMPEG'
|
||||||
scn.render.ffmpeg.gopsize = 5
|
scn.render.ffmpeg.gopsize = 8
|
||||||
scn.render.ffmpeg.constant_rate_factor = 'HIGH'
|
scn.render.ffmpeg.constant_rate_factor = 'HIGH'
|
||||||
scn.render.ffmpeg.format = 'QUICKTIME'
|
scn.render.ffmpeg.format = 'QUICKTIME'
|
||||||
scn.render.ffmpeg.audio_codec = 'AAC'
|
scn.render.ffmpeg.audio_codec = 'AAC'
|
||||||
|
@ -304,8 +304,18 @@ class VSETB_OT_open_shot_folder(Operator):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
|
settings = get_scene_settings()
|
||||||
|
project = settings.active_project
|
||||||
|
if not project.templates.get('shot_dir'):
|
||||||
|
cls.poll_message_set('No shot_dir template setted')
|
||||||
|
return
|
||||||
|
|
||||||
strip = context.active_sequence_strip
|
strip = context.active_sequence_strip
|
||||||
return strip and get_channel_name(strip) == 'Shots'
|
if not strip or get_channel_name(strip) != 'Shots':
|
||||||
|
cls.poll_message_set('No shot strip active')
|
||||||
|
return
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
strip = context.active_sequence_strip
|
strip = context.active_sequence_strip
|
||||||
|
@ -316,7 +326,7 @@ class VSETB_OT_open_shot_folder(Operator):
|
||||||
|
|
||||||
format_data = {**settings.format_data, **project.format_data, **strip_settings.format_data}
|
format_data = {**settings.format_data, **project.format_data, **strip_settings.format_data}
|
||||||
|
|
||||||
shot_folder_template = expandvars(project.import_shots.shot_folder_template)
|
shot_folder_template = expandvars(project.templates['shot_dir'].value)
|
||||||
shot_folder_path = shot_folder_template.format(**format_data)
|
shot_folder_path = shot_folder_template.format(**format_data)
|
||||||
bpy.ops.wm.path_open(filepath=shot_folder_path)
|
bpy.ops.wm.path_open(filepath=shot_folder_path)
|
||||||
|
|
||||||
|
|
|
@ -12,10 +12,11 @@ from bpy.props import (BoolProperty, EnumProperty, StringProperty)
|
||||||
|
|
||||||
from vse_toolbox.constants import (ASSET_PREVIEWS, PREVIEWS_DIR, ASSET_ITEMS)
|
from vse_toolbox.constants import (ASSET_PREVIEWS, PREVIEWS_DIR, ASSET_ITEMS)
|
||||||
|
|
||||||
from vse_toolbox.sequencer_utils import (get_strips, get_strip_render_path, get_strip_sequence_name)
|
from vse_toolbox.sequencer_utils import (get_strips, get_strip_render_path, get_strip_sequence_name,
|
||||||
|
render_strip, get_render_attributes)
|
||||||
|
|
||||||
from vse_toolbox.bl_utils import (get_addon_prefs, get_scene_settings)
|
from vse_toolbox.bl_utils import (get_addon_prefs, get_scene_settings)
|
||||||
from vse_toolbox.file_utils import (norm_name,)
|
from vse_toolbox.file_utils import (norm_name, expand)
|
||||||
from bpy.app.handlers import persistent
|
from bpy.app.handlers import persistent
|
||||||
|
|
||||||
|
|
||||||
|
@ -36,7 +37,7 @@ class VSETB_OT_tracker_connect(Operator):
|
||||||
settings = get_scene_settings()
|
settings = get_scene_settings()
|
||||||
try:
|
try:
|
||||||
prefs.tracker.connect()
|
prefs.tracker.connect()
|
||||||
self.report({'INFO'}, f'Sucessfully login to {settings.tracker_name.title()}')
|
self.report({'INFO'}, f'successfully login to {settings.tracker_name.title()}')
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print('e: ', e)
|
print('e: ', e)
|
||||||
|
@ -121,6 +122,10 @@ class VSETB_OT_load_projects(Operator):
|
||||||
(r,g,b), a = map(lambda component: component / 255, bytes.fromhex(color_str[-6:])), 1.0
|
(r,g,b), a = map(lambda component: component / 255, bytes.fromhex(color_str[-6:])), 1.0
|
||||||
return (r,g,b,a)
|
return (r,g,b,a)
|
||||||
|
|
||||||
|
def invoke(self, context, event):
|
||||||
|
self.ctrl = event.ctrl
|
||||||
|
return self.execute(context)
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
settings = get_scene_settings()
|
settings = get_scene_settings()
|
||||||
prefs = get_addon_prefs()
|
prefs = get_addon_prefs()
|
||||||
|
@ -213,7 +218,8 @@ class VSETB_OT_load_projects(Operator):
|
||||||
if project.name not in project_names:
|
if project.name not in project_names:
|
||||||
settings.projects.remove(list(settings.projects).index(project))
|
settings.projects.remove(list(settings.projects).index(project))
|
||||||
|
|
||||||
bpy.ops.vse_toolbox.load_settings()
|
if self.ctrl or not settings.get('projects_loaded'):
|
||||||
|
bpy.ops.vse_toolbox.load_settings()
|
||||||
|
|
||||||
if prev_project_name != '/' and prev_project_name in settings.projects:
|
if prev_project_name != '/' and prev_project_name in settings.projects:
|
||||||
settings.project_name = prev_project_name
|
settings.project_name = prev_project_name
|
||||||
|
@ -221,6 +227,7 @@ class VSETB_OT_load_projects(Operator):
|
||||||
#if settings.active_project:
|
#if settings.active_project:
|
||||||
# settings.active_project.set_strip_metadata()
|
# settings.active_project.set_strip_metadata()
|
||||||
|
|
||||||
|
settings['projects_loaded'] = True
|
||||||
|
|
||||||
self.report({"INFO"}, 'Successfully Load Tracker Projects')
|
self.report({"INFO"}, 'Successfully Load Tracker Projects')
|
||||||
|
|
||||||
|
@ -251,19 +258,16 @@ class VSETB_OT_new_episode(Operator):
|
||||||
tracker = prefs.tracker
|
tracker = prefs.tracker
|
||||||
|
|
||||||
episode_name = settings.episode_template.format(index=int(self.episode_name))
|
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)
|
episode = tracker.get_episode(episode_name)
|
||||||
if episode:
|
if episode:
|
||||||
self.report({'ERROR'}, f'Episode {episode_name} already exists')
|
self.report({'ERROR'}, f'Episode {episode_name} already exists')
|
||||||
return {"CANCELLED"}
|
return {"CANCELLED"}
|
||||||
|
|
||||||
tracker.new_episode(episode_name)
|
tracker.new_episode(episode_name)
|
||||||
# tracker.get_episodes
|
|
||||||
tracker.update_project()
|
tracker.update_project()
|
||||||
|
|
||||||
self.report({'INFO'}, f'Episode {episode_name} successfully created')
|
self.report({'INFO'}, f'Episode {episode_name} successfully created')
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
|
@ -302,8 +306,6 @@ class VSETB_OT_upload_to_tracker(Operator):
|
||||||
col.use_property_split = False
|
col.use_property_split = False
|
||||||
col.prop(upload_to_tracker, 'render_strip_template', text='')
|
col.prop(upload_to_tracker, 'render_strip_template', text='')
|
||||||
col.use_property_split = True
|
col.use_property_split = True
|
||||||
#else:
|
|
||||||
# col.label(text=f'Source: {self.project.render_video_strip_template}')
|
|
||||||
|
|
||||||
col.separator()
|
col.separator()
|
||||||
|
|
||||||
|
@ -329,7 +331,11 @@ class VSETB_OT_upload_to_tracker(Operator):
|
||||||
#self.report({'ERROR'}, f'Export not implemented yet.')
|
#self.report({'ERROR'}, f'Export not implemented yet.')
|
||||||
prefs = get_addon_prefs()
|
prefs = get_addon_prefs()
|
||||||
settings = get_scene_settings()
|
settings = get_scene_settings()
|
||||||
|
tracker = prefs.tracker
|
||||||
|
|
||||||
upload_to_tracker = self.project.upload_to_tracker
|
upload_to_tracker = self.project.upload_to_tracker
|
||||||
|
render_attrs = get_render_attributes()
|
||||||
|
project_templates = {t.name: t.value for t in self.project.templates}
|
||||||
|
|
||||||
episode = None
|
episode = None
|
||||||
if settings.active_episode:
|
if settings.active_episode:
|
||||||
|
@ -337,13 +343,15 @@ class VSETB_OT_upload_to_tracker(Operator):
|
||||||
|
|
||||||
format_data = {**settings.format_data, **self.project.format_data}
|
format_data = {**settings.format_data, **self.project.format_data}
|
||||||
|
|
||||||
tracker = prefs.tracker
|
|
||||||
|
|
||||||
status = upload_to_tracker.status
|
status = upload_to_tracker.status
|
||||||
if status == 'CURRENT':
|
if status == 'CURRENT':
|
||||||
status = None
|
status = None
|
||||||
|
|
||||||
for strip in get_strips(channel='Shots', selected_only=True):
|
shot_strips = get_strips(channel='Shots', selected_only=True)
|
||||||
|
context.window_manager.progress_begin(0, len(shot_strips))
|
||||||
|
|
||||||
|
for i, strip in enumerate(shot_strips):
|
||||||
|
context.window_manager.progress_update(i)
|
||||||
strip_settings = strip.vsetb_strip_settings
|
strip_settings = strip.vsetb_strip_settings
|
||||||
sequence_name = get_strip_sequence_name(strip)
|
sequence_name = get_strip_sequence_name(strip)
|
||||||
shot_name = strip.name
|
shot_name = strip.name
|
||||||
|
@ -369,12 +377,17 @@ class VSETB_OT_upload_to_tracker(Operator):
|
||||||
|
|
||||||
strip_data = {**format_data, **strip_settings.format_data}
|
strip_data = {**format_data, **strip_settings.format_data}
|
||||||
if upload_to_tracker.render_strips:
|
if upload_to_tracker.render_strips:
|
||||||
preview_template = expandvars(upload_to_tracker.render_strip_template)
|
preview_template = expand(upload_to_tracker.render_strip_template, **project_templates)
|
||||||
|
strip_data['ext'] = 'mov'
|
||||||
else:
|
else:
|
||||||
preview_template = expandvars(self.project.render_video_strip_template)
|
preview_template = expandvars(self.project.render_video_strip_template)
|
||||||
|
|
||||||
preview = preview_template.format(**strip_data)
|
preview = preview_template.format(**strip_data)
|
||||||
preview = Path(os.path.abspath(bpy.path.abspath(preview)))
|
preview = Path(os.path.abspath(bpy.path.abspath(preview)))
|
||||||
|
|
||||||
|
if upload_to_tracker.render_strips:
|
||||||
|
render_strip(strip, preview, attributes=render_attrs)
|
||||||
|
|
||||||
#print(preview)
|
#print(preview)
|
||||||
if not preview.exists():
|
if not preview.exists():
|
||||||
print(f'The preview {preview} not exists')
|
print(f'The preview {preview} not exists')
|
||||||
|
@ -387,7 +400,7 @@ class VSETB_OT_upload_to_tracker(Operator):
|
||||||
preview = None
|
preview = None
|
||||||
|
|
||||||
comment_data = None
|
comment_data = None
|
||||||
if status or comment or preview:
|
if status or upload_to_tracker.comment or preview:
|
||||||
comment_data = tracker.new_comment(task, comment=upload_to_tracker.comment, status=status)
|
comment_data = tracker.new_comment(task, comment=upload_to_tracker.comment, status=status)
|
||||||
if preview:
|
if preview:
|
||||||
print('Upload preview from', preview)
|
print('Upload preview from', preview)
|
||||||
|
@ -423,6 +436,8 @@ class VSETB_OT_upload_to_tracker(Operator):
|
||||||
if task.comment and tracker_task.get('last_comment') != task.comment:
|
if task.comment and tracker_task.get('last_comment') != task.comment:
|
||||||
tracker.new_comment(tracker_task, comment=task.comment)
|
tracker.new_comment(tracker_task, comment=task.comment)
|
||||||
|
|
||||||
|
context.window_manager.progress_end()
|
||||||
|
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
@ -448,6 +463,7 @@ class VSETB_OT_open_shot_on_tracker(Operator):
|
||||||
|
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
@persistent
|
@persistent
|
||||||
def set_asset_items(scene=None):
|
def set_asset_items(scene=None):
|
||||||
ASSET_ITEMS.clear()
|
ASSET_ITEMS.clear()
|
||||||
|
|
|
@ -78,7 +78,7 @@ class Kitsu(Tracker):
|
||||||
print(f'Info: Log in to kitsu as {login}')
|
print(f'Info: Log in to kitsu as {login}')
|
||||||
res = gazu.log_in(login, password)
|
res = gazu.log_in(login, password)
|
||||||
LOGIN = login
|
LOGIN = login
|
||||||
print(f'Info: Sucessfully login to Kitsu as {res["user"]["full_name"]}')
|
print(f'Info: successfully login to Kitsu as {res["user"]["full_name"]}')
|
||||||
return res['user']
|
return res['user']
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f'Error: {traceback.format_exc()}')
|
print(f'Error: {traceback.format_exc()}')
|
||||||
|
|
|
@ -16,6 +16,19 @@ import subprocess
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
|
|
||||||
|
def get_render_attributes():
|
||||||
|
scn = bpy.context.scene
|
||||||
|
return [
|
||||||
|
(scn.view_settings, "view_transform", 'Standard'),
|
||||||
|
(scn.render.image_settings, "file_format", 'FFMPEG'),
|
||||||
|
(scn.render.ffmpeg, "gopsize", 8),
|
||||||
|
(scn.render.ffmpeg, "constant_rate_factor", 'HIGH'),
|
||||||
|
(scn.render.ffmpeg, "format", 'QUICKTIME'),
|
||||||
|
(scn.render.ffmpeg, "audio_codec", 'MP3'),
|
||||||
|
(scn.render.ffmpeg, "audio_mixrate", 44100),
|
||||||
|
(scn.render.ffmpeg, "audio_bitrate", 128)
|
||||||
|
]
|
||||||
|
|
||||||
def frame_to_timecode(frame, fps):
|
def frame_to_timecode(frame, fps):
|
||||||
total_seconds = frame / fps
|
total_seconds = frame / fps
|
||||||
|
|
||||||
|
@ -109,20 +122,23 @@ def rename_strips(strips, template, increment=10, start_number=0, padding=3, by_
|
||||||
strip_number = 0
|
strip_number = 0
|
||||||
|
|
||||||
for strip in strips:
|
for strip in strips:
|
||||||
|
channel = get_channel_name(strip)
|
||||||
sequence_name = get_strip_sequence_name(strip)
|
sequence_name = get_strip_sequence_name(strip)
|
||||||
sequence_data = parse(project.sequence_template, sequence_name)
|
format_data = {}
|
||||||
|
if channel == 'Shots':
|
||||||
|
format_data = parse(project.sequence_template, sequence_name)
|
||||||
|
else:
|
||||||
|
format_data['sequence'] = str(strip_number*increment + start_number).zfill(padding)
|
||||||
|
|
||||||
if (by_sequence and prev_sequence_name and
|
if (by_sequence and prev_sequence_name and
|
||||||
sequence_name and sequence_name != prev_sequence_name):
|
sequence_name and sequence_name != prev_sequence_name):
|
||||||
strip_number = 0
|
strip_number = 0
|
||||||
|
|
||||||
format_data = dict(
|
format_data.update(
|
||||||
sequence_strip=sequence_name,
|
sequence_strip=sequence_name,
|
||||||
episode=episode_name,
|
episode=episode_name,
|
||||||
shot=str(strip_number*increment + start_number).zfill(padding))
|
shot=str(strip_number*increment + start_number).zfill(padding))
|
||||||
|
|
||||||
format_data.update(sequence_data)
|
|
||||||
|
|
||||||
name = template.format(**format_data)
|
name = template.format(**format_data)
|
||||||
|
|
||||||
existing_strip = scn.sequence_editor.sequences_all.get(name)
|
existing_strip = scn.sequence_editor.sequences_all.get(name)
|
||||||
|
@ -270,26 +286,32 @@ def render_sound(strip, output):
|
||||||
scn.frame_end = scene_end
|
scn.frame_end = scene_end
|
||||||
scn.frame_current = scene_current
|
scn.frame_current = scene_current
|
||||||
|
|
||||||
def render_scene(output):
|
def render_scene(output, attributes=None):
|
||||||
output = os.path.abspath(bpy.path.abspath(output))
|
output = os.path.abspath(bpy.path.abspath(str(output)))
|
||||||
|
|
||||||
scn = bpy.context.scene
|
scn = bpy.context.scene
|
||||||
render_path = scn.render.filepath
|
render_path = scn.render.filepath
|
||||||
|
|
||||||
scn.render.filepath = output
|
if attributes is None:
|
||||||
|
attributes = []
|
||||||
|
|
||||||
|
attributes += [
|
||||||
|
(scn.render, "filepath", output),
|
||||||
|
]
|
||||||
|
|
||||||
print(f'Render Strip to {scn.render.filepath}')
|
print(f'Render Strip to {scn.render.filepath}')
|
||||||
Path(output).parent.mkdir(exist_ok=True, parents=True)
|
Path(output).parent.mkdir(exist_ok=True, parents=True)
|
||||||
bpy.ops.render.opengl(animation=True, sequencer=True)
|
bpy.ops.render.opengl(animation=True, sequencer=True)
|
||||||
|
|
||||||
scn.render.filepath = render_path
|
def render_strip(strip, output, attributes=None):
|
||||||
|
output = os.path.abspath(bpy.path.abspath(str(output)))
|
||||||
def render_strip(strip, output):
|
|
||||||
output = os.path.abspath(bpy.path.abspath(output))
|
|
||||||
|
|
||||||
scn = bpy.context.scene
|
scn = bpy.context.scene
|
||||||
|
|
||||||
attributes = [
|
if attributes is None:
|
||||||
|
attributes = []
|
||||||
|
|
||||||
|
attributes += [
|
||||||
(scn, "frame_start", strip.frame_final_start),
|
(scn, "frame_start", strip.frame_final_start),
|
||||||
(scn, "frame_end", strip.frame_final_end - 1),
|
(scn, "frame_end", strip.frame_final_end - 1),
|
||||||
(scn, "frame_current"),
|
(scn, "frame_current"),
|
||||||
|
@ -316,7 +338,6 @@ def import_edit(filepath, adapter="cmx_3600", channel='Shots', match_by='name'):
|
||||||
for s in strips:
|
for s in strips:
|
||||||
s.channel = empty_channel
|
s.channel = empty_channel
|
||||||
|
|
||||||
|
|
||||||
edl = Path(filepath)
|
edl = Path(filepath)
|
||||||
try:
|
try:
|
||||||
timeline = opentimelineio.adapters.read_from_file(
|
timeline = opentimelineio.adapters.read_from_file(
|
||||||
|
@ -397,9 +418,12 @@ def import_edit(filepath, adapter="cmx_3600", channel='Shots', match_by='name'):
|
||||||
scn.frame_end = frame_end-1
|
scn.frame_end = frame_end-1
|
||||||
return timeline
|
return timeline
|
||||||
|
|
||||||
def import_movie(filepath):
|
def import_movie(filepath, frame_start=None, frame_end=None):
|
||||||
scn = bpy.context.scene
|
scn = bpy.context.scene
|
||||||
|
|
||||||
|
if frame_start is None:
|
||||||
|
frame_start = scn.frame_start
|
||||||
|
|
||||||
res_x = scn.render.resolution_x
|
res_x = scn.render.resolution_x
|
||||||
res_y = scn.render.resolution_y
|
res_y = scn.render.resolution_y
|
||||||
|
|
||||||
|
@ -412,7 +436,7 @@ def import_movie(filepath):
|
||||||
name=Path(filepath).stem,
|
name=Path(filepath).stem,
|
||||||
filepath=str(filepath),
|
filepath=str(filepath),
|
||||||
channel=get_channel_index('Movie'),
|
channel=get_channel_index('Movie'),
|
||||||
frame_start=scn.frame_start
|
frame_start=frame_start
|
||||||
)
|
)
|
||||||
|
|
||||||
elem = strip.strip_elem_from_frame(scn.frame_current)
|
elem = strip.strip_elem_from_frame(scn.frame_current)
|
||||||
|
@ -423,7 +447,8 @@ def import_movie(filepath):
|
||||||
if src_height != res_y:
|
if src_height != res_y:
|
||||||
strip.transform.scale_y = (res_y / src_height)
|
strip.transform.scale_y = (res_y / src_height)
|
||||||
|
|
||||||
|
if frame_end is not None:
|
||||||
|
strip.frame_final_end = frame_end
|
||||||
|
|
||||||
return strip
|
return strip
|
||||||
|
|
||||||
|
|
36
ui/panels.py
36
ui/panels.py
|
@ -39,21 +39,53 @@ class VSETB_PT_main(VSETB_main, Panel):
|
||||||
# row.operator('vse_toolbox.load_projects', icon='FILE_REFRESH', text='', emboss=False)
|
# row.operator('vse_toolbox.load_projects', icon='FILE_REFRESH', text='', emboss=False)
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
wm = context.window_manager
|
wm = context.window_manager
|
||||||
scn = context.scene
|
scn = context.scene
|
||||||
settings = get_scene_settings()
|
settings = get_scene_settings()
|
||||||
prefs = get_addon_prefs()
|
prefs = get_addon_prefs()
|
||||||
|
|
||||||
row = self.layout.row(align=False)
|
row = layout.row(align=True)
|
||||||
|
|
||||||
row.operator('vse_toolbox.load_projects', icon='FILE_REFRESH', text='', emboss=False)
|
row.operator('vse_toolbox.load_projects', icon='FILE_REFRESH', text='', emboss=False)
|
||||||
|
row.separator(factor=0.5)
|
||||||
row.prop(settings, 'project_name', text='')
|
row.prop(settings, 'project_name', text='')
|
||||||
|
|
||||||
project = settings.active_project
|
project = settings.active_project
|
||||||
|
|
||||||
if project and project.type == 'TVSHOW':
|
if project and project.type == 'TVSHOW':
|
||||||
|
row.separator(factor=0.5)
|
||||||
row.prop(project, 'episode_name', text='')
|
row.prop(project, 'episode_name', text='')
|
||||||
|
|
||||||
|
row.separator(factor=0.5)
|
||||||
|
row.prop(project, "show_settings", icon="PREFERENCES", text='')
|
||||||
|
if project.show_settings:
|
||||||
|
box = layout.box()
|
||||||
|
split = box.split(factor=0.3)
|
||||||
|
name_col = split.column()
|
||||||
|
template_col = split.column()
|
||||||
|
|
||||||
|
row = name_col.row(align=True) # Padding
|
||||||
|
row.separator(factor=0.5)
|
||||||
|
row.label(text="Name")
|
||||||
|
|
||||||
|
row = template_col.row(align=True) # Padding
|
||||||
|
row.separator(factor=0.5)
|
||||||
|
row.label(text="Template")
|
||||||
|
|
||||||
|
row.operator("vse_toolbox.add_template", text="", icon='ADD', emboss=False)
|
||||||
|
|
||||||
|
for i, template in enumerate(project.templates):
|
||||||
|
row = name_col.row()
|
||||||
|
row.prop(template, "name", text="")
|
||||||
|
|
||||||
|
row = template_col.row(align=True)
|
||||||
|
subrow = row.row()
|
||||||
|
subrow.prop(template, "value", text="")
|
||||||
|
row.separator(factor=0.25)
|
||||||
|
row.operator("vse_toolbox.remove_template", text="", icon='REMOVE', emboss=False).index = i
|
||||||
|
|
||||||
|
|
||||||
# settings = get_scene_settings()
|
# settings = get_scene_settings()
|
||||||
# prefs = get_addon_prefs()
|
# prefs = get_addon_prefs()
|
||||||
|
|
||||||
|
@ -173,7 +205,7 @@ class VSETB_PT_settings(VSETB_main, Panel):
|
||||||
class VSETB_PT_imports(VSETB_main, Panel):
|
class VSETB_PT_imports(VSETB_main, Panel):
|
||||||
bl_label = "Imports"
|
bl_label = "Imports"
|
||||||
#bl_parent_id = "VSETB_PT_main"
|
#bl_parent_id = "VSETB_PT_main"
|
||||||
bl_options = {'DEFAULT_CLOSED'}
|
#bl_options = {'DEFAULT_CLOSED'}
|
||||||
|
|
||||||
def draw_header_preset(self, context):
|
def draw_header_preset(self, context):
|
||||||
self.layout.operator('vse_toolbox.import_files', icon='IMPORT', text='', emboss=False)
|
self.layout.operator('vse_toolbox.import_files', icon='IMPORT', text='', emboss=False)
|
||||||
|
|
|
@ -63,6 +63,7 @@ def load_trackers():
|
||||||
print(f'Could not register Tracker {name}')
|
print(f'Could not register Tracker {name}')
|
||||||
print(e)
|
print(e)
|
||||||
|
|
||||||
|
|
||||||
def load_prefs():
|
def load_prefs():
|
||||||
prefs = get_addon_prefs()
|
prefs = get_addon_prefs()
|
||||||
prefs_config_file = prefs.config_path
|
prefs_config_file = prefs.config_path
|
||||||
|
@ -72,6 +73,9 @@ def load_prefs():
|
||||||
|
|
||||||
prefs_datas = read_file(os.path.expandvars(prefs_config_file))
|
prefs_datas = read_file(os.path.expandvars(prefs_config_file))
|
||||||
|
|
||||||
|
if not prefs_datas:
|
||||||
|
return
|
||||||
|
|
||||||
for tracker_data in prefs_datas['trackers']:
|
for tracker_data in prefs_datas['trackers']:
|
||||||
tracker_name = norm_str(tracker_data['name'])
|
tracker_name = norm_str(tracker_data['name'])
|
||||||
if not hasattr(prefs.trackers, tracker_name):
|
if not hasattr(prefs.trackers, tracker_name):
|
||||||
|
|
|
@ -159,6 +159,10 @@ class Episode(PropertyGroup):
|
||||||
return self.get(settings.project_name)
|
return self.get(settings.project_name)
|
||||||
|
|
||||||
|
|
||||||
|
class Template(PropertyGroup):
|
||||||
|
value : StringProperty()
|
||||||
|
|
||||||
|
|
||||||
class SpreadsheetExportCell(PropertyGroup):
|
class SpreadsheetExportCell(PropertyGroup):
|
||||||
export_name : StringProperty()
|
export_name : StringProperty()
|
||||||
enabled : BoolProperty(default=True)
|
enabled : BoolProperty(default=True)
|
||||||
|
@ -241,19 +245,21 @@ def get_task_type_items(self, context):
|
||||||
class ImportShots(PropertyGroup):
|
class ImportShots(PropertyGroup):
|
||||||
import_source: EnumProperty(items=[(i, i.title(), '') for i in ('DISK', 'TRACKER')])
|
import_source: EnumProperty(items=[(i, i.title(), '') for i in ('DISK', 'TRACKER')])
|
||||||
import_task: EnumProperty(items=[(i, i.title().replace('_', ' '), '')
|
import_task: EnumProperty(items=[(i, i.title().replace('_', ' '), '')
|
||||||
for i in ('LAST', 'FROM_LIST', 'ALL')], default='FROM_LIST')
|
for i in ('FROM_LIST',)], default='FROM_LIST') #('LAST', 'FROM_LIST', 'ALL')
|
||||||
|
|
||||||
#sequence_dir_template: StringProperty(
|
#sequence_dir_template: StringProperty(
|
||||||
# name="Sequence Template", default="$PROJECT_ROOT/sequences/{sequence}")
|
# name="Sequence Template", default="$PROJECT_ROOT/sequences/{sequence}")
|
||||||
|
|
||||||
shot_folder_template: StringProperty(
|
#shot_folder_template: StringProperty(
|
||||||
name="Shot Template", default="$PROJECT_ROOT/sequences/sq{sequence}/sh{shot}")
|
# name="Shot Template", default="$PROJECT_ROOT/sequences/sq{sequence}/sh{shot}")
|
||||||
|
|
||||||
import_video_template : StringProperty(
|
video_template : StringProperty(
|
||||||
name="Video Path", default="./{task}/render/{version}.{ext}")
|
name="Video Path", default="//sources/{sequence}_{shot}_{task}.{ext}")
|
||||||
|
|
||||||
|
video_templates : CollectionProperty(type=PropertyGroup)
|
||||||
|
|
||||||
import_sequence: EnumProperty(items=[(i, i.title().replace('_', ' '), '')
|
import_sequence: EnumProperty(items=[(i, i.title().replace('_', ' '), '')
|
||||||
for i in ('SELECTED_STRIPS', 'FROM_LIST', 'ALL')], default='FROM_LIST')
|
for i in ('FROM_LIST',)], default='FROM_LIST') #('SELECTED_STRIPS', 'FROM_LIST', 'ALL')
|
||||||
|
|
||||||
previews_folder: StringProperty(
|
previews_folder: StringProperty(
|
||||||
name="Previews Folder", default="//sources", subtype='DIR_PATH')
|
name="Previews Folder", default="//sources", subtype='DIR_PATH')
|
||||||
|
@ -262,7 +268,7 @@ class ImportShots(PropertyGroup):
|
||||||
class UploadToTracker(PropertyGroup):
|
class UploadToTracker(PropertyGroup):
|
||||||
render_strips: BoolProperty(default=False)
|
render_strips: BoolProperty(default=False)
|
||||||
render_strip_template : StringProperty(
|
render_strip_template : StringProperty(
|
||||||
name="Movie Path", default="//render/{project_basename}.{ext}")
|
name="Movie Path", default="//render/{strip}.{ext}")
|
||||||
|
|
||||||
task : EnumProperty(items=get_task_type_items)
|
task : EnumProperty(items=get_task_type_items)
|
||||||
status : EnumProperty(items=get_task_status_items)
|
status : EnumProperty(items=get_task_status_items)
|
||||||
|
@ -297,6 +303,9 @@ def on_episode_updated(self, context):
|
||||||
class Project(PropertyGroup):
|
class Project(PropertyGroup):
|
||||||
id : StringProperty(default='')
|
id : StringProperty(default='')
|
||||||
|
|
||||||
|
show_settings : BoolProperty()
|
||||||
|
templates : CollectionProperty(type=Template)
|
||||||
|
|
||||||
shot_start_number : IntProperty(name="Shot Start Number", default=10, min=0)
|
shot_start_number : IntProperty(name="Shot Start Number", default=10, min=0)
|
||||||
shot_padding : IntProperty(name="Shot Padding", default=4, min=0, max=10)
|
shot_padding : IntProperty(name="Shot Padding", default=4, min=0, max=10)
|
||||||
|
|
||||||
|
@ -316,28 +325,28 @@ class Project(PropertyGroup):
|
||||||
name="Shot Increment", default=10, min=0, step=10)
|
name="Shot Increment", default=10, min=0, step=10)
|
||||||
|
|
||||||
sequence_template : StringProperty(
|
sequence_template : StringProperty(
|
||||||
name="Sequence Name", default="sq{sequence}")
|
name="Sequence Name", default="{sequence}")
|
||||||
|
|
||||||
episode_template : StringProperty(
|
episode_template : StringProperty(
|
||||||
name="Episode Name", default="ep{episode}")
|
name="Episode Name", default="{episode}")
|
||||||
|
|
||||||
shot_template : StringProperty(
|
shot_template : StringProperty(
|
||||||
name="Shot Name", default="sq{sequence}_sh{shot}")
|
name="Shot Name", default="{sequence}_{shot}")
|
||||||
|
|
||||||
render_video_template : StringProperty(
|
render_video_template : StringProperty(
|
||||||
name="Movie Path", default="//render/{project_basename}.{ext}")
|
name="Movie Path", default="//render/{project}.mov")
|
||||||
|
|
||||||
render_audio_template : StringProperty(
|
render_audio_template : StringProperty(
|
||||||
name="Audio Path", default="//render/{project_basename}.wav")
|
name="Audio Path", default="//render/{project}.wav")
|
||||||
|
|
||||||
render_video_strip_template : StringProperty(
|
render_video_strip_template : StringProperty(
|
||||||
name="Strip Path", default="//render/shots/{strip}.{ext}")
|
name="Strip Path", default="//render/shots/{strip}.mov")
|
||||||
|
|
||||||
render_audio_strip_template: StringProperty(
|
render_audio_strip_template: StringProperty(
|
||||||
name="Sound Path", default="//render/sounds/{strip}.wav")
|
name="Sound Path", default="//render/sounds/{strip}.wav")
|
||||||
|
|
||||||
render_video_sequence_template : StringProperty(
|
render_video_sequence_template : StringProperty(
|
||||||
name="Sequence Path", default="//render/sequences/{sequence}.{ext}")
|
name="Sequence Path", default="//render/sequences/{sequence}.mov")
|
||||||
|
|
||||||
render_audio_sequence_template: StringProperty(
|
render_audio_sequence_template: StringProperty(
|
||||||
name="Sound Path", default="//render/sounds/{sequence}.wav")
|
name="Sound Path", default="//render/sounds/{sequence}.wav")
|
||||||
|
@ -359,7 +368,7 @@ class Project(PropertyGroup):
|
||||||
#render_sound_format: EnumProperty(items=[(e, e, '') for e in ('mp3', 'wav')])
|
#render_sound_format: EnumProperty(items=[(e, e, '') for e in ('mp3', 'wav')])
|
||||||
|
|
||||||
export_edl_template : StringProperty(
|
export_edl_template : StringProperty(
|
||||||
name="Edl Path", default="//render/{project_basename}.edl")
|
name="Edl Path", default="//render/{project}.edl")
|
||||||
|
|
||||||
episode_name : EnumProperty(items=get_episodes_items, update=on_episode_updated)
|
episode_name : EnumProperty(items=get_episodes_items, update=on_episode_updated)
|
||||||
episodes : CollectionProperty(type=Episode)
|
episodes : CollectionProperty(type=Episode)
|
||||||
|
@ -394,6 +403,9 @@ class Project(PropertyGroup):
|
||||||
data['episode'] = norm_str(self.episode_name)
|
data['episode'] = norm_str(self.episode_name)
|
||||||
data['project_basename'] = f"{data['project']}_{data['episode']}"
|
data['project_basename'] = f"{data['project']}_{data['episode']}"
|
||||||
|
|
||||||
|
#for template in self.templates:
|
||||||
|
# data[template.name] = template.value
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def get_cell_types(self):
|
def get_cell_types(self):
|
||||||
|
@ -745,6 +757,7 @@ classes = (
|
||||||
AssetType,
|
AssetType,
|
||||||
TaskStatus,
|
TaskStatus,
|
||||||
Episode,
|
Episode,
|
||||||
|
Template,
|
||||||
Metadata,
|
Metadata,
|
||||||
MetadataType,
|
MetadataType,
|
||||||
Sequence,
|
Sequence,
|
||||||
|
|
Loading…
Reference in New Issue