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