export background

This commit is contained in:
“christopheseux”
2023-05-19 11:51:05 +02:00
parent 48dddb1905
commit beb85721a9
10 changed files with 416 additions and 120 deletions
+2 -2
View File
@@ -1,13 +1,13 @@
# SPDX-License-Identifier: GPL-2.0-or-later
from vse_toolbox.operators import (addon, casting, imports, render, sequencer,
from vse_toolbox.operators import (addon, casting, imports, exports, sequencer,
spreadsheet, tracker)
modules = (
addon,
casting,
imports,
render,
exports,
sequencer,
spreadsheet,
tracker
+35 -9
View File
@@ -2,7 +2,7 @@
import json
import bpy
from bpy.types import PropertyGroup, Operator
from bpy.types import Context, Event, PropertyGroup, Operator
from bpy.props import (CollectionProperty, EnumProperty, StringProperty)
from vse_toolbox.constants import CASTING_BUFFER
@@ -249,15 +249,27 @@ class VSETB_OT_copy_casting(Operator):
class VSETB_OT_paste_casting(Operator):
bl_idname = "vse_toolbox.paste_casting"
bl_label = "Paste Casting"
bl_description = "Paste Casting to active strip"
bl_description = "Paste Casting to active strip (ctrl|shift: Add, alt:Remove)"
bl_options = {"REGISTER", "UNDO"}
mode : EnumProperty(items=[(m, m.title(), '') for m in ('REPLACE', 'ADD', 'REMOVE')])
@classmethod
def poll(cls, context):
active_strip = context.scene.sequence_editor.active_strip
if active_strip:
return True
def invoke(self, context, event):
self.mode = 'REPLACE'
if event.ctrl or event.shift:
self.mode = 'ADD'
elif event.alt:
self.mode = 'REMOVE'
return self.execute(context)
def execute(self, context):
scn = context.scene
strip_settings = get_strip_settings()
@@ -267,19 +279,33 @@ class VSETB_OT_paste_casting(Operator):
return {"CANCELLED"}
casting_datas = json.loads(CASTING_BUFFER.read_text())
casting_ids = set(c['id'] for c in casting_datas)
for strip in context.selected_sequences:
strip_settings = strip.vsetb_strip_settings
strip.vsetb_strip_settings.casting.clear()
if self.mode == 'REPLACE':
strip.vsetb_strip_settings.casting.clear()
for casting_data in casting_datas:
item = strip.vsetb_strip_settings.casting.add()
if self.mode == 'REMOVE':
for asset_casting in strip_settings.casting:
index = list(strip_settings.casting).index(asset_casting)
if asset_casting.id in casting_ids:
strip_settings.casting.remove(index)
item.name = casting_data['name']
item.id = casting_data['id']
item['_name'] = casting_data['_name']
if strip_settings.casting_index != 0:
strip_settings.casting_index -= 1
strip_settings.casting.update()
else:
item = strip.vsetb_strip_settings.casting.add()
item.name = casting_data['name']
item.id = casting_data['id']
item['_name'] = casting_data['_name']
strip_settings.casting.update()
return {"FINISHED"}
+183
View File
@@ -0,0 +1,183 @@
import time
import re
from pathlib import Path
import os
import bpy
from bpy.types import Operator
from bpy.props import BoolProperty
from vse_toolbox.sequencer_utils import (get_strips, render_strip)
from vse_toolbox.bl_utils import (get_scene_settings, background_render)
from vse_toolbox.file_utils import install_module
class VSETB_OT_render(Operator):
bl_idname = "vse_toolbox.strips_render"
bl_label = "Render Shots Strips"
bl_description = "Render Shots Strips"
bl_options = {"REGISTER", "UNDO"}
#selected_only : BoolProperty(name="Selected Only", default=False)
@classmethod
def poll(cls, context):
settings = get_scene_settings()
return settings.active_project
def invoke(self, context, event):
scn = context.scene
settings = get_scene_settings()
return context.window_manager.invoke_props_dialog(self)
def draw(self, context):
scn = context.scene
settings = get_scene_settings()
layout = self.layout
col = layout.column()
#col.use_property_split = True
#col.use_property_decorate = False
col.prop(settings.active_project, "render_single_file")
row = col.row()
row.enabled = settings.active_project.render_single_file
row.prop(settings.active_project, "render_template")
col.separator()
col.prop(settings.active_project, "render_per_strip")
row = col.row()
row.enabled = settings.active_project.render_per_strip
row.prop(settings.active_project, "render_strip_template")
#col.prop(settings, 'channel', text='Channel')
#col.prop(self, 'selected_only')
def execute(self, context):
scn = context.scene
settings = get_scene_settings()
project = settings.active_project
format_data = {**settings.format_data, **project.format_data}
start_time = time.perf_counter()
if project.render_single_file:
render_path = project.render_template.format(**format_data)
background_render(output=render_path)
if project.render_per_strip:
for strip in get_strips(channel='Shots', selected_only=True):
strip_settings = strip.vsetb_strip_settings
strip_data = {**format_data, **strip_settings.format_data}
strip_render_path = project.render_strip_template.format(**strip_data)
render_strip(strip, strip_render_path)
self.report({"INFO"}, f'Strips rendered in {time.perf_counter()-start_time} seconds')
return {"FINISHED"}
class VSETB_OT_export_edl(Operator):
bl_idname = "vse_toolbox.export_edl"
bl_label = "Export Edl"
bl_description = "Export Edl"
bl_options = {"REGISTER", "UNDO"}
#selected_only : BoolProperty(name="Selected Only", default=False)
@classmethod
def poll(cls, context):
settings = get_scene_settings()
return settings.active_project
def invoke(self, context, event):
scn = context.scene
settings = get_scene_settings()
return context.window_manager.invoke_props_dialog(self)
def draw(self, context):
scn = context.scene
settings = get_scene_settings()
layout = self.layout
col = layout.column()
col.use_property_split = True
col.use_property_decorate = False
#col.prop(settings, 'channel', text='Channel')
#col.prop(self, 'selected_only')
col.prop(settings.active_project, "export_edl_template")
def execute(self, context):
opentimelineio = install_module('opentimelineio')
from opentimelineio.schema import (Clip, Timeline, Track, ExternalReference)
from opentimelineio.opentime import (RationalTime, TimeRange)
start_time = time.perf_counter()
scn = context.scene
settings = get_scene_settings()
fps = scn.render.fps
project = settings.active_project
format_data = {**settings.format_data, **project.format_data}
output_edl = project.export_edl_template.format(**format_data)
output_edl = os.path.abspath(bpy.path.abspath(output_edl))
output_edl = Path(output_edl)
timeline = Timeline(output_edl.stem)
track = Track(f"Track 1")
track.kind = "Video"
timeline.tracks.append(track)
for strip in get_strips(channel='Shots', selected_only=False):
strip_data = {**format_data, **strip.vsetb_strip_settings.format_data}
strip_render_path = project.render_strip_template.format(**strip_data)
clip = Clip(Path(strip_render_path).name)
clip.metadata.setdefault("cmx_3600", {})
clip.metadata['cmx_3600']['reel'] = strip.name
#clip.metadata['cmx_3600']['flags'] = 'IS_CLIP'
#clip.media_reference = ExternalReference(f'//render/{strip.name}.mov')
#clip.media_reference.name = strip.name
#clip.available_range = TimeRange(RationalTime(0, fps), RationalTime(strip.frame_duration, fps))
clip.source_range = TimeRange(RationalTime(strip.frame_offset_start, fps), RationalTime(strip.frame_final_duration, fps))
track.append(clip)
output_edl.parent.mkdir(exist_ok=True, parents=True)
edl = opentimelineio.adapters.write_to_string(timeline, 'cmx_3600')
output_edl.write_text(edl)
#opentimelineio.adapters.write_to_file(timeline, str(output_edl), 'cmx_3600')
self.report({"INFO"}, f'Edl Exported in {time.perf_counter()-start_time} seconds')
return {"FINISHED"}
classes = (
VSETB_OT_render,
VSETB_OT_export_edl
)
def register():
for cls in classes:
bpy.utils.register_class(cls)
def unregister():
for cls in reversed(classes):
bpy.utils.unregister_class(cls)
-70
View File
@@ -1,70 +0,0 @@
import time
import bpy
from bpy.types import Operator
from vse_toolbox.sequencer_utils import (get_strips, render_strips)
from vse_toolbox.bl_utils import get_scene_settings
class VSETB_OT_render(Operator):
bl_idname = "vse_toolbox.strips_render"
bl_label = "Render Shots Strips"
bl_description = "Render Shots Strips"
bl_options = {"REGISTER", "UNDO"}
#selected_only : BoolProperty(name="Selected Only", default=False)
@classmethod
def poll(cls, context):
settings = get_scene_settings()
return settings.active_project
def invoke(self, context, event):
scn = context.scene
settings = get_scene_settings()
return context.window_manager.invoke_props_dialog(self)
def draw(self, context):
scn = context.scene
settings = get_scene_settings()
layout = self.layout
col = layout.column()
col.use_property_split = True
col.use_property_decorate = False
#col.prop(settings, 'channel', text='Channel')
#col.prop(self, 'selected_only')
col.prop(settings.active_project, "render_template")
def execute(self, context):
scn = context.scene
settings = get_scene_settings()
strips = get_strips(channel='Shots', selected_only=True)
start_time = time.perf_counter()
render_strips(strips, settings.active_project.render_template)
self.report({"INFO"}, f'Strips rendered in {time.perf_counter()-start_time} seconds')
return {"FINISHED"}
classes = (
VSETB_OT_render,
)
def register():
for cls in classes:
bpy.utils.register_class(cls)
def unregister():
for cls in reversed(classes):
bpy.utils.unregister_class(cls)
+53 -14
View File
@@ -171,6 +171,40 @@ class VSETB_OT_spreadsheet_from_clipboard(Operator):
return {"FINISHED"}
class VSETB_OT_spreadsheet_to_clipboard(Operator):
bl_idname = "vse_toolbox.spreadsheet_to_clipboard"
bl_label = "Copy Spreadsheet to clipboard"
bl_description = "Copy Spreadsheet to clipboard"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
scn = context.scene
project = get_scene_settings().active_project
import_cells = project.spreadsheet_import.cells
import_cells.clear()
SPREADSHEET.clear()
spreadsheet = context.window_manager.clipboard
cell_types = project.get_cell_types()
rows = list(csv.reader(StringIO(spreadsheet), delimiter='\t'))
for cell_name in rows[0]:
if not cell_name:
continue
cell = import_cells.add()
cell.name = cell_name
cell.import_name = max(cell_types.keys(), key=lambda x: fuzzy_match(cell_name, x))
cell.enabled = True
project.spreadsheet_import.use_custom_cells = True
SPREADSHEET.extend(rows)
return {"FINISHED"}
class VSETB_OT_import_spreadsheet(Operator):
bl_idname = "vse_toolbox.import_spreadsheet"
bl_label = "Import Spreadsheet"
@@ -368,13 +402,7 @@ class VSETB_OT_import_spreadsheet(Operator):
strip_settings.casting.update()
else:
self.report({'WARNING'}, f'Asset {asset_name} not found in Project')
self.report({'WARNING'}, f'Asset {asset_name} not found in Project')
return {"FINISHED"}
@@ -446,12 +474,13 @@ class VSETB_OT_export_spreadsheet(Operator):
row.prop(spreadsheet, 'show_settings', text='', icon='PREFERENCES')
if spreadsheet.show_settings:
col.prop(spreadsheet, "separator", expand=True, text='Separator')
if spreadsheet.format == 'CSV':
if spreadsheet.format == 'csv':
col.prop(spreadsheet, "delimiter", expand=True, text='Delimiter')
col.separator()
col.prop(spreadsheet, 'open_folder', text='Open Folder')
col.prop(spreadsheet, 'export_path', text='Export Path')
if spreadsheet.format != 'Clipboard':
col.separator()
col.prop(spreadsheet, 'open_folder', text='Open Folder')
col.prop(spreadsheet, 'export_path', text='Export Path')
def execute(self, context):
#self.report({'ERROR'}, f'Export not implemented yet.')
@@ -499,7 +528,7 @@ class VSETB_OT_export_spreadsheet(Operator):
row += [strip.name]
elif cell.field_name == 'DESCRIPTION':
row += [strip.vsetb_strip_settings.description]
elif cell.field_name == 'FRAMES':
elif cell.field_name == 'NB_FRAMES':
row += [strip.frame_final_duration]
rows.append(row)
@@ -531,14 +560,14 @@ class VSETB_OT_export_spreadsheet(Operator):
#2023_04_11_kitsu_boris_ep01_shots
export_path.parent.mkdir(parents=True, exist_ok=True)
if spreadsheet.format == 'CSV':
if spreadsheet.format == 'csv':
print('Writing .csv file to', export_path)
with open(str(export_path), 'w', newline='\n', encoding='utf-8') as f:
writer = csv.writer(f, delimiter=spreadsheet.delimiter)
for row in rows:
writer.writerow(row)
elif spreadsheet.format == 'XLSX':
elif spreadsheet.format == 'xlsx':
try:
import openpyxl
except ModuleNotFoundError:
@@ -558,6 +587,15 @@ class VSETB_OT_export_spreadsheet(Operator):
# Save the file
workbook.save(str(export_path))
elif spreadsheet.format == 'Clipboard':
csv_buffer = StringIO()
# Write CSV data to the StringIO buffer
csv_writer = csv.writer(csv_buffer, delimiter='\t')
csv_writer.writerows(rows)
context.window_manager.clipboard = csv_buffer.getvalue()
if spreadsheet.open_folder:
open_file(export_path, select=True)
@@ -570,6 +608,7 @@ classes = (
VSETB_MT_export_spreadsheet_presets,
VSETB_OT_spreadsheet_from_file,
VSETB_OT_spreadsheet_from_clipboard,
VSETB_OT_spreadsheet_to_clipboard,
VSETB_OT_spreadsheet_cell_move,
VSETB_OT_export_spreadsheet,
VSETB_OT_import_spreadsheet