upload
parent
93134f25a9
commit
d2caf90ea2
|
@ -23,6 +23,8 @@ SOUND_SUFFIXES = ['.mp3', '.aaf', '.flac', '.wav']
|
||||||
CONFIG_DIR = Path(appdirs.user_config_dir(__package__.split('.')[0]))
|
CONFIG_DIR = Path(appdirs.user_config_dir(__package__.split('.')[0]))
|
||||||
PREVIEWS_DIR = CONFIG_DIR / 'thumbnails'
|
PREVIEWS_DIR = CONFIG_DIR / 'thumbnails'
|
||||||
|
|
||||||
|
TASK_ITEMS = []
|
||||||
|
|
||||||
ASSET_PREVIEWS = bpy.utils.previews.new()
|
ASSET_PREVIEWS = bpy.utils.previews.new()
|
||||||
|
|
||||||
CASTING_BUFFER = CONFIG_DIR / 'casting.json'
|
CASTING_BUFFER = CONFIG_DIR / 'casting.json'
|
|
@ -4,6 +4,7 @@ import bpy
|
||||||
import importlib
|
import importlib
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
|
import time
|
||||||
import vse_toolbox
|
import vse_toolbox
|
||||||
|
|
||||||
from bpy_extras.io_utils import ImportHelper
|
from bpy_extras.io_utils import ImportHelper
|
||||||
|
@ -29,6 +30,7 @@ from vse_toolbox.constants import (
|
||||||
PREVIEWS_DIR,
|
PREVIEWS_DIR,
|
||||||
SOUNDS,
|
SOUNDS,
|
||||||
SOUND_SUFFIXES,
|
SOUND_SUFFIXES,
|
||||||
|
TASK_ITEMS
|
||||||
)
|
)
|
||||||
from vse_toolbox.sequencer_utils import (
|
from vse_toolbox.sequencer_utils import (
|
||||||
clean_sequencer,
|
clean_sequencer,
|
||||||
|
@ -41,8 +43,11 @@ from vse_toolbox.sequencer_utils import (
|
||||||
render_strips,
|
render_strips,
|
||||||
set_channels,
|
set_channels,
|
||||||
get_channel_index,
|
get_channel_index,
|
||||||
new_text_strip
|
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.bl_utils import get_addon_prefs, get_scene_settings, get_strip_settings
|
||||||
from vse_toolbox.file_utils import install_module, norm_name, norm_str
|
from vse_toolbox.file_utils import install_module, norm_name, norm_str
|
||||||
|
|
||||||
|
@ -88,6 +93,133 @@ class VSETB_OT_export_csv(Operator):
|
||||||
return {"CANCELLED"}
|
return {"CANCELLED"}
|
||||||
|
|
||||||
|
|
||||||
|
def get_task_status_items(self, context):
|
||||||
|
settings = get_scene_settings()
|
||||||
|
project = settings.active_project
|
||||||
|
|
||||||
|
status_items = [('CURRENT', 'Current', '')]
|
||||||
|
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
|
||||||
|
|
||||||
|
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=False)
|
||||||
|
preview_mode : EnumProperty(items=[(m, m.title().replace('_', ' '), '') for m in ('ONLY_NEW', 'REPLACE', 'ADD')])
|
||||||
|
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
|
||||||
|
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)
|
||||||
|
|
||||||
|
if not sequence:
|
||||||
|
self.report({"INFO"}, f'Create sequence {sequence_name} in Kitsu')
|
||||||
|
sequence = tracker.new_sequence(sequence_name)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
print(task)
|
||||||
|
tracker.new_comment(task, comment=self.comment, status=status)
|
||||||
|
#status = tracker.get_task(shot, self.task)
|
||||||
|
# if self.add_preview:
|
||||||
|
# strip_movie_path = Path(get_strip_render_path(strip, template))
|
||||||
|
# if path.exists():
|
||||||
|
|
||||||
|
# else:
|
||||||
|
# self.report({"WARNING"}, f"{strip_movie_path} not exist, skipped")
|
||||||
|
|
||||||
|
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
# if add_to_kitsu:
|
||||||
|
# shot_name = T['shot_tracker_name'].fields['shot'].format(data['shot'])
|
||||||
|
# seq_name = T['sequence_tracker_name'].fields['sequence'].format(data['sequence'])
|
||||||
|
# sequence = p.sequences.add(seq_name)
|
||||||
|
# shot = sequence.shots.add(shot_name)
|
||||||
|
# animatic_task = shot.tasks.add('animatic')
|
||||||
|
|
||||||
|
# animatic_task.comments.new(
|
||||||
|
# comment=f'Reel edit v{version:03d}',
|
||||||
|
# status='done',
|
||||||
|
# preview=movie_output,
|
||||||
|
# set_main_preview=True
|
||||||
|
# )
|
||||||
|
|
||||||
|
# shot_data = {
|
||||||
|
# 'fps': int(FPS),
|
||||||
|
# 'frame_in': strip.frame_final_start,
|
||||||
|
# 'frame_out': strip.frame_final_end-1,
|
||||||
|
# 'nb_frames': strip.frame_final_duration
|
||||||
|
# }
|
||||||
|
|
||||||
|
# shot.update_data(shot_data)
|
||||||
|
|
||||||
|
# return {"CANCELLED"}
|
||||||
|
|
||||||
|
|
||||||
class VSETB_OT_auto_select_files(Operator):
|
class VSETB_OT_auto_select_files(Operator):
|
||||||
bl_idname = "import.auto_select_files"
|
bl_idname = "import.auto_select_files"
|
||||||
bl_label = "Auto Select"
|
bl_label = "Auto Select"
|
||||||
|
@ -317,8 +449,6 @@ class VSETB_OT_load_projects(Operator):
|
||||||
tracker.connect()
|
tracker.connect()
|
||||||
|
|
||||||
for project_data in tracker.get_projects():
|
for project_data in tracker.get_projects():
|
||||||
|
|
||||||
|
|
||||||
project = settings.projects.add()
|
project = settings.projects.add()
|
||||||
project.type = project_data['production_type'].upper().replace(' ', '')
|
project.type = project_data['production_type'].upper().replace(' ', '')
|
||||||
project.name = project_data['name']
|
project.name = project_data['name']
|
||||||
|
@ -336,6 +466,15 @@ class VSETB_OT_load_projects(Operator):
|
||||||
metadata_type.name = metadata_data['field_name']
|
metadata_type.name = metadata_data['field_name']
|
||||||
metadata_type['choices'] = metadata_data['choices']
|
metadata_type['choices'] = metadata_data['choices']
|
||||||
|
|
||||||
|
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):
|
for asset_type_data in tracker.get_asset_types(project_data):
|
||||||
asset_type = project.asset_types.add()
|
asset_type = project.asset_types.add()
|
||||||
asset_type.name = asset_type_data['name']
|
asset_type.name = asset_type_data['name']
|
||||||
|
@ -465,11 +604,12 @@ class VSETB_OT_render(Operator):
|
||||||
bl_description = "Render Shots Strips"
|
bl_description = "Render Shots Strips"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
selected_only : BoolProperty(name="Selected Only", default=False)
|
#selected_only : BoolProperty(name="Selected Only", default=False)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return True
|
settings = get_scene_settings()
|
||||||
|
return settings.active_project
|
||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
scn = context.scene
|
scn = context.scene
|
||||||
|
@ -485,15 +625,20 @@ class VSETB_OT_render(Operator):
|
||||||
col = layout.column()
|
col = layout.column()
|
||||||
col.use_property_split = True
|
col.use_property_split = True
|
||||||
col.use_property_decorate = False
|
col.use_property_decorate = False
|
||||||
col.prop(settings, 'channel', text='Channel')
|
#col.prop(settings, 'channel', text='Channel')
|
||||||
col.prop(self, 'selected_only')
|
#col.prop(self, 'selected_only')
|
||||||
|
|
||||||
|
col.prop(settings.active_project, "render_template")
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
scn = context.scene
|
scn = context.scene
|
||||||
settings = get_scene_settings()
|
settings = get_scene_settings()
|
||||||
strips = get_strips(channel=settings.channel, selected_only=self.selected_only)
|
strips = get_strips(channel='Shots', selected_only=True)
|
||||||
|
|
||||||
render_strips(strips)
|
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"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
@ -522,6 +667,16 @@ class VSETB_OT_set_sequencer(Operator):
|
||||||
else:
|
else:
|
||||||
self.report({'INFO'}, f'Cannot set Resolution. No Movie Found.')
|
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"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
@ -744,6 +899,9 @@ class VSETB_OT_set_stamps(Operator):
|
||||||
|
|
||||||
bpy.ops.sequencer.select_all(action='DESELECT')
|
bpy.ops.sequencer.select_all(action='DESELECT')
|
||||||
|
|
||||||
|
crop_x = int(scn.render.resolution_x * 0.33)
|
||||||
|
crop_y = int(scn.render.resolution_y * 0.95)
|
||||||
|
|
||||||
# Project Name
|
# Project Name
|
||||||
project_strip_stamp = new_text_strip(
|
project_strip_stamp = new_text_strip(
|
||||||
'project_name_stamp', channel=1, start=scn.frame_start, end=scn.frame_end,
|
'project_name_stamp', channel=1, start=scn.frame_start, end=scn.frame_end,
|
||||||
|
@ -752,6 +910,9 @@ class VSETB_OT_set_stamps(Operator):
|
||||||
box_color=(0, 0, 0, 0.5), box_margin=0.005,
|
box_color=(0, 0, 0, 0.5), box_margin=0.005,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
project_strip_stamp.crop.max_x = crop_x * 2
|
||||||
|
project_strip_stamp.crop.max_y = crop_y
|
||||||
|
|
||||||
# Shot Name
|
# Shot Name
|
||||||
shot_strip_stamp = new_text_strip(
|
shot_strip_stamp = new_text_strip(
|
||||||
f'shot_name_stamp', channel=2, start=scn.frame_start, end=scn.frame_end,
|
f'shot_name_stamp', channel=2, start=scn.frame_start, end=scn.frame_end,
|
||||||
|
@ -760,6 +921,10 @@ class VSETB_OT_set_stamps(Operator):
|
||||||
box_color=(0, 0, 0, 0.5), box_margin=0.005,
|
box_color=(0, 0, 0, 0.5), box_margin=0.005,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
shot_strip_stamp.crop.min_x = crop_x
|
||||||
|
shot_strip_stamp.crop.max_x = crop_x
|
||||||
|
shot_strip_stamp.crop.max_y = crop_y
|
||||||
|
|
||||||
# Frame Range
|
# Frame Range
|
||||||
frame_strip_stamp = new_text_strip(
|
frame_strip_stamp = new_text_strip(
|
||||||
'frame_range_stamp', channel=3, start=scn.frame_start, end=scn.frame_end,
|
'frame_range_stamp', channel=3, start=scn.frame_start, end=scn.frame_end,
|
||||||
|
@ -768,6 +933,8 @@ class VSETB_OT_set_stamps(Operator):
|
||||||
box_color=(0, 0, 0, 0.5), box_margin=0.005,
|
box_color=(0, 0, 0, 0.5), box_margin=0.005,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
frame_strip_stamp.crop.min_x = int(scn.render.resolution_x * 0.66)
|
||||||
|
frame_strip_stamp.crop.max_y = crop_y
|
||||||
# for shot_strip in get_strips('Shots'):
|
# for shot_strip in get_strips('Shots'):
|
||||||
# # Shot Name
|
# # Shot Name
|
||||||
# shot_strip_stamp = new_text_strip(
|
# shot_strip_stamp = new_text_strip(
|
||||||
|
@ -806,7 +973,8 @@ classes = (
|
||||||
VSETB_OT_render,
|
VSETB_OT_render,
|
||||||
VSETB_OT_set_sequencer,
|
VSETB_OT_set_sequencer,
|
||||||
VSETB_OT_tracker_connect,
|
VSETB_OT_tracker_connect,
|
||||||
VSETB_OT_set_stamps
|
VSETB_OT_set_stamps,
|
||||||
|
VSETB_OT_upload_to_tracker
|
||||||
)
|
)
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
|
|
55
panels.py
55
panels.py
|
@ -86,9 +86,13 @@ class VSETB_PT_sequencer(VSETB_main, Panel):
|
||||||
col.operator('vse_toolbox.set_sequencer', text='Set-Up Sequencer', icon='SEQ_SEQUENCER')
|
col.operator('vse_toolbox.set_sequencer', text='Set-Up Sequencer', icon='SEQ_SEQUENCER')
|
||||||
|
|
||||||
#row = col.row()
|
#row = col.row()
|
||||||
episode = project.episode_name
|
shot_label = ''
|
||||||
sequence_label = project.sequence_template.format(episode=episode, index=project.sequence_start_number)
|
sequence_label = ''
|
||||||
shot_label = project.shot_template.format(episode=episode, sequence=sequence_label, index=project.shot_start_number)
|
|
||||||
|
if project:
|
||||||
|
episode = project.episode_name
|
||||||
|
sequence_label = project.sequence_template.format(episode=episode, index=project.sequence_start_number)
|
||||||
|
shot_label = project.shot_template.format(episode=episode, sequence=sequence_label, index=project.shot_start_number)
|
||||||
|
|
||||||
#row.separator()
|
#row.separator()
|
||||||
|
|
||||||
|
@ -106,19 +110,41 @@ class VSETB_PT_sequencer(VSETB_main, Panel):
|
||||||
row.enabled = False
|
row.enabled = False
|
||||||
|
|
||||||
op = row.operator('vse_toolbox.strips_rename', text=f'Rename {channel_name} ( {label} )', icon='SORTALPHA')
|
op = row.operator('vse_toolbox.strips_rename', text=f'Rename {channel_name} ( {label} )', icon='SORTALPHA')
|
||||||
op.channel_name = channel_name
|
if project:
|
||||||
if channel_name == 'Shots':
|
op.channel_name = channel_name
|
||||||
op.start_number = project.shot_start_number
|
if channel_name == 'Shots':
|
||||||
op.template = project.shot_template
|
op.start_number = project.shot_start_number
|
||||||
op.increment = project.shot_increment
|
op.template = project.shot_template
|
||||||
else:
|
op.increment = project.shot_increment
|
||||||
op.start_number = project.sequence_start_number
|
else:
|
||||||
op.template = project.sequence_template
|
op.start_number = project.sequence_start_number
|
||||||
op.increment =project.sequence_increment
|
op.template = project.sequence_template
|
||||||
|
op.increment = project.sequence_increment
|
||||||
|
|
||||||
col.operator('vse_toolbox.set_stamps', text='Set Stamps', icon='COLOR')
|
col.operator('vse_toolbox.set_stamps', text='Set Stamps', icon='COLOR')
|
||||||
|
|
||||||
|
|
||||||
|
class VSETB_PT_settings(VSETB_main, Panel):
|
||||||
|
bl_label = "Settings"
|
||||||
|
bl_parent_id = "VSETB_PT_main"
|
||||||
|
bl_options = {'DEFAULT_CLOSED'}
|
||||||
|
|
||||||
|
#def draw_header_preset(self, context):
|
||||||
|
# self.layout.operator('vse_toolbox.import_files', icon='IMPORT', text='', emboss=False)
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
prefs = get_addon_prefs()
|
||||||
|
layout = self.layout
|
||||||
|
settings = get_scene_settings()
|
||||||
|
project = settings.active_project
|
||||||
|
|
||||||
|
col = layout.column()
|
||||||
|
#row = col.row(align=True)
|
||||||
|
col.prop(project, 'sequence_template')
|
||||||
|
col.prop(project, 'shot_template')
|
||||||
|
col.prop(project, 'render_template')
|
||||||
|
|
||||||
|
|
||||||
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"
|
||||||
|
@ -154,7 +180,10 @@ class VSETB_PT_exports(VSETB_main, Panel):
|
||||||
|
|
||||||
# TODO FAIRE DES VRAIS OPS
|
# TODO FAIRE DES VRAIS OPS
|
||||||
layout.operator('vse_toolbox.strips_render', text='Render Strips', icon='SEQUENCE')
|
layout.operator('vse_toolbox.strips_render', text='Render Strips', icon='SEQUENCE')
|
||||||
layout.operator('vse_toolbox.export_csv', text='Export', icon='EXPORT')
|
|
||||||
|
tracker_label = settings.tracker_name.title().replace('_', ' ')
|
||||||
|
layout.operator('vse_toolbox.upload_to_tracker', text=f'Upload to {tracker_label}', icon='EXPORT')
|
||||||
|
layout.operator('vse_toolbox.export_csv', text='Export csv', icon='SPREADSHEET')
|
||||||
|
|
||||||
|
|
||||||
class VSETB_PT_casting(VSETB_main, Panel):
|
class VSETB_PT_casting(VSETB_main, Panel):
|
||||||
|
|
|
@ -48,16 +48,18 @@ def load_trackers():
|
||||||
if not Tracker in obj.__mro__:
|
if not Tracker in obj.__mro__:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if obj is Tracker or obj.name in (a.name for a in TRACKERS):
|
if obj is Tracker or name in (a.__name__ for a in TRACKERS):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
print(f'Register Plugin {name}')
|
print(f'Register Tracker {name}')
|
||||||
bpy.utils.register_class(obj)
|
bpy.utils.register_class(obj)
|
||||||
setattr(Trackers, norm_str(obj.name), PointerProperty(type=obj))
|
#obj.register()
|
||||||
|
|
||||||
|
setattr(Trackers, norm_str(name), PointerProperty(type=obj))
|
||||||
TRACKERS.append(obj)
|
TRACKERS.append(obj)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f'Could not register library_type {name}')
|
print(f'Could not register Tracker {name}')
|
||||||
print(e)
|
print(e)
|
||||||
|
|
||||||
def load_tracker_prefs():
|
def load_tracker_prefs():
|
||||||
|
|
|
@ -41,15 +41,20 @@ def on_project_updated(self, context):
|
||||||
settings = get_scene_settings()
|
settings = get_scene_settings()
|
||||||
settings['episodes'] = 0
|
settings['episodes'] = 0
|
||||||
|
|
||||||
print('Update active Project')
|
#print('Update active Project')
|
||||||
|
|
||||||
bpy.ops.vse_toolbox.load_assets()
|
bpy.ops.vse_toolbox.load_assets()
|
||||||
|
|
||||||
if settings.active_project:
|
if settings.active_project:
|
||||||
settings.active_project.set_strip_metadata()
|
settings.active_project.set_strip_metadata()
|
||||||
|
|
||||||
|
os.environ['TRACKER_PROJECT_ID'] = settings.active_project.id
|
||||||
|
|
||||||
|
def on_episode_updated(self, context):
|
||||||
|
os.environ['TRACKER_EPISODE_ID'] = settings.active_episode.id
|
||||||
|
|
||||||
def get_tracker_items(self, context):
|
def get_tracker_items(self, context):
|
||||||
return [(norm_str(a.name, format=str.upper), a.name, "", i) for i, a in enumerate(TRACKERS)]
|
return [(norm_str(a.__name__, format=str.upper), a.__name__, "", i) for i, a in enumerate(TRACKERS)]
|
||||||
|
|
||||||
|
|
||||||
class Asset(PropertyGroup):
|
class Asset(PropertyGroup):
|
||||||
|
@ -97,6 +102,14 @@ class MetadataType(PropertyGroup):
|
||||||
choice : EnumProperty(items=lambda s, c: [(c, c.replace(' ', '_').upper(), '') for c in s['choices']])
|
choice : EnumProperty(items=lambda s, c: [(c, c.replace(' ', '_').upper(), '') for c in s['choices']])
|
||||||
|
|
||||||
|
|
||||||
|
class TaskType(PropertyGroup):
|
||||||
|
__annotations__ = {}
|
||||||
|
|
||||||
|
|
||||||
|
class TaskStatus(PropertyGroup):
|
||||||
|
__annotations__ = {}
|
||||||
|
|
||||||
|
|
||||||
class Metadata(PropertyGroup):
|
class Metadata(PropertyGroup):
|
||||||
__annotations__ = {}
|
__annotations__ = {}
|
||||||
|
|
||||||
|
@ -131,11 +144,17 @@ class Project(PropertyGroup):
|
||||||
shot_template : StringProperty(
|
shot_template : StringProperty(
|
||||||
name="Shot Name", default="{sequence}_sh{index:04d}")
|
name="Shot Name", default="{sequence}_sh{index:04d}")
|
||||||
|
|
||||||
episode_name : EnumProperty(items=get_episodes_items)
|
render_template : StringProperty(
|
||||||
|
name="Render Name", default="//render/{strip_name}.{ext}")
|
||||||
|
|
||||||
|
episode_name : EnumProperty(items=get_episodes_items, update=on_episode_updated)
|
||||||
episodes : CollectionProperty(type=Episode)
|
episodes : CollectionProperty(type=Episode)
|
||||||
assets : CollectionProperty(type=Asset)
|
assets : CollectionProperty(type=Asset)
|
||||||
asset_types : CollectionProperty(type=AssetType)
|
asset_types : CollectionProperty(type=AssetType)
|
||||||
metadata_types : CollectionProperty(type=MetadataType)
|
metadata_types : CollectionProperty(type=MetadataType)
|
||||||
|
task_types : CollectionProperty(type=TaskType)
|
||||||
|
task_statuses : CollectionProperty(type=TaskStatus)
|
||||||
|
|
||||||
type : StringProperty()
|
type : StringProperty()
|
||||||
|
|
||||||
def set_strip_metadata(self):
|
def set_strip_metadata(self):
|
||||||
|
@ -272,9 +291,11 @@ classes=(
|
||||||
Asset,
|
Asset,
|
||||||
AssetCasting,
|
AssetCasting,
|
||||||
AssetType,
|
AssetType,
|
||||||
|
TaskStatus,
|
||||||
Episode,
|
Episode,
|
||||||
Metadata,
|
Metadata,
|
||||||
MetadataType,
|
MetadataType,
|
||||||
|
TaskType,
|
||||||
Project,
|
Project,
|
||||||
VSETB_UL_casting,
|
VSETB_UL_casting,
|
||||||
VSETB_PGT_scene_settings,
|
VSETB_PGT_scene_settings,
|
||||||
|
@ -290,6 +311,7 @@ def load_handler(dummy):
|
||||||
settings = get_scene_settings()
|
settings = get_scene_settings()
|
||||||
if settings.active_project:
|
if settings.active_project:
|
||||||
settings.active_project.set_strip_metadata()
|
settings.active_project.set_strip_metadata()
|
||||||
|
os.environ['TRACKER_PROJECT_ID'] = settings.active_project.id
|
||||||
|
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
|
|
|
@ -5,10 +5,10 @@ import re
|
||||||
import urllib3
|
import urllib3
|
||||||
import traceback
|
import traceback
|
||||||
import time
|
import time
|
||||||
|
import uuid
|
||||||
|
|
||||||
from bpy.props import PointerProperty, StringProperty
|
from bpy.props import PointerProperty, StringProperty
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from vse_toolbox.bl_utils import get_addon_prefs, get_scene_settings
|
|
||||||
from vse_toolbox.file_utils import install_module, norm_str
|
from vse_toolbox.file_utils import install_module, norm_str
|
||||||
from vse_toolbox.resources.trackers.tracker import Tracker
|
from vse_toolbox.resources.trackers.tracker import Tracker
|
||||||
|
|
||||||
|
@ -18,34 +18,163 @@ except Exception as e:
|
||||||
print('Could not install gazu')
|
print('Could not install gazu')
|
||||||
print(e)
|
print(e)
|
||||||
|
|
||||||
|
LOGIN = None
|
||||||
|
|
||||||
class Kitsu(Tracker):
|
class Kitsu(Tracker):
|
||||||
name = "Kitsu"
|
|
||||||
|
|
||||||
url: StringProperty()
|
url: StringProperty()
|
||||||
login: StringProperty()
|
login: StringProperty()
|
||||||
password: StringProperty(subtype='PASSWORD')
|
password: StringProperty(subtype='PASSWORD')
|
||||||
|
|
||||||
project_name = None
|
def connect(self, url=None, login=None, password=None):
|
||||||
|
'''Connect to kitsu api using provided url, login and password'''
|
||||||
|
|
||||||
def draw_prefs(self, layout):
|
global LOGIN
|
||||||
layout.prop(self, 'url', text='Url')
|
|
||||||
layout.prop(self, 'login', text='Login')
|
urllib3.disable_warnings()
|
||||||
layout.prop(self, 'password', text='Password')
|
|
||||||
|
if url is None:
|
||||||
|
url = self.url
|
||||||
|
if login is None:
|
||||||
|
login = self.login
|
||||||
|
if password is None:
|
||||||
|
password = self.password
|
||||||
|
|
||||||
|
if not url:
|
||||||
|
print(f'Kitsu Url: {self.url} is empty')
|
||||||
|
return
|
||||||
|
|
||||||
|
if login == LOGIN:
|
||||||
|
return
|
||||||
|
|
||||||
|
if not url.endswith('/api'):
|
||||||
|
url += '/api'
|
||||||
|
|
||||||
|
print(f'Info: Setting Host for kitsu {url}')
|
||||||
|
gazu.client.set_host(url)
|
||||||
|
|
||||||
|
if not gazu.client.host_is_up():
|
||||||
|
print('Error: Kitsu Host is down')
|
||||||
|
|
||||||
|
try:
|
||||||
|
print(f'Info: Log in to kitsu as {login}')
|
||||||
|
res = gazu.log_in(login, password)
|
||||||
|
LOGIN = login
|
||||||
|
print(f'Info: Sucessfully login to Kitsu as {res["user"]["full_name"]}')
|
||||||
|
return res['user']
|
||||||
|
except Exception as e:
|
||||||
|
print(f'Error: {traceback.format_exc()}')
|
||||||
|
|
||||||
|
def get_id(self, data):
|
||||||
|
if isinstance(data, str):
|
||||||
|
if self.is_id(data):
|
||||||
|
return data
|
||||||
|
#return None
|
||||||
|
elif isinstance(data, dict):
|
||||||
|
return data['id']
|
||||||
|
elif data: # Should be a Class
|
||||||
|
return data.id
|
||||||
|
|
||||||
|
def is_id(self, id):
|
||||||
|
if not isinstance(id, str):
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
uuid.UUID(id)
|
||||||
|
return True
|
||||||
|
except ValueError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_project(self, project=None):
|
||||||
|
if project:
|
||||||
|
project_id = self.get_id(project)
|
||||||
|
if project_id:
|
||||||
|
return project_id
|
||||||
|
return gazu.project.get_project_by_name(project)
|
||||||
|
|
||||||
|
if os.environ.get('TRACKER_PROJECT_ID'):
|
||||||
|
return os.environ['TRACKER_PROJECT_ID']
|
||||||
|
elif os.environ.get('TRACKER_PROJECT_NAME'):
|
||||||
|
return os.environ['TRACKER_PROJECT_NAME']
|
||||||
|
|
||||||
def get_projects(self):
|
def get_projects(self):
|
||||||
return gazu.project.all_open_projects()
|
return gazu.project.all_open_projects()
|
||||||
|
|
||||||
|
def get_episode(self, episode, project=None):
|
||||||
|
project = self.get_project(project)
|
||||||
|
if episode:
|
||||||
|
episode_id = self.get_id(episode)
|
||||||
|
if episode_id:
|
||||||
|
return episode_id
|
||||||
|
return gazu.shot.get_episode_by_name(project, episode)
|
||||||
|
|
||||||
|
if os.environ.get('TRACKER_EPISODE_ID'):
|
||||||
|
return os.environ['TRACKER_EPISODE_ID']
|
||||||
|
elif os.environ.get('TRACKER_EPISODE_NAME'):
|
||||||
|
return os.environ['TRACKER_EPISODE_NAME']
|
||||||
|
|
||||||
def get_episodes(self, project):
|
def get_episodes(self, project):
|
||||||
return gazu.shot.all_episodes_for_project(project)
|
return gazu.shot.all_episodes_for_project(project)
|
||||||
|
|
||||||
def get_episode(self, name):
|
def get_task_type(self, task_type=None):
|
||||||
return gazu.shot.get_episode_by_name(self.project, name)
|
print('get_task_type', task_type)
|
||||||
|
return gazu.task.get_task_type_by_name(task_type)
|
||||||
|
|
||||||
def get_asset_types(self, project):
|
def get_shot_task_types(self, project=None):
|
||||||
|
project = self.get_project(project)
|
||||||
|
task_types = gazu.task.all_task_types_for_project(project)
|
||||||
|
return [t for t in task_types if t['for_entity'].lower() == 'shot']
|
||||||
|
|
||||||
|
def get_shots_metadata(self, project=None):
|
||||||
|
project = self.get_project(project)
|
||||||
|
metadatas = []
|
||||||
|
|
||||||
|
for metadata in gazu.project.all_metadata_descriptors(project):
|
||||||
|
if metadata['entity_type'] == 'Shot' and metadata['name']:
|
||||||
|
metadatas.append(metadata)
|
||||||
|
|
||||||
|
return metadatas
|
||||||
|
|
||||||
|
def get_task_status(self, status=None):
|
||||||
|
status_id = self.get_id(status)
|
||||||
|
if status_id:
|
||||||
|
return status_id
|
||||||
|
|
||||||
|
return gazu.client.fetch_first('task-status', {"short_name": status.lower()})
|
||||||
|
|
||||||
|
def get_task_statuses(self, project=None):
|
||||||
|
project = self.get_project(project)
|
||||||
|
return gazu.task.all_task_statuses_for_project(project)
|
||||||
|
|
||||||
|
def get_asset_types(self, project=None):
|
||||||
|
project = self.get_project(project)
|
||||||
return gazu.asset.all_asset_types_for_project(project)
|
return gazu.asset.all_asset_types_for_project(project)
|
||||||
|
|
||||||
def get_assets(self, project):
|
def get_sequence(self, sequence, project=None):
|
||||||
|
print(f'get_sequence({sequence=}, {project=})')
|
||||||
|
project = self.get_project(project)
|
||||||
|
|
||||||
|
sequence_id = self.get_id(sequence)
|
||||||
|
if sequence_id:
|
||||||
|
return sequence_id
|
||||||
|
|
||||||
|
return gazu.shot.get_sequence_by_name(project, sequence)
|
||||||
|
|
||||||
|
def get_shot(self, shot, sequence, project=None):
|
||||||
|
print(f'get_shot({shot=}, {sequence=}, {project=})')
|
||||||
|
project = self.get_project(project)
|
||||||
|
sequence = self.get_sequence(sequence, project)
|
||||||
|
|
||||||
|
if not sequence:
|
||||||
|
return
|
||||||
|
|
||||||
|
shot_id = self.get_id(shot)
|
||||||
|
if shot_id:
|
||||||
|
return shot_id
|
||||||
|
|
||||||
|
return gazu.shot.get_shot_by_name(sequence, shot)
|
||||||
|
|
||||||
|
def get_assets(self, project=None):
|
||||||
|
project = self.get_project(project)
|
||||||
assets = gazu.asset.all_assets_for_project(project)
|
assets = gazu.asset.all_assets_for_project(project)
|
||||||
entity_types = self.get_asset_types(project)
|
entity_types = self.get_asset_types(project)
|
||||||
entity_types_ids = {e['id']: e['name'] for e in entity_types}
|
entity_types_ids = {e['id']: e['name'] for e in entity_types}
|
||||||
|
@ -55,14 +184,54 @@ class Kitsu(Tracker):
|
||||||
|
|
||||||
return assets
|
return assets
|
||||||
|
|
||||||
def get_shots_metadata(self, project):
|
def get_last_comment(self, task):
|
||||||
metadatas = []
|
task = self.get_id(task)
|
||||||
|
return gazu.task.get_last_comment_for_task(task)
|
||||||
|
|
||||||
for metadata in gazu.project.all_metadata_descriptors(project):
|
def get_task(self, task=None, entity=None):
|
||||||
if metadata['entity_type'] == 'Shot' and metadata['name']:
|
entity = self.get_id(entity)
|
||||||
metadatas.append(metadata)
|
|
||||||
|
|
||||||
return metadatas
|
task_type = self.get_task_type(task)
|
||||||
|
|
||||||
|
print('task_type', task_type)
|
||||||
|
print('task_type', task_type)
|
||||||
|
|
||||||
|
task = gazu.task.get_task_by_name(entity, task_type)
|
||||||
|
#task = gazu.task.get_task(task['id'])
|
||||||
|
|
||||||
|
task['last_comment'] = self.get_last_comment(task)
|
||||||
|
|
||||||
|
return task
|
||||||
|
|
||||||
|
def new_comment(self, task, status=None, comment='', preview=None, set_main_preview=False):
|
||||||
|
#task = self.get_task(task)
|
||||||
|
|
||||||
|
#print('Add Comment', status)
|
||||||
|
if status is None:
|
||||||
|
#print(task)
|
||||||
|
status = {'id' : task['task_status_id']}
|
||||||
|
else:
|
||||||
|
status = self.get_task_status(status)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
comment = gazu.task.add_comment(
|
||||||
|
task=task,
|
||||||
|
task_status=status,
|
||||||
|
comment=comment )
|
||||||
|
|
||||||
|
if preview:
|
||||||
|
logging.info(f'Adding Preview to Kitsu {preview}')
|
||||||
|
preview = self.add_preview(
|
||||||
|
task=task,
|
||||||
|
comment=comment,
|
||||||
|
preview=str(preview) )
|
||||||
|
|
||||||
|
if set_main_preview:
|
||||||
|
gazu.task.set_main_preview(preview)
|
||||||
|
|
||||||
|
|
||||||
|
return comment
|
||||||
|
|
||||||
def download_preview(self, preview_id, filepath):
|
def download_preview(self, preview_id, filepath):
|
||||||
if isinstance(filepath, str):
|
if isinstance(filepath, str):
|
||||||
|
@ -74,100 +243,43 @@ class Kitsu(Tracker):
|
||||||
filepath.parent.mkdir(parents=True, exist_ok=True)
|
filepath.parent.mkdir(parents=True, exist_ok=True)
|
||||||
gazu.files.download_preview_file_thumbnail(preview_id, filepath.as_posix())
|
gazu.files.download_preview_file_thumbnail(preview_id, filepath.as_posix())
|
||||||
|
|
||||||
def connect(self, url=None, login=None, password=None):
|
def new_sequence(self, sequence, episode=None, project=None):
|
||||||
'''Connect to kitsu api using provided url, login and password'''
|
project = self.get_project(project)
|
||||||
|
|
||||||
urllib3.disable_warnings()
|
params = dict(name=sequence, project=project)
|
||||||
|
episode = self.get_episode(episode)
|
||||||
|
if episode:
|
||||||
|
params['episode'] = episode
|
||||||
|
|
||||||
if not self.url:
|
return gazu.shot.new_sequence(**params)
|
||||||
print(f'Kitsu Url: {self.url} is empty')
|
|
||||||
return
|
|
||||||
|
|
||||||
url = self.url
|
def new_shot(self, shot, sequence, nb_frames=None, frame_in=None,
|
||||||
if not url.endswith('/api'):
|
frame_out=None, description='', custom_data=None, project=None):
|
||||||
url += '/api'
|
|
||||||
|
|
||||||
print(f'Info: Setting Host for kitsu {url}')
|
project = self.get_project(project)
|
||||||
gazu.client.set_host(url)
|
sequence = self.get_sequence(sequence)
|
||||||
|
|
||||||
if not gazu.client.host_is_up():
|
custom_data = custom_data or {}
|
||||||
print('Error: Kitsu Host is down')
|
|
||||||
|
|
||||||
try:
|
if frame_in is not None:
|
||||||
print(f'Info: Log in to kitsu as {self.login}')
|
custom_data["frame_in"] = frame_in
|
||||||
res = gazu.log_in(self.login, self.password)
|
if frame_out is not None:
|
||||||
print(f'Info: Sucessfully login to Kitsu as {res["user"]["full_name"]}')
|
custom_data["frame_out"] = frame_out
|
||||||
return res['user']
|
|
||||||
except Exception as e:
|
|
||||||
print(f'Error: {traceback.format_exc()}')
|
|
||||||
|
|
||||||
def get_asset_path(self, name, catalog, directory=None):
|
params = dict(name=shot, data=custom_data,
|
||||||
directory = directory or self.source_directory
|
sequence_id=self.get_id(sequence), description=description)
|
||||||
return Path(directory, self.get_asset_relative_path(name, catalog))
|
|
||||||
|
|
||||||
def get_asset_info(self, data, asset_path):
|
if nb_frames is not None:
|
||||||
modified = time.time_ns()
|
params["nb_frames"] = nb_frames
|
||||||
catalog = data['entity_type_name'].title()
|
|
||||||
asset_path = self.prop_rel_path(asset_path, 'source_directory')
|
|
||||||
|
|
||||||
asset_info = dict(
|
shot = self.get_shot(shot=shot, sequence=sequence)
|
||||||
filepath=asset_path,
|
if shot:
|
||||||
modified=modified,
|
return shot
|
||||||
library_id=self.library.id,
|
else:
|
||||||
assets=[dict(
|
path = f"data/projects/{self.get_id(project)}/shots"
|
||||||
catalog=catalog,
|
return gazu.client.post(path, params)
|
||||||
metadata=data.get('data', {}),
|
|
||||||
description=data['description'],
|
|
||||||
tags=[],
|
|
||||||
type=self.data_type,
|
|
||||||
name=data['name'])
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
return asset_info
|
def draw_prefs(self, layout):
|
||||||
|
layout.prop(self, 'url', text='Url')
|
||||||
def fetch(self):
|
layout.prop(self, 'login', text='Login')
|
||||||
"""Gather in a list all assets found in the folder"""
|
layout.prop(self, 'password', text='Password')
|
||||||
print(f'Fetch Assets for {self.library.name}')
|
|
||||||
|
|
||||||
self.connect()
|
|
||||||
|
|
||||||
template_file = Template(self.template_file)
|
|
||||||
template_name = Template(self.template_name)
|
|
||||||
|
|
||||||
project = gazu.client.fetch_first('projects', {'name': self.project_name})
|
|
||||||
entity_types = gazu.client.fetch_all('entity-types')
|
|
||||||
entity_types_ids = {e['id']: e['name'] for e in entity_types}
|
|
||||||
|
|
||||||
cache = self.read_cache()
|
|
||||||
|
|
||||||
for asset_data in gazu.asset.all_assets_for_project(project):
|
|
||||||
asset_data['entity_type_name'] = entity_types_ids[asset_data.pop('entity_type_id')]
|
|
||||||
asset_name = asset_data['name']
|
|
||||||
|
|
||||||
asset_field_data = dict(asset_name=asset_name, type=asset_data['entity_type_name'], source_directory=self.source_directory)
|
|
||||||
|
|
||||||
try:
|
|
||||||
asset_field_data.update(template_name.parse(asset_name))
|
|
||||||
except Exception:
|
|
||||||
print(f'Warning: Could not parse {asset_name} with template {template_name}')
|
|
||||||
|
|
||||||
asset_path = template_file.find(asset_field_data)
|
|
||||||
if not asset_path:
|
|
||||||
print(f'Warning: Could not find file for {template_file.format(asset_field_data)}')
|
|
||||||
continue
|
|
||||||
|
|
||||||
|
|
||||||
asset_path = self.prop_rel_path(asset_path, 'source_directory')
|
|
||||||
asset_cache_data = dict(
|
|
||||||
catalog=asset_data['entity_type_name'].title(),
|
|
||||||
metadata=asset_data.get('data', {}),
|
|
||||||
description=asset_data['description'],
|
|
||||||
tags=[],
|
|
||||||
type=self.data_type,
|
|
||||||
name=asset_data['name']
|
|
||||||
)
|
|
||||||
|
|
||||||
cache.add_asset_cache(asset_cache_data, filepath=asset_path)
|
|
||||||
|
|
||||||
return cache
|
|
|
@ -1,4 +1,9 @@
|
||||||
|
import bpy
|
||||||
from bpy.types import PropertyGroup
|
from bpy.types import PropertyGroup
|
||||||
|
from bpy.props import PointerProperty, StringProperty
|
||||||
|
from vse_toolbox.file_utils import norm_str
|
||||||
|
|
||||||
|
|
||||||
class Tracker(PropertyGroup):
|
class Tracker(PropertyGroup):
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
import bpy
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from bpy.app.handlers import persistent
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
from bpy.app.handlers import persistent
|
||||||
|
|
||||||
from vse_toolbox.bl_utils import get_scene_settings, get_strip_settings
|
from vse_toolbox.bl_utils import get_scene_settings, get_strip_settings
|
||||||
from vse_toolbox.constants import SOUND_SUFFIXES
|
from vse_toolbox.constants import SOUND_SUFFIXES
|
||||||
|
|
||||||
|
@ -122,9 +123,31 @@ def set_channels():
|
||||||
for i, c in enumerate(items.keys(), start=1):
|
for i, c in enumerate(items.keys(), start=1):
|
||||||
scn.sequence_editor.channels[i].name = c.title()
|
scn.sequence_editor.channels[i].name = c.title()
|
||||||
|
|
||||||
def render_strips(strips):
|
def get_strip_render_path(strip, template):
|
||||||
|
return template.format(strip_name=strip.name, ext=Path(scn.render.frame_path()).suffix)
|
||||||
|
|
||||||
|
def render_strips(strips, template):
|
||||||
|
scn = bpy.context.scene
|
||||||
|
scene_start = scn.frame_start
|
||||||
|
scene_end = scn.frame_end
|
||||||
|
|
||||||
for strip in strips:
|
for strip in strips:
|
||||||
print(strip.name)
|
#print(render_template, strip.name, path)
|
||||||
|
|
||||||
|
scn.frame_start = strip.frame_final_start
|
||||||
|
scn.frame_end = strip.frame_final_end - 1
|
||||||
|
|
||||||
|
## render animatic
|
||||||
|
#strip_render_path = render_template.format(strip_name=strip.name, ext=Path(scn.render.frame_path()).suffix)
|
||||||
|
scn.render.filepath = get_strip_render_path(strip, template)
|
||||||
|
#print(scn.render.filepath)
|
||||||
|
print(f'Render Strip to {scn.render.filepath}')
|
||||||
|
#bpy.ops.render.render(animation=True)
|
||||||
|
bpy.ops.render.opengl(animation=True, sequencer=True)
|
||||||
|
|
||||||
|
|
||||||
|
scn.frame_start = scene_start
|
||||||
|
scn.frame_end = scene_end
|
||||||
|
|
||||||
def import_edit(filepath, adapter="cmx_3600", clean_sequencer=False):
|
def import_edit(filepath, adapter="cmx_3600", clean_sequencer=False):
|
||||||
import opentimelineio as otio
|
import opentimelineio as otio
|
||||||
|
|
Loading…
Reference in New Issue