Sequencer UI layout tweaks.
[blender.git] / release / ui / space_sequencer.py
1
2 import bpy
3
4 def act_strip(context):
5         try:            return context.scene.sequence_editor.active_strip
6         except: return None
7
8 # Header
9 class SEQUENCER_HT_header(bpy.types.Header):
10         __space_type__ = "SEQUENCE_EDITOR"
11
12         def draw(self, context):
13                 
14                 st = context.space_data
15                 layout = self.layout
16
17                 layout.template_header()
18                 
19                 if context.area.show_menus:
20                         row = layout.row()
21                         row.itemM("SEQUENCER_MT_view")
22                         
23                         row.itemR(st, "display_mode")
24                         
25                         layout.itemS()
26                         
27                         if st.display_mode == 'SEQUENCER':
28                                 row.itemM("SEQUENCER_MT_select")
29                                 row.itemM("SEQUENCER_MT_marker")
30                                 row.itemM("SEQUENCER_MT_add")
31                                 row.itemM("SEQUENCER_MT_strip")
32                                 layout.itemS()
33                                 row.itemO("sequencer.reload")
34                         else:
35                                 row.itemR(st, "display_channel") # text="Chan"
36
37 class SEQUENCER_MT_view(bpy.types.Menu):
38         __space_type__ = "SEQUENCE_EDITOR"
39         __label__ = "View (TODO)"
40         
41         def draw(self, context):
42                 layout = self.layout
43                 st = context.space_data
44                 
45                 layout.column()
46                 
47                 """
48         uiBlock *block= uiBeginBlock(C, ar, "seq_viewmenu", UI_EMBOSSP);
49         short yco= 0, menuwidth=120;
50
51         if (sseq->mainb == SEQ_DRAW_SEQUENCE) {
52                 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
53                                  "Play Back Animation "
54                                  "in all Sequence Areas|Alt A", 0, yco-=20,
55                                  menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
56         }
57         else {
58                 uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL,
59                                  "Grease Pencil...", 0, yco-=20,
60                                  menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
61                 uiDefMenuSep(block);
62
63                 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
64                                  "Play Back Animation "
65                                  "in this window|Alt A", 0, yco-=20,
66                                  menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
67         }
68         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
69                          "Play Back Animation in all "
70                          "3D Views and Sequence Areas|Alt Shift A",
71                          0, yco-=20,
72                          menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
73
74                 """
75                 layout.itemS()
76                 layout.itemO("sequencer.view_all")
77                 layout.itemO("sequencer.view_selected")
78                 layout.itemS()
79                 """
80         
81
82         /* Lock Time */
83         uiDefIconTextBut(block, BUTM, 1, (v2d->flag & V2D_VIEWSYNC_SCREEN_TIME)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT,
84                         "Lock Time to Other Windows|", 0, yco-=20,
85                         menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
86
87         /* Draw time or frames.*/
88         uiDefMenuSep(block);
89                 """
90                 
91                 layout.itemR(st, "draw_frames")
92                 if st.display_mode == 'IMAGE':
93                         layout.itemR(st, "draw_safe_margin")
94                 if st.display_mode == 'WAVEFORM':
95                         layout.itemR(st, "seperate_color_preview")
96                 
97                 """
98         if(!sa->full) uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Maximize Window|Ctrl UpArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0,0, "");
99         else uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Tile Window|Ctrl DownArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
100
101                 """
102
103 class SEQUENCER_MT_select(bpy.types.Menu):
104         __space_type__ = "SEQUENCE_EDITOR"
105         __label__ = "Select"
106
107         def draw(self, context):
108                 layout = self.layout
109                 st = context.space_data
110                 
111                 layout.column()
112                 layout.item_enumO("sequencer.select_active_side", "side", 'LEFT', text="Strips to the Left")
113                 layout.item_enumO("sequencer.select_active_side", "side", 'RIGHT', text="Strips to the Right")
114                 layout.itemS()
115                 layout.item_enumO("sequencer.select_handles", "side", 'BOTH', text="Surrounding Handles")
116                 layout.item_enumO("sequencer.select_handles", "side", 'LEFT', text="Left Handle")
117                 layout.item_enumO("sequencer.select_handles", "side", 'RIGHT', text="Right Handle")
118                 layout.itemS()
119                 layout.itemO("sequencer.select_linked")
120                 layout.itemO("sequencer.select_all_toggle")
121                 layout.itemO("sequencer.select_inverse")
122
123 class SEQUENCER_MT_marker(bpy.types.Menu):
124         __space_type__ = "SEQUENCE_EDITOR"
125         __label__ = "Marker (TODO)"
126
127         def draw(self, context):
128                 layout = self.layout
129                 st = context.space_data
130                 
131                 layout.column()
132                 layout.itemO("sequencer.sound_strip_add", text="Add Marker|Ctrl Alt M")
133                 layout.itemO("sequencer.sound_strip_add", text="Duplicate Marker|Ctrl Shift D")
134                 layout.itemO("sequencer.sound_strip_add", text="Delete Marker|Shift X")
135                 layout.itemS()
136                 layout.itemO("sequencer.sound_strip_add", text="(Re)Name Marker|Ctrl M")
137                 layout.itemO("sequencer.sound_strip_add", text="Grab/Move Marker|Ctrl G")
138                 layout.itemS()
139                 layout.itemO("sequencer.sound_strip_add", text="Transform Markers") # toggle, will be rna - (sseq->flag & SEQ_MARKER_TRANS)
140
141 class SEQUENCER_MT_add(bpy.types.Menu):
142         __space_type__ = "SEQUENCE_EDITOR"
143         __label__ = "Add"
144
145         def draw(self, context):
146                 layout = self.layout
147                 st = context.space_data
148                 
149                 layout.column()
150                 layout.itemO("sequencer.scene_strip_add", text="Scene")
151                 layout.itemO("sequencer.movie_strip_add", text="Movie")
152                 layout.itemO("sequencer.image_strip_add", text="Image")
153                 layout.itemO("sequencer.sound_strip_add", text="Sound")
154                 
155                 layout.itemM("SEQUENCER_MT_add_effect")
156
157
158 class SEQUENCER_MT_add_effect(bpy.types.Menu):
159         __space_type__ = "SEQUENCE_EDITOR"
160         __label__ = "Effect Strip..."
161
162         def draw(self, context):
163                 layout = self.layout
164                 st = context.space_data
165                 
166                 self.layout.column()
167                 self.layout.item_enumO("sequencer.effect_strip_add", 'type', 'ADD')
168                 self.layout.item_enumO("sequencer.effect_strip_add", 'type', 'SUBTRACT')
169                 self.layout.item_enumO("sequencer.effect_strip_add", 'type', 'ALPHA_OVER')
170                 self.layout.item_enumO("sequencer.effect_strip_add", 'type', 'ALPHA_UNDER')
171                 self.layout.item_enumO("sequencer.effect_strip_add", 'type', 'GAMMA_CROSS')
172                 self.layout.item_enumO("sequencer.effect_strip_add", 'type', 'MULTIPLY')
173                 self.layout.item_enumO("sequencer.effect_strip_add", 'type', 'OVER_DROP')
174                 self.layout.item_enumO("sequencer.effect_strip_add", 'type', 'PLUGIN')
175                 self.layout.item_enumO("sequencer.effect_strip_add", 'type', 'WIPE')
176                 self.layout.item_enumO("sequencer.effect_strip_add", 'type', 'GLOW')
177                 self.layout.item_enumO("sequencer.effect_strip_add", 'type', 'TRANSFORM')
178                 self.layout.item_enumO("sequencer.effect_strip_add", 'type', 'COLOR')
179                 self.layout.item_enumO("sequencer.effect_strip_add", 'type', 'SPEED')
180
181 class SEQUENCER_MT_strip(bpy.types.Menu):
182         __space_type__ = "SEQUENCE_EDITOR"
183         __label__ = "Strip"
184
185         def draw(self, context):
186                 layout = self.layout
187                 st = context.space_data
188                 
189                 layout.operator_context = 'INVOKE_REGION_WIN'
190                 
191                 layout.column()
192                 layout.item_enumO("tfm.transform", "mode", 'TRANSLATION', text="Grab/Move")
193                 layout.item_enumO("tfm.transform", "mode", 'TIME_EXTEND', text="Grab/Extend from frame")
194                 #  uiItemO(layout, NULL, 0, "sequencer.strip_snap"); // TODO - add this operator
195                 layout.itemS()
196                 
197                 layout.item_enumO("sequencer.cut", "type", 'HARD', text="Cut (hard) at frame")
198                 layout.item_enumO("sequencer.cut", "type", 'SOFT', text="Cut (soft) at frame")
199                 layout.itemO("sequencer.images_separate")
200                 layout.itemS()
201                 
202                 layout.itemO("sequencer.duplicate")
203                 layout.itemO("sequencer.delete")
204                 
205                 strip = act_strip(context)
206                 
207                 if strip:
208                         stype = strip.type
209                         
210                         if      stype=='EFFECT':
211                                 layout.itemS()
212                                 layout.itemO("sequencer.effect_change")
213                                 layout.itemO("sequencer.effect_reassign_inputs")
214                         elif stype=='IMAGE':
215                                 layout.itemS()
216                                 layout.itemO("sequencer.image_change")
217                         elif stype=='SCENE':
218                                 layout.itemS()
219                                 layout.itemO("sequencer.scene_change", text="Change Scene")
220                         elif stype=='MOVIE':
221                                 layout.itemS()
222                                 layout.itemO("sequencer.movie_change")
223                         
224                 layout.itemS()
225                 
226                 layout.itemO("sequencer.meta_make")
227                 layout.itemO("sequencer.meta_separate")
228                 
229                 #if (ed && (ed->metastack.first || (ed->act_seq && ed->act_seq->type == SEQ_META))) {
230                 #       uiItemS(layout);
231                 #       uiItemO(layout, NULL, 0, "sequencer.meta_toggle");
232                 #}
233                 
234                 layout.itemS()
235                 layout.itemO("sequencer.reload")
236                 layout.itemS()
237                 layout.itemO("sequencer.lock")
238                 layout.itemO("sequencer.unlock")
239                 layout.itemO("sequencer.mute")
240                 layout.itemO("sequencer.unmute")
241                 
242                 layout.item_booleanO("sequencer.mute", "unselected", 1, text="Mute Deselected Strips")
243
244                 layout.itemO("sequencer.snap")
245
246 # Panels
247 class SequencerButtonsPanel(bpy.types.Panel):
248         __space_type__ = "SEQUENCE_EDITOR"
249         __region_type__ = "UI"
250
251         def poll(self, context):
252                 return context.space_data.display_mode == 'SEQUENCER' and act_strip(context) != None
253                 
254 class SequencerButtonsPanel_Output(bpy.types.Panel):
255         __space_type__ = "SEQUENCE_EDITOR"
256         __region_type__ = "UI"
257
258         def poll(self, context):
259                 return context.space_data.display_mode != 'SEQUENCER'
260
261 class SEQUENCER_PT_edit(SequencerButtonsPanel):
262         __label__ = "Edit Strip"
263
264         def draw(self, context):
265                 layout = self.layout
266                 
267                 strip = act_strip(context)
268                 
269                 split = layout.split(percentage=0.3)
270                 split.itemL(text="Name:")
271                 split.itemR(strip, "name", text="")
272                 
273                 split = layout.split(percentage=0.3)
274                 split.itemL(text="Type:")
275                 split.itemR(strip, "type", text="")
276                 
277                 split = layout.split(percentage=0.3)
278                 split.itemL(text="Blend:")
279                 split.itemR(strip, "blend_mode", text="")
280                 
281                 row = layout.row()
282                 
283                 
284                 if strip.mute == True:
285                         row.itemR(strip, "mute", toggle=True, icon='ICON_RESTRICT_VIEW_ON', text="")
286                 elif strip.mute == False:
287                         row.itemR(strip, "mute", toggle=True, icon='ICON_RESTRICT_VIEW_OFF', text="")
288                 
289                 sub = row.row()
290                 sub.active = (not strip.mute)
291                 
292                 sub.itemR(strip, "blend_opacity", text="Opacity", slider=True)
293                 
294                 row = layout.row()
295                 row.itemR(strip, "lock")
296                 row.itemR(strip, "frame_locked", text="Frame Lock")
297                 
298                 col = layout.column()
299                 col.itemR(strip, "channel")
300                 col.itemR(strip, "start_frame")
301                 col.itemR(strip, "length")
302                 
303                 col = layout.column(align=True)
304                 col.itemL(text="Offset:")
305                 col.itemR(strip, "start_offset", text="Start")
306                 col.itemR(strip, "end_offset", text="End")
307                 
308                 col = layout.column(align=True)
309                 col.itemL(text="Still:")
310                 col.itemR(strip, "start_still", text="Start")
311                 col.itemR(strip, "end_still", text="End")
312                 
313 class SEQUENCER_PT_effect(SequencerButtonsPanel):
314         __label__ = "Effect Strip"
315
316         def poll(self, context):
317                 if context.space_data.display_mode != 'SEQUENCER':
318                         return False
319                 
320                 strip = act_strip(context)
321                 if not strip:
322                         return False
323                 
324                 return strip.type in ('COLOR', 'WIPE', 'GLOW', 'SPEED', 'TRANSFORM')
325
326         def draw(self, context):
327                 layout = self.layout
328                 
329                 strip = act_strip(context)
330                 
331                 if strip.type == 'COLOR':
332                         layout.itemR(strip, "color")
333                         
334                 elif strip.type == 'WIPE':
335                         
336                         col = layout.column()
337                         col.itemR(strip, "transition_type")
338                         col.itemL(text="Direction:")
339                         col.row().itemR(strip, "direction", expand=True)
340                         
341                         col = layout.column()
342                         col.itemR(strip, "blur_width", slider=True)
343                         if strip.transition_type in ('SINGLE', 'DOUBLE'):
344                                 col.itemR(strip, "angle")
345                                 
346                 elif strip.type == 'GLOW':
347                         flow = layout.column_flow()
348                         flow.itemR(strip, "threshold", slider=True)
349                         flow.itemR(strip, "clamp", slider=True)
350                         flow.itemR(strip, "boost_factor")
351                         flow.itemR(strip, "blur_distance")
352                         
353                         row = layout.row()
354                         row.itemR(strip, "quality", slider=True)
355                         row.itemR(strip, "only_boost")
356                         
357                 elif strip.type == 'SPEED':
358                         layout.itemR(strip, "global_speed")
359                         
360                         flow = layout.column_flow()
361                         flow.itemR(strip, "curve_velocity")
362                         flow.itemR(strip, "curve_compress_y")
363                         flow.itemR(strip, "frame_blending")
364                         
365                 elif strip.type == 'TRANSFORM':
366                         
367                         col = layout.column()
368                         col.itemR(strip, "interpolation")
369                         col.itemR(strip, "translation_unit")
370                         
371                         col = layout.column(align=True)
372                         col.itemL(text="Position X:")
373                         col.itemR(strip, "translate_start_x", text="Start")
374                         col.itemR(strip, "translate_end_x", text="End")
375                         
376                         col = layout.column(align=True)
377                         col.itemL(text="Position Y:")
378                         col.itemR(strip, "translate_start_y", text="Start")
379                         col.itemR(strip, "translate_end_y", text="End")
380                         
381                         layout.itemS()
382                         
383                         col = layout.column(align=True)
384                         col.itemL(text="Scale X:")
385                         col.itemR(strip, "scale_start_x", text="Start")
386                         col.itemR(strip, "scale_end_x", text="End")
387                         
388                         col = layout.column(align=True)
389                         col.itemL(text="Scale Y:")
390                         col.itemR(strip, "scale_start_y", text="Start")
391                         col.itemR(strip, "scale_end_y", text="End")
392                         
393                         layout.itemS()
394                         
395                         col = layout.column(align=True)
396                         col.itemL(text="Rotation:")
397                         col.itemR(strip, "rotation_start", text="Start")
398                         col.itemR(strip, "rotation_end", text="End")
399                         
400
401 class SEQUENCER_PT_input(SequencerButtonsPanel):
402         __label__ = "Strip Input"
403         
404         def poll(self, context):
405                 if context.space_data.display_mode != 'SEQUENCER':
406                         return False
407                 
408                 strip = act_strip(context)
409                 if not strip:
410                         return False
411                 
412                 return strip.type in ('MOVIE', 'IMAGE', 'SOUND')
413         
414         def draw(self, context):
415                 layout = self.layout
416                 
417                 strip = act_strip(context)
418                 
419                 split = layout.split(percentage=0.3)
420                 sub = split.column()
421                 sub.itemL(text="Directory:")
422                 sub = split.column() 
423                 sub.itemR(strip, "directory", text="")
424                 
425                 # Current element for the filename
426                 split = layout.split(percentage=0.3)
427                 sub = split.column()
428                 sub.itemL(text="File Name:")
429                 sub = split.column()
430                 
431                 elem = strip.getStripElem(context.scene.current_frame)
432                 if elem:
433                         sub.itemR(elem, "filename", text="") # strip.elements[0] could be a fallback
434                 
435                 layout.itemR(strip, "use_translation", text="Image Offset:")
436                 if strip.transform:
437                         col = layout.column(align=True)
438                         col.active = strip.use_translation
439                         col.itemR(strip.transform, "offset_x", text="X")
440                         col.itemR(strip.transform, "offset_y", text="Y")
441                         
442                         
443                 layout.itemR(strip, "use_crop", text="Image Crop:")
444                 if strip.crop:
445                         col = layout.column(align=True)
446                         col.active = strip.use_crop
447                         col.itemR(strip.crop, "top")
448                         col.itemR(strip.crop, "left")
449                         col.itemR(strip.crop, "bottom")
450                         col.itemR(strip.crop, "right")
451                 
452                 col = layout.column(align=True)
453                 col.itemL(text="Trim Duration:")
454                 col.itemR(strip, "animation_start_offset", text="Start")
455                 col.itemR(strip, "animation_end_offset", text="End")
456                 
457
458 class SEQUENCER_PT_filter(SequencerButtonsPanel):
459         __label__ = "Filter"
460         
461         def poll(self, context):
462                 if context.space_data.display_mode != 'SEQUENCER':
463                         return False
464                 
465                 strip = act_strip(context)
466                 if not strip:
467                         return False
468                 
469                 return strip.type in ('MOVIE', 'IMAGE', 'SCENE', 'META')
470         
471         def draw(self, context):
472                 layout = self.layout
473                 
474                 strip = act_strip(context)
475                 
476                 
477                 col = layout.column()
478                 col.itemL(text="Video:")
479                 col.itemR(strip, "strobe")
480                 col.itemR(strip, "de_interlace")
481                 
482                 col = layout.column()
483                 col.itemL(text="Colors:")
484                 col.itemR(strip, "multiply_colors", text="Multiply")
485                 col.itemR(strip, "premultiply")
486                 col.itemR(strip, "convert_float")
487
488                 col = layout.column()
489                 col.itemL(text="Flip:")
490                 col.itemR(strip, "flip_x", text="X")
491                 col.itemR(strip, "flip_y", text="Y")
492                 col.itemR(strip, "reverse_frames", text="Backwards")
493                 
494                 layout.itemR(strip, "use_color_balance")
495                 if strip.color_balance: # TODO - need to add this somehow
496                         row = layout.row()
497                         row.active = strip.use_color_balance
498                         col = row.column()
499                         col.itemR(strip.color_balance, "lift")
500                         col.itemR(strip.color_balance, "inverse_lift", text="Inverse")
501                         col = row.column()
502                         col.itemR(strip.color_balance, "gamma")
503                         col.itemR(strip.color_balance, "inverse_gamma", text="Inverse")
504                         col = row.column()
505                         col.itemR(strip.color_balance, "gain")
506                         col.itemR(strip.color_balance, "inverse_gain", text="Inverse")
507                         
508
509 class SEQUENCER_PT_proxy(SequencerButtonsPanel):
510         __label__ = "Proxy"
511         
512         def poll(self, context):
513                 if context.space_data.display_mode != 'SEQUENCER':
514                         return False
515                 
516                 strip = act_strip(context)
517                 if not strip:
518                         return False
519                 
520                 return strip.type in ('MOVIE', 'IMAGE', 'SCENE', 'META')
521         
522         def draw_header(self, context):
523                 strip = act_strip(context)
524
525                 layout = self.layout
526                 
527                 layout.itemR(strip, "use_proxy", text="")
528
529         def draw(self, context):
530                 strip = act_strip(context)
531                 
532                 layout = self.layout
533                 
534                 flow = layout.column_flow()
535                 flow.itemR(strip, "proxy_custom_directory")
536                 if strip.proxy: # TODO - need to add this somehow
537                         flow.itemR(strip.proxy, "directory")
538                         flow.itemR(strip.proxy, "file")
539
540
541 class SEQUENCER_PT_view(SequencerButtonsPanel_Output):
542         __label__ = "View Settings"
543
544         def draw(self, context):
545                 st = context.space_data
546
547                 layout = self.layout
548
549                 flow = layout.column_flow()
550                 flow.itemR(st, "draw_overexposed") # text="Zebra"
551                 flow.itemR(st, "draw_safe_margin")
552
553
554 bpy.types.register(SEQUENCER_HT_header) # header/menu classes
555 bpy.types.register(SEQUENCER_MT_view)
556 bpy.types.register(SEQUENCER_MT_select)
557 bpy.types.register(SEQUENCER_MT_marker)
558 bpy.types.register(SEQUENCER_MT_add)
559 bpy.types.register(SEQUENCER_MT_add_effect)
560 bpy.types.register(SEQUENCER_MT_strip)
561
562 bpy.types.register(SEQUENCER_PT_edit) # sequencer panels
563 bpy.types.register(SEQUENCER_PT_effect)
564 bpy.types.register(SEQUENCER_PT_input)
565 bpy.types.register(SEQUENCER_PT_filter)
566 bpy.types.register(SEQUENCER_PT_proxy)
567
568 bpy.types.register(SEQUENCER_PT_view) # view panels