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