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