Camera tracking integration
[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 compliant>
20 import bpy
21 from bpy.types import Operator, Panel, Header, Menu
22
23
24 class CLIP_OT_track_to_empty(Operator):
25     bl_idname = "clip.track_to_empty"
26     bl_label = "2D Track to Empty"
27     bl_options = {'UNDO', 'REGISTER'}
28
29     @classmethod
30     def poll(cls, context):
31         if context.space_data.type != 'CLIP_EDITOR':
32             return False
33
34         sc = context.space_data
35         clip = sc.clip
36
37         return clip and clip.tracking.active_track
38
39     def execute(self, context):
40         sc = context.space_data
41         clip = sc.clip
42         track = clip.tracking.active_track
43         constraint = None
44         ob = None
45
46         if track.name in bpy.data.objects:
47             if bpy.data.objects[track.name].type == 'Empty':
48                 ob = bpy.data.objects[track.name]
49
50         if  not ob:
51             ob = bpy.data.objects.new(name=track.name, object_data=None)
52             ob.select = True
53             bpy.context.scene.objects.link(ob)
54             bpy.context.scene.objects.active = ob
55
56         for con in ob.constraints:
57             if con.type == 'FOLLOW_TRACK':
58                 constraint = con
59                 break
60
61         if constraint is None:
62             constraint = ob.constraints.new(type='FOLLOW_TRACK')
63
64         constraint.clip = sc.clip
65         constraint.track = track.name
66         constraint.reference = 'TRACK'
67
68         return {'FINISHED'}
69
70
71 class CLIP_OT_bundles_to_mesh(Operator):
72     bl_idname = "clip.bundles_to_mesh"
73     bl_label = "Bundles to Mesh"
74     bl_options = {'UNDO', 'REGISTER'}
75
76     @classmethod
77     def poll(cls, context):
78         if context.space_data.type != 'CLIP_EDITOR':
79             return False
80
81         sc = context.space_data
82         clip = sc.clip
83
84         return clip
85
86     def execute(self, context):
87         sc = context.space_data
88         clip = sc.clip
89
90         mesh = bpy.data.meshes.new(name="Bundles")
91         for track in clip.tracking.tracks:
92             if track.has_bundle:
93                 mesh.vertices.add(1)
94                 mesh.vertices[-1].co = track.bundle
95
96         ob = bpy.data.objects.new(name="Bundles", object_data=mesh)
97
98         bpy.context.scene.objects.link(ob)
99
100         return {'FINISHED'}
101
102
103 class CLIP_HT_header(Header):
104     bl_space_type = 'CLIP_EDITOR'
105
106     def draw(self, context):
107         layout = self.layout
108
109         sc = context.space_data
110         clip = sc.clip
111
112         row = layout.row(align=True)
113         row.template_header()
114
115         if context.area.show_menus:
116             sub = row.row(align=True)
117             sub.menu("CLIP_MT_view")
118             sub.menu("CLIP_MT_clip")
119
120             if clip:
121                 sub.menu("CLIP_MT_select")
122                 sub.menu("CLIP_MT_track")
123
124         if clip:
125             layout.prop(sc, "mode", text="")
126
127         row = layout.row()
128         row.template_ID(sc, "clip", open='clip.open')
129
130         if clip:
131             r = clip.tracking.reconstruction
132
133             if r.is_reconstructed:
134                 layout.label(text="Average solve error: %.4f" % \
135                     (r.average_error))
136
137         layout.template_running_jobs()
138
139
140 class CLIP_PT_tools(Panel):
141     bl_space_type = 'CLIP_EDITOR'
142     bl_region_type = 'TOOLS'
143     bl_label = "Tools"
144
145     @classmethod
146     def poll(cls, context):
147         sc = context.space_data
148         clip = sc.clip
149
150         return not clip and sc.mode == 'TRACKING'
151
152     def draw(self, context):
153         layout = self.layout
154         layout.operator('clip.open')
155
156
157 class CLIP_PT_tools_marker(Panel):
158     bl_space_type = 'CLIP_EDITOR'
159     bl_region_type = 'TOOLS'
160     bl_label = "Marker"
161
162     @classmethod
163     def poll(cls, context):
164         sc = context.space_data
165         clip = sc.clip
166
167         return clip and sc.mode == 'TRACKING'
168
169     def draw(self, context):
170         layout = self.layout
171
172         col = layout.column(align=True)
173         col.operator("clip.add_marker_move")
174         col.operator("clip.detect_features")
175         col.operator("clip.delete_track")
176
177
178 class CLIP_PT_tools_tracking(Panel):
179     bl_space_type = 'CLIP_EDITOR'
180     bl_region_type = 'TOOLS'
181     bl_label = "Track"
182
183     @classmethod
184     def poll(cls, context):
185         sc = context.space_data
186         clip = sc.clip
187
188         return clip and sc.mode == 'TRACKING'
189
190     def draw(self, context):
191         layout = self.layout
192         clip = context.space_data.clip
193         settings = clip.tracking.settings
194
195         row = layout.row(align=True)
196
197         op = row.operator("clip.track_markers", text="", icon='FRAME_PREV')
198         op.backwards = True
199         op = row.operator("clip.track_markers", text="", \
200              icon='PLAY_REVERSE')
201         op.backwards = True
202         op.sequence = True
203         op = row.operator("clip.track_markers", text="", icon='PLAY')
204         op.sequence = True
205         row.operator("clip.track_markers", text="", icon='FRAME_NEXT')
206
207         col = layout.column(align=True)
208         op = col.operator("clip.clear_track_path", text="Clear After")
209         op.action = 'REMAINED'
210
211         op = col.operator("clip.clear_track_path", text="Clear Before")
212         op.action = 'UPTO'
213
214         op = col.operator("clip.clear_track_path", text="Clear Track Path")
215         op.action = 'ALL'
216
217         layout.operator("clip.join_tracks")
218
219
220 class CLIP_PT_tools_solving(Panel):
221     bl_space_type = 'CLIP_EDITOR'
222     bl_region_type = 'TOOLS'
223     bl_label = "Solving"
224
225     @classmethod
226     def poll(cls, context):
227         sc = context.space_data
228         clip = sc.clip
229
230         return clip and sc.mode == 'TRACKING'
231
232     def draw(self, context):
233         layout = self.layout
234         clip = context.space_data.clip
235         settings = clip.tracking.settings
236
237         col = layout.column(align=True)
238         col.prop(settings, "keyframe1")
239         col.prop(settings, "keyframe2")
240
241         col = layout.column(align=True)
242         col.operator("clip.solve_camera")
243         col.operator("clip.clear_solution")
244
245
246 class CLIP_PT_tools_cleanup(Panel):
247     bl_space_type = 'CLIP_EDITOR'
248     bl_region_type = 'TOOLS'
249     bl_label = "Clean up"
250
251     @classmethod
252     def poll(cls, context):
253         sc = context.space_data
254         clip = sc.clip
255
256         return clip and sc.mode == 'TRACKING'
257
258     def draw(self, context):
259         layout = self.layout
260         clip = context.space_data.clip
261         settings = clip.tracking.settings
262
263         layout.prop(settings, 'clean_frames', text="Frames")
264         layout.prop(settings, 'clean_error', text="Error")
265         layout.prop(settings, 'clean_action', text="")
266
267         layout.operator("clip.clean_tracks")
268
269
270 class CLIP_PT_tools_geometry(Panel):
271     bl_space_type = 'CLIP_EDITOR'
272     bl_region_type = 'TOOLS'
273     bl_label = "Geometry"
274
275     @classmethod
276     def poll(cls, context):
277         sc = context.space_data
278         clip = sc.clip
279
280         return clip and sc.mode == 'RECONSTRUCTION'
281
282     def draw(self, context):
283         layout = self.layout
284
285         layout.operator("clip.bundles_to_mesh")
286         layout.operator("clip.track_to_empty")
287
288
289 class CLIP_PT_tools_orientation(Panel):
290     bl_space_type = 'CLIP_EDITOR'
291     bl_region_type = 'TOOLS'
292     bl_label = "Orientation"
293
294     @classmethod
295     def poll(cls, context):
296         sc = context.space_data
297         clip = sc.clip
298
299         return clip and sc.mode == 'RECONSTRUCTION'
300
301     def draw(self, context):
302         sc = context.space_data
303         layout = self.layout
304         settings = sc.clip.tracking.settings
305
306         col = layout.column(align=True)
307         col.label(text="Scene Orientation:")
308         col.operator("clip.set_floor")
309         col.operator("clip.set_origin")
310
311         row = col.row()
312         row.operator("clip.set_axis", text="Set X Axis").axis = 'X'
313         row.operator("clip.set_axis", text="Set Y Axis").axis = 'Y'
314
315         col = layout.column()
316         col.prop(settings, "distance")
317         col.operator("clip.set_scale")
318
319
320 class CLIP_PT_tools_grease_pencil(Panel):
321     bl_space_type = 'CLIP_EDITOR'
322     bl_region_type = 'TOOLS'
323     bl_label = "Grease Pencil"
324
325     @classmethod
326     def poll(cls, context):
327         sc = context.space_data
328         clip = sc.clip
329
330         return clip and sc.mode == 'DISTORTION'
331
332     def draw(self, context):
333         layout = self.layout
334
335         col = layout.column(align=True)
336
337         row = col.row(align=True)
338         row.operator("gpencil.draw", text="Draw").mode = 'DRAW'
339         row.operator("gpencil.draw", text="Line").mode = 'DRAW_STRAIGHT'
340
341         row = col.row(align=True)
342         row.operator("gpencil.draw", text="Poly").mode = 'DRAW_POLY'
343         row.operator("gpencil.draw", text="Erase").mode = 'ERASER'
344
345         row = col.row()
346         row.prop(context.tool_settings, "use_grease_pencil_sessions")
347
348
349 class CLIP_PT_track(Panel):
350     bl_space_type = 'CLIP_EDITOR'
351     bl_region_type = 'UI'
352     bl_label = "Track"
353
354     @classmethod
355     def poll(cls, context):
356         sc = context.space_data
357         clip = sc.clip
358
359         return sc.mode == 'TRACKING' and clip
360
361     def draw(self, context):
362         layout = self.layout
363         sc = context.space_data
364         clip = context.space_data.clip
365         act_track = clip.tracking.active_track
366
367         if not act_track:
368             layout.active = False
369             layout.label(text="No active track")
370             return
371
372         row = layout.row()
373         row.prop(act_track, "name", text="")
374
375         sub = row.row(align=True)
376
377         sub.template_marker(sc, "clip", sc.clip_user, act_track, True)
378
379         icon = 'LOCKED' if act_track.locked else 'UNLOCKED'
380         sub.prop(act_track, "locked", text="", icon=icon)
381
382         layout.template_track(sc, "scopes")
383
384         row = layout.row()
385         row.prop(act_track, "use_red_channel", text="Red")
386         row.prop(act_track, "use_green_channel", text="Green")
387         row.prop(act_track, "use_blue_channel", text="Blue")
388
389         layout.separator()
390
391         row = layout.row(align=True)
392         label = bpy.types.CLIP_MT_track_color_presets.bl_label
393         row.menu('CLIP_MT_track_color_presets', text=label)
394         row.menu('CLIP_MT_track_color_specials', text="", icon="DOWNARROW_HLT")
395         row.operator("clip.track_color_preset_add", text="", icon="ZOOMIN")
396         op = row.operator("clip.track_color_preset_add", \
397             text="", icon="ZOOMOUT")
398         op.remove_active = True
399
400         row = layout.row()
401         row.prop(act_track, "use_custom_color")
402         if act_track.use_custom_color:
403             row.prop(act_track, "color", text="")
404
405         if act_track.has_bundle:
406             label_text = "Average Error: %.4f" % (act_track.average_error)
407             layout.label(text=label_text)
408
409
410 class CLIP_PT_tracking_camera(Panel):
411     bl_space_type = 'CLIP_EDITOR'
412     bl_region_type = 'UI'
413     bl_label = "Camera Data"
414     bl_options = {'DEFAULT_CLOSED'}
415
416     @classmethod
417     def poll(cls, context):
418         sc = context.space_data
419
420         return sc.mode in ['TRACKING', 'DISTORTION'] and sc.clip
421
422     def draw(self, context):
423         layout = self.layout
424
425         sc = context.space_data
426         clip = sc.clip
427
428         row = layout.row(align=True)
429         label = bpy.types.CLIP_MT_camera_presets.bl_label
430         row.menu('CLIP_MT_camera_presets', text=label)
431         row.operator("clip.camera_preset_add", text="", icon="ZOOMIN")
432         op = row.operator("clip.camera_preset_add", text="", icon="ZOOMOUT")
433         op.remove_active = True
434
435         row = layout.row(align=True)
436         sub = row.split(percentage=0.65)
437         sub.prop(clip.tracking.camera, "focal_length")
438         sub.prop(clip.tracking.camera, "units", text="")
439
440         col = layout.column(align=True)
441         col.label(text="Sensor:")
442         col.prop(clip.tracking.camera, "sensor_width", text="Size")
443         col.prop(clip.tracking.camera, "pixel_aspect")
444
445         col = layout.column()
446         col.label(text="Principal Point")
447         row = col.row()
448         row.prop(clip.tracking.camera, "principal", text="")
449         col.operator("clip.set_center_principal", text="Center")
450
451         col = layout.column(align=True)
452         col.label(text="Undistortion:")
453         col.prop(clip.tracking.camera, "k1")
454         col.prop(clip.tracking.camera, "k2")
455         col.prop(clip.tracking.camera, "k3")
456
457
458 class CLIP_PT_display(Panel):
459     bl_space_type = 'CLIP_EDITOR'
460     bl_region_type = 'UI'
461     bl_label = "Display"
462
463     def draw(self, context):
464         layout = self.layout
465         sc = context.space_data
466
467         row = layout.row()
468         row.prop(sc, "show_marker_pattern", text="Pattern")
469         row.prop(sc, "show_marker_search", text="Search")
470
471         row = layout.row()
472         row.prop(sc, "show_track_path", text="Path")
473         sub = row.column()
474         sub.active = sc.show_track_path
475         sub.prop(sc, "path_length", text="Length")
476
477         row = layout.row()
478         row.prop(sc, "show_disabled", text="Disabled")
479         row.prop(sc, "show_bundles", text="Bundles")
480
481         row = layout.row()
482         row.prop(sc, "show_names", text="Names")
483         row.prop(sc, "show_tiny_markers", text="Tiny Markers")
484
485         row = layout.row()
486         row.prop(sc, "show_grease_pencil", text="Grease Pencil")
487         row.prop(sc, "use_mute_footage", text="Mute")
488
489         if sc.mode == 'DISTORTION':
490             layout.prop(sc, "show_grid", text="Grid")
491             layout.prop(sc, "use_manual_calibration")
492         elif sc.mode == 'RECONSTRUCTION':
493             layout.prop(sc, "show_stable", text="Stable")
494
495         layout.prop(sc, "lock_selection")
496
497         clip = sc.clip
498         if clip:
499             layout.label(text="Display Aspect:")
500             layout.prop(clip, "display_aspect", text="")
501
502
503 class CLIP_PT_track_settings(Panel):
504     bl_space_type = 'CLIP_EDITOR'
505     bl_region_type = 'UI'
506     bl_label = "Tracking Settings"
507     bl_options = {'DEFAULT_CLOSED'}
508
509     @classmethod
510     def poll(cls, context):
511         sc = context.space_data
512
513         return sc.mode == 'TRACKING' and sc.clip
514
515     def draw(self, context):
516         layout = self.layout
517         clip = context.space_data.clip
518         settings = clip.tracking.settings
519
520         layout.prop(settings, "tracker")
521
522         layout.prop(settings, "adjust_frames")
523
524         if settings.tracker == "SAD":
525             layout.prop(settings, "min_correlation")
526
527         layout.prop(settings, "speed")
528         layout.prop(settings, "frames_limit")
529         layout.prop(settings, "margin")
530
531
532 class CLIP_PT_stabilization(Panel):
533     bl_space_type = 'CLIP_EDITOR'
534     bl_region_type = 'UI'
535     bl_label = "2D Stabilization"
536     bl_options = {'DEFAULT_CLOSED'}
537
538     @classmethod
539     def poll(cls, context):
540         sc = context.space_data
541
542         return sc.mode == 'RECONSTRUCTION' and sc.clip
543
544     def draw_header(self, context):
545         sc = context.space_data
546         tracking = sc.clip.tracking
547         stab = tracking.stabilization
548
549         self.layout.prop(stab, "use_2d_stabilization", text="")
550
551     def draw(self, context):
552         layout = self.layout
553         sc = context.space_data
554         tracking = sc.clip.tracking
555         stab = tracking.stabilization
556
557         layout.active = stab.use_2d_stabilization
558
559         row = layout.row()
560         row.template_list(stab, "tracks", stab, "active_track_index", rows=3)
561
562         sub = row.column(align=True)
563
564         sub.operator("clip.stabilize_2d_add", icon='ZOOMIN', text="")
565         sub.operator("clip.stabilize_2d_remove", icon='ZOOMOUT', text="")
566
567         sub.menu('CLIP_MT_stabilize_2d_specials', text="", \
568             icon="DOWNARROW_HLT")
569
570         layout.prop(stab, "influence_location")
571
572         layout.separator()
573
574         layout.prop(stab, "use_autoscale")
575         col = layout.column()
576         col.active = stab.use_autoscale
577         col.prop(stab, "max_scale")
578         col.prop(stab, "influence_scale")
579
580         layout.separator()
581
582         layout.label(text="Rotation:")
583
584         row = layout.row(align=True)
585         row.prop_search(stab, "rotation_track", tracking, "tracks", text="")
586         row.operator("clip.stabilize_2d_set_rotation", text="", icon='ZOOMIN')
587
588         row = layout.row()
589         row.active = stab.rotation_track is not None
590         row.prop(stab, "influence_rotation")
591
592
593 class CLIP_PT_marker(Panel):
594     bl_space_type = 'CLIP_EDITOR'
595     bl_region_type = 'UI'
596     bl_label = "Marker"
597     bl_options = {'DEFAULT_CLOSED'}
598
599     @classmethod
600     def poll(cls, context):
601         sc = context.space_data
602         clip = sc.clip
603
604         return sc.mode == 'TRACKING' and clip
605
606     def draw(self, context):
607         layout = self.layout
608         sc = context.space_data
609         clip = context.space_data.clip
610         act_track = clip.tracking.active_track
611
612         if act_track:
613             layout.template_marker(sc, "clip", sc.clip_user, act_track, False)
614         else:
615             layout.active = False
616             layout.label(text="No active track")
617
618
619 class CLIP_PT_proxy(Panel):
620     bl_space_type = 'CLIP_EDITOR'
621     bl_region_type = 'UI'
622     bl_label = "Proxy / Timecode"
623     bl_options = {'DEFAULT_CLOSED'}
624
625     @classmethod
626     def poll(cls, context):
627         sc = context.space_data
628
629         return sc.clip
630
631     def draw_header(self, context):
632         sc = context.space_data
633
634         self.layout.prop(sc.clip, "use_proxy", text="")
635
636     def draw(self, context):
637         layout = self.layout
638         sc = context.space_data
639         clip = sc.clip
640
641         layout.active = clip.use_proxy
642
643         layout.label(text="Build Sizes:")
644         row = layout.row()
645         row.prop(clip.proxy, "build_25")
646         row.prop(clip.proxy, "build_50")
647         row.prop(clip.proxy, "build_75")
648
649         layout.prop(clip.proxy, "quality")
650
651         layout.prop(clip, 'use_proxy_custom_directory')
652         if clip.use_proxy_custom_directory:
653             layout.prop(clip.proxy, "directory")
654
655         layout.operator("clip.rebuild_proxy", text="Rebuild Proxy")
656
657         if clip.source == 'MOVIE':
658             col = layout.column()
659
660             col.label(text="Use timecode index:")
661             col.prop(clip.proxy, "timecode", text="")
662
663         col = layout.column()
664         col.label(text="Proxy render size:")
665         col.prop(clip, "proxy_render_size", text="")
666
667
668 class CLIP_PT_footage(Panel):
669     bl_space_type = 'CLIP_EDITOR'
670     bl_region_type = 'UI'
671     bl_label = "Footage Settings"
672     bl_options = {'DEFAULT_CLOSED'}
673
674     @classmethod
675     def poll(cls, context):
676         sc = context.space_data
677
678         return sc.clip
679
680     def draw(self, context):
681         layout = self.layout
682
683         sc = context.space_data
684         clip = sc.clip
685
686         if clip:
687             layout.template_movieclip(sc, "clip", compact=True)
688         else:
689             layout.operator("clip.open", icon='FILESEL')
690
691
692 class CLIP_MT_view(Menu):
693     bl_label = "View"
694
695     def draw(self, context):
696         layout = self.layout
697
698         layout.operator("clip.properties", icon='MENU_PANEL')
699         layout.operator("clip.tools", icon='MENU_PANEL')
700         layout.separator()
701
702         layout.operator("clip.view_selected")
703         layout.operator("clip.view_all")
704
705         layout.separator()
706         layout.operator("clip.view_zoom_in")
707         layout.operator("clip.view_zoom_out")
708
709         layout.separator()
710
711         ratios = [[1, 8], [1, 4], [1, 2], [1, 1], [2, 1], [4, 1], [8, 1]]
712
713         for a, b in ratios:
714             text = "Zoom %d:%d" % (a, b)
715             layout.operator("clip.view_zoom_ratio", text=text).ratio = a / b
716
717         layout.separator()
718         layout.operator("screen.area_dupli")
719         layout.operator("screen.screen_full_area")
720
721
722 class CLIP_MT_clip(Menu):
723     bl_label = "Clip"
724
725     def draw(self, context):
726         layout = self.layout
727
728         sc = context.space_data
729         clip = sc.clip
730
731         if clip:
732             layout.operator("clip.reload")
733
734         layout.operator("clip.open")
735
736
737 class CLIP_MT_track(Menu):
738     bl_label = "Track"
739
740     def draw(self, context):
741         layout = self.layout
742
743         layout.operator("clip.set_origin")
744
745         layout.separator()
746         layout.operator("clip.clear_reconstruction")
747         layout.operator("clip.solve_camera")
748
749         layout.separator()
750         op = layout.operator("clip.clear_track_path", \
751              text="Clear Remained Path")
752         op.action = 'REMAINED'
753
754         op = layout.operator("clip.clear_track_path", \
755              text="Clear Path Up To")
756         op.action = 'UPTO'
757
758         op = layout.operator("clip.clear_track_path", \
759              text="Clear Track Path")
760         op.action = 'ALL'
761
762         layout.separator()
763         op = layout.operator("clip.track_markers", \
764             text="Track Frame Backwards")
765         op.backwards = True
766
767         op = layout.operator("clip.track_markers", text="Track Backwards")
768         op.backwards = True
769         op.sequence = True
770
771         op = layout.operator("clip.track_markers", text="Track Forwards")
772         op.sequence = True
773         layout.operator("clip.track_markers", text="Track Frame Forwards")
774
775         layout.separator()
776         layout.operator("clip.delete_track")
777         layout.operator("clip.delete_marker")
778
779         layout.separator()
780         layout.operator("clip.add_marker_move")
781
782         layout.separator()
783         layout.menu("CLIP_MT_track_visibility")
784         layout.menu("CLIP_MT_track_transform")
785
786
787 class CLIP_MT_track_visibility(Menu):
788     bl_label = "Show/Hide"
789
790     def draw(self, context):
791         layout = self.layout
792
793         layout.operator("clip.hide_tracks_clear", text="Show Hidden")
794         layout.operator("clip.hide_tracks", text="Hide Selected")
795
796         op = layout.operator("clip.hide_tracks", text="Hide Unselected")
797         op.unselected = True
798
799
800 class CLIP_MT_track_transform(Menu):
801     bl_label = "Transform"
802
803     def draw(self, context):
804         layout = self.layout
805
806         layout.operator("transform.translate")
807         layout.operator("transform.resize")
808
809
810 class CLIP_MT_select(Menu):
811     bl_label = "Select"
812
813     def draw(self, context):
814         layout = self.layout
815
816         sc = context.space_data
817
818         layout.menu("CLIP_MT_select_grouped")
819         layout.operator("clip.select_border")
820         layout.operator("clip.select_circle")
821         layout.operator("clip.select_all", text="Select/Deselect all")
822         layout.operator("clip.select_all", text="Inverse").action = 'INVERT'
823
824
825 class CLIP_MT_select_grouped(Menu):
826     bl_label = "Select Grouped"
827
828     def draw(self, context):
829         layout = self.layout
830
831         sc = context.space_data
832
833         op = layout.operator("clip.select_grouped", text="Select Keyframed")
834         op.group = 'KEYFRAMED'
835
836         op = layout.operator("clip.select_grouped", text="Select Estimated")
837         op.group = 'ESTIMATED'
838
839         op = layout.operator("clip.select_grouped", text="Select Tracked")
840         op.group = 'TRACKED'
841
842         op = layout.operator("clip.select_grouped", text="Select Locked")
843         op.group = 'LOCKED'
844
845         op = layout.operator("clip.select_grouped", text="Select Disabled")
846         op.group = 'DISABLED'
847
848         op = layout.operator("clip.select_grouped", text="Select Failed")
849         op.group = 'FAILED'
850
851         op = layout.operator("clip.select_grouped", text="Select by Color")
852         op.group = 'COLOR'
853
854
855 class CLIP_MT_tracking_specials(Menu):
856     bl_label = "Specials"
857
858     @classmethod
859     def poll(cls, context):
860         return context.space_data.clip
861
862     def draw(self, context):
863         layout = self.layout
864
865         op = layout.operator("clip.disable_markers", text="Enable Markers")
866         op.action = 'ENABLE'
867
868         op = layout.operator("clip.disable_markers", text="Disable markers")
869         op.action = 'DISABLE'
870
871         layout.separator()
872         layout.operator("clip.set_origin")
873
874         layout.separator()
875         layout.operator("clip.hide_tracks")
876         layout.operator("clip.hide_tracks_clear", text="Show Tracks")
877
878         layout.separator()
879         op = layout.operator("clip.lock_tracks", text="Lock Tracks")
880         op.action = 'LOCK'
881
882         op = layout.operator("clip.lock_tracks", text="Unlock Tracks")
883         op.action = 'UNLOCK'
884
885
886 class CLIP_MT_camera_presets(Menu):
887     bl_label = "Camera Presets"
888     preset_subdir = "tracking_camera"
889     preset_operator = "script.execute_preset"
890     draw = bpy.types.Menu.draw_preset
891
892
893 class CLIP_MT_track_color_presets(Menu):
894     bl_label = "Color Presets"
895     preset_subdir = "tracking_track_color"
896     preset_operator = "script.execute_preset"
897     draw = bpy.types.Menu.draw_preset
898
899
900 class CLIP_MT_track_color_specials(Menu):
901     bl_label = "Track Color Specials"
902
903     def draw(self, context):
904         layout = self.layout
905
906         layout.operator('clip.track_copy_color', icon='COPY_ID')
907
908
909 class CLIP_MT_stabilize_2d_specials(Menu):
910     bl_label = "Track Color Specials"
911
912     def draw(self, context):
913         layout = self.layout
914
915         layout.operator('clip.stabilize_2d_select')
916
917
918 if __name__ == "__main__":  # only for live edit.
919     bpy.utils.register_module(__name__)