-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathzoom.py
263 lines (217 loc) · 10.2 KB
/
zoom.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
import bpy
from . import timeline
from . import vseqf
def zoom_custom(begin, end, bottom=None, top=None, preroll=True):
"""Zooms to an area on the sequencer timeline by adding a temporary strip, zooming to it, then deleting that strip.
Note that this function will retain selected and active sequences.
Arguments:
begin: The starting frame of the zoom area
end: The ending frame of the zoom area
bottom: The lowest visible channel
top: The topmost visible channel
preroll: If true, add a buffer before the beginning"""
del bottom #Add in someday...
del top #Add in someday...
scene = bpy.context.scene
selected = []
#Find sequence editor, or create if not found
try:
sequences = bpy.context.sequences
except:
scene.sequence_editor_create()
sequences = bpy.context.sequences
#Save selected sequences and active strip because they will be overwritten
for sequence in sequences:
if sequence.select:
selected.append(sequence)
sequence.select = False
active = timeline.current_active(bpy.context)
begin = int(begin)
end = int(end)
#Determine preroll for the zoom
zoomlength = end - begin
if zoomlength > 60 and preroll:
preroll = int(round((zoomlength-60) / 10))
else:
preroll = 0
#Create a temporary sequence, zoom in on it, then delete it
zoom_clip = scene.sequence_editor.sequences.new_effect(name='----vseqf-temp-zoom----', type='ADJUSTMENT', channel=1, frame_start=begin - preroll, frame_end=end)
scene.sequence_editor.active_strip = zoom_clip
for region in bpy.context.area.regions:
if region.type == 'WINDOW':
with bpy.context.temp_override(region=region, window=bpy.context.window, screen=bpy.context.screen, area=bpy.context.area, scene=bpy.context.scene):
bpy.ops.sequencer.view_selected()
bpy.ops.sequencer.delete()
#Reset selected sequences and active strip
for sequence in selected:
sequence.select = True
if active:
bpy.context.scene.sequence_editor.active_strip = active
def zoom_cursor(self=None, context=None):
"""Zooms near the cursor based on the 'zoom_size' vseqf variable"""
del self
del context
cursor = bpy.context.scene.frame_current
zoom_custom(cursor, (cursor + bpy.context.scene.vseqf.zoom_size))
class VSEQFQuickZoomsMenu(bpy.types.Menu):
"""Pop-up menu for sequencer zoom shortcuts"""
bl_idname = "VSEQF_MT_quickzooms_menu"
bl_label = "Quick Zooms"
def draw(self, context):
scene = context.scene
layout = self.layout
prop = layout.operator('vseqf.quickzooms', text='Zoom All Sequences')
prop.area = 'all'
prop.tooltip = 'Zoom the timeline to all sequences'
prop = layout.operator('vseqf.quickzooms', text='Zoom To Timeline')
prop.area = 'timeline'
prop.tooltip = 'Zoom the timeline to the current playback range'
selected_sequences = timeline.current_selected(bpy.context)
if len(selected_sequences) > 0:
#Only show if a sequence is selected
prop = layout.operator('vseqf.quickzooms', text='Zoom Selected')
prop.area = 'selected'
prop.tooltip = 'Zoom the timeline to the selected sequences'
prop = layout.operator('vseqf.quickzooms', text='Zoom Cursor')
prop.area = 'cursor'
prop.tooltip = 'Zoom the timeline to '+str(context.scene.vseqf.zoom_size)+' frames around the cursor'
layout.prop(scene.vseqf, 'zoom_size', text="Size")
layout.operator('vseqf.quickzoom_add', text='Save Current Zoom')
if len(scene.vseqf.zoom_presets) > 0:
layout.menu('VSEQF_MT_quickzoom_preset_menu')
layout.separator()
prop = layout.operator('vseqf.quickzooms', text='Zoom 2 Seconds')
prop.area = '2'
prop.tooltip = 'Zoom the timeline to 2 seconds around the play cursor'
prop = layout.operator('vseqf.quickzooms', text='Zoom 10 Seconds')
prop.area = '10'
prop.tooltip = 'Zoom the timeline to 10 seconds around the play cursor'
prop = layout.operator('vseqf.quickzooms', text='Zoom 30 Seconds')
prop.area = '30'
prop.tooltip = 'Zoom the timeline to 30 seconds around the play cursor'
prop = layout.operator('vseqf.quickzooms', text='Zoom 1 Minute')
prop.area = '60'
prop.tooltip = 'Zoom the timeline to one minute around the play cursor'
prop = layout.operator('vseqf.quickzooms', text='Zoom 2 Minutes')
prop.area = '120'
prop.tooltip = 'Zoom the timeline to 2 minutes around the play cursor'
prop = layout.operator('vseqf.quickzooms', text='Zoom 5 Minutes')
prop.area = '300'
prop.tooltip = 'Zoom the timeline to 5 minutes around the play cursor'
prop = layout.operator('vseqf.quickzooms', text='Zoom 10 Minutes')
prop.area = '600'
prop.tooltip = 'Zoom the timeline to 10 minutes around the play cursor'
class VSEQFQuickZoomPresetMenu(bpy.types.Menu):
"""Menu for saved zoom presets"""
bl_idname = "VSEQF_MT_quickzoom_preset_menu"
bl_label = "Zoom Presets"
def draw(self, context):
del context
scene = bpy.context.scene
layout = self.layout
split = layout.split()
column = split.column()
for zoom in scene.vseqf.zoom_presets:
column.operator('vseqf.quickzoom_preset', text=zoom.name).name = zoom.name
column.separator()
column.operator('vseqf.quickzoom_clear', text='Clear All')
column = split.column()
for zoom in scene.vseqf.zoom_presets:
column.operator('vseqf.quickzoom_remove', text='X').name = zoom.name
class VSEQFQuickZoomPreset(bpy.types.Operator):
"""Zoom to a preset"""
bl_idname = 'vseqf.quickzoom_preset'
bl_label = "Zoom To QuickZoom Preset"
name: bpy.props.StringProperty()
def execute(self, context):
scene = context.scene
for zoom in scene.vseqf.zoom_presets:
if zoom.name == self.name:
zoom_custom(zoom.left, zoom.right, bottom=zoom.bottom, top=zoom.top, preroll=False)
break
return {'FINISHED'}
class VSEQFClearZooms(bpy.types.Operator):
"""Clears all zoom presets"""
bl_idname = 'vseqf.quickzoom_clear'
bl_label = 'Clear All Presets'
def execute(self, context):
scene = context.scene
bpy.ops.ed.undo_push()
for index, zoom_preset in reversed(list(enumerate(scene.vseqf.zoom_presets))):
scene.vseqf.zoom_presets.remove(index)
return{'FINISHED'}
class VSEQFRemoveZoom(bpy.types.Operator):
"""Removes a zoom preset from the preset list"""
bl_idname = 'vseqf.quickzoom_remove'
bl_label = 'Remove Zoom Preset'
name: bpy.props.StringProperty()
def execute(self, context):
scene = context.scene
for index, zoom_preset in reversed(list(enumerate(scene.vseqf.zoom_presets))):
if zoom_preset.name == self.name:
bpy.ops.ed.undo_push()
scene.vseqf.zoom_presets.remove(index)
return{'FINISHED'}
class VSEQFAddZoom(bpy.types.Operator):
"""Stores the current vse zoom and position"""
bl_idname = 'vseqf.quickzoom_add'
bl_label = "Add Zoom Preset"
mode: bpy.props.StringProperty()
def execute(self, context):
left, right, bottom, top = timeline.get_vse_position(context)
scene = context.scene
#name = "Frames "+str(int(round(left)))+'-'+str(int(round(right)))+', Channels '+str(int(round(bottom)))+'-'+str(int(round(top)))
name = "Frames "+str(int(round(left)))+'-'+str(int(round(right)))
bpy.ops.ed.undo_push()
for index, zoom_preset in enumerate(scene.vseqf.zoom_presets):
if zoom_preset.name == name:
scene.vseqf.zoom_presets.move(index, len(scene.vseqf.zoom_presets) - 1)
return{'FINISHED'}
preset = scene.vseqf.zoom_presets.add()
preset.name = name
preset.left = left
preset.right = right
preset.bottom = bottom
preset.top = top
return{'FINISHED'}
class VSEQFQuickZooms(bpy.types.Operator):
"""Wrapper operator for zooming the sequencer in different ways
Argument:
area: String, determines the zoom method, can be set to:
all: calls bpy.ops.sequencer.view_all()
selected: calls bpy.ops.sequencer.view_selected()
cursor: calls the zoom_cursor() function
numerical value: zooms to the number of seconds given in the value"""
bl_idname = 'vseqf.quickzooms'
bl_label = 'VSEQF Quick Zooms'
bl_description = 'Changes zoom level of the sequencer timeline'
#Should be set to 'all', 'selected', cursor', or a positive number of seconds
area: bpy.props.StringProperty()
tooltip: bpy.props.StringProperty("Zoom the timeline")
@classmethod
def description(cls, context, properties):
return properties.tooltip
def execute(self, context):
#return bpy.ops.view2d.smoothview("INVOKE_DEFAULT", xmin=0, xmax=10, ymin=0, ymax=10, wait_for_input=False)
if self.area.isdigit():
#Zoom value is a number of seconds
scene = context.scene
cursor = scene.frame_current
zoom_custom(cursor, (cursor + (vseqf.get_fps(scene) * int(self.area))))
elif self.area == 'timeline':
scene = context.scene
zoom_custom(scene.frame_start, scene.frame_end)
elif self.area == 'all':
bpy.ops.sequencer.view_all()
elif self.area == 'selected':
bpy.ops.sequencer.view_selected()
elif self.area == 'cursor':
zoom_cursor()
return{'FINISHED'}
class VSEQFZoomPreset(bpy.types.PropertyGroup):
"""Property group to store a sequencer view position"""
name: bpy.props.StringProperty(name="Preset Name", default="")
left: bpy.props.FloatProperty(name="Leftmost Visible Frame", default=0.0)
right: bpy.props.FloatProperty(name="Rightmost Visible Frame", default=300.0)
bottom: bpy.props.FloatProperty(name="Bottom Visible Channel", default=0.0)
top: bpy.props.FloatProperty(name="Top Visible Channel", default=5.0)