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