Page MenuHome

sequencer_extra_actions.py

sequencer_extra_actions.py

# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
bl_info = {
'name': 'Extra Sequencer Actions',
'author': 'Turi Scandurra',
'version': (1, 0),
'blender': (2, 6, 2, 1),
'api': 44652,
'category': 'Sequencer',
'location': 'Sequencer',
'description': 'Collection of extra operators to manipulate VSE strips',
'wiki_url': '',
'tracker_url': '',
'support': 'COMMUNITY'}
'''
Usage:
- Install the script by copying its .py file to your Blender addons
folder. Enable the script in User Preferences > Addons > Sequencer.
The script is composed of a collection of several operators placed in
different locations.
Location: Timeline > Frame
- Trim to Timeline Content
Automatically set start and end frames of current scene according to
the content of the Sequence Editor.
- Trim to Selection
Set start and end frames of current scene to match selected strips
in the Sequence Editor.
Location: Video Sequence Editor > Select
- Select All by Type
Select all the strips of the specified type in the Sequence Editor.
Location: Video Sequence Editor > Strip
- Edit Externally
Open active image strip with the default external image editor. To use
this operator a valid path to the external editor must be specified in
User Preferences > File.
- Ripple Delete
Delete the active strip and shift back all other strips the number of
frames between the beginning of deleted strip and the next edit in the
sequence.
- File Name to Strip Name
Set strip name to input file name. This operator is useful after
separating images of a sequence.
- Slide
Alter in and out points of a strip but not its duration. Only available
when a the type of active strip is Movie, Scene or Meta.
Click 'Input...' to choose the amount of sliding desired. The start and
end frame of active strip will be moved, but its length and position
will remain unchanged. This action is also known as slipping.
Click 'Current Frame to Start' or 'Current Frame to End' to perform the
slide according to current frame.
- Copy Properties
Copy properties of active strip to selected strips. Start selecting
multiple strips, then make active the strip whose properties need to be
copied to the selected strips. Click the desired operator to perform
the action. Some operators affect single properties, while some others
affect a group of properties.
- Fade
Fade opacity of active strip, or its volume if its type is Sound,
creating keyframes for the corresponding property.
Possible fade directions are In, Out, In and Out.
Duration defines the number of frames between the start and the end
of the fade.
Amount defines the maximum value that the fade will set. For opacity
fades, the maximum value is 1.0.
The minimum value reached by the fade is always 0.
Keyframes created with this operator can be manipulated through the
F-Curve Editor.
- Distribute
Evenly distribute selected strips along the timeline according to a
specified offset. This operator is useful to reassign strip length to
every element of an image sequence.
The operator also allows to reverse the order of the distributed strips.
To perform a simple reversion of an image sequence, first separate its
images and select them, then run Distribute with Offset set to 1 and
Reverse Order enabled.
- Navigate Up
Move current view to parent timeline. Only enabled when current view is
relative to a Meta strip. This operator does not perform any
modification to timeline elements.
Version History:
- 1.0, 2012-03-07 - Initial release
'''
import bpy
from bpy.types import Menu
from bpy.types import Header
from bpy.props import IntProperty
from bpy.props import FloatProperty
from bpy.props import EnumProperty
from bpy.props import BoolProperty
# ##### UTILS #####
def act_strip(context):
try:
return context.scene.sequence_editor.active_strip
except AttributeError:
return None
# ##### INITIALIZATION #####
def initSceneProperties(scn):
try:
if bpy.context.scene.scene_initialized == True:
return False
except AttributeError:
pass
bpy.types.Scene.default_slide_offset = IntProperty(
name='Offset',
description='Number of frames to slide',
min=-250, max=250,
default=0)
scn['default_slide_offset'] = 0
bpy.types.Scene.default_fade_duration = IntProperty(
name='Duration',
description='Number of frames to fade',
min=1, max=250,
default=scn.render.fps)
scn['default_fade_duration'] = scn.render.fps
bpy.types.Scene.default_fade_amount = FloatProperty(
name='Amount',
description='Maximum value of fade',
min=0.0,
max=100.0,
default=1.0)
scn['default_fade_amount'] = 1.0
bpy.types.Scene.default_distribute_offset = IntProperty(
name='Offset',
description='Number of frames between strip start frames',
min=1,
max=250,
default=2)
scn['default_distribute_offset'] = 2
bpy.types.Scene.default_distribute_reverse = BoolProperty(
name='Reverse Order',
description='Reverse the order of selected strips',
default=False)
scn['default_distribute_reverse'] = False
bpy.types.Scene.scene_initialized = BoolProperty(
name='Init',
default=False)
scn['scene_initialized'] = True
return True
# ##### CLASSES #####
# TRIM TIMELINE
class Sequencer_Extra_TrimTimeline(bpy.types.Operator):
bl_label = 'Trim to Timeline Content'
bl_idname = 'timeextra.trimtimeline'
bl_description = 'Automatically set start and end frames'
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
scn = bpy.context.scene
seq = scn.sequence_editor
meta_level = len(seq.meta_stack)
if meta_level > 0:
seq = seq.meta_stack[meta_level - 1]
frame_start = 300000
frame_end = -300000
for i in seq.sequences:
try:
if i.frame_final_start < frame_start:
frame_start = i.frame_final_start
if i.frame_final_end > frame_end:
frame_end = i.frame_final_end - 1
except AttributeError:
pass
if frame_start != 300000:
scn.frame_start = frame_start
if frame_end != -300000:
scn.frame_end = frame_end
return {'FINISHED'}
# TRIM TIMELINE TO SELECTION
class Sequencer_Extra_TrimTimelineToSelection(bpy.types.Operator):
bl_label = 'Trim to Selection'
bl_idname = 'timeextra.trimtimelinetoselection'
bl_description = 'Set start and end frames to selection'
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
scn = bpy.context.scene
seq = scn.sequence_editor
meta_level = len(seq.meta_stack)
if meta_level > 0:
seq = seq.meta_stack[meta_level - 1]
frame_start = 300000
frame_end = -300000
for i in seq.sequences:
try:
if i.frame_final_start < frame_start and i.select == True:
frame_start = i.frame_final_start
if i.frame_final_end > frame_end and i.select == True:
frame_end = i.frame_final_end - 1
except AttributeError:
pass
if frame_start != 300000:
scn.frame_start = frame_start
if frame_end != -300000:
scn.frame_end = frame_end
return {'FINISHED'}
# SLIDE STRIP
class Sequencer_Extra_SlideStrip(bpy.types.Operator):
bl_label = 'Slide'
bl_idname = 'sequencerextra.slide'
bl_description = 'Alter in and out points but not duration of a strip'
mode = EnumProperty(
name="Mode",
items=(
('TOSTART', 'Current Frame to Strip Start', ''),
('TOEND', 'Current Frame to Strip End', ''),
('INPUT', 'Input...', '')),
default='INPUT',
options={'HIDDEN'}
)
bl_options = {'REGISTER', 'UNDO'}
initSceneProperties(bpy.context.scene)
@classmethod
def poll(self, context):
strip = act_strip(context)
scn = context.scene
if scn and scn.sequence_editor and scn.sequence_editor.active_strip:
return strip.type in ('MOVIE', 'IMAGE', 'META', 'SCENE')
else:
return False
slide_offset = bpy.types.Scene.default_slide_offset
def execute(self, context):
strip = act_strip(context)
scn = context.scene
cf = scn.frame_current
if self.mode == 'TOSTART':
sx = strip.frame_final_start - cf
elif self.mode == 'TOEND':
sx = strip.frame_final_end - cf
else:
sx = self.slide_offset
frame_end = strip.frame_start + strip.frame_duration
pad_left = strip.frame_final_start - strip.frame_start
pad_right = (frame_end - strip.frame_final_end) * -1
if sx > pad_left:
sx = pad_left
elif sx < pad_right:
sx = pad_right
strip.frame_start += sx
strip.frame_final_start -= sx
strip.frame_final_end -= sx
self.report({'INFO'}, "Strip slid %d frame(s)" % (sx))
scn['default_slide_offset'] = sx
bpy.ops.sequencer.reload()
return {'FINISHED'}
def invoke(self, context, event):
scn = context.scene
self.slide_offset = scn['default_slide_offset']
if self.mode == 'INPUT':
return context.window_manager.invoke_props_dialog(self)
else:
return self.execute(context)
# FILE NAME TO STRIP NAME
class Sequencer_Extra_FileNameToStripName(bpy.types.Operator):
bl_label = 'File Name to Selected Strips Name'
bl_idname = 'sequencerextra.striprename'
bl_description = 'Set strip name to input file name'
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
scn = bpy.context.scene
seq = scn.sequence_editor
meta_level = len(seq.meta_stack)
if meta_level > 0:
seq = seq.meta_stack[meta_level - 1]
selection = False
for i in seq.sequences:
if i.select == True:
if i.type == 'IMAGE':
selection = True
i.name = i.elements[0].filename
if i.type == 'SOUND' or i.type == 'MOVIE':
selection = True
i.name = bpy.path.display_name_from_filepath(i.filepath)
if selection == False:
self.report({'ERROR_INVALID_INPUT'},
'No image or movie strip selected')
return {'CANCELLED'}
return {'FINISHED'}
# NAVIGATE UP
class Sequencer_Extra_NavigateUp(bpy.types.Operator):
bl_label = 'Navigate Up'
bl_idname = 'sequencerextra.navigateup'
bl_description = 'Move to Parent Timeline'
@classmethod
def poll(self, context):
strip = act_strip(context)
try:
if context.scene.sequence_editor.meta_stack:
return True
else:
return False
except:
return False
def execute(self, context):
if (act_strip(context)):
strip = act_strip(context)
seq_type = strip.type
if seq_type == 'META':
context.scene.sequence_editor.active_strip = None
bpy.ops.sequencer.meta_toggle()
return {'FINISHED'}
# RIPPLE DELETE
class Sequencer_Extra_Rippledelete(bpy.types.Operator):
bl_label = 'Ripple delete'
bl_idname = 'sequencerextra.rippledelete'
bl_description = 'Delete a strip and shift back following ones'
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(self, context):
strip = act_strip(context)
scn = context.scene
if scn and scn.sequence_editor and scn.sequence_editor.active_strip:
return True
else:
return False
def execute(self, context):
scn = bpy.context.scene
seq = scn.sequence_editor
meta_level = len(seq.meta_stack)
if meta_level > 0:
seq = seq.meta_stack[meta_level - 1]
strip = act_strip(context)
cut_frame = strip.frame_final_start
next_edit = 300000
bpy.ops.sequencer.select_all(action='DESELECT')
strip.select = True
bpy.ops.sequencer.delete()
striplist = []
for i in seq.sequences:
try:
if i.frame_final_start > cut_frame:
if i.frame_final_start < next_edit:
next_edit = i.frame_final_start
striplist.append(i)
except AttributeError:
pass
if next_edit == 300000:
return {'FINISHED'}
ripple_length = next_edit - cut_frame
for i in range(len(striplist)):
strip = striplist[i]
try:
if strip.frame_final_start > cut_frame:
strip.frame_start = strip.frame_start - ripple_length
except AttributeError:
pass
bpy.ops.sequencer.reload()
return {'FINISHED'}
# SELECT BY TYPE
class Sequencer_Extra_SelectAllByType(bpy.types.Operator):
bl_label = 'All by Type'
bl_idname = 'sequencerextra.select_all_by_type'
bl_description = 'Select all the strips of the same type'
type = EnumProperty(
name="Strip Type",
items=(
('ACTIVE', "Same as Active Strip", ""),
('IMAGE', "Image", ""),
('META', "Meta", ""),
('SCENE', "Scene", ""),
('MOVIE', "Movie", ""),
('SOUND', "Sound", ""),
('TRANSFORM', "Transform", ""),
('COLOR', "Color", "")),
default='ACTIVE',
)
bl_options = {'REGISTER', 'UNDO'}
def invoke(self, context, event):
strip_type = self.type
scn = bpy.context.scene
seq = scn.sequence_editor
meta_level = len(seq.meta_stack)
if meta_level > 0:
seq = seq.meta_stack[meta_level - 1]
active_strip = act_strip(context)
if strip_type == 'ACTIVE':
if active_strip == None:
self.report({'ERROR_INVALID_INPUT'},
'No active strip')
return {'CANCELLED'}
strip_type = active_strip.type
striplist = []
for i in seq.sequences:
try:
if i.type == strip_type:
striplist.append(i)
except AttributeError:
pass
# TWO PASSES REQUIRED FOR ACCURACY
for i in range(len(striplist)):
strip = striplist[i]
try:
strip.select = True
except AttributeError:
pass
bpy.ops.sequencer.reload()
return {'FINISHED'}
# OPEN IMAGE WITH EXTERNAL EDITOR
class Sequencer_Extra_EditExternally(bpy.types.Operator):
bl_label = 'Edit Externally'
bl_idname = 'sequencerextra.editexternally'
bl_description = 'Open with the default external image editor'
@classmethod
def poll(self, context):
strip = act_strip(context)
scn = context.scene
if scn and scn.sequence_editor and scn.sequence_editor.active_strip:
return strip.type == 'IMAGE'
else:
return False
def execute(self, context):
strip = act_strip(context)
scn = bpy.context.scene
base_dir = bpy.path.abspath(strip.directory)
strip_elem = strip.getStripElem(scn.frame_current)
file_path = base_dir + strip_elem.filename
try:
bpy.ops.image.external_edit(filepath=file_path)
except AttributeError:
self.report({'ERROR_INVALID_INPUT'},
'Please specify an Image Editor in Preferences > File')
return {'CANCELLED'}
return {'FINISHED'}
# COPY STRIP PROPERTIES
class Sequencer_Extra_CopyProperties(bpy.types.Operator):
bl_label = 'Copy Properties'
bl_idname = 'sequencerextra.copyproperties'
bl_description = 'Copy properties of active strip to selected strips'
bl_options = {'REGISTER', 'UNDO'}
prop = EnumProperty(
name="Property",
items=[
# COMMON
('name', 'Name', ''),
('blend_alpha', 'Opacity', ''),
('blend_type', 'Blend Mode', ''),
('animation_offset', 'Input - Trim Duration', ''),
# NON-SOUND
('use_translation', 'Input - Image Offset', ''),
('crop', 'Input - Image Crop', ''),
('proxy', 'Proxy / Timecode', ''),
('strobe', 'Filter - Strobe', ''),
('color_balance', 'Filter - Color Balance', ''),
('color_multiply', 'Filter - Multiply', ''),
('color_saturation', 'Filter - Saturation', ''),
('deinterlace', 'Filter - De-Interlace', ''),
('flip', 'Filter - Flip', ''),
('float', 'Filter - Convert Float', ''),
('premultiply', 'Filter - Premultiply', ''),
('reverse', 'Filter - Backwards', ''),
# SOUND
('pan', 'Sound - Pan', ''),
('pitch', 'Sound - Pitch', ''),
('volume', 'Sound - Volume', ''),
('cache', 'Sound - Caching', ''),
# IMAGE
('directory', 'Image - Directory', ''),
# MOVIE
('mpeg_preseek', 'Movie - MPEG Preseek', ''),
('stream_index', 'Movie - Stream Index', ''),
# WIPE
('wipe', 'Effect - Wipe', ''),
# TRANSFORM
('transform', 'Effect - Transform', ''),
# COLOR
('color', 'Effect - Color', ''),
# SPEED
('speed', 'Effect - Speed', ''),
# MULTICAM
('multicam_source', 'Effect - Multicam Source', ''),
# EFFECT
('effect_fader', 'Effect - Effect Fader', ''),
],
default='blend_alpha')
@classmethod
def poll(self, context):
strip = act_strip(context)
scn = context.scene
if scn and scn.sequence_editor and scn.sequence_editor.active_strip:
return True
else:
return False
def execute(self, context):
scn = bpy.context.scene
seq = scn.sequence_editor
meta_level = len(seq.meta_stack)
if meta_level > 0:
seq = seq.meta_stack[meta_level - 1]
strip = act_strip(context)
for i in seq.sequences:
if i.select == True:
try:
if self.prop == 'name':
i.name = strip.name
elif self.prop == 'blend_alpha':
i.blend_alpha = strip.blend_alpha
elif self.prop == 'blend_type':
i.blend_type = strip.blend_type
elif self.prop == 'animation_offset':
i.animation_offset_start = strip.animation_offset_start
i.animation_offset_end = strip.animation_offset_end
elif self.prop == 'use_translation':
i.use_translation = strip.use_translation
i.transform.offset_x = strip.transform.offset_x
i.transform.offset_y = strip.transform.offset_y
elif self.prop == 'crop':
i.use_crop = strip.use_crop
i.crop.min_x = strip.crop.min_x
i.crop.min_y = strip.crop.min_y
i.crop.max_x = strip.crop.max_x
i.crop.max_y = strip.crop.max_y
elif self.prop == 'proxy':
i.use_proxy = strip.use_proxy
i.use_proxy_custom_file = strip.use_proxy_custom_file
i.use_proxy_custom_directory = strip.use_proxy_custom_directory
i.proxy.filepath = strip.proxy.filepath
i.proxy.directory = strip.proxy.directory
i.proxy.build_25 = strip.proxy.build_25
i.proxy.build_50 = strip.proxy.build_50
i.proxy.build_75 = strip.proxy.build_75
i.proxy.build_100 = strip.proxy.build_100
i.proxy.quality = strip.proxy.quality
i.proxy.timecode = strip.proxy.timecode
elif self.prop == 'strobe':
i.strobe = strip.strobe
elif self.prop == 'color_balance':
i.use_color_balance = strip.use_color_balance
i.use_color_balance = strip.use_color_balance
i.color_balance.lift = strip.color_balance.lift
i.color_balance.gamma = strip.color_balance.gamma
i.color_balance.gain = strip.color_balance.gain
i.color_balance.invert_lift = strip.color_balance.invert_lift
i.color_balance.invert_gamma = strip.color_balance.invert_gamma
i.color_balance.invert_gain = strip.color_balance.invert_gain
elif self.prop == 'color_multiply':
i.color_multiply = strip.color_multiply
elif self.prop == 'color_saturation':
i.color_saturation = strip.color_saturation
elif self.prop == 'deinterlace':
i.use_deinterlace = strip.use_deinterlace
elif self.prop == 'flip':
i.use_flip_x = strip.use_flip_x
i.use_flip_y = strip.use_flip_y
elif self.prop == 'float':
i.use_float = strip.use_float
elif self.prop == 'premultiply':
i.use_premultiply = strip.use_premultiply
elif self.prop == 'reverse':
i.use_reverse_frames = strip.use_reverse_frames
elif self.prop == 'pan':
i.pan = strip.pan
elif self.prop == 'pitch':
i.pitch = strip.pitch
elif self.prop == 'volume':
i.volume = strip.volume
elif self.prop == 'cache':
i.use_memory_cache = strip.use_memory_cache
elif self.prop == 'directory':
i.directory = strip.directory
elif self.prop == 'mpeg_preseek':
i.mpeg_preseek = strip.mpeg_preseek
elif self.prop == 'stream_index':
i.stream_index = strip.stream_index
elif self.prop == 'wipe':
i.angle = strip.angle
i.blur_width = strip.blur_width
i.direction = strip.direction
i.transition_type = strip.transition_type
elif self.prop == 'transform':
i.interpolation = strip.interpolation
i.rotation_start = strip.rotation_start
i.use_uniform_scale = strip.use_uniform_scale
i.scale_start_x = strip.scale_start_x
i.scale_start_y = strip.scale_start_y
i.translation_unit = strip.translation_unit
i.translate_start_x = strip.translate_start_x
i.translate_start_y = strip.translate_start_y
elif self.prop == 'color':
i.color = strip.color
elif self.prop == 'speed':
i.use_default_fade = strip.use_default_fade
i.speed_factor = strip.speed_factor
i.use_as_speed = strip.use_as_speed
i.scale_to_length = strip.scale_to_length
i.multiply_speed = strip.multiply_speed
i.use_frame_blend = strip.use_frame_blend
elif self.prop == 'multicam_source':
i.multicam_source = strip.multicam_source
elif self.prop == 'effect_fader':
i.use_default_fade = strip.use_default_fade
i.effect_fader = strip.effect_fader
except AttributeError:
pass
bpy.ops.sequencer.reload()
return {'FINISHED'}
# FADE IN AND OUT
class Sequencer_Extra_FadeInOut(bpy.types.Operator):
bl_idname = "sequencerextra.fadeinout"
bl_label = "Fade..."
bl_description = 'Fade volume or opacity of active strip'
mode = EnumProperty(
name="Direction",
items=(
('IN', "Fade In...", ""),
('OUT', "Fade Out...", ""),
('INOUT', "Fade In and Out...", "")),
default='IN',
)
bl_options = {'REGISTER', 'UNDO'}
initSceneProperties(bpy.context.scene)
@classmethod
def poll(cls, context):
scn = context.scene
if scn and scn.sequence_editor and scn.sequence_editor.active_strip:
return True
else:
return False
fade_duration = bpy.types.Scene.default_fade_duration
fade_amount = bpy.types.Scene.default_fade_amount
def execute(self, context):
seq = context.scene.sequence_editor
scn = bpy.context.scene
strip = seq.active_strip
tmp_current_frame = context.scene.frame_current
if strip.type == 'SOUND':
if(self.mode) == 'OUT':
context.scene.frame_current = strip.frame_final_end - self.fade_duration
strip.volume = self.fade_amount
strip.keyframe_insert('volume')
context.scene.frame_current = strip.frame_final_end
strip.volume = 0
strip.keyframe_insert('volume')
elif(self.mode) == 'INOUT':
context.scene.frame_current = strip.frame_final_start
strip.volume = 0
strip.keyframe_insert('volume')
context.scene.frame_current += self.fade_duration
strip.volume = self.fade_amount
strip.keyframe_insert('volume')
context.scene.frame_current = strip.frame_final_end - self.fade_duration
strip.volume = self.fade_amount
strip.keyframe_insert('volume')
context.scene.frame_current = strip.frame_final_end
strip.volume = 0
strip.keyframe_insert('volume')
else:
context.scene.frame_current = strip.frame_final_start
strip.volume = 0
strip.keyframe_insert('volume')
context.scene.frame_current += self.fade_duration
strip.volume = self.fade_amount
strip.keyframe_insert('volume')
else:
if(self.mode) == 'OUT':
context.scene.frame_current = strip.frame_final_end - self.fade_duration
strip.blend_alpha = self.fade_amount
strip.keyframe_insert('blend_alpha')
context.scene.frame_current = strip.frame_final_end
strip.blend_alpha = 0
strip.keyframe_insert('blend_alpha')
elif(self.mode) == 'INOUT':
context.scene.frame_current = strip.frame_final_start
strip.blend_alpha = 0
strip.keyframe_insert('blend_alpha')
context.scene.frame_current += self.fade_duration
strip.blend_alpha = self.fade_amount
strip.keyframe_insert('blend_alpha')
context.scene.frame_current = strip.frame_final_end - self.fade_duration
strip.blend_alpha = self.fade_amount
strip.keyframe_insert('blend_alpha')
context.scene.frame_current = strip.frame_final_end
strip.blend_alpha = 0
strip.keyframe_insert('blend_alpha')
else:
context.scene.frame_current = strip.frame_final_start
strip.blend_alpha = 0
strip.keyframe_insert('blend_alpha')
context.scene.frame_current += self.fade_duration
strip.blend_alpha = self.fade_amount
strip.keyframe_insert('blend_alpha')
context.scene.frame_current = tmp_current_frame
scn['default_fade_duration'] = self.fade_duration
scn['default_fade_amount'] = self.fade_amount
return{'FINISHED'}
def invoke(self, context, event):
scn = bpy.context.scene
self.fade_duration = scn['default_fade_duration']
self.fade_amount = scn['default_fade_amount']
return context.window_manager.invoke_props_dialog(self)
# DISTRIBUTE
class Sequencer_Extra_Distribute(bpy.types.Operator):
bl_idname = "sequencerextra.distribute"
bl_label = "Distribute..."
bl_description = 'Evenly distribute selected strips'
bl_options = {'REGISTER', 'UNDO'}
initSceneProperties(bpy.context.scene)
distribute_offset = bpy.types.Scene.default_distribute_offset
distribute_reverse = bpy.types.Scene.default_distribute_reverse
def execute(self, context):
scn = bpy.context.scene
seq = scn.sequence_editor
meta_level = len(seq.meta_stack)
if meta_level > 0:
seq = seq.meta_stack[meta_level - 1]
seq_list = {}
first_start = 300000
item_num = 0
for i in seq.sequences:
if i.select == True:
seq_list[i.frame_start] = i.name
item_num += 1
if i.frame_start < first_start:
first_start = i.frame_start
n = item_num - 1
if(self.distribute_reverse):
for key in sorted(seq_list.keys()):
dest_frame = first_start + (n * self.distribute_offset)
seq.sequences_all[str(seq_list[key])].frame_start = dest_frame
n -= 1
else:
for key in sorted(seq_list.keys(), reverse=True):
dest_frame = first_start + (n * self.distribute_offset)
seq.sequences_all[str(seq_list[key])].frame_start = dest_frame
n -= 1
scn['default_distribute_offset'] = self.distribute_offset
scn['default_distribute_reverse'] = self.distribute_reverse
return{'FINISHED'}
def invoke(self, context, event):
scn = bpy.context.scene
self.distribute_offset = scn['default_distribute_offset']
self.distribute_reverse = scn['default_distribute_reverse']
return context.window_manager.invoke_props_dialog(self)
# ##### MENU FUNCTIONS #####
def sequencer_select_menu_func(self, context):
self.layout.operator_menu_enum('sequencerextra.select_all_by_type',
'type', text='All by Type', icon='PLUGIN')
self.layout.separator()
def sequencer_strip_menu_func(self, context):
self.layout.operator('sequencerextra.distribute',
text='Distribute', icon='PLUGIN')
self.layout.operator_menu_enum('sequencerextra.fadeinout',
'mode', text='Fade', icon='PLUGIN')
self.layout.operator_menu_enum('sequencerextra.copyproperties',
'prop', icon='PLUGIN')
self.layout.operator_menu_enum('sequencerextra.slide',
'mode', icon='PLUGIN')
self.layout.operator('sequencerextra.striprename',
text='File Name to Strip Name', icon='PLUGIN')
self.layout.operator("sequencerextra.rippledelete",
text="Ripple delete", icon='PLUGIN')
self.layout.operator("sequencerextra.editexternally",
text="Edit Externally", icon="PLUGIN")
self.layout.separator()
def sequencer_header_func(self, context):
self.layout.operator('sequencerextra.navigateup',
text='Navigate Up', icon='PLUGIN')
self.layout.separator()
def time_frame_menu_func(self, context):
self.layout.operator('timeextra.trimtimelinetoselection',
text='Trim to Selection', icon='PLUGIN')
self.layout.operator('timeextra.trimtimeline',
text='Trim to Timeline Content', icon='PLUGIN')
self.layout.separator()
# ##### REGISTRATION #####
def register():
bpy.utils.register_class(Sequencer_Extra_TrimTimeline)
bpy.utils.register_class(Sequencer_Extra_TrimTimelineToSelection)
bpy.utils.register_class(Sequencer_Extra_SlideStrip)
bpy.utils.register_class(Sequencer_Extra_FileNameToStripName)
bpy.utils.register_class(Sequencer_Extra_NavigateUp)
bpy.utils.register_class(Sequencer_Extra_Rippledelete)
bpy.utils.register_class(Sequencer_Extra_SelectAllByType)
bpy.utils.register_class(Sequencer_Extra_EditExternally)
bpy.utils.register_class(Sequencer_Extra_CopyProperties)
bpy.utils.register_class(Sequencer_Extra_FadeInOut)
bpy.utils.register_class(Sequencer_Extra_Distribute)
bpy.types.SEQUENCER_MT_select.prepend(sequencer_select_menu_func)
bpy.types.SEQUENCER_MT_strip.prepend(sequencer_strip_menu_func)
bpy.types.SEQUENCER_HT_header.append(sequencer_header_func)
bpy.types.TIME_MT_frame.prepend(time_frame_menu_func)
def unregister():
bpy.utils.unregister_class(Sequencer_Extra_TrimTimeline)
bpy.utils.unregister_class(Sequencer_Extra_TrimTimelineToSelection)
bpy.utils.unregister_class(Sequencer_Extra_SlideStrip)
bpy.utils.unregister_class(Sequencer_Extra_FileNameToStripName)
bpy.utils.unregister_class(Sequencer_Extra_NavigateUp)
bpy.utils.unregister_class(Sequencer_Extra_Rippledelete)
bpy.utils.unregister_class(Sequencer_Extra_SelectAllByType)
bpy.utils.unregister_class(Sequencer_Extra_EditExternally)
bpy.utils.unregister_class(Sequencer_Extra_CopyProperties)
bpy.utils.unregister_class(Sequencer_Extra_FadeInOut)
bpy.utils.unregister_class(Sequencer_Extra_Distribute)
bpy.types.SEQUENCER_MT_select.remove(sequencer_select_menu_func)
bpy.types.SEQUENCER_MT_strip.remove(sequencer_strip_menu_func)
bpy.types.SEQUENCER_HT_header.remove(sequencer_header_func)
bpy.types.TIME_MT_frame.remove(time_frame_menu_func)
if __name__ == '__main__':
register()

File Metadata

Mime Type
text/x-python
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
ac/ef/8c7fdc5acae8a1f566aa529b5873

Event Timeline