patch [#28571]
[blender.git] / release / scripts / startup / bl_ui / space_sequencer.py
1 # ##### BEGIN GPL LICENSE BLOCK #####
2 #
3 #  This program is free software; you can redistribute it and/or
4 #  modify it under the terms of the GNU General Public License
5 #  as published by the Free Software Foundation; either version 2
6 #  of the License, or (at your option) any later version.
7 #
8 #  This program is distributed in the hope that it will be useful,
9 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 #  GNU General Public License for more details.
12 #
13 #  You should have received a copy of the GNU General Public License
14 #  along with this program; if not, write to the Free Software Foundation,
15 #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 #
17 # ##### END GPL LICENSE BLOCK #####
18
19 # <pep8 compliant>
20 import bpy
21 from bpy.types import Header, Menu, Panel
22
23
24 def act_strip(context):
25     try:
26         return context.scene.sequence_editor.active_strip
27     except AttributeError:
28         return None
29
30
31 class SEQUENCER_HT_header(Header):
32     bl_space_type = 'SEQUENCE_EDITOR'
33
34     def draw(self, context):
35         layout = self.layout
36
37         st = context.space_data
38
39         row = layout.row(align=True)
40         row.template_header()
41
42         if context.area.show_menus:
43             row.menu("SEQUENCER_MT_view")
44
45             if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}:
46                 row.menu("SEQUENCER_MT_select")
47                 row.menu("SEQUENCER_MT_marker")
48                 row.menu("SEQUENCER_MT_add")
49                 row.menu("SEQUENCER_MT_strip")
50
51         layout.prop(st, "view_type", expand=True, text="")
52
53         if st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}:
54             layout.prop(st, "display_mode", expand=True, text="")
55
56         if st.view_type == 'SEQUENCER':
57             row = layout.row(align=True)
58             row.operator("sequencer.copy", text="", icon='COPYDOWN')
59             row.operator("sequencer.paste", text="", icon='PASTEDOWN')
60
61             layout.separator()
62             layout.operator("sequencer.refresh_all")
63             layout.template_running_jobs()
64         elif st.view_type == 'SEQUENCER_PREVIEW':
65             layout.separator()
66             layout.operator("sequencer.refresh_all")
67             layout.prop(st, "display_channel", text="Channel")
68         else:
69             layout.prop(st, "display_channel", text="Channel")
70
71             ed = context.scene.sequence_editor
72             if ed:
73                 row = layout.row(align=True)
74                 row.prop(ed, "show_overlay", text="", icon='GHOST_ENABLED')
75                 if ed.show_overlay:
76                     row.prop(ed, "overlay_frame", text="")
77                     row.prop(ed, "overlay_lock", text="", icon='LOCKED')
78
79
80 class SEQUENCER_MT_view_toggle(Menu):
81     bl_label = "View Type"
82
83     def draw(self, context):
84         layout = self.layout
85
86         layout.operator("sequencer.view_toggle").type = 'SEQUENCER'
87         layout.operator("sequencer.view_toggle").type = 'PREVIEW'
88         layout.operator("sequencer.view_toggle").type = 'SEQUENCER_PREVIEW'
89
90
91 class SEQUENCER_MT_view(Menu):
92     bl_label = "View"
93
94     def draw(self, context):
95         layout = self.layout
96
97         st = context.space_data
98
99         layout.operator("sequencer.properties", icon='MENU_PANEL')
100
101         layout.separator()
102
103         if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}:
104             layout.operator("sequencer.view_all", text="View all Sequences")
105         if st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}:
106             layout.operator_context = 'INVOKE_REGION_PREVIEW'
107             layout.operator("sequencer.view_all_preview", text="Fit preview in window")
108             layout.operator("sequencer.view_zoom_ratio", text="Show preview 1:1").ratio = 1.0
109             layout.operator_context = 'INVOKE_DEFAULT'
110
111             # # XXX, invokes in the header view
112             # layout.operator("sequencer.view_ghost_border", text='Overlay Border')
113
114         layout.operator("sequencer.view_selected")
115
116         if st.show_frames:
117             layout.operator("anim.time_toggle", text="Show Seconds")
118         else:
119             layout.operator("anim.time_toggle", text="Show Frames")
120
121         layout.prop(st, "show_frame_indicator")
122         if st.display_mode == 'IMAGE':
123             layout.prop(st, "show_safe_margin")
124         if st.display_mode == 'WAVEFORM':
125             layout.prop(st, "show_separate_color")
126
127         layout.separator()
128         layout.prop(st, "use_marker_sync")
129         layout.separator()
130
131         layout.operator("screen.area_dupli")
132         layout.operator("screen.screen_full_area")
133
134
135 class SEQUENCER_MT_select(Menu):
136     bl_label = "Select"
137
138     def draw(self, context):
139         layout = self.layout
140
141         layout.operator("sequencer.select_active_side", text="Strips to the Left").side = 'LEFT'
142         layout.operator("sequencer.select_active_side", text="Strips to the Right").side = 'RIGHT'
143         layout.separator()
144         layout.operator("sequencer.select_handles", text="Surrounding Handles").side = 'BOTH'
145         layout.operator("sequencer.select_handles", text="Left Handle").side = 'LEFT'
146         layout.operator("sequencer.select_handles", text="Right Handle").side = 'RIGHT'
147         layout.separator()
148         layout.operator_menu_enum("object.select_grouped", "type", text="Grouped")
149         layout.operator("sequencer.select_linked")
150         layout.operator("sequencer.select_all_toggle")
151         layout.operator("sequencer.select_inverse")
152
153
154 class SEQUENCER_MT_marker(Menu):
155     bl_label = "Marker"
156
157     def draw(self, context):
158         layout = self.layout
159
160         #layout.operator_context = 'EXEC_REGION_WIN'
161
162         layout.operator("marker.add", "Add Marker")
163         layout.operator("marker.duplicate", text="Duplicate Marker")
164         layout.operator("marker.delete", text="Delete Marker")
165
166         layout.separator()
167
168         layout.operator("marker.rename", text="Rename Marker")
169         layout.operator("marker.move", text="Grab/Move Marker")
170
171         #layout.operator("sequencer.sound_strip_add", text="Transform Markers") # toggle, will be rna - (sseq->flag & SEQ_MARKER_TRANS)
172
173
174 class SEQUENCER_MT_change(Menu):
175     bl_label = "Change"
176
177     def draw(self, context):
178         layout = self.layout
179
180         layout.operator_context = 'INVOKE_REGION_WIN'
181
182         layout.operator_menu_enum("sequencer.change_effect_input", "swap")
183         layout.operator_menu_enum("sequencer.change_effect_type", "type")
184         layout.operator("sequencer.change_path", text="Path/Files")
185
186
187 class SEQUENCER_MT_add(Menu):
188     bl_label = "Add"
189
190     def draw(self, context):
191         layout = self.layout
192         layout.operator_context = 'INVOKE_REGION_WIN'
193
194         if len(bpy.data.scenes) > 10:
195             layout.operator_context = 'INVOKE_DEFAULT'
196             layout.operator("sequencer.scene_strip_add", text="Scene...")
197         else:
198             layout.operator_menu_enum("sequencer.scene_strip_add", "scene", text="Scene...")
199
200         layout.operator("sequencer.movie_strip_add", text="Movie")
201         layout.operator("sequencer.image_strip_add", text="Image")
202         layout.operator("sequencer.sound_strip_add", text="Sound")
203
204         layout.menu("SEQUENCER_MT_add_effect")
205
206
207 class SEQUENCER_MT_add_effect(Menu):
208     bl_label = "Effect Strip..."
209
210     def draw(self, context):
211         layout = self.layout
212         layout.operator_context = 'INVOKE_REGION_WIN'
213
214         layout.operator("sequencer.effect_strip_add", text="Add").type = 'ADD'
215         layout.operator("sequencer.effect_strip_add", text="Subtract").type = 'SUBTRACT'
216         layout.operator("sequencer.effect_strip_add", text="Alpha Over").type = 'ALPHA_OVER'
217         layout.operator("sequencer.effect_strip_add", text="Alpha Under").type = 'ALPHA_UNDER'
218         layout.operator("sequencer.effect_strip_add", text="Cross").type = 'CROSS'
219         layout.operator("sequencer.effect_strip_add", text="Gamma Cross").type = 'GAMMA_CROSS'
220         layout.operator("sequencer.effect_strip_add", text="Multiply").type = 'MULTIPLY'
221         layout.operator("sequencer.effect_strip_add", text="Over Drop").type = 'OVER_DROP'
222         layout.operator("sequencer.effect_strip_add", text="Plugin").type = 'PLUGIN'
223         layout.operator("sequencer.effect_strip_add", text="Wipe").type = 'WIPE'
224         layout.operator("sequencer.effect_strip_add", text="Glow").type = 'GLOW'
225         layout.operator("sequencer.effect_strip_add", text="Transform").type = 'TRANSFORM'
226         layout.operator("sequencer.effect_strip_add", text="Color").type = 'COLOR'
227         layout.operator("sequencer.effect_strip_add", text="Speed Control").type = 'SPEED'
228         layout.operator("sequencer.effect_strip_add", text="Multicam Selector").type = 'MULTICAM'
229         layout.operator("sequencer.effect_strip_add", text="Adjustment Layer").type = 'ADJUSTMENT'
230
231
232 class SEQUENCER_MT_strip(Menu):
233     bl_label = "Strip"
234
235     def draw(self, context):
236         layout = self.layout
237
238         layout.operator_context = 'INVOKE_REGION_WIN'
239
240         layout.operator("transform.transform", text="Grab/Move").mode = 'TRANSLATION'
241         layout.operator("transform.transform", text="Grab/Extend from frame").mode = 'TIME_EXTEND'
242         #  uiItemO(layout, NULL, 0, "sequencer.strip_snap"); // TODO - add this operator
243         layout.separator()
244
245         layout.operator("sequencer.cut", text="Cut (hard) at frame").type = 'HARD'
246         layout.operator("sequencer.cut", text="Cut (soft) at frame").type = 'SOFT'
247         layout.operator("sequencer.images_separate")
248         layout.operator("sequencer.offset_clear")
249         layout.operator("sequencer.deinterlace_selected_movies")
250         layout.operator("sequencer.rebuild_proxy")
251         layout.separator()
252
253         layout.operator("sequencer.duplicate")
254         layout.operator("sequencer.delete")
255
256         strip = act_strip(context)
257
258         if strip:
259             stype = strip.type
260
261             # XXX note strip.type is never equal to 'EFFECT', look at seq_type_items within rna_sequencer.c
262             if stype == 'EFFECT':
263                 pass
264                 # layout.separator()
265                 # layout.operator("sequencer.effect_change")
266                 # layout.operator("sequencer.effect_reassign_inputs")
267             elif stype == 'IMAGE':
268                 layout.separator()
269                 # layout.operator("sequencer.image_change")
270                 layout.operator("sequencer.rendersize")
271             elif stype == 'SCENE':
272                 pass
273                 # layout.separator()
274                 # layout.operator("sequencer.scene_change", text="Change Scene")
275             elif stype == 'MOVIE':
276                 layout.separator()
277                 # layout.operator("sequencer.movie_change")
278                 layout.operator("sequencer.rendersize")
279
280         layout.separator()
281
282         layout.operator("sequencer.meta_make")
283         layout.operator("sequencer.meta_separate")
284
285         #if (ed && (ed->metastack.first || (ed->act_seq && ed->act_seq->type == SEQ_META))) {
286         #       uiItemS(layout);
287         #       uiItemO(layout, NULL, 0, "sequencer.meta_toggle");
288         #}
289
290         layout.separator()
291         layout.operator("sequencer.reload")
292         layout.operator("sequencer.reassign_inputs")
293         layout.operator("sequencer.swap_inputs")
294         layout.separator()
295         layout.operator("sequencer.lock")
296         layout.operator("sequencer.unlock")
297         layout.operator("sequencer.mute")
298         layout.operator("sequencer.unmute")
299
300         layout.operator("sequencer.mute", text="Mute Deselected Strips").unselected = True
301
302         layout.operator("sequencer.snap")
303
304         layout.operator_menu_enum("sequencer.swap", "side")
305
306         layout.separator()
307
308         layout.operator("sequencer.swap_data")
309         layout.menu("SEQUENCER_MT_change")
310
311
312 class SequencerButtonsPanel():
313     bl_space_type = 'SEQUENCE_EDITOR'
314     bl_region_type = 'UI'
315
316     @staticmethod
317     def has_sequencer(context):
318         return (context.space_data.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'})
319
320     @classmethod
321     def poll(cls, context):
322         return cls.has_sequencer(context) and (act_strip(context) is not None)
323
324
325 class SequencerButtonsPanel_Output():
326     bl_space_type = 'SEQUENCE_EDITOR'
327     bl_region_type = 'UI'
328
329     @staticmethod
330     def has_preview(context):
331         return (context.space_data.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'})
332
333     @classmethod
334     def poll(cls, context):
335         return cls.has_preview(context)
336
337
338 class SEQUENCER_PT_edit(SequencerButtonsPanel, Panel):
339     bl_label = "Edit Strip"
340
341     def draw(self, context):
342         layout = self.layout
343         scene = context.scene
344         frame_current = scene.frame_current
345         strip = act_strip(context)
346
347         split = layout.split(percentage=0.3)
348         split.label(text="Name:")
349         split.prop(strip, "name", text="")
350
351         split = layout.split(percentage=0.3)
352         split.label(text="Type:")
353         split.prop(strip, "type", text="")
354
355         split = layout.split(percentage=0.3)
356         split.label(text="Blend:")
357         split.prop(strip, "blend_type", text="")
358
359         row = layout.row(align=True)
360         sub = row.row()
361         sub.active = (not strip.mute)
362         sub.prop(strip, "blend_alpha", text="Opacity", slider=True)
363         row.prop(strip, "mute", toggle=True, icon='RESTRICT_VIEW_ON' if strip.mute else 'RESTRICT_VIEW_OFF', text="")
364         row.prop(strip, "lock", toggle=True, icon='LOCKED' if strip.lock else 'UNLOCKED', text="")
365
366         col = layout.column()
367         sub = col.column()
368         sub.enabled = not strip.lock
369         sub.prop(strip, "channel")
370         sub.prop(strip, "frame_start")
371         sub.prop(strip, "frame_final_duration")
372
373         col = layout.column(align=True)
374         row = col.row()
375         row.label(text="Final Length" + ": %s" % bpy.utils.smpte_from_frame(strip.frame_final_duration))
376         row = col.row()
377         row.active = (frame_current >= strip.frame_start and frame_current <= strip.frame_start + strip.frame_duration)
378         row.label(text="Playhead" + ": %d" % (frame_current - strip.frame_start))
379
380         col.label(text="Frame Offset" + " %d:%d" % (strip.frame_offset_start, strip.frame_offset_end))
381         col.label(text="Frame Still" + " %d:%d" % (strip.frame_still_start, strip.frame_still_end))
382
383         elem = False
384
385         if strip.type == 'IMAGE':
386             elem = strip.getStripElem(frame_current)
387         elif strip.type == 'MOVIE':
388             elem = strip.elements[0]
389
390         if elem and elem.orig_width > 0 and elem.orig_height > 0:
391             col.label(text="Orig Dim" + ": %dx%d" % (elem.orig_width, elem.orig_height))
392         else:
393             col.label(text="Orig Dim: None")
394
395
396 class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
397     bl_label = "Effect Strip"
398
399     @classmethod
400     def poll(cls, context):
401         if not cls.has_sequencer(context):
402             return False
403
404         strip = act_strip(context)
405         if not strip:
406             return False
407
408         return strip.type in {'ADD', 'SUBTRACT', 'ALPHA_OVER', 'ALPHA_UNDER',
409                               'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP',
410                               'PLUGIN',
411                               'WIPE', 'GLOW', 'TRANSFORM', 'SPEED',
412                               'MULTICAM', 'ADJUSTMENT'}
413
414     def draw(self, context):
415         layout = self.layout
416
417         strip = act_strip(context)
418         if strip.input_count > 0:
419             col = layout.column()
420             col.prop(strip, "input_1")
421             if strip.input_count > 1:
422                 col.prop(strip, "input_2")
423             if strip.input_count > 2:
424                 col.prop(strip, "input_3")
425
426         if strip.type == 'COLOR':
427             layout.prop(strip, "color")
428
429         elif strip.type == 'WIPE':
430
431             col = layout.column()
432             col.prop(strip, "transition_type")
433             col.label(text="Direction:")
434             col.row().prop(strip, "direction", expand=True)
435
436             col = layout.column()
437             col.prop(strip, "blur_width", slider=True)
438             if strip.transition_type in {'SINGLE', 'DOUBLE'}:
439                 col.prop(strip, "angle")
440
441         elif strip.type == 'GLOW':
442             flow = layout.column_flow()
443             flow.prop(strip, "threshold", slider=True)
444             flow.prop(strip, "clamp", slider=True)
445             flow.prop(strip, "boost_factor")
446             flow.prop(strip, "blur_radius")
447
448             row = layout.row()
449             row.prop(strip, "quality", slider=True)
450             row.prop(strip, "use_only_boost")
451
452         elif strip.type == 'SPEED':
453             layout.prop(strip, "use_default_fade", "Stretch to input strip length")
454             if not strip.use_default_fade:
455                 layout.prop(strip, "use_as_speed")
456                 if strip.use_as_speed:
457                     layout.prop(strip, "speed_factor")
458                 else:
459                     layout.prop(strip, "speed_factor", text="Frame number")
460                     layout.prop(strip, "scale_to_length")
461
462             #doesn't work currently
463             #layout.prop(strip, "use_frame_blend")
464
465         elif strip.type == 'TRANSFORM':
466             self.draw_panel_transform(strip)
467
468         elif strip.type == "MULTICAM":
469             layout.prop(strip, "multicam_source")
470
471             row = layout.row(align=True)
472             sub = row.row()
473             sub.scale_x = 2.0
474
475             sub.operator("screen.animation_play", text="", icon='PAUSE' if context.screen.is_animation_playing else 'PLAY')
476
477             row.label("Cut To")
478             for i in range(1, strip.channel):
479                 row.operator("sequencer.cut_multicam", text=str(i)).camera = i
480
481         col = layout.column(align=True)
482         if strip.type == 'SPEED':
483             col.prop(strip, "multiply_speed")
484         elif strip.type in {'CROSS', 'GAMMA_CROSS', 'PLUGIN', 'WIPE'}:
485                 col.prop(strip, "use_default_fade", "Default fade")
486                 if not strip.use_default_fade:
487                     col.prop(strip, "effect_fader", text="Effect fader")
488
489         layout.prop(strip, "use_translation", text="Image Offset:")
490         if strip.use_translation:
491             col = layout.column(align=True)
492             col.prop(strip.transform, "offset_x", text="X")
493             col.prop(strip.transform, "offset_y", text="Y")
494
495         layout.prop(strip, "use_crop", text="Image Crop:")
496         if strip.use_crop:
497             col = layout.column(align=True)
498             col.prop(strip.crop, "max_y")
499             col.prop(strip.crop, "min_x")
500             col.prop(strip.crop, "min_y")
501             col.prop(strip.crop, "max_x")
502
503     def draw_panel_transform(self, strip):
504         layout = self.layout
505         col = layout.column()
506
507         col.prop(strip, "interpolation")
508         col.prop(strip, "translation_unit")
509         col = layout.column(align=True)
510         col.label(text="Position:")
511         col.prop(strip, "translate_start_x", text="X")
512         col.prop(strip, "translate_start_y", text="Y")
513
514         layout.separator()
515
516         col = layout.column(align=True)
517         col.prop(strip, "use_uniform_scale")
518         if (strip.use_uniform_scale):
519             col = layout.column(align=True)
520             col.prop(strip, "scale_start_x", text="Scale")
521         else:
522             col = layout.column(align=True)
523             col.label(text="Scale:")
524             col.prop(strip, "scale_start_x", text="X")
525             col.prop(strip, "scale_start_y", text="Y")
526
527         layout.separator()
528
529         col = layout.column(align=True)
530         col.label(text="Rotation:")
531         col.prop(strip, "rotation_start", text="Rotation")
532
533
534 class SEQUENCER_PT_input(SequencerButtonsPanel, Panel):
535     bl_label = "Strip Input"
536
537     @classmethod
538     def poll(cls, context):
539         if not cls.has_sequencer(context):
540             return False
541
542         strip = act_strip(context)
543         if not strip:
544             return False
545
546         return strip.type in {'MOVIE', 'IMAGE', 'SCENE', 'META',
547                               'ADD', 'SUBTRACT', 'ALPHA_OVER', 'ALPHA_UNDER',
548                               'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP',
549                               'PLUGIN',
550                               'WIPE', 'GLOW', 'TRANSFORM', 'COLOR',
551                               'MULTICAM', 'SPEED', 'ADJUSTMENT'}
552
553     def draw(self, context):
554         layout = self.layout
555
556         strip = act_strip(context)
557
558         seq_type = strip.type
559
560         # draw a filename if we have one
561         if seq_type == 'IMAGE':
562             split = layout.split(percentage=0.2)
563             col = split.column()
564             col.label(text="Path:")
565             col = split.column()
566             col.prop(strip, "directory", text="")
567
568             # Current element for the filename
569
570             elem = strip.getStripElem(context.scene.frame_current)
571             if elem:
572                 split = layout.split(percentage=0.2)
573                 col = split.column()
574                 col.label(text="File:")
575                 col = split.column()
576                 col.prop(elem, "filename", text="")  # strip.elements[0] could be a fallback
577
578             # also accessible from the menu
579             layout.operator("sequencer.change_path")
580
581         elif seq_type == 'MOVIE':
582             split = layout.split(percentage=0.2)
583             col = split.column()
584             col.label(text="Path:")
585             col = split.column()
586             col.prop(strip, "filepath", text="")
587             col.prop(strip, "mpeg_preseek", text="MPEG Preseek")
588             col.prop(strip, "stream_index", text="Stream Index")
589
590         # TODO, sound???
591         # end drawing filename
592
593         layout.prop(strip, "use_translation", text="Image Offset:")
594         if strip.use_translation:
595             col = layout.column(align=True)
596             col.prop(strip.transform, "offset_x", text="X")
597             col.prop(strip.transform, "offset_y", text="Y")
598
599         layout.prop(strip, "use_crop", text="Image Crop:")
600         if strip.use_crop:
601             col = layout.column(align=True)
602             col.prop(strip.crop, "max_y")
603             col.prop(strip.crop, "min_x")
604             col.prop(strip.crop, "min_y")
605             col.prop(strip.crop, "max_x")
606
607         if not isinstance(strip, bpy.types.EffectSequence):
608             col = layout.column(align=True)
609             col.label(text="Trim Duration (hard):")
610             col.prop(strip, "animation_offset_start", text="Start")
611             col.prop(strip, "animation_offset_end", text="End")
612
613         col = layout.column(align=True)
614         col.label(text="Trim Duration (soft):")
615         col.prop(strip, "frame_offset_start", text="Start")
616         col.prop(strip, "frame_offset_end", text="End")
617
618
619 class SEQUENCER_PT_sound(SequencerButtonsPanel, Panel):
620     bl_label = "Sound"
621
622     @classmethod
623     def poll(cls, context):
624         if not cls.has_sequencer(context):
625             return False
626
627         strip = act_strip(context)
628         if not strip:
629             return False
630
631         return (strip.type == 'SOUND')
632
633     def draw(self, context):
634         layout = self.layout
635
636         strip = act_strip(context)
637
638         layout.template_ID(strip, "sound", open="sound.open")
639
640         layout.separator()
641         layout.prop(strip, "filepath", text="")
642
643         row = layout.row()
644         if strip.sound.packed_file:
645             row.operator("sound.unpack", icon='PACKAGE', text="Unpack")
646         else:
647             row.operator("sound.pack", icon='UGLYPACKAGE', text="Pack")
648
649         row.prop(strip.sound, "use_memory_cache")
650
651         layout.prop(strip, "waveform")
652         layout.prop(strip, "volume")
653         layout.prop(strip, "pitch")
654         layout.prop(strip, "pan")
655
656         col = layout.column(align=True)
657         col.label(text="Trim Duration:")
658         col.prop(strip, "animation_offset_start", text="Start")
659         col.prop(strip, "animation_offset_end", text="End")
660
661
662 class SEQUENCER_PT_scene(SequencerButtonsPanel, Panel):
663     bl_label = "Scene"
664
665     @classmethod
666     def poll(cls, context):
667         if not cls.has_sequencer(context):
668             return False
669
670         strip = act_strip(context)
671         if not strip:
672             return False
673
674         return (strip.type == 'SCENE')
675
676     def draw(self, context):
677         layout = self.layout
678
679         strip = act_strip(context)
680
681         layout.template_ID(strip, "scene")
682
683         scene = strip.scene
684         if scene:
685             layout.prop(scene.render, "use_sequencer")
686
687         layout.label(text="Camera Override")
688         layout.template_ID(strip, "scene_camera")
689
690         if scene:
691             sta = scene.frame_start
692             end = scene.frame_end
693             layout.label(text="Original frame range" + ": %d-%d (%d)" % (sta, end, end - sta + 1))
694
695
696 class SEQUENCER_PT_filter(SequencerButtonsPanel, Panel):
697     bl_label = "Filter"
698
699     @classmethod
700     def poll(cls, context):
701         if not cls.has_sequencer(context):
702             return False
703
704         strip = act_strip(context)
705         if not strip:
706             return False
707
708         return strip.type in {'MOVIE', 'IMAGE', 'SCENE', 'META',
709                               'ADD', 'SUBTRACT', 'ALPHA_OVER', 'ALPHA_UNDER',
710                               'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP',
711                               'PLUGIN',
712                               'WIPE', 'GLOW', 'TRANSFORM', 'COLOR',
713                               'MULTICAM', 'SPEED', 'ADJUSTMENT'}
714
715     def draw(self, context):
716         layout = self.layout
717
718         strip = act_strip(context)
719
720         col = layout.column()
721         col.label(text="Video:")
722         col.prop(strip, "strobe")
723
724         row = layout.row()
725         row.label(text="Flip:")
726         row.prop(strip, "use_flip_x", text="X")
727         row.prop(strip, "use_flip_y", text="Y")
728
729         col = layout.column()
730         col.prop(strip, "use_reverse_frames", text="Backwards")
731         col.prop(strip, "use_deinterlace")
732
733         col = layout.column()
734         col.label(text="Colors:")
735         col.prop(strip, "color_saturation", text="Saturation")
736         col.prop(strip, "color_multiply", text="Multiply")
737         col.prop(strip, "use_premultiply")
738         col.prop(strip, "use_float")
739
740         layout.prop(strip, "use_color_balance")
741         if strip.use_color_balance and strip.color_balance:  # TODO - need to add this somehow
742             row = layout.row()
743             row.active = strip.use_color_balance
744             col = row.column()
745             col.template_color_wheel(strip.color_balance, "lift", value_slider=False, cubic=True)
746             col.row().prop(strip.color_balance, "lift")
747             col.prop(strip.color_balance, "invert_lift", text="Inverse")
748             col = row.column()
749             col.template_color_wheel(strip.color_balance, "gamma", value_slider=False, lock_luminosity=True, cubic=True)
750             col.row().prop(strip.color_balance, "gamma")
751             col.prop(strip.color_balance, "invert_gamma", text="Inverse")
752             col = row.column()
753             col.template_color_wheel(strip.color_balance, "gain", value_slider=False, lock_luminosity=True, cubic=True)
754             col.row().prop(strip.color_balance, "gain")
755             col.prop(strip.color_balance, "invert_gain", text="Inverse")
756
757
758 class SEQUENCER_PT_proxy(SequencerButtonsPanel, Panel):
759     bl_label = "Proxy / Timecode"
760
761     @classmethod
762     def poll(cls, context):
763         if not cls.has_sequencer(context):
764             return False
765
766         strip = act_strip(context)
767         if not strip:
768             return False
769
770         return strip.type in {'MOVIE', 'IMAGE', 'SCENE', 'META', 'MULTICAM'}
771
772     def draw_header(self, context):
773         strip = act_strip(context)
774
775         self.layout.prop(strip, "use_proxy", text="")
776
777     def draw(self, context):
778         layout = self.layout
779
780         strip = act_strip(context)
781
782         flow = layout.column_flow()
783         flow.prop(strip, "use_proxy_custom_directory")
784         flow.prop(strip, "use_proxy_custom_file")
785         if strip.proxy:
786             if strip.use_proxy_custom_directory and not strip.use_proxy_custom_file:
787                 flow.prop(strip.proxy, "directory")
788             if strip.use_proxy_custom_file:
789                 flow.prop(strip.proxy, "filepath")
790
791             row = layout.row()
792             row.prop(strip.proxy, "build_25")
793             row.prop(strip.proxy, "build_50")
794             row.prop(strip.proxy, "build_75")
795             row.prop(strip.proxy, "build_100")
796
797             col = layout.column()
798             col.label(text="Build JPEG quality")
799             col.prop(strip.proxy, "quality")
800
801             if strip.type == "MOVIE":
802                 col = layout.column()
803                 col.label(text="Use timecode index:")
804
805                 col.prop(strip.proxy, "timecode")
806
807
808 class SEQUENCER_PT_preview(SequencerButtonsPanel_Output, Panel):
809     bl_label = "Scene Preview/Render"
810     bl_space_type = 'SEQUENCE_EDITOR'
811     bl_region_type = 'UI'
812
813     def draw(self, context):
814         layout = self.layout
815         render = context.scene.render
816
817         col = layout.column()
818         col.active = False  # Currently only opengl preview works!
819         col.prop(render, "use_sequencer_gl_preview", text="Open GL Preview")
820         col = layout.column()
821         #col.active = render.use_sequencer_gl_preview
822         col.prop(render, "sequencer_gl_preview", text="")
823
824         '''
825         col = layout.column()
826         col.prop(render, "use_sequencer_gl_render", text="Open GL Render")
827         col = layout.column()
828         col.active = render.use_sequencer_gl_render
829         col.prop(render, "sequencer_gl_render", text="")
830         '''
831
832
833 class SEQUENCER_PT_view(SequencerButtonsPanel_Output, Panel):
834     bl_label = "View Settings"
835
836     def draw(self, context):
837         layout = self.layout
838
839         st = context.space_data
840
841         col = layout.column()
842         if st.display_mode == 'IMAGE':
843             col.prop(st, "draw_overexposed")  # text="Zebra"
844             col.prop(st, "show_safe_margin")
845         if st.display_mode == 'WAVEFORM':
846             col.prop(st, "show_separate_color")
847         col.prop(st, "proxy_render_size")
848
849 if __name__ == "__main__":  # only for live edit.
850     bpy.utils.register_module(__name__)