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