1# 2# Copyright (C) 2016-2020 by Nathan Lovato, Daniel Oakey, Razvan Radulescu, and contributors 3# 4# This file is part of Power Sequencer. 5# 6# Power Sequencer is free software: you can redistribute it and/or modify it under the terms of the 7# GNU General Public License as published by the Free Software Foundation, either version 3 of the 8# License, or (at your option) any later version. 9# 10# Power Sequencer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 11# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12# GNU General Public License for more details. 13# 14# You should have received a copy of the GNU General Public License along with Power Sequencer. If 15# not, see <https://www.gnu.org/licenses/>. 16# 17import bpy 18 19from .utils.doc import doc_brief, doc_description, doc_idname, doc_name 20from .utils.functions import ( 21 get_frame_range, 22 get_mouse_frame_and_channel, 23 slice_selection, 24 ripple_move, 25) 26 27 28class POWER_SEQUENCER_OT_ripple_delete(bpy.types.Operator): 29 """ 30 Delete selected strips and remove remaining gaps 31 """ 32 33 doc = { 34 "name": doc_name(__qualname__), 35 "demo": "", 36 "description": doc_description(__doc__), 37 "shortcuts": [({"type": "X", "value": "PRESS", "shift": True}, {}, "Ripple Delete")], 38 "keymap": "Sequencer", 39 } 40 bl_idname = doc_idname(__qualname__) 41 bl_label = doc["name"] 42 bl_description = doc_brief(doc["description"]) 43 bl_options = {"REGISTER", "UNDO"} 44 45 @classmethod 46 def poll(cls, context): 47 return context.sequences 48 49 def invoke(self, context, event): 50 # Auto select if no strip selected 51 frame, channel = get_mouse_frame_and_channel(context, event) 52 if not context.selected_sequences: 53 bpy.ops.power_sequencer.select_closest_to_mouse(frame=frame, channel=channel) 54 if not context.selected_sequences: 55 return {"CANCELLED"} 56 return self.execute(context) 57 58 def execute(self, context): 59 scene = context.scene 60 sequencer = bpy.ops.sequencer 61 selection = context.selected_sequences 62 selection_length = len(selection) 63 64 audio_scrub_active = context.scene.use_audio_scrub 65 context.scene.use_audio_scrub = False 66 67 channels = list(set([s.channel for s in selection])) 68 selection_blocks = slice_selection(context, selection) 69 70 is_single_channel = len(channels) == 1 71 if is_single_channel: 72 for block in selection_blocks: 73 delete_start = block[0].frame_final_start 74 delete_end = block[-1].frame_final_end 75 ripple_duration = abs(delete_end - delete_start) 76 ripple_move(context, block, -ripple_duration, delete=True) 77 78 else: 79 cursor_frame = scene.frame_current 80 for block in selection_blocks: 81 sequencer.select_all(action="DESELECT") 82 for s in block: 83 s.select = True 84 selection_start = get_frame_range(block)[0] 85 sequencer.delete() 86 87 scene.frame_current = selection_start 88 bpy.ops.power_sequencer.gap_remove() 89 scene.frame_current = cursor_frame 90 91 self.report( 92 {"INFO"}, 93 "Deleted " + str(selection_length) + " sequence" + "s" if selection_length > 1 else "", 94 ) 95 96 context.scene.use_audio_scrub = audio_scrub_active 97 return {"FINISHED"} 98