vse_toolbox/operators/casting.py

363 lines
11 KiB
Python

import json
import bpy
from bpy.types import Context, Event, PropertyGroup, Operator
from bpy.props import (CollectionProperty, EnumProperty, StringProperty)
from vse_toolbox.constants import CASTING_BUFFER, ASSET_ITEMS
from vse_toolbox.sequencer_utils import get_strips
from vse_toolbox.bl_utils import (get_addon_prefs, get_scene_settings, get_strip_settings)
from time import perf_counter
class VSETB_OT_casting_replace(Operator):
bl_idname = "vse_toolbox.casting_replace"
bl_label = "Replace Asset"
bl_description = "Replace Asset of selected strips"
old_asset : StringProperty()
new_asset : StringProperty()
assets : CollectionProperty(type=PropertyGroup)
def execute(self, context):
prefs = get_addon_prefs()
settings = get_scene_settings()
new_asset = next(a for a in settings.active_project.assets if a.tracker_name == self.new_asset)
for strip in get_strips('Shots', selected_only=True):
strip_settings = strip.vsetb_strip_settings
for asset_casting in strip_settings.casting:
if asset_casting.asset.tracker_name == self.old_asset:
print(f'Replace casting on {strip.name}')
asset_casting.name = new_asset.name
asset_casting.id = new_asset.id
asset_casting['_name'] = new_asset.label
strip_settings.casting.update()
self.assets.clear()
return {'FINISHED'}
def invoke(self, context, event):
settings = get_scene_settings()
project = settings.active_project
self.assets.clear()
for asset in project.assets:
item = self.assets.add()
item.name = asset.tracker_name
strip = context.active_sequence_strip
asset_casting_index = strip.vsetb_strip_settings.casting_index
active_asset = strip.vsetb_strip_settings.casting[asset_casting_index].asset
self.old_asset = active_asset.tracker_name
self.new_asset = ''
return context.window_manager.invoke_props_dialog(self)
#
def draw(self, context):
scn = context.scene
settings = get_scene_settings()
project = settings.active_project
layout = self.layout
col = layout.column()
col.use_property_split = True
col.prop_search(self, 'old_asset', self, 'assets', text='Old Asset', icon='ASSET_MANAGER')
col.prop_search(self, 'new_asset', self, 'assets', text='New Asset', icon='ASSET_MANAGER')
class VSETB_OT_casting_add(Operator):
bl_idname = "vse_toolbox.casting_add"
bl_label = "Casting Add"
bl_description = "Add Asset to Castin"
bl_options = {"REGISTER", "UNDO"}
bl_property = "asset_name"
asset_name : EnumProperty(name='', items=lambda s,c : ASSET_ITEMS)
#asset_name : EnumProperty(name='', items=get_scene_settings().active_project.get('asset_items', []))
@classmethod
def poll(cls, context):
active_strip = context.scene.sequence_editor.active_strip
if active_strip:
return True
def invoke(self, context, event):
context.window_manager.invoke_search_popup(self)
return {'FINISHED'}
def execute(self, context):
scn = context.scene
settings = get_scene_settings()
project = settings.active_project
asset = project.assets[self.asset_name]
strips = get_strips('Shots', selected_only=True)
for strip in strips:
#active_strip = scn.sequence_editor.active_strip
strip_settings = strip.vsetb_strip_settings
if strip_settings.casting.get(self.asset_name):
self.report({'WARNING'}, f"Asset {asset.label} already casted.")
return {"CANCELLED"}
item = strip_settings.casting.add()
item.name = asset.name
item.id = asset.id
item['_name'] = asset.label
strip_settings.casting.update()
self.report({"INFO"}, f'Item {asset.label} added in {len(strips)} shots')
return {"FINISHED"}
class VSETB_OT_casting_remove(Operator):
bl_idname = "vse_toolbox.casting_remove"
bl_label = "Remove Item from Casting"
bl_description = "Remove Item from Casting"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
active_strip = context.scene.sequence_editor.active_strip
if active_strip:
return True
def invoke(self, context, event):
scn = context.scene
settings = get_strip_settings()
asset_id = settings.active_casting.id
strips = get_strips('Shots', selected_only=True)
strips_modified = 0
for strip in strips:
strip_settings = strip.vsetb_strip_settings
for i, asset_casting in enumerate(list(strip_settings.casting)):
if asset_casting.id == asset_id:
strip_settings.casting.remove(i)
if strip_settings.casting_index != 0:
strip_settings.casting_index -= 1
strips_modified += 1
continue
if asset := settings.active_casting.asset:
name = asset.label
else:
name = settings.active_casting.get('_name', '')
self.report({"INFO"}, f'Item {name} removed in {strips_modified} shots')
return {"FINISHED"}
class VSETB_OT_casting_move(Operator):
bl_idname = "vse_toolbox.casting_move"
bl_label = "Move Casting items"
bl_description = "Move Casting items"
bl_options = {"REGISTER", "UNDO"}
direction: EnumProperty(
items=(
('UP', "Up", ""),
('DOWN', "Down", ""),
)
)
asset_name : StringProperty()
@classmethod
def poll(cls, context):
active_strip = context.scene.sequence_editor.active_strip
if active_strip:
return True
def execute(self, context):
scn = context.scene
strip_settings = get_strip_settings()
idx = strip_settings.casting_index
try:
item = strip_settings.casting[idx]
except IndexError:
pass
else:
if self.direction == 'DOWN' and idx < len(strip_settings.casting) - 1:
item_next = strip_settings.casting[idx+1].name
strip_settings.casting.move(idx, idx+1)
strip_settings.casting_index += 1
elif self.direction == 'UP' and idx >= 1:
item_prev = strip_settings.casting[idx-1].name
strip_settings.casting.move(idx, idx-1)
strip_settings.casting_index -= 1
info = f"Item {item.asset.label} moved to position {(item.asset.label, strip_settings.casting_index + 1)}"
self.report({'INFO'}, info)
return {"FINISHED"}
class VSETB_OT_copy_casting(Operator):
bl_idname = "vse_toolbox.copy_casting"
bl_label = "Copy Casting"
bl_description = "Copy Casting from active strip"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
active_strip = context.scene.sequence_editor.active_strip
strip_settings = get_strip_settings()
if active_strip and strip_settings.casting:
return True
def execute(self, context):
scn = context.scene
active_strip = scn.sequence_editor.active_strip
strip_settings = get_strip_settings()
datas = [c.to_dict() for c in strip_settings.casting]
CASTING_BUFFER.write_text(json.dumps(datas), encoding='utf-8')
return {"FINISHED"}
class VSETB_OT_paste_casting(Operator):
bl_idname = "vse_toolbox.paste_casting"
bl_label = "Paste Casting"
bl_description = "Paste Casting to active strip (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()
if not CASTING_BUFFER.exists():
self.report({'ERROR'}, f'No Casting to copy.')
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
if self.mode == 'REPLACE':
strip.vsetb_strip_settings.casting.clear()
for casting_data in casting_datas:
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)
if strip_settings.casting_index != 0:
strip_settings.casting_index -= 1
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"}
class VSETB_OT_copy_metadata(Operator):
bl_idname = "vse_toolbox.copy_metadata"
bl_label = "Copy metadata to selected"
bl_description = "Copy Metadata to selected strips"
metadata : StringProperty()
@classmethod
def poll(cls, context):
return context.selected_sequences and context.active_sequence_strip
def execute(self, context):
prefs = get_addon_prefs()
settings = get_scene_settings()
project = settings.active_project
metadata = next((m.field_name for m in project.metadata_types if m.name == self.metadata), None)
if not metadata:
self.report({'ERROR'}, f'No Metadata named {self.metadata}')
active_strip = context.active_sequence_strip
metadata_value = getattr(active_strip.vsetb_strip_settings.metadata, metadata)
for strip in context.selected_sequences:
if strip == context.active_sequence_strip:
continue
setattr(strip.vsetb_strip_settings.metadata, metadata, metadata_value)
return {"FINISHED"}
classes = (
VSETB_OT_casting_add,
VSETB_OT_casting_remove,
VSETB_OT_casting_move,
VSETB_OT_copy_casting,
VSETB_OT_paste_casting,
VSETB_OT_casting_replace,
VSETB_OT_copy_metadata
)
def register():
for cls in classes:
bpy.utils.register_class(cls)
def unregister():
for cls in reversed(classes):
bpy.utils.unregister_class(cls)