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