Merging r47581 through r47603 from trunk into soc-2011-tomato
[blender.git] / release / scripts / startup / bl_ui / space_clip.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-80 compliant>
20
21 import bpy
22 from bpy.types import Panel, Header, Menu
23
24
25 class CLIP_HT_header(Header):
26     bl_space_type = 'CLIP_EDITOR'
27
28     def _draw_tracking(self, context):
29         layout = self.layout
30
31         sc = context.space_data
32         clip = sc.clip
33
34         row = layout.row(align=True)
35         row.template_header()
36
37         if context.area.show_menus:
38             sub = row.row(align=True)
39             sub.menu("CLIP_MT_view")
40
41             if sc.view == 'CLIP':
42                 if clip:
43                     sub.menu("CLIP_MT_select")
44                     sub.menu("CLIP_MT_clip")
45                     sub.menu("CLIP_MT_track")
46                     sub.menu("CLIP_MT_reconstruction")
47                 else:
48                     sub.menu("CLIP_MT_clip")
49
50         row = layout.row()
51         row.template_ID(sc, "clip", open='clip.open')
52
53         if clip:
54             tracking = clip.tracking
55             active_object = tracking.objects.active
56
57             if sc.view == 'CLIP':
58                 layout.prop(sc, "mode", text="")
59                 layout.prop(sc, "view", text="", expand=True)
60                 layout.prop(sc, "pivot_point", text="", icon_only=True)
61
62                 r = active_object.reconstruction
63
64                 if r.is_valid and sc.view == 'CLIP':
65                     layout.label(text="Average solve error: %.4f" %
66                                  (r.average_error))
67             elif sc.view == 'GRAPH':
68                 layout.prop(sc, "view", text="", expand=True)
69
70                 row = layout.row(align=True)
71
72                 if sc.show_filters:
73                     row.prop(sc, "show_filters", icon='DISCLOSURE_TRI_DOWN',
74                              text="Filters")
75
76                     sub = row.column()
77                     sub.active = clip.tracking.reconstruction.is_valid
78                     sub.prop(sc, "show_graph_frames", icon='SEQUENCE', text="")
79
80                     row.prop(sc, "show_graph_tracks", icon='ANIM', text="")
81                 else:
82                     row.prop(sc, "show_filters", icon='DISCLOSURE_TRI_RIGHT',
83                              text="Filters")
84             elif sc.view == 'DOPESHEET':
85                 layout.prop(sc, "view", text="", expand=True)
86
87                 layout.label(text="Sort by:")
88                 layout.prop(sc, "dopesheet_sort_method", text="")
89                 layout.prop(sc, "invert_dopesheet_sort", text="Invert")
90         else:
91             layout.prop(sc, "view", text="", expand=True)
92
93     def _draw_masking(self, context):
94         layout = self.layout
95
96         toolsettings = context.tool_settings
97         sc = context.space_data
98         clip = sc.clip
99
100         row = layout.row(align=True)
101         row.template_header()
102
103         if context.area.show_menus:
104             sub = row.row(align=True)
105             sub.menu("CLIP_MT_view")
106
107             if clip:
108                 sub.menu("CLIP_MT_select")
109                 sub.menu("CLIP_MT_clip")
110                 sub.menu("CLIP_MT_mask")
111             else:
112                 sub.menu("CLIP_MT_clip")
113
114         row = layout.row()
115         row.template_ID(sc, "clip", open='clip.open')
116
117         layout.prop(sc, "mode", text="")
118
119         row = layout.row()
120         row.template_ID(sc, "mask", new="mask.new")
121
122         layout.prop(sc, "pivot_point", text="", icon_only=True)
123
124         row = layout.row(align=True)
125         row.prop(toolsettings, "use_proportional_edit_mask",
126                  text="", icon_only=True)
127         if toolsettings.use_proportional_edit_mask:
128             row.prop(toolsettings, "proportional_edit_falloff",
129                      text="", icon_only=True)
130
131     def draw(self, context):
132         layout = self.layout
133
134         sc = context.space_data
135
136         if sc.mode in {'TRACKING', 'RECONSTRUCTION', 'DISTORTION'}:
137             self._draw_tracking(context)
138         else:
139             self._draw_masking(context)
140
141         layout.template_running_jobs()
142
143
144 class CLIP_PT_clip_view_panel:
145
146     @classmethod
147     def poll(cls, context):
148         sc = context.space_data
149         clip = sc.clip
150
151         return clip and sc.view == 'CLIP'
152
153
154 class CLIP_PT_mask_view_panel:
155
156     @classmethod
157     def poll(cls, context):
158         sc = context.space_data
159         clip = sc.clip
160
161         return clip and sc.view == 'CLIP' and sc.mode == 'MASKEDIT'
162
163
164 class CLIP_PT_tracking_panel:
165
166     @classmethod
167     def poll(cls, context):
168         sc = context.space_data
169         clip = sc.clip
170
171         return clip and sc.mode == 'TRACKING' and sc.view == 'CLIP'
172
173
174 class CLIP_PT_reconstruction_panel:
175
176     @classmethod
177     def poll(cls, context):
178         sc = context.space_data
179         clip = sc.clip
180
181         return clip and sc.mode == 'RECONSTRUCTION' and sc.view == 'CLIP'
182
183
184 class CLIP_PT_tools_marker(CLIP_PT_tracking_panel, Panel):
185     bl_space_type = 'CLIP_EDITOR'
186     bl_region_type = 'TOOLS'
187     bl_label = "Marker"
188
189     def draw(self, context):
190         sc = context.space_data
191         clip = sc.clip
192         settings = clip.tracking.settings
193         layout = self.layout
194
195         col = layout.column(align=True)
196         col.operator("clip.add_marker_move")
197         col.operator("clip.detect_features")
198         col.operator("clip.delete_track")
199
200         box = layout.box()
201         row = box.row(align=True)
202         row.prop(settings, "show_default_expanded", text="", emboss=False)
203         row.label(text="Tracking Settings")
204
205         if settings.show_default_expanded:
206             col = box.column()
207             row = col.row(align=True)
208             label = CLIP_MT_tracking_settings_presets.bl_label
209             row.menu('CLIP_MT_tracking_settings_presets', text=label)
210             row.operator("clip.tracking_settings_preset_add",
211                          text="", icon='ZOOMIN')
212             props = row.operator("clip.tracking_settings_preset_add",
213                                  text="", icon='ZOOMOUT')
214             props.remove_active = True
215
216             col.separator()
217
218             row = col.row(align=True)
219             row.prop(settings, "use_default_red_channel",
220                      text="R", toggle=True)
221             row.prop(settings, "use_default_green_channel",
222                      text="G", toggle=True)
223             row.prop(settings, "use_default_blue_channel",
224                      text="B", toggle=True)
225
226             col.separator()
227
228             sub = col.column(align=True)
229             sub.prop(settings, "default_pattern_size")
230             sub.prop(settings, "default_search_size")
231
232             col.label(text="Tracker:")
233             col.prop(settings, "default_motion_model")
234             col.prop(settings, "default_use_brute")
235             col.prop(settings, "default_use_normalization")
236             col.prop(settings, "default_correlation_min")
237
238             col.separator()
239
240             sub = col.column(align=True)
241             sub.prop(settings, "default_frames_limit")
242             sub.prop(settings, "default_margin")
243
244             col.label(text="Match:")
245             col.prop(settings, "default_pattern_match", text="")
246
247             col.separator()
248             col.operator('clip.track_settings_as_default',
249                          text="Copy From Active Track")
250
251
252 class CLIP_PT_tools_tracking(CLIP_PT_tracking_panel, Panel):
253     bl_space_type = 'CLIP_EDITOR'
254     bl_region_type = 'TOOLS'
255     bl_label = "Track"
256
257     def draw(self, context):
258         layout = self.layout
259
260         row = layout.row(align=True)
261
262         props = row.operator("clip.track_markers", text="", icon='FRAME_PREV')
263         props.backwards = True
264         props = row.operator("clip.track_markers", text="",
265                              icon='PLAY_REVERSE')
266         props.backwards = True
267         props.sequence = True
268         props = row.operator("clip.track_markers", text="", icon='PLAY')
269         props.backwards = False
270         props.sequence = True
271         row.operator("clip.track_markers", text="", icon='FRAME_NEXT')
272
273         col = layout.column(align=True)
274         props = col.operator("clip.clear_track_path", text="Clear After")
275         props.action = 'REMAINED'
276
277         props = col.operator("clip.clear_track_path", text="Clear Before")
278         props.action = 'UPTO'
279         col.operator("clip.clear_track_path", text="Clear").action = 'ALL'
280
281         layout.operator("clip.join_tracks", text="Join")
282
283
284 class CLIP_PT_tools_solve(CLIP_PT_tracking_panel, Panel):
285     bl_space_type = 'CLIP_EDITOR'
286     bl_region_type = 'TOOLS'
287     bl_label = "Solve"
288
289     def draw(self, context):
290         layout = self.layout
291         clip = context.space_data.clip
292         tracking = clip.tracking
293         settings = tracking.settings
294         tracking_object = tracking.objects.active
295
296         col = layout.column(align=True)
297
298         col.operator("clip.solve_camera",
299                      text="Camera Motion" if tracking_object.is_camera
300                      else "Object Motion")
301         col.operator("clip.clear_solution")
302
303         col = layout.column()
304         col.prop(settings, "use_tripod_solver")
305
306         col = layout.column(align=True)
307         col.active = not settings.use_tripod_solver
308         col.prop(settings, "keyframe_a")
309         col.prop(settings, "keyframe_b")
310
311         col = layout.column(align=True)
312         col.active = (tracking_object.is_camera and
313                       not settings.use_tripod_solver)
314         col.label(text="Refine:")
315         col.prop(settings, "refine_intrinsics", text="")
316
317
318 class CLIP_PT_tools_cleanup(CLIP_PT_tracking_panel, Panel):
319     bl_space_type = 'CLIP_EDITOR'
320     bl_region_type = 'TOOLS'
321     bl_label = "Clean up"
322
323     def draw(self, context):
324         layout = self.layout
325         clip = context.space_data.clip
326         settings = clip.tracking.settings
327
328         layout.operator("clip.clean_tracks")
329
330         layout.prop(settings, 'clean_frames', text="Frames")
331         layout.prop(settings, 'clean_error', text="Error")
332         layout.prop(settings, 'clean_action', text="")
333
334
335 class CLIP_PT_tools_geometry(CLIP_PT_reconstruction_panel, Panel):
336     bl_space_type = 'CLIP_EDITOR'
337     bl_region_type = 'TOOLS'
338     bl_label = "Geometry"
339
340     def draw(self, context):
341         layout = self.layout
342
343         layout.operator("clip.bundles_to_mesh")
344         layout.operator("clip.track_to_empty")
345
346
347 class CLIP_PT_tools_orientation(CLIP_PT_reconstruction_panel, Panel):
348     bl_space_type = 'CLIP_EDITOR'
349     bl_region_type = 'TOOLS'
350     bl_label = "Orientation"
351
352     def draw(self, context):
353         sc = context.space_data
354         layout = self.layout
355         settings = sc.clip.tracking.settings
356
357         col = layout.column(align=True)
358         row = col.row()
359         props = row.operator("clip.set_plane", text="Floor")
360         props.plane = 'FLOOR'
361         props = row.operator("clip.set_plane", text="Wall")
362         props.plane = 'WALL'
363         col.operator("clip.set_origin")
364
365         row = col.row()
366         row.operator("clip.set_axis", text="Set X Axis").axis = 'X'
367         row.operator("clip.set_axis", text="Set Y Axis").axis = 'Y'
368
369         layout.separator()
370
371         col = layout.column()
372         col.operator("clip.set_scale")
373         col.prop(settings, "distance")
374
375
376 class CLIP_PT_tools_object(CLIP_PT_reconstruction_panel, Panel):
377     bl_space_type = 'CLIP_EDITOR'
378     bl_region_type = 'TOOLS'
379     bl_label = "Object"
380
381     @classmethod
382     def poll(cls, context):
383         if CLIP_PT_reconstruction_panel.poll(context):
384             sc = context.space_data
385             clip = sc.clip
386
387             tracking_object = clip.tracking.objects.active
388
389             return not tracking_object.is_camera
390
391         return False
392
393     def draw(self, context):
394         layout = self.layout
395
396         sc = context.space_data
397         clip = sc.clip
398         tracking_object = clip.tracking.objects.active
399         settings = sc.clip.tracking.settings
400
401         col = layout.column()
402
403         col.prop(tracking_object, "scale")
404
405         col.separator()
406
407         col.operator("clip.set_solution_scale", text="Set Scale")
408         col.prop(settings, "object_distance")
409
410
411 class CLIP_PT_tools_mask(CLIP_PT_mask_view_panel, Panel):
412     bl_space_type = 'CLIP_EDITOR'
413     bl_region_type = 'TOOLS'
414     bl_label = "Mask Tools"
415
416     def draw(self, context):
417         layout = self.layout
418
419         col = layout.column(align=True)
420         col.label(text="Transform:")
421         col.operator("transform.translate")
422         col.operator("transform.rotate")
423         col.operator("transform.resize", text="Scale")
424         props = col.operator("transform.transform", text="Shrink/Fatten")
425         props.mode = 'MASK_SHRINKFATTEN'
426
427         col = layout.column(align=True)
428         col.label(text="Spline:")
429         col.operator("mask.delete")
430         col.operator("mask.cyclic_toggle")
431         col.operator("mask.switch_direction")
432
433         col = layout.column(align=True)
434         col.label(text="Parenting:")
435         col.operator("mask.parent_set")
436         col.operator("mask.parent_clear")
437
438
439 class CLIP_PT_tools_grease_pencil(Panel):
440     bl_space_type = 'CLIP_EDITOR'
441     bl_region_type = 'TOOLS'
442     bl_label = "Grease Pencil"
443
444     @classmethod
445     def poll(cls, context):
446         sc = context.space_data
447         clip = sc.clip
448
449         if not clip:
450             return False
451
452         if sc.mode == 'DISTORTION':
453             return sc.view == 'CLIP'
454         elif sc.mode == 'MASKEDIT':
455             return True
456
457         return False
458
459     def draw(self, context):
460         layout = self.layout
461
462         col = layout.column(align=True)
463
464         row = col.row(align=True)
465         row.operator("gpencil.draw", text="Draw").mode = 'DRAW'
466         row.operator("gpencil.draw", text="Line").mode = 'DRAW_STRAIGHT'
467
468         row = col.row(align=True)
469         row.operator("gpencil.draw", text="Poly").mode = 'DRAW_POLY'
470         row.operator("gpencil.draw", text="Erase").mode = 'ERASER'
471
472         row = col.row()
473         row.prop(context.tool_settings, "use_grease_pencil_sessions")
474
475
476 class CLIP_PT_objects(CLIP_PT_clip_view_panel, Panel):
477     bl_space_type = 'CLIP_EDITOR'
478     bl_region_type = 'UI'
479     bl_label = "Objects"
480     bl_options = {'DEFAULT_CLOSED'}
481
482     def draw(self, context):
483         layout = self.layout
484
485         sc = context.space_data
486         tracking = sc.clip.tracking
487
488         row = layout.row()
489         row.template_list(tracking, "objects",
490                           tracking, "active_object_index", rows=3)
491
492         sub = row.column(align=True)
493
494         sub.operator("clip.tracking_object_new", icon='ZOOMIN', text="")
495         sub.operator("clip.tracking_object_remove", icon='ZOOMOUT', text="")
496
497         active = tracking.objects.active
498         if active:
499             layout.prop(active, "name")
500
501
502 class CLIP_PT_track(CLIP_PT_tracking_panel, Panel):
503     bl_space_type = 'CLIP_EDITOR'
504     bl_region_type = 'UI'
505     bl_label = "Track"
506
507     def draw(self, context):
508         layout = self.layout
509         sc = context.space_data
510         clip = context.space_data.clip
511         act_track = clip.tracking.tracks.active
512
513         if not act_track:
514             layout.active = False
515             layout.label(text="No active track")
516             return
517
518         row = layout.row()
519         row.prop(act_track, "name", text="")
520
521         sub = row.row(align=True)
522
523         sub.template_marker(sc, "clip", sc.clip_user, act_track, True)
524
525         icon = 'LOCKED' if act_track.lock else 'UNLOCKED'
526         sub.prop(act_track, "lock", text="", icon=icon)
527
528         layout.template_track(sc, "scopes")
529
530         row = layout.row(align=True)
531         sub = row.row()
532         sub.prop(act_track, "use_red_channel", text="R", toggle=True)
533         sub.prop(act_track, "use_green_channel", text="G", toggle=True)
534         sub.prop(act_track, "use_blue_channel", text="B", toggle=True)
535
536         row.separator()
537
538         sub = row.row()
539         sub.prop(act_track, "use_grayscale_preview", text="B/W", toggle=True)
540
541         layout.separator()
542
543         row = layout.row(align=True)
544         label = bpy.types.CLIP_MT_track_color_presets.bl_label
545         row.menu('CLIP_MT_track_color_presets', text=label)
546         row.menu('CLIP_MT_track_color_specials', text="", icon='DOWNARROW_HLT')
547         row.operator("clip.track_color_preset_add", text="", icon='ZOOMIN')
548         props = row.operator("clip.track_color_preset_add",
549                              text="", icon='ZOOMOUT')
550         props.remove_active = True
551
552         row = layout.row()
553         row.prop(act_track, "use_custom_color")
554         if act_track.use_custom_color:
555             row.prop(act_track, "color", text="")
556
557         if act_track.has_bundle:
558             label_text = "Average Error: %.4f" % (act_track.average_error)
559             layout.label(text=label_text)
560
561
562 class CLIP_PT_track_settings(CLIP_PT_tracking_panel, Panel):
563     bl_space_type = 'CLIP_EDITOR'
564     bl_region_type = 'UI'
565     bl_label = "Tracking Settings"
566     bl_options = {'DEFAULT_CLOSED'}
567
568     def draw(self, context):
569         layout = self.layout
570         clip = context.space_data.clip
571         settings = clip.tracking.settings
572
573         col = layout.column()
574
575         active = clip.tracking.tracks.active
576         if active:
577             col.prop(active, "motion_model")
578             col.prop(active, "use_brute")
579             col.prop(active, "use_normalization")
580             col.prop(active, "correlation_min")
581
582             col.separator()
583             col.prop(active, "frames_limit")
584             col.prop(active, "margin")
585             col.prop(active, "pattern_match", text="Match")
586
587         col.prop(settings, "speed")
588
589
590 class CLIP_PT_tracking_camera(Panel):
591     bl_space_type = 'CLIP_EDITOR'
592     bl_region_type = 'UI'
593     bl_label = "Camera Data"
594     bl_options = {'DEFAULT_CLOSED'}
595
596     @classmethod
597     def poll(cls, context):
598         if CLIP_PT_clip_view_panel.poll(context):
599             sc = context.space_data
600
601             return sc.mode in {'TRACKING', 'DISTORTION'} and sc.clip
602
603         return False
604
605     def draw(self, context):
606         layout = self.layout
607
608         sc = context.space_data
609         clip = sc.clip
610
611         row = layout.row(align=True)
612         label = bpy.types.CLIP_MT_camera_presets.bl_label
613         row.menu('CLIP_MT_camera_presets', text=label)
614         row.operator("clip.camera_preset_add", text="", icon='ZOOMIN')
615         props = row.operator("clip.camera_preset_add", text="", icon='ZOOMOUT')
616         props.remove_active = True
617
618         row = layout.row(align=True)
619         sub = row.split(percentage=0.65)
620         if clip.tracking.camera.units == 'MILLIMETERS':
621             sub.prop(clip.tracking.camera, "focal_length")
622         else:
623             sub.prop(clip.tracking.camera, "focal_length_pixels")
624         sub.prop(clip.tracking.camera, "units", text="")
625
626         col = layout.column(align=True)
627         col.label(text="Sensor:")
628         col.prop(clip.tracking.camera, "sensor_width", text="Width")
629         col.prop(clip.tracking.camera, "pixel_aspect")
630
631         col = layout.column()
632         col.label(text="Optical Center:")
633         row = col.row()
634         row.prop(clip.tracking.camera, "principal", text="")
635         col.operator("clip.set_center_principal", text="Center")
636
637         col = layout.column(align=True)
638         col.label(text="Lens Distortion:")
639         col.prop(clip.tracking.camera, "k1")
640         col.prop(clip.tracking.camera, "k2")
641         col.prop(clip.tracking.camera, "k3")
642
643
644 class CLIP_PT_mask_layers(Panel):
645     bl_space_type = 'CLIP_EDITOR'
646     bl_region_type = 'UI'
647     bl_label = "Mask Layers"
648
649     @classmethod
650     def poll(cls, context):
651         sc = context.space_data
652
653         return sc.mask and sc.mode == 'MASKEDIT'
654
655     def draw(self, context):
656         layout = self.layout
657
658         sc = context.space_data
659         mask = sc.mask
660
661         row = layout.row()
662         row.template_list(mask, "layers",
663                           mask, "active_layer_index", rows=3)
664
665         sub = row.column(align=True)
666
667         sub.operator("mask.layer_new", icon='ZOOMIN', text="")
668         sub.operator("mask.layer_remove", icon='ZOOMOUT', text="")
669
670         active = mask.layers.active
671         if active:
672             layout.prop(active, "name")
673
674             # blending
675             row = layout.row(align=True)
676             row.prop(active, "alpha")
677             row.prop(active, "invert", text="", icon='IMAGE_ALPHA')
678
679             layout.prop(active, "blend")
680
681
682 class CLIP_PT_active_mask_spline(Panel):
683     bl_space_type = 'CLIP_EDITOR'
684     bl_region_type = 'UI'
685     bl_label = "Active Spline"
686
687     @classmethod
688     def poll(cls, context):
689         sc = context.space_data
690         mask = sc.mask
691
692         if mask and sc.mode == 'MASKEDIT':
693             return mask.layers.active and mask.layers.active.splines.active
694
695         return False
696
697     def draw(self, context):
698         layout = self.layout
699
700         sc = context.space_data
701         mask = sc.mask
702         spline = mask.layers.active.splines.active
703
704         col = layout.column()
705         col.prop(spline, "weight_interpolation")
706         col.prop(spline, "use_cyclic")
707
708
709 class CLIP_PT_active_mask_point(Panel):
710     bl_space_type = 'CLIP_EDITOR'
711     bl_region_type = 'UI'
712     bl_label = "Active Point"
713
714     @classmethod
715     def poll(cls, context):
716         sc = context.space_data
717         mask = sc.mask
718
719         if mask and sc.mode == 'MASKEDIT':
720             return mask.layers.active and mask.layers.active.splines.active_point
721
722         return False
723
724     def draw(self, context):
725         layout = self.layout
726
727         sc = context.space_data
728         mask = sc.mask
729         point = mask.layers.active.splines.active_point
730         parent = point.parent
731
732         col = layout.column()
733         col.prop(point, "handle_type")
734
735         col = layout.column()
736         # Currently only parenting yo movie clip is allowed, so do not
737         # ver-oplicate things for now and use single template_ID
738         #col.template_any_ID(parent, "id", "id_type", text="")
739
740         col.label("Parent:")
741         col.prop(parent, "id", text="")
742
743         if parent.id_type == 'MOVIECLIP' and parent.id:
744             clip = parent.id
745             tracking = clip.tracking
746
747             col.prop_search(parent, "parent", tracking,
748                             "objects", icon='OBJECT_DATA', text="Object:")
749
750             if parent.parent in tracking.objects:
751                 object = tracking.objects[parent.parent]
752                 col.prop_search(parent, "sub_parent", object,
753                                 "tracks", icon='ANIM_DATA', text="Track:")
754             else:
755                 col.prop_search(parent, "sub_parent", tracking,
756                                 "tracks", icon='ANIM_DATA', text="Track:")
757
758
759 class CLIP_PT_display(CLIP_PT_clip_view_panel, Panel):
760     bl_space_type = 'CLIP_EDITOR'
761     bl_region_type = 'UI'
762     bl_label = "Display"
763
764     def draw(self, context):
765         layout = self.layout
766         sc = context.space_data
767
768         row = layout.row(align=True)
769         sub = row.row()
770         sub.prop(sc, "show_red_channel", text="R", toggle=True)
771         sub.prop(sc, "show_green_channel", text="G", toggle=True)
772         sub.prop(sc, "show_blue_channel", text="B", toggle=True)
773
774         row.separator()
775
776         sub = row.row()
777         sub.prop(sc, "use_grayscale_preview", text="B/W", toggle=True)
778
779         col = layout.column(align=True)
780
781         col.prop(sc, "show_disabled", "Disabled Tracks")
782         col.prop(sc, "show_names", text="Names and Status")
783         col.prop(sc, "show_bundles", text="3D Markers")
784
785         col.prop(sc, "use_mute_footage", text="Mute Footage")
786         col.prop(sc, "lock_selection")
787
788         if sc.view == 'GRAPH':
789             col.prop(sc, "lock_time_cursor")
790
791         if sc.mode == 'DISTORTION':
792             col.prop(sc, "show_grid", text="Grid")
793             col.prop(sc, "use_manual_calibration")
794         elif sc.mode == 'RECONSTRUCTION':
795             col.prop(sc, "show_stable", text="Stable")
796
797         clip = sc.clip
798         if clip:
799             col.label(text="Display Aspect Ratio:")
800             row = col.row()
801             row.prop(clip, "display_aspect", text="")
802
803         if sc.mode == 'MASKEDIT':
804             col = layout.column()
805             col.prop(sc, "mask_draw_type", text="")
806             col.prop(sc, "show_mask_smooth")
807
808
809 # TODO, move into its own file
810 class CLIP_PT_mask(CLIP_PT_mask_view_panel, Panel):
811     bl_space_type = 'CLIP_EDITOR'
812     bl_region_type = 'UI'
813     bl_label = "Mask Settings"
814     bl_options = {'DEFAULT_CLOSED'}
815
816     def draw(self, context):
817         layout = self.layout
818
819         sc = context.space_data
820         mask = sc.mask
821
822         col = layout.column(align=True)
823         col.prop(mask, "frame_start")
824         col.prop(mask, "frame_end")
825
826
827 class CLIP_PT_marker_display(CLIP_PT_clip_view_panel, Panel):
828     bl_space_type = 'CLIP_EDITOR'
829     bl_region_type = 'UI'
830     bl_label = "Marker Display"
831
832     @classmethod
833     def poll(cls, context):
834         sc = context.space_data
835
836         return sc.mode != 'MASKEDIT'
837
838     def draw(self, context):
839         layout = self.layout
840         sc = context.space_data
841
842         col = layout.column(align=True)
843
844         row = col.row()
845         row.prop(sc, "show_marker_pattern", text="Pattern")
846         row.prop(sc, "show_marker_search", text="Search")
847
848         col.prop(sc, "show_tiny_markers", text="Thin Markers")
849         col.prop(sc, "show_track_path", text="Path")
850
851         row = col.row()
852         row.active = sc.show_track_path
853         row.prop(sc, "path_length", text="Length")
854
855
856 class CLIP_PT_stabilization(CLIP_PT_reconstruction_panel, Panel):
857     bl_space_type = 'CLIP_EDITOR'
858     bl_region_type = 'UI'
859     bl_label = "2D Stabilization"
860     bl_options = {'DEFAULT_CLOSED'}
861
862     def draw_header(self, context):
863         stab = context.space_data.clip.tracking.stabilization
864
865         self.layout.prop(stab, "use_2d_stabilization", text="")
866
867     def draw(self, context):
868         layout = self.layout
869
870         tracking = context.space_data.clip.tracking
871         stab = tracking.stabilization
872
873         layout.active = stab.use_2d_stabilization
874
875         row = layout.row()
876         row.template_list(stab, "tracks", stab, "active_track_index", rows=3)
877
878         sub = row.column(align=True)
879
880         sub.operator("clip.stabilize_2d_add", icon='ZOOMIN', text="")
881         sub.operator("clip.stabilize_2d_remove", icon='ZOOMOUT', text="")
882
883         sub.menu('CLIP_MT_stabilize_2d_specials', text="",
884                  icon='DOWNARROW_HLT')
885
886         layout.prop(stab, "influence_location")
887
888         layout.prop(stab, "use_autoscale")
889         col = layout.column()
890         col.active = stab.use_autoscale
891         col.prop(stab, "scale_max")
892         col.prop(stab, "influence_scale")
893
894         layout.prop(stab, "use_stabilize_rotation")
895         col = layout.column()
896         col.active = stab.use_stabilize_rotation
897
898         row = col.row(align=True)
899         row.prop_search(stab, "rotation_track", tracking, "tracks", text="")
900         row.operator("clip.stabilize_2d_set_rotation", text="", icon='ZOOMIN')
901
902         row = col.row()
903         row.active = stab.rotation_track is not None
904         row.prop(stab, "influence_rotation")
905
906         layout.prop(stab, "filter_type")
907
908
909 class CLIP_PT_marker(CLIP_PT_tracking_panel, Panel):
910     bl_space_type = 'CLIP_EDITOR'
911     bl_region_type = 'UI'
912     bl_label = "Marker"
913     bl_options = {'DEFAULT_CLOSED'}
914
915     def draw(self, context):
916         layout = self.layout
917         sc = context.space_data
918         clip = context.space_data.clip
919         act_track = clip.tracking.tracks.active
920
921         if act_track:
922             layout.template_marker(sc, "clip", sc.clip_user, act_track, False)
923         else:
924             layout.active = False
925             layout.label(text="No active track")
926
927
928 class CLIP_PT_proxy(CLIP_PT_clip_view_panel, Panel):
929     bl_space_type = 'CLIP_EDITOR'
930     bl_region_type = 'UI'
931     bl_label = "Proxy / Timecode"
932     bl_options = {'DEFAULT_CLOSED'}
933
934     def draw_header(self, context):
935         sc = context.space_data
936
937         self.layout.prop(sc.clip, "use_proxy", text="")
938
939     def draw(self, context):
940         layout = self.layout
941         sc = context.space_data
942         clip = sc.clip
943
944         layout.active = clip.use_proxy
945
946         layout.label(text="Build Original:")
947
948         row = layout.row(align=True)
949         row.prop(clip.proxy, "build_25", toggle=True)
950         row.prop(clip.proxy, "build_50", toggle=True)
951         row.prop(clip.proxy, "build_75", toggle=True)
952         row.prop(clip.proxy, "build_100", toggle=True)
953
954         layout.label(text="Build Undistorted:")
955
956         row = layout.row(align=True)
957         row.prop(clip.proxy, "build_undistorted_25", toggle=True)
958         row.prop(clip.proxy, "build_undistorted_50", toggle=True)
959         row.prop(clip.proxy, "build_undistorted_75", toggle=True)
960         row.prop(clip.proxy, "build_undistorted_100", toggle=True)
961
962         layout.prop(clip.proxy, "quality")
963
964         layout.prop(clip, 'use_proxy_custom_directory')
965         if clip.use_proxy_custom_directory:
966             layout.prop(clip.proxy, "directory")
967
968         layout.operator("clip.rebuild_proxy", text="Build Proxy")
969
970         if clip.source == 'MOVIE':
971             col = layout.column()
972
973             col.label(text="Use timecode index:")
974             col.prop(clip.proxy, "timecode", text="")
975
976         col = layout.column()
977         col.label(text="Proxy render size:")
978
979         col.prop(sc.clip_user, "proxy_render_size", text="")
980         col.prop(sc.clip_user, "use_render_undistorted")
981
982
983 class CLIP_PT_footage(CLIP_PT_clip_view_panel, Panel):
984     bl_space_type = 'CLIP_EDITOR'
985     bl_region_type = 'UI'
986     bl_label = "Footage Settings"
987     bl_options = {'DEFAULT_CLOSED'}
988
989     def draw(self, context):
990         layout = self.layout
991
992         sc = context.space_data
993         clip = sc.clip
994
995         col = layout.column()
996         col.template_movieclip(sc, "clip", compact=True)
997         col.prop(clip, "start_frame")
998
999
1000 class CLIP_PT_tools_clip(CLIP_PT_clip_view_panel, Panel):
1001     bl_space_type = 'CLIP_EDITOR'
1002     bl_region_type = 'TOOLS'
1003     bl_label = "Clip"
1004
1005     def draw(self, context):
1006         layout = self.layout
1007
1008         layout.operator("clip.set_viewport_background")
1009         layout.operator("clip.setup_tracking_scene")
1010
1011
1012 class CLIP_MT_view(Menu):
1013     bl_label = "View"
1014
1015     def draw(self, context):
1016         layout = self.layout
1017         sc = context.space_data
1018
1019         if sc.view == 'CLIP':
1020             layout.operator("clip.properties", icon='MENU_PANEL')
1021             layout.operator("clip.tools", icon='MENU_PANEL')
1022             layout.separator()
1023
1024             layout.operator("clip.view_selected")
1025             layout.operator("clip.view_all")
1026
1027             layout.separator()
1028             layout.operator("clip.view_zoom_in")
1029             layout.operator("clip.view_zoom_out")
1030
1031             layout.separator()
1032
1033             ratios = ((1, 8), (1, 4), (1, 2), (1, 1), (2, 1), (4, 1), (8, 1))
1034
1035             for a, b in ratios:
1036                 text = "Zoom %d:%d" % (a, b)
1037                 layout.operator("clip.view_zoom_ratio", text=text).ratio = a / b
1038         else:
1039             layout.prop(sc, "show_seconds")
1040             layout.separator()
1041
1042         layout.separator()
1043         layout.operator("screen.area_dupli")
1044         layout.operator("screen.screen_full_area")
1045
1046
1047 class CLIP_MT_clip(Menu):
1048     bl_label = "Clip"
1049
1050     def draw(self, context):
1051         layout = self.layout
1052
1053         sc = context.space_data
1054         clip = sc.clip
1055
1056         layout.operator("clip.open")
1057
1058         if clip:
1059             layout.operator("clip.reload")
1060             layout.menu("CLIP_MT_proxy")
1061
1062
1063 class CLIP_MT_proxy(Menu):
1064     bl_label = "Proxy"
1065
1066     def draw(self, context):
1067         layout = self.layout
1068
1069         layout.operator("clip.rebuild_proxy")
1070         layout.operator("clip.delete_proxy")
1071
1072
1073 class CLIP_MT_track(Menu):
1074     bl_label = "Track"
1075
1076     def draw(self, context):
1077         layout = self.layout
1078
1079         layout.operator("clip.clear_solution")
1080         layout.operator("clip.solve_camera")
1081
1082         layout.separator()
1083         props = layout.operator("clip.clear_track_path", text="Clear After")
1084         props.action = 'REMAINED'
1085
1086         props = layout.operator("clip.clear_track_path", text="Clear Before")
1087         props.action = 'UPTO'
1088
1089         props = layout.operator("clip.clear_track_path",
1090             text="Clear Track Path")
1091         props.action = 'ALL'
1092
1093         layout.separator()
1094         layout.operator("clip.join_tracks")
1095
1096         layout.separator()
1097         layout.operator("clip.clean_tracks")
1098
1099         layout.separator()
1100         layout.operator("clip.copy_tracks")
1101         layout.operator("clip.paste_tracks")
1102
1103         layout.separator()
1104         props = layout.operator("clip.track_markers",
1105             text="Track Frame Backwards")
1106         props.backwards = True
1107
1108         props = layout.operator("clip.track_markers", text="Track Backwards")
1109         props.backwards = True
1110         props.sequence = True
1111
1112         props = layout.operator("clip.track_markers", text="Track Forwards")
1113         props.sequence = True
1114         layout.operator("clip.track_markers", text="Track Frame Forwards")
1115
1116         layout.separator()
1117         layout.operator("clip.delete_track")
1118         layout.operator("clip.delete_marker")
1119
1120         layout.separator()
1121         layout.operator("clip.add_marker_move")
1122
1123         layout.separator()
1124         layout.menu("CLIP_MT_track_visibility")
1125         layout.menu("CLIP_MT_track_transform")
1126
1127
1128 class CLIP_MT_reconstruction(Menu):
1129     bl_label = "Reconstruction"
1130
1131     def draw(self, context):
1132         layout = self.layout
1133
1134         layout.operator("clip.set_origin")
1135         props = layout.operator("clip.set_plane", text="Set Floor")
1136         props.plane = 'FLOOR'
1137         props = layout.operator("clip.set_plane", text="Set Wall")
1138         props.plane = 'WALL'
1139
1140         layout.operator("clip.set_axis", text="Set X Axis").axis = "X"
1141         layout.operator("clip.set_axis", text="Set Y Axis").axis = "Y"
1142
1143         layout.operator("clip.set_scale")
1144
1145         layout.separator()
1146
1147         layout.operator("clip.track_to_empty")
1148         layout.operator("clip.bundles_to_mesh")
1149
1150
1151 class CLIP_MT_track_visibility(Menu):
1152     bl_label = "Show/Hide"
1153
1154     def draw(self, context):
1155         layout = self.layout
1156
1157         layout.operator("clip.hide_tracks_clear", text="Show Hidden")
1158         layout.operator("clip.hide_tracks", text="Hide Selected")
1159
1160         props = layout.operator("clip.hide_tracks", text="Hide Unselected")
1161         props.unselected = True
1162
1163
1164 class CLIP_MT_track_transform(Menu):
1165     bl_label = "Transform"
1166
1167     def draw(self, context):
1168         layout = self.layout
1169
1170         layout.operator("transform.translate")
1171         layout.operator("transform.resize")
1172
1173
1174 class CLIP_MT_select(Menu):
1175     bl_label = "Select"
1176
1177     def draw(self, context):
1178         layout = self.layout
1179         sc = context.space_data
1180
1181         if sc.mode == 'MASKEDIT':
1182             layout.operator("mask.select_border")
1183             layout.operator("mask.select_circle")
1184
1185             layout.separator()
1186
1187             layout.operator("mask.select_all").action = 'TOGGLE'
1188             layout.operator("mask.select_all", text="Inverse").action = 'INVERT'
1189         else:
1190             layout.operator("clip.select_border")
1191             layout.operator("clip.select_circle")
1192
1193             layout.separator()
1194
1195             layout.operator("clip.select_all").action = 'TOGGLE'
1196             layout.operator("clip.select_all", text="Inverse").action = 'INVERT'
1197
1198             layout.menu("CLIP_MT_select_grouped")
1199
1200
1201 class CLIP_MT_select_grouped(Menu):
1202     bl_label = "Select Grouped"
1203
1204     def draw(self, context):
1205         layout = self.layout
1206
1207         layout.operator_enum("clip.select_grouped", "group")
1208
1209
1210 class CLIP_MT_tracking_specials(Menu):
1211     bl_label = "Specials"
1212
1213     @classmethod
1214     def poll(cls, context):
1215         return context.space_data.clip
1216
1217     def draw(self, context):
1218         layout = self.layout
1219
1220         props = layout.operator("clip.disable_markers",
1221                                 text="Enable Markers")
1222         props.action = 'ENABLE'
1223
1224         props = layout.operator("clip.disable_markers", text="Disable markers")
1225         props.action = 'DISABLE'
1226
1227         layout.separator()
1228         layout.operator("clip.set_origin")
1229
1230         layout.separator()
1231         layout.operator("clip.hide_tracks")
1232         layout.operator("clip.hide_tracks_clear", text="Show Tracks")
1233
1234         layout.separator()
1235         props = layout.operator("clip.lock_tracks", text="Lock Tracks")
1236         props.action = 'LOCK'
1237
1238         props = layout.operator("clip.lock_tracks", text="Unlock Tracks")
1239         props.action = 'UNLOCK'
1240
1241
1242 class CLIP_MT_mask(Menu):
1243     bl_label = "Mask"
1244
1245     def draw(self, context):
1246         layout = self.layout
1247
1248         layout.operator("mask.delete")
1249
1250         layout.separator()
1251         layout.operator("mask.cyclic_toggle")
1252         layout.operator("mask.switch_direction")
1253         layout.operator("mask.feather_weight_clear")  # TODO, better place?
1254
1255         layout.separator()
1256         layout.operator("mask.parent_clear")
1257         layout.operator("mask.parent_set")
1258
1259         layout.separator()
1260         layout.menu("CLIP_MT_mask_visibility")
1261         layout.menu("CLIP_MT_mask_transform")
1262         layout.menu("CLIP_MT_mask_animation")
1263
1264
1265 class CLIP_MT_mask_visibility(Menu):
1266     bl_label = "Show/Hide"
1267
1268     def draw(self, context):
1269         layout = self.layout
1270
1271         layout.operator("mask.hide_view_clear", text="Show Hidden")
1272         layout.operator("mask.hide_view_set", text="Hide Selected")
1273
1274         props = layout.operator("mask.hide_view_set", text="Hide Unselected")
1275         props.unselected = True
1276
1277
1278 class CLIP_MT_mask_transform(Menu):
1279     bl_label = "Transform"
1280
1281     def draw(self, context):
1282         layout = self.layout
1283
1284         layout.operator("transform.translate")
1285         layout.operator("transform.rotate")
1286         layout.operator("transform.resize")
1287         props = layout.operator("transform.transform", text="Shrink/Fatten")
1288         props.mode = 'MASK_SHRINKFATTEN'
1289
1290
1291 class CLIP_MT_mask_animation(Menu):
1292     bl_label = "Animation"
1293
1294     def draw(self, context):
1295         layout = self.layout
1296
1297         layout.operator("mask.shape_key_clear")
1298         layout.operator("mask.shape_key_insert")
1299         layout.operator("mask.shape_key_feather_reset")
1300
1301
1302 class CLIP_MT_camera_presets(Menu):
1303     """Predefined tracking camera intrinsics"""
1304     bl_label = "Camera Presets"
1305     preset_subdir = "tracking_camera"
1306     preset_operator = "script.execute_preset"
1307     draw = Menu.draw_preset
1308
1309
1310 class CLIP_MT_track_color_presets(Menu):
1311     """Predefined track color"""
1312     bl_label = "Color Presets"
1313     preset_subdir = "tracking_track_color"
1314     preset_operator = "script.execute_preset"
1315     draw = Menu.draw_preset
1316
1317
1318 class CLIP_MT_tracking_settings_presets(Menu):
1319     """Predefined tracking settings"""
1320     bl_label = "Tracking Presets"
1321     preset_subdir = "tracking_settings"
1322     preset_operator = "script.execute_preset"
1323     draw = Menu.draw_preset
1324
1325
1326 class CLIP_MT_track_color_specials(Menu):
1327     bl_label = "Track Color Specials"
1328
1329     def draw(self, context):
1330         layout = self.layout
1331
1332         layout.operator('clip.track_copy_color', icon='COPY_ID')
1333
1334
1335 class CLIP_MT_stabilize_2d_specials(Menu):
1336     bl_label = "Track Color Specials"
1337
1338     def draw(self, context):
1339         layout = self.layout
1340
1341         layout.operator('clip.stabilize_2d_select')
1342
1343 if __name__ == "__main__":  # only for live edit.
1344     bpy.utils.register_module(__name__)