978c326c83ad53162b716fe24f57df9f83ecdbb8
[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 from bpy.app.translations import pgettext_iface as iface_
23
24
25 def act_strip(context):
26     try:
27         return context.scene.sequence_editor.active_strip
28     except AttributeError:
29         return None
30
31
32 def draw_color_balance(layout, color_balance):
33     col = layout.column()
34     col.label(text="Lift:")
35     col.template_color_picker(color_balance, "lift", value_slider=True, cubic=True)
36     row = col.row()
37     row.prop(color_balance, "lift", text="")
38     row.prop(color_balance, "invert_lift", text="Inverse")
39
40     col = layout.column()
41     col.label(text="Gamma:")
42     col.template_color_picker(color_balance, "gamma", value_slider=True, lock_luminosity=True, cubic=True)
43     row = col.row()
44     row.prop(color_balance, "gamma", text="")
45     row.prop(color_balance, "invert_gamma", text="Inverse")
46
47     col = layout.column()
48     col.label(text="Gain:")
49     col.template_color_picker(color_balance, "gain", value_slider=True, lock_luminosity=True, cubic=True)
50     row = col.row()
51     row.prop(color_balance, "gain", text="")
52     row.prop(color_balance, "invert_gain", text="Inverse")
53
54
55 class SEQUENCER_HT_header(Header):
56     bl_space_type = 'SEQUENCE_EDITOR'
57
58     def draw(self, context):
59         layout = self.layout
60
61         st = context.space_data
62
63         row = layout.row(align=True)
64         row.template_header()
65
66         SEQUENCER_MT_editor_menus.draw_collapsible(context, layout)
67
68         layout.prop(st, "view_type", expand=True, text="")
69
70         if st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}:
71             layout.prop(st, "display_mode", expand=True, text="")
72
73         if st.view_type == 'SEQUENCER':
74             row = layout.row(align=True)
75             row.operator("sequencer.copy", text="", icon='COPYDOWN')
76             row.operator("sequencer.paste", text="", icon='PASTEDOWN')
77
78             layout.separator()
79             layout.operator("sequencer.refresh_all")
80         else:
81             if st.view_type == 'SEQUENCER_PREVIEW':
82                 layout.separator()
83                 layout.operator("sequencer.refresh_all")
84
85             layout.prop(st, "preview_channels", expand=True, text="")
86             layout.prop(st, "display_channel", text="Channel")
87
88             ed = context.scene.sequence_editor
89             if ed:
90                 row = layout.row(align=True)
91                 row.prop(ed, "show_overlay", text="", icon='GHOST_ENABLED')
92                 if ed.show_overlay:
93                     row.prop(ed, "overlay_frame", text="")
94                     row.prop(ed, "use_overlay_lock", text="", icon='LOCKED')
95
96                     row = layout.row()
97                     row.prop(st, "overlay_type", text="")
98
99         row = layout.row(align=True)
100         row.operator("render.opengl", text="", icon='RENDER_STILL').sequencer = True
101         props = row.operator("render.opengl", text="", icon='RENDER_ANIMATION')
102         props.animation = True
103         props.sequencer = True
104
105         layout.template_running_jobs()
106
107
108 class SEQUENCER_MT_editor_menus(Menu):
109     bl_idname = "SEQUENCER_MT_editor_menus"
110     bl_label = ""
111
112     def draw(self, context):
113         self.draw_menus(self.layout, context)
114
115     @staticmethod
116     def draw_menus(layout, context):
117         st = context.space_data
118
119         layout.menu("SEQUENCER_MT_view")
120
121         if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}:
122             layout.menu("SEQUENCER_MT_select")
123             layout.menu("SEQUENCER_MT_marker")
124             layout.menu("SEQUENCER_MT_add")
125             layout.menu("SEQUENCER_MT_strip")
126
127
128 class SEQUENCER_MT_view_toggle(Menu):
129     bl_label = "View Type"
130
131     def draw(self, context):
132         layout = self.layout
133
134         layout.operator("sequencer.view_toggle").type = 'SEQUENCER'
135         layout.operator("sequencer.view_toggle").type = 'PREVIEW'
136         layout.operator("sequencer.view_toggle").type = 'SEQUENCER_PREVIEW'
137
138
139 class SEQUENCER_MT_view(Menu):
140     bl_label = "View"
141
142     def draw(self, context):
143         layout = self.layout
144
145         st = context.space_data
146
147         if st.view_type in {'PREVIEW'}:
148             # Specifying the REGION_PREVIEW context is needed in preview-only
149             # mode, else the lookup for the shortcut will fail in
150             # wm_keymap_item_find_props() (see #32595).
151             layout.operator_context = 'INVOKE_REGION_PREVIEW'
152         layout.operator("sequencer.properties", icon='MENU_PANEL')
153         layout.operator_context = 'INVOKE_DEFAULT'
154
155         layout.separator()
156
157         if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}:
158             layout.operator("sequencer.view_all", text="View all Sequences")
159             layout.operator("sequencer.view_selected")
160         if st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}:
161             layout.operator_context = 'INVOKE_REGION_PREVIEW'
162             layout.operator("sequencer.view_all_preview", text="Fit preview in window")
163             
164             layout.separator()
165             
166             ratios = ((1, 8), (1, 4), (1, 2), (1, 1), (2, 1), (4, 1), (8, 1))
167
168             for a, b in ratios:
169                 layout.operator("sequencer.view_zoom_ratio", text=iface_("Zoom %d:%d") % (a, b), translate=False).ratio = a / b
170             
171             layout.separator()
172
173             layout.operator_context = 'INVOKE_DEFAULT'
174
175             # # XXX, invokes in the header view
176             # layout.operator("sequencer.view_ghost_border", text="Overlay Border")
177
178         if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}:
179             layout.prop(st, "show_seconds")
180             layout.prop(st, "show_frame_indicator")
181
182         if st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}:
183             if st.display_mode == 'IMAGE':
184                 layout.prop(st, "show_safe_margin")
185             elif st.display_mode == 'WAVEFORM':
186                 layout.prop(st, "show_separate_color")
187
188         layout.separator()
189
190         if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}:
191             layout.prop(st, "use_marker_sync")
192             layout.separator()
193
194         layout.operator("screen.area_dupli")
195         layout.operator("screen.screen_full_area")
196
197
198 class SEQUENCER_MT_select(Menu):
199     bl_label = "Select"
200
201     def draw(self, context):
202         layout = self.layout
203
204         layout.operator("sequencer.select_active_side", text="Strips to the Left").side = 'LEFT'
205         layout.operator("sequencer.select_active_side", text="Strips to the Right").side = 'RIGHT'
206         layout.separator()
207         layout.operator("sequencer.select_handles", text="Surrounding Handles").side = 'BOTH'
208         layout.operator("sequencer.select_handles", text="Left Handle").side = 'LEFT'
209         layout.operator("sequencer.select_handles", text="Right Handle").side = 'RIGHT'
210         layout.separator()
211         layout.operator_menu_enum("sequencer.select_grouped", "type", text="Grouped")
212         layout.operator("sequencer.select_linked")
213         layout.operator("sequencer.select_all").action = 'TOGGLE'
214         layout.operator("sequencer.select_all", text="Inverse").action = 'INVERT'
215
216
217 class SEQUENCER_MT_marker(Menu):
218     bl_label = "Marker"
219
220     def draw(self, context):
221         layout = self.layout
222
223         from bl_ui.space_time import marker_menu_generic
224         marker_menu_generic(layout)
225
226
227 class SEQUENCER_MT_change(Menu):
228     bl_label = "Change"
229
230     def draw(self, context):
231         layout = self.layout
232
233         layout.operator_context = 'INVOKE_REGION_WIN'
234
235         layout.operator_menu_enum("sequencer.change_effect_input", "swap")
236         layout.operator_menu_enum("sequencer.change_effect_type", "type")
237         layout.operator("sequencer.change_path", text="Path/Files")
238
239
240 class SEQUENCER_MT_add(Menu):
241     bl_label = "Add"
242
243     def draw(self, context):
244         layout = self.layout
245
246         layout.operator_context = 'INVOKE_REGION_WIN'
247
248         if len(bpy.data.scenes) > 10:
249             layout.operator_context = 'INVOKE_DEFAULT'
250             layout.operator("sequencer.scene_strip_add", text="Scene...")
251         else:
252             layout.operator_menu_enum("sequencer.scene_strip_add", "scene", text="Scene...")
253
254         if len(bpy.data.movieclips) > 10:
255             layout.operator_context = 'INVOKE_DEFAULT'
256             layout.operator("sequencer.movieclip_strip_add", text="Clips...")
257         else:
258             layout.operator_menu_enum("sequencer.movieclip_strip_add", "clip", text="Clip...")
259
260         if len(bpy.data.masks) > 10:
261             layout.operator_context = 'INVOKE_DEFAULT'
262             layout.operator("sequencer.mask_strip_add", text="Masks...")
263         else:
264             layout.operator_menu_enum("sequencer.mask_strip_add", "mask", text="Mask...")
265
266         layout.operator("sequencer.movie_strip_add", text="Movie")
267         layout.operator("sequencer.image_strip_add", text="Image")
268         layout.operator("sequencer.sound_strip_add", text="Sound")
269
270         layout.menu("SEQUENCER_MT_add_effect")
271
272
273 class SEQUENCER_MT_add_effect(Menu):
274     bl_label = "Effect Strip..."
275
276     def draw(self, context):
277         layout = self.layout
278
279         layout.operator_context = 'INVOKE_REGION_WIN'
280
281         layout.operator("sequencer.effect_strip_add", text="Add").type = 'ADD'
282         layout.operator("sequencer.effect_strip_add", text="Subtract").type = 'SUBTRACT'
283         layout.operator("sequencer.effect_strip_add", text="Alpha Over").type = 'ALPHA_OVER'
284         layout.operator("sequencer.effect_strip_add", text="Alpha Under").type = 'ALPHA_UNDER'
285         layout.operator("sequencer.effect_strip_add", text="Cross").type = 'CROSS'
286         layout.operator("sequencer.effect_strip_add", text="Gamma Cross").type = 'GAMMA_CROSS'
287         layout.operator("sequencer.effect_strip_add", text="Gaussian Blur").type = 'GAUSSIAN_BLUR'
288         layout.operator("sequencer.effect_strip_add", text="Multiply").type = 'MULTIPLY'
289         layout.operator("sequencer.effect_strip_add", text="Over Drop").type = 'OVER_DROP'
290         layout.operator("sequencer.effect_strip_add", text="Wipe").type = 'WIPE'
291         layout.operator("sequencer.effect_strip_add", text="Glow").type = 'GLOW'
292         layout.operator("sequencer.effect_strip_add", text="Transform").type = 'TRANSFORM'
293         layout.operator("sequencer.effect_strip_add", text="Color").type = 'COLOR'
294         layout.operator("sequencer.effect_strip_add", text="Speed Control").type = 'SPEED'
295         layout.operator("sequencer.effect_strip_add", text="Multicam Selector").type = 'MULTICAM'
296         layout.operator("sequencer.effect_strip_add", text="Adjustment Layer").type = 'ADJUSTMENT'
297
298
299 class SEQUENCER_MT_strip(Menu):
300     bl_label = "Strip"
301
302     def draw(self, context):
303         layout = self.layout
304
305         layout.operator_context = 'INVOKE_REGION_WIN'
306
307         layout.operator("transform.transform", text="Grab/Move").mode = 'TRANSLATION'
308         layout.operator("transform.transform", text="Grab/Extend from frame").mode = 'TIME_EXTEND'
309         layout.operator("sequencer.gap_remove")
310         layout.operator("sequencer.gap_insert")
311
312         #  uiItemO(layout, NULL, 0, "sequencer.strip_snap"); // TODO - add this operator
313         layout.separator()
314
315         layout.operator("sequencer.cut", text="Cut (hard) at frame").type = 'HARD'
316         layout.operator("sequencer.cut", text="Cut (soft) at frame").type = 'SOFT'
317         layout.operator("sequencer.images_separate")
318         layout.operator("sequencer.offset_clear")
319         layout.operator("sequencer.deinterlace_selected_movies")
320         layout.operator("sequencer.rebuild_proxy")
321         layout.separator()
322
323         layout.operator("sequencer.duplicate_move")
324         layout.operator("sequencer.delete")
325
326         strip = act_strip(context)
327
328         if strip:
329             stype = strip.type
330
331             # XXX note strip.type is never equal to 'EFFECT', look at seq_type_items within rna_sequencer.c
332             if stype == 'EFFECT':
333                 pass
334                 # layout.separator()
335                 # layout.operator("sequencer.effect_change")
336                 # layout.operator("sequencer.effect_reassign_inputs")
337             elif stype == 'IMAGE':
338                 layout.separator()
339                 # layout.operator("sequencer.image_change")
340                 layout.operator("sequencer.rendersize")
341             elif stype == 'SCENE':
342                 pass
343                 # layout.separator()
344                 # layout.operator("sequencer.scene_change", text="Change Scene")
345             elif stype == 'MOVIE':
346                 layout.separator()
347                 # layout.operator("sequencer.movie_change")
348                 layout.operator("sequencer.rendersize")
349             elif stype == 'SOUND':
350                 layout.separator()
351                 layout.operator("sequencer.crossfade_sounds")
352
353         layout.separator()
354
355         layout.operator("sequencer.meta_make")
356         layout.operator("sequencer.meta_separate")
357
358         #if (ed && (ed->metastack.first || (ed->act_seq && ed->act_seq->type == SEQ_META))) {
359         #       uiItemS(layout);
360         #       uiItemO(layout, NULL, 0, "sequencer.meta_toggle");
361         #}
362
363         layout.separator()
364         layout.operator("sequencer.reload", text="Reload Strips").adjust_length = False
365         layout.operator("sequencer.reload", text="Reload Strips and Adjust Length").adjust_length = True
366         layout.operator("sequencer.reassign_inputs")
367         layout.operator("sequencer.swap_inputs")
368
369         layout.separator()
370         layout.operator("sequencer.lock")
371         layout.operator("sequencer.unlock")
372         layout.operator("sequencer.mute").unselected = False
373         layout.operator("sequencer.unmute")
374
375         layout.operator("sequencer.mute", text="Mute Deselected Strips").unselected = True
376
377         layout.operator("sequencer.snap")
378
379         layout.operator_menu_enum("sequencer.swap", "side")
380
381         layout.separator()
382
383         layout.operator("sequencer.swap_data")
384         layout.menu("SEQUENCER_MT_change")
385
386
387 class SequencerButtonsPanel():
388     bl_space_type = 'SEQUENCE_EDITOR'
389     bl_region_type = 'UI'
390
391     @staticmethod
392     def has_sequencer(context):
393         return (context.space_data.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'})
394
395     @classmethod
396     def poll(cls, context):
397         return cls.has_sequencer(context) and (act_strip(context) is not None)
398
399
400 class SequencerButtonsPanel_Output():
401     bl_space_type = 'SEQUENCE_EDITOR'
402     bl_region_type = 'UI'
403
404     @staticmethod
405     def has_preview(context):
406         return (context.space_data.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'})
407
408     @classmethod
409     def poll(cls, context):
410         return cls.has_preview(context)
411
412
413 class SEQUENCER_PT_edit(SequencerButtonsPanel, Panel):
414     bl_label = "Edit Strip"
415
416     def draw(self, context):
417         layout = self.layout
418
419         scene = context.scene
420         frame_current = scene.frame_current
421         strip = act_strip(context)
422
423         split = layout.split(percentage=0.3)
424         split.label(text="Name:")
425         split.prop(strip, "name", text="")
426
427         split = layout.split(percentage=0.3)
428         split.label(text="Type:")
429         split.prop(strip, "type", text="")
430
431         if strip.type not in {'SOUND'}:
432             split = layout.split(percentage=0.3)
433             split.label(text="Blend:")
434             split.prop(strip, "blend_type", text="")
435
436             row = layout.row(align=True)
437             sub = row.row(align=True)
438             sub.active = (not strip.mute)
439             sub.prop(strip, "blend_alpha", text="Opacity", slider=True)
440             row.prop(strip, "mute", toggle=True, icon_only=True)
441             row.prop(strip, "lock", toggle=True, icon_only=True)
442         else:
443             row = layout.row(align=True)
444             row.prop(strip, "mute", toggle=True, icon_only=True)
445             row.prop(strip, "lock", toggle=True, icon_only=True)
446
447         col = layout.column()
448         sub = col.column()
449         sub.enabled = not strip.lock
450         sub.prop(strip, "channel")
451         sub.prop(strip, "frame_start")
452         sub.prop(strip, "frame_final_duration")
453
454         col = layout.column(align=True)
455         row = col.row(align=True)
456         row.label(text=iface_("Final Length: %s") % bpy.utils.smpte_from_frame(strip.frame_final_duration),
457                   translate=False)
458         row = col.row(align=True)
459         row.active = (frame_current >= strip.frame_start and frame_current <= strip.frame_start + strip.frame_duration)
460         row.label(text=iface_("Playhead: %d") % (frame_current - strip.frame_start), translate=False)
461
462         col.label(text=iface_("Frame Offset %d:%d") % (strip.frame_offset_start, strip.frame_offset_end),
463                   translate=False)
464         col.label(text=iface_("Frame Still %d:%d") % (strip.frame_still_start, strip.frame_still_end), translate=False)
465
466         elem = False
467
468         if strip.type == 'IMAGE':
469             elem = strip.strip_elem_from_frame(frame_current)
470         elif strip.type == 'MOVIE':
471             elem = strip.elements[0]
472
473         if elem and elem.orig_width > 0 and elem.orig_height > 0:
474             col.label(text=iface_("Original Dimension: %dx%d") % (elem.orig_width, elem.orig_height), translate=False)
475         else:
476             col.label(text="Original Dimension: None")
477
478
479 class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
480     bl_label = "Effect Strip"
481
482     @classmethod
483     def poll(cls, context):
484         if not cls.has_sequencer(context):
485             return False
486
487         strip = act_strip(context)
488         if not strip:
489             return False
490
491         return strip.type in {'ADD', 'SUBTRACT', 'ALPHA_OVER', 'ALPHA_UNDER',
492                               'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP',
493                               'WIPE', 'GLOW', 'TRANSFORM', 'COLOR', 'SPEED',
494                               'MULTICAM', 'GAUSSIAN_BLUR'}
495
496     def draw(self, context):
497         layout = self.layout
498
499         strip = act_strip(context)
500
501         if strip.input_count > 0:
502             col = layout.column()
503             col.prop(strip, "input_1")
504             if strip.input_count > 1:
505                 col.prop(strip, "input_2")
506
507         if strip.type == 'COLOR':
508             layout.prop(strip, "color")
509
510         elif strip.type == 'WIPE':
511             col = layout.column()
512             col.prop(strip, "transition_type")
513             col.label(text="Direction:")
514             col.row().prop(strip, "direction", expand=True)
515
516             col = layout.column()
517             col.prop(strip, "blur_width", slider=True)
518             if strip.transition_type in {'SINGLE', 'DOUBLE'}:
519                 col.prop(strip, "angle")
520
521         elif strip.type == 'GLOW':
522             flow = layout.column_flow()
523             flow.prop(strip, "threshold", slider=True)
524             flow.prop(strip, "clamp", slider=True)
525             flow.prop(strip, "boost_factor")
526             flow.prop(strip, "blur_radius")
527
528             row = layout.row()
529             row.prop(strip, "quality", slider=True)
530             row.prop(strip, "use_only_boost")
531
532         elif strip.type == 'SPEED':
533             layout.prop(strip, "use_default_fade", "Stretch to input strip length")
534             if not strip.use_default_fade:
535                 layout.prop(strip, "use_as_speed")
536                 if strip.use_as_speed:
537                     layout.prop(strip, "speed_factor")
538                 else:
539                     layout.prop(strip, "speed_factor", text="Frame number")
540                     layout.prop(strip, "scale_to_length")
541
542         elif strip.type == 'TRANSFORM':
543             layout = self.layout
544             col = layout.column()
545
546             col.prop(strip, "interpolation")
547             col.prop(strip, "translation_unit")
548             col = layout.column(align=True)
549             col.label(text="Position:")
550             col.prop(strip, "translate_start_x", text="X")
551             col.prop(strip, "translate_start_y", text="Y")
552
553             layout.separator()
554
555             col = layout.column(align=True)
556             col.prop(strip, "use_uniform_scale")
557             if strip.use_uniform_scale:
558                 col = layout.column(align=True)
559                 col.prop(strip, "scale_start_x", text="Scale")
560             else:
561                 col = layout.column(align=True)
562                 col.label(text="Scale:")
563                 col.prop(strip, "scale_start_x", text="X")
564                 col.prop(strip, "scale_start_y", text="Y")
565
566             layout.separator()
567
568             col = layout.column(align=True)
569             col.label(text="Rotation:")
570             col.prop(strip, "rotation_start", text="Rotation")
571
572         elif strip.type == 'MULTICAM':
573             layout.prop(strip, "multicam_source")
574
575             row = layout.row(align=True)
576             sub = row.row(align=True)
577             sub.scale_x = 2.0
578
579             sub.operator("screen.animation_play", text="", icon='PAUSE' if context.screen.is_animation_playing else 'PLAY')
580
581             row.label("Cut To")
582             for i in range(1, strip.channel):
583                 row.operator("sequencer.cut_multicam", text="%d" % i).camera = i
584
585         col = layout.column(align=True)
586         if strip.type == 'SPEED':
587             col.prop(strip, "multiply_speed")
588         elif strip.type in {'CROSS', 'GAMMA_CROSS', 'WIPE'}:
589             col.prop(strip, "use_default_fade", "Default fade")
590             if not strip.use_default_fade:
591                 col.prop(strip, "effect_fader", text="Effect fader")
592         elif strip.type == 'GAUSSIAN_BLUR':
593             col.prop(strip, "size_x")
594             col.prop(strip, "size_y")
595
596
597 class SEQUENCER_PT_input(SequencerButtonsPanel, Panel):
598     bl_label = "Strip Input"
599
600     @classmethod
601     def poll(cls, context):
602         if not cls.has_sequencer(context):
603             return False
604
605         strip = act_strip(context)
606         if not strip:
607             return False
608
609         return strip.type in {'MOVIE', 'IMAGE', 'SCENE', 'MOVIECLIP', 'META',
610                               'ADD', 'SUBTRACT', 'ALPHA_OVER', 'ALPHA_UNDER',
611                               'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP',
612                               'WIPE', 'GLOW', 'TRANSFORM', 'COLOR',
613                               'MULTICAM', 'SPEED', 'ADJUSTMENT'}
614
615     def draw(self, context):
616         layout = self.layout
617
618         strip = act_strip(context)
619
620         seq_type = strip.type
621
622         # draw a filename if we have one
623         if seq_type == 'IMAGE':
624             split = layout.split(percentage=0.2)
625             split.label(text="Path:")
626             split.prop(strip, "directory", text="")
627
628             # Current element for the filename
629
630             elem = strip.strip_elem_from_frame(context.scene.frame_current)
631             if elem:
632                 split = layout.split(percentage=0.2)
633                 split.label(text="File:")
634                 split.prop(elem, "filename", text="")  # strip.elements[0] could be a fallback
635
636             layout.prop(strip.colorspace_settings, "name")
637             layout.prop(strip, "alpha_mode")
638
639             layout.operator("sequencer.change_path")
640
641         elif seq_type == 'MOVIE':
642             split = layout.split(percentage=0.2)
643             split.label(text="Path:")
644             split.prop(strip, "filepath", text="")
645
646             layout.prop(strip.colorspace_settings, "name")
647
648             layout.prop(strip, "mpeg_preseek")
649             layout.prop(strip, "stream_index")
650
651         layout.prop(strip, "use_translation", text="Image Offset")
652         if strip.use_translation:
653             col = layout.column(align=True)
654             col.prop(strip.transform, "offset_x", text="X")
655             col.prop(strip.transform, "offset_y", text="Y")
656
657         layout.prop(strip, "use_crop", text="Image Crop")
658         if strip.use_crop:
659             col = layout.column(align=True)
660             col.prop(strip.crop, "max_y")
661             col.prop(strip.crop, "min_x")
662             col.prop(strip.crop, "min_y")
663             col.prop(strip.crop, "max_x")
664
665         if not isinstance(strip, bpy.types.EffectSequence):
666             col = layout.column(align=True)
667             col.label(text="Trim Duration (hard):")
668             col.prop(strip, "animation_offset_start", text="Start")
669             col.prop(strip, "animation_offset_end", text="End")
670
671         col = layout.column(align=True)
672         col.label(text="Trim Duration (soft):")
673         col.prop(strip, "frame_offset_start", text="Start")
674         col.prop(strip, "frame_offset_end", text="End")
675
676
677 class SEQUENCER_PT_sound(SequencerButtonsPanel, Panel):
678     bl_label = "Sound"
679
680     @classmethod
681     def poll(cls, context):
682         if not cls.has_sequencer(context):
683             return False
684
685         strip = act_strip(context)
686         if not strip:
687             return False
688
689         return (strip.type == 'SOUND')
690
691     def draw(self, context):
692         layout = self.layout
693
694         strip = act_strip(context)
695         sound = strip.sound
696
697         layout.template_ID(strip, "sound", open="sound.open")
698
699         layout.separator()
700         layout.prop(strip, "filepath", text="")
701
702         if sound is not None:
703             row = layout.row()
704             if sound.packed_file:
705                 row.operator("sound.unpack", icon='PACKAGE', text="Unpack")
706             else:
707                 row.operator("sound.pack", icon='UGLYPACKAGE', text="Pack")
708
709             row.prop(sound, "use_memory_cache")
710
711         layout.prop(strip, "show_waveform")
712         layout.prop(strip, "volume")
713         layout.prop(strip, "pitch")
714         layout.prop(strip, "pan")
715
716         col = layout.column(align=True)
717         col.label(text="Trim Duration (hard):")
718         col.prop(strip, "animation_offset_start", text="Start")
719         col.prop(strip, "animation_offset_end", text="End")
720
721         col = layout.column(align=True)
722         col.label(text="Trim Duration (soft):")
723         col.prop(strip, "frame_offset_start", text="Start")
724         col.prop(strip, "frame_offset_end", text="End")
725
726
727 class SEQUENCER_PT_scene(SequencerButtonsPanel, Panel):
728     bl_label = "Scene"
729
730     @classmethod
731     def poll(cls, context):
732         if not cls.has_sequencer(context):
733             return False
734
735         strip = act_strip(context)
736         if not strip:
737             return False
738
739         return (strip.type == 'SCENE')
740
741     def draw(self, context):
742         layout = self.layout
743
744         strip = act_strip(context)
745
746         layout.template_ID(strip, "scene")
747
748         scene = strip.scene
749
750         layout.label(text="Camera Override")
751         layout.template_ID(strip, "scene_camera")
752
753         if scene:
754             layout.prop(scene, "audio_volume", text="Audio Volume")
755
756             sta = scene.frame_start
757             end = scene.frame_end
758             layout.label(text=iface_("Original frame range: %d-%d (%d)") % (sta, end, end - sta + 1), translate=False)
759
760
761 class SEQUENCER_PT_mask(SequencerButtonsPanel, Panel):
762     bl_label = "Mask"
763
764     @classmethod
765     def poll(cls, context):
766         if not cls.has_sequencer(context):
767             return False
768
769         strip = act_strip(context)
770         if not strip:
771             return False
772
773         return (strip.type == 'MASK')
774
775     def draw(self, context):
776         layout = self.layout
777
778         strip = act_strip(context)
779
780         layout.template_ID(strip, "mask")
781
782         mask = strip.mask
783
784         if mask:
785             sta = mask.frame_start
786             end = mask.frame_end
787             layout.label(text=iface_("Original frame range: %d-%d (%d)") % (sta, end, end - sta + 1), translate=False)
788
789
790 class SEQUENCER_PT_filter(SequencerButtonsPanel, Panel):
791     bl_label = "Filter"
792
793     @classmethod
794     def poll(cls, context):
795         if not cls.has_sequencer(context):
796             return False
797
798         strip = act_strip(context)
799         if not strip:
800             return False
801
802         return strip.type in {'MOVIE', 'IMAGE', 'SCENE', 'MOVIECLIP', 'MASK',
803                               'META', 'ADD', 'SUBTRACT', 'ALPHA_OVER',
804                               'ALPHA_UNDER', 'CROSS', 'GAMMA_CROSS', 'MULTIPLY',
805                               'OVER_DROP', 'WIPE', 'GLOW', 'TRANSFORM', 'COLOR',
806                               'MULTICAM', 'SPEED', 'ADJUSTMENT'}
807
808     def draw(self, context):
809         layout = self.layout
810
811         strip = act_strip(context)
812
813         col = layout.column()
814         col.label(text="Video:")
815         col.prop(strip, "strobe")
816
817         if strip.type == 'MOVIECLIP':
818             col = layout.column()
819             col.label(text="Tracker:")
820             col.prop(strip, "stabilize2d")
821
822             col = layout.column()
823             col.label(text="Distortion:")
824             col.prop(strip, "undistort")
825
826         split = layout.split(percentage=0.65)
827
828         col = split.column()
829         col.prop(strip, "use_reverse_frames", text="Backwards")
830         col.prop(strip, "use_deinterlace")
831
832         col = split.column()
833         col.label(text="Flip:")
834         col.prop(strip, "use_flip_x", text="X")
835         col.prop(strip, "use_flip_y", text="Y")
836
837         col = layout.column()
838         col.label(text="Colors:")
839         col.prop(strip, "color_saturation", text="Saturation")
840         col.prop(strip, "color_multiply", text="Multiply")
841         col.prop(strip, "use_float")
842
843
844 class SEQUENCER_PT_proxy(SequencerButtonsPanel, Panel):
845     bl_label = "Proxy / Timecode"
846
847     @classmethod
848     def poll(cls, context):
849         if not cls.has_sequencer(context):
850             return False
851
852         strip = act_strip(context)
853         if not strip:
854             return False
855
856         return strip.type in {'MOVIE', 'IMAGE', 'SCENE', 'META', 'MULTICAM'}
857
858     def draw_header(self, context):
859         strip = act_strip(context)
860
861         self.layout.prop(strip, "use_proxy", text="")
862
863     def draw(self, context):
864         layout = self.layout
865
866         strip = act_strip(context)
867
868         flow = layout.column_flow()
869         flow.prop(strip, "use_proxy_custom_directory")
870         flow.prop(strip, "use_proxy_custom_file")
871         if strip.proxy:
872             if strip.use_proxy_custom_directory and not strip.use_proxy_custom_file:
873                 flow.prop(strip.proxy, "directory")
874             if strip.use_proxy_custom_file:
875                 flow.prop(strip.proxy, "filepath")
876
877             row = layout.row()
878             row.prop(strip.proxy, "build_25")
879             row.prop(strip.proxy, "build_50")
880             row.prop(strip.proxy, "build_75")
881             row.prop(strip.proxy, "build_100")
882
883             col = layout.column()
884             col.label(text="Build JPEG quality")
885             col.prop(strip.proxy, "quality")
886
887             if strip.type == 'MOVIE':
888                 col = layout.column()
889                 col.label(text="Use timecode index:")
890
891                 col.prop(strip.proxy, "timecode")
892
893
894 class SEQUENCER_PT_preview(SequencerButtonsPanel_Output, Panel):
895     bl_label = "Scene Preview/Render"
896     bl_space_type = 'SEQUENCE_EDITOR'
897     bl_region_type = 'UI'
898
899     def draw(self, context):
900         layout = self.layout
901
902         render = context.scene.render
903
904         col = layout.column()
905         col.prop(render, "use_sequencer_gl_preview", text="Open GL Preview")
906         col = layout.column()
907         #col.active = render.use_sequencer_gl_preview
908         col.prop(render, "sequencer_gl_preview", text="")
909
910         row = col.row()
911         row.active = render.sequencer_gl_preview == 'SOLID'
912         row.prop(render, "use_sequencer_gl_textured_solid")
913
914
915 class SEQUENCER_PT_view(SequencerButtonsPanel_Output, Panel):
916     bl_label = "View Settings"
917
918     def draw(self, context):
919         layout = self.layout
920
921         st = context.space_data
922
923         col = layout.column()
924         if st.display_mode == 'IMAGE':
925             col.prop(st, "draw_overexposed")
926             col.prop(st, "show_safe_margin")
927         elif st.display_mode == 'WAVEFORM':
928             col.prop(st, "show_separate_color")
929         col.prop(st, "proxy_render_size")
930
931
932 class SEQUENCER_PT_modifiers(SequencerButtonsPanel, Panel):
933     bl_label = "Modifiers"
934
935     def draw(self, context):
936         layout = self.layout
937
938         strip = act_strip(context)
939         sequencer = context.scene.sequence_editor
940
941         layout.prop(strip, "use_linear_modifiers")
942
943         layout.operator_menu_enum("sequencer.strip_modifier_add", "type")
944
945         for mod in strip.modifiers:
946             box = layout.box()
947
948             row = box.row()
949             row.prop(mod, "show_expanded", text="", emboss=False)
950             row.prop(mod, "name", text="")
951
952             row.prop(mod, "mute", text="")
953
954             sub = row.row(align=True)
955             props = sub.operator("sequencer.strip_modifier_move", text="", icon='TRIA_UP')
956             props.name = mod.name
957             props.direction = 'UP'
958             props = sub.operator("sequencer.strip_modifier_move", text="", icon='TRIA_DOWN')
959             props.name = mod.name
960             props.direction = 'DOWN'
961
962             row.operator("sequencer.strip_modifier_remove", text="", icon='X', emboss=False).name = mod.name
963
964             if mod.show_expanded:
965                 row = box.row()
966                 row.prop(mod, "input_mask_type", expand=True)
967
968                 if mod.input_mask_type == 'STRIP':
969                     sequences_object = sequencer
970                     if sequencer.meta_stack:
971                         sequences_object = sequencer.meta_stack[-1]
972                     box.prop_search(mod, "input_mask_strip", sequences_object, "sequences", text="Mask")
973                 else:
974                     box.prop(mod, "input_mask_id")
975
976                 if mod.type == 'COLOR_BALANCE':
977                     box.prop(mod, "color_multiply")
978                     draw_color_balance(box, mod.color_balance)
979                 elif mod.type == 'CURVES':
980                     box.template_curve_mapping(mod, "curve_mapping", type='COLOR')
981                 elif mod.type == 'HUE_CORRECT':
982                     box.template_curve_mapping(mod, "curve_mapping", type='HUE')
983                 elif mod.type == 'BRIGHT_CONTRAST':
984                     col = box.column()
985                     col.prop(mod, "bright")
986                     col.prop(mod, "contrast")
987
988
989 if __name__ == "__main__":  # only for live edit.
990     bpy.utils.register_module(__name__)